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