百度一下
http://bbs.csdn.net/topics/310030218
IOCTL_UFN_CHANGE_CURRENT_CLIENT 这个貌似可以实现
********************************LoongEmbedded******************************** 作者:LoongEmbedded(kandi) 时间:2012.05.04 类别:WINCE驱动开发 ********************************LoongEmbedded******************************** 根据客户的要求,希望我们WINCE设备可以作为PC机器的可移动磁盘,并且可以通过应用软件能够实现mass storage和ActiveSync的切换,那怎么实现这个功能呢: 1. 系统组件 选择ActiveSync、mass storage和serial组件,如下图所示:
图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 ); } }
[ 本帖最后由 Wince.Android 于 2013-10-15 10:25 编辑 ] |