hid_device * HID_API_EXPORT hid_open_path(const char *path) { hid_device *dev = NULL; hid_init(); dev = new_hid_device(); if (kernel_version == 0) { struct utsname name; int major, minor, release; int ret; uname(&name); ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release); if (ret == 3) { kernel_version = major << 16 | minor << 8 | release; //printf("Kernel Version: %d\n", kernel_version); } else { printf("Couldn't sscanf() version string %s\n", name.release); } } // OPEN HERE // dev->device_handle = open(path, O_RDWR); // If we have a good handle, return it. if (dev->device_handle > 0) { /* Get the report descriptor */ int res; struct hidraw_report_descriptor rpt_desc; res = get_report_descriptor(dev->device_handle, &rpt_desc); if (res >= 0) { /* Determine if this device uses numbered reports. */ dev->uses_numbered_reports = uses_numbered_reports(rpt_desc.value, rpt_desc.size); } return dev; } else { // Unable to open any devices. free(dev); return NULL; } }
static unsigned int handle_standard_requests() { switch(usb_setup_buffer.bmRequestType) { case 0x80: /* standard device IN requests */ switch(usb_setup_buffer.bRequest) { case GET_DESCRIPTOR: switch (HIGH_BYTE(usb_setup_buffer.wValue)) { case DEVICE: get_device_descriptor(); break; case CONFIGURATION: get_configuration_descriptor(); break; case STRING: get_string_descriptor(); break; default: /* Unknown descriptor */ return 0; } break; case GET_CONFIGURATION: get_configuration(); break; case GET_STATUS: get_device_status(); break; case GET_INTERFACE: get_interface(); break; default: return 0; } break; case 0x81: /* standard interface IN requests */ switch(usb_setup_buffer.bRequest) { case GET_STATUS: get_interface_status(); break; #ifdef HID_ENABLED case GET_DESCRIPTOR: switch (USB_setup_buffer.wValue.byte.high) { case REPORT: get_report_descriptor(); break; } break; #endif default: return 0; } break; case 0x82: /* standard endpoint IN requests */ switch(usb_setup_buffer.bRequest) { case GET_STATUS: get_endpoint_status(); break; default: return 0; } break; case 0x00: /* standard device OUT requests */ switch(usb_setup_buffer.bRequest) { case SET_ADDRESS: PRINTF("Address: %d\r\n", LOW_BYTE(usb_setup_buffer.wValue)); usb_flags |= USB_FLAG_ADDRESS_PENDING; /* The actual setting of the address is done when the status packet is sent. */ usb_send_ctrl_status(); break; #if SETABLE_STRING_DESCRIPTORS > 0 case SET_DESCRIPTOR: if (usb_setup_buffer.wValue.byte.high == STRING) { set_string_descriptor(); } else { return 0; } break; #endif case SET_CONFIGURATION: if (set_configuration()) { #if 0 config_msg.data.config = LOW_BYTE(usb_setup_buffer.wValue); notify_user(&config_msg); #endif } break; default: return 0; } break; case 0x01: /* standard interface OUT requests */ switch(usb_setup_buffer.bRequest) { case SET_INTERFACE: /* Change interface here if we support more than one */ usb_send_ctrl_status(); break; default: return 0; } break; case 0x02: /* standard endpoint OUT requests */ switch(usb_setup_buffer.bRequest) { case SET_FEATURE: case CLEAR_FEATURE: if (usb_setup_buffer.wValue == ENDPOINT_HALT_FEATURE) { usb_arch_halt_endpoint(usb_setup_buffer.wIndex, usb_setup_buffer.bRequest== SET_FEATURE); usb_send_ctrl_status(); } else { usb_error_stall(); } break; default: return 0; } break; #ifdef HID_ENABLED case 0xa1: /* class specific interface IN request*/ switch(USB_setup_buffer.bRequest) { case GET_HID_REPORT: PRINTF("Get report\r\n"); send_ctrl_response((code u_int8_t*)&zero_byte, sizeof(zero_byte)); break; case GET_HID_IDLE: PRINTF("Get idle\r\n"); send_ctrl_response((code u_int8_t*)&zero_byte, sizeof(zero_byte)); break; default: return 0; } break; case 0x21: /* class specific interface OUT request*/ switch(USB_setup_buffer.bRequest) { case SET_HID_IDLE: PRINTF("Set idle\r\n"); send_ctrl_status(); break; default: return 0; } break; #endif default: return 0; } return 1; }
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct hid_device_info *root = NULL; // return object struct hid_device_info *cur_dev = NULL; hid_init(); /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); return NULL; } /* Create a list of the devices in the 'hidraw' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "hidraw"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each item, see if it matches the vid/pid, and if so create a udev_device record for it */ udev_list_entry_foreach(dev_list_entry, devices) { const char *sysfs_path; const char *dev_path; const char *str; struct udev_device *hid_dev; // The device's HID udev node. struct udev_device *dev; // The actual hardware device. struct udev_device *intf_dev; // The device's interface (in the USB sense). unsigned short dev_vid; unsigned short dev_pid; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ sysfs_path = udev_list_entry_get_name(dev_list_entry); hid_dev = udev_device_new_from_syspath(udev, sysfs_path); dev_path = udev_device_get_devnode(hid_dev); /* The device pointed to by hid_dev contains information about the hidraw device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it.*/ dev = udev_device_get_parent_with_subsystem_devtype( hid_dev, "usb", "usb_device"); if (!dev) { /* Unable to find parent usb device. */ goto next; } /* Get the VID/PID of the device */ str = udev_device_get_sysattr_value(dev,"idVendor"); dev_vid = (str)? strtol(str, NULL, 16): 0x0; str = udev_device_get_sysattr_value(dev, "idProduct"); dev_pid = (str)? strtol(str, NULL, 16): 0x0; /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 && product_id == 0x0) || (vendor_id == dev_vid && product_id == dev_pid)) { struct hid_device_info *tmp; size_t len; /* VID/PID match. Create the record. */ tmp = malloc(sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Fill out the record */ cur_dev->next = NULL; str = dev_path; if (str) { len = strlen(str); cur_dev->path = calloc(len+1, sizeof(char)); strncpy(cur_dev->path, str, len+1); cur_dev->path[len] = '\0'; } else cur_dev->path = NULL; /* Serial Number */ cur_dev->serial_number = copy_udev_string(dev, "serial"); /* Manufacturer and Product strings */ cur_dev->manufacturer_string = copy_udev_string(dev, "manufacturer"); cur_dev->product_string = copy_udev_string(dev, "product"); /* Usage Page and Usage */ int res; struct hidraw_report_descriptor rpt_desc; int device_handle = open(dev_path, O_RDWR); if (device_handle > 0) { res = get_report_descriptor(device_handle, &rpt_desc); if (res >= 0) { unsigned short page=0, usage=0; /* Parse the usage and usage page out of the report descriptor. */ get_usage(rpt_desc.value, rpt_desc.size, &page, &usage); cur_dev->usage_page = page; cur_dev->usage = usage; } close(device_handle); } /* VID/PID */ cur_dev->vendor_id = dev_vid; cur_dev->product_id = dev_pid; /* Release Number */ str = udev_device_get_sysattr_value(dev, "bcdDevice"); cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; /* Interface Number */ cur_dev->interface_number = -1; /* Get a handle to the interface's udev node. */ intf_dev = udev_device_get_parent_with_subsystem_devtype( hid_dev, "usb", "usb_interface"); if (intf_dev) { str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; } } else goto next; next: udev_device_unref(hid_dev); /* dev and intf_dev don't need to be (and can't be) unref()d. It will cause a double-free() error. I'm not sure why. */ } /* Free the enumerator and udev objects. */ udev_enumerate_unref(enumerate); udev_unref(udev); return root; }