Skip to content

Commit

Permalink
(ckb-daemon Linux) Fixed incorrect USB error usage
Browse files Browse the repository at this point in the history
(ckb-daemon Linux) Added guards against accidentally adding the same device twice
(ckb-daemon) Added extra delay between error reports
  • Loading branch information
ccMSC committed Jun 23, 2015
1 parent 233582a commit ba0b327
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 18 deletions.
3 changes: 3 additions & 0 deletions src/ckb-daemon/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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);
Expand Down
55 changes: 37 additions & 18 deletions src/ckb-daemon/usb_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,48 @@

#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;
}

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;
}

Expand Down Expand Up @@ -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){
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit ba0b327

Please sign in to comment.