fixed failure to construct full config descriptor; handle linux's inability to deal...
[goodfet] / client / USBInterface.py
1 # USBInterface.py
2 #
3 # Contains class definition for USBInterface.
4
5 from USB import *
6
7 class USBInterface:
8     name = "generic USB interface"
9
10     def __init__(self, interface_number, interface_alternate, interface_class,
11             interface_subclass, interface_protocol, interface_string_index,
12             verbose=0, endpoints=[], descriptors={}):
13
14         self.number = interface_number
15         self.alternate = interface_alternate
16         self.iclass = interface_class
17         self.subclass = interface_subclass
18         self.protocol = interface_protocol
19         self.string_index = interface_string_index
20
21         self.endpoints = endpoints
22         self.descriptors = descriptors
23
24         self.verbose = verbose
25
26         self.descriptors[USB.desc_type_interface] = self.get_descriptor
27
28         self.request_handlers = {
29              6 : self.handle_get_descriptor_request,
30             11 : self.handle_set_interface_request
31         }
32
33     # USB 2.0 specification, section 9.4.3 (p 281 of pdf)
34     # HACK: blatant copypasta from USBDevice pains me deeply
35     def handle_get_descriptor_request(self, req):
36         dtype  = (req.value >> 8) & 0xff
37         dindex = req.value & 0xff
38         lang   = req.index
39         n      = req.length
40
41         response = None
42
43         if self.verbose > 2:
44             print(self.name, ("received GET_DESCRIPTOR req %d, index %d, " \
45                     + "language 0x%04x, length %d") \
46                     % (dtype, dindex, lang, n))
47
48         # TODO: handle KeyError
49         response = self.descriptors[dtype]
50         if callable(response):
51             response = response(dindex)
52
53         if response:
54             n = min(n, len(response))
55             self.device.maxusb_app.send_on_endpoint(0, response[:n])
56
57             if self.verbose > 5:
58                 print(self.name, "sent", n, "bytes in response")
59
60     def handle_set_interface_request(self, req):
61         self.device.maxusb_app.stall_ep0()
62
63     # Table 9-12 of USB 2.0 spec (pdf page 296)
64     def get_descriptor(self):
65
66         d = bytearray([
67                 9,          # length of descriptor in bytes
68                 4,          # descriptor type 4 == interface
69                 self.number,
70                 self.alternate,
71                 len(self.endpoints),
72                 self.iclass,
73                 self.subclass,
74                 self.protocol,
75                 self.string_index
76         ])
77
78         if self.iclass:
79             iclass_desc_num = USB.interface_class_to_descriptor_type(self.iclass)
80             d += self.descriptors[iclass_desc_num]
81
82         for e in self.endpoints:
83             d += e.get_descriptor()
84
85         return d
86