adding old command-line-tool
[labortage2013badge.git] / hostware / commandline / opendevice.c
1 /* Name: opendevice.c
2  * Project: AVR-USB host-side library
3  * Author: Christian Starkjohann
4  * Creation Date: 2008-04-10
5  * Tabsize: 4
6  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
7  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
8  * This Revision: $Id: opendevice.c 692 2008-11-07 15:07:40Z cs $
9  */
10
11 /*
12 General Description:
13 The functions in this module can be used to find and open a device based on
14 libusb or libusb-win32.
15 */
16
17 #include <stdio.h>
18 #include "opendevice.h"
19
20 /* ------------------------------------------------------------------------- */
21
22 #define MATCH_SUCCESS                   1
23 #define MATCH_FAILED                    0
24 #define MATCH_ABORT                             -1
25
26 /* private interface: match text and p, return MATCH_SUCCESS, MATCH_FAILED, or MATCH_ABORT. */
27 static int  _shellStyleMatch(char *text, char *p)
28 {
29 int last, matched, reverse;
30
31     for(; *p; text++, p++){
32         if(*text == 0 && *p != '*')
33             return MATCH_ABORT;
34         switch(*p){
35         case '\\':
36             /* Literal match with following character. */
37             p++;
38             /* FALLTHROUGH */
39         default:
40             if(*text != *p)
41                 return MATCH_FAILED;
42             continue;
43         case '?':
44             /* Match anything. */
45             continue;
46         case '*':
47             while(*++p == '*')
48                 /* Consecutive stars act just like one. */
49                 continue;
50             if(*p == 0)
51                 /* Trailing star matches everything. */
52                 return MATCH_SUCCESS;
53             while(*text)
54                 if((matched = _shellStyleMatch(text++, p)) != MATCH_FAILED)
55                     return matched;
56             return MATCH_ABORT;
57         case '[':
58             reverse = p[1] == '^';
59             if(reverse) /* Inverted character class. */
60                 p++;
61             matched = MATCH_FAILED;
62             if(p[1] == ']' || p[1] == '-')
63                 if(*++p == *text)
64                     matched = MATCH_SUCCESS;
65             for(last = *p; *++p && *p != ']'; last = *p)
66                 if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p)
67                     matched = MATCH_SUCCESS;
68             if(matched == reverse)
69                 return MATCH_FAILED;
70             continue;
71         }
72     }
73     return *text == 0;
74 }
75
76 /* public interface for shell style matching: returns 0 if fails, 1 if matches */
77 static int shellStyleMatch(char *text, char *pattern)
78 {
79     if(pattern == NULL) /* NULL pattern is synonymous to "*" */
80         return 1;
81     return _shellStyleMatch(text, pattern) == MATCH_SUCCESS;
82 }
83
84 /* ------------------------------------------------------------------------- */
85
86 int usbGetStringAscii(usb_dev_handle *dev, int index, char *buf, int buflen)
87 {
88 char    buffer[256];
89 int     rval, i;
90
91     if((rval = usb_get_string_simple(dev, index, buf, buflen)) >= 0) /* use libusb version if it works */
92         return rval;
93     if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, 0x0409, buffer, sizeof(buffer), 5000)) < 0)
94         return rval;
95     if(buffer[1] != USB_DT_STRING){
96         *buf = 0;
97         return 0;
98     }
99     if((unsigned char)buffer[0] < rval)
100         rval = (unsigned char)buffer[0];
101     rval /= 2;
102     /* lossy conversion to ISO Latin1: */
103     for(i=1;i<rval;i++){
104         if(i > buflen)              /* destination buffer overflow */
105             break;
106         buf[i-1] = buffer[2 * i];
107         if(buffer[2 * i + 1] != 0)  /* outside of ISO Latin1 range */
108             buf[i-1] = '?';
109     }
110     buf[i-1] = 0;
111     return i-1;
112 }
113
114 /* ------------------------------------------------------------------------- */
115
116 int usbOpenDevice(usb_dev_handle **device, int vendorID, char *vendorNamePattern, int productID, char *productNamePattern, char *serialNamePattern, FILE *printMatchingDevicesFp, FILE *warningsFp)
117 {
118 struct usb_bus      *bus;
119 struct usb_device   *dev;
120 usb_dev_handle      *handle = NULL;
121 int                 errorCode = USBOPEN_ERR_NOTFOUND;
122
123     usb_find_busses();
124     usb_find_devices();
125     for(bus = usb_get_busses(); bus; bus = bus->next){
126         for(dev = bus->devices; dev; dev = dev->next){  /* iterate over all devices on all busses */
127             if((vendorID == 0 || dev->descriptor.idVendor == vendorID)
128                         && (productID == 0 || dev->descriptor.idProduct == productID)){
129                 char    vendor[256], product[256], serial[256];
130                 int     len;
131                 handle = usb_open(dev); /* we need to open the device in order to query strings */
132                 if(!handle){
133                     errorCode = USBOPEN_ERR_ACCESS;
134                     if(warningsFp != NULL)
135                         fprintf(warningsFp, "Warning: cannot open VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
136                     continue;
137                 }
138                 /* now check whether the names match: */
139                 len = vendor[0] = 0;
140                 if(dev->descriptor.iManufacturer > 0){
141                     len = usbGetStringAscii(handle, dev->descriptor.iManufacturer, vendor, sizeof(vendor));
142                 }
143                 if(len < 0){
144                     errorCode = USBOPEN_ERR_ACCESS;
145                     if(warningsFp != NULL)
146                         fprintf(warningsFp, "Warning: cannot query manufacturer for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
147                 }else{
148                     errorCode = USBOPEN_ERR_NOTFOUND;
149                     /* printf("seen device from vendor ->%s<-\n", vendor); */
150                     if(shellStyleMatch(vendor, vendorNamePattern)){
151                         len = product[0] = 0;
152                         if(dev->descriptor.iProduct > 0){
153                             len = usbGetStringAscii(handle, dev->descriptor.iProduct, product, sizeof(product));
154                         }
155                         if(len < 0){
156                             errorCode = USBOPEN_ERR_ACCESS;
157                             if(warningsFp != NULL)
158                                 fprintf(warningsFp, "Warning: cannot query product for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
159                         }else{
160                             errorCode = USBOPEN_ERR_NOTFOUND;
161                             /* printf("seen product ->%s<-\n", product); */
162                             if(shellStyleMatch(product, productNamePattern)){
163                                 len = serial[0] = 0;
164                                 if(dev->descriptor.iSerialNumber > 0){
165                                     len = usbGetStringAscii(handle, dev->descriptor.iSerialNumber, serial, sizeof(serial));
166                                 }
167                                 if(len < 0){
168                                     errorCode = USBOPEN_ERR_ACCESS;
169                                     if(warningsFp != NULL)
170                                         fprintf(warningsFp, "Warning: cannot query serial for VID=0x%04x PID=0x%04x: %s\n", dev->descriptor.idVendor, dev->descriptor.idProduct, usb_strerror());
171                                 }
172                                 if(shellStyleMatch(serial, serialNamePattern)){
173                                     if(printMatchingDevicesFp != NULL){
174                                         if(serial[0] == 0){
175                                             fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product);
176                                         }else{
177                                             fprintf(printMatchingDevicesFp, "VID=0x%04x PID=0x%04x vendor=\"%s\" product=\"%s\" serial=\"%s\"\n", dev->descriptor.idVendor, dev->descriptor.idProduct, vendor, product, serial);
178                                         }
179                                     }else{
180                                         break;
181                                     }
182                                 }
183                             }
184                         }
185                     }
186                 }
187                 usb_close(handle);
188                 handle = NULL;
189             }
190         }
191         if(handle)  /* we have found a deice */
192             break;
193     }
194     if(handle != NULL){
195         errorCode = 0;
196         *device = handle;
197     }
198     if(printMatchingDevicesFp != NULL)  /* never return an error for listing only */
199         errorCode = 0;
200     return errorCode;
201 }
202
203 /* ------------------------------------------------------------------------- */