wcmd.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  1. /*
  2. * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * File: wcmd.c
  20. *
  21. * Purpose: Handles the management command interface functions
  22. *
  23. * Author: Lyndon Chen
  24. *
  25. * Date: May 8, 2003
  26. *
  27. * Functions:
  28. * s_vProbeChannel - Active scan channel
  29. * s_MgrMakeProbeRequest - Make ProbeRequest packet
  30. * CommandTimer - Timer function to handle command
  31. * s_bCommandComplete - Command Complete function
  32. * bScheduleCommand - Push Command and wait Command Scheduler to do
  33. * vCommandTimer- Command call back functions
  34. * vCommandTimerWait- Call back timer
  35. * bClearBSSID_SCAN- Clear BSSID_SCAN cmd in CMD Queue
  36. *
  37. * Revision History:
  38. *
  39. */
  40. #include "ttype.h"
  41. #include "tmacro.h"
  42. #include "device.h"
  43. #include "mac.h"
  44. #include "card.h"
  45. #include "80211hdr.h"
  46. #include "wcmd.h"
  47. #include "wmgr.h"
  48. #include "power.h"
  49. #include "wctl.h"
  50. #include "baseband.h"
  51. #include "rxtx.h"
  52. #include "rf.h"
  53. #include "iowpa.h"
  54. #include "channel.h"
  55. /*--------------------- Static Definitions -------------------------*/
  56. /*--------------------- Static Classes ----------------------------*/
  57. /*--------------------- Static Functions --------------------------*/
  58. static
  59. void
  60. s_vProbeChannel(
  61. struct vnt_private *pDevice
  62. );
  63. static
  64. PSTxMgmtPacket
  65. s_MgrMakeProbeRequest(
  66. struct vnt_private *pDevice,
  67. PSMgmtObject pMgmt,
  68. unsigned char *pScanBSSID,
  69. PWLAN_IE_SSID pSSID,
  70. PWLAN_IE_SUPP_RATES pCurrRates,
  71. PWLAN_IE_SUPP_RATES pCurrExtSuppRates
  72. );
  73. static
  74. bool
  75. s_bCommandComplete(
  76. struct vnt_private *pDevice
  77. );
  78. /*--------------------- Export Variables --------------------------*/
  79. /*--------------------- Export Functions --------------------------*/
  80. /*
  81. * Description:
  82. * Stop AdHoc beacon during scan process
  83. *
  84. * Parameters:
  85. * In:
  86. * pDevice - Pointer to the adapter
  87. * Out:
  88. * none
  89. *
  90. * Return Value: none
  91. *
  92. */
  93. static
  94. void
  95. vAdHocBeaconStop(struct vnt_private *pDevice)
  96. {
  97. PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
  98. bool bStop;
  99. /*
  100. * temporarily stop Beacon packet for AdHoc Server
  101. * if all of the following conditions are met:
  102. * (1) STA is in AdHoc mode
  103. * (2) VT3253 is programmed as automatic Beacon Transmitting
  104. * (3) One of the following conditions is met
  105. * (3.1) AdHoc channel is in B/G band and the
  106. * current scan channel is in A band
  107. * or
  108. * (3.2) AdHoc channel is in A mode
  109. */
  110. bStop = false;
  111. if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
  112. (pMgmt->eCurrState >= WMAC_STATE_STARTED)) {
  113. if ((pMgmt->uIBSSChannel <= CB_MAX_CHANNEL_24G) &&
  114. (pMgmt->uScanChannel > CB_MAX_CHANNEL_24G)) {
  115. bStop = true;
  116. }
  117. if (pMgmt->uIBSSChannel > CB_MAX_CHANNEL_24G)
  118. bStop = true;
  119. }
  120. if (bStop)
  121. MACvRegBitsOff(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
  122. } /* vAdHocBeaconStop */
  123. /*
  124. * Description:
  125. * Restart AdHoc beacon after scan process complete
  126. *
  127. * Parameters:
  128. * In:
  129. * pDevice - Pointer to the adapter
  130. * Out:
  131. * none
  132. *
  133. * Return Value: none
  134. *
  135. */
  136. static
  137. void
  138. vAdHocBeaconRestart(struct vnt_private *pDevice)
  139. {
  140. PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
  141. /*
  142. * Restart Beacon packet for AdHoc Server
  143. * if all of the following coditions are met:
  144. * (1) STA is in AdHoc mode
  145. * (2) VT3253 is programmed as automatic Beacon Transmitting
  146. */
  147. if ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) &&
  148. (pMgmt->eCurrState >= WMAC_STATE_STARTED)) {
  149. MACvRegBitsOn(pDevice->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX);
  150. }
  151. }
  152. /*+
  153. *
  154. * Routine Description:
  155. * Prepare and send probe request management frames.
  156. *
  157. *
  158. * Return Value:
  159. * none.
  160. *
  161. -*/
  162. static
  163. void
  164. s_vProbeChannel(
  165. struct vnt_private *pDevice
  166. )
  167. {
  168. //1M, 2M, 5M, 11M, 18M, 24M, 36M, 54M
  169. unsigned char abyCurrSuppRatesG[] = {WLAN_EID_SUPP_RATES, 8, 0x02, 0x04, 0x0B, 0x16, 0x24, 0x30, 0x48, 0x6C};
  170. unsigned char abyCurrExtSuppRatesG[] = {WLAN_EID_EXTSUPP_RATES, 4, 0x0C, 0x12, 0x18, 0x60};
  171. //6M, 9M, 12M, 48M
  172. unsigned char abyCurrSuppRatesA[] = {WLAN_EID_SUPP_RATES, 8, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C};
  173. unsigned char abyCurrSuppRatesB[] = {WLAN_EID_SUPP_RATES, 4, 0x02, 0x04, 0x0B, 0x16};
  174. unsigned char *pbyRate;
  175. PSTxMgmtPacket pTxPacket;
  176. PSMgmtObject pMgmt = pDevice->pMgmt;
  177. unsigned int ii;
  178. if (pDevice->eCurrentPHYType == PHY_TYPE_11A)
  179. pbyRate = &abyCurrSuppRatesA[0];
  180. else if (pDevice->eCurrentPHYType == PHY_TYPE_11B)
  181. pbyRate = &abyCurrSuppRatesB[0];
  182. else
  183. pbyRate = &abyCurrSuppRatesG[0];
  184. // build an assocreq frame and send it
  185. pTxPacket = s_MgrMakeProbeRequest
  186. (
  187. pDevice,
  188. pMgmt,
  189. pMgmt->abyScanBSSID,
  190. (PWLAN_IE_SSID)pMgmt->abyScanSSID,
  191. (PWLAN_IE_SUPP_RATES)pbyRate,
  192. (PWLAN_IE_SUPP_RATES)abyCurrExtSuppRatesG
  193. );
  194. if (pTxPacket != NULL) {
  195. for (ii = 0; ii < 2; ii++) {
  196. if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING)
  197. pr_debug("Probe request sending fail..\n");
  198. else
  199. pr_debug("Probe request is sending..\n");
  200. }
  201. }
  202. }
  203. /*+
  204. *
  205. * Routine Description:
  206. * Constructs an probe request frame
  207. *
  208. *
  209. * Return Value:
  210. * A ptr to Tx frame or NULL on allocation failure
  211. *
  212. -*/
  213. static PSTxMgmtPacket
  214. s_MgrMakeProbeRequest(
  215. struct vnt_private *pDevice,
  216. PSMgmtObject pMgmt,
  217. unsigned char *pScanBSSID,
  218. PWLAN_IE_SSID pSSID,
  219. PWLAN_IE_SUPP_RATES pCurrRates,
  220. PWLAN_IE_SUPP_RATES pCurrExtSuppRates
  221. )
  222. {
  223. PSTxMgmtPacket pTxPacket = NULL;
  224. WLAN_FR_PROBEREQ sFrame;
  225. pTxPacket = (PSTxMgmtPacket)pMgmt->pbyMgmtPacketPool;
  226. memset(pTxPacket, 0, sizeof(STxMgmtPacket) + WLAN_PROBEREQ_FR_MAXLEN);
  227. pTxPacket->p80211Header = (PUWLAN_80211HDR)((unsigned char *)pTxPacket + sizeof(STxMgmtPacket));
  228. sFrame.pBuf = (unsigned char *)pTxPacket->p80211Header;
  229. sFrame.len = WLAN_PROBEREQ_FR_MAXLEN;
  230. vMgrEncodeProbeRequest(&sFrame);
  231. sFrame.pHdr->sA3.wFrameCtl = cpu_to_le16(
  232. (
  233. WLAN_SET_FC_FTYPE(WLAN_TYPE_MGR) |
  234. WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_PROBEREQ)
  235. ));
  236. memcpy(sFrame.pHdr->sA3.abyAddr1, pScanBSSID, WLAN_ADDR_LEN);
  237. memcpy(sFrame.pHdr->sA3.abyAddr2, pMgmt->abyMACAddr, WLAN_ADDR_LEN);
  238. memcpy(sFrame.pHdr->sA3.abyAddr3, pScanBSSID, WLAN_BSSID_LEN);
  239. // Copy the SSID, pSSID->len=0 indicate broadcast SSID
  240. sFrame.pSSID = (PWLAN_IE_SSID)(sFrame.pBuf + sFrame.len);
  241. sFrame.len += pSSID->len + WLAN_IEHDR_LEN;
  242. memcpy(sFrame.pSSID, pSSID, pSSID->len + WLAN_IEHDR_LEN);
  243. sFrame.pSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
  244. sFrame.len += pCurrRates->len + WLAN_IEHDR_LEN;
  245. memcpy(sFrame.pSuppRates, pCurrRates, pCurrRates->len + WLAN_IEHDR_LEN);
  246. // Copy the extension rate set
  247. if (pDevice->eCurrentPHYType == PHY_TYPE_11G) {
  248. sFrame.pExtSuppRates = (PWLAN_IE_SUPP_RATES)(sFrame.pBuf + sFrame.len);
  249. sFrame.len += pCurrExtSuppRates->len + WLAN_IEHDR_LEN;
  250. memcpy(sFrame.pExtSuppRates, pCurrExtSuppRates, pCurrExtSuppRates->len + WLAN_IEHDR_LEN);
  251. }
  252. pTxPacket->cbMPDULen = sFrame.len;
  253. pTxPacket->cbPayloadLen = sFrame.len - WLAN_HDR_ADDR3_LEN;
  254. return pTxPacket;
  255. }
  256. void
  257. vCommandTimerWait(
  258. void *hDeviceContext,
  259. unsigned int MSecond
  260. )
  261. {
  262. struct vnt_private *pDevice = hDeviceContext;
  263. init_timer(&pDevice->sTimerCommand);
  264. pDevice->sTimerCommand.data = (unsigned long) pDevice;
  265. pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
  266. // RUN_AT :1 msec ~= (HZ/1024)
  267. pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10);
  268. add_timer(&pDevice->sTimerCommand);
  269. }
  270. void
  271. vCommandTimer(
  272. void *hDeviceContext
  273. )
  274. {
  275. struct vnt_private *pDevice = hDeviceContext;
  276. PSMgmtObject pMgmt = pDevice->pMgmt;
  277. PWLAN_IE_SSID pItemSSID;
  278. PWLAN_IE_SSID pItemSSIDCurr;
  279. CMD_STATUS Status;
  280. unsigned int ii;
  281. unsigned char byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
  282. struct sk_buff *skb;
  283. if (pDevice->dwDiagRefCount != 0)
  284. return;
  285. if (!pDevice->bCmdRunning)
  286. return;
  287. spin_lock_irq(&pDevice->lock);
  288. switch (pDevice->eCommandState) {
  289. case WLAN_CMD_SCAN_START:
  290. pDevice->byReAssocCount = 0;
  291. if (pDevice->bRadioOff) {
  292. s_bCommandComplete(pDevice);
  293. spin_unlock_irq(&pDevice->lock);
  294. return;
  295. }
  296. if (pMgmt->eCurrMode == WMAC_MODE_ESS_AP) {
  297. s_bCommandComplete(pDevice);
  298. CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_AP);
  299. spin_unlock_irq(&pDevice->lock);
  300. return;
  301. }
  302. pr_debug("eCommandState= WLAN_CMD_SCAN_START\n");
  303. pItemSSID = (PWLAN_IE_SSID)pMgmt->abyScanSSID;
  304. // wait all Data TD complete
  305. if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
  306. spin_unlock_irq(&pDevice->lock);
  307. vCommandTimerWait((void *)pDevice, 10);
  308. return;
  309. }
  310. if (pMgmt->uScanChannel == 0) {
  311. pMgmt->uScanChannel = pDevice->byMinChannel;
  312. // Set Baseband to be more sensitive.
  313. }
  314. if (pMgmt->uScanChannel > pDevice->byMaxChannel) {
  315. pMgmt->eScanState = WMAC_NO_SCANNING;
  316. // Set Baseband's sensitivity back.
  317. // Set channel back
  318. set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
  319. pr_debug("Scanning, set back to channel: [%d]\n",
  320. pMgmt->uCurrChannel);
  321. if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
  322. CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_ADHOC);
  323. else
  324. CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_STATION);
  325. vAdHocBeaconRestart(pDevice);
  326. s_bCommandComplete(pDevice);
  327. } else {
  328. //2008-8-4 <add> by chester
  329. if (!is_channel_valid(pMgmt->uScanChannel)) {
  330. pr_debug("Invalid channel pMgmt->uScanChannel = %d\n",
  331. pMgmt->uScanChannel);
  332. s_bCommandComplete(pDevice);
  333. spin_unlock_irq(&pDevice->lock);
  334. return;
  335. }
  336. if (pMgmt->uScanChannel == pDevice->byMinChannel) {
  337. pMgmt->abyScanBSSID[0] = 0xFF;
  338. pMgmt->abyScanBSSID[1] = 0xFF;
  339. pMgmt->abyScanBSSID[2] = 0xFF;
  340. pMgmt->abyScanBSSID[3] = 0xFF;
  341. pMgmt->abyScanBSSID[4] = 0xFF;
  342. pMgmt->abyScanBSSID[5] = 0xFF;
  343. pItemSSID->byElementID = WLAN_EID_SSID;
  344. pMgmt->eScanState = WMAC_IS_SCANNING;
  345. }
  346. vAdHocBeaconStop(pDevice);
  347. if (set_channel(pMgmt->pAdapter, pMgmt->uScanChannel))
  348. pr_debug("SCAN Channel: %d\n",
  349. pMgmt->uScanChannel);
  350. else
  351. pr_debug("SET SCAN Channel Fail: %d\n",
  352. pMgmt->uScanChannel);
  353. CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_UNSPECIFIED);
  354. pMgmt->uScanChannel++;
  355. //2008-8-4 <modify> by chester
  356. if (!is_channel_valid(pMgmt->uScanChannel) &&
  357. pMgmt->uScanChannel <= pDevice->byMaxChannel) {
  358. pMgmt->uScanChannel = pDevice->byMaxChannel + 1;
  359. pMgmt->eCommandState = WLAN_CMD_SCAN_END;
  360. }
  361. if (!pMgmt->b11hEnable ||
  362. (pMgmt->uScanChannel < CB_MAX_CHANNEL_24G)) {
  363. s_vProbeChannel(pDevice);
  364. spin_unlock_irq(&pDevice->lock);
  365. vCommandTimerWait((void *)pDevice, WCMD_ACTIVE_SCAN_TIME);
  366. return;
  367. } else {
  368. spin_unlock_irq(&pDevice->lock);
  369. vCommandTimerWait((void *)pDevice, WCMD_PASSIVE_SCAN_TIME);
  370. return;
  371. }
  372. }
  373. break;
  374. case WLAN_CMD_SCAN_END:
  375. // Set Baseband's sensitivity back.
  376. // Set channel back
  377. set_channel(pMgmt->pAdapter, pMgmt->uCurrChannel);
  378. pr_debug("Scanning, set back to channel: [%d]\n",
  379. pMgmt->uCurrChannel);
  380. if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)
  381. CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_ADHOC);
  382. else
  383. CARDbSetBSSID(pMgmt->pAdapter, pMgmt->abyCurrBSSID, NL80211_IFTYPE_STATION);
  384. pMgmt->eScanState = WMAC_NO_SCANNING;
  385. vAdHocBeaconRestart(pDevice);
  386. //2008-0409-07, <Add> by Einsn Liu
  387. #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
  388. if (pMgmt->eScanType == WMAC_SCAN_PASSIVE) {
  389. //send scan event to wpa_Supplicant
  390. union iwreq_data wrqu;
  391. memset(&wrqu, 0, sizeof(wrqu));
  392. wireless_send_event(pDevice->dev, SIOCGIWSCAN, &wrqu, NULL);
  393. }
  394. #endif
  395. s_bCommandComplete(pDevice);
  396. break;
  397. case WLAN_CMD_DISASSOCIATE_START:
  398. pDevice->byReAssocCount = 0;
  399. if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) &&
  400. (pMgmt->eCurrState != WMAC_STATE_ASSOC)) {
  401. s_bCommandComplete(pDevice);
  402. spin_unlock_irq(&pDevice->lock);
  403. return;
  404. } else {
  405. pr_debug("Send Disassociation Packet..\n");
  406. // reason = 8 : disassoc because sta has left
  407. vMgrDisassocBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (8), &Status);
  408. pDevice->bLinkPass = false;
  409. // unlock command busy
  410. pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
  411. pItemSSID->len = 0;
  412. memset(pItemSSID->abySSID, 0, WLAN_SSID_MAXLEN);
  413. pMgmt->eCurrState = WMAC_STATE_IDLE;
  414. pMgmt->sNodeDBTable[0].bActive = false;
  415. }
  416. netif_stop_queue(pDevice->dev);
  417. pDevice->eCommandState = WLAN_DISASSOCIATE_WAIT;
  418. // wait all Control TD complete
  419. if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
  420. vCommandTimerWait((void *)pDevice, 10);
  421. spin_unlock_irq(&pDevice->lock);
  422. return;
  423. }
  424. pr_debug(" CARDbRadioPowerOff\n");
  425. //2008-09-02 <mark> by chester
  426. s_bCommandComplete(pDevice);
  427. break;
  428. case WLAN_DISASSOCIATE_WAIT:
  429. // wait all Control TD complete
  430. if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
  431. vCommandTimerWait((void *)pDevice, 10);
  432. spin_unlock_irq(&pDevice->lock);
  433. return;
  434. }
  435. //2008-09-02 <mark> by chester
  436. s_bCommandComplete(pDevice);
  437. break;
  438. case WLAN_CMD_SSID_START:
  439. pDevice->byReAssocCount = 0;
  440. if (pDevice->bRadioOff) {
  441. s_bCommandComplete(pDevice);
  442. spin_unlock_irq(&pDevice->lock);
  443. return;
  444. }
  445. pr_debug("chester-abyDesireSSID=%s\n", ((PWLAN_IE_SSID)pMgmt->abyDesireSSID)->abySSID);
  446. pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
  447. pItemSSIDCurr = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
  448. pr_debug(" cmd: desire ssid = %s\n", pItemSSID->abySSID);
  449. pr_debug(" cmd: curr ssid = %s\n", pItemSSIDCurr->abySSID);
  450. if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
  451. pr_debug(" Cmd pMgmt->eCurrState == WMAC_STATE_ASSOC\n");
  452. pr_debug(" pItemSSID->len =%d\n", pItemSSID->len);
  453. pr_debug(" pItemSSIDCurr->len = %d\n",
  454. pItemSSIDCurr->len);
  455. pr_debug(" desire ssid = %s\n", pItemSSID->abySSID);
  456. pr_debug(" curr ssid = %s\n", pItemSSIDCurr->abySSID);
  457. }
  458. if ((pMgmt->eCurrState == WMAC_STATE_ASSOC) ||
  459. ((pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED))) {
  460. if (pItemSSID->len == pItemSSIDCurr->len) {
  461. if (memcmp(pItemSSID->abySSID, pItemSSIDCurr->abySSID, pItemSSID->len) == 0) {
  462. s_bCommandComplete(pDevice);
  463. spin_unlock_irq(&pDevice->lock);
  464. return;
  465. }
  466. }
  467. netif_stop_queue(pDevice->dev);
  468. pDevice->bLinkPass = false;
  469. }
  470. // set initial state
  471. pMgmt->eCurrState = WMAC_STATE_IDLE;
  472. pMgmt->eCurrMode = WMAC_MODE_STANDBY;
  473. PSvDisablePowerSaving((void *)pDevice);
  474. BSSvClearNodeDBTable(pDevice, 0);
  475. vMgrJoinBSSBegin((void *)pDevice, &Status);
  476. // if Infra mode
  477. if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_JOINTED)) {
  478. // Call mgr to begin the deauthentication
  479. // reason = (3) because sta has left ESS
  480. if (pMgmt->eCurrState >= WMAC_STATE_AUTH)
  481. vMgrDeAuthenBeginSta((void *)pDevice, pMgmt, pMgmt->abyCurrBSSID, (3), &Status);
  482. // Call mgr to begin the authentication
  483. vMgrAuthenBeginSta((void *)pDevice, pMgmt, &Status);
  484. if (Status == CMD_STATUS_SUCCESS) {
  485. pDevice->byLinkWaitCount = 0;
  486. pDevice->eCommandState = WLAN_AUTHENTICATE_WAIT;
  487. vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT);
  488. spin_unlock_irq(&pDevice->lock);
  489. pr_debug(" Set eCommandState = WLAN_AUTHENTICATE_WAIT\n");
  490. return;
  491. }
  492. }
  493. // if Adhoc mode
  494. else if (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA) {
  495. if (pMgmt->eCurrState == WMAC_STATE_JOINTED) {
  496. if (netif_queue_stopped(pDevice->dev))
  497. netif_wake_queue(pDevice->dev);
  498. pDevice->bLinkPass = true;
  499. pMgmt->sNodeDBTable[0].bActive = true;
  500. pMgmt->sNodeDBTable[0].uInActiveCount = 0;
  501. bClearBSSID_SCAN(pDevice);
  502. } else {
  503. // start own IBSS
  504. vMgrCreateOwnIBSS((void *)pDevice, &Status);
  505. if (Status != CMD_STATUS_SUCCESS)
  506. pr_debug(" WLAN_CMD_IBSS_CREATE fail !\n");
  507. BSSvAddMulticastNode(pDevice);
  508. }
  509. }
  510. // if SSID not found
  511. else if (pMgmt->eCurrMode == WMAC_MODE_STANDBY) {
  512. if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA ||
  513. pMgmt->eConfigMode == WMAC_CONFIG_AUTO) {
  514. // start own IBSS
  515. vMgrCreateOwnIBSS((void *)pDevice, &Status);
  516. if (Status != CMD_STATUS_SUCCESS)
  517. pr_debug(" WLAN_CMD_IBSS_CREATE fail !\n");
  518. BSSvAddMulticastNode(pDevice);
  519. if (netif_queue_stopped(pDevice->dev))
  520. netif_wake_queue(pDevice->dev);
  521. pDevice->bLinkPass = true;
  522. } else {
  523. pr_debug("Disconnect SSID none\n");
  524. #ifdef WPA_SUPPLICANT_DRIVER_WEXT_SUPPORT
  525. {
  526. union iwreq_data wrqu;
  527. memset(&wrqu, 0, sizeof(wrqu));
  528. wrqu.ap_addr.sa_family = ARPHRD_ETHER;
  529. pr_debug("wireless_send_event--->SIOCGIWAP(disassociated:vMgrJoinBSSBegin Fail !!)\n");
  530. wireless_send_event(pDevice->dev, SIOCGIWAP, &wrqu, NULL);
  531. }
  532. #endif
  533. }
  534. }
  535. s_bCommandComplete(pDevice);
  536. break;
  537. case WLAN_AUTHENTICATE_WAIT:
  538. pr_debug("eCommandState == WLAN_AUTHENTICATE_WAIT\n");
  539. if (pMgmt->eCurrState == WMAC_STATE_AUTH) {
  540. // Call mgr to begin the association
  541. pDevice->byLinkWaitCount = 0;
  542. pr_debug("eCurrState == WMAC_STATE_AUTH\n");
  543. vMgrAssocBeginSta((void *)pDevice, pMgmt, &Status);
  544. if (Status == CMD_STATUS_SUCCESS) {
  545. pDevice->byLinkWaitCount = 0;
  546. pr_debug("eCommandState = WLAN_ASSOCIATE_WAIT\n");
  547. pDevice->eCommandState = WLAN_ASSOCIATE_WAIT;
  548. vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT);
  549. spin_unlock_irq(&pDevice->lock);
  550. return;
  551. }
  552. }
  553. else if (pMgmt->eCurrState < WMAC_STATE_AUTHPENDING) {
  554. pr_debug("WLAN_AUTHENTICATE_WAIT:Authen Fail???\n");
  555. } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if authenticated_frame delay!
  556. pDevice->byLinkWaitCount++;
  557. pr_debug("WLAN_AUTHENTICATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
  558. spin_unlock_irq(&pDevice->lock);
  559. vCommandTimerWait((void *)pDevice, AUTHENTICATE_TIMEOUT/2);
  560. return;
  561. }
  562. pDevice->byLinkWaitCount = 0;
  563. s_bCommandComplete(pDevice);
  564. break;
  565. case WLAN_ASSOCIATE_WAIT:
  566. if (pMgmt->eCurrState == WMAC_STATE_ASSOC) {
  567. pr_debug("eCurrState == WMAC_STATE_ASSOC\n");
  568. if (pDevice->ePSMode != WMAC_POWER_CAM)
  569. PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
  570. if (pMgmt->eAuthenMode >= WMAC_AUTH_WPA)
  571. KeybRemoveAllKey(&(pDevice->sKey), pDevice->abyBSSID, pDevice->PortOffset);
  572. pDevice->bLinkPass = true;
  573. pDevice->byLinkWaitCount = 0;
  574. pDevice->byReAssocCount = 0;
  575. bClearBSSID_SCAN(pDevice);
  576. if (pDevice->byFOETuning) {
  577. BBvSetFOE(pDevice->PortOffset);
  578. PSbSendNullPacket(pDevice);
  579. }
  580. if (netif_queue_stopped(pDevice->dev))
  581. netif_wake_queue(pDevice->dev);
  582. if (pDevice->IsTxDataTrigger) { //TxDataTimer is not triggered at the first time
  583. del_timer(&pDevice->sTimerTxData);
  584. init_timer(&pDevice->sTimerTxData);
  585. pDevice->sTimerTxData.data = (unsigned long) pDevice;
  586. pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData;
  587. pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback
  588. pDevice->fTxDataInSleep = false;
  589. pDevice->nTxDataTimeCout = 0;
  590. }
  591. pDevice->IsTxDataTrigger = true;
  592. add_timer(&pDevice->sTimerTxData);
  593. } else if (pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) {
  594. printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n");
  595. } else if (pDevice->byLinkWaitCount <= 4) { //mike add:wait another 2 sec if associated_frame delay!
  596. pDevice->byLinkWaitCount++;
  597. pr_debug("WLAN_ASSOCIATE_WAIT:wait %d times!!\n", pDevice->byLinkWaitCount);
  598. spin_unlock_irq(&pDevice->lock);
  599. vCommandTimerWait((void *)pDevice, ASSOCIATE_TIMEOUT/2);
  600. return;
  601. }
  602. pDevice->byLinkWaitCount = 0;
  603. s_bCommandComplete(pDevice);
  604. break;
  605. case WLAN_CMD_AP_MODE_START:
  606. pr_debug("eCommandState == WLAN_CMD_AP_MODE_START\n");
  607. if (pMgmt->eConfigMode == WMAC_CONFIG_AP) {
  608. del_timer(&pMgmt->sTimerSecondCallback);
  609. pMgmt->eCurrState = WMAC_STATE_IDLE;
  610. pMgmt->eCurrMode = WMAC_MODE_STANDBY;
  611. pDevice->bLinkPass = false;
  612. if (pDevice->bEnableHostWEP)
  613. BSSvClearNodeDBTable(pDevice, 1);
  614. else
  615. BSSvClearNodeDBTable(pDevice, 0);
  616. pDevice->uAssocCount = 0;
  617. pMgmt->eCurrState = WMAC_STATE_IDLE;
  618. pDevice->bFixRate = false;
  619. vMgrCreateOwnIBSS((void *)pDevice, &Status);
  620. if (Status != CMD_STATUS_SUCCESS)
  621. pr_debug(" vMgrCreateOwnIBSS fail !\n");
  622. // alway turn off unicast bit
  623. MACvRegBitsOff(pDevice->PortOffset, MAC_REG_RCR, RCR_UNICAST);
  624. pDevice->byRxMode &= ~RCR_UNICAST;
  625. pr_debug("wcmd: rx_mode = %x\n", pDevice->byRxMode);
  626. BSSvAddMulticastNode(pDevice);
  627. if (netif_queue_stopped(pDevice->dev))
  628. netif_wake_queue(pDevice->dev);
  629. pDevice->bLinkPass = true;
  630. add_timer(&pMgmt->sTimerSecondCallback);
  631. }
  632. s_bCommandComplete(pDevice);
  633. break;
  634. case WLAN_CMD_TX_PSPACKET_START:
  635. // DTIM Multicast tx
  636. if (pMgmt->sNodeDBTable[0].bRxPSPoll) {
  637. while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[0].sTxPSQueue)) != NULL) {
  638. if (skb_queue_empty(&pMgmt->sNodeDBTable[0].sTxPSQueue)) {
  639. pMgmt->abyPSTxMap[0] &= ~byMask[0];
  640. pDevice->bMoreData = false;
  641. } else {
  642. pDevice->bMoreData = true;
  643. }
  644. if (!device_dma0_xmit(pDevice, skb, 0))
  645. pr_debug("Multicast ps tx fail\n");
  646. pMgmt->sNodeDBTable[0].wEnQueueCnt--;
  647. }
  648. }
  649. // PS nodes tx
  650. for (ii = 1; ii < (MAX_NODE_NUM + 1); ii++) {
  651. if (pMgmt->sNodeDBTable[ii].bActive &&
  652. pMgmt->sNodeDBTable[ii].bRxPSPoll) {
  653. pr_debug("Index=%d Enqueu Cnt= %d\n",
  654. ii,
  655. pMgmt->sNodeDBTable[ii].wEnQueueCnt);
  656. while ((skb = skb_dequeue(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) != NULL) {
  657. if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
  658. // clear tx map
  659. pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
  660. ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
  661. pDevice->bMoreData = false;
  662. } else {
  663. pDevice->bMoreData = true;
  664. }
  665. if (!device_dma0_xmit(pDevice, skb, ii))
  666. pr_debug("sta ps tx fail\n");
  667. pMgmt->sNodeDBTable[ii].wEnQueueCnt--;
  668. // check if sta ps enabled, and wait next pspoll.
  669. // if sta ps disable, then send all pending buffers.
  670. if (pMgmt->sNodeDBTable[ii].bPSEnable)
  671. break;
  672. }
  673. if (skb_queue_empty(&pMgmt->sNodeDBTable[ii].sTxPSQueue)) {
  674. // clear tx map
  675. pMgmt->abyPSTxMap[pMgmt->sNodeDBTable[ii].wAID >> 3] &=
  676. ~byMask[pMgmt->sNodeDBTable[ii].wAID & 7];
  677. pr_debug("Index=%d PS queue clear\n",
  678. ii);
  679. }
  680. pMgmt->sNodeDBTable[ii].bRxPSPoll = false;
  681. }
  682. }
  683. s_bCommandComplete(pDevice);
  684. break;
  685. case WLAN_CMD_RADIO_START:
  686. pr_debug("eCommandState == WLAN_CMD_RADIO_START\n");
  687. if (pDevice->bRadioCmd)
  688. CARDbRadioPowerOn(pDevice);
  689. else
  690. CARDbRadioPowerOff(pDevice);
  691. s_bCommandComplete(pDevice);
  692. break;
  693. case WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE:
  694. // wait all TD complete
  695. if (pDevice->iTDUsed[TYPE_AC0DMA] != 0) {
  696. vCommandTimerWait((void *)pDevice, 10);
  697. spin_unlock_irq(&pDevice->lock);
  698. return;
  699. }
  700. if (pDevice->iTDUsed[TYPE_TXDMA0] != 0) {
  701. vCommandTimerWait((void *)pDevice, 10);
  702. spin_unlock_irq(&pDevice->lock);
  703. return;
  704. }
  705. pDevice->byBBVGACurrent = pDevice->byBBVGANew;
  706. BBvSetVGAGainOffset(pDevice, pDevice->byBBVGACurrent);
  707. pr_debug("SetVGAGainOffset %02X\n", pDevice->byBBVGACurrent);
  708. s_bCommandComplete(pDevice);
  709. break;
  710. default:
  711. s_bCommandComplete(pDevice);
  712. break;
  713. } //switch
  714. spin_unlock_irq(&pDevice->lock);
  715. }
  716. static
  717. bool
  718. s_bCommandComplete(
  719. struct vnt_private *pDevice
  720. )
  721. {
  722. PWLAN_IE_SSID pSSID;
  723. bool bRadioCmd = false;
  724. bool bForceSCAN = true;
  725. PSMgmtObject pMgmt = pDevice->pMgmt;
  726. pDevice->eCommandState = WLAN_CMD_IDLE;
  727. if (pDevice->cbFreeCmdQueue == CMD_Q_SIZE) {
  728. //Command Queue Empty
  729. pDevice->bCmdRunning = false;
  730. return true;
  731. } else {
  732. pDevice->eCommand = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].eCmd;
  733. pSSID = (PWLAN_IE_SSID)pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].abyCmdDesireSSID;
  734. bRadioCmd = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bRadioCmd;
  735. bForceSCAN = pDevice->eCmdQueue[pDevice->uCmdDequeueIdx].bForceSCAN;
  736. ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdDequeueIdx, CMD_Q_SIZE);
  737. pDevice->cbFreeCmdQueue++;
  738. pDevice->bCmdRunning = true;
  739. switch (pDevice->eCommand) {
  740. case WLAN_CMD_BSSID_SCAN:
  741. pr_debug("eCommandState= WLAN_CMD_BSSID_SCAN\n");
  742. pDevice->eCommandState = WLAN_CMD_SCAN_START;
  743. pMgmt->uScanChannel = 0;
  744. if (pSSID->len != 0)
  745. memcpy(pMgmt->abyScanSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
  746. else
  747. memset(pMgmt->abyScanSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
  748. break;
  749. case WLAN_CMD_SSID:
  750. pDevice->eCommandState = WLAN_CMD_SSID_START;
  751. if (pSSID->len > WLAN_SSID_MAXLEN)
  752. pSSID->len = WLAN_SSID_MAXLEN;
  753. if (pSSID->len != 0)
  754. memcpy(pDevice->pMgmt->abyDesireSSID, pSSID, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
  755. pr_debug("eCommandState= WLAN_CMD_SSID_START\n");
  756. break;
  757. case WLAN_CMD_DISASSOCIATE:
  758. pDevice->eCommandState = WLAN_CMD_DISASSOCIATE_START;
  759. break;
  760. case WLAN_CMD_RX_PSPOLL:
  761. pDevice->eCommandState = WLAN_CMD_TX_PSPACKET_START;
  762. break;
  763. case WLAN_CMD_RUN_AP:
  764. pDevice->eCommandState = WLAN_CMD_AP_MODE_START;
  765. break;
  766. case WLAN_CMD_RADIO:
  767. pDevice->eCommandState = WLAN_CMD_RADIO_START;
  768. pDevice->bRadioCmd = bRadioCmd;
  769. break;
  770. case WLAN_CMD_CHANGE_BBSENSITIVITY:
  771. pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
  772. break;
  773. default:
  774. break;
  775. }
  776. vCommandTimerWait((void *)pDevice, 0);
  777. }
  778. return true;
  779. }
  780. bool bScheduleCommand(
  781. void *hDeviceContext,
  782. CMD_CODE eCommand,
  783. unsigned char *pbyItem0
  784. )
  785. {
  786. struct vnt_private *pDevice = hDeviceContext;
  787. if (pDevice->cbFreeCmdQueue == 0)
  788. return false;
  789. pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].eCmd = eCommand;
  790. pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = true;
  791. memset(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID, 0 , WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
  792. if (pbyItem0 != NULL) {
  793. switch (eCommand) {
  794. case WLAN_CMD_BSSID_SCAN:
  795. memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
  796. pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
  797. pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bForceSCAN = false;
  798. break;
  799. case WLAN_CMD_SSID:
  800. memcpy(pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].abyCmdDesireSSID,
  801. pbyItem0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
  802. break;
  803. case WLAN_CMD_DISASSOCIATE:
  804. pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bNeedRadioOFF = *((int *)pbyItem0);
  805. break;
  806. case WLAN_CMD_RX_PSPOLL:
  807. break;
  808. case WLAN_CMD_RADIO:
  809. pDevice->eCmdQueue[pDevice->uCmdEnqueueIdx].bRadioCmd = *((int *)pbyItem0);
  810. break;
  811. case WLAN_CMD_CHANGE_BBSENSITIVITY:
  812. pDevice->eCommandState = WLAN_CMD_CHECK_BBSENSITIVITY_CHANGE;
  813. break;
  814. default:
  815. break;
  816. }
  817. }
  818. ADD_ONE_WITH_WRAP_AROUND(pDevice->uCmdEnqueueIdx, CMD_Q_SIZE);
  819. pDevice->cbFreeCmdQueue--;
  820. if (!pDevice->bCmdRunning)
  821. s_bCommandComplete(pDevice);
  822. return true;
  823. }
  824. /*
  825. * Description:
  826. * Clear BSSID_SCAN cmd in CMD Queue
  827. *
  828. * Parameters:
  829. * In:
  830. * hDeviceContext - Pointer to the adapter
  831. * eCommand - Command
  832. * Out:
  833. * none
  834. *
  835. * Return Value: true if success; otherwise false
  836. *
  837. */
  838. bool bClearBSSID_SCAN(
  839. void *hDeviceContext
  840. )
  841. {
  842. struct vnt_private *pDevice = hDeviceContext;
  843. unsigned int uCmdDequeueIdx = pDevice->uCmdDequeueIdx;
  844. unsigned int ii;
  845. if ((pDevice->cbFreeCmdQueue < CMD_Q_SIZE) && (uCmdDequeueIdx != pDevice->uCmdEnqueueIdx)) {
  846. for (ii = 0; ii < (CMD_Q_SIZE - pDevice->cbFreeCmdQueue); ii++) {
  847. if (pDevice->eCmdQueue[uCmdDequeueIdx].eCmd == WLAN_CMD_BSSID_SCAN)
  848. pDevice->eCmdQueue[uCmdDequeueIdx].eCmd = WLAN_CMD_IDLE;
  849. ADD_ONE_WITH_WRAP_AROUND(uCmdDequeueIdx, CMD_Q_SIZE);
  850. if (uCmdDequeueIdx == pDevice->uCmdEnqueueIdx)
  851. break;
  852. }
  853. }
  854. return true;
  855. }
  856. //mike add:reset command timer
  857. void
  858. vResetCommandTimer(
  859. void *hDeviceContext
  860. )
  861. {
  862. struct vnt_private *pDevice = hDeviceContext;
  863. //delete timer
  864. del_timer(&pDevice->sTimerCommand);
  865. //init timer
  866. init_timer(&pDevice->sTimerCommand);
  867. pDevice->sTimerCommand.data = (unsigned long) pDevice;
  868. pDevice->sTimerCommand.function = (TimerFunction)vCommandTimer;
  869. pDevice->sTimerCommand.expires = RUN_AT(HZ);
  870. pDevice->cbFreeCmdQueue = CMD_Q_SIZE;
  871. pDevice->uCmdDequeueIdx = 0;
  872. pDevice->uCmdEnqueueIdx = 0;
  873. pDevice->eCommandState = WLAN_CMD_IDLE;
  874. pDevice->bCmdRunning = false;
  875. pDevice->bCmdClear = false;
  876. }
  877. void
  878. BSSvSecondTxData(
  879. void *hDeviceContext
  880. )
  881. {
  882. struct vnt_private *pDevice = hDeviceContext;
  883. PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
  884. pDevice->nTxDataTimeCout++;
  885. if (pDevice->nTxDataTimeCout < 4) //don't tx data if timer less than 40s
  886. {
  887. pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback
  888. add_timer(&pDevice->sTimerTxData);
  889. return;
  890. }
  891. spin_lock_irq(&pDevice->lock);
  892. /* open && sharekey linking */
  893. if ((pDevice->bLinkPass && (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) ||
  894. pDevice->fWPA_Authened) { /* wpa linking */
  895. pDevice->fTxDataInSleep = true;
  896. PSbSendNullPacket(pDevice); /* send null packet */
  897. pDevice->fTxDataInSleep = false;
  898. }
  899. spin_unlock_irq(&pDevice->lock);
  900. pDevice->sTimerTxData.expires = RUN_AT(10*HZ); /* 10s callback */
  901. add_timer(&pDevice->sTimerTxData);
  902. }