PrabuKumar's WinCE Blog

October 7, 2008

USB Function driver dynamic Switching in WINCE

We have three USB function class drivers in WinCE.

1. Serial

2. Mass Storage

3. RNDIS

Usually only one driver will load by default.Now the question is

“Is it possible to switch the USB Function driver dynamically during WinCE runtime?”

Yes it is possible.We have one IOCTL(IOCTL_UFN_CHANGE_CURRENT_CLIENT) for changing the current USB function driver.I found this solution in wince newsgroups only.Just to share the code I have written this blog.

You can test this by doing the following things:

But before doing these steps,first confirm the working of individual functions(Serial,Mass Storage,RNDIS) on your platform.Then go for this option.

1. Add all the three components in the catalog items.”Device Driver–>USB Function Driver–>Serial

                                                                                                                –>Mass Storage

                                                                                                                –>RNDIS”

2. Compile and generate the OS binary.

3. Write simple application to add the following functions.

HANDLE GetUfnController()
{
    HANDLE hUfn = NULL;
    BYTE rgbGuidBuffer[sizeof(GUID) + 4]; // +4 because scanf writes longs
    LPGUID pguidBus = (LPGUID) rgbGuidBuffer;
    LPCTSTR pszBusGuid = _T(“E2BDC372-598F-4619-BC50-54B3F7848D35”);
    // Parse the GUID
    int iErr = _stscanf(pszBusGuid, SVSUTIL_GUID_FORMAT,SVSUTIL_PGUID_ELEMENTS(&pguidBus));
    if (iErr == 0 || iErr == EOF)
        return INVALID_HANDLE_VALUE;
    // Get a handle to the bus driver
    DEVMGR_DEVICE_INFORMATION di;
    memset(&di, 0, sizeof(di));
    di.dwSize = sizeof(di);
    HANDLE hf = FindFirstDevice(DeviceSearchByGuid, pguidBus, &di);
    if (hf != INVALID_HANDLE_VALUE) {
        RETAILMSG(1,(TEXT(“FindDevice = %s\r\n”),di.szBusName));
        hUfn = CreateFile(di.szBusName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
        CloseHandle(hf);
    }
    else {
        hUfn = INVALID_HANDLE_VALUE;
    }
    return hUfn;

}

BOOL ChangeClient(HANDLE hUfn, LPCTSTR pszNewClient)
{
    if(hUfn == INVALID_HANDLE_VALUE || pszNewClient == NULL)
        return ERROR_INVALID_PARAMETER;
    DWORD dwRet = ERROR_SUCCESS;
    UFN_CLIENT_NAME ucn;
    _tcscpy(ucn.szName, pszNewClient);
    RETAILMSG(1,(TEXT(“NewClient Name: %s\r\n”),pszNewClient));
    BOOL fSuccess = DeviceIoControl(hUfn,IOCTL_UFN_CHANGE_CURRENT_CLIENT, &ucn, sizeof(ucn), NULL, 0, NULL,
NULL);

    CloseHandle(hUfn);
    RETAILMSG(1,(TEXT(“DeviceIOcontrol Returned value=0x%x\r\n”),fSuccess));
   return fSuccess;

}

4. I have written small menu based application with three menus for selecting the current client driver to load.Here is the code which I handled in the menus.By selecting the corresponding menu will change the corresponding function driver to load.

case ID_USBFN_SERIAL:
    wsprintf(tempBuf,_T(“serial_class”));
    ChangeClient(GetUfnController(),tempBuf);
    break;

case ID_USBFN_MASS:
    wsprintf(tempBuf,_T(“mass_storage_class”));
    ChangeClient(GetUfnController(),tempBuf);
    break;

case ID_USBFN_RNDIS:
    wsprintf(tempBuf,_T(“RNDIS”));
    ChangeClient(GetUfnController(),tempBuf);
    break;

With this solution now you have all the three functions in single NK.bin but still you can use only one function(i.e.either serial or mass storage or RNDIS)at a time.If you want to use two functions(ex:Serial and Mass storage) simultaneously then you need to go for new feature USB Function Composite device driver which is supported in Wince 6.0.

Advertisements

4 Comments »

  1. I am using this code in my user application (WM2003, WM5.0, WM6.1 and WinCE 5.0 based devices) which require disconnect ActiveSync, do the processing and then connect again the ActiveSync.

    For disconnecting I am calling IOCTL_UFN_CHANGE_CURRENT_CLIENT with wsprintf(tempBuf,_T(”mass_storage_class”)), and for connecting again I am using wsprintf(tempBuf,_T(”serial_class”));

    Its working properly, but not in all devices. Sometime It does not connect back the ActiveSync. Not able to find out that on user lavel what is the way to connect and disconnect ActiveSync programatically.

    Can you suggest something ?
    – Rahul

    Comment by rahulprashant — January 19, 2009 @ 4:10 pm

  2. Hi Prabhu,

    Thanks for you post. It is really useful.
    I have a query.I have a Hp Ipaq in which after switching the mode using the above code, my PC is able to find that the connected device mode has changed automatically( with unplugging and plugging back the Hp ipaq to the PC). However, I have another PDA in which after switching the mode using the above code I had to unplug and plug back to the PC to get the PC understand that device mode has changed.

    Why is this difference?

    I was trying to use a USB port monitor to find the difference in both the scenarios. Look like device sends RESET command in working case, which does not happen in the non working case.

    Is it possible for a application running in device, to issue a force reset(after switching mode) to its usb device port so that the host recognizes the mode switch without unplugging and plugging?

    Any help appreciated.

    With Thanks & Regards,
    A.Ilamparithi.

    Comment by ilamparithi1982 — February 17, 2009 @ 2:44 pm

  3. At the application level it is not possible,but if you have the rights to edit your BSP driver code then you can achieve this.

    Comment by prabukumar — February 18, 2009 @ 10:55 pm

  4. […] USB Function driver dynamic Switching in WINCE October 2008 3 comments 4 […]

    Pingback by 2010 in review « PrabuKumar’s Blog — January 31, 2011 @ 4:49 pm


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: