Source code of Windows XP (NT5)
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.

2738 lines
76 KiB

  1. /**************************************************************************************************************************
  2. * RECEIVE.C SigmaTel STIR4200 packet reception and decoding module
  3. **************************************************************************************************************************
  4. * (C) Unpublished Copyright of Sigmatel, Inc. All Rights Reserved.
  5. *
  6. *
  7. * Created: 04/06/2000
  8. * Version 0.9
  9. * Edited: 04/24/2000
  10. * Version 0.91
  11. * Edited: 04/27/2000
  12. * Version 0.92
  13. * Edited: 05/03/2000
  14. * Version 0.93
  15. * Edited: 05/12/2000
  16. * Version 0.94
  17. * Edited: 05/19/2000
  18. * Version 0.95
  19. * Edited: 07/13/2000
  20. * Version 1.00
  21. * Edited: 08/22/2000
  22. * Version 1.02
  23. * Edited: 09/25/2000
  24. * Version 1.10
  25. * Edited: 10/13/2000
  26. * Version 1.11
  27. * Edited: 11/09/2000
  28. * Version 1.12
  29. * Edited: 12/29/2000
  30. * Version 1.13
  31. * Edited: 01/16/2001
  32. * Version 1.14
  33. * Edited: 02/20/2001
  34. * Version 1.15
  35. *
  36. **************************************************************************************************************************/
  37. #define DOBREAKS // enable debug breaks
  38. #include <ndis.h>
  39. #include <ntdef.h>
  40. #include <windef.h>
  41. #include "stdarg.h"
  42. #include "stdio.h"
  43. #include "debug.h"
  44. #include "usbdi.h"
  45. #include "usbdlib.h"
  46. #include "ircommon.h"
  47. #include "irusb.h"
  48. /*****************************************************************************
  49. *
  50. * Function: ReceiveProcessFifoData
  51. *
  52. * Synopsis: Processes the received data and indicates packets to the protocol
  53. *
  54. * Arguments: pThisDev - pointer to current ir device object
  55. *
  56. * Returns: None
  57. *
  58. *
  59. *****************************************************************************/
  60. VOID
  61. ReceiveProcessFifoData(
  62. IN OUT PIR_DEVICE pThisDev
  63. )
  64. {
  65. ULONG BytesProcessed;
  66. BOOLEAN ReturnValue = TRUE;
  67. while( ReturnValue )
  68. {
  69. if( pThisDev->currentSpeed<=MAX_SIR_SPEED )
  70. {
  71. ReturnValue = ReceiveSirStepFSM( pThisDev, &BytesProcessed );
  72. }
  73. else if( pThisDev->currentSpeed<=MAX_MIR_SPEED )
  74. {
  75. ReturnValue = ReceiveMirStepFSM( pThisDev, &BytesProcessed );
  76. }
  77. else
  78. {
  79. ReturnValue = ReceiveFirStepFSM( pThisDev, &BytesProcessed );
  80. }
  81. }
  82. //
  83. // Indicate that we are no more receiving
  84. //
  85. InterlockedExchange( (PLONG)&pThisDev->fCurrentlyReceiving, FALSE );
  86. }
  87. /*****************************************************************************
  88. *
  89. * Function: ReceiveResetPointers
  90. *
  91. * Synopsis: Reset the receive pointers as the data is gone when we are sending
  92. *
  93. * Arguments: pThisDev - pointer to current ir device object
  94. *
  95. * Returns: None
  96. *
  97. *
  98. *****************************************************************************/
  99. VOID
  100. ReceiveResetPointers(
  101. IN OUT PIR_DEVICE pThisDev
  102. )
  103. {
  104. pThisDev->rcvState = STATE_INIT;
  105. pThisDev->readBufPos = 0;
  106. }
  107. /*****************************************************************************
  108. *
  109. * Function: ReceivePreprocessFifo
  110. *
  111. * Synopsis: Verifies if there is data to be received
  112. *
  113. * Arguments: MiniportAdapterContext - pointer to current ir device object
  114. * pFifoCount - pinter to count to return
  115. *
  116. * Returns: NT status code
  117. *
  118. *
  119. *****************************************************************************/
  120. NTSTATUS
  121. ReceivePreprocessFifo(
  122. IN OUT PIR_DEVICE pThisDev,
  123. OUT PULONG pFifoCount
  124. )
  125. {
  126. NTSTATUS Status;
  127. #ifdef WORKAROUND_POLLING_FIFO_COUNT
  128. LARGE_INTEGER CurrentTime;
  129. BOOLEAN SlowReceive;
  130. ULONG OldFifoCount = 0;
  131. LONG Delay;
  132. //
  133. // Set the receive algorithm
  134. //
  135. #if defined(SUPPORT_LA8)
  136. if( pThisDev->ChipRevision >= CHIP_REVISION_8 )
  137. SlowReceive = FALSE;
  138. else
  139. #endif
  140. SlowReceive = TRUE;
  141. if( SlowReceive )
  142. {
  143. Status = St4200GetFifoCount( pThisDev, pFifoCount );
  144. if( Status != STATUS_SUCCESS )
  145. {
  146. DEBUGMSG(DBG_ERR, (" ReceivePreprocessFifo(): USB failure\n"));
  147. return Status;
  148. }
  149. }
  150. else
  151. {
  152. *pFifoCount = 1;
  153. }
  154. //
  155. // Receive the data
  156. //
  157. if( *pFifoCount || pThisDev->fReadHoldingReg )
  158. {
  159. //
  160. // See if we need to take care of the fake empty FIFO
  161. //
  162. #if defined( WORKAROUND_FAKE_EMPTY_FIFO )
  163. if( *pFifoCount )
  164. {
  165. #endif
  166. //
  167. // If we are in SIR read again until we see a stable value
  168. //
  169. if( (pThisDev->currentSpeed <= MAX_SIR_SPEED) && (pThisDev->currentSpeed != SPEED_9600) && SlowReceive )
  170. {
  171. //
  172. // Make also sure we don't ever wrap
  173. //
  174. while( (OldFifoCount != *pFifoCount) && (*pFifoCount < 9*STIR4200_FIFO_SIZE/10) )
  175. {
  176. OldFifoCount = *pFifoCount;
  177. St4200GetFifoCount( pThisDev, pFifoCount );
  178. }
  179. }
  180. //
  181. // If we are in FIR we need to delay
  182. //
  183. if( (pThisDev->currentSpeed > MAX_MIR_SPEED) && SlowReceive )
  184. {
  185. if( pThisDev->ChipRevision < CHIP_REVISION_7 )
  186. {
  187. #if !defined(ONLY_ERROR_MESSAGES)
  188. DEBUGMSG(DBG_ERR, (" ReceivePreprocessFifo(): Delaying\n"));
  189. #endif
  190. Delay = STIR4200_READ_DELAY - (STIR4200_READ_DELAY*(*pFifoCount))/STIR4200_ESC_PACKET_SIZE;
  191. if( Delay > 0 )
  192. {
  193. NdisStallExecution( (ULONG)Delay );
  194. }
  195. }
  196. else //if( pThisDev->dongleCaps.windowSize == 2 )
  197. {
  198. /*if( !(*pFifoCount%10) )
  199. {
  200. DEBUGMSG(DBG_ERR, (" ReceivePreprocessFifo(): Forcing wrap\n"));
  201. NdisMSleep( 1000 );
  202. }*/
  203. Delay = pThisDev->ReceiveAdaptiveDelay -
  204. (pThisDev->ReceiveAdaptiveDelay*(*pFifoCount))/STIR4200_MULTIPLE_READ_THREHOLD;
  205. if( Delay > 0 )
  206. {
  207. NdisStallExecution( (ULONG)Delay );
  208. }
  209. }
  210. }
  211. #if defined( WORKAROUND_FAKE_EMPTY_FIFO )
  212. }
  213. //
  214. // Read after a successful bulk-in with count of zero
  215. //
  216. else
  217. {
  218. pThisDev->fReadHoldingReg = FALSE;
  219. }
  220. #endif
  221. //
  222. // Perform the read
  223. //
  224. pThisDev->PreReadBuffer.DataLen = 0;
  225. Status = ReceivePacketRead(
  226. pThisDev,
  227. &pThisDev->PreReadBuffer
  228. );
  229. if( Status == STATUS_SUCCESS )
  230. {
  231. *pFifoCount = pThisDev->PreReadBuffer.DataLen;
  232. #if defined( WORKAROUND_FAKE_EMPTY_FIFO )
  233. //
  234. // If we got data restore the flag
  235. //
  236. if( *pFifoCount )
  237. {
  238. pThisDev->fReadHoldingReg = TRUE;
  239. }
  240. #endif
  241. #if !defined(ONLY_ERROR_MESSAGES) && defined( WORKAROUND_FAKE_EMPTY_FIFO )
  242. if( *pFifoCount && !pThisDev->fReadHoldingReg )
  243. DEBUGMSG(DBG_ERR, (" ReceivePreprocessFifo(): Final byte(s) workaround\n"));
  244. #endif
  245. #if defined(RECEIVE_LOGGING)
  246. if( pThisDev->ReceiveFileHandle && *pFifoCount )
  247. {
  248. IO_STATUS_BLOCK IoStatusBlock;
  249. ZwWriteFile(
  250. pThisDev->ReceiveFileHandle,
  251. NULL,
  252. NULL,
  253. NULL,
  254. &IoStatusBlock,
  255. pThisDev->PreReadBuffer.pDataBuf,
  256. pThisDev->PreReadBuffer.DataLen,
  257. (PLARGE_INTEGER)&pThisDev->ReceiveFilePosition,
  258. NULL
  259. );
  260. pThisDev->ReceiveFilePosition += pThisDev->PreReadBuffer.DataLen;
  261. }
  262. #endif
  263. }
  264. else
  265. {
  266. DEBUGMSG(DBG_ERR, (" ReceivePreprocessFifo(): USB failure\n"));
  267. pThisDev->PreReadBuffer.DataLen = 0;
  268. *pFifoCount = 0;
  269. }
  270. }
  271. #else
  272. Status = ReceivePacketRead(
  273. pThisDev,
  274. &pThisDev->PreReadBuffer
  275. );
  276. if( Status == STATUS_SUCCESS )
  277. *pFifoCount = pThisDev->PreReadBuffer.DataLen;
  278. #endif
  279. return Status;
  280. }
  281. /*****************************************************************************
  282. *
  283. * Function: ReceiveGetFifoData
  284. *
  285. * Synopsis: Load the preprocessed data if any is vailable, otherwise tries to read and load new data
  286. *
  287. * Arguments: pThisDev - pointer to current ir device object
  288. * pData - buffer to copy to
  289. * pBytesRead - pointer to return bytes read
  290. * BytesToRead - requested number of bytes
  291. *
  292. * Returns: Number of bytes in the FIFO
  293. *
  294. *
  295. *****************************************************************************/
  296. NTSTATUS
  297. ReceiveGetFifoData(
  298. IN OUT PIR_DEVICE pThisDev,
  299. OUT PUCHAR pData,
  300. OUT PULONG pBytesRead,
  301. ULONG BytesToRead
  302. )
  303. {
  304. NTSTATUS Status;
  305. #ifdef WORKAROUND_POLLING_FIFO_COUNT
  306. LARGE_INTEGER CurrentTime;
  307. BOOLEAN SlowReceive;
  308. ULONG FifoCount = 0, OldFifoCount = 0;
  309. LONG Delay;
  310. //
  311. // Make sure if there is data in the preread buffer
  312. //
  313. if( pThisDev->PreReadBuffer.DataLen )
  314. {
  315. ULONG OutputBufferSize;
  316. IRUSB_ASSERT( pThisDev->PreReadBuffer.DataLen <= BytesToRead );
  317. //
  318. // Copy the data
  319. //
  320. RtlCopyMemory( pData, pThisDev->PreReadBuffer.pDataBuf, pThisDev->PreReadBuffer.DataLen );
  321. #if !defined(WORKAROUND_BROKEN_MIR)
  322. //
  323. // Consider MIR
  324. //
  325. if( pThisDev->currentSpeed == SPEED_1152000 )
  326. ReceiveMirUnstuff(
  327. pThisDev,
  328. pData,
  329. pThisDev->PreReadBuffer.DataLen,
  330. pThisDev->pRawUnstuffedBuf,
  331. &OutputBufferSize
  332. );
  333. #endif
  334. *pBytesRead = pThisDev->PreReadBuffer.DataLen;
  335. pThisDev->PreReadBuffer.DataLen = 0;
  336. return STATUS_SUCCESS;
  337. }
  338. //
  339. // Try to read if no data is already available
  340. //
  341. else
  342. {
  343. //
  344. // Set the receive algorithm
  345. //
  346. #if defined(SUPPORT_LA8)
  347. if( pThisDev->ChipRevision >= CHIP_REVISION_8 )
  348. SlowReceive = FALSE;
  349. else
  350. #endif
  351. SlowReceive = TRUE;
  352. if( SlowReceive )
  353. {
  354. Status = St4200GetFifoCount( pThisDev, &FifoCount );
  355. if( Status != STATUS_SUCCESS )
  356. {
  357. DEBUGMSG(DBG_ERR, (" ReceiveGetFifoData(): USB failure\n"));
  358. return Status;
  359. }
  360. }
  361. else
  362. {
  363. FifoCount = 1;
  364. }
  365. //
  366. // Receive the data
  367. //
  368. if( FifoCount || pThisDev->fReadHoldingReg )
  369. {
  370. //
  371. // See if we need to take care of the fake empty FIFO
  372. //
  373. #if defined( WORKAROUND_FAKE_EMPTY_FIFO )
  374. if( FifoCount )
  375. {
  376. #endif
  377. //
  378. // If we are in SIR read again until we see a stable value
  379. //
  380. #if defined( WORKAROUND_9600_ANTIBOUNCING )
  381. if( (pThisDev->currentSpeed <= MAX_SIR_SPEED) && SlowReceive )
  382. {
  383. if( pThisDev->currentSpeed != SPEED_9600 )
  384. {
  385. //
  386. // Make also sure we don't ever wrap
  387. //
  388. while( (OldFifoCount != FifoCount) && (FifoCount < 9*STIR4200_FIFO_SIZE/10) )
  389. {
  390. OldFifoCount = FifoCount;
  391. St4200GetFifoCount( pThisDev, &FifoCount );
  392. }
  393. }
  394. else
  395. {
  396. if( pThisDev->rcvState != STATE_INIT )
  397. {
  398. while( OldFifoCount != FifoCount )
  399. {
  400. OldFifoCount = FifoCount;
  401. St4200GetFifoCount( pThisDev, &FifoCount );
  402. }
  403. }
  404. }
  405. }
  406. #else
  407. if( (pThisDev->currentSpeed <= MAX_SIR_SPEED) && ( pThisDev->currentSpeed != SPEED_9600) && SlowReceive )
  408. {
  409. while( OldFifoCount != FifoCount )
  410. {
  411. OldFifoCount = FifoCount;
  412. St4200GetFifoCount( pThisDev, &FifoCount );
  413. }
  414. }
  415. #endif
  416. //
  417. // If we are in FIR we need to delay
  418. //
  419. if( (pThisDev->currentSpeed > MAX_MIR_SPEED) && SlowReceive )
  420. {
  421. if( pThisDev->ChipRevision <= CHIP_REVISION_6 )
  422. {
  423. #if !defined(ONLY_ERROR_MESSAGES)
  424. DEBUGMSG(DBG_ERR, (" ReceiveGetFifoData(): Delaying\n"));
  425. #endif
  426. Delay = STIR4200_READ_DELAY - (STIR4200_READ_DELAY*FifoCount)/STIR4200_ESC_PACKET_SIZE;
  427. if( Delay > 0 )
  428. {
  429. NdisStallExecution( (ULONG)Delay );
  430. }
  431. }
  432. else //if( pThisDev->dongleCaps.windowSize == 2 )
  433. {
  434. /*if( !(FifoCount%10) )
  435. {
  436. DEBUGMSG(DBG_ERR, (" ReceiveGetFifoData(): Forcing wrap\n"));
  437. NdisMSleep( 1000 );
  438. }*/
  439. Delay = pThisDev->ReceiveAdaptiveDelay -
  440. (pThisDev->ReceiveAdaptiveDelay*FifoCount)/STIR4200_MULTIPLE_READ_THREHOLD;
  441. if( Delay > 0 )
  442. {
  443. NdisStallExecution( (ULONG)Delay );
  444. }
  445. }
  446. }
  447. #if defined( WORKAROUND_FAKE_EMPTY_FIFO )
  448. }
  449. else
  450. {
  451. // Force antibouncing to take care of OHCI
  452. if( pThisDev->currentSpeed <= MAX_SIR_SPEED )
  453. {
  454. if( pThisDev->rcvState != STATE_INIT )
  455. {
  456. OldFifoCount = 1;
  457. while( OldFifoCount != FifoCount )
  458. {
  459. OldFifoCount = FifoCount;
  460. St4200GetFifoCount( pThisDev, &FifoCount );
  461. }
  462. }
  463. }
  464. pThisDev->fReadHoldingReg = FALSE;
  465. }
  466. #endif
  467. //
  468. // Perform the read
  469. //
  470. pThisDev->PreReadBuffer.DataLen = 0;
  471. Status = ReceivePacketRead(
  472. pThisDev,
  473. &pThisDev->PreReadBuffer
  474. );
  475. if( Status == STATUS_SUCCESS )
  476. {
  477. IRUSB_ASSERT( pThisDev->PreReadBuffer.DataLen <= BytesToRead );
  478. //
  479. // Copy the data
  480. //
  481. RtlCopyMemory( pData, pThisDev->PreReadBuffer.pDataBuf, pThisDev->PreReadBuffer.DataLen );
  482. FifoCount = pThisDev->PreReadBuffer.DataLen;
  483. #if defined( WORKAROUND_FAKE_EMPTY_FIFO )
  484. //
  485. // If we got data restore the flag
  486. //
  487. if( FifoCount )
  488. {
  489. pThisDev->fReadHoldingReg = TRUE;
  490. }
  491. #endif
  492. #if !defined(ONLY_ERROR_MESSAGES) && defined( WORKAROUND_FAKE_EMPTY_FIFO )
  493. if( FifoCount && !pThisDev->fReadHoldingReg )
  494. DEBUGMSG(DBG_ERR, (" ReceiveGetFifoData(): Final byte(s) workaround\n"));
  495. #endif
  496. #if defined(RECEIVE_LOGGING)
  497. if( pThisDev->ReceiveFileHandle && FifoCount )
  498. {
  499. IO_STATUS_BLOCK IoStatusBlock;
  500. ZwWriteFile(
  501. pThisDev->ReceiveFileHandle,
  502. NULL,
  503. NULL,
  504. NULL,
  505. &IoStatusBlock,
  506. pThisDev->PreReadBuffer.pDataBuf,
  507. pThisDev->PreReadBuffer.DataLen,
  508. (PLARGE_INTEGER)&pThisDev->ReceiveFilePosition,
  509. NULL
  510. );
  511. pThisDev->ReceiveFilePosition += pThisDev->PreReadBuffer.DataLen;
  512. }
  513. #endif
  514. pThisDev->PreReadBuffer.DataLen = 0;
  515. }
  516. else
  517. {
  518. DEBUGMSG(DBG_ERR, (" ReceiveGetFifoData(): USB failure\n"));
  519. pThisDev->PreReadBuffer.DataLen = 0;
  520. FifoCount = 0;
  521. }
  522. }
  523. }
  524. *pBytesRead = FifoCount;
  525. return Status;
  526. #else
  527. if( pThisDev->PreReadBuffer.DataLen )
  528. {
  529. IRUSB_ASSERT( pThisDev->PreReadBuffer.DataLen <= BytesToRead );
  530. //
  531. // Copy the data
  532. //
  533. RtlCopyMemory( pData, pThisDev->PreReadBuffer.pDataBuf, pThisDev->PreReadBuffer.DataLen );
  534. *pBytesRead = pThisDev->PreReadBuffer.DataLen;
  535. pThisDev->PreReadBuffer.DataLen = 0;
  536. return STATUS_SUCCESS;
  537. }
  538. else
  539. {
  540. Status = ReceivePacketRead(
  541. pThisDev,
  542. &pThisDev->PreReadBuffer
  543. );
  544. if( Status == STATUS_SUCCESS )
  545. {
  546. RtlCopyMemory( pData, pThisDev->PreReadBuffer.pDataBuf, pThisDev->PreReadBuffer.DataLen );
  547. *pBytesRead = pThisDev->PreReadBuffer.DataLen;
  548. pThisDev->PreReadBuffer.DataLen = 0;
  549. }
  550. return Status;
  551. }
  552. #endif
  553. }
  554. /*****************************************************************************
  555. *
  556. * Function: ReceiveFirStepFSM
  557. *
  558. * Synopsis: Step the receive FSM to read in a piece of an IrDA frame.
  559. * Strip the BOFs and EOF, and eliminate escape sequences.
  560. *
  561. * Arguments: pIrDev - pointer to the current IR device object
  562. * pBytesProcessed - pointer to bytes processed
  563. *
  564. * Returns: TRUE after an entire frame has been read in
  565. * FALSE otherwise
  566. *
  567. *****************************************************************************/
  568. BOOLEAN
  569. ReceiveFirStepFSM(
  570. IN OUT PIR_DEVICE pIrDev,
  571. OUT PULONG pBytesProcessed
  572. )
  573. {
  574. ULONG rawBufPos, rawBytesRead;
  575. BOOLEAN FrameProcessed = FALSE, ForceExit = FALSE;
  576. UCHAR ThisChar;
  577. PUCHAR pRawBuf, pReadBuf;
  578. PRCV_BUFFER pRecBuf;
  579. *pBytesProcessed = 0;
  580. if( !pIrDev->pCurrentRecBuf )
  581. {
  582. UINT Index;
  583. pRecBuf = ReceiveGetBuf( pIrDev, &Index, RCV_STATE_FULL );
  584. if( !pRecBuf )
  585. {
  586. //
  587. // no buffers available; stop
  588. //
  589. DEBUGMSG(DBG_ERR, (" ReceiveSirStepFSM out of buffers\n"));
  590. pIrDev->packetsReceivedNoBuffer ++;
  591. return FALSE;
  592. }
  593. pIrDev->pCurrentRecBuf = pRecBuf;
  594. }
  595. else
  596. pRecBuf = pIrDev->pCurrentRecBuf;
  597. pReadBuf = pRecBuf->pDataBuf;
  598. pRawBuf = pIrDev->pRawBuf;
  599. /***********************************************/
  600. /* Read in and process groups of incoming */
  601. /* bytes from the FIFO. */
  602. /***********************************************/
  603. while( (pIrDev->rcvState != STATE_SAW_EOF) &&
  604. (pIrDev->readBufPos <= (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + FAST_IR_FCS_SIZE)) &&
  605. !ForceExit )
  606. {
  607. if( pIrDev->rcvState == STATE_CLEANUP )
  608. {
  609. /***********************************************/
  610. /* We returned a complete packet last time, */
  611. /* but we had read some extra bytes, which */
  612. /* we stored into the rawBuf after */
  613. /* returning the previous complete buffer */
  614. /* to the user. So instead of calling */
  615. /* DoRcvDirect() in this first execution of */
  616. /* this loop, we just use these previously */
  617. /* read bytes. (This is typically only 1 or */
  618. /* 2 bytes). */
  619. /***********************************************/
  620. rawBytesRead = pIrDev->rawCleanupBytesRead;
  621. pIrDev->rcvState = STATE_INIT;
  622. }
  623. else
  624. {
  625. if( ReceiveGetFifoData( pIrDev, pRawBuf, &rawBytesRead, STIR4200_FIFO_SIZE ) == STATUS_SUCCESS )
  626. {
  627. if( rawBytesRead == (ULONG)-1 )
  628. {
  629. /***********************************************/
  630. /* Receive error...back to INIT state... */
  631. /***********************************************/
  632. pIrDev->rcvState = STATE_INIT;
  633. pIrDev->readBufPos = 0;
  634. continue;
  635. }
  636. else if( rawBytesRead == 0 )
  637. {
  638. /***********************************************/
  639. /* No more receive bytes...break out... */
  640. /***********************************************/
  641. break;
  642. }
  643. }
  644. else
  645. break;
  646. }
  647. /***********************************************/
  648. /* Let the receive state machine process */
  649. /* this group of bytes. */
  650. /* */
  651. /* NOTE: We have to loop once more after */
  652. /* getting MAX_RCV_DATA_SIZE bytes so that */
  653. /* we can see the 'EOF'; hence <= and not */
  654. /* <. */
  655. /***********************************************/
  656. for( rawBufPos = 0;
  657. ((pIrDev->rcvState != STATE_SAW_EOF) && (rawBufPos < rawBytesRead) &&
  658. (pIrDev->readBufPos <= (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + FAST_IR_FCS_SIZE)));
  659. rawBufPos++ )
  660. {
  661. *pBytesProcessed += 1;
  662. ThisChar = pRawBuf[rawBufPos];
  663. switch( pIrDev->rcvState )
  664. {
  665. case STATE_INIT:
  666. switch( ThisChar )
  667. {
  668. case STIR4200_FIR_BOF:
  669. pIrDev->rcvState = STATE_GOT_FIR_BOF;
  670. break;
  671. #if defined(WORKAROUND_XX_HANG)
  672. case 0x3F:
  673. if( (rawBufPos+1) < rawBytesRead )
  674. {
  675. if( pRawBuf[rawBufPos+1] == 0x3F )
  676. {
  677. DEBUGMSG(DBG_INT_ERR,
  678. (" ReceiveFirStepFSM(): hang sequence in INIT state\n"));
  679. St4200ResetFifo( pIrDev );
  680. }
  681. }
  682. break;
  683. #endif
  684. #if defined(WORKAROUND_FF_HANG)
  685. case 0xFF:
  686. if( (rawBufPos+2) < rawBytesRead )
  687. {
  688. if( (pRawBuf[rawBufPos+2] == 0xFF) && (pRawBuf[rawBufPos+1] == 0xFF) &&
  689. (rawBytesRead>STIR4200_FIFO_OVERRUN_THRESHOLD) )
  690. {
  691. DEBUGMSG(DBG_INT_ERR,
  692. (" ReceiveFirStepFSM(): overflow sequence in INIT state\n"));
  693. St4200ResetFifo( pIrDev );
  694. rawBufPos = rawBytesRead;
  695. ForceExit = TRUE;
  696. }
  697. }
  698. break;
  699. #endif
  700. default:
  701. DEBUGMSG(DBG_INT_ERR,
  702. (" ReceiveFirStepFSM(): invalid char in INIT state\n"));
  703. break;
  704. }
  705. break;
  706. case STATE_GOT_FIR_BOF:
  707. switch( ThisChar )
  708. {
  709. case STIR4200_FIR_BOF:
  710. pIrDev->rcvState = STATE_GOT_BOF;
  711. break;
  712. #if defined(WORKAROUND_BAD_ESC)
  713. case STIR4200_FIR_ESC_CHAR:
  714. DEBUGMSG(DBG_INT_ERR,
  715. (" ReceiveFirStepFSM(): invalid char in BOF state, bufpos=%d, char=%X\n", pIrDev->readBufPos, (ULONG)ThisChar));
  716. if( rawBufPos < (rawBytesRead-1) )
  717. {
  718. pIrDev->rcvState = STATE_GOT_BOF;
  719. rawBufPos ++;
  720. }
  721. else
  722. {
  723. pIrDev->rcvState = STATE_INIT;
  724. pIrDev->readBufPos = 0;
  725. }
  726. break;
  727. #endif
  728. default:
  729. DEBUGMSG(DBG_INT_ERR,
  730. (" ReceiveFirStepFSM(): invalid char in BOF state, bufpos=%d, char=%X\n", pIrDev->readBufPos, (ULONG)ThisChar));
  731. #if defined(WORKAROUND_BAD_SOF)
  732. pIrDev->rcvState = STATE_GOT_BOF;
  733. rawBufPos --;
  734. #else
  735. pIrDev->rcvState = STATE_INIT;
  736. pIrDev->readBufPos = 0;
  737. #endif
  738. break;
  739. }
  740. break;
  741. case STATE_GOT_BOF:
  742. switch( ThisChar )
  743. {
  744. case STIR4200_FIR_BOF:
  745. /***********************************************/
  746. /* It's a mistake, but could still be valid data
  747. /***********************************************/
  748. DEBUGMSG(DBG_INT_ERR,
  749. (" ReceiveFirStepFSM(): More than legal BOFs, bufpos=%d\n", pIrDev->readBufPos));
  750. pIrDev->rcvState = STATE_GOT_BOF;
  751. pIrDev->readBufPos = 0;
  752. break;
  753. case STIR4200_FIR_PREAMBLE:
  754. /***********************************************/
  755. /* Garbage */
  756. /***********************************************/
  757. DEBUGMSG(DBG_INT_ERR,
  758. (" ReceiveFirStepFSM(): invalid char in BOF state, bufpos=%d, char=%X\n", pIrDev->readBufPos, (ULONG)ThisChar));
  759. pIrDev->packetsReceivedDropped ++;
  760. pIrDev->rcvState = STATE_INIT;
  761. pIrDev->readBufPos = 0;
  762. break;
  763. case STIR4200_FIR_ESC_CHAR:
  764. /***********************************************/
  765. /* Start of data. Our first data byte */
  766. /* happens to be an ESC sequence. */
  767. /***********************************************/
  768. pIrDev->rcvState = STATE_ESC_SEQUENCE;
  769. pIrDev->readBufPos = 0;
  770. break;
  771. default:
  772. pReadBuf[0] = ThisChar;
  773. pIrDev->rcvState = STATE_ACCEPTING;
  774. pIrDev->readBufPos = 1;
  775. break;
  776. }
  777. break;
  778. case STATE_ACCEPTING:
  779. switch( ThisChar )
  780. {
  781. case STIR4200_FIR_EOF:
  782. #if defined( WORKAROUND_33_HANG )
  783. if( pIrDev->readBufPos < (IRDA_A_C_TOTAL_SIZE + FAST_IR_FCS_SIZE - 1) )
  784. #else
  785. if( pIrDev->readBufPos < (IRDA_A_C_TOTAL_SIZE + FAST_IR_FCS_SIZE) )
  786. #endif
  787. {
  788. DEBUGMSG(DBG_INT_ERR,
  789. ("ReceiveFirStepFSM(): WARNING: EOF encountered in short packet, bufpos=%d\n", pIrDev->readBufPos));
  790. pIrDev->packetsReceivedRunt ++;
  791. pIrDev->rcvState = STATE_INIT;
  792. pIrDev->readBufPos = 0;
  793. }
  794. else
  795. {
  796. #if defined( WORKAROUND_MISSING_7E )
  797. // Force to get out if there is one EOF and we have no more data
  798. if( rawBufPos == (rawBytesRead-1) )
  799. {
  800. #if !defined(ONLY_ERROR_MESSAGES)
  801. DEBUGMSG(DBG_INT_ERR, ("ReceiveFirStepFSM(): Using a single 7E EOF\n"));
  802. #endif
  803. pIrDev->rcvState = STATE_SAW_EOF;
  804. }
  805. else
  806. pIrDev->rcvState = STATE_SAW_FIR_BOF;
  807. #else
  808. pIrDev->rcvState = STATE_SAW_FIR_BOF;
  809. #endif
  810. }
  811. break;
  812. case STIR4200_FIR_ESC_CHAR:
  813. pIrDev->rcvState = STATE_ESC_SEQUENCE;
  814. break;
  815. case STIR4200_FIR_PREAMBLE:
  816. DEBUGMSG(DBG_INT_ERR,
  817. (" ReceiveFirStepFSM(): invalid preamble char in ACCEPTING state, bufpos=%d\n", pIrDev->readBufPos));
  818. pIrDev->packetsReceivedDropped ++;
  819. pIrDev->rcvState = STATE_INIT;
  820. pIrDev->readBufPos = 0;
  821. break;
  822. default:
  823. pReadBuf[pIrDev->readBufPos++] = ThisChar;
  824. break;
  825. }
  826. break;
  827. case STATE_ESC_SEQUENCE:
  828. switch( ThisChar )
  829. {
  830. case STIR4200_FIR_ESC_DATA_7D:
  831. pReadBuf[pIrDev->readBufPos++] = 0x7d;
  832. pIrDev->rcvState = STATE_ACCEPTING;
  833. break;
  834. case STIR4200_FIR_ESC_DATA_7E:
  835. pReadBuf[pIrDev->readBufPos++] = 0x7e;
  836. pIrDev->rcvState = STATE_ACCEPTING;
  837. break;
  838. case STIR4200_FIR_ESC_DATA_7F:
  839. pReadBuf[pIrDev->readBufPos++] = 0x7f;
  840. pIrDev->rcvState = STATE_ACCEPTING;
  841. break;
  842. default:
  843. DEBUGMSG(DBG_INT_ERR,
  844. (" ReceiveFirStepFSM(): invalid escaped char=%X\n", (ULONG)ThisChar));
  845. pIrDev->packetsReceivedDropped ++;
  846. pIrDev->rcvState = STATE_INIT;
  847. pIrDev->readBufPos = 0;
  848. break;
  849. }
  850. break;
  851. case STATE_SAW_FIR_BOF:
  852. switch( ThisChar )
  853. {
  854. case STIR4200_FIR_EOF:
  855. pIrDev->rcvState = STATE_SAW_EOF;
  856. break;
  857. default:
  858. DEBUGMSG(DBG_INT_ERR,
  859. (" ReceiveFirStepFSM(): invalid char=%X, expected EOF\n", (ULONG)ThisChar));
  860. pIrDev->rcvState = STATE_SAW_EOF;
  861. #if !defined(WORKAROUND_MISSING_7E)
  862. pIrDev->packetsReceivedDropped ++;
  863. pIrDev->rcvState = STATE_INIT;
  864. pIrDev->readBufPos = 0;
  865. #endif
  866. break;
  867. }
  868. break;
  869. case STATE_SAW_EOF:
  870. default:
  871. DEBUGMSG(DBG_ERR, (" ReceiveFirStepFSM(): Illegal state, bufpos=%d\n", pIrDev->readBufPos));
  872. IRUSB_ASSERT( 0 );
  873. pIrDev->readBufPos = 0;
  874. pIrDev->rcvState = STATE_INIT;
  875. return FALSE;
  876. }
  877. }
  878. }
  879. // * Set result and do any post-cleanup.
  880. switch( pIrDev->rcvState )
  881. {
  882. case STATE_SAW_EOF:
  883. /***********************************************/
  884. /* We've read in the entire packet. Queue */
  885. /* it and return TRUE. */
  886. /***********************************************/
  887. pRecBuf->DataLen = pIrDev->readBufPos;
  888. pIrDev->pCurrentRecBuf = NULL;
  889. ReceiveDeliverBuffer(
  890. pIrDev,
  891. pRecBuf
  892. );
  893. FrameProcessed = TRUE;
  894. if( rawBufPos < rawBytesRead )
  895. {
  896. /***********************************************/
  897. /* This is ugly. We have some more */
  898. /* unprocessed bytes in the raw buffer. */
  899. /* Move these to the beginning of the raw */
  900. /* buffer go to the CLEANUP state, which */
  901. /* indicates that these bytes be used up */
  902. /* during the next call. (This is typically */
  903. /* only 1 or 2 bytes). */
  904. /* */
  905. /* Note: We can't just leave these in the */
  906. /* raw buffer because we might be */
  907. /* supporting connections to multiple COM */
  908. /* ports. */
  909. /* */
  910. /***********************************************/
  911. RtlMoveMemory( pRawBuf, &pRawBuf[rawBufPos], rawBytesRead - rawBufPos );
  912. pIrDev->rawCleanupBytesRead = rawBytesRead - rawBufPos;
  913. pIrDev->rcvState = STATE_CLEANUP;
  914. }
  915. else
  916. {
  917. pIrDev->rcvState = STATE_INIT;
  918. }
  919. pIrDev->readBufPos = 0;
  920. break;
  921. default:
  922. if( pIrDev->readBufPos > (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + FAST_IR_FCS_SIZE) )
  923. {
  924. DEBUGMSG( DBG_INT_ERR,(" ReceiveFirStepFSM() Overflow\n"));
  925. St4200ResetFifo( pIrDev );
  926. pIrDev->packetsReceivedOverflow ++;
  927. pIrDev->rcvState = STATE_INIT;
  928. pIrDev->readBufPos = 0;
  929. pIrDev->pCurrentRecBuf = NULL;
  930. InterlockedExchange( &pRecBuf->DataLen, 0 );
  931. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  932. }
  933. else
  934. {
  935. #if !defined(ONLY_ERROR_MESSAGES)
  936. DEBUGMSG(DBG_INT_ERR,
  937. (" ReceiveFirStepFSM(): returning with partial packet, read %d bytes\n", pIrDev->readBufPos));
  938. #endif
  939. }
  940. FrameProcessed = FALSE;
  941. break;
  942. }
  943. return FrameProcessed;
  944. }
  945. #if !defined(WORKAROUND_BROKEN_MIR)
  946. /*****************************************************************************
  947. *
  948. * Function: ReceiveMirUnstuff
  949. *
  950. * Synopsis: Software unstuffing for a MIR frmae
  951. *
  952. * Arguments: pIrDev - pointer to the current IR device object
  953. * pBytesProcessed - pointer to bytes processed
  954. *
  955. * Returns: TRUE after an entire frame has been read in
  956. *
  957. *****************************************************************************/
  958. BOOLEAN
  959. ReceiveMirUnstuff(
  960. IN OUT PIR_DEVICE pIrDev,
  961. IN PUCHAR pInputBuffer,
  962. ULONG InputBufferSize,
  963. OUT PUCHAR pOutputBuffer,
  964. OUT PULONG pOutputBufferSize
  965. )
  966. {
  967. ULONG MirIncompleteBitCount = pIrDev->MirIncompleteBitCount;
  968. ULONG MirOneBitCount = pIrDev->MirOneBitCount;
  969. UCHAR MirIncompleteByte = pIrDev->MirIncompleteByte;
  970. ULONG ByteCounter, BitCounter;
  971. BOOL MirUnstuffNext = FALSE;
  972. *pOutputBufferSize = 0;
  973. if( MirOneBitCount == 5 )
  974. {
  975. MirUnstuffNext = TRUE;
  976. }
  977. //
  978. // Loop on the input buffer
  979. //
  980. for( ByteCounter=0; ByteCounter<InputBufferSize; ByteCounter++ )
  981. {
  982. //
  983. // Loop on the byte
  984. //
  985. for( BitCounter=0; BitCounter<8; BitCounter++ )
  986. {
  987. //
  988. // test for one
  989. //
  990. if( pInputBuffer[ByteCounter] & (0x01<<BitCounter) )
  991. {
  992. //
  993. // Sixth one, reset
  994. //
  995. if( MirUnstuffNext )
  996. {
  997. MirOneBitCount = 0;
  998. MirUnstuffNext = FALSE;
  999. pIrDev->MirFlagCount ++;
  1000. }
  1001. //
  1002. // Increase the one count
  1003. //
  1004. else
  1005. {
  1006. MirOneBitCount ++;
  1007. if( MirOneBitCount == 5 )
  1008. {
  1009. MirUnstuffNext = TRUE;
  1010. }
  1011. }
  1012. //
  1013. // Copy to the temp byte
  1014. //
  1015. MirIncompleteByte += 0x01<<MirIncompleteBitCount;
  1016. //
  1017. // Increase the output bit count
  1018. //
  1019. MirIncompleteBitCount ++;
  1020. }
  1021. else
  1022. {
  1023. //
  1024. // Increase the output bit count if we are not stuffing
  1025. //
  1026. if( !MirUnstuffNext )
  1027. {
  1028. MirIncompleteBitCount ++;
  1029. }
  1030. //
  1031. // Reset
  1032. //
  1033. MirOneBitCount = 0;
  1034. MirUnstuffNext = FALSE;
  1035. //
  1036. // No copy needs to be done
  1037. //
  1038. }
  1039. //
  1040. // Flush to output buffer
  1041. //
  1042. if( MirIncompleteBitCount == 8 )
  1043. {
  1044. pOutputBuffer[*pOutputBufferSize] = MirIncompleteByte;
  1045. (*pOutputBufferSize) ++;
  1046. MirIncompleteBitCount = 0;
  1047. MirIncompleteByte = 0;
  1048. }
  1049. //
  1050. // Check for complete packet
  1051. //
  1052. if( pIrDev->MirFlagCount == 2 )
  1053. {
  1054. pIrDev->MirFlagCount = 0;
  1055. pIrDev->MirIncompleteBitCount = 0;
  1056. pIrDev->MirOneBitCount = 0;
  1057. pIrDev->MirIncompleteByte = 0;
  1058. return TRUE;
  1059. }
  1060. }
  1061. }
  1062. //
  1063. // roll over
  1064. //
  1065. pIrDev->MirIncompleteBitCount = MirIncompleteBitCount;
  1066. pIrDev->MirOneBitCount = MirOneBitCount;
  1067. pIrDev->MirIncompleteByte = MirIncompleteByte;
  1068. return FALSE;
  1069. }
  1070. #endif
  1071. /*****************************************************************************
  1072. *
  1073. * Function: ReceiveMirStepFSM
  1074. *
  1075. * Synopsis: Step the receive FSM to read in a piece of an IrDA frame.
  1076. * Strip the BOFs and EOF, and eliminate escape sequences.
  1077. *
  1078. * Arguments: pIrDev - pointer to the current IR device object
  1079. * pBytesProcessed - pointer to bytes processed
  1080. *
  1081. * Returns: TRUE after an entire frame has been read in
  1082. * FALSE otherwise
  1083. *
  1084. *****************************************************************************/
  1085. BOOLEAN
  1086. ReceiveMirStepFSM(
  1087. IN OUT PIR_DEVICE pIrDev,
  1088. OUT PULONG pBytesProcessed
  1089. )
  1090. {
  1091. ULONG rawBufPos, rawBytesRead;
  1092. BOOLEAN FrameProcessed = FALSE, ForceExit = FALSE;
  1093. UCHAR ThisChar;
  1094. PUCHAR pRawBuf, pReadBuf;
  1095. PRCV_BUFFER pRecBuf;
  1096. *pBytesProcessed = 0;
  1097. if( !pIrDev->pCurrentRecBuf )
  1098. {
  1099. UINT Index;
  1100. pRecBuf = ReceiveGetBuf( pIrDev, &Index, RCV_STATE_FULL );
  1101. if ( !pRecBuf)
  1102. {
  1103. //
  1104. // no buffers available; stop
  1105. //
  1106. DEBUGMSG(DBG_ERR, (" ReceiveMirStepFSM out of buffers\n"));
  1107. pIrDev->packetsReceivedNoBuffer ++;
  1108. return FALSE;
  1109. }
  1110. pIrDev->pCurrentRecBuf = pRecBuf;
  1111. }
  1112. else
  1113. pRecBuf = pIrDev->pCurrentRecBuf;
  1114. pReadBuf = pRecBuf->pDataBuf;
  1115. pRawBuf = pIrDev->pRawBuf;
  1116. /***********************************************/
  1117. /* Read in and process groups of incoming */
  1118. /* bytes from the FIFO. */
  1119. /***********************************************/
  1120. while( (pIrDev->rcvState != STATE_SAW_EOF) &&
  1121. (pIrDev->readBufPos <= (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + MEDIUM_IR_FCS_SIZE)) &&
  1122. !ForceExit )
  1123. {
  1124. if( pIrDev->rcvState == STATE_CLEANUP )
  1125. {
  1126. /***********************************************/
  1127. /* We returned a complete packet last time, */
  1128. /* but we had read some extra bytes, which */
  1129. /* we stored into the rawBuf after */
  1130. /* returning the previous complete buffer */
  1131. /* to the user. So instead of calling */
  1132. /* DoRcvDirect() in this first execution of */
  1133. /* this loop, we just use these previously */
  1134. /* read bytes. (This is typically only 1 or */
  1135. /* 2 bytes). */
  1136. /***********************************************/
  1137. rawBytesRead = pIrDev->rawCleanupBytesRead;
  1138. pIrDev->rcvState = STATE_INIT;
  1139. }
  1140. else
  1141. {
  1142. if( ReceiveGetFifoData( pIrDev, pRawBuf, &rawBytesRead, STIR4200_FIFO_SIZE ) == STATUS_SUCCESS )
  1143. {
  1144. if( rawBytesRead == (ULONG)-1 )
  1145. {
  1146. /***********************************************/
  1147. /* Receive error...back to INIT state... */
  1148. /***********************************************/
  1149. pIrDev->rcvState = STATE_INIT;
  1150. pIrDev->readBufPos = 0;
  1151. continue;
  1152. }
  1153. else if( rawBytesRead == 0 )
  1154. {
  1155. /***********************************************/
  1156. /* No more receive bytes...break out... */
  1157. /***********************************************/
  1158. break;
  1159. }
  1160. }
  1161. else
  1162. break;
  1163. }
  1164. /***********************************************/
  1165. /* Let the receive state machine process */
  1166. /* this group of bytes. */
  1167. /* */
  1168. /* NOTE: We have to loop once more after */
  1169. /* getting MAX_RCV_DATA_SIZE bytes so that */
  1170. /* we can see the 'EOF'; hence <= and not */
  1171. /* <. */
  1172. /***********************************************/
  1173. for( rawBufPos = 0;
  1174. ((pIrDev->rcvState != STATE_SAW_EOF) && (rawBufPos < rawBytesRead) &&
  1175. (pIrDev->readBufPos <= (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + MEDIUM_IR_FCS_SIZE)));
  1176. rawBufPos++ )
  1177. {
  1178. *pBytesProcessed += 1;
  1179. ThisChar = pRawBuf[rawBufPos];
  1180. switch( pIrDev->rcvState )
  1181. {
  1182. case STATE_INIT:
  1183. switch( ThisChar )
  1184. {
  1185. case STIR4200_MIR_BOF:
  1186. pIrDev->rcvState = STATE_GOT_MIR_BOF;
  1187. break;
  1188. case 0xFF:
  1189. if( ((rawBufPos+2) < rawBytesRead) && (rawBufPos==0) )
  1190. {
  1191. if( (pRawBuf[rawBufPos+2] == 0xFF) && (pRawBuf[rawBufPos+1] == 0xFF) )
  1192. {
  1193. DEBUGMSG(DBG_INT_ERR,
  1194. (" ReceiveMirStepFSM(): overflow sequence in INIT state\n"));
  1195. St4200ResetFifo( pIrDev );
  1196. St4200SoftReset( pIrDev );
  1197. //rawBufPos = rawBytesRead;
  1198. //ForceExit = TRUE;
  1199. }
  1200. }
  1201. break;
  1202. default:
  1203. break;
  1204. }
  1205. break;
  1206. case STATE_GOT_MIR_BOF:
  1207. switch( ThisChar )
  1208. {
  1209. case STIR4200_MIR_BOF:
  1210. pIrDev->rcvState = STATE_GOT_BOF;
  1211. break;
  1212. default:
  1213. DEBUGMSG(DBG_INT_ERR,
  1214. (" ReceiveMirStepFSM(): invalid char in BOF state, bufpos=%d\n", pIrDev->readBufPos));
  1215. pIrDev->rcvState = STATE_INIT;
  1216. pIrDev->readBufPos = 0;
  1217. break;
  1218. }
  1219. break;
  1220. case STATE_GOT_BOF:
  1221. switch( ThisChar )
  1222. {
  1223. case STIR4200_MIR_BOF:
  1224. /***********************************************/
  1225. /* It's a mistake, but could still be valid data
  1226. /***********************************************/
  1227. DEBUGMSG(DBG_INT_ERR,
  1228. (" ReceiveMirStepFSM(): More than legal BOFs, bufpos=%d\n", pIrDev->readBufPos));
  1229. pIrDev->readBufPos = 0;
  1230. pIrDev->rcvState = STATE_GOT_BOF;
  1231. break;
  1232. case STIR4200_MIR_ESC_CHAR:
  1233. /***********************************************/
  1234. /* Start of data. Our first data byte */
  1235. /* happens to be an ESC sequence. */
  1236. /***********************************************/
  1237. pIrDev->readBufPos = 0;
  1238. pIrDev->rcvState = STATE_ESC_SEQUENCE;
  1239. break;
  1240. default:
  1241. pReadBuf[0] = ThisChar;
  1242. pIrDev->readBufPos = 1;
  1243. pIrDev->rcvState = STATE_ACCEPTING;
  1244. break;
  1245. }
  1246. break;
  1247. case STATE_ACCEPTING:
  1248. switch( ThisChar )
  1249. {
  1250. case STIR4200_MIR_EOF:
  1251. if( pIrDev->readBufPos < (IRDA_A_C_TOTAL_SIZE + MEDIUM_IR_FCS_SIZE) )
  1252. {
  1253. DEBUGMSG(DBG_INT_ERR,
  1254. (" ReceiveMirStepFSM(): WARNING: EOF encountered in short packet, bufpos=%d\n", pIrDev->readBufPos));
  1255. pIrDev->packetsReceivedRunt ++;
  1256. pIrDev->rcvState = STATE_INIT;
  1257. pIrDev->readBufPos = 0;
  1258. }
  1259. else
  1260. {
  1261. pIrDev->rcvState = STATE_SAW_FIR_BOF;
  1262. }
  1263. break;
  1264. case STIR4200_MIR_ESC_CHAR:
  1265. pIrDev->rcvState = STATE_ESC_SEQUENCE;
  1266. break;
  1267. default:
  1268. pReadBuf[pIrDev->readBufPos++] = ThisChar;
  1269. break;
  1270. }
  1271. break;
  1272. case STATE_ESC_SEQUENCE:
  1273. switch( ThisChar )
  1274. {
  1275. case STIR4200_MIR_ESC_DATA_7D:
  1276. pReadBuf[pIrDev->readBufPos++] = 0x7d;
  1277. pIrDev->rcvState = STATE_ACCEPTING;
  1278. break;
  1279. case STIR4200_MIR_ESC_DATA_7E:
  1280. pReadBuf[pIrDev->readBufPos++] = 0x7e;
  1281. pIrDev->rcvState = STATE_ACCEPTING;
  1282. break;
  1283. default:
  1284. DEBUGMSG(DBG_INT_ERR,
  1285. (" ReceiveFirStepFSM(): invalid escaped char=%X\n", (ULONG)ThisChar));
  1286. pIrDev->packetsReceivedDropped ++;
  1287. pIrDev->rcvState = STATE_INIT;
  1288. pIrDev->readBufPos = 0;
  1289. break;
  1290. }
  1291. break;
  1292. case STATE_SAW_MIR_BOF:
  1293. switch( ThisChar )
  1294. {
  1295. case STIR4200_MIR_EOF:
  1296. pIrDev->rcvState = STATE_SAW_EOF;
  1297. break;
  1298. default:
  1299. DEBUGMSG(DBG_INT_ERR,
  1300. (" ReceiveMirStepFSM(): invalid char=%X, expected EOF\n", (ULONG)ThisChar));
  1301. pIrDev->packetsReceivedDropped ++;
  1302. pIrDev->rcvState = STATE_INIT;
  1303. pIrDev->readBufPos = 0;
  1304. break;
  1305. }
  1306. break;
  1307. case STATE_SAW_EOF:
  1308. default:
  1309. DEBUGMSG(DBG_INT_ERR,
  1310. (" ReceiveMirStepFSM(): Illegal state, bufpos=%d\n", pIrDev->readBufPos));
  1311. IRUSB_ASSERT( 0 );
  1312. pIrDev->readBufPos = 0;
  1313. pIrDev->rcvState = STATE_INIT;
  1314. return FALSE;
  1315. }
  1316. }
  1317. }
  1318. // * Set result and do any post-cleanup.
  1319. switch( pIrDev->rcvState )
  1320. {
  1321. case STATE_SAW_EOF:
  1322. /***********************************************/
  1323. /* We've read in the entire packet. Queue */
  1324. /* it and return TRUE. */
  1325. /***********************************************/
  1326. pRecBuf->DataLen = pIrDev->readBufPos;
  1327. pIrDev->pCurrentRecBuf = NULL;
  1328. ReceiveDeliverBuffer(
  1329. pIrDev,
  1330. pRecBuf
  1331. );
  1332. FrameProcessed = TRUE;
  1333. if( rawBufPos < rawBytesRead )
  1334. {
  1335. /***********************************************/
  1336. /* This is ugly. We have some more */
  1337. /* unprocessed bytes in the raw buffer. */
  1338. /* Move these to the beginning of the raw */
  1339. /* buffer go to the CLEANUP state, which */
  1340. /* indicates that these bytes be used up */
  1341. /* during the next call. (This is typically */
  1342. /* only 1 or 2 bytes). */
  1343. /* */
  1344. /* Note: We can't just leave these in the */
  1345. /* raw buffer because we might be */
  1346. /* supporting connections to multiple COM */
  1347. /* ports. */
  1348. /* */
  1349. /***********************************************/
  1350. RtlMoveMemory( pRawBuf, &pRawBuf[rawBufPos], rawBytesRead - rawBufPos );
  1351. pIrDev->rawCleanupBytesRead = rawBytesRead - rawBufPos;
  1352. pIrDev->rcvState = STATE_CLEANUP;
  1353. }
  1354. else
  1355. {
  1356. pIrDev->rcvState = STATE_INIT;
  1357. }
  1358. pIrDev->readBufPos = 0;
  1359. break;
  1360. default:
  1361. if( pIrDev->readBufPos > (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + MEDIUM_IR_FCS_SIZE) )
  1362. {
  1363. DEBUGMSG( DBG_INT_ERR,(" ReceiveMirStepFSM() Overflow\n"));
  1364. pIrDev->packetsReceivedOverflow ++;
  1365. pIrDev->readBufPos = 0;
  1366. pIrDev->rcvState = STATE_INIT;
  1367. pIrDev->pCurrentRecBuf = NULL;
  1368. InterlockedExchange( &pRecBuf->DataLen, 0 );
  1369. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  1370. }
  1371. else
  1372. {
  1373. #if !defined(ONLY_ERROR_MESSAGES)
  1374. DEBUGMSG(DBG_INT_ERR,
  1375. (" ReceiveMirStepFSM(): returning with partial packet, read %d bytes\n", pIrDev->readBufPos));
  1376. #endif
  1377. }
  1378. FrameProcessed = FALSE;
  1379. break;
  1380. }
  1381. return FrameProcessed;
  1382. }
  1383. /*****************************************************************************
  1384. *
  1385. * Function: ReceiveSirStepFSM
  1386. *
  1387. * Synopsis: Step the receive FSM to read in a piece of an IrDA frame.
  1388. * Strip the BOFs and EOF, and eliminate escape sequences.
  1389. *
  1390. * Arguments: pIrDev - pointer to the current IR device object
  1391. * pBytesProcessed - pointer to bytes processed
  1392. *
  1393. * Returns: TRUE after an entire frame has been read in
  1394. * FALSE otherwise
  1395. *
  1396. *****************************************************************************/
  1397. BOOLEAN
  1398. ReceiveSirStepFSM(
  1399. IN OUT PIR_DEVICE pIrDev,
  1400. OUT PULONG pBytesProcessed
  1401. )
  1402. {
  1403. ULONG rawBufPos, rawBytesRead;
  1404. BOOLEAN FrameProcessed = FALSE, ForceExit = FALSE;
  1405. UCHAR ThisChar;
  1406. PUCHAR pRawBuf, pReadBuf;
  1407. PRCV_BUFFER pRecBuf;
  1408. *pBytesProcessed = 0;
  1409. if( !pIrDev->pCurrentRecBuf )
  1410. {
  1411. UINT Index;
  1412. pRecBuf = ReceiveGetBuf( pIrDev, &Index, RCV_STATE_FULL );
  1413. if ( !pRecBuf)
  1414. {
  1415. //
  1416. // no buffers available; stop
  1417. //
  1418. DEBUGMSG(DBG_ERR, (" ReceiveSirStepFSM out of buffers\n"));
  1419. pIrDev->packetsReceivedNoBuffer ++;
  1420. return FALSE;
  1421. }
  1422. pIrDev->pCurrentRecBuf = pRecBuf;
  1423. }
  1424. else
  1425. pRecBuf = pIrDev->pCurrentRecBuf;
  1426. pReadBuf = pRecBuf->pDataBuf;
  1427. pRawBuf = pIrDev->pRawBuf;
  1428. // Read in and process groups of incoming bytes from the FIFO.
  1429. // NOTE: We have to loop once more after getting MAX_RCV_DATA_SIZE
  1430. // bytes so that we can see the 'EOF'; hence <= and not <.
  1431. while( (pIrDev->rcvState != STATE_SAW_EOF) &&
  1432. (pIrDev->readBufPos <= (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + SLOW_IR_FCS_SIZE)) &&
  1433. !ForceExit )
  1434. {
  1435. if( pIrDev->rcvState == STATE_CLEANUP )
  1436. {
  1437. /***********************************************/
  1438. /* We returned a complete packet last time, */
  1439. /* but we had read some extra bytes, which */
  1440. /* we stored into the rawBuf after */
  1441. /* returning the previous complete buffer */
  1442. /* to the user. So instead of calling */
  1443. /* DoRcvDirect() in this first execution of */
  1444. /* this loop, we just use these previously */
  1445. /* read bytes. (This is typically only 1 or */
  1446. /* 2 bytes). */
  1447. /***********************************************/
  1448. rawBytesRead = pIrDev->rawCleanupBytesRead;
  1449. pIrDev->rcvState = STATE_INIT;
  1450. }
  1451. else
  1452. {
  1453. if( ReceiveGetFifoData( pIrDev, pRawBuf, &rawBytesRead, STIR4200_FIFO_SIZE ) == STATUS_SUCCESS )
  1454. {
  1455. if( rawBytesRead == (ULONG)-1 )
  1456. {
  1457. /***********************************************/
  1458. /* Receive error...back to INIT state... */
  1459. /***********************************************/
  1460. DEBUGMSG( DBG_ERR,(" ReceiveSirStepFSM() Error in receiving packet\n"));
  1461. pIrDev->rcvState = STATE_INIT;
  1462. pIrDev->readBufPos = 0;
  1463. continue;
  1464. }
  1465. else if( rawBytesRead == 0 )
  1466. {
  1467. /***********************************************/
  1468. /* No more receive bytes...break out... */
  1469. /***********************************************/
  1470. #if defined(WORKAROUND_MISSING_C1)
  1471. if( (pIrDev->rcvState == STATE_ACCEPTING) && (pIrDev->ChipRevision <= CHIP_REVISION_7) )
  1472. {
  1473. pIrDev->rcvState = STATE_SAW_EOF;
  1474. DEBUGMSG(DBG_INT_ERR, (" ReceiveSirStepFSM(): Missing C1 workaround\n"));
  1475. pRecBuf->MissingC1Detected = TRUE;
  1476. }
  1477. #endif
  1478. break;
  1479. }
  1480. }
  1481. else
  1482. break;
  1483. }
  1484. /***********************************************/
  1485. /* Let the receive state machine process */
  1486. /* this group of bytes. */
  1487. /* */
  1488. /* NOTE: We have to loop once more after */
  1489. /* getting MAX_RCV_DATA_SIZE bytes so that */
  1490. /* we can see the 'EOF'; hence <= and not */
  1491. /* <. */
  1492. /***********************************************/
  1493. for( rawBufPos = 0;
  1494. ((pIrDev->rcvState != STATE_SAW_EOF) && (rawBufPos < rawBytesRead) &&
  1495. (pIrDev->readBufPos <= (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + SLOW_IR_FCS_SIZE)));
  1496. rawBufPos ++ )
  1497. {
  1498. *pBytesProcessed += 1;
  1499. ThisChar = pRawBuf[rawBufPos];
  1500. switch( pIrDev->rcvState )
  1501. {
  1502. case STATE_INIT:
  1503. switch( ThisChar )
  1504. {
  1505. #if defined(WORKAROUND_FF_HANG)
  1506. case 0xFF:
  1507. if( (rawBufPos+2) < rawBytesRead )
  1508. {
  1509. if( (pRawBuf[rawBufPos+2] == 0xFF) && (pRawBuf[rawBufPos+1] == 0xFF) &&
  1510. (rawBytesRead>STIR4200_FIFO_OVERRUN_THRESHOLD) )
  1511. {
  1512. DEBUGMSG(DBG_INT_ERR,
  1513. (" ReceiveFirStepFSM(): overflow sequence in INIT state\n"));
  1514. St4200DoubleResetFifo( pIrDev );
  1515. rawBufPos = rawBytesRead;
  1516. ForceExit = TRUE;
  1517. }
  1518. }
  1519. break;
  1520. #endif
  1521. #if defined( WORKAROUND_E0_81_FLAG )
  1522. // This will take care of wrong start flags at low rates
  1523. case 0x81:
  1524. case 0xe0:
  1525. #if !defined(ONLY_ERROR_MESSAGES)
  1526. DEBUGMSG(DBG_INT_ERR,
  1527. (" ReceiveSirStepFSM(): WORKAROUND_E0_81_FLAG\n"));
  1528. #endif
  1529. #endif
  1530. case SLOW_IR_BOF:
  1531. pIrDev->rcvState = STATE_GOT_BOF;
  1532. break;
  1533. case SLOW_IR_EOF:
  1534. case SLOW_IR_ESC:
  1535. default:
  1536. /***********************************************/
  1537. /* Byte is garbage...scan past it.... */
  1538. /***********************************************/
  1539. DEBUGMSG(DBG_INT_ERR,
  1540. (" ReceiveSirStepFSM(): invalid char in INIT state\n"));
  1541. break;
  1542. }
  1543. break;
  1544. case STATE_GOT_BOF:
  1545. switch( ThisChar )
  1546. {
  1547. case SLOW_IR_BOF:
  1548. break;
  1549. case SLOW_IR_EOF:
  1550. /***********************************************/
  1551. /* Garbage */
  1552. /***********************************************/
  1553. DEBUGMSG( DBG_INT_ERR,(" ReceiveSirStepFSM() Invalid char in BOF state\n"));
  1554. pIrDev->packetsReceivedDropped ++;
  1555. pIrDev->rcvState = STATE_INIT;
  1556. pIrDev->readBufPos = 0;
  1557. break;
  1558. case SLOW_IR_ESC:
  1559. /***********************************************/
  1560. /* Start of data. Our first data byte */
  1561. /* happens to be an ESC sequence. */
  1562. /***********************************************/
  1563. pIrDev->rcvState = STATE_ESC_SEQUENCE;
  1564. pIrDev->readBufPos = 0;
  1565. break;
  1566. default:
  1567. pReadBuf[0] = ThisChar;
  1568. pIrDev->rcvState = STATE_ACCEPTING;
  1569. pIrDev->readBufPos = 1;
  1570. break;
  1571. }
  1572. break;
  1573. case STATE_ACCEPTING:
  1574. switch( ThisChar )
  1575. {
  1576. case SLOW_IR_BOF:
  1577. //
  1578. // Either a new packet is starting here and we're missing parts of the old one
  1579. // or it's garbage
  1580. //
  1581. #if !defined(WORKAROUND_MISSING_C1)
  1582. DEBUGMSG( DBG_INT_ERR,(" ReceiveSirStepFSM() Invalid char in ACCEPTING state\n"));
  1583. pIrDev->packetsReceivedDropped ++;
  1584. pIrDev->rcvState = STATE_INIT;
  1585. pIrDev->readBufPos = 0;
  1586. break;
  1587. #else
  1588. //
  1589. // Take the packet and decrement the pointer in the FIFO decoding so that
  1590. // the new packet can be processed
  1591. //
  1592. DEBUGMSG( DBG_INT_ERR,(" ReceiveSirStepFSM() C0 in ACCEPTING state, trying workaround\n"));
  1593. rawBufPos --;
  1594. pRecBuf->MissingC1Detected = TRUE;
  1595. #endif
  1596. case SLOW_IR_EOF:
  1597. if( pIrDev->readBufPos < (IRDA_A_C_TOTAL_SIZE + SLOW_IR_FCS_SIZE) )
  1598. {
  1599. pIrDev->packetsReceivedRunt ++;
  1600. pIrDev->rcvState = STATE_INIT;
  1601. pIrDev->readBufPos = 0;
  1602. #if defined(WORKAROUND_MISSING_C1)
  1603. if( pRecBuf->MissingC1Detected )
  1604. pRecBuf->MissingC1Detected = FALSE;
  1605. else
  1606. DEBUGMSG( DBG_INT_ERR,(" ReceiveSirStepFSM() Error packet too small\n"));
  1607. #else
  1608. DEBUGMSG( DBG_INT_ERR,(" ReceiveSirStepFSM() Error packet too small\n"));
  1609. #endif
  1610. }
  1611. else
  1612. {
  1613. pIrDev->rcvState = STATE_SAW_EOF;
  1614. }
  1615. break;
  1616. case SLOW_IR_ESC:
  1617. pIrDev->rcvState = STATE_ESC_SEQUENCE;
  1618. break;
  1619. default:
  1620. pReadBuf[pIrDev->readBufPos++] = ThisChar;
  1621. break;
  1622. }
  1623. break;
  1624. case STATE_ESC_SEQUENCE:
  1625. switch( ThisChar )
  1626. {
  1627. case SLOW_IR_EOF:
  1628. case SLOW_IR_BOF:
  1629. case SLOW_IR_ESC:
  1630. /***********************************************/
  1631. /* ESC + {EOF|BOF|ESC} is an abort sequence */
  1632. /***********************************************/
  1633. pIrDev->rcvState = STATE_INIT;
  1634. pIrDev->readBufPos = 0;
  1635. break;
  1636. case SLOW_IR_EOF ^ SLOW_IR_ESC_COMP:
  1637. case SLOW_IR_BOF ^ SLOW_IR_ESC_COMP:
  1638. case SLOW_IR_ESC ^ SLOW_IR_ESC_COMP:
  1639. pReadBuf[pIrDev->readBufPos++] = ThisChar ^ SLOW_IR_ESC_COMP;
  1640. pIrDev->rcvState = STATE_ACCEPTING;
  1641. break;
  1642. default:
  1643. // junk
  1644. DEBUGMSG(DBG_INT_ERR,
  1645. (" ReceiveSirStepFSM(): invalid escaped char=%X\n", (ULONG)ThisChar));
  1646. pIrDev->packetsReceivedDropped ++;
  1647. pIrDev->rcvState = STATE_INIT;
  1648. pIrDev->readBufPos = 0;
  1649. break;
  1650. }
  1651. break;
  1652. case STATE_SAW_EOF:
  1653. default:
  1654. DEBUGMSG(DBG_INT_ERR,
  1655. (" ReceiveSirStepFSM(): Illegal state, bufpos=%d\n", pIrDev->readBufPos));
  1656. IRUSB_ASSERT( 0 );
  1657. pIrDev->rcvState = STATE_INIT;
  1658. pIrDev->readBufPos = 0;
  1659. return FALSE;
  1660. }
  1661. }
  1662. }
  1663. // * Set result and do any post-cleanup.
  1664. switch( pIrDev->rcvState )
  1665. {
  1666. case STATE_SAW_EOF:
  1667. // We've read in the entire packet.
  1668. // Queue it and return TRUE.
  1669. pRecBuf->DataLen = pIrDev->readBufPos;
  1670. pIrDev->pCurrentRecBuf = NULL;
  1671. ReceiveDeliverBuffer(
  1672. pIrDev,
  1673. pRecBuf
  1674. );
  1675. FrameProcessed = TRUE;
  1676. if( rawBufPos < rawBytesRead )
  1677. {
  1678. /***********************************************/
  1679. /* This is ugly. We have some more */
  1680. /* unprocessed bytes in the raw buffer. */
  1681. /* Move these to the beginning of the raw */
  1682. /* buffer go to the CLEANUP state, which */
  1683. /* indicates that these bytes be used up */
  1684. /* during the next call. (This is typically */
  1685. /* only 1 or 2 bytes). */
  1686. /* */
  1687. /* Note: We can't just leave these in the */
  1688. /* raw buffer because we might be */
  1689. /* supporting connections to multiple COM */
  1690. /* ports. */
  1691. /* */
  1692. /***********************************************/
  1693. RtlMoveMemory( pRawBuf, &pRawBuf[rawBufPos], rawBytesRead - rawBufPos );
  1694. pIrDev->rawCleanupBytesRead = rawBytesRead - rawBufPos;
  1695. pIrDev->rcvState = STATE_CLEANUP;
  1696. #if defined( WORKAROUND_9600_ANTIBOUNCING )
  1697. if( (pIrDev->currentSpeed == SPEED_9600) && (pIrDev->ChipRevision <= CHIP_REVISION_7) )
  1698. {
  1699. #if !defined(ONLY_ERROR_MESSAGES)
  1700. DEBUGMSG(DBG_INT_ERR, (" ReceiveSirStepFSM(): Delaying\n"));
  1701. #endif
  1702. NdisMSleep( 10*1000 );
  1703. }
  1704. #endif
  1705. }
  1706. else
  1707. {
  1708. pIrDev->rcvState = STATE_INIT;
  1709. }
  1710. pIrDev->readBufPos = 0;
  1711. break;
  1712. default:
  1713. if( pIrDev->readBufPos > (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + SLOW_IR_FCS_SIZE) )
  1714. {
  1715. DEBUGMSG( DBG_INT_ERR,(" ReceiveSirStepFSM() Overflow\n"));
  1716. pIrDev->packetsReceivedOverflow ++;
  1717. pIrDev->rcvState = STATE_INIT;
  1718. pIrDev->readBufPos = 0;
  1719. pIrDev->pCurrentRecBuf = NULL;
  1720. InterlockedExchange( &pRecBuf->DataLen, 0 );
  1721. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  1722. }
  1723. else
  1724. {
  1725. #if !defined(ONLY_ERROR_MESSAGES)
  1726. DEBUGMSG(DBG_INT_ERR, (" ReceiveSirStepFSM(): returning with partial packet, read %d bytes\n", pIrDev->readBufPos));
  1727. #endif
  1728. }
  1729. FrameProcessed = FALSE;
  1730. break;
  1731. }
  1732. return FrameProcessed;
  1733. }
  1734. /*****************************************************************************
  1735. *
  1736. * Function: ReceiveProcessReturnPacket
  1737. *
  1738. * Synopsis: Returns the packet to the free pool after preparing for reuse
  1739. *
  1740. * Arguments: pThisDev - pointer to the current ir device object
  1741. * pReceiveBuffer - pointer to a RCV_BUFFER struct
  1742. *
  1743. * Returns: None
  1744. *
  1745. *
  1746. *****************************************************************************/
  1747. VOID
  1748. ReceiveProcessReturnPacket(
  1749. OUT PIR_DEVICE pThisDev,
  1750. OUT PRCV_BUFFER pReceiveBuffer
  1751. )
  1752. {
  1753. PNDIS_BUFFER pBuffer;
  1754. DEBUGONCE(DBG_FUNC, ("+ReceiveProcessReturnPacket\n"));
  1755. //
  1756. // Deallocate the buffer
  1757. //
  1758. NdisUnchainBufferAtFront( (PNDIS_PACKET)pReceiveBuffer->pPacket, &pBuffer );
  1759. IRUSB_ASSERT( pBuffer );
  1760. if( pBuffer )
  1761. {
  1762. NdisFreeBuffer( pBuffer );
  1763. }
  1764. //
  1765. // Get ready to reuse
  1766. //
  1767. InterlockedExchange( &pReceiveBuffer->DataLen, 0 );
  1768. InterlockedExchange( &pReceiveBuffer->fInRcvDpc, FALSE );
  1769. InterlockedExchange( (PULONG)&pReceiveBuffer->BufferState, RCV_STATE_FREE );
  1770. #if DBG
  1771. if( InterlockedDecrement(&pThisDev->packetsHeldByProtocol)<0 )
  1772. {
  1773. IRUSB_ASSERT(0);
  1774. }
  1775. #endif
  1776. DEBUGMSG(DBG_FUNC, ("-ReceiveProcessReturnPacket\n"));
  1777. }
  1778. /*****************************************************************************
  1779. *
  1780. * Function: ReceiveDeliverBuffer
  1781. *
  1782. * Synopsis: Delivers the buffer to the protocol via
  1783. * NdisMIndicateReceivePacket.
  1784. *
  1785. * Arguments: pThisDev - pointer to the current ir device object
  1786. * pRecBuf - poiter to descriptor to deliver
  1787. *
  1788. * Returns: None
  1789. *
  1790. *
  1791. *****************************************************************************/
  1792. VOID
  1793. ReceiveDeliverBuffer(
  1794. IN OUT PIR_DEVICE pThisDev,
  1795. IN PRCV_BUFFER pRecBuf
  1796. )
  1797. {
  1798. PNDIS_BUFFER pBuffer;
  1799. NDIS_STATUS Status;
  1800. DEBUGMSG(DBG_FUNC, ("+ReceiveDeliverBuffer\n"));
  1801. if( pThisDev->currentSpeed <= MAX_MIR_SPEED )
  1802. {
  1803. USHORT sirfcs;
  1804. /***********************************************/
  1805. /* The packet we have already has had BOFs, */
  1806. /* EOF, and * escape-sequences removed. It */
  1807. /* contains an FCS code at the end, which */
  1808. /* we need to verify and then remove before */
  1809. /* delivering the frame. We compute the FCS */
  1810. /* on the packet with the packet FCS */
  1811. /* attached; this should produce the */
  1812. /* constant value GOOD_FCS. */
  1813. /***********************************************/
  1814. if( (sirfcs = ComputeFCS16(pRecBuf->pDataBuf, pRecBuf->DataLen)) != GOOD_FCS )
  1815. {
  1816. #if !defined(WORKAROUND_EXTRA_BYTE) && !defined(WORKAROUND_MISSING_C1)
  1817. //
  1818. // FCS error...drop frame...
  1819. //
  1820. DEBUGMSG( DBG_INT_ERR,(" ReceiveDeliverBuffer(): Bad FCS, size: %d\n",pRecBuf->DataLen));
  1821. pThisDev->packetsReceivedChecksum ++;
  1822. InterlockedExchange( &pRecBuf->DataLen, 0 );
  1823. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  1824. goto done;
  1825. #else
  1826. //
  1827. // Calculate again stripping off the last byte
  1828. //
  1829. if( pRecBuf->MissingC1Detected )
  1830. {
  1831. if( (sirfcs = ComputeFCS16(pRecBuf->pDataBuf, pRecBuf->DataLen-1)) != GOOD_FCS )
  1832. {
  1833. #if defined(RECEIVE_ERROR_LOGGING)
  1834. if( pThisDev->ReceiveErrorFileHandle )
  1835. {
  1836. IO_STATUS_BLOCK IoStatusBlock;
  1837. ZwWriteFile(
  1838. pThisDev->ReceiveErrorFileHandle,
  1839. NULL,
  1840. NULL,
  1841. NULL,
  1842. &IoStatusBlock,
  1843. pRecBuf->pDataBuf,
  1844. pRecBuf->DataLen,
  1845. (PLARGE_INTEGER)&pThisDev->ReceiveErrorFilePosition,
  1846. NULL
  1847. );
  1848. pThisDev->ReceiveErrorFilePosition += pRecBuf->DataLen;
  1849. }
  1850. #endif
  1851. //
  1852. // It is really junk
  1853. //
  1854. DEBUGMSG( DBG_INT_ERR,(" ReceiveDeliverBuffer(): Bad FCS, size: %d\n",pRecBuf->DataLen));
  1855. pThisDev->packetsReceivedChecksum ++;
  1856. InterlockedExchange( &pRecBuf->DataLen, 0 );
  1857. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  1858. pRecBuf->MissingC1Detected = FALSE;
  1859. goto done;
  1860. }
  1861. else
  1862. {
  1863. //
  1864. // Readjust to get rid of the extra byte
  1865. //
  1866. pRecBuf->DataLen --;
  1867. pRecBuf->MissingC1Detected = FALSE;
  1868. }
  1869. }
  1870. else
  1871. {
  1872. //
  1873. // Or maybe the first one
  1874. //
  1875. if( (sirfcs = ComputeFCS16(pRecBuf->pDataBuf+1, pRecBuf->DataLen-1)) != GOOD_FCS )
  1876. {
  1877. #if defined(RECEIVE_ERROR_LOGGING)
  1878. if( pThisDev->ReceiveErrorFileHandle )
  1879. {
  1880. IO_STATUS_BLOCK IoStatusBlock;
  1881. ZwWriteFile(
  1882. pThisDev->ReceiveErrorFileHandle,
  1883. NULL,
  1884. NULL,
  1885. NULL,
  1886. &IoStatusBlock,
  1887. pRecBuf->pDataBuf,
  1888. pRecBuf->DataLen,
  1889. (PLARGE_INTEGER)&pThisDev->ReceiveErrorFilePosition,
  1890. NULL
  1891. );
  1892. pThisDev->ReceiveErrorFilePosition += pRecBuf->DataLen;
  1893. }
  1894. #endif
  1895. //
  1896. // It is really junk
  1897. //
  1898. DEBUGMSG( DBG_INT_ERR,(" ReceiveDeliverBuffer(): Bad FCS, size: %d\n",pRecBuf->DataLen));
  1899. pThisDev->packetsReceivedChecksum ++;
  1900. InterlockedExchange( &pRecBuf->DataLen, 0 );
  1901. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  1902. goto done;
  1903. }
  1904. //
  1905. else
  1906. {
  1907. //
  1908. // Readjust to get rid of the extra byte
  1909. //
  1910. pRecBuf->DataLen --;
  1911. RtlMoveMemory( pRecBuf->pDataBuf, &pRecBuf->pDataBuf[1], pRecBuf->DataLen );
  1912. }
  1913. }
  1914. #endif
  1915. }
  1916. /***********************************************/
  1917. /* Remove FCS from end of packet... */
  1918. /***********************************************/
  1919. pRecBuf->DataLen -= SLOW_IR_FCS_SIZE;
  1920. }
  1921. else
  1922. {
  1923. LONG firfcs;
  1924. #if !defined(WORKAROUND_33_HANG)
  1925. if( (firfcs = ComputeFCS32(pRecBuf->dataBuf, pRecBuf->dataLen)) != FIR_GOOD_FCS )
  1926. {
  1927. /***********************************************/
  1928. /* FCS error...drop frame... */
  1929. /***********************************************/
  1930. DEBUGMSG( DBG_INT_ERR,(" ReceiveDeliverBuffer(): Bad FCS, size: %d\n",pRecBuf->dataLen));
  1931. pThisDev->packetsReceivedChecksum ++;
  1932. InterlockedExchange( &pRecBuf->dataLen, 0 );
  1933. InterlockedExchange( (PULONG)&pRecBuf->state, RCV_STATE_FREE );
  1934. goto done;
  1935. }
  1936. #else
  1937. if( (firfcs = ComputeFCS32(pRecBuf->pDataBuf, pRecBuf->DataLen)) != FIR_GOOD_FCS )
  1938. {
  1939. NTSTATUS rc;
  1940. //
  1941. // Try again with the data stuffed with 0x33
  1942. //
  1943. if( pRecBuf->DataLen < (MAX_TOTAL_SIZE_WITH_ALL_HEADERS + FAST_IR_FCS_SIZE) )
  1944. {
  1945. pRecBuf->pDataBuf[pRecBuf->DataLen] = 0x33;
  1946. pRecBuf->DataLen ++;
  1947. if( (firfcs = ComputeFCS32(pRecBuf->pDataBuf, pRecBuf->DataLen)) != FIR_GOOD_FCS )
  1948. {
  1949. #if defined(RECEIVE_ERROR_LOGGING)
  1950. if( pThisDev->ReceiveErrorFileHandle )
  1951. {
  1952. IO_STATUS_BLOCK IoStatusBlock;
  1953. ZwWriteFile(
  1954. pThisDev->ReceiveErrorFileHandle,
  1955. NULL,
  1956. NULL,
  1957. NULL,
  1958. &IoStatusBlock,
  1959. pRecBuf->pDataBuf,
  1960. pRecBuf->DataLen,
  1961. (PLARGE_INTEGER)&pThisDev->ReceiveErrorFilePosition,
  1962. NULL
  1963. );
  1964. pThisDev->ReceiveErrorFilePosition += pRecBuf->DataLen;
  1965. }
  1966. #endif
  1967. /***********************************************/
  1968. /* FCS error...drop frame... */
  1969. /***********************************************/
  1970. DEBUGMSG( DBG_INT_ERR,(" ReceiveDeliverBuffer(): Bad FCS, size: %d\n",pRecBuf->DataLen));
  1971. pThisDev->ReceiveAdaptiveDelayBoost += STIR4200_DELTA_DELAY;
  1972. if( pThisDev->ReceiveAdaptiveDelayBoost <= STIR4200_MAX_BOOST_DELAY )
  1973. pThisDev->ReceiveAdaptiveDelay += STIR4200_DELTA_DELAY;
  1974. DEBUGMSG( DBG_INT_ERR,(" ReceiveDeliverBuffer(): Delay: %d\n",pThisDev->ReceiveAdaptiveDelay));
  1975. pThisDev->packetsReceivedChecksum ++;
  1976. InterlockedExchange( &pRecBuf->DataLen, 0 );
  1977. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  1978. goto done;
  1979. }
  1980. }
  1981. else
  1982. {
  1983. #if defined(RECEIVE_ERROR_LOGGING)
  1984. if( pThisDev->ReceiveErrorFileHandle )
  1985. {
  1986. IO_STATUS_BLOCK IoStatusBlock;
  1987. ZwWriteFile(
  1988. pThisDev->ReceiveErrorFileHandle,
  1989. NULL,
  1990. NULL,
  1991. NULL,
  1992. &IoStatusBlock,
  1993. pRecBuf->pDataBuf,
  1994. pRecBuf->DataLen,
  1995. (PLARGE_INTEGER)&pThisDev->ReceiveErrorFilePosition,
  1996. NULL
  1997. );
  1998. pThisDev->ReceiveErrorFilePosition += pRecBuf->DataLen;
  1999. }
  2000. #endif
  2001. /***********************************************/
  2002. /* FCS error...drop frame... */
  2003. /***********************************************/
  2004. DEBUGMSG( DBG_INT_ERR,(" ReceiveDeliverBuffer(): Bad FCS, size: %d\n",pRecBuf->DataLen));
  2005. pThisDev->ReceiveAdaptiveDelayBoost += STIR4200_DELTA_DELAY;
  2006. if( pThisDev->ReceiveAdaptiveDelayBoost <= STIR4200_MAX_BOOST_DELAY )
  2007. pThisDev->ReceiveAdaptiveDelay += STIR4200_DELTA_DELAY;
  2008. DEBUGMSG( DBG_INT_ERR,(" ReceiveDeliverBuffer(): Delay: %d\n",pThisDev->ReceiveAdaptiveDelay));
  2009. pThisDev->packetsReceivedChecksum ++;
  2010. InterlockedExchange( &pRecBuf->DataLen, 0 );
  2011. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  2012. goto done;
  2013. }
  2014. //
  2015. // Reset the USB of the part
  2016. //
  2017. if( pThisDev->ChipRevision <= CHIP_REVISION_7 )
  2018. {
  2019. St4200ResetFifo( pThisDev );
  2020. }
  2021. }
  2022. #endif
  2023. /***********************************************/
  2024. /* Remove FCS from end of packet... */
  2025. /***********************************************/
  2026. pRecBuf->DataLen -= FAST_IR_FCS_SIZE;
  2027. }
  2028. //
  2029. // If in normal mode, give the packet to the protocol
  2030. //
  2031. #if defined(DIAGS)
  2032. if( !pThisDev->DiagsActive )
  2033. {
  2034. #endif
  2035. NdisAllocateBuffer(
  2036. &Status,
  2037. &pBuffer,
  2038. pThisDev->hBufferPool,
  2039. (PVOID)pRecBuf->pDataBuf,
  2040. pRecBuf->DataLen
  2041. );
  2042. if( Status != NDIS_STATUS_SUCCESS )
  2043. {
  2044. DEBUGMSG( DBG_ERR,(" ReceiveDeliverBuffer(): No packets available...\n"));
  2045. InterlockedExchange( &pRecBuf->DataLen, 0);
  2046. InterlockedExchange( (PULONG)&pRecBuf->BufferState, RCV_STATE_FREE );
  2047. goto done;
  2048. }
  2049. NdisChainBufferAtFront( (PNDIS_PACKET)pRecBuf->pPacket, pBuffer );
  2050. //
  2051. // Fix up some other packet fields.
  2052. // Remember, we only account for A and C fields
  2053. //
  2054. NDIS_SET_PACKET_HEADER_SIZE(
  2055. (PNDIS_PACKET)pRecBuf->pPacket,
  2056. IRDA_CONTROL_FIELD_SIZE + IRDA_ADDRESS_FIELD_SIZE
  2057. );
  2058. #if DBG
  2059. InterlockedIncrement( &pThisDev->packetsHeldByProtocol );
  2060. if( pThisDev->packetsHeldByProtocol > pThisDev->MaxPacketsHeldByProtocol )
  2061. {
  2062. pThisDev->MaxPacketsHeldByProtocol = pThisDev->packetsHeldByProtocol; //keep record of our longest attained len
  2063. }
  2064. #endif
  2065. #if !defined(ONLY_ERROR_MESSAGES)
  2066. DEBUGMSG( DBG_INT_ERR,
  2067. (" ReceiveDeliverBuffer() Handed packet to protocol, size: %d\n", pRecBuf->DataLen ));
  2068. #endif
  2069. //
  2070. // Indicate the packet to NDIS
  2071. //
  2072. NDIS_SET_PACKET_STATUS( (PNDIS_PACKET)pRecBuf->pPacket, NDIS_STATUS_PENDING );
  2073. InterlockedExchange( &pRecBuf->fInRcvDpc, TRUE );
  2074. NdisMIndicateReceivePacket(
  2075. pThisDev->hNdisAdapter,
  2076. &((PNDIS_PACKET)pRecBuf->pPacket),
  2077. 1
  2078. );
  2079. //
  2080. // Check to see if the packet is not pending (patch for 98)
  2081. //
  2082. #if defined(LEGACY_NDIS5)
  2083. Status = NDIS_GET_PACKET_STATUS( (PNDIS_PACKET)pRecBuf->pPacket );
  2084. if( (Status == NDIS_STATUS_SUCCESS) || (Status == NDIS_STATUS_RESOURCES) )
  2085. {
  2086. ReceiveProcessReturnPacket( pThisDev, pRecBuf ) ;
  2087. }
  2088. #endif
  2089. #if defined(DIAGS)
  2090. }
  2091. //
  2092. // Do a diagnostic receive
  2093. //
  2094. else
  2095. {
  2096. #if !defined(ONLY_ERROR_MESSAGES)
  2097. DEBUGMSG( DBG_INT_ERR,
  2098. (" ReceiveDeliverBuffer() Queued packet, size: %d\n", pRecBuf->DataLen ));
  2099. #endif
  2100. //
  2101. // Put the buffer in the diagnostic queue
  2102. //
  2103. ExInterlockedInsertTailList(
  2104. &pThisDev->DiagsReceiveQueue,
  2105. &pRecBuf->ListEntry,
  2106. &pThisDev->DiagsReceiveLock
  2107. );
  2108. }
  2109. #endif
  2110. done:
  2111. DEBUGMSG(DBG_FUNC, ("-ReceiveDeliverBuffer\n"));
  2112. }
  2113. /*****************************************************************************
  2114. *
  2115. * Function: StIrUsbReturnPacket
  2116. *
  2117. * Synopsis: The protocol returns ownership of a receive packet to
  2118. * the ir device object.
  2119. *
  2120. * Arguments: Context - a pointer to the current ir device obect.
  2121. * pReturnedPacket - a pointer the packet which the protocol
  2122. * is returning ownership.
  2123. *
  2124. * Returns: None.
  2125. *
  2126. *
  2127. *
  2128. *****************************************************************************/
  2129. VOID
  2130. StIrUsbReturnPacket(
  2131. IN OUT NDIS_HANDLE Context,
  2132. IN OUT PNDIS_PACKET pReturnedPacket
  2133. )
  2134. {
  2135. PIR_DEVICE pThisDev;
  2136. PNDIS_BUFFER pBuffer;
  2137. PRCV_BUFFER pRecBuffer;
  2138. UINT Index;
  2139. BOOLEAN found = FALSE;
  2140. DEBUGONCE(DBG_FUNC, ("+StIrUsbReturnPacket\n"));
  2141. //
  2142. // The context is just the pointer to the current ir device object.
  2143. //
  2144. pThisDev = CONTEXT_TO_DEV( Context );
  2145. NdisInterlockedIncrement( (PLONG)&pThisDev->packetsReceived );
  2146. //
  2147. // Search the queue to find the right packet.
  2148. //
  2149. for( Index=0; Index < NUM_RCV_BUFS; Index ++ )
  2150. {
  2151. pRecBuffer = &(pThisDev->rcvBufs[Index]);
  2152. if( ((PNDIS_PACKET) pRecBuffer->pPacket) == pReturnedPacket )
  2153. {
  2154. if( pRecBuffer->fInRcvDpc )
  2155. {
  2156. ReceiveProcessReturnPacket( pThisDev, pRecBuffer );
  2157. found = TRUE;
  2158. }
  2159. else
  2160. {
  2161. DEBUGMSG(DBG_ERR, (" StIrUsbReturnPacket, queues are corrupt\n"));
  2162. IRUSB_ASSERT( 0 );
  2163. }
  2164. break;
  2165. }
  2166. }
  2167. //
  2168. // Ensure that the packet was found.
  2169. //
  2170. IRUSB_ASSERT( found );
  2171. DEBUGMSG(DBG_FUNC, ("-StIrUsbReturnPacket\n"));
  2172. }
  2173. /*****************************************************************************
  2174. *
  2175. * Function: ReceiveGetBuf
  2176. *
  2177. * Synopsis: Gets a receive buffer
  2178. *
  2179. * Arguments: pThisDev - a pointer to the current ir device obect
  2180. * pIndex - pointer to return the buffer index
  2181. * state - state to set the buffer to
  2182. *
  2183. * Returns: buffer
  2184. *
  2185. *
  2186. *****************************************************************************/
  2187. PRCV_BUFFER
  2188. ReceiveGetBuf(
  2189. IN PIR_DEVICE pThisDev,
  2190. OUT PUINT pIndex,
  2191. IN RCV_BUFFER_STATE BufferState
  2192. )
  2193. {
  2194. UINT Index;
  2195. PRCV_BUFFER pBuf = NULL;
  2196. DEBUGMSG(DBG_FUNC, ("+ReceiveGetBuf()\n"));
  2197. //
  2198. // Look for a free buffer to return
  2199. //
  2200. for( Index=0; Index<NUM_RCV_BUFS; Index++ )
  2201. {
  2202. if( pThisDev->rcvBufs[Index].BufferState == RCV_STATE_FREE )
  2203. {
  2204. //
  2205. // set to input state
  2206. //
  2207. InterlockedExchange( (PULONG)&pThisDev->rcvBufs[Index].BufferState, (ULONG)BufferState );
  2208. *pIndex = Index;
  2209. pBuf = &(pThisDev->rcvBufs[*pIndex]);
  2210. break;
  2211. }
  2212. }
  2213. DEBUGMSG(DBG_FUNC, ("-ReceiveGetBuf()\n"));
  2214. return pBuf;
  2215. }
  2216. /*****************************************************************************
  2217. *
  2218. * Function: ReceivePacketRead
  2219. *
  2220. * Synopsis: Reads a packet from the US device
  2221. * the inbound USB header, check for overrun,
  2222. * deliver to the protocol
  2223. *
  2224. * Arguments: pThisDev - pointer to the current ir device object
  2225. * pRecBuf - pointer to a RCV_BUFFER struct
  2226. *
  2227. * Returns: NT status code
  2228. *
  2229. *
  2230. *****************************************************************************/
  2231. NTSTATUS
  2232. ReceivePacketRead(
  2233. IN PIR_DEVICE pThisDev,
  2234. OUT PFIFO_BUFFER pRecBuf
  2235. )
  2236. {
  2237. ULONG UrbSize;
  2238. ULONG TransferLength;
  2239. PURB pUrb = NULL;
  2240. PDEVICE_OBJECT pUrbTargetDev;
  2241. PIO_STACK_LOCATION pNextStack;
  2242. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  2243. DEBUGMSG(DBG_FUNC, ("+ReceivePacketRead()\n"));
  2244. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  2245. UrbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  2246. TransferLength = STIR4200_FIFO_SIZE;
  2247. //
  2248. // Stop if a halt/reset/suspend is going on
  2249. //
  2250. if( pThisDev->fPendingReadClearStall || pThisDev->fPendingHalt ||
  2251. pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall || !pThisDev->fProcessing )
  2252. {
  2253. //
  2254. // USB reset going on?
  2255. //
  2256. DEBUGMSG( DBG_ERR,(" ReceivePacketRead() rejecting a packet due to pendig halt/reset\n"));
  2257. Status = STATUS_UNSUCCESSFUL;
  2258. goto done;
  2259. }
  2260. pUrb = pThisDev->pUrb;
  2261. //
  2262. // Build our URB for USBD
  2263. //
  2264. NdisZeroMemory( pUrb, UrbSize );
  2265. IRUSB_ASSERT( pThisDev->BulkInPipeHandle );
  2266. //
  2267. // Now that we have created the urb, we will send a
  2268. // request to the USB device object.
  2269. //
  2270. KeClearEvent( &pThisDev->EventSyncUrb );
  2271. pUrbTargetDev = pThisDev->pUsbDevObj;
  2272. IRUSB_ASSERT( pUrbTargetDev );
  2273. //
  2274. // make an irp sending to usbhub
  2275. //
  2276. pRecBuf->pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  2277. if( NULL == pRecBuf->pIrp )
  2278. {
  2279. DEBUGMSG(DBG_ERR, (" read failed to alloc IRP\n"));
  2280. Status = STATUS_INSUFFICIENT_RESOURCES;
  2281. goto done;
  2282. }
  2283. ((PIRP)pRecBuf->pIrp)->IoStatus.Status = STATUS_PENDING;
  2284. ((PIRP)pRecBuf->pIrp)->IoStatus.Information = 0;
  2285. //
  2286. // Build our URB for USBD
  2287. //
  2288. pUrb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT)UrbSize;
  2289. pUrb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  2290. pUrb->UrbBulkOrInterruptTransfer.PipeHandle = pThisDev->BulkInPipeHandle;
  2291. pUrb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN ;
  2292. //
  2293. // short packet is not treated as an error.
  2294. //
  2295. pUrb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  2296. //
  2297. // not using linked urb's
  2298. //
  2299. pUrb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
  2300. pUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
  2301. pUrb->UrbBulkOrInterruptTransfer.TransferBuffer = pRecBuf->pDataBuf;
  2302. pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = TransferLength;
  2303. //
  2304. // Call the class driver to perform the operation.
  2305. //
  2306. pNextStack = IoGetNextIrpStackLocation( (PIRP)pRecBuf->pIrp );
  2307. IRUSB_ASSERT( pNextStack != NULL );
  2308. //
  2309. // pass the URB to the USB driver stack
  2310. //
  2311. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  2312. pNextStack->Parameters.Others.Argument1 = pUrb;
  2313. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  2314. IoSetCompletionRoutine(
  2315. ((PIRP)pRecBuf->pIrp), // irp to use
  2316. ReceiveCompletePacketRead, // routine to call when irp is done
  2317. pRecBuf, // context to pass routine is the RCV_BUFFER
  2318. TRUE, // call on success
  2319. TRUE, // call on error
  2320. TRUE // call on cancel
  2321. );
  2322. //
  2323. // Call IoCallDriver to send the irp to the usb port.
  2324. //
  2325. InterlockedExchange( (PLONG)&pRecBuf->BufferState, RCV_STATE_PENDING );
  2326. Status = MyIoCallDriver( pThisDev, pUrbTargetDev, (PIRP)pRecBuf->pIrp ); // Start UsbRead()
  2327. DEBUGMSG(DBG_FUNC, (" ReceivePacketRead() after IoCallDriver () status = 0x%x\n", Status));
  2328. IRUSB_ASSERT( STATUS_SUCCESS != Status );
  2329. //
  2330. // Wait for completion
  2331. //
  2332. Status = MyKeWaitForSingleObject(
  2333. pThisDev,
  2334. &pThisDev->EventSyncUrb, // event to wait on
  2335. NULL, // irp to cancel on halt/reset or timeout
  2336. 0
  2337. );
  2338. if( Status == STATUS_TIMEOUT )
  2339. {
  2340. IrUsb_CancelIo( pThisDev, pRecBuf->pIrp, &pThisDev->EventSyncUrb );
  2341. }
  2342. else
  2343. {
  2344. //
  2345. // Update the status to reflect the real return code
  2346. //
  2347. Status = pThisDev->StatusSendReceive;
  2348. }
  2349. IRUSB_ASSERT( NULL == pRecBuf->pIrp ); // Will be nulled by completion routine
  2350. DEBUGMSG(DBG_FUNC, (" ReceivePacketRead() after KeWaitForSingleObject() Status = 0x%x\n", Status));
  2351. done:
  2352. DEBUGMSG(DBG_FUNC, ("-ReceivePacketRead()\n"));
  2353. return Status;
  2354. }
  2355. /*****************************************************************************
  2356. *
  2357. * Function: ReceiveCompletePacketRead
  2358. *
  2359. * Synopsis: Completes USB read operation
  2360. *
  2361. * Arguments: pUsbDevObj - pointer to the USB device object which
  2362. * completed the irp
  2363. * pIrp - the irp which was completed by the
  2364. * device object
  2365. * Context - the context given to IoSetCompletionRoutine
  2366. * before calling IoCallDriver on the irp
  2367. * The Context is a pointer to the ir device object.
  2368. *
  2369. * Returns: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
  2370. * (IofCompleteRequest) to stop working on the irp.
  2371. *
  2372. *
  2373. *****************************************************************************/
  2374. NTSTATUS
  2375. ReceiveCompletePacketRead(
  2376. IN PDEVICE_OBJECT pUsbDevObj,
  2377. IN PIRP pIrp,
  2378. IN PVOID Context
  2379. )
  2380. {
  2381. PIR_DEVICE pThisDev;
  2382. NTSTATUS status;
  2383. ULONG_PTR BytesRead;
  2384. PFIFO_BUFFER pFifoBuf;
  2385. DEBUGMSG(DBG_FUNC, ("+ReceiveCompletePacketRead\n"));
  2386. //
  2387. // The context given to ReceiveCompletePacketRead is the receive buffer object
  2388. //
  2389. pFifoBuf = (PFIFO_BUFFER)Context;
  2390. pThisDev = (PIR_DEVICE)pFifoBuf->pThisDev;
  2391. IRUSB_ASSERT( pFifoBuf->pIrp == pIrp );
  2392. IRUSB_ASSERT( NULL != pThisDev );
  2393. //
  2394. // We have a number of cases:
  2395. // 1) The USB read timed out and we received no data.
  2396. // 2) The USB read timed out and we received some data.
  2397. // 3) The USB read was successful and fully filled our irp buffer.
  2398. // 4) The irp was cancelled.
  2399. // 5) Some other failure from the USB device object.
  2400. //
  2401. status = pIrp->IoStatus.Status;
  2402. //
  2403. // IoCallDriver has been called on this Irp;
  2404. // Set the length based on the TransferBufferLength
  2405. // value in the URB
  2406. //
  2407. pIrp->IoStatus.Information = pThisDev->pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  2408. BytesRead = pIrp->IoStatus.Information;
  2409. DEBUGMSG(DBG_FUNC, (" ReceiveCompletePacketRead Bytes Read = 0x%x, dec %d\n", BytesRead,BytesRead ));
  2410. switch( status )
  2411. {
  2412. case STATUS_SUCCESS:
  2413. DEBUGMSG(DBG_FUNC, (" ReceiveCompletePacketRead STATUS_SUCCESS\n"));
  2414. if( BytesRead > 0 )
  2415. {
  2416. pFifoBuf->DataLen = (UINT)pIrp->IoStatus.Information;
  2417. }
  2418. break; // STATUS_SUCCESS
  2419. case STATUS_TIMEOUT:
  2420. InterlockedIncrement( (PLONG)&pThisDev->NumDataErrors );
  2421. DEBUGMSG(DBG_FUNC, (" ReceiveCompletePacketRead STATUS_TIMEOUT\n"));
  2422. break;
  2423. case STATUS_PENDING:
  2424. DEBUGMSG(DBG_FUNC, (" ReceiveCompletePacketRead STATUS_PENDING\n"));
  2425. break;
  2426. case STATUS_DEVICE_DATA_ERROR:
  2427. // can get during shutdown
  2428. InterlockedIncrement( (PLONG)&pThisDev->NumDataErrors );
  2429. DEBUGMSG(DBG_FUNC, (" ReceiveCompletePacketRead STATUS_DEVICE_DATA_ERROR\n"));
  2430. break;
  2431. case STATUS_UNSUCCESSFUL:
  2432. InterlockedIncrement( (PLONG)&pThisDev->NumDataErrors );
  2433. DEBUGMSG(DBG_ERR, (" ReceiveCompletePacketRead STATUS_UNSUCCESSFUL\n"));
  2434. break;
  2435. case STATUS_INSUFFICIENT_RESOURCES:
  2436. InterlockedIncrement( (PLONG)&pThisDev->NumDataErrors );
  2437. DEBUGMSG(DBG_ERR, (" ReceiveCompletePacketRead STATUS_INSUFFICIENT_RESOURCES\n"));
  2438. break;
  2439. case STATUS_INVALID_PARAMETER:
  2440. InterlockedIncrement( (PLONG)&pThisDev->NumDataErrors );
  2441. DEBUGMSG(DBG_ERR, (" ReceiveCompletePacketRead STATUS_INVALID_PARAMETER\n"));
  2442. break;
  2443. case STATUS_CANCELLED:
  2444. DEBUGMSG(DBG_FUNC, (" ReceiveCompletePacketRead STATUS_CANCELLED\n"));
  2445. break;
  2446. case STATUS_DEVICE_NOT_CONNECTED:
  2447. // can get during shutdown
  2448. InterlockedIncrement( (PLONG)&pThisDev->NumDataErrors );
  2449. DEBUGMSG(DBG_ERR, (" ReceiveCompletePacketRead STATUS_DEVICE_NOT_CONNECTED\n"));
  2450. break;
  2451. case STATUS_DEVICE_POWER_FAILURE:
  2452. // can get during shutdown
  2453. InterlockedIncrement( (PLONG)&pThisDev->NumDataErrors );
  2454. DEBUGMSG(DBG_ERR, (" ReceiveCompletePacketRead STATUS_DEVICE_POWER_FAILURE\n"));
  2455. break;
  2456. default:
  2457. InterlockedIncrement( (PLONG)&pThisDev->NumDataErrors );
  2458. DEBUGMSG(DBG_ERR, (" ReceiveCompletePacketRead UNKNOWN WEIRD STATUS = 0x%x, dec %d\n",status,status ));
  2459. break;
  2460. }
  2461. //
  2462. // change the status
  2463. //
  2464. if( STATUS_SUCCESS != status )
  2465. {
  2466. InterlockedExchange( (PLONG)&pFifoBuf->BufferState, RCV_STATE_FREE );
  2467. }
  2468. else
  2469. {
  2470. InterlockedExchange( (PLONG)&pFifoBuf->BufferState, RCV_STATE_FULL );
  2471. }
  2472. //
  2473. // Free the IRP and its mdl because they were allocated by us
  2474. //
  2475. IoFreeIrp( pIrp );
  2476. pFifoBuf->pIrp = NULL;
  2477. InterlockedIncrement( (PLONG)&pThisDev->NumReads );
  2478. //
  2479. // we will track count of pending irps
  2480. //
  2481. IrUsb_DecIoCount( pThisDev );
  2482. if( ( STATUS_SUCCESS != status ) && ( STATUS_CANCELLED != status ) &&
  2483. ( STATUS_DEVICE_NOT_CONNECTED != status ) )
  2484. {
  2485. PURB urb = pThisDev->pUrb;
  2486. DEBUGMSG(DBG_ERR, (" USBD status = 0x%x\n", urb->UrbHeader.Status));
  2487. DEBUGMSG(DBG_ERR, (" NT status = 0x%x\n", status));
  2488. if( !pThisDev->fPendingReadClearStall && !pThisDev->fPendingClearTotalStall &&
  2489. !pThisDev->fPendingHalt && !pThisDev->fPendingReset && pThisDev->fProcessing )
  2490. {
  2491. DEBUGMSG(DBG_ERR,
  2492. (" ReceiveCompletePacketRead error, will schedule a clear stall via URB_FUNCTION_RESET_PIPE (IN)\n"));
  2493. InterlockedExchange( &pThisDev->fPendingReadClearStall, TRUE );
  2494. ScheduleWorkItem( pThisDev, ResetPipeCallback, pThisDev->BulkInPipeHandle, 0 );
  2495. }
  2496. }
  2497. //
  2498. // This will only work as long as we serialize the access to the hardware
  2499. //
  2500. pThisDev->StatusSendReceive = status;
  2501. //
  2502. // Signal completion
  2503. //
  2504. KeSetEvent( &pThisDev->EventSyncUrb, 0, FALSE );
  2505. //
  2506. // We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
  2507. // routine (IoCompleteRequest) will stop working on the irp.
  2508. //
  2509. DEBUGMSG(DBG_FUNC, ("-ReceiveCompletePacketRead\n"));
  2510. return STATUS_MORE_PROCESSING_REQUIRED;
  2511. }