static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) { struct hid_struct *h; //fprintf(stderr,"attach callback\n"); // if (IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone) != kIOReturnSuccess) return; h = (hid_t *)malloc(sizeof(hid_t)); if (!h) return; memset(h, 0, sizeof(hid_t)); IOHIDDeviceScheduleWithRunLoop(dev, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); IOHIDDeviceRegisterInputReportCallback(dev, h->buffer, sizeof(h->buffer), input_callback, h); h->ref = dev; h->open = 1; add_hid(h); usbstatus=1; /* r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200); if (r <= 0) { fprintf(stderr,"no rawhid device found\n"); } else { fprintf(stderr,"new rawhid device found\n"); } */ }
static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev) { struct hid_struct *h; printf("attach callback\n"); if (IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone) != kIOReturnSuccess) return; h = (hid_t *)malloc(sizeof(hid_t)); if (!h) return; memset(h, 0, sizeof(hid_t)); IOHIDDeviceScheduleWithRunLoop(dev, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); IOHIDDeviceRegisterInputReportCallback(dev, h->buffer, sizeof(h->buffer), input_callback, h); h->ref = dev; h->open = 1; add_hid(h); }
// rawhid_open - open 1 or more devices // // Inputs: // max = maximum number of devices to open // vid = Vendor ID, or -1 if any // pid = Product ID, or -1 if any // usage_page = top level usage page, or -1 if any // usage = top level usage number, or -1 if any // Output: // actual number of devices opened // int rawhid_open(int max, int vid, int pid, int usage_page, int usage) { struct usb_bus *bus; struct usb_device *dev; struct usb_interface *iface; struct usb_interface_descriptor *desc; struct usb_endpoint_descriptor *ep; usb_dev_handle *u; uint8_t buf[1024], *p; int i, n, len, tag, ep_in, ep_out, count=0, claimed; uint32_t val=0, parsed_usage, parsed_usage_page; hid_t *hid; if (first_hid) free_all_hid(); printf("rawhid_open, max=%d\n", max); if (max < 1) return 0; usb_init(); usb_find_busses(); usb_find_devices(); for (bus = usb_get_busses(); bus; bus = bus->next) { for (dev = bus->devices; dev; dev = dev->next) { if (vid > 0 && dev->descriptor.idVendor != vid) continue; if (pid > 0 && dev->descriptor.idProduct != pid) continue; if (!dev->config) continue; if (dev->config->bNumInterfaces < 1) continue; printf("device: vid=%04X, pic=%04X, with %d iface\n", dev->descriptor.idVendor, dev->descriptor.idProduct, dev->config->bNumInterfaces); iface = dev->config->interface; u = NULL; claimed = 0; for (i=0; i<dev->config->bNumInterfaces && iface; i++, iface++) { desc = iface->altsetting; if (!desc) continue; printf(" type %d, %d, %d\n", desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol); if (desc->bInterfaceClass != 3) continue; if (desc->bInterfaceSubClass != 0) continue; if (desc->bInterfaceProtocol != 0) continue; ep = desc->endpoint; ep_in = ep_out = 0; for (n = 0; n < desc->bNumEndpoints; n++, ep++) { if (ep->bEndpointAddress & 0x80) { if (!ep_in) ep_in = ep->bEndpointAddress & 0x7F; printf(" IN endpoint %d\n", ep_in); } else { if (!ep_out) ep_out = ep->bEndpointAddress; printf(" OUT endpoint %d\n", ep_out); } } if (!ep_in) continue; if (!u) { u = usb_open(dev); if (!u) { printf(" unable to open device\n"); break; } } printf(" hid interface (generic)\n"); if (usb_get_driver_np(u, i, (char *)buf, sizeof(buf)) >= 0) { printf(" in use by driver \"%s\"\n", buf); if (usb_detach_kernel_driver_np(u, i) < 0) { printf(" unable to detach from kernel\n"); continue; } } if (usb_claim_interface(u, i) < 0) { printf(" unable claim interface %d\n", i); continue; } len = usb_control_msg(u, 0x81, 6, 0x2200, i, (char *)buf, sizeof(buf), 250); printf(" descriptor, len=%d\n", len); if (len < 2) { usb_release_interface(u, i); continue; } p = buf; parsed_usage_page = parsed_usage = 0; while ((tag = hid_parse_item(&val, &p, buf + len)) >= 0) { printf(" tag: %X, val %X\n", tag, val); if (tag == 4) parsed_usage_page = val; if (tag == 8) parsed_usage = val; if (parsed_usage_page && parsed_usage) break; } if ((!parsed_usage_page) || (!parsed_usage) || (usage_page > 0 && parsed_usage_page != usage_page) || (usage > 0 && parsed_usage != usage)) { usb_release_interface(u, i); continue; } hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); if (!hid) { usb_release_interface(u, i); continue; } hid->usb = u; hid->iface = i; hid->ep_in = ep_in; hid->ep_out = ep_out; hid->open = 1; add_hid(hid); claimed++; count++; if (count >= max) return count; } if (u && !claimed) usb_close(u); } } return count; }
// open - open 1 or more devices // // Inputs: // max = maximum number of devices to open // vid = Vendor ID, or -1 if any // pid = Product ID, or -1 if any // usage_page = top level usage page, or -1 if any // usage = top level usage number, or -1 if any // Output: // actual number of devices opened // int pjrc_rawhid::open(int max, int vid, int pid, int usage_page, int usage) { GUID guid; HDEVINFO info; DWORD index=0, reqd_size; SP_DEVICE_INTERFACE_DATA iface; SP_DEVICE_INTERFACE_DETAIL_DATA *details; HIDD_ATTRIBUTES attrib; PHIDP_PREPARSED_DATA hid_data; HIDP_CAPS capabilities; HANDLE h; BOOL ret; hid_t *hid; int count=0; if (first_hid) free_all_hid(); if (max < 1) return 0; if (!rx_event) { rx_event = CreateEvent(NULL, TRUE, TRUE, NULL); tx_event = CreateEvent(NULL, TRUE, TRUE, NULL); InitializeCriticalSection(&rx_mutex); InitializeCriticalSection(&tx_mutex); } HidD_GetHidGuid(&guid); info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (info == INVALID_HANDLE_VALUE) return 0; for (index=0; 1 ;index++) { iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface); if (!ret) return count; SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &reqd_size, NULL); details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(reqd_size); if (details == NULL) continue; memset(details, 0, reqd_size); details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details, reqd_size, NULL, NULL); if (!ret) { free(details); continue; } h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (h == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); // I get ERROR_ACCESS_DENIED with most/all my input devices (mice/trackballs/tablet). // Let's not log it :) if (err == ERROR_ACCESS_DENIED) { free(details); continue; } // qDebug wipes the GetLastError() it seems, so do that after print_win32_err(). print_win32_err(err); qDebug() << "Problem opening handle, path: " << QString().fromWCharArray(details->DevicePath); free(details); continue; } free(details); attrib.Size = sizeof(HIDD_ATTRIBUTES); ret = HidD_GetAttributes(h, &attrib); //printf("vid: %4x\n", attrib.VendorID); if (!ret || (vid > 0 && attrib.VendorID != vid) || (pid > 0 && attrib.ProductID != pid) || !HidD_GetPreparsedData(h, &hid_data)) { CloseHandle(h); continue; } if (!HidP_GetCaps(hid_data, &capabilities) || (usage_page > 0 && capabilities.UsagePage != usage_page) || (usage > 0 && capabilities.Usage != usage)) { HidD_FreePreparsedData(hid_data); CloseHandle(h); continue; } HidD_FreePreparsedData(hid_data); hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); if (!hid) { CloseHandle(h); continue; } // COMMTIMEOUTS CommTimeouts; // CommTimeouts.ReadIntervalTimeout = 100; // 100ms // CommTimeouts.ReadTotalTimeoutConstant = 5; // ms // CommTimeouts.ReadTotalTimeoutMultiplier = 1; // // CommTimeouts.WriteTotalTimeoutConstant = 5; // ms // CommTimeouts.WriteTotalTimeoutMultiplier = 1; // // if (!SetCommTimeouts(h, &CommTimeouts)) // { //// DWORD err = GetLastError(); // // } qDebug("Open: Handle address: %li for num: %i", (long int) h, count); hid->handle = h; add_hid(hid); count++; if (count >= max) return count; } return count; }
int main(int argc, char *argv[]) { int i; if (argc == 1) { printf("version : %s\n", HIDEMU_VERSION); return 0; } if(hci_get_route(NULL) < 0) { printf("Bluetooth off\n"); return -1; } if (DBG_CONSOLE) { for (i = 0; i < argc; i++) { printf("arg[%d]=%s\n", i, argv[i]); } } if (argc == ADD_HID_ARGS && (strncmp(argv[1], ADD_HID_GENERIC, strlen(argv[1])) == 0)) { int handle = add_hid(HID_MODE_GENERIC); printf("handle: 0x%X\n", handle); if (sdp_record != NULL) { sdp_record_free(sdp_record); } } else if (argc == ADD_HID_ARGS && (strncmp(argv[1], ADD_HID_BDREMOTE, strlen(argv[1])) == 0)) { int handle = add_hid(HID_MODE_BDREMOTE); printf("handle: 0x%X\n", handle); if (sdp_record != NULL) { sdp_record_free(sdp_record); } } else if (argc == ADD_HID_ARGS && (strncmp(argv[1], ADD_HID_PS3KEYPAD, strlen(argv[1])) == 0)) { int handle = add_hid(HID_MODE_PS3KEYPAD); printf("handle: 0x%X\n", handle); if (sdp_record != NULL) { sdp_record_free(sdp_record); } } else if (argc == DEL_HID_ARGS && (strncmp(argv[1], DEL_HID, strlen(argv[1])) == 0) && !strncasecmp(argv[2], "0x", 2)) { int handle = strtol(argv[2]+2, NULL, 16); printf("Removed handle: 0x%X\n", handle); if (!sdp_session) { sdp_open(sdp_session); } sdp_remove(handle); sdp_close(sdp_session); } else if (argc == READ_CLASS_ARGS && (strncmp(argv[1], READ_CLASS, strlen(argv[1])) == 0)) { uint8_t cls[3]; if (read_device_class(0, cls) == 0) { printf("class: 0x%02x%02x%02x\n", cls[2], cls[1], cls[0]); } } else if (argc == SPOOF_CLASS_ARGS && (strncmp(argv[1], SPOOF_CLASS, strlen(argv[1])) == 0)) { if (spoof_device_class(0, argv[2]) == 0) { printf("class spoofed.\n"); } } else { printf("Invalid arguments\n"); LOGE("Invalid arguments\n"); } return 0; }
// rawhid_open - open 1 or more devices // // Inputs: // max = maximum number of devices to open // vid = Vendor ID, or -1 if any // pid = Product ID, or -1 if any // usage_page = top level usage page, or -1 if any // usage = top level usage number, or -1 if any // Output: // actual number of devices opened // int rawhid_open(int max, int vid, int pid, int usage_page, int usage) { GUID guid; HDEVINFO info; DWORD index=0, reqd_size; SP_DEVICE_INTERFACE_DATA iface; SP_DEVICE_INTERFACE_DETAIL_DATA *details; HIDD_ATTRIBUTES attrib; PHIDP_PREPARSED_DATA hid_data; HIDP_CAPS capabilities; HANDLE h; BOOL ret; hid_t *hid; int count=0; if (first_hid) free_all_hid(); if (max < 1) return 0; if (!rx_event) { rx_event = CreateEvent(NULL, TRUE, TRUE, NULL); tx_event = CreateEvent(NULL, TRUE, TRUE, NULL); InitializeCriticalSection(&rx_mutex); InitializeCriticalSection(&tx_mutex); } HidD_GetHidGuid(&guid); info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (info == INVALID_HANDLE_VALUE) return 0; for (index=0; 1 ;index++) { iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface); if (!ret) return count; SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &reqd_size, NULL); details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(reqd_size); if (details == NULL) continue; memset(details, 0, reqd_size); details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details, reqd_size, NULL, NULL); if (!ret) { free(details); continue; } h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); free(details); if (h == INVALID_HANDLE_VALUE) continue; attrib.Size = sizeof(HIDD_ATTRIBUTES); ret = HidD_GetAttributes(h, &attrib); //printf("vid: %4x\n", attrib.VendorID); if (!ret || (vid > 0 && attrib.VendorID != vid) || (pid > 0 && attrib.ProductID != pid) || !HidD_GetPreparsedData(h, &hid_data)) { CloseHandle(h); continue; } if (!HidP_GetCaps(hid_data, &capabilities) || (usage_page > 0 && capabilities.UsagePage != usage_page) || (usage > 0 && capabilities.Usage != usage)) { HidD_FreePreparsedData(hid_data); CloseHandle(h); continue; } HidD_FreePreparsedData(hid_data); hid = (struct hid_struct *)malloc(sizeof(struct hid_struct)); if (!hid) { CloseHandle(h); continue; } hid->handle = h; hid->open = 1; add_hid(hid); count++; if (count >= max) return count; } return count; }