18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2005-2007 Takahiro Hirofuchi 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include "usbip_common.h" 78c2ecf20Sopenharmony_ci#include "vhci_driver.h" 88c2ecf20Sopenharmony_ci#include <limits.h> 98c2ecf20Sopenharmony_ci#include <netdb.h> 108c2ecf20Sopenharmony_ci#include <libudev.h> 118c2ecf20Sopenharmony_ci#include <dirent.h> 128c2ecf20Sopenharmony_ci#include "sysfs_utils.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#undef PROGNAME 158c2ecf20Sopenharmony_ci#define PROGNAME "libusbip" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct usbip_vhci_driver *vhci_driver; 188c2ecf20Sopenharmony_cistruct udev *udev_context; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic struct usbip_imported_device * 218c2ecf20Sopenharmony_ciimported_device_init(struct usbip_imported_device *idev, char *busid) 228c2ecf20Sopenharmony_ci{ 238c2ecf20Sopenharmony_ci struct udev_device *sudev; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci sudev = udev_device_new_from_subsystem_sysname(udev_context, 268c2ecf20Sopenharmony_ci "usb", busid); 278c2ecf20Sopenharmony_ci if (!sudev) { 288c2ecf20Sopenharmony_ci dbg("udev_device_new_from_subsystem_sysname failed: %s", busid); 298c2ecf20Sopenharmony_ci goto err; 308c2ecf20Sopenharmony_ci } 318c2ecf20Sopenharmony_ci read_usb_device(sudev, &idev->udev); 328c2ecf20Sopenharmony_ci udev_device_unref(sudev); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci return idev; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cierr: 378c2ecf20Sopenharmony_ci return NULL; 388c2ecf20Sopenharmony_ci} 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic int parse_status(const char *value) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci int ret = 0; 438c2ecf20Sopenharmony_ci char *c; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* skip a header line */ 468c2ecf20Sopenharmony_ci c = strchr(value, '\n'); 478c2ecf20Sopenharmony_ci if (!c) 488c2ecf20Sopenharmony_ci return -1; 498c2ecf20Sopenharmony_ci c++; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci while (*c != '\0') { 528c2ecf20Sopenharmony_ci int port, status, speed, devid; 538c2ecf20Sopenharmony_ci int sockfd; 548c2ecf20Sopenharmony_ci char lbusid[SYSFS_BUS_ID_SIZE]; 558c2ecf20Sopenharmony_ci struct usbip_imported_device *idev; 568c2ecf20Sopenharmony_ci char hub[3]; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci ret = sscanf(c, "%2s %d %d %d %x %u %31s\n", 598c2ecf20Sopenharmony_ci hub, &port, &status, &speed, 608c2ecf20Sopenharmony_ci &devid, &sockfd, lbusid); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci if (ret < 5) { 638c2ecf20Sopenharmony_ci dbg("sscanf failed: %d", ret); 648c2ecf20Sopenharmony_ci BUG(); 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci dbg("hub %s port %d status %d speed %d devid %x", 688c2ecf20Sopenharmony_ci hub, port, status, speed, devid); 698c2ecf20Sopenharmony_ci dbg("sockfd %u lbusid %s", sockfd, lbusid); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci /* if a device is connected, look at it */ 728c2ecf20Sopenharmony_ci idev = &vhci_driver->idev[port]; 738c2ecf20Sopenharmony_ci memset(idev, 0, sizeof(*idev)); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci if (strncmp("hs", hub, 2) == 0) 768c2ecf20Sopenharmony_ci idev->hub = HUB_SPEED_HIGH; 778c2ecf20Sopenharmony_ci else /* strncmp("ss", hub, 2) == 0 */ 788c2ecf20Sopenharmony_ci idev->hub = HUB_SPEED_SUPER; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci idev->port = port; 818c2ecf20Sopenharmony_ci idev->status = status; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci idev->devid = devid; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci idev->busnum = (devid >> 16); 868c2ecf20Sopenharmony_ci idev->devnum = (devid & 0x0000ffff); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci if (idev->status != VDEV_ST_NULL 898c2ecf20Sopenharmony_ci && idev->status != VDEV_ST_NOTASSIGNED) { 908c2ecf20Sopenharmony_ci idev = imported_device_init(idev, lbusid); 918c2ecf20Sopenharmony_ci if (!idev) { 928c2ecf20Sopenharmony_ci dbg("imported_device_init failed"); 938c2ecf20Sopenharmony_ci return -1; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* go to the next line */ 988c2ecf20Sopenharmony_ci c = strchr(c, '\n'); 998c2ecf20Sopenharmony_ci if (!c) 1008c2ecf20Sopenharmony_ci break; 1018c2ecf20Sopenharmony_ci c++; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci dbg("exit"); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#define MAX_STATUS_NAME 18 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic int refresh_imported_device_list(void) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci const char *attr_status; 1148c2ecf20Sopenharmony_ci char status[MAX_STATUS_NAME+1] = "status"; 1158c2ecf20Sopenharmony_ci int i, ret; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci for (i = 0; i < vhci_driver->ncontrollers; i++) { 1188c2ecf20Sopenharmony_ci if (i > 0) 1198c2ecf20Sopenharmony_ci snprintf(status, sizeof(status), "status.%d", i); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device, 1228c2ecf20Sopenharmony_ci status); 1238c2ecf20Sopenharmony_ci if (!attr_status) { 1248c2ecf20Sopenharmony_ci err("udev_device_get_sysattr_value failed"); 1258c2ecf20Sopenharmony_ci return -1; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci dbg("controller %d", i); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci ret = parse_status(attr_status); 1318c2ecf20Sopenharmony_ci if (ret != 0) 1328c2ecf20Sopenharmony_ci return ret; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci return 0; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic int get_nports(struct udev_device *hc_device) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci const char *attr_nports; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci attr_nports = udev_device_get_sysattr_value(hc_device, "nports"); 1438c2ecf20Sopenharmony_ci if (!attr_nports) { 1448c2ecf20Sopenharmony_ci err("udev_device_get_sysattr_value nports failed"); 1458c2ecf20Sopenharmony_ci return -1; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci return (int)strtoul(attr_nports, NULL, 10); 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int vhci_hcd_filter(const struct dirent *dirent) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci return !strncmp(dirent->d_name, "vhci_hcd.", 9); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic int get_ncontrollers(void) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci struct dirent **namelist; 1598c2ecf20Sopenharmony_ci struct udev_device *platform; 1608c2ecf20Sopenharmony_ci int n; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci platform = udev_device_get_parent(vhci_driver->hc_device); 1638c2ecf20Sopenharmony_ci if (platform == NULL) 1648c2ecf20Sopenharmony_ci return -1; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci n = scandir(udev_device_get_syspath(platform), &namelist, vhci_hcd_filter, NULL); 1678c2ecf20Sopenharmony_ci if (n < 0) 1688c2ecf20Sopenharmony_ci err("scandir failed"); 1698c2ecf20Sopenharmony_ci else { 1708c2ecf20Sopenharmony_ci for (int i = 0; i < n; i++) 1718c2ecf20Sopenharmony_ci free(namelist[i]); 1728c2ecf20Sopenharmony_ci free(namelist); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci return n; 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci/* 1798c2ecf20Sopenharmony_ci * Read the given port's record. 1808c2ecf20Sopenharmony_ci * 1818c2ecf20Sopenharmony_ci * To avoid buffer overflow we will read the entire line and 1828c2ecf20Sopenharmony_ci * validate each part's size. The initial buffer is padded by 4 to 1838c2ecf20Sopenharmony_ci * accommodate the 2 spaces, 1 newline and an additional character 1848c2ecf20Sopenharmony_ci * which is needed to properly validate the 3rd part without it being 1858c2ecf20Sopenharmony_ci * truncated to an acceptable length. 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_cistatic int read_record(int rhport, char *host, unsigned long host_len, 1888c2ecf20Sopenharmony_ci char *port, unsigned long port_len, char *busid) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci int part; 1918c2ecf20Sopenharmony_ci FILE *file; 1928c2ecf20Sopenharmony_ci char path[PATH_MAX+1]; 1938c2ecf20Sopenharmony_ci char *buffer, *start, *end; 1948c2ecf20Sopenharmony_ci char delim[] = {' ', ' ', '\n'}; 1958c2ecf20Sopenharmony_ci int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE}; 1968c2ecf20Sopenharmony_ci size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci buffer = malloc(buffer_len); 1998c2ecf20Sopenharmony_ci if (!buffer) 2008c2ecf20Sopenharmony_ci return -1; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci file = fopen(path, "r"); 2058c2ecf20Sopenharmony_ci if (!file) { 2068c2ecf20Sopenharmony_ci err("fopen"); 2078c2ecf20Sopenharmony_ci free(buffer); 2088c2ecf20Sopenharmony_ci return -1; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (fgets(buffer, buffer_len, file) == NULL) { 2128c2ecf20Sopenharmony_ci err("fgets"); 2138c2ecf20Sopenharmony_ci free(buffer); 2148c2ecf20Sopenharmony_ci fclose(file); 2158c2ecf20Sopenharmony_ci return -1; 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci fclose(file); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci /* validate the length of each of the 3 parts */ 2208c2ecf20Sopenharmony_ci start = buffer; 2218c2ecf20Sopenharmony_ci for (part = 0; part < 3; part++) { 2228c2ecf20Sopenharmony_ci end = strchr(start, delim[part]); 2238c2ecf20Sopenharmony_ci if (end == NULL || (end - start) > max_len[part]) { 2248c2ecf20Sopenharmony_ci free(buffer); 2258c2ecf20Sopenharmony_ci return -1; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci start = end + 1; 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) { 2318c2ecf20Sopenharmony_ci err("sscanf"); 2328c2ecf20Sopenharmony_ci free(buffer); 2338c2ecf20Sopenharmony_ci return -1; 2348c2ecf20Sopenharmony_ci } 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci free(buffer); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci return 0; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci/* ---------------------------------------------------------------------- */ 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ciint usbip_vhci_driver_open(void) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci int nports; 2468c2ecf20Sopenharmony_ci struct udev_device *hc_device; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci udev_context = udev_new(); 2498c2ecf20Sopenharmony_ci if (!udev_context) { 2508c2ecf20Sopenharmony_ci err("udev_new failed"); 2518c2ecf20Sopenharmony_ci return -1; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* will be freed in usbip_driver_close() */ 2558c2ecf20Sopenharmony_ci hc_device = 2568c2ecf20Sopenharmony_ci udev_device_new_from_subsystem_sysname(udev_context, 2578c2ecf20Sopenharmony_ci USBIP_VHCI_BUS_TYPE, 2588c2ecf20Sopenharmony_ci USBIP_VHCI_DEVICE_NAME); 2598c2ecf20Sopenharmony_ci if (!hc_device) { 2608c2ecf20Sopenharmony_ci err("udev_device_new_from_subsystem_sysname failed"); 2618c2ecf20Sopenharmony_ci goto err; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci nports = get_nports(hc_device); 2658c2ecf20Sopenharmony_ci if (nports <= 0) { 2668c2ecf20Sopenharmony_ci err("no available ports"); 2678c2ecf20Sopenharmony_ci goto err; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci dbg("available ports: %d", nports); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver) + 2728c2ecf20Sopenharmony_ci nports * sizeof(struct usbip_imported_device)); 2738c2ecf20Sopenharmony_ci if (!vhci_driver) { 2748c2ecf20Sopenharmony_ci err("vhci_driver allocation failed"); 2758c2ecf20Sopenharmony_ci goto err; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci vhci_driver->nports = nports; 2798c2ecf20Sopenharmony_ci vhci_driver->hc_device = hc_device; 2808c2ecf20Sopenharmony_ci vhci_driver->ncontrollers = get_ncontrollers(); 2818c2ecf20Sopenharmony_ci dbg("available controllers: %d", vhci_driver->ncontrollers); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (vhci_driver->ncontrollers <=0) { 2848c2ecf20Sopenharmony_ci err("no available usb controllers"); 2858c2ecf20Sopenharmony_ci goto err; 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci if (refresh_imported_device_list()) 2898c2ecf20Sopenharmony_ci goto err; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci return 0; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cierr: 2948c2ecf20Sopenharmony_ci udev_device_unref(hc_device); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci if (vhci_driver) 2978c2ecf20Sopenharmony_ci free(vhci_driver); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci vhci_driver = NULL; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci udev_unref(udev_context); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci return -1; 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_civoid usbip_vhci_driver_close(void) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci if (!vhci_driver) 3108c2ecf20Sopenharmony_ci return; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci udev_device_unref(vhci_driver->hc_device); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci free(vhci_driver); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci vhci_driver = NULL; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci udev_unref(udev_context); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ciint usbip_vhci_refresh_device_list(void) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (refresh_imported_device_list()) 3268c2ecf20Sopenharmony_ci goto err; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci return 0; 3298c2ecf20Sopenharmony_cierr: 3308c2ecf20Sopenharmony_ci dbg("failed to refresh device list"); 3318c2ecf20Sopenharmony_ci return -1; 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ciint usbip_vhci_get_free_port(uint32_t speed) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci for (int i = 0; i < vhci_driver->nports; i++) { 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci switch (speed) { 3408c2ecf20Sopenharmony_ci case USB_SPEED_SUPER: 3418c2ecf20Sopenharmony_ci if (vhci_driver->idev[i].hub != HUB_SPEED_SUPER) 3428c2ecf20Sopenharmony_ci continue; 3438c2ecf20Sopenharmony_ci break; 3448c2ecf20Sopenharmony_ci default: 3458c2ecf20Sopenharmony_ci if (vhci_driver->idev[i].hub != HUB_SPEED_HIGH) 3468c2ecf20Sopenharmony_ci continue; 3478c2ecf20Sopenharmony_ci break; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci if (vhci_driver->idev[i].status == VDEV_ST_NULL) 3518c2ecf20Sopenharmony_ci return vhci_driver->idev[i].port; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci return -1; 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ciint usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid, 3588c2ecf20Sopenharmony_ci uint32_t speed) { 3598c2ecf20Sopenharmony_ci char buff[200]; /* what size should be ? */ 3608c2ecf20Sopenharmony_ci char attach_attr_path[SYSFS_PATH_MAX]; 3618c2ecf20Sopenharmony_ci char attr_attach[] = "attach"; 3628c2ecf20Sopenharmony_ci const char *path; 3638c2ecf20Sopenharmony_ci int ret; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci snprintf(buff, sizeof(buff), "%u %d %u %u", 3668c2ecf20Sopenharmony_ci port, sockfd, devid, speed); 3678c2ecf20Sopenharmony_ci dbg("writing: %s", buff); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci path = udev_device_get_syspath(vhci_driver->hc_device); 3708c2ecf20Sopenharmony_ci snprintf(attach_attr_path, sizeof(attach_attr_path), "%s/%s", 3718c2ecf20Sopenharmony_ci path, attr_attach); 3728c2ecf20Sopenharmony_ci dbg("attach attribute path: %s", attach_attr_path); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci ret = write_sysfs_attribute(attach_attr_path, buff, strlen(buff)); 3758c2ecf20Sopenharmony_ci if (ret < 0) { 3768c2ecf20Sopenharmony_ci dbg("write_sysfs_attribute failed"); 3778c2ecf20Sopenharmony_ci return -1; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci dbg("attached port: %d", port); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci return 0; 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic unsigned long get_devid(uint8_t busnum, uint8_t devnum) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci return (busnum << 16) | devnum; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci/* will be removed */ 3918c2ecf20Sopenharmony_ciint usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum, 3928c2ecf20Sopenharmony_ci uint8_t devnum, uint32_t speed) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci int devid = get_devid(busnum, devnum); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci return usbip_vhci_attach_device2(port, sockfd, devid, speed); 3978c2ecf20Sopenharmony_ci} 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ciint usbip_vhci_detach_device(uint8_t port) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci char detach_attr_path[SYSFS_PATH_MAX]; 4028c2ecf20Sopenharmony_ci char attr_detach[] = "detach"; 4038c2ecf20Sopenharmony_ci char buff[200]; /* what size should be ? */ 4048c2ecf20Sopenharmony_ci const char *path; 4058c2ecf20Sopenharmony_ci int ret; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci snprintf(buff, sizeof(buff), "%u", port); 4088c2ecf20Sopenharmony_ci dbg("writing: %s", buff); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci path = udev_device_get_syspath(vhci_driver->hc_device); 4118c2ecf20Sopenharmony_ci snprintf(detach_attr_path, sizeof(detach_attr_path), "%s/%s", 4128c2ecf20Sopenharmony_ci path, attr_detach); 4138c2ecf20Sopenharmony_ci dbg("detach attribute path: %s", detach_attr_path); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci ret = write_sysfs_attribute(detach_attr_path, buff, strlen(buff)); 4168c2ecf20Sopenharmony_ci if (ret < 0) { 4178c2ecf20Sopenharmony_ci dbg("write_sysfs_attribute failed"); 4188c2ecf20Sopenharmony_ci return -1; 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci dbg("detached port: %d", port); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci return 0; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ciint usbip_vhci_imported_device_dump(struct usbip_imported_device *idev) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci char product_name[100]; 4298c2ecf20Sopenharmony_ci char host[NI_MAXHOST] = "unknown host"; 4308c2ecf20Sopenharmony_ci char serv[NI_MAXSERV] = "unknown port"; 4318c2ecf20Sopenharmony_ci char remote_busid[SYSFS_BUS_ID_SIZE]; 4328c2ecf20Sopenharmony_ci int ret; 4338c2ecf20Sopenharmony_ci int read_record_error = 0; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED) 4368c2ecf20Sopenharmony_ci return 0; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv), 4398c2ecf20Sopenharmony_ci remote_busid); 4408c2ecf20Sopenharmony_ci if (ret) { 4418c2ecf20Sopenharmony_ci err("read_record"); 4428c2ecf20Sopenharmony_ci read_record_error = 1; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci printf("Port %02d: <%s> at %s\n", idev->port, 4468c2ecf20Sopenharmony_ci usbip_status_string(idev->status), 4478c2ecf20Sopenharmony_ci usbip_speed_string(idev->udev.speed)); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci usbip_names_get_product(product_name, sizeof(product_name), 4508c2ecf20Sopenharmony_ci idev->udev.idVendor, idev->udev.idProduct); 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci printf(" %s\n", product_name); 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci if (!read_record_error) { 4558c2ecf20Sopenharmony_ci printf("%10s -> usbip://%s:%s/%s\n", idev->udev.busid, 4568c2ecf20Sopenharmony_ci host, serv, remote_busid); 4578c2ecf20Sopenharmony_ci printf("%10s -> remote bus/dev %03d/%03d\n", " ", 4588c2ecf20Sopenharmony_ci idev->busnum, idev->devnum); 4598c2ecf20Sopenharmony_ci } else { 4608c2ecf20Sopenharmony_ci printf("%10s -> unknown host, remote port and remote busid\n", 4618c2ecf20Sopenharmony_ci idev->udev.busid); 4628c2ecf20Sopenharmony_ci printf("%10s -> remote bus/dev %03d/%03d\n", " ", 4638c2ecf20Sopenharmony_ci idev->busnum, idev->devnum); 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci return 0; 4678c2ecf20Sopenharmony_ci} 468