Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force winCE to see SD/MMC card after startup

Tags:

c#

windows-ce

I am working on the software for a new instrument that interacts with some scientific equipment. The user interface is via Windows CE pocket PC (Windows CE 600 V3.01 Build 195). The instrument is setup with one end of a flex cable always plugged into the SD card slot on the PC. The cable runs into the instrument, and the other end plugs into a mounted SD card when it is present. The SD card contains a chip for use with the instrument, as well as software/firmware updates as needed and a data file pertaining to the chip. I have a c# software application that is run when WinCE boots. This application checks for the presence of the SDMMC card as it depends on data related to the accompanying chip for certain functionality.

My problem: If the SD card is inserted into the other end of the flex cable when WinCE boots, winCE detects the card's presence and the \SDMMC folder is created allowing software to read the data. If only the flex cable is plugged in, but the SDMMC card is NOT present at the other end, Windows does not create the folder. This I expect. But our field engineers will swap the card in and out for various reasons to replace the chip while the software is active. This is a problem if windows is booted before the card is inserted. Because of the flex cable, WinCE never detects that the card has been inserted. It also never detects that it was removed.

The software polls the SD card every 5 seconds. The firmware can tell via the setting of bits if the card is inserted, and it relays this info to software. If the card had previously been absent, is now detected, but the \SDMMC folder is not present, I'd like software to trigger WinCE to attempt detection again. I thought about using registry values but am not clear the presense of the HKEY_LOCAL_MACHINE SDMMc value can be written. I"m also not quite sure what the values mean. Can these be reset? I see the Storage Manager Registry would define this as below:

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

Is there someway to read/write this registry to poke winCE to see that a card has been inserted at the other end of the cable? AM I totally off base with this thought? Is there some other way to do this?

I apologize for the long question. I generally play at the application level. Googling this issue has not given me the answers I need, though perhaps I don't know enough to ask the right questions. Thanks for any help you can give me.

UPDATE: I'm still trying to find a resolution to this problem. My current thought is to force Windows CE to re-enumerate the device when my instrument firmware detects the card has been inserted. MY code polls firmware to receive notice of this in my c# application. For my instrument/application the SD Card is always in "Dsk2:". When the c# application receives notice the SD Card has been inserted it calls a method that does the following:

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

IN the above, the CreateFile() call fails with error 55: "The Specified network resource or device is no longer available".

MY questions: Is what I'm trying to do reasonable to re-enumerate the device? Does the CreateFile error indicate I should make an ActivateDevice() call instead? I see an example here: Problems getting a device driver to load at startup - WM6.1 of someone calling ActivateDevice() from c# code and wonder if that would take care of the problem of getting WIndows CE to recognize that an SD card is now inserted. Can anyone help me understand what parameters to send to window's ActivateDevice() command? Am I offbase with this approach?

This is all new territory for me and I appreciate any help you can provide. Thanks.

like image 302
lynnj Avatar asked Dec 27 '12 17:12

lynnj


1 Answers

For anyone interested, here is the code that fixed the problem. This method is called when the firmware detects the SD card has either been inserted or deleted after power up. In essence, it unloads/loads the device driver:

[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
like image 78
lynnj Avatar answered Sep 21 '22 05:09

lynnj