首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何强制winCE在启动后看到SD/MMC卡

如何强制winCE在启动后看到SD/MMC卡
EN

Stack Overflow用户
提问于 2012-12-28 01:46:20
回答 3查看 5K关注 0票数 5

我正在为一种可以与一些科学设备交互的新仪器开发软件。用户界面通过Windows CE pocket PC (Windows CE 600 V3.01 Build 195)实现。仪器设置时,软线的一端总是插入PC上的SD卡插槽。电缆插入仪器,另一端插入已安装的SD卡。SD卡包含与仪器一起使用的芯片,以及所需的软件/固件更新和与芯片相关的数据文件。我有一个在WinCE引导时运行的c#软件应用程序。此应用程序检查SDMMC卡的存在,因为它依赖于与附带芯片相关的数据来实现某些功能。

我的问题是:如果在WinCE启动时将SD卡插入flex电缆的另一端,winCE会检测到该卡的存在,并创建\SDMMC文件夹以允许软件读取数据。如果只插入了软电缆,但另一端没有SDMMC卡,则Windows不会创建该文件夹。这是我所期望的。但我们的现场工程师会出于各种原因更换卡,以便在软件处于活动状态时更换芯片。如果在插入卡之前启动windows,这将是一个问题。由于使用了软电缆,WinCE永远不会检测到卡已插入。它也永远不会检测到它被删除了。

该软件每5秒轮询SD卡一次。固件可以通过设置位来判断是否插入了卡,并将此信息转发给软件。如果卡以前不存在,现在检测到,但\SDMMC文件夹不存在,我希望软件触发WinCE再次尝试检测。我考虑过使用注册表值,但不清楚是否可以写入HKEY_LOCAL_MACHINE SDMMc值。我也不太确定这些值是什么意思。这些值可以重置吗?我看到Storage Manager Registry会这样定义:

代码语言:javascript
复制
[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMMC] 
"Name"="SD MMC device"
"Folder"="SD Card

是否可以通过读/写此注册表的方式来戳winCE,以查看电缆另一端是否已插入卡?我的这种想法是完全错误的吗?有没有其他方法可以做到这一点?

我为这个冗长的问题道歉。我通常在应用程序级别进行游戏。在谷歌上搜索这个问题并没有给出我需要的答案,尽管我可能不知道足够多的知识来提出正确的问题。谢谢你能给我的任何帮助。

更新:我仍在努力寻找解决这个问题的方法。我目前的想法是,当仪器固件检测到卡已插入时,强制Windows CE重新枚举设备。我的代码轮询固件,以便在我的c#应用程序中收到这方面的通知。对于我的仪器/应用程序,SD卡始终为"Dsk2:“。当c#应用程序收到SD卡已插入的通知时,它将调用一个方法,该方法执行以下操作:

代码

代码语言:javascript
复制
     hDevice = CreateFile("\\Dsk2:", (0x80000000) | (0x40000000), 0,
        IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

     if (hDevice == INVALID_HANDLE_VALUE)
     {
        int hDeviceError = Marshal.GetLastWin32Error();
        // THis is an error - call GetLastERror to find
        // out what happened.
        using (StreamWriter bw = new StreamWriter(File.Open(App.chipDebugFile, FileMode.Append)))
        {
           String iua = "DevDriverInterface: error from CreateFile: " + hDeviceError.ToString();
           bw.WriteLine(iua);
        }
        return false;
     }

     bResult = DeviceIoControl(hDevice,
        IOCTL_DISK_UPDATE_PROPERTIES, 
        null,
        0,
        null,
        0,
        ref nBytesReturned,
        nOverLapped);

/CODE

在上面的代码中,CreateFile()调用失败并返回错误55:“指定的网络资源或设备不再可用”。

我的问题是:为了重新枚举设备,我尝试做的事情是否合理?CreateFile错误是否表明我应该改为调用ActivateDevice()?我在这里看到了一个示例:某个人从c#代码调用ActivateDevice()的Problems getting a device driver to load at startup - WM6.1,不知道这是否可以解决让WIndows CE识别现在插入的SD卡的问题。有没有人能帮我理解一下要发送给window的ActivateDevice()命令的参数是什么?我使用这种方法是离谱的吗?

这对我来说是全新的领域,我很感谢你能提供的任何帮助。谢谢。

EN

回答 3

Stack Overflow用户

发布于 2013-01-21 07:32:41

这个问题在我在研华的同事的帮助下得到了解决。他们给我提供了一个小的c++可执行文件,它验证了加载/卸载设备驱动程序是否会触发wince来识别已经插入的SD卡。然后,我的问题变成了让它在我的c#应用程序中工作。在这个帖子的帮助下(我自己的帖子):

c# FindFirstDevice Marshaling

通过调用FindFirstDevice() (使用"SDH1“作为标识设备的字符串),然后调用DeactivateDevice()/ActivateDeviceEX(),我能够让它工作。如果任何人对特定的代码感兴趣,我可以稍后发布(我现在在家,代码在我的工作笔记本上)。

票数 1
EN

Stack Overflow用户

发布于 2013-01-22 03:19:13

对于任何感兴趣的人,这里是修复该问题的代码。当固件在通电后检测到SD卡已插入或已删除时,将调用此方法。本质上,它卸载/加载设备驱动程序:

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
 public struct DEVMGR_DEVICE_INFORMATION
 {
  public uint dwSize;
  public IntPtr hDevice;
  public IntPtr hParentDevice;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
  public string szLegacyName;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  public string szDeviceKey;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  public string szDeviceName;
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  public string szBusName;
}

public enum DeviceSearchType : int
{
  DeviceSearchByLegacyName = 0,
  DeviceSearchByDeviceName = 1,
  DeviceSearchByBusName = 2,
  DeviceSearchByGuid = 3,
  DeviceSearchByParent = 4
}
class DevDriverInterface
{
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  public struct SECURITY_ATTRIBUTES
  {
     public int nLength;
     public IntPtr lpSecurityDescriptor;
     public bool bInheritHandle;
  }

  [DllImport("coredll.dll", SetLastError = true)]
  public extern static int ActivateDeviceEx(string device, IntPtr regEnts,
     UInt32 cRegEnts, IntPtr devKey);

  [DllImport("coredll.dll", SetLastError = true)]
  public extern static bool DeactivateDevice(int handle);

  [DllImport("coredll.dll", SetLastError = true)]
  public static extern int FindFirstDevice(DeviceSearchType
  searchType, IntPtr searchParam, ref DEVMGR_DEVICE_INFORMATION pdi);

  // Constructor
  public DevDriverInterface() { }

  public bool MountSDCardDrive()
  {
     const int INVALID_HANDLE_VALUE = -1;

     string mRegPath1 = "";
     int handle = INVALID_HANDLE_VALUE;
     DeviceSearchType searchType = DeviceSearchType.DeviceSearchByDeviceName;

     DEVMGR_DEVICE_INFORMATION di = new DEVMGR_DEVICE_INFORMATION();
     di.dwSize = (uint)Marshal.SizeOf(typeof(DEVMGR_DEVICE_INFORMATION));

     String searchParamString = "SDH1";

     IntPtr searchParam = Marshal.StringToBSTR(searchParamString);

     handle = FindFirstDevice(searchType, searchParam, ref di);

     if (handle == INVALID_HANDLE_VALUE)
     {
        // Failure - print error
        int hFindFirstDeviceError = Marshal.GetLastWin32Error();
        using (StreamWriter bw = new StreamWriter(File.Open(App.chipDebugFile, 
            FileMode.Append)))
        {
           String iua = "DevDriverInterface: error from FindFirstDevice: " + 
                  hFindFirstDeviceError.ToString();
           bw.WriteLine(iua);
        }
        return false;
     }
     else
     {
        mRegPath1 = di.szDeviceKey;
        bool deactBool = DeactivateDevice((int) di.hDevice);
        if (deactBool == false)
        {
           using (StreamWriter bw = new StreamWriter(File.Open(App.chipDebugFile,
              FileMode.Append)))
           {
              String iua = "DevDriverInterface: DeactivateDevice: returned false -
                          FAILED";
              bw.WriteLine(iua);
           }
           return false;
        }

        Thread.Sleep(50);
        // Call ActiveDevice to setup the device driver
        handle = ActivateDeviceEx(mRegPath1, IntPtr.Zero, 0, IntPtr.Zero);
        if (handle == INVALID_HANDLE_VALUE)
        {
           // Failure - print error
           int hActivateDeviceError = Marshal.GetLastWin32Error();

           using (StreamWriter bw = new StreamWriter(File.Open(App.chipDebugFile, 
              FileMode.Append)))
           {
              String iua = "DevDriverInterface: error from ActivateDevice: " + 
                     hActivateDeviceError.ToString();
              bw.WriteLine(iua);
           }
           return false;
        }

     }

     return true;
  }

}; // end class
票数 1
EN

Stack Overflow用户

发布于 2013-01-03 22:41:58

让我们看看正常运行的系统中事件的顺序。

  1. 设备启动并加载SD/MMC驱动程序
  2. 卡插入卡槽
  3. 发生硬件中断(可能是电源检测,可能是数据-这取决于原始设备制造商)
  4. 中断处理程序通知SDMMC驱动程序卡存在<

>H19驱动程序查询卡类型

  1. 正确的功能驱动程序(存储等)已加载(或在存储的情况下被通知)
  2. 函数驱动程序执行其工作,将硬件暴露给操作系统和applications

你的问题是,如果卡已经在插槽中,那么#3在启动时不会正确发生。这在SD或USB平台开发中并不少见-在插槽通电之前,中断处理程序必须正常工作并取消屏蔽。

很难为此创建一个软件解决方案,特别是如果OAL (由硬件制造商开发的操作系统的一部分,而不是Microsoft)是一个黑盒。我假设在这种情况下是这样的。

需要说明的是,这绝对是一个平台错误。第一个行动应该是与设备OEM的支持小组交谈,告诉他们有一个bug,看看你是否能让他们修复它。

如果失败了(如果你买的设备不多,或者设备太旧,需要获得is....challenging支持),那么我建议深入研究平台SDMMC驱动程序,看看是否有任何方法可以进入这个过程。我从来没有尝试过(我一直在OEM这方面,只是修复了驱动程序或平台代码),所以我不确定是否有解决方案,但它值得一看。

如果您下载并安装Platform Builder的评估版本(请确保选择“安装源”选项),则可以免费获得源代码。这都是C语言,尝试浏览并不是很有趣,但正如俗话所说,“使用源代码,Luke。”

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14058885

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档