2 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
3 * 2005-2007 Takahiro Hirofuchi
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "usbip_common.h"
31 #include "sysfs_utils.h"
39 static const char usbip_bind_usage_string
[] =
41 " -b, --busid=<busid> Bind " USBIP_HOST_DRV_NAME
".ko to device "
44 void usbip_bind_usage(void)
46 printf("usage: %s", usbip_bind_usage_string
);
49 /* call at unbound state */
50 static int bind_usbip(char *busid
)
52 char attr_name
[] = "bind";
53 char bind_attr_path
[SYSFS_PATH_MAX
];
56 snprintf(bind_attr_path
, sizeof(bind_attr_path
), "%s/%s/%s/%s/%s/%s",
57 SYSFS_MNT_PATH
, SYSFS_BUS_NAME
, SYSFS_BUS_TYPE
,
58 SYSFS_DRIVERS_NAME
, USBIP_HOST_DRV_NAME
, attr_name
);
60 rc
= write_sysfs_attribute(bind_attr_path
, busid
, strlen(busid
));
62 err("error binding device %s to driver: %s", busid
,
70 /* buggy driver may cause dead lock */
71 static int unbind_other(char *busid
)
73 enum unbind_status status
= UNBIND_ST_OK
;
75 char attr_name
[] = "unbind";
76 char unbind_attr_path
[SYSFS_PATH_MAX
];
80 struct udev_device
*dev
;
82 const char *bDevClass
;
84 /* Create libudev context. */
88 dev
= udev_device_new_from_subsystem_sysname(udev
, "usb", busid
);
90 dbg("unable to find device with bus ID %s", busid
);
91 goto err_close_busid_dev
;
94 /* Check what kind of device it is. */
95 bDevClass
= udev_device_get_sysattr_value(dev
, "bDeviceClass");
97 dbg("unable to get bDevClass device attribute");
98 goto err_close_busid_dev
;
101 if (!strncmp(bDevClass
, "09", strlen(bDevClass
))) {
102 dbg("skip unbinding of hub");
103 goto err_close_busid_dev
;
106 /* Get the device driver. */
107 driver
= udev_device_get_driver(dev
);
109 /* No driver bound to this device. */
113 if (!strncmp(USBIP_HOST_DRV_NAME
, driver
,
114 strlen(USBIP_HOST_DRV_NAME
))) {
115 /* Already bound to usbip-host. */
116 status
= UNBIND_ST_USBIP_HOST
;
120 /* Unbind device from driver. */
121 snprintf(unbind_attr_path
, sizeof(unbind_attr_path
), "%s/%s/%s/%s/%s/%s",
122 SYSFS_MNT_PATH
, SYSFS_BUS_NAME
, SYSFS_BUS_TYPE
,
123 SYSFS_DRIVERS_NAME
, driver
, attr_name
);
125 rc
= write_sysfs_attribute(unbind_attr_path
, busid
, strlen(busid
));
127 err("error unbinding device %s from driver", busid
);
128 goto err_close_busid_dev
;
134 status
= UNBIND_ST_FAILED
;
136 udev_device_unref(dev
);
142 static int bind_device(char *busid
)
146 struct udev_device
*dev
;
148 /* Check whether the device with this bus ID exists. */
150 dev
= udev_device_new_from_subsystem_sysname(udev
, "usb", busid
);
152 err("device with the specified bus ID does not exist");
157 rc
= unbind_other(busid
);
158 if (rc
== UNBIND_ST_FAILED
) {
159 err("could not unbind driver from device on busid %s", busid
);
161 } else if (rc
== UNBIND_ST_USBIP_HOST
) {
162 err("device on busid %s is already bound to %s", busid
,
163 USBIP_HOST_DRV_NAME
);
167 rc
= modify_match_busid(busid
, 1);
169 err("unable to bind device on %s", busid
);
173 rc
= bind_usbip(busid
);
175 err("could not bind device to %s", USBIP_HOST_DRV_NAME
);
176 modify_match_busid(busid
, 0);
180 info("bind device on busid %s: complete", busid
);
185 int usbip_bind(int argc
, char *argv
[])
187 static const struct option opts
[] = {
188 { "busid", required_argument
, NULL
, 'b' },
196 opt
= getopt_long(argc
, argv
, "b:", opts
, NULL
);
203 ret
= bind_device(optarg
);