blob: daa981ff49cd2f6714a7297258a26449a52113bf [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2012, 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,
69};
70
71struct f_mbim {
Anna Perel557bf722012-09-20 11:16:35 +030072 struct usb_function function;
73 struct usb_composite_dev *cdev;
Anna Perela8c991d2012-04-09 16:44:46 +030074
75 atomic_t online;
76 bool is_open;
77
78 atomic_t open_excl;
79 atomic_t ioctl_excl;
80 atomic_t read_excl;
81 atomic_t write_excl;
82
83 wait_queue_head_t read_wq;
84 wait_queue_head_t write_wq;
85
86 u8 port_num;
87 struct data_port bam_port;
88 struct mbim_notify_port not_port;
89
90 struct mbim_ep_descs fs;
91 struct mbim_ep_descs hs;
92
93 u8 ctrl_id, data_id;
Bar Weinerb1c95f52012-12-23 09:09:13 +020094 u8 data_alt_int;
Anna Perela8c991d2012-04-09 16:44:46 +030095
96 struct ndp_parser_opts *parser_opts;
97
98 spinlock_t lock;
99
100 struct list_head cpkt_req_q;
101 struct list_head cpkt_resp_q;
102
103 u32 ntb_input_size;
104 u16 ntb_max_datagrams;
105
Anna Perela8c991d2012-04-09 16:44:46 +0300106 atomic_t error;
107};
108
109struct mbim_ntb_input_size {
110 u32 ntb_input_size;
111 u16 ntb_max_datagrams;
112 u16 reserved;
113};
114
115/* temporary variable used between mbim_open() and mbim_gadget_bind() */
116static struct f_mbim *_mbim_dev;
117
118static unsigned int nr_mbim_ports;
119
120static struct mbim_ports {
121 struct f_mbim *port;
122 unsigned port_num;
123} mbim_ports[NR_MBIM_PORTS];
124
125static inline struct f_mbim *func_to_mbim(struct usb_function *f)
126{
127 return container_of(f, struct f_mbim, function);
128}
129
130/* peak (theoretical) bulk transfer rate in bits-per-second */
131static inline unsigned mbim_bitrate(struct usb_gadget *g)
132{
133 if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
134 return 13 * 512 * 8 * 1000 * 8;
135 else
136 return 19 * 64 * 1 * 1000 * 8;
137}
138
139/*-------------------------------------------------------------------------*/
140
141#define NTB_DEFAULT_IN_SIZE (0x4000)
142#define NTB_OUT_SIZE (0x1000)
143#define NDP_IN_DIVISOR (0x4)
144
145#define FORMATS_SUPPORTED USB_CDC_NCM_NTB16_SUPPORTED
146
147static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
148 .wLength = sizeof ntb_parameters,
149 .bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
150 .dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
151 .wNdpInDivisor = cpu_to_le16(NDP_IN_DIVISOR),
152 .wNdpInPayloadRemainder = cpu_to_le16(0),
153 .wNdpInAlignment = cpu_to_le16(4),
154
155 .dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE),
156 .wNdpOutDivisor = cpu_to_le16(4),
157 .wNdpOutPayloadRemainder = cpu_to_le16(0),
158 .wNdpOutAlignment = cpu_to_le16(4),
Anna Perelf99cd0c2012-05-03 13:30:26 +0300159 .wNtbOutMaxDatagrams = 0,
Anna Perela8c991d2012-04-09 16:44:46 +0300160};
161
162/*
163 * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
164 * packet, to simplify cancellation; and a big transfer interval, to
165 * waste less bandwidth.
166 */
167
168#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
169#define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
170
171static struct usb_interface_assoc_descriptor mbim_iad_desc = {
172 .bLength = sizeof mbim_iad_desc,
173 .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
174
175 /* .bFirstInterface = DYNAMIC, */
176 .bInterfaceCount = 2, /* control + data */
177 .bFunctionClass = 2,
178 .bFunctionSubClass = 0x0e,
179 .bFunctionProtocol = 0,
180 /* .iFunction = DYNAMIC */
181};
182
183/* interface descriptor: */
184static struct usb_interface_descriptor mbim_control_intf = {
185 .bLength = sizeof mbim_control_intf,
186 .bDescriptorType = USB_DT_INTERFACE,
187
188 /* .bInterfaceNumber = DYNAMIC */
189 .bNumEndpoints = 1,
190 .bInterfaceClass = 0x02,
191 .bInterfaceSubClass = 0x0e,
192 .bInterfaceProtocol = 0,
193 /* .iInterface = DYNAMIC */
194};
195
196static struct usb_cdc_header_desc mbim_header_desc = {
197 .bLength = sizeof mbim_header_desc,
198 .bDescriptorType = USB_DT_CS_INTERFACE,
199 .bDescriptorSubType = USB_CDC_HEADER_TYPE,
200
201 .bcdCDC = cpu_to_le16(0x0110),
202};
203
204static struct usb_cdc_union_desc mbim_union_desc = {
205 .bLength = sizeof(mbim_union_desc),
206 .bDescriptorType = USB_DT_CS_INTERFACE,
207 .bDescriptorSubType = USB_CDC_UNION_TYPE,
208 /* .bMasterInterface0 = DYNAMIC */
209 /* .bSlaveInterface0 = DYNAMIC */
210};
211
212static struct usb_cdc_mbb_desc mbb_desc = {
213 .bLength = sizeof mbb_desc,
214 .bDescriptorType = USB_DT_CS_INTERFACE,
215 .bDescriptorSubType = USB_CDC_MBB_TYPE,
216
217 .bcdMbbVersion = cpu_to_le16(0x0100),
218
219 .wMaxControlMessage = cpu_to_le16(0x1000),
Anna Perel3354bdc2012-12-09 12:08:10 +0200220 .bNumberFilters = 0x20,
Anna Perela8c991d2012-04-09 16:44:46 +0300221 .bMaxFilterSize = 0x80,
Anna Perel26ae27c2012-05-23 18:07:31 +0300222 .wMaxSegmentSize = cpu_to_le16(0xfe0),
Anna Perela8c991d2012-04-09 16:44:46 +0300223 .bmNetworkCapabilities = 0x20,
224};
225
226/* the default data interface has no endpoints ... */
227static struct usb_interface_descriptor mbim_data_nop_intf = {
228 .bLength = sizeof mbim_data_nop_intf,
229 .bDescriptorType = USB_DT_INTERFACE,
230
231 /* .bInterfaceNumber = DYNAMIC */
232 .bAlternateSetting = 0,
233 .bNumEndpoints = 0,
234 .bInterfaceClass = 0x0a,
235 .bInterfaceSubClass = 0,
236 .bInterfaceProtocol = 0x02,
237 /* .iInterface = DYNAMIC */
238};
239
240/* ... but the "real" data interface has two bulk endpoints */
241static struct usb_interface_descriptor mbim_data_intf = {
242 .bLength = sizeof mbim_data_intf,
243 .bDescriptorType = USB_DT_INTERFACE,
244
245 /* .bInterfaceNumber = DYNAMIC */
246 .bAlternateSetting = 1,
247 .bNumEndpoints = 2,
248 .bInterfaceClass = 0x0a,
249 .bInterfaceSubClass = 0,
250 .bInterfaceProtocol = 0x02,
251 /* .iInterface = DYNAMIC */
252};
253
254/* full speed support: */
255
256static struct usb_endpoint_descriptor fs_mbim_notify_desc = {
257 .bLength = USB_DT_ENDPOINT_SIZE,
258 .bDescriptorType = USB_DT_ENDPOINT,
259
260 .bEndpointAddress = USB_DIR_IN,
261 .bmAttributes = USB_ENDPOINT_XFER_INT,
262 .wMaxPacketSize = 4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
263 .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
264};
265
266static struct usb_endpoint_descriptor fs_mbim_in_desc = {
267 .bLength = USB_DT_ENDPOINT_SIZE,
268 .bDescriptorType = USB_DT_ENDPOINT,
269
270 .bEndpointAddress = USB_DIR_IN,
271 .bmAttributes = USB_ENDPOINT_XFER_BULK,
272};
273
274static struct usb_endpoint_descriptor fs_mbim_out_desc = {
275 .bLength = USB_DT_ENDPOINT_SIZE,
276 .bDescriptorType = USB_DT_ENDPOINT,
277
278 .bEndpointAddress = USB_DIR_OUT,
279 .bmAttributes = USB_ENDPOINT_XFER_BULK,
280};
281
282static struct usb_descriptor_header *mbim_fs_function[] = {
283 (struct usb_descriptor_header *) &mbim_iad_desc,
284 /* MBIM control descriptors */
285 (struct usb_descriptor_header *) &mbim_control_intf,
286 (struct usb_descriptor_header *) &mbim_header_desc,
287 (struct usb_descriptor_header *) &mbb_desc,
288 (struct usb_descriptor_header *) &fs_mbim_notify_desc,
289 /* data interface, altsettings 0 and 1 */
290 (struct usb_descriptor_header *) &mbim_data_nop_intf,
291 (struct usb_descriptor_header *) &mbim_data_intf,
292 (struct usb_descriptor_header *) &fs_mbim_in_desc,
293 (struct usb_descriptor_header *) &fs_mbim_out_desc,
294 NULL,
295};
296
297/* high speed support: */
298
299static struct usb_endpoint_descriptor hs_mbim_notify_desc = {
300 .bLength = USB_DT_ENDPOINT_SIZE,
301 .bDescriptorType = USB_DT_ENDPOINT,
302
303 .bEndpointAddress = USB_DIR_IN,
304 .bmAttributes = USB_ENDPOINT_XFER_INT,
305 .wMaxPacketSize = 4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
306 .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
307};
308static struct usb_endpoint_descriptor hs_mbim_in_desc = {
309 .bLength = USB_DT_ENDPOINT_SIZE,
310 .bDescriptorType = USB_DT_ENDPOINT,
311
312 .bEndpointAddress = USB_DIR_IN,
313 .bmAttributes = USB_ENDPOINT_XFER_BULK,
314 .wMaxPacketSize = cpu_to_le16(512),
315};
316
317static struct usb_endpoint_descriptor hs_mbim_out_desc = {
318 .bLength = USB_DT_ENDPOINT_SIZE,
319 .bDescriptorType = USB_DT_ENDPOINT,
320
321 .bEndpointAddress = USB_DIR_OUT,
322 .bmAttributes = USB_ENDPOINT_XFER_BULK,
323 .wMaxPacketSize = cpu_to_le16(512),
324};
325
326static struct usb_descriptor_header *mbim_hs_function[] = {
327 (struct usb_descriptor_header *) &mbim_iad_desc,
328 /* MBIM control descriptors */
329 (struct usb_descriptor_header *) &mbim_control_intf,
330 (struct usb_descriptor_header *) &mbim_header_desc,
331 (struct usb_descriptor_header *) &mbb_desc,
332 (struct usb_descriptor_header *) &hs_mbim_notify_desc,
333 /* data interface, altsettings 0 and 1 */
334 (struct usb_descriptor_header *) &mbim_data_nop_intf,
335 (struct usb_descriptor_header *) &mbim_data_intf,
336 (struct usb_descriptor_header *) &hs_mbim_in_desc,
337 (struct usb_descriptor_header *) &hs_mbim_out_desc,
338 NULL,
339};
340
341/* string descriptors: */
342
343#define STRING_CTRL_IDX 0
344#define STRING_DATA_IDX 1
345
346static struct usb_string mbim_string_defs[] = {
347 [STRING_CTRL_IDX].s = "MBIM Control",
348 [STRING_DATA_IDX].s = "MBIM Data",
349 { } /* end of list */
350};
351
352static struct usb_gadget_strings mbim_string_table = {
353 .language = 0x0409, /* en-us */
354 .strings = mbim_string_defs,
355};
356
357static struct usb_gadget_strings *mbim_strings[] = {
358 &mbim_string_table,
359 NULL,
360};
361
Jack Pham2df2f702012-10-11 19:08:24 -0700362/* Microsoft OS Descriptors */
363
364/*
365 * We specify our own bMS_VendorCode byte which Windows will use
366 * as the bRequest value in subsequent device get requests.
367 */
368#define MBIM_VENDOR_CODE 0xA5
369
370/* Microsoft OS String */
371static u8 mbim_os_string[] = {
372 18, /* sizeof(mtp_os_string) */
373 USB_DT_STRING,
374 /* Signature field: "MSFT100" */
375 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0,
376 /* vendor code */
377 MBIM_VENDOR_CODE,
378 /* padding */
379 0
380};
381
382/* Microsoft Extended Configuration Descriptor Header Section */
383struct mbim_ext_config_desc_header {
384 __le32 dwLength;
385 __u16 bcdVersion;
386 __le16 wIndex;
387 __u8 bCount;
388 __u8 reserved[7];
389};
390
391/* Microsoft Extended Configuration Descriptor Function Section */
392struct mbim_ext_config_desc_function {
393 __u8 bFirstInterfaceNumber;
394 __u8 bInterfaceCount;
395 __u8 compatibleID[8];
396 __u8 subCompatibleID[8];
397 __u8 reserved[6];
398};
399
400/* Microsoft Extended Configuration Descriptor */
401static struct {
402 struct mbim_ext_config_desc_header header;
403 struct mbim_ext_config_desc_function function;
404} mbim_ext_config_desc = {
405 .header = {
406 .dwLength = __constant_cpu_to_le32(sizeof mbim_ext_config_desc),
407 .bcdVersion = __constant_cpu_to_le16(0x0100),
408 .wIndex = __constant_cpu_to_le16(4),
409 .bCount = 1,
410 },
411 .function = {
412 .bFirstInterfaceNumber = 0,
413 .bInterfaceCount = 1,
414 .compatibleID = { 'A', 'L', 'T', 'R', 'C', 'F', 'G' },
415 /* .subCompatibleID = DYNAMIC */
416 },
417};
418
Anna Perela8c991d2012-04-09 16:44:46 +0300419/*
420 * Here are options for the Datagram Pointer table (NDP) parser.
421 * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
422 * in NDP16 offsets and sizes fields are 1 16bit word wide,
423 * in NDP32 -- 2 16bit words wide. Also signatures are different.
424 * To make the parser code the same, put the differences in the structure,
425 * and switch pointers to the structures when the format is changed.
426 */
427
428struct ndp_parser_opts {
429 u32 nth_sign;
430 u32 ndp_sign;
431 unsigned nth_size;
432 unsigned ndp_size;
433 unsigned ndplen_align;
434 /* sizes in u16 units */
435 unsigned dgram_item_len; /* index or length */
436 unsigned block_length;
437 unsigned fp_index;
438 unsigned reserved1;
439 unsigned reserved2;
440 unsigned next_fp_index;
441};
442
443#define INIT_NDP16_OPTS { \
444 .nth_sign = USB_CDC_NCM_NTH16_SIGN, \
445 .ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \
446 .nth_size = sizeof(struct usb_cdc_ncm_nth16), \
447 .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \
448 .ndplen_align = 4, \
449 .dgram_item_len = 1, \
450 .block_length = 1, \
451 .fp_index = 1, \
452 .reserved1 = 0, \
453 .reserved2 = 0, \
454 .next_fp_index = 1, \
455}
456
457#define INIT_NDP32_OPTS { \
458 .nth_sign = USB_CDC_NCM_NTH32_SIGN, \
459 .ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \
460 .nth_size = sizeof(struct usb_cdc_ncm_nth32), \
461 .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \
462 .ndplen_align = 8, \
463 .dgram_item_len = 2, \
464 .block_length = 2, \
465 .fp_index = 2, \
466 .reserved1 = 1, \
467 .reserved2 = 2, \
468 .next_fp_index = 2, \
469}
470
471static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
472static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
473
474static inline int mbim_lock(atomic_t *excl)
475{
476 if (atomic_inc_return(excl) == 1) {
477 return 0;
478 } else {
479 atomic_dec(excl);
480 return -EBUSY;
481 }
482}
483
484static inline void mbim_unlock(atomic_t *excl)
485{
486 atomic_dec(excl);
487}
488
489static struct ctrl_pkt *mbim_alloc_ctrl_pkt(unsigned len, gfp_t flags)
490{
491 struct ctrl_pkt *pkt;
492
493 pkt = kzalloc(sizeof(struct ctrl_pkt), flags);
494 if (!pkt)
495 return ERR_PTR(-ENOMEM);
496
497 pkt->buf = kmalloc(len, flags);
498 if (!pkt->buf) {
499 kfree(pkt);
500 return ERR_PTR(-ENOMEM);
501 }
502 pkt->len = len;
503
504 return pkt;
505}
506
507static void mbim_free_ctrl_pkt(struct ctrl_pkt *pkt)
508{
509 if (pkt) {
510 kfree(pkt->buf);
511 kfree(pkt);
512 }
513}
514
515static struct usb_request *mbim_alloc_req(struct usb_ep *ep, int buffer_size)
516{
517 struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
518 if (!req)
519 return NULL;
520
521 req->buf = kmalloc(buffer_size, GFP_KERNEL);
522 if (!req->buf) {
523 usb_ep_free_request(ep, req);
524 return NULL;
525 }
526 req->length = buffer_size;
527 return req;
528}
529
530void fmbim_free_req(struct usb_ep *ep, struct usb_request *req)
531{
532 if (req) {
533 kfree(req->buf);
534 usb_ep_free_request(ep, req);
535 }
536}
537
538static void fmbim_ctrl_response_available(struct f_mbim *dev)
539{
540 struct usb_request *req = dev->not_port.notify_req;
541 struct usb_cdc_notification *event = NULL;
542 unsigned long flags;
543 int ret;
544
Anna Perel68aeb172012-10-28 09:00:45 +0200545 pr_debug("dev:%p portno#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300546
547 spin_lock_irqsave(&dev->lock, flags);
548
549 if (!atomic_read(&dev->online)) {
Anna Perel20c91152012-10-30 16:26:44 +0200550 pr_err("dev:%p is not online\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300551 spin_unlock_irqrestore(&dev->lock, flags);
552 return;
553 }
554
555 if (!req) {
Anna Perel20c91152012-10-30 16:26:44 +0200556 pr_err("dev:%p req is NULL\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300557 spin_unlock_irqrestore(&dev->lock, flags);
558 return;
559 }
560
561 if (!req->buf) {
Anna Perel20c91152012-10-30 16:26:44 +0200562 pr_err("dev:%p req->buf is NULL\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300563 spin_unlock_irqrestore(&dev->lock, flags);
564 return;
565 }
566
Anna Perel68aeb172012-10-28 09:00:45 +0200567 if (atomic_inc_return(&dev->not_port.notify_count) != 1) {
568 pr_debug("delay ep_queue: notifications queue is busy[%d]",
569 atomic_read(&dev->not_port.notify_count));
570 spin_unlock_irqrestore(&dev->lock, flags);
571 return;
572 }
Anna Perela8c991d2012-04-09 16:44:46 +0300573
574 event = req->buf;
575 event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
576 | USB_RECIP_INTERFACE;
577 event->bNotificationType = USB_CDC_NOTIFY_RESPONSE_AVAILABLE;
578 event->wValue = cpu_to_le16(0);
579 event->wIndex = cpu_to_le16(dev->ctrl_id);
580 event->wLength = cpu_to_le16(0);
581 spin_unlock_irqrestore(&dev->lock, flags);
582
Anna Perela8c991d2012-04-09 16:44:46 +0300583 ret = usb_ep_queue(dev->not_port.notify,
584 dev->not_port.notify_req, GFP_ATOMIC);
585 if (ret) {
586 atomic_dec(&dev->not_port.notify_count);
587 pr_err("ep enqueue error %d\n", ret);
588 }
589
Anna Perel68aeb172012-10-28 09:00:45 +0200590 pr_debug("Successful Exit");
Anna Perela8c991d2012-04-09 16:44:46 +0300591}
592
593static int
594fmbim_send_cpkt_response(struct f_mbim *gr, struct ctrl_pkt *cpkt)
595{
596 struct f_mbim *dev = gr;
597 unsigned long flags;
598
599 if (!gr || !cpkt) {
600 pr_err("Invalid cpkt, dev:%p cpkt:%p\n",
601 gr, cpkt);
602 return -ENODEV;
603 }
604
Anna Perel20c91152012-10-30 16:26:44 +0200605 pr_debug("dev:%p port_num#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300606
607 if (!atomic_read(&dev->online)) {
Anna Perel20c91152012-10-30 16:26:44 +0200608 pr_err("dev:%p is not connected\n", dev);
Anna Perela8c991d2012-04-09 16:44:46 +0300609 mbim_free_ctrl_pkt(cpkt);
610 return 0;
611 }
612
613 spin_lock_irqsave(&dev->lock, flags);
Anna Perel40c550c2012-04-11 14:09:27 +0300614 list_add_tail(&cpkt->list, &dev->cpkt_resp_q);
Anna Perela8c991d2012-04-09 16:44:46 +0300615 spin_unlock_irqrestore(&dev->lock, flags);
616
617 fmbim_ctrl_response_available(dev);
618
619 return 0;
620}
621
622/* ---------------------------- BAM INTERFACE ----------------------------- */
623
624static int mbim_bam_setup(int no_ports)
625{
626 int ret;
627
628 pr_info("no_ports:%d\n", no_ports);
629
630 ret = bam_data_setup(no_ports);
631 if (ret) {
632 pr_err("bam_data_setup failed err: %d\n", ret);
633 return ret;
634 }
635
636 pr_info("Initialized %d ports\n", no_ports);
637 return 0;
638}
639
640static int mbim_bam_connect(struct f_mbim *dev)
641{
642 int ret;
643
644 pr_info("dev:%p portno:%d\n", dev, dev->port_num);
645
646 ret = bam_data_connect(&dev->bam_port, dev->port_num, dev->port_num);
647 if (ret) {
648 pr_err("bam_data_setup failed: err:%d\n",
649 ret);
650 return ret;
651 } else {
652 pr_info("mbim bam connected\n");
653 }
654
655 return 0;
656}
657
658static int mbim_bam_disconnect(struct f_mbim *dev)
659{
660 pr_info("dev:%p port:%d. Do nothing.\n",
661 dev, dev->port_num);
662
Amit Blay51bebe92012-12-25 18:48:10 +0200663 bam_data_disconnect(&dev->bam_port, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300664
665 return 0;
666}
667
668/* -------------------------------------------------------------------------*/
669
670static inline void mbim_reset_values(struct f_mbim *mbim)
671{
672 mbim->parser_opts = &ndp16_opts;
673
674 mbim->ntb_input_size = NTB_DEFAULT_IN_SIZE;
675
Anna Perela8c991d2012-04-09 16:44:46 +0300676 atomic_set(&mbim->online, 0);
677}
678
Anna Perel86ea7c92012-04-24 14:31:29 +0300679static void mbim_reset_function_queue(struct f_mbim *dev)
680{
681 struct ctrl_pkt *cpkt = NULL;
682
683 pr_debug("Queue empty packet for QBI");
684
685 spin_lock(&dev->lock);
686 if (!dev->is_open) {
687 pr_err("%s: mbim file handler %p is not open", __func__, dev);
688 spin_unlock(&dev->lock);
689 return;
690 }
691
692 cpkt = mbim_alloc_ctrl_pkt(0, GFP_ATOMIC);
693 if (!cpkt) {
694 pr_err("%s: Unable to allocate reset function pkt\n", __func__);
695 spin_unlock(&dev->lock);
696 return;
697 }
698
699 list_add_tail(&cpkt->list, &dev->cpkt_req_q);
700 spin_unlock(&dev->lock);
701
702 pr_debug("%s: Wake up read queue", __func__);
703 wake_up(&dev->read_wq);
704}
705
706static void fmbim_reset_cmd_complete(struct usb_ep *ep, struct usb_request *req)
707{
708 struct f_mbim *dev = req->context;
709
710 mbim_reset_function_queue(dev);
711}
712
713static void mbim_clear_queues(struct f_mbim *mbim)
714{
715 struct ctrl_pkt *cpkt = NULL;
716 struct list_head *act, *tmp;
717
718 spin_lock(&mbim->lock);
719 list_for_each_safe(act, tmp, &mbim->cpkt_req_q) {
720 cpkt = list_entry(act, struct ctrl_pkt, list);
721 list_del(&cpkt->list);
722 mbim_free_ctrl_pkt(cpkt);
723 }
724 list_for_each_safe(act, tmp, &mbim->cpkt_resp_q) {
725 cpkt = list_entry(act, struct ctrl_pkt, list);
726 list_del(&cpkt->list);
727 mbim_free_ctrl_pkt(cpkt);
728 }
729 spin_unlock(&mbim->lock);
730}
731
Anna Perela8c991d2012-04-09 16:44:46 +0300732/*
733 * Context: mbim->lock held
734 */
735static void mbim_do_notify(struct f_mbim *mbim)
736{
737 struct usb_request *req = mbim->not_port.notify_req;
738 struct usb_cdc_notification *event;
739 struct usb_composite_dev *cdev = mbim->cdev;
740 __le32 *data;
741 int status;
742
Anna Perel20c91152012-10-30 16:26:44 +0200743 pr_debug("notify_state: %d", mbim->not_port.notify_state);
Anna Perela8c991d2012-04-09 16:44:46 +0300744
745 if (!req)
746 return;
747
748 event = req->buf;
749
750 switch (mbim->not_port.notify_state) {
751
752 case NCM_NOTIFY_NONE:
Anna Perel68aeb172012-10-28 09:00:45 +0200753 pr_debug("Notification %02x sent\n", event->bNotificationType);
754
755 if (atomic_read(&mbim->not_port.notify_count) <= 0) {
756 pr_debug("notify_none: done");
757 return;
758 }
759
760 spin_unlock(&mbim->lock);
761 status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
762 spin_lock(&mbim->lock);
763 if (status) {
764 atomic_dec(&mbim->not_port.notify_count);
765 pr_err("Queue notify request failed, err: %d", status);
766 }
767
Anna Perela8c991d2012-04-09 16:44:46 +0300768 return;
769
770 case NCM_NOTIFY_CONNECT:
771 event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
772 if (mbim->is_open)
773 event->wValue = cpu_to_le16(1);
774 else
775 event->wValue = cpu_to_le16(0);
776 event->wLength = 0;
777 req->length = sizeof *event;
778
779 pr_info("notify connect %s\n",
780 mbim->is_open ? "true" : "false");
781 mbim->not_port.notify_state = NCM_NOTIFY_NONE;
782 break;
783
784 case NCM_NOTIFY_SPEED:
785 event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
786 event->wValue = cpu_to_le16(0);
787 event->wLength = cpu_to_le16(8);
788 req->length = NCM_STATUS_BYTECOUNT;
789
790 /* SPEED_CHANGE data is up/down speeds in bits/sec */
791 data = req->buf + sizeof *event;
792 data[0] = cpu_to_le32(mbim_bitrate(cdev->gadget));
793 data[1] = data[0];
794
795 pr_info("notify speed %d\n",
796 mbim_bitrate(cdev->gadget));
797 mbim->not_port.notify_state = NCM_NOTIFY_CONNECT;
798 break;
799 }
Anna Perel68aeb172012-10-28 09:00:45 +0200800
Anna Perela8c991d2012-04-09 16:44:46 +0300801 event->bmRequestType = 0xA1;
802 event->wIndex = cpu_to_le16(mbim->ctrl_id);
803
Anna Perela8c991d2012-04-09 16:44:46 +0300804 /*
805 * In double buffering if there is a space in FIFO,
806 * completion callback can be called right after the call,
807 * so unlocking
808 */
Anna Perel68aeb172012-10-28 09:00:45 +0200809 atomic_inc(&mbim->not_port.notify_count);
810 pr_debug("queue request: notify_count = %d",
811 atomic_read(&mbim->not_port.notify_count));
Anna Perela8c991d2012-04-09 16:44:46 +0300812 spin_unlock(&mbim->lock);
813 status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
814 spin_lock(&mbim->lock);
Anna Perel68aeb172012-10-28 09:00:45 +0200815 if (status) {
Anna Perela8c991d2012-04-09 16:44:46 +0300816 atomic_dec(&mbim->not_port.notify_count);
817 pr_err("usb_ep_queue failed, err: %d", status);
818 }
819}
820
821/*
822 * Context: mbim->lock held
823 */
824static void mbim_notify(struct f_mbim *mbim)
825{
826 /*
827 * If mbim_notify() is called before the second (CONNECT)
828 * notification is sent, then it will reset to send the SPEED
829 * notificaion again (and again, and again), but it's not a problem
830 */
Anna Perel20c91152012-10-30 16:26:44 +0200831 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300832
833 mbim->not_port.notify_state = NCM_NOTIFY_SPEED;
834 mbim_do_notify(mbim);
835}
836
837static void mbim_notify_complete(struct usb_ep *ep, struct usb_request *req)
838{
839 struct f_mbim *mbim = req->context;
840 struct usb_cdc_notification *event = req->buf;
841
Anna Perel68aeb172012-10-28 09:00:45 +0200842 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300843
844 spin_lock(&mbim->lock);
845 switch (req->status) {
846 case 0:
Anna Perel68aeb172012-10-28 09:00:45 +0200847 atomic_dec(&mbim->not_port.notify_count);
848 pr_debug("notify_count = %d",
849 atomic_read(&mbim->not_port.notify_count));
Anna Perela8c991d2012-04-09 16:44:46 +0300850 break;
851
852 case -ECONNRESET:
853 case -ESHUTDOWN:
854 /* connection gone */
855 mbim->not_port.notify_state = NCM_NOTIFY_NONE;
856 atomic_set(&mbim->not_port.notify_count, 0);
857 pr_info("ESHUTDOWN/ECONNRESET, connection gone");
Anna Perel86ea7c92012-04-24 14:31:29 +0300858 spin_unlock(&mbim->lock);
859 mbim_clear_queues(mbim);
860 mbim_reset_function_queue(mbim);
Anna Perel89ad1212012-06-13 17:17:24 +0300861 spin_lock(&mbim->lock);
Anna Perela8c991d2012-04-09 16:44:46 +0300862 break;
863 default:
864 pr_err("Unknown event %02x --> %d\n",
865 event->bNotificationType, req->status);
866 break;
867 }
868
Anna Perela8c991d2012-04-09 16:44:46 +0300869 mbim_do_notify(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300870 spin_unlock(&mbim->lock);
871
Anna Perel20c91152012-10-30 16:26:44 +0200872 pr_debug("dev:%p Exit\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300873}
874
875static void mbim_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
876{
877 /* now for SET_NTB_INPUT_SIZE only */
878 unsigned in_size = 0;
879 struct usb_function *f = req->context;
880 struct f_mbim *mbim = func_to_mbim(f);
881 struct mbim_ntb_input_size *ntb = NULL;
882
Anna Perel20c91152012-10-30 16:26:44 +0200883 pr_debug("dev:%p\n", mbim);
Anna Perela8c991d2012-04-09 16:44:46 +0300884
885 req->context = NULL;
886 if (req->status || req->actual != req->length) {
887 pr_err("Bad control-OUT transfer\n");
888 goto invalid;
889 }
890
891 if (req->length == 4) {
892 in_size = get_unaligned_le32(req->buf);
893 if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
894 in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
895 pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
896 goto invalid;
897 }
898 } else if (req->length == 8) {
899 ntb = (struct mbim_ntb_input_size *)req->buf;
900 in_size = get_unaligned_le32(&(ntb->ntb_input_size));
901 if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
902 in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
903 pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
904 goto invalid;
905 }
906 mbim->ntb_max_datagrams =
907 get_unaligned_le16(&(ntb->ntb_max_datagrams));
908 } else {
909 pr_err("Illegal NTB length %d\n", in_size);
910 goto invalid;
911 }
912
Anna Perel20c91152012-10-30 16:26:44 +0200913 pr_debug("Set NTB INPUT SIZE %d\n", in_size);
Anna Perela8c991d2012-04-09 16:44:46 +0300914
915 mbim->ntb_input_size = in_size;
916 return;
917
918invalid:
919 usb_ep_set_halt(ep);
920
921 pr_err("dev:%p Failed\n", mbim);
922
923 return;
924}
925
926static void
927fmbim_cmd_complete(struct usb_ep *ep, struct usb_request *req)
928{
929 struct f_mbim *dev = req->context;
930 struct ctrl_pkt *cpkt = NULL;
931 int len = req->actual;
932
933 if (!dev) {
934 pr_err("mbim dev is null\n");
935 return;
936 }
937
938 if (req->status < 0) {
939 pr_err("mbim command error %d\n", req->status);
940 return;
941 }
942
Anna Perel20c91152012-10-30 16:26:44 +0200943 pr_debug("dev:%p port#%d\n", dev, dev->port_num);
Anna Perela8c991d2012-04-09 16:44:46 +0300944
Anna Perela8c991d2012-04-09 16:44:46 +0300945 cpkt = mbim_alloc_ctrl_pkt(len, GFP_ATOMIC);
946 if (!cpkt) {
947 pr_err("Unable to allocate ctrl pkt\n");
Anna Perela8c991d2012-04-09 16:44:46 +0300948 return;
949 }
950
Anna Perel20c91152012-10-30 16:26:44 +0200951 pr_debug("Add to cpkt_req_q packet with len = %d\n", len);
Anna Perela8c991d2012-04-09 16:44:46 +0300952 memcpy(cpkt->buf, req->buf, len);
Anna Perel20c91152012-10-30 16:26:44 +0200953
Anna Perel182ab572012-11-18 10:10:12 +0200954 spin_lock(&dev->lock);
955 if (!dev->is_open) {
956 pr_err("mbim file handler %p is not open", dev);
957 spin_unlock(&dev->lock);
958 mbim_free_ctrl_pkt(cpkt);
959 return;
960 }
961
Anna Perela8c991d2012-04-09 16:44:46 +0300962 list_add_tail(&cpkt->list, &dev->cpkt_req_q);
963 spin_unlock(&dev->lock);
964
965 /* wakeup read thread */
Anna Perel20c91152012-10-30 16:26:44 +0200966 pr_debug("Wake up read queue");
Anna Perela8c991d2012-04-09 16:44:46 +0300967 wake_up(&dev->read_wq);
968
969 return;
970}
971
972static int
973mbim_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
974{
975 struct f_mbim *mbim = func_to_mbim(f);
976 struct usb_composite_dev *cdev = mbim->cdev;
977 struct usb_request *req = cdev->req;
978 struct ctrl_pkt *cpkt = NULL;
979 int value = -EOPNOTSUPP;
980 u16 w_index = le16_to_cpu(ctrl->wIndex);
981 u16 w_value = le16_to_cpu(ctrl->wValue);
982 u16 w_length = le16_to_cpu(ctrl->wLength);
983
984 /*
985 * composite driver infrastructure handles everything except
986 * CDC class messages; interface activation uses set_alt().
987 */
988
989 if (!atomic_read(&mbim->online)) {
990 pr_info("usb cable is not connected\n");
991 return -ENOTCONN;
992 }
993
994 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
995 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
996 | USB_CDC_RESET_FUNCTION:
997
Anna Perel20c91152012-10-30 16:26:44 +0200998 pr_debug("USB_CDC_RESET_FUNCTION");
Anna Perela8c991d2012-04-09 16:44:46 +0300999 value = 0;
Anna Perel86ea7c92012-04-24 14:31:29 +03001000 req->complete = fmbim_reset_cmd_complete;
1001 req->context = mbim;
Anna Perela8c991d2012-04-09 16:44:46 +03001002 break;
1003
1004 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1005 | USB_CDC_SEND_ENCAPSULATED_COMMAND:
1006
Anna Perel20c91152012-10-30 16:26:44 +02001007 pr_debug("USB_CDC_SEND_ENCAPSULATED_COMMAND");
Anna Perela8c991d2012-04-09 16:44:46 +03001008
1009 if (w_length > req->length) {
Anna Perel20c91152012-10-30 16:26:44 +02001010 pr_debug("w_length > req->length: %d > %d",
Anna Perela8c991d2012-04-09 16:44:46 +03001011 w_length, req->length);
1012 }
1013 value = w_length;
1014 req->complete = fmbim_cmd_complete;
1015 req->context = mbim;
1016 break;
1017
1018 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1019 | USB_CDC_GET_ENCAPSULATED_RESPONSE:
1020
Anna Perel20c91152012-10-30 16:26:44 +02001021 pr_debug("USB_CDC_GET_ENCAPSULATED_RESPONSE");
Anna Perela8c991d2012-04-09 16:44:46 +03001022
1023 if (w_value) {
1024 pr_err("w_length > 0: %d", w_length);
1025 break;
1026 }
1027
Anna Perel20c91152012-10-30 16:26:44 +02001028 pr_debug("req%02x.%02x v%04x i%04x l%d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001029 ctrl->bRequestType, ctrl->bRequest,
1030 w_value, w_index, w_length);
1031
1032 spin_lock(&mbim->lock);
1033 if (list_empty(&mbim->cpkt_resp_q)) {
1034 pr_err("ctrl resp queue empty\n");
1035 spin_unlock(&mbim->lock);
1036 break;
1037 }
1038
1039 cpkt = list_first_entry(&mbim->cpkt_resp_q,
1040 struct ctrl_pkt, list);
1041 list_del(&cpkt->list);
1042 spin_unlock(&mbim->lock);
1043
1044 value = min_t(unsigned, w_length, cpkt->len);
1045 memcpy(req->buf, cpkt->buf, value);
1046 mbim_free_ctrl_pkt(cpkt);
1047
Anna Perel20c91152012-10-30 16:26:44 +02001048 pr_debug("copied encapsulated_response %d bytes",
Anna Perela8c991d2012-04-09 16:44:46 +03001049 value);
1050
1051 break;
1052
1053 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1054 | USB_CDC_GET_NTB_PARAMETERS:
1055
Anna Perel20c91152012-10-30 16:26:44 +02001056 pr_debug("USB_CDC_GET_NTB_PARAMETERS");
Anna Perela8c991d2012-04-09 16:44:46 +03001057
1058 if (w_length == 0 || w_value != 0 || w_index != mbim->ctrl_id)
1059 break;
1060
1061 value = w_length > sizeof ntb_parameters ?
1062 sizeof ntb_parameters : w_length;
1063 memcpy(req->buf, &ntb_parameters, value);
1064 break;
1065
1066 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1067 | USB_CDC_GET_NTB_INPUT_SIZE:
1068
Anna Perel20c91152012-10-30 16:26:44 +02001069 pr_debug("USB_CDC_GET_NTB_INPUT_SIZE");
Anna Perela8c991d2012-04-09 16:44:46 +03001070
1071 if (w_length < 4 || w_value != 0 || w_index != mbim->ctrl_id)
1072 break;
1073
1074 put_unaligned_le32(mbim->ntb_input_size, req->buf);
1075 value = 4;
Anna Perel20c91152012-10-30 16:26:44 +02001076 pr_debug("Reply to host INPUT SIZE %d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001077 mbim->ntb_input_size);
1078 break;
1079
1080 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1081 | USB_CDC_SET_NTB_INPUT_SIZE:
1082
Anna Perel20c91152012-10-30 16:26:44 +02001083 pr_debug("USB_CDC_SET_NTB_INPUT_SIZE");
Anna Perela8c991d2012-04-09 16:44:46 +03001084
1085 if (w_length != 4 && w_length != 8) {
1086 pr_err("wrong NTB length %d", w_length);
1087 break;
1088 }
1089
1090 if (w_value != 0 || w_index != mbim->ctrl_id)
1091 break;
1092
1093 req->complete = mbim_ep0out_complete;
1094 req->length = w_length;
1095 req->context = f;
1096
1097 value = req->length;
1098 break;
1099
1100 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1101 | USB_CDC_GET_NTB_FORMAT:
1102 {
1103 uint16_t format;
1104
Anna Perel20c91152012-10-30 16:26:44 +02001105 pr_debug("USB_CDC_GET_NTB_FORMAT");
Anna Perela8c991d2012-04-09 16:44:46 +03001106
1107 if (w_length < 2 || w_value != 0 || w_index != mbim->ctrl_id)
1108 break;
1109
1110 format = (mbim->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001;
1111 put_unaligned_le16(format, req->buf);
1112 value = 2;
Anna Perel20c91152012-10-30 16:26:44 +02001113 pr_debug("NTB FORMAT: sending %d\n", format);
Anna Perela8c991d2012-04-09 16:44:46 +03001114 break;
1115 }
1116
1117 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
1118 | USB_CDC_SET_NTB_FORMAT:
1119 {
Anna Perel20c91152012-10-30 16:26:44 +02001120 pr_debug("USB_CDC_SET_NTB_FORMAT");
Anna Perela8c991d2012-04-09 16:44:46 +03001121
1122 if (w_length != 0 || w_index != mbim->ctrl_id)
1123 break;
1124 switch (w_value) {
1125 case 0x0000:
1126 mbim->parser_opts = &ndp16_opts;
Anna Perel20c91152012-10-30 16:26:44 +02001127 pr_debug("NCM16 selected\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001128 break;
1129 case 0x0001:
1130 mbim->parser_opts = &ndp32_opts;
Anna Perel20c91152012-10-30 16:26:44 +02001131 pr_debug("NCM32 selected\n");
Anna Perela8c991d2012-04-09 16:44:46 +03001132 break;
1133 default:
1134 break;
1135 }
1136 value = 0;
1137 break;
1138 }
1139
1140 /* optional in mbim descriptor: */
1141 /* case USB_CDC_GET_MAX_DATAGRAM_SIZE: */
1142 /* case USB_CDC_SET_MAX_DATAGRAM_SIZE: */
1143
1144 default:
1145 pr_err("invalid control req: %02x.%02x v%04x i%04x l%d\n",
1146 ctrl->bRequestType, ctrl->bRequest,
1147 w_value, w_index, w_length);
1148 }
1149
1150 /* respond with data transfer or status phase? */
1151 if (value >= 0) {
Anna Perel20c91152012-10-30 16:26:44 +02001152 pr_debug("control request: %02x.%02x v%04x i%04x l%d\n",
Anna Perela8c991d2012-04-09 16:44:46 +03001153 ctrl->bRequestType, ctrl->bRequest,
1154 w_value, w_index, w_length);
Anna Perel2dfcaca2012-04-18 17:25:59 +03001155 req->zero = (value < w_length);
Anna Perela8c991d2012-04-09 16:44:46 +03001156 req->length = value;
1157 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
1158 if (value < 0) {
1159 pr_err("queueing req failed: %02x.%02x, err %d\n",
1160 ctrl->bRequestType,
1161 ctrl->bRequest, value);
1162 }
1163 } else {
1164 pr_err("ctrl req err %d: %02x.%02x v%04x i%04x l%d\n",
1165 value, ctrl->bRequestType, ctrl->bRequest,
1166 w_value, w_index, w_length);
1167 }
1168
1169 /* device either stalls (value < 0) or reports success */
1170 return value;
1171}
1172
Jack Pham2df2f702012-10-11 19:08:24 -07001173/*
1174 * This function handles the Microsoft-specific OS descriptor control
1175 * requests that are issued by Windows host drivers to determine the
1176 * configuration containing the MBIM function.
1177 *
1178 * Unlike mbim_setup() this function handles two specific device requests,
1179 * and only when a configuration has not yet been selected.
1180 */
1181static int mbim_ctrlrequest(struct usb_composite_dev *cdev,
1182 const struct usb_ctrlrequest *ctrl)
1183{
1184 int value = -EOPNOTSUPP;
1185 u16 w_index = le16_to_cpu(ctrl->wIndex);
1186 u16 w_value = le16_to_cpu(ctrl->wValue);
1187 u16 w_length = le16_to_cpu(ctrl->wLength);
1188
1189 /* only respond to OS desciptors when no configuration selected */
1190 if (cdev->config || !mbim_ext_config_desc.function.subCompatibleID[0])
1191 return value;
1192
1193 pr_debug("%02x.%02x v%04x i%04x l%u",
1194 ctrl->bRequestType, ctrl->bRequest,
1195 w_value, w_index, w_length);
1196
1197 /* Handle MSFT OS string */
1198 if (ctrl->bRequestType ==
1199 (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)
1200 && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR
1201 && (w_value >> 8) == USB_DT_STRING
1202 && (w_value & 0xFF) == MBIM_OS_STRING_ID) {
1203
1204 value = (w_length < sizeof(mbim_os_string) ?
1205 w_length : sizeof(mbim_os_string));
1206 memcpy(cdev->req->buf, mbim_os_string, value);
1207
1208 } else if (ctrl->bRequestType ==
1209 (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)
1210 && ctrl->bRequest == MBIM_VENDOR_CODE && w_index == 4) {
1211
1212 /* Handle Extended OS descriptor */
1213 value = (w_length < sizeof(mbim_ext_config_desc) ?
1214 w_length : sizeof(mbim_ext_config_desc));
1215 memcpy(cdev->req->buf, &mbim_ext_config_desc, value);
1216 }
1217
1218 /* respond with data transfer or status phase? */
1219 if (value >= 0) {
1220 int rc;
1221 cdev->req->zero = value < w_length;
1222 cdev->req->length = value;
1223 rc = usb_ep_queue(cdev->gadget->ep0, cdev->req, GFP_ATOMIC);
1224 if (rc < 0)
1225 pr_err("response queue error: %d", rc);
1226 }
1227 return value;
1228}
1229
Anna Perela8c991d2012-04-09 16:44:46 +03001230static int mbim_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
1231{
1232 struct f_mbim *mbim = func_to_mbim(f);
1233 struct usb_composite_dev *cdev = mbim->cdev;
1234 int ret = 0;
1235
1236 /* Control interface has only altsetting 0 */
1237 if (intf == mbim->ctrl_id) {
1238
1239 pr_info("CONTROL_INTERFACE");
1240
1241 if (alt != 0)
1242 goto fail;
1243
1244 if (mbim->not_port.notify->driver_data) {
1245 pr_info("reset mbim control %d\n", intf);
1246 usb_ep_disable(mbim->not_port.notify);
1247 }
1248
1249 ret = config_ep_by_speed(cdev->gadget, f,
1250 mbim->not_port.notify);
1251 if (ret) {
1252 mbim->not_port.notify->desc = NULL;
1253 pr_err("Failed configuring notify ep %s: err %d\n",
1254 mbim->not_port.notify->name, ret);
1255 return ret;
1256 }
1257
1258 ret = usb_ep_enable(mbim->not_port.notify);
1259 if (ret) {
1260 pr_err("usb ep#%s enable failed, err#%d\n",
1261 mbim->not_port.notify->name, ret);
1262 return ret;
1263 }
1264 mbim->not_port.notify->driver_data = mbim;
1265
1266 /* Data interface has two altsettings, 0 and 1 */
1267 } else if (intf == mbim->data_id) {
1268
1269 pr_info("DATA_INTERFACE");
1270
1271 if (alt > 1)
1272 goto fail;
1273
1274 if (mbim->bam_port.in->driver_data) {
1275 pr_info("reset mbim\n");
1276 mbim_reset_values(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +03001277 }
1278
1279 /*
1280 * CDC Network only sends data in non-default altsettings.
1281 * Changing altsettings resets filters, statistics, etc.
1282 */
1283 if (alt == 1) {
1284 pr_info("Alt set 1, initialize ports");
1285
1286 if (!mbim->bam_port.in->desc) {
1287
1288 pr_info("Choose endpoints");
1289
1290 ret = config_ep_by_speed(cdev->gadget, f,
1291 mbim->bam_port.in);
1292 if (ret) {
1293 mbim->bam_port.in->desc = NULL;
1294 pr_err("IN ep %s failed: %d\n",
1295 mbim->bam_port.in->name, ret);
1296 return ret;
1297 }
1298
1299 pr_info("Set mbim port in_desc = 0x%p",
1300 mbim->bam_port.in->desc);
1301
1302 ret = config_ep_by_speed(cdev->gadget, f,
1303 mbim->bam_port.out);
1304 if (ret) {
1305 mbim->bam_port.out->desc = NULL;
1306 pr_err("OUT ep %s failed: %d\n",
1307 mbim->bam_port.out->name, ret);
1308 return ret;
1309 }
1310
1311 pr_info("Set mbim port out_desc = 0x%p",
1312 mbim->bam_port.out->desc);
Anna Perel6637bd72012-10-23 10:53:32 +02001313
1314 pr_debug("Activate mbim\n");
1315 mbim_bam_connect(mbim);
1316
Anna Perela8c991d2012-04-09 16:44:46 +03001317 } else {
1318 pr_info("PORTS already SET");
1319 }
Anna Perela8c991d2012-04-09 16:44:46 +03001320 }
1321
Bar Weinerb1c95f52012-12-23 09:09:13 +02001322 mbim->data_alt_int = alt;
Anna Perela8c991d2012-04-09 16:44:46 +03001323 spin_lock(&mbim->lock);
1324 mbim_notify(mbim);
1325 spin_unlock(&mbim->lock);
1326 } else {
1327 goto fail;
1328 }
1329
1330 atomic_set(&mbim->online, 1);
1331
1332 pr_info("SET DEVICE ONLINE");
1333
1334 /* wakeup file threads */
1335 wake_up(&mbim->read_wq);
1336 wake_up(&mbim->write_wq);
1337
1338 return 0;
1339
1340fail:
1341 pr_err("ERROR: Illegal Interface");
1342 return -EINVAL;
1343}
1344
1345/*
1346 * Because the data interface supports multiple altsettings,
1347 * this MBIM function *MUST* implement a get_alt() method.
1348 */
1349static int mbim_get_alt(struct usb_function *f, unsigned intf)
1350{
1351 struct f_mbim *mbim = func_to_mbim(f);
1352
1353 if (intf == mbim->ctrl_id)
1354 return 0;
Bar Weinerb1c95f52012-12-23 09:09:13 +02001355 else if (intf == mbim->data_id)
1356 return mbim->data_alt_int;
1357
1358 return -EINVAL;
Anna Perela8c991d2012-04-09 16:44:46 +03001359}
1360
1361static void mbim_disable(struct usb_function *f)
1362{
1363 struct f_mbim *mbim = func_to_mbim(f);
1364
1365 pr_info("SET DEVICE OFFLINE");
1366 atomic_set(&mbim->online, 0);
1367
Anna Perel86ea7c92012-04-24 14:31:29 +03001368 mbim_clear_queues(mbim);
1369 mbim_reset_function_queue(mbim);
Anna Perela8c991d2012-04-09 16:44:46 +03001370
1371 mbim_bam_disconnect(mbim);
1372
1373 if (mbim->not_port.notify->driver_data) {
1374 usb_ep_disable(mbim->not_port.notify);
1375 mbim->not_port.notify->driver_data = NULL;
1376 }
1377
Anna Perel68aeb172012-10-28 09:00:45 +02001378 atomic_set(&mbim->not_port.notify_count, 0);
1379
Anna Perela8c991d2012-04-09 16:44:46 +03001380 pr_info("mbim deactivated\n");
1381}
1382
Anna Perel557bf722012-09-20 11:16:35 +03001383#define MBIM_ACTIVE_PORT 0
1384
1385static void mbim_suspend(struct usb_function *f)
1386{
1387 pr_info("mbim suspended\n");
1388 bam_data_suspend(MBIM_ACTIVE_PORT);
1389}
1390
1391static void mbim_resume(struct usb_function *f)
1392{
1393 pr_info("mbim resumed\n");
1394 bam_data_resume(MBIM_ACTIVE_PORT);
1395}
1396
Anna Perela8c991d2012-04-09 16:44:46 +03001397/*---------------------- function driver setup/binding ---------------------*/
1398
1399static int
1400mbim_bind(struct usb_configuration *c, struct usb_function *f)
1401{
1402 struct usb_composite_dev *cdev = c->cdev;
1403 struct f_mbim *mbim = func_to_mbim(f);
1404 int status;
1405 struct usb_ep *ep;
1406
1407 pr_info("Enter");
1408
1409 mbim->cdev = cdev;
1410
1411 /* allocate instance-specific interface IDs */
1412 status = usb_interface_id(c, f);
1413 if (status < 0)
1414 goto fail;
1415 mbim->ctrl_id = status;
1416 mbim_iad_desc.bFirstInterface = status;
1417
1418 mbim_control_intf.bInterfaceNumber = status;
1419 mbim_union_desc.bMasterInterface0 = status;
1420
1421 status = usb_interface_id(c, f);
1422 if (status < 0)
1423 goto fail;
1424 mbim->data_id = status;
Bar Weinerb1c95f52012-12-23 09:09:13 +02001425 mbim->data_alt_int = 0;
Anna Perela8c991d2012-04-09 16:44:46 +03001426
1427 mbim_data_nop_intf.bInterfaceNumber = status;
1428 mbim_data_intf.bInterfaceNumber = status;
1429 mbim_union_desc.bSlaveInterface0 = status;
1430
Anna Perel557bf722012-09-20 11:16:35 +03001431 mbim->bam_port.cdev = cdev;
1432
Anna Perela8c991d2012-04-09 16:44:46 +03001433 status = -ENODEV;
1434
1435 /* allocate instance-specific endpoints */
1436 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_in_desc);
1437 if (!ep) {
1438 pr_err("usb epin autoconfig failed\n");
1439 goto fail;
1440 }
1441 pr_info("usb epin autoconfig succeeded\n");
1442 ep->driver_data = cdev; /* claim */
1443 mbim->bam_port.in = ep;
1444
1445 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_out_desc);
1446 if (!ep) {
1447 pr_err("usb epout autoconfig failed\n");
1448 goto fail;
1449 }
1450 pr_info("usb epout autoconfig succeeded\n");
1451 ep->driver_data = cdev; /* claim */
1452 mbim->bam_port.out = ep;
1453
1454 ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_notify_desc);
1455 if (!ep) {
1456 pr_err("usb notify ep autoconfig failed\n");
1457 goto fail;
1458 }
1459 pr_info("usb notify ep autoconfig succeeded\n");
1460 mbim->not_port.notify = ep;
1461 ep->driver_data = cdev; /* claim */
1462
1463 status = -ENOMEM;
1464
1465 /* allocate notification request and buffer */
1466 mbim->not_port.notify_req = mbim_alloc_req(ep, NCM_STATUS_BYTECOUNT);
1467 if (!mbim->not_port.notify_req) {
1468 pr_info("failed to allocate notify request\n");
1469 goto fail;
1470 }
1471 pr_info("allocated notify ep request & request buffer\n");
1472
1473 mbim->not_port.notify_req->context = mbim;
1474 mbim->not_port.notify_req->complete = mbim_notify_complete;
1475
1476 /* copy descriptors, and track endpoint copies */
1477 f->descriptors = usb_copy_descriptors(mbim_fs_function);
1478 if (!f->descriptors)
1479 goto fail;
1480
1481 /*
1482 * support all relevant hardware speeds... we expect that when
1483 * hardware is dual speed, all bulk-capable endpoints work at
1484 * both speeds
1485 */
1486 if (gadget_is_dualspeed(c->cdev->gadget)) {
1487 hs_mbim_in_desc.bEndpointAddress =
1488 fs_mbim_in_desc.bEndpointAddress;
1489 hs_mbim_out_desc.bEndpointAddress =
1490 fs_mbim_out_desc.bEndpointAddress;
1491 hs_mbim_notify_desc.bEndpointAddress =
1492 fs_mbim_notify_desc.bEndpointAddress;
1493
1494 /* copy descriptors, and track endpoint copies */
1495 f->hs_descriptors = usb_copy_descriptors(mbim_hs_function);
1496 if (!f->hs_descriptors)
1497 goto fail;
1498 }
1499
Jack Pham2df2f702012-10-11 19:08:24 -07001500 /*
1501 * If MBIM is bound in a config other than the first, tell Windows
1502 * about it by returning the num as a string in the OS descriptor's
1503 * subCompatibleID field. Windows only supports up to config #4.
1504 */
1505 if (c->bConfigurationValue >= 2 && c->bConfigurationValue <= 4) {
1506 pr_debug("MBIM in configuration %d", c->bConfigurationValue);
1507 mbim_ext_config_desc.function.subCompatibleID[0] =
1508 c->bConfigurationValue + '0';
1509 }
1510
Anna Perela8c991d2012-04-09 16:44:46 +03001511 pr_info("mbim(%d): %s speed IN/%s OUT/%s NOTIFY/%s\n",
1512 mbim->port_num,
1513 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
1514 mbim->bam_port.in->name, mbim->bam_port.out->name,
1515 mbim->not_port.notify->name);
1516
1517 return 0;
1518
1519fail:
1520 pr_err("%s failed to bind, err %d\n", f->name, status);
1521
1522 if (f->descriptors)
1523 usb_free_descriptors(f->descriptors);
1524
1525 if (mbim->not_port.notify_req) {
1526 kfree(mbim->not_port.notify_req->buf);
1527 usb_ep_free_request(mbim->not_port.notify,
1528 mbim->not_port.notify_req);
1529 }
1530
1531 /* we might as well release our claims on endpoints */
1532 if (mbim->not_port.notify)
1533 mbim->not_port.notify->driver_data = NULL;
1534 if (mbim->bam_port.out)
1535 mbim->bam_port.out->driver_data = NULL;
1536 if (mbim->bam_port.in)
1537 mbim->bam_port.in->driver_data = NULL;
1538
1539 return status;
1540}
1541
1542static void mbim_unbind(struct usb_configuration *c, struct usb_function *f)
1543{
1544 struct f_mbim *mbim = func_to_mbim(f);
1545
1546 if (gadget_is_dualspeed(c->cdev->gadget))
1547 usb_free_descriptors(f->hs_descriptors);
1548 usb_free_descriptors(f->descriptors);
1549
1550 kfree(mbim->not_port.notify_req->buf);
1551 usb_ep_free_request(mbim->not_port.notify, mbim->not_port.notify_req);
Jack Pham2df2f702012-10-11 19:08:24 -07001552
1553 mbim_ext_config_desc.function.subCompatibleID[0] = 0;
Anna Perela8c991d2012-04-09 16:44:46 +03001554}
1555
1556/**
1557 * mbim_bind_config - add MBIM link to a configuration
1558 * @c: the configuration to support the network link
1559 * Context: single threaded during gadget setup
1560 * Returns zero on success, else negative errno.
1561 */
1562int mbim_bind_config(struct usb_configuration *c, unsigned portno)
1563{
1564 struct f_mbim *mbim = NULL;
1565 int status = 0;
1566
1567 pr_info("port number %u", portno);
1568
1569 if (portno >= nr_mbim_ports) {
1570 pr_err("Can not add port %u. Max ports = %d",
1571 portno, nr_mbim_ports);
1572 return -ENODEV;
1573 }
1574
1575 status = mbim_bam_setup(nr_mbim_ports);
1576 if (status) {
1577 pr_err("bam setup failed");
1578 return status;
1579 }
1580
1581 /* maybe allocate device-global string IDs */
1582 if (mbim_string_defs[0].id == 0) {
1583
1584 /* control interface label */
1585 status = usb_string_id(c->cdev);
1586 if (status < 0)
1587 return status;
1588 mbim_string_defs[STRING_CTRL_IDX].id = status;
1589 mbim_control_intf.iInterface = status;
1590
1591 /* data interface label */
1592 status = usb_string_id(c->cdev);
1593 if (status < 0)
1594 return status;
1595 mbim_string_defs[STRING_DATA_IDX].id = status;
1596 mbim_data_nop_intf.iInterface = status;
1597 mbim_data_intf.iInterface = status;
1598 }
1599
1600 /* allocate and initialize one new instance */
1601 mbim = mbim_ports[0].port;
1602 if (!mbim) {
1603 pr_info("mbim struct not allocated");
1604 return -ENOMEM;
1605 }
1606
1607 mbim->cdev = c->cdev;
1608
Anna Perela8c991d2012-04-09 16:44:46 +03001609 mbim_reset_values(mbim);
1610
1611 mbim->function.name = "usb_mbim";
1612 mbim->function.strings = mbim_strings;
1613 mbim->function.bind = mbim_bind;
1614 mbim->function.unbind = mbim_unbind;
1615 mbim->function.set_alt = mbim_set_alt;
1616 mbim->function.get_alt = mbim_get_alt;
1617 mbim->function.setup = mbim_setup;
1618 mbim->function.disable = mbim_disable;
Anna Perel557bf722012-09-20 11:16:35 +03001619 mbim->function.suspend = mbim_suspend;
1620 mbim->function.resume = mbim_resume;
Anna Perela8c991d2012-04-09 16:44:46 +03001621
1622 INIT_LIST_HEAD(&mbim->cpkt_req_q);
1623 INIT_LIST_HEAD(&mbim->cpkt_resp_q);
1624
1625 status = usb_add_function(c, &mbim->function);
1626
1627 pr_info("Exit status %d", status);
1628
1629 return status;
1630}
1631
1632/* ------------ MBIM DRIVER File Operations API for USER SPACE ------------ */
1633
1634static ssize_t
1635mbim_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
1636{
1637 struct f_mbim *dev = fp->private_data;
1638 struct ctrl_pkt *cpkt = NULL;
1639 int ret = 0;
1640
1641 pr_debug("Enter(%d)\n", count);
1642
1643 if (!dev) {
1644 pr_err("Received NULL mbim pointer\n");
1645 return -ENODEV;
1646 }
1647
1648 if (count > MBIM_BULK_BUFFER_SIZE) {
1649 pr_err("Buffer size is too big %d, should be at most %d\n",
1650 count, MBIM_BULK_BUFFER_SIZE);
1651 return -EINVAL;
1652 }
1653
1654 if (mbim_lock(&dev->read_excl)) {
1655 pr_err("Previous reading is not finished yet\n");
1656 return -EBUSY;
1657 }
1658
1659 /* block until mbim online */
1660 while (!(atomic_read(&dev->online) || atomic_read(&dev->error))) {
1661 pr_err("USB cable not connected. Wait.\n");
1662 ret = wait_event_interruptible(dev->read_wq,
1663 (atomic_read(&dev->online) ||
1664 atomic_read(&dev->error)));
1665 if (ret < 0) {
1666 mbim_unlock(&dev->read_excl);
Anna Perel96eea9d2012-12-09 14:08:04 +02001667 return -ERESTARTSYS;
Anna Perela8c991d2012-04-09 16:44:46 +03001668 }
1669 }
1670
1671 if (atomic_read(&dev->error)) {
1672 mbim_unlock(&dev->read_excl);
1673 return -EIO;
1674 }
1675
1676 while (list_empty(&dev->cpkt_req_q)) {
1677 pr_err("Requests list is empty. Wait.\n");
1678 ret = wait_event_interruptible(dev->read_wq,
1679 !list_empty(&dev->cpkt_req_q));
1680 if (ret < 0) {
1681 pr_err("Waiting failed\n");
1682 mbim_unlock(&dev->read_excl);
Anna Perel96eea9d2012-12-09 14:08:04 +02001683 return -ERESTARTSYS;
Anna Perela8c991d2012-04-09 16:44:46 +03001684 }
1685 pr_debug("Received request packet\n");
1686 }
1687
1688 cpkt = list_first_entry(&dev->cpkt_req_q, struct ctrl_pkt,
1689 list);
1690 if (cpkt->len > count) {
1691 mbim_unlock(&dev->read_excl);
1692 pr_err("cpkt size too big:%d > buf size:%d\n",
1693 cpkt->len, count);
1694 return -ENOMEM;
1695 }
1696
1697 pr_debug("cpkt size:%d\n", cpkt->len);
1698
1699 list_del(&cpkt->list);
1700 mbim_unlock(&dev->read_excl);
1701
1702 ret = copy_to_user(buf, cpkt->buf, cpkt->len);
1703 if (ret) {
1704 pr_err("copy_to_user failed: err %d\n", ret);
Anna Perel96eea9d2012-12-09 14:08:04 +02001705 ret = -ENOMEM;
Anna Perela8c991d2012-04-09 16:44:46 +03001706 } else {
1707 pr_debug("copied %d bytes to user\n", cpkt->len);
1708 ret = cpkt->len;
1709 }
1710
1711 mbim_free_ctrl_pkt(cpkt);
1712
1713 return ret;
1714}
1715
1716static ssize_t
1717mbim_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos)
1718{
1719 struct f_mbim *dev = fp->private_data;
1720 struct ctrl_pkt *cpkt = NULL;
1721 int ret = 0;
1722
1723 pr_debug("Enter(%d)", count);
1724
1725 if (!dev) {
1726 pr_err("Received NULL mbim pointer\n");
1727 return -ENODEV;
1728 }
1729
1730 if (!count) {
1731 pr_err("zero length ctrl pkt\n");
1732 return -ENODEV;
1733 }
1734
1735 if (count > MAX_CTRL_PKT_SIZE) {
1736 pr_err("given pkt size too big:%d > max_pkt_size:%d\n",
1737 count, MAX_CTRL_PKT_SIZE);
1738 return -ENOMEM;
1739 }
1740
1741 if (mbim_lock(&dev->write_excl)) {
1742 pr_err("Previous writing not finished yet\n");
1743 return -EBUSY;
1744 }
1745
1746 if (!atomic_read(&dev->online)) {
1747 pr_err("USB cable not connected\n");
1748 mbim_unlock(&dev->write_excl);
1749 return -EPIPE;
1750 }
1751
1752 cpkt = mbim_alloc_ctrl_pkt(count, GFP_KERNEL);
1753 if (!cpkt) {
1754 pr_err("failed to allocate ctrl pkt\n");
1755 mbim_unlock(&dev->write_excl);
1756 return -ENOMEM;
1757 }
1758
1759 ret = copy_from_user(cpkt->buf, buf, count);
1760 if (ret) {
1761 pr_err("copy_from_user failed err:%d\n", ret);
1762 mbim_free_ctrl_pkt(cpkt);
1763 mbim_unlock(&dev->write_excl);
1764 return 0;
1765 }
1766
1767 fmbim_send_cpkt_response(dev, cpkt);
1768
1769 mbim_unlock(&dev->write_excl);
1770
1771 pr_debug("Exit(%d)", count);
1772
1773 return count;
Anna Perel89ad1212012-06-13 17:17:24 +03001774
Anna Perela8c991d2012-04-09 16:44:46 +03001775}
1776
1777static int mbim_open(struct inode *ip, struct file *fp)
1778{
1779 pr_info("Open mbim driver\n");
1780
1781 while (!_mbim_dev) {
1782 pr_err("mbim_dev not created yet\n");
1783 return -ENODEV;
1784 }
1785
1786 if (mbim_lock(&_mbim_dev->open_excl)) {
1787 pr_err("Already opened\n");
1788 return -EBUSY;
1789 }
1790
1791 pr_info("Lock mbim_dev->open_excl for open\n");
1792
1793 if (!atomic_read(&_mbim_dev->online))
1794 pr_err("USB cable not connected\n");
1795
Anna Perela8c991d2012-04-09 16:44:46 +03001796 fp->private_data = _mbim_dev;
1797
1798 atomic_set(&_mbim_dev->error, 0);
1799
1800 spin_lock(&_mbim_dev->lock);
1801 _mbim_dev->is_open = true;
Anna Perela8c991d2012-04-09 16:44:46 +03001802 spin_unlock(&_mbim_dev->lock);
1803
1804 pr_info("Exit, mbim file opened\n");
1805
1806 return 0;
1807}
1808
1809static int mbim_release(struct inode *ip, struct file *fp)
1810{
1811 struct f_mbim *mbim = fp->private_data;
1812
1813 pr_info("Close mbim file");
1814
1815 spin_lock(&mbim->lock);
1816 mbim->is_open = false;
Anna Perela8c991d2012-04-09 16:44:46 +03001817 spin_unlock(&mbim->lock);
1818
Anna Perela8c991d2012-04-09 16:44:46 +03001819 mbim_unlock(&_mbim_dev->open_excl);
1820
1821 return 0;
1822}
1823
1824static long mbim_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
1825{
1826 struct f_mbim *mbim = fp->private_data;
1827 int ret = 0;
1828
Anna Perel20c91152012-10-30 16:26:44 +02001829 pr_debug("Received command %d", cmd);
Anna Perela8c991d2012-04-09 16:44:46 +03001830
1831 if (mbim_lock(&mbim->ioctl_excl))
1832 return -EBUSY;
1833
1834 switch (cmd) {
1835 case MBIM_GET_NTB_SIZE:
1836 ret = copy_to_user((void __user *)arg,
1837 &mbim->ntb_input_size, sizeof(mbim->ntb_input_size));
1838 if (ret) {
1839 pr_err("copying to user space failed");
1840 ret = -EFAULT;
1841 }
1842 pr_info("Sent NTB size %d", mbim->ntb_input_size);
1843 break;
1844 case MBIM_GET_DATAGRAM_COUNT:
1845 ret = copy_to_user((void __user *)arg,
1846 &mbim->ntb_max_datagrams,
1847 sizeof(mbim->ntb_max_datagrams));
1848 if (ret) {
1849 pr_err("copying to user space failed");
1850 ret = -EFAULT;
1851 }
1852 pr_info("Sent NTB datagrams count %d",
1853 mbim->ntb_max_datagrams);
1854 break;
1855 default:
1856 pr_err("wrong parameter");
1857 ret = -EINVAL;
1858 }
1859
1860 mbim_unlock(&mbim->ioctl_excl);
1861
1862 return ret;
1863}
1864
1865/* file operations for MBIM device /dev/android_mbim */
1866static const struct file_operations mbim_fops = {
1867 .owner = THIS_MODULE,
1868 .open = mbim_open,
1869 .release = mbim_release,
1870 .read = mbim_read,
1871 .write = mbim_write,
1872 .unlocked_ioctl = mbim_ioctl,
1873};
1874
1875static struct miscdevice mbim_device = {
1876 .minor = MISC_DYNAMIC_MINOR,
1877 .name = "android_mbim",
1878 .fops = &mbim_fops,
1879};
1880
1881static int mbim_init(int instances)
1882{
1883 int i;
1884 struct f_mbim *dev = NULL;
1885 int ret;
1886
1887 pr_info("initialize %d instances\n", instances);
1888
1889 if (instances > NR_MBIM_PORTS) {
1890 pr_err("Max-%d instances supported\n", NR_MBIM_PORTS);
1891 return -EINVAL;
1892 }
1893
1894 for (i = 0; i < instances; i++) {
1895 dev = kzalloc(sizeof(struct f_mbim), GFP_KERNEL);
1896 if (!dev) {
1897 pr_err("Failed to allocate mbim dev\n");
1898 ret = -ENOMEM;
1899 goto fail_probe;
1900 }
1901
1902 dev->port_num = i;
1903 spin_lock_init(&dev->lock);
1904 INIT_LIST_HEAD(&dev->cpkt_req_q);
1905 INIT_LIST_HEAD(&dev->cpkt_resp_q);
1906
1907 mbim_ports[i].port = dev;
1908 mbim_ports[i].port_num = i;
1909
1910 init_waitqueue_head(&dev->read_wq);
1911 init_waitqueue_head(&dev->write_wq);
1912
1913 atomic_set(&dev->open_excl, 0);
1914 atomic_set(&dev->ioctl_excl, 0);
1915 atomic_set(&dev->read_excl, 0);
1916 atomic_set(&dev->write_excl, 0);
1917
1918 nr_mbim_ports++;
1919
1920 }
1921
1922 _mbim_dev = dev;
1923 ret = misc_register(&mbim_device);
1924 if (ret) {
1925 pr_err("mbim driver failed to register");
1926 goto fail_probe;
1927 }
1928
1929 pr_info("Initialized %d ports\n", nr_mbim_ports);
1930
1931 return ret;
1932
1933fail_probe:
1934 pr_err("Failed");
1935 for (i = 0; i < nr_mbim_ports; i++) {
1936 kfree(mbim_ports[i].port);
1937 mbim_ports[i].port = NULL;
1938 }
1939
1940 return ret;
1941}
1942
1943static void fmbim_cleanup(void)
1944{
1945 int i = 0;
1946
1947 pr_info("Enter");
1948
1949 for (i = 0; i < nr_mbim_ports; i++) {
1950 kfree(mbim_ports[i].port);
1951 mbim_ports[i].port = NULL;
1952 }
1953 nr_mbim_ports = 0;
1954
1955 misc_deregister(&mbim_device);
1956
1957 _mbim_dev = NULL;
1958}
1959