1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
4 * 2005-2007 Takahiro Hirofuchi
16 #include "usbip_common.h"
19 #include "sysfs_utils.h"
27 static const char usbip_bind_usage_string
[] =
29 " -b, --busid=<busid> Bind " USBIP_HOST_DRV_NAME
".ko to device "
32 void usbip_bind_usage(void)
34 printf("usage: %s", usbip_bind_usage_string
);
37 /* call at unbound state */
38 static int bind_usbip(char *busid
)
40 char attr_name
[] = "bind";
41 char bind_attr_path
[SYSFS_PATH_MAX
];
44 snprintf(bind_attr_path
, sizeof(bind_attr_path
), "%s/%s/%s/%s/%s/%s",
45 SYSFS_MNT_PATH
, SYSFS_BUS_NAME
, SYSFS_BUS_TYPE
,
46 SYSFS_DRIVERS_NAME
, USBIP_HOST_DRV_NAME
, attr_name
);
48 rc
= write_sysfs_attribute(bind_attr_path
, busid
, strlen(busid
));
50 err("error binding device %s to driver: %s", busid
,
58 /* buggy driver may cause dead lock */
59 static int unbind_other(char *busid
)
61 enum unbind_status status
= UNBIND_ST_OK
;
63 char attr_name
[] = "unbind";
64 char unbind_attr_path
[SYSFS_PATH_MAX
];
68 struct udev_device
*dev
;
70 const char *bDevClass
;
72 /* Create libudev context. */
76 dev
= udev_device_new_from_subsystem_sysname(udev
, "usb", busid
);
78 dbg("unable to find device with bus ID %s", busid
);
79 goto err_close_busid_dev
;
82 /* Check what kind of device it is. */
83 bDevClass
= udev_device_get_sysattr_value(dev
, "bDeviceClass");
85 dbg("unable to get bDevClass device attribute");
86 goto err_close_busid_dev
;
89 if (!strncmp(bDevClass
, "09", strlen(bDevClass
))) {
90 dbg("skip unbinding of hub");
91 goto err_close_busid_dev
;
94 /* Get the device driver. */
95 driver
= udev_device_get_driver(dev
);
97 /* No driver bound to this device. */
101 if (!strncmp(USBIP_HOST_DRV_NAME
, driver
,
102 strlen(USBIP_HOST_DRV_NAME
))) {
103 /* Already bound to usbip-host. */
104 status
= UNBIND_ST_USBIP_HOST
;
108 /* Unbind device from driver. */
109 snprintf(unbind_attr_path
, sizeof(unbind_attr_path
), "%s/%s/%s/%s/%s/%s",
110 SYSFS_MNT_PATH
, SYSFS_BUS_NAME
, SYSFS_BUS_TYPE
,
111 SYSFS_DRIVERS_NAME
, driver
, attr_name
);
113 rc
= write_sysfs_attribute(unbind_attr_path
, busid
, strlen(busid
));
115 err("error unbinding device %s from driver", busid
);
116 goto err_close_busid_dev
;
122 status
= UNBIND_ST_FAILED
;
124 udev_device_unref(dev
);
130 static int bind_device(char *busid
)
134 struct udev_device
*dev
;
137 /* Check whether the device with this bus ID exists. */
139 dev
= udev_device_new_from_subsystem_sysname(udev
, "usb", busid
);
141 err("device with the specified bus ID does not exist");
144 devpath
= udev_device_get_devpath(dev
);
147 /* If the device is already attached to vhci_hcd - bail out */
148 if (strstr(devpath
, USBIP_VHCI_DRV_NAME
)) {
149 err("bind loop detected: device: %s is attached to %s\n",
150 devpath
, USBIP_VHCI_DRV_NAME
);
154 rc
= unbind_other(busid
);
155 if (rc
== UNBIND_ST_FAILED
) {
156 err("could not unbind driver from device on busid %s", busid
);
158 } else if (rc
== UNBIND_ST_USBIP_HOST
) {
159 err("device on busid %s is already bound to %s", busid
,
160 USBIP_HOST_DRV_NAME
);
164 rc
= modify_match_busid(busid
, 1);
166 err("unable to bind device on %s", busid
);
170 rc
= bind_usbip(busid
);
172 err("could not bind device to %s", USBIP_HOST_DRV_NAME
);
173 modify_match_busid(busid
, 0);
177 info("bind device on busid %s: complete", busid
);
182 int usbip_bind(int argc
, char *argv
[])
184 static const struct option opts
[] = {
185 { "busid", required_argument
, NULL
, 'b' },
193 opt
= getopt_long(argc
, argv
, "b:", opts
, NULL
);
200 ret
= bind_device(optarg
);