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.

728 lines
20 KiB

  1. //-------------------------------------------------------------------
  2. // This is abstract class for generic device
  3. // Specific devices should use it as a parent device
  4. // Author: Sergey Ivanov
  5. // Log:
  6. // 01.11.99 - implemented
  7. //-------------------------------------------------------------------
  8. #ifdef USBREADER_PROJECT
  9. #pragma message("COMPILING USB READER...")
  10. #ifndef __USB_READER__
  11. #define __USB_READER__
  12. #include "generic.h"
  13. #include "usbreader.h"
  14. #include "smartcard.h"
  15. #include "usbdev.h"
  16. #include "reader.h"
  17. #include "gemcore.h"
  18. #pragma PAGEDCODE
  19. CUSBReader::CUSBReader()
  20. {
  21. ULONG DevID;
  22. m_Status = STATUS_INSUFFICIENT_RESOURCES;
  23. m_Type = USBREADER_DEVICE;
  24. interface = NULL;
  25. DevID = incrementDeviceNumber();
  26. TRACE("########### Creating USBReader with index %d\n",DevID);
  27. // Each reader creates own smartcard object...
  28. scard_Initialized = FALSE;
  29. smartCard = new (NonPagedPool) CSmartCard;
  30. TRACE("**** Creating pooling thread... ****\n");
  31. // We can not use default device function because it was already used by
  32. // our Io thread (unless we extend it?)
  33. // Lets define new thread function and xfer control to it...
  34. PoolingThread = new (NonPagedPool) CThread((PCLIENT_THREAD_ROUTINE)PoolingThreadFunction,this,
  35. getDevicePoolingInterval());
  36. if(!ALLOCATED_OK(PoolingThread))
  37. {
  38. DISPOSE_OBJECT(PoolingThread);
  39. TRACE("****** FAILED TO CREATE POOLING THREAD!\n");
  40. }
  41. else
  42. {
  43. // Thread which controls asynchronous driver communications
  44. IoThread = new (NonPagedPool) CThread((PCLIENT_THREAD_ROUTINE)ThreadFunction,this,0);
  45. if(!ALLOCATED_OK(IoThread))
  46. {
  47. DISPOSE_OBJECT(IoThread);
  48. TRACE("****** FAILED TO CREATE IO THREAD!\n");
  49. }
  50. else
  51. {
  52. IoThread->start();
  53. setDeviceState(WORKING);
  54. m_Status = STATUS_SUCCESS;
  55. }
  56. }
  57. TRACE("********* USB Reader %8.8lX was created with status %8.8lX...\n",this,m_Status);
  58. }
  59. #pragma PAGEDCODE
  60. CUSBReader::~CUSBReader()
  61. {
  62. TRACE("Destroing USB reader pooling thread...\n");
  63. if(PoolingThread) PoolingThread->dispose();
  64. if(smartCard)
  65. {
  66. TRACE("Disconnecting from smartcard system...\n");
  67. smartCard->smartCardDisconnect();
  68. smartCard->dispose();
  69. }
  70. if(interface) interface->dispose();
  71. if(IoThread) IoThread->stop();
  72. cancelAllPendingRequests();
  73. if(IoThread) IoThread->dispose();
  74. remove();
  75. TRACE("********* USB Reader %8.8lX was destroied...\n",this);
  76. }
  77. //Handle IRP_MJ_DEVICE_READ request
  78. #pragma PAGEDCODE
  79. NTSTATUS CUSBReader::open(IN PIRP Irp)
  80. {
  81. NTSTATUS status;
  82. TRACE("\n------- USB READER OPEN DEVICE --------\n");
  83. if(getDeviceState()!=WORKING)
  84. {
  85. TRACE(" READER IS NOT AT WORKING STATE... State %x\n",getDeviceState());
  86. status = STATUS_DEVICE_NOT_CONNECTED;
  87. return completeDeviceRequest(Irp,status,0);
  88. }
  89. if(IoThread)
  90. {
  91. status = makeRequestPending(Irp,m_DeviceObject,OPEN_REQUEST);
  92. // Tell thread to start processing
  93. if(NT_SUCCESS(status))
  94. {
  95. TRACE("CALL THREAD FUNCTION...\n");
  96. IoThread->callThreadFunction();
  97. }
  98. else return completeDeviceRequest(Irp,status,0);
  99. }
  100. else
  101. {
  102. // IoThread is not ready... Process synchronously!
  103. status = thread_open(Irp);
  104. }
  105. return status;
  106. }
  107. #pragma PAGEDCODE
  108. NTSTATUS CUSBReader::thread_open(PIRP Irp)
  109. {
  110. TRACE("\n------- PROCESSING USB READER OPEN DEVICE --------\n");
  111. TRACE("DEVICE NUMBER %x\n", this);
  112. if (!NT_SUCCESS(acquireRemoveLock()))
  113. {
  114. TRACE("------- FAILED TO LOCK USB READER --------\n");
  115. return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  116. }
  117. // Check if device is already active and reports
  118. // device busy...
  119. if(isOpenned())
  120. {
  121. TRACE("------- USB READER ALREADY OPENNED --------\n");
  122. releaseRemoveLock();
  123. return completeDeviceRequest(Irp, STATUS_DEVICE_BUSY, 0);
  124. }
  125. if(!NT_SUCCESS(synchronizeDevicePowerState()))
  126. {
  127. DEBUG_START();//Force to debug even if thread disable it...
  128. TRACE("******* FAILED TO SYNCHRONIZE DEVICE POWER...\n");
  129. releaseRemoveLock();
  130. return completeDeviceRequest(Irp, STATUS_INVALID_DEVICE_STATE, 0);
  131. }
  132. if(PoolingThread) PoolingThread->start();
  133. markAsOpenned();
  134. TRACE("\n------- USB READER OPENNED! --------\n");
  135. releaseRemoveLock();
  136. return completeDeviceRequest(Irp, STATUS_SUCCESS, 0);
  137. };//Create
  138. #pragma PAGEDCODE
  139. VOID CUSBReader::onDeviceStart()
  140. {
  141. TRACE("============= PNP START INITIALIZATION ===============\n");
  142. if(interface)
  143. {
  144. if(!interface->isInitialized())
  145. {
  146. interface->initialize();
  147. }
  148. }
  149. reader_UpdateCardState();
  150. setNotificationState(SCARD_SWALLOWED);
  151. TRACE("============= PNP START INITIALIZATION FINISHED ===============\n");
  152. };
  153. #pragma PAGEDCODE
  154. NTSTATUS CUSBReader::close(PIRP Irp)
  155. {
  156. DEBUG_START();//Force to debug even if thread disable it...
  157. TRACE("\n------- USB READER CLOSE DEVICE -------\n");
  158. if(!isOpenned())
  159. {
  160. return completeDeviceRequest(Irp, STATUS_SUCCESS, 0);
  161. }
  162. // Check lock count to know if some pending calls exist...
  163. // Finish all pending calls...
  164. // Stop Card pooling...
  165. if(PoolingThread) PoolingThread->stop();
  166. // Power down card if inserted...
  167. if(getCardState()== SCARD_SWALLOWED)
  168. {
  169. ULONG ResponseBufferLength = 0;
  170. reader_WaitForIdleAndBlock();
  171. reader_Power(SCARD_POWER_DOWN,NULL,&ResponseBufferLength, FALSE);
  172. reader_set_Idle();
  173. }
  174. setNotificationState(getCardState());
  175. completeCardTracking();
  176. markAsClosed();
  177. return completeDeviceRequest(Irp, STATUS_SUCCESS, 0);
  178. };
  179. #pragma PAGEDCODE
  180. NTSTATUS CUSBReader::deviceControl(IN PIRP Irp)
  181. {
  182. NTSTATUS status;
  183. TRACE("\n----- IRP_MJ_DEVICE_CONTROL ------\n");
  184. if(getDeviceState()!=WORKING)
  185. {
  186. TRACE(" READER IS NOT AT WORKING STATE... State %x\n",getDeviceState());
  187. status = STATUS_DEVICE_NOT_CONNECTED;
  188. return completeDeviceRequest(Irp,status,0);
  189. }
  190. status = thread_deviceControl(Irp);
  191. return status;
  192. }
  193. // Redefine base class system interface function...
  194. //Handle IRP_MJ_DEVICE_CONTROL request
  195. #pragma PAGEDCODE
  196. NTSTATUS CUSBReader::thread_deviceControl(IN PIRP Irp)
  197. { // RequestControl
  198. NTSTATUS status = STATUS_SUCCESS;
  199. ULONG info = 0;
  200. if (!NT_SUCCESS(acquireRemoveLock()))
  201. {
  202. DEBUG_START();//Force to debug even if thread disable it...
  203. TRACE("******* DIOC: FAILED TO AQUIRE REMOVE LOCK...\n");
  204. return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  205. }
  206. TRACE("----- thread_deviceControl() ------\n");
  207. if(isSurprizeRemoved())
  208. {
  209. DEBUG_START();//Force to debug even if thread disable it...
  210. TRACE("******* DIOC: FAILED! DEVICE WAS SURPRIZE REMOVED...\n");
  211. releaseRemoveLock();
  212. return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  213. }
  214. // This was fix for "device SET_POWER without system SET_POWER"
  215. // It was seen first on ia64 machine
  216. // If device was powered off tell system to restore power on this device,
  217. // wait till device will be at proper state...
  218. /*if(!NT_SUCCESS(synchronizeDevicePowerState()))
  219. {
  220. DEBUG_START();//Force to debug even if thread disable it...
  221. TRACE("******* FAILED TO SYNCHRONIZE DEVICE POWER...\n");
  222. releaseRemoveLock();
  223. return completeDeviceRequest(Irp, STATUS_INVALID_DEVICE_STATE, 0);
  224. }
  225. */
  226. // If we've got request but device was not enable yet -> wait for the device!
  227. // (One of the reasons to disable device - power state change)
  228. if(!synchronizeDeviceExecution())
  229. {
  230. DEBUG_START();//Force to debug even if thread disable it...
  231. TRACE("******* DIOC: FAILED TO SYNCHRONIZE EXECUTION ...\n");
  232. releaseRemoveLock();
  233. return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  234. }
  235. // SmartCard system will complete the request,
  236. // So... We do not need to do it here.
  237. status = SmartcardDeviceControl(getCardExtention(),Irp);
  238. TRACE("===== USB reader: SmartcardDeviceControl() returns %8.8lX\n", status);
  239. releaseRemoveLock();
  240. if(!NT_SUCCESS(status))
  241. {// In case of errors force to update card status...
  242. if(PoolingThread) PoolingThread->callThreadFunction();
  243. }
  244. return status;
  245. }
  246. #pragma PAGEDCODE
  247. NTSTATUS CUSBReader::cleanup(PIRP Irp)
  248. {
  249. DEBUG_START();//Force to debug even if thread disable it...
  250. TRACE("\n----- IRP_MJ_CLEANUP ------\n");
  251. if(PoolingThread) PoolingThread->stop();
  252. cancelAllPendingRequests();
  253. setNotificationState(getCardState());
  254. completeCardTracking();
  255. reader_set_Idle();
  256. TRACE("----- IRP_MJ_CLEANUP FINISHED... ------\n");
  257. return completeDeviceRequest(Irp, STATUS_SUCCESS, 0);
  258. }
  259. #pragma LOCKEDCODE
  260. // This is callback function for the attached threads
  261. VOID CUSBReader::PoolingThreadFunction(CUSBReader* device)
  262. {
  263. if(device) device->PoolingThreadRoutine();
  264. };
  265. #pragma PAGEDCODE
  266. NTSTATUS CUSBReader::PoolingThreadRoutine()
  267. {
  268. NTSTATUS status;
  269. ULONG State;
  270. LONG TimeOut;
  271. if(!NT_SUCCESS(status = reader_WaitForIdle())) return status;
  272. reader_set_busy();
  273. TimeOut = getCommandTimeout();
  274. setCommandTimeout(10000);//Change get status command timeout!
  275. DEBUG_STOP();
  276. State = reader_UpdateCardState();
  277. TRACE("======>> Card state %x\n",CardState);
  278. DEBUG_START();
  279. setCommandTimeout(TimeOut);
  280. reader_set_Idle();
  281. return STATUS_SUCCESS;
  282. };
  283. #pragma LOCKEDCODE
  284. VOID CUSBReader::reader_set_busy()
  285. {
  286. setBusy();
  287. };
  288. #pragma LOCKEDCODE
  289. VOID CUSBReader::reader_set_Idle()
  290. {
  291. setIdle();
  292. };
  293. #pragma LOCKEDCODE
  294. NTSTATUS CUSBReader::reader_WaitForIdle()
  295. {
  296. return waitForIdle();
  297. };
  298. #pragma LOCKEDCODE
  299. NTSTATUS CUSBReader::reader_WaitForIdleAndBlock()
  300. {
  301. return waitForIdleAndBlock();
  302. };
  303. #ifdef DEBUG
  304. /*
  305. // Overwrite device functions...
  306. NTSTATUS CUSBReader::read(IN PIRP Irp)
  307. {
  308. NTSTATUS status = STATUS_SUCCESS;
  309. ULONG info = 0;
  310. TRACE("USB reader: IRP_MJ_DEVICE_READ\n");
  311. if (!NT_SUCCESS(acquireRemoveLock())) return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  312. status = reader_Read(Irp);
  313. releaseRemoveLock();
  314. status = completeDeviceRequest(Irp, status, info);
  315. return status;
  316. }
  317. NTSTATUS CUSBReader::write(IN PIRP Irp)
  318. {
  319. NTSTATUS status = STATUS_SUCCESS;
  320. ULONG info = 0;
  321. TRACE("USB reader: IRP_MJ_DEVICE_WRITE\n");
  322. if (!NT_SUCCESS(acquireRemoveLock())) return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  323. status = reader_Write(Irp);
  324. releaseRemoveLock();
  325. status = completeDeviceRequest(Irp, status, info);
  326. return status;
  327. }
  328. */
  329. #endif
  330. #pragma PAGEDCODE
  331. BOOL CUSBReader::createInterface(LONG interfaceType, LONG protocolType,CUSBReader* device)
  332. {
  333. interface = kernel->createReaderInterface(interfaceType,protocolType,device);
  334. if(interface) return TRUE;
  335. else return FALSE;
  336. };
  337. #pragma PAGEDCODE
  338. VOID CUSBReader::initializeSmartCardSystem()
  339. {
  340. if(smartCard)
  341. {
  342. CardState = SCARD_UNKNOWN;
  343. StateToNotify = SCARD_UNKNOWN;
  344. smartCard->smartCardConnect(this);
  345. }
  346. };
  347. #pragma PAGEDCODE
  348. VOID CUSBReader::onSystemPowerDown()
  349. {
  350. // Stop pooling thread
  351. TRACE("Stop polling thread going to PowerDeviceD3 (OFF)\n");
  352. disableDevice();
  353. if(PoolingThread) {if(PoolingThread->isThreadActive()) setThreadRestart();};
  354. if(PoolingThread) PoolingThread->stop();
  355. return;
  356. }
  357. #pragma PAGEDCODE
  358. VOID CUSBReader::onSystemPowerUp()
  359. {
  360. // Stop pooling thread
  361. TRACE("Restore reader state going to PowerDeviceD0 (ON)\n");
  362. if(interface)
  363. {
  364. if(interface->isInitialized())
  365. {
  366. // Restore reader mode after power down
  367. NTSTATUS status = interface->setReaderMode(READER_MODE_NATIVE);
  368. if(!NT_SUCCESS(status))
  369. {
  370. TRACE("Failed to set Gemcore reader mode %x\n",READER_MODE_NATIVE);
  371. }
  372. }
  373. }
  374. if(getCardState() >= SCARD_SWALLOWED) setCardState(SCARD_ABSENT);
  375. completeCardTracking();
  376. if(isRequiredThreadRestart())
  377. {
  378. TRACE("Starting pooling thread going to PowerDeviceD0 (ON)\n");
  379. if(PoolingThread) PoolingThread->start();
  380. }
  381. enableDevice();
  382. return;
  383. }
  384. #pragma PAGEDCODE
  385. BOOLEAN CUSBReader::setDevicePowerState(IN DEVICE_POWER_STATE DeviceState)
  386. {
  387. NTSTATUS ntStatus = STATUS_SUCCESS;
  388. BOOLEAN fRes = FALSE;
  389. DEBUG_START();
  390. switch (DeviceState)
  391. {
  392. case PowerDeviceD3:
  393. // Device will be going OFF,
  394. // TODO: add any needed device-dependent code to save state here.
  395. // ( We have nothing to do in this sample )
  396. TRACE("Set Device Power State to PowerDeviceD3 (OFF)\n");
  397. setCurrentDevicePowerState(DeviceState);
  398. break;
  399. case PowerDeviceD1:
  400. case PowerDeviceD2:
  401. // power states D1,D2 translate to USB suspend
  402. #ifdef DEBUG
  403. TRACE("Set Device Power State to %s\n",Powerdevstate[DeviceState]);
  404. #endif
  405. setCurrentDevicePowerState(DeviceState);
  406. break;
  407. case PowerDeviceD0:
  408. TRACE("Set Device Power State to PowerDeviceD0(ON)\n");
  409. // We'll need to finish the rest in the completion routine;
  410. // signal caller we're going to D0 and will need to set a completion routine
  411. fRes = TRUE;
  412. // Caller will pass on to PDO ( Physical Device object )
  413. break;
  414. default:
  415. TRACE(" Bogus DeviceState = %x\n", DeviceState);
  416. }
  417. return fRes;
  418. }
  419. #pragma PAGEDCODE
  420. ULONG CUSBReader::reader_UpdateCardState()
  421. {
  422. if(interface)
  423. {
  424. CardState = interface->getReaderState();
  425. completeCardTracking();
  426. }
  427. else CardState = 0;
  428. return CardState;
  429. };
  430. #pragma LOCKEDCODE
  431. VOID CUSBReader::completeCardTracking()
  432. {
  433. if(smartCard)
  434. {
  435. smartCard->completeCardTracking();
  436. }
  437. };
  438. #pragma PAGEDCODE
  439. NTSTATUS CUSBReader::reader_getVersion(PUCHAR pVersion, PULONG pLength)
  440. {
  441. if(interface) return interface->getReaderVersion(pVersion,pLength);
  442. else return STATUS_INVALID_DEVICE_STATE;
  443. };
  444. #pragma PAGEDCODE
  445. NTSTATUS CUSBReader::reader_setMode(ULONG mode)
  446. {
  447. if(interface) return interface->setReaderMode(mode);
  448. else return STATUS_INVALID_DEVICE_STATE;
  449. };
  450. #ifdef DEBUG
  451. #pragma PAGEDCODE
  452. NTSTATUS CUSBReader::reader_Read(IN PIRP Irp)
  453. {
  454. CIoPacket* request = new (NonPagedPool) CIoPacket(Irp);
  455. if(!ALLOCATED_OK(request) || !ALLOCATED_OK(interface))
  456. {
  457. DISPOSE_OBJECT(request);
  458. return completeDeviceRequest(Irp,STATUS_INSUFFICIENT_RESOURCES,0);
  459. }
  460. NTSTATUS status = interface->read(request);
  461. DISPOSE_OBJECT(request);
  462. return status;
  463. };
  464. #pragma PAGEDCODE
  465. NTSTATUS CUSBReader::reader_Write(IN PIRP Irp)
  466. {
  467. CIoPacket* request = new (NonPagedPool) CIoPacket(Irp);
  468. if(!ALLOCATED_OK(request) || !ALLOCATED_OK(interface))
  469. {
  470. DISPOSE_OBJECT(request);
  471. return completeDeviceRequest(Irp,STATUS_INSUFFICIENT_RESOURCES,0);
  472. }
  473. NTSTATUS status = interface->write(request);
  474. DISPOSE_OBJECT(request);
  475. return status;
  476. };
  477. #endif
  478. #pragma PAGEDCODE
  479. NTSTATUS CUSBReader::reader_Read(BYTE * pRequest,ULONG RequestLength,BYTE * pReply,ULONG* pReplyLength)
  480. {
  481. if(interface) return interface->readAndWait(pRequest,RequestLength,pReply,pReplyLength);
  482. else return STATUS_INVALID_DEVICE_STATE;
  483. };
  484. #pragma PAGEDCODE
  485. NTSTATUS CUSBReader::reader_Write(BYTE* pRequest,ULONG RequestLength,BYTE * pReply,ULONG* pReplyLength)
  486. {
  487. if(interface) return interface->writeAndWait(pRequest,RequestLength,pReply,pReplyLength);
  488. else return STATUS_INVALID_DEVICE_STATE;
  489. };
  490. #pragma PAGEDCODE
  491. NTSTATUS CUSBReader::reader_Ioctl(ULONG ControlCode,BYTE* pRequest,ULONG RequestLength,BYTE* pReply,ULONG* pReplyLength)
  492. {
  493. if(interface) return interface->ioctl(ControlCode,pRequest,RequestLength,pReply,pReplyLength);
  494. else return STATUS_INVALID_DEVICE_STATE;
  495. };
  496. #pragma PAGEDCODE
  497. NTSTATUS CUSBReader::reader_SwitchSpeed(ULONG ControlCode,BYTE* pRequest,ULONG RequestLength,BYTE* pReply,ULONG* pReplyLength)
  498. {
  499. if(interface) return interface->SwitchSpeed(ControlCode,pRequest,RequestLength,pReply,pReplyLength);
  500. else return STATUS_INVALID_DEVICE_STATE;
  501. };
  502. #pragma PAGEDCODE
  503. NTSTATUS CUSBReader::reader_VendorAttribute(ULONG ControlCode,BYTE* pRequest,ULONG RequestLength,BYTE* pReply,ULONG* pReplyLength)
  504. {
  505. if(interface) return interface->VendorAttribute(ControlCode,pRequest,RequestLength,pReply,pReplyLength);
  506. else return STATUS_INVALID_DEVICE_STATE;
  507. };
  508. #pragma PAGEDCODE
  509. NTSTATUS CUSBReader::reader_Power(ULONG ControlCode,BYTE* pReply,ULONG* pReplyLength, BOOLEAN Specific)
  510. {
  511. if(interface) return interface->power(ControlCode,pReply,pReplyLength, Specific);
  512. else return STATUS_INVALID_DEVICE_STATE;
  513. };
  514. #pragma PAGEDCODE
  515. NTSTATUS CUSBReader::reader_SetProtocol(ULONG ProtocolRequested, UCHAR ProtocolNegociation)
  516. {
  517. NTSTATUS status;
  518. if(interface)
  519. {
  520. ReaderConfig config = interface->getConfiguration();
  521. // Update all required configuration fields to set specific protocol
  522. switch(ProtocolNegociation)
  523. {
  524. case PROTOCOL_MODE_DEFAULT:
  525. config.PTSMode = PTS_MODE_DISABLED;
  526. break;
  527. case PROTOCOL_MODE_MANUALLY:
  528. default:
  529. config.PTSMode = PTS_MODE_MANUALLY;
  530. break;
  531. }
  532. config.PTS1 = smartCardExtention.CardCapabilities.PtsData.Fl << 4 |
  533. smartCardExtention.CardCapabilities.PtsData.Dl;
  534. interface->setConfiguration(config);
  535. status = interface->setProtocol(ProtocolRequested);
  536. return status;
  537. }
  538. else return STATUS_INVALID_DEVICE_STATE;
  539. };
  540. #pragma PAGEDCODE
  541. NTSTATUS CUSBReader::setTransparentConfig(PSCARD_CARD_CAPABILITIES cardCapabilities, BYTE NewWtx)
  542. {
  543. if(interface) return interface->setTransparentConfig(cardCapabilities,NewWtx);
  544. else return STATUS_INVALID_DEVICE_STATE;
  545. };
  546. #pragma PAGEDCODE
  547. NTSTATUS CUSBReader::reader_translate_request(BYTE * pRequest,ULONG RequestLength,BYTE * pReply,ULONG* pReplyLength, PSCARD_CARD_CAPABILITIES cardCapabilities, BYTE NewWtx)
  548. {
  549. if(interface) return interface->translate_request(pRequest,RequestLength,pReply,pReplyLength, cardCapabilities, NewWtx);
  550. else return STATUS_INVALID_DEVICE_STATE;
  551. };
  552. #pragma PAGEDCODE
  553. NTSTATUS CUSBReader::reader_translate_response(BYTE * pRequest,ULONG RequestLength,BYTE * pReply,ULONG* pReplyLength)
  554. {
  555. if(interface) return interface->translate_response(pRequest,RequestLength,pReply,pReplyLength);
  556. else return STATUS_INVALID_DEVICE_STATE;
  557. };
  558. #pragma PAGEDCODE
  559. NTSTATUS CUSBReader::PnP_HandleSurprizeRemoval(IN PIRP Irp)
  560. { // It is PnP internal function.
  561. // So, device will be locked at PnP entry and
  562. // we do not need to do it here.
  563. TRACE("******** USB READER SURPRIZE REMOVAL ********\n");
  564. // Just stop thread and remove all pending IOs
  565. if(PoolingThread) PoolingThread->stop();
  566. setSurprizeRemoved();
  567. cancelAllPendingRequests();
  568. return PnP_Default(Irp);
  569. };
  570. VOID CUSBReader::onDeviceStop()
  571. {
  572. TRACE("******** ON USB READER STOP ********\n");
  573. // Just stop thread and remove all pending IOs
  574. if(PoolingThread) PoolingThread->stop();
  575. //if(IoThread) IoThread->stop();
  576. return;
  577. };
  578. // Reader startIoRequest function
  579. // It will dispatch all pending Io requests
  580. NTSTATUS CUSBReader::startIoRequest(CPendingIRP* IrpReq)
  581. {
  582. NTSTATUS status;
  583. TRACE(" CUSBReader::::startIoRequest() was called...\n");
  584. // Our child's functions run under protection of child BUSY/IDLE breaks.
  585. // So, we do not need to check idle state here...
  586. if(getDeviceState()!=WORKING)
  587. {
  588. TRACE(" READER IS NOT AT WORKING STATE... State %x\n",getDeviceState());
  589. TRACE(" <<<<<< READER IO REQUEST FINISHED WITH STATUS %8.8lX>>>>>>\n",STATUS_DEVICE_NOT_CONNECTED);
  590. NTSTATUS status = completeDeviceRequest(IrpReq->Irp, STATUS_DEVICE_NOT_CONNECTED, 0);
  591. IrpReq->dispose();
  592. return status;
  593. }
  594. // Our reader will support asynchronous communications only for these functions...
  595. switch(IrpReq->Type)
  596. {
  597. case OPEN_REQUEST:
  598. TRACE("OPEN_REQUEST RECIEVED FROM THREAD...\n");
  599. status = thread_open(IrpReq->Irp);
  600. break;
  601. case IOCTL_REQUEST:
  602. TRACE("IOCTL_REQUEST RECIEVED FROM THREAD...\n");
  603. status = thread_deviceControl(IrpReq->Irp);
  604. break;
  605. default:
  606. status = STATUS_INVALID_DEVICE_REQUEST;
  607. }
  608. IrpReq->dispose();
  609. TRACE(" <<<<<< READER IO REQUEST FINISHED WITH STATUS %8.8lX>>>>>>\n",status);
  610. return status;
  611. };
  612. NTSTATUS CUSBReader::ThreadRoutine()
  613. {
  614. // If somebody inserted pending request - dispatch it...
  615. // It will call specific child device startIoRequest().
  616. // It is up to that device how to handle it.
  617. // If child device is busy - it can insert this request into
  618. // child device request queue again and process it later...
  619. startNextPendingRequest();
  620. return STATUS_SUCCESS;
  621. };
  622. #endif
  623. #endif //USBREADER_PROJECT