6

我正在为与一些科学设备交互的新仪器开发软件。用户界面是通过 Windows CE 掌上电脑(Windows CE 600 V3.01 Build 195)。仪器设置为始终将柔性电缆的一端插入 PC 上的 SD 卡插槽。电缆插入仪器,另一端插入已安装的 SD 卡(如果存在)。SD 卡包含一个用于仪器的芯片,以及所需的软件/固件更新和与该芯片相关的数据文件。我有在 WinCE 启动时运行的 ac# 软件应用程序。此应用程序检查是否存在 SDMMC 卡,因为它依赖于与随附芯片相关的数据来实现某些功能。

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

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

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

有没有办法读/写这个注册表来戳winCE看看卡已经插在电缆的另一端?我完全不同意这个想法吗?还有其他方法可以做到这一点吗?

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

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

代码

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

/代码

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

我的问题:我试图重新枚举设备是否合理?CreateFile 错误是否表明我应该进行 ActivateDevice() 调用?我在这里看到一个例子: Problems getting a device driver to load at startup - WM6.1 of someone calls ActivateDevice() from c# code 并想知道这是否会解决让 WIndows CE 识别 SD 卡现在的问题插入。谁能帮我理解要发送到窗口的 ActivateDevice() 命令的参数?我用这种方法离谱吗?

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

4

3 回答 3

2

对于任何感兴趣的人,这里是解决问题的代码。当固件检测到 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
于 2013-01-21T19:19:13.327 回答
1

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

c# FindFirstDevice 编组

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

于 2013-01-20T23:32:40.790 回答
0

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

  1. 设备启动并加载 SD/MMC 驱动程序
  2. 卡已插入卡槽
  3. 发生硬件中断(可能是电源检测,可能是数据 - 这取决于 OEM)
  4. 中断处理程序通知 SDMMC 驱动程序存在卡
  5. 驱动查询卡类型
  6. 加载正确的功能驱动程序(存储等)(或在存储的情况下通知)
  7. 功能驱动程序的工作是将硬件暴露给操作系统和应用程序

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

很难为此创建软件解决方法,特别是如果 OAL(由硬件制造商而非 Microsoft 开发的操作系统的一部分)是一个黑匣子。我认为它是在这种情况下。

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

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

如果您下载并安装 Platform Builder 的评估版,源代码是免费的(请务必选择“安装源”选项)。都是C,尝试浏览并没有什么好玩的,但俗话说,“使用源代码,卢克。”

于 2013-01-03T14:41:58.213 回答