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