diff options
-rw-r--r-- | drivers/usb/serial/qcserial.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 5022fcfa0260..0e46af0d0cb4 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #define DRIVER_AUTHOR "Qualcomm Inc" | 22 | #define DRIVER_AUTHOR "Qualcomm Inc" |
23 | #define DRIVER_DESC "Qualcomm USB Serial driver" | 23 | #define DRIVER_DESC "Qualcomm USB Serial driver" |
24 | 24 | ||
25 | #define QUECTEL_EC20_PID 0x9215 | ||
26 | |||
25 | /* standard device layouts supported by this driver */ | 27 | /* standard device layouts supported by this driver */ |
26 | enum qcserial_layouts { | 28 | enum qcserial_layouts { |
27 | QCSERIAL_G2K = 0, /* Gobi 2000 */ | 29 | QCSERIAL_G2K = 0, /* Gobi 2000 */ |
@@ -171,6 +173,38 @@ static const struct usb_device_id id_table[] = { | |||
171 | }; | 173 | }; |
172 | MODULE_DEVICE_TABLE(usb, id_table); | 174 | MODULE_DEVICE_TABLE(usb, id_table); |
173 | 175 | ||
176 | static int handle_quectel_ec20(struct device *dev, int ifnum) | ||
177 | { | ||
178 | int altsetting = 0; | ||
179 | |||
180 | /* | ||
181 | * Quectel EC20 Mini PCIe LTE module layout: | ||
182 | * 0: DM/DIAG (use libqcdm from ModemManager for communication) | ||
183 | * 1: NMEA | ||
184 | * 2: AT-capable modem port | ||
185 | * 3: Modem interface | ||
186 | * 4: NDIS | ||
187 | */ | ||
188 | switch (ifnum) { | ||
189 | case 0: | ||
190 | dev_dbg(dev, "Quectel EC20 DM/DIAG interface found\n"); | ||
191 | break; | ||
192 | case 1: | ||
193 | dev_dbg(dev, "Quectel EC20 NMEA GPS interface found\n"); | ||
194 | break; | ||
195 | case 2: | ||
196 | case 3: | ||
197 | dev_dbg(dev, "Quectel EC20 Modem port found\n"); | ||
198 | break; | ||
199 | case 4: | ||
200 | /* Don't claim the QMI/net interface */ | ||
201 | altsetting = -1; | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | return altsetting; | ||
206 | } | ||
207 | |||
174 | static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | 208 | static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) |
175 | { | 209 | { |
176 | struct usb_host_interface *intf = serial->interface->cur_altsetting; | 210 | struct usb_host_interface *intf = serial->interface->cur_altsetting; |
@@ -240,6 +274,12 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
240 | altsetting = -1; | 274 | altsetting = -1; |
241 | break; | 275 | break; |
242 | case QCSERIAL_G2K: | 276 | case QCSERIAL_G2K: |
277 | /* handle non-standard layouts */ | ||
278 | if (nintf == 5 && id->idProduct == QUECTEL_EC20_PID) { | ||
279 | altsetting = handle_quectel_ec20(dev, ifnum); | ||
280 | goto done; | ||
281 | } | ||
282 | |||
243 | /* | 283 | /* |
244 | * Gobi 2K+ USB layout: | 284 | * Gobi 2K+ USB layout: |
245 | * 0: QMI/net | 285 | * 0: QMI/net |