aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-02-19 20:54:15 +0100
committerArnd Bergmann <arnd@arndb.de>2013-02-19 20:54:25 +0100
commit6e7f7cfce26cabea2965a43b69b4a0c285a7e4c5 (patch)
treedb7c3d908e8b308c7c559ed4bd561c7ff86da753 /drivers/usb
parent001c5c4aaaffda840184700b8f488ced3c9dd0a1 (diff)
parent64ff1673332a1109780d731ca08dcd4f8ad33097 (diff)
Merge tag 'omap-for-v3.9/usb-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc
These changes contain the OMAP USB related platform data changes that were dropped from linux next because of the merge conflicts as requested by me and Olof. The reason was that at this point we really should be able to do the arch/arm related changes separately from driver changes to avoid dependencies between branches. These patches were initially part of the USB related MFD patches. Based on our comments, Roger Quadros quickly reworked these patches into a shared branch between ARM SoC tree and the MFD tree, then separate patches for the OMAP platform data and MFD driver. Note that this branch will conflict with c1d1cd597fc7 ("ARM: OMAP2+: omap_device: remove obsolete pm_lats and early_device code"). Please see http://lkml.org/lkml/2013/2/11/16 for the merge resolution. [arnd - resolved the merge conflict] Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/hcd.c44
-rw-r--r--drivers/usb/core/hub.c70
-rw-r--r--drivers/usb/host/ehci-hcd.c1
-rw-r--r--drivers/usb/host/ehci-hub.c9
-rw-r--r--drivers/usb/host/ehci-q.c50
-rw-r--r--drivers/usb/host/ehci-sched.c9
-rw-r--r--drivers/usb/host/ehci-timer.c29
-rw-r--r--drivers/usb/host/pci-quirks.c1
-rw-r--r--drivers/usb/host/uhci-hub.c3
-rw-r--r--drivers/usb/host/xhci-ring.c13
-rw-r--r--drivers/usb/serial/cp210x.c1
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h9
-rw-r--r--drivers/usb/serial/option.c13
-rw-r--r--drivers/usb/serial/qcserial.c1
-rw-r--r--drivers/usb/storage/initializers.c76
-rw-r--r--drivers/usb/storage/initializers.h4
-rw-r--r--drivers/usb/storage/unusual_devs.h329
-rw-r--r--drivers/usb/storage/usb.c12
-rw-r--r--drivers/usb/storage/usual-tables.c15
20 files changed, 299 insertions, 392 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 4225d5e7213..8e64adf8e4d 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -39,6 +39,7 @@
#include <asm/unaligned.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -1025,6 +1026,49 @@ static int register_root_hub(struct usb_hcd *hcd)
return retval;
}
+/*
+ * usb_hcd_start_port_resume - a root-hub port is sending a resume signal
+ * @bus: the bus which the root hub belongs to
+ * @portnum: the port which is being resumed
+ *
+ * HCDs should call this function when they know that a resume signal is
+ * being sent to a root-hub port. The root hub will be prevented from
+ * going into autosuspend until usb_hcd_end_port_resume() is called.
+ *
+ * The bus's private lock must be held by the caller.
+ */
+void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum)
+{
+ unsigned bit = 1 << portnum;
+
+ if (!(bus->resuming_ports & bit)) {
+ bus->resuming_ports |= bit;
+ pm_runtime_get_noresume(&bus->root_hub->dev);
+ }
+}
+EXPORT_SYMBOL_GPL(usb_hcd_start_port_resume);
+
+/*
+ * usb_hcd_end_port_resume - a root-hub port has stopped sending a resume signal
+ * @bus: the bus which the root hub belongs to
+ * @portnum: the port which is being resumed
+ *
+ * HCDs should call this function when they know that a resume signal has
+ * stopped being sent to a root-hub port. The root hub will be allowed to
+ * autosuspend again.
+ *
+ * The bus's private lock must be held by the caller.
+ */
+void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum)
+{
+ unsigned bit = 1 << portnum;
+
+ if (bus->resuming_ports & bit) {
+ bus->resuming_ports &= ~bit;
+ pm_runtime_put_noidle(&bus->root_hub->dev);
+ }
+}
+EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume);
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 957ed2c4148..cbf7168e3ce 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2838,6 +2838,23 @@ void usb_enable_ltm(struct usb_device *udev)
EXPORT_SYMBOL_GPL(usb_enable_ltm);
#ifdef CONFIG_USB_SUSPEND
+/*
+ * usb_disable_function_remotewakeup - disable usb3.0
+ * device's function remote wakeup
+ * @udev: target device
+ *
+ * Assume there's only one function on the USB 3.0
+ * device and disable remote wake for the first
+ * interface. FIXME if the interface association
+ * descriptor shows there's more than one function.
+ */
+static int usb_disable_function_remotewakeup(struct usb_device *udev)
+{
+ return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE,
+ USB_INTRF_FUNC_SUSPEND, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+}
/*
* usb_port_suspend - suspend a usb device's upstream port
@@ -2955,12 +2972,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
port1, status);
/* paranoia: "should not happen" */
- if (udev->do_remote_wakeup)
- (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
- USB_DEVICE_REMOTE_WAKEUP, 0,
- NULL, 0,
- USB_CTRL_SET_TIMEOUT);
+ if (udev->do_remote_wakeup) {
+ if (!hub_is_superspeed(hub->hdev)) {
+ (void) usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ USB_REQ_CLEAR_FEATURE,
+ USB_RECIP_DEVICE,
+ USB_DEVICE_REMOTE_WAKEUP, 0,
+ NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ } else
+ (void) usb_disable_function_remotewakeup(udev);
+
+ }
/* Try to enable USB2 hardware LPM again */
if (udev->usb2_hw_lpm_capable == 1)
@@ -3052,20 +3076,30 @@ static int finish_port_resume(struct usb_device *udev)
* udev->reset_resume
*/
} else if (udev->actconfig && !udev->reset_resume) {
- le16_to_cpus(&devstatus);
- if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
- status = usb_control_msg(udev,
- usb_sndctrlpipe(udev, 0),
- USB_REQ_CLEAR_FEATURE,
+ if (!hub_is_superspeed(udev->parent)) {
+ le16_to_cpus(&devstatus);
+ if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
+ status = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ USB_REQ_CLEAR_FEATURE,
USB_RECIP_DEVICE,
- USB_DEVICE_REMOTE_WAKEUP, 0,
- NULL, 0,
- USB_CTRL_SET_TIMEOUT);
- if (status)
- dev_dbg(&udev->dev,
- "disable remote wakeup, status %d\n",
- status);
+ USB_DEVICE_REMOTE_WAKEUP, 0,
+ NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ } else {
+ status = usb_get_status(udev, USB_RECIP_INTERFACE, 0,
+ &devstatus);
+ le16_to_cpus(&devstatus);
+ if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP
+ | USB_INTRF_STAT_FUNC_RW))
+ status =
+ usb_disable_function_remotewakeup(udev);
}
+
+ if (status)
+ dev_dbg(&udev->dev,
+ "disable remote wakeup, status %d\n",
+ status);
status = 0;
}
return status;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 09537b2f100..b416a3fc995 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -797,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
set_bit(i, &ehci->resuming_ports);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
+ usb_hcd_start_port_resume(&hcd->self, i);
mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
}
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 4ccb97c0678..4d3b294f203 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
status = STS_PCD;
}
}
- /* FIXME autosuspend idle root hubs */
+
+ /* If a resume is in progress, make sure it can finish */
+ if (ehci->resuming_ports)
+ mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25));
+
spin_unlock_irqrestore (&ehci->lock, flags);
return status ? retval : 0;
}
@@ -851,6 +855,7 @@ static int ehci_hub_control (
/* resume signaling for 20 msec */
ehci->reset_done[wIndex] = jiffies
+ msecs_to_jiffies(20);
+ usb_hcd_start_port_resume(&hcd->self, wIndex);
/* check the port again */
mod_timer(&ehci_to_hcd(ehci)->rh_timer,
ehci->reset_done[wIndex]);
@@ -862,6 +867,7 @@ static int ehci_hub_control (
clear_bit(wIndex, &ehci->suspended_ports);
set_bit(wIndex, &ehci->port_c_suspend);
ehci->reset_done[wIndex] = 0;
+ usb_hcd_end_port_resume(&hcd->self, wIndex);
/* stop resume signaling */
temp = ehci_readl(ehci, status_reg);
@@ -950,6 +956,7 @@ static int ehci_hub_control (
ehci->reset_done[wIndex] = 0;
if (temp & PORT_PE)
set_bit(wIndex, &ehci->port_c_suspend);
+ usb_hcd_end_port_resume(&hcd->self, wIndex);
}
if (temp & PORT_OC)
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 3d989028c83..fd252f0cfb3 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
if (ehci->async_iaa || ehci->async_unlinking)
return;
- /* Do all the waiting QHs at once */
- ehci->async_iaa = ehci->async_unlink;
- ehci->async_unlink = NULL;
-
/* If the controller isn't running, we don't have to wait for it */
if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
+
+ /* Do all the waiting QHs */
+ ehci->async_iaa = ehci->async_unlink;
+ ehci->async_unlink = NULL;
+
if (!nested) /* Avoid recursion */
end_unlink_async(ehci);
/* Otherwise start a new IAA cycle */
} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
+ struct ehci_qh *qh;
+
+ /* Do only the first waiting QH (nVidia bug?) */
+ qh = ehci->async_unlink;
+ ehci->async_iaa = qh;
+ ehci->async_unlink = qh->unlink_next;
+ qh->unlink_next = NULL;
+
/* Make sure the unlinks are all visible to the hardware */
wmb();
@@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci)
}
}
+static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
+
static void unlink_empty_async(struct ehci_hcd *ehci)
{
- struct ehci_qh *qh, *next;
- bool stopped = (ehci->rh_state < EHCI_RH_RUNNING);
+ struct ehci_qh *qh;
+ struct ehci_qh *qh_to_unlink = NULL;
bool check_unlinks_later = false;
+ int count = 0;
- /* Unlink all the async QHs that have been empty for a timer cycle */
- next = ehci->async->qh_next.qh;
- while (next) {
- qh = next;
- next = qh->qh_next.qh;
-
+ /* Find the last async QH which has been empty for a timer cycle */
+ for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) {
if (list_empty(&qh->qtd_list) &&
qh->qh_state == QH_STATE_LINKED) {
- if (!stopped && qh->unlink_cycle ==
- ehci->async_unlink_cycle)
+ ++count;
+ if (qh->unlink_cycle == ehci->async_unlink_cycle)
check_unlinks_later = true;
else
- single_unlink_async(ehci, qh);
+ qh_to_unlink = qh;
}
}
- /* Start a new IAA cycle if any QHs are waiting for it */
- if (ehci->async_unlink)
- start_iaa_cycle(ehci, false);
+ /* If nothing else is being unlinked, unlink the last empty QH */
+ if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
+ start_unlink_async(ehci, qh_to_unlink);
+ --count;
+ }
- /* QHs that haven't been empty for long enough will be handled later */
- if (check_unlinks_later) {
+ /* Other QHs will be handled later */
+ if (count > 0) {
ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true);
++ehci->async_unlink_cycle;
}
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 69ebee73c0c..b476daf49f6 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask)
}
static const unsigned char
-max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 };
+max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 };
/* carryover low/fullspeed bandwidth that crosses uframe boundries */
static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
@@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci)
}
ehci->now_frame = now_frame;
+ frame = ehci->last_iso_frame;
for (;;) {
union ehci_shadow q, *q_p;
__hc32 type, *hw_p;
- frame = ehci->last_iso_frame;
restart:
/* scan each element in frame's queue for completions */
q_p = &ehci->pshadow [frame];
@@ -2321,6 +2321,9 @@ restart:
/* Stop when we have reached the current frame */
if (frame == now_frame)
break;
- ehci->last_iso_frame = (frame + 1) & fmask;
+
+ /* The last frame may still have active siTDs */
+ ehci->last_iso_frame = frame;
+ frame = (frame + 1) & fmask;
}
}
diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c
index 20dbdcbe9b0..f904071d70d 100644
--- a/drivers/usb/host/ehci-timer.c
+++ b/drivers/usb/host/ehci-timer.c
@@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
if (want != actual) {
- /* Poll again later, but give up after about 20 ms */
- if (ehci->ASS_poll_count++ < 20) {
- ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
- return;
- }
- ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n",
- want, actual);
+ /* Poll again later */
+ ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
+ ++ehci->ASS_poll_count;
+ return;
}
+
+ if (ehci->ASS_poll_count > 20)
+ ehci_dbg(ehci, "ASS poll count reached %d\n",
+ ehci->ASS_poll_count);
ehci->ASS_poll_count = 0;
/* The status is up-to-date; restart or stop the schedule as needed */
@@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
if (want != actual) {
- /* Poll again later, but give up after about 20 ms */
- if (ehci->PSS_poll_count++ < 20) {
- ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
- return;
- }
- ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
- want, actual);
+ /* Poll again later */
+ ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
+ return;
}
+
+ if (ehci->PSS_poll_count > 20)
+ ehci_dbg(ehci, "PSS poll count reached %d\n",
+ ehci->PSS_poll_count);
ehci->PSS_poll_count = 0;
/* The status is up-to-date; restart or stop the schedule as needed */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index a3b6d7104ae..4c338ec03a0 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
"defaulting to EHCI.\n");
dev_warn(&xhci_pdev->dev,
"USB 3.0 devices will work at USB 2.0 speeds.\n");
+ usb_disable_xhci_ports(xhci_pdev);
return;
}
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 768d54295a2..15d13229ddb 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
}
}
clear_bit(port, &uhci->resuming_ports);
+ usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port);
}
/* Wait for the UHCI controller in HP's iLO2 server management chip.
@@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci)
set_bit(port, &uhci->resuming_ports);
uhci->ports_timeout = jiffies +
msecs_to_jiffies(25);
+ usb_hcd_start_port_resume(
+ &uhci_to_hcd(uhci)->self, port);
/* Make sure we see the port again
* after the resuming period is over. */
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 59fb5c677db..7f76a49e90d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
faked_port_index + 1);
if (slot_id && xhci->devs[slot_id])
xhci_ring_device(xhci, slot_id);
- if (bus_state->port_remote_wakeup && (1 << faked_port_index)) {
+ if (bus_state->port_remote_wakeup & (1 << faked_port_index)) {
bus_state->port_remote_wakeup &=
~(1 << faked_port_index);
xhci_test_and_clear_bit(xhci, port_array,
@@ -2589,6 +2589,8 @@ cleanup:
(trb_comp_code != COMP_STALL &&
trb_comp_code != COMP_BABBLE))
xhci_urb_free_priv(xhci, urb_priv);
+ else
+ kfree(urb_priv);
usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
if ((urb->actual_length != urb->transfer_buffer_length &&
@@ -3108,7 +3110,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
* running_total.
*/
packets_transferred = (running_total + trb_buff_len) /
- usb_endpoint_maxp(&urb->ep->desc);
+ GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
if ((total_packet_count - packets_transferred) > 31)
return 31 << 17;
@@ -3642,7 +3644,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
td_len = urb->iso_frame_desc[i].length;
td_remain_len = td_len;
total_packet_count = DIV_ROUND_UP(td_len,
- usb_endpoint_maxp(&urb->ep->desc));
+ GET_MAX_PACKET(
+ usb_endpoint_maxp(&urb->ep->desc)));
/* A zero-length transfer still involves at least one packet. */
if (total_packet_count == 0)
total_packet_count++;
@@ -3664,9 +3667,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
td = urb_priv->td[i];
for (j = 0; j < trbs_per_td; j++) {
u32 remainder = 0;
- field = TRB_TBC(burst_count) | TRB_TLBPC(residue);
+ field = 0;
if (first_trb) {
+ field = TRB_TBC(burst_count) |
+ TRB_TLBPC(residue);
/* Queue the isoc TRB */
field |= TRB_TYPE(TRB_ISOC);
/* Assume URB_ISO_ASAP is set */
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index f14736f647f..edc0f0dcad8 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
+ { USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */
{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index ba68835d06a..90ceef1776c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -584,6 +584,7 @@ static struct usb_device_id id_table_combined [] = {
/*
* ELV devices:
*/
+ { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) },
@@ -670,6 +671,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) },
{ USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) },
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index fa5d5603827..9d359e189a6 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -147,6 +147,11 @@
#define XSENS_CONVERTER_6_PID 0xD38E
#define XSENS_CONVERTER_7_PID 0xD38F
+/**
+ * Zolix (www.zolix.com.cb) product ids
+ */
+#define FTDI_OMNI1509 0xD491 /* Omni1509 embedded USB-serial */
+
/*
* NDI (www.ndigital.com) product ids
*/
@@ -204,7 +209,7 @@
/*
* ELV USB devices submitted by Christian Abt of ELV (www.elv.de).
- * All of these devices use FTDI's vendor ID (0x0403).
+ * Almost all of these devices use FTDI's vendor ID (0x0403).
* Further IDs taken from ELV Windows .inf file.
*
* The previously included PID for the UO 100 module was incorrect.
@@ -212,6 +217,8 @@
*
* Armin Laeuger originally sent the PID for the UM 100 module.
*/
+#define FTDI_ELV_VID 0x1B1F /* ELV AG */
+#define FTDI_ELV_WS300_PID 0xC006 /* eQ3 WS 300 PC II */
#define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */
#define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */
#define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 0d9dac9e7f9..567bc77d639 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb);
#define TELIT_PRODUCT_CC864_DUAL 0x1005
#define TELIT_PRODUCT_CC864_SINGLE 0x1006
#define TELIT_PRODUCT_DE910_DUAL 0x1010
+#define TELIT_PRODUCT_LE920 0x1200
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
@@ -453,6 +454,10 @@ static void option_instat_callback(struct urb *urb);
#define TPLINK_VENDOR_ID 0x2357
#define TPLINK_PRODUCT_MA180 0x0201
+/* Changhong products */
+#define CHANGHONG_VENDOR_ID 0x2077
+#define CHANGHONG_PRODUCT_CH690 0x7001
+
/* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason {
OPTION_BLACKLIST_NONE = 0,
@@ -534,6 +539,11 @@ static const struct option_blacklist_info zte_1255_blacklist = {
.reserved = BIT(3) | BIT(4),
};
+static const struct option_blacklist_info telit_le920_blacklist = {
+ .sendsetup = BIT(0),
+ .reserved = BIT(1) | BIT(5),
+};
+
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -784,6 +794,8 @@ static const struct usb_device_id option_ids[] = {
{ 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(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
+ .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, 0x0002, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -1318,6 +1330,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },
{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index aa148c21ea4..24662547dc5 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = {
{DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
{DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
{DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+ {DEVICE_G1K(0x1bc7, 0x900e)}, /* Telit Gobi QDL device */
/* Gobi 2000 devices */
{USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c
index 105d900150c..16b0bf055ee 100644
--- a/drivers/usb/storage/initializers.c
+++ b/drivers/usb/storage/initializers.c
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
return 0;
}
-/* This places the HUAWEI E220 devices in multi-port mode */
-int usb_stor_huawei_e220_init(struct us_data *us)
+/* This places the HUAWEI usb dongles in multi-port mode */
+static int usb_stor_huawei_feature_init(struct us_data *us)
{
int result;
@@ -104,3 +104,75 @@ int usb_stor_huawei_e220_init(struct us_data *us)
US_DEBUGP("Huawei mode set result is %d\n", result);
return 0;
}
+
+/*
+ * It will send a scsi switch command called rewind' to huawei dongle.
+ * When the dongle receives this command at the first time,
+ * it will reboot immediately. After rebooted, it will ignore this command.
+ * So it is unnecessary to read its response.
+ */
+static int usb_stor_huawei_scsi_init(struct us_data *us)
+{
+ int result = 0;
+ int act_len = 0;
+ struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
+ char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+ bcbw->Tag = 0;
+ bcbw->DataTransferLength = 0;
+ bcbw->Flags = bcbw->Lun = 0;
+ bcbw->Length = sizeof(rewind_cmd);
+ memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
+ memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
+
+ result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
+ US_BULK_CB_WRAP_LEN, &act_len);
+ US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
+ return result;
+}
+
+/*
+ * It tries to find the supported Huawei USB dongles.
+ * In Huawei, they assign the following product IDs
+ * for all of their mobile broadband dongles,
+ * including the new dongles in the future.
+ * So if the product ID is not included in this list,
+ * it means it is not Huawei's mobile broadband dongles.
+ */
+static int usb_stor_huawei_dongles_pid(struct us_data *us)
+{
+ struct usb_interface_descriptor *idesc;
+ int idProduct;
+
+ idesc = &us->pusb_intf->cur_altsetting->desc;
+ idProduct = us->pusb_dev->descriptor.idProduct;
+ /* The first port is CDROM,
+ * means the dongle in the single port mode,
+ * and a switch command is required to be sent. */
+ if (idesc && idesc->bInterfaceNumber == 0) {
+ if ((idProduct == 0x1001)
+ || (idProduct == 0x1003)
+ || (idProduct == 0x1004)
+ || (idProduct >= 0x1401 && idProduct <= 0x1500)
+ || (idProduct >= 0x1505 && idProduct <= 0x1600)
+ || (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int usb_stor_huawei_init(struct us_data *us)
+{
+ int result = 0;
+
+ if (usb_stor_huawei_dongles_pid(us)) {
+ if (us->pusb_dev->descriptor.idProduct >= 0x1446)
+ result = usb_stor_huawei_scsi_init(us);
+ else
+ result = usb_stor_huawei_feature_init(us);
+ }
+ return result;
+}
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h
index 529327fbb06..5376d4fc76f 100644
--- a/drivers/usb/storage/initializers.h
+++ b/drivers/usb/storage/initializers.h
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);
* flash reader */
int usb_stor_ucr61s2b_init(struct us_data *us);
-/* This places the HUAWEI E220 devices in multi-port mode */
-int usb_stor_huawei_e220_init(struct us_data *us);
+/* This places the HUAWEI usb dongles in multi-port mode */
+int usb_stor_huawei_init(struct us_data *us);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index d305a5aa3a5..72923b56bbf 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1527,335 +1527,10 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
/* Reported by fangxiaozhi <huananhu@huawei.com>
* This brings the HUAWEI data card devices into multi-port mode
*/
-UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000,
+UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50,
"HUAWEI MOBILE",
"Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1402, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1404, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1407, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x140A, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x140B, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x140C, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x140D, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x140E, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x140F, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x141A, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x141B, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x141C, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x141D, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x141E, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x141F, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1420, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1421, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1422, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1423, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1424, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1425, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1426, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1427, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1428, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1429, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x142A, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x142B, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x142C, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x142D, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x142E, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x142F, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1430, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1431, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1432, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1433, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1434, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1435, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1436, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1437, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1438, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x1439, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x143A, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x143B, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x143C, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x143D, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x143E, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
- 0),
-UNUSUAL_DEV( 0x12d1, 0x143F, 0x0000, 0x0000,
- "HUAWEI MOBILE",
- "Mass Storage",
- USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+ USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init,
0),
/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 31b3e1a61bb..cf09b6ba71f 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -120,6 +120,17 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
.useTransport = use_transport, \
}
+#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \
+ vendor_name, product_name, use_protocol, use_transport, \
+ init_function, Flags) \
+{ \
+ .vendorName = vendor_name, \
+ .productName = product_name, \
+ .useProtocol = use_protocol, \
+ .useTransport = use_transport, \
+ .initFunction = init_function, \
+}
+
static struct us_unusual_dev us_unusual_dev_list[] = {
# include "unusual_devs.h"
{ } /* Terminating entry */
@@ -131,6 +142,7 @@ static struct us_unusual_dev for_dynamic_ids =
#undef UNUSUAL_DEV
#undef COMPLIANT_DEV
#undef USUAL_DEV
+#undef UNUSUAL_VENDOR_INTF
#ifdef CONFIG_LOCKDEP
diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
index b78a526910f..5ef8ce74aae 100644
--- a/drivers/usb/storage/usual-tables.c
+++ b/drivers/usb/storage/usual-tables.c
@@ -41,6 +41,20 @@
#define USUAL_DEV(useProto, useTrans) \
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) }
+/* Define the device is matched with Vendor ID and interface descriptors */
+#define UNUSUAL_VENDOR_INTF(id_vendor, cl, sc, pr, \
+ vendorName, productName, useProtocol, useTransport, \
+ initFunction, flags) \
+{ \
+ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \
+ | USB_DEVICE_ID_MATCH_VENDOR, \
+ .idVendor = (id_vendor), \
+ .bInterfaceClass = (cl), \
+ .bInterfaceSubClass = (sc), \
+ .bInterfaceProtocol = (pr), \
+ .driver_info = (flags) \
+}
+
struct usb_device_id usb_storage_usb_ids[] = {
# include "unusual_devs.h"
{ } /* Terminating entry */
@@ -50,6 +64,7 @@ MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids);
#undef UNUSUAL_DEV
#undef COMPLIANT_DEV
#undef USUAL_DEV
+#undef UNUSUAL_VENDOR_INTF
/*
* The table of devices to ignore