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.

2093 lines
75 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Copyright (c) 1996 Intel Corporation
  4. Module Name:
  5. ISOPERF.c
  6. Abstract:
  7. USB device driver for ISOPERF USB Device
  8. Environment:
  9. kernel mode only
  10. Notes:
  11. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  12. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  14. PURPOSE.
  15. Copyright (c) 1996 Microsoft Corporation. All Rights Reserved.
  16. Copyright (c) 1996 Intel Corporation All Rights Reserved.
  17. Revision History:
  18. 8-15-96: Version 1.0 Kosar Jaff
  19. --*/
  20. #define DRIVER
  21. #define DEADMAN_TIMEOUT 5000 //timeout in ms
  22. //use a 5 second timeout
  23. /*
  24. // Include files needed for WDM driver support
  25. */
  26. #pragma warning(disable:4214) // bitfield nonstd
  27. #include "wdm.h"
  28. #pragma warning(default:4214)
  29. #include "stdarg.h"
  30. #include "stdio.h"
  31. /*
  32. // Include files needed for USB support
  33. */
  34. #pragma warning(disable:4200) //non std struct used
  35. #include "usbdi.h"
  36. #pragma warning(default:4200)
  37. #include "usbdlib.h"
  38. #include "usb.h"
  39. /*
  40. // Include file for the ISOPERF Device
  41. */
  42. #include "ioctl.h"
  43. #include "ISOPERF.h"
  44. #include "iso.h"
  45. ULONG gulInstanceNumber = 0;
  46. ULONG gIsoPerfMaxDebug = TRUE;
  47. // NOTE (old code) (kjaff)
  48. // due to WDM loading separate images for the same ven/prod device, we can't rely on a device
  49. // chain, so...if we find an iso out dev obj we put it here as a short term fix
  50. //
  51. PDEVICE_OBJECT gMyOutputDevice = NULL;
  52. NTSTATUS
  53. DriverEntry(
  54. IN PDRIVER_OBJECT DriverObject,
  55. IN PUNICODE_STRING RegistryPath
  56. )
  57. /*++
  58. Routine Description:
  59. Installable driver initialization entry point.
  60. This is where the driver is called when the driver is being loaded
  61. by the I/O system. This entry point is called directly by the I/O system.
  62. Arguments:
  63. DriverObject - pointer to the driver object
  64. RegistryPath - pointer to a unicode string representing the path
  65. to driver-specific key in the registry
  66. Return Value:
  67. STATUS_SUCCESS if successful,
  68. STATUS_UNSUCCESSFUL otherwise
  69. --*/
  70. {
  71. NTSTATUS ntStatus = STATUS_SUCCESS;
  72. PDEVICE_OBJECT deviceObject = NULL;
  73. ISOPERF_KdPrint (("entering (ISOPERF) DriverEntry (build time/date: %s/%s\n",__TIME__,__DATE__));
  74. DriverObject->MajorFunction[IRP_MJ_CREATE] = ISOPERF_Create;
  75. DriverObject->MajorFunction[IRP_MJ_CLOSE] = ISOPERF_Close;
  76. DriverObject->DriverUnload = ISOPERF_Unload;
  77. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ISOPERF_ProcessIOCTL;
  78. DriverObject->MajorFunction[IRP_MJ_WRITE] = ISOPERF_Write;
  79. DriverObject->MajorFunction[IRP_MJ_READ] = ISOPERF_Read;
  80. DriverObject->MajorFunction[IRP_MJ_PNP] = ISOPERF_Dispatch;
  81. DriverObject->DriverExtension->AddDevice = ISOPERF_PnPAddDevice;
  82. ISOPERF_KdPrint (("exiting (ISOPERF) DriverEntry (%x)\n", ntStatus));
  83. ISOPERF_KdPrint (("sizeof IsoStats: %d\n",sizeof(Config_Stat_Info)));
  84. return ntStatus;
  85. }
  86. NTSTATUS
  87. ISOPERF_Dispatch(
  88. IN PDEVICE_OBJECT DeviceObject,
  89. IN PIRP Irp
  90. )
  91. /*++
  92. Routine Description:
  93. Process the IRPs sent to this device.
  94. Arguments:
  95. DeviceObject - pointer to a device object
  96. Irp - pointer to an I/O Request Packet
  97. Return Value:
  98. NTSTATUS
  99. --*/
  100. {
  101. PIO_STACK_LOCATION irpStack, nextStack;
  102. PDEVICE_EXTENSION deviceExtension;
  103. NTSTATUS ntStatus;
  104. Irp->IoStatus.Status = STATUS_SUCCESS;
  105. Irp->IoStatus.Information = 0;
  106. /*
  107. // Get a pointer to the current location in the Irp. This is where
  108. // the function codes and parameters are located.
  109. */
  110. irpStack = IoGetCurrentIrpStackLocation (Irp);
  111. /*
  112. // Get a pointer to the device extension
  113. */
  114. deviceExtension = DeviceObject->DeviceExtension;
  115. switch (irpStack->MajorFunction) {
  116. case IRP_MJ_PNP:
  117. /*
  118. //
  119. // This IRP is for Plug and Play and Power Management messages for your device.
  120. //
  121. // When your device is first installed, the port on the hub to which it
  122. // is attached is powered on and the USB software subsystem does some
  123. // minimal querying of the device. After the USB subsystem is done with that
  124. // basic communication, (the device ID has been determined, and the device
  125. // has been given a unique USB bus address), it is considered "powered" by
  126. // the system. The IRP's minor code gives more information about the power event.
  127. //
  128. // Similarly, when the USB device is being removed from the system, the Plug
  129. // and Play subsystem and the USB software stack interact to notify the
  130. // appropriate driver using this same IRP code, although in this case the
  131. // minor code gives more information about the exact power event.
  132. //
  133. */
  134. ISOPERF_KdPrint (("IRP_MJ_PNP\n"));
  135. switch (irpStack->MinorFunction) {
  136. case IRP_MN_START_DEVICE:
  137. ISOPERF_KdPrint (("IRP_MN_START_DEVICE\n"));
  138. /*
  139. // We pass the Irp down to the underlying PDO first since that driver
  140. // may have some configuration work to do before we can control the device
  141. */
  142. nextStack = IoGetNextIrpStackLocation(Irp);
  143. ASSERT(nextStack != NULL);
  144. RtlCopyMemory(nextStack, irpStack, sizeof(IO_STACK_LOCATION));
  145. ISOPERF_KdPrint (("Passing START_DEVICE Irp down\n"));
  146. // This will be deviceExtension->StackDeviceObject in future revisions of this driver
  147. ntStatus = IoCallDriver(deviceExtension->PhysicalDeviceObject, Irp);
  148. ISOPERF_KdPrint (("Back from passing START_DEVICE Irp down; status: %#X\n", ntStatus));
  149. // Now we can begin our configuration actions on the device
  150. ntStatus = ISOPERF_StartDevice(DeviceObject);
  151. break; //IRP_MN_START_DEVICE
  152. case IRP_MN_STOP_DEVICE:
  153. ISOPERF_KdPrint (("IRP_MN_STOP_DEVICE\n"));
  154. ISOPERF_Cleanup (DeviceObject);
  155. ntStatus = ISOPERF_StopDevice(DeviceObject);
  156. break; //IRP_MN_STOP_DEVICE
  157. case IRP_MN_REMOVE_DEVICE:
  158. /*
  159. // Note: This IRP handler will change slightly in future revisions of this
  160. // sample driver. Please watch this space for updates.
  161. */
  162. ISOPERF_KdPrint (("IRP_MN_REMOVE_DEVICE\n"))
  163. ISOPERF_Cleanup (DeviceObject);
  164. ntStatus = ISOPERF_RemoveDevice(DeviceObject);
  165. break; //IRP_MN_REMOVE_DEVICE
  166. case IRP_MN_QUERY_STOP_DEVICE:
  167. ISOPERF_KdPrint (("IRP_MN_QUERY_STOP_DEVICE\n"));
  168. break;
  169. case IRP_MN_QUERY_REMOVE_DEVICE:
  170. ISOPERF_KdPrint (("IRP_MN_QUERY_REMOVE_DEVICE\n"));
  171. break;
  172. case IRP_MN_CANCEL_STOP_DEVICE:
  173. ISOPERF_KdPrint (("IRP_MN_CANCEL_STOP_DEVICE\n"));
  174. break;
  175. case IRP_MN_CANCEL_REMOVE_DEVICE:
  176. ISOPERF_KdPrint (("IRP_MN_CANCEL_REMOVE_DEVICE\n"));
  177. break;
  178. default:
  179. // A PnP Minor Function was not handled
  180. ISOPERF_KdPrint (("PnP IOCTL not handled\n"));
  181. } /* switch MinorFunction*/
  182. nextStack = IoGetNextIrpStackLocation(Irp);
  183. ASSERT(nextStack != NULL);
  184. RtlCopyMemory(nextStack, irpStack, sizeof(IO_STACK_LOCATION));
  185. /*
  186. // All PNP_POWER messages get passed to the PhysicalDeviceObject
  187. // (which in future revisions of this driver will be the StackDeviceObject)
  188. // we were given in PnPAddDevice.
  189. //
  190. // This physical device object is managed by the USB software subsystem,
  191. // and so this IRP must be propagated to the owning device driver for
  192. // that physical device object, so that driver in turn can perform any
  193. // device state management (e.g., remove its device object, etc.).
  194. */
  195. ISOPERF_KdPrint (("Passing PnP Irp down, status = %x\n", ntStatus));
  196. // This will be deviceExtension->StackDeviceObject in future revisions of this driver
  197. ntStatus =
  198. IoCallDriver(deviceExtension->PhysicalDeviceObject, Irp);
  199. /*
  200. // If lower layer driver marked the Irp as pending then reflect that by
  201. // calling IoMarkIrpPending.
  202. */
  203. if (ntStatus == STATUS_PENDING) {
  204. IoMarkIrpPending(Irp);
  205. ISOPERF_KdPrint (("PnP Irp came back with STATUS_PENDING (%x)\n", ntStatus));
  206. } else {
  207. ISOPERF_KdPrint (("PnP Irp came back, status = %x\n", ntStatus));
  208. } // if ntStatus
  209. goto ISOPERF_Dispatch_Done;
  210. break; //IRP_MJ_PNP
  211. case IRP_MJ_POWER:
  212. /*
  213. //
  214. // This IRP is for Plug and Play and Power Management messages for your device.
  215. //
  216. // When your device is first installed, the port on the hub to which it
  217. // is attached is powered on and the USB software subsystem does some
  218. // minimal querying of the device. After the USB subsystem is done with that
  219. // basic communication, (the device ID has been determined, and the device
  220. // has been given a unique USB bus address), it is considered "powered" by
  221. // the system. The IRP's minor code gives more information about the power event.
  222. //
  223. // Similarly, when the USB device is being removed from the system, the Plug
  224. // and Play subsystem and the USB software stack interact to notify the
  225. // appropriate driver using this same IRP code, although in this case the
  226. // minor code gives more information about the exact power event.
  227. //
  228. */
  229. ISOPERF_KdPrint (("IRP_MJ_POWER\n"));
  230. switch (irpStack->MinorFunction) {
  231. case IRP_MN_SET_POWER:
  232. switch (irpStack->Parameters.Power.Type) {
  233. case SystemPowerState:
  234. break; //SystemPowerState
  235. case DevicePowerState:
  236. switch (irpStack->Parameters.Power.State.DeviceState) {
  237. case PowerDeviceD3:
  238. ISOPERF_KdPrint (("IRP_MN_SET_D3\n"));
  239. break;
  240. case PowerDeviceD2:
  241. ISOPERF_KdPrint (("IRP_MN_SET_D2\n"));
  242. break;
  243. case PowerDeviceD1:
  244. ISOPERF_KdPrint (("IRP_MN_SET_D1\n"));
  245. break;
  246. case PowerDeviceD0:
  247. ISOPERF_KdPrint (("IRP_MN_SET_D0\n"));
  248. break;
  249. } // switch on Power.State.DeviceState
  250. break; //DevicePowerState
  251. }// switch on Power.Type
  252. break; //IRP_MN_SET_POWER
  253. case IRP_MN_QUERY_POWER:
  254. // Look at what type of power query this is
  255. switch (irpStack->Parameters.Power.Type) {
  256. case SystemPowerState:
  257. break; //SystemPowerState
  258. case DevicePowerState:
  259. switch (irpStack->Parameters.Power.State.DeviceState) {
  260. case PowerDeviceD2:
  261. ISOPERF_KdPrint (("IRP_MN_QUERY_D2\n"));
  262. break;
  263. case PowerDeviceD1:
  264. ISOPERF_KdPrint (("IRP_MN_QUERY_D1\n"));
  265. break;
  266. case PowerDeviceD3:
  267. ISOPERF_KdPrint (("IRP_MN_QUERY_D3\n"));
  268. break;
  269. } //switch on Power.State.DeviceState
  270. break; //DevicePowerState
  271. }//switch on Power.Type
  272. break; //IRP_MN_QUERY_POWER
  273. default:
  274. // A Power Minor Function was not handled
  275. ISOPERF_KdPrint (("Power IOCTL not handled\n"));
  276. } /* switch MinorFunction*/
  277. nextStack = IoGetNextIrpStackLocation(Irp);
  278. ASSERT(nextStack != NULL);
  279. RtlCopyMemory(nextStack, irpStack, sizeof(IO_STACK_LOCATION));
  280. /*
  281. // All PNP_POWER messages get passed to the PhysicalDeviceObject
  282. // (which in future revisions of this driver will be the StackDeviceObject)
  283. // we were given in PnPAddDevice.
  284. //
  285. // This physical device object is managed by the USB software subsystem,
  286. // and so this IRP must be propagated to the owning device driver for
  287. // that physical device object, so that driver in turn can perform any
  288. // device state management (e.g., remove its device object, etc.).
  289. */
  290. ISOPERF_KdPrint (("Passing power down, status = %x\n", ntStatus));
  291. // This will be deviceExtension->StackDeviceObject in future revisions of this driver
  292. ntStatus =
  293. IoCallDriver(deviceExtension->PhysicalDeviceObject, Irp);
  294. /*
  295. // If lower layer driver marked the Irp as pending then reflect that by
  296. // calling IoMarkIrpPending.
  297. */
  298. if (ntStatus == STATUS_PENDING) {
  299. IoMarkIrpPending(Irp);
  300. ISOPERF_KdPrint (("PnP Irp came back with STATUS_PENDING (%x)\n", ntStatus));
  301. } else {
  302. ISOPERF_KdPrint (("PnP Irp came back, status = %x\n", ntStatus));
  303. } // if ntStatus
  304. goto ISOPERF_Dispatch_Done;
  305. break; //IRP_MJ_POWER
  306. default:
  307. ISOPERF_KdPrint (("A MAJOR IOCTL Code was not handled: %#X\n",
  308. irpStack->MajorFunction));
  309. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  310. } /* switch MajorFunction */
  311. ntStatus = Irp->IoStatus.Status;
  312. IoCompleteRequest (Irp,
  313. IO_NO_INCREMENT
  314. );
  315. ISOPERF_Dispatch_Done:
  316. ISOPERF_KdPrint (("Exit ISOPERF_Dispatch %x\n", ntStatus));
  317. return ntStatus;
  318. }//ISOPERF_Dispatch
  319. VOID
  320. ISOPERF_Unload(
  321. IN PDRIVER_OBJECT DriverObject
  322. )
  323. /*++
  324. Routine Description:
  325. Free all the allocated resources, etc.
  326. TODO: This is a placeholder for driver writer to add code on unload
  327. Arguments:
  328. DriverObject - pointer to a driver object
  329. Return Value:
  330. None
  331. --*/
  332. {
  333. ISOPERF_KdPrint (("enter ISOPERF_Unload\n"));
  334. /*
  335. // TODO: Free any global resources allocated in DriverEntry
  336. */
  337. ISOPERF_KdPrint (("exit ISOPERF_Unload\n"));
  338. }
  339. NTSTATUS
  340. ISOPERF_StartDevice(
  341. IN PDEVICE_OBJECT DeviceObject
  342. )
  343. /*++
  344. Routine Description:
  345. Initializes a given instance of the ISOPERF Device on the USB.
  346. TODO: Perform any device initialization and querying here. For example,
  347. this routine queries the device's descriptors. Your device can
  348. be queried in a similar fashion with more specific requests that are
  349. tailored to your device's functionality.
  350. Arguments:
  351. DeviceObject - pointer to the device object for this instance of a
  352. ISOPERF Device
  353. Return Value:
  354. NT status code
  355. --*/
  356. {
  357. PDEVICE_EXTENSION deviceExtension;
  358. NTSTATUS ntStatus;
  359. PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
  360. PURB urb;
  361. ULONG siz;
  362. ISOPERF_KdPrint (("enter ISOPERF_StartDevice\n"));
  363. deviceExtension = DeviceObject->DeviceExtension;
  364. deviceExtension->NeedCleanup = TRUE;
  365. /*
  366. // Get some memory from then non paged pool (fixed, locked system memory)
  367. // for use by the USB Request Block (urb) for the specific USB Request we
  368. // will be performing below (a USB device request).
  369. */
  370. urb = ISOPERF_ExAllocatePool(NonPagedPool,
  371. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  372. &gulBytesAllocated);
  373. if (urb) {
  374. siz = sizeof(USB_DEVICE_DESCRIPTOR);
  375. // Get some non paged memory for the device descriptor contents
  376. deviceDescriptor = ISOPERF_ExAllocatePool(NonPagedPool,
  377. siz,
  378. &gulBytesAllocated);
  379. if (deviceDescriptor) {
  380. // Use a macro in the standard USB header files to build the URB
  381. UsbBuildGetDescriptorRequest(urb,
  382. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  383. USB_DEVICE_DESCRIPTOR_TYPE,
  384. 0,
  385. 0,
  386. deviceDescriptor,
  387. NULL,
  388. siz,
  389. NULL);
  390. // Get the device descriptor
  391. ntStatus = ISOPERF_CallUSBD(DeviceObject, urb);
  392. // Dump out the descriptor info to the debugger
  393. if (NT_SUCCESS(ntStatus)) {
  394. ISOPERF_KdPrint (("Device Descriptor = %x, len %x\n",
  395. deviceDescriptor,
  396. urb->UrbControlDescriptorRequest.TransferBufferLength));
  397. ISOPERF_KdPrint (("ISOPERF Device Descriptor:\n"));
  398. ISOPERF_KdPrint (("-------------------------\n"));
  399. ISOPERF_KdPrint (("bLength %d\n", deviceDescriptor->bLength));
  400. ISOPERF_KdPrint (("bDescriptorType 0x%x\n", deviceDescriptor->bDescriptorType));
  401. ISOPERF_KdPrint (("bcdUSB 0x%x\n", deviceDescriptor->bcdUSB));
  402. ISOPERF_KdPrint (("bDeviceClass 0x%x\n", deviceDescriptor->bDeviceClass));
  403. ISOPERF_KdPrint (("bDeviceSubClass 0x%x\n", deviceDescriptor->bDeviceSubClass));
  404. ISOPERF_KdPrint (("bDeviceProtocol 0x%x\n", deviceDescriptor->bDeviceProtocol));
  405. ISOPERF_KdPrint (("bMaxPacketSize0 0x%x\n", deviceDescriptor->bMaxPacketSize0));
  406. ISOPERF_KdPrint (("idVendor 0x%x\n", deviceDescriptor->idVendor));
  407. ISOPERF_KdPrint (("idProduct 0x%x\n", deviceDescriptor->idProduct));
  408. ISOPERF_KdPrint (("bcdDevice 0x%x\n", deviceDescriptor->bcdDevice));
  409. ISOPERF_KdPrint (("iManufacturer 0x%x\n", deviceDescriptor->iManufacturer));
  410. ISOPERF_KdPrint (("iProduct 0x%x\n", deviceDescriptor->iProduct));
  411. ISOPERF_KdPrint (("iSerialNumber 0x%x\n", deviceDescriptor->iSerialNumber));
  412. ISOPERF_KdPrint (("bNumConfigurations 0x%x\n", deviceDescriptor->bNumConfigurations));
  413. }
  414. } else {
  415. ntStatus = STATUS_NO_MEMORY;
  416. }
  417. if (NT_SUCCESS(ntStatus)) {
  418. /*
  419. // Put a ptr to the device descriptor in the device extension for easy
  420. // access (like a "cached" copy). We will free this memory when the
  421. // device is removed. See the "ISOPERF_RemoveDevice" code.
  422. */
  423. deviceExtension->DeviceDescriptor = deviceDescriptor;
  424. deviceExtension->Stopped = FALSE;
  425. }
  426. if (urb) {
  427. ISOPERF_ExFreePool(urb, &gulBytesFreed);
  428. }/* if urb */
  429. } else {
  430. ntStatus = STATUS_NO_MEMORY;
  431. }
  432. // If the Get_Descriptor call was successful, then configure the device.
  433. if (NT_SUCCESS(ntStatus)) {
  434. ntStatus = ISOPERF_ConfigureDevice(DeviceObject);
  435. }
  436. ISOPERF_KdPrint (("exit ISOPERF_StartDevice (%x)\n", ntStatus));
  437. return ntStatus;
  438. }
  439. NTSTATUS
  440. ISOPERF_RemoveDevice(
  441. IN PDEVICE_OBJECT DeviceObject
  442. )
  443. /*++
  444. Routine Description:
  445. Removes a given instance of a ISOPERF Device device on the USB.
  446. Arguments:
  447. DeviceObject - pointer to the device object for this instance of a ISOPERF Device
  448. Return Value:
  449. NT status code
  450. --*/
  451. {
  452. PDEVICE_EXTENSION deviceExtension;
  453. NTSTATUS ntStatus = STATUS_SUCCESS;
  454. int nInterfaceNumber;
  455. ISOPERF_KdPrint (("enter ISOPERF_RemoveDevice\n"));
  456. deviceExtension = DeviceObject->DeviceExtension;
  457. // After all the outstanding transfers are done, the test routines will clear the DeviceIsBusy flag
  458. if (deviceExtension->DeviceIsBusy) {
  459. ISOPERF_KdPrint (("RemoveDevice: Device is still busy\n"));
  460. //Tell test routines to stop submitting txfers
  461. deviceExtension->StopTransfers = TRUE;
  462. ntStatus = STATUS_DEVICE_BUSY;
  463. }else{
  464. ISOPERF_KdPrint (("Freeing up Device Descriptor in DevExtension (%X)\n",deviceExtension->DeviceDescriptor));
  465. if (deviceExtension->DeviceDescriptor) {
  466. ISOPERF_ExFreePool(deviceExtension->DeviceDescriptor,
  467. &gulBytesFreed);
  468. }
  469. // Free up any interface structures in our device extension
  470. for (nInterfaceNumber=0;nInterfaceNumber < MAX_INTERFACE; nInterfaceNumber++) {
  471. ISOPERF_KdPrint (("Freeing USBD Interfce Objs %d in DevExt: (%X)\n",
  472. nInterfaceNumber,
  473. deviceExtension->Interface[nInterfaceNumber]));
  474. if ((deviceExtension->Interface[nInterfaceNumber]) != NULL) {
  475. ISOPERF_ExFreePool(deviceExtension->Interface[nInterfaceNumber], &gulBytesFreed);
  476. }//if
  477. }/* for all the interfaces */
  478. // Free up the device's config and stat memory
  479. if ((deviceExtension->pConfig_Stat_Information)!=NULL) {
  480. ISOPERF_ExFreePool (deviceExtension->pConfig_Stat_Information, &gulBytesFreed);
  481. }/* if valid device config/stat space */
  482. /*
  483. // If someone has a symbolic link open, then just indicate in the dev ext that the device is stopped
  484. // since it's possible that the device object will stick around
  485. */
  486. deviceExtension->Stopped = TRUE;
  487. /*
  488. // Delete the link to the Stack Device Object, and delete the
  489. // Functional Device Object we created
  490. */
  491. IoDetachDevice(deviceExtension->StackDeviceObject);
  492. IoDeleteDevice (DeviceObject);
  493. }/*else it's ok to free up parts of the device object */
  494. ISOPERF_KdPrint (("exit ISOPERF_RemoveDevice (%x)\n", ntStatus));
  495. return ntStatus;
  496. }
  497. NTSTATUS
  498. ISOPERF_StopDevice(
  499. IN PDEVICE_OBJECT DeviceObject
  500. )
  501. /*++
  502. Routine Description:
  503. Stops a given instance of a ISOPERF Device device on the USB.
  504. Arguments:
  505. DeviceObject - pointer to the device object for this instance of a ISOPERF Device
  506. Return Value:
  507. NT status code
  508. --*/
  509. {
  510. PDEVICE_EXTENSION deviceExtension;
  511. NTSTATUS ntStatus = STATUS_SUCCESS;
  512. PURB urb;
  513. ULONG siz;
  514. ISOPERF_KdPrint (("enter ISOPERF_StopDevice\n"));
  515. deviceExtension = DeviceObject->DeviceExtension;
  516. /*
  517. // Send the select configuration urb with a NULL pointer for the configuration
  518. // handle, this closes the configuration and puts the device in the 'unconfigured'
  519. // state.
  520. */
  521. siz = sizeof(struct _URB_SELECT_CONFIGURATION);
  522. urb = ISOPERF_ExAllocatePool(NonPagedPool,
  523. siz,
  524. &gulBytesAllocated);
  525. if (urb) {
  526. NTSTATUS status;
  527. UsbBuildSelectConfigurationRequest(urb,
  528. (USHORT) siz,
  529. NULL);
  530. status = ISOPERF_CallUSBD(DeviceObject, urb);
  531. ISOPERF_KdPrint (("Device Configuration Closed status = %x usb status = %x.\n",
  532. status, urb->UrbHeader.Status));
  533. ISOPERF_ExFreePool(urb, &gulBytesFreed);
  534. } else {
  535. ntStatus = STATUS_NO_MEMORY;
  536. }
  537. ISOPERF_KdPrint (("exit ISOPERF_StopDevice (%x)\n", ntStatus));
  538. return ntStatus;
  539. }
  540. NTSTATUS
  541. ISOPERF_PnPAddDevice(
  542. IN PDRIVER_OBJECT DriverObject,
  543. IN PDEVICE_OBJECT PhysicalDeviceObject
  544. )
  545. /*++
  546. Routine Description:
  547. This routine is called to create a new instance of the device
  548. Arguments:
  549. DriverObject - pointer to the driver object for this instance of ISOPERF
  550. PhysicalDeviceObject - pointer to a device object created by the bus
  551. Return Value:
  552. STATUS_SUCCESS if successful,
  553. STATUS_UNSUCCESSFUL otherwise
  554. --*/
  555. {
  556. NTSTATUS ntStatus = STATUS_SUCCESS;
  557. PDEVICE_OBJECT deviceObject = NULL;
  558. PDEVICE_EXTENSION deviceExtension;
  559. ISOPERF_KdPrint(("enter ISOPERF_PnPAddDevice\n"));
  560. // create our funtional device object (FDO)
  561. ntStatus =
  562. ISOPERF_CreateDeviceObject(DriverObject, &deviceObject, gulInstanceNumber);
  563. if (NT_SUCCESS(ntStatus)) {
  564. deviceExtension = deviceObject->DeviceExtension;
  565. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  566. /*
  567. // Add more flags here if your driver supports other specific
  568. // behavior. For example, if your IRP_MJ_READ and IRP_MJ_WRITE
  569. // handlers support DIRECT_IO, you would set that flag here.
  570. //
  571. // Also, store away the Physical device Object
  572. */
  573. deviceExtension->PhysicalDeviceObject=PhysicalDeviceObject;
  574. //
  575. // Attach to the StackDeviceObject. This is the device object that what we
  576. // use to send Irps and Urbs down the USB software stack
  577. //
  578. deviceExtension->StackDeviceObject =
  579. IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);
  580. ASSERT (deviceExtension->StackDeviceObject != NULL);
  581. }
  582. gulInstanceNumber++;
  583. ISOPERF_KdPrint(("exit ISOPERF_PnPAddDevice (%x)\n", ntStatus));
  584. return ntStatus;
  585. }
  586. NTSTATUS
  587. ISOPERF_CreateDeviceObject(
  588. IN PDRIVER_OBJECT DriverObject,
  589. IN PDEVICE_OBJECT *DeviceObject,
  590. LONG Instance
  591. )
  592. /*++
  593. Routine Description:
  594. Creates a Functional DeviceObject
  595. Arguments:
  596. DriverObject - pointer to the driver object for device
  597. DeviceObject - pointer to DeviceObject pointer to return
  598. created device object.
  599. Instance - instnace of the device create.
  600. Return Value:
  601. STATUS_SUCCESS if successful,
  602. STATUS_UNSUCCESSFUL otherwise
  603. --*/
  604. {
  605. NTSTATUS ntStatus;
  606. WCHAR deviceLinkBuffer[] = L"\\DosDevices\\ISOPERF-0";
  607. UNICODE_STRING deviceLinkUnicodeString;
  608. WCHAR deviceNameBuffer[] = L"\\Device\\ISOPERF-0";
  609. UNICODE_STRING deviceNameUnicodeString;
  610. PDEVICE_EXTENSION deviceExtension;
  611. int i;
  612. ISOPERF_KdPrint(("enter ISOPERF_CreateDeviceObject instance = %d\n", Instance));
  613. /*
  614. // fix up device names based on Instance
  615. //
  616. // NOTE: Watch this space for potential changes to this approach in future revisions
  617. // of this sample driver.
  618. */
  619. deviceLinkBuffer[19] = (USHORT) ('0' + Instance);
  620. deviceNameBuffer[15] = (USHORT) ('0' + Instance);
  621. ISOPERF_KdPrint(("Create Device name (%ws)\n", deviceNameBuffer));
  622. RtlInitUnicodeString (&deviceNameUnicodeString,
  623. deviceNameBuffer);
  624. ntStatus = IoCreateDevice (DriverObject,
  625. sizeof (DEVICE_EXTENSION),
  626. &deviceNameUnicodeString,
  627. FILE_DEVICE_UNKNOWN,
  628. 0,
  629. FALSE,
  630. DeviceObject);
  631. if (NT_SUCCESS(ntStatus)) {
  632. RtlInitUnicodeString (&deviceLinkUnicodeString,
  633. deviceLinkBuffer);
  634. ISOPERF_KdPrint(("Create DosDevice name (%ws)\n", deviceLinkBuffer));
  635. ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
  636. &deviceNameUnicodeString);
  637. // Initialize our device extension
  638. deviceExtension = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);
  639. RtlCopyMemory(deviceExtension->DeviceLinkNameBuffer,
  640. deviceLinkBuffer,
  641. sizeof(deviceLinkBuffer));
  642. deviceExtension->ConfigurationHandle = NULL;
  643. deviceExtension->DeviceDescriptor = NULL;
  644. deviceExtension->NeedCleanup = TRUE;
  645. deviceExtension->Stopped = FALSE;
  646. //init to some huge number; this doesn't get decremented by this driver unless
  647. //the user has requested a stop (in the app)
  648. deviceExtension->ulCountDownToStop = 0xFFFFFFFF;
  649. // Initialize our interface
  650. for (i=0;i<MAX_INTERFACE;i++) {
  651. deviceExtension->Interface[i] = NULL;
  652. }//for
  653. }
  654. ISOPERF_KdPrint(("exit ISOPERF_CreateDeviceObject (%x)\n", ntStatus));
  655. return ntStatus;
  656. }
  657. VOID
  658. ISOPERF_Cleanup(
  659. PDEVICE_OBJECT DeviceObject
  660. )
  661. /*++
  662. Routine Description:
  663. Cleans up certain elements of the device object. This is called when the device
  664. is being removed from the system
  665. Arguments:
  666. DeviceObject - pointer to DeviceObject
  667. Return Value:
  668. None.
  669. --*/
  670. {
  671. PDEVICE_EXTENSION deviceExtension;
  672. UNICODE_STRING deviceLinkUnicodeString;
  673. deviceExtension = DeviceObject->DeviceExtension;
  674. if (deviceExtension->NeedCleanup) {
  675. deviceExtension->NeedCleanup = FALSE;
  676. deviceExtension->StopTransfers = TRUE; //Let test thread know it should stop transfers
  677. deviceExtension->Stopped = TRUE; //Let everyone know this device is not working
  678. RtlInitUnicodeString (&deviceLinkUnicodeString,
  679. deviceExtension->DeviceLinkNameBuffer);
  680. IoDeleteSymbolicLink(&deviceLinkUnicodeString);
  681. }
  682. }
  683. NTSTATUS
  684. ISOPERF_CallUSBD(
  685. IN PDEVICE_OBJECT DeviceObject,
  686. IN PURB Urb
  687. )
  688. /*++
  689. Routine Description:
  690. Passes a Usb Request Block (URB) to the USB class driver (USBD)
  691. Note that we create our own IRP here and use it to send the request to
  692. the USB software subsystem. This means that this routine is essentially
  693. independent of the IRP that caused this driver to be called in the first
  694. place. The IRP for this transfer is created, used, and then destroyed
  695. in this routine.
  696. However, note that this routine uses the Usb Request Block (urb) passed
  697. in by the caller as the request block for the USB software stack.
  698. Implementation of this routine may be changed depending on the specific
  699. requirements of your driver. For example, while this routine issues a
  700. synchronous request to the USB stack, you may wish to implement this as an
  701. asynchronous request in which you set an IoCompletionRoutine to be called
  702. when the request is complete.
  703. Arguments:
  704. DeviceObject - pointer to the device object for this instance of an ISOPERF Device
  705. Urb - pointer to Urb request block
  706. Return Value:
  707. STATUS_SUCCESS if successful,
  708. STATUS_UNSUCCESSFUL otherwise
  709. --*/
  710. {
  711. NTSTATUS ntStatus, status = STATUS_SUCCESS;
  712. PDEVICE_EXTENSION deviceExtension;
  713. PIRP irp;
  714. KEVENT event;
  715. IO_STATUS_BLOCK ioStatus;
  716. PIO_STACK_LOCATION nextStack;
  717. ISOPERF_KdPrint (("enter ISOPERF_CallUSBD\n"));
  718. deviceExtension = DeviceObject->DeviceExtension;
  719. // issue a synchronous request (see notes above)
  720. KeInitializeEvent(&event, NotificationEvent, FALSE);
  721. irp = IoBuildDeviceIoControlRequest(
  722. IOCTL_INTERNAL_USB_SUBMIT_URB,
  723. deviceExtension->StackDeviceObject,
  724. NULL,
  725. 0,
  726. NULL,
  727. 0,
  728. TRUE, /* INTERNAL */
  729. &event,
  730. &ioStatus);
  731. // Prepare for calling the USB driver stack
  732. nextStack = IoGetNextIrpStackLocation(irp);
  733. ASSERT(nextStack != NULL);
  734. // Set up the URB ptr to pass to the USB driver stack
  735. nextStack->Parameters.Others.Argument1 = Urb;
  736. ISOPERF_KdPrint (("Calling USB Driver Stack\n"));
  737. /*
  738. // Call the USB class driver to perform the operation. If the returned status
  739. // is PENDING, wait for the request to complete.
  740. */
  741. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  742. irp);
  743. ISOPERF_KdPrint (("return from IoCallDriver USBD %x\n", ntStatus));
  744. if (ntStatus == STATUS_PENDING) {
  745. ISOPERF_KdPrint (("Wait for single object\n"));
  746. status = KeWaitForSingleObject(
  747. &event,
  748. Suspended,
  749. KernelMode,
  750. FALSE,
  751. NULL);
  752. ISOPERF_KdPrint (("Wait for single object, returned %x\n", status));
  753. } else {
  754. ioStatus.Status = ntStatus;
  755. }
  756. ISOPERF_KdPrint (("URB status = %x status = %x irp status %x\n",
  757. Urb->UrbHeader.Status, status, ioStatus.Status));
  758. ntStatus = ioStatus.Status;
  759. ISOPERF_KdPrint(("exit ISOPERF_CallUSBD (%x)\n", ntStatus));
  760. return ntStatus;
  761. }
  762. NTSTATUS
  763. ISOPERF_ConfigureDevice(
  764. IN PDEVICE_OBJECT DeviceObject
  765. )
  766. /*++
  767. Routine Description:
  768. Configures the USB device via USB-specific device requests and interaction
  769. with the USB software subsystem.
  770. Arguments:
  771. DeviceObject - pointer to the device object for this instance of the ISOPERF Device
  772. Return Value:
  773. NT status code
  774. --*/
  775. {
  776. PDEVICE_EXTENSION deviceExtension;
  777. NTSTATUS ntStatus;
  778. PURB urb = NULL;
  779. ULONG siz;
  780. PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;
  781. ISOPERF_KdPrint (("enter ISOPERF_ConfigureDevice\n"));
  782. deviceExtension = DeviceObject->DeviceExtension;
  783. // Get the config descriptor from the device
  784. // Get memory for the USB Request Block (urb) for the Getconfigdesc request.
  785. urb = ISOPERF_ExAllocatePool(NonPagedPool,
  786. sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  787. &gulBytesAllocated);
  788. if (urb != NULL) {
  789. /*
  790. // Set size of the data buffer. Note we add padding to cover hardware faults
  791. // that may cause the device to go past the end of the data buffer
  792. */
  793. siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 16;
  794. // Get the nonpaged pool memory for the data buffer
  795. configurationDescriptor = ISOPERF_ExAllocatePool(NonPagedPool,
  796. siz,
  797. &gulBytesAllocated);
  798. if (configurationDescriptor != NULL) {
  799. UsbBuildGetDescriptorRequest(urb,
  800. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  801. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  802. 0,
  803. 0,
  804. configurationDescriptor,
  805. NULL,
  806. sizeof (USB_CONFIGURATION_DESCRIPTOR),/* Get only the configuration descriptor */
  807. NULL);
  808. ntStatus = ISOPERF_CallUSBD(DeviceObject, urb);
  809. if (NT_SUCCESS(ntStatus))
  810. {
  811. ISOPERF_KdPrint (("Configuration Descriptor is at %x, bytes txferred: %d\n\
  812. Configuration Descriptor Actual Length: %d\n",
  813. configurationDescriptor,
  814. urb->UrbControlDescriptorRequest.TransferBufferLength,
  815. configurationDescriptor->wTotalLength));
  816. }//if
  817. } else {
  818. ntStatus = STATUS_NO_MEMORY;
  819. goto Exit_ISOPERFConfigureDevice;
  820. }//if-else
  821. // Determine how much data is in the entire configuration descriptor
  822. // and add extra room to protect against accidental overrun
  823. siz = configurationDescriptor->wTotalLength + 16;
  824. if (configurationDescriptor) {
  825. // Free up the data buffer memory just used
  826. ISOPERF_ExFreePool(configurationDescriptor, &gulBytesFreed);
  827. }
  828. configurationDescriptor = NULL;
  829. // Get nonpaged pool memory for the data buffer
  830. configurationDescriptor = ISOPERF_ExAllocatePool(NonPagedPool,
  831. siz,
  832. &gulBytesAllocated);
  833. // Now get the entire Configuration Descriptor
  834. if (configurationDescriptor != NULL) {
  835. UsbBuildGetDescriptorRequest(urb,
  836. (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
  837. USB_CONFIGURATION_DESCRIPTOR_TYPE,
  838. 0,
  839. 0,
  840. configurationDescriptor,
  841. NULL,
  842. siz, // Get all the descriptor data
  843. NULL);
  844. ntStatus = ISOPERF_CallUSBD(DeviceObject, urb);
  845. if (NT_SUCCESS(ntStatus)) {
  846. ISOPERF_KdPrint (("Entire Configuration Descriptor is at %x, bytes txferred: %d\n",
  847. configurationDescriptor,
  848. urb->UrbControlDescriptorRequest.TransferBufferLength));
  849. } else {
  850. //Error in getting configuration descriptor
  851. goto Exit_ISOPERFConfigureDevice;
  852. }//else
  853. } else {
  854. // Failed getting data buffer (configurationDescriptor) memory
  855. ntStatus = STATUS_NO_MEMORY;
  856. goto Exit_ISOPERFConfigureDevice;
  857. }//if-else
  858. } else {
  859. // failed getting urb memory
  860. ntStatus = STATUS_NO_MEMORY;
  861. goto Exit_ISOPERFConfigureDevice;
  862. }//if-else
  863. /*
  864. // We have the configuration descriptor for the configuration
  865. // we want.
  866. //
  867. // Now we issue the SelectConfiguration command to get
  868. // the pipes associated with this configuration.
  869. */
  870. if (configurationDescriptor) {
  871. // Get our pipes
  872. ntStatus = ISOPERF_SelectInterfaces(DeviceObject,
  873. configurationDescriptor,
  874. NULL // Device not yet configured
  875. );
  876. } //if
  877. Exit_ISOPERFConfigureDevice:
  878. // Clean up and exit this routine
  879. if (urb != NULL) {
  880. ISOPERF_ExFreePool(urb, &gulBytesFreed); // Free urb memory
  881. }//if
  882. if (configurationDescriptor != NULL) {
  883. ISOPERF_ExFreePool(configurationDescriptor,&gulBytesFreed);// Free data buffer
  884. }//if
  885. ISOPERF_KdPrint (("exit ISOPERF_ConfigureDevice (%x)\n", ntStatus));
  886. return ntStatus;
  887. }//ISOPERF_ConfigureDevice
  888. NTSTATUS
  889. ISOPERF_SelectInterfaces(
  890. IN PDEVICE_OBJECT DeviceObject,
  891. IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
  892. IN PUSBD_INTERFACE_INFORMATION Interface
  893. )
  894. /*++
  895. Routine Description:
  896. Initializes an ISOPERF Device with multiple interfaces
  897. Note: This routine initializes some memory for the Interface objects in the Device Extension
  898. that must be freed when the device is torn down. So, we do NOT free that memory here, but rather
  899. we free it in the RemoveDevice code path. This note is intended to help anyone who is maintaining
  900. this code. --kjaff 12/20/96
  901. Arguments:
  902. DeviceObject - pointer to the device object for this instance of the ISOPERF Device
  903. ConfigurationDescriptor - pointer to the USB configuration descriptor containing the interface and endpoint
  904. descriptors.
  905. Interface - pointer to a USBD Interface Information Object
  906. - If this is NULL, then this driver must choose its interface based on driver-specific
  907. criteria, and the driver must also CONFIGURE the device.
  908. - If it is NOT NULL, then the driver has already been given an interface and
  909. the device has already been configured by the parent of this device driver.
  910. Return Value:
  911. NT status code
  912. --*/
  913. {
  914. PDEVICE_EXTENSION deviceExtension;
  915. NTSTATUS ntStatus;
  916. PURB urb = NULL;
  917. ULONG siz, numberOfInterfaces, j, nInterfaceNumber, numberOfPipes;
  918. UCHAR alternateSetting, MyInterfaceNumber;
  919. PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
  920. PUSBD_INTERFACE_INFORMATION interfaceObject;
  921. ISOPERF_KdPrint (("enter ISOPERF_SelectInterfaces\n"));
  922. deviceExtension = DeviceObject->DeviceExtension;
  923. MyInterfaceNumber = SAMPLE_INTERFACE_NBR;
  924. if (Interface == NULL) {
  925. /*
  926. // This example driver only supports one interface. This can be extended
  927. // to be a dynamically allocated array by your driver.
  928. */
  929. numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
  930. ISOPERF_KdPrint (("Device has %d Interfaces\n",numberOfInterfaces));
  931. numberOfPipes = 0; // Initialize to zero
  932. /*
  933. // We use alternate interface setting 0 for all interfaces
  934. */
  935. alternateSetting = 0;
  936. /*
  937. // Call a USBD helper function that returns a ptr to a USB Interface Descriptor given
  938. // a USB Configuration Descriptor, an Inteface Number, and an Alternate Setting for that Interface
  939. */
  940. interfaceDescriptor =
  941. USBD_ParseConfigurationDescriptor(ConfigurationDescriptor,
  942. MyInterfaceNumber, //interface number (this is bInterfaceNumber from interface descr)
  943. alternateSetting);
  944. ASSERT(interfaceDescriptor != NULL);
  945. if (interfaceDescriptor != NULL)
  946. {
  947. ISOPERF_KdPrint (("Device has %d Interface(s) | MyInterface (%d) is at: (%#X)\n",
  948. numberOfInterfaces, MyInterfaceNumber, interfaceDescriptor));
  949. } /* if there was a valid interfacedesc */
  950. numberOfPipes = ISOPERF_Internal_GetNumberOfPipes(ConfigurationDescriptor);
  951. ISOPERF_KdPrint (("config has %d pipes total on all the interfaces\n",numberOfPipes));
  952. /*
  953. // Now that we have looked at the interface, we configure the device so that the remainder
  954. // of the USBD objects will come into existence (ie., pipes, etc.) as a result of the configuration,
  955. // thus completing the configuration process for the USB device.
  956. //
  957. // Allocate a URB big enough for this Select Configuration request
  958. //
  959. // NOTE: The new service USBD_CreateConfigurationRequest will replace some of the
  960. // code below. Future releases of this driver will demonstrate how to use
  961. // that service.
  962. //
  963. */
  964. siz = GET_SELECT_CONFIGURATION_REQUEST_SIZE(numberOfInterfaces, numberOfPipes);
  965. ISOPERF_KdPrint (("size of config request Urb = %d for %d interfaces & %d pipes\n",
  966. siz,
  967. numberOfInterfaces,
  968. numberOfPipes));
  969. urb = ISOPERF_ExAllocatePool(NonPagedPool,
  970. siz,
  971. &gulBytesAllocated);
  972. if (urb) {
  973. interfaceObject = (PUSBD_INTERFACE_INFORMATION) (&(urb->UrbSelectConfiguration.Interface));
  974. // set up the input parameters in our interface request structure.
  975. interfaceObject->Length =
  976. GET_USBD_INTERFACE_SIZE(interfaceDescriptor->bNumEndpoints);
  977. ISOPERF_KdPrint (("size of interface request = %d\n", interfaceObject->Length));
  978. ISOPERF_KdPrint (("Selecting interface Number: %d Alternate Setting: %d NumEndpoints %d\n",
  979. interfaceDescriptor->bInterfaceNumber,
  980. interfaceDescriptor->bAlternateSetting,
  981. interfaceDescriptor->bNumEndpoints));
  982. interfaceObject->InterfaceNumber = interfaceDescriptor->bInterfaceNumber;
  983. interfaceObject->AlternateSetting = interfaceDescriptor->bAlternateSetting;
  984. interfaceObject->NumberOfPipes = interfaceDescriptor->bNumEndpoints;
  985. /*
  986. // We set up a default max transfer size for the endpoints. Your driver will
  987. // need to change this to reflect the capabilities of your device's endpoints.
  988. */
  989. for (j=0; j<interfaceDescriptor->bNumEndpoints; j++) {
  990. interfaceObject->Pipes[j].MaximumTransferSize =
  991. USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
  992. } /* for */
  993. ISOPERF_KdPrint (("InterfaceObj Inteface Nbr: %d | InterfaceObj AltSett: %d |NbrPip: %d\n",
  994. interfaceObject->InterfaceNumber,
  995. interfaceObject->AlternateSetting,
  996. interfaceObject->NumberOfPipes));
  997. UsbBuildSelectConfigurationRequest(urb,
  998. (USHORT) siz,
  999. ConfigurationDescriptor);
  1000. ntStatus = ISOPERF_CallUSBD(DeviceObject, urb);
  1001. if (NT_SUCCESS(ntStatus) && USBD_SUCCESS(urb->UrbSelectConfiguration.Status)) {
  1002. // Get mem for the config and stat space (initialize it later; we need it now since some
  1003. // of the info in this struct depends on the endpoint number and we walk thru the ep nbrs below)
  1004. deviceExtension->pConfig_Stat_Information=
  1005. ISOPERF_ExAllocatePool( NonPagedPool,
  1006. sizeof (Config_Stat_Info),
  1007. &gulBytesAllocated);
  1008. deviceExtension->dtTestDeviceType = Unknown_Device_Type;
  1009. ISOPERF_KdPrint (("Trying to figure out what type of device (%x) this is...\n", DeviceObject));
  1010. // Figure out what type of device this is based on the class/subclass/protocol codes and store that
  1011. // in the device extension variable that holds that information
  1012. if (interfaceDescriptor->bInterfaceClass == USB_CLASS_CODE_TEST_CLASS_DEVICE) {
  1013. ISOPERF_KdPrint (("This is a Test Class Device\n"));
  1014. ISOPERF_KdPrint (("Checking Subclass Code (%#X)\n",interfaceDescriptor->bInterfaceSubClass));
  1015. if (interfaceDescriptor->bInterfaceSubClass == USB_SUBCLASS_CODE_TEST_CLASS_ISO) {
  1016. ISOPERF_KdPrint (("This is an ISO Test SubClass Device\n"));
  1017. ISOPERF_KdPrint (("Checking Protocol Code (%#X)\n",interfaceDescriptor->bInterfaceProtocol));
  1018. switch (interfaceDescriptor->bInterfaceProtocol) {
  1019. case USB_PROTOCOL_CODE_TEST_CLASS_INPATTERN:
  1020. case USB_PROTOCOL_CODE_TEST_CLASS_INPATTERN_ALT:
  1021. ISOPERF_KdPrint (("This is an Iso_In_With_Pattern device\n"));
  1022. deviceExtension->dtTestDeviceType = Iso_In_With_Pattern;
  1023. break;
  1024. case USB_PROTOCOL_CODE_TEST_CLASS_OUTINTERR:
  1025. deviceExtension->dtTestDeviceType = Iso_Out_With_Interrupt_Feedback;
  1026. ISOPERF_KdPrint (("This is an Iso_Out_With_Interrupt_Feedback device\n"));
  1027. gMyOutputDevice = DeviceObject; //SHORT term workaround for wdm loading issue
  1028. break;
  1029. case USB_PROTOCOL_CODE_TEST_CLASS_OUTNOCHEK:
  1030. deviceExtension->dtTestDeviceType = Iso_Out_Without_Feedback;
  1031. ISOPERF_KdPrint (("This is an Iso_Out_WithOut_Feedback device\n"));
  1032. gMyOutputDevice = DeviceObject; //SHORT term workaround for wdm loading issue
  1033. break;
  1034. default:
  1035. deviceExtension->dtTestDeviceType = Unknown_Device_Type;
  1036. ISOPERF_KdPrint (("This is an Unknown Protocol Iso test class device type\n"));
  1037. break;
  1038. }//switch on protocol code
  1039. } else {
  1040. ISOPERF_KdPrint (("This is not a Iso Test SubClass Device\n"));
  1041. }//else not a test iso dev sub class code
  1042. }else{
  1043. ISOPERF_KdPrint(("This is not a test class device\n"));
  1044. }//else not a test class dev
  1045. // For each of the interfaces on this device, save away the interface information structure
  1046. // that USBD returned on the SelectConfiguration request
  1047. for (nInterfaceNumber=0; nInterfaceNumber < numberOfInterfaces; nInterfaceNumber++) {
  1048. // Save the configuration handle for this device
  1049. deviceExtension->ConfigurationHandle =
  1050. urb->UrbSelectConfiguration.ConfigurationHandle;
  1051. deviceExtension->Interface[nInterfaceNumber] = ISOPERF_ExAllocatePool(NonPagedPool,
  1052. interfaceObject->Length,
  1053. &gulBytesAllocated);
  1054. if (deviceExtension->Interface[nInterfaceNumber]) {
  1055. // save a copy of the interfaceObject information returned
  1056. RtlCopyMemory(deviceExtension->Interface[nInterfaceNumber], interfaceObject, interfaceObject->Length);
  1057. // Dump the interfaceObject to the debugger
  1058. ISOPERF_KdPrint (("---------\n"));
  1059. ISOPERF_KdPrint (("NumberOfPipes 0x%x\n", deviceExtension->Interface[nInterfaceNumber]->NumberOfPipes));
  1060. ISOPERF_KdPrint (("Length 0x%x\n", deviceExtension->Interface[nInterfaceNumber]->Length));
  1061. ISOPERF_KdPrint (("Alt Setting 0x%x\n", deviceExtension->Interface[nInterfaceNumber]->AlternateSetting));
  1062. ISOPERF_KdPrint (("Interface Number 0x%x\n", deviceExtension->Interface[nInterfaceNumber]->InterfaceNumber));
  1063. // Dump the pipe info
  1064. for (j=0; j<interfaceObject->NumberOfPipes; j++) {
  1065. PUSBD_PIPE_INFORMATION pipeInformation;
  1066. pipeInformation = &deviceExtension->Interface[nInterfaceNumber]->Pipes[j];
  1067. ISOPERF_KdPrint (("---------\n"));
  1068. ISOPERF_KdPrint (("PipeType 0x%x\n", pipeInformation->PipeType));
  1069. ISOPERF_KdPrint (("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
  1070. ISOPERF_KdPrint (("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
  1071. ISOPERF_KdPrint (("Interval 0x%x\n", pipeInformation->Interval));
  1072. ISOPERF_KdPrint (("Handle 0x%x\n", pipeInformation->PipeHandle));
  1073. ISOPERF_KdPrint (("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));
  1074. //NOTE: we only care about the first 2 endpoints on these devices (they must be the first 2 endpoints!)
  1075. if ((USB_ENDPOINT_DIRECTION_IN(pipeInformation->EndpointAddress)) && (j<2)) {
  1076. deviceExtension->pConfig_Stat_Information->ulMaxPacketSize_IN =pipeInformation->MaximumPacketSize;
  1077. deviceExtension->pConfig_Stat_Information->ulMaxPacketSize_OUT =0;
  1078. ISOPERF_KdPrint (("Endpoint %d is IN\n", j+1));
  1079. }
  1080. else if ((USB_ENDPOINT_DIRECTION_OUT(pipeInformation->EndpointAddress)) && (j<2)) {
  1081. deviceExtension->pConfig_Stat_Information->ulMaxPacketSize_OUT =pipeInformation->MaximumPacketSize;
  1082. deviceExtension->pConfig_Stat_Information->ulMaxPacketSize_IN =0;
  1083. ISOPERF_KdPrint (("Endpoint %d is OUT\n", j+1));
  1084. }//else it is an OUT endpoint
  1085. }/* for all the pipes in this interface */
  1086. ISOPERF_KdPrint (("---------\n"));
  1087. } /*If ExAllocate passed */
  1088. }/* for all the interfaces on this device */
  1089. // Init the rest of the config and stat space
  1090. deviceExtension->pConfig_Stat_Information->ulNumberOfFrames =10;
  1091. deviceExtension->pConfig_Stat_Information->ulMax_Urbs_Per_Pipe =4;
  1092. deviceExtension->pConfig_Stat_Information->ulSuccessfulIrps =0;
  1093. deviceExtension->pConfig_Stat_Information->ulUnSuccessfulIrps =0;
  1094. deviceExtension->pConfig_Stat_Information->ulBytesTransferredIn =0;
  1095. deviceExtension->pConfig_Stat_Information->ulBytesTransferredOut =0;
  1096. deviceExtension->pConfig_Stat_Information->erError =NoError;
  1097. deviceExtension->pConfig_Stat_Information->bStopped =0;
  1098. deviceExtension->pConfig_Stat_Information->ulFrameOffset =200;
  1099. deviceExtension->pConfig_Stat_Information->ulStartingFrameNumber =0;
  1100. deviceExtension->pConfig_Stat_Information->ulFrameNumberAtStart =0;
  1101. deviceExtension->pConfig_Stat_Information->UsbdPacketStatCode =0;
  1102. deviceExtension->pConfig_Stat_Information->UrbStatusCode =0;
  1103. deviceExtension->pConfig_Stat_Information->ulFrameOffsetMate =0;
  1104. deviceExtension->pConfig_Stat_Information->bDeviceRunning =0;
  1105. }/* if selectconfiguration request was successful */
  1106. else {
  1107. ISOPERF_KdPrint (("Select Configuration Request Failed (urb status: %x)\n",
  1108. urb->UrbSelectConfiguration.Status));
  1109. }/* else selectconfiguration request failed */
  1110. } else {
  1111. ntStatus = STATUS_NO_MEMORY;
  1112. }/* if urb alloc passed */
  1113. }//if Interface was not NULL
  1114. // Clean up
  1115. if (urb != NULL) {
  1116. ISOPERF_ExFreePool (urb, &gulBytesFreed);
  1117. }/* if valid Urb */
  1118. ISOPERF_KdPrint (("exit ISOPERF_SelectInterfaces (%x)\n", ntStatus));
  1119. return ntStatus;
  1120. }/* ISOPERF_SelectInterfaces */
  1121. NTSTATUS
  1122. ISOPERF_CallUSBDEx (
  1123. IN PDEVICE_OBJECT DeviceObject,
  1124. IN PURB Urb,
  1125. IN BOOLEAN fBlock,
  1126. PIO_COMPLETION_ROUTINE CompletionRoutine,
  1127. PVOID pvContext,
  1128. BOOLEAN fWantTimeOut
  1129. )
  1130. /**************************************************************************
  1131. Routine Description:
  1132. Passes a URB to the USBD class driver
  1133. NOTE: Creates an IRP to do this. Doesn't use the IRP that is passed down from user
  1134. mode app (it's not passed to this routine at all).
  1135. Arguments:
  1136. DeviceObject - pointer to the device object for this instance of a UTB
  1137. Urb - pointer to Urb request block
  1138. fBlock - bool indicating if this fn should wait for IRP to return from USBD
  1139. CompletionRoutine - fn to set as the completionroutine for this transfer ONLY IF
  1140. the fBlock is set to FALSE, indicating that the caller wants
  1141. to handle completion on their own and this fn should not
  1142. block
  1143. pvContext - Context to be set in setting up the completion routine for the
  1144. Irp created in this function. This is passed in by caller and is
  1145. just a pass-thru to the IoSetCompletionRoutine call. If this is NULL
  1146. but there is a CompletionRoutine specified, then the Irp that is created
  1147. in this app is used as the context.
  1148. fWantTimeOut - If caller wants this function to use a deadman timeout and cancel
  1149. the Irp after the timeout expires. TRUE means this function will
  1150. use the timeout mechanism, and FALSE means this function will block
  1151. indefinitely and wait for the Irp/Urb to return from the USB stack.
  1152. Return Value:
  1153. STATUS_SUCCESS if successful,
  1154. STATUS_UNSUCCESSFUL otherwise
  1155. **************************************************************************/
  1156. {
  1157. NTSTATUS ntStatus, status;
  1158. PDEVICE_EXTENSION deviceExtension;
  1159. PIRP irp;
  1160. KEVENT event;
  1161. PIO_STATUS_BLOCK ioStatus;
  1162. PIO_STACK_LOCATION nextStack;
  1163. BOOLEAN haveTimer=FALSE;
  1164. LARGE_INTEGER dueTime;
  1165. ISOPERF_KdPrint_MAXDEBUG (("enter ISOPERF_CallUSBDEx\n"));
  1166. /*
  1167. {
  1168. KIRQL irql;
  1169. irql = KeGetCurrentIrql();
  1170. ASSERT(irql <= PASSIVE_LEVEL);
  1171. }
  1172. */
  1173. deviceExtension = DeviceObject->DeviceExtension;
  1174. ASSERT (deviceExtension != NULL);
  1175. ASSERT ((deviceExtension->StackDeviceObject) != NULL);
  1176. if ((deviceExtension) && (deviceExtension->StackDeviceObject))
  1177. {
  1178. if (fBlock) {
  1179. // issue a synchronous request to read the USB Device Ctrl pipe
  1180. KeInitializeEvent(&event, NotificationEvent, FALSE);
  1181. }/* if block requested */
  1182. // Create the memory for the Io Status Block
  1183. ioStatus = ISOPERF_ExAllocatePool (NonPagedPool, sizeof (IO_STATUS_BLOCK), &gulBytesAllocated);
  1184. // Create the IRP that we'll use to submit this URB to the USB stack
  1185. irp = IoBuildDeviceIoControlRequest(
  1186. IOCTL_INTERNAL_USB_SUBMIT_URB,
  1187. deviceExtension->StackDeviceObject,
  1188. NULL,
  1189. 0,
  1190. NULL,
  1191. 0,
  1192. TRUE, /* INTERNAL */
  1193. fBlock ? &event : NULL,
  1194. ioStatus); //the status codes in NT IRPs go here
  1195. // remove this Irp from the current thread's list
  1196. RemoveEntryList(&irp->ThreadListEntry);
  1197. // Call the class driver to perform the operation. If the returned status
  1198. // is PENDING, wait for the request to complete.
  1199. nextStack = IoGetNextIrpStackLocation(irp);
  1200. ASSERT(nextStack != NULL);
  1201. // pass the URB to the USBD 'class driver'
  1202. nextStack->Parameters.Others.Argument1 = Urb;
  1203. // If caller doesn't want this fn to block, then set the iocompletion routine up
  1204. // for them
  1205. if (fBlock == FALSE) {
  1206. ASSERT (CompletionRoutine != NULL);
  1207. ISOPERF_KdPrint_MAXDEBUG (("Setting compl routine\n"));
  1208. // If the user didn't supply a context, then we'll use the irp as the context
  1209. if (pvContext==NULL) {
  1210. ISOPERF_KdPrint (("No context supplied...setting Irp as context\n"));
  1211. pvContext = (PVOID)irp;
  1212. }
  1213. IoSetCompletionRoutine(irp,
  1214. CompletionRoutine,
  1215. pvContext,
  1216. TRUE, //InvokeOnSuccess
  1217. TRUE, //InvokeOnError,
  1218. FALSE); //InvokeOnCancel
  1219. }//if
  1220. ISOPERF_KdPrint_MAXDEBUG (("calling USBD\n"));
  1221. ntStatus = IoCallDriver(deviceExtension->StackDeviceObject,
  1222. irp);
  1223. // Register that another Irp was put into the stack by incrementing a counter in the dev extension
  1224. if (ntStatus == STATUS_PENDING)
  1225. (deviceExtension->ulNumberOfOutstandingIrps)++;
  1226. // If the Irp came back w/ SUCCESS, then it finished synchronously, so free the IoStatus Block
  1227. if ((ntStatus == STATUS_SUCCESS) && (fBlock == FALSE)) {
  1228. //Free the IoStatus block that we created for this call
  1229. if (irp->UserIosb) {
  1230. ISOPERF_ExFreePool (irp->UserIosb, &gulBytesFreed);
  1231. }else{
  1232. //Bogus iostatus pointer. Bad.
  1233. ISOPERF_KdPrint (("ERROR: Irp's IoStatus block is apparently NULL!\n"));
  1234. TRAP();
  1235. }//else bad iostatus pointer
  1236. }//if successful (sync) Irp
  1237. ISOPERF_KdPrint_MAXDEBUG (("return from IoCallDriver USBD in ISOPERF_CallUSBDEx %x\n", ntStatus));
  1238. // After calling USBD only block if the caller requested a block
  1239. if ((ntStatus == STATUS_PENDING) && (fBlock == TRUE))
  1240. {
  1241. if (fWantTimeOut == TRUE) {
  1242. // Setup timer stuff so we can timeout commands to unresponsive devices
  1243. KeInitializeTimer(&(deviceExtension->TimeoutTimer)); //build the timer object
  1244. KeInitializeDpc(&(deviceExtension->TimeoutDpc), //set up the DPC call based
  1245. ISOPERF_SyncTimeoutDPC, //DPC func
  1246. irp); //context ptr to pass into DPC func
  1247. dueTime.QuadPart = -10000 * DEADMAN_TIMEOUT;
  1248. //NOTE: (kjaff) KeSetTimer returns FALSE for unknown reason so we will hack for now
  1249. // and pretend we were successful in setting the timer up
  1250. KeSetTimer(&(deviceExtension->TimeoutTimer), //Set the timer params up
  1251. dueTime, //This is how long to wait
  1252. &(deviceExtension->TimeoutDpc)); //This is the DPC object we created
  1253. haveTimer = TRUE; //our own local var to finger out if we
  1254. } // if fWantTimeOut == TRUE
  1255. ISOPERF_KdPrint_MAXDEBUG (("Waiting for single object\n"));
  1256. status = KeWaitForSingleObject(
  1257. &event,
  1258. Suspended,
  1259. KernelMode,
  1260. FALSE,
  1261. NULL);
  1262. // Since we waited on the Irp we can safely say it's not outstanding anymore if the Wait completes
  1263. (deviceExtension -> ulNumberOfOutstandingIrps)--;
  1264. ISOPERF_KdPrint_MAXDEBUG (("Wait for single object, returned %x\n", status));
  1265. // Now free the IoStatus block since we're done with this Irp (we blocked)
  1266. if (irp->UserIosb) {
  1267. ISOPERF_ExFreePool (irp->UserIosb, &gulBytesFreed);
  1268. }else{
  1269. //Bogus iostatus pointer. Bad.
  1270. ISOPERF_KdPrint (("ERROR: Irp's IoStatus block is apparently NULL!\n"));
  1271. TRAP();
  1272. }//else bad iostatus pointer
  1273. } //if pending and we want to block
  1274. else
  1275. {
  1276. ISOPERF_KdPrint_MAXDEBUG (("Didn't block calling usbd\n"));
  1277. ioStatus->Status = ntStatus;
  1278. }//else we didn't want to block or we didn't get a status pending (it completed)
  1279. ISOPERF_KdPrint_MAXDEBUG (("URB status = %x status = %x irp status %x\n",
  1280. Urb->UrbHeader.Status, status, ioStatus->Status));
  1281. // USBD maps the error code for us
  1282. ntStatus = ioStatus->Status;
  1283. ISOPERF_KdPrint_MAXDEBUG(("URB TransferBufferLength OUT is: %d\n",Urb->UrbControlDescriptorRequest.TransferBufferLength));
  1284. if ((haveTimer==TRUE) && (ntStatus!=STATUS_CANCELLED)) {
  1285. ISOPERF_KdPrint_MAXDEBUG (("Irp wasn't cancelled, so cancelling Timer (%x)\n", (&(deviceExtension->TimeoutTimer))));
  1286. KeCancelTimer(&(deviceExtension->TimeoutTimer));
  1287. ISOPERF_KdPrint_MAXDEBUG (("Done cancelling timer\n"));
  1288. }//if
  1289. }//if valid deviceExtension and StackDevObjects
  1290. else
  1291. {
  1292. // Invalid extension or stackdevobj received
  1293. ntStatus = STATUS_INVALID_PARAMETER;
  1294. ISOPERF_KdPrint_MAXDEBUG (("Invalid deviceExtension or StackDeviceObject\n"));
  1295. } //else invalid devExt or stackdevobj
  1296. ISOPERF_KdPrint_MAXDEBUG(("exiting ISOPERF_CallUSBDEx w/ URB/ntStatus: %x\n", ntStatus));
  1297. return ntStatus;
  1298. }//ISOPERF_CallUSBDEx
  1299. VOID
  1300. ISOPERF_SyncTimeoutDPC(
  1301. IN PKDPC Dpc,
  1302. IN PVOID DeferredContext,
  1303. IN PVOID SystemArgument1,
  1304. IN PVOID SystemArgument2
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. This routine runs at DISPATCH_LEVEL IRQL.
  1309. Arguments:
  1310. Dpc - Pointer to the DPC object.
  1311. DeferredContext - passed in to IOS by caller as context (we use it as pIrp)
  1312. SystemArgument1 - not used.
  1313. SystemArgument2 - not used.
  1314. Return Value:
  1315. None.
  1316. --*/
  1317. {
  1318. BOOLEAN status;
  1319. PIRP irp = DeferredContext;
  1320. TRAP();
  1321. // The cancel Irp call below will return immediately, but that doesn't mean things are all
  1322. // cleaned up in the USB stack. The only way to be assured of that is when the
  1323. // WaitForSingleObject that blocked in the first place returns (due to the USB stack
  1324. // completing the Irp, either due to normal completion or due to this cancel Irp call.
  1325. status = IoCancelIrp(irp);
  1326. //NOTE: (kosar) We don't do anything if the cancel fails, and we probably should.
  1327. // (like maybe reschedule or something)
  1328. return;
  1329. }
  1330. ULONG
  1331. ISOPERF_Internal_GetNumberOfPipes(
  1332. PUSB_CONFIGURATION_DESCRIPTOR pCD
  1333. )
  1334. /*++
  1335. Routine Description:
  1336. Tallies up the total number of pipes in a given configuration descriptor
  1337. Arguments:
  1338. Pointer to a Configuration Descriptor
  1339. Return Value:
  1340. Non-zero number indicating total number of pipes in the given configuration.
  1341. A value of FFFFFFFF indicates an invalid Configuration Descriptor was received.
  1342. --*/
  1343. {
  1344. int nInterfaceNumber = 0;
  1345. char * pcWorkerPtr = NULL;
  1346. ULONG ulNumberOfPipes = 0;
  1347. PUSB_INTERFACE_DESCRIPTOR pID = NULL;
  1348. ISOPERF_KdPrint (("Enter GetNumberOfPipes (%X)\n",pCD));
  1349. //Check if the given descriptor is a valid config descriptor
  1350. if (pCD->bDescriptorType != USB_CONFIGURATION_DESCRIPTOR_TYPE) {
  1351. ISOPERF_KdPrint (("GetNumberOfPipes got a bogus ConfDesc: (%X) (type=%d)\n",pCD,pCD->bDescriptorType));
  1352. return (0xFFFFFFFF);
  1353. }//if bad config descriptor
  1354. //Point to the interface descriptor
  1355. pID = (PUSB_INTERFACE_DESCRIPTOR) ((((char*)pCD) + pCD->bLength));
  1356. for (nInterfaceNumber = 0; nInterfaceNumber < pCD->bNumInterfaces; nInterfaceNumber++)
  1357. {
  1358. //Check if this an Interface Descriptor
  1359. if ((pID->bDescriptorType) != USB_INTERFACE_DESCRIPTOR_TYPE) {
  1360. //NOTE right now we just give out and return an error. This should be fixed
  1361. //to look for a class specific descriptor and try to step over it and go on to find
  1362. //the interface descriptor, but since our 82930 boards will not have class descriptors
  1363. //embedded in there for now, we'll just abort to safeguard against bogus descriptors.
  1364. ISOPERF_KdPrint (("GetNumberOfPipes got a bogus InterfDesc: (%X) (type=%d)\n",pID,pID->bDescriptorType));
  1365. return (0xFFFFFFFF);
  1366. }//if not an interface descriptor
  1367. //Add to tally of number of pipes for this interface
  1368. ulNumberOfPipes += pID->bNumEndpoints;
  1369. //Go to next interface
  1370. pcWorkerPtr = (char*)pID;
  1371. pcWorkerPtr += (pID->bLength) +
  1372. (pID->bNumEndpoints * sizeof (USB_ENDPOINT_DESCRIPTOR));
  1373. // Now you should be pointing to the next interface descriptor
  1374. pID = (PUSB_INTERFACE_DESCRIPTOR) pcWorkerPtr;
  1375. }// for all the interfaces on this config
  1376. ISOPERF_KdPrint (("Exit GetNumberOfPipes: (%d)\n",ulNumberOfPipes));
  1377. return (ulNumberOfPipes);
  1378. }//ISOPERF_Internal_GetNumberOfPipes
  1379. #ifndef TOM_MEM
  1380. PVOID
  1381. ISOPERF_ExAllocatePool(
  1382. IN POOL_TYPE PoolType,
  1383. IN ULONG NumberOfBytes,
  1384. IN PULONG pTallyOfBytesAllocated
  1385. )
  1386. {
  1387. PUCHAR pch;
  1388. PULONG length;
  1389. NumberOfBytes += sizeof(ULONG);
  1390. if (pTallyOfBytesAllocated)
  1391. *pTallyOfBytesAllocated += NumberOfBytes;
  1392. pch = ExAllocatePool(PoolType, NumberOfBytes);
  1393. if (pch) {
  1394. length = (PULONG) pch;
  1395. *length = NumberOfBytes;
  1396. ISOPERF_KdPrint_MAXDEBUG (("Allocated %d bytes at %x | TotBytesAlloc: %d\n",NumberOfBytes, pch, *pTallyOfBytesAllocated));
  1397. return (pch+(sizeof(ULONG)));
  1398. } else {
  1399. return NULL;
  1400. }
  1401. }
  1402. VOID
  1403. ISOPERF_ExFreePool(
  1404. IN PVOID P,
  1405. IN PULONG pTallyOfBytesFreed
  1406. )
  1407. {
  1408. PUCHAR pch;
  1409. ULONG length;
  1410. pch = P;
  1411. pch = pch-sizeof(ULONG);
  1412. length = *(PULONG)(pch);
  1413. if (pTallyOfBytesFreed)
  1414. *pTallyOfBytesFreed += (length);
  1415. ISOPERF_KdPrint_MAXDEBUG (("Freeing %d bytes at %x | TotBytesFreed %d\n",length, pch, *pTallyOfBytesFreed));;
  1416. memset(pch, 0xff, length);
  1417. ExFreePool(pch);
  1418. }
  1419. #endif
  1420. #ifdef TOM_MEM
  1421. #define MEM_SIGNATURE ((ULONG) 'CLLA')
  1422. #define MEM_FREED_SIGNATURE ((ULONG) 'EERF')
  1423. PVOID
  1424. ISOPERF_ExAllocatePool(
  1425. IN POOL_TYPE PoolType,
  1426. IN ULONG NumberOfBytes,
  1427. IN PULONG pTallyOfBytesAllocated
  1428. )
  1429. {
  1430. PULONG pMem;
  1431. // allocate memory plus a little extra for our own use
  1432. pMem = ExAllocatePool(PoolType, NumberOfBytes + (2 * sizeof(ULONG)));
  1433. // see if we actually allocated any memory
  1434. if(pMem)
  1435. {
  1436. // keep track of how much we allocated
  1437. *pTallyOfBytesAllocated += NumberOfBytes;
  1438. // store number of bytes allocated at start of memory allocated
  1439. *pMem++ = NumberOfBytes;
  1440. // now we are pointing at the memory allocated for caller
  1441. // put signature word at end
  1442. // get new pointer that points to end of buffer - ULONG
  1443. pMem = (PULONG) (((PUCHAR) pMem) + NumberOfBytes);
  1444. // write signature
  1445. *pMem = MEM_SIGNATURE;
  1446. // get back pointer to return to caller
  1447. pMem = (PULONG) (((PUCHAR) pMem) - NumberOfBytes);
  1448. }
  1449. //debug only
  1450. ISOPERF_KdPrint_MAXDEBUG (("Allocated %d bytes | returning pv = %x\n",NumberOfBytes,pMem));
  1451. //end debug only
  1452. return (PVOID) pMem;
  1453. }
  1454. VOID
  1455. ISOPERF_ExFreePool(
  1456. IN PVOID P,
  1457. IN PULONG pTallyOfBytesFreed
  1458. )
  1459. {
  1460. PULONG pTmp = (PULONG) P;
  1461. ULONG buffSize;
  1462. PULONG pSav=pTmp;
  1463. // point at size ULONG at start of buffer, and address to free
  1464. pTmp--;
  1465. // get the size of memory allocated by caller
  1466. buffSize = *pTmp;
  1467. // point at signature and make sure it's O.K.
  1468. ((PCHAR) P) += buffSize;
  1469. if(*((PULONG) P) == MEM_SIGNATURE)
  1470. {
  1471. // let's go ahead and get rid of signature in case we get called
  1472. // with this pointer again and memory is still paged in
  1473. *((PULONG) P) = MEM_FREED_SIGNATURE;
  1474. // adjust amount of memory allocated
  1475. *pTallyOfBytesFreed += buffSize;
  1476. // free real pointer
  1477. ExFreePool(pTmp);
  1478. ISOPERF_KdPrint_MAXDEBUG (("Freed %d bytes at %x (pvBuff: %x)\n",buffSize, pTmp, (((PUCHAR)pTmp)+sizeof(buffSize)) ));
  1479. }
  1480. else {
  1481. //debug only
  1482. ISOPERF_KdPrint (("ISOPERF_ExFreePool found incorrect mem signature: %x at %x (orig buff Ptr: %x)\n",*((PULONG)P), P, pSav));
  1483. ISOPERF_KdPrint (("BufferSize: %d\n",buffSize));
  1484. //end debug only
  1485. TRAP();
  1486. }//else
  1487. }
  1488. #endif
  1489. NTSTATUS
  1490. ISOPERF_Create(
  1491. IN PDEVICE_OBJECT DeviceObject,
  1492. IN PIRP Irp
  1493. )
  1494. /*++
  1495. Routine Description:
  1496. This is the Entry point for CreateFile calls from user mode apps (apps may open "\\.\ISOPERF-x\yyzz"
  1497. where yy is the interface number and zz is the endpoint address).
  1498. Here is where you would add code to create symbolic links between endpoints
  1499. (i.e., pipes in USB software terminology) and User Mode file names. You are
  1500. free to use any convention you wish to create these links, although the above
  1501. convention offers a way to identify resources on a device by familiar file and
  1502. directory structure nomenclature.
  1503. Arguments:
  1504. DeviceObject - pointer to the device object for this instance of the ISOPERF device
  1505. Return Value:
  1506. NT status code
  1507. --*/
  1508. {
  1509. NTSTATUS ntStatus;
  1510. Irp->IoStatus.Status = STATUS_SUCCESS;
  1511. Irp->IoStatus.Information = 0;
  1512. ISOPERF_KdPrint_MAXDEBUG (("In ISOPERF_Create\n"));
  1513. ntStatus = Irp->IoStatus.Status;
  1514. IoCompleteRequest (Irp,
  1515. IO_NO_INCREMENT
  1516. );
  1517. ISOPERF_KdPrint_MAXDEBUG (("Exit ISOPERF_Create (%x)\n", ntStatus));
  1518. return ntStatus;
  1519. }//ISOPERF_Create
  1520. NTSTATUS
  1521. ISOPERF_Close(
  1522. IN PDEVICE_OBJECT DeviceObject,
  1523. IN PIRP Irp
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. Entry point for CloseHandle calls from user mode apps to close handles they have opened
  1528. Arguments:
  1529. DeviceObject - pointer to the device object for this instance of the ISOPERF device
  1530. Irp - pointer to an irp
  1531. Return Value:
  1532. NT status code
  1533. --*/
  1534. {
  1535. NTSTATUS ntStatus = STATUS_SUCCESS;
  1536. Irp->IoStatus.Status = STATUS_SUCCESS;
  1537. Irp->IoStatus.Information = 0;
  1538. ISOPERF_KdPrint_MAXDEBUG (("In ISOPERF_Close\n"));
  1539. IoCompleteRequest (Irp,
  1540. IO_NO_INCREMENT
  1541. );
  1542. ISOPERF_KdPrint_MAXDEBUG (("Exit ISOPERF_Close (%x)\n", ntStatus));
  1543. return ntStatus;
  1544. }//ISOPERF_Close
  1545. NTSTATUS
  1546. ISOPERF_Read(
  1547. IN PDEVICE_OBJECT DeviceObject,
  1548. IN PIRP Irp
  1549. )
  1550. /*++
  1551. Routine Description:
  1552. This function is called for a IRP_MJ_READ.
  1553. TODO: Add functionality here for your device driver if it handles that IRP code.
  1554. Arguments:
  1555. DeviceObject - pointer to the device object for this instance of the ISOPERF device.
  1556. Irp - pointer to IRP
  1557. Return Value:
  1558. NT status code
  1559. --*/
  1560. {
  1561. NTSTATUS ntStatus = STATUS_SUCCESS;
  1562. return (ntStatus);
  1563. }
  1564. NTSTATUS
  1565. ISOPERF_Write(
  1566. IN PDEVICE_OBJECT DeviceObject,
  1567. IN PIRP Irp
  1568. )
  1569. /*++
  1570. Routine Description:
  1571. This function is called for a IRP_MJ_WRITE.
  1572. TODO: Add functionality here for your device driver if it handles that IRP code.
  1573. Arguments:
  1574. DeviceObject - pointer to the device object for this instance of the ISOPERF device.
  1575. Irp - pointer to IRP
  1576. Return Value:
  1577. NT status code
  1578. --*/
  1579. {
  1580. NTSTATUS ntStatus = STATUS_SUCCESS;
  1581. return (ntStatus);
  1582. }