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.

2528 lines
72 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. usbdiag.c
  5. Abstract:
  6. USB device driver for Intel/Microsoft USB 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. 7-21-97 : Todd Carpenter adds Chap11 IOCTL's
  18. --*/
  19. #define DRIVER
  20. #include "wdm.h"
  21. #include "stdarg.h"
  22. #include "stdio.h"
  23. #pragma pack (push,1)
  24. #include "usb100.h"
  25. #include "usbdi.h"
  26. #include "usbdlib.h"
  27. #include "usbioctl.h"
  28. #pragma pack (pop) //disable 1-byte alignment
  29. #include "opaque.h"
  30. #pragma pack (push,1)
  31. #include "ioctl.h"
  32. #include "chap9drv.h"
  33. #include "USBDIAG.h"
  34. #pragma pack (pop) //disable 1-byte alignment
  35. PDEVICE_OBJECT USBDIAG_GlobalDeviceObject = NULL;
  36. ULONG USBDIAG_NextDeviceNumber = 0;
  37. ULONG USBDIAG_NumberDevices = 0;
  38. ULONG gulMemoryAllocated = 0;
  39. USBD_VERSION_INFORMATION gVersionInformation;
  40. /* UCHAR *SystemPowerStateString[] = {
  41. "PowerSystemUnspecified",
  42. "PowerSystemWorking",
  43. "PowerSystemSleeping1",
  44. "PowerSystemSleeping2",
  45. "PowerSystemSleeping3",
  46. "PowerSystemHibernate",
  47. "PowerSystemShutdown",
  48. "PowerSystemMaximum"
  49. };
  50. UCHAR *DevicePowerStateString[] = {
  51. "PowerDeviceUnspecified",
  52. "PowerDeviceD0",
  53. "PowerDeviceD1",
  54. "PowerDeviceD2",
  55. "PowerDeviceD3",
  56. "PowerDeviceMaximum"
  57. }; */
  58. //
  59. // Global pointer to Driver Object
  60. //
  61. PDRIVER_OBJECT USBDIAG_DriverObject;
  62. #define REMOTE_WAKEUP 0x20
  63. #ifdef PAGE_CODE
  64. #ifdef ALLOC_PRAGMA
  65. #pragma alloc_text(PAGE, USBD_SubmitSynchronousURB)
  66. #pragma alloc_text(PAGE, USBD_CloseEndpoint)
  67. #endif
  68. #endif
  69. NTSTATUS
  70. DriverEntry(
  71. IN PDRIVER_OBJECT DriverObject,
  72. IN PUNICODE_STRING RegistryPath
  73. )
  74. /*++
  75. Routine Description:
  76. Installable driver initialization entry point.
  77. This entry point is called directly by the I/O system.
  78. Arguments:
  79. DriverObject - pointer to the driver object
  80. RegistryPath - pointer to a unicode string representing the path
  81. to driver-specific key in the registry
  82. Return Value:
  83. STATUS_SUCCESS if successful,
  84. STATUS_UNSUCCESSFUL otherwise
  85. --*/
  86. {
  87. NTSTATUS ntStatus = STATUS_SUCCESS;
  88. //PDEVICE_OBJECT deviceObject = NULL;
  89. DbgPrint("USBDIAG.SYS: entering (USBDIAG) DriverEntry\n");
  90. DbgPrint("USBDIAG.SYS: USBDIAG Driver Build Date/Time: %s %s\n",
  91. __DATE__, __TIME__);
  92. USBDIAG_DriverObject = DriverObject;
  93. //
  94. // Create dispatch points for device control, create, close.
  95. //
  96. DriverObject->MajorFunction[IRP_MJ_PNP] = USBDIAG_PnP;
  97. DriverObject->MajorFunction[IRP_MJ_POWER] = USBDIAG_Power;
  98. DriverObject->MajorFunction[IRP_MJ_CREATE] =
  99. DriverObject->MajorFunction[IRP_MJ_CLOSE] = USBDIAG_Dispatch;
  100. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = USBDIAG_ProcessIOCTL;
  101. DriverObject->MajorFunction[IRP_MJ_WRITE] = NULL;
  102. DriverObject->MajorFunction[IRP_MJ_READ] = NULL;
  103. DriverObject->DriverUnload = USBDIAG_Unload;
  104. DriverObject->DriverExtension->AddDevice = USBDIAG_PnPAddDevice;
  105. DbgPrint ("'USBDIAG.SYS: exiting (USBDIAG) DriverEntry (%x)\n", ntStatus);
  106. // determine the os version and store in a global.
  107. USBD_GetUSBDIVersion(&gVersionInformation);
  108. return ntStatus;
  109. }
  110. NTSTATUS
  111. USBDIAG_Dispatch(
  112. IN PDEVICE_OBJECT DeviceObject,
  113. IN PIRP Irp
  114. )
  115. /*++
  116. Routine Description:
  117. Process the IRPs sent to this device.
  118. Arguments:
  119. DeviceObject - pointer to a device object
  120. Irp - pointer to an I/O Request Packet
  121. Return Value:
  122. --*/
  123. {
  124. PIO_STACK_LOCATION irpStack;
  125. NTSTATUS ntStatus;
  126. PDEVICE_EXTENSION globalDeviceExtension;
  127. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_Dispatch\n"));
  128. //
  129. // Default return status unless overridden later
  130. //
  131. Irp->IoStatus.Status = STATUS_SUCCESS;
  132. Irp->IoStatus.Information = 0;
  133. //
  134. // Get a pointer to the current location in the Irp. This is where
  135. // the function codes and parameters are located.
  136. //
  137. irpStack = IoGetCurrentIrpStackLocation (Irp);
  138. switch (irpStack->MajorFunction) {
  139. case IRP_MJ_CREATE:
  140. //USBDIAG_KdPrint(("USBDIAG.SYS: IRP_MJ_CREATE\n"));
  141. ASSERT(USBDIAG_GlobalDeviceObject != NULL);
  142. globalDeviceExtension = USBDIAG_GlobalDeviceObject->DeviceExtension;
  143. globalDeviceExtension->OpenFRC++;
  144. break;
  145. case IRP_MJ_CLOSE:
  146. //USBDIAG_KdPrint(("USBDIAG.SYS: IRP_MJ_CLOSE\n"));
  147. ASSERT(USBDIAG_GlobalDeviceObject != NULL);
  148. globalDeviceExtension = USBDIAG_GlobalDeviceObject->DeviceExtension;
  149. globalDeviceExtension->OpenFRC--;
  150. break;
  151. default:
  152. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  153. break;
  154. } /* case MajorFunction */
  155. ntStatus = Irp->IoStatus.Status;
  156. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  157. //USBDIAG_KdPrint(("USBDIAG.SYS: Exit USBDIAG_Dispatch %x\n", ntStatus));
  158. return ntStatus;
  159. }
  160. NTSTATUS
  161. USBDIAG_PnP(
  162. IN PDEVICE_OBJECT DeviceObject,
  163. IN PIRP Irp
  164. )
  165. /*++
  166. Routine Description:
  167. Process the PnP IRPs sent to this device.
  168. Arguments:
  169. DeviceObject - pointer to a device object
  170. Irp - pointer to an I/O Request Packet
  171. Return Value:
  172. --*/
  173. {
  174. NTSTATUS ntStatus;
  175. PIO_STACK_LOCATION irpStack;
  176. PDEVICE_EXTENSION deviceExtension;
  177. PDEVICE_EXTENSION globalDeviceExtension;
  178. PDEVICE_LIST_ENTRY device, foundDevice;
  179. BOOLEAN passDownIrp;
  180. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_PnP\n"));
  181. //
  182. // Default to passing down all Irps unless overridden later.
  183. //
  184. passDownIrp = TRUE;
  185. //
  186. // Get a pointer to the current location in the Irp. This is where
  187. // the function codes and parameters are located.
  188. //
  189. irpStack = IoGetCurrentIrpStackLocation (Irp);
  190. //
  191. // Get a pointer to the device extension
  192. //
  193. deviceExtension = DeviceObject->DeviceExtension;
  194. ASSERT (deviceExtension != NULL);
  195. //
  196. // Get a pointer to the global device extension
  197. //
  198. globalDeviceExtension = USBDIAG_GlobalDeviceObject->DeviceExtension;
  199. //
  200. // Switch on the PnP minor function
  201. //
  202. switch (irpStack->MinorFunction) {
  203. case IRP_MN_START_DEVICE:
  204. //USBDIAG_KdPrint(("USBDIAG.SYS: IRP_MN_START_DEVICE\n"));
  205. ntStatus = USBDIAG_PassDownIrp(DeviceObject, Irp);
  206. USBDIAG_KdPrint (("Back from passing down IRP_MN_START_DEVICE; status: %#X\n",
  207. ntStatus));
  208. if (NT_SUCCESS(ntStatus))
  209. {
  210. // Now we can begin our configuration actions on the device
  211. //
  212. ntStatus = USBDIAG_StartDevice(DeviceObject);
  213. }
  214. passDownIrp = FALSE;
  215. break;
  216. case IRP_MN_QUERY_CAPABILITIES: // 0x09
  217. USBDIAG_KdPrint (("*********************************\n"));
  218. USBDIAG_KdPrint (("IRP_MN_QUERY_CAPABILITIES\n"));
  219. passDownIrp = FALSE;
  220. IoCopyCurrentIrpStackLocationToNext(Irp);
  221. IoSetCompletionRoutine(Irp,
  222. USBDIAG_QueryCapabilitiesCompletionRoutine,
  223. DeviceObject,
  224. TRUE,
  225. TRUE,
  226. TRUE);
  227. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject, Irp);
  228. break;
  229. case IRP_MN_STOP_DEVICE:
  230. //USBDIAG_KdPrint(("USBDIAG.SYS: IRP_MN_STOP_DEVICE\n"));
  231. ntStatus = USBDIAG_StopDevice(DeviceObject);
  232. break;
  233. case IRP_MN_REMOVE_DEVICE:
  234. {
  235. int i = 1;
  236. //USBDIAG_KdPrint(("USBDIAG.SYS: IRP_MN_REMOVE_DEVICE\n"));
  237. ntStatus = USBDIAG_StopDevice(DeviceObject);
  238. // remove all downstream devices
  239. for (i = 1; i <= MAX_DOWNSTREAM_DEVICES; i++)
  240. {
  241. if (deviceExtension->DeviceData[i])
  242. {
  243. USBDIAG_KdPrint(("IRP_MN_REMOVE_DEVICE: Removing device on downstream port %d\n", i));
  244. USBDIAG_RemoveDownstreamDevice(deviceExtension->DeviceData[i],
  245. deviceExtension->StackDeviceObject);
  246. }
  247. }
  248. USBDIAG_KdPrint(("Done removing downstream devices\n"));
  249. //
  250. // Remove this device object from our list
  251. //
  252. device = globalDeviceExtension->DeviceList;
  253. USBDIAG_KdPrint(("USBDIAG.SYS: IRP_MN_REMOVE_DEVICE devobj = %x dev = %x\n",
  254. DeviceObject, device));
  255. ASSERT(device != NULL);
  256. if (device->DeviceObject == DeviceObject) {
  257. //
  258. // DeviceObject is the first one on the list. Delete from the
  259. // list by setting the head of the list to point to the next
  260. // one on the list.
  261. //
  262. globalDeviceExtension->DeviceList = device->Next;
  263. USBDIAG_ExFreePool(device);
  264. } else {
  265. //
  266. // DeviceObject is not the first one on the list. Walk the
  267. // list and find it.
  268. //
  269. while (device->Next) {
  270. if (device->Next->DeviceObject == DeviceObject) {
  271. //
  272. // DeviceObject is the next one on the list, remember
  273. // the next one and delete it by setting the next one
  274. // to the next next one.
  275. //
  276. foundDevice = device->Next;
  277. device->Next = foundDevice->Next;
  278. USBDIAG_ExFreePool(foundDevice);
  279. break;
  280. }
  281. device = device->Next;
  282. }
  283. }
  284. //USBDIAG_KdPrint(("USBDIAG.SYS: Detaching stack device object...%X\n",
  285. //deviceExtension->StackDeviceObject));
  286. IoDetachDevice(deviceExtension->StackDeviceObject);
  287. //
  288. // Pass the REMOVE_DEVICE Irp down now after detaching and
  289. // removing the device instead of later.
  290. //
  291. passDownIrp = FALSE;
  292. IoSkipCurrentIrpStackLocation (Irp);
  293. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject, Irp);
  294. //USBDIAG_KdPrint(("USBDIAG.SYS: Deleting device object...%X\n", DeviceObject));
  295. IoDeleteDevice(DeviceObject);
  296. USBDIAG_NumberDevices--;
  297. //
  298. // Free the GlobalDeviceObject if this was the last real
  299. // DeviceObject. XXXXX Take a careful look at what the
  300. // hell this routine is all about.
  301. //
  302. USBDIAG_RemoveGlobalDeviceObject();
  303. }
  304. break;
  305. default:
  306. //USBDIAG_KdPrint(("USBDIAG.SYS: PnP IOCTL not handled: (%#X)\n",
  307. //irpStack->MinorFunction));
  308. break;
  309. }
  310. if (passDownIrp)
  311. {
  312. //
  313. // Pass the PnP Irp down the stack
  314. //
  315. IoSkipCurrentIrpStackLocation (Irp);
  316. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  317. Irp);
  318. }
  319. //USBDIAG_KdPrint(("USBDIAG.SYS: Exit USBDIAG_PnP %x\n", ntStatus));
  320. return ntStatus;
  321. }
  322. NTSTATUS
  323. USBDIAG_PassDownIrp (
  324. IN PDEVICE_OBJECT DeviceObject,
  325. IN PIRP Irp
  326. )
  327. {
  328. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  329. KEVENT localevent;
  330. NTSTATUS ntStatus;
  331. PAGED_CODE();
  332. // Initialize the event we'll wait on
  333. //
  334. KeInitializeEvent(&localevent,
  335. SynchronizationEvent,
  336. FALSE);
  337. // Copy down Irp params for the next driver
  338. //
  339. IoCopyCurrentIrpStackLocationToNext(Irp);
  340. // Set the completion routine, which will signal the event
  341. //
  342. IoSetCompletionRoutine(Irp,
  343. USBDIAG_GenericCompletionRoutine,
  344. &localevent,
  345. TRUE, // InvokeOnSuccess
  346. TRUE, // InvokeOnError
  347. TRUE); // InvokeOnCancel
  348. // Pass the Irp down the stack
  349. //
  350. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject, Irp);
  351. // If the request is pending, block until it completes
  352. //
  353. if (ntStatus == STATUS_PENDING)
  354. {
  355. KeWaitForSingleObject(&localevent,
  356. Executive,
  357. KernelMode,
  358. FALSE,
  359. NULL);
  360. ntStatus = Irp->IoStatus.Status;
  361. }
  362. return ntStatus;
  363. }
  364. NTSTATUS
  365. USBDIAG_GenericCompletionRoutine(
  366. IN PDEVICE_OBJECT DeviceObject,
  367. IN PIRP Irp,
  368. IN PVOID Context
  369. )
  370. {
  371. PKEVENT kevent;
  372. kevent = (PKEVENT)Context;
  373. KeSetEvent(kevent, IO_NO_INCREMENT,FALSE);
  374. return STATUS_MORE_PROCESSING_REQUIRED;
  375. }
  376. VOID
  377. USBDIAG_Unload(
  378. IN PDRIVER_OBJECT DriverObject
  379. )
  380. /*++
  381. Routine Description:
  382. Free all the allocated resources, etc.
  383. Arguments:
  384. DriverObject - pointer to a driver object
  385. Return Value:
  386. --*/
  387. {
  388. DbgPrint ("USBDIAG.SYS: enter USBDIAG_Unload\n");
  389. //
  390. // Free any global resources allocated
  391. // in DriverEntry
  392. //
  393. // free the global deviceobject here
  394. USBDIAG_RemoveGlobalDeviceObject();
  395. DbgPrint ("USBDIAG.SYS: exit USBDIAG_Unload\n");
  396. }
  397. NTSTATUS
  398. USBDIAG_StartDevice(
  399. IN PDEVICE_OBJECT DeviceObject
  400. )
  401. /*++
  402. Routine Description:
  403. Initializes a given instance of the device on the USB.
  404. Arguments:
  405. DeviceObject - pointer to the device object for this instance of a
  406. UTB
  407. Return Value:
  408. NT status code
  409. --*/
  410. {
  411. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  412. NTSTATUS ntStatus;
  413. PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
  414. PURB urb;
  415. ULONG siz;
  416. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_StartDevice\n"));
  417. //
  418. // Fetch the device descriptor for the device
  419. //
  420. urb = USBDIAG_ExAllocatePool(NonPagedPool,
  421. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  422. if (urb)
  423. {
  424. siz = sizeof(USB_DEVICE_DESCRIPTOR);
  425. deviceDescriptor = USBDIAG_ExAllocatePool(NonPagedPool, siz);
  426. if (deviceDescriptor)
  427. {
  428. UsbBuildGetDescriptorRequest(urb,
  429. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  430. USB_DEVICE_DESCRIPTOR_TYPE,
  431. 0,
  432. 0,
  433. deviceDescriptor,
  434. NULL,
  435. siz,
  436. NULL);
  437. ntStatus = USBDIAG_CallUSBD(DeviceObject, urb);
  438. if (NT_SUCCESS(ntStatus))
  439. {
  440. //USBDIAG_KdPrint(("USBDIAG.SYS: Device Descriptor = %x, len %x\n",
  441. //deviceDescriptor,
  442. //urb->UrbControlDescriptorRequest.TransferBufferLength));
  443. //USBDIAG_KdPrint(("USBDIAG.SYS: USB Device Descriptor:\n"));
  444. //USBDIAG_KdPrint(("USBDIAG.SYS: -------------------------\n"));
  445. //USBDIAG_KdPrint(("USBDIAG.SYS: bLength %d\n", deviceDescriptor->bLength));
  446. //USBDIAG_KdPrint(("USBDIAG.SYS: bDescriptorType 0x%x\n", deviceDescriptor->bDescriptorType));
  447. //USBDIAG_KdPrint(("USBDIAG.SYS: bcdUSB 0x%x\n", deviceDescriptor->bcdUSB));
  448. //USBDIAG_KdPrint(("USBDIAG.SYS: bDeviceClass 0x%x\n", deviceDescriptor->bDeviceClass));
  449. //USBDIAG_KdPrint(("USBDIAG.SYS: bDeviceSubClass 0x%x\n", deviceDescriptor->bDeviceSubClass));
  450. //USBDIAG_KdPrint(("USBDIAG.SYS: bDeviceProtocol 0x%x\n", deviceDescriptor->bDeviceProtocol));
  451. //USBDIAG_KdPrint(("USBDIAG.SYS: bMaxPacketSize0 0x%x\n", deviceDescriptor->bMaxPacketSize0));
  452. //USBDIAG_KdPrint(("USBDIAG.SYS: idVendor 0x%x\n", deviceDescriptor->idVendor));
  453. //USBDIAG_KdPrint(("USBDIAG.SYS: idProduct 0x%x\n", deviceDescriptor->idProduct));
  454. //USBDIAG_KdPrint(("USBDIAG.SYS: bcdDevice 0x%x\n", deviceDescriptor->bcdDevice));
  455. //USBDIAG_KdPrint(("USBDIAG.SYS: iManufacturer 0x%x\n", deviceDescriptor->iManufacturer));
  456. //USBDIAG_KdPrint(("USBDIAG.SYS: iProduct 0x%x\n", deviceDescriptor->iProduct));
  457. //USBDIAG_KdPrint(("USBDIAG.SYS: iSerialNumber 0x%x\n", deviceDescriptor->iSerialNumber));
  458. //USBDIAG_KdPrint(("USBDIAG.SYS: bNumConfigurations 0x%x\n", deviceDescriptor->bNumConfigurations));
  459. }
  460. }
  461. else
  462. {
  463. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  464. }
  465. if (NT_SUCCESS(ntStatus))
  466. {
  467. deviceExtension->pDeviceDescriptor = deviceDescriptor;
  468. deviceExtension->Stopped = FALSE;
  469. }
  470. else if (deviceDescriptor)
  471. {
  472. USBDIAG_ExFreePool(deviceDescriptor);
  473. }
  474. USBDIAG_ExFreePool(urb);
  475. }
  476. else
  477. {
  478. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  479. }
  480. //USBDIAG_KdPrint(("USBDIAG.SYS: exit USBDIAG_StartDevice (%x)\n", ntStatus));
  481. return ntStatus;
  482. }
  483. NTSTATUS
  484. USBDIAG_QueryCapabilitiesCompletionRoutine(
  485. IN PDEVICE_OBJECT NullDeviceObject,
  486. IN PIRP Irp,
  487. IN PVOID Context
  488. )
  489. {
  490. PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT) Context;
  491. PDEVICE_EXTENSION deviceExtension = deviceObject->DeviceExtension;
  492. NTSTATUS ntStatus = STATUS_SUCCESS;
  493. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (Irp);
  494. ULONG ulPowerLevel;
  495. USBDIAG_KdPrint(("enter USBDIAG_QueryCapabilitiesCompletionRoutine (Irp->IoStatus.Status = 0x%x)\n", Irp->IoStatus.Status));
  496. // If the lower driver returned PENDING, mark our stack location as pending also.
  497. if (Irp->PendingReturned)
  498. {
  499. IoMarkIrpPending(Irp);
  500. }
  501. ASSERT(irpStack->MajorFunction == IRP_MJ_PNP);
  502. ASSERT(irpStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES);
  503. irpStack = IoGetCurrentIrpStackLocation (Irp);
  504. USBDIAG_KdPrint(("sizeof(DEVICE_CAPABILITIES) = %d (0x%x)\n",sizeof(DEVICE_CAPABILITIES),sizeof(DEVICE_CAPABILITIES)));
  505. // this is for Win2k
  506. irpStack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
  507. irpStack->Parameters.DeviceCapabilities.Capabilities->Removable = TRUE;
  508. RtlCopyMemory(&deviceExtension->DeviceCapabilities,
  509. irpStack->Parameters.DeviceCapabilities.Capabilities,
  510. sizeof(DEVICE_CAPABILITIES));
  511. // print out capabilities info
  512. USBDIAG_KdPrint(("************ Device Capabilites ************\n"));
  513. USBDIAG_KdPrint(("SystemWake = 0x%x\n", deviceExtension->DeviceCapabilities.SystemWake));
  514. USBDIAG_KdPrint(("DeviceWake = 0x%x\n", deviceExtension->DeviceCapabilities.DeviceWake));
  515. // USBDIAG_KdPrint(("SystemWake = %s\n",
  516. // SystemPowerStateString[deviceExtension->DeviceCapabilities.SystemWake]));
  517. // USBDIAG_KdPrint(("DeviceWake = %s\n",
  518. // DevicePowerStateString[deviceExtension->DeviceCapabilities.DeviceWake]));
  519. USBDIAG_KdPrint(("Device Address: 0x%x\n", deviceExtension->DeviceCapabilities.Address));
  520. for (ulPowerLevel=PowerSystemUnspecified; ulPowerLevel< PowerSystemMaximum; ulPowerLevel++)
  521. {
  522. // USBDIAG_KdPrint(("Dev State Map: sys st %s = dev st %s\n",
  523. // SystemPowerStateString[ulPowerLevel],
  524. // DevicePowerStateString[deviceExtension->DeviceCapabilities.DeviceState[ulPowerLevel]] ));
  525. }
  526. Irp->IoStatus.Status = STATUS_SUCCESS;
  527. return ntStatus;
  528. }
  529. NTSTATUS
  530. USBDIAG_StopDevice(
  531. IN PDEVICE_OBJECT DeviceObject
  532. )
  533. /*++
  534. Routine Description:
  535. Stops a given instance of a UTB device on the 82930.
  536. Arguments:
  537. DeviceObject - pointer to the device object for this instance of a 82930
  538. Return Value:
  539. NT status code
  540. --*/
  541. {
  542. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  543. NTSTATUS ntStatus = STATUS_SUCCESS;
  544. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_StopDevice\n"));
  545. if (deviceExtension->Stopped != TRUE)
  546. {
  547. ntStatus = USBDIAG_CancelAllIrps(deviceExtension);
  548. //
  549. // if we are already stopped then just exit
  550. //
  551. if (deviceExtension->pDeviceDescriptor)
  552. {
  553. USBDIAG_ExFreePool(deviceExtension->pDeviceDescriptor);
  554. deviceExtension->pDeviceDescriptor = NULL;
  555. }
  556. deviceExtension->Stopped = TRUE;
  557. }
  558. //USBDIAG_KdPrint(("USBDIAG.SYS: exit USBDIAG_StopDevice (%x)\n", ntStatus));
  559. return ntStatus;
  560. }
  561. NTSTATUS
  562. USBDIAG_PnPAddDevice(
  563. IN PDRIVER_OBJECT DriverObject,
  564. IN OUT PDEVICE_OBJECT PhysicalDeviceObject
  565. )
  566. /*++
  567. Routine Description:
  568. This routine is called to create a new instance of the device
  569. Arguments:
  570. DriverObject - pointer to the driver object for this instance of USBDIAG
  571. PhysicalDeviceObject - pointer to device object created by the bus
  572. Return Value:
  573. STATUS_SUCCESS if successful,
  574. STATUS_UNSUCCESSFUL otherwise
  575. --*/
  576. {
  577. NTSTATUS ntStatus = STATUS_SUCCESS;
  578. PDEVICE_OBJECT deviceObject = NULL;
  579. PDEVICE_EXTENSION deviceExtension, globalDeviceExtension = NULL;
  580. // PDEVICE_OBJECT tempdeviceObject = NULL;
  581. USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_PnPAddDevice\n"));
  582. //
  583. // Are we given the physical device object?
  584. //
  585. if (PhysicalDeviceObject) {
  586. if (USBDIAG_GlobalDeviceObject == NULL) {
  587. //USBDIAG_KdPrint(("USBDIAG.SYS: PnPAddDevice Creating Global Device Object\n"));
  588. ntStatus =
  589. USBDIAG_CreateDeviceObject(DriverObject, &USBDIAG_GlobalDeviceObject, TRUE);
  590. if (NT_SUCCESS(ntStatus)) {
  591. globalDeviceExtension = USBDIAG_GlobalDeviceObject->DeviceExtension;
  592. USBDIAG_GlobalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  593. globalDeviceExtension->DeviceList = NULL;
  594. globalDeviceExtension->OpenFRC = 0;
  595. }
  596. }
  597. else
  598. {
  599. globalDeviceExtension = USBDIAG_GlobalDeviceObject->DeviceExtension;
  600. }
  601. //
  602. // create our funtional device object (FDO)
  603. //
  604. if (NT_SUCCESS(ntStatus))
  605. {
  606. //USBDIAG_KdPrint(("USBDIAG.SYS: PnPAddDevice creating new USB device object\n"));
  607. ntStatus = USBDIAG_CreateDeviceObject(DriverObject, &deviceObject, FALSE);
  608. if (NT_SUCCESS(ntStatus))
  609. {
  610. //USBDIAG_KdPrint(("USBDIAG.SYS: PnPAddDevice DONE creating new USB device object\n"));
  611. }//if
  612. }
  613. if (NT_SUCCESS(ntStatus))
  614. {
  615. PDEVICE_LIST_ENTRY device;
  616. deviceExtension = deviceObject->DeviceExtension;
  617. RtlZeroMemory(deviceExtension->DeviceData, MAX_DOWNSTREAM_DEVICES * sizeof(PUSBD_DEVICE_DATA));
  618. // We support buffered I/O only
  619. deviceObject->Flags |= DO_BUFFERED_IO;
  620. //
  621. // remember the Physical device Object
  622. //
  623. deviceExtension->PhysicalDeviceObject=PhysicalDeviceObject;
  624. //
  625. // Attach to the PDO
  626. //
  627. //USBDIAG_KdPrint(("USBDIAG.SYS: PnPAddDevice attaching device to Stack.\n"));
  628. //
  629. // The stackdeviceobject is what we use to send Urbs down the stack
  630. //
  631. deviceExtension->StackDeviceObject =
  632. IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
  633. RtlZeroMemory(deviceExtension->DeviceData, MAX_DOWNSTREAM_DEVICES * sizeof(PUSBD_DEVICE_DATA));
  634. if ((deviceExtension->StackDeviceObject) != NULL)
  635. {
  636. //passed the IoAttachDeviceToDeviceStack call
  637. //USBDIAG_KdPrint(("USBDIAG.SYS: PnPAddDevice successfully attached device to stack\n"));
  638. USBDIAG_KdPrint(("USBDIAG.SYS: PnPAddDevice stackDevObj: %X\n",deviceExtension->StackDeviceObject));
  639. USBDIAG_KdPrint(("USBDIAG.SYS: Saving in deviceExtension 0x%x.\n",
  640. deviceExtension));
  641. if (gVersionInformation.USBDI_Version >= USBD_WIN98_SE_VERSION) // Win98 SE, Win2K and beyond
  642. {
  643. device = USBDIAG_ExAllocatePool(NonPagedPool, sizeof(DEVICE_LIST_ENTRY));
  644. if (device)
  645. {
  646. PDEVICE_OBJECT RootHubPdo = NULL;
  647. PDEVICE_OBJECT TopOfHcdStackDeviceObject = NULL;
  648. ASSERT(globalDeviceExtension != NULL);
  649. device->Next = globalDeviceExtension->DeviceList;
  650. globalDeviceExtension->DeviceList = device;
  651. device->DeviceNumber = USBDIAG_NextDeviceNumber++;
  652. device->PhysicalDeviceObject = PhysicalDeviceObject;
  653. device->DeviceObject = deviceObject;
  654. KeInitializeEvent(&deviceExtension->WaitWakeEvent, SynchronizationEvent, FALSE);
  655. // Get the RootHubPdo & TopOfHcdStackDeviceObject
  656. ntStatus = USBDIAG_SyncGetRootHubPdo(deviceExtension->StackDeviceObject,
  657. PhysicalDeviceObject,
  658. &RootHubPdo,
  659. &TopOfHcdStackDeviceObject);
  660. if (NT_SUCCESS(ntStatus))
  661. {
  662. ASSERT(RootHubPdo);
  663. deviceExtension->RootHubPdo = RootHubPdo;
  664. //ASSERT(TopOfHcdStackDeviceObject);
  665. //deviceExtension->TopOfHcdStackDeviceObject = TopOfHcdStackDeviceObject;
  666. }
  667. else
  668. {
  669. ASSERT(FALSE);
  670. deviceExtension->RootHubPdo = NULL;
  671. deviceExtension->TopOfHcdStackDeviceObject = NULL;
  672. }
  673. ntStatus = STATUS_SUCCESS;
  674. } //if device allocate was successful
  675. }
  676. }//if attach device was successful
  677. else
  678. {
  679. ntStatus = STATUS_NO_SUCH_DEVICE;
  680. //USBDIAG_KdPrint(("USBDIAG.SYS: PnPAddDevice FAILED attaching device to stack\n"));
  681. } //else attach failed
  682. }// if successfully created device object
  683. }
  684. else
  685. {
  686. //
  687. // Given no physical device object, therefore asked to do detection.
  688. // This is a dream on as all USB controller are PCI devices.
  689. //
  690. ntStatus = STATUS_NO_MORE_ENTRIES;
  691. }//else no PDO given
  692. //USBDIAG_KdPrint(("USBDIAG.SYS: exit USBDIAG_PnPAddDevice (%x)\n", ntStatus));
  693. if(NT_SUCCESS(ntStatus))
  694. USBDIAG_NumberDevices++;
  695. return ntStatus;
  696. }
  697. NTSTATUS
  698. USBDIAG_CreateDeviceObject(
  699. IN PDRIVER_OBJECT DriverObject,
  700. IN PDEVICE_OBJECT *DeviceObject,
  701. BOOLEAN Global
  702. )
  703. /*++
  704. Routine Description:
  705. Creates a Functional DeviceObject for the diag driver
  706. Arguments:
  707. DriverObject - pointer to the driver object for device
  708. DeviceObject - pointer to DeviceObject pointer to return
  709. created device object.
  710. Global - create the global device object and symbolic link.
  711. Return Value:
  712. STATUS_SUCCESS if successful,
  713. STATUS_UNSUCCESSFUL otherwise
  714. --*/
  715. {
  716. NTSTATUS ntStatus;
  717. WCHAR deviceLinkBuffer[] = L"\\DosDevices\\USBDIAG";
  718. UNICODE_STRING deviceLinkUnicodeString;
  719. WCHAR deviceNameBuffer[] = L"\\Device\\USBDIAG";
  720. UNICODE_STRING deviceNameUnicodeString;
  721. PDEVICE_EXTENSION deviceExtension;
  722. STRING deviceName;
  723. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_CreateDeviceObject\n"));
  724. //
  725. // fix up device names based on Instance
  726. //
  727. //USBDIAG_KdPrint(("USBDIAG.SYS: USBDIAG_CreateDeviceObject InitUnicode String\n"));
  728. RtlInitUnicodeString (&deviceNameUnicodeString,
  729. deviceNameBuffer);
  730. //USBDIAG_KdPrint(("USBDIAG.SYS: USBDIAG_CreateDeviceObject Convert unicode to ansi\n"));
  731. //Print out the unicode string
  732. deviceName.Buffer = NULL;
  733. ntStatus = RtlUnicodeStringToAnsiString (&deviceName,
  734. &deviceNameUnicodeString,
  735. TRUE);
  736. if (NT_SUCCESS(ntStatus)) {
  737. //USBDIAG_KdPrint(("USBDIAG.SYS: Create Device Name (%s)\n", deviceName.Buffer));
  738. RtlFreeAnsiString (&deviceName);
  739. if (!NT_SUCCESS(ntStatus)) {
  740. //USBDIAG_KdPrint(("USBDIAG.SYS: Failed freeing ansi string!\n"));
  741. }//if not successful ntstatus
  742. } else {
  743. //USBDIAG_KdPrint(("USBDIAG.SYS: Unicode to Ansi str failed w/ ntStatus: 0x%x\n",ntStatus));
  744. }
  745. //USBDIAG_KdPrint(("USBDIAG.SYS: USBDIAG_CreateDeviceObject IOCreateDevice \n"));
  746. ntStatus = IoCreateDevice (DriverObject,
  747. sizeof (DEVICE_EXTENSION),
  748. Global ? &deviceNameUnicodeString : NULL,
  749. FILE_DEVICE_UNKNOWN,
  750. 0,
  751. FALSE,
  752. DeviceObject);
  753. if (NT_SUCCESS(ntStatus)) {
  754. //
  755. // Initialize our device extension
  756. //
  757. deviceExtension = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);
  758. if (Global)
  759. {
  760. RtlInitUnicodeString (&deviceLinkUnicodeString,
  761. deviceLinkBuffer);
  762. //USBDIAG_KdPrint(("USBDIAG.SYS: Global: Create DosDevice name (%s)\n", deviceLinkBuffer));
  763. ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
  764. &deviceNameUnicodeString);
  765. RtlCopyMemory(deviceExtension->DeviceLinkNameBuffer,
  766. deviceLinkBuffer,
  767. sizeof(deviceLinkBuffer));
  768. }//if Global
  769. else
  770. {
  771. deviceExtension->Stopped = TRUE;
  772. (*DeviceObject)->Flags |= DO_POWER_PAGABLE;
  773. (*DeviceObject)->Flags &= ~DO_DEVICE_INITIALIZING;
  774. }//else
  775. //Setup the ptr to the device extension for this device & init the Irp field (for now)
  776. //deviceExtension->IrpHead = NULL;
  777. InitializeListHead(&deviceExtension->ListHead);
  778. KeInitializeSpinLock(&deviceExtension->SpinLock);
  779. KeInitializeEvent(&deviceExtension->CancelEvent, NotificationEvent, FALSE);
  780. // this event is triggered when self-requested power irps complete
  781. //KeInitializeEvent(&deviceExtension->SelfRequestedPowerIrpEvent, NotificationEvent, FALSE);
  782. deviceExtension->SelfRequestedPowerIrpEvent = NULL;
  783. // initialize original power level as fully on
  784. deviceExtension->CurrentDeviceState.DeviceState = PowerDeviceD0;
  785. deviceExtension->CurrentSystemState.SystemState = PowerSystemWorking;
  786. deviceExtension->WaitWakeIrp = NULL;
  787. deviceExtension->InterruptIrp = NULL;
  788. }//if ntsuccess
  789. //USBDIAG_KdPrint(("USBDIAG.SYS: exit USBDIAG_CreateDeviceObject (%x)\n", ntStatus));
  790. return ntStatus;
  791. }
  792. NTSTATUS
  793. USBDIAG_CallUSBD(
  794. IN PDEVICE_OBJECT DeviceObject,
  795. IN PURB Urb
  796. )
  797. /*++
  798. Routine Description:
  799. Passes a URB to the USBD class driver
  800. Arguments:
  801. DeviceObject - pointer to the device object for this instance of an 82930
  802. Urb - pointer to Urb request block
  803. Return Value:
  804. STATUS_SUCCESS if successful,
  805. STATUS_UNSUCCESSFUL otherwise
  806. --*/
  807. {
  808. NTSTATUS ntStatus, status = STATUS_SUCCESS;
  809. PDEVICE_EXTENSION deviceExtension;
  810. PIRP irp;
  811. KEVENT event;
  812. IO_STATUS_BLOCK ioStatus;
  813. PIO_STACK_LOCATION nextStack;
  814. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_CallUSBD\n"));
  815. deviceExtension = DeviceObject->DeviceExtension;
  816. //
  817. // issue a synchronous request
  818. //
  819. KeInitializeEvent(&event, NotificationEvent, FALSE);
  820. irp = IoBuildDeviceIoControlRequest(
  821. IOCTL_INTERNAL_USB_SUBMIT_URB,
  822. deviceExtension->StackDeviceObject,
  823. NULL,
  824. 0,
  825. NULL,
  826. 0,
  827. TRUE, /* INTERNAL */
  828. &event,
  829. &ioStatus);
  830. //
  831. // Call the class driver to perform the operation. If the returned status
  832. // is PENDING, wait for the request to complete.
  833. //
  834. nextStack = IoGetNextIrpStackLocation(irp);
  835. ASSERT(nextStack != NULL);
  836. //
  837. // pass the URB to the USB driver stack
  838. //
  839. nextStack->Parameters.Others.Argument1 = Urb;
  840. //USBDIAG_KdPrint(("USBDIAG.SYS: calling USBD\n"));
  841. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  842. irp);
  843. //USBDIAG_KdPrint(("USBDIAG.SYS: return from IoCallDriver USBD %x\n", ntStatus));
  844. {
  845. KIRQL irql;
  846. irql = KeGetCurrentIrql();
  847. ASSERT(irql <= PASSIVE_LEVEL);
  848. }
  849. if (ntStatus == STATUS_PENDING) {
  850. //USBDIAG_KdPrint(("USBDIAG.SYS: Wait for single object\n"));
  851. status = KeWaitForSingleObject(
  852. &event,
  853. Suspended,
  854. KernelMode,
  855. FALSE,
  856. NULL);
  857. //USBDIAG_KdPrint(("USBDIAG.SYS: Wait for single object, returned %x\n", status));
  858. } else {
  859. ioStatus.Status = ntStatus;
  860. }
  861. //USBDIAG_KdPrint(("USBDIAG.SYS: URB status = %x status = %x irp status %x\n",
  862. // Urb->UrbHeader.Status, status, ioStatus.Status));
  863. //
  864. // USBD maps the error code for us
  865. //
  866. ntStatus = ioStatus.Status;
  867. //USBDIAG_KdPrint(("USBDIAG.SYS: exit USBDIAG_CallUSBD (%x)\n", ntStatus));
  868. return ntStatus;
  869. }
  870. NTSTATUS
  871. USBDIAG_RemoveGlobalDeviceObject(
  872. )
  873. /*++
  874. Routine Description:
  875. Arguments:
  876. Return Value:
  877. STATUS_SUCCESS if successful,
  878. STATUS_UNSUCCESSFUL otherwise
  879. --*/
  880. {
  881. NTSTATUS ntStatus = STATUS_SUCCESS;
  882. PDEVICE_EXTENSION globalDeviceExtension;
  883. UNICODE_STRING deviceLinkUnicodeString;
  884. KIRQL irql;
  885. //USBDIAG_KdPrint(("USBDIAG.SYS: enter USBDIAG_RemoveGlobalDeviceObjec\n"));
  886. irql = KeGetCurrentIrql();
  887. ASSERT(irql <= PASSIVE_LEVEL);
  888. if (USBDIAG_GlobalDeviceObject != NULL) {
  889. globalDeviceExtension = USBDIAG_GlobalDeviceObject->DeviceExtension;
  890. //USBDIAG_KdPrint(("USBDIAG.SYS: USBDIAG_RemoveGlobalDeviceObject open frc = %x, list = %x\n",
  891. //globalDeviceExtension->OpenFRC,
  892. //globalDeviceExtension->DeviceList));
  893. if ( globalDeviceExtension->DeviceList == NULL &&
  894. globalDeviceExtension->OpenFRC == 0) {
  895. //USBDIAG_KdPrint(("USBDIAG.SYS: Deleting global device object\n"));
  896. // delete our global device object once we have no more devices
  897. RtlInitUnicodeString (&deviceLinkUnicodeString,
  898. globalDeviceExtension->DeviceLinkNameBuffer);
  899. //USBDIAG_KdPrint(("USBDIAG.SYS: Deleting Symbolic Link (UnicodeStr) at addr %X\n",
  900. //&deviceLinkUnicodeString));
  901. ntStatus = IoDeleteSymbolicLink(&deviceLinkUnicodeString);
  902. if (NT_SUCCESS(ntStatus)) {
  903. //USBDIAG_KdPrint(("USBDIAG.SYS: Deleting Global Device Object at addr %X\n",
  904. // USBDIAG_GlobalDeviceObject));
  905. IoDeleteDevice( USBDIAG_GlobalDeviceObject );
  906. USBDIAG_GlobalDeviceObject = NULL;
  907. //USBDIAG_KdPrint(("USBDIAG.SYS: Successfully Deleted Global Device Object\n"));
  908. }
  909. }
  910. }
  911. return ntStatus;
  912. }
  913. #define MEM_SIGNATURE ((ULONG) 'CLLA')
  914. #define MEM_FREED_SIGNATURE ((ULONG) 'EERF')
  915. PVOID
  916. USBDIAG_ExAllocatePool(
  917. IN POOL_TYPE PoolType,
  918. IN ULONG NumberOfBytes
  919. )
  920. {
  921. PULONG pMem;
  922. // allocate memory plus a little extra for our own use
  923. pMem = ExAllocatePool(PoolType, NumberOfBytes + (2 * sizeof(ULONG)));
  924. // see if we actually allocated any memory
  925. if(pMem)
  926. {
  927. // store number of bytes allocated at start of memory allocated
  928. *pMem++ = NumberOfBytes;
  929. // now we are pointing at the memory allocated for caller
  930. // put signature word at end
  931. // get new pointer that points to end of buffer - ULONG
  932. pMem = (PULONG) (((PUCHAR) pMem) + NumberOfBytes);
  933. // write signature
  934. *pMem = MEM_SIGNATURE;
  935. // get back pointer to return to caller
  936. pMem = (PULONG) (((PUCHAR) pMem) - NumberOfBytes);
  937. gulMemoryAllocated += NumberOfBytes;
  938. //USBDIAG_KdPrint(("USBDIAG_ExAllocatePool: bytes allocated: %d\n", gulMemoryAllocated));
  939. }
  940. return (PVOID) pMem;
  941. }
  942. VOID
  943. USBDIAG_ExFreePool(
  944. IN PVOID P
  945. )
  946. {
  947. PULONG pTmp = (PULONG) P;
  948. ULONG buffSize;
  949. //PULONG pSav=pTmp;
  950. // point at size ULONG at start of buffer, and address to free
  951. pTmp--;
  952. // get the size of memory allocated by caller
  953. buffSize = *pTmp;
  954. // point at signature and make sure it's O.K.
  955. ((PCHAR) P) += buffSize;
  956. if(*((PULONG) P) == MEM_SIGNATURE)
  957. {
  958. // let's go ahead and get rid of signature in case we get called
  959. // with this pointer again and memory is still paged in
  960. *((PULONG) P) = MEM_FREED_SIGNATURE;
  961. // free real pointer
  962. ExFreePool(pTmp);
  963. gulMemoryAllocated -= buffSize;
  964. //USBDIAG_KdPrint(("USBDIAG_ExFreePool: bytes allocated: %d\n", gulMemoryAllocated));
  965. }
  966. else {
  967. TRAP();
  968. }//else
  969. }
  970. NTSTATUS
  971. USBDIAG_ResetParentPort(
  972. IN PDEVICE_OBJECT DeviceObject
  973. )
  974. /*++
  975. Routine Description:
  976. Reset the our parent port
  977. Arguments:
  978. Return Value:
  979. STATUS_SUCCESS if successful,
  980. STATUS_UNSUCCESSFUL otherwise
  981. --*/
  982. {
  983. NTSTATUS ntStatus, status = STATUS_SUCCESS;
  984. PIRP irp;
  985. KEVENT event;
  986. IO_STATUS_BLOCK ioStatus;
  987. PIO_STACK_LOCATION nextStack;
  988. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;//USBDIAG_GlobalDeviceObject->DeviceExtension;
  989. USBDIAG_KdPrint(("enter USBDIAG_ResetParentPort\n"));
  990. ASSERT(deviceExtension);
  991. ASSERT(deviceExtension->StackDeviceObject);
  992. if (!deviceExtension->StackDeviceObject)
  993. return STATUS_UNSUCCESSFUL;
  994. //
  995. // issue a synchronous request
  996. //
  997. KeInitializeEvent(&event, NotificationEvent, FALSE);
  998. irp = IoBuildDeviceIoControlRequest(
  999. IOCTL_INTERNAL_USB_RESET_PORT,
  1000. deviceExtension->StackDeviceObject,
  1001. NULL,
  1002. 0,
  1003. NULL,
  1004. 0,
  1005. TRUE, /* INTERNAL */
  1006. &event,
  1007. &ioStatus);
  1008. //
  1009. // Call the class driver to perform the operation. If the returned status
  1010. // is PENDING, wait for the request to complete.
  1011. //
  1012. nextStack = IoGetNextIrpStackLocation(irp);
  1013. ASSERT(nextStack != NULL);
  1014. USBDIAG_KdPrint(("USBDIAG_ResetParentPort() calling USBD enable port api\n"));
  1015. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  1016. irp);
  1017. USBDIAG_KdPrint(("USBDIAG_ResetParentPort() return from IoCallDriver USBD %x\n", ntStatus));
  1018. if (ntStatus == STATUS_PENDING)
  1019. {
  1020. USBDIAG_KdPrint(("USBDIAG_ResetParentPort() Wait for single object\n"));
  1021. status = KeWaitForSingleObject(
  1022. &event,
  1023. Suspended,
  1024. KernelMode,
  1025. FALSE,
  1026. NULL);
  1027. USBDIAG_KdPrint(("USBDIAG_ResetParentPort() Wait for single object, returned %x\n", status));
  1028. }
  1029. else
  1030. {
  1031. ioStatus.Status = ntStatus;
  1032. }
  1033. //
  1034. // USBD maps the error code for us
  1035. //
  1036. ntStatus = ioStatus.Status;
  1037. USBDIAG_KdPrint(("Exit USBDIAG_ResetPort (%x)\n", ntStatus));
  1038. return ntStatus;
  1039. }
  1040. // *************************************
  1041. PWCHAR
  1042. GetString(PWCHAR pwc, BOOLEAN MultiSZ);
  1043. // **************************************************************************
  1044. // **************************************************************************
  1045. // downstream manipulation routines
  1046. NTSTATUS
  1047. USBDIAG_RemoveDownstreamDevice(
  1048. IN PUSBD_DEVICE_DATA DeviceData,
  1049. IN PDEVICE_OBJECT DeviceObject
  1050. )
  1051. {
  1052. NTSTATUS ntStatus = STATUS_SUCCESS;
  1053. PUSBD_PIPE defaultPipe = &DeviceData->DefaultPipe;
  1054. //USBDIAG_KdPrint(("- USBDIAG_RemoveDownstreamDevice calling USBD_CloseEndpoint -\n"));
  1055. ntStatus = USBD_CloseEndpoint(DeviceData,
  1056. DeviceObject,
  1057. defaultPipe,
  1058. NULL);
  1059. DeviceData = NULL;
  1060. return ntStatus;
  1061. }
  1062. NTSTATUS
  1063. USBDIAG_Chap11SetConfiguration(
  1064. IN PUSBD_DEVICE_DATA DeviceData,
  1065. IN PDEVICE_OBJECT DeviceObject
  1066. )
  1067. {
  1068. NTSTATUS ntStatus = STATUS_SUCCESS;
  1069. ASSERT(DeviceObject);
  1070. USBDIAG_KdPrint(("USBDIAG_Chap11SetConfiguration: DeviceData 0x%x (& 0x%x), DeviceObject 0x%x\n",
  1071. *DeviceData,
  1072. DeviceData,
  1073. DeviceObject));
  1074. ntStatus = USBD_SendCommand(DeviceData,
  1075. DeviceObject,
  1076. STANDARD_COMMAND_SET_CONFIGURATION,
  1077. 0x01, // wValue = 1
  1078. 0, // wIndex = 0
  1079. 0, // wLength = 0
  1080. NULL,
  1081. 0,
  1082. NULL,
  1083. NULL);
  1084. return ntStatus;
  1085. }
  1086. NTSTATUS
  1087. USBDIAG_Chap11EnableRemoteWakeup(
  1088. IN PUSBD_DEVICE_DATA DeviceData,
  1089. IN PDEVICE_OBJECT DeviceObject
  1090. )
  1091. {
  1092. NTSTATUS ntStatus = STATUS_SUCCESS;
  1093. ASSERT(DeviceData);
  1094. USBDIAG_KdPrint(("USBDIAG_Chap11EnableRemoteWakeup: DeviceData 0x%x (& 0x%x), DeviceObject 0x%x\n",
  1095. *DeviceData,
  1096. DeviceData,
  1097. DeviceObject));
  1098. ntStatus = USBD_SendCommand(DeviceData,
  1099. DeviceObject,
  1100. STANDARD_COMMAND_SET_DEVICE_FEATURE,
  1101. 0x01, // wValue = 2 for rwu
  1102. 0, // wIndex = 0
  1103. 0, // wLength = 0
  1104. NULL,
  1105. 0,
  1106. NULL,
  1107. NULL);
  1108. return ntStatus;
  1109. }
  1110. NTSTATUS
  1111. USBDIAG_Chap11SendPacketDownstream(
  1112. IN PUSBD_DEVICE_DATA DeviceData,
  1113. IN PDEVICE_OBJECT DeviceObject,
  1114. IN PREQ_SEND_PACKET_DOWNSTREAM pSendPacketDownstream
  1115. )
  1116. {
  1117. NTSTATUS ntStatus = STATUS_SUCCESS;
  1118. PCHAP11_SETUP_PACKET pSetupPacket = &pSendPacketDownstream->SetupPacket;
  1119. PUCHAR pucTempBuffer = NULL;
  1120. if (pSetupPacket->wLength)
  1121. {
  1122. pucTempBuffer = ExAllocatePool(NonPagedPool, pSetupPacket->wLength);
  1123. if (!pucTempBuffer)
  1124. return STATUS_INSUFFICIENT_RESOURCES;
  1125. }
  1126. ASSERT(DeviceData);
  1127. ntStatus = USBD_SendCommand(DeviceData,
  1128. DeviceObject,
  1129. pSetupPacket->wRequest,
  1130. pSetupPacket->wValue,
  1131. pSetupPacket->wIndex,
  1132. pSetupPacket->wLength,
  1133. pucTempBuffer,
  1134. pSetupPacket->wLength,
  1135. &pSendPacketDownstream->dwBytes,
  1136. &pSendPacketDownstream->ulUrbStatus);
  1137. if (NT_SUCCESS(ntStatus) && pSetupPacket->wLength && pSendPacketDownstream->pucBuffer)
  1138. {
  1139. RtlCopyMemory(pSendPacketDownstream->pucBuffer, pucTempBuffer, pSendPacketDownstream->dwBytes);
  1140. }
  1141. if (pSetupPacket->wLength && pSendPacketDownstream->pucBuffer && pucTempBuffer)
  1142. {
  1143. ExFreePool(pucTempBuffer);
  1144. pucTempBuffer = NULL;
  1145. }
  1146. return ntStatus;
  1147. }
  1148. NTSTATUS
  1149. USBDIAG_CreateInitDownstreamDevice(
  1150. PREQ_ENUMERATE_DOWNSTREAM_DEVICE pEnumerate,
  1151. PDEVICE_EXTENSION deviceExtension
  1152. )
  1153. {
  1154. NTSTATUS ntStatus = STATUS_SUCCESS;
  1155. UCHAR ucPortNumber = pEnumerate->ucPortNumber;
  1156. PUSBD_DEVICE_DATA DeviceData = NULL;
  1157. BOOLEAN bLowSpeed = pEnumerate->bLowSpeed;
  1158. ULONG MaxPacketSize0 = 8;
  1159. ULONG DeviceHackFlags;
  1160. PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
  1161. ULONG deviceDescriptorLength = 0;
  1162. PUSB_CONFIGURATION_DESCRIPTOR configDescriptor = NULL;
  1163. ULONG configDescriptorLength = 0;
  1164. if (deviceExtension->DeviceData[ucPortNumber])
  1165. return STATUS_SUCCESS;
  1166. USBDIAG_KdPrint(("***************************************************\n"));
  1167. USBDIAG_KdPrint(("USBDIAG.SYS: REQ_FUNCTION_CHAP11_CREATE_USBD_DEVICE\n"));
  1168. USBDIAG_KdPrint(("- Downstream device:\n"));
  1169. USBDIAG_KdPrint(("- Port: %d\n", pEnumerate->ucPortNumber));
  1170. USBDIAG_KdPrint(("- Lowspeed: %d\n", pEnumerate->bLowSpeed));
  1171. if (!deviceExtension->RootHubPdo)
  1172. return STATUS_INVALID_PARAMETER;
  1173. ntStatus = USBD_CreateDevice(&DeviceData,
  1174. deviceExtension->RootHubPdo,
  1175. bLowSpeed,
  1176. MaxPacketSize0,
  1177. &DeviceHackFlags);
  1178. USBDIAG_KdPrint(("* After USBD_CreateDevice, DeviceData = 0x%x\n", DeviceData));
  1179. if (NT_SUCCESS(ntStatus))
  1180. {
  1181. ASSERT(DeviceData);
  1182. //USBDIAG_KdPrint(("deviceExtension->DeviceData[%d] = 0x%x\n", deviceExtension->DeviceData[ucPortNumber]));
  1183. deviceDescriptorLength = sizeof(USB_DEVICE_DESCRIPTOR);
  1184. deviceDescriptor = ExAllocatePool(NonPagedPool, deviceDescriptorLength);
  1185. if (!deviceDescriptor)
  1186. {
  1187. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1188. }
  1189. else
  1190. {
  1191. configDescriptorLength = 0xFF;
  1192. configDescriptor = ExAllocatePool(NonPagedPool, configDescriptorLength);
  1193. }
  1194. if (!configDescriptor)
  1195. {
  1196. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1197. }
  1198. }
  1199. if (NT_SUCCESS(ntStatus))
  1200. {
  1201. USBDIAG_KdPrint(("== Chap9Control calling USBD_InitializeDevice ==\n"));
  1202. ntStatus = USBD_InitializeDevice(DeviceData,
  1203. deviceExtension->RootHubPdo,
  1204. deviceDescriptor,
  1205. deviceDescriptorLength,
  1206. configDescriptor,
  1207. configDescriptorLength);
  1208. }
  1209. if (NT_SUCCESS(ntStatus))
  1210. {
  1211. deviceExtension->DeviceData[ucPortNumber] = DeviceData;
  1212. USBDIAG_KdPrint(("SAVING...\n"));
  1213. USBDIAG_KdPrint(("PortNumber: %d\n", ucPortNumber));
  1214. USBDIAG_KdPrint(("DeviceData: 0x%x\n", DeviceData));
  1215. if (configDescriptor)
  1216. {
  1217. deviceExtension->DownstreamConfigDescriptor[ucPortNumber] = configDescriptor;
  1218. }
  1219. else
  1220. {
  1221. USBDIAG_KdPrint(("configDescriptor after USBD_InitializeDevice is NULL\n!"));
  1222. }
  1223. //USBDIAG_KdPrint(("deviceExtension->DeviceData[%d]: 0x%x\n",
  1224. //ucPortNumber,
  1225. //deviceExtension->DeviceData[ucPortNumber]));
  1226. //USBDIAG_KdPrint(("deviceExtension: 0x%x\n", deviceExtension));
  1227. //USBDIAG_KdPrint(("deviceExtension->DeviceData: 0x%x\n",
  1228. //deviceExtension->DeviceData));
  1229. //USBDIAG_KdPrint(("&deviceExtension->DeviceData[0]: 0x%x\n",
  1230. //&deviceExtension->DeviceData[0]));
  1231. //USBDIAG_KdPrint(("&deviceExtension->DeviceData[%d]: 0x%x\n",
  1232. //ucPortNumber,
  1233. //&deviceExtension->DeviceData[ucPortNumber]));
  1234. }
  1235. if (!deviceExtension->DeviceData[ucPortNumber])
  1236. {
  1237. USBDIAG_KdPrint(("Attempt to create/init downstream device FAILED!\n"));
  1238. ntStatus = STATUS_UNSUCCESSFUL;
  1239. }
  1240. return ntStatus;
  1241. }
  1242. NTSTATUS
  1243. USBDIAG_SetCfgEnableRWu(
  1244. PDEVICE_EXTENSION deviceExtension,
  1245. PREQ_ENUMERATE_DOWNSTREAM_DEVICE pEnumerate
  1246. )
  1247. {
  1248. UCHAR ucPortNumber = pEnumerate->ucPortNumber;
  1249. PUSBD_DEVICE_DATA DeviceData = deviceExtension->DeviceData[ucPortNumber];
  1250. NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
  1251. PUSB_CONFIGURATION_DESCRIPTOR configDescriptor = deviceExtension->DownstreamConfigDescriptor[ucPortNumber];
  1252. USBDIAG_KdPrint(("*************************************************\n"));
  1253. USBDIAG_KdPrint(("USBDIAG.SYS: REQ_FUNCTION_CHAP11_INIT_USBD_DEVICE\n"));
  1254. USBDIAG_KdPrint(("PortNumber: %d\n", ucPortNumber));
  1255. USBDIAG_KdPrint(("DeviceData: 0x%x\n", DeviceData));
  1256. USBDIAG_KdPrint(("deviceExtension->DeviceData[%d]: 0x%x\n",
  1257. ucPortNumber,
  1258. deviceExtension->DeviceData[ucPortNumber]));
  1259. ASSERT(deviceExtension->RootHubPdo);
  1260. ASSERT(DeviceData);
  1261. USBDIAG_KdPrint(("- Chap9Control calling USBDIAG_Chap11SetConfiguration -\n"));
  1262. if (DeviceData)
  1263. {
  1264. ntStatus = USBDIAG_Chap11SetConfiguration(DeviceData,
  1265. deviceExtension->RootHubPdo);
  1266. USBDIAG_KdPrint(("Set Config On Downstream Device On Port %d %s\n",
  1267. ucPortNumber,
  1268. NT_SUCCESS(ntStatus) ? "Passed" : "FAILED"));
  1269. if (NT_SUCCESS(ntStatus))
  1270. {
  1271. if (configDescriptor->bmAttributes & REMOTE_WAKEUP)
  1272. {
  1273. USBDIAG_KdPrint((" Chap9Control calling USBDIAG_Chap11EnableRemoteWakeup -\n"));
  1274. ntStatus = USBDIAG_Chap11EnableRemoteWakeup(DeviceData,
  1275. //deviceExtension->StackDeviceObject);
  1276. deviceExtension->RootHubPdo);
  1277. USBDIAG_KdPrint(("Enable RWu On Downstream Device On Port %d %s\n",
  1278. ucPortNumber,
  1279. NT_SUCCESS(ntStatus) ? "Passed" : "FAILED"));
  1280. }
  1281. }
  1282. }
  1283. return ntStatus;
  1284. }
  1285. NTSTATUS
  1286. USBD_SendCommand(
  1287. IN PUSBD_DEVICE_DATA DeviceData,
  1288. IN PDEVICE_OBJECT DeviceObject,
  1289. IN USHORT RequestCode,
  1290. IN USHORT WValue,
  1291. IN USHORT WIndex,
  1292. IN USHORT WLength,
  1293. IN PVOID Buffer,
  1294. IN ULONG BufferLength,
  1295. OUT PULONG BytesReturned,
  1296. OUT USBD_STATUS *UsbStatus
  1297. )
  1298. /*++
  1299. Routine Description:
  1300. Send a standard USB command on the default pipe.
  1301. Arguments:
  1302. DeviceData - ptr to USBD device structure the command will be sent to
  1303. DeviceObject -
  1304. RequestCode -
  1305. WValue - wValue for setup packet
  1306. WIndex - wIndex for setup packet
  1307. WLength - wLength for setup packet
  1308. Buffer - Input/Output Buffer for command
  1309. BufferLength - Length of Input/Output buffer.
  1310. BytesReturned - pointer to ulong to copy number of bytes
  1311. returned (optional)
  1312. UsbStatus - USBD status code returned in the URB.
  1313. Return Value:
  1314. STATUS_SUCCESS if successful,
  1315. STATUS_UNSUCCESSFUL otherwise
  1316. --*/
  1317. {
  1318. NTSTATUS ntStatus;
  1319. PHCD_URB urb = NULL;
  1320. PUSBD_PIPE defaultPipe = &(DeviceData->DefaultPipe);
  1321. PUSB_STANDARD_SETUP_PACKET setupPacket;
  1322. PUSBD_EXTENSION deviceExtension;
  1323. PAGED_CODE();
  1324. //USBDIAG_KdPrint(("enter USBD_SendCommand\n"));
  1325. ASSERT_DEVICE(DeviceData);
  1326. deviceExtension = DeviceObject->DeviceExtension;
  1327. if (deviceExtension->DeviceHackFlags &
  1328. USBD_DEVHACK_SLOW_ENUMERATION) {
  1329. //
  1330. // if noncomplience switch is on in the
  1331. // registry we'll pause here to give the
  1332. // device a chance to respond.
  1333. //
  1334. LARGE_INTEGER deltaTime;
  1335. deltaTime.QuadPart = 100 * -10000;
  1336. (VOID) KeDelayExecutionThread(KernelMode,
  1337. FALSE,
  1338. &deltaTime);
  1339. }
  1340. urb = ExAllocatePool(NonPagedPool,
  1341. sizeof(struct _URB_CONTROL_TRANSFER));
  1342. if (!urb) {
  1343. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1344. } else {
  1345. urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_TRANSFER);
  1346. urb->UrbHeader.Function = URB_FUNCTION_CONTROL_TRANSFER;
  1347. setupPacket = (PUSB_STANDARD_SETUP_PACKET)
  1348. urb->HcdUrbCommonTransfer.Extension.u.SetupPacket;
  1349. setupPacket->RequestCode = RequestCode;
  1350. setupPacket->wValue = WValue;
  1351. setupPacket->wIndex = WIndex;
  1352. setupPacket->wLength = WLength;
  1353. urb->HcdUrbCommonTransfer.hca.HcdEndpoint = defaultPipe->HcdEndpoint;
  1354. urb->HcdUrbCommonTransfer.TransferFlags = USBD_SHORT_TRANSFER_OK;
  1355. // USBD is responsible for setting the transfer direction
  1356. //
  1357. // TRANSFER direction is implied in the command
  1358. if (RequestCode & USB_DEVICE_TO_HOST)
  1359. USBD_SET_TRANSFER_DIRECTION_IN(urb->HcdUrbCommonTransfer.TransferFlags);
  1360. else
  1361. USBD_SET_TRANSFER_DIRECTION_OUT(urb->HcdUrbCommonTransfer.TransferFlags);
  1362. urb->HcdUrbCommonTransfer.TransferBufferLength = BufferLength;
  1363. urb->HcdUrbCommonTransfer.TransferBuffer = Buffer;
  1364. urb->HcdUrbCommonTransfer.TransferBufferMDL = NULL;
  1365. urb->HcdUrbCommonTransfer.UrbLink = NULL;
  1366. //USBDIAG_KdPrint(("SendCommand cmd = 0x%x buffer = 0x%x length = 0x%x direction = 0x%x\n",
  1367. //setupPacket->RequestCode,
  1368. //urb->HcdUrbCommonTransfer.TransferBuffer,
  1369. //urb->HcdUrbCommonTransfer.TransferBufferLength,
  1370. //urb->HcdUrbCommonTransfer.TransferFlags
  1371. //));
  1372. ntStatus = USBD_SubmitSynchronousURB((PURB)urb, DeviceObject, DeviceData);
  1373. if (BytesReturned) {
  1374. *BytesReturned = urb->HcdUrbCommonTransfer.TransferBufferLength;
  1375. }
  1376. if (UsbStatus) {
  1377. *UsbStatus = urb->HcdUrbCommonTransfer.Status;
  1378. }
  1379. // free the transfer URB
  1380. ExFreePool(urb);
  1381. }
  1382. //USBDIAG_KdPrint(("exit USBD_SendCommand 0x%x\n", ntStatus));
  1383. return ntStatus;
  1384. }
  1385. NTSTATUS
  1386. USBD_CloseEndpoint(
  1387. IN PUSBD_DEVICE_DATA DeviceData,
  1388. IN PDEVICE_OBJECT DeviceObject,
  1389. IN PUSBD_PIPE PipeHandle,
  1390. IN OUT USBD_STATUS *UsbStatus
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. Close an Endpoint
  1395. Arguments:
  1396. DeviceData - ptr to USBD device data structure.
  1397. DeviceObject - USBD device object.
  1398. PipeHandle - USBD pipe handle associated with the endpoint.
  1399. Return Value:
  1400. STATUS_SUCCESS if successful,
  1401. STATUS_UNSUCCESSFUL otherwise
  1402. --*/
  1403. {
  1404. NTSTATUS ntStatus;
  1405. PHCD_URB urb;
  1406. PUSBD_EXTENSION deviceExtension;
  1407. PAGED_CODE();
  1408. //USBDIAG_KdPrint(("enter USBD_CloseEndpoint\n"));
  1409. ASSERT_DEVICE(DeviceData);
  1410. deviceExtension = DeviceObject->DeviceExtension;
  1411. urb = ExAllocatePool(NonPagedPool,
  1412. sizeof(struct _URB_HCD_CLOSE_ENDPOINT));
  1413. if (!urb) {
  1414. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1415. } else {
  1416. urb->UrbHeader.Length = sizeof(struct _URB_HCD_CLOSE_ENDPOINT);
  1417. urb->UrbHeader.Function = URB_FUNCTION_HCD_CLOSE_ENDPOINT;
  1418. urb->HcdUrbCloseEndpoint.HcdEndpoint = PipeHandle->HcdEndpoint;
  1419. //
  1420. // Serialize Close Endpoint requests
  1421. //
  1422. ntStatus = USBD_SubmitSynchronousURB((PURB) urb, DeviceObject,
  1423. DeviceData);
  1424. if (UsbStatus)
  1425. *UsbStatus = urb->UrbHeader.Status;
  1426. ExFreePool(urb);
  1427. }
  1428. //USBDIAG_KdPrint(("exit USBD_CloseEndpoint 0x%x\n", ntStatus));
  1429. return ntStatus;
  1430. }
  1431. // downstream manipulation routines done
  1432. // **************************************************************************
  1433. // **************************************************************************
  1434. NTSTATUS
  1435. USBDIAG_WaitForWakeup(
  1436. PDEVICE_EXTENSION deviceExtension
  1437. )
  1438. {
  1439. NTSTATUS ntStatus;
  1440. USBDIAG_KdPrint(("'USBDIAG_WaitForWakeup: Waiting for Wait/Wake completion event\n"));
  1441. USBDIAG_KdPrint(("Waiting for WaitWakeEvent...\n"));
  1442. ntStatus = KeWaitForSingleObject(&deviceExtension->WaitWakeEvent,
  1443. Suspended,
  1444. KernelMode,
  1445. FALSE,
  1446. NULL);
  1447. USBDIAG_KdPrint(("'WaitWakeEvent Signalled, Clearing ...\n"));
  1448. KeClearEvent(&deviceExtension->WaitWakeEvent);
  1449. return ntStatus;
  1450. }
  1451. PWCHAR
  1452. GetString(PWCHAR pwc, BOOLEAN MultiSZ)
  1453. {
  1454. PWCHAR psz, p;
  1455. SIZE_T Size;
  1456. PAGED_CODE();
  1457. psz=pwc;
  1458. while (*psz!='\0' || (MultiSZ && *(psz+1)!='\0')) {
  1459. psz++;
  1460. }
  1461. Size=(psz-pwc+1+(MultiSZ ? 1: 0))*sizeof(*pwc);
  1462. // We use pool here because these pointers are passed
  1463. // to the PnP code who is responsible for freeing them
  1464. if ((p=ExAllocatePool(PagedPool, Size))!=NULL) {
  1465. RtlCopyMemory(p, pwc, Size);
  1466. }
  1467. return(p);
  1468. }
  1469. #if DBG
  1470. ULONG USBD_Debug_Trace_Level =
  1471. #ifdef MAX_DEBUG
  1472. 9;
  1473. #else
  1474. #ifdef NTKERN
  1475. 1;
  1476. #else
  1477. 0;
  1478. #endif /* NTKERN */
  1479. #endif /* MAX_DEBUG */
  1480. #endif /* DBG */
  1481. #ifdef DEBUG_LOG
  1482. struct USBD_LOG_ENTRY {
  1483. CHAR le_name[4]; // Identifying string
  1484. ULONG le_info1; // entry specific info
  1485. ULONG le_info2; // entry specific info
  1486. ULONG le_info3; // entry specific info
  1487. }; /* USBD_LOG_ENTRY */
  1488. struct USBD_LOG_ENTRY *LStart = 0; // No log yet
  1489. struct USBD_LOG_ENTRY *LPtr;
  1490. struct USBD_LOG_ENTRY *LEnd;
  1491. #endif /* DEBUG_LOG */
  1492. #if DBG
  1493. ULONG
  1494. _cdecl
  1495. USBD_KdPrintX(
  1496. PCH Format,
  1497. ...
  1498. )
  1499. {
  1500. va_list list;
  1501. int i;
  1502. int arg[5];
  1503. if (USBD_Debug_Trace_Level == 1) {
  1504. DbgPrint("USBD: ");
  1505. } else {
  1506. DbgPrint("'USBD: ");
  1507. }
  1508. va_start(list, Format);
  1509. for (i=0; i<4; i++)
  1510. arg[i] = va_arg(list, int);
  1511. DbgPrint(Format, arg[0], arg[1], arg[2], arg[3]);
  1512. return 0;
  1513. }
  1514. VOID
  1515. USBD_Warning(
  1516. PUSBD_DEVICE_DATA DeviceData,
  1517. PUCHAR Message,
  1518. BOOLEAN DebugBreak
  1519. )
  1520. {
  1521. DbgPrint("USBD: Warning ****************************************************************\n");
  1522. if (DeviceData) {
  1523. DbgPrint("Device PID %04.4x, VID %04.4x\n",
  1524. DeviceData->DeviceDescriptor.idProduct,
  1525. DeviceData->DeviceDescriptor.idVendor);
  1526. }
  1527. DbgPrint("%s", Message);
  1528. DbgPrint("******************************************************************************\n");
  1529. // if (DebugBreak) {
  1530. // DBGBREAK();
  1531. // }
  1532. }
  1533. VOID
  1534. USBD_Assert(
  1535. IN PVOID FailedAssertion,
  1536. IN PVOID FileName,
  1537. IN ULONG LineNumber,
  1538. IN PCHAR Message
  1539. )
  1540. /*++
  1541. Routine Description:
  1542. Debug Assert function.
  1543. Arguments:
  1544. DeviceObject - pointer to a device object
  1545. Irp - pointer to an I/O Request Packet
  1546. Return Value:
  1547. --*/
  1548. {
  1549. #ifdef NTKERN
  1550. // this makes the compiler generate a ret
  1551. ULONG stop = 1;
  1552. assert_loop:
  1553. #endif
  1554. // just call the NT assert function and stop
  1555. // in the debugger.
  1556. RtlAssert( FailedAssertion, FileName, LineNumber, Message );
  1557. // loop here to prevent users from going past
  1558. // are assert before we can look at it
  1559. #ifdef NTKERN
  1560. DBGBREAK();
  1561. if (stop) {
  1562. goto assert_loop;
  1563. }
  1564. #endif
  1565. return;
  1566. }
  1567. #endif /* DBG */
  1568. #define DEADMAN_TIMER
  1569. #define DEADMAN_TIMEOUT 5000 //timeout in ms
  1570. //use a 5 second timeout
  1571. typedef struct _USBD_DEADMAN_TIMER {
  1572. PIRP Irp;
  1573. KTIMER TimeoutTimer;
  1574. KDPC TimeoutDpc;
  1575. } USBD_DEADMAN_TIMER, *PUSBD_DEADMAN_TIMER;
  1576. NTSTATUS
  1577. USBD_SubmitSynchronousURB(
  1578. IN PURB Urb,
  1579. IN PDEVICE_OBJECT DeviceObject,
  1580. IN PUSBD_DEVICE_DATA DeviceData
  1581. )
  1582. /*++
  1583. Routine Description:
  1584. Submit a Urb to HCD synchronously
  1585. Arguments:
  1586. Urb - Urb to submit
  1587. DeviceObject USBD device object
  1588. Return Value:
  1589. STATUS_SUCCESS if successful,
  1590. STATUS_UNSUCCESSFUL otherwise
  1591. --*/
  1592. {
  1593. NTSTATUS ntStatus = STATUS_SUCCESS, status;
  1594. PIRP irp;
  1595. KEVENT event;
  1596. IO_STATUS_BLOCK ioStatus;
  1597. PIO_STACK_LOCATION nextStack;
  1598. //#ifdef DEADMAN_TIMER
  1599. #if 0
  1600. BOOLEAN haveTimer = FALSE;
  1601. PUSBD_DEADMAN_TIMER timer;
  1602. #endif /* DEADMAN_TIMER */
  1603. PAGED_CODE();
  1604. //USBDIAG_KdPrint(("enter USBD_SubmitSynchronousURB\n"));
  1605. ASSERT_DEVICE(DeviceData);
  1606. irp = IoBuildDeviceIoControlRequest(
  1607. IOCTL_INTERNAL_USB_SUBMIT_URB,
  1608. HCD_DEVICE_OBJECT(DeviceObject),
  1609. NULL,
  1610. 0,
  1611. NULL,
  1612. 0,
  1613. TRUE, /* INTERNAL */
  1614. &event,
  1615. &ioStatus);
  1616. //
  1617. // Call the hc driver to perform the operation. If the returned status
  1618. // is PENDING, wait for the request to complete.
  1619. //
  1620. KeInitializeEvent(&event, NotificationEvent, FALSE);
  1621. nextStack = IoGetNextIrpStackLocation(irp);
  1622. ASSERT(nextStack != NULL);
  1623. nextStack->Parameters.Others.Argument1 = Urb;
  1624. //
  1625. // initialize flags field
  1626. // for internal request
  1627. //
  1628. Urb->UrbHeader.UsbdFlags = 0;
  1629. //
  1630. // Init the Irp field for transfers
  1631. //
  1632. switch(Urb->UrbHeader.Function) {
  1633. case URB_FUNCTION_CONTROL_TRANSFER:
  1634. case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
  1635. HC_URB(Urb)->HcdUrbCommonTransfer.hca.HcdIrp = irp;
  1636. if (HC_URB(Urb)->HcdUrbCommonTransfer.TransferBufferMDL == NULL &&
  1637. HC_URB(Urb)->HcdUrbCommonTransfer.TransferBufferLength != 0) {
  1638. if ((HC_URB(Urb)->HcdUrbCommonTransfer.TransferBufferMDL =
  1639. IoAllocateMdl(HC_URB(Urb)->HcdUrbCommonTransfer.TransferBuffer,
  1640. HC_URB(Urb)->HcdUrbCommonTransfer.TransferBufferLength,
  1641. FALSE,
  1642. FALSE,
  1643. NULL)) == NULL)
  1644. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1645. else {
  1646. Urb->UrbHeader.UsbdFlags |= USBD_REQUEST_MDL_ALLOCATED;
  1647. MmBuildMdlForNonPagedPool(HC_URB(Urb)->HcdUrbCommonTransfer.TransferBufferMDL);
  1648. }
  1649. }
  1650. break;
  1651. }
  1652. //USBDIAG_KdPrint(("USBD_SubmitSynchronousURB: calling HCD with URB\n"));
  1653. if (NT_SUCCESS(ntStatus)) {
  1654. // set the renter bit on the URB function code
  1655. Urb->UrbHeader.Function |= 0x2000;
  1656. ntStatus = IoCallDriver(HCD_DEVICE_OBJECT(DeviceObject),
  1657. irp);
  1658. }
  1659. //USBDIAG_KdPrint(("ntStatus from IoCallDriver = 0x%x\n", ntStatus));
  1660. status = STATUS_SUCCESS;
  1661. if (ntStatus == STATUS_PENDING) {
  1662. //#ifdef DEADMAN_TIMER
  1663. #if 0
  1664. LARGE_INTEGER dueTime;
  1665. timer = ExAllocatePool(NonPagedPool, sizeof(USBD_DEADMAN_TIMER));
  1666. if (timer) {
  1667. timer->Irp = irp;
  1668. KeInitializeTimer(&timer->TimeoutTimer);
  1669. KeInitializeDpc(&timer->TimeoutDpc,
  1670. USBD_SyncUrbTimeoutDPC,
  1671. timer);
  1672. dueTime.QuadPart = -10000 * DEADMAN_TIMEOUT;
  1673. KeSetTimer(&timer->TimeoutTimer,
  1674. dueTime,
  1675. &timer->TimeoutDpc);
  1676. haveTimer = TRUE;
  1677. }
  1678. #endif /* DEADMAN_TIMER */
  1679. status = KeWaitForSingleObject(
  1680. &event,
  1681. Suspended,
  1682. KernelMode,
  1683. FALSE,
  1684. NULL);
  1685. ntStatus = ioStatus.Status;
  1686. } else {
  1687. ioStatus.Status = ntStatus;
  1688. }
  1689. //#ifdef DEADMAN_TIMER
  1690. #if 0
  1691. //
  1692. // remove our timeoutDPC from the queue
  1693. //
  1694. if (haveTimer) {
  1695. KeCancelTimer(&timer->TimeoutTimer);
  1696. ExFreePool(timer);
  1697. }
  1698. #endif /* DEADMAN_TIMER */
  1699. // NOTE:
  1700. // mapping is handled by completion routine
  1701. // called by HCD
  1702. //USBDIAG_KdPrint(("Leave Synch URB urb status = 0x%x ntStatus = 0x%x\n", Urb->UrbHeader.Status, ntStatus));
  1703. return ntStatus;
  1704. }
  1705. NTSTATUS
  1706. USBDIAG_SyncGetRootHubPdo(
  1707. IN PDEVICE_OBJECT StackDeviceObject,
  1708. IN PDEVICE_OBJECT PhysicalDeviceObject,
  1709. IN OUT PDEVICE_OBJECT *RootHubPdo,
  1710. IN OUT PDEVICE_OBJECT *TopOfHcdStackDeviceObject
  1711. )
  1712. {
  1713. NTSTATUS ntStatus, status;
  1714. PIRP irp;
  1715. KEVENT event;
  1716. IO_STATUS_BLOCK ioStatus;
  1717. PIO_STACK_LOCATION nextStack;
  1718. PAGED_CODE();
  1719. USBDIAG_KdPrint(("enter USBDIAG_SyncGetRootHubPdo\n"));
  1720. //
  1721. // issue a synchronous request to the RootHubBdo
  1722. //
  1723. KeInitializeEvent(&event, NotificationEvent, FALSE);
  1724. //USBDIAG_KdPrint(("USBDIAG_SyncGetRootHubPdo: ioctl code: 0x%x\n", IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO));
  1725. irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO,
  1726. //StackDeviceObject, //PhysicalDeviceObject,
  1727. PhysicalDeviceObject,
  1728. NULL,
  1729. 0,
  1730. NULL,
  1731. 0,
  1732. TRUE, // INTERNAL
  1733. &event,
  1734. &ioStatus);
  1735. if (NULL == irp) {
  1736. USBDIAG_KdPrint(("USBUSBDIAG_SyncGetRootHubPdo build Irp failed\n"));
  1737. return STATUS_INSUFFICIENT_RESOURCES;
  1738. }
  1739. //
  1740. // Call the class driver to perform the operation. If the returned
  1741. // status
  1742. // is PENDING, wait for the request to complete.
  1743. //
  1744. nextStack = IoGetNextIrpStackLocation(irp);
  1745. //nextStack = IoGetCurrentIrpStackLocation(irp);
  1746. //
  1747. // pass the URB to the USBD 'class driver'
  1748. //
  1749. nextStack->Parameters.Others.Argument1 = NULL;
  1750. nextStack->Parameters.Others.Argument2 = NULL;
  1751. //nextStack->Parameters.Others.Argument3 = NULL;
  1752. nextStack->Parameters.Others.Argument4 = RootHubPdo;
  1753. // _asm int 3
  1754. ntStatus = IoCallDriver(PhysicalDeviceObject, irp);
  1755. USBDIAG_KdPrint(("return from IoCallDriver USBD %x\n", ntStatus));
  1756. if (ntStatus == STATUS_PENDING)
  1757. {
  1758. USBDIAG_KdPrint(("Wait for single object\n"));
  1759. status = KeWaitForSingleObject(&event,
  1760. Suspended,
  1761. KernelMode,
  1762. FALSE,
  1763. NULL);
  1764. USBDIAG_KdPrint(("Wait for single object, returned %x\n", status));
  1765. } else {
  1766. ioStatus.Status = ntStatus;
  1767. }
  1768. ntStatus = ioStatus.Status;
  1769. USBDIAG_KdPrint(("exit USBDIAG_SyncGetRootHubPdo with ntStatus: 0x%x)\n", ntStatus));
  1770. return ntStatus;
  1771. }
  1772. //#ifdef DEADMAN_TIMER
  1773. #if 0
  1774. VOID
  1775. USBD_SyncUrbTimeoutDPC(
  1776. IN PKDPC Dpc,
  1777. IN PVOID DeferredContext,
  1778. IN PVOID SystemArgument1,
  1779. IN PVOID SystemArgument2
  1780. )
  1781. /*++
  1782. Routine Description:
  1783. This routine runs at DISPATCH_LEVEL IRQL.
  1784. Arguments:
  1785. Dpc - Pointer to the DPC object.
  1786. DeferredContext -
  1787. SystemArgument1 - not used.
  1788. SystemArgument2 - not used.
  1789. Return Value:
  1790. None.
  1791. --*/
  1792. {
  1793. PUSBD_DEADMAN_TIMER timer;
  1794. #if DBG
  1795. BOOLEAN status;
  1796. #endif
  1797. timer = DeferredContext;
  1798. #if DBG
  1799. status =
  1800. #endif
  1801. IoCancelIrp(timer->Irp);
  1802. #if DBG
  1803. USBD_ASSERT(status == TRUE);
  1804. #endif
  1805. }
  1806. #endif /* DEADMAN_TIMER */
  1807. NTSTATUS
  1808. USBD_SetPdoRegistryParameter (
  1809. IN PDEVICE_OBJECT PhysicalDeviceObject,
  1810. IN PWCHAR KeyName,
  1811. IN ULONG KeyNameLength,
  1812. IN PVOID Data,
  1813. IN ULONG DataLength,
  1814. IN ULONG KeyType,
  1815. IN ULONG DevInstKeyType
  1816. )
  1817. /*++
  1818. Routine Description:
  1819. Arguments:
  1820. Return Value:
  1821. --*/
  1822. {
  1823. NTSTATUS ntStatus;
  1824. HANDLE handle;
  1825. UNICODE_STRING keyNameUnicodeString;
  1826. PAGED_CODE();
  1827. RtlInitUnicodeString(&keyNameUnicodeString, KeyName);
  1828. ntStatus=IoOpenDeviceRegistryKey(PhysicalDeviceObject,
  1829. DevInstKeyType,
  1830. STANDARD_RIGHTS_ALL,
  1831. &handle);
  1832. if (NT_SUCCESS(ntStatus)) {
  1833. USBD_SetRegistryKeyValue(handle,
  1834. &keyNameUnicodeString,
  1835. Data,
  1836. DataLength,
  1837. KeyType);
  1838. ZwClose(handle);
  1839. }
  1840. //USBDIAG_KdPrint((" RtlQueryRegistryValues status 0x%x\n"));
  1841. return ntStatus;
  1842. }
  1843. NTSTATUS
  1844. USBD_SetRegistryKeyValue (
  1845. IN HANDLE Handle,
  1846. IN PUNICODE_STRING KeyNameUnicodeString,
  1847. IN PVOID Data,
  1848. IN ULONG DataLength,
  1849. IN ULONG KeyType
  1850. )
  1851. /*++
  1852. Routine Description:
  1853. Arguments:
  1854. Return Value:
  1855. --*/
  1856. {
  1857. NTSTATUS ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1858. PAGED_CODE();
  1859. //
  1860. // Create the key or open it, as appropriate based on the caller's
  1861. // wishes.
  1862. //
  1863. ntStatus = ZwSetValueKey(Handle,
  1864. KeyNameUnicodeString,
  1865. 0,
  1866. KeyType,
  1867. Data,
  1868. DataLength);
  1869. //USBDIAG_KdPrint((" ZwSetKeyValue = 0x%x\n", ntStatus));
  1870. return ntStatus;
  1871. }