天天看點

基于WINCE6.0系統,SD卡和flash作為PC機的U盤

基于WINCE6.0系統,SD卡和flash作為PC機的U盤

分類:  WINCE驅動開發2012-05-04 21:26  181人閱讀  評論(0)  收藏  舉報

********************************LoongEmbedded********************************

作者:LoongEmbedded(kandi)

時間:2012.05.04

類别:WINCE驅動開發

********************************LoongEmbedded********************************

根據客戶的要求,希望我們WINCE裝置可以作為PC機器的可移動磁盤,并且可以通過應用軟體能夠實作mass storage和ActiveSync的切換,那怎麼實作這個功能呢:

1.       系統元件

選擇ActiveSync、mass storage和serial元件,如下圖所示:

基于WINCE6.0系統,SD卡和flash作為PC機的U盤

圖1

2.       驅動的支援以及需要注意的系統資料庫項

我們先來看USB用戶端驅動的系統資料庫資訊

IF BSP_USBFNCLASS == MASS_STORAGE

[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers]

    "DefaultClientDriver"=- ; erase previous default

    "DefaultClientDriver"="Mass_Storage_Class"

ENDIF BSP_USBFNCLASS

[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers\Mass_Storage_Class]

    "Dll"="usbmsfn.dll"

    "InterfaceSubClass"=dword:06

    "InterfaceProtocol"=dword:50

    "DeviceName"="DSK1:" ; 被映射為U盤的儲存設備的裝置名

    "FriendlyName"="Mass Storage";顯示裝置名

    "idVendor"=dword:045E; Vendor ID,應該向USB組織申請

    "Manufacturer"="Generic Manufacturer (PROTOTYPE--Remember to change idVendor)";廠商命

    "idProduct"=dword:FFFF; Product ID,由廠商定義

    "Product"="Generic Mass Storage (PROTOTYPE--Remember to change idVendor)";産品名

    "bcdDevice"=dword:0;裝置的版本号

[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers\RNDIS]

    "idVendor"=dword:0547

    "Manufacturer"=LOC_USBFN_RNDIS_MANUFACTURER

    "idProduct"=dword:2c2d

    "Product"=LOC_USBFN_RNDIS_PRODUCT

[HKEY_LOCAL_MACHINE\Drivers\USB\FunctionDrivers\Serial_Class]

    "FriendlyName"=LOC_USBFN_SERIAL_NAME

    "idVendor"=dword:045E

    "Manufacturer"=LOC_USBFN_SERIAL_MANUFACTURER

    "idProduct"=dword:00CE

    "Product"=LOC_USBFN_SERIAL_PRODUCT

    "Index"=dword:5

[HKEY_CURRENT_USER\ControlPanel\Comm]

"Cnct"="`USB"

在上面的系統資料庫資訊中,如果要把SD卡或是flash分區作為PC機的可移動盤,一定要讓"DeviceName"="DSK1:"中的1和SD卡驅動或是flash驅動的index一緻,這樣就可以實作這個功能了。

3.       mass storage和ActiveSync切換

這個功能可以通過一個應用軟體來實作,主要的工作如下:

⑴基于GUID調用FindFirstDevice函數擷取到USB控制器驅動(比如s3c2450_usbfn.dll)的句柄。

⑵通過上面擷取的驅動句柄,以控制碼IOCTL_UFN_GET_CURRENT_CLIENT調用DeviceIoControl函數來擷取目前已經加載的USB用戶端驅動,然後以控制碼IOCTL_UFN_CHANGE_CURRENT_CLIENT調用DeviceIoControl函數來切換USB用戶端驅動(比如由mass storage切換為ActiveSync)。

⑶修改系統資料庫資訊,比如把"DefaultClientDriver"="Mass_Storage_Class"改為"DefaultClientDriver"="serial"

具體的代碼如下:

#define FILE_DEVICE_UNKNOWN             0x00000022

#define METHOD_BUFFERED                 0

#define FILE_ANY_ACCESS                 0

#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \

    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \

)

#define _UFN_ACCESS_CTL_CODE(_Function)  \

    CTL_CODE(FILE_DEVICE_UNKNOWN, _Function, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_UFN_GET_CURRENT_CLIENT                _UFN_ACCESS_CTL_CODE(3)

#define IOCTL_UFN_CHANGE_CURRENT_CLIENT             _UFN_ACCESS_CTL_CODE(4)

#define UFN_CLIENT_NAME_MAX_CHARS 128

#define UFN_CLIENT_DESCRIPTION_MAX_CHARS 250

typedef struct _UFN_CLIENT_INFO {

    TCHAR szName[UFN_CLIENT_NAME_MAX_CHARS];

    TCHAR szDescription[UFN_CLIENT_DESCRIPTION_MAX_CHARS];

} UFN_CLIENT_INFO, *PUFN_CLIENT_INFO;

typedef struct _UFN_CLIENT_NAME {

    TCHAR szName[UFN_CLIENT_NAME_MAX_CHARS];

} UFN_CLIENT_NAME, *PUFN_CLIENT_NAME;

static HKEY hOpenKey=NULL;

#define DRIVER_USB_KEY TEXT("Drivers\\USB\\FunctionDrivers")

#define DRIVER_USB_NAME TEXT("DefaultClientDriver")

#define DRIVER_USB_VALUE_SERIAL TEXT("Serial_Class")

#define DRIVER_USB_VALUE_STORAGE TEXT("Mass_Storage_Class")

HANDLE GetUfncontroller()

{

    HANDLE hUfn = NULL;

DEVMGR_DEVICE_INFORMATION di;

memset(&di, 0, sizeof(di));

di.dwSize = sizeof(di);

GUID guidUsbFn = { 0xE2BDC372, 0x598F, 0x4619, 0xBC, 0x50, 0x54, 0xB3, 0xF7, 0x84, 0x8D, 0x35 };

    HANDLE hf = FindFirstDevice(DeviceSearchByGuid, &guidUsbFn, &di);

if (hf != INVALID_HANDLE_VALUE)

{

   hUfn = CreateFile(di.szBusName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

CloseHandle(hf);

}

else

{

   hUfn = INVALID_HANDLE_VALUE;

}

return hUfn;

}

void CusbfunctionswitchDlg::OnBnClickedStorageActivesyncSwitch()

{

         // TODO: Add your control notification handler code here

         HANDLE hDisk = NULL;

         BOOL   fnTypeStorage = TRUE;

         UFN_CLIENT_NAME uname;

         UFN_CLIENT_INFO uinfo;

         DWORD dwReturn = 0;

         _tcscpy(uname.szName, L"Mass_Storage_Class");

         hDisk = GetUfncontroller();

         if (hDisk == INVALID_HANDLE_VALUE)

         {

         RETAILMSG(1, (TEXT("invalid usb handle, error = %d/r/n"), GetLastError()));

         }

         if (DeviceIoControl(hDisk, IOCTL_UFN_GET_CURRENT_CLIENT, NULL, 0, &uinfo, sizeof(uinfo), &dwReturn, 0) && (dwReturn == sizeof(uinfo)))

         {

         if (_tcscmp(L"Mass_Storage_Class", uinfo.szName) == 0)

         {

                   _tcscpy(uname.szName, L"Serial_Class");

                   fnTypeStorage = FALSE;

         }

         else

         {

                   fnTypeStorage = TRUE;

         }

         }

         if (!DeviceIoControl(hDisk, IOCTL_UFN_CHANGE_CURRENT_CLIENT, &uname, sizeof(uname), NULL, 0, NULL, NULL))

         {

                   RETAILMSG(1, (TEXT("deviceiocontrol failed, error = %d/r/n"), GetLastError()));

         }

         else

         {

                   LONG    lResult = 0;

                   if(fnTypeStorage)

                   {

                            lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, DRIVER_USB_KEY, 0, 0, &hOpenKey );

                            if(ERROR_SUCCESS == lResult)

                            {

                                     lResult = RegSetValueEx(hOpenKey,DRIVER_USB_NAME,0,REG_SZ,(BYTE *)DRIVER_USB_VALUE_STORAGE,sizeof(DRIVER_USB_VALUE_STORAGE));

                            }

                   }

                   else

                   {

                            lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, DRIVER_USB_KEY, 0, 0, &hOpenKey );

                            if(ERROR_SUCCESS == lResult)

                            {

                                     lResult = RegSetValueEx(hOpenKey,DRIVER_USB_NAME,0,REG_SZ,(BYTE *)DRIVER_USB_VALUE_SERIAL,sizeof(DRIVER_USB_VALUE_SERIAL));

                            }

                   }

                   RegCloseKey( hOpenKey );

         }

}