xref: /OK3568_Linux_fs/kernel/drivers/net/usb/GobiNet/QMI.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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