HID Device端的逻辑稍微复杂一点,需要先设计一下。
首先,我需要一个GUI窗口,它不用显示什么,而是要帮我捕获鼠标和键盘事件。当这个GUI窗口在前端时,如果我的鼠标在这个GUI窗口上移动或点击,或者按下键盘按键,这个GUI窗口必须能接收到这些Input事件。然后,把这些Input事件转译成HID Report,并调用之前实现的蓝牙接口,通过HID Interrupt通道,发送到蓝牙主机那里。
所以,我需要两个角色:一个Input事件的捕获者,以及一个HID事件的报告者。当捕获者抓到一个Input事件后,把它告诉报告者,由报告者调用蓝牙接口发送出去。
Python原生支持的Tkinter模块就能够提供我所需要的GUI支持。下面我就先来实现Input事件的捕获者。
import Tkinter,sys,time
import log
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
return
def __str__(self):
return 'Point({0},{1})'.format(self.x,self.y)
pass
class Key:
def __init__(self, char='', keycode=0, keysym='', keysym_num=0, meta=0):
self.char = char
self.keycode = keycode
self.keysym = keysym
self.keysym_num = keysym_num
self.meta = meta
self.ch_val = 0
if len(self.char): self.ch_val = ord(self.char[0])
return
def __str__(self):
return 'Key({0}({1}), VK={2}, SYM={3}, SYMNUM={4}, META={5})'.format(
self.char,self.ch_val,self.keycode,
self.keysym,self.keysym_num,self.meta)
pass
class Reporter:
INPUTEVT_MOUSEMOVE = 0
INPUTEVT_MOUSELEFTDOWN = 1
INPUTEVT_MOUSELEFTUP = 2
INPUTEVT_MOUSERIGHTDOWN = 3
INPUTEVT_MOUSERIGHTUP = 4
INPUTEVT_MOUSEMIDDLEDOWN = 5
INPUTEVT_MOUSEMIDDLEUP = 6
INPUTEVT_MOUSEWHEEL = 7
INPUTEVT_KEYDOWN = 8
INPUTEVT_KEYUP = 9
INPUTEVT_MAX = 10
def isValid(self):
return True
def reportInputEvent(self, itype, e):
log.i('itype:{0}, event:{1}'.format(itype, e))
return
pass
class InputReceptor(Tkinter.Tk):
m_lastPoint = None # instance of class Point.
m_reporter = None # it reports the input event to elsewhere.
def __init__(self, reporter=Reporter()):
Tkinter.Tk.__init__(self)
self.title("Bluetooth HID Client Test")
self.geometry('640x480+100+100')
self.minsize(640, 480)
self.bind('<Motion>', self.onMouseMoveREL)
self.bind('<Button-1>', self.onMouseLeftDown)
self.bind('<ButtonRelease-1>', self.onMouseLeftUp)
self.bind('<Button-3>', self.onMouseRightDown)
self.bind('<ButtonRelease-3>', self.onMouseRightUp)
self.bind('<KeyPress>', self.onKeyDown)
self.bind('<KeyRelease>', self.onKeyUp)
self.bind('<Enter>', self.onEnter) # pointer enters the widget.
self.bind('<Leave>', self.onLeave) # pointer leaves the widget.
self.m_reporter = reporter
return
def onMouseMoveREL(self, e):
if not self.m_lastPoint:
self.m_lastPoint = Point(e.x, e.y)
return
delta = Point(e.x - self.m_lastPoint.x, e.y - self.m_lastPoint.y)
self.m_lastPoint = Point(e.x, e.y)
self.m_reporter.reportInputEvent(Reporter.INPUTEVT_MOUSEMOVE, delta)
return
def onMouseLeftDown(self, e):