+
+static uint16_t
+read_le16(uint8_t *src)
+{
+ return (uint16_t) src[0] | ((uint16_t) src[1] << 8);
+}
+
+bool
+ao_heximage_usb_id(struct ao_hex_image *image, struct ao_usb_id *id)
+{
+ uint32_t usb_descriptors;
+
+ if (!AO_USB_DESCRIPTORS)
+ return false;
+ usb_descriptors = AO_USB_DESCRIPTORS - image->address;
+
+ while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) {
+ if (image->data[usb_descriptors+1] == AO_USB_DESC_DEVICE) {
+ break;
+ }
+ usb_descriptors += image->data[usb_descriptors];
+ }
+
+ /*
+ * check to make sure there's at least 0x12 (size of a USB
+ * device descriptor) available
+ */
+ if (usb_descriptors >= image->length || image->data[usb_descriptors] != 0x12)
+ return false;
+
+ id->vid = read_le16(image->data + usb_descriptors + 8);
+ id->pid = read_le16(image->data + usb_descriptors + 10);
+
+ return true;
+}
+
+uint16_t *
+ao_heximage_usb_product(struct ao_hex_image *image)
+{
+ uint32_t usb_descriptors;
+ int string_num;
+ uint16_t *product;
+ uint8_t product_len;
+
+ if (!AO_USB_DESCRIPTORS)
+ return NULL;
+ usb_descriptors = AO_USB_DESCRIPTORS - image->address;
+
+ string_num = 0;
+ while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) {
+ if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) {
+ ++string_num;
+ if (string_num == 3)
+ break;
+ }
+ usb_descriptors += image->data[usb_descriptors];
+ }
+
+ /*
+ * check to make sure there's at least 0x12 (size of a USB
+ * device descriptor) available
+ */
+ if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0)
+ return NULL;
+
+ product_len = image->data[usb_descriptors] - 2;
+
+ if (usb_descriptors < product_len + 2)
+ return NULL;
+
+ product = malloc (product_len + 2);
+ if (!product)
+ return NULL;
+
+ memcpy(product, image->data + usb_descriptors + 2, product_len);
+ product[product_len/2] = 0;
+ return product;
+}