WM6.0 USBToPC 添加存储卡检测功能开发备忘

2008.12.22 USBTOPC 开发备忘

Windows Embedded CE uses device interface notification to alert applications, services, and device drivers to the appearance and disappearance of device interfaces. It is the Windows Embedded CE equivalent to the Plug and Play event system on Windows-based desktop platforms.


(1)添加存储卡检测功能。
在没有插入存储卡时不能切换至“USB大容量存储器”选项,
会以文本形式在选项的下方提示用户插入存储卡。

(2)

(3)总论:在SD Memory Card总线上建立消息队列,接收设备通知(Notification),
插入拔出存储卡时,会有通知发送到消息队列中。

UINT CardDetect(LPVOID pParam)  
{
    GUID card_guid;    // or any known and relevant device interface GUID
    HANDLE hq, hn;
    HRESULT hr;
    MSGQUEUEOPTIONS msgopts;
    MYDEV detail;
    DWORD flags;
    DWORD size;

    // Parse the GUID
    hr = CLSIDFromString(CARD_GUID, &card_guid);
   
    msgopts.dwSize = sizeof(MSGQUEUEOPTIONS);
    msgopts.dwFlags = 0;
    msgopts.dwMaxMessages = 0;
    msgopts.cbMaxMessage = sizeof(MYDEV);
    msgopts.bReadAccess = TRUE;

    hq = CreateMsgQueue(NULL, &msgopts);
    if(hq == NULL) return 0;

    hn = RequestDeviceNotifications(&card_guid, hq, TRUE);
    if(hn == NULL) return 0;

    //-----------------------初始检测存储卡是否存在----------------------------------------------------
    //read and neglect the first message.
    ReadMsgQueue(hq, &detail, sizeof(detail), &size, 1, &flags);

    //The second msg can tell if there is sd card.
    if(ReadMsgQueue(hq, &detail, sizeof(detail), &size, 1, &flags) == TRUE)
    {
        // Trace(L"Device notification: %S,%s,f=0x%x/n", detail.d.szName,detail.d.fAttached ? L"appeared" : L"was removed", flags);
        g_bCardInserted = TRUE;
        //    Trace(L"card exist!");
    }
    else
    {
        g_bCardInserted = FALSE;
        //    Trace(L"There is no card!");
    }
    //------------------------------------------------------------------------------------

    //开一个新线程来在后台监视存储卡的插入拔出情况
    while(g_bThreadExit == FALSE)
    {
        if(WaitForSingleObject(hq, 50) == WAIT_OBJECT_0)//最多50ms超时退出检测一次g_bThreadExit
        {
            if(ReadMsgQueue(hq, &detail, sizeof(detail), &size, 1, &flags) == TRUE)
            {
                g_bCardInserted = detail.d.fAttached ? TRUE:FALSE;
                //        Trace(L"Card %s/n",g_bCardInserted ? L"inserted" : L"was removed");
            }
        }
    }

    //结束通知
    if(hn != NULL)
        StopDeviceNotifications(hn);
    //结束消息队列
    if(hq != NULL)
        CloseMsgQueue(hq);

    return 1;
}
通过GUID来注册通知,
从注册表HKEY_LOCAL_MACHINE/Drivers/SDCARD/ClientDrivers/Class/MMC_Class/IClass获取GUID号。


(4)开辟了专门的线程来检测卡的拔插情况。
AfxBeginThread(CardDetect,NULL);

这里CardDetect函数似乎不能作为类成员,最好作为全局函数来处理。
而且,AfxBeginThread要求其第一个参数必须有UINT funcname(LPVOID pParam)的签名格式,否则会报错。

线程的退出是通过一个全局变量g_bThreadExit 来做信号的
while(g_bThreadExit == FALSE)
{
    if(WaitForSingleObject(hq, 50) == WAIT_OBJECT_0)//最多50ms超时退出检测一次g_bThreadExit
    {
        if(ReadMsgQueue(hq, &detail, sizeof(detail), &size, 1, &flags) == TRUE)
        {
            g_bCardInserted = detail.d.fAttached ? TRUE:FALSE;

        }
    }
}

(5)实践表明,在RequestDeviceNotifications注册通知时必然会产生一个attatch,如果此时有sd卡存在,
还会产生另一个attach。即,如果有sd卡插入,则注册通知时会在消息队列里收到两条通知,如果没有sd卡插入,
则会有一条。所以,在检测时,应忽略掉第一次ReadMsgQueue,根据第二次ReadMsgQueue的结果来判断
初始时有无sd卡。

(6)
        CWnd *pWnd = GetDlgItem(IDC_STATIC2);
        pWnd->ShowWindow(SW_SHOWNORMAL);//刚开始时用的是SW_SHOW,报错,SW_HIDE为隐藏

        CButton* m_check1 = (CButton*)GetDlgItem(IDC_CHECK1);
        m_check1->EnableWindow(FALSE);//置灰使不可用

(7)    //由GUID号转换成GUID类型
    #define CARD_GUID L"{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
    GUID card_guid;
    // Parse the GUID
    hr = CLSIDFromString(CARD_GUID, &card_guid);

(8)在开发时需要加
BOOL g_bThreadExit;//是否退出线程
BOOL g_bCardInserted;//是否有sd卡插入设备
两个变量,一开始是直接添加到头文件中,后来报重复定义的错误,即使加了#ifdef也无用。
最终解决方案是将其定义在cpp文件中,在头文件里
extern BOOL g_bThreadExit;
extern BOOL g_bCardInserted;
总结:在头文件中只声明,不要进行变量定义。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值