blob: d69e85057778976f20a6251e1abbb884919f7fb2 [file] [log] [blame]
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +02001/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Anna Perela8c991d2012-04-09 16:44:46 +03002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#define pr_fmt(fmt) "%s: " fmt, __func__
15
16#include <linux/kernel.h>
17#include <linux/device.h>
18
19#include <linux/usb/cdc.h>
20
21#include <linux/usb/composite.h>
Anna Perela8c991d2012-04-09 16:44:46 +030022#include <linux/platform_device.h>
23
24#include <linux/spinlock.h>
25
26/*
27 * This function is a "Mobile Broadband Interface Model" (MBIM) link.
28 * MBIM is intended to be used with high-speed network attachments.
29 *
30 * Note that MBIM requires the use of "alternate settings" for its data
31 * interface. This means that the set_alt() method has real work to do,
32 * and also means that a get_alt() method is required.
33 */
34
35#define MBIM_BULK_BUFFER_SIZE 4096
36
37#define MBIM_IOCTL_MAGIC 'o'
38#define MBIM_GET_NTB_SIZE _IOR(MBIM_IOCTL_MAGIC, 2, u32)
39#define MBIM_GET_DATAGRAM_COUNT _IOR(MBIM_IOCTL_MAGIC, 3, u16)
40
41#define NR_MBIM_PORTS 1
42
Jack Pham2df2f702012-10-11 19:08:24 -070043/* ID for Microsoft OS String */
44#define MBIM_OS_STRING_ID 0xEE
45
Anna Perela8c991d2012-04-09 16:44:46 +030046struct ctrl_pkt {
47 void *buf;
48 int len;
49 struct list_head list;
50};
51
52struct mbim_ep_descs {
53 struct usb_endpoint_descriptor *in;
54 struct usb_endpoint_descriptor *out;
55 struct usb_endpoint_descriptor *notify;
56};
57
58struct mbim_notify_port {
59 struct usb_ep *notify;
60 struct usb_request *notify_req;
61 u8 notify_state;
62 atomic_t notify_count;
63};
64
65enum mbim_notify_state {
66 NCM_NOTIFY_NONE,
67 NCM_NOTIFY_CONNECT,
68 NCM_NOTIFY_SPEED,
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +020069 NCM_NOTIFY_RESPONSE_AVAILABLE,
Anna Perela8c991d2012-04-09 16:44:46 +030070};
71
72struct f_mbim {
Anna Perel557bf722012-09-20 11:16:35 +030073 struct usb_function function;
74 struct usb_composite_dev *cdev;
Anna Perela8c991d2012-04-09 16:44:46 +030075
76 atomic_t online;
77 bool is_open;
78
79 atomic_t open_excl;
80 atomic_t ioctl_excl;
81 atomic_t read_excl;
82 atomic_t write_excl;
83
84 wait_queue_head_t read_wq;
85 wait_queue_head_t write_wq;
86
87 u8 port_num;
88 struct data_port bam_port;
89 struct mbim_notify_port not_port;
90
91 struct mbim_ep_descs fs;
92 struct mbim_ep_descs hs;
93
94 u8 ctrl_id, data_id;
Bar Weinerb1c95f52012-12-23 09:09:13 +020095 u8 data_alt_int;
Anna Perela8c991d2012-04-09 16:44:46 +030096
97 struct ndp_parser_opts *parser_opts;
98
99 spinlock_t lock;
100
101 struct list_head cpkt_req_q;
102 struct list_head cpkt_resp_q;
103
104 u32 ntb_input_size;
105 u16 ntb_max_datagrams;
106
Anna Perela8c991d2012-04-09 16:44:46 +0300107 atomic_t error;
108};
109
110struct mbim_ntb_input_size {
111 u32 ntb_input_size;
112 u16 ntb_max_datagrams;
113 u16 reserved;
114};
115
116/* temporary variable used between mbim_open() and mbim_gadget_bind() */
117static struct f_mbim *_mbim_dev;
118
119static unsigned int nr_mbim_ports;
120
121static struct mbim_ports {
122 struct f_mbim *port;
123 unsigned port_num;
124} mbim_ports[NR_MBIM_PORTS];
125
126static inline struct f_mbim *func_to_mbim(struct usb_function *f)
127{
128 return container_of(f, struct f_mbim, function);
129}
130
131/* peak (theoretical) bulk transfer rate in bits-per-second */
132static inline unsigned mbim_bitrate(struct usb_gadget *g)
133{
134 if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
135 return 13 * 512 * 8 * 1000 * 8;
136 else
137 return 19 * 64 * 1 * 1000 * 8;
138}
139
140/*-------------------------------------------------------------------------*/
141
142#define NTB_DEFAULT_IN_SIZE (0x4000)
143#define NTB_OUT_SIZE (0x1000)
144#define NDP_IN_DIVISOR (0x4)
145
146#define FORMATS_SUPPORTED USB_CDC_NCM_NTB16_SUPPORTED
147
148static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
149 .wLength = sizeof ntb_parameters,
150 .bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
151 .dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
152 .wNdpInDivisor = cpu_to_le16(NDP_IN_DIVISOR),
153 .wNdpInPayloadRemainder = cpu_to_le16(0),
154 .wNdpInAlignment = cpu_to_le16(4),
155
156 .dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE),
157 .wNdpOutDivisor = cpu_to_le16(4),
158 .wNdpOutPayloadRemainder = cpu_to_le16(0),
159 .wNdpOutAlignment = cpu_to_le16(4),
Anna Perelf99cd0c2012-05-03 13:30:26 +0300160 .wNtbOutMaxDatagrams = 0,
Anna Perela8c991d2012-04-09 16:44:46 +0300161};
162
163/*
164 * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
165 * packet, to simplify cancellation; and a big transfer interval, to
166 * waste less bandwidth.
167 */
168
169#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
170#define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
171
172static struct usb_interface_assoc_descriptor mbim_iad_desc = {
173 .bLength = sizeof mbim_iad_desc,
174 .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
175
176 /* .bFirstInterface = DYNAMIC, */
177 .bInterfaceCount = 2, /* control + data */
178 .bFunctionClass = 2,
179 .bFunctionSubClass = 0x0e,
180 .bFunctionProtocol = 0,
181 /* .iFunction = DYNAMIC */
182};
183
184/* interface descriptor: */
185static struct usb_interface_descriptor mbim_control_intf = {
186 .bLength = sizeof mbim_control_intf,
187 .bDescriptorType = USB_DT_INTERFACE,
188
189 /* .bInterfaceNumber = DYNAMIC */
190 .bNumEndpoints = 1,
191 .bInterfaceClass = 0x02,
192 .bInterfaceSubClass = 0x0e,
193 .bInterfaceProtocol = 0,
194 /* .iInterface = DYNAMIC */
195};
196
197static struct usb_cdc_header_desc mbim_header_desc = {
198 .bLength = sizeof mbim_header_desc,
199 .bDescriptorType = USB_DT_CS_INTERFACE,
200 .bDescriptorSubType = USB_CDC_HEADER_TYPE,
201
202 .bcdCDC = cpu_to_le16(0x0110),
203};
204
205static struct usb_cdc_union_desc mbim_union_desc = {
206 .bLength = sizeof(mbim_union_desc),
207 .bDescriptorType = USB_DT_CS_INTERFACE,
208 .bDescriptorSubType = USB_CDC_UNION_TYPE,
209 /* .bMasterInterface0 = DYNAMIC */
210 /* .bSlaveInterface0 = DYNAMIC */
211};
212
213static struct usb_cdc_mbb_desc mbb_desc = {
214 .bLength = sizeof mbb_desc,
215 .bDescriptorType = USB_DT_CS_INTERFACE,
216 .bDescriptorSubType = USB_CDC_MBB_TYPE,
217
218 .bcdMbbVersion = cpu_to_le16(0x0100),
219
220 .wMaxControlMessage = cpu_to_le16(0x1000),
Anna Perel3354bdc2012-12-09 12:08:10 +0200221 .bNumberFilters = 0x20,
Anna Perela8c991d2012-04-09 16:44:46 +0300222 .bMaxFilterSize = 0x80,
Anna Perel26ae27c2012-05-23 18:07:31 +0300223 .wMaxSegmentSize = cpu_to_le16(0xfe0),
Anna Perela8c991d2012-04-09 16:44:46 +0300224 .bmNetworkCapabilities = 0x20,
225};
226
Bar Weiner38c3e642013-02-12 10:25:17 +0200227static struct usb_cdc_ext_mbb_desc ext_mbb_desc = {
228 .bLength = sizeof ext_mbb_desc,
229 .bDescriptorType = USB_DT_CS_INTERFACE,
230 .bDescriptorSubType = USB_CDC_EXT_MBB_TYPE,
231
232 .bcdMbbExtendedVersion = cpu_to_le16(0x0100),
233 .bMaxOutstandingCmdMsges = 64,
234 .wMTU = 1500,
235};
236
Anna Perela8c991d2012-04-09 16:44:46 +0300237/* the default data interface has no endpoints ... */
238static struct usb_interface_descriptor mbim_data_nop_intf = {
239 .bLength = sizeof mbim_data_nop_intf,
240 .bDescriptorType = USB_DT_INTERFACE,
241
242 /* .bInterfaceNumber = DYNAMIC */
243 .bAlternateSetting = 0,
244 .bNumEndpoints = 0,
245 .bInterfaceClass = 0x0a,
246 .bInterfaceSubClass = 0,
247 .bInterfaceProtocol = 0x02,
248 /* .iInterface = DYNAMIC */
249};
250
251/* ... but the "real" data interface has two bulk endpoints */
252static struct usb_interface_descriptor mbim_data_intf = {
253 .bLength = sizeof mbim_data_intf,
254 .bDescriptorType = USB_DT_INTERFACE,
255
256 /* .bInterfaceNumber = DYNAMIC */
257 .bAlternateSetting = 1,
258 .bNumEndpoints = 2,
259 .bInterfaceClass = 0x0a,
260 .bInterfaceSubClass = 0,
261 .bInterfaceProtocol = 0x02,
262 /* .iInterface = DYNAMIC */
263};
264
265/* full speed support: */
266
267static struct usb_endpoint_descriptor fs_mbim_notify_desc = {
268 .bLength = USB_DT_ENDPOINT_SIZE,
269 .bDescriptorType = USB_DT_ENDPOINT,
270
271 .bEndpointAddress = USB_DIR_IN,
272 .bmAttributes = USB_ENDPOINT_XFER_INT,
273 .wMaxPacketSize = 4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
274 .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
275};
276
277static struct usb_endpoint_descriptor fs_mbim_in_desc = {
278 .bLength = USB_DT_ENDPOINT_SIZE,
279 .bDescriptorType = USB_DT_ENDPOINT,
280
281 .bEndpointAddress = USB_DIR_IN,
282 .bmAttributes = USB_ENDPOINT_XFER_BULK,
283};
284
285static struct usb_endpoint_descriptor fs_mbim_out_desc = {
286 .bLength = USB_DT_ENDPOINT_SIZE,
287 .bDescriptorType = USB_DT_ENDPOINT,
288
289 .bEndpointAddress = USB_DIR_OUT,
290 .bmAttributes = USB_ENDPOINT_XFER_BULK,
291};
292
293static struct usb_descriptor_header *mbim_fs_function[] = {
294 (struct usb_descriptor_header *) &mbim_iad_desc,
295 /* MBIM control descriptors */
296 (struct usb_descriptor_header *) &mbim_control_intf,
297 (struct usb_descriptor_header *) &mbim_header_desc,
298 (struct usb_descriptor_header *) &mbb_desc,
Bar Weiner38c3e642013-02-12 10:25:17 +0200299 (struct usb_descriptor_header *) &ext_mbb_desc,
Anna Perela8c991d2012-04-09 16:44:46 +0300300 (struct usb_descriptor_header *) &fs_mbim_notify_desc,
301 /* data interface, altsettings 0 and 1 */
302 (struct usb_descriptor_header *) &mbim_data_nop_intf,
303 (struct usb_descriptor_header *) &mbim_data_intf,
304 (struct usb_descriptor_header *) &fs_mbim_in_desc,
305 (struct usb_descriptor_header *) &fs_mbim_out_desc,
306 NULL,
307};
308
309/* high speed support: */
310
311static struct usb_endpoint_descriptor hs_mbim_notify_desc = {
312 .bLength = USB_DT_ENDPOINT_SIZE,
313 .bDescriptorType = USB_DT_ENDPOINT,
314
315 .bEndpointAddress = USB_DIR_IN,
316 .bmAttributes = USB_ENDPOINT_XFER_INT,
317 .wMaxPacketSize = 4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
318 .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
319};
320static struct usb_endpoint_descriptor hs_mbim_in_desc = {
321 .bLength = USB_DT_ENDPOINT_SIZE,
322 .bDescriptorType = USB_DT_ENDPOINT,
323
324 .bEndpointAddress = USB_DIR_IN,
325 .bmAttributes = USB_ENDPOINT_XFER_BULK,
326 .wMaxPacketSize = cpu_to_le16(512),
327};
328
329static struct usb_endpoint_descriptor hs_mbim_out_desc = {
330 .bLength = USB_DT_ENDPOINT_SIZE,
331 .bDescriptorType = USB_DT_ENDPOINT,
332
333 .bEndpointAddress = USB_DIR_OUT,
334 .bmAttributes = USB_ENDPOINT_XFER_BULK,
335 .wMaxPacketSize = cpu_to_le16(512),
336};
337
338static struct usb_descriptor_header *mbim_hs_function[] = {
339 (struct usb_descriptor_header *) &mbim_iad_desc,
340 /* MBIM control descriptors */
341 (struct usb_descriptor_header *) &mbim_control_intf,
342 (struct usb_descriptor_header *) &mbim_header_desc,
343 (struct usb_descriptor_header *) &mbb_desc,
Bar Weiner38c3e642013-02-12 10:25:17 +0200344 (struct usb_descriptor_header *) &ext_mbb_desc,
Anna Perela8c991d2012-04-09 16:44:46 +0300345 (struct usb_descriptor_header *) &hs_mbim_notify_desc,
346 /* data interface, altsettings 0 and 1 */
347 (struct usb_descriptor_header *) &mbim_data_nop_intf,
348 (struct usb_descriptor_header *) &mbim_data_intf,
349 (struct usb_descriptor_header *) &hs_mbim_in_desc,
350 (struct usb_descriptor_header *) &hs_mbim_out_desc,
351 NULL,
352};
353
354/* string descriptors: */
355
356#define STRING_CTRL_IDX 0
357#define STRING_DATA_IDX 1
358
359static struct usb_string mbim_string_defs[] = {
360 [STRING_CTRL_IDX].s = "MBIM Control",
361 [STRING_DATA_IDX].s = "MBIM Data",
362 { } /* end of list */
363};
364
365static struct usb_gadget_strings mbim_string_table = {
366 .language = 0x0409, /* en-us */
367 .strings = mbim_string_defs,
368};
369
370static struct usb_gadget_strings *mbim_strings[] = {
371 &mbim_string_table,
372 NULL,
373};
374
Jack Pham2df2f702012-10-11 19:08:24 -0700375/* Microsoft OS Descriptors */
376
377/*
378 * We specify our own bMS_VendorCode byte which Windows will use
379 * as the bRequest value in subsequent device get requests.
380 */
381#define MBIM_VENDOR_CODE 0xA5
382
383/* Microsoft OS String */
384static u8 mbim_os_string[] = {
385 18, /* sizeof(mtp_os_string) */
386 USB_DT_STRING,
387 /* Signature field: "MSFT100" */
388 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0,
389 /* vendor code */
390 MBIM_VENDOR_CODE,
391 /* padding */
392 0
393};
394
395/* Microsoft Extended Configuration Descriptor Header Section */
396struct mbim_ext_config_desc_header {
397 __le32 dwLength;
398 __u16 bcdVersion;
399 __le16 wIndex;
400 __u8 bCount;
401 __u8 reserved[7];
402};
403
404/* Microsoft Extended Configuration Descriptor Function Section */
405struct mbim_ext_config_desc_function {
406 __u8 bFirstInterfaceNumber;
407 __u8 bInterfaceCount;
408 __u8 compatibleID[8];
409 __u8 subCompatibleID[8];
410 __u8 reserved[6];
411};
412
413/* Microsoft Extended Configuration Descriptor */
414static struct {
415 struct mbim_ext_config_desc_header header;
416 struct mbim_ext_config_desc_function function;
417} mbim_ext_config_desc = {
418 .header = {
419 .dwLength = __constant_cpu_to_le32(sizeof mbim_ext_config_desc),
420 .bcdVersion = __constant_cpu_to_le16(0x0100),
421 .wIndex = __constant_cpu_to_le16(4),
422 .bCount = 1,
423 },
424 .function = {
425 .bFirstInterfaceNumber = 0,
426 .bInterfaceCount = 1,
427 .compatibleID = { 'A', 'L', 'T', 'R', 'C', 'F', 'G' },
428 /* .subCompatibleID = DYNAMIC */
429 },
430};
431
Anna Perela8c991d2012-04-09 16:44:46 +0300432/*
433 * Here are options for the Datagram Pointer table (NDP) parser.
434 * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
435 * in NDP16 offsets and sizes fields are 1 16bit word wide,
436 * in NDP32 -- 2 16bit words wide. Also signatures are different.
437 * To make the parser code the same, put the differences in the structure,
438 * and switch pointers to the structures when the format is changed.
439 */
440
441struct ndp_parser_opts {
442 u32 nth_sign;
443 u32 ndp_sign;
444 unsigned nth_size;
445 unsigned ndp_size;
446 unsigned ndplen_align;
447 /* sizes in u16 units */
448 unsigned dgram_item_len; /* index or length */
449 unsigned block_length;
450 unsigned fp_index;
451 unsigned reserved1;
452 unsigned reserved2;
453 unsigned next_fp_index;
454};
455
456#define INIT_NDP16_OPTS { \
457 .nth_sign = USB_CDC_NCM_NTH16_SIGN, \
458 .ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \
459 .nth_size = sizeof(struct usb_cdc_ncm_nth16), \
460 .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \
461 .ndplen_align = 4, \
462 .dgram_item_len = 1, \
463 .block_length = 1, \
464 .fp_index = 1, \
465 .reserved1 = 0, \
466 .reserved2 = 0, \
467 .next_fp_index = 1, \
468}
469
470#define INIT_NDP32_OPTS { \
471 .nth_sign = USB_CDC_NCM_NTH32_SIGN, \
472 .ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \
473 .nth_size = sizeof(struct usb_cdc_ncm_nth32), \
474 .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \
475 .ndplen_align = 8, \
476 .dgram_item_len = 2, \
477 .block_length = 2, \
478 .fp_index = 2, \
479 .reserved1 = 1, \
480 .reserved2 = 2, \
481 .next_fp_index = 2, \
482}
483
484static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
485static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
486
487static inline int mbim_lock(atomic_t *excl)
488{
489 if (atomic_inc_return(excl) == 1) {
490 return 0;
491 } else {
492 atomic_dec(excl);
493 return -EBUSY;
494 }
495}
496
497static inline void mbim_unlock(atomic_t *excl)
498{
499 atomic_dec(excl);
500}
501
502static struct ctrl_pkt *mbim_alloc_ctrl_pkt(unsigned len, gfp_t flags)
503{
504 struct ctrl_pkt *pkt;
505
506 pkt = kzalloc(sizeof(struct ctrl_pkt), flags);
507 if (!pkt)
508 return ERR_PTR(-ENOMEM);
509
510 pkt->buf = kmalloc(len, flags);
511 if (!pkt->buf) {
512 kfree(pkt);
513 return ERR_PTR(-ENOMEM);
514 }
515 pkt->len = len;
516
517 return pkt;
518}
519
520static void mbim_free_ctrl_pkt(struct ctrl_pkt *pkt)
521{
522 if (pkt) {
523 kfree(pkt->buf);
524 kfree(pkt);
525 }
526}
527
528static struct usb_request *mbim_alloc_req(struct usb_ep *ep, int buffer_size)
529{
530 struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
531 if (!req)
532 return NULL;
533
534 req->buf = kmalloc(buffer_size, GFP_KERNEL);
535 if (!req->buf) {
536 usb_ep_free_request(ep, req);
537 return NULL;
538 }
539 req->length = buffer_size;
540 return req;
541}
542
543void fmbim_free_req(struct usb_ep *ep, struct usb_request *req)
544{
545 if (req) {
546 kfree(req->buf);
547 usb_ep_free_request(ep, req);
548 }
549}
550
551static void fmbim_ctrl_response_available(struct f_mbim *dev)
552{
553 struct usb_request *req = dev->not_port.notify_req;
554 struct usb_cdc_notification *event = NULL;
555 unsigned long flags;
556 int ret;
557
Anna Perel68aeb172012-10-28 09:00:45 +0200558 pr_debug("dev:%p portno#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300559
560 spin_lock_irqsave(&dev->lock, flags);
561
562 if (!atomic_read(&dev->online)) {
Anna Perel20c91152012-10-30 16:26:44 +0200563 pr_err("dev:%p is not online\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300564 spin_unlock_irqrestore(&dev->lock, flags);
565 return;
566 }
567
568 if (!req) {
Anna Perel20c91152012-10-30 16:26:44 +0200569 pr_err("dev:%p req is NULL\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300570 spin_unlock_irqrestore(&dev->lock, flags);
571 return;
572 }
573
574 if (!req->buf) {
Anna Perel20c91152012-10-30 16:26:44 +0200575 pr_err("dev:%p req->buf is NULL\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300576 spin_unlock_irqrestore(&dev->lock, flags);
577 return;
578 }
579
Anna Perel68aeb172012-10-28 09:00:45 +0200580 if (atomic_inc_return(&dev->not_port.notify_count) != 1) {
581 pr_debug("delay ep_queue: notifications queue is busy[%d]",
582 atomic_read(&dev->not_port.notify_count));
583 spin_unlock_irqrestore(&dev->lock, flags);
584 return;
585 }
Anna Perela8c991d2012-04-09 16:44:46 +0300586
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200587 req->length = sizeof *event;
Anna Perela8c991d2012-04-09 16:44:46 +0300588 event = req->buf;
589 event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
590 | USB_RECIP_INTERFACE;
591 event->bNotificationType = USB_CDC_NOTIFY_RESPONSE_AVAILABLE;
592 event->wValue = cpu_to_le16(0);
593 event->wIndex = cpu_to_le16(dev->ctrl_id);
594 event->wLength = cpu_to_le16(0);
595 spin_unlock_irqrestore(&dev->lock, flags);
596
Anna Perela8c991d2012-04-09 16:44:46 +0300597 ret = usb_ep_queue(dev->not_port.notify,
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200598 req, GFP_ATOMIC);
Anna Perela8c991d2012-04-09 16:44:46 +0300599 if (ret) {
600 atomic_dec(&dev->not_port.notify_count);
601 pr_err("ep enqueue error %d\n", ret);
602 }
603
Anna Perel68aeb172012-10-28 09:00:45 +0200604 pr_debug("Successful Exit");
Anna Perela8c991d2012-04-09 16:44:46 +0300605}
606
607static int
608fmbim_send_cpkt_response(struct f_mbim *gr, struct ctrl_pkt *cpkt)
609{
610 struct f_mbim *dev = gr;
611 unsigned long flags;
612
613 if (!gr || !cpkt) {
614 pr_err("Invalid cpkt, dev:%p cpkt:%p\n",
615 gr, cpkt);
616 return -ENODEV;
617 }
618
Anna Perel20c91152012-10-30 16:26:44 +0200619 pr_debug("dev:%p port_num#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300620
621 if (!atomic_read(&dev->online)) {
Anna Perel20c91152012-10-30 16:26:44 +0200622 pr_err("dev:%p is not connected\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300623 mbim_free_ctrl_pkt(cpkt);
624 return 0;
625 }
626
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200627 if (dev->not_port.notify_state != NCM_NOTIFY_RESPONSE_AVAILABLE) {
628 pr_err("dev:%p state=%d, recover!!\n", dev,
629 dev->not_port.notify_state);
630 mbim_free_ctrl_pkt(cpkt);
631 return 0;
632 }
633
Anna Perela8c991d2012-04-09 16:44:46 +0300634 spin_lock_irqsave(&dev->lock, flags);
Anna Perel40c550c2012-04-11 14:09:27 +0300635 list_add_tail(&cpkt->list, &dev->cpkt_resp_q);
Anna Perela8c991d2012-04-09 16:44:46 +0300636 spin_unlock_irqrestore(&dev->lock, flags);
637
638 fmbim_ctrl_response_available(dev);
639
640 return 0;
641}
642
643/* ---------------------------- BAM INTERFACE ----------------------------- */
644
645static int mbim_bam_setup(int no_ports)
646{
647 int ret;
648
649 pr_info("no_ports:%d\n", no_ports);
650
651 ret = bam_data_setup(no_ports);
652 if (ret) {
653 pr_err("bam_data_setup failed err: %d\n", ret);
654 return ret;
655 }
656
657 pr_info("Initialized %d ports\n", no_ports);
658 return 0;
659}
660
661static int mbim_bam_connect(struct f_mbim *dev)
662{
663 int ret;
664
665 pr_info("dev:%p portno:%d\n", dev, dev->port_num);
666
667 ret = bam_data_connect(&dev->bam_port, dev->port_num, dev->port_num);
668 if (ret) {
669 pr_err("bam_data_setup failed: err:%d\n",
670 ret);
671 return ret;
672 } else {
673 pr_info("mbim bam connected\n");
674 }
675
676 return 0;
677}
678
679static int mbim_bam_disconnect(struct f_mbim *dev)
680{
681 pr_info("dev:%p port:%d. Do nothing.\n",
682 dev, dev->port_num);
683
Amit Blay51bebe92012-12-25 18:48:10 +0200684 bam_data_disconnect(&dev->bam_port, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300685
686 return 0;
687}
688
689/* -------------------------------------------------------------------------*/
690
691static inline void mbim_reset_values(struct f_mbim *mbim)
692{
693 mbim->parser_opts = &ndp16_opts;
694
695 mbim->ntb_input_size = NTB_DEFAULT_IN_SIZE;
696
Anna Perela8c991d2012-04-09 16:44:46 +0300697 atomic_set(&mbim->online, 0);
698}
699
Anna Perel86ea7c92012-04-24 14:31:29 +0300700static void mbim_reset_function_queue(struct f_mbim *dev)
701{
702 struct ctrl_pkt *cpkt = NULL;
703
704 pr_debug("Queue empty packet for QBI");
705
706 spin_lock(&dev->lock);
707 if (!dev->is_open) {
708 pr_err("%s: mbim file handler %p is not open", __func__, dev);
709 spin_unlock(&dev->lock);
710 return;
711 }
712
713 cpkt = mbim_alloc_ctrl_pkt(0, GFP_ATOMIC);
714 if (!cpkt) {
715 pr_err("%s: Unable to allocate reset function pkt\n", __func__);
716 spin_unlock(&dev->lock);
717 return;
718 }
719
720 list_add_tail(&cpkt->list, &dev->cpkt_req_q);
721 spin_unlock(&dev->lock);
722
723 pr_debug("%s: Wake up read queue", __func__);
724 wake_up(&dev->read_wq);
725}
726
727static void fmbim_reset_cmd_complete(struct usb_ep *ep, struct usb_request *req)
728{
729 struct f_mbim *dev = req->context;
730
731 mbim_reset_function_queue(dev);
732}
733
734static void mbim_clear_queues(struct f_mbim *mbim)
735{
736 struct ctrl_pkt *cpkt = NULL;
737 struct list_head *act, *tmp;
738
739 spin_lock(&mbim->lock);
740 list_for_each_safe(act, tmp, &mbim->cpkt_req_q) {
741 cpkt = list_entry(act, struct ctrl_pkt, list);
742 list_del(&cpkt->list);
743 mbim_free_ctrl_pkt(cpkt);
744 }
745 list_for_each_safe(act, tmp, &mbim->cpkt_resp_q) {
746 cpkt = list_entry(act, struct ctrl_pkt, list);
747 list_del(&cpkt->list);
748 mbim_free_ctrl_pkt(cpkt);
749 }
750 spin_unlock(&mbim->lock);
751}
752
Anna Perela8c991d2012-04-09 16:44:46 +0300753/*
754 * Context: mbim->lock held
755 */
756static void mbim_do_notify(struct f_mbim *mbim)
757{
758 struct usb_request *req = mbim->not_port.notify_req;
759 struct usb_cdc_notification *event;
760 struct usb_composite_dev *cdev = mbim->cdev;
761 __le32 *data;
762 int status;
763
Anna Perel20c91152012-10-30 16:26:44 +0200764 pr_debug("notify_state: %d", mbim->not_port.notify_state);
Anna Perela8c991d2012-04-09 16:44:46 +0300765
766 if (!req)
767 return;
768
769 event = req->buf;
770
771 switch (mbim->not_port.notify_state) {
772
773 case NCM_NOTIFY_NONE:
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200774 if (atomic_read(&mbim->not_port.notify_count) > 0)
775 pr_err("Pending notifications in NCM_NOTIFY_NONE\n");
776 else
777 pr_debug("No pending notifications\n");
778
779 return;
780
781 case NCM_NOTIFY_RESPONSE_AVAILABLE:
Anna Perel68aeb172012-10-28 09:00:45 +0200782 pr_debug("Notification %02x sent\n", event->bNotificationType);
783
784 if (atomic_read(&mbim->not_port.notify_count) <= 0) {
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200785 pr_debug("notify_response_avaliable: done");
Anna Perel68aeb172012-10-28 09:00:45 +0200786 return;
787 }
788
789 spin_unlock(&mbim->lock);
790 status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
791 spin_lock(&mbim->lock);
792 if (status) {
793 atomic_dec(&mbim->not_port.notify_count);
794 pr_err("Queue notify request failed, err: %d", status);
795 }
796
Anna Perela8c991d2012-04-09 16:44:46 +0300797 return;
798
799 case NCM_NOTIFY_CONNECT:
800 event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
801 if (mbim->is_open)
802 event->wValue = cpu_to_le16(1);
803 else
804 event->wValue = cpu_to_le16(0);
805 event->wLength = 0;
806 req->length = sizeof *event;
807
808 pr_info("notify connect %s\n",
809 mbim->is_open ? "true" : "false");
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200810 mbim->not_port.notify_state = NCM_NOTIFY_RESPONSE_AVAILABLE;
Anna Perela8c991d2012-04-09 16:44:46 +0300811 break;
812
813 case NCM_NOTIFY_SPEED:
814 event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
815 event->wValue = cpu_to_le16(0);
816 event->wLength = cpu_to_le16(8);
817 req->length = NCM_STATUS_BYTECOUNT;
818
819 /* SPEED_CHANGE data is up/down speeds in bits/sec */
820 data = req->buf + sizeof *event;
821 data[0] = cpu_to_le32(mbim_bitrate(cdev->gadget));
822 data[1] = data[0];
823
824 pr_info("notify speed %d\n",
825 mbim_bitrate(cdev->gadget));
826 mbim->not_port.notify_state = NCM_NOTIFY_CONNECT;
827 break;
828 }
Anna Perel68aeb172012-10-28 09:00:45 +0200829
Anna Perela8c991d2012-04-09 16:44:46 +0300830 event->bmRequestType = 0xA1;
831 event->wIndex = cpu_to_le16(mbim->ctrl_id);
832
Anna Perela8c991d2012-04-09 16:44:46 +0300833 /*
834 * In double buffering if there is a space in FIFO,
835 * completion callback can be called right after the call,
836 * so unlocking
837 */
Anna Perel68aeb172012-10-28 09:00:45 +0200838 atomic_inc(&mbim->not_port.notify_count);
839 pr_debug("queue request: notify_count = %d",
840 atomic_read(&mbim->not_port.notify_count));
Anna Perela8c991d2012-04-09 16:44:46 +0300841 spin_unlock(&mbim->lock);
842 status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
843 spin_lock(&mbim->lock);
Anna Perel68aeb172012-10-28 09:00:45 +0200844 if (status) {
Anna Perela8c991d2012-04-09 16:44:46 +0300845 atomic_dec(&mbim->not_port.notify_count);
846 pr_err("usb_ep_queue failed, err: %d", status);
847 }
848}
849
850/*
851 * Context: mbim->lock held
852 */
853static void mbim_notify(struct f_mbim *mbim)
854{
855 /*
856 * If mbim_notify() is called before the second (CONNECT)
857 * notification is sent, then it will reset to send the SPEED
858 * notificaion again (and again, and again), but it's not a problem
859 */
Anna Perel20c91152012-10-30 16:26:44 +0200860 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300861
Ido Shayevitzf1510c02013-02-07 11:48:49 +0200862 mbim->not_port.notify_state = NCM_NOTIFY_RESPONSE_AVAILABLE;
Anna Perela8c991d2012-04-09 16:44:46 +0300863 mbim_do_notify(mbim);
864}
865
866static void mbim_notify_complete(struct usb_ep *ep, struct usb_request *req)
867{
868 struct f_mbim *mbim = req->context;
869 struct usb_cdc_notification *event = req->buf;
870
Anna Perel68aeb172012-10-28 09:00:45 +0200871 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300872
873 spin_lock(&mbim->lock);
874 switch (req->status) {
875 case 0:
Anna Perel68aeb172012-10-28 09:00:45 +0200876 atomic_dec(&mbim->not_port.notify_count);
877 pr_debug("notify_count = %d",
878 atomic_read(&mbim->not_port.notify_count));
Anna Perela8c991d2012-04-09 16:44:46 +0300879 break;
880
881 case -ECONNRESET:
882 case -ESHUTDOWN:
883 /* connection gone */
884 mbim->not_port.notify_state = NCM_NOTIFY_NONE;
885 atomic_set(&mbim->not_port.notify_count, 0);
886 pr_info("ESHUTDOWN/ECONNRESET, connection gone");
Anna Perel86ea7c92012-04-24 14:31:29 +0300887 spin_unlock(&mbim->lock);
888 mbim_clear_queues(mbim);
889 mbim_reset_function_queue(mbim);
Anna Perel89ad1212012-06-13 17:17:24 +0300890 spin_lock(&mbim->lock);
Anna Perela8c991d2012-04-09 16:44:46 +0300891 break;
892 default:
893 pr_err("Unknown event %02x --> %d\n",
894 event->bNotificationType, req->status);
895 break;
896 }
897
Anna Perela8c991d2012-04-09 16:44:46 +0300898 mbim_do_notify(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300899 spin_unlock(&mbim->lock);
900
Anna Perel20c91152012-10-30 16:26:44 +0200901 pr_debug("dev:%p Exit\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300902}
903
904static void mbim_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
905{
906 /* now for SET_NTB_INPUT_SIZE only */
907 unsigned in_size = 0;
908 struct usb_function *f = req->context;
909 struct f_mbim *mbim = func_to_mbim(f);
910 struct mbim_ntb_input_size *ntb = NULL;
911
Anna Perel20c91152012-10-30 16:26:44 +0200912 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300913
914 req->context = NULL;
915 if (req->status || req->actual != req->length) {
916 pr_err("Bad control-OUT transfer\n");
917 goto invalid;
918 }
919
920 if (req->length == 4) {
921 in_size = get_unaligned_le32(req->buf);
922 if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
923 in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
924 pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
925 goto invalid;
926 }
927 } else if (req->length == 8) {
928 ntb = (struct mbim_ntb_input_size *)req->buf;
929 in_size = get_unaligned_le32(&(ntb->ntb_input_size));
930 if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
931 in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
932 pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
933 goto invalid;
934 }
935 mbim->ntb_max_datagrams =
936 get_unaligned_le16(&(ntb->ntb_max_datagrams));
937 } else {
938 pr_err("Illegal NTB length %d\n", in_size);
939 goto invalid;
940 }
941
Anna Perel20c91152012-10-30 16:26:44 +0200942 pr_debug("Set NTB INPUT SIZE %d\n", in_size);
Anna Perela8c991d2012-04-09 16:44:46 +0300943
944 mbim->ntb_input_size = in_size;
945 return;
946
947invalid:
948 usb_ep_set_halt(ep);
949
950 pr_err("dev:%p Failed\n", mbim);
951
952 return;
953}
954
955static void
956fmbim_cmd_complete(struct usb_ep *ep, struct usb_request *req)
957{
958 struct f_mbim *dev = req->context;
959 struct ctrl_pkt *cpkt = NULL;
960 int len = req->actual;
961
962 if (!dev) {
963 pr_err("mbim dev is null\n");
964 return;
965 }
966
967 if (req->status < 0) {
968 pr_err("mbim command error %d\n", req->status);
969 return;
970 }
971
Anna Perel20c91152012-10-30 16:26:44 +0200972 pr_debug("dev:%p port#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300973
Anna Perela8c991d2012-04-09 16:44:46 +0300974 cpkt = mbim_alloc_ctrl_pkt(len, GFP_ATOMIC);
975 if (!cpkt) {
976 pr_err("Unable to allocate ctrl pkt\n");
Anna Perela8c991d2012-04-09 16:44:46 +0300977 return;
978 }
979
Anna Perel20c91152012-10-30 16:26:44 +0200980 pr_debug("Add to cpkt_req_q packet with len = %d\n", len);
Anna Perela8c991d2012-04-09 16:44:46 +0300981 memcpy(cpkt->buf, req->buf, len);
Anna Perel20c91152012-10-30 16:26:44 +0200982
Anna Perel182ab572012-11-18 10:10:12 +0200983 spin_lock(&dev->lock);
984 if (!dev->is_open) {
985 pr_err("mbim file handler %p is not open", dev);
986 spin_unlock(&dev->lock);
987 mbim_free_ctrl_pkt(cpkt);
988 return;
989 }
990
Anna Perela8c991d2012-04-09 16:44:46 +0300991 list_add_tail(&cpkt->list, &dev->cpkt_req_q);
992 spin_unlock(&dev->lock);
993
994 /* wakeup read thread */
Anna Perel20c91152012-10-30 16:26:44 +0200995 pr_debug("Wake up read queue");
Anna Perela8c991d2012-04-09 16:44:46 +0300996 wake_up(&dev->read_wq);
997
998 return;
999}
1000
1001static int
1002mbim_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
1003{
1004 struct f_mbim *mbim = func_to_mbim(f);
1005 struct usb_composite_dev *cdev = mbim->cdev;
1006 struct usb_request *req = cdev->req;
1007 struct ctrl_pkt *cpkt = NULL;
1008 int value = -EOPNOTSUPP;
1009 u16 w_index = le16_to_cpu(ctrl->wIndex);
1010 u16 w_value = le16_to_cpu(ctrl->wValue);
1011 u16 w_length = le16_to_cpu(ctrl->wLength);
1012
1013 /*
1014 * composite driver infrastructure handles everything except
1015 * CDC class messages; interface activation uses set_alt().
1016 */
1017
1018 if (!atomic_read(&mbim->online)) {
1019 pr_info("usb cable is not connected\n");
1020 return -ENOTCONN;
1021 }
1022
1023 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
1024 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1025 | USB_CDC_RESET_FUNCTION:
1026
Anna Perel20c91152012-10-30 16:26:44 +02001027 pr_debug("USB_CDC_RESET_FUNCTION");
Anna Perela8c991d2012-04-09 16:44:46 +03001028 value = 0;
Anna Perel86ea7c92012-04-24 14:31:29 +03001029 req->complete = fmbim_reset_cmd_complete;
1030 req->context = mbim;
Anna Perela8c991d2012-04-09 16:44:46 +03001031 break;
1032
1033 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1034 | USB_CDC_SEND_ENCAPSULATED_COMMAND:
1035
Anna Perel20c91152012-10-30 16:26:44 +02001036 pr_debug("USB_CDC_SEND_ENCAPSULATED_COMMAND");
Anna Perela8c991d2012-04-09 16:44:46 +03001037
1038 if (w_length > req->length) {
Anna Perel20c91152012-10-30 16:26:44 +02001039 pr_debug("w_length > req->length: %d > %d",
Anna Perela8c991d2012-04-09 16:44:46 +03001040 w_length, req->length);
1041 }
1042 value = w_length;
1043 req->complete = fmbim_cmd_complete;
1044 req->context = mbim;
1045 break;
1046
1047 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1048 | USB_CDC_GET_ENCAPSULATED_RESPONSE:
1049
Anna Perel20c91152012-10-30 16:26:44 +02001050 pr_debug("USB_CDC_GET_ENCAPSULATED_RESPONSE");
Anna Perela8c991d2012-04-09 16:44:46 +03001051
1052 if (w_value) {
1053 pr_err("w_length > 0: %d", w_length);
1054 break;
1055 }
1056
Anna Perel20c91152012-10-30 16:26:44 +02001057 pr_debug("req%02x.%02x v%04x i%04x l%d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001058 ctrl->bRequestType, ctrl->bRequest,
1059 w_value, w_index, w_length);
1060
1061 spin_lock(&mbim->lock);
1062 if (list_empty(&mbim->cpkt_resp_q)) {
1063 pr_err("ctrl resp queue empty\n");
1064 spin_unlock(&mbim->lock);
1065 break;
1066 }
1067
1068 cpkt = list_first_entry(&mbim->cpkt_resp_q,
1069 struct ctrl_pkt, list);
1070 list_del(&cpkt->list);
1071 spin_unlock(&mbim->lock);
1072
1073 value = min_t(unsigned, w_length, cpkt->len);
1074 memcpy(req->buf, cpkt->buf, value);
1075 mbim_free_ctrl_pkt(cpkt);
1076
Anna Perel20c91152012-10-30 16:26:44 +02001077 pr_debug("copied encapsulated_response %d bytes",
Anna Perela8c991d2012-04-09 16:44:46 +03001078 value);
1079
1080 break;
1081
1082 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1083 | USB_CDC_GET_NTB_PARAMETERS:
1084
Anna Perel20c91152012-10-30 16:26:44 +02001085 pr_debug("USB_CDC_GET_NTB_PARAMETERS");
Anna Perela8c991d2012-04-09 16:44:46 +03001086
1087 if (w_length == 0 || w_value != 0 || w_index != mbim->ctrl_id)
1088 break;
1089
1090 value = w_length > sizeof ntb_parameters ?
1091 sizeof ntb_parameters : w_length;
1092 memcpy(req->buf, &ntb_parameters, value);
1093 break;
1094
1095 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1096 | USB_CDC_GET_NTB_INPUT_SIZE:
1097
Anna Perel20c91152012-10-30 16:26:44 +02001098 pr_debug("USB_CDC_GET_NTB_INPUT_SIZE");
Anna Perela8c991d2012-04-09 16:44:46 +03001099
1100 if (w_length < 4 || w_value != 0 || w_index != mbim->ctrl_id)
1101 break;
1102
1103 put_unaligned_le32(mbim->ntb_input_size, req->buf);
1104 value = 4;
Anna Perel20c91152012-10-30 16:26:44 +02001105 pr_debug("Reply to host INPUT SIZE %d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001106 mbim->ntb_input_size);
1107 break;
1108
1109 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1110 | USB_CDC_SET_NTB_INPUT_SIZE:
1111
Anna Perel20c91152012-10-30 16:26:44 +02001112 pr_debug("USB_CDC_SET_NTB_INPUT_SIZE");
Anna Perela8c991d2012-04-09 16:44:46 +03001113
1114 if (w_length != 4 && w_length != 8) {
1115 pr_err("wrong NTB length %d", w_length);
1116 break;
1117 }
1118
1119 if (w_value != 0 || w_index != mbim->ctrl_id)
1120 break;
1121
1122 req->complete = mbim_ep0out_complete;
1123 req->length = w_length;
1124 req->context = f;
1125
1126 value = req->length;
1127 break;
1128
1129 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1130 | USB_CDC_GET_NTB_FORMAT:
1131 {
1132 uint16_t format;
1133
Anna Perel20c91152012-10-30 16:26:44 +02001134 pr_debug("USB_CDC_GET_NTB_FORMAT");
Anna Perela8c991d2012-04-09 16:44:46 +03001135
1136 if (w_length < 2 || w_value != 0 || w_index != mbim->ctrl_id)
1137 break;
1138
1139 format = (mbim->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001;
1140 put_unaligned_le16(format, req->buf);
1141 value = 2;
Anna Perel20c91152012-10-30 16:26:44 +02001142 pr_debug("NTB FORMAT: sending %d\n", format);
Anna Perela8c991d2012-04-09 16:44:46 +03001143 break;
1144 }
1145
1146 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1147 | USB_CDC_SET_NTB_FORMAT:
1148 {
Anna Perel20c91152012-10-30 16:26:44 +02001149 pr_debug("USB_CDC_SET_NTB_FORMAT");
Anna Perela8c991d2012-04-09 16:44:46 +03001150
1151 if (w_length != 0 || w_index != mbim->ctrl_id)
1152 break;
1153 switch (w_value) {
1154 case 0x0000:
1155 mbim->parser_opts = &ndp16_opts;
Anna Perel20c91152012-10-30 16:26:44 +02001156 pr_debug("NCM16 selected\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001157 break;
1158 case 0x0001:
1159 mbim->parser_opts = &ndp32_opts;
Anna Perel20c91152012-10-30 16:26:44 +02001160 pr_debug("NCM32 selected\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001161 break;
1162 default:
1163 break;
1164 }
1165 value = 0;
1166 break;
1167 }
1168
1169 /* optional in mbim descriptor: */
1170 /* case USB_CDC_GET_MAX_DATAGRAM_SIZE: */
1171 /* case USB_CDC_SET_MAX_DATAGRAM_SIZE: */
1172
1173 default:
1174 pr_err("invalid control req: %02x.%02x v%04x i%04x l%d\n",
1175 ctrl->bRequestType, ctrl->bRequest,
1176 w_value, w_index, w_length);
1177 }
1178
1179 /* respond with data transfer or status phase? */
1180 if (value >= 0) {
Anna Perel20c91152012-10-30 16:26:44 +02001181 pr_debug("control request: %02x.%02x v%04x i%04x l%d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001182 ctrl->bRequestType, ctrl->bRequest,
1183 w_value, w_index, w_length);
Anna Perel2dfcaca2012-04-18 17:25:59 +03001184 req->zero = (value < w_length);
Anna Perela8c991d2012-04-09 16:44:46 +03001185 req->length = value;
1186 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
1187 if (value < 0) {
1188 pr_err("queueing req failed: %02x.%02x, err %d\n",
1189 ctrl->bRequestType,
1190 ctrl->bRequest, value);
1191 }
1192 } else {
1193 pr_err("ctrl req err %d: %02x.%02x v%04x i%04x l%d\n",
1194 value, ctrl->bRequestType, ctrl->bRequest,
1195 w_value, w_index, w_length);
1196 }
1197
1198 /* device either stalls (value < 0) or reports success */
1199 return value;
1200}
1201
Jack Pham2df2f702012-10-11 19:08:24 -07001202/*
1203 * This function handles the Microsoft-specific OS descriptor control
1204 * requests that are issued by Windows host drivers to determine the
1205 * configuration containing the MBIM function.
1206 *
1207 * Unlike mbim_setup() this function handles two specific device requests,
1208 * and only when a configuration has not yet been selected.
1209 */
1210static int mbim_ctrlrequest(struct usb_composite_dev *cdev,
1211 const struct usb_ctrlrequest *ctrl)
1212{
1213 int value = -EOPNOTSUPP;
1214 u16 w_index = le16_to_cpu(ctrl->wIndex);
1215 u16 w_value = le16_to_cpu(ctrl->wValue);
1216 u16 w_length = le16_to_cpu(ctrl->wLength);
1217
1218 /* only respond to OS desciptors when no configuration selected */
1219 if (cdev->config || !mbim_ext_config_desc.function.subCompatibleID[0])
1220 return value;
1221
1222 pr_debug("%02x.%02x v%04x i%04x l%u",
1223 ctrl->bRequestType, ctrl->bRequest,
1224 w_value, w_index, w_length);
1225
1226 /* Handle MSFT OS string */
1227 if (ctrl->bRequestType ==
1228 (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)
1229 && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR
1230 && (w_value >> 8) == USB_DT_STRING
1231 && (w_value & 0xFF) == MBIM_OS_STRING_ID) {
1232
1233 value = (w_length < sizeof(mbim_os_string) ?
1234 w_length : sizeof(mbim_os_string));
1235 memcpy(cdev->req->buf, mbim_os_string, value);
1236
1237 } else if (ctrl->bRequestType ==
1238 (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
1239 && ctrl->bRequest == MBIM_VENDOR_CODE && w_index == 4) {
1240
1241 /* Handle Extended OS descriptor */
1242 value = (w_length < sizeof(mbim_ext_config_desc) ?
1243 w_length : sizeof(mbim_ext_config_desc));
1244 memcpy(cdev->req->buf, &mbim_ext_config_desc, value);
1245 }
1246
1247 /* respond with data transfer or status phase? */
1248 if (value >= 0) {
1249 int rc;
1250 cdev->req->zero = value < w_length;
1251 cdev->req->length = value;
1252 rc = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
1253 if (rc < 0)
1254 pr_err("response queue error: %d", rc);
1255 }
1256 return value;
1257}
1258
Anna Perela8c991d2012-04-09 16:44:46 +03001259static int mbim_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
1260{
1261 struct f_mbim *mbim = func_to_mbim(f);
1262 struct usb_composite_dev *cdev = mbim->cdev;
1263 int ret = 0;
1264
1265 /* Control interface has only altsetting 0 */
1266 if (intf == mbim->ctrl_id) {
1267
1268 pr_info("CONTROL_INTERFACE");
1269
1270 if (alt != 0)
1271 goto fail;
1272
1273 if (mbim->not_port.notify->driver_data) {
1274 pr_info("reset mbim control %d\n", intf);
1275 usb_ep_disable(mbim->not_port.notify);
1276 }
1277
1278 ret = config_ep_by_speed(cdev->gadget, f,
1279 mbim->not_port.notify);
1280 if (ret) {
1281 mbim->not_port.notify->desc = NULL;
1282 pr_err("Failed configuring notify ep %s: err %d\n",
1283 mbim->not_port.notify->name, ret);
1284 return ret;
1285 }
1286
1287 ret = usb_ep_enable(mbim->not_port.notify);
1288 if (ret) {
1289 pr_err("usb ep#%s enable failed, err#%d\n",
1290 mbim->not_port.notify->name, ret);
1291 return ret;
1292 }
1293 mbim->not_port.notify->driver_data = mbim;
1294
1295 /* Data interface has two altsettings, 0 and 1 */
1296 } else if (intf == mbim->data_id) {
1297
1298 pr_info("DATA_INTERFACE");
1299
1300 if (alt > 1)
1301 goto fail;
1302
1303 if (mbim->bam_port.in->driver_data) {
1304 pr_info("reset mbim\n");
1305 mbim_reset_values(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +03001306 }
1307
1308 /*
1309 * CDC Network only sends data in non-default altsettings.
1310 * Changing altsettings resets filters, statistics, etc.
1311 */
1312 if (alt == 1) {
1313 pr_info("Alt set 1, initialize ports");
1314
1315 if (!mbim->bam_port.in->desc) {
1316
1317 pr_info("Choose endpoints");
1318
1319 ret = config_ep_by_speed(cdev->gadget, f,
1320 mbim->bam_port.in);
1321 if (ret) {
1322 mbim->bam_port.in->desc = NULL;
1323 pr_err("IN ep %s failed: %d\n",
1324 mbim->bam_port.in->name, ret);
1325 return ret;
1326 }
1327
1328 pr_info("Set mbim port in_desc = 0x%p",
1329 mbim->bam_port.in->desc);
1330
1331 ret = config_ep_by_speed(cdev->gadget, f,
1332 mbim->bam_port.out);
1333 if (ret) {
1334 mbim->bam_port.out->desc = NULL;
1335 pr_err("OUT ep %s failed: %d\n",
1336 mbim->bam_port.out->name, ret);
1337 return ret;
1338 }
1339
1340 pr_info("Set mbim port out_desc = 0x%p",
1341 mbim->bam_port.out->desc);
Anna Perel6637bd72012-10-23 10:53:32 +02001342
1343 pr_debug("Activate mbim\n");
1344 mbim_bam_connect(mbim);
1345
Anna Perela8c991d2012-04-09 16:44:46 +03001346 } else {
1347 pr_info("PORTS already SET");
1348 }
Anna Perela8c991d2012-04-09 16:44:46 +03001349 }
1350
Bar Weinerb1c95f52012-12-23 09:09:13 +02001351 mbim->data_alt_int = alt;
Anna Perela8c991d2012-04-09 16:44:46 +03001352 spin_lock(&mbim->lock);
1353 mbim_notify(mbim);
1354 spin_unlock(&mbim->lock);
1355 } else {
1356 goto fail;
1357 }
1358
1359 atomic_set(&mbim->online, 1);
1360
1361 pr_info("SET DEVICE ONLINE");
1362
1363 /* wakeup file threads */
1364 wake_up(&mbim->read_wq);
1365 wake_up(&mbim->write_wq);
1366
1367 return 0;
1368
1369fail:
1370 pr_err("ERROR: Illegal Interface");
1371 return -EINVAL;
1372}
1373
1374/*
1375 * Because the data interface supports multiple altsettings,
1376 * this MBIM function *MUST* implement a get_alt() method.
1377 */
1378static int mbim_get_alt(struct usb_function *f, unsigned intf)
1379{
1380 struct f_mbim *mbim = func_to_mbim(f);
1381
1382 if (intf == mbim->ctrl_id)
1383 return 0;
Bar Weinerb1c95f52012-12-23 09:09:13 +02001384 else if (intf == mbim->data_id)
1385 return mbim->data_alt_int;
1386
1387 return -EINVAL;
Anna Perela8c991d2012-04-09 16:44:46 +03001388}
1389
1390static void mbim_disable(struct usb_function *f)
1391{
1392 struct f_mbim *mbim = func_to_mbim(f);
1393
1394 pr_info("SET DEVICE OFFLINE");
1395 atomic_set(&mbim->online, 0);
1396
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +02001397 mbim->not_port.notify_state = NCM_NOTIFY_NONE;
1398
Anna Perel86ea7c92012-04-24 14:31:29 +03001399 mbim_clear_queues(mbim);
1400 mbim_reset_function_queue(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +03001401
1402 mbim_bam_disconnect(mbim);
1403
1404 if (mbim->not_port.notify->driver_data) {
1405 usb_ep_disable(mbim->not_port.notify);
1406 mbim->not_port.notify->driver_data = NULL;
1407 }
1408
Anna Perel68aeb172012-10-28 09:00:45 +02001409 atomic_set(&mbim->not_port.notify_count, 0);
1410
Anna Perela8c991d2012-04-09 16:44:46 +03001411 pr_info("mbim deactivated\n");
1412}
1413
Anna Perel557bf722012-09-20 11:16:35 +03001414#define MBIM_ACTIVE_PORT 0
1415
1416static void mbim_suspend(struct usb_function *f)
1417{
1418 pr_info("mbim suspended\n");
1419 bam_data_suspend(MBIM_ACTIVE_PORT);
1420}
1421
1422static void mbim_resume(struct usb_function *f)
1423{
1424 pr_info("mbim resumed\n");
1425 bam_data_resume(MBIM_ACTIVE_PORT);
1426}
1427
Anna Perela8c991d2012-04-09 16:44:46 +03001428/*---------------------- function driver setup/binding ---------------------*/
1429
1430static int
1431mbim_bind(struct usb_configuration *c, struct usb_function *f)
1432{
1433 struct usb_composite_dev *cdev = c->cdev;
1434 struct f_mbim *mbim = func_to_mbim(f);
1435 int status;
1436 struct usb_ep *ep;
1437
1438 pr_info("Enter");
1439
1440 mbim->cdev = cdev;
1441
1442 /* allocate instance-specific interface IDs */
1443 status = usb_interface_id(c, f);
1444 if (status < 0)
1445 goto fail;
1446 mbim->ctrl_id = status;
1447 mbim_iad_desc.bFirstInterface = status;
1448
1449 mbim_control_intf.bInterfaceNumber = status;
1450 mbim_union_desc.bMasterInterface0 = status;
1451
1452 status = usb_interface_id(c, f);
1453 if (status < 0)
1454 goto fail;
1455 mbim->data_id = status;
Bar Weinerb1c95f52012-12-23 09:09:13 +02001456 mbim->data_alt_int = 0;
Anna Perela8c991d2012-04-09 16:44:46 +03001457
1458 mbim_data_nop_intf.bInterfaceNumber = status;
1459 mbim_data_intf.bInterfaceNumber = status;
1460 mbim_union_desc.bSlaveInterface0 = status;
1461
Anna Perel557bf722012-09-20 11:16:35 +03001462 mbim->bam_port.cdev = cdev;
1463
Anna Perela8c991d2012-04-09 16:44:46 +03001464 status = -ENODEV;
1465
1466 /* allocate instance-specific endpoints */
1467 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_in_desc);
1468 if (!ep) {
1469 pr_err("usb epin autoconfig failed\n");
1470 goto fail;
1471 }
1472 pr_info("usb epin autoconfig succeeded\n");
1473 ep->driver_data = cdev; /* claim */
1474 mbim->bam_port.in = ep;
1475
1476 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_out_desc);
1477 if (!ep) {
1478 pr_err("usb epout autoconfig failed\n");
1479 goto fail;
1480 }
1481 pr_info("usb epout autoconfig succeeded\n");
1482 ep->driver_data = cdev; /* claim */
1483 mbim->bam_port.out = ep;
1484
1485 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_notify_desc);
1486 if (!ep) {
1487 pr_err("usb notify ep autoconfig failed\n");
1488 goto fail;
1489 }
1490 pr_info("usb notify ep autoconfig succeeded\n");
1491 mbim->not_port.notify = ep;
1492 ep->driver_data = cdev; /* claim */
1493
1494 status = -ENOMEM;
1495
1496 /* allocate notification request and buffer */
1497 mbim->not_port.notify_req = mbim_alloc_req(ep, NCM_STATUS_BYTECOUNT);
1498 if (!mbim->not_port.notify_req) {
1499 pr_info("failed to allocate notify request\n");
1500 goto fail;
1501 }
1502 pr_info("allocated notify ep request & request buffer\n");
1503
1504 mbim->not_port.notify_req->context = mbim;
1505 mbim->not_port.notify_req->complete = mbim_notify_complete;
1506
1507 /* copy descriptors, and track endpoint copies */
1508 f->descriptors = usb_copy_descriptors(mbim_fs_function);
1509 if (!f->descriptors)
1510 goto fail;
1511
1512 /*
1513 * support all relevant hardware speeds... we expect that when
1514 * hardware is dual speed, all bulk-capable endpoints work at
1515 * both speeds
1516 */
1517 if (gadget_is_dualspeed(c->cdev->gadget)) {
1518 hs_mbim_in_desc.bEndpointAddress =
1519 fs_mbim_in_desc.bEndpointAddress;
1520 hs_mbim_out_desc.bEndpointAddress =
1521 fs_mbim_out_desc.bEndpointAddress;
1522 hs_mbim_notify_desc.bEndpointAddress =
1523 fs_mbim_notify_desc.bEndpointAddress;
1524
1525 /* copy descriptors, and track endpoint copies */
1526 f->hs_descriptors = usb_copy_descriptors(mbim_hs_function);
1527 if (!f->hs_descriptors)
1528 goto fail;
1529 }
1530
Jack Pham2df2f702012-10-11 19:08:24 -07001531 /*
1532 * If MBIM is bound in a config other than the first, tell Windows
1533 * about it by returning the num as a string in the OS descriptor's
1534 * subCompatibleID field. Windows only supports up to config #4.
1535 */
1536 if (c->bConfigurationValue >= 2 && c->bConfigurationValue <= 4) {
1537 pr_debug("MBIM in configuration %d", c->bConfigurationValue);
1538 mbim_ext_config_desc.function.subCompatibleID[0] =
1539 c->bConfigurationValue + '0';
1540 }
1541
Anna Perela8c991d2012-04-09 16:44:46 +03001542 pr_info("mbim(%d): %s speed IN/%s OUT/%s NOTIFY/%s\n",
1543 mbim->port_num,
1544 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
1545 mbim->bam_port.in->name, mbim->bam_port.out->name,
1546 mbim->not_port.notify->name);
1547
1548 return 0;
1549
1550fail:
1551 pr_err("%s failed to bind, err %d\n", f->name, status);
1552
1553 if (f->descriptors)
1554 usb_free_descriptors(f->descriptors);
1555
1556 if (mbim->not_port.notify_req) {
1557 kfree(mbim->not_port.notify_req->buf);
1558 usb_ep_free_request(mbim->not_port.notify,
1559 mbim->not_port.notify_req);
1560 }
1561
1562 /* we might as well release our claims on endpoints */
1563 if (mbim->not_port.notify)
1564 mbim->not_port.notify->driver_data = NULL;
1565 if (mbim->bam_port.out)
1566 mbim->bam_port.out->driver_data = NULL;
1567 if (mbim->bam_port.in)
1568 mbim->bam_port.in->driver_data = NULL;
1569
1570 return status;
1571}
1572
1573static void mbim_unbind(struct usb_configuration *c, struct usb_function *f)
1574{
1575 struct f_mbim *mbim = func_to_mbim(f);
1576
1577 if (gadget_is_dualspeed(c->cdev->gadget))
1578 usb_free_descriptors(f->hs_descriptors);
1579 usb_free_descriptors(f->descriptors);
1580
1581 kfree(mbim->not_port.notify_req->buf);
1582 usb_ep_free_request(mbim->not_port.notify, mbim->not_port.notify_req);
Jack Pham2df2f702012-10-11 19:08:24 -07001583
1584 mbim_ext_config_desc.function.subCompatibleID[0] = 0;
Anna Perela8c991d2012-04-09 16:44:46 +03001585}
1586
1587/**
1588 * mbim_bind_config - add MBIM link to a configuration
1589 * @c: the configuration to support the network link
1590 * Context: single threaded during gadget setup
1591 * Returns zero on success, else negative errno.
1592 */
1593int mbim_bind_config(struct usb_configuration *c, unsigned portno)
1594{
1595 struct f_mbim *mbim = NULL;
1596 int status = 0;
1597
1598 pr_info("port number %u", portno);
1599
1600 if (portno >= nr_mbim_ports) {
1601 pr_err("Can not add port %u. Max ports = %d",
1602 portno, nr_mbim_ports);
1603 return -ENODEV;
1604 }
1605
1606 status = mbim_bam_setup(nr_mbim_ports);
1607 if (status) {
1608 pr_err("bam setup failed");
1609 return status;
1610 }
1611
1612 /* maybe allocate device-global string IDs */
1613 if (mbim_string_defs[0].id == 0) {
1614
1615 /* control interface label */
1616 status = usb_string_id(c->cdev);
1617 if (status < 0)
1618 return status;
1619 mbim_string_defs[STRING_CTRL_IDX].id = status;
1620 mbim_control_intf.iInterface = status;
1621
1622 /* data interface label */
1623 status = usb_string_id(c->cdev);
1624 if (status < 0)
1625 return status;
1626 mbim_string_defs[STRING_DATA_IDX].id = status;
1627 mbim_data_nop_intf.iInterface = status;
1628 mbim_data_intf.iInterface = status;
1629 }
1630
1631 /* allocate and initialize one new instance */
1632 mbim = mbim_ports[0].port;
1633 if (!mbim) {
1634 pr_info("mbim struct not allocated");
1635 return -ENOMEM;
1636 }
1637
1638 mbim->cdev = c->cdev;
1639
Anna Perela8c991d2012-04-09 16:44:46 +03001640 mbim_reset_values(mbim);
1641
1642 mbim->function.name = "usb_mbim";
1643 mbim->function.strings = mbim_strings;
1644 mbim->function.bind = mbim_bind;
1645 mbim->function.unbind = mbim_unbind;
1646 mbim->function.set_alt = mbim_set_alt;
1647 mbim->function.get_alt = mbim_get_alt;
1648 mbim->function.setup = mbim_setup;
1649 mbim->function.disable = mbim_disable;
Anna Perel557bf722012-09-20 11:16:35 +03001650 mbim->function.suspend = mbim_suspend;
1651 mbim->function.resume = mbim_resume;
Anna Perela8c991d2012-04-09 16:44:46 +03001652
1653 INIT_LIST_HEAD(&mbim->cpkt_req_q);
1654 INIT_LIST_HEAD(&mbim->cpkt_resp_q);
1655
1656 status = usb_add_function(c, &mbim->function);
1657
1658 pr_info("Exit status %d", status);
1659
1660 return status;
1661}
1662
1663/* ------------ MBIM DRIVER File Operations API for USER SPACE ------------ */
1664
1665static ssize_t
1666mbim_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
1667{
1668 struct f_mbim *dev = fp->private_data;
1669 struct ctrl_pkt *cpkt = NULL;
1670 int ret = 0;
1671
1672 pr_debug("Enter(%d)\n", count);
1673
1674 if (!dev) {
1675 pr_err("Received NULL mbim pointer\n");
1676 return -ENODEV;
1677 }
1678
1679 if (count > MBIM_BULK_BUFFER_SIZE) {
1680 pr_err("Buffer size is too big %d, should be at most %d\n",
1681 count, MBIM_BULK_BUFFER_SIZE);
1682 return -EINVAL;
1683 }
1684
1685 if (mbim_lock(&dev->read_excl)) {
1686 pr_err("Previous reading is not finished yet\n");
1687 return -EBUSY;
1688 }
1689
1690 /* block until mbim online */
1691 while (!(atomic_read(&dev->online) || atomic_read(&dev->error))) {
1692 pr_err("USB cable not connected. Wait.\n");
1693 ret = wait_event_interruptible(dev->read_wq,
1694 (atomic_read(&dev->online) ||
1695 atomic_read(&dev->error)));
1696 if (ret < 0) {
1697 mbim_unlock(&dev->read_excl);
Anna Perel96eea9d2012-12-09 14:08:04 +02001698 return -ERESTARTSYS;
Anna Perela8c991d2012-04-09 16:44:46 +03001699 }
1700 }
1701
1702 if (atomic_read(&dev->error)) {
1703 mbim_unlock(&dev->read_excl);
1704 return -EIO;
1705 }
1706
1707 while (list_empty(&dev->cpkt_req_q)) {
Anna Perel3747fdae2013-02-17 15:19:04 +02001708 pr_debug("Requests list is empty. Wait.\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001709 ret = wait_event_interruptible(dev->read_wq,
1710 !list_empty(&dev->cpkt_req_q));
1711 if (ret < 0) {
1712 pr_err("Waiting failed\n");
1713 mbim_unlock(&dev->read_excl);
Anna Perel96eea9d2012-12-09 14:08:04 +02001714 return -ERESTARTSYS;
Anna Perela8c991d2012-04-09 16:44:46 +03001715 }
1716 pr_debug("Received request packet\n");
1717 }
1718
1719 cpkt = list_first_entry(&dev->cpkt_req_q, struct ctrl_pkt,
1720 list);
1721 if (cpkt->len > count) {
1722 mbim_unlock(&dev->read_excl);
1723 pr_err("cpkt size too big:%d > buf size:%d\n",
1724 cpkt->len, count);
1725 return -ENOMEM;
1726 }
1727
1728 pr_debug("cpkt size:%d\n", cpkt->len);
1729
1730 list_del(&cpkt->list);
1731 mbim_unlock(&dev->read_excl);
1732
1733 ret = copy_to_user(buf, cpkt->buf, cpkt->len);
1734 if (ret) {
1735 pr_err("copy_to_user failed: err %d\n", ret);
Anna Perel96eea9d2012-12-09 14:08:04 +02001736 ret = -ENOMEM;
Anna Perela8c991d2012-04-09 16:44:46 +03001737 } else {
1738 pr_debug("copied %d bytes to user\n", cpkt->len);
1739 ret = cpkt->len;
1740 }
1741
1742 mbim_free_ctrl_pkt(cpkt);
1743
1744 return ret;
1745}
1746
1747static ssize_t
1748mbim_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos)
1749{
1750 struct f_mbim *dev = fp->private_data;
1751 struct ctrl_pkt *cpkt = NULL;
1752 int ret = 0;
1753
1754 pr_debug("Enter(%d)", count);
1755
1756 if (!dev) {
1757 pr_err("Received NULL mbim pointer\n");
1758 return -ENODEV;
1759 }
1760
1761 if (!count) {
1762 pr_err("zero length ctrl pkt\n");
1763 return -ENODEV;
1764 }
1765
1766 if (count > MAX_CTRL_PKT_SIZE) {
1767 pr_err("given pkt size too big:%d > max_pkt_size:%d\n",
1768 count, MAX_CTRL_PKT_SIZE);
1769 return -ENOMEM;
1770 }
1771
1772 if (mbim_lock(&dev->write_excl)) {
1773 pr_err("Previous writing not finished yet\n");
1774 return -EBUSY;
1775 }
1776
1777 if (!atomic_read(&dev->online)) {
1778 pr_err("USB cable not connected\n");
1779 mbim_unlock(&dev->write_excl);
1780 return -EPIPE;
1781 }
1782
1783 cpkt = mbim_alloc_ctrl_pkt(count, GFP_KERNEL);
1784 if (!cpkt) {
1785 pr_err("failed to allocate ctrl pkt\n");
1786 mbim_unlock(&dev->write_excl);
1787 return -ENOMEM;
1788 }
1789
1790 ret = copy_from_user(cpkt->buf, buf, count);
1791 if (ret) {
1792 pr_err("copy_from_user failed err:%d\n", ret);
1793 mbim_free_ctrl_pkt(cpkt);
1794 mbim_unlock(&dev->write_excl);
1795 return 0;
1796 }
1797
1798 fmbim_send_cpkt_response(dev, cpkt);
1799
1800 mbim_unlock(&dev->write_excl);
1801
1802 pr_debug("Exit(%d)", count);
1803
1804 return count;
Anna Perel89ad1212012-06-13 17:17:24 +03001805
Anna Perela8c991d2012-04-09 16:44:46 +03001806}
1807
1808static int mbim_open(struct inode *ip, struct file *fp)
1809{
1810 pr_info("Open mbim driver\n");
1811
1812 while (!_mbim_dev) {
1813 pr_err("mbim_dev not created yet\n");
1814 return -ENODEV;
1815 }
1816
1817 if (mbim_lock(&_mbim_dev->open_excl)) {
1818 pr_err("Already opened\n");
1819 return -EBUSY;
1820 }
1821
1822 pr_info("Lock mbim_dev->open_excl for open\n");
1823
1824 if (!atomic_read(&_mbim_dev->online))
1825 pr_err("USB cable not connected\n");
1826
Anna Perela8c991d2012-04-09 16:44:46 +03001827 fp->private_data = _mbim_dev;
1828
1829 atomic_set(&_mbim_dev->error, 0);
1830
1831 spin_lock(&_mbim_dev->lock);
1832 _mbim_dev->is_open = true;
Anna Perela8c991d2012-04-09 16:44:46 +03001833 spin_unlock(&_mbim_dev->lock);
1834
1835 pr_info("Exit, mbim file opened\n");
1836
1837 return 0;
1838}
1839
1840static int mbim_release(struct inode *ip, struct file *fp)
1841{
1842 struct f_mbim *mbim = fp->private_data;
1843
1844 pr_info("Close mbim file");
1845
1846 spin_lock(&mbim->lock);
1847 mbim->is_open = false;
Anna Perela8c991d2012-04-09 16:44:46 +03001848 spin_unlock(&mbim->lock);
1849
Anna Perela8c991d2012-04-09 16:44:46 +03001850 mbim_unlock(&_mbim_dev->open_excl);
1851
1852 return 0;
1853}
1854
1855static long mbim_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
1856{
1857 struct f_mbim *mbim = fp->private_data;
1858 int ret = 0;
1859
Anna Perel20c91152012-10-30 16:26:44 +02001860 pr_debug("Received command %d", cmd);
Anna Perela8c991d2012-04-09 16:44:46 +03001861
1862 if (mbim_lock(&mbim->ioctl_excl))
1863 return -EBUSY;
1864
1865 switch (cmd) {
1866 case MBIM_GET_NTB_SIZE:
1867 ret = copy_to_user((void __user *)arg,
1868 &mbim->ntb_input_size, sizeof(mbim->ntb_input_size));
1869 if (ret) {
1870 pr_err("copying to user space failed");
1871 ret = -EFAULT;
1872 }
1873 pr_info("Sent NTB size %d", mbim->ntb_input_size);
1874 break;
1875 case MBIM_GET_DATAGRAM_COUNT:
1876 ret = copy_to_user((void __user *)arg,
1877 &mbim->ntb_max_datagrams,
1878 sizeof(mbim->ntb_max_datagrams));
1879 if (ret) {
1880 pr_err("copying to user space failed");
1881 ret = -EFAULT;
1882 }
1883 pr_info("Sent NTB datagrams count %d",
1884 mbim->ntb_max_datagrams);
1885 break;
1886 default:
1887 pr_err("wrong parameter");
1888 ret = -EINVAL;
1889 }
1890
1891 mbim_unlock(&mbim->ioctl_excl);
1892
1893 return ret;
1894}
1895
1896/* file operations for MBIM device /dev/android_mbim */
1897static const struct file_operations mbim_fops = {
1898 .owner = THIS_MODULE,
1899 .open = mbim_open,
1900 .release = mbim_release,
1901 .read = mbim_read,
1902 .write = mbim_write,
1903 .unlocked_ioctl = mbim_ioctl,
1904};
1905
1906static struct miscdevice mbim_device = {
1907 .minor = MISC_DYNAMIC_MINOR,
1908 .name = "android_mbim",
1909 .fops = &mbim_fops,
1910};
1911
1912static int mbim_init(int instances)
1913{
1914 int i;
1915 struct f_mbim *dev = NULL;
1916 int ret;
1917
1918 pr_info("initialize %d instances\n", instances);
1919
1920 if (instances > NR_MBIM_PORTS) {
1921 pr_err("Max-%d instances supported\n", NR_MBIM_PORTS);
1922 return -EINVAL;
1923 }
1924
1925 for (i = 0; i < instances; i++) {
1926 dev = kzalloc(sizeof(struct f_mbim), GFP_KERNEL);
1927 if (!dev) {
1928 pr_err("Failed to allocate mbim dev\n");
1929 ret = -ENOMEM;
1930 goto fail_probe;
1931 }
1932
1933 dev->port_num = i;
1934 spin_lock_init(&dev->lock);
1935 INIT_LIST_HEAD(&dev->cpkt_req_q);
1936 INIT_LIST_HEAD(&dev->cpkt_resp_q);
1937
1938 mbim_ports[i].port = dev;
1939 mbim_ports[i].port_num = i;
1940
1941 init_waitqueue_head(&dev->read_wq);
1942 init_waitqueue_head(&dev->write_wq);
1943
1944 atomic_set(&dev->open_excl, 0);
1945 atomic_set(&dev->ioctl_excl, 0);
1946 atomic_set(&dev->read_excl, 0);
1947 atomic_set(&dev->write_excl, 0);
1948
1949 nr_mbim_ports++;
1950
1951 }
1952
1953 _mbim_dev = dev;
1954 ret = misc_register(&mbim_device);
1955 if (ret) {
1956 pr_err("mbim driver failed to register");
1957 goto fail_probe;
1958 }
1959
1960 pr_info("Initialized %d ports\n", nr_mbim_ports);
1961
1962 return ret;
1963
1964fail_probe:
1965 pr_err("Failed");
1966 for (i = 0; i < nr_mbim_ports; i++) {
1967 kfree(mbim_ports[i].port);
1968 mbim_ports[i].port = NULL;
1969 }
1970
1971 return ret;
1972}
1973
1974static void fmbim_cleanup(void)
1975{
1976 int i = 0;
1977
1978 pr_info("Enter");
1979
1980 for (i = 0; i < nr_mbim_ports; i++) {
1981 kfree(mbim_ports[i].port);
1982 mbim_ports[i].port = NULL;
1983 }
1984 nr_mbim_ports = 0;
1985
1986 misc_deregister(&mbim_device);
1987
1988 _mbim_dev = NULL;
1989}
1990