// rawhid_send - send a packet // Inputs: // num = device to transmit to (zero based) // buf = buffer containing packet to send // len = number of bytes to transmit // timeout = time to wait, in milliseconds // Output: // number of bytes sent, or -1 on error // int rawhid_send(int num, void *buf, int len, int timeout) { hid_t *hid; unsigned char tmpbuf[516]; OVERLAPPED ov; DWORD n, r; if (sizeof(tmpbuf) < len + 1) return -1; hid = get_hid(num); if (!hid || !hid->open) return -1; EnterCriticalSection(&tx_mutex); ResetEvent(&tx_event); memset(&ov, 0, sizeof(ov)); ov.hEvent = tx_event; tmpbuf[0] = 0; memcpy(tmpbuf + 1, buf, len); if (!WriteFile(hid->handle, tmpbuf, len + 1, NULL, &ov)) { if (GetLastError() != ERROR_IO_PENDING) goto return_error; r = WaitForSingleObject(tx_event, timeout); if (r == WAIT_TIMEOUT) goto return_timeout; if (r != WAIT_OBJECT_0) goto return_error; } if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) goto return_error; LeaveCriticalSection(&tx_mutex); if (n <= 0) return -1; return n - 1; return_timeout: CancelIo(hid->handle); LeaveCriticalSection(&tx_mutex); return 0; return_error: print_win32_err(); LeaveCriticalSection(&tx_mutex); return -1; }
QString pjrc_rawhid::getserial(int num) { hid_t *hid = get_hid(num); if (!hid) return ""; if (!hid->handle) return ""; // Should we do some "critical section" stuff here?? char temp[126]; if (!HidD_GetSerialNumberString(hid->handle, temp, sizeof(temp))) { DWORD err = GetLastError(); print_win32_err(err); if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged hid_close(hid); emit deviceUnplugged(num); return ""; } return QString("Error"); } return QString().fromUtf16((ushort*)temp,-1); }
// rawhid_close - close a device // // Inputs: // num = device to close (zero based) // Output // (nothing) // void rawhid_close(int num) { hid_t *hid; hid = get_hid(num); if (!hid || !hid->open) return; hid_close(hid); }
// close - close a device // // Inputs: // num = device to close (zero based) // Output // (nothing) // void pjrc_rawhid::close(int num) { hid_t *hid; hid = get_hid(num); if (!hid || !hid->open) return; hid_close(hid); hid->open = 0; }
// rawhid_send - send a packet // Inputs: // num = device to transmit to (zero based) // buf = buffer containing packet to send // len = number of bytes to transmit // timeout = time to wait, in milliseconds // Output: // number of bytes sent, or -1 on error // int rawhid_send(int num, void *buf, int len, int timeout) { hid_t *hid; hid = get_hid(num); if (!hid || !hid->open) return -1; if (hid->ep_out) { return usb_interrupt_write(hid->usb, hid->ep_out, buf, len, timeout); } else { return usb_control_msg(hid->usb, 0x21, 9, 0, hid->iface, buf, len, timeout); } }
// rawhid_recv - receive a packet // Inputs: // num = device to receive from (zero based) // buf = buffer to receive packet // len = buffer's size // timeout = time to wait, in milliseconds // Output: // number of bytes received, or -1 on error // int rawhid_recv(int num, void *buf, int len, int timeout) { hid_t *hid; int r; hid = get_hid(num); if (!hid || !hid->open) return -1; r = usb_interrupt_read(hid->usb, hid->ep_in, buf, len, timeout); if (r >= 0) return r; if (r == -110) return 0; // timeout return -1; }
// recveive - receive a packet // Inputs: // num = device to receive from (zero based) // buf = buffer to receive packet // len = buffer's size // timeout = time to wait, in milliseconds // Output: // number of bytes received, or -1 on error // int pjrc_rawhid::receive(int num, void *buf, int len, int timeout) { hid_t *hid; buffer_t *b; CFRunLoopTimerRef timer=NULL; CFRunLoopTimerContext context; int ret=0, timeout_occurred=0; if (len < 1) return 0; hid = get_hid(num); if (!hid || !hid->open) return -1; if ((b = hid->first_buffer) != NULL) { if (len > b->len) len = b->len; memcpy(buf, b->buf, len); hid->first_buffer = b->next; free(b); return len; } memset(&context, 0, sizeof(context)); context.info = &timeout_occurred; timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + (double)timeout / 1000.0, 0, 0, 0, timeout_callback, &context); CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); the_correct_runloop = CFRunLoopGetCurrent(); //qDebug("--"); while (1) { //qDebug("."); CFRunLoopRun(); // Found the problem: somehow the input_callback does not // stop this CFRunLoopRun because it is hooked to a different run loop !!! // Hence the use of the "correct_runloop" variable above. //qDebug(" .."); if ((b = hid->first_buffer) != NULL) { if (len > b->len) len = b->len; memcpy(buf, b->buf, len); hid->first_buffer = b->next; free(b); ret = len; //qDebug("*************"); break; } if (!hid->open) { printf("pjrc_rawhid_recv, device not open\n"); ret = -1; break; } if (timeout_occurred) break; } CFRunLoopTimerInvalidate(timer); CFRelease(timer); return ret; }
// send - send a packet // Inputs: // num = device to transmit to (zero based) // buf = buffer containing packet to send // len = number of bytes to transmit // timeout = time to wait, in milliseconds // Output: // number of bytes sent, or -1 on error // int pjrc_rawhid::send(int num, void *buf, int len, int timeout) { hid_t *hid; int result=-100; hid = get_hid(num); if (!hid || !hid->open) return -1; #if 1 #warning "Send timeout not implemented on MACOSX" uint8_t *report_buf = (uint8_t *) malloc(len); memcpy(&report_buf[0], buf,len); // Note: packet processing done in OS indepdent code IOReturn ret = IOHIDDeviceSetReport(hid->ref, kIOHIDReportTypeOutput, 2, (uint8_t *)report_buf, len); result = (ret == kIOReturnSuccess) ? len : -1; if (err_get_system(ret) == err_get_system(sys_iokit)) { // The error was in the I/O Kit system UInt32 codeValue = err_get_code(ret); qDebug("Returned: %x", codeValue); // Can now perform test on error code, display it to user, or whatever. usleep(1000000); } #endif #if 0 // No matter what I tried this never actually sends an output // report and output_callback never gets called. Why?? // Did I miss something? This is exactly the same params as // the sync call that works. Is it an Apple bug? // (submitted to Apple on 22-sep-2009, problem ID 7245050) // IOHIDDeviceScheduleWithRunLoop(hid->ref, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); // should already be scheduled with run loop by attach_callback, // sadly this doesn't make any difference either way // IOHIDDeviceSetReportWithCallback(hid->ref, kIOHIDReportTypeOutput, 0, buf, len, (double)timeout / 1000.0, output_callback, &result); while (1) { printf("enter run loop (send)\n"); CFRunLoopRun(); printf("leave run loop (send)\n"); if (result > -100) break; if (!hid->open) { result = -1; break; } } #endif return result; }
int rawhid_recv(int num, void *buf, int len, int timeout) { //fprintf(stderr,"rawhid_recv start len: %d\n",len); //fprintf(stderr,"rawhid_recv start \n"); hid_t *hid; buffer_t *b; CFRunLoopTimerRef timer=NULL; CFRunLoopTimerContext context; int ret=0, timeout_occurred=0; if (len < 1) return 0; hid = get_hid(num); if (!hid || !hid->open) return -1; if ((b = hid->first_buffer) != NULL) { if (len > b->len) len = b->len; memcpy(buf, b->buf, len); hid->first_buffer = b->next; free(b); // fprintf(stderr,"rawhid_recv A len: %d\n\n",len); return len; } memset(&context, 0, sizeof(context)); context.info = &timeout_occurred; timer = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + (double)timeout / 1000.0, 0, 0, 0, timeout_callback, &context); CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopDefaultMode); while (1) { CFRunLoopRun(); if ((b = hid->first_buffer) != NULL) { if (len > b->len) len = b->len; memcpy(buf, b->buf, len); hid->first_buffer = b->next; free(b); ret = len; break; } if (!hid->open) { //printf("rawhid_recv, device not open\n"); ret = -1; break; } if (timeout_occurred) break; } CFRunLoopTimerInvalidate(timer); CFRelease(timer); //fprintf(stderr,"rawhid_recv ret: %d\n",ret); return ret; }
// rawhid_send - send a packet // Inputs: // num = device to transmit to (zero based) // buf = buffer containing packet to send // len = number of bytes to transmit // timeout = time to wait, in milliseconds // Output: // number of bytes sent, or -1 on error // int rawhid_send(int num, void *buf, int len, int timeout) { //fprintf(stderr,"rawhid_send num: %d\n",num); hid_t *hid; int result=-100; hid = get_hid(num); if (!hid || !hid->open) return -1; //fprintf(stderr,"rawhid_send A\n"); #if 1 #warning "Send timeout not implemented on MACOSX" IOReturn ret = IOHIDDeviceSetReport(hid->ref, kIOHIDReportTypeOutput, 0, buf, len); result = (ret == kIOReturnSuccess) ? len : -1; //fprintf(stderr,"rawhid_send B result: %d\n",result); #endif #if 0 // No matter what I tried this never actually sends an output // report and output_callback never gets called. Why?? // Did I miss something? This is exactly the same params as // the sync call that works. Is it an Apple bug? // (submitted to Apple on 22-sep-2009, problem ID 7245050) // fprintf(stderr,"rawhid_send C\n"); IOHIDDeviceScheduleWithRunLoop(hid->ref, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); // should already be scheduled with run loop by attach_callback, // sadly this doesn't make any difference either way // IOHIDDeviceSetReportWithCallback(hid->ref, kIOHIDReportTypeOutput, 0, buf, len, (double)timeout / 1000.0, output_callback, &result); //fprintf(stderr,"rawhid_send D\n"); while (1) { fprintf(stderr,"enter run loop (send)\n"); CFRunLoopRun(); fprintf(stderr,"leave run loop (send)\n"); if (result > -100) break; if (!hid->open) { result = -1; break; } } #endif fprintf(stderr,"rawhid_send result: %d\n",result); return result; }
const char* get_prod() { hid_t * cnc = get_hid(0); if (cnc) { CFTypeRef prod= IOHIDDeviceGetProperty(cnc->ref,CFSTR(kIOHIDProductKey)); //CFStringRef manu = (CFStringRef)prop; const char* prodstr = CFStringGetCStringPtr(prod, kCFStringEncodingMacRoman); //fprintf(stderr,"prodstr: %s\n",prodstr); return prodstr; } else { return "*\n"; } }
const char* get_manu() { hid_t * cnc = get_hid(0); if (cnc) { CFTypeRef manu= IOHIDDeviceGetProperty(cnc->ref,CFSTR(kIOHIDManufacturerKey)); //CFStringRef manu = (CFStringRef)prop; const char* manustr = CFStringGetCStringPtr(manu, kCFStringEncodingMacRoman); //fprintf(stderr,"manustr: %s\n",manustr); return manustr; } else { return "Kein USB-Device vorhanden\n"; } }
QString pjrc_rawhid::getserial(int num) { hid_t *hid; char buf[128]; hid = get_hid(num); if (!hid || !hid->open) return QString("Error"); CFTypeRef serialnum = IOHIDDeviceGetProperty(hid->ref, CFSTR(kIOHIDSerialNumberKey)); if(serialnum && CFGetTypeID(serialnum) == CFStringGetTypeID()) { //Note: I'm not sure it will always succeed if encoded as MacRoman but that //is a superset of UTF8 so I think this is fine CFStringRef str = (CFStringRef)serialnum; const char * buf = CFStringGetCStringPtr(str, kCFStringEncodingMacRoman); return QString(buf); } return QString("Error"); }
// close - close a device // // Inputs: // num = device to close (zero based) // Output // (nothing) // void pjrc_rawhid::close(int num) { hid_close(get_hid(num)); }
// send - send a packet // Inputs: // num = device to transmit to (zero based) // buf = buffer containing packet to send // len = number of bytes to transmit // timeout = time to wait, in milliseconds // Output: // number of bytes sent, or -1 on error // int pjrc_rawhid::send(int num, void *buf, int len, int timeout) { OVERLAPPED ov; DWORD n, r; hid_t *hid = get_hid(num); if (!hid) return -1; if (!hid->handle) return -1; // qDebug("Send: Handle address: %li for num: %i", (long int) hid->handle, num); EnterCriticalSection(&tx_mutex); ResetEvent(&tx_event); memset(&ov, 0, sizeof(ov)); ov.hEvent = tx_event; // qDebug("Trying to write %u bytes. First %x second %x",len, *((char *) buf), *((char *)buf + 1)); if (!WriteFile(hid->handle, buf, len, NULL, &ov)) { DWORD err = GetLastError(); if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged hid_close(hid); LeaveCriticalSection(&tx_mutex); emit deviceUnplugged(num); return -1; } if (err == ERROR_SUCCESS || err == ERROR_IO_PENDING) { // qDebug("Waiting for write to finish"); r = WaitForSingleObject(tx_event, timeout); if (r == WAIT_TIMEOUT) { CancelIo(hid->handle); LeaveCriticalSection(&tx_mutex); return 0; } if (r != WAIT_OBJECT_0) { DWORD err = GetLastError(); print_win32_err(err); LeaveCriticalSection(&tx_mutex); return -1; } } else { // qDebug("Error writing to file"); print_win32_err(err); LeaveCriticalSection(&tx_mutex); return -1; } } if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) { DWORD err = GetLastError(); qDebug("Problem getting overlapped result"); print_win32_err(err); if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged hid_close(hid); LeaveCriticalSection(&tx_mutex); emit deviceUnplugged(num); return -1; } } LeaveCriticalSection(&tx_mutex); if (n <= 0) return -1; return n; }
// recveive - receive a packet // Inputs: // num = device to receive from (zero based) // buf = buffer to receive packet // len = buffer's size // timeout = time to wait, in milliseconds // Output: // number of bytes received, or -1 on error // int pjrc_rawhid::receive(int num, void *buf, int len, int timeout) { OVERLAPPED ov; DWORD n; hid_t *hid = get_hid(num); if (!hid) return -1; if (!hid->handle) return -1; EnterCriticalSection(&rx_mutex); ResetEvent(&rx_event); memset(&ov, 0, sizeof(ov)); ov.hEvent = rx_event; if (!ReadFile(hid->handle, buf, len, NULL, &ov)) { DWORD err = GetLastError(); if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged print_win32_err(err); hid_close(hid); LeaveCriticalSection(&rx_mutex); emit deviceUnplugged(num); return -1; } if (err != ERROR_IO_PENDING) { print_win32_err(err); LeaveCriticalSection(&rx_mutex); return -1; } DWORD r = WaitForSingleObject(rx_event, timeout); if (r == WAIT_TIMEOUT) { CancelIo(hid->handle); LeaveCriticalSection(&rx_mutex); return 0; } if (r != WAIT_OBJECT_0) { DWORD err = GetLastError(); print_win32_err(err); LeaveCriticalSection(&rx_mutex); return -1; } } if (!GetOverlappedResult(hid->handle, &ov, &n, FALSE)) { DWORD err = GetLastError(); print_win32_err(err); if (err == ERROR_DEVICE_NOT_CONNECTED) { // the device has been unplugged hid_close(hid); LeaveCriticalSection(&rx_mutex); emit deviceUnplugged(num); return -1; } LeaveCriticalSection(&rx_mutex); return -1; } LeaveCriticalSection(&rx_mutex); if (n <= 0) return -1; // qDebug("Received %i bytes, first %x, second %x", len, *((char *) buf),*((char *)buf + 1)); if ((int)n > len) n = len; return n; }