diff options
Diffstat (limited to 'drivers/usb/serial/sierra.c')
-rw-r--r-- | drivers/usb/serial/sierra.c | 170 |
1 files changed, 79 insertions, 91 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 2f6f1523ec56..706033753adb 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -14,7 +14,7 @@ | |||
14 | Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> | 14 | Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define DRIVER_VERSION "v.1.2.9c" | 17 | #define DRIVER_VERSION "v.1.2.13a" |
18 | #define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>" | 18 | #define DRIVER_AUTHOR "Kevin Lloyd <klloyd@sierrawireless.com>" |
19 | #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" | 19 | #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" |
20 | 20 | ||
@@ -31,6 +31,7 @@ | |||
31 | #define SWIMS_USB_REQUEST_SetPower 0x00 | 31 | #define SWIMS_USB_REQUEST_SetPower 0x00 |
32 | #define SWIMS_USB_REQUEST_SetNmea 0x07 | 32 | #define SWIMS_USB_REQUEST_SetNmea 0x07 |
33 | #define SWIMS_USB_REQUEST_SetMode 0x0B | 33 | #define SWIMS_USB_REQUEST_SetMode 0x0B |
34 | #define SWIMS_USB_REQUEST_GetSwocInfo 0x0A | ||
34 | #define SWIMS_SET_MODE_Modem 0x0001 | 35 | #define SWIMS_SET_MODE_Modem 0x0001 |
35 | 36 | ||
36 | /* per port private data */ | 37 | /* per port private data */ |
@@ -40,18 +41,11 @@ | |||
40 | 41 | ||
41 | static int debug; | 42 | static int debug; |
42 | static int nmea; | 43 | static int nmea; |
43 | static int truinstall = 1; | ||
44 | |||
45 | enum devicetype { | ||
46 | DEVICE_3_PORT = 0, | ||
47 | DEVICE_1_PORT = 1, | ||
48 | DEVICE_INSTALLER = 2, | ||
49 | }; | ||
50 | 44 | ||
51 | static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) | 45 | static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) |
52 | { | 46 | { |
53 | int result; | 47 | int result; |
54 | dev_dbg(&udev->dev, "%s", "SET POWER STATE\n"); | 48 | dev_dbg(&udev->dev, "%s", __func__); |
55 | result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 49 | result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
56 | SWIMS_USB_REQUEST_SetPower, /* __u8 request */ | 50 | SWIMS_USB_REQUEST_SetPower, /* __u8 request */ |
57 | USB_TYPE_VENDOR, /* __u8 request type */ | 51 | USB_TYPE_VENDOR, /* __u8 request type */ |
@@ -63,25 +57,10 @@ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) | |||
63 | return result; | 57 | return result; |
64 | } | 58 | } |
65 | 59 | ||
66 | static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode) | ||
67 | { | ||
68 | int result; | ||
69 | dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH\n"); | ||
70 | result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
71 | SWIMS_USB_REQUEST_SetMode, /* __u8 request */ | ||
72 | USB_TYPE_VENDOR, /* __u8 request type */ | ||
73 | eSWocMode, /* __u16 value */ | ||
74 | 0x0000, /* __u16 index */ | ||
75 | NULL, /* void *data */ | ||
76 | 0, /* __u16 size */ | ||
77 | USB_CTRL_SET_TIMEOUT); /* int timeout */ | ||
78 | return result; | ||
79 | } | ||
80 | |||
81 | static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) | 60 | static int sierra_vsc_set_nmea(struct usb_device *udev, __u16 enable) |
82 | { | 61 | { |
83 | int result; | 62 | int result; |
84 | dev_dbg(&udev->dev, "%s", "NMEA Enable sent\n"); | 63 | dev_dbg(&udev->dev, "%s", __func__); |
85 | result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 64 | result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
86 | SWIMS_USB_REQUEST_SetNmea, /* __u8 request */ | 65 | SWIMS_USB_REQUEST_SetNmea, /* __u8 request */ |
87 | USB_TYPE_VENDOR, /* __u8 request type */ | 66 | USB_TYPE_VENDOR, /* __u8 request type */ |
@@ -97,6 +76,7 @@ static int sierra_calc_num_ports(struct usb_serial *serial) | |||
97 | { | 76 | { |
98 | int result; | 77 | int result; |
99 | int *num_ports = usb_get_serial_data(serial); | 78 | int *num_ports = usb_get_serial_data(serial); |
79 | dev_dbg(&serial->dev->dev, "%s", __func__); | ||
100 | 80 | ||
101 | result = *num_ports; | 81 | result = *num_ports; |
102 | 82 | ||
@@ -110,22 +90,23 @@ static int sierra_calc_num_ports(struct usb_serial *serial) | |||
110 | 90 | ||
111 | static int sierra_calc_interface(struct usb_serial *serial) | 91 | static int sierra_calc_interface(struct usb_serial *serial) |
112 | { | 92 | { |
113 | int interface; | 93 | int interface; |
114 | struct usb_interface *p_interface; | 94 | struct usb_interface *p_interface; |
115 | struct usb_host_interface *p_host_interface; | 95 | struct usb_host_interface *p_host_interface; |
96 | dev_dbg(&serial->dev->dev, "%s", __func__); | ||
116 | 97 | ||
117 | /* Get the interface structure pointer from the serial struct */ | 98 | /* Get the interface structure pointer from the serial struct */ |
118 | p_interface = serial->interface; | 99 | p_interface = serial->interface; |
119 | 100 | ||
120 | /* Get a pointer to the host interface structure */ | 101 | /* Get a pointer to the host interface structure */ |
121 | p_host_interface = p_interface->cur_altsetting; | 102 | p_host_interface = p_interface->cur_altsetting; |
122 | 103 | ||
123 | /* read the interface descriptor for this active altsetting | 104 | /* read the interface descriptor for this active altsetting |
124 | * to find out the interface number we are on | 105 | * to find out the interface number we are on |
125 | */ | 106 | */ |
126 | interface = p_host_interface->desc.bInterfaceNumber; | 107 | interface = p_host_interface->desc.bInterfaceNumber; |
127 | 108 | ||
128 | return interface; | 109 | return interface; |
129 | } | 110 | } |
130 | 111 | ||
131 | static int sierra_probe(struct usb_serial *serial, | 112 | static int sierra_probe(struct usb_serial *serial, |
@@ -135,43 +116,40 @@ static int sierra_probe(struct usb_serial *serial, | |||
135 | struct usb_device *udev; | 116 | struct usb_device *udev; |
136 | int *num_ports; | 117 | int *num_ports; |
137 | u8 ifnum; | 118 | u8 ifnum; |
119 | u8 numendpoints; | ||
120 | |||
121 | dev_dbg(&serial->dev->dev, "%s", __func__); | ||
138 | 122 | ||
139 | num_ports = kmalloc(sizeof(*num_ports), GFP_KERNEL); | 123 | num_ports = kmalloc(sizeof(*num_ports), GFP_KERNEL); |
140 | if (!num_ports) | 124 | if (!num_ports) |
141 | return -ENOMEM; | 125 | return -ENOMEM; |
142 | 126 | ||
143 | ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; | 127 | ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; |
128 | numendpoints = serial->interface->cur_altsetting->desc.bNumEndpoints; | ||
144 | udev = serial->dev; | 129 | udev = serial->dev; |
145 | 130 | ||
146 | /* Figure out the interface number from the serial structure */ | 131 | /* Figure out the interface number from the serial structure */ |
147 | ifnum = sierra_calc_interface(serial); | 132 | ifnum = sierra_calc_interface(serial); |
148 | |||
149 | /* | ||
150 | * If this interface supports more than 1 alternate | ||
151 | * select the 2nd one | ||
152 | */ | ||
153 | if (serial->interface->num_altsetting == 2) { | ||
154 | dev_dbg(&udev->dev, | ||
155 | "Selecting alt setting for interface %d\n", | ||
156 | ifnum); | ||
157 | 133 | ||
158 | /* We know the alternate setting is 1 for the MC8785 */ | 134 | /* |
159 | usb_set_interface(udev, ifnum, 1); | 135 | * If this interface supports more than 1 alternate |
160 | } | 136 | * select the 2nd one |
137 | */ | ||
138 | if (serial->interface->num_altsetting == 2) { | ||
139 | dev_dbg(&udev->dev, "Selecting alt setting for interface %d\n", | ||
140 | ifnum); | ||
141 | /* We know the alternate setting is 1 for the MC8785 */ | ||
142 | usb_set_interface(udev, ifnum, 1); | ||
143 | } | ||
161 | 144 | ||
162 | /* Check if in installer mode */ | 145 | /* Dummy interface present on some SKUs should be ignored */ |
163 | if (truinstall && id->driver_info == DEVICE_INSTALLER) { | 146 | if (ifnum == 0x99) |
164 | dev_dbg(&udev->dev, "%s", "FOUND TRU-INSTALL DEVICE(SW)\n"); | ||
165 | result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem); | ||
166 | /* Don't bind to the device when in installer mode */ | ||
167 | kfree(num_ports); | ||
168 | return -EIO; | ||
169 | } else if (id->driver_info == DEVICE_1_PORT) | ||
170 | *num_ports = 1; | ||
171 | else if (ifnum == 0x99) | ||
172 | *num_ports = 0; | 147 | *num_ports = 0; |
148 | else if (numendpoints <= 3) | ||
149 | *num_ports = 1; | ||
173 | else | 150 | else |
174 | *num_ports = 3; | 151 | *num_ports = (numendpoints-1)/2; |
152 | |||
175 | /* | 153 | /* |
176 | * save off our num_ports info so that we can use it in the | 154 | * save off our num_ports info so that we can use it in the |
177 | * calc_num_ports callback | 155 | * calc_num_ports callback |
@@ -187,40 +165,50 @@ static struct usb_device_id id_table [] = { | |||
187 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ | 165 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ |
188 | { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ | 166 | { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ |
189 | { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ | 167 | { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ |
168 | { USB_DEVICE(0x1199, 0x0024) }, /* Sierra Wireless MC5727 */ | ||
190 | { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ | 169 | { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ |
191 | { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ | 170 | { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ |
192 | { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ | 171 | { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ |
193 | { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ | 172 | { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ |
194 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, /* Sierra Wireless C597 */ | 173 | /* Sierra Wireless C597 */ |
174 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) }, | ||
175 | /* Sierra Wireless Device */ | ||
176 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0025, 0xFF, 0xFF, 0xFF) }, | ||
177 | { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless Device */ | ||
195 | 178 | ||
196 | { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ | 179 | { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ |
197 | { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ | 180 | { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ |
198 | { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ | 181 | { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ |
199 | { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ | 182 | { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ |
200 | { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */ | 183 | { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Lenovo) */ |
201 | { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */ | 184 | { USB_DEVICE(0x1199, 0x6815) }, /* Sierra Wireless MC8775 */ |
202 | { USB_DEVICE(0x03f0, 0x1e1d) }, /* HP hs2300 a.k.a MC8775 */ | 185 | { USB_DEVICE(0x03f0, 0x1e1d) }, /* HP hs2300 a.k.a MC8775 */ |
203 | { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ | 186 | { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ |
204 | { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */ | 187 | { USB_DEVICE(0x1199, 0x6821) }, /* Sierra Wireless AirCard 875U */ |
205 | { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/ | 188 | { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780 */ |
206 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/ | 189 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ |
207 | { USB_DEVICE(0x1199, 0x683B), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless MC8785 Composite*/ | 190 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ |
191 | { USB_DEVICE(0x1199, 0x683C) }, /* Sierra Wireless MC8790 */ | ||
192 | { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8790 */ | ||
193 | { USB_DEVICE(0x1199, 0x683E) }, /* Sierra Wireless MC8790 */ | ||
208 | { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ | 194 | { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ |
209 | { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ | 195 | { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ |
210 | { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */ | 196 | { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */ |
211 | { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */ | 197 | { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */ |
212 | { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */ | 198 | { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */ |
213 | { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */ | 199 | { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */ |
214 | { USB_DEVICE(0x1199, 0x6859), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 885 E */ | 200 | { USB_DEVICE(0x1199, 0x6859) }, /* Sierra Wireless AirCard 885 E */ |
215 | { USB_DEVICE(0x1199, 0x685A), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 885 E */ | 201 | { USB_DEVICE(0x1199, 0x685A) }, /* Sierra Wireless AirCard 885 E */ |
216 | 202 | /* Sierra Wireless C885 */ | |
217 | { USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */ | 203 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6880, 0xFF, 0xFF, 0xFF)}, |
218 | { USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */ | 204 | /* Sierra Wireless Device */ |
219 | 205 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6890, 0xFF, 0xFF, 0xFF)}, | |
220 | { USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */ | 206 | /* Sierra Wireless Device */ |
221 | { USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */ | 207 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)}, |
208 | |||
209 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ | ||
210 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ | ||
222 | 211 | ||
223 | { USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER}, | ||
224 | { } | 212 | { } |
225 | }; | 213 | }; |
226 | MODULE_DEVICE_TABLE(usb, id_table); | 214 | MODULE_DEVICE_TABLE(usb, id_table); |
@@ -268,13 +256,19 @@ static int sierra_send_setup(struct tty_struct *tty, | |||
268 | if (portdata->rts_state) | 256 | if (portdata->rts_state) |
269 | val |= 0x02; | 257 | val |= 0x02; |
270 | 258 | ||
271 | /* Determine which port is targeted */ | 259 | /* If composite device then properly report interface */ |
272 | if (port->bulk_out_endpointAddress == 2) | 260 | if (serial->num_ports == 1) |
273 | interface = 0; | 261 | interface = sierra_calc_interface(serial); |
274 | else if (port->bulk_out_endpointAddress == 4) | 262 | |
275 | interface = 1; | 263 | /* Otherwise the need to do non-composite mapping */ |
276 | else if (port->bulk_out_endpointAddress == 5) | 264 | else { |
277 | interface = 2; | 265 | if (port->bulk_out_endpointAddress == 2) |
266 | interface = 0; | ||
267 | else if (port->bulk_out_endpointAddress == 4) | ||
268 | interface = 1; | ||
269 | else if (port->bulk_out_endpointAddress == 5) | ||
270 | interface = 2; | ||
271 | } | ||
278 | 272 | ||
279 | return usb_control_msg(serial->dev, | 273 | return usb_control_msg(serial->dev, |
280 | usb_rcvctrlpipe(serial->dev, 0), | 274 | usb_rcvctrlpipe(serial->dev, 0), |
@@ -713,7 +707,7 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
713 | static struct usb_serial_driver sierra_device = { | 707 | static struct usb_serial_driver sierra_device = { |
714 | .driver = { | 708 | .driver = { |
715 | .owner = THIS_MODULE, | 709 | .owner = THIS_MODULE, |
716 | .name = "sierra1", | 710 | .name = "sierra", |
717 | }, | 711 | }, |
718 | .description = "Sierra USB modem", | 712 | .description = "Sierra USB modem", |
719 | .id_table = id_table, | 713 | .id_table = id_table, |
@@ -769,14 +763,8 @@ MODULE_DESCRIPTION(DRIVER_DESC); | |||
769 | MODULE_VERSION(DRIVER_VERSION); | 763 | MODULE_VERSION(DRIVER_VERSION); |
770 | MODULE_LICENSE("GPL"); | 764 | MODULE_LICENSE("GPL"); |
771 | 765 | ||
772 | module_param(truinstall, bool, 0); | 766 | module_param(nmea, bool, S_IRUGO | S_IWUSR); |
773 | MODULE_PARM_DESC(truinstall, "TRU-Install support"); | ||
774 | |||
775 | module_param(nmea, bool, 0); | ||
776 | MODULE_PARM_DESC(nmea, "NMEA streaming"); | 767 | MODULE_PARM_DESC(nmea, "NMEA streaming"); |
777 | 768 | ||
778 | #ifdef CONFIG_USB_DEBUG | ||
779 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 769 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
780 | MODULE_PARM_DESC(debug, "Debug messages"); | 770 | MODULE_PARM_DESC(debug, "Debug messages"); |
781 | #endif | ||
782 | |||