1 /*
2 usb.c - USB support
3 
4 Copyright (c) 2003       Ulrich Hecht <uli@emulinks.de>
5 Copyright (c) 2004       NoisyB
6 Copyright (c) 2015, 2018 dbjh
7 
8 
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23 #ifdef  HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #ifdef  USE_USB
27 #ifdef  _MSC_VER
28 #pragma warning(push)
29 #pragma warning(disable: 4668) // 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
30 #endif
31 #include <stdio.h>
32 #ifdef  _MSC_VER
33 #pragma warning(pop)
34 #endif
35 #include <string.h>
36 #include "misc/usb.h"
37 
38 
39 static int
usb_get_string_ascii(usb_dev_handle * dev,int index,char * buf,int buflen)40 usb_get_string_ascii (usb_dev_handle *dev, int index, char *buf, int buflen)
41 {
42   char buffer[256];
43   int rval, i;
44 
45   if ((rval = usb_get_string_simple (dev, index, buf, buflen)) >= 0)
46     return rval;
47   if ((rval = usb_control_msg (dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
48                                (USB_DT_STRING << 8) + index, 0x0409, buffer,
49                                sizeof buffer, 5000)) < 0)
50     return rval;
51   if (buffer[1] != USB_DT_STRING)
52     {
53       *buf = '\0';
54       return 0;
55     }
56   if ((unsigned char) buffer[0] < rval)
57     rval = (unsigned char) buffer[0];
58   rval /= 2;
59   // lossy conversion to ISO Latin1
60   for (i = 1; i < rval; i++)
61     {
62       if (i > buflen)                           // destination buffer overflow
63         break;
64       buf[i - 1] = buffer[2 * i];
65       if (buffer[2 * i + 1] != '\0')            // outside of ISO Latin1 range
66         buf[i - 1] = '?';
67     }
68   buf[i - 1] = '\0';
69   return i - 1;
70 }
71 
72 
73 int
usbport_open(usb_dev_handle ** result_handle,int vendor_id,char * vendor_name,int product_id,char * product_name)74 usbport_open (usb_dev_handle **result_handle, int vendor_id, char *vendor_name,
75               int product_id, char *product_name)
76 {
77   struct usb_bus *bus;
78   struct usb_device *dev;
79   usb_dev_handle *handle = NULL;
80   int error_code = USBOPEN_ERR_NOTFOUND;
81 
82   usb_find_busses ();
83   usb_find_devices ();
84   for (bus = usb_get_busses (); bus; bus = bus->next)
85     {
86       for (dev = bus->devices; dev; dev = dev->next)
87         if ((vendor_id == 0 || dev->descriptor.idVendor == vendor_id) &&
88             (product_id == 0 || dev->descriptor.idProduct == product_id))
89           {
90             char vendor[256];
91             int len = 0;
92 
93             handle = usb_open (dev);
94             if (!handle)
95               {
96                 error_code = USBOPEN_ERR_ACCESS;
97                 continue;
98               }
99             vendor[0] = '\0';
100             if (dev->descriptor.iManufacturer > 0)
101               len = usb_get_string_ascii (handle, dev->descriptor.iManufacturer,
102                                           vendor, sizeof vendor);
103             if (len < 0)
104               error_code = USBOPEN_ERR_ACCESS;
105             else
106               {
107                 error_code = USBOPEN_ERR_NOTFOUND;
108                 if (strcmp (vendor, vendor_name) == 0)
109                   {
110                     char product[256];
111 
112                     product[0] = '\0';
113                     if (dev->descriptor.iProduct > 0)
114                       len = usb_get_string_ascii (handle, dev->descriptor.iProduct,
115                                                   product, sizeof product);
116                     if (len < 0)
117                       error_code = USBOPEN_ERR_ACCESS;
118                     else
119                       {
120                         error_code = USBOPEN_ERR_NOTFOUND;
121                         if (strcmp (product, product_name) == 0)
122                           {
123                             char serial[256];
124 
125                             serial[0] = '\0';
126                             if (dev->descriptor.iSerialNumber > 0)
127                               len = usb_get_string_ascii (handle,
128                                                           dev->descriptor.iSerialNumber,
129                                                           serial, sizeof serial);
130                             if (len < 0)
131                               error_code = USBOPEN_ERR_ACCESS;
132                             else
133                               break;
134                           }
135                       }
136                   }
137               }
138             usb_close (handle);
139             handle = NULL;
140           }
141       if (handle)                               // we have found a device
142         break;
143     }
144   if (handle)
145     {
146       error_code = USBOPEN_SUCCESS;
147       *result_handle = handle;
148     }
149   return error_code;
150 }
151 
152 
153 struct usb_device *
usbport_probe(int vendor_id,int product_id)154 usbport_probe (int vendor_id, int product_id)
155 {
156   struct usb_bus *bus;
157   struct usb_device *dev;
158 
159   usb_init ();
160   usb_find_busses ();
161   usb_find_devices ();
162 
163   for (bus = usb_busses; bus; bus = bus->next)  // usb_busses is present in libusb
164     for (dev = bus->devices; dev; dev = dev->next)
165       if ((dev->descriptor.idVendor == vendor_id) &&
166           (dev->descriptor.idProduct == product_id))
167         return dev;
168 
169   return NULL;
170 }
171 
172 
173 int
usbport_read(usb_dev_handle * handle,int endpoint,char * buffer,int buffer_size,int timeout)174 usbport_read (usb_dev_handle *handle, int endpoint, char *buffer,
175               int buffer_size, int timeout)
176 {
177   int result = usb_bulk_read (handle, endpoint, buffer, buffer_size, timeout);
178 
179   if (result < 0)
180     fprintf (stderr, "\n"
181                      "ERROR: Could not read requested number of bytes from USB\n"
182                      "       %s\n", usb_strerror ());
183   return result;
184 }
185 
186 
187 int
usbport_write(usb_dev_handle * handle,int endpoint,char * buffer,int buffer_size,int timeout)188 usbport_write (usb_dev_handle *handle, int endpoint, char *buffer,
189                int buffer_size, int timeout)
190 {
191   int result = usb_bulk_write (handle, endpoint, buffer, buffer_size, timeout);
192 
193   if (result < 0)
194     fprintf (stderr, "\n"
195                      "ERROR: Could not write requested number of bytes to USB\n"
196                      "       %s\n", usb_strerror ());
197   return result;
198 }
199 
200 #endif // USE_USB
201