Пример #1
0
/*
 * To start a new USB/IP attachment, a userland program needs to setup a TCP
 * connection and then write its socket descriptor with remote device
 * information into this sysfs file.
 *
 * A remote device is virtually attached to the root-hub port of @rhport with
 * @speed. @devid is embedded into a request to specify the remote device in a
 * server host.
 *
 * write() returns 0 on success, else negative errno.
 */
static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
			    const char *buf, size_t count)
{
	struct vhci_device *vdev;
	struct socket *socket;
	int sockfd = 0;
	__u32 rhport = 0, devid = 0, speed = 0;

	/*
	 * @rhport: port number of vhci_hcd
	 * @sockfd: socket descriptor of an established TCP connection
	 * @devid: unique device identifier in a remote host
	 * @speed: usb device speed in a remote host
	 */
	sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed);

	usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n",
				rhport, sockfd, devid, speed);


	/* check received parameters */
	if (valid_args(rhport, speed) < 0)
		return -EINVAL;

	/* check sockfd */
	socket = sockfd_to_socket(sockfd);
	if (!socket)
		return  -EINVAL;

	/* now need lock until setting vdev status as used */

	/* begin a lock */
	spin_lock(&the_controller->lock);

	vdev = port_to_vdev(rhport);

	spin_lock(&vdev->ud.lock);

	if (vdev->ud.status != VDEV_ST_NULL) {
		/* end of the lock */
		spin_unlock(&vdev->ud.lock);
		spin_unlock(&the_controller->lock);

		usbip_uerr("port %d already used\n", rhport);
		return -EINVAL;
	}

	usbip_uinfo("rhport(%u) sockfd(%d) devid(%u) speed(%u)\n",
				rhport, sockfd, devid, speed);

	vdev->devid         = devid;
	vdev->speed         = speed;
	vdev->ud.tcp_socket = socket;
	vdev->ud.status     = VDEV_ST_NOTASSIGNED;

	wake_up_process(vdev->ud.tcp_rx);
	wake_up_process(vdev->ud.tcp_tx);

	spin_unlock(&vdev->ud.lock);
	spin_unlock(&the_controller->lock);
	/* end the lock */

	rh_port_connect(rhport, speed);

	return count;
}
Пример #2
0
/*
 * To start a new USB/IP attachment, a userland program needs to setup a TCP
 * connection and then write its socket descriptor with remote device
 * information into this sysfs file.
 *
 * A remote device is virtually attached to the root-hub port of @rhport with
 * @speed. @busnum and @devnum are used to convert URBs between a client host
 * and a server host.
 *
 * write() returns 0 on success, else negative errno.
 */
static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	struct vhci_device *vdev;
	struct socket *socket;
	int sockfd = 0;
	__u32 rhport=0, busnum=0, devnum=0, speed=0;


	/*
	 * @rhport: port number of vhci_hcd
	 * @sockfd: socket descriptor of an established TCP connection
	 * @busnum: usb bus number in a remote host
	 * @devnum: usb device number in a remote host
	 * @speed: usb device speed in a remote host
	 */
	sscanf(buf, "%u %u %u %u %u", &rhport, &sockfd, &busnum, &devnum, &speed);

	dbg_vhci_sysfs("rhport(%u) sockfd(%u) busnum(%u) devnum(%u) speed(%u)\n",
			rhport, sockfd, busnum, devnum, speed);


	/* check received parameters */
	if (valid_args(rhport, busnum, devnum, speed) < 0)
		return -EINVAL;

	/* check sockfd */
	socket = sockfd_to_socket(sockfd);
	if (!socket)
		return  -EINVAL;

#if 0
	setnodelay(socket);
#endif

	/* now need lock until setting vdev status as used */

	/* begin a lock */
	spin_lock(&the_controller->lock);

	vdev = port_to_vdev(rhport);

	spin_lock(&vdev->ud.lock);

	if (vdev->ud.status != VDEV_ST_NULL) {
		/* end of the lock */
		spin_unlock(&vdev->ud.lock);
		spin_unlock(&the_controller->lock);

		uerr("port %d already used\n", rhport);
		return -EINVAL;
	}

	uinfo("rhport(%u) sockfd(%d) busnum(%u) devnum(%u) speed(%u)\n",
			rhport, sockfd, busnum, devnum, speed);

	vdev->busnum        = busnum;
	vdev->devnum        = devnum;
	vdev->speed         = speed;
	vdev->ud.tcp_socket = socket;
	vdev->ud.status     = VDEV_ST_NOTASSIGNED;

	spin_unlock(&vdev->ud.lock);
	spin_unlock(&the_controller->lock);
	/* end the lock */

	/*
	 * this function will sleep, so should be out of the lock. but, it's ok
	 * because we already marked vdev as being used. really?
	 */
	usbip_start_threads(&vdev->ud);

	rh_port_connect(rhport, speed);

	return count;
}