USB system wide device locking on windows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
diff --git a/usbutils.c b/usbutils.c
index 3c03510..42b23d3 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -600,10 +600,67 @@ union semun {
static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address)
{
#ifdef WIN32
- // NOOP for now
- drv = 0;
- bus_number = device_address = 0;
+ struct cgpu_info *cgpu;
+ HANDLE usbMutex;
+ char name[64];
+ DWORD res;
+ int i;
+
+ sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
+
+ usbMutex = CreateMutex(NULL, FALSE, name);
+ if (usbMutex == NULL) {
+ applog(LOG_ERR,
+ "MTX: %s USB failed to get '%s' err (%d)",
+ drv->dname, name, GetLastError());
+ return false;
+ }
+
+ res = WaitForSingleObject(usbMutex, 0);
+ switch(res) {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+ // Am I using it already?
+ for (i = 0; i < total_devices; i++) {
+ cgpu = devices[i];
+ if (cgpu->usbinfo.bus_number == bus_number &&
+ cgpu->usbinfo.device_address == device_address &&
+ cgpu->usbinfo.nodev == false) {
+ if (ReleaseMutex(usbMutex)) {
+ applog(LOG_WARNING,
+ "MTX: %s USB can't get '%s' - device in use",
+ drv->dname, name);
+ goto fail;
+ }
+ applog(LOG_ERR,
+ "MTX: %s USB can't get '%s' - device in use - failure (%d)",
+ drv->dname, name, GetLastError());
+ goto fail;
+ }
+ }
+ return true;
+ case WAIT_TIMEOUT:
+ applog(LOG_WARNING,
+ "MTX: %s USB failed to get '%s' - device in use",
+ drv->dname, name);
+ goto fail;
+ case WAIT_FAILED:
+ applog(LOG_ERR,
+ "MTX: %s USB failed to get '%s' err (%d)",
+ drv->dname, name, GetLastError());
+ goto fail;
+ default:
+ applog(LOG_ERR,
+ "MTX: %s USB failed to get '%s' unknown reply (%d)",
+ drv->dname, name, res);
+ goto fail;
+ }
+
+ CloseHandle(usbMutex);
return true;
+fail:
+ CloseHandle(usbMutex);
+ return false;
#else
struct semid_ds seminfo;
union semun opt;
@@ -672,7 +729,7 @@ static bool cgminer_usb_lock_bd(struct device_drv *drv, uint8_t bus_number, uint
drv->dname, sem, name);
} else {
applog(LOG_DEBUG,
- "SEM: %s USB failed to get (%d) '%s' err(%d) %s",
+ "SEM: %s USB failed to get (%d) '%s' err (%d) %s",
drv->dname, sem, name, errno, strerror(errno));
}
return false;
@@ -692,9 +749,26 @@ static bool cgminer_usb_lock(struct device_drv *drv, libusb_device *dev)
static void cgminer_usb_unlock_bd(struct device_drv *drv, uint8_t bus_number, uint8_t device_address)
{
#ifdef WIN32
- // NOOP for now
- drv = 0;
- bus_number = device_address = 0;
+ HANDLE usbMutex;
+ char name[64];
+
+ sprintf(name, "cgminer-usb-%d-%d", (int)bus_number, (int)device_address);
+
+ usbMutex = CreateMutex(NULL, FALSE, name);
+ if (usbMutex == NULL) {
+ applog(LOG_ERR,
+ "MTX: %s USB failed to get '%s' for release err (%d)",
+ drv->dname, name, GetLastError());
+ return;
+ }
+
+ if (!ReleaseMutex(usbMutex))
+ applog(LOG_ERR,
+ "MTX: %s USB failed to release '%s' err (%d)",
+ drv->dname, name, GetLastError());
+
+ CloseHandle(usbMutex);
+ return;
#else
char name[64];
key_t key;