diff options
author | Anssi Hannula <anssi.hannula@gmail.com> | 2010-04-01 12:31:10 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:37 -0400 |
commit | e07896e62abbf7a741a5cd5b25ba7637bdf91ad0 (patch) | |
tree | e70a6c872a96283874faf8acbafeae97020d3095 /drivers/usb/serial/qcserial.c | |
parent | 3d7e59ad88fdb6bc50ae9b7e822d4bb5f68b68f9 (diff) |
USB: qcserial: Add support for Qualcomm Gobi 2000 devices
Add ids for Qualcomm Gobi 2000 QDL and Modem modes. Gobi 2000 has a
single altsetting in QDL mode, so adapt code to handle that.
Firmware upload protocol is also slightly different, with an
additional firmware file. However, qcserial doesn't handle firmware
uploading.
Tested on Lenovo Thinkpad T510.
Signed-off-by: Anssi Hannula <anssi.hannula@gmail.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/qcserial.c')
-rw-r--r-- | drivers/usb/serial/qcserial.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 9215f6c582c3..04bb759536bb 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c | |||
@@ -78,6 +78,8 @@ static const struct usb_device_id id_table[] = { | |||
78 | {USB_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ | 78 | {USB_DEVICE(0x1199, 0x900a)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ |
79 | {USB_DEVICE(0x16d8, 0x8001)}, /* CMDTech Gobi 2000 QDL device (VU922) */ | 79 | {USB_DEVICE(0x16d8, 0x8001)}, /* CMDTech Gobi 2000 QDL device (VU922) */ |
80 | {USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ | 80 | {USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ |
81 | {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */ | ||
82 | {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ | ||
81 | { } /* Terminating entry */ | 83 | { } /* Terminating entry */ |
82 | }; | 84 | }; |
83 | MODULE_DEVICE_TABLE(usb, id_table); | 85 | MODULE_DEVICE_TABLE(usb, id_table); |
@@ -95,6 +97,7 @@ static struct usb_driver qcdriver = { | |||
95 | static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | 97 | static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) |
96 | { | 98 | { |
97 | struct usb_wwan_intf_private *data; | 99 | struct usb_wwan_intf_private *data; |
100 | struct usb_host_interface *intf = serial->interface->cur_altsetting; | ||
98 | int retval = -ENODEV; | 101 | int retval = -ENODEV; |
99 | __u8 nintf; | 102 | __u8 nintf; |
100 | __u8 ifnum; | 103 | __u8 ifnum; |
@@ -103,7 +106,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
103 | 106 | ||
104 | nintf = serial->dev->actconfig->desc.bNumInterfaces; | 107 | nintf = serial->dev->actconfig->desc.bNumInterfaces; |
105 | dbg("Num Interfaces = %d", nintf); | 108 | dbg("Num Interfaces = %d", nintf); |
106 | ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; | 109 | ifnum = intf->desc.bInterfaceNumber; |
107 | dbg("This Interface = %d", ifnum); | 110 | dbg("This Interface = %d", ifnum); |
108 | 111 | ||
109 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), | 112 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), |
@@ -116,27 +119,32 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
116 | switch (nintf) { | 119 | switch (nintf) { |
117 | case 1: | 120 | case 1: |
118 | /* QDL mode */ | 121 | /* QDL mode */ |
119 | if (serial->interface->num_altsetting == 2) { | 122 | /* Gobi 2000 has a single altsetting, older ones have two */ |
120 | struct usb_host_interface *intf; | 123 | if (serial->interface->num_altsetting == 2) |
121 | |||
122 | intf = &serial->interface->altsetting[1]; | 124 | intf = &serial->interface->altsetting[1]; |
123 | if (intf->desc.bNumEndpoints == 2) { | 125 | else if (serial->interface->num_altsetting > 2) |
124 | if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && | 126 | break; |
125 | usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { | 127 | |
126 | dbg("QDL port found"); | 128 | if (intf->desc.bNumEndpoints == 2 && |
127 | retval = usb_set_interface(serial->dev, ifnum, 1); | 129 | usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && |
128 | if (retval < 0) { | 130 | usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { |
129 | dev_err(&serial->dev->dev, | 131 | dbg("QDL port found"); |
130 | "Could not set interface, error %d\n", | 132 | |
131 | retval); | 133 | if (serial->interface->num_altsetting == 1) |
132 | retval = -ENODEV; | 134 | return 0; |
133 | } | 135 | |
134 | return retval; | 136 | retval = usb_set_interface(serial->dev, ifnum, 1); |
135 | } | 137 | if (retval < 0) { |
138 | dev_err(&serial->dev->dev, | ||
139 | "Could not set interface, error %d\n", | ||
140 | retval); | ||
141 | retval = -ENODEV; | ||
136 | } | 142 | } |
143 | return retval; | ||
137 | } | 144 | } |
138 | break; | 145 | break; |
139 | 146 | ||
147 | case 3: | ||
140 | case 4: | 148 | case 4: |
141 | /* Composite mode */ | 149 | /* Composite mode */ |
142 | if (ifnum == 2) { | 150 | if (ifnum == 2) { |