1 /* 2 * Copyright (C) 2015 Karol Kosik <karo9@interia.eu> 3 * Copyright (C) 2015-2016 Samsung Electronics 4 * Igor Kotrasinski <i.kotrasinsk@samsung.com> 5 * Krzysztof Opasiak <k.opasiak@samsung.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include <linux/device.h> 22 #include <linux/list.h> 23 #include <linux/usb/gadget.h> 24 #include <linux/usb/ch9.h> 25 #include <linux/sysfs.h> 26 #include <linux/kthread.h> 27 #include <linux/byteorder/generic.h> 28 29 #include "usbip_common.h" 30 #include "vudc.h" 31 32 #include <net/sock.h> 33 34 /* called with udc->lock held */ 35 int get_gadget_descs(struct vudc *udc) 36 { 37 struct vrequest *usb_req; 38 struct vep *ep0 = to_vep(udc->gadget.ep0); 39 struct usb_device_descriptor *ddesc = &udc->dev_desc; 40 struct usb_ctrlrequest req; 41 int ret; 42 43 if (!udc || !udc->driver || !udc->pullup) 44 return -EINVAL; 45 46 req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; 47 req.bRequest = USB_REQ_GET_DESCRIPTOR; 48 req.wValue = cpu_to_le16(USB_DT_DEVICE << 8); 49 req.wIndex = cpu_to_le16(0); 50 req.wLength = cpu_to_le16(sizeof(*ddesc)); 51 52 spin_unlock(&udc->lock); 53 ret = udc->driver->setup(&(udc->gadget), &req); 54 spin_lock(&udc->lock); 55 if (ret < 0) 56 goto out; 57 58 /* assuming request queue is empty; request is now on top */ 59 usb_req = list_last_entry(&ep0->req_queue, struct vrequest, req_entry); 60 list_del(&usb_req->req_entry); 61 62 if (usb_req->req.length > sizeof(*ddesc)) { 63 ret = -EOVERFLOW; 64 goto giveback_req; 65 } 66 67 memcpy(ddesc, usb_req->req.buf, sizeof(*ddesc)); 68 udc->desc_cached = 1; 69 ret = 0; 70 giveback_req: 71 usb_req->req.status = 0; 72 usb_req->req.actual = usb_req->req.length; 73 usb_gadget_giveback_request(&(ep0->ep), &(usb_req->req)); 74 out: 75 return ret; 76 } 77 78 /* 79 * Exposes device descriptor from the gadget driver. 80 */ 81 static ssize_t dev_desc_read(struct file *file, struct kobject *kobj, 82 struct bin_attribute *attr, char *out, 83 loff_t off, size_t count) 84 { 85 struct device *dev = kobj_to_dev(kobj); 86 struct vudc *udc = (struct vudc *)dev_get_drvdata(dev); 87 char *desc_ptr = (char *) &udc->dev_desc; 88 unsigned long flags; 89 int ret; 90 91 spin_lock_irqsave(&udc->lock, flags); 92 if (!udc->desc_cached) { 93 ret = -ENODEV; 94 goto unlock; 95 } 96 97 memcpy(out, desc_ptr + off, count); 98 ret = count; 99 unlock: 100 spin_unlock_irqrestore(&udc->lock, flags); 101 return ret; 102 } 103 static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor)); 104 105 static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr, 106 const char *in, size_t count) 107 { 108 struct vudc *udc = (struct vudc *) dev_get_drvdata(dev); 109 int rv; 110 int sockfd = 0; 111 int err; 112 struct socket *socket; 113 unsigned long flags; 114 int ret; 115 116 rv = kstrtoint(in, 0, &sockfd); 117 if (rv != 0) 118 return -EINVAL; 119 120 spin_lock_irqsave(&udc->lock, flags); 121 /* Don't export what we don't have */ 122 if (!udc || !udc->driver || !udc->pullup) { 123 dev_err(dev, "no device or gadget not bound"); 124 ret = -ENODEV; 125 goto unlock; 126 } 127 128 if (sockfd != -1) { 129 if (udc->connected) { 130 dev_err(dev, "Device already connected"); 131 ret = -EBUSY; 132 goto unlock; 133 } 134 135 spin_lock_irq(&udc->ud.lock); 136 137 if (udc->ud.status != SDEV_ST_AVAILABLE) { 138 ret = -EINVAL; 139 goto unlock_ud; 140 } 141 142 socket = sockfd_lookup(sockfd, &err); 143 if (!socket) { 144 dev_err(dev, "failed to lookup sock"); 145 ret = -EINVAL; 146 goto unlock_ud; 147 } 148 149 udc->ud.tcp_socket = socket; 150 151 spin_unlock_irq(&udc->ud.lock); 152 spin_unlock_irqrestore(&udc->lock, flags); 153 154 udc->ud.tcp_rx = kthread_get_run(&v_rx_loop, 155 &udc->ud, "vudc_rx"); 156 udc->ud.tcp_tx = kthread_get_run(&v_tx_loop, 157 &udc->ud, "vudc_tx"); 158 159 spin_lock_irqsave(&udc->lock, flags); 160 spin_lock_irq(&udc->ud.lock); 161 udc->ud.status = SDEV_ST_USED; 162 spin_unlock_irq(&udc->ud.lock); 163 164 do_gettimeofday(&udc->start_time); 165 v_start_timer(udc); 166 udc->connected = 1; 167 } else { 168 if (!udc->connected) { 169 dev_err(dev, "Device not connected"); 170 ret = -EINVAL; 171 goto unlock; 172 } 173 174 spin_lock_irq(&udc->ud.lock); 175 if (udc->ud.status != SDEV_ST_USED) { 176 ret = -EINVAL; 177 goto unlock_ud; 178 } 179 spin_unlock_irq(&udc->ud.lock); 180 181 usbip_event_add(&udc->ud, VUDC_EVENT_DOWN); 182 } 183 184 spin_unlock_irqrestore(&udc->lock, flags); 185 186 return count; 187 188 unlock_ud: 189 spin_unlock_irq(&udc->ud.lock); 190 unlock: 191 spin_unlock_irqrestore(&udc->lock, flags); 192 193 return ret; 194 } 195 static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd); 196 197 static ssize_t usbip_status_show(struct device *dev, 198 struct device_attribute *attr, char *out) 199 { 200 struct vudc *udc = (struct vudc *) dev_get_drvdata(dev); 201 int status; 202 203 if (!udc) { 204 dev_err(dev, "no device"); 205 return -ENODEV; 206 } 207 spin_lock_irq(&udc->ud.lock); 208 status = udc->ud.status; 209 spin_unlock_irq(&udc->ud.lock); 210 211 return snprintf(out, PAGE_SIZE, "%d\n", status); 212 } 213 static DEVICE_ATTR_RO(usbip_status); 214 215 static struct attribute *dev_attrs[] = { 216 &dev_attr_usbip_sockfd.attr, 217 &dev_attr_usbip_status.attr, 218 NULL, 219 }; 220 221 static struct bin_attribute *dev_bin_attrs[] = { 222 &bin_attr_dev_desc, 223 NULL, 224 }; 225 226 const struct attribute_group vudc_attr_group = { 227 .attrs = dev_attrs, 228 .bin_attrs = dev_bin_attrs, 229 }; 230