3517|2

854

帖子

0

TA的资源

五彩晶圆(中级)

楼主
 

WINCE USB客户端驱动切换 [复制链接]

原文地址:http://blog.csdn.net/cenewman/article/details/6822173

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

//evc code:

//#include "usbfnioctl.h"
//#include

#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);
}

最新回复

谢谢分享   详情 回复 发表于 2021-3-20 16:47
点赞 关注
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460

回复
举报

854

帖子

0

TA的资源

五彩晶圆(中级)

沙发
 
  1. // to avoid the system error "Comunicatoin Error", disable the flowing setting:
  2.    if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("ControlPanel\\Comm"), 0, 0, &hKey))
  3.    {
  4.     dwSize = sizeof(DWORD);
  5.     dwValue = 0;
  6.     RegSetValueEx(hKey, TEXT("AutoCnct"), 0, REG_DWORD, (LPBYTE)&dwValue, dwSize);
  7.     RegCloseKey(hKey);
  8.    }
复制代码
这个代码是很多人容易忽视的。
 
个人签名如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
 

回复

661

帖子

0

TA的资源

纯净的硅(初级)

板凳
 

谢谢分享

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表