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.

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