1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2588b48caSValentina Manea /*
3588b48caSValentina Manea * Copyright (C) 2005-2007 Takahiro Hirofuchi
4588b48caSValentina Manea */
5588b48caSValentina Manea
6588b48caSValentina Manea #include <libudev.h>
7588b48caSValentina Manea #include "usbip_common.h"
8588b48caSValentina Manea #include "names.h"
9588b48caSValentina Manea
10588b48caSValentina Manea #undef PROGNAME
11588b48caSValentina Manea #define PROGNAME "libusbip"
12588b48caSValentina Manea
13588b48caSValentina Manea int usbip_use_syslog;
14588b48caSValentina Manea int usbip_use_stderr;
15588b48caSValentina Manea int usbip_use_debug;
16588b48caSValentina Manea
17588b48caSValentina Manea extern struct udev *udev_context;
18588b48caSValentina Manea
19588b48caSValentina Manea struct speed_string {
20588b48caSValentina Manea int num;
21588b48caSValentina Manea char *speed;
22588b48caSValentina Manea char *desc;
23588b48caSValentina Manea };
24588b48caSValentina Manea
25588b48caSValentina Manea static const struct speed_string speed_strings[] = {
26588b48caSValentina Manea { USB_SPEED_UNKNOWN, "unknown", "Unknown Speed"},
27588b48caSValentina Manea { USB_SPEED_LOW, "1.5", "Low Speed(1.5Mbps)" },
28588b48caSValentina Manea { USB_SPEED_FULL, "12", "Full Speed(12Mbps)" },
29588b48caSValentina Manea { USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
30588b48caSValentina Manea { USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
31588b48caSValentina Manea { USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
32588b48caSValentina Manea { 0, NULL, NULL }
33588b48caSValentina Manea };
34588b48caSValentina Manea
35588b48caSValentina Manea struct portst_string {
36588b48caSValentina Manea int num;
37588b48caSValentina Manea char *desc;
38588b48caSValentina Manea };
39588b48caSValentina Manea
40588b48caSValentina Manea static struct portst_string portst_strings[] = {
41588b48caSValentina Manea { SDEV_ST_AVAILABLE, "Device Available" },
42588b48caSValentina Manea { SDEV_ST_USED, "Device in Use" },
43588b48caSValentina Manea { SDEV_ST_ERROR, "Device Error"},
44588b48caSValentina Manea { VDEV_ST_NULL, "Port Available"},
45588b48caSValentina Manea { VDEV_ST_NOTASSIGNED, "Port Initializing"},
46588b48caSValentina Manea { VDEV_ST_USED, "Port in Use"},
47588b48caSValentina Manea { VDEV_ST_ERROR, "Port Error"},
48588b48caSValentina Manea { 0, NULL}
49588b48caSValentina Manea };
50588b48caSValentina Manea
usbip_status_string(int32_t status)51588b48caSValentina Manea const char *usbip_status_string(int32_t status)
52588b48caSValentina Manea {
53588b48caSValentina Manea for (int i = 0; portst_strings[i].desc != NULL; i++)
54588b48caSValentina Manea if (portst_strings[i].num == status)
55588b48caSValentina Manea return portst_strings[i].desc;
56588b48caSValentina Manea
57588b48caSValentina Manea return "Unknown Status";
58588b48caSValentina Manea }
59588b48caSValentina Manea
usbip_speed_string(int num)60588b48caSValentina Manea const char *usbip_speed_string(int num)
61588b48caSValentina Manea {
62588b48caSValentina Manea for (int i = 0; speed_strings[i].speed != NULL; i++)
63588b48caSValentina Manea if (speed_strings[i].num == num)
64588b48caSValentina Manea return speed_strings[i].desc;
65588b48caSValentina Manea
66588b48caSValentina Manea return "Unknown Speed";
67588b48caSValentina Manea }
68588b48caSValentina Manea
69f6bcbf2eSShuah Khan struct op_common_status_string {
70f6bcbf2eSShuah Khan int num;
71f6bcbf2eSShuah Khan char *desc;
72f6bcbf2eSShuah Khan };
73f6bcbf2eSShuah Khan
74f6bcbf2eSShuah Khan static struct op_common_status_string op_common_status_strings[] = {
75f6bcbf2eSShuah Khan { ST_OK, "Request Completed Successfully" },
76f6bcbf2eSShuah Khan { ST_NA, "Request Failed" },
77f6bcbf2eSShuah Khan { ST_DEV_BUSY, "Device busy (exported)" },
78f6bcbf2eSShuah Khan { ST_DEV_ERR, "Device in error state" },
79f6bcbf2eSShuah Khan { ST_NODEV, "Device not found" },
80f6bcbf2eSShuah Khan { ST_ERROR, "Unexpected response" },
81f6bcbf2eSShuah Khan { 0, NULL}
82f6bcbf2eSShuah Khan };
83f6bcbf2eSShuah Khan
usbip_op_common_status_string(int status)84f6bcbf2eSShuah Khan const char *usbip_op_common_status_string(int status)
85f6bcbf2eSShuah Khan {
86f6bcbf2eSShuah Khan for (int i = 0; op_common_status_strings[i].desc != NULL; i++)
87f6bcbf2eSShuah Khan if (op_common_status_strings[i].num == status)
88f6bcbf2eSShuah Khan return op_common_status_strings[i].desc;
89f6bcbf2eSShuah Khan
90f6bcbf2eSShuah Khan return "Unknown Op Common Status";
91f6bcbf2eSShuah Khan }
92588b48caSValentina Manea
93588b48caSValentina Manea #define DBG_UDEV_INTEGER(name)\
94588b48caSValentina Manea dbg("%-20s = %x", to_string(name), (int) udev->name)
95588b48caSValentina Manea
96588b48caSValentina Manea #define DBG_UINF_INTEGER(name)\
97588b48caSValentina Manea dbg("%-20s = %x", to_string(name), (int) uinf->name)
98588b48caSValentina Manea
dump_usb_interface(struct usbip_usb_interface * uinf)99588b48caSValentina Manea void dump_usb_interface(struct usbip_usb_interface *uinf)
100588b48caSValentina Manea {
101588b48caSValentina Manea char buff[100];
102588b48caSValentina Manea
103588b48caSValentina Manea usbip_names_get_class(buff, sizeof(buff),
104588b48caSValentina Manea uinf->bInterfaceClass,
105588b48caSValentina Manea uinf->bInterfaceSubClass,
106588b48caSValentina Manea uinf->bInterfaceProtocol);
107588b48caSValentina Manea dbg("%-20s = %s", "Interface(C/SC/P)", buff);
108588b48caSValentina Manea }
109588b48caSValentina Manea
dump_usb_device(struct usbip_usb_device * udev)110588b48caSValentina Manea void dump_usb_device(struct usbip_usb_device *udev)
111588b48caSValentina Manea {
112588b48caSValentina Manea char buff[100];
113588b48caSValentina Manea
114588b48caSValentina Manea dbg("%-20s = %s", "path", udev->path);
115588b48caSValentina Manea dbg("%-20s = %s", "busid", udev->busid);
116588b48caSValentina Manea
117588b48caSValentina Manea usbip_names_get_class(buff, sizeof(buff),
118588b48caSValentina Manea udev->bDeviceClass,
119588b48caSValentina Manea udev->bDeviceSubClass,
120588b48caSValentina Manea udev->bDeviceProtocol);
121588b48caSValentina Manea dbg("%-20s = %s", "Device(C/SC/P)", buff);
122588b48caSValentina Manea
123588b48caSValentina Manea DBG_UDEV_INTEGER(bcdDevice);
124588b48caSValentina Manea
125588b48caSValentina Manea usbip_names_get_product(buff, sizeof(buff),
126588b48caSValentina Manea udev->idVendor,
127588b48caSValentina Manea udev->idProduct);
128588b48caSValentina Manea dbg("%-20s = %s", "Vendor/Product", buff);
129588b48caSValentina Manea
130588b48caSValentina Manea DBG_UDEV_INTEGER(bNumConfigurations);
131588b48caSValentina Manea DBG_UDEV_INTEGER(bNumInterfaces);
132588b48caSValentina Manea
133588b48caSValentina Manea dbg("%-20s = %s", "speed",
134588b48caSValentina Manea usbip_speed_string(udev->speed));
135588b48caSValentina Manea
136588b48caSValentina Manea DBG_UDEV_INTEGER(busnum);
137588b48caSValentina Manea DBG_UDEV_INTEGER(devnum);
138588b48caSValentina Manea }
139588b48caSValentina Manea
140588b48caSValentina Manea
read_attr_value(struct udev_device * dev,const char * name,const char * format)141588b48caSValentina Manea int read_attr_value(struct udev_device *dev, const char *name,
142588b48caSValentina Manea const char *format)
143588b48caSValentina Manea {
144588b48caSValentina Manea const char *attr;
145588b48caSValentina Manea int num = 0;
146588b48caSValentina Manea int ret;
147588b48caSValentina Manea
148588b48caSValentina Manea attr = udev_device_get_sysattr_value(dev, name);
149588b48caSValentina Manea if (!attr) {
150588b48caSValentina Manea err("udev_device_get_sysattr_value failed");
151588b48caSValentina Manea goto err;
152588b48caSValentina Manea }
153588b48caSValentina Manea
154588b48caSValentina Manea /* The client chooses the device configuration
155588b48caSValentina Manea * when attaching it so right after being bound
156588b48caSValentina Manea * to usbip-host on the server the device will
157588b48caSValentina Manea * have no configuration.
158588b48caSValentina Manea * Therefore, attributes such as bConfigurationValue
159588b48caSValentina Manea * and bNumInterfaces will not exist and sscanf will
160588b48caSValentina Manea * fail. Check for these cases and don't treat them
161588b48caSValentina Manea * as errors.
162588b48caSValentina Manea */
163588b48caSValentina Manea
164588b48caSValentina Manea ret = sscanf(attr, format, &num);
165588b48caSValentina Manea if (ret < 1) {
166588b48caSValentina Manea if (strcmp(name, "bConfigurationValue") &&
167588b48caSValentina Manea strcmp(name, "bNumInterfaces")) {
168588b48caSValentina Manea err("sscanf failed for attribute %s", name);
169588b48caSValentina Manea goto err;
170588b48caSValentina Manea }
171588b48caSValentina Manea }
172588b48caSValentina Manea
173588b48caSValentina Manea err:
174588b48caSValentina Manea
175588b48caSValentina Manea return num;
176588b48caSValentina Manea }
177588b48caSValentina Manea
178588b48caSValentina Manea
read_attr_speed(struct udev_device * dev)179588b48caSValentina Manea int read_attr_speed(struct udev_device *dev)
180588b48caSValentina Manea {
181588b48caSValentina Manea const char *speed;
182588b48caSValentina Manea
183588b48caSValentina Manea speed = udev_device_get_sysattr_value(dev, "speed");
184588b48caSValentina Manea if (!speed) {
185588b48caSValentina Manea err("udev_device_get_sysattr_value failed");
186588b48caSValentina Manea goto err;
187588b48caSValentina Manea }
188588b48caSValentina Manea
189588b48caSValentina Manea for (int i = 0; speed_strings[i].speed != NULL; i++) {
190588b48caSValentina Manea if (!strcmp(speed, speed_strings[i].speed))
191588b48caSValentina Manea return speed_strings[i].num;
192588b48caSValentina Manea }
193588b48caSValentina Manea
194588b48caSValentina Manea err:
195588b48caSValentina Manea
196588b48caSValentina Manea return USB_SPEED_UNKNOWN;
197588b48caSValentina Manea }
198588b48caSValentina Manea
199588b48caSValentina Manea #define READ_ATTR(object, type, dev, name, format) \
200588b48caSValentina Manea do { \
201588b48caSValentina Manea (object)->name = (type) read_attr_value(dev, to_string(name), \
202588b48caSValentina Manea format); \
203588b48caSValentina Manea } while (0)
204588b48caSValentina Manea
205588b48caSValentina Manea
read_usb_device(struct udev_device * sdev,struct usbip_usb_device * udev)206588b48caSValentina Manea int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev)
207588b48caSValentina Manea {
208588b48caSValentina Manea uint32_t busnum, devnum;
209588b48caSValentina Manea const char *path, *name;
210588b48caSValentina Manea
211588b48caSValentina Manea READ_ATTR(udev, uint8_t, sdev, bDeviceClass, "%02x\n");
212588b48caSValentina Manea READ_ATTR(udev, uint8_t, sdev, bDeviceSubClass, "%02x\n");
213588b48caSValentina Manea READ_ATTR(udev, uint8_t, sdev, bDeviceProtocol, "%02x\n");
214588b48caSValentina Manea
215588b48caSValentina Manea READ_ATTR(udev, uint16_t, sdev, idVendor, "%04x\n");
216588b48caSValentina Manea READ_ATTR(udev, uint16_t, sdev, idProduct, "%04x\n");
217588b48caSValentina Manea READ_ATTR(udev, uint16_t, sdev, bcdDevice, "%04x\n");
218588b48caSValentina Manea
219588b48caSValentina Manea READ_ATTR(udev, uint8_t, sdev, bConfigurationValue, "%02x\n");
220588b48caSValentina Manea READ_ATTR(udev, uint8_t, sdev, bNumConfigurations, "%02x\n");
221588b48caSValentina Manea READ_ATTR(udev, uint8_t, sdev, bNumInterfaces, "%02x\n");
222588b48caSValentina Manea
223588b48caSValentina Manea READ_ATTR(udev, uint8_t, sdev, devnum, "%d\n");
224588b48caSValentina Manea udev->speed = read_attr_speed(sdev);
225588b48caSValentina Manea
226588b48caSValentina Manea path = udev_device_get_syspath(sdev);
227588b48caSValentina Manea name = udev_device_get_sysname(sdev);
228588b48caSValentina Manea
229*6389a62fSLiu, Changcheng strncpy(udev->path, path, SYSFS_PATH_MAX - 1);
230*6389a62fSLiu, Changcheng udev->path[SYSFS_PATH_MAX - 1] = '\0';
231*6389a62fSLiu, Changcheng strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE - 1);
232*6389a62fSLiu, Changcheng udev->busid[SYSFS_BUS_ID_SIZE - 1] = '\0';
233588b48caSValentina Manea
234588b48caSValentina Manea sscanf(name, "%u-%u", &busnum, &devnum);
235588b48caSValentina Manea udev->busnum = busnum;
236588b48caSValentina Manea
237588b48caSValentina Manea return 0;
238588b48caSValentina Manea }
239588b48caSValentina Manea
read_usb_interface(struct usbip_usb_device * udev,int i,struct usbip_usb_interface * uinf)240588b48caSValentina Manea int read_usb_interface(struct usbip_usb_device *udev, int i,
241588b48caSValentina Manea struct usbip_usb_interface *uinf)
242588b48caSValentina Manea {
243588b48caSValentina Manea char busid[SYSFS_BUS_ID_SIZE];
244e5dfa3f9SJonathan Dieter int size;
245588b48caSValentina Manea struct udev_device *sif;
246588b48caSValentina Manea
247e5dfa3f9SJonathan Dieter size = snprintf(busid, sizeof(busid), "%s:%d.%d",
248e5dfa3f9SJonathan Dieter udev->busid, udev->bConfigurationValue, i);
249e5dfa3f9SJonathan Dieter if (size < 0 || (unsigned int)size >= sizeof(busid)) {
250e5dfa3f9SJonathan Dieter err("busid length %i >= %lu or < 0", size,
251e5dfa3f9SJonathan Dieter (long unsigned)sizeof(busid));
252e5dfa3f9SJonathan Dieter return -1;
253e5dfa3f9SJonathan Dieter }
254588b48caSValentina Manea
255588b48caSValentina Manea sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
256588b48caSValentina Manea if (!sif) {
257588b48caSValentina Manea err("udev_device_new_from_subsystem_sysname %s failed", busid);
258588b48caSValentina Manea return -1;
259588b48caSValentina Manea }
260588b48caSValentina Manea
261588b48caSValentina Manea READ_ATTR(uinf, uint8_t, sif, bInterfaceClass, "%02x\n");
262588b48caSValentina Manea READ_ATTR(uinf, uint8_t, sif, bInterfaceSubClass, "%02x\n");
263588b48caSValentina Manea READ_ATTR(uinf, uint8_t, sif, bInterfaceProtocol, "%02x\n");
264588b48caSValentina Manea
265588b48caSValentina Manea return 0;
266588b48caSValentina Manea }
267588b48caSValentina Manea
usbip_names_init(char * f)268588b48caSValentina Manea int usbip_names_init(char *f)
269588b48caSValentina Manea {
270588b48caSValentina Manea return names_init(f);
271588b48caSValentina Manea }
272588b48caSValentina Manea
usbip_names_free(void)273588b48caSValentina Manea void usbip_names_free(void)
274588b48caSValentina Manea {
275588b48caSValentina Manea names_free();
276588b48caSValentina Manea }
277588b48caSValentina Manea
usbip_names_get_product(char * buff,size_t size,uint16_t vendor,uint16_t product)278588b48caSValentina Manea void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
279588b48caSValentina Manea uint16_t product)
280588b48caSValentina Manea {
281588b48caSValentina Manea const char *prod, *vend;
282588b48caSValentina Manea
283588b48caSValentina Manea prod = names_product(vendor, product);
284588b48caSValentina Manea if (!prod)
285588b48caSValentina Manea prod = "unknown product";
286588b48caSValentina Manea
287588b48caSValentina Manea
288588b48caSValentina Manea vend = names_vendor(vendor);
289588b48caSValentina Manea if (!vend)
290588b48caSValentina Manea vend = "unknown vendor";
291588b48caSValentina Manea
292588b48caSValentina Manea snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
293588b48caSValentina Manea }
294588b48caSValentina Manea
usbip_names_get_class(char * buff,size_t size,uint8_t class,uint8_t subclass,uint8_t protocol)295588b48caSValentina Manea void usbip_names_get_class(char *buff, size_t size, uint8_t class,
296588b48caSValentina Manea uint8_t subclass, uint8_t protocol)
297588b48caSValentina Manea {
298588b48caSValentina Manea const char *c, *s, *p;
299588b48caSValentina Manea
300588b48caSValentina Manea if (class == 0 && subclass == 0 && protocol == 0) {
301588b48caSValentina Manea snprintf(buff, size, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass, protocol);
302588b48caSValentina Manea return;
303588b48caSValentina Manea }
304588b48caSValentina Manea
305588b48caSValentina Manea p = names_protocol(class, subclass, protocol);
306588b48caSValentina Manea if (!p)
307588b48caSValentina Manea p = "unknown protocol";
308588b48caSValentina Manea
309588b48caSValentina Manea s = names_subclass(class, subclass);
310588b48caSValentina Manea if (!s)
311588b48caSValentina Manea s = "unknown subclass";
312588b48caSValentina Manea
313588b48caSValentina Manea c = names_class(class);
314588b48caSValentina Manea if (!c)
315588b48caSValentina Manea c = "unknown class";
316588b48caSValentina Manea
317588b48caSValentina Manea snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
318588b48caSValentina Manea }
319