qcserial.c 16.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Qualcomm Serial USB driver
 *
 *	Copyright (c) 2008 QUALCOMM Incorporated.
 *	Copyright (c) 2009 Greg Kroah-Hartman <gregkh@suse.de>
 *	Copyright (c) 2009 Novell Inc.
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License version
 *	2 as published by the Free Software Foundation.
 *
 */

#include <linux/tty.h>
#include <linux/tty_flip.h>
16
#include <linux/module.h>
17 18
#include <linux/usb.h>
#include <linux/usb/serial.h>
19 20
#include <linux/slab.h>
#include "usb-wwan.h"
21 22 23 24

#define DRIVER_AUTHOR "Qualcomm Inc"
#define DRIVER_DESC "Qualcomm USB Serial driver"

25 26
#define QUECTEL_EC20_PID	0x9215

27 28 29 30
/* standard device layouts supported by this driver */
enum qcserial_layouts {
	QCSERIAL_G2K = 0,	/* Gobi 2000 */
	QCSERIAL_G1K = 1,	/* Gobi 1000 */
31
	QCSERIAL_SWI = 2,	/* Sierra Wireless */
32
	QCSERIAL_HWI = 3,	/* Huawei */
33 34
};

35
#define DEVICE_G1K(v, p) \
36
	USB_DEVICE(v, p), .driver_info = QCSERIAL_G1K
37 38
#define DEVICE_SWI(v, p) \
	USB_DEVICE(v, p), .driver_info = QCSERIAL_SWI
39 40
#define DEVICE_HWI(v, p) \
	USB_DEVICE(v, p), .driver_info = QCSERIAL_HWI
41

42
static const struct usb_device_id id_table[] = {
43 44 45 46 47 48 49 50 51
	/* Gobi 1000 devices */
	{DEVICE_G1K(0x05c6, 0x9211)},	/* Acer Gobi QDL device */
	{DEVICE_G1K(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
	{DEVICE_G1K(0x03f0, 0x1f1d)},	/* HP un2400 Gobi Modem Device */
	{DEVICE_G1K(0x03f0, 0x201d)},	/* HP un2400 Gobi QDL Device */
	{DEVICE_G1K(0x04da, 0x250d)},	/* Panasonic Gobi Modem device */
	{DEVICE_G1K(0x04da, 0x250c)},	/* Panasonic Gobi QDL device */
	{DEVICE_G1K(0x413c, 0x8172)},	/* Dell Gobi Modem device */
	{DEVICE_G1K(0x413c, 0x8171)},	/* Dell Gobi QDL device */
52 53 54 55 56 57 58
	{DEVICE_G1K(0x1410, 0xa001)},	/* Novatel/Verizon USB-1000 */
	{DEVICE_G1K(0x1410, 0xa002)},	/* Novatel Gobi Modem device */
	{DEVICE_G1K(0x1410, 0xa003)},	/* Novatel Gobi Modem device */
	{DEVICE_G1K(0x1410, 0xa004)},	/* Novatel Gobi Modem device */
	{DEVICE_G1K(0x1410, 0xa005)},	/* Novatel Gobi Modem device */
	{DEVICE_G1K(0x1410, 0xa006)},	/* Novatel Gobi Modem device */
	{DEVICE_G1K(0x1410, 0xa007)},	/* Novatel Gobi Modem device */
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
	{DEVICE_G1K(0x1410, 0xa008)},	/* Novatel Gobi QDL device */
	{DEVICE_G1K(0x0b05, 0x1776)},	/* Asus Gobi Modem device */
	{DEVICE_G1K(0x0b05, 0x1774)},	/* Asus Gobi QDL device */
	{DEVICE_G1K(0x19d2, 0xfff3)},	/* ONDA Gobi Modem device */
	{DEVICE_G1K(0x19d2, 0xfff2)},	/* ONDA Gobi QDL device */
	{DEVICE_G1K(0x1557, 0x0a80)},	/* OQO Gobi QDL device */
	{DEVICE_G1K(0x05c6, 0x9001)},   /* Generic Gobi Modem device */
	{DEVICE_G1K(0x05c6, 0x9002)},	/* Generic Gobi Modem device */
	{DEVICE_G1K(0x05c6, 0x9202)},	/* Generic Gobi Modem device */
	{DEVICE_G1K(0x05c6, 0x9203)},	/* Generic Gobi Modem device */
	{DEVICE_G1K(0x05c6, 0x9222)},	/* Generic Gobi Modem device */
	{DEVICE_G1K(0x05c6, 0x9008)},	/* Generic Gobi QDL device */
	{DEVICE_G1K(0x05c6, 0x9009)},	/* Generic Gobi Modem device */
	{DEVICE_G1K(0x05c6, 0x9201)},	/* Generic Gobi QDL device */
	{DEVICE_G1K(0x05c6, 0x9221)},	/* Generic Gobi QDL device */
	{DEVICE_G1K(0x05c6, 0x9231)},	/* Generic Gobi QDL device */
	{DEVICE_G1K(0x1f45, 0x0001)},	/* Unknown Gobi QDL device */
76
	{DEVICE_G1K(0x1bc7, 0x900e)},	/* Telit Gobi QDL device */
77 78 79 80 81 82 83

	/* Gobi 2000 devices */
	{USB_DEVICE(0x1410, 0xa010)},	/* Novatel Gobi 2000 QDL device */
	{USB_DEVICE(0x1410, 0xa011)},	/* Novatel Gobi 2000 QDL device */
	{USB_DEVICE(0x1410, 0xa012)},	/* Novatel Gobi 2000 QDL device */
	{USB_DEVICE(0x1410, 0xa013)},	/* Novatel Gobi 2000 QDL device */
	{USB_DEVICE(0x1410, 0xa014)},	/* Novatel Gobi 2000 QDL device */
84 85
	{USB_DEVICE(0x413c, 0x8185)},	/* Dell Gobi 2000 QDL device (N0218, VU936) */
	{USB_DEVICE(0x413c, 0x8186)},	/* Dell Gobi 2000 Modem device (N0218, VU936) */
86 87
	{USB_DEVICE(0x05c6, 0x9208)},	/* Generic Gobi 2000 QDL device */
	{USB_DEVICE(0x05c6, 0x920b)},	/* Generic Gobi 2000 Modem device */
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
	{USB_DEVICE(0x05c6, 0x9224)},	/* Sony Gobi 2000 QDL device (N0279, VU730) */
	{USB_DEVICE(0x05c6, 0x9225)},	/* Sony Gobi 2000 Modem device (N0279, VU730) */
	{USB_DEVICE(0x05c6, 0x9244)},	/* Samsung Gobi 2000 QDL device (VL176) */
	{USB_DEVICE(0x05c6, 0x9245)},	/* Samsung Gobi 2000 Modem device (VL176) */
	{USB_DEVICE(0x03f0, 0x241d)},	/* HP Gobi 2000 QDL device (VP412) */
	{USB_DEVICE(0x03f0, 0x251d)},	/* HP Gobi 2000 Modem device (VP412) */
	{USB_DEVICE(0x05c6, 0x9214)},	/* Acer Gobi 2000 QDL device (VP413) */
	{USB_DEVICE(0x05c6, 0x9215)},	/* Acer Gobi 2000 Modem device (VP413) */
	{USB_DEVICE(0x05c6, 0x9264)},	/* Asus Gobi 2000 QDL device (VR305) */
	{USB_DEVICE(0x05c6, 0x9265)},	/* Asus Gobi 2000 Modem device (VR305) */
	{USB_DEVICE(0x05c6, 0x9234)},	/* Top Global Gobi 2000 QDL device (VR306) */
	{USB_DEVICE(0x05c6, 0x9235)},	/* Top Global Gobi 2000 Modem device (VR306) */
	{USB_DEVICE(0x05c6, 0x9274)},	/* iRex Technologies Gobi 2000 QDL device (VR307) */
	{USB_DEVICE(0x05c6, 0x9275)},	/* iRex Technologies Gobi 2000 Modem device (VR307) */
	{USB_DEVICE(0x1199, 0x9000)},	/* Sierra Wireless Gobi 2000 QDL device (VT773) */
	{USB_DEVICE(0x1199, 0x9001)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x9002)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x9003)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x9004)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x9005)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x9006)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x9007)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x9008)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x9009)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
	{USB_DEVICE(0x1199, 0x900a)},	/* Sierra Wireless Gobi 2000 Modem device (VT773) */
113
	{USB_DEVICE(0x1199, 0x9011)},   /* Sierra Wireless Gobi 2000 Modem device (MC8305) */
114 115
	{USB_DEVICE(0x16d8, 0x8001)},	/* CMDTech Gobi 2000 QDL device (VU922) */
	{USB_DEVICE(0x16d8, 0x8002)},	/* CMDTech Gobi 2000 Modem device (VU922) */
116 117
	{USB_DEVICE(0x05c6, 0x9204)},	/* Gobi 2000 QDL device */
	{USB_DEVICE(0x05c6, 0x9205)},	/* Gobi 2000 Modem device */
118

119 120
	/* Gobi 3000 devices */
	{USB_DEVICE(0x03f0, 0x371d)},	/* HP un2430 Gobi 3000 QDL */
121 122 123 124 125 126
	{USB_DEVICE(0x05c6, 0x920c)},	/* Gobi 3000 QDL */
	{USB_DEVICE(0x05c6, 0x920d)},	/* Gobi 3000 Composite */
	{USB_DEVICE(0x1410, 0xa020)},   /* Novatel Gobi 3000 QDL */
	{USB_DEVICE(0x1410, 0xa021)},	/* Novatel Gobi 3000 Composite */
	{USB_DEVICE(0x413c, 0x8193)},	/* Dell Gobi 3000 QDL */
	{USB_DEVICE(0x413c, 0x8194)},	/* Dell Gobi 3000 Composite */
127
	{USB_DEVICE(0x413c, 0x81a6)},	/* Dell DW5570 QDL (MC8805) */
128 129 130 131
	{USB_DEVICE(0x1199, 0x68a4)},	/* Sierra Wireless QDL */
	{USB_DEVICE(0x1199, 0x68a5)},	/* Sierra Wireless Modem */
	{USB_DEVICE(0x1199, 0x68a8)},	/* Sierra Wireless QDL */
	{USB_DEVICE(0x1199, 0x68a9)},	/* Sierra Wireless Modem */
132 133
	{USB_DEVICE(0x1199, 0x9010)},	/* Sierra Wireless Gobi 3000 QDL */
	{USB_DEVICE(0x1199, 0x9012)},	/* Sierra Wireless Gobi 3000 QDL */
134
	{USB_DEVICE(0x1199, 0x9013)},	/* Sierra Wireless Gobi 3000 Modem device (MC8355) */
135 136 137 138
	{USB_DEVICE(0x1199, 0x9014)},	/* Sierra Wireless Gobi 3000 QDL */
	{USB_DEVICE(0x1199, 0x9015)},	/* Sierra Wireless Gobi 3000 Modem device */
	{USB_DEVICE(0x1199, 0x9018)},	/* Sierra Wireless Gobi 3000 QDL */
	{USB_DEVICE(0x1199, 0x9019)},	/* Sierra Wireless Gobi 3000 Modem device */
139
	{USB_DEVICE(0x1199, 0x901b)},	/* Sierra Wireless MC7770 */
140 141
	{USB_DEVICE(0x12D1, 0x14F0)},	/* Sony Gobi 3000 QDL */
	{USB_DEVICE(0x12D1, 0x14F1)},	/* Sony Gobi 3000 Composite */
142
	{USB_DEVICE(0x0AF0, 0x8120)},	/* Option GTM681W */
143

144
	/* non-Gobi Sierra Wireless devices */
145
	{DEVICE_SWI(0x03f0, 0x4e1d)},	/* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
146 147 148
	{DEVICE_SWI(0x0f3d, 0x68a2)},	/* Sierra Wireless MC7700 */
	{DEVICE_SWI(0x114f, 0x68a2)},	/* Sierra Wireless MC7750 */
	{DEVICE_SWI(0x1199, 0x68a2)},	/* Sierra Wireless MC7710 */
149
	{DEVICE_SWI(0x1199, 0x68c0)},	/* Sierra Wireless MC7304/MC7354 */
150 151
	{DEVICE_SWI(0x1199, 0x901c)},	/* Sierra Wireless EM7700 */
	{DEVICE_SWI(0x1199, 0x901f)},	/* Sierra Wireless EM7355 */
152
	{DEVICE_SWI(0x1199, 0x9040)},	/* Sierra Wireless Modem */
153
	{DEVICE_SWI(0x1199, 0x9041)},	/* Sierra Wireless MC7305/MC7355 */
154
	{DEVICE_SWI(0x1199, 0x9051)},	/* Netgear AirCard 340U */
155 156
	{DEVICE_SWI(0x1199, 0x9053)},	/* Sierra Wireless Modem */
	{DEVICE_SWI(0x1199, 0x9054)},	/* Sierra Wireless Modem */
157
	{DEVICE_SWI(0x1199, 0x9055)},	/* Netgear AirCard 341U */
158 159 160
	{DEVICE_SWI(0x1199, 0x9056)},	/* Sierra Wireless Modem */
	{DEVICE_SWI(0x1199, 0x9060)},	/* Sierra Wireless Modem */
	{DEVICE_SWI(0x1199, 0x9061)},	/* Sierra Wireless Modem */
161
	{DEVICE_SWI(0x1199, 0x9063)},	/* Sierra Wireless EM7305 */
162 163 164 165
	{DEVICE_SWI(0x1199, 0x9070)},	/* Sierra Wireless MC74xx */
	{DEVICE_SWI(0x1199, 0x9071)},	/* Sierra Wireless MC74xx */
	{DEVICE_SWI(0x1199, 0x9078)},	/* Sierra Wireless EM74xx */
	{DEVICE_SWI(0x1199, 0x9079)},	/* Sierra Wireless EM74xx */
166 167
	{DEVICE_SWI(0x1199, 0x907a)},	/* Sierra Wireless EM74xx QDL */
	{DEVICE_SWI(0x1199, 0x907b)},	/* Sierra Wireless EM74xx */
168 169 170 171 172
	{DEVICE_SWI(0x413c, 0x81a2)},	/* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
	{DEVICE_SWI(0x413c, 0x81a3)},	/* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
	{DEVICE_SWI(0x413c, 0x81a4)},	/* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
	{DEVICE_SWI(0x413c, 0x81a8)},	/* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
	{DEVICE_SWI(0x413c, 0x81a9)},	/* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
173
	{DEVICE_SWI(0x413c, 0x81b1)},	/* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
174
	{DEVICE_SWI(0x413c, 0x81b3)},	/* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
175 176
	{DEVICE_SWI(0x413c, 0x81b5)},	/* Dell Wireless 5811e QDL */
	{DEVICE_SWI(0x413c, 0x81b6)},	/* Dell Wireless 5811e QDL */
177 178 179 180
	{DEVICE_SWI(0x413c, 0x81cf)},   /* Dell Wireless 5819 */
	{DEVICE_SWI(0x413c, 0x81d0)},   /* Dell Wireless 5819 */
	{DEVICE_SWI(0x413c, 0x81d1)},   /* Dell Wireless 5818 */
	{DEVICE_SWI(0x413c, 0x81d2)},   /* Dell Wireless 5818 */
181

182 183 184
	/* Huawei devices */
	{DEVICE_HWI(0x03f0, 0x581d)},	/* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */

185 186 187 188
	{ }				/* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);

189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
static int handle_quectel_ec20(struct device *dev, int ifnum)
{
	int altsetting = 0;

	/*
	 * Quectel EC20 Mini PCIe LTE module layout:
	 * 0: DM/DIAG (use libqcdm from ModemManager for communication)
	 * 1: NMEA
	 * 2: AT-capable modem port
	 * 3: Modem interface
	 * 4: NDIS
	 */
	switch (ifnum) {
	case 0:
		dev_dbg(dev, "Quectel EC20 DM/DIAG interface found\n");
		break;
	case 1:
		dev_dbg(dev, "Quectel EC20 NMEA GPS interface found\n");
		break;
	case 2:
	case 3:
		dev_dbg(dev, "Quectel EC20 Modem port found\n");
		break;
	case 4:
		/* Don't claim the QMI/net interface */
		altsetting = -1;
		break;
	}

	return altsetting;
}

221 222
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
223
	struct usb_host_interface *intf = serial->interface->cur_altsetting;
224
	struct device *dev = &serial->dev->dev;
225 226 227
	int retval = -ENODEV;
	__u8 nintf;
	__u8 ifnum;
228
	int altsetting = -1;
229
	bool sendsetup = false;
230

231 232 233 234
	/* we only support vendor specific functions */
	if (intf->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
		goto done;

235
	nintf = serial->dev->actconfig->desc.bNumInterfaces;
236
	dev_dbg(dev, "Num Interfaces = %d\n", nintf);
237
	ifnum = intf->desc.bInterfaceNumber;
238
	dev_dbg(dev, "This Interface = %d\n", ifnum);
239

240
	if (nintf == 1) {
241
		/* QDL mode */
242 243
		/* Gobi 2000 has a single altsetting, older ones have two */
		if (serial->interface->num_altsetting == 2)
244
			intf = &serial->interface->altsetting[1];
245
		else if (serial->interface->num_altsetting > 2)
246
			goto done;
247 248 249 250

		if (intf->desc.bNumEndpoints == 2 &&
		    usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) &&
		    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
251
			dev_dbg(dev, "QDL port found\n");
252

253
			if (serial->interface->num_altsetting == 1)
254
				retval = 0; /* Success */
255 256
			else
				altsetting = 1;
257
		}
258
		goto done;
259

260 261 262 263
	}

	/* default to enabling interface */
	altsetting = 0;
264

265 266
	/*
	 * Composite mode; don't bind to the QMI/net interface as that
267 268 269
	 * gets handled by other drivers.
	 */

270 271
	switch (id->driver_info) {
	case QCSERIAL_G1K:
272 273
		/*
		 * Gobi 1K USB layout:
274
		 * 0: DM/DIAG (use libqcdm from ModemManager for communication)
275 276 277
		 * 1: serial port (doesn't respond)
		 * 2: AT-capable modem port
		 * 3: QMI/net
278
		 */
279 280 281 282 283 284
		if (nintf < 3 || nintf > 4) {
			dev_err(dev, "unknown number of interfaces: %d\n", nintf);
			altsetting = -1;
			goto done;
		}

285 286 287 288
		if (ifnum == 0) {
			dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n");
			altsetting = 1;
		} else if (ifnum == 2)
289 290 291
			dev_dbg(dev, "Modem port found\n");
		else
			altsetting = -1;
292 293
		break;
	case QCSERIAL_G2K:
294 295 296 297 298 299
		/* handle non-standard layouts */
		if (nintf == 5 && id->idProduct == QUECTEL_EC20_PID) {
			altsetting = handle_quectel_ec20(dev, ifnum);
			goto done;
		}

300 301
		/*
		 * Gobi 2K+ USB layout:
302 303 304 305 306
		 * 0: QMI/net
		 * 1: DM/DIAG (use libqcdm from ModemManager for communication)
		 * 2: AT-capable modem port
		 * 3: NMEA
		 */
307 308 309 310 311 312
		if (nintf < 3 || nintf > 4) {
			dev_err(dev, "unknown number of interfaces: %d\n", nintf);
			altsetting = -1;
			goto done;
		}

313 314 315
		switch (ifnum) {
		case 0:
			/* Don't claim the QMI/net interface */
316
			altsetting = -1;
317 318
			break;
		case 1:
319
			dev_dbg(dev, "Gobi 2K+ DM/DIAG interface found\n");
320 321 322 323 324
			break;
		case 2:
			dev_dbg(dev, "Modem port found\n");
			break;
		case 3:
325 326 327 328 329
			/*
			 * NMEA (serial line 9600 8N1)
			 * # echo "\$GPS_START" > /dev/ttyUSBx
			 * # echo "\$GPS_STOP"  > /dev/ttyUSBx
			 */
330
			dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n");
331 332
			break;
		}
333
		break;
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
	case QCSERIAL_SWI:
		/*
		 * Sierra Wireless layout:
		 * 0: DM/DIAG (use libqcdm from ModemManager for communication)
		 * 2: NMEA
		 * 3: AT-capable modem port
		 * 8: QMI/net
		 */
		switch (ifnum) {
		case 0:
			dev_dbg(dev, "DM/DIAG interface found\n");
			break;
		case 2:
			dev_dbg(dev, "NMEA GPS interface found\n");
			break;
		case 3:
			dev_dbg(dev, "Modem port found\n");
351
			sendsetup = true;
352 353 354 355 356 357 358
			break;
		default:
			/* don't claim any unsupported interface */
			altsetting = -1;
			break;
		}
		break;
359 360
	case QCSERIAL_HWI:
		/*
361 362 363 364 365 366 367 368
		 * Huawei devices map functions by subclass + protocol
		 * instead of interface numbers. The protocol identify
		 * a specific function, while the subclass indicate a
		 * specific firmware source
		 *
		 * This is a blacklist of functions known to be
		 * non-serial.  The rest are assumed to be serial and
		 * will be handled by this driver
369
		 */
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
		switch (intf->desc.bInterfaceProtocol) {
			/* QMI combined (qmi_wwan) */
		case 0x07:
		case 0x37:
		case 0x67:
			/* QMI data (qmi_wwan) */
		case 0x08:
		case 0x38:
		case 0x68:
			/* QMI control (qmi_wwan) */
		case 0x09:
		case 0x39:
		case 0x69:
			/* NCM like (huawei_cdc_ncm) */
		case 0x16:
		case 0x46:
		case 0x76:
387 388
			altsetting = -1;
			break;
389 390 391 392 393
		default:
			dev_dbg(dev, "Huawei type serial port found (%02x/%02x/%02x)\n",
				intf->desc.bInterfaceClass,
				intf->desc.bInterfaceSubClass,
				intf->desc.bInterfaceProtocol);
394 395
		}
		break;
396 397 398 399
	default:
		dev_err(dev, "unsupported device layout type: %lu\n",
			id->driver_info);
		break;
400 401
	}

402
done:
403 404 405 406 407 408 409 410 411 412
	if (altsetting >= 0) {
		retval = usb_set_interface(serial->dev, ifnum, altsetting);
		if (retval < 0) {
			dev_err(dev,
				"Could not set interface, error %d\n",
				retval);
			retval = -ENODEV;
		}
	}

413 414 415
	if (!retval)
		usb_set_serial_data(serial, (void *)(unsigned long)sendsetup);

416 417 418
	return retval;
}

419 420 421
static int qc_attach(struct usb_serial *serial)
{
	struct usb_wwan_intf_private *data;
422
	bool sendsetup;
423 424 425 426 427

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

428 429 430 431
	sendsetup = !!(unsigned long)(usb_get_serial_data(serial));
	if (sendsetup)
		data->use_send_setup = 1;

432 433 434 435 436 437 438
	spin_lock_init(&data->susp_lock);

	usb_set_serial_data(serial, data);

	return 0;
}

439 440 441 442 443 444 445 446
static void qc_release(struct usb_serial *serial)
{
	struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);

	usb_set_serial_data(serial, NULL);
	kfree(priv);
}

447 448 449 450 451 452 453 454 455
static struct usb_serial_driver qcdevice = {
	.driver = {
		.owner     = THIS_MODULE,
		.name      = "qcserial",
	},
	.description         = "Qualcomm USB modem",
	.id_table            = id_table,
	.num_ports           = 1,
	.probe               = qcprobe,
456 457
	.open		     = usb_wwan_open,
	.close		     = usb_wwan_close,
458
	.dtr_rts	     = usb_wwan_dtr_rts,
459 460 461
	.write		     = usb_wwan_write,
	.write_room	     = usb_wwan_write_room,
	.chars_in_buffer     = usb_wwan_chars_in_buffer,
462 463
	.tiocmget            = usb_wwan_tiocmget,
	.tiocmset            = usb_wwan_tiocmset,
464
	.attach              = qc_attach,
465
	.release	     = qc_release,
466
	.port_probe          = usb_wwan_port_probe,
467
	.port_remove	     = usb_wwan_port_remove,
468 469 470 471
#ifdef CONFIG_PM
	.suspend	     = usb_wwan_suspend,
	.resume		     = usb_wwan_resume,
#endif
472 473
};

474 475 476 477
static struct usb_serial_driver * const serial_drivers[] = {
	&qcdevice, NULL
};

478
module_usb_serial_driver(serial_drivers, id_table);
479 480 481 482

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL v2");