kb_client.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #!/usr/bin/python
  2. #
  3. # YAPTB Bluetooth keyboard emulation service
  4. # keyboard copy client.
  5. # Reads local key events and forwards them to the btk_server DBUS service
  6. #
  7. # Adapted from www.linuxuser.co.uk/tutorials/emulate-a-bluetooth-keyboard-with-the-raspberry-pi
  8. #
  9. #
  10. import os #used to all external commands
  11. import sys # used to exit the script
  12. import dbus
  13. import dbus.service
  14. import dbus.mainloop.glib
  15. import time
  16. import evdev # used to get input from the keyboard
  17. from evdev import *
  18. import keymap # used to map evdev input to hid keodes
  19. #Define a client to listen to local key events
  20. class Keyboard():
  21. def __init__(self):
  22. #the structure for a bt keyboard input report (size is 10 bytes)
  23. self.state=[
  24. 0xA1, #this is an input report
  25. 0x01, #Usage report = Keyboard
  26. #Bit array for Modifier keys
  27. [0, #Right GUI - Windows Key
  28. 0, #Right ALT
  29. 0, #Right Shift
  30. 0, #Right Control
  31. 0, #Left GUI
  32. 0, #Left ALT
  33. 0, #Left Shift
  34. 0], #Left Control
  35. 0x00, #Vendor reserved
  36. 0x00, #rest is space for 6 keys
  37. 0x00,
  38. 0x00,
  39. 0x00,
  40. 0x00,
  41. 0x00]
  42. print "setting up DBus Client"
  43. self.bus = dbus.SystemBus()
  44. self.btkservice = self.bus.get_object('org.yaptb.btkbservice','/org/yaptb/btkbservice')
  45. self.iface = dbus.Interface(self.btkservice,'org.yaptb.btkbservice')
  46. print "waiting for keyboard"
  47. #keep trying to key a keyboard
  48. have_dev = False
  49. while have_dev == False:
  50. try:
  51. #try and get a keyboard - should always be event0 as
  52. #we're only plugging one thing in
  53. self.dev = InputDevice("/dev/input/event0")
  54. have_dev=True
  55. except OSError:
  56. print "Keyboard not found, waiting 3 seconds and retrying"
  57. time.sleep(3)
  58. print "found a keyboard"
  59. def change_state(self,event):
  60. evdev_code=ecodes.KEY[event.code]
  61. modkey_element = keymap.modkey(evdev_code)
  62. if modkey_element > 0:
  63. if self.state[2][modkey_element] == 0:
  64. self.state[2][modkey_element] = 1
  65. else:
  66. self.state[2][modkey_element] = 0
  67. else:
  68. #Get the keycode of the key
  69. hex_key = keymap.convert(ecodes.KEY[event.code])
  70. #Loop through elements 4 to 9 of the inport report structure
  71. for i in range(4,10):
  72. if self.state[i]== hex_key and event.value == 0:
  73. #Code 0 so we need to depress it
  74. self.state[i] = 0x00
  75. elif self.state[i] == 0x00 and event.value == 1:
  76. #if the current space if empty and the key is being pressed
  77. self.state[i]=hex_key
  78. break
  79. #poll for keyboard events
  80. def event_loop(self):
  81. for event in self.dev.read_loop():
  82. #only bother if we hit a key and its an up or down event
  83. if event.type==ecodes.EV_KEY and event.value < 2:
  84. self.change_state(event)
  85. self.send_input()
  86. #forward keyboard events to the dbus service
  87. def send_input(self):
  88. bin_str=""
  89. element=self.state[2]
  90. for bit in element:
  91. bin_str += str(bit)
  92. self.iface.send_keys(int(bin_str,2),self.state[4:10])
  93. if __name__ == "__main__":
  94. print "Setting up keyboard"
  95. kb = Keyboard()
  96. print "starting event loop"
  97. kb.event_loop()