Skip to content

Commit a2d86ad

Browse files
author
Your Name
committed
Update libusb to version 1.0
1 parent 1f77bce commit a2d86ad

File tree

6 files changed

+1161
-1062
lines changed

6 files changed

+1161
-1062
lines changed

cmake/modules/FindLIBUSB.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ IF(NOT LIBUSB_FOUND)
3232
SET(LIBUSB_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/bin/x86/")
3333
ELSE(MINGW)
3434
FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "$ENV{ProgramW6432}/libusb-win32/include" NO_SYSTEM_ENVIRONMENT_PATH)
35-
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "$ENV{ProgramW6432}/libusb-win32/lib/msvc_x64")
35+
FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0 libusb-1.0 libusb PATHS "$ENV{ProgramW6432}/libusb-win32/lib/msvc_x64")
3636
SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramW6432}/libusb-win32/bin/amd64/")
3737
ENDIF(MINGW)
3838
# Must fix up variable to avoid backslashes during packaging
@@ -41,7 +41,7 @@ IF(NOT LIBUSB_FOUND)
4141
# If not under Windows we use PkgConfig
4242
FIND_PACKAGE (PkgConfig)
4343
IF(PKG_CONFIG_FOUND)
44-
PKG_CHECK_MODULES(LIBUSB REQUIRED libusb)
44+
PKG_CHECK_MODULES(LIBUSB REQUIRED libusb-1.0)
4545
ELSE(PKG_CONFIG_FOUND)
4646
MESSAGE(FATAL_ERROR "Could not find PkgConfig")
4747
ENDIF(PKG_CONFIG_FOUND)

libnfc/buses/usbbus.c

Lines changed: 284 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* Copyright (C) 2010-2012 Romain Tartière
88
* Copyright (C) 2010-2013 Philippe Teuwen
99
* Copyright (C) 2012-2013 Ludovic Rousseau
10+
* Copyright (C) 2022 Kenspeckle
1011
* See AUTHORS file for a more comprehensive list of contributors.
1112
* Additional contributors of this file:
1213
*
@@ -24,56 +25,315 @@
2425
* along with this program. If not, see <http://www.gnu.org/licenses/>
2526
*
2627
*/
27-
28-
/**
29-
* @file usbbus.c
30-
* @brief libusb 0.1 driver wrapper
31-
*/
28+
#include <stdbool.h>
29+
#include <string.h>
30+
#include <stdlib.h>
31+
#include "usbbus.h"
32+
#include "log.h"
3233

3334
#ifdef HAVE_CONFIG_H
3435
# include "config.h"
3536
#endif // HAVE_CONFIG_H
3637

37-
#include <stdlib.h>
38-
39-
#include "usbbus.h"
40-
#include "log.h"
41-
#define LOG_CATEGORY "libnfc.buses.usbbus"
38+
#define LOG_CATEGORY "libnfc.bus.usbbus"
4239
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
4340

44-
int usb_prepare(void)
45-
{
41+
static libusb_context *ctx = NULL;
42+
43+
uint8_t get_usb_num_configs(struct libusb_device *dev);
44+
45+
int usbbus_prepare() {
4646
static bool usb_initialized = false;
47+
int res;
4748
if (!usb_initialized) {
4849

4950
#ifdef ENVVARS
5051
char *env_log_level = getenv("LIBNFC_LOG_LEVEL");
5152
// Set libusb debug only if asked explicitely:
5253
// LIBUSB_LOG_LEVEL=12288 (= NFC_LOG_PRIORITY_DEBUG * 2 ^ NFC_LOG_GROUP_LIBUSB)
53-
if (env_log_level && (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) {
54+
if (env_log_level
55+
&& (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) {
5456
setenv("USB_DEBUG", "255", 1);
5557
}
5658
#endif
5759

58-
usb_init();
60+
res = libusb_init(&ctx);
61+
if (res != 0) {
62+
log_put(LOG_GROUP,
63+
LOG_CATEGORY,
64+
NFC_LOG_PRIORITY_ERROR,
65+
"Unable to init libusb (%s)",
66+
libusb_strerror(res));
67+
return res;
68+
}
5969
usb_initialized = true;
6070
}
6171

62-
int res;
63-
// usb_find_busses will find all of the busses on the system. Returns the
64-
// number of changes since previous call to this function (total of new
65-
// busses and busses removed).
66-
if ((res = usb_find_busses()) < 0) {
67-
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB busses (%s)", _usb_strerror(res));
68-
return -1;
69-
}
7072
// usb_find_devices will find all of the devices on each bus. This should be
7173
// called after usb_find_busses. Returns the number of changes since the
7274
// previous call to this function (total of new device and devices removed).
73-
if ((res = usb_find_devices()) < 0) {
74-
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", _usb_strerror(res));
75+
libusb_device **tmp_devices;
76+
ssize_t num_devices = libusb_get_device_list(ctx, &tmp_devices);
77+
libusb_free_device_list(tmp_devices, (int) num_devices);
78+
if (num_devices <= 0) {
79+
log_put(LOG_GROUP,
80+
LOG_CATEGORY,
81+
NFC_LOG_PRIORITY_ERROR,
82+
"Unable to find USB devices (%s)",
83+
libusb_strerror((int) num_devices));
7584
return -1;
7685
}
7786
return 0;
7887
}
7988

89+
size_t usbbus_usb_scan(nfc_connstring connstrings[],
90+
const size_t connstrings_len,
91+
struct usbbus_device *nfc_usb_devices,
92+
const size_t num_nfc_usb_devices,
93+
char *usb_driver_name) {
94+
usbbus_prepare();
95+
96+
size_t device_found = 0;
97+
struct libusb_device **devices;
98+
ssize_t num_devices = libusb_get_device_list(ctx, &devices);
99+
for (size_t i = 0; i < num_devices; i++) {
100+
struct libusb_device *dev = devices[i];
101+
102+
for (size_t nfc_dev_idx = 0; nfc_dev_idx < num_nfc_usb_devices; nfc_dev_idx++) {
103+
if (nfc_usb_devices[nfc_dev_idx].vendor_id == usbbus_get_vendor_id(dev)
104+
&& nfc_usb_devices[nfc_dev_idx].product_id == usbbus_get_product_id(dev)) {
105+
106+
size_t valid_config_idx = 1;
107+
108+
// Make sure there are 2 endpoints available
109+
// with libusb-win32 we got some null pointers so be robust before looking at endpoints
110+
if (nfc_usb_devices[nfc_dev_idx].max_packet_size == 0) {
111+
112+
bool found_valid_config = false;
113+
114+
for (size_t config_idx = 0; config_idx < get_usb_num_configs(dev); i++) {
115+
struct libusb_config_descriptor *usb_config;
116+
int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
117+
118+
if (r != 0
119+
|| usb_config->interface == NULL
120+
|| usb_config->interface->altsetting == NULL
121+
|| usb_config->interface->altsetting->bNumEndpoints < 2) {
122+
// Nope, we maybe want the next one, let's try to find another
123+
libusb_free_config_descriptor(usb_config);
124+
continue;
125+
}
126+
127+
libusb_free_config_descriptor(usb_config);
128+
129+
found_valid_config = true;
130+
valid_config_idx = config_idx;
131+
break;
132+
}
133+
if (!found_valid_config) {
134+
libusb_unref_device(dev);
135+
continue;
136+
}
137+
}
138+
139+
libusb_device_handle *udev;
140+
int res = libusb_open(dev, &udev);
141+
if (res < 0 && udev == NULL) {
142+
libusb_unref_device(dev);
143+
continue;
144+
}
145+
146+
// Set configuration
147+
res = libusb_set_configuration(udev, (int) valid_config_idx);
148+
if (res < 0) {
149+
log_put(LOG_GROUP,
150+
LOG_CATEGORY,
151+
NFC_LOG_PRIORITY_ERROR,
152+
"Unable to set USB configuration (%s)",
153+
libusb_strerror(res));
154+
libusb_close(udev);
155+
libusb_unref_device(dev);
156+
// we failed to use the device
157+
continue;
158+
}
159+
160+
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Vendor-Id: %d Product-Id %d",
161+
usbbus_get_vendor_id(dev), usbbus_get_product_id(dev));
162+
libusb_close(udev);
163+
164+
uint8_t dev_address = libusb_get_device_address(dev);
165+
printf("%s:%03d:%03d",
166+
"Test",
167+
dev_address,
168+
(int) valid_config_idx);
169+
size_t size_new_str = snprintf(
170+
connstrings[device_found],
171+
sizeof(connstrings[device_found]),
172+
"%s:%03d:%03d",
173+
usb_driver_name,
174+
dev_address,
175+
(int) valid_config_idx);
176+
177+
if (size_new_str >= (int) sizeof(nfc_connstring)) {
178+
// truncation occurred, skipping that one
179+
libusb_unref_device(dev);
180+
continue;
181+
}
182+
device_found++;
183+
// Test if we reach the maximum "wanted" devices
184+
if (device_found == connstrings_len) {
185+
libusb_free_device_list(devices, 0);
186+
return device_found;
187+
}
188+
}
189+
}
190+
}
191+
libusb_free_device_list(devices, 0);
192+
return device_found;
193+
}
194+
195+
void usbbus_get_usb_endpoints(struct libusb_device *dev,
196+
uint8_t *endpoint_in,
197+
uint8_t *endpoint_out,
198+
uint16_t *max_packet_size) {
199+
200+
bool endpoint_in_set = false;
201+
bool endpoint_out_set = false;
202+
size_t num_configs = get_usb_num_configs(dev);
203+
for (size_t config_idx = 0; config_idx < num_configs; config_idx++) {
204+
struct libusb_config_descriptor *usb_config;
205+
206+
int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
207+
if (r != 0) {
208+
continue;
209+
}
210+
211+
if (!usb_config->interface) {
212+
continue;
213+
}
214+
for (size_t interface_idx = 0; interface_idx < usb_config->bNumInterfaces; interface_idx++) {
215+
struct libusb_interface interface = usb_config->interface[interface_idx];
216+
if (!interface.altsetting) {
217+
continue;
218+
}
219+
for (size_t settings_idx = 0; settings_idx < interface.num_altsetting; settings_idx++) {
220+
struct libusb_interface_descriptor settings = interface.altsetting[settings_idx];
221+
if (!settings.endpoint) {
222+
continue;
223+
}
224+
225+
// 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
226+
for (size_t endpoint_idx = 0; endpoint_idx < settings.bNumEndpoints; endpoint_idx++) {
227+
struct libusb_endpoint_descriptor endpoint = settings.endpoint[endpoint_idx];
228+
229+
// Only accept bulk transfer endpoints (ignore interrupt endpoints)
230+
if (endpoint.bmAttributes != LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK) {
231+
continue;
232+
}
233+
234+
// Copy the endpoint to a local var, makes it more readable code
235+
uint8_t endpoint_address = endpoint.bEndpointAddress;
236+
237+
// Test if we dealing with a bulk IN endpoint
238+
if ((endpoint_address & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN && !endpoint_in_set) {
239+
*endpoint_in = endpoint_address;
240+
*max_packet_size = endpoint.wMaxPacketSize;
241+
endpoint_in_set = true;
242+
}
243+
// Test if we dealing with a bulk OUT endpoint
244+
if ((endpoint_address & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT && !endpoint_out_set) {
245+
*endpoint_out = endpoint_address;
246+
*max_packet_size = endpoint.wMaxPacketSize;
247+
endpoint_out_set = true;
248+
}
249+
250+
if (endpoint_in_set && endpoint_out_set) {
251+
libusb_free_config_descriptor(usb_config);
252+
return;
253+
}
254+
}
255+
}
256+
}
257+
258+
libusb_free_config_descriptor(usb_config);
259+
}
260+
}
261+
262+
uint8_t get_usb_num_configs(struct libusb_device *dev) {
263+
struct libusb_device_descriptor descriptor;
264+
libusb_get_device_descriptor(dev, &descriptor);
265+
return descriptor.bNumConfigurations;
266+
}
267+
268+
void usbbus_get_usb_device_name(struct libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) {
269+
struct libusb_device_descriptor descriptor;
270+
libusb_get_device_descriptor(dev, &descriptor);
271+
if (descriptor.iManufacturer || descriptor.iProduct) {
272+
if (udev) {
273+
libusb_get_string_descriptor_ascii(udev, descriptor.iManufacturer & 0xff, (unsigned char *) buffer, len);
274+
if (strlen(buffer) > 0) {
275+
strncpy(buffer + strlen(buffer), " / ", 4);
276+
}
277+
libusb_get_string_descriptor_ascii(udev,
278+
descriptor.iProduct & 0xff,
279+
(unsigned char *) buffer + strlen(buffer),
280+
len - strlen(buffer));
281+
}
282+
}
283+
}
284+
285+
286+
void usbbus_get_device(uint8_t dev_address, struct libusb_device ** dev, struct libusb_device_handle ** dev_handle) {
287+
struct libusb_device ** device_list;
288+
ssize_t num_devices = libusb_get_device_list(ctx, &device_list);
289+
for (size_t i = 0; i < num_devices; i++) {
290+
if (libusb_get_device_address(device_list[i]) != dev_address) {
291+
continue;
292+
} else {
293+
*dev = device_list[i];
294+
int res = libusb_open(*dev, dev_handle);
295+
if (res != 0 || dev_handle == NULL) {
296+
log_put(LOG_GROUP,LOG_CATEGORY,NFC_LOG_PRIORITY_ERROR,
297+
"Unable to open libusb device (%s)",libusb_strerror(res));
298+
continue;
299+
}
300+
}
301+
}
302+
303+
// libusb works with a reference counter which is set to 1 for each device when calling libusb_get_device_list and increased
304+
// by libusb_open. Thus we decrease the counter by 1 for all devices and only the "real" device will survive
305+
libusb_free_device_list(device_list, num_devices);
306+
}
307+
308+
309+
void usbbus_close(struct libusb_device * dev, struct libusb_device_handle * dev_handle) {
310+
libusb_close(dev_handle);
311+
libusb_unref_device(dev);
312+
libusb_exit(ctx);
313+
}
314+
315+
uint16_t usbbus_get_vendor_id(struct libusb_device *dev) {
316+
struct libusb_device_descriptor descriptor;
317+
libusb_get_device_descriptor(dev, &descriptor);
318+
return descriptor.idVendor;
319+
}
320+
321+
uint16_t usbbus_get_product_id(struct libusb_device *dev) {
322+
struct libusb_device_descriptor descriptor;
323+
libusb_get_device_descriptor(dev, &descriptor);
324+
return descriptor.idProduct;
325+
}
326+
327+
328+
int usbbus_get_num_alternate_settings(struct libusb_device *dev, uint8_t config_idx) {
329+
struct libusb_config_descriptor *usb_config;
330+
int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
331+
if (r != 0 || usb_config == NULL) {
332+
return -1;
333+
}
334+
libusb_free_config_descriptor(usb_config);
335+
return usb_config->interface->num_altsetting;
336+
}
337+
338+
339+

0 commit comments

Comments
 (0)