new maxusb library
[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         }
31
32     # USB 2.0 specification, section 9.4.3 (p 281 of pdf)
33     # HACK: blatant copypasta from USBDevice pains me deeply
34     def handle_get_descriptor_request(self, req):
35         dtype  = (req.value >> 8) & 0xff
36         dindex = req.value & 0xff
37         lang   = req.index
38         n      = req.length
39
40         response = None
41
42         if self.verbose > 2:
43             print(self.name, ("received GET_DESCRIPTOR req %d, index %d, " \
44                     + "language 0x%04x, length %d") \
45                     % (dtype, dindex, lang, n))
46
47         # TODO: handle KeyError
48         response = self.descriptors[dtype]
49         if callable(response):
50             response = response(dindex)
51
52         if response:
53             n = min(n, len(response))
54             self.device.maxusb_app.send_on_endpoint(0, response[:n])
55
56             if self.verbose > 5:
57                 print(self.name, "sent", n, "bytes in response")
58
59     # Table 9-12 of USB 2.0 spec (pdf page 296)
60     def get_descriptor(self):
61
62         d = bytearray([
63                 9,          # length of descriptor in bytes
64                 4,          # descriptor type 4 == interface
65                 self.number,
66                 self.alternate,
67                 len(self.endpoints),
68                 self.iclass,
69                 self.subclass,
70                 self.protocol,
71                 self.string_index
72         ])
73
74         if self.iclass:
75             iclass_desc_num = USB.interface_class_to_descriptor_type(self.iclass)
76             d += self.descriptors[iclass_desc_num]
77
78         for e in self.endpoints:
79             d += e.get_descriptor()
80
81         return d
82