1 #ifdef __QUEC_INCLUDE_QMI_C__
2 /*===========================================================================
3 FILE:
4 QMI.c
5
6 DESCRIPTION:
7 Qualcomm QMI driver code
8
9 FUNCTIONS:
10 Generic QMUX functions
11 ParseQMUX
12 FillQMUX
13
14 Generic QMI functions
15 GetTLV
16 ValidQMIMessage
17 GetQMIMessageID
18
19 Fill Buffers with QMI requests
20 QMICTLGetClientIDReq
21 QMICTLReleaseClientIDReq
22 QMICTLReadyReq
23 QMIWDSSetEventReportReq
24 QMIWDSGetPKGSRVCStatusReq
25 QMIDMSGetMEIDReq
26 QMIWDASetDataFormatReq
27 QMICTLSetDataFormatReq
28 QMICTLSyncReq
29
30 Parse data from QMI responses
31 QMICTLGetClientIDResp
32 QMICTLReleaseClientIDResp
33 QMIWDSEventResp
34 QMIDMSGetMEIDResp
35 QMIWDASetDataFormatResp
36 QMICTLSyncResp
37
38 Copyright (c) 2011, Code Aurora Forum. All rights reserved.
39
40 Redistribution and use in source and binary forms, with or without
41 modification, are permitted provided that the following conditions are met:
42 * Redistributions of source code must retain the above copyright
43 notice, this list of conditions and the following disclaimer.
44 * Redistributions in binary form must reproduce the above copyright
45 notice, this list of conditions and the following disclaimer in the
46 documentation and/or other materials provided with the distribution.
47 * Neither the name of Code Aurora Forum nor
48 the names of its contributors may be used to endorse or promote
49 products derived from this software without specific prior written
50 permission.
51
52
53 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
54 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
57 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 POSSIBILITY OF SUCH DAMAGE.
64 ===========================================================================*/
65
66 //---------------------------------------------------------------------------
67 // Include Files
68 //---------------------------------------------------------------------------
69 #include <asm/unaligned.h>
70 #include <linux/kernel.h>
71 #include "Structs.h"
72 #include "QMI.h"
73
74 /*=========================================================================*/
75 // Get sizes of buffers needed by QMI requests
76 /*=========================================================================*/
77
78 /*===========================================================================
79 METHOD:
80 QMUXHeaderSize (Public Method)
81
82 DESCRIPTION:
83 Get size of buffer needed for QMUX
84
85 RETURN VALUE:
86 u16 - size of buffer
87 ===========================================================================*/
QMUXHeaderSize(void)88 static u16 QMUXHeaderSize( void )
89 {
90 return sizeof( sQMUX );
91 }
92
93 /*===========================================================================
94 METHOD:
95 QMICTLGetClientIDReqSize (Public Method)
96
97 DESCRIPTION:
98 Get size of buffer needed for QMUX + QMICTLGetClientIDReq
99
100 RETURN VALUE:
101 u16 - size of buffer
102 ===========================================================================*/
QMICTLGetClientIDReqSize(void)103 static u16 QMICTLGetClientIDReqSize( void )
104 {
105 return sizeof( sQMUX ) + 10;
106 }
107
108 /*===========================================================================
109 METHOD:
110 QMICTLReleaseClientIDReqSize (Public Method)
111
112 DESCRIPTION:
113 Get size of buffer needed for QMUX + QMICTLReleaseClientIDReq
114
115 RETURN VALUE:
116 u16 - size of header
117 ===========================================================================*/
QMICTLReleaseClientIDReqSize(void)118 static u16 QMICTLReleaseClientIDReqSize( void )
119 {
120 return sizeof( sQMUX ) + 11;
121 }
122
123 /*===========================================================================
124 METHOD:
125 QMICTLReadyReqSize (Public Method)
126
127 DESCRIPTION:
128 Get size of buffer needed for QMUX + QMICTLReadyReq
129
130 RETURN VALUE:
131 u16 - size of buffer
132 ===========================================================================*/
QMICTLReadyReqSize(void)133 static u16 QMICTLReadyReqSize( void )
134 {
135 return sizeof( sQMUX ) + 6;
136 }
137
138 /*===========================================================================
139 METHOD:
140 QMIWDSSetEventReportReqSize (Public Method)
141
142 DESCRIPTION:
143 Get size of buffer needed for QMUX + QMIWDSSetEventReportReq
144
145 RETURN VALUE:
146 u16 - size of buffer
147 ===========================================================================*/
QMIWDSSetEventReportReqSize(void)148 static u16 QMIWDSSetEventReportReqSize( void )
149 {
150 return sizeof( sQMUX ) + 15;
151 }
152
153 /*===========================================================================
154 METHOD:
155 QMIWDSGetPKGSRVCStatusReqSize (Public Method)
156
157 DESCRIPTION:
158 Get size of buffer needed for QMUX + QMIWDSGetPKGSRVCStatusReq
159
160 RETURN VALUE:
161 u16 - size of buffer
162 ===========================================================================*/
QMIWDSGetPKGSRVCStatusReqSize(void)163 static u16 QMIWDSGetPKGSRVCStatusReqSize( void )
164 {
165 return sizeof( sQMUX ) + 7;
166 }
167
168 /*===========================================================================
169 METHOD:
170 QMIDMSGetMEIDReqSize (Public Method)
171
172 DESCRIPTION:
173 Get size of buffer needed for QMUX + QMIDMSGetMEIDReq
174
175 RETURN VALUE:
176 u16 - size of buffer
177 ===========================================================================*/
QMIDMSGetMEIDReqSize(void)178 static u16 QMIDMSGetMEIDReqSize( void )
179 {
180 return sizeof( sQMUX ) + 7;
181 }
182
183 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS
184 {
185 u8 TLVType;
186 u16 TLVLength;
187 u8 QOSSetting;
188 } __packed;
189
190 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV
191 {
192 u8 TLVType;
193 u16 TLVLength;
194 u32 Value;
195 } __packed;
196
197 struct QMIWDS_ENDPOINT_TLV
198 {
199 u8 TLVType;
200 u16 TLVLength;
201 u32 ep_type;
202 u32 iface_id;
203 } __packed;
204
205 struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG
206 {
207 u8 CtlFlags; // 0: single QMUX Msg; 1:
208 u16 TransactionId;
209 u16 Type;
210 u16 Length;
211 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS QosDataFormatTlv;
212 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UnderlyingLinkLayerProtocolTlv;
213 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationProtocolTlv;
214 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationProtocolTlv;
215 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxDatagramsTlv;
216 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxSizeTlv;
217 struct QMIWDS_ENDPOINT_TLV epTlv;
218 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV dl_minimum_padding;
219 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxDatagramsTlv;
220 struct QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxSizeTlv;
221 } __packed;
222
223 /*===========================================================================
224 METHOD:
225 QMIWDASetDataFormatReqSize (Public Method)
226
227 DESCRIPTION:
228 Get size of buffer needed for QMUX + QMIWDASetDataFormatReq
229
230 RETURN VALUE:
231 u16 - size of buffer
232 ===========================================================================*/
QMIWDASetDataFormatReqSize(int qmap_version)233 static u16 QMIWDASetDataFormatReqSize( int qmap_version )
234 {
235 if (qmap_version)
236 return sizeof( sQMUX ) + sizeof(struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG);
237 else
238 return sizeof( sQMUX ) + 18;
239 }
240
241 /*===========================================================================
242 METHOD:
243 QMICTLSyncReqSize (Public Method)
244
245 DESCRIPTION:
246 Get size of buffer needed for QMUX + QMICTLSyncReq
247
248 RETURN VALUE:
249 u16 - size of buffer
250 ===========================================================================*/
QMICTLSyncReqSize(void)251 static u16 QMICTLSyncReqSize( void )
252 {
253 return sizeof( sQMUX ) + 6;
254 }
255
256 /*=========================================================================*/
257 // Generic QMUX functions
258 /*=========================================================================*/
259
260 /*===========================================================================
261 METHOD:
262 ParseQMUX (Public Method)
263
264 DESCRIPTION:
265 Remove QMUX headers from a buffer
266
267 PARAMETERS
268 pClientID [ O ] - On success, will point to Client ID
269 pBuffer [ I ] - Full Message passed in
270 buffSize [ I ] - Size of pBuffer
271
272 RETURN VALUE:
273 int - Positive for size of QMUX header
274 Negative errno for error
275 ===========================================================================*/
ParseQMUX(u16 * pClientID,void * pBuffer,u16 buffSize)276 static int ParseQMUX(
277 u16 * pClientID,
278 void * pBuffer,
279 u16 buffSize )
280 {
281 sQMUX * pQMUXHeader;
282
283 if (pBuffer == 0 || buffSize < 12)
284 {
285 return -ENOMEM;
286 }
287
288 // QMUX Header
289 pQMUXHeader = (sQMUX *)pBuffer;
290
291 if (pQMUXHeader->mTF != 1
292 || le16_to_cpu(get_unaligned(&pQMUXHeader->mLength)) != buffSize - 1
293 || pQMUXHeader->mCtrlFlag != 0x80 )
294 {
295 return -EINVAL;
296 }
297
298 // Client ID
299 *pClientID = (pQMUXHeader->mQMIClientID << 8) + pQMUXHeader->mQMIService;
300
301 return sizeof( sQMUX );
302 }
303
304 /*===========================================================================
305 METHOD:
306 FillQMUX (Public Method)
307
308 DESCRIPTION:
309 Fill buffer with QMUX headers
310
311 PARAMETERS
312 clientID [ I ] - Client ID
313 pBuffer [ O ] - Buffer to be filled
314 buffSize [ I ] - Size of pBuffer (must be at least 6)
315
316 RETURN VALUE:
317 int - 0 for success
318 Negative errno for error
319 ===========================================================================*/
FillQMUX(u16 clientID,void * pBuffer,u16 buffSize)320 static int FillQMUX(
321 u16 clientID,
322 void * pBuffer,
323 u16 buffSize )
324 {
325 sQMUX * pQMUXHeader;
326
327 if (pBuffer == 0 || buffSize < sizeof( sQMUX ))
328 {
329 return -ENOMEM;
330 }
331
332 // QMUX Header
333 pQMUXHeader = (sQMUX *)pBuffer;
334
335 pQMUXHeader->mTF = 1;
336 put_unaligned(cpu_to_le16(buffSize - 1), &pQMUXHeader->mLength);
337 //DBG("pQMUXHeader->mLength = 0x%x, buffSize - 1 = 0x%x\n",pQMUXHeader->mLength, buffSize - 1);
338 pQMUXHeader->mCtrlFlag = 0;
339
340 // Service and Client ID
341 pQMUXHeader->mQMIService = clientID & 0xff;
342 pQMUXHeader->mQMIClientID = clientID >> 8;
343
344 return 0;
345 }
346
347 /*=========================================================================*/
348 // Generic QMI functions
349 /*=========================================================================*/
350
351 /*===========================================================================
352 METHOD:
353 GetTLV (Public Method)
354
355 DESCRIPTION:
356 Get data buffer of a specified TLV from a QMI message
357
358 QMI Message shall NOT include SDU
359
360 PARAMETERS
361 pQMIMessage [ I ] - QMI Message buffer
362 messageLen [ I ] - Size of QMI Message buffer
363 type [ I ] - Desired Type
364 pOutDataBuf [ O ] - Buffer to be filled with TLV
365 messageLen [ I ] - Size of QMI Message buffer
366
367 RETURN VALUE:
368 u16 - Size of TLV for success
369 Negative errno for error
370 ===========================================================================*/
GetTLV(void * pQMIMessage,u16 messageLen,u8 type,void * pOutDataBuf,u16 bufferLen)371 static int GetTLV(
372 void * pQMIMessage,
373 u16 messageLen,
374 u8 type,
375 void * pOutDataBuf,
376 u16 bufferLen )
377 {
378 u16 pos;
379 u16 tlvSize = 0;
380 u16 cpyCount;
381
382 if (pQMIMessage == 0 || pOutDataBuf == 0)
383 {
384 return -ENOMEM;
385 }
386
387 for (pos = 4;
388 pos + 3 < messageLen;
389 pos += tlvSize + 3)
390 {
391 tlvSize = le16_to_cpu( get_unaligned(((u16 *)(pQMIMessage + pos + 1) )) );
392 if (*(u8 *)(pQMIMessage + pos) == type)
393 {
394 if (bufferLen < tlvSize)
395 {
396 return -ENOMEM;
397 }
398
399 for (cpyCount = 0; cpyCount < tlvSize; cpyCount++)
400 {
401 *((char*)(pOutDataBuf + cpyCount)) = *((char*)(pQMIMessage + pos + 3 + cpyCount));
402 }
403
404 return tlvSize;
405 }
406 }
407
408 return -ENOMSG;
409 }
410
411 /*===========================================================================
412 METHOD:
413 ValidQMIMessage (Public Method)
414
415 DESCRIPTION:
416 Check mandatory TLV in a QMI message
417
418 QMI Message shall NOT include SDU
419
420 PARAMETERS
421 pQMIMessage [ I ] - QMI Message buffer
422 messageLen [ I ] - Size of QMI Message buffer
423
424 RETURN VALUE:
425 int - 0 for success (no error)
426 Negative errno for error
427 Positive for QMI error code
428 ===========================================================================*/
ValidQMIMessage(void * pQMIMessage,u16 messageLen)429 static int ValidQMIMessage(
430 void * pQMIMessage,
431 u16 messageLen )
432 {
433 char mandTLV[4];
434
435 if (GetTLV( pQMIMessage, messageLen, 2, &mandTLV[0], 4 ) == 4)
436 {
437 // Found TLV
438 if (*(u16 *)&mandTLV[0] != 0)
439 {
440 return le16_to_cpu( get_unaligned(&mandTLV[2]) );
441 }
442 else
443 {
444 return 0;
445 }
446 }
447 else
448 {
449 return -ENOMSG;
450 }
451 }
452
453 /*===========================================================================
454 METHOD:
455 GetQMIMessageID (Public Method)
456
457 DESCRIPTION:
458 Get the message ID of a QMI message
459
460 QMI Message shall NOT include SDU
461
462 PARAMETERS
463 pQMIMessage [ I ] - QMI Message buffer
464 messageLen [ I ] - Size of QMI Message buffer
465
466 RETURN VALUE:
467 int - Positive for message ID
468 Negative errno for error
469 ===========================================================================*/
GetQMIMessageID(void * pQMIMessage,u16 messageLen)470 static int GetQMIMessageID(
471 void * pQMIMessage,
472 u16 messageLen )
473 {
474 if (messageLen < 2)
475 {
476 return -ENODATA;
477 }
478 else
479 {
480 return le16_to_cpu( get_unaligned((u16 *)pQMIMessage) );
481 }
482 }
483
484 /*=========================================================================*/
485 // Fill Buffers with QMI requests
486 /*=========================================================================*/
487
488 /*===========================================================================
489 METHOD:
490 QMICTLGetClientIDReq (Public Method)
491
492 DESCRIPTION:
493 Fill buffer with QMI CTL Get Client ID Request
494
495 PARAMETERS
496 pBuffer [ 0 ] - Buffer to be filled
497 buffSize [ I ] - Size of pBuffer
498 transactionID [ I ] - Transaction ID
499 serviceType [ I ] - Service type requested
500
501 RETURN VALUE:
502 int - Positive for resulting size of pBuffer
503 Negative errno for error
504 ===========================================================================*/
QMICTLGetClientIDReq(void * pBuffer,u16 buffSize,u8 transactionID,u8 serviceType)505 static int QMICTLGetClientIDReq(
506 void * pBuffer,
507 u16 buffSize,
508 u8 transactionID,
509 u8 serviceType )
510 {
511 if (pBuffer == 0 || buffSize < QMICTLGetClientIDReqSize() )
512 {
513 return -ENOMEM;
514 }
515
516 // QMI CTL GET CLIENT ID
517 // Request
518 *(u8 *)(pBuffer + sizeof( sQMUX ))= 0x00;
519 // Transaction ID
520 *(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID;
521 // Message ID
522 put_unaligned(cpu_to_le16(0x0022), (u16 *)(pBuffer + sizeof( sQMUX ) + 2));
523 // Size of TLV's
524 put_unaligned(cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 4));
525 // QMI Service Type
526 *(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01;
527 // Size
528 put_unaligned(cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 7));
529 // QMI svc type
530 *(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = serviceType;
531
532 // success
533 return sizeof( sQMUX ) + 10;
534 }
535
536 /*===========================================================================
537 METHOD:
538 QMICTLReleaseClientIDReq (Public Method)
539
540 DESCRIPTION:
541 Fill buffer with QMI CTL Release Client ID Request
542
543 PARAMETERS
544 pBuffer [ 0 ] - Buffer to be filled
545 buffSize [ I ] - Size of pBuffer
546 transactionID [ I ] - Transaction ID
547 clientID [ I ] - Service type requested
548
549 RETURN VALUE:
550 int - Positive for resulting size of pBuffer
551 Negative errno for error
552 ===========================================================================*/
QMICTLReleaseClientIDReq(void * pBuffer,u16 buffSize,u8 transactionID,u16 clientID)553 static int QMICTLReleaseClientIDReq(
554 void * pBuffer,
555 u16 buffSize,
556 u8 transactionID,
557 u16 clientID )
558 {
559 if (pBuffer == 0 || buffSize < QMICTLReleaseClientIDReqSize() )
560 {
561 return -ENOMEM;
562 }
563
564 DBG( "buffSize: 0x%x, transactionID: 0x%x, clientID: 0x%x,\n",
565 buffSize, transactionID, clientID );
566
567 // QMI CTL RELEASE CLIENT ID REQ
568 // Request
569 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
570 // Transaction ID
571 *(u8 *)(pBuffer + sizeof( sQMUX ) + 1 ) = transactionID;
572 // Message ID
573 put_unaligned( cpu_to_le16(0x0023), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) );
574 // Size of TLV's
575 put_unaligned( cpu_to_le16(0x0005), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) );
576 // Release client ID
577 *(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01;
578 // Size
579 put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 7));
580 // QMI svs type / Client ID
581 put_unaligned(cpu_to_le16(clientID), (u16 *)(pBuffer + sizeof( sQMUX ) + 9));
582
583 // success
584 return sizeof( sQMUX ) + 11;
585 }
586
587 /*===========================================================================
588 METHOD:
589 QMICTLReadyReq (Public Method)
590
591 DESCRIPTION:
592 Fill buffer with QMI CTL Get Version Info Request
593
594 PARAMETERS
595 pBuffer [ 0 ] - Buffer to be filled
596 buffSize [ I ] - Size of pBuffer
597 transactionID [ I ] - Transaction ID
598
599 RETURN VALUE:
600 int - Positive for resulting size of pBuffer
601 Negative errno for error
602 ===========================================================================*/
QMICTLReadyReq(void * pBuffer,u16 buffSize,u8 transactionID)603 static int QMICTLReadyReq(
604 void * pBuffer,
605 u16 buffSize,
606 u8 transactionID )
607 {
608 if (pBuffer == 0 || buffSize < QMICTLReadyReqSize() )
609 {
610 return -ENOMEM;
611 }
612
613 DBG("buffSize: 0x%x, transactionID: 0x%x\n", buffSize, transactionID);
614
615 // QMI CTL GET VERSION INFO REQ
616 // Request
617 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
618 // Transaction ID
619 *(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID;
620 // Message ID
621 put_unaligned( cpu_to_le16(0x0021), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) );
622 // Size of TLV's
623 put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) );
624
625 // success
626 return sizeof( sQMUX ) + 6;
627 }
628
629 /*===========================================================================
630 METHOD:
631 QMIWDSSetEventReportReq (Public Method)
632
633 DESCRIPTION:
634 Fill buffer with QMI WDS Set Event Report Request
635
636 PARAMETERS
637 pBuffer [ 0 ] - Buffer to be filled
638 buffSize [ I ] - Size of pBuffer
639 transactionID [ I ] - Transaction ID
640
641 RETURN VALUE:
642 int - Positive for resulting size of pBuffer
643 Negative errno for error
644 ===========================================================================*/
QMIWDSSetEventReportReq(void * pBuffer,u16 buffSize,u16 transactionID)645 static int QMIWDSSetEventReportReq(
646 void * pBuffer,
647 u16 buffSize,
648 u16 transactionID )
649 {
650 if (pBuffer == 0 || buffSize < QMIWDSSetEventReportReqSize() )
651 {
652 return -ENOMEM;
653 }
654
655 // QMI WDS SET EVENT REPORT REQ
656 // Request
657 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
658 // Transaction ID
659 put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1));
660 // Message ID
661 put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 3));
662 // Size of TLV's
663 put_unaligned(cpu_to_le16(0x0008), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
664 // Report channel rate TLV
665 *(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x11;
666 // Size
667 put_unaligned( cpu_to_le16(0x0005), (u16 *)(pBuffer + sizeof( sQMUX ) + 8));
668 // Stats period
669 *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 0x01;
670 // Stats mask
671 put_unaligned( cpu_to_le32(0x000000ff), (u32 *)(pBuffer + sizeof( sQMUX ) + 11) );
672
673 // success
674 return sizeof( sQMUX ) + 15;
675 }
676
677 /*===========================================================================
678 METHOD:
679 QMIWDSGetPKGSRVCStatusReq (Public Method)
680
681 DESCRIPTION:
682 Fill buffer with QMI WDS Get PKG SRVC Status Request
683
684 PARAMETERS
685 pBuffer [ 0 ] - Buffer to be filled
686 buffSize [ I ] - Size of pBuffer
687 transactionID [ I ] - Transaction ID
688
689 RETURN VALUE:
690 int - Positive for resulting size of pBuffer
691 Negative errno for error
692 ===========================================================================*/
QMIWDSGetPKGSRVCStatusReq(void * pBuffer,u16 buffSize,u16 transactionID)693 static int QMIWDSGetPKGSRVCStatusReq(
694 void * pBuffer,
695 u16 buffSize,
696 u16 transactionID )
697 {
698 if (pBuffer == 0 || buffSize < QMIWDSGetPKGSRVCStatusReqSize() )
699 {
700 return -ENOMEM;
701 }
702
703 // QMI WDS Get PKG SRVC Status REQ
704 // Request
705 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
706 // Transaction ID
707 put_unaligned(cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1));
708 // Message ID
709 put_unaligned(cpu_to_le16(0x0022), (u16 *)(pBuffer + sizeof( sQMUX ) + 3));
710 // Size of TLV's
711 put_unaligned(cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
712
713 // success
714 return sizeof( sQMUX ) + 7;
715 }
716
717 #if 0
718 static u16 QMIWDSSetQMUXBindMuxDataPortSize( void )
719 {
720 return sizeof( sQMUX ) + 29;
721 }
722
723 static u16 QMIWDSSetQMUXBindMuxDataPortReq(
724 void * pBuffer,
725 u16 buffSize,
726 u8 MuxId,
727 u16 transactionID )
728 {
729 if (pBuffer == 0 || buffSize < QMIWDSSetQMUXBindMuxDataPortSize() )
730 {
731 return -ENOMEM;
732 }
733
734 // QMI WDS Set QMUX Bind Mux Data Port REQ
735 // Request
736 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
737 // Transaction ID
738 put_unaligned(cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1));
739 // Message ID
740 put_unaligned(cpu_to_le16(0x00a2), (u16 *)(pBuffer + sizeof( sQMUX ) + 3));
741 // Size of TLV's
742 put_unaligned(cpu_to_le16(0x0016), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
743
744 *(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x10;
745 put_unaligned(cpu_to_le16(0x08), (u16 *)(pBuffer + sizeof( sQMUX ) + 8));
746 put_unaligned(cpu_to_le32(0x02), (u32 *)(pBuffer + sizeof( sQMUX ) + 10)); // ep_type
747 put_unaligned(cpu_to_le32(0x04), (u32 *)(pBuffer + sizeof( sQMUX ) + 14)); // iface_id
748
749 *(u8 *)(pBuffer + sizeof( sQMUX ) + 18) = 0x11;
750 put_unaligned(cpu_to_le16(0x01), (u16 *)(pBuffer + sizeof( sQMUX ) + 19));
751 *(u8 *)(pBuffer + sizeof( sQMUX ) + 21) = MuxId; // MuxId
752
753 *(u8 *)(pBuffer + sizeof( sQMUX ) + 22) = 0x13;
754 put_unaligned(cpu_to_le16(0x04), (u16 *)(pBuffer + sizeof( sQMUX ) + 23));
755 put_unaligned(cpu_to_le32(0x01), (u32 *)(pBuffer + sizeof( sQMUX ) + 25));
756
757 // success
758 return sizeof( sQMUX ) + 29;
759 }
760 #endif
761
762 /*===========================================================================
763 METHOD:
764 QMIDMSGetMEIDReq (Public Method)
765
766 DESCRIPTION:
767 Fill buffer with QMI DMS Get Serial Numbers Request
768
769 PARAMETERS
770 pBuffer [ 0 ] - Buffer to be filled
771 buffSize [ I ] - Size of pBuffer
772 transactionID [ I ] - Transaction ID
773
774 RETURN VALUE:
775 int - Positive for resulting size of pBuffer
776 Negative errno for error
777 ===========================================================================*/
QMIDMSGetMEIDReq(void * pBuffer,u16 buffSize,u16 transactionID)778 static int QMIDMSGetMEIDReq(
779 void * pBuffer,
780 u16 buffSize,
781 u16 transactionID )
782 {
783 if (pBuffer == 0 || buffSize < QMIDMSGetMEIDReqSize() )
784 {
785 return -ENOMEM;
786 }
787
788 // QMI DMS GET SERIAL NUMBERS REQ
789 // Request
790 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
791 // Transaction ID
792 put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1) );
793 // Message ID
794 put_unaligned( cpu_to_le16(0x0025), (u16 *)(pBuffer + sizeof( sQMUX ) + 3) );
795 // Size of TLV's
796 put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
797
798 // success
799 return sizeof( sQMUX ) + 7;
800 }
801
802 /*===========================================================================
803 METHOD:
804 QMIWDASetDataFormatReq (Public Method)
805
806 DESCRIPTION:
807 Fill buffer with QMI WDA Set Data Format Request
808
809 PARAMETERS
810 pBuffer [ 0 ] - Buffer to be filled
811 buffSize [ I ] - Size of pBuffer
812 transactionID [ I ] - Transaction ID
813
814 RETURN VALUE:
815 int - Positive for resulting size of pBuffer
816 Negative errno for error
817 ===========================================================================*/
QMIWDASetDataFormatReq(void * pBuffer,u16 buffSize,bool bRawIPMode,int qmap_version,u32 rx_size,u16 transactionID)818 static int QMIWDASetDataFormatReq(
819 void * pBuffer,
820 u16 buffSize,
821 bool bRawIPMode, int qmap_version, u32 rx_size,
822 u16 transactionID )
823 {
824 if (qmap_version) {
825 struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG *pMUXMsg = (struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG *)(pBuffer + sizeof( sQMUX ));
826
827 pMUXMsg->CtlFlags = 0x00;
828 put_unaligned( cpu_to_le16(transactionID), &pMUXMsg->TransactionId);
829 put_unaligned( cpu_to_le16(0x0020), &pMUXMsg->Type);
830 put_unaligned( cpu_to_le16(sizeof( struct QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG) - 7), &pMUXMsg->Length);
831
832 //Indicates whether the Quality of Service(QOS) data format is used by the client.
833 pMUXMsg->QosDataFormatTlv.TLVType = 0x10;
834 pMUXMsg->QosDataFormatTlv.TLVLength = cpu_to_le16(0x0001);
835 pMUXMsg->QosDataFormatTlv.QOSSetting = 0; /* no-QOS header */
836 //Underlying Link Layer Protocol
837 pMUXMsg->UnderlyingLinkLayerProtocolTlv.TLVType = 0x11;
838 pMUXMsg->UnderlyingLinkLayerProtocolTlv.TLVLength = cpu_to_le16(4);
839 pMUXMsg->UnderlyingLinkLayerProtocolTlv.Value = cpu_to_le32(0x02); /* Set Ethernet mode */
840 //Uplink (UL) data aggregation protocol to be used for uplink data transfer.
841 pMUXMsg->UplinkDataAggregationProtocolTlv.TLVType = 0x12;
842 pMUXMsg->UplinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4);
843 pMUXMsg->UplinkDataAggregationProtocolTlv.Value = cpu_to_le32(qmap_version); //UL QMAP is enabled
844 //Downlink (DL) data aggregation protocol to be used for downlink data transfer
845 pMUXMsg->DownlinkDataAggregationProtocolTlv.TLVType = 0x13;
846 pMUXMsg->DownlinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4);
847 pMUXMsg->DownlinkDataAggregationProtocolTlv.Value = cpu_to_le32(qmap_version); //UL QMAP is enabled
848 //Maximum number of datagrams in a single aggregated packet on downlink
849 pMUXMsg->DownlinkDataAggregationMaxDatagramsTlv.TLVType = 0x15;
850 pMUXMsg->DownlinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4);
851 pMUXMsg->DownlinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32(rx_size/1024);
852 //Maximum size in bytes of a single aggregated packet allowed on downlink
853 pMUXMsg->DownlinkDataAggregationMaxSizeTlv.TLVType = 0x16;
854 pMUXMsg->DownlinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4);
855 pMUXMsg->DownlinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(rx_size);
856 //Peripheral End Point ID
857 pMUXMsg->epTlv.TLVType = 0x17;
858 pMUXMsg->epTlv.TLVLength = cpu_to_le16(8);
859 pMUXMsg->epTlv.ep_type = cpu_to_le32(0x02); // DATA_EP_TYPE_BAM_DMUX
860 pMUXMsg->epTlv.iface_id = cpu_to_le32(0x04);
861 //Specifies the minimum padding bytes to be added in between aggregated downlink QMAP packets.
862 pMUXMsg->dl_minimum_padding.TLVType = 0x19;
863 pMUXMsg->dl_minimum_padding.TLVLength = cpu_to_le16(4);
864 pMUXMsg->dl_minimum_padding.Value = cpu_to_le32(0);
865 //Maximum number of datagrams in a single aggregated packet on uplink
866 pMUXMsg->UplinkDataAggregationMaxDatagramsTlv.TLVType = 27;
867 pMUXMsg->UplinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4);
868 pMUXMsg->UplinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32(11);
869 //Maximum size in bytes of a single aggregated packet allowed on uplink
870 pMUXMsg->UplinkDataAggregationMaxSizeTlv.TLVType = 28;
871 pMUXMsg->UplinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4);
872 pMUXMsg->UplinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(8*1024);
873 }
874 else {
875 if (pBuffer == 0 || buffSize < QMIWDASetDataFormatReqSize(qmap_version) )
876 {
877 return -ENOMEM;
878 }
879
880 // QMI WDA SET DATA FORMAT REQ
881 // Request
882 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
883
884 // Transaction ID
885 put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1) );
886
887 // Message ID
888 put_unaligned( cpu_to_le16(0x0020), (u16 *)(pBuffer + sizeof( sQMUX ) + 3) );
889
890 // Size of TLV's
891 put_unaligned( cpu_to_le16(0x000b), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
892
893 /* TLVType QOS Data Format 1 byte */
894 *(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x10; // type data format
895
896 /* TLVLength 2 bytes - see spec */
897 put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 8));
898
899 /* DataFormat: 0-default; 1-QoS hdr present 2 bytes */
900 #ifdef QOS_MODE
901 *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 1; /* QOS header */
902 #else
903 *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 0; /* no-QOS header */
904 #endif
905
906 /* TLVType Link-Layer Protocol (Optional) 1 byte */
907 *(u8 *)(pBuffer + sizeof( sQMUX ) + 11) = 0x11;
908
909 /* TLVLength 2 bytes */
910 put_unaligned( cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 12));
911
912 /* LinkProt: 0x1 - ETH; 0x2 - rawIP 4 bytes */
913 if (bRawIPMode) { //#ifdef DATA_MODE_RP
914 /* Set RawIP mode */
915 put_unaligned( cpu_to_le32(0x00000002), (u32 *)(pBuffer + sizeof( sQMUX ) + 14));
916 DBG("Request RawIP Data Format\n");
917 } else { //#else
918 /* Set Ethernet mode */
919 put_unaligned( cpu_to_le32(0x00000001), (u32 *)(pBuffer + sizeof( sQMUX ) + 14));
920 DBG("Request Ethernet Data Format\n");
921 } //#endif
922
923 }
924
925 // success
926 return QMIWDASetDataFormatReqSize(qmap_version);
927 }
928
929 #if 0
930 static int QMIWDASetDataQmapReq(
931 void * pBuffer,
932 u16 buffSize,
933 u16 transactionID )
934 {
935 // QMI WDA SET DATA FORMAT REQ
936 // Request
937 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
938
939 // Transaction ID
940 put_unaligned( cpu_to_le16(transactionID), (u16 *)(pBuffer + sizeof( sQMUX ) + 1) );
941
942 // Message ID
943 put_unaligned( cpu_to_le16(0x002B), (u16 *)(pBuffer + sizeof( sQMUX ) + 3) );
944
945 // Size of TLV's
946 put_unaligned( cpu_to_le16(0x0004), (u16 *)(pBuffer + sizeof( sQMUX ) + 5));
947
948 /* TLVType QMAP In-Band Flow Control 1 byte */
949 *(u8 *)(pBuffer + sizeof( sQMUX ) + 7) = 0x10;
950 put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 8));
951 *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = 0x01;
952
953 // success
954 return ( sizeof( sQMUX ) + 11);
955 }
956 #endif
957
958 #if 0
959 /*===========================================================================
960 METHOD:
961 QMICTLSetDataFormatReqSize (Public Method)
962
963 DESCRIPTION:
964 Get size of buffer needed for QMUX + QMICTLSetDataFormatReq
965
966 RETURN VALUE:
967 u16 - size of buffer
968 ===========================================================================*/
969 static u16 QMICTLSetDataFormatReqSize( void )
970 {
971 return sizeof( sQMUX ) + 15;
972 }
973
974 /*===========================================================================
975 METHOD:
976 QMICTLSetDataFormatReq (Public Method)
977
978 DESCRIPTION:
979 Fill buffer with QMI CTL Set Data Format Request
980
981 PARAMETERS
982 pBuffer [ 0 ] - Buffer to be filled
983 buffSize [ I ] - Size of pBuffer
984 transactionID [ I ] - Transaction ID
985
986 RETURN VALUE:
987 int - Positive for resulting size of pBuffer
988 Negative errno for error
989 ===========================================================================*/
990 static int QMICTLSetDataFormatReq(
991 void * pBuffer,
992 u16 buffSize,
993 u8 transactionID )
994 {
995 if (pBuffer == 0 || buffSize < QMICTLSetDataFormatReqSize() )
996 {
997 return -ENOMEM;
998 }
999
1000 /* QMI CTL Set Data Format Request */
1001 /* Request */
1002 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00; // QMICTL_FLAG_REQUEST
1003
1004 /* Transaction ID 1 byte */
1005 *(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID; /* 1 byte as in spec */
1006
1007 /* QMICTLType 2 bytes */
1008 put_unaligned( cpu_to_le16(0x0026), (u16 *)(pBuffer + sizeof( sQMUX ) + 2));
1009
1010 /* Length 2 bytes of 2 TLVs each - see spec */
1011 put_unaligned( cpu_to_le16(0x0009), (u16 *)(pBuffer + sizeof( sQMUX ) + 4));
1012
1013 /* TLVType Data Format (Mandatory) 1 byte */
1014 *(u8 *)(pBuffer + sizeof( sQMUX ) + 6) = 0x01; // type data format
1015
1016 /* TLVLength 2 bytes - see spec */
1017 put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 7));
1018
1019 /* DataFormat: 0-default; 1-QoS hdr present 2 bytes */
1020 #ifdef QOS_MODE
1021 *(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = 1; /* QOS header */
1022 #else
1023 *(u8 *)(pBuffer + sizeof( sQMUX ) + 9) = 0; /* no-QOS header */
1024 #endif
1025
1026 /* TLVType Link-Layer Protocol (Optional) 1 byte */
1027 *(u8 *)(pBuffer + sizeof( sQMUX ) + 10) = TLV_TYPE_LINK_PROTO;
1028
1029 /* TLVLength 2 bytes */
1030 put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 11));
1031
1032 /* LinkProt: 0x1 - ETH; 0x2 - rawIP 2 bytes */
1033 #ifdef DATA_MODE_RP
1034 /* Set RawIP mode */
1035 put_unaligned( cpu_to_le16(0x0002), (u16 *)(pBuffer + sizeof( sQMUX ) + 13));
1036 DBG("Request RawIP Data Format\n");
1037 #else
1038 /* Set Ethernet mode */
1039 put_unaligned( cpu_to_le16(0x0001), (u16 *)(pBuffer + sizeof( sQMUX ) + 13));
1040 DBG("Request Ethernet Data Format\n");
1041 #endif
1042
1043 /* success */
1044 return sizeof( sQMUX ) + 15;
1045
1046 }
1047 #endif
1048
1049 /*===========================================================================
1050 METHOD:
1051 QMICTLSyncReq (Public Method)
1052
1053 DESCRIPTION:
1054 Fill buffer with QMI CTL Sync Request
1055
1056 PARAMETERS
1057 pBuffer [ 0 ] - Buffer to be filled
1058 buffSize [ I ] - Size of pBuffer
1059 transactionID [ I ] - Transaction ID
1060
1061 RETURN VALUE:
1062 int - Positive for resulting size of pBuffer
1063 Negative errno for error
1064 ===========================================================================*/
QMICTLSyncReq(void * pBuffer,u16 buffSize,u16 transactionID)1065 static int QMICTLSyncReq(
1066 void * pBuffer,
1067 u16 buffSize,
1068 u16 transactionID )
1069 {
1070 if (pBuffer == 0 || buffSize < QMICTLSyncReqSize() )
1071 {
1072 return -ENOMEM;
1073 }
1074
1075 // Request
1076 *(u8 *)(pBuffer + sizeof( sQMUX )) = 0x00;
1077 // Transaction ID
1078 *(u8 *)(pBuffer + sizeof( sQMUX ) + 1) = transactionID;
1079 // Message ID
1080 put_unaligned( cpu_to_le16(0x0027), (u16 *)(pBuffer + sizeof( sQMUX ) + 2) );
1081 // Size of TLV's
1082 put_unaligned( cpu_to_le16(0x0000), (u16 *)(pBuffer + sizeof( sQMUX ) + 4) );
1083
1084 // success
1085 return sizeof( sQMUX ) + 6;
1086 }
1087
1088 /*=========================================================================*/
1089 // Parse data from QMI responses
1090 /*=========================================================================*/
1091
1092 /*===========================================================================
1093 METHOD:
1094 QMICTLGetClientIDResp (Public Method)
1095
1096 DESCRIPTION:
1097 Parse the QMI CTL Get Client ID Resp
1098
1099 PARAMETERS
1100 pBuffer [ I ] - Buffer to be parsed
1101 buffSize [ I ] - Size of pBuffer
1102 pClientID [ 0 ] - Recieved client ID
1103
1104 RETURN VALUE:
1105 int - 0 for success
1106 Negative errno for error
1107 ===========================================================================*/
QMICTLGetClientIDResp(void * pBuffer,u16 buffSize,u16 * pClientID)1108 static int QMICTLGetClientIDResp(
1109 void * pBuffer,
1110 u16 buffSize,
1111 u16 * pClientID )
1112 {
1113 int result;
1114
1115 // Ignore QMUX and SDU
1116 // QMI CTL SDU is 2 bytes, not 3
1117 u8 offset = sizeof( sQMUX ) + 2;
1118
1119 if (pBuffer == 0 || buffSize < offset)
1120 {
1121 return -ENOMEM;
1122 }
1123
1124 pBuffer = pBuffer + offset;
1125 buffSize -= offset;
1126
1127 result = GetQMIMessageID( pBuffer, buffSize );
1128 if (result != 0x22)
1129 {
1130 return -EFAULT;
1131 }
1132
1133 result = ValidQMIMessage( pBuffer, buffSize );
1134 if (result != 0)
1135 {
1136 return -EFAULT;
1137 }
1138
1139 result = GetTLV( pBuffer, buffSize, 0x01, pClientID, 2 );
1140 if (result != 2)
1141 {
1142 return -EFAULT;
1143 }
1144
1145 return 0;
1146 }
1147
1148 /*===========================================================================
1149 METHOD:
1150 QMICTLReleaseClientIDResp (Public Method)
1151
1152 DESCRIPTION:
1153 Verify the QMI CTL Release Client ID Resp is valid
1154
1155 PARAMETERS
1156 pBuffer [ I ] - Buffer to be parsed
1157 buffSize [ I ] - Size of pBuffer
1158
1159 RETURN VALUE:
1160 int - 0 for success
1161 Negative errno for error
1162 ===========================================================================*/
QMICTLReleaseClientIDResp(void * pBuffer,u16 buffSize)1163 static int QMICTLReleaseClientIDResp(
1164 void * pBuffer,
1165 u16 buffSize )
1166 {
1167 int result;
1168
1169 // Ignore QMUX and SDU
1170 // QMI CTL SDU is 2 bytes, not 3
1171 u8 offset = sizeof( sQMUX ) + 2;
1172
1173 if (pBuffer == 0 || buffSize < offset)
1174 {
1175 return -ENOMEM;
1176 }
1177
1178 pBuffer = pBuffer + offset;
1179 buffSize -= offset;
1180
1181 result = GetQMIMessageID( pBuffer, buffSize );
1182 if (result != 0x23)
1183 {
1184 return -EFAULT;
1185 }
1186
1187 result = ValidQMIMessage( pBuffer, buffSize );
1188 if (result != 0)
1189 {
1190 return -EFAULT;
1191 }
1192
1193 return 0;
1194 }
1195
1196 /*===========================================================================
1197 METHOD:
1198 QMIWDSEventResp (Public Method)
1199
1200 DESCRIPTION:
1201 Parse the QMI WDS Set Event Report Resp/Indication or
1202 QMI WDS Get PKG SRVC Status Resp/Indication
1203
1204 Return parameters will only be updated if value was received
1205
1206 PARAMETERS
1207 pBuffer [ I ] - Buffer to be parsed
1208 buffSize [ I ] - Size of pBuffer
1209 pTXOk [ O ] - Number of transmitted packets without errors
1210 pRXOk [ O ] - Number of recieved packets without errors
1211 pTXErr [ O ] - Number of transmitted packets with framing errors
1212 pRXErr [ O ] - Number of recieved packets with framing errors
1213 pTXOfl [ O ] - Number of transmitted packets dropped due to overflow
1214 pRXOfl [ O ] - Number of recieved packets dropped due to overflow
1215 pTXBytesOk [ O ] - Number of transmitted bytes without errors
1216 pRXBytesOk [ O ] - Number of recieved bytes without errors
1217 pbLinkState [ 0 ] - Is the link active?
1218 pbReconfigure [ 0 ] - Must interface be reconfigured? (reset IP address)
1219
1220 RETURN VALUE:
1221 int - 0 for success
1222 Negative errno for error
1223 ===========================================================================*/
QMIWDSEventResp(void * pBuffer,u16 buffSize,u32 * pTXOk,u32 * pRXOk,u32 * pTXErr,u32 * pRXErr,u32 * pTXOfl,u32 * pRXOfl,u64 * pTXBytesOk,u64 * pRXBytesOk,bool * pbLinkState,bool * pbReconfigure)1224 static int QMIWDSEventResp(
1225 void * pBuffer,
1226 u16 buffSize,
1227 u32 * pTXOk,
1228 u32 * pRXOk,
1229 u32 * pTXErr,
1230 u32 * pRXErr,
1231 u32 * pTXOfl,
1232 u32 * pRXOfl,
1233 u64 * pTXBytesOk,
1234 u64 * pRXBytesOk,
1235 bool * pbLinkState,
1236 bool * pbReconfigure )
1237 {
1238 int result;
1239 u8 pktStatusRead[2];
1240
1241 // Ignore QMUX and SDU
1242 u8 offset = sizeof( sQMUX ) + 3;
1243
1244 if (pBuffer == 0
1245 || buffSize < offset
1246 || pTXOk == 0
1247 || pRXOk == 0
1248 || pTXErr == 0
1249 || pRXErr == 0
1250 || pTXOfl == 0
1251 || pRXOfl == 0
1252 || pTXBytesOk == 0
1253 || pRXBytesOk == 0
1254 || pbLinkState == 0
1255 || pbReconfigure == 0 )
1256 {
1257 return -ENOMEM;
1258 }
1259
1260 pBuffer = pBuffer + offset;
1261 buffSize -= offset;
1262
1263 // Note: Indications. No Mandatory TLV required
1264
1265 result = GetQMIMessageID( pBuffer, buffSize );
1266 // QMI WDS Set Event Report Resp
1267 if (result == 0x01)
1268 {
1269 // TLV's are not mandatory
1270 GetTLV( pBuffer, buffSize, 0x10, (void*)pTXOk, 4 );
1271 put_unaligned( le32_to_cpu(*pTXOk), pTXOk);
1272 GetTLV( pBuffer, buffSize, 0x11, (void*)pRXOk, 4 );
1273 put_unaligned( le32_to_cpu(*pRXOk), pRXOk);
1274 GetTLV( pBuffer, buffSize, 0x12, (void*)pTXErr, 4 );
1275 put_unaligned( le32_to_cpu(*pTXErr), pTXErr);
1276 GetTLV( pBuffer, buffSize, 0x13, (void*)pRXErr, 4 );
1277 put_unaligned( le32_to_cpu(*pRXErr), pRXErr);
1278 GetTLV( pBuffer, buffSize, 0x14, (void*)pTXOfl, 4 );
1279 put_unaligned( le32_to_cpu(*pTXOfl), pTXOfl);
1280 GetTLV( pBuffer, buffSize, 0x15, (void*)pRXOfl, 4 );
1281 put_unaligned( le32_to_cpu(*pRXOfl), pRXOfl);
1282 GetTLV( pBuffer, buffSize, 0x19, (void*)pTXBytesOk, 8 );
1283 put_unaligned( le64_to_cpu(*pTXBytesOk), pTXBytesOk);
1284 GetTLV( pBuffer, buffSize, 0x1A, (void*)pRXBytesOk, 8 );
1285 put_unaligned( le64_to_cpu(*pRXBytesOk), pRXBytesOk);
1286 }
1287 // QMI WDS Get PKG SRVC Status Resp
1288 else if (result == 0x22)
1289 {
1290 result = GetTLV( pBuffer, buffSize, 0x01, &pktStatusRead[0], 2 );
1291 // 1 or 2 bytes may be received
1292 if (result >= 1)
1293 {
1294 if (pktStatusRead[0] == 0x02)
1295 {
1296 *pbLinkState = true;
1297 }
1298 else
1299 {
1300 *pbLinkState = false;
1301 }
1302 }
1303 if (result == 2)
1304 {
1305 if (pktStatusRead[1] == 0x01)
1306 {
1307 *pbReconfigure = true;
1308 }
1309 else
1310 {
1311 *pbReconfigure = false;
1312 }
1313 }
1314
1315 if (result < 0)
1316 {
1317 return result;
1318 }
1319 }
1320 else
1321 {
1322 return -EFAULT;
1323 }
1324
1325 return 0;
1326 }
1327
1328 /*===========================================================================
1329 METHOD:
1330 QMIDMSGetMEIDResp (Public Method)
1331
1332 DESCRIPTION:
1333 Parse the QMI DMS Get Serial Numbers Resp
1334
1335 PARAMETERS
1336 pBuffer [ I ] - Buffer to be parsed
1337 buffSize [ I ] - Size of pBuffer
1338 pMEID [ O ] - Device MEID
1339 meidSize [ I ] - Size of MEID buffer (at least 14)
1340
1341 RETURN VALUE:
1342 int - 0 for success
1343 Negative errno for error
1344 ===========================================================================*/
QMIDMSGetMEIDResp(void * pBuffer,u16 buffSize,char * pMEID,int meidSize)1345 static int QMIDMSGetMEIDResp(
1346 void * pBuffer,
1347 u16 buffSize,
1348 char * pMEID,
1349 int meidSize )
1350 {
1351 int result;
1352
1353 // Ignore QMUX and SDU
1354 u8 offset = sizeof( sQMUX ) + 3;
1355
1356 if (pBuffer == 0 || buffSize < offset || meidSize < 14)
1357 {
1358 return -ENOMEM;
1359 }
1360
1361 pBuffer = pBuffer + offset;
1362 buffSize -= offset;
1363
1364 result = GetQMIMessageID( pBuffer, buffSize );
1365 if (result != 0x25)
1366 {
1367 return -EFAULT;
1368 }
1369
1370 result = ValidQMIMessage( pBuffer, buffSize );
1371 if (result != 0)
1372 {
1373 return -EFAULT;
1374 }
1375
1376 result = GetTLV( pBuffer, buffSize, 0x12, (void*)pMEID, 14 );
1377 if (result != 14)
1378 {
1379 return -EFAULT;
1380 }
1381
1382 return 0;
1383 }
1384
1385 /*===========================================================================
1386 METHOD:
1387 QMIWDASetDataFormatResp (Public Method)
1388
1389 DESCRIPTION:
1390 Parse the QMI WDA Set Data Format Response
1391
1392 PARAMETERS
1393 pBuffer [ I ] - Buffer to be parsed
1394 buffSize [ I ] - Size of pBuffer
1395
1396 RETURN VALUE:
1397 int - 0 for success
1398 Negative errno for error
1399 ===========================================================================*/
QMIWDASetDataFormatResp(void * pBuffer,u16 buffSize,bool bRawIPMode,int * qmap_version,int * rx_size,int * tx_size,QMAP_SETTING * set)1400 static int QMIWDASetDataFormatResp(
1401 void * pBuffer,
1402 u16 buffSize, bool bRawIPMode, int *qmap_version, int *rx_size, int *tx_size, QMAP_SETTING *set)
1403 {
1404
1405 int result;
1406
1407 u8 pktLinkProtocol[4];
1408
1409 // Ignore QMUX and SDU
1410 // QMI SDU is 3 bytes
1411 u8 offset = sizeof( sQMUX ) + 3;
1412
1413 if (pBuffer == 0 || buffSize < offset)
1414 {
1415 return -ENOMEM;
1416 }
1417
1418 pBuffer = pBuffer + offset;
1419 buffSize -= offset;
1420
1421 result = GetQMIMessageID( pBuffer, buffSize );
1422 if (result != 0x20)
1423 {
1424 return -EFAULT;
1425 }
1426
1427 /* Check response message result TLV */
1428 result = ValidQMIMessage( pBuffer, buffSize );
1429 if (result != 0)
1430 {
1431 DBG("EFAULT: Data Format Mode Bad Response\n");
1432 // return -EFAULT;
1433 return 0;
1434 }
1435
1436 /* Check response message link protocol */
1437 result = GetTLV( pBuffer, buffSize, 0x11,
1438 &pktLinkProtocol[0], 4);
1439 if (result != 4)
1440 {
1441 DBG("EFAULT: Wrong TLV format\n");
1442 return 0;
1443 }
1444
1445 if (bRawIPMode) { ////#ifdef DATA_MODE_RP
1446 if (pktLinkProtocol[0] != 2)
1447 {
1448 DBG("EFAULT: Data Format Cannot be set to RawIP Mode\n");
1449 return pktLinkProtocol[0];
1450 }
1451 DBG("Data Format Set to RawIP\n");
1452 } else { ////#else
1453 if (pktLinkProtocol[0] != 1)
1454 {
1455 DBG("EFAULT: Data Format Cannot be set to Ethernet Mode\n");
1456 return pktLinkProtocol[0];
1457 }
1458 DBG("Data Format Set to Ethernet Mode \n");
1459 } //#endif
1460
1461 GetTLV( pBuffer, buffSize, 0x12, qmap_version, 4);
1462 if (le32_to_cpu(*qmap_version))
1463 GetTLV( pBuffer, buffSize, 0x13, qmap_version, 4);
1464
1465 GetTLV( pBuffer, buffSize, 0x16, rx_size, 4);
1466 GetTLV( pBuffer, buffSize, 0x18, tx_size, 4);
1467
1468 if (set) {
1469 GetTLV( pBuffer, buffSize, 0x15, &set->dl_data_aggregation_max_datagrams, 4);
1470 GetTLV( pBuffer, buffSize, 0x16, &set->dl_data_aggregation_max_size, 4);
1471 GetTLV( pBuffer, buffSize, 0x17, &set->ul_data_aggregation_max_datagrams, 4);
1472 GetTLV( pBuffer, buffSize, 0x18, &set->ul_data_aggregation_max_size, 4);
1473 GetTLV( pBuffer, buffSize, 0x1a, &set->dl_minimum_padding, 4);
1474 }
1475
1476 return pktLinkProtocol[0];
1477 }
1478
1479 /*===========================================================================
1480 METHOD:
1481 QMICTLSyncResp (Public Method)
1482
1483 DESCRIPTION:
1484 Validate the QMI CTL Sync Response
1485
1486 PARAMETERS
1487 pBuffer [ I ] - Buffer to be parsed
1488 buffSize [ I ] - Size of pBuffer
1489
1490 RETURN VALUE:
1491 int - 0 for success
1492 Negative errno for error
1493 ===========================================================================*/
QMICTLSyncResp(void * pBuffer,u16 buffSize)1494 static int QMICTLSyncResp(
1495 void *pBuffer,
1496 u16 buffSize )
1497 {
1498 int result;
1499
1500 // Ignore QMUX (2 bytes for QMI CTL) and SDU
1501 u8 offset = sizeof( sQMUX ) + 2;
1502
1503 if (pBuffer == 0 || buffSize < offset)
1504 {
1505 return -ENOMEM;
1506 }
1507
1508 pBuffer = pBuffer + offset;
1509 buffSize -= offset;
1510
1511 result = GetQMIMessageID( pBuffer, buffSize );
1512 if (result != 0x27)
1513 {
1514 return -EFAULT;
1515 }
1516
1517 result = ValidQMIMessage( pBuffer, buffSize );
1518
1519 return result;
1520 }
1521 #endif
1522