Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4697 lines
138 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1995 Microsoft Corporation
  4. *
  5. * @doc
  6. * @module irlap.c | Provides IrLAP API
  7. *
  8. * Author: mbert
  9. *
  10. * Date: 4/15/95
  11. *
  12. * @comm
  13. *
  14. * This module exports the following API's:
  15. *
  16. * IrlapDown(Message)
  17. * Receives from LMP:
  18. * - Discovery request
  19. * - Connect request/response
  20. * - Disconnect request
  21. * - Data/UData request
  22. *
  23. * IrlapUp(Message)
  24. * Receives from MAC:
  25. * - Data indications
  26. * - Control confirmations
  27. *
  28. * IrlapTimerExp(Timer)
  29. * Receives from timer thread timer expiration notifications
  30. *
  31. * IrlapCloseLink()
  32. * Shut down IRLAP and IRMAC.
  33. *
  34. * IrlapGetQosParmVal()
  35. * Allows IRLMP to decode Qos.
  36. *
  37. * |---------|
  38. * | IRLMP |
  39. * |---------|
  40. * /|\ |
  41. * | |
  42. * IrlmpUp() | | IrlapDown()
  43. * | |
  44. * | \|/
  45. * |---------| IRDA_TimerStart/Stop() |-------|
  46. * | |-------------------------->| |
  47. * | IRLAP | | TIMER |
  48. * | |<--------------------------| |
  49. * |---------| XTimerExp() |-------|
  50. * /|\ |
  51. * | |
  52. * IrlapUp() | |IrmacDown()
  53. * | |
  54. * | \|/
  55. * |---------|
  56. * | IRMAC |
  57. * |---------|
  58. *
  59. *
  60. * Discovery Request
  61. *
  62. * |-------| IRLAP_DISCOVERY_REQ |-------|
  63. * | |---------------------------------------------------->| |
  64. * | IRLMP | | IRLAP |
  65. * | |<----------------------------------------------------| |
  66. * |-------| IRLAP_DISCOVERY_CONF |-------|
  67. * DscvStatus = IRLAP_DISCOVERY_COMPLETE
  68. * IRLAP_DISCOVERY_COLLISION
  69. * MAC_MEDIA_BUSY
  70. *
  71. * Connect Request
  72. *
  73. * |-------| IRLAP_CONNECT_REQ |-------|
  74. * | |---------------------------------------------------->| |
  75. * | IRLMP | | IRLAP |
  76. * | |<----------------------------------------------------| |
  77. * |-------| IRLAP_CONNECT_CONF |-------|
  78. * ConnStatus = IRLAP_CONNECTION_COMPLETE
  79. * IRLAP_DISCONNECT_IND
  80. * DiscStatus = IRLAP_NO_RESPONSE
  81. * MAC_MEDIA_BUSY
  82. *
  83. * Disconnect Request
  84. *
  85. * |-------| IRLAP_DISCONNECT_REQ |-------|
  86. * | |---------------------------------------------------->| |
  87. * | IRLMP | | IRLAP |
  88. * | |<----------------------------------------------------| |
  89. * |-------| IRLAP_DISCONNECT_IND |-------|
  90. * DiscStatus = IRLAP_DISCONNECT_COMPLETE
  91. * IRLAP_NO_RESPONSE
  92. *
  93. * UData/Data Request
  94. *
  95. * |-------| IRLAP_DATA/UDATA_REQ |-------|
  96. * | |---------------------------------------------------->| |
  97. * | IRLMP | | IRLAP |
  98. * | |<----------------------------------------------------| |
  99. * |-------| IRLAP_DATA_CONF |-------|
  100. * DataStatus = IRLAP_DATA_REQUEST_COMPLETED
  101. * IRLAP_DATA_REQUEST_FAILED_LINK_RESET
  102. *
  103. * See irda.h for complete message definitions
  104. */
  105. #include <irda.h>
  106. #include <irioctl.h>
  107. #include <irlap.h>
  108. #include <irlmp.h>
  109. #include <irlapp.h>
  110. #include <irlapio.h>
  111. #include <irlaplog.h>
  112. #undef offsetof
  113. #include "irlap.tmh"
  114. #ifdef TEMPERAMENTAL_SERIAL_DRIVER
  115. int TossedDups;
  116. #endif
  117. #ifdef ALLOC_DATA_PRAGMA
  118. #pragma data_seg("PAGE")
  119. #endif
  120. BOOLEAN MonitoringLinkStatus;
  121. const UINT IrlapSlotTable[] = {1, 6, 8, 16};
  122. const UCHAR IrlapBroadcastDevAddr[IRDA_DEV_ADDR_LEN] = {0xFF,0xFF,0xFF,0xFF};
  123. // Parameter Value (PV) tables used for negotation
  124. // bit0 1 2 3 4
  125. // 5 6 7 8
  126. // --------------------------------------------
  127. const
  128. UINT vBaudTable[] = {2400, 9600, 19200, 38400, 57600,\
  129. 115200, 576000, 1152000, 4000000,16000000};
  130. const
  131. UINT vMaxTATTable[] = {500, 250, 100, 50, 25, \
  132. 10, 5, 0, 0, 0 };
  133. const
  134. UINT vMinTATTable[] = {10000, 5000, 1000, 500, 100, \
  135. 50, 10, 0, 0, 0 };
  136. const
  137. UINT vDataSizeTable[] = {64, 128, 256, 512, 1024, \
  138. 2048, 0, 0, 0, 0 };
  139. const
  140. UINT vWinSizeTable[] = {1, 2, 3, 4, 5, \
  141. 6, 7, 0, 0, 0 };
  142. const
  143. UINT vBOFSTable[] = {48, 24, 12, 5, 3, \
  144. 2, 1, 0, -1, -1 };
  145. const
  146. UINT vDiscTable[] = {3, 8, 12, 16, 20, \
  147. 25, 30, 40, 0, 0 };
  148. const
  149. UINT vThreshTable[] = {0, 3, 3, 3, 3, \
  150. 3, 3, 3, 0, 0 };
  151. const
  152. UINT vBOFSDivTable[] = {48, 12, 6, 3, 2, \
  153. 1, 1, 1, 1, 1 };
  154. // Tables for determining number of BOFS for baud and min turn time
  155. // min turn time - 10ms 5ms 1ms 0.5ms 0.1ms 0.05ms 0.01ms
  156. // -------------------------------------------------------------
  157. const UINT BOFS_9600[] = {10, 5, 1, 0, 0, 0, 0};
  158. const UINT BOFS_19200[] = {20, 10, 2, 1, 0, 0, 0};
  159. const UINT BOFS_38400[] = {40, 20, 4, 2, 0, 0, 0};
  160. const UINT BOFS_57600[] = {58, 29, 6, 3, 1, 0, 0};
  161. const UINT BOFS_115200[] = {115, 58, 12, 6, 1, 1, 0};
  162. const UINT BOFS_576000[] = {720, 360, 72, 36, 7, 4, 2};
  163. const UINT BOFS_1152000[] = {1140, 720, 144, 72, 14, 7, 1};
  164. const UINT BOFS_4000000[] = {5000,2500, 500, 250, 50, 25, 5};
  165. const UINT BOFS_16000000[] = {20000,10000,2000,1000, 200, 100, 20};
  166. // Tables for determining maximum line capacity for baud, max turn time
  167. // max turn time - 500ms 250ms 100ms 50ms 25ms 10ms 5ms
  168. // -------------------------------------------------------------
  169. const UINT MAXCAP_9600[] = {400, 200, 80, 0, 0, 0, 0};
  170. const UINT MAXCAP_19200[] = {800, 400, 160, 0, 0, 0, 0};
  171. const UINT MAXCAP_38400[] = {1600, 800, 320, 0, 0, 0, 0};
  172. const UINT MAXCAP_57600[] = {2360, 1180, 472, 0, 0, 0, 0};
  173. const UINT MAXCAP_115200[] = {4800, 2400, 960, 480, 240, 96, 48};
  174. const UINT MAXCAP_576000[] = {28800, 11520, 5760, 2880, 1440, 720, 360};
  175. const UINT MAXCAP_1152000[] = {57600, 28800, 11520, 5760, 2880, 1440, 720};
  176. const UINT MAXCAP_4000000[] = {200000,100000, 40000,20000,10000, 5000, 2500};
  177. const UINT MAXCAP_16000000[] ={800000,400000, 160000,80000,40000,20000,10000};
  178. #ifdef ALLOC_DATA_PRAGMA
  179. #pragma data_seg()
  180. #endif
  181. // prototypes
  182. STATIC VOID InitializeState(PIRLAP_CB, IRLAP_STN_TYPE);
  183. STATIC VOID ReturnRxTxWinMsgs(PIRLAP_CB);
  184. STATIC UINT ProcessConnectReq(PIRLAP_CB, PIRDA_MSG);
  185. STATIC VOID ProcessConnectResp(PIRLAP_CB, PIRDA_MSG);
  186. STATIC UINT ProcessDiscoveryReq(PIRLAP_CB, PIRDA_MSG);
  187. STATIC VOID ProcessDisconnectReq(PIRLAP_CB);
  188. STATIC UINT ProcessDataAndUDataReq(PIRLAP_CB, PIRDA_MSG);
  189. STATIC VOID XmitTxMsgList(PIRLAP_CB, BOOLEAN, BOOLEAN *);
  190. STATIC VOID GotoPCloseState(PIRLAP_CB);
  191. STATIC VOID GotoNDMThenDscvOrConn(PIRLAP_CB);
  192. STATIC VOID ProcessMACControlConf(PIRLAP_CB, PIRDA_MSG);
  193. STATIC VOID ProcessMACDataInd(PIRLAP_CB, PIRDA_MSG);
  194. STATIC VOID ProcessDscvXIDCmd(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, UCHAR *);
  195. STATIC VOID ProcessDscvXIDRsp(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, UCHAR *);
  196. STATIC VOID ExtractQosParms(IRDA_QOS_PARMS *, UCHAR *, UCHAR *);
  197. STATIC VOID InitDscvCmdProcessing(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *);
  198. STATIC VOID ExtractDeviceInfo(IRDA_DEVICE *, IRLAP_XID_DSCV_FORMAT *, UCHAR *);
  199. STATIC BOOLEAN DevInDevList(UCHAR[], LIST_ENTRY *);
  200. STATIC VOID AddDevToList(PIRLAP_CB, IRLAP_XID_DSCV_FORMAT *, UCHAR *);
  201. STATIC VOID FreeDevList(LIST_ENTRY *);
  202. STATIC VOID ProcessSNRM(PIRLAP_CB, IRLAP_SNRM_FORMAT *, UCHAR *);
  203. STATIC VOID ProcessUA(PIRLAP_CB, IRLAP_UA_FORMAT *, UCHAR *);
  204. STATIC VOID ProcessDISC(PIRLAP_CB);
  205. STATIC VOID ProcessRD(PIRLAP_CB);
  206. STATIC VOID ProcessRNRM(PIRLAP_CB);
  207. STATIC VOID ProcessDM(PIRLAP_CB);
  208. STATIC VOID ProcessFRMR(PIRLAP_CB);
  209. STATIC VOID ProcessTEST(PIRLAP_CB, PIRDA_MSG, IRLAP_UA_FORMAT *, int, int);
  210. STATIC VOID ProcessUI(PIRLAP_CB, PIRDA_MSG, int, int);
  211. STATIC VOID ProcessREJ_SREJ(
  212. PIRLAP_CB,
  213. int,
  214. int,
  215. int,
  216. UINT
  217. );
  218. STATIC VOID ProcessRR_RNR(PIRLAP_CB,
  219. int,
  220. int,
  221. int,
  222. UINT
  223. );
  224. STATIC VOID ProcessIFrame(PIRLAP_CB, PIRDA_MSG, int, int, UINT, UINT);
  225. STATIC BOOLEAN InvalidNs(PIRLAP_CB, UINT);
  226. STATIC BOOLEAN InvalidNr(PIRLAP_CB, UINT);
  227. STATIC BOOLEAN InWindow(UINT, UINT, UINT);
  228. STATIC VOID ProcessInvalidNsOrNr(PIRLAP_CB, int);
  229. STATIC VOID ProcessInvalidNr(PIRLAP_CB, int);
  230. STATIC VOID InsertRxWinAndForward(PIRLAP_CB, PIRDA_MSG, UINT);
  231. STATIC VOID ResendRejects(PIRLAP_CB, UINT);
  232. STATIC VOID ConfirmAckedTxMsgs(PIRLAP_CB, UINT);
  233. STATIC VOID MissingRxFrames(PIRLAP_CB);
  234. STATIC VOID IFrameOtherStates(PIRLAP_CB, int, int);
  235. STATIC UINT NegotiateQosParms(PIRLAP_CB, IRDA_QOS_PARMS *);
  236. STATIC VOID ApplyQosParms(PIRLAP_CB);
  237. STATIC VOID StationConflict(PIRLAP_CB);
  238. STATIC VOID ApplyDefaultParms(PIRLAP_CB);
  239. STATIC VOID ResendDISC(PIRLAP_CB);
  240. STATIC BOOLEAN IgnoreState(PIRLAP_CB);
  241. STATIC BOOLEAN MyDevAddr(PIRLAP_CB, UCHAR []);
  242. STATIC VOID SlotTimerExp(PVOID);
  243. STATIC VOID FinalTimerExp(PVOID);
  244. STATIC VOID PollTimerExp(PVOID);
  245. STATIC VOID BackoffTimerExp(PVOID);
  246. STATIC VOID WDogTimerExp(PVOID);
  247. STATIC VOID QueryTimerExp(PVOID);
  248. // STATIC VOID StatusTimerExp(PVOID);
  249. STATIC VOID IndicateLinkStatus(PIRLAP_CB);
  250. STATIC VOID StatusReq(PIRLAP_CB, IRDA_MSG *pMsg);
  251. #ifdef ALLOC_PRAGMA
  252. #pragma alloc_text(PAGEIRDA, IrlapOpenLink)
  253. #pragma alloc_text(PAGEIRDA, InitializeState)
  254. #pragma alloc_text(PAGEIRDA, ReturnRxTxWinMsgs)
  255. #pragma alloc_text(PAGEIRDA, ProcessConnectReq)
  256. #pragma alloc_text(PAGEIRDA, ProcessConnectResp)
  257. #pragma alloc_text(PAGEIRDA, ProcessDiscoveryReq)
  258. #pragma alloc_text(PAGEIRDA, ProcessDisconnectReq)
  259. #pragma alloc_text(PAGEIRDA, GotoPCloseState)
  260. #pragma alloc_text(PAGEIRDA, GotoNDMThenDscvOrConn)
  261. #pragma alloc_text(PAGEIRDA, ProcessMACControlConf)
  262. #pragma alloc_text(PAGEIRDA, ExtractQosParms)
  263. #pragma alloc_text(PAGEIRDA, ExtractDeviceInfo)
  264. #pragma alloc_text(PAGEIRDA, FreeDevList)
  265. #pragma alloc_text(PAGEIRDA, ProcessSNRM)
  266. #pragma alloc_text(PAGEIRDA, ProcessUA)
  267. #pragma alloc_text(PAGEIRDA, ProcessRD)
  268. #pragma alloc_text(PAGEIRDA, ProcessRNRM)
  269. #pragma alloc_text(PAGEIRDA, ProcessDM)
  270. #pragma alloc_text(PAGEIRDA, ProcessFRMR)
  271. #pragma alloc_text(PAGEIRDA, ProcessTEST)
  272. #pragma alloc_text(PAGEIRDA, ProcessUI)
  273. #pragma alloc_text(PAGEIRDA, NegotiateQosParms)
  274. #pragma alloc_text(PAGEIRDA, ApplyQosParms)
  275. #pragma alloc_text(PAGEIRDA, StationConflict)
  276. #pragma alloc_text(PAGEIRDA, ApplyDefaultParms)
  277. #endif
  278. #if DBG
  279. void _inline IrlapTimerStart(PIRLAP_CB pIrlapCb, PIRDA_TIMER pTmr)
  280. {
  281. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Start %hs timer for %dms"), pTmr->pName,
  282. pTmr->Timeout));
  283. IrdaTimerStart(pTmr);
  284. }
  285. void _inline IrlapTimerStop(PIRLAP_CB pIrlapCb, PIRDA_TIMER pTmr)
  286. {
  287. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Stop %hs timer"), pTmr->pName));
  288. IrdaTimerStop(pTmr);
  289. }
  290. #else
  291. #define IrlapTimerStart(c,t) IrdaTimerStart(t)
  292. #define IrlapTimerStop(c,t) IrdaTimerStop(t)
  293. #endif
  294. VOID
  295. IrlapOpenLink(OUT PNTSTATUS Status,
  296. IN PIRDA_LINK_CB pIrdaLinkCb,
  297. IN IRDA_QOS_PARMS *pQos,
  298. IN UCHAR *pDscvInfo,
  299. IN int DscvInfoLen,
  300. IN UINT MaxSlot,
  301. IN UCHAR *pDeviceName,
  302. IN int DeviceNameLen,
  303. IN UCHAR CharSet)
  304. {
  305. UINT rc = SUCCESS;
  306. int i;
  307. IRDA_MSG IMsg;
  308. PIRLAP_CB pIrlapCb;
  309. NDIS_STRING AStr = NDIS_STRING_CONST("InfraredTransceiverType");
  310. PAGED_CODE();
  311. DEBUGMSG(DBG_IRLAP, (TEXT("IrlapOpenLink\n")));
  312. if (IRDA_ALLOC_MEM(pIrlapCb, sizeof(IRLAP_CB), MT_IRLAPCB) == NULL)
  313. {
  314. DEBUGMSG(DBG_ERROR, (TEXT("Alloc failed\n")));
  315. *Status = STATUS_INSUFFICIENT_RESOURCES;
  316. return;
  317. }
  318. CTEMemSet(pIrlapCb, 0, sizeof(IRLAP_CB));
  319. IrlmpOpenLink(Status,
  320. pIrdaLinkCb,
  321. pDeviceName,
  322. DeviceNameLen,
  323. CharSet);
  324. if (*Status != STATUS_SUCCESS)
  325. {
  326. DEBUGMSG(DBG_ERROR, (TEXT("IrlmpOpenLink failed\n")));
  327. IRDA_FREE_MEM(pIrlapCb);
  328. return;
  329. }
  330. pIrdaLinkCb->IrlapContext = pIrlapCb;
  331. DscvInfoLen = DscvInfoLen > IRLAP_DSCV_INFO_LEN ?
  332. IRLAP_DSCV_INFO_LEN : DscvInfoLen;
  333. CTEMemCopy(pIrlapCb->LocalDevice.DscvInfo, pDscvInfo, DscvInfoLen);
  334. pIrlapCb->LocalDevice.DscvInfoLen = DscvInfoLen;
  335. CTEMemCopy(&pIrlapCb->LocalQos, pQos, sizeof(IRDA_QOS_PARMS));
  336. pIrlapCb->MaxSlot = MaxSlot;
  337. pIrlapCb->pIrdaLinkCb = pIrdaLinkCb;
  338. InitializeListHead(&pIrlapCb->TxMsgList);
  339. InitializeListHead(&pIrlapCb->ExTxMsgList);
  340. InitializeListHead(&pIrlapCb->DevList);
  341. for (i = 0; i < IRLAP_MOD; i++)
  342. {
  343. pIrlapCb->TxWin.pMsg[i] = NULL;
  344. pIrlapCb->RxWin.pMsg[i] = NULL;
  345. }
  346. // Get the local MAX TAT (for final timeout)
  347. if ((pIrlapCb->LocalMaxTAT =
  348. IrlapGetQosParmVal(vMaxTATTable,
  349. pIrlapCb->LocalQos.bfMaxTurnTime, NULL)) == -1)
  350. {
  351. *Status = STATUS_UNSUCCESSFUL;
  352. return /*IRLAP_BAD_QOS*/;
  353. }
  354. if ((pIrlapCb->LocalWinSize =
  355. IrlapGetQosParmVal(vWinSizeTable,
  356. pIrlapCb->LocalQos.bfWindowSize, NULL)) == -1)
  357. {
  358. *Status = STATUS_UNSUCCESSFUL;
  359. return /*IRLAP_BAD_QOS*/;
  360. }
  361. // initialize as PRIMARY so UI frames in contention
  362. // state sends CRBit = cmd
  363. InitializeState(pIrlapCb, PRIMARY);
  364. pIrlapCb->State = NDM;
  365. // Generate random local address
  366. StoreULAddr(pIrlapCb->LocalDevice.DevAddr, (ULONG) GetMyDevAddr(FALSE));
  367. pIrlapCb->LocalDevice.IRLAP_Version = 0;
  368. pIrlapCb->Baud = IRLAP_CONTENTION_BAUD;
  369. pIrlapCb->RemoteMaxTAT = IRLAP_CONTENTION_MAX_TAT;
  370. pIrlapCb->RemoteDataSize = IRLAP_CONTENTION_DATA_SIZE;
  371. pIrlapCb->RemoteWinSize = IRLAP_CONTENTION_WIN_SIZE;
  372. pIrlapCb->RemoteNumBOFS = IRLAP_CONTENTION_BOFS;
  373. pIrlapCb->ConnAddr = IRLAP_BROADCAST_CONN_ADDR;
  374. pIrlapCb->N1 = 0; // calculated at negotiation
  375. pIrlapCb->N2 = 0;
  376. pIrlapCb->N3 = 5; // recalculated after negotiation ??
  377. #if DBG
  378. pIrlapCb->PollTimer.pName = "Poll";
  379. pIrlapCb->FinalTimer.pName = "Final" ;
  380. pIrlapCb->SlotTimer.pName = "Slot";
  381. pIrlapCb->QueryTimer.pName = "Query";
  382. pIrlapCb->WDogTimer.pName = "WatchDog";
  383. pIrlapCb->BackoffTimer.pName = "Backoff";
  384. // pIrlapCb->StatusTimer.pName = "Status";
  385. #endif
  386. IrdaTimerInitialize(&pIrlapCb->PollTimer,
  387. PollTimerExp,
  388. pIrlapCb->RemoteMaxTAT,
  389. pIrlapCb,
  390. pIrdaLinkCb);
  391. IrdaTimerInitialize(&pIrlapCb->FinalTimer,
  392. FinalTimerExp,
  393. pIrlapCb->LocalMaxTAT,
  394. pIrlapCb,
  395. pIrdaLinkCb);
  396. IrdaTimerInitialize(&pIrlapCb->SlotTimer,
  397. SlotTimerExp,
  398. IRLAP_SLOT_TIMEOUT,
  399. pIrlapCb,
  400. pIrdaLinkCb);
  401. IrdaTimerInitialize(&pIrlapCb->QueryTimer,
  402. QueryTimerExp,
  403. (IRLAP_MAX_SLOTS + 4) * IRLAP_SLOT_TIMEOUT*2,
  404. pIrlapCb,
  405. pIrdaLinkCb);
  406. IrdaTimerInitialize(&pIrlapCb->WDogTimer,
  407. WDogTimerExp,
  408. 3000,
  409. pIrlapCb,
  410. pIrdaLinkCb);
  411. IrdaTimerInitialize(&pIrlapCb->BackoffTimer,
  412. BackoffTimerExp,
  413. 0,
  414. pIrlapCb,
  415. pIrdaLinkCb);
  416. /*
  417. IrdaTimerInitialize(&pIrlapCb->StatusTimer,
  418. StatusTimerExp,
  419. 250,
  420. pIrlapCb,
  421. pIrdaLinkCb);
  422. // Only monitor the link status of the first link
  423. if (!MonitoringLinkStatus)
  424. {
  425. MonitoringLinkStatus = TRUE;
  426. pIrlapCb->MonitorLink = TRUE;
  427. }
  428. else
  429. {
  430. pIrlapCb->MonitorLink = FALSE;
  431. }
  432. */
  433. // Initialize Link
  434. IMsg.Prim = MAC_CONTROL_REQ;
  435. IMsg.IRDA_MSG_Op = MAC_INITIALIZE_LINK;
  436. IMsg.IRDA_MSG_Baud = IRLAP_CONTENTION_BAUD;
  437. IMsg.IRDA_MSG_NumBOFs = IRLAP_CONTENTION_BOFS;
  438. IMsg.IRDA_MSG_DataSize = IRLAP_CONTENTION_DATA_SIZE;
  439. IMsg.IRDA_MSG_MinTat = 0;
  440. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  441. *Status = STATUS_SUCCESS;
  442. }
  443. /*****************************************************************************
  444. */
  445. VOID
  446. IrlapCloseLink(PIRDA_LINK_CB pIrdaLinkCb)
  447. {
  448. IRDA_MSG IMsg;
  449. PIRLAP_CB pIrlapCb = (PIRLAP_CB) pIrdaLinkCb->IrlapContext;
  450. IRLAP_LOG_START((pIrlapCb, TEXT("IRLAP: CloseLink")));
  451. ReturnRxTxWinMsgs(pIrlapCb);
  452. IrlapTimerStop(pIrlapCb, &pIrlapCb->SlotTimer);
  453. IrlapTimerStop(pIrlapCb, &pIrlapCb->QueryTimer);
  454. IrlapTimerStop(pIrlapCb, &pIrlapCb->PollTimer);
  455. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  456. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  457. IrlapTimerStop(pIrlapCb, &pIrlapCb->BackoffTimer);
  458. /*
  459. if (pIrlapCb->MonitorLink)
  460. {
  461. IrdaTimerStop(&pIrlapCb->StatusTimer);
  462. }
  463. */
  464. IRLAP_LOG_COMPLETE(pIrlapCb);
  465. IMsg.Prim = MAC_CONTROL_REQ;
  466. IMsg.IRDA_MSG_Op = MAC_CLOSE_LINK;
  467. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  468. return;
  469. }
  470. /*****************************************************************************
  471. *
  472. * Delete memory associated with an Irlap instance
  473. *
  474. */
  475. VOID
  476. IrlapDeleteInstance(PVOID Context)
  477. {
  478. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  479. #if DBG
  480. int i;
  481. for (i = 0; i < IRLAP_MOD; i++)
  482. {
  483. ASSERT(pIrlapCb->TxWin.pMsg[i] == NULL);
  484. ASSERT(pIrlapCb->RxWin.pMsg[i] == NULL);
  485. }
  486. #endif
  487. FreeDevList(&pIrlapCb->DevList);
  488. DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: Delete instance %p\n"), pIrlapCb));
  489. IRDA_FREE_MEM(pIrlapCb);
  490. }
  491. /*****************************************************************************
  492. *
  493. * InitializeState - resets link control block
  494. *
  495. */
  496. VOID
  497. InitializeState(PIRLAP_CB pIrlapCb,
  498. IRLAP_STN_TYPE StationType)
  499. {
  500. PAGED_CODE();
  501. pIrlapCb->StationType = StationType;
  502. if (StationType == PRIMARY)
  503. pIrlapCb->CRBit = IRLAP_CMD;
  504. else
  505. pIrlapCb->CRBit = IRLAP_RSP;
  506. pIrlapCb->RemoteBusy = FALSE;
  507. pIrlapCb->LocalBusy = FALSE;
  508. pIrlapCb->ClrLocalBusy = FALSE;
  509. pIrlapCb->NoResponse = FALSE;
  510. pIrlapCb->LocalDiscReq = FALSE;
  511. pIrlapCb->ConnAfterClose = FALSE;
  512. pIrlapCb->DscvAfterClose = FALSE;
  513. pIrlapCb->GenNewAddr = FALSE;
  514. pIrlapCb->StatusSent = FALSE;
  515. pIrlapCb->Vs = 0;
  516. pIrlapCb->Vr = 0;
  517. pIrlapCb->WDogExpCnt = 0;
  518. pIrlapCb->StatusFlags = 0;
  519. pIrlapCb->FastPollCount = 0;
  520. FreeDevList(&pIrlapCb->DevList);
  521. memset(&pIrlapCb->RemoteQos, 0, sizeof(IRDA_QOS_PARMS));
  522. memset(&pIrlapCb->NegotiatedQos, 0, sizeof(IRDA_QOS_PARMS));
  523. // Return msgs on tx list and in tx/rx windows
  524. ReturnRxTxWinMsgs(pIrlapCb);
  525. }
  526. /*****************************************************************************
  527. *
  528. * IrlapDown - Entry point into IRLAP for LMP
  529. *
  530. */
  531. UINT
  532. IrlapDown(PVOID Context,
  533. PIRDA_MSG pMsg)
  534. {
  535. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  536. UINT rc = SUCCESS;
  537. IRLAP_LOG_START((pIrlapCb, IRDA_PrimStr[pMsg->Prim]));
  538. switch (pMsg->Prim)
  539. {
  540. case IRLAP_DISCOVERY_REQ:
  541. rc = ProcessDiscoveryReq(pIrlapCb, pMsg);
  542. break;
  543. case IRLAP_CONNECT_REQ:
  544. rc = ProcessConnectReq(pIrlapCb, pMsg);
  545. break;
  546. case IRLAP_CONNECT_RESP:
  547. ProcessConnectResp(pIrlapCb, pMsg);
  548. break;
  549. case IRLAP_DISCONNECT_REQ:
  550. ProcessDisconnectReq(pIrlapCb);
  551. break;
  552. case IRLAP_DATA_REQ:
  553. case IRLAP_UDATA_REQ:
  554. rc = ProcessDataAndUDataReq(pIrlapCb, pMsg);
  555. break;
  556. case IRLAP_FLOWON_REQ:
  557. if (pIrlapCb->LocalBusy)
  558. {
  559. IRLAP_LOG_ACTION((pIrlapCb,TEXT("Local busy condition cleared")));
  560. pIrlapCb->LocalBusy = FALSE;
  561. pIrlapCb->ClrLocalBusy = TRUE;
  562. }
  563. break;
  564. case IRLAP_STATUS_REQ:
  565. StatusReq(pIrlapCb, pMsg);
  566. break;
  567. default:
  568. ASSERT(0);
  569. rc = IRLAP_BAD_PRIM;
  570. }
  571. IRLAP_LOG_COMPLETE(pIrlapCb);
  572. return rc;
  573. }
  574. /*****************************************************************************
  575. *
  576. * IrlapUp - Entry point into IRLAP for MAC
  577. *
  578. */
  579. VOID
  580. IrlapUp(PVOID Context, PIRDA_MSG pMsg)
  581. {
  582. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  583. switch (pMsg->Prim)
  584. {
  585. case MAC_DATA_IND:
  586. // IRLAP_LOG_START((pIrlapCb, TEXT("MAC_DATA_IND: %s"), FrameToStr(pMsg)));
  587. IRLAP_LOG_START((pIrlapCb, TEXT("MAC_DATA_IND")));
  588. ProcessMACDataInd(pIrlapCb, pMsg);
  589. break;
  590. case MAC_DATA_CONF:
  591. IRLAP_LOG_START((pIrlapCb, TEXT("IRLAP: MAC_DATA_CONF pMsg:%p"), pMsg));
  592. ASSERT(pMsg->IRDA_MSG_RefCnt == 0);
  593. pMsg->Prim = IRLAP_DATA_CONF;
  594. pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_COMPLETED;
  595. IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  596. break;
  597. case MAC_CONTROL_CONF:
  598. IRLAP_LOG_START((pIrlapCb, IRDA_PrimStr[pMsg->Prim]));
  599. ProcessMACControlConf(pIrlapCb, pMsg);
  600. break;
  601. default:
  602. IRLAP_LOG_START((pIrlapCb, IRDA_PrimStr[pMsg->Prim]));
  603. ASSERT(0); //rc = IRLAP_BAD_PRIM;
  604. }
  605. IRLAP_LOG_COMPLETE(pIrlapCb);
  606. }
  607. /*****************************************************************************
  608. *
  609. */
  610. VOID
  611. ReturnRxTxWinMsgs(PIRLAP_CB pIrlapCb)
  612. {
  613. int i;
  614. IRDA_MSG *pMsg;
  615. PAGED_CODE();
  616. // Return messages on ExTxMsgList and TxMsgList to LMP
  617. pMsg = (PIRDA_MSG) RemoveHeadList(&pIrlapCb->ExTxMsgList);
  618. while (pMsg != (PIRDA_MSG) &pIrlapCb->ExTxMsgList)
  619. {
  620. pMsg->Prim += 2; // make it a confirm
  621. pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_FAILED_LINK_RESET;
  622. IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  623. pMsg = (PIRDA_MSG) RemoveHeadList(&pIrlapCb->ExTxMsgList);
  624. }
  625. pMsg = (PIRDA_MSG) RemoveHeadList(&pIrlapCb->TxMsgList);
  626. while (pMsg != (PIRDA_MSG) &pIrlapCb->TxMsgList)
  627. {
  628. pMsg->Prim += 2; // make it a confirm
  629. pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_FAILED_LINK_RESET;
  630. IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  631. pMsg = (PIRDA_MSG) RemoveHeadList(&pIrlapCb->TxMsgList);
  632. }
  633. pIrlapCb->TxWin.Start = 0;
  634. pIrlapCb->TxWin.End = 0;
  635. // Transmit window
  636. for (i = 0; i < IRLAP_MOD; i++)
  637. {
  638. pMsg = pIrlapCb->TxWin.pMsg[i];
  639. pIrlapCb->TxWin.pMsg[i] = NULL;
  640. if (pMsg != NULL)
  641. {
  642. ASSERT(pMsg->IRDA_MSG_RefCnt);
  643. if (InterlockedDecrement(&pMsg->IRDA_MSG_RefCnt) == 0)
  644. {
  645. pMsg->Prim = IRLAP_DATA_CONF;
  646. pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_FAILED_LINK_RESET;
  647. IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  648. }
  649. #if DBG
  650. else
  651. {
  652. DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: Outstanding msg %p, SendCnt is %d at disconnect\n"),
  653. pMsg, pMsg->IRDA_MSG_RefCnt));
  654. }
  655. #endif
  656. }
  657. }
  658. // Cleanup RxWin
  659. pIrlapCb->RxWin.Start = 0;
  660. pIrlapCb->RxWin.End = 0;
  661. for (i = 0; i < IRLAP_MOD; i++)
  662. {
  663. // Receive window
  664. if ((pMsg = pIrlapCb->RxWin.pMsg[i]) != NULL)
  665. {
  666. pMsg->IRDA_MSG_RefCnt = 0;
  667. pMsg->Prim = MAC_DATA_RESP;
  668. IrmacDown(pIrlapCb->pIrdaLinkCb, pMsg);
  669. pIrlapCb->RxWin.pMsg[i] = NULL;
  670. }
  671. }
  672. return;
  673. }
  674. /*****************************************************************************
  675. *
  676. * MyDevAddr - Determines if DevAddr matches the local
  677. * device address or is the broadcast
  678. *
  679. * TRUE if address is mine or broadcast else FALS
  680. *
  681. *
  682. */
  683. BOOLEAN
  684. MyDevAddr(PIRLAP_CB pIrlapCb,
  685. UCHAR DevAddr[])
  686. {
  687. if (CTEMemCmp(DevAddr, IrlapBroadcastDevAddr,
  688. IRDA_DEV_ADDR_LEN) &&
  689. CTEMemCmp(DevAddr, pIrlapCb->LocalDevice.DevAddr,
  690. IRDA_DEV_ADDR_LEN))
  691. {
  692. return FALSE;
  693. }
  694. return TRUE;
  695. }
  696. /*****************************************************************************
  697. *
  698. * ProcessConnectReq - Process connect request from LMP
  699. *
  700. */
  701. UINT
  702. ProcessConnectReq(PIRLAP_CB pIrlapCb,
  703. PIRDA_MSG pMsg)
  704. {
  705. IRDA_MSG IMsg;
  706. PAGED_CODE();
  707. DEBUGMSG(DBG_IRLAP, (TEXT("IRLAP: ProcessConnectReq: state=%d\n"),pIrlapCb->State));
  708. switch (pIrlapCb->State)
  709. {
  710. case NDM:
  711. // Save Remote Address for later use
  712. CTEMemCopy(pIrlapCb->RemoteDevice.DevAddr,
  713. pMsg->IRDA_MSG_RemoteDevAddr,
  714. IRDA_DEV_ADDR_LEN);
  715. IMsg.Prim = MAC_CONTROL_REQ;
  716. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  717. IMsg.IRDA_MSG_SenseTime = IRLAP_MEDIA_SENSE_TIME;
  718. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  719. pIrlapCb->State = CONN_MEDIA_SENSE;
  720. IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (media sense)")));
  721. break;
  722. case DSCV_REPLY:
  723. return IRLAP_REMOTE_DISCOVERY_IN_PROGRESS_ERR;
  724. case P_CLOSE:
  725. CTEMemCopy(pIrlapCb->RemoteDevice.DevAddr,
  726. pMsg->IRDA_MSG_RemoteDevAddr, IRDA_DEV_ADDR_LEN);
  727. pIrlapCb->ConnAfterClose = TRUE;
  728. break;
  729. case CONN_MEDIA_SENSE:
  730. IRLAP_LOG_ACTION((pIrlapCb, TEXT(" already doing media sense")));
  731. #if DBG
  732. DbgPrint("IRDA: ProcessConnectRequest() already doing media sense\n");
  733. #endif
  734. return IRLAP_BAD_STATE;
  735. break;
  736. default:
  737. ASSERT(0);
  738. return IRLAP_BAD_STATE;
  739. }
  740. return SUCCESS;
  741. }
  742. /*****************************************************************************
  743. *
  744. * ProcessConnectResp - Process connect response from LMP
  745. *
  746. */
  747. VOID
  748. ProcessConnectResp(PIRLAP_CB pIrlapCb,
  749. PIRDA_MSG pMsg)
  750. {
  751. PAGED_CODE();
  752. DEBUGMSG(DBG_IRLAP, (TEXT("IRLAP: ProcessConnectResp: state=%d\n"),pIrlapCb->State));
  753. if (pIrlapCb->State != SNRM_RECEIVED)
  754. {
  755. ASSERT(0);
  756. return;
  757. }
  758. pIrlapCb->ConnAddr = pIrlapCb->SNRMConnAddr;
  759. SendUA(pIrlapCb, TRUE);
  760. ApplyQosParms(pIrlapCb);
  761. InitializeState(pIrlapCb, SECONDARY);
  762. // start watchdog timer with poll timeout
  763. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  764. pIrlapCb->State = S_NRM;
  765. }
  766. /*****************************************************************************
  767. *
  768. * ProcessDiscoveryReq - Process Discovery request from LMP
  769. *
  770. */
  771. UINT
  772. ProcessDiscoveryReq(PIRLAP_CB pIrlapCb,
  773. PIRDA_MSG pMsg)
  774. {
  775. IRDA_MSG IMsg;
  776. PAGED_CODE();
  777. DEBUGMSG(DBG_IRLAP, (TEXT("IRLAP: ProcessDiscoveryReq: state=%d\n"),pIrlapCb->State));
  778. switch (pIrlapCb->State)
  779. {
  780. case NDM:
  781. if (pMsg->IRDA_MSG_SenseMedia == TRUE)
  782. {
  783. IMsg.Prim = MAC_CONTROL_REQ;
  784. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  785. IMsg.IRDA_MSG_SenseTime = IRLAP_MEDIA_SENSE_TIME;
  786. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  787. pIrlapCb->State = DSCV_MEDIA_SENSE;
  788. IRLAP_LOG_ACTION((pIrlapCb,TEXT("MAC_CONTROL_REQ (mediasense)")));
  789. }
  790. else
  791. {
  792. pIrlapCb->SlotCnt = 0;
  793. pIrlapCb->GenNewAddr = FALSE;
  794. FreeDevList(&pIrlapCb->DevList);
  795. SendDscvXIDCmd(pIrlapCb);
  796. IMsg.Prim = MAC_CONTROL_REQ;
  797. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  798. IMsg.IRDA_MSG_SenseTime = IRLAP_DSCV_SENSE_TIME;
  799. IRLAP_LOG_ACTION((pIrlapCb,TEXT("MAC_CONTROL_REQ (dscvsense)")));
  800. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  801. pIrlapCb->State = DSCV_QUERY;
  802. }
  803. break;
  804. case DSCV_REPLY:
  805. return IRLAP_REMOTE_DISCOVERY_IN_PROGRESS_ERR;
  806. case SNRM_RECEIVED:
  807. return IRLAP_REMOTE_CONNECTION_IN_PROGRESS_ERR;
  808. case P_CLOSE:
  809. pIrlapCb->DscvAfterClose = TRUE;
  810. break;
  811. default:
  812. ASSERT(0);
  813. return IRLAP_BAD_STATE;
  814. }
  815. return SUCCESS;
  816. }
  817. /*****************************************************************************
  818. *
  819. * ProcessDisconnectReq - Process disconnect request from LMP
  820. *
  821. */
  822. VOID
  823. ProcessDisconnectReq(PIRLAP_CB pIrlapCb)
  824. {
  825. ReturnRxTxWinMsgs(pIrlapCb);
  826. DEBUGMSG(DBG_IRLAP, (TEXT("IRLAP: ProcessDisconnectReq: state=%d\n"),pIrlapCb->State));
  827. switch (pIrlapCb->State)
  828. {
  829. case NDM:
  830. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  831. break;
  832. case SNRM_SENT:
  833. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  834. pIrlapCb->State = NDM;
  835. break;
  836. case DSCV_REPLY:
  837. IrlapTimerStop(pIrlapCb, &pIrlapCb->QueryTimer);
  838. pIrlapCb->State = NDM;
  839. break;
  840. case DSCV_MEDIA_SENSE:
  841. case DSCV_QUERY:
  842. case CONN_MEDIA_SENSE:
  843. pIrlapCb->State = NDM;
  844. break;
  845. case BACKOFF_WAIT:
  846. IrlapTimerStop(pIrlapCb, &pIrlapCb->BackoffTimer);
  847. pIrlapCb->State = NDM;
  848. break;
  849. case SNRM_RECEIVED:
  850. pIrlapCb->ConnAddr = pIrlapCb->SNRMConnAddr;
  851. SendDM(pIrlapCb);
  852. pIrlapCb->ConnAddr = IRLAP_BROADCAST_CONN_ADDR;
  853. pIrlapCb->State = NDM;
  854. break;
  855. case P_XMIT:
  856. pIrlapCb->LocalDiscReq = TRUE;
  857. IrlapTimerStop(pIrlapCb, &pIrlapCb->PollTimer);
  858. SendDISC(pIrlapCb);
  859. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  860. pIrlapCb->RetryCnt = 0;
  861. pIrlapCb->State = P_CLOSE;
  862. break;
  863. case P_RECV:
  864. pIrlapCb->LocalDiscReq = TRUE;
  865. pIrlapCb->State = P_DISCONNECT_PEND;
  866. break;
  867. case S_NRM:
  868. pIrlapCb->LocalDiscReq = TRUE;
  869. pIrlapCb->State = S_DISCONNECT_PEND;
  870. break;
  871. default:
  872. ASSERT(0);
  873. // return IRLAP_BAD_STATE;
  874. }
  875. }
  876. /*****************************************************************************
  877. *
  878. * ProcessDataReq - Process data request from LMP
  879. *
  880. */
  881. UINT
  882. ProcessDataAndUDataReq(PIRLAP_CB pIrlapCb,
  883. PIRDA_MSG pMsg)
  884. {
  885. BOOLEAN LinkTurned;
  886. LONG_PTR DataSize = (pMsg->IRDA_MSG_pHdrWrite - pMsg->IRDA_MSG_pHdrRead) +
  887. (pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead);
  888. DEBUGMSG(DBG_IRLAP, (TEXT("IRLAP: ProcessDataAndUDataReq: state=%d\n"),pIrlapCb->State));
  889. if (DataSize > pIrlapCb->RemoteDataSize)
  890. {
  891. return IRLAP_BAD_DATA_REQUEST;
  892. }
  893. switch (pIrlapCb->State)
  894. {
  895. case P_XMIT:
  896. // Enque message, then drain the message list. If the link
  897. // was turned in the process of draining messages stop Poll Timer,
  898. // start Final Timer and enter P_RECV. Otherwise we'll stay in P_XMIT
  899. // waiting for more data requests from LMP or Poll Timer expiration
  900. if (pMsg->IRDA_MSG_Expedited)
  901. {
  902. InsertTailList(&pIrlapCb->ExTxMsgList, &pMsg->Linkage);
  903. }
  904. else
  905. {
  906. InsertTailList(&pIrlapCb->TxMsgList, &pMsg->Linkage);
  907. }
  908. XmitTxMsgList(pIrlapCb, FALSE, &LinkTurned);
  909. if (LinkTurned)
  910. {
  911. IrlapTimerStop(pIrlapCb, &pIrlapCb->PollTimer);
  912. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  913. pIrlapCb->State = P_RECV;
  914. }
  915. return SUCCESS;
  916. case P_DISCONNECT_PEND: //For pending disc states, take the message.
  917. case S_DISCONNECT_PEND: // They will be returned when the link discs
  918. case P_RECV:
  919. case S_NRM:
  920. // Que the message for later transmission
  921. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Queueing request")));
  922. if (pMsg->IRDA_MSG_Expedited)
  923. {
  924. InsertTailList(&pIrlapCb->ExTxMsgList, &pMsg->Linkage);
  925. }
  926. else
  927. {
  928. InsertTailList(&pIrlapCb->TxMsgList, &pMsg->Linkage);
  929. }
  930. return SUCCESS;
  931. default:
  932. if (pMsg->Prim == IRLAP_DATA_REQ)
  933. {
  934. ASSERT(0);
  935. return IRLAP_BAD_STATE;
  936. }
  937. else
  938. {
  939. if (pIrlapCb->State == NDM)
  940. {
  941. SendUIFrame(pIrlapCb, pMsg);
  942. }
  943. else
  944. {
  945. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  946. }
  947. }
  948. }
  949. return SUCCESS;
  950. }
  951. /*****************************************************************************
  952. *
  953. */
  954. VOID
  955. XmitTxMsgList(PIRLAP_CB pIrlapCb, BOOLEAN AlwaysTurnLink,
  956. BOOLEAN *pLinkTurned)
  957. {
  958. IRDA_MSG *pMsg;
  959. BOOLEAN LinkTurned;
  960. LinkTurned = FALSE;
  961. // If the remote is not busy send data
  962. // If we need to clear the local busy condition, don't send data send RR
  963. if (!pIrlapCb->RemoteBusy && !pIrlapCb->ClrLocalBusy)
  964. {
  965. while (!LinkTurned)
  966. {
  967. if (!IsListEmpty(&pIrlapCb->ExTxMsgList))
  968. {
  969. pMsg = (PIRDA_MSG) RemoveHeadList(&pIrlapCb->ExTxMsgList);
  970. }
  971. else if (!IsListEmpty(&pIrlapCb->TxMsgList))
  972. {
  973. pMsg = (PIRDA_MSG) RemoveHeadList(&pIrlapCb->TxMsgList);
  974. }
  975. else
  976. {
  977. break;
  978. }
  979. pIrlapCb->FastPollCount = IRLAP_FAST_POLL_COUNT;
  980. pIrlapCb->PollTimer.Timeout = IRLAP_FAST_POLL_TIME >
  981. pIrlapCb->RemoteMaxTAT ? pIrlapCb->RemoteMaxTAT : IRLAP_FAST_POLL_TIME;
  982. if (pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead)
  983. pIrlapCb->StatusFlags |= LF_TX;
  984. if (pMsg->Prim == IRLAP_DATA_REQ)
  985. {
  986. // Insert message into transmit window
  987. pIrlapCb->TxWin.pMsg[pIrlapCb->Vs] = pMsg;
  988. pMsg->IRDA_MSG_RefCnt = 1;
  989. // Send message. If full window or there are no
  990. // more data requests, send with PF Set (turns link).
  991. if ((pIrlapCb->Vs == (pIrlapCb->TxWin.Start +
  992. pIrlapCb->RemoteWinSize-1) % IRLAP_MOD) ||
  993. (IsListEmpty(&pIrlapCb->TxMsgList) &&
  994. IsListEmpty(&pIrlapCb->ExTxMsgList)))
  995. {
  996. SendIFrame(pIrlapCb,
  997. pMsg,
  998. pIrlapCb->Vs,
  999. IRLAP_PFBIT_SET);
  1000. LinkTurned = TRUE;
  1001. }
  1002. else
  1003. {
  1004. SendIFrame(pIrlapCb,
  1005. pMsg,
  1006. pIrlapCb->Vs,
  1007. IRLAP_PFBIT_CLEAR);
  1008. }
  1009. pIrlapCb->Vs = (pIrlapCb->Vs + 1) % IRLAP_MOD;
  1010. }
  1011. else // IRLAP_UDATA_REQUEST
  1012. {
  1013. // For now, always turn link
  1014. SendUIFrame(pIrlapCb, pMsg);
  1015. pMsg->Prim = IRLAP_UDATA_CONF;
  1016. pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_COMPLETED;
  1017. IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  1018. LinkTurned = TRUE;
  1019. }
  1020. }
  1021. pIrlapCb->TxWin.End = pIrlapCb->Vs;
  1022. }
  1023. if ((AlwaysTurnLink && !LinkTurned) || pIrlapCb->ClrLocalBusy)
  1024. {
  1025. SendRR_RNR(pIrlapCb);
  1026. LinkTurned = TRUE;
  1027. if (pIrlapCb->ClrLocalBusy)
  1028. {
  1029. pIrlapCb->ClrLocalBusy = FALSE;
  1030. }
  1031. }
  1032. if (pLinkTurned != NULL)
  1033. {
  1034. *pLinkTurned = LinkTurned;
  1035. }
  1036. }
  1037. VOID
  1038. GotoPCloseState(PIRLAP_CB pIrlapCb)
  1039. {
  1040. IRDA_MSG IMsg;
  1041. PAGED_CODE();
  1042. if (!pIrlapCb->LocalDiscReq)
  1043. {
  1044. IMsg.Prim = IRLAP_DISCONNECT_IND;
  1045. IMsg.IRDA_MSG_DiscStatus = IRLAP_REMOTE_INITIATED;
  1046. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1047. }
  1048. ReturnRxTxWinMsgs(pIrlapCb);
  1049. pIrlapCb->State = P_CLOSE;
  1050. }
  1051. VOID
  1052. GotoNDMThenDscvOrConn(PIRLAP_CB pIrlapCb)
  1053. {
  1054. IRDA_MSG IMsg;
  1055. PAGED_CODE();
  1056. if (pIrlapCb->ConnAfterClose)
  1057. {
  1058. pIrlapCb->ConnAfterClose = FALSE;
  1059. IMsg.Prim = MAC_CONTROL_REQ;
  1060. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  1061. IMsg.IRDA_MSG_SenseTime = IRLAP_MEDIA_SENSE_TIME;
  1062. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  1063. pIrlapCb->State = CONN_MEDIA_SENSE;
  1064. IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (conn media sense)")));
  1065. return;
  1066. }
  1067. if (pIrlapCb->DscvAfterClose)
  1068. {
  1069. pIrlapCb->DscvAfterClose = FALSE;
  1070. IMsg.Prim = MAC_CONTROL_REQ;
  1071. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  1072. IMsg.IRDA_MSG_SenseTime = IRLAP_MEDIA_SENSE_TIME;
  1073. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  1074. pIrlapCb->State = DSCV_MEDIA_SENSE;
  1075. IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (disc media sense)")));
  1076. return;
  1077. }
  1078. pIrlapCb->State = NDM;
  1079. return;
  1080. }
  1081. /*****************************************************************************
  1082. *
  1083. * ProcessMACControlConf - Process a control confirm from MAC
  1084. *
  1085. */
  1086. VOID
  1087. ProcessMACControlConf(PIRLAP_CB pIrlapCb, PIRDA_MSG pMsg)
  1088. {
  1089. IRDA_MSG IMsg;
  1090. PAGED_CODE();
  1091. if (pMsg->IRDA_MSG_Op != MAC_MEDIA_SENSE)
  1092. {
  1093. ASSERT(0);
  1094. return; //IRLAP_BAD_OP;
  1095. }
  1096. switch (pIrlapCb->State)
  1097. {
  1098. case DSCV_MEDIA_SENSE:
  1099. switch (pMsg->IRDA_MSG_OpStatus)
  1100. {
  1101. case MAC_MEDIA_CLEAR:
  1102. IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_MEDIA_CLEAR")));
  1103. //IndicateLinkStatus(pIrlapCb, LINK_STATUS_DISCOVERING);
  1104. pIrlapCb->SlotCnt = 0;
  1105. pIrlapCb->GenNewAddr = FALSE;
  1106. FreeDevList(&pIrlapCb->DevList);
  1107. SendDscvXIDCmd(pIrlapCb);
  1108. IMsg.Prim = MAC_CONTROL_REQ;
  1109. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  1110. IMsg.IRDA_MSG_SenseTime = IRLAP_DSCV_SENSE_TIME;
  1111. IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (dscvsense)")));
  1112. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  1113. pIrlapCb->State = DSCV_QUERY;
  1114. break;
  1115. case MAC_MEDIA_BUSY:
  1116. IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_MEDIA_BUSY")));
  1117. pIrlapCb->State = NDM;
  1118. IMsg.Prim = IRLAP_DISCOVERY_CONF;
  1119. IMsg.IRDA_MSG_pDevList = NULL;
  1120. IMsg.IRDA_MSG_DscvStatus = MAC_MEDIA_BUSY;
  1121. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1122. break;
  1123. default:
  1124. ASSERT(0);
  1125. return;// IRLAP_BAD_OPSTATUS;
  1126. }
  1127. break;
  1128. case CONN_MEDIA_SENSE:
  1129. switch (pMsg->IRDA_MSG_OpStatus)
  1130. {
  1131. case MAC_MEDIA_CLEAR:
  1132. // Generate a random connection address
  1133. pIrlapCb->ConnAddr = IRLAP_RAND(1, 0x7e);
  1134. pIrlapCb->RetryCnt = 0;
  1135. SendSNRM(pIrlapCb, TRUE);
  1136. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  1137. pIrlapCb->State = SNRM_SENT;
  1138. break;
  1139. case MAC_MEDIA_BUSY:
  1140. pIrlapCb->State = NDM;
  1141. IMsg.Prim = IRLAP_DISCONNECT_IND;
  1142. IMsg.IRDA_MSG_DiscStatus = MAC_MEDIA_BUSY;
  1143. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1144. break;
  1145. default:
  1146. ASSERT(0);
  1147. return;// IRLAP_BAD_OPSTATUS;
  1148. }
  1149. break;
  1150. case DSCV_QUERY:
  1151. switch (pMsg->IRDA_MSG_OpStatus)
  1152. {
  1153. case MAC_MEDIA_CLEAR:
  1154. // Nobody responded, procede as if the slot timer expired
  1155. IRLAP_LOG_ACTION((pIrlapCb,
  1156. TEXT("Media clear, making fake slot exp")));
  1157. SlotTimerExp(pIrlapCb);
  1158. break;
  1159. case MAC_MEDIA_BUSY:
  1160. // Some responding, give'm more time
  1161. IRLAP_LOG_ACTION((pIrlapCb,
  1162. TEXT("Media busy, starting slot timer")));
  1163. IrlapTimerStart(pIrlapCb, &pIrlapCb->SlotTimer);
  1164. break;
  1165. }
  1166. break;
  1167. default:
  1168. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  1169. }
  1170. }
  1171. /*****************************************************************************
  1172. *
  1173. * ProcessMACDataInd - Processes MAC Data
  1174. *
  1175. *
  1176. */
  1177. VOID
  1178. ProcessMACDataInd(PIRLAP_CB pIrlapCb, PIRDA_MSG pMsg)
  1179. {
  1180. //
  1181. // frame was checked to be atleast two bytes long in indication handler
  1182. // so we can get the addesss and control bytes
  1183. //
  1184. ULONG_PTR FrameLength= pMsg->IRDA_MSG_pWrite-pMsg->IRDA_MSG_pRead;
  1185. UCHAR Addr = IRLAP_GET_ADDR(*(pMsg->IRDA_MSG_pRead));
  1186. UCHAR CRBit = IRLAP_GET_CRBIT(*(pMsg->IRDA_MSG_pRead));
  1187. UCHAR Cntl = *(pMsg->IRDA_MSG_pRead + 1);
  1188. UCHAR PFBit = IRLAP_GET_PFBIT(Cntl);
  1189. UCHAR FrameType = IRLAP_FRAME_TYPE(Cntl);
  1190. UINT Ns = IRLAP_GET_NS(Cntl);
  1191. UINT Nr = IRLAP_GET_NR(Cntl);
  1192. if (Addr != pIrlapCb->ConnAddr && Addr != IRLAP_BROADCAST_CONN_ADDR)
  1193. {
  1194. IRLAP_LOG_ACTION((pIrlapCb,
  1195. TEXT("Ignoring, connection address %02X"), Addr));
  1196. return;
  1197. }
  1198. pIrlapCb->StatusSent = FALSE;
  1199. pIrlapCb->Frmr.CntlField = Cntl; // for later maybe
  1200. // Peer has sent a frame so clear the NoResponse condition
  1201. // Unnumbered frame shouldn't reset the no response condition
  1202. // (ie only frames received in the connected state).
  1203. if (pIrlapCb->NoResponse && FrameType != IRLAP_U_FRAME)
  1204. {
  1205. pIrlapCb->NoResponse = FALSE;
  1206. pIrlapCb->RetryCnt = 0;
  1207. pIrlapCb->WDogExpCnt = 0;
  1208. pIrlapCb->StatusFlags = LF_CONNECTED;
  1209. IndicateLinkStatus(pIrlapCb);
  1210. }
  1211. switch (FrameType)
  1212. {
  1213. /*****************/
  1214. case IRLAP_I_FRAME:
  1215. /*****************/
  1216. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: I-frame)")));
  1217. ProcessIFrame(pIrlapCb, pMsg, CRBit, PFBit, Ns, Nr);
  1218. return;
  1219. /*****************/
  1220. case IRLAP_S_FRAME:
  1221. /*****************/
  1222. switch (IRLAP_GET_SCNTL(Cntl))
  1223. {
  1224. /*-----------*/
  1225. case IRLAP_RR:
  1226. case IRLAP_RNR:
  1227. /*-----------*/
  1228. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(RR/RNR-frame)")));
  1229. ProcessRR_RNR(pIrlapCb, IRLAP_GET_SCNTL(Cntl),
  1230. CRBit, PFBit, Nr);
  1231. return;
  1232. /*------------*/
  1233. case IRLAP_SREJ:
  1234. case IRLAP_REJ:
  1235. /*------------*/
  1236. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(SJREJ/REJ-frame)")));
  1237. ProcessREJ_SREJ(pIrlapCb, IRLAP_GET_SCNTL(Cntl),
  1238. CRBit, PFBit, Nr);
  1239. return;
  1240. }
  1241. break;
  1242. /*****************/
  1243. case IRLAP_U_FRAME:
  1244. /*****************/
  1245. switch (IRLAP_GET_UCNTL(Cntl))
  1246. {
  1247. /*---------------*/
  1248. case IRLAP_XID_CMD:
  1249. /*---------------*/
  1250. {
  1251. UCHAR XIDFormatID;
  1252. IRLAP_XID_DSCV_FORMAT *pXIDFormat;
  1253. //
  1254. // make sure frame is big enough
  1255. //
  1256. // AC + FI + SRC + DEST + FLAGS + SLOT + Ver
  1257. //
  1258. if (FrameLength < 2 + 1 + 4 + 4 + 1 + 1 + 1) {
  1259. //
  1260. // too small
  1261. //
  1262. IRLAP_LOG_ACTION((pIrlapCb,TEXT("Received XID frmae to small")));
  1263. ASSERT(0);
  1264. return;
  1265. }
  1266. //
  1267. // we know the frame is big enough get some of the info
  1268. //
  1269. XIDFormatID = *(pMsg->IRDA_MSG_pRead+2);
  1270. pXIDFormat = (IRLAP_XID_DSCV_FORMAT *)(pMsg->IRDA_MSG_pRead + 3);
  1271. //
  1272. // Should always be a command
  1273. //
  1274. if (CRBit != IRLAP_CMD)
  1275. {
  1276. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received XID cmd with CRBit = rsp")));
  1277. ASSERT(0);
  1278. return; // IRLAP_XID_CMD_RSP;
  1279. }
  1280. //
  1281. // Poll bit should always be set
  1282. //
  1283. if (PFBit != IRLAP_PFBIT_SET)
  1284. {
  1285. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received XID command without Poll set")));
  1286. ASSERT(0);
  1287. return; // IRLAP_XID_CMD_NOT_P;
  1288. }
  1289. if (XIDFormatID == IRLAP_XID_DSCV_FORMAT_ID)
  1290. {
  1291. // Slot No is less than max slot or 0xff
  1292. if (pXIDFormat->SlotNo > IrlapSlotTable[pXIDFormat->NoOfSlots & 0x03]
  1293. && pXIDFormat->SlotNo != IRLAP_END_DSCV_SLOT_NO)
  1294. {
  1295. IRLAP_LOG_ACTION((pIrlapCb,
  1296. TEXT("Invalid slot number %d"),
  1297. pXIDFormat->SlotNo));
  1298. ASSERT(0);
  1299. return;// IRLAP_BAD_SLOTNO;
  1300. }
  1301. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: DscvXidCmd slot=%d)"),pXIDFormat->SlotNo));
  1302. ProcessDscvXIDCmd(pIrlapCb, pXIDFormat,
  1303. pMsg->IRDA_MSG_pWrite);
  1304. return;
  1305. }
  1306. return;
  1307. }
  1308. /*---------------*/
  1309. case IRLAP_XID_RSP:
  1310. /*---------------*/
  1311. {
  1312. UCHAR XIDFormatID;
  1313. IRLAP_XID_DSCV_FORMAT *pXIDFormat;
  1314. //
  1315. // make sure frame is big enough
  1316. //
  1317. // AC + FI + SRC + DEST + FLAGS + SLOT + Ver
  1318. //
  1319. if (FrameLength < 2 + 1 + 4 + 4 + 1 + 1 + 1) {
  1320. //
  1321. // too small
  1322. //
  1323. IRLAP_LOG_ACTION((pIrlapCb,TEXT("Received XID frmae to small")));
  1324. ASSERT(0);
  1325. return;
  1326. }
  1327. //
  1328. // we know the frame is big enough get some of the info
  1329. //
  1330. XIDFormatID = *(pMsg->IRDA_MSG_pRead+2);
  1331. pXIDFormat = (IRLAP_XID_DSCV_FORMAT *)(pMsg->IRDA_MSG_pRead + 3);
  1332. if (XIDFormatID == IRLAP_XID_DSCV_FORMAT_ID)
  1333. {
  1334. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: DscvXidRsp)")));
  1335. ProcessDscvXIDRsp(pIrlapCb, pXIDFormat,pMsg->IRDA_MSG_pWrite);
  1336. return;
  1337. }
  1338. else
  1339. {
  1340. return; // ignore per errata
  1341. }
  1342. return;
  1343. }
  1344. /*------------*/
  1345. case IRLAP_SNRM: // or IRLAP_RNRM
  1346. /*------------*/
  1347. {
  1348. IRLAP_SNRM_FORMAT *pSNRMFormat = (IRLAP_SNRM_FORMAT *)(pMsg->IRDA_MSG_pRead + 2);
  1349. if (IRLAP_PFBIT_SET != PFBit)
  1350. {
  1351. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received SNRM/RNRM without P set")));
  1352. return;// IRLAP_SNRM_NOT_P;
  1353. }
  1354. if (IRLAP_CMD == CRBit)
  1355. {
  1356. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: SNRM)")));
  1357. ProcessSNRM(pIrlapCb, pSNRMFormat, pMsg->IRDA_MSG_pWrite);
  1358. return;
  1359. }
  1360. else
  1361. {
  1362. ProcessRNRM(pIrlapCb);
  1363. return;
  1364. }
  1365. return;
  1366. }
  1367. /*----------*/
  1368. case IRLAP_UA:
  1369. /*----------*/
  1370. {
  1371. IRLAP_UA_FORMAT *pUAFormat = (IRLAP_UA_FORMAT *)(pMsg->IRDA_MSG_pRead + 2);
  1372. if (CRBit != IRLAP_RSP)
  1373. {
  1374. IRLAP_LOG_ACTION((pIrlapCb,TEXT("Received UA as a command")));
  1375. return;// IRLAP_UA_NOT_RSP;
  1376. }
  1377. if (PFBit != IRLAP_PFBIT_SET)
  1378. {
  1379. IRLAP_LOG_ACTION((pIrlapCb,TEXT("Received UA without F set")));
  1380. return;// IRLAP_UA_NOT_F;
  1381. }
  1382. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: UA)")));
  1383. ProcessUA(pIrlapCb, pUAFormat, pMsg->IRDA_MSG_pWrite);
  1384. return;
  1385. }
  1386. /*------------*/
  1387. case IRLAP_DISC: // or IRLAP_RD
  1388. /*------------*/
  1389. if (IRLAP_PFBIT_SET != PFBit)
  1390. {
  1391. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Received DISC/RD command without Poll set")));
  1392. return;// IRLAP_DISC_CMD_NOT_P;
  1393. }
  1394. if (IRLAP_CMD == CRBit)
  1395. {
  1396. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: DISC)")));
  1397. ProcessDISC(pIrlapCb);
  1398. return;
  1399. }
  1400. else
  1401. {
  1402. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: RD)")));
  1403. ProcessRD(pIrlapCb);
  1404. return;
  1405. }
  1406. /*----------*/
  1407. case IRLAP_UI:
  1408. /*----------*/
  1409. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: UI)")));
  1410. ProcessUI(pIrlapCb, pMsg, CRBit, PFBit);
  1411. return;
  1412. /*------------*/
  1413. case IRLAP_TEST:
  1414. /*------------*/
  1415. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: TEST)")));
  1416. return;
  1417. /*------------*/
  1418. case IRLAP_FRMR:
  1419. /*------------*/
  1420. if (IRLAP_RSP != CRBit)
  1421. {
  1422. IRLAP_LOG_ACTION((pIrlapCb,
  1423. TEXT("Received FRMR cmd (must be resp)")));
  1424. return;// IRLAP_FRMR_RSP_CMD;
  1425. }
  1426. if (IRLAP_PFBIT_SET != PFBit)
  1427. {
  1428. IRLAP_LOG_ACTION((pIrlapCb,
  1429. TEXT("Received FRMR resp without Final set")));
  1430. return;// IRLAP_FRMR_RSP_NOT_F;
  1431. }
  1432. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: FRMR)")));
  1433. ProcessFRMR(pIrlapCb);
  1434. return;
  1435. /*----------*/
  1436. case IRLAP_DM:
  1437. /*----------*/
  1438. if (IRLAP_RSP != CRBit)
  1439. {
  1440. IRLAP_LOG_ACTION((pIrlapCb,
  1441. TEXT("Received DM command (must be response)")));
  1442. return;// IRLAP_DM_RSP_CMD;
  1443. }
  1444. if (IRLAP_PFBIT_SET != PFBit)
  1445. {
  1446. IRLAP_LOG_ACTION((pIrlapCb,
  1447. TEXT("Received DM response without Final set")));
  1448. return;// IRLAP_DM_RSP_NOT_F;
  1449. }
  1450. IRLAP_LOG_ACTION((pIrlapCb, TEXT("(Rx: DM)")));
  1451. ProcessDM(pIrlapCb);
  1452. return;
  1453. }
  1454. break;
  1455. }
  1456. }
  1457. /*****************************************************************************
  1458. *
  1459. * ProcessDscvXIDCmd - Process received XID Discovery command
  1460. *
  1461. */
  1462. VOID
  1463. ProcessDscvXIDCmd(PIRLAP_CB pIrlapCb,
  1464. IRLAP_XID_DSCV_FORMAT *pXidFormat,
  1465. UCHAR *pEndDscvInfoUCHAR)
  1466. {
  1467. IRDA_MSG IMsg;
  1468. if (!MyDevAddr(pIrlapCb, pXidFormat->DestAddr))
  1469. {
  1470. /* IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring XID addressed to:%02X%02X%02X%02X"),
  1471. EXPAND_ADDR(pXidFormat->DestAddr)));*/
  1472. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring XID addressed to %X"),
  1473. pXidFormat->DestAddr));
  1474. return;
  1475. }
  1476. if (pXidFormat->SlotNo == IRLAP_END_DSCV_SLOT_NO)
  1477. {
  1478. pIrlapCb->GenNewAddr = FALSE;
  1479. switch (pIrlapCb->State)
  1480. {
  1481. case DSCV_QUERY:
  1482. IrlapTimerStop(pIrlapCb, &pIrlapCb->SlotTimer);
  1483. IMsg.Prim = IRLAP_DISCOVERY_CONF;
  1484. IMsg.IRDA_MSG_pDevList = NULL;
  1485. IMsg.IRDA_MSG_DscvStatus =
  1486. IRLAP_REMOTE_DISCOVERY_IN_PROGRESS;
  1487. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1488. // fall through. Send indication to LMP
  1489. case DSCV_REPLY:
  1490. if (pIrlapCb->State == DSCV_REPLY)
  1491. {
  1492. IrlapTimerStop(pIrlapCb, &pIrlapCb->QueryTimer);
  1493. }
  1494. // Place the device information in the control block
  1495. ExtractDeviceInfo(&pIrlapCb->RemoteDevice, pXidFormat,
  1496. pEndDscvInfoUCHAR);
  1497. if (!DevInDevList(pXidFormat->SrcAddr, &pIrlapCb->DevList))
  1498. {
  1499. AddDevToList(pIrlapCb, pXidFormat, pEndDscvInfoUCHAR);
  1500. }
  1501. // Notifiy LMP
  1502. pIrlapCb->State = NDM;
  1503. IMsg.Prim = IRLAP_DISCOVERY_IND;
  1504. IMsg.IRDA_MSG_pDevList = &pIrlapCb->DevList;
  1505. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1506. break;
  1507. default:
  1508. IRLAP_LOG_ACTION((pIrlapCb,
  1509. TEXT("Ignoring End XID in this state")));
  1510. }
  1511. }
  1512. else // in middle of discovery process
  1513. {
  1514. switch (pIrlapCb->State)
  1515. {
  1516. case DSCV_MEDIA_SENSE:
  1517. IMsg.Prim = IRLAP_DISCOVERY_CONF;
  1518. IMsg.IRDA_MSG_pDevList = NULL;
  1519. IMsg.IRDA_MSG_DscvStatus =
  1520. IRLAP_REMOTE_DISCOVERY_IN_PROGRESS;
  1521. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1522. // fall through
  1523. case NDM:
  1524. InitDscvCmdProcessing(pIrlapCb, pXidFormat);
  1525. pIrlapCb->State = DSCV_REPLY;
  1526. break;
  1527. case DSCV_QUERY:
  1528. pIrlapCb->State = NDM;
  1529. IMsg.Prim = IRLAP_DISCOVERY_CONF;
  1530. IMsg.IRDA_MSG_pDevList = NULL;
  1531. IMsg.IRDA_MSG_DscvStatus = IRLAP_DISCOVERY_COLLISION;
  1532. IrlapTimerStop(pIrlapCb, &pIrlapCb->SlotTimer);
  1533. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1534. break;
  1535. case DSCV_REPLY:
  1536. if (pXidFormat->GenNewAddr)
  1537. {
  1538. pIrlapCb->GenNewAddr = TRUE;
  1539. IrlapTimerStop(pIrlapCb, &pIrlapCb->QueryTimer);
  1540. InitDscvCmdProcessing(pIrlapCb, pXidFormat);
  1541. }
  1542. else
  1543. {
  1544. if (pIrlapCb->RespSlot <= pXidFormat->SlotNo &&
  1545. !pIrlapCb->DscvRespSent)
  1546. {
  1547. SendDscvXIDRsp(pIrlapCb);
  1548. pIrlapCb->DscvRespSent = TRUE;
  1549. }
  1550. }
  1551. break;
  1552. default:
  1553. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  1554. }
  1555. }
  1556. return;
  1557. }
  1558. /*****************************************************************************
  1559. *
  1560. *
  1561. */
  1562. void
  1563. ExtractDeviceInfo(IRDA_DEVICE *pDevice, IRLAP_XID_DSCV_FORMAT *pXidFormat,
  1564. UCHAR *pEndDscvInfoUCHAR)
  1565. {
  1566. PAGED_CODE();
  1567. CTEMemCopy(pDevice->DevAddr, pXidFormat->SrcAddr, IRDA_DEV_ADDR_LEN);
  1568. pDevice->IRLAP_Version = pXidFormat->Version;
  1569. // ??? what about DscvMethod
  1570. pDevice->DscvInfoLen =
  1571. pEndDscvInfoUCHAR > &pXidFormat->FirstDscvInfoByte ?
  1572. (int) (pEndDscvInfoUCHAR-&pXidFormat->FirstDscvInfoByte) : 0;
  1573. if (pDevice->DscvInfoLen > IRLAP_DSCV_INFO_LEN)
  1574. {
  1575. pDevice->DscvInfoLen = IRLAP_DSCV_INFO_LEN;
  1576. }
  1577. CTEMemCopy(pDevice->DscvInfo, &pXidFormat->FirstDscvInfoByte,
  1578. pDevice->DscvInfoLen);
  1579. }
  1580. /*****************************************************************************
  1581. *
  1582. *
  1583. */
  1584. VOID
  1585. InitDscvCmdProcessing(PIRLAP_CB pIrlapCb,
  1586. IRLAP_XID_DSCV_FORMAT *pXidFormat)
  1587. {
  1588. pIrlapCb->RemoteMaxSlot = IrlapSlotTable[pXidFormat->NoOfSlots & 0x3];
  1589. pIrlapCb->RespSlot = IRLAP_RAND(pXidFormat->SlotNo,
  1590. pIrlapCb->RemoteMaxSlot - 1);
  1591. CTEMemCopy(pIrlapCb->RemoteDevice.DevAddr, pXidFormat->SrcAddr,
  1592. IRDA_DEV_ADDR_LEN);
  1593. IRLAP_LOG_ACTION((pIrlapCb,
  1594. TEXT("Responding in slot %d to dev %02X%02X%02X%02X"),
  1595. pIrlapCb->RespSlot,
  1596. pIrlapCb->RemoteDevice.DevAddr[0],
  1597. pIrlapCb->RemoteDevice.DevAddr[1],
  1598. pIrlapCb->RemoteDevice.DevAddr[2],
  1599. pIrlapCb->RemoteDevice.DevAddr[3]));
  1600. if (pIrlapCb->RespSlot == pXidFormat->SlotNo)
  1601. {
  1602. SendDscvXIDRsp(pIrlapCb);
  1603. pIrlapCb->DscvRespSent = TRUE;
  1604. }
  1605. else
  1606. {
  1607. pIrlapCb->DscvRespSent = FALSE;
  1608. }
  1609. IrlapTimerStart(pIrlapCb, &pIrlapCb->QueryTimer);
  1610. }
  1611. /*****************************************************************************
  1612. *
  1613. */
  1614. VOID
  1615. ProcessDscvXIDRsp(PIRLAP_CB pIrlapCb,
  1616. IRLAP_XID_DSCV_FORMAT *pXidFormat,
  1617. UCHAR *pEndDscvInfoUCHAR)
  1618. {
  1619. IRDA_MSG IMsg;
  1620. if (pIrlapCb->State == DSCV_QUERY)
  1621. {
  1622. if (DevInDevList(pXidFormat->SrcAddr, &pIrlapCb->DevList))
  1623. {
  1624. IrlapTimerStop(pIrlapCb, &pIrlapCb->SlotTimer);
  1625. pIrlapCb->SlotCnt = 0;
  1626. pIrlapCb->GenNewAddr = TRUE;
  1627. FreeDevList(&pIrlapCb->DevList);
  1628. SendDscvXIDCmd(pIrlapCb);
  1629. IMsg.Prim = MAC_CONTROL_REQ;
  1630. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  1631. IMsg.IRDA_MSG_SenseTime = IRLAP_DSCV_SENSE_TIME;
  1632. IRLAP_LOG_ACTION((pIrlapCb,
  1633. TEXT("MAC_CONTROL_REQ (dscv sense)")));
  1634. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  1635. }
  1636. else
  1637. {
  1638. AddDevToList(pIrlapCb, pXidFormat, pEndDscvInfoUCHAR);
  1639. }
  1640. }
  1641. else
  1642. {
  1643. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  1644. }
  1645. }
  1646. /*****************************************************************************
  1647. *
  1648. * DevInDevList - Determines if given device is already in list
  1649. *
  1650. */
  1651. BOOLEAN
  1652. DevInDevList(UCHAR DevAddr[], LIST_ENTRY *pDevList)
  1653. {
  1654. IRDA_DEVICE *pDevice;
  1655. pDevice = (IRDA_DEVICE *) pDevList->Flink;
  1656. while (pDevList != (LIST_ENTRY *) pDevice)
  1657. {
  1658. if (CTEMemCmp(pDevice->DevAddr, DevAddr,
  1659. IRDA_DEV_ADDR_LEN) == 0)
  1660. return (TRUE);
  1661. pDevice = (IRDA_DEVICE *) pDevice->Linkage.Flink;
  1662. }
  1663. return (FALSE);
  1664. }
  1665. /*****************************************************************************
  1666. *
  1667. * AddDevToList - Adds elements in a device list
  1668. *
  1669. */
  1670. VOID
  1671. AddDevToList(PIRLAP_CB pIrlapCb,
  1672. IRLAP_XID_DSCV_FORMAT *pXidFormat,
  1673. UCHAR *pEndDscvInfoUCHAR)
  1674. {
  1675. IRDA_DEVICE *pDevice;
  1676. if (IRDA_ALLOC_MEM(pDevice, sizeof(IRDA_DEVICE), MT_IRLAP_DEVICE) == NULL)
  1677. {
  1678. ASSERT(0);
  1679. return;// (IRLAP_MALLOC_FAILED);
  1680. }
  1681. else
  1682. {
  1683. ExtractDeviceInfo(pDevice, pXidFormat, pEndDscvInfoUCHAR);
  1684. InsertTailList(&pIrlapCb->DevList, &(pDevice->Linkage));
  1685. IRLAP_LOG_ACTION((pIrlapCb,
  1686. TEXT("%02X%02X%02X%02X added to Device List"),
  1687. EXPAND_ADDR(pDevice->DevAddr)));
  1688. }
  1689. }
  1690. /*****************************************************************************
  1691. *
  1692. */
  1693. void
  1694. FreeDevList(LIST_ENTRY *pDevList)
  1695. {
  1696. IRDA_DEVICE *pDevice;
  1697. PAGED_CODE();
  1698. while (IsListEmpty(pDevList) == FALSE)
  1699. {
  1700. pDevice = (IRDA_DEVICE *) RemoveHeadList(pDevList);
  1701. IRDA_FREE_MEM(pDevice);
  1702. }
  1703. //IRLAP_LOG_ACTION((pIrlapCb, TEXT("Device list cleared")));
  1704. }
  1705. /*****************************************************************************
  1706. *
  1707. */
  1708. int
  1709. AddressGreaterThan(UCHAR A1[], UCHAR A2[])
  1710. {
  1711. int i;
  1712. for (i = 0; i < IRDA_DEV_ADDR_LEN; i++)
  1713. {
  1714. if (A1[i] > A2[i])
  1715. return TRUE;
  1716. if (A1[i] != A2[1])
  1717. return FALSE;
  1718. }
  1719. return FALSE;
  1720. }
  1721. /*****************************************************************************
  1722. *
  1723. */
  1724. VOID
  1725. ProcessSNRM(PIRLAP_CB pIrlapCb,
  1726. IRLAP_SNRM_FORMAT *pSnrmFormat,
  1727. UCHAR *pEndQosUCHAR)
  1728. {
  1729. IRDA_MSG IMsg;
  1730. BOOLEAN QosInSNRM = &pSnrmFormat->FirstQosByte < pEndQosUCHAR;
  1731. BOOLEAN AddrsInSNRM = ((UCHAR *)pSnrmFormat)+8 < pEndQosUCHAR;
  1732. UINT rc;
  1733. PAGED_CODE();
  1734. if (AddrsInSNRM)
  1735. {
  1736. if (!MyDevAddr(pIrlapCb, pSnrmFormat->DestAddr))
  1737. {
  1738. IRLAP_LOG_ACTION((pIrlapCb,
  1739. TEXT("Ignoring SNRM addressed to:%02X%02X%02X%02X"),
  1740. EXPAND_ADDR(pSnrmFormat->DestAddr)));
  1741. return;
  1742. }
  1743. CTEMemCopy(pIrlapCb->RemoteDevice.DevAddr,
  1744. pSnrmFormat->SrcAddr, IRDA_DEV_ADDR_LEN);
  1745. }
  1746. switch (pIrlapCb->State)
  1747. {
  1748. case DSCV_MEDIA_SENSE:
  1749. case DSCV_QUERY:
  1750. // In the middle of discovery... End discovery and reply to SNRM
  1751. IMsg.Prim = IRLAP_DISCOVERY_CONF;
  1752. IMsg.IRDA_MSG_pDevList = NULL;
  1753. IMsg.IRDA_MSG_DscvStatus = IRLAP_REMOTE_CONNECTION_IN_PROGRESS;
  1754. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1755. // fall through and send connect indication
  1756. case DSCV_REPLY:
  1757. case NDM:
  1758. if (pIrlapCb->State == DSCV_REPLY)
  1759. {
  1760. IrlapTimerStop(pIrlapCb, &pIrlapCb->QueryTimer);
  1761. }
  1762. if (AddrsInSNRM)
  1763. {
  1764. pIrlapCb->SNRMConnAddr =
  1765. (int)IRLAP_GET_ADDR(pSnrmFormat->ConnAddr);
  1766. }
  1767. if (QosInSNRM)
  1768. {
  1769. ExtractQosParms(&pIrlapCb->RemoteQos, &pSnrmFormat->FirstQosByte,
  1770. pEndQosUCHAR);
  1771. if ((rc = NegotiateQosParms(pIrlapCb, &pIrlapCb->RemoteQos)))
  1772. {
  1773. DEBUGMSG(DBG_IRLAP, (TEXT("IRLAP: SNRM/UA negotiation failed, rc=%d\n"), rc));
  1774. #if DBG
  1775. DbgPrint("IRLAP: SNRM/UA negotiation failed, rc=%d\n", rc);
  1776. #endif
  1777. return;
  1778. }
  1779. }
  1780. CTEMemCopy(IMsg.IRDA_MSG_RemoteDevAddr,
  1781. pIrlapCb->RemoteDevice.DevAddr, IRDA_DEV_ADDR_LEN);
  1782. IMsg.IRDA_MSG_pQos = &pIrlapCb->NegotiatedQos;
  1783. IMsg.Prim = IRLAP_CONNECT_IND;
  1784. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1785. pIrlapCb->State = SNRM_RECEIVED;
  1786. break;
  1787. case BACKOFF_WAIT: // CROSSED SNRM
  1788. // if Remote address greater than mine we'll respond to SNRM
  1789. if (AddrsInSNRM)
  1790. {
  1791. if (AddressGreaterThan(pSnrmFormat->SrcAddr,
  1792. pIrlapCb->LocalDevice.DevAddr))
  1793. {
  1794. IrlapTimerStop(pIrlapCb, &pIrlapCb->BackoffTimer);
  1795. }
  1796. }
  1797. // fall through
  1798. case CONN_MEDIA_SENSE: // CROSSED SNRM
  1799. case SNRM_SENT:
  1800. // if Remote address greater than mine we'll respond to SNRM
  1801. if (AddrsInSNRM && AddressGreaterThan(pSnrmFormat->SrcAddr,
  1802. pIrlapCb->LocalDevice.DevAddr))
  1803. {
  1804. if (pIrlapCb->State != BACKOFF_WAIT)
  1805. {
  1806. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  1807. }
  1808. InitializeState(pIrlapCb, SECONDARY);
  1809. if (QosInSNRM)
  1810. {
  1811. ExtractQosParms(&pIrlapCb->RemoteQos,
  1812. &pSnrmFormat->FirstQosByte, pEndQosUCHAR);
  1813. if ((rc = NegotiateQosParms(pIrlapCb, &pIrlapCb->RemoteQos)))
  1814. {
  1815. DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: SNRM/UA negotiation failed, rc=%d\n"), rc));
  1816. ASSERT(0);
  1817. pIrlapCb->State = NDM;
  1818. return;
  1819. }
  1820. }
  1821. if (AddrsInSNRM)
  1822. {
  1823. pIrlapCb->ConnAddr =
  1824. (int)IRLAP_GET_ADDR(pSnrmFormat->ConnAddr);
  1825. }
  1826. SendUA(pIrlapCb, TRUE);
  1827. if (QosInSNRM)
  1828. {
  1829. ApplyQosParms(pIrlapCb);
  1830. }
  1831. IMsg.IRDA_MSG_pQos = &pIrlapCb->NegotiatedQos;
  1832. IMsg.Prim = IRLAP_CONNECT_CONF;
  1833. IMsg.IRDA_MSG_ConnStatus = IRLAP_CONNECTION_COMPLETED;
  1834. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1835. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  1836. pIrlapCb->State = S_NRM;
  1837. }
  1838. break;
  1839. case P_RECV:
  1840. case P_DISCONNECT_PEND:
  1841. case P_CLOSE:
  1842. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  1843. pIrlapCb->State = NDM;
  1844. StationConflict(pIrlapCb);
  1845. ReturnRxTxWinMsgs(pIrlapCb);
  1846. if (pIrlapCb->State == P_CLOSE)
  1847. {
  1848. GotoNDMThenDscvOrConn(pIrlapCb);
  1849. }
  1850. break;
  1851. case S_NRM:
  1852. case S_CLOSE:
  1853. case S_DISCONNECT_PEND:
  1854. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  1855. SendDM(pIrlapCb);
  1856. ApplyDefaultParms(pIrlapCb);
  1857. IMsg.Prim = IRLAP_DISCONNECT_IND;
  1858. if (pIrlapCb->State == S_NRM)
  1859. {
  1860. IMsg.IRDA_MSG_DiscStatus = IRLAP_DECLINE_RESET;
  1861. }
  1862. else
  1863. {
  1864. IMsg.IRDA_MSG_DiscStatus = IRLAP_DISCONNECT_COMPLETED;
  1865. }
  1866. pIrlapCb->State = NDM;
  1867. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1868. break;
  1869. case S_ERROR:
  1870. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  1871. SendFRMR(pIrlapCb, &pIrlapCb->Frmr);
  1872. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  1873. pIrlapCb->State = S_NRM;
  1874. break;
  1875. default:
  1876. IRLAP_LOG_ACTION((pIrlapCb, TEXT("SNRM ignored in this state")));
  1877. }
  1878. return;
  1879. }
  1880. /*****************************************************************************
  1881. *
  1882. */
  1883. VOID
  1884. ProcessUA(PIRLAP_CB pIrlapCb,
  1885. IRLAP_UA_FORMAT *pUAFormat,
  1886. UCHAR *pEndQosUCHAR)
  1887. {
  1888. BOOLEAN QosInUA = &pUAFormat->FirstQosByte < pEndQosUCHAR;
  1889. BOOLEAN AddrsInUA = (UCHAR *)pUAFormat+8 < pEndQosUCHAR;
  1890. int Tmp;
  1891. IRDA_MSG IMsg;
  1892. UINT rc;
  1893. PAGED_CODE();
  1894. if (AddrsInUA && !MyDevAddr(pIrlapCb, pUAFormat->DestAddr))
  1895. {
  1896. IRLAP_LOG_ACTION((pIrlapCb,
  1897. TEXT("Ignoring UA addressed to:%02X%02X%02X%02X"),
  1898. EXPAND_ADDR(pUAFormat->DestAddr)));
  1899. return;
  1900. }
  1901. switch (pIrlapCb->State)
  1902. {
  1903. case BACKOFF_WAIT:
  1904. IrlapTimerStop(pIrlapCb, &pIrlapCb->BackoffTimer);
  1905. // fall through
  1906. case SNRM_SENT:
  1907. if (pIrlapCb->State != BACKOFF_WAIT)
  1908. {
  1909. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  1910. }
  1911. InitializeState(pIrlapCb, PRIMARY);
  1912. if (QosInUA)
  1913. {
  1914. ExtractQosParms(&pIrlapCb->RemoteQos, &pUAFormat->FirstQosByte,
  1915. pEndQosUCHAR);
  1916. if ((rc = NegotiateQosParms(pIrlapCb, &pIrlapCb->RemoteQos)))
  1917. {
  1918. DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: SNRM/UA negotiation failed, rc=%d\n"), rc));
  1919. ASSERT(0);
  1920. pIrlapCb->State = NDM;
  1921. return;
  1922. }
  1923. ApplyQosParms(pIrlapCb);
  1924. }
  1925. IMsg.IRDA_MSG_pQos = &pIrlapCb->NegotiatedQos;
  1926. IMsg.Prim = IRLAP_CONNECT_CONF;
  1927. IMsg.IRDA_MSG_ConnStatus = IRLAP_CONNECTION_COMPLETED;
  1928. // notify LMP of connection
  1929. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1930. // send RR (turn link), start FinalTimer/2
  1931. SendRR_RNR(pIrlapCb);
  1932. Tmp = pIrlapCb->FinalTimer.Timeout;
  1933. pIrlapCb->FinalTimer.Timeout = pIrlapCb->FinalTimer.Timeout/2;
  1934. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  1935. pIrlapCb->FinalTimer.Timeout = Tmp;
  1936. pIrlapCb->State = P_RECV;
  1937. break;
  1938. case P_RECV: // Unsolicited UA, may want to do something else ???
  1939. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  1940. IrlapTimerStart(pIrlapCb, &pIrlapCb->PollTimer);
  1941. pIrlapCb->State = P_XMIT;
  1942. break;
  1943. case P_DISCONNECT_PEND:
  1944. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  1945. SendDISC(pIrlapCb);
  1946. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  1947. pIrlapCb->RetryCnt = 0;
  1948. GotoPCloseState(pIrlapCb);
  1949. break;
  1950. case P_CLOSE:
  1951. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  1952. ApplyDefaultParms(pIrlapCb);
  1953. if (pIrlapCb->LocalDiscReq == TRUE)
  1954. {
  1955. pIrlapCb->LocalDiscReq = FALSE;
  1956. IMsg.Prim = IRLAP_DISCONNECT_IND;
  1957. IMsg.IRDA_MSG_DiscStatus = IRLAP_DISCONNECT_COMPLETED;
  1958. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  1959. }
  1960. GotoNDMThenDscvOrConn(pIrlapCb);
  1961. break;
  1962. case S_NRM:
  1963. case S_DISCONNECT_PEND:
  1964. case S_ERROR:
  1965. case S_CLOSE:
  1966. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  1967. StationConflict(pIrlapCb);
  1968. pIrlapCb->State = NDM;
  1969. break;
  1970. default:
  1971. IRLAP_LOG_ACTION((pIrlapCb, TEXT("UA ignored in this state")));
  1972. }
  1973. }
  1974. UCHAR *
  1975. GetPv(UCHAR *pQosUCHAR,
  1976. UINT *pBitField)
  1977. {
  1978. int Pl = (int) *pQosUCHAR++;
  1979. *pBitField = 0;
  1980. if (Pl == 1)
  1981. {
  1982. *pBitField = (UINT) *pQosUCHAR;
  1983. }
  1984. else
  1985. {
  1986. *pBitField = ((UINT) *(pQosUCHAR+1))<<8;
  1987. *pBitField |= (UINT) *(pQosUCHAR);
  1988. }
  1989. return pQosUCHAR + Pl;
  1990. }
  1991. /*****************************************************************************
  1992. *
  1993. * THIS WILL BREAK IF PARAMETER LENGTH (PL) IS GREATER THAN 2
  1994. */
  1995. void
  1996. ExtractQosParms(IRDA_QOS_PARMS *pQos,
  1997. UCHAR *pQosUCHAR,
  1998. UCHAR *pEndQosUCHAR)
  1999. {
  2000. PAGED_CODE();
  2001. while (pQosUCHAR + 2 < pEndQosUCHAR)
  2002. {
  2003. switch (*pQosUCHAR)
  2004. {
  2005. case QOS_PI_BAUD:
  2006. pQosUCHAR = GetPv(pQosUCHAR+1, &pQos->bfBaud);
  2007. break;
  2008. case QOS_PI_MAX_TAT:
  2009. pQosUCHAR = GetPv(pQosUCHAR+1, &pQos->bfMaxTurnTime);
  2010. break;
  2011. case QOS_PI_DATA_SZ:
  2012. pQosUCHAR = GetPv(pQosUCHAR+1, &pQos->bfDataSize);
  2013. break;
  2014. case QOS_PI_WIN_SZ:
  2015. pQosUCHAR = GetPv(pQosUCHAR+1, &pQos->bfWindowSize);
  2016. break;
  2017. case QOS_PI_BOFS:
  2018. pQosUCHAR = GetPv(pQosUCHAR+1, &pQos->bfBofs);
  2019. break;
  2020. case QOS_PI_MIN_TAT:
  2021. pQosUCHAR = GetPv(pQosUCHAR+1, &pQos->bfMinTurnTime);
  2022. break;
  2023. case QOS_PI_DISC_THRESH:
  2024. pQosUCHAR = GetPv(pQosUCHAR+1, &pQos->bfDisconnectTime);
  2025. break;
  2026. default:
  2027. DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: Invalid Qos parameter type %X\n"), *pQosUCHAR));
  2028. ASSERT(0);
  2029. pQosUCHAR = pEndQosUCHAR;
  2030. }
  2031. }
  2032. }
  2033. /*****************************************************************************
  2034. *
  2035. * @func UINT | NegotiateQosParms | Take the received Qos build
  2036. * negotiated Qos.
  2037. *
  2038. * @rdesc SUCCESS, otherwise one of the folowing:
  2039. * @flag IRLAP_BAUD_NEG_ERR | Failed to negotiate baud
  2040. * @flag IRLAP_DISC_NEG_ERR | Failed to negotiate disconnect time
  2041. * @flag IRLAP_MAXTAT_NEG_ERR | Failed to negotiate max turn time
  2042. * @flag IRLAP_DATASIZE_NEG_ERR | Failed to negotiate data size
  2043. * @flag IRLAP_WINSIZE_NEG_ERR | Failed to negotiate window size
  2044. * @flag IRLAP_BOFS_NEG_ERR | Failed to negotiate number of BOFS
  2045. * @flag IRLAP_WINSIZE_NEG_ERR | Failed to window size
  2046. * @flag IRLAP_LINECAP_ERR | Failed to determine valid line capacity
  2047. *
  2048. * @parm IRDA_QOS_PARMS * | pRemoteQos | Pointer to QOS parm struct
  2049. */
  2050. UINT
  2051. NegotiateQosParms(PIRLAP_CB pIrlapCb,
  2052. IRDA_QOS_PARMS *pRemoteQos)
  2053. {
  2054. UINT BitSet;
  2055. BOOLEAN ParmSet = FALSE;
  2056. UINT BOFSDivisor = 1;
  2057. UINT MaxLineCap = 0;
  2058. UINT LineCapacity;
  2059. UINT DataSizeBit = 0;
  2060. UINT WinSizeBit = 0;
  2061. #ifdef GET_LARGEST_DATA_SIZE
  2062. UINT WSBit;
  2063. #else
  2064. UINT DataBit;
  2065. #endif
  2066. int RemoteDataSize = 0;
  2067. int RemoteWinSize = 0;
  2068. PAGED_CODE();
  2069. // Baud rate is Type 0 parm
  2070. pIrlapCb->Baud = IrlapGetQosParmVal(vBaudTable,
  2071. pIrlapCb->LocalQos.bfBaud & pRemoteQos->bfBaud,
  2072. &BitSet);
  2073. BOFSDivisor = IrlapGetQosParmVal(vBOFSDivTable,
  2074. pIrlapCb->LocalQos.bfBaud & pRemoteQos->bfBaud,
  2075. &BitSet);
  2076. pIrlapCb->NegotiatedQos.bfBaud = BitSet;
  2077. if (-1 == pIrlapCb->Baud)
  2078. {
  2079. return IRLAP_BAUD_NEG_ERR;
  2080. }
  2081. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Negotiated Baud:%d"), pIrlapCb->Baud));
  2082. // Disconnect/Threshold time is Type 0 parm
  2083. pIrlapCb->DisconnectTime = IrlapGetQosParmVal(vDiscTable,
  2084. pIrlapCb->LocalQos.bfDisconnectTime & pRemoteQos->bfDisconnectTime,
  2085. &BitSet);
  2086. pIrlapCb->ThresholdTime = IrlapGetQosParmVal(vThreshTable,
  2087. pIrlapCb->LocalQos.bfDisconnectTime & pRemoteQos->bfDisconnectTime,
  2088. &BitSet);
  2089. pIrlapCb->NegotiatedQos.bfDisconnectTime = BitSet;
  2090. if (-1 == pIrlapCb->DisconnectTime)
  2091. {
  2092. return IRLAP_DISC_NEG_ERR;
  2093. }
  2094. IRLAP_LOG_ACTION((pIrlapCb,
  2095. TEXT("Negotiated Disconnect/Threshold time:%d/%d"),
  2096. pIrlapCb->DisconnectTime, pIrlapCb->ThresholdTime));
  2097. pIrlapCb->RemoteMaxTAT = IrlapGetQosParmVal(vMaxTATTable,
  2098. pRemoteQos->bfMaxTurnTime,
  2099. &BitSet);
  2100. pIrlapCb->NegotiatedQos.bfMaxTurnTime = BitSet;
  2101. if (-1 == pIrlapCb->RemoteMaxTAT)
  2102. {
  2103. return IRLAP_MAXTAT_NEG_ERR;
  2104. }
  2105. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Remote max turnaround time:%d"),
  2106. pIrlapCb->RemoteMaxTAT));
  2107. pIrlapCb->RemoteMinTAT = IrlapGetQosParmVal(vMinTATTable,
  2108. pRemoteQos->bfMinTurnTime,
  2109. &BitSet);
  2110. pIrlapCb->NegotiatedQos.bfMinTurnTime = BitSet;
  2111. if (-1 == pIrlapCb->RemoteMinTAT)
  2112. {
  2113. return IRLAP_MINTAT_NEG_ERR;
  2114. }
  2115. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Remote min turnaround time:%d"),
  2116. pIrlapCb->RemoteMinTAT));
  2117. // DataSize ISNOT A TYPE 0 PARAMETER. BUT WIN95's IRCOMM implementation
  2118. // ASSUMES THAT IT IS. SO FOR NOW, NEGOTIATE IT. grrrr..
  2119. /* WIN95 out
  2120. pIrlapCb->RemoteDataSize = IrlapGetQosParmVal(vDataSizeTable,
  2121. (UCHAR) (pIrlapCb->LocalQos.bfDataSize &
  2122. pRemoteQos->bfDataSize), &BitSet);
  2123. */
  2124. pIrlapCb->RemoteDataSize = IrlapGetQosParmVal(vDataSizeTable,
  2125. pRemoteQos->bfDataSize, &BitSet);
  2126. DataSizeBit = BitSet;
  2127. pIrlapCb->NegotiatedQos.bfDataSize = BitSet;
  2128. if (-1 == pIrlapCb->RemoteDataSize)
  2129. {
  2130. return IRLAP_DATASIZE_NEG_ERR;
  2131. }
  2132. IRLAP_LOG_ACTION((pIrlapCb,
  2133. TEXT("Remote data size:%d"), pIrlapCb->RemoteDataSize));
  2134. pIrlapCb->RemoteWinSize = IrlapGetQosParmVal(vWinSizeTable,
  2135. pRemoteQos->bfWindowSize, &BitSet);
  2136. WinSizeBit = BitSet;
  2137. pIrlapCb->NegotiatedQos.bfWindowSize = BitSet;
  2138. if (-1 == pIrlapCb->RemoteWinSize)
  2139. {
  2140. return IRLAP_WINSIZE_NEG_ERR;
  2141. }
  2142. IRLAP_LOG_ACTION((pIrlapCb,
  2143. TEXT("Remote window size:%d"),
  2144. pIrlapCb->RemoteWinSize));
  2145. pIrlapCb->RemoteNumBOFS=(IrlapGetQosParmVal(vBOFSTable,
  2146. pRemoteQos->bfBofs, &BitSet)
  2147. / BOFSDivisor)+1;
  2148. pIrlapCb->NegotiatedQos.bfBofs = BitSet;
  2149. if (-1 == pIrlapCb->RemoteNumBOFS)
  2150. {
  2151. return IRLAP_BOFS_NEG_ERR;
  2152. }
  2153. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Remote number of BOFS:%d"),
  2154. pIrlapCb->RemoteNumBOFS));
  2155. // The maximum line capacity is in UCHARs and comes from a table in spec.
  2156. // (can't calc because table isn't linear). It is determined by the
  2157. // maximum line capacity and baud rate.
  2158. //
  2159. // Later note: Errata corrected table so values could be calculated.
  2160. // Could get rid of tables
  2161. switch (pIrlapCb->Baud)
  2162. {
  2163. case 9600:
  2164. MaxLineCap = IrlapGetQosParmVal(MAXCAP_9600,
  2165. pRemoteQos->bfMaxTurnTime, &BitSet);
  2166. break;
  2167. case 19200:
  2168. MaxLineCap = IrlapGetQosParmVal(MAXCAP_19200,
  2169. pRemoteQos->bfMaxTurnTime, &BitSet);
  2170. break;
  2171. case 38400:
  2172. MaxLineCap = IrlapGetQosParmVal(MAXCAP_38400,
  2173. pRemoteQos->bfMaxTurnTime, &BitSet);
  2174. break;
  2175. case 57600:
  2176. MaxLineCap = IrlapGetQosParmVal(MAXCAP_57600,
  2177. pRemoteQos->bfMaxTurnTime, &BitSet);
  2178. break;
  2179. case 115200:
  2180. MaxLineCap = IrlapGetQosParmVal(MAXCAP_115200,
  2181. pRemoteQos->bfMaxTurnTime, &BitSet);
  2182. break;
  2183. case 576000:
  2184. MaxLineCap = IrlapGetQosParmVal(MAXCAP_576000,
  2185. pRemoteQos->bfMaxTurnTime, &BitSet);
  2186. break;
  2187. case 1152000:
  2188. MaxLineCap = IrlapGetQosParmVal(MAXCAP_1152000,
  2189. pRemoteQos->bfMaxTurnTime, &BitSet);
  2190. break;
  2191. case 4000000:
  2192. MaxLineCap = IrlapGetQosParmVal(MAXCAP_4000000,
  2193. pRemoteQos->bfMaxTurnTime, &BitSet);
  2194. break;
  2195. case 16000000:
  2196. MaxLineCap = IrlapGetQosParmVal(MAXCAP_16000000,
  2197. pRemoteQos->bfMaxTurnTime, &BitSet);
  2198. break;
  2199. default:
  2200. ASSERT(0);
  2201. }
  2202. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Maximum line capacity:%d"), MaxLineCap));
  2203. LineCapacity = LINE_CAPACITY(pIrlapCb);
  2204. IRLAP_LOG_ACTION((pIrlapCb,
  2205. TEXT("Requested line capacity:%d"), LineCapacity));
  2206. if (LineCapacity > MaxLineCap)
  2207. {
  2208. ParmSet = FALSE;
  2209. // Adjust data and window size to fit within the line capacity.
  2210. #ifdef GET_LARGEST_DATA_SIZE
  2211. // Get largest possible datasize
  2212. for (; DataSizeBit != 0 && !ParmSet; DataSizeBit >>= 1)
  2213. {
  2214. pIrlapCb->RemoteDataSize = IrlapGetQosParmVal(vDataSizeTable,
  2215. DataSizeBit, NULL);
  2216. // Start with smallest window
  2217. for (WSBit=1; WSBit <= WinSizeBit; WSBit <<=1)
  2218. {
  2219. pIrlapCb->RemoteWinSize = IrlapGetQosParmVal(vWinSizeTable,
  2220. WSBit, NULL);
  2221. LineCapacity = LINE_CAPACITY(pIrlapCb);
  2222. IRLAP_LOG_ACTION((pIrlapCb,
  2223. TEXT("adjusted data size=%d, window size= %d, line cap=%d"),
  2224. pIrlapCb->RemoteDataSize, pIrlapCb->RemoteWinSize,
  2225. LineCapacity));
  2226. if (LineCapacity > MaxLineCap)
  2227. {
  2228. // Get a smaller data size (only if ParmSet is false)
  2229. break;
  2230. }
  2231. ParmSet = TRUE;
  2232. // Save the last good one,then loop and try a larger window
  2233. RemoteDataSize = pIrlapCb->RemoteDataSize;
  2234. RemoteWinSize = pIrlapCb->RemoteWinSize;
  2235. pIrlapCb->NegotiatedQos.bfWindowSize = WSBit;
  2236. pIrlapCb->NegotiatedQos.bfDataSize = DataSizeBit;
  2237. }
  2238. }
  2239. #else
  2240. // Get largest possible windowsize
  2241. for (; WinSizeBit != 0 && !ParmSet; WinSizeBit >>= 1)
  2242. {
  2243. pIrlapCb->RemoteWinSize = IrlapGetQosParmVal(vWinSizeTable,
  2244. WinSizeBit, NULL);
  2245. // Start with smallest datasize
  2246. for (DataBit=1; DataBit <= DataSizeBit; DataBit <<=1)
  2247. {
  2248. pIrlapCb->RemoteDataSize = IrlapGetQosParmVal(vDataSizeTable,
  2249. DataBit, NULL);
  2250. LineCapacity = LINE_CAPACITY(pIrlapCb);
  2251. IRLAP_LOG_ACTION((pIrlapCb,
  2252. TEXT("adjusted data size=%d, window size= %d, line cap=%d"),
  2253. pIrlapCb->RemoteDataSize, pIrlapCb->RemoteWinSize,
  2254. LineCapacity));
  2255. if (LineCapacity > MaxLineCap)
  2256. {
  2257. // Get a smaller window size (only if ParmSet is false)
  2258. break;
  2259. }
  2260. ParmSet = TRUE;
  2261. // Save the last good one,then loop and try a larger Data size
  2262. RemoteWinSize = pIrlapCb->RemoteWinSize;
  2263. RemoteDataSize = pIrlapCb->RemoteDataSize;
  2264. pIrlapCb->NegotiatedQos.bfDataSize = DataBit;
  2265. pIrlapCb->NegotiatedQos.bfWindowSize = WinSizeBit;
  2266. }
  2267. }
  2268. #endif
  2269. if (!ParmSet)
  2270. {
  2271. return IRLAP_LINECAP_ERR;
  2272. }
  2273. pIrlapCb->RemoteDataSize = RemoteDataSize;
  2274. pIrlapCb->RemoteWinSize = RemoteWinSize;
  2275. IRLAP_LOG_ACTION((pIrlapCb,
  2276. TEXT("final data size=%d, window size= %d, line cap=%d"),
  2277. pIrlapCb->RemoteDataSize, pIrlapCb->RemoteWinSize,
  2278. LINE_CAPACITY(pIrlapCb)));
  2279. }
  2280. return SUCCESS;
  2281. }
  2282. /*****************************************************************************
  2283. *
  2284. *
  2285. */
  2286. VOID
  2287. ApplyQosParms(PIRLAP_CB pIrlapCb)
  2288. {
  2289. IRDA_MSG IMsg;
  2290. PAGED_CODE();
  2291. pIrlapCb->PollTimer.Timeout = pIrlapCb->RemoteMaxTAT;
  2292. pIrlapCb->FinalTimer.Timeout = pIrlapCb->LocalMaxTAT;
  2293. if (pIrlapCb->Baud <= 115200)
  2294. {
  2295. pIrlapCb->FinalTimer.Timeout += 150; // fudge factor for SIR
  2296. }
  2297. // convert disconnect/threshold time to ms and divide by final timer
  2298. // to get number of retries
  2299. pIrlapCb->N1 = pIrlapCb->ThresholdTime * 1000 / pIrlapCb->FinalTimer.Timeout;
  2300. pIrlapCb->N2 = pIrlapCb->DisconnectTime * 1000 / pIrlapCb->FinalTimer.Timeout;
  2301. IMsg.Prim = MAC_CONTROL_REQ;
  2302. IMsg.IRDA_MSG_Op = MAC_RECONFIG_LINK;
  2303. IMsg.IRDA_MSG_Baud = pIrlapCb->Baud;
  2304. IMsg.IRDA_MSG_NumBOFs = pIrlapCb->RemoteNumBOFS; // Number of BOFS
  2305. // to add to tx
  2306. IMsg.IRDA_MSG_DataSize = pIrlapCb->RemoteDataSize; // Max rx size packet
  2307. // causes major heap
  2308. // problems later
  2309. IMsg.IRDA_MSG_MinTat = pIrlapCb->RemoteMinTAT;
  2310. IRLAP_LOG_ACTION((pIrlapCb,
  2311. TEXT("Reconfig link for Baud:%d, Remote BOFS:%d"),
  2312. pIrlapCb->Baud, pIrlapCb->RemoteNumBOFS));
  2313. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Retry counts N1=%d, N2=%d"),
  2314. pIrlapCb->N1, pIrlapCb->N2));
  2315. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  2316. /*
  2317. if (pIrlapCb->MonitorLink)
  2318. {
  2319. IrdaTimerStart(&pIrlapCb->StatusTimer);
  2320. }
  2321. */
  2322. }
  2323. /*****************************************************************************
  2324. *
  2325. * @func UINT | IrlapGetQosParmVal |
  2326. * retrieves the parameters value from table
  2327. *
  2328. * @rdesc value contained in parmeter value table, 0 if not found
  2329. * (0 is a valid parameter in some tables though)
  2330. *
  2331. * @parm UINT [] | PVTable | table containing parm values
  2332. * USHORT | BitField | contains bit indicating which parm to select
  2333. *
  2334. * @comm
  2335. */
  2336. UINT
  2337. IrlapGetQosParmVal(const UINT PVTable[], UINT BitField, UINT *pBitSet)
  2338. {
  2339. int i;
  2340. UINT Mask;
  2341. for (i = PV_TABLE_MAX_BIT, Mask = (1<<PV_TABLE_MAX_BIT);
  2342. Mask > 0; i--, Mask = Mask >> 1)
  2343. {
  2344. if (Mask & BitField)
  2345. {
  2346. if (pBitSet != NULL)
  2347. {
  2348. *pBitSet = Mask;
  2349. }
  2350. return (PVTable[i]);
  2351. }
  2352. }
  2353. if (pBitSet != NULL) {
  2354. *pBitSet = 0;
  2355. }
  2356. return (UINT) -1;
  2357. }
  2358. /*****************************************************************************
  2359. *
  2360. */
  2361. VOID
  2362. ProcessUI(PIRLAP_CB pIrlapCb,
  2363. PIRDA_MSG pMsg,
  2364. int CRBit,
  2365. int PFBit)
  2366. {
  2367. BOOLEAN LinkTurned = TRUE;
  2368. PAGED_CODE();
  2369. pMsg->IRDA_MSG_pRead += 2; // chop the IRLAP header
  2370. switch (pIrlapCb->State)
  2371. {
  2372. case NDM:
  2373. case DSCV_MEDIA_SENSE:
  2374. case DSCV_QUERY:
  2375. case DSCV_REPLY:
  2376. case CONN_MEDIA_SENSE:
  2377. case SNRM_SENT:
  2378. case BACKOFF_WAIT:
  2379. case SNRM_RECEIVED:
  2380. pMsg->Prim = IRLAP_UDATA_IND;
  2381. IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  2382. return;
  2383. case P_XMIT:
  2384. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  2385. return;
  2386. }
  2387. if (PRIMARY == pIrlapCb->StationType)
  2388. {
  2389. // stop timers if PF bit set or invalid CRBit (matches mine)
  2390. if (IRLAP_PFBIT_SET == PFBit || pIrlapCb->CRBit == CRBit)
  2391. {
  2392. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  2393. }
  2394. }
  2395. else
  2396. {
  2397. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  2398. }
  2399. if (pIrlapCb->CRBit == CRBit)
  2400. {
  2401. StationConflict(pIrlapCb);
  2402. pIrlapCb->State = NDM;
  2403. return;
  2404. }
  2405. // Send the Unnumber information to LMP
  2406. pMsg->Prim = IRLAP_UDATA_IND;
  2407. IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  2408. if (IRLAP_PFBIT_SET == PFBit)
  2409. {
  2410. switch (pIrlapCb->State)
  2411. {
  2412. case P_RECV:
  2413. XmitTxMsgList(pIrlapCb, FALSE, &LinkTurned);
  2414. break;
  2415. case P_DISCONNECT_PEND:
  2416. SendDISC(pIrlapCb);
  2417. pIrlapCb->RetryCnt = 0;
  2418. GotoPCloseState(pIrlapCb);
  2419. break;
  2420. case P_CLOSE:
  2421. ResendDISC(pIrlapCb);
  2422. break;
  2423. case S_NRM:
  2424. XmitTxMsgList(pIrlapCb, TRUE, NULL);
  2425. break;
  2426. case S_DISCONNECT_PEND:
  2427. SendRD(pIrlapCb);
  2428. pIrlapCb->State = S_CLOSE;
  2429. break;
  2430. case S_ERROR:
  2431. SendFRMR(pIrlapCb, &pIrlapCb->Frmr);
  2432. pIrlapCb->State = S_NRM;
  2433. break;
  2434. case S_CLOSE:
  2435. SendRD(pIrlapCb);
  2436. }
  2437. }
  2438. if (PRIMARY == pIrlapCb->StationType)
  2439. {
  2440. if (IRLAP_PFBIT_SET == PFBit && pIrlapCb->State != NDM)
  2441. {
  2442. if (LinkTurned)
  2443. {
  2444. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2445. }
  2446. else
  2447. {
  2448. IrlapTimerStart(pIrlapCb, &pIrlapCb->PollTimer);
  2449. pIrlapCb->State = P_XMIT;
  2450. }
  2451. }
  2452. }
  2453. else
  2454. {
  2455. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  2456. }
  2457. return;
  2458. }
  2459. /*****************************************************************************
  2460. *
  2461. */
  2462. VOID
  2463. ProcessDM(PIRLAP_CB pIrlapCb)
  2464. {
  2465. IRDA_MSG IMsg;
  2466. BOOLEAN LinkTurned;
  2467. PAGED_CODE();
  2468. switch (pIrlapCb->State)
  2469. {
  2470. case NDM:
  2471. case DSCV_MEDIA_SENSE:
  2472. case DSCV_QUERY:
  2473. case DSCV_REPLY:
  2474. case CONN_MEDIA_SENSE:
  2475. case BACKOFF_WAIT:
  2476. case SNRM_RECEIVED:
  2477. case P_XMIT:
  2478. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  2479. return;
  2480. }
  2481. if (PRIMARY != pIrlapCb->StationType)
  2482. {
  2483. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  2484. StationConflict(pIrlapCb);
  2485. pIrlapCb->State = NDM;
  2486. return;
  2487. }
  2488. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  2489. switch (pIrlapCb->State)
  2490. {
  2491. case P_RECV: // I'm not sure why I am doing this ???
  2492. XmitTxMsgList(pIrlapCb, FALSE, &LinkTurned);
  2493. if (LinkTurned)
  2494. {
  2495. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2496. }
  2497. else
  2498. {
  2499. IrlapTimerStart(pIrlapCb, &pIrlapCb->PollTimer);
  2500. pIrlapCb->State = P_XMIT;
  2501. }
  2502. break;
  2503. case P_DISCONNECT_PEND:
  2504. pIrlapCb->RetryCnt = 0;
  2505. SendDISC(pIrlapCb);
  2506. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2507. GotoPCloseState(pIrlapCb);
  2508. break;
  2509. case SNRM_SENT:
  2510. ApplyDefaultParms(pIrlapCb);
  2511. pIrlapCb->State = NDM;
  2512. if (pIrlapCb->LocalDiscReq || pIrlapCb->State == SNRM_SENT)
  2513. {
  2514. IMsg.Prim = IRLAP_DISCONNECT_IND;
  2515. IMsg.IRDA_MSG_DiscStatus = IRLAP_REMOTE_INITIATED;
  2516. pIrlapCb->LocalDiscReq = FALSE;
  2517. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  2518. }
  2519. break;
  2520. case P_CLOSE:
  2521. pIrlapCb->State = NDM;
  2522. ApplyDefaultParms(pIrlapCb);
  2523. if (pIrlapCb->LocalDiscReq || pIrlapCb->State == SNRM_SENT)
  2524. {
  2525. IMsg.Prim = IRLAP_DISCONNECT_IND;
  2526. IMsg.IRDA_MSG_DiscStatus = IRLAP_DISCONNECT_COMPLETED;
  2527. pIrlapCb->LocalDiscReq = FALSE;
  2528. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  2529. }
  2530. GotoNDMThenDscvOrConn(pIrlapCb);
  2531. break;
  2532. }
  2533. }
  2534. /*****************************************************************************
  2535. *
  2536. *
  2537. */
  2538. VOID
  2539. ProcessDISC(PIRLAP_CB pIrlapCb)
  2540. {
  2541. IRDA_MSG IMsg;
  2542. if (IgnoreState(pIrlapCb))
  2543. {
  2544. return;
  2545. }
  2546. if (SECONDARY != pIrlapCb->StationType)
  2547. {
  2548. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  2549. StationConflict(pIrlapCb);
  2550. pIrlapCb->State = NDM;
  2551. return;
  2552. }
  2553. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  2554. // Acknowledge primary's disconnect request
  2555. SendUA(pIrlapCb, FALSE /* No Qos */);
  2556. // notify LMP of disconnect
  2557. IMsg.Prim = IRLAP_DISCONNECT_IND;
  2558. if (pIrlapCb->LocalDiscReq)
  2559. {
  2560. IMsg.IRDA_MSG_DiscStatus = IRLAP_DISCONNECT_COMPLETED;
  2561. pIrlapCb->LocalDiscReq = FALSE;
  2562. }
  2563. else
  2564. {
  2565. IMsg.IRDA_MSG_DiscStatus = IRLAP_REMOTE_INITIATED;
  2566. }
  2567. pIrlapCb->State = NDM;
  2568. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  2569. ReturnRxTxWinMsgs(pIrlapCb);
  2570. ApplyDefaultParms(pIrlapCb);
  2571. return;
  2572. }
  2573. /*****************************************************************************
  2574. *
  2575. * @func ret_type | func_name | funcdesc
  2576. *
  2577. * @rdesc SUCCESS, otherwise one of the following errors:
  2578. * @flag val | desc
  2579. *
  2580. * @parm data_type | parm_name | description
  2581. *
  2582. * @comm
  2583. * comments
  2584. *
  2585. * @ex
  2586. * example
  2587. */
  2588. VOID
  2589. ProcessRD(PIRLAP_CB pIrlapCb)
  2590. {
  2591. PAGED_CODE();
  2592. if (IgnoreState(pIrlapCb))
  2593. {
  2594. return;
  2595. }
  2596. if (PRIMARY != pIrlapCb->StationType)
  2597. {
  2598. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  2599. StationConflict(pIrlapCb);
  2600. pIrlapCb->State = NDM;
  2601. return;
  2602. }
  2603. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  2604. if (pIrlapCb->State == P_CLOSE)
  2605. {
  2606. ResendDISC(pIrlapCb);
  2607. }
  2608. else
  2609. {
  2610. ReturnRxTxWinMsgs(pIrlapCb);
  2611. pIrlapCb->RetryCnt = 0;
  2612. SendDISC(pIrlapCb);
  2613. GotoPCloseState(pIrlapCb);
  2614. }
  2615. if (pIrlapCb->State != NDM)
  2616. {
  2617. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2618. }
  2619. }
  2620. /*****************************************************************************
  2621. *
  2622. */
  2623. VOID
  2624. ProcessFRMR(PIRLAP_CB pIrlapCb)
  2625. {
  2626. PAGED_CODE();
  2627. if (IgnoreState(pIrlapCb))
  2628. {
  2629. return;
  2630. }
  2631. if (PRIMARY != pIrlapCb->StationType)
  2632. {
  2633. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  2634. StationConflict(pIrlapCb);
  2635. pIrlapCb->State = NDM;
  2636. return;
  2637. }
  2638. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  2639. switch (pIrlapCb->State)
  2640. {
  2641. case P_RECV:
  2642. ReturnRxTxWinMsgs(pIrlapCb);
  2643. // fall through
  2644. case P_DISCONNECT_PEND:
  2645. pIrlapCb->RetryCnt = 0;
  2646. SendDISC(pIrlapCb);
  2647. GotoPCloseState(pIrlapCb);
  2648. break;
  2649. case P_CLOSE:
  2650. ResendDISC(pIrlapCb);
  2651. break;
  2652. }
  2653. if (pIrlapCb->State != NDM)
  2654. {
  2655. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2656. }
  2657. }
  2658. /*****************************************************************************
  2659. *
  2660. */
  2661. VOID
  2662. ProcessRNRM(PIRLAP_CB pIrlapCb)
  2663. {
  2664. PAGED_CODE();
  2665. if (IgnoreState(pIrlapCb))
  2666. {
  2667. return;
  2668. }
  2669. if (PRIMARY != pIrlapCb->StationType)
  2670. {
  2671. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  2672. StationConflict(pIrlapCb);
  2673. pIrlapCb->State = NDM;
  2674. return;
  2675. }
  2676. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  2677. switch (pIrlapCb->State)
  2678. {
  2679. case P_RECV:
  2680. case P_DISCONNECT_PEND:
  2681. pIrlapCb->RetryCnt = 0;
  2682. SendDISC(pIrlapCb);
  2683. GotoPCloseState(pIrlapCb);
  2684. break;
  2685. case P_CLOSE:
  2686. ResendDISC(pIrlapCb);
  2687. break;
  2688. }
  2689. if (pIrlapCb->State != NDM)
  2690. {
  2691. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2692. }
  2693. return;
  2694. }
  2695. /*****************************************************************************
  2696. *
  2697. */
  2698. VOID
  2699. ProcessREJ_SREJ(PIRLAP_CB pIrlapCb,
  2700. int FrameType,
  2701. int CRBit,
  2702. int PFBit,
  2703. UINT Nr)
  2704. {
  2705. if (IgnoreState(pIrlapCb))
  2706. {
  2707. return;
  2708. }
  2709. if (PRIMARY == pIrlapCb->StationType)
  2710. {
  2711. // stop timers if PF bit set or invalid CRBit (matches mine)
  2712. if (IRLAP_PFBIT_SET == PFBit || pIrlapCb->CRBit == CRBit)
  2713. {
  2714. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  2715. }
  2716. }
  2717. else
  2718. {
  2719. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  2720. }
  2721. if (pIrlapCb->CRBit == CRBit)
  2722. {
  2723. StationConflict(pIrlapCb);
  2724. pIrlapCb->State = NDM;
  2725. return;
  2726. }
  2727. switch (pIrlapCb->State)
  2728. {
  2729. case P_RECV:
  2730. case S_NRM:
  2731. if (IRLAP_PFBIT_SET == PFBit)
  2732. {
  2733. if (InvalidNr(pIrlapCb,Nr) || Nr == pIrlapCb->TxWin.End)
  2734. {
  2735. ProcessInvalidNr(pIrlapCb, PFBit);
  2736. }
  2737. else
  2738. {
  2739. ConfirmAckedTxMsgs(pIrlapCb, Nr);
  2740. if (FrameType == IRLAP_REJ)
  2741. {
  2742. ResendRejects(pIrlapCb, Nr); // link turned here
  2743. }
  2744. else // selective reject
  2745. {
  2746. IRLAP_LOG_ACTION((pIrlapCb, TEXT("RETRANSMISSION:")));
  2747. SendIFrame(pIrlapCb,
  2748. pIrlapCb->TxWin.pMsg[Nr],
  2749. Nr, IRLAP_PFBIT_SET);
  2750. }
  2751. }
  2752. }
  2753. break;
  2754. case P_DISCONNECT_PEND:
  2755. if (IRLAP_PFBIT_SET == PFBit)
  2756. {
  2757. pIrlapCb->RetryCnt = 0;
  2758. SendDISC(pIrlapCb);
  2759. GotoPCloseState(pIrlapCb);
  2760. }
  2761. break;
  2762. case P_CLOSE:
  2763. if (IRLAP_PFBIT_SET == PFBit)
  2764. {
  2765. ResendDISC(pIrlapCb);
  2766. }
  2767. break;
  2768. case S_DISCONNECT_PEND:
  2769. if (IRLAP_PFBIT_SET == PFBit)
  2770. {
  2771. SendRD(pIrlapCb);
  2772. pIrlapCb->State = S_CLOSE;
  2773. }
  2774. break;
  2775. case S_ERROR:
  2776. if (IRLAP_PFBIT_SET == PFBit)
  2777. {
  2778. SendFRMR(pIrlapCb, &pIrlapCb->Frmr);
  2779. pIrlapCb->State = S_NRM;
  2780. }
  2781. break;
  2782. case S_CLOSE:
  2783. if (IRLAP_PFBIT_SET == PFBit)
  2784. {
  2785. SendRD(pIrlapCb);
  2786. }
  2787. break;
  2788. }
  2789. if (PRIMARY == pIrlapCb->StationType)
  2790. {
  2791. if (IRLAP_PFBIT_SET == PFBit && pIrlapCb->State != NDM)
  2792. {
  2793. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2794. }
  2795. }
  2796. else
  2797. {
  2798. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  2799. }
  2800. }
  2801. /*****************************************************************************
  2802. *
  2803. */
  2804. VOID
  2805. ProcessRR_RNR(PIRLAP_CB pIrlapCb,
  2806. int FrameType,
  2807. int CRBit,
  2808. int PFBit,
  2809. UINT Nr)
  2810. {
  2811. BOOLEAN LinkTurned = TRUE;
  2812. if (IgnoreState(pIrlapCb))
  2813. {
  2814. return;
  2815. }
  2816. if (pIrlapCb->FastPollCount == 0)
  2817. {
  2818. pIrlapCb->PollTimer.Timeout = pIrlapCb->RemoteMaxTAT;
  2819. }
  2820. else
  2821. {
  2822. pIrlapCb->FastPollCount -= 1;
  2823. }
  2824. if (PRIMARY == pIrlapCb->StationType)
  2825. {
  2826. // stop timers if PF bit set or invalid CRBit (matches mine)
  2827. if (IRLAP_PFBIT_SET == PFBit || pIrlapCb->CRBit == CRBit)
  2828. {
  2829. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  2830. }
  2831. }
  2832. else // SECONDARY, restart WDog
  2833. {
  2834. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  2835. if (pIrlapCb->CRBit != CRBit)
  2836. {
  2837. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  2838. }
  2839. }
  2840. if (pIrlapCb->CRBit == CRBit)
  2841. {
  2842. StationConflict(pIrlapCb);
  2843. pIrlapCb->State = NDM;
  2844. return;
  2845. }
  2846. if (FrameType == IRLAP_RR)
  2847. {
  2848. pIrlapCb->RemoteBusy = FALSE;
  2849. }
  2850. else // RNR
  2851. {
  2852. pIrlapCb->RemoteBusy = TRUE;
  2853. }
  2854. switch (pIrlapCb->State)
  2855. {
  2856. case P_RECV:
  2857. case S_NRM:
  2858. if (PFBit == IRLAP_PFBIT_SET)
  2859. {
  2860. if (InvalidNr(pIrlapCb, Nr))
  2861. {
  2862. ProcessInvalidNr(pIrlapCb, PFBit);
  2863. }
  2864. else
  2865. {
  2866. ConfirmAckedTxMsgs(pIrlapCb,Nr);
  2867. if (Nr != pIrlapCb->Vs) // Implicit reject
  2868. {
  2869. if (PRIMARY == pIrlapCb->StationType &&
  2870. IRLAP_RNR == FrameType)
  2871. {
  2872. LinkTurned = FALSE;
  2873. }
  2874. else
  2875. {
  2876. ResendRejects(pIrlapCb, Nr); // always turns link
  2877. }
  2878. }
  2879. else
  2880. {
  2881. if (pIrlapCb->Vr != pIrlapCb->RxWin.End)
  2882. {
  2883. MissingRxFrames(pIrlapCb); // Send SREJ or REJ
  2884. }
  2885. else
  2886. {
  2887. if (PRIMARY == pIrlapCb->StationType)
  2888. {
  2889. LinkTurned = FALSE;
  2890. if (IRLAP_RR == FrameType)
  2891. {
  2892. XmitTxMsgList(pIrlapCb, FALSE, &LinkTurned);
  2893. }
  2894. }
  2895. else
  2896. {
  2897. // Always turn link if secondary
  2898. // with data or an RR if remote is busy
  2899. if (IRLAP_RR == FrameType)
  2900. {
  2901. XmitTxMsgList(pIrlapCb, TRUE, NULL);
  2902. }
  2903. else
  2904. {
  2905. SendRR_RNR(pIrlapCb);
  2906. }
  2907. }
  2908. }
  2909. }
  2910. }
  2911. // If the link was turned, restart Final timer,
  2912. // else start the Poll timer and enter the transmit state
  2913. if (PRIMARY == pIrlapCb->StationType)
  2914. {
  2915. if (LinkTurned)
  2916. {
  2917. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2918. }
  2919. else
  2920. {
  2921. IrlapTimerStart(pIrlapCb, &pIrlapCb->PollTimer);
  2922. pIrlapCb->State = P_XMIT;
  2923. }
  2924. }
  2925. }
  2926. break;
  2927. case P_DISCONNECT_PEND:
  2928. SendDISC(pIrlapCb);
  2929. pIrlapCb->RetryCnt = 0;
  2930. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2931. GotoPCloseState(pIrlapCb);
  2932. break;
  2933. case P_CLOSE:
  2934. ResendDISC(pIrlapCb);
  2935. if (pIrlapCb->State != NDM)
  2936. {
  2937. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  2938. }
  2939. break;
  2940. case S_DISCONNECT_PEND:
  2941. case S_CLOSE:
  2942. if (IRLAP_PFBIT_SET == PFBit)
  2943. {
  2944. SendRD(pIrlapCb);
  2945. if (pIrlapCb->State != S_CLOSE)
  2946. pIrlapCb->State = S_CLOSE;
  2947. }
  2948. break;
  2949. case S_ERROR:
  2950. if (IRLAP_PFBIT_SET == PFBit)
  2951. {
  2952. SendFRMR(pIrlapCb, &pIrlapCb->Frmr);
  2953. pIrlapCb->State = S_NRM;
  2954. }
  2955. break;
  2956. default:
  2957. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  2958. }
  2959. }
  2960. /*****************************************************************************
  2961. *
  2962. */
  2963. VOID
  2964. ProcessInvalidNr(PIRLAP_CB pIrlapCb,
  2965. int PFBit)
  2966. {
  2967. DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: ERROR, Invalid Nr\r\n")));
  2968. ReturnRxTxWinMsgs(pIrlapCb);
  2969. if (PRIMARY == pIrlapCb->StationType)
  2970. {
  2971. if (PFBit == IRLAP_PFBIT_SET)
  2972. {
  2973. SendDISC(pIrlapCb);
  2974. pIrlapCb->RetryCnt = 0;
  2975. // F-timer will be started by caller
  2976. GotoPCloseState(pIrlapCb);
  2977. }
  2978. else
  2979. {
  2980. pIrlapCb->State = P_DISCONNECT_PEND;
  2981. }
  2982. }
  2983. else // SECONDARY
  2984. {
  2985. if (PFBit == IRLAP_PFBIT_SET)
  2986. {
  2987. pIrlapCb->Frmr.Vs = (UCHAR) pIrlapCb->Vs;
  2988. pIrlapCb->Frmr.Vr = (UCHAR) pIrlapCb->Vr;
  2989. pIrlapCb->Frmr.W = 0;
  2990. pIrlapCb->Frmr.X = 0;
  2991. pIrlapCb->Frmr.Y = 0;
  2992. pIrlapCb->Frmr.Z = 1; // bad NR
  2993. SendFRMR(pIrlapCb, &pIrlapCb->Frmr);
  2994. }
  2995. }
  2996. }
  2997. /*****************************************************************************
  2998. *
  2999. */
  3000. VOID
  3001. ProcessIFrame(PIRLAP_CB pIrlapCb,
  3002. PIRDA_MSG pMsg,
  3003. int CRBit,
  3004. int PFBit,
  3005. UINT Ns,
  3006. UINT Nr)
  3007. {
  3008. #if DBG_OUT
  3009. UCHAR *p1, *p2;
  3010. #endif
  3011. if ((pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead) > IRDA_HEADER_LEN)
  3012. {
  3013. pIrlapCb->StatusFlags |= LF_RX;
  3014. }
  3015. pMsg->IRDA_MSG_pRead += IRLAP_HEADER_LEN; // chop the IRLAP header
  3016. #if DBG_CHECKSUM
  3017. // print first and last 4 bytes of frame to help isolate
  3018. // data corruption problem. Should be used with sledge
  3019. if ((pMsg->IRDA_MSG_pWrite - pMsg->IRDA_MSG_pRead) > 20)
  3020. DEBUGMSG(1, (TEXT("R(%p): %c%c%c%c, %c%c%c%c\n"),
  3021. pMsg->IRDA_MSG_pRead+3,
  3022. *(pMsg->IRDA_MSG_pRead+3),
  3023. *(pMsg->IRDA_MSG_pRead+4),
  3024. *(pMsg->IRDA_MSG_pRead+5),
  3025. *(pMsg->IRDA_MSG_pRead+6),
  3026. *(pMsg->IRDA_MSG_pWrite-4),
  3027. *(pMsg->IRDA_MSG_pWrite-3),
  3028. *(pMsg->IRDA_MSG_pWrite-2),
  3029. *(pMsg->IRDA_MSG_pWrite-1)));
  3030. #endif
  3031. switch (pIrlapCb->State)
  3032. {
  3033. case S_NRM:
  3034. case P_RECV:
  3035. // Stop Timers: if PFSet stop Final (I frame from secondary)
  3036. // Always stop WDog (I from primary)
  3037. if (PRIMARY == pIrlapCb->StationType)
  3038. {
  3039. if (PFBit == IRLAP_PFBIT_SET)
  3040. {
  3041. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  3042. }
  3043. }
  3044. else
  3045. {
  3046. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  3047. }
  3048. if (pIrlapCb->CRBit == CRBit)
  3049. {
  3050. StationConflict(pIrlapCb);
  3051. pIrlapCb->State = NDM;
  3052. return;
  3053. }
  3054. if (InvalidNs(pIrlapCb, Ns))
  3055. {
  3056. DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: ignoring invalid NS frame\n")));
  3057. }
  3058. else if (InvalidNr(pIrlapCb, Nr))
  3059. {
  3060. #if DBG_OUT
  3061. p1 = pMsg->IRDA_MSG_pRead - 2; // Get header back
  3062. p2 = pMsg->IRDA_MSG_pWrite + 2; // and FCS
  3063. while (p1 < p2)
  3064. DEBUGMSG(1, (TEXT("%02X "), *p1++));
  3065. DEBUGMSG(1, (TEXT("\n")));
  3066. #endif
  3067. #ifdef TEMPERAMENTAL_SERIAL_DRIVER
  3068. if (pIrlapCb->RxWin.FCS[Ns] == pMsg->IRDA_MSG_FCS)
  3069. TossedDups++;
  3070. else
  3071. ProcessInvalidNsOrNr(pIrlapCb, PFBit);
  3072. #else
  3073. ProcessInvalidNsOrNr(pIrlapCb, PFBit);
  3074. #endif
  3075. }
  3076. else
  3077. {
  3078. ConfirmAckedTxMsgs(pIrlapCb, Nr);
  3079. if (PFBit == IRLAP_PFBIT_SET)
  3080. {
  3081. InsertRxWinAndForward(pIrlapCb, pMsg, Ns);
  3082. if (Nr != pIrlapCb->Vs)
  3083. {
  3084. ResendRejects(pIrlapCb, Nr); // always turns link
  3085. }
  3086. else // Nr == Vs, Good Nr
  3087. {
  3088. // Link will always be turned here
  3089. if (pIrlapCb->Vr != pIrlapCb->RxWin.End)
  3090. {
  3091. MissingRxFrames(pIrlapCb);
  3092. }
  3093. else
  3094. {
  3095. XmitTxMsgList(pIrlapCb, TRUE, NULL);
  3096. }
  3097. }
  3098. }
  3099. else // PF Bit not set
  3100. {
  3101. InsertRxWinAndForward(pIrlapCb, pMsg, Ns);
  3102. }
  3103. }
  3104. // Start Timers: If PFBit set, link was turned so start final
  3105. // WDog is always stopped, so restart
  3106. if (PRIMARY == pIrlapCb->StationType)
  3107. {
  3108. if (PFBit == IRLAP_PFBIT_SET)
  3109. {
  3110. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  3111. }
  3112. }
  3113. else // command from primary
  3114. {
  3115. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  3116. }
  3117. break;
  3118. default:
  3119. IFrameOtherStates(pIrlapCb, CRBit, PFBit);
  3120. }
  3121. }
  3122. /*****************************************************************************
  3123. *
  3124. */
  3125. BOOLEAN
  3126. InvalidNs(PIRLAP_CB pIrlapCb,
  3127. UINT Ns)
  3128. {
  3129. // Valididate ns
  3130. if (!InWindow(pIrlapCb->Vr,
  3131. (pIrlapCb->RxWin.Start + pIrlapCb->LocalWinSize-1) % IRLAP_MOD, Ns)
  3132. || !InWindow(pIrlapCb->RxWin.Start,
  3133. (pIrlapCb->RxWin.Start + pIrlapCb->LocalWinSize-1) % IRLAP_MOD, Ns))
  3134. {
  3135. DEBUGMSG(DBG_ERROR,
  3136. (TEXT("IRLAP: ERROR, Invalid Ns=%d! Vr=%d, RxStrt=%d Win=%d\r\n"),
  3137. Ns, pIrlapCb->Vr, pIrlapCb->RxWin.Start,
  3138. pIrlapCb->LocalWinSize));
  3139. IRLAP_LOG_ACTION((pIrlapCb, TEXT("** INVALID Ns **")));
  3140. return TRUE;
  3141. }
  3142. return FALSE;
  3143. }
  3144. /*****************************************************************************
  3145. *
  3146. */
  3147. BOOLEAN
  3148. InvalidNr(PIRLAP_CB pIrlapCb,
  3149. UINT Nr)
  3150. {
  3151. if (!InWindow(pIrlapCb->TxWin.Start, pIrlapCb->Vs, Nr))
  3152. {
  3153. DEBUGMSG(DBG_ERROR,
  3154. (TEXT("IRLAP: ERROR, Invalid Nr=%d! Vs=%d, TxStrt=%d\r\n"),
  3155. Nr, pIrlapCb->Vs, pIrlapCb->TxWin.Start));
  3156. return TRUE; // Invalid Nr
  3157. }
  3158. return FALSE;
  3159. }
  3160. /*****************************************************************************
  3161. *
  3162. */
  3163. BOOLEAN
  3164. InWindow(UINT Start, UINT End, UINT i)
  3165. {
  3166. if (Start <= End)
  3167. {
  3168. if (i >= Start && i <= End)
  3169. return TRUE;
  3170. }
  3171. else
  3172. {
  3173. if (i >= Start || i <= End)
  3174. return TRUE;
  3175. }
  3176. return FALSE;
  3177. }
  3178. /*****************************************************************************
  3179. *
  3180. */
  3181. VOID
  3182. ProcessInvalidNsOrNr(PIRLAP_CB pIrlapCb,
  3183. int PFBit)
  3184. {
  3185. ReturnRxTxWinMsgs(pIrlapCb);
  3186. if (PRIMARY == pIrlapCb->StationType)
  3187. {
  3188. if (PFBit == IRLAP_PFBIT_SET)
  3189. {
  3190. SendDISC(pIrlapCb);
  3191. pIrlapCb->RetryCnt = 0;
  3192. // F-timer will be started by caller
  3193. GotoPCloseState(pIrlapCb);
  3194. }
  3195. else
  3196. {
  3197. pIrlapCb->State = P_DISCONNECT_PEND;
  3198. }
  3199. }
  3200. else // SECONDARY
  3201. {
  3202. pIrlapCb->Frmr.Vs = (UCHAR) pIrlapCb->Vs;
  3203. pIrlapCb->Frmr.Vr = (UCHAR) pIrlapCb->Vr;
  3204. pIrlapCb->Frmr.W = 0;
  3205. pIrlapCb->Frmr.X = 0;
  3206. pIrlapCb->Frmr.Y = 0;
  3207. pIrlapCb->Frmr.Z = 1; // bad NR
  3208. if (PFBit == IRLAP_PFBIT_SET)
  3209. {
  3210. SendFRMR(pIrlapCb, &pIrlapCb->Frmr);
  3211. }
  3212. else
  3213. {
  3214. pIrlapCb->State = S_ERROR;
  3215. }
  3216. }
  3217. }
  3218. /*****************************************************************************
  3219. *
  3220. */
  3221. VOID
  3222. InsertRxWinAndForward(PIRLAP_CB pIrlapCb,
  3223. PIRDA_MSG pIrdaMsg,
  3224. UINT Ns)
  3225. {
  3226. UINT rc = SUCCESS;
  3227. PIRDA_MSG pMsg;
  3228. if (pIrlapCb->RxWin.pMsg[Ns] != NULL)
  3229. {
  3230. DEBUGMSG(DBG_ERROR, (TEXT("IRLAP: RxFrame Ns:%d already in RxWin\n"),Ns));
  3231. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ns:%d already in window\n"), Ns));
  3232. return;
  3233. }
  3234. // insert message into receive window
  3235. pIrlapCb->RxWin.pMsg[Ns] = pIrdaMsg;
  3236. #ifdef TEMPERAMENTAL_SERIAL_DRIVER
  3237. pIrlapCb->RxWin.FCS[Ns] = pIrdaMsg->IRDA_MSG_FCS;
  3238. #endif
  3239. #if DBG_BADDRIVER
  3240. // What if the MAC driver modifies the buffer that we may hold onto?
  3241. {
  3242. UINT CheckVal = 0;
  3243. UCHAR *pByte = pIrdaMsg->IRDA_MSG_pRead;
  3244. while (pByte != pIrdaMsg->IRDA_MSG_pWrite)
  3245. {
  3246. CheckVal += *pByte++;
  3247. }
  3248. *(UINT *) pIrdaMsg->IRDA_MSG_Header = CheckVal;
  3249. }
  3250. #endif
  3251. // Advance RxWin.End to Ns+1 if Ns is at or beyond RxWin.End
  3252. if (!InWindow(pIrlapCb->RxWin.Start, pIrlapCb->RxWin.End, Ns) ||
  3253. Ns == pIrlapCb->RxWin.End)
  3254. {
  3255. pIrlapCb->RxWin.End = (Ns + 1) % IRLAP_MOD;
  3256. }
  3257. //
  3258. // Increment reference. It may be out of sequence so
  3259. // we'll will have to hold onto it.
  3260. //
  3261. ASSERT(pIrdaMsg->IRDA_MSG_RefCnt == 1);
  3262. pIrdaMsg->IRDA_MSG_RefCnt += 1;
  3263. // Forward in sequence frames starting from Vr
  3264. pMsg = pIrlapCb->RxWin.pMsg[pIrlapCb->Vr];
  3265. while (pMsg != NULL && !pIrlapCb->LocalBusy)
  3266. {
  3267. #if DBG_BADDRIVER
  3268. // What if the MAC driver modifies the buffer that we may hold onto?
  3269. {
  3270. UINT CheckVal = 0;
  3271. UCHAR *pByte = pMsg->IRDA_MSG_pRead;
  3272. while (pByte != pMsg->IRDA_MSG_pWrite)
  3273. {
  3274. CheckVal += *pByte++;
  3275. }
  3276. if (CheckVal != *(UINT *) pMsg->IRDA_MSG_Header)
  3277. {
  3278. DEBUGMSG(1, (TEXT("IRLAP: MAC driver has modified buffer owned by IrLAP! SEVERE ERROR\n")));
  3279. ASSERT(0);
  3280. }
  3281. }
  3282. #endif
  3283. pMsg->Prim = IRLAP_DATA_IND;
  3284. rc = IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  3285. if (rc == SUCCESS || rc == IRLMP_LOCAL_BUSY)
  3286. {
  3287. // Delivered successfully. Done with this message. Remove it from
  3288. // the RxWin and return msg to MAC. Update Vr
  3289. pIrlapCb->RxWin.pMsg[pIrlapCb->Vr] = NULL;
  3290. ASSERT(pMsg->IRDA_MSG_RefCnt);
  3291. pMsg->IRDA_MSG_RefCnt -=1;
  3292. if (pMsg->IRDA_MSG_RefCnt == 0)
  3293. {
  3294. // if this is the current irda message then don't
  3295. // do the data_response. It will be taken care of
  3296. // by the caller.
  3297. pMsg->Prim = MAC_DATA_RESP;
  3298. IrmacDown(pIrlapCb->pIrdaLinkCb, pMsg);
  3299. }
  3300. pIrlapCb->Vr = (pIrlapCb->Vr + 1) % IRLAP_MOD;
  3301. pMsg = pIrlapCb->RxWin.pMsg[pIrlapCb->Vr];
  3302. // LMP doesn't want anymore messages
  3303. if (rc == IRLMP_LOCAL_BUSY)
  3304. {
  3305. // The receive window will be cleaned out when RNR is sent
  3306. pIrlapCb->LocalBusy = TRUE;
  3307. }
  3308. }
  3309. else
  3310. {
  3311. ASSERT(0);
  3312. return;
  3313. }
  3314. }
  3315. if (pIrdaMsg->IRDA_MSG_RefCnt > 1)
  3316. {
  3317. //
  3318. // The message was not indicated to Irlmp.
  3319. // We'll have to copy the data out of the buffer
  3320. // since some miniports can't handle us
  3321. // holding onto the packets
  3322. if (pIrdaMsg->DataContext)
  3323. {
  3324. UCHAR *pCurRead, *pCurWrite;
  3325. LONG_PTR Len;
  3326. pCurRead = pIrdaMsg->IRDA_MSG_pRead;
  3327. pCurWrite = pIrdaMsg->IRDA_MSG_pWrite;
  3328. Len = pCurWrite - pCurRead;
  3329. //
  3330. // the size is check when the miniport indiactes the frame.
  3331. // Should not be possible for it to be too big here
  3332. //
  3333. ASSERT(Len <= pIrlapCb->pIrdaLinkCb->RxMsgDataSize);
  3334. pIrdaMsg->IRDA_MSG_pRead = (UCHAR *) pIrdaMsg + sizeof(IRDA_MSG);
  3335. ASSERT(pIrdaMsg->IRDA_MSG_pRead != pCurRead);
  3336. CTEMemCopy(pIrdaMsg->IRDA_MSG_pRead, pCurRead, Len);
  3337. pIrdaMsg->IRDA_MSG_pWrite = pIrdaMsg->IRDA_MSG_pRead + Len;
  3338. }
  3339. }
  3340. }
  3341. /*****************************************************************************
  3342. *
  3343. */
  3344. VOID
  3345. ResendRejects(PIRLAP_CB pIrlapCb, UINT Nr)
  3346. {
  3347. if (!pIrlapCb->RemoteBusy)
  3348. {
  3349. // Set Vs back
  3350. for (pIrlapCb->Vs=Nr; pIrlapCb->Vs !=
  3351. (pIrlapCb->TxWin.End-1)%IRLAP_MOD;
  3352. pIrlapCb->Vs = (pIrlapCb->Vs + 1) % IRLAP_MOD)
  3353. {
  3354. pIrlapCb->RetranCnt++;
  3355. IRLAP_LOG_ACTION((pIrlapCb, TEXT("RETRANSMISSION:")));
  3356. SendIFrame(pIrlapCb,
  3357. pIrlapCb->TxWin.pMsg[pIrlapCb->Vs],
  3358. pIrlapCb->Vs,
  3359. IRLAP_PFBIT_CLEAR);
  3360. }
  3361. IRLAP_LOG_ACTION((pIrlapCb, TEXT("RETRANSMISSION:")));
  3362. // Send last one with PFBit set
  3363. SendIFrame(pIrlapCb, pIrlapCb->TxWin.pMsg[pIrlapCb->Vs],
  3364. pIrlapCb->Vs, IRLAP_PFBIT_SET);
  3365. pIrlapCb->Vs = (pIrlapCb->Vs + 1) % IRLAP_MOD; // Vs == TxWin.End
  3366. }
  3367. else
  3368. {
  3369. SendRR_RNR(pIrlapCb);
  3370. }
  3371. }
  3372. /*****************************************************************************
  3373. *
  3374. */
  3375. VOID
  3376. ConfirmAckedTxMsgs(PIRLAP_CB pIrlapCb,
  3377. UINT Nr)
  3378. {
  3379. UINT i = pIrlapCb->TxWin.Start;
  3380. IRDA_MSG *pMsg;
  3381. while (i != Nr)
  3382. {
  3383. pMsg = pIrlapCb->TxWin.pMsg[i];
  3384. pIrlapCb->TxWin.pMsg[i] = NULL;
  3385. if (pMsg != NULL)
  3386. {
  3387. ASSERT(pMsg->IRDA_MSG_RefCnt);
  3388. if (InterlockedDecrement(&pMsg->IRDA_MSG_RefCnt) == 0)
  3389. {
  3390. pMsg->Prim = IRLAP_DATA_CONF;
  3391. pMsg->IRDA_MSG_DataStatus = IRLAP_DATA_REQUEST_COMPLETED;
  3392. IrlmpUp(pIrlapCb->pIrdaLinkCb, pMsg);
  3393. }
  3394. #if DBG
  3395. else
  3396. {
  3397. pIrlapCb->DelayedConf++;
  3398. }
  3399. #endif
  3400. }
  3401. i = (i + 1) % IRLAP_MOD;
  3402. }
  3403. pIrlapCb->TxWin.Start = i;
  3404. }
  3405. /*****************************************************************************
  3406. *
  3407. */
  3408. VOID
  3409. MissingRxFrames(PIRLAP_CB pIrlapCb)
  3410. {
  3411. int MissingFrameCnt = 0;
  3412. int MissingFrame = -1;
  3413. UINT i;
  3414. i = pIrlapCb->Vr;
  3415. // Count missing frame, determine first missing frame
  3416. for (i = pIrlapCb->Vr; (i + 1) % IRLAP_MOD != pIrlapCb->RxWin.End;
  3417. i = (i+1) % IRLAP_MOD)
  3418. {
  3419. if (pIrlapCb->RxWin.pMsg[i] == NULL)
  3420. {
  3421. MissingFrameCnt++;
  3422. if (MissingFrame == -1)
  3423. {
  3424. MissingFrame = i;
  3425. }
  3426. }
  3427. }
  3428. // if there are missing frames send SREJ (1) or RR (more than 1)
  3429. // and turn link around
  3430. if (MissingFrameCnt == 1 && !pIrlapCb->LocalBusy)
  3431. {
  3432. // we don't want to send the SREJ when local is busy because
  3433. // peer *MAY* interpret it as a clearing of the local busy condition
  3434. SendSREJ(pIrlapCb, MissingFrame);
  3435. }
  3436. else
  3437. {
  3438. // The RR/RNR will serve as an implicit REJ
  3439. SendRR_RNR(pIrlapCb);
  3440. }
  3441. }
  3442. /*****************************************************************************
  3443. *
  3444. */
  3445. VOID
  3446. IFrameOtherStates(PIRLAP_CB pIrlapCb,
  3447. int CRBit,
  3448. int PFBit)
  3449. {
  3450. switch (pIrlapCb->State)
  3451. {
  3452. case NDM:
  3453. case DSCV_MEDIA_SENSE:
  3454. case DSCV_QUERY:
  3455. case DSCV_REPLY:
  3456. case CONN_MEDIA_SENSE:
  3457. case SNRM_SENT:
  3458. case BACKOFF_WAIT:
  3459. case SNRM_RECEIVED:
  3460. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  3461. return;
  3462. }
  3463. if (pIrlapCb->CRBit == CRBit) // should be opposite of mine
  3464. {
  3465. if (pIrlapCb->StationType == PRIMARY)
  3466. {
  3467. if (pIrlapCb->State == P_XMIT)
  3468. {
  3469. IrlapTimerStop(pIrlapCb, &pIrlapCb->PollTimer);
  3470. }
  3471. else
  3472. {
  3473. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  3474. }
  3475. }
  3476. else
  3477. {
  3478. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  3479. }
  3480. StationConflict(pIrlapCb);
  3481. pIrlapCb->State = NDM;
  3482. return;
  3483. }
  3484. if (pIrlapCb->StationType == PRIMARY) // I'm PRIMARY, this is a
  3485. { // response from secondary
  3486. switch (pIrlapCb->State)
  3487. {
  3488. case P_DISCONNECT_PEND:
  3489. if (PFBit == IRLAP_PFBIT_CLEAR)
  3490. {
  3491. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  3492. }
  3493. else
  3494. {
  3495. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  3496. SendDISC(pIrlapCb);
  3497. pIrlapCb->RetryCnt = 0;
  3498. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  3499. GotoPCloseState(pIrlapCb);
  3500. }
  3501. break;
  3502. case P_CLOSE:
  3503. if (PFBit == IRLAP_PFBIT_CLEAR)
  3504. {
  3505. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  3506. }
  3507. else
  3508. {
  3509. IrlapTimerStop(pIrlapCb, &pIrlapCb->FinalTimer);
  3510. ResendDISC(pIrlapCb);
  3511. if (pIrlapCb->State != NDM)
  3512. {
  3513. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  3514. }
  3515. }
  3516. break;
  3517. case S_CLOSE:
  3518. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  3519. break;
  3520. default:
  3521. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  3522. }
  3523. }
  3524. else
  3525. {
  3526. switch (pIrlapCb->State)
  3527. {
  3528. case S_DISCONNECT_PEND:
  3529. if (IRLAP_PFBIT_SET == PFBit)
  3530. {
  3531. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  3532. SendRD(pIrlapCb);
  3533. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  3534. pIrlapCb->State = S_CLOSE;
  3535. }
  3536. else
  3537. {
  3538. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  3539. }
  3540. break;
  3541. case S_ERROR:
  3542. if (IRLAP_PFBIT_SET == PFBit)
  3543. {
  3544. SendFRMR(pIrlapCb, &pIrlapCb->Frmr);
  3545. pIrlapCb->State = S_NRM;
  3546. }
  3547. else
  3548. {
  3549. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  3550. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  3551. }
  3552. break;
  3553. case S_CLOSE:
  3554. if (IRLAP_PFBIT_SET == PFBit)
  3555. {
  3556. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  3557. SendRD(pIrlapCb);
  3558. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  3559. }
  3560. else
  3561. {
  3562. IrlapTimerStop(pIrlapCb, &pIrlapCb->WDogTimer);
  3563. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  3564. }
  3565. default:
  3566. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignore in this state")));
  3567. }
  3568. }
  3569. }
  3570. /*****************************************************************************
  3571. *
  3572. */
  3573. VOID
  3574. StationConflict(PIRLAP_CB pIrlapCb)
  3575. {
  3576. IRDA_MSG IMsg;
  3577. PAGED_CODE();
  3578. InitializeState(pIrlapCb, PRIMARY); // Primary doesn't mean anything here
  3579. ApplyDefaultParms(pIrlapCb);
  3580. IMsg.Prim = IRLAP_DISCONNECT_IND;
  3581. IMsg.IRDA_MSG_DiscStatus = IRLAP_PRIMARY_CONFLICT;
  3582. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  3583. }
  3584. /*****************************************************************************
  3585. *
  3586. */
  3587. VOID
  3588. ApplyDefaultParms(PIRLAP_CB pIrlapCb)
  3589. {
  3590. IRDA_MSG IMsg;
  3591. PAGED_CODE();
  3592. //IndicateLinkStatus(pIrlapCb, LINK_STATUS_IDLE);
  3593. pIrlapCb->StatusFlags = 0;
  3594. pIrlapCb->Baud = IRLAP_CONTENTION_BAUD;
  3595. pIrlapCb->RemoteMaxTAT = IRLAP_CONTENTION_MAX_TAT;
  3596. pIrlapCb->RemoteDataSize = IRLAP_CONTENTION_DATA_SIZE;
  3597. pIrlapCb->RemoteWinSize = IRLAP_CONTENTION_WIN_SIZE;
  3598. pIrlapCb->RemoteNumBOFS = IRLAP_CONTENTION_BOFS;
  3599. pIrlapCb->ConnAddr = IRLAP_BROADCAST_CONN_ADDR;
  3600. pIrlapCb->NoResponse = FALSE;
  3601. IMsg.Prim = MAC_CONTROL_REQ;
  3602. IMsg.IRDA_MSG_Op = MAC_RECONFIG_LINK;
  3603. IMsg.IRDA_MSG_Baud = IRLAP_CONTENTION_BAUD;
  3604. IMsg.IRDA_MSG_NumBOFs = IRLAP_CONTENTION_BOFS;
  3605. IMsg.IRDA_MSG_DataSize = IRLAP_CONTENTION_DATA_SIZE;
  3606. IMsg.IRDA_MSG_MinTat = 0;
  3607. IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ - reconfig link")));
  3608. IrmacDown(pIrlapCb->pIrdaLinkCb, &IMsg);
  3609. }
  3610. /*****************************************************************************
  3611. *
  3612. */
  3613. VOID
  3614. ResendDISC(PIRLAP_CB pIrlapCb)
  3615. {
  3616. IRDA_MSG IMsg;
  3617. if (pIrlapCb->RetryCnt >= pIrlapCb->N3)
  3618. {
  3619. ApplyDefaultParms(pIrlapCb);
  3620. pIrlapCb->RetryCnt = 0;
  3621. IMsg.Prim = IRLAP_DISCONNECT_IND;
  3622. IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE;
  3623. pIrlapCb->State = NDM;
  3624. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  3625. }
  3626. else
  3627. {
  3628. SendDISC(pIrlapCb);
  3629. pIrlapCb->RetryCnt++;
  3630. }
  3631. }
  3632. /*****************************************************************************
  3633. *
  3634. */
  3635. BOOLEAN
  3636. IgnoreState(PIRLAP_CB pIrlapCb)
  3637. {
  3638. switch (pIrlapCb->State)
  3639. {
  3640. case NDM:
  3641. case DSCV_MEDIA_SENSE:
  3642. case DSCV_QUERY:
  3643. case DSCV_REPLY:
  3644. case CONN_MEDIA_SENSE:
  3645. case SNRM_SENT:
  3646. case BACKOFF_WAIT:
  3647. case SNRM_RECEIVED:
  3648. case P_XMIT:
  3649. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring in this state")));
  3650. return TRUE;
  3651. }
  3652. return FALSE;
  3653. }
  3654. /*****************************************************************************
  3655. *
  3656. */
  3657. VOID
  3658. QueryTimerExp(PVOID Context)
  3659. {
  3660. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  3661. IRLAP_LOG_START((pIrlapCb, TEXT("Query timer expired")));
  3662. if (pIrlapCb->State == DSCV_REPLY)
  3663. {
  3664. pIrlapCb->State = NDM;
  3665. }
  3666. else
  3667. {
  3668. IRLAP_LOG_ACTION((pIrlapCb,
  3669. TEXT("Ignoring QueryTimer Expriation in state %s"),
  3670. IRLAP_StateStr[pIrlapCb->State]));
  3671. }
  3672. IRLAP_LOG_COMPLETE(pIrlapCb);
  3673. return;
  3674. }
  3675. /*****************************************************************************
  3676. *
  3677. */
  3678. VOID
  3679. SlotTimerExp(PVOID Context)
  3680. {
  3681. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  3682. IRDA_MSG IMsg;
  3683. IRLAP_LOG_START((pIrlapCb, TEXT("Slot timer expired, slot=%d"),pIrlapCb->SlotCnt+1));
  3684. if (pIrlapCb->State == DSCV_QUERY)
  3685. {
  3686. pIrlapCb->SlotCnt++;
  3687. SendDscvXIDCmd(pIrlapCb);
  3688. if (pIrlapCb->SlotCnt < pIrlapCb->MaxSlot)
  3689. {
  3690. IMsg.Prim = MAC_CONTROL_REQ;
  3691. IMsg.IRDA_MSG_Op = MAC_MEDIA_SENSE;
  3692. IMsg.IRDA_MSG_SenseTime = IRLAP_DSCV_SENSE_TIME;
  3693. IRLAP_LOG_ACTION((pIrlapCb, TEXT("MAC_CONTROL_REQ (dscv sense)")));
  3694. IrmacDown(pIrlapCb->pIrdaLinkCb,&IMsg);
  3695. }
  3696. else
  3697. {
  3698. //IndicateLinkStatus(pIrlapCb, LINK_STATUS_IDLE);
  3699. pIrlapCb->GenNewAddr = FALSE;
  3700. IMsg.Prim = IRLAP_DISCOVERY_CONF;
  3701. IMsg.IRDA_MSG_pDevList = &pIrlapCb->DevList;
  3702. IMsg.IRDA_MSG_DscvStatus = IRLAP_DISCOVERY_COMPLETED;
  3703. // Change state now so IRLMP can do DISCOVERY_REQ on this thread
  3704. pIrlapCb->State = NDM;
  3705. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  3706. }
  3707. }
  3708. else
  3709. {
  3710. IRLAP_LOG_ACTION((pIrlapCb, TEXT("Ignoring SlotTimer Expriation in state %s"),
  3711. IRLAP_StateStr[pIrlapCb->State]));
  3712. ; // maybe return bad state ???
  3713. }
  3714. IRLAP_LOG_COMPLETE(pIrlapCb);
  3715. return;
  3716. }
  3717. /*****************************************************************************
  3718. *
  3719. */
  3720. VOID
  3721. FinalTimerExp(PVOID Context)
  3722. {
  3723. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  3724. IRDA_MSG IMsg;
  3725. IRLAP_LOG_START((pIrlapCb, TEXT("Final timer expired")));
  3726. pIrlapCb->NoResponse = TRUE;
  3727. pIrlapCb->FTimerExpCnt++;
  3728. switch (pIrlapCb->State)
  3729. {
  3730. case SNRM_SENT:
  3731. if (pIrlapCb->RetryCnt < pIrlapCb->N3)
  3732. {
  3733. pIrlapCb->BackoffTimer.Timeout = IRLAP_BACKOFF_TIME();
  3734. IrlapTimerStart(pIrlapCb, &pIrlapCb->BackoffTimer);
  3735. pIrlapCb->State = BACKOFF_WAIT;
  3736. }
  3737. else
  3738. {
  3739. ApplyDefaultParms(pIrlapCb);
  3740. pIrlapCb->RetryCnt = 0;
  3741. IMsg.Prim = IRLAP_DISCONNECT_IND;
  3742. IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE;
  3743. pIrlapCb->State = NDM;
  3744. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  3745. }
  3746. break;
  3747. case P_RECV:
  3748. if (pIrlapCb->RetryCnt == pIrlapCb->N2)
  3749. {
  3750. pIrlapCb->RetryCnt = 0; // Don't have to, do it for logger
  3751. IMsg.Prim = IRLAP_DISCONNECT_IND;
  3752. IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE;
  3753. pIrlapCb->State = NDM;
  3754. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  3755. ReturnRxTxWinMsgs(pIrlapCb);
  3756. ApplyDefaultParms(pIrlapCb);
  3757. }
  3758. else
  3759. {
  3760. pIrlapCb->RetryCnt++;
  3761. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  3762. SendRR_RNR(pIrlapCb);
  3763. if (pIrlapCb->RetryCnt == pIrlapCb->N1)
  3764. {
  3765. pIrlapCb->StatusFlags = LF_INTERRUPTED;
  3766. IndicateLinkStatus(pIrlapCb);
  3767. }
  3768. }
  3769. break;
  3770. case P_DISCONNECT_PEND:
  3771. SendDISC(pIrlapCb);
  3772. pIrlapCb->RetryCnt = 0;
  3773. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  3774. GotoPCloseState(pIrlapCb);
  3775. break;
  3776. case P_CLOSE:
  3777. if (pIrlapCb->RetryCnt >= pIrlapCb->N3)
  3778. {
  3779. ApplyDefaultParms(pIrlapCb);
  3780. pIrlapCb->RetryCnt = 0; // Don't have to, do it for logger
  3781. IMsg.Prim = IRLAP_DISCONNECT_IND;
  3782. IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE;
  3783. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  3784. GotoNDMThenDscvOrConn(pIrlapCb);
  3785. }
  3786. else
  3787. {
  3788. pIrlapCb->RetryCnt++;
  3789. SendDISC(pIrlapCb);
  3790. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  3791. }
  3792. break;
  3793. default:
  3794. IRLAP_LOG_ACTION((pIrlapCb,
  3795. TEXT("Ignoring Final Expriation in state %s"),
  3796. IRLAP_StateStr[pIrlapCb->State]));
  3797. }
  3798. IRLAP_LOG_COMPLETE(pIrlapCb);
  3799. return;
  3800. }
  3801. /*****************************************************************************
  3802. *
  3803. */
  3804. VOID
  3805. PollTimerExp(PVOID Context)
  3806. {
  3807. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  3808. IRLAP_LOG_START((pIrlapCb, TEXT("Poll timer expired")));
  3809. if (pIrlapCb->State == P_XMIT)
  3810. {
  3811. SendRR_RNR(pIrlapCb);
  3812. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  3813. pIrlapCb->State = P_RECV;
  3814. }
  3815. else
  3816. {
  3817. IRLAP_LOG_ACTION((pIrlapCb,
  3818. TEXT("Ignoring Poll Expriation in state %s"),
  3819. IRLAP_StateStr[pIrlapCb->State]));
  3820. }
  3821. IRLAP_LOG_COMPLETE(pIrlapCb);
  3822. return;
  3823. }
  3824. /*****************************************************************************
  3825. *
  3826. */
  3827. VOID
  3828. BackoffTimerExp(PVOID Context)
  3829. {
  3830. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  3831. IRLAP_LOG_START((pIrlapCb, TEXT("Backoff timer expired")));
  3832. if (pIrlapCb->State == BACKOFF_WAIT)
  3833. {
  3834. SendSNRM(pIrlapCb, TRUE);
  3835. IrlapTimerStart(pIrlapCb, &pIrlapCb->FinalTimer);
  3836. pIrlapCb->RetryCnt += 1;
  3837. pIrlapCb->State = SNRM_SENT;
  3838. }
  3839. else
  3840. {
  3841. IRLAP_LOG_ACTION((pIrlapCb,
  3842. TEXT("Ignoring BackoffTimer Expriation in this state ")));
  3843. }
  3844. IRLAP_LOG_COMPLETE(pIrlapCb);
  3845. return;
  3846. }
  3847. /*****************************************************************************
  3848. *
  3849. */
  3850. VOID
  3851. WDogTimerExp(PVOID Context)
  3852. {
  3853. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  3854. IRDA_MSG IMsg;
  3855. IRLAP_LOG_START((pIrlapCb, TEXT("WDog timer expired")));
  3856. pIrlapCb->NoResponse = TRUE;
  3857. switch (pIrlapCb->State)
  3858. {
  3859. case S_DISCONNECT_PEND:
  3860. case S_NRM:
  3861. pIrlapCb->WDogExpCnt++;
  3862. // Disconnect/threshold time is in seconds
  3863. if (pIrlapCb->WDogExpCnt * (int)pIrlapCb->WDogTimer.Timeout >=
  3864. pIrlapCb->DisconnectTime * 1000)
  3865. {
  3866. pIrlapCb->State = NDM;
  3867. IMsg.Prim = IRLAP_DISCONNECT_IND;
  3868. IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE;
  3869. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  3870. ReturnRxTxWinMsgs(pIrlapCb);
  3871. ApplyDefaultParms(pIrlapCb);
  3872. }
  3873. else
  3874. {
  3875. if ((pIrlapCb->WDogExpCnt * (int) pIrlapCb->WDogTimer.Timeout >=
  3876. pIrlapCb->ThresholdTime * 1000) && !pIrlapCb->StatusSent)
  3877. {
  3878. pIrlapCb->StatusFlags = LF_INTERRUPTED;
  3879. IndicateLinkStatus(pIrlapCb);
  3880. pIrlapCb->StatusSent = TRUE;
  3881. }
  3882. IrlapTimerStart(pIrlapCb, &pIrlapCb->WDogTimer);
  3883. }
  3884. break;
  3885. case S_CLOSE:
  3886. ApplyDefaultParms(pIrlapCb);
  3887. IMsg.Prim = IRLAP_DISCONNECT_IND;
  3888. IMsg.IRDA_MSG_DiscStatus = IRLAP_NO_RESPONSE;
  3889. pIrlapCb->State = NDM;
  3890. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  3891. break;
  3892. default:
  3893. IRLAP_LOG_ACTION((pIrlapCb,
  3894. TEXT("Ignore WDogTimer expiration in state %s"),
  3895. IRLAP_StateStr[pIrlapCb->State]));
  3896. }
  3897. IRLAP_LOG_COMPLETE(pIrlapCb);
  3898. return;
  3899. }
  3900. /*
  3901. VOID
  3902. StatusTimerExp(PVOID Context)
  3903. {
  3904. PIRLAP_CB pIrlapCb = (PIRLAP_CB) Context;
  3905. IndicateLinkStatus(pIrlapCb);
  3906. }
  3907. */
  3908. /*****************************************************************************
  3909. *
  3910. * @func ret_type | func_name | funcdesc
  3911. *
  3912. * @rdesc return desc
  3913. * @flag val | desc
  3914. *
  3915. * @parm data_type | parm_name | description
  3916. *
  3917. * @comm
  3918. * comments
  3919. *
  3920. * @ex
  3921. * example
  3922. */
  3923. /* !!!
  3924. void
  3925. IRLAP_PrintState()
  3926. {
  3927. #if DBG
  3928. DEBUGMSG(1, (TEXT("IRLAP State %s\n"), IRLAP_StateStr[pIrlapCb->State]));
  3929. #else
  3930. DEBUGMSG(1, (TEXT("IRLAP State %d\n"), pIrlapCb->State));
  3931. #endif
  3932. DEBUGMSG(1,
  3933. (TEXT(" Vs=%d Vr=%d RxWin(%d,%d) TxWin(%d,%d) TxMsgListLen=%d RxMsgFreeListLen=%d\r\n"),
  3934. pIrlapCb->Vs, pIrlapCb->Vr,
  3935. pIrlapCb->RxWin.Start, pIrlapCb->RxWin.End,
  3936. pIrlapCb->TxWin.Start, pIrlapCb->TxWin.End,
  3937. pIrlapCb->TxMsgList.Len, pIrlapCb->RxMsgFreeList.Len));
  3938. #ifdef TEMPERAMENTAL_SERIAL_DRIVER
  3939. DEBUGMSG(1, (TEXT(" Tossed duplicates %d\n"), TossedDups));
  3940. #endif
  3941. IRMAC_PrintState();
  3942. return;
  3943. }
  3944. */
  3945. int
  3946. GetMyDevAddr(BOOLEAN New)
  3947. {
  3948. #ifndef UNDER_CE
  3949. int DevAddr, NewDevAddr;
  3950. LARGE_INTEGER li;
  3951. KeQueryTickCount(&li);
  3952. NewDevAddr = (int) li.LowPart;
  3953. DevAddr = NewDevAddr;
  3954. #else
  3955. int DevAddr = GetTickCount();
  3956. HKEY hKey;
  3957. LONG hRes;
  3958. TCHAR KeyName[32];
  3959. ULONG RegDevAddr = 0;
  3960. TCHAR ValName[] = TEXT("DevAddr");
  3961. // Get the device address from the registry. If the key exists and the
  3962. // value is 0, store a new random address. If no key, then return
  3963. // a random address.
  3964. _tcscpy (KeyName, COMM_REG_KEY);
  3965. _tcscat (KeyName, TEXT("IrDA"));
  3966. hRes = RegOpenKeyEx (HKEY_LOCAL_MACHINE, KeyName, 0, 0, &hKey);
  3967. if (hRes == ERROR_SUCCESS &&
  3968. GetRegDWORDValue(hKey, ValName, &RegDevAddr))
  3969. {
  3970. if (RegDevAddr == 0)
  3971. {
  3972. RegDevAddr = GetTickCount();
  3973. SetRegDWORDValue(hKey, ValName, RegDevAddr);
  3974. }
  3975. RegCloseKey(hKey);
  3976. DevAddr = (int) RegDevAddr;
  3977. }
  3978. #endif
  3979. return DevAddr;
  3980. }
  3981. VOID
  3982. StatusReq(
  3983. PIRLAP_CB pIrlapCb,
  3984. IRDA_MSG *pMsg)
  3985. {
  3986. PIRLINK_STATUS pLinkStatus = (IRLINK_STATUS *) pMsg->IRDA_MSG_pLinkStatus;
  3987. CTEMemCopy(pLinkStatus->ConnectedDeviceId,
  3988. pIrlapCb->RemoteDevice.DevAddr,
  3989. IRDA_DEV_ADDR_LEN);
  3990. pLinkStatus->ConnectSpeed = pIrlapCb->Baud;
  3991. }
  3992. VOID
  3993. IndicateLinkStatus(PIRLAP_CB pIrlapCb)
  3994. {
  3995. IRDA_MSG IMsg;
  3996. IRLINK_STATUS LinkStatus;
  3997. CTEMemCopy(LinkStatus.ConnectedDeviceId,
  3998. pIrlapCb->RemoteDevice.DevAddr,
  3999. IRDA_DEV_ADDR_LEN);
  4000. LinkStatus.ConnectSpeed = pIrlapCb->Baud;
  4001. if (pIrlapCb->StatusFlags & LF_INTERRUPTED)
  4002. {
  4003. LinkStatus.Flags = LF_INTERRUPTED;
  4004. }
  4005. else
  4006. {
  4007. if (pIrlapCb->State >= P_XMIT)
  4008. {
  4009. LinkStatus.Flags = LF_CONNECTED;
  4010. }
  4011. else
  4012. {
  4013. LinkStatus.Flags = 0;
  4014. }
  4015. LinkStatus.Flags |= pIrlapCb->StatusFlags;
  4016. pIrlapCb->StatusFlags = 0;
  4017. }
  4018. IMsg.Prim = IRLAP_STATUS_IND;
  4019. IMsg.IRDA_MSG_pLinkStatus = &LinkStatus;
  4020. IrlmpUp(pIrlapCb->pIrdaLinkCb, &IMsg);
  4021. /*
  4022. if (pIrlapCb->State >= P_XMIT && pIrlapCb->MonitorLink)
  4023. {
  4024. IrdaTimerStart(&pIrlapCb->StatusTimer);
  4025. }
  4026. */
  4027. }
  4028. /*
  4029. VOID
  4030. IrlapGetLinkStatus(PIRLINK_STATUS pLinkStatus)
  4031. {
  4032. PIRDA_LINK_CB pIrdaLinkCb = (PIRDA_LINK_CB) IrdaLinkCbList.Flink;
  4033. PIRLAP_CB pIrlapCb = (PIRLAP_CB) pIrdaLinkCb->IrlapContext;
  4034. pLinkStatus->Flags = 0;
  4035. if (IrdaLinkCbList.Flink == &IrdaLinkCbList)
  4036. {
  4037. return;
  4038. }
  4039. CTEMemCopy(pLinkStatus->ConnectedDeviceId,
  4040. pIrlapCb->RemoteDevice.DevAddr,
  4041. IRDA_DEV_ADDR_LEN);
  4042. pLinkStatus->ConnectSpeed = pIrlapCb->Baud;
  4043. if (pIrlapCb->StatusFlags & LF_INTERRUPTED)
  4044. {
  4045. pLinkStatus->Flags = LF_INTERRUPTED;
  4046. return;
  4047. }
  4048. else if (pIrlapCb->State >= P_XMIT)
  4049. {
  4050. pLinkStatus->Flags = LF_CONNECTED;
  4051. }
  4052. pLinkStatus->Flags |= pIrlapCb->StatusFlags;
  4053. pIrlapCb->StatusFlags = 0;
  4054. return;
  4055. }
  4056. BOOLEAN
  4057. IrlapConnectionActive(PVOID Context)
  4058. {
  4059. PIRLAP_CB pIrlapCb = Context;
  4060. if (pIrlapCb->State >= P_XMIT)
  4061. {
  4062. return TRUE;
  4063. }
  4064. else
  4065. {
  4066. return FALSE;
  4067. }
  4068. }
  4069. */