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.

1169 lines
29 KiB

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