From ba0b327af0acd2e73350831338f2e4203c9668e3 Mon Sep 17 00:00:00 2001 From: ccMSC Date: Mon, 22 Jun 2015 20:55:26 -0600 Subject: [PATCH] (ckb-daemon Linux) Fixed incorrect USB error usage (ckb-daemon Linux) Added guards against accidentally adding the same device twice (ckb-daemon) Added extra delay between error reports --- src/ckb-daemon/usb.c | 3 +++ src/ckb-daemon/usb_linux.c | 55 +++++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/ckb-daemon/usb.c b/src/ckb-daemon/usb.c index 1d5e322..1e5cfb2 100644 --- a/src/ckb-daemon/usb.c +++ b/src/ckb-daemon/usb.c @@ -193,6 +193,7 @@ int _usbsend(usbdevice* kb, const uchar* messages, int count, const char* file, if(reset_stop) return 0; // Retry as long as the result is temporary failure + DELAY_LONG(kb); } } return total_sent; @@ -210,6 +211,7 @@ int _usbrecv(usbdevice* kb, const uchar* out_msg, uchar* in_msg, const char* fil // Retry on temporary failure if(reset_stop) return 0; + DELAY_LONG(kb); continue; } // Wait for the response @@ -221,6 +223,7 @@ int _usbrecv(usbdevice* kb, const uchar* out_msg, uchar* in_msg, const char* fil return res; if(reset_stop) return 0; + DELAY_LONG(kb); } // Give up ckb_err_fn("Too many recv failures. Dropping.\n", file, line); diff --git a/src/ckb-daemon/usb_linux.c b/src/ckb-daemon/usb_linux.c index a13278c..652fe7c 100644 --- a/src/ckb-daemon/usb_linux.c +++ b/src/ckb-daemon/usb_linux.c @@ -6,29 +6,32 @@ #ifdef OS_LINUX +static char kbsyspath[DEV_MAX][FILENAME_MAX]; + int os_usbsend(usbdevice* kb, const uchar* out_msg, int is_recv, const char* file, int line){ int res; if(kb->fwversion >= 0x120){ #if 0 // Change to #if 1 if using valgrind (4 padding bytes between timeout/data; valgrind thinks they're uninit'd and complains) struct usbdevfs_bulktransfer transfer; memset(&transfer, 0, sizeof(transfer)); - transfer.ep = 3; transfer.len = MSG_SIZE; transfer.timeout = 500; transfer.data = (void*)out_msg; + transfer.ep = 3; transfer.len = MSG_SIZE; transfer.timeout = 5000; transfer.data = (void*)out_msg; #else - struct usbdevfs_bulktransfer transfer = { 3, MSG_SIZE, 500, (void*)out_msg }; + struct usbdevfs_bulktransfer transfer = { 3, MSG_SIZE, 5000, (void*)out_msg }; #endif res = ioctl(kb->handle, USBDEVFS_BULK, &transfer); } else { - struct usbdevfs_ctrltransfer transfer = { 0x21, 0x09, 0x0300, 0x03, MSG_SIZE, 500, (void*)out_msg }; + struct usbdevfs_ctrltransfer transfer = { 0x21, 0x09, 0x0300, 0x03, MSG_SIZE, 5000, (void*)out_msg }; res = ioctl(kb->handle, USBDEVFS_CONTROL, &transfer); } - if(res == -EPERM){ - ckb_warn_fn("Send failed (continuing)\n", file, line); - return -1; - } else if(res <= 0){ - ckb_err_fn("%s\n", file, line, res ? strerror(-res) : "No data written"); + if(res <= 0){ + if(res == -1 && errno == ETIMEDOUT){ + ckb_warn_fn("%s (continuing)\n", file, line, strerror(errno)); + return -1; + } + ckb_err_fn("%s\n", file, line, res ? strerror(errno) : "No data written"); return 0; } else if(res != MSG_SIZE) - ckb_err_fn("Wrote %d bytes (expected %d)\n", file, line, res, MSG_SIZE); + ckb_warn_fn("Wrote %d bytes (expected %d)\n", file, line, res, MSG_SIZE); return res; } @@ -36,14 +39,15 @@ int os_usbrecv(usbdevice* kb, uchar* in_msg, const char* file, int line){ DELAY_MEDIUM(kb); struct usbdevfs_ctrltransfer transfer = { 0xa1, 0x01, 0x0300, 0x03, MSG_SIZE, 5000, in_msg }; int res = ioctl(kb->handle, USBDEVFS_CONTROL, &transfer); - if(res == -EPERM){ - ckb_warn_fn("Receive failed (continuing)\n", file, line); - return -1; - } else if(res <= 0){ - ckb_err_fn("%s\n", file, line, res ? strerror(-res) : "No data read"); + if(res <= 0){ + if(res == -1 && errno == ETIMEDOUT){ + ckb_warn_fn("%s (continuing)\n", file, line, strerror(errno)); + return -1; + } + ckb_err_fn("%s\n", file, line, res ? strerror(errno) : "No data read"); return 0; } else if(res != MSG_SIZE) - ckb_err_fn("Read %d bytes (expected %d)\n", file, line, res, MSG_SIZE); + ckb_warn_fn("Read %d bytes (expected %d)\n", file, line, res, MSG_SIZE); return res; } @@ -176,6 +180,7 @@ void os_closeusb(usbdevice* kb){ udev_device_unref(kb->udev); kb->handle = 0; kb->udev = 0; + kbsyspath[INDEX_OF(kb, keyboard)][0] = 0; } int usbclaim(usbdevice* kb, int rgb){ @@ -236,12 +241,22 @@ int os_setupusb(usbdevice* kb){ int usbadd(struct udev_device* dev, short vendor, short product){ const char* path = udev_device_get_devnode(dev); + const char* syspath = udev_device_get_syspath(dev); + if(!path || !syspath || path[0] == 0 || syspath[0] == 0){ + ckb_err("Failed to get device path\n"); + return -1; + } // Find a free USB slot for(int index = 1; index < DEV_MAX; index++){ usbdevice* kb = keyboard + index; - if(pthread_mutex_trylock(dmutex(kb))) + if(pthread_mutex_trylock(dmutex(kb))){ // If the mutex is locked then the device is obviously in use, so keep going + if(!strcmp(syspath, kbsyspath[index])){ + // Make sure this existing keyboard doesn't have the same syspath (this shouldn't happen) + return 0; + } continue; + } if(!IS_CONNECTED(kb)){ // Open the sysfs device kb->handle = open(path, O_RDWR); @@ -255,6 +270,8 @@ int usbadd(struct udev_device* dev, short vendor, short product){ kb->udev = dev; kb->vendor = vendor; kb->product = product; + strncpy(kbsyspath[index], syspath, FILENAME_MAX); + // Mutex remains locked setupusb(kb); return 0; } @@ -304,10 +321,12 @@ static int usb_add_device(struct udev_device* dev){ // Remove a udev device. static void usb_rm_device(struct udev_device* dev){ // Device removed. Look for it in our list of keyboards - const char* path = udev_device_get_syspath(dev); + const char* syspath = udev_device_get_syspath(dev); + if(!syspath || syspath[0] == 0) + return; for(int i = 1; i < DEV_MAX; i++){ pthread_mutex_lock(devmutex + i); - if(keyboard[i].udev && !strcmp(path, udev_device_get_syspath(keyboard[i].udev))) + if(!strcmp(syspath, kbsyspath[i])) closeusb(keyboard + i); pthread_mutex_unlock(devmutex + i); }