Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve HID keyboard LED state tracking #10

Closed
3 tasks
mame82 opened this issue Sep 6, 2018 · 1 comment
Closed
3 tasks

Improve HID keyboard LED state tracking #10

mame82 opened this issue Sep 6, 2018 · 1 comment
Assignees
Labels
Milestone

Comments

@mame82
Copy link
Collaborator

mame82 commented Sep 6, 2018

Currently only changes to the LED state of the HID keyboard are tracked, there's no way to determine the actual state itself. The problem behind this has more complexity as it seems on the first look.
LED tracking has two goals:

  1. Determine "keyboard input readiness" of a possible target (on Windows/Linux the keyboard driver sends the LED state once, when the driver is ready to receive keyboard input).
  2. Control the flow of HIDScripts by changing LED state by key pressing on the keyboard of target hosts (f.e. pressing NUMLOCK on the target keyboard changes the LED state, which on Windows/Linux is shared among all keyboards and thus could be read back by P4wnP1 and ultimately change control flow of a HID script)

One of the core features of the new HIDScript engine is to run multiple concurrent scripts which share the same resource (a single virtual keyboard and a single virtual mouse). The HIDScript methods utilizing the LED state changes are waitLED and waitLEDRepeat. To account for the first goal, determine keyboard input readiness, it has to be assured that no LED state change gets missed after connecting to a new USB host (connecting/disconnecting without rebooting P4wnP1 is another new feature). The waitLED method is intended to retrieve a single LED change and would trigger, in case the method is running when the initial LED state arrives from the target host. As it couldn't be assured that the user already runs the waitLED method, when the initial LED state arrives (which effectively is a state change, as no other state is known), all LED state events have to be preserved, until at least one script registers a listener for LED state changes (by calling waitLEDor waitLEDRepeat).

Currently this is accomplished like this:

  • HID keyboard LED output reports arrive in a dev file, which gets constantly read in a blocking loop (blocks reading when no new state is present).
  • one of the tasks of the reader loop is to "fan out" LED state changes to all registered listeners (waitLED or waitLEDRepeatinternally are registering such listeners).
  • this means: if no listener is registered, the loop blocks and no state change is read
  • not reading state changes, effectively means the kernel enqueues arriving states in FIFO fashion, till they are read from the dev file
  • the actual LED state is represented by the last HID output report of this queue, which couldn't be retrieved if no listener (waitLED/waitLEDRepeat) is registered

To have the latest LED state accessible, without missing any LED state change when needed (determine input readiness of USB host), the state queue of the kernel has to be moved into the P4wnP1 service. The optimal solution would be to use a channel as internal FIFO queue and to keep LED state changes till consumed. Before a new LED state is written to this channel, the current LED state could be updated. The shortcoming of this approach is, that such a channel has a defined, and thus limited, size. If LED state changes should be read constantly (in order to have latest state available), state changes have to be dropped, when the queue is full.

ToDos

  • introduce an additional (channel based) LED state queue to allow consuming all state changes as soon as they happen, without loosing history
  • before writing the latest state to this FIFO queue channel update global LED state

An additional problem is that the LED state is undefined, until the first LED output report arrives. From this point up the state is defined. Successively received LED states are interpreted as changes, if they differ from the last state. This only holds true, if P4wnP1 isn't disconnected from and reattached to the USB host. When this happens, the state has to be transferred back to undefined. To accomplish this, a trigger on USB attach/detach is needed to reset the state (see issue #6 )

  • once the needed trigger exists, reset LED state on USB disconnect/reconnect
@mame82 mame82 self-assigned this Sep 6, 2018
@mame82 mame82 added the HID label Sep 6, 2018
@mame82 mame82 added this to ToDo in P4wnP1 alpha release via automation Sep 6, 2018
@mame82 mame82 added this to the Alpha release milestone Sep 6, 2018
@mame82
Copy link
Collaborator Author

mame82 commented Nov 27, 2018

Invalid

@mame82 mame82 closed this as completed Nov 27, 2018
P4wnP1 alpha release automation moved this from ToDo to Done Nov 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

No branches or pull requests

1 participant