Hallo zusammen, nachdem ich mittlerweile schon eine ganze Weile probiere und suche, aber nichts vernünftiges zu Weg gebracht habe, wende ich mich an euch: Was ich vor habe: Ich möchte über C# auf ein HID Gerät zugreifen, an dieses Daten senden, um dort einige Leuchtdioden zu steuern. Es müssen lediglich 4Byte gesendet werden um dies zu realisieren. Jetzt meine Probleme: - Wie erkenne ich welche HID Geräte angeschlossenen sind? Hier wäre mir am liebsten eine Liste aller angeschlossenen HID Geräte (mit VID und PID etc.) zu erhalten, sodass man anhand dieser Liste das betreffende Gerät auswählen kann. - Wie stelle ich eine Verbindung zu dem von mir ausgewählten Gerät her und übertrage dann die Daten? am liebsten wäre es mir keine fertigen Treiber zu nutzen sondern die Umsetzung mit den von Windows zur Verfügung gestellten DLLs zu machen, sodass mir das ganze von Grund auf klar wird. Vielen Dank für eure Hilfe!!
Hallo, auch wenn sich der folgende Artikel mit einer speziellen HID Host Bibliothek befasst, bei der die Sourcen nicht zugänglich sind, so findest Du am Ende doch eine schöne Übersicht über frei zugängliche Treiber. Das wäre ein guter Startpunkt: http://www.mikrocontroller.net/articles/USB_HID_Host_Treiber Gruß Potter
Wayne Interessierts schrieb: > Hallo zusammen, > > nachdem ich mittlerweile schon eine ganze Weile probiere und suche, aber > nichts vernünftiges zu Weg gebracht habe, wende ich mich an euch: google - C# hid liefert unter den ersten Treffern http://www.lvr.com/hidpage.htm und http://www.florian-leitner.de/index.php/2007/08/03/hid-usb-driver-library/ Etwas schwerer zu finden "Microchip Application Libraries" http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en547784 darin enthalten sind unter anderem "Device - HID - Custom Demos" inkl. der Quelltexte für Firmware und PC-Software. > Was ich vor habe: > Ich möchte über C# auf ein HID Gerät zugreifen, an dieses Daten senden, > um dort einige Leuchtdioden zu steuern. Es müssen lediglich 4Byte > gesendet werden um dies zu realisieren. > > Jetzt meine Probleme: > - Wie erkenne ich welche HID Geräte angeschlossenen sind? Hier wäre mir > am liebsten eine Liste aller angeschlossenen HID Geräte (mit VID und PID > etc.) zu erhalten, sodass man anhand dieser Liste das betreffende Gerät > auswählen kann. SetupDiGetClassDevsUM und noch etwas mehr Code > - Wie stelle ich eine Verbindung zu dem von mir ausgewählten Gerät her > und übertrage dann die Daten? Wie zu jedem anderen Gerät unter Windows auch CreateFile, ReadFile, WriteFile Erklärt wird beides auf den oben verlinkten Seiten.
Vielen Dank für eure Hilfe! Ich habe mir mal die ganzen Links angeschaut und dabei folgendes zu Stande bekommen (siehe Anhang). Somit kann ich jetzt schon mal die komplette ID der angeschlossenen HID Geräte auslesen. Aber jetzt habe ich folgendes Problem, ich möchte noch die Herstellernamen des USB Gerätes ausgeben. Ich habe es schon mit "SetupDiGetDeviceRegistryProperty" probiert (siehe Quellcode). Jedoch bekomme ich als Ergebnis irgendwelche komischen Zeichen geliefert. Hat irgend jemand eine Idee warum? Nächster Schritt wäre dann, eine Verbindung zu einem dieser Geräte herzustellen. Hat jemand einen Befehl, wie ich dabei vorgehen kann? Vielen Dank!
Wayne Interessierts schrieb: > Vielen Dank für eure Hilfe! > > Ich habe mir mal die ganzen Links angeschaut und dabei folgendes zu > Stande bekommen (siehe Anhang). > Somit kann ich jetzt schon mal die komplette ID der angeschlossenen HID > Geräte auslesen. > > Aber jetzt habe ich folgendes Problem, ich möchte noch die > Herstellernamen des USB Gerätes ausgeben. > Ich habe es schon mit "SetupDiGetDeviceRegistryProperty" probiert (siehe > Quellcode). Jedoch bekomme ich als Ergebnis irgendwelche komischen > Zeichen geliefert. > Hat irgend jemand eine Idee warum? Mal ins blaue... SetupDiGetDeviceRegistryProperty muss zweimal aufgerufen werden, einmal um die nötige Puffergröße zu erhalten, dann, nachdem man Speicher reserviert hat, um den Wert kopieren zu lassen.
1 | SetupDiGetDeviceRegistryProperty(infoSet, ref infoData, SPDRP_ABCDEF, ref regDataType, IntPtr.Zero, 0, ref regSize); |
2 | IntPtr buffer = Marshal.AllocHGlobal((int)regSize); |
3 | SetupDiGetDeviceRegistryProperty(infoSet, ref infoData, SPDRP_ABCDEF, ref regDataType, buffer, regSize, ref regSizeFill); |
4 | string propStr = Marshal.PtrToStringUni(buffer); |
5 | Marshal.FreeHGlobal(buffer); |
> > Nächster Schritt wäre dann, eine Verbindung zu einem dieser Geräte > herzustellen. Hat jemand einen Befehl, wie ich dabei vorgehen kann? Wenn mit SetupDiGetDeviceInterfaceDetail der Gerätepfad ermittelt ist, bekommt man mit
1 | writeHandle = CreateFile(devicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); |
2 | // Fehlerbehandlung und u.U. Marshal.GetLastWin32Error()
|
3 | readHandle = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); |
4 | // Fehlerbehandlung und u.U. Marshal.GetLastWin32Error()
|
die entsprechenden Handles (die vom Typ SafeFileHandle sein sollten) für
WriteFile bzw. ReadFile.
Ansonsten siehe die Links von oben...
> Vielen Dank!
Vielen Dank Arc Net Deine Tips haben mich sehr viel weiter gebracht! Ich bin mittlerweile soweit, dass ich alle HID Geräte mit zugehörigem Herstellernamen anzeigen lassen kann. Weiterhin kann ich die entsprechenden Files zum schreiben und lesen erstellen. Für Tastaturen und Maus kann ich logischerweise nur ein Read File erzeugen, für mein Gerät ist es jedoch möglich auch das Write File zu erzugen. Möchte ich nun 2 Bytes an mein Gerät schicken so bleibt die Variable result jeweils auf False. Hier mal der Codeschnipsel: bool result = WriteFile(ptr, ref test, 2, ref geschrieben, IntPtr.Zero); Das komplette Quellcode befindet sich in der Textdatei im Anhang. Was mach ich da noch falsch? Vielen Dank für eure Hilfe!
Da das hier irgendwie nix mit den .txt Dateien wird. Das Code hier: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Runtime.InteropServices; using System.IO; using System.IO.Ports; using System.IO.IsolatedStorage; using System.IO.Compression; using Microsoft.Win32.SafeHandles; namespace KeyDownModul { public partial class Form1 : Form { /* private class Sp_DEVICE_INTERFACE_DETAIL_DATA { public int cbsize; public string Devicepath; } private class SP_DEVICE_INTERFACE_DATA { public int cbSize; public Guid InterfaceClassGuid; public int FLAGS; public int Reserved; } */ //Step1: Obtaining the Device Interface Guid [DllImport("hid.dll")] private static extern void HidD_GetHidGuid(ref Guid GUID); //end step1: Obtaining the Device Interface Guid //Step 2: requesting a pointer to a device Information Set [DllImport("setupapi.dll", CharSet = CharSet.Auto)] private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, UInt32 Enumerator, IntPtr hwndParent, UInt32 Flags); IntPtr deviceinfoset; //End Step 2: requesting a pointer to a device Information Set [StructLayout(LayoutKind.Sequential)] public struct SP_DEVICE_INTERFACE_DATA { public Int32 cbSize; public Guid interfaceClassGuid; public Int32 flags; private UIntPtr reserved; } [StructLayout(LayoutKind.Sequential)] public struct SP_DEVINFO_DATA { public Int32 cbSize; public Guid ClassGuid; public Int32 DevInst; public IntPtr Reserved; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] struct SP_DEVICE_INTERFACE_DETAIL_DATA { public int cbSize; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string DevicePath; } [DllImport("setupapi.dll")] public static extern Boolean SetupDiEnumDeviceInterfaces( IntPtr DeviceInfoSet, int DeviceInfoData, ref Guid InterfaceClassGuid, int MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData ); //SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA(); //int MemberIndex; //Boolean Result; [DllImport("setupapi.dll", CharSet = CharSet.Auto)] public static extern Boolean SetupDiGetDeviceInterfaceDetail( IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceIntefaceData, IntPtr DeviceInterfaceDetailData, int DeviceInterfacedetailDatasize, ref int DeviceInterfacedetaildataSize, IntPtr DeviceInfoData ); int BufferSize; //Boolean Success; //int counter; [DllImport("setupapi.dll")] static extern int CM_Get_Parent( out UInt32 pdnDevInst, UInt32 dnDevInst, int ulFlags ); [DllImport("setupapi.dll", CharSet = CharSet.Auto)] static extern int CM_Get_Device_ID( UInt32 dnDevInst, IntPtr Buffer, int BufferLen, int ulFlags ); [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool SetupDiGetDeviceRegistryProperty( IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, uint Property, out UInt32 PropertyRegDataType, IntPtr PropertyBuffer, uint PropertyBufferSize, out UInt32 RequiredSize ); public const short FILE_ATTRIBUTE_NORMAL = 0x80; public const short INVALID_HANDLE_VALUE = -1; public const uint GENERIC_READ = 0x80000000; public const int GENERIC_WRITE = 0x40000000; public const uint CREATE_NEW = 1; public const uint CREATE_ALWAYS = 2; public const int OPEN_EXISTING = 3; [DllImport("kernel32.dll")] public static extern IntPtr CreateFile( string lpFileName, int dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile); private const int FILE_SHARE_READ = 1; private const int FILE_SHARE_WRITE = 2; private const int OPEN_ALWAYS = 4; //private const int INVALID_HANDLE_VALUE = -1; [DllImport("hid.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern Boolean HidD_GetManufacturerString( SafeFileHandle HidDeviceObject, StringBuilder Buffer, Int32 BufferLength); [DllImport("kernel32", EntryPoint = "CloseHandle", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.VariantBool)] internal static extern bool CloseHandle(uint hHandle); [DllImport("hid.dll", SetLastError = true)] static extern Boolean HidD_FreePreparsedData(ref IntPtr PreparsedData); [DllImport("hid.dll", SetLastError = true)] internal static extern bool HidD_GetPreparsedData( IntPtr hDevice, out IntPtr hData); [DllImport("hid.dll", SetLastError = true)] static extern Boolean HidD_GetAttributes(SafeFileHandle HidDeviceObject, ref HIDD_ATTRIBUTES Attributes); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool WriteFile(IntPtr hFile, ref byte[] lpBuffer, uint nNumberOfBytesToWrite, ref uint lpNumberOfBytesWritten, IntPtr ipOverlapped); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { this.Close(); } public struct HIDD_ATTRIBUTES { public UInt32 Size; public UInt16 VendorID; public UInt16 ProductID; public UInt16 VersionNumber; } private void button3_Click(object sender, EventArgs e) { //Step1: code to call step1 Guid HidGuid = new Guid(); HidD_GetHidGuid(ref HidGuid); //End Step1: code to call step1 //Step2: code to call step2 //const int DIGCF_PRESENT = 0x1c80; const int DIGCF_PRESENT = 0x00000002; const int DIGCF_DEVICEINTERFACE = 0x00000010; //const int DIGCF_DEVICEINTERFACE = (0×00000001); deviceinfoset = SetupDiGetClassDevs(ref HidGuid, 0, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); //Display listBox1.Items.Add("Device Info Set = " + deviceinfoset.ToString()); listBox1.Items.Add("HidGuid = " + HidGuid.ToString()); //End dispaly //End Step2: code to call step2 bool success = true; int nIndex=0; while (success) //Aufzählen der Geräte { SP_DEVICE_INTERFACE_DATA oInterface = new SP_DEVICE_INTERFACE_DATA(); oInterface.cbSize = Marshal.SizeOf(oInterface); success = SetupDiEnumDeviceInterfaces(deviceinfoset, 0, ref HidGuid, nIndex, ref oInterface); if (success) { // build a DevInfo Data structure SP_DEVINFO_DATA da = new SP_DEVINFO_DATA(); da.cbSize = Marshal.SizeOf(da); // build a Device Interface Detail Data structure SP_DEVICE_INTERFACE_DETAIL_DATA didd = new SP_DEVICE_INTERFACE_DETAIL_DATA(); didd.cbSize = 4 + Marshal.SystemDefaultCharSize; // trust me :) success = SetupDiGetDeviceInterfaceDetail(deviceinfoset, ref oInterface, IntPtr.Zero, 0, ref BufferSize, IntPtr.Zero); IntPtr detailDataBuffer; detailDataBuffer = Marshal.AllocHGlobal(BufferSize); Marshal.WriteInt32(detailDataBuffer, 4 + Marshal.SystemDefaultCharSize); success = SetupDiGetDeviceInterfaceDetail(deviceinfoset, ref oInterface, detailDataBuffer, BufferSize, ref BufferSize, IntPtr.Zero); string Devicepathname; IntPtr pDevicePathName; pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4); Devicepathname = Marshal.PtrToStringAuto(pDevicePathName); Marshal.FreeHGlobal(detailDataBuffer); //display listBox1.Items.Add("path name = " + pDevicePathName.ToString()); //Pfad und Produktid ausgeben listBox1.Items.Add(Devicepathname); listBox1.Items.Add("File Exists = " + File.Exists(Devicepathname).ToString()); IntPtr ptr = CreateFile(Devicepathname, 0, FILE_SHARE_READ, IntPtr.Zero, OPEN_ALWAYS, 0, IntPtr.Zero); //Handle zum Gerät erzeugen SafeFileHandle handleValue = new SafeFileHandle(ptr, true); if (ptr.ToInt32() == -1) { listBox1.Items.Add("nicht geöffnet"); } else { HIDD_ATTRIBUTES Attributes = new HIDD_ATTRIBUTES(); StringBuilder manufacturerString = new StringBuilder(128); //Herstellernamen auslesen HidD_GetManufacturerString(handleValue, manufacturerString, manufacturerString.Capacity); listBox1.Items.Add(manufacturerString.ToString()); HidD_GetAttributes(handleValue, ref Attributes); listBox1.Items.Add(Attributes.ProductID.ToString()); listBox1.Items.Add(Attributes.VendorID.ToString()); listBox1.Items.Add(Attributes.VersionNumber.ToString()); listBox1.Items.Add(Attributes.Size.ToString()); //Capabilities.UsagePage * 256) + Capabilities.Usage; } } nIndex++; } } private void PrepareForOverlappedTransfer(string devicepathname) { byte[] test = new byte[2]; test[0]=0; test[1]=0x20; uint geschrieben =0; IntPtr ptr = CreateFile(devicepathname, 0, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); //Handle zum Gerät erzeugen //SafeFileHandle writeHandle = new SafeFileHandle(ptr, true); IntPtr ptr1 = CreateFile(devicepathname, 0, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); //Handle zum Gerät erzeugen //SafeFileHandle readHandle = new SafeFileHandle(ptr1, true); if ((ptr.ToInt32() == -1) || (ptr1.ToInt32() == -1)) { MessageBox.Show("Verbindung nicht hergestellt"); } else { bool result = WriteFile(ptr, ref test, 2, ref geschrieben, IntPtr.Zero); if (result) { MessageBox.Show("er hats geschickt"); } else { MessageBox.Show("nix wars"); } } } private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { string text = listBox1.SelectedItem.ToString(); PrepareForOverlappedTransfer(text); } } }
War mir aufgefallen ist
1 | // die Handles werden anders erzeugt
|
2 | writeHandle = CreateFile(devicePath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); |
3 | // Fehlerbehandlung und u.U. Marshal.GetLastWin32Error()
|
4 | readHandle = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); |
5 | // Fehlerbehandlung und u.U. Marshal.GetLastWin32Error()
|
6 | |
7 | // und das sieht auch etwas merkwürdig aus
|
8 | [DllImport("kernel32.dll", SetLastError = true)] |
9 | public static extern bool WriteFile(IntPtr hFile, |
10 | ref byte[] lpBuffer, |
11 | uint nNumberOfBytesToWrite, |
12 | ref uint lpNumberOfBytesWritten, |
13 | IntPtr ipOverlapped); |
14 | |
15 | WriteFile(ptr, ref test, 2, ref geschrieben, IntPtr.Zero); |
16 | |
17 | // WriteFile erwartet einen "normalen" Zeiger für den Buffer...
|
18 | [DllImport("kernel32.dll", SetLastError = true)] |
19 | static extern bool WriteFile( |
20 | SafeFileHandle hFile, |
21 | byte[] lpBuffer, |
22 | uint nNumberOfBytesToWrite, |
23 | ref uint lpNumberOfBytesWritten, |
24 | IntPtr lpOverlapped); |
25 | |
26 | WriteFile(ptr, test, 2, ref geschrieben, IntPtr.Zero |
Hallo, vielen Dank für die Tips. Ich hab die Anregungen von Arc Net mal übernommen. Jetzt habe ich das Problem, dass ich das Write File nicht mal mehr erzeugen kann. Ich erhalte immer eine False zurück. erzeugt wird es so: IntPtr ptr = CreateFile(devicepathname, GenericWrite, FILE_SHARE_READ|FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); //Handle zum Gerät erzeugen SafeFileHandle writeHandle = new SafeFileHandle(ptr, true); die ganzen Konstanten wurden so bestimmt: private const int FILE_SHARE_WRITE = 2; private const int OPEN_ALWAYS = 4; private const int INVALID_HANDLE_VALUE = -1; private const int OPEN_EXISTING = 3; private const uint GenericRead = 0x80000000; private const uint GenericWrite = 0x40000000; Das Read File kann ich weiterhin erzeugen. Hat noch jemand eine Idee woran es liegen könnte? Vielen Dank schon mal!
1 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] |
2 | internal static extern SafeFileHandle CreateFile(string lpFileName, |
3 | uint dwDesiredAccess, uint dwShareMode, |
4 | IntPtr lpSecurityAttributes, |
5 | uint dwCreationDisposition, uint dwFlagsAndAttributes, |
6 | IntPtr hTemplateFile); |
7 | |
8 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] |
9 | internal static extern bool WriteFile(SafeFileHandle hFile, |
10 | byte[] lpBuffer, |
11 | uint nNumberOfBytesToWrite, ref uint lpNumberOfBytesWritten, |
12 | IntPtr lpOverlapped); |
13 | |
14 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] |
15 | public static extern bool ReadFile(SafeFileHandle hFile, |
16 | byte[] lpBuffer, |
17 | uint nNumberOfBytesToRead, |
18 | ref uint lpNumberOfBytesRead, |
19 | IntPtr lpOverlapped); |
20 | |
21 | // Methoden zum Erzeugen der Handles
|
22 | public static SafeFileHandle CreateRead(string path) { |
23 | return CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); |
24 | |
25 | }
|
26 | |
27 | public static SafeFileHandle CreateWrite(string path) { |
28 | return CreateFile(path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); |
29 | }
|
30 | |
31 | public static string GetPath(string vidPid) { |
32 | ...
|
33 | }
|
34 | |
35 | // Aufruf der Funktionen (Vid/Pid sind von einem SiLabs ToolStick)
|
36 | string path = GetPath("Vid_10c4&Pid_8253"); |
37 | |
38 | // path ist hier
|
39 | // "\\\\?\\hid#vid_10c4&pid_8253#6&2ab428c9&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"
|
40 | |
41 | Microsoft.Win32.SafeHandles.SafeFileHandle writeHandle, readHandle; |
42 | writeHandle = CreateRead(path); |
43 | readHandle = CreateWrite(path); |
Das ist in etwa das was hier funktioniert
Hallo, vielen Dank ArcNet! bei deinem letzten Eintrag waren die passenden Hinweise dabei! Das erzeugen von Fils und das verschicken der gewünschten Daten klappt jetzt Prima! Aber es war letztenendes eine dummer Fehler, der dazu führte, dass ich das File zum schreiben nicht erzeugen konnte. Ich habe das File, das ich benötige um die Herstellerdaten (VID, PID, Herstellername etc.)auszulesen nicht mehr geschlossen. Aber eine Frage bleibt mir noch offen: Wo und wie kann ich für folgende Zeile die 3. zu übertragende Variable (Number of Bytes to write) auslesen um sie als Variable zu übergeben? Hab es hier mit 3 fest definiert, weil ich es wusste. Aber das muss doch auch irgendwo aus den Daten ausgelesen werden können. bool result = WriteFile(writeHandle, test, 3, ref geschrieben, IntPtr.Zero); Vielen Dank nochmals für deine Hilfe!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.