Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed MAX14720 MAX30205 USBDevice
NimitzHID.cs
00001 using Microsoft.VisualBasic; 00002 using System; 00003 using System.Collections; 00004 using System.Data; 00005 using System.Diagnostics; 00006 using System.Drawing; 00007 using System.Windows.Forms; 00008 using Microsoft.Win32.SafeHandles; 00009 using System.Runtime.InteropServices; 00010 00011 00012 namespace SimpleHID 00013 { 00014 class NimitzHID 00015 { 00016 internal const byte COMMAND_SUCCEED = 0xEE; 00017 internal const byte COMMAND_FAILED = 0xFA; 00018 00019 // private IntPtr deviceNotificationHandle; 00020 // private Boolean exclusiveAccess; 00021 private SafeFileHandle hidHandle; 00022 private String hidUsage; 00023 private Boolean myDeviceDetected; 00024 private String myDevicePathName; 00025 private SafeFileHandle readHandle; 00026 private SafeFileHandle writeHandle; 00027 00028 // private Debugging MyDebugging = new Debugging(); // For viewing results of API calls via Debug.Write. 00029 private Guid hidGuid; 00030 private IntPtr deviceNotificationHandle = System.IntPtr.Zero; 00031 private HID myHID; 00032 00033 //internal FrmMain FrmMy; 00034 00035 /// <summary> 00036 /// Define a class of delegates that point to the Hid.ReportIn.Read function. 00037 /// The delegate has the same parameters as Hid.ReportIn.Read. 00038 /// Used for asynchronous reads from the device. 00039 /// </summary> 00040 00041 private delegate void ReadInputReportDelegate(SafeFileHandle hidHandle, SafeFileHandle readHandle, SafeFileHandle writeHandle, ref Boolean myDeviceDetected, ref Byte[] readBuffer, ref Boolean success); 00042 00043 // This delegate has the same parameters as AccessForm. 00044 // Used in accessing the application's form from a different thread. 00045 00046 private delegate void MarshalToForm(String action, String textToAdd); 00047 /// <summary> 00048 /// Uses a series of API calls to locate a HID-class device 00049 /// by its Vendor ID and Product ID. 00050 /// </summary> 00051 /// 00052 /// <returns> 00053 /// True if the device is detected, False if not detected. 00054 /// </returns> 00055 00056 internal Boolean OpenNimitzH() 00057 { 00058 Boolean deviceFound = false; 00059 String[] devicePathName = new String[128]; 00060 Guid hidGuid = Guid.Empty; 00061 Int32 memberIndex = 0; 00062 Int32 myProductID = 0x1365; 00063 Int32 myVendorID = 0x0B6A; 00064 Boolean success = false; 00065 00066 myDeviceDetected = false; 00067 00068 myHID.findHIDs(); 00069 00070 // *** 00071 // API function: 'HidD_GetHidGuid 00072 // Purpose: Retrieves the interface class GUID for the HID class. 00073 // Accepts: 'A System.Guid object for storing the GUID. 00074 // *** 00075 00076 Hid.HidD_GetHidGuid(ref hidGuid); 00077 00078 // Fill an array with the device path names of all attached HIDs. 00079 00080 deviceFound = MyDeviceManagement.FindDeviceFromGuid(hidGuid, ref devicePathName); 00081 00082 // If there is at least one HID, attempt to read the Vendor ID and Product ID 00083 // of each device until there is a match or all devices have been examined. 00084 00085 if (deviceFound) 00086 { 00087 memberIndex = 0; 00088 00089 do 00090 { 00091 // *** 00092 // API function: 00093 // CreateFile 00094 // Purpose: 00095 // Retrieves a handle to a device. 00096 // Accepts: 00097 // A device path name returned by SetupDiGetDeviceInterfaceDetail 00098 // The type of access requested (read/write). 00099 // FILE_SHARE attributes to allow other processes to access the device while this handle is open. 00100 // A Security structure or IntPtr.Zero. 00101 // A creation disposition value. Use OPEN_EXISTING for devices. 00102 // Flags and attributes for files. Not used for devices. 00103 // Handle to a template file. Not used. 00104 // Returns: a handle without read or write access. 00105 // This enables obtaining information about all HIDs, even system 00106 // keyboards and mice. 00107 // Separate handles are used for reading and writing. 00108 // *** 00109 hidHandle = FileIO.CreateFile(devicePathName[memberIndex], 0, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0); 00110 00111 if (!hidHandle.IsInvalid) 00112 { 00113 // The returned handle is valid, 00114 // so find out if this is the device we're looking for. 00115 00116 // Set the Size property of DeviceAttributes to the number of bytes in the structure. 00117 MyHid.DeviceAttributes.Size = Marshal.SizeOf(MyHid.DeviceAttributes); 00118 00119 // *** 00120 // API function: 00121 // HidD_GetAttributes 00122 00123 // Purpose: 00124 // Retrieves a HIDD_ATTRIBUTES structure containing the Vendor ID, 00125 // Product ID, and Product Version Number for a device. 00126 00127 // Accepts: 00128 // A handle returned by CreateFile. 00129 // A pointer to receive a HIDD_ATTRIBUTES structure. 00130 00131 // Returns: 00132 // True on success, False on failure. 00133 // *** 00134 00135 success = Hid.HidD_GetAttributes(hidHandle, ref MyHid.DeviceAttributes); 00136 00137 if (success) 00138 { 00139 // Find out if the device matches the one we're looking for. 00140 if ((MyHid.DeviceAttributes.VendorID == myVendorID) && (MyHid.DeviceAttributes.ProductID == myProductID)) 00141 { 00142 myDeviceDetected = true; 00143 // Save the DevicePathName for OnDeviceChange(). 00144 myDevicePathName = devicePathName[memberIndex]; 00145 } 00146 else 00147 { 00148 // It's not a match, so close the handle. 00149 myDeviceDetected = false; 00150 hidHandle.Close(); 00151 } 00152 } 00153 else 00154 { 00155 // There was a problem in retrieving the information. 00156 myDeviceDetected = false; 00157 hidHandle.Close(); 00158 } 00159 } 00160 00161 // Keep looking until we find the device or there are no devices left to examine. 00162 memberIndex = memberIndex + 1; 00163 } 00164 while (!((myDeviceDetected || (memberIndex == devicePathName.Length)))); 00165 } 00166 00167 if (myDeviceDetected) 00168 { 00169 // The device was detected. 00170 // Learn the capabilities of the device. 00171 MyHid.Capabilities = MyHid.GetDeviceCapabilities(hidHandle); 00172 00173 // Find out if the device is a system mouse or keyboard. 00174 hidUsage = MyHid.GetHidUsage(MyHid.Capabilities); 00175 00176 // Get handles to use in requesting Input and Output reports. 00177 readHandle = FileIO.CreateFile(myDevicePathName, FileIO.GENERIC_READ, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, FileIO.FILE_FLAG_OVERLAPPED, 0); 00178 writeHandle = FileIO.CreateFile(myDevicePathName, FileIO.GENERIC_WRITE, FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE, IntPtr.Zero, FileIO.OPEN_EXISTING, 0, 0); 00179 00180 // Flush any waiting reports in the input buffer. (optional) 00181 MyHid.FlushQueue(readHandle); 00182 } 00183 return myDeviceDetected; 00184 } 00185 00186 internal void CloseNimitzH() 00187 { 00188 if (!(hidHandle == null)) 00189 { 00190 if (!(hidHandle.IsInvalid)) 00191 { 00192 hidHandle.Close(); 00193 } 00194 } 00195 00196 if (!(readHandle == null)) 00197 { 00198 if (!(readHandle.IsInvalid)) 00199 { 00200 readHandle.Close(); 00201 } 00202 } 00203 00204 if (!(writeHandle == null)) 00205 { 00206 if (!(writeHandle.IsInvalid)) 00207 { 00208 writeHandle.Close(); 00209 } 00210 } 00211 } 00212 00213 // This function only checks the status variable and does not actively check 00214 // if the NimitzH is still present. This function 00215 // only checks the variable to avoid any timeout delays. 00216 internal Boolean NimitzHPresent() 00217 { 00218 if (myDeviceDetected) 00219 return true; 00220 else 00221 return false; 00222 } 00223 00224 ////////////////////////////////////////////////////////////////////// 00225 // Functions that can be called once NimitzH is opened 00226 ////////////////////////////////////////////////////////////////////// 00227 00228 // This function calls the NimitzH Read Revision command. 00229 // This is done by sending 0xC2, and then receiving 1 byte major rev, then 1byte minor Rev, and then 0xD2 00230 // This function returns firmware MAJORVERSION in upper word and MINORVERSION in lower word 00231 // This function returns -1 if an error occurs 00232 00233 internal int GetFirmwareVersion() 00234 { 00235 Boolean success = false; 00236 Byte[] inputBuffer = null; 00237 Byte[] dataOut = new Byte[2]; 00238 00239 dataOut[0] = 0x01;//number of bytes to send 00240 dataOut[1] = 0x02;//firmware command 00241 00242 success = InputOutputReports(dataOut, ref inputBuffer); 00243 00244 if (!success) 00245 return -1; 00246 00247 if (inputBuffer[2] == COMMAND_SUCCEED) 00248 return (inputBuffer[3] << 16) + inputBuffer[4]; 00249 else 00250 return -1; 00251 00252 } 00253 internal Boolean TestSendPacket(byte[] sendData, ref byte[] readData) 00254 { 00255 Boolean success = false; 00256 Byte[] inputBuffer = null; 00257 byte numData = (byte)sendData.Length; 00258 Byte[] dataOut = new Byte[3 + numData]; 00259 00260 if ((numData > 62) || (numData < 0)) 00261 return false; // Max packet size is 62 bytes 00262 00263 dataOut[0] = (byte)(0x02 + numData);//number of bytes to send (include command and data bytes) 00264 dataOut[1] = 0x01;//command byte 00265 dataOut[2] = (byte)(numData);//number of data bytes 00266 00267 for (int i = 0; i < numData; i++) 00268 dataOut[i + 3] = sendData[i]; 00269 00270 success = InputOutputReports(dataOut, ref inputBuffer); 00271 00272 if (!success) 00273 return false; 00274 00275 for (int i = 0; i < numData; i++) 00276 readData[i] = inputBuffer[i + 3]; 00277 00278 if (inputBuffer[2] == COMMAND_SUCCEED) 00279 return true; 00280 else 00281 return false; 00282 } 00283 /****************I2CPacketWrite****************/ 00284 /* Description: Generates the correct sequence of events on the I2C bus for a packet write (up to 60 data bytes) 00285 /* Information: New Implementation for packet writes ( SHOULD BE USED in most ALLL Writes/Read of and I2C Device )!! 00286 /* Paramters: slaveAddress = slave address of DUT (R/W# is set in firmware), numBytes = Number of data bytes to write (1 to 60), 00287 /* memoryaddress = Desired memory location, databuffer = pointer to the data to write on the buss*/ 00288 internal Boolean I2CWritePacket(Byte slaveAddress, Byte memoryaddress, Byte numBytes, Byte[] databuffer) 00289 { 00290 Boolean success = false; 00291 Byte[] inputBuffer = null; 00292 Byte[] dataOut = new Byte[64]; 00293 00294 if ((numBytes > 59) || (numBytes < 0)) 00295 return false; // Max packet size is 60 bytes 00296 00297 dataOut[0] = (byte)(numBytes + 4); 00298 dataOut[1] = 0x20; 00299 dataOut[2] = slaveAddress; 00300 dataOut[3] = memoryaddress; 00301 dataOut[4] = numBytes; 00302 00303 for (int i = 0; i < numBytes; i++) 00304 dataOut[i + 5] = databuffer[i]; 00305 00306 success = InputOutputReports(dataOut, ref inputBuffer); 00307 00308 if (!success) 00309 return false; 00310 00311 if (inputBuffer[2] == COMMAND_SUCCEED) 00312 return true; 00313 else 00314 return false; 00315 } 00316 00317 /****************I2CPacketRead****************/ 00318 /* Description: Generates the correct sequence of events on the I2C bus for a packet read (up to 60 data bytes) 00319 /* Information: New Implementation for packet reads ( SHOULD BE USED in most ALLL Writes/Read of and I2C Device )!! 00320 /* Paramters: slaveAddress = slave address of DUT (R/W# is set in firmware), numBytes = Number of data bytes to write (1 to 60), 00321 /* memoryaddress = Desired memory location, databuffer = pointer to the data read should be saved*/ 00322 internal Boolean I2CReadPacket(Byte slaveAddress, Byte memoryaddress, Byte numBytes, ref Byte[] databuffer) 00323 { 00324 Boolean success = false; 00325 Byte[] inputBuffer = null; 00326 Byte[] dataOut = new Byte[5]; 00327 00328 if ((numBytes > 62) || (numBytes < 1)) 00329 return false; // Max packet size is 62 bytes 00330 00331 dataOut[0] = 0x04; 00332 dataOut[1] = 0x21; 00333 dataOut[2] = (byte)(slaveAddress | 0x01); 00334 dataOut[3] = memoryaddress; 00335 dataOut[4] = numBytes; 00336 00337 success = InputOutputReports(dataOut, ref inputBuffer); 00338 00339 if (!success) 00340 return false; 00341 00342 for (int i = 0; i < numBytes; i++) 00343 databuffer[i] = inputBuffer[i + 3]; 00344 00345 if (inputBuffer[2] == COMMAND_SUCCEED) 00346 return true; 00347 else 00348 return false; 00349 } 00350 00351 internal Boolean SPIReadPacket(Byte address, Byte numBytes, ref Byte[] data) 00352 { 00353 Boolean success = false; 00354 Byte[] inputBuffer = null; 00355 Byte[] dataOut = new Byte[4]; 00356 00357 if ((numBytes > 62) || (numBytes < 1)) 00358 return false; // Max packet size is 62 bytes 00359 00360 dataOut[0] = 3; 00361 dataOut[1] = 0x41; 00362 dataOut[2] = address; 00363 dataOut[3] = numBytes; 00364 00365 success = InputOutputReports(dataOut, ref inputBuffer); 00366 00367 if (!success) 00368 return false; 00369 00370 for (int i = 0; i < numBytes; i++) 00371 data[i] = inputBuffer[i + 3]; 00372 00373 if (inputBuffer[2] == COMMAND_SUCCEED) 00374 return true; 00375 else 00376 return false; 00377 } 00378 00379 internal Boolean SPIStartSampling(Byte address, Byte numBytes, uint numSamples, ref Byte[] data) 00380 { 00381 Boolean success = false; 00382 Byte[] inputBuffer = null; 00383 Byte[] dataOut = new Byte[6]; 00384 00385 if ((numBytes > 62) || (numBytes < 1)) 00386 return false; // Max packet size is 62 bytes 00387 00388 dataOut[0] = 5; 00389 dataOut[1] = 0x45; 00390 dataOut[2] = address; 00391 dataOut[3] = numBytes; 00392 dataOut[4] = (byte)(numSamples >> 8); 00393 dataOut[5] = (byte)numSamples; 00394 00395 success = InputOutputReports(dataOut, ref inputBuffer); 00396 00397 if (!success) 00398 return false; 00399 00400 for (int i = 0; i < numBytes; i++) 00401 data[i] = inputBuffer[i + 3]; 00402 00403 if (inputBuffer[2] == COMMAND_SUCCEED) 00404 return true; 00405 else 00406 return false; 00407 } 00408 00409 internal bool SPIWritePacket(Byte address, Byte numBytes, Byte[] data) 00410 { 00411 Boolean success = false; 00412 Byte[] inputBuffer = null; 00413 Byte[] dataOut = new Byte[64]; 00414 00415 if ((numBytes > 60) || (numBytes < 1)) 00416 return false; // Max packet size is 60 bytes 00417 00418 dataOut[0] = (byte)(numBytes + 3); 00419 dataOut[1] = 0x40; 00420 dataOut[2] = address; 00421 dataOut[3] = numBytes; 00422 00423 for (int i = 0; i < numBytes; i++) 00424 dataOut[4 + i] = data[i]; 00425 00426 success = InputOutputReports(dataOut, ref inputBuffer); 00427 00428 if (!success) 00429 return false; 00430 00431 if (inputBuffer[2] == COMMAND_SUCCEED) 00432 return true; 00433 else 00434 return false; 00435 } 00436 /// <summary> 00437 /// Sends an Output report, then retrieves an Input report. 00438 /// Assumes report ID = 0 for both reports. 00439 /// </summary> 00440 00441 private Boolean InputOutputReports(Byte[] data, ref Byte[] inputReportBuffer) 00442 { 00443 // Byte[] inputReportBuffer = null; 00444 Byte[] outputReportBuffer = null; 00445 Boolean success = false; 00446 00447 success = false; 00448 00449 // Don't attempt to exchange reports if valid handles aren't available 00450 // (as for a mouse or keyboard under Windows 2000/XP.) 00451 00452 if (!readHandle.IsInvalid && !writeHandle.IsInvalid) 00453 { 00454 // Don't attempt to send an Output report if the HID has no Output report. 00455 if (MyHid.Capabilities.OutputReportByteLength > 0) 00456 { 00457 // Set the size of the Output report buffer. 00458 00459 outputReportBuffer = new Byte[MyHid.Capabilities.OutputReportByteLength]; 00460 00461 outputReportBuffer[0] = 0; // Ensure Report ID = 0 00462 00463 00464 for (int i = 0; i < data.Length; i++) 00465 outputReportBuffer[i + 1] = data[i]; 00466 00467 // Use WriteFile to send the report. 00468 // If the HID has an interrupt OUT endpoint, WriteFile uses an 00469 // interrupt transfer to send the report. 00470 // If not, WriteFile uses a control transfer. 00471 00472 Hid.OutputReportViaInterruptTransfer myOutputReport = new Hid.OutputReportViaInterruptTransfer(); 00473 success = myOutputReport.Write(outputReportBuffer, writeHandle); 00474 } 00475 00476 if (!success) 00477 return false; 00478 00479 // Read an Input report 00480 success = false; 00481 00482 // Don't attempt to send an Input report if the HID has no Input report. 00483 // (The HID spec requires all HIDs to have an interrupt IN endpoint, 00484 // which suggests that all HIDs must support Input reports.) 00485 00486 if (MyHid.Capabilities.InputReportByteLength > 0) 00487 { 00488 // Set the size of the Input report buffer. 00489 inputReportBuffer = new Byte[MyHid.Capabilities.InputReportByteLength]; 00490 00491 Hid.InputReportViaInterruptTransfer myInputReport = new Hid.InputReportViaInterruptTransfer(); 00492 myInputReport.Read(hidHandle, readHandle, writeHandle, ref myDeviceDetected, ref inputReportBuffer, ref success); 00493 00494 } 00495 00496 } 00497 return success; 00498 } 00499 } 00500 }
Generated on Thu Jul 28 2022 18:07:15 by
1.7.2