option.c revision f1469fc3ef1d5a8a67146c1c72021f012a59dea6
158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/*
214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  USB Driver for GSM modems
358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs  Copyright (C) 2005  Matthias Urlichs <smurf@smurf.noris.de>
558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs  This driver is free software; you can redistribute it and/or modify
758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs  it under the terms of Version 2 of the GNU General Public License as
858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs  published by the Free Software Foundation.
958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs  Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
1158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
12b3fdab59b8f5d8e42fa339be74cd015dc1a3192fMatthias Urlichs  History: see the git log.
13ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs
14ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs  Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
15ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs
1614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  This driver exists because the "normal" serial driver doesn't work too well
1714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  with GSM modems. Issues:
1814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  - data loss -- one single Receive URB is not nearly enough
197c1c2f73e00b5d0413399a14b7ab9e80db94926fMatthias Urlichs  - nonstandard flow (Option devices) control
2014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  - controlling the baud rate doesn't make sense
2114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs
2214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  This driver is named "option" because the most common device it's
2314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  used for is a PC-Card (with an internal OHCI-USB interface, behind
2414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  which the GSM interface sits), made by Option Inc.
2514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs
2614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  Some of the "one port" devices actually exhibit multiple USB instances
2714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  on the USB bus. This is not a bug, these ports are used for different
2814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs  device features.
2958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs*/
30ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs
315f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins#define DRIVER_VERSION "v0.7.2"
3258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
3314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs#define DRIVER_DESC "USB Driver for GSM modems"
3458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
3558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/kernel.h>
3658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/jiffies.h>
3758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/errno.h>
3858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/tty.h>
3958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/tty_flip.h>
4058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/module.h>
4159c2afa072506aae10ef93126aab651142e0c908Alan Stern#include <linux/bitops.h>
4258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs#include <linux/usb.h>
43a969888ce91673c7f4b86520d851a6f0d5a5fa7dGreg Kroah-Hartman#include <linux/usb/serial.h>
4458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
4558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Function prototypes */
46c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjanstatic int  option_probe(struct usb_serial *serial,
47c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan			const struct usb_device_id *id);
4819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Coxstatic int  option_open(struct tty_struct *tty, struct usb_serial_port *port,
4919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox							struct file *filp);
50335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void option_close(struct usb_serial_port *port);
51335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void option_dtr_rts(struct usb_serial_port *port, int on);
52335f8514f200e63d689113d29cb7253a5c282967Alan Cox
537bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int  option_startup(struct usb_serial *serial);
54f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Sternstatic void option_disconnect(struct usb_serial *serial);
55f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Sternstatic void option_release(struct usb_serial *serial);
5695da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_write_room(struct tty_struct *tty);
5758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
587d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_instat_callback(struct urb *urb);
5958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
6095da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_write(struct tty_struct *tty, struct usb_serial_port *port,
617bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			const unsigned char *buf, int count);
6295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_chars_in_buffer(struct tty_struct *tty);
6395da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void option_set_termios(struct tty_struct *tty,
6495da310e66ee8090119596c70ca8432e57f9a97fAlan Cox			struct usb_serial_port *port, struct ktermios *old);
6595da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_tiocmget(struct tty_struct *tty, struct file *file);
6695da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_tiocmset(struct tty_struct *tty, struct file *file,
677bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton				unsigned int set, unsigned int clear);
68335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic int  option_send_setup(struct usb_serial_port *port);
695f4fab91f2b12c12f0506b4da49ed199db8c64edOliver Neukum#ifdef CONFIG_PM
704901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukumstatic int  option_suspend(struct usb_serial *serial, pm_message_t message);
714901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukumstatic int  option_resume(struct usb_serial *serial);
725f4fab91f2b12c12f0506b4da49ed199db8c64edOliver Neukum#endif
7358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
7458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Vendor and product IDs */
75fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_VENDOR_ID			0x0AF0
76fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_COLT			0x5000
77fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA			0x6000
78fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_LIGHT		0x6100
79fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_QUAD		0x6200
80fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_QUAD_LIGHT	0x6300
81fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_NDIS		0x6050
82fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_NDIS_LIGHT	0x6150
83fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_NDIS_QUAD		0x6250
84fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT	0x6350
85fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_COBRA			0x6500
86fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_COBRA_BUS		0x6501
87fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_VIPER			0x6600
88fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_VIPER_BUS		0x6601
89fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_GT_MAX_READY		0x6701
90fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_FUJI_MODEM_LIGHT		0x6721
91fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_FUJI_MODEM_GT		0x6741
92fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_FUJI_MODEM_EX		0x6761
93fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_KOI_MODEM		0x6800
94fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_SCORPION_MODEM		0x6901
95fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_MODEM		0x7001
96fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_MODEM_LITE		0x7021
97fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_MODEM_GT		0x7041
98fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_MODEM_EX		0x7061
99fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_KOI_MODEM		0x7100
100e7f2f0d77a7b483a26054f29ba8393831b25a8a4Achilleas Kotsis#define OPTION_PRODUCT_GTM380_MODEM		0x7201
101fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman
102fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define HUAWEI_VENDOR_ID			0x12D1
103fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define HUAWEI_PRODUCT_E600			0x1001
104fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define HUAWEI_PRODUCT_E220			0x1003
105a3209a0efc404cc4190b496bae247e7706371032Jaime Velasco Juan#define HUAWEI_PRODUCT_E220BIS			0x1004
106aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1401			0x1401
1071460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1402			0x1402
108aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1403			0x1403
1091460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1404			0x1404
110aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1405			0x1405
111aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1406			0x1406
1121460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1407			0x1407
113aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1408			0x1408
114aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1409			0x1409
1151460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140A			0x140A
1161460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140B			0x140B
1171460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140C			0x140C
1181460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140D			0x140D
1191460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140E			0x140E
1201460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140F			0x140F
121aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1410			0x1410
122aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1411			0x1411
123aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1412			0x1412
124aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1413			0x1413
125aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1414			0x1414
126aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1415			0x1415
127aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1416			0x1416
128aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1417			0x1417
129aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1418			0x1418
130aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1419			0x1419
1311460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141A			0x141A
1321460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141B			0x141B
1331460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141C			0x141C
1341460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141D			0x141D
1351460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141E			0x141E
1361460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141F			0x141F
1371460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1420			0x1420
1381460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1421			0x1421
1391460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1422			0x1422
1401460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1423			0x1423
1411460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1424			0x1424
1421460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1425			0x1425
1431460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1426			0x1426
1441460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1427			0x1427
1451460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1428			0x1428
1461460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1429			0x1429
1471460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142A			0x142A
1481460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142B			0x142B
1491460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142C			0x142C
1501460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142D			0x142D
1511460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142E			0x142E
1521460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142F			0x142F
1531460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1430			0x1430
1541460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1431			0x1431
1551460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1432			0x1432
1561460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1433			0x1433
1571460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1434			0x1434
1581460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1435			0x1435
1591460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1436			0x1436
1601460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1437			0x1437
1611460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1438			0x1438
1621460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1439			0x1439
1631460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143A			0x143A
1641460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143B			0x143B
1651460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143C			0x143C
1661460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143D			0x143D
1671460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143E			0x143E
1681460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143F			0x143F
169fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman
170fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_VENDOR_ID			0x0408
171fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_Q101			0xEA02
172fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_Q111			0xEA03
173fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_GLX			0xEA04
174fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_GKE			0xEA05
175fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_GLE			0xEA06
176fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com
177fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define NOVATELWIRELESS_VENDOR_ID		0x1410
17872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
179c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter/* YISO PRODUCTS */
180c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter
181c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter#define YISO_VENDOR_ID				0x0EAB
182c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter#define YISO_PRODUCT_U893			0xC893
183c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter
18472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* MERLIN EVDO PRODUCTS */
18572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_V640		0x1100
18672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_V620		0x1110
18772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_V740		0x1120
18872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_V720		0x1130
18972ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
19072ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* MERLIN HSDPA/HSPA PRODUCTS */
19172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_U730		0x1400
19272ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_U740		0x1410
19372ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_U870		0x1420
19472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_XU870		0x1430
19572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_X950D		0x1450
19672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
19772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* EXPEDITE PRODUCTS */
19872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_EV620		0x2100
19972ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_ES720		0x2110
20072ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_E725		0x2120
201a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs#define NOVATELWIRELESS_PRODUCT_ES620		0x2130
20272ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_EU730		0x2400
20372ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_EU740		0x2410
20472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_EU870D		0x2420
20572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
20672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* OVATION PRODUCTS */
20772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_MC727		0x4100
20872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_MC950D		0x4400
20956a21827439a4d715b510bfaf488534e6f4ad2f8Dirk Hohndel#define NOVATELWIRELESS_PRODUCT_U727		0x5010
210f1469fc3ef1d5a8a67146c1c72021f012a59dea6Tim Gardner#define NOVATELWIRELESS_PRODUCT_MC727_NEW	0x5100
2119685a59a2bc0e1e85d1848c744214dbe74e9ce7dRichard Laager#define NOVATELWIRELESS_PRODUCT_MC760		0x6000
21271f9f6cc9eef47fddc05f34b3d32677ab2e0f1faDan Williams#define NOVATELWIRELESS_PRODUCT_OVMC760		0x6002
21372ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
21472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* FUTURE NOVATEL PRODUCTS */
215c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED	0X6001
216c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED	0X7000
217c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED	0X7001
218c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED	0X8000
219c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED	0X8001
220c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED	0X9000
221c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED	0X9001
222c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_GLOBAL		0XA001
22372ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
22432147be4cc50e5e4445a8760125cacc258c61638tang kai/* AMOI PRODUCTS */
22532147be4cc50e5e4445a8760125cacc258c61638tang kai#define AMOI_VENDOR_ID				0x1614
22632147be4cc50e5e4445a8760125cacc258c61638tang kai#define AMOI_PRODUCT_H01			0x0800
22732147be4cc50e5e4445a8760125cacc258c61638tang kai#define AMOI_PRODUCT_H01A			0x7002
22832147be4cc50e5e4445a8760125cacc258c61638tang kai#define AMOI_PRODUCT_H02			0x0802
22932147be4cc50e5e4445a8760125cacc258c61638tang kai
23096443218be7f61027c23772d048a1bf549dfb2d7Faidon Liambotis#define DELL_VENDOR_ID				0x413C
231fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman
232c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper/* Dell modems */
233c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5700_MINICARD		0x8114
234c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5500_MINICARD		0x8115
235c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5505_MINICARD		0x8116
236c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5700_EXPRESSCARD		0x8117
237c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5510_EXPRESSCARD		0x8118
238c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper
239c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5700_MINICARD_SPRINT	0x8128
240c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5700_MINICARD_TELUS	0x8129
241c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper
242c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5720_MINICARD_VZW		0x8133
243c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5720_MINICARD_SPRINT	0x8134
244c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5720_MINICARD_TELUS	0x8135
245c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5520_MINICARD_CINGULAR	0x8136
246c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5520_MINICARD_GENERIC_L	0x8137
247c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5520_MINICARD_GENERIC_I	0x8138
248c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper
249c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5730_MINICARD_SPRINT	0x8180
250c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5730_MINICARD_TELUS	0x8181
251c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5730_MINICARD_VZW		0x8182
252c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper
253564d61d30effcc727f9519538143a6c6aeb92e46Dan Williams#define KYOCERA_VENDOR_ID			0x0c88
254640c1bce86d1e11ee6a1263fdf6170d3210b1684Greg Kroah-Hartman#define KYOCERA_PRODUCT_KPC650			0x17da
255564d61d30effcc727f9519538143a6c6aeb92e46Dan Williams#define KYOCERA_PRODUCT_KPC680			0x180a
256564d61d30effcc727f9519538143a6c6aeb92e46Dan Williams
257fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define ANYDATA_VENDOR_ID			0x16d5
258f8033827d8e92db6159d34ed45c608522674ecd8Hiroshi Miura#define ANYDATA_PRODUCT_ADU_620UW		0x6202
25946269db99cc1a618d707deb370d821d1f8d75945Alexander Gattin#define ANYDATA_PRODUCT_ADU_E100A		0x6501
26046269db99cc1a618d707deb370d821d1f8d75945Alexander Gattin#define ANYDATA_PRODUCT_ADU_500A		0x6502
26158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
26285fb62a001278270f9fffbdc3508ef23d5f3693dDaniel Kozák#define AXESSTEL_VENDOR_ID			0x1726
26385fb62a001278270f9fffbdc3508ef23d5f3693dDaniel Kozák#define AXESSTEL_PRODUCT_MV110H			0x1000
26485fb62a001278270f9fffbdc3508ef23d5f3693dDaniel Kozák
2653f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong#define BANDRICH_VENDOR_ID			0x1A8D
2663f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong#define BANDRICH_PRODUCT_C100_1			0x1002
2673f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong#define BANDRICH_PRODUCT_C100_2			0x1003
268bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1004			0x1004
269bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1005			0x1005
270bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1006			0x1006
271bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1007			0x1007
272bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1008			0x1008
273bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1009			0x1009
274bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100A			0x100a
275bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong
276bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100B			0x100b
277bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100C			0x100c
278bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100D			0x100d
279bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100E			0x100e
280bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong
281bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100F			0x100f
282bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1010			0x1010
283bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1011			0x1011
284bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1012			0x1012
2853f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong
286a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs#define AMOI_VENDOR_ID			0x1614
287a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs#define AMOI_PRODUCT_9508			0x0800
288a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs
289d726fb757722a3907356830a0b8d976267596d5cKevin Lloyd#define QUALCOMM_VENDOR_ID			0x05C6
290d726fb757722a3907356830a0b8d976267596d5cKevin Lloyd
29180d9709832390fa7e721bbf4a017da474fdc6c29James Cameron#define MAXON_VENDOR_ID				0x16d8
29280d9709832390fa7e721bbf4a017da474fdc6c29James Cameron
293ee53b0ca0153b4f944cb142b5e65c96a1860d765Greg Kroah-Hartman#define TELIT_VENDOR_ID				0x1bc7
294ee53b0ca0153b4f944cb142b5e65c96a1860d765Greg Kroah-Hartman#define TELIT_PRODUCT_UC864E			0x1003
295ee53b0ca0153b4f944cb142b5e65c96a1860d765Greg Kroah-Hartman
2966188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin/* ZTE PRODUCTS */
2976188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin#define ZTE_VENDOR_ID				0x19d2
2989ea19b82f3126da4e47d6b94563a3c2cd586f6e2Albert Pauw#define ZTE_PRODUCT_MF622			0x0001
2996188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin#define ZTE_PRODUCT_MF628			0x0015
300bfd8408d68975759aba1b466af6f5388d7adb836Mikhail Gusarov#define ZTE_PRODUCT_MF626			0x0031
301884579d03a3e1e9ac8b7f32a1c36387cac3eb80bOtavio Salvador#define ZTE_PRODUCT_CDMA_TECH			0xfffe
3026188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin
30328fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung#define BENQ_VENDOR_ID				0x04a5
30428fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung#define BENQ_PRODUCT_H10			0x4068
30528fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung
306c00deaa542100a697acb5be200b9f54317c1cf69Pascal Terjan#define DLINK_VENDOR_ID				0x1186
307c00deaa542100a697acb5be200b9f54317c1cf69Pascal Terjan#define DLINK_PRODUCT_DWM_652			0x3e04
308c00deaa542100a697acb5be200b9f54317c1cf69Pascal Terjan
309e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu#define QISDA_VENDOR_ID				0x1da5
310e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu#define QISDA_PRODUCT_H21_4512			0x4512
311e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu#define QISDA_PRODUCT_H21_4523			0x4523
312e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu#define QISDA_PRODUCT_H20_4515			0x4515
313e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu#define QISDA_PRODUCT_H20_4519			0x4519
314e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu
315c00deaa542100a697acb5be200b9f54317c1cf69Pascal Terjan
316334f9b0f23c9bb90589213279c9cfe19ebe4c0c6Michele Valzelli/* TOSHIBA PRODUCTS */
317334f9b0f23c9bb90589213279c9cfe19ebe4c0c6Michele Valzelli#define TOSHIBA_VENDOR_ID			0x0930
318334f9b0f23c9bb90589213279c9cfe19ebe4c0c6Michele Valzelli#define TOSHIBA_PRODUCT_HSDPA_MINICARD		0x1302
319334f9b0f23c9bb90589213279c9cfe19ebe4c0c6Michele Valzelli
320c3325eb16d36a49f9a5ae09241c418cfd1d3f4f5Anssi Hannula#define ALINK_VENDOR_ID				0x1e0e
321c3325eb16d36a49f9a5ae09241c418cfd1d3f4f5Anssi Hannula#define ALINK_PRODUCT_3GU			0x9200
322c3325eb16d36a49f9a5ae09241c418cfd1d3f4f5Anssi Hannula
32358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic struct usb_device_id option_ids[] = {
324fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
325fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
326fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
327fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
328fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },
329fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) },
330fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_LIGHT) },
331fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD) },
332fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT) },
33314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
334fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA_BUS) },
335fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) },
336fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) },
337fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) },
338fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) },
339fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) },
340fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) },
341fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) },
342fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) },
343fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) },
344fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) },
345fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) },
346fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) },
347fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
348e7f2f0d77a7b483a26054f29ba8393831b25a8a4Achilleas Kotsis	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTM380_MODEM) },
349fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q101) },
350fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q111) },
351fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
352fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
353fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
354a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
355b5ce18afecda8ce1a9ed5fb8ec6362df6f6f85b8Jaime Velasco Juan	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
356b5ce18afecda8ce1a9ed5fb8ec6362df6f6f85b8Jaime Velasco Juan	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
357a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
3581460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) },
359a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
3601460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) },
361a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
362a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
3631460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) },
364a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
365a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
3661460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) },
3671460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) },
3681460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) },
3691460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) },
3701460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) },
3711460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) },
372a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
373a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
374a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
375a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) },
376a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) },
377a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) },
378a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) },
379a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
380a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
381a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
3821460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) },
3831460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) },
3841460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) },
3851460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) },
3861460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) },
3871460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) },
3881460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) },
3891460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) },
3901460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) },
3911460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) },
3921460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) },
3931460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) },
3941460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) },
3951460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) },
3961460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) },
3971460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) },
3981460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) },
3991460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) },
4001460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) },
4011460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) },
4021460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) },
4031460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) },
4041460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) },
4051460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) },
4061460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) },
4071460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) },
4081460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) },
4091460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) },
4101460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) },
4111460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) },
4121460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) },
4131460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) },
4141460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) },
4151460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) },
4161460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) },
4171460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
4181460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
4191460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
420a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
42172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
42272ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
42372ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */
42472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, /* Novatel Merlin V720/S720/PC720 */
42572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, /* Novatel U730/U740 (VF version) */
42672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, /* Novatel U740 */
42772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, /* Novatel U870 */
42872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, /* Novatel Merlin XU870 HSDPA/3G */
42972ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, /* Novatel X950D */
43072ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, /* Novatel EV620/ES620 CDMA/EV-DO */
43172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, /* Novatel ES620/ES720/U720/USB720 */
43272ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, /* Novatel E725/E726 */
433a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) }, /* Novatel Merlin ES620 SM Bus */
43472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, /* Novatel EU730 and Vodafone EU740 */
43572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, /* Novatel non-Vodafone EU740 */
43672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
43772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
43872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
439f1469fc3ef1d5a8a67146c1c72021f012a59dea6Tim Gardner	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727_NEW) }, /* Novatel MC727/U727/USB727 refresh */
44056a21827439a4d715b510bfaf488534e6f4ad2f8Dirk Hohndel	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */
4419685a59a2bc0e1e85d1848c744214dbe74e9ce7dRichard Laager	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC760) }, /* Novatel MC760/U760/USB760 */
44271f9f6cc9eef47fddc05f34b3d32677ab2e0f1faDan Williams	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_OVMC760) }, /* Novatel Ovation MC760 */
443c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */
444c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */
445c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */
446c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, /* Novatel EVDO product */
447c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) }, /* Novatel HSPA product */
448c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, /* Novatel EVDO Embedded product */
449c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, /* Novatel HSPA Embedded product */
450c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL) }, /* Novatel Global product */
45172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
45232147be4cc50e5e4445a8760125cacc258c61638tang kai	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
45332147be4cc50e5e4445a8760125cacc258c61638tang kai	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
45432147be4cc50e5e4445a8760125cacc258c61638tang kai	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H02) },
45532147be4cc50e5e4445a8760125cacc258c61638tang kai
456c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5700_MINICARD) },		/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite EV620 CDMA/EV-DO */
457c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5500_MINICARD) },		/* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
458c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5505_MINICARD) },		/* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
459c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5700_EXPRESSCARD) },		/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO ExpressCard == Novatel Merlin XV620 CDMA/EV-DO */
460c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5510_EXPRESSCARD) },		/* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */
461c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5700_MINICARD_SPRINT) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite E720 CDMA/EV-DO */
462c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5700_MINICARD_TELUS) },	/* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite ET620 CDMA/EV-DO */
463c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5720_MINICARD_VZW) }, 	/* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */
464c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5720_MINICARD_SPRINT) }, 	/* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */
465c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5720_MINICARD_TELUS) }, 	/* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */
466c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_CINGULAR) },	/* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
467c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_L) },	/* Dell Wireless HSDPA 5520 */
468c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_I) },	/* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */
469c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) },	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
470c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) },	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
471c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, 	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
472bb78a825fa91621e52b9a5409fd9ef07895275bfJon K Hellan	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },	/* ADU-E100, ADU-310 */
47346269db99cc1a618d707deb370d821d1f8d75945Alexander Gattin	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
474f8033827d8e92db6159d34ed45c608522674ecd8Hiroshi Miura	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
47585fb62a001278270f9fffbdc3508ef23d5f3693dDaniel Kozák	{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
476c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter	{ USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
4773f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
4783f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
479bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
480bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) },
481bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) },
482bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) },
483bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) },
484bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) },
485bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) },
486bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) },
487bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) },
488bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) },
489bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) },
490bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) },
491bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) },
492bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) },
493bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) },
494640c1bce86d1e11ee6a1263fdf6170d3210b1684Greg Kroah-Hartman	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
495564d61d30effcc727f9519538143a6c6aeb92e46Dan Williams	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
496d2e2affba4a3619df203d3be8d655ec48d00e3ecGreg Kroah-Hartman	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
497d726fb757722a3907356830a0b8d976267596d5cKevin Lloyd	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
49880d9709832390fa7e721bbf4a017da474fdc6c29James Cameron	{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
499ee53b0ca0153b4f944cb142b5e65c96a1860d765Greg Kroah-Hartman	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
500c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
501c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff) },
502c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) },
503c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0004, 0xff, 0xff, 0xff) },
504c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0005, 0xff, 0xff, 0xff) },
505c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0006, 0xff, 0xff, 0xff) },
506c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0007, 0xff, 0xff, 0xff) },
507c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0008, 0xff, 0xff, 0xff) },
508c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0009, 0xff, 0xff, 0xff) },
509c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000a, 0xff, 0xff, 0xff) },
510c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000b, 0xff, 0xff, 0xff) },
511c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000c, 0xff, 0xff, 0xff) },
512c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000d, 0xff, 0xff, 0xff) },
513c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000e, 0xff, 0xff, 0xff) },
514c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x000f, 0xff, 0xff, 0xff) },
515c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0010, 0xff, 0xff, 0xff) },
516c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0011, 0xff, 0xff, 0xff) },
517c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff) },
518c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
519c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
520c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
521c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff) },
522c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0018, 0xff, 0xff, 0xff) },
523c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff) },
524c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0020, 0xff, 0xff, 0xff) },
525c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff) },
526c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0022, 0xff, 0xff, 0xff) },
527c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0023, 0xff, 0xff, 0xff) },
528c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
529c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff) },
530c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) },
531c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
532c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
533c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
534c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) },
535c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) },
536c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) },
537c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0037, 0xff, 0xff, 0xff) },
538c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0039, 0xff, 0xff, 0xff) },
539c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0042, 0xff, 0xff, 0xff) },
540c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0043, 0xff, 0xff, 0xff) },
541c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0048, 0xff, 0xff, 0xff) },
542c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0049, 0xff, 0xff, 0xff) },
543c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
544c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff) },
545c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
546c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff) },
547c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
548c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff) },
549c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
550c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
551c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff) },
552c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0064, 0xff, 0xff, 0xff) },
553c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
554c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
555c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
556c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
557c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0082, 0xff, 0xff, 0xff) },
558c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
559c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
560c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
561c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
562c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
563c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
564c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
565c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
566c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
567c420befde6b2747ebc2b8f015687a5dbd6e167caHerton Ronaldo Krzesinski	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
56828fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
569c00deaa542100a697acb5be200b9f54317c1cf69Pascal Terjan	{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
570e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) },
571e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
572e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
573e3a3174519bae99fe3a3d3b9dfda68d820527b44Brad Lu	{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
574334f9b0f23c9bb90589213279c9cfe19ebe4c0c6Michele Valzelli	{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
575c3325eb16d36a49f9a5ae09241c418cfd1d3f4f5Anssi Hannula	{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
576c3325eb16d36a49f9a5ae09241c418cfd1d3f4f5Anssi Hannula	{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
57714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	{ } /* Terminating entry */
57814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs};
57958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_DEVICE_TABLE(usb, option_ids);
58058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
58158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic struct usb_driver option_driver = {
58258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	.name       = "option",
58358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	.probe      = usb_serial_probe,
58458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	.disconnect = usb_serial_disconnect,
5855f4fab91f2b12c12f0506b4da49ed199db8c64edOliver Neukum#ifdef CONFIG_PM
5864901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	.suspend    = usb_serial_suspend,
5874901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	.resume     = usb_serial_resume,
5885f4fab91f2b12c12f0506b4da49ed199db8c64edOliver Neukum#endif
58958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	.id_table   = option_ids,
590ba9dc657af86d05d2971633e57d1f6f94ed60472Greg Kroah-Hartman	.no_dynamic_id = 	1,
59158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs};
59258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
593c30fe7f73194650148b58ee80908c1bc38246397Uwe Zeisberger/* The card has three separate interfaces, which the serial driver
59458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs * recognizes separately, thus num_port=1.
59558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs */
59614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs
59714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichsstatic struct usb_serial_driver option_1port_device = {
59814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	.driver = {
59914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		.owner =	THIS_MODULE,
60002b2ac5b0370b1157a5a99f2fdf006644b9b86d5Matthias Urlichs		.name =		"option1",
60114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	},
60214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	.description       = "GSM modem (1-port)",
603d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl	.usb_driver        = &option_driver,
604b656b2cbd74fb591d46e07c7c291791b280ad5b4Greg Kroah-Hartman	.id_table          = option_ids,
60514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	.num_ports         = 1,
606c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan	.probe             = option_probe,
607ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.open              = option_open,
608ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.close             = option_close,
609335f8514f200e63d689113d29cb7253a5c282967Alan Cox	.dtr_rts	   = option_dtr_rts,
610ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.write             = option_write,
611ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.write_room        = option_write_room,
612ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.chars_in_buffer   = option_chars_in_buffer,
613ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.set_termios       = option_set_termios,
614ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.tiocmget          = option_tiocmget,
615ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.tiocmset          = option_tiocmset,
616ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.attach            = option_startup,
617f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern	.disconnect        = option_disconnect,
618f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern	.release           = option_release,
619ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.read_int_callback = option_instat_callback,
6205f4fab91f2b12c12f0506b4da49ed199db8c64edOliver Neukum#ifdef CONFIG_PM
6214901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	.suspend           = option_suspend,
6224901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	.resume            = option_resume,
6235f4fab91f2b12c12f0506b4da49ed199db8c64edOliver Neukum#endif
62458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs};
62558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
62658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic int debug;
627ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs
62858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* per port private data */
62958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
630ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#define N_IN_URB 4
631f1632df36b9467b75b7abfd2799aef67ec74a60aGreg Kroah-Hartman#define N_OUT_URB 4
632b27c73dcab61826e5f1228d69d56f469b0abfc05Matthias Urlichs#define IN_BUFLEN 4096
633f1632df36b9467b75b7abfd2799aef67ec74a60aGreg Kroah-Hartman#define OUT_BUFLEN 4096
63458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
63558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstruct option_port_private {
63658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Input endpoints and buffer for this port */
637ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct urb *in_urbs[N_IN_URB];
6382129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	u8 *in_buffer[N_IN_URB];
63958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Output endpoints and buffer for this port */
640ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct urb *out_urbs[N_OUT_URB];
6412129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	u8 *out_buffer[N_OUT_URB];
64259c2afa072506aae10ef93126aab651142e0c908Alan Stern	unsigned long out_busy;		/* Bit vector of URBs in use */
64358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
64458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Settings for the port */
645ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int rts_state;	/* Handshaking pins (outputs) */
646ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int dtr_state;
647ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int cts_state;	/* Handshaking pins (inputs) */
648ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int dsr_state;
649ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int dcd_state;
650ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int ri_state;
651ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs
652ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	unsigned long tx_start_time[N_OUT_URB];
65358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs};
65458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
65558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Functions used by new usb-serial code. */
6567bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int __init option_init(void)
65758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
65858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int retval;
65914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	retval = usb_serial_register(&option_1port_device);
66014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	if (retval)
66114f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		goto failed_1port_device_register;
66258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	retval = usb_register(&option_driver);
66358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (retval)
66458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		goto failed_driver_register;
66558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
666c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
667c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman	       DRIVER_DESC "\n");
66858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
66958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return 0;
67058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
67158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsfailed_driver_register:
67219e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	usb_serial_deregister(&option_1port_device);
67314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichsfailed_1port_device_register:
67458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return retval;
67558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
67658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
6777bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void __exit option_exit(void)
67858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
67919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	usb_deregister(&option_driver);
68019e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	usb_serial_deregister(&option_1port_device);
68158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
68258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
68358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_init(option_init);
68458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_exit(option_exit);
68558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
686c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjanstatic int option_probe(struct usb_serial *serial,
687c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan			const struct usb_device_id *id)
688c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan{
689c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan	/* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */
690c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan	if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID &&
691c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan		serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 &&
692c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan		serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8)
693c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan		return -ENODEV;
694c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan
695c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan	return 0;
696c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan}
697c5be1b52d9ea6ede4931691bf9f0bd454515aa52Pascal Terjan
69895da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void option_set_termios(struct tty_struct *tty,
69995da310e66ee8090119596c70ca8432e57f9a97fAlan Cox		struct usb_serial_port *port, struct ktermios *old_termios)
70058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
701441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
702e650d8ae0494bb937eea6c7fd1a60e57ba74cd53Alan Cox	/* Doesn't support option setting */
70395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	tty_termios_copy_hw(tty->termios, old_termios);
704335f8514f200e63d689113d29cb7253a5c282967Alan Cox	option_send_setup(port);
70558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
70658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
70795da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_tiocmget(struct tty_struct *tty, struct file *file)
70858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
70995da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	struct usb_serial_port *port = tty->driver_data;
710ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	unsigned int value;
711ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
71258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
71358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
71458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
71558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
71658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->dtr_state) ? TIOCM_DTR : 0) |
71758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->cts_state) ? TIOCM_CTS : 0) |
71858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->dsr_state) ? TIOCM_DSR : 0) |
71958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->dcd_state) ? TIOCM_CAR : 0) |
72058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->ri_state) ? TIOCM_RNG : 0);
72158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
72258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return value;
72358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
72458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
72595da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_tiocmset(struct tty_struct *tty, struct file *file,
7267bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			unsigned int set, unsigned int clear)
72758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
72895da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	struct usb_serial_port *port = tty->driver_data;
729ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
73058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
73158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
73258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
733e298449401463dd18f24a87c48f9b0ec62bad936Alan Cox	/* FIXME: what locks portdata fields ? */
73458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (set & TIOCM_RTS)
73558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->rts_state = 1;
73658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (set & TIOCM_DTR)
73758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->dtr_state = 1;
73858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
73958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (clear & TIOCM_RTS)
74058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->rts_state = 0;
74158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (clear & TIOCM_DTR)
74258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->dtr_state = 0;
743335f8514f200e63d689113d29cb7253a5c282967Alan Cox	return option_send_setup(port);
74458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
74558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
74658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Write */
74795da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_write(struct tty_struct *tty, struct usb_serial_port *port,
7487bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			const unsigned char *buf, int count)
74958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
750ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
751ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int i;
752ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int left, todo;
753ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct urb *this_urb = NULL; /* spurious */
754ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int err;
75558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
75658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
75758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
758441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: write (%d chars)", __func__, count);
75958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
76058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	i = 0;
76158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	left = count;
76219e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	for (i = 0; left > 0 && i < N_OUT_URB; i++) {
76358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		todo = left;
76458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (todo > OUT_BUFLEN)
76558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			todo = OUT_BUFLEN;
76658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
767ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs		this_urb = portdata->out_urbs[i];
76859c2afa072506aae10ef93126aab651142e0c908Alan Stern		if (test_and_set_bit(i, &portdata->out_busy)) {
7697bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			if (time_before(jiffies,
7707bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton					portdata->tx_start_time[i] + 10 * HZ))
77158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				continue;
77258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			usb_unlink_urb(this_urb);
773ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs			continue;
77458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
775441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison		dbg("%s: endpoint %d buf %d", __func__,
7767bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			usb_pipeendpoint(this_urb->pipe), i);
77758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
778ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs		/* send the data */
77919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		memcpy(this_urb->transfer_buffer, buf, todo);
78058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		this_urb->transfer_buffer_length = todo;
78158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
78258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		err = usb_submit_urb(this_urb, GFP_ATOMIC);
78358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (err) {
7847bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("usb_submit_urb %p (write bulk) failed "
78550de36f7af3b1d791c402478210790c582126fe5Greg Kroah-Hartman				"(%d)", this_urb, err);
78659c2afa072506aae10ef93126aab651142e0c908Alan Stern			clear_bit(i, &portdata->out_busy);
78758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			continue;
78858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
78958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->tx_start_time[i] = jiffies;
79058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		buf += todo;
79158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		left -= todo;
79258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
79358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
79458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	count -= left;
795441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: wrote (did %d)", __func__, count);
79658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return count;
79758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
79858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
7997d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_indat_callback(struct urb *urb)
80058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
80133f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	int err;
80258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int endpoint;
80358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct usb_serial_port *port;
80458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct tty_struct *tty;
80558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	unsigned char *data = urb->transfer_buffer;
806d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	int status = urb->status;
80758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
808441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: %p", __func__, urb);
80958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
81058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	endpoint = usb_pipeendpoint(urb->pipe);
811cdc97792289179974af6dda781c855696358d307Ming Lei	port =  urb->context;
81258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
813d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	if (status) {
81458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		dbg("%s: nonzero status: %d on endpoint %02x.",
815441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison		    __func__, status, endpoint);
81658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	} else {
8174a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox		tty = tty_port_tty_get(&port->port);
81858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (urb->actual_length) {
81933f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox			tty_buffer_request_room(tty, urb->actual_length);
82033f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox			tty_insert_flip_string(tty, data, urb->actual_length);
82158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			tty_flip_buffer_push(tty);
8224a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox		} else
823441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: empty read urb received", __func__);
8244a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox		tty_kref_put(tty);
82558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
82658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		/* Resubmit urb so we continue receiving */
82795da310e66ee8090119596c70ca8432e57f9a97fAlan Cox		if (port->port.count && status != -ESHUTDOWN) {
82858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			err = usb_submit_urb(urb, GFP_ATOMIC);
82958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			if (err)
8307bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton				printk(KERN_ERR "%s: resubmit read urb failed. "
831441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison					"(%d)", __func__, err);
83258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
83358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
83458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return;
83558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
83658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
8377d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_outdat_callback(struct urb *urb)
83858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
83958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct usb_serial_port *port;
84059c2afa072506aae10ef93126aab651142e0c908Alan Stern	struct option_port_private *portdata;
84159c2afa072506aae10ef93126aab651142e0c908Alan Stern	int i;
84258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
843441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
84458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
845cdc97792289179974af6dda781c855696358d307Ming Lei	port =  urb->context;
84658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
847cf2c7481d2ff7f0c266de873b2fe93883e9782f9Pete Zaitcev	usb_serial_port_softint(port);
84859c2afa072506aae10ef93126aab651142e0c908Alan Stern
84959c2afa072506aae10ef93126aab651142e0c908Alan Stern	portdata = usb_get_serial_port_data(port);
85059c2afa072506aae10ef93126aab651142e0c908Alan Stern	for (i = 0; i < N_OUT_URB; ++i) {
85159c2afa072506aae10ef93126aab651142e0c908Alan Stern		if (portdata->out_urbs[i] == urb) {
85259c2afa072506aae10ef93126aab651142e0c908Alan Stern			smp_mb__before_clear_bit();
85359c2afa072506aae10ef93126aab651142e0c908Alan Stern			clear_bit(i, &portdata->out_busy);
85459c2afa072506aae10ef93126aab651142e0c908Alan Stern			break;
85559c2afa072506aae10ef93126aab651142e0c908Alan Stern		}
85659c2afa072506aae10ef93126aab651142e0c908Alan Stern	}
85758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
85858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
8597d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_instat_callback(struct urb *urb)
86058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
86158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int err;
862d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	int status = urb->status;
863cdc97792289179974af6dda781c855696358d307Ming Lei	struct usb_serial_port *port =  urb->context;
86458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct option_port_private *portdata = usb_get_serial_port_data(port);
86558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
866441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
86719e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
86858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
869d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	if (status == 0) {
87058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		struct usb_ctrlrequest *req_pkt =
87158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				(struct usb_ctrlrequest *)urb->transfer_buffer;
87258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
87358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (!req_pkt) {
874441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: NULL req_pkt\n", __func__);
87558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			return;
87658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
8777bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		if ((req_pkt->bRequestType == 0xA1) &&
8787bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton				(req_pkt->bRequest == 0x20)) {
87958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			int old_dcd_state;
88058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			unsigned char signals = *((unsigned char *)
8817bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton					urb->transfer_buffer +
8827bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton					sizeof(struct usb_ctrlrequest));
88358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
884441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: signal x%x", __func__, signals);
88558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
88658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			old_dcd_state = portdata->dcd_state;
88758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			portdata->cts_state = 1;
88858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
88958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
89058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			portdata->ri_state = ((signals & 0x08) ? 1 : 0);
89158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
8924a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox			if (old_dcd_state && !portdata->dcd_state) {
8934a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox				struct tty_struct *tty =
8944a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox						tty_port_tty_get(&port->port);
8954a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox				if (tty && !C_CLOCAL(tty))
8964a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox					tty_hangup(tty);
8974a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox				tty_kref_put(tty);
8984a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox			}
8997bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		} else {
900441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: type %x req %x", __func__,
90119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox				req_pkt->bRequestType, req_pkt->bRequest);
9027bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		}
90358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	} else
9044901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		err("%s: error %d", __func__, status);
90558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
90658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Resubmit urb so we continue receiving IRQ data */
9074901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	if (status != -ESHUTDOWN && status != -ENOENT) {
90858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		err = usb_submit_urb(urb, GFP_ATOMIC);
90958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (err)
9107bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("%s: resubmit intr urb failed. (%d)",
911441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison				__func__, err);
91258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
91358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
91458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
91595da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_write_room(struct tty_struct *tty)
91658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
91795da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	struct usb_serial_port *port = tty->driver_data;
91858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct option_port_private *portdata;
91958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int i;
92058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int data_len = 0;
92158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct urb *this_urb;
92258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
92358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
92458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
92519e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	for (i = 0; i < N_OUT_URB; i++) {
92658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		this_urb = portdata->out_urbs[i];
92759c2afa072506aae10ef93126aab651142e0c908Alan Stern		if (this_urb && !test_bit(i, &portdata->out_busy))
92858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			data_len += OUT_BUFLEN;
929ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	}
93058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
931441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: %d", __func__, data_len);
93258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return data_len;
93358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
93458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
93595da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_chars_in_buffer(struct tty_struct *tty)
93658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
93795da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	struct usb_serial_port *port = tty->driver_data;
93858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct option_port_private *portdata;
93958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int i;
94058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int data_len = 0;
94158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct urb *this_urb;
94258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
94358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
94458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
94519e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	for (i = 0; i < N_OUT_URB; i++) {
94658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		this_urb = portdata->out_urbs[i];
947a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox		/* FIXME: This locking is insufficient as this_urb may
948a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox		   go unused during the test */
94959c2afa072506aae10ef93126aab651142e0c908Alan Stern		if (this_urb && test_bit(i, &portdata->out_busy))
95058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			data_len += this_urb->transfer_buffer_length;
951ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	}
952441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: %d", __func__, data_len);
95358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return data_len;
95458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
95558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
95695da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_open(struct tty_struct *tty,
95795da310e66ee8090119596c70ca8432e57f9a97fAlan Cox			struct usb_serial_port *port, struct file *filp)
95858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
959ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
960ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int i, err;
961ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct urb *urb;
96258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
96358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
96458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
965441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
96658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
967f092c240494f2d807401d93f95f683909b90af96Alan Stern	/* Start reading from the IN endpoint */
96858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < N_IN_URB; i++) {
96958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		urb = portdata->in_urbs[i];
97019e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		if (!urb)
97158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			continue;
97258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		err = usb_submit_urb(urb, GFP_KERNEL);
97358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (err) {
9747bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("%s: submit urb %d failed (%d) %d",
975441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison				__func__, i, err,
97658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				urb->transfer_buffer_length);
97758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
97858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
97958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
980335f8514f200e63d689113d29cb7253a5c282967Alan Cox	option_send_setup(port);
98158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
98219e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	return 0;
98358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
98458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
985335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void option_dtr_rts(struct usb_serial_port *port, int on)
98658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
987ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial *serial = port->serial;
988ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
98958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
990441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
99158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
992335f8514f200e63d689113d29cb7253a5c282967Alan Cox	mutex_lock(&serial->disc_mutex);
993335f8514f200e63d689113d29cb7253a5c282967Alan Cox	portdata->rts_state = on;
994335f8514f200e63d689113d29cb7253a5c282967Alan Cox	portdata->dtr_state = on;
995335f8514f200e63d689113d29cb7253a5c282967Alan Cox	if (serial->dev)
996335f8514f200e63d689113d29cb7253a5c282967Alan Cox		option_send_setup(port);
997335f8514f200e63d689113d29cb7253a5c282967Alan Cox	mutex_unlock(&serial->disc_mutex);
998335f8514f200e63d689113d29cb7253a5c282967Alan Cox}
99958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
100058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1001335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic void option_close(struct usb_serial_port *port)
1002335f8514f200e63d689113d29cb7253a5c282967Alan Cox{
1003335f8514f200e63d689113d29cb7253a5c282967Alan Cox	int i;
1004335f8514f200e63d689113d29cb7253a5c282967Alan Cox	struct usb_serial *serial = port->serial;
1005335f8514f200e63d689113d29cb7253a5c282967Alan Cox	struct option_port_private *portdata;
1006335f8514f200e63d689113d29cb7253a5c282967Alan Cox
1007335f8514f200e63d689113d29cb7253a5c282967Alan Cox	dbg("%s", __func__);
1008335f8514f200e63d689113d29cb7253a5c282967Alan Cox	portdata = usb_get_serial_port_data(port);
100958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1010335f8514f200e63d689113d29cb7253a5c282967Alan Cox	if (serial->dev) {
101158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		/* Stop reading/writing urbs */
101258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (i = 0; i < N_IN_URB; i++)
10137d28e74b97c8eb859fd9f5eb018bb1c75627bd55Oliver Neukum			usb_kill_urb(portdata->in_urbs[i]);
101458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (i = 0; i < N_OUT_URB; i++)
10157d28e74b97c8eb859fd9f5eb018bb1c75627bd55Oliver Neukum			usb_kill_urb(portdata->out_urbs[i]);
101658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
101758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
101858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
101958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Helper functions used by option_setup_urbs */
10207bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
10217bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		int dir, void *ctx, char *buf, int len,
10227d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells		void (*callback)(struct urb *))
102358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
102458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct urb *urb;
102558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
102658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (endpoint == -1)
102758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		return NULL;		/* endpoint not needed */
102858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
102958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */
103058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (urb == NULL) {
1031441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison		dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
103258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		return NULL;
103358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
103458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
103558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		/* Fill URB using supplied data. */
103658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	usb_fill_bulk_urb(urb, serial->dev,
103758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		      usb_sndbulkpipe(serial->dev, endpoint) | dir,
103858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		      buf, len, callback, ctx);
103958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
104058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return urb;
104158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
104258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
104358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Setup urbs */
10447bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_setup_urbs(struct usb_serial *serial)
104558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
104619e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	int i, j;
1047ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial_port *port;
1048ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
104958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1050441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
105158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
105214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	for (i = 0; i < serial->num_ports; i++) {
105314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		port = serial->port[i];
105414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		portdata = usb_get_serial_port_data(port);
105558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
105619e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		/* Do indat endpoints first */
105714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		for (j = 0; j < N_IN_URB; ++j) {
105819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox			portdata->in_urbs[j] = option_setup_urb(serial,
105919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					port->bulk_in_endpointAddress,
106019e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					USB_DIR_IN, port,
106119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					portdata->in_buffer[j],
106219e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					IN_BUFLEN, option_indat_callback);
106314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		}
106458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
106514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		/* outdat endpoints */
106614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		for (j = 0; j < N_OUT_URB; ++j) {
106719e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox			portdata->out_urbs[j] = option_setup_urb(serial,
106819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					port->bulk_out_endpointAddress,
106919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					USB_DIR_OUT, port,
107019e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					portdata->out_buffer[j],
107119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					OUT_BUFLEN, option_outdat_callback);
107214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		}
107358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
107458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
107558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
10765f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins
10775f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins/** send RTS/DTR state to the port.
10785f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins *
10795f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
10805f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins * CDC.
10815f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins*/
1082335f8514f200e63d689113d29cb7253a5c282967Alan Coxstatic int option_send_setup(struct usb_serial_port *port)
108358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
108458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct usb_serial *serial = port->serial;
108558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct option_port_private *portdata;
10865f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins	int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
1087335f8514f200e63d689113d29cb7253a5c282967Alan Cox	int val = 0;
1088441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
108958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
109058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
109158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1092335f8514f200e63d689113d29cb7253a5c282967Alan Cox	if (portdata->dtr_state)
1093335f8514f200e63d689113d29cb7253a5c282967Alan Cox		val |= 0x01;
1094335f8514f200e63d689113d29cb7253a5c282967Alan Cox	if (portdata->rts_state)
1095335f8514f200e63d689113d29cb7253a5c282967Alan Cox		val |= 0x02;
109658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1097335f8514f200e63d689113d29cb7253a5c282967Alan Cox	return usb_control_msg(serial->dev,
1098335f8514f200e63d689113d29cb7253a5c282967Alan Cox		usb_rcvctrlpipe(serial->dev, 0),
1099335f8514f200e63d689113d29cb7253a5c282967Alan Cox		0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
110058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
110158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
11027bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_startup(struct usb_serial *serial)
110358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
11042129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	int i, j, err;
1105ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial_port *port;
1106ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
11072129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	u8 *buffer;
110858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1109441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
111058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
111158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Now setup per port private data */
111258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < serial->num_ports; i++) {
111358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		port = serial->port[i];
111480b6ca48321974a6566a1c9048ba34f60420bca6Eric Sesterhenn		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
111558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (!portdata) {
11167bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("%s: kmalloc for option_port_private (%d) failed!.",
1117441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison					__func__, i);
111819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox			return 1;
111958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
112058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
11212129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		for (j = 0; j < N_IN_URB; j++) {
11222129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			buffer = (u8 *)__get_free_page(GFP_KERNEL);
11232129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			if (!buffer)
11242129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum				goto bail_out_error;
11252129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			portdata->in_buffer[j] = buffer;
11262129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		}
11272129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum
11282129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		for (j = 0; j < N_OUT_URB; j++) {
11292129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
11302129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			if (!buffer)
11312129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum				goto bail_out_error2;
11322129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			portdata->out_buffer[j] = buffer;
11332129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		}
11342129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum
113558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		usb_set_serial_port_data(port, portdata);
113658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
113719e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		if (!port->interrupt_in_urb)
113858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			continue;
113958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
114058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (err)
11417bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("%s: submit irq_in urb failed %d",
1142441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison				__func__, err);
114358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
114458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	option_setup_urbs(serial);
114519e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	return 0;
11462129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum
11472129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukumbail_out_error2:
11482129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	for (j = 0; j < N_OUT_URB; j++)
11492129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		kfree(portdata->out_buffer[j]);
11502129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukumbail_out_error:
11512129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	for (j = 0; j < N_IN_URB; j++)
11522129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		if (portdata->in_buffer[j])
11532129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			free_page((unsigned long)portdata->in_buffer[j]);
11542129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	kfree(portdata);
11552129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	return 1;
115658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
115758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
11584901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukumstatic void stop_read_write_urbs(struct usb_serial *serial)
115958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
1160ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int i, j;
1161ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial_port *port;
1162ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
116358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
116458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Stop reading/writing urbs */
116558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < serial->num_ports; ++i) {
116658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		port = serial->port[i];
116758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata = usb_get_serial_port_data(port);
116858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (j = 0; j < N_IN_URB; j++)
11697d28e74b97c8eb859fd9f5eb018bb1c75627bd55Oliver Neukum			usb_kill_urb(portdata->in_urbs[j]);
117058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (j = 0; j < N_OUT_URB; j++)
11717d28e74b97c8eb859fd9f5eb018bb1c75627bd55Oliver Neukum			usb_kill_urb(portdata->out_urbs[j]);
117258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
11734901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum}
11744901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
1175f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Sternstatic void option_disconnect(struct usb_serial *serial)
1176f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern{
1177f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern	dbg("%s", __func__);
1178f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern
1179f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern	stop_read_write_urbs(serial);
1180f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern}
1181f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Stern
1182f9c99bb8b3a1ec81af68d484a551307326c2e933Alan Sternstatic void option_release(struct usb_serial *serial)
11834901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum{
11844901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	int i, j;
11854901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	struct usb_serial_port *port;
11864901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	struct option_port_private *portdata;
11874901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
11884901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	dbg("%s", __func__);
11894901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
119058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Now free them */
119158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < serial->num_ports; ++i) {
119258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		port = serial->port[i];
119358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata = usb_get_serial_port_data(port);
119458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
119558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (j = 0; j < N_IN_URB; j++) {
119658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			if (portdata->in_urbs[j]) {
119758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				usb_free_urb(portdata->in_urbs[j]);
119819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox				free_page((unsigned long)
119919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					portdata->in_buffer[j]);
120058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				portdata->in_urbs[j] = NULL;
120158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			}
120258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
120358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (j = 0; j < N_OUT_URB; j++) {
120458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			if (portdata->out_urbs[j]) {
120558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				usb_free_urb(portdata->out_urbs[j]);
12062129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum				kfree(portdata->out_buffer[j]);
120758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				portdata->out_urbs[j] = NULL;
120858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			}
120958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
121058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
121158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
121258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Now free per port private data */
121358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < serial->num_ports; i++) {
121458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		port = serial->port[i];
121558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		kfree(usb_get_serial_port_data(port));
121658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
121758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
121858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
12195f4fab91f2b12c12f0506b4da49ed199db8c64edOliver Neukum#ifdef CONFIG_PM
12204901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukumstatic int option_suspend(struct usb_serial *serial, pm_message_t message)
12214901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum{
12224901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	dbg("%s entered", __func__);
12234901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	stop_read_write_urbs(serial);
12244901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
12254901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	return 0;
12264901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum}
12274901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
12284901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukumstatic int option_resume(struct usb_serial *serial)
12294901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum{
12304901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	int err, i, j;
12314901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	struct usb_serial_port *port;
12324901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	struct urb *urb;
12334901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	struct option_port_private *portdata;
12344901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
12354901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	dbg("%s entered", __func__);
12364901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	/* get the interrupt URBs resubmitted unconditionally */
12374901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	for (i = 0; i < serial->num_ports; i++) {
12384901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		port = serial->port[i];
12394901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		if (!port->interrupt_in_urb) {
12404901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			dbg("%s: No interrupt URB for port %d\n", __func__, i);
12414901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			continue;
12424901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		}
12434901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
12444901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		dbg("Submitted interrupt URB for port %d (result %d)", i, err);
12454901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		if (err < 0) {
12464901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			err("%s: Error %d for interrupt URB of port%d",
12474901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum				 __func__, err, i);
12484901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			return err;
12494901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		}
12504901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	}
12514901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
12524901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	for (i = 0; i < serial->num_ports; i++) {
12534901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		/* walk all ports */
12544901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		port = serial->port[i];
12554901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		portdata = usb_get_serial_port_data(port);
12564901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		mutex_lock(&port->mutex);
12574901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
12584901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		/* skip closed ports */
12594901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		if (!port->port.count) {
12604901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			mutex_unlock(&port->mutex);
12614901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			continue;
12624901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		}
12634901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
12644901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		for (j = 0; j < N_IN_URB; j++) {
12654901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			urb = portdata->in_urbs[j];
12664901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			err = usb_submit_urb(urb, GFP_NOIO);
12674901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			if (err < 0) {
12684901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum				mutex_unlock(&port->mutex);
12694901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum				err("%s: Error %d for bulk URB %d",
12704901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum					 __func__, err, i);
12714901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum				return err;
12724901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum			}
12734901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		}
12744901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum		mutex_unlock(&port->mutex);
12754901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	}
12764901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum	return 0;
12774901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum}
12785f4fab91f2b12c12f0506b4da49ed199db8c64edOliver Neukum#endif
12794901b2c34ecb6fc45909228ad269c8126efe4401Oliver Neukum
128058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_AUTHOR(DRIVER_AUTHOR);
128158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_DESCRIPTION(DRIVER_DESC);
128258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_VERSION(DRIVER_VERSION);
128358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_LICENSE("GPL");
128458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
128558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_param(debug, bool, S_IRUGO | S_IWUSR);
128658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_PARM_DESC(debug, "Debug messages");
1287