I have Project Cars for the PS4 and found out that I can use a keyboard with it for extra controls. Since I can use the keyboard to engage each gear (like a H-Patten gear stick for steering wheels can), I am thinking of making a H-patten gearbox my self with the rPI.

How would I allow my Raspberry Pi to keystroke a button press like a usb keyboard would?

I have looked at this tutorial, however I cannot seem to find a way to simply keystroke one key (programatically) and get it to connect (tried paring it to my Mac and it would connect then one second later it would disconnect).

In simple terms I would like a script (preferbaly python) where I can send a keystroke by doing send_key('1') and that would pretend to press a '1' on a bluetooth keyboard which the game will pick up.

Sorry if this is hard to understand. I wasn't sure how to work this. Please ask me to explain anything you found hard to understand.

  • Just to clarify, you want the Pi to act as a remote bluetooth keyboard that is paired to a PS4 where you can send arbitrary "key presses" programatically? – rob Aug 4 '15 at 8:58
  • @rob Yes. In the end I want to send a keypress when a GPIO input is enabled. – iProgram Aug 4 '15 at 9:48
  • I would suggest that you reword your question to something like "Emulating bluetooth keyboard with raspberry pi" – rob Aug 4 '15 at 10:21

In Step 20 of the tutorial you mentioned, all that is happening is that the script listens for keyboard input on the raspberry pi, and then sends that over Bluetooth. If you simply want to instantiate the Bluetooth connection and then send keystrokes programmatically and finally exit you just need to replace the call to kb.event_loop(bt) with something like bt.send_input(self.state) and of course manually set the self.state structure. As described in Step 17, the input reports are made of 9 bytes and prefixed with a byte indicating that the remaining bytes are an input report (0xA1). You will need to instantiate the report with 9 values and do the following things:

  1. assign 0x01 to the first byte in the array, which will basically tell the bluetooth device that you are working with a keyboard input report.
  2. the second byte is used to specify any modifier keys (alt, shift, ctrl etc.) which is useful if you need to hold down shift to sprint in the game.
  3. the third byte you shouldn't touch.
  4. The other 6 bytes you should use to specify which keys you want to simulate in form of Bluetooth key constants provided in the keymap.py file.

All you need to do is to pass an array with this content to bt.send_input Here is an example of what the structure could look like:

self.state = [
 0xA1, # This is an input report
 0x01, # Usage report = Keyboard
 # Bit array for Modifier keys
 [0,   # Right GUI - (usually the Windows key)
  0,   # Right ALT
  0,   # Right Shift
  0,   # Right Control
  0,   # Left GUI - (again, usually the Windows key)
  0,   # Left ALT
  1,   # Left Shift is pressed
  0],   # Left Control
 0x00,  # Vendor reserved
 0x04,  # The W key is pressed
 0x00 ]

The hex array would be something like this in hex:

This would simulate that you hold left shift and the w key. You should probably use keymap.modkey(ecodes.KEY_W) for readability.

For further information I found this github repository which I think could be useful for you. Also you should read the documentation for python-evdev here.

Unfortunately I can't test this as I haven't got a raspberry pi available now, but I think you should be able to figure it out, good luck!

| improve this answer | |
  • Thanks for giving me more information on this! So do you mean I should change kb.event_loop(bt) to bt.send_input(bt.send_serial(keymap.modkey(ecodes.KEY_W)))? – iProgram Aug 6 '15 at 20:32
  • Sorry, send_serial should of course be send_input. You need to pass a list of bytes to send_input which will convert the hex array to a string that can be sent of Bluetooth. You need manually modify that hex array as above for it to work. Currently the change_state function takes an evdev event and changes the keyboard’s state and populates the hex array for you. Look at the example structure above. You should replace the kb.event_loop function which would be blocking your program to bt.send_input(self.state) which you have instantiated manually. – Linus Aug 6 '15 at 21:05
  • Thanks for the reply. Would I be able to change self.state to encodes.KEY_W? If so would 1 be encodes.KEY_1? – iProgram Aug 6 '15 at 21:55
  • Have a look at keymap.py there is all the Bluetooth HID codes, you can use any of those you wish. Now, to make it clear take a look at this pastebin, maybe it will be easier to understand if you can see the code. – Linus Aug 6 '15 at 22:42
  • What I've done is put keymap.modkey(ecodes.KEY_W) on the first byte reserved for key events you wish to send via Bluetooth, but you can replace ecodes.KEY_W with any other key you find in the keysmap.py file (e.g KEY_1). The keymap.modkey function is only used for readability, but you could use 30 instead. You have to use that structure because otherwise the send_input function wouldn't understand what it is supposed to do with that value. It's like trying to give a string to a function expecting an integer, you simply can't! – Linus Aug 6 '15 at 22:45


You can just ignore evdev package and establish BT2BT socket connection and focus on send_input() funtion.

Let me know which Bluetooth USB dongle you preferred to do this activity?

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.