| 9 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 1 /* | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 2  * In this module we implement the function that locates a USB device | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 3  * by matchspec structure: looking for specific VID/PID, possibly qualified | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 4  * by strings and/or index. | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 5  */ | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 6 | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 7 #include <stdio.h> | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 8 #include <stdlib.h> | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 9 #include <string.h> | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 10 #include <strings.h> | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 11 #include <usb.h> | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 12 #include "find_dev.h" | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 13 #include "prelim_init.h" | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 14 | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 15 static void | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 16 get_string(usb_dev_handle *usbh, int index, char *buf, size_t buflen) | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 17 { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 18 	int rc; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 19 | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 20 	rc = usb_get_string_simple(usbh, index, buf, buflen); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 21 	if (rc <= 0) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 22 		fprintf(stderr, "error: USB string retrieval failed\n"); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 23 		exit(1); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 24 	} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 25 } | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 26 | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 27 static int | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 28 is_match(struct usb_device *dev, const struct usbdev_matchspec *match) | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 29 { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 30 	struct usb_device_descriptor *desc = &dev->descriptor; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 31 	usb_dev_handle *usbh; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 32 	char strbuf[1024]; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 33 | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 34 	if (desc->idVendor != match->usb_vid) | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 35 		return 0; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 36 	if (desc->idProduct != match->usb_pid) | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 37 		return 0; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 38 	if (match->manuf_string || match->product_string || match->serial) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 39 		usbh = usb_open(dev); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 40 		if (!usbh) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 41 			fprintf(stderr, "error: usb_open() failed\n"); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 42 			exit(1); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 43 		} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 44 		if (match->manuf_string) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 45 			get_string(usbh, desc->iManufacturer, | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 46 				   strbuf, sizeof strbuf); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 47 			if (strncmp(match->manuf_string, | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 48 				    strbuf, sizeof strbuf)) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 49 				usb_close(usbh); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 50 				return 0; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 51 			} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 52 		} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 53 		if (match->product_string) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 54 			get_string(usbh, desc->iProduct, strbuf, sizeof strbuf); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 55 			if (strncmp(match->product_string, | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 56 				    strbuf, sizeof strbuf)) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 57 				usb_close(usbh); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 58 				return 0; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 59 			} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 60 		} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 61 		if (match->serial) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 62 			get_string(usbh, desc->iSerialNumber, | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 63 				   strbuf, sizeof strbuf); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 64 			if (strncmp(match->serial, strbuf, sizeof strbuf)) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 65 				usb_close(usbh); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 66 				return 0; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 67 			} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 68 		} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 69 		usb_close(usbh); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 70 	} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 71 	return 1; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 72 } | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 73 | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 74 struct usb_device * | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 75 find_usbdev_by_matchspec(const struct usbdev_matchspec *match) | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 76 { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 77 	struct usb_bus *bus; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 78 	struct usb_device *dev; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 79 	unsigned index = match->index; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 80 | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 81 	libusb_prelim_init(); | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 82 	for (bus = usb_get_busses(); bus; bus = bus->next) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 83 		for (dev = bus->devices; dev; dev = dev->next) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 84 			if (is_match(dev, match)) { | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 85 				if (!index) | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 86 					return dev; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 87 				index--; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 88 			} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 89 		} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 90 	} | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 91 	return 0; | 
| 
Mychaela Falconia <falcon@freecalypso.org> parents: diff
changeset | 92 } |