Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

USB Reader

JohnNichols
Valued Contributor III
1,795 Views
Dear Fellow Fortraners:

Greetings from Texas where is the world is burning.

Two new things in one month is to much to ask for:

A new Fortran compiler and a new daughter. Steve: Nice intro to the new compiler.

I am writing some code to access a USB port. I have a previous post about this, but now I have he device driver loaded. I found it nearly impossible to use MS Studio to access the device in C++. So now I am back where I belong in Fortran.

Question 1: How dod I put a GUID into Fortran:

[bash] GUIDUSB = "78A1C341-4539-11d3-B88D-00C04FAD5171"

    
	TYPE (GUID), PARAMETER :: IID_IDispatch = &
		  GUID(#00020400, #0000, #0000, &
		  CHAR('C0'X)//CHAR('00'X)//CHAR('00'X)//CHAR('00'X)// &
		  CHAR('00'X)//CHAR('00'X)//CHAR('00'X)//CHAR('46'X))
   
[/bash]
0 Kudos
13 Replies
Steven_L_Intel1
Employee
1,795 Views
How about you show us the declaration of the device routine you want to pass the GUID to.
0 Kudos
JohnNichols
Valued Contributor III
1,795 Views
Dear Steve:

There is a board called OSRUSBFX2 sold by OSRONLINE as a teaching board for device drivers.

It is by some quirk of fate used by microsoft as the example in WINDDK for the development of device drivers.

I enclose the C files for the build, the problem is the WINDDK uses a different build environment to the MS Studio and it is a ***** to translate. There is a program called DDKBUILD that has two variants, but again problematic.

I have the board driver loaded, but getting the exe file that runs the board into FORTRAN would be a nice goal so I know I can do the same with the acceleromter driver.

I am aware of the degree of difficulty.

I need to get the CREATEFILE working, but to do that we need a routine that turns the GUID into a file name so to speak.

JMN
0 Kudos
JohnNichols
Valued Contributor III
1,795 Views
Files required.
0 Kudos
JohnNichols
Valued Contributor III
1,795 Views
0 Kudos
JohnNichols
Valued Contributor III
1,795 Views
[bash]BOOL GetDeviceHandle (GUID guidDeviceInterface, PHANDLE hDeviceHandle)
{
    if (guidDeviceInterface==GUID_NULL)
    {
        return FALSE;
    }

    BOOL bResult = TRUE;
    HDEVINFO hDeviceInfo;
    SP_DEVINFO_DATA DeviceInfoData;

    SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;

    ULONG requiredLength=0;

    LPTSTR lpDevicePath = NULL;

    DWORD index = 0;

    // Get information about all the installed devices for the specified
    // device interface class.
    hDeviceInfo = SetupDiGetClassDevs( 
        &guidDeviceInterface,
        NULL, 
        NULL,
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

    if (hDeviceInfo == INVALID_HANDLE_VALUE) 
    { 
        // ERROR 
        printf("Error SetupDiGetClassDevs: %d.n", GetLastError());
        goto done;
    }

    //Enumerate all the device interfaces in the device information set.
    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

    for (index = 0; SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData); index++)
    {
        //Reset for this iteration
        if (lpDevicePath)
        {
            LocalFree(lpDevicePath);
        }
        if (pInterfaceDetailData)
        {
            LocalFree(pInterfaceDetailData);
        }

        deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

        //Get information about the device interface.
        bResult = SetupDiEnumDeviceInterfaces( 
           hDeviceInfo,
           &DeviceInfoData,
           &guidDeviceInterface,
           index, 
           &deviceInterfaceData);

        // Check if last item
        if (GetLastError () == ERROR_NO_MORE_ITEMS)
        {
            break;
        }

        //Check for some other error
        if (!bResult) 
        {
            printf("Error SetupDiEnumDeviceInterfaces: %d.n", GetLastError());
            goto done;
        }

        //Interface data is returned in SP_DEVICE_INTERFACE_DETAIL_DATA
        //which we need to allocate, so we have to call this function twice.
        //First to get the size so that we know how much to allocate
        //Second, the actual call with the allocated buffer
        
        bResult = SetupDiGetDeviceInterfaceDetail(
            hDeviceInfo,
            &deviceInterfaceData,
            NULL, 0,
            &requiredLength,
            NULL);


        //Check for some other error
        if (!bResult) 
        {
            if ((ERROR_INSUFFICIENT_BUFFER==GetLastError()) && (requiredLength>0))
            {
                //we got the size, allocate buffer
                pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, requiredLength);
                
                if (!pInterfaceDetailData) 
                { 
                    // ERROR 
                    printf("Error allocating memory for the device detail buffer.n");
                    goto done;
                }
            }
            else
            {
                printf("Error SetupDiEnumDeviceInterfaces: %d.n", GetLastError());
                goto done;
            }
        }

        //get the interface detailed data
        pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        //Now call it with the correct size and allocated buffer
        bResult = SetupDiGetDeviceInterfaceDetail(
                hDeviceInfo,
                &deviceInterfaceData,
                pInterfaceDetailData,
                requiredLength,
                NULL,
                &DeviceInfoData);
        
        //Check for some other error
        if (!bResult) 
        {
            printf("Error SetupDiGetDeviceInterfaceDetail: %d.n", GetLastError());
            goto done;
        }

        //copy device path
                
        size_t nLength = wcslen (pInterfaceDetailData->DevicePath) + 1;  
        lpDevicePath = (TCHAR *) LocalAlloc (LPTR, nLength * sizeof(TCHAR));
        StringCchCopy(lpDevicePath, nLength, pInterfaceDetailData->DevicePath);
        lpDevicePath[nLength-1] = 0;
                        
        printf("Device path:  %sn", lpDevicePath);

    }

    if (!lpDevicePath)
    {
        //Error.
        printf("Error %d.", GetLastError());
        goto done;
    }

    //Open the device
    *hDeviceHandle = CreateFile (
        lpDevicePath,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        NULL);

    if (*hDeviceHandle == INVALID_HANDLE_VALUE)
    {
        //Error.
        printf("Error %d.", GetLastError());
        goto done;
    }
[/bash]
0 Kudos
JohnNichols
Valued Contributor III
1,795 Views
Dear Steve:

This is the problem as I see it.

I can find the CREATEFILE routine through IFWINTY and it is not that hard to seehow to implement it, but the routine GETDEVICEHANDLE written by Microsoft as part of their help files is not available as a FORTRAN interface.

So that is where it stands.

Why MICROSOFT makes the WINDDK outsde the Visual Studio system is a mystery, but then again the world is full of mysteries,

REgards

JMN
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,795 Views
John,

You might find this article interesting:

http://www.developerfusion.com/article/84338/making-usb-c-friendly/

And this .PDF file has additional technical information:

http://delcomproducts.com/downloads/USBPRGMNL.pdf

Jim Dempsey



0 Kudos
JohnNichols
Valued Contributor III
1,795 Views
Dear Jim:

Thanks I found the two articles very helpful.

I note with interest in one of the articles, the first, that the author notes that there is very limited written information available on the topic.

I tried to get even the first DDK header C files to be accepted in VS and got nowhere.

I think chewing away at this problem in FORTRAN will be the quickest in the long run.

Why the DDK team at Microsoft did there own thing using a special purpose make program called BUILD is beyond my understanding. VS might have its problems and it does, but at least we know the problems and can talk to intelligent people about them.

Thanks again.

JMN

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,795 Views
John,

For some (screwy) reason MS choose to use CreateFile to do all kinds of goofy things, one of which is to get a device handle. My guess is the sample program had a wrapper function called GETDEVICEHANDLE and the wrapper function wasn't included (or you did not notice it in the sample program). The "goofy things" are accessed by passing "goofy path" such as \\.\DeviceNameHere\... or \\?\... or \\{other token here\...

I would have added a separate API. Unfortunately MSDN documentation for CreateFile does not conveniently list all the possibilities of use.

Jim Dempsey
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,795 Views
Here is another link

http://msdn.microsoft.com/en-us/library/ff540174(v=vs.85).aspx#filehandle

"To access a USB device, you need a valid file handle for the device...."

***

BTW this sample code contains a function

BOOL GetDeviceHandle (GUID guidDeviceInterface, PHANDLE hDeviceHandle)


Jim Dempsey
0 Kudos
JohnNichols
Valued Contributor III
1,795 Views
Dear Jim:

Thanks for the notes. The DELCOM stuff is really good.

I have boought a test board from OSRONLINE to learn about this stuff, mainly so I could see how to play with a much more complicated USB device.

The Driver people remind me of the old University Unix people who took some perverse pleasure in using arcane commands and forming a small clannish sect on some small Outer Scottish island. I imagine there pub is full of smoke whiskey and old macs.

LISP is ultimate expression of this form, except that it was first and there is an age oldbeauty to the product, that I can not see in WINDDK.

Iam going to try today to get it running, now that I have read enough.

Thanks again

JMN



0 Kudos
jimdempseyatthecove
Honored Contributor III
1,795 Views
The OSR group is real great, I've delt with them in a past life. (Cost are an arm and leg but well worth it)

>>...the old University Unix people who took some perverse pleasure in using arcane commands and forming a small clannish sect on some small Outer Scottish island...

Well you know about the Irishman who liked to play practical jokes. He concocted this gawd-awful sounding insturment out of a sheep's stomach and woodwinds then took it to Scottland... the rest is history.

After you get your USB project running, you might want to posta link to your web site where you document your work. It may be of interest to others that have been following this thread.

Jim Dempsey
0 Kudos
JohnNichols
Valued Contributor III
1,795 Views
Dear Jim:

Thanks for your help on the USB device. It was a long slow ten days from the 6th till the 17th when I finally got the USB device to respond to a program written using VS 2010, in this case in C++.

I have a separate post asking Steve how to get the linker to see the SETUPAPI library which is needed to access USB devices from Intel Fortran. I know it is simple I just can not see it.

I learnt a lot along the way,
1. USB driver are built using DDKBuild, which is an interesting command line program. The programmers who use it seem to love it. it is the standard Microsoft build method if I understand the various notes I got correclty.
2. To access a USB device it is necessary to either use the DDk Build or to take the libraries and sample programs and build a C++ one in VS 2010 or whatever flaovour you like. Certainly this is the deepest foray I have had into C++ and like most previous forays it is an interesting language with many features and a lot of pitfalls.
3. this morning I got the code running in C++ on VS 2010. it is for the OSR USB FX2 board.

There is absolutely no way I am going to port the code to Fortran, life is to short for that much "pleasure", but at least now I can call the C++ code from my Fortran CX1Reader program.

Back to normal work now.

JMN
0 Kudos
Reply