Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3633 lines
142 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. chap9drv.c
  5. Abstract:
  6. USB device driver for Intel/Microsoft diagnostic apps
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 5-4-96 : created
  17. --*/
  18. #define DRIVER
  19. #define USBDIAG_VERSION 0x0610
  20. #include "wdm.h"
  21. #include "stdarg.h"
  22. #include "stdio.h"
  23. // Enable 1-byte alignment in structs
  24. #pragma pack (push,1)
  25. #include "usb100.h"
  26. #include "usbdi.h"
  27. #include "usbdlib.h"
  28. #include "usbioctl.h"
  29. #pragma pack (pop) //disable 1-byte alignment
  30. #include "opaque.h"
  31. // Enable 1-byte alignment in structs
  32. #pragma pack (push,1)
  33. #include "hidpddi.h"
  34. #include "ioctl.h"
  35. #include "chap9drv.h"
  36. #include "USBDIAG.h"
  37. #include "chap11.h"
  38. #include "_m_usb.h"
  39. #include "typedefs.h"
  40. #pragma pack (pop) //disable 1-byte alignment
  41. #define DEADMAN_TIMEOUT 5000 //timeout in ms; we use a 5 second timeout
  42. #define RAWPACKET_DIRECTION_IN(bmReq) (((bmReq) & bmReqD2H)>>7)
  43. extern USBD_VERSION_INFORMATION gVersionInformation;
  44. /* ------------------ local prototypes ---------------*/
  45. typedef BYTE *PBYTE;
  46. VOID
  47. Ch9FillInReqStatus (
  48. IN NTSTATUS ntStatusCode,
  49. IN ULONG ulUrbStatus,
  50. IN OUT struct _REQ_HEADER * pReqHeader
  51. );
  52. PBYTE
  53. pAllocFromBuffer(
  54. PBYTE pBuffer,
  55. ULONG iSize,
  56. PULONG piOffset,
  57. PULONG piTotalUsed,
  58. ULONG iAmountRequested
  59. );
  60. /* ------------------ end local prototypes ---------------*/
  61. NTSTATUS
  62. USBDIAG_Chap9Control(
  63. IN PDEVICE_OBJECT DeviceObject,
  64. IN PIRP Irp
  65. )
  66. /*++
  67. Routine Description:
  68. Arguments:
  69. DeviceObject - pointer to the device object for the USBDIAG driver's device
  70. object, which is not the actual physical device. That ptr is not
  71. used here since our PDO is in the REQ packet sent down from user app,
  72. and that is in the IRP.
  73. Return Value:
  74. NT status code
  75. --*/
  76. {
  77. PIO_STACK_LOCATION irpStack;
  78. PVOID ioBuffer = NULL;
  79. ULONG inputBufferLength = 0;
  80. ULONG outputBufferLength= 0;
  81. NTSTATUS ntStatus = STATUS_SUCCESS;
  82. PURB urb = NULL;
  83. ULONG ulUrbStatus = USBD_STATUS_SUCCESS;
  84. ULONG siz = 0;
  85. ULONG sizeToCopy;
  86. BOOLEAN bCompleteIrp = TRUE;
  87. PUSB_DEVICE_DESCRIPTOR deviceDesc ;
  88. struct _REQ_HEADER * REQHeader;
  89. PDEVICE_LIST_ENTRY devListEntry;
  90. PDEVICE_OBJECT actualdeviceObject = NULL;
  91. PDEVICE_EXTENSION deviceExtension = NULL;
  92. // Get a pointer to the current location in the Irp. This is where
  93. // the function codes and parameters are located.
  94. irpStack = IoGetCurrentIrpStackLocation (Irp);
  95. // Get the pointer to the input/output buffer and it's length
  96. ioBuffer = Irp->AssociatedIrp.SystemBuffer;
  97. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  98. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  99. // The REQHeader, which is the struct that the app fills in describing this REQuest is
  100. // referenced in the SystemBuffer since it is sent down in the InputBuffer field of the
  101. // DeviceIoControl call in User Mode.
  102. REQHeader = (struct _REQ_HEADER *)ioBuffer;
  103. // The DeviceHandle is a ptr to the list entry that USBDIAG manages for devices it is
  104. // testing. This used to be a "USBD Device handle" in the old Chap9 method. Now it's a
  105. // ptr to the list entry object that USBDIAG maintains for each device under test. That
  106. // list entry contains the PDO and other junk about the device object
  107. devListEntry = (PDEVICE_LIST_ENTRY)(REQHeader->UsbdDeviceHandle);
  108. //USBDIAG_KdPrint(("USBDIAG.SYS: DevListEntry: %X\n",devListEntry));
  109. // Device object given is not the real DevObj that was created by PnPAddDevice, so
  110. // extract that DevObj with a handy macro before calling the lower level drivers (USB stk)
  111. // NOTE: This extracted DevObj contains the deviceExtension that in turn contains
  112. // the "StackDeviceObject" that is needed by the IoCallDriver function to pass
  113. // Urbs down the stack.
  114. if(devListEntry)
  115. {
  116. actualdeviceObject = FDO_FROM_DEVICE_HANDLE(devListEntry);
  117. deviceExtension = actualdeviceObject->DeviceExtension;
  118. //USBDIAG_KdPrint(("USBDIAG.SYS: PDO for DUT: %X\n",actualdeviceObject));
  119. }
  120. // Find out which of the Chap9 functions is being sent down from app
  121. switch (REQHeader->Function)
  122. {
  123. case REQ_FUNCTION_RESET_PARENT_PORT:
  124. {
  125. ntStatus = USBDIAG_ResetParentPort(actualdeviceObject);
  126. Irp->IoStatus.Status = ntStatus;
  127. Irp->IoStatus.Information = sizeof(struct _REQ_HEADER);
  128. }
  129. break;
  130. case REQ_FUNCTION_GET_CHAP9VERSION:
  131. {
  132. struct _REQ_GETCHAP9_VERSION * pGetVersion;
  133. pGetVersion = (struct _REQ_GETCHAP9_VERSION *)(ioBuffer);
  134. pGetVersion->Version = USBDIAG_VERSION;
  135. ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
  136. Irp->IoStatus.Information = sizeof (struct _REQ_GETCHAP9_VERSION);
  137. }
  138. break;
  139. case REQ_FUNCTION_GET_DESCRIPTOR:
  140. {
  141. /* Create an URB for the USBD call to get device descriptor. */
  142. struct _REQ_GETSET_DESCRIPTOR *pGetSetDesc = (struct _REQ_GETSET_DESCRIPTOR *)(ioBuffer) ;
  143. //USBDIAG_KdPrint(("***USBDIAG.SYS: In Get Descriptor 0x%x\n", pGetSetDesc->DescriptorType)) ;
  144. switch (pGetSetDesc->DescriptorType)
  145. {
  146. case USB_DEVICE_DESCRIPTOR_TYPE:
  147. USBDIAG_KdPrint (("USBDIAG.SYS: DEVICE DESCRIPTOR requested\n"));
  148. break;
  149. case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  150. USBDIAG_KdPrint (("USBDIAG.SYS: CONFIG DESCRIPTOR requested\n"));
  151. break;
  152. case USB_STRING_DESCRIPTOR_TYPE:
  153. USBDIAG_KdPrint (("USBDIAG.SYS: STRING DESCRIPTOR requested\n"));
  154. break;
  155. default:
  156. USBDIAG_KdPrint (("USBDIAG.SYS: Error--Unknown Descriptor Type Requested!!\n"));
  157. TRAP();
  158. break;
  159. }//switch
  160. siz = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST) ;
  161. urb = USBDIAG_ExAllocatePool(NonPagedPool, siz ) ;
  162. if (urb)
  163. {
  164. // Get the memory in Ke mode for this txfer, based on client's request
  165. siz = (pGetSetDesc->TransferBufferLength);
  166. deviceDesc = USBDIAG_ExAllocatePool(NonPagedPool, siz);
  167. if (deviceDesc)
  168. {
  169. // NOTE: We create the URB down in Ke mode.
  170. UsbBuildGetDescriptorRequest(
  171. urb,
  172. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  173. (UCHAR)(pGetSetDesc->DescriptorType),
  174. (UCHAR)(pGetSetDesc->Index), // Descriptor Index
  175. pGetSetDesc->LanguageId, //language ID
  176. deviceDesc, //transfer buffer
  177. NULL, // " " MDL
  178. siz, //transfer buffer length
  179. NULL); //link - not used
  180. ntStatus = USBDIAG_Ch9CallUSBD(actualdeviceObject, urb, TRUE, NULL, NULL, TRUE);
  181. ulUrbStatus = urb->UrbHeader.Status; //capture the urb status for later
  182. if (!NT_SUCCESS(ntStatus))
  183. {
  184. USBDIAG_KdPrint (("USBDIAG.SYS: Error in Get device descriptor\n")) ;
  185. }
  186. if ( pGetSetDesc->DescriptorType == USB_DEVICE_DESCRIPTOR_TYPE )
  187. {
  188. //USBDIAG_KdPrint(("USBDIAG.SYS: A device descriptor was requested. Got back \n"));
  189. /*USBDIAG_KdPrint(("USBDIAG.SYS: \tDevDesc Length = %x, type %x MaxpacketSize %x\n",
  190. deviceDesc->bLength,
  191. deviceDesc->bDescriptorType,
  192. deviceDesc->bMaxPacketSize0));
  193. */
  194. }
  195. // copy the data directly into the User Mode buffer. We can do this becauase
  196. // we're still in the thread context of the calling User Mode app
  197. if (( ioBuffer ) && (pGetSetDesc->TransferBuffer))
  198. {
  199. /*
  200. USBDIAG_KdPrint(("USBDIAG.SYS: Device sent back %d bytes of descriptor data\n",
  201. urb->UrbControlDescriptorRequest.TransferBufferLength));
  202. //USBDIAG_KdPrint(("USBDIAG.SYS: Copying %d bytes to UserMode's buffer (at %X)\n",
  203. (pGetSetDesc->TransferBufferLength < urb->UrbControlDescriptorRequest.TransferBufferLength ) ? pGetSetDesc->TransferBufferLength : urb->UrbControlDescriptorRequest.TransferBufferLength,
  204. pGetSetDesc->TransferBuffer));
  205. */
  206. sizeToCopy = pGetSetDesc->TransferBufferLength < urb->UrbControlDescriptorRequest.TransferBufferLength
  207. ? pGetSetDesc->TransferBufferLength
  208. : urb->UrbControlDescriptorRequest.TransferBufferLength;
  209. __try
  210. {
  211. ProbeForWrite(pGetSetDesc->TransferBuffer,
  212. sizeToCopy,
  213. TYPE_ALIGNMENT(HIDP_DEVICE_DESC));
  214. RtlCopyMemory( pGetSetDesc->TransferBuffer,
  215. deviceDesc,
  216. sizeToCopy);
  217. }
  218. __except (EXCEPTION_EXECUTE_HANDLER)
  219. {
  220. ntStatus = STATUS_INVALID_PARAMETER;
  221. sizeToCopy = 0;
  222. // USBDIAG_KdPrint(("USBDIAG.SYS: BAD POINTER RECEIVED! Bailing...\n"));
  223. }
  224. }
  225. USBDIAG_ExFreePool(deviceDesc);
  226. // The Information field tells IOM how much to copy back into the
  227. // usermode buffer in the BUFFERED method
  228. // In this case all we want the IOM to copy back is the REQ itself
  229. // so things like the status field get updated
  230. //
  231. Irp->IoStatus.Information = sizeof(struct _REQ_HEADER);
  232. Irp->IoStatus.Status = ntStatus;
  233. //
  234. // Fill in the length in the REQ block with the number
  235. // of bytes copied back into the TransferBuffer.
  236. //
  237. pGetSetDesc->TransferBufferLength = sizeToCopy;
  238. }
  239. else
  240. {
  241. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  242. }
  243. USBDIAG_ExFreePool(urb);
  244. } // if urb
  245. } // REQ_FUNCTION_GET_DESCRIPTOR
  246. break ;
  247. case REQ_FUNCTION_SET_DESCRIPTOR:
  248. {
  249. struct _REQ_GETSET_DESCRIPTOR *pGetSetDesc = (struct _REQ_GETSET_DESCRIPTOR *)(ioBuffer) ;
  250. //USBDIAG_KdPrint(("USBDIAG.SYS: In Set Descriptor buf = 0x%x\n", *pGetSetDesc)) ;
  251. siz = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST) ;
  252. urb = USBDIAG_ExAllocatePool(NonPagedPool, siz ) ;
  253. if (urb)
  254. {
  255. // Get nonpaged mem for this transfer and use len given by app
  256. siz = pGetSetDesc->TransferBufferLength ;
  257. deviceDesc = USBDIAG_ExAllocatePool(NonPagedPool, siz);
  258. if (deviceDesc)
  259. {
  260. memcpy( deviceDesc, pGetSetDesc->TransferBuffer, siz);
  261. //
  262. // Unfortunately, there is no macro to build a
  263. // SetDescriptorRequest in the USBDI.H. Therefore,
  264. // we will use our own.
  265. //
  266. // NOTE: Should it every appear, the below statement
  267. // can be changed.
  268. //
  269. _m_UsbBuildSetDescriptorRequest(urb,
  270. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), //len
  271. (UCHAR)(pGetSetDesc->DescriptorType), //desc type
  272. (UCHAR)(pGetSetDesc->Index), //index
  273. pGetSetDesc->LanguageId, //language ID
  274. deviceDesc, //buffer
  275. NULL, //MDL
  276. siz, //buff len
  277. NULL); //link
  278. ntStatus = USBDIAG_Ch9CallUSBD(actualdeviceObject, urb, TRUE, NULL, NULL, TRUE);
  279. ulUrbStatus = urb->UrbHeader.Status; //capture the urb status for later
  280. if ( ! NT_SUCCESS(ntStatus) )
  281. {
  282. //USBDIAG_KdPrint(("USBDIAG.SYS: Error in Set device descriptor\n")) ;
  283. }
  284. /*USBDIAG_KdPrint(("USBDIAG.SYS: Set Descriptor at %x, type %x len %x bytes\n",
  285. deviceDesc,
  286. pGetSetDesc->DescriptorType,
  287. urb->UrbControlDescriptorRequest.TransferBufferLength));
  288. */
  289. USBDIAG_ExFreePool(deviceDesc);
  290. }
  291. else
  292. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  293. // The Information field tells IOM how much to copy back into the
  294. // usermode buffer in the BUFFERED method
  295. // In this case all we want the IOM to copy back is the REQ itself
  296. // so things like the status field get updated
  297. Irp->IoStatus.Information = sizeof(*pGetSetDesc);
  298. Irp->IoStatus.Status = ntStatus;
  299. USBDIAG_ExFreePool(urb);
  300. } // if urb
  301. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Set Descriptor\n")) ;
  302. } // End of REQ_FUNCTION_SET_DESCRIPTOR
  303. break ;
  304. case REQ_FUNCTION_SET_FEATURE:
  305. case REQ_FUNCTION_CLEAR_FEATURE:
  306. {
  307. struct _REQ_FEATURE *pSetClrFeature;
  308. pSetClrFeature = (struct _REQ_FEATURE *) ioBuffer;
  309. // We check again here since the set_feat case drops thru here
  310. if (REQHeader->Function == REQ_FUNCTION_CLEAR_FEATURE)
  311. {
  312. //USBDIAG_KdPrint(("USBDIAG.SYS: In Clear Feature\n")) ;
  313. }
  314. else
  315. {
  316. //USBDIAG_KdPrint(("USBDIAG.SYS: In Set Feature\n")) ;
  317. }
  318. if ( pSetClrFeature == NULL )
  319. {
  320. //USBDIAG_KdPrint(("USBDIAG.SYS: NULL parameter passsed\n")) ;
  321. Irp->IoStatus.Information = sizeof(struct _REQ_HEADER);
  322. Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
  323. break ;
  324. }
  325. siz = sizeof(struct _URB_CONTROL_FEATURE_REQUEST) ;
  326. urb = USBDIAG_ExAllocatePool(NonPagedPool, siz ) ;
  327. if (urb)
  328. {
  329. /*
  330. // Set the function code for USBD to use. NOte that the function code
  331. // differs depending on the recipient and so we do this for each of the
  332. // Set and Clear feature requests.
  333. */
  334. ntStatus = STATUS_SUCCESS;
  335. if ( REQHeader->Function == REQ_FUNCTION_CLEAR_FEATURE )
  336. {
  337. //Oh, look it's a CLEAR_FEATURE
  338. switch (pSetClrFeature->Recipient)
  339. {
  340. case (RECIPIENT_DEVICE):
  341. urb->UrbHeader.Function = URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE;
  342. break;
  343. case (RECIPIENT_ENDPOINT):
  344. urb->UrbHeader.Function = URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT;
  345. break;
  346. case (RECIPIENT_INTERFACE):
  347. urb->UrbHeader.Function = URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE;
  348. break;
  349. default:
  350. ntStatus = STATUS_INVALID_PARAMETER;
  351. break;
  352. }//switch
  353. }/*if it's a CLEAR_FEATURE */
  354. else
  355. {
  356. // OK, it's a SET_FEATURE
  357. switch (pSetClrFeature->Recipient)
  358. {
  359. case (RECIPIENT_DEVICE):
  360. urb->UrbHeader.Function = URB_FUNCTION_SET_FEATURE_TO_DEVICE;
  361. break;
  362. case (RECIPIENT_ENDPOINT):
  363. urb->UrbHeader.Function = URB_FUNCTION_SET_FEATURE_TO_ENDPOINT;
  364. break;
  365. case (RECIPIENT_INTERFACE):
  366. urb->UrbHeader.Function = URB_FUNCTION_SET_FEATURE_TO_INTERFACE;
  367. break;
  368. default:
  369. ntStatus = STATUS_INVALID_PARAMETER;
  370. break;
  371. }//switch
  372. }/* else it's a SET_FEATURE */
  373. if (NT_SUCCESS(ntStatus))
  374. {
  375. urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_CONTROL_FEATURE_REQUEST);
  376. urb->UrbControlFeatureRequest.UrbLink = NULL;
  377. urb->UrbControlFeatureRequest.FeatureSelector = pSetClrFeature->FeatureSelector;
  378. urb->UrbControlFeatureRequest.Index = pSetClrFeature->Index;
  379. //USBDIAG_KdPrint(("USBDIAG.SYS: Device Object = %x\n", REQHeader->UsbdDeviceHandle )) ;
  380. ntStatus = USBDIAG_Ch9CallUSBD(actualdeviceObject,
  381. urb,
  382. TRUE,
  383. NULL,
  384. NULL,
  385. TRUE);
  386. //
  387. // Capture the urb status
  388. //
  389. ulUrbStatus = urb->UrbHeader.Status;
  390. }
  391. if (!NT_SUCCESS(ntStatus))
  392. {
  393. //USBDIAG_KdPrint(("USBDIAG.SYS: Error in Set/Clear feature\n")) ;
  394. }
  395. else
  396. {
  397. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully did Set/Clear feature\n")) ;
  398. }
  399. // The Information field tells IOM how much to copy back into the
  400. // usermode buffer in the BUFFERED method
  401. // In this case all we want the IOM to copy back is the REQ itself
  402. // so things like the status field get updated
  403. Irp->IoStatus.Information = sizeof(struct _REQ_FEATURE);
  404. Irp->IoStatus.Status = ntStatus;
  405. USBDIAG_ExFreePool(urb);
  406. } // if urb
  407. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Set/Clear feature\n")) ;
  408. } // End of REQ_FUNCTION_CLEAR_FEATURE
  409. break ;
  410. case REQ_FUNCTION_GET_STATUS:
  411. {
  412. struct _REQ_GET_STATUS * pGetStatus = (struct _REQ_GET_STATUS *)(ioBuffer) ;
  413. //USBDIAG_KdPrint(("USBDIAG.SYS: In GetStatus\n")) ;
  414. if (pGetStatus == NULL)
  415. {
  416. //USBDIAG_KdPrint(("USBDIAG.SYS: NULL parameter passsed\n")) ;
  417. TRAP();
  418. break ;
  419. }
  420. siz = sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST) ;
  421. //Create an URB for the USBD call to get status
  422. urb = USBDIAG_ExAllocatePool(NonPagedPool, siz ) ;
  423. if (urb)
  424. {
  425. USHORT function;
  426. USHORT * pStatus;
  427. switch (pGetStatus->Recipient)
  428. {
  429. case RECIPIENT_DEVICE :
  430. //USBDIAG_KdPrint(("USBDIAG.SYS: Getting Status from DEVICE\n"))
  431. function = URB_FUNCTION_GET_STATUS_FROM_DEVICE;
  432. break;
  433. case RECIPIENT_INTERFACE:
  434. //USBDIAG_KdPrint(("USBDIAG.SYS: Getting Status from INTERFACE\n"))
  435. function = URB_FUNCTION_GET_STATUS_FROM_INTERFACE;
  436. break;
  437. case RECIPIENT_ENDPOINT:
  438. //USBDIAG_KdPrint(("USBDIAG.SYS: Getting Status from ENDPOINT\n"))
  439. function = URB_FUNCTION_GET_STATUS_FROM_ENDPOINT;
  440. break;
  441. default:
  442. //USBDIAG_KdPrint(("USBDIAG.SYS: Getting Status from OTHER (??)\n"))
  443. function = URB_FUNCTION_GET_STATUS_FROM_OTHER; // ?
  444. } //switch
  445. // Fill in the URB
  446. urb->UrbHeader.Function = function;
  447. urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_CONTROL_GET_STATUS_REQUEST);
  448. urb->UrbControlGetStatusRequest.UrbLink = NULL;
  449. //
  450. // Get a buffer for the status data to be put in
  451. // Don't know why we have to get so much more data than we need?
  452. // Don't use siz again but I'm not about to investigate the
  453. // effects of a change.
  454. //
  455. siz = GET_STATUS_DATA_LEN + 128;
  456. pStatus = USBDIAG_ExAllocatePool(NonPagedPool, siz);
  457. if (pStatus == NULL)
  458. {
  459. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed getting mem in GetStatus!\n"));
  460. TRAP();
  461. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  462. goto GetStatus_FreeMem;
  463. }//if
  464. urb->UrbControlGetStatusRequest.TransferBufferLength = GET_STATUS_DATA_LEN;
  465. urb->UrbControlGetStatusRequest.TransferBuffer = pStatus;
  466. urb->UrbControlGetStatusRequest.TransferBufferMDL = NULL;
  467. urb->UrbControlGetStatusRequest.Index = pGetStatus->Index;
  468. ntStatus = USBDIAG_Ch9CallUSBD (actualdeviceObject, urb, TRUE, NULL, NULL, TRUE);
  469. ulUrbStatus = urb->UrbHeader.Status; //capture the urb status for later
  470. if (NT_SUCCESS(ntStatus))
  471. {
  472. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully did Get Status\n")) ;
  473. //USBDIAG_KdPrint(("USBDIAG.SYS: Status value = %02x\n", *pStatus )) ;
  474. pGetStatus->Status = *pStatus ;
  475. }
  476. else
  477. {
  478. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed Get Status\n")) ;
  479. }
  480. USBDIAG_ExFreePool(pStatus) ;
  481. GetStatus_FreeMem:
  482. // The Information field tells IOM how much to copy back into the
  483. // usermode buffer in the BUFFERED method
  484. // In this case all we want the IOM to copy back is the REQ itself
  485. // so things like the status field get updated
  486. Irp->IoStatus.Information = sizeof(struct _REQ_GET_STATUS);
  487. Irp->IoStatus.Status = ntStatus;
  488. USBDIAG_ExFreePool(urb);
  489. }// if urb
  490. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Get Status\n")) ;
  491. } // End of REQ_FUNCTION_GET_STATUS
  492. break ;
  493. case REQ_FUNCTION_SET_ADDRESS:
  494. {
  495. char SetUpPacket[8] ;
  496. struct _REQ_SET_ADDRESS * pSetAddr = (struct _REQ_SET_ADDRESS *)(ioBuffer) ;
  497. //USBDIAG_KdPrint(("USBDIAG.SYS: In Set Address\n")) ;
  498. // Set up the setup packet for SET_ADDRESS
  499. SetUpPacket[0] = 0x0 ;
  500. SetUpPacket[1] = USB_REQUEST_SET_ADDRESS ;
  501. SetUpPacket[2] = LOBYTE(pSetAddr->DevAddr) ;
  502. SetUpPacket[3] = HIBYTE(pSetAddr->DevAddr) ;
  503. SetUpPacket[4] = 0x0 ;
  504. SetUpPacket[5] = 0x0 ;
  505. SetUpPacket[6] = 0x0 ;
  506. SetUpPacket[7] = 0x0 ;
  507. //USBDIAG_KdPrint(("USBDIAG.SYS: Set Address to %02x %02x\n", SetUpPacket[2], SetUpPacket[3] )) ;
  508. siz = 0;
  509. ntStatus = USBDIAG_SendPacket(actualdeviceObject,SetUpPacket, NULL, &siz, &ulUrbStatus) ;
  510. if (NT_SUCCESS(ntStatus))
  511. {
  512. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully did Set Address\n")) ;
  513. }
  514. else
  515. {
  516. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed Set Address\n")) ;
  517. }
  518. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Set Address\n")) ;
  519. // The Information field tells IOM how much to copy back into the
  520. // usermode buffer in the BUFFERED method
  521. // In this case all we want the IOM to copy back is the REQ itself
  522. // so things like the status field get updated
  523. Irp->IoStatus.Information = sizeof(struct _REQ_SET_ADDRESS);
  524. Irp->IoStatus.Status = ntStatus;
  525. // return the status
  526. pSetAddr->Hdr.Status = ntStatus;
  527. } /* end case REQ_FUNCTION_SET_ADDRESS */
  528. break ;
  529. case REQ_FUNCTION_GET_CONFIGURATION:
  530. {
  531. struct _REQ_GETSET_CONFIGURATION * pGetConf = (struct _REQ_GETSET_CONFIGURATION *)(ioBuffer) ;
  532. UCHAR SetUpPacket[8] ;
  533. char *ConfigValue = NULL ;
  534. //USBDIAG_KdPrint(("USBDIAG.SYS: In Get Configuration\n")) ;
  535. siz = 1;
  536. ConfigValue = USBDIAG_ExAllocatePool(NonPagedPool, siz + 16) ;
  537. // Set up the setup packet for GET_CONFIG
  538. SetUpPacket[0] = (bmReqD2H | bmReqSTANDARD | bmReqDEVICE) ;
  539. SetUpPacket[1] = USB_REQUEST_GET_CONFIGURATION ;
  540. SetUpPacket[2] = 0x0;
  541. SetUpPacket[3] = 0x0;
  542. SetUpPacket[4] = 0x0 ;
  543. SetUpPacket[5] = 0x0 ;
  544. SetUpPacket[6] = 0x01 ; //Configuration value is 1 byte
  545. SetUpPacket[7] = 0x0;
  546. ntStatus = USBDIAG_SendPacket( actualdeviceObject, (PCHAR)SetUpPacket, ConfigValue, &siz, &ulUrbStatus) ;
  547. if (NT_SUCCESS(ntStatus))
  548. {
  549. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully did Get Configuration (%d bytes txferred)\n", siz)) ;
  550. //USBDIAG_KdPrint(("USBDIAG.SYS: Configuration value = %02x\n", *ConfigValue )) ;
  551. pGetConf->ConfigValue = (USHORT)*ConfigValue ;
  552. }
  553. else
  554. {
  555. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed Get Configuration\n")) ;
  556. }
  557. // The Information field tells IOM how much to copy back into the
  558. // usermode buffer in the BUFFERED method
  559. // In this case all we want the IOM to copy back is the REQ itself
  560. // so things like the status field get updated
  561. Irp->IoStatus.Information = sizeof(struct _REQ_GETSET_CONFIGURATION);
  562. Irp->IoStatus.Status = ntStatus;
  563. // return the status
  564. pGetConf->Hdr.Status = ntStatus;
  565. USBDIAG_ExFreePool(ConfigValue) ;
  566. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Get Configuration\n")) ;
  567. } // End of case REQ_FUNCTION_GET_CONFIGURATION
  568. break ;
  569. case REQ_FUNCTION_SET_CONFIGURATION:
  570. {
  571. struct _REQ_GETSET_CONFIGURATION * pGetConf = (struct _REQ_GETSET_CONFIGURATION *)(ioBuffer) ;
  572. char SetUpPacket[8] ;
  573. //USBDIAG_KdPrint(("USBDIAG.SYS: In Set Configuration\n")) ;
  574. siz=0;
  575. // Set up the setup packet for SET_CONFIG
  576. SetUpPacket[0] = (bmReqH2D | bmReqSTANDARD | bmReqDEVICE) ;
  577. SetUpPacket[1] = USB_REQUEST_SET_CONFIGURATION ;
  578. SetUpPacket[2] = LOBYTE(pGetConf->ConfigValue) ;
  579. SetUpPacket[3] = HIBYTE(pGetConf->ConfigValue) ;
  580. SetUpPacket[4] = 0x00 ;
  581. SetUpPacket[5] = 0x00 ;
  582. SetUpPacket[6] = 0x00 ;
  583. SetUpPacket[7] = 0x00 ;
  584. ntStatus = USBDIAG_SendPacket(actualdeviceObject,SetUpPacket, NULL, &siz, &ulUrbStatus) ;
  585. if (NT_SUCCESS(ntStatus))
  586. {
  587. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully did Set Configuration to %02x\n", pGetConf->ConfigValue)) ;
  588. }
  589. else
  590. {
  591. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed Set Configuration\n")) ;
  592. }
  593. // The Information field tells IOM how much to copy back into the
  594. // usermode buffer in the BUFFERED method
  595. // In this case all we want the IOM to copy back is the REQ itself
  596. // so things like the status field get updated
  597. Irp->IoStatus.Information = sizeof(struct _REQ_GETSET_CONFIGURATION);
  598. Irp->IoStatus.Status = ntStatus;
  599. // return the status
  600. pGetConf->Hdr.Status = ntStatus;
  601. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Set Configuration\n")) ;
  602. } // End of REQ_FUNCTION_SET_CONFIGURATION
  603. break ;
  604. case REQ_FUNCTION_GET_INTERFACE:
  605. {
  606. struct _REQ_GETSET_INTERFACE * pGetInt = (struct _REQ_GETSET_INTERFACE *)(ioBuffer) ;
  607. UCHAR SetUpPacket[8] ;
  608. ULONG cbBytesToGet;
  609. char *IntValue = NULL ;
  610. //USBDIAG_KdPrint(("USBDIAG.SYS: In Get Interfaces\n")) ;
  611. cbBytesToGet = siz = 1 ;
  612. IntValue = USBDIAG_ExAllocatePool(NonPagedPool, siz) ;
  613. // Set up the setup packet for GET_INTERFACE
  614. SetUpPacket[0] = (bmReqD2H | bmReqSTANDARD | bmReqINTERFACE) ;
  615. SetUpPacket[1] = USB_REQUEST_GET_INTERFACE ;
  616. SetUpPacket[2] = 0 ;
  617. SetUpPacket[3] = 0 ;
  618. SetUpPacket[4] = LOBYTE(pGetInt->Index) ;
  619. SetUpPacket[5] = HIBYTE(pGetInt->Index) ;
  620. SetUpPacket[6] = LOBYTE(cbBytesToGet) ;
  621. SetUpPacket[7] = HIBYTE(cbBytesToGet) ;
  622. ntStatus = USBDIAG_SendPacket(actualdeviceObject, (PCHAR)SetUpPacket, IntValue, &siz, &ulUrbStatus) ;
  623. if (NT_SUCCESS(ntStatus))
  624. {
  625. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully did Get Interface (%d bytes txferred)\n", siz)) ;
  626. //USBDIAG_KdPrint(("USBDIAG.SYS: Interface value = %02x\n", *IntValue )) ;
  627. pGetInt->AltSetting = (USHORT)*IntValue ;
  628. }
  629. else
  630. {
  631. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed Get Interface\n")) ;
  632. }
  633. // The Information field tells IOM how much to copy back into the
  634. // usermode buffer in the BUFFERED method
  635. // In this case all we want the IOM to copy back is the REQ itself
  636. // so things like the status field get updated
  637. Irp->IoStatus.Information = sizeof(struct _REQ_GETSET_INTERFACE);
  638. Irp->IoStatus.Status = ntStatus;
  639. // return the status
  640. pGetInt->Hdr.Status = ntStatus;
  641. USBDIAG_ExFreePool(IntValue) ;
  642. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Get Interfaces\n")) ;
  643. } // End of REQ_FUNCTION_GET_INTERFACE
  644. break ;
  645. case REQ_FUNCTION_SET_INTERFACE:
  646. {
  647. struct _REQ_GETSET_INTERFACE * pGetInt = (struct _REQ_GETSET_INTERFACE *)(ioBuffer) ;
  648. char SetUpPacket[8] ;
  649. //USBDIAG_KdPrint(("USBDIAG.SYS: In Set Interfaces\n")) ;
  650. siz = 0;
  651. // Set up the setup packet for SET_INTERF
  652. SetUpPacket[0] = (bmReqH2D | bmReqSTANDARD | bmReqINTERFACE) ;
  653. SetUpPacket[1] = USB_REQUEST_SET_INTERFACE ;
  654. SetUpPacket[2] = LOBYTE(pGetInt->AltSetting) ;
  655. SetUpPacket[3] = HIBYTE(pGetInt->AltSetting) ;
  656. SetUpPacket[4] = LOBYTE(pGetInt->Index) ;
  657. SetUpPacket[5] = HIBYTE(pGetInt->Index) ;
  658. SetUpPacket[6] = 0x00 ;
  659. SetUpPacket[7] = 0x00 ;
  660. //USBDIAG_KdPrint(("USBDIAG.SYS: SetupPacket: %X\n",SetUpPacket)) ;
  661. ntStatus = USBDIAG_SendPacket(actualdeviceObject, SetUpPacket, NULL, &siz, &ulUrbStatus) ;
  662. if (NT_SUCCESS(ntStatus))
  663. {
  664. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully did Set Interface\n")) ;
  665. }
  666. else
  667. {
  668. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed Set Interface\n")) ;
  669. }
  670. // The Information field tells IOM how much to copy back into the
  671. // usermode buffer in the BUFFERED method
  672. // In this case all we want the IOM to copy back is the REQ itself
  673. // so things like the status field get updated
  674. Irp->IoStatus.Information = sizeof(struct _REQ_GETSET_INTERFACE);
  675. Irp->IoStatus.Status = ntStatus;
  676. // return the status
  677. pGetInt->Hdr.Status = ntStatus;
  678. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Set Interfaces\n")) ;
  679. } // End of REQ_FUNCTION_SET_INTERFACE
  680. break ;
  681. case REQ_FUNCTION_ORAW_PACKET:
  682. {
  683. struct _REQ_HEADER *REQHeader = (struct _REQ_HEADER *)ioBuffer;
  684. struct _REQ_SEND_ORAWPACKET * pRawPkt = (struct _REQ_SEND_ORAWPACKET *)(Irp->UserBuffer) ;
  685. char SetUpPacket[8] ;
  686. char *buffer = NULL ;
  687. UCHAR bmRT=0;
  688. //USBDIAG_KdPrint(("USBDIAG.SYS: Entering Send Raw Packet\n")) ;
  689. //USBDIAG_KdPrint(("USBDIAG.SYS: SystemBuffer: %X\t|UserBuffer: %X\n", ioBuffer, Irp->UserBuffer)) ;
  690. if ( pRawPkt == NULL )
  691. {
  692. ntStatus = STATUS_INSUFFICIENT_RESOURCES ;
  693. //USBDIAG_KdPrint(("USBDIAG.SYS: Called with NULL Raw Packet\n")) ;
  694. break ;
  695. }
  696. bmRT = pRawPkt->bmRequestType; //save the bmReqType in case it gets stomped on (gets used later)
  697. siz = pRawPkt->wLength ;
  698. //USBDIAG_KdPrint(("USBDIAG.SYS: Raw Packet siz = %d\n",siz));
  699. if ( siz )
  700. {
  701. buffer = USBDIAG_ExAllocatePool(NonPagedPool, siz) ;
  702. if ( buffer == NULL )
  703. {
  704. ntStatus = STATUS_INSUFFICIENT_RESOURCES ;
  705. break ;
  706. }//if couldn't get buffer
  707. }
  708. //USBDIAG_KdPrint(("USBDIAG.SYS: Raw Packet bmRequestType = %x bRequest = %x\n",pRawPkt->bmRequestType, pRawPkt->bRequest )) ;
  709. //USBDIAG_KdPrint(("USBDIAG.SYS: wValue = %x wIndex = %x Length = %x\n", pRawPkt->wValue, pRawPkt->wIndex, pRawPkt->wLength )) ;
  710. //USBDIAG_KdPrint(("USBDIAG.SYS: SetupPacket base: %x\n",SetUpPacket));
  711. SetUpPacket[0] = pRawPkt->bmRequestType ;
  712. SetUpPacket[1] = pRawPkt->bRequest ;
  713. SetUpPacket[2] = LOBYTE(pRawPkt->wValue) ;
  714. SetUpPacket[3] = HIBYTE(pRawPkt->wValue) ;
  715. SetUpPacket[4] = LOBYTE(pRawPkt->wIndex) ;
  716. SetUpPacket[5] = HIBYTE(pRawPkt->wIndex) ;
  717. SetUpPacket[6] = LOBYTE(pRawPkt->wLength) ;
  718. SetUpPacket[7] = HIBYTE(pRawPkt->wLength) ;
  719. ntStatus = USBDIAG_SendPacket(actualdeviceObject, SetUpPacket, buffer, &siz, &ulUrbStatus) ;
  720. if (NT_SUCCESS(ntStatus))
  721. {
  722. //USBDIAG_KdPrint(("USBDIAG.SYS: Successful Procssed RAWPKT; copying %d bytes to %X\n",
  723. // siz, pRawPkt->pvBuffer)) ;
  724. // Only copy the data back to user's buffer if user's wLength indicates
  725. // it and there are valid buffers from which to copy and the direction was
  726. // Device to Host
  727. if ( (siz>0) && //some bytes to copy
  728. (buffer != NULL) && //source buffer valid
  729. (pRawPkt->pvBuffer != NULL) && //dest buffer valid
  730. (RAWPACKET_DIRECTION_IN(bmRT))) //dir was Dev2Host
  731. {
  732. // copy data to user mode buffer
  733. memcpy(pRawPkt->pvBuffer, buffer,siz) ;
  734. //Fill in the length in the REQ block so user-mode knows how much data is in buffer
  735. pRawPkt->wLength = LOWORD(siz);
  736. }//if ok to copy to user's buffer
  737. }
  738. else
  739. {
  740. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed Processing RAW PKT : Status = %x\n", ntStatus)) ;
  741. }
  742. // The Information field tells IOM how much to copy back into the
  743. // usermode buffer in the BUFFERED method
  744. // In this case all we want the IOM to copy back is the REQ itself
  745. // so things like the status field get updated
  746. Irp->IoStatus.Information = sizeof(struct _REQ_HEADER);
  747. Irp->IoStatus.Status = ntStatus;
  748. // return the status
  749. REQHeader->Status = ntStatus;
  750. if (buffer != NULL)
  751. {
  752. USBDIAG_ExFreePool(buffer) ;
  753. }// if buffer should be freed
  754. //USBDIAG_KdPrint(("USBDIAG.SYS: Exiting Send Raw Packet\n")) ;
  755. } // End switch REQ_FUNCTION_ORAW_PACKET
  756. break;
  757. case REQ_FUNCTION_READ_FROM_PIPE:
  758. {
  759. struct _REQ_READ_WRITE_PIPE * pREQ_RWPipe;
  760. USBD_INTERFACE_INFORMATION * pInterfaceInfo;
  761. USBD_PIPE_INFORMATION * pPipeInfo;
  762. ULONG ulPipeNum;
  763. PVOID pvBuffer;
  764. //USBDIAG_KdPrint(("USBDIAG.SYS: enter READ\n"));
  765. pREQ_RWPipe = (struct _REQ_READ_WRITE_PIPE *) (ioBuffer);
  766. ulPipeNum = pREQ_RWPipe->Contxt.PipeNum;
  767. ASSERT (deviceExtension != NULL);
  768. pInterfaceInfo = deviceExtension->Interface[0];
  769. ASSERT (pInterfaceInfo != NULL);
  770. ASSERT (pREQ_RWPipe != NULL);
  771. ASSERT (ulPipeNum <= (pInterfaceInfo->NumberOfPipes));
  772. pPipeInfo = &(deviceExtension->Interface[0]->Pipes[ulPipeNum]);
  773. ASSERT (pPipeInfo != NULL);
  774. ASSERT ((pPipeInfo->PipeHandle) != NULL);
  775. siz = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  776. // allocate urb
  777. urb = USBDIAG_ExAllocatePool(NonPagedPool, siz);
  778. // allocate data buffer
  779. pvBuffer = USBDIAG_ExAllocatePool (NonPagedPool, pREQ_RWPipe->ulLength);
  780. // set up urb
  781. UsbBuildInterruptOrBulkTransferRequest(urb, //ptr to urb
  782. (USHORT) siz, //siz of urb
  783. pPipeInfo->PipeHandle, //usbd pipe handle
  784. pvBuffer, //transferbuffer
  785. NULL, //mdl
  786. pREQ_RWPipe->ulLength, //bufferlength
  787. USBD_SHORT_TRANSFER_OK, //flags
  788. NULL); //link
  789. // NOTE: We don't request a TIMEOUT in this call to Ch9CallUSBD
  790. ntStatus = USBDIAG_Ch9CallUSBD(actualdeviceObject, urb, TRUE, NULL, NULL, FALSE);
  791. // The Information field tells IOM how much to copy back into the
  792. // usermode buffer in the BUFFERED method
  793. // In this case all we want the IOM to copy back is the REQ itself
  794. // so things like the status field get updated
  795. Irp->IoStatus.Information = sizeof(struct _REQ_READ_WRITE_PIPE);
  796. Irp->IoStatus.Status = ntStatus;
  797. pREQ_RWPipe->Hdr.Status = ntStatus;
  798. if (!NT_SUCCESS(ntStatus))
  799. {
  800. USBDIAG_KdPrint(("'Read pipe failed!\n ntStatus = 0x%x\n urbStatus = 0x%x\n",
  801. ntStatus,
  802. urb->UrbHeader.Status));
  803. }
  804. // The REQ coming from user mode gets its length field trampled on w/ the actual
  805. // length of this transfer, so user mode app should look there and not in
  806. // the nBytes field of the DeviceIoControl call.
  807. pREQ_RWPipe->ulLength = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  808. ulUrbStatus = urb->UrbHeader.Status; //capture the Urb status for later
  809. // Copy the data back to user mode buffer if successful transfer
  810. if (ulUrbStatus == USBD_STATUS_SUCCESS)
  811. {
  812. //USBDIAG_KdPrint(("USBDIAG.SYS: Successful Read; Copying %d bytes to UserMode Buf (%X)",
  813. //pREQ_RWPipe->ulLength,
  814. //pREQ_RWPipe->pvBuffer));
  815. if (pREQ_RWPipe->pvBuffer)
  816. {
  817. memcpy ( (pREQ_RWPipe->pvBuffer) , pvBuffer, (pREQ_RWPipe->ulLength) );
  818. } // if pvBuffer is non NULL
  819. }//if status is SUCCESS
  820. // free allocated urb
  821. USBDIAG_ExFreePool(urb);
  822. // free our non paged pool data buffer
  823. USBDIAG_ExFreePool (pvBuffer);
  824. //USBDIAG_KdPrint(("USBDIAG.SYS: exit READ\n"));
  825. break;
  826. }//REQ_FUNCTION_READ_FROM_PIPE
  827. break; //REQ_FUNCTION_READ_FROM_PIPE
  828. case REQ_FUNCTION_WRITE_TO_PIPE:
  829. {
  830. struct _REQ_READ_WRITE_PIPE * pREQ_RWPipe;
  831. USBD_INTERFACE_INFORMATION * pInterfaceInfo;
  832. USBD_PIPE_INFORMATION * pPipeInfo;
  833. ULONG ulPipeNum;
  834. PVOID pvBuffer;
  835. //USBDIAG_KdPrint(("USBDIAG.SYS: enter WRITE \n"));
  836. pREQ_RWPipe = (struct _REQ_READ_WRITE_PIPE *) (ioBuffer);
  837. ulPipeNum = pREQ_RWPipe->Contxt.PipeNum;
  838. ASSERT (deviceExtension != NULL);
  839. pInterfaceInfo = deviceExtension->Interface[0];
  840. ASSERT (pInterfaceInfo != NULL);
  841. ASSERT (pREQ_RWPipe != NULL);
  842. ASSERT (ulPipeNum <= (pInterfaceInfo->NumberOfPipes));
  843. pPipeInfo = &(deviceExtension->Interface[0]->Pipes[ulPipeNum]);
  844. ASSERT (pPipeInfo != NULL);
  845. ASSERT ((pPipeInfo->PipeHandle) != NULL);
  846. siz = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
  847. // allocate urb
  848. urb = USBDIAG_ExAllocatePool(NonPagedPool, siz);
  849. // allocate data buffer
  850. pvBuffer = USBDIAG_ExAllocatePool (NonPagedPool, pREQ_RWPipe->ulLength);
  851. // COPY the data to write out into the nonpaged pool buffer
  852. RtlCopyMemory(pvBuffer, pREQ_RWPipe->pvBuffer, pREQ_RWPipe->ulLength);
  853. // set up urb
  854. UsbBuildInterruptOrBulkTransferRequest(urb, //ptr to urb
  855. (USHORT) siz, //siz of urb
  856. pPipeInfo->PipeHandle, //usbd pipe handle
  857. pvBuffer, //transferbuffer
  858. NULL, //mdl
  859. pREQ_RWPipe->ulLength, //bufferlength
  860. USBD_SHORT_TRANSFER_OK, //flags
  861. NULL); //link
  862. // NOTE: We don't request a TIMEOUT in this call to Ch9CallUSBD
  863. ntStatus = USBDIAG_Ch9CallUSBD(actualdeviceObject, urb, TRUE, NULL, NULL, FALSE);
  864. // The Information field tells IOM how much to copy back into the
  865. // usermode buffer in the BUFFERED method
  866. // In this case all we want the IOM to copy back is the REQ itself
  867. // so things like the status field get updated
  868. Irp->IoStatus.Information = sizeof(struct _REQ_HEADER);
  869. Irp->IoStatus.Status = ntStatus;
  870. // The REQ coming from user mode gets its length field trampled on w/ the actual
  871. // length of this transfer, so user mode app should look there and not in
  872. // the nBytes field of the DeviceIoControl call.
  873. pREQ_RWPipe->ulLength = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
  874. ulUrbStatus = urb->UrbHeader.Status; //capture the Urb status for later
  875. // Copy the data back to user mode buffer if successful transfer
  876. if (ulUrbStatus == USBD_STATUS_SUCCESS)
  877. {
  878. //USBDIAG_KdPrint(("USBDIAG.SYS: Successful Write; %d bytes Transferred",
  879. //pREQ_RWPipe->ulLength));
  880. }//if status is SUCCESS
  881. // free allocated urb
  882. USBDIAG_ExFreePool(urb);
  883. // free our non paged pool data buffer
  884. USBDIAG_ExFreePool (pvBuffer);
  885. //USBDIAG_KdPrint(("USBDIAG.SYS: exit WRITE \n"));
  886. // The Information field tells IOM how much to copy back into the
  887. // usermode buffer in the BUFFERED method
  888. // In this case all we want the IOM to copy back is the REQ itself
  889. // so things like the status field get updated
  890. Irp->IoStatus.Information = sizeof(struct _REQ_READ_WRITE_PIPE);
  891. Irp->IoStatus.Status = ntStatus;
  892. }
  893. break; //REQ_FUNCTION_WRITE_TO_PIPE
  894. case REQ_FUNCTION_CANCEL_TRANSFERS:
  895. {
  896. // Input: a device on which any outstanding Irps should be cancelled
  897. // We get the Irp ptr from the device extension. For now, we
  898. // only support one outstanding Irp on an entire device, even
  899. // if that Irp is on one of the device's pipes. This is a limitation
  900. // that can be lifted if we keep a track of more Irps on the device.
  901. NTSTATUS ntStatus = USBDIAG_CancelAllIrps(deviceExtension);
  902. BOOLEAN status = (BOOLEAN)NT_SUCCESS(ntStatus);
  903. ASSERT (deviceExtension != NULL);
  904. if (deviceExtension != NULL)
  905. {
  906. Ch9FillInReqStatus (status, status, REQHeader);
  907. Irp->IoStatus.Information = sizeof(struct _REQ_HEADER);
  908. Irp->IoStatus.Status = ntStatus;
  909. }// if valid physdevice extension
  910. }//REQ_FUNCTION_CANCEL_TRANSFERS
  911. break;
  912. case REQ_FUNCTION_SET_DEVICE_POWER_STATE:
  913. {
  914. /*******
  915. Suspends/resumes device under test
  916. Input: Device Handle
  917. Output: Nothing yet
  918. ********/
  919. PDEVICE_OBJECT stackDeviceObject;
  920. POWER_STATE powerState;
  921. struct _REQ_GET_SET_DEVICE_POWER_STATE * pSetDevicePowerState = (struct _REQ_GET_SET_DEVICE_POWER_STATE *)ioBuffer;
  922. stackDeviceObject = deviceExtension->StackDeviceObject;
  923. // Set device to suspend
  924. powerState.DeviceState = pSetDevicePowerState->DevicePowerState;
  925. // cancel the pending irp if applicable
  926. if (powerState.DeviceState != PowerDeviceD0)
  927. {
  928. //USBDIAG_KdPrint(("Powering down - InterruptIrp = 0x%x\n", deviceExtension->InterruptIrp));
  929. if (deviceExtension->InterruptIrp)
  930. {
  931. if (IoCancelIrp(deviceExtension->InterruptIrp))
  932. {
  933. USBDIAG_KdPrint(("'Powering down, so all pending interrupt irp cancelled\n"));
  934. }
  935. else
  936. {
  937. USBDIAG_KdPrint(("'Powering down, pending interrupt irp cancelled FAILED\n"));
  938. }
  939. deviceExtension->InterruptIrp = NULL;
  940. }
  941. }
  942. ntStatus = USBDIAG_SetDevicePowerState(actualdeviceObject,
  943. powerState.DeviceState);
  944. if (NT_SUCCESS(ntStatus))
  945. {
  946. //USBDIAG_KdPrint(("'USBDIAG.SYS: Set device power state 0x%x passed\n", powerState.DeviceState));
  947. }
  948. else
  949. {
  950. USBDIAG_KdPrint(("'USBDIAG.SYS: Set device power state 0x%x FAILED (0x%x)\n", powerState.DeviceState, ntStatus));
  951. }
  952. } //REQ_FUNCTION_CHAP11_SUSPEND_HUT
  953. break;
  954. case REQ_FUNCTION_GET_DEVICE_STATE:
  955. {
  956. struct _REQ_GET_SET_DEVICE_POWER_STATE * pREQ_GetDevPowerState = (struct _REQ_GET_SET_DEVICE_POWER_STATE *)(ioBuffer);
  957. USBDIAG_KdPrint(("'USBDIAG.SYS: REQ_GET_DEV_POWER_STATE\n"));
  958. pREQ_GetDevPowerState->DevicePowerState = (ULONG)deviceExtension->CurrentDeviceState.DeviceState;
  959. ntStatus = STATUS_SUCCESS;
  960. Irp->IoStatus.Information = sizeof(struct _REQ_GET_SET_DEVICE_POWER_STATE);
  961. Irp->IoStatus.Status = ntStatus;
  962. }
  963. break;
  964. case REQ_FUNCTION_ISSUE_WAIT_WAKE:
  965. USBDIAG_KdPrint(("'USBDIAG.SYS: REQ_FUNCTION_ISSUE_WAIT_WAKE\n"));
  966. if (deviceExtension->WaitWakeIrp)
  967. {
  968. return STATUS_DEVICE_BUSY;
  969. }
  970. else
  971. {
  972. USBDIAG_KdPrint(("'Generating IRP_MN_WAIT_WAKE Power Irp\n"));
  973. // Generate and save the power irp
  974. ntStatus = USBDIAG_IssueWaitWake(actualdeviceObject);
  975. if (ntStatus == STATUS_PENDING)
  976. {
  977. Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS;
  978. Irp->IoStatus.Information = 0;
  979. }
  980. }
  981. break;
  982. case REQ_FUNCTION_WAIT_FOR_WAKEUP:
  983. {
  984. NTSTATUS ntStatus = USBDIAG_WaitForWakeup(deviceExtension);
  985. Irp->IoStatus.Status = ntStatus;
  986. Irp->IoStatus.Information = 0;
  987. }
  988. break;
  989. case REQ_FUNCTION_CANCEL_WAIT_WAKE:
  990. {
  991. ntStatus = STATUS_UNSUCCESSFUL;
  992. if (deviceExtension->WaitWakeIrp)
  993. {
  994. BOOLEAN bCancelSuccess = IoCancelIrp(deviceExtension->WaitWakeIrp);
  995. if (bCancelSuccess)
  996. {
  997. ntStatus = STATUS_SUCCESS;
  998. }
  999. }
  1000. Irp->IoStatus.Status = ntStatus;
  1001. Irp->IoStatus.Information = 0;
  1002. }
  1003. break;
  1004. case REQ_FUNCTION_CHAP11_CREATE_USBD_DEVICE:
  1005. /*******
  1006. Creates handle to device attatched to hub
  1007. Input:
  1008. Output: Device handle, and device descriptor
  1009. ********/
  1010. {
  1011. ntStatus = USBDIAG_CreateInitDownstreamDevice((PREQ_ENUMERATE_DOWNSTREAM_DEVICE)ioBuffer,
  1012. deviceExtension);
  1013. ASSERT(NT_SUCCESS(ntStatus));
  1014. Irp->IoStatus.Status = ntStatus;
  1015. Irp->IoStatus.Information = sizeof(struct _REQ_ENUMERATE_DOWNSTREAM_DEVICE);;
  1016. }
  1017. break;
  1018. case REQ_FUNCTION_CHAP11_INIT_USBD_DEVICE:
  1019. /*******
  1020. Initialize device attached to hub.
  1021. Input: Device Handle
  1022. Output: Nothing yet
  1023. ********/
  1024. if (gVersionInformation.USBDI_Version >= USBD_WIN98_SE_VERSION) // Win98 SE / Win2K & beyond
  1025. {
  1026. ntStatus = USBDIAG_SetCfgEnableRWu(deviceExtension, (PREQ_ENUMERATE_DOWNSTREAM_DEVICE)ioBuffer);
  1027. Irp->IoStatus.Status = ntStatus;
  1028. Irp->IoStatus.Information = sizeof(struct _REQ_ENUMERATE_DOWNSTREAM_DEVICE);
  1029. }
  1030. else
  1031. ntStatus = STATUS_NOT_IMPLEMENTED;
  1032. break;
  1033. case REQ_FUNCTION_CHAP11_DESTROY_USBD_DEVICE:
  1034. /*******
  1035. Destroys device handle to device attached to hub.
  1036. Input: Device Handle
  1037. Output: Nothing yet
  1038. ********/
  1039. if (gVersionInformation.USBDI_Version >= USBD_WIN98_SE_VERSION) // Win98 SE / Win2K & beyond
  1040. {
  1041. PREQ_ENUMERATE_DOWNSTREAM_DEVICE pEnumerate = (PREQ_ENUMERATE_DOWNSTREAM_DEVICE)ioBuffer;
  1042. UCHAR ucPortNumber = pEnumerate->ucPortNumber;
  1043. UCHAR flags = 0;
  1044. USBDIAG_KdPrint(("*************************************************\n"));
  1045. USBDIAG_KdPrint(("USBDIAG.SYS: REQ_FUNCTION_DESTROY_USBD_DEVICE\n"));
  1046. USBDIAG_KdPrint(("Port: %d\n", ucPortNumber));
  1047. if (deviceExtension->DeviceData[ucPortNumber] != NULL)
  1048. {
  1049. ntStatus = USBD_RemoveDevice(deviceExtension->DeviceData[ucPortNumber],
  1050. deviceExtension->RootHubPdo,
  1051. flags);
  1052. }
  1053. else
  1054. {
  1055. ntStatus = STATUS_SUCCESS;
  1056. }
  1057. if (NT_SUCCESS(ntStatus))
  1058. {
  1059. deviceExtension->DeviceData[ucPortNumber] = NULL;
  1060. Irp->IoStatus.Status = ntStatus;
  1061. Irp->IoStatus.Information = sizeof(struct _REQ_ENUMERATE_DOWNSTREAM_DEVICE);;
  1062. }
  1063. }
  1064. else
  1065. ntStatus = STATUS_NOT_IMPLEMENTED;
  1066. break;
  1067. case REQ_FUNCTION_CHAP11_SEND_PACKET_DOWNSTREAM:
  1068. {
  1069. PREQ_SEND_PACKET_DOWNSTREAM pReqSendPacket = (PREQ_SEND_PACKET_DOWNSTREAM)ioBuffer;
  1070. UCHAR ucPortNumber = (UCHAR)pReqSendPacket->usPortNumber;
  1071. PUSBD_DEVICE_DATA DeviceData = deviceExtension->DeviceData[ucPortNumber];
  1072. //PDEVICE_OBJECT StackDeviceObject =deviceExtension->StackDeviceObject;
  1073. USBDIAG_KdPrint(("*************************************************\n"));
  1074. USBDIAG_KdPrint(("USBDIAG.SYS: REQ_FUNCTION_CHAP11_SEND_PACKET_DOWNSTREAM\n"));
  1075. //USBDIAG_KdPrint(("DeviceData: 0x%x\n", DeviceData));
  1076. //USBDIAG_KdPrint(("DeviceObject: 0x%x\n", StackDeviceObject));
  1077. USBDIAG_KdPrint(("PortNumber: %d\n", ucPortNumber));
  1078. //USBDIAG_KdPrint(("DeviceData: 0x%x\n", deviceExtension->DeviceData[ucPortNumber]));
  1079. //USBDIAG_KdPrint(("bLowSpeed: 0x%x\n", pReqSendPacket->bLowSpeed));
  1080. //USBDIAG_KdPrint(("pucBuffer: 0x%x\n", pReqSendPacket->pucBuffer));
  1081. USBDIAG_KdPrint(("SetupPacket:\n"));
  1082. USBDIAG_KdPrint((" wRequest: 0x%04x\n", pReqSendPacket->SetupPacket.wRequest));
  1083. USBDIAG_KdPrint((" wValue: 0x%04x\n", pReqSendPacket->SetupPacket.wValue));
  1084. USBDIAG_KdPrint((" wIndex: 0x%04x\n", pReqSendPacket->SetupPacket.wIndex));
  1085. USBDIAG_KdPrint((" wLength: 0x%04x\n", pReqSendPacket->SetupPacket.wLength));
  1086. if (deviceExtension->DeviceData[ucPortNumber] != NULL)
  1087. {
  1088. ntStatus = USBDIAG_Chap11SendPacketDownstream(DeviceData,
  1089. deviceExtension->RootHubPdo,
  1090. pReqSendPacket);
  1091. if (NT_SUCCESS(ntStatus))
  1092. {
  1093. Irp->IoStatus.Status = ntStatus;
  1094. Irp->IoStatus.Information = sizeof(struct _REQ_SEND_PACKET_DOWNSTREAM);
  1095. }
  1096. }
  1097. else
  1098. {
  1099. ntStatus = STATUS_INVALID_PARAMETER;
  1100. }
  1101. ASSERT(NT_SUCCESS(ntStatus));
  1102. break;
  1103. }
  1104. case REQ_FUNCTION_CHAP11_GET_DOWNSTREAM_DESCRIPTOR:
  1105. {
  1106. PREQ_GET_DOWNSTREAM_DESCRIPTOR pGetDownstreamDescriptor = (PREQ_GET_DOWNSTREAM_DESCRIPTOR)ioBuffer;
  1107. USHORT usPortNumber = pGetDownstreamDescriptor->usPortNumber;
  1108. PUSBD_DEVICE_DATA DeviceData = deviceExtension->DeviceData[usPortNumber];
  1109. USHORT usDescType = pGetDownstreamDescriptor->DescriptorType;
  1110. Irp->IoStatus.Information = sizeof(struct _REQ_GET_DOWNSTREAM_DESCRIPTOR);
  1111. USBDIAG_KdPrint(("'REQ_FUNCTION_CHAP11_GET_DOWNSTREAM_DESCRIPTOR:\n"));
  1112. USBDIAG_KdPrint(("'PortNumber %d\n", usPortNumber));
  1113. USBDIAG_KdPrint(("'DeviceData 0x%x\n", DeviceData));
  1114. USBDIAG_KdPrint(("'usDescType %d\n", usDescType));
  1115. USBDIAG_KdPrint(("'pGetDownstreamDescriptor->TransferBufferLength %d\n", pGetDownstreamDescriptor->TransferBufferLength));
  1116. USBDIAG_KdPrint(("'sizeof(USB_DEVICE_DESCRIPTOR) %d\n", sizeof(USB_DEVICE_DESCRIPTOR)));
  1117. if (!DeviceData) goto BAD_REQ_CHAP11_GET_DOWNSTREAM_DESCRIPTOR;
  1118. switch (usDescType)
  1119. {
  1120. case USB_DEVICE_DESCRIPTOR_TYPE:
  1121. if (pGetDownstreamDescriptor->TransferBufferLength < sizeof(USB_DEVICE_DESCRIPTOR))
  1122. goto BAD_REQ_CHAP11_GET_DOWNSTREAM_DESCRIPTOR;
  1123. RtlCopyMemory(pGetDownstreamDescriptor->TransferBuffer,
  1124. &DeviceData->DeviceDescriptor,
  1125. sizeof(USB_DEVICE_DESCRIPTOR));
  1126. ntStatus = STATUS_SUCCESS;
  1127. break;
  1128. case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  1129. if (pGetDownstreamDescriptor->TransferBufferLength < sizeof(USB_CONFIGURATION_DESCRIPTOR) ||
  1130. deviceExtension->DownstreamConfigDescriptor[usPortNumber] == NULL)
  1131. goto BAD_REQ_CHAP11_GET_DOWNSTREAM_DESCRIPTOR;
  1132. RtlCopyMemory(pGetDownstreamDescriptor->TransferBuffer,
  1133. deviceExtension->DownstreamConfigDescriptor[usPortNumber],
  1134. sizeof(USB_CONFIGURATION_DESCRIPTOR));
  1135. ntStatus = STATUS_SUCCESS;
  1136. break;
  1137. default: // currently all others are unsupported
  1138. goto BAD_REQ_CHAP11_GET_DOWNSTREAM_DESCRIPTOR;
  1139. }
  1140. break;
  1141. BAD_REQ_CHAP11_GET_DOWNSTREAM_DESCRIPTOR:
  1142. ntStatus = STATUS_INVALID_PARAMETER;
  1143. break;
  1144. }
  1145. break;
  1146. case REQ_FUNCTION_DISABLE_ENABLING_REMOTE_WAKEUP:
  1147. case REQ_FUNCTION_ENABLE_ENABLING_REMOTE_WAKEUP:
  1148. {
  1149. BOOLEAN bDisable = (BOOLEAN)(REQHeader->Function == REQ_FUNCTION_DISABLE_ENABLING_REMOTE_WAKEUP ? TRUE : FALSE);
  1150. ntStatus = USBDIAG_DisableRemoteWakeupEnable(actualdeviceObject, bDisable);
  1151. }
  1152. break;
  1153. default:
  1154. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  1155. }
  1156. Ch9FillInReqStatus (ntStatus, ulUrbStatus, REQHeader);
  1157. if (bCompleteIrp)
  1158. {
  1159. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1160. }
  1161. //USBDIAG_KdPrint(("USBDIAG.SYS: Chap9Ctrl returning w/ ntStatus: %#X REQStatus: %#X\n",
  1162. //ntStatus,
  1163. //REQHeader->Status));
  1164. return ntStatus;
  1165. } //USBDIAG_Chap9Control
  1166. NTSTATUS
  1167. USBDIAG_Ch9CallUSBD(
  1168. IN PDEVICE_OBJECT DeviceObject,
  1169. IN PURB Urb,
  1170. IN BOOLEAN fBlock, // currently ignored
  1171. PIO_COMPLETION_ROUTINE CompletionRoutine, // just passed to generic completion routine
  1172. PVOID pvContext, // just passed to generic completion routine
  1173. BOOLEAN fWantTimeOut // currently ignored
  1174. )
  1175. /**************************************************************************
  1176. Routine Description:
  1177. Passes a URB to the USBD class driver
  1178. NOTE: Creates an IRP to do this. Doesn't use the IRP that is passed down from user
  1179. mode app (it's not passed to this routine at all).
  1180. Arguments:
  1181. DeviceObject - pointer to the device object for this instance of a UTB
  1182. Urb - pointer to Urb request block
  1183. fBlock - bool indicating if this fn should wait for IRP to return from USBD
  1184. CompletionRoutine - fn to set as the completionroutine for this transfer ONLY IF
  1185. the fBlock is set to FALSE, indicating that the caller wants
  1186. to handle completion on their own and this fn should not
  1187. block
  1188. pvContext - Context to be set in setting up the completion routine for the
  1189. Irp created in this function. This is passed in by caller and is
  1190. just a pass-thru to the IoSetCompletionRoutine call.
  1191. fWantTimeOut - If caller wants this function to use a deadman timeout and cancel
  1192. the Irp after the timeout expires. TRUE means this function will
  1193. use the timeout mechanism, and FALSE means this function will block
  1194. indefinitely and wait for the Irp/Urb to return from the USB stack.
  1195. Return Value:
  1196. STATUS_SUCCESS if successful,
  1197. STATUS_UNSUCCESSFUL otherwise
  1198. **************************************************************************/
  1199. {
  1200. NTSTATUS ntStatus;
  1201. PDEVICE_EXTENSION deviceExtension;
  1202. PIRP irp;
  1203. IO_STATUS_BLOCK ioStatus;
  1204. PIO_STACK_LOCATION nextStack;
  1205. PCOMPLETION_CONTEXT pGenericContext;
  1206. USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_Ch9CallUSBD\n"));
  1207. {
  1208. KIRQL irql;
  1209. irql = KeGetCurrentIrql();
  1210. ASSERT(irql <= PASSIVE_LEVEL);
  1211. }
  1212. pGenericContext = ExAllocatePool(NonPagedPool, sizeof(COMPLETION_CONTEXT));
  1213. if (!pGenericContext)
  1214. return STATUS_INSUFFICIENT_RESOURCES;
  1215. deviceExtension = DeviceObject->DeviceExtension;
  1216. ASSERT (deviceExtension != NULL);
  1217. ASSERT ((deviceExtension->StackDeviceObject) != NULL);
  1218. if ((deviceExtension) && (deviceExtension->StackDeviceObject))
  1219. {
  1220. // issue a synchronous request to read the USB Device Ctrl pipe
  1221. KeInitializeEvent(&pGenericContext->DoneEvent, NotificationEvent, FALSE);
  1222. // Create the IRP that we'll use to submit this URB to the USB stack
  1223. irp = IoBuildDeviceIoControlRequest(
  1224. IOCTL_INTERNAL_USB_SUBMIT_URB,
  1225. deviceExtension->StackDeviceObject,
  1226. NULL,
  1227. 0,
  1228. NULL,
  1229. 0,
  1230. TRUE, /* INTERNAL */
  1231. //&event,
  1232. &pGenericContext->DoneEvent,
  1233. &ioStatus); //the status codes in NT IRPs go here
  1234. pGenericContext->DeviceObject = DeviceObject;
  1235. pGenericContext->Irp = irp;
  1236. pGenericContext->CompletionRoutine = CompletionRoutine;
  1237. pGenericContext->Context = pvContext;
  1238. //NOTE: The status returned by USBD in the URB is more USB transfer-specific (e.g.,
  1239. // it indicates things like USB stall conditions, etc.). The USBD status
  1240. // is contained in the URB's status field. However, USBD maps those URB error
  1241. // codes to more generic NT_STATUS_XXX error codes when the IRP returns. To
  1242. // get a more detailed and USB-specific reading of the error code, look at
  1243. // the URB's status field.
  1244. // Call the class driver to perform the operation. If the returned status
  1245. // is PENDING, wait for the request to complete.
  1246. nextStack = IoGetNextIrpStackLocation(irp);
  1247. ASSERT(nextStack != NULL);
  1248. // save a pointer to the Irp for our cancel routine
  1249. ntStatus = USBDIAG_SaveIrp(deviceExtension, irp);
  1250. USBDIAG_KdPrint (("USBDIAG.SYS: Urb header function 0x%x (0x%x)\n",
  1251. Urb->UrbHeader.Function,
  1252. URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER));
  1253. if (Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER)
  1254. {
  1255. USBDIAG_KdPrint(("Saving interrupt irp\n"));
  1256. ASSERT(deviceExtension->InterruptIrp == NULL);
  1257. deviceExtension->InterruptIrp = irp;
  1258. }
  1259. if (!NT_SUCCESS(ntStatus))
  1260. {
  1261. ExFreePool(pGenericContext);
  1262. return ntStatus;
  1263. }
  1264. // pass the URB to the USBD 'class driver'
  1265. nextStack->Parameters.Others.Argument1 = Urb;
  1266. // set the generic routine
  1267. IoSetCompletionRoutine(irp,
  1268. USBDIAG_IoGenericCompletionRoutine,
  1269. pGenericContext,
  1270. TRUE, //InvokeOnSuccess
  1271. TRUE, //InvokeOnError,
  1272. TRUE); //InvokeOnCancel
  1273. USBDIAG_KdPrint (("USBDIAG.SYS: calling USBD\n"));
  1274. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject, irp);
  1275. USBDIAG_KdPrint (("USBDIAG.SYS: return from IoCallDriver USBD in USBDIAG_Ch9CallUSBD %x\n", ntStatus));
  1276. if (ntStatus == STATUS_PENDING)
  1277. {
  1278. USBDIAG_KdPrint(("USBDIAG.SYS: Waiting for done signal\n"));
  1279. KeWaitForSingleObject(&pGenericContext->DoneEvent,
  1280. Suspended,
  1281. KernelMode,
  1282. FALSE,
  1283. NULL);
  1284. ntStatus = Urb->UrbHeader.Status;
  1285. }
  1286. USBDIAG_KdPrint (("USBDIAG.SYS: Urb status = %x Irp status %x\n",
  1287. Urb->UrbHeader.Status,
  1288. irp->IoStatus.Status));
  1289. ioStatus.Status = ntStatus;
  1290. //ioStatus.Information = 0;
  1291. //USBD maps the error code for us
  1292. USBDIAG_KdPrint(("USBDIAG.SYS: URB TransferBufferLength OUT is: %d\n",Urb->UrbControlDescriptorRequest.TransferBufferLength));
  1293. }//if valid deviceExtension and StackDevObjects
  1294. else
  1295. {
  1296. // Invalid extension or stackdevobj received
  1297. ntStatus = STATUS_INVALID_PARAMETER;
  1298. USBDIAG_KdPrint(("USBDIAG.SYS: Invalid deviceExtension or StackDeviceObject\n"));
  1299. } //else invalid devExt or stackdevobj
  1300. USBDIAG_KdPrint(("USBDIAG.SYS: exiting USBDIAG_Ch9CallUSBD w/ URB/ntStatus: %x\n", ntStatus));
  1301. ExFreePool(pGenericContext);
  1302. return ntStatus;
  1303. }//USBDIAG_Ch9CallUSBD
  1304. NTSTATUS
  1305. USBDIAG_SendPacket(
  1306. IN PDEVICE_OBJECT DeviceObject,
  1307. IN CHAR SetUpPacket[],
  1308. PVOID TxBuffer,
  1309. ULONG * TxBufferLen, //see comments below!
  1310. ULONG * pulUrbStatus
  1311. )
  1312. /*++
  1313. Routine Description:
  1314. Arguments:
  1315. DeviceObject - pointer to the device object for this instance of the TESTDRV
  1316. devcice.
  1317. SetupPacket - formatted by caller to contain exactly the 8 bytes setup pkt
  1318. TxBuffer - if a data stage occurs, this is where data originates or ends up
  1319. TxBufferLen - incoming it's a ptr to the len of the TxBuffer
  1320. - outgoing we shove the actual len of the data in the buffer for INPUT bus transfers
  1321. pulUrbStatus - Urb status is put here for more visibility into what happened on USB
  1322. Return Value:
  1323. NT status code
  1324. --*/
  1325. {
  1326. PDEVICE_EXTENSION deviceExtension;
  1327. NTSTATUS ntStatus;
  1328. PURB urb;
  1329. // PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  1330. int i = 0 ;
  1331. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_SendPacket\n"));
  1332. deviceExtension = DeviceObject->DeviceExtension;
  1333. urb = USBDIAG_ExAllocatePool(NonPagedPool,
  1334. sizeof(struct _URB_CONTROL_TRANSFER));
  1335. // need to zero out this buffer, kludge to fix a language ID problem
  1336. RtlZeroMemory(urb, sizeof(struct _URB_CONTROL_TRANSFER));
  1337. if (urb)
  1338. {
  1339. (urb)->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
  1340. (urb)->UrbHeader.Length = sizeof(struct _URB_CONTROL_TRANSFER);
  1341. (urb)->UrbControlTransfer.PipeHandle = 0; // this will cause us to use the default pipe
  1342. //USBDIAG_KdPrint(("USBDIAG.SYS: TxBufferLen=%d | TxBuffer = %x\n",*TxBufferLen, TxBuffer));
  1343. (urb)->UrbControlTransfer.TransferBufferLength = *TxBufferLen ;
  1344. (urb)->UrbControlTransfer.TransferBufferMDL = NULL ;
  1345. (urb)->UrbControlTransfer.TransferBuffer = TxBuffer ;
  1346. (urb)->UrbControlTransfer.UrbLink = NULL;
  1347. (urb)->UrbControlTransfer.TransferFlags = ( (SetUpPacket[0] & bmReqD2H) ? (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK) : 0 ) ;
  1348. //USBDIAG_KdPrint(("USBDIAG.SYS: Tx direction %x\n", (urb)->UrbControlTransfer.TransferFlags)) ;
  1349. (urb)->UrbControlTransfer.UrbLink = NULL;
  1350. for ( i = 0 ; i < SETUP_PACKET_LEN ; i ++ )
  1351. {
  1352. (urb)->UrbControlTransfer.SetupPacket[i] = SetUpPacket[i] ; // 0x01;
  1353. }
  1354. //don't need to do this. stack will yank it out of the PDO and use
  1355. //the right usbdhandle for this txfer
  1356. // urb->UrbHeader.UsbdDeviceHandle = UsbdHandle ;
  1357. ntStatus = USBDIAG_Ch9CallUSBD(DeviceObject, urb, TRUE, NULL, NULL, TRUE);
  1358. // Set the caller's urb status
  1359. if (pulUrbStatus)
  1360. *pulUrbStatus = urb->UrbHeader.Status;
  1361. //USBDIAG_KdPrint(("USBDIAG.SYS: SendPacket: UrbStatus = 0x%x\n",urb->UrbHeader.Status));
  1362. if (NT_SUCCESS(ntStatus) && (TxBufferLen != NULL))
  1363. {
  1364. // Tell caller how much data was transferred (mostly valid on INs)
  1365. // Don't know how interesting this is on OUTs but it's set anyway
  1366. //
  1367. *TxBufferLen = urb->UrbControlDescriptorRequest.TransferBufferLength;
  1368. //USBDIAG_KdPrint(("USBDIAG.SYS: USBDIAG_SendPacket-TransferBufferLength: %d\n",
  1369. //*TxBufferLen));
  1370. }//if
  1371. USBDIAG_ExFreePool(urb);
  1372. //USBDIAG_KdPrint(("USBDIAG.SYS: Inside the if before the else STATUS_INSUFFICIENT_RESOURCES\n"));
  1373. }
  1374. else
  1375. {
  1376. //USBDIAG_KdPrint(("USBDIAG.SYS: Inside the else STATUS_INSUFFICIENT_RESOURCES"));
  1377. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1378. }
  1379. //USBDIAG_KdPrint(("USBDIAG.SYS: exit USBDIAG_SendPacket (%x)\n",ntStatus));
  1380. return ntStatus;
  1381. } /* End of USBDIAG_SendPacket() */
  1382. PBYTE
  1383. pAllocFromBuffer(
  1384. PBYTE pBuffer,
  1385. ULONG iSize,
  1386. PULONG piOffset,
  1387. PULONG piTotalUsed,
  1388. ULONG iRequested
  1389. )
  1390. /*
  1391. This function is used to sub-allocate memory from the buffer managed
  1392. by the ioctl call. This allows complex structures to be build in a
  1393. single contigious buffer, which can be returned to ring 3. (The
  1394. routine is necessary because DeviceIoControl only provides for the
  1395. movement of one buffer from ring 3 to ring 0 and back
  1396. */
  1397. {
  1398. PVOID pReturn;
  1399. //
  1400. // CROBINS: This was buggy...Changed *piOffset+iRequested to
  1401. // *piTtoalUsed+iRequested
  1402. if (*piTotalUsed + iRequested > iSize)
  1403. {
  1404. pReturn=NULL;
  1405. }
  1406. else
  1407. {
  1408. pReturn = pBuffer + *piTotalUsed;
  1409. *piOffset = *piTotalUsed;
  1410. (*piTotalUsed)+=iRequested;
  1411. }
  1412. return pReturn;
  1413. }
  1414. NTSTATUS
  1415. USBDIAG_HIDP_GetCollection(
  1416. IN PDEVICE_OBJECT DeviceObject,
  1417. IN PIRP Irp
  1418. )
  1419. /*++
  1420. History:
  1421. This routine was added for support of the HID Test application's parsing
  1422. capabilities.
  1423. Kosar Jaff 8-14-96 (Intel Corp.)
  1424. Routine Description:
  1425. Calls the Hid Parser driver with a raw report descriptor
  1426. (see HidP_GetCollectionDescription in hidpddi.h for behavior)
  1427. This function assumes that the caller will use an IOCTL with the
  1428. METHOD_BUFFERED specified. The function will place the result of
  1429. the parse in the SystemBuffer and expect IOS to copy the result to the
  1430. user's OutputBuffer specified in the DeviceIoControl call made in UserMode.
  1431. The incoming buffer will be used as it appears in the SystemBuffer (locked by
  1432. IOS on the way down) even though since this function is in the calling thread's
  1433. context, we could have used UserBuffer directly.
  1434. Note: This function will put the
  1435. Arguments:
  1436. DeviceObject - ptr to this driver's "Device" object
  1437. Irp - incoming IRP from user mode ioctl
  1438. Return Value:
  1439. NT status code
  1440. --*/
  1441. {
  1442. PIO_STACK_LOCATION irpStack;
  1443. HIDP_DEVICE_DESC rCollectionsAndIDs;
  1444. PVOID ioBuffer;
  1445. ULONG inputBufferLength;
  1446. ULONG outputBufferLength;
  1447. NTSTATUS ntStatus;
  1448. PHIDP_COLLECTION_DESC pHidPCollDesc = NULL;
  1449. //PHIDP_COLLECTION_DESC pTempCollDesc = NULL;
  1450. PCHAR pCollBlock;
  1451. ULONG ulBytInBuff;
  1452. ULONG nCollectionDescElem = 0;
  1453. ULONG i;
  1454. //ULONG ulTotBytesCopied =0;
  1455. BOOL bFailed = FALSE;
  1456. ULONG iOffset=0;
  1457. ULONG iTotalUsed=0;
  1458. PBYTE pSubBuffer;
  1459. PHIDP_DEVICE_DESC pDeviceDesc;
  1460. PHIDP_COLLECTION_DESC pCollectionDesc;
  1461. // Get a pointer to the current location in the Irp. This is where
  1462. // the function codes and parameters are located.
  1463. irpStack = IoGetCurrentIrpStackLocation (Irp);
  1464. //USBDIAG_KdPrint(("USBDIAG.SYS: irpStk->Prm.DvIoC.InptLn: %x | OutptLen: %x | UsrBuff: %x\n",
  1465. //irpStack->Parameters.DeviceIoControl.InputBufferLength,
  1466. //irpStack->Parameters.DeviceIoControl.OutputBufferLength,
  1467. //Irp->UserBuffer));
  1468. // Get the pointer to the input/output buffer and it's length
  1469. // the SystemBuffer contains the raw descriptor that is to be parsed
  1470. ioBuffer = Irp->AssociatedIrp.SystemBuffer;
  1471. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  1472. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  1473. //USBDIAG_KdPrint(("USBDIAG.SYS: RepDesc (ioBuffer): %X | RepDesc Len: %d\n",
  1474. //ioBuffer,
  1475. //inputBufferLength));
  1476. //call the parser function in HIDPARSE library
  1477. /* ntStatus =
  1478. HidP_GetCollectionDescription (ioBuffer,
  1479. inputBufferLength,
  1480. NonPagedPool,
  1481. &pHidPCollDesc,
  1482. &nCollectionDescElem);
  1483. This is being changed to match a change to hidparse. JobyL
  1484. */
  1485. rCollectionsAndIDs.CollectionDesc=NULL;
  1486. rCollectionsAndIDs.CollectionDescLength=0;
  1487. //USBDIAG_KdPrint(("USBDIAG.SYS: Before the call to HidP_GetCollectionDescription\n"));
  1488. ntStatus=HidP_GetCollectionDescription (ioBuffer,
  1489. inputBufferLength,
  1490. NonPagedPool,
  1491. &rCollectionsAndIDs);
  1492. //USBDIAG_KdPrint(("USBDIAG.SYS: After the call to HidP_GetCollectionDescription\n"));
  1493. pHidPCollDesc=rCollectionsAndIDs.CollectionDesc;
  1494. nCollectionDescElem=rCollectionsAndIDs.CollectionDescLength;
  1495. //USBDIAG_KdPrint(("USBDIAG.SYS: HidCollDesc: %X | NbrCollElem: %d\n",
  1496. //pHidPCollDesc,
  1497. //nCollectionDescElem));
  1498. if ( (nCollectionDescElem) && NT_SUCCESS(ntStatus) ) {
  1499. /*
  1500. // We put the collection descriptor into the "systembuffer" so that
  1501. // IOS can copy from there to the user buffer when we complete the IRP.
  1502. // Note the collection descriptors go in the buffer first, and then if
  1503. // there is room left, the PreParsedData is appended to the end.
  1504. //
  1505. // Since the pointers in the structures passed back from HIDPARSE are all
  1506. // Ke-Mode pointers, they won't be valid in User Mode, so we convert all
  1507. // those to relative pointers (offsets) and then let User Mode code re-convert
  1508. // them back to pointers w.r.t. the User Mode base pointers.
  1509. //
  1510. // VERY IMPORTANT: Note that the pointer to the Pre Parsed Data structure that
  1511. // gets patched by this routine is an OFFSET based on the base
  1512. // of the collection descriptor blocks. So, this means that the
  1513. // pre parsed data blocks are referenced based on the first
  1514. // collection description element, which also happens to be the
  1515. // base of the entire output buffer.
  1516. //
  1517. // User mode code that is trying to reconstruct this buffer must
  1518. // be aware of this organization.
  1519. //
  1520. */
  1521. ASSERT (pHidPCollDesc != NULL);
  1522. ulBytInBuff = outputBufferLength;
  1523. // Early out--if not enough room for the fixed size blocks, don't continue
  1524. if (ulBytInBuff < (nCollectionDescElem * sizeof(HIDP_COLLECTION_DESC))) {
  1525. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1526. //USBDIAG_KdPrint(("USBDIAG.SYS: ERROR: Not enuf mem in outbuff to put collection descriptions!\n"));
  1527. TRAP();
  1528. goto DoneWithParse;
  1529. }
  1530. //set the base ptr of collection descriptions and PPD blocks
  1531. pCollBlock = (PCHAR)ioBuffer;
  1532. //USBDIAG_KdPrint(("USBDIAG.SYS: pCollBlock (base): %X NbrCollDescElem: %d\n",
  1533. //pCollBlock, nCollectionDescElem));
  1534. pSubBuffer = pAllocFromBuffer((PBYTE) pCollBlock,
  1535. outputBufferLength,
  1536. &iOffset,
  1537. &iTotalUsed,
  1538. sizeof(HIDP_DEVICE_DESC));
  1539. if (NULL == pSubBuffer)
  1540. {
  1541. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1542. TRAP();
  1543. goto DoneWithParse;
  1544. }
  1545. memcpy(pSubBuffer, &rCollectionsAndIDs, sizeof(HIDP_DEVICE_DESC));
  1546. pDeviceDesc = (PHIDP_DEVICE_DESC) pSubBuffer;
  1547. pSubBuffer = pAllocFromBuffer((PBYTE) pCollBlock,
  1548. outputBufferLength,
  1549. &iOffset,
  1550. &iTotalUsed,
  1551. sizeof(HIDP_REPORT_IDS)*(pDeviceDesc->ReportIDsLength));
  1552. if (NULL == pSubBuffer)
  1553. {
  1554. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1555. TRAP();
  1556. goto DoneWithParse;
  1557. }
  1558. memcpy(pSubBuffer,
  1559. pDeviceDesc->ReportIDs,
  1560. sizeof(HIDP_REPORT_IDS)*(pDeviceDesc->ReportIDsLength));
  1561. //
  1562. // patch pointer to make it relative
  1563. //
  1564. pDeviceDesc->ReportIDs = (PHIDP_REPORT_IDS) UlongToPtr(iOffset);
  1565. pSubBuffer = pAllocFromBuffer((PBYTE) pCollBlock,
  1566. outputBufferLength,
  1567. &iOffset,
  1568. &iTotalUsed,
  1569. sizeof(HIDP_COLLECTION_DESC)*(pDeviceDesc->CollectionDescLength));
  1570. if (NULL == pSubBuffer)
  1571. {
  1572. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1573. TRAP();
  1574. goto DoneWithParse;
  1575. }
  1576. memcpy(pSubBuffer,
  1577. pDeviceDesc->CollectionDesc,
  1578. sizeof(HIDP_COLLECTION_DESC)*(pDeviceDesc->CollectionDescLength));
  1579. //
  1580. // patch pointer to make it relative
  1581. //
  1582. pDeviceDesc->CollectionDesc = (PHIDP_COLLECTION_DESC) ULongToPtr(iOffset);
  1583. pCollectionDesc = (PHIDP_COLLECTION_DESC) pSubBuffer;
  1584. for (i=0; i < pDeviceDesc->CollectionDescLength; i++)
  1585. {
  1586. pSubBuffer = pAllocFromBuffer((PBYTE) pCollBlock,
  1587. outputBufferLength,
  1588. &iOffset,
  1589. &iTotalUsed,
  1590. pCollectionDesc->PreparsedDataLength);
  1591. if (NULL == pSubBuffer)
  1592. {
  1593. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1594. TRAP();
  1595. goto DoneWithParse;
  1596. }
  1597. memcpy(pSubBuffer,
  1598. pCollectionDesc->PreparsedData,
  1599. pCollectionDesc->PreparsedDataLength);
  1600. //
  1601. // patch pointer to make it relative
  1602. //
  1603. pCollectionDesc->PreparsedData = (PHIDP_PREPARSED_DATA) ULongToPtr(iOffset);
  1604. pCollectionDesc++;
  1605. }
  1606. DoneWithParse:
  1607. /*
  1608. // Setting the Irp->IoStatus.Information field tells the IOS how many bytes to copy
  1609. // back into the user buffer and hopefully will set the value in
  1610. // DeviceIoControl's "lpBytesReturned" field.
  1611. */
  1612. //
  1613. // free up collection stuff that parser returned
  1614. //
  1615. HidP_FreeCollectionDescription(&rCollectionsAndIDs);
  1616. Irp->IoStatus.Information = iTotalUsed;
  1617. //USBDIAG_KdPrint(("USBDIAG.SYS: TotalBytesCopied into systembuffer%d\n", iTotalUsed));
  1618. } else {
  1619. // call to parser failed
  1620. // //USBDIAG_KdPrint(("USBDIAG.SYS: HidP_GetCollectionDescription failed w/ ntStatus: %X\n", ntStatus));
  1621. memcpy(ioBuffer,&rCollectionsAndIDs,sizeof(HIDP_DEVICE_DESC));
  1622. // Irp->IoStatus.Information = sizeof(HIDP_DEVICE_DESC); //Copy just the DeviceDesc struct so that ring3 gets the debug struct
  1623. Irp->IoStatus.Information=sizeof(HIDP_DEVICE_DESC);
  1624. bFailed=TRUE;
  1625. }//if
  1626. // We always complete w/ success since the real status is in the REQ Header status field
  1627. Irp->IoStatus.Status = ntStatus = STATUS_SUCCESS;
  1628. // Complete the IRP here so we can free the buffer created by HIDPARSE when we called it
  1629. // after the IOS copies stuff back to user space, etc.
  1630. return ntStatus;
  1631. }//USBDIAG_HIDP_GetCollection
  1632. VOID
  1633. USBDIAG_SyncTimeoutDPC(
  1634. IN PKDPC Dpc,
  1635. IN PVOID DeferredContext,
  1636. IN PVOID SystemArgument1,
  1637. IN PVOID SystemArgument2
  1638. )
  1639. /*++
  1640. Routine Description:
  1641. This routine runs at DISPATCH_LEVEL IRQL.
  1642. Arguments:
  1643. Dpc - Pointer to the DPC object.
  1644. DeferredContext - passed in to IOS by caller as context (we use it as pIrp)
  1645. SystemArgument1 - not used.
  1646. SystemArgument2 - not used.
  1647. Return Value:
  1648. None.
  1649. --*/
  1650. {
  1651. BOOLEAN status;
  1652. PIRP irp = DeferredContext;
  1653. // TRAP();
  1654. // The cancel Irp call below will return immediately, but that doesn't mean things are all
  1655. // cleaned up in the USB stack. The only way to be assured of that is when the
  1656. // WaitForSingleObject that blocked in the first place returns (due to the USB stack
  1657. // completing the Irp, either due to normal completion or due to this cancel Irp call.
  1658. status = IoCancelIrp(irp);
  1659. //BUGBUG (kosar) We don't do anything if the cancel fails, and we probably should.
  1660. // (like maybe reschedule or something)
  1661. return;
  1662. }
  1663. NTSTATUS
  1664. USBDIAG_Configure_Device (
  1665. IN PDEVICE_OBJECT DeviceObject,
  1666. IN PIRP Irp)
  1667. {
  1668. PDEVICE_EXTENSION deviceExtension;
  1669. NTSTATUS ntStatus;
  1670. PURB urb = NULL;
  1671. ULONG siz;
  1672. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  1673. struct _REQ_HEADER * REQHeader = NULL;
  1674. struct _REQ_SET_DEVICE_CONFIG * REQSetDeviceConfig = NULL;
  1675. PIO_STACK_LOCATION irpStack = NULL;
  1676. PVOID ioBuffer;
  1677. ULONG inputBufferLength;
  1678. ULONG outputBufferLength;
  1679. PDEVICE_LIST_ENTRY devListEntry;
  1680. PDEVICE_OBJECT actualdeviceObject;
  1681. ULONG ulUrbStatus;
  1682. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_ConfigureDevice\n"));
  1683. // Get a pointer to the current location in the Irp. This is where
  1684. // the function codes and parameters are located.
  1685. irpStack = IoGetCurrentIrpStackLocation (Irp);
  1686. // Get the pointer to the input/output buffer and it's length
  1687. ioBuffer = Irp->AssociatedIrp.SystemBuffer;
  1688. inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  1689. outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  1690. // The REQHeader, which is the struct that the app fills in describing this REQuest is
  1691. // referenced in the SystemBuffer since it is sent down in the InputBuffer field of the
  1692. // DeviceIoControl call in User Mode.
  1693. // The ReqSetDeviceConfig is where the results of this call will go (using a separate
  1694. // var here just for convenience.
  1695. REQHeader = (struct _REQ_HEADER *)ioBuffer;
  1696. REQSetDeviceConfig = (struct _REQ_SET_DEVICE_CONFIG *) ioBuffer;
  1697. // The DeviceHandle is a ptr to the list entry that USBDIAG manages for devices it is
  1698. // testing. This used to be a "USBD Device handle" in the old Chap9 method. Now it's a
  1699. // ptr to the list entry object that USBDIAG maintains for each device under test. That
  1700. // list entry contains the PDO and other junk about the device object
  1701. devListEntry = (PDEVICE_LIST_ENTRY)(REQHeader->UsbdDeviceHandle);
  1702. //USBDIAG_KdPrint(("USBDIAG.SYS: DevListEntry: %X\n",devListEntry));
  1703. ASSERT (devListEntry != NULL);
  1704. if (devListEntry == NULL)
  1705. {
  1706. ntStatus = STATUS_INVALID_PARAMETER;
  1707. REQHeader->Status = CH9_STATUS_INVALID_PARAMETER;
  1708. Irp->IoStatus.Information=sizeof (struct _REQ_HEADER); //return the status junk
  1709. Irp->IoStatus.Information=ntStatus;
  1710. goto Exit_USBDIAGConfigureDevice; //Bail if things look bad
  1711. } //if
  1712. // Device object given is not the real PDO that is needed by the USB stack, so
  1713. // extract that PDO with a handy macro before calling the lower level drivers (USB stk)
  1714. actualdeviceObject = FDO_FROM_DEVICE_HANDLE(devListEntry);
  1715. //USBDIAG_KdPrint(("USBDIAG.SYS: PDO for DUT: %X\n",actualdeviceObject));
  1716. ASSERT (actualdeviceObject != NULL);
  1717. if (actualdeviceObject == NULL)
  1718. {
  1719. ntStatus = STATUS_INVALID_PARAMETER;
  1720. REQHeader->Status = CH9_STATUS_INVALID_PARAMETER;
  1721. Irp->IoStatus.Information=sizeof (struct _REQ_HEADER); //return the status junk
  1722. Irp->IoStatus.Information=ntStatus;
  1723. goto Exit_USBDIAGConfigureDevice; //Bail if things look bad
  1724. }//if
  1725. urb = USBDIAG_ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  1726. if (urb)
  1727. {
  1728. /*
  1729. // Set size of the data buffer. Note we add padding to cover hardware faults
  1730. // that may cause the device to go past the end of the data buffer
  1731. */
  1732. siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 256;
  1733. // Get the nonpaged pool memory for the data buffer
  1734. configurationDescriptor = USBDIAG_ExAllocatePool(NonPagedPool, siz);
  1735. //USBDIAG_KdPrint(("USBDIAG.SYS: Config Index Requested: %#X\n",
  1736. //REQSetDeviceConfig->iConfigurationDescIndex));
  1737. if (configurationDescriptor)
  1738. {
  1739. UsbBuildGetDescriptorRequest(urb,
  1740. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1741. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1742. (UCHAR)(REQSetDeviceConfig->iConfigurationDescIndex),
  1743. 0, //LANGUAGE ID
  1744. configurationDescriptor,
  1745. NULL,
  1746. siz, // sizeof (USB_CONFIGURATION_DESCRIPTOR),/* Get only the configuration descriptor */
  1747. NULL);
  1748. ntStatus = USBDIAG_Ch9CallUSBD(actualdeviceObject, urb, TRUE, NULL, NULL, TRUE);
  1749. ulUrbStatus = urb->UrbHeader.Status;
  1750. if (NT_SUCCESS(ntStatus))
  1751. {
  1752. //USBDIAG_KdPrint(("USBDIAG.SYS: Configuration Descriptor is at %x, bytes txferred: %d\n\
  1753. //Configuration Descriptor Actual Length: %d\n",
  1754. //configurationDescriptor,
  1755. //urb->UrbControlDescriptorRequest.TransferBufferLength,
  1756. //configurationDescriptor->wTotalLength));
  1757. }//if
  1758. else
  1759. {
  1760. //Urb had a failure
  1761. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed getting partial Config Descr: UrbStatus: %#X\n",ulUrbStatus));
  1762. Ch9FillInReqStatus (ntStatus, ulUrbStatus, REQHeader);
  1763. Irp->IoStatus.Information = sizeof (struct _REQ_SET_DEVICE_CONFIG);
  1764. Irp->IoStatus.Status = ntStatus;
  1765. goto Exit_USBDIAGConfigureDevice;
  1766. }//else failed Urb
  1767. }
  1768. else
  1769. {
  1770. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1771. goto Exit_USBDIAGConfigureDevice;
  1772. }//if-else
  1773. // Determine how much data is in the entire configuration descriptor
  1774. // and add extra room to protect against accidental overrun
  1775. siz = configurationDescriptor->wTotalLength + 16;
  1776. // Free up the data buffer memory just used
  1777. USBDIAG_ExFreePool(configurationDescriptor);
  1778. configurationDescriptor = NULL;
  1779. // Get nonpaged pool memory for the data buffer
  1780. configurationDescriptor = USBDIAG_ExAllocatePool(NonPagedPool,
  1781. siz);
  1782. // Now get the entire Configuration Descriptor
  1783. if (configurationDescriptor)
  1784. {
  1785. UsbBuildGetDescriptorRequest(urb,
  1786. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  1787. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  1788. (UCHAR)(REQSetDeviceConfig->iConfigurationDescIndex),
  1789. 0, //LANGUAGE ID
  1790. configurationDescriptor,
  1791. NULL,
  1792. siz, // Get all the descriptor data
  1793. NULL);
  1794. //USBDIAG_KdPrint(("USBDIAG.SYS: Trying to get entire Config Descriptor (%d bytes)...\n",
  1795. //siz-16));
  1796. ntStatus = USBDIAG_Ch9CallUSBD(actualdeviceObject, urb, TRUE, NULL, NULL, TRUE);
  1797. ulUrbStatus = urb->UrbHeader.Status;
  1798. if (NT_SUCCESS(ntStatus))
  1799. {
  1800. //USBDIAG_KdPrint(("USBDIAG.SYS: Entire Configuration Descriptor is at %x, bytes txferred: %d\n",
  1801. //configurationDescriptor,
  1802. //urb->UrbControlDescriptorRequest.TransferBufferLength));
  1803. }
  1804. else
  1805. {
  1806. //Error in getting configuration descriptor
  1807. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed getting entire Config Descr: UrbStatus: %#X\n",ulUrbStatus));
  1808. Ch9FillInReqStatus (ntStatus, ulUrbStatus, REQHeader);
  1809. Irp->IoStatus.Information = sizeof (struct _REQ_HEADER);
  1810. Irp->IoStatus.Status = ntStatus;
  1811. goto Exit_USBDIAGConfigureDevice;
  1812. }//else failed getconfig descriptor
  1813. }
  1814. else
  1815. {
  1816. // Failed getting data buffer (configurationDescriptor) memory
  1817. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1818. REQHeader->Status = CH9_STATUS_NO_MEMORY;
  1819. Irp->IoStatus.Information = sizeof (struct _REQ_HEADER);
  1820. Irp->IoStatus.Status = ntStatus;
  1821. goto Exit_USBDIAGConfigureDevice;
  1822. }//if-else
  1823. }
  1824. else
  1825. {
  1826. // failed getting urb memory
  1827. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1828. REQHeader->Status = CH9_STATUS_NO_MEMORY;
  1829. Irp->IoStatus.Information = sizeof (struct _REQ_HEADER);
  1830. Irp->IoStatus.Status = ntStatus;
  1831. goto Exit_USBDIAGConfigureDevice;
  1832. }//if-else
  1833. /*
  1834. // We have the configuration descriptor for the configuration
  1835. // we want.
  1836. //
  1837. // Now we issue the SelectConfiguration command to get
  1838. // the pipes associated with this configuration.
  1839. */
  1840. if (configurationDescriptor)
  1841. {
  1842. // Get our pipes
  1843. // NOTE: USBDIAG_SelectInterfaces will set the status field in the Chap9 REQHeader
  1844. // struct so we don't need to do it here, just set the length of the Irp based
  1845. // on the ntStatus code that SelectInterfaces returns.
  1846. ntStatus = USBDIAG_SelectInterfaces(actualdeviceObject,
  1847. configurationDescriptor,
  1848. NULL, // Device not yet configured
  1849. REQSetDeviceConfig //Send the user's config context down
  1850. );
  1851. if (NT_SUCCESS(ntStatus))
  1852. {
  1853. //If success, then copy back all the data to user's buffer
  1854. //USBDIAG_KdPrint(("USBDIAG.SYS: Successful SelectInterfaces \n"));
  1855. Irp->IoStatus.Information= REQHeader->Length; //return everything if success
  1856. Irp->IoStatus.Status = ntStatus; //fill in Irp code
  1857. } //if success
  1858. else
  1859. {
  1860. //if didn't succeed, only copy the header portion which has the status code
  1861. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed SelectInterfaces \n"));
  1862. Irp->IoStatus.Information= sizeof (REQHeader); //return only header portion
  1863. Irp->IoStatus.Status = ntStatus; //fill in Irp code
  1864. }//else failure
  1865. } //if
  1866. Exit_USBDIAGConfigureDevice:
  1867. // Clean up and exit this routine
  1868. if (urb)
  1869. {
  1870. USBDIAG_ExFreePool(urb); // Free urb memory
  1871. }//if
  1872. if (configurationDescriptor)
  1873. {
  1874. USBDIAG_ExFreePool(configurationDescriptor);// Free data buffer
  1875. }//if
  1876. //USBDIAG_KdPrint(("USBDIAG.SYS: exit USBDIAG_ConfigureDevice (ntStat: %x)\n", ntStatus));
  1877. return ntStatus;
  1878. }//USBDIAG_Configure_Device
  1879. NTSTATUS
  1880. USBDIAG_SelectInterfaces(
  1881. IN PDEVICE_OBJECT DeviceObject,
  1882. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  1883. IN PUSBD_INTERFACE_INFORMATION Interface,
  1884. IN OUT struct _REQ_SET_DEVICE_CONFIG * REQSetDeviceConfig
  1885. )
  1886. /*++
  1887. Arguments:
  1888. DeviceObject - pointer to the device object for this instance of the USB Device
  1889. ConfigurationDescriptor - pointer to the USB configuration descriptor containing the interface and endpoint
  1890. descriptors.
  1891. Interface - pointer to a USBD Interface Information Object
  1892. - If this is NULL, then this driver must choose its interface based on driver-specific
  1893. criteria, and the driver must also CONFIGURE the device.
  1894. - If it is NOT NULL, then the driver has already been given an interface and
  1895. the device has already been configured by the parent of this device driver.
  1896. REQSetDeviceConfig - Where the results will go for this config request
  1897. Return Value:
  1898. NT status code
  1899. --*/
  1900. {
  1901. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1902. NTSTATUS ntStatus = STATUS_SUCCESS;
  1903. PURB urb;
  1904. ULONG siz, numberOfInterfaces, j, numberOfPipes;
  1905. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  1906. PUSBD_INTERFACE_INFORMATION interfaceObject;
  1907. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_SelectInterfaces\n"));
  1908. if (Interface == NULL)
  1909. {
  1910. // This driver only supports one interface.
  1911. numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
  1912. //USBDIAG_KdPrint(("USBDIAG.SYS: Device has %d Interfaces\n",numberOfInterfaces));
  1913. numberOfInterfaces =1; // Fixed for this sample driver in this revision
  1914. numberOfPipes = 0; // Initialize to zero
  1915. // Call a USBD helper function that returns a ptr to a USB Interface Descriptor given
  1916. // a USB Configuration Descriptor, an Inteface Number, and an Alternate Setting for that Interface
  1917. interfaceDescriptor =
  1918. USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor,
  1919. ConfigurationDescriptor,
  1920. -1, // InterfaceNumber
  1921. -1, // AlternateSetting
  1922. -1, // InterfaceClass
  1923. -1, // InterfaceSubClass
  1924. -1); // InterfaceProtocol
  1925. ASSERT(interfaceDescriptor != NULL);
  1926. if (interfaceDescriptor != NULL)
  1927. {
  1928. //USBDIAG_KdPrint(("USBDIAG.SYS: Device has %d Interface(s) | Interface is at: (%#X)\n",
  1929. //numberOfInterfaces, interfaceDescriptor));
  1930. // Check if caller gave us enough pipe contexts to put all the info in
  1931. if ((REQSetDeviceConfig->nNumContexts) < (interfaceDescriptor->bNumEndpoints))
  1932. {
  1933. //USBDIAG_KdPrint(("USBDIAG.SYS: Not enough mem to configure device \n"));
  1934. //USBDIAG_KdPrint(("USBDIAG.SYS: Number of Contexts: %d | Number of Endpoints: %d",
  1935. //REQSetDeviceConfig->nNumContexts,interfaceDescriptor->bNumEndpoints));
  1936. return (STATUS_INSUFFICIENT_RESOURCES);
  1937. }/* if size is ok */
  1938. // Check if the number of pipes in this interface exceeds the maximum we can
  1939. // support in the device extension area
  1940. if ((interfaceDescriptor->bNumEndpoints) > USBDIAG_MAX_PIPES)
  1941. {
  1942. //USBDIAG_KdPrint(("USBDIAG.SYS: Number of Endpoints (%d) exceeds MAX_PIPES (%d)",
  1943. //interfaceDescriptor->bNumEndpoints, USBDIAG_MAX_PIPES));
  1944. return (STATUS_INSUFFICIENT_RESOURCES);
  1945. }/* if dev ext has enough room */
  1946. /* Add to the tally of pipes in this configuration */
  1947. numberOfPipes += interfaceDescriptor->bNumEndpoints;
  1948. //USBDIAG_KdPrint(("USBDIAG.SYS: Interface has %d endpoints\n",
  1949. //interfaceDescriptor->bNumEndpoints));
  1950. /*
  1951. // Now that we have looked at the interface, we configure the device so that the remainder
  1952. // of the USBD objects will come into existence (ie., pipes, etc.) as a result of the configuration,
  1953. // thus completing the configuration process for the USB device.
  1954. //
  1955. // Allocate a URB big enough for this Select Configuration request
  1956. // This driver supports only 1 interface
  1957. //
  1958. // NOTE: The new service USBD_CreateConfigurationRequest will replace some of the
  1959. // code below. Future releases of this driver will demonstrate how to use
  1960. // that service.
  1961. //
  1962. */
  1963. siz = GET_SELECT_CONFIGURATION_REQUEST_SIZE(numberOfInterfaces, numberOfPipes);
  1964. //USBDIAG_KdPrint(("USBDIAG.SYS: size of config request Urb = %d\n", siz));
  1965. urb = USBDIAG_ExAllocatePool(NonPagedPool,
  1966. siz);
  1967. if (urb) {
  1968. interfaceObject = (PUSBD_INTERFACE_INFORMATION) (&(urb->UrbSelectConfiguration.Interface));
  1969. //USBDIAG_KdPrint(("USBDIAG.SYS: urb.Interface=%#X\n", &(urb->UrbSelectConfiguration.Interface)));
  1970. // set up the input parameters in our interface request structure.
  1971. interfaceObject->Length = (USHORT)GET_USBD_INTERFACE_SIZE(interfaceDescriptor->bNumEndpoints);
  1972. //USBDIAG_KdPrint(("USBDIAG.SYS: size of interface request = %d\n", interfaceObject->Length));
  1973. interfaceObject->InterfaceNumber = interfaceDescriptor->bInterfaceNumber;
  1974. interfaceObject->AlternateSetting = interfaceDescriptor->bAlternateSetting;
  1975. interfaceObject->NumberOfPipes = interfaceDescriptor->bNumEndpoints;
  1976. /*
  1977. // We set up a default max transfer size for the endpoints. Your driver will
  1978. // need to change this to reflect the capabilities of your device's endpoints.
  1979. */
  1980. for (j=0; j<interfaceDescriptor->bNumEndpoints; j++) {
  1981. interfaceObject->Pipes[j].MaximumTransferSize =
  1982. USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; //Defaults to PAGE_SIZE (4k)
  1983. interfaceObject->Pipes[j].PipeFlags = 0;
  1984. } /* for */
  1985. //USBDIAG_KdPrint(("USBDIAG.SYS: InterfaceObj Inteface Nbr: %d | InterfaceObj AltSett: %d |NbrPip: %d\n",
  1986. //interfaceObject->InterfaceNumber,
  1987. //interfaceObject->AlternateSetting,
  1988. //interfaceObject->NumberOfPipes));
  1989. UsbBuildSelectConfigurationRequest(urb,
  1990. (USHORT) siz,
  1991. ConfigurationDescriptor);
  1992. ntStatus = USBDIAG_Ch9CallUSBD(DeviceObject, urb, TRUE, NULL, NULL, TRUE);
  1993. if (NT_SUCCESS(ntStatus) && USBD_SUCCESS(urb->UrbSelectConfiguration.Hdr.Status)) {
  1994. // Save the configuration handle for this device
  1995. deviceExtension->ConfigurationHandle =
  1996. urb->UrbSelectConfiguration.ConfigurationHandle;
  1997. deviceExtension->Interface[0] = USBDIAG_ExAllocatePool(NonPagedPool,
  1998. interfaceObject->Length);
  1999. if (deviceExtension->Interface[0]) {
  2000. // Save a copy of the interfaceObject information returned
  2001. RtlCopyMemory(deviceExtension->Interface[0], interfaceObject, interfaceObject->Length);
  2002. // Dump the interfaceObject to the debugger
  2003. //USBDIAG_KdPrint(("USBDIAG.SYS: ---------\n"));
  2004. //USBDIAG_KdPrint(("USBDIAG.SYS: NumberOfPipes 0x%x\n", deviceExtension->Interface[0]->NumberOfPipes));
  2005. //USBDIAG_KdPrint(("USBDIAG.SYS: Length 0x%x\n", deviceExtension->Interface[0]->Length));
  2006. //USBDIAG_KdPrint(("USBDIAG.SYS: Alt Setting 0x%x\n", deviceExtension->Interface[0]->AlternateSetting));
  2007. //USBDIAG_KdPrint(("USBDIAG.SYS: Interface Number 0x%x\n", deviceExtension->Interface[0]->InterfaceNumber));
  2008. // Dump the pipe info
  2009. for (j=0; j<interfaceObject->NumberOfPipes; j++) {
  2010. PUSBD_PIPE_INFORMATION pipeInformation;
  2011. pipeInformation = &(deviceExtension->Interface[0]->Pipes[j]);
  2012. //USBDIAG_KdPrint(("USBDIAG.SYS: ---------\n"));
  2013. //USBDIAG_KdPrint(("USBDIAG.SYS: PipeType 0x%x\n", pipeInformation->PipeType));
  2014. //USBDIAG_KdPrint(("USBDIAG.SYS: EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
  2015. //USBDIAG_KdPrint(("USBDIAG.SYS: MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
  2016. //USBDIAG_KdPrint(("USBDIAG.SYS: Interval 0x%x\n", pipeInformation->Interval));
  2017. //USBDIAG_KdPrint(("USBDIAG.SYS: Handle 0x%x\n", pipeInformation->PipeHandle));
  2018. //USBDIAG_KdPrint(("USBDIAG.SYS: MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));
  2019. // Set the user's pipe context information structure
  2020. //USBDIAG_KdPrint(("USBDIAG.SYS: Setting PipeNum: %d\n",j));
  2021. //USBDIAG_KdPrint(("USBDIAG.SYS: Setting PipeType: %d\n",pipeInformation->PipeType));
  2022. //USBDIAG_KdPrint(("USBDIAG.SYS: &PipeNum: %#X\n", &(REQSetDeviceConfig->Contxt[j].PipeNum) ));
  2023. //USBDIAG_KdPrint(("USBDIAG.SYS: &PipeType: %#X\n",&(REQSetDeviceConfig->Contxt[j].PipeType) ));
  2024. REQSetDeviceConfig->Contxt[j].PipeNum = j;
  2025. REQSetDeviceConfig->Contxt[j].PipeType = pipeInformation->PipeType;
  2026. }/* for all the pipes in this interface */
  2027. //USBDIAG_KdPrint(("USBDIAG.SYS: ---------\n"));
  2028. } /*If ExAllocate passed */
  2029. }/* if selectconfiguration request was successful */
  2030. //Fill in the user mode app's status field
  2031. Ch9FillInReqStatus (ntStatus, urb->UrbSelectConfiguration.Hdr.Status,
  2032. ((struct _REQ_HEADER * ) REQSetDeviceConfig) );
  2033. } /* if urb create successful */
  2034. else
  2035. {
  2036. //USBDIAG_KdPrint(("USBDIAG.SYS: Sample_SelectInterfaces FAILED creating Urb for selecting interface\n"));
  2037. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2038. }/* Failed creating mem for urb */
  2039. } /* if there was a valid interfacedesc */
  2040. else
  2041. {
  2042. ntStatus = STATUS_INVALID_PARAMETER;
  2043. }//else error in interfacedesc
  2044. }//if Interface given to this func was NULL (ie., we are the configuring driver)
  2045. //USBDIAG_KdPrint(("USBDIAG.SYS: exit Sample_SelectInterfaces (ntSt: %x)\n", ntStatus));
  2046. return ntStatus;
  2047. }/* Sample_SelectInterfaces */
  2048. VOID
  2049. Ch9FillInReqStatus (
  2050. IN NTSTATUS ntStatusCode,
  2051. IN ULONG ulUrbStatus,
  2052. IN OUT struct _REQ_HEADER * REQHeader //This should be the SystemBuffer (ioBuffer)
  2053. )
  2054. {
  2055. // Put the status code in the Chapter 9 structure so that the app can
  2056. // finger out what happened
  2057. switch (ntStatusCode)
  2058. {
  2059. case (STATUS_SUCCESS):
  2060. //Success
  2061. //USBDIAG_KdPrint(("USBDIAG.SYS: Status Success received\n"));
  2062. REQHeader->Status = CH9_STATUS_SUCCESS;
  2063. break;
  2064. case (STATUS_CANCELLED):
  2065. //Irp was cancelled, and we assume it was due to a nonresponsive device
  2066. //USBDIAG_KdPrint(("USBDIAG.SYS: Status Cancelled received\n"));
  2067. REQHeader->Status = CH9_STATUS_DEVICE_NOT_RESPONDING;
  2068. break; //Status_Cancelled
  2069. default:
  2070. // if you got here the irp was not successful, so look at the Urb status
  2071. // that was saved and see if that can be mapped to something the app
  2072. // understands
  2073. switch (ulUrbStatus | 0xC0000000) {
  2074. case USBD_STATUS_CRC:
  2075. //USBDIAG_KdPrint(("USBDIAG.SYS: UrbStatus CRC Failure\n"));
  2076. REQHeader->Status = CH9_STATUS_CRC_ERROR;
  2077. break;
  2078. case USBD_STATUS_STALL_PID:
  2079. case USBD_STATUS_ENDPOINT_HALTED:
  2080. //USBDIAG_KdPrint(("USBDIAG.SYS: UrbStatus EP Stalled\n"));
  2081. REQHeader->Status = CH9_STATUS_ENDPOINT_STALLED;
  2082. break;
  2083. case USBD_STATUS_BTSTUFF:
  2084. //USBDIAG_KdPrint(("USBDIAG.SYS: UrbStatus USBD_STATUS_BTSTUFF\n"));
  2085. REQHeader->Status = CH9_STATUS_BITSTUFF_ERROR;
  2086. break;
  2087. case USBD_STATUS_DATA_TOGGLE_MISMATCH:
  2088. //USBDIAG_KdPrint(("USBDIAG.SYS: UrbStatus USBD_STATUS_DATA_TOGGLE_MISMATCH\n"));
  2089. REQHeader->Status = CH9_STATUS_DATA_TOGGLE_ERROR;
  2090. break;
  2091. case USBD_STATUS_DEV_NOT_RESPONDING:
  2092. //USBDIAG_KdPrint(("USBDIAG.SYS: UrbStatus USBD_STATUS_DEV_NOT_RESPONDING\n"));
  2093. REQHeader->Status = CH9_STATUS_DEVICE_NOT_RESPONDING;
  2094. break;
  2095. default:
  2096. REQHeader->Status = CH9_STATUS_DEVICE_ERROR; //put a generic one in here for now
  2097. //USBDIAG_KdPrint(("USBDIAG.SYS: UrbStatus Other Device Failure\n"));
  2098. break;
  2099. }//switch ulUrbStatus
  2100. }//switch ntStatus
  2101. return;
  2102. }//FillInReqStatus
  2103. //#if 0
  2104. VOID
  2105. USBDIAG_IoCancelRoutine (
  2106. PDEVICE_OBJECT DeviceObject,
  2107. PIRP Irp
  2108. )
  2109. /* ++
  2110. -- */
  2111. {
  2112. //USBDIAG_KdPrint(("USBDIAG.SYS: In USBDIAG_IoCancelRoutine %x %x\n",DeviceObject,Irp));
  2113. TRAP();
  2114. return;
  2115. }//USBDIAG_IoCancelRoutine
  2116. //#endif
  2117. NTSTATUS
  2118. USBDIAG_IoGenericCompletionRoutine (
  2119. PDEVICE_OBJECT DeviceObject,
  2120. PIRP Irp,
  2121. PVOID context
  2122. )
  2123. {
  2124. PCOMPLETION_CONTEXT Context = (PCOMPLETION_CONTEXT)context;
  2125. PDEVICE_OBJECT actualDeviceObject = Context->DeviceObject;
  2126. PDEVICE_EXTENSION deviceExtension = actualDeviceObject->DeviceExtension;
  2127. PIRP irp = Context->Irp;
  2128. //USBDIAG_KdPrint(("USBDIAG.SYS: In USBDIAG_IoGenericCompletionRoutine %x %x\n",DeviceObject,Irp));
  2129. //TRAP();
  2130. // remove the irp from the irp list
  2131. USBDIAG_ClearSavedIrp(deviceExtension, irp);
  2132. if (irp->Cancel) // cancel all irps is the only one to set this bit
  2133. {
  2134. //USBDIAG_KdPrint(("CompletionRoutine: irp->Cancel bit set\n"));
  2135. KeSetEvent(&deviceExtension->CancelEvent,
  2136. 1,
  2137. FALSE);
  2138. }
  2139. //USBDIAG_KdPrint(("USBDIAG.SYS: Setting DoneEvent\n"));
  2140. // KeSetEvent(&Context->DoneEvent,
  2141. // 1,
  2142. // FALSE); // ditto with the priority
  2143. return STATUS_SUCCESS;
  2144. // return STATUS_MORE_PROCESSING_REQUIRED;
  2145. }
  2146. NTSTATUS
  2147. USBDIAG_WaitWakeCompletionRoutine(
  2148. IN PDEVICE_OBJECT DeviceObject,
  2149. IN PIRP Irp,
  2150. IN PVOID Context
  2151. )
  2152. {
  2153. PCOMPLETION_CONTEXT CompletionContext = (PCOMPLETION_CONTEXT)Context;
  2154. PDEVICE_OBJECT deviceObject = CompletionContext->DeviceObject;
  2155. PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  2156. POWER_STATE powerState;
  2157. POWER_STATE_TYPE Type = DevicePowerState;
  2158. POWER_STATE State;
  2159. NTSTATUS ntStatus = STATUS_SUCCESS;
  2160. USBDIAG_KdPrint(("'Entering USBDIAG_WaitWakeCompletionRoutine\n"));
  2161. if (Irp->Cancel)
  2162. {
  2163. USBDIAG_KdPrint(("'Cancel Bit Set. Calling USBDIAG_WaitWakeCancelRoutine\n"));
  2164. USBDIAG_WaitWakeCancelRoutine(deviceObject, Irp);
  2165. return STATUS_CANCELLED;
  2166. }
  2167. else
  2168. {
  2169. deviceExtension->WaitWakeIrp = NULL;
  2170. State.DeviceState = PowerDeviceD0;
  2171. powerState = PoSetPowerState(deviceObject, Type, State);
  2172. IoSetCancelRoutine(Irp, NULL);
  2173. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  2174. ntStatus = Irp->IoStatus.Status;
  2175. KeSetEvent(&CompletionContext->DoneEvent, 1, FALSE);
  2176. }
  2177. return ntStatus;
  2178. }
  2179. VOID
  2180. USBDIAG_WaitWakeCancelRoutine
  2181. (
  2182. IN PDEVICE_OBJECT DeviceObject,
  2183. IN PIRP Irp
  2184. )
  2185. {
  2186. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2187. USBDIAG_KdPrint(("'Entering USBDIAG_WaitWakeCancelRoutine\n"));
  2188. IoSetCancelRoutine(Irp, NULL);
  2189. IoReleaseCancelSpinLock(Irp->CancelIrql);
  2190. // reset any relevant flags here
  2191. deviceExtension->WaitWakeIrp = NULL;
  2192. Irp->IoStatus.Status = STATUS_CANCELLED;
  2193. }
  2194. NTSTATUS
  2195. USBDIAG_PoRequestCompletion(
  2196. IN PDEVICE_OBJECT DeviceObject,
  2197. IN UCHAR MinorFunction,
  2198. IN POWER_STATE PowerState,
  2199. IN PVOID Context,
  2200. IN PIO_STATUS_BLOCK IoStatus
  2201. )
  2202. /*++
  2203. Routine Description:
  2204. This routine is called when the port driver completes an IRP.
  2205. Arguments:
  2206. DeviceObject - Pointer to the device object for the class device.
  2207. Context - Driver defined context.
  2208. Return Value:
  2209. The function value is the final status from the operation.
  2210. --*/
  2211. {
  2212. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)Context;
  2213. PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  2214. PIRP irp = deviceExtension->PowerIrp;
  2215. NTSTATUS ntStatus;
  2216. ntStatus = IoStatus->Status;
  2217. //USBDIAG_KdPrint(("***USBDIAG.SYS: USBDIAG_PoRequestCompletion\n"));
  2218. IoCopyCurrentIrpStackLocationToNext(irp);
  2219. PoStartNextPowerIrp(irp);
  2220. PoCallDriver(deviceExtension->PhysicalDeviceObject, irp);
  2221. return ntStatus;
  2222. }
  2223. NTSTATUS
  2224. USBDIAG_SaveIrp(
  2225. IN PDEVICE_EXTENSION deviceExtension,
  2226. IN PIRP Irp
  2227. )
  2228. {
  2229. PIRPNODE pNode = USBDIAG_ExAllocatePool(NonPagedPool, sizeof(IRPNODE));
  2230. KIRQL Irql = KeGetCurrentIrql();
  2231. NTSTATUS ntStatus = STATUS_SUCCESS;
  2232. //USBDIAG_KdPrint(("USBDIAG_SaveIrp: Irql = 0x%x\n", Irql));
  2233. if (!pNode)
  2234. return STATUS_INSUFFICIENT_RESOURCES;
  2235. KeAcquireSpinLock(&deviceExtension->SpinLock, &Irql);
  2236. pNode->Irp = Irp;
  2237. InsertHeadList(&deviceExtension->ListHead, (PLIST_ENTRY)pNode);
  2238. KeReleaseSpinLock(&deviceExtension->SpinLock, Irql);
  2239. return ntStatus;
  2240. }
  2241. NTSTATUS
  2242. USBDIAG_ClearSavedIrp(
  2243. IN PDEVICE_EXTENSION deviceExtension,
  2244. IN PIRP Irp
  2245. )
  2246. {
  2247. NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; // assume initially it won't be found
  2248. PIRPNODE pNode = NULL;
  2249. KIRQL Irql = KeGetCurrentIrql();
  2250. BOOLEAN fContinue = TRUE;
  2251. PIRPNODE pFirstNodeSeen = NULL;
  2252. USBDIAG_KdPrint(("'USBDIAG_ClearSavedIrp: Searching for Irp 0x%x at Irql 0x%x...\n",
  2253. Irp,
  2254. Irql));
  2255. KeAcquireSpinLock(&deviceExtension->SpinLock, &Irql);
  2256. if (IsListEmpty(&deviceExtension->ListHead))
  2257. {
  2258. ntStatus = STATUS_INVALID_PARAMETER;
  2259. }
  2260. else
  2261. {
  2262. while (fContinue)
  2263. {
  2264. pNode = (PIRPNODE)RemoveHeadList(&deviceExtension->ListHead);
  2265. if (pNode == pFirstNodeSeen) // back at original head of list -> stop
  2266. {
  2267. fContinue = FALSE;
  2268. InsertHeadList(&deviceExtension->ListHead, (PLIST_ENTRY)pNode);
  2269. }
  2270. else if (pNode->Irp == Irp)
  2271. {
  2272. if (Irp == deviceExtension->InterruptIrp)
  2273. {
  2274. USBDIAG_KdPrint(("'Interrupt complete (0x%x) - clearing from list\n", Irp));
  2275. deviceExtension->InterruptIrp = NULL;
  2276. }
  2277. fContinue = FALSE;
  2278. ntStatus = STATUS_SUCCESS;
  2279. USBDIAG_ExFreePool(pNode);
  2280. }
  2281. else // not head, put at end of list
  2282. {
  2283. if (!pFirstNodeSeen)
  2284. pFirstNodeSeen = pNode;
  2285. InsertTailList(&deviceExtension->ListHead, (PLIST_ENTRY)pNode);
  2286. }
  2287. }
  2288. }
  2289. KeReleaseSpinLock(&deviceExtension->SpinLock, Irql);
  2290. return ntStatus;
  2291. }
  2292. NTSTATUS
  2293. USBDIAG_CancelAllIrps(
  2294. PDEVICE_EXTENSION deviceExtension
  2295. )
  2296. {
  2297. NTSTATUS ntStatus = STATUS_SUCCESS;
  2298. BOOLEAN bCancelled = FALSE;
  2299. KIRQL Irql = KeGetCurrentIrql();
  2300. //KIRQL RaisedIrql = DISPATCH_LEVEL;
  2301. PIRPNODE pNode = NULL;
  2302. ASSERT (deviceExtension);
  2303. USBDIAG_KdPrint(("'USBDIAG_CancelAllIrps: Entering\n"));
  2304. KeAcquireSpinLock(&deviceExtension->SpinLock, &Irql);
  2305. while (!IsListEmpty(&deviceExtension->ListHead))
  2306. {
  2307. // get the head, cancel it, and put it back
  2308. pNode = (PIRPNODE)RemoveHeadList(&deviceExtension->ListHead);
  2309. bCancelled = IoCancelIrp(pNode->Irp);
  2310. InsertHeadList(&deviceExtension->ListHead, (PLIST_ENTRY)pNode);
  2311. KeReleaseSpinLock(&deviceExtension->SpinLock, Irql);
  2312. if (!bCancelled)
  2313. {
  2314. USBDIAG_KdPrint(("USBDIAG.SYS: CancelIrp FAILED (Irp=%X | returned value=%X)\n",
  2315. pNode->Irp,
  2316. bCancelled));
  2317. // return this if not all irps were successfully cancelled
  2318. ntStatus = STATUS_UNSUCCESSFUL;
  2319. }
  2320. else
  2321. {
  2322. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully Cancelled Irp (%X)\n", pNode->Irp));
  2323. // Sleep to let the irps clean themselves up
  2324. USBDIAG_KdPrint(("'Going to sleep in cancel routine\n"));
  2325. KeWaitForSingleObject(&deviceExtension->CancelEvent,
  2326. Suspended,
  2327. KernelMode,
  2328. FALSE,
  2329. NULL);
  2330. USBDIAG_KdPrint(("'Waking up in cancel routine\n"));
  2331. }
  2332. KeAcquireSpinLock(&deviceExtension->SpinLock, &Irql);
  2333. }
  2334. KeReleaseSpinLock(&deviceExtension->SpinLock, Irql);
  2335. USBDIAG_KdPrint(("'USBDIAG_CancelAllIrps: Exiting\n"));
  2336. return ntStatus;
  2337. }
  2338. NTSTATUS
  2339. USBDIAG_IssueWaitWake(
  2340. IN PDEVICE_OBJECT DeviceObject
  2341. )
  2342. {
  2343. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2344. NTSTATUS ntStatus;
  2345. POWER_STATE powerState;
  2346. USBDIAG_KdPrint(("'*********************************\n"));
  2347. USBDIAG_KdPrint(("'USBDIAG_IssueWaitWake: Entering\n"));
  2348. USBDIAG_KdPrint(("'Issue Wait/Wake for Device Object 0x%x, extension 0x%x\n",
  2349. DeviceObject,
  2350. deviceExtension));
  2351. if (deviceExtension->WaitWakeIrp != NULL)
  2352. {
  2353. USBDIAG_KdPrint(("'Wait wake all ready active!\n"));
  2354. return STATUS_INVALID_DEVICE_STATE;
  2355. }
  2356. powerState.SystemState = deviceExtension->DeviceCapabilities.DeviceWake;
  2357. ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
  2358. IRP_MN_WAIT_WAKE,
  2359. powerState,
  2360. USBDIAG_RequestWaitWakeCompletion,
  2361. DeviceObject,
  2362. &deviceExtension->WaitWakeIrp);
  2363. if (!deviceExtension->WaitWakeIrp)
  2364. {
  2365. USBDIAG_KdPrint(("'Wait wake is NULL!\n"));
  2366. return STATUS_UNSUCCESSFUL;
  2367. }
  2368. USBDIAG_KdPrint(("'USBDIAG_IssueWaitWake: exiting with ntStatus 0x%x (wait wake is 0x%x)\n",
  2369. ntStatus,
  2370. deviceExtension->WaitWakeIrp));
  2371. return ntStatus;
  2372. }
  2373. // **************************************************************************
  2374. // Completion routine for irp generated by PoRequestPowerIrp in USBDIAG_IssueWaitWake
  2375. NTSTATUS
  2376. USBDIAG_RequestWaitWakeCompletion(
  2377. IN PDEVICE_OBJECT DeviceObject,
  2378. IN UCHAR MinorFunction,
  2379. IN POWER_STATE PowerState,
  2380. IN PVOID Context,
  2381. IN PIO_STATUS_BLOCK IoStatus
  2382. )
  2383. {
  2384. PDEVICE_OBJECT deviceObject = Context;
  2385. PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  2386. POWER_STATE powerState;
  2387. //POWER_STATE_TYPE Type = DevicePowerState;
  2388. POWER_STATE State;
  2389. NTSTATUS ntStatus = STATUS_SUCCESS;
  2390. USBDIAG_KdPrint(("'#########################################\n"));
  2391. USBDIAG_KdPrint(("'### USBDIAG_RequestWaitWakeCompletion ###\n"));
  2392. USBDIAG_KdPrint(("'#########################################\n"));
  2393. USBDIAG_KdPrint(("'Received Wait/Wake completion for Device Object 0x%x (0x%x) extension 0x%x\n",
  2394. deviceObject,
  2395. DeviceObject,
  2396. deviceExtension));
  2397. State.DeviceState = PowerDeviceD0;
  2398. ntStatus = IoStatus->Status;
  2399. deviceExtension->WaitWakeIrp = NULL;
  2400. USBDIAG_KdPrint(("'USBDIAG_RequestWaitWakeCompletion: Wake irp completed status 0x%x\n", ntStatus));
  2401. //DbgPrint("Wait/Wake completed with status 0x%x\n", ntStatus);
  2402. switch (ntStatus)
  2403. {
  2404. case STATUS_SUCCESS:
  2405. USBDIAG_KdPrint(("'USBDIAG_RequestWaitWakeCompletion: Wake irp completed succefully.\n"));
  2406. // There are 3 cases in which we will cancel the wait wake IRP
  2407. // 1) We are going to an S state where we can't wake the machine. We will
  2408. // resend the irp when we transition back to S0
  2409. // 2) We get a stop. We will resend the irp if we get another start
  2410. // 3) We get a remove. We will not (obviously) send another wait wake
  2411. ntStatus = USBDIAG_SetDevicePowerState(deviceObject, PowerDeviceD0);
  2412. break;
  2413. case STATUS_CANCELLED:
  2414. USBDIAG_KdPrint(("'USBDIAG_RequestWaitWakeCompletion: Wake irp cancelled\n"));
  2415. // case STATUS_ACPI_POWER_REQUEST_FAILED:
  2416. // case STATUS_POWER_STATE_INVALID:
  2417. break;
  2418. default:
  2419. break;
  2420. }
  2421. USBDIAG_KdPrint(("'Setting WaitWakeEvent\n"));
  2422. KeSetEvent(&deviceExtension->WaitWakeEvent, IO_NO_INCREMENT, FALSE);
  2423. return ntStatus;
  2424. }
  2425. NTSTATUS
  2426. USBDIAG_PoSelfRequestCompletion(
  2427. IN PDEVICE_OBJECT DeviceObject,
  2428. IN UCHAR MinorFunction,
  2429. IN POWER_STATE PowerState,
  2430. IN PVOID Context,
  2431. IN PIO_STATUS_BLOCK IoStatus
  2432. )
  2433. {
  2434. PDEVICE_OBJECT deviceObject = Context;
  2435. PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  2436. NTSTATUS ntStatus = IoStatus->Status;
  2437. // We only need to set the event if we're powering up;
  2438. // No caller waits on power down complete
  2439. if (deviceExtension->CurrentDeviceState.DeviceState > PowerState.DeviceState)
  2440. {
  2441. // Trigger Self-requested power irp completed event;
  2442. // The caller is waiting for completion
  2443. KeSetEvent(deviceExtension->SelfRequestedPowerIrpEvent, 1, FALSE);
  2444. }
  2445. USBDIAG_KdPrint(("'USBDIAG_PoSelfRequestCompletion:\n"));// Setting deviceExtension->PowerState.DeviceState\n"));
  2446. //deviceExtension->PowerState.DeviceState = PowerState.DeviceState;
  2447. USBDIAG_KdPrint(("'Exiting USBDIAG_PoSelfRequestCompletion\n"));
  2448. return ntStatus;
  2449. }
  2450. NTSTATUS
  2451. USBDIAG_PowerIrpCompletionRoutine(
  2452. IN PDEVICE_OBJECT DeviceObject,
  2453. IN PIRP Irp,
  2454. IN PVOID Context
  2455. )
  2456. {
  2457. PKEVENT event = Context;
  2458. // Set the input event
  2459. KeSetEvent(event,
  2460. 1, // Priority increment for waiting thread.
  2461. FALSE); // Flag this call is not immediately followed by wait.
  2462. // This routine must return STATUS_MORE_PROCESSING_REQUIRED because we have not yet called
  2463. // IoFreeIrp() on this IRP.
  2464. return STATUS_MORE_PROCESSING_REQUIRED;
  2465. }
  2466. #define DRIVER
  2467. #pragma warning(disable:4214) // bitfield nonstd
  2468. #include "wdm.h"
  2469. #pragma warning(default:4214)
  2470. #include "stdarg.h"
  2471. #include "stdio.h"
  2472. #pragma warning(disable:4200) //non std struct used
  2473. #include "usbdi.h"
  2474. #pragma warning(default:4200)
  2475. #include "usbdlib.h"
  2476. #include "ioctl.h"
  2477. #include "USBDIAG.h"
  2478. UCHAR *SystemPowerStateString[] = {
  2479. "PowerSystemUnspecified",
  2480. "PowerSystemWorking",
  2481. "PowerSystemSleeping1",
  2482. "PowerSystemSleeping2",
  2483. "PowerSystemSleeping3",
  2484. "PowerSystemHibernate",
  2485. "PowerSystemShutdown",
  2486. "PowerSystemMaximum"
  2487. };
  2488. UCHAR *DevicePowerStateString[] = {
  2489. "PowerDeviceUnspecified",
  2490. "PowerDeviceD0",
  2491. "PowerDeviceD1",
  2492. "PowerDeviceD2",
  2493. "PowerDeviceD3",
  2494. "PowerDeviceMaximum"
  2495. };
  2496. NTSTATUS
  2497. USBDIAG_Power(
  2498. IN PDEVICE_OBJECT DeviceObject,
  2499. IN PIRP Irp
  2500. )
  2501. {
  2502. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2503. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  2504. NTSTATUS ntStatus = STATUS_SUCCESS;
  2505. BOOLEAN fGoingToD0 = FALSE;
  2506. POWER_STATE sysPowerState, desiredDevicePowerState;
  2507. KEVENT event;
  2508. USBDIAG_KdPrint(("'=======================================================================\n"));
  2509. USBDIAG_KdPrint(("'USBDIAG_Power() IRP_MJ_POWER\n"));
  2510. switch (irpStack->MinorFunction)
  2511. {
  2512. case IRP_MN_WAIT_WAKE:
  2513. USBDIAG_KdPrint(("'==========================================\n"));
  2514. USBDIAG_KdPrint(("'USBDIAG_Power() Enter IRP_MN_WAIT_WAKE --\n"));
  2515. // The only way this comes through us is if we send it via PoRequestPowerIrp
  2516. IoSkipCurrentIrpStackLocation(Irp); // not attaching a completion routine
  2517. PoStartNextPowerIrp(Irp);
  2518. ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp);
  2519. break;
  2520. case IRP_MN_SET_POWER:
  2521. // The system power policy manager sends this IRP to set the system power state.
  2522. // A device power policy manager sends this IRP to set the device power state for a device.
  2523. USBDIAG_KdPrint(("'==========================================\n"));
  2524. USBDIAG_KdPrint(("'USBDIAG_Power() Enter IRP_MN_SET_POWER\n"));
  2525. // Set Irp->IoStatus.Status to STATUS_SUCCESS to indicate that the device
  2526. // has entered the requested state. Drivers cannot fail this IRP.
  2527. switch (irpStack->Parameters.Power.Type)
  2528. {
  2529. case SystemPowerState:
  2530. // Get input system power state
  2531. sysPowerState.SystemState = irpStack->Parameters.Power.State.SystemState;
  2532. USBDIAG_KdPrint(("'USBDIAG_Power() Set Power, type SystemPowerState = %s\n",
  2533. SystemPowerStateString[sysPowerState.SystemState] ));
  2534. // If system is in working state always set our device to D0
  2535. // regardless of the wait state or system-to-device state power map
  2536. if ( sysPowerState.SystemState == PowerSystemWorking)
  2537. {
  2538. desiredDevicePowerState.DeviceState = PowerDeviceD0;
  2539. USBDIAG_KdPrint(("'USBDIAG_Power() PowerSystemWorking, will set D0, not use state map\n"));
  2540. }
  2541. else
  2542. {
  2543. // set to corresponding system state if IRP_MN_WAIT_WAKE pending
  2544. if ( deviceExtension->WaitWakeIrp ) // got a WAIT_WAKE IRP pending?
  2545. {
  2546. // Find the device power state equivalent to the given system state.
  2547. // We get this info from the DEVICE_CAPABILITIES struct in our device
  2548. // extension (initialized in USBDIAG_PnPAddDevice() )
  2549. desiredDevicePowerState.DeviceState =
  2550. deviceExtension->DeviceCapabilities.DeviceState[ sysPowerState.SystemState ];
  2551. USBDIAG_KdPrint(("'USBDIAG_Power() IRP_MN_WAIT_WAKE pending, will use state map\n"));
  2552. }
  2553. else
  2554. {
  2555. // if no wait pending and the system's not in working state, just turn off
  2556. desiredDevicePowerState.DeviceState = PowerDeviceD3;
  2557. USBDIAG_KdPrint(("'USBDIAG_Power() Not EnabledForWakeup and the system's not in working state,\n settting PowerDeviceD3 (off )\n"));
  2558. }
  2559. }
  2560. //
  2561. // We've determined the desired device state; are we already in this state?
  2562. //
  2563. USBDIAG_KdPrint(("'USBDIAG_Power() Set Power, desiredDevicePowerState = %s\n",
  2564. DevicePowerStateString[desiredDevicePowerState.DeviceState]));
  2565. if (desiredDevicePowerState.DeviceState != deviceExtension->CurrentDeviceState.DeviceState)
  2566. {
  2567. // No, request that we be put into this state
  2568. // by requesting a new Power Irp from the Pnp manager
  2569. deviceExtension->PowerIrp = Irp;
  2570. ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
  2571. IRP_MN_SET_POWER,
  2572. desiredDevicePowerState,
  2573. // completion routine will pass the Irp down to the PDO
  2574. USBDIAG_PoRequestCompletion,
  2575. DeviceObject,
  2576. NULL);
  2577. }
  2578. else
  2579. {
  2580. // Yes, just pass it on to PDO (Physical Device Object)
  2581. IoCopyCurrentIrpStackLocationToNext(Irp);
  2582. PoStartNextPowerIrp(Irp);
  2583. ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp);
  2584. USBDIAG_KdPrint(("'USBDIAG_Power() Exit IRP_MN_SET_POWER\n"));
  2585. }
  2586. break;
  2587. case DevicePowerState:
  2588. USBDIAG_KdPrint(("'USBDIAG_Power() Set Power, type DevicePowerState = %s\n",
  2589. DevicePowerStateString[irpStack->Parameters.Power.State.DeviceState]));
  2590. // For requests to D1, D2, or D3 ( sleep or off states ),
  2591. // sets deviceExtension->CurrentDeviceState to DeviceState immediately.
  2592. // This enables any code checking state to consider us as sleeping or off
  2593. // already, as this will imminently become our state.
  2594. // For requests to DeviceState D0 ( fully on ), sets fGoingToD0 flag TRUE
  2595. // to flag that we must set a completion routine and update
  2596. // deviceExtension->CurrentDeviceState there.
  2597. // In the case of powering up to fully on, we really want to make sure
  2598. // the process is completed before updating our CurrentDeviceState,
  2599. // so no IO will be attempted or accepted before we're really ready.
  2600. fGoingToD0 = (BOOLEAN)(irpStack->Parameters.Power.State.DeviceState == PowerDeviceD0);
  2601. IoCopyCurrentIrpStackLocationToNext(Irp);
  2602. if (fGoingToD0) {
  2603. USBDIAG_KdPrint(("'USBDIAG_Power() Set PowerIrp Completion Routine, fGoingToD0 =%d\n", fGoingToD0));
  2604. IoSetCompletionRoutine(Irp,
  2605. USBDIAG_PowerIrp_Complete,
  2606. // Always pass FDO to completion routine as its Context;
  2607. // This is because the DriverObject passed by the system to the routine
  2608. // is the Physical Device Object ( PDO ) not the Functional Device Object ( FDO )
  2609. DeviceObject,
  2610. TRUE, // invoke on success
  2611. TRUE, // invoke on error
  2612. TRUE); // invoke on cancellation of the Irp
  2613. }
  2614. PoStartNextPowerIrp(Irp);
  2615. ntStatus = PoCallDriver(deviceExtension->StackDeviceObject,
  2616. Irp);
  2617. USBDIAG_KdPrint(("'USBDIAG_Power() Exit IRP_MN_SET_POWER\n"));
  2618. break;
  2619. } /* case irpStack->Parameters.Power.Type */
  2620. break; /* IRP_MN_SET_POWER */
  2621. case IRP_MN_QUERY_POWER:
  2622. //
  2623. // A power policy manager sends this IRP to determine whether it can change
  2624. // the system or device power state, typically to go to sleep.
  2625. //
  2626. USBDIAG_KdPrint(("'==========================================\n"));
  2627. USBDIAG_KdPrint(("'USBDIAG_Power() IRP_MN_QUERY_POWER\n"));
  2628. // We do nothing special here, just let the PDO handle it
  2629. IoCopyCurrentIrpStackLocationToNext(Irp);
  2630. PoStartNextPowerIrp(Irp);
  2631. ntStatus = PoCallDriver(deviceExtension->StackDeviceObject,
  2632. Irp);
  2633. break; /* IRP_MN_QUERY_POWER */
  2634. default:
  2635. USBDIAG_KdPrint(("'==========================================\n"));
  2636. USBDIAG_KdPrint(("'USBDIAG_Power() UNKNOWN POWER MESSAGE (%x)\n", irpStack->MinorFunction));
  2637. //
  2638. // All unhandled power messages are passed on to the PDO
  2639. //
  2640. IoCopyCurrentIrpStackLocationToNext(Irp);
  2641. PoStartNextPowerIrp(Irp);
  2642. ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp);
  2643. }
  2644. USBDIAG_KdPrint(("'Exit USBDIAG_Power() ntStatus = 0x%x\n", ntStatus ) );
  2645. return ntStatus;
  2646. }
  2647. NTSTATUS
  2648. USBDIAG_SetDevicePowerState(
  2649. IN PDEVICE_OBJECT DeviceObject,
  2650. IN ULONG ulPowerState
  2651. )
  2652. {
  2653. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2654. NTSTATUS ntStatus = STATUS_SUCCESS;
  2655. POWER_STATE PowerState;
  2656. PowerState.DeviceState = (DEVICE_POWER_STATE)ulPowerState;
  2657. deviceExtension->SelfRequestedPowerIrpEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  2658. if (!deviceExtension->SelfRequestedPowerIrpEvent)
  2659. return STATUS_INSUFFICIENT_RESOURCES;
  2660. KeInitializeEvent(deviceExtension->SelfRequestedPowerIrpEvent, NotificationEvent, FALSE);
  2661. ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
  2662. IRP_MN_SET_POWER,
  2663. PowerState,
  2664. USBDIAG_PoSelfRequestCompletion,
  2665. DeviceObject,
  2666. NULL);
  2667. if ( ntStatus == STATUS_PENDING )
  2668. {
  2669. // We only need to wait for completion if we're powering up
  2670. if ( deviceExtension->CurrentDeviceState.DeviceState > PowerState.DeviceState )
  2671. {
  2672. NTSTATUS waitStatus;
  2673. waitStatus = KeWaitForSingleObject(
  2674. deviceExtension->SelfRequestedPowerIrpEvent,
  2675. Suspended,
  2676. KernelMode,
  2677. FALSE,
  2678. NULL);
  2679. ExFreePool(deviceExtension->SelfRequestedPowerIrpEvent);
  2680. deviceExtension->SelfRequestedPowerIrpEvent = NULL;
  2681. }
  2682. }
  2683. deviceExtension->CurrentDeviceState.DeviceState = PowerState.DeviceState;
  2684. USBDIAG_KdPrint(("'CurrentDeviceState set to 0x%x\n",deviceExtension->CurrentDeviceState.DeviceState));
  2685. ntStatus = STATUS_SUCCESS;
  2686. return ntStatus;
  2687. }
  2688. NTSTATUS
  2689. USBDIAG_PowerIrp_Complete(
  2690. IN PDEVICE_OBJECT NullDeviceObject,
  2691. IN PIRP Irp,
  2692. IN PVOID Context
  2693. )
  2694. /*++
  2695. Routine Description:
  2696. This routine is called when An IRP_MN_SET_POWER of type 'DevicePowerState'
  2697. has been received by USBDIAG_ProcessPowerIrp(), and that routine has determined
  2698. 1) the request is for full powerup ( to PowerDeviceD0 ), and
  2699. 2) We are not already in that state
  2700. A call is then made to PoRequestPowerIrp() with this routine set as the completion routine.
  2701. Arguments:
  2702. DeviceObject - Pointer to the device object for the class device.
  2703. Irp - Irp completed.
  2704. Context - Driver defined context.
  2705. Return Value:
  2706. The function value is the final status from the operation.
  2707. --*/
  2708. {
  2709. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context;
  2710. PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  2711. NTSTATUS ntStatus = STATUS_SUCCESS;
  2712. PIO_STACK_LOCATION irpStack;
  2713. USBDIAG_KdPrint(("'enter USBDIAG_PowerIrp_Complete\n"));
  2714. // If the lower driver returned PENDING, mark our stack location as pending also.
  2715. if (Irp->PendingReturned)
  2716. {
  2717. IoMarkIrpPending(Irp);
  2718. }
  2719. irpStack = IoGetCurrentIrpStackLocation (Irp);
  2720. // We can assert that we're a device powerup-to D0 request,
  2721. // because that was the only type of request we set a completion routine
  2722. // for in the first place
  2723. ASSERT(irpStack->MajorFunction == IRP_MJ_POWER);
  2724. ASSERT(irpStack->MinorFunction == IRP_MN_SET_POWER);
  2725. ASSERT(irpStack->Parameters.Power.Type==DevicePowerState);
  2726. ASSERT(irpStack->Parameters.Power.State.DeviceState==PowerDeviceD0);
  2727. // Now that we know we've let the lower drivers do what was needed to power up,
  2728. // we can set our device extension flags accordingly
  2729. deviceExtension->CurrentDeviceState.DeviceState = PowerDeviceD0;
  2730. Irp->IoStatus.Status = ntStatus;
  2731. USBDIAG_KdPrint(("'exit USBDIAG_PowerIrp_Complete Exit IRP_MN_SET_POWER D0 complete\n"));
  2732. return ntStatus;
  2733. }
  2734. #if 0
  2735. NTSTATUS
  2736. ISOPERF_ResetPipe(
  2737. IN PDEVICE_OBJECT DeviceObject,
  2738. IN PUSBD_PIPE_INFORMATION Pipe,
  2739. IN BOOLEAN IsoClearStall
  2740. )
  2741. /*++
  2742. Routine Description:
  2743. Reset a given USB pipe.
  2744. NOTES:
  2745. This will reset the host to Data0 and should also reset the device
  2746. to Data0 for Bulk and Interrupt pipes.
  2747. For Iso pipes this will set the virgin state of pipe so that ASAP
  2748. transfers begin with the current bus frame instead of the next frame
  2749. after the last transfer occurred.
  2750. Arguments:
  2751. Return Value:
  2752. --*/
  2753. {
  2754. NTSTATUS ntStatus;
  2755. PURB urb;
  2756. ISOPERF_KdPrint ( DBGLVL_MEDIUM, (" Reset Pipe %x\n", Pipe));
  2757. urb = ExAllocatePool(NonPagedPool,
  2758. sizeof(struct _URB_PIPE_REQUEST));
  2759. if (urb) {
  2760. urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
  2761. urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
  2762. urb->UrbPipeRequest.PipeHandle =
  2763. Pipe->PipeHandle;
  2764. ntStatus = ISOPERF_CallUSBD(DeviceObject, urb);
  2765. ExFreePool(urb);
  2766. } else {
  2767. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2768. }
  2769. //
  2770. // Memphis RESET_PIPE will send a Clear-Feature Endpoint Stall to
  2771. // reset the data toggle of non-Iso pipes as part of a RESET_PIPE
  2772. // request. It does not do this for Iso pipes as Iso pipes do not use
  2773. // the data toggle (all Iso packets are Data0). However, we also use
  2774. // the Clear-Feature Endpoint Stall request in our device firmware to
  2775. // reset data buffer points inside the device so we explicitly send
  2776. // this request to the device for Iso pipes if desired.
  2777. //
  2778. if (NT_SUCCESS(ntStatus) && IsoClearStall &&
  2779. (Pipe->PipeType == UsbdPipeTypeIsochronous)) {
  2780. urb = ExAllocatePool(NonPagedPool,
  2781. sizeof(struct _URB_CONTROL_FEATURE_REQUEST));
  2782. if (urb)
  2783. {
  2784. UsbBuildFeatureRequest(urb,
  2785. URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT,
  2786. USB_FEATURE_ENDPOINT_STALL,
  2787. Pipe->EndpointAddress,
  2788. NULL);
  2789. ntStatus = ISOPERF_CallUSBD(DeviceObject, urb);
  2790. ExFreePool(urb);
  2791. }
  2792. else
  2793. {
  2794. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2795. }
  2796. }
  2797. return ntStatus;
  2798. }
  2799. #endif
  2800. NTSTATUS
  2801. USBDIAG_DisableRemoteWakeupEnable(
  2802. IN PDEVICE_OBJECT DeviceObject,
  2803. IN BOOLEAN bDisable
  2804. )
  2805. {
  2806. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  2807. NTSTATUS ntStatus;
  2808. WCHAR KeyName[] = L"DisableRemoteWakeup";
  2809. ULONG KeyNameLength = sizeof(KeyName);
  2810. PVOID Data = ExAllocatePool(NonPagedPool, sizeof(ULONG));
  2811. ULONG DataLength = sizeof(ULONG);
  2812. ULONG KeyType = REG_DWORD;
  2813. if (Data)
  2814. {
  2815. *((PULONG)Data) = bDisable ? 0x01 : 0x00;
  2816. USBDIAG_KdPrint(("'calling USBD_SetPdoRegistryParameter with Data = 0x%x\n", *((PULONG)Data)));
  2817. ntStatus = USBD_SetPdoRegistryParameter(deviceExtension->PhysicalDeviceObject,
  2818. KeyName,
  2819. KeyNameLength,
  2820. Data,
  2821. DataLength,
  2822. KeyType,
  2823. PLUGPLAY_REGKEY_DRIVER);
  2824. USBDIAG_KdPrint(("'USBD_SetPdoRegistryParameter returned ntStatus 0x%x\n", ntStatus));
  2825. ExFreePool(Data);
  2826. Data = NULL;
  2827. }
  2828. else
  2829. {
  2830. ntStatus = STATUS_NO_MEMORY;
  2831. }
  2832. return ntStatus;
  2833. }