/*****************************************************************************
* *
* 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
}
}