Пример #1
0
struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
	libusb_device **devs;
	libusb_device *dev;
	libusb_device_handle *handle;
	ssize_t num_devs;
	int i = 0;
	
	struct hid_device_info *root = NULL; // return object
	struct hid_device_info *cur_dev = NULL;
	
	setlocale(LC_ALL,"");
	
	if (!initialized) {
		libusb_init(NULL);
		initialized = 1;
	}
	
	num_devs = libusb_get_device_list(NULL, &devs);
	if (num_devs < 0)
		return NULL;
	while ((dev = devs[i++]) != NULL) {
		struct libusb_device_descriptor desc;
		struct libusb_config_descriptor *conf_desc = NULL;
		int skip = 1;
		int j, k;
		int interface_num = 0;

		int res = libusb_get_device_descriptor(dev, &desc);
		unsigned short dev_vid = desc.idVendor;
		unsigned short dev_pid = desc.idProduct;
		
		/* HID's are defined at the interface level. */
		if (desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE)
			continue;

		res = libusb_get_active_config_descriptor(dev, &conf_desc);
		if (res < 0)
			libusb_get_config_descriptor(dev, 0, &conf_desc);
		if (conf_desc) {
			for (j = 0; j < conf_desc->bNumInterfaces; j++) {
				const struct libusb_interface *intf = &conf_desc->interface[j];
				for (k = 0; k < intf->num_altsetting; k++) {
					const struct libusb_interface_descriptor *intf_desc;
					intf_desc = &intf->altsetting[k];
					if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
						interface_num = intf_desc->bInterfaceNumber;
						skip = 0;
					}
				}
			}
			libusb_free_config_descriptor(conf_desc);
		}

		if (skip)
			continue;
			
		/* 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;

		    	/* VID/PID match. Create the record. */
			tmp = calloc(1, 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;
			cur_dev->path = make_path(dev, interface_num);
			
			res = libusb_open(dev, &handle);


			if (res >= 0) {
			
				/* Serial Number */
				if (desc.iSerialNumber > 0)
					cur_dev->serial_number =
						get_usb_string(handle, desc.iSerialNumber);

				/* Manufacturer and Product strings */
				if (desc.iManufacturer > 0)
					cur_dev->manufacturer_string =
						get_usb_string(handle, desc.iManufacturer);
				if (desc.iProduct > 0)
					cur_dev->product_string =
						get_usb_string(handle, desc.iProduct);
				
				libusb_close(handle);
			}
			/* VID/PID */
			cur_dev->vendor_id = dev_vid;
			cur_dev->product_id = dev_pid;
		}
	}

	libusb_free_device_list(devs, 1);

	return root;
}
Пример #2
0
struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
	libusb_device **devs;
	libusb_device *dev;
	libusb_device_handle *handle;
	ssize_t num_devs;
	int i = 0;
	
	struct hid_device_info *root = NULL; // return object
	struct hid_device_info *cur_dev = NULL;
	
	hid_init();

	num_devs = libusb_get_device_list(usb_context, &devs);
	if (num_devs < 0)
		return NULL;
	while ((dev = devs[i++]) != NULL) {
		struct libusb_device_descriptor desc;
		struct libusb_config_descriptor *conf_desc = NULL;
		int j, k;
		int interface_num = 0;

		int res = libusb_get_device_descriptor(dev, &desc);
		unsigned short dev_vid = desc.idVendor;
		unsigned short dev_pid = desc.idProduct;
		
		/* HID's are defined at the interface level. */
		if (desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE)
			continue;

		res = libusb_get_active_config_descriptor(dev, &conf_desc);
		if (res < 0)
			libusb_get_config_descriptor(dev, 0, &conf_desc);
		if (conf_desc) {
			for (j = 0; j < conf_desc->bNumInterfaces; j++) {
				const struct libusb_interface *intf = &conf_desc->interface[j];
				for (k = 0; k < intf->num_altsetting; k++) {
					const struct libusb_interface_descriptor *intf_desc;
					intf_desc = &intf->altsetting[k];
					if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) {
						interface_num = intf_desc->bInterfaceNumber;

						/* 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;

							/* VID/PID match. Create the record. */
							tmp = calloc(1, 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;
							cur_dev->path = make_path(dev, interface_num);
							
							res = libusb_open(dev, &handle);

							if (res >= 0) {
								/* Serial Number */
								if (desc.iSerialNumber > 0)
									cur_dev->serial_number =
										get_usb_string(handle, desc.iSerialNumber);

								/* Manufacturer and Product strings */
								if (desc.iManufacturer > 0)
									cur_dev->manufacturer_string =
										get_usb_string(handle, desc.iManufacturer);
								if (desc.iProduct > 0)
									cur_dev->product_string =
										get_usb_string(handle, desc.iProduct);

#ifdef INVASIVE_GET_USAGE
							/*
							This section is removed because it is too
							invasive on the system. Getting a Usage Page
							and Usage requires parsing the HID Report
							descriptor. Getting a HID Report descriptor
							involves claiming the interface. Claiming the
							interface involves detaching the kernel driver.
							Detaching the kernel driver is hard on the system
							because it will unclaim interfaces (if another
							app has them claimed) and the re-attachment of
							the driver will sometimes change /dev entry names.
							It is for these reasons that this section is
							#if 0. For composite devices, use the interface
							field in the hid_device_info struct to distinguish
							between interfaces. */
								unsigned char data[256];
#ifdef DETACH_KERNEL_DRIVER
								int detached = 0;
								/* Usage Page and Usage */
								res = libusb_kernel_driver_active(handle, interface_num);
								if (res == 1) {
									res = libusb_detach_kernel_driver(handle, interface_num);
									if (res < 0)
										LOG("Couldn't detach kernel driver, even though a kernel driver was attached.");
									else
										detached = 1;
								}
#endif
								res = libusb_claim_interface(handle, interface_num);
								if (res >= 0) {
									/* Get the HID Report Descriptor. */
									res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000);
									if (res >= 0) {
										unsigned short page=0, usage=0;
										/* Parse the usage and usage page
										   out of the report descriptor. */
										get_usage(data, res,  &page, &usage);
										cur_dev->usage_page = page;
										cur_dev->usage = usage;
									}
									else
										LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res);

									/* Release the interface */
									res = libusb_release_interface(handle, interface_num);
									if (res < 0)
										LOG("Can't release the interface.\n");
								}
								else
									LOG("Can't claim interface %d\n", res);
#ifdef DETACH_KERNEL_DRIVER
								/* Re-attach kernel driver if necessary. */
								if (detached) {
									res = libusb_attach_kernel_driver(handle, interface_num);
									if (res < 0)
										LOG("Couldn't re-attach kernel driver.\n");
								}
#endif

#endif // INVASIVE_GET_USAGE

								libusb_close(handle);
							}
							/* VID/PID */
							cur_dev->vendor_id = dev_vid;
							cur_dev->product_id = dev_pid;

							/* Release Number */
							cur_dev->release_number = desc.bcdDevice;
							
							/* Interface Number */
							cur_dev->interface_number = interface_num;
						}
					}
				} /* altsettings */
			} /* interfaces */
			libusb_free_config_descriptor(conf_desc);
		}
	}

	libusb_free_device_list(devs, 1);

	return root;
}
Пример #3
0
int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid)
{
  struct usb_device *found = NULL;
  struct usb_device *dev;
  struct usb_bus *bus;

  /* At last, we reach out through the USB bus to the part. There are three
   * ways to specify the part: by USB address, by USB vendor and product id,
   * and by part name. To specify the part by USB address, the user specifies
   * a port parameter in the form "usb:BUS:DEV" (see dfu_open()). To specify
   * the part by vendor and product, the user must specify a usbvid and usbpid
   * in the configuration file. Finally, if the user specifies the part only,
   * we use the default vendor and product id.
   */

  if (pid == 0 && dfu->dev_name == NULL) {
    fprintf(stderr, "%s: Error: No DFU support for part; "
      "specify PID in config or USB address (via -P) to override.\n",
      progname);
    return -1;
  }

  /* Scan through all the devices for the part. The matching rules are:
   *
   *   1. If the user specified a USB bus name, it must match.
   *   2. If the user specified a USB device name, it must match.
   *   3. If the user didn't specify a USB device name and specified a vendor
   *      id, the vendor id must match.
   *   4. If the user didn't specify a USB device name and specified a product
   *      id, the product id must match.
   */

  for (bus = usb_busses; !found && bus != NULL; bus = bus->next) {
    for (dev = bus->devices; !found && dev != NULL; dev = dev->next) {
      if (dfu->bus_name != NULL && strcmp(bus->dirname, dfu->bus_name))
         continue;
      if (dfu->dev_name != NULL) {
        if (strcmp(dev->filename, dfu->dev_name))
          continue;
      } else if (vid != dev->descriptor.idVendor)
        continue;
      else if (pid != 0 && pid != dev->descriptor.idProduct)
        continue;

      found = dev;
    }
  }

  if (found == NULL) {
    /* We could try to be more informative here. For example, we could report
     * why the match failed, and if we came across another DFU-capable part.
     */

    fprintf(stderr, "%s: Error: No matching USB device found\n", progname);
    return -1;
  }

  if(verbose)
    fprintf(stderr,
      "%s: Found VID=0x%04x PID=0x%04x at %s:%s\n",
      progname, found->descriptor.idVendor, found->descriptor.idProduct,
      found->bus->dirname, found->filename);

  dfu->dev_handle = usb_open(found);

  if (dfu->dev_handle == NULL) {
    fprintf(stderr, "%s: Error: USB device at %s:%s: %s\n",
      progname, found->bus->dirname, found->filename, usb_strerror());
    return -1;
  }

  /* Save device, configuration, interface and endpoint descriptors. */

  memcpy(&dfu->dev_desc, &found->descriptor, sizeof(dfu->dev_desc));
  memcpy(&dfu->conf_desc, found->config, sizeof(dfu->conf_desc));
  dfu->conf_desc.interface = NULL;

  memcpy(&dfu->intf_desc, found->config->interface->altsetting,
    sizeof(dfu->intf_desc));
  dfu->intf_desc.endpoint = &dfu->endp_desc;

  if (found->config->interface->altsetting->endpoint != 0)
      memcpy(&dfu->endp_desc, found->config->interface->altsetting->endpoint,
             sizeof(dfu->endp_desc));

  /* Get strings. */

  dfu->manf_str = get_usb_string(dfu->dev_handle,
    dfu->dev_desc.iManufacturer);

  dfu->prod_str = get_usb_string(dfu->dev_handle,
    dfu->dev_desc.iProduct);

  dfu->serno_str = get_usb_string(dfu->dev_handle,
    dfu->dev_desc.iSerialNumber);

  return 0;
}