1 /*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2016 secunet Security Networks AG
5 * Copyright (C) 2018 Linaro Limited
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18 #include <inttypes.h>
19 #include <stdbool.h>
20 #include <string.h>
21 #include <libusb.h>
22 #include "programmer.h"
23
24 /*
25 * Check whether we should filter the current device.
26 *
27 * The main code filters by VID/PID then calls out to the filter function for extra filtering.
28 * The filter function is called twice for each device. Once with handle == NULL to allow the
29 * filter to cull devices without opening them and, assuming the first filter does not trigger,
30 * also with a real handle to allow the filter to query the device further.
31 *
32 * Returns true if the device should be skipped.
33 */
34 typedef bool (*filter_func)(struct libusb_device_descriptor *desc, struct libusb_device_handle *handle, void*ctx);
35
get_by_vid_pid_filter(struct libusb_context * usb_ctx,uint16_t vid,uint16_t pid,filter_func filter_fn,void * filter_ctx)36 static struct libusb_device_handle *get_by_vid_pid_filter(struct libusb_context *usb_ctx,
37 uint16_t vid, uint16_t pid, filter_func filter_fn, void *filter_ctx)
38 {
39 struct libusb_device **list;
40 ssize_t count = libusb_get_device_list(usb_ctx, &list);
41 if (count < 0) {
42 msg_perr("Getting the USB device list failed (%s)!\n", libusb_error_name(count));
43 return NULL;
44 }
45
46 ssize_t i = 0;
47 for (i = 0; i < count; i++) {
48 struct libusb_device *dev = list[i];
49 struct libusb_device_descriptor desc;
50 struct libusb_device_handle *handle;
51
52 int res = libusb_get_device_descriptor(dev, &desc);
53 if (res != 0) {
54 msg_perr("Reading the USB device descriptor failed (%s)!\n", libusb_error_name(res));
55 continue;
56 }
57
58 if ((desc.idVendor != vid) || (desc.idProduct != pid))
59 continue;
60
61 msg_pdbg("Found USB device %04"PRIx16":%04"PRIx16" at address %d-%d.\n",
62 desc.idVendor, desc.idProduct,
63 libusb_get_bus_number(dev), libusb_get_device_address(dev));
64
65 /* allow filters to trigger before the device is opened */
66 if (filter_fn(&desc, NULL, filter_ctx))
67 continue;
68
69 res = libusb_open(dev, &handle);
70 if (res != 0) {
71 msg_perr("Opening the USB device at address %d-%d failed (%s)!\n",
72 libusb_get_bus_number(dev), libusb_get_device_address(dev),
73 libusb_error_name(res));
74 break;
75 }
76
77 /* filter can also trigger after a device is opened */
78 if (filter_fn(&desc, handle, filter_ctx)) {
79 libusb_close(handle);
80 continue;
81 }
82
83 libusb_free_device_list(list, 1);
84 return handle;
85 }
86
87 libusb_free_device_list(list, 1);
88 return NULL;
89
90 }
91
filter_by_serial(struct libusb_device_descriptor * desc,struct libusb_device_handle * handle,void * serialno)92 static bool filter_by_serial(struct libusb_device_descriptor *desc, struct libusb_device_handle *handle,
93 void *serialno)
94 {
95 /* Never filter if device is not yet open or when user did not provide a serial number */
96 if (!handle || !serialno)
97 return false;
98
99 unsigned char myserial[64];
100 int res = libusb_get_string_descriptor_ascii(handle, desc->iSerialNumber, myserial, sizeof(myserial));
101 if (res < 0) {
102 msg_perr("Reading the USB serialno failed (%s)!\n", libusb_error_name(res));
103 return true;
104 }
105 msg_pdbg("Serial number is %s\n", myserial);
106
107 /* Filter out any serial number that does not commence with serialno */
108 return 0 != strncmp(serialno, (char *)myserial, strlen(serialno));
109 }
110
usb_dev_get_by_vid_pid_serial(struct libusb_context * usb_ctx,uint16_t vid,uint16_t pid,const char * serialno)111 struct libusb_device_handle *usb_dev_get_by_vid_pid_serial(
112 struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, const char *serialno)
113 {
114 return get_by_vid_pid_filter(usb_ctx, vid, pid, filter_by_serial, (void *)serialno);
115 }
116
filter_by_number(struct libusb_device_descriptor * desc,struct libusb_device_handle * handle,void * ctx)117 static bool filter_by_number(struct libusb_device_descriptor *desc, struct libusb_device_handle *handle,
118 void *ctx)
119 {
120 /* This filter never triggers once it has allowed the device to be opened */
121 if (handle != NULL)
122 return false;
123
124 unsigned int *nump = ctx;
125 if (*nump) {
126 (*nump)--;
127 return true;
128 }
129
130 return false;
131 }
132
133 /*
134 * This function allows different devices to be targeted based on enumeration order. Different
135 * hotplug sequencing (or simply a reboot) may change the enumeration order. This function should
136 * only be used if a programmers does not provide an alternative way to identify itself uniquely
137 * (such as a unique serial number).
138 */
usb_dev_get_by_vid_pid_number(struct libusb_context * usb_ctx,uint16_t vid,uint16_t pid,unsigned int num)139 struct libusb_device_handle *usb_dev_get_by_vid_pid_number(
140 struct libusb_context *usb_ctx, uint16_t vid, uint16_t pid, unsigned int num)
141 {
142 return get_by_vid_pid_filter(usb_ctx, vid, pid, filter_by_number, &num);
143 }
144