Eigenen Tastatur Treiber programmieren

Hardware- und Elektronikbasteleien, Ansteuerung von Schnittstellen und Peripherie.
Fragen zu "Consumer"-Problemen kommen in Offtopic.
¯\_(ツ)_/¯
Beiträge: 141
Registriert: 18.08.2017 09:35

Eigenen Tastatur Treiber programmieren

Beitrag von ¯\_(ツ)_/¯ »

Moin moin,
ich möchte gerne einen eigenen USB Treiber für eine Tastatur programmieren damit ich Zugriff auf die Tasten habe die ich umprogrammieren bzw. selber bestimmen kann was dann passieren soll wenn man auf die jeweiligen Tasten drückt.
Nein dieser Treiber soll kein Trojaner werden. Dieser Treiber soll nur für mich sein.
Es gibt zwar Windows Software zum Umlenken der Tasten aber ich möchte über einen eigenen Treiber machen da ich damit auch bestimmen kann von welcher Tastatur die Keycodes kommen.
Jemand eine Idee wie ich anfangen kann und was ich machen muss? Mit PB ist es bestimt nicht möglich. Mit C? Oder muss es ASM sein?
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Eigenen Tastatur Treiber programmieren

Beitrag von RSBasic »

Ich weiß nicht, ob es dir weiterhilft: https://www.pjrc.com/teensy/usb_keyboard.html
Ansonsten gibt es auch was fertiges.
Eine Tastatur mit 20 programmierbaren Tasten: https://www.amazon.de/Expertkeys-EK-20- ... e+tastatur
Eine Tastatur mit 58 programmierbaren Tasten: https://www.amazon.de/Expertkeys-EK-58- ... e+tastatur
Eine Tastatur mit 128 programmierbaren Tasten: https://www.amazon.de/Expertkeys-EK-128 ... e+tastatur
Oder wenn du eine Tastatur mit LCD-Tasten haben möchtest: https://www.amazon.de/Elgato-Stream-Dec ... e+tastatur
Oder wenn du selber bauen möchtest, was deutlich günstiger ist, kannst du auf Amazon nach "button matrix" suchen.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
DePe
Beiträge: 153
Registriert: 26.11.2017 16:17
Wohnort: Wien
Kontaktdaten:

Re: Eigenen Tastatur Treiber programmieren

Beitrag von DePe »

Vom User_Russian gibt es einen Beitrag, ich habe ihn einmal gespeichert, aber nicht genau durchgelesen:

Driver development using PureBasic
https://www.purebasic.fr/english/viewtopic.php?p=404498

Peter
¯\_(ツ)_/¯
Beiträge: 141
Registriert: 18.08.2017 09:35

Re: Eigenen Tastatur Treiber programmieren

Beitrag von ¯\_(ツ)_/¯ »

Danke für eure Antworts. Hardware bauen will ich nicht und fertiges kaufen ist zwar sehr nice aber extrem teuer.
USB Treiber wäre am besten. Kann jemand ihn dort anschreiben ob ein USB Treiber für eine Tastatur möglich ist um Keycodes pro Tastatur zu empfangen und zu steuern?
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Eigenen Tastatur Treiber programmieren

Beitrag von RSBasic »

Ich habe für dich in dem Thread deine Frage gestellt.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Eigenen Tastatur Treiber programmieren

Beitrag von RSBasic »

Ich habe da eine viel bessere und leichtere Lösung ohne Treiber gefunden und zwar mit der WinAPI-Funktion GetRawInputData_().
Damit kannst du die Eingabe von jeder Tastatur unterschieden. Siehe *pRawData\header\hDevice
Code: https://www.purebasic.fr/english/viewto ... 13&t=66655
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
¯\_(ツ)_/¯
Beiträge: 141
Registriert: 18.08.2017 09:35

Re: Eigenen Tastatur Treiber programmieren

Beitrag von ¯\_(ツ)_/¯ »

Danke für beides :) Wie kann ich bei dem Code die Eingabe unterbrechen und stattdessen was anderes machen? Ich mein ich drücke die Taste A und er soll A nicht ausgeben sondern ein Programm starten. Wie mache ich im Code das? Also genauso wie der Code https://www.rsbasic.de/aktualisierung/w ... ardHook.pb aus deiner tollen Winapi Lib nur da kann ich nicht herausfinden von welchem Tastatur Gerät die gedrückte Taste stammt.
Bild
¯\_(ツ)_/¯
Beiträge: 141
Registriert: 18.08.2017 09:35

Re: Eigenen Tastatur Treiber programmieren

Beitrag von ¯\_(ツ)_/¯ »

Ich habe beide Codes kombiniert aber warum wird KeyboardHook immer vor Callback aufgerufen? Selbst ein Delay kann ich die Reihenfolge nicht verändern.

Code: Alles auswählen

EnableExplicit



#RID_HEADER         = $10000005 ; get header structure
#RID_INPUT         = $10000003  ; get whole RAWINPUT structure

; Types of raw input data
#RIM_TYPEMOUSE       = 0
#RIM_TYPEKEYBOARD   = 1
#RIM_TYPEHID      = 2

; RAWINPUTDEVICE flags
#RIDEV_REMOVE       = $00000001
#RIDEV_EXCLUDE      = $00000010
#RIDEV_PAGEONLY    = $00000020
#RIDEV_NOLEGACY      = $00000030
#RIDEV_INPUTSINK     = $00000100
#RIDEV_CAPTUREMOUSE   = $00000200
#RIDEV_NOHOTKEYS   = $00000200
#RIDEV_APPKEYS      = $00000400
#RIDEV_EXINPUTSINK   = $00001000
#RIDEV_DEVNOTIFY   = $00002000

; GetRawInputDeviceInfo() flags
#RIDI_PREPARSEDDATA = $20000005 ; returns previously parsed data
#RIDI_DEVICENAME    = $20000007 ;- a string containing the device name
#RIDI_DEVICEINFO    = $2000000b ;- an RIDI_DEVICE_INFO Structure

Prototype GetRawInputData(hRawInput, uiCommand, *pData.RAWINPUT, *pcbSize, cbSizeHeader)
Prototype RegisterRawInputDevices(*pRawInputDevices.RAWINPUTDEVICE, *uiNumDevices, cbSize)
Prototype GetRawInputDeviceList(*pRawInputDeviceList.RAWINPUTDEVICELIST, *uiNumDevices, cbSize)
Prototype GetRawInputDeviceInfo(hDevice, uiCommand, *pData, *pcbSize)



; import functions
Global User32_dll = OpenLibrary(#PB_Any, "user32.dll")
If IsLibrary(User32_dll)
  Global RegisterRawInputDevices.RegisterRawInputDevices   = GetFunction(User32_dll, "RegisterRawInputDevices")
  Global GetRawInputData.GetRawInputData               = GetFunction(User32_dll, "GetRawInputData")
  Global GetRawInputDeviceList.GetRawInputDeviceList      = GetFunction(User32_dll, "GetRawInputDeviceList")
  Global GetRawInputDeviceInfo.GetRawInputDeviceInfo      = GetFunction(User32_dll, "GetRawInputDeviceInfoW")
EndIf

Procedure WinCallback (hWnd, Message, WParam, LParam)
  Select Message       
    Case #WM_INPUT: ; Raw Input
      
      Protected pcbSize.l
      Protected *pRawData.RAWINPUT
      If GetRawInputData(lParam, #RID_INPUT, #Null, @pcbSize, SizeOf(RAWINPUTHEADER)) = 0
        *pRawData = AllocateMemory(pcbSize) ; If input is from HID-device, data size can vary
        If *pRawData
          GetRawInputData(lParam, #RID_INPUT, *pRawData, @pcbSize, SizeOf(RAWINPUTHEADER))
          Select *pRawData\header\dwType
            Case #RIM_TYPEKEYBOARD:
              ; here input is collected
              Debug "Vk " + Str(*pRawData\keyboard\VKey) + " from device " + Str(*pRawData\header\hDevice)
          EndSelect
          
          FreeMemory(*pRawData)
        EndIf
        
      EndIf
  EndSelect
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure




Procedure.l KeyboardHook(nCode, wParam, *p.KBDLLHOOKSTRUCT)
  If wParam = #WM_KEYDOWN Or wParam = #WM_SYSKEYDOWN Or wParam = #WM_KEYUP Or wParam = #WM_SYSKEYUP
    If *p\vkCode = 65
      ;Delay(1000)
      Debug "AAA"
    EndIf
  EndIf
  ProcedureReturn CallNextHookEx_(0, nCode, wParam, *p)
EndProcedure



If OpenWindow(0,0,0,500,250,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  
  SetWindowsHookEx_(#WH_KEYBOARD_LL,@KeyboardHook(),GetModuleHandle_(0),0)
  
  
  SetWindowCallback(@WinCallback())
  
  ; set raw input capture for all mouses and keyboards
  Dim Rid.RAWINPUTDEVICE(0)
  Rid(0)\usUsagePage  = 1
  Rid(0)\usUsage      = 0
  Rid(0)\hwndTarget   = WindowID(0)
  Rid(0)\dwFlags      = #RIDEV_INPUTSINK | #RIDEV_PAGEONLY
  
  RegisterRawInputDevices (@Rid(), ArraySize(Rid()) + 1, SizeOf(RAWINPUTDEVICE))
  
  
  
  
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Was ich will: Ich möchte zuerst prüfen auf welcher Tastatur die Taste gedrückt wurde und erst danach möchte ich im KeyboardHook entscheiden was danach passieren soll. D.h. "AAA" soll erst nach "Vk xxx from device xxx" erscheinen. Wie mache ich das?
Bild
¯\_(ツ)_/¯
Beiträge: 141
Registriert: 18.08.2017 09:35

Re: Eigenen Tastatur Treiber programmieren

Beitrag von ¯\_(ツ)_/¯ »

Ich habe nachgelesen dass man dafür #WH_KEYBOARD und nicht #WH_KEYBOARD_LL benutzen soll. Damit erreiche ich zwar die richtige Reihenfolge also zuerst "Vk xxx from device xxx" und danach "AAA" ABER leider arbeitet #WH_KEYBOARD nicht global sondern nur innerhalb meines eigenen Fensters. Wie kann ich das beheben?

Hier mein umgebauter Code:

Code: Alles auswählen

EnableExplicit



#RID_HEADER         = $10000005 ; get header structure
#RID_INPUT         = $10000003  ; get whole RAWINPUT structure

; Types of raw input data
#RIM_TYPEMOUSE       = 0
#RIM_TYPEKEYBOARD   = 1
#RIM_TYPEHID      = 2

; RAWINPUTDEVICE flags
#RIDEV_REMOVE       = $00000001
#RIDEV_EXCLUDE      = $00000010
#RIDEV_PAGEONLY    = $00000020
#RIDEV_NOLEGACY      = $00000030
#RIDEV_INPUTSINK     = $00000100
#RIDEV_CAPTUREMOUSE   = $00000200
#RIDEV_NOHOTKEYS   = $00000200
#RIDEV_APPKEYS      = $00000400
#RIDEV_EXINPUTSINK   = $00001000
#RIDEV_DEVNOTIFY   = $00002000

; GetRawInputDeviceInfo() flags
#RIDI_PREPARSEDDATA = $20000005 ; returns previously parsed data
#RIDI_DEVICENAME    = $20000007 ;- a string containing the device name
#RIDI_DEVICEINFO    = $2000000b ;- an RIDI_DEVICE_INFO Structure

Prototype GetRawInputData(hRawInput, uiCommand, *pData.RAWINPUT, *pcbSize, cbSizeHeader)
Prototype RegisterRawInputDevices(*pRawInputDevices.RAWINPUTDEVICE, *uiNumDevices, cbSize)
Prototype GetRawInputDeviceList(*pRawInputDeviceList.RAWINPUTDEVICELIST, *uiNumDevices, cbSize)
Prototype GetRawInputDeviceInfo(hDevice, uiCommand, *pData, *pcbSize)



; import functions
Global User32_dll = OpenLibrary(#PB_Any, "user32.dll")
If IsLibrary(User32_dll)
  Global RegisterRawInputDevices.RegisterRawInputDevices   = GetFunction(User32_dll, "RegisterRawInputDevices")
  Global GetRawInputData.GetRawInputData               = GetFunction(User32_dll, "GetRawInputData")
  Global GetRawInputDeviceList.GetRawInputDeviceList      = GetFunction(User32_dll, "GetRawInputDeviceList")
  Global GetRawInputDeviceInfo.GetRawInputDeviceInfo      = GetFunction(User32_dll, "GetRawInputDeviceInfoW")
EndIf

Procedure WinCallback (hWnd, Message, WParam, LParam)
  Select Message       
    Case #WM_INPUT: ; Raw Input
      
      Protected pcbSize.l
      Protected *pRawData.RAWINPUT
      If GetRawInputData(lParam, #RID_INPUT, #Null, @pcbSize, SizeOf(RAWINPUTHEADER)) = 0
        *pRawData = AllocateMemory(pcbSize) ; If input is from HID-device, data size can vary
        If *pRawData
          GetRawInputData(lParam, #RID_INPUT, *pRawData, @pcbSize, SizeOf(RAWINPUTHEADER))
          Select *pRawData\header\dwType
            Case #RIM_TYPEKEYBOARD:
              ; here input is collected
              Debug "Vk " + Str(*pRawData\keyboard\VKey) + " from device " + Str(*pRawData\header\hDevice)
          EndSelect
          
          FreeMemory(*pRawData)
        EndIf
        
      EndIf
  EndSelect
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


Global hook

; Procedure.l KeyboardHook(nCode, wParam, *p.KBDLLHOOKSTRUCT)
;   If wParam = #WM_KEYDOWN Or wParam = #WM_SYSKEYDOWN Or wParam = #WM_KEYUP Or wParam = #WM_SYSKEYUP
;     If *p\vkCode = 65
;       ;Delay(1000)
;       Debug "AAA"
;     EndIf
;   EndIf
;   ProcedureReturn CallNextHookEx_(0, nCode, wParam, *p)
; EndProcedure

Procedure.l KeyboardHook(nCode.i, wParam.i, lParam.i)

  
  If wParam = 65
    Debug "AAA"
    ProcedureReturn 1
  EndIf
  
  
ProcedureReturn CallNextHookEx_(hook, nCode, wParam, lParam)
EndProcedure



If OpenWindow(0,0,0,500,250,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  
  ;SetWindowsHookEx_(#WH_KEYBOARD_LL,@KeyboardHook(),GetModuleHandle_(0),0)
  hook = SetWindowsHookEx_(#WH_KEYBOARD,@KeyboardHook(),GetModuleHandle_(0),GetWindowThreadProcessId_(WindowID(0), 0))
  
  
  SetWindowCallback(@WinCallback())
  
  ; set raw input capture for all mouses and keyboards
  Dim Rid.RAWINPUTDEVICE(0)
  Rid(0)\usUsagePage  = 1
  Rid(0)\usUsage      = 6
  Rid(0)\hwndTarget   = WindowID(0)
  Rid(0)\dwFlags      = #RIDEV_INPUTSINK
  
  RegisterRawInputDevices (@Rid(), ArraySize(Rid()) + 1, SizeOf(RAWINPUTDEVICE))
  
  
  
  
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Bild
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Eigenen Tastatur Treiber programmieren

Beitrag von RSBasic »

Wenn du #WH_KEYBOARD und global (letzter Parameter durch 0 ersetzen) verwenden möchtest, dann musst du es in eine DLL-Datei auslagern.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Antworten