]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/usbip/userspace/src/usbip_bind.c
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/>.
19 #include <sysfs/libsysfs.h>
28 #include "usbip_common.h"
38 static const char usbip_bind_usage_string
[] =
40 " -b, --busid=<busid> Bind " USBIP_HOST_DRV_NAME
".ko to device "
43 void usbip_bind_usage(void)
45 printf("usage: %s", usbip_bind_usage_string
);
48 /* call at unbound state */
49 static int bind_usbip(char *busid
)
51 char bus_type
[] = "usb";
52 char attr_name
[] = "bind";
53 char sysfs_mntpath
[SYSFS_PATH_MAX
];
54 char bind_attr_path
[SYSFS_PATH_MAX
];
55 struct sysfs_attribute
*bind_attr
;
59 rc
= sysfs_get_mnt_path(sysfs_mntpath
, SYSFS_PATH_MAX
);
61 err("sysfs must be mounted: %s", strerror(errno
));
65 snprintf(bind_attr_path
, sizeof(bind_attr_path
), "%s/%s/%s/%s/%s/%s",
66 sysfs_mntpath
, SYSFS_BUS_NAME
, bus_type
, SYSFS_DRIVERS_NAME
,
67 USBIP_HOST_DRV_NAME
, attr_name
);
69 bind_attr
= sysfs_open_attribute(bind_attr_path
);
71 dbg("problem getting bind attribute: %s", strerror(errno
));
75 rc
= sysfs_write_attribute(bind_attr
, busid
, SYSFS_BUS_ID_SIZE
);
77 dbg("bind driver at %s failed", busid
);
84 sysfs_close_attribute(bind_attr
);
89 /* buggy driver may cause dead lock */
90 static int unbind_other(char *busid
)
92 char bus_type
[] = "usb";
93 struct sysfs_device
*busid_dev
;
94 struct sysfs_device
*dev
;
95 struct sysfs_driver
*drv
;
96 struct sysfs_attribute
*unbind_attr
;
97 struct sysfs_attribute
*bDevClass
;
99 enum unbind_status status
= UNBIND_ST_OK
;
101 busid_dev
= sysfs_open_device(bus_type
, busid
);
103 dbg("sysfs_open_device %s failed: %s", busid
, strerror(errno
));
106 dbg("busid path: %s", busid_dev
->path
);
108 bDevClass
= sysfs_get_device_attr(busid_dev
, "bDeviceClass");
110 dbg("problem getting device attribute: %s",
112 goto err_close_busid_dev
;
115 if (!strncmp(bDevClass
->value
, "09", bDevClass
->len
)) {
116 dbg("skip unbinding of hub");
117 goto err_close_busid_dev
;
120 dev
= sysfs_open_device(bus_type
, busid
);
122 dbg("could not open device: %s",
124 goto err_close_busid_dev
;
127 dbg("%s -> %s", dev
->name
, dev
->driver_name
);
129 if (!strncmp("unknown", dev
->driver_name
, SYSFS_NAME_LEN
)) {
130 /* unbound interface */
131 sysfs_close_device(dev
);
135 if (!strncmp(USBIP_HOST_DRV_NAME
, dev
->driver_name
,
137 /* already bound to usbip-host */
138 status
= UNBIND_ST_USBIP_HOST
;
139 sysfs_close_device(dev
);
144 drv
= sysfs_open_driver(bus_type
, dev
->driver_name
);
146 dbg("could not open device driver on %s: %s",
147 dev
->name
, strerror(errno
));
148 goto err_close_intf_dev
;
150 dbg("device driver: %s", drv
->path
);
152 unbind_attr
= sysfs_get_driver_attr(drv
, "unbind");
154 dbg("problem getting device driver attribute: %s",
156 goto err_close_intf_drv
;
159 rc
= sysfs_write_attribute(unbind_attr
, dev
->bus_id
,
162 /* NOTE: why keep unbinding other interfaces? */
163 dbg("unbind driver at %s failed", dev
->bus_id
);
164 status
= UNBIND_ST_FAILED
;
167 sysfs_close_driver(drv
);
168 sysfs_close_device(dev
);
173 sysfs_close_driver(drv
);
175 sysfs_close_device(dev
);
177 status
= UNBIND_ST_FAILED
;
179 sysfs_close_device(busid_dev
);
184 static int bind_device(char *busid
)
188 rc
= unbind_other(busid
);
189 if (rc
== UNBIND_ST_FAILED
) {
190 err("could not unbind driver from device on busid %s", busid
);
192 } else if (rc
== UNBIND_ST_USBIP_HOST
) {
193 err("device on busid %s is already bound to %s", busid
,
194 USBIP_HOST_DRV_NAME
);
198 rc
= modify_match_busid(busid
, 1);
200 err("unable to bind device on %s", busid
);
204 rc
= bind_usbip(busid
);
206 err("could not bind device to %s", USBIP_HOST_DRV_NAME
);
207 modify_match_busid(busid
, 0);
211 printf("bind device on busid %s: complete\n", busid
);
216 int usbip_bind(int argc
, char *argv
[])
218 static const struct option opts
[] = {
219 { "busid", required_argument
, NULL
, 'b' },
227 opt
= getopt_long(argc
, argv
, "b:", opts
, NULL
);
234 ret
= bind_device(optarg
);