提交 528a506e 编写于 作者: L Linus Torvalds

Merge tag 'usb-3.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a bunch of USB fixes for 3.18-rc3.

  Mostly usb-serial device ids and gadget fixes for issues that have
  been reported.  Full details are in the shortlog.

  All of these have been in linux-next for a while"

* tag 'usb-3.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (42 commits)
  usb: chipidea: Fix oops when removing the ci_hdrc module
  usb: gadget: function: Fixed the return value on error path
  usb: dwc2: gadget: disable phy before turning off power regulators
  usb: gadget: function: Remove redundant usb_free_all_descriptors
  usb: dwc3: gadget: Properly initialize LINK TRB
  usb: dwc2: gadget: fix gadget unregistration in udc_stop() function
  usb: dwc2: Bits in bitfield should add up to 32
  usb: dwc2: gadget: sparse warning of context imbalance
  usb: gadget: udc: core: fix kernel oops with soft-connect
  usb: musb: musb_dsps: fix NULL pointer in suspend
  usb: musb: dsps: start OTG timer on resume again
  usb: gadget: loopback: don't queue requests to bogus endpoints
  usb: ffs: fix regression when quirk_ep_out_aligned_size flag is set
  usb: gadget: f_fs: remove redundant ffs_data_get()
  usb: gadget: udc: USB_GADGET_XILINX should depend on HAS_DMA
  Revert "usb: dwc3: dwc3-omap: Disable/Enable only wrapper interrupts in prepare/complete"
  usb: gadget: composite: enable BESL support
  usb: musb: cppi41: restart hrtimer only if not yet done
  usb: dwc3: ep0: fix Data Phase for transfer sizes aligned to wMaxPacketSize
  usb: serial: ftdi_sio: add "bricked" FTDI device PID
  ...
...@@ -742,7 +742,6 @@ static int ci_hdrc_remove(struct platform_device *pdev) ...@@ -742,7 +742,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
ci_role_destroy(ci); ci_role_destroy(ci);
ci_hdrc_enter_lpm(ci, true); ci_hdrc_enter_lpm(ci, true);
usb_phy_shutdown(ci->transceiver); usb_phy_shutdown(ci->transceiver);
kfree(ci->hw_bank.regmap);
return 0; return 0;
} }
......
...@@ -619,7 +619,7 @@ struct dwc2_hsotg { ...@@ -619,7 +619,7 @@ struct dwc2_hsotg {
unsigned port_suspend_change:1; unsigned port_suspend_change:1;
unsigned port_over_current_change:1; unsigned port_over_current_change:1;
unsigned port_l1_change:1; unsigned port_l1_change:1;
unsigned reserved:26; unsigned reserved:25;
} b; } b;
} flags; } flags;
......
...@@ -2561,8 +2561,10 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, ...@@ -2561,8 +2561,10 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
hs_ep->fifo_size = val; hs_ep->fifo_size = val;
break; break;
} }
if (i == 8) if (i == 8) {
return -ENOMEM; ret = -ENOMEM;
goto error;
}
} }
/* for non control endpoints, set PID to D0 */ /* for non control endpoints, set PID to D0 */
...@@ -2579,6 +2581,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, ...@@ -2579,6 +2581,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
/* enable the endpoint interrupt */ /* enable the endpoint interrupt */
s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
error:
spin_unlock_irqrestore(&hsotg->lock, flags); spin_unlock_irqrestore(&hsotg->lock, flags);
return ret; return ret;
} }
...@@ -2934,9 +2937,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget, ...@@ -2934,9 +2937,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
spin_lock_irqsave(&hsotg->lock, flags); spin_lock_irqsave(&hsotg->lock, flags);
if (!driver)
hsotg->driver = NULL; hsotg->driver = NULL;
hsotg->gadget.speed = USB_SPEED_UNKNOWN; hsotg->gadget.speed = USB_SPEED_UNKNOWN;
spin_unlock_irqrestore(&hsotg->lock, flags); spin_unlock_irqrestore(&hsotg->lock, flags);
...@@ -3567,6 +3568,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3567,6 +3568,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum); s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum);
/* disable power and clock */ /* disable power and clock */
s3c_hsotg_phy_disable(hsotg);
ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
hsotg->supplies); hsotg->supplies);
...@@ -3575,8 +3577,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev) ...@@ -3575,8 +3577,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
goto err_ep_mem; goto err_ep_mem;
} }
s3c_hsotg_phy_disable(hsotg);
ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget); ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
if (ret) if (ret)
goto err_ep_mem; goto err_ep_mem;
......
...@@ -597,7 +597,7 @@ static int dwc3_omap_prepare(struct device *dev) ...@@ -597,7 +597,7 @@ static int dwc3_omap_prepare(struct device *dev)
{ {
struct dwc3_omap *omap = dev_get_drvdata(dev); struct dwc3_omap *omap = dev_get_drvdata(dev);
dwc3_omap_write_irqmisc_set(omap, 0x00); dwc3_omap_disable_irqs(omap);
return 0; return 0;
} }
...@@ -605,19 +605,8 @@ static int dwc3_omap_prepare(struct device *dev) ...@@ -605,19 +605,8 @@ static int dwc3_omap_prepare(struct device *dev)
static void dwc3_omap_complete(struct device *dev) static void dwc3_omap_complete(struct device *dev)
{ {
struct dwc3_omap *omap = dev_get_drvdata(dev); struct dwc3_omap *omap = dev_get_drvdata(dev);
u32 reg;
reg = (USBOTGSS_IRQMISC_OEVT | dwc3_omap_enable_irqs(omap);
USBOTGSS_IRQMISC_DRVVBUS_RISE |
USBOTGSS_IRQMISC_CHRGVBUS_RISE |
USBOTGSS_IRQMISC_DISCHRGVBUS_RISE |
USBOTGSS_IRQMISC_IDPULLUP_RISE |
USBOTGSS_IRQMISC_DRVVBUS_FALL |
USBOTGSS_IRQMISC_CHRGVBUS_FALL |
USBOTGSS_IRQMISC_DISCHRGVBUS_FALL |
USBOTGSS_IRQMISC_IDPULLUP_FALL);
dwc3_omap_write_irqmisc_set(omap, reg);
} }
static int dwc3_omap_suspend(struct device *dev) static int dwc3_omap_suspend(struct device *dev)
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd
#define PCI_DEVICE_ID_INTEL_BYT 0x0f37 #define PCI_DEVICE_ID_INTEL_BYT 0x0f37
#define PCI_DEVICE_ID_INTEL_MRFLD 0x119e #define PCI_DEVICE_ID_INTEL_MRFLD 0x119e
#define PCI_DEVICE_ID_INTEL_BSW 0x22B7
struct dwc3_pci { struct dwc3_pci {
struct device *dev; struct device *dev;
...@@ -181,6 +182,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = { ...@@ -181,6 +182,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS, PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3), PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
}, },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
{ } /* Terminating Entry */ { } /* Terminating Entry */
......
...@@ -256,7 +256,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) ...@@ -256,7 +256,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
/* stall is always issued on EP0 */ /* stall is always issued on EP0 */
dep = dwc->eps[0]; dep = dwc->eps[0];
__dwc3_gadget_ep_set_halt(dep, 1); __dwc3_gadget_ep_set_halt(dep, 1, false);
dep->flags = DWC3_EP_ENABLED; dep->flags = DWC3_EP_ENABLED;
dwc->delayed_status = false; dwc->delayed_status = false;
...@@ -271,7 +271,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) ...@@ -271,7 +271,7 @@ static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
dwc3_ep0_out_start(dwc); dwc3_ep0_out_start(dwc);
} }
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
{ {
struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
...@@ -281,6 +281,20 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value) ...@@ -281,6 +281,20 @@ int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
return 0; return 0;
} }
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value)
{
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc;
unsigned long flags;
int ret;
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep0_set_halt(ep, value);
spin_unlock_irqrestore(&dwc->lock, flags);
return ret;
}
void dwc3_ep0_out_start(struct dwc3 *dwc) void dwc3_ep0_out_start(struct dwc3 *dwc)
{ {
int ret; int ret;
...@@ -466,7 +480,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, ...@@ -466,7 +480,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
return -EINVAL; return -EINVAL;
if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) if (set == 0 && (dep->flags & DWC3_EP_WEDGE))
break; break;
ret = __dwc3_gadget_ep_set_halt(dep, set); ret = __dwc3_gadget_ep_set_halt(dep, set, true);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
break; break;
...@@ -775,9 +789,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ...@@ -775,9 +789,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS; dwc->ep0_next_event = DWC3_EP0_NRDY_STATUS;
r = next_request(&ep0->request_list);
ur = &r->request;
trb = dwc->ep0_trb; trb = dwc->ep0_trb;
status = DWC3_TRB_SIZE_TRBSTS(trb->size); status = DWC3_TRB_SIZE_TRBSTS(trb->size);
...@@ -790,6 +801,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ...@@ -790,6 +801,12 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
return; return;
} }
r = next_request(&ep0->request_list);
if (!r)
return;
ur = &r->request;
length = trb->size & DWC3_TRB_SIZE_MASK; length = trb->size & DWC3_TRB_SIZE_MASK;
if (dwc->ep0_bounced) { if (dwc->ep0_bounced) {
...@@ -811,12 +828,19 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ...@@ -811,12 +828,19 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
dwc3_ep0_stall_and_restart(dwc); dwc3_ep0_stall_and_restart(dwc);
} else { } else {
/*
* handle the case where we have to send a zero packet. This
* seems to be case when req.length > maxpacket. Could it be?
*/
if (r)
dwc3_gadget_giveback(ep0, r, 0); dwc3_gadget_giveback(ep0, r, 0);
if (IS_ALIGNED(ur->length, ep0->endpoint.maxpacket) &&
ur->length && ur->zero) {
int ret;
dwc->ep0_next_event = DWC3_EP0_COMPLETE;
ret = dwc3_ep0_start_trans(dwc, epnum,
dwc->ctrl_req_addr, 0,
DWC3_TRBCTL_CONTROL_DATA);
WARN_ON(ret < 0);
}
} }
} }
......
...@@ -525,12 +525,11 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, ...@@ -525,12 +525,11 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
if (!usb_endpoint_xfer_isoc(desc)) if (!usb_endpoint_xfer_isoc(desc))
return 0; return 0;
memset(&trb_link, 0, sizeof(trb_link));
/* Link TRB for ISOC. The HWO bit is never reset */ /* Link TRB for ISOC. The HWO bit is never reset */
trb_st_hw = &dep->trb_pool[0]; trb_st_hw = &dep->trb_pool[0];
trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1]; trb_link = &dep->trb_pool[DWC3_TRB_NUM - 1];
memset(trb_link, 0, sizeof(*trb_link));
trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); trb_link->bpl = lower_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw)); trb_link->bph = upper_32_bits(dwc3_trb_dma_offset(dep, trb_st_hw));
...@@ -581,7 +580,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) ...@@ -581,7 +580,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
/* make sure HW endpoint isn't stalled */ /* make sure HW endpoint isn't stalled */
if (dep->flags & DWC3_EP_STALL) if (dep->flags & DWC3_EP_STALL)
__dwc3_gadget_ep_set_halt(dep, 0); __dwc3_gadget_ep_set_halt(dep, 0, false);
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg &= ~DWC3_DALEPENA_EP(dep->number); reg &= ~DWC3_DALEPENA_EP(dep->number);
...@@ -1202,15 +1201,28 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, ...@@ -1202,15 +1201,28 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
return ret; return ret;
} }
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
{ {
struct dwc3_gadget_ep_cmd_params params; struct dwc3_gadget_ep_cmd_params params;
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
int ret; int ret;
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name);
return -EINVAL;
}
memset(&params, 0x00, sizeof(params)); memset(&params, 0x00, sizeof(params));
if (value) { if (value) {
if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) ||
(!list_empty(&dep->req_queued) ||
!list_empty(&dep->request_list)))) {
dev_dbg(dwc->dev, "%s: pending request, cannot halt\n",
dep->name);
return -EAGAIN;
}
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
DWC3_DEPCMD_SETSTALL, &params); DWC3_DEPCMD_SETSTALL, &params);
if (ret) if (ret)
...@@ -1241,15 +1253,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value) ...@@ -1241,15 +1253,7 @@ static int dwc3_gadget_ep_set_halt(struct usb_ep *ep, int value)
int ret; int ret;
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_set_halt(dep, value, false);
if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name);
ret = -EINVAL;
goto out;
}
ret = __dwc3_gadget_ep_set_halt(dep, value);
out:
spin_unlock_irqrestore(&dwc->lock, flags); spin_unlock_irqrestore(&dwc->lock, flags);
return ret; return ret;
...@@ -1260,15 +1264,18 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep) ...@@ -1260,15 +1264,18 @@ static int dwc3_gadget_ep_set_wedge(struct usb_ep *ep)
struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc;
unsigned long flags; unsigned long flags;
int ret;
spin_lock_irqsave(&dwc->lock, flags); spin_lock_irqsave(&dwc->lock, flags);
dep->flags |= DWC3_EP_WEDGE; dep->flags |= DWC3_EP_WEDGE;
spin_unlock_irqrestore(&dwc->lock, flags);
if (dep->number == 0 || dep->number == 1) if (dep->number == 0 || dep->number == 1)
return dwc3_gadget_ep0_set_halt(ep, 1); ret = __dwc3_gadget_ep0_set_halt(ep, 1);
else else
return dwc3_gadget_ep_set_halt(ep, 1); ret = __dwc3_gadget_ep_set_halt(dep, 1, false);
spin_unlock_irqrestore(&dwc->lock, flags);
return ret;
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
......
...@@ -82,10 +82,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, ...@@ -82,10 +82,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
void dwc3_ep0_interrupt(struct dwc3 *dwc, void dwc3_ep0_interrupt(struct dwc3 *dwc,
const struct dwc3_event_depevt *event); const struct dwc3_event_depevt *event);
void dwc3_ep0_out_start(struct dwc3 *dwc); void dwc3_ep0_out_start(struct dwc3 *dwc);
int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value); int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
gfp_t gfp_flags); gfp_t gfp_flags);
int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value); int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
/** /**
* dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
......
...@@ -73,15 +73,23 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl, ...@@ -73,15 +73,23 @@ DECLARE_EVENT_CLASS(dwc3_log_ctrl,
TP_PROTO(struct usb_ctrlrequest *ctrl), TP_PROTO(struct usb_ctrlrequest *ctrl),
TP_ARGS(ctrl), TP_ARGS(ctrl),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(struct usb_ctrlrequest *, ctrl) __field(__u8, bRequestType)
__field(__u8, bRequest)
__field(__le16, wValue)
__field(__le16, wIndex)
__field(__le16, wLength)
), ),
TP_fast_assign( TP_fast_assign(
__entry->ctrl = ctrl; __entry->bRequestType = ctrl->bRequestType;
__entry->bRequest = ctrl->bRequest;
__entry->wValue = ctrl->wValue;
__entry->wIndex = ctrl->wIndex;
__entry->wLength = ctrl->wLength;
), ),
TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d", TP_printk("bRequestType %02x bRequest %02x wValue %04x wIndex %04x wLength %d",
__entry->ctrl->bRequestType, __entry->ctrl->bRequest, __entry->bRequestType, __entry->bRequest,
le16_to_cpu(__entry->ctrl->wValue), le16_to_cpu(__entry->ctrl->wIndex), le16_to_cpu(__entry->wValue), le16_to_cpu(__entry->wIndex),
le16_to_cpu(__entry->ctrl->wLength) le16_to_cpu(__entry->wLength)
) )
); );
...@@ -94,15 +102,22 @@ DECLARE_EVENT_CLASS(dwc3_log_request, ...@@ -94,15 +102,22 @@ DECLARE_EVENT_CLASS(dwc3_log_request,
TP_PROTO(struct dwc3_request *req), TP_PROTO(struct dwc3_request *req),
TP_ARGS(req), TP_ARGS(req),
TP_STRUCT__entry( TP_STRUCT__entry(
__dynamic_array(char, name, DWC3_MSG_MAX)
__field(struct dwc3_request *, req) __field(struct dwc3_request *, req)
__field(unsigned, actual)
__field(unsigned, length)
__field(int, status)
), ),
TP_fast_assign( TP_fast_assign(
snprintf(__get_str(name), DWC3_MSG_MAX, "%s", req->dep->name);
__entry->req = req; __entry->req = req;
__entry->actual = req->request.actual;
__entry->length = req->request.length;
__entry->status = req->request.status;
), ),
TP_printk("%s: req %p length %u/%u ==> %d", TP_printk("%s: req %p length %u/%u ==> %d",
__entry->req->dep->name, __entry->req, __get_str(name), __entry->req, __entry->actual, __entry->length,
__entry->req->request.actual, __entry->req->request.length, __entry->status
__entry->req->request.status
) )
); );
...@@ -158,17 +173,17 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd, ...@@ -158,17 +173,17 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd,
struct dwc3_gadget_ep_cmd_params *params), struct dwc3_gadget_ep_cmd_params *params),
TP_ARGS(dep, cmd, params), TP_ARGS(dep, cmd, params),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(struct dwc3_ep *, dep) __dynamic_array(char, name, DWC3_MSG_MAX)
__field(unsigned int, cmd) __field(unsigned int, cmd)
__field(struct dwc3_gadget_ep_cmd_params *, params) __field(struct dwc3_gadget_ep_cmd_params *, params)
), ),
TP_fast_assign( TP_fast_assign(
__entry->dep = dep; snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
__entry->cmd = cmd; __entry->cmd = cmd;
__entry->params = params; __entry->params = params;
), ),
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x\n", TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x\n",
__entry->dep->name, dwc3_gadget_ep_cmd_string(__entry->cmd), __get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->params->param0, __entry->cmd, __entry->params->param0,
__entry->params->param1, __entry->params->param2 __entry->params->param1, __entry->params->param2
) )
...@@ -184,16 +199,24 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, ...@@ -184,16 +199,24 @@ DECLARE_EVENT_CLASS(dwc3_log_trb,
TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb), TP_PROTO(struct dwc3_ep *dep, struct dwc3_trb *trb),
TP_ARGS(dep, trb), TP_ARGS(dep, trb),
TP_STRUCT__entry( TP_STRUCT__entry(
__field(struct dwc3_ep *, dep) __dynamic_array(char, name, DWC3_MSG_MAX)
__field(struct dwc3_trb *, trb) __field(struct dwc3_trb *, trb)
__field(u32, bpl)
__field(u32, bph)
__field(u32, size)
__field(u32, ctrl)
), ),
TP_fast_assign( TP_fast_assign(
__entry->dep = dep; snprintf(__get_str(name), DWC3_MSG_MAX, "%s", dep->name);
__entry->trb = trb; __entry->trb = trb;
__entry->bpl = trb->bpl;
__entry->bph = trb->bph;
__entry->size = trb->size;
__entry->ctrl = trb->ctrl;
), ),
TP_printk("%s: trb %p bph %08x bpl %08x size %08x ctrl %08x\n", TP_printk("%s: trb %p bph %08x bpl %08x size %08x ctrl %08x\n",
__entry->dep->name, __entry->trb, __entry->trb->bph, __get_str(name), __entry->trb, __entry->bph, __entry->bpl,
__entry->trb->bpl, __entry->trb->size, __entry->trb->ctrl __entry->size, __entry->ctrl
) )
); );
......
...@@ -560,7 +560,7 @@ static int bos_desc(struct usb_composite_dev *cdev) ...@@ -560,7 +560,7 @@ static int bos_desc(struct usb_composite_dev *cdev)
usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE; usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY; usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT; usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT); usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT | USB_BESL_SUPPORT);
/* /*
* The Superspeed USB Capability descriptor shall be implemented by all * The Superspeed USB Capability descriptor shall be implemented by all
......
...@@ -433,12 +433,12 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) ...@@ -433,12 +433,12 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
dev_vdbg(&cdev->gadget->dev, dev_vdbg(&cdev->gadget->dev,
"reset acm control interface %d\n", intf); "reset acm control interface %d\n", intf);
usb_ep_disable(acm->notify); usb_ep_disable(acm->notify);
} else { }
dev_vdbg(&cdev->gadget->dev,
"init acm ctrl interface %d\n", intf); if (!acm->notify->desc)
if (config_ep_by_speed(cdev->gadget, f, acm->notify)) if (config_ep_by_speed(cdev->gadget, f, acm->notify))
return -EINVAL; return -EINVAL;
}
usb_ep_enable(acm->notify); usb_ep_enable(acm->notify);
acm->notify->driver_data = acm; acm->notify->driver_data = acm;
......
...@@ -325,7 +325,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -325,7 +325,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
usb_free_all_descriptors(f);
if (eem->port.out_ep) if (eem->port.out_ep)
eem->port.out_ep->driver_data = NULL; eem->port.out_ep->driver_data = NULL;
if (eem->port.in_ep) if (eem->port.in_ep)
......
...@@ -647,15 +647,26 @@ static void ffs_user_copy_worker(struct work_struct *work) ...@@ -647,15 +647,26 @@ static void ffs_user_copy_worker(struct work_struct *work)
if (io_data->read && ret > 0) { if (io_data->read && ret > 0) {
int i; int i;
size_t pos = 0; size_t pos = 0;
/*
* Since req->length may be bigger than io_data->len (after
* being rounded up to maxpacketsize), we may end up with more
* data then user space has space for.
*/
ret = min_t(int, ret, io_data->len);
use_mm(io_data->mm); use_mm(io_data->mm);
for (i = 0; i < io_data->nr_segs; i++) { for (i = 0; i < io_data->nr_segs; i++) {
size_t len = min_t(size_t, ret - pos,
io_data->iovec[i].iov_len);
if (!len)
break;
if (unlikely(copy_to_user(io_data->iovec[i].iov_base, if (unlikely(copy_to_user(io_data->iovec[i].iov_base,
&io_data->buf[pos], &io_data->buf[pos], len))) {
io_data->iovec[i].iov_len))) {
ret = -EFAULT; ret = -EFAULT;
break; break;
} }
pos += io_data->iovec[i].iov_len; pos += len;
} }
unuse_mm(io_data->mm); unuse_mm(io_data->mm);
} }
...@@ -687,7 +698,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ...@@ -687,7 +698,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
struct ffs_epfile *epfile = file->private_data; struct ffs_epfile *epfile = file->private_data;
struct ffs_ep *ep; struct ffs_ep *ep;
char *data = NULL; char *data = NULL;
ssize_t ret, data_len; ssize_t ret, data_len = -EINVAL;
int halt; int halt;
/* Are we still active? */ /* Are we still active? */
...@@ -787,13 +798,30 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ...@@ -787,13 +798,30 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
/* Fire the request */ /* Fire the request */
struct usb_request *req; struct usb_request *req;
/*
* Sanity Check: even though data_len can't be used
* uninitialized at the time I write this comment, some
* compilers complain about this situation.
* In order to keep the code clean from warnings, data_len is
* being initialized to -EINVAL during its declaration, which
* means we can't rely on compiler anymore to warn no future
* changes won't result in data_len being used uninitialized.
* For such reason, we're adding this redundant sanity check
* here.
*/
if (unlikely(data_len == -EINVAL)) {
WARN(1, "%s: data_len == -EINVAL\n", __func__);
ret = -EINVAL;
goto error_lock;
}
if (io_data->aio) { if (io_data->aio) {
req = usb_ep_alloc_request(ep->ep, GFP_KERNEL); req = usb_ep_alloc_request(ep->ep, GFP_KERNEL);
if (unlikely(!req)) if (unlikely(!req))
goto error_lock; goto error_lock;
req->buf = data; req->buf = data;
req->length = io_data->len; req->length = data_len;
io_data->buf = data; io_data->buf = data;
io_data->ep = ep->ep; io_data->ep = ep->ep;
...@@ -815,7 +843,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) ...@@ -815,7 +843,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
req = ep->req; req = ep->req;
req->buf = data; req->buf = data;
req->length = io_data->len; req->length = data_len;
req->context = &done; req->context = &done;
req->complete = ffs_epfile_io_complete; req->complete = ffs_epfile_io_complete;
...@@ -2663,8 +2691,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, ...@@ -2663,8 +2691,6 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f,
func->conf = c; func->conf = c;
func->gadget = c->cdev->gadget; func->gadget = c->cdev->gadget;
ffs_data_get(func->ffs);
/* /*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind() * in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry, * configurations are bound in sequence with list_for_each_entry,
......
...@@ -621,12 +621,14 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -621,12 +621,14 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
dev = MKDEV(major, hidg->minor); dev = MKDEV(major, hidg->minor);
status = cdev_add(&hidg->cdev, dev, 1); status = cdev_add(&hidg->cdev, dev, 1);
if (status) if (status)
goto fail; goto fail_free_descs;
device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor); device_create(hidg_class, NULL, dev, NULL, "%s%d", "hidg", hidg->minor);
return 0; return 0;
fail_free_descs:
usb_free_all_descriptors(f);
fail: fail:
ERROR(f->config->cdev, "hidg_bind FAILED\n"); ERROR(f->config->cdev, "hidg_bind FAILED\n");
if (hidg->req != NULL) { if (hidg->req != NULL) {
...@@ -635,7 +637,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -635,7 +637,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
usb_ep_free_request(hidg->in_ep, hidg->req); usb_ep_free_request(hidg->in_ep, hidg->req);
} }
usb_free_all_descriptors(f);
return status; return status;
} }
......
...@@ -253,22 +253,13 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -253,22 +253,13 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
case 0: /* normal completion? */ case 0: /* normal completion? */
if (ep == loop->out_ep) { if (ep == loop->out_ep) {
/* loop this OUT packet back IN to the host */
req->zero = (req->actual < req->length); req->zero = (req->actual < req->length);
req->length = req->actual; req->length = req->actual;
status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);
if (status == 0)
return;
/* "should never get here" */
ERROR(cdev, "can't loop %s to %s: %d\n",
ep->name, loop->in_ep->name,
status);
} }
/* queue the buffer for some later OUT packet */ /* queue the buffer for some later OUT packet */
req->length = buflen; req->length = buflen;
status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC); status = usb_ep_queue(ep, req, GFP_ATOMIC);
if (status == 0) if (status == 0)
return; return;
...@@ -308,60 +299,66 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len) ...@@ -308,60 +299,66 @@ static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
return alloc_ep_req(ep, len, buflen); return alloc_ep_req(ep, len, buflen);
} }
static int static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop,
enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) struct usb_ep *ep)
{ {
int result = 0;
struct usb_ep *ep;
struct usb_request *req; struct usb_request *req;
unsigned i; unsigned i;
int result;
/* one endpoint writes data back IN to the host */ /*
ep = loop->in_ep; * one endpoint writes data back IN to the host while another endpoint
* just reads OUT packets
*/
result = config_ep_by_speed(cdev->gadget, &(loop->function), ep); result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
if (result) if (result)
return result; goto fail0;
result = usb_ep_enable(ep); result = usb_ep_enable(ep);
if (result < 0) if (result < 0)
return result;
ep->driver_data = loop;
/* one endpoint just reads OUT packets */
ep = loop->out_ep;
result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
if (result)
goto fail0; goto fail0;
result = usb_ep_enable(ep);
if (result < 0) {
fail0:
ep = loop->in_ep;
usb_ep_disable(ep);
ep->driver_data = NULL;
return result;
}
ep->driver_data = loop; ep->driver_data = loop;
/* allocate a bunch of read buffers and queue them all at once. /*
* allocate a bunch of read buffers and queue them all at once.
* we buffer at most 'qlen' transfers; fewer if any need more * we buffer at most 'qlen' transfers; fewer if any need more
* than 'buflen' bytes each. * than 'buflen' bytes each.
*/ */
for (i = 0; i < qlen && result == 0; i++) { for (i = 0; i < qlen && result == 0; i++) {
req = lb_alloc_ep_req(ep, 0); req = lb_alloc_ep_req(ep, 0);
if (req) { if (!req)
goto fail1;
req->complete = loopback_complete; req->complete = loopback_complete;
result = usb_ep_queue(ep, req, GFP_ATOMIC); result = usb_ep_queue(ep, req, GFP_ATOMIC);
if (result) if (result) {
ERROR(cdev, "%s queue req --> %d\n", ERROR(cdev, "%s queue req --> %d\n",
ep->name, result); ep->name, result);
} else { goto fail1;
usb_ep_disable(ep);
ep->driver_data = NULL;
result = -ENOMEM;
goto fail0;
} }
} }
return 0;
fail1:
usb_ep_disable(ep);
fail0:
return result;
}
static int
enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
{
int result = 0;
result = enable_endpoint(cdev, loop, loop->in_ep);
if (result)
return result;
result = enable_endpoint(cdev, loop, loop->out_ep);
if (result)
return result;
DBG(cdev, "%s enabled\n", loop->function.name); DBG(cdev, "%s enabled\n", loop->function.name);
return result; return result;
} }
......
...@@ -1461,7 +1461,6 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -1461,7 +1461,6 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
usb_free_all_descriptors(f);
if (ncm->notify_req) { if (ncm->notify_req) {
kfree(ncm->notify_req->buf); kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req); usb_ep_free_request(ncm->notify, ncm->notify_req);
......
...@@ -35,6 +35,7 @@ struct f_obex { ...@@ -35,6 +35,7 @@ struct f_obex {
struct gserial port; struct gserial port;
u8 ctrl_id; u8 ctrl_id;
u8 data_id; u8 data_id;
u8 cur_alt;
u8 port_num; u8 port_num;
u8 can_activate; u8 can_activate;
}; };
...@@ -235,6 +236,8 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt) ...@@ -235,6 +236,8 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
} else } else
goto fail; goto fail;
obex->cur_alt = alt;
return 0; return 0;
fail: fail:
...@@ -245,10 +248,7 @@ static int obex_get_alt(struct usb_function *f, unsigned intf) ...@@ -245,10 +248,7 @@ static int obex_get_alt(struct usb_function *f, unsigned intf)
{ {
struct f_obex *obex = func_to_obex(f); struct f_obex *obex = func_to_obex(f);
if (intf == obex->ctrl_id) return obex->cur_alt;
return 0;
return obex->port.in->driver_data ? 1 : 0;
} }
static void obex_disable(struct usb_function *f) static void obex_disable(struct usb_function *f)
...@@ -397,7 +397,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -397,7 +397,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
usb_free_all_descriptors(f);
/* we might as well release our claims on endpoints */ /* we might as well release our claims on endpoints */
if (obex->port.out) if (obex->port.out)
obex->port.out->driver_data = NULL; obex->port.out->driver_data = NULL;
......
...@@ -570,8 +570,8 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -570,8 +570,8 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f)
err_req: err_req:
for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++) for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
err:
usb_free_all_descriptors(f); usb_free_all_descriptors(f);
err:
if (fp->out_ep) if (fp->out_ep)
fp->out_ep->driver_data = NULL; fp->out_ep->driver_data = NULL;
if (fp->in_ep) if (fp->in_ep)
......
...@@ -802,8 +802,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -802,8 +802,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
if (rndis->manufacturer && rndis->vendorID && if (rndis->manufacturer && rndis->vendorID &&
rndis_set_param_vendor(rndis->config, rndis->vendorID, rndis_set_param_vendor(rndis->config, rndis->vendorID,
rndis->manufacturer)) rndis->manufacturer)) {
goto fail; status = -EINVAL;
goto fail_free_descs;
}
/* NOTE: all that is done without knowing or caring about /* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code * the network link ... which is unavailable to this code
...@@ -817,10 +819,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -817,10 +819,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis->notify->name); rndis->notify->name);
return 0; return 0;
fail_free_descs:
usb_free_all_descriptors(f);
fail: fail:
kfree(f->os_desc_table); kfree(f->os_desc_table);
f->os_desc_n = 0; f->os_desc_n = 0;
usb_free_all_descriptors(f);
if (rndis->notify_req) { if (rndis->notify_req) {
kfree(rndis->notify_req->buf); kfree(rndis->notify_req->buf);
......
...@@ -380,7 +380,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -380,7 +380,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
usb_free_all_descriptors(f);
/* we might as well release our claims on endpoints */ /* we might as well release our claims on endpoints */
if (geth->port.out_ep) if (geth->port.out_ep)
geth->port.out_ep->driver_data = NULL; geth->port.out_ep->driver_data = NULL;
......
...@@ -512,6 +512,11 @@ static int snd_uac2_remove(struct platform_device *pdev) ...@@ -512,6 +512,11 @@ static int snd_uac2_remove(struct platform_device *pdev)
return 0; return 0;
} }
static void snd_uac2_release(struct device *dev)
{
dev_dbg(dev, "releasing '%s'\n", dev_name(dev));
}
static int alsa_uac2_init(struct audio_dev *agdev) static int alsa_uac2_init(struct audio_dev *agdev)
{ {
struct snd_uac2_chip *uac2 = &agdev->uac2; struct snd_uac2_chip *uac2 = &agdev->uac2;
...@@ -523,6 +528,7 @@ static int alsa_uac2_init(struct audio_dev *agdev) ...@@ -523,6 +528,7 @@ static int alsa_uac2_init(struct audio_dev *agdev)
uac2->pdev.id = 0; uac2->pdev.id = 0;
uac2->pdev.name = uac2_name; uac2->pdev.name = uac2_name;
uac2->pdev.dev.release = snd_uac2_release;
/* Register snd_uac2 driver */ /* Register snd_uac2 driver */
err = platform_driver_register(&uac2->pdrv); err = platform_driver_register(&uac2->pdrv);
...@@ -772,6 +778,7 @@ struct usb_endpoint_descriptor fs_epout_desc = { ...@@ -772,6 +778,7 @@ struct usb_endpoint_descriptor fs_epout_desc = {
.bEndpointAddress = USB_DIR_OUT, .bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
.wMaxPacketSize = cpu_to_le16(1023),
.bInterval = 1, .bInterval = 1,
}; };
...@@ -780,6 +787,7 @@ struct usb_endpoint_descriptor hs_epout_desc = { ...@@ -780,6 +787,7 @@ struct usb_endpoint_descriptor hs_epout_desc = {
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
.wMaxPacketSize = cpu_to_le16(1024),
.bInterval = 4, .bInterval = 4,
}; };
...@@ -847,6 +855,7 @@ struct usb_endpoint_descriptor fs_epin_desc = { ...@@ -847,6 +855,7 @@ struct usb_endpoint_descriptor fs_epin_desc = {
.bEndpointAddress = USB_DIR_IN, .bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
.wMaxPacketSize = cpu_to_le16(1023),
.bInterval = 1, .bInterval = 1,
}; };
...@@ -855,6 +864,7 @@ struct usb_endpoint_descriptor hs_epin_desc = { ...@@ -855,6 +864,7 @@ struct usb_endpoint_descriptor hs_epin_desc = {
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
.wMaxPacketSize = cpu_to_le16(1024),
.bInterval = 4, .bInterval = 4,
}; };
...@@ -947,6 +957,9 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) ...@@ -947,6 +957,9 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep)
struct snd_uac2_chip *uac2 = prm->uac2; struct snd_uac2_chip *uac2 = prm->uac2;
int i; int i;
if (!prm->ep_enabled)
return;
prm->ep_enabled = false; prm->ep_enabled = false;
for (i = 0; i < USB_XFERS; i++) { for (i = 0; i < USB_XFERS; i++) {
...@@ -1071,7 +1084,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) ...@@ -1071,7 +1084,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
if (!prm->rbuf) { if (!prm->rbuf) {
prm->max_psize = 0; prm->max_psize = 0;
goto err; goto err_free_descs;
} }
prm = &agdev->uac2.p_prm; prm = &agdev->uac2.p_prm;
...@@ -1079,17 +1092,19 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) ...@@ -1079,17 +1092,19 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
if (!prm->rbuf) { if (!prm->rbuf) {
prm->max_psize = 0; prm->max_psize = 0;
goto err; goto err_free_descs;
} }
ret = alsa_uac2_init(agdev); ret = alsa_uac2_init(agdev);
if (ret) if (ret)
goto err; goto err_free_descs;
return 0; return 0;
err_free_descs:
usb_free_all_descriptors(fn);
err: err:
kfree(agdev->uac2.p_prm.rbuf); kfree(agdev->uac2.p_prm.rbuf);
kfree(agdev->uac2.c_prm.rbuf); kfree(agdev->uac2.c_prm.rbuf);
usb_free_all_descriptors(fn);
if (agdev->in_ep) if (agdev->in_ep)
agdev->in_ep->driver_data = NULL; agdev->in_ep->driver_data = NULL;
if (agdev->out_ep) if (agdev->out_ep)
......
...@@ -279,27 +279,41 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface) ...@@ -279,27 +279,41 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
else if (interface != uvc->streaming_intf) else if (interface != uvc->streaming_intf)
return -EINVAL; return -EINVAL;
else else
return uvc->state == UVC_STATE_STREAMING ? 1 : 0; return uvc->video.ep->driver_data ? 1 : 0;
} }
static int static int
uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
{ {
struct uvc_device *uvc = to_uvc(f); struct uvc_device *uvc = to_uvc(f);
struct usb_composite_dev *cdev = f->config->cdev;
struct v4l2_event v4l2_event; struct v4l2_event v4l2_event;
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
int ret; int ret;
INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
if (interface == uvc->control_intf) { if (interface == uvc->control_intf) {
if (alt) if (alt)
return -EINVAL; return -EINVAL;
if (uvc->control_ep->driver_data) {
INFO(cdev, "reset UVC Control\n");
usb_ep_disable(uvc->control_ep);
uvc->control_ep->driver_data = NULL;
}
if (!uvc->control_ep->desc)
if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep))
return -EINVAL;
usb_ep_enable(uvc->control_ep);
uvc->control_ep->driver_data = uvc;
if (uvc->state == UVC_STATE_DISCONNECTED) { if (uvc->state == UVC_STATE_DISCONNECTED) {
memset(&v4l2_event, 0, sizeof(v4l2_event)); memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_CONNECT; v4l2_event.type = UVC_EVENT_CONNECT;
uvc_event->speed = f->config->cdev->gadget->speed; uvc_event->speed = cdev->gadget->speed;
v4l2_event_queue(uvc->vdev, &v4l2_event); v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_CONNECTED; uvc->state = UVC_STATE_CONNECTED;
...@@ -321,8 +335,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) ...@@ -321,8 +335,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (uvc->state != UVC_STATE_STREAMING) if (uvc->state != UVC_STATE_STREAMING)
return 0; return 0;
if (uvc->video.ep) if (uvc->video.ep) {
usb_ep_disable(uvc->video.ep); usb_ep_disable(uvc->video.ep);
uvc->video.ep->driver_data = NULL;
}
memset(&v4l2_event, 0, sizeof(v4l2_event)); memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMOFF; v4l2_event.type = UVC_EVENT_STREAMOFF;
...@@ -335,13 +351,21 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) ...@@ -335,13 +351,21 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
if (uvc->state != UVC_STATE_CONNECTED) if (uvc->state != UVC_STATE_CONNECTED)
return 0; return 0;
if (uvc->video.ep) { if (!uvc->video.ep)
return -EINVAL;
if (uvc->video.ep->driver_data) {
INFO(cdev, "reset UVC\n");
usb_ep_disable(uvc->video.ep);
uvc->video.ep->driver_data = NULL;
}
ret = config_ep_by_speed(f->config->cdev->gadget, ret = config_ep_by_speed(f->config->cdev->gadget,
&(uvc->func), uvc->video.ep); &(uvc->func), uvc->video.ep);
if (ret) if (ret)
return ret; return ret;
usb_ep_enable(uvc->video.ep); usb_ep_enable(uvc->video.ep);
} uvc->video.ep->driver_data = uvc;
memset(&v4l2_event, 0, sizeof(v4l2_event)); memset(&v4l2_event, 0, sizeof(v4l2_event));
v4l2_event.type = UVC_EVENT_STREAMON; v4l2_event.type = UVC_EVENT_STREAMON;
...@@ -366,6 +390,16 @@ uvc_function_disable(struct usb_function *f) ...@@ -366,6 +390,16 @@ uvc_function_disable(struct usb_function *f)
v4l2_event_queue(uvc->vdev, &v4l2_event); v4l2_event_queue(uvc->vdev, &v4l2_event);
uvc->state = UVC_STATE_DISCONNECTED; uvc->state = UVC_STATE_DISCONNECTED;
if (uvc->video.ep->driver_data) {
usb_ep_disable(uvc->video.ep);
uvc->video.ep->driver_data = NULL;
}
if (uvc->control_ep->driver_data) {
usb_ep_disable(uvc->control_ep);
uvc->control_ep->driver_data = NULL;
}
} }
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
......
...@@ -352,6 +352,7 @@ int uvcg_video_enable(struct uvc_video *video, int enable) ...@@ -352,6 +352,7 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
if (!enable) { if (!enable) {
for (i = 0; i < UVC_NUM_REQUESTS; ++i) for (i = 0; i < UVC_NUM_REQUESTS; ++i)
if (video->req[i])
usb_ep_dequeue(video->ep, video->req[i]); usb_ep_dequeue(video->ep, video->req[i]);
uvc_video_free_requests(video); uvc_video_free_requests(video);
......
...@@ -357,6 +357,7 @@ config USB_EG20T ...@@ -357,6 +357,7 @@ config USB_EG20T
config USB_GADGET_XILINX config USB_GADGET_XILINX
tristate "Xilinx USB Driver" tristate "Xilinx USB Driver"
depends on HAS_DMA
depends on OF || COMPILE_TEST depends on OF || COMPILE_TEST
help help
USB peripheral controller driver for Xilinx USB2 device. USB peripheral controller driver for Xilinx USB2 device.
......
...@@ -507,6 +507,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev, ...@@ -507,6 +507,11 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
{ {
struct usb_udc *udc = container_of(dev, struct usb_udc, dev); struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
if (!udc->driver) {
dev_err(dev, "soft-connect without a gadget driver\n");
return -EOPNOTSUPP;
}
if (sysfs_streq(buf, "connect")) { if (sysfs_streq(buf, "connect")) {
usb_gadget_udc_start(udc->gadget, udc->driver); usb_gadget_udc_start(udc->gadget, udc->driver);
usb_gadget_connect(udc->gadget); usb_gadget_connect(udc->gadget);
......
...@@ -209,7 +209,8 @@ static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer) ...@@ -209,7 +209,8 @@ static enum hrtimer_restart cppi41_recheck_tx_req(struct hrtimer *timer)
} }
} }
if (!list_empty(&controller->early_tx_list)) { if (!list_empty(&controller->early_tx_list) &&
!hrtimer_is_queued(&controller->early_tx)) {
ret = HRTIMER_RESTART; ret = HRTIMER_RESTART;
hrtimer_forward_now(&controller->early_tx, hrtimer_forward_now(&controller->early_tx,
ktime_set(0, 20 * NSEC_PER_USEC)); ktime_set(0, 20 * NSEC_PER_USEC));
......
...@@ -868,9 +868,15 @@ static int dsps_suspend(struct device *dev) ...@@ -868,9 +868,15 @@ static int dsps_suspend(struct device *dev)
struct dsps_glue *glue = dev_get_drvdata(dev); struct dsps_glue *glue = dev_get_drvdata(dev);
const struct dsps_musb_wrapper *wrp = glue->wrp; const struct dsps_musb_wrapper *wrp = glue->wrp;
struct musb *musb = platform_get_drvdata(glue->musb); struct musb *musb = platform_get_drvdata(glue->musb);
void __iomem *mbase = musb->ctrl_base; void __iomem *mbase;
del_timer_sync(&glue->timer); del_timer_sync(&glue->timer);
if (!musb)
/* This can happen if the musb device is in -EPROBE_DEFER */
return 0;
mbase = musb->ctrl_base;
glue->context.control = dsps_readl(mbase, wrp->control); glue->context.control = dsps_readl(mbase, wrp->control);
glue->context.epintr = dsps_readl(mbase, wrp->epintr_set); glue->context.epintr = dsps_readl(mbase, wrp->epintr_set);
glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set); glue->context.coreintr = dsps_readl(mbase, wrp->coreintr_set);
...@@ -887,8 +893,12 @@ static int dsps_resume(struct device *dev) ...@@ -887,8 +893,12 @@ static int dsps_resume(struct device *dev)
struct dsps_glue *glue = dev_get_drvdata(dev); struct dsps_glue *glue = dev_get_drvdata(dev);
const struct dsps_musb_wrapper *wrp = glue->wrp; const struct dsps_musb_wrapper *wrp = glue->wrp;
struct musb *musb = platform_get_drvdata(glue->musb); struct musb *musb = platform_get_drvdata(glue->musb);
void __iomem *mbase = musb->ctrl_base; void __iomem *mbase;
if (!musb)
return 0;
mbase = musb->ctrl_base;
dsps_writel(mbase, wrp->control, glue->context.control); dsps_writel(mbase, wrp->control, glue->context.control);
dsps_writel(mbase, wrp->epintr_set, glue->context.epintr); dsps_writel(mbase, wrp->epintr_set, glue->context.epintr);
dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr); dsps_writel(mbase, wrp->coreintr_set, glue->context.coreintr);
...@@ -896,7 +906,9 @@ static int dsps_resume(struct device *dev) ...@@ -896,7 +906,9 @@ static int dsps_resume(struct device *dev)
dsps_writel(mbase, wrp->mode, glue->context.mode); dsps_writel(mbase, wrp->mode, glue->context.mode);
dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode); dsps_writel(mbase, wrp->tx_mode, glue->context.tx_mode);
dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode); dsps_writel(mbase, wrp->rx_mode, glue->context.rx_mode);
setup_timer(&glue->timer, otg_timer, (unsigned long) musb); if (musb->xceiv->state == OTG_STATE_B_IDLE &&
musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ);
return 0; return 0;
} }
......
...@@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = { ...@@ -155,6 +155,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
{ USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
{ USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
{ USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */ { USB_DEVICE(0x1D6F, 0x0010) }, /* Seluxit ApS RF Dongle */
{ USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
......
...@@ -140,6 +140,7 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = { ...@@ -140,6 +140,7 @@ static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
* /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report. * /sys/bus/usb-serial/drivers/ftdi_sio/new_id and send a patch or report.
*/ */
static const struct usb_device_id id_table_combined[] = { static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_BRICK_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
...@@ -661,6 +662,8 @@ static const struct usb_device_id id_table_combined[] = { ...@@ -661,6 +662,8 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
{ USB_DEVICE(XSENS_VID, XSENS_AWINDA_DONGLE_PID) },
{ USB_DEVICE(XSENS_VID, XSENS_AWINDA_STATION_PID) },
{ USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) }, { USB_DEVICE(XSENS_VID, XSENS_CONVERTER_PID) },
{ USB_DEVICE(XSENS_VID, XSENS_MTW_PID) }, { USB_DEVICE(XSENS_VID, XSENS_MTW_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
......
...@@ -30,6 +30,12 @@ ...@@ -30,6 +30,12 @@
/*** third-party PIDs (using FTDI_VID) ***/ /*** third-party PIDs (using FTDI_VID) ***/
/*
* Certain versions of the official Windows FTDI driver reprogrammed
* counterfeit FTDI devices to PID 0. Support these devices anyway.
*/
#define FTDI_BRICK_PID 0x0000
#define FTDI_LUMEL_PD12_PID 0x6002 #define FTDI_LUMEL_PD12_PID 0x6002
/* /*
...@@ -143,8 +149,12 @@ ...@@ -143,8 +149,12 @@
* Xsens Technologies BV products (http://www.xsens.com). * Xsens Technologies BV products (http://www.xsens.com).
*/ */
#define XSENS_VID 0x2639 #define XSENS_VID 0x2639
#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */ #define XSENS_AWINDA_STATION_PID 0x0101
#define XSENS_AWINDA_DONGLE_PID 0x0102
#define XSENS_MTW_PID 0x0200 /* Xsens MTw */ #define XSENS_MTW_PID 0x0200 /* Xsens MTw */
#define XSENS_CONVERTER_PID 0xD00D /* Xsens USB-serial converter */
/* Xsens devices using FTDI VID */
#define XSENS_CONVERTER_0_PID 0xD388 /* Xsens USB converter */ #define XSENS_CONVERTER_0_PID 0xD388 /* Xsens USB converter */
#define XSENS_CONVERTER_1_PID 0xD389 /* Xsens Wireless Receiver */ #define XSENS_CONVERTER_1_PID 0xD389 /* Xsens Wireless Receiver */
#define XSENS_CONVERTER_2_PID 0xD38A #define XSENS_CONVERTER_2_PID 0xD38A
......
...@@ -414,8 +414,6 @@ static int kobil_tiocmset(struct tty_struct *tty, ...@@ -414,8 +414,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
int result; int result;
int dtr = 0; int dtr = 0;
int rts = 0; int rts = 0;
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
/* FIXME: locking ? */ /* FIXME: locking ? */
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
...@@ -425,11 +423,6 @@ static int kobil_tiocmset(struct tty_struct *tty, ...@@ -425,11 +423,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
return -EINVAL; return -EINVAL;
} }
/* allocate memory for transfer buffer */
transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
if (!transfer_buffer)
return -ENOMEM;
if (set & TIOCM_RTS) if (set & TIOCM_RTS)
rts = 1; rts = 1;
if (set & TIOCM_DTR) if (set & TIOCM_DTR)
...@@ -469,7 +462,6 @@ static int kobil_tiocmset(struct tty_struct *tty, ...@@ -469,7 +462,6 @@ static int kobil_tiocmset(struct tty_struct *tty,
KOBIL_TIMEOUT); KOBIL_TIMEOUT);
} }
dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result); dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result);
kfree(transfer_buffer);
return (result < 0) ? result : 0; return (result < 0) ? result : 0;
} }
...@@ -530,8 +522,6 @@ static int kobil_ioctl(struct tty_struct *tty, ...@@ -530,8 +522,6 @@ static int kobil_ioctl(struct tty_struct *tty,
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct kobil_private *priv = usb_get_serial_port_data(port); struct kobil_private *priv = usb_get_serial_port_data(port);
unsigned char *transfer_buffer;
int transfer_buffer_length = 8;
int result; int result;
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID ||
...@@ -541,10 +531,6 @@ static int kobil_ioctl(struct tty_struct *tty, ...@@ -541,10 +531,6 @@ static int kobil_ioctl(struct tty_struct *tty,
switch (cmd) { switch (cmd) {
case TCFLSH: case TCFLSH:
transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
if (!transfer_buffer)
return -ENOBUFS;
result = usb_control_msg(port->serial->dev, result = usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0), usb_sndctrlpipe(port->serial->dev, 0),
SUSBCRequest_Misc, SUSBCRequest_Misc,
...@@ -559,7 +545,6 @@ static int kobil_ioctl(struct tty_struct *tty, ...@@ -559,7 +545,6 @@ static int kobil_ioctl(struct tty_struct *tty,
dev_dbg(&port->dev, dev_dbg(&port->dev,
"%s - Send reset_all_queues (FLUSH) URB returns: %i\n", "%s - Send reset_all_queues (FLUSH) URB returns: %i\n",
__func__, result); __func__, result);
kfree(transfer_buffer);
return (result < 0) ? -EIO: 0; return (result < 0) ? -EIO: 0;
default: default:
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
......
...@@ -269,6 +269,7 @@ static void option_instat_callback(struct urb *urb); ...@@ -269,6 +269,7 @@ static void option_instat_callback(struct urb *urb);
#define TELIT_PRODUCT_DE910_DUAL 0x1010 #define TELIT_PRODUCT_DE910_DUAL 0x1010
#define TELIT_PRODUCT_UE910_V2 0x1012 #define TELIT_PRODUCT_UE910_V2 0x1012
#define TELIT_PRODUCT_LE920 0x1200 #define TELIT_PRODUCT_LE920 0x1200
#define TELIT_PRODUCT_LE910 0x1201
/* ZTE PRODUCTS */ /* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2 #define ZTE_VENDOR_ID 0x19d2
...@@ -362,6 +363,7 @@ static void option_instat_callback(struct urb *urb); ...@@ -362,6 +363,7 @@ static void option_instat_callback(struct urb *urb);
/* Haier products */ /* Haier products */
#define HAIER_VENDOR_ID 0x201e #define HAIER_VENDOR_ID 0x201e
#define HAIER_PRODUCT_CE81B 0x10f8
#define HAIER_PRODUCT_CE100 0x2009 #define HAIER_PRODUCT_CE100 0x2009
/* Cinterion (formerly Siemens) products */ /* Cinterion (formerly Siemens) products */
...@@ -589,6 +591,11 @@ static const struct option_blacklist_info zte_1255_blacklist = { ...@@ -589,6 +591,11 @@ static const struct option_blacklist_info zte_1255_blacklist = {
.reserved = BIT(3) | BIT(4), .reserved = BIT(3) | BIT(4),
}; };
static const struct option_blacklist_info telit_le910_blacklist = {
.sendsetup = BIT(0),
.reserved = BIT(1) | BIT(2),
};
static const struct option_blacklist_info telit_le920_blacklist = { static const struct option_blacklist_info telit_le920_blacklist = {
.sendsetup = BIT(0), .sendsetup = BIT(0),
.reserved = BIT(1) | BIT(5), .reserved = BIT(1) | BIT(5),
...@@ -1138,6 +1145,8 @@ static const struct usb_device_id option_ids[] = { ...@@ -1138,6 +1145,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
.driver_info = (kernel_ulong_t)&telit_le920_blacklist }, .driver_info = (kernel_ulong_t)&telit_le920_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
...@@ -1621,6 +1630,7 @@ static const struct usb_device_id option_ids[] = { ...@@ -1621,6 +1630,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
{ USB_DEVICE_AND_INTERFACE_INFO(HAIER_VENDOR_ID, HAIER_PRODUCT_CE81B, 0xff, 0xff, 0xff) },
/* Pirelli */ /* Pirelli */
{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) }, { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1, 0xff) },
{ USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) }, { USB_DEVICE_INTERFACE_CLASS(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_2, 0xff) },
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册