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