Notice: This forum has been recovered from an old backup, so some content, links, and dates may be outdated. The forum is currently read-only while we restore sign-in and registration functionality. Details

If you find this forum valuable and would like to help keep it online, donations to help cover hosting and domain costs are greatly appreciated, but never expected. You can support the forum through Buy Me a Coffee or Ko-fi. Thank you for helping preserve the EventGhost community.

HID PlugIn

Allgemeines zum Thema EventGhost
Bartman
Plugin Developer
Posts: 881
Joined: Sun Feb 12, 2006 9:03 am

HID PlugIn

Post by Bartman »

Wir haben ja schon mal ├╝ber das HID-Thema geredet und ich habe heute noch mal nachgeforscht.
Anscheinend kann man das recht einfach mit Boardmitteln l├Âsen, da man die Ger├ñte einfach wie eine Datei ├Âffnen und lesen kann.

Damit kann ich z.B. einen Tastendruck auf meinem GameVoice auslesen. Zum PlugIn fehlt zwar noch einiges, aber ist ja schon mal ein Anfang.

Code: Select all

import win32file
import win32con
import binascii

print "starting"

name = "\\\\?\HID#Vid_045e&Pid_003b#7&195e397&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"

handle = win32file.CreateFile(
    name,
    win32con.GENERIC_READ|win32con.GENERIC_WRITE,
    win32con.FILE_SHARE_READ | win32con.FILE_SHARE_WRITE,
    None, # no security
    win32con.OPEN_EXISTING,
    0,
    0
)

buffer = win32file.AllocateReadBuffer(2)

err, data = win32file.ReadFile(handle, buffer)
if err == 0:
    print binascii.hexlify(data)
else:
    eg.PrintError("Error")
    
win32file.CloseHandle(handle)

print "finished"
User avatar
Bitmonster
Site Admin
Posts: 2239
Joined: Mon Feb 06, 2006 10:28 pm

Post by Bitmonster »

Ja, das Problem ist nur, dass jedes Gerät anders arbeitet. Viele HID-FBs machen z.B. einen Teil der Tasten als HID-Keyboard und das wird dann nicht so einfach. Hatte ich hier mal erwähnt:
http://www.eventghost.org/forum/viewtopic.php?t=167

Bei den generischen HID-Devices (die dann nach Maus und Keyboard übrig bleiben), gibt es dann kein festgelegtes Format der Daten. Da muss man also wieder für jedes Gerät experimentieren.

Über die HID-Descriptoren sollten solche FBs zwar ihre Tasten bekannt machen, aber da wird es dann kompliziert die zu enumerieren.

(Ich hab hier noch einen 600 Seiten Wälzer über USB/HID rumliegen. Aber noch nicht viel Lust gehabt ihn durchzulesen.)
Bartman
Plugin Developer
Posts: 881
Joined: Sun Feb 12, 2006 9:03 am

Post by Bartman »

Für den einfachen Fall wäre die einfache Bytefolge doch auch schon was.
Gibt es denn wirklich Fernbedienungen, die eine Standardtaste wie 1 oder einen Buchstaben als HID-Keyboard an Windows schicken?
Sowas wie Play/Pause oder Stopp wäre ja noch halbwegs sinnvoll und würden dann durch das Keyboard PlugIn erkennbar.
User avatar
Bitmonster
Site Admin
Posts: 2239
Joined: Mon Feb 06, 2006 10:28 pm

Post by Bitmonster »

Bartman wrote:Gibt es denn wirklich Fernbedienungen, die eine Standardtaste wie 1 oder einen Buchstaben als HID-Keyboard an Windows schicken?
Ja, die gibt es:
http://www.eventghost.org/forum/viewtop ... =1860#1860
Bartman
Plugin Developer
Posts: 881
Joined: Sun Feb 12, 2006 9:03 am

Post by Bartman »

ich mach mich trotzdem mal dran, um wenigstens meine Zusatztasten nutzen zu k├Ânnen. Da m├╝ssen die Fernbedienungsnutzer dann mal testen, was passiert.
An die Ger├ñte, die sich als Tastatur oder Maus ausgeben kommt man anscheinend eh nicht per Standarddateizugriff ran, weil die exklusiv vom OS ge├Âffnet werden. Da muss dann wieder per RawInput dran. Vielleicht schau ich mir das mal irgendwann mal an, weil so wie es aussieht gibt es f├╝r neuere Betriebssysteme keine Treiber von Logitech f├╝r meine M├ñuse, so dass ich die ganzen zus├ñtzlichen Tasten nicht nutzen k├Ânnte.

Ich habe da aber grade zwei kleine Probleme:
Ich gebe in der Configure Methode des PlugIns ein dictionary zurück. Wenn dann die Startmethode aufgerufen wird scheinen die Einträge des Dictionary entpackt zu sein und die Anzahl der Argument passt entsprechend nicht.

Ich suche grade eine Eingabekomponente, die in einer Art Tabelle die Geräte auflistet, wo aber eine Spalte editierbar sein soll.

War es eigentlich schon immer so, dass PlugIns beim Aufruf des Konfigurationsdialogs gestoppt und dann wieder gestartet werden?
Das beendet nämlich beim Timer-Plugin effektiv alle laufenden Timer.

Und dann hab ich noch eine Frage, wie das mit dem HotPlug von Geräten gehandhabt werden soll. Zumindest beim USB_UIRT wird das bislang ja gar nicht gehandhabt und es knallt auch nach dem Wiederanstecken beim Senden und es wird nichts empfangen.
User avatar
Bitmonster
Site Admin
Posts: 2239
Joined: Mon Feb 06, 2006 10:28 pm

Post by Bitmonster »

Bartman wrote:Ich habe da aber grade zwei kleine Probleme:
Ich gebe in der Configure Methode des PlugIns ein dictionary zurück. Wenn dann die Startmethode aufgerufen wird scheinen die Einträge des Dictionary entpackt zu sein und die Anzahl der Argument passt entsprechend nicht.
Gibst du denn das Dict auch als Teil des Return-Tupels zur├╝ck?
Bartman wrote:Ich suche grade eine Eingabekomponente, die in einer Art Tabelle die Geräte auflistet, wo aber eine Spalte editierbar sein soll.
Im wxPythonDemo ist so eine Liste unter "ListCtrl". Habe mir aber noch nicht genauer angesehen, wie die das gemacht haben. Anscheinend ├╝ber irgendwelche MixIn-Klassen.
Bartman wrote:War es eigentlich schon immer so, dass PlugIns beim Aufruf des Konfigurationsdialogs gestoppt und dann wieder gestartet werden?
Das beendet nämlich beim Timer-Plugin effektiv alle laufenden Timer.
Das sollte nur passieren, wenn sich die Parameter geändert haben. Das Timer Plugin hat doch eigentlich gar keine Parameter, oder?
Bartman
Plugin Developer
Posts: 881
Joined: Sun Feb 12, 2006 9:03 am

Post by Bartman »

Die Demo suche ich mal raus.
Ich habe in das Posting vorher noch einen Satz zum HotPlug reineditiert.

Das Timer Plugin macht derzeit

Code: Select all

def Configure(self, *args):
...
        if dialog.AffirmedShowModal():
            return args
Nach einem OK ist die Liste jedenfalls leer. Bei meinem HID Plugin sah das auch so aus, als ob das immer neugestartet wurde.
User avatar
Bitmonster
Site Admin
Posts: 2239
Joined: Mon Feb 06, 2006 10:28 pm

Post by Bitmonster »

Ich glaube HotPlug-Unterst├╝tzung k├Ânnen wir uns zur Zeit sparen. Ein Neustart von EG ist ja kein Beinbruch.

Das mit den Plugin-Neustart ist tatsächlich ein Bug, der wohl bei dem Undo-Kram entstanden ist. Wird demnächst gefixt.
Bartman
Plugin Developer
Posts: 881
Joined: Sun Feb 12, 2006 9:03 am

Post by Bartman »

Ich bekomme manchmal beim Starten von EG folgenden Fehler. Danach geht praktisch gar nichts mehr und ich kann EG nur noch per Taskmanager beenden.
Wenn ein einfacher Kompilierungsfehler vorliegt wird doch sonst auch sch├Ân die Zeile angezeigt.

Code: Select all

22:14:28 Traceback (most recent call last):
22:14:28   File "D:\Media\EventGhost\eg\ThreadWorker.py", line 87, in DoOneEvent
22:14:28   File "D:\Media\EventGhost\eg\ThreadWorker.py", line 32, in __call__
22:14:28   File "D:\Media\EventGhost\eg\ActionThread.py", line 37, in StartSession
22:14:28   File "D:\Media\EventGhost\eg\MainFrame.py", line 421, in OnAutoLoad
22:14:28   File "D:\Media\EventGhost\eg\Document.py", line 106, in Load
22:14:28   File "D:\Media\EventGhost\eg\TreeItems\RootItem.py", line 31, in __init__
22:14:28   File "D:\Media\EventGhost\eg\TreeItems\ContainerItem.py", line 21, in __init__
22:14:28   File "D:\Media\EventGhost\eg\TreeItems\AutostartItem.py", line 9, in __init__
22:14:28   File "D:\Media\EventGhost\eg\TreeItems\ContainerItem.py", line 21, in __init__
22:14:28   File "D:\Media\EventGhost\eg\TreeItems\PluginItem.py", line 74, in __init__
22:14:28   File "pickle.pyc", line 1374, in loads
22:14:28   File "pickle.pyc", line 858, in load
22:14:28   File "pickle.pyc", line 1090, in load_global
22:14:28   File "pickle.pyc", line 1124, in find_class
22:14:28 ImportError: No module named HID
User avatar
Bitmonster
Site Admin
Posts: 2239
Joined: Mon Feb 06, 2006 10:28 pm

Post by Bitmonster »

Sieht so aus, als ob du dem Plugin irgendeine Klassen-Instanz (namens HID) als Parameter ├╝bergibst. Als Parameter sind nur "built-in" Typen wie int, string, bool, sowie Listen, Tupel und Dictionarys daraus erlaubt.
Bartman
Plugin Developer
Posts: 881
Joined: Sun Feb 12, 2006 9:03 am

Post by Bartman »

ich habe eine Klasse HIDInfo in der ich die Infos zu ausgewählten Geräte speichere und ein paar Convenience-Funktionen eingebaut habe.
Ein Dictionary mit Instanzen der Klasse wollte ich dann als Datenstruktur abspeichern.
Geht das gar nicht?
User avatar
Bitmonster
Site Admin
Posts: 2239
Joined: Mon Feb 06, 2006 10:28 pm

Post by Bitmonster »

Nein, das geht zur Zeit nicht. Vielleicht irgendwann mal, aber das wird ziemlich kompliziert. Denn die Pickle-Funktion erlaubt nur das erstellen von Instanzen, deren Klassen es vorher schon kennt.

Workaround:
Wenn du dein Dict in Configure speicherst, dann speichere die __dict__ der Instanzen:

Code: Select all

newDict = {}
for key, value in oldDict.items():
  newDict[key] = value.__dict__
Wenn dann dieses Dict an deine __start__ Methode kommt, musst du die Instanzen selber erzeugen und deren Dict mit den Parametern updaten:

Code: Select all

def __start__(self, myDict):
    for key, value in myDict.items():
        inst = HIDInfo()
        inst.__dict__.update(value)
Bartman
Plugin Developer
Posts: 881
Joined: Sun Feb 12, 2006 9:03 am

Post by Bartman »

Ich habe jetzt eine einfache Version, allerdings fliegt es mir meistens beim HidP_GetCaps Aufruf um die Ohren. Irgendwas stimmt da wohl mit dem Pointer nicht. Gelegentlich klappt es aber. Ich kapier aber nicht, was falsch ist.
Last edited by Bartman on Mon Feb 12, 2007 11:06 am, edited 1 time in total.
User avatar
Bitmonster
Site Admin
Posts: 2239
Joined: Mon Feb 06, 2006 10:28 pm

Post by Bitmonster »

Bei mir scheint es eher in der win32file.ReadFile-Schleife zu knallen. Ich komme aber auch gerade nicht dahinter, was da los ist.

Probierst du das mit der normalen EG.exe aus oder welche Entwicklungsumgebung nutzt du? Solches Debugging mit "print" Anweisungen kann leicht t├╝ckisch sein, weil EG dann beim Absturz gar nicht die Zeit hat noch die letzten Ausgaben zu machen.

EDIT: Oder anders gesagt: die Ausgabe im Logger erfolgt asynchron.
Bartman
Plugin Developer
Posts: 881
Joined: Sun Feb 12, 2006 9:03 am

Post by Bartman »

Ich nehm einfach die normale EG.
Bei den print Ausgaben habe ich schon mal ein time.sleep eingebaut.
Es gibt wohl die M├Âglichkeiten
  • HidP_GetCaps greift au├ƒerhalb des zugeteilten Speichers zu -> EG st├╝rzt komplett ab
  • Die HIDP_CAPS Structure nicht wird nicht beschrieben -> Puffer mit Gr├Â├ƒe 0 wird angelgt -> Readfile f├ñllt auf die Nase
  • alles klappt
Post Reply