repo time

Dependencies:   mbed MAX14720 MAX30205 USBDevice

Committer:
darienf
Date:
Tue Apr 06 06:41:40 2021 +0000
Revision:
20:6d2af70c92ab
another repo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
darienf 20:6d2af70c92ab 1 using System;
darienf 20:6d2af70c92ab 2 using System.Collections;
darienf 20:6d2af70c92ab 3 using System.Threading;
darienf 20:6d2af70c92ab 4 using System.IO;
darienf 20:6d2af70c92ab 5 using System.Runtime.InteropServices;
darienf 20:6d2af70c92ab 6 using System.Windows.Forms;
darienf 20:6d2af70c92ab 7 using Microsoft.Win32.SafeHandles;
darienf 20:6d2af70c92ab 8
darienf 20:6d2af70c92ab 9 //------------------------------------------------------------------------------------------
darienf 20:6d2af70c92ab 10 // OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
darienf 20:6d2af70c92ab 11 // Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
darienf 20:6d2af70c92ab 12 // Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
darienf 20:6d2af70c92ab 13 // OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
darienf 20:6d2af70c92ab 14
darienf 20:6d2af70c92ab 15 // OS24EVK-59 moved class HID into namespace Maxim.MAX30101 instead of namespace HeartRateApp
darienf 20:6d2af70c92ab 16 namespace Maxim.MAX30101
darienf 20:6d2af70c92ab 17 {
darienf 20:6d2af70c92ab 18 #pragma warning disable 1574
darienf 20:6d2af70c92ab 19 /// <summary>
darienf 20:6d2af70c92ab 20 /// USB Human Interface Device functions to connect to EV kit without requiring a custom device driver
darienf 20:6d2af70c92ab 21 /// </summary>
darienf 20:6d2af70c92ab 22 #pragma warning restore 1574
darienf 20:6d2af70c92ab 23 public class HID
darienf 20:6d2af70c92ab 24 {
darienf 20:6d2af70c92ab 25 private IntPtr EventObject;
darienf 20:6d2af70c92ab 26 private System.Threading.NativeOverlapped managedOverlapped;
darienf 20:6d2af70c92ab 27 private IntPtr nonManagedOverlapped;
darienf 20:6d2af70c92ab 28 private IntPtr nonManagedBuffer;
darienf 20:6d2af70c92ab 29 public SafeFileHandle writeHandle;
darienf 20:6d2af70c92ab 30 public ArrayList writeHandleArray = new ArrayList();
darienf 20:6d2af70c92ab 31 public SafeFileHandle readHandle;
darienf 20:6d2af70c92ab 32 public ArrayList readHandleArray = new ArrayList();
darienf 20:6d2af70c92ab 33 public ArrayList desiredHIDPathNameArray = new ArrayList();
darienf 20:6d2af70c92ab 34 public String deviceID = System.String.Format("Vid_{0:x4}&Pid_{1:x4}", support.DEFAULT_VENDOR_ID, support.DEFAULT_PRODUCT_ID);
darienf 20:6d2af70c92ab 35
darienf 20:6d2af70c92ab 36 private bool explicit_report_id = true;
darienf 20:6d2af70c92ab 37 private const byte DEFAULT_REPORT_ID = 0;
darienf 20:6d2af70c92ab 38 private const byte SHORT_REPORT_ID = 1;
darienf 20:6d2af70c92ab 39 public const byte HID_REPORT_ID_1 = 1; // MAX30101 optical data, 3 bytes per channel, up to 3 channels per sample
darienf 20:6d2af70c92ab 40 public const byte HID_REPORT_ID_2 = 2; // LIS2DH accelerometer data, 2 bytes per channel, 3 channels per sample
darienf 20:6d2af70c92ab 41 public const byte HID_REPORT_ID_3 = 3; // reserved
darienf 20:6d2af70c92ab 42 private const byte USB_OVERFLOW = 8;
darienf 20:6d2af70c92ab 43 private const byte USB_WRITE_ERROR = 4;
darienf 20:6d2af70c92ab 44 private const byte USB_READ_ERROR = 2;
darienf 20:6d2af70c92ab 45 public const byte I2C_NACK_ERROR = 1;
darienf 20:6d2af70c92ab 46 private const byte API_FAIL = 0; //API functions return non-0 upon success, to easily denote 'true' for C programs
darienf 20:6d2af70c92ab 47 private const byte I2C_SUCCESS = 3; //we'll also use a non-0 value to denote success, since returning a '0' would lead to trouble when mixed with API's returns.
darienf 20:6d2af70c92ab 48 private const byte GP_SUCCESS = 3;
darienf 20:6d2af70c92ab 49 private const byte GP_FAIL = 0;
darienf 20:6d2af70c92ab 50 private const byte REPORT_SIZE = 64;
darienf 20:6d2af70c92ab 51
darienf 20:6d2af70c92ab 52 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] before FlushQueue()
darienf 20:6d2af70c92ab 53 // mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 54 // mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 55 public static Mutex mutexGuardIOBuf = new Mutex();
darienf 20:6d2af70c92ab 56 // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
darienf 20:6d2af70c92ab 57 public byte[] IOBuf = new byte[REPORT_SIZE];
darienf 20:6d2af70c92ab 58
darienf 20:6d2af70c92ab 59 private const int IOtimeout = 10000;
darienf 20:6d2af70c92ab 60
darienf 20:6d2af70c92ab 61 // API declarations relating to device management (SetupDixxx and
darienf 20:6d2af70c92ab 62 // RegisterDeviceNotification functions).
darienf 20:6d2af70c92ab 63
darienf 20:6d2af70c92ab 64 // from dbt.h
darienf 20:6d2af70c92ab 65
darienf 20:6d2af70c92ab 66 internal const Int32 DBT_DEVNODES_CHANGED = 7;
darienf 20:6d2af70c92ab 67 internal const Int32 DBT_DEVICEARRIVAL = 0X8000;
darienf 20:6d2af70c92ab 68 internal const Int32 DBT_DEVICEREMOVECOMPLETE = 0X8004;
darienf 20:6d2af70c92ab 69 internal const Int32 DBT_DEVTYP_DEVICEINTERFACE = 5;
darienf 20:6d2af70c92ab 70 internal const Int32 DBT_DEVTYP_HANDLE = 6;
darienf 20:6d2af70c92ab 71 internal const Int32 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4;
darienf 20:6d2af70c92ab 72 internal const Int32 DEVICE_NOTIFY_SERVICE_HANDLE = 1;
darienf 20:6d2af70c92ab 73 internal const Int32 DEVICE_NOTIFY_WINDOW_HANDLE = 0;
darienf 20:6d2af70c92ab 74 internal const Int32 WM_DEVICECHANGE = 0X219;
darienf 20:6d2af70c92ab 75 internal const Int32 SPDRP_HARDWAREID = 1;
darienf 20:6d2af70c92ab 76
darienf 20:6d2af70c92ab 77 // from setupapi.h
darienf 20:6d2af70c92ab 78
darienf 20:6d2af70c92ab 79 internal const Int32 DIGCF_PRESENT = 2;
darienf 20:6d2af70c92ab 80 internal const Int32 DIGCF_DEVICEINTERFACE = 0X10;
darienf 20:6d2af70c92ab 81
darienf 20:6d2af70c92ab 82 // Two declarations for the DEV_BROADCAST_DEVICEINTERFACE structure.
darienf 20:6d2af70c92ab 83
darienf 20:6d2af70c92ab 84 // Use this one in the call to RegisterDeviceNotification() and
darienf 20:6d2af70c92ab 85 // in checking dbch_devicetype in a DEV_BROADCAST_HDR structure:
darienf 20:6d2af70c92ab 86
darienf 20:6d2af70c92ab 87 [StructLayout(LayoutKind.Sequential)]
darienf 20:6d2af70c92ab 88 internal class DEV_BROADCAST_DEVICEINTERFACE
darienf 20:6d2af70c92ab 89 {
darienf 20:6d2af70c92ab 90 internal Int32 dbcc_size;
darienf 20:6d2af70c92ab 91 internal Int32 dbcc_devicetype;
darienf 20:6d2af70c92ab 92 internal Int32 dbcc_reserved;
darienf 20:6d2af70c92ab 93 internal Guid dbcc_classguid;
darienf 20:6d2af70c92ab 94 internal Int16 dbcc_name;
darienf 20:6d2af70c92ab 95 }
darienf 20:6d2af70c92ab 96
darienf 20:6d2af70c92ab 97 // Use this to read the dbcc_name String and classguid:
darienf 20:6d2af70c92ab 98
darienf 20:6d2af70c92ab 99 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
darienf 20:6d2af70c92ab 100 internal class DEV_BROADCAST_DEVICEINTERFACE_1
darienf 20:6d2af70c92ab 101 {
darienf 20:6d2af70c92ab 102 internal Int32 dbcc_size;
darienf 20:6d2af70c92ab 103 internal Int32 dbcc_devicetype;
darienf 20:6d2af70c92ab 104 internal Int32 dbcc_reserved;
darienf 20:6d2af70c92ab 105 [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)]
darienf 20:6d2af70c92ab 106 internal Byte[] dbcc_classguid;
darienf 20:6d2af70c92ab 107 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
darienf 20:6d2af70c92ab 108 internal Char[] dbcc_name;
darienf 20:6d2af70c92ab 109 }
darienf 20:6d2af70c92ab 110
darienf 20:6d2af70c92ab 111 [StructLayout(LayoutKind.Sequential)]
darienf 20:6d2af70c92ab 112 internal class DEV_BROADCAST_HDR
darienf 20:6d2af70c92ab 113 {
darienf 20:6d2af70c92ab 114 internal Int32 dbch_size;
darienf 20:6d2af70c92ab 115 internal Int32 dbch_devicetype;
darienf 20:6d2af70c92ab 116 internal Int32 dbch_reserved;
darienf 20:6d2af70c92ab 117 }
darienf 20:6d2af70c92ab 118
darienf 20:6d2af70c92ab 119 internal struct SP_DEVICE_INTERFACE_DATA
darienf 20:6d2af70c92ab 120 {
darienf 20:6d2af70c92ab 121 internal Int32 cbSize;
darienf 20:6d2af70c92ab 122 internal System.Guid InterfaceClassGuid;
darienf 20:6d2af70c92ab 123 internal Int32 Flags;
darienf 20:6d2af70c92ab 124 internal IntPtr Reserved;
darienf 20:6d2af70c92ab 125 }
darienf 20:6d2af70c92ab 126
darienf 20:6d2af70c92ab 127 //[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
darienf 20:6d2af70c92ab 128 //internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
darienf 20:6d2af70c92ab 129 //{
darienf 20:6d2af70c92ab 130 // internal Int32 cbSize;
darienf 20:6d2af70c92ab 131 // //internal String DevicePath;
darienf 20:6d2af70c92ab 132 // internal Char[] DevicePath;
darienf 20:6d2af70c92ab 133 //}
darienf 20:6d2af70c92ab 134
darienf 20:6d2af70c92ab 135 // warning CS0649: Field 'Maxim.MAX30101.HID.SP_DEVINFO_DATA.cbSize' is never assigned to, and will always have its default value 0
darienf 20:6d2af70c92ab 136 #pragma warning disable 0649
darienf 20:6d2af70c92ab 137 internal struct SP_DEVINFO_DATA
darienf 20:6d2af70c92ab 138 {
darienf 20:6d2af70c92ab 139 internal Int32 cbSize;
darienf 20:6d2af70c92ab 140 internal System.Guid ClassGuid;
darienf 20:6d2af70c92ab 141 internal Int32 DevInst;
darienf 20:6d2af70c92ab 142 internal Int32 Reserved;
darienf 20:6d2af70c92ab 143 }
darienf 20:6d2af70c92ab 144 #pragma warning restore 0649
darienf 20:6d2af70c92ab 145
darienf 20:6d2af70c92ab 146 //HDEVINFO SetupDiGetClassDevs(const GUID *ClassGuid, PCTSTR Enumerator, HWND hwndParent, DWORD Flags);
darienf 20:6d2af70c92ab 147 [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
darienf 20:6d2af70c92ab 148 internal static extern IntPtr SetupDiGetClassDevs(ref System.Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags);
darienf 20:6d2af70c92ab 149
darienf 20:6d2af70c92ab 150 //BOOL SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet);
darienf 20:6d2af70c92ab 151 [DllImport("setupapi.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 152 internal static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
darienf 20:6d2af70c92ab 153
darienf 20:6d2af70c92ab 154 //BOOL SetupDiEnumDeviceInterfaces(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, const GUID *InterfaceClassGuid, DWORD MemberIndex, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
darienf 20:6d2af70c92ab 155 [DllImport("setupapi.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 156 internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
darienf 20:6d2af70c92ab 157 [DllImport("setupapi.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 158 // required to pass DeviceInfoData=null
darienf 20:6d2af70c92ab 159 internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
darienf 20:6d2af70c92ab 160
darienf 20:6d2af70c92ab 161 //BOOL SetupDiGetDeviceInterfaceDetail(HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, DWORD DeviceInterfaceDetailDataSize, PDWORD RequiredSize, PSP_DEVINFO_DATA DeviceInfoData);
darienf 20:6d2af70c92ab 162 //[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
darienf 20:6d2af70c92ab 163 //internal extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData);
darienf 20:6d2af70c92ab 164 //[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
darienf 20:6d2af70c92ab 165 //// required to pass DeviceInfoData=null
darienf 20:6d2af70c92ab 166 //internal extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData);
darienf 20:6d2af70c92ab 167 // cannot get SP_DEVICE_INTERFACE_DETAIL_DATA's DevicePath field to work properly, so use IntPtr instead of ref SP_DEVICE_INTERFACE_DATA
darienf 20:6d2af70c92ab 168 [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
darienf 20:6d2af70c92ab 169 // required to pass DeviceInterfaceDetailData=null
darienf 20:6d2af70c92ab 170 internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData);
darienf 20:6d2af70c92ab 171 [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
darienf 20:6d2af70c92ab 172 // required to pass DeviceInterfaceDetailData=null, DeviceInfoData=null
darienf 20:6d2af70c92ab 173 internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData);
darienf 20:6d2af70c92ab 174
darienf 20:6d2af70c92ab 175 //BOOL SetupDiEnumDeviceInfo(HDEVINFO DeviceInfoSet, DWORD MemberIndex, PSP_DEVINFO_DATA DeviceInfoData);
darienf 20:6d2af70c92ab 176 [DllImport("setupapi.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 177 internal static extern Boolean SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, Int32 MemberIndex, ref SP_DEVINFO_DATA DevInfoData);
darienf 20:6d2af70c92ab 178
darienf 20:6d2af70c92ab 179 //BOOL SetupDiGetDeviceRegistryProperty(HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, DWORD Property, PDWORD PropertyRegDataType, PBYTE PropertyBuffer, DWORD PropertyBufferSize, PDWORD RequiredSize);
darienf 20:6d2af70c92ab 180 [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
darienf 20:6d2af70c92ab 181 internal static extern Boolean SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DevInfoData, Int32 Property, IntPtr PropertyRegDataType, IntPtr PropertyBuffer, Int32 PropertyBufferSize, ref Int32 RequiredSize);
darienf 20:6d2af70c92ab 182
darienf 20:6d2af70c92ab 183 [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
darienf 20:6d2af70c92ab 184 internal static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags);
darienf 20:6d2af70c92ab 185
darienf 20:6d2af70c92ab 186 [DllImport("user32.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 187 internal static extern Boolean UnregisterDeviceNotification(IntPtr Handle);
darienf 20:6d2af70c92ab 188
darienf 20:6d2af70c92ab 189 // API declarations for HID communications.
darienf 20:6d2af70c92ab 190
darienf 20:6d2af70c92ab 191 // from hidpi.h
darienf 20:6d2af70c92ab 192 // Typedef enum defines a set of integer constants for HidP_Report_Type
darienf 20:6d2af70c92ab 193
darienf 20:6d2af70c92ab 194 internal const Int16 HidP_Input = 0;
darienf 20:6d2af70c92ab 195 internal const Int16 HidP_Output = 1;
darienf 20:6d2af70c92ab 196 internal const Int16 HidP_Feature = 2;
darienf 20:6d2af70c92ab 197
darienf 20:6d2af70c92ab 198 [StructLayout(LayoutKind.Sequential)]
darienf 20:6d2af70c92ab 199 internal struct HIDD_ATTRIBUTES
darienf 20:6d2af70c92ab 200 {
darienf 20:6d2af70c92ab 201 internal Int32 Size;
darienf 20:6d2af70c92ab 202 internal UInt16 VendorID;
darienf 20:6d2af70c92ab 203 internal UInt16 ProductID;
darienf 20:6d2af70c92ab 204 internal UInt16 VersionNumber;
darienf 20:6d2af70c92ab 205 }
darienf 20:6d2af70c92ab 206
darienf 20:6d2af70c92ab 207 [DllImport("hid.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 208 internal static extern Boolean HidD_FlushQueue(SafeFileHandle HidDeviceObject);
darienf 20:6d2af70c92ab 209
darienf 20:6d2af70c92ab 210 [DllImport("hid.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 211 internal static extern Boolean HidD_GetAttributes(SafeFileHandle HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);
darienf 20:6d2af70c92ab 212
darienf 20:6d2af70c92ab 213 [DllImport("hid.dll", SetLastError = true)]
darienf 20:6d2af70c92ab 214 internal static extern void HidD_GetHidGuid(ref System.Guid HidGuid);
darienf 20:6d2af70c92ab 215
darienf 20:6d2af70c92ab 216 public void getHidGuid(ref System.Guid hidGuid)
darienf 20:6d2af70c92ab 217 {
darienf 20:6d2af70c92ab 218 DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 219 #if DEBUG
darienf 20:6d2af70c92ab 220 HidD_GetHidGuid(ref hidGuid);
darienf 20:6d2af70c92ab 221 #else
darienf 20:6d2af70c92ab 222 try
darienf 20:6d2af70c92ab 223 {
darienf 20:6d2af70c92ab 224 HidD_GetHidGuid(ref hidGuid);
darienf 20:6d2af70c92ab 225 }
darienf 20:6d2af70c92ab 226 catch (Exception ex)
darienf 20:6d2af70c92ab 227 {
darienf 20:6d2af70c92ab 228 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 229 }
darienf 20:6d2af70c92ab 230 #endif
darienf 20:6d2af70c92ab 231 DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 232 }
darienf 20:6d2af70c92ab 233
darienf 20:6d2af70c92ab 234 public string DebugMessage;
darienf 20:6d2af70c92ab 235 //public void TraceMessage(string message,
darienf 20:6d2af70c92ab 236 //[System.Runtime.CompilerServices.CallerMemberName] string memberName = "",
darienf 20:6d2af70c92ab 237 //[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "",
darienf 20:6d2af70c92ab 238 //[System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
darienf 20:6d2af70c92ab 239 //{
darienf 20:6d2af70c92ab 240 // Console.WriteLine("message: " + message);
darienf 20:6d2af70c92ab 241 // Console.WriteLine("member name: " + memberName);
darienf 20:6d2af70c92ab 242 // Console.WriteLine("source file path: " + sourceFilePath);
darienf 20:6d2af70c92ab 243 // Console.WriteLine("source line number: " + sourceLineNumber);
darienf 20:6d2af70c92ab 244 //}
darienf 20:6d2af70c92ab 245
darienf 20:6d2af70c92ab 246 /// <summary>
darienf 20:6d2af70c92ab 247 /// FindDesiredHIDPathNamesFromGuid() only appends to desiredHIDPathNameArray.
darienf 20:6d2af70c92ab 248 /// Desired HIDs that have been removed from the system are removed from desiredHIDPathNameArray in openHIDhandles
darienf 20:6d2af70c92ab 249 /// </summary>
darienf 20:6d2af70c92ab 250 /// <param name="myGuid"></param>
darienf 20:6d2af70c92ab 251 private void FindDesiredHIDPathNamesFromGuid(System.Guid myGuid)
darienf 20:6d2af70c92ab 252 {
darienf 20:6d2af70c92ab 253 DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 254 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 255 // But I never see this kind of exception thrown from within the C# GUI.
darienf 20:6d2af70c92ab 256 // HID.findHIDs() still raises the exception in Matlab,
darienf 20:6d2af70c92ab 257 // Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 258 //
darienf 20:6d2af70c92ab 259 // % Required: connect to MAX30101EVKIT hardware
darienf 20:6d2af70c92ab 260 // fprintf('Connecting to MAX30101EVKIT hardware...\n');
darienf 20:6d2af70c92ab 261 // for trial=0:2000
darienf 20:6d2af70c92ab 262 // try
darienf 20:6d2af70c92ab 263 // %pause(1) % delay at least 1 second
darienf 20:6d2af70c92ab 264 // myMAX30101.myHID.findHIDs();
darienf 20:6d2af70c92ab 265 // % Sometimes we get Error using MAX30101Example
darienf 20:6d2af70c92ab 266 // % If this happens, try clearing the workspace and run again.
darienf 20:6d2af70c92ab 267 // % Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 268 // % FindDesiredHIDPathNamesFromGuid
darienf 20:6d2af70c92ab 269 // % findHIDs
darienf 20:6d2af70c92ab 270 // % Source: MAX30101
darienf 20:6d2af70c92ab 271 // % HelpLink:
darienf 20:6d2af70c92ab 272 // if (myMAX30101.myHID.isConnected())
darienf 20:6d2af70c92ab 273 // break
darienf 20:6d2af70c92ab 274 // end
darienf 20:6d2af70c92ab 275 // catch me
darienf 20:6d2af70c92ab 276 // % disp(me)
darienf 20:6d2af70c92ab 277 // end
darienf 20:6d2af70c92ab 278 // end
darienf 20:6d2af70c92ab 279 //
darienf 20:6d2af70c92ab 280 // If matlab does successfully connect to USB, it is able to get
darienf 20:6d2af70c92ab 281 // streaming data through the PartialArrayIntAvailable event
darienf 20:6d2af70c92ab 282 // handler -- even though it can't understand
darienf 20:6d2af70c92ab 283 // System.Collections.ArrayList data, it does at least understand
darienf 20:6d2af70c92ab 284 // Array<System.Int32> or int[] data.
darienf 20:6d2af70c92ab 285 //
darienf 20:6d2af70c92ab 286 Int32 memberIndex = 0;
darienf 20:6d2af70c92ab 287 Int32 bufferSize = 0;
darienf 20:6d2af70c92ab 288 IntPtr deviceInfoSet = new System.IntPtr();
darienf 20:6d2af70c92ab 289 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
darienf 20:6d2af70c92ab 290 IntPtr deviceInterfaceDetailDataBuffer = IntPtr.Zero;
darienf 20:6d2af70c92ab 291
darienf 20:6d2af70c92ab 292 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 293 // diagnostic: trying to avoid "Arithmetic overflow" from matlab. Limit the number of HID devices to be checked.
darienf 20:6d2af70c92ab 294 const int memberIndexLimit = 100;
darienf 20:6d2af70c92ab 295
darienf 20:6d2af70c92ab 296 #if DEBUG
darienf 20:6d2af70c92ab 297 #else
darienf 20:6d2af70c92ab 298 try
darienf 20:6d2af70c92ab 299 {
darienf 20:6d2af70c92ab 300 #endif
darienf 20:6d2af70c92ab 301 DebugMessage = string.Format("{0} first deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 302 deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
darienf 20:6d2af70c92ab 303
darienf 20:6d2af70c92ab 304 memberIndex = 0;
darienf 20:6d2af70c92ab 305
darienf 20:6d2af70c92ab 306 // The cbSize element of the DeviceInterfaceData structure must be set to the structure's size in bytes.
darienf 20:6d2af70c92ab 307 // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
darienf 20:6d2af70c92ab 308 DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData);
darienf 20:6d2af70c92ab 309
darienf 20:6d2af70c92ab 310 while (memberIndex < memberIndexLimit)
darienf 20:6d2af70c92ab 311 {
darienf 20:6d2af70c92ab 312 // Begin with memberIndex = 0 and increment through the device information set until no more devices are available.
darienf 20:6d2af70c92ab 313 DebugMessage = string.Format("{0} memberIndex={1} first SetupDiEnumDeviceInterfaces ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 314 if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref DeviceInterfaceData))
darienf 20:6d2af70c92ab 315 {
darienf 20:6d2af70c92ab 316 break;
darienf 20:6d2af70c92ab 317 }
darienf 20:6d2af70c92ab 318
darienf 20:6d2af70c92ab 319 DebugMessage = string.Format("{0} memberIndex={1} first SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 320 SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
darienf 20:6d2af70c92ab 321 //tempLastError = GetLastError();
darienf 20:6d2af70c92ab 322 //if (tempLastError != ERROR_INSUFFICIENT_BUFFER) // ERROR_INSUFFICIENT_BUFFER is expected on this first call
darienf 20:6d2af70c92ab 323 // break;
darienf 20:6d2af70c92ab 324 //FIXME add error check
darienf 20:6d2af70c92ab 325
darienf 20:6d2af70c92ab 326 // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
darienf 20:6d2af70c92ab 327 DebugMessage = string.Format("{0} memberIndex={1} Marshal.AllocHGlobal(bufferSize) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 328 deviceInterfaceDetailDataBuffer = Marshal.AllocHGlobal(bufferSize);
darienf 20:6d2af70c92ab 329 // Returns a System.IntPtr pointer to the newly allocated global heap memory.
darienf 20:6d2af70c92ab 330 // This memory must be released using the Marshal.FreeHGlobal method.
darienf 20:6d2af70c92ab 331 // Marshal.AllocHGlobal(numBytes) could throw OutOfMemoryException ?
darienf 20:6d2af70c92ab 332
darienf 20:6d2af70c92ab 333 // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
darienf 20:6d2af70c92ab 334 DebugMessage = string.Format("{0} memberIndex={1} Marshal.WriteInt32 ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 335 Marshal.WriteInt32(deviceInterfaceDetailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
darienf 20:6d2af70c92ab 336
darienf 20:6d2af70c92ab 337 // Call SetupDiGetDeviceInterfaceDetail again.
darienf 20:6d2af70c92ab 338 // This time, pass a pointer to DetailDataBuffer and the returned required buffer size.
darienf 20:6d2af70c92ab 339 DebugMessage = string.Format("{0} memberIndex={1} second SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 340 if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, deviceInterfaceDetailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero))
darienf 20:6d2af70c92ab 341 break;
darienf 20:6d2af70c92ab 342
darienf 20:6d2af70c92ab 343 // Skip over cbsize (4 bytes) to get the address of the devicePathName.
darienf 20:6d2af70c92ab 344 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
darienf 20:6d2af70c92ab 345 DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 346 IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4);
darienf 20:6d2af70c92ab 347 // DebugMessage = string.Format("{0} memberIndex={1} new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 348 // BAD CODE. IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4);
darienf 20:6d2af70c92ab 349 // BAD CODE. assumes the pointer is a 32-bit address, intermittently fails from 64-bit matlab client.
darienf 20:6d2af70c92ab 350
darienf 20:6d2af70c92ab 351 // Get the String containing the devicePathName.
darienf 20:6d2af70c92ab 352 DebugMessage = string.Format("{0} memberIndex={1} Marshal.PtrToStringAuto(pDevicePathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 353 string tempPathName = Marshal.PtrToStringAuto(pDevicePathName);
darienf 20:6d2af70c92ab 354
darienf 20:6d2af70c92ab 355 // match any device pathname that contains deviceID (case-insensitive match) "Vid_{0:x4}&Pid_{1:x4}"
darienf 20:6d2af70c92ab 356 DebugMessage = string.Format("{0} memberIndex={1} if (tempPathName.ToLower().IndexOf(deviceID.ToLower()) != -1) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 357 if (tempPathName.ToLower().IndexOf(deviceID.ToLower()) != -1)
darienf 20:6d2af70c92ab 358 {
darienf 20:6d2af70c92ab 359 DebugMessage = string.Format("{0} memberIndex={1} desiredHIDPathNameArray.Add(tempPathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 360 desiredHIDPathNameArray.Add(tempPathName);
darienf 20:6d2af70c92ab 361 }
darienf 20:6d2af70c92ab 362
darienf 20:6d2af70c92ab 363 DebugMessage = string.Format("{0} memberIndex={1} memberIndex = memberIndex + 1; ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 364
darienf 20:6d2af70c92ab 365 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
darienf 20:6d2af70c92ab 366 // why didn't they call Marshal.FreeHGlobal here, inside the while loop? Isn't this a memory leak?
darienf 20:6d2af70c92ab 367 // Free the memory allocated previously by AllocHGlobal.
darienf 20:6d2af70c92ab 368 if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
darienf 20:6d2af70c92ab 369 {
darienf 20:6d2af70c92ab 370 Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
darienf 20:6d2af70c92ab 371 deviceInterfaceDetailDataBuffer = IntPtr.Zero;
darienf 20:6d2af70c92ab 372 }
darienf 20:6d2af70c92ab 373
darienf 20:6d2af70c92ab 374 memberIndex = memberIndex + 1;
darienf 20:6d2af70c92ab 375 }
darienf 20:6d2af70c92ab 376 #if DEBUG
darienf 20:6d2af70c92ab 377 // Free the memory allocated previously by AllocHGlobal.
darienf 20:6d2af70c92ab 378 if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
darienf 20:6d2af70c92ab 379 Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
darienf 20:6d2af70c92ab 380
darienf 20:6d2af70c92ab 381 if (deviceInfoSet != IntPtr.Zero)
darienf 20:6d2af70c92ab 382 SetupDiDestroyDeviceInfoList(deviceInfoSet);
darienf 20:6d2af70c92ab 383 #else
darienf 20:6d2af70c92ab 384 }
darienf 20:6d2af70c92ab 385 catch (Exception ex)
darienf 20:6d2af70c92ab 386 {
darienf 20:6d2af70c92ab 387 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 388 }
darienf 20:6d2af70c92ab 389 finally
darienf 20:6d2af70c92ab 390 {
darienf 20:6d2af70c92ab 391 // Free the memory allocated previously by AllocHGlobal.
darienf 20:6d2af70c92ab 392 if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
darienf 20:6d2af70c92ab 393 Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
darienf 20:6d2af70c92ab 394
darienf 20:6d2af70c92ab 395 if (deviceInfoSet != IntPtr.Zero)
darienf 20:6d2af70c92ab 396 SetupDiDestroyDeviceInfoList(deviceInfoSet);
darienf 20:6d2af70c92ab 397 }
darienf 20:6d2af70c92ab 398 #endif
darienf 20:6d2af70c92ab 399 DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 400 }
darienf 20:6d2af70c92ab 401
darienf 20:6d2af70c92ab 402 private void FindAllHIDPathNamesFromGuid(System.Guid myGuid, ArrayList allHIDPathNameArray)
darienf 20:6d2af70c92ab 403 {
darienf 20:6d2af70c92ab 404 DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 405 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 406 // But I never see this kind of exception thrown from within the C# GUI.
darienf 20:6d2af70c92ab 407 // HID.findHIDs() still raises the exception in Matlab,
darienf 20:6d2af70c92ab 408 // Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 409 Int32 memberIndex = 0;
darienf 20:6d2af70c92ab 410 Int32 bufferSize = 0;
darienf 20:6d2af70c92ab 411 IntPtr deviceInfoSet = new System.IntPtr();
darienf 20:6d2af70c92ab 412 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
darienf 20:6d2af70c92ab 413 IntPtr deviceInterfaceDetailDataBuffer = IntPtr.Zero;
darienf 20:6d2af70c92ab 414
darienf 20:6d2af70c92ab 415 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 416 // diagnostic: trying to avoid "Arithmetic overflow" from matlab. Limit the number of HID devices to be checked.
darienf 20:6d2af70c92ab 417 const int memberIndexLimit = 100;
darienf 20:6d2af70c92ab 418
darienf 20:6d2af70c92ab 419
darienf 20:6d2af70c92ab 420 #if DEBUG
darienf 20:6d2af70c92ab 421 #else
darienf 20:6d2af70c92ab 422 try
darienf 20:6d2af70c92ab 423 {
darienf 20:6d2af70c92ab 424 #endif
darienf 20:6d2af70c92ab 425 DebugMessage = string.Format("{0} first deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 426 deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
darienf 20:6d2af70c92ab 427
darienf 20:6d2af70c92ab 428 memberIndex = 0;
darienf 20:6d2af70c92ab 429
darienf 20:6d2af70c92ab 430 // The cbSize element of the DeviceInterfaceData structure must be set to the structure's size in bytes.
darienf 20:6d2af70c92ab 431 // The size is 28 bytes for 32-bit code and 32 bits for 64-bit code.
darienf 20:6d2af70c92ab 432 DeviceInterfaceData.cbSize = Marshal.SizeOf(DeviceInterfaceData);
darienf 20:6d2af70c92ab 433
darienf 20:6d2af70c92ab 434 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 435 while (memberIndex < memberIndexLimit)
darienf 20:6d2af70c92ab 436 {
darienf 20:6d2af70c92ab 437 DebugMessage = string.Format("{0} memberIndex={1} first SetupDiEnumDeviceInterfaces ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 438 if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref DeviceInterfaceData))
darienf 20:6d2af70c92ab 439 {
darienf 20:6d2af70c92ab 440 break;
darienf 20:6d2af70c92ab 441 }
darienf 20:6d2af70c92ab 442
darienf 20:6d2af70c92ab 443 DebugMessage = string.Format("{0} memberIndex={1} first SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 444 SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
darienf 20:6d2af70c92ab 445
darienf 20:6d2af70c92ab 446 // Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
darienf 20:6d2af70c92ab 447 DebugMessage = string.Format("{0} memberIndex={1} Marshal.AllocHGlobal(bufferSize) ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 448 deviceInterfaceDetailDataBuffer = Marshal.AllocHGlobal(bufferSize);
darienf 20:6d2af70c92ab 449
darienf 20:6d2af70c92ab 450 // Store cbSize in the first bytes of the array. The number of bytes varies with 32- and 64-bit systems.
darienf 20:6d2af70c92ab 451 DebugMessage = string.Format("{0} memberIndex={1} Marshal.WriteInt32 ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 452 Marshal.WriteInt32(deviceInterfaceDetailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
darienf 20:6d2af70c92ab 453
darienf 20:6d2af70c92ab 454 // Call SetupDiGetDeviceInterfaceDetail again.
darienf 20:6d2af70c92ab 455 // This time, pass a pointer to deviceInterfaceDetailDataBuffer and the returned required buffer size.
darienf 20:6d2af70c92ab 456 DebugMessage = string.Format("{0} memberIndex={1} second SetupDiGetDeviceInterfaceDetail ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 457 if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref DeviceInterfaceData, deviceInterfaceDetailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero))
darienf 20:6d2af70c92ab 458 break;
darienf 20:6d2af70c92ab 459
darienf 20:6d2af70c92ab 460 // Skip over cbsize (4 bytes) to get the address of the devicePathName.
darienf 20:6d2af70c92ab 461 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
darienf 20:6d2af70c92ab 462 DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 463 // example: IntPtr right way to add an offset (portable to 64-bit clients)
darienf 20:6d2af70c92ab 464 IntPtr pDevicePathName = IntPtr.Add(deviceInterfaceDetailDataBuffer, 4);
darienf 20:6d2af70c92ab 465 // DebugMessage = string.Format("{0} memberIndex={1} IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 466 // BAD CODE. IntPtr pDevicePathName = new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4);
darienf 20:6d2af70c92ab 467 // BAD CODE. assumes the pointer is a 32-bit address, intermittently fails from 64-bit matlab client.
darienf 20:6d2af70c92ab 468
darienf 20:6d2af70c92ab 469 // Get the String containing the devicePathName.
darienf 20:6d2af70c92ab 470 DebugMessage = string.Format("{0} memberIndex={1} Marshal.PtrToStringAuto(pDevicePathName); ", System.Reflection.MethodInfo.GetCurrentMethod().Name, memberIndex);
darienf 20:6d2af70c92ab 471 allHIDPathNameArray.Add(Marshal.PtrToStringAuto(pDevicePathName));
darienf 20:6d2af70c92ab 472
darienf 20:6d2af70c92ab 473 // VERIFY: https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message
darienf 20:6d2af70c92ab 474 // why didn't they call Marshal.FreeHGlobal here, inside the while loop? Isn't this a memory leak?
darienf 20:6d2af70c92ab 475 // Free the memory allocated previously by AllocHGlobal.
darienf 20:6d2af70c92ab 476 if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
darienf 20:6d2af70c92ab 477 {
darienf 20:6d2af70c92ab 478 Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
darienf 20:6d2af70c92ab 479 deviceInterfaceDetailDataBuffer = IntPtr.Zero;
darienf 20:6d2af70c92ab 480 }
darienf 20:6d2af70c92ab 481
darienf 20:6d2af70c92ab 482 memberIndex = memberIndex + 1;
darienf 20:6d2af70c92ab 483 }
darienf 20:6d2af70c92ab 484 #if DEBUG
darienf 20:6d2af70c92ab 485 // Free the memory allocated previously by AllocHGlobal.
darienf 20:6d2af70c92ab 486 if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
darienf 20:6d2af70c92ab 487 Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
darienf 20:6d2af70c92ab 488
darienf 20:6d2af70c92ab 489 if (deviceInfoSet != IntPtr.Zero)
darienf 20:6d2af70c92ab 490 SetupDiDestroyDeviceInfoList(deviceInfoSet);
darienf 20:6d2af70c92ab 491 #else
darienf 20:6d2af70c92ab 492 }
darienf 20:6d2af70c92ab 493 catch (Exception ex)
darienf 20:6d2af70c92ab 494 {
darienf 20:6d2af70c92ab 495 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 496 }
darienf 20:6d2af70c92ab 497 finally
darienf 20:6d2af70c92ab 498 {
darienf 20:6d2af70c92ab 499 // Free the memory allocated previously by AllocHGlobal.
darienf 20:6d2af70c92ab 500 if (deviceInterfaceDetailDataBuffer != IntPtr.Zero)
darienf 20:6d2af70c92ab 501 Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
darienf 20:6d2af70c92ab 502
darienf 20:6d2af70c92ab 503 if (deviceInfoSet != IntPtr.Zero)
darienf 20:6d2af70c92ab 504 SetupDiDestroyDeviceInfoList(deviceInfoSet);
darienf 20:6d2af70c92ab 505 }
darienf 20:6d2af70c92ab 506 #endif
darienf 20:6d2af70c92ab 507 DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 508 }
darienf 20:6d2af70c92ab 509
darienf 20:6d2af70c92ab 510 public bool isConnected()
darienf 20:6d2af70c92ab 511 {
darienf 20:6d2af70c92ab 512 try
darienf 20:6d2af70c92ab 513 {
darienf 20:6d2af70c92ab 514 return desiredHIDPathNameArray.Count != 0 ? true : false;
darienf 20:6d2af70c92ab 515 }
darienf 20:6d2af70c92ab 516 catch (Exception ex)
darienf 20:6d2af70c92ab 517 {
darienf 20:6d2af70c92ab 518 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 519 }
darienf 20:6d2af70c92ab 520 }
darienf 20:6d2af70c92ab 521
darienf 20:6d2af70c92ab 522
darienf 20:6d2af70c92ab 523 /// <summary>
darienf 20:6d2af70c92ab 524 /// Called when a WM_DEVICECHANGE message has arrived,
darienf 20:6d2af70c92ab 525 /// indicating that a device has been attached or removed.
darienf 20:6d2af70c92ab 526 ///
darienf 20:6d2af70c92ab 527 /// </summary>
darienf 20:6d2af70c92ab 528 /// <param name="m"> a message with information about the device </param>
darienf 20:6d2af70c92ab 529 /// <returns>true on HID device arrival or remove complete</returns>
darienf 20:6d2af70c92ab 530 public bool HandleWMDeviceChangeMessage(Message m)
darienf 20:6d2af70c92ab 531 {
darienf 20:6d2af70c92ab 532 // Example code:
darienf 20:6d2af70c92ab 533 //
darienf 20:6d2af70c92ab 534 // <code>
darienf 20:6d2af70c92ab 535 // protected override void WndProc(ref Message m)
darienf 20:6d2af70c92ab 536 // {
darienf 20:6d2af70c92ab 537 // if (myHID != null)
darienf 20:6d2af70c92ab 538 // {
darienf 20:6d2af70c92ab 539 // if (myHID.HandleWMDeviceChangeMessage(m) /* m.Msg == HID.WM_DEVICECHANGE */ )
darienf 20:6d2af70c92ab 540 // {
darienf 20:6d2af70c92ab 541 // // optional: handle newly arrived connection or surprise disconnect
darienf 20:6d2af70c92ab 542 // }
darienf 20:6d2af70c92ab 543 // }
darienf 20:6d2af70c92ab 544 // // Let the base form process the message.
darienf 20:6d2af70c92ab 545 // base.WndProc(ref m);
darienf 20:6d2af70c92ab 546 // }
darienf 20:6d2af70c92ab 547 // </code>
darienf 20:6d2af70c92ab 548 //
darienf 20:6d2af70c92ab 549 // https://jira.maxim-ic.com/browse/OS24EVK-59 WndProc if HID.WM_DEVICECHANGE do HID.OnDeviceChange(Message m)
darienf 20:6d2af70c92ab 550 try
darienf 20:6d2af70c92ab 551 {
darienf 20:6d2af70c92ab 552 if (m.Msg == HID.WM_DEVICECHANGE)
darienf 20:6d2af70c92ab 553 {
darienf 20:6d2af70c92ab 554 //if ((int)m.WParam == HID.DBT_DEVNODES_CHANGED) //this always occurs when any USB device is attached/detached. Use this if not registering for device notifications.
darienf 20:6d2af70c92ab 555 if (
darienf 20:6d2af70c92ab 556 ( m.WParam.ToInt32() == HID.DBT_DEVICEARRIVAL
darienf 20:6d2af70c92ab 557 || m.WParam.ToInt32() == HID.DBT_DEVICEREMOVECOMPLETE
darienf 20:6d2af70c92ab 558 )
darienf 20:6d2af70c92ab 559 &&
darienf 20:6d2af70c92ab 560 (m.LParam.ToInt32() != 0)
darienf 20:6d2af70c92ab 561 &&
darienf 20:6d2af70c92ab 562 DeviceIDMatch(m)
darienf 20:6d2af70c92ab 563 )
darienf 20:6d2af70c92ab 564 {
darienf 20:6d2af70c92ab 565 closeHIDhandles();
darienf 20:6d2af70c92ab 566 findHIDs();
darienf 20:6d2af70c92ab 567 // cboEVB_init();
darienf 20:6d2af70c92ab 568 return true;
darienf 20:6d2af70c92ab 569 }
darienf 20:6d2af70c92ab 570 }
darienf 20:6d2af70c92ab 571 return false;
darienf 20:6d2af70c92ab 572 }
darienf 20:6d2af70c92ab 573 catch (Exception ex)
darienf 20:6d2af70c92ab 574 {
darienf 20:6d2af70c92ab 575 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 576 }
darienf 20:6d2af70c92ab 577 }
darienf 20:6d2af70c92ab 578
darienf 20:6d2af70c92ab 579 /// <summary>
darienf 20:6d2af70c92ab 580 /// findHIDs() called upon startup or if a desired HID has been inserted or removed
darienf 20:6d2af70c92ab 581 /// </summary>
darienf 20:6d2af70c92ab 582 public void findHIDs()
darienf 20:6d2af70c92ab 583 {
darienf 20:6d2af70c92ab 584 DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 585 ArrayList allHIDPathNameArray = new ArrayList();
darienf 20:6d2af70c92ab 586 System.Guid hidGuid = new System.Guid();
darienf 20:6d2af70c92ab 587
darienf 20:6d2af70c92ab 588 // https://jira.maxim-ic.com/browse/OS24EVK-59 (intermittent) Matlab Exception Message: Arithmetic operation resulted in an overflow.
darienf 20:6d2af70c92ab 589 #if DEBUG
darienf 20:6d2af70c92ab 590 #else
darienf 20:6d2af70c92ab 591 try
darienf 20:6d2af70c92ab 592 {
darienf 20:6d2af70c92ab 593 #endif
darienf 20:6d2af70c92ab 594 HidD_GetHidGuid(ref hidGuid);
darienf 20:6d2af70c92ab 595 // FindDesiredHIDPathNamesFromGuid() builds desiredHIDPathNameArray which is a list of all desired HIDs in the system
darienf 20:6d2af70c92ab 596 // desiredHIDPathNameArray is a global list and is used to maintain the order of desired HIDs in the selection list.
darienf 20:6d2af70c92ab 597 // USB ports have different priorities, and the user could have attached the first desired HID to a lower priority port.
darienf 20:6d2af70c92ab 598 // Hence, when another desired HID is attached to a higher priority port, it will come earlier in allHIDPathNameArray, but it will be maintained in the same attachment order in desiredHIDPathNameArray.
darienf 20:6d2af70c92ab 599 // Note that desiredHIDPathNameArray is only appended to or deleted from; it is never recreated in whole.
darienf 20:6d2af70c92ab 600 // FIXME desiredHIDPathNameArray will get duplicate pathnames for desired HIDs that were already attached, but these will be removed by openHIDhandles() since they're in allHIDPathNameArray only once.
darienf 20:6d2af70c92ab 601 // These duplicates pathnames are appended after the initial list, so they won't affect order.
darienf 20:6d2af70c92ab 602 FindDesiredHIDPathNamesFromGuid(hidGuid);
darienf 20:6d2af70c92ab 603 // FindAllHIDPathNamesFromGuid() builds allHIDPathNameArray which is a list of all HIDs in the system. It is recreated every time a desired HID is attached or removed.
darienf 20:6d2af70c92ab 604 FindAllHIDPathNamesFromGuid(hidGuid, allHIDPathNameArray);
darienf 20:6d2af70c92ab 605 // openHIDhandles() gets handles for all desired HIDs
darienf 20:6d2af70c92ab 606 // openHIDhandles() loops through all attached HIDs and checks for a match of each item in desiredHIDPathNameArray. This maintains the attachement order.
darienf 20:6d2af70c92ab 607 // If a previously attached HID has been removed, it won't be found in allHIDPathNameArray and it will be removed from desiredHIDPathNameArray.
darienf 20:6d2af70c92ab 608 openHIDhandles(allHIDPathNameArray);
darienf 20:6d2af70c92ab 609 if (desiredHIDPathNameArray.Count != 0)
darienf 20:6d2af70c92ab 610 {
darienf 20:6d2af70c92ab 611 prepareForOverlappedTransfer();
darienf 20:6d2af70c92ab 612 }
darienf 20:6d2af70c92ab 613 #if DEBUG
darienf 20:6d2af70c92ab 614 #else
darienf 20:6d2af70c92ab 615 }
darienf 20:6d2af70c92ab 616 catch (Exception ex)
darienf 20:6d2af70c92ab 617 {
darienf 20:6d2af70c92ab 618 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 619 }
darienf 20:6d2af70c92ab 620 #endif
darienf 20:6d2af70c92ab 621 DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 622 }
darienf 20:6d2af70c92ab 623
darienf 20:6d2af70c92ab 624 private void openHIDhandles(ArrayList allHIDPathNameArray)
darienf 20:6d2af70c92ab 625 {
darienf 20:6d2af70c92ab 626 DebugMessage = string.Format("{0} entered", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 627 int desiredHIDPathNameArrayCounter;
darienf 20:6d2af70c92ab 628 int allHIDPathNameArrayCounter;
darienf 20:6d2af70c92ab 629 bool found_installed_device;
darienf 20:6d2af70c92ab 630 try
darienf 20:6d2af70c92ab 631 {
darienf 20:6d2af70c92ab 632 desiredHIDPathNameArrayCounter = 0;
darienf 20:6d2af70c92ab 633 while (desiredHIDPathNameArrayCounter < desiredHIDPathNameArray.Count) // count will change if a previously installed device has been removed, so don't use a for loop
darienf 20:6d2af70c92ab 634 {
darienf 20:6d2af70c92ab 635 found_installed_device = false;
darienf 20:6d2af70c92ab 636 allHIDPathNameArrayCounter = 0;
darienf 20:6d2af70c92ab 637 while (allHIDPathNameArrayCounter < allHIDPathNameArray.Count)
darienf 20:6d2af70c92ab 638 {
darienf 20:6d2af70c92ab 639 if ((string)allHIDPathNameArray[allHIDPathNameArrayCounter] == (string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter])
darienf 20:6d2af70c92ab 640 {
darienf 20:6d2af70c92ab 641 writeHandle = FileIO.CreateFile((string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter], FileIO.GENERIC_READ | FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0);
darienf 20:6d2af70c92ab 642 if (!(writeHandle.IsInvalid))
darienf 20:6d2af70c92ab 643 {
darienf 20:6d2af70c92ab 644 readHandle = FileIO.CreateFile((string)desiredHIDPathNameArray[desiredHIDPathNameArrayCounter], FileIO.GENERIC_READ | FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, FileIO.FILE_FLAG_OVERLAPPED, 0);
darienf 20:6d2af70c92ab 645 if (!(readHandle.IsInvalid))
darienf 20:6d2af70c92ab 646 {
darienf 20:6d2af70c92ab 647 writeHandleArray.Add(writeHandle);
darienf 20:6d2af70c92ab 648 readHandleArray.Add(readHandle);
darienf 20:6d2af70c92ab 649 allHIDPathNameArray.RemoveAt(allHIDPathNameArrayCounter); // remove it so we don't repeatedly add it when we check for new devices (after we finish checking for previously installed devices)
darienf 20:6d2af70c92ab 650 found_installed_device = true;
darienf 20:6d2af70c92ab 651 }
darienf 20:6d2af70c92ab 652 else
darienf 20:6d2af70c92ab 653 {
darienf 20:6d2af70c92ab 654 writeHandle.Close();
darienf 20:6d2af70c92ab 655 writeHandle = null;
darienf 20:6d2af70c92ab 656 readHandle = null;
darienf 20:6d2af70c92ab 657 }
darienf 20:6d2af70c92ab 658 }
darienf 20:6d2af70c92ab 659 else
darienf 20:6d2af70c92ab 660 {
darienf 20:6d2af70c92ab 661 writeHandle = null;
darienf 20:6d2af70c92ab 662 readHandle = null;
darienf 20:6d2af70c92ab 663 }
darienf 20:6d2af70c92ab 664 break;
darienf 20:6d2af70c92ab 665 }
darienf 20:6d2af70c92ab 666 allHIDPathNameArrayCounter++;
darienf 20:6d2af70c92ab 667 }
darienf 20:6d2af70c92ab 668 if (found_installed_device == false) // no match in all allHIDPathNameArray elements; the device has been removed so remove its pathname from desiredHIDPathNameArray. Don't use counter at max count to check if not found, since max count can change.
darienf 20:6d2af70c92ab 669 desiredHIDPathNameArray.RemoveAt(desiredHIDPathNameArrayCounter); // decrements count by 1; don't increment desiredHIDPathNameArrayCounter
darienf 20:6d2af70c92ab 670 else
darienf 20:6d2af70c92ab 671 desiredHIDPathNameArrayCounter++;
darienf 20:6d2af70c92ab 672 }
darienf 20:6d2af70c92ab 673 }
darienf 20:6d2af70c92ab 674 catch (Exception ex)
darienf 20:6d2af70c92ab 675 {
darienf 20:6d2af70c92ab 676 DebugMessage = string.Format("{0} exception {1}", System.Reflection.MethodInfo.GetCurrentMethod().Name, ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 677 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 678 }
darienf 20:6d2af70c92ab 679 DebugMessage = string.Format("{0} exited", System.Reflection.MethodInfo.GetCurrentMethod().Name);
darienf 20:6d2af70c92ab 680 }
darienf 20:6d2af70c92ab 681
darienf 20:6d2af70c92ab 682 public void closeHIDhandles()
darienf 20:6d2af70c92ab 683 {
darienf 20:6d2af70c92ab 684 try
darienf 20:6d2af70c92ab 685 {
darienf 20:6d2af70c92ab 686 if (desiredHIDPathNameArray.Count != 0)
darienf 20:6d2af70c92ab 687 {
darienf 20:6d2af70c92ab 688 foreach (Object obj in writeHandleArray)
darienf 20:6d2af70c92ab 689 ((SafeFileHandle)obj).Close();
darienf 20:6d2af70c92ab 690 writeHandleArray.Clear();
darienf 20:6d2af70c92ab 691 writeHandle = null;
darienf 20:6d2af70c92ab 692 foreach (Object obj in readHandleArray)
darienf 20:6d2af70c92ab 693 ((SafeFileHandle)obj).Close();
darienf 20:6d2af70c92ab 694 readHandleArray.Clear();
darienf 20:6d2af70c92ab 695 readHandle = null;
darienf 20:6d2af70c92ab 696 }
darienf 20:6d2af70c92ab 697 }
darienf 20:6d2af70c92ab 698 catch (Exception ex)
darienf 20:6d2af70c92ab 699 {
darienf 20:6d2af70c92ab 700 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 701 }
darienf 20:6d2af70c92ab 702 }
darienf 20:6d2af70c92ab 703
darienf 20:6d2af70c92ab 704 private void prepareForOverlappedTransfer()
darienf 20:6d2af70c92ab 705 {
darienf 20:6d2af70c92ab 706 try
darienf 20:6d2af70c92ab 707 {
darienf 20:6d2af70c92ab 708 EventObject = FileIO.CreateEvent(IntPtr.Zero, false, false, String.Empty);
darienf 20:6d2af70c92ab 709 managedOverlapped.OffsetLow = 0;
darienf 20:6d2af70c92ab 710 managedOverlapped.OffsetHigh = 0;
darienf 20:6d2af70c92ab 711 managedOverlapped.EventHandle = EventObject; // HIDOverlapped is the overlapped structure used in ReadFile; EventObject will be signaled upon completion of ReadFile
darienf 20:6d2af70c92ab 712 nonManagedOverlapped = Marshal.AllocHGlobal(Marshal.SizeOf(managedOverlapped));
darienf 20:6d2af70c92ab 713 Marshal.StructureToPtr(managedOverlapped, nonManagedOverlapped, false);
darienf 20:6d2af70c92ab 714
darienf 20:6d2af70c92ab 715 nonManagedBuffer = Marshal.AllocHGlobal(REPORT_SIZE);
darienf 20:6d2af70c92ab 716 }
darienf 20:6d2af70c92ab 717 catch (Exception ex)
darienf 20:6d2af70c92ab 718 {
darienf 20:6d2af70c92ab 719 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 720 }
darienf 20:6d2af70c92ab 721 }
darienf 20:6d2af70c92ab 722
darienf 20:6d2af70c92ab 723 public void FlushQueue()
darienf 20:6d2af70c92ab 724 {
darienf 20:6d2af70c92ab 725 try
darienf 20:6d2af70c92ab 726 {
darienf 20:6d2af70c92ab 727 if (writeHandle == null)
darienf 20:6d2af70c92ab 728 {
darienf 20:6d2af70c92ab 729 return;
darienf 20:6d2af70c92ab 730 }
darienf 20:6d2af70c92ab 731 if (readHandle == null)
darienf 20:6d2af70c92ab 732 {
darienf 20:6d2af70c92ab 733 return;
darienf 20:6d2af70c92ab 734 }
darienf 20:6d2af70c92ab 735
darienf 20:6d2af70c92ab 736 HidD_FlushQueue(writeHandle);
darienf 20:6d2af70c92ab 737 HidD_FlushQueue(readHandle);
darienf 20:6d2af70c92ab 738 }
darienf 20:6d2af70c92ab 739 catch
darienf 20:6d2af70c92ab 740 {
darienf 20:6d2af70c92ab 741 throw new Exception(new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 742 }
darienf 20:6d2af70c92ab 743 }
darienf 20:6d2af70c92ab 744
darienf 20:6d2af70c92ab 745 public void writeReadHID()
darienf 20:6d2af70c92ab 746 {
darienf 20:6d2af70c92ab 747 try
darienf 20:6d2af70c92ab 748 {
darienf 20:6d2af70c92ab 749 if (writeHandle == null)
darienf 20:6d2af70c92ab 750 {
darienf 20:6d2af70c92ab 751 return;
darienf 20:6d2af70c92ab 752 }
darienf 20:6d2af70c92ab 753 if (readHandle == null)
darienf 20:6d2af70c92ab 754 {
darienf 20:6d2af70c92ab 755 return;
darienf 20:6d2af70c92ab 756 }
darienf 20:6d2af70c92ab 757
darienf 20:6d2af70c92ab 758 writeHID();
darienf 20:6d2af70c92ab 759 readHID();
darienf 20:6d2af70c92ab 760 }
darienf 20:6d2af70c92ab 761 catch (Exception ex)
darienf 20:6d2af70c92ab 762 {
darienf 20:6d2af70c92ab 763 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 764 }
darienf 20:6d2af70c92ab 765 }
darienf 20:6d2af70c92ab 766
darienf 20:6d2af70c92ab 767 public void writeHID()
darienf 20:6d2af70c92ab 768 {
darienf 20:6d2af70c92ab 769 if (writeHandle == null)
darienf 20:6d2af70c92ab 770 {
darienf 20:6d2af70c92ab 771 return;
darienf 20:6d2af70c92ab 772 }
darienf 20:6d2af70c92ab 773 if (readHandle == null)
darienf 20:6d2af70c92ab 774 {
darienf 20:6d2af70c92ab 775 return;
darienf 20:6d2af70c92ab 776 }
darienf 20:6d2af70c92ab 777
darienf 20:6d2af70c92ab 778 int BytesSucceed;
darienf 20:6d2af70c92ab 779 bool api_status;
darienf 20:6d2af70c92ab 780
darienf 20:6d2af70c92ab 781 try
darienf 20:6d2af70c92ab 782 {
darienf 20:6d2af70c92ab 783 BytesSucceed = 0;
darienf 20:6d2af70c92ab 784 Marshal.Copy(IOBuf, 0, nonManagedBuffer, REPORT_SIZE);
darienf 20:6d2af70c92ab 785 api_status = FileIO.WriteFile(writeHandle, nonManagedBuffer, REPORT_SIZE, ref BytesSucceed, IntPtr.Zero);
darienf 20:6d2af70c92ab 786 //endpoint in interrupt at uC occurs after this WriteFile call since the in data is ready and the host takes it; endpoint in interrupt does not occur after ReadFile call
darienf 20:6d2af70c92ab 787
darienf 20:6d2af70c92ab 788 if (api_status == false)
darienf 20:6d2af70c92ab 789 {
darienf 20:6d2af70c92ab 790 //MessageBox.Show(Err.LastDllError);
darienf 20:6d2af70c92ab 791 throw new Exception(support.ResultOfAPICall("API WriteFile error"));
darienf 20:6d2af70c92ab 792 }
darienf 20:6d2af70c92ab 793 }
darienf 20:6d2af70c92ab 794 catch (Exception ex)
darienf 20:6d2af70c92ab 795 {
darienf 20:6d2af70c92ab 796 throw new Exception(ex.Message + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 797 }
darienf 20:6d2af70c92ab 798 }
darienf 20:6d2af70c92ab 799
darienf 20:6d2af70c92ab 800 public void readHID()
darienf 20:6d2af70c92ab 801 {
darienf 20:6d2af70c92ab 802 if (writeHandle == null)
darienf 20:6d2af70c92ab 803 {
darienf 20:6d2af70c92ab 804 return;
darienf 20:6d2af70c92ab 805 }
darienf 20:6d2af70c92ab 806 if (readHandle == null)
darienf 20:6d2af70c92ab 807 {
darienf 20:6d2af70c92ab 808 return;
darienf 20:6d2af70c92ab 809 }
darienf 20:6d2af70c92ab 810
darienf 20:6d2af70c92ab 811 int BytesSucceed;
darienf 20:6d2af70c92ab 812 bool api_status;
darienf 20:6d2af70c92ab 813 int status;
darienf 20:6d2af70c92ab 814
darienf 20:6d2af70c92ab 815 try
darienf 20:6d2af70c92ab 816 {
darienf 20:6d2af70c92ab 817 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 818
darienf 20:6d2af70c92ab 819 BytesSucceed = 0;
darienf 20:6d2af70c92ab 820
darienf 20:6d2af70c92ab 821 api_status = FileIO.ReadFile(readHandle, nonManagedBuffer, REPORT_SIZE, ref BytesSucceed, nonManagedOverlapped);
darienf 20:6d2af70c92ab 822
darienf 20:6d2af70c92ab 823 if (api_status == false)
darienf 20:6d2af70c92ab 824 {
darienf 20:6d2af70c92ab 825 //MsgBox(Err.LastDllError)
darienf 20:6d2af70c92ab 826 status = FileIO.WaitForSingleObject(EventObject, IOtimeout);
darienf 20:6d2af70c92ab 827
darienf 20:6d2af70c92ab 828 if (status != FileIO.WAIT_OBJECT_0)
darienf 20:6d2af70c92ab 829 {
darienf 20:6d2af70c92ab 830 api_status = FileIO.CancelIo(readHandle);
darienf 20:6d2af70c92ab 831 throw new Exception(support.ResultOfAPICall("API ReadFile error"));
darienf 20:6d2af70c92ab 832 }
darienf 20:6d2af70c92ab 833 FileIO.GetOverlappedResult(readHandle, nonManagedOverlapped, ref BytesSucceed, false);
darienf 20:6d2af70c92ab 834 }
darienf 20:6d2af70c92ab 835
darienf 20:6d2af70c92ab 836 // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
darienf 20:6d2af70c92ab 837 if (BytesSucceed > IOBuf.Length)
darienf 20:6d2af70c92ab 838 {
darienf 20:6d2af70c92ab 839 IOBuf = new byte[BytesSucceed];
darienf 20:6d2af70c92ab 840 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 841 }
darienf 20:6d2af70c92ab 842 Marshal.Copy(nonManagedBuffer, IOBuf, 0, BytesSucceed);
darienf 20:6d2af70c92ab 843 }
darienf 20:6d2af70c92ab 844 catch (Exception ex)
darienf 20:6d2af70c92ab 845 {
darienf 20:6d2af70c92ab 846 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 847 }
darienf 20:6d2af70c92ab 848 }
darienf 20:6d2af70c92ab 849
darienf 20:6d2af70c92ab 850 public void readHID2() // this function is for testing multiple report read on a single ReadFile()
darienf 20:6d2af70c92ab 851 {
darienf 20:6d2af70c92ab 852 if (writeHandle == null)
darienf 20:6d2af70c92ab 853 {
darienf 20:6d2af70c92ab 854 return;
darienf 20:6d2af70c92ab 855 }
darienf 20:6d2af70c92ab 856 if (readHandle == null)
darienf 20:6d2af70c92ab 857 {
darienf 20:6d2af70c92ab 858 return;
darienf 20:6d2af70c92ab 859 }
darienf 20:6d2af70c92ab 860
darienf 20:6d2af70c92ab 861 int BytesSucceed;
darienf 20:6d2af70c92ab 862 bool api_status;
darienf 20:6d2af70c92ab 863 int status;
darienf 20:6d2af70c92ab 864
darienf 20:6d2af70c92ab 865 try
darienf 20:6d2af70c92ab 866 {
darienf 20:6d2af70c92ab 867 int size = 128;
darienf 20:6d2af70c92ab 868 //byte[] buf = new byte[size];
darienf 20:6d2af70c92ab 869 IntPtr nonManagedBuf = Marshal.AllocHGlobal(size);
darienf 20:6d2af70c92ab 870 //Array.Clear(buf, 0, size);
darienf 20:6d2af70c92ab 871
darienf 20:6d2af70c92ab 872 BytesSucceed = 0;
darienf 20:6d2af70c92ab 873
darienf 20:6d2af70c92ab 874 api_status = FileIO.ReadFile(readHandle, nonManagedBuf, size, ref BytesSucceed, nonManagedOverlapped);
darienf 20:6d2af70c92ab 875
darienf 20:6d2af70c92ab 876 if (api_status == false)
darienf 20:6d2af70c92ab 877 {
darienf 20:6d2af70c92ab 878 //MsgBox(Err.LastDllError)
darienf 20:6d2af70c92ab 879 status = FileIO.WaitForSingleObject(EventObject, IOtimeout);
darienf 20:6d2af70c92ab 880
darienf 20:6d2af70c92ab 881 if (status != FileIO.WAIT_OBJECT_0)
darienf 20:6d2af70c92ab 882 {
darienf 20:6d2af70c92ab 883 api_status = FileIO.CancelIo(readHandle);
darienf 20:6d2af70c92ab 884 throw new Exception(support.ResultOfAPICall("API ReadFile error"));
darienf 20:6d2af70c92ab 885 }
darienf 20:6d2af70c92ab 886 FileIO.GetOverlappedResult(readHandle, nonManagedOverlapped, ref BytesSucceed, false);
darienf 20:6d2af70c92ab 887 }
darienf 20:6d2af70c92ab 888
darienf 20:6d2af70c92ab 889 // TODO1: OS24EVK-57 2015-04-01 myHID.readHID2() needs to return result into IOBuf. But IOBuf = new byte[64], do we replace with IOBuf = new byte[128]? Does this affect readHID()?
darienf 20:6d2af70c92ab 890 if (BytesSucceed > IOBuf.Length)
darienf 20:6d2af70c92ab 891 {
darienf 20:6d2af70c92ab 892 IOBuf = new byte[BytesSucceed];
darienf 20:6d2af70c92ab 893 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 894 }
darienf 20:6d2af70c92ab 895 Marshal.Copy(nonManagedBuf, IOBuf, 0, BytesSucceed);
darienf 20:6d2af70c92ab 896
darienf 20:6d2af70c92ab 897 if (nonManagedBuf != IntPtr.Zero)
darienf 20:6d2af70c92ab 898 Marshal.FreeHGlobal(nonManagedBuffer);
darienf 20:6d2af70c92ab 899 }
darienf 20:6d2af70c92ab 900 catch (Exception ex)
darienf 20:6d2af70c92ab 901 {
darienf 20:6d2af70c92ab 902 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 903 }
darienf 20:6d2af70c92ab 904 }
darienf 20:6d2af70c92ab 905 public void freeHeap()
darienf 20:6d2af70c92ab 906 {
darienf 20:6d2af70c92ab 907 try
darienf 20:6d2af70c92ab 908 {
darienf 20:6d2af70c92ab 909 if (nonManagedBuffer != IntPtr.Zero)
darienf 20:6d2af70c92ab 910 Marshal.FreeHGlobal(nonManagedBuffer);
darienf 20:6d2af70c92ab 911 if (nonManagedOverlapped != IntPtr.Zero)
darienf 20:6d2af70c92ab 912 Marshal.FreeHGlobal(nonManagedOverlapped);
darienf 20:6d2af70c92ab 913 }
darienf 20:6d2af70c92ab 914 catch (Exception ex)
darienf 20:6d2af70c92ab 915 {
darienf 20:6d2af70c92ab 916 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 917 }
darienf 20:6d2af70c92ab 918 }
darienf 20:6d2af70c92ab 919
darienf 20:6d2af70c92ab 920 /// <summary>
darienf 20:6d2af70c92ab 921 /// Requests to receive a notification when a device is attached or removed.
darienf 20:6d2af70c92ab 922 /// </summary>
darienf 20:6d2af70c92ab 923 ///
darienf 20:6d2af70c92ab 924 /// <param name="formHandle"> handle to the window that will receive device events. </param>
darienf 20:6d2af70c92ab 925 /// <param name="classGuid"> device interface GUID. </param>
darienf 20:6d2af70c92ab 926 /// <param name="deviceNotificationHandle"> returned device notification handle. </param>
darienf 20:6d2af70c92ab 927 ///
darienf 20:6d2af70c92ab 928 /// <returns>
darienf 20:6d2af70c92ab 929 /// True on success.
darienf 20:6d2af70c92ab 930 /// </returns>
darienf 20:6d2af70c92ab 931 ///
darienf 20:6d2af70c92ab 932 public Boolean RegisterForDeviceNotifications(IntPtr formHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
darienf 20:6d2af70c92ab 933 {
darienf 20:6d2af70c92ab 934 DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE();
darienf 20:6d2af70c92ab 935 IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
darienf 20:6d2af70c92ab 936 Int32 size = 0;
darienf 20:6d2af70c92ab 937
darienf 20:6d2af70c92ab 938 try
darienf 20:6d2af70c92ab 939 {
darienf 20:6d2af70c92ab 940 size = Marshal.SizeOf(devBroadcastDeviceInterface);
darienf 20:6d2af70c92ab 941 devBroadcastDeviceInterface.dbcc_size = size;
darienf 20:6d2af70c92ab 942 devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
darienf 20:6d2af70c92ab 943 devBroadcastDeviceInterface.dbcc_reserved = 0;
darienf 20:6d2af70c92ab 944 devBroadcastDeviceInterface.dbcc_classguid = classGuid;
darienf 20:6d2af70c92ab 945
darienf 20:6d2af70c92ab 946 // Allocate memory for the buffer that holds the DEV_BROADCAST_DEVICEINTERFACE structure.
darienf 20:6d2af70c92ab 947 devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size);
darienf 20:6d2af70c92ab 948
darienf 20:6d2af70c92ab 949 // Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer.
darienf 20:6d2af70c92ab 950 // Set fDeleteOld True to prevent memory leaks.
darienf 20:6d2af70c92ab 951 Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
darienf 20:6d2af70c92ab 952
darienf 20:6d2af70c92ab 953 // ***
darienf 20:6d2af70c92ab 954 // API function
darienf 20:6d2af70c92ab 955
darienf 20:6d2af70c92ab 956 // summary
darienf 20:6d2af70c92ab 957 // Request to receive notification messages when a device in an interface class
darienf 20:6d2af70c92ab 958 // is attached or removed.
darienf 20:6d2af70c92ab 959
darienf 20:6d2af70c92ab 960 // parameters
darienf 20:6d2af70c92ab 961 // Handle to the window that will receive device events.
darienf 20:6d2af70c92ab 962 // Pointer to a DEV_BROADCAST_DEVICEINTERFACE to specify the type of
darienf 20:6d2af70c92ab 963 // device to send notifications for.
darienf 20:6d2af70c92ab 964 // DEVICE_NOTIFY_WINDOW_HANDLE indicates the handle is a window handle.
darienf 20:6d2af70c92ab 965
darienf 20:6d2af70c92ab 966 // Returns
darienf 20:6d2af70c92ab 967 // Device notification handle or NULL on failure.
darienf 20:6d2af70c92ab 968 // ***
darienf 20:6d2af70c92ab 969
darienf 20:6d2af70c92ab 970 deviceNotificationHandle = RegisterDeviceNotification(formHandle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE);
darienf 20:6d2af70c92ab 971
darienf 20:6d2af70c92ab 972 // Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to the managed object devBroadcastDeviceInterface
darienf 20:6d2af70c92ab 973 // why?
darienf 20:6d2af70c92ab 974 Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
darienf 20:6d2af70c92ab 975
darienf 20:6d2af70c92ab 976 return deviceNotificationHandle.ToInt32() == IntPtr.Zero.ToInt32() ? false : true;
darienf 20:6d2af70c92ab 977 }
darienf 20:6d2af70c92ab 978 catch (Exception ex)
darienf 20:6d2af70c92ab 979 {
darienf 20:6d2af70c92ab 980 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 981 }
darienf 20:6d2af70c92ab 982 finally
darienf 20:6d2af70c92ab 983 {
darienf 20:6d2af70c92ab 984 // Free the memory allocated previously by AllocHGlobal.
darienf 20:6d2af70c92ab 985 if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
darienf 20:6d2af70c92ab 986 Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
darienf 20:6d2af70c92ab 987 }
darienf 20:6d2af70c92ab 988 }
darienf 20:6d2af70c92ab 989
darienf 20:6d2af70c92ab 990 /// <summary>
darienf 20:6d2af70c92ab 991 /// Requests to stop receiving notification messages when a device in an
darienf 20:6d2af70c92ab 992 /// interface class is attached or removed.
darienf 20:6d2af70c92ab 993 /// </summary>
darienf 20:6d2af70c92ab 994 ///
darienf 20:6d2af70c92ab 995 /// <param name="deviceNotificationHandle"> handle returned previously by
darienf 20:6d2af70c92ab 996 /// RegisterDeviceNotification. </param>
darienf 20:6d2af70c92ab 997
darienf 20:6d2af70c92ab 998 public void StopReceivingDeviceNotifications(IntPtr deviceNotificationHandle)
darienf 20:6d2af70c92ab 999 {
darienf 20:6d2af70c92ab 1000 try
darienf 20:6d2af70c92ab 1001 {
darienf 20:6d2af70c92ab 1002 UnregisterDeviceNotification(deviceNotificationHandle);
darienf 20:6d2af70c92ab 1003 }
darienf 20:6d2af70c92ab 1004 catch (Exception ex)
darienf 20:6d2af70c92ab 1005 {
darienf 20:6d2af70c92ab 1006 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 1007 }
darienf 20:6d2af70c92ab 1008 }
darienf 20:6d2af70c92ab 1009
darienf 20:6d2af70c92ab 1010 public Boolean DeviceIDMatch(Message m)
darienf 20:6d2af70c92ab 1011 {
darienf 20:6d2af70c92ab 1012 Int32 stringSize;
darienf 20:6d2af70c92ab 1013
darienf 20:6d2af70c92ab 1014 try
darienf 20:6d2af70c92ab 1015 {
darienf 20:6d2af70c92ab 1016 DEV_BROADCAST_HDR devBroadcastHeader = new DEV_BROADCAST_HDR();
darienf 20:6d2af70c92ab 1017 DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE_1();
darienf 20:6d2af70c92ab 1018
darienf 20:6d2af70c92ab 1019 // The LParam parameter of Message is a pointer to a DEV_BROADCAST_HDR structure.
darienf 20:6d2af70c92ab 1020 Marshal.PtrToStructure(m.LParam, devBroadcastHeader);
darienf 20:6d2af70c92ab 1021 if ((devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
darienf 20:6d2af70c92ab 1022 {
darienf 20:6d2af70c92ab 1023 // The dbch_devicetype parameter indicates that the event applies to a device interface.
darienf 20:6d2af70c92ab 1024 // So the structure in LParam is actually a DEV_BROADCAST_INTERFACE structure,
darienf 20:6d2af70c92ab 1025 // which begins with a DEV_BROADCAST_HDR.
darienf 20:6d2af70c92ab 1026
darienf 20:6d2af70c92ab 1027 // Obtain the number of characters in dbch_name by subtracting the 32 bytes
darienf 20:6d2af70c92ab 1028 // in the strucutre that are not part of dbch_name and dividing by 2 because there are
darienf 20:6d2af70c92ab 1029 // 2 bytes per character.
darienf 20:6d2af70c92ab 1030
darienf 20:6d2af70c92ab 1031 stringSize = System.Convert.ToInt32((devBroadcastHeader.dbch_size - 32) / 2);
darienf 20:6d2af70c92ab 1032
darienf 20:6d2af70c92ab 1033 // The dbcc_name parameter of devBroadcastDeviceInterface contains the device name.
darienf 20:6d2af70c92ab 1034 // Trim dbcc_name to match the size of the String.
darienf 20:6d2af70c92ab 1035
darienf 20:6d2af70c92ab 1036 devBroadcastDeviceInterface.dbcc_name = new Char[stringSize + 1];
darienf 20:6d2af70c92ab 1037
darienf 20:6d2af70c92ab 1038 // Marshal data from the unmanaged block pointed to by m.LParam
darienf 20:6d2af70c92ab 1039 // to the managed object devBroadcastDeviceInterface.
darienf 20:6d2af70c92ab 1040
darienf 20:6d2af70c92ab 1041 Marshal.PtrToStructure(m.LParam, devBroadcastDeviceInterface);
darienf 20:6d2af70c92ab 1042
darienf 20:6d2af70c92ab 1043 // Store the device name in a String.
darienf 20:6d2af70c92ab 1044
darienf 20:6d2af70c92ab 1045 String DeviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
darienf 20:6d2af70c92ab 1046
darienf 20:6d2af70c92ab 1047 // Compare the name of the newly attached device with the name of the device
darienf 20:6d2af70c92ab 1048 // the application is accessing (deviceID).
darienf 20:6d2af70c92ab 1049 // Set ignorecase True.
darienf 20:6d2af70c92ab 1050
darienf 20:6d2af70c92ab 1051 return (DeviceNameString.ToLower().IndexOf(deviceID.ToLower()) == -1) ? false : true;
darienf 20:6d2af70c92ab 1052 }
darienf 20:6d2af70c92ab 1053 else
darienf 20:6d2af70c92ab 1054 return false;
darienf 20:6d2af70c92ab 1055 }
darienf 20:6d2af70c92ab 1056 catch (Exception ex)
darienf 20:6d2af70c92ab 1057 {
darienf 20:6d2af70c92ab 1058 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 1059 }
darienf 20:6d2af70c92ab 1060 }
darienf 20:6d2af70c92ab 1061
darienf 20:6d2af70c92ab 1062 public void reportID()
darienf 20:6d2af70c92ab 1063 {
darienf 20:6d2af70c92ab 1064 try
darienf 20:6d2af70c92ab 1065 {
darienf 20:6d2af70c92ab 1066 if (explicit_report_id)
darienf 20:6d2af70c92ab 1067 IOBuf[0] = SHORT_REPORT_ID; // explicit out report ID in HID's descriptor
darienf 20:6d2af70c92ab 1068 else
darienf 20:6d2af70c92ab 1069 IOBuf[0] = DEFAULT_REPORT_ID; // default report ID; this byte is dropped in transfer, so we don't really waste a byte transmitting it
darienf 20:6d2af70c92ab 1070 }
darienf 20:6d2af70c92ab 1071 catch (Exception ex)
darienf 20:6d2af70c92ab 1072 {
darienf 20:6d2af70c92ab 1073 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 1074 }
darienf 20:6d2af70c92ab 1075 }
darienf 20:6d2af70c92ab 1076
darienf 20:6d2af70c92ab 1077 public int readI2C(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] readData, byte[] reg, bool ignoreNACK = false)
darienf 20:6d2af70c92ab 1078 {
darienf 20:6d2af70c92ab 1079 //readData is passed back to caller with the read data
darienf 20:6d2af70c92ab 1080 int status;
darienf 20:6d2af70c92ab 1081 int i;
darienf 20:6d2af70c92ab 1082
darienf 20:6d2af70c92ab 1083 try
darienf 20:6d2af70c92ab 1084 {
darienf 20:6d2af70c92ab 1085 if (numDataBytes > REPORT_SIZE - 2) {
darienf 20:6d2af70c92ab 1086 throw new Exception("USB buffer overflow");
darienf 20:6d2af70c92ab 1087 }
darienf 20:6d2af70c92ab 1088
darienf 20:6d2af70c92ab 1089 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in readI2C
darienf 20:6d2af70c92ab 1090 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1091 FlushQueue();
darienf 20:6d2af70c92ab 1092 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1093
darienf 20:6d2af70c92ab 1094 reportID();
darienf 20:6d2af70c92ab 1095 IOBuf[1] = 6; // I2C transaction -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1096 IOBuf[2] = (byte)(deviceAddress | 1); // set read bit
darienf 20:6d2af70c92ab 1097 IOBuf[3] = numDataBytes;
darienf 20:6d2af70c92ab 1098 IOBuf[4] = numRegBytes;
darienf 20:6d2af70c92ab 1099 // TODO1: OS24EVK-57 HID readI2C no validation that numRegBytes == reg.Length ?
darienf 20:6d2af70c92ab 1100 for (i = 0; i < numRegBytes; i++) {
darienf 20:6d2af70c92ab 1101 IOBuf[i + 5] = reg[i];
darienf 20:6d2af70c92ab 1102 }
darienf 20:6d2af70c92ab 1103
darienf 20:6d2af70c92ab 1104 writeHID();
darienf 20:6d2af70c92ab 1105 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1106
darienf 20:6d2af70c92ab 1107 status = checkNACK();
darienf 20:6d2af70c92ab 1108
darienf 20:6d2af70c92ab 1109 // checkNACK also reads the data, assuming NACK didn't occur
darienf 20:6d2af70c92ab 1110 if (status == I2C_NACK_ERROR && ignoreNACK == false) {
darienf 20:6d2af70c92ab 1111 throw new Exception("invalid I2C address");
darienf 20:6d2af70c92ab 1112 }
darienf 20:6d2af70c92ab 1113
darienf 20:6d2af70c92ab 1114 for (i = 0; i < numDataBytes; i++) {
darienf 20:6d2af70c92ab 1115 readData[i] = IOBuf[i + 2];
darienf 20:6d2af70c92ab 1116 }
darienf 20:6d2af70c92ab 1117
darienf 20:6d2af70c92ab 1118 return status; // the caller will not need the return value if an exception is thrown
darienf 20:6d2af70c92ab 1119 }
darienf 20:6d2af70c92ab 1120 catch (Exception ex)
darienf 20:6d2af70c92ab 1121 {
darienf 20:6d2af70c92ab 1122 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 1123 }
darienf 20:6d2af70c92ab 1124 }
darienf 20:6d2af70c92ab 1125
darienf 20:6d2af70c92ab 1126 public void writeI2C(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] data, byte[] reg, bool ignoreNACK = false)
darienf 20:6d2af70c92ab 1127 {
darienf 20:6d2af70c92ab 1128 int i;
darienf 20:6d2af70c92ab 1129
darienf 20:6d2af70c92ab 1130 try
darienf 20:6d2af70c92ab 1131 {
darienf 20:6d2af70c92ab 1132 if (numDataBytes > REPORT_SIZE - 5) {
darienf 20:6d2af70c92ab 1133 throw new Exception("USB buffer overflow");
darienf 20:6d2af70c92ab 1134 }
darienf 20:6d2af70c92ab 1135
darienf 20:6d2af70c92ab 1136 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in writeI2C
darienf 20:6d2af70c92ab 1137 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1138 FlushQueue();
darienf 20:6d2af70c92ab 1139 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1140
darienf 20:6d2af70c92ab 1141 //send data to tell uC to do I2C read from slave
darienf 20:6d2af70c92ab 1142 reportID();
darienf 20:6d2af70c92ab 1143 IOBuf[1] = 6; // I2C transaction -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1144 IOBuf[2] = deviceAddress;
darienf 20:6d2af70c92ab 1145 IOBuf[3] = numDataBytes;
darienf 20:6d2af70c92ab 1146 IOBuf[4] = numRegBytes;
darienf 20:6d2af70c92ab 1147 for (i = 0; i < numRegBytes; i++) {
darienf 20:6d2af70c92ab 1148 IOBuf[i + 5] = reg[i];
darienf 20:6d2af70c92ab 1149 }
darienf 20:6d2af70c92ab 1150 for (i = 0; i < numDataBytes; i++) {
darienf 20:6d2af70c92ab 1151 IOBuf[i + 5 + numRegBytes] = data[i];
darienf 20:6d2af70c92ab 1152 }
darienf 20:6d2af70c92ab 1153
darienf 20:6d2af70c92ab 1154 writeHID();
darienf 20:6d2af70c92ab 1155 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1156
darienf 20:6d2af70c92ab 1157 if (checkNACK() == I2C_NACK_ERROR && ignoreNACK == false) {
darienf 20:6d2af70c92ab 1158 throw new Exception("invalid I2C address");
darienf 20:6d2af70c92ab 1159 }
darienf 20:6d2af70c92ab 1160 }
darienf 20:6d2af70c92ab 1161 catch (Exception ex)
darienf 20:6d2af70c92ab 1162 {
darienf 20:6d2af70c92ab 1163 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 1164 }
darienf 20:6d2af70c92ab 1165 }
darienf 20:6d2af70c92ab 1166
darienf 20:6d2af70c92ab 1167 private int checkNACK()
darienf 20:6d2af70c92ab 1168 {
darienf 20:6d2af70c92ab 1169 // Check if I2C write was really succesful or a NACK occurred, since this is independent of USB success
darienf 20:6d2af70c92ab 1170 // This function also reads all the data from the report. If NACK occured, the data is invalid.
darienf 20:6d2af70c92ab 1171 try
darienf 20:6d2af70c92ab 1172 {
darienf 20:6d2af70c92ab 1173 readHID();
darienf 20:6d2af70c92ab 1174 return (IOBuf[1] == 0 ? I2C_SUCCESS : I2C_NACK_ERROR); // the caller will not need the return value if an exception is thrown
darienf 20:6d2af70c92ab 1175 }
darienf 20:6d2af70c92ab 1176 catch (Exception ex)
darienf 20:6d2af70c92ab 1177 {
darienf 20:6d2af70c92ab 1178 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 1179 }
darienf 20:6d2af70c92ab 1180 }
darienf 20:6d2af70c92ab 1181
darienf 20:6d2af70c92ab 1182 // only allows 2 byte data
darienf 20:6d2af70c92ab 1183 public void setBitI2C(byte deviceAddress, int reg, byte range, int data, bool ignoreNACK = false)
darienf 20:6d2af70c92ab 1184 {
darienf 20:6d2af70c92ab 1185 int i;
darienf 20:6d2af70c92ab 1186
darienf 20:6d2af70c92ab 1187 try
darienf 20:6d2af70c92ab 1188 {
darienf 20:6d2af70c92ab 1189 int LSb = range & 0xF;
darienf 20:6d2af70c92ab 1190 int MSb = (range & 0xF0) >> 4;
darienf 20:6d2af70c92ab 1191 if (MSb < LSb)
darienf 20:6d2af70c92ab 1192 throw new Exception("invalid bit range");
darienf 20:6d2af70c92ab 1193 //if (numDataBytes > REPORT_SIZE - 5)
darienf 20:6d2af70c92ab 1194 // throw new Exception("USB buffer overflow");
darienf 20:6d2af70c92ab 1195
darienf 20:6d2af70c92ab 1196 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in setBitI2C
darienf 20:6d2af70c92ab 1197 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1198 FlushQueue();
darienf 20:6d2af70c92ab 1199
darienf 20:6d2af70c92ab 1200 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1201
darienf 20:6d2af70c92ab 1202 //send data to tell uC to do I2C read from slave
darienf 20:6d2af70c92ab 1203 reportID();
darienf 20:6d2af70c92ab 1204 IOBuf[1] = 6; // I2C transaction -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1205 IOBuf[2] = deviceAddress;
darienf 20:6d2af70c92ab 1206 byte numDataBytes = (byte)(MSb > 7 ? 2 : 1);
darienf 20:6d2af70c92ab 1207 IOBuf[3] = numDataBytes;
darienf 20:6d2af70c92ab 1208 byte numRegBytes = (byte)Math.Ceiling(reg / 255.0);
darienf 20:6d2af70c92ab 1209 IOBuf[4] = numRegBytes;
darienf 20:6d2af70c92ab 1210 for (i = 0; i < numRegBytes; i++)
darienf 20:6d2af70c92ab 1211 IOBuf[i + 5] = (byte)((reg>>(8*i)) & 0xFF);
darienf 20:6d2af70c92ab 1212 //for (i = 0; i < numDataBytes; i++)
darienf 20:6d2af70c92ab 1213 // IOBuf[i + 5 + numRegBytes] = data[i];
darienf 20:6d2af70c92ab 1214
darienf 20:6d2af70c92ab 1215 writeHID();
darienf 20:6d2af70c92ab 1216 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1217
darienf 20:6d2af70c92ab 1218 if (checkNACK() == I2C_NACK_ERROR && ignoreNACK == false)
darienf 20:6d2af70c92ab 1219 throw new Exception("invalid I2C address");
darienf 20:6d2af70c92ab 1220 }
darienf 20:6d2af70c92ab 1221 catch (Exception ex)
darienf 20:6d2af70c92ab 1222 {
darienf 20:6d2af70c92ab 1223 throw new Exception(ex.Message + Environment.NewLine + new System.Diagnostics.StackFrame().GetMethod().Name);
darienf 20:6d2af70c92ab 1224 }
darienf 20:6d2af70c92ab 1225 }
darienf 20:6d2af70c92ab 1226
darienf 20:6d2af70c92ab 1227 /// <summary>
darienf 20:6d2af70c92ab 1228 /// <para>Firmware command code 0 IN = Firmware version</para>
darienf 20:6d2af70c92ab 1229 ///
darienf 20:6d2af70c92ab 1230 /// </summary>
darienf 20:6d2af70c92ab 1231 /// <param name="VerMajor"></param>
darienf 20:6d2af70c92ab 1232 /// <param name="VerMinor"></param>
darienf 20:6d2af70c92ab 1233 /// <param name="verYearHundreds"></param>
darienf 20:6d2af70c92ab 1234 /// <param name="verYear"></param>
darienf 20:6d2af70c92ab 1235 /// <param name="verMonth"></param>
darienf 20:6d2af70c92ab 1236 /// <param name="verDay"></param>
darienf 20:6d2af70c92ab 1237 public void FirmwareVersion(out byte VerMajor, out byte VerMinor, out byte verYearHundreds, out byte verYear, out byte verMonth, out byte verDay)
darienf 20:6d2af70c92ab 1238 {
darienf 20:6d2af70c92ab 1239 if (FirmwareINT0Enabled != 0)
darienf 20:6d2af70c92ab 1240 {
darienf 20:6d2af70c92ab 1241 // firmware is busy streaming out HID reports,
darienf 20:6d2af70c92ab 1242 // so return a previously retrieved firmware version.
darienf 20:6d2af70c92ab 1243 VerMajor = _VerMajor;
darienf 20:6d2af70c92ab 1244 VerMinor = _VerMinor;
darienf 20:6d2af70c92ab 1245 verYearHundreds = _verYearHundreds;
darienf 20:6d2af70c92ab 1246 verYear = _verYear;
darienf 20:6d2af70c92ab 1247 verMonth = _verMonth;
darienf 20:6d2af70c92ab 1248 verDay = _verDay;
darienf 20:6d2af70c92ab 1249 return;
darienf 20:6d2af70c92ab 1250 }
darienf 20:6d2af70c92ab 1251 // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
darienf 20:6d2af70c92ab 1252 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in FirmwareVersion
darienf 20:6d2af70c92ab 1253 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1254 FlushQueue();
darienf 20:6d2af70c92ab 1255 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1256 reportID();
darienf 20:6d2af70c92ab 1257 IOBuf[1] = 0; // Firmware version -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1258 writeReadHID();
darienf 20:6d2af70c92ab 1259 VerMajor = IOBuf[2];
darienf 20:6d2af70c92ab 1260 VerMinor = IOBuf[3];
darienf 20:6d2af70c92ab 1261 verYearHundreds = IOBuf[4];
darienf 20:6d2af70c92ab 1262 verYear = IOBuf[5];
darienf 20:6d2af70c92ab 1263 verMonth = IOBuf[6];
darienf 20:6d2af70c92ab 1264 verDay = IOBuf[7];
darienf 20:6d2af70c92ab 1265 //
darienf 20:6d2af70c92ab 1266 // save the recently read values
darienf 20:6d2af70c92ab 1267 _VerMajor = VerMajor;
darienf 20:6d2af70c92ab 1268 _VerMinor = VerMinor;
darienf 20:6d2af70c92ab 1269 _verYearHundreds = verYearHundreds;
darienf 20:6d2af70c92ab 1270 _verYear = verYear;
darienf 20:6d2af70c92ab 1271 _verMonth = verMonth;
darienf 20:6d2af70c92ab 1272 _verDay = verDay;
darienf 20:6d2af70c92ab 1273 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1274 }
darienf 20:6d2af70c92ab 1275 private byte _VerMajor = 0;
darienf 20:6d2af70c92ab 1276 private byte _VerMinor = 0;
darienf 20:6d2af70c92ab 1277 private byte _verYearHundreds = 0;
darienf 20:6d2af70c92ab 1278 private byte _verYear = 0;
darienf 20:6d2af70c92ab 1279 private byte _verMonth = 0;
darienf 20:6d2af70c92ab 1280 private byte _verDay = 0;
darienf 20:6d2af70c92ab 1281
darienf 20:6d2af70c92ab 1282 /// <summary>
darienf 20:6d2af70c92ab 1283 /// <para>Firmware command code 1 OUT = LED (C51F321 P2.2=red, P2.1=green) </para>
darienf 20:6d2af70c92ab 1284 ///
darienf 20:6d2af70c92ab 1285 /// </summary>
darienf 20:6d2af70c92ab 1286 /// <param name="xxxxxxP22P21">0x02=P2.2 Red, 0x01=P2.1 Green</param>
darienf 20:6d2af70c92ab 1287 public void LEDSet(byte xxxxxxP22P21)
darienf 20:6d2af70c92ab 1288 {
darienf 20:6d2af70c92ab 1289 // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers LEDSet(byte xxxxxxP22P21)
darienf 20:6d2af70c92ab 1290 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in LEDSet
darienf 20:6d2af70c92ab 1291 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1292 FlushQueue();
darienf 20:6d2af70c92ab 1293 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1294 reportID();
darienf 20:6d2af70c92ab 1295 IOBuf[1] = 1; // case (1): //LED (C51F321 P2.2=red, P2.1=green) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1296 IOBuf[2] = 0; // case (0): // write
darienf 20:6d2af70c92ab 1297 IOBuf[3] = xxxxxxP22P21;
darienf 20:6d2af70c92ab 1298 // Led2 = IO_BUFFER.Ptr[2+gOffset] & 1; // sbit Led2 = P2^1;
darienf 20:6d2af70c92ab 1299 // Led1 = (IO_BUFFER.Ptr[2+gOffset] & 2) >> 1; // sbit Led1 = P2^2;
darienf 20:6d2af70c92ab 1300 writeHID();
darienf 20:6d2af70c92ab 1301 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1302 }
darienf 20:6d2af70c92ab 1303
darienf 20:6d2af70c92ab 1304 /// <summary>
darienf 20:6d2af70c92ab 1305 /// <para>Firmware command code 1 IN = GPIOP0Get read I/O pins P0.6, P0.7</para>
darienf 20:6d2af70c92ab 1306 ///
darienf 20:6d2af70c92ab 1307 /// </summary>
darienf 20:6d2af70c92ab 1308 /// <param name="xxxxxxP06P07"></param>
darienf 20:6d2af70c92ab 1309 public void GPIOP0Get(out byte xxxxxxP06P07)
darienf 20:6d2af70c92ab 1310 {
darienf 20:6d2af70c92ab 1311 // todo: verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP0Get(out byte xxxxxxP06P07)
darienf 20:6d2af70c92ab 1312 // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: Rename LEDGet(out byte xxxxxxP06P07) to GPIOP0Get(out byte xxxxxxP06P07)
darienf 20:6d2af70c92ab 1313 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP0Get
darienf 20:6d2af70c92ab 1314 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1315 FlushQueue();
darienf 20:6d2af70c92ab 1316 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1317 reportID();
darienf 20:6d2af70c92ab 1318 IOBuf[1] = 1; // case (1): //LED (C51F321 P2.2=red, P2.1=green) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1319 IOBuf[2] = 1; // case (1): // read
darienf 20:6d2af70c92ab 1320 writeReadHID();
darienf 20:6d2af70c92ab 1321 // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
darienf 20:6d2af70c92ab 1322 // IO_BUFFER.Ptr[0 + gOffset] = 0; // error status
darienf 20:6d2af70c92ab 1323 // IO_BUFFER.Ptr[1 + gOffset] = ((P0 & 0x80) >> 7) + ((P0 & 0x40) >> 5);
darienf 20:6d2af70c92ab 1324 xxxxxxP06P07 = IOBuf[2];
darienf 20:6d2af70c92ab 1325 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1326 }
darienf 20:6d2af70c92ab 1327
darienf 20:6d2af70c92ab 1328 /// <summary>
darienf 20:6d2af70c92ab 1329 /// <para>Firmware command code 2 OUT = GPIO configuration (C51F321 P1 and P2) </para>
darienf 20:6d2af70c92ab 1330 ///
darienf 20:6d2af70c92ab 1331 /// </summary>
darienf 20:6d2af70c92ab 1332 /// <param name="P1MDOUT"></param>
darienf 20:6d2af70c92ab 1333 /// <param name="P2MDOUT"></param>
darienf 20:6d2af70c92ab 1334 /// <param name="weakPullupDisable"></param>
darienf 20:6d2af70c92ab 1335 public void GPIOP1P2ConfigSet(byte P1MDOUT, byte P2MDOUT, byte weakPullupDisable)
darienf 20:6d2af70c92ab 1336 {
darienf 20:6d2af70c92ab 1337 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2ConfigSet(byte P1MDOUT, byte P2MDOUT, byte weakPullupDisable)
darienf 20:6d2af70c92ab 1338 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2ConfigSet
darienf 20:6d2af70c92ab 1339 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1340 FlushQueue();
darienf 20:6d2af70c92ab 1341 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1342 reportID();
darienf 20:6d2af70c92ab 1343 IOBuf[1] = 2; // case (2): //GPIO configuration (C51F321 P1 and P2) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1344 IOBuf[2] = 0; // case (0): // write
darienf 20:6d2af70c92ab 1345 IOBuf[3] = P1MDOUT; // P1MDOUT = IO_BUFFER.Ptr[2+gOffset]; // P1 push-pull (1) or open-collector (0)
darienf 20:6d2af70c92ab 1346 IOBuf[4] = P2MDOUT; // P2MDOUT = IO_BUFFER.Ptr[3 + gOffset]; // P2 push-pull (1) or open-collector (0)
darienf 20:6d2af70c92ab 1347 IOBuf[5] = weakPullupDisable; // (IO_BUFFER.Ptr[4 + gOffset] & 1) ? (XBR1 |= 0x80) : (XBR1 &= 0x7F); // weak pull up disable (open collector only); 1 disabled, 0 enabled
darienf 20:6d2af70c92ab 1348 writeHID();
darienf 20:6d2af70c92ab 1349 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1350 }
darienf 20:6d2af70c92ab 1351
darienf 20:6d2af70c92ab 1352 /// <summary>
darienf 20:6d2af70c92ab 1353 /// <para>Firmware command code 2 IN = GPIO configuration (C51F321 P1 and P2) </para>
darienf 20:6d2af70c92ab 1354 ///
darienf 20:6d2af70c92ab 1355 /// </summary>
darienf 20:6d2af70c92ab 1356 /// <param name="P1MDOUT"></param>
darienf 20:6d2af70c92ab 1357 /// <param name="P2MDOUT"></param>
darienf 20:6d2af70c92ab 1358 /// <param name="weakPullupDisable"></param>
darienf 20:6d2af70c92ab 1359 public void GPIOP1P2ConfigGet(out byte P1MDOUT, out byte P2MDOUT, out byte weakPullupDisable)
darienf 20:6d2af70c92ab 1360 {
darienf 20:6d2af70c92ab 1361 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2ConfigGet(out byte P1MDOUT, out byte P2MDOUT, out byte weakPullupDisable)
darienf 20:6d2af70c92ab 1362 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2ConfigGet
darienf 20:6d2af70c92ab 1363 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1364 FlushQueue();
darienf 20:6d2af70c92ab 1365 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1366 reportID();
darienf 20:6d2af70c92ab 1367 IOBuf[1] = 2; // case (2): //GPIO configuration (C51F321 P1 and P2) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1368 IOBuf[2] = 1; // case (1): // read
darienf 20:6d2af70c92ab 1369 writeReadHID();
darienf 20:6d2af70c92ab 1370 // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
darienf 20:6d2af70c92ab 1371 // IO_BUFFER.Ptr[0 + gOffset] = 0; // error status
darienf 20:6d2af70c92ab 1372 // IO_BUFFER.Ptr[1 + gOffset] = P1MDOUT; // P1 push-pull (1) or open-collector (0)
darienf 20:6d2af70c92ab 1373 // IO_BUFFER.Ptr[2 + gOffset] = P2MDOUT; // P2 push-pull (1) or open-collector (0)
darienf 20:6d2af70c92ab 1374 // IO_BUFFER.Ptr[3 + gOffset] = (XBR1 & 0x80) >> 7; // weakPullupDisable
darienf 20:6d2af70c92ab 1375 P1MDOUT = IOBuf[2];
darienf 20:6d2af70c92ab 1376 P2MDOUT = IOBuf[3];
darienf 20:6d2af70c92ab 1377 weakPullupDisable = IOBuf[4];
darienf 20:6d2af70c92ab 1378 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1379 }
darienf 20:6d2af70c92ab 1380
darienf 20:6d2af70c92ab 1381 /// <summary>
darienf 20:6d2af70c92ab 1382 /// <para>Firmware command code 3 OUT = GPIO value (C51F321 P1 and P2) </para>
darienf 20:6d2af70c92ab 1383 ///
darienf 20:6d2af70c92ab 1384 /// </summary>
darienf 20:6d2af70c92ab 1385 /// <param name="P1"></param>
darienf 20:6d2af70c92ab 1386 /// <param name="P2"></param>
darienf 20:6d2af70c92ab 1387 public void GPIOP1P2Out(byte P1, byte P2)
darienf 20:6d2af70c92ab 1388 {
darienf 20:6d2af70c92ab 1389 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2Out(byte P1, byte P2)
darienf 20:6d2af70c92ab 1390 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2Out
darienf 20:6d2af70c92ab 1391 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1392 FlushQueue();
darienf 20:6d2af70c92ab 1393 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1394 reportID();
darienf 20:6d2af70c92ab 1395 IOBuf[1] = 3; // case (3): //GPIO value (C51F321 P1 and P2) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1396 IOBuf[2] = 0; // case (0): // write
darienf 20:6d2af70c92ab 1397 IOBuf[3] = P1; // P1 = IO_BUFFER.Ptr[2 + gOffset]; // P1 HI (1) or LO (0); set P1==1 and P1MDOUT==1 for HI-Z
darienf 20:6d2af70c92ab 1398 IOBuf[4] = P2; // P2 = IO_BUFFER.Ptr[3 + gOffset]; // P2 HI (1) or LO (0); set P2==1 and P1MDOUT==2 for HI-Z
darienf 20:6d2af70c92ab 1399 writeHID();
darienf 20:6d2af70c92ab 1400 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1401 }
darienf 20:6d2af70c92ab 1402
darienf 20:6d2af70c92ab 1403 /// <summary>
darienf 20:6d2af70c92ab 1404 /// <para>Firmware command code 3 IN = GPIO value (C51F321 P1 and P2) </para>
darienf 20:6d2af70c92ab 1405 ///
darienf 20:6d2af70c92ab 1406 /// </summary>
darienf 20:6d2af70c92ab 1407 /// <param name="P1"></param>
darienf 20:6d2af70c92ab 1408 /// <param name="P2"></param>
darienf 20:6d2af70c92ab 1409 public void GPIOP1P2In(out byte P1, out byte P2)
darienf 20:6d2af70c92ab 1410 {
darienf 20:6d2af70c92ab 1411 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers GPIOP1P2In(out byte P1, out byte P2)
darienf 20:6d2af70c92ab 1412 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in GPIOP1P2In
darienf 20:6d2af70c92ab 1413 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1414 FlushQueue();
darienf 20:6d2af70c92ab 1415 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1416 reportID();
darienf 20:6d2af70c92ab 1417 IOBuf[1] = 3; // case (3): //GPIO value (C51F321 P1 and P2) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1418 IOBuf[2] = 1; // case (1): // read
darienf 20:6d2af70c92ab 1419 writeReadHID();
darienf 20:6d2af70c92ab 1420 // temp = XBR1;
darienf 20:6d2af70c92ab 1421 // if (IO_BUFFER.Ptr[2+gOffset] & 1) // enable weak pullups in case GP pins are open-collector and not connected to anything (which would falsely give '0')
darienf 20:6d2af70c92ab 1422 // {
darienf 20:6d2af70c92ab 1423 // XBR1 &= 0x7F;
darienf 20:6d2af70c92ab 1424 // Timer0_Init(HALFMS);
darienf 20:6d2af70c92ab 1425 // T0_Wait(2);
darienf 20:6d2af70c92ab 1426 // }
darienf 20:6d2af70c92ab 1427 // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
darienf 20:6d2af70c92ab 1428 // IO_BUFFER.Ptr[0+gOffset] = 0; // error status
darienf 20:6d2af70c92ab 1429 // IO_BUFFER.Ptr[1+gOffset] = P1; // P1 HI (1) or LO (0)
darienf 20:6d2af70c92ab 1430 // IO_BUFFER.Ptr[2+gOffset] = P2; // P2 HI (1) or LO (0)
darienf 20:6d2af70c92ab 1431 // XBR1 = temp;
darienf 20:6d2af70c92ab 1432 // SendPacket(); // no need to check for internal call since only the GUI will request a read through this function
darienf 20:6d2af70c92ab 1433 P1 = IOBuf[2];
darienf 20:6d2af70c92ab 1434 P2 = IOBuf[3];
darienf 20:6d2af70c92ab 1435 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1436 }
darienf 20:6d2af70c92ab 1437
darienf 20:6d2af70c92ab 1438 /// <summary>
darienf 20:6d2af70c92ab 1439 /// <para>Firmware command code 4 OUT = I2C configuration </para>
darienf 20:6d2af70c92ab 1440 /// (IO_BUFFER.Ptr[3+gOffset] &amp; 1) ? (SMB0CF |= 0x10) : (SMB0CF &amp;= 0xEF)
darienf 20:6d2af70c92ab 1441 /// </summary>
darienf 20:6d2af70c92ab 1442 /// <param name="gI2Cflags">bit0 == 1: repeated start</param>
darienf 20:6d2af70c92ab 1443 /// <param name="EXTHOLD">set EXTHOLD bit (SMBus setup / hold time extension)</param>
darienf 20:6d2af70c92ab 1444 /// <param name="ClearSDAbyTogglingSCL">clear SDA by toggling SCL</param>
darienf 20:6d2af70c92ab 1445 public void I2CConfigSet(byte gI2Cflags, byte EXTHOLD, byte ClearSDAbyTogglingSCL)
darienf 20:6d2af70c92ab 1446 {
darienf 20:6d2af70c92ab 1447 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CConfigSet(byte gI2Cflags, byte EXTHOLD, byte ClearSDAbyTogglingSCL)
darienf 20:6d2af70c92ab 1448 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigSet
darienf 20:6d2af70c92ab 1449 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1450 FlushQueue();
darienf 20:6d2af70c92ab 1451 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1452 reportID();
darienf 20:6d2af70c92ab 1453 IOBuf[1] = 4; // case (4): //I2C configuration -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1454 IOBuf[2] = 0; // case (0): // write
darienf 20:6d2af70c92ab 1455 IOBuf[3] = gI2Cflags; // gI2Cflags = IO_BUFFER.Ptr[2+gOffset];
darienf 20:6d2af70c92ab 1456 // // bit0 == 1: repeated start (versus stop/start) after write before read (applies to random read only)
darienf 20:6d2af70c92ab 1457 // // bit1 == 1: start random read with a write, but end the write right away without sending reg address (emulate Jungo dongle for debug purposes)
darienf 20:6d2af70c92ab 1458 // // bit2 == 1: repeat transaction if slave NACKs (suggest not to use this)
darienf 20:6d2af70c92ab 1459 // // all flags are OR'd
darienf 20:6d2af70c92ab 1460 IOBuf[4] = EXTHOLD; // (IO_BUFFER.Ptr[3+gOffset] & 1) ? (SMB0CF |= 0x10) : (SMB0CF &= 0xEF); // set EXTHOLD bit (SMBus setup / hold time extension)
darienf 20:6d2af70c92ab 1461 IOBuf[5] = ClearSDAbyTogglingSCL; // if (IO_BUFFER.Ptr[4+gOffset] & 1) // clear SDA by toggling SCL
darienf 20:6d2af70c92ab 1462 // {s
darienf 20:6d2af70c92ab 1463 // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
darienf 20:6d2af70c92ab 1464 // IO_BUFFER.Ptr[0+gOffset] = 0; // transaction error status
darienf 20:6d2af70c92ab 1465 // IO_BUFFER.Ptr[1+gOffset] = clearSDA(); // clearSDA error status
darienf 20:6d2af70c92ab 1466 // SendPacket(); // send status of clearing SDA to host
darienf 20:6d2af70c92ab 1467 // }
darienf 20:6d2af70c92ab 1468 writeHID();
darienf 20:6d2af70c92ab 1469 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1470 }
darienf 20:6d2af70c92ab 1471
darienf 20:6d2af70c92ab 1472 /// <summary>
darienf 20:6d2af70c92ab 1473 /// <para>Firmware command code 4 IN = I2C configuration </para>
darienf 20:6d2af70c92ab 1474 /// (IO_BUFFER.Ptr[3+gOffset] &amp; 1) ? (SMB0CF |= 0x10) : (SMB0CF &amp;= 0xEF)
darienf 20:6d2af70c92ab 1475 /// </summary>
darienf 20:6d2af70c92ab 1476 /// <param name="gI2Cflags">bit0 == 1: repeated start</param>
darienf 20:6d2af70c92ab 1477 /// <param name="EXTHOLD">SMB0CF &amp; 0x10</param>
darienf 20:6d2af70c92ab 1478 public void I2CConfigGet(out byte gI2Cflags, out byte EXTHOLD)
darienf 20:6d2af70c92ab 1479 {
darienf 20:6d2af70c92ab 1480 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CConfigGet(out byte gI2Cflags, out byte EXTHOLD)
darienf 20:6d2af70c92ab 1481 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigGet
darienf 20:6d2af70c92ab 1482 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1483 FlushQueue();
darienf 20:6d2af70c92ab 1484 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1485 reportID();
darienf 20:6d2af70c92ab 1486 IOBuf[1] = 4; // case (4): //I2C configuration -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1487 IOBuf[2] = 1; // case (1): // read
darienf 20:6d2af70c92ab 1488 writeReadHID();
darienf 20:6d2af70c92ab 1489 // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
darienf 20:6d2af70c92ab 1490 // IO_BUFFER.Ptr[0+gOffset] = 0; // error status
darienf 20:6d2af70c92ab 1491 // IO_BUFFER.Ptr[1+gOffset] = gI2Cflags;
darienf 20:6d2af70c92ab 1492 // IO_BUFFER.Ptr[2+gOffset] = (SMB0CF & 0x10) >> 4; // EXTHOLD
darienf 20:6d2af70c92ab 1493 gI2Cflags = IOBuf[2];
darienf 20:6d2af70c92ab 1494 EXTHOLD = IOBuf[3];
darienf 20:6d2af70c92ab 1495 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1496 }
darienf 20:6d2af70c92ab 1497
darienf 20:6d2af70c92ab 1498 /// <summary>
darienf 20:6d2af70c92ab 1499 /// <para>Firmware command code 5 OUT = I2C clock rate (number of counts to overflow) </para>
darienf 20:6d2af70c92ab 1500 /// <para>SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</para>
darienf 20:6d2af70c92ab 1501 /// </summary>
darienf 20:6d2af70c92ab 1502 /// <param name="ReloadTH1">SMBus timer's count value: ReloadTH1 = (byte)(0.5 + (TimerClockMHz * 1000 / SCL_kHz))</param>
darienf 20:6d2af70c92ab 1503 public void I2CClockSet(byte ReloadTH1)
darienf 20:6d2af70c92ab 1504 {
darienf 20:6d2af70c92ab 1505 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CClockSet(byte ReloadTH1)
darienf 20:6d2af70c92ab 1506 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CClockSet
darienf 20:6d2af70c92ab 1507 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1508 FlushQueue();
darienf 20:6d2af70c92ab 1509 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1510 reportID();
darienf 20:6d2af70c92ab 1511 IOBuf[1] = 5; // case (5): //I2C clock rate (number of counts to overflow) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1512 IOBuf[2] = 0; // case (0): // write
darienf 20:6d2af70c92ab 1513 IOBuf[3] = ReloadTH1;
darienf 20:6d2af70c92ab 1514 // gSMBusClkFreq = gTimer1ClkFreq / 3.0 / IO_BUFFER.Ptr[2+gOffset]; //GUI sends the number of counts to overflow; HID must calculate the desired SMBus clock frequency
darienf 20:6d2af70c92ab 1515 // TR1 = 0;
darienf 20:6d2af70c92ab 1516 // Timer1_Init();
darienf 20:6d2af70c92ab 1517 writeHID();
darienf 20:6d2af70c92ab 1518 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1519 }
darienf 20:6d2af70c92ab 1520
darienf 20:6d2af70c92ab 1521 /// <summary>
darienf 20:6d2af70c92ab 1522 /// <para>Firmware command code 5 IN = I2C clock rate (number of counts to overflow) </para>
darienf 20:6d2af70c92ab 1523 /// <para>SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</para>
darienf 20:6d2af70c92ab 1524 /// </summary>
darienf 20:6d2af70c92ab 1525 /// <param name="TimerClockMHz">SMBus timer's clock frequency (in MHz); expect constant 8</param>
darienf 20:6d2af70c92ab 1526 /// <param name="ReloadTH1">SMBus timer's count value: SCL_kHz = TimerClockMHz * 1000 / ReloadTH1</param>
darienf 20:6d2af70c92ab 1527 public void I2CClockGet(out byte TimerClockMHz, out byte ReloadTH1)
darienf 20:6d2af70c92ab 1528 {
darienf 20:6d2af70c92ab 1529 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers I2CClockGet(out byte TimerClockMHz, out byte ReloadTH1)
darienf 20:6d2af70c92ab 1530 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CClockGet
darienf 20:6d2af70c92ab 1531 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1532 FlushQueue();
darienf 20:6d2af70c92ab 1533 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1534 reportID();
darienf 20:6d2af70c92ab 1535 IOBuf[1] = 5; // case (5): //I2C clock rate (number of counts to overflow) -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1536 IOBuf[2] = 1; // case (1): // read
darienf 20:6d2af70c92ab 1537 writeReadHID();
darienf 20:6d2af70c92ab 1538 // case (1): // read -- myHID.I2CClockGet(out TimerClockMHz, out ReloadTH1)
darienf 20:6d2af70c92ab 1539 // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
darienf 20:6d2af70c92ab 1540 // IO_BUFFER.Ptr[0+gOffset] = 0; // error status
darienf 20:6d2af70c92ab 1541 // IO_BUFFER.Ptr[1+gOffset] = gTimer1ClkFreq / 1000000 / 3; //return the SMBus timer's clock frequency (in MHz)
darienf 20:6d2af70c92ab 1542 // IO_BUFFER.Ptr[2+gOffset] = 256-TH1; //and return the SMBus timer's count value in order to calculate the SMBus clock frequency; TH1 is the reload value that gets loaded into TL0 upon overflow; the reload value is 256-TH1 since (0)-TH1 gives the proper number of counts to overflow
darienf 20:6d2af70c92ab 1543 // SendPacket(); // no need to check for internal call since only the GUI will request a read through this function
darienf 20:6d2af70c92ab 1544 // break;
darienf 20:6d2af70c92ab 1545 TimerClockMHz = IOBuf[2];
darienf 20:6d2af70c92ab 1546 ReloadTH1 = IOBuf[3];
darienf 20:6d2af70c92ab 1547 // todo: OS24EVK-24 how determine SCL from TimerClockMHZ? Observed I2CClockGet() TimerClockMHz = 8 when SCL = 400kHz.
darienf 20:6d2af70c92ab 1548 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1549 }
darienf 20:6d2af70c92ab 1550
darienf 20:6d2af70c92ab 1551 /// <summary>
darienf 20:6d2af70c92ab 1552 /// <para>Firmware command code 6 OUT = I2C transaction </para>
darienf 20:6d2af70c92ab 1553 ///
darienf 20:6d2af70c92ab 1554 /// </summary>
darienf 20:6d2af70c92ab 1555 /// <param name="deviceAddress">I2C device address, 8-bit left-justified (LSB=R/w bit)</param>
darienf 20:6d2af70c92ab 1556 /// <param name="numDataBytes"></param>
darienf 20:6d2af70c92ab 1557 /// <param name="numRegBytes"></param>
darienf 20:6d2af70c92ab 1558 /// <param name="data"></param>
darienf 20:6d2af70c92ab 1559 /// <param name="reg"></param>
darienf 20:6d2af70c92ab 1560 /// <param name="ignoreNACK"></param>
darienf 20:6d2af70c92ab 1561 public void I2CWrite(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] data, byte[] reg, bool ignoreNACK = false)
darienf 20:6d2af70c92ab 1562 {
darienf 20:6d2af70c92ab 1563 // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
darienf 20:6d2af70c92ab 1564 // alias of existing function
darienf 20:6d2af70c92ab 1565 // IOBuf[1] = 6; // case (6): // I2C transaction -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1566 writeI2C(deviceAddress, numDataBytes, numRegBytes, data, reg, ignoreNACK);
darienf 20:6d2af70c92ab 1567 }
darienf 20:6d2af70c92ab 1568
darienf 20:6d2af70c92ab 1569 /// <summary>
darienf 20:6d2af70c92ab 1570 /// <para>Firmware command code 6 IN = I2C transaction </para>
darienf 20:6d2af70c92ab 1571 ///
darienf 20:6d2af70c92ab 1572 /// </summary>
darienf 20:6d2af70c92ab 1573 /// <param name="deviceAddress">I2C device address, 8-bit left-justified (LSB=R/w bit)</param>
darienf 20:6d2af70c92ab 1574 /// <param name="numDataBytes"></param>
darienf 20:6d2af70c92ab 1575 /// <param name="numRegBytes"></param>
darienf 20:6d2af70c92ab 1576 /// <param name="readData"></param>
darienf 20:6d2af70c92ab 1577 /// <param name="reg"></param>
darienf 20:6d2af70c92ab 1578 /// <param name="ignoreNACK"></param>
darienf 20:6d2af70c92ab 1579 /// <returns>status value; may be HID.I2C_NACK_ERROR if ignoreNACK parameter is true</returns>
darienf 20:6d2af70c92ab 1580 public int I2CRead(byte deviceAddress, byte numDataBytes, byte numRegBytes, byte[] readData, byte[] reg, bool ignoreNACK = false)
darienf 20:6d2af70c92ab 1581 {
darienf 20:6d2af70c92ab 1582 // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
darienf 20:6d2af70c92ab 1583 // alias of existing function
darienf 20:6d2af70c92ab 1584 // IOBuf[1] = 6; // case (6): // I2C transaction -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1585 return readI2C(deviceAddress, numDataBytes, numRegBytes, readData, reg, ignoreNACK);
darienf 20:6d2af70c92ab 1586 }
darienf 20:6d2af70c92ab 1587
darienf 20:6d2af70c92ab 1588 /// <summary>
darienf 20:6d2af70c92ab 1589 /// <para>Firmware command code 7 OUT = SPI config </para>
darienf 20:6d2af70c92ab 1590 /// ((SPI0CFG &amp; 0x30) &gt;&gt; 4) + (SPI0CN &amp; 4)
darienf 20:6d2af70c92ab 1591 /// </summary>
darienf 20:6d2af70c92ab 1592 /// <param name="config"></param>
darienf 20:6d2af70c92ab 1593 public void SPIConfigSet(byte config)
darienf 20:6d2af70c92ab 1594 {
darienf 20:6d2af70c92ab 1595 // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIConfigSet(byte config)
darienf 20:6d2af70c92ab 1596 // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
darienf 20:6d2af70c92ab 1597 // IOBuf[1] = 7; // case (7): // SPI config -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1598 }
darienf 20:6d2af70c92ab 1599
darienf 20:6d2af70c92ab 1600 /// <summary>
darienf 20:6d2af70c92ab 1601 /// <para>Firmware command code 7 IN = SPI config </para>
darienf 20:6d2af70c92ab 1602 /// ((SPI0CFG &amp; 0x30) &gt;&gt; 4) + (SPI0CN &amp; 4)
darienf 20:6d2af70c92ab 1603 /// </summary>
darienf 20:6d2af70c92ab 1604 /// <param name="config"></param>
darienf 20:6d2af70c92ab 1605 public void SPIConfigGet(out byte config)
darienf 20:6d2af70c92ab 1606 {
darienf 20:6d2af70c92ab 1607 // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIConfigGet(out byte config)
darienf 20:6d2af70c92ab 1608 // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
darienf 20:6d2af70c92ab 1609 // IOBuf[1] = 7; // case (7): // SPI config -- HID.cs void writeI2C() readI2C() -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1610 config = 0;
darienf 20:6d2af70c92ab 1611 }
darienf 20:6d2af70c92ab 1612
darienf 20:6d2af70c92ab 1613 /// <summary>
darienf 20:6d2af70c92ab 1614 /// <para>Firmware command code 8 OUT = SPI clock rate </para>
darienf 20:6d2af70c92ab 1615 /// </summary>
darienf 20:6d2af70c92ab 1616 /// <param name="SPI0CKR"></param>
darienf 20:6d2af70c92ab 1617 public void SPIClockSet(byte SPI0CKR)
darienf 20:6d2af70c92ab 1618 {
darienf 20:6d2af70c92ab 1619 // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIClockSet(byte SPI0CKR)
darienf 20:6d2af70c92ab 1620 // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
darienf 20:6d2af70c92ab 1621 // IOBuf[1] = 8; // case (8): // SPI clock rate -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1622 }
darienf 20:6d2af70c92ab 1623
darienf 20:6d2af70c92ab 1624 /// <summary>
darienf 20:6d2af70c92ab 1625 /// <para>Firmware command code 8 IN = SPI clock rate </para>
darienf 20:6d2af70c92ab 1626 /// </summary>
darienf 20:6d2af70c92ab 1627 /// <param name="SPI0CKR"></param>
darienf 20:6d2af70c92ab 1628 public void SPIClockGet(out byte SPI0CKR)
darienf 20:6d2af70c92ab 1629 {
darienf 20:6d2af70c92ab 1630 // todo: https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers SPIClockGet(out byte SPI0CKR)
darienf 20:6d2af70c92ab 1631 // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
darienf 20:6d2af70c92ab 1632 // IOBuf[1] = 8; // case (8): // SPI clock rate -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1633 SPI0CKR = 0;
darienf 20:6d2af70c92ab 1634 }
darienf 20:6d2af70c92ab 1635
darienf 20:6d2af70c92ab 1636 /// <summary>
darienf 20:6d2af70c92ab 1637 /// <para>Firmware command code 9 = SPI transaction </para>
darienf 20:6d2af70c92ab 1638 /// </summary>
darienf 20:6d2af70c92ab 1639 /// <param name="mosiData">SPI MOSI (Master-Out, Slave-In) data to write into slave device</param>
darienf 20:6d2af70c92ab 1640 /// <param name="misoBuffer">SPI MISO (Master-In, Slave-Out) data buffer containing data bytes received from slave device
darienf 20:6d2af70c92ab 1641 /// (size will be allocated same size as mosiData)</param>
darienf 20:6d2af70c92ab 1642 public void SPITransfer(byte[] mosiData, out byte[] misoBuffer)
darienf 20:6d2af70c92ab 1643 {
darienf 20:6d2af70c92ab 1644 // verify: https://jira.maxim-ic.com/browse/OS24EVK-24 SPITransfer(byte[] mosiData, out byte[] misoBuffer)
darienf 20:6d2af70c92ab 1645 // Although the MAX30101EVKIT firmware will accept HID SPI commands, this firmware doesn't support SPI interface.
darienf 20:6d2af70c92ab 1646 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in I2CConfigSet
darienf 20:6d2af70c92ab 1647 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1648 FlushQueue();
darienf 20:6d2af70c92ab 1649 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1650 reportID();
darienf 20:6d2af70c92ab 1651 // assign default out values in case of failure
darienf 20:6d2af70c92ab 1652 int byteCount = mosiData.Length;
darienf 20:6d2af70c92ab 1653 byte num_bytes = (byte)(byteCount & 0xFF);
darienf 20:6d2af70c92ab 1654 misoBuffer = new byte[byteCount];
darienf 20:6d2af70c92ab 1655 for (int byteIndex = 0; byteIndex < byteCount; byteIndex++)
darienf 20:6d2af70c92ab 1656 {
darienf 20:6d2af70c92ab 1657 // initial dummy data
darienf 20:6d2af70c92ab 1658 misoBuffer[byteIndex] = 0x55;
darienf 20:6d2af70c92ab 1659 }
darienf 20:6d2af70c92ab 1660 IOBuf[1] = 9; // case (9): // SPI transaction -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1661 //IOBuf[8] = x; // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
darienf 20:6d2af70c92ab 1662 for (uint byteIndex = 0; byteIndex < num_bytes; byteIndex++)
darienf 20:6d2af70c92ab 1663 {
darienf 20:6d2af70c92ab 1664 IOBuf[8 + byteIndex] = (byte)(mosiData[byteIndex]);
darienf 20:6d2af70c92ab 1665 }
darienf 20:6d2af70c92ab 1666 //switch (SPImode)
darienf 20:6d2af70c92ab 1667 //{
darienf 20:6d2af70c92ab 1668 // case 0:
darienf 20:6d2af70c92ab 1669 IOBuf[2] = 0; // IO_BUFFER.Ptr[1+gOffset] -- 0 for SPI_mode0: multi-byte SPI transfer.
darienf 20:6d2af70c92ab 1670 IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- not used
darienf 20:6d2af70c92ab 1671 IOBuf[4] = 0; // IO_BUFFER.Ptr[3+gOffset] -- phase_change // !=0 enable changing the clock phase. some slaves change phase between write/read
darienf 20:6d2af70c92ab 1672 IOBuf[5] = 0; // IO_BUFFER.Ptr[4+gOffset] -- phase_change_byte // byte index where phase change should happen
darienf 20:6d2af70c92ab 1673 IOBuf[6] = num_bytes; // IO_BUFFER.Ptr[5+gOffset] -- num_bytes
darienf 20:6d2af70c92ab 1674 IOBuf[7] = 0; // IO_BUFFER.Ptr[6+gOffset] -- not used
darienf 20:6d2af70c92ab 1675 // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
darienf 20:6d2af70c92ab 1676 // SPI_mode0(IO_BUFFER.Ptr[3 + gOffset], IO_BUFFER.Ptr[4 + gOffset], IO_BUFFER.Ptr[5 + gOffset], IO_BUFFER.Ptr);
darienf 20:6d2af70c92ab 1677 // break;
darienf 20:6d2af70c92ab 1678 //case 1:
darienf 20:6d2af70c92ab 1679 // IOBuf[2] = 1; // IO_BUFFER.Ptr[1+gOffset] -- 1 for SPI_mode1: two-byte SPI transfer. read flag: enable changing the clock phase on first byte and changing phase between first and second byte
darienf 20:6d2af70c92ab 1680 // IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- read flag
darienf 20:6d2af70c92ab 1681 // // IO_BUFFER.Ptr[3+gOffset] -- not used
darienf 20:6d2af70c92ab 1682 // // IO_BUFFER.Ptr[4+gOffset] -- not used
darienf 20:6d2af70c92ab 1683 // // IO_BUFFER.Ptr[5+gOffset] -- not used; num_bytes = 2
darienf 20:6d2af70c92ab 1684 // // IO_BUFFER.Ptr[6+gOffset] -- not used
darienf 20:6d2af70c92ab 1685 // // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
darienf 20:6d2af70c92ab 1686 // // SPI_mode1(temp, IO_BUFFER.Ptr);
darienf 20:6d2af70c92ab 1687 // break;
darienf 20:6d2af70c92ab 1688 //case 2:
darienf 20:6d2af70c92ab 1689 // IOBuf[2] = 2; // IO_BUFFER.Ptr[1+gOffset] --2 for SPI_mode2: two-byte SPI transfer. read flag: enable changing the clock phase on first byte and sampling the LSb after the second byte read
darienf 20:6d2af70c92ab 1690 // IOBuf[3] = 0; // IO_BUFFER.Ptr[2+gOffset] -- read flag
darienf 20:6d2af70c92ab 1691 // // IO_BUFFER.Ptr[3+gOffset] -- not used
darienf 20:6d2af70c92ab 1692 // // IO_BUFFER.Ptr[4+gOffset] -- not used
darienf 20:6d2af70c92ab 1693 // // IO_BUFFER.Ptr[5+gOffset] -- not used; num_bytes = 2
darienf 20:6d2af70c92ab 1694 // // IO_BUFFER.Ptr[6+gOffset] -- not used
darienf 20:6d2af70c92ab 1695 // // IO_BUFFER.Ptr[7+gOffset] -- first byte of data starts on the (7 + offset) byte
darienf 20:6d2af70c92ab 1696 // // SPI_mode2(temp, IO_BUFFER.Ptr);
darienf 20:6d2af70c92ab 1697 // break;
darienf 20:6d2af70c92ab 1698 //}
darienf 20:6d2af70c92ab 1699 writeHID();
darienf 20:6d2af70c92ab 1700 // IO_BUFFER.Ptr[0] = SHORT_REPORT_ID;
darienf 20:6d2af70c92ab 1701 // IO_BUFFER.Ptr[0+gOffset] = 0; // error status
darienf 20:6d2af70c92ab 1702 // IO_BUFFER.Ptr[1+gOffset] = gI2Cflags;
darienf 20:6d2af70c92ab 1703 // IO_BUFFER.Ptr[2+gOffset] = (SMB0CF & 0x10) >> 4; // EXTHOLD
darienf 20:6d2af70c92ab 1704 //gI2Cflags = IOBuf[2];
darienf 20:6d2af70c92ab 1705 //EXTHOLD = IOBuf[3];
darienf 20:6d2af70c92ab 1706 for (uint byteIndex = 0; byteIndex < byteCount; byteIndex++)
darienf 20:6d2af70c92ab 1707 {
darienf 20:6d2af70c92ab 1708 misoBuffer[byteIndex] = IOBuf[byteIndex + 2];
darienf 20:6d2af70c92ab 1709 }
darienf 20:6d2af70c92ab 1710 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1711 }
darienf 20:6d2af70c92ab 1712
darienf 20:6d2af70c92ab 1713 /// <summary>
darienf 20:6d2af70c92ab 1714 /// <para>Firmware command code 23 OUT = enable INT0 (or Mock HID FIFO data diagnostic) </para>
darienf 20:6d2af70c92ab 1715 /// <para>
darienf 20:6d2af70c92ab 1716 /// - INT0Enable(0) disabled (EX0=0)
darienf 20:6d2af70c92ab 1717 /// - INT0Enable(1) real hardware (EX0=1)
darienf 20:6d2af70c92ab 1718 /// - INT0Enable(2) Mock HID x1 channel 101, 102, 103, ...
darienf 20:6d2af70c92ab 1719 /// - INT0Enable(3) Mock HID x2 channels 101, 201, 102, 202, 103, 203, ...
darienf 20:6d2af70c92ab 1720 /// - INT0Enable(4) Mock HID x3 channels 101, 201, 301, 102, 202, 302, 103, 203, 303, ...
darienf 20:6d2af70c92ab 1721 /// - INT0Enable(5) Mock HID x4 channels 101, 201, 301, 401, 102, 202, 302, 402, 103, 203, 303, 403, ...
darienf 20:6d2af70c92ab 1722 /// </para>
darienf 20:6d2af70c92ab 1723 /// </summary>
darienf 20:6d2af70c92ab 1724 /// <param name="EX0"></param>
darienf 20:6d2af70c92ab 1725 public void INT0Enable(byte EX0)
darienf 20:6d2af70c92ab 1726 {
darienf 20:6d2af70c92ab 1727 // https://jira.maxim-ic.com/browse/OS24EVK-24 Refactor: HID report enum and wrappers
darienf 20:6d2af70c92ab 1728 // reset report counter in the HID and enable INT0
darienf 20:6d2af70c92ab 1729 // verify: https://jira.maxim-ic.com/browse/OS24EVK-57 mutex lock HID.IOBuf[] in INT0Enable
darienf 20:6d2af70c92ab 1730 mutexGuardIOBuf.WaitOne(); // Wait until it is safe to enter.
darienf 20:6d2af70c92ab 1731 FlushQueue();
darienf 20:6d2af70c92ab 1732 Array.Clear(IOBuf, 0, IOBuf.Length);
darienf 20:6d2af70c92ab 1733 reportID();
darienf 20:6d2af70c92ab 1734 IOBuf[1] = 23; // enable INT0 -- see F3xx_USB0_ReportHandler.c void OUT_REPORT_HANDLER(int internalCall)
darienf 20:6d2af70c92ab 1735 IOBuf[2] = EX0; // reportTypeFlag; // 1;
darienf 20:6d2af70c92ab 1736 writeHID();
darienf 20:6d2af70c92ab 1737 _firmwareINT0Enabled = EX0;
darienf 20:6d2af70c92ab 1738 mutexGuardIOBuf.ReleaseMutex(); // Release the Mutex.
darienf 20:6d2af70c92ab 1739 }
darienf 20:6d2af70c92ab 1740 private byte _firmwareINT0Enabled = 0;
darienf 20:6d2af70c92ab 1741 public byte FirmwareINT0Enabled { get { return _firmwareINT0Enabled; } }
darienf 20:6d2af70c92ab 1742
darienf 20:6d2af70c92ab 1743 /// <summary>
darienf 20:6d2af70c92ab 1744 /// Search for a device attached to I2C bus,
darienf 20:6d2af70c92ab 1745 /// given a list of poossible device addresses,
darienf 20:6d2af70c92ab 1746 /// and a constant device ID register to test.
darienf 20:6d2af70c92ab 1747 /// </summary>
darienf 20:6d2af70c92ab 1748 /// <param name="I2C_DeviceAddressList_8bitLeftJustified">List of possible I2C device addresses to test. I2C device addresses are 8-bit left-justified (LSB=R/w bit)</param>
darienf 20:6d2af70c92ab 1749 /// <param name="DeviceId_RegAddress">device register address of a constant "Device ID" register</param>
darienf 20:6d2af70c92ab 1750 /// <param name="DeviceId_RegValue_Expect">register value of the constant "Device ID" register</param>
darienf 20:6d2af70c92ab 1751 /// <returns>I2C device addresses, or 0 if not found</returns>
darienf 20:6d2af70c92ab 1752 public byte SearchI2CdeviceAddressList(byte[] I2C_DeviceAddressList_8bitLeftJustified, byte DeviceId_RegAddress, byte DeviceId_RegValue_Expect)
darienf 20:6d2af70c92ab 1753 {
darienf 20:6d2af70c92ab 1754 // https://jira.maxim-ic.com/browse/OS24EVK-57 accelerometer support: SearchI2CdeviceAddressList optional I2C device
darienf 20:6d2af70c92ab 1755 foreach (byte test_I2C_Address in I2C_DeviceAddressList_8bitLeftJustified)
darienf 20:6d2af70c92ab 1756 {
darienf 20:6d2af70c92ab 1757 //try
darienf 20:6d2af70c92ab 1758 //{
darienf 20:6d2af70c92ab 1759 byte[] data = new byte[2];
darienf 20:6d2af70c92ab 1760 byte[] reg = new byte[1];
darienf 20:6d2af70c92ab 1761 reg[0] = (byte)DeviceId_RegAddress;
darienf 20:6d2af70c92ab 1762 // readI2C should already take care of mutex lock / unlock
darienf 20:6d2af70c92ab 1763 // https://jira.maxim-ic.com/browse/OS24EVK-59 avoid NACK exception in SearchI2CdeviceAddressList
darienf 20:6d2af70c92ab 1764 bool ignoreNACK = true;
darienf 20:6d2af70c92ab 1765 int status = readI2C(test_I2C_Address, 2, 1, data, reg, ignoreNACK);
darienf 20:6d2af70c92ab 1766 if (status == HID.I2C_NACK_ERROR)
darienf 20:6d2af70c92ab 1767 {
darienf 20:6d2af70c92ab 1768 continue;
darienf 20:6d2af70c92ab 1769 }
darienf 20:6d2af70c92ab 1770 else
darienf 20:6d2af70c92ab 1771 {
darienf 20:6d2af70c92ab 1772 byte DeviceId_RegValue_Actual = data[0];
darienf 20:6d2af70c92ab 1773 if (DeviceId_RegValue_Actual == DeviceId_RegValue_Expect)
darienf 20:6d2af70c92ab 1774 {
darienf 20:6d2af70c92ab 1775 return test_I2C_Address;
darienf 20:6d2af70c92ab 1776 }
darienf 20:6d2af70c92ab 1777 }
darienf 20:6d2af70c92ab 1778 //}
darienf 20:6d2af70c92ab 1779 //catch (Exception)
darienf 20:6d2af70c92ab 1780 //{
darienf 20:6d2af70c92ab 1781 // // myHID.readI2C can throw Exception("invalid I2C address");
darienf 20:6d2af70c92ab 1782 //}
darienf 20:6d2af70c92ab 1783 }
darienf 20:6d2af70c92ab 1784 return 0;
darienf 20:6d2af70c92ab 1785 }
darienf 20:6d2af70c92ab 1786
darienf 20:6d2af70c92ab 1787 }
darienf 20:6d2af70c92ab 1788 }