summaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorClark Williams <williams@redhat.com>2012-04-04 10:52:26 -0500
committerClark Williams <williams@redhat.com>2012-04-04 10:52:26 -0500
commit2d93eaf2d4ace5853a74a4b0596f601aa62cb840 (patch)
treeb0a2e2083c1749c4e3b8ae23db7bb13a7ca9aafe /drivers/usb
parent003133585fc61d7bd36d3a097d7fde62e64a9550 (diff)
parent23d8c3f8f494c8516c9b4c05529e118e6a485956 (diff)
Merge commit 'v3.2.14' into rt-3.2.14-rt23v3.2.14-rt23
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/class/cdc-wdm.c17
-rw-r--r--drivers/usb/dwc3/gadget.c24
-rw-r--r--drivers/usb/gadget/f_subset.c34
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c18
-rw-r--r--drivers/usb/gadget/hid.c6
-rw-r--r--drivers/usb/gadget/inode.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c4
-rw-r--r--drivers/usb/host/ehci-fsl.h1
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c1
-rw-r--r--drivers/usb/musb/musb_gadget.c18
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c6
-rw-r--r--drivers/usb/serial/cp210x.c44
-rw-r--r--drivers/usb/serial/ftdi_sio.c32
-rw-r--r--drivers/usb/serial/ftdi_sio.h3
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h19
-rw-r--r--drivers/usb/serial/generic.c4
-rw-r--r--drivers/usb/serial/mos7840.c83
-rw-r--r--drivers/usb/serial/option.c16
-rw-r--r--drivers/usb/serial/qcserial.c109
-rw-r--r--drivers/usb/storage/realtek_cr.c8
20 files changed, 317 insertions, 132 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index fd4aee188fe9..9eb71d8e1a27 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -397,7 +397,7 @@ outnl:
static ssize_t wdm_read
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
- int rv, cntr = 0;
+ int rv, cntr;
int i = 0;
struct wdm_device *desc = file->private_data;
@@ -406,7 +406,8 @@ static ssize_t wdm_read
if (rv < 0)
return -ERESTARTSYS;
- if (desc->length == 0) {
+ cntr = ACCESS_ONCE(desc->length);
+ if (cntr == 0) {
desc->read = 0;
retry:
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
@@ -456,26 +457,30 @@ retry:
spin_unlock_irq(&desc->iuspin);
goto retry;
}
- clear_bit(WDM_READ, &desc->flags);
+ cntr = desc->length;
spin_unlock_irq(&desc->iuspin);
}
- cntr = count > desc->length ? desc->length : count;
+ if (cntr > count)
+ cntr = count;
rv = copy_to_user(buffer, desc->ubuf, cntr);
if (rv > 0) {
rv = -EFAULT;
goto err;
}
+ spin_lock_irq(&desc->iuspin);
+
for (i = 0; i < desc->length - cntr; i++)
desc->ubuf[i] = desc->ubuf[i + cntr];
- spin_lock_irq(&desc->iuspin);
desc->length -= cntr;
- spin_unlock_irq(&desc->iuspin);
/* in case we had outstanding data */
if (!desc->length)
clear_bit(WDM_READ, &desc->flags);
+
+ spin_unlock_irq(&desc->iuspin);
+
rv = cntr;
err:
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 25dbd8614e72..3700aa6ba7bf 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -449,16 +449,16 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_CONTROL:
- strncat(dep->name, "-control", sizeof(dep->name));
+ strlcat(dep->name, "-control", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_ISOC:
- strncat(dep->name, "-isoc", sizeof(dep->name));
+ strlcat(dep->name, "-isoc", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_BULK:
- strncat(dep->name, "-bulk", sizeof(dep->name));
+ strlcat(dep->name, "-bulk", sizeof(dep->name));
break;
case USB_ENDPOINT_XFER_INT:
- strncat(dep->name, "-int", sizeof(dep->name));
+ strlcat(dep->name, "-int", sizeof(dep->name));
break;
default:
dev_err(dwc->dev, "invalid endpoint transfer type\n");
@@ -1405,7 +1405,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
{
- u32 uf;
+ u32 uf, mask;
if (list_empty(&dep->request_list)) {
dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
@@ -1413,16 +1413,10 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
return;
}
- if (event->parameters) {
- u32 mask;
-
- mask = ~(dep->interval - 1);
- uf = event->parameters & mask;
- /* 4 micro frames in the future */
- uf += dep->interval * 4;
- } else {
- uf = 0;
- }
+ mask = ~(dep->interval - 1);
+ uf = event->parameters & mask;
+ /* 4 micro frames in the future */
+ uf += dep->interval * 4;
__dwc3_gadget_kick_transfer(dep, uf, 1);
}
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index c1540648125a..21ab474aca07 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -74,7 +74,7 @@ static inline struct f_gether *func_to_geth(struct usb_function *f)
/* interface descriptor: */
-static struct usb_interface_descriptor subset_data_intf __initdata = {
+static struct usb_interface_descriptor subset_data_intf = {
.bLength = sizeof subset_data_intf,
.bDescriptorType = USB_DT_INTERFACE,
@@ -87,7 +87,7 @@ static struct usb_interface_descriptor subset_data_intf __initdata = {
/* .iInterface = DYNAMIC */
};
-static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
+static struct usb_cdc_header_desc mdlm_header_desc = {
.bLength = sizeof mdlm_header_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_HEADER_TYPE,
@@ -95,7 +95,7 @@ static struct usb_cdc_header_desc mdlm_header_desc __initdata = {
.bcdCDC = cpu_to_le16(0x0110),
};
-static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
+static struct usb_cdc_mdlm_desc mdlm_desc = {
.bLength = sizeof mdlm_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_MDLM_TYPE,
@@ -111,7 +111,7 @@ static struct usb_cdc_mdlm_desc mdlm_desc __initdata = {
* can't really use its struct. All we do here is say that we're using
* the submode of "SAFE" which directly matches the CDC Subset.
*/
-static u8 mdlm_detail_desc[] __initdata = {
+static u8 mdlm_detail_desc[] = {
6,
USB_DT_CS_INTERFACE,
USB_CDC_MDLM_DETAIL_TYPE,
@@ -121,7 +121,7 @@ static u8 mdlm_detail_desc[] __initdata = {
0, /* network data capabilities ("raw" encapsulation) */
};
-static struct usb_cdc_ether_desc ether_desc __initdata = {
+static struct usb_cdc_ether_desc ether_desc = {
.bLength = sizeof ether_desc,
.bDescriptorType = USB_DT_CS_INTERFACE,
.bDescriptorSubType = USB_CDC_ETHERNET_TYPE,
@@ -136,7 +136,7 @@ static struct usb_cdc_ether_desc ether_desc __initdata = {
/* full speed support: */
-static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -144,7 +144,7 @@ static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor fs_subset_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -152,7 +152,7 @@ static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
};
-static struct usb_descriptor_header *fs_eth_function[] __initdata = {
+static struct usb_descriptor_header *fs_eth_function[] = {
(struct usb_descriptor_header *) &subset_data_intf,
(struct usb_descriptor_header *) &mdlm_header_desc,
(struct usb_descriptor_header *) &mdlm_desc,
@@ -165,7 +165,7 @@ static struct usb_descriptor_header *fs_eth_function[] __initdata = {
/* high speed support: */
-static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -173,7 +173,7 @@ static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
-static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor hs_subset_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -181,7 +181,7 @@ static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(512),
};
-static struct usb_descriptor_header *hs_eth_function[] __initdata = {
+static struct usb_descriptor_header *hs_eth_function[] = {
(struct usb_descriptor_header *) &subset_data_intf,
(struct usb_descriptor_header *) &mdlm_header_desc,
(struct usb_descriptor_header *) &mdlm_desc,
@@ -194,7 +194,7 @@ static struct usb_descriptor_header *hs_eth_function[] __initdata = {
/* super speed support: */
-static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = {
+static struct usb_endpoint_descriptor ss_subset_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -202,7 +202,7 @@ static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(1024),
};
-static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = {
+static struct usb_endpoint_descriptor ss_subset_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
@@ -210,7 +210,7 @@ static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = {
.wMaxPacketSize = cpu_to_le16(1024),
};
-static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc = {
.bLength = sizeof ss_subset_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
@@ -219,7 +219,7 @@ static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = {
/* .bmAttributes = 0, */
};
-static struct usb_descriptor_header *ss_eth_function[] __initdata = {
+static struct usb_descriptor_header *ss_eth_function[] = {
(struct usb_descriptor_header *) &subset_data_intf,
(struct usb_descriptor_header *) &mdlm_header_desc,
(struct usb_descriptor_header *) &mdlm_desc,
@@ -290,7 +290,7 @@ static void geth_disable(struct usb_function *f)
/* serial function driver setup/binding */
-static int __init
+static int
geth_bind(struct usb_configuration *c, struct usb_function *f)
{
struct usb_composite_dev *cdev = c->cdev;
@@ -404,7 +404,7 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
* Caller must have called @gether_setup(). Caller is also responsible
* for calling @gether_cleanup() before module unload.
*/
-int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
{
struct f_gether *geth;
int status;
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index dd28ef3def71..8e3e509f3a53 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -768,7 +768,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
* @is_last: return flag if it is the last dTD of the request
* return: pointer to the built dTD */
static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
- dma_addr_t *dma, int *is_last)
+ dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
{
u32 swap_temp;
struct ep_td_struct *dtd;
@@ -777,7 +777,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
*length = min(req->req.length - req->req.actual,
(unsigned)EP_MAX_LENGTH_TRANSFER);
- dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma);
+ dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
if (dtd == NULL)
return dtd;
@@ -827,7 +827,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
}
/* Generate dtd chain for a request */
-static int fsl_req_to_dtd(struct fsl_req *req)
+static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
{
unsigned count;
int is_last;
@@ -836,7 +836,7 @@ static int fsl_req_to_dtd(struct fsl_req *req)
dma_addr_t dma;
do {
- dtd = fsl_build_dtd(req, &count, &dma, &is_last);
+ dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
if (dtd == NULL)
return -ENOMEM;
@@ -910,13 +910,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req->req.actual = 0;
req->dtd_count = 0;
- spin_lock_irqsave(&udc->lock, flags);
-
/* build dtds and push them to device queue */
- if (!fsl_req_to_dtd(req)) {
+ if (!fsl_req_to_dtd(req, gfp_flags)) {
+ spin_lock_irqsave(&udc->lock, flags);
fsl_queue_td(ep, req);
} else {
- spin_unlock_irqrestore(&udc->lock, flags);
return -ENOMEM;
}
@@ -1295,7 +1293,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 1;
- if (fsl_req_to_dtd(req) == 0)
+ if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
fsl_queue_td(ep, req);
else
return -ENOMEM;
@@ -1379,7 +1377,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
req->mapped = 1;
/* prime the data phase */
- if ((fsl_req_to_dtd(req) == 0))
+ if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
fsl_queue_td(ep, req);
else /* no mem */
goto stall;
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index f888c3ede860..3493adf064f5 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -60,9 +60,9 @@ static struct usb_device_descriptor device_desc = {
/* .bDeviceClass = USB_CLASS_COMM, */
/* .bDeviceSubClass = 0, */
/* .bDeviceProtocol = 0, */
- .bDeviceClass = 0xEF,
- .bDeviceSubClass = 2,
- .bDeviceProtocol = 1,
+ .bDeviceClass = USB_CLASS_PER_INTERFACE,
+ .bDeviceSubClass = 0,
+ .bDeviceProtocol = 0,
/* .bMaxPacketSize0 = f(hardware) */
/* Vendor and product id can be overridden by module parameters. */
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 6ccae2707e59..71385402f4c1 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1043,6 +1043,8 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
// FIXME don't call this with the spinlock held ...
if (copy_to_user (buf, dev->req->buf, len))
retval = -EFAULT;
+ else
+ retval = len;
clean_req (dev->gadget->ep0, dev->req);
/* NOTE userspace can't yet choose to stall */
}
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index b556a72264d1..da487fde475f 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -216,6 +216,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
unsigned int port_offset)
{
u32 portsc;
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+ void __iomem *non_ehci = hcd->regs;
portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
@@ -231,6 +233,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
portsc |= PORT_PTS_PTW;
/* fall through */
case FSL_USB2_PHY_UTMI:
+ /* enable UTMI PHY */
+ setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
portsc |= PORT_PTS_UTMI;
break;
case FSL_USB2_PHY_NONE:
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 491806221165..bea5013ab7f5 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -45,5 +45,6 @@
#define FSL_SOC_USB_PRICTRL 0x40c /* NOTE: big-endian */
#define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */
#define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */
+#define CTRL_UTMI_PHY_EN (1<<9)
#define SNOOP_SIZE_2GB 0x1e
#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 9037035ad1e4..5a42cf0c9bb6 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -94,7 +94,6 @@ struct platform_device * __devinit fsl_usb2_device_register(
pdev->dev.parent = &ofdev->dev;
pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
- pdev->dev.dma_mask = &pdev->archdata.dma_mask;
*pdev->dev.dma_mask = *ofdev->dev.dma_mask;
retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 922148ff8d29..c860597eeb3a 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -576,6 +576,15 @@ void musb_g_tx(struct musb *musb, u8 epnum)
if (request->actual == request->length) {
musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by the gadget_queue function especially
+ * on SMP systems. Reselect the INDEX to be sure
+ * we are reading/modifying the right registers
+ */
+ musb_ep_select(mbase, epnum);
req = musb_ep->desc ? next_request(musb_ep) : NULL;
if (!req) {
dev_dbg(musb->controller, "%s idle now\n",
@@ -985,6 +994,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
}
#endif
musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by the gadget_queue function especially
+ * on SMP systems. Reselect the INDEX to be sure
+ * we are reading/modifying the right registers
+ */
+ musb_ep_select(mbase, epnum);
req = next_request(musb_ep);
if (!req)
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 7f4e80338570..aa0d183236c9 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -816,6 +816,11 @@ static int usbhsg_stop(struct usbhs_priv *priv)
return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
}
+static void usbhs_mod_gadget_release(struct device *pdev)
+{
+ /* do nothing */
+}
+
int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
{
struct usbhsg_gpriv *gpriv;
@@ -864,6 +869,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
*/
dev_set_name(&gpriv->gadget.dev, "gadget");
gpriv->gadget.dev.parent = dev;
+ gpriv->gadget.dev.release = usbhs_mod_gadget_release;
gpriv->gadget.name = "renesas_usbhs_udc";
gpriv->gadget.ops = &usbhsg_gadget_ops;
gpriv->gadget.is_dualspeed = 1;
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 33d25d4e6807..4c12404963e8 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -49,6 +49,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port,
unsigned int, unsigned int);
static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *);
+static void cp210x_release(struct usb_serial *);
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
static int debug;
@@ -121,6 +122,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
@@ -149,6 +152,10 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
+struct cp210x_port_private {
+ __u8 bInterfaceNumber;
+};
+
static struct usb_driver cp210x_driver = {
.name = "cp210x",
.probe = usb_serial_probe,
@@ -174,6 +181,7 @@ static struct usb_serial_driver cp210x_device = {
.tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset,
.attach = cp210x_startup,
+ .release = cp210x_release,
.dtr_rts = cp210x_dtr_rts
};
@@ -261,6 +269,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
__le32 *buf;
int result, i, length;
@@ -276,7 +285,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
/* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
- 0, buf, size, 300);
+ port_priv->bInterfaceNumber, buf, size, 300);
/* Convert data into an array of integers */
for (i = 0; i < length; i++)
@@ -304,6 +313,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
__le32 *buf;
int result, i, length;
@@ -325,12 +335,12 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, 0x0000,
- 0, buf, size, 300);
+ port_priv->bInterfaceNumber, buf, size, 300);
} else {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, data[0],
- 0, NULL, 0, 300);
+ port_priv->bInterfaceNumber, NULL, 0, 300);
}
kfree(buf);
@@ -830,11 +840,39 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
static int cp210x_startup(struct usb_serial *serial)
{
+ struct cp210x_port_private *port_priv;
+ int i;
+
/* cp210x buffers behave strangely unless device is reset */
usb_reset_device(serial->dev);
+
+ for (i = 0; i < serial->num_ports; i++) {
+ port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+ if (!port_priv)
+ return -ENOMEM;
+
+ memset(port_priv, 0x00, sizeof(*port_priv));
+ port_priv->bInterfaceNumber =
+ serial->interface->cur_altsetting->desc.bInterfaceNumber;
+
+ usb_set_serial_port_data(serial->port[i], port_priv);
+ }
+
return 0;
}
+static void cp210x_release(struct usb_serial *serial)
+{
+ struct cp210x_port_private *port_priv;
+ int i;
+
+ for (i = 0; i < serial->num_ports; i++) {
+ port_priv = usb_get_serial_port_data(serial->port[i]);
+ kfree(port_priv);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+}
+
static int __init cp210x_init(void)
{
int retval;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f030471363e1..f2c9ef780b18 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -188,6 +188,7 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_FTX_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -536,6 +537,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
@@ -797,7 +802,7 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
- { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
+ { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -846,6 +851,9 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
+ { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -868,7 +876,8 @@ static const char *ftdi_chip_name[] = {
[FT232RL] = "FT232RL",
[FT2232H] = "FT2232H",
[FT4232H] = "FT4232H",
- [FT232H] = "FT232H"
+ [FT232H] = "FT232H",
+ [FTX] = "FT-X"
};
@@ -1169,7 +1178,8 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
break;
case FT232BM: /* FT232BM chip */
case FT2232C: /* FT2232C chip */
- case FT232RL:
+ case FT232RL: /* FT232RL chip */
+ case FTX: /* FT-X series */
if (baud <= 3000000) {
__u16 product_id = le16_to_cpu(
port->serial->dev->descriptor.idProduct);
@@ -1458,10 +1468,14 @@ static void ftdi_determine_type(struct usb_serial_port *port)
} else if (version < 0x900) {
/* Assume it's an FT232RL */
priv->chip_type = FT232RL;
- } else {
+ } else if (version < 0x1000) {
/* Assume it's an FT232H */
priv->chip_type = FT232H;
+ } else {
+ /* Assume it's an FT-X series device */
+ priv->chip_type = FTX;
}
+
dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
}
@@ -1589,7 +1603,8 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
priv->chip_type == FT232RL ||
priv->chip_type == FT2232H ||
priv->chip_type == FT4232H ||
- priv->chip_type == FT232H)) {
+ priv->chip_type == FT232H ||
+ priv->chip_type == FTX)) {
retval = device_create_file(&port->dev,
&dev_attr_latency_timer);
}
@@ -1611,7 +1626,8 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
priv->chip_type == FT232RL ||
priv->chip_type == FT2232H ||
priv->chip_type == FT4232H ||
- priv->chip_type == FT232H) {
+ priv->chip_type == FT232H ||
+ priv->chip_type == FTX) {
device_remove_file(&port->dev, &dev_attr_latency_timer);
}
}
@@ -1763,7 +1779,8 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
dbg("%s", __func__);
- if (strcmp(udev->manufacturer, "CALAO Systems") == 0)
+ if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
+ (udev->product && !strcmp(udev->product, "BeagleBone/XDS100")))
return ftdi_jtag_probe(serial);
return 0;
@@ -2284,6 +2301,7 @@ static int ftdi_tiocmget(struct tty_struct *tty)
case FT2232H:
case FT4232H:
case FT232H:
+ case FTX:
len = 2;
break;
default:
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 19584faa86f9..ed58c6fa8dbe 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -157,7 +157,8 @@ enum ftdi_chip_type {
FT232RL = 5,
FT2232H = 6,
FT4232H = 7,
- FT232H = 8
+ FT232H = 8,
+ FTX = 9,
};
enum ftdi_sio_baudrate {
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 4eb77150f035..c6dd18e346b6 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -23,12 +23,15 @@
#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
#define FTDI_232H_PID 0x6014 /* Single channel hi-speed device */
+#define FTDI_FTX_PID 0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */
#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */
#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
/*** third-party PIDs (using FTDI_VID) ***/
+#define FTDI_LUMEL_PD12_PID 0x6002
+
/*
* Marvell OpenRD Base, Client
* http://www.open-rd.org
@@ -97,6 +100,8 @@
#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */
#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */
+#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID 0xCFF8
+
/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
/* the VID is the standard ftdi vid (FTDI_VID) */
#define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */
@@ -532,10 +537,14 @@
#define ADI_GNICEPLUS_PID 0xF001
/*
- * Hornby Elite
+ * Microchip Technology, Inc.
+ *
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by:
+ * Hornby Elite - Digital Command Control Console
+ * http://www.hornby.com/hornby-dcc/controllers/
*/
-#define HORNBY_VID 0x04D8
-#define HORNBY_ELITE_PID 0x000A
+#define MICROCHIP_VID 0x04D8
+#define MICROCHIP_USB_BOARD_PID 0x000A /* CDC RS-232 Emulation Demo */
/*
* RATOC REX-USB60F
@@ -680,6 +689,10 @@
#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */
#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */
#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */
+#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */
+#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */
+#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */
+#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */
/*
* JETI SPECTROMETER SPECBOS 1201
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index e4db5ad2bc55..9f0b2bff8ee4 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -215,8 +215,10 @@ retry:
clear_bit(i, &port->write_urbs_free);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - error submitting urb: %d\n",
+ if (!port->port.console) {
+ dev_err(&port->dev, "%s - error submitting urb: %d\n",
__func__, result);
+ }
set_bit(i, &port->write_urbs_free);
spin_lock_irqsave(&port->lock, flags);
port->tx_bytes -= count;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index c72abd524983..5c7d6540053f 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -174,6 +174,7 @@
#define CLK_MULTI_REGISTER ((__u16)(0x02))
#define CLK_START_VALUE_REGISTER ((__u16)(0x03))
+#define GPIO_REGISTER ((__u16)(0x07))
#define SERIAL_LCR_DLAB ((__u16)(0x0080))
@@ -1103,14 +1104,25 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
mos7840_port->read_urb = port->read_urb;
/* set up our bulk in urb */
-
- usb_fill_bulk_urb(mos7840_port->read_urb,
- serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
- port->bulk_in_buffer,
- mos7840_port->read_urb->transfer_buffer_length,
- mos7840_bulk_in_callback, mos7840_port);
+ if ((serial->num_ports == 2)
+ && ((((__u16)port->number -
+ (__u16)(port->serial->minor)) % 2) != 0)) {
+ usb_fill_bulk_urb(mos7840_port->read_urb,
+ serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ (port->bulk_in_endpointAddress) + 2),
+ port->bulk_in_buffer,
+ mos7840_port->read_urb->transfer_buffer_length,
+ mos7840_bulk_in_callback, mos7840_port);
+ } else {
+ usb_fill_bulk_urb(mos7840_port->read_urb,
+ serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->bulk_in_buffer,
+ mos7840_port->read_urb->transfer_buffer_length,
+ mos7840_bulk_in_callback, mos7840_port);
+ }
dbg("mos7840_open: bulkin endpoint is %d",
port->bulk_in_endpointAddress);
@@ -1521,13 +1533,25 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
memcpy(urb->transfer_buffer, current_position, transfer_size);
/* fill urb with data and submit */
- usb_fill_bulk_urb(urb,
- serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- urb->transfer_buffer,
- transfer_size,
- mos7840_bulk_out_data_callback, mos7840_port);
+ if ((serial->num_ports == 2)
+ && ((((__u16)port->number -
+ (__u16)(port->serial->minor)) % 2) != 0)) {
+ usb_fill_bulk_urb(urb,
+ serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ (port->bulk_out_endpointAddress) + 2),
+ urb->transfer_buffer,
+ transfer_size,
+ mos7840_bulk_out_data_callback, mos7840_port);
+ } else {
+ usb_fill_bulk_urb(urb,
+ serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
+ urb->transfer_buffer,
+ transfer_size,
+ mos7840_bulk_out_data_callback, mos7840_port);
+ }
data1 = urb->transfer_buffer;
dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
@@ -1840,7 +1864,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
} else {
#ifdef HW_flow_control
- / *setting h/w flow control bit to 0 */
+ /* setting h/w flow control bit to 0 */
Data = 0xb;
mos7840_port->shadowMCR = Data;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
@@ -2309,19 +2333,26 @@ static int mos7840_ioctl(struct tty_struct *tty,
static int mos7840_calc_num_ports(struct usb_serial *serial)
{
- int mos7840_num_ports = 0;
-
- dbg("numberofendpoints: cur %d, alt %d",
- (int)serial->interface->cur_altsetting->desc.bNumEndpoints,
- (int)serial->interface->altsetting->desc.bNumEndpoints);
- if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
- mos7840_num_ports = serial->num_ports = 2;
- } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
+ __u16 Data = 0x00;
+ int ret = 0;
+ int mos7840_num_ports;
+
+ ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data,
+ VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+
+ if ((Data & 0x01) == 0) {
+ mos7840_num_ports = 2;
+ serial->num_bulk_in = 2;
+ serial->num_bulk_out = 2;
+ serial->num_ports = 2;
+ } else {
+ mos7840_num_ports = 4;
serial->num_bulk_in = 4;
serial->num_bulk_out = 4;
- mos7840_num_ports = serial->num_ports = 4;
+ serial->num_ports = 4;
}
- dbg ("mos7840_num_ports = %d", mos7840_num_ports);
+
return mos7840_num_ports;
}
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 68fa8c7c162c..54898c995afb 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -307,6 +307,9 @@ static void option_instat_callback(struct urb *urb);
#define TELIT_VENDOR_ID 0x1bc7
#define TELIT_PRODUCT_UC864E 0x1003
#define TELIT_PRODUCT_UC864G 0x1004
+#define TELIT_PRODUCT_CC864_DUAL 0x1005
+#define TELIT_PRODUCT_CC864_SINGLE 0x1006
+#define TELIT_PRODUCT_DE910_DUAL 0x1010
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
@@ -484,6 +487,9 @@ static void option_instat_callback(struct urb *urb);
#define LG_VENDOR_ID 0x1004
#define LG_PRODUCT_L02C 0x618f
+/* MediaTek products */
+#define MEDIATEK_VENDOR_ID 0x0e8d
+
/* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason {
OPTION_BLACKLIST_NONE = 0,
@@ -768,6 +774,9 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
{ 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, 0x0002, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -892,6 +901,8 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
@@ -1198,6 +1209,10 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
{ USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1360,6 +1375,7 @@ static int option_probe(struct usb_serial *serial,
serial->interface->cur_altsetting->desc.bInterfaceNumber,
OPTION_BLACKLIST_RESERVED_IF,
(const struct option_blacklist_info *) id->driver_info))
+ return -ENODEV;
/* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID &&
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index aa9367f5b421..3187d8b97bfb 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -24,34 +24,44 @@
static int debug;
+#define DEVICE_G1K(v, p) \
+ USB_DEVICE(v, p), .driver_info = 1
+
static const struct usb_device_id id_table[] = {
- {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
- {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
- {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
- {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */
- {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
- {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
- {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
- {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
- {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
- {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
- {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
- {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
- {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
- {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
- {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+ /* Gobi 1000 devices */
+ {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
+ {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
+ {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
+ {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
+ {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
+ {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */
+ {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */
+ {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
+ {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
+ {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
+ {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
+ {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
+ {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+
+ /* Gobi 2000 devices */
+ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 QDL device */
{USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */
{USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */
{USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */
@@ -86,7 +96,18 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
{USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
{USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
+
+ /* Gobi 3000 devices */
+ {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */
+ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */
+ {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */
+ {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */
+ {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */
{USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+ {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */
+ {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -108,8 +129,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
int retval = -ENODEV;
__u8 nintf;
__u8 ifnum;
+ bool is_gobi1k = id->driver_info ? true : false;
dbg("%s", __func__);
+ dbg("Is Gobi 1000 = %d", is_gobi1k);
nintf = serial->dev->actconfig->desc.bNumInterfaces;
dbg("Num Interfaces = %d", nintf);
@@ -157,15 +180,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
case 3:
case 4:
- /* Composite mode */
- /* ifnum == 0 is a broadband network adapter */
- if (ifnum == 1) {
- /*
- * Diagnostics Monitor (serial line 9600 8N1)
- * Qualcomm DM protocol
- * use "libqcdm" (ModemManager) for communication
- */
- dbg("Diagnostics Monitor found");
+ /* Composite mode; don't bind to the QMI/net interface as that
+ * gets handled by other drivers.
+ */
+
+ /* Gobi 1K USB layout:
+ * 0: serial port (doesn't respond)
+ * 1: serial port (doesn't respond)
+ * 2: AT-capable modem port
+ * 3: QMI/net
+ *
+ * Gobi 2K+ USB layout:
+ * 0: QMI/net
+ * 1: DM/DIAG (use libqcdm from ModemManager for communication)
+ * 2: AT-capable modem port
+ * 3: NMEA
+ */
+
+ if (ifnum == 1 && !is_gobi1k) {
+ dbg("Gobi 2K+ DM/DIAG interface found");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
dev_err(&serial->dev->dev,
@@ -184,13 +217,13 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
retval = -ENODEV;
kfree(data);
}
- } else if (ifnum==3) {
+ } else if (ifnum==3 && !is_gobi1k) {
/*
* NMEA (serial line 9600 8N1)
* # echo "\$GPS_START" > /dev/ttyUSBx
* # echo "\$GPS_STOP" > /dev/ttyUSBx
*/
- dbg("NMEA GPS interface found");
+ dbg("Gobi 2K+ NMEA GPS interface found");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
dev_err(&serial->dev->dev,
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index 32c93d78d660..e39b1885f517 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -509,9 +509,14 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)
int retval;
u16 addr = 0xFE47;
u8 cmnd[12] = {0};
+ u8 *buf;
US_DEBUGP("%s, addr = 0x%x, len = %d\n", __FUNCTION__, addr, len);
+ buf = kmemdup(data, len, GFP_NOIO);
+ if (!buf)
+ return USB_STOR_TRANSPORT_ERROR;
+
cmnd[0] = 0xF0;
cmnd[1] = 0x0E;
cmnd[2] = (u8)(addr >> 8);
@@ -519,7 +524,8 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)
cmnd[4] = (u8)(len >> 8);
cmnd[5] = (u8)len;
- retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL);
+ retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL);
+ kfree(buf);
if (retval != USB_STOR_TRANSPORT_GOOD) {
return -EIO;
}