Pull USB fixes from Greg KH: "Here are a number of USB fixes for 5.7-rc6 The "largest" in here is a bunch of raw-gadget fixes and api changes as the driver just showed up in -rc1 and work has been done to fix up some uapi issues found with the original submission, before it shows up in a -final release. Other than that, a bunch of other small USB gadget fixes, xhci fixes, some quirks, andother tiny fixes for reported issues. All of these have been in linux-next with no reported issues" * tag 'usb-5.7-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (26 commits) USB: gadget: fix illegal array access in binding with UDC usb: core: hub: limit HUB_QUIRK_DISABLE_AUTOSUSPEND to USB5534B USB: usbfs: fix mmap dma mismatch usb: host: xhci-plat: keep runtime active when removing host usb: xhci: Fix NULL pointer dereference when enqueuing trbs from urb sg list usb: cdns3: gadget: make a bunch of functions static usb: mtu3: constify struct debugfs_reg32 usb: gadget: udc: atmel: Make some symbols static usb: raw-gadget: fix null-ptr-deref when reenabling endpoints usb: raw-gadget: documentation updates usb: raw-gadget: support stalling/halting/wedging endpoints usb: raw-gadget: fix gadget endpoint selection usb: raw-gadget: improve uapi headers comments usb: typec: mux: intel: Fix DP_HPD_LVL bit field usb: raw-gadget: fix return value of ep read ioctls usb: dwc3: select USB_ROLE_SWITCH usb: gadget: legacy: fix error return code in gncm_bind() usb: gadget: legacy: fix error return code in cdc_bind() usb: gadget: legacy: fix redundant initialization warnings usb: gadget: tegra-xudc: Fix idle suspend/resume ...
Unified · Split
| @@ -27,9 +27,8 @@ differences are: · 26 unmodified lines | |||
| 27 | 3. Raw Gadget provides a way to select a UDC device/driver to bind to, | 27 | 3. Raw Gadget provides a way to select a UDC device/driver to bind to, |
| 28 | while GadgetFS currently binds to the first available UDC. | 28 | while GadgetFS currently binds to the first available UDC. |
| 29 | 29 | ||
| 30 | 4. Raw Gadget uses predictable endpoint names (handles) across different | 30 | 4. Raw Gadget explicitly exposes information about endpoints addresses and |
| 31 | UDCs (as long as UDCs have enough endpoints of each required transfer | 31 | capabilities allowing a user to write UDC-agnostic gadgets. |
| 32 | type). | ||
| 33 | 32 | ||
| 34 | 5. Raw Gadget has ioctl-based interface instead of a filesystem-based one. | 33 | 5. Raw Gadget has ioctl-based interface instead of a filesystem-based one. |
| 35 | 34 | ||
| @@ -50,12 +49,36 @@ The typical usage of Raw Gadget looks like: · 14 unmodified lines | |||
| 50 | Raw Gadget and react to those depending on what kind of USB device | 49 | Raw Gadget and react to those depending on what kind of USB device |
| 51 | needs to be emulated. | 50 | needs to be emulated. |
| 52 | 51 | ||
| 52 | Note, that some UDC drivers have fixed addresses assigned to endpoints, and | ||
| 53 | therefore arbitrary endpoint addresses can't be used in the descriptors. | ||
| 54 | Nevertheles, Raw Gadget provides a UDC-agnostic way to write USB gadgets. | ||
| 55 | Once a USB_RAW_EVENT_CONNECT event is received via USB_RAW_IOCTL_EVENT_FETCH, | ||
| 56 | the USB_RAW_IOCTL_EPS_INFO ioctl can be used to find out information about | ||
| 57 | endpoints that the UDC driver has. Based on that information, the user must | ||
| 58 | chose UDC endpoints that will be used for the gadget being emulated, and | ||
| 59 | properly assign addresses in endpoint descriptors. | ||
| 60 | |||
| 61 | You can find usage examples (along with a test suite) here: | ||
| 62 | |||
| 63 | https://github.com/xairy/raw-gadget | ||
| 64 | |||
| 65 | Internal details | ||
| 66 | ~~~~~~~~~~~~~~~~ | ||
| 67 | |||
| 68 | Currently every endpoint read/write ioctl submits a USB request and waits until | ||
| 69 | its completion. This is the desired mode for coverage-guided fuzzing (as we'd | ||
| 70 | like all USB request processing happen during the lifetime of a syscall), | ||
| 71 | and must be kept in the implementation. (This might be slow for real world | ||
| 72 | applications, thus the O_NONBLOCK improvement suggestion below.) | ||
| 73 | |||
| 53 | Potential future improvements | 74 | Potential future improvements |
| 54 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 75 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 55 | 76 | ||
| 56 | - Implement ioctl's for setting/clearing halt status on endpoints. | 77 | - Report more events (suspend, resume, etc.) through USB_RAW_IOCTL_EVENT_FETCH. |
| 57 | |||
| 58 | - Reporting more events (suspend, resume, etc.) through | ||
| 59 | USB_RAW_IOCTL_EVENT_FETCH. | ||
| 60 | 78 | ||
| 61 | - Support O_NONBLOCK I/O. | 79 | - Support O_NONBLOCK I/O. |
| 80 | |||
| 81 | - Support USB 3 features (accept SS endpoint companion descriptor when | ||
| 82 | enabling endpoints; allow providing stream_id for bulk transfers). | ||
| 83 | |||
| 84 | - Support ISO transfer features (expose frame_number for completed requests). | ||
| @@ -82,7 +82,7 @@ static int cdns3_ep_run_stream_transfer(struct cdns3_endpoint *priv_ep, · 81 unmodified lines | |||
| 82 | * @ptr: address of device controller register to be read and changed | 82 | * @ptr: address of device controller register to be read and changed |
| 83 | * @mask: bits requested to clar | 83 | * @mask: bits requested to clar |
| 84 | */ | 84 | */ |
| 85 | void cdns3_clear_register_bit(void __iomem *ptr, u32 mask) | 85 | static void cdns3_clear_register_bit(void __iomem *ptr, u32 mask) |
| 86 | { | 86 | { |
| 87 | mask = readl(ptr) & ~mask; | 87 | mask = readl(ptr) & ~mask; |
| 88 | writel(mask, ptr); | 88 | writel(mask, ptr); |
| @@ -137,7 +137,7 @@ struct usb_request *cdns3_next_request(struct list_head *list) · 48 unmodified lines | |||
| 137 | * | 137 | * |
| 138 | * Returns buffer or NULL if no buffers in list | 138 | * Returns buffer or NULL if no buffers in list |
| 139 | */ | 139 | */ |
| 140 | struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list) | 140 | static struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list) |
| 141 | { | 141 | { |
| 142 | return list_first_entry_or_null(list, struct cdns3_aligned_buf, list); | 142 | return list_first_entry_or_null(list, struct cdns3_aligned_buf, list); |
| 143 | } | 143 | } |
| @@ -148,7 +148,7 @@ struct cdns3_aligned_buf *cdns3_next_align_buf(struct list_head *list) · 4 unmodified lines | |||
| 148 | * | 148 | * |
| 149 | * Returns request or NULL if no requests in list | 149 | * Returns request or NULL if no requests in list |
| 150 | */ | 150 | */ |
| 151 | struct cdns3_request *cdns3_next_priv_request(struct list_head *list) | 151 | static struct cdns3_request *cdns3_next_priv_request(struct list_head *list) |
| 152 | { | 152 | { |
| 153 | return list_first_entry_or_null(list, struct cdns3_request, list); | 153 | return list_first_entry_or_null(list, struct cdns3_request, list); |
| 154 | } | 154 | } |
| @@ -190,7 +190,7 @@ dma_addr_t cdns3_trb_virt_to_dma(struct cdns3_endpoint *priv_ep, · 35 unmodified lines | |||
| 190 | return priv_ep->trb_pool_dma + offset; | 190 | return priv_ep->trb_pool_dma + offset; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | int cdns3_ring_size(struct cdns3_endpoint *priv_ep) | 193 | static int cdns3_ring_size(struct cdns3_endpoint *priv_ep) |
| 194 | { | 194 | { |
| 195 | switch (priv_ep->type) { | 195 | switch (priv_ep->type) { |
| 196 | case USB_ENDPOINT_XFER_ISOC: | 196 | case USB_ENDPOINT_XFER_ISOC: |
| @@ -345,7 +345,7 @@ static void cdns3_ep_inc_deq(struct cdns3_endpoint *priv_ep) · 148 unmodified lines | |||
| 345 | cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs); | 345 | cdns3_ep_inc_trb(&priv_ep->dequeue, &priv_ep->ccs, priv_ep->num_trbs); |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req) | 348 | static void cdns3_move_deq_to_next_trb(struct cdns3_request *priv_req) |
| 349 | { | 349 | { |
| 350 | struct cdns3_endpoint *priv_ep = priv_req->priv_ep; | 350 | struct cdns3_endpoint *priv_ep = priv_req->priv_ep; |
| 351 | int current_trb = priv_req->start_trb; | 351 | int current_trb = priv_req->start_trb; |
| @@ -511,7 +511,7 @@ static void cdns3_wa2_descmiss_copy_data(struct cdns3_endpoint *priv_ep, · 159 unmodified lines | |||
| 511 | } | 511 | } |
| 512 | } | 512 | } |
| 513 | 513 | ||
| 514 | struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev, | 514 | static struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev, |
| 515 | struct cdns3_endpoint *priv_ep, | 515 | struct cdns3_endpoint *priv_ep, |
| 516 | struct cdns3_request *priv_req) | 516 | struct cdns3_request *priv_req) |
| 517 | { | 517 | { |
| @@ -551,7 +551,7 @@ struct usb_request *cdns3_wa2_gadget_giveback(struct cdns3_device *priv_dev, · 33 unmodified lines | |||
| 551 | return &priv_req->request; | 551 | return &priv_req->request; |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | int cdns3_wa2_gadget_ep_queue(struct cdns3_device *priv_dev, | 554 | static int cdns3_wa2_gadget_ep_queue(struct cdns3_device *priv_dev, |
| 555 | struct cdns3_endpoint *priv_ep, | 555 | struct cdns3_endpoint *priv_ep, |
| 556 | struct cdns3_request *priv_req) | 556 | struct cdns3_request *priv_req) |
| 557 | { | 557 | { |
| @@ -836,7 +836,7 @@ void cdns3_gadget_giveback(struct cdns3_endpoint *priv_ep, · 278 unmodified lines | |||
| 836 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, request); | 836 | cdns3_gadget_ep_free_request(&priv_ep->endpoint, request); |
| 837 | } | 837 | } |
| 838 | 838 | ||
| 839 | void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep) | 839 | static void cdns3_wa1_restore_cycle_bit(struct cdns3_endpoint *priv_ep) |
| 840 | { | 840 | { |
| 841 | /* Work around for stale data address in TRB*/ | 841 | /* Work around for stale data address in TRB*/ |
| 842 | if (priv_ep->wa1_set) { | 842 | if (priv_ep->wa1_set) { |
| @@ -1904,7 +1904,7 @@ static int cdns3_ep_onchip_buffer_reserve(struct cdns3_device *priv_dev, · 1061 unmodified lines | |||
| 1904 | return 0; | 1904 | return 0; |
| 1905 | } | 1905 | } |
| 1906 | 1906 | ||
| 1907 | void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev, | 1907 | static void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev, |
| 1908 | struct cdns3_endpoint *priv_ep) | 1908 | struct cdns3_endpoint *priv_ep) |
| 1909 | { | 1909 | { |
| 1910 | if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER) | 1910 | if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER) |
| @@ -1925,7 +1925,7 @@ void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev, · 14 unmodified lines | |||
| 1925 | EP_CFG_TDL_CHK | EP_CFG_SID_CHK); | 1925 | EP_CFG_TDL_CHK | EP_CFG_SID_CHK); |
| 1926 | } | 1926 | } |
| 1927 | 1927 | ||
| 1928 | void cdns3_configure_dmult(struct cdns3_device *priv_dev, | 1928 | static void cdns3_configure_dmult(struct cdns3_device *priv_dev, |
| 1929 | struct cdns3_endpoint *priv_ep) | 1929 | struct cdns3_endpoint *priv_ep) |
| 1930 | { | 1930 | { |
| 1931 | struct cdns3_usb_regs __iomem *regs = priv_dev->regs; | 1931 | struct cdns3_usb_regs __iomem *regs = priv_dev->regs; |
| @@ -2548,7 +2548,7 @@ found: · 616 unmodified lines | |||
| 2548 | link_trb = priv_req->trb; | 2548 | link_trb = priv_req->trb; |
| 2549 | 2549 | ||
| 2550 | /* Update ring only if removed request is on pending_req_list list */ | 2550 | /* Update ring only if removed request is on pending_req_list list */ |
| 2551 | if (req_on_hw_ring) { | 2551 | if (req_on_hw_ring && link_trb) { |
| 2552 | link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma + | 2552 | link_trb->buffer = TRB_BUFFER(priv_ep->trb_pool_dma + |
| 2553 | ((priv_req->end_trb + 1) * TRB_SIZE)); | 2553 | ((priv_req->end_trb + 1) * TRB_SIZE)); |
| 2554 | link_trb->control = (link_trb->control & TRB_CYCLE) | | 2554 | link_trb->control = (link_trb->control & TRB_CYCLE) | |
| @@ -251,9 +251,19 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma) · 250 unmodified lines | |||
| 251 | usbm->vma_use_count = 1; | 251 | usbm->vma_use_count = 1; |
| 252 | INIT_LIST_HEAD(&usbm->memlist); | 252 | INIT_LIST_HEAD(&usbm->memlist); |
| 253 | 253 | ||
| 254 | if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle, size)) { | 254 | if (hcd->localmem_pool || !hcd_uses_dma(hcd)) { |
| 255 | dec_usb_memory_use_count(usbm, &usbm->vma_use_count); | 255 | if (remap_pfn_range(vma, vma->vm_start, |
| 256 | return -EAGAIN; | 256 | virt_to_phys(usbm->mem) >> PAGE_SHIFT, |
| 257 | size, vma->vm_page_prot) < 0) { | ||
| 258 | dec_usb_memory_use_count(usbm, &usbm->vma_use_count); | ||
| 259 | return -EAGAIN; | ||
| 260 | } | ||
| 261 | } else { | ||
| 262 | if (dma_mmap_coherent(hcd->self.sysdev, vma, mem, dma_handle, | ||
| 263 | size)) { | ||
| 264 | dec_usb_memory_use_count(usbm, &usbm->vma_use_count); | ||
| 265 | return -EAGAIN; | ||
| 266 | } | ||
| 257 | } | 267 | } |
| 258 | 268 | ||
| 259 | vma->vm_flags |= VM_IO; | 269 | vma->vm_flags |= VM_IO; |
| @@ -39,6 +39,7 @@ · 38 unmodified lines | |||
| 39 | 39 | ||
| 40 | #define USB_VENDOR_GENESYS_LOGIC 0x05e3 | 40 | #define USB_VENDOR_GENESYS_LOGIC 0x05e3 |
| 41 | #define USB_VENDOR_SMSC 0x0424 | 41 | #define USB_VENDOR_SMSC 0x0424 |
| 42 | #define USB_PRODUCT_USB5534B 0x5534 | ||
| 42 | #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 | 43 | #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 |
| 43 | #define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02 | 44 | #define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02 |
| 44 | 45 | ||
| @@ -5621,8 +5622,11 @@ out_hdev_lock: · 5576 unmodified lines | |||
| 5621 | } | 5622 | } |
| 5622 | 5623 | ||
| 5623 | static const struct usb_device_id hub_id_table[] = { | 5624 | static const struct usb_device_id hub_id_table[] = { |
| 5624 | { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS, | 5625 | { .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
| 5626 | | USB_DEVICE_ID_MATCH_PRODUCT | ||
| 5627 | | USB_DEVICE_ID_MATCH_INT_CLASS, | ||
| 5625 | .idVendor = USB_VENDOR_SMSC, | 5628 | .idVendor = USB_VENDOR_SMSC, |
| 5629 | .idProduct = USB_PRODUCT_USB5534B, | ||
| 5626 | .bInterfaceClass = USB_CLASS_HUB, | 5630 | .bInterfaceClass = USB_CLASS_HUB, |
| 5627 | .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, | 5631 | .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND}, |
| 5628 | { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | 5632 | { .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
| @@ -4,6 +4,7 @@ config USB_DWC3 · 3 unmodified lines | |||
| 4 | tristate "DesignWare USB3 DRD Core Support" | 4 | tristate "DesignWare USB3 DRD Core Support" |
| 5 | depends on (USB || USB_GADGET) && HAS_DMA | 5 | depends on (USB || USB_GADGET) && HAS_DMA |
| 6 | select USB_XHCI_PLATFORM if USB_XHCI_HCD | 6 | select USB_XHCI_PLATFORM if USB_XHCI_HCD |
| 7 | select USB_ROLE_SWITCH if USB_DWC3_DUAL_ROLE | ||
| 7 | help | 8 | help |
| 8 | Say Y or M here if your system has a Dual Role SuperSpeed | 9 | Say Y or M here if your system has a Dual Role SuperSpeed |
| 9 | USB controller based on the DesignWare USB3 IP Core. | 10 | USB controller based on the DesignWare USB3 IP Core. |
| @@ -114,6 +114,7 @@ static const struct property_entry dwc3_pci_intel_properties[] = { · 113 unmodified lines | |||
| 114 | 114 | ||
| 115 | static const struct property_entry dwc3_pci_mrfld_properties[] = { | 115 | static const struct property_entry dwc3_pci_mrfld_properties[] = { |
| 116 | PROPERTY_ENTRY_STRING("dr_mode", "otg"), | 116 | PROPERTY_ENTRY_STRING("dr_mode", "otg"), |
| 117 | PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"), | ||
| 117 | PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), | 118 | PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), |
| 118 | {} | 119 | {} |
| 119 | }; | 120 | }; |
| @@ -2483,9 +2483,6 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep, · 2482 unmodified lines | |||
| 2483 | for_each_sg(sg, s, pending, i) { | 2483 | for_each_sg(sg, s, pending, i) { |
| 2484 | trb = &dep->trb_pool[dep->trb_dequeue]; | 2484 | trb = &dep->trb_pool[dep->trb_dequeue]; |
| 2485 | 2485 | ||
| 2486 | if (trb->ctrl & DWC3_TRB_CTRL_HWO) | ||
| 2487 | break; | ||
| 2488 | |||
| 2489 | req->sg = sg_next(s); | 2486 | req->sg = sg_next(s); |
| 2490 | req->num_pending_sgs--; | 2487 | req->num_pending_sgs--; |
| 2491 | 2488 | ||
| @@ -260,6 +260,9 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, · 259 unmodified lines | |||
| 260 | char *name; | 260 | char *name; |
| 261 | int ret; | 261 | int ret; |
| 262 | 262 | ||
| 263 | if (strlen(page) < len) | ||
| 264 | return -EOVERFLOW; | ||
| 265 | |||
| 263 | name = kstrdup(page, GFP_KERNEL); | 266 | name = kstrdup(page, GFP_KERNEL); |
| 264 | if (!name) | 267 | if (!name) |
| 265 | return -ENOMEM; | 268 | return -ENOMEM; |
| @@ -300,8 +300,10 @@ static int audio_bind(struct usb_composite_dev *cdev) · 299 unmodified lines | |||
| 300 | struct usb_descriptor_header *usb_desc; | 300 | struct usb_descriptor_header *usb_desc; |
| 301 | 301 | ||
| 302 | usb_desc = usb_otg_descriptor_alloc(cdev->gadget); | 302 | usb_desc = usb_otg_descriptor_alloc(cdev->gadget); |
| 303 | if (!usb_desc) | 303 | if (!usb_desc) { |
| 304 | status = -ENOMEM; | ||
| 304 | goto fail; | 305 | goto fail; |
| 306 | } | ||
| 305 | usb_otg_descriptor_init(cdev->gadget, usb_desc); | 307 | usb_otg_descriptor_init(cdev->gadget, usb_desc); |
| 306 | otg_desc[0] = usb_desc; | 308 | otg_desc[0] = usb_desc; |
| 307 | otg_desc[1] = NULL; | 309 | otg_desc[1] = NULL; |
| @@ -179,8 +179,10 @@ static int cdc_bind(struct usb_composite_dev *cdev) · 178 unmodified lines | |||
| 179 | struct usb_descriptor_header *usb_desc; | 179 | struct usb_descriptor_header *usb_desc; |
| 180 | 180 | ||
| 181 | usb_desc = usb_otg_descriptor_alloc(gadget); | 181 | usb_desc = usb_otg_descriptor_alloc(gadget); |
| 182 | if (!usb_desc) | 182 | if (!usb_desc) { |
| 183 | status = -ENOMEM; | ||
| 183 | goto fail1; | 184 | goto fail1; |
| 185 | } | ||
| 184 | usb_otg_descriptor_init(gadget, usb_desc); | 186 | usb_otg_descriptor_init(gadget, usb_desc); |
| 185 | otg_desc[0] = usb_desc; | 187 | otg_desc[0] = usb_desc; |
| 186 | otg_desc[1] = NULL; | 188 | otg_desc[1] = NULL; |
| @@ -1361,7 +1361,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) · 1360 unmodified lines | |||
| 1361 | 1361 | ||
| 1362 | req->buf = dev->rbuf; | 1362 | req->buf = dev->rbuf; |
| 1363 | req->context = NULL; | 1363 | req->context = NULL; |
| 1364 | value = -EOPNOTSUPP; | ||
| 1365 | switch (ctrl->bRequest) { | 1364 | switch (ctrl->bRequest) { |
| 1366 | 1365 | ||
| 1367 | case USB_REQ_GET_DESCRIPTOR: | 1366 | case USB_REQ_GET_DESCRIPTOR: |
| @@ -1784,7 +1783,7 @@ static ssize_t · 416 unmodified lines | |||
| 1784 | dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | 1783 | dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) |
| 1785 | { | 1784 | { |
| 1786 | struct dev_data *dev = fd->private_data; | 1785 | struct dev_data *dev = fd->private_data; |
| 1787 | ssize_t value = len, length = len; | 1786 | ssize_t value, length = len; |
| 1788 | unsigned total; | 1787 | unsigned total; |
| 1789 | u32 tag; | 1788 | u32 tag; |
| 1790 | char *kbuf; | 1789 | char *kbuf; |
| @@ -156,8 +156,10 @@ static int gncm_bind(struct usb_composite_dev *cdev) · 155 unmodified lines | |||
| 156 | struct usb_descriptor_header *usb_desc; | 156 | struct usb_descriptor_header *usb_desc; |
| 157 | 157 | ||
| 158 | usb_desc = usb_otg_descriptor_alloc(gadget); | 158 | usb_desc = usb_otg_descriptor_alloc(gadget); |
| 159 | if (!usb_desc) | 159 | if (!usb_desc) { |
| 160 | status = -ENOMEM; | ||
| 160 | goto fail; | 161 | goto fail; |
| 162 | } | ||
| 161 | usb_otg_descriptor_init(gadget, usb_desc); | 163 | usb_otg_descriptor_init(gadget, usb_desc); |
| 162 | otg_desc[0] = usb_desc; | 164 | otg_desc[0] = usb_desc; |
| 163 | otg_desc[1] = NULL; | 165 | otg_desc[1] = NULL; |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/compiler.h> | 9 | #include <linux/compiler.h> |
| 10 | #include <linux/ctype.h> | ||
| 10 | #include <linux/debugfs.h> | 11 | #include <linux/debugfs.h> |
| 11 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 12 | #include <linux/kref.h> | 13 | #include <linux/kref.h> |
| @@ -123,8 +124,6 @@ static void raw_event_queue_destroy(struct raw_event_queue *queue) · 110 unmodified lines | |||
| 123 | 124 | ||
| 124 | struct raw_dev; | 125 | struct raw_dev; |
| 125 | 126 | ||
| 126 | #define USB_RAW_MAX_ENDPOINTS 32 | ||
| 127 | |||
| 128 | enum ep_state { | 127 | enum ep_state { |
| 129 | STATE_EP_DISABLED, | 128 | STATE_EP_DISABLED, |
| 130 | STATE_EP_ENABLED, | 129 | STATE_EP_ENABLED, |
| @@ -134,6 +133,7 @@ struct raw_ep { · 3 unmodified lines | |||
| 134 | struct raw_dev *dev; | 133 | struct raw_dev *dev; |
| 135 | enum ep_state state; | 134 | enum ep_state state; |
| 136 | struct usb_ep *ep; | 135 | struct usb_ep *ep; |
| 136 | u8 addr; | ||
| 137 | struct usb_request *req; | 137 | struct usb_request *req; |
| 138 | bool urb_queued; | 138 | bool urb_queued; |
| 139 | bool disabling; | 139 | bool disabling; |
| @@ -168,7 +168,8 @@ struct raw_dev { · 28 unmodified lines | |||
| 168 | bool ep0_out_pending; | 168 | bool ep0_out_pending; |
| 169 | bool ep0_urb_queued; | 169 | bool ep0_urb_queued; |
| 170 | ssize_t ep0_status; | 170 | ssize_t ep0_status; |
| 171 | struct raw_ep eps[USB_RAW_MAX_ENDPOINTS]; | 171 | struct raw_ep eps[USB_RAW_EPS_NUM_MAX]; |
| 172 | int eps_num; | ||
| 172 | 173 | ||
| 173 | struct completion ep0_done; | 174 | struct completion ep0_done; |
| 174 | struct raw_event_queue queue; | 175 | struct raw_event_queue queue; |
| @@ -202,8 +203,8 @@ static void dev_free(struct kref *kref) · 27 unmodified lines | |||
| 202 | usb_ep_free_request(dev->gadget->ep0, dev->req); | 203 | usb_ep_free_request(dev->gadget->ep0, dev->req); |
| 203 | } | 204 | } |
| 204 | raw_event_queue_destroy(&dev->queue); | 205 | raw_event_queue_destroy(&dev->queue); |
| 205 | for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) { | 206 | for (i = 0; i < dev->eps_num; i++) { |
| 206 | if (dev->eps[i].state != STATE_EP_ENABLED) | 207 | if (dev->eps[i].state == STATE_EP_DISABLED) |
| 207 | continue; | 208 | continue; |
| 208 | usb_ep_disable(dev->eps[i].ep); | 209 | usb_ep_disable(dev->eps[i].ep); |
| 209 | usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); | 210 | usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); |
| @@ -249,12 +250,26 @@ static void gadget_ep0_complete(struct usb_ep *ep, struct usb_request *req) · 39 unmodified lines | |||
| 249 | complete(&dev->ep0_done); | 250 | complete(&dev->ep0_done); |
| 250 | } | 251 | } |
| 251 | 252 | ||
| 253 | static u8 get_ep_addr(const char *name) | ||
| 254 | { | ||
| 255 | /* If the endpoint has fixed function (named as e.g. "ep12out-bulk"), | ||
| 256 | * parse the endpoint address from its name. We deliberately use | ||
| 257 | * deprecated simple_strtoul() function here, as the number isn't | ||
| 258 | * followed by '\0' nor '\n'. | ||
| 259 | */ | ||
| 260 | if (isdigit(name[2])) | ||
| 261 | return simple_strtoul(&name[2], NULL, 10); | ||
| 262 | /* Otherwise the endpoint is configurable (named as e.g. "ep-a"). */ | ||
| 263 | return USB_RAW_EP_ADDR_ANY; | ||
| 264 | } | ||
| 265 | |||
| 252 | static int gadget_bind(struct usb_gadget *gadget, | 266 | static int gadget_bind(struct usb_gadget *gadget, |
| 253 | struct usb_gadget_driver *driver) | 267 | struct usb_gadget_driver *driver) |
| 254 | { | 268 | { |
| 255 | int ret = 0; | 269 | int ret = 0, i = 0; |
| 256 | struct raw_dev *dev = container_of(driver, struct raw_dev, driver); | 270 | struct raw_dev *dev = container_of(driver, struct raw_dev, driver); |
| 257 | struct usb_request *req; | 271 | struct usb_request *req; |
| 272 | struct usb_ep *ep; | ||
| 258 | unsigned long flags; | 273 | unsigned long flags; |
| 259 | 274 | ||
| 260 | if (strcmp(gadget->name, dev->udc_name) != 0) | 275 | if (strcmp(gadget->name, dev->udc_name) != 0) |
| @@ -273,6 +288,13 @@ static int gadget_bind(struct usb_gadget *gadget, · 12 unmodified lines | |||
| 273 | dev->req->context = dev; | 288 | dev->req->context = dev; |
| 274 | dev->req->complete = gadget_ep0_complete; | 289 | dev->req->complete = gadget_ep0_complete; |
| 275 | dev->gadget = gadget; | 290 | dev->gadget = gadget; |
| 291 | gadget_for_each_ep(ep, dev->gadget) { | ||
| 292 | dev->eps[i].ep = ep; | ||
| 293 | dev->eps[i].addr = get_ep_addr(ep->name); | ||
| 294 | dev->eps[i].state = STATE_EP_DISABLED; | ||
| 295 | i++; | ||
| 296 | } | ||
| 297 | dev->eps_num = i; | ||
| 276 | spin_unlock_irqrestore(&dev->lock, flags); | 298 | spin_unlock_irqrestore(&dev->lock, flags); |
| 277 | 299 | ||
| 278 | /* Matches kref_put() in gadget_unbind(). */ | 300 | /* Matches kref_put() in gadget_unbind(). */ |
| @@ -555,7 +577,7 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr, · 276 unmodified lines | |||
| 555 | 577 | ||
| 556 | if (copy_from_user(io, ptr, sizeof(*io))) | 578 | if (copy_from_user(io, ptr, sizeof(*io))) |
| 557 | return ERR_PTR(-EFAULT); | 579 | return ERR_PTR(-EFAULT); |
| 558 | if (io->ep >= USB_RAW_MAX_ENDPOINTS) | 580 | if (io->ep >= USB_RAW_EPS_NUM_MAX) |
| 559 | return ERR_PTR(-EINVAL); | 581 | return ERR_PTR(-EINVAL); |
| 560 | if (!usb_raw_io_flags_valid(io->flags)) | 582 | if (!usb_raw_io_flags_valid(io->flags)) |
| 561 | return ERR_PTR(-EINVAL); | 583 | return ERR_PTR(-EINVAL); |
| @@ -669,43 +691,61 @@ static int raw_ioctl_ep0_read(struct raw_dev *dev, unsigned long value) · 107 unmodified lines | |||
| 669 | if (IS_ERR(data)) | 691 | if (IS_ERR(data)) |
| 670 | return PTR_ERR(data); | 692 | return PTR_ERR(data); |
| 671 | ret = raw_process_ep0_io(dev, &io, data, false); | 693 | ret = raw_process_ep0_io(dev, &io, data, false); |
| 672 | if (ret) | 694 | if (ret < 0) |
| 673 | goto free; | 695 | goto free; |
| 674 | 696 | ||
| 675 | length = min(io.length, (unsigned int)ret); | 697 | length = min(io.length, (unsigned int)ret); |
| 676 | if (copy_to_user((void __user *)(value + sizeof(io)), data, length)) | 698 | if (copy_to_user((void __user *)(value + sizeof(io)), data, length)) |
| 677 | ret = -EFAULT; | 699 | ret = -EFAULT; |
| 700 | else | ||
| 701 | ret = length; | ||
| 678 | free: | 702 | free: |
| 679 | kfree(data); | 703 | kfree(data); |
| 680 | return ret; | 704 | return ret; |
| 681 | } | 705 | } |
| 682 | 706 | ||
| 683 | static bool check_ep_caps(struct usb_ep *ep, | 707 | static int raw_ioctl_ep0_stall(struct raw_dev *dev, unsigned long value) |
| 684 | struct usb_endpoint_descriptor *desc) | ||
| 685 | { | 708 | { |
| 686 | switch (usb_endpoint_type(desc)) { | 709 | int ret = 0; |
| 687 | case USB_ENDPOINT_XFER_ISOC: | 710 | unsigned long flags; |
| 688 | if (!ep->caps.type_iso) | 711 | |
| 689 | return false; | 712 | if (value) |
| 690 | break; | 713 | return -EINVAL; |
| 691 | case USB_ENDPOINT_XFER_BULK: | 714 | spin_lock_irqsave(&dev->lock, flags); |
| 692 | if (!ep->caps.type_bulk) | 715 | if (dev->state != STATE_DEV_RUNNING) { |
| 693 | return false; | 716 | dev_dbg(dev->dev, "fail, device is not running\n"); |
| 694 | break; | 717 | ret = -EINVAL; |
| 695 | case USB_ENDPOINT_XFER_INT: | 718 | goto out_unlock; |
| 696 | if (!ep->caps.type_int) | 719 | } |
| 697 | return false; | 720 | if (!dev->gadget) { |
| 698 | break; | 721 | dev_dbg(dev->dev, "fail, gadget is not bound\n"); |
| 699 | default: | 722 | ret = -EBUSY; |
| 700 | return false; | 723 | goto out_unlock; |
| 724 | } | ||
| 725 | if (dev->ep0_urb_queued) { | ||
| 726 | dev_dbg(&dev->gadget->dev, "fail, urb already queued\n"); | ||
| 727 | ret = -EBUSY; | ||
| 728 | goto out_unlock; | ||
| 729 | } | ||
| 730 | if (!dev->ep0_in_pending && !dev->ep0_out_pending) { | ||
| 731 | dev_dbg(&dev->gadget->dev, "fail, no request pending\n"); | ||
| 732 | ret = -EBUSY; | ||
| 733 | goto out_unlock; | ||
| 701 | } | 734 | } |
| 702 | 735 | ||
| 703 | if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) | 736 | ret = usb_ep_set_halt(dev->gadget->ep0); |
| 704 | return false; | 737 | if (ret < 0) |
| 705 | if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) | 738 | dev_err(&dev->gadget->dev, |
| 706 | return false; | 739 | "fail, usb_ep_set_halt returned %d\n", ret); |
| 740 | |||
| 741 | if (dev->ep0_in_pending) | ||
| 742 | dev->ep0_in_pending = false; | ||
| 743 | else | ||
| 744 | dev->ep0_out_pending = false; | ||
| 707 | 745 | ||
| 708 | return true; | 746 | out_unlock: |
| 747 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 748 | return ret; | ||
| 709 | } | 749 | } |
| 710 | 750 | ||
| 711 | static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) | 751 | static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) |
| @@ -713,7 +753,7 @@ static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) · 1 unmodified line | |||
| 713 | int ret = 0, i; | 753 | int ret = 0, i; |
| 714 | unsigned long flags; | 754 | unsigned long flags; |
| 715 | struct usb_endpoint_descriptor *desc; | 755 | struct usb_endpoint_descriptor *desc; |
| 716 | struct usb_ep *ep = NULL; | 756 | struct raw_ep *ep; |
| 717 | 757 | ||
| 718 | desc = memdup_user((void __user *)value, sizeof(*desc)); | 758 | desc = memdup_user((void __user *)value, sizeof(*desc)); |
| 719 | if (IS_ERR(desc)) | 759 | if (IS_ERR(desc)) |
| @@ -741,41 +781,32 @@ static int raw_ioctl_ep_enable(struct raw_dev *dev, unsigned long value) · 21 unmodified lines | |||
| 741 | goto out_free; | 781 | goto out_free; |
| 742 | } | 782 | } |
| 743 | 783 | ||
| 744 | for (i = 0; i < USB_RAW_MAX_ENDPOINTS; i++) { | 784 | for (i = 0; i < dev->eps_num; i++) { |
| 745 | if (dev->eps[i].state == STATE_EP_ENABLED) | 785 | ep = &dev->eps[i]; |
| 786 | if (ep->state != STATE_EP_DISABLED) | ||
| 746 | continue; | 787 | continue; |
| 747 | break; | 788 | if (ep->addr != usb_endpoint_num(desc) && |
| 748 | } | 789 | ep->addr != USB_RAW_EP_ADDR_ANY) |
| 749 | if (i == USB_RAW_MAX_ENDPOINTS) { | ||
| 750 | dev_dbg(&dev->gadget->dev, | ||
| 751 | "fail, no device endpoints available\n"); | ||
| 752 | ret = -EBUSY; | ||
| 753 | goto out_free; | ||
| 754 | } | ||
| 755 | |||
| 756 | gadget_for_each_ep(ep, dev->gadget) { | ||
| 757 | if (ep->enabled) | ||
| 758 | continue; | 790 | continue; |
| 759 | if (!check_ep_caps(ep, desc)) | 791 | if (!usb_gadget_ep_match_desc(dev->gadget, ep->ep, desc, NULL)) |
| 760 | continue; | 792 | continue; |
| 761 | ep->desc = desc; | 793 | ep->ep->desc = desc; |
| 762 | ret = usb_ep_enable(ep); | 794 | ret = usb_ep_enable(ep->ep); |
| 763 | if (ret < 0) { | 795 | if (ret < 0) { |
| 764 | dev_err(&dev->gadget->dev, | 796 | dev_err(&dev->gadget->dev, |
| 765 | "fail, usb_ep_enable returned %d\n", ret); | 797 | "fail, usb_ep_enable returned %d\n", ret); |
| 766 | goto out_free; | 798 | goto out_free; |
| 767 | } | 799 | } |
| 768 | dev->eps[i].req = usb_ep_alloc_request(ep, GFP_ATOMIC); | 800 | ep->req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC); |
| 769 | if (!dev->eps[i].req) { | 801 | if (!ep->req) { |
| 770 | dev_err(&dev->gadget->dev, | 802 | dev_err(&dev->gadget->dev, |
| 771 | "fail, usb_ep_alloc_request failed\n"); | 803 | "fail, usb_ep_alloc_request failed\n"); |
| 772 | usb_ep_disable(ep); | 804 | usb_ep_disable(ep->ep); |
| 773 | ret = -ENOMEM; | 805 | ret = -ENOMEM; |
| 774 | goto out_free; | 806 | goto out_free; |
| 775 | } | 807 | } |
| 776 | dev->eps[i].ep = ep; | 808 | ep->state = STATE_EP_ENABLED; |
| 777 | dev->eps[i].state = STATE_EP_ENABLED; | 809 | ep->ep->driver_data = ep; |
| 778 | ep->driver_data = &dev->eps[i]; | ||
| 779 | ret = i; | 810 | ret = i; |
| 780 | goto out_unlock; | 811 | goto out_unlock; |
| 781 | } | 812 | } |
| @@ -794,10 +825,6 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) · 12 unmodified lines | |||
| 794 | { | 825 | { |
| 795 | int ret = 0, i = value; | 826 | int ret = 0, i = value; |
| 796 | unsigned long flags; | 827 | unsigned long flags; |
| 797 | const void *desc; | ||
| 798 | |||
| 799 | if (i < 0 || i >= USB_RAW_MAX_ENDPOINTS) | ||
| 800 | return -EINVAL; | ||
| 801 | 828 | ||
| 802 | spin_lock_irqsave(&dev->lock, flags); | 829 | spin_lock_irqsave(&dev->lock, flags); |
| 803 | if (dev->state != STATE_DEV_RUNNING) { | 830 | if (dev->state != STATE_DEV_RUNNING) { |
| @@ -810,7 +837,12 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) · 6 unmodified lines | |||
| 810 | ret = -EBUSY; | 837 | ret = -EBUSY; |
| 811 | goto out_unlock; | 838 | goto out_unlock; |
| 812 | } | 839 | } |
| 813 | if (dev->eps[i].state != STATE_EP_ENABLED) { | 840 | if (i < 0 || i >= dev->eps_num) { |
| 841 | dev_dbg(dev->dev, "fail, invalid endpoint\n"); | ||
| 842 | ret = -EBUSY; | ||
| 843 | goto out_unlock; | ||
| 844 | } | ||
| 845 | if (dev->eps[i].state == STATE_EP_DISABLED) { | ||
| 814 | dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); | 846 | dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); |
| 815 | ret = -EINVAL; | 847 | ret = -EINVAL; |
| 816 | goto out_unlock; | 848 | goto out_unlock; |
| @@ -834,10 +866,8 @@ static int raw_ioctl_ep_disable(struct raw_dev *dev, unsigned long value) · 17 unmodified lines | |||
| 834 | 866 | ||
| 835 | spin_lock_irqsave(&dev->lock, flags); | 867 | spin_lock_irqsave(&dev->lock, flags); |
| 836 | usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); | 868 | usb_ep_free_request(dev->eps[i].ep, dev->eps[i].req); |
| 837 | desc = dev->eps[i].ep->desc; | 869 | kfree(dev->eps[i].ep->desc); |
| 838 | dev->eps[i].ep = NULL; | ||
| 839 | dev->eps[i].state = STATE_EP_DISABLED; | 870 | dev->eps[i].state = STATE_EP_DISABLED; |
| 840 | kfree(desc); | ||
| 841 | dev->eps[i].disabling = false; | 871 | dev->eps[i].disabling = false; |
| 842 | 872 | ||
| 843 | out_unlock: | 873 | out_unlock: |
| @@ -845,6 +875,74 @@ out_unlock: · 1 unmodified line | |||
| 845 | return ret; | 875 | return ret; |
| 846 | } | 876 | } |
| 847 | 877 | ||
| 878 | static int raw_ioctl_ep_set_clear_halt_wedge(struct raw_dev *dev, | ||
| 879 | unsigned long value, bool set, bool halt) | ||
| 880 | { | ||
| 881 | int ret = 0, i = value; | ||
| 882 | unsigned long flags; | ||
| 883 | |||
| 884 | spin_lock_irqsave(&dev->lock, flags); | ||
| 885 | if (dev->state != STATE_DEV_RUNNING) { | ||
| 886 | dev_dbg(dev->dev, "fail, device is not running\n"); | ||
| 887 | ret = -EINVAL; | ||
| 888 | goto out_unlock; | ||
| 889 | } | ||
| 890 | if (!dev->gadget) { | ||
| 891 | dev_dbg(dev->dev, "fail, gadget is not bound\n"); | ||
| 892 | ret = -EBUSY; | ||
| 893 | goto out_unlock; | ||
| 894 | } | ||
| 895 | if (i < 0 || i >= dev->eps_num) { | ||
| 896 | dev_dbg(dev->dev, "fail, invalid endpoint\n"); | ||
| 897 | ret = -EBUSY; | ||
| 898 | goto out_unlock; | ||
| 899 | } | ||
| 900 | if (dev->eps[i].state == STATE_EP_DISABLED) { | ||
| 901 | dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); | ||
| 902 | ret = -EINVAL; | ||
| 903 | goto out_unlock; | ||
| 904 | } | ||
| 905 | if (dev->eps[i].disabling) { | ||
| 906 | dev_dbg(&dev->gadget->dev, | ||
| 907 | "fail, disable is in progress\n"); | ||
| 908 | ret = -EINVAL; | ||
| 909 | goto out_unlock; | ||
| 910 | } | ||
| 911 | if (dev->eps[i].urb_queued) { | ||
| 912 | dev_dbg(&dev->gadget->dev, | ||
| 913 | "fail, waiting for urb completion\n"); | ||
| 914 | ret = -EINVAL; | ||
| 915 | goto out_unlock; | ||
| 916 | } | ||
| 917 | if (usb_endpoint_xfer_isoc(dev->eps[i].ep->desc)) { | ||
| 918 | dev_dbg(&dev->gadget->dev, | ||
| 919 | "fail, can't halt/wedge ISO endpoint\n"); | ||
| 920 | ret = -EINVAL; | ||
| 921 | goto out_unlock; | ||
| 922 | } | ||
| 923 | |||
| 924 | if (set && halt) { | ||
| 925 | ret = usb_ep_set_halt(dev->eps[i].ep); | ||
| 926 | if (ret < 0) | ||
| 927 | dev_err(&dev->gadget->dev, | ||
| 928 | "fail, usb_ep_set_halt returned %d\n", ret); | ||
| 929 | } else if (!set && halt) { | ||
| 930 | ret = usb_ep_clear_halt(dev->eps[i].ep); | ||
| 931 | if (ret < 0) | ||
| 932 | dev_err(&dev->gadget->dev, | ||
| 933 | "fail, usb_ep_clear_halt returned %d\n", ret); | ||
| 934 | } else if (set && !halt) { | ||
| 935 | ret = usb_ep_set_wedge(dev->eps[i].ep); | ||
| 936 | if (ret < 0) | ||
| 937 | dev_err(&dev->gadget->dev, | ||
| 938 | "fail, usb_ep_set_wedge returned %d\n", ret); | ||
| 939 | } | ||
| 940 | |||
| 941 | out_unlock: | ||
| 942 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 943 | return ret; | ||
| 944 | } | ||
| 945 | |||
| 848 | static void gadget_ep_complete(struct usb_ep *ep, struct usb_request *req) | 946 | static void gadget_ep_complete(struct usb_ep *ep, struct usb_request *req) |
| 849 | { | 947 | { |
| 850 | struct raw_ep *r_ep = (struct raw_ep *)ep->driver_data; | 948 | struct raw_ep *r_ep = (struct raw_ep *)ep->driver_data; |
| @@ -866,7 +964,7 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io, · 15 unmodified lines | |||
| 866 | { | 964 | { |
| 867 | int ret = 0; | 965 | int ret = 0; |
| 868 | unsigned long flags; | 966 | unsigned long flags; |
| 869 | struct raw_ep *ep = &dev->eps[io->ep]; | 967 | struct raw_ep *ep; |
| 870 | DECLARE_COMPLETION_ONSTACK(done); | 968 | DECLARE_COMPLETION_ONSTACK(done); |
| 871 | 969 | ||
| 872 | spin_lock_irqsave(&dev->lock, flags); | 970 | spin_lock_irqsave(&dev->lock, flags); |
| @@ -880,6 +978,12 @@ static int raw_process_ep_io(struct raw_dev *dev, struct usb_raw_ep_io *io, · 7 unmodified lines | |||
| 880 | ret = -EBUSY; | 978 | ret = -EBUSY; |
| 881 | goto out_unlock; | 979 | goto out_unlock; |
| 882 | } | 980 | } |
| 981 | if (io->ep >= dev->eps_num) { | ||
| 982 | dev_dbg(&dev->gadget->dev, "fail, invalid endpoint\n"); | ||
| 983 | ret = -EINVAL; | ||
| 984 | goto out_unlock; | ||
| 985 | } | ||
| 986 | ep = &dev->eps[io->ep]; | ||
| 883 | if (ep->state != STATE_EP_ENABLED) { | 987 | if (ep->state != STATE_EP_ENABLED) { |
| 884 | dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); | 988 | dev_dbg(&dev->gadget->dev, "fail, endpoint is not enabled\n"); |
| 885 | ret = -EBUSY; | 989 | ret = -EBUSY; |
| @@ -964,12 +1068,14 @@ static int raw_ioctl_ep_read(struct raw_dev *dev, unsigned long value) · 78 unmodified lines | |||
| 964 | if (IS_ERR(data)) | 1068 | if (IS_ERR(data)) |
| 965 | return PTR_ERR(data); | 1069 | return PTR_ERR(data); |
| 966 | ret = raw_process_ep_io(dev, &io, data, false); | 1070 | ret = raw_process_ep_io(dev, &io, data, false); |
| 967 | if (ret) | 1071 | if (ret < 0) |
| 968 | goto free; | 1072 | goto free; |
| 969 | 1073 | ||
| 970 | length = min(io.length, (unsigned int)ret); | 1074 | length = min(io.length, (unsigned int)ret); |
| 971 | if (copy_to_user((void __user *)(value + sizeof(io)), data, length)) | 1075 | if (copy_to_user((void __user *)(value + sizeof(io)), data, length)) |
| 972 | ret = -EFAULT; | 1076 | ret = -EFAULT; |
| 1077 | else | ||
| 1078 | ret = length; | ||
| 973 | free: | 1079 | free: |
| 974 | kfree(data); | 1080 | kfree(data); |
| 975 | return ret; | 1081 | return ret; |
| @@ -1023,6 +1129,71 @@ out_unlock: · 47 unmodified lines | |||
| 1023 | return ret; | 1129 | return ret; |
| 1024 | } | 1130 | } |
| 1025 | 1131 | ||
| 1132 | static void fill_ep_caps(struct usb_ep_caps *caps, | ||
| 1133 | struct usb_raw_ep_caps *raw_caps) | ||
| 1134 | { | ||
| 1135 | raw_caps->type_control = caps->type_control; | ||
| 1136 | raw_caps->type_iso = caps->type_iso; | ||
| 1137 | raw_caps->type_bulk = caps->type_bulk; | ||
| 1138 | raw_caps->type_int = caps->type_int; | ||
| 1139 | raw_caps->dir_in = caps->dir_in; | ||
| 1140 | raw_caps->dir_out = caps->dir_out; | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | static void fill_ep_limits(struct usb_ep *ep, struct usb_raw_ep_limits *limits) | ||
| 1144 | { | ||
| 1145 | limits->maxpacket_limit = ep->maxpacket_limit; | ||
| 1146 | limits->max_streams = ep->max_streams; | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | static int raw_ioctl_eps_info(struct raw_dev *dev, unsigned long value) | ||
| 1150 | { | ||
| 1151 | int ret = 0, i; | ||
| 1152 | unsigned long flags; | ||
| 1153 | struct usb_raw_eps_info *info; | ||
| 1154 | struct raw_ep *ep; | ||
| 1155 | |||
| 1156 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
| 1157 | if (!info) { | ||
| 1158 | ret = -ENOMEM; | ||
| 1159 | goto out; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | spin_lock_irqsave(&dev->lock, flags); | ||
| 1163 | if (dev->state != STATE_DEV_RUNNING) { | ||
| 1164 | dev_dbg(dev->dev, "fail, device is not running\n"); | ||
| 1165 | ret = -EINVAL; | ||
| 1166 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1167 | goto out_free; | ||
| 1168 | } | ||
| 1169 | if (!dev->gadget) { | ||
| 1170 | dev_dbg(dev->dev, "fail, gadget is not bound\n"); | ||
| 1171 | ret = -EBUSY; | ||
| 1172 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1173 | goto out_free; | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | memset(info, 0, sizeof(*info)); | ||
| 1177 | for (i = 0; i < dev->eps_num; i++) { | ||
| 1178 | ep = &dev->eps[i]; | ||
| 1179 | strscpy(&info->eps[i].name[0], ep->ep->name, | ||
| 1180 | USB_RAW_EP_NAME_MAX); | ||
| 1181 | info->eps[i].addr = ep->addr; | ||
| 1182 | fill_ep_caps(&ep->ep->caps, &info->eps[i].caps); | ||
| 1183 | fill_ep_limits(ep->ep, &info->eps[i].limits); | ||
| 1184 | } | ||
| 1185 | ret = dev->eps_num; | ||
| 1186 | spin_unlock_irqrestore(&dev->lock, flags); | ||
| 1187 | |||
| 1188 | if (copy_to_user((void __user *)value, info, sizeof(*info))) | ||
| 1189 | ret = -EFAULT; | ||
| 1190 | |||
| 1191 | out_free: | ||
| 1192 | kfree(info); | ||
| 1193 | out: | ||
| 1194 | return ret; | ||
| 1195 | } | ||
| 1196 | |||
| 1026 | static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) | 1197 | static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) |
| 1027 | { | 1198 | { |
| 1028 | struct raw_dev *dev = fd->private_data; | 1199 | struct raw_dev *dev = fd->private_data; |
| @@ -1065,6 +1236,24 @@ static long raw_ioctl(struct file *fd, unsigned int cmd, unsigned long value) · 36 unmodified lines | |||
| 1065 | case USB_RAW_IOCTL_VBUS_DRAW: | 1236 | case USB_RAW_IOCTL_VBUS_DRAW: |
| 1066 | ret = raw_ioctl_vbus_draw(dev, value); | 1237 | ret = raw_ioctl_vbus_draw(dev, value); |
| 1067 | break; | 1238 | break; |
| 1239 | case USB_RAW_IOCTL_EPS_INFO: | ||
| 1240 | ret = raw_ioctl_eps_info(dev, value); | ||
| 1241 | break; | ||
| 1242 | case USB_RAW_IOCTL_EP0_STALL: | ||
| 1243 | ret = raw_ioctl_ep0_stall(dev, value); | ||
| 1244 | break; | ||
| 1245 | case USB_RAW_IOCTL_EP_SET_HALT: | ||
| 1246 | ret = raw_ioctl_ep_set_clear_halt_wedge( | ||
| 1247 | dev, value, true, true); | ||
| 1248 | break; | ||
| 1249 | case USB_RAW_IOCTL_EP_CLEAR_HALT: | ||
| 1250 | ret = raw_ioctl_ep_set_clear_halt_wedge( | ||
| 1251 | dev, value, false, true); | ||
| 1252 | break; | ||
| 1253 | case USB_RAW_IOCTL_EP_SET_WEDGE: | ||
| 1254 | ret = raw_ioctl_ep_set_clear_halt_wedge( | ||
| 1255 | dev, value, true, false); | ||
| 1256 | break; | ||
| 1068 | default: | 1257 | default: |
| 1069 | ret = -EINVAL; | 1258 | ret = -EINVAL; |
| 1070 | } | 1259 | } |
| @@ -185,7 +185,7 @@ static int regs_dbg_release(struct inode *inode, struct file *file) · 184 unmodified lines | |||
| 185 | return 0; | 185 | return 0; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | const struct file_operations queue_dbg_fops = { | 188 | static const struct file_operations queue_dbg_fops = { |
| 189 | .owner = THIS_MODULE, | 189 | .owner = THIS_MODULE, |
| 190 | .open = queue_dbg_open, | 190 | .open = queue_dbg_open, |
| 191 | .llseek = no_llseek, | 191 | .llseek = no_llseek, |
| @@ -193,7 +193,7 @@ const struct file_operations queue_dbg_fops = { · 1 unmodified line | |||
| 193 | .release = queue_dbg_release, | 193 | .release = queue_dbg_release, |
| 194 | }; | 194 | }; |
| 195 | 195 | ||
| 196 | const struct file_operations regs_dbg_fops = { | 196 | static const struct file_operations regs_dbg_fops = { |
| 197 | .owner = THIS_MODULE, | 197 | .owner = THIS_MODULE, |
| 198 | .open = regs_dbg_open, | 198 | .open = regs_dbg_open, |
| 199 | .llseek = generic_file_llseek, | 199 | .llseek = generic_file_llseek, |
| @@ -2647,6 +2647,8 @@ net2272_plat_probe(struct platform_device *pdev) · 2646 unmodified lines | |||
| 2647 | err_req: | 2647 | err_req: |
| 2648 | release_mem_region(base, len); | 2648 | release_mem_region(base, len); |
| 2649 | err: | 2649 | err: |
| 2650 | kfree(dev); | ||
| 2651 | |||
| 2650 | return ret; | 2652 | return ret; |
| 2651 | } | 2653 | } |
| 2652 | 2654 | ||
| @@ -3840,11 +3840,11 @@ static int __maybe_unused tegra_xudc_suspend(struct device *dev) · 3839 unmodified lines | |||
| 3840 | 3840 | ||
| 3841 | flush_work(&xudc->usb_role_sw_work); | 3841 | flush_work(&xudc->usb_role_sw_work); |
| 3842 | 3842 | ||
| 3843 | /* Forcibly disconnect before powergating. */ | 3843 | if (!pm_runtime_status_suspended(dev)) { |
| 3844 | tegra_xudc_device_mode_off(xudc); | 3844 | /* Forcibly disconnect before powergating. */ |
| 3845 | 3845 | tegra_xudc_device_mode_off(xudc); | |
| 3846 | if (!pm_runtime_status_suspended(dev)) | ||
| 3847 | tegra_xudc_powergate(xudc); | 3846 | tegra_xudc_powergate(xudc); |
| 3847 | } | ||
| 3848 | 3848 | ||
| 3849 | pm_runtime_disable(dev); | 3849 | pm_runtime_disable(dev); |
| 3850 | 3850 | ||
| @@ -362,6 +362,7 @@ static int xhci_plat_remove(struct platform_device *dev) · 361 unmodified lines | |||
| 362 | struct clk *reg_clk = xhci->reg_clk; | 362 | struct clk *reg_clk = xhci->reg_clk; |
| 363 | struct usb_hcd *shared_hcd = xhci->shared_hcd; | 363 | struct usb_hcd *shared_hcd = xhci->shared_hcd; |
| 364 | 364 | ||
| 365 | pm_runtime_get_sync(&dev->dev); | ||
| 365 | xhci->xhc_state |= XHCI_STATE_REMOVING; | 366 | xhci->xhc_state |= XHCI_STATE_REMOVING; |
| 366 | 367 | ||
| 367 | usb_remove_hcd(shared_hcd); | 368 | usb_remove_hcd(shared_hcd); |
| @@ -375,8 +376,9 @@ static int xhci_plat_remove(struct platform_device *dev) · 7 unmodified lines | |||
| 375 | clk_disable_unprepare(reg_clk); | 376 | clk_disable_unprepare(reg_clk); |
| 376 | usb_put_hcd(hcd); | 377 | usb_put_hcd(hcd); |
| 377 | 378 | ||
| 378 | pm_runtime_set_suspended(&dev->dev); | ||
| 379 | pm_runtime_disable(&dev->dev); | 379 | pm_runtime_disable(&dev->dev); |
| 380 | pm_runtime_put_noidle(&dev->dev); | ||
| 381 | pm_runtime_set_suspended(&dev->dev); | ||
| 380 | 382 | ||
| 381 | return 0; | 383 | return 0; |
| 382 | } | 384 | } |
| @@ -3433,8 +3433,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, · 3432 unmodified lines | |||
| 3433 | /* New sg entry */ | 3433 | /* New sg entry */ |
| 3434 | --num_sgs; | 3434 | --num_sgs; |
| 3435 | sent_len -= block_len; | 3435 | sent_len -= block_len; |
| 3436 | if (num_sgs != 0) { | 3436 | sg = sg_next(sg); |
| 3437 | sg = sg_next(sg); | 3437 | if (num_sgs != 0 && sg) { |
| 3438 | block_len = sg_dma_len(sg); | 3438 | block_len = sg_dma_len(sg); |
| 3439 | addr = (u64) sg_dma_address(sg); | 3439 | addr = (u64) sg_dma_address(sg); |
| 3440 | addr += sent_len; | 3440 | addr += sent_len; |
| @@ -276,7 +276,7 @@ static const struct file_operations mtu3_ep_fops = { · 275 unmodified lines | |||
| 276 | .release = single_release, | 276 | .release = single_release, |
| 277 | }; | 277 | }; |
| 278 | 278 | ||
| 279 | static struct debugfs_reg32 mtu3_prb_regs[] = { | 279 | static const struct debugfs_reg32 mtu3_prb_regs[] = { |
| 280 | dump_prb_reg("enable", U3D_SSUSB_PRB_CTRL0), | 280 | dump_prb_reg("enable", U3D_SSUSB_PRB_CTRL0), |
| 281 | dump_prb_reg("byte-sell", U3D_SSUSB_PRB_CTRL1), | 281 | dump_prb_reg("byte-sell", U3D_SSUSB_PRB_CTRL1), |
| 282 | dump_prb_reg("byte-selh", U3D_SSUSB_PRB_CTRL2), | 282 | dump_prb_reg("byte-selh", U3D_SSUSB_PRB_CTRL2), |
| @@ -349,7 +349,7 @@ static const struct file_operations mtu3_probe_fops = { · 66 unmodified lines | |||
| 349 | static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu) | 349 | static void mtu3_debugfs_create_prb_files(struct mtu3 *mtu) |
| 350 | { | 350 | { |
| 351 | struct ssusb_mtk *ssusb = mtu->ssusb; | 351 | struct ssusb_mtk *ssusb = mtu->ssusb; |
| 352 | struct debugfs_reg32 *regs; | 352 | const struct debugfs_reg32 *regs; |
| 353 | struct dentry *dir_prb; | 353 | struct dentry *dir_prb; |
| 354 | int i; | 354 | int i; |
| 355 | 355 | ||
| @@ -377,7 +377,7 @@ static int twl6030_usb_probe(struct platform_device *pdev) · 376 unmodified lines | |||
| 377 | if (status < 0) { | 377 | if (status < 0) { |
| 378 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 378 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
| 379 | twl->irq1, status); | 379 | twl->irq1, status); |
| 380 | return status; | 380 | goto err_put_regulator; |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq, | 383 | status = request_threaded_irq(twl->irq2, NULL, twl6030_usb_irq, |
| @@ -386,8 +386,7 @@ static int twl6030_usb_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 386 | if (status < 0) { | 386 | if (status < 0) { |
| 387 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", | 387 | dev_err(&pdev->dev, "can't get IRQ %d, err %d\n", |
| 388 | twl->irq2, status); | 388 | twl->irq2, status); |
| 389 | free_irq(twl->irq1, twl); | 389 | goto err_free_irq1; |
| 390 | return status; | ||
| 391 | } | 390 | } |
| 392 | 391 | ||
| 393 | twl->asleep = 0; | 392 | twl->asleep = 0; |
| @@ -396,6 +395,13 @@ static int twl6030_usb_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 396 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); | 395 | dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); |
| 397 | 396 | ||
| 398 | return 0; | 397 | return 0; |
| 398 | |||
| 399 | err_free_irq1: | ||
| 400 | free_irq(twl->irq1, twl); | ||
| 401 | err_put_regulator: | ||
| 402 | regulator_put(twl->usb3v3); | ||
| 403 | |||
| 404 | return status; | ||
| 399 | } | 405 | } |
| 400 | 406 | ||
| 401 | static int twl6030_usb_remove(struct platform_device *pdev) | 407 | static int twl6030_usb_remove(struct platform_device *pdev) |
| @@ -63,6 +63,7 @@ enum { · 62 unmodified lines | |||
| 63 | #define PMC_USB_ALTMODE_DP_MODE_SHIFT 8 | 63 | #define PMC_USB_ALTMODE_DP_MODE_SHIFT 8 |
| 64 | 64 | ||
| 65 | /* TBT specific Mode Data bits */ | 65 | /* TBT specific Mode Data bits */ |
| 66 | #define PMC_USB_ALTMODE_HPD_HIGH BIT(14) | ||
| 66 | #define PMC_USB_ALTMODE_TBT_TYPE BIT(17) | 67 | #define PMC_USB_ALTMODE_TBT_TYPE BIT(17) |
| 67 | #define PMC_USB_ALTMODE_CABLE_TYPE BIT(18) | 68 | #define PMC_USB_ALTMODE_CABLE_TYPE BIT(18) |
| 68 | #define PMC_USB_ALTMODE_ACTIVE_LINK BIT(20) | 69 | #define PMC_USB_ALTMODE_ACTIVE_LINK BIT(20) |
| @@ -74,8 +75,8 @@ enum { · 5 unmodified lines | |||
| 74 | #define PMC_USB_ALTMODE_TBT_GEN(_g_) (((_g_) & GENMASK(1, 0)) << 28) | 75 | #define PMC_USB_ALTMODE_TBT_GEN(_g_) (((_g_) & GENMASK(1, 0)) << 28) |
| 75 | 76 | ||
| 76 | /* Display HPD Request bits */ | 77 | /* Display HPD Request bits */ |
| 78 | #define PMC_USB_DP_HPD_LVL BIT(4) | ||
| 77 | #define PMC_USB_DP_HPD_IRQ BIT(5) | 79 | #define PMC_USB_DP_HPD_IRQ BIT(5) |
| 78 | #define PMC_USB_DP_HPD_LVL BIT(6) | ||
| 79 | 80 | ||
| 80 | struct pmc_usb; | 81 | struct pmc_usb; |
| 81 | 82 | ||
| @@ -158,8 +159,7 @@ pmc_usb_mux_dp(struct pmc_usb_port *port, struct typec_mux_state *state) · 76 unmodified lines | |||
| 158 | PMC_USB_ALTMODE_DP_MODE_SHIFT; | 159 | PMC_USB_ALTMODE_DP_MODE_SHIFT; |
| 159 | 160 | ||
| 160 | if (data->status & DP_STATUS_HPD_STATE) | 161 | if (data->status & DP_STATUS_HPD_STATE) |
| 161 | req.mode_data |= PMC_USB_DP_HPD_LVL << | 162 | req.mode_data |= PMC_USB_ALTMODE_HPD_HIGH; |
| 162 | PMC_USB_ALTMODE_DP_MODE_SHIFT; | ||
| 163 | 163 | ||
| 164 | return pmc_usb_command(port, (void *)&req, sizeof(req)); | 164 | return pmc_usb_command(port, (void *)&req, sizeof(req)); |
| 165 | } | 165 | } |
| @@ -93,6 +93,64 @@ struct usb_raw_ep_io { · 92 unmodified lines | |||
| 93 | __u8 data[0]; | 93 | __u8 data[0]; |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | /* Maximum number of non-control endpoints in struct usb_raw_eps_info. */ | ||
| 97 | #define USB_RAW_EPS_NUM_MAX 30 | ||
| 98 | |||
| 99 | /* Maximum length of UDC endpoint name in struct usb_raw_ep_info. */ | ||
| 100 | #define USB_RAW_EP_NAME_MAX 16 | ||
| 101 | |||
| 102 | /* Used as addr in struct usb_raw_ep_info if endpoint accepts any address. */ | ||
| 103 | #define USB_RAW_EP_ADDR_ANY 0xff | ||
| 104 | |||
| 105 | /* | ||
| 106 | * struct usb_raw_ep_caps - exposes endpoint capabilities from struct usb_ep | ||
| 107 | * (technically from its member struct usb_ep_caps). | ||
| 108 | */ | ||
| 109 | struct usb_raw_ep_caps { | ||
| 110 | __u32 type_control : 1; | ||
| 111 | __u32 type_iso : 1; | ||
| 112 | __u32 type_bulk : 1; | ||
| 113 | __u32 type_int : 1; | ||
| 114 | __u32 dir_in : 1; | ||
| 115 | __u32 dir_out : 1; | ||
| 116 | }; | ||
| 117 | |||
| 118 | /* | ||
| 119 | * struct usb_raw_ep_limits - exposes endpoint limits from struct usb_ep. | ||
| 120 | * @maxpacket_limit: Maximum packet size value supported by this endpoint. | ||
| 121 | * @max_streams: maximum number of streams supported by this endpoint | ||
| 122 | * (actual number is 2^n). | ||
| 123 | * @reserved: Empty, reserved for potential future extensions. | ||
| 124 | */ | ||
| 125 | struct usb_raw_ep_limits { | ||
| 126 | __u16 maxpacket_limit; | ||
| 127 | __u16 max_streams; | ||
| 128 | __u32 reserved; | ||
| 129 | }; | ||
| 130 | |||
| 131 | /* | ||
| 132 | * struct usb_raw_ep_info - stores information about a gadget endpoint. | ||
| 133 | * @name: Name of the endpoint as it is defined in the UDC driver. | ||
| 134 | * @addr: Address of the endpoint that must be specified in the endpoint | ||
| 135 | * descriptor passed to USB_RAW_IOCTL_EP_ENABLE ioctl. | ||
| 136 | * @caps: Endpoint capabilities. | ||
| 137 | * @limits: Endpoint limits. | ||
| 138 | */ | ||
| 139 | struct usb_raw_ep_info { | ||
| 140 | __u8 name[USB_RAW_EP_NAME_MAX]; | ||
| 141 | __u32 addr; | ||
| 142 | struct usb_raw_ep_caps caps; | ||
| 143 | struct usb_raw_ep_limits limits; | ||
| 144 | }; | ||
| 145 | |||
| 146 | /* | ||
| 147 | * struct usb_raw_eps_info - argument for USB_RAW_IOCTL_EPS_INFO ioctl. | ||
| 148 | * eps: Structures that store information about non-control endpoints. | ||
| 149 | */ | ||
| 150 | struct usb_raw_eps_info { | ||
| 151 | struct usb_raw_ep_info eps[USB_RAW_EPS_NUM_MAX]; | ||
| 152 | }; | ||
| 153 | |||
| 96 | /* | 154 | /* |
| 97 | * Initializes a Raw Gadget instance. | 155 | * Initializes a Raw Gadget instance. |
| 98 | * Accepts a pointer to the usb_raw_init struct as an argument. | 156 | * Accepts a pointer to the usb_raw_init struct as an argument. |
| @@ -115,37 +173,38 @@ struct usb_raw_ep_io { · 16 unmodified lines | |||
| 115 | #define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event) | 173 | #define USB_RAW_IOCTL_EVENT_FETCH _IOR('U', 2, struct usb_raw_event) |
| 116 | 174 | ||
| 117 | /* | 175 | /* |
| 118 | * Queues an IN (OUT for READ) urb as a response to the last control request | 176 | * Queues an IN (OUT for READ) request as a response to the last setup request |
| 119 | * received on endpoint 0, provided that was an IN (OUT for READ) request and | 177 | * received on endpoint 0 (provided that was an IN (OUT for READ) request), and |
| 120 | * waits until the urb is completed. Copies received data to user for READ. | 178 | * waits until the request is completed. Copies received data to user for READ. |
| 121 | * Accepts a pointer to the usb_raw_ep_io struct as an argument. | 179 | * Accepts a pointer to the usb_raw_ep_io struct as an argument. |
| 122 | * Returns length of trasferred data on success or negative error code on | 180 | * Returns length of transferred data on success or negative error code on |
| 123 | * failure. | 181 | * failure. |
| 124 | */ | 182 | */ |
| 125 | #define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io) | 183 | #define USB_RAW_IOCTL_EP0_WRITE _IOW('U', 3, struct usb_raw_ep_io) |
| 126 | #define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io) | 184 | #define USB_RAW_IOCTL_EP0_READ _IOWR('U', 4, struct usb_raw_ep_io) |
| 127 | 185 | ||
| 128 | /* | 186 | /* |
| 129 | * Finds an endpoint that supports the transfer type specified in the | 187 | * Finds an endpoint that satisfies the parameters specified in the provided |
| 130 | * descriptor and enables it. | 188 | * descriptors (address, transfer type, etc.) and enables it. |
| 131 | * Accepts a pointer to the usb_endpoint_descriptor struct as an argument. | 189 | * Accepts a pointer to the usb_raw_ep_descs struct as an argument. |
| 132 | * Returns enabled endpoint handle on success or negative error code on failure. | 190 | * Returns enabled endpoint handle on success or negative error code on failure. |
| 133 | */ | 191 | */ |
| 134 | #define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor) | 192 | #define USB_RAW_IOCTL_EP_ENABLE _IOW('U', 5, struct usb_endpoint_descriptor) |
| 135 | 193 | ||
| 136 | /* Disables specified endpoint. | 194 | /* |
| 195 | * Disables specified endpoint. | ||
| 137 | * Accepts endpoint handle as an argument. | 196 | * Accepts endpoint handle as an argument. |
| 138 | * Returns 0 on success or negative error code on failure. | 197 | * Returns 0 on success or negative error code on failure. |
| 139 | */ | 198 | */ |
| 140 | #define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32) | 199 | #define USB_RAW_IOCTL_EP_DISABLE _IOW('U', 6, __u32) |
| 141 | 200 | ||
| 142 | /* | 201 | /* |
| 143 | * Queues an IN (OUT for READ) urb as a response to the last control request | 202 | * Queues an IN (OUT for READ) request as a response to the last setup request |
| 144 | * received on endpoint usb_raw_ep_io.ep, provided that was an IN (OUT for READ) | 203 | * received on endpoint usb_raw_ep_io.ep (provided that was an IN (OUT for READ) |
| 145 | * request and waits until the urb is completed. Copies received data to user | 204 | * request), and waits until the request is completed. Copies received data to |
| 146 | * for READ. | 205 | * user for READ. |
| 147 | * Accepts a pointer to the usb_raw_ep_io struct as an argument. | 206 | * Accepts a pointer to the usb_raw_ep_io struct as an argument. |
| 148 | * Returns length of trasferred data on success or negative error code on | 207 | * Returns length of transferred data on success or negative error code on |
| 149 | * failure. | 208 | * failure. |
| 150 | */ | 209 | */ |
| 151 | #define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io) | 210 | #define USB_RAW_IOCTL_EP_WRITE _IOW('U', 7, struct usb_raw_ep_io) |
| @@ -164,4 +223,27 @@ struct usb_raw_ep_io { · 12 unmodified lines | |||
| 164 | */ | 223 | */ |
| 165 | #define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32) | 224 | #define USB_RAW_IOCTL_VBUS_DRAW _IOW('U', 10, __u32) |
| 166 | 225 | ||
| 226 | /* | ||
| 227 | * Fills in the usb_raw_eps_info structure with information about non-control | ||
| 228 | * endpoints available for the currently connected UDC. | ||
| 229 | * Returns the number of available endpoints on success or negative error code | ||
| 230 | * on failure. | ||
| 231 | */ | ||
| 232 | #define USB_RAW_IOCTL_EPS_INFO _IOR('U', 11, struct usb_raw_eps_info) | ||
| 233 | |||
| 234 | /* | ||
| 235 | * Stalls a pending control request on endpoint 0. | ||
| 236 | * Returns 0 on success or negative error code on failure. | ||
| 237 | */ | ||
| 238 | #define USB_RAW_IOCTL_EP0_STALL _IO('U', 12) | ||
| 239 | |||
| 240 | /* | ||
| 241 | * Sets or clears halt or wedge status of the endpoint. | ||
| 242 | * Accepts endpoint handle as an argument. | ||
| 243 | * Returns 0 on success or negative error code on failure. | ||
| 244 | */ | ||
| 245 | #define USB_RAW_IOCTL_EP_SET_HALT _IOW('U', 13, __u32) | ||
| 246 | #define USB_RAW_IOCTL_EP_CLEAR_HALT _IOW('U', 14, __u32) | ||
| 247 | #define USB_RAW_IOCTL_EP_SET_WEDGE _IOW('U', 15, __u32) | ||
| 248 | |||
| 167 | #endif /* _UAPI__LINUX_USB_RAW_GADGET_H */ | 249 | #endif /* _UAPI__LINUX_USB_RAW_GADGET_H */ |