diff options
author | Kevin Lloyd <linux@sierrawireless.com> | 2007-07-16 16:49:27 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-19 20:46:03 -0400 |
commit | 112225b13cedd53dfd6455038b8843cf004ddec9 (patch) | |
tree | b700aba6f57c5d7805314039a49b89801dd2e166 /drivers/usb/serial | |
parent | eb33caec1ed29fa2b04a2c5f02e3fed2add91db4 (diff) |
USB: sierra: Add TRU-Install (c) Support
This patch adds compatibility with Sierra Wireless' new TRU-Install
feature. Future devices that use this feature will not work unless this
patch has been applied.
Signed-off-by: Kevin Lloyd <linux@sierrawireless.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/sierra.c | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index e7db20343d1a..c137c8962b9f 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | USB Driver for Sierra Wireless | 2 | USB Driver for Sierra Wireless |
3 | 3 | ||
4 | Copyright (C) 2006 Kevin Lloyd <linux@sierrawireless.com> | 4 | Copyright (C) 2006, 2007 Kevin Lloyd <linux@sierrawireless.com> |
5 | 5 | ||
6 | IMPORTANT DISCLAIMER: This driver is not commercially supported by | 6 | IMPORTANT DISCLAIMER: This driver is not commercially supported by |
7 | Sierra Wireless. Use at your own risk. | 7 | Sierra Wireless. Use at your own risk. |
@@ -12,10 +12,9 @@ | |||
12 | 12 | ||
13 | Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de> | 13 | Portions based on the option driver by Matthias Urlichs <smurf@smurf.noris.de> |
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 | |||
16 | */ | 15 | */ |
17 | 16 | ||
18 | #define DRIVER_VERSION "v.1.0.6" | 17 | #define DRIVER_VERSION "v.1.2.4b" |
19 | #define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>" | 18 | #define DRIVER_AUTHOR "Kevin Lloyd <linux@sierrawireless.com>" |
20 | #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" | 19 | #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" |
21 | 20 | ||
@@ -28,6 +27,71 @@ | |||
28 | #include <linux/usb.h> | 27 | #include <linux/usb.h> |
29 | #include <linux/usb/serial.h> | 28 | #include <linux/usb/serial.h> |
30 | 29 | ||
30 | #define SWIMS_USB_REQUEST_SetMode 0x0B | ||
31 | #define SWIMS_USB_REQUEST_TYPE_SetMode 0x40 | ||
32 | #define SWIMS_USB_INDEX_SetMode 0x0000 | ||
33 | #define SWIMS_SET_MODE_Modem 0x0001 | ||
34 | |||
35 | /* per port private data */ | ||
36 | #define N_IN_URB 4 | ||
37 | #define N_OUT_URB 4 | ||
38 | #define IN_BUFLEN 4096 | ||
39 | |||
40 | static int debug; | ||
41 | |||
42 | enum devicetype { | ||
43 | DEVICE_3_PORT = 0, | ||
44 | DEVICE_1_PORT = 1, | ||
45 | DEVICE_INSTALLER = 2, | ||
46 | }; | ||
47 | |||
48 | int sierra_set_power_state(struct usb_device *udev, __u16 swiState) | ||
49 | { | ||
50 | int result; | ||
51 | dev_dbg(&udev->dev, "%s", "SET POWER STATE"); | ||
52 | result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
53 | 0x00, /* __u8 request */ | ||
54 | 0x40, /* __u8 request type */ | ||
55 | swiState, /* __u16 value */ | ||
56 | 0, /* __u16 index */ | ||
57 | NULL, /* void *data */ | ||
58 | 0, /* __u16 size */ | ||
59 | USB_CTRL_SET_TIMEOUT); /* int timeout */ | ||
60 | return result; | ||
61 | } | ||
62 | |||
63 | int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode) | ||
64 | { | ||
65 | int result; | ||
66 | dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH"); | ||
67 | result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
68 | SWIMS_USB_REQUEST_SetMode, /* __u8 request */ | ||
69 | SWIMS_USB_REQUEST_TYPE_SetMode, /* __u8 request type */ | ||
70 | eSocMode, /* __u16 value */ | ||
71 | SWIMS_USB_INDEX_SetMode, /* __u16 index */ | ||
72 | NULL, /* void *data */ | ||
73 | 0, /* __u16 size */ | ||
74 | USB_CTRL_SET_TIMEOUT); /* int timeout */ | ||
75 | return result; | ||
76 | } | ||
77 | |||
78 | int sierra_probe(struct usb_interface *iface, const struct usb_device_id *id) | ||
79 | { | ||
80 | int result; | ||
81 | struct usb_device *udev; | ||
82 | |||
83 | udev = usb_get_dev(interface_to_usbdev(iface)); | ||
84 | |||
85 | /* Check if in installer mode */ | ||
86 | if (id->driver_info == DEVICE_INSTALLER) { | ||
87 | dev_dbg(&udev->dev, "%s", "FOUND DEVICE(SW)\n"); | ||
88 | result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem); | ||
89 | /*We do not want to bind to the device when in installer mode*/ | ||
90 | return -EIO; | ||
91 | } | ||
92 | |||
93 | return usb_serial_probe(iface, id); | ||
94 | } | ||
31 | 95 | ||
32 | static struct usb_device_id id_table [] = { | 96 | static struct usb_device_id id_table [] = { |
33 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ | 97 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ |
@@ -43,8 +107,10 @@ static struct usb_device_id id_table [] = { | |||
43 | { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ | 107 | { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ |
44 | { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ | 108 | { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ |
45 | 109 | ||
46 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ | 110 | { USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */ |
47 | { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */ | 111 | { USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */ |
112 | |||
113 | { USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER}, | ||
48 | { } | 114 | { } |
49 | }; | 115 | }; |
50 | MODULE_DEVICE_TABLE(usb, id_table); | 116 | MODULE_DEVICE_TABLE(usb, id_table); |
@@ -56,6 +122,7 @@ static struct usb_device_id id_table_1port [] = { | |||
56 | }; | 122 | }; |
57 | 123 | ||
58 | static struct usb_device_id id_table_3port [] = { | 124 | static struct usb_device_id id_table_3port [] = { |
125 | /* CDMA Devices */ | ||
59 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ | 126 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ |
60 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ | 127 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ |
61 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ | 128 | { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ |
@@ -63,6 +130,8 @@ static struct usb_device_id id_table_3port [] = { | |||
63 | { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ | 130 | { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ |
64 | { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */ | 131 | { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless AirCard 595U */ |
65 | { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ | 132 | { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ |
133 | |||
134 | /* GSM/UMTS Devices */ | ||
66 | { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ | 135 | { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ |
67 | { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ | 136 | { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ |
68 | { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ | 137 | { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ |
@@ -73,20 +142,13 @@ static struct usb_device_id id_table_3port [] = { | |||
73 | 142 | ||
74 | static struct usb_driver sierra_driver = { | 143 | static struct usb_driver sierra_driver = { |
75 | .name = "sierra", | 144 | .name = "sierra", |
76 | .probe = usb_serial_probe, | 145 | .probe = sierra_probe, |
77 | .disconnect = usb_serial_disconnect, | 146 | .disconnect = usb_serial_disconnect, |
78 | .id_table = id_table, | 147 | .id_table = id_table, |
79 | .no_dynamic_id = 1, | 148 | .no_dynamic_id = 1, |
80 | }; | 149 | }; |
81 | 150 | ||
82 | 151 | ||
83 | static int debug; | ||
84 | |||
85 | /* per port private data */ | ||
86 | #define N_IN_URB 4 | ||
87 | #define N_OUT_URB 4 | ||
88 | #define IN_BUFLEN 4096 | ||
89 | |||
90 | struct sierra_port_private { | 152 | struct sierra_port_private { |
91 | spinlock_t lock; /* lock the structure */ | 153 | spinlock_t lock; /* lock the structure */ |
92 | int outstanding_urbs; /* number of out urbs in flight */ | 154 | int outstanding_urbs; /* number of out urbs in flight */ |
@@ -421,7 +483,6 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
421 | int i; | 483 | int i; |
422 | struct urb *urb; | 484 | struct urb *urb; |
423 | int result; | 485 | int result; |
424 | __u16 set_mode_dzero = 0x0000; | ||
425 | 486 | ||
426 | portdata = usb_get_serial_port_data(port); | 487 | portdata = usb_get_serial_port_data(port); |
427 | 488 | ||
@@ -457,12 +518,6 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
457 | 518 | ||
458 | port->tty->low_latency = 1; | 519 | port->tty->low_latency = 1; |
459 | 520 | ||
460 | /* set mode to D0 */ | ||
461 | result = usb_control_msg(serial->dev, | ||
462 | usb_rcvctrlpipe(serial->dev, 0), | ||
463 | 0x00, 0x40, set_mode_dzero, 0, NULL, | ||
464 | 0, USB_CTRL_SET_TIMEOUT); | ||
465 | |||
466 | sierra_send_setup(port); | 521 | sierra_send_setup(port); |
467 | 522 | ||
468 | /* start up the interrupt endpoint if we have one */ | 523 | /* start up the interrupt endpoint if we have one */ |
@@ -510,6 +565,9 @@ static int sierra_startup(struct usb_serial *serial) | |||
510 | 565 | ||
511 | dbg("%s", __FUNCTION__); | 566 | dbg("%s", __FUNCTION__); |
512 | 567 | ||
568 | /*Set Device mode to D0 */ | ||
569 | sierra_set_power_state(serial->dev, 0x0000); | ||
570 | |||
513 | /* Now setup per port private data */ | 571 | /* Now setup per port private data */ |
514 | for (i = 0; i < serial->num_ports; i++) { | 572 | for (i = 0; i < serial->num_ports; i++) { |
515 | port = serial->port[i]; | 573 | port = serial->port[i]; |