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