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