WINCE USB客户端驱动切换

        今天遇到一个比较特殊的客户要求,需要应用程序可以控制USB从设备,只有在应用程序使能之后,用户才能连接到电脑,说是怕用户随意拷贝或者破坏设备里存储的资料,当然界面是封装的,可不能避免用户通过连接电脑进行拷贝等操作。目前设备连接电脑有两种方式,同步方式(Active Sync)和U盘模式(Mass Storage)。当初想着从USB设备是通过ENT2外部中断来获取连接线状态,到时把这个中断消息在系统中广播,应用程序接收后可通过事件的方式来控制连接与否,从而达到控制的目标,于是答应了客户说可以做到。可到了要修改时才发现,这个外部中断的作用只是用来切断USB连接,即使是把这个中断的电路去掉,插入USB照样连接到电脑,只是拨掉USB线后电脑已经检测到断开连接,设备因为无法检测,依然的连接中而已。最终才发现这个USB连接中断是通过硬件检测数据线(D+、D-)的电平来实现,哎~。真的没有办法实现了吗?突然灵光一闪,把客户驱动切换到RNDIS模式,而这个模式我们设备中并没有加载这个驱动,设备就不能连接到电脑了。于是写了一个应用程序尝试控制,可以得到想要的效果,于是记录于下:

//evc code:

//#include "usbfnioctl.h"
//#include <svsutil.hxx>

#include "winioctl.h"
#define _UFN_ACCESS_CTL_CODE(_Function)  \
    CTL_CODE(FILE_DEVICE_UNKNOWN, _Function, METHOD_BUFFERED, FILE_ANY_ACCESS)

#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;
#define SVSUTIL_GUID_FORMAT_W   L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
#define SVSUTIL_GUID_FORMAT     SVSUTIL_GUID_FORMAT_W
#define SVSUTIL_PGUID_ELEMENTS(p) \
    p->Data1,                 p->Data2,    p->Data3,\
    p->Data4[0], p->Data4[1], p->Data4[2], p->Data4[3],\
    p->Data4[4], p->Data4[5], p->Data4[6], p->Data4[7]

#define IOCTL_UFN_CHANGE_CURRENT_CLIENT             _UFN_ACCESS_CTL_CODE(4)


#define USB_RNDIS  0 //Note that X11 don't support this client mode
#define USB_Serial 1
#define USB_MSF    2
UINT GetClientMode()
{
 UINT ret = USB_MSF; // USB_MSF is default class
 DWORD dwType = REG_SZ;
 HKEY hkDevice = NULL;
 HKEY hKey = NULL;
 DWORD dwTmp;
 WCHAR Data[20];
 DWORD cbData;
 cbData = sizeof( Data );

 dwTmp = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Drivers\\USB\\FunctionDrivers"), 0, 0, &hKey );

 if( dwTmp == ERROR_SUCCESS )
 {
  dwTmp = RegQueryValueEx( hKey, TEXT("DefaultClientDriver"), NULL, &dwType, (LPBYTE)Data, &cbData );
  if( dwTmp == ERROR_SUCCESS && dwType == REG_SZ )
  {
   if( wcscmp(Data, TEXT("RNDIS")) == 0 )
   {
    //USB RNDIS Function Class Enabled
    ret = USB_RNDIS;
   }
   else if( wcscmp(Data, TEXT("Serial_Class")) == 0 )
   {
    //USB Serial Function Class Enabled
    ret = USB_Serial;
   }
   else if( wcscmp(Data, TEXT("Mass_Storage_Class")) == 0 )
   {
    //USB MSF Function Class Enabled
    ret = USB_MSF;
   }
  }

  RegCloseKey( hKey );
 }
 return ret;
}

 

BOOL SetClientMode(UINT mode)
{
 BOOL dwRet = TRUE;
 UFN_CLIENT_NAME uClientName;
 int  iErr;
 HANDLE hUfn = NULL;
 HANDLE hf;
 BYTE bGuidBuffer[sizeof(GUID) + 4];
 LPGUID pGuidBus;
 LPCTSTR pszBusGuid = _T("E2BDC372-598F-4619-BC50-54B3F7848D35");
 DEVMGR_DEVICE_INFORMATION devInfo;

 LPCTSTR szNewDriverName = NULL;
 static const TCHAR c_szRndisFnName[]       = TEXT("RNDIS");
 static const TCHAR c_szUsbSerialFnName[]   = TEXT("Serial_Class");
 static const TCHAR c_szMassStorageFnName[] = TEXT("Mass_Storage_Class");

 HKEY hKey;
    DWORD dwSize, dwValue;
 TCHAR strValue[MAX_PATH] = {0};

 // save to registry
 if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Drivers\\USB\\FunctionDrivers"), 0, 0, &hKey))
 {
  switch(mode)
  {
  case USB_RNDIS:
   dwSize = (wcslen( c_szRndisFnName)+1)*sizeof(WCHAR);
   RegSetValueEx(hKey, TEXT("DefaultClientDriver"), NULL, REG_SZ, (BYTE *)c_szRndisFnName, dwSize);
   szNewDriverName = c_szRndisFnName;
   RegCloseKey(hKey); 

   // to avoid the system error "Comunicatoin Error", disable the flowing setting:
   if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("ControlPanel\\Comm"), 0, 0, &hKey))
   {
    dwSize = sizeof(DWORD);
    dwValue = 0;
    RegSetValueEx(hKey, TEXT("AutoCnct"), 0, REG_DWORD, (LPBYTE)&dwValue, dwSize);
    RegCloseKey(hKey); 
   }
  break;
  case USB_Serial:
   dwSize = (wcslen( c_szUsbSerialFnName)+1)*sizeof(WCHAR);
   RegSetValueEx(hKey, TEXT("DefaultClientDriver"), NULL, REG_SZ, (BYTE *)c_szUsbSerialFnName, dwSize);
   szNewDriverName = c_szUsbSerialFnName;
   RegCloseKey(hKey); 

   // to avoid the system error "Comunicatoin Error", disable the flowing setting, and now reset it
   if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("ControlPanel\\Comm"), 0, 0, &hKey))
   {
    dwSize = sizeof(DWORD);
    dwValue = 1;
    RegSetValueEx(hKey, TEXT("AutoCnct"), 0, REG_DWORD, (LPBYTE)&dwValue, dwSize);
    RegCloseKey(hKey); 
   }
  break;
  case USB_MSF:
   dwSize = (wcslen( c_szMassStorageFnName)+1)*sizeof(WCHAR);
   RegSetValueEx(hKey, TEXT("DefaultClientDriver"), NULL, REG_SZ, (BYTE *)c_szMassStorageFnName, dwSize);
   szNewDriverName = c_szMassStorageFnName;
   RegCloseKey(hKey); 

   // to avoid the system error "Comunicatoin Error", disable the flowing setting:
   if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("ControlPanel\\Comm"), 0, 0, &hKey))
   {
    dwSize = sizeof(DWORD);
    dwValue = 0;
    RegSetValueEx(hKey, TEXT("AutoCnct"), 0, REG_DWORD, (LPBYTE)&dwValue, dwSize);
    RegCloseKey(hKey); 
   }
  break;
  }
 }
 
 // Change mode
 // Parse the GUID
 pGuidBus = (LPGUID)bGuidBuffer;
 iErr = _stscanf(pszBusGuid, SVSUTIL_GUID_FORMAT, SVSUTIL_PGUID_ELEMENTS(&pGuidBus));
 if (iErr == 0 || iErr == EOF)
 {
  return FALSE;
 }

 // Get a handle to the bus driver
 memset(&devInfo, 0, sizeof(devInfo));
 devInfo.dwSize = sizeof(devInfo);
 hf = FindFirstDevice(DeviceSearchByGuid, pGuidBus, &devInfo);
 if (hf != INVALID_HANDLE_VALUE)
 {
  hUfn = CreateFile(devInfo.szBusName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  if( hUfn != INVALID_HANDLE_VALUE)
  {
   _tcscpy(uClientName.szName, szNewDriverName);
   dwRet = DeviceIoControl(hUfn, IOCTL_UFN_CHANGE_CURRENT_CLIENT, &uClientName, sizeof(uClientName), NULL, 0, NULL, NULL);
   
   CloseHandle(hUfn);
  }
  CloseHandle(hf);
 }

 return dwRet;
}


BOOL CClientModeDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // Set the icon for this dialog.  The framework does this automatically
 //  when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE);   // Set big icon
 SetIcon(m_hIcon, FALSE);  // Set small icon
 
 CenterWindow(GetDesktopWindow()); // center to the hpc screen

 // TODO: Add extra initialization here
 m_nClient = (int)GetClientMode();//m_nClient 是一个COMBO_BOX变量
 m_strStatus = TEXT("Ready.");
 UpdateData(FALSE);
 return TRUE;  // return TRUE  unless you set the focus to a control
}

 

void CClientModeDlg::OnButtonSwitch()
{
 // TODO: Add your control notification handler code here
 UpdateData();
 SetClientMode(m_nClient);
 switch(m_nClient)
 {
 case USB_RNDIS:
  m_strStatus.Format(TEXT("Client Mode: RNDIS"));
  break;
 case USB_Serial:
  m_strStatus.Format(TEXT("Client Mode: Serial"));
  break;
 case USB_MSF:
  m_strStatus.Format(TEXT("Client Mode: Mass Storage"));
  break;
 }
 UpdateData(FALSE);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值