1 /*===========================================================================
2 FILE:
3 QMIDevice.c
4
5 DESCRIPTION:
6 Functions related to the QMI interface device
7
8 FUNCTIONS:
9 Generic functions
10 IsDeviceValid
11 PrintHex
12 GobiSetDownReason
13 GobiClearDownReason
14 GobiTestDownReason
15
16 Driver level asynchronous read functions
17 ResubmitIntURB
18 ReadCallback
19 IntCallback
20 StartRead
21 KillRead
22
23 Internal read/write functions
24 ReadAsync
25 UpSem
26 ReadSync
27 WriteSyncCallback
28 WriteSync
29
30 Internal memory management functions
31 GetClientID
32 ReleaseClientID
33 FindClientMem
34 AddToReadMemList
35 PopFromReadMemList
36 AddToNotifyList
37 NotifyAndPopNotifyList
38 AddToURBList
39 PopFromURBList
40
41 Internal userspace wrapper functions
42 UserspaceunlockedIOCTL
43
44 Userspace wrappers
45 UserspaceOpen
46 UserspaceIOCTL
47 UserspaceClose
48 UserspaceRead
49 UserspaceWrite
50 UserspacePoll
51
52 Initializer and destructor
53 RegisterQMIDevice
54 DeregisterQMIDevice
55
56 Driver level client management
57 QMIReady
58 QMIWDSCallback
59 SetupQMIWDSCallback
60 QMIDMSGetMEID
61
62 Copyright (c) 2011, Code Aurora Forum. All rights reserved.
63
64 Redistribution and use in source and binary forms, with or without
65 modification, are permitted provided that the following conditions are met:
66 * Redistributions of source code must retain the above copyright
67 notice, this list of conditions and the following disclaimer.
68 * Redistributions in binary form must reproduce the above copyright
69 notice, this list of conditions and the following disclaimer in the
70 documentation and/or other materials provided with the distribution.
71 * Neither the name of Code Aurora Forum nor
72 the names of its contributors may be used to endorse or promote
73 products derived from this software without specific prior written
74 permission.
75
76
77 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
78 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
81 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
82 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
83 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
84 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
85 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
86 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
87 POSSIBILITY OF SUCH DAMAGE.
88 ===========================================================================*/
89
90 //---------------------------------------------------------------------------
91 // Include Files
92 //---------------------------------------------------------------------------
93 #include <asm/unaligned.h>
94 #include <linux/module.h>
95 #include <linux/usb/cdc.h>
96 #include <linux/usb.h>
97
98 //-----------------------------------------------------------------------------
99 // Definitions
100 //-----------------------------------------------------------------------------
101
102 #define __QUEC_INCLUDE_QMI_C__
103 #include "QMI.c"
104 #define __QUECTEL_INTER__
105 #include "QMIDevice.h"
106
107 #if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,22 ))
108 static int s_interval;
109 #endif
110
111 #if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,14 ))
112 #include <linux/devfs_fs_kernel.h>
113 static char devfs_name[32];
device_create(struct class * class,struct device * parent,dev_t devt,const char * fmt,...)114 static int device_create(struct class *class, struct device *parent, dev_t devt, const char *fmt, ...)
115 {
116 va_list vargs;
117 struct class_device *class_dev;
118 int err;
119
120 va_start(vargs, fmt);
121 vsnprintf(devfs_name, sizeof(devfs_name), fmt, vargs);
122 va_end(vargs);
123
124 class_dev = class_device_create(class, devt, parent, "%s", devfs_name);
125 if (IS_ERR(class_dev)) {
126 err = PTR_ERR(class_dev);
127 goto out;
128 }
129
130 err = devfs_mk_cdev(devt, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, devfs_name);
131 if (err) {
132 class_device_destroy(class, devt);
133 goto out;
134 }
135
136 return 0;
137
138 out:
139 return err;
140 }
141
device_destroy(struct class * class,dev_t devt)142 static void device_destroy(struct class *class, dev_t devt)
143 {
144 class_device_destroy(class, devt);
145 devfs_remove(devfs_name);
146 }
147 #endif
148
149 #ifdef CONFIG_PM
150 // Prototype to GobiNetSuspend function
151 int QuecGobiNetSuspend(
152 struct usb_interface * pIntf,
153 pm_message_t powerEvent );
154 #endif /* CONFIG_PM */
155
156 // IOCTL to generate a client ID for this service type
157 #define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1
158
159 // IOCTL to get the VIDPID of the device
160 #define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2
161
162 // IOCTL to get the MEID of the device
163 #define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3
164
165 #define IOCTL_QMI_RELEASE_SERVICE_FILE_IOCTL (0x8BE0 + 4)
166
167 // CDC GET_ENCAPSULATED_RESPONSE packet
168 #define CDC_GET_ENCAPSULATED_RESPONSE_LE 0x01A1ll
169 #define CDC_GET_ENCAPSULATED_RESPONSE_BE 0xA101000000000000ll
170 /* The following masks filter the common part of the encapsulated response
171 * packet value for Gobi and QMI devices, ie. ignore usb interface number
172 */
173 #define CDC_RSP_MASK_BE 0xFFFFFFFF00FFFFFFll
174 #define CDC_RSP_MASK_LE 0xFFFFFFE0FFFFFFFFll
175
176 static const int i = 1;
177 #define is_bigendian() ( (*(char*)&i) == 0 )
178 #define CDC_GET_ENCAPSULATED_RESPONSE(pcdcrsp, pmask)\
179 {\
180 *pcdcrsp = is_bigendian() ? CDC_GET_ENCAPSULATED_RESPONSE_BE \
181 : CDC_GET_ENCAPSULATED_RESPONSE_LE ; \
182 *pmask = is_bigendian() ? CDC_RSP_MASK_BE \
183 : CDC_RSP_MASK_LE; \
184 }
185
186 // CDC CONNECTION_SPEED_CHANGE indication packet
187 #define CDC_CONNECTION_SPEED_CHANGE_LE 0x2AA1ll
188 #define CDC_CONNECTION_SPEED_CHANGE_BE 0xA12A000000000000ll
189 /* The following masks filter the common part of the connection speed change
190 * packet value for Gobi and QMI devices
191 */
192 #define CDC_CONNSPD_MASK_BE 0xFFFFFFFFFFFF7FFFll
193 #define CDC_CONNSPD_MASK_LE 0XFFF7FFFFFFFFFFFFll
194 #define CDC_GET_CONNECTION_SPEED_CHANGE(pcdccscp, pmask)\
195 {\
196 *pcdccscp = is_bigendian() ? CDC_CONNECTION_SPEED_CHANGE_BE \
197 : CDC_CONNECTION_SPEED_CHANGE_LE ; \
198 *pmask = is_bigendian() ? CDC_CONNSPD_MASK_BE \
199 : CDC_CONNSPD_MASK_LE; \
200 }
201
202 #define SET_CONTROL_LINE_STATE_REQUEST_TYPE 0x21
203 #define SET_CONTROL_LINE_STATE_REQUEST 0x22
204 #define CONTROL_DTR 0x01
205 #define CONTROL_RTS 0x02
206
207 /*=========================================================================*/
208 // UserspaceQMIFops
209 // QMI device's userspace file operations
210 /*=========================================================================*/
211 static struct file_operations UserspaceQMIFops =
212 {
213 .owner = THIS_MODULE,
214 .read = UserspaceRead,
215 .write = UserspaceWrite,
216 #ifdef CONFIG_COMPAT
217 .compat_ioctl = UserspaceunlockedIOCTL,
218 #endif
219 #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,36 ))
220 .unlocked_ioctl = UserspaceunlockedIOCTL,
221 #else
222 .ioctl = UserspaceIOCTL,
223 #endif
224 .open = UserspaceOpen,
225 #ifdef quectel_no_for_each_process
226 .release = UserspaceClose,
227 #else
228 .flush = UserspaceClose,
229 #endif
230 .poll = UserspacePoll,
231 };
232
233 /*=========================================================================*/
234 // Generic functions
235 /*=========================================================================*/
QMIXactionIDGet(sGobiUSBNet * pDev)236 static u8 QMIXactionIDGet( sGobiUSBNet *pDev)
237 {
238 u8 transactionID;
239
240 if( 0 == (transactionID = atomic_add_return( 1, &pDev->mQMIDev.mQMICTLTransactionID)) )
241 {
242 transactionID = atomic_add_return( 1, &pDev->mQMIDev.mQMICTLTransactionID );
243 }
244
245 #if 1 //free these ununsed qmi response, or when these transactionID re-used, they will be regarded as qmi response of the qmi request that have same transactionID
246 if (transactionID) {
247 unsigned long flags;
248 void * pReadBuffer;
249 u16 readBufferSize;
250
251 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
252 while (PopFromReadMemList( pDev,
253 QMICTL,
254 transactionID,
255 &pReadBuffer,
256 &readBufferSize ) == true)
257 {
258 kfree( pReadBuffer );
259 }
260 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
261 }
262 #endif
263
264 return transactionID;
265 }
266
GetEndpoint(struct usb_interface * pintf,int type,int dir)267 static struct usb_endpoint_descriptor *GetEndpoint(
268 struct usb_interface *pintf,
269 int type,
270 int dir )
271 {
272 int i;
273 struct usb_host_interface *iface = pintf->cur_altsetting;
274 struct usb_endpoint_descriptor *pendp;
275
276 for( i = 0; i < iface->desc.bNumEndpoints; i++)
277 {
278 pendp = &iface->endpoint[i].desc;
279 if( ((pendp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == dir)
280 &&
281 (usb_endpoint_type(pendp) == type) )
282 {
283 return pendp;
284 }
285 }
286
287 return NULL;
288 }
289
290 /*===========================================================================
291 METHOD:
292 IsDeviceValid (Public Method)
293
294 DESCRIPTION:
295 Basic test to see if device memory is valid
296
297 PARAMETERS:
298 pDev [ I ] - Device specific memory
299
300 RETURN VALUE:
301 bool
302 ===========================================================================*/
IsDeviceValid(sGobiUSBNet * pDev)303 static bool IsDeviceValid( sGobiUSBNet * pDev )
304 {
305 if (pDev == NULL)
306 {
307 return false;
308 }
309
310 if (pDev->mbQMIValid == false)
311 {
312 return false;
313 }
314
315 return true;
316 }
317
318 /*===========================================================================
319 METHOD:
320 PrintHex (Public Method)
321
322 DESCRIPTION:
323 Print Hex data, for debug purposes
324
325 PARAMETERS:
326 pBuffer [ I ] - Data buffer
327 bufSize [ I ] - Size of data buffer
328
329 RETURN VALUE:
330 None
331 ===========================================================================*/
QuecPrintHex(void * pBuffer,u16 bufSize)332 void QuecPrintHex(
333 void * pBuffer,
334 u16 bufSize )
335 {
336 char * pPrintBuf;
337 u16 pos;
338 int status;
339
340 if (quec_debug != 1)
341 {
342 return;
343 }
344
345 pPrintBuf = kmalloc( bufSize * 3 + 1, GFP_ATOMIC );
346 if (pPrintBuf == NULL)
347 {
348 DBG( "Unable to allocate buffer\n" );
349 return;
350 }
351 memset( pPrintBuf, 0 , bufSize * 3 + 1 );
352
353 for (pos = 0; pos < bufSize; pos++)
354 {
355 status = snprintf( (pPrintBuf + (pos * 3)),
356 4,
357 "%02X ",
358 *(u8 *)(pBuffer + pos) );
359 if (status != 3)
360 {
361 DBG( "snprintf error %d\n", status );
362 kfree( pPrintBuf );
363 return;
364 }
365 }
366
367 DBG( " : %s\n", pPrintBuf );
368
369 kfree( pPrintBuf );
370 pPrintBuf = NULL;
371 return;
372 }
373
374 /*===========================================================================
375 METHOD:
376 GobiSetDownReason (Public Method)
377
378 DESCRIPTION:
379 Sets mDownReason and turns carrier off
380
381 PARAMETERS
382 pDev [ I ] - Device specific memory
383 reason [ I ] - Reason device is down
384
385 RETURN VALUE:
386 None
387 ===========================================================================*/
QuecGobiSetDownReason(sGobiUSBNet * pDev,u8 reason)388 void QuecGobiSetDownReason(
389 sGobiUSBNet * pDev,
390 u8 reason )
391 {
392 DBG("%s reason=%d, mDownReason=%x\n", __func__, reason, (unsigned)pDev->mDownReason);
393
394 #ifdef QUECTEL_WWAN_QMAP
395 if (reason == NO_NDIS_CONNECTION)
396 return;
397 #endif
398
399 set_bit( reason, &pDev->mDownReason );
400
401 netif_carrier_off( pDev->mpNetDev->net );
402 }
403
404 /*===========================================================================
405 METHOD:
406 GobiClearDownReason (Public Method)
407
408 DESCRIPTION:
409 Clear mDownReason and may turn carrier on
410
411 PARAMETERS
412 pDev [ I ] - Device specific memory
413 reason [ I ] - Reason device is no longer down
414
415 RETURN VALUE:
416 None
417 ===========================================================================*/
QuecGobiClearDownReason(sGobiUSBNet * pDev,u8 reason)418 void QuecGobiClearDownReason(
419 sGobiUSBNet * pDev,
420 u8 reason )
421 {
422 clear_bit( reason, &pDev->mDownReason );
423
424 DBG("%s reason=%d, mDownReason=%x\n", __func__, reason, (unsigned)pDev->mDownReason);
425 #if 0 //(LINUX_VERSION_CODE >= KERNEL_VERSION( 3,11,0 ))
426 netif_carrier_on( pDev->mpNetDev->net );
427 #else
428 if (pDev->mDownReason == 0)
429 {
430 #ifdef QUECTEL_WWAN_QMAP
431 if (pDev->qmap_mode && !pDev->link_state)
432 ;
433 else
434 #endif
435 netif_carrier_on( pDev->mpNetDev->net );
436 }
437 #endif
438 }
439
440 /*===========================================================================
441 METHOD:
442 GobiTestDownReason (Public Method)
443
444 DESCRIPTION:
445 Test mDownReason and returns whether reason is set
446
447 PARAMETERS
448 pDev [ I ] - Device specific memory
449 reason [ I ] - Reason device is down
450
451 RETURN VALUE:
452 bool
453 ===========================================================================*/
QuecGobiTestDownReason(sGobiUSBNet * pDev,u8 reason)454 bool QuecGobiTestDownReason(
455 sGobiUSBNet * pDev,
456 u8 reason )
457 {
458 return test_bit( reason, &pDev->mDownReason );
459 }
460
461 /*=========================================================================*/
462 // Driver level asynchronous read functions
463 /*=========================================================================*/
464
465 /*===========================================================================
466 METHOD:
467 ResubmitIntURB (Public Method)
468
469 DESCRIPTION:
470 Resubmit interrupt URB, re-using same values
471
472 PARAMETERS
473 pIntURB [ I ] - Interrupt URB
474
475 RETURN VALUE:
476 int - 0 for success
477 negative errno for failure
478 ===========================================================================*/
ResubmitIntURB(struct urb * pIntURB)479 static int ResubmitIntURB( struct urb * pIntURB )
480 {
481 int status;
482 int interval;
483
484 // Sanity test
485 if ( (pIntURB == NULL)
486 || (pIntURB->dev == NULL) )
487 {
488 return -EINVAL;
489 }
490
491 // Interval needs reset after every URB completion
492 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,22 ))
493 interval = max((int)(pIntURB->ep->desc.bInterval),
494 (pIntURB->dev->speed == USB_SPEED_HIGH) ? 7 : 3);
495 #else
496 interval = s_interval;
497 #endif
498
499 // Reschedule interrupt URB
500 usb_fill_int_urb( pIntURB,
501 pIntURB->dev,
502 pIntURB->pipe,
503 pIntURB->transfer_buffer,
504 pIntURB->transfer_buffer_length,
505 pIntURB->complete,
506 pIntURB->context,
507 interval );
508 status = usb_submit_urb( pIntURB, GFP_ATOMIC );
509 if (status != 0)
510 {
511 DBG( "Error re-submitting Int URB %d\n", status );
512 }
513
514 return status;
515 }
516
517
518 #ifdef QUECTEL_QMI_MERGE
MergeRecQmiMsg(sQMIDev * pQMIDev,struct urb * pReadURB)519 static int MergeRecQmiMsg( sQMIDev * pQMIDev, struct urb * pReadURB )
520 {
521 sQMIMsgHeader * mHeader;
522 sQMIMsgPacket * mPacket;
523
524 DBG( "%s called \n", __func__ );
525 mPacket = pQMIDev->mpQmiMsgPacket;
526
527 if(pReadURB->actual_length < sizeof(sQMIMsgHeader))
528 {
529 return -1;
530 }
531
532 mHeader = (sQMIMsgHeader *)pReadURB->transfer_buffer;
533 if(le16_to_cpu(mHeader->idenity) != MERGE_PACKET_IDENTITY || le16_to_cpu(mHeader->version) != MERGE_PACKET_VERSION || le16_to_cpu(mHeader->cur_len) > le16_to_cpu(mHeader->total_len))
534 return -1;
535
536 if(le16_to_cpu(mHeader->cur_len) == le16_to_cpu(mHeader->total_len)) {
537 mPacket->len = le16_to_cpu(mHeader->total_len);
538 memcpy(pReadURB->transfer_buffer, pReadURB->transfer_buffer + sizeof(sQMIMsgHeader), mPacket->len);
539 pReadURB->actual_length = mPacket->len;
540 mPacket->len = 0;
541
542 return 0;
543 }
544
545 memcpy(mPacket->buf + mPacket->len, pReadURB->transfer_buffer + sizeof(sQMIMsgHeader), le16_to_cpu(mHeader->cur_len));
546 mPacket->len += le16_to_cpu(mHeader->cur_len);
547
548 if (le16_to_cpu(mHeader->cur_len) < MERGE_PACKET_MAX_PAYLOAD_SIZE || mPacket->len >= le16_to_cpu(mHeader->total_len)) {
549 memcpy(pReadURB->transfer_buffer, mPacket->buf, mPacket->len);
550 pReadURB->actual_length = mPacket->len;
551 mPacket->len = 0;
552 return 0;
553 }
554
555 return -1;
556 }
557 #endif
558
559 /*===========================================================================
560 METHOD:
561 ReadCallback (Public Method)
562
563 DESCRIPTION:
564 Put the data in storage and notify anyone waiting for data
565
566 PARAMETERS
567 pReadURB [ I ] - URB this callback is run for
568
569 RETURN VALUE:
570 None
571 ===========================================================================*/
572 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 ))
ReadCallback(struct urb * pReadURB)573 static void ReadCallback( struct urb * pReadURB )
574 #else
575 static void ReadCallback(struct urb *pReadURB, struct pt_regs *regs)
576 #endif
577 {
578 int result;
579 u16 clientID;
580 sClientMemList * pClientMem;
581 void * pData;
582 void * pDataCopy;
583 u16 dataSize;
584 sGobiUSBNet * pDev;
585 unsigned long flags;
586 u16 transactionID;
587
588 if (pReadURB == NULL)
589 {
590 DBG( "bad read URB\n" );
591 return;
592 }
593
594 pDev = pReadURB->context;
595 if (IsDeviceValid( pDev ) == false)
596 {
597 DBG( "Invalid device!\n" );
598 return;
599 }
600
601 #ifdef READ_QMI_URB_ERROR
602 del_timer(&pDev->mQMIDev.mReadUrbTimer);
603 if ((pReadURB->status == -ECONNRESET) && (pReadURB->actual_length > 0))
604 pReadURB->status = 0;
605 #endif
606
607 if (pReadURB->status != 0)
608 {
609 DBG( "Read status = %d\n", pReadURB->status );
610
611 // Resubmit the interrupt URB
612 ResubmitIntURB( pDev->mQMIDev.mpIntURB );
613
614 return;
615 }
616 DBG( "Read %d bytes\n", pReadURB->actual_length );
617
618 #ifdef QUECTEL_QMI_MERGE
619 if(MergeRecQmiMsg(&pDev->mQMIDev, pReadURB))
620 {
621 DBG( "not a full packet, read again\n");
622 // Resubmit the interrupt URB
623 ResubmitIntURB( pDev->mQMIDev.mpIntURB );
624 return;
625 }
626 #endif
627
628 pData = pReadURB->transfer_buffer;
629 dataSize = pReadURB->actual_length;
630
631 PrintHex( pData, dataSize );
632
633 #ifdef READ_QMI_URB_ERROR
634 if (dataSize < (le16_to_cpu(get_unaligned((u16*)(pData + 1))) + 1)) {
635 dataSize = (le16_to_cpu(get_unaligned((u16*)(pData + 1))) + 1);
636 memset(pReadURB->transfer_buffer + pReadURB->actual_length, 0x00, dataSize - pReadURB->actual_length);
637 INFO( "Read %d / %d bytes\n", pReadURB->actual_length, dataSize);
638 }
639 #endif
640
641 result = ParseQMUX( &clientID,
642 pData,
643 dataSize );
644 if (result < 0)
645 {
646 DBG( "Read error parsing QMUX %d\n", result );
647
648 // Resubmit the interrupt URB
649 ResubmitIntURB( pDev->mQMIDev.mpIntURB );
650
651 return;
652 }
653
654 // Grab transaction ID
655
656 // Data large enough?
657 if (dataSize < result + 3)
658 {
659 DBG( "Data buffer too small to parse\n" );
660
661 // Resubmit the interrupt URB
662 ResubmitIntURB( pDev->mQMIDev.mpIntURB );
663
664 return;
665 }
666
667 // Transaction ID size is 1 for QMICTL, 2 for others
668 if (clientID == QMICTL)
669 {
670 transactionID = *(u8*)(pData + result + 1);
671 }
672 else
673 {
674 transactionID = le16_to_cpu( get_unaligned((u16*)(pData + result + 1)) );
675 }
676
677 // Critical section
678 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
679
680 // Find memory storage for this service and Client ID
681 // Not using FindClientMem because it can't handle broadcasts
682 pClientMem = pDev->mQMIDev.mpClientMemList;
683
684 while (pClientMem != NULL)
685 {
686 if (pClientMem->mClientID == clientID
687 || (pClientMem->mClientID | 0xff00) == clientID)
688 {
689 // Make copy of pData
690 pDataCopy = kmalloc( dataSize, GFP_ATOMIC );
691 if (pDataCopy == NULL)
692 {
693 DBG( "Error allocating client data memory\n" );
694
695 // End critical section
696 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
697
698 // Resubmit the interrupt URB
699 ResubmitIntURB( pDev->mQMIDev.mpIntURB );
700
701 return;
702 }
703
704 memcpy( pDataCopy, pData, dataSize );
705
706 if (AddToReadMemList( pDev,
707 pClientMem->mClientID,
708 transactionID,
709 pDataCopy,
710 dataSize ) == false)
711 {
712 DBG( "Error allocating pReadMemListEntry "
713 "read will be discarded\n" );
714 kfree( pDataCopy );
715
716 // End critical section
717 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
718
719 // Resubmit the interrupt URB
720 ResubmitIntURB( pDev->mQMIDev.mpIntURB );
721
722 return;
723 }
724
725 // Success
726 VDBG( "Creating new readListEntry for client 0x%04X, TID %x\n",
727 clientID,
728 transactionID );
729
730 // Notify this client data exists
731 NotifyAndPopNotifyList( pDev,
732 pClientMem->mClientID,
733 transactionID );
734
735 // Possibly notify poll() that data exists
736 wake_up_interruptible_sync( &pClientMem->mWaitQueue );
737
738 // Not a broadcast
739 if (clientID >> 8 != 0xff)
740 {
741 break;
742 }
743 }
744
745 // Next element
746 pClientMem = pClientMem->mpNext;
747 }
748
749 // End critical section
750 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
751
752 // Resubmit the interrupt URB
753 ResubmitIntURB( pDev->mQMIDev.mpIntURB );
754 }
755
756 /*===========================================================================
757 METHOD:
758 IntCallback (Public Method)
759
760 DESCRIPTION:
761 Data is available, fire off a read URB
762
763 PARAMETERS
764 pIntURB [ I ] - URB this callback is run for
765
766 RETURN VALUE:
767 None
768 ===========================================================================*/
769 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 ))
IntCallback(struct urb * pIntURB)770 static void IntCallback( struct urb * pIntURB )
771 {
772 #else
773 static void IntCallback(struct urb *pIntURB, struct pt_regs *regs)
774 {
775 #endif
776 int status;
777 struct usb_cdc_notification *dr;
778
779 sGobiUSBNet * pDev = (sGobiUSBNet *)pIntURB->context;
780 dr = (struct usb_cdc_notification *)pDev->mQMIDev.mpIntBuffer;
781
782 if (IsDeviceValid( pDev ) == false)
783 {
784 DBG( "Invalid device!\n" );
785 return;
786 }
787
788 // Verify this was a normal interrupt
789 if (pIntURB->status != 0)
790 {
791 DBG( "IntCallback: Int status = %d\n", pIntURB->status );
792
793 // Ignore EOVERFLOW errors
794 if (pIntURB->status != -EOVERFLOW)
795 {
796 // Read 'thread' dies here
797 return;
798 }
799 }
800 else
801 {
802 //TODO cast transfer_buffer to struct usb_cdc_notification
803
804 VDBG( "IntCallback: Encapsulated Response = 0x%llx\n",
805 (*(u64*)pIntURB->transfer_buffer));
806
807 switch (dr->bNotificationType) {
808 case USB_CDC_NOTIFY_RESPONSE_AVAILABLE: //0x01
809 {
810 // Time to read
811 usb_fill_control_urb( pDev->mQMIDev.mpReadURB,
812 pDev->mpNetDev->udev,
813 usb_rcvctrlpipe( pDev->mpNetDev->udev, 0 ),
814 (unsigned char *)pDev->mQMIDev.mpReadSetupPacket,
815 pDev->mQMIDev.mpReadBuffer,
816 DEFAULT_READ_URB_LENGTH,
817 ReadCallback,
818 pDev );
819 #ifdef READ_QMI_URB_ERROR
820 mod_timer( &pDev->mQMIDev.mReadUrbTimer, jiffies + msecs_to_jiffies(300) );
821 #endif
822 status = usb_submit_urb( pDev->mQMIDev.mpReadURB, GFP_ATOMIC );
823 if (status != 0)
824 {
825 DBG("Error submitting Read URB %d\n", status);
826 // Resubmit the interrupt urb
827 ResubmitIntURB(pIntURB);
828 return;
829 }
830
831 // Int URB will be resubmitted during ReadCallback
832 return;
833 }
834 case USB_CDC_NOTIFY_SPEED_CHANGE: //0x2a
835 {
836 DBG( "IntCallback: Connection Speed Change = 0x%llx\n",
837 (*(u64*)pIntURB->transfer_buffer));
838
839 // if upstream or downstream is 0, stop traffic. Otherwise resume it
840 if ((*(u32*)(pIntURB->transfer_buffer + 8) == 0)
841 || (*(u32*)(pIntURB->transfer_buffer + 12) == 0))
842 {
843 GobiSetDownReason( pDev, CDC_CONNECTION_SPEED );
844 DBG( "traffic stopping due to CONNECTION_SPEED_CHANGE\n" );
845 }
846 else
847 {
848 GobiClearDownReason( pDev, CDC_CONNECTION_SPEED );
849 DBG( "resuming traffic due to CONNECTION_SPEED_CHANGE\n" );
850 }
851 }
852 break;
853 default:
854 {
855 DBG( "ignoring invalid interrupt in packet\n" );
856 PrintHex( pIntURB->transfer_buffer, pIntURB->actual_length );
857 }
858 }
859
860 // Resubmit the interrupt urb
861 ResubmitIntURB( pIntURB );
862
863 return;
864 }
865 }
866
867 #ifdef READ_QMI_URB_ERROR
868 static void ReadUrbTimerFunc( struct urb * pReadURB )
869 {
870 int result;
871
872 INFO( "%s called (%ld).\n", __func__, jiffies );
873
874 if ((pReadURB != NULL) && (pReadURB->status == -EINPROGRESS))
875 {
876 // Asynchronously unlink URB. On success, -EINPROGRESS will be returned,
877 // URB status will be set to -ECONNRESET, and ReadCallback() executed
878 result = usb_unlink_urb( pReadURB );
879 INFO( "%s called usb_unlink_urb, result = %d\n", __func__, result);
880 }
881 }
882 #endif
883
884 /*===========================================================================
885 METHOD:
886 StartRead (Public Method)
887
888 DESCRIPTION:
889 Start continuous read "thread" (callback driven)
890
891 Note: In case of error, KillRead() should be run
892 to remove urbs and clean up memory.
893
894 PARAMETERS:
895 pDev [ I ] - Device specific memory
896
897 RETURN VALUE:
898 int - 0 for success
899 negative errno for failure
900 ===========================================================================*/
901 int QuecStartRead( sGobiUSBNet * pDev )
902 {
903 int interval;
904 struct usb_endpoint_descriptor *pendp;
905
906 if (IsDeviceValid( pDev ) == false)
907 {
908 DBG( "Invalid device!\n" );
909 return -ENXIO;
910 }
911
912 // Allocate URB buffers
913 pDev->mQMIDev.mpReadURB = usb_alloc_urb( 0, GFP_KERNEL );
914 if (pDev->mQMIDev.mpReadURB == NULL)
915 {
916 DBG( "Error allocating read urb\n" );
917 return -ENOMEM;
918 }
919
920 #ifdef READ_QMI_URB_ERROR
921 setup_timer( &pDev->mQMIDev.mReadUrbTimer, (void*)ReadUrbTimerFunc, (unsigned long)pDev->mQMIDev.mpReadURB );
922 #endif
923
924 pDev->mQMIDev.mpIntURB = usb_alloc_urb( 0, GFP_KERNEL );
925 if (pDev->mQMIDev.mpIntURB == NULL)
926 {
927 DBG( "Error allocating int urb\n" );
928 usb_free_urb( pDev->mQMIDev.mpReadURB );
929 pDev->mQMIDev.mpReadURB = NULL;
930 return -ENOMEM;
931 }
932
933 // Create data buffers
934 pDev->mQMIDev.mpReadBuffer = kmalloc( DEFAULT_READ_URB_LENGTH, GFP_KERNEL );
935 if (pDev->mQMIDev.mpReadBuffer == NULL)
936 {
937 DBG( "Error allocating read buffer\n" );
938 usb_free_urb( pDev->mQMIDev.mpIntURB );
939 pDev->mQMIDev.mpIntURB = NULL;
940 usb_free_urb( pDev->mQMIDev.mpReadURB );
941 pDev->mQMIDev.mpReadURB = NULL;
942 return -ENOMEM;
943 }
944
945 pDev->mQMIDev.mpIntBuffer = kmalloc( 64, GFP_KERNEL );
946 if (pDev->mQMIDev.mpIntBuffer == NULL)
947 {
948 DBG( "Error allocating int buffer\n" );
949 kfree( pDev->mQMIDev.mpReadBuffer );
950 pDev->mQMIDev.mpReadBuffer = NULL;
951 usb_free_urb( pDev->mQMIDev.mpIntURB );
952 pDev->mQMIDev.mpIntURB = NULL;
953 usb_free_urb( pDev->mQMIDev.mpReadURB );
954 pDev->mQMIDev.mpReadURB = NULL;
955 return -ENOMEM;
956 }
957
958 pDev->mQMIDev.mpReadSetupPacket = kmalloc( sizeof( sURBSetupPacket ),
959 GFP_KERNEL );
960 if (pDev->mQMIDev.mpReadSetupPacket == NULL)
961 {
962 DBG( "Error allocating setup packet buffer\n" );
963 kfree( pDev->mQMIDev.mpIntBuffer );
964 pDev->mQMIDev.mpIntBuffer = NULL;
965 kfree( pDev->mQMIDev.mpReadBuffer );
966 pDev->mQMIDev.mpReadBuffer = NULL;
967 usb_free_urb( pDev->mQMIDev.mpIntURB );
968 pDev->mQMIDev.mpIntURB = NULL;
969 usb_free_urb( pDev->mQMIDev.mpReadURB );
970 pDev->mQMIDev.mpReadURB = NULL;
971 return -ENOMEM;
972 }
973
974 // CDC Get Encapsulated Response packet
975 pDev->mQMIDev.mpReadSetupPacket->mRequestType = 0xA1;
976 pDev->mQMIDev.mpReadSetupPacket->mRequestCode = 1;
977 pDev->mQMIDev.mpReadSetupPacket->mValue = 0;
978 pDev->mQMIDev.mpReadSetupPacket->mIndex =
979 cpu_to_le16(pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber); /* interface number */
980 pDev->mQMIDev.mpReadSetupPacket->mLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
981
982 pendp = GetEndpoint(pDev->mpIntf, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
983 if (pendp == NULL)
984 {
985 DBG( "Invalid interrupt endpoint!\n" );
986 kfree(pDev->mQMIDev.mpReadSetupPacket);
987 pDev->mQMIDev.mpReadSetupPacket = NULL;
988 kfree( pDev->mQMIDev.mpIntBuffer );
989 pDev->mQMIDev.mpIntBuffer = NULL;
990 kfree( pDev->mQMIDev.mpReadBuffer );
991 pDev->mQMIDev.mpReadBuffer = NULL;
992 usb_free_urb( pDev->mQMIDev.mpIntURB );
993 pDev->mQMIDev.mpIntURB = NULL;
994 usb_free_urb( pDev->mQMIDev.mpReadURB );
995 pDev->mQMIDev.mpReadURB = NULL;
996 return -ENXIO;
997 }
998
999 #ifdef QUECTEL_QMI_MERGE
1000 pDev->mQMIDev.mpQmiMsgPacket = kmalloc( sizeof(sQMIMsgPacket), GFP_KERNEL );
1001 if (pDev->mQMIDev.mpQmiMsgPacket == NULL)
1002 {
1003 DBG( "Error allocating qmi msg merge packet buffer!\n" );
1004 kfree(pDev->mQMIDev.mpReadSetupPacket);
1005 pDev->mQMIDev.mpReadSetupPacket = NULL;
1006 kfree( pDev->mQMIDev.mpIntBuffer );
1007 pDev->mQMIDev.mpIntBuffer = NULL;
1008 kfree( pDev->mQMIDev.mpReadBuffer );
1009 pDev->mQMIDev.mpReadBuffer = NULL;
1010 usb_free_urb( pDev->mQMIDev.mpIntURB );
1011 pDev->mQMIDev.mpIntURB = NULL;
1012 usb_free_urb( pDev->mQMIDev.mpReadURB );
1013 pDev->mQMIDev.mpReadURB = NULL;
1014 return -ENOMEM;
1015 }
1016 #endif
1017
1018 // Interval needs reset after every URB completion
1019 interval = max((int)(pendp->bInterval),
1020 (pDev->mpNetDev->udev->speed == USB_SPEED_HIGH) ? 7 : 3);
1021 #if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,22 ))
1022 s_interval = interval;
1023 #endif
1024
1025 // Schedule interrupt URB
1026 usb_fill_int_urb( pDev->mQMIDev.mpIntURB,
1027 pDev->mpNetDev->udev,
1028 /* QMI interrupt endpoint for the following
1029 * interface configuration: DM, NMEA, MDM, NET
1030 */
1031 usb_rcvintpipe( pDev->mpNetDev->udev,
1032 pendp->bEndpointAddress),
1033 pDev->mQMIDev.mpIntBuffer,
1034 min((int)le16_to_cpu(pendp->wMaxPacketSize), 64),
1035 IntCallback,
1036 pDev,
1037 interval );
1038 return usb_submit_urb( pDev->mQMIDev.mpIntURB, GFP_KERNEL );
1039 }
1040
1041 /*===========================================================================
1042 METHOD:
1043 KillRead (Public Method)
1044
1045 DESCRIPTION:
1046 Kill continuous read "thread"
1047
1048 PARAMETERS:
1049 pDev [ I ] - Device specific memory
1050
1051 RETURN VALUE:
1052 None
1053 ===========================================================================*/
1054 void QuecKillRead( sGobiUSBNet * pDev )
1055 {
1056 // Stop reading
1057 if (pDev->mQMIDev.mpReadURB != NULL)
1058 {
1059 DBG( "Killng read URB\n" );
1060 usb_kill_urb( pDev->mQMIDev.mpReadURB );
1061 }
1062
1063 if (pDev->mQMIDev.mpIntURB != NULL)
1064 {
1065 DBG( "Killng int URB\n" );
1066 usb_kill_urb( pDev->mQMIDev.mpIntURB );
1067 }
1068
1069 // Release buffers
1070 kfree( pDev->mQMIDev.mpReadSetupPacket );
1071 pDev->mQMIDev.mpReadSetupPacket = NULL;
1072 kfree( pDev->mQMIDev.mpReadBuffer );
1073 pDev->mQMIDev.mpReadBuffer = NULL;
1074 kfree( pDev->mQMIDev.mpIntBuffer );
1075 pDev->mQMIDev.mpIntBuffer = NULL;
1076
1077 // Release URB's
1078 usb_free_urb( pDev->mQMIDev.mpReadURB );
1079 pDev->mQMIDev.mpReadURB = NULL;
1080 usb_free_urb( pDev->mQMIDev.mpIntURB );
1081 pDev->mQMIDev.mpIntURB = NULL;
1082
1083 #ifdef QUECTEL_QMI_MERGE
1084 kfree( pDev->mQMIDev.mpQmiMsgPacket );
1085 pDev->mQMIDev.mpQmiMsgPacket = NULL;
1086 #endif
1087 }
1088
1089 /*=========================================================================*/
1090 // Internal read/write functions
1091 /*=========================================================================*/
1092
1093 /*===========================================================================
1094 METHOD:
1095 ReadAsync (Public Method)
1096
1097 DESCRIPTION:
1098 Start asynchronous read
1099 NOTE: Reading client's data store, not device
1100
1101 PARAMETERS:
1102 pDev [ I ] - Device specific memory
1103 clientID [ I ] - Requester's client ID
1104 transactionID [ I ] - Transaction ID or 0 for any
1105 pCallback [ I ] - Callback to be executed when data is available
1106 pData [ I ] - Data buffer that willl be passed (unmodified)
1107 to callback
1108
1109 RETURN VALUE:
1110 int - 0 for success
1111 negative errno for failure
1112 ===========================================================================*/
1113 static int ReadAsync(
1114 sGobiUSBNet * pDev,
1115 u16 clientID,
1116 u16 transactionID,
1117 void (*pCallback)(sGobiUSBNet*, u16, void *),
1118 void * pData )
1119 {
1120 sClientMemList * pClientMem;
1121 sReadMemList ** ppReadMemList;
1122
1123 unsigned long flags;
1124
1125 if (IsDeviceValid( pDev ) == false)
1126 {
1127 DBG( "Invalid device!\n" );
1128 return -ENXIO;
1129 }
1130
1131 // Critical section
1132 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1133
1134 // Find memory storage for this client ID
1135 pClientMem = FindClientMem( pDev, clientID );
1136 if (pClientMem == NULL)
1137 {
1138 DBG( "Could not find matching client ID 0x%04X\n",
1139 clientID );
1140
1141 // End critical section
1142 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1143 return -ENXIO;
1144 }
1145
1146 ppReadMemList = &(pClientMem->mpList);
1147
1148 // Does data already exist?
1149 while (*ppReadMemList != NULL)
1150 {
1151 // Is this element our data?
1152 if (transactionID == 0
1153 || transactionID == (*ppReadMemList)->mTransactionID)
1154 {
1155 // End critical section
1156 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1157
1158 // Run our own callback
1159 pCallback( pDev, clientID, pData );
1160
1161 return 0;
1162 }
1163
1164 // Next
1165 ppReadMemList = &(*ppReadMemList)->mpNext;
1166 }
1167
1168 // Data not found, add ourself to list of waiters
1169 if (AddToNotifyList( pDev,
1170 clientID,
1171 transactionID,
1172 pCallback,
1173 pData ) == false)
1174 {
1175 DBG( "Unable to register for notification\n" );
1176 }
1177
1178 // End critical section
1179 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1180
1181 // Success
1182 return 0;
1183 }
1184
1185 /*===========================================================================
1186 METHOD:
1187 UpSem (Public Method)
1188
1189 DESCRIPTION:
1190 Notification function for synchronous read
1191
1192 PARAMETERS:
1193 pDev [ I ] - Device specific memory
1194 clientID [ I ] - Requester's client ID
1195 pData [ I ] - Buffer that holds semaphore to be up()-ed
1196
1197 RETURN VALUE:
1198 None
1199 ===========================================================================*/
1200 #define QUEC_SEM_MAGIC 0x12345678
1201 struct QuecSem {
1202 struct semaphore readSem;
1203 int magic;
1204 };
1205
1206 static void UpSem(
1207 sGobiUSBNet * pDev,
1208 u16 clientID,
1209 void * pData )
1210 {
1211 struct QuecSem *pSem = (struct QuecSem *)pData;
1212
1213 VDBG( "0x%04X\n", clientID );
1214
1215 if (pSem->magic == QUEC_SEM_MAGIC)
1216 up( &(pSem->readSem) );
1217 else
1218 kfree(pSem);
1219 return;
1220 }
1221
1222 /*===========================================================================
1223 METHOD:
1224 ReadSync (Public Method)
1225
1226 DESCRIPTION:
1227 Start synchronous read
1228 NOTE: Reading client's data store, not device
1229
1230 PARAMETERS:
1231 pDev [ I ] - Device specific memory
1232 ppOutBuffer [I/O] - On success, will be filled with a
1233 pointer to read buffer
1234 clientID [ I ] - Requester's client ID
1235 transactionID [ I ] - Transaction ID or 0 for any
1236
1237 RETURN VALUE:
1238 int - size of data read for success
1239 negative errno for failure
1240 ===========================================================================*/
1241 static int ReadSync(
1242 sGobiUSBNet * pDev,
1243 void ** ppOutBuffer,
1244 u16 clientID,
1245 u16 transactionID )
1246 {
1247 int result;
1248 sClientMemList * pClientMem;
1249 sNotifyList ** ppNotifyList, * pDelNotifyListEntry;
1250 struct QuecSem readSem;
1251 void * pData;
1252 unsigned long flags;
1253 u16 dataSize;
1254
1255 if (IsDeviceValid( pDev ) == false)
1256 {
1257 DBG( "Invalid device!\n" );
1258 return -ENXIO;
1259 }
1260
1261 // Critical section
1262 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1263
1264 // Find memory storage for this Client ID
1265 pClientMem = FindClientMem( pDev, clientID );
1266 if (pClientMem == NULL)
1267 {
1268 DBG( "Could not find matching client ID 0x%04X\n",
1269 clientID );
1270
1271 // End critical section
1272 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1273 return -ENXIO;
1274 }
1275
1276 // Note: in cases where read is interrupted,
1277 // this will verify client is still valid
1278 while (PopFromReadMemList( pDev,
1279 clientID,
1280 transactionID,
1281 &pData,
1282 &dataSize ) == false)
1283 {
1284 // Data does not yet exist, wait
1285 sema_init( &readSem.readSem, 0 );
1286 readSem.magic = QUEC_SEM_MAGIC;
1287
1288 // Add ourself to list of waiters
1289 if (AddToNotifyList( pDev,
1290 clientID,
1291 transactionID,
1292 UpSem,
1293 &readSem ) == false)
1294 {
1295 DBG( "unable to register for notification\n" );
1296 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1297 return -EFAULT;
1298 }
1299
1300 // End critical section while we block
1301 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1302
1303 // Wait for notification
1304 result = down_interruptible( &readSem.readSem );
1305 //if (result) INFO("down_interruptible = %d\n", result);
1306 if (result == -EINTR) {
1307 result = down_timeout(&readSem.readSem, msecs_to_jiffies(200));
1308 //if (result) INFO("down_timeout = %d\n", result);
1309 }
1310 if (result != 0)
1311 {
1312 DBG( "Down Timeout %d\n", result );
1313
1314 // readSem will fall out of scope,
1315 // remove from notify list so it's not referenced
1316 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1317 ppNotifyList = &(pClientMem->mpReadNotifyList);
1318 pDelNotifyListEntry = NULL;
1319
1320 // Find and delete matching entry
1321 while (*ppNotifyList != NULL)
1322 {
1323 if ((*ppNotifyList)->mpData == &readSem)
1324 {
1325 pDelNotifyListEntry = *ppNotifyList;
1326 *ppNotifyList = (*ppNotifyList)->mpNext;
1327 kfree( pDelNotifyListEntry );
1328 break;
1329 }
1330
1331 // Next
1332 ppNotifyList = &(*ppNotifyList)->mpNext;
1333 }
1334
1335 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1336 return -EINTR;
1337 }
1338
1339 // Verify device is still valid
1340 if (IsDeviceValid( pDev ) == false)
1341 {
1342 DBG( "Invalid device!\n" );
1343 return -ENXIO;
1344 }
1345
1346 // Restart critical section and continue loop
1347 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1348 }
1349
1350 // End Critical section
1351 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1352
1353 // Success
1354 *ppOutBuffer = pData;
1355
1356 return dataSize;
1357 }
1358
1359 /*===========================================================================
1360 METHOD:
1361 WriteSyncCallback (Public Method)
1362
1363 DESCRIPTION:
1364 Write callback
1365
1366 PARAMETERS
1367 pWriteURB [ I ] - URB this callback is run for
1368
1369 RETURN VALUE:
1370 None
1371 ===========================================================================*/
1372 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 ))
1373 static void WriteSyncCallback( struct urb * pWriteURB )
1374 #else
1375 static void WriteSyncCallback(struct urb *pWriteURB, struct pt_regs *regs)
1376 #endif
1377 {
1378 if (pWriteURB == NULL)
1379 {
1380 DBG( "null urb\n" );
1381 return;
1382 }
1383
1384 DBG( "Write status/size %d/%d\n",
1385 pWriteURB->status,
1386 pWriteURB->actual_length );
1387
1388 // Notify that write has completed by up()-ing semeaphore
1389 up( (struct semaphore * )pWriteURB->context );
1390
1391 return;
1392 }
1393
1394 /*===========================================================================
1395 METHOD:
1396 WriteSync (Public Method)
1397
1398 DESCRIPTION:
1399 Start synchronous write
1400
1401 PARAMETERS:
1402 pDev [ I ] - Device specific memory
1403 pWriteBuffer [ I ] - Data to be written
1404 writeBufferSize [ I ] - Size of data to be written
1405 clientID [ I ] - Client ID of requester
1406
1407 RETURN VALUE:
1408 int - write size (includes QMUX)
1409 negative errno for failure
1410 ===========================================================================*/
1411 static int WriteSync(
1412 sGobiUSBNet * pDev,
1413 char * pWriteBuffer,
1414 int writeBufferSize,
1415 u16 clientID )
1416 {
1417 int result;
1418 struct semaphore writeSem;
1419 struct urb * pWriteURB;
1420 sURBSetupPacket *writeSetup;
1421 unsigned long flags;
1422
1423 if (IsDeviceValid( pDev ) == false)
1424 {
1425 DBG( "Invalid device!\n" );
1426 return -ENXIO;
1427 }
1428
1429 pWriteURB = usb_alloc_urb( 0, GFP_KERNEL );
1430 if (pWriteURB == NULL)
1431 {
1432 DBG( "URB mem error\n" );
1433 return -ENOMEM;
1434 }
1435
1436 // Fill writeBuffer with QMUX
1437 result = FillQMUX( clientID, pWriteBuffer, writeBufferSize );
1438 if (result < 0)
1439 {
1440 usb_free_urb( pWriteURB );
1441 return result;
1442 }
1443
1444 // CDC Send Encapsulated Request packet
1445 writeSetup = kmalloc(sizeof(sURBSetupPacket), GFP_KERNEL);
1446 writeSetup->mRequestType = 0x21;
1447 writeSetup->mRequestCode = 0;
1448 writeSetup->mValue = 0;
1449 writeSetup->mIndex = cpu_to_le16(pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber);
1450 writeSetup->mLength = cpu_to_le16(writeBufferSize);
1451
1452 // Create URB
1453 usb_fill_control_urb( pWriteURB,
1454 pDev->mpNetDev->udev,
1455 usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ),
1456 (unsigned char *)writeSetup,
1457 (void*)pWriteBuffer,
1458 writeBufferSize,
1459 NULL,
1460 pDev );
1461
1462 DBG( "Actual Write:\n" );
1463 PrintHex( pWriteBuffer, writeBufferSize );
1464
1465 sema_init( &writeSem, 0 );
1466
1467 pWriteURB->complete = WriteSyncCallback;
1468 pWriteURB->context = &writeSem;
1469
1470 // Wake device
1471 result = usb_autopm_get_interface( pDev->mpIntf );
1472 if (result < 0)
1473 {
1474 DBG( "unable to resume interface: %d\n", result );
1475
1476 // Likely caused by device going from autosuspend -> full suspend
1477 if (result == -EPERM)
1478 {
1479 #ifdef CONFIG_PM
1480 #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,33 ))
1481 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,18 ))
1482 pDev->mpNetDev->udev->auto_pm = 0;
1483 #endif
1484 #endif
1485 QuecGobiNetSuspend( pDev->mpIntf, PMSG_SUSPEND );
1486 #endif /* CONFIG_PM */
1487 }
1488 usb_free_urb( pWriteURB );
1489 kfree(writeSetup);
1490
1491 return result;
1492 }
1493
1494 // Critical section
1495 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1496
1497 if (AddToURBList( pDev, clientID, pWriteURB ) == false)
1498 {
1499 usb_free_urb( pWriteURB );
1500 kfree(writeSetup);
1501
1502 // End critical section
1503 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1504 usb_autopm_put_interface( pDev->mpIntf );
1505 return -EINVAL;
1506 }
1507
1508 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1509 result = usb_submit_urb( pWriteURB, GFP_KERNEL );
1510 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1511
1512 if (result < 0)
1513 {
1514 DBG( "submit URB error %d\n", result );
1515
1516 // Get URB back so we can destroy it
1517 if (PopFromURBList( pDev, clientID ) != pWriteURB)
1518 {
1519 // This shouldn't happen
1520 DBG( "Didn't get write URB back\n" );
1521 //advoid ReleaseClientID() free again (no PopFromURBList)
1522 }
1523 else
1524 {
1525 usb_free_urb( pWriteURB );
1526 kfree(writeSetup);
1527 }
1528
1529 // End critical section
1530 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1531 usb_autopm_put_interface( pDev->mpIntf );
1532 return result;
1533 }
1534
1535 // End critical section while we block
1536 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1537
1538 // Wait for write to finish
1539 if (1 != 0) //(interruptible != 0)
1540 {
1541 // Allow user interrupts
1542 result = down_interruptible( &writeSem );
1543 //if (result) INFO("down_interruptible = %d\n", result);
1544 if (result == -EINTR) {
1545 result = down_timeout(&writeSem, msecs_to_jiffies(200));
1546 //if (result) INFO("down_interruptible = %d\n", result);
1547 }
1548 }
1549 else
1550 {
1551 // Ignore user interrupts
1552 result = 0;
1553 down( &writeSem );
1554 }
1555
1556 // Write is done, release device
1557 usb_autopm_put_interface( pDev->mpIntf );
1558
1559 // Verify device is still valid
1560 if (IsDeviceValid( pDev ) == false)
1561 {
1562 DBG( "Invalid device!\n" );
1563
1564 usb_kill_urb( pWriteURB );
1565 #if 0 //advoid ReleaseClientID() free again (no PopFromURBList)
1566 usb_free_urb( pWriteURB );
1567 kfree(writeSetup);
1568 #endif
1569 return -ENXIO;
1570 }
1571
1572 // Restart critical section
1573 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1574
1575 // Get URB back so we can destroy it
1576 if (PopFromURBList( pDev, clientID ) != pWriteURB)
1577 {
1578 // This shouldn't happen
1579 DBG( "Didn't get write URB back\n" );
1580
1581 // End critical section
1582 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1583 usb_kill_urb( pWriteURB );
1584 #if 0 //advoid ReleaseClientID() free again (fail PopFromURBList)
1585 usb_free_urb( pWriteURB );
1586 kfree(writeSetup);
1587 #endif
1588 return -EINVAL;
1589 }
1590
1591 // End critical section
1592 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1593
1594 if (result == 0)
1595 {
1596 // Write is finished
1597 if (pWriteURB->status == 0)
1598 {
1599 // Return number of bytes that were supposed to have been written,
1600 // not size of QMI request
1601 result = writeBufferSize;
1602 }
1603 else
1604 {
1605 DBG( "bad status = %d\n", pWriteURB->status );
1606
1607 // Return error value
1608 result = pWriteURB->status;
1609 }
1610 }
1611 else
1612 {
1613 // We have been forcibly interrupted
1614 DBG( "Interrupted %d !!!\n", result );
1615 DBG( "Device may be in bad state and need reset !!!\n" );
1616
1617 // URB has not finished
1618 usb_kill_urb( pWriteURB );
1619 }
1620
1621 usb_free_urb( pWriteURB );
1622 kfree(writeSetup);
1623
1624 return result;
1625 }
1626
1627 /*=========================================================================*/
1628 // Internal memory management functions
1629 /*=========================================================================*/
1630
1631 /*===========================================================================
1632 METHOD:
1633 GetClientID (Public Method)
1634
1635 DESCRIPTION:
1636 Request a QMI client for the input service type and initialize memory
1637 structure
1638
1639 PARAMETERS:
1640 pDev [ I ] - Device specific memory
1641 serviceType [ I ] - Desired QMI service type
1642
1643 RETURN VALUE:
1644 int - Client ID for success (positive)
1645 Negative errno for error
1646 ===========================================================================*/
1647 static int GetClientID(
1648 sGobiUSBNet * pDev,
1649 u8 serviceType )
1650 {
1651 u16 clientID;
1652 sClientMemList ** ppClientMem;
1653 int result;
1654 void * pWriteBuffer;
1655 u16 writeBufferSize;
1656 void * pReadBuffer;
1657 u16 readBufferSize;
1658 unsigned long flags;
1659 u8 transactionID;
1660
1661 if (IsDeviceValid( pDev ) == false)
1662 {
1663 DBG( "Invalid device!\n" );
1664 return -ENXIO;
1665 }
1666
1667 // Run QMI request to be asigned a Client ID
1668 if (serviceType != 0)
1669 {
1670 writeBufferSize = QMICTLGetClientIDReqSize();
1671 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
1672 if (pWriteBuffer == NULL)
1673 {
1674 return -ENOMEM;
1675 }
1676
1677 transactionID = QMIXactionIDGet( pDev );
1678
1679 result = QMICTLGetClientIDReq( pWriteBuffer,
1680 writeBufferSize,
1681 transactionID,
1682 serviceType );
1683 if (result < 0)
1684 {
1685 kfree( pWriteBuffer );
1686 return result;
1687 }
1688
1689
1690 result = WriteSync( pDev,
1691 pWriteBuffer,
1692 writeBufferSize,
1693 QMICTL );
1694 kfree( pWriteBuffer );
1695
1696 if (result < 0)
1697 {
1698 return result;
1699 }
1700
1701 result = ReadSync( pDev,
1702 &pReadBuffer,
1703 QMICTL,
1704 transactionID );
1705 if (result < 0)
1706 {
1707 DBG( "bad read data %d\n", result );
1708 return result;
1709 }
1710 readBufferSize = result;
1711
1712 result = QMICTLGetClientIDResp( pReadBuffer,
1713 readBufferSize,
1714 &clientID );
1715
1716 /* Upon return from QMICTLGetClientIDResp, clientID
1717 * low address contains the Service Number (SN), and
1718 * clientID high address contains Client Number (CN)
1719 * For the ReadCallback to function correctly,we swap
1720 * the SN and CN on a Big Endian architecture.
1721 */
1722 clientID = le16_to_cpu(clientID);
1723
1724 kfree( pReadBuffer );
1725
1726 if (result < 0)
1727 {
1728 return result;
1729 }
1730 }
1731 else
1732 {
1733 // QMI CTL will always have client ID 0
1734 clientID = 0;
1735 }
1736
1737 // Critical section
1738 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1739
1740 // Verify client is not already allocated
1741 if (FindClientMem( pDev, clientID ) != NULL)
1742 {
1743 DBG( "Client memory already exists\n" );
1744
1745 // End Critical section
1746 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1747 return -ETOOMANYREFS;
1748 }
1749
1750 // Go to last entry in client mem list
1751 ppClientMem = &pDev->mQMIDev.mpClientMemList;
1752 while (*ppClientMem != NULL)
1753 {
1754 ppClientMem = &(*ppClientMem)->mpNext;
1755 }
1756
1757 // Create locations for read to place data into
1758 *ppClientMem = kmalloc( sizeof( sClientMemList ), GFP_ATOMIC );
1759 if (*ppClientMem == NULL)
1760 {
1761 DBG( "Error allocating read list\n" );
1762
1763 // End critical section
1764 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1765 return -ENOMEM;
1766 }
1767
1768 (*ppClientMem)->mClientID = clientID;
1769 (*ppClientMem)->mpList = NULL;
1770 (*ppClientMem)->mpReadNotifyList = NULL;
1771 (*ppClientMem)->mpURBList = NULL;
1772 (*ppClientMem)->mpNext = NULL;
1773
1774 // Initialize workqueue for poll()
1775 init_waitqueue_head( &(*ppClientMem)->mWaitQueue );
1776
1777 // End Critical section
1778 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1779
1780 return (int)( (*ppClientMem)->mClientID );
1781 }
1782
1783 /*===========================================================================
1784 METHOD:
1785 ReleaseClientID (Public Method)
1786
1787 DESCRIPTION:
1788 Release QMI client and free memory
1789
1790 PARAMETERS:
1791 pDev [ I ] - Device specific memory
1792 clientID [ I ] - Requester's client ID
1793
1794 RETURN VALUE:
1795 None
1796 ===========================================================================*/
1797 static void ReleaseClientID(
1798 sGobiUSBNet * pDev,
1799 u16 clientID )
1800 {
1801 int result;
1802 sClientMemList ** ppDelClientMem;
1803 sClientMemList * pNextClientMem;
1804 struct urb * pDelURB;
1805 void * pDelData;
1806 u16 dataSize;
1807 void * pWriteBuffer;
1808 u16 writeBufferSize;
1809 void * pReadBuffer;
1810 u16 readBufferSize;
1811 unsigned long flags;
1812 u8 transactionID;
1813
1814 // Is device is still valid?
1815 if (IsDeviceValid( pDev ) == false)
1816 {
1817 DBG( "invalid device\n" );
1818 return;
1819 }
1820
1821 DBG( "releasing 0x%04X\n", clientID );
1822
1823 // Run QMI ReleaseClientID if this isn't QMICTL
1824 if (clientID != QMICTL && pDev->mpNetDev->udev->state)
1825 {
1826 // Note: all errors are non fatal, as we always want to delete
1827 // client memory in latter part of function
1828
1829 writeBufferSize = QMICTLReleaseClientIDReqSize();
1830 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
1831 if (pWriteBuffer == NULL)
1832 {
1833 DBG( "memory error\n" );
1834 }
1835 else
1836 {
1837 transactionID = QMIXactionIDGet( pDev );
1838
1839 result = QMICTLReleaseClientIDReq( pWriteBuffer,
1840 writeBufferSize,
1841 transactionID,
1842 clientID );
1843 if (result < 0)
1844 {
1845 kfree( pWriteBuffer );
1846 DBG( "error %d filling req buffer\n", result );
1847 }
1848 else
1849 {
1850 result = WriteSync( pDev,
1851 pWriteBuffer,
1852 writeBufferSize,
1853 QMICTL );
1854 kfree( pWriteBuffer );
1855
1856 if (result < 0)
1857 {
1858 DBG( "bad write status %d\n", result );
1859 }
1860 else
1861 {
1862 result = ReadSync( pDev,
1863 &pReadBuffer,
1864 QMICTL,
1865 transactionID );
1866 if (result < 0)
1867 {
1868 DBG( "bad read status %d\n", result );
1869 }
1870 else
1871 {
1872 readBufferSize = result;
1873
1874 result = QMICTLReleaseClientIDResp( pReadBuffer,
1875 readBufferSize );
1876 kfree( pReadBuffer );
1877
1878 if (result < 0)
1879 {
1880 DBG( "error %d parsing response\n", result );
1881 }
1882 }
1883 }
1884 }
1885 }
1886 }
1887
1888 // Cleaning up client memory
1889
1890 // Critical section
1891 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1892
1893 // Can't use FindClientMem, I need to keep pointer of previous
1894 ppDelClientMem = &pDev->mQMIDev.mpClientMemList;
1895 while (*ppDelClientMem != NULL)
1896 {
1897 if ((*ppDelClientMem)->mClientID == clientID)
1898 {
1899 pNextClientMem = (*ppDelClientMem)->mpNext;
1900
1901 // Notify all clients
1902 while (NotifyAndPopNotifyList( pDev,
1903 clientID,
1904 0 ) == true );
1905
1906 // Kill and free all URB's
1907 pDelURB = PopFromURBList( pDev, clientID );
1908 while (pDelURB != NULL)
1909 {
1910 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1911 usb_kill_urb( pDelURB );
1912 usb_free_urb( pDelURB );
1913 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
1914 pDelURB = PopFromURBList( pDev, clientID );
1915 }
1916
1917 // Free any unread data
1918 while (PopFromReadMemList( pDev,
1919 clientID,
1920 0,
1921 &pDelData,
1922 &dataSize ) == true )
1923 {
1924 kfree( pDelData );
1925 }
1926
1927 // Delete client Mem
1928 if (!waitqueue_active( &(*ppDelClientMem)->mWaitQueue))
1929 kfree( *ppDelClientMem );
1930 else
1931 INFO("memory leak!\n");
1932
1933 // Overwrite the pointer that was to this client mem
1934 *ppDelClientMem = pNextClientMem;
1935 }
1936 else
1937 {
1938 // I now point to (a pointer of ((the node I was at)'s mpNext))
1939 ppDelClientMem = &(*ppDelClientMem)->mpNext;
1940 }
1941 }
1942
1943 // End Critical section
1944 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
1945
1946 return;
1947 }
1948
1949 /*===========================================================================
1950 METHOD:
1951 FindClientMem (Public Method)
1952
1953 DESCRIPTION:
1954 Find this client's memory
1955
1956 Caller MUST have lock on mClientMemLock
1957
1958 PARAMETERS:
1959 pDev [ I ] - Device specific memory
1960 clientID [ I ] - Requester's client ID
1961
1962 RETURN VALUE:
1963 sClientMemList - Pointer to requested sClientMemList for success
1964 NULL for error
1965 ===========================================================================*/
1966 static sClientMemList * FindClientMem(
1967 sGobiUSBNet * pDev,
1968 u16 clientID )
1969 {
1970 sClientMemList * pClientMem;
1971
1972 if (IsDeviceValid( pDev ) == false)
1973 {
1974 DBG( "Invalid device\n" );
1975 return NULL;
1976 }
1977
1978 #ifdef CONFIG_SMP
1979 // Verify Lock
1980 if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
1981 {
1982 DBG( "unlocked\n" );
1983 BUG();
1984 }
1985 #endif
1986
1987 pClientMem = pDev->mQMIDev.mpClientMemList;
1988 while (pClientMem != NULL)
1989 {
1990 if (pClientMem->mClientID == clientID)
1991 {
1992 // Success
1993 VDBG("Found client's 0x%x memory\n", clientID);
1994 return pClientMem;
1995 }
1996
1997 pClientMem = pClientMem->mpNext;
1998 }
1999
2000 DBG( "Could not find client mem 0x%04X\n", clientID );
2001 return NULL;
2002 }
2003
2004 /*===========================================================================
2005 METHOD:
2006 AddToReadMemList (Public Method)
2007
2008 DESCRIPTION:
2009 Add Data to this client's ReadMem list
2010
2011 Caller MUST have lock on mClientMemLock
2012
2013 PARAMETERS:
2014 pDev [ I ] - Device specific memory
2015 clientID [ I ] - Requester's client ID
2016 transactionID [ I ] - Transaction ID or 0 for any
2017 pData [ I ] - Data to add
2018 dataSize [ I ] - Size of data to add
2019
2020 RETURN VALUE:
2021 bool
2022 ===========================================================================*/
2023 static bool AddToReadMemList(
2024 sGobiUSBNet * pDev,
2025 u16 clientID,
2026 u16 transactionID,
2027 void * pData,
2028 u16 dataSize )
2029 {
2030 sClientMemList * pClientMem;
2031 sReadMemList ** ppThisReadMemList;
2032
2033 #ifdef CONFIG_SMP
2034 // Verify Lock
2035 if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2036 {
2037 DBG( "unlocked\n" );
2038 BUG();
2039 }
2040 #endif
2041
2042 // Get this client's memory location
2043 pClientMem = FindClientMem( pDev, clientID );
2044 if (pClientMem == NULL)
2045 {
2046 DBG( "Could not find this client's memory 0x%04X\n",
2047 clientID );
2048
2049 return false;
2050 }
2051
2052 // Go to last ReadMemList entry
2053 ppThisReadMemList = &pClientMem->mpList;
2054 while (*ppThisReadMemList != NULL)
2055 {
2056 ppThisReadMemList = &(*ppThisReadMemList)->mpNext;
2057 }
2058
2059 *ppThisReadMemList = kmalloc( sizeof( sReadMemList ), GFP_ATOMIC );
2060 if (*ppThisReadMemList == NULL)
2061 {
2062 DBG( "Mem error\n" );
2063
2064 return false;
2065 }
2066
2067 (*ppThisReadMemList)->mpNext = NULL;
2068 (*ppThisReadMemList)->mpData = pData;
2069 (*ppThisReadMemList)->mDataSize = dataSize;
2070 (*ppThisReadMemList)->mTransactionID = transactionID;
2071
2072 return true;
2073 }
2074
2075 /*===========================================================================
2076 METHOD:
2077 PopFromReadMemList (Public Method)
2078
2079 DESCRIPTION:
2080 Remove data from this client's ReadMem list if it matches
2081 the specified transaction ID.
2082
2083 Caller MUST have lock on mClientMemLock
2084
2085 PARAMETERS:
2086 pDev [ I ] - Device specific memory
2087 clientID [ I ] - Requester's client ID
2088 transactionID [ I ] - Transaction ID or 0 for any
2089 ppData [I/O] - On success, will be filled with a
2090 pointer to read buffer
2091 pDataSize [I/O] - On succces, will be filled with the
2092 read buffer's size
2093
2094 RETURN VALUE:
2095 bool
2096 ===========================================================================*/
2097 static bool PopFromReadMemList(
2098 sGobiUSBNet * pDev,
2099 u16 clientID,
2100 u16 transactionID,
2101 void ** ppData,
2102 u16 * pDataSize )
2103 {
2104 sClientMemList * pClientMem;
2105 sReadMemList * pDelReadMemList, ** ppReadMemList;
2106
2107 #ifdef CONFIG_SMP
2108 // Verify Lock
2109 if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2110 {
2111 DBG( "unlocked\n" );
2112 BUG();
2113 }
2114 #endif
2115
2116 // Get this client's memory location
2117 pClientMem = FindClientMem( pDev, clientID );
2118 if (pClientMem == NULL)
2119 {
2120 DBG( "Could not find this client's memory 0x%04X\n",
2121 clientID );
2122
2123 return false;
2124 }
2125
2126 ppReadMemList = &(pClientMem->mpList);
2127 pDelReadMemList = NULL;
2128
2129 // Find first message that matches this transaction ID
2130 while (*ppReadMemList != NULL)
2131 {
2132 // Do we care about transaction ID?
2133 if (transactionID == 0
2134 || transactionID == (*ppReadMemList)->mTransactionID )
2135 {
2136 pDelReadMemList = *ppReadMemList;
2137 VDBG( "*ppReadMemList = 0x%p pDelReadMemList = 0x%p\n",
2138 *ppReadMemList, pDelReadMemList );
2139 break;
2140 }
2141
2142 VDBG( "skipping 0x%04X data TID = %x\n", clientID, (*ppReadMemList)->mTransactionID );
2143
2144 // Next
2145 ppReadMemList = &(*ppReadMemList)->mpNext;
2146 }
2147 VDBG( "*ppReadMemList = 0x%p pDelReadMemList = 0x%p\n",
2148 *ppReadMemList, pDelReadMemList );
2149 if (pDelReadMemList != NULL)
2150 {
2151 *ppReadMemList = (*ppReadMemList)->mpNext;
2152
2153 // Copy to output
2154 *ppData = pDelReadMemList->mpData;
2155 *pDataSize = pDelReadMemList->mDataSize;
2156 VDBG( "*ppData = 0x%p pDataSize = %u\n",
2157 *ppData, *pDataSize );
2158
2159 // Free memory
2160 kfree( pDelReadMemList );
2161
2162 return true;
2163 }
2164 else
2165 {
2166 DBG( "No read memory to pop, Client 0x%04X, TID = %x\n",
2167 clientID,
2168 transactionID );
2169 return false;
2170 }
2171 }
2172
2173 /*===========================================================================
2174 METHOD:
2175 AddToNotifyList (Public Method)
2176
2177 DESCRIPTION:
2178 Add Notify entry to this client's notify List
2179
2180 Caller MUST have lock on mClientMemLock
2181
2182 PARAMETERS:
2183 pDev [ I ] - Device specific memory
2184 clientID [ I ] - Requester's client ID
2185 transactionID [ I ] - Transaction ID or 0 for any
2186 pNotifyFunct [ I ] - Callback function to be run when data is available
2187 pData [ I ] - Data buffer that willl be passed (unmodified)
2188 to callback
2189
2190 RETURN VALUE:
2191 bool
2192 ===========================================================================*/
2193 static bool AddToNotifyList(
2194 sGobiUSBNet * pDev,
2195 u16 clientID,
2196 u16 transactionID,
2197 void (* pNotifyFunct)(sGobiUSBNet *, u16, void *),
2198 void * pData )
2199 {
2200 sClientMemList * pClientMem;
2201 sNotifyList ** ppThisNotifyList;
2202
2203 #ifdef CONFIG_SMP
2204 // Verify Lock
2205 if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2206 {
2207 DBG( "unlocked\n" );
2208 BUG();
2209 }
2210 #endif
2211
2212 // Get this client's memory location
2213 pClientMem = FindClientMem( pDev, clientID );
2214 if (pClientMem == NULL)
2215 {
2216 DBG( "Could not find this client's memory 0x%04X\n", clientID );
2217 return false;
2218 }
2219
2220 // Go to last URBList entry
2221 ppThisNotifyList = &pClientMem->mpReadNotifyList;
2222 while (*ppThisNotifyList != NULL)
2223 {
2224 ppThisNotifyList = &(*ppThisNotifyList)->mpNext;
2225 }
2226
2227 *ppThisNotifyList = kmalloc( sizeof( sNotifyList ), GFP_ATOMIC );
2228 if (*ppThisNotifyList == NULL)
2229 {
2230 DBG( "Mem error\n" );
2231 return false;
2232 }
2233
2234 (*ppThisNotifyList)->mpNext = NULL;
2235 (*ppThisNotifyList)->mpNotifyFunct = pNotifyFunct;
2236 (*ppThisNotifyList)->mpData = pData;
2237 (*ppThisNotifyList)->mTransactionID = transactionID;
2238
2239 return true;
2240 }
2241
2242 /*===========================================================================
2243 METHOD:
2244 NotifyAndPopNotifyList (Public Method)
2245
2246 DESCRIPTION:
2247 Remove first Notify entry from this client's notify list
2248 and Run function
2249
2250 Caller MUST have lock on mClientMemLock
2251
2252 PARAMETERS:
2253 pDev [ I ] - Device specific memory
2254 clientID [ I ] - Requester's client ID
2255 transactionID [ I ] - Transaction ID or 0 for any
2256
2257 RETURN VALUE:
2258 bool
2259 ===========================================================================*/
2260 static bool NotifyAndPopNotifyList(
2261 sGobiUSBNet * pDev,
2262 u16 clientID,
2263 u16 transactionID )
2264 {
2265 sClientMemList * pClientMem;
2266 sNotifyList * pDelNotifyList, ** ppNotifyList;
2267
2268 #ifdef CONFIG_SMP
2269 // Verify Lock
2270 if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2271 {
2272 DBG( "unlocked\n" );
2273 BUG();
2274 }
2275 #endif
2276
2277 // Get this client's memory location
2278 pClientMem = FindClientMem( pDev, clientID );
2279 if (pClientMem == NULL)
2280 {
2281 DBG( "Could not find this client's memory 0x%04X\n", clientID );
2282 return false;
2283 }
2284
2285 ppNotifyList = &(pClientMem->mpReadNotifyList);
2286 pDelNotifyList = NULL;
2287
2288 // Remove from list
2289 while (*ppNotifyList != NULL)
2290 {
2291 // Do we care about transaction ID?
2292 if (transactionID == 0
2293 || (*ppNotifyList)->mTransactionID == 0
2294 || transactionID == (*ppNotifyList)->mTransactionID)
2295 {
2296 pDelNotifyList = *ppNotifyList;
2297 break;
2298 }
2299
2300 DBG( "skipping data TID = %x\n", (*ppNotifyList)->mTransactionID );
2301
2302 // next
2303 ppNotifyList = &(*ppNotifyList)->mpNext;
2304 }
2305
2306 if (pDelNotifyList != NULL)
2307 {
2308 // Remove element
2309 *ppNotifyList = (*ppNotifyList)->mpNext;
2310
2311 // Run notification function
2312 if (pDelNotifyList->mpNotifyFunct != NULL)
2313 {
2314 // Unlock for callback
2315 spin_unlock( &pDev->mQMIDev.mClientMemLock );
2316
2317 pDelNotifyList->mpNotifyFunct( pDev,
2318 clientID,
2319 pDelNotifyList->mpData );
2320
2321 // Restore lock
2322 spin_lock( &pDev->mQMIDev.mClientMemLock );
2323 }
2324
2325 // Delete memory
2326 kfree( pDelNotifyList );
2327
2328 return true;
2329 }
2330 else
2331 {
2332 DBG( "no one to notify for TID %x\n", transactionID );
2333
2334 return false;
2335 }
2336 }
2337
2338 /*===========================================================================
2339 METHOD:
2340 AddToURBList (Public Method)
2341
2342 DESCRIPTION:
2343 Add URB to this client's URB list
2344
2345 Caller MUST have lock on mClientMemLock
2346
2347 PARAMETERS:
2348 pDev [ I ] - Device specific memory
2349 clientID [ I ] - Requester's client ID
2350 pURB [ I ] - URB to be added
2351
2352 RETURN VALUE:
2353 bool
2354 ===========================================================================*/
2355 static bool AddToURBList(
2356 sGobiUSBNet * pDev,
2357 u16 clientID,
2358 struct urb * pURB )
2359 {
2360 sClientMemList * pClientMem;
2361 sURBList ** ppThisURBList;
2362
2363 #ifdef CONFIG_SMP
2364 // Verify Lock
2365 if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2366 {
2367 DBG( "unlocked\n" );
2368 BUG();
2369 }
2370 #endif
2371
2372 // Get this client's memory location
2373 pClientMem = FindClientMem( pDev, clientID );
2374 if (pClientMem == NULL)
2375 {
2376 DBG( "Could not find this client's memory 0x%04X\n", clientID );
2377 return false;
2378 }
2379
2380 // Go to last URBList entry
2381 ppThisURBList = &pClientMem->mpURBList;
2382 while (*ppThisURBList != NULL)
2383 {
2384 ppThisURBList = &(*ppThisURBList)->mpNext;
2385 }
2386
2387 *ppThisURBList = kmalloc( sizeof( sURBList ), GFP_ATOMIC );
2388 if (*ppThisURBList == NULL)
2389 {
2390 DBG( "Mem error\n" );
2391 return false;
2392 }
2393
2394 (*ppThisURBList)->mpNext = NULL;
2395 (*ppThisURBList)->mpURB = pURB;
2396
2397 return true;
2398 }
2399
2400 /*===========================================================================
2401 METHOD:
2402 PopFromURBList (Public Method)
2403
2404 DESCRIPTION:
2405 Remove URB from this client's URB list
2406
2407 Caller MUST have lock on mClientMemLock
2408
2409 PARAMETERS:
2410 pDev [ I ] - Device specific memory
2411 clientID [ I ] - Requester's client ID
2412
2413 RETURN VALUE:
2414 struct urb - Pointer to requested client's URB
2415 NULL for error
2416 ===========================================================================*/
2417 static struct urb * PopFromURBList(
2418 sGobiUSBNet * pDev,
2419 u16 clientID )
2420 {
2421 sClientMemList * pClientMem;
2422 sURBList * pDelURBList;
2423 struct urb * pURB;
2424
2425 #ifdef CONFIG_SMP
2426 // Verify Lock
2427 if (spin_is_locked( &pDev->mQMIDev.mClientMemLock ) == 0)
2428 {
2429 DBG( "unlocked\n" );
2430 BUG();
2431 }
2432 #endif
2433
2434 // Get this client's memory location
2435 pClientMem = FindClientMem( pDev, clientID );
2436 if (pClientMem == NULL)
2437 {
2438 DBG( "Could not find this client's memory 0x%04X\n", clientID );
2439 return NULL;
2440 }
2441
2442 // Remove from list
2443 if (pClientMem->mpURBList != NULL)
2444 {
2445 pDelURBList = pClientMem->mpURBList;
2446 pClientMem->mpURBList = pClientMem->mpURBList->mpNext;
2447
2448 // Copy to output
2449 pURB = pDelURBList->mpURB;
2450
2451 // Delete memory
2452 kfree( pDelURBList );
2453
2454 return pURB;
2455 }
2456 else
2457 {
2458 DBG( "No URB's to pop\n" );
2459
2460 return NULL;
2461 }
2462 }
2463
2464 #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 3,19,0 ))
2465 #ifndef f_dentry
2466 #define f_dentry f_path.dentry
2467 #endif
2468 #endif
2469
2470 /*=========================================================================*/
2471 // Internal userspace wrappers
2472 /*=========================================================================*/
2473
2474 /*===========================================================================
2475 METHOD:
2476 UserspaceunlockedIOCTL (Public Method)
2477
2478 DESCRIPTION:
2479 Internal wrapper for Userspace IOCTL interface
2480
2481 PARAMETERS
2482 pFilp [ I ] - userspace file descriptor
2483 cmd [ I ] - IOCTL command
2484 arg [ I ] - IOCTL argument
2485
2486 RETURN VALUE:
2487 long - 0 for success
2488 Negative errno for failure
2489 ===========================================================================*/
2490 static long UserspaceunlockedIOCTL(
2491 struct file * pFilp,
2492 unsigned int cmd,
2493 unsigned long arg )
2494 {
2495 int result;
2496 u32 devVIDPID;
2497
2498 sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2499
2500 if (pFilpData == NULL)
2501 {
2502 DBG( "Bad file data\n" );
2503 return -EBADF;
2504 }
2505
2506 if (IsDeviceValid( pFilpData->mpDev ) == false)
2507 {
2508 DBG( "Invalid device! Updating f_ops\n" );
2509 pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
2510 return -ENXIO;
2511 }
2512
2513 switch (cmd)
2514 {
2515 case IOCTL_QMI_GET_SERVICE_FILE:
2516 DBG( "Setting up QMI for service %lu\n", arg );
2517 if ((u8)arg == 0)
2518 {
2519 DBG( "Cannot use QMICTL from userspace\n" );
2520 return -EINVAL;
2521 }
2522
2523 // Connection is already setup
2524 if (pFilpData->mClientID != (u16)-1)
2525 {
2526 DBG( "Close the current connection before opening a new one\n" );
2527 return -EBADR;
2528 }
2529
2530 result = GetClientID( pFilpData->mpDev, (u8)arg );
2531 // it seems QMIWDA only allow one client, if the last quectel-CM donot realese it (killed by SIGKILL).
2532 // can force release it at here
2533 #if 1
2534 if (result < 0 && (u8)arg == QMIWDA)
2535 {
2536 ReleaseClientID( pFilpData->mpDev, QMIWDA | (1 << 8) );
2537 result = GetClientID( pFilpData->mpDev, (u8)arg );
2538 }
2539 #endif
2540 if (result < 0)
2541 {
2542 return result;
2543 }
2544 pFilpData->mClientID = (u16)result;
2545 DBG("pFilpData->mClientID = 0x%x\n", pFilpData->mClientID );
2546 return 0;
2547 break;
2548
2549
2550 case IOCTL_QMI_GET_DEVICE_VIDPID:
2551 if (arg == 0)
2552 {
2553 DBG( "Bad VIDPID buffer\n" );
2554 return -EINVAL;
2555 }
2556
2557 // Extra verification
2558 if (pFilpData->mpDev->mpNetDev == 0)
2559 {
2560 DBG( "Bad mpNetDev\n" );
2561 return -ENOMEM;
2562 }
2563 if (pFilpData->mpDev->mpNetDev->udev == 0)
2564 {
2565 DBG( "Bad udev\n" );
2566 return -ENOMEM;
2567 }
2568
2569 devVIDPID = ((le16_to_cpu( pFilpData->mpDev->mpNetDev->udev->descriptor.idVendor ) << 16)
2570 + le16_to_cpu( pFilpData->mpDev->mpNetDev->udev->descriptor.idProduct ) );
2571
2572 result = copy_to_user( (unsigned int *)arg, &devVIDPID, 4 );
2573 if (result != 0)
2574 {
2575 DBG( "Copy to userspace failure %d\n", result );
2576 }
2577
2578 return result;
2579
2580 break;
2581
2582 case IOCTL_QMI_GET_DEVICE_MEID:
2583 if (arg == 0)
2584 {
2585 DBG( "Bad MEID buffer\n" );
2586 return -EINVAL;
2587 }
2588
2589 result = copy_to_user( (unsigned int *)arg, &pFilpData->mpDev->mMEID[0], 14 );
2590 if (result != 0)
2591 {
2592 DBG( "Copy to userspace failure %d\n", result );
2593 }
2594
2595 return result;
2596
2597 break;
2598
2599 default:
2600 return -EBADRQC;
2601 }
2602 }
2603
2604 /*=========================================================================*/
2605 // Userspace wrappers
2606 /*=========================================================================*/
2607
2608 /*===========================================================================
2609 METHOD:
2610 UserspaceOpen (Public Method)
2611
2612 DESCRIPTION:
2613 Userspace open
2614 IOCTL must be called before reads or writes
2615
2616 PARAMETERS
2617 pInode [ I ] - kernel file descriptor
2618 pFilp [ I ] - userspace file descriptor
2619
2620 RETURN VALUE:
2621 int - 0 for success
2622 Negative errno for failure
2623 ===========================================================================*/
2624 static int UserspaceOpen(
2625 struct inode * pInode,
2626 struct file * pFilp )
2627 {
2628 sQMIFilpStorage * pFilpData;
2629
2630 // Optain device pointer from pInode
2631 sQMIDev * pQMIDev = container_of( pInode->i_cdev,
2632 sQMIDev,
2633 mCdev );
2634 sGobiUSBNet * pDev = container_of( pQMIDev,
2635 sGobiUSBNet,
2636 mQMIDev );
2637
2638 if (pDev->mbMdm9x07)
2639 {
2640 atomic_inc(&pDev->refcount);
2641 if (!pDev->mbQMIReady) {
2642 if (wait_for_completion_interruptible_timeout(&pDev->mQMIReadyCompletion, 15*HZ) <= 0) {
2643 if (atomic_dec_and_test(&pDev->refcount)) {
2644 kfree( pDev );
2645 }
2646 return -ETIMEDOUT;
2647 }
2648 }
2649 atomic_dec(&pDev->refcount);
2650 }
2651
2652 if (IsDeviceValid( pDev ) == false)
2653 {
2654 DBG( "Invalid device\n" );
2655 return -ENXIO;
2656 }
2657
2658 // Setup data in pFilp->private_data
2659 pFilp->private_data = kmalloc( sizeof( sQMIFilpStorage ), GFP_KERNEL );
2660 if (pFilp->private_data == NULL)
2661 {
2662 DBG( "Mem error\n" );
2663 return -ENOMEM;
2664 }
2665
2666 pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2667 pFilpData->mClientID = (u16)-1;
2668 pFilpData->mpDev = pDev;
2669 atomic_inc(&pFilpData->mpDev->refcount);
2670
2671 return 0;
2672 }
2673
2674 /*===========================================================================
2675 METHOD:
2676 UserspaceIOCTL (Public Method)
2677
2678 DESCRIPTION:
2679 Userspace IOCTL functions
2680
2681 PARAMETERS
2682 pUnusedInode [ I ] - (unused) kernel file descriptor
2683 pFilp [ I ] - userspace file descriptor
2684 cmd [ I ] - IOCTL command
2685 arg [ I ] - IOCTL argument
2686
2687 RETURN VALUE:
2688 int - 0 for success
2689 Negative errno for failure
2690 ===========================================================================*/
2691 #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,36 ))
2692 static int UserspaceIOCTL(
2693 struct inode * pUnusedInode,
2694 struct file * pFilp,
2695 unsigned int cmd,
2696 unsigned long arg )
2697 {
2698 // call the internal wrapper function
2699 return (int)UserspaceunlockedIOCTL( pFilp, cmd, arg );
2700 }
2701 #endif
2702
2703 #ifdef quectel_no_for_each_process
2704 static int UserspaceClose(
2705 struct inode * pInode,
2706 struct file * pFilp )
2707 {
2708 sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2709
2710 if (pFilpData == NULL)
2711 {
2712 DBG( "bad file data\n" );
2713 return -EBADF;
2714 }
2715
2716 atomic_dec(&pFilpData->mpDev->refcount);
2717
2718 if (IsDeviceValid( pFilpData->mpDev ) == false)
2719 {
2720 return -ENXIO;
2721 }
2722
2723 DBG( "0x%04X\n", pFilpData->mClientID );
2724
2725 // Disable pFilpData so they can't keep sending read or write
2726 // should this function hang
2727 // Note: memory pointer is still saved in pFilpData to be deleted later
2728 pFilp->private_data = NULL;
2729
2730 if (pFilpData->mClientID != (u16)-1)
2731 {
2732 if (pFilpData->mpDev->mbDeregisterQMIDevice)
2733 pFilpData->mClientID = (u16)-1; //DeregisterQMIDevice() will release this ClientID
2734 else
2735 ReleaseClientID( pFilpData->mpDev,
2736 pFilpData->mClientID );
2737 }
2738
2739 kfree( pFilpData );
2740 return 0;
2741 }
2742 #else
2743 /*===========================================================================
2744 METHOD:
2745 UserspaceClose (Public Method)
2746
2747 DESCRIPTION:
2748 Userspace close
2749 Release client ID and free memory
2750
2751 PARAMETERS
2752 pFilp [ I ] - userspace file descriptor
2753 unusedFileTable [ I ] - (unused) file table
2754
2755 RETURN VALUE:
2756 int - 0 for success
2757 Negative errno for failure
2758 ===========================================================================*/
2759 #if (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,14 ))
2760 int UserspaceClose(
2761 struct file * pFilp,
2762 fl_owner_t unusedFileTable )
2763 #else
2764 int UserspaceClose( struct file * pFilp )
2765 #endif
2766 {
2767 sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2768 struct task_struct * pEachTask;
2769 struct fdtable * pFDT;
2770 int count = 0;
2771 int used = 0;
2772 unsigned long flags;
2773
2774 if (pFilpData == NULL)
2775 {
2776 DBG( "bad file data\n" );
2777 return -EBADF;
2778 }
2779
2780 // Fallthough. If f_count == 1 no need to do more checks
2781 #if (LINUX_VERSION_CODE <= KERNEL_VERSION( 2,6,24 ))
2782 if (atomic_read( &pFilp->f_count ) != 1)
2783 #else
2784 if (atomic_long_read( &pFilp->f_count ) != 1)
2785 #endif
2786 {
2787 rcu_read_lock();
2788 for_each_process( pEachTask )
2789 {
2790 task_lock(pEachTask);
2791 if (pEachTask == NULL || pEachTask->files == NULL)
2792 {
2793 // Some tasks may not have files (e.g. Xsession)
2794 task_unlock(pEachTask);
2795 continue;
2796 }
2797 spin_lock_irqsave( &pEachTask->files->file_lock, flags );
2798 task_unlock(pEachTask); //kernel/exit.c:do_exit() -> fs/file.c:exit_files()
2799 pFDT = files_fdtable( pEachTask->files );
2800 for (count = 0; count < pFDT->max_fds; count++)
2801 {
2802 // Before this function was called, this file was removed
2803 // from our task's file table so if we find it in a file
2804 // table then it is being used by another task
2805 if (pFDT->fd[count] == pFilp)
2806 {
2807 used++;
2808 break;
2809 }
2810 }
2811 spin_unlock_irqrestore( &pEachTask->files->file_lock, flags );
2812 }
2813 rcu_read_unlock();
2814
2815 if (used > 0)
2816 {
2817 DBG( "not closing, as this FD is open by %d other process\n", used );
2818 return 0;
2819 }
2820 }
2821
2822 if (IsDeviceValid( pFilpData->mpDev ) == false)
2823 {
2824 DBG( "Invalid device! Updating f_ops\n" );
2825 pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
2826 return -ENXIO;
2827 }
2828
2829 DBG( "0x%04X\n", pFilpData->mClientID );
2830
2831 // Disable pFilpData so they can't keep sending read or write
2832 // should this function hang
2833 // Note: memory pointer is still saved in pFilpData to be deleted later
2834 pFilp->private_data = NULL;
2835
2836 if (pFilpData->mClientID != (u16)-1)
2837 {
2838 if (pFilpData->mpDev->mbDeregisterQMIDevice)
2839 pFilpData->mClientID = (u16)-1; //DeregisterQMIDevice() will release this ClientID
2840 else
2841 ReleaseClientID( pFilpData->mpDev,
2842 pFilpData->mClientID );
2843 }
2844 atomic_dec(&pFilpData->mpDev->refcount);
2845
2846 kfree( pFilpData );
2847 return 0;
2848 }
2849 #endif
2850
2851 /*===========================================================================
2852 METHOD:
2853 UserspaceRead (Public Method)
2854
2855 DESCRIPTION:
2856 Userspace read (synchronous)
2857
2858 PARAMETERS
2859 pFilp [ I ] - userspace file descriptor
2860 pBuf [ I ] - read buffer
2861 size [ I ] - size of read buffer
2862 pUnusedFpos [ I ] - (unused) file position
2863
2864 RETURN VALUE:
2865 ssize_t - Number of bytes read for success
2866 Negative errno for failure
2867 ===========================================================================*/
2868 static ssize_t UserspaceRead(
2869 struct file * pFilp,
2870 char __user * pBuf,
2871 size_t size,
2872 loff_t * pUnusedFpos )
2873 {
2874 int result;
2875 void * pReadData = NULL;
2876 void * pSmallReadData;
2877 sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2878
2879 if (pFilpData == NULL)
2880 {
2881 DBG( "Bad file data\n" );
2882 return -EBADF;
2883 }
2884
2885 if (IsDeviceValid( pFilpData->mpDev ) == false)
2886 {
2887 DBG( "Invalid device! Updating f_ops\n" );
2888 pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
2889 return -ENXIO;
2890 }
2891
2892 if (pFilpData->mClientID == (u16)-1)
2893 {
2894 DBG( "Client ID must be set before reading 0x%04X\n",
2895 pFilpData->mClientID );
2896 return -EBADR;
2897 }
2898
2899 // Perform synchronous read
2900 result = ReadSync( pFilpData->mpDev,
2901 &pReadData,
2902 pFilpData->mClientID,
2903 0 );
2904 if (result <= 0)
2905 {
2906 return result;
2907 }
2908
2909 // Discard QMUX header
2910 result -= QMUXHeaderSize();
2911 pSmallReadData = pReadData + QMUXHeaderSize();
2912
2913 if (result > size)
2914 {
2915 DBG( "Read data is too large for amount user has requested\n" );
2916 kfree( pReadData );
2917 return -EOVERFLOW;
2918 }
2919
2920 DBG( "pBuf = 0x%p pSmallReadData = 0x%p, result = %d",
2921 pBuf, pSmallReadData, result );
2922
2923 if (copy_to_user( pBuf, pSmallReadData, result ) != 0)
2924 {
2925 DBG( "Error copying read data to user\n" );
2926 result = -EFAULT;
2927 }
2928
2929 // Reader is responsible for freeing read buffer
2930 kfree( pReadData );
2931
2932 return result;
2933 }
2934
2935 /*===========================================================================
2936 METHOD:
2937 UserspaceWrite (Public Method)
2938
2939 DESCRIPTION:
2940 Userspace write (synchronous)
2941
2942 PARAMETERS
2943 pFilp [ I ] - userspace file descriptor
2944 pBuf [ I ] - write buffer
2945 size [ I ] - size of write buffer
2946 pUnusedFpos [ I ] - (unused) file position
2947
2948 RETURN VALUE:
2949 ssize_t - Number of bytes read for success
2950 Negative errno for failure
2951 ===========================================================================*/
2952 static ssize_t UserspaceWrite(
2953 struct file * pFilp,
2954 const char __user * pBuf,
2955 size_t size,
2956 loff_t * pUnusedFpos )
2957 {
2958 int status;
2959 void * pWriteBuffer;
2960 sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
2961
2962 if (pFilpData == NULL)
2963 {
2964 DBG( "Bad file data\n" );
2965 return -EBADF;
2966 }
2967
2968 if (IsDeviceValid( pFilpData->mpDev ) == false)
2969 {
2970 DBG( "Invalid device! Updating f_ops\n" );
2971 pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
2972 return -ENXIO;
2973 }
2974
2975 if (pFilpData->mClientID == (u16)-1)
2976 {
2977 DBG( "Client ID must be set before writing 0x%04X\n",
2978 pFilpData->mClientID );
2979 return -EBADR;
2980 }
2981
2982 // Copy data from user to kernel space
2983 pWriteBuffer = kmalloc( size + QMUXHeaderSize(), GFP_KERNEL );
2984 if (pWriteBuffer == NULL)
2985 {
2986 return -ENOMEM;
2987 }
2988 status = copy_from_user( pWriteBuffer + QMUXHeaderSize(), pBuf, size );
2989 if (status != 0)
2990 {
2991 DBG( "Unable to copy data from userspace %d\n", status );
2992 kfree( pWriteBuffer );
2993 return status;
2994 }
2995
2996 status = WriteSync( pFilpData->mpDev,
2997 pWriteBuffer,
2998 size + QMUXHeaderSize(),
2999 pFilpData->mClientID );
3000
3001 kfree( pWriteBuffer );
3002
3003 // On success, return requested size, not full QMI reqest size
3004 if (status == size + QMUXHeaderSize())
3005 {
3006 return size;
3007 }
3008 else
3009 {
3010 return status;
3011 }
3012 }
3013
3014 /*===========================================================================
3015 METHOD:
3016 UserspacePoll (Public Method)
3017
3018 DESCRIPTION:
3019 Used to determine if read/write operations are possible without blocking
3020
3021 PARAMETERS
3022 pFilp [ I ] - userspace file descriptor
3023 pPollTable [I/O] - Wait object to notify the kernel when data
3024 is ready
3025
3026 RETURN VALUE:
3027 unsigned int - bitmask of what operations can be done immediately
3028 ===========================================================================*/
3029 static unsigned int UserspacePoll(
3030 struct file * pFilp,
3031 struct poll_table_struct * pPollTable )
3032 {
3033 sQMIFilpStorage * pFilpData = (sQMIFilpStorage *)pFilp->private_data;
3034 sClientMemList * pClientMem;
3035 unsigned long flags;
3036
3037 // Always ready to write
3038 unsigned long status = POLLOUT | POLLWRNORM;
3039
3040 if (pFilpData == NULL)
3041 {
3042 DBG( "Bad file data\n" );
3043 return POLLERR;
3044 }
3045
3046 if (IsDeviceValid( pFilpData->mpDev ) == false)
3047 {
3048 DBG( "Invalid device! Updating f_ops\n" );
3049 pFilp->f_op = pFilp->f_dentry->d_inode->i_fop;
3050 return POLLERR;
3051 }
3052
3053 if (pFilpData->mpDev->mbDeregisterQMIDevice)
3054 {
3055 DBG( "DeregisterQMIDevice ing\n" );
3056 return POLLHUP | POLLERR;
3057 }
3058
3059 if (pFilpData->mClientID == (u16)-1)
3060 {
3061 DBG( "Client ID must be set before polling 0x%04X\n",
3062 pFilpData->mClientID );
3063 return POLLERR;
3064 }
3065
3066 // Critical section
3067 spin_lock_irqsave( &pFilpData->mpDev->mQMIDev.mClientMemLock, flags );
3068
3069 // Get this client's memory location
3070 pClientMem = FindClientMem( pFilpData->mpDev,
3071 pFilpData->mClientID );
3072 if (pClientMem == NULL)
3073 {
3074 DBG( "Could not find this client's memory 0x%04X\n",
3075 pFilpData->mClientID );
3076
3077 spin_unlock_irqrestore( &pFilpData->mpDev->mQMIDev.mClientMemLock,
3078 flags );
3079 return POLLERR;
3080 }
3081
3082 poll_wait( pFilp, &pClientMem->mWaitQueue, pPollTable );
3083
3084 if (pClientMem->mpList != NULL)
3085 {
3086 status |= POLLIN | POLLRDNORM;
3087 }
3088
3089 // End critical section
3090 spin_unlock_irqrestore( &pFilpData->mpDev->mQMIDev.mClientMemLock, flags );
3091
3092 // Always ready to write
3093 return (status | POLLOUT | POLLWRNORM);
3094 }
3095
3096 /*=========================================================================*/
3097 // Initializer and destructor
3098 /*=========================================================================*/
3099 static int QMICTLSyncProc(sGobiUSBNet *pDev)
3100 {
3101 void *pWriteBuffer;
3102 void *pReadBuffer;
3103 int result;
3104 u16 writeBufferSize;
3105 u16 readBufferSize;
3106 u8 transactionID;
3107 unsigned long flags;
3108
3109 if (IsDeviceValid( pDev ) == false)
3110 {
3111 DBG( "Invalid device\n" );
3112 return -EFAULT;
3113 }
3114
3115 writeBufferSize= QMICTLSyncReqSize();
3116 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
3117 if (pWriteBuffer == NULL)
3118 {
3119 return -ENOMEM;
3120 }
3121
3122 transactionID = QMIXactionIDGet(pDev);
3123
3124 /* send a QMI_CTL_SYNC_REQ (0x0027) */
3125 result = QMICTLSyncReq( pWriteBuffer,
3126 writeBufferSize,
3127 transactionID );
3128 if (result < 0)
3129 {
3130 kfree( pWriteBuffer );
3131 return result;
3132 }
3133
3134 result = WriteSync( pDev,
3135 pWriteBuffer,
3136 writeBufferSize,
3137 QMICTL );
3138
3139 if (result < 0)
3140 {
3141 kfree( pWriteBuffer );
3142 return result;
3143 }
3144
3145 // QMI CTL Sync Response
3146 result = ReadSync( pDev,
3147 &pReadBuffer,
3148 QMICTL,
3149 transactionID );
3150 if (result < 0)
3151 {
3152 return result;
3153 }
3154
3155 result = QMICTLSyncResp( pReadBuffer,
3156 (u16)result );
3157
3158 kfree( pReadBuffer );
3159
3160 if (result < 0) /* need to re-sync */
3161 {
3162 DBG( "sync response error code %d\n", result );
3163 /* start timer and wait for the response */
3164 /* process response */
3165 return result;
3166 }
3167
3168 #if 1 //free these ununsed qmi response, or when these transactionID re-used, they will be regarded as qmi response of the qmi request that have same transactionID
3169 // Enter critical section
3170 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3171
3172 // Free any unread data
3173 while (PopFromReadMemList( pDev, QMICTL, 0, &pReadBuffer, &readBufferSize) == true) {
3174 kfree( pReadBuffer );
3175 }
3176
3177 // End critical section
3178 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3179 #endif
3180
3181 // Success
3182 return 0;
3183 }
3184
3185 static int qmi_sync_thread(void *data) {
3186 sGobiUSBNet * pDev = (sGobiUSBNet *)data;
3187 int result = 0;
3188
3189 #if 1
3190 // Device is not ready for QMI connections right away
3191 // Wait up to 30 seconds before failing
3192 if (QMIReady( pDev, 30000 ) == false)
3193 {
3194 DBG( "Device unresponsive to QMI\n" );
3195 goto __qmi_sync_finished;
3196 }
3197
3198 // Initiate QMI CTL Sync Procedure
3199 DBG( "Sending QMI CTL Sync Request\n" );
3200 result = QMICTLSyncProc(pDev);
3201 if (result != 0)
3202 {
3203 DBG( "QMI CTL Sync Procedure Error\n" );
3204 goto __qmi_sync_finished;
3205 }
3206 else
3207 {
3208 DBG( "QMI CTL Sync Procedure Successful\n" );
3209 }
3210
3211 #if defined(QUECTEL_WWAN_QMAP)
3212 if (pDev->qmap_mode) {
3213 // Setup Data Format
3214 result = QMIWDASetDataFormat (pDev, pDev->qmap_mode, &pDev->qmap_size);
3215 if (result != 0)
3216 {
3217 goto __qmi_sync_finished;
3218 }
3219 pDev->mpNetDev->rx_urb_size = pDev->qmap_size;
3220 }
3221 #endif
3222
3223 // Setup WDS callback
3224 result = SetupQMIWDSCallback( pDev );
3225 if (result != 0)
3226 {
3227 goto __qmi_sync_finished;
3228 }
3229
3230 // Fill MEID for device
3231 result = QMIDMSGetMEID( pDev );
3232 if (result != 0)
3233 {
3234 goto __qmi_sync_finished;
3235 }
3236 #endif
3237
3238 __qmi_sync_finished:
3239 pDev->mbQMIReady = true;
3240 complete_all(&pDev->mQMIReadyCompletion);
3241 pDev->mbQMISyncIng = false;
3242 if (atomic_dec_and_test(&pDev->refcount)) {
3243 kfree( pDev );
3244 }
3245 return result;
3246 }
3247
3248 /*===========================================================================
3249 METHOD:
3250 RegisterQMIDevice (Public Method)
3251
3252 DESCRIPTION:
3253 QMI Device initialization function
3254
3255 PARAMETERS:
3256 pDev [ I ] - Device specific memory
3257
3258 RETURN VALUE:
3259 int - 0 for success
3260 Negative errno for failure
3261 ===========================================================================*/
3262 int RegisterQMIDevice( sGobiUSBNet * pDev )
3263 {
3264 int result;
3265 int GobiQMIIndex = 0;
3266 dev_t devno;
3267 char * pDevName;
3268
3269 if (pDev->mQMIDev.mbCdevIsInitialized == true)
3270 {
3271 // Should never happen, but always better to check
3272 DBG( "device already exists\n" );
3273 return -EEXIST;
3274 }
3275
3276 pDev->mbQMIValid = true;
3277 pDev->mbDeregisterQMIDevice = false;
3278
3279 // Set up for QMICTL
3280 // (does not send QMI message, just sets up memory)
3281 result = GetClientID( pDev, QMICTL );
3282 if (result != 0)
3283 {
3284 pDev->mbQMIValid = false;
3285 return result;
3286 }
3287 atomic_set( &pDev->mQMIDev.mQMICTLTransactionID, 1 );
3288
3289 // Start Async reading
3290 result = StartRead( pDev );
3291 if (result != 0)
3292 {
3293 pDev->mbQMIValid = false;
3294 return result;
3295 }
3296
3297 if (pDev->mbMdm9x07)
3298 {
3299 usb_control_msg( pDev->mpNetDev->udev,
3300 usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ),
3301 SET_CONTROL_LINE_STATE_REQUEST,
3302 SET_CONTROL_LINE_STATE_REQUEST_TYPE,
3303 CONTROL_DTR,
3304 /* USB interface number to receive control message */
3305 pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber,
3306 NULL,
3307 0,
3308 100 );
3309 }
3310
3311 //for EC21&25, must wait about 15 seconds to wait QMI ready. it is too long for driver probe(will block other drivers probe).
3312 if (pDev->mbMdm9x07)
3313 {
3314 struct task_struct *qmi_sync_task;
3315 atomic_inc(&pDev->refcount);
3316 init_completion(&pDev->mQMIReadyCompletion);
3317 pDev->mbQMIReady = false;
3318 pDev->mbQMISyncIng = true;
3319 qmi_sync_task = kthread_run(qmi_sync_thread, (void *)pDev, "qmi_sync/%d", pDev->mpNetDev->udev->devnum);
3320 if (IS_ERR(qmi_sync_task)) {
3321 pDev->mbQMISyncIng = false;
3322 atomic_dec(&pDev->refcount);
3323 DBG( "Create qmi_sync_thread fail\n" );
3324 return PTR_ERR(qmi_sync_task);
3325 }
3326 goto __register_chardev_qccmi;
3327 }
3328
3329 // Device is not ready for QMI connections right away
3330 // Wait up to 30 seconds before failing
3331 if (QMIReady( pDev, 30000 ) == false)
3332 {
3333 DBG( "Device unresponsive to QMI\n" );
3334 return -ETIMEDOUT;
3335 }
3336
3337 // Initiate QMI CTL Sync Procedure
3338 DBG( "Sending QMI CTL Sync Request\n" );
3339 result = QMICTLSyncProc(pDev);
3340 if (result != 0)
3341 {
3342 DBG( "QMI CTL Sync Procedure Error\n" );
3343 return result;
3344 }
3345 else
3346 {
3347 DBG( "QMI CTL Sync Procedure Successful\n" );
3348 }
3349
3350 // Setup Data Format
3351 #if defined(QUECTEL_WWAN_QMAP)
3352 result = QMIWDASetDataFormat (pDev, pDev->qmap_mode, NULL);
3353 #else
3354 result = QMIWDASetDataFormat (pDev, 0, NULL);
3355 #endif
3356 if (result != 0)
3357 {
3358 return result;
3359 }
3360
3361 // Setup WDS callback
3362 result = SetupQMIWDSCallback( pDev );
3363 if (result != 0)
3364 {
3365 return result;
3366 }
3367
3368 // Fill MEID for device
3369 result = QMIDMSGetMEID( pDev );
3370 if (result != 0)
3371 {
3372 return result;
3373 }
3374
3375 __register_chardev_qccmi:
3376 // allocate and fill devno with numbers
3377 result = alloc_chrdev_region( &devno, 0, 1, "qcqmi" );
3378 if (result < 0)
3379 {
3380 return result;
3381 }
3382
3383 // Create cdev
3384 cdev_init( &pDev->mQMIDev.mCdev, &UserspaceQMIFops );
3385 pDev->mQMIDev.mCdev.owner = THIS_MODULE;
3386 pDev->mQMIDev.mCdev.ops = &UserspaceQMIFops;
3387 pDev->mQMIDev.mbCdevIsInitialized = true;
3388
3389 result = cdev_add( &pDev->mQMIDev.mCdev, devno, 1 );
3390 if (result != 0)
3391 {
3392 DBG( "error adding cdev\n" );
3393 return result;
3394 }
3395
3396 // Match interface number (usb# or eth#)
3397 if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "eth" ))) {
3398 pDevName += strlen( "eth" );
3399 } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "usb" ))) {
3400 pDevName += strlen( "usb" );
3401 #if 1 //openWRT like use ppp# or lte#
3402 } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "ppp" ))) {
3403 pDevName += strlen( "ppp" );
3404 } else if (!!(pDevName = strstr( pDev->mpNetDev->net->name, "lte" ))) {
3405 pDevName += strlen( "lte" );
3406 #endif
3407 } else {
3408 DBG( "Bad net name: %s\n", pDev->mpNetDev->net->name );
3409 return -ENXIO;
3410 }
3411 GobiQMIIndex = simple_strtoul( pDevName, NULL, 10 );
3412 if (GobiQMIIndex < 0)
3413 {
3414 DBG( "Bad minor number\n" );
3415 return -ENXIO;
3416 }
3417
3418 // Always print this output
3419 printk( KERN_INFO "creating qcqmi%d\n",
3420 GobiQMIIndex );
3421
3422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION( 2,6,27 ))
3423 // kernel 2.6.27 added a new fourth parameter to device_create
3424 // void * drvdata : the data to be added to the device for callbacks
3425 device_create( pDev->mQMIDev.mpDevClass,
3426 &pDev->mpIntf->dev,
3427 devno,
3428 NULL,
3429 "qcqmi%d",
3430 GobiQMIIndex );
3431 #else
3432 device_create( pDev->mQMIDev.mpDevClass,
3433 &pDev->mpIntf->dev,
3434 devno,
3435 "qcqmi%d",
3436 GobiQMIIndex );
3437 #endif
3438
3439 pDev->mQMIDev.mDevNum = devno;
3440
3441 // Success
3442 return 0;
3443 }
3444
3445 /*===========================================================================
3446 METHOD:
3447 DeregisterQMIDevice (Public Method)
3448
3449 DESCRIPTION:
3450 QMI Device cleanup function
3451
3452 NOTE: When this function is run the device is no longer valid
3453
3454 PARAMETERS:
3455 pDev [ I ] - Device specific memory
3456
3457 RETURN VALUE:
3458 None
3459 ===========================================================================*/
3460 void DeregisterQMIDevice( sGobiUSBNet * pDev )
3461 {
3462 #ifndef quectel_no_for_each_process
3463 struct inode * pOpenInode;
3464 struct list_head * pInodeList;
3465 struct task_struct * pEachTask;
3466 struct fdtable * pFDT;
3467 struct file * pFilp;
3468 int count = 0;
3469 #endif
3470 unsigned long flags;
3471 int tries;
3472 int result;
3473
3474 // Should never happen, but check anyway
3475 if (IsDeviceValid( pDev ) == false)
3476 {
3477 DBG( "wrong device\n" );
3478 return;
3479 }
3480
3481 pDev->mbDeregisterQMIDevice = true;
3482
3483 for (tries = 0; tries < 3000; tries += 10) {
3484 if (pDev->mbQMISyncIng == false)
3485 break;
3486 msleep(10);
3487 }
3488
3489 if (pDev->mbQMISyncIng) {
3490 DBG( "QMI sync ing\n" );
3491 }
3492
3493 // Release all clients
3494 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3495 while (pDev->mQMIDev.mpClientMemList != NULL)
3496 {
3497 u16 mClientID = pDev->mQMIDev.mpClientMemList->mClientID;
3498 if (waitqueue_active(&pDev->mQMIDev.mpClientMemList->mWaitQueue)) {
3499 DBG("WaitQueue 0x%04X\n", mClientID);
3500 wake_up_interruptible_sync( &pDev->mQMIDev.mpClientMemList->mWaitQueue );
3501 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3502 msleep(10);
3503 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3504 continue;
3505 }
3506
3507 DBG( "release 0x%04X\n", pDev->mQMIDev.mpClientMemList->mClientID );
3508
3509 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3510 ReleaseClientID( pDev, mClientID );
3511 // NOTE: pDev->mQMIDev.mpClientMemList will
3512 // be updated in ReleaseClientID()
3513 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3514 }
3515 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3516
3517 // Stop all reads
3518 KillRead( pDev );
3519
3520 pDev->mbQMIValid = false;
3521
3522 if (pDev->mQMIDev.mbCdevIsInitialized == false)
3523 {
3524 return;
3525 }
3526
3527 #ifndef quectel_no_for_each_process
3528 // Find each open file handle, and manually close it
3529
3530 // Generally there will only be only one inode, but more are possible
3531 list_for_each( pInodeList, &pDev->mQMIDev.mCdev.list )
3532 {
3533 // Get the inode
3534 pOpenInode = container_of( pInodeList, struct inode, i_devices );
3535 if (pOpenInode != NULL && (IS_ERR( pOpenInode ) == false))
3536 {
3537 // Look for this inode in each task
3538
3539 rcu_read_lock();
3540 for_each_process( pEachTask )
3541 {
3542 task_lock(pEachTask);
3543 if (pEachTask == NULL || pEachTask->files == NULL)
3544 {
3545 // Some tasks may not have files (e.g. Xsession)
3546 task_unlock(pEachTask);
3547 continue;
3548 }
3549 // For each file this task has open, check if it's referencing
3550 // our inode.
3551 spin_lock_irqsave( &pEachTask->files->file_lock, flags );
3552 task_unlock(pEachTask); //kernel/exit.c:do_exit() -> fs/file.c:exit_files()
3553 pFDT = files_fdtable( pEachTask->files );
3554 for (count = 0; count < pFDT->max_fds; count++)
3555 {
3556 pFilp = pFDT->fd[count];
3557 if (pFilp != NULL && pFilp->f_dentry != NULL)
3558 {
3559 if (pFilp->f_dentry->d_inode == pOpenInode)
3560 {
3561 // Close this file handle
3562 rcu_assign_pointer( pFDT->fd[count], NULL );
3563 spin_unlock_irqrestore( &pEachTask->files->file_lock, flags );
3564
3565 DBG( "forcing close of open file handle\n" );
3566 filp_close( pFilp, pEachTask->files );
3567
3568 spin_lock_irqsave( &pEachTask->files->file_lock, flags );
3569 }
3570 }
3571 }
3572 spin_unlock_irqrestore( &pEachTask->files->file_lock, flags );
3573 }
3574 rcu_read_unlock();
3575 }
3576 }
3577 #endif
3578
3579 if (pDev->mpNetDev->udev->state) {
3580 // Send SetControlLineState request (USB_CDC)
3581 result = usb_control_msg( pDev->mpNetDev->udev,
3582 usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ),
3583 SET_CONTROL_LINE_STATE_REQUEST,
3584 SET_CONTROL_LINE_STATE_REQUEST_TYPE,
3585 0, // DTR not present
3586 /* USB interface number to receive control message */
3587 pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber,
3588 NULL,
3589 0,
3590 100 );
3591 if (result < 0)
3592 {
3593 DBG( "Bad SetControlLineState status %d\n", result );
3594 }
3595 }
3596
3597 // Remove device (so no more calls can be made by users)
3598 if (IS_ERR( pDev->mQMIDev.mpDevClass ) == false)
3599 {
3600 device_destroy( pDev->mQMIDev.mpDevClass,
3601 pDev->mQMIDev.mDevNum );
3602 }
3603
3604 // Hold onto cdev memory location until everyone is through using it.
3605 // Timeout after 30 seconds (10 ms interval). Timeout should never happen,
3606 // but exists to prevent an infinate loop just in case.
3607 for (tries = 0; tries < 30 * 100; tries++)
3608 {
3609 #if (LINUX_VERSION_CODE < KERNEL_VERSION( 4,11,0 ))
3610 int ref = atomic_read( &pDev->mQMIDev.mCdev.kobj.kref.refcount );
3611 #else
3612 int ref = kref_read( &pDev->mQMIDev.mCdev.kobj.kref );
3613 #endif
3614 if (ref > 1)
3615 {
3616 DBG( "cdev in use by %d tasks\n", ref - 1 );
3617 if (tries > 10)
3618 INFO( "cdev in use by %d tasks\n", ref - 1 );
3619 msleep( 10 );
3620 }
3621 else
3622 {
3623 break;
3624 }
3625 }
3626
3627 cdev_del( &pDev->mQMIDev.mCdev );
3628
3629 unregister_chrdev_region( pDev->mQMIDev.mDevNum, 1 );
3630
3631 return;
3632 }
3633
3634 /*=========================================================================*/
3635 // Driver level client management
3636 /*=========================================================================*/
3637
3638 /*===========================================================================
3639 METHOD:
3640 QMIReady (Public Method)
3641
3642 DESCRIPTION:
3643 Send QMI CTL GET VERSION INFO REQ and SET DATA FORMAT REQ
3644 Wait for response or timeout
3645
3646 PARAMETERS:
3647 pDev [ I ] - Device specific memory
3648 timeout [ I ] - Milliseconds to wait for response
3649
3650 RETURN VALUE:
3651 bool
3652 ===========================================================================*/
3653 static bool QMIReady(
3654 sGobiUSBNet * pDev,
3655 u16 timeout )
3656 {
3657 int result;
3658 void * pWriteBuffer;
3659 u16 writeBufferSize;
3660 void * pReadBuffer;
3661 u16 readBufferSize;
3662 u16 curTime;
3663 unsigned long flags;
3664 u8 transactionID;
3665 u16 interval = 2000;
3666
3667 if (IsDeviceValid( pDev ) == false)
3668 {
3669 DBG( "Invalid device\n" );
3670 return false;
3671 }
3672
3673 writeBufferSize = QMICTLReadyReqSize();
3674 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
3675 if (pWriteBuffer == NULL)
3676 {
3677 return false;
3678 }
3679
3680 // An implimentation of down_timeout has not been agreed on,
3681 // so it's been added and removed from the kernel several times.
3682 // We're just going to ignore it and poll the semaphore.
3683
3684 // Send a write every 1000 ms and see if we get a response
3685 for (curTime = 0; curTime < timeout; curTime += interval)
3686 {
3687 // Start read
3688 struct QuecSem *readSem = kmalloc(sizeof(struct QuecSem ), GFP_KERNEL);
3689 readSem->magic = QUEC_SEM_MAGIC;
3690 sema_init( &readSem->readSem, 0 );
3691
3692 transactionID = QMIXactionIDGet( pDev );
3693
3694 result = ReadAsync( pDev, QMICTL, transactionID, UpSem, readSem );
3695 if (result != 0)
3696 {
3697 kfree( pWriteBuffer );
3698 return false;
3699 }
3700
3701 // Fill buffer
3702 result = QMICTLReadyReq( pWriteBuffer,
3703 writeBufferSize,
3704 transactionID );
3705 if (result < 0)
3706 {
3707 kfree( pWriteBuffer );
3708 return false;
3709 }
3710
3711 // Disregard status. On errors, just try again
3712 result = WriteSync( pDev,
3713 pWriteBuffer,
3714 writeBufferSize,
3715 QMICTL );
3716
3717 if (result < 0) //maybe caused by usb disconnect
3718 {
3719 kfree( pWriteBuffer );
3720 return false;
3721 }
3722
3723 #if 1
3724 if (down_timeout( &readSem->readSem, msecs_to_jiffies(interval) ) == 0)
3725 #else
3726 msleep( interval );
3727 if (down_trylock( &readSem->readSem ) == 0)
3728 #endif
3729 {
3730 kfree(readSem);
3731 // Enter critical section
3732 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3733
3734 // Pop the read data
3735 if (PopFromReadMemList( pDev,
3736 QMICTL,
3737 transactionID,
3738 &pReadBuffer,
3739 &readBufferSize ) == true)
3740 {
3741 // Success
3742
3743 // End critical section
3744 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3745
3746 // We don't care about the result
3747 kfree( pReadBuffer );
3748
3749 break;
3750 }
3751 else
3752 {
3753 // Read mismatch/failure, unlock and continue
3754 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3755 }
3756 }
3757 else
3758 {
3759 readSem->magic = 0;
3760 // Enter critical section
3761 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3762
3763 // Timeout, remove the async read
3764 NotifyAndPopNotifyList( pDev, QMICTL, transactionID );
3765
3766 // End critical section
3767 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3768 }
3769
3770 if (pDev->mbDeregisterQMIDevice)
3771 {
3772 kfree( pWriteBuffer );
3773 return false;
3774 }
3775 }
3776
3777 kfree( pWriteBuffer );
3778
3779 // Did we time out?
3780 if (curTime >= timeout)
3781 {
3782 return false;
3783 }
3784
3785 DBG( "QMI Ready after %u milliseconds\n", curTime );
3786
3787 // Success
3788 return true;
3789 }
3790
3791 /*===========================================================================
3792 METHOD:
3793 QMIWDSCallback (Public Method)
3794
3795 DESCRIPTION:
3796 QMI WDS callback function
3797 Update net stats or link state
3798
3799 PARAMETERS:
3800 pDev [ I ] - Device specific memory
3801 clientID [ I ] - Client ID
3802 pData [ I ] - Callback data (unused)
3803
3804 RETURN VALUE:
3805 None
3806 ===========================================================================*/
3807 static void QMIWDSCallback(
3808 sGobiUSBNet * pDev,
3809 u16 clientID,
3810 void * pData )
3811 {
3812 bool bRet;
3813 int result;
3814 void * pReadBuffer;
3815 u16 readBufferSize;
3816
3817 #if 0
3818 #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,31 ))
3819 struct net_device_stats * pStats = &(pDev->mpNetDev->stats);
3820 #else
3821 struct net_device_stats * pStats = &(pDev->mpNetDev->net->stats);
3822 #endif
3823 #endif
3824
3825 u32 TXOk = (u32)-1;
3826 u32 RXOk = (u32)-1;
3827 u32 TXErr = (u32)-1;
3828 u32 RXErr = (u32)-1;
3829 u32 TXOfl = (u32)-1;
3830 u32 RXOfl = (u32)-1;
3831 u64 TXBytesOk = (u64)-1;
3832 u64 RXBytesOk = (u64)-1;
3833 bool bLinkState;
3834 bool bReconfigure;
3835 unsigned long flags;
3836
3837 if (IsDeviceValid( pDev ) == false)
3838 {
3839 DBG( "Invalid device\n" );
3840 return;
3841 }
3842
3843 // Critical section
3844 spin_lock_irqsave( &pDev->mQMIDev.mClientMemLock, flags );
3845
3846 bRet = PopFromReadMemList( pDev,
3847 clientID,
3848 0,
3849 &pReadBuffer,
3850 &readBufferSize );
3851
3852 // End critical section
3853 spin_unlock_irqrestore( &pDev->mQMIDev.mClientMemLock, flags );
3854
3855 if (bRet == false)
3856 {
3857 DBG( "WDS callback failed to get data\n" );
3858 return;
3859 }
3860
3861 // Default values
3862 bLinkState = ! GobiTestDownReason( pDev, NO_NDIS_CONNECTION );
3863 bReconfigure = false;
3864
3865 result = QMIWDSEventResp( pReadBuffer,
3866 readBufferSize,
3867 &TXOk,
3868 &RXOk,
3869 &TXErr,
3870 &RXErr,
3871 &TXOfl,
3872 &RXOfl,
3873 &TXBytesOk,
3874 &RXBytesOk,
3875 &bLinkState,
3876 &bReconfigure );
3877 if (result < 0)
3878 {
3879 DBG( "bad WDS packet\n" );
3880 }
3881 else
3882 {
3883 #if 0 //usbbet.c will do this job
3884 // Fill in new values, ignore max values
3885 if (TXOfl != (u32)-1)
3886 {
3887 pStats->tx_fifo_errors = TXOfl;
3888 }
3889
3890 if (RXOfl != (u32)-1)
3891 {
3892 pStats->rx_fifo_errors = RXOfl;
3893 }
3894
3895 if (TXErr != (u32)-1)
3896 {
3897 pStats->tx_errors = TXErr;
3898 }
3899
3900 if (RXErr != (u32)-1)
3901 {
3902 pStats->rx_errors = RXErr;
3903 }
3904
3905 if (TXOk != (u32)-1)
3906 {
3907 pStats->tx_packets = TXOk + pStats->tx_errors;
3908 }
3909
3910 if (RXOk != (u32)-1)
3911 {
3912 pStats->rx_packets = RXOk + pStats->rx_errors;
3913 }
3914
3915 if (TXBytesOk != (u64)-1)
3916 {
3917 pStats->tx_bytes = TXBytesOk;
3918 }
3919
3920 if (RXBytesOk != (u64)-1)
3921 {
3922 pStats->rx_bytes = RXBytesOk;
3923 }
3924 #endif
3925
3926 if (bReconfigure == true)
3927 {
3928 DBG( "Net device link reset\n" );
3929 GobiSetDownReason( pDev, NO_NDIS_CONNECTION );
3930 GobiClearDownReason( pDev, NO_NDIS_CONNECTION );
3931 }
3932 else
3933 {
3934 if (bLinkState == true)
3935 {
3936 if (GobiTestDownReason( pDev, NO_NDIS_CONNECTION )) {
3937 DBG( "Net device link is connected\n" );
3938 GobiClearDownReason( pDev, NO_NDIS_CONNECTION );
3939 }
3940 }
3941 else
3942 {
3943 if (!GobiTestDownReason( pDev, NO_NDIS_CONNECTION )) {
3944 DBG( "Net device link is disconnected\n" );
3945 GobiSetDownReason( pDev, NO_NDIS_CONNECTION );
3946 }
3947 }
3948 }
3949 }
3950
3951 kfree( pReadBuffer );
3952
3953 // Setup next read
3954 result = ReadAsync( pDev,
3955 clientID,
3956 0,
3957 QMIWDSCallback,
3958 pData );
3959 if (result != 0)
3960 {
3961 DBG( "unable to setup next async read\n" );
3962 }
3963
3964 return;
3965 }
3966
3967 /*===========================================================================
3968 METHOD:
3969 SetupQMIWDSCallback (Public Method)
3970
3971 DESCRIPTION:
3972 Request client and fire off reqests and start async read for
3973 QMI WDS callback
3974
3975 PARAMETERS:
3976 pDev [ I ] - Device specific memory
3977
3978 RETURN VALUE:
3979 int - 0 for success
3980 Negative errno for failure
3981 ===========================================================================*/
3982 static int SetupQMIWDSCallback( sGobiUSBNet * pDev )
3983 {
3984 int result;
3985 void * pWriteBuffer;
3986 u16 writeBufferSize;
3987 u16 WDSClientID;
3988
3989 if (IsDeviceValid( pDev ) == false)
3990 {
3991 DBG( "Invalid device\n" );
3992 return -EFAULT;
3993 }
3994
3995 result = GetClientID( pDev, QMIWDS );
3996 if (result < 0)
3997 {
3998 return result;
3999 }
4000 WDSClientID = result;
4001
4002 #if 0 // add for "AT$QCRMCALL=1,1", be careful: donot enable these codes if use quectel-CM, or cannot obtain IP by udhcpc
4003 if (pDev->mbMdm9x07)
4004 {
4005 void * pReadBuffer;
4006 u16 readBufferSize;
4007
4008 writeBufferSize = QMIWDSSetQMUXBindMuxDataPortSize();
4009 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4010 if (pWriteBuffer == NULL)
4011 {
4012 return -ENOMEM;
4013 }
4014
4015 result = QMIWDSSetQMUXBindMuxDataPortReq( pWriteBuffer,
4016 writeBufferSize,
4017 0x81,
4018 3 );
4019 if (result < 0)
4020 {
4021 kfree( pWriteBuffer );
4022 return result;
4023 }
4024
4025 result = WriteSync( pDev,
4026 pWriteBuffer,
4027 writeBufferSize,
4028 WDSClientID );
4029 kfree( pWriteBuffer );
4030
4031 if (result < 0)
4032 {
4033 return result;
4034 }
4035
4036 result = ReadSync( pDev,
4037 &pReadBuffer,
4038 WDSClientID,
4039 3 );
4040 if (result < 0)
4041 {
4042 return result;
4043 }
4044 readBufferSize = result;
4045
4046 kfree( pReadBuffer );
4047 }
4048 #endif
4049
4050 // QMI WDS Set Event Report
4051 writeBufferSize = QMIWDSSetEventReportReqSize();
4052 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4053 if (pWriteBuffer == NULL)
4054 {
4055 return -ENOMEM;
4056 }
4057
4058 result = QMIWDSSetEventReportReq( pWriteBuffer,
4059 writeBufferSize,
4060 1 );
4061 if (result < 0)
4062 {
4063 kfree( pWriteBuffer );
4064 return result;
4065 }
4066
4067 result = WriteSync( pDev,
4068 pWriteBuffer,
4069 writeBufferSize,
4070 WDSClientID );
4071 kfree( pWriteBuffer );
4072
4073 if (result < 0)
4074 {
4075 return result;
4076 }
4077
4078 // QMI WDS Get PKG SRVC Status
4079 writeBufferSize = QMIWDSGetPKGSRVCStatusReqSize();
4080 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4081 if (pWriteBuffer == NULL)
4082 {
4083 return -ENOMEM;
4084 }
4085
4086 result = QMIWDSGetPKGSRVCStatusReq( pWriteBuffer,
4087 writeBufferSize,
4088 2 );
4089 if (result < 0)
4090 {
4091 kfree( pWriteBuffer );
4092 return result;
4093 }
4094
4095 result = WriteSync( pDev,
4096 pWriteBuffer,
4097 writeBufferSize,
4098 WDSClientID );
4099 kfree( pWriteBuffer );
4100
4101 if (result < 0)
4102 {
4103 return result;
4104 }
4105
4106 // Setup asnyc read callback
4107 result = ReadAsync( pDev,
4108 WDSClientID,
4109 0,
4110 QMIWDSCallback,
4111 NULL );
4112 if (result != 0)
4113 {
4114 DBG( "unable to setup async read\n" );
4115 return result;
4116 }
4117
4118 // Send SetControlLineState request (USB_CDC)
4119 // Required for Autoconnect
4120 result = usb_control_msg( pDev->mpNetDev->udev,
4121 usb_sndctrlpipe( pDev->mpNetDev->udev, 0 ),
4122 SET_CONTROL_LINE_STATE_REQUEST,
4123 SET_CONTROL_LINE_STATE_REQUEST_TYPE,
4124 CONTROL_DTR,
4125 /* USB interface number to receive control message */
4126 pDev->mpIntf->cur_altsetting->desc.bInterfaceNumber,
4127 NULL,
4128 0,
4129 100 );
4130 if (result < 0)
4131 {
4132 DBG( "Bad SetControlLineState status %d\n", result );
4133 return result;
4134 }
4135
4136 return 0;
4137 }
4138
4139 /*===========================================================================
4140 METHOD:
4141 QMIDMSGetMEID (Public Method)
4142
4143 DESCRIPTION:
4144 Register DMS client
4145 send MEID req and parse response
4146 Release DMS client
4147
4148 PARAMETERS:
4149 pDev [ I ] - Device specific memory
4150
4151 RETURN VALUE:
4152 None
4153 ===========================================================================*/
4154 static int QMIDMSGetMEID( sGobiUSBNet * pDev )
4155 {
4156 int result;
4157 void * pWriteBuffer;
4158 u16 writeBufferSize;
4159 void * pReadBuffer;
4160 u16 readBufferSize;
4161 u16 DMSClientID;
4162
4163 if (IsDeviceValid( pDev ) == false)
4164 {
4165 DBG( "Invalid device\n" );
4166 return -EFAULT;
4167 }
4168
4169 result = GetClientID( pDev, QMIDMS );
4170 if (result < 0)
4171 {
4172 return result;
4173 }
4174 DMSClientID = result;
4175
4176 // QMI DMS Get Serial numbers Req
4177 writeBufferSize = QMIDMSGetMEIDReqSize();
4178 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4179 if (pWriteBuffer == NULL)
4180 {
4181 return -ENOMEM;
4182 }
4183
4184 result = QMIDMSGetMEIDReq( pWriteBuffer,
4185 writeBufferSize,
4186 1 );
4187 if (result < 0)
4188 {
4189 kfree( pWriteBuffer );
4190 return result;
4191 }
4192
4193 result = WriteSync( pDev,
4194 pWriteBuffer,
4195 writeBufferSize,
4196 DMSClientID );
4197 kfree( pWriteBuffer );
4198
4199 if (result < 0)
4200 {
4201 return result;
4202 }
4203
4204 // QMI DMS Get Serial numbers Resp
4205 result = ReadSync( pDev,
4206 &pReadBuffer,
4207 DMSClientID,
4208 1 );
4209 if (result < 0)
4210 {
4211 return result;
4212 }
4213 readBufferSize = result;
4214
4215 result = QMIDMSGetMEIDResp( pReadBuffer,
4216 readBufferSize,
4217 &pDev->mMEID[0],
4218 14 );
4219 kfree( pReadBuffer );
4220
4221 if (result < 0)
4222 {
4223 DBG( "bad get MEID resp\n" );
4224
4225 // Non fatal error, device did not return any MEID
4226 // Fill with 0's
4227 memset( &pDev->mMEID[0], '0', 14 );
4228 }
4229
4230 ReleaseClientID( pDev, DMSClientID );
4231
4232 // Success
4233 return 0;
4234 }
4235
4236 /*===========================================================================
4237 METHOD:
4238 QMIWDASetDataFormat (Public Method)
4239
4240 DESCRIPTION:
4241 Register WDA client
4242 send Data format request and parse response
4243 Release WDA client
4244
4245 PARAMETERS:
4246 pDev [ I ] - Device specific memory
4247
4248 RETURN VALUE:
4249 None
4250 ===========================================================================*/
4251 static int QMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size )
4252 {
4253 int result;
4254 void * pWriteBuffer;
4255 u16 writeBufferSize;
4256 void * pReadBuffer;
4257 u16 readBufferSize;
4258 u16 WDAClientID;
4259
4260 DBG("\n");
4261
4262 if (IsDeviceValid( pDev ) == false)
4263 {
4264 DBG( "Invalid device\n" );
4265 return -EFAULT;
4266 }
4267
4268 result = GetClientID( pDev, QMIWDA );
4269 if (result < 0)
4270 {
4271 return result;
4272 }
4273 WDAClientID = result;
4274
4275 // QMI WDA Set Data Format Request
4276 writeBufferSize = QMIWDASetDataFormatReqSize(qmap_mode);
4277 pWriteBuffer = kmalloc( writeBufferSize, GFP_KERNEL );
4278 if (pWriteBuffer == NULL)
4279 {
4280 return -ENOMEM;
4281 }
4282
4283 result = QMIWDASetDataFormatReq( pWriteBuffer,
4284 writeBufferSize, pDev->mbRawIPMode,
4285 qmap_mode ? pDev->qmap_version : 0, (31*1024),
4286 1 );
4287
4288 if (result < 0)
4289 {
4290 kfree( pWriteBuffer );
4291 return result;
4292 }
4293
4294 result = WriteSync( pDev,
4295 pWriteBuffer,
4296 writeBufferSize,
4297 WDAClientID );
4298 kfree( pWriteBuffer );
4299
4300 if (result < 0)
4301 {
4302 return result;
4303 }
4304
4305 // QMI DMS Get Serial numbers Resp
4306 result = ReadSync( pDev,
4307 &pReadBuffer,
4308 WDAClientID,
4309 1 );
4310 if (result < 0)
4311 {
4312 return result;
4313 }
4314 readBufferSize = result;
4315
4316 if (qmap_mode && rx_urb_size) {
4317 int qmap_version = 0, rx_size = 0, tx_size = 0;
4318 result = QMIWDASetDataFormatResp( pReadBuffer,
4319 readBufferSize, pDev->mbRawIPMode, &qmap_version, &rx_size, &tx_size, &pDev->qmap_settings);
4320 INFO( "qmap settings qmap_version=%d, rx_size=%d, tx_size=%d\n",
4321 le32_to_cpu(qmap_version), le32_to_cpu(rx_size), le32_to_cpu(tx_size));
4322
4323 if (le32_to_cpu(qmap_version)) {
4324 #if defined(QUECTEL_UL_DATA_AGG)
4325 struct ul_agg_ctx *ctx = &pDev->agg_ctx;
4326
4327 if (le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_datagrams) > 1) {
4328 ctx->ul_data_aggregation_max_size = le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_size);
4329 ctx->ul_data_aggregation_max_datagrams = le32_to_cpu(pDev->qmap_settings.ul_data_aggregation_max_datagrams);
4330 ctx->dl_minimum_padding = le32_to_cpu(pDev->qmap_settings.dl_minimum_padding);
4331 }
4332 INFO( "qmap settings ul_data_aggregation_max_size=%d, ul_data_aggregation_max_datagrams=%d\n",
4333 ctx->ul_data_aggregation_max_size, ctx->ul_data_aggregation_max_datagrams);
4334 if (ctx->ul_data_aggregation_max_datagrams > 11)
4335 ctx->ul_data_aggregation_max_datagrams = 11;
4336 #endif
4337 *rx_urb_size = le32_to_cpu(rx_size);
4338 } else {
4339 *rx_urb_size = 0;
4340 result = -EFAULT;
4341 }
4342 } else {
4343 int qmap_enabled = 0, rx_size = 0, tx_size = 0;
4344 result = QMIWDASetDataFormatResp( pReadBuffer,
4345 readBufferSize, pDev->mbRawIPMode, &qmap_enabled, &rx_size, &tx_size, NULL);
4346 }
4347
4348 kfree( pReadBuffer );
4349
4350 if (result < 0)
4351 {
4352 DBG( "Data Format Cannot be set\n" );
4353 }
4354
4355 ReleaseClientID( pDev, WDAClientID );
4356
4357 // Success
4358 return 0;
4359 }
4360
4361 int QuecQMIWDASetDataFormat( sGobiUSBNet * pDev, int qmap_mode, int *rx_urb_size ) {
4362 return QMIWDASetDataFormat(pDev, qmap_mode, rx_urb_size);
4363 }
4364