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";
70 #define DBG_UDEV_INTEGER(name)\
71 dbg("%-20s = %x", to_string(name), (int) udev->name)
73 #define DBG_UINF_INTEGER(name)\
74 dbg("%-20s = %x", to_string(name), (int) uinf->name)
76 void dump_usb_interface(struct usbip_usb_interface
*uinf
)
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
);
87 void dump_usb_device(struct usbip_usb_device
*udev
)
91 dbg("%-20s = %s", "path", udev
->path
);
92 dbg("%-20s = %s", "busid", udev
->busid
);
94 usbip_names_get_class(buff
, sizeof(buff
),
96 udev
->bDeviceSubClass
,
97 udev
->bDeviceProtocol
);
98 dbg("%-20s = %s", "Device(C/SC/P)", buff
);
100 DBG_UDEV_INTEGER(bcdDevice
);
102 usbip_names_get_product(buff
, sizeof(buff
),
105 dbg("%-20s = %s", "Vendor/Product", buff
);
107 DBG_UDEV_INTEGER(bNumConfigurations
);
108 DBG_UDEV_INTEGER(bNumInterfaces
);
110 dbg("%-20s = %s", "speed",
111 usbip_speed_string(udev
->speed
));
113 DBG_UDEV_INTEGER(busnum
);
114 DBG_UDEV_INTEGER(devnum
);
118 int read_attr_value(struct udev_device
*dev
, const char *name
,
125 attr
= udev_device_get_sysattr_value(dev
, name
);
127 err("udev_device_get_sysattr_value failed");
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
141 ret
= sscanf(attr
, format
, &num
);
143 if (strcmp(name
, "bConfigurationValue") &&
144 strcmp(name
, "bNumInterfaces")) {
145 err("sscanf failed for attribute %s", name
);
156 int read_attr_speed(struct udev_device
*dev
)
160 speed
= udev_device_get_sysattr_value(dev
, "speed");
162 err("udev_device_get_sysattr_value failed");
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
;
173 return USB_SPEED_UNKNOWN
;
176 #define READ_ATTR(object, type, dev, name, format) \
178 (object)->name = (type) read_attr_value(dev, to_string(name), \
183 int read_usb_device(struct udev_device
*sdev
, struct usbip_usb_device
*udev
)
185 uint32_t busnum
, devnum
;
186 const char *path
, *name
;
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");
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");
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");
200 READ_ATTR(udev
, uint8_t, sdev
, devnum
, "%d\n");
201 udev
->speed
= read_attr_speed(sdev
);
203 path
= udev_device_get_syspath(sdev
);
204 name
= udev_device_get_sysname(sdev
);
206 strncpy(udev
->path
, path
, SYSFS_PATH_MAX
);
207 strncpy(udev
->busid
, name
, SYSFS_BUS_ID_SIZE
);
209 sscanf(name
, "%u-%u", &busnum
, &devnum
);
210 udev
->busnum
= busnum
;
215 int read_usb_interface(struct usbip_usb_device
*udev
, int i
,
216 struct usbip_usb_interface
*uinf
)
218 char busid
[SYSFS_BUS_ID_SIZE
];
220 struct udev_device
*sif
;
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
));
230 sif
= udev_device_new_from_subsystem_sysname(udev_context
, "usb", busid
);
232 err("udev_device_new_from_subsystem_sysname %s failed", busid
);
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");
243 int usbip_names_init(char *f
)
245 return names_init(f
);
248 void usbip_names_free(void)
253 void usbip_names_get_product(char *buff
, size_t size
, uint16_t vendor
,
256 const char *prod
, *vend
;
258 prod
= names_product(vendor
, product
);
260 prod
= "unknown product";
263 vend
= names_vendor(vendor
);
265 vend
= "unknown vendor";
267 snprintf(buff
, size
, "%s : %s (%04x:%04x)", vend
, prod
, vendor
, product
);
270 void usbip_names_get_class(char *buff
, size_t size
, uint8_t class,
271 uint8_t subclass
, uint8_t protocol
)
273 const char *c
, *s
, *p
;
275 if (class == 0 && subclass
== 0 && protocol
== 0) {
276 snprintf(buff
, size
, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass
, protocol
);
280 p
= names_protocol(class, subclass
, protocol
);
282 p
= "unknown protocol";
284 s
= names_subclass(class, subclass
);
286 s
= "unknown subclass";
288 c
= names_class(class);
292 snprintf(buff
, size
, "%s / %s / %s (%02x/%02x/%02x)", c
, s
, p
, class, subclass
, protocol
);