1/*
2 * This file is developed based on USBModemECMControl.cpp
3 * which is used by mac NDIS dail 2012.01.05
4 * this file only process the qmi data package,so hope for porting to other system easily.
5 * Copyright (C) 2012 by qiaoyongkang (longcheer Ltd.)
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will support Longcheer data card devices for Linux networking,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/ctype.h>
24#include <linux/kernel.h>
25#include "qmi_oper.h"
26#include "qmi_header.h"
27#define bzero(b,len) memset((b),0,(len))
28
29static UInt8    fQMITransactionId = 0;
30//#define HEX_DEBUG
31#ifdef DEBUG
32#define lc_kdbg(fmt, arg...) 	do{ \
33	printk(KERN_ERR "######: " fmt , ## arg); \
34	}while(0)
35#else
36#define lc_kdbg(fmt, arg...) 	do{ \
37	}while(0)
38#endif
39/********************************************************************
40 *
41 *         Name:  printk_hex
42 *  Description:  print data buffer with hex which is lined by 16 bytes
43 *        Input:  buf:the data buffer to be print of
44 *                buf_size:the data buffer length.
45 *       Return:  null
46 *        Notes:
47 ********************************************************************/
48void printk_hex(UInt8 *buf,int buf_size)
49{
50#ifdef HEX_DEBUG
51    int i,j;
52    int total_size = 0;
53    int line_cout =  buf_size>>4;
54    if((buf_size&0x0000000f)!=0)
55        line_cout++;
56
57    for(i=0;i<line_cout;i++)
58    {
59        printk("\n%d:",total_size);
60        for(j=0;j<16;j++)
61        {
62            total_size++;
63            printk("%02X ",buf[(i<<4)+j]);
64            if(((i<<4)+1+j)==buf_size)
65            {
66                printk("\n");
67                return;
68            }
69        }
70    }
71#endif
72}
73/********************************************************************
74 *
75 *         Name:  QCTL_GetClientID
76 *  Description:  get a qmi client ID
77 *        Input:  qmiType:the type of qmi,there are QMUX_TYPE_WDS
78 *                length:the pMsgBuff max length.
79 *       Output:  pMsgBuff : the buf used to generate a package.
80 *       Return:  -1 : call faled.
81 *                >0  : call success,the package length used.
82 *        Notes:
83 ********************************************************************/
84int  QCTL_GetClientID(UInt8* pMsgBuff,UInt32 length,UInt8 qmiType)
85{
86    UInt16 msgLength;
87//	void *pMsgBuff = NULL;
88	QCQMI* qmi = NULL;
89	QMICTL_GET_CLIENT_ID_REQ_MSG* pReq = NULL;
90
91	lc_kdbg("QCTL_GetClientID : entry\n");
92
93	msgLength = sizeof(QCQMI_HDR) + sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG);
94	lc_kdbg("%s:msgLength=%d,%d,%d\n",__func__, msgLength,sizeof(QCQMI_HDR),sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG) );
95
96	if(msgLength>length||pMsgBuff==NULL)
97	{
98		lc_kdbg("QCTL_GetClientID : length=%d < msgLength=%d OR pMsgBuff==NULL\n",msgLength,length);
99		return -1;
100	}
101
102	bzero(pMsgBuff, length);
103
104	qmi = (QCQMI*)pMsgBuff;
105	pReq = (QMICTL_GET_CLIENT_ID_REQ_MSG*)&(qmi->SDU);
106
107	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
108	qmi->Length   = msgLength - sizeof(qmi->IFType);
109	qmi->CtlFlags  = QMICTL_CTL_FLAG_CMD;
110	qmi->QMIType  = QMUX_TYPE_CTL;
111	qmi->ClientId = 0x00;
112
113	pReq->CtlFlags = QMICTL_CTL_FLAG_REQUEST;
114	++fQMITransactionId;
115	pReq->TransactionId = fQMITransactionId;
116	pReq->QMICTLType    = QMICTL_GET_CLIENT_ID_REQ;
117	pReq->Length        = sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG) - sizeof(QCQMICTL_MSG_HDR);
118	pReq->TLVType       = QCTLV_TYPE_REQUIRED_PARAMETER;
119	pReq->TLVLength     = 1;
120	pReq->QMIType       = qmiType;
121
122	//lc_kdbg("QCTL_GetClientID : leave");
123	lc_kdbg("%s : leave\n",__func__);
124	return msgLength;
125}
126/********************************************************************
127 *
128 *         Name:  QCTL_ReleaseClientID
129 *  Description:  relase a qmi client ID
130 *        Input:  length:the pMsgBuff max length.
131 *                pndis_status : the input global parameters.
132 *       Output:  pMsgBuff : the buf used to generate a package.
133 *       Return:  -1 : call faled.
134 *                >0  : call success,the package length used.
135 *        Notes:
136 ********************************************************************/
137int QCTL_ReleaseClientID(UInt8* pMsgBuff,UInt32 length,NDIS_QMI_STATUS* pndis_status)
138{
139	UInt16 msgLength;
140//	void *pMsgBuff = NULL;
141	QCQMI* qmi = NULL;
142	QMICTL_RELEASE_CLIENT_ID_REQ_MSG* pReq = NULL;
143
144	lc_kdbg("QCTL_ReleaseClientID : entry\n");
145	msgLength = sizeof(QCQMI_HDR) + sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG);
146
147	if(msgLength>length||pMsgBuff==NULL)
148	{
149		lc_kdbg("QCTL_ReleaseClientID : length=%d < msgLength=%d OR pMsgBuff==NULL\n",msgLength,length);
150		return -1;
151	}
152	bzero(pMsgBuff, length);
153
154	qmi = (QCQMI*)pMsgBuff;
155	pReq = (QMICTL_RELEASE_CLIENT_ID_REQ_MSG*)&(qmi->SDU);
156
157	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
158	qmi->Length   = msgLength - sizeof(qmi->IFType);
159	qmi->CtlFlags  = QMICTL_CTL_FLAG_CMD;
160	qmi->QMIType  = QMUX_TYPE_CTL;
161	qmi->ClientId = 0x00;
162
163	pReq->CtlFlags = QMICTL_CTL_FLAG_REQUEST;
164	++fQMITransactionId;
165	pReq->TransactionId = fQMITransactionId;
166	pReq->QMICTLType    = QMICTL_RELEASE_CLIENT_ID_REQ;
167	pReq->Length        = sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG) - sizeof(QCQMICTL_MSG_HDR);
168	pReq->TLVType       = QCTLV_TYPE_REQUIRED_PARAMETER;
169	pReq->TLVLength     = 2;
170	pReq->QMIType       = pndis_status->fQMIType;
171	pReq->ClientId      = pndis_status->fClientID;
172
173	//lc_kdbg("QCTL_ReleaseClientID : leave");
174	lc_kdbg("%s : leave\n",__func__);
175    return msgLength;
176}
177/********************************************************************
178 *
179 *         Name:  QCTL_GetVersionReq
180 *  Description:  GET a qmi version info
181 *        Input:  length:the pMsgBuff max length.
182 *       Output:  pMsgBuff : the buf used to generate a package.
183 *       Return:  -1 : call faled.
184 *                >0  : call success,the package length used.
185 *        Notes:
186 ********************************************************************/
187int QCTL_GetVersionReq(UInt8* pMsgBuff,UInt32 length)
188{
189	UInt16 msgLength;
190//	void *pMsgBuff = NULL;
191	QCQMI* qmi = NULL;
192	QMICTL_GET_VERSION_REQ_MSG* pReq = NULL;
193
194	lc_kdbg("QCTL_GetVersionReq : entry\n");
195
196	msgLength = sizeof(QCQMI_HDR) + sizeof(QMICTL_GET_VERSION_REQ_MSG);
197
198	if (msgLength>length||pMsgBuff==NULL)
199	{
200	    lc_kdbg("QCTL_GetVersionReq : length=%d < msgLength=%d OR pMsgBuff==NULL\n",msgLength,length);
201		return -1;
202	}
203
204	bzero(pMsgBuff, length);
205
206	qmi = (QCQMI*)pMsgBuff;
207	pReq = (QMICTL_GET_VERSION_REQ_MSG*)&(qmi->SDU);
208
209	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
210	qmi->Length   = msgLength - sizeof(qmi->IFType);
211	qmi->CtlFlags  = QMICTL_CTL_FLAG_CMD;
212	qmi->QMIType  = QMUX_TYPE_CTL;
213	qmi->ClientId = 0x00;
214
215	pReq->CtlFlags = QMICTL_CTL_FLAG_REQUEST;
216	++fQMITransactionId;
217	pReq->TransactionId = fQMITransactionId;
218	pReq->QMICTLType    = QMICTL_GET_VERSION_REQ;
219	pReq->Length        = sizeof(QMICTL_GET_VERSION_REQ_MSG) - sizeof(QCQMICTL_MSG_HDR);
220	pReq->TLVType       = QCTLV_TYPE_REQUIRED_PARAMETER;
221	pReq->TLVLength     = 0x0001;
222	pReq->QMIType       = QMUX_TYPE_ALL;
223
224	//lc_kdbg("QCTL_GetVersionReq : leave");
225	lc_kdbg("%s : leave\n",__func__);
226    return msgLength;
227}
228/********************************************************************
229 *
230 *         Name:  QCTL_SetDataFormatReq
231 *  Description:  set a qmi data format
232 *        Input:  length:the pMsgBuff max length.
233 *       Output:  pMsgBuff : the buf used to generate a package.
234 *       Return:  -1 : call faled.
235 *                >0  : call success,the package length used.
236 *        Notes:
237 ********************************************************************/
238int QCTL_SetDataFormatReq(UInt8* pMsgBuff,UInt32 length)
239{
240	UInt16 msgLength;
241//	void *pMsgBuff = NULL;
242	QCQMI* qmi = NULL;
243	QMICTL_SET_DATA_FORMAT_REQ_MSG* pReq = NULL;
244
245	lc_kdbg("QCTL_SetDataFormatReq : entry\n");
246
247	msgLength = sizeof(QCQMI_HDR) + sizeof(QMICTL_SET_DATA_FORMAT_REQ_MSG);
248
249//	pMsgBuff = IOMalloc(msgLength);
250
251	if (msgLength>length||pMsgBuff==NULL)
252	{
253	    lc_kdbg("QCTL_SetDataFormatReq : length=%d < msgLength=%d OR pMsgBuff==NULL\n",msgLength,length);
254		return -1;
255	}
256
257	bzero(pMsgBuff, length);
258
259	qmi = (QCQMI*)pMsgBuff;
260	pReq = (QMICTL_SET_DATA_FORMAT_REQ_MSG*)&(qmi->SDU);
261
262	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
263	qmi->Length   = msgLength - sizeof(qmi->IFType);
264	qmi->CtlFlags  = QMICTL_CTL_FLAG_CMD;
265	qmi->QMIType  = QMUX_TYPE_CTL;
266	qmi->ClientId = 0x00;
267
268	pReq->CtlFlags = QMICTL_CTL_FLAG_REQUEST;
269	++fQMITransactionId;
270	pReq->TransactionId = fQMITransactionId;
271	pReq->QMICTLType    = QMICTL_SET_DATA_FORMAT_REQ;
272	pReq->Length        = sizeof(QMICTL_SET_DATA_FORMAT_REQ_MSG) - sizeof(QCQMICTL_MSG_HDR);
273	pReq->TLVType       = QCTLV_TYPE_REQUIRED_PARAMETER;
274	pReq->TLVLength     = 0x0001;
275	pReq->DataFormat    = 0; // disable qos
276	pReq->Proto.TLVType = SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO;
277	pReq->Proto.TLVLength = 0x0002;
278	pReq->Proto.LinkProt  = (SET_DATA_FORMAT_LINK_PROTO_ETH | SET_DATA_FORMAT_LINK_PROTO_IP);
279
280	//lc_kdbg("QCTL_SetDataFormatReq : leave");
281	lc_kdbg("%s : leave\n",__func__);
282    return msgLength;
283}
284/********************************************************************
285 *
286 *         Name:  QCTL_SetInstanceId
287 *  Description:  set a qmi Instance ID
288 *        Input:  length:the pMsgBuff max length.
289 *       Output:  pMsgBuff : the buf used to generate a package.
290 *       Return:  -1 : call faled.
291 *                >0  : call success,the package length used.
292 *        Notes:
293 ********************************************************************/
294int QCTL_SetInstanceId(UInt8* pMsgBuff,UInt32 length)
295{
296	UInt16 msgLength;
297//	void *pMsgBuff = NULL;
298	QCQMI* qmi = NULL;
299	QMICTL_SET_INSTANCE_ID_REQ_MSG* pSet = NULL;
300
301	//lc_kdbg("QCTL_SetInstanceId : entry");
302	lc_kdbg("%s : entry\n",__func__);
303
304	msgLength = sizeof(QCQMI_HDR) + sizeof(QMICTL_SET_INSTANCE_ID_REQ_MSG);
305
306//	pMsgBuff = IOMalloc(msgLength);
307	if (msgLength>length||pMsgBuff==NULL)
308	{
309	    lc_kdbg("%s : length=%d < msgLength=%d OR pMsgBuff==NULL\n",__func__,msgLength,length);
310		return -1;
311	}
312
313	bzero(pMsgBuff, length);
314
315	qmi = (QCQMI*)pMsgBuff;
316	pSet = (QMICTL_SET_INSTANCE_ID_REQ_MSG*)&(qmi->SDU);
317
318	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
319	qmi->Length   = msgLength - sizeof(qmi->IFType);
320	qmi->CtlFlags  = QMICTL_CTL_FLAG_CMD;
321	qmi->QMIType  = QMUX_TYPE_CTL;
322	qmi->ClientId = 0x00;
323
324	pSet->CtlFlags = QMICTL_CTL_FLAG_REQUEST;
325	++fQMITransactionId;
326	pSet->TransactionId = fQMITransactionId;
327	pSet->QMICTLType    = QMICTL_SET_INSTANCE_ID_REQ;
328	pSet->Length        = sizeof(QMICTL_SET_INSTANCE_ID_REQ_MSG) - sizeof(QCQMICTL_MSG_HDR);
329	pSet->TLVType       = QCTLV_TYPE_REQUIRED_PARAMETER;
330	pSet->TLVLength     = 1;
331	pSet->Value         = 1; // will fail?
332
333	lc_kdbg("%s : leave\n",__func__);
334
335    return msgLength;
336}
337/********************************************************************
338 *
339 *         Name:  QC_WDS_GetIPAddress
340 *  Description:  get  qmi ip address
341 *        Input:  length:the pMsgBuff max length.
342 *                fClientID:the current clientID
343 *       Output:  pMsgBuff : the buf used to generate a package.
344 *       Return:  -1 : call faled.
345 *                >0  : call success,the package length used.
346 *        Notes:
347 ********************************************************************/
348int QC_WDS_GetIPAddress(UInt8* pMsgBuff,UInt32 length,UInt8 fClientID)
349{
350	UInt16 msgLength;
351	QCQMI* qmi = NULL;
352	QCQMUX* pQCQMUX = NULL;
353	QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG* pGetMsg = NULL;
354
355	lc_kdbg("%s : entry\n",__func__);
356	msgLength = sizeof(QCQMI_HDR) + sizeof(QCQMUX_HDR) + sizeof(QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG);
357	if (msgLength>length||pMsgBuff==NULL)
358	{
359	    lc_kdbg("%s : length=%d < msgLength=%d OR pMsgBuff==NULL\n",__func__,msgLength,length);
360		return -1;
361	}
362	qmi = (QCQMI*)pMsgBuff;
363	bzero(pMsgBuff, length);
364
365	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
366	qmi->CtlFlags = QMICTL_CTL_FLAG_CMD;
367	qmi->QMIType  = QMUX_TYPE_WDS;
368	qmi->ClientId = fClientID;
369	qmi->Length   = msgLength - sizeof(qmi->IFType);
370
371	pQCQMUX = (QCQMUX*)&(qmi->SDU);
372
373	pQCQMUX->CtlFlags = QMUX_CTL_FLAG_SINGLE_MSG | QMUX_CTL_FLAG_TYPE_CMD;
374	++fQMITransactionId;
375	pQCQMUX->TransactionId = fQMITransactionId;
376
377	pGetMsg = (QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG*)&(pQCQMUX->Message);
378	pGetMsg->Type = QMIWDS_GET_RUNTIME_SETTINGS_REQ;
379	pGetMsg->Length  = sizeof(QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG) - sizeof(QCQMUX_MSG_HDR);
380	pGetMsg->TLVType =  0x10;
381	pGetMsg->TLVLength = 0x04;
382	pGetMsg->Mask = QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR;
383
384	lc_kdbg("%s : leave\n",__func__);
385
386    return msgLength;
387}
388
389/********************************************************************
390 *
391 *         Name:  QC_WDS_ModifyProfile
392 *  Description:  use apn dail to internet through qmi
393 *        Input:  length:the pMsgBuff max length;
394 *                fClientID:the current clientID
395 *                accessString:apn;
396 *                userName: user name;
397 *                passWord: password;
398 *                compression: auth type.
399 *       Output:  pMsgBuff : the buf used to generate a package.
400 *       Return:  -1 : call faled.
401 *                >0  : call success,the package length used.
402 *        Notes:
403 ********************************************************************/
404int QC_WDS_ModifyProfile(UInt8* pMsgBuff,
405					UInt32 length,
406					NDIS_QMI_STATUS*  pndis_status,//fClientID
407					char *accessString,
408					char *userName,
409					char *passWord,
410					UInt8 compression,
411					UInt32 ConnectIpMode)
412{
413	UInt16 msgLength;
414	QCQMI* qmi = NULL;
415	UInt8  *pMsg = NULL;
416	QCQMUX* pQCQMUX = NULL;
417	QCQMUX_MSG_HDR* qmuxMsg = NULL;
418
419//	if(ConnectIpMode == 0)
420//		return -1;
421	lc_kdbg("%s : entry\n",__func__);
422	qmi = (QCQMI*)pMsgBuff;
423
424	bzero(pMsgBuff, length);
425
426	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
427	qmi->CtlFlags = QMICTL_CTL_FLAG_CMD;
428	qmi->QMIType  = QMUX_TYPE_WDS;
429	qmi->ClientId = pndis_status->fClientID;
430
431	msgLength = sizeof(QCQMI_HDR);
432	pMsg = (UInt8 *)pMsgBuff;
433
434	pMsg += msgLength;
435
436	pQCQMUX = (QCQMUX*)&(qmi->SDU);
437
438	//lc_kdbg_hex(pMsgBuff,32);
439
440	pQCQMUX->CtlFlags = QMUX_CTL_FLAG_SINGLE_MSG | QMUX_CTL_FLAG_TYPE_CMD;
441	++fQMITransactionId;
442	pQCQMUX->TransactionId = cpu_to_le16(fQMITransactionId);
443	//pndis_status->fConnectionTransId = cpu_to_le16(pQCQMUX->TransactionId);
444	//lc_kdbg_hex(pMsgBuff,32);
445	//pQCQMUX->CtlFlags = QMUX_CTL_FLAG_TYPE_RSP | QMUX_CTL_FLAG_TYPE_CMD;
446	//lc_kdbg_hex(pMsgBuff,32);
447
448
449	qmuxMsg = (QCQMUX_MSG_HDR*)&(pQCQMUX->Message);
450	qmuxMsg->Type = cpu_to_le16(QMI_WDS_MODIFY_PROFILE_SETTINGS_REQ);
451	//lc_kdbg_hex(pMsgBuff,32);
452	pMsg = (UInt8 *)&(qmuxMsg->Length);
453
454	pMsg += sizeof(qmuxMsg->Length);
455
456	// APN
457	//if (accessString && (strlen(accessString) > 0))
458	{
459		*pMsg = QCTLV_TYPE_APN;
460		++pMsg;
461		// length
462		*(UInt16 *)pMsg = cpu_to_le16(strlen(accessString));
463		pMsg += sizeof(UInt16);
464
465		strcpy((char *)pMsg, accessString);
466
467		pMsg += strlen(accessString);
468	}
469
470	// Auth
471	switch (compression)
472	{
473		case WwanAuthProtocolNone:
474		{
475		    break;
476		}
477
478		case WwanAuthProtocolPap:
479		{
480			*pMsg = 0x1d;
481			++pMsg;
482			*(UInt16 *)pMsg = 1;
483			pMsg += sizeof(UInt16);
484			*pMsg = 1;
485			++pMsg;
486			break;
487		}
488
489		case WwanAuthProtocolChap:
490		case WwanAuthProtocolMax:
491		{
492			*pMsg = 0x1d;
493			++pMsg;
494			*(UInt16 *)pMsg = 1;
495			pMsg += sizeof(UInt16);
496			*pMsg = 2;
497			++pMsg;
498			break;
499		}
500
501		default:
502		{
503		    break;
504		}
505	}
506
507	// user name
508	if (userName)
509	{
510	   if (strlen(userName) > 0)
511	   {
512		   *pMsg = 0x1b;
513		   ++pMsg;
514		   *(UInt16 *)pMsg = strlen(userName);
515		   pMsg += sizeof(UInt16);
516		   strcpy((char *)pMsg, userName);
517		   pMsg += strlen(userName);
518	   }
519	}
520
521	// password
522	if (passWord)
523	{
524		if (strlen(passWord) > 0)
525		{
526			*pMsg = 0x1c;
527			++pMsg;
528			*(UInt16 *)pMsg = strlen(passWord);
529			pMsg += sizeof(UInt16);
530			strcpy((char *)pMsg, passWord);
531			pMsg += strlen(passWord);
532		}
533	}
534
535	switch(ConnectIpMode)
536	{
537		case IPv4:			//ipv 4
538			{
539				*pMsg = 0x1d;
540				++pMsg;
541				// length
542				*(UInt16 *)pMsg = 1;
543				pMsg += sizeof(UInt16);
544
545				*(char *)pMsg = 4;
546				pMsg += sizeof(UInt8);
547			}
548			break;
549		case IPv6:		//ipv 6
550			{
551				*pMsg = 0x1d;
552				++pMsg;
553				// length
554				*(UInt16 *)pMsg = 1;
555				pMsg += sizeof(UInt16);
556
557				*(char *)pMsg = 6;
558				pMsg += sizeof(UInt8);
559
560			}
561			break;
562	}
563
564
565	// ProfileType & ProfileIndex
566	{
567		*pMsg = 0x01;
568		++pMsg;
569		// length
570		*(UInt16 *)pMsg = 2;
571		pMsg += sizeof(UInt16);
572
573		if(ConnectIpMode == IPv6)
574		{
575			*(char *)pMsg = 0;
576			pMsg += sizeof(UInt8);
577			*(char *)pMsg = 2;
578		}
579		else if (ConnectIpMode == IPv4v6)
580		{
581			*(char *)pMsg = 0;
582			pMsg += sizeof(UInt8);
583			*(char *)pMsg = 2;
584		}
585
586		pMsg += sizeof(UInt8);
587	}
588
589	// PdpType
590	{
591		*pMsg = 0x11;
592		++pMsg;
593		// length
594		*(UInt16 *)pMsg = 1;
595		pMsg += sizeof(UInt16);
596
597		if(ConnectIpMode == IPv6)
598		{
599			*(char *)pMsg = 2;
600		}
601		else if(ConnectIpMode == IPv4v6)
602		{
603			*(char *)pMsg = 3;
604		}
605
606		pMsg += sizeof(UInt8);
607	}
608
609
610
611
612	// set the length
613	qmuxMsg->Length = cpu_to_le16((UInt8 *)pMsg - (UInt8 *)&(qmuxMsg->Length) - sizeof(UInt16));
614	qmi->Length     = cpu_to_le16((UInt8 *)pMsg - (UInt8 *)&(qmi->Length));
615	msgLength       = (UInt8 *)pMsg - (UInt8 *)qmi;
616
617	lc_kdbg("%s: Connect dump data:\n",__func__);
618	printk_hex(pMsgBuff,msgLength);
619
620	lc_kdbg("%s : leave\n",__func__);
621
622    return msgLength;
623}
624
625/********************************************************************
626 *
627 *         Name:  QC_WDS_Connect
628 *  Description:  use apn dail to internet through qmi
629 *        Input:  length:the pMsgBuff max length;
630 *                fClientID:the current clientID
631 *                accessString:apn;
632 *                userName: user name;
633 *                passWord: password;
634 *                compression: auth type.
635 *       Output:  pMsgBuff : the buf used to generate a package.
636 *       Return:  -1 : call faled.
637 *                >0  : call success,the package length used.
638 *        Notes:
639 ********************************************************************/
640int QC_WDS_Connect(UInt8* pMsgBuff,
641					UInt32 length,
642					UInt8  fClientID,
643					char *accessString,
644					char *userName,
645					char *passWord,
646					UInt8 compression,
647					UInt32 ConnectIpMode)
648{
649	UInt16 msgLength;
650	QCQMI* qmi = NULL;
651	UInt8  *pMsg = NULL;
652	QCQMUX* pQCQMUX = NULL;
653	QCQMUX_MSG_HDR* qmuxMsg = NULL;
654
655	if(ConnectIpMode == 2)
656		return -1;
657	lc_kdbg("%s : entry\n",__func__);
658	qmi = (QCQMI*)pMsgBuff;
659
660	bzero(pMsgBuff, length);
661
662	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
663	qmi->CtlFlags = QMICTL_CTL_FLAG_CMD;
664	qmi->QMIType  = QMUX_TYPE_WDS;
665	qmi->ClientId = fClientID;
666
667	msgLength = sizeof(QCQMI_HDR);
668	pMsg = (UInt8 *)pMsgBuff;
669
670	pMsg += msgLength;
671
672	pQCQMUX = (QCQMUX*)&(qmi->SDU);
673
674	//lc_kdbg_hex(pMsgBuff,32);
675
676	pQCQMUX->CtlFlags = QMUX_CTL_FLAG_SINGLE_MSG | QMUX_CTL_FLAG_TYPE_CMD;
677	++fQMITransactionId;
678	pQCQMUX->TransactionId = fQMITransactionId;
679	//lc_kdbg_hex(pMsgBuff,32);
680	//pQCQMUX->CtlFlags = QMUX_CTL_FLAG_TYPE_RSP | QMUX_CTL_FLAG_TYPE_CMD;
681	//lc_kdbg_hex(pMsgBuff,32);
682
683
684	qmuxMsg = (QCQMUX_MSG_HDR*)&(pQCQMUX->Message);
685	qmuxMsg->Type = QMIWDS_START_NETWORK_INTERFACE_REQ;
686	//lc_kdbg_hex(pMsgBuff,32);
687	pMsg = (UInt8 *)&(qmuxMsg->Length);
688
689	pMsg += sizeof(qmuxMsg->Length);
690
691	// APN
692	//if (accessString && (strlen(accessString) > 0))
693	{
694		*pMsg = QCTLV_TYPE_APN;
695		++pMsg;
696		// length
697		*(UInt16 *)pMsg = strlen(accessString);
698		pMsg += sizeof(UInt16);
699
700		strcpy((char *)pMsg, accessString);
701
702		pMsg += strlen(accessString);
703	}
704
705	// Auth
706	switch (compression)
707	{
708		case WwanAuthProtocolNone:
709		{
710		    break;
711		}
712
713		case WwanAuthProtocolPap:
714		{
715			*pMsg = QCTLV_TYPE_AUTH_TYPE;
716			++pMsg;
717			*(UInt16 *)pMsg = 1;
718			pMsg += sizeof(UInt16);
719			*pMsg = 1;
720			++pMsg;
721			break;
722		}
723
724		case WwanAuthProtocolChap:
725		{
726			*pMsg = QCTLV_TYPE_AUTH_TYPE;
727			++pMsg;
728			*(UInt16 *)pMsg = 1;
729			pMsg += sizeof(UInt16);
730			*pMsg = 2;
731			++pMsg;
732			break;
733		}
734
735		default:
736		{
737		    break;
738		}
739	}
740
741	// user name
742	if (userName)
743	{
744	   if (strlen(userName) > 0)
745	   {
746		   *pMsg = QCTLV_TYPE_USER_NAME;
747		   ++pMsg;
748		   *(UInt16 *)pMsg = strlen(userName);
749		   pMsg += sizeof(UInt16);
750		   strcpy((char *)pMsg, userName);
751		   pMsg += strlen(userName);
752	   }
753	}
754
755	// password
756	if (passWord)
757	{
758		if (strlen(passWord) > 0)
759		{
760			*pMsg = QCTLV_TYPE_PASSWORD;
761			++pMsg;
762			*(UInt16 *)pMsg = strlen(passWord);
763			pMsg += sizeof(UInt16);
764			strcpy((char *)pMsg, passWord);
765			pMsg += strlen(passWord);
766		}
767	}
768
769	switch(ConnectIpMode)
770	{
771		case IPv4:			//ipv 4
772			{
773				*pMsg = 0x19;
774				++pMsg;
775				// length
776				*(UInt16 *)pMsg = 1;
777				pMsg += sizeof(UInt16);
778
779				*(char *)pMsg = 4;
780				pMsg += sizeof(UInt8);
781			}
782			break;
783		case IPv6:		//ipv 6
784			{
785				*pMsg = 0x19;
786				++pMsg;
787				// length
788				*(UInt16 *)pMsg = 1;
789				pMsg += sizeof(UInt16);
790
791				*(char *)pMsg = 6;
792				pMsg += sizeof(UInt8);
793
794				*pMsg = 0x31;
795				++pMsg;
796				// length
797				*(UInt16 *)pMsg = 1;
798				pMsg += sizeof(UInt16);
799
800				*(char *)pMsg = 2;
801				pMsg += sizeof(UInt8);
802
803			}
804			break;
805	}
806
807	// set the length
808	qmuxMsg->Length = (UInt8 *)pMsg - (UInt8 *)&(qmuxMsg->Length) - sizeof(UInt16);
809	qmi->Length     = (UInt8 *)pMsg - (UInt8 *)&(qmi->Length);
810	msgLength       = (UInt8 *)pMsg - (UInt8 *)qmi;
811
812	lc_kdbg("%s: Connect dump data:\n",__func__);
813	printk_hex(pMsgBuff,msgLength);
814
815	lc_kdbg("%s : leave\n",__func__);
816
817    return msgLength;
818}
819/********************************************************************
820 *
821 *         Name:  QC_WDS_Disconnect
822 *  Description:  disconnect from  qmi internet.
823 *        Input:  length:the pMsgBuff max length.
824 *                pndis_status:ndis global status parameters.
825 *       Output:  pMsgBuff : the buf used to generate a package.
826 *       Return:  -1 : call faled.
827 *                >0  : call success,the package length used.
828 *        Notes:
829 ********************************************************************/
830int QC_WDS_Disconnect(UInt8* pMsgBuff,UInt32 length,NDIS_QMI_STATUS* pndis_status,UInt8 flag)
831{
832	UInt16 msgLength;
833	QCQMI* qmi = NULL;
834	QCQMUX* pQCQMUX = NULL;
835	QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG* pStopMsg = NULL;
836
837	lc_kdbg("%s : entry\n",__func__);
838
839	msgLength = sizeof(QCQMI_HDR) + sizeof(QCQMUX_HDR) + sizeof(QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG);
840	if (msgLength>length||pMsgBuff==NULL)
841	{
842	    lc_kdbg("%s : length=%d < msgLength=%d OR pMsgBuff==NULL\n",__func__,msgLength,length);
843		return -1;
844	}
845
846	qmi = (QCQMI*)pMsgBuff;
847
848	bzero(pMsgBuff, length);
849
850	qmi->IFType   = USB_CTL_MSG_TYPE_QMI;
851	qmi->CtlFlags = QMICTL_CTL_FLAG_CMD;
852	qmi->QMIType  = QMUX_TYPE_WDS;
853	qmi->ClientId = pndis_status->fClientID;
854	qmi->Length   = msgLength - sizeof(qmi->IFType);
855
856	pQCQMUX = (QCQMUX*)&(qmi->SDU);
857
858	pQCQMUX->CtlFlags = QMUX_CTL_FLAG_SINGLE_MSG | QMUX_CTL_FLAG_TYPE_CMD;
859	++fQMITransactionId;
860	pQCQMUX->TransactionId = fQMITransactionId;
861
862	pStopMsg = (QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG*)&(pQCQMUX->Message);
863	pStopMsg->Type = QMIWDS_STOP_NETWORK_INTERFACE_REQ;
864	pStopMsg->Length  = sizeof(QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG) - sizeof(QCQMUX_MSG_HDR);
865	pStopMsg->TLVType =  QCTLV_TYPE_REQUIRED_PARAMETER;
866	pStopMsg->TLVLength = 0x04;
867	if(flag)
868		pStopMsg->Packet_Handle = cpu_to_le32(pndis_status->fPacketHandle);
869	else
870		pStopMsg->Packet_Handle = cpu_to_le32(pndis_status->fPacketHandle1);
871
872	lc_kdbg("%s : leave\n",__func__);
873
874    return msgLength;
875
876	lc_kdbg("%s : leave\n",__func__);
877
878    return msgLength;
879}
880/********************************************************************
881 *
882 *         Name:  QCTL_Procecess_GetClient_ID_Response
883 *  Description:  QCTL Procecess GetClient ID Response
884 *        Input:  pQmi:the package message get from qmi server.
885 *       Output:  fClientID : client ID getted from the package.
886 *                fQMIType  : fQMIType getted from the package.
887 *       Return:  -1 : call faled.
888 *                >0  : call success,the package length used.
889 *        Notes:
890 ********************************************************************/
891int QCTL_Procecess_GetClient_ID_Response(QCQMI* pQmi,UInt8* fClientID,UInt8* fQMIType)
892{
893	QMICTL_GET_CLIENT_ID_RESP_MSG* pMsg = (QMICTL_GET_CLIENT_ID_RESP_MSG*)&(pQmi->SDU);
894
895	lc_kdbg("%s : entry\n",__func__);
896
897	if (pMsg->QMIResult == QMI_RESULT_SUCCESS)
898	{
899	    *fClientID = pMsg->ClientId;
900		*fQMIType  = pMsg->QMIType;
901
902		lc_kdbg("%s: get client id.\n",__func__);
903	}
904	else
905	{
906		*fClientID = 0;
907		*fQMIType = 0;
908		lc_kdbg("%s: failed to get client id.\n",__func__);
909		return -1;
910	}
911
912	lc_kdbg("%s : leave\n",__func__);
913
914	return 0;
915}
916/********************************************************************
917 *
918 *         Name:  QCTL_Procecess_SetDataFormat_Response
919 *  Description:  QCTL Procecess SetDataFormat Response.
920 *        Input:  pQmi:the package message get from qmi server.
921 *       Output:  pndis_status : qmi global status parameters.
922 *       Return:  -1 : call faled.
923 *                >0  : call success,the package length used.
924 *        Notes:
925 ********************************************************************/
926int QCTL_Procecess_SetDataFormat_Response(QCQMI* pQmi,NDIS_QMI_STATUS* pndis_status)
927{
928    QMICTL_SET_DATA_FORMAT_RESP_MSG* pMsg = (QMICTL_SET_DATA_FORMAT_RESP_MSG*)&(pQmi->SDU);
929
930	lc_kdbg("%s : entry\n",__func__);
931
932	if (pMsg->QMIResult == QMI_RESULT_SUCCESS)
933	{
934	    if (pndis_status->fIPPacketSupport)
935		{
936		    UInt8 *pMsgStart = (UInt8 *) &(pMsg->TLVType);
937			UInt8 *pMsgPtr = (UInt8 *)&(pMsg->QMIError);
938			UInt32 remaningBytes;
939			pMsgPtr += sizeof(UInt16);
940
941			remaningBytes = pMsg->Length - (pMsgPtr -pMsgStart);
942
943			if (remaningBytes >= sizeof(QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT))
944			{
945				if (pMsg->Proto.TLVType == SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO)
946				{
947					lc_kdbg("%s: link protocol received.pMsg->Proto.LinkProt=%u\n",__func__,pMsg->Proto.LinkProt);
948					pndis_status->fIPModeEnabled = (pMsg->Proto.LinkProt == SET_DATA_FORMAT_LINK_PROTO_IP);
949					if (pndis_status->fIPModeEnabled)
950					{
951					    lc_kdbg("IP Mode is enabled!\n");
952					}
953				}
954			}
955		}
956	}
957	else
958	{
959	    lc_kdbg("%s: failed to set data format.QMIError=%u,QMIResult=%u\n",__func__, pMsg->QMIError, pMsg->QMIResult);
960		return -1;
961	}
962
963/*	if (fSetDataFormating)
964	{
965	    fSetDataFormating = false;
966		fCommandGate->commandWakeup(NULL, false);
967		XTRACE(this, 0, 0, "QCTL_Procecess_SetDataFormat_Response: now wake up command gate");
968	}*/
969	lc_kdbg("%s : leave\n",__func__);
970
971	return 0;
972}
973/********************************************************************
974 *
975 *         Name:  QCTL_Procecess_SetInstanceId_Response
976 *  Description:  QCTL Procecess SetInstanceId Response.
977 *        Input:  pQmi:the package message get from qmi server.
978 *       Output:  fSetInstanceIdFail : if get qmi id return -1,else return 1.
979 *                fQMI_ID : QMI_ID
980 *       Return:  -1 : call faled.
981 *                >0  : call success,the package length used.
982 *        Notes:
983 ********************************************************************/
984int QCTL_Procecess_SetInstanceId_Response(QCQMI* pQmi,int* fSetInstanceIdFail,UInt32* fQMI_ID)
985{
986	QMICTL_SET_INSTANCE_ID_RESP_MSG* pMsg = (QMICTL_SET_INSTANCE_ID_RESP_MSG*)&(pQmi->SDU);
987
988	lc_kdbg("%s : entry\n",__func__);
989
990	if (pMsg->QMIResult == QMI_RESULT_SUCCESS)
991	{
992	    *fQMI_ID = pMsg->QMI_ID;
993		*fSetInstanceIdFail = -1;
994		lc_kdbg("%s: get qmi id,QMI_ID=%u\n",__func__,pMsg->QMI_ID);
995	}
996	else
997	{
998		*fSetInstanceIdFail = 1;
999		*fQMI_ID = MP_INVALID_QMI_ID;
1000		lc_kdbg("%s: failed to get qmi id,QMIResult=%u,QMIError=%u.\n",
1001				__func__,pMsg->QMIResult, pMsg->QMIError);
1002		return -1;
1003	}
1004
1005/*	if (fSetInstanceIding)
1006	{
1007	    fSetInstanceIding = false;
1008		fCommandGate->commandWakeup(NULL, false);
1009		XTRACE(this, 0, 0, "QCTL_Procecess_SetInstanceId_Response: now wake up command gate");
1010	}*/
1011	lc_kdbg("%s : leave\n",__func__);
1012
1013	return 0;
1014}
1015/********************************************************************
1016 *
1017 *         Name:  QCTL_Procecess_ReleaseClient_ID_Response
1018 *  Description:  QCTL Procecess ReleaseClient ID Response.
1019 *        Input:  pQmi:the package message get from qmi server.
1020 *       Output:  fClientID : client ID getted from the package.
1021 *                fQMIType  : fQMIType getted from the package.
1022 *       Return:  -1 : call faled.
1023 *                >0  : call success,the package length used.
1024 *        Notes:
1025 ********************************************************************/
1026int QCTL_Procecess_ReleaseClient_ID_Response(QCQMI* pQmi,UInt8* fClientID,UInt8* fQMIType)
1027{
1028	QMICTL_RELEASE_CLIENT_ID_RESP_MSG* pMsg = (QMICTL_RELEASE_CLIENT_ID_RESP_MSG*)&(pQmi->SDU);
1029
1030	lc_kdbg("%s : entry\n",__func__);
1031
1032	if (pMsg->QMIResult == QMI_RESULT_SUCCESS)
1033	{
1034	    lc_kdbg( "%s: release client id.ClientId=%u,QMIType=%u.\n", __func__,pMsg->ClientId, pMsg->QMIType);
1035
1036		if (*fClientID == pMsg->ClientId && *fQMIType == pMsg->QMIType)
1037		{
1038		    *fClientID = 0;
1039			*fQMIType  = 0;
1040		}
1041	}
1042	else
1043	{
1044		lc_kdbg( "%s: failed to release client id,QMIError=%u,QMIResult=%u.\n",__func__,pMsg->QMIError, pMsg->QMIResult);
1045		return -1;
1046	}
1047
1048/*	if (fReleaseingID)
1049	{
1050	    fReleaseingID = false;
1051		fCommandGate->commandWakeup(NULL, false);
1052		XTRACE(this, 0, 0, "QCTL_Procecess_ReleaseClient_ID_Response: now wake up command gate");
1053	}*/
1054	lc_kdbg("%s : leave\n",__func__);
1055
1056	return 0;
1057}
1058/********************************************************************
1059 *
1060 *         Name:  QCTL_Procecess_GetVersion_Respons
1061 *  Description:  QCTL Procecess GetVersion Respons.
1062 *        Input:  pQmi:the package message get from qmi server.
1063 *       Output:  pndis_status : qmi global status parameters.
1064 *       Return:  -1 : call faled.
1065 *                0  : call success
1066 *        Notes:
1067 ********************************************************************/
1068int QCTL_Procecess_GetVersion_Respons(QCQMI* pQmi,NDIS_QMI_STATUS* pndis_status)
1069{
1070	QMICTL_GET_VERSION_RESP_MSG* pMsg = (QMICTL_GET_VERSION_RESP_MSG*) &(pQmi->SDU);
1071	QMUX_TYPE_VERSION_STRUCT* pVersion = NULL;
1072	UInt32 msgLen;
1073	UInt8 *pMsgStart;
1074	int i;
1075	msgLen = pMsg->Length;
1076	pMsgStart = (UInt8 *) &(pMsg->TLVType);
1077
1078
1079	lc_kdbg("%s : entry\n",__func__);
1080
1081	if (pMsg->QMIResult != QMI_RESULT_SUCCESS)
1082	{
1083		lc_kdbg( "%s: failed to get version.QMIError=%u,QMIResult=%u.\n",__func__,pMsg->QMIError, pMsg->QMIResult);
1084		return -1;
1085	}
1086	else
1087	{
1088		// judge message length
1089		msgLen -= sizeof(QMI_TLV_HDR);
1090		pMsgStart += sizeof(QMI_TLV_HDR);
1091		msgLen -= pMsg->TLVLength;
1092		pMsgStart += pMsg->TLVLength;
1093		msgLen -= sizeof(QMI_TLV_HDR);
1094		pMsgStart += sizeof(QMI_TLV_HDR);
1095		msgLen -= pMsg->TLV2Length;
1096		pMsgStart += pMsg->TLV2Length;
1097
1098		pVersion = (QMUX_TYPE_VERSION_STRUCT*) &(pMsg->TypeVersion);
1099
1100		for ( i = 0; i < pMsg->NumElements; ++i)
1101		{
1102			if (pVersion->QMUXType == QMUX_TYPE_CTL)
1103			{
1104			    lc_kdbg( "%s: get qmi control version,MajorVersion=%u,MinorVersion=%u.\n",
1105						__func__,pVersion->MajorVersion,pVersion->MinorVersion);
1106
1107				if (pVersion->MajorVersion >= 1 && pVersion->MinorVersion >= 3)
1108				{
1109				    pndis_status->fIPPacketSupport = true;
1110					lc_kdbg("%s: IP Supported,MajorVersion=%u,MinorVersion=%u.\n",
1111							__func__,pVersion->MajorVersion, pVersion->MinorVersion);
1112					sprintf(pndis_status->fVersion,"%u.%u",pVersion->MajorVersion, pVersion->MinorVersion);
1113				}
1114			}
1115
1116			++pVersion;
1117		}
1118
1119		// extra length
1120		while (msgLen >= sizeof(QMI_TLV_HDR))
1121		{
1122			QMI_TLV_HDR* pHdr = (QMI_TLV_HDR*) pMsgStart;
1123			UInt8 *pCurMsg = NULL;
1124			UInt8 numInstances;
1125
1126			lc_kdbg("%s: extra tlv process.",__func__);
1127			msgLen -= sizeof(QMI_TLV_HDR);
1128			pMsgStart += sizeof(QMI_TLV_HDR);
1129			pCurMsg = pMsgStart;
1130			msgLen -= pHdr->TLVLength;
1131			pMsgStart += pHdr->TLVLength;
1132
1133			if (msgLen < 0)
1134			{
1135			    break;
1136			}
1137
1138			switch (pHdr->TLVType)
1139		    {
1140		        case QMICTL_GETVERSION_RSP_TLV_TYPE_ADD_VERSION:
1141				{
1142					// length
1143					pCurMsg += *pCurMsg;
1144					pCurMsg += 1;
1145
1146					numInstances = *pCurMsg;
1147					pCurMsg += 1;
1148
1149					pVersion = (QMUX_TYPE_VERSION_STRUCT*) &(pCurMsg);
1150
1151					for ( i = 0; i < numInstances; ++i)
1152					{
1153						if (pVersion->QMUXType == QMUX_TYPE_CTL)
1154						{
1155							lc_kdbg( "%s: get qmi control version,MajorVersion=%u,MinorVersion=%u.\n",
1156									__func__,pVersion->MajorVersion, pVersion->MinorVersion);
1157
1158							if (pVersion->MajorVersion >= 1 && pVersion->MinorVersion >= 3)
1159							{
1160								pndis_status->fIPPacketSupport = true;
1161								lc_kdbg( "%s: IP Supported,MajorVersion=%u,MinorVersion=%u.\n",
1162										__func__, pVersion->MajorVersion, pVersion->MinorVersion);
1163								sprintf(pndis_status->fVersion,"%u.%u",pVersion->MajorVersion, pVersion->MinorVersion);
1164							}
1165						}
1166
1167						++pVersion;
1168					}
1169				    break;
1170				}
1171				default:
1172				{
1173				    break;
1174				}
1175			}
1176
1177		}
1178	}
1179
1180/*	if (fGetVersioning)
1181	{
1182		fGetVersioning = false;
1183		fCommandGate->commandWakeup(NULL, false);
1184		XTRACE(this, 0, 0, "QCTL_Procecess_GetVersion_Respons: now wake up command gate");
1185	}*/
1186	lc_kdbg("%s : leave\n",__func__);
1187
1188    return 0;
1189}
1190/********************************************************************
1191 *
1192 *         Name:  QCQMI_ProcessQMUXWDSResponse
1193 *  Description:  QCQMI Process QMUX WDS Response
1194 *        Input:  pQmi:the data getted from qmi server
1195 *        Output: pndis_status: ndis global status parameters.
1196 *       Return:  -1 : call faled.
1197 *                0  : call success
1198 *        Notes:
1199 ********************************************************************/
1200int QCQMI_ProcessQMUXWDSResponse(QCQMI* pQmi,NDIS_QMI_STATUS* pndis_status)
1201{
1202	QCQMUX* pQmux = NULL;
1203	QCQMUX_MSG_HDR* pQmuxMsg = NULL;
1204	UInt16 totalLength = 0;
1205	bool bCompound = false;
1206	bool bDone     = false;
1207	int ret = -1;
1208
1209	lc_kdbg("%s : entry\n",__func__);
1210
1211	pQmux = (QCQMUX*)&(pQmi->SDU);
1212	pQmuxMsg = (QCQMUX_MSG_HDR*)&(pQmux->Message);
1213
1214	// message length
1215	totalLength = pQmi->Length;
1216
1217	totalLength -= sizeof(QCQMI_HDR);
1218	totalLength += sizeof(pQmi->IFType);
1219
1220	totalLength -=sizeof(QCQMUX);
1221	totalLength += sizeof(pQmux->Message);
1222
1223	if (pQmux->CtlFlags & QMUX_CTL_FLAG_MASK_COMPOUND)
1224	{
1225	    bCompound = true;
1226		lc_kdbg("%s:compounded message.\n",__func__);
1227	}
1228
1229	while (bDone == false)
1230	{
1231	    switch (pQmuxMsg->Type)
1232		{
1233		    case QMIWDS_START_NETWORK_INTERFACE_RESP:
1234			{
1235				QMIWDS_START_NETWORK_INTERFACE_RESP_MSG* pStartMsg = (QMIWDS_START_NETWORK_INTERFACE_RESP_MSG*)pQmuxMsg;
1236
1237				lc_kdbg("QCQMI_ProcessQMUXWDSResponse:QMIWDS_START_NETWORK_INTERFACE_RESP.\n");
1238				ret = QMI_CONNECT;
1239				if (pStartMsg->QMUXResult != QMI_RESULT_SUCCESS)
1240				{
1241					// to do
1242				    lc_kdbg("QCQMI_ProcessQMUXWDSResponse:Connection Failed,QMUXError=%u.\n",pStartMsg->QMUXError);
1243					pndis_status->fPacketHandle    = 0;
1244					//if((pndis_status->fConnectionError == -1) && (pndis_status->fConnectionError != 0))
1245					if(pndis_status->fConnecting)
1246					{
1247						pndis_status->fConnectionError = pStartMsg->QMUXError;
1248						lc_kdbg("kaibo : QCQMI_ProcessQMUXWDSResponse:No connect has ok.\n");
1249					}
1250					else
1251					{
1252						lc_kdbg("kaibo : QCQMI_ProcessQMUXWDSResponse:One connect has ok.Iogren it\n");
1253											}
1254					// release commandgate
1255					if (pndis_status->fConnecting)
1256					{
1257						pndis_status->fConnecting = false;
1258					//	fCommandGate->commandWakeup(NULL, false);
1259						lc_kdbg("QCQMI_ProcessQMUXWDSResponse:QMIWDS_START_NETWORK_INTERFACE_RESP command wake up.\n");
1260					}
1261				}
1262				else
1263				{
1264					if(pndis_status->fPacketHandle)
1265						pndis_status->fPacketHandle = le32_to_cpu(pStartMsg->Pkt_Data_Handle);
1266					if(!pndis_status->fPacketHandle)
1267						pndis_status->fPacketHandle1 = le32_to_cpu(pStartMsg->Pkt_Data_Handle);
1268					pndis_status->fConnectionError = 0;
1269					lc_kdbg("QCQMI_ProcessQMUXWDSResponse:Connection Succeeded,Pkt_Data_Handle=%u!\n", pStartMsg->Pkt_Data_Handle);
1270
1271					// release commandgate
1272					if (pndis_status->fConnecting && !pndis_status->fIPModeEnabled)
1273					{
1274						pndis_status->fConnecting = false;
1275					//	fCommandGate->commandWakeup(NULL, false);
1276						lc_kdbg("QCQMI_ProcessQMUXWDSResponse:QMIWDS_START_NETWORK_INTERFACE_RESP command wake up.\n");
1277					}
1278				}
1279			    break;
1280			}
1281			case QMIWDS_STOP_NETWORK_INTERFACE_RESP:
1282			{
1283				QMIWDS_RESP_MSG_HEADER* pMsgHeader = (QMIWDS_RESP_MSG_HEADER*) pQmuxMsg;
1284
1285				lc_kdbg("QCQMI_ProcessQMUXWDSResponse:QMIWDS_STOP_NETWORK_INTERFACE_RESP");
1286				ret = QMI_DISCONNECT;
1287				if (pMsgHeader->QMUXResult != QMI_RESULT_SUCCESS)
1288				{
1289					pndis_status->fConnectionError = pMsgHeader->QMUXError;
1290					lc_kdbg("QCQMI_ProcessQMUXWDSResponse:Disconnection Failed,QMUXError=%u.\n",pMsgHeader->QMUXError);
1291				}
1292				else
1293				{
1294				    pndis_status->fPacketHandle    = 0;
1295					pndis_status->fConnectionError = 0;
1296				}
1297
1298				if (pndis_status->fDisconnecting)
1299				{
1300					pndis_status->fDisconnecting = false;
1301					//fCommandGate->commandWakeup(NULL, false);
1302					lc_kdbg("QCQMI_ProcessQMUXWDSResponse:QMIWDS_STOP_NETWORK_INTERFACE_RESP command wake up.\n");
1303				}
1304
1305				break;
1306			}
1307
1308			case QMIWDS_GET_RUNTIME_SETTINGS_RESP:
1309			{
1310				lc_kdbg("QCQMI_ProcessQMUXWDSResponse:QMIWDS_GET_RUNTIME_SETTINGS_RESP.\n");
1311			    QC_WDS_Process_GetRunTimeSettings_Respons(pQmuxMsg,pndis_status);
1312			    ret = QMI_GET_IP_ADDR;
1313				break;
1314			}
1315
1316
1317			case QMI_WDS_MODIFY_PROFILE_SETTINGS_RESP:
1318			{
1319				lc_kdbg("QCQMI_ProcessQMUXWDSResponse:QMI_WDS_MODIFY_PROFILE_SETTINGS_RESP.\n");
1320			    ret = QMI_MODIFY_PRO;
1321				break;
1322			}
1323		    default:
1324			{
1325			    break;
1326			}
1327		}
1328
1329		// no need to process again
1330		if (!bCompound)
1331		{
1332		    break;
1333		}
1334
1335		totalLength -= sizeof(QCQMUX_MSG_HDR);
1336		totalLength -= pQmuxMsg->Length;
1337
1338		if (totalLength > sizeof(PQCQMUX_MSG_HDR))//PQCQMUX_MSG_HDR
1339		{
1340		    bDone = false;
1341		}
1342		else
1343		{
1344		    bDone = true;
1345		}
1346
1347		// move pointer
1348		pQmuxMsg = (PQCQMUX_MSG_HDR)((UInt8 *)pQmuxMsg + sizeof(QCQMUX_MSG_HDR) + pQmuxMsg->Length);
1349	}
1350	lc_kdbg("%s : leave\n",__func__);
1351
1352	return ret;
1353}
1354/********************************************************************
1355 *
1356 *         Name:  QC_WDS_Process_GetRunTimeSettings_Respons
1357 *  Description:  QC WDS Process Get RunTime Settings Respons
1358 *        Input:  pQMuxMsg:the data getted from qmi server
1359 *        Output: pndis_status: ndis global status parameters.
1360 *       Return:  -1 : call faled.
1361 *                0  : call success
1362 *        Notes:
1363 ********************************************************************/
1364int  QC_WDS_Process_GetRunTimeSettings_Respons(QCQMUX_MSG_HDR* pQMuxMsg,NDIS_QMI_STATUS* pndis_status)
1365{
1366    QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG* pGetMsg = (QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG*)pQMuxMsg;
1367	int ret = 0;
1368
1369	lc_kdbg("%s : entry\n",__func__);
1370
1371	if (pGetMsg->QMUXResult != QMI_RESULT_SUCCESS)
1372	{
1373	    pndis_status->fIPAddress = 0;
1374	    pndis_status->fConnectionError = pGetMsg->QMUXError;
1375		lc_kdbg("%s: failed to get ip address,QMUXError=%u,QMUXResult=%u.\n",__func__,
1376				pGetMsg->QMUXError, pGetMsg->QMUXResult);
1377		ret = -1;
1378	}
1379	else
1380	{
1381		UInt32 remainingBytes = 0;
1382	    UInt8 *pMsgStart = (UInt8 *)&(pGetMsg->TLVType);
1383		UInt8 *pMsgPtr   = (UInt8 *)&(pGetMsg->QMUXError);
1384		pMsgPtr += sizeof(UInt16);
1385
1386		remainingBytes = pQMuxMsg->Length - (pMsgStart - pMsgPtr);
1387
1388		if (remainingBytes >= sizeof(QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR))
1389		{
1390			QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR* pAddr = (QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR*)pMsgPtr;
1391
1392			if (pAddr->TLVType == QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4)
1393			{
1394				pndis_status->fIPAddress = ntohl(pAddr->IPV4Address);
1395
1396				// linkup net card
1397				if (pndis_status->fIPPacketSupport && pndis_status->fIPModeEnabled && pndis_status->fPacketHandle != 0)
1398				{
1399				//	IONetworkMedium	*medium;
1400				//	IOMediumType mediumType = kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex;
1401				//	medium = IONetworkMedium::getMediumWithType(pndis_status->fMediumDict, mediumType);
1402				//	setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 10 * 1000000);
1403					pndis_status->fLinkStatus = 1;
1404				}
1405
1406				lc_kdbg("%s: successfully get ip address:IPV4Address=%u,fIPAddress=%u.\n",__func__,
1407				      pAddr->IPV4Address, pndis_status->fIPAddress);
1408				ret = 0;
1409			}
1410			else
1411			{
1412			    lc_kdbg("QC_WDS_Process_GetRunTimeSettings_Respons: invalid tlv type=%u.\n",pAddr->TLVType);
1413			    ret = -1;
1414			}
1415		}
1416	}
1417#if 0
1418	if (fGetIpAddressing)
1419	{
1420	    fGetIpAddressing = false;
1421		fCommandGate->commandWakeup(NULL, false);
1422		XTRACE(this, 0, 0, "QC_WDS_Process_GetRunTimeSettings_Respons: now wake up command gate");
1423	}
1424#endif
1425	lc_kdbg("%s : leave\n",__func__);
1426
1427	return ret;
1428}
1429/********************************************************************
1430 *
1431 *         Name:  processQMIResponse
1432 *  Description:  process QMI Respons
1433 *        Input:  buffer:the data getted from qmi server
1434 *        Output: pndis_status: ndis global status parameters.
1435 *       Return:  -1 : call faled.
1436 *                QMI_GET_CLIENT_ID--QMI_GET_VERSION  : call success
1437 *        Notes:
1438 ********************************************************************/
1439int processQMIResponse(void *buffer,NDIS_QMI_STATUS* pndis_status)
1440{
1441    QCQMI* qmi = (QCQMI*)buffer;
1442    int    ret = -1;
1443
1444	lc_kdbg("%s : entry.\n",__func__);
1445	lc_kdbg("qmi buffer is %02x, %04x, %02x, %02x, %02x\n", qmi->IFType, qmi->Length, qmi->CtlFlags, qmi->QMIType, qmi->ClientId);
1446
1447	if (qmi->CtlFlags != QCQMI_CTL_FLAG_SERVICE)
1448	{
1449	    lc_kdbg("%s:Unexpected QMI control flags,IFType=%u,CtlFlags=%u.\n",__func__,qmi->IFType, qmi->CtlFlags);
1450		return -1;
1451	}
1452
1453	if (QMUX_TYPE_CTL == qmi->QMIType)
1454	{
1455	    // handle set_Instance_id and getclientid and release client id
1456		QCQMICTL_MSG_HDR* pCtlMsgHdr = (QCQMICTL_MSG_HDR*)&(qmi->SDU);
1457		UInt8 controlFlag;
1458
1459		controlFlag = pCtlMsgHdr->CtlFlag & 0x03;
1460
1461		switch (controlFlag)
1462	    {
1463			// response
1464			case QMICTL_CTL_FLAG_RSP:
1465			{
1466				switch (pCtlMsgHdr->QMICTLType)
1467				{
1468					case QMICTL_SET_INSTANCE_ID_RESP:
1469					{
1470						lc_kdbg("processQMIResponse:QMICTL_SET_INSTANCE_ID_RESP.\n");
1471						QCTL_Procecess_SetInstanceId_Response(qmi,&(pndis_status->fSetInstanceIdFail),&(pndis_status->fQMI_ID));
1472						ret = QMI_SET_INSTANCE;
1473						break;
1474					}
1475
1476					case QMICTL_GET_CLIENT_ID_RESP:
1477					{
1478						lc_kdbg("processQMIResponse:QMICTL_GET_CLIENT_ID_RESP.\n");
1479						QCTL_Procecess_GetClient_ID_Response(qmi,&(pndis_status->fClientID),&(pndis_status->fQMIType));
1480						ret = QMI_GET_CLIENT_ID;
1481						break;
1482					}
1483
1484					case QMICTL_RELEASE_CLIENT_ID_RESP:
1485					{
1486						lc_kdbg("processQMIResponse:QMICTL_RELEASE_CLIENT_ID_RESP.\n");
1487						QCTL_Procecess_ReleaseClient_ID_Response(qmi,&(pndis_status->fClientID),&(pndis_status->fQMIType));
1488						ret = QMI_RELEASE_CLIENT_ID;
1489						break;
1490					}
1491					case QMICTL_GET_VERSION_RESP:
1492					{
1493						lc_kdbg("processQMIResponse:QMICTL_GET_VERSION_RESP.\n");
1494						QCTL_Procecess_GetVersion_Respons(qmi,pndis_status);
1495						ret = QMI_GET_VERSION;
1496					    break;
1497					}
1498					case QMICTL_SET_DATA_FORMAT_RESP:
1499					{
1500					    lc_kdbg("processQMIResponse:QMICTL_SET_DATA_FORMAT_RESP.\n");
1501						QCTL_Procecess_SetDataFormat_Response(qmi,pndis_status);
1502						ret = QMI_SET_DATA_FORMAT;
1503						break;
1504					}
1505					default:
1506					{
1507						lc_kdbg("processQMIResponse:unkown control message,QMICTLType=%u.\n",pCtlMsgHdr->QMICTLType);
1508						return -1;
1509					}
1510				}
1511
1512				break;
1513			}
1514
1515			// Indication
1516			case QMICTL_CTL_FLAG_IND:
1517			{
1518			    switch (pCtlMsgHdr->QMICTLType)
1519				{
1520				    case QMICTL_REVOKE_CLIENT_IDIND:
1521					{
1522						lc_kdbg("processQMIResponse:QMICTL_REVOKE_CLIENT_IDIND.\n");
1523						// should reacquire id
1524						pndis_status->fClientID = 0;
1525						pndis_status->fQMIType  = 0;
1526					    break;
1527					}
1528					case QMICTL_INVALID_CLIENT_ID_IND:
1529					{
1530					    lc_kdbg("processQMIResponse:QMICTL_INVALID_CLIENT_ID_IND.\n");
1531					    break;
1532					}
1533					default:
1534					{
1535					    lc_kdbg("%s:unkown QMICTLType=%u.\n",__func__,pCtlMsgHdr->QMICTLType);
1536						return -1;
1537					}
1538				}
1539			}
1540
1541			default:
1542			{
1543				lc_kdbg("%s:unkown controlFlag=%u.\n",__func__,controlFlag);
1544			    return -1;
1545			}
1546		}
1547	}
1548	else
1549	{
1550	    UInt8 controlFlag = 0;
1551		QCQMUX* pQmux = NULL;
1552		QCQMUX_MSG_HDR* pQmuxMsg = NULL;
1553
1554		pQmux = (QCQMUX*)&(qmi->SDU);
1555		pQmuxMsg = (QCQMUX_MSG_HDR*)&(pQmux->Message);
1556
1557		controlFlag = pQmux->CtlFlags & QMUX_CTL_FLAG_MASK_TYPE;
1558
1559		switch (controlFlag)
1560	    {
1561		    case QMUX_CTL_FLAG_TYPE_RSP:
1562			{
1563			    switch (qmi->QMIType)
1564			    {
1565				    case QMUX_TYPE_WDS:
1566					{
1567						lc_kdbg("processQMIResponse:QMUX_CTL_FLAG_TYPE_RSP-QMUX_TYPE_WDS.\n");
1568						ret = QCQMI_ProcessQMUXWDSResponse(qmi, pndis_status);
1569					    break;
1570					}
1571					case QMUX_TYPE_DMS:
1572					{
1573						lc_kdbg("processQMIResponse:QMUX_CTL_FLAG_TYPE_RSP-QMUX_TYPE_DMS.\n");
1574					    break;
1575					}
1576					default:
1577					{
1578						lc_kdbg("processQMIResponse:QMUX_CTL_FLAG_TYPE_RSP-QMUXUnknown,QMIType=%u.\n", qmi->QMIType);
1579					    break;
1580					}
1581				}
1582
1583				break;
1584			}
1585			case QMUX_CTL_FLAG_TYPE_IND:
1586			{
1587				switch (qmi->QMIType)
1588			    {
1589			        case QMUX_TYPE_WDS:
1590					{
1591						lc_kdbg("processQMIResponse:QMUX_CTL_FLAG_TYPE_IND-QMUX_TYPE_WDS.\n");
1592						ret = QCQMI_ProcessQMUXWDSIndication(qmi, pndis_status);
1593					    break;
1594					}
1595				    default:
1596					{
1597						lc_kdbg("processQMIResponse:QMUX_CTL_FLAG_TYPE_IND-QMUXUnknown,QMIType=%u.\n", qmi->QMIType);
1598					    break;
1599					}
1600			    }
1601
1602			    break;
1603			}
1604		    default:
1605			{
1606			    lc_kdbg("%s:unkown controlFlag=%u.\n",__func__,controlFlag);
1607			    return -1;
1608			}
1609		}
1610	}
1611
1612	lc_kdbg("%s : leave\n",__func__);
1613
1614	return ret;
1615}
1616/********************************************************************
1617 *
1618 *         Name:  QCQMI_ProcessQMUXWDSIndication
1619 *  Description:  QCQMI Process QMUX WDS Indication
1620 *        Input:  pQmi:the data getted from qmi server
1621 *        Output: pndis_status: ndis global status parameters.
1622 *       Return:  -1 : call faled.
1623 *                0  : call success
1624 *        Notes:
1625 ********************************************************************/
1626int QCQMI_ProcessQMUXWDSIndication(QCQMI* pQmi,NDIS_QMI_STATUS* pndis_status)
1627{
1628	QCQMUX* pQmux = NULL;
1629	QCQMUX_MSG_HDR* pQmuxMsg = NULL;
1630	UInt16 totalLength = 0;
1631	bool bCompound = false;
1632	bool bDone     = false;
1633
1634	lc_kdbg("%s : entry.\n",__func__);
1635
1636	pQmux = (QCQMUX*)&(pQmi->SDU);
1637	pQmuxMsg = (QCQMUX_MSG_HDR*)&(pQmux->Message);
1638
1639	// message length
1640	totalLength = pQmi->Length;
1641
1642	totalLength -= sizeof(QCQMI_HDR);
1643	totalLength += sizeof(pQmi->IFType);
1644
1645	totalLength -=sizeof(QCQMUX);
1646	totalLength += sizeof(pQmux->Message);
1647
1648
1649
1650	if (pQmux->CtlFlags & QMUX_CTL_FLAG_MASK_COMPOUND)
1651	{
1652	    bCompound = true;
1653	}
1654
1655	while (bDone == false)
1656	{
1657	    switch (pQmuxMsg->Type)
1658		{
1659		    case QMIWDS_GET_PKT_SRVC_STATUS_IND:
1660			{
1661				QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG* pPktInd = (QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG*)pQmuxMsg;
1662
1663		        lc_kdbg("QCQMI_ProcessQMUXWDSIndication:QMIWDS_GET_PKT_SRVC_STATUS_IND.\n");
1664
1665				if (pPktInd->ConnectionStatus == QWDS_PKT_DATA_CONNECTED)
1666				{
1667				    if (pPktInd->ReconfigRequired == 0)
1668					{
1669						if (!pndis_status->fIPModeEnabled)
1670						{
1671/* 						    IONetworkMedium	*medium;
1672						    IOMediumType mediumType = kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex;
1673						    medium = IONetworkMedium::getMediumWithType(fMediumDict, mediumType);
1674						    setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 10 * 1000000); */
1675							pndis_status->fLinkStatus = 1;
1676						}
1677						lc_kdbg("QCQMI_ProcessQMUXWDSIndication:QMIWDS_GET_PKT_SRVC_STATUS_IND connected.\n");
1678					}
1679					else
1680					{
1681					    // make disconnection
1682						//setLinkStatus(kIONetworkLinkValid, 0);
1683						//ResetPacketCount();
1684						pndis_status->fLinkStatus = 0;
1685						pndis_status->fPacketHandle    = 0;
1686						pndis_status->fIPAddress = 0;
1687						lc_kdbg("QCQMI_ProcessQMUXWDSIndication:QMIWDS_GET_PKT_SRVC_STATUS_IND disconnected.\n");
1688					}
1689
1690				}
1691				else
1692				{
1693				    // make disconnection
1694					//setLinkStatus(kIONetworkLinkValid, 0);
1695					pndis_status->fLinkStatus = 0;
1696					pndis_status->fPacketHandle    = 0;
1697					pndis_status->fIPAddress = 0;
1698					lc_kdbg("QCQMI_ProcessQMUXWDSIndication:QMIWDS_GET_PKT_SRVC_STATUS_IND disconnected.\n");
1699					//ResetPacketCount();
1700					pndis_status->fLinkStatus = 0;
1701
1702				}
1703
1704				// release commandgate when ip enabled
1705				if (pndis_status->fConnecting)
1706				{
1707					pndis_status->fConnecting = false;
1708				//	pndis_status->fCommandGate->commandWakeup(NULL, false);
1709					lc_kdbg("QCQMI_ProcessQMUXWDSIndication:QMIWDS_GET_PKT_SRVC_STATUS_IND command wake up.\n");
1710				}
1711
1712			    break;
1713			}
1714		    default:
1715			{
1716				break;
1717			}
1718		}
1719
1720		// no need to process again
1721		if (!bCompound)
1722		{
1723		    break;
1724		}
1725
1726		totalLength -= sizeof(QCQMUX_MSG_HDR);
1727		totalLength -= pQmuxMsg->Length;
1728
1729		if (totalLength > sizeof(PQCQMUX_MSG_HDR))//PQCQMUX_MSG_HDR
1730		{
1731		    bDone = false;
1732		}
1733		else
1734		{
1735		    bDone = true;
1736		}
1737
1738		// move pointer
1739		pQmuxMsg = (PQCQMUX_MSG_HDR)((UInt8 *)pQmuxMsg + sizeof(QCQMUX_MSG_HDR) + pQmuxMsg->Length);
1740	}
1741
1742	lc_kdbg("%s : leave\n",__func__);
1743
1744	return 0;
1745}
1746