WinUsb_Initialize return error 1

I am trying to WinUsb_Initialize function. But I keep getting Error 1 when I use GetLastError() function to catch the error. What is causing the error 1?

I did use the FILE_FLAG_OVERLAPPED as required by the windows document.

But still failing. Can someone please help me?

Thanks,

Trey

Are you sure winusb is running on the device handle you opened?

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, July 6, 2015 8:57 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] WinUsb_Initialize return error 1

I am trying to WinUsb_Initialize function. But I keep getting Error 1 when I use GetLastError() function to catch the error. What is causing the error 1?

I did use the FILE_FLAG_OVERLAPPED as required by the windows document.

But still failing. Can someone please help me?

Thanks,

Trey


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

I just realize that to be able to use winusb functions, I will have to use winusb.sys. for the function driver. But I was using the kmdf_fx2 driver sample by Microsoft.

So now I have two routes to go:

  1. use the winusb driver and following the steps in this link: https://msdn.microsoft.com/en-us/library/windows/hardware/ff540174(v=vs.85).aspx

  2. use WdfUsbTargetPipeWriteSynchronously to write to certain endpoint.

Which way do you think is easier? Or is it even possible to write to a certain endpoint without using winusb??

You can write to a certain endpoint without winusb very easily, your driver needs to expose that functionality. It is not hard. If your driver is paired with just your app, I would strongly suggest you use winusb and not write your own driver.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, July 6, 2015 9:51 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WinUsb_Initialize return error 1

I just realize that to be able to use winusb functions, I will have to use winusb.sys. for the function driver. But I was using the kmdf_fx2 driver sample by Microsoft.

So now I have two routes to go:

1. use the winusb driver and following the steps in this link: https://msdn.microsoft.com/en-us/library/windows/hardware/ff540174(v=vs.85).aspx

2. use WdfUsbTargetPipeWriteSynchronously to write to certain endpoint.

Which way do you think is easier? Or is it even possible to write to a certain endpoint without using winusb??


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

xxxxx@gmail.com wrote:

I just realize that to be able to use winusb functions, I will have to use winusb.sys. for the function driver. But I was using the kmdf_fx2 driver sample by Microsoft.

So now I have two routes to go:

  1. use the winusb driver and following the steps in this link: https://msdn.microsoft.com/en-us/library/windows/hardware/ff540174(v=vs.85).aspx

  2. use WdfUsbTargetPipeWriteSynchronously to write to certain endpoint.

Which way do you think is easier? Or is it even possible to write to a certain endpoint without using winusb??

In my own humble opinion, if your device does not fall into one of the
standard classes, there is no reason to write a kernel driver for it.
WinUSB is a far better solution. It is simple, robust, and
well-understood. By using the Microsoft extended string descriptors,
you don’t even need an INF for it.

There are a few exceptions. If you need to have a single device shared
between multiple applications, then a driver may be necessary. You can
do that sharing with a client/server mechanism using a service, but
that’s essentially what a UMDF driver is anyway.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I tried to use WinUSB driver and WinUSB library but the program keeps failing at SetupDiEnumDeviceInterfaces(…)

So if I need to take the second route of not using winUSB, then how do I write data to certain endpoint?

Don’t give up that easily.
a) did you verify winusb.sys is installed on your device?
b) has the device successfully started or is it !'ed out in device manager?
c) which device interface guid did you use? It has to be the one you specify in the INF

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, July 6, 2015 2:25 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WinUsb_Initialize return error 1

I tried to use WinUSB driver and WinUSB library but the program keeps failing at SetupDiEnumDeviceInterfaces(…)

So if I need to take the second route of not using winUSB, then how do I write data to certain endpoint?


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

xxxxx@gmail.com wrote:

I tried to use WinUSB driver and WinUSB library but the program keeps failing at SetupDiEnumDeviceInterfaces(…)

I am torn between my innate need to answer your question and my
immediate desire to whack you for asking this kind of question.

WinUSB works, and works well. If you couldn’t get it to work, then YOU
HAVE DONE SOMETHING WRONG. The failure you describe above, however, has
nothing to do with WinUSB. If you couldn’t find your device interface,
then you probably made a mistake in the device interface. Every WinUSB
device advertises its own device interface GUID. That’s part of the INF
file. In order to find that device, you use
SetupDiEnumDeviceInterfaces. You have to specify the correct GUID, and
you have to give the correct options to the API. There are many
examples on the web showing this. We don’t know where you got yours,
and therefore we can’t possibly help you isolate the problem.

Show us your entire INF. Show us the code you have to find the device.
Tell us what error code you got from SetupDiEnumDeviceInterfaces. Show
us the lines where you define the GUID in your code. THAT’S how you go
about solving a problem.

So if I need to take the second route of not using winUSB, then how do I write data to certain endpoint?

If you can’t make the connection to WinUSB work, then I have some doubts
about your ability to modify a kernel driver to access an endpoint.
Let’s fix the code you have first.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

WinUSB.inf file:

;
;
; Installs WinUsb
;

[Version]
Signature = “$Windows NT$”
Class = USBDevice
ClassGUID = {36FC9E60-C465-11CF-8056-444553540000}
Provider = %ManufacturerName%
CatalogFile = winusbinstallation.cat
DriverVer=07/02/2015,15.26.7.730

; ========== Manufacturer/Models sections ===========

[Manufacturer]
%ManufacturerName% = Standard,NTamd64

[Standard.NTamd64]
%DeviceName% =USB_Install, USB\VID_18F7&PID_0030

; ========== Class definition ===========

[ClassInstall32]
AddReg = ClassInstall_AddReg

[ClassInstall_AddReg]
HKR,%ClassName%
HKR,NoInstallClass,1
HKR,IconPath,%REG_MULTI_SZ%,“%systemroot%\system32\setupapi.dll,-20”
HKR,LowerLogoVersion,5.2

; =================== Installation ===================

[USB_Install]
Include = winusb.inf
Needs = WINUSB.NT

[USB_Install.Services]
Include =winusb.inf
Needs = WINUSB.NT.Services

[USB_Install.HW]
AddReg=Dev_AddReg

[Dev_AddReg]
HKR,DeviceInterfaceGUIDs,0x10000,%osrusbfx2.GUID%

; [DestinationDirs]
; If your INF needs to copy files, you must not use the DefaultDestDir directive here.
; You must explicitly reference all file-list-section names in this section.

; =================== Strings ===================

[Strings]
ManufacturerName=“”
ClassName=“Universal Serial Bus devices”
DeviceName=“Fx2 Learning Kit Device”
REG_MULTI_SZ = 0x00010000
osrusbfx2.GUID=“{AE18AA60-7F6A-11d4-97DD-00010229B959}”

Testing code:

/*++

Copyright (c) Microsoft Corporation. All rights reserved.

THIS CODE AND INFORMATION IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.

Module Name:

TESTAPP.C

Abstract:

Console test app for osrusbfx2 driver.

Environment:

user mode only

–*/

#include <driverspecs.h>
Analysis_mode(Analysis_code_type_user_code)

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include “devioctl.h”
#include “strsafe.h”

#pragma warning(disable:4200) //
#pragma warning(disable:4201) // nameless struct/union
#pragma warning(disable:4214) // bit field types other than int

#include <setupapi.h>
#include <basetyps.h>
#include “usbdi.h”
#include “public.h”

#pragma warning(default:4200)
#pragma warning(default:4201)
#pragma warning(default:4214)

#define WHILE(a) <br>while(__pragma(warning(disable:4127)) a__pragma(warning(disable:4127)))

#define MAX_DEVPATH_LENGTH 256
#define NUM_ASYNCH_IO 100
#define BUFFER_SIZE 1024
#define READER_TYPE 1
#define WRITER_TYPE 2

BOOL G_fDumpUsbConfig = FALSE; // flags set in response to console command line switches
BOOL G_fDumpReadData = FALSE;
BOOL G_fRead = FALSE;
BOOL G_fWrite = FALSE;
BOOL G_fPlayWithDevice = FALSE;
BOOL G_fPerformAsyncIo = FALSE;
ULONG G_IterationCount = 1; //count of iterations of the test we are to perform
ULONG G_WriteLen = 512; // #bytes to write
ULONG G_ReadLen = 512; // #bytes to read

BOOL
DumpUsbConfig( // defined in dump.c
);

typedef enum _INPUT_FUNCTION {
LIGHT_ONE_BAR = 1,
CLEAR_ONE_BAR,
LIGHT_ALL_BARS,
CLEAR_ALL_BARS,
GET_BAR_GRAPH_LIGHT_STATE,
GET_SWITCH_STATE,
GET_SWITCH_STATE_AS_INTERRUPT_MESSAGE,
GET_7_SEGEMENT_STATE,
SET_7_SEGEMENT_STATE,
RESET_DEVICE,
REENUMERATE_DEVICE,
} INPUT_FUNCTION;

Success(return)
BOOL
GetDevicePath(
IN LPGUID InterfaceGuid,
Out_writes_z(BufLen) PCHAR DevicePath,
In size_t BufLen
)
{
HDEVINFO HardwareDeviceInfo;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
ULONG Length, RequiredLength = 0;
BOOL bResult;
HRESULT hr;

HardwareDeviceInfo = SetupDiGetClassDevs(
InterfaceGuid,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));

if (HardwareDeviceInfo == INVALID_HANDLE_VALUE) {
printf(“SetupDiGetClassDevs failed!\n”);
return FALSE;
}

DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
0,
InterfaceGuid,
0,
&DeviceInterfaceData);

if (bResult == FALSE) {

LPVOID lpMsgBuf;

if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &lpMsgBuf,
0,
NULL
)) {

printf(“SetupDiEnumDeviceInterfaces failed: %s”, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}

SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
return FALSE;
}

SetupDiGetDeviceInterfaceDetail(
HardwareDeviceInfo,
&DeviceInterfaceData,
NULL,
0,
&RequiredLength,
NULL
);

DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
LocalAlloc(LMEM_FIXED, RequiredLength);

if (DeviceInterfaceDetailData == NULL) {
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
printf(“Failed to allocate memory.\n”);
return FALSE;
}

DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

Length = RequiredLength;

bResult = SetupDiGetDeviceInterfaceDetail(
HardwareDeviceInfo,
&DeviceInterfaceData,
DeviceInterfaceDetailData,
Length,
&RequiredLength,
NULL);

if (bResult == FALSE) {

LPVOID lpMsgBuf;

if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &lpMsgBuf,
0,
NULL)) {

printf(“Error in SetupDiGetDeviceInterfaceDetail: %s\n”, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}

SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData);
return FALSE;
}

hr = StringCchCopy(DevicePath,
BufLen,
DeviceInterfaceDetailData->DevicePath);
if (FAILED(hr)) {
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData);
return FALSE;
}

SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData);

return TRUE;

}

HANDLE
OpenDevice(
In BOOL Synchronous
)

/++
Routine Description:

Called by main() to open an instance of our device after obtaining its name

Arguments:

Synchronous - TRUE, if Device is to be opened for synchronous access.
FALSE, otherwise.

Return Value:

Device handle on success else INVALID_HANDLE_VALUE

/

{
HANDLE hDev;
char completeDeviceName[MAX_DEVPATH_LENGTH];

if ( !GetDevicePath(
(LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
completeDeviceName,
sizeof(completeDeviceName)) )
{
return INVALID_HANDLE_VALUE;
}

printf(“DeviceName = (%s)\n”, completeDeviceName);

if(Synchronous) {
hDev = CreateFile(completeDeviceName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL, // default security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
} else {

hDev = CreateFile(completeDeviceName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL, // default security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
}

if (hDev == INVALID_HANDLE_VALUE) {
printf(“Failed to open the device, error - %d”, GetLastError());
} else {
printf(“Opened the device successfully.\n”);
}

return hDev;
}

VOID
Usage()

/++
Routine Description:

Called by main() to dump usage info to the console when
the app is called with no parms or with an invalid parm

Arguments:

None

Return Value:

None

/

{
printf(“Usage for osrusbfx2 testapp:\n”);
printf(“-r [n] where n is number of bytes to read\n”);
printf(“-w [n] where n is number of bytes to write\n”);
printf(“-c [n] where n is number of iterations (default = 1)\n”);
printf(“-v verbose – dumps read data\n”);
printf(“-p to control bar LEDs, seven segment, and dip switch\n”);
printf(“-a to perform asynchronous I/O\n”);
printf(“-u to dump USB configuration and pipe info \n”);

return;
}

void
Parse(
In int argc,
In_reads(argc) LPSTR argv
)

/
++
Routine Description:

Called by main() to parse command line parms

Arguments:

argc and argv that was passed to main()

Return Value:

Sets global flags as per user function request

/

{
int i;

if ( argc < 2 ) // give usage if invoked with no parms
Usage();

for (i=0; i if (argv[i][0] == ‘-’ ||
argv[i][0] == ‘/’) {
switch(argv[i][1]) {
case ‘r’:
case ‘R’:
if (i+1 >= argc) {
Usage();
exit(1);
}
else {
#pragma warning(suppress: 6385)
G_ReadLen = atoi(&argv[i+1][0]);
G_fRead = TRUE;
}
i++;
break;
case ‘w’:
case ‘W’:
if (i+1 >= argc) {
Usage();
exit(1);
}
else {
G_WriteLen = atoi(&argv[i+1][0]);
G_fWrite = TRUE;
}
i++;
break;
case ‘c’:
case ‘C’:
if (i+1 >= argc) {
Usage();
exit(1);
}
else {
G_IterationCount = atoi(&argv[i+1][0]);
}
i++;
break;
case ‘u’:
case ‘U’:
G_fDumpUsbConfig = TRUE;
break;
case ‘p’:
case ‘P’:
G_fPlayWithDevice = TRUE;
break;
case ‘a’:
case ‘A’:
G_fPerformAsyncIo = TRUE;
break;
case ‘v’:
case ‘V’:
G_fDumpReadData = TRUE;
break;
default:
Usage();
}
}
}
}

BOOL
Compare_Buffs(
In_reads_bytes(buff1length) char buff1,
In ULONG buff1length,
In_reads_bytes(buff2length) char buff2,
In ULONG buff2length
)
/
++
Routine Description:

Called to verify read and write buffers match for loopback test

Arguments:

buffers to compare and length

Return Value:

TRUE if buffers match, else FALSE

/
{
int ok = 1;

if (buff1length != buff2length || memcmp(buff1, buff2, buff1length )) {
// Edi, and Esi point to the mismatching char and ecx indicates the
// remaining length.
ok = 0;
}

return ok;
}

#define NPERLN 8

VOID
Dump(
UCHAR b,
int len
)

/
++
Routine Description:

Called to do formatted ascii dump to console of the io buffer

Arguments:

buffer and length

Return Value:

none

/

{
ULONG i;
ULONG longLen = (ULONG)len / sizeof( ULONG );
PULONG pBuf = (PULONG) b;

// dump an ordinal ULONG for each sizeof(ULONG)'th byte
printf(“\n*BEGIN DUMP LEN decimal %d, 0x%x\n", len,len);
for (i=0; i printf("%04X ", pBuf++);
if (i % NPERLN == (NPERLN - 1)) {
printf(“\n”);
}
}
if (i % NPERLN != 0) {
printf(“\n”);
}
printf("\n
END DUMP LEN decimal %d, 0x%x\n”, len,len);
}

BOOL
PlayWithDevice()
{
HANDLE deviceHandle;
DWORD code;
ULONG index;
INPUT_FUNCTION function;
BAR_GRAPH_STATE barGraphState;
ULONG bar;
SWITCH_STATE switchState;
UCHAR sevenSegment = 0;
UCHAR i;
BOOL result = FALSE;

deviceHandle = OpenDevice(FALSE);

if (deviceHandle == INVALID_HANDLE_VALUE) {

printf(“Unable to find any OSR FX2 devices!\n”);

return FALSE;

}

//
// Infinitely print out the list of choices, ask for input, process
// the request
//
WHILE(TRUE) {

printf (“\nUSBFX TEST – Functions:\n\n”);
printf (“\t1. Light Bar\n”);
printf (“\t2. Clear Bar\n”);
printf (“\t3. Light entire Bar graph\n”);
printf (“\t4. Clear entire Bar graph\n”);
printf (“\t5. Get bar graph state\n”);
printf (“\t6. Get Switch state\n”);
printf (“\t7. Get Switch Interrupt Message\n”);
printf (“\t8. Get 7 segment state\n”);
printf (“\t9. Set 7 segment state\n”);
printf (“\t10. Reset the device\n”);
printf (“\t11. Reenumerate the device\n”);
printf (“\n\t0. Exit\n”);
printf (“\n\tSelection: “);

if (scanf_s (”%d”, &function) <= 0) {

printf(“Error reading input!\n”);
goto Error;

}

switch(function) {

case LIGHT_ONE_BAR:

printf(“Which Bar (input number 1 thru 8)?\n”);
if (scanf_s (“%d”, &bar) <= 0) {

printf(“Error reading input!\n”);
goto Error;

}

if(bar == 0 || bar > 8){
printf(“Invalid bar number!\n”);
goto Error;
}

bar–; // normalize to 0 to 7

barGraphState.BarsAsUChar = 1 << (UCHAR)bar;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
&barGraphState, // Ptr to InBuffer
sizeof(BAR_GRAPH_STATE), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

break;

case CLEAR_ONE_BAR:

printf(“Which Bar (input number 1 thru 8)?\n”);
if (scanf_s (“%d”, &bar) <= 0) {

printf(“Error reading input!\n”);
goto Error;

}

if(bar == 0 || bar > 8){
printf(“Invalid bar number!\n”);
goto Error;
}

bar–;

//
// Read the current state
//
if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&barGraphState, // Ptr to OutBuffer
sizeof(BAR_GRAPH_STATE), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

if (barGraphState.BarsAsUChar & (1 << bar)) {

printf(“Bar is set…Clearing it\n”);
barGraphState.BarsAsUChar &= ~(1 << bar);

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
&barGraphState, // Ptr to InBuffer
sizeof(BAR_GRAPH_STATE), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;

}

} else {

printf(“Bar not set.\n”);

}

break;

case LIGHT_ALL_BARS:

barGraphState.BarsAsUChar = 0xFF;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
&barGraphState, // Ptr to InBuffer
sizeof(BAR_GRAPH_STATE), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

break;

case CLEAR_ALL_BARS:

barGraphState.BarsAsUChar = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
&barGraphState, // Ptr to InBuffer
sizeof(BAR_GRAPH_STATE), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

break;

case GET_BAR_GRAPH_LIGHT_STATE:

barGraphState.BarsAsUChar = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&barGraphState, // Ptr to OutBuffer
sizeof(BAR_GRAPH_STATE), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“Bar Graph: \n”);
printf(" Bar8 is %s\n", barGraphState.Bar8 ? “ON” : “OFF”);
printf(" Bar7 is %s\n", barGraphState.Bar7 ? “ON” : “OFF”);
printf(" Bar6 is %s\n", barGraphState.Bar6 ? “ON” : “OFF”);
printf(" Bar5 is %s\n", barGraphState.Bar5 ? “ON” : “OFF”);
printf(" Bar4 is %s\n", barGraphState.Bar4 ? “ON” : “OFF”);
printf(" Bar3 is %s\n", barGraphState.Bar3 ? “ON” : “OFF”);
printf(" Bar2 is %s\n", barGraphState.Bar2 ? “ON” : “OFF”);
printf(" Bar1 is %s\n", barGraphState.Bar1 ? “ON” : “OFF”);

break;

case GET_SWITCH_STATE:

switchState.SwitchesAsUChar = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_READ_SWITCHES,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&switchState, // Ptr to OutBuffer
sizeof(SWITCH_STATE), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“Switches: \n”);
printf(" Switch8 is %s\n", switchState.Switch8 ? “ON” : “OFF”);
printf(" Switch7 is %s\n", switchState.Switch7 ? “ON” : “OFF”);
printf(" Switch6 is %s\n", switchState.Switch6 ? “ON” : “OFF”);
printf(" Switch5 is %s\n", switchState.Switch5 ? “ON” : “OFF”);
printf(" Switch4 is %s\n", switchState.Switch4 ? “ON” : “OFF”);
printf(" Switch3 is %s\n", switchState.Switch3 ? “ON” : “OFF”);
printf(" Switch2 is %s\n", switchState.Switch2 ? “ON” : “OFF”);
printf(" Switch1 is %s\n", switchState.Switch1 ? “ON” : “OFF”);

break;

case GET_SWITCH_STATE_AS_INTERRUPT_MESSAGE:

switchState.SwitchesAsUChar = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&switchState, // Ptr to OutBuffer
sizeof(switchState), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“Switches: %d\n”,index);
printf(" Switch8 is %s\n", switchState.Switch8 ? “ON” : “OFF”);
printf(" Switch7 is %s\n", switchState.Switch7 ? “ON” : “OFF”);
printf(" Switch6 is %s\n", switchState.Switch6 ? “ON” : “OFF”);
printf(" Switch5 is %s\n", switchState.Switch5 ? “ON” : “OFF”);
printf(" Switch4 is %s\n", switchState.Switch4 ? “ON” : “OFF”);
printf(" Switch3 is %s\n", switchState.Switch3 ? “ON” : “OFF”);
printf(" Switch2 is %s\n", switchState.Switch2 ? “ON” : “OFF”);
printf(" Switch1 is %s\n", switchState.Switch1 ? “ON” : “OFF”);

break;

case GET_7_SEGEMENT_STATE:

sevenSegment = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&sevenSegment, // Ptr to OutBuffer
sizeof(UCHAR), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“7 Segment mask: 0x%x\n”, sevenSegment);
break;

case SET_7_SEGEMENT_STATE:

for (i = 0; i < 8; i++) {

sevenSegment = 1 << i;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY,
&sevenSegment, // Ptr to InBuffer
sizeof(UCHAR), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“This is %d\n”, i);
Sleep(500);

}

printf(“7 Segment mask: 0x%x\n”, sevenSegment);
break;

case RESET_DEVICE:

printf(“Reset the device\n”);

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_RESET_DEVICE,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
NULL)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

break;

case REENUMERATE_DEVICE:

printf(“Re-enumerate the device\n”);

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_REENUMERATE_DEVICE,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
NULL)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

//
// Close the handle to the device and exit out so that
// the driver can unload when the device is surprise-removed
// and reenumerated.
//
default:

result = TRUE;
goto Error;

}

} // end of while loop

Error:

CloseHandle(deviceHandle);
return result;

}

ULONG
AsyncIo(
PVOID ThreadParameter
)
{
HANDLE hDevice = INVALID_HANDLE_VALUE;
HANDLE hCompletionPort = NULL;
OVERLAPPED pOvList = NULL;
PUCHAR buf = NULL;
ULONG_PTR i;
ULONG ioType = (ULONG)(ULONG_PTR)ThreadParameter;
ULONG error;

hDevice = OpenDevice(FALSE);

if (hDevice == INVALID_HANDLE_VALUE) {
printf(“Cannot open device %d\n”, GetLastError());
goto Error;
}

hCompletionPort = CreateIoCompletionPort(hDevice, NULL, 1, 0);

if (hCompletionPort == NULL) {
printf(“Cannot open completion port %d \n”,GetLastError());
goto Error;
}

pOvList = (OVERLAPPED )malloc(NUM_ASYNCH_IO * sizeof(OVERLAPPED));

if (pOvList == NULL) {
printf(“Cannot allocate overlapped array \n”);
goto Error;
}

buf = (PUCHAR)malloc(NUM_ASYNCH_IO * BUFFER_SIZE);

if (buf == NULL) {
printf(“Cannot allocate buffer \n”);
goto Error;
}

ZeroMemory(pOvList, NUM_ASYNCH_IO * sizeof(OVERLAPPED));
ZeroMemory(buf, NUM_ASYNCH_IO * BUFFER_SIZE);

//
// Issue asynch I/O
//

for (i = 0; i < NUM_ASYNCH_IO; i++) {
if (ioType == READER_TYPE) {
if ( ReadFile( hDevice,
buf + (i
BUFFER_SIZE),
BUFFER_SIZE,
NULL,
&pOvList[i]) == 0) {

error = GetLastError();
if (error != ERROR_IO_PENDING) {
printf(" %Iu th read failed %d \n",i, GetLastError());
goto Error;
}
}

} else {
if ( WriteFile( hDevice,
buf + (i
BUFFER_SIZE),
BUFFER_SIZE,
NULL,
&pOvList[i]) == 0) {
error = GetLastError();
if (error != ERROR_IO_PENDING) {
printf(" %Iu th write failed %d \n",i, GetLastError());
goto Error;
}
}
}
}

//
// Wait for the I/Os to complete. If one completes then reissue the I/O
//

WHILE (1) {
OVERLAPPED completedOv;
ULONG_PTR key;
ULONG numberOfBytesTransferred;

if ( GetQueuedCompletionStatus(hCompletionPort, &numberOfBytesTransferred,
&key, &completedOv, INFINITE) == 0) {
printf(“GetQueuedCompletionStatus failed %d\n”, GetLastError());
goto Error;
}

//
// Read successfully completed. Issue another one.
//

if (ioType == READER_TYPE) {

i = completedOv - pOvList;

printf(“Number of bytes read by request number %Iu is %d\n”,
i, numberOfBytesTransferred);

if ( ReadFile( hDevice,
buf + (i * BUFFER_SIZE),
BUFFER_SIZE,
NULL,
completedOv) == 0) {
error = GetLastError();
if (error != ERROR_IO_PENDING) {
printf(“%Iu th Read failed %d \n”, i, GetLastError());
goto Error;
}
}
} else {

i = completedOv - pOvList;

printf(“Number of bytes written by request number %Iu is %d\n”,
i, numberOfBytesTransferred);

if ( WriteFile( hDevice,
buf + (i * BUFFER_SIZE),
BUFFER_SIZE,
NULL,
completedOv) == 0) {
error = GetLastError();
if (error != ERROR_IO_PENDING) {
printf(“%Iu th write failed %d \n”, i, GetLastError());
goto Error;
}
}
}
}

Error:
if (hDevice != INVALID_HANDLE_VALUE) {
CloseHandle(hDevice);
}

if (hCompletionPort) {
CloseHandle(hCompletionPort);
}

if (pOvList) {
free(pOvList);
}
if (buf) {
free(buf);
}

return 1;

}

int
_cdecl
main(
In int argc,
In_reads(argc) LPSTR argv
)
/
++
Routine Description:

Entry point to rwbulk.exe
Parses cmdline, performs user-requested tests

Arguments:

argc, argv standard console ‘c’ app arguments

Return Value:

Zero

/

{
char * pinBuf = NULL;
char * poutBuf = NULL;
ULONG nBytesRead;
ULONG nBytesWrite = 0;
int ok;
int retValue = 0;
UINT success;
HANDLE hRead = INVALID_HANDLE_VALUE;
HANDLE hWrite = INVALID_HANDLE_VALUE;
ULONG fail = 0L;
ULONG i;

Parse(argc, argv );

//
// dump USB configuation and pipe info
//
if (G_fDumpUsbConfig) {
DumpUsbConfig();
}

if (G_fPlayWithDevice) {
PlayWithDevice();
goto exit;
}

if (G_fPerformAsyncIo) {
HANDLE th1;

//
// Create a reader thread
//
th1 = CreateThread( NULL, // Default Security Attrib.
0, // Initial Stack Size,
AsyncIo, // Thread Func
(LPVOID)READER_TYPE,
0, // Creation Flags
NULL ); // Don’t need the Thread Id.

if (th1 == NULL) {
printf(“Couldn’t create reader thread - error %d\n”, GetLastError());
retValue = 1;
goto exit;
}

//
// Use this thread for peforming write.
//
AsyncIo((PVOID)WRITER_TYPE);

goto exit;
}

//
// doing a read, write, or both test
//
if ((G_fRead) || (G_fWrite)) {

if (G_fRead) {
if ( G_fDumpReadData ) { // round size to sizeof ULONG for readable dumping
while( G_ReadLen % sizeof( ULONG ) ) {
G_ReadLen++;
}
}

//
// open the output file
//
hRead = OpenDevice(TRUE);
if(hRead == INVALID_HANDLE_VALUE) {
retValue = 1;
goto exit;
}

pinBuf = malloc(G_ReadLen);
}

if (G_fWrite) {
if ( G_fDumpReadData ) { // round size to sizeof ULONG for readable dumping
while( G_WriteLen % sizeof( ULONG ) ) {
G_WriteLen++;
}
}

//
// open the output file
//
hWrite = OpenDevice(TRUE);
if(hWrite == INVALID_HANDLE_VALUE) {
retValue = 1;
goto exit;
}

poutBuf = malloc(G_WriteLen);
}

for (i = 0; i < G_IterationCount; i++) {
ULONG j;

if (G_fWrite && poutBuf && hWrite != INVALID_HANDLE_VALUE) {

PULONG pOut = (PULONG) poutBuf;
ULONG numLongs = G_WriteLen / sizeof( ULONG );

//
// put some data in the output buffer
//
for (j=0; j *(pOut+j) = j;
}

//
// send the write
//
success = WriteFile(hWrite, poutBuf, G_WriteLen, &nBytesWrite, NULL);
if(success == 0) {
printf(“WriteFile failed - error %d\n”, GetLastError());
retValue = 1;
goto exit;
}
printf(“Write (%04.4u) : request %06.6u bytes – %06.6u bytes written\n”,
i, G_WriteLen, nBytesWrite);

assert(nBytesWrite == G_WriteLen);
}

if (G_fRead && pinBuf) {

success = ReadFile(hRead, pinBuf, G_ReadLen, &nBytesRead, NULL);
if(success == 0) {
printf(“ReadFile failed - error %d\n”, GetLastError());
retValue = 1;
goto exit;
}

printf(“Read (%04.4u) : request %06.6u bytes – %06.6u bytes read\n”,
i, G_ReadLen, nBytesRead);

if (G_fWrite && poutBuf) {

//
// validate the input buffer against what
// we sent to the 82930 (loopback test)
//
ok = Compare_Buffs(pinBuf, nBytesRead, poutBuf, nBytesWrite);

if( G_fDumpReadData ) {
printf(“Dumping read buffer\n”);
Dump( (PUCHAR) pinBuf, nBytesRead );
printf(“Dumping write buffer\n”);
Dump( (PUCHAR) poutBuf, nBytesRead );
}
assert(ok);

if(ok != 1) {
fail++;
}

assert(G_ReadLen == G_WriteLen);
assert(nBytesRead == G_ReadLen);
}
}
}

}

exit:

if (pinBuf) {
free(pinBuf);
}

if (poutBuf) {
free(poutBuf);
}

// close devices if needed
if (hRead != INVALID_HANDLE_VALUE) {
CloseHandle(hRead);
}

if (hWrite != INVALID_HANDLE_VALUE) {
CloseHandle(hWrite);
}

return retValue;
}</basetyps.h></setupapi.h></assert.h></stdlib.h></stdio.h></windows.h></driverspecs.h>

Is GUID_DEVINTERFACE_OSRUSBFX2 initialized with {AE18AA60-7F6A-11d4-97DD-00010229B959}? The GUID you pass needs to match the GUID specified in this line of the INF

HKR,DeviceInterfaceGUIDs,0x10000,%osrusbfx2.GUID%

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Wednesday, July 8, 2015 7:18 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WinUsb_Initialize return error 1

Testing code:

/++

Copyright (c) Microsoft Corporation. All rights reserved.

THIS CODE AND INFORMATION IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.

Module Name:

TESTAPP.C

Abstract:

Console test app for osrusbfx2 driver.

Environment:

user mode only

/

#include <driverspecs.h>
Analysis_mode(Analysis_code_type_user_code)

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include “devioctl.h”
#include “strsafe.h”

#pragma warning(disable:4200) //
#pragma warning(disable:4201) // nameless struct/union #pragma warning(disable:4214) // bit field types other than int

#include <setupapi.h>
#include <basetyps.h>
#include “usbdi.h”
#include “public.h”

#pragma warning(default:4200)
#pragma warning(default:4201)
#pragma warning(default:4214)

#define WHILE(a) <br>while(__pragma(warning(disable:4127)) a__pragma(warning(disable:4127)))

#define MAX_DEVPATH_LENGTH 256
#define NUM_ASYNCH_IO 100
#define BUFFER_SIZE 1024
#define READER_TYPE 1
#define WRITER_TYPE 2

BOOL G_fDumpUsbConfig = FALSE; // flags set in response to console command line switches
BOOL G_fDumpReadData = FALSE;
BOOL G_fRead = FALSE;
BOOL G_fWrite = FALSE;
BOOL G_fPlayWithDevice = FALSE;
BOOL G_fPerformAsyncIo = FALSE;
ULONG G_IterationCount = 1; //count of iterations of the test we are to perform
ULONG G_WriteLen = 512; // #bytes to write
ULONG G_ReadLen = 512; // #bytes to read

BOOL
DumpUsbConfig( // defined in dump.c
);

typedef enum _INPUT_FUNCTION {
LIGHT_ONE_BAR = 1,
CLEAR_ONE_BAR,
LIGHT_ALL_BARS,
CLEAR_ALL_BARS,
GET_BAR_GRAPH_LIGHT_STATE,
GET_SWITCH_STATE,
GET_SWITCH_STATE_AS_INTERRUPT_MESSAGE,
GET_7_SEGEMENT_STATE,
SET_7_SEGEMENT_STATE,
RESET_DEVICE,
REENUMERATE_DEVICE,
} INPUT_FUNCTION;

Success(return)
BOOL
GetDevicePath(
IN LPGUID InterfaceGuid,
Out_writes_z(BufLen) PCHAR DevicePath,
In size_t BufLen
)
{
HDEVINFO HardwareDeviceInfo;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
ULONG Length, RequiredLength = 0;
BOOL bResult;
HRESULT hr;

HardwareDeviceInfo = SetupDiGetClassDevs(
InterfaceGuid,
NULL,
NULL,
(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));

if (HardwareDeviceInfo == INVALID_HANDLE_VALUE) {
printf(“SetupDiGetClassDevs failed!\n”);
return FALSE;
}

DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

bResult = SetupDiEnumDeviceInterfaces(HardwareDeviceInfo,
0,
InterfaceGuid,
0,
&DeviceInterfaceData);

if (bResult == FALSE) {

LPVOID lpMsgBuf;

if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &lpMsgBuf,
0,
NULL
)) {

printf(“SetupDiEnumDeviceInterfaces failed: %s”, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}

SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
return FALSE;
}

SetupDiGetDeviceInterfaceDetail(
HardwareDeviceInfo,
&DeviceInterfaceData,
NULL,
0,
&RequiredLength,
NULL
);

DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
LocalAlloc(LMEM_FIXED, RequiredLength);

if (DeviceInterfaceDetailData == NULL) {
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
printf(“Failed to allocate memory.\n”);
return FALSE;
}

DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

Length = RequiredLength;

bResult = SetupDiGetDeviceInterfaceDetail(
HardwareDeviceInfo,
&DeviceInterfaceData,
DeviceInterfaceDetailData,
Length,
&RequiredLength,
NULL);

if (bResult == FALSE) {

LPVOID lpMsgBuf;

if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &lpMsgBuf,
0,
NULL)) {

printf(“Error in SetupDiGetDeviceInterfaceDetail: %s\n”, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf);
}

SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData);
return FALSE;
}

hr = StringCchCopy(DevicePath,
BufLen,
DeviceInterfaceDetailData->DevicePath);
if (FAILED(hr)) {
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData);
return FALSE;
}

SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
LocalFree(DeviceInterfaceDetailData);

return TRUE;

}

HANDLE
OpenDevice(
In BOOL Synchronous
)

/++
Routine Description:

Called by main() to open an instance of our device after obtaining its name

Arguments:

Synchronous - TRUE, if Device is to be opened for synchronous access.
FALSE, otherwise.

Return Value:

Device handle on success else INVALID_HANDLE_VALUE

/

{
HANDLE hDev;
char completeDeviceName[MAX_DEVPATH_LENGTH];

if ( !GetDevicePath(
(LPGUID) &GUID_DEVINTERFACE_OSRUSBFX2,
completeDeviceName,
sizeof(completeDeviceName)) )
{
return INVALID_HANDLE_VALUE;
}

printf(“DeviceName = (%s)\n”, completeDeviceName);

if(Synchronous) {
hDev = CreateFile(completeDeviceName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL, // default security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
} else {

hDev = CreateFile(completeDeviceName,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL, // default security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
}

if (hDev == INVALID_HANDLE_VALUE) {
printf(“Failed to open the device, error - %d”, GetLastError());
} else {
printf(“Opened the device successfully.\n”);
}

return hDev;
}

VOID
Usage()

/++
Routine Description:

Called by main() to dump usage info to the console when
the app is called with no parms or with an invalid parm

Arguments:

None

Return Value:

None

/

{
printf(“Usage for osrusbfx2 testapp:\n”);
printf(“-r [n] where n is number of bytes to read\n”);
printf(“-w [n] where n is number of bytes to write\n”);
printf(“-c [n] where n is number of iterations (default = 1)\n”);
printf(“-v verbose – dumps read data\n”);
printf(“-p to control bar LEDs, seven segment, and dip switch\n”);
printf(“-a to perform asynchronous I/O\n”);
printf(“-u to dump USB configuration and pipe info \n”);

return;
}

void
Parse(
In int argc,
In_reads(argc) LPSTR argv
)

/
++
Routine Description:

Called by main() to parse command line parms

Arguments:

argc and argv that was passed to main()

Return Value:

Sets global flags as per user function request

/

{
int i;

if ( argc < 2 ) // give usage if invoked with no parms
Usage();

for (i=0; i if (argv[i][0] == ‘-’ ||
argv[i][0] == ‘/’) {
switch(argv[i][1]) {
case ‘r’:
case ‘R’:
if (i+1 >= argc) {
Usage();
exit(1);
}
else {
#pragma warning(suppress: 6385)
G_ReadLen = atoi(&argv[i+1][0]);
G_fRead = TRUE;
}
i++;
break;
case ‘w’:
case ‘W’:
if (i+1 >= argc) {
Usage();
exit(1);
}
else {
G_WriteLen = atoi(&argv[i+1][0]);
G_fWrite = TRUE;
}
i++;
break;
case ‘c’:
case ‘C’:
if (i+1 >= argc) {
Usage();
exit(1);
}
else {
G_IterationCount = atoi(&argv[i+1][0]);
}
i++;
break;
case ‘u’:
case ‘U’:
G_fDumpUsbConfig = TRUE;
break;
case ‘p’:
case ‘P’:
G_fPlayWithDevice = TRUE;
break;
case ‘a’:
case ‘A’:
G_fPerformAsyncIo = TRUE;
break;
case ‘v’:
case ‘V’:
G_fDumpReadData = TRUE;
break;
default:
Usage();
}
}
}
}

BOOL
Compare_Buffs(
In_reads_bytes(buff1length) char buff1,
In ULONG buff1length,
In_reads_bytes(buff2length) char buff2,
In ULONG buff2length
)
/
++
Routine Description:

Called to verify read and write buffers match for loopback test

Arguments:

buffers to compare and length

Return Value:

TRUE if buffers match, else FALSE

/
{
int ok = 1;

if (buff1length != buff2length || memcmp(buff1, buff2, buff1length )) {
// Edi, and Esi point to the mismatching char and ecx indicates the
// remaining length.
ok = 0;
}

return ok;
}

#define NPERLN 8

VOID
Dump(
UCHAR b,
int len
)

/
++
Routine Description:

Called to do formatted ascii dump to console of the io buffer

Arguments:

buffer and length

Return Value:

none

/

{
ULONG i;
ULONG longLen = (ULONG)len / sizeof( ULONG );
PULONG pBuf = (PULONG) b;

// dump an ordinal ULONG for each sizeof(ULONG)'th byte
printf(“\n*BEGIN DUMP LEN decimal %d, 0x%x\n", len,len);
for (i=0; i printf("%04X ", pBuf++);
if (i % NPERLN == (NPERLN - 1)) {
printf(“\n”);
}
}
if (i % NPERLN != 0) {
printf(“\n”);
}
printf("\n
END DUMP LEN decimal %d, 0x%x\n”, len,len); }

BOOL
PlayWithDevice()
{
HANDLE deviceHandle;
DWORD code;
ULONG index;
INPUT_FUNCTION function;
BAR_GRAPH_STATE barGraphState;
ULONG bar;
SWITCH_STATE switchState;
UCHAR sevenSegment = 0;
UCHAR i;
BOOL result = FALSE;

deviceHandle = OpenDevice(FALSE);

if (deviceHandle == INVALID_HANDLE_VALUE) {

printf(“Unable to find any OSR FX2 devices!\n”);

return FALSE;

}

//
// Infinitely print out the list of choices, ask for input, process
// the request
//
WHILE(TRUE) {

printf (“\nUSBFX TEST – Functions:\n\n”);
printf (“\t1. Light Bar\n”);
printf (“\t2. Clear Bar\n”);
printf (“\t3. Light entire Bar graph\n”);
printf (“\t4. Clear entire Bar graph\n”);
printf (“\t5. Get bar graph state\n”);
printf (“\t6. Get Switch state\n”);
printf (“\t7. Get Switch Interrupt Message\n”);
printf (“\t8. Get 7 segment state\n”);
printf (“\t9. Set 7 segment state\n”);
printf (“\t10. Reset the device\n”);
printf (“\t11. Reenumerate the device\n”);
printf (“\n\t0. Exit\n”);
printf (“\n\tSelection: “);

if (scanf_s (”%d”, &function) <= 0) {

printf(“Error reading input!\n”);
goto Error;

}

switch(function) {

case LIGHT_ONE_BAR:

printf(“Which Bar (input number 1 thru 8)?\n”);
if (scanf_s (“%d”, &bar) <= 0) {

printf(“Error reading input!\n”);
goto Error;

}

if(bar == 0 || bar > 8){
printf(“Invalid bar number!\n”);
goto Error;
}

bar–; // normalize to 0 to 7

barGraphState.BarsAsUChar = 1 << (UCHAR)bar;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
&barGraphState, // Ptr to InBuffer
sizeof(BAR_GRAPH_STATE), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

break;

case CLEAR_ONE_BAR:

printf(“Which Bar (input number 1 thru 8)?\n”);
if (scanf_s (“%d”, &bar) <= 0) {

printf(“Error reading input!\n”);
goto Error;

}

if(bar == 0 || bar > 8){
printf(“Invalid bar number!\n”);
goto Error;
}

bar–;

//
// Read the current state
//
if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&barGraphState, // Ptr to OutBuffer
sizeof(BAR_GRAPH_STATE), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

if (barGraphState.BarsAsUChar & (1 << bar)) {

printf(“Bar is set…Clearing it\n”);
barGraphState.BarsAsUChar &= ~(1 << bar);

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
&barGraphState, // Ptr to InBuffer
sizeof(BAR_GRAPH_STATE), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;

}

} else {

printf(“Bar not set.\n”);

}

break;

case LIGHT_ALL_BARS:

barGraphState.BarsAsUChar = 0xFF;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
&barGraphState, // Ptr to InBuffer
sizeof(BAR_GRAPH_STATE), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

break;

case CLEAR_ALL_BARS:

barGraphState.BarsAsUChar = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY,
&barGraphState, // Ptr to InBuffer
sizeof(BAR_GRAPH_STATE), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

break;

case GET_BAR_GRAPH_LIGHT_STATE:

barGraphState.BarsAsUChar = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&barGraphState, // Ptr to OutBuffer
sizeof(BAR_GRAPH_STATE), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“Bar Graph: \n”);
printf(" Bar8 is %s\n", barGraphState.Bar8 ? “ON” : “OFF”);
printf(" Bar7 is %s\n", barGraphState.Bar7 ? “ON” : “OFF”);
printf(" Bar6 is %s\n", barGraphState.Bar6 ? “ON” : “OFF”);
printf(" Bar5 is %s\n", barGraphState.Bar5 ? “ON” : “OFF”);
printf(" Bar4 is %s\n", barGraphState.Bar4 ? “ON” : “OFF”);
printf(" Bar3 is %s\n", barGraphState.Bar3 ? “ON” : “OFF”);
printf(" Bar2 is %s\n", barGraphState.Bar2 ? “ON” : “OFF”);
printf(" Bar1 is %s\n", barGraphState.Bar1 ? “ON” : “OFF”);

break;

case GET_SWITCH_STATE:

switchState.SwitchesAsUChar = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_READ_SWITCHES,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&switchState, // Ptr to OutBuffer
sizeof(SWITCH_STATE), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“Switches: \n”);
printf(" Switch8 is %s\n", switchState.Switch8 ? “ON” : “OFF”);
printf(" Switch7 is %s\n", switchState.Switch7 ? “ON” : “OFF”);
printf(" Switch6 is %s\n", switchState.Switch6 ? “ON” : “OFF”);
printf(" Switch5 is %s\n", switchState.Switch5 ? “ON” : “OFF”);
printf(" Switch4 is %s\n", switchState.Switch4 ? “ON” : “OFF”);
printf(" Switch3 is %s\n", switchState.Switch3 ? “ON” : “OFF”);
printf(" Switch2 is %s\n", switchState.Switch2 ? “ON” : “OFF”);
printf(" Switch1 is %s\n", switchState.Switch1 ? “ON” : “OFF”);

break;

case GET_SWITCH_STATE_AS_INTERRUPT_MESSAGE:

switchState.SwitchesAsUChar = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&switchState, // Ptr to OutBuffer
sizeof(switchState), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“Switches: %d\n”,index);
printf(" Switch8 is %s\n", switchState.Switch8 ? “ON” : “OFF”);
printf(" Switch7 is %s\n", switchState.Switch7 ? “ON” : “OFF”);
printf(" Switch6 is %s\n", switchState.Switch6 ? “ON” : “OFF”);
printf(" Switch5 is %s\n", switchState.Switch5 ? “ON” : “OFF”);
printf(" Switch4 is %s\n", switchState.Switch4 ? “ON” : “OFF”);
printf(" Switch3 is %s\n", switchState.Switch3 ? “ON” : “OFF”);
printf(" Switch2 is %s\n", switchState.Switch2 ? “ON” : “OFF”);
printf(" Switch1 is %s\n", switchState.Switch1 ? “ON” : “OFF”);

break;

case GET_7_SEGEMENT_STATE:

sevenSegment = 0;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
&sevenSegment, // Ptr to OutBuffer
sizeof(UCHAR), // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“7 Segment mask: 0x%x\n”, sevenSegment);
break;

case SET_7_SEGEMENT_STATE:

for (i = 0; i < 8; i++) {

sevenSegment = 1 << i;

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY,
&sevenSegment, // Ptr to InBuffer
sizeof(UCHAR), // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
0)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

printf(“This is %d\n”, i);
Sleep(500);

}

printf(“7 Segment mask: 0x%x\n”, sevenSegment);
break;

case RESET_DEVICE:

printf(“Reset the device\n”);

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_RESET_DEVICE,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
NULL)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

break;

case REENUMERATE_DEVICE:

printf(“Re-enumerate the device\n”);

if (!DeviceIoControl(deviceHandle,
IOCTL_OSRUSBFX2_REENUMERATE_DEVICE,
NULL, // Ptr to InBuffer
0, // Length of InBuffer
NULL, // Ptr to OutBuffer
0, // Length of OutBuffer
&index, // BytesReturned
NULL)) { // Ptr to Overlapped structure

code = GetLastError();

printf(“DeviceIoControl failed with error 0x%x\n”, code);

goto Error;
}

//
// Close the handle to the device and exit out so that
// the driver can unload when the device is surprise-removed
// and reenumerated.
//
default:

result = TRUE;
goto Error;

}

} // end of while loop

Error:

CloseHandle(deviceHandle);
return result;

}

ULONG
AsyncIo(
PVOID ThreadParameter
)
{
HANDLE hDevice = INVALID_HANDLE_VALUE;
HANDLE hCompletionPort = NULL;
OVERLAPPED pOvList = NULL;
PUCHAR buf = NULL;
ULONG_PTR i;
ULONG ioType = (ULONG)(ULONG_PTR)ThreadParameter;
ULONG error;

hDevice = OpenDevice(FALSE);

if (hDevice == INVALID_HANDLE_VALUE) {
printf(“Cannot open device %d\n”, GetLastError());
goto Error;
}

hCompletionPort = CreateIoCompletionPort(hDevice, NULL, 1, 0);

if (hCompletionPort == NULL) {
printf(“Cannot open completion port %d \n”,GetLastError());
goto Error;
}

pOvList = (OVERLAPPED )malloc(NUM_ASYNCH_IO * sizeof(OVERLAPPED));

if (pOvList == NULL) {
printf(“Cannot allocate overlapped array \n”);
goto Error;
}

buf = (PUCHAR)malloc(NUM_ASYNCH_IO * BUFFER_SIZE);

if (buf == NULL) {
printf(“Cannot allocate buffer \n”);
goto Error;
}

ZeroMemory(pOvList, NUM_ASYNCH_IO * sizeof(OVERLAPPED));
ZeroMemory(buf, NUM_ASYNCH_IO * BUFFER_SIZE);

//
// Issue asynch I/O
//

for (i = 0; i < NUM_ASYNCH_IO; i++) {
if (ioType == READER_TYPE) {
if ( ReadFile( hDevice,
buf + (i
BUFFER_SIZE),
BUFFER_SIZE,
NULL,
&pOvList[i]) == 0) {

error = GetLastError();
if (error != ERROR_IO_PENDING) {
printf(" %Iu th read failed %d \n",i, GetLastError());
goto Error;
}
}

} else {
if ( WriteFile( hDevice,
buf + (i
BUFFER_SIZE),
BUFFER_SIZE,
NULL,
&pOvList[i]) == 0) {
error = GetLastError();
if (error != ERROR_IO_PENDING) {
printf(" %Iu th write failed %d \n",i, GetLastError());
goto Error;
}
}
}
}

//
// Wait for the I/Os to complete. If one completes then reissue the I/O
//

WHILE (1) {
OVERLAPPED completedOv;
ULONG_PTR key;
ULONG numberOfBytesTransferred;

if ( GetQueuedCompletionStatus(hCompletionPort, &numberOfBytesTransferred,
&key, &completedOv, INFINITE) == 0) {
printf(“GetQueuedCompletionStatus failed %d\n”, GetLastError());
goto Error;
}

//
// Read successfully completed. Issue another one.
//

if (ioType == READER_TYPE) {

i = completedOv - pOvList;

printf(“Number of bytes read by request number %Iu is %d\n”,
i, numberOfBytesTransferred);

if ( ReadFile( hDevice,
buf + (i * BUFFER_SIZE),
BUFFER_SIZE,
NULL,
completedOv) == 0) {
error = GetLastError();
if (error != ERROR_IO_PENDING) {
printf(“%Iu th Read failed %d \n”, i, GetLastError());
goto Error;
}
}
} else {

i = completedOv - pOvList;

printf(“Number of bytes written by request number %Iu is %d\n”,
i, numberOfBytesTransferred);

if ( WriteFile( hDevice,
buf + (i * BUFFER_SIZE),
BUFFER_SIZE,
NULL,
completedOv) == 0) {
error = GetLastError();
if (error != ERROR_IO_PENDING) {
printf(“%Iu th write failed %d \n”, i, GetLastError());
goto Error;
}
}
}
}

Error:
if (hDevice != INVALID_HANDLE_VALUE) {
CloseHandle(hDevice);
}

if (hCompletionPort) {
CloseHandle(hCompletionPort);
}

if (pOvList) {
free(pOvList);
}
if (buf) {
free(buf);
}

return 1;

}

int
_cdecl
main(
In int argc,
In_reads(argc) LPSTR argv
)
/
++
Routine Description:

Entry point to rwbulk.exe
Parses cmdline, performs user-requested tests

Arguments:

argc, argv standard console ‘c’ app arguments

Return Value:

Zero

/

{
char * pinBuf = NULL;
char * poutBuf = NULL;
ULONG nBytesRead;
ULONG nBytesWrite = 0;
int ok;
int retValue = 0;
UINT success;
HANDLE hRead = INVALID_HANDLE_VALUE;
HANDLE hWrite = INVALID_HANDLE_VALUE;
ULONG fail = 0L;
ULONG i;

Parse(argc, argv );

//
// dump USB configuation and pipe info
//
if (G_fDumpUsbConfig) {
DumpUsbConfig();
}

if (G_fPlayWithDevice) {
PlayWithDevice();
goto exit;
}

if (G_fPerformAsyncIo) {
HANDLE th1;

//
// Create a reader thread
//
th1 = CreateThread( NULL, // Default Security Attrib.
0, // Initial Stack Size,
AsyncIo, // Thread Func
(LPVOID)READER_TYPE,
0, // Creation Flags
NULL ); // Don’t need the Thread Id.

if (th1 == NULL) {
printf(“Couldn’t create reader thread - error %d\n”, GetLastError());
retValue = 1;
goto exit;
}

//
// Use this thread for peforming write.
//
AsyncIo((PVOID)WRITER_TYPE);

goto exit;
}

//
// doing a read, write, or both test
//
if ((G_fRead) || (G_fWrite)) {

if (G_fRead) {
if ( G_fDumpReadData ) { // round size to sizeof ULONG for readable dumping
while( G_ReadLen % sizeof( ULONG ) ) {
G_ReadLen++;
}
}

//
// open the output file
//
hRead = OpenDevice(TRUE);
if(hRead == INVALID_HANDLE_VALUE) {
retValue = 1;
goto exit;
}

pinBuf = malloc(G_ReadLen);
}

if (G_fWrite) {
if ( G_fDumpReadData ) { // round size to sizeof ULONG for readable dumping
while( G_WriteLen % sizeof( ULONG ) ) {
G_WriteLen++;
}
}

//
// open the output file
//
hWrite = OpenDevice(TRUE);
if(hWrite == INVALID_HANDLE_VALUE) {
retValue = 1;
goto exit;
}

poutBuf = malloc(G_WriteLen);
}

for (i = 0; i < G_IterationCount; i++) {
ULONG j;

if (G_fWrite && poutBuf && hWrite != INVALID_HANDLE_VALUE) {

PULONG pOut = (PULONG) poutBuf;
ULONG numLongs = G_WriteLen / sizeof( ULONG );

//
// put some data in the output buffer
//
for (j=0; j *(pOut+j) = j;
}

//
// send the write
//
success = WriteFile(hWrite, poutBuf, G_WriteLen, &nBytesWrite, NULL);
if(success == 0) {
printf(“WriteFile failed - error %d\n”, GetLastError());
retValue = 1;
goto exit;
}
printf(“Write (%04.4u) : request %06.6u bytes – %06.6u bytes written\n”,
i, G_WriteLen, nBytesWrite);

assert(nBytesWrite == G_WriteLen);
}

if (G_fRead && pinBuf) {

success = ReadFile(hRead, pinBuf, G_ReadLen, &nBytesRead, NULL);
if(success == 0) {
printf(“ReadFile failed - error %d\n”, GetLastError());
retValue = 1;
goto exit;
}

printf(“Read (%04.4u) : request %06.6u bytes – %06.6u bytes read\n”,
i, G_ReadLen, nBytesRead);

if (G_fWrite && poutBuf) {

//
// validate the input buffer against what
// we sent to the 82930 (loopback test)
//
ok = Compare_Buffs(pinBuf, nBytesRead, poutBuf, nBytesWrite);

if( G_fDumpReadData ) {
printf(“Dumping read buffer\n”);
Dump( (PUCHAR) pinBuf, nBytesRead );
printf(“Dumping write buffer\n”);
Dump( (PUCHAR) poutBuf, nBytesRead );
}
assert(ok);

if(ok != 1) {
fail++;
}

assert(G_ReadLen == G_WriteLen);
assert(nBytesRead == G_ReadLen);
}
}
}

}

exit:

if (pinBuf) {
free(pinBuf);
}

if (poutBuf) {
free(poutBuf);
}

// close devices if needed
if (hRead != INVALID_HANDLE_VALUE) {
CloseHandle(hRead);
}

if (hWrite != INVALID_HANDLE_VALUE) {
CloseHandle(hWrite);
}

return retValue;
}


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</basetyps.h></setupapi.h></assert.h></stdlib.h></stdio.h></windows.h></driverspecs.h>

Thanks. I changed the interface GUID and now it initialized successfully. I was confusing the class GUID with the interface GUID that’s why it didn’t work.

But now I encountered something really strange. I enumerate the endpoints and I can get 4 endpoints listed but with the same pipe ID ?

Device found: VID_18F7&PID_0030; bcdUsb 0200
Device speed: 3 (High speed).
Endpoint index: 0 Pipe type: Bulk OUT Pipe ID: 0x2 ( OUTPUT)
Endpoint index: 1 Pipe type: Bulk IN Pipe ID: 0x2 ( INPUT )
Endpoint index: 2 Pipe type: Bulk OUT Pipe ID: 0x2 ( OUTPUT)
Endpoint index: 3 Pipe type: Bulk IN Pipe ID: 0x2 ( INPUT )

===========================================================
Below is the code I use:
#include “pch.h”
#include <setupapi.h>

HRESULT
RetrieveDevicePath(
Out_bytecap(BufLen) LPTSTR DevicePath,
In ULONG BufLen,
Out_opt PBOOL FailureDeviceNotFound
);

HRESULT
OpenDevice(
Out PDEVICE_DATA DeviceData,
Out_opt PBOOL FailureDeviceNotFound
)
/++

Routine description:

Open all needed handles to interact with the device.

If the device has multiple USB interfaces, this function grants access to
only the first interface.

If multiple devices have the same device interface GUID, there is no
guarantee of which one will be returned.

Arguments:

DeviceData - Struct filled in by this function. The caller should use the
WinusbHandle to interact with the device, and must pass the struct to
CloseDevice when finished.

FailureDeviceNotFound - TRUE when failure is returned due to no devices
found with the correct device interface (device not connected, driver
not installed, or device is disabled in Device Manager); FALSE
otherwise.

Return value:

HRESULT

/
{
HRESULT hr = S_OK;
BOOL bResult;

DeviceData->HandlesOpen = FALSE;

hr = RetrieveDevicePath(DeviceData->DevicePath,
sizeof(DeviceData->DevicePath),
FailureDeviceNotFound);

if (FAILED(hr)) {

return hr;
}

DeviceData->DeviceHandle = CreateFile(DeviceData->DevicePath,
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);

if (INVALID_HANDLE_VALUE == DeviceData->DeviceHandle) {

hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}

bResult = WinUsb_Initialize(DeviceData->DeviceHandle,
&DeviceData->WinusbHandle);

if (FALSE == bResult) {

hr = HRESULT_FROM_WIN32(GetLastError());
CloseHandle(DeviceData->DeviceHandle);
return hr;
}

DeviceData->HandlesOpen = TRUE;
return hr;
}

VOID
CloseDevice(
Inout PDEVICE_DATA DeviceData
)
/++

Routine description:

Perform required cleanup when the device is no longer needed.

If OpenDevice failed, do nothing.

Arguments:

DeviceData - Struct filled in by OpenDevice

Return value:

None

/
{
if (FALSE == DeviceData->HandlesOpen) {

//
// Called on an uninitialized DeviceData
//
return;
}

WinUsb_Free(DeviceData->WinusbHandle);
CloseHandle(DeviceData->DeviceHandle);
DeviceData->HandlesOpen = FALSE;

return;
}

HRESULT
RetrieveDevicePath(
Out_bytecap(BufLen) LPTSTR DevicePath,
In ULONG BufLen,
Out_opt PBOOL FailureDeviceNotFound
)
/++

Routine description:

Retrieve the device path that can be used to open the WinUSB-based device.

If multiple devices have the same device interface GUID, there is no
guarantee of which one will be returned.

Arguments:

DevicePath - On successful return, the path of the device (use with CreateFile).

BufLen - The size of DevicePath’s buffer, in bytes

FailureDeviceNotFound - TRUE when failure is returned due to no devices
found with the correct device interface (device not connected, driver
not installed, or device is disabled in Device Manager); FALSE
otherwise.

Return value:

HRESULT

/
{
BOOL bResult = FALSE;
HDEVINFO deviceInfo;
SP_DEVICE_INTERFACE_DATA interfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;
ULONG length;
ULONG requiredLength=0;
HRESULT hr;

if (NULL != FailureDeviceNotFound) {

FailureDeviceNotFound = FALSE;
}

//
// Enumerate all devices exposing the interface
//
deviceInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBApplication1,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if (deviceInfo == INVALID_HANDLE_VALUE) {

hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}

interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

//
// Get the first interface (index 0) in the result set
//
bResult = SetupDiEnumDeviceInterfaces(deviceInfo,
NULL,
&GUID_DEVINTERFACE_USBApplication1,
0,
&interfaceData);

if (FALSE == bResult) {

//
// We would see this error if no devices were found
//
if (ERROR_NO_MORE_ITEMS == GetLastError() &&
NULL != FailureDeviceNotFound) {

FailureDeviceNotFound = TRUE;
}

hr = HRESULT_FROM_WIN32(GetLastError());
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}

//
// Get the size of the path string
// We expect to get a failure with insufficient buffer
//
bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo,
&interfaceData,
NULL,
0,
&requiredLength,
NULL);

if (FALSE == bResult && ERROR_INSUFFICIENT_BUFFER != GetLastError()) {

hr = HRESULT_FROM_WIN32(GetLastError());
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}

//
// Allocate temporary space for SetupDi structure
//
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
LocalAlloc(LMEM_FIXED, requiredLength);

if (NULL == detailData)
{
hr = E_OUTOFMEMORY;
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}

detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
length = requiredLength;

//
// Get the interface’s path string
//
bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo,
&interfaceData,
detailData,
length,
&requiredLength,
NULL);

if(FALSE == bResult)
{
hr = HRESULT_FROM_WIN32(GetLastError());
LocalFree(detailData);
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}

//
// Give path to the caller. SetupDiGetDeviceInterfaceDetail ensured
// DevicePath is NULL-terminated.
//
hr = StringCbCopy(DevicePath,
BufLen,
detailData->DevicePath);

LocalFree(detailData);
SetupDiDestroyDeviceInfoList(deviceInfo);

return hr;
}

/

//-----------------------------------------------------------------------------
// QueryDeviceEndpoints()
//
// Parameters:
// hDeviceHandle : WinUSB Interface Handle
// pipeid : Pipe ID returned
//
// Return Values:
// true : success
// false: fail
//
// Remarks:
// Function to check end points and get pipe ID
//-----------------------------------------------------------------------------
/
BOOL QueryDeviceEndpoints(WINUSB_INTERFACE_HANDLE hDeviceHandle, struct PIPE_ID* pipeid)
{
if (hDeviceHandle == INVALID_HANDLE_VALUE) {
return FALSE;
}

BOOL bResult = TRUE;

USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
ZeroMemory(&InterfaceDescriptor, sizeof(USB_INTERFACE_DESCRIPTOR));

WINUSB_PIPE_INFORMATION Pipe;
ZeroMemory(&Pipe, sizeof(WINUSB_PIPE_INFORMATION));

bResult = WinUsb_QueryInterfaceSettings(hDeviceHandle, 0, &InterfaceDescriptor);

if (bResult) {
for (int index = 0; index < InterfaceDescriptor.bNumEndpoints; index++) {

bResult = WinUsb_QueryPipe(hDeviceHandle, NULL, index, &Pipe);

if (bResult) {
if (Pipe.PipeType == UsbdPipeTypeControl) {
printf(“Endpoint index: %d Pipe type: Control Pipe ID: %d.\n”, index, Pipe.PipeType, Pipe.PipeId);
}

if (Pipe.PipeType == UsbdPipeTypeIsochronous) {
printf(“Endpoint index: %d Pipe type: Isochronous Pipe ID: %d.\n”, index, Pipe.PipeType, Pipe.PipeId);
}

if (Pipe.PipeType == UsbdPipeTypeBulk) {

if (USB_ENDPOINT_DIRECTION_IN(Pipe.PipeId)) {
printf(“Endpoint index: %d Pipe type: Bulk IN Pipe ID: 0x%x ( INPUT )\n”, index, Pipe.PipeType, Pipe.PipeId);
pipeid->PipeInId = Pipe.PipeId;
}

if (USB_ENDPOINT_DIRECTION_OUT(Pipe.PipeId)) {
printf(“Endpoint index: %d Pipe type: Bulk OUT Pipe ID: 0x%x ( OUTPUT)\n”, index, Pipe.PipeType, Pipe.PipeId);
pipeid->PipeOutId = Pipe.PipeId;
}

}

if (Pipe.PipeType == UsbdPipeTypeInterrupt) {
printf(“Endpoint index: %d Pipe type: Interrupt Pipe ID: %d.\n”, index, Pipe.PipeType, Pipe.PipeId);
}
}
else {
continue;
}
}
}

//done:
return bResult;
} // End of QueryDeviceEndpoints()

/
//-----------------------------------------------------------------------------
// GetUSBDeviceSpeed()
//
// Parameters:
// hDeviceHandle : WinUSB Interface Handle
// pDeviceSpeed : Device Speed returned
//
// Return Values:
// true : success
// false: fail
//
// Remarks:
// Function to get device speed
//-----------------------------------------------------------------------------
/

BOOL GetUSBDeviceSpeed(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pDeviceSpeed)
{
if (!pDeviceSpeed || hDeviceHandle == INVALID_HANDLE_VALUE) {
return FALSE;
}

BOOL bResult = TRUE;

ULONG length = sizeof(UCHAR);

bResult = WinUsb_QueryDeviceInformation(hDeviceHandle, DEVICE_SPEED, &length, pDeviceSpeed);
if (!bResult) {
printf(“Error getting device speed: %d.\n”, GetLastError());
goto done;
}

if (*pDeviceSpeed == LowSpeed) {
printf(“Device speed: %d (Low speed).\n”, *pDeviceSpeed);
goto done;
}

if (pDeviceSpeed == FullSpeed) {
printf(“Device speed: %d (Full speed).\n”, pDeviceSpeed);
goto done;
}

if (pDeviceSpeed == HighSpeed) {
printf(“Device speed: %d (High speed).\n”, pDeviceSpeed);
goto done;
}

done:
return bResult;
} // End of GetUSBDeviceSpeed()

/

//-----------------------------------------------------------------------------
// WriteToBulkEndpoint()
//
// Parameters:
// hDeviceHandle : WinUSB Interface Handle
// pID : pointer to Pipe ID
// pcbWritten : number of bytes actually written to the OUT endpoint
// szBuffer : data buffer to be written
// cbSize : size of the data buffer to be written
//
// Return Values:
// true : success
// false: fail
//
// Remarks:
// Function to write data to OUT bulk endpoint
//-----------------------------------------------------------------------------
/

BOOL WriteToBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR
pID, ULONG
pcbWritten, UCHAR szBuffer, ULONG cbSize)
{
if (hDeviceHandle == INVALID_HANDLE_VALUE || !pID || !pcbWritten) {
return FALSE;
}

BOOL bResult = TRUE;

// UCHAR szBuffer[] = “Hello World”;
// ULONG cbSize = strlen((char
)szBuffer);
ULONG cbSent = 0;

bResult = WinUsb_WritePipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbSent, 0);
if (!bResult) {
goto done;
}

//== printf(“Wrote to pipe %d: %s \nActual data transferred: %d.\n”, pID, szBuffer, cbSent);
pcbWritten = cbSent;

done:
return bResult;

} // End of WriteToBulkEndpoint()

===========================================================
main.cpp

#include “pch.h”

#include <stdio.h>

LONG __cdecl
_tmain(
LONG Argc,
LPTSTR * Argv
)
/
++

Routine description:

Sample program that communicates with a USB device using WinUSB

/
{
DEVICE_DATA deviceData;
HRESULT hr;
USB_DEVICE_DESCRIPTOR deviceDesc;
BOOL bResult;
BOOL noDevice;
ULONG lengthReceived;

UNREFERENCED_PARAMETER(Argc);
UNREFERENCED_PARAMETER(Argv);

struct PIPE_ID PipeID;
UCHAR DeviceSpeed;
//
// Find a device connected to the system that has WinUSB installed using our
// INF
//
hr = OpenDevice(&deviceData, &noDevice);

if (FAILED(hr)) {

if (noDevice) {

printf(_T(“Device not connected or driver not installed\n”));

} else {

printf(_T(“Failed looking for device, HRESULT 0x%x\n”), hr);
}

return 0;
}

//
// Get device descriptor
//
bResult = WinUsb_GetDescriptor(deviceData.WinusbHandle,
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
(PBYTE) &deviceDesc,
sizeof(deviceDesc),
&lengthReceived);

if (FALSE == bResult || lengthReceived != sizeof(deviceDesc)) {

printf(T(“Error among LastError %d or lengthReceived %d\n”),
FALSE == bResult ? GetLastError() : 0,
lengthReceived);
CloseDevice(&deviceData);
return 0;
}

//
// Print a few parts of the device descriptor
//
printf(T("Device found: VID%04X&PID
%04X; bcdUsb %04X\n"),
deviceDesc.idVendor,
deviceDesc.idProduct,
deviceDesc.bcdUSB);

bResult = GetUSBDeviceSpeed(deviceData.WinusbHandle, &DeviceSpeed);

bResult = QueryDeviceEndpoints(deviceData.WinusbHandle, &PipeID);

CloseDevice(&deviceData);
return 0;
}</stdio.h></setupapi.h>

xxxxx@gmail.com wrote:

But now I encountered something really strange. I enumerate the endpoints and I can get 4 endpoints listed but with the same pipe ID ?

Device found: VID_18F7&PID_0030; bcdUsb 0200
Device speed: 3 (High speed).
Endpoint index: 0 Pipe type: Bulk OUT Pipe ID: 0x2 ( OUTPUT)
Endpoint index: 1 Pipe type: Bulk IN Pipe ID: 0x2 ( INPUT )
Endpoint index: 2 Pipe type: Bulk OUT Pipe ID: 0x2 ( OUTPUT)
Endpoint index: 3 Pipe type: Bulk IN Pipe ID: 0x2 ( INPUT )

It’s because you have a bug:
printf(“Endpoint index:
%d Pipe type: Bulk IN Pipe ID: 0x%x ( INPUT )\n”, index, Pipe.PipeType,
Pipe.PipeId);

The “0x2” is the PipeType. You are not using the PipeId. You should
have been able to figure out that you weren’t really looking at the
PipeId, because your code uses the PipeId to decide whether to print OUT
or IN, and that’s working correctly.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Thanks. That was as dumb as I can be…