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