4dee1f9197eb26d48f62d2c9dd3181c250af1306
[goodfet] / client / USBKeyboard.py
1 # USBKeyboard.py
2 #
3 # Contains class definitions to implement a USB keyboard.
4
5 from USB import *
6 from USBDevice import *
7 from USBConfiguration import *
8 from USBInterface import *
9 from USBEndpoint import *
10
11 class USBKeyboardInterface(USBInterface):
12     name = "USB keyboard interface"
13
14     hid_descriptor = b'\x09\x21\x10\x01\x00\x01\x22\x2b\x00'
15     report_descriptor = b'\x05\x01\x09\x06\xA1\x01\x05\x07\x19\xE0\x29\xE7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x19\x00\x29\x65\x15\x00\x25\x65\x75\x08\x95\x01\x81\x00\xC0'
16
17     def __init__(self, verbose=0):
18         descriptors = { 
19                 USB.desc_type_hid    : self.hid_descriptor,
20                 USB.desc_type_report : self.report_descriptor
21         }
22
23         endpoint = USBEndpoint(
24                 3,          # endpoint number
25                 USBEndpoint.direction_in,
26                 USBEndpoint.transfer_type_interrupt,
27                 USBEndpoint.sync_type_none,
28                 USBEndpoint.usage_type_data,
29                 16384,      # max packet size
30                 10,         # polling interval, see USB 2.0 spec Table 9-13
31                 self.handle_buffer_available    # handler function
32         )
33
34         # TODO: un-hardcode string index (last arg before "verbose")
35         USBInterface.__init__(
36                 self,
37                 0,          # interface number
38                 0,          # alternate setting
39                 3,          # interface class
40                 0,          # subclass
41                 0,          # protocol
42                 0,          # string index
43                 verbose,
44                 [ endpoint ],
45                 descriptors
46         )
47
48         # "l<KEY UP>s<KEY UP><ENTER><KEY UP>"
49         empty_preamble = [ 0x00 ] * 10
50         text = [ 0x0f, 0x00, 0x16, 0x00, 0x28, 0x00 ]
51
52         self.keys = [ chr(x) for x in empty_preamble + text ]
53
54     def handle_buffer_available(self):
55         if not self.keys:
56             return
57
58         letter = self.keys.pop(0)
59         self.type_letter(letter)
60
61     def type_letter(self, letter, modifiers=0):
62         data = bytes([ 0, 0, ord(letter) ])
63
64         if self.verbose > 2:
65             print(self.name, "sending keypress 0x%02x" % ord(letter))
66
67         self.device.maxusb_app.send_on_endpoint(3, data)
68
69
70 class USBKeyboardDevice(USBDevice):
71     name = "USB keyboard device"
72
73     def __init__(self, maxusb_app, verbose=0):
74         config = USBConfiguration(
75                 1,                                          # index
76                 "Emulated Keyboard",    # string desc
77                 [ USBKeyboardInterface() ]                  # interfaces
78         )
79
80         USBDevice.__init__(
81                 self,
82                 maxusb_app,
83                 0,                      # device class
84                 0,                      # device subclass
85                 0,                      # protocol release number
86                 64,                     # max packet size for endpoint 0
87                 0x610b,                 # vendor id
88                 0x4653,                 # product id
89                 0x3412,                 # device revision
90                 "Maxim",                # manufacturer string
91                 "MAX3420E Enum Code",   # product string
92                 "S/N3420E",             # serial number string
93                 [ config ],
94                 verbose=verbose
95         )
96