/* * 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; }
/* * 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; }