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

时间:2012-12-27 17:46:20

标签: c# windows-ce

我正在开发一种与某些科学设备相互作用的新仪器的软件。用户界面是通过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值的存在。我也不太确定这些值是什么意思。这些可以重置吗?我看到存储管理器注册表会将其定义如下:

[HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\SDMMC] 
"Name"="SD MMC device"
"Folder"="SD Card

有没有办法读/写这个注册表来戳你的winCE,看看有没有插入一根卡在电缆的另一端?我完全偏离了这个想法吗?还有其他方法可以做到这一点吗?

我为这个长期问题道歉。我通常在应用程序级别玩。谷歌搜索这个问题并没有给我我需要的答案,尽管我可能不太了解问题。谢谢你能给我的任何帮助。

更新:我仍在尝试找到解决此问题的方法。我目前的想法是当仪器固件检测到插入卡时强制Windows CE重新枚举设备。我的代码轮询固件以在我的c#应用程序中接收此通知。对于我的乐器/应用程序,SD卡始终位于“Dsk2:”中。当c#应用程序收到通知已插入SD卡时,它会调用执行以下操作的方法:

CODE

     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()调用?我在这里看到一个例子:Problems getting a device driver to load at startup - WM6.1某人从c#代码调用ActivateDevice()并想知道是否会解决让WIndows CE识别出现在插入了SD卡的问题。谁能帮我理解发送到窗口的ActivateDevice()命令的参数?我是这种方法的基础吗?

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

3 个答案:

答案 0 :(得分:0)

让我们看一下功能正常的系统中的事件顺序。

  1. 设备启动并加载SD / MMC驱动程序
  2. 将卡插入卡槽
  3. 发生硬件中断(可能是电源检测,可能是数据 - 这取决于OEM)
  4. 中断处理程序通知SDMMC驱动程序存在卡
  5. 驱动程序查询卡片类型
  6. 加载(或存储时通知)正确的功能驱动程序(存储等)
  7. 功能驱动程序将硬件暴露给操作系统和应用程序
  8. 问题在于,如果卡已经在插槽中,则#3在启动时不会正常发生。这在SD或USB的平台开发中并不罕见 - 在插槽通电之前,中断处理程序必须正常工作并取消屏蔽。

    为此创建软件解决方法非常困难,特别是如果OAL(由硬件制造商开发的操作系统部分,而不是Microsoft)是黑盒子。我认为就是这种情况。

    要清楚,这绝对是一个平台错误。第一步应该是与设备OEM的支持小组讨论,告诉他们他们有一个bug,看看你是否可以让他们修复它。

    如果失败了(如果你没有购买很多设备,或者设备已经老了,获得支持就是挑战)那么我建议深入研究平台SDMMC驱动程序以查看是否有任何方法进入过程的中间。我从来没有尝试过(我一直在OEM方面,只修复了驱动程序或平台代码),所以我不确定是否有解决方案,但值得一看。

    如果您下载并安装Platform Builder的评估版,则可免费获得源代码(请务必选择“安装源”选项)。这都是C,尝试浏览并不是很有趣,但俗话说“使用来源,卢克。”

答案 1 :(得分:0)

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

c# FindFirstDevice Marshaling

我能够通过使用“SDH1”作为识别设备的字符串调用FindFirstDevice(),然后调用DeactivateDevice()/ ActivateDeviceEX()来实现此功能。如果有人对特定代码感兴趣,我可以稍后发布(我现在在家,代码在我的工作笔记本电脑上)。

答案 2 :(得分:0)

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

[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