Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1286 lines
32 KiB

  1. /*++
  2. Copyright (c) 1997-1998 Microsoft Corporation
  3. Module Name:
  4. RwIso.c
  5. Abstract:
  6. Console test app for IsoUsb.sys driver
  7. Environment:
  8. user 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) 1997-1998 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 11/17/97: created
  17. --*/
  18. #include <windows.h>
  19. #include <conio.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <assert.h>
  23. #include <time.h>
  24. #include "devioctl.h"
  25. #include <setupapi.h>
  26. #include <basetyps.h>
  27. #include "IsoUsr.h"
  28. #include "usbdi.h"
  29. #define NOISY(_x_) printf _x_ ;
  30. char inPipe[32] = "PIPE04"; // pipe name for iso input pipe on our test board
  31. char outPipe[32] = "PIPE05"; // pipe name for iso output pipe on our test board
  32. char completeDeviceName[256] = ""; //generated from the GUID registered by the driver itself
  33. BOOL fDumpUsbConfig = FALSE; // flags set in response to console command line switches
  34. BOOL fDumpReadData = FALSE;
  35. BOOL fRead = FALSE;
  36. BOOL fWrite = FALSE;
  37. PVOID gpStreamObj;
  38. char gbuf[256];
  39. BOOL fIsoStreamStarted = FALSE;
  40. HANDLE ghStreamDev = NULL;
  41. int gMS = 10000; // default to 10 secs stream test
  42. int gDebugLevel = 1; // higher == more verbose, default is 1, 0 turns off all
  43. ULONG IterationCount = 1; // count of iterations of the test we are to perform
  44. int WriteLen = 0; // #bytes to write
  45. int ReadLen = 0; // #bytes to read
  46. void StartIsoStream( void );
  47. void StopIsoStream( void );
  48. // functions
  49. HANDLE
  50. OpenOneDevice (
  51. IN HDEVINFO HardwareDeviceInfo,
  52. IN PSP_DEVICE_INTERFACE_DATA DeviceInfoData,
  53. IN char *devName
  54. )
  55. /*++
  56. Routine Description:
  57. Given the HardwareDeviceInfo, representing a handle to the plug and
  58. play information, and deviceInfoData, representing a specific usb device,
  59. open that device and fill in all the relevant information in the given
  60. USB_DEVICE_DESCRIPTOR structure.
  61. Arguments:
  62. HardwareDeviceInfo: handle to info obtained from Pnp mgr via SetupDiGetClassDevs()
  63. DeviceInfoData: ptr to info obtained via SetupDiEnumDeviceInterfaces()
  64. Return Value:
  65. return HANDLE if the open and initialization was successfull,
  66. else INVLAID_HANDLE_VALUE.
  67. --*/
  68. {
  69. PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData = NULL;
  70. ULONG predictedLength = 0;
  71. ULONG requiredLength = 0;
  72. HANDLE hOut = INVALID_HANDLE_VALUE;
  73. //
  74. // allocate a function class device data structure to receive the
  75. // goods about this particular device.
  76. //
  77. SetupDiGetDeviceInterfaceDetail (
  78. HardwareDeviceInfo,
  79. DeviceInfoData,
  80. NULL, // probing so no output buffer yet
  81. 0, // probing so output buffer length of zero
  82. &requiredLength,
  83. NULL); // not interested in the specific dev-node
  84. predictedLength = requiredLength;
  85. // sizeof (SP_FNCLASS_DEVICE_DATA) + 512;
  86. functionClassDeviceData = malloc (predictedLength);
  87. if(NULL == functionClassDeviceData) {
  88. return INVALID_HANDLE_VALUE;
  89. }
  90. functionClassDeviceData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
  91. //
  92. // Retrieve the information from Plug and Play.
  93. //
  94. if (! SetupDiGetDeviceInterfaceDetail (
  95. HardwareDeviceInfo,
  96. DeviceInfoData,
  97. functionClassDeviceData,
  98. predictedLength,
  99. &requiredLength,
  100. NULL)) {
  101. free( functionClassDeviceData );
  102. return INVALID_HANDLE_VALUE;
  103. }
  104. strcpy( devName,functionClassDeviceData->DevicePath) ;
  105. printf( "Attempting to open %s\n", devName );
  106. hOut = CreateFile (
  107. functionClassDeviceData->DevicePath,
  108. GENERIC_READ | GENERIC_WRITE,
  109. FILE_SHARE_READ | FILE_SHARE_WRITE,
  110. NULL, // no SECURITY_ATTRIBUTES structure
  111. OPEN_EXISTING, // No special create flags
  112. 0, // No special attributes
  113. NULL); // No template file
  114. if (INVALID_HANDLE_VALUE == hOut) {
  115. printf( "FAILED to open %s\n", devName );
  116. }
  117. free( functionClassDeviceData );
  118. return hOut;
  119. }
  120. HANDLE
  121. OpenUsbDevice( LPGUID pGuid, char *outNameBuf)
  122. /*++
  123. Routine Description:
  124. Do the required PnP things in order to find
  125. the next available proper device in the system at this time.
  126. Arguments:
  127. pGuid: ptr to GUID registered by the driver itself
  128. outNameBuf: the generated name for this device
  129. Return Value:
  130. return HANDLE if the open and initialization was successful,
  131. else INVLAID_HANDLE_VALUE.
  132. --*/
  133. {
  134. ULONG NumberDevices;
  135. HANDLE hOut = INVALID_HANDLE_VALUE;
  136. HDEVINFO hardwareDeviceInfo;
  137. SP_DEVICE_INTERFACE_DATA deviceInfoData;
  138. ULONG i;
  139. BOOLEAN done;
  140. PUSB_DEVICE_DESCRIPTOR usbDeviceInst;
  141. PUSB_DEVICE_DESCRIPTOR *UsbDevices = &usbDeviceInst;
  142. PUSB_DEVICE_DESCRIPTOR tempDevDesc;
  143. *UsbDevices = NULL;
  144. tempDevDesc = NULL;
  145. NumberDevices = 0;
  146. //
  147. // Open a handle to the plug and play dev node.
  148. // SetupDiGetClassDevs() returns a device information set that contains info on all
  149. // installed devices of a specified class.
  150. //
  151. hardwareDeviceInfo = SetupDiGetClassDevs (
  152. pGuid,
  153. NULL, // Define no enumerator (global)
  154. NULL, // Define no
  155. (DIGCF_PRESENT | // Only Devices present
  156. DIGCF_DEVICEINTERFACE)); // Function class devices.
  157. //
  158. // Take a wild guess at the number of devices we have;
  159. // Be prepared to realloc and retry if there are more than we guessed
  160. //
  161. NumberDevices = 4;
  162. done = FALSE;
  163. deviceInfoData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
  164. i=0;
  165. while (!done) {
  166. NumberDevices *= 2;
  167. if (*UsbDevices) {
  168. tempDevDesc =
  169. realloc (*UsbDevices, (NumberDevices * sizeof (USB_DEVICE_DESCRIPTOR)));
  170. if(tempDevDesc) {
  171. *UsbDevices = tempDevDesc;
  172. tempDevDesc = NULL;
  173. }
  174. else {
  175. free(*UsbDevices);
  176. *UsbDevices = NULL;
  177. }
  178. } else {
  179. *UsbDevices = calloc (NumberDevices, sizeof (USB_DEVICE_DESCRIPTOR));
  180. }
  181. if (NULL == *UsbDevices) {
  182. // SetupDiDestroyDeviceInfoList destroys a device information set
  183. // and frees all associated memory.
  184. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  185. return INVALID_HANDLE_VALUE;
  186. }
  187. usbDeviceInst = *UsbDevices + i;
  188. for (; i < NumberDevices; i++) {
  189. // SetupDiEnumDeviceInterfaces() returns information about device interfaces
  190. // exposed by one or more devices. Each call returns information about one interface;
  191. // the routine can be called repeatedly to get information about several interfaces
  192. // exposed by one or more devices.
  193. if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
  194. 0, // We don't care about specific PDOs
  195. pGuid,
  196. i,
  197. &deviceInfoData)) {
  198. hOut = OpenOneDevice (hardwareDeviceInfo, &deviceInfoData, outNameBuf);
  199. if ( hOut != INVALID_HANDLE_VALUE ) {
  200. done = TRUE;
  201. break;
  202. }
  203. } else {
  204. if (ERROR_NO_MORE_ITEMS == GetLastError()) {
  205. done = TRUE;
  206. break;
  207. }
  208. }
  209. }
  210. }
  211. NumberDevices = i;
  212. // SetupDiDestroyDeviceInfoList() destroys a device information set
  213. // and frees all associated memory.
  214. SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
  215. free ( *UsbDevices );
  216. return hOut;
  217. }
  218. BOOL
  219. GetUsbDeviceFileName( LPGUID pGuid, char *outNameBuf)
  220. /*++
  221. Routine Description:
  222. Given a ptr to a driver-registered GUID, give us a string with the device name
  223. that can be used in a CreateFile() call.
  224. Actually briefly opens and closes the device and sets outBuf if successfull;
  225. returns FALSE if not
  226. Arguments:
  227. pGuid: ptr to GUID registered by the driver itself
  228. outNameBuf: the generated zero-terminated name for this device
  229. Return Value:
  230. TRUE on success else FALSE
  231. --*/
  232. {
  233. HANDLE hDev = OpenUsbDevice( pGuid, outNameBuf );
  234. if ( hDev != INVALID_HANDLE_VALUE )
  235. {
  236. CloseHandle( hDev );
  237. return TRUE;
  238. }
  239. return FALSE;
  240. }
  241. HANDLE
  242. open_dev()
  243. /*++
  244. Routine Description:
  245. Called by dumpUsbConfig() to open an instance of our device
  246. Arguments:
  247. None
  248. Return Value:
  249. Device handle on success else NULL
  250. --*/
  251. {
  252. HANDLE hDEV = OpenUsbDevice( (LPGUID)&GUID_CLASS_I82930_ISO, completeDeviceName);
  253. if (hDEV == INVALID_HANDLE_VALUE) {
  254. printf("Failed to open (%s) = %d", completeDeviceName, GetLastError());
  255. } else {
  256. printf("DeviceName = (%s)\n", completeDeviceName);
  257. }
  258. return hDEV;
  259. }
  260. HANDLE
  261. open_file( char *filename)
  262. /*++
  263. Routine Description:
  264. Called by main() to open an instance of our device after obtaining its name
  265. Arguments:
  266. None
  267. Return Value:
  268. Device handle on success else NULL
  269. --*/
  270. {
  271. int success = 1;
  272. HANDLE h;
  273. if ( !GetUsbDeviceFileName(
  274. (LPGUID) &GUID_CLASS_I82930_ISO,
  275. completeDeviceName) )
  276. {
  277. NOISY(("Failed to GetUsbDeviceFileName - err = %d\n", GetLastError()));
  278. return INVALID_HANDLE_VALUE;
  279. }
  280. strcat (completeDeviceName,
  281. "\\"
  282. );
  283. if((strlen(completeDeviceName) + strlen(filename)) > 255) {
  284. NOISY(("Failed to open handle - possibly long filename\n"));
  285. return INVALID_HANDLE_VALUE;
  286. }
  287. strcat (completeDeviceName,
  288. filename
  289. );
  290. printf("completeDeviceName = (%s)\n", completeDeviceName);
  291. h = CreateFile(completeDeviceName,
  292. GENERIC_WRITE | GENERIC_READ,
  293. FILE_SHARE_WRITE | FILE_SHARE_READ,
  294. NULL,
  295. OPEN_EXISTING,
  296. 0,
  297. NULL);
  298. if (h == INVALID_HANDLE_VALUE) {
  299. NOISY(("Failed to open (%s) = %d", completeDeviceName, GetLastError()));
  300. success = 0;
  301. } else {
  302. NOISY(("Opened successfully.\n"));
  303. }
  304. return h;
  305. }
  306. void
  307. usage()
  308. /*++
  309. Routine Description:
  310. Called by main() to dump usage info to the console when
  311. the app is called with no parms or with an invalid parm
  312. Arguments:
  313. None
  314. Return Value:
  315. None
  316. --*/
  317. {
  318. printf("Usage for Read/Write test:\n");
  319. printf("-r [n] where n is number of bytes to read\n");
  320. printf("-w [n] where n is number of bytes to write\n");
  321. printf("-c [n] where n is number of iterations (default = 1)\n");
  322. printf("-i [s] where s is the input pipe\n");
  323. printf("-o [s] where s is the output pipe\n");
  324. printf("-v verbose -- dumps read data\n");
  325. printf("\nUsage for USB and Endpoint info:\n");
  326. printf("-u to dump USB configuration and pipe info \n");
  327. printf("-g [s] Run Isochronous test stream for 's' seconds \n");
  328. }
  329. void
  330. parse(
  331. int argc,
  332. char *argv[] )
  333. /*++
  334. Routine Description:
  335. Called by main() to parse command line parms
  336. Arguments:
  337. argc and argv that was passed to main()
  338. Return Value:
  339. Sets global flags as per user function request
  340. --*/
  341. {
  342. int i;
  343. if ( argc < 2 ) // give usage if invoked with no parms
  344. usage();
  345. for (i=0; i<argc; i++) {
  346. if (argv[i][0] == '-' ||
  347. argv[i][0] == '/') {
  348. switch(argv[i][1]) {
  349. case 'r':
  350. case 'R':
  351. ReadLen = atoi(&argv[i+1][0]);
  352. fRead = TRUE;
  353. i++;
  354. break;
  355. case 'w':
  356. case 'W':
  357. WriteLen = atoi(&argv[i+1][0]);
  358. fWrite = TRUE;
  359. i++;
  360. break;
  361. case 'c':
  362. case 'C':
  363. IterationCount = atoi(&argv[i+1][0]);
  364. i++;
  365. break;
  366. case 'i':
  367. case 'I':
  368. strcpy(inPipe, &argv[i+1][0]);
  369. i++;
  370. break;
  371. case 'u':
  372. case 'U':
  373. fDumpUsbConfig = TRUE;
  374. i++;
  375. break;
  376. case 'v':
  377. case 'V':
  378. fDumpReadData = TRUE;
  379. i++;
  380. break;
  381. case 'o':
  382. case 'O':
  383. strcpy(outPipe, &argv[i+1][0]);
  384. i++;
  385. break;
  386. case 'g':
  387. case 'G':
  388. gMS = 1000 * atoi(&argv[i+1][0]);
  389. StartIsoStream();
  390. break;
  391. case 'x':
  392. case 'X':
  393. StopIsoStream();
  394. break;
  395. default:
  396. usage();
  397. }
  398. }
  399. }
  400. }
  401. BOOL
  402. compare_buffs(char *buff1, char *buff2, int length)
  403. /*++
  404. Routine Description:
  405. Called to verify read and write buffers match for loopback test
  406. Arguments:
  407. buffers to compare and length
  408. Return Value:
  409. TRUE if buffers match, else FALSE
  410. --*/
  411. {
  412. int ok = 1;
  413. if (memcmp(buff1, buff2, length )) {
  414. // Edi, and Esi point to the mismatching char and ecx indicates the
  415. // remaining length.
  416. ok = 0;
  417. }
  418. return ok;
  419. }
  420. #define NPERLN 8
  421. void
  422. dump(
  423. UCHAR *b,
  424. int len
  425. )
  426. /*++
  427. Routine Description:
  428. Called to do formatted ascii dump to console of the io buffer
  429. Arguments:
  430. buffer and length
  431. Return Value:
  432. none
  433. --*/
  434. {
  435. ULONG i;
  436. ULONG longLen = (ULONG)len / sizeof( ULONG );
  437. PULONG pBuf = (PULONG) b;
  438. // dump an ordinal ULONG for each sizeof(ULONG)'th byte
  439. printf("\n****** BEGIN DUMP LEN decimal %d, 0x%x\n", len,len);
  440. for (i=0; i<longLen; i++) {
  441. printf("%04X ", *pBuf++);
  442. if (i % NPERLN == (NPERLN - 1)) {
  443. printf("\n");
  444. }
  445. }
  446. if (i % NPERLN != 0) {
  447. printf("\n");
  448. }
  449. printf("\n****** END DUMP LEN decimal %d, 0x%x\n", len,len);
  450. }
  451. // Begin, routines for USB configuration dump (Cmdline "rwiso -u" )
  452. char
  453. *usbDescriptorTypeString(UCHAR bDescriptorType )
  454. /*++
  455. Routine Description:
  456. Called to get ascii string of USB descriptor
  457. Arguments:
  458. PUSB_ENDPOINT_DESCRIPTOR->bDescriptorType or
  459. PUSB_DEVICE_DESCRIPTOR->bDescriptorType or
  460. PUSB_INTERFACE_DESCRIPTOR->bDescriptorType or
  461. PUSB_STRING_DESCRIPTOR->bDescriptorType or
  462. PUSB_POWER_DESCRIPTOR->bDescriptorType or
  463. PUSB_CONFIGURATION_DESCRIPTOR->bDescriptorType
  464. Return Value:
  465. ptr to string
  466. --*/{
  467. switch(bDescriptorType) {
  468. case USB_DEVICE_DESCRIPTOR_TYPE:
  469. return "USB_DEVICE_DESCRIPTOR_TYPE";
  470. case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  471. return "USB_CONFIGURATION_DESCRIPTOR_TYPE";
  472. case USB_STRING_DESCRIPTOR_TYPE:
  473. return "USB_STRING_DESCRIPTOR_TYPE";
  474. case USB_INTERFACE_DESCRIPTOR_TYPE:
  475. return "USB_INTERFACE_DESCRIPTOR_TYPE";
  476. case USB_ENDPOINT_DESCRIPTOR_TYPE:
  477. return "USB_ENDPOINT_DESCRIPTOR_TYPE";
  478. #ifdef USB_POWER_DESCRIPTOR_TYPE // this is the older definintion which is actually obsolete
  479. // workaround for temporary bug in 98ddk, older USB100.h file
  480. case USB_POWER_DESCRIPTOR_TYPE:
  481. return "USB_POWER_DESCRIPTOR_TYPE";
  482. #endif
  483. #ifdef USB_RESERVED_DESCRIPTOR_TYPE // this is the current version of USB100.h as in NT5DDK
  484. case USB_RESERVED_DESCRIPTOR_TYPE:
  485. return "USB_RESERVED_DESCRIPTOR_TYPE";
  486. case USB_CONFIG_POWER_DESCRIPTOR_TYPE:
  487. return "USB_CONFIG_POWER_DESCRIPTOR_TYPE";
  488. case USB_INTERFACE_POWER_DESCRIPTOR_TYPE:
  489. return "USB_INTERFACE_POWER_DESCRIPTOR_TYPE";
  490. #endif // for current nt5ddk version of USB100.h
  491. default:
  492. return "??? UNKNOWN!!";
  493. }
  494. }
  495. char
  496. *usbEndPointTypeString(UCHAR bmAttributes)
  497. /*++
  498. Routine Description:
  499. Called to get ascii string of endpt descriptor type
  500. Arguments:
  501. PUSB_ENDPOINT_DESCRIPTOR->bmAttributes
  502. Return Value:
  503. ptr to string
  504. --*/
  505. {
  506. UINT typ = bmAttributes & USB_ENDPOINT_TYPE_MASK;
  507. switch( typ) {
  508. case USB_ENDPOINT_TYPE_INTERRUPT:
  509. return "USB_ENDPOINT_TYPE_INTERRUPT";
  510. case USB_ENDPOINT_TYPE_BULK:
  511. return "USB_ENDPOINT_TYPE_BULK";
  512. case USB_ENDPOINT_TYPE_ISOCHRONOUS:
  513. return "USB_ENDPOINT_TYPE_ISOCHRONOUS";
  514. case USB_ENDPOINT_TYPE_CONTROL:
  515. return "USB_ENDPOINT_TYPE_CONTROL";
  516. default:
  517. return "??? UNKNOWN!!";
  518. }
  519. }
  520. char
  521. *usbConfigAttributesString(UCHAR bmAttributes)
  522. /*++
  523. Routine Description:
  524. Called to get ascii string of USB_CONFIGURATION_DESCRIPTOR attributes
  525. Arguments:
  526. PUSB_CONFIGURATION_DESCRIPTOR->bmAttributes
  527. Return Value:
  528. ptr to string
  529. --*/
  530. {
  531. UINT typ = bmAttributes & USB_CONFIG_POWERED_MASK;
  532. switch( typ) {
  533. case USB_CONFIG_BUS_POWERED:
  534. return "USB_CONFIG_BUS_POWERED";
  535. case USB_CONFIG_SELF_POWERED:
  536. return "USB_CONFIG_SELF_POWERED";
  537. case USB_CONFIG_REMOTE_WAKEUP:
  538. return "USB_CONFIG_REMOTE_WAKEUP";
  539. default:
  540. return "??? UNKNOWN!!";
  541. }
  542. }
  543. void
  544. print_USB_CONFIGURATION_DESCRIPTOR(PUSB_CONFIGURATION_DESCRIPTOR cd)
  545. /*++
  546. Routine Description:
  547. Called to do formatted ascii dump to console of a USB config descriptor
  548. Arguments:
  549. ptr to USB configuration descriptor
  550. Return Value:
  551. none
  552. --*/
  553. {
  554. printf("\n===================\nUSB_CONFIGURATION_DESCRIPTOR\n");
  555. printf(
  556. "bLength = 0x%x, decimal %d\n", cd->bLength, cd->bLength
  557. );
  558. printf(
  559. "bDescriptorType = 0x%x ( %s )\n", cd->bDescriptorType, usbDescriptorTypeString( cd->bDescriptorType )
  560. );
  561. printf(
  562. "wTotalLength = 0x%x, decimal %d\n", cd->wTotalLength, cd->wTotalLength
  563. );
  564. printf(
  565. "bNumInterfaces = 0x%x, decimal %d\n", cd->bNumInterfaces, cd->bNumInterfaces
  566. );
  567. printf(
  568. "bConfigurationValue = 0x%x, decimal %d\n", cd->bConfigurationValue, cd->bConfigurationValue
  569. );
  570. printf(
  571. "iConfiguration = 0x%x, decimal %d\n", cd->iConfiguration, cd->iConfiguration
  572. );
  573. printf(
  574. "bmAttributes = 0x%x ( %s )\n", cd->bmAttributes, usbConfigAttributesString( cd->bmAttributes )
  575. );
  576. printf(
  577. "MaxPower = 0x%x, decimal %d\n", cd->MaxPower, cd->MaxPower
  578. );
  579. }
  580. void
  581. print_USB_INTERFACE_DESCRIPTOR(PUSB_INTERFACE_DESCRIPTOR id, UINT ix)
  582. /*++
  583. Routine Description:
  584. Called to do formatted ascii dump to console of a USB interface descriptor
  585. Arguments:
  586. ptr to USB interface descriptor
  587. Return Value:
  588. none
  589. --*/
  590. {
  591. printf("\n-----------------------------\nUSB_INTERFACE_DESCRIPTOR #%d\n", ix);
  592. printf(
  593. "bLength = 0x%x\n", id->bLength
  594. );
  595. printf(
  596. "bDescriptorType = 0x%x ( %s )\n", id->bDescriptorType, usbDescriptorTypeString( id->bDescriptorType )
  597. );
  598. printf(
  599. "bInterfaceNumber = 0x%x\n", id->bInterfaceNumber
  600. );
  601. printf(
  602. "bAlternateSetting = 0x%x\n", id->bAlternateSetting
  603. );
  604. printf(
  605. "bNumEndpoints = 0x%x\n", id->bNumEndpoints
  606. );
  607. printf(
  608. "bInterfaceClass = 0x%x\n", id->bInterfaceClass
  609. );
  610. printf(
  611. "bInterfaceSubClass = 0x%x\n", id->bInterfaceSubClass
  612. );
  613. printf(
  614. "bInterfaceProtocol = 0x%x\n", id->bInterfaceProtocol
  615. );
  616. printf(
  617. "bInterface = 0x%x\n", id->iInterface
  618. );
  619. }
  620. void
  621. print_USB_ENDPOINT_DESCRIPTOR(PUSB_ENDPOINT_DESCRIPTOR ed, int i)
  622. /*++
  623. Routine Description:
  624. Called to do formatted ascii dump to console of a USB endpoint descriptor
  625. Arguments:
  626. ptr to USB endpoint descriptor,
  627. index of this endpt in interface desc
  628. Return Value:
  629. none
  630. --*/
  631. {
  632. printf(
  633. "------------------------------\nUSB_ENDPOINT_DESCRIPTOR for Pipe%02d\n", i
  634. );
  635. printf(
  636. "bLength = 0x%x\n", ed->bLength
  637. );
  638. printf(
  639. "bDescriptorType = 0x%x ( %s )\n", ed->bDescriptorType, usbDescriptorTypeString( ed->bDescriptorType )
  640. );
  641. if ( USB_ENDPOINT_DIRECTION_IN( ed->bEndpointAddress ) ) {
  642. printf(
  643. "bEndpointAddress= 0x%x ( INPUT )\n", ed->bEndpointAddress
  644. );
  645. } else {
  646. printf(
  647. "bEndpointAddress= 0x%x ( OUTPUT )\n", ed->bEndpointAddress
  648. );
  649. }
  650. printf(
  651. "bmAttributes= 0x%x ( %s )\n", ed->bmAttributes, usbEndPointTypeString ( ed->bmAttributes )
  652. );
  653. printf(
  654. "wMaxPacketSize= 0x%x, decimal %d\n", ed->wMaxPacketSize, ed->wMaxPacketSize
  655. );
  656. printf(
  657. "bInterval = 0x%x, decimal %d\n", ed->bInterval, ed->bInterval
  658. );
  659. }
  660. void
  661. rw_dev( HANDLE hDEV )
  662. /*++
  663. Routine Description:
  664. Called to do formatted ascii dump to console of USB
  665. configuration, interface, and endpoint descriptors
  666. (Cmdline "rwiso -u" )
  667. Arguments:
  668. handle to device
  669. Return Value:
  670. none
  671. --*/
  672. {
  673. ULONG success;
  674. int siz, nBytes;
  675. char buf[256];
  676. PUSB_CONFIGURATION_DESCRIPTOR cd;
  677. PUSB_INTERFACE_DESCRIPTOR id;
  678. PUSB_ENDPOINT_DESCRIPTOR ed;
  679. siz = sizeof(buf);
  680. if (hDEV == INVALID_HANDLE_VALUE) {
  681. NOISY(("DEV not open"));
  682. return;
  683. }
  684. success = DeviceIoControl(hDEV,
  685. IOCTL_ISOUSB_GET_CONFIG_DESCRIPTOR,
  686. buf,
  687. siz,
  688. buf,
  689. siz,
  690. &nBytes,
  691. NULL);
  692. NOISY(("request complete, success = %d nBytes = %d\n", success, nBytes));
  693. if (success) {
  694. ULONG i;
  695. UINT j, n;
  696. char *pch;
  697. pch = buf;
  698. n = 0;
  699. cd = (PUSB_CONFIGURATION_DESCRIPTOR) pch;
  700. print_USB_CONFIGURATION_DESCRIPTOR( cd );
  701. pch += cd->bLength;
  702. do {
  703. id = (PUSB_INTERFACE_DESCRIPTOR) pch;
  704. print_USB_INTERFACE_DESCRIPTOR(id, n++);
  705. pch += id->bLength;
  706. for (j=0; j<id->bNumEndpoints; j++) {
  707. ed = (PUSB_ENDPOINT_DESCRIPTOR) pch;
  708. print_USB_ENDPOINT_DESCRIPTOR(ed,j);
  709. pch += ed->bLength;
  710. }
  711. i = (ULONG)(pch - buf);
  712. } while (i<cd->wTotalLength);
  713. }
  714. return;
  715. }
  716. int dumpUsbConfig()
  717. /*++
  718. Routine Description:
  719. Called to do formatted ascii dump to console of USB
  720. configuration, interface, and endpoint descriptors
  721. (Cmdline "rwiso -u" )
  722. Arguments:
  723. none
  724. Return Value:
  725. none
  726. --*/
  727. {
  728. HANDLE hDEV = open_dev();
  729. if ( hDEV )
  730. {
  731. rw_dev( hDEV );
  732. CloseHandle(hDEV);
  733. }
  734. return 0;
  735. }
  736. // End, routines for USB configuration and pipe info dump (Cmdline "rwiso -u" )
  737. // Begin, routines for Iso Streaming
  738. void
  739. IsoStream( HANDLE hDEV, BOOL fStop )
  740. /*++
  741. Routine Description:
  742. Called to start or stop an iso stream
  743. (Cmdline "RwIso -g" )
  744. Arguments:
  745. handle to device
  746. Return Value:
  747. none
  748. --*/
  749. {
  750. ULONG success;
  751. int nBytes;
  752. DWORD ioctl;
  753. char i;
  754. if ( fStop )
  755. {
  756. ioctl = IOCTL_ISOUSB_STOP_ISO_STREAM;
  757. for ( i = 0; i < sizeof( gbuf ); i ++ )
  758. gbuf[ i ] = 0; // init outbuf to 0's to make sure read was good
  759. success = DeviceIoControl(hDEV,
  760. ioctl,
  761. &gpStreamObj, //pointer to stream object initted when stream was started
  762. sizeof( PVOID),
  763. gbuf, // output buffer gets back from kernel mode
  764. sizeof(gbuf),
  765. &nBytes,
  766. NULL);
  767. NOISY(("DeviceIoControl STOP_ISO_STREAM complete, success = %d\n", success));
  768. }
  769. else
  770. {
  771. ioctl = IOCTL_ISOUSB_START_ISO_STREAM;
  772. //input is our 256-byte buffer, binary char 0-255
  773. for ( i = 0; i < sizeof( gbuf ); i ++ )
  774. gbuf[ i ] = i;
  775. success = DeviceIoControl(hDEV,
  776. ioctl,
  777. gbuf,
  778. sizeof(gbuf),
  779. &gpStreamObj, // will receive pointer to stream object
  780. sizeof( PVOID),
  781. &nBytes,
  782. NULL);
  783. NOISY(("DeviceIoControl START_ISO_STREAM complete, success = %d\n", success));
  784. }
  785. if (hDEV == INVALID_HANDLE_VALUE) {
  786. NOISY(("DEV not open"));
  787. return;
  788. }
  789. }
  790. void StartIsoStream( void )
  791. {
  792. if ( !ghStreamDev ) {
  793. ghStreamDev = open_dev();
  794. if ( ghStreamDev != INVALID_HANDLE_VALUE ) {
  795. IsoStream( ghStreamDev , FALSE );
  796. Sleep( gMS );
  797. StopIsoStream();
  798. }
  799. }
  800. }
  801. void StopIsoStream( void )
  802. {
  803. if ( ghStreamDev ) {
  804. IsoStream( ghStreamDev , TRUE );
  805. ghStreamDev = NULL;
  806. }
  807. }
  808. // End, routines for Iso Streaming
  809. int _cdecl main(
  810. int argc,
  811. char *argv[])
  812. /*++
  813. Routine Description:
  814. Entry point to RwIso.exe
  815. Parses cmdline, performs user-requested tests
  816. Arguments:
  817. argc, argv standard console 'c' app arguments
  818. Return Value:
  819. Zero
  820. --*/
  821. {
  822. char *pinBuf = NULL, *poutBuf = NULL;
  823. ULONG nBytesRead, nBytesWrite, nBytes;
  824. ULONG i, j;
  825. int ok;
  826. ULONG success;
  827. HANDLE hRead = INVALID_HANDLE_VALUE, hWrite = INVALID_HANDLE_VALUE;
  828. char buf[1024];
  829. clock_t start, finish;
  830. ULONG totalBytes = 0L;
  831. double seconds;
  832. ULONG fail = 0L;
  833. parse(argc, argv );
  834. // dump USB configuation and pipe info
  835. if( fDumpUsbConfig ) {
  836. dumpUsbConfig();
  837. }
  838. // doing a read, write, or both test
  839. if ((fRead) || (fWrite)) {
  840. if (fRead) {
  841. //
  842. // open the output file
  843. //
  844. if ( fDumpReadData ) { // round size to sizeof ULONG for readable dumping
  845. while( ReadLen % sizeof( ULONG ) )
  846. ReadLen++;
  847. }
  848. hRead = open_file( inPipe);
  849. pinBuf = malloc(ReadLen);
  850. }
  851. if (fWrite) {
  852. if ( fDumpReadData ) { // round size to sizeof ULONG for readable dumping
  853. while( WriteLen % sizeof( ULONG ) )
  854. WriteLen++;
  855. }
  856. hWrite = open_file( outPipe);
  857. poutBuf = malloc(WriteLen);
  858. }
  859. for (i=0; i<IterationCount; i++) {
  860. if (fWrite && poutBuf && hWrite != INVALID_HANDLE_VALUE) {
  861. PULONG pOut = (PULONG) poutBuf;
  862. ULONG numLongs = WriteLen / sizeof( ULONG );
  863. //
  864. // put some data in the output buffer
  865. //
  866. for (j=0; j<numLongs; j++) {
  867. *(pOut+j) = j;
  868. }
  869. //
  870. // send the write
  871. //
  872. WriteFile(hWrite,
  873. poutBuf,
  874. WriteLen,
  875. &nBytesWrite,
  876. NULL);
  877. printf("<%s> W (%04.4d) : request %06.6d bytes -- %06.6d bytes written\n",
  878. outPipe, i, WriteLen, nBytesWrite);
  879. assert(nBytesWrite == WriteLen);
  880. }
  881. if (fRead && pinBuf) {
  882. success = ReadFile(hRead,
  883. pinBuf,
  884. ReadLen,
  885. &nBytesRead,
  886. NULL);
  887. printf("<%s> R (%04.4d) : request %06.6d bytes -- %06.6d bytes read\n",
  888. inPipe, i, ReadLen, nBytesRead);
  889. if (fWrite) {
  890. //
  891. // validate the input buffer against what
  892. // we sent to the 82930 (loopback test)
  893. //
  894. ok = compare_buffs(pinBuf, poutBuf, nBytesRead);
  895. if( fDumpReadData ) {
  896. printf("Dumping read buffer\n");
  897. dump( pinBuf, nBytesRead );
  898. printf("Dumping write buffer\n");
  899. dump( poutBuf, nBytesRead );
  900. }
  901. assert(ok);
  902. if(ok != 1)
  903. fail++;
  904. assert(ReadLen == WriteLen);
  905. assert(nBytesRead == ReadLen);
  906. assert(nBytesWrite == WriteLen);
  907. }
  908. }
  909. }
  910. if (pinBuf) {
  911. free(pinBuf);
  912. }
  913. if (poutBuf) {
  914. free(poutBuf);
  915. }
  916. // close devices if needed
  917. if(hRead != INVALID_HANDLE_VALUE)
  918. CloseHandle(hRead);
  919. if(hWrite != INVALID_HANDLE_VALUE)
  920. CloseHandle(hWrite);
  921. }
  922. StopIsoStream(); // stop iso stream if we started one
  923. return 0;
  924. }