option.c revision 9ea19b82f3126da4e47d6b94563a3c2cd586f6e2
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 */
4619e58fae0c8f197d80fcea338b94fb5740369bc1Alan Coxstatic int  option_open(struct tty_struct *tty, struct usb_serial_port *port,
4719e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox							struct file *filp);
4819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Coxstatic void option_close(struct tty_struct *tty, struct usb_serial_port *port,
4919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox							struct file *filp);
507bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int  option_startup(struct usb_serial *serial);
517bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_shutdown(struct usb_serial *serial);
5295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_write_room(struct tty_struct *tty);
5358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
547d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_instat_callback(struct urb *urb);
5558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
5695da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_write(struct tty_struct *tty, struct usb_serial_port *port,
577bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			const unsigned char *buf, int count);
5895da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_chars_in_buffer(struct tty_struct *tty);
5995da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void option_set_termios(struct tty_struct *tty,
6095da310e66ee8090119596c70ca8432e57f9a97fAlan Cox			struct usb_serial_port *port, struct ktermios *old);
6195da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_tiocmget(struct tty_struct *tty, struct file *file);
6295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_tiocmset(struct tty_struct *tty, struct file *file,
637bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton				unsigned int set, unsigned int clear);
6495da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
6558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
6658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Vendor and product IDs */
67fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_VENDOR_ID			0x0AF0
68fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_COLT			0x5000
69fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA			0x6000
70fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_LIGHT		0x6100
71fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_QUAD		0x6200
72fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_QUAD_LIGHT	0x6300
73fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_NDIS		0x6050
74fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_NDIS_LIGHT	0x6150
75fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_NDIS_QUAD		0x6250
76fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT	0x6350
77fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_COBRA			0x6500
78fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_COBRA_BUS		0x6501
79fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_VIPER			0x6600
80fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_VIPER_BUS		0x6601
81fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_GT_MAX_READY		0x6701
82fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_FUJI_MODEM_LIGHT		0x6721
83fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_FUJI_MODEM_GT		0x6741
84fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_FUJI_MODEM_EX		0x6761
85fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_KOI_MODEM		0x6800
86fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_SCORPION_MODEM		0x6901
87fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_MODEM		0x7001
88fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_MODEM_LITE		0x7021
89fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_MODEM_GT		0x7041
90fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_MODEM_EX		0x7061
91fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define OPTION_PRODUCT_ETNA_KOI_MODEM		0x7100
92fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman
93fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define HUAWEI_VENDOR_ID			0x12D1
94fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define HUAWEI_PRODUCT_E600			0x1001
95fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define HUAWEI_PRODUCT_E220			0x1003
96a3209a0efc404cc4190b496bae247e7706371032Jaime Velasco Juan#define HUAWEI_PRODUCT_E220BIS			0x1004
97aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1401			0x1401
981460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1402			0x1402
99aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1403			0x1403
1001460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1404			0x1404
101aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1405			0x1405
102aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1406			0x1406
1031460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1407			0x1407
104aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1408			0x1408
105aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1409			0x1409
1061460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140A			0x140A
1071460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140B			0x140B
1081460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140C			0x140C
1091460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140D			0x140D
1101460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140E			0x140E
1111460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E140F			0x140F
112aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1410			0x1410
113aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1411			0x1411
114aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1412			0x1412
115aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1413			0x1413
116aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1414			0x1414
117aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1415			0x1415
118aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1416			0x1416
119aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1417			0x1417
120aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1418			0x1418
121aad8a278f37e748bfe310a1366f2aa7e0dbaf365fangxiaozhi#define HUAWEI_PRODUCT_E1419			0x1419
1221460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141A			0x141A
1231460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141B			0x141B
1241460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141C			0x141C
1251460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141D			0x141D
1261460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141E			0x141E
1271460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E141F			0x141F
1281460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1420			0x1420
1291460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1421			0x1421
1301460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1422			0x1422
1311460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1423			0x1423
1321460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1424			0x1424
1331460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1425			0x1425
1341460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1426			0x1426
1351460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1427			0x1427
1361460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1428			0x1428
1371460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1429			0x1429
1381460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142A			0x142A
1391460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142B			0x142B
1401460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142C			0x142C
1411460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142D			0x142D
1421460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142E			0x142E
1431460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E142F			0x142F
1441460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1430			0x1430
1451460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1431			0x1431
1461460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1432			0x1432
1471460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1433			0x1433
1481460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1434			0x1434
1491460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1435			0x1435
1501460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1436			0x1436
1511460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1437			0x1437
1521460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1438			0x1438
1531460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E1439			0x1439
1541460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143A			0x143A
1551460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143B			0x143B
1561460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143C			0x143C
1571460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143D			0x143D
1581460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143E			0x143E
1591460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi#define HUAWEI_PRODUCT_E143F			0x143F
160fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman
161fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_VENDOR_ID			0x0408
162fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_Q101			0xEA02
163fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_Q111			0xEA03
164fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_GLX			0xEA04
165fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_GKE			0xEA05
166fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com#define QUANTA_PRODUCT_GLE			0xEA06
167fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com
168fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define NOVATELWIRELESS_VENDOR_ID		0x1410
16972ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
170c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter/* YISO PRODUCTS */
171c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter
172c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter#define YISO_VENDOR_ID				0x0EAB
173c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter#define YISO_PRODUCT_U893			0xC893
174c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter
17572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* MERLIN EVDO PRODUCTS */
17672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_V640		0x1100
17772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_V620		0x1110
17872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_V740		0x1120
17972ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_V720		0x1130
18072ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
18172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* MERLIN HSDPA/HSPA PRODUCTS */
18272ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_U730		0x1400
18372ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_U740		0x1410
18472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_U870		0x1420
18572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_XU870		0x1430
18672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_X950D		0x1450
18772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
18872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* EXPEDITE PRODUCTS */
18972ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_EV620		0x2100
19072ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_ES720		0x2110
19172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_E725		0x2120
192a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs#define NOVATELWIRELESS_PRODUCT_ES620		0x2130
19372ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_EU730		0x2400
19472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_EU740		0x2410
19572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_EU870D		0x2420
19672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
19772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* OVATION PRODUCTS */
19872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_MC727		0x4100
19972ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper#define NOVATELWIRELESS_PRODUCT_MC950D		0x4400
20072ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
20172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper/* FUTURE NOVATEL PRODUCTS */
202c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED	0X6000
203c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED	0X6001
204c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED	0X7000
205c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED	0X7001
206c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED	0X8000
207c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED	0X8001
208c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED	0X9000
209c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED	0X9001
210c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define NOVATELWIRELESS_PRODUCT_GLOBAL		0XA001
21172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
21232147be4cc50e5e4445a8760125cacc258c61638tang kai/* AMOI PRODUCTS */
21332147be4cc50e5e4445a8760125cacc258c61638tang kai#define AMOI_VENDOR_ID				0x1614
21432147be4cc50e5e4445a8760125cacc258c61638tang kai#define AMOI_PRODUCT_H01			0x0800
21532147be4cc50e5e4445a8760125cacc258c61638tang kai#define AMOI_PRODUCT_H01A			0x7002
21632147be4cc50e5e4445a8760125cacc258c61638tang kai#define AMOI_PRODUCT_H02			0x0802
21732147be4cc50e5e4445a8760125cacc258c61638tang kai
21896443218be7f61027c23772d048a1bf549dfb2d7Faidon Liambotis#define DELL_VENDOR_ID				0x413C
219fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman
220c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper/* Dell modems */
221c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5700_MINICARD		0x8114
222c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5500_MINICARD		0x8115
223c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5505_MINICARD		0x8116
224c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5700_EXPRESSCARD		0x8117
225c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5510_EXPRESSCARD		0x8118
226c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper
227c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5700_MINICARD_SPRINT	0x8128
228c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5700_MINICARD_TELUS	0x8129
229c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper
230c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5720_MINICARD_VZW		0x8133
231c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5720_MINICARD_SPRINT	0x8134
232c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5720_MINICARD_TELUS	0x8135
233c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5520_MINICARD_CINGULAR	0x8136
234c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5520_MINICARD_GENERIC_L	0x8137
235c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5520_MINICARD_GENERIC_I	0x8138
236c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper
237c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5730_MINICARD_SPRINT	0x8180
238c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5730_MINICARD_TELUS	0x8181
239c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper#define DELL_PRODUCT_5730_MINICARD_VZW		0x8182
240c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper
241564d61d30effcc727f9519538143a6c6aeb92e46Dan Williams#define KYOCERA_VENDOR_ID			0x0c88
242640c1bce86d1e11ee6a1263fdf6170d3210b1684Greg Kroah-Hartman#define KYOCERA_PRODUCT_KPC650			0x17da
243564d61d30effcc727f9519538143a6c6aeb92e46Dan Williams#define KYOCERA_PRODUCT_KPC680			0x180a
244564d61d30effcc727f9519538143a6c6aeb92e46Dan Williams
245fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman#define ANYDATA_VENDOR_ID			0x16d5
246f8033827d8e92db6159d34ed45c608522674ecd8Hiroshi Miura#define ANYDATA_PRODUCT_ADU_620UW		0x6202
24746269db99cc1a618d707deb370d821d1f8d75945Alexander Gattin#define ANYDATA_PRODUCT_ADU_E100A		0x6501
24846269db99cc1a618d707deb370d821d1f8d75945Alexander Gattin#define ANYDATA_PRODUCT_ADU_500A		0x6502
24958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
25085fb62a001278270f9fffbdc3508ef23d5f3693dDaniel Kozák#define AXESSTEL_VENDOR_ID			0x1726
25185fb62a001278270f9fffbdc3508ef23d5f3693dDaniel Kozák#define AXESSTEL_PRODUCT_MV110H			0x1000
25285fb62a001278270f9fffbdc3508ef23d5f3693dDaniel Kozák
2534c7d3137fe4fce634d55a6e99c95dff4c6306702andreoli@samba.ing.unimo.it#define ONDA_VENDOR_ID				0x19d2
2541b2d23d49cf4b4b1fe3b43d3ffd6077fc4ee9ac6Arnaldo Carvalho de Melo#define ONDA_PRODUCT_MSA501HS			0x0001
2554c7d3137fe4fce634d55a6e99c95dff4c6306702andreoli@samba.ing.unimo.it#define ONDA_PRODUCT_ET502HS			0x0002
2563b498a66a698c581535c0fcf1a8907f3fe9449ccMarcel Sebek#define ONDA_PRODUCT_MT503HS			0x2000
2574c7d3137fe4fce634d55a6e99c95dff4c6306702andreoli@samba.ing.unimo.it
2583f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong#define BANDRICH_VENDOR_ID			0x1A8D
2593f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong#define BANDRICH_PRODUCT_C100_1			0x1002
2603f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong#define BANDRICH_PRODUCT_C100_2			0x1003
261bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1004			0x1004
262bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1005			0x1005
263bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1006			0x1006
264bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1007			0x1007
265bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1008			0x1008
266bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1009			0x1009
267bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100A			0x100a
268bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong
269bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100B			0x100b
270bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100C			0x100c
271bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100D			0x100d
272bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100E			0x100e
273bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong
274bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_100F			0x100f
275bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1010			0x1010
276bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1011			0x1011
277bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong#define BANDRICH_PRODUCT_1012			0x1012
2783f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong
279a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs#define AMOI_VENDOR_ID			0x1614
280a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs#define AMOI_PRODUCT_9508			0x0800
281a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs
282d726fb757722a3907356830a0b8d976267596d5cKevin Lloyd#define QUALCOMM_VENDOR_ID			0x05C6
283d726fb757722a3907356830a0b8d976267596d5cKevin Lloyd
28480d9709832390fa7e721bbf4a017da474fdc6c29James Cameron#define MAXON_VENDOR_ID				0x16d8
28580d9709832390fa7e721bbf4a017da474fdc6c29James Cameron
286ee53b0ca0153b4f944cb142b5e65c96a1860d765Greg Kroah-Hartman#define TELIT_VENDOR_ID				0x1bc7
287ee53b0ca0153b4f944cb142b5e65c96a1860d765Greg Kroah-Hartman#define TELIT_PRODUCT_UC864E			0x1003
288ee53b0ca0153b4f944cb142b5e65c96a1860d765Greg Kroah-Hartman
2896188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin/* ZTE PRODUCTS */
2906188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin#define ZTE_VENDOR_ID				0x19d2
2919ea19b82f3126da4e47d6b94563a3c2cd586f6e2Albert Pauw#define ZTE_PRODUCT_MF622			0x0001
2926188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin#define ZTE_PRODUCT_MF628			0x0015
293bfd8408d68975759aba1b466af6f5388d7adb836Mikhail Gusarov#define ZTE_PRODUCT_MF626			0x0031
294884579d03a3e1e9ac8b7f32a1c36387cac3eb80bOtavio Salvador#define ZTE_PRODUCT_CDMA_TECH			0xfffe
2956188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin
296b064eca9b0cdbb2b8f731ae2e44fa02194a1219aDan Williams/* Ericsson products */
297b064eca9b0cdbb2b8f731ae2e44fa02194a1219aDan Williams#define ERICSSON_VENDOR_ID			0x0bdb
2985d7a4755d53a5305d05d836d87ef7c9ff94d6fa7Patrik Kullman#define ERICSSON_PRODUCT_F3507G_1		0x1900
2995d7a4755d53a5305d05d836d87ef7c9ff94d6fa7Patrik Kullman#define ERICSSON_PRODUCT_F3507G_2		0x1902
300b064eca9b0cdbb2b8f731ae2e44fa02194a1219aDan Williams
30128fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung#define BENQ_VENDOR_ID				0x04a5
30228fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung#define BENQ_PRODUCT_H10			0x4068
30328fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung
30458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic struct usb_device_id option_ids[] = {
305fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
306fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
307fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
308fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
309fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },
310fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS) },
311fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_LIGHT) },
312fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD) },
313fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_NDIS_QUAD_LIGHT) },
31414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
315fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA_BUS) },
316fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER) },
317fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_VIPER_BUS) },
318fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GT_MAX_READY) },
319fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_LIGHT) },
320fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_GT) },
321fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUJI_MODEM_EX) },
322fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_KOI_MODEM) },
323fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_SCORPION_MODEM) },
324fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM) },
325fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_LITE) },
326fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) },
327fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) },
328fd978bfa127a0b8c0bdbbbc9d64f3c73bf080f61Greg Kroah-Hartman	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) },
329fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q101) },
330fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q111) },
331fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) },
332fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) },
333fc91be2ad03e0d243418414a854665274d560ca2Alex.Cheng@quantatw.com	{ USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) },
334a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) },
335b5ce18afecda8ce1a9ed5fb8ec6362df6f6f85b8Jaime Velasco Juan	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) },
336b5ce18afecda8ce1a9ed5fb8ec6362df6f6f85b8Jaime Velasco Juan	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) },
337a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) },
3381460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) },
339a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) },
3401460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) },
341a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) },
342a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) },
3431460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) },
344a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) },
345a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) },
3461460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) },
3471460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) },
3481460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) },
3491460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) },
3501460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) },
3511460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) },
352a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) },
353a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) },
354a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) },
355a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) },
356a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) },
357a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) },
358a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) },
359a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) },
360a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) },
361a7f3872c43b8001f01000f79583d422c6995f98dMichael Karcher	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) },
3621460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) },
3631460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) },
3641460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) },
3651460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) },
3661460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) },
3671460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) },
3681460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) },
3691460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) },
3701460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) },
3711460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) },
3721460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) },
3731460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) },
3741460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) },
3751460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) },
3761460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) },
3771460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) },
3781460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) },
3791460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) },
3801460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) },
3811460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) },
3821460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) },
3831460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) },
3841460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) },
3851460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) },
3861460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) },
3871460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) },
3881460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) },
3891460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) },
3901460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) },
3911460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) },
3921460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) },
3931460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) },
3941460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) },
3951460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) },
3961460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) },
3971460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
3981460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
3991460e5e44cc5ecad7704f63b10dcb3a59d0e008bfangxiaozhi	{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
400a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
40172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
40272ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
40372ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */
40472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V720) }, /* Novatel Merlin V720/S720/PC720 */
40572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U730) }, /* Novatel U730/U740 (VF version) */
40672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U740) }, /* Novatel U740 */
40772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U870) }, /* Novatel U870 */
40872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_XU870) }, /* Novatel Merlin XU870 HSDPA/3G */
40972ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_X950D) }, /* Novatel X950D */
41072ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EV620) }, /* Novatel EV620/ES620 CDMA/EV-DO */
41172ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES720) }, /* Novatel ES620/ES720/U720/USB720 */
41272ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E725) }, /* Novatel E725/E726 */
413a1d9bc12e06a71b01f626040dc5149b357e8f1ebMatthias Urlichs	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_ES620) }, /* Novatel Merlin ES620 SM Bus */
41472ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU730) }, /* Novatel EU730 and Vodafone EU740 */
41572ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU740) }, /* Novatel non-Vodafone EU740 */
41672ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */
41772ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */
41872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */
419c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) }, /* Novatel EVDO product */
420c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */
421c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */
422c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) }, /* Novatel HSPA Embedded product */
423c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) }, /* Novatel EVDO product */
424c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) }, /* Novatel HSPA product */
425c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, /* Novatel EVDO Embedded product */
426c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, /* Novatel HSPA Embedded product */
427c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_GLOBAL) }, /* Novatel Global product */
42872ab6414cf1eaeae8cece64290123d82357fda7eDirk DeSchepper
42932147be4cc50e5e4445a8760125cacc258c61638tang kai	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
43032147be4cc50e5e4445a8760125cacc258c61638tang kai	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
43132147be4cc50e5e4445a8760125cacc258c61638tang kai	{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H02) },
43232147be4cc50e5e4445a8760125cacc258c61638tang kai
433c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk 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 */
434c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5500_MINICARD) },		/* Dell Wireless 5500 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
435c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5505_MINICARD) },		/* Dell Wireless 5505 Mobile Broadband HSDPA Mini-Card == Novatel Expedite EU740 HSDPA/3G */
436c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk 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 */
437c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5510_EXPRESSCARD) },		/* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */
438c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk 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 */
439c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk 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 */
440c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5720_MINICARD_VZW) }, 	/* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */
441c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5720_MINICARD_SPRINT) }, 	/* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */
442c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5720_MINICARD_TELUS) }, 	/* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */
443c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_CINGULAR) },	/* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
444c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_L) },	/* Dell Wireless HSDPA 5520 */
445c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_I) },	/* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */
446c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, 0x8147) },					/* Dell Wireless 5530 Mobile Broadband (3G HSPA) Mini-Card */
447c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) },	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
448c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) },	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
449c200b9c9e8ec93cdd262cfa1699ad92e883d4876Dirk De Schepper	{ USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, 	/* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
450bb78a825fa91621e52b9a5409fd9ef07895275bfJon K Hellan	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },	/* ADU-E100, ADU-310 */
45146269db99cc1a618d707deb370d821d1f8d75945Alexander Gattin	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
452f8033827d8e92db6159d34ed45c608522674ecd8Hiroshi Miura	{ USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
45385fb62a001278270f9fffbdc3508ef23d5f3693dDaniel Kozák	{ USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) },
4541b2d23d49cf4b4b1fe3b43d3ffd6077fc4ee9ac6Arnaldo Carvalho de Melo	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) },
4554c7d3137fe4fce634d55a6e99c95dff4c6306702andreoli@samba.ing.unimo.it	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) },
4565bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0003) },
4575bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0004) },
4585bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0005) },
4595bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0006) },
4605bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0007) },
4615bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0008) },
4625bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0009) },
4635bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x000a) },
4645bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x000b) },
4655bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x000c) },
4665bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x000d) },
4675bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x000e) },
4685bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x000f) },
4695bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0010) },
4705bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0011) },
4715bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0012) },
4725bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0013) },
4735bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0014) },
4745bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0015) },
4755bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0016) },
4765bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0017) },
4775bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0018) },
4785bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0019) },
4795bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0020) },
4805bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0021) },
4815bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0022) },
4825bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0023) },
4835bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0024) },
4845bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0025) },
4855bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0026) },
4865bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0027) },
4875bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0028) },
4885bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, 0x0029) },
4895bb4bd9895df508ed2bd8b3280252d8a8170e4acGreg Kroah-Hartman	{ USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MT503HS) },
490c6206faa4f18bcc837a12552b8c184ab1668fdeaLeslie Watter	{ USB_DEVICE(YISO_VENDOR_ID, YISO_PRODUCT_U893) },
4913f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) },
4923f6e58467c635ebbb4a139cbe5e0c1f46792e18cLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) },
493bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1004) },
494bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1005) },
495bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1006) },
496bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1007) },
497bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1008) },
498bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1009) },
499bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100A) },
500bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100B) },
501bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100C) },
502bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100D) },
503bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100E) },
504bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_100F) },
505bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1010) },
506bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1011) },
507bf3fc82895f4f501da9daef44d057749fe900c3eLeon Leong	{ USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012) },
508640c1bce86d1e11ee6a1263fdf6170d3210b1684Greg Kroah-Hartman	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
509564d61d30effcc727f9519538143a6c6aeb92e46Dan Williams	{ USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
510d2e2affba4a3619df203d3be8d655ec48d00e3ecGreg Kroah-Hartman	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
511d726fb757722a3907356830a0b8d976267596d5cKevin Lloyd	{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
51280d9709832390fa7e721bbf4a017da474fdc6c29James Cameron	{ USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
513ee53b0ca0153b4f944cb142b5e65c96a1860d765Greg Kroah-Hartman	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
5149ea19b82f3126da4e47d6b94563a3c2cd586f6e2Albert Pauw	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) },
515bfd8408d68975759aba1b466af6f5388d7adb836Mikhail Gusarov	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
5166188a83f7264edebe9b8ee10ad7b2136d3531ea6Oliver Martin	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
517884579d03a3e1e9ac8b7f32a1c36387cac3eb80bOtavio Salvador	{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
5185d7a4755d53a5305d05d836d87ef7c9ff94d6fa7Patrik Kullman	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) },
5195d7a4755d53a5305d05d836d87ef7c9ff94d6fa7Patrik Kullman	{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) },
52028fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung	{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
52128fb66821f884870987a0b5ab064ef651d9f7c16Jesse Sung	{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
52214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	{ } /* Terminating entry */
52314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs};
52458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_DEVICE_TABLE(usb, option_ids);
52558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
52658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic struct usb_driver option_driver = {
52758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	.name       = "option",
52858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	.probe      = usb_serial_probe,
52958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	.disconnect = usb_serial_disconnect,
53058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	.id_table   = option_ids,
531ba9dc657af86d05d2971633e57d1f6f94ed60472Greg Kroah-Hartman	.no_dynamic_id = 	1,
53258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs};
53358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
534c30fe7f73194650148b58ee80908c1bc38246397Uwe Zeisberger/* The card has three separate interfaces, which the serial driver
53558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs * recognizes separately, thus num_port=1.
53658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs */
53714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs
53814f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichsstatic struct usb_serial_driver option_1port_device = {
53914f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	.driver = {
54014f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		.owner =	THIS_MODULE,
54102b2ac5b0370b1157a5a99f2fdf006644b9b86d5Matthias Urlichs		.name =		"option1",
54214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	},
54314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	.description       = "GSM modem (1-port)",
544d9b1b787736852f462dbf277b3ca708cbbf693aeJohannes Hölzl	.usb_driver        = &option_driver,
545b656b2cbd74fb591d46e07c7c291791b280ad5b4Greg Kroah-Hartman	.id_table          = option_ids,
54614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	.num_ports         = 1,
547ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.open              = option_open,
548ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.close             = option_close,
549ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.write             = option_write,
550ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.write_room        = option_write_room,
551ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.chars_in_buffer   = option_chars_in_buffer,
552ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.set_termios       = option_set_termios,
553ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.tiocmget          = option_tiocmget,
554ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.tiocmset          = option_tiocmset,
555ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.attach            = option_startup,
556ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.shutdown          = option_shutdown,
557ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	.read_int_callback = option_instat_callback,
55858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs};
55958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
56058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstatic int debug;
561ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs
56258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* per port private data */
56358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
564ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs#define N_IN_URB 4
565f1632df36b9467b75b7abfd2799aef67ec74a60aGreg Kroah-Hartman#define N_OUT_URB 4
566b27c73dcab61826e5f1228d69d56f469b0abfc05Matthias Urlichs#define IN_BUFLEN 4096
567f1632df36b9467b75b7abfd2799aef67ec74a60aGreg Kroah-Hartman#define OUT_BUFLEN 4096
56858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
56958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsstruct option_port_private {
57058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Input endpoints and buffer for this port */
571ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct urb *in_urbs[N_IN_URB];
5722129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	u8 *in_buffer[N_IN_URB];
57358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Output endpoints and buffer for this port */
574ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct urb *out_urbs[N_OUT_URB];
5752129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	u8 *out_buffer[N_OUT_URB];
57659c2afa072506aae10ef93126aab651142e0c908Alan Stern	unsigned long out_busy;		/* Bit vector of URBs in use */
57758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
57858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Settings for the port */
579ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int rts_state;	/* Handshaking pins (outputs) */
580ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int dtr_state;
581ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int cts_state;	/* Handshaking pins (inputs) */
582ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int dsr_state;
583ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int dcd_state;
584ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int ri_state;
585ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs
586ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	unsigned long tx_start_time[N_OUT_URB];
58758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs};
58858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
58958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Functions used by new usb-serial code. */
5907bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int __init option_init(void)
59158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
59258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int retval;
59314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	retval = usb_serial_register(&option_1port_device);
59414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	if (retval)
59514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		goto failed_1port_device_register;
59658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	retval = usb_register(&option_driver);
59758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (retval)
59858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		goto failed_driver_register;
59958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
600c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
601c197a8db59daf06dc5e77acd5a9681329cb22458Greg Kroah-Hartman	       DRIVER_DESC "\n");
60258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
60358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return 0;
60458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
60558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsfailed_driver_register:
60619e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	usb_serial_deregister(&option_1port_device);
60714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichsfailed_1port_device_register:
60858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return retval;
60958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
61058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
6117bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void __exit option_exit(void)
61258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
61319e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	usb_deregister(&option_driver);
61419e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	usb_serial_deregister(&option_1port_device);
61558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
61658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
61758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_init(option_init);
61858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_exit(option_exit);
61958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
62095da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void option_set_termios(struct tty_struct *tty,
62195da310e66ee8090119596c70ca8432e57f9a97fAlan Cox		struct usb_serial_port *port, struct ktermios *old_termios)
62258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
623441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
624e650d8ae0494bb937eea6c7fd1a60e57ba74cd53Alan Cox	/* Doesn't support option setting */
62595da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	tty_termios_copy_hw(tty->termios, old_termios);
62695da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	option_send_setup(tty, port);
62758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
62858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
62995da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_tiocmget(struct tty_struct *tty, struct file *file)
63058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
63195da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	struct usb_serial_port *port = tty->driver_data;
632ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	unsigned int value;
633ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
63458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
63558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
63658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
63758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
63858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->dtr_state) ? TIOCM_DTR : 0) |
63958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->cts_state) ? TIOCM_CTS : 0) |
64058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->dsr_state) ? TIOCM_DSR : 0) |
64158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->dcd_state) ? TIOCM_CAR : 0) |
64258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		((portdata->ri_state) ? TIOCM_RNG : 0);
64358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
64458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return value;
64558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
64658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
64795da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_tiocmset(struct tty_struct *tty, struct file *file,
6487bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			unsigned int set, unsigned int clear)
64958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
65095da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	struct usb_serial_port *port = tty->driver_data;
651ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
65258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
65358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
65458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
655e298449401463dd18f24a87c48f9b0ec62bad936Alan Cox	/* FIXME: what locks portdata fields ? */
65658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (set & TIOCM_RTS)
65758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->rts_state = 1;
65858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (set & TIOCM_DTR)
65958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->dtr_state = 1;
66058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
66158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (clear & TIOCM_RTS)
66258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->rts_state = 0;
66358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (clear & TIOCM_DTR)
66458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->dtr_state = 0;
66595da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	return option_send_setup(tty, port);
66658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
66758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
66858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Write */
66995da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_write(struct tty_struct *tty, struct usb_serial_port *port,
6707bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			const unsigned char *buf, int count)
67158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
672ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
673ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int i;
674ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int left, todo;
675ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct urb *this_urb = NULL; /* spurious */
676ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int err;
67758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
67858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
67958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
680441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: write (%d chars)", __func__, count);
68158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
68258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	i = 0;
68358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	left = count;
68419e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	for (i = 0; left > 0 && i < N_OUT_URB; i++) {
68558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		todo = left;
68658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (todo > OUT_BUFLEN)
68758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			todo = OUT_BUFLEN;
68858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
689ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs		this_urb = portdata->out_urbs[i];
69059c2afa072506aae10ef93126aab651142e0c908Alan Stern		if (test_and_set_bit(i, &portdata->out_busy)) {
6917bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			if (time_before(jiffies,
6927bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton					portdata->tx_start_time[i] + 10 * HZ))
69358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				continue;
69458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			usb_unlink_urb(this_urb);
695ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs			continue;
69658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
697441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison		dbg("%s: endpoint %d buf %d", __func__,
6987bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			usb_pipeendpoint(this_urb->pipe), i);
69958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
700ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs		/* send the data */
70119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		memcpy(this_urb->transfer_buffer, buf, todo);
70258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		this_urb->transfer_buffer_length = todo;
70358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
70458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		this_urb->dev = port->serial->dev;
70558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		err = usb_submit_urb(this_urb, GFP_ATOMIC);
70658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (err) {
7077bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("usb_submit_urb %p (write bulk) failed "
70850de36f7af3b1d791c402478210790c582126fe5Greg Kroah-Hartman				"(%d)", this_urb, err);
70959c2afa072506aae10ef93126aab651142e0c908Alan Stern			clear_bit(i, &portdata->out_busy);
71058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			continue;
71158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
71258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata->tx_start_time[i] = jiffies;
71358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		buf += todo;
71458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		left -= todo;
71558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
71658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
71758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	count -= left;
718441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: wrote (did %d)", __func__, count);
71958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return count;
72058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
72158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
7227d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_indat_callback(struct urb *urb)
72358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
72433f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox	int err;
72558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int endpoint;
72658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct usb_serial_port *port;
72758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct tty_struct *tty;
72858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	unsigned char *data = urb->transfer_buffer;
729d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	int status = urb->status;
73058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
731441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: %p", __func__, urb);
73258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
73358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	endpoint = usb_pipeendpoint(urb->pipe);
734cdc97792289179974af6dda781c855696358d307Ming Lei	port =  urb->context;
73558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
736d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	if (status) {
73758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		dbg("%s: nonzero status: %d on endpoint %02x.",
738441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison		    __func__, status, endpoint);
73958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	} else {
7404a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox		tty = tty_port_tty_get(&port->port);
74158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (urb->actual_length) {
74233f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox			tty_buffer_request_room(tty, urb->actual_length);
74333f0f88f1c51ae5c2d593d26960c760ea154c2e2Alan Cox			tty_insert_flip_string(tty, data, urb->actual_length);
74458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			tty_flip_buffer_push(tty);
7454a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox		} else
746441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: empty read urb received", __func__);
7474a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox		tty_kref_put(tty);
74858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
74958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		/* Resubmit urb so we continue receiving */
75095da310e66ee8090119596c70ca8432e57f9a97fAlan Cox		if (port->port.count && status != -ESHUTDOWN) {
75158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			err = usb_submit_urb(urb, GFP_ATOMIC);
75258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			if (err)
7537bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton				printk(KERN_ERR "%s: resubmit read urb failed. "
754441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison					"(%d)", __func__, err);
75558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
75658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
75758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return;
75858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
75958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
7607d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_outdat_callback(struct urb *urb)
76158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
76258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct usb_serial_port *port;
76359c2afa072506aae10ef93126aab651142e0c908Alan Stern	struct option_port_private *portdata;
76459c2afa072506aae10ef93126aab651142e0c908Alan Stern	int i;
76558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
766441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
76758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
768cdc97792289179974af6dda781c855696358d307Ming Lei	port =  urb->context;
76958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
770cf2c7481d2ff7f0c266de873b2fe93883e9782f9Pete Zaitcev	usb_serial_port_softint(port);
77159c2afa072506aae10ef93126aab651142e0c908Alan Stern
77259c2afa072506aae10ef93126aab651142e0c908Alan Stern	portdata = usb_get_serial_port_data(port);
77359c2afa072506aae10ef93126aab651142e0c908Alan Stern	for (i = 0; i < N_OUT_URB; ++i) {
77459c2afa072506aae10ef93126aab651142e0c908Alan Stern		if (portdata->out_urbs[i] == urb) {
77559c2afa072506aae10ef93126aab651142e0c908Alan Stern			smp_mb__before_clear_bit();
77659c2afa072506aae10ef93126aab651142e0c908Alan Stern			clear_bit(i, &portdata->out_busy);
77759c2afa072506aae10ef93126aab651142e0c908Alan Stern			break;
77859c2afa072506aae10ef93126aab651142e0c908Alan Stern		}
77959c2afa072506aae10ef93126aab651142e0c908Alan Stern	}
78058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
78158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
7827d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic void option_instat_callback(struct urb *urb)
78358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
78458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int err;
785d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	int status = urb->status;
786cdc97792289179974af6dda781c855696358d307Ming Lei	struct usb_serial_port *port =  urb->context;
78758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct option_port_private *portdata = usb_get_serial_port_data(port);
78858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct usb_serial *serial = port->serial;
78958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
790441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
79119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata);
79258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
793d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	if (status == 0) {
79458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		struct usb_ctrlrequest *req_pkt =
79558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				(struct usb_ctrlrequest *)urb->transfer_buffer;
79658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
79758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (!req_pkt) {
798441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: NULL req_pkt\n", __func__);
79958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			return;
80058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
8017bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		if ((req_pkt->bRequestType == 0xA1) &&
8027bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton				(req_pkt->bRequest == 0x20)) {
80358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			int old_dcd_state;
80458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			unsigned char signals = *((unsigned char *)
8057bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton					urb->transfer_buffer +
8067bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton					sizeof(struct usb_ctrlrequest));
80758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
808441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: signal x%x", __func__, signals);
80958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
81058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			old_dcd_state = portdata->dcd_state;
81158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			portdata->cts_state = 1;
81258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
81358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
81458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			portdata->ri_state = ((signals & 0x08) ? 1 : 0);
81558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
8164a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox			if (old_dcd_state && !portdata->dcd_state) {
8174a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox				struct tty_struct *tty =
8184a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox						tty_port_tty_get(&port->port);
8194a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox				if (tty && !C_CLOCAL(tty))
8204a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox					tty_hangup(tty);
8214a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox				tty_kref_put(tty);
8224a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox			}
8237bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		} else {
824441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: type %x req %x", __func__,
82519e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox				req_pkt->bRequestType, req_pkt->bRequest);
8267bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		}
82758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	} else
828441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison		dbg("%s: error %d", __func__, status);
82958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
83058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Resubmit urb so we continue receiving IRQ data */
831d6977b51d5faa8649bbab0e53455e8421d425ce1Greg Kroah-Hartman	if (status != -ESHUTDOWN) {
83258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		urb->dev = serial->dev;
83358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		err = usb_submit_urb(urb, GFP_ATOMIC);
83458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (err)
8357bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("%s: resubmit intr urb failed. (%d)",
836441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison				__func__, err);
83758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
83858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
83958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
84095da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_write_room(struct tty_struct *tty)
84158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
84295da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	struct usb_serial_port *port = tty->driver_data;
84358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct option_port_private *portdata;
84458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int i;
84558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int data_len = 0;
84658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct urb *this_urb;
84758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
84858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
84958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
850a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox
85119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	for (i = 0; i < N_OUT_URB; i++) {
85258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		this_urb = portdata->out_urbs[i];
85359c2afa072506aae10ef93126aab651142e0c908Alan Stern		if (this_urb && !test_bit(i, &portdata->out_busy))
85458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			data_len += OUT_BUFLEN;
855ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	}
85658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
857441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: %d", __func__, data_len);
85858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return data_len;
85958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
86058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
86195da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_chars_in_buffer(struct tty_struct *tty)
86258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
86395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	struct usb_serial_port *port = tty->driver_data;
86458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct option_port_private *portdata;
86558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int i;
86658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	int data_len = 0;
86758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct urb *this_urb;
86858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
86958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
87058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
87119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	for (i = 0; i < N_OUT_URB; i++) {
87258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		this_urb = portdata->out_urbs[i];
873a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox		/* FIXME: This locking is insufficient as this_urb may
874a5b6f60c5a30c494017c7a2d11c4067f90d3d0dfAlan Cox		   go unused during the test */
87559c2afa072506aae10ef93126aab651142e0c908Alan Stern		if (this_urb && test_bit(i, &portdata->out_busy))
87658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			data_len += this_urb->transfer_buffer_length;
877ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	}
878441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s: %d", __func__, data_len);
87958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return data_len;
88058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
88158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
88295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_open(struct tty_struct *tty,
88395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox			struct usb_serial_port *port, struct file *filp)
88458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
885ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
886ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial *serial = port->serial;
887ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int i, err;
888ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct urb *urb;
88958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
89058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
89158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
892441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
89358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
89458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Set some sane defaults */
89558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata->rts_state = 1;
89658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata->dtr_state = 1;
89758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
89858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Reset low level data toggle and start reading from endpoints */
89958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < N_IN_URB; i++) {
90058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		urb = portdata->in_urbs[i];
90119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		if (!urb)
90258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			continue;
90358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (urb->dev != serial->dev) {
904441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison			dbg("%s: dev %p != %p", __func__,
9057bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton				urb->dev, serial->dev);
90658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			continue;
90758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
90858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
9097bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		/*
9107bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		 * make sure endpoint data toggle is synchronized with the
9117bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		 * device
9127bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		 */
91358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		usb_clear_halt(urb->dev, urb->pipe);
91458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
91558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		err = usb_submit_urb(urb, GFP_KERNEL);
91658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (err) {
9177bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("%s: submit urb %d failed (%d) %d",
918441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison				__func__, i, err,
91958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				urb->transfer_buffer_length);
92058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
92158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
92258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
92358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Reset low level data toggle on out endpoints */
92458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < N_OUT_URB; i++) {
92558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		urb = portdata->out_urbs[i];
92619e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		if (!urb)
92758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			continue;
92858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		urb->dev = serial->dev;
9297bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
9307bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton				usb_pipeout(urb->pipe), 0); */
93158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
93258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
93395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	if (tty)
93495da310e66ee8090119596c70ca8432e57f9a97fAlan Cox		tty->low_latency = 1;
93558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
93695da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	option_send_setup(tty, port);
93758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
93819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	return 0;
93958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
94058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
94195da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic void option_close(struct tty_struct *tty,
94295da310e66ee8090119596c70ca8432e57f9a97fAlan Cox			struct usb_serial_port *port, struct file *filp)
94358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
944ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int i;
945ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial *serial = port->serial;
946ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
94758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
948441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
94958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
95058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
95158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata->rts_state = 0;
95258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata->dtr_state = 0;
95358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
95458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (serial->dev) {
955e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum		mutex_lock(&serial->disc_mutex);
956e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum		if (!serial->disconnected)
95795da310e66ee8090119596c70ca8432e57f9a97fAlan Cox			option_send_setup(tty, port);
958e33fe4d86f91127f6f7d931ff59ed6cbda06e72bOliver Neukum		mutex_unlock(&serial->disc_mutex);
95958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
96058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		/* Stop reading/writing urbs */
96158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (i = 0; i < N_IN_URB; i++)
9627d28e74b97c8eb859fd9f5eb018bb1c75627bd55Oliver Neukum			usb_kill_urb(portdata->in_urbs[i]);
96358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (i = 0; i < N_OUT_URB; i++)
9647d28e74b97c8eb859fd9f5eb018bb1c75627bd55Oliver Neukum			usb_kill_urb(portdata->out_urbs[i]);
96558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
9664a90f09b20f4622dcbff1f0e1e6bae1704f8ad8cAlan Cox	tty_port_tty_set(&port->port, NULL);
96758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
96858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
96958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Helper functions used by option_setup_urbs */
9707bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic struct urb *option_setup_urb(struct usb_serial *serial, int endpoint,
9717bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		int dir, void *ctx, char *buf, int len,
9727d12e780e003f93433d49ce78cfedf4b4c52adc5David Howells		void (*callback)(struct urb *))
97358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
97458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct urb *urb;
97558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
97658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (endpoint == -1)
97758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		return NULL;		/* endpoint not needed */
97858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
97958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */
98058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	if (urb == NULL) {
981441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison		dbg("%s: alloc for endpoint %d failed.", __func__, endpoint);
98258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		return NULL;
98358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
98458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
98558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		/* Fill URB using supplied data. */
98658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	usb_fill_bulk_urb(urb, serial->dev,
98758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		      usb_sndbulkpipe(serial->dev, endpoint) | dir,
98858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		      buf, len, callback, ctx);
98958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
99058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return urb;
99158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
99258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
99358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs/* Setup urbs */
9947bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_setup_urbs(struct usb_serial *serial)
99558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
99619e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	int i, j;
997ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial_port *port;
998ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
99958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1000441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
100158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
100214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs	for (i = 0; i < serial->num_ports; i++) {
100314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		port = serial->port[i];
100414f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		portdata = usb_get_serial_port_data(port);
100558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
100619e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		/* Do indat endpoints first */
100714f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		for (j = 0; j < N_IN_URB; ++j) {
100819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox			portdata->in_urbs[j] = option_setup_urb(serial,
100919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					port->bulk_in_endpointAddress,
101019e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					USB_DIR_IN, port,
101119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					portdata->in_buffer[j],
101219e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					IN_BUFLEN, option_indat_callback);
101314f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		}
101458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
101514f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		/* outdat endpoints */
101614f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		for (j = 0; j < N_OUT_URB; ++j) {
101719e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox			portdata->out_urbs[j] = option_setup_urb(serial,
101819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					port->bulk_out_endpointAddress,
101919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					USB_DIR_OUT, port,
102019e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					portdata->out_buffer[j],
102119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					OUT_BUFLEN, option_outdat_callback);
102214f76cc7ab75b1c9db036dcd6b247e0dcc8952beMatthias Urlichs		}
102358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
102458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
102558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
10265f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins
10275f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins/** send RTS/DTR state to the port.
10285f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins *
10295f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
10305f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins * CDC.
10315f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins*/
103295da310e66ee8090119596c70ca8432e57f9a97fAlan Coxstatic int option_send_setup(struct tty_struct *tty,
103395da310e66ee8090119596c70ca8432e57f9a97fAlan Cox						struct usb_serial_port *port)
103458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
103558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct usb_serial *serial = port->serial;
103658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	struct option_port_private *portdata;
10375f760040bcb4cc0498d4c662c4ea305290198ef3Chris Collins	int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
1038441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
103958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
104058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	portdata = usb_get_serial_port_data(port);
104158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
104295da310e66ee8090119596c70ca8432e57f9a97fAlan Cox	if (tty) {
104358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		int val = 0;
104458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (portdata->dtr_state)
104558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			val |= 0x01;
104658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (portdata->rts_state)
104758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			val |= 0x02;
104858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
10497bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton		return usb_control_msg(serial->dev,
105019e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox			usb_rcvctrlpipe(serial->dev, 0),
105119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox			0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
105258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
105358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	return 0;
105458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
105558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
10567bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic int option_startup(struct usb_serial *serial)
105758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
10582129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	int i, j, err;
1059ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial_port *port;
1060ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
10612129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	u8 *buffer;
106258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1063441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
106458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
106558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Now setup per port private data */
106658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < serial->num_ports; i++) {
106758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		port = serial->port[i];
106880b6ca48321974a6566a1c9048ba34f60420bca6Eric Sesterhenn		portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
106958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (!portdata) {
10707bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("%s: kmalloc for option_port_private (%d) failed!.",
1071441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison					__func__, i);
107219e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox			return 1;
107358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
107458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
10752129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		for (j = 0; j < N_IN_URB; j++) {
10762129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			buffer = (u8 *)__get_free_page(GFP_KERNEL);
10772129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			if (!buffer)
10782129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum				goto bail_out_error;
10792129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			portdata->in_buffer[j] = buffer;
10802129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		}
10812129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum
10822129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		for (j = 0; j < N_OUT_URB; j++) {
10832129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
10842129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			if (!buffer)
10852129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum				goto bail_out_error2;
10862129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			portdata->out_buffer[j] = buffer;
10872129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		}
10882129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum
108958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		usb_set_serial_port_data(port, portdata);
109058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
109119e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox		if (!port->interrupt_in_urb)
109258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			continue;
109358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
109458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		if (err)
10957bb75aeeeec7417a961920b3f63a83007475260fAndrew Morton			dbg("%s: submit irq_in urb failed %d",
1096441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison				__func__, err);
109758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
109858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	option_setup_urbs(serial);
109919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox	return 0;
11002129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum
11012129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukumbail_out_error2:
11022129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	for (j = 0; j < N_OUT_URB; j++)
11032129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		kfree(portdata->out_buffer[j]);
11042129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukumbail_out_error:
11052129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	for (j = 0; j < N_IN_URB; j++)
11062129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum		if (portdata->in_buffer[j])
11072129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum			free_page((unsigned long)portdata->in_buffer[j]);
11082129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	kfree(portdata);
11092129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum	return 1;
111058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
111158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
11127bb75aeeeec7417a961920b3f63a83007475260fAndrew Mortonstatic void option_shutdown(struct usb_serial *serial)
111358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs{
1114ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	int i, j;
1115ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct usb_serial_port *port;
1116ba460e48064edeb57e3398eb8972c58de33f11eaMatthias Urlichs	struct option_port_private *portdata;
111758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
1118441b62c1edb986827154768d89bbac0ba779984fHarvey Harrison	dbg("%s", __func__);
111958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
112058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Stop reading/writing urbs */
112158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < serial->num_ports; ++i) {
112258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		port = serial->port[i];
112358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata = usb_get_serial_port_data(port);
112458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (j = 0; j < N_IN_URB; j++)
11257d28e74b97c8eb859fd9f5eb018bb1c75627bd55Oliver Neukum			usb_kill_urb(portdata->in_urbs[j]);
112658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (j = 0; j < N_OUT_URB; j++)
11277d28e74b97c8eb859fd9f5eb018bb1c75627bd55Oliver Neukum			usb_kill_urb(portdata->out_urbs[j]);
112858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
112958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
113058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Now free them */
113158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < serial->num_ports; ++i) {
113258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		port = serial->port[i];
113358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		portdata = usb_get_serial_port_data(port);
113458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
113558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (j = 0; j < N_IN_URB; j++) {
113658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			if (portdata->in_urbs[j]) {
113758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				usb_free_urb(portdata->in_urbs[j]);
113819e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox				free_page((unsigned long)
113919e58fae0c8f197d80fcea338b94fb5740369bc1Alan Cox					portdata->in_buffer[j]);
114058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				portdata->in_urbs[j] = NULL;
114158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			}
114258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
114358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		for (j = 0; j < N_OUT_URB; j++) {
114458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			if (portdata->out_urbs[j]) {
114558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				usb_free_urb(portdata->out_urbs[j]);
11462129c4e1b4469e1f9711a54e97e8ddf8b26bb62dOliver Neukum				kfree(portdata->out_buffer[j]);
114758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs				portdata->out_urbs[j] = NULL;
114858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs			}
114958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		}
115058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
115158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
115258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	/* Now free per port private data */
115358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	for (i = 0; i < serial->num_ports; i++) {
115458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		port = serial->port[i];
115558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs		kfree(usb_get_serial_port_data(port));
115658cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs	}
115758cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs}
115858cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
115958cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_AUTHOR(DRIVER_AUTHOR);
116058cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_DESCRIPTION(DRIVER_DESC);
116158cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_VERSION(DRIVER_VERSION);
116258cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_LICENSE("GPL");
116358cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichs
116458cfe9113e485f7e04bd0eac4fc4251b330af501Matthias Urlichsmodule_param(debug, bool, S_IRUGO | S_IWUSR);
116558cfe9113e485f7e04bd0eac4fc4251b330af501Matthias UrlichsMODULE_PARM_DESC(debug, "Debug messages");
1166