Darien Figueroa / Mbed 2 deprecated repo3

Dependencies:   mbed MAX14720 MAX30205 USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NimitzHID.cs Source File

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 }