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