aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/qcserial.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/serial/qcserial.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/usb/serial/qcserial.c')
-rw-r--r--drivers/usb/serial/qcserial.c64
1 files changed, 56 insertions, 8 deletions
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index cde67cacb2c3..54a9dab1f33b 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -111,13 +111,15 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
111 ifnum = intf->desc.bInterfaceNumber; 111 ifnum = intf->desc.bInterfaceNumber;
112 dbg("This Interface = %d", ifnum); 112 dbg("This Interface = %d", ifnum);
113 113
114 data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), 114 data = kzalloc(sizeof(struct usb_wwan_intf_private),
115 GFP_KERNEL); 115 GFP_KERNEL);
116 if (!data) 116 if (!data)
117 return -ENOMEM; 117 return -ENOMEM;
118 118
119 spin_lock_init(&data->susp_lock); 119 spin_lock_init(&data->susp_lock);
120 120
121 usb_enable_autosuspend(serial->dev);
122
121 switch (nintf) { 123 switch (nintf) {
122 case 1: 124 case 1:
123 /* QDL mode */ 125 /* QDL mode */
@@ -132,8 +134,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
132 usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { 134 usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
133 dbg("QDL port found"); 135 dbg("QDL port found");
134 136
135 if (serial->interface->num_altsetting == 1) 137 if (serial->interface->num_altsetting == 1) {
136 return 0; 138 retval = 0; /* Success */
139 break;
140 }
137 141
138 retval = usb_set_interface(serial->dev, ifnum, 1); 142 retval = usb_set_interface(serial->dev, ifnum, 1);
139 if (retval < 0) { 143 if (retval < 0) {
@@ -143,14 +147,29 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
143 retval = -ENODEV; 147 retval = -ENODEV;
144 kfree(data); 148 kfree(data);
145 } 149 }
146 return retval;
147 } 150 }
148 break; 151 break;
149 152
150 case 3: 153 case 3:
151 case 4: 154 case 4:
152 /* Composite mode */ 155 /* Composite mode */
153 if (ifnum == 2) { 156 /* ifnum == 0 is a broadband network adapter */
157 if (ifnum == 1) {
158 /*
159 * Diagnostics Monitor (serial line 9600 8N1)
160 * Qualcomm DM protocol
161 * use "libqcdm" (ModemManager) for communication
162 */
163 dbg("Diagnostics Monitor found");
164 retval = usb_set_interface(serial->dev, ifnum, 0);
165 if (retval < 0) {
166 dev_err(&serial->dev->dev,
167 "Could not set interface, error %d\n",
168 retval);
169 retval = -ENODEV;
170 kfree(data);
171 }
172 } else if (ifnum == 2) {
154 dbg("Modem port found"); 173 dbg("Modem port found");
155 retval = usb_set_interface(serial->dev, ifnum, 0); 174 retval = usb_set_interface(serial->dev, ifnum, 0);
156 if (retval < 0) { 175 if (retval < 0) {
@@ -160,7 +179,21 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
160 retval = -ENODEV; 179 retval = -ENODEV;
161 kfree(data); 180 kfree(data);
162 } 181 }
163 return retval; 182 } else if (ifnum==3) {
183 /*
184 * NMEA (serial line 9600 8N1)
185 * # echo "\$GPS_START" > /dev/ttyUSBx
186 * # echo "\$GPS_STOP" > /dev/ttyUSBx
187 */
188 dbg("NMEA GPS interface found");
189 retval = usb_set_interface(serial->dev, ifnum, 0);
190 if (retval < 0) {
191 dev_err(&serial->dev->dev,
192 "Could not set interface, error %d\n",
193 retval);
194 retval = -ENODEV;
195 kfree(data);
196 }
164 } 197 }
165 break; 198 break;
166 199
@@ -168,12 +201,27 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
168 dev_err(&serial->dev->dev, 201 dev_err(&serial->dev->dev,
169 "unknown number of interfaces: %d\n", nintf); 202 "unknown number of interfaces: %d\n", nintf);
170 kfree(data); 203 kfree(data);
171 return -ENODEV; 204 retval = -ENODEV;
172 } 205 }
173 206
207 /* Set serial->private if not returning -ENODEV */
208 if (retval != -ENODEV)
209 usb_set_serial_data(serial, data);
174 return retval; 210 return retval;
175} 211}
176 212
213static void qc_release(struct usb_serial *serial)
214{
215 struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
216
217 dbg("%s", __func__);
218
219 /* Call usb_wwan release & free the private data allocated in qcprobe */
220 usb_wwan_release(serial);
221 usb_set_serial_data(serial, NULL);
222 kfree(priv);
223}
224
177static struct usb_serial_driver qcdevice = { 225static struct usb_serial_driver qcdevice = {
178 .driver = { 226 .driver = {
179 .owner = THIS_MODULE, 227 .owner = THIS_MODULE,
@@ -191,7 +239,7 @@ static struct usb_serial_driver qcdevice = {
191 .chars_in_buffer = usb_wwan_chars_in_buffer, 239 .chars_in_buffer = usb_wwan_chars_in_buffer,
192 .attach = usb_wwan_startup, 240 .attach = usb_wwan_startup,
193 .disconnect = usb_wwan_disconnect, 241 .disconnect = usb_wwan_disconnect,
194 .release = usb_wwan_release, 242 .release = qc_release,
195#ifdef CONFIG_PM 243#ifdef CONFIG_PM
196 .suspend = usb_wwan_suspend, 244 .suspend = usb_wwan_suspend,
197 .resume = usb_wwan_resume, 245 .resume = usb_wwan_resume,