License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[sfrench/cifs-2.6.git] / tools / usb / usbip / libsrc / usbip_common.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2005-2007 Takahiro Hirofuchi
4  */
5
6 #include <libudev.h>
7 #include "usbip_common.h"
8 #include "names.h"
9
10 #undef  PROGNAME
11 #define PROGNAME "libusbip"
12
13 int usbip_use_syslog;
14 int usbip_use_stderr;
15 int usbip_use_debug;
16
17 extern struct udev *udev_context;
18
19 struct speed_string {
20         int num;
21         char *speed;
22         char *desc;
23 };
24
25 static const struct speed_string speed_strings[] = {
26         { USB_SPEED_UNKNOWN, "unknown", "Unknown Speed"},
27         { USB_SPEED_LOW,  "1.5", "Low Speed(1.5Mbps)"  },
28         { USB_SPEED_FULL, "12",  "Full Speed(12Mbps)" },
29         { USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
30         { USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
31         { USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
32         { 0, NULL, NULL }
33 };
34
35 struct portst_string {
36         int num;
37         char *desc;
38 };
39
40 static struct portst_string portst_strings[] = {
41         { SDEV_ST_AVAILABLE,    "Device Available" },
42         { SDEV_ST_USED,         "Device in Use" },
43         { SDEV_ST_ERROR,        "Device Error"},
44         { VDEV_ST_NULL,         "Port Available"},
45         { VDEV_ST_NOTASSIGNED,  "Port Initializing"},
46         { VDEV_ST_USED,         "Port in Use"},
47         { VDEV_ST_ERROR,        "Port Error"},
48         { 0, NULL}
49 };
50
51 const char *usbip_status_string(int32_t status)
52 {
53         for (int i = 0; portst_strings[i].desc != NULL; i++)
54                 if (portst_strings[i].num == status)
55                         return portst_strings[i].desc;
56
57         return "Unknown Status";
58 }
59
60 const char *usbip_speed_string(int num)
61 {
62         for (int i = 0; speed_strings[i].speed != NULL; i++)
63                 if (speed_strings[i].num == num)
64                         return speed_strings[i].desc;
65
66         return "Unknown Speed";
67 }
68
69
70 #define DBG_UDEV_INTEGER(name)\
71         dbg("%-20s = %x", to_string(name), (int) udev->name)
72
73 #define DBG_UINF_INTEGER(name)\
74         dbg("%-20s = %x", to_string(name), (int) uinf->name)
75
76 void dump_usb_interface(struct usbip_usb_interface *uinf)
77 {
78         char buff[100];
79
80         usbip_names_get_class(buff, sizeof(buff),
81                         uinf->bInterfaceClass,
82                         uinf->bInterfaceSubClass,
83                         uinf->bInterfaceProtocol);
84         dbg("%-20s = %s", "Interface(C/SC/P)", buff);
85 }
86
87 void dump_usb_device(struct usbip_usb_device *udev)
88 {
89         char buff[100];
90
91         dbg("%-20s = %s", "path",  udev->path);
92         dbg("%-20s = %s", "busid", udev->busid);
93
94         usbip_names_get_class(buff, sizeof(buff),
95                         udev->bDeviceClass,
96                         udev->bDeviceSubClass,
97                         udev->bDeviceProtocol);
98         dbg("%-20s = %s", "Device(C/SC/P)", buff);
99
100         DBG_UDEV_INTEGER(bcdDevice);
101
102         usbip_names_get_product(buff, sizeof(buff),
103                         udev->idVendor,
104                         udev->idProduct);
105         dbg("%-20s = %s", "Vendor/Product", buff);
106
107         DBG_UDEV_INTEGER(bNumConfigurations);
108         DBG_UDEV_INTEGER(bNumInterfaces);
109
110         dbg("%-20s = %s", "speed",
111                         usbip_speed_string(udev->speed));
112
113         DBG_UDEV_INTEGER(busnum);
114         DBG_UDEV_INTEGER(devnum);
115 }
116
117
118 int read_attr_value(struct udev_device *dev, const char *name,
119                     const char *format)
120 {
121         const char *attr;
122         int num = 0;
123         int ret;
124
125         attr = udev_device_get_sysattr_value(dev, name);
126         if (!attr) {
127                 err("udev_device_get_sysattr_value failed");
128                 goto err;
129         }
130
131         /* The client chooses the device configuration
132          * when attaching it so right after being bound
133          * to usbip-host on the server the device will
134          * have no configuration.
135          * Therefore, attributes such as bConfigurationValue
136          * and bNumInterfaces will not exist and sscanf will
137          * fail. Check for these cases and don't treat them
138          * as errors.
139          */
140
141         ret = sscanf(attr, format, &num);
142         if (ret < 1) {
143                 if (strcmp(name, "bConfigurationValue") &&
144                                 strcmp(name, "bNumInterfaces")) {
145                         err("sscanf failed for attribute %s", name);
146                         goto err;
147                 }
148         }
149
150 err:
151
152         return num;
153 }
154
155
156 int read_attr_speed(struct udev_device *dev)
157 {
158         const char *speed;
159
160         speed = udev_device_get_sysattr_value(dev, "speed");
161         if (!speed) {
162                 err("udev_device_get_sysattr_value failed");
163                 goto err;
164         }
165
166         for (int i = 0; speed_strings[i].speed != NULL; i++) {
167                 if (!strcmp(speed, speed_strings[i].speed))
168                         return speed_strings[i].num;
169         }
170
171 err:
172
173         return USB_SPEED_UNKNOWN;
174 }
175
176 #define READ_ATTR(object, type, dev, name, format)                            \
177         do {                                                                  \
178                 (object)->name = (type) read_attr_value(dev, to_string(name), \
179                                                         format);              \
180         } while (0)
181
182
183 int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev)
184 {
185         uint32_t busnum, devnum;
186         const char *path, *name;
187
188         READ_ATTR(udev, uint8_t,  sdev, bDeviceClass,           "%02x\n");
189         READ_ATTR(udev, uint8_t,  sdev, bDeviceSubClass,        "%02x\n");
190         READ_ATTR(udev, uint8_t,  sdev, bDeviceProtocol,        "%02x\n");
191
192         READ_ATTR(udev, uint16_t, sdev, idVendor,               "%04x\n");
193         READ_ATTR(udev, uint16_t, sdev, idProduct,              "%04x\n");
194         READ_ATTR(udev, uint16_t, sdev, bcdDevice,              "%04x\n");
195
196         READ_ATTR(udev, uint8_t,  sdev, bConfigurationValue,    "%02x\n");
197         READ_ATTR(udev, uint8_t,  sdev, bNumConfigurations,     "%02x\n");
198         READ_ATTR(udev, uint8_t,  sdev, bNumInterfaces,         "%02x\n");
199
200         READ_ATTR(udev, uint8_t,  sdev, devnum,                 "%d\n");
201         udev->speed = read_attr_speed(sdev);
202
203         path = udev_device_get_syspath(sdev);
204         name = udev_device_get_sysname(sdev);
205
206         strncpy(udev->path,  path,  SYSFS_PATH_MAX);
207         strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE);
208
209         sscanf(name, "%u-%u", &busnum, &devnum);
210         udev->busnum = busnum;
211
212         return 0;
213 }
214
215 int read_usb_interface(struct usbip_usb_device *udev, int i,
216                        struct usbip_usb_interface *uinf)
217 {
218         char busid[SYSFS_BUS_ID_SIZE];
219         int size;
220         struct udev_device *sif;
221
222         size = snprintf(busid, sizeof(busid), "%s:%d.%d",
223                         udev->busid, udev->bConfigurationValue, i);
224         if (size < 0 || (unsigned int)size >= sizeof(busid)) {
225                 err("busid length %i >= %lu or < 0", size,
226                     (long unsigned)sizeof(busid));
227                 return -1;
228         }
229
230         sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
231         if (!sif) {
232                 err("udev_device_new_from_subsystem_sysname %s failed", busid);
233                 return -1;
234         }
235
236         READ_ATTR(uinf, uint8_t,  sif, bInterfaceClass,         "%02x\n");
237         READ_ATTR(uinf, uint8_t,  sif, bInterfaceSubClass,      "%02x\n");
238         READ_ATTR(uinf, uint8_t,  sif, bInterfaceProtocol,      "%02x\n");
239
240         return 0;
241 }
242
243 int usbip_names_init(char *f)
244 {
245         return names_init(f);
246 }
247
248 void usbip_names_free(void)
249 {
250         names_free();
251 }
252
253 void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
254                              uint16_t product)
255 {
256         const char *prod, *vend;
257
258         prod = names_product(vendor, product);
259         if (!prod)
260                 prod = "unknown product";
261
262
263         vend = names_vendor(vendor);
264         if (!vend)
265                 vend = "unknown vendor";
266
267         snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
268 }
269
270 void usbip_names_get_class(char *buff, size_t size, uint8_t class,
271                            uint8_t subclass, uint8_t protocol)
272 {
273         const char *c, *s, *p;
274
275         if (class == 0 && subclass == 0 && protocol == 0) {
276                 snprintf(buff, size, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass, protocol);
277                 return;
278         }
279
280         p = names_protocol(class, subclass, protocol);
281         if (!p)
282                 p = "unknown protocol";
283
284         s = names_subclass(class, subclass);
285         if (!s)
286                 s = "unknown subclass";
287
288         c = names_class(class);
289         if (!c)
290                 c = "unknown class";
291
292         snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
293 }