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.

2342 lines
93 KiB

  1. #ifdef USBREADER_PROJECT
  2. #ifndef USBDEVICE_PROJECT
  3. #define USBDEVICE_PROJECT
  4. #endif
  5. #endif
  6. #ifdef USBDEVICE_PROJECT
  7. #pragma message("COMPILING USB DEVICE...")
  8. #include "usbdev.h"
  9. // GUID should be defined outside of any block!
  10. #include "guid.h"
  11. #include "thread.h"
  12. #include "usbreader.h" //TO BE REMOVED
  13. VOID onSendDeviceSetPowerComplete(PDEVICE_OBJECT junk, UCHAR fcn, POWER_STATE state, PPOWER_CONTEXT context, PIO_STATUS_BLOCK pstatus)
  14. {// SendDeviceSetPowerComplete
  15. context->status = pstatus->Status;
  16. KeSetEvent(context->powerEvent, EVENT_INCREMENT, FALSE);
  17. }// SendDeviceSetPowerComplete
  18. #pragma PAGEDCODE
  19. CUSBDevice::CUSBDevice()
  20. {
  21. m_Status = STATUS_INSUFFICIENT_RESOURCES;
  22. INCLUDE_PNP_FUNCTIONS_NAMES();
  23. INCLUDE_POWER_FUNCTIONS_NAMES();
  24. m_Type = USB_DEVICE;
  25. m_Flags |= DEVICE_SURPRISE_REMOVAL_OK;
  26. m_MaximumTransferSize = GUR_MAX_TRANSFER_SIZE;
  27. CommandBufferLength = DEFAULT_COMMAND_BUFFER_SIZE;
  28. ResponseBufferLength = DEFAULT_RESPONSE_BUFFER_SIZE;
  29. InterruptBufferLength = DEFAULT_INTERRUPT_BUFFER_SIZE;
  30. // Register handlers processed by this device...
  31. activatePnPHandler(IRP_MN_START_DEVICE);
  32. activatePnPHandler(IRP_MN_QUERY_REMOVE_DEVICE);
  33. activatePnPHandler(IRP_MN_REMOVE_DEVICE);
  34. activatePnPHandler(IRP_MN_SURPRISE_REMOVAL);
  35. activatePnPHandler(IRP_MN_CANCEL_REMOVE_DEVICE);
  36. activatePnPHandler(IRP_MN_QUERY_STOP_DEVICE);
  37. activatePnPHandler(IRP_MN_CANCEL_STOP_DEVICE);
  38. activatePnPHandler(IRP_MN_STOP_DEVICE);
  39. activatePnPHandler(IRP_MN_QUERY_CAPABILITIES);
  40. // Register Power handlers processed by driver...
  41. activatePowerHandler(IRP_MN_SET_POWER);
  42. activatePowerHandler(IRP_MN_QUERY_POWER);
  43. TRACE(" *** New USB device %8.8lX was created ***\n",this);
  44. m_Status = STATUS_SUCCESS;
  45. }
  46. #pragma PAGEDCODE
  47. CUSBDevice::~CUSBDevice()
  48. {
  49. waitForIdle();
  50. TRACE(" USB device %8.8lX was destroyed ***\n",this);
  51. }
  52. // Function redirects all PnP requests
  53. // This is main entry point for the system (after c wrapper).
  54. // It handles locking device for a PnP requests and redirecting
  55. // it to specific PnP handlers.
  56. // In case of IRP_MN_REMOVE_DEVICE it leaves device locked till
  57. // remove message recieved.
  58. #pragma PAGEDCODE
  59. NTSTATUS CUSBDevice::pnpRequest(IN PIRP Irp)
  60. {
  61. NTSTATUS status;
  62. if (!NT_SUCCESS(acquireRemoveLock()))
  63. {
  64. TRACE("Failed to lock USB device...\n");
  65. return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  66. }
  67. PIO_STACK_LOCATION stack = irp->getCurrentStackLocation(Irp);
  68. ASSERT(stack->MajorFunction == IRP_MJ_PNP);
  69. ULONG fcn = stack->MinorFunction;
  70. if (fcn >= arraysize(PnPfcntab))
  71. { // some function we don't know about
  72. TRACE("Unknown PnP function at USB device...\n");
  73. status = PnP_Default(Irp);
  74. releaseRemoveLock();
  75. return status;
  76. }
  77. #ifdef DEBUG
  78. TRACE("PnP request (%s) \n", PnPfcnname[fcn]);
  79. #endif
  80. // Call real function to handle the request
  81. status = PnPHandler(fcn,Irp);
  82. // If we've got PnP request to remove->
  83. // Keep device locked to prevent futher connections.
  84. // Device will be unlocked and removed by driver later...
  85. if (fcn != IRP_MN_REMOVE_DEVICE) releaseRemoveLock();
  86. if(!NT_SUCCESS(status))
  87. {
  88. if(status != STATUS_NOT_SUPPORTED)
  89. {
  90. TRACE("\n******** PnP handler reported ERROR -> %x\n", status);
  91. }
  92. }
  93. return status;
  94. }
  95. #pragma PAGEDCODE
  96. // Main redirector of all PnP handlers...
  97. NTSTATUS CUSBDevice::PnPHandler(LONG HandlerID,IN PIRP Irp)
  98. {
  99. // If Handler is not registered...
  100. if (HandlerID >= arraysize(PnPfcntab)) return PnP_Default(Irp);
  101. if(!PnPfcntab[HandlerID]) return PnP_Default(Irp);
  102. // Call registered PnP Handler...
  103. switch(HandlerID)
  104. {
  105. case IRP_MN_START_DEVICE: return PnP_HandleStartDevice(Irp);
  106. break;
  107. case IRP_MN_QUERY_REMOVE_DEVICE: return PnP_HandleQueryRemove(Irp);
  108. break;
  109. case IRP_MN_REMOVE_DEVICE: return PnP_HandleRemoveDevice(Irp);
  110. break;
  111. case IRP_MN_CANCEL_REMOVE_DEVICE: return PnP_HandleCancelRemove(Irp);
  112. break;
  113. case IRP_MN_STOP_DEVICE: return PnP_HandleStopDevice(Irp);
  114. break;
  115. case IRP_MN_QUERY_STOP_DEVICE: return PnP_HandleQueryStop(Irp);
  116. break;
  117. case IRP_MN_CANCEL_STOP_DEVICE: return PnP_HandleCancelStop(Irp);
  118. break;
  119. case IRP_MN_QUERY_DEVICE_RELATIONS: return PnP_HandleQueryRelations(Irp);
  120. break;
  121. case IRP_MN_QUERY_INTERFACE: return PnP_HandleQueryInterface(Irp);
  122. break;
  123. case IRP_MN_QUERY_CAPABILITIES: return PnP_HandleQueryCapabilities(Irp);
  124. break;
  125. case IRP_MN_QUERY_RESOURCES: return PnP_HandleQueryResources(Irp);
  126. break;
  127. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  128. return PnP_HandleQueryResRequirements(Irp);
  129. break;
  130. case IRP_MN_QUERY_DEVICE_TEXT: return PnP_HandleQueryText(Irp);
  131. break;
  132. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  133. return PnP_HandleFilterResRequirements(Irp);
  134. break;
  135. case 0x0E: return PnP_Default(Irp);
  136. break;
  137. case IRP_MN_READ_CONFIG: return PnP_HandleReadConfig(Irp);
  138. break;
  139. case IRP_MN_WRITE_CONFIG: return PnP_HandleWriteConfig(Irp);
  140. break;
  141. case IRP_MN_EJECT: return PnP_HandleEject(Irp);
  142. break;
  143. case IRP_MN_SET_LOCK: return PnP_HandleSetLock(Irp);
  144. break;
  145. case IRP_MN_QUERY_ID: return PnP_HandleQueryID(Irp);
  146. break;
  147. case IRP_MN_QUERY_PNP_DEVICE_STATE: return PnP_HandleQueryPnPState(Irp);
  148. break;
  149. case IRP_MN_QUERY_BUS_INFORMATION: return PnP_HandleQueryBusInfo(Irp);
  150. break;
  151. case IRP_MN_DEVICE_USAGE_NOTIFICATION: return PnP_HandleUsageNotification(Irp);
  152. break;
  153. case IRP_MN_SURPRISE_REMOVAL: return PnP_HandleSurprizeRemoval(Irp);
  154. break;
  155. }
  156. return PnP_Default(Irp);
  157. }
  158. #pragma PAGEDCODE
  159. // Asks object to remove device
  160. // Object itself will be removed at wrapper function
  161. NTSTATUS CUSBDevice::PnP_HandleRemoveDevice(IN PIRP Irp)
  162. {
  163. // Set device removal state
  164. m_RemoveLock.removing = TRUE;
  165. // Do any processing required for *us* to remove the device. This
  166. // would include completing any outstanding requests, etc.
  167. PnP_StopDevice();
  168. // Do not remove actually our device here!
  169. // It will be done automatically by PnP handler at basic class.
  170. // Let lower-level drivers handle this request. Ignore whatever
  171. // result eventuates.
  172. Irp->IoStatus.Status = STATUS_SUCCESS;
  173. NTSTATUS status = PnP_Default(Irp);
  174. // lower-level completed IoStatus already
  175. return status;
  176. }
  177. #pragma PAGEDCODE
  178. NTSTATUS CUSBDevice::PnP_HandleStartDevice(IN PIRP Irp)
  179. {
  180. waitForIdleAndBlock();
  181. // First let all lower-level drivers handle this request. In this particular
  182. // sample, the only lower-level driver should be the physical device created
  183. // by the bus driver, but there could theoretically be any number of intervening
  184. // bus filter devices. Those drivers may need to do some setup at this point
  185. // in time before they'll be ready to handle non-PnP IRP's.
  186. Irp->IoStatus.Status = STATUS_SUCCESS;
  187. NTSTATUS status = forwardAndWait(Irp);
  188. if (!NT_SUCCESS(status))
  189. {
  190. TRACE(" ******* BUS DRIVER FAILED START REQUEST! %8.8lX ******",status);
  191. CLogger* logger = kernel->getLogger();
  192. if(logger) logger->logEvent(GRCLASS_BUS_DRIVER_FAILED_REQUEST,getSystemObject());
  193. return completeDeviceRequest(Irp, status, Irp->IoStatus.Information);
  194. }
  195. status = PnP_StartDevice();
  196. setIdle();
  197. return completeDeviceRequest(Irp, status, Irp->IoStatus.Information);
  198. }
  199. #pragma PAGEDCODE
  200. NTSTATUS CUSBDevice::PnP_HandleStopDevice(IN PIRP Irp)
  201. {
  202. PnP_StopDevice();
  203. m_Started = FALSE;
  204. // Let lower-level drivers handle this request. Ignore whatever
  205. // result eventuates.
  206. Irp->IoStatus.Status = STATUS_SUCCESS;
  207. NTSTATUS status = PnP_Default(Irp);
  208. return status;
  209. }
  210. #pragma PAGEDCODE
  211. NTSTATUS CUSBDevice::PnP_StartDevice()
  212. { // StartDevice
  213. NTSTATUS status = STATUS_SUCCESS;
  214. if(m_Started)
  215. {
  216. TRACE("##### Current device was already started!\n");
  217. ASSERT(!m_Started);
  218. return STATUS_DEVICE_BUSY;
  219. }
  220. __try
  221. {
  222. // Do all required processing to start USB device.
  223. // It will include getting Device and configuration descriptors
  224. // and selecting specific interface.
  225. // For now our device support only interface.
  226. // So, it will be activated at activateInterface().
  227. m_DeviceDescriptor = getDeviceDescriptor();
  228. if(!m_DeviceDescriptor)
  229. {
  230. status = STATUS_INSUFFICIENT_RESOURCES;
  231. __leave;
  232. }
  233. TRACE("\nDeviceDescriptor %8.8lX\n",m_DeviceDescriptor);
  234. m_Configuration = getConfigurationDescriptor();
  235. if(!m_Configuration)
  236. {
  237. status = STATUS_INSUFFICIENT_RESOURCES;
  238. __leave;
  239. }
  240. TRACE("Configuration %8.8lX\n",m_Configuration);
  241. m_Interface = activateInterface(m_Configuration);
  242. if(!m_Interface)
  243. {
  244. status = STATUS_INSUFFICIENT_RESOURCES;
  245. __leave;
  246. }
  247. TRACE("Selected interface %8.8lX\n\n",m_Interface);
  248. // Allocate Xfer buffers
  249. if(m_CommandPipe)
  250. {
  251. TRACE("Allocating command buffer (length 0x%x)...\n",CommandBufferLength);
  252. m_CommandBuffer = memory->allocate(NonPagedPool, CommandBufferLength);
  253. if(!m_CommandBuffer)
  254. {
  255. status = STATUS_INSUFFICIENT_RESOURCES;
  256. __leave;
  257. }
  258. }
  259. if(m_ResponsePipe)
  260. {
  261. TRACE("Allocating response buffer (length 0x%x)...\n", ResponseBufferLength);
  262. m_ResponseBuffer = memory->allocate(NonPagedPool, ResponseBufferLength);
  263. if(!m_ResponseBuffer)
  264. {
  265. status = STATUS_INSUFFICIENT_RESOURCES;
  266. __leave;
  267. }
  268. }
  269. if(m_InterruptPipe)
  270. {
  271. TRACE("Allocating interrupt buffer (length 0x%x)...\n", InterruptBufferLength);
  272. m_InterruptBuffer = memory->allocate(NonPagedPool, InterruptBufferLength);
  273. if(!m_InterruptBuffer)
  274. {
  275. status = STATUS_INSUFFICIENT_RESOURCES;
  276. __leave;
  277. }
  278. }
  279. }
  280. __finally
  281. {
  282. // Check memory allocations!
  283. if(!NT_SUCCESS(status))
  284. {
  285. if(m_DeviceDescriptor) memory->free(m_DeviceDescriptor);
  286. if(m_Configuration) memory->free(m_Configuration);
  287. if(m_Interface) memory->free(m_Interface);
  288. if(m_CommandBuffer) memory->free(m_CommandBuffer);
  289. if(m_ResponseBuffer) memory->free(m_ResponseBuffer);
  290. if(m_InterruptBuffer) memory->free(m_InterruptBuffer);
  291. m_DeviceDescriptor = NULL;
  292. m_Configuration = NULL;
  293. m_Interface = NULL;
  294. m_CommandBuffer = NULL;
  295. m_ResponseBuffer = NULL;
  296. m_InterruptBuffer = NULL;
  297. }
  298. else
  299. {
  300. // Give chance inhereted devices to initialize...
  301. onDeviceStart();
  302. TRACE("USB device started successfully...\n\n");
  303. // Device has been completely initialized and is ready to run.
  304. m_Started = TRUE;
  305. }
  306. }
  307. return status;
  308. }
  309. #pragma PAGEDCODE
  310. // This function used for both Stop and Remove PnP events
  311. // It will undo everything what was done at StartDevice
  312. VOID CUSBDevice::PnP_StopDevice()
  313. { // StopDevice
  314. if (!m_Started) return; // device not started, so nothing to do
  315. TRACE("*** Stop USB Device %8.8lX requested... ***\n", this);
  316. onDeviceStop();
  317. // If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
  318. // This call will also close the pipes; if any user close calls get through,
  319. // they will be noops
  320. abortPipes();
  321. //We basically just tell USB this device is now 'unconfigured'
  322. if(!isSurprizeRemoved()) disactivateInterface();
  323. // Free resources allocated at startup
  324. m_ControlPipe = NULL;
  325. m_InterruptPipe = NULL;
  326. m_ResponsePipe = NULL;
  327. m_CommandPipe = NULL;
  328. if(m_DeviceDescriptor) memory->free(m_DeviceDescriptor);
  329. if(m_Configuration) memory->free(m_Configuration);
  330. if(m_Interface) memory->free(m_Interface);
  331. if(m_CommandBuffer) memory->free(m_CommandBuffer);
  332. if(m_ResponseBuffer) memory->free(m_ResponseBuffer);
  333. if(m_InterruptBuffer) memory->free(m_InterruptBuffer);
  334. TRACE("*** Device resources released ***\n");
  335. setIdle();
  336. m_Started = FALSE;
  337. }
  338. #pragma PAGEDCODE
  339. NTSTATUS CUSBDevice::PnP_HandleQueryRemove(IN PIRP Irp)
  340. {
  341. TRACE("******** QUERY REMOVAL ********\n");
  342. // Win98 doesn't check for open handles before allowing a remove to proceed,
  343. // and it may deadlock in IoReleaseRemoveLockAndWait if handles are still
  344. // open.
  345. if (isWin98() && m_DeviceObject->ReferenceCount)
  346. {
  347. TRACE("Failing removal query due to open handles\n");
  348. return completeDeviceRequest(Irp, STATUS_DEVICE_BUSY, 0);
  349. }
  350. Irp->IoStatus.Status = STATUS_SUCCESS;
  351. NTSTATUS status = forwardAndWait(Irp);
  352. return completeDeviceRequest(Irp, Irp->IoStatus.Status,0);
  353. }
  354. NTSTATUS CUSBDevice::PnP_HandleCancelRemove(IN PIRP Irp)
  355. {
  356. NTSTATUS status;
  357. status = forwardAndWait(Irp);
  358. ASSERT(NT_SUCCESS(status));
  359. Irp->IoStatus.Status = STATUS_SUCCESS;
  360. return completeDeviceRequest(Irp, Irp->IoStatus.Status,0);
  361. }
  362. NTSTATUS CUSBDevice::PnP_HandleQueryStop(IN PIRP Irp)
  363. {
  364. TRACE("******** QUERY STOP ********\n");
  365. if(isDeviceLocked())
  366. {
  367. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  368. return completeDeviceRequest(Irp, Irp->IoStatus.Status,0);
  369. }
  370. Irp->IoStatus.Status = STATUS_SUCCESS;
  371. NTSTATUS status = forwardAndWait(Irp);
  372. return completeDeviceRequest(Irp, Irp->IoStatus.Status,0);
  373. }
  374. NTSTATUS CUSBDevice::PnP_HandleCancelStop(IN PIRP Irp)
  375. {
  376. TRACE("******** CANCEL STOP ********\n");
  377. Irp->IoStatus.Status = STATUS_SUCCESS;
  378. NTSTATUS status = forwardAndWait(Irp);
  379. return completeDeviceRequest(Irp, Irp->IoStatus.Status,0);
  380. }
  381. NTSTATUS CUSBDevice::PnP_HandleQueryRelations(IN PIRP Irp)
  382. {
  383. return PnP_Default(Irp);
  384. }
  385. NTSTATUS CUSBDevice::PnP_HandleQueryInterface(IN PIRP Irp)
  386. {
  387. return PnP_Default(Irp);
  388. }
  389. #pragma PAGEDCODE
  390. NTSTATUS CUSBDevice::PnP_HandleQueryCapabilities(PIRP Irp)
  391. {
  392. if(!Irp) return STATUS_INVALID_PARAMETER;
  393. PIO_STACK_LOCATION stack = irp->getCurrentStackLocation(Irp);
  394. PDEVICE_CAPABILITIES pdc = stack->Parameters.DeviceCapabilities.Capabilities;
  395. // Check to be sure we know how to handle this version of the capabilities structure
  396. if (pdc->Version < 1) return PnP_Default(Irp);
  397. Irp->IoStatus.Status = STATUS_SUCCESS;
  398. NTSTATUS status = forwardAndWait(Irp);
  399. if (NT_SUCCESS(status))
  400. { // IRP succeeded
  401. stack = irp->getCurrentStackLocation(Irp);
  402. pdc = stack->Parameters.DeviceCapabilities.Capabilities;
  403. if(!pdc) return STATUS_INVALID_PARAMETER;
  404. //if (m_Flags & DEVICE_SURPRISE_REMOVAL_OK)
  405. /*{ // Smartcard readers do not support it!
  406. //if(!isWin98()) pdc->SurpriseRemovalOK = TRUE;
  407. }*/
  408. pdc->SurpriseRemovalOK = FALSE;
  409. m_DeviceCapabilities = *pdc; // save capabilities for whoever needs to see them
  410. TRACE(" Device allows surprize removal - %s\n",(m_DeviceCapabilities.SurpriseRemovalOK?"YES":"NO"));
  411. } // IRP succeeded
  412. return completeDeviceRequest(Irp, status,Irp->IoStatus.Information);
  413. }// HandleQueryCapabilities
  414. NTSTATUS CUSBDevice::PnP_HandleQueryResources(IN PIRP Irp)
  415. {
  416. return PnP_Default(Irp);
  417. }
  418. NTSTATUS CUSBDevice::PnP_HandleQueryResRequirements(IN PIRP Irp)
  419. {
  420. return PnP_Default(Irp);
  421. }
  422. NTSTATUS CUSBDevice::PnP_HandleQueryText(IN PIRP Irp)
  423. {
  424. return PnP_Default(Irp);
  425. }
  426. NTSTATUS CUSBDevice::PnP_HandleFilterResRequirements(IN PIRP Irp)
  427. {
  428. TRACE("Default action for filtering resource requirements...");
  429. return PnP_Default(Irp);
  430. }
  431. NTSTATUS CUSBDevice::PnP_HandleReadConfig(IN PIRP Irp)
  432. {
  433. return PnP_Default(Irp);
  434. }
  435. NTSTATUS CUSBDevice::PnP_HandleWriteConfig(IN PIRP Irp)
  436. {
  437. return PnP_Default(Irp);
  438. }
  439. NTSTATUS CUSBDevice::PnP_HandleEject(IN PIRP Irp)
  440. {
  441. return PnP_Default(Irp);
  442. }
  443. NTSTATUS CUSBDevice::PnP_HandleSetLock(IN PIRP Irp)
  444. {
  445. return PnP_Default(Irp);
  446. }
  447. NTSTATUS CUSBDevice::PnP_HandleQueryID(IN PIRP Irp)
  448. {
  449. return PnP_Default(Irp);
  450. }
  451. NTSTATUS CUSBDevice::PnP_HandleQueryPnPState(IN PIRP Irp)
  452. {
  453. return PnP_Default(Irp);
  454. }
  455. NTSTATUS CUSBDevice::PnP_HandleQueryBusInfo(IN PIRP Irp)
  456. {
  457. return PnP_Default(Irp);
  458. }
  459. NTSTATUS CUSBDevice::PnP_HandleUsageNotification(IN PIRP Irp)
  460. {
  461. return PnP_Default(Irp);
  462. }
  463. NTSTATUS CUSBDevice::PnP_HandleSurprizeRemoval(IN PIRP Irp)
  464. {
  465. TRACE("******** SURPRIZE REMOVAL ********\n");
  466. return PnP_Default(Irp);
  467. }
  468. // Functions allocate and initialize USB request block.
  469. // It can be used for read/write request on specific Pipe.
  470. // Allocated URB should be free later upon completing of the request.
  471. PURB CUSBDevice::buildBusTransferRequest(CIoPacket* Irp,UCHAR Command)
  472. {
  473. USHORT Size;
  474. ULONG BufferLength;
  475. PURB Urb = NULL;
  476. PVOID pBuffer;
  477. ULONG TransferFlags;
  478. IN USBD_PIPE_HANDLE Pipe = NULL;
  479. ULONG TransferLength;
  480. if(!Irp) return NULL;
  481. if(Command == COMMAND_REQUEST)
  482. {
  483. BufferLength = CommandBufferLength;
  484. pBuffer = m_CommandBuffer;
  485. TransferFlags = USBD_SHORT_TRANSFER_OK;
  486. Pipe = m_CommandPipe;
  487. TransferLength = Irp->getWriteLength();
  488. if(!Pipe || !TransferLength)
  489. {
  490. TRACE("##### Requested Pipe or TransferLength == 0 for the requested command %d ...\n", Command);
  491. return NULL;
  492. }
  493. TRACE("Command transfer requested...\n");
  494. }
  495. else
  496. if(Command == RESPONSE_REQUEST)
  497. {
  498. BufferLength = ResponseBufferLength;
  499. pBuffer = m_ResponseBuffer;
  500. TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
  501. Pipe = m_ResponsePipe;
  502. TransferLength = BufferLength;
  503. if(!Pipe || !TransferLength)
  504. {
  505. TRACE("##### Requested Pipe or TransferLength == 0 for the requested command %d ...\n", Command);
  506. return NULL;
  507. }
  508. TRACE("Response transfer requested with number of expected bytes %x\n",Irp->getReadLength());
  509. }
  510. else
  511. if(Command == INTERRUPT_REQUEST)
  512. {
  513. BufferLength = InterruptBufferLength;
  514. pBuffer = m_InterruptBuffer;
  515. TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK;
  516. Pipe = m_InterruptPipe;
  517. TransferLength = BufferLength;
  518. if(!Pipe || !TransferLength)
  519. {
  520. TRACE("##### Requested Pipe or TransferLength == 0 for the requested command %d ...\n", Command);
  521. return NULL;
  522. }
  523. TRACE("Interrupt transfer requested...\n");
  524. }
  525. else
  526. {
  527. TRACE("Incorrect command was requested %d", Command);
  528. return NULL;
  529. }
  530. Size = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  531. Urb = (PURB) memory->allocate(NonPagedPool, Size);
  532. if (Urb)
  533. {
  534. memory->zero(Urb, Size);
  535. memory->zero(pBuffer, BufferLength);
  536. if(Command == COMMAND_REQUEST)
  537. {
  538. memory->copy(pBuffer,Irp->getBuffer(), TransferLength);
  539. ((PUCHAR)pBuffer)[TransferLength] = 0x00;
  540. //TRACE("Command ");
  541. //TRACE_BUFFER(pBuffer,TransferLength);
  542. }
  543. UsbBuildInterruptOrBulkTransferRequest(Urb,(USHORT) Size,
  544. Pipe,
  545. pBuffer,
  546. NULL,
  547. TransferLength,
  548. TransferFlags,
  549. NULL);
  550. }
  551. else
  552. {
  553. TRACE("##### ERROR: failed to allocate URB request...\n");
  554. }
  555. return Urb;
  556. }
  557. VOID CUSBDevice::finishBusTransferRequest(CIoPacket* Irp,UCHAR Command)
  558. {
  559. ULONG BufferLength;
  560. PVOID pBuffer;
  561. ULONG_PTR info;
  562. if(!Irp)
  563. {
  564. TRACE(" **** Invalid parameter -> Irp\n");
  565. return;
  566. }
  567. if(!(info = Irp->getInformation()))
  568. {
  569. TRACE(" **** There is no reported information\n");
  570. return;
  571. }
  572. if(Command == COMMAND_REQUEST)
  573. {
  574. BufferLength = CommandBufferLength;
  575. pBuffer = m_CommandBuffer;
  576. TRACE(" Command transfer finished with length %d\n",info);
  577. }
  578. else
  579. if(Command == RESPONSE_REQUEST)
  580. {
  581. ULONG Length = Irp->getReadLength();
  582. BufferLength = (ULONG)(info>ResponseBufferLength?ResponseBufferLength:info);
  583. BufferLength = BufferLength>Length?Length:BufferLength;
  584. pBuffer = m_ResponseBuffer;
  585. TRACE("Bus Driver replied with length %d\n",info);
  586. memory->copy(Irp->getBuffer(),pBuffer, BufferLength);
  587. if(BufferLength!=info)
  588. {
  589. TRACE("##### Response Buffer short! Buffer length %x Reply length %x \n",ResponseBufferLength,info);
  590. }
  591. //TRACE("Response ");
  592. //TRACE_BUFFER(pBuffer,BufferLength);
  593. }
  594. else
  595. if(Command == INTERRUPT_REQUEST)
  596. {
  597. ULONG Length = Irp->getReadLength();
  598. BufferLength = (ULONG)(info>InterruptBufferLength?InterruptBufferLength:info);
  599. BufferLength = BufferLength>Length?Length:BufferLength;
  600. pBuffer = m_InterruptBuffer;
  601. TRACE("Bus Driver replied with length %d\n",info);
  602. memory->copy(Irp->getBuffer(),pBuffer, BufferLength);
  603. if(BufferLength!=info)
  604. {
  605. TRACE("##### Interrupt Buffer short! Buffer length %x Reply length %x \n",InterruptBufferLength,info);
  606. }
  607. TRACE("Interrupt ");
  608. TRACE_BUFFER(pBuffer,BufferLength);
  609. }
  610. else
  611. {
  612. TRACE("Incorrect command was requested %d", Command);
  613. return;
  614. }
  615. }
  616. // This function generates an internal IRP from this driver to the PDO
  617. // to obtain information on the Physical Device Object's capabilities.
  618. // We are most interested in learning which system power states
  619. // are to be mapped to which device power states for honoring IRP_MJ_SET_POWER Irps.
  620. #pragma PAGEDCODE
  621. NTSTATUS CUSBDevice::QueryBusCapabilities(PDEVICE_CAPABILITIES Capabilities)
  622. {
  623. NTSTATUS status;
  624. CIoPacket* IoPacket;
  625. PAGED_CODE();
  626. TRACE("Quering USB bus capabilities...\n");
  627. // Build an IRP for us to generate an internal query request to the PDO
  628. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  629. if(!ALLOCATED_OK(IoPacket))
  630. {
  631. DISPOSE_OBJECT(IoPacket);
  632. return STATUS_INSUFFICIENT_RESOURCES;
  633. }
  634. IoPacket->setTimeout(getCommandTimeout());
  635. IoPacket->buildStack(getSystemObject(),IRP_MJ_PNP, IRP_MN_QUERY_CAPABILITIES, 0,Capabilities);
  636. status = sendRequestToDeviceAndWait(IoPacket);
  637. DISPOSE_OBJECT(IoPacket);
  638. return status;
  639. }
  640. #pragma PAGEDCODE
  641. // Function gets device descriptor from the USB bus driver
  642. PUSB_DEVICE_DESCRIPTOR CUSBDevice::getDeviceDescriptor()
  643. {
  644. PUSB_DEVICE_DESCRIPTOR Descriptor = NULL;
  645. PURB Urb;
  646. ULONG Size;
  647. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  648. CIoPacket* IoPacket = NULL;
  649. TRACE("Getting USB device descriptor...\n");
  650. __try
  651. {
  652. Urb = (PURB)memory->allocate(NonPagedPool,sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  653. if(!Urb) __leave;
  654. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  655. if(!ALLOCATED_OK(IoPacket)) __leave;
  656. IoPacket->setTimeout(getCommandTimeout());
  657. Size = sizeof(USB_DEVICE_DESCRIPTOR);
  658. Descriptor = (PUSB_DEVICE_DESCRIPTOR)memory->allocate(NonPagedPool,Size);
  659. if(!Descriptor) __leave;
  660. UsbBuildGetDescriptorRequest(Urb,
  661. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  662. USB_DEVICE_DESCRIPTOR_TYPE,
  663. 0,
  664. 0,
  665. Descriptor,
  666. NULL,
  667. Size,
  668. NULL);
  669. IoPacket->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  670. Status = sendRequestToDeviceAndWait(IoPacket);
  671. if (NT_SUCCESS(Status))
  672. {
  673. TRACE("Device Descriptor = %x, len %x\n",
  674. Descriptor,
  675. Urb->UrbControlDescriptorRequest.TransferBufferLength);
  676. TRACE("\nGemplus USB SmartCard Device Descriptor:\n");
  677. TRACE("-------------------------\n");
  678. TRACE("bLength 0x%x\n", Descriptor->bLength);
  679. TRACE("bDescriptorType 0x%x\n", Descriptor->bDescriptorType);
  680. TRACE("bcdUSB 0x%x\n", Descriptor->bcdUSB);
  681. TRACE("bDeviceClass 0x%x\n", Descriptor->bDeviceClass);
  682. TRACE("bDeviceSubClass 0x%x\n", Descriptor->bDeviceSubClass);
  683. TRACE("bDeviceProtocol 0x%x\n", Descriptor->bDeviceProtocol);
  684. TRACE("bMaxPacketSize0 0x%x\n", Descriptor->bMaxPacketSize0);
  685. TRACE("idVendor 0x%x\n", Descriptor->idVendor);
  686. TRACE("idProduct 0x%x\n", Descriptor->idProduct);
  687. TRACE("bcdDevice 0x%x\n", Descriptor->bcdDevice);
  688. TRACE("iManufacturer 0x%x\n", Descriptor->iManufacturer);
  689. TRACE("iProduct 0x%x\n", Descriptor->iProduct);
  690. TRACE("iSerialNumber 0x%x\n", Descriptor->iSerialNumber);
  691. TRACE("bNumConfigurations 0x%x\n", Descriptor->bNumConfigurations);
  692. TRACE("-------------------------\n");
  693. }
  694. else
  695. {
  696. TRACE("#### ERROR: Failed to get device descriptor...\n");
  697. CLogger* logger = kernel->getLogger();
  698. if(logger) logger->logEvent(GRCLASS_BUS_DRIVER_FAILED_REQUEST,getSystemObject());
  699. }
  700. __leave;;
  701. }
  702. __finally
  703. {
  704. if(Urb) memory->free(Urb);
  705. DISPOSE_OBJECT(IoPacket);
  706. if (!NT_SUCCESS(Status))
  707. {
  708. if(Descriptor) memory->free(Descriptor);
  709. Descriptor = NULL;
  710. }
  711. else
  712. {
  713. if(Descriptor) TRACE("*** Succeed to get device descriptor ***\n");
  714. }
  715. }
  716. return Descriptor;
  717. }
  718. // Function gets confuguration descriptor
  719. PUSB_CONFIGURATION_DESCRIPTOR CUSBDevice::getConfigurationDescriptor()
  720. {
  721. PUSB_CONFIGURATION_DESCRIPTOR Descriptor = NULL;
  722. PURB Urb;
  723. ULONG Size;
  724. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  725. CIoPacket* IoPacket = NULL;
  726. TRACE("Getting USB configuration descriptor...\n");
  727. __try
  728. {
  729. Urb = (PURB)memory->allocate(NonPagedPool,sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  730. if(!Urb) __leave;
  731. Size = sizeof(USB_CONFIGURATION_DESCRIPTOR);
  732. while(TRUE)
  733. {
  734. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  735. if(!ALLOCATED_OK(IoPacket)) __leave;
  736. IoPacket->setTimeout(getCommandTimeout());
  737. Descriptor = (PUSB_CONFIGURATION_DESCRIPTOR)memory->allocate(NonPagedPool,Size);
  738. if(!Descriptor) __leave;
  739. UsbBuildGetDescriptorRequest(Urb,
  740. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  741. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  742. 0,
  743. 0,
  744. Descriptor,
  745. NULL,
  746. Size,
  747. NULL);
  748. IoPacket->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  749. Status = sendRequestToDeviceAndWait(IoPacket);
  750. if (Urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&
  751. Descriptor->wTotalLength > Size)
  752. {
  753. // If bus driver truncated his descriptor-> resend command with
  754. // bus return value
  755. Size = Descriptor->wTotalLength;
  756. TRACE("Descriptor length retrieved - 0x%x! Getting USB device configuration... ***\n",Size);
  757. IoPacket->dispose();
  758. IoPacket = NULL;
  759. memory->free(Descriptor);
  760. Descriptor = NULL;
  761. Status = STATUS_INSUFFICIENT_RESOURCES;
  762. }
  763. else break;
  764. }
  765. if(NT_SUCCESS(Status))
  766. {
  767. TRACE("\nUSB device Configuration Descriptor = %x, len %x\n",Descriptor,
  768. Urb->UrbControlDescriptorRequest.TransferBufferLength);
  769. TRACE("---------\n");
  770. TRACE("bLength 0x%x\n", Descriptor->bLength);
  771. TRACE("bDescriptorType 0x%x\n", Descriptor->bDescriptorType);
  772. TRACE("wTotalLength 0x%x\n", Descriptor->wTotalLength);
  773. TRACE("bNumInterfaces 0x%x\n", Descriptor->bNumInterfaces);
  774. TRACE("bConfigurationValue 0x%x\n", Descriptor->bConfigurationValue);
  775. TRACE("iConfiguration 0x%x\n", Descriptor->iConfiguration);
  776. TRACE("bmAttributes 0x%x\n", Descriptor->bmAttributes);
  777. TRACE("MaxPower 0x%x\n", Descriptor->MaxPower);
  778. TRACE("---------\n");
  779. }
  780. else
  781. {
  782. TRACE("*** Failed to get configuration descriptor ***\n");
  783. CLogger* logger = kernel->getLogger();
  784. if(logger) logger->logEvent(GRCLASS_BUS_DRIVER_FAILED_REQUEST,getSystemObject());
  785. }
  786. __leave;
  787. }
  788. __finally
  789. {
  790. if(Urb) memory->free(Urb);
  791. DISPOSE_OBJECT(IoPacket);
  792. if (!NT_SUCCESS(Status))
  793. {
  794. if(Descriptor) memory->free(Descriptor);
  795. Descriptor = NULL;
  796. }
  797. else
  798. {
  799. if(Descriptor) TRACE("*** Succeed to get configuration descriptor ***\n");
  800. }
  801. }
  802. return Descriptor;
  803. }
  804. #pragma PAGEDCODE
  805. // Function gets confuguration descriptor
  806. PUSBD_INTERFACE_INFORMATION CUSBDevice::activateInterface(PUSB_CONFIGURATION_DESCRIPTOR Configuration)
  807. {
  808. PURB Urb = NULL;
  809. USHORT Size;
  810. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  811. USHORT j;
  812. PUSBD_INTERFACE_LIST_ENTRY InterfaceList;
  813. PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor = NULL;
  814. PUSBD_INTERFACE_INFORMATION Interface = NULL;
  815. PUSBD_INTERFACE_INFORMATION UsbInterface = NULL;
  816. ULONG NumberOfInterfaces;
  817. CIoPacket* IoPacket = NULL;
  818. TRACE("Activating USB device configuration %8.8lX, setting device interface...\n",Configuration);
  819. if(!Configuration) return NULL;
  820. // get this from the config descriptor
  821. NumberOfInterfaces = Configuration->bNumInterfaces;
  822. // We only support one interface!
  823. TRACE("\nNumber of interfaces at the configuration - %d \n",NumberOfInterfaces);
  824. // USBD_ParseConfigurationDescriptorEx searches a given configuration
  825. // descriptor and returns a pointer to an interface that matches the
  826. // given search criteria.
  827. // We only support one interface on this device
  828. if(NumberOfInterfaces==1)
  829. {
  830. InterfaceDescriptor =
  831. USBD_ParseConfigurationDescriptorEx(
  832. Configuration,
  833. Configuration,
  834. 0, // intreface number, don't care
  835. -1, // alt setting, don't care
  836. -1, // class, don't care
  837. -1, // subclass, don't care
  838. -1);// protocol, don't care
  839. }
  840. else
  841. {
  842. if(NumberOfInterfaces>1)
  843. {
  844. TRACE("Trying next to get interface descriptor for KEYBOARD READER...\n");
  845. InterfaceDescriptor =
  846. USBD_ParseConfigurationDescriptorEx(
  847. Configuration,
  848. Configuration,
  849. 1, // intreface number 1 for keyboard reader
  850. -1, // alt setting, don't care
  851. -1, // class, don't care
  852. -1, // subclass, don't care
  853. -1);// protocol, don't care
  854. }
  855. }
  856. if (!InterfaceDescriptor)
  857. {
  858. TRACE("##### ERROR: Failed to get interface description...\n");
  859. return NULL;
  860. }
  861. InterfaceList = (PUSBD_INTERFACE_LIST_ENTRY)memory->allocate(NonPagedPool,sizeof(USBD_INTERFACE_LIST_ENTRY) * (NumberOfInterfaces+1));
  862. if(!InterfaceList)
  863. {
  864. TRACE("Failed to alloacte memory for the interfacelist...\n");
  865. return NULL;
  866. }
  867. // We support only one interface after current!
  868. InterfaceList->InterfaceDescriptor = InterfaceDescriptor;
  869. InterfaceList++;
  870. InterfaceList->InterfaceDescriptor = NULL;
  871. InterfaceList--;
  872. __try
  873. {
  874. //For now our device support only one interface.
  875. Urb = USBD_CreateConfigurationRequestEx(Configuration, InterfaceList);
  876. if(!Urb) __leave;
  877. Interface = &Urb->UrbSelectConfiguration.Interface;
  878. TRACE("Pipe MaximumTransferSize set to 0x%x\n",m_MaximumTransferSize);
  879. for (ULONG i=0; i< Interface->NumberOfPipes; i++)
  880. {
  881. // perform any pipe initialization here
  882. Interface->Pipes[i].MaximumTransferSize = m_MaximumTransferSize;
  883. Interface->Pipes[i].PipeFlags = 0;
  884. }
  885. TRACE("Building select configuration request...\n");
  886. Size = sizeof(struct _URB_SELECT_CONFIGURATION);
  887. UsbBuildSelectConfigurationRequest(Urb,Size, Configuration);
  888. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  889. if(!ALLOCATED_OK(IoPacket)) __leave;
  890. IoPacket->setTimeout(getCommandTimeout());
  891. IoPacket->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  892. Status = sendRequestToDeviceAndWait(IoPacket);
  893. if (!NT_SUCCESS(Status))
  894. {
  895. TRACE("##### ERROR: Failed to Select configuration, ret 0x%x...\n",Status);
  896. CLogger* logger = kernel->getLogger();
  897. if(logger) logger->logEvent(GRCLASS_BUS_DRIVER_FAILED_REQUEST,getSystemObject());
  898. __leave;
  899. }
  900. // Save the configuration handle for this device
  901. // Well... It is not really nice to initialize it here, but...
  902. m_ConfigurationHandle = Urb->UrbSelectConfiguration.ConfigurationHandle;
  903. TRACE("Device Configuration handle 0x%x\n",m_ConfigurationHandle);
  904. UsbInterface = (PUSBD_INTERFACE_INFORMATION)memory->allocate(NonPagedPool,Interface->Length);
  905. if (!UsbInterface)
  906. {
  907. TRACE(("##### ERROR: Failed to allocate memory for the UsbInterface\n"));
  908. __leave;
  909. }
  910. // save a copy of the interface information returned
  911. memory->copy(UsbInterface, Interface, Interface->Length);
  912. TRACE("\nGemplus USB device interface:\n");
  913. // Dump the interface to the debugger
  914. TRACE("---------\n");
  915. TRACE("NumberOfPipes 0x%x\n", UsbInterface->NumberOfPipes);
  916. TRACE("Length 0x%x\n", UsbInterface->Length);
  917. TRACE("Alt Setting 0x%x\n", UsbInterface->AlternateSetting);
  918. TRACE("Interface Number 0x%x\n", UsbInterface->InterfaceNumber);
  919. TRACE("Class, subclass, protocol 0x%x 0x%x 0x%x\n",
  920. UsbInterface->Class,
  921. UsbInterface->SubClass,
  922. UsbInterface->Protocol);
  923. TRACE("---------\n");
  924. // Dump the pipe info
  925. for (j=0; j<Interface->NumberOfPipes; j++)
  926. {
  927. PUSBD_PIPE_INFORMATION pipeInformation;
  928. pipeInformation = &UsbInterface->Pipes[j];
  929. TRACE("\nGemplus USB device pipe[%d] ",j);
  930. if(pipeInformation->PipeType==UsbdPipeTypeBulk)
  931. {
  932. if(pipeInformation->EndpointAddress&0x80)
  933. {
  934. TRACE(("(Bulk Response Pipe):\n"));
  935. m_ResponsePipe = pipeInformation->PipeHandle;
  936. TRACE("m_ResponsePipe 0x%x\n", m_ResponsePipe);
  937. }
  938. else
  939. {
  940. TRACE("(Bulk Command pipe):\n");
  941. m_CommandPipe = pipeInformation->PipeHandle;
  942. TRACE("m_CommandPipe 0x%x\n", m_CommandPipe);
  943. }
  944. }
  945. else
  946. {
  947. if(pipeInformation->PipeType==UsbdPipeTypeInterrupt)
  948. {
  949. if(pipeInformation->EndpointAddress&0x80)
  950. {
  951. TRACE(("(Interrupt Response Pipe):\n"));
  952. m_InterruptPipe = pipeInformation->PipeHandle;
  953. TRACE("m_InterruptPipe 0x%x\n", m_InterruptPipe);
  954. }
  955. else
  956. {
  957. TRACE(("(Unexpected Interrupt OUT pipe):\n"));
  958. TRACE("Unexpected pipe 0x%x\n", pipeInformation);
  959. }
  960. }
  961. else
  962. {
  963. TRACE("Unexpected pipe type 0x%x\n", pipeInformation);
  964. }
  965. }
  966. TRACE("---------\n");
  967. TRACE("PipeType 0x%x\n", pipeInformation->PipeType);
  968. TRACE("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress);
  969. TRACE("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize);
  970. TRACE("Interval 0x%x\n", pipeInformation->Interval);
  971. TRACE("Handle 0x%x\n", pipeInformation->PipeHandle);
  972. TRACE("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize);
  973. }
  974. TRACE("---------\n");
  975. __leave;
  976. }
  977. __finally
  978. {
  979. if(Urb) memory->free(Urb);
  980. if(InterfaceList) memory->free(InterfaceList);
  981. DISPOSE_OBJECT(IoPacket);
  982. if (!NT_SUCCESS(Status))
  983. {
  984. if(UsbInterface) memory->free(UsbInterface);
  985. UsbInterface = NULL;
  986. }
  987. else
  988. {
  989. if(UsbInterface) TRACE("*** Succeed to set UsbInterface ***\n");
  990. }
  991. }
  992. return UsbInterface;
  993. }
  994. #pragma PAGEDCODE
  995. // Function gets confuguration descriptor
  996. NTSTATUS CUSBDevice::disactivateInterface()
  997. {
  998. PURB Urb = NULL;
  999. USHORT Size;
  1000. NTSTATUS Status = STATUS_SUCCESS;
  1001. CIoPacket* IoPacket;
  1002. TRACE("Disactivating USB device interface...\n");
  1003. Size = sizeof(struct _URB_SELECT_CONFIGURATION);
  1004. Urb = (PURB)memory->allocate(NonPagedPool,Size);
  1005. if(!Urb)
  1006. {
  1007. TRACE("##### ERROR: Failed to create disable configuration request...\n");
  1008. return STATUS_INSUFFICIENT_RESOURCES;
  1009. }
  1010. //UsbBuildSelectConfigurationRequest(Urb,Size, NULL);
  1011. (Urb)->UrbHeader.Function = URB_FUNCTION_SELECT_CONFIGURATION;
  1012. (Urb)->UrbHeader.Length = Size;
  1013. (Urb)->UrbSelectConfiguration.ConfigurationDescriptor = NULL;
  1014. __try
  1015. {
  1016. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  1017. if(!ALLOCATED_OK(IoPacket)) __leave;
  1018. IoPacket->setTimeout(getCommandTimeout());
  1019. IoPacket->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  1020. Status = sendRequestToDeviceAndWait(IoPacket);
  1021. if (!NT_SUCCESS(Status))
  1022. {
  1023. TRACE("##### ERROR: Failed to disable device interface..., ret %x...\n",Status);
  1024. }
  1025. __leave;
  1026. }
  1027. __finally
  1028. {
  1029. if(Urb) memory->free(Urb);
  1030. DISPOSE_OBJECT(IoPacket);
  1031. if (!NT_SUCCESS(Status))
  1032. {
  1033. TRACE("*** Failed to disactivateInterface() %8.8lX ***\n",Status);
  1034. }
  1035. else
  1036. {
  1037. TRACE("*** Succeed to disactivateInterface() ***\n");
  1038. }
  1039. }
  1040. return Status;
  1041. }
  1042. #pragma PAGEDCODE
  1043. // Function resets specified pipe
  1044. NTSTATUS CUSBDevice::resetPipe(IN USBD_PIPE_HANDLE Pipe)
  1045. {
  1046. PURB Urb = NULL;
  1047. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  1048. CIoPacket* IoPacket;
  1049. TRACE("Resetting USB device pipe %8.8lX...\n",Pipe);
  1050. Urb = (PURB)memory->allocate(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST));
  1051. if (!Urb)
  1052. {
  1053. TRACE("#### ERROR: Failed to allocate Urb at Pipe reset...\n");
  1054. return STATUS_INSUFFICIENT_RESOURCES;
  1055. }
  1056. Urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  1057. Urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  1058. Urb->UrbPipeRequest.PipeHandle = Pipe;
  1059. __try
  1060. {
  1061. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  1062. if(!ALLOCATED_OK(IoPacket)) __leave;
  1063. IoPacket->setTimeout(getCommandTimeout());
  1064. IoPacket->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  1065. Status = sendRequestToDeviceAndWait(IoPacket);
  1066. if (!NT_SUCCESS(Status))
  1067. {
  1068. TRACE("##### ERROR: Failed to reset Pipe, ret %x...\n",Status);
  1069. }
  1070. __leave;
  1071. }
  1072. __finally
  1073. {
  1074. if(Urb) memory->free(Urb);
  1075. DISPOSE_OBJECT(IoPacket);
  1076. if (!NT_SUCCESS(Status))
  1077. {
  1078. TRACE("*** Failed to resetPipe() %8.8lX ***\n",Status);
  1079. }
  1080. else
  1081. {
  1082. TRACE("*** Succeed to resetPipe() ***\n");
  1083. }
  1084. }
  1085. return Status;
  1086. }
  1087. #pragma PAGEDCODE
  1088. // Function resets specified pipe
  1089. NTSTATUS CUSBDevice::resetDevice()
  1090. {
  1091. PURB Urb = NULL;
  1092. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  1093. CIoPacket* IoPacket;
  1094. TRACE("Resetting USB device...\n");
  1095. Urb = (PURB)memory->allocate(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST));
  1096. if (!Urb)
  1097. {
  1098. TRACE("#### ERROR: Failed to allocate Urb at Device reset...\n");
  1099. return STATUS_INSUFFICIENT_RESOURCES;
  1100. }
  1101. __try
  1102. {
  1103. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  1104. if(!ALLOCATED_OK(IoPacket)) __leave;
  1105. IoPacket->setTimeout(getCommandTimeout());
  1106. IoPacket->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_RESET_PORT,Urb);
  1107. Status = sendRequestToDeviceAndWait(IoPacket);
  1108. if (!NT_SUCCESS(Status))
  1109. {
  1110. TRACE("##### ERROR: Failed to reset Device, ret %x...\n",Status);
  1111. }
  1112. __leave;
  1113. }
  1114. __finally
  1115. {
  1116. if(Urb) memory->free(Urb);
  1117. DISPOSE_OBJECT(IoPacket);
  1118. if (!NT_SUCCESS(Status))
  1119. {
  1120. TRACE("*** Failed to resetPipe() %8.8lX ***\n",Status);
  1121. }
  1122. else
  1123. {
  1124. TRACE("*** Succeed to resetPipe() ***\n");
  1125. }
  1126. }
  1127. return Status;
  1128. }
  1129. // Called as part of sudden device removal handling.
  1130. // Cancels any pending transfers for all open pipes.
  1131. // If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
  1132. // Also marks the pipe 'closed' in our saved configuration info.
  1133. NTSTATUS CUSBDevice::abortPipes()
  1134. {
  1135. PURB Urb = NULL;
  1136. NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
  1137. PUSBD_PIPE_INFORMATION Pipe;
  1138. CIoPacket* IoPacket;
  1139. TRACE("Aborting all USB device pipes...\n");
  1140. Urb = (PURB)memory->allocate(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST));
  1141. if (!Urb)
  1142. {
  1143. TRACE("#### ERROR: Failed to allocate Urb at Pipe reset...\n");
  1144. return STATUS_INSUFFICIENT_RESOURCES;
  1145. }
  1146. for (USHORT i=0; i<m_Interface->NumberOfPipes; i++)
  1147. {
  1148. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  1149. if(!ALLOCATED_OK(IoPacket)) break;
  1150. IoPacket->setTimeout(getCommandTimeout());
  1151. Pipe = &m_Interface->Pipes[i]; // PUSBD_PIPE_INFORMATION PipeInfo;
  1152. if ( Pipe->PipeFlags )
  1153. { // we set this if open, clear if closed
  1154. Urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  1155. Urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
  1156. Urb->UrbPipeRequest.PipeHandle = Pipe->PipeHandle;
  1157. IoPacket->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  1158. Status = sendRequestToDeviceAndWait(IoPacket);
  1159. if (!NT_SUCCESS(Status))
  1160. {
  1161. TRACE("##### ERROR: Failed to abort Pipe %d\n",i);
  1162. }
  1163. Pipe->PipeFlags = FALSE; // mark the pipe 'closed'
  1164. }
  1165. DISPOSE_OBJECT(IoPacket);
  1166. }
  1167. if(Urb) memory->free(Urb);
  1168. TRACE("**** Interface' pipes closed ****\n");
  1169. return STATUS_SUCCESS;;
  1170. }
  1171. NTSTATUS CUSBDevice::resetAllPipes()
  1172. {
  1173. PURB Urb = NULL;
  1174. NTSTATUS Status;
  1175. PUSBD_PIPE_INFORMATION Pipe;
  1176. CIoPacket* IoPacket;
  1177. TRACE("Resetting all USB device pipes...\n");
  1178. Urb = (PURB)memory->allocate(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST));
  1179. if (!Urb)
  1180. {
  1181. TRACE("#### ERROR: Failed to allocate Urb at Pipe reset...\n");
  1182. return STATUS_INSUFFICIENT_RESOURCES;
  1183. }
  1184. for (USHORT i=0; i<m_Interface->NumberOfPipes; i++)
  1185. {
  1186. IoPacket = new (NonPagedPool) CIoPacket(m_pLowerDeviceObject->StackSize);
  1187. if(!ALLOCATED_OK(IoPacket)) break;
  1188. IoPacket->setTimeout(getCommandTimeout());
  1189. Pipe = &m_Interface->Pipes[i]; // PUSBD_PIPE_INFORMATION PipeInfo;
  1190. if ( Pipe->PipeFlags )
  1191. { // we set this if open, clear if closed
  1192. Urb->UrbHeader.Length = sizeof (struct _URB_PIPE_REQUEST);
  1193. Urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  1194. Urb->UrbPipeRequest.PipeHandle = Pipe->PipeHandle;
  1195. IoPacket->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  1196. Status = sendRequestToDeviceAndWait(IoPacket);
  1197. if (!NT_SUCCESS(Status))
  1198. {
  1199. TRACE("##### ERROR: Failed to abort Pipe %d\n",i);
  1200. }
  1201. Pipe->PipeFlags = FALSE; // mark the pipe 'closed'
  1202. }
  1203. DISPOSE_OBJECT(IoPacket);
  1204. }
  1205. if(Urb) memory->free(Urb);
  1206. TRACE(("**** Interface pipes were resetted ****\n"));
  1207. return STATUS_SUCCESS;;
  1208. }
  1209. // Overwrite base class virtual functions
  1210. //Handle IRP_MJ_DEVICE_CONTROL request
  1211. NTSTATUS CUSBDevice::deviceControl(IN PIRP Irp)
  1212. {
  1213. if (!NT_SUCCESS(acquireRemoveLock())) return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  1214. PIO_STACK_LOCATION stack = irp->getCurrentStackLocation(Irp);
  1215. ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
  1216. //ULONG outlength = stack->Parameters.DeviceIoControl.OutputBufferLength;
  1217. NTSTATUS status = STATUS_SUCCESS;
  1218. ULONG info = 0;
  1219. TRACE("IRP_MJ_DEVICE_CONTROL\n");
  1220. //switch (code)
  1221. { // process control operation
  1222. //default:
  1223. TRACE("INVALID_DEVICE_REQUEST\n");
  1224. status = STATUS_INVALID_DEVICE_REQUEST;
  1225. }
  1226. releaseRemoveLock();
  1227. return completeDeviceRequest(Irp, status, info);
  1228. }
  1229. NTSTATUS CUSBDevice::read(IN PIRP Irp)
  1230. {
  1231. NTSTATUS status = STATUS_SUCCESS;
  1232. ULONG info = 0;
  1233. CIoPacket* IoPacket;
  1234. if (!NT_SUCCESS(acquireRemoveLock())) return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  1235. TRACE("---- Read request ----\n");
  1236. if(!m_ResponsePipe)
  1237. {
  1238. TRACE("#### ERROR: Response Pipe is not ready yet!...\n");
  1239. releaseRemoveLock();
  1240. return completeDeviceRequest(Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
  1241. }
  1242. if(!NT_SUCCESS(status = waitForIdleAndBlock()))
  1243. {
  1244. releaseRemoveLock();
  1245. return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  1246. }
  1247. if(Response_ErrorNum)
  1248. {
  1249. NTSTATUS res_status = resetPipe(m_ResponsePipe);
  1250. if(NT_SUCCESS(res_status)) Response_ErrorNum = 0;
  1251. }
  1252. IoPacket = new (NonPagedPool) CIoPacket(Irp);
  1253. if(!ALLOCATED_OK(IoPacket))
  1254. {
  1255. DISPOSE_OBJECT(IoPacket);
  1256. setIdle();
  1257. releaseRemoveLock();
  1258. return completeDeviceRequest(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
  1259. }
  1260. status = readSynchronously(IoPacket,m_ResponsePipe);
  1261. TRACE("---- Read completed ----\n");
  1262. status = completeDeviceRequest(IoPacket->getIrpHandle(), status, IoPacket->getInformation());
  1263. DISPOSE_OBJECT(IoPacket);
  1264. setIdle();
  1265. releaseRemoveLock();
  1266. return status;
  1267. }
  1268. NTSTATUS CUSBDevice::write(IN PIRP Irp)
  1269. {
  1270. NTSTATUS status = STATUS_SUCCESS;
  1271. ULONG info = 0;
  1272. CIoPacket* IoPacket;
  1273. if(!Irp) return STATUS_INVALID_PARAMETER;
  1274. if (!NT_SUCCESS(acquireRemoveLock())) return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  1275. TRACE("---- Write request ----\n");
  1276. if(!m_CommandPipe)
  1277. {
  1278. TRACE("#### ERROR: Command Pipe is not ready yet!...\n");
  1279. releaseRemoveLock();
  1280. return completeDeviceRequest(Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
  1281. }
  1282. if(!NT_SUCCESS(status = waitForIdleAndBlock()))
  1283. {
  1284. releaseRemoveLock();
  1285. return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  1286. }
  1287. if(Command_ErrorNum)
  1288. {
  1289. NTSTATUS res_status = resetPipe(m_CommandPipe);
  1290. if(NT_SUCCESS(res_status)) Command_ErrorNum = 0;
  1291. }
  1292. IoPacket = new (NonPagedPool) CIoPacket(Irp);
  1293. if(!ALLOCATED_OK(IoPacket))
  1294. {
  1295. DISPOSE_OBJECT(IoPacket);
  1296. releaseRemoveLock();
  1297. return completeDeviceRequest(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
  1298. }
  1299. status = writeSynchronously(IoPacket,m_CommandPipe);
  1300. releaseRemoveLock();
  1301. TRACE("---- Write completed ----\n");
  1302. status = completeDeviceRequest(IoPacket->getIrpHandle(), status, IoPacket->getInformation());
  1303. DISPOSE_OBJECT(IoPacket);
  1304. setIdle();
  1305. releaseRemoveLock();
  1306. return status;
  1307. }
  1308. NTSTATUS CUSBDevice::sendRequestToDevice(CIoPacket* IoPacket,PIO_COMPLETION_ROUTINE Routine)
  1309. {
  1310. if(!IoPacket) return STATUS_INVALID_PARAMETER;
  1311. IoPacket->copyStackToNext();
  1312. if(Routine) IoPacket->setCompletion(Routine);
  1313. else IoPacket->setDefaultCompletionFunction();
  1314. return system->callDriver(getLowerDriver(),IoPacket->getIrpHandle());
  1315. };
  1316. // Send request to low level driver and wait for reply
  1317. // Current IRP will not be completed, so we can process it and
  1318. // complete later.
  1319. // See also description of send() function.
  1320. NTSTATUS CUSBDevice::sendRequestToDeviceAndWait(CIoPacket* IoPacket)
  1321. { // Send request to low level and wait for a reply
  1322. NTSTATUS status;
  1323. TRACE("sendAndWait...\n");
  1324. if(!IoPacket) return STATUS_INVALID_PARAMETER;
  1325. IoPacket->setStackDefaults();
  1326. status = system->callDriver(getLowerDriver(),IoPacket->getIrpHandle());
  1327. if(status == STATUS_PENDING)
  1328. {
  1329. TRACE("Waiting for the bus driver to complete...\n");
  1330. ASSERT(system->getCurrentIrql()<=DISPATCH_LEVEL);
  1331. status = IoPacket->waitForCompletion();
  1332. TRACE("Request completed with status %x\n",status);
  1333. }
  1334. return status;
  1335. };
  1336. NTSTATUS CUSBDevice::send(CIoPacket* packet)
  1337. {
  1338. NTSTATUS status;
  1339. if(!packet) return STATUS_INVALID_PARAMETER;
  1340. __try
  1341. {
  1342. if(packet->getMajorIOCtl()==IRP_MJ_READ)
  1343. {
  1344. if(!m_ResponsePipe)
  1345. {
  1346. TRACE("#### ERROR: Response Pipe is not ready yet!...\n");
  1347. status = STATUS_INVALID_DEVICE_REQUEST;
  1348. __leave;
  1349. }
  1350. status = readSynchronously(packet,m_ResponsePipe);
  1351. }
  1352. else
  1353. {
  1354. if(!m_CommandPipe)
  1355. {
  1356. TRACE("#### ERROR: Command Pipe is not ready yet!...\n");
  1357. status = STATUS_INVALID_DEVICE_REQUEST;
  1358. __leave;
  1359. }
  1360. status = writeSynchronously(packet,m_CommandPipe);
  1361. }
  1362. __leave;
  1363. }
  1364. __finally
  1365. {
  1366. }
  1367. return status;
  1368. };
  1369. NTSTATUS CUSBDevice::sendAndWait(CIoPacket* packet)
  1370. {
  1371. NTSTATUS status = STATUS_SUCCESS;
  1372. if(!packet) return STATUS_INVALID_PARAMETER;
  1373. __try
  1374. {
  1375. if(packet->getMajorIOCtl()==IRP_MJ_READ)
  1376. {
  1377. TRACE("---- Packet Read request ----\n");
  1378. if(!m_ResponsePipe)
  1379. {
  1380. TRACE("#### ERROR: Response Pipe is not ready yet!...\n");
  1381. status = STATUS_INVALID_DEVICE_REQUEST;
  1382. __leave;
  1383. }
  1384. status = readSynchronously(packet,m_ResponsePipe);
  1385. TRACE("---- Packet Read completed ----\n");
  1386. }
  1387. else
  1388. {
  1389. TRACE("---- Packet Write request ----\n");
  1390. if(!m_CommandPipe)
  1391. {
  1392. TRACE("#### ERROR: Command Pipe is not ready yet!...\n");
  1393. status = STATUS_INVALID_DEVICE_REQUEST;
  1394. __leave;
  1395. }
  1396. status = writeSynchronously(packet,m_CommandPipe);
  1397. TRACE("---- Packet Write completed ----\n");
  1398. if(!NT_SUCCESS(status))
  1399. {
  1400. TRACE("writeSynchronously reported error %x\n", status);
  1401. }
  1402. }
  1403. __leave;
  1404. }
  1405. __finally
  1406. {
  1407. }
  1408. return status;
  1409. };
  1410. NTSTATUS CUSBDevice::readSynchronously(CIoPacket* Irp,IN USBD_PIPE_HANDLE Pipe)
  1411. {
  1412. NTSTATUS ntStatus = STATUS_SUCCESS;
  1413. PURB Urb = NULL;
  1414. NTSTATUS Status;
  1415. if(!Irp) return STATUS_INVALID_PARAMETER;
  1416. if(Pipe != m_ResponsePipe && Pipe != m_InterruptPipe)
  1417. {
  1418. TRACE("##### ERROR: Invalid device Pipe requested!...\n");
  1419. return STATUS_INVALID_DEVICE_REQUEST;
  1420. }
  1421. Urb = buildBusTransferRequest(Irp,RESPONSE_REQUEST);
  1422. if (!Urb)
  1423. {
  1424. TRACE("#### ERROR: Failed to allocate Urb at Pipe read...\n");
  1425. return STATUS_INSUFFICIENT_RESOURCES;
  1426. }
  1427. Irp->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  1428. Status = sendRequestToDeviceAndWait(Irp);
  1429. if (!NT_SUCCESS(Status))
  1430. {
  1431. TRACE("##### ERROR: Bus driver reported error 0x%x\n",Status);
  1432. Response_ErrorNum++;
  1433. Irp->setInformation(0);
  1434. }
  1435. else
  1436. {
  1437. Irp->setInformation(Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
  1438. finishBusTransferRequest(Irp,RESPONSE_REQUEST);
  1439. }
  1440. USBD_STATUS urb_status = URB_STATUS(Urb);
  1441. TRACE("URB reports status %8.8lX\n",urb_status);
  1442. memory->free(Urb);
  1443. return Status;
  1444. }
  1445. NTSTATUS CUSBDevice::writeSynchronously(CIoPacket* Irp,IN USBD_PIPE_HANDLE Pipe)
  1446. {
  1447. NTSTATUS ntStatus = STATUS_SUCCESS;
  1448. PURB Urb = NULL;
  1449. NTSTATUS Status;
  1450. if(!Irp) return STATUS_INVALID_PARAMETER;
  1451. if(Pipe != m_CommandPipe)
  1452. {
  1453. TRACE("##### ERROR: Invalid device Pipe requested!...\n");
  1454. return STATUS_INVALID_DEVICE_REQUEST;
  1455. }
  1456. Urb = buildBusTransferRequest(Irp,COMMAND_REQUEST);
  1457. if (!Urb)
  1458. {
  1459. TRACE("#### ERROR: Failed to allocate Urb at Pipe read...\n");
  1460. return STATUS_INSUFFICIENT_RESOURCES;
  1461. }
  1462. Irp->buildStack(getSystemObject(),IRP_MJ_INTERNAL_DEVICE_CONTROL, 0, IOCTL_INTERNAL_USB_SUBMIT_URB,Urb);
  1463. Status = sendRequestToDeviceAndWait(Irp);
  1464. if (!NT_SUCCESS(Status))
  1465. {
  1466. TRACE("##### ERROR: Bus driver reported error %8.8lX\n",Status);
  1467. Command_ErrorNum++;
  1468. }
  1469. else
  1470. {
  1471. finishBusTransferRequest(Irp,COMMAND_REQUEST);
  1472. }
  1473. USBD_STATUS urb_status = URB_STATUS(Urb);
  1474. TRACE(" URB reports status %8.8lX\n",urb_status);
  1475. Irp->setInformation(0);
  1476. memory->free(Urb);
  1477. return Status;
  1478. }
  1479. NTSTATUS CUSBDevice::writeAndWait(PUCHAR pRequest,ULONG RequestLength,PUCHAR pReply,ULONG* pReplyLength)
  1480. {
  1481. NTSTATUS status;
  1482. CIoPacket* IoPacket;
  1483. if(!pRequest || !RequestLength || !pReply || !pReplyLength) return STATUS_INVALID_PARAMETER;
  1484. if(Response_ErrorNum || Command_ErrorNum)
  1485. {
  1486. TRACE("======= RESETTING ERROR CONDITIONS! =========\n");
  1487. NTSTATUS res_status = resetDevice();
  1488. if(NT_SUCCESS(res_status))
  1489. {
  1490. Command_ErrorNum = 0;
  1491. Response_ErrorNum = 0;
  1492. }
  1493. else
  1494. {
  1495. *pReplyLength = 0;
  1496. TRACE("======= FAILED TO RESET DEVICE! =========\n");
  1497. return STATUS_INVALID_DEVICE_STATE;
  1498. }
  1499. /*
  1500. NTSTATUS res_status = resetPipe(m_ResponsePipe);
  1501. if(NT_SUCCESS(res_status)) Response_ErrorNum = 0;
  1502. else
  1503. {
  1504. *pReplyLength = 0;
  1505. TRACE("======= FAILED TO RESET RESPONSE PIPE! =========\n");
  1506. resetDevice();
  1507. //return STATUS_INVALID_DEVICE_STATE;
  1508. }
  1509. res_status = resetPipe(m_CommandPipe);
  1510. if(NT_SUCCESS(res_status)) Command_ErrorNum = 0;
  1511. else
  1512. {
  1513. *pReplyLength = 0;
  1514. TRACE("======= FAILED TO RESET COMMAND PIPE! =========\n");
  1515. //return STATUS_INVALID_DEVICE_STATE;
  1516. res_status = resetDevice();
  1517. if(NT_SUCCESS(res_status)) Command_ErrorNum = 0;
  1518. else
  1519. {
  1520. *pReplyLength = 0;
  1521. TRACE("======= FAILED TO RESET DEVICE! =========\n");
  1522. return STATUS_INVALID_DEVICE_STATE;
  1523. }
  1524. }
  1525. */
  1526. }
  1527. IoPacket = new (NonPagedPool) CIoPacket(getLowerDriver()->StackSize);
  1528. if(!ALLOCATED_OK(IoPacket))
  1529. {
  1530. DISPOSE_OBJECT(IoPacket);
  1531. return STATUS_INSUFFICIENT_RESOURCES;
  1532. }
  1533. IoPacket->setTimeout(getCommandTimeout());
  1534. TRACE("IoPacket with device %x\n",getSystemObject());
  1535. IoPacket->buildStack(getSystemObject(),IRP_MJ_WRITE);
  1536. IoPacket->setWriteLength(RequestLength);
  1537. IoPacket->copyBuffer(pRequest,RequestLength);
  1538. TRACE(" USB sendAndWait()...\n");
  1539. status = sendAndWait(IoPacket);
  1540. TRACE(" USB writeAndWait finished: %x\n",status);
  1541. if(!NT_SUCCESS(status))
  1542. {
  1543. *pReplyLength = 0;
  1544. IoPacket->dispose();
  1545. return status;
  1546. }
  1547. // Ignore bus driver reply...
  1548. DISPOSE_OBJECT(IoPacket);
  1549. TRACE(" **** Current WTR %d\n",get_WTR_Delay());
  1550. DELAY(get_WTR_Delay());
  1551. IoPacket = new (NonPagedPool) CIoPacket(getLowerDriver()->StackSize);
  1552. if(!ALLOCATED_OK(IoPacket))
  1553. {
  1554. DISPOSE_OBJECT(IoPacket);
  1555. return STATUS_INSUFFICIENT_RESOURCES;
  1556. }
  1557. IoPacket->setTimeout(getCommandTimeout());
  1558. IoPacket->buildStack(getSystemObject(),IRP_MJ_READ);
  1559. IoPacket->setReadLength(RequestLength);
  1560. IoPacket->copyBuffer(pRequest,RequestLength);
  1561. TRACE(" USB sendAndWait()...\n");
  1562. status = sendAndWait(IoPacket);
  1563. TRACE(" USB sendAndWait finished: %x\n",status);
  1564. if(!NT_SUCCESS(status))
  1565. {
  1566. *pReplyLength = 0;
  1567. IoPacket->dispose();
  1568. return status;
  1569. }
  1570. *pReplyLength = (ULONG)IoPacket->getInformation();
  1571. IoPacket->getSystemReply(pReply,*pReplyLength);
  1572. //TRACE_BUFFER(pReply,*pReplyLength);
  1573. DISPOSE_OBJECT(IoPacket);
  1574. return status;
  1575. };
  1576. NTSTATUS CUSBDevice::readAndWait(PUCHAR pRequest,ULONG RequestLength,PUCHAR pReply,ULONG* pReplyLength)
  1577. {
  1578. CIoPacket* IoPacket;
  1579. if(!pRequest || !RequestLength || !pReply || !pReplyLength) return STATUS_INVALID_PARAMETER;
  1580. if(Response_ErrorNum || Command_ErrorNum)
  1581. {
  1582. TRACE("======= RESETTING ERROR CONDITIONS! =========\n");
  1583. NTSTATUS res_status = resetDevice();
  1584. if(NT_SUCCESS(res_status))
  1585. {
  1586. Command_ErrorNum = 0;
  1587. Response_ErrorNum = 0;
  1588. }
  1589. else
  1590. {
  1591. *pReplyLength = 0;
  1592. TRACE("======= FAILED TO RESET DEVICE! =========\n");
  1593. return STATUS_INVALID_DEVICE_STATE;
  1594. }
  1595. /*TRACE("======= RESETTING ERROR CONDITIONS AT PIPES! =========\n");
  1596. NTSTATUS res_status = resetPipe(m_ResponsePipe);
  1597. if(NT_SUCCESS(res_status)) Response_ErrorNum = 0;
  1598. else
  1599. {
  1600. *pReplyLength = 0;
  1601. TRACE("======= FAILED TO RESET RESPONSE PIPE! =========\n");
  1602. return STATUS_INVALID_DEVICE_STATE;
  1603. }
  1604. res_status = resetPipe(m_CommandPipe);
  1605. if(NT_SUCCESS(res_status)) Command_ErrorNum = 0;
  1606. else
  1607. {
  1608. *pReplyLength = 0;
  1609. TRACE("======= FAILED TO RESET COMMAND PIPE! =========\n");
  1610. return STATUS_INVALID_DEVICE_STATE;
  1611. }
  1612. */
  1613. }
  1614. IoPacket = new (NonPagedPool) CIoPacket(getLowerDriver()->StackSize);
  1615. if(!ALLOCATED_OK(IoPacket))
  1616. {
  1617. DISPOSE_OBJECT(IoPacket);
  1618. return STATUS_INSUFFICIENT_RESOURCES;
  1619. }
  1620. IoPacket->setTimeout(getCommandTimeout());
  1621. IoPacket->buildStack(getSystemObject(),IRP_MJ_READ);
  1622. IoPacket->setReadLength(RequestLength);
  1623. IoPacket->copyBuffer(pRequest,RequestLength);
  1624. TRACE("WDM sendAndWait()...\n");
  1625. NTSTATUS status = sendAndWait(IoPacket);
  1626. TRACE("WDM sendAndWait finished: %x\n",status);
  1627. if(!NT_SUCCESS(status))
  1628. {
  1629. *pReplyLength = 0;
  1630. IoPacket->dispose();
  1631. return status;
  1632. }
  1633. *pReplyLength = (ULONG)IoPacket->getInformation();
  1634. IoPacket->getSystemReply(pReply,*pReplyLength);
  1635. //TRACE_BUFFER(pReply,*pReplyLength);
  1636. DISPOSE_OBJECT(IoPacket);
  1637. return status;
  1638. };
  1639. // Handle IRP_MJ_POWER request
  1640. // This routine uses the IRP's minor function code to dispatch a handler
  1641. // function (such as HandleSetPower for IRP_MN_SET_POWER). It calls DefaultPowerHandler
  1642. // for any function we don't specifically need to handle.
  1643. NTSTATUS CUSBDevice::powerRequest(IN PIRP Irp)
  1644. {
  1645. if(!Irp) return STATUS_INVALID_PARAMETER;
  1646. if (!NT_SUCCESS(acquireRemoveLock()))
  1647. {
  1648. power->startNextPowerIrp(Irp); // must be done while we own the IRP
  1649. return completeDeviceRequest(Irp, STATUS_DELETE_PENDING, 0);
  1650. }
  1651. PIO_STACK_LOCATION stack = irp->getCurrentStackLocation(Irp);
  1652. ASSERT(stack->MajorFunction == IRP_MJ_POWER);
  1653. ULONG fcn = stack->MinorFunction;
  1654. NTSTATUS status;
  1655. if (fcn >= arraysize(Powerfcntab))
  1656. { // unknown function
  1657. status = power_Default(Irp);
  1658. releaseRemoveLock();
  1659. return status;
  1660. }
  1661. #ifdef DEBUG
  1662. if (fcn == IRP_MN_SET_POWER || fcn == IRP_MN_QUERY_POWER)
  1663. {
  1664. ULONG context = stack->Parameters.Power.SystemContext;
  1665. POWER_STATE_TYPE type = stack->Parameters.Power.Type;
  1666. TRACE("\n(%s)\nSystemContext %X, ", Powerfcnname[fcn], context);
  1667. if (type==SystemPowerState)
  1668. {
  1669. TRACE("SYSTEM POWER STATE = %s\n", Powersysstate[stack->Parameters.Power.State.SystemState]);
  1670. }
  1671. else
  1672. {
  1673. TRACE("DEVICE POWER STATE = %s\n", Powerdevstate[stack->Parameters.Power.State.DeviceState]);
  1674. }
  1675. }
  1676. else
  1677. TRACE("Request (%s)\n", Powerfcnname[fcn]);
  1678. #endif // DEBUG
  1679. status = callPowerHandler(fcn,Irp);
  1680. releaseRemoveLock();
  1681. return status;
  1682. }
  1683. VOID CUSBDevice::activatePowerHandler(LONG HandlerID)
  1684. {
  1685. if (HandlerID >= arraysize(Powerfcntab)) return;
  1686. Powerfcntab[HandlerID] = TRUE;
  1687. }
  1688. VOID CUSBDevice::disActivatePowerHandler(LONG HandlerID)
  1689. {
  1690. if (HandlerID >= arraysize(Powerfcntab)) return;
  1691. Powerfcntab[HandlerID] = FALSE;
  1692. }
  1693. NTSTATUS CUSBDevice::callPowerHandler(LONG HandlerID,IN PIRP Irp)
  1694. {
  1695. if(!Powerfcntab[HandlerID]) // If Handler is not registered...
  1696. return power_Default(Irp);
  1697. // Call registered Power Handler...
  1698. // This is virtual function...
  1699. switch(HandlerID)
  1700. {
  1701. case IRP_MN_WAIT_WAKE: return power_HandleWaitWake(Irp);
  1702. break;
  1703. case IRP_MN_POWER_SEQUENCE: return power_HandleSequencePower(Irp);
  1704. break;
  1705. case IRP_MN_SET_POWER: return power_HandleSetPower(Irp);
  1706. break;
  1707. case IRP_MN_QUERY_POWER: return power_HandleQueryPower(Irp);
  1708. break;
  1709. }
  1710. return power_Default(Irp);
  1711. }
  1712. #pragma PAGEDCODE
  1713. NTSTATUS CUSBDevice::power_HandleSetPower(IN PIRP Irp)
  1714. {
  1715. PIO_STACK_LOCATION irpStack;
  1716. NTSTATUS status = STATUS_SUCCESS;
  1717. BOOLEAN fGoingToD0 = FALSE;
  1718. POWER_STATE sysPowerState, desiredDevicePowerState;
  1719. if(!Irp) return STATUS_INVALID_PARAMETER;
  1720. irpStack = irp->getCurrentStackLocation (Irp);
  1721. switch (irpStack->Parameters.Power.Type)
  1722. {
  1723. case SystemPowerState:
  1724. // Get input system power state
  1725. sysPowerState.SystemState = irpStack->Parameters.Power.State.SystemState;
  1726. #ifdef DEBUG
  1727. TRACE("Set Power with type SystemPowerState = %s\n",Powersysstate[sysPowerState.SystemState]);
  1728. #endif
  1729. // If system is in working state always set our device to D0
  1730. // regardless of the wait state or system-to-device state power map
  1731. if ( sysPowerState.SystemState == PowerSystemWorking)
  1732. {
  1733. desiredDevicePowerState.DeviceState = PowerDeviceD0;
  1734. TRACE("PowerSystemWorking, device will be set to D0, state map is not used\n");
  1735. }
  1736. else
  1737. {
  1738. // set to corresponding system state if IRP_MN_WAIT_WAKE pending
  1739. if (isEnabledForWakeup())
  1740. { // got a WAIT_WAKE IRP pending?
  1741. // Find the device power state equivalent to the given system state.
  1742. // We get this info from the DEVICE_CAPABILITIES struct in our device
  1743. // extension (initialized in BulkUsb_PnPAddDevice() )
  1744. desiredDevicePowerState.DeviceState = m_DeviceCapabilities.DeviceState[sysPowerState.SystemState];
  1745. TRACE("IRP_MN_WAIT_WAKE pending, will use state map\n");
  1746. }
  1747. else
  1748. {
  1749. // if no wait pending and the system's not in working state, just turn off
  1750. desiredDevicePowerState.DeviceState = PowerDeviceD3;
  1751. TRACE("Not EnabledForWakeup and the system's not in the working state,\n settting PowerDeviceD3(off)\n");
  1752. }
  1753. }
  1754. // We've determined the desired device state; are we already in this state?
  1755. #ifdef DEBUG
  1756. TRACE("Set Power, desiredDevicePowerState = %s\n",
  1757. Powerdevstate[desiredDevicePowerState.DeviceState]);
  1758. #endif
  1759. if (desiredDevicePowerState.DeviceState != m_CurrentDevicePowerState)
  1760. {
  1761. acquireRemoveLock();// Callback will release the lock
  1762. // No, request that we be put into this state
  1763. // by requesting a new Power Irp from the Pnp manager
  1764. registerPowerIrp(Irp);
  1765. IoMarkIrpPending(Irp);
  1766. status = power->requestPowerIrp(getSystemObject(),
  1767. IRP_MN_SET_POWER,
  1768. desiredDevicePowerState,
  1769. // completion routine will pass the Irp down to the PDO
  1770. (PREQUEST_POWER_COMPLETE)onPowerRequestCompletion,
  1771. this, NULL);
  1772. }
  1773. else
  1774. { // Yes, just pass it on to PDO (Physical Device Object)
  1775. irp->copyCurrentStackLocationToNext(Irp);
  1776. power->startNextPowerIrp(Irp);
  1777. status = power->callPowerDriver(getLowerDriver(),Irp);
  1778. }
  1779. break;
  1780. case DevicePowerState:
  1781. #ifdef DEBUG
  1782. TRACE("Set DevicePowerState %s\n",
  1783. Powerdevstate[irpStack->Parameters.Power.State.DeviceState]);
  1784. #endif
  1785. // For requests to D1, D2, or D3 ( sleep or off states ),
  1786. // sets deviceExtension->CurrentDevicePowerState to DeviceState immediately.
  1787. // This enables any code checking state to consider us as sleeping or off
  1788. // already, as this will imminently become our state.
  1789. // For requests to DeviceState D0 ( fully on ), sets fGoingToD0 flag TRUE
  1790. // to flag that we must set a completion routine and update
  1791. // deviceExtension->CurrentDevicePowerState there.
  1792. // In the case of powering up to fully on, we really want to make sure
  1793. // the process is completed before updating our CurrentDevicePowerState,
  1794. // so no IO will be attempted or accepted before we're really ready.
  1795. fGoingToD0 = setDevicePowerState(irpStack->Parameters.Power.State.DeviceState); // returns TRUE for D0
  1796. if (fGoingToD0)
  1797. {
  1798. acquireRemoveLock();// Callback will release the lock
  1799. TRACE("Set PowerIrp Completion Routine, fGoingToD0 =%d\n", fGoingToD0);
  1800. irp->copyCurrentStackLocationToNext(Irp);
  1801. irp->setCompletionRoutine(Irp,
  1802. onPowerIrpComplete,
  1803. // Always pass FDO to completion routine as its Context;
  1804. // This is because the DriverObject passed by the system to the routine
  1805. // is the Physical Device Object ( PDO ) not the Functional Device Object ( FDO )
  1806. this,
  1807. TRUE, // invoke on success
  1808. TRUE, // invoke on error
  1809. TRUE); // invoke on cancellation of the Irp
  1810. // Completion routine will set our state and start next power Irp
  1811. }
  1812. else
  1813. {
  1814. // D3 device state
  1815. //Device reduces power, so do specific for device processing...
  1816. onSystemPowerDown();
  1817. // Report our state to power manager
  1818. desiredDevicePowerState.DeviceState = PowerDeviceD3;
  1819. power->declarePowerState(getSystemObject(),DevicePowerState,desiredDevicePowerState);
  1820. irp->copyCurrentStackLocationToNext(Irp);
  1821. power->startNextPowerIrp(Irp);
  1822. }
  1823. status = power->callPowerDriver(getLowerDriver(),Irp);
  1824. break;
  1825. } /* case irpStack->Parameters.Power.Type */
  1826. return status;
  1827. }
  1828. #pragma PAGEDCODE
  1829. VOID CUSBDevice::onSystemPowerDown()
  1830. {
  1831. return;
  1832. }
  1833. #pragma PAGEDCODE
  1834. VOID CUSBDevice::onSystemPowerUp()
  1835. {
  1836. return;
  1837. }
  1838. #pragma PAGEDCODE
  1839. BOOLEAN CUSBDevice::setDevicePowerState(IN DEVICE_POWER_STATE DeviceState)
  1840. {
  1841. NTSTATUS ntStatus = STATUS_SUCCESS;
  1842. BOOLEAN fRes = FALSE;
  1843. switch (DeviceState)
  1844. {
  1845. case PowerDeviceD3:
  1846. // Device will be going OFF,
  1847. // TODO: add any needed device-dependent code to save state here.
  1848. // ( We have nothing to do in this sample )
  1849. TRACE("SetDevicePowerState() PowerDeviceD3 (OFF)\n");
  1850. setCurrentDevicePowerState(DeviceState);
  1851. break;
  1852. case PowerDeviceD1:
  1853. case PowerDeviceD2:
  1854. // power states D1,D2 translate to USB suspend
  1855. #ifdef DEBUG
  1856. TRACE("SetDevicePowerState() %s\n",Powerdevstate[DeviceState]);
  1857. #endif
  1858. setCurrentDevicePowerState(DeviceState);
  1859. break;
  1860. case PowerDeviceD0:
  1861. TRACE("Set Device Power State to PowerDeviceD0(ON)\n");
  1862. // We'll need to finish the rest in the completion routine;
  1863. // signal caller we're going to D0 and will need to set a completion routine
  1864. fRes = TRUE;
  1865. // Caller will pass on to PDO ( Physical Device object )
  1866. break;
  1867. default:
  1868. TRACE(" Bogus DeviceState = %x\n", DeviceState);
  1869. }
  1870. return fRes;
  1871. }
  1872. /*++
  1873. Routine Description:
  1874. This is the completion routine set in a call to PoRequestPowerIrp()
  1875. that was made in ProcessPowerIrp() in response to receiving
  1876. an IRP_MN_SET_POWER of type 'SystemPowerState' when the device was
  1877. not in a compatible device power state. In this case, a pointer to
  1878. the IRP_MN_SET_POWER Irp is saved into the FDO device extension
  1879. (deviceExtension->PowerIrp), and then a call must be
  1880. made to PoRequestPowerIrp() to put the device into a proper power state,
  1881. and this routine is set as the completion routine.
  1882. We decrement our pending io count and pass the saved IRP_MN_SET_POWER Irp
  1883. on to the next driver
  1884. Arguments:
  1885. DeviceObject - Pointer to the device object for the class device.
  1886. Note that we must get our own device object from the Context
  1887. Context - Driver defined context, in this case our own functional device object ( FDO )
  1888. Return Value:
  1889. The function value is the final status from the operation.
  1890. --*/
  1891. #pragma LOCKEDCODE
  1892. NTSTATUS onPowerRequestCompletion(
  1893. IN PDEVICE_OBJECT DeviceObject,
  1894. IN UCHAR MinorFunction,
  1895. IN POWER_STATE PowerState,
  1896. IN PVOID Context,
  1897. IN PIO_STATUS_BLOCK IoStatus
  1898. )
  1899. {
  1900. PIRP Irp;
  1901. NTSTATUS status;
  1902. if(!Context) return STATUS_INVALID_PARAMETER;
  1903. CUSBReader* device = (CUSBReader*) Context;
  1904. // Get the Irp we saved for later processing
  1905. // when we decided to request the Power Irp that this routine
  1906. // is the completion routine for.
  1907. Irp = device->getPowerIrp();
  1908. // We will return the status set by the PDO for the power request we're completing
  1909. status = IoStatus->Status;
  1910. DBG_PRINT("Enter onPowerRequestCompletion()\n");
  1911. // we must pass down to the next driver in the stack
  1912. IoCopyCurrentIrpStackLocationToNext(Irp);
  1913. // Calling PoStartNextPowerIrp() indicates that the driver is finished
  1914. // with the previous power IRP, if any, and is ready to handle the next power IRP.
  1915. // It must be called for every power IRP.Although power IRPs are completed only once,
  1916. // typically by the lowest-level driver for a device, PoStartNextPowerIrp must be called
  1917. // for every stack location. Drivers must call PoStartNextPowerIrp while the current IRP
  1918. // stack location points to the current driver. Therefore, this routine must be called
  1919. // before IoCompleteRequest, IoSkipCurrentStackLocation, and PoCallDriver.
  1920. PoStartNextPowerIrp(Irp);
  1921. // PoCallDriver is used to pass any power IRPs to the PDO instead of IoCallDriver.
  1922. // When passing a power IRP down to a lower-level driver, the caller should use
  1923. // IoSkipCurrentIrpStackLocation or IoCopyCurrentIrpStackLocationToNext to copy the IRP to
  1924. // the next stack location, then call PoCallDriver. Use IoCopyCurrentIrpStackLocationToNext
  1925. // if processing the IRP requires setting a completion routine, or IoSkipCurrentStackLocation
  1926. // if no completion routine is needed.
  1927. PoCallDriver(device->getLowerDriver(),Irp);
  1928. device->unregisterPowerIrp();
  1929. device->releaseRemoveLock();
  1930. DBG_PRINT("Exit onPowerRequestCompletion()\n");
  1931. return status;
  1932. }
  1933. /*++
  1934. Routine Description:
  1935. This routine is called when An IRP_MN_SET_POWER of type 'DevicePowerState'
  1936. has been received by BulkUsb_ProcessPowerIrp(), and that routine has determined
  1937. 1) the request is for full powerup ( to PowerDeviceD0 ), and
  1938. 2) We are not already in that state
  1939. A call is then made to PoRequestPowerIrp() with this routine set as the completion routine.
  1940. Arguments:
  1941. DeviceObject - Pointer to the device object for the class device.
  1942. Irp - Irp completed.
  1943. Context - Driver defined context.
  1944. Return Value:
  1945. The function value is the final status from the operation.
  1946. --*/
  1947. #pragma LOCKEDCODE
  1948. NTSTATUS onPowerIrpComplete(
  1949. IN PDEVICE_OBJECT NullDeviceObject,
  1950. IN PIRP Irp,
  1951. IN PVOID Context
  1952. )
  1953. {
  1954. NTSTATUS status = STATUS_SUCCESS;
  1955. PIO_STACK_LOCATION irpStack;
  1956. POWER_STATE desiredDevicePowerState;
  1957. DBG_PRINT("Enter onPowerIrpComplete()\n");
  1958. if(!Context) return STATUS_INVALID_PARAMETER;
  1959. CUSBReader* device = (CUSBReader*) Context;
  1960. // If the lower driver returned PENDING, mark our stack location as pending also.
  1961. if (Irp->PendingReturned) IoMarkIrpPending(Irp);
  1962. irpStack = IoGetCurrentIrpStackLocation (Irp);
  1963. // We can assert that we're a device powerup-to D0 request,
  1964. // because that was the only type of request we set a completion routine
  1965. // for in the first place
  1966. ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
  1967. ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
  1968. ASSERT(irpStack->Parameters.Power.Type==DevicePowerState);
  1969. ASSERT(irpStack->Parameters.Power.State.DeviceState==PowerDeviceD0);
  1970. // Now that we know we've let the lower drivers do what was needed to power up,
  1971. // we can set our device extension flags accordingly
  1972. device->setCurrentDevicePowerState(PowerDeviceD0);
  1973. // Do device specific stuff...
  1974. device->onSystemPowerUp();
  1975. Irp->IoStatus.Status = status;
  1976. device->releaseRemoveLock();
  1977. desiredDevicePowerState.DeviceState = PowerDeviceD0;
  1978. PoSetPowerState(device->getSystemObject(),DevicePowerState,desiredDevicePowerState);
  1979. PoStartNextPowerIrp(Irp);
  1980. DBG_PRINT("Exit onPowerIrpComplete() for the state D0\n");
  1981. return status;
  1982. }
  1983. #pragma PAGEDCODE
  1984. NTSTATUS CUSBDevice::power_HandleWaitWake(IN PIRP Irp)
  1985. {
  1986. return power_Default(Irp);
  1987. }
  1988. NTSTATUS CUSBDevice::power_HandleSequencePower(IN PIRP Irp)
  1989. {
  1990. return power_Default(Irp);
  1991. }
  1992. NTSTATUS CUSBDevice::power_HandleQueryPower(IN PIRP Irp)
  1993. {
  1994. TRACE("******** QUERY POWER ********\n");
  1995. if(isDeviceLocked())
  1996. {
  1997. TRACE("******** FAILED TO CHANGE POWER (DEVICE BUSY) ********\n");
  1998. Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
  1999. power->startNextPowerIrp(Irp); // must be done while we own the IRP
  2000. return completeDeviceRequest(Irp, STATUS_DEVICE_BUSY, 0);
  2001. }
  2002. Irp->IoStatus.Status = STATUS_SUCCESS;
  2003. return power_Default(Irp);
  2004. }
  2005. NTSTATUS CUSBDevice::createDeviceObjectByName(PDEVICE_OBJECT* ppFdo)
  2006. {
  2007. NTSTATUS status;
  2008. // Construct device name...
  2009. CUString* index = new (PagedPool) CUString(getDeviceNumber(),10);
  2010. CUString* base = new (PagedPool) CUString(NT_OBJECT_NAME);
  2011. if(!ALLOCATED_OK(index) || !ALLOCATED_OK(base))
  2012. {
  2013. DISPOSE_OBJECT(index);
  2014. DISPOSE_OBJECT(base);
  2015. return STATUS_INSUFFICIENT_RESOURCES;
  2016. }
  2017. USHORT size = (USHORT)(index->getLength() + base->getLength() + sizeof(WCHAR));
  2018. // Allocate string with required length
  2019. m_DeviceObjectName = new (NonPagedPool) CUString(size);
  2020. if(!ALLOCATED_OK(m_DeviceObjectName))
  2021. {
  2022. DISPOSE_OBJECT(index);
  2023. DISPOSE_OBJECT(base);
  2024. DISPOSE_OBJECT(m_DeviceObjectName);
  2025. return STATUS_INSUFFICIENT_RESOURCES;
  2026. }
  2027. m_DeviceObjectName->append(&base->m_String);
  2028. m_DeviceObjectName->append(&index->m_String);
  2029. TRACE("Driver registers DeviceObjectName as %ws\n", m_DeviceObjectName->m_String.Buffer);
  2030. delete index;
  2031. delete base;
  2032. status = system->createDevice(m_DriverObject,sizeof(CWDMDevice*),&m_DeviceObjectName->m_String,
  2033. FILE_DEVICE_UNKNOWN,0,FALSE,ppFdo);
  2034. if(!NT_SUCCESS(status))
  2035. {
  2036. TRACE("#### Failed to create physical device! Status %x\n",status);
  2037. delete m_DeviceObjectName;
  2038. }
  2039. return status;
  2040. }
  2041. #endif // USBDEVICE_PROJECT