blob: 52e312647ac83ded30ec80100551dc3c0fc89bd1 [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
Lena Salmandf7e7992013-03-15 09:46:27 +020087 enum transport_type xport;
Anna Perela8c991d2012-04-09 16:44:46 +030088 u8 port_num;
89 struct data_port bam_port;
90 struct mbim_notify_port not_port;
91
92 struct mbim_ep_descs fs;
93 struct mbim_ep_descs hs;
94
95 u8 ctrl_id, data_id;
Bar Weinerb1c95f52012-12-23 09:09:13 +020096 u8 data_alt_int;
Anna Perela8c991d2012-04-09 16:44:46 +030097
98 struct ndp_parser_opts *parser_opts;
99
100 spinlock_t lock;
101
102 struct list_head cpkt_req_q;
103 struct list_head cpkt_resp_q;
104
105 u32 ntb_input_size;
106 u16 ntb_max_datagrams;
107
Anna Perela8c991d2012-04-09 16:44:46 +0300108 atomic_t error;
109};
110
111struct mbim_ntb_input_size {
112 u32 ntb_input_size;
113 u16 ntb_max_datagrams;
114 u16 reserved;
115};
116
117/* temporary variable used between mbim_open() and mbim_gadget_bind() */
118static struct f_mbim *_mbim_dev;
119
120static unsigned int nr_mbim_ports;
121
122static struct mbim_ports {
123 struct f_mbim *port;
124 unsigned port_num;
125} mbim_ports[NR_MBIM_PORTS];
126
127static inline struct f_mbim *func_to_mbim(struct usb_function *f)
128{
129 return container_of(f, struct f_mbim, function);
130}
131
132/* peak (theoretical) bulk transfer rate in bits-per-second */
133static inline unsigned mbim_bitrate(struct usb_gadget *g)
134{
135 if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
136 return 13 * 512 * 8 * 1000 * 8;
137 else
138 return 19 * 64 * 1 * 1000 * 8;
139}
140
141/*-------------------------------------------------------------------------*/
142
143#define NTB_DEFAULT_IN_SIZE (0x4000)
144#define NTB_OUT_SIZE (0x1000)
145#define NDP_IN_DIVISOR (0x4)
146
Lena Salmandf7e7992013-03-15 09:46:27 +0200147#define NTB_DEFAULT_IN_SIZE_IPA (0x2000)
148#define NTB_OUT_SIZE_IPA (0x2000)
149
Anna Perela8c991d2012-04-09 16:44:46 +0300150#define FORMATS_SUPPORTED USB_CDC_NCM_NTB16_SUPPORTED
151
152static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
153 .wLength = sizeof ntb_parameters,
154 .bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
155 .dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
156 .wNdpInDivisor = cpu_to_le16(NDP_IN_DIVISOR),
157 .wNdpInPayloadRemainder = cpu_to_le16(0),
158 .wNdpInAlignment = cpu_to_le16(4),
159
160 .dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE),
161 .wNdpOutDivisor = cpu_to_le16(4),
162 .wNdpOutPayloadRemainder = cpu_to_le16(0),
163 .wNdpOutAlignment = cpu_to_le16(4),
Anna Perelf99cd0c2012-05-03 13:30:26 +0300164 .wNtbOutMaxDatagrams = 0,
Anna Perela8c991d2012-04-09 16:44:46 +0300165};
166
167/*
168 * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
169 * packet, to simplify cancellation; and a big transfer interval, to
170 * waste less bandwidth.
171 */
172
173#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
174#define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
175
176static struct usb_interface_assoc_descriptor mbim_iad_desc = {
177 .bLength = sizeof mbim_iad_desc,
178 .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
179
180 /* .bFirstInterface = DYNAMIC, */
181 .bInterfaceCount = 2, /* control + data */
182 .bFunctionClass = 2,
183 .bFunctionSubClass = 0x0e,
184 .bFunctionProtocol = 0,
185 /* .iFunction = DYNAMIC */
186};
187
188/* interface descriptor: */
189static struct usb_interface_descriptor mbim_control_intf = {
190 .bLength = sizeof mbim_control_intf,
191 .bDescriptorType = USB_DT_INTERFACE,
192
193 /* .bInterfaceNumber = DYNAMIC */
194 .bNumEndpoints = 1,
195 .bInterfaceClass = 0x02,
196 .bInterfaceSubClass = 0x0e,
197 .bInterfaceProtocol = 0,
198 /* .iInterface = DYNAMIC */
199};
200
201static struct usb_cdc_header_desc mbim_header_desc = {
202 .bLength = sizeof mbim_header_desc,
203 .bDescriptorType = USB_DT_CS_INTERFACE,
204 .bDescriptorSubType = USB_CDC_HEADER_TYPE,
205
206 .bcdCDC = cpu_to_le16(0x0110),
207};
208
209static struct usb_cdc_union_desc mbim_union_desc = {
210 .bLength = sizeof(mbim_union_desc),
211 .bDescriptorType = USB_DT_CS_INTERFACE,
212 .bDescriptorSubType = USB_CDC_UNION_TYPE,
213 /* .bMasterInterface0 = DYNAMIC */
214 /* .bSlaveInterface0 = DYNAMIC */
215};
216
217static struct usb_cdc_mbb_desc mbb_desc = {
218 .bLength = sizeof mbb_desc,
219 .bDescriptorType = USB_DT_CS_INTERFACE,
220 .bDescriptorSubType = USB_CDC_MBB_TYPE,
221
222 .bcdMbbVersion = cpu_to_le16(0x0100),
223
224 .wMaxControlMessage = cpu_to_le16(0x1000),
Anna Perel3354bdc2012-12-09 12:08:10 +0200225 .bNumberFilters = 0x20,
Anna Perela8c991d2012-04-09 16:44:46 +0300226 .bMaxFilterSize = 0x80,
Anna Perel26ae27c2012-05-23 18:07:31 +0300227 .wMaxSegmentSize = cpu_to_le16(0xfe0),
Anna Perela8c991d2012-04-09 16:44:46 +0300228 .bmNetworkCapabilities = 0x20,
229};
230
Bar Weiner38c3e642013-02-12 10:25:17 +0200231static struct usb_cdc_ext_mbb_desc ext_mbb_desc = {
232 .bLength = sizeof ext_mbb_desc,
233 .bDescriptorType = USB_DT_CS_INTERFACE,
234 .bDescriptorSubType = USB_CDC_EXT_MBB_TYPE,
235
236 .bcdMbbExtendedVersion = cpu_to_le16(0x0100),
237 .bMaxOutstandingCmdMsges = 64,
238 .wMTU = 1500,
239};
240
Anna Perela8c991d2012-04-09 16:44:46 +0300241/* the default data interface has no endpoints ... */
242static struct usb_interface_descriptor mbim_data_nop_intf = {
243 .bLength = sizeof mbim_data_nop_intf,
244 .bDescriptorType = USB_DT_INTERFACE,
245
246 /* .bInterfaceNumber = DYNAMIC */
247 .bAlternateSetting = 0,
248 .bNumEndpoints = 0,
249 .bInterfaceClass = 0x0a,
250 .bInterfaceSubClass = 0,
251 .bInterfaceProtocol = 0x02,
252 /* .iInterface = DYNAMIC */
253};
254
255/* ... but the "real" data interface has two bulk endpoints */
256static struct usb_interface_descriptor mbim_data_intf = {
257 .bLength = sizeof mbim_data_intf,
258 .bDescriptorType = USB_DT_INTERFACE,
259
260 /* .bInterfaceNumber = DYNAMIC */
261 .bAlternateSetting = 1,
262 .bNumEndpoints = 2,
263 .bInterfaceClass = 0x0a,
264 .bInterfaceSubClass = 0,
265 .bInterfaceProtocol = 0x02,
266 /* .iInterface = DYNAMIC */
267};
268
269/* full speed support: */
270
271static struct usb_endpoint_descriptor fs_mbim_notify_desc = {
272 .bLength = USB_DT_ENDPOINT_SIZE,
273 .bDescriptorType = USB_DT_ENDPOINT,
274
275 .bEndpointAddress = USB_DIR_IN,
276 .bmAttributes = USB_ENDPOINT_XFER_INT,
277 .wMaxPacketSize = 4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
278 .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
279};
280
281static struct usb_endpoint_descriptor fs_mbim_in_desc = {
282 .bLength = USB_DT_ENDPOINT_SIZE,
283 .bDescriptorType = USB_DT_ENDPOINT,
284
285 .bEndpointAddress = USB_DIR_IN,
286 .bmAttributes = USB_ENDPOINT_XFER_BULK,
287};
288
289static struct usb_endpoint_descriptor fs_mbim_out_desc = {
290 .bLength = USB_DT_ENDPOINT_SIZE,
291 .bDescriptorType = USB_DT_ENDPOINT,
292
293 .bEndpointAddress = USB_DIR_OUT,
294 .bmAttributes = USB_ENDPOINT_XFER_BULK,
295};
296
297static struct usb_descriptor_header *mbim_fs_function[] = {
298 (struct usb_descriptor_header *) &mbim_iad_desc,
299 /* MBIM control descriptors */
300 (struct usb_descriptor_header *) &mbim_control_intf,
301 (struct usb_descriptor_header *) &mbim_header_desc,
Anna Perel555a7b22013-02-26 13:14:32 +0200302 (struct usb_descriptor_header *) &mbim_union_desc,
Anna Perela8c991d2012-04-09 16:44:46 +0300303 (struct usb_descriptor_header *) &mbb_desc,
Bar Weiner38c3e642013-02-12 10:25:17 +0200304 (struct usb_descriptor_header *) &ext_mbb_desc,
Anna Perela8c991d2012-04-09 16:44:46 +0300305 (struct usb_descriptor_header *) &fs_mbim_notify_desc,
306 /* data interface, altsettings 0 and 1 */
307 (struct usb_descriptor_header *) &mbim_data_nop_intf,
308 (struct usb_descriptor_header *) &mbim_data_intf,
309 (struct usb_descriptor_header *) &fs_mbim_in_desc,
310 (struct usb_descriptor_header *) &fs_mbim_out_desc,
311 NULL,
312};
313
314/* high speed support: */
315
316static struct usb_endpoint_descriptor hs_mbim_notify_desc = {
317 .bLength = USB_DT_ENDPOINT_SIZE,
318 .bDescriptorType = USB_DT_ENDPOINT,
319
320 .bEndpointAddress = USB_DIR_IN,
321 .bmAttributes = USB_ENDPOINT_XFER_INT,
322 .wMaxPacketSize = 4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
323 .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
324};
325static struct usb_endpoint_descriptor hs_mbim_in_desc = {
326 .bLength = USB_DT_ENDPOINT_SIZE,
327 .bDescriptorType = USB_DT_ENDPOINT,
328
329 .bEndpointAddress = USB_DIR_IN,
330 .bmAttributes = USB_ENDPOINT_XFER_BULK,
331 .wMaxPacketSize = cpu_to_le16(512),
332};
333
334static struct usb_endpoint_descriptor hs_mbim_out_desc = {
335 .bLength = USB_DT_ENDPOINT_SIZE,
336 .bDescriptorType = USB_DT_ENDPOINT,
337
338 .bEndpointAddress = USB_DIR_OUT,
339 .bmAttributes = USB_ENDPOINT_XFER_BULK,
340 .wMaxPacketSize = cpu_to_le16(512),
341};
342
343static struct usb_descriptor_header *mbim_hs_function[] = {
344 (struct usb_descriptor_header *) &mbim_iad_desc,
345 /* MBIM control descriptors */
346 (struct usb_descriptor_header *) &mbim_control_intf,
347 (struct usb_descriptor_header *) &mbim_header_desc,
348 (struct usb_descriptor_header *) &mbb_desc,
Bar Weiner38c3e642013-02-12 10:25:17 +0200349 (struct usb_descriptor_header *) &ext_mbb_desc,
Anna Perela8c991d2012-04-09 16:44:46 +0300350 (struct usb_descriptor_header *) &hs_mbim_notify_desc,
351 /* data interface, altsettings 0 and 1 */
352 (struct usb_descriptor_header *) &mbim_data_nop_intf,
353 (struct usb_descriptor_header *) &mbim_data_intf,
354 (struct usb_descriptor_header *) &hs_mbim_in_desc,
355 (struct usb_descriptor_header *) &hs_mbim_out_desc,
356 NULL,
357};
358
359/* string descriptors: */
360
361#define STRING_CTRL_IDX 0
362#define STRING_DATA_IDX 1
363
364static struct usb_string mbim_string_defs[] = {
365 [STRING_CTRL_IDX].s = "MBIM Control",
366 [STRING_DATA_IDX].s = "MBIM Data",
367 { } /* end of list */
368};
369
370static struct usb_gadget_strings mbim_string_table = {
371 .language = 0x0409, /* en-us */
372 .strings = mbim_string_defs,
373};
374
375static struct usb_gadget_strings *mbim_strings[] = {
376 &mbim_string_table,
377 NULL,
378};
379
Jack Pham2df2f702012-10-11 19:08:24 -0700380/* Microsoft OS Descriptors */
381
382/*
383 * We specify our own bMS_VendorCode byte which Windows will use
384 * as the bRequest value in subsequent device get requests.
385 */
386#define MBIM_VENDOR_CODE 0xA5
387
388/* Microsoft OS String */
389static u8 mbim_os_string[] = {
390 18, /* sizeof(mtp_os_string) */
391 USB_DT_STRING,
392 /* Signature field: "MSFT100" */
393 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0,
394 /* vendor code */
395 MBIM_VENDOR_CODE,
396 /* padding */
397 0
398};
399
400/* Microsoft Extended Configuration Descriptor Header Section */
401struct mbim_ext_config_desc_header {
402 __le32 dwLength;
403 __u16 bcdVersion;
404 __le16 wIndex;
405 __u8 bCount;
406 __u8 reserved[7];
407};
408
409/* Microsoft Extended Configuration Descriptor Function Section */
410struct mbim_ext_config_desc_function {
411 __u8 bFirstInterfaceNumber;
412 __u8 bInterfaceCount;
413 __u8 compatibleID[8];
414 __u8 subCompatibleID[8];
415 __u8 reserved[6];
416};
417
418/* Microsoft Extended Configuration Descriptor */
419static struct {
420 struct mbim_ext_config_desc_header header;
421 struct mbim_ext_config_desc_function function;
422} mbim_ext_config_desc = {
423 .header = {
424 .dwLength = __constant_cpu_to_le32(sizeof mbim_ext_config_desc),
425 .bcdVersion = __constant_cpu_to_le16(0x0100),
426 .wIndex = __constant_cpu_to_le16(4),
427 .bCount = 1,
428 },
429 .function = {
430 .bFirstInterfaceNumber = 0,
431 .bInterfaceCount = 1,
432 .compatibleID = { 'A', 'L', 'T', 'R', 'C', 'F', 'G' },
433 /* .subCompatibleID = DYNAMIC */
434 },
435};
436
Anna Perela8c991d2012-04-09 16:44:46 +0300437/*
438 * Here are options for the Datagram Pointer table (NDP) parser.
439 * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
440 * in NDP16 offsets and sizes fields are 1 16bit word wide,
441 * in NDP32 -- 2 16bit words wide. Also signatures are different.
442 * To make the parser code the same, put the differences in the structure,
443 * and switch pointers to the structures when the format is changed.
444 */
445
446struct ndp_parser_opts {
447 u32 nth_sign;
448 u32 ndp_sign;
449 unsigned nth_size;
450 unsigned ndp_size;
451 unsigned ndplen_align;
452 /* sizes in u16 units */
453 unsigned dgram_item_len; /* index or length */
454 unsigned block_length;
455 unsigned fp_index;
456 unsigned reserved1;
457 unsigned reserved2;
458 unsigned next_fp_index;
459};
460
461#define INIT_NDP16_OPTS { \
462 .nth_sign = USB_CDC_NCM_NTH16_SIGN, \
463 .ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \
464 .nth_size = sizeof(struct usb_cdc_ncm_nth16), \
465 .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \
466 .ndplen_align = 4, \
467 .dgram_item_len = 1, \
468 .block_length = 1, \
469 .fp_index = 1, \
470 .reserved1 = 0, \
471 .reserved2 = 0, \
472 .next_fp_index = 1, \
473}
474
475#define INIT_NDP32_OPTS { \
476 .nth_sign = USB_CDC_NCM_NTH32_SIGN, \
477 .ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \
478 .nth_size = sizeof(struct usb_cdc_ncm_nth32), \
479 .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \
480 .ndplen_align = 8, \
481 .dgram_item_len = 2, \
482 .block_length = 2, \
483 .fp_index = 2, \
484 .reserved1 = 1, \
485 .reserved2 = 2, \
486 .next_fp_index = 2, \
487}
488
489static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
490static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
491
492static inline int mbim_lock(atomic_t *excl)
493{
494 if (atomic_inc_return(excl) == 1) {
495 return 0;
496 } else {
497 atomic_dec(excl);
498 return -EBUSY;
499 }
500}
501
502static inline void mbim_unlock(atomic_t *excl)
503{
504 atomic_dec(excl);
505}
506
507static struct ctrl_pkt *mbim_alloc_ctrl_pkt(unsigned len, gfp_t flags)
508{
509 struct ctrl_pkt *pkt;
510
511 pkt = kzalloc(sizeof(struct ctrl_pkt), flags);
512 if (!pkt)
513 return ERR_PTR(-ENOMEM);
514
515 pkt->buf = kmalloc(len, flags);
516 if (!pkt->buf) {
517 kfree(pkt);
518 return ERR_PTR(-ENOMEM);
519 }
520 pkt->len = len;
521
522 return pkt;
523}
524
525static void mbim_free_ctrl_pkt(struct ctrl_pkt *pkt)
526{
527 if (pkt) {
528 kfree(pkt->buf);
529 kfree(pkt);
530 }
531}
532
533static struct usb_request *mbim_alloc_req(struct usb_ep *ep, int buffer_size)
534{
535 struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
536 if (!req)
537 return NULL;
538
539 req->buf = kmalloc(buffer_size, GFP_KERNEL);
540 if (!req->buf) {
541 usb_ep_free_request(ep, req);
542 return NULL;
543 }
544 req->length = buffer_size;
545 return req;
546}
547
548void fmbim_free_req(struct usb_ep *ep, struct usb_request *req)
549{
550 if (req) {
551 kfree(req->buf);
552 usb_ep_free_request(ep, req);
553 }
554}
555
556static void fmbim_ctrl_response_available(struct f_mbim *dev)
557{
558 struct usb_request *req = dev->not_port.notify_req;
559 struct usb_cdc_notification *event = NULL;
560 unsigned long flags;
561 int ret;
562
Anna Perel68aeb172012-10-28 09:00:45 +0200563 pr_debug("dev:%p portno#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300564
565 spin_lock_irqsave(&dev->lock, flags);
566
567 if (!atomic_read(&dev->online)) {
Anna Perel20c91152012-10-30 16:26:44 +0200568 pr_err("dev:%p is not online\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300569 spin_unlock_irqrestore(&dev->lock, flags);
570 return;
571 }
572
573 if (!req) {
Anna Perel20c91152012-10-30 16:26:44 +0200574 pr_err("dev:%p req is NULL\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300575 spin_unlock_irqrestore(&dev->lock, flags);
576 return;
577 }
578
579 if (!req->buf) {
Anna Perel20c91152012-10-30 16:26:44 +0200580 pr_err("dev:%p req->buf is NULL\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300581 spin_unlock_irqrestore(&dev->lock, flags);
582 return;
583 }
584
Anna Perel68aeb172012-10-28 09:00:45 +0200585 if (atomic_inc_return(&dev->not_port.notify_count) != 1) {
586 pr_debug("delay ep_queue: notifications queue is busy[%d]",
587 atomic_read(&dev->not_port.notify_count));
588 spin_unlock_irqrestore(&dev->lock, flags);
589 return;
590 }
Anna Perela8c991d2012-04-09 16:44:46 +0300591
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200592 req->length = sizeof *event;
Anna Perela8c991d2012-04-09 16:44:46 +0300593 event = req->buf;
594 event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
595 | USB_RECIP_INTERFACE;
596 event->bNotificationType = USB_CDC_NOTIFY_RESPONSE_AVAILABLE;
597 event->wValue = cpu_to_le16(0);
598 event->wIndex = cpu_to_le16(dev->ctrl_id);
599 event->wLength = cpu_to_le16(0);
600 spin_unlock_irqrestore(&dev->lock, flags);
601
Anna Perela8c991d2012-04-09 16:44:46 +0300602 ret = usb_ep_queue(dev->not_port.notify,
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200603 req, GFP_ATOMIC);
Anna Perela8c991d2012-04-09 16:44:46 +0300604 if (ret) {
605 atomic_dec(&dev->not_port.notify_count);
606 pr_err("ep enqueue error %d\n", ret);
607 }
608
Anna Perel68aeb172012-10-28 09:00:45 +0200609 pr_debug("Successful Exit");
Anna Perela8c991d2012-04-09 16:44:46 +0300610}
611
612static int
613fmbim_send_cpkt_response(struct f_mbim *gr, struct ctrl_pkt *cpkt)
614{
615 struct f_mbim *dev = gr;
616 unsigned long flags;
617
618 if (!gr || !cpkt) {
619 pr_err("Invalid cpkt, dev:%p cpkt:%p\n",
620 gr, cpkt);
621 return -ENODEV;
622 }
623
Anna Perel20c91152012-10-30 16:26:44 +0200624 pr_debug("dev:%p port_num#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300625
626 if (!atomic_read(&dev->online)) {
Anna Perel20c91152012-10-30 16:26:44 +0200627 pr_err("dev:%p is not connected\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300628 mbim_free_ctrl_pkt(cpkt);
629 return 0;
630 }
631
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200632 if (dev->not_port.notify_state != NCM_NOTIFY_RESPONSE_AVAILABLE) {
633 pr_err("dev:%p state=%d, recover!!\n", dev,
634 dev->not_port.notify_state);
635 mbim_free_ctrl_pkt(cpkt);
636 return 0;
637 }
638
Anna Perela8c991d2012-04-09 16:44:46 +0300639 spin_lock_irqsave(&dev->lock, flags);
Anna Perel40c550c2012-04-11 14:09:27 +0300640 list_add_tail(&cpkt->list, &dev->cpkt_resp_q);
Anna Perela8c991d2012-04-09 16:44:46 +0300641 spin_unlock_irqrestore(&dev->lock, flags);
642
643 fmbim_ctrl_response_available(dev);
644
645 return 0;
646}
647
648/* ---------------------------- BAM INTERFACE ----------------------------- */
649
650static int mbim_bam_setup(int no_ports)
651{
652 int ret;
653
654 pr_info("no_ports:%d\n", no_ports);
655
656 ret = bam_data_setup(no_ports);
657 if (ret) {
658 pr_err("bam_data_setup failed err: %d\n", ret);
659 return ret;
660 }
661
662 pr_info("Initialized %d ports\n", no_ports);
663 return 0;
664}
665
Lena Salmandf7e7992013-03-15 09:46:27 +0200666int mbim_configure_params(void)
667{
668 struct teth_aggr_params aggr_params;
669 int ret = 0;
670
671 aggr_params.dl.aggr_prot = TETH_AGGR_PROTOCOL_MBIM;
672 aggr_params.dl.max_datagrams = ntb_parameters.wNtbOutMaxDatagrams;
673 aggr_params.dl.max_transfer_size_byte = ntb_parameters.dwNtbInMaxSize;
674
675 aggr_params.ul.aggr_prot = TETH_AGGR_PROTOCOL_MBIM;
676 aggr_params.ul.max_datagrams = ntb_parameters.wNtbOutMaxDatagrams;
677 aggr_params.ul.max_transfer_size_byte = ntb_parameters.dwNtbOutMaxSize;
678
679 ret = teth_bridge_set_aggr_params(&aggr_params);
680 if (ret)
681 pr_err("%s: teth_bridge_set_aggr_params failed\n", __func__);
682
683 return ret;
684}
685
Anna Perela8c991d2012-04-09 16:44:46 +0300686static int mbim_bam_connect(struct f_mbim *dev)
687{
688 int ret;
Shimrit Malichidbf43d72013-03-16 03:32:27 +0200689 u8 src_connection_idx, dst_connection_idx;
690 struct usb_gadget *gadget = dev->cdev->gadget;
Lena Salmandf7e7992013-03-15 09:46:27 +0200691 enum peer_bam bam_name = (dev->xport == USB_GADGET_XPORT_BAM2BAM_IPA) ?
692 IPA_P_BAM : A2_P_BAM;
Anna Perela8c991d2012-04-09 16:44:46 +0300693
694 pr_info("dev:%p portno:%d\n", dev, dev->port_num);
695
Lena Salmandf7e7992013-03-15 09:46:27 +0200696 src_connection_idx = usb_bam_get_connection_idx(gadget->name, bam_name,
697 USB_TO_PEER_PERIPHERAL, dev->port_num);
698 dst_connection_idx = usb_bam_get_connection_idx(gadget->name, bam_name,
699 PEER_PERIPHERAL_TO_USB, dev->port_num);
Shimrit Malichidbf43d72013-03-16 03:32:27 +0200700 if (src_connection_idx < 0 || dst_connection_idx < 0) {
701 pr_err("%s: usb_bam_get_connection_idx failed\n", __func__);
702 return ret;
703 }
704
Amit Blayf9b352b2013-03-04 15:01:40 +0200705 ret = bam_data_connect(&dev->bam_port, dev->port_num,
Lena Salmandf7e7992013-03-15 09:46:27 +0200706 dev->xport, src_connection_idx, dst_connection_idx,
707 USB_FUNC_MBIM);
708
Anna Perela8c991d2012-04-09 16:44:46 +0300709 if (ret) {
710 pr_err("bam_data_setup failed: err:%d\n",
711 ret);
712 return ret;
Anna Perela8c991d2012-04-09 16:44:46 +0300713 }
714
Shimrit Malichidbf43d72013-03-16 03:32:27 +0200715 pr_info("mbim bam connected\n");
Anna Perela8c991d2012-04-09 16:44:46 +0300716 return 0;
717}
718
719static int mbim_bam_disconnect(struct f_mbim *dev)
720{
721 pr_info("dev:%p port:%d. Do nothing.\n",
722 dev, dev->port_num);
723
Amit Blay51bebe92012-12-25 18:48:10 +0200724 bam_data_disconnect(&dev->bam_port, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300725
726 return 0;
727}
728
729/* -------------------------------------------------------------------------*/
730
731static inline void mbim_reset_values(struct f_mbim *mbim)
732{
733 mbim->parser_opts = &ndp16_opts;
734
735 mbim->ntb_input_size = NTB_DEFAULT_IN_SIZE;
736
Anna Perela8c991d2012-04-09 16:44:46 +0300737 atomic_set(&mbim->online, 0);
738}
739
Anna Perel86ea7c92012-04-24 14:31:29 +0300740static void mbim_reset_function_queue(struct f_mbim *dev)
741{
742 struct ctrl_pkt *cpkt = NULL;
743
744 pr_debug("Queue empty packet for QBI");
745
746 spin_lock(&dev->lock);
747 if (!dev->is_open) {
748 pr_err("%s: mbim file handler %p is not open", __func__, dev);
749 spin_unlock(&dev->lock);
750 return;
751 }
752
753 cpkt = mbim_alloc_ctrl_pkt(0, GFP_ATOMIC);
754 if (!cpkt) {
755 pr_err("%s: Unable to allocate reset function pkt\n", __func__);
756 spin_unlock(&dev->lock);
757 return;
758 }
759
760 list_add_tail(&cpkt->list, &dev->cpkt_req_q);
761 spin_unlock(&dev->lock);
762
763 pr_debug("%s: Wake up read queue", __func__);
764 wake_up(&dev->read_wq);
765}
766
767static void fmbim_reset_cmd_complete(struct usb_ep *ep, struct usb_request *req)
768{
769 struct f_mbim *dev = req->context;
770
771 mbim_reset_function_queue(dev);
772}
773
774static void mbim_clear_queues(struct f_mbim *mbim)
775{
776 struct ctrl_pkt *cpkt = NULL;
777 struct list_head *act, *tmp;
778
779 spin_lock(&mbim->lock);
780 list_for_each_safe(act, tmp, &mbim->cpkt_req_q) {
781 cpkt = list_entry(act, struct ctrl_pkt, list);
782 list_del(&cpkt->list);
783 mbim_free_ctrl_pkt(cpkt);
784 }
785 list_for_each_safe(act, tmp, &mbim->cpkt_resp_q) {
786 cpkt = list_entry(act, struct ctrl_pkt, list);
787 list_del(&cpkt->list);
788 mbim_free_ctrl_pkt(cpkt);
789 }
790 spin_unlock(&mbim->lock);
791}
792
Anna Perela8c991d2012-04-09 16:44:46 +0300793/*
794 * Context: mbim->lock held
795 */
796static void mbim_do_notify(struct f_mbim *mbim)
797{
798 struct usb_request *req = mbim->not_port.notify_req;
799 struct usb_cdc_notification *event;
800 struct usb_composite_dev *cdev = mbim->cdev;
801 __le32 *data;
802 int status;
803
Anna Perel20c91152012-10-30 16:26:44 +0200804 pr_debug("notify_state: %d", mbim->not_port.notify_state);
Anna Perela8c991d2012-04-09 16:44:46 +0300805
806 if (!req)
807 return;
808
809 event = req->buf;
810
811 switch (mbim->not_port.notify_state) {
812
813 case NCM_NOTIFY_NONE:
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200814 if (atomic_read(&mbim->not_port.notify_count) > 0)
815 pr_err("Pending notifications in NCM_NOTIFY_NONE\n");
816 else
817 pr_debug("No pending notifications\n");
818
819 return;
820
821 case NCM_NOTIFY_RESPONSE_AVAILABLE:
Anna Perel68aeb172012-10-28 09:00:45 +0200822 pr_debug("Notification %02x sent\n", event->bNotificationType);
823
824 if (atomic_read(&mbim->not_port.notify_count) <= 0) {
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200825 pr_debug("notify_response_avaliable: done");
Anna Perel68aeb172012-10-28 09:00:45 +0200826 return;
827 }
828
829 spin_unlock(&mbim->lock);
830 status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
831 spin_lock(&mbim->lock);
832 if (status) {
833 atomic_dec(&mbim->not_port.notify_count);
834 pr_err("Queue notify request failed, err: %d", status);
835 }
836
Anna Perela8c991d2012-04-09 16:44:46 +0300837 return;
838
839 case NCM_NOTIFY_CONNECT:
840 event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
841 if (mbim->is_open)
842 event->wValue = cpu_to_le16(1);
843 else
844 event->wValue = cpu_to_le16(0);
845 event->wLength = 0;
846 req->length = sizeof *event;
847
848 pr_info("notify connect %s\n",
849 mbim->is_open ? "true" : "false");
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +0200850 mbim->not_port.notify_state = NCM_NOTIFY_RESPONSE_AVAILABLE;
Anna Perela8c991d2012-04-09 16:44:46 +0300851 break;
852
853 case NCM_NOTIFY_SPEED:
854 event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
855 event->wValue = cpu_to_le16(0);
856 event->wLength = cpu_to_le16(8);
857 req->length = NCM_STATUS_BYTECOUNT;
858
859 /* SPEED_CHANGE data is up/down speeds in bits/sec */
860 data = req->buf + sizeof *event;
861 data[0] = cpu_to_le32(mbim_bitrate(cdev->gadget));
862 data[1] = data[0];
863
864 pr_info("notify speed %d\n",
865 mbim_bitrate(cdev->gadget));
866 mbim->not_port.notify_state = NCM_NOTIFY_CONNECT;
867 break;
868 }
Anna Perel68aeb172012-10-28 09:00:45 +0200869
Anna Perela8c991d2012-04-09 16:44:46 +0300870 event->bmRequestType = 0xA1;
871 event->wIndex = cpu_to_le16(mbim->ctrl_id);
872
Anna Perela8c991d2012-04-09 16:44:46 +0300873 /*
874 * In double buffering if there is a space in FIFO,
875 * completion callback can be called right after the call,
876 * so unlocking
877 */
Anna Perel68aeb172012-10-28 09:00:45 +0200878 atomic_inc(&mbim->not_port.notify_count);
879 pr_debug("queue request: notify_count = %d",
880 atomic_read(&mbim->not_port.notify_count));
Anna Perela8c991d2012-04-09 16:44:46 +0300881 spin_unlock(&mbim->lock);
882 status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
883 spin_lock(&mbim->lock);
Anna Perel68aeb172012-10-28 09:00:45 +0200884 if (status) {
Anna Perela8c991d2012-04-09 16:44:46 +0300885 atomic_dec(&mbim->not_port.notify_count);
886 pr_err("usb_ep_queue failed, err: %d", status);
887 }
888}
889
890/*
891 * Context: mbim->lock held
892 */
893static void mbim_notify(struct f_mbim *mbim)
894{
895 /*
896 * If mbim_notify() is called before the second (CONNECT)
897 * notification is sent, then it will reset to send the SPEED
898 * notificaion again (and again, and again), but it's not a problem
899 */
Anna Perel20c91152012-10-30 16:26:44 +0200900 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300901
Ido Shayevitzf1510c02013-02-07 11:48:49 +0200902 mbim->not_port.notify_state = NCM_NOTIFY_RESPONSE_AVAILABLE;
Anna Perela8c991d2012-04-09 16:44:46 +0300903 mbim_do_notify(mbim);
904}
905
906static void mbim_notify_complete(struct usb_ep *ep, struct usb_request *req)
907{
908 struct f_mbim *mbim = req->context;
909 struct usb_cdc_notification *event = req->buf;
910
Anna Perel68aeb172012-10-28 09:00:45 +0200911 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300912
913 spin_lock(&mbim->lock);
914 switch (req->status) {
915 case 0:
Anna Perel68aeb172012-10-28 09:00:45 +0200916 atomic_dec(&mbim->not_port.notify_count);
917 pr_debug("notify_count = %d",
918 atomic_read(&mbim->not_port.notify_count));
Anna Perela8c991d2012-04-09 16:44:46 +0300919 break;
920
921 case -ECONNRESET:
922 case -ESHUTDOWN:
923 /* connection gone */
924 mbim->not_port.notify_state = NCM_NOTIFY_NONE;
925 atomic_set(&mbim->not_port.notify_count, 0);
926 pr_info("ESHUTDOWN/ECONNRESET, connection gone");
Anna Perel86ea7c92012-04-24 14:31:29 +0300927 spin_unlock(&mbim->lock);
928 mbim_clear_queues(mbim);
929 mbim_reset_function_queue(mbim);
Anna Perel89ad1212012-06-13 17:17:24 +0300930 spin_lock(&mbim->lock);
Anna Perela8c991d2012-04-09 16:44:46 +0300931 break;
932 default:
933 pr_err("Unknown event %02x --> %d\n",
934 event->bNotificationType, req->status);
935 break;
936 }
937
Anna Perela8c991d2012-04-09 16:44:46 +0300938 mbim_do_notify(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300939 spin_unlock(&mbim->lock);
940
Anna Perel20c91152012-10-30 16:26:44 +0200941 pr_debug("dev:%p Exit\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300942}
943
944static void mbim_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
945{
946 /* now for SET_NTB_INPUT_SIZE only */
947 unsigned in_size = 0;
948 struct usb_function *f = req->context;
949 struct f_mbim *mbim = func_to_mbim(f);
950 struct mbim_ntb_input_size *ntb = NULL;
951
Anna Perel20c91152012-10-30 16:26:44 +0200952 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300953
954 req->context = NULL;
955 if (req->status || req->actual != req->length) {
956 pr_err("Bad control-OUT transfer\n");
957 goto invalid;
958 }
959
960 if (req->length == 4) {
961 in_size = get_unaligned_le32(req->buf);
962 if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
963 in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
964 pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
965 goto invalid;
966 }
967 } else if (req->length == 8) {
968 ntb = (struct mbim_ntb_input_size *)req->buf;
969 in_size = get_unaligned_le32(&(ntb->ntb_input_size));
970 if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
971 in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
972 pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
973 goto invalid;
974 }
975 mbim->ntb_max_datagrams =
976 get_unaligned_le16(&(ntb->ntb_max_datagrams));
977 } else {
978 pr_err("Illegal NTB length %d\n", in_size);
979 goto invalid;
980 }
981
Anna Perel20c91152012-10-30 16:26:44 +0200982 pr_debug("Set NTB INPUT SIZE %d\n", in_size);
Anna Perela8c991d2012-04-09 16:44:46 +0300983
984 mbim->ntb_input_size = in_size;
985 return;
986
987invalid:
988 usb_ep_set_halt(ep);
989
990 pr_err("dev:%p Failed\n", mbim);
991
992 return;
993}
994
995static void
996fmbim_cmd_complete(struct usb_ep *ep, struct usb_request *req)
997{
998 struct f_mbim *dev = req->context;
999 struct ctrl_pkt *cpkt = NULL;
1000 int len = req->actual;
1001
1002 if (!dev) {
1003 pr_err("mbim dev is null\n");
1004 return;
1005 }
1006
1007 if (req->status < 0) {
1008 pr_err("mbim command error %d\n", req->status);
1009 return;
1010 }
1011
Anna Perel20c91152012-10-30 16:26:44 +02001012 pr_debug("dev:%p port#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +03001013
Anna Perela8c991d2012-04-09 16:44:46 +03001014 cpkt = mbim_alloc_ctrl_pkt(len, GFP_ATOMIC);
1015 if (!cpkt) {
1016 pr_err("Unable to allocate ctrl pkt\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001017 return;
1018 }
1019
Anna Perel20c91152012-10-30 16:26:44 +02001020 pr_debug("Add to cpkt_req_q packet with len = %d\n", len);
Anna Perela8c991d2012-04-09 16:44:46 +03001021 memcpy(cpkt->buf, req->buf, len);
Anna Perel20c91152012-10-30 16:26:44 +02001022
Anna Perel182ab572012-11-18 10:10:12 +02001023 spin_lock(&dev->lock);
1024 if (!dev->is_open) {
1025 pr_err("mbim file handler %p is not open", dev);
1026 spin_unlock(&dev->lock);
1027 mbim_free_ctrl_pkt(cpkt);
1028 return;
1029 }
1030
Anna Perela8c991d2012-04-09 16:44:46 +03001031 list_add_tail(&cpkt->list, &dev->cpkt_req_q);
1032 spin_unlock(&dev->lock);
1033
1034 /* wakeup read thread */
Anna Perel20c91152012-10-30 16:26:44 +02001035 pr_debug("Wake up read queue");
Anna Perela8c991d2012-04-09 16:44:46 +03001036 wake_up(&dev->read_wq);
1037
1038 return;
1039}
1040
1041static int
1042mbim_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
1043{
1044 struct f_mbim *mbim = func_to_mbim(f);
1045 struct usb_composite_dev *cdev = mbim->cdev;
1046 struct usb_request *req = cdev->req;
1047 struct ctrl_pkt *cpkt = NULL;
1048 int value = -EOPNOTSUPP;
1049 u16 w_index = le16_to_cpu(ctrl->wIndex);
1050 u16 w_value = le16_to_cpu(ctrl->wValue);
1051 u16 w_length = le16_to_cpu(ctrl->wLength);
1052
1053 /*
1054 * composite driver infrastructure handles everything except
1055 * CDC class messages; interface activation uses set_alt().
1056 */
1057
1058 if (!atomic_read(&mbim->online)) {
1059 pr_info("usb cable is not connected\n");
1060 return -ENOTCONN;
1061 }
1062
1063 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
1064 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1065 | USB_CDC_RESET_FUNCTION:
1066
Anna Perel20c91152012-10-30 16:26:44 +02001067 pr_debug("USB_CDC_RESET_FUNCTION");
Anna Perela8c991d2012-04-09 16:44:46 +03001068 value = 0;
Anna Perel86ea7c92012-04-24 14:31:29 +03001069 req->complete = fmbim_reset_cmd_complete;
1070 req->context = mbim;
Anna Perela8c991d2012-04-09 16:44:46 +03001071 break;
1072
1073 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1074 | USB_CDC_SEND_ENCAPSULATED_COMMAND:
1075
Anna Perel20c91152012-10-30 16:26:44 +02001076 pr_debug("USB_CDC_SEND_ENCAPSULATED_COMMAND");
Anna Perela8c991d2012-04-09 16:44:46 +03001077
1078 if (w_length > req->length) {
Anna Perel20c91152012-10-30 16:26:44 +02001079 pr_debug("w_length > req->length: %d > %d",
Anna Perela8c991d2012-04-09 16:44:46 +03001080 w_length, req->length);
1081 }
1082 value = w_length;
1083 req->complete = fmbim_cmd_complete;
1084 req->context = mbim;
1085 break;
1086
1087 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1088 | USB_CDC_GET_ENCAPSULATED_RESPONSE:
1089
Anna Perel20c91152012-10-30 16:26:44 +02001090 pr_debug("USB_CDC_GET_ENCAPSULATED_RESPONSE");
Anna Perela8c991d2012-04-09 16:44:46 +03001091
1092 if (w_value) {
1093 pr_err("w_length > 0: %d", w_length);
1094 break;
1095 }
1096
Anna Perel20c91152012-10-30 16:26:44 +02001097 pr_debug("req%02x.%02x v%04x i%04x l%d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001098 ctrl->bRequestType, ctrl->bRequest,
1099 w_value, w_index, w_length);
1100
1101 spin_lock(&mbim->lock);
1102 if (list_empty(&mbim->cpkt_resp_q)) {
1103 pr_err("ctrl resp queue empty\n");
1104 spin_unlock(&mbim->lock);
1105 break;
1106 }
1107
1108 cpkt = list_first_entry(&mbim->cpkt_resp_q,
1109 struct ctrl_pkt, list);
1110 list_del(&cpkt->list);
1111 spin_unlock(&mbim->lock);
1112
1113 value = min_t(unsigned, w_length, cpkt->len);
1114 memcpy(req->buf, cpkt->buf, value);
1115 mbim_free_ctrl_pkt(cpkt);
1116
Anna Perel20c91152012-10-30 16:26:44 +02001117 pr_debug("copied encapsulated_response %d bytes",
Anna Perela8c991d2012-04-09 16:44:46 +03001118 value);
1119
1120 break;
1121
1122 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1123 | USB_CDC_GET_NTB_PARAMETERS:
1124
Anna Perel20c91152012-10-30 16:26:44 +02001125 pr_debug("USB_CDC_GET_NTB_PARAMETERS");
Anna Perela8c991d2012-04-09 16:44:46 +03001126
1127 if (w_length == 0 || w_value != 0 || w_index != mbim->ctrl_id)
1128 break;
1129
1130 value = w_length > sizeof ntb_parameters ?
1131 sizeof ntb_parameters : w_length;
1132 memcpy(req->buf, &ntb_parameters, value);
1133 break;
1134
1135 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1136 | USB_CDC_GET_NTB_INPUT_SIZE:
1137
Anna Perel20c91152012-10-30 16:26:44 +02001138 pr_debug("USB_CDC_GET_NTB_INPUT_SIZE");
Anna Perela8c991d2012-04-09 16:44:46 +03001139
1140 if (w_length < 4 || w_value != 0 || w_index != mbim->ctrl_id)
1141 break;
1142
1143 put_unaligned_le32(mbim->ntb_input_size, req->buf);
1144 value = 4;
Anna Perel20c91152012-10-30 16:26:44 +02001145 pr_debug("Reply to host INPUT SIZE %d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001146 mbim->ntb_input_size);
1147 break;
1148
1149 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1150 | USB_CDC_SET_NTB_INPUT_SIZE:
1151
Anna Perel20c91152012-10-30 16:26:44 +02001152 pr_debug("USB_CDC_SET_NTB_INPUT_SIZE");
Anna Perela8c991d2012-04-09 16:44:46 +03001153
1154 if (w_length != 4 && w_length != 8) {
1155 pr_err("wrong NTB length %d", w_length);
1156 break;
1157 }
1158
1159 if (w_value != 0 || w_index != mbim->ctrl_id)
1160 break;
1161
1162 req->complete = mbim_ep0out_complete;
1163 req->length = w_length;
1164 req->context = f;
1165
1166 value = req->length;
1167 break;
1168
1169 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1170 | USB_CDC_GET_NTB_FORMAT:
1171 {
1172 uint16_t format;
1173
Anna Perel20c91152012-10-30 16:26:44 +02001174 pr_debug("USB_CDC_GET_NTB_FORMAT");
Anna Perela8c991d2012-04-09 16:44:46 +03001175
1176 if (w_length < 2 || w_value != 0 || w_index != mbim->ctrl_id)
1177 break;
1178
1179 format = (mbim->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001;
1180 put_unaligned_le16(format, req->buf);
1181 value = 2;
Anna Perel20c91152012-10-30 16:26:44 +02001182 pr_debug("NTB FORMAT: sending %d\n", format);
Anna Perela8c991d2012-04-09 16:44:46 +03001183 break;
1184 }
1185
1186 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1187 | USB_CDC_SET_NTB_FORMAT:
1188 {
Anna Perel20c91152012-10-30 16:26:44 +02001189 pr_debug("USB_CDC_SET_NTB_FORMAT");
Anna Perela8c991d2012-04-09 16:44:46 +03001190
1191 if (w_length != 0 || w_index != mbim->ctrl_id)
1192 break;
1193 switch (w_value) {
1194 case 0x0000:
1195 mbim->parser_opts = &ndp16_opts;
Anna Perel20c91152012-10-30 16:26:44 +02001196 pr_debug("NCM16 selected\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001197 break;
1198 case 0x0001:
1199 mbim->parser_opts = &ndp32_opts;
Anna Perel20c91152012-10-30 16:26:44 +02001200 pr_debug("NCM32 selected\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001201 break;
1202 default:
1203 break;
1204 }
1205 value = 0;
1206 break;
1207 }
1208
1209 /* optional in mbim descriptor: */
1210 /* case USB_CDC_GET_MAX_DATAGRAM_SIZE: */
1211 /* case USB_CDC_SET_MAX_DATAGRAM_SIZE: */
1212
1213 default:
1214 pr_err("invalid control req: %02x.%02x v%04x i%04x l%d\n",
1215 ctrl->bRequestType, ctrl->bRequest,
1216 w_value, w_index, w_length);
1217 }
1218
1219 /* respond with data transfer or status phase? */
1220 if (value >= 0) {
Anna Perel20c91152012-10-30 16:26:44 +02001221 pr_debug("control request: %02x.%02x v%04x i%04x l%d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001222 ctrl->bRequestType, ctrl->bRequest,
1223 w_value, w_index, w_length);
Anna Perel2dfcaca2012-04-18 17:25:59 +03001224 req->zero = (value < w_length);
Anna Perela8c991d2012-04-09 16:44:46 +03001225 req->length = value;
1226 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
1227 if (value < 0) {
1228 pr_err("queueing req failed: %02x.%02x, err %d\n",
1229 ctrl->bRequestType,
1230 ctrl->bRequest, value);
1231 }
1232 } else {
1233 pr_err("ctrl req err %d: %02x.%02x v%04x i%04x l%d\n",
1234 value, ctrl->bRequestType, ctrl->bRequest,
1235 w_value, w_index, w_length);
1236 }
1237
1238 /* device either stalls (value < 0) or reports success */
1239 return value;
1240}
1241
Jack Pham2df2f702012-10-11 19:08:24 -07001242/*
1243 * This function handles the Microsoft-specific OS descriptor control
1244 * requests that are issued by Windows host drivers to determine the
1245 * configuration containing the MBIM function.
1246 *
1247 * Unlike mbim_setup() this function handles two specific device requests,
1248 * and only when a configuration has not yet been selected.
1249 */
1250static int mbim_ctrlrequest(struct usb_composite_dev *cdev,
1251 const struct usb_ctrlrequest *ctrl)
1252{
1253 int value = -EOPNOTSUPP;
1254 u16 w_index = le16_to_cpu(ctrl->wIndex);
1255 u16 w_value = le16_to_cpu(ctrl->wValue);
1256 u16 w_length = le16_to_cpu(ctrl->wLength);
1257
1258 /* only respond to OS desciptors when no configuration selected */
1259 if (cdev->config || !mbim_ext_config_desc.function.subCompatibleID[0])
1260 return value;
1261
1262 pr_debug("%02x.%02x v%04x i%04x l%u",
1263 ctrl->bRequestType, ctrl->bRequest,
1264 w_value, w_index, w_length);
1265
1266 /* Handle MSFT OS string */
1267 if (ctrl->bRequestType ==
1268 (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)
1269 && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR
1270 && (w_value >> 8) == USB_DT_STRING
1271 && (w_value & 0xFF) == MBIM_OS_STRING_ID) {
1272
1273 value = (w_length < sizeof(mbim_os_string) ?
1274 w_length : sizeof(mbim_os_string));
1275 memcpy(cdev->req->buf, mbim_os_string, value);
1276
1277 } else if (ctrl->bRequestType ==
1278 (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
1279 && ctrl->bRequest == MBIM_VENDOR_CODE && w_index == 4) {
1280
1281 /* Handle Extended OS descriptor */
1282 value = (w_length < sizeof(mbim_ext_config_desc) ?
1283 w_length : sizeof(mbim_ext_config_desc));
1284 memcpy(cdev->req->buf, &mbim_ext_config_desc, value);
1285 }
1286
1287 /* respond with data transfer or status phase? */
1288 if (value >= 0) {
1289 int rc;
1290 cdev->req->zero = value < w_length;
1291 cdev->req->length = value;
1292 rc = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
1293 if (rc < 0)
1294 pr_err("response queue error: %d", rc);
1295 }
1296 return value;
1297}
1298
Anna Perela8c991d2012-04-09 16:44:46 +03001299static int mbim_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
1300{
1301 struct f_mbim *mbim = func_to_mbim(f);
1302 struct usb_composite_dev *cdev = mbim->cdev;
1303 int ret = 0;
1304
1305 /* Control interface has only altsetting 0 */
1306 if (intf == mbim->ctrl_id) {
1307
1308 pr_info("CONTROL_INTERFACE");
1309
1310 if (alt != 0)
1311 goto fail;
1312
1313 if (mbim->not_port.notify->driver_data) {
1314 pr_info("reset mbim control %d\n", intf);
1315 usb_ep_disable(mbim->not_port.notify);
1316 }
1317
1318 ret = config_ep_by_speed(cdev->gadget, f,
1319 mbim->not_port.notify);
1320 if (ret) {
1321 mbim->not_port.notify->desc = NULL;
1322 pr_err("Failed configuring notify ep %s: err %d\n",
1323 mbim->not_port.notify->name, ret);
1324 return ret;
1325 }
1326
1327 ret = usb_ep_enable(mbim->not_port.notify);
1328 if (ret) {
1329 pr_err("usb ep#%s enable failed, err#%d\n",
1330 mbim->not_port.notify->name, ret);
1331 return ret;
1332 }
1333 mbim->not_port.notify->driver_data = mbim;
1334
1335 /* Data interface has two altsettings, 0 and 1 */
1336 } else if (intf == mbim->data_id) {
1337
1338 pr_info("DATA_INTERFACE");
1339
1340 if (alt > 1)
1341 goto fail;
1342
1343 if (mbim->bam_port.in->driver_data) {
1344 pr_info("reset mbim\n");
1345 mbim_reset_values(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +03001346 }
1347
1348 /*
1349 * CDC Network only sends data in non-default altsettings.
1350 * Changing altsettings resets filters, statistics, etc.
1351 */
1352 if (alt == 1) {
1353 pr_info("Alt set 1, initialize ports");
1354
1355 if (!mbim->bam_port.in->desc) {
1356
1357 pr_info("Choose endpoints");
1358
1359 ret = config_ep_by_speed(cdev->gadget, f,
1360 mbim->bam_port.in);
1361 if (ret) {
1362 mbim->bam_port.in->desc = NULL;
1363 pr_err("IN ep %s failed: %d\n",
1364 mbim->bam_port.in->name, ret);
1365 return ret;
1366 }
1367
1368 pr_info("Set mbim port in_desc = 0x%p",
1369 mbim->bam_port.in->desc);
1370
1371 ret = config_ep_by_speed(cdev->gadget, f,
1372 mbim->bam_port.out);
1373 if (ret) {
1374 mbim->bam_port.out->desc = NULL;
1375 pr_err("OUT ep %s failed: %d\n",
1376 mbim->bam_port.out->name, ret);
1377 return ret;
1378 }
1379
1380 pr_info("Set mbim port out_desc = 0x%p",
1381 mbim->bam_port.out->desc);
Anna Perel6637bd72012-10-23 10:53:32 +02001382
1383 pr_debug("Activate mbim\n");
1384 mbim_bam_connect(mbim);
1385
Anna Perela8c991d2012-04-09 16:44:46 +03001386 } else {
1387 pr_info("PORTS already SET");
1388 }
Anna Perela8c991d2012-04-09 16:44:46 +03001389 }
1390
Bar Weinerb1c95f52012-12-23 09:09:13 +02001391 mbim->data_alt_int = alt;
Anna Perela8c991d2012-04-09 16:44:46 +03001392 spin_lock(&mbim->lock);
1393 mbim_notify(mbim);
1394 spin_unlock(&mbim->lock);
1395 } else {
1396 goto fail;
1397 }
1398
1399 atomic_set(&mbim->online, 1);
1400
1401 pr_info("SET DEVICE ONLINE");
1402
1403 /* wakeup file threads */
1404 wake_up(&mbim->read_wq);
1405 wake_up(&mbim->write_wq);
1406
1407 return 0;
1408
1409fail:
1410 pr_err("ERROR: Illegal Interface");
1411 return -EINVAL;
1412}
1413
1414/*
1415 * Because the data interface supports multiple altsettings,
1416 * this MBIM function *MUST* implement a get_alt() method.
1417 */
1418static int mbim_get_alt(struct usb_function *f, unsigned intf)
1419{
1420 struct f_mbim *mbim = func_to_mbim(f);
1421
1422 if (intf == mbim->ctrl_id)
1423 return 0;
Bar Weinerb1c95f52012-12-23 09:09:13 +02001424 else if (intf == mbim->data_id)
1425 return mbim->data_alt_int;
1426
1427 return -EINVAL;
Anna Perela8c991d2012-04-09 16:44:46 +03001428}
1429
1430static void mbim_disable(struct usb_function *f)
1431{
1432 struct f_mbim *mbim = func_to_mbim(f);
1433
1434 pr_info("SET DEVICE OFFLINE");
1435 atomic_set(&mbim->online, 0);
1436
Ido Shayevitzbadc8ea2013-02-06 14:14:54 +02001437 mbim->not_port.notify_state = NCM_NOTIFY_NONE;
1438
Anna Perel86ea7c92012-04-24 14:31:29 +03001439 mbim_clear_queues(mbim);
1440 mbim_reset_function_queue(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +03001441
1442 mbim_bam_disconnect(mbim);
1443
1444 if (mbim->not_port.notify->driver_data) {
1445 usb_ep_disable(mbim->not_port.notify);
1446 mbim->not_port.notify->driver_data = NULL;
1447 }
1448
Anna Perel68aeb172012-10-28 09:00:45 +02001449 atomic_set(&mbim->not_port.notify_count, 0);
1450
Anna Perela8c991d2012-04-09 16:44:46 +03001451 pr_info("mbim deactivated\n");
1452}
1453
Anna Perel557bf722012-09-20 11:16:35 +03001454#define MBIM_ACTIVE_PORT 0
1455
1456static void mbim_suspend(struct usb_function *f)
1457{
1458 pr_info("mbim suspended\n");
1459 bam_data_suspend(MBIM_ACTIVE_PORT);
1460}
1461
1462static void mbim_resume(struct usb_function *f)
1463{
1464 pr_info("mbim resumed\n");
1465 bam_data_resume(MBIM_ACTIVE_PORT);
1466}
1467
Anna Perela8c991d2012-04-09 16:44:46 +03001468/*---------------------- function driver setup/binding ---------------------*/
1469
1470static int
1471mbim_bind(struct usb_configuration *c, struct usb_function *f)
1472{
1473 struct usb_composite_dev *cdev = c->cdev;
1474 struct f_mbim *mbim = func_to_mbim(f);
1475 int status;
1476 struct usb_ep *ep;
1477
1478 pr_info("Enter");
1479
1480 mbim->cdev = cdev;
1481
1482 /* allocate instance-specific interface IDs */
1483 status = usb_interface_id(c, f);
1484 if (status < 0)
1485 goto fail;
1486 mbim->ctrl_id = status;
1487 mbim_iad_desc.bFirstInterface = status;
1488
1489 mbim_control_intf.bInterfaceNumber = status;
1490 mbim_union_desc.bMasterInterface0 = status;
1491
1492 status = usb_interface_id(c, f);
1493 if (status < 0)
1494 goto fail;
1495 mbim->data_id = status;
Bar Weinerb1c95f52012-12-23 09:09:13 +02001496 mbim->data_alt_int = 0;
Anna Perela8c991d2012-04-09 16:44:46 +03001497
1498 mbim_data_nop_intf.bInterfaceNumber = status;
1499 mbim_data_intf.bInterfaceNumber = status;
1500 mbim_union_desc.bSlaveInterface0 = status;
1501
Anna Perel557bf722012-09-20 11:16:35 +03001502 mbim->bam_port.cdev = cdev;
1503
Anna Perela8c991d2012-04-09 16:44:46 +03001504 status = -ENODEV;
1505
1506 /* allocate instance-specific endpoints */
1507 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_in_desc);
1508 if (!ep) {
1509 pr_err("usb epin autoconfig failed\n");
1510 goto fail;
1511 }
1512 pr_info("usb epin autoconfig succeeded\n");
1513 ep->driver_data = cdev; /* claim */
1514 mbim->bam_port.in = ep;
1515
1516 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_out_desc);
1517 if (!ep) {
1518 pr_err("usb epout autoconfig failed\n");
1519 goto fail;
1520 }
1521 pr_info("usb epout autoconfig succeeded\n");
1522 ep->driver_data = cdev; /* claim */
1523 mbim->bam_port.out = ep;
1524
1525 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_notify_desc);
1526 if (!ep) {
1527 pr_err("usb notify ep autoconfig failed\n");
1528 goto fail;
1529 }
1530 pr_info("usb notify ep autoconfig succeeded\n");
1531 mbim->not_port.notify = ep;
1532 ep->driver_data = cdev; /* claim */
1533
1534 status = -ENOMEM;
1535
1536 /* allocate notification request and buffer */
1537 mbim->not_port.notify_req = mbim_alloc_req(ep, NCM_STATUS_BYTECOUNT);
1538 if (!mbim->not_port.notify_req) {
1539 pr_info("failed to allocate notify request\n");
1540 goto fail;
1541 }
1542 pr_info("allocated notify ep request & request buffer\n");
1543
1544 mbim->not_port.notify_req->context = mbim;
1545 mbim->not_port.notify_req->complete = mbim_notify_complete;
1546
1547 /* copy descriptors, and track endpoint copies */
1548 f->descriptors = usb_copy_descriptors(mbim_fs_function);
1549 if (!f->descriptors)
1550 goto fail;
1551
1552 /*
1553 * support all relevant hardware speeds... we expect that when
1554 * hardware is dual speed, all bulk-capable endpoints work at
1555 * both speeds
1556 */
1557 if (gadget_is_dualspeed(c->cdev->gadget)) {
1558 hs_mbim_in_desc.bEndpointAddress =
1559 fs_mbim_in_desc.bEndpointAddress;
1560 hs_mbim_out_desc.bEndpointAddress =
1561 fs_mbim_out_desc.bEndpointAddress;
1562 hs_mbim_notify_desc.bEndpointAddress =
1563 fs_mbim_notify_desc.bEndpointAddress;
1564
1565 /* copy descriptors, and track endpoint copies */
1566 f->hs_descriptors = usb_copy_descriptors(mbim_hs_function);
1567 if (!f->hs_descriptors)
1568 goto fail;
1569 }
1570
Jack Pham2df2f702012-10-11 19:08:24 -07001571 /*
1572 * If MBIM is bound in a config other than the first, tell Windows
1573 * about it by returning the num as a string in the OS descriptor's
1574 * subCompatibleID field. Windows only supports up to config #4.
1575 */
1576 if (c->bConfigurationValue >= 2 && c->bConfigurationValue <= 4) {
1577 pr_debug("MBIM in configuration %d", c->bConfigurationValue);
1578 mbim_ext_config_desc.function.subCompatibleID[0] =
1579 c->bConfigurationValue + '0';
1580 }
1581
Anna Perela8c991d2012-04-09 16:44:46 +03001582 pr_info("mbim(%d): %s speed IN/%s OUT/%s NOTIFY/%s\n",
1583 mbim->port_num,
1584 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
1585 mbim->bam_port.in->name, mbim->bam_port.out->name,
1586 mbim->not_port.notify->name);
1587
1588 return 0;
1589
1590fail:
1591 pr_err("%s failed to bind, err %d\n", f->name, status);
1592
1593 if (f->descriptors)
1594 usb_free_descriptors(f->descriptors);
1595
1596 if (mbim->not_port.notify_req) {
1597 kfree(mbim->not_port.notify_req->buf);
1598 usb_ep_free_request(mbim->not_port.notify,
1599 mbim->not_port.notify_req);
1600 }
1601
1602 /* we might as well release our claims on endpoints */
1603 if (mbim->not_port.notify)
1604 mbim->not_port.notify->driver_data = NULL;
1605 if (mbim->bam_port.out)
1606 mbim->bam_port.out->driver_data = NULL;
1607 if (mbim->bam_port.in)
1608 mbim->bam_port.in->driver_data = NULL;
1609
1610 return status;
1611}
1612
1613static void mbim_unbind(struct usb_configuration *c, struct usb_function *f)
1614{
1615 struct f_mbim *mbim = func_to_mbim(f);
1616
1617 if (gadget_is_dualspeed(c->cdev->gadget))
1618 usb_free_descriptors(f->hs_descriptors);
1619 usb_free_descriptors(f->descriptors);
1620
1621 kfree(mbim->not_port.notify_req->buf);
1622 usb_ep_free_request(mbim->not_port.notify, mbim->not_port.notify_req);
Jack Pham2df2f702012-10-11 19:08:24 -07001623
1624 mbim_ext_config_desc.function.subCompatibleID[0] = 0;
Anna Perela8c991d2012-04-09 16:44:46 +03001625}
1626
1627/**
1628 * mbim_bind_config - add MBIM link to a configuration
1629 * @c: the configuration to support the network link
1630 * Context: single threaded during gadget setup
1631 * Returns zero on success, else negative errno.
1632 */
Lena Salmandf7e7992013-03-15 09:46:27 +02001633int mbim_bind_config(struct usb_configuration *c, unsigned portno,
1634 char *xport_name)
Anna Perela8c991d2012-04-09 16:44:46 +03001635{
1636 struct f_mbim *mbim = NULL;
1637 int status = 0;
1638
1639 pr_info("port number %u", portno);
1640
1641 if (portno >= nr_mbim_ports) {
1642 pr_err("Can not add port %u. Max ports = %d",
1643 portno, nr_mbim_ports);
1644 return -ENODEV;
1645 }
1646
1647 status = mbim_bam_setup(nr_mbim_ports);
1648 if (status) {
1649 pr_err("bam setup failed");
1650 return status;
1651 }
1652
1653 /* maybe allocate device-global string IDs */
1654 if (mbim_string_defs[0].id == 0) {
1655
1656 /* control interface label */
1657 status = usb_string_id(c->cdev);
1658 if (status < 0)
1659 return status;
1660 mbim_string_defs[STRING_CTRL_IDX].id = status;
1661 mbim_control_intf.iInterface = status;
1662
1663 /* data interface label */
1664 status = usb_string_id(c->cdev);
1665 if (status < 0)
1666 return status;
1667 mbim_string_defs[STRING_DATA_IDX].id = status;
1668 mbim_data_nop_intf.iInterface = status;
1669 mbim_data_intf.iInterface = status;
1670 }
1671
1672 /* allocate and initialize one new instance */
1673 mbim = mbim_ports[0].port;
1674 if (!mbim) {
1675 pr_info("mbim struct not allocated");
1676 return -ENOMEM;
1677 }
1678
1679 mbim->cdev = c->cdev;
1680
Anna Perela8c991d2012-04-09 16:44:46 +03001681 mbim_reset_values(mbim);
1682
1683 mbim->function.name = "usb_mbim";
1684 mbim->function.strings = mbim_strings;
1685 mbim->function.bind = mbim_bind;
1686 mbim->function.unbind = mbim_unbind;
1687 mbim->function.set_alt = mbim_set_alt;
1688 mbim->function.get_alt = mbim_get_alt;
1689 mbim->function.setup = mbim_setup;
1690 mbim->function.disable = mbim_disable;
Anna Perel557bf722012-09-20 11:16:35 +03001691 mbim->function.suspend = mbim_suspend;
1692 mbim->function.resume = mbim_resume;
Lena Salmandf7e7992013-03-15 09:46:27 +02001693 mbim->xport = str_to_xport(xport_name);
1694
1695 if (mbim->xport != USB_GADGET_XPORT_BAM2BAM_IPA) {
1696 /* Use BAM2BAM by default if not IPA */
1697 mbim->xport = USB_GADGET_XPORT_BAM2BAM;
1698 } else {
1699 /* For IPA we use limit of 16 */
1700 ntb_parameters.wNtbOutMaxDatagrams = 16;
1701 /* For IPA this is proven to give maximum throughput */
1702 ntb_parameters.dwNtbInMaxSize =
1703 cpu_to_le32(NTB_DEFAULT_IN_SIZE_IPA);
1704 ntb_parameters.dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE_IPA);
1705 }
Anna Perela8c991d2012-04-09 16:44:46 +03001706
1707 INIT_LIST_HEAD(&mbim->cpkt_req_q);
1708 INIT_LIST_HEAD(&mbim->cpkt_resp_q);
1709
1710 status = usb_add_function(c, &mbim->function);
1711
1712 pr_info("Exit status %d", status);
1713
1714 return status;
1715}
1716
1717/* ------------ MBIM DRIVER File Operations API for USER SPACE ------------ */
1718
1719static ssize_t
1720mbim_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
1721{
1722 struct f_mbim *dev = fp->private_data;
1723 struct ctrl_pkt *cpkt = NULL;
1724 int ret = 0;
1725
1726 pr_debug("Enter(%d)\n", count);
1727
1728 if (!dev) {
1729 pr_err("Received NULL mbim pointer\n");
1730 return -ENODEV;
1731 }
1732
1733 if (count > MBIM_BULK_BUFFER_SIZE) {
1734 pr_err("Buffer size is too big %d, should be at most %d\n",
1735 count, MBIM_BULK_BUFFER_SIZE);
1736 return -EINVAL;
1737 }
1738
1739 if (mbim_lock(&dev->read_excl)) {
1740 pr_err("Previous reading is not finished yet\n");
1741 return -EBUSY;
1742 }
1743
1744 /* block until mbim online */
1745 while (!(atomic_read(&dev->online) || atomic_read(&dev->error))) {
1746 pr_err("USB cable not connected. Wait.\n");
1747 ret = wait_event_interruptible(dev->read_wq,
1748 (atomic_read(&dev->online) ||
1749 atomic_read(&dev->error)));
1750 if (ret < 0) {
1751 mbim_unlock(&dev->read_excl);
Anna Perel96eea9d2012-12-09 14:08:04 +02001752 return -ERESTARTSYS;
Anna Perela8c991d2012-04-09 16:44:46 +03001753 }
1754 }
1755
1756 if (atomic_read(&dev->error)) {
1757 mbim_unlock(&dev->read_excl);
1758 return -EIO;
1759 }
1760
1761 while (list_empty(&dev->cpkt_req_q)) {
Anna Perel3747fdae2013-02-17 15:19:04 +02001762 pr_debug("Requests list is empty. Wait.\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001763 ret = wait_event_interruptible(dev->read_wq,
1764 !list_empty(&dev->cpkt_req_q));
1765 if (ret < 0) {
1766 pr_err("Waiting failed\n");
1767 mbim_unlock(&dev->read_excl);
Anna Perel96eea9d2012-12-09 14:08:04 +02001768 return -ERESTARTSYS;
Anna Perela8c991d2012-04-09 16:44:46 +03001769 }
1770 pr_debug("Received request packet\n");
1771 }
1772
1773 cpkt = list_first_entry(&dev->cpkt_req_q, struct ctrl_pkt,
1774 list);
1775 if (cpkt->len > count) {
1776 mbim_unlock(&dev->read_excl);
1777 pr_err("cpkt size too big:%d > buf size:%d\n",
1778 cpkt->len, count);
1779 return -ENOMEM;
1780 }
1781
1782 pr_debug("cpkt size:%d\n", cpkt->len);
1783
1784 list_del(&cpkt->list);
1785 mbim_unlock(&dev->read_excl);
1786
1787 ret = copy_to_user(buf, cpkt->buf, cpkt->len);
1788 if (ret) {
1789 pr_err("copy_to_user failed: err %d\n", ret);
Anna Perel96eea9d2012-12-09 14:08:04 +02001790 ret = -ENOMEM;
Anna Perela8c991d2012-04-09 16:44:46 +03001791 } else {
1792 pr_debug("copied %d bytes to user\n", cpkt->len);
1793 ret = cpkt->len;
1794 }
1795
1796 mbim_free_ctrl_pkt(cpkt);
1797
1798 return ret;
1799}
1800
1801static ssize_t
1802mbim_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos)
1803{
1804 struct f_mbim *dev = fp->private_data;
1805 struct ctrl_pkt *cpkt = NULL;
1806 int ret = 0;
1807
1808 pr_debug("Enter(%d)", count);
1809
1810 if (!dev) {
1811 pr_err("Received NULL mbim pointer\n");
1812 return -ENODEV;
1813 }
1814
1815 if (!count) {
1816 pr_err("zero length ctrl pkt\n");
1817 return -ENODEV;
1818 }
1819
1820 if (count > MAX_CTRL_PKT_SIZE) {
1821 pr_err("given pkt size too big:%d > max_pkt_size:%d\n",
1822 count, MAX_CTRL_PKT_SIZE);
1823 return -ENOMEM;
1824 }
1825
1826 if (mbim_lock(&dev->write_excl)) {
1827 pr_err("Previous writing not finished yet\n");
1828 return -EBUSY;
1829 }
1830
1831 if (!atomic_read(&dev->online)) {
1832 pr_err("USB cable not connected\n");
1833 mbim_unlock(&dev->write_excl);
1834 return -EPIPE;
1835 }
1836
1837 cpkt = mbim_alloc_ctrl_pkt(count, GFP_KERNEL);
1838 if (!cpkt) {
1839 pr_err("failed to allocate ctrl pkt\n");
1840 mbim_unlock(&dev->write_excl);
1841 return -ENOMEM;
1842 }
1843
1844 ret = copy_from_user(cpkt->buf, buf, count);
1845 if (ret) {
1846 pr_err("copy_from_user failed err:%d\n", ret);
1847 mbim_free_ctrl_pkt(cpkt);
1848 mbim_unlock(&dev->write_excl);
1849 return 0;
1850 }
1851
1852 fmbim_send_cpkt_response(dev, cpkt);
1853
1854 mbim_unlock(&dev->write_excl);
1855
1856 pr_debug("Exit(%d)", count);
1857
1858 return count;
Anna Perel89ad1212012-06-13 17:17:24 +03001859
Anna Perela8c991d2012-04-09 16:44:46 +03001860}
1861
1862static int mbim_open(struct inode *ip, struct file *fp)
1863{
1864 pr_info("Open mbim driver\n");
1865
1866 while (!_mbim_dev) {
1867 pr_err("mbim_dev not created yet\n");
1868 return -ENODEV;
1869 }
1870
1871 if (mbim_lock(&_mbim_dev->open_excl)) {
1872 pr_err("Already opened\n");
1873 return -EBUSY;
1874 }
1875
1876 pr_info("Lock mbim_dev->open_excl for open\n");
1877
1878 if (!atomic_read(&_mbim_dev->online))
1879 pr_err("USB cable not connected\n");
1880
Anna Perela8c991d2012-04-09 16:44:46 +03001881 fp->private_data = _mbim_dev;
1882
1883 atomic_set(&_mbim_dev->error, 0);
1884
1885 spin_lock(&_mbim_dev->lock);
1886 _mbim_dev->is_open = true;
Anna Perela8c991d2012-04-09 16:44:46 +03001887 spin_unlock(&_mbim_dev->lock);
1888
1889 pr_info("Exit, mbim file opened\n");
1890
1891 return 0;
1892}
1893
1894static int mbim_release(struct inode *ip, struct file *fp)
1895{
1896 struct f_mbim *mbim = fp->private_data;
1897
1898 pr_info("Close mbim file");
1899
1900 spin_lock(&mbim->lock);
1901 mbim->is_open = false;
Anna Perela8c991d2012-04-09 16:44:46 +03001902 spin_unlock(&mbim->lock);
1903
Anna Perela8c991d2012-04-09 16:44:46 +03001904 mbim_unlock(&_mbim_dev->open_excl);
1905
1906 return 0;
1907}
1908
1909static long mbim_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
1910{
1911 struct f_mbim *mbim = fp->private_data;
1912 int ret = 0;
1913
Anna Perel20c91152012-10-30 16:26:44 +02001914 pr_debug("Received command %d", cmd);
Anna Perela8c991d2012-04-09 16:44:46 +03001915
1916 if (mbim_lock(&mbim->ioctl_excl))
1917 return -EBUSY;
1918
1919 switch (cmd) {
1920 case MBIM_GET_NTB_SIZE:
1921 ret = copy_to_user((void __user *)arg,
1922 &mbim->ntb_input_size, sizeof(mbim->ntb_input_size));
1923 if (ret) {
1924 pr_err("copying to user space failed");
1925 ret = -EFAULT;
1926 }
1927 pr_info("Sent NTB size %d", mbim->ntb_input_size);
1928 break;
1929 case MBIM_GET_DATAGRAM_COUNT:
1930 ret = copy_to_user((void __user *)arg,
1931 &mbim->ntb_max_datagrams,
1932 sizeof(mbim->ntb_max_datagrams));
1933 if (ret) {
1934 pr_err("copying to user space failed");
1935 ret = -EFAULT;
1936 }
1937 pr_info("Sent NTB datagrams count %d",
1938 mbim->ntb_max_datagrams);
1939 break;
1940 default:
1941 pr_err("wrong parameter");
1942 ret = -EINVAL;
1943 }
1944
1945 mbim_unlock(&mbim->ioctl_excl);
1946
1947 return ret;
1948}
1949
1950/* file operations for MBIM device /dev/android_mbim */
1951static const struct file_operations mbim_fops = {
1952 .owner = THIS_MODULE,
1953 .open = mbim_open,
1954 .release = mbim_release,
1955 .read = mbim_read,
1956 .write = mbim_write,
1957 .unlocked_ioctl = mbim_ioctl,
1958};
1959
1960static struct miscdevice mbim_device = {
1961 .minor = MISC_DYNAMIC_MINOR,
1962 .name = "android_mbim",
1963 .fops = &mbim_fops,
1964};
1965
1966static int mbim_init(int instances)
1967{
1968 int i;
1969 struct f_mbim *dev = NULL;
1970 int ret;
1971
1972 pr_info("initialize %d instances\n", instances);
1973
1974 if (instances > NR_MBIM_PORTS) {
1975 pr_err("Max-%d instances supported\n", NR_MBIM_PORTS);
1976 return -EINVAL;
1977 }
1978
1979 for (i = 0; i < instances; i++) {
1980 dev = kzalloc(sizeof(struct f_mbim), GFP_KERNEL);
1981 if (!dev) {
1982 pr_err("Failed to allocate mbim dev\n");
1983 ret = -ENOMEM;
1984 goto fail_probe;
1985 }
1986
1987 dev->port_num = i;
1988 spin_lock_init(&dev->lock);
1989 INIT_LIST_HEAD(&dev->cpkt_req_q);
1990 INIT_LIST_HEAD(&dev->cpkt_resp_q);
1991
1992 mbim_ports[i].port = dev;
1993 mbim_ports[i].port_num = i;
1994
1995 init_waitqueue_head(&dev->read_wq);
1996 init_waitqueue_head(&dev->write_wq);
1997
1998 atomic_set(&dev->open_excl, 0);
1999 atomic_set(&dev->ioctl_excl, 0);
2000 atomic_set(&dev->read_excl, 0);
2001 atomic_set(&dev->write_excl, 0);
2002
2003 nr_mbim_ports++;
2004
2005 }
2006
2007 _mbim_dev = dev;
2008 ret = misc_register(&mbim_device);
2009 if (ret) {
2010 pr_err("mbim driver failed to register");
2011 goto fail_probe;
2012 }
2013
2014 pr_info("Initialized %d ports\n", nr_mbim_ports);
2015
2016 return ret;
2017
2018fail_probe:
2019 pr_err("Failed");
2020 for (i = 0; i < nr_mbim_ports; i++) {
2021 kfree(mbim_ports[i].port);
2022 mbim_ports[i].port = NULL;
2023 }
2024
2025 return ret;
2026}
2027
2028static void fmbim_cleanup(void)
2029{
2030 int i = 0;
2031
2032 pr_info("Enter");
2033
2034 for (i = 0; i < nr_mbim_ports; i++) {
2035 kfree(mbim_ports[i].port);
2036 mbim_ports[i].port = NULL;
2037 }
2038 nr_mbim_ports = 0;
2039
2040 misc_deregister(&mbim_device);
2041
2042 _mbim_dev = NULL;
2043}
2044