xref: /linux/tools/usb/usbip/libsrc/usbip_common.c (revision 6389a62f)
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