1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
7 #include "usbip_common.h"
11 #define PROGNAME "libusbip"
17 extern struct udev
*udev_context
;
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)" },
35 struct portst_string
{
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"},
51 const char *usbip_status_string(int32_t status
)
53 for (int i
= 0; portst_strings
[i
].desc
!= NULL
; i
++)
54 if (portst_strings
[i
].num
== status
)
55 return portst_strings
[i
].desc
;
57 return "Unknown Status";
60 const char *usbip_speed_string(int num
)
62 for (int i
= 0; speed_strings
[i
].speed
!= NULL
; i
++)
63 if (speed_strings
[i
].num
== num
)
64 return speed_strings
[i
].desc
;
66 return "Unknown Speed";
69 struct op_common_status_string
{
74 static struct op_common_status_string op_common_status_strings
[] = {
75 { ST_OK
, "Request Completed Successfully" },
76 { ST_NA
, "Request Failed" },
77 { ST_DEV_BUSY
, "Device busy (exported)" },
78 { ST_DEV_ERR
, "Device in error state" },
79 { ST_NODEV
, "Device not found" },
80 { ST_ERROR
, "Unexpected response" },
84 const char *usbip_op_common_status_string(int status
)
86 for (int i
= 0; op_common_status_strings
[i
].desc
!= NULL
; i
++)
87 if (op_common_status_strings
[i
].num
== status
)
88 return op_common_status_strings
[i
].desc
;
90 return "Unknown Op Common Status";
93 #define DBG_UDEV_INTEGER(name)\
94 dbg("%-20s = %x", to_string(name), (int) udev->name)
96 #define DBG_UINF_INTEGER(name)\
97 dbg("%-20s = %x", to_string(name), (int) uinf->name)
99 void dump_usb_interface(struct usbip_usb_interface
*uinf
)
103 usbip_names_get_class(buff
, sizeof(buff
),
104 uinf
->bInterfaceClass
,
105 uinf
->bInterfaceSubClass
,
106 uinf
->bInterfaceProtocol
);
107 dbg("%-20s = %s", "Interface(C/SC/P)", buff
);
110 void dump_usb_device(struct usbip_usb_device
*udev
)
114 dbg("%-20s = %s", "path", udev
->path
);
115 dbg("%-20s = %s", "busid", udev
->busid
);
117 usbip_names_get_class(buff
, sizeof(buff
),
119 udev
->bDeviceSubClass
,
120 udev
->bDeviceProtocol
);
121 dbg("%-20s = %s", "Device(C/SC/P)", buff
);
123 DBG_UDEV_INTEGER(bcdDevice
);
125 usbip_names_get_product(buff
, sizeof(buff
),
128 dbg("%-20s = %s", "Vendor/Product", buff
);
130 DBG_UDEV_INTEGER(bNumConfigurations
);
131 DBG_UDEV_INTEGER(bNumInterfaces
);
133 dbg("%-20s = %s", "speed",
134 usbip_speed_string(udev
->speed
));
136 DBG_UDEV_INTEGER(busnum
);
137 DBG_UDEV_INTEGER(devnum
);
141 int read_attr_value(struct udev_device
*dev
, const char *name
,
148 attr
= udev_device_get_sysattr_value(dev
, name
);
150 err("udev_device_get_sysattr_value failed");
154 /* The client chooses the device configuration
155 * when attaching it so right after being bound
156 * to usbip-host on the server the device will
157 * have no configuration.
158 * Therefore, attributes such as bConfigurationValue
159 * and bNumInterfaces will not exist and sscanf will
160 * fail. Check for these cases and don't treat them
164 ret
= sscanf(attr
, format
, &num
);
166 if (strcmp(name
, "bConfigurationValue") &&
167 strcmp(name
, "bNumInterfaces")) {
168 err("sscanf failed for attribute %s", name
);
179 int read_attr_speed(struct udev_device
*dev
)
183 speed
= udev_device_get_sysattr_value(dev
, "speed");
185 err("udev_device_get_sysattr_value failed");
189 for (int i
= 0; speed_strings
[i
].speed
!= NULL
; i
++) {
190 if (!strcmp(speed
, speed_strings
[i
].speed
))
191 return speed_strings
[i
].num
;
196 return USB_SPEED_UNKNOWN
;
199 #define READ_ATTR(object, type, dev, name, format) \
201 (object)->name = (type) read_attr_value(dev, to_string(name), \
206 int read_usb_device(struct udev_device
*sdev
, struct usbip_usb_device
*udev
)
208 uint32_t busnum
, devnum
;
209 const char *path
, *name
;
211 READ_ATTR(udev
, uint8_t, sdev
, bDeviceClass
, "%02x\n");
212 READ_ATTR(udev
, uint8_t, sdev
, bDeviceSubClass
, "%02x\n");
213 READ_ATTR(udev
, uint8_t, sdev
, bDeviceProtocol
, "%02x\n");
215 READ_ATTR(udev
, uint16_t, sdev
, idVendor
, "%04x\n");
216 READ_ATTR(udev
, uint16_t, sdev
, idProduct
, "%04x\n");
217 READ_ATTR(udev
, uint16_t, sdev
, bcdDevice
, "%04x\n");
219 READ_ATTR(udev
, uint8_t, sdev
, bConfigurationValue
, "%02x\n");
220 READ_ATTR(udev
, uint8_t, sdev
, bNumConfigurations
, "%02x\n");
221 READ_ATTR(udev
, uint8_t, sdev
, bNumInterfaces
, "%02x\n");
223 READ_ATTR(udev
, uint8_t, sdev
, devnum
, "%d\n");
224 udev
->speed
= read_attr_speed(sdev
);
226 path
= udev_device_get_syspath(sdev
);
227 name
= udev_device_get_sysname(sdev
);
229 strncpy(udev
->path
, path
, SYSFS_PATH_MAX
- 1);
230 udev
->path
[SYSFS_PATH_MAX
- 1] = '\0';
231 strncpy(udev
->busid
, name
, SYSFS_BUS_ID_SIZE
- 1);
232 udev
->busid
[SYSFS_BUS_ID_SIZE
- 1] = '\0';
234 sscanf(name
, "%u-%u", &busnum
, &devnum
);
235 udev
->busnum
= busnum
;
240 int read_usb_interface(struct usbip_usb_device
*udev
, int i
,
241 struct usbip_usb_interface
*uinf
)
243 char busid
[SYSFS_BUS_ID_SIZE
];
245 struct udev_device
*sif
;
247 size
= snprintf(busid
, sizeof(busid
), "%s:%d.%d",
248 udev
->busid
, udev
->bConfigurationValue
, i
);
249 if (size
< 0 || (unsigned int)size
>= sizeof(busid
)) {
250 err("busid length %i >= %lu or < 0", size
,
251 (long unsigned)sizeof(busid
));
255 sif
= udev_device_new_from_subsystem_sysname(udev_context
, "usb", busid
);
257 err("udev_device_new_from_subsystem_sysname %s failed", busid
);
261 READ_ATTR(uinf
, uint8_t, sif
, bInterfaceClass
, "%02x\n");
262 READ_ATTR(uinf
, uint8_t, sif
, bInterfaceSubClass
, "%02x\n");
263 READ_ATTR(uinf
, uint8_t, sif
, bInterfaceProtocol
, "%02x\n");
268 int usbip_names_init(char *f
)
270 return names_init(f
);
273 void usbip_names_free(void)
278 void usbip_names_get_product(char *buff
, size_t size
, uint16_t vendor
,
281 const char *prod
, *vend
;
283 prod
= names_product(vendor
, product
);
285 prod
= "unknown product";
288 vend
= names_vendor(vendor
);
290 vend
= "unknown vendor";
292 snprintf(buff
, size
, "%s : %s (%04x:%04x)", vend
, prod
, vendor
, product
);
295 void usbip_names_get_class(char *buff
, size_t size
, uint8_t class,
296 uint8_t subclass
, uint8_t protocol
)
298 const char *c
, *s
, *p
;
300 if (class == 0 && subclass
== 0 && protocol
== 0) {
301 snprintf(buff
, size
, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass
, protocol
);
305 p
= names_protocol(class, subclass
, protocol
);
307 p
= "unknown protocol";
309 s
= names_subclass(class, subclass
);
311 s
= "unknown subclass";
313 c
= names_class(class);
317 snprintf(buff
, size
, "%s / %s / %s (%02x/%02x/%02x)", c
, s
, p
, class, subclass
, protocol
);