| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2005-2007 Takahiro Hirofuchi | 
 | 3 |  */ | 
 | 4 |  | 
| matt mooney | 099f79f | 2011-06-19 22:44:37 -0700 | [diff] [blame] | 5 | #include "usbip_common.h" | 
 | 6 | #include "vhci_driver.h" | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 7 | #include <limits.h> | 
 | 8 | #include <netdb.h> | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 9 | #include <libudev.h> | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 10 | #include "sysfs_utils.h" | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 11 |  | 
| matt mooney | f2fb62b | 2011-06-19 22:44:35 -0700 | [diff] [blame] | 12 | #undef  PROGNAME | 
 | 13 | #define PROGNAME "libusbip" | 
 | 14 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 15 | struct usbip_vhci_driver *vhci_driver; | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 16 | struct udev *udev_context; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 17 |  | 
| Kurt Kanzenbach | 9db91e1 | 2013-02-22 12:13:29 +0100 | [diff] [blame] | 18 | static struct usbip_imported_device * | 
 | 19 | imported_device_init(struct usbip_imported_device *idev, char *busid) | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 20 | { | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 21 | 	struct udev_device *sudev; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 22 |  | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 23 | 	sudev = udev_device_new_from_subsystem_sysname(udev_context, | 
 | 24 | 						       "usb", busid); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 25 | 	if (!sudev) { | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 26 | 		dbg("udev_device_new_from_subsystem_sysname failed: %s", busid); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 27 | 		goto err; | 
 | 28 | 	} | 
 | 29 | 	read_usb_device(sudev, &idev->udev); | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 30 | 	udev_device_unref(sudev); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 31 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 32 | 	return idev; | 
 | 33 |  | 
 | 34 | err: | 
 | 35 | 	return NULL; | 
 | 36 | } | 
 | 37 |  | 
 | 38 |  | 
 | 39 |  | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 40 | static int parse_status(const char *value) | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 41 | { | 
 | 42 | 	int ret = 0; | 
 | 43 | 	char *c; | 
 | 44 |  | 
 | 45 |  | 
 | 46 | 	for (int i = 0; i < vhci_driver->nports; i++) | 
| matt mooney | 950a4cd | 2011-05-27 01:44:10 -0700 | [diff] [blame] | 47 | 		memset(&vhci_driver->idev[i], 0, sizeof(vhci_driver->idev[i])); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 48 |  | 
 | 49 |  | 
 | 50 | 	/* skip a header line */ | 
| Christopher Harvey | 2f5c638 | 2012-03-23 10:55:25 -0400 | [diff] [blame] | 51 | 	c = strchr(value, '\n'); | 
 | 52 | 	if (!c) | 
 | 53 | 		return -1; | 
 | 54 | 	c++; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 55 |  | 
 | 56 | 	while (*c != '\0') { | 
 | 57 | 		int port, status, speed, devid; | 
 | 58 | 		unsigned long socket; | 
 | 59 | 		char lbusid[SYSFS_BUS_ID_SIZE]; | 
 | 60 |  | 
| Alan | 2d32927 | 2013-12-11 18:32:59 +0000 | [diff] [blame] | 61 | 		ret = sscanf(c, "%d %d %d %x %lx %31s\n", | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 62 | 				&port, &status, &speed, | 
 | 63 | 				&devid, &socket, lbusid); | 
 | 64 |  | 
 | 65 | 		if (ret < 5) { | 
| matt mooney | 25567a3 | 2011-06-19 22:44:38 -0700 | [diff] [blame] | 66 | 			dbg("sscanf failed: %d", ret); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 67 | 			BUG(); | 
 | 68 | 		} | 
 | 69 |  | 
 | 70 | 		dbg("port %d status %d speed %d devid %x", | 
 | 71 | 				port, status, speed, devid); | 
 | 72 | 		dbg("socket %lx lbusid %s", socket, lbusid); | 
 | 73 |  | 
 | 74 |  | 
 | 75 | 		/* if a device is connected, look at it */ | 
 | 76 | 		{ | 
 | 77 | 			struct usbip_imported_device *idev = &vhci_driver->idev[port]; | 
 | 78 |  | 
 | 79 | 			idev->port	= port; | 
 | 80 | 			idev->status	= status; | 
 | 81 |  | 
 | 82 | 			idev->devid	= devid; | 
 | 83 |  | 
 | 84 | 			idev->busnum	= (devid >> 16); | 
 | 85 | 			idev->devnum	= (devid & 0x0000ffff); | 
 | 86 |  | 
| Kurt Kanzenbach | 9db91e1 | 2013-02-22 12:13:29 +0100 | [diff] [blame] | 87 | 			if (idev->status != VDEV_ST_NULL | 
 | 88 | 			    && idev->status != VDEV_ST_NOTASSIGNED) { | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 89 | 				idev = imported_device_init(idev, lbusid); | 
 | 90 | 				if (!idev) { | 
| matt mooney | 25567a3 | 2011-06-19 22:44:38 -0700 | [diff] [blame] | 91 | 					dbg("imported_device_init failed"); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 92 | 					return -1; | 
 | 93 | 				} | 
 | 94 | 			} | 
 | 95 | 		} | 
 | 96 |  | 
 | 97 |  | 
 | 98 | 		/* go to the next line */ | 
| Christopher Harvey | 2f5c638 | 2012-03-23 10:55:25 -0400 | [diff] [blame] | 99 | 		c = strchr(c, '\n'); | 
 | 100 | 		if (!c) | 
 | 101 | 			break; | 
 | 102 | 		c++; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 103 | 	} | 
 | 104 |  | 
 | 105 | 	dbg("exit"); | 
 | 106 |  | 
 | 107 | 	return 0; | 
 | 108 | } | 
 | 109 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 110 | static int refresh_imported_device_list(void) | 
 | 111 | { | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 112 | 	const char *attr_status; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 113 |  | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 114 | 	attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device, | 
 | 115 | 					       "status"); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 116 | 	if (!attr_status) { | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 117 | 		err("udev_device_get_sysattr_value failed"); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 118 | 		return -1; | 
 | 119 | 	} | 
 | 120 |  | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 121 | 	return parse_status(attr_status); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 122 | } | 
 | 123 |  | 
 | 124 | static int get_nports(void) | 
 | 125 | { | 
| Yuyang Du | 37e47d5 | 2017-04-06 06:03:23 +0800 | [diff] [blame] | 126 | 	const char *attr_nports; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 127 |  | 
| Yuyang Du | 37e47d5 | 2017-04-06 06:03:23 +0800 | [diff] [blame] | 128 | 	attr_nports = udev_device_get_sysattr_value(vhci_driver->hc_device, "nports"); | 
 | 129 | 	if (!attr_nports) { | 
 | 130 | 		err("udev_device_get_sysattr_value nports failed"); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 131 | 		return -1; | 
 | 132 | 	} | 
 | 133 |  | 
| Yuyang Du | 37e47d5 | 2017-04-06 06:03:23 +0800 | [diff] [blame] | 134 | 	return (int)strtoul(attr_nports, NULL, 10); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 135 | } | 
 | 136 |  | 
| Mark Asselstine | a37d70e | 2014-02-12 21:47:56 -0500 | [diff] [blame] | 137 | /* | 
 | 138 |  * Read the given port's record. | 
 | 139 |  * | 
 | 140 |  * To avoid buffer overflow we will read the entire line and | 
 | 141 |  * validate each part's size. The initial buffer is padded by 4 to | 
 | 142 |  * accommodate the 2 spaces, 1 newline and an additional character | 
 | 143 |  * which is needed to properly validate the 3rd part without it being | 
 | 144 |  * truncated to an acceptable length. | 
 | 145 |  */ | 
 | 146 | static int read_record(int rhport, char *host, unsigned long host_len, | 
 | 147 | 		char *port, unsigned long port_len, char *busid) | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 148 | { | 
| Mark Asselstine | a37d70e | 2014-02-12 21:47:56 -0500 | [diff] [blame] | 149 | 	int part; | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 150 | 	FILE *file; | 
 | 151 | 	char path[PATH_MAX+1]; | 
| Mark Asselstine | a37d70e | 2014-02-12 21:47:56 -0500 | [diff] [blame] | 152 | 	char *buffer, *start, *end; | 
 | 153 | 	char delim[] = {' ', ' ', '\n'}; | 
 | 154 | 	int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE}; | 
 | 155 | 	size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4; | 
 | 156 |  | 
 | 157 | 	buffer = malloc(buffer_len); | 
 | 158 | 	if (!buffer) | 
 | 159 | 		return -1; | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 160 |  | 
 | 161 | 	snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport); | 
 | 162 |  | 
 | 163 | 	file = fopen(path, "r"); | 
 | 164 | 	if (!file) { | 
 | 165 | 		err("fopen"); | 
| Mark Asselstine | a37d70e | 2014-02-12 21:47:56 -0500 | [diff] [blame] | 166 | 		free(buffer); | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 167 | 		return -1; | 
 | 168 | 	} | 
 | 169 |  | 
| Mark Asselstine | a37d70e | 2014-02-12 21:47:56 -0500 | [diff] [blame] | 170 | 	if (fgets(buffer, buffer_len, file) == NULL) { | 
 | 171 | 		err("fgets"); | 
 | 172 | 		free(buffer); | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 173 | 		fclose(file); | 
 | 174 | 		return -1; | 
 | 175 | 	} | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 176 | 	fclose(file); | 
 | 177 |  | 
| Mark Asselstine | a37d70e | 2014-02-12 21:47:56 -0500 | [diff] [blame] | 178 | 	/* validate the length of each of the 3 parts */ | 
 | 179 | 	start = buffer; | 
 | 180 | 	for (part = 0; part < 3; part++) { | 
 | 181 | 		end = strchr(start, delim[part]); | 
 | 182 | 		if (end == NULL || (end - start) > max_len[part]) { | 
 | 183 | 			free(buffer); | 
 | 184 | 			return -1; | 
 | 185 | 		} | 
 | 186 | 		start = end + 1; | 
 | 187 | 	} | 
 | 188 |  | 
 | 189 | 	if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) { | 
 | 190 | 		err("sscanf"); | 
 | 191 | 		free(buffer); | 
 | 192 | 		return -1; | 
 | 193 | 	} | 
 | 194 |  | 
 | 195 | 	free(buffer); | 
 | 196 |  | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 197 | 	return 0; | 
 | 198 | } | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 199 |  | 
 | 200 | /* ---------------------------------------------------------------------- */ | 
 | 201 |  | 
 | 202 | int usbip_vhci_driver_open(void) | 
 | 203 | { | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 204 | 	udev_context = udev_new(); | 
 | 205 | 	if (!udev_context) { | 
 | 206 | 		err("udev_new failed"); | 
 | 207 | 		return -1; | 
 | 208 | 	} | 
 | 209 |  | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 210 | 	vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver)); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 211 |  | 
 | 212 | 	/* will be freed in usbip_driver_close() */ | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 213 | 	vhci_driver->hc_device = | 
 | 214 | 		udev_device_new_from_subsystem_sysname(udev_context, | 
 | 215 | 						       USBIP_VHCI_BUS_TYPE, | 
 | 216 | 						       USBIP_VHCI_DRV_NAME); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 217 | 	if (!vhci_driver->hc_device) { | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 218 | 		err("udev_device_new_from_subsystem_sysname failed"); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 219 | 		goto err; | 
 | 220 | 	} | 
 | 221 |  | 
 | 222 | 	vhci_driver->nports = get_nports(); | 
| matt mooney | 25567a3 | 2011-06-19 22:44:38 -0700 | [diff] [blame] | 223 | 	dbg("available ports: %d", vhci_driver->nports); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 224 |  | 
| Yuyang Du | c350971 | 2017-05-22 18:20:15 +0800 | [diff] [blame^] | 225 | 	if (vhci_driver->nports <= 0) { | 
 | 226 | 		err("no available ports"); | 
 | 227 | 		goto err; | 
 | 228 | 	} else if (vhci_driver->nports > MAXNPORT) { | 
 | 229 | 		err("port number exceeds %d", MAXNPORT); | 
 | 230 | 		goto err; | 
 | 231 | 	} | 
 | 232 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 233 | 	if (refresh_imported_device_list()) | 
 | 234 | 		goto err; | 
 | 235 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 236 | 	return 0; | 
 | 237 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 238 | err: | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 239 | 	udev_device_unref(vhci_driver->hc_device); | 
 | 240 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 241 | 	if (vhci_driver) | 
 | 242 | 		free(vhci_driver); | 
 | 243 |  | 
 | 244 | 	vhci_driver = NULL; | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 245 |  | 
 | 246 | 	udev_unref(udev_context); | 
 | 247 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 248 | 	return -1; | 
 | 249 | } | 
 | 250 |  | 
 | 251 |  | 
| Pawel Lebioda | 1949551 | 2014-05-14 21:28:27 +0200 | [diff] [blame] | 252 | void usbip_vhci_driver_close(void) | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 253 | { | 
 | 254 | 	if (!vhci_driver) | 
 | 255 | 		return; | 
 | 256 |  | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 257 | 	udev_device_unref(vhci_driver->hc_device); | 
 | 258 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 259 | 	free(vhci_driver); | 
 | 260 |  | 
 | 261 | 	vhci_driver = NULL; | 
| Valentina Manea | 021aed8 | 2014-03-08 14:53:26 +0200 | [diff] [blame] | 262 |  | 
 | 263 | 	udev_unref(udev_context); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 264 | } | 
 | 265 |  | 
 | 266 |  | 
 | 267 | int usbip_vhci_refresh_device_list(void) | 
 | 268 | { | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 269 |  | 
 | 270 | 	if (refresh_imported_device_list()) | 
 | 271 | 		goto err; | 
 | 272 |  | 
 | 273 | 	return 0; | 
 | 274 | err: | 
| matt mooney | 25567a3 | 2011-06-19 22:44:38 -0700 | [diff] [blame] | 275 | 	dbg("failed to refresh device list"); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 276 | 	return -1; | 
 | 277 | } | 
 | 278 |  | 
 | 279 |  | 
 | 280 | int usbip_vhci_get_free_port(void) | 
 | 281 | { | 
 | 282 | 	for (int i = 0; i < vhci_driver->nports; i++) { | 
 | 283 | 		if (vhci_driver->idev[i].status == VDEV_ST_NULL) | 
 | 284 | 			return i; | 
 | 285 | 	} | 
 | 286 |  | 
 | 287 | 	return -1; | 
 | 288 | } | 
 | 289 |  | 
 | 290 | int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid, | 
 | 291 | 		uint32_t speed) { | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 292 | 	char buff[200]; /* what size should be ? */ | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 293 | 	char attach_attr_path[SYSFS_PATH_MAX]; | 
 | 294 | 	char attr_attach[] = "attach"; | 
 | 295 | 	const char *path; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 296 | 	int ret; | 
 | 297 |  | 
| Masanari Iida | 5484081 | 2014-02-27 20:36:31 +0900 | [diff] [blame] | 298 | 	snprintf(buff, sizeof(buff), "%u %d %u %u", | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 299 | 			port, sockfd, devid, speed); | 
 | 300 | 	dbg("writing: %s", buff); | 
 | 301 |  | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 302 | 	path = udev_device_get_syspath(vhci_driver->hc_device); | 
 | 303 | 	snprintf(attach_attr_path, sizeof(attach_attr_path), "%s/%s", | 
 | 304 | 		 path, attr_attach); | 
 | 305 | 	dbg("attach attribute path: %s", attach_attr_path); | 
 | 306 |  | 
 | 307 | 	ret = write_sysfs_attribute(attach_attr_path, buff, strlen(buff)); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 308 | 	if (ret < 0) { | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 309 | 		dbg("write_sysfs_attribute failed"); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 310 | 		return -1; | 
 | 311 | 	} | 
 | 312 |  | 
| matt mooney | 25567a3 | 2011-06-19 22:44:38 -0700 | [diff] [blame] | 313 | 	dbg("attached port: %d", port); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 314 |  | 
 | 315 | 	return 0; | 
 | 316 | } | 
 | 317 |  | 
 | 318 | static unsigned long get_devid(uint8_t busnum, uint8_t devnum) | 
 | 319 | { | 
 | 320 | 	return (busnum << 16) | devnum; | 
 | 321 | } | 
 | 322 |  | 
 | 323 | /* will be removed */ | 
 | 324 | int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum, | 
 | 325 | 		uint8_t devnum, uint32_t speed) | 
 | 326 | { | 
 | 327 | 	int devid = get_devid(busnum, devnum); | 
 | 328 |  | 
 | 329 | 	return usbip_vhci_attach_device2(port, sockfd, devid, speed); | 
 | 330 | } | 
 | 331 |  | 
 | 332 | int usbip_vhci_detach_device(uint8_t port) | 
 | 333 | { | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 334 | 	char detach_attr_path[SYSFS_PATH_MAX]; | 
 | 335 | 	char attr_detach[] = "detach"; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 336 | 	char buff[200]; /* what size should be ? */ | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 337 | 	const char *path; | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 338 | 	int ret; | 
 | 339 |  | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 340 | 	snprintf(buff, sizeof(buff), "%u", port); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 341 | 	dbg("writing: %s", buff); | 
 | 342 |  | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 343 | 	path = udev_device_get_syspath(vhci_driver->hc_device); | 
 | 344 | 	snprintf(detach_attr_path, sizeof(detach_attr_path), "%s/%s", | 
 | 345 | 		 path, attr_detach); | 
 | 346 | 	dbg("detach attribute path: %s", detach_attr_path); | 
 | 347 |  | 
 | 348 | 	ret = write_sysfs_attribute(detach_attr_path, buff, strlen(buff)); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 349 | 	if (ret < 0) { | 
| Valentina Manea | a744b7c | 2014-03-08 14:53:28 +0200 | [diff] [blame] | 350 | 		dbg("write_sysfs_attribute failed"); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 351 | 		return -1; | 
 | 352 | 	} | 
 | 353 |  | 
| matt mooney | 25567a3 | 2011-06-19 22:44:38 -0700 | [diff] [blame] | 354 | 	dbg("detached port: %d", port); | 
| Takahiro Hirofuchi | 0945b4f | 2011-05-14 03:55:07 -0700 | [diff] [blame] | 355 |  | 
 | 356 | 	return 0; | 
 | 357 | } | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 358 |  | 
 | 359 | int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev) | 
 | 360 | { | 
 | 361 | 	char product_name[100]; | 
 | 362 | 	char host[NI_MAXHOST] = "unknown host"; | 
 | 363 | 	char serv[NI_MAXSERV] = "unknown port"; | 
 | 364 | 	char remote_busid[SYSFS_BUS_ID_SIZE]; | 
 | 365 | 	int ret; | 
 | 366 | 	int read_record_error = 0; | 
 | 367 |  | 
 | 368 | 	if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED) | 
 | 369 | 		return 0; | 
 | 370 |  | 
| Mark Asselstine | a37d70e | 2014-02-12 21:47:56 -0500 | [diff] [blame] | 371 | 	ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv), | 
 | 372 | 			  remote_busid); | 
| Valentina Manea | ec2ff62 | 2014-01-07 21:05:56 +0200 | [diff] [blame] | 373 | 	if (ret) { | 
 | 374 | 		err("read_record"); | 
 | 375 | 		read_record_error = 1; | 
 | 376 | 	} | 
 | 377 |  | 
 | 378 | 	printf("Port %02d: <%s> at %s\n", idev->port, | 
 | 379 | 	       usbip_status_string(idev->status), | 
 | 380 | 	       usbip_speed_string(idev->udev.speed)); | 
 | 381 |  | 
 | 382 | 	usbip_names_get_product(product_name, sizeof(product_name), | 
 | 383 | 				idev->udev.idVendor, idev->udev.idProduct); | 
 | 384 |  | 
 | 385 | 	printf("       %s\n",  product_name); | 
 | 386 |  | 
 | 387 | 	if (!read_record_error) { | 
 | 388 | 		printf("%10s -> usbip://%s:%s/%s\n", idev->udev.busid, | 
 | 389 | 		       host, serv, remote_busid); | 
 | 390 | 		printf("%10s -> remote bus/dev %03d/%03d\n", " ", | 
 | 391 | 		       idev->busnum, idev->devnum); | 
 | 392 | 	} else { | 
 | 393 | 		printf("%10s -> unknown host, remote port and remote busid\n", | 
 | 394 | 		       idev->udev.busid); | 
 | 395 | 		printf("%10s -> remote bus/dev %03d/%03d\n", " ", | 
 | 396 | 		       idev->busnum, idev->devnum); | 
 | 397 | 	} | 
 | 398 |  | 
 | 399 | 	return 0; | 
 | 400 | } |