int os_usbrecv(usbdevice* kb, uchar* in_msg, const char* file, int line){ DELAY_MEDIUM(kb); int res; if(kb->fwversion >= 0x130){ struct usbdevfs_bulktransfer transfer; memset(&transfer, 0, sizeof(transfer)); transfer.ep = 0x84; transfer.len = MSG_SIZE; transfer.timeout = 5000; transfer.data = in_msg; res = ioctl(kb->handle, USBDEVFS_BULK, &transfer); } else { struct usbdevfs_ctrltransfer transfer = { 0xa1, 0x01, 0x0300, 0x03, MSG_SIZE, 5000, in_msg }; res = ioctl(kb->handle, USBDEVFS_CONTROL, &transfer); } 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_warn_fn("Read %d bytes (expected %d)\n", file, line, res, MSG_SIZE); return res; }
int _usbrecv(usbdevice* kb, const uchar* out_msg, uchar* in_msg, const char* file, int line){ // Try a maximum of 3 times for(int try = 0; try < 5; try++){ // Send the output message DELAY_SHORT(kb); int res = os_usbsend(kb, out_msg, 1, file, line); if(res == 0) return 0; else if(res == -1){ // Retry on temporary failure if(reset_stop) return 0; DELAY_LONG(kb); continue; } // Wait for the response DELAY_MEDIUM(kb); res = os_usbrecv(kb, in_msg, file, line); if(res == 0) return 0; else if(res != -1) return res; if(reset_stop || hwload_mode != 2) return 0; DELAY_LONG(kb); } // Give up ckb_err_fn("Too many send/recv failures. Dropping.\n", file, line); return 0; } int closeusb(usbdevice* kb){ pthread_mutex_lock(imutex(kb)); if(kb->handle){ int index = INDEX_OF(kb, keyboard); ckb_info("Disconnecting %s%d\n", devpath, index); os_inputclose(kb); updateconnected(); // Close USB device os_closeusb(kb); } else updateconnected(); rmdevpath(kb); // Wait for thread to close pthread_mutex_unlock(imutex(kb)); pthread_mutex_unlock(dmutex(kb)); pthread_join(kb->thread, 0); pthread_mutex_lock(dmutex(kb)); // Delete the profile and the control path if(!kb->vtable) return 0; kb->vtable->freeprofile(kb); memset(kb, 0, sizeof(usbdevice)); return 0; }