-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbtk.py
executable file
·163 lines (125 loc) · 4.1 KB
/
btk.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#! /usr/bin/env python
from __future__ import print_function
import dbus
import dbus.mainloop.glib
import dbus.service
try:
from gi.repository import GObject as gobject
except ImportError:
import gobject
import kb
import os
import sys
import bluetooth as bt
import uuid
import time
import glob
mainloop = None
keyboard = kb.Keyboard(glob.glob('/dev/input/by-id/usb*event-kbd')[0])
BUF_SIZE = 1024
PSM_CTRL = 0x11
PSM_INTR = 0x13
HIDP_HEADER_PARAM_MASK = 0x0f
HIDP_HEADER_TRANS_MASK = 0xf0
HIDP_HSHK_ERR_UNKNOWN = 0x0e
HIDP_HSHK_SUCCESSFUL = 0x00
HIDP_TRANS_DATA = 0xa0
HIDP_TRANS_HANDSHAKE = 0x00
HIDP_TRANS_SET_PROTOCOL = 0x70
class HIDConnection:
ctrl_fd = -1
intr_sock = None
ctrl_io_id = None
intr_id_id = None
kb = None
def __init__(self, ctrl_fd):
self.ctrl_fd = ctrl_fd
self.ctrl_io_id = gobject.io_add_watch(
self.ctrl_fd,
gobject.IO_IN,
self.ctrl_data_cb
)
def hello(self):
print('------hello-------')
os.write(self.ctrl_fd, b'\xa1\x13\x03')
os.write(self.ctrl_fd, b'\xa1\x13\x02')
time.sleep(1)
def ctrl_data_cb(self, fd, io_type):
data = os.read(fd, BUF_SIZE)
handshake = HIDP_TRANS_HANDSHAKE
msg_type = data[0] & HIDP_HEADER_TRANS_MASK
if msg_type & HIDP_TRANS_SET_PROTOCOL:
print('set protocol')
handshake |= HIDP_HSHK_SUCCESSFUL
os.write(fd, handshake)
return True
if msg_type & HIDP_TRANS_DATA:
print('data')
return True
print('unknown error')
handshake |= HIDP_HSHK_ERR_UNKNOWN
os.write(fd, handshake)
return True
def register_intr_sock(self, sock):
self.hello()
self.intr_sock = sock
keyboard.register_intr_sock(self.intr_sock)
def close(self):
pass
class HIDProfile(dbus.service.Object):
conns = {}
sock = None
def __init__(self, bus, path, sock):
dbus.service.Object.__init__(self, bus, path)
if (sock):
self.sock = sock
@dbus.service.method("org.bluez.Profile1",
in_signature="", out_signature="")
def Release(self):
print("Release")
mainloop.quit()
@dbus.service.method("org.bluez.Profile1",
in_signature="o", out_signature="")
def RequestDisconnection(self, path):
print('RequestDisconnection')
conns.pop(path).close()
@dbus.service.method("org.bluez.Profile1",
in_signature="oha{sv}", out_signature="")
def NewConnection(self, path, fd, properties):
print("new control connectin")
self.conns[path] = HIDConnection(fd.take())
def new_intr_conn(ssock, ip_type):
sock, info = ssock.accept()
print("interrput connection:", info)
self.conns[path].register_intr_sock(sock)
return False
gobject.io_add_watch(self.sock, gobject.IO_IN, new_intr_conn)
def main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
obj_path = '/ml/jlyu/HIDProfile'
sock = bt.BluetoothSocket(bt.L2CAP)
sock.setblocking(False)
try:
sock.bind(('', PSM_INTR))
except:
print("Someone has the bluetooth HID socket open, it might be bluetoothd")
print("For bluez5 add --noplugin=input to the bluetoothd commandline")
print("For bluez4 add PluginsDisable=input to /etc/bluetooth/main.conf")
print("Else there is another application running that has it open.")
sys.exit(errno.EACCES)
sock.listen(1)
profile = HIDProfile(bus, obj_path, sock)
opts = {
"PSM": dbus.UInt16(PSM_CTRL),
"ServiceRecord": open('./sdp_record.xml', 'r').read(),
"RequireAuthentication": dbus.Boolean(True),
"RequireAuthorization": dbus.Boolean(False),
}
dbus.Interface(
bus.get_object("org.bluez", "/org/bluez"),
"org.bluez.ProfileManager1"
).RegisterProfile(obj_path, str(uuid.uuid4()), opts)
gobject.MainLoop().run()
if __name__ == '__main__':
main()