diff options
Diffstat (limited to 'drivers/usb/serial/option.c')
-rw-r--r-- | drivers/usb/serial/option.c | 104 |
1 files changed, 55 insertions, 49 deletions
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 1aae9028cd0b..adf8ce72be50 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -47,6 +47,7 @@ | |||
47 | /* Function prototypes */ | 47 | /* Function prototypes */ |
48 | static int option_probe(struct usb_serial *serial, | 48 | static int option_probe(struct usb_serial *serial, |
49 | const struct usb_device_id *id); | 49 | const struct usb_device_id *id); |
50 | static void option_release(struct usb_serial *serial); | ||
50 | static int option_send_setup(struct usb_serial_port *port); | 51 | static int option_send_setup(struct usb_serial_port *port); |
51 | static void option_instat_callback(struct urb *urb); | 52 | static void option_instat_callback(struct urb *urb); |
52 | 53 | ||
@@ -150,6 +151,7 @@ static void option_instat_callback(struct urb *urb); | |||
150 | #define HUAWEI_PRODUCT_E14AC 0x14AC | 151 | #define HUAWEI_PRODUCT_E14AC 0x14AC |
151 | #define HUAWEI_PRODUCT_K3806 0x14AE | 152 | #define HUAWEI_PRODUCT_K3806 0x14AE |
152 | #define HUAWEI_PRODUCT_K4605 0x14C6 | 153 | #define HUAWEI_PRODUCT_K4605 0x14C6 |
154 | #define HUAWEI_PRODUCT_K5005 0x14C8 | ||
153 | #define HUAWEI_PRODUCT_K3770 0x14C9 | 155 | #define HUAWEI_PRODUCT_K3770 0x14C9 |
154 | #define HUAWEI_PRODUCT_K3771 0x14CA | 156 | #define HUAWEI_PRODUCT_K3771 0x14CA |
155 | #define HUAWEI_PRODUCT_K4510 0x14CB | 157 | #define HUAWEI_PRODUCT_K4510 0x14CB |
@@ -234,6 +236,7 @@ static void option_instat_callback(struct urb *urb); | |||
234 | #define NOVATELWIRELESS_PRODUCT_G1 0xA001 | 236 | #define NOVATELWIRELESS_PRODUCT_G1 0xA001 |
235 | #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 | 237 | #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 |
236 | #define NOVATELWIRELESS_PRODUCT_G2 0xA010 | 238 | #define NOVATELWIRELESS_PRODUCT_G2 0xA010 |
239 | #define NOVATELWIRELESS_PRODUCT_MC551 0xB001 | ||
237 | 240 | ||
238 | /* AMOI PRODUCTS */ | 241 | /* AMOI PRODUCTS */ |
239 | #define AMOI_VENDOR_ID 0x1614 | 242 | #define AMOI_VENDOR_ID 0x1614 |
@@ -425,7 +428,7 @@ static void option_instat_callback(struct urb *urb); | |||
425 | #define SAMSUNG_VENDOR_ID 0x04e8 | 428 | #define SAMSUNG_VENDOR_ID 0x04e8 |
426 | #define SAMSUNG_PRODUCT_GT_B3730 0x6889 | 429 | #define SAMSUNG_PRODUCT_GT_B3730 0x6889 |
427 | 430 | ||
428 | /* YUGA products www.yuga-info.com*/ | 431 | /* YUGA products www.yuga-info.com gavin.kx@qq.com */ |
429 | #define YUGA_VENDOR_ID 0x257A | 432 | #define YUGA_VENDOR_ID 0x257A |
430 | #define YUGA_PRODUCT_CEM600 0x1601 | 433 | #define YUGA_PRODUCT_CEM600 0x1601 |
431 | #define YUGA_PRODUCT_CEM610 0x1602 | 434 | #define YUGA_PRODUCT_CEM610 0x1602 |
@@ -442,6 +445,8 @@ static void option_instat_callback(struct urb *urb); | |||
442 | #define YUGA_PRODUCT_CEU516 0x160C | 445 | #define YUGA_PRODUCT_CEU516 0x160C |
443 | #define YUGA_PRODUCT_CEU528 0x160D | 446 | #define YUGA_PRODUCT_CEU528 0x160D |
444 | #define YUGA_PRODUCT_CEU526 0x160F | 447 | #define YUGA_PRODUCT_CEU526 0x160F |
448 | #define YUGA_PRODUCT_CEU881 0x161F | ||
449 | #define YUGA_PRODUCT_CEU882 0x162F | ||
445 | 450 | ||
446 | #define YUGA_PRODUCT_CWM600 0x2601 | 451 | #define YUGA_PRODUCT_CWM600 0x2601 |
447 | #define YUGA_PRODUCT_CWM610 0x2602 | 452 | #define YUGA_PRODUCT_CWM610 0x2602 |
@@ -457,23 +462,26 @@ static void option_instat_callback(struct urb *urb); | |||
457 | #define YUGA_PRODUCT_CWU518 0x260B | 462 | #define YUGA_PRODUCT_CWU518 0x260B |
458 | #define YUGA_PRODUCT_CWU516 0x260C | 463 | #define YUGA_PRODUCT_CWU516 0x260C |
459 | #define YUGA_PRODUCT_CWU528 0x260D | 464 | #define YUGA_PRODUCT_CWU528 0x260D |
465 | #define YUGA_PRODUCT_CWU581 0x260E | ||
460 | #define YUGA_PRODUCT_CWU526 0x260F | 466 | #define YUGA_PRODUCT_CWU526 0x260F |
461 | 467 | #define YUGA_PRODUCT_CWU582 0x261F | |
462 | #define YUGA_PRODUCT_CLM600 0x2601 | 468 | #define YUGA_PRODUCT_CWU583 0x262F |
463 | #define YUGA_PRODUCT_CLM610 0x2602 | 469 | |
464 | #define YUGA_PRODUCT_CLM500 0x2603 | 470 | #define YUGA_PRODUCT_CLM600 0x3601 |
465 | #define YUGA_PRODUCT_CLM510 0x2604 | 471 | #define YUGA_PRODUCT_CLM610 0x3602 |
466 | #define YUGA_PRODUCT_CLM800 0x2605 | 472 | #define YUGA_PRODUCT_CLM500 0x3603 |
467 | #define YUGA_PRODUCT_CLM900 0x2606 | 473 | #define YUGA_PRODUCT_CLM510 0x3604 |
468 | 474 | #define YUGA_PRODUCT_CLM800 0x3605 | |
469 | #define YUGA_PRODUCT_CLU718 0x2607 | 475 | #define YUGA_PRODUCT_CLM900 0x3606 |
470 | #define YUGA_PRODUCT_CLU716 0x2608 | 476 | |
471 | #define YUGA_PRODUCT_CLU728 0x2609 | 477 | #define YUGA_PRODUCT_CLU718 0x3607 |
472 | #define YUGA_PRODUCT_CLU726 0x260A | 478 | #define YUGA_PRODUCT_CLU716 0x3608 |
473 | #define YUGA_PRODUCT_CLU518 0x260B | 479 | #define YUGA_PRODUCT_CLU728 0x3609 |
474 | #define YUGA_PRODUCT_CLU516 0x260C | 480 | #define YUGA_PRODUCT_CLU726 0x360A |
475 | #define YUGA_PRODUCT_CLU528 0x260D | 481 | #define YUGA_PRODUCT_CLU518 0x360B |
476 | #define YUGA_PRODUCT_CLU526 0x260F | 482 | #define YUGA_PRODUCT_CLU516 0x360C |
483 | #define YUGA_PRODUCT_CLU528 0x360D | ||
484 | #define YUGA_PRODUCT_CLU526 0x360F | ||
477 | 485 | ||
478 | /* Viettel products */ | 486 | /* Viettel products */ |
479 | #define VIETTEL_VENDOR_ID 0x2262 | 487 | #define VIETTEL_VENDOR_ID 0x2262 |
@@ -490,6 +498,10 @@ static void option_instat_callback(struct urb *urb); | |||
490 | /* MediaTek products */ | 498 | /* MediaTek products */ |
491 | #define MEDIATEK_VENDOR_ID 0x0e8d | 499 | #define MEDIATEK_VENDOR_ID 0x0e8d |
492 | 500 | ||
501 | /* Cellient products */ | ||
502 | #define CELLIENT_VENDOR_ID 0x2692 | ||
503 | #define CELLIENT_PRODUCT_MEN200 0x9005 | ||
504 | |||
493 | /* some devices interfaces need special handling due to a number of reasons */ | 505 | /* some devices interfaces need special handling due to a number of reasons */ |
494 | enum option_blacklist_reason { | 506 | enum option_blacklist_reason { |
495 | OPTION_BLACKLIST_NONE = 0, | 507 | OPTION_BLACKLIST_NONE = 0, |
@@ -666,6 +678,11 @@ static const struct usb_device_id option_ids[] = { | |||
666 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, | 678 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, |
667 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), | 679 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), |
668 | .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, | 680 | .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, |
681 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, | ||
682 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, | ||
683 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, | ||
684 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, | ||
685 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, | ||
669 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, | 686 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, |
670 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, | 687 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, |
671 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, | 688 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, |
@@ -722,6 +739,8 @@ static const struct usb_device_id option_ids[] = { | |||
722 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) }, | 739 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) }, |
723 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) }, | 740 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) }, |
724 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, | 741 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, |
742 | /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ | ||
743 | { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, | ||
725 | 744 | ||
726 | { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, | 745 | { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, |
727 | { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, | 746 | { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, |
@@ -1209,6 +1228,11 @@ static const struct usb_device_id option_ids[] = { | |||
1209 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) }, | 1228 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) }, |
1210 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) }, | 1229 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) }, |
1211 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, | 1230 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, |
1231 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU881) }, | ||
1232 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU882) }, | ||
1233 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU581) }, | ||
1234 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU582) }, | ||
1235 | { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU583) }, | ||
1212 | { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, | 1236 | { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, |
1213 | { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, | 1237 | { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, |
1214 | { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ | 1238 | { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ |
@@ -1216,6 +1240,7 @@ static const struct usb_device_id option_ids[] = { | |||
1216 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) }, | 1240 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) }, |
1217 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) }, | 1241 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) }, |
1218 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */ | 1242 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */ |
1243 | { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, | ||
1219 | { } /* Terminating entry */ | 1244 | { } /* Terminating entry */ |
1220 | }; | 1245 | }; |
1221 | MODULE_DEVICE_TABLE(usb, option_ids); | 1246 | MODULE_DEVICE_TABLE(usb, option_ids); |
@@ -1245,7 +1270,7 @@ static struct usb_serial_driver option_1port_device = { | |||
1245 | .ioctl = usb_wwan_ioctl, | 1270 | .ioctl = usb_wwan_ioctl, |
1246 | .attach = usb_wwan_startup, | 1271 | .attach = usb_wwan_startup, |
1247 | .disconnect = usb_wwan_disconnect, | 1272 | .disconnect = usb_wwan_disconnect, |
1248 | .release = usb_wwan_release, | 1273 | .release = option_release, |
1249 | .read_int_callback = option_instat_callback, | 1274 | .read_int_callback = option_instat_callback, |
1250 | #ifdef CONFIG_PM | 1275 | #ifdef CONFIG_PM |
1251 | .suspend = usb_wwan_suspend, | 1276 | .suspend = usb_wwan_suspend, |
@@ -1259,35 +1284,6 @@ static struct usb_serial_driver * const serial_drivers[] = { | |||
1259 | 1284 | ||
1260 | static bool debug; | 1285 | static bool debug; |
1261 | 1286 | ||
1262 | /* per port private data */ | ||
1263 | |||
1264 | #define N_IN_URB 4 | ||
1265 | #define N_OUT_URB 4 | ||
1266 | #define IN_BUFLEN 4096 | ||
1267 | #define OUT_BUFLEN 4096 | ||
1268 | |||
1269 | struct option_port_private { | ||
1270 | /* Input endpoints and buffer for this port */ | ||
1271 | struct urb *in_urbs[N_IN_URB]; | ||
1272 | u8 *in_buffer[N_IN_URB]; | ||
1273 | /* Output endpoints and buffer for this port */ | ||
1274 | struct urb *out_urbs[N_OUT_URB]; | ||
1275 | u8 *out_buffer[N_OUT_URB]; | ||
1276 | unsigned long out_busy; /* Bit vector of URBs in use */ | ||
1277 | int opened; | ||
1278 | struct usb_anchor delayed; | ||
1279 | |||
1280 | /* Settings for the port */ | ||
1281 | int rts_state; /* Handshaking pins (outputs) */ | ||
1282 | int dtr_state; | ||
1283 | int cts_state; /* Handshaking pins (inputs) */ | ||
1284 | int dsr_state; | ||
1285 | int dcd_state; | ||
1286 | int ri_state; | ||
1287 | |||
1288 | unsigned long tx_start_time[N_OUT_URB]; | ||
1289 | }; | ||
1290 | |||
1291 | module_usb_serial_driver(serial_drivers, option_ids); | 1287 | module_usb_serial_driver(serial_drivers, option_ids); |
1292 | 1288 | ||
1293 | static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, | 1289 | static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, |
@@ -1356,12 +1352,22 @@ static int option_probe(struct usb_serial *serial, | |||
1356 | return 0; | 1352 | return 0; |
1357 | } | 1353 | } |
1358 | 1354 | ||
1355 | static void option_release(struct usb_serial *serial) | ||
1356 | { | ||
1357 | struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); | ||
1358 | |||
1359 | usb_wwan_release(serial); | ||
1360 | |||
1361 | kfree(priv); | ||
1362 | } | ||
1363 | |||
1359 | static void option_instat_callback(struct urb *urb) | 1364 | static void option_instat_callback(struct urb *urb) |
1360 | { | 1365 | { |
1361 | int err; | 1366 | int err; |
1362 | int status = urb->status; | 1367 | int status = urb->status; |
1363 | struct usb_serial_port *port = urb->context; | 1368 | struct usb_serial_port *port = urb->context; |
1364 | struct option_port_private *portdata = usb_get_serial_port_data(port); | 1369 | struct usb_wwan_port_private *portdata = |
1370 | usb_get_serial_port_data(port); | ||
1365 | 1371 | ||
1366 | dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); | 1372 | dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); |
1367 | 1373 | ||
@@ -1421,7 +1427,7 @@ static int option_send_setup(struct usb_serial_port *port) | |||
1421 | struct usb_serial *serial = port->serial; | 1427 | struct usb_serial *serial = port->serial; |
1422 | struct usb_wwan_intf_private *intfdata = | 1428 | struct usb_wwan_intf_private *intfdata = |
1423 | (struct usb_wwan_intf_private *) serial->private; | 1429 | (struct usb_wwan_intf_private *) serial->private; |
1424 | struct option_port_private *portdata; | 1430 | struct usb_wwan_port_private *portdata; |
1425 | int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; | 1431 | int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; |
1426 | int val = 0; | 1432 | int val = 0; |
1427 | 1433 | ||