/***************************************************************************** * * * HID USB DRIVER - FLORIAN LEITNER * * Copyright 2007 - Florian Leitner | http://www.florian-leitner.de * * mail@florian-leitner.de * * * * This file is part of HID USB DRIVER. * * * * HID USB DRIVER is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License 3.0 as published by * * the Free Software Foundation; * * HID USB DRIVER is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ******************************************************************************/ //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.IO; using System.Threading; namespace USBHIDDRIVER.USB { /// /// /// public class HIDUSBDevice: IDisposable { bool disposed = false; private Thread usbThread; /*Variables --------------------------------------------------------------------*/ private String vendorID; //Vendor ID of the Device private String productID; //Product ID of the Device private String devicePath; //device path private int deviceCount; //device count private bool connectionState; //Connection Status true: connected, false: disconnected public int byteCount = 0; //Recieved Bytes //recieve Buffer (Each report is one Element) //this one was replaced by the receive Buffer in the interface //public static ArrayList receiveBuffer = new ArrayList(); //USB Object private USBSharp myUSB = new USBSharp(); //thread for read operations protected Thread dataReadingThread; /*Functions --------------------------------------------------------------------*/ //---#+************************************************************************ //---NOTATION: //- HIDUSBDevice(int vID, int pID) //- //--- DESCRIPTION: //-- constructor //-- tries to establish a connection to the device // Autor: F.L. //-*************************************************************************+#* /// /// Initializes a new instance of the class. /// And tries to establish a connection to the device. /// /// The vendor ID of the USB device. /// The product ID of the USB device. public HIDUSBDevice(String vID, String pID) { //set vid and pid setDeviceData(vID, pID); //try to establish connection connectDevice(); //create Read Thread dataReadingThread = new Thread(new ThreadStart(readDataThread)); } //---#+************************************************************************ //---NOTATION: //- bool connectDevice() //- //--- DESCRIPTION: //-- tries to establish a connection to the device // Autor: F.L. //-*************************************************************************+#* /// /// Connects the device. /// /// true if connection is established public bool connectDevice() { //searchDevice searchDevice(); //return connection state return this.getConnectionState(); } //---#+************************************************************************ //---NOTATION: //- bool searchDevice() //- //--- DESCRIPTION: //-- tries to find the device with specified vendorID and productID // Autor: F.L. //-*************************************************************************+#* /// /// Searches the device with soecified vendor and product id an connect to it. /// /// private bool searchDevice() { //no device found yet bool deviceFound = false; this.deviceCount = 0; this.devicePath = string.Empty; myUSB.CT_HidGuid(); myUSB.CT_SetupDiGetClassDevs(); int result = -1; int resultb = -1; int device_count = 0; int size = 0; int requiredSize = 0; //search the device until you have found it or no more devices in list while (result != 0) { //open the device result = myUSB.CT_SetupDiEnumDeviceInterfaces(device_count); //get size of device path resultb = myUSB.CT_SetupDiGetDeviceInterfaceDetail(ref requiredSize, 0); size = requiredSize; //get device path resultb = myUSB.CT_SetupDiGetDeviceInterfaceDetailx(ref requiredSize, size); //is this the device i want? string deviceID = this.vendorID + "&" + this.productID; if (myUSB.DevicePathName.IndexOf(deviceID) > 0) { //yes it is //store device information this.deviceCount = device_count; this.devicePath = myUSB.DevicePathName; deviceFound = true; //init device myUSB.CT_SetupDiEnumDeviceInterfaces(this.deviceCount); size = 0; requiredSize = 0; resultb = myUSB.CT_SetupDiGetDeviceInterfaceDetail(ref requiredSize, size); resultb = 0; resultb = myUSB.CT_SetupDiGetDeviceInterfaceDetailx(ref requiredSize, size); resultb = 0; //create HID Device Handel resultb = myUSB.CT_CreateFile(this.devicePath); //we have found our device so stop searching break; } device_count++; } //set connection state this.setConnectionState(deviceFound); //return state return this.getConnectionState(); } //---#+************************************************************************ //---NOTATION: //- bool getDevices() //- //--- DESCRIPTION: //-- returns the number of devices with specified vendorID and productID // Autor: F.L. //-*************************************************************************+#* /// /// returns the number of devices with specified vendorID and productID /// /// returns the number of devices with specified vendorID and productID public int getDevice() { //no device found yet bool deviceFound = false; this.deviceCount = 0; this.devicePath = string.Empty; myUSB.CT_HidGuid(); myUSB.CT_SetupDiGetClassDevs(); int result = -1; int resultb = -1; int device_count = 0; int size = 0; int requiredSize = 0; int numberOfDevices = 0; //search the device until you have found it or no more devices in list while (result != 0) { //open the device result = myUSB.CT_SetupDiEnumDeviceInterfaces(device_count); //get size of device path resultb = myUSB.CT_SetupDiGetDeviceInterfaceDetail(ref requiredSize, 0); size = requiredSize; //get device path resultb = myUSB.CT_SetupDiGetDeviceInterfaceDetailx(ref requiredSize, size); //is this the device i want? string deviceID = this.vendorID + "&" + this.productID; if (myUSB.DevicePathName.IndexOf(deviceID) > 0) { numberOfDevices++; } device_count++; } return numberOfDevices; } //---#+************************************************************************ //---NOTATION: //- bool writeData(char[] cDataToWrite) //- //--- DESCRIPTION: //-- writes data to the device and returns true if no error occured // Autor: F.L. //-*************************************************************************+#* /// /// Writes the data. /// /// The b data to write. /// public bool writeData(byte[] bDataToWrite) { bool success = false; if (getConnectionState()) { try { //get output report length int myPtrToPreparsedData = -1; // myUSB.CT_HidD_GetPreparsedData(myUSB.HidHandle, ref myPtrToPreparsedData); // int code = myUSB.CT_HidP_GetCaps(myPtrToPreparsedData); int outputReportByteLength = 65; int bytesSend = 0; //if bWriteData is bigger then one report diveide into sevral reports while (bytesSend < bDataToWrite.Length) { // Set the size of the Output report buffer. // byte[] OutputReportBuffer = new byte[myUSB.myHIDP_CAPS.OutputReportByteLength - 1 + 1]; byte[] OutputReportBuffer = new byte[outputReportByteLength - 1 + 1]; // Store the report ID in the first byte of the buffer: OutputReportBuffer[0] = 0; // Store the report data following the report ID. for (int i = 1; i < OutputReportBuffer.Length; i++) { if (bytesSend < bDataToWrite.Length) { OutputReportBuffer[i] = bDataToWrite[bytesSend]; bytesSend++; } else { OutputReportBuffer[i] = 0; } } OutputReport myOutputReport = new OutputReport(); success = myOutputReport.Write(OutputReportBuffer, myUSB.HidHandle); } } catch (System.AccessViolationException ex) { success = false; } } else { success = false; } return success; } //---#+************************************************************************ //---NOTATION: //- readDataThread() //- //--- DESCRIPTION: //-- ThreadMethod for reading Data // Autor: F.L. //-*************************************************************************+#* /// /// ThreadMethod for reading Data /// public void readDataThread() { int receivedNull = 0; while (true) { int myPtrToPreparsedData = -1; if (myUSB.CT_HidD_GetPreparsedData(myUSB.HidHandle, ref myPtrToPreparsedData) != 0) { int code = myUSB.CT_HidP_GetCaps(myPtrToPreparsedData); int reportLength = myUSB.myHIDP_CAPS.InputReportByteLength; while (true) {//read until thread is stopped byte[] myRead = myUSB.CT_ReadFile(myUSB.myHIDP_CAPS.InputReportByteLength); if (myRead != null) { //ByteCount + bytes received byteCount += myRead.Length; //Store received bytes /* lock (recieveBuffer.SyncRoot) { recieveBuffer.Add(myRead); }*/ lock (USBHIDDRIVER.USBInterface.usbBuffer.SyncRoot) { USBHIDDRIVER.USBInterface.usbBuffer.Add(myRead); } } else { //Recieved a lot of null bytes! //mybe device disconnected? if (receivedNull > 100) { receivedNull = 0; Thread.Sleep(1); } receivedNull++; } } } } } //---#+************************************************************************ //---NOTATION: //- readData() //- //--- DESCRIPTION: //-- handling of the read thread // Autor: F.L. //-*************************************************************************+#* /// /// controls the read thread /// public void readData() { if (dataReadingThread.ThreadState.ToString() == "Unstarted") { //start the thread dataReadingThread.Start(); Thread.Sleep(0); } else if (dataReadingThread.ThreadState.ToString() == "Running") { //Stop the Thread dataReadingThread.Abort(); } else { //create Read Thread dataReadingThread = new Thread(new ThreadStart(readDataThread)); //start the thread dataReadingThread.Start(); Thread.Sleep(0); } } //---#+************************************************************************ //---NOTATION: //- abortreadData() //- //--- DESCRIPTION: //-- handling of the read thread // Autor: F.L. //-*************************************************************************+#* /// /// Aborts the read thread. /// public void abortreadData() { if (dataReadingThread.ThreadState.ToString() == "Running") { //Stop the Thread dataReadingThread.Abort(); } } //---#+************************************************************************ //---NOTATION: //- disconnectDevice() //- //--- DESCRIPTION: //-- disconnects the device and cleans up // Autor: F.L. //-*************************************************************************+#* /// /// Disconnects the device. /// public void disconnectDevice() { usbThread.Abort(); myUSB.CT_CloseHandle(myUSB.HidHandle); } /* GET AND SET Methods*/ //---#+************************************************************************ //---NOTATION: //- setDeviceData(String vID, String pID) //- //--- DESCRIPTION: //-- set vendor and product ID // Autor: F.L. //-*************************************************************************+#* /// /// Sets the device data. /// /// The vendor ID. /// The product ID. public void setDeviceData(String vID, String pID) { this.vendorID = vID; this.productID = pID; } //---#+************************************************************************ //---NOTATION: //- String getVendorID() //- //--- DESCRIPTION: //-- returns the vendor ID // Autor: F.L. //-*************************************************************************+#* /// /// Gets the vendor ID. /// /// the vendor ID public String getVendorID() { return this.vendorID; } //---#+************************************************************************ //---NOTATION: //- String getProductID() //- //--- DESCRIPTION: //-- returns the product ID // Autor: F.L. //-*************************************************************************+#* /// /// Gets the product ID. /// /// the product ID public String getProductID() { return this.productID; } //---#+************************************************************************ //---NOTATION: //- setConnectionState(bool state) //- //--- DESCRIPTION: //-- set the connection state // Autor: F.L. //-*************************************************************************+#* /// /// Sets the state of the connection. /// /// state public void setConnectionState(bool state) { this.connectionState = state; } //---#+************************************************************************ //---NOTATION: //- bool getConnectionState() //- //--- DESCRIPTION: //-- returns the connection state // Autor: F.L. //-*************************************************************************+#* /// /// Gets the state of the connection. /// /// true = connected; false = diconnected public bool getConnectionState() { return this.connectionState; } //---#+************************************************************************ //---NOTATION: //- int getDeviceCount() //- //--- DESCRIPTION: //-- returns the device count // Autor: F.L. //-*************************************************************************+#* /// /// Gets the device count. /// /// public ArrayList getDevices() { ArrayList devices = new ArrayList(); //no device found yet bool deviceFound = false; this.deviceCount = 0; this.devicePath = string.Empty; myUSB.CT_HidGuid(); myUSB.CT_SetupDiGetClassDevs(); int result = -1; int resultb = -1; int device_count = 0; int size = 0; int requiredSize = 0; int numberOfDevices = 0; //search the device until you have found it or no more devices in list while (result != 0) { //open the device result = myUSB.CT_SetupDiEnumDeviceInterfaces(device_count); //get size of device path resultb = myUSB.CT_SetupDiGetDeviceInterfaceDetail(ref requiredSize, 0); size = requiredSize; //get device path resultb = myUSB.CT_SetupDiGetDeviceInterfaceDetailx(ref requiredSize, size); //is this the device i want? string deviceID = this.vendorID; if (myUSB.DevicePathName.IndexOf(deviceID) > 0) { devices.Add(myUSB.DevicePathName); numberOfDevices++; } device_count++; } return devices; } //---#+************************************************************************ //---NOTATION: //- getDevicePath() //- //--- DESCRIPTION: //-- returns the device path // Autor: F.L. //-*************************************************************************+#* /// /// Gets the device path. /// /// public string getDevicePath() { return this.devicePath; } internal abstract class HostReport { // For reports the host sends to the device. // Each report class defines a ProtectedWrite method for writing a type of report. protected abstract bool ProtectedWrite(int deviceHandle, byte[] reportBuffer); internal bool Write(byte[] reportBuffer, int deviceHandle) { bool Success = false; // Purpose : Calls the overridden ProtectedWrite routine. // : This method enables other classes to override ProtectedWrite // : while limiting access as Friend. // : (Directly declaring Write as Friend MustOverride causes the // : compiler(warning) "Other languages may permit Friend // : Overridable members to be overridden.") // Accepts : reportBuffer - contains the report ID and report data. // : deviceHandle - handle to the device. ' // Returns : True on success. False on failure. try { Success = ProtectedWrite(deviceHandle, reportBuffer); } catch (Exception ex) { } return Success; } } internal class OutputReport : HostReport { // For Output reports the host sends to the device. // Uses interrupt or control transfers depending on the device and OS. protected override bool ProtectedWrite(int hidHandle, byte[] outputReportBuffer) { // Purpose : writes an Output report to the device. // Accepts : HIDHandle - a handle to the device. // OutputReportBuffer - contains the report ID and report to send. // Returns : True on success. False on failure. int NumberOfBytesWritten = 0; int Result; bool Success = false; try { // The host will use an interrupt transfer if the the HID has an interrupt OUT // endpoint (requires USB 1.1 or later) AND the OS is NOT Windows 98 Gold (original version). // Otherwise the the host will use a control transfer. // The application doesn't have to know or care which type of transfer is used. // *** // API function: WriteFile // Purpose: writes an Output report to the device. // Accepts: // A handle returned by CreateFile // The output report byte length returned by HidP_GetCaps. // An integer to hold the number of bytes written. // Returns: True on success, False on failure. // *** Result = USBSharp.WriteFile(hidHandle, ref outputReportBuffer[0], outputReportBuffer.Length, ref NumberOfBytesWritten, 0); Success = (Result == 0) ? false : true; } catch (Exception ex) { } return Success; } } #region IDisposable Members public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected void Dispose(bool disposeManagedResources) { if (!this.disposed) { if (disposeManagedResources) { //only clear up managed stuff here } //clear up unmanaged stuff here if (myUSB.HidHandle != -1) { myUSB.CT_CloseHandle(myUSB.HidHandle); } if (myUSB.hDevInfo != -1) { myUSB.CT_SetupDiDestroyDeviceInfoList(); } this.disposed = true; } } #endregion } }