3 # Contains class definition for MAXUSBApp.
6 from Facedancer import *
8 from USBDevice import USBDeviceRequest
10 class MAXUSBApp(FacedancerApp):
15 reg_ep1_out_fifo = 0x01
16 reg_ep2_in_fifo = 0x02
17 reg_ep3_in_fifo = 0x03
18 reg_setup_data_fifo = 0x04
19 reg_ep0_byte_count = 0x05
20 reg_ep1_out_byte_count = 0x06
21 reg_ep2_in_byte_count = 0x07
22 reg_ep3_in_byte_count = 0x08
25 reg_endpoint_irq = 0x0b
26 reg_endpoint_interrupt_enable = 0x0c
28 reg_usb_interrupt_enable = 0x0e
29 reg_usb_control = 0x0f
30 reg_cpu_control = 0x10
31 reg_pin_control = 0x11
33 reg_function_address = 0x13
36 # bitmask values for reg_endpoint_irq = 0x0b
37 is_setup_data_avail = 0x20 # SUDAVIRQ
38 is_in3_buffer_avail = 0x10 # IN3BAVIRQ
39 is_in2_buffer_avail = 0x08 # IN2BAVIRQ
40 is_out1_data_avail = 0x04 # OUT1DAVIRQ
41 is_out0_data_avail = 0x02 # OUT0DAVIRQ
42 is_in0_buffer_avail = 0x01 # IN0BAVIRQ
44 # bitmask values for reg_usb_control = 0x0f
45 usb_control_vbgate = 0x40
46 usb_control_connect = 0x08
48 # bitmask values for reg_pin_control = 0x11
49 interrupt_level = 0x08
52 def __init__(self, device, verbose=0):
53 FacedancerApp.__init__(self, device, verbose)
55 self.connected_device = None
60 rev = self.read_register(self.reg_revision)
61 print(self.app_name, "revision", rev)
63 # set duplex and negative INT level (from GoodFEDMAXUSB.py)
64 self.write_register(self.reg_pin_control,
65 self.full_duplex | self.interrupt_level)
67 def init_commands(self):
68 self.read_register_cmd = FacedancerCommand(self.app_num, 0x00, b'')
69 self.write_register_cmd = FacedancerCommand(self.app_num, 0x00, b'')
70 self.enable_app_cmd = FacedancerCommand(self.app_num, 0x10, b'')
71 self.ack_cmd = FacedancerCommand(self.app_num, 0x00, b'\x01')
73 def read_register(self, reg_num, ack=False):
75 print(self.app_name, "reading register 0x%02x" % reg_num)
77 self.read_register_cmd.data = bytearray([ reg_num << 3, 0 ])
79 self.write_register_cmd.data[0] |= 1
81 self.device.writecmd(self.read_register_cmd)
83 resp = self.device.readcmd()
86 print(self.app_name, "read register 0x%02x has value 0x%02x" %
87 (reg_num, resp.data[1]))
91 def write_register(self, reg_num, value, ack=False):
93 print(self.app_name, "writing register 0x%02x with value 0x%02x" %
96 self.write_register_cmd.data = bytearray([ (reg_num << 3) | 2, value ])
98 self.write_register_cmd.data[0] |= 1
100 self.device.writecmd(self.write_register_cmd)
101 self.device.readcmd()
103 def get_version(self):
104 return self.read_register(self.reg_revision)
106 def ack_status_stage(self):
108 print(self.app_name, "sending ack!")
110 self.device.writecmd(self.ack_cmd)
111 self.device.readcmd()
113 def connect(self, usb_device):
114 self.write_register(self.reg_usb_control, self.usb_control_vbgate |
115 self.usb_control_connect)
117 self.connected_device = usb_device
120 print(self.app_name, "connected device", self.connected_device.name)
122 def disconnect(self):
123 self.write_register(self.reg_usb_control, self.usb_control_vbgate)
126 print(self.app_name, "disconnected device", self.connected_device.name)
127 self.connected_device = None
129 def clear_irq_bit(self, reg, bit):
130 self.write_register(reg, bit)
132 def read_bytes(self, reg, n):
134 print(self.app_name, "reading", n, "bytes from register", reg)
136 data = bytes([ (reg << 3) ] + ([0] * n))
137 cmd = FacedancerCommand(self.app_num, 0x00, data)
139 self.device.writecmd(cmd)
140 resp = self.device.readcmd()
143 print(self.app_name, "read", len(resp.data) - 1, "bytes from register", reg)
147 def write_bytes(self, reg, data):
148 data = bytes([ (reg << 3) | 3 ]) + data
149 cmd = FacedancerCommand(self.app_num, 0x00, data)
151 self.device.writecmd(cmd)
152 self.device.readcmd() # null response
155 print(self.app_name, "wrote", len(data) - 1, "bytes to register", reg)
157 # HACK: but given the limitations of the MAX chips, it seems necessary
158 def send_on_endpoint(self, ep_num, data):
160 fifo_reg = self.reg_ep0_fifo
161 bc_reg = self.reg_ep0_byte_count
163 fifo_reg = self.reg_ep2_in_fifo
164 bc_reg = self.reg_ep2_in_byte_count
166 fifo_reg = self.reg_ep3_in_fifo
167 bc_reg = self.reg_ep3_in_byte_count
169 raise ValueError('endpoint ' + str(ep_num) + ' not supported')
171 # FIFO buffer is only 64 bytes, must loop
172 while len(data) > 64:
173 self.write_bytes(fifo_reg, data[:64])
174 self.write_register(bc_reg, 64, ack=True)
178 self.write_bytes(fifo_reg, data)
179 self.write_register(bc_reg, len(data), ack=True)
182 print(self.app_name, "wrote", bytes_as_hex(data), "to endpoint",
185 # HACK: but given the limitations of the MAX chips, it seems necessary
186 def read_from_endpoint(self, ep_num):
190 byte_count = self.read_register(self.reg_ep1_out_byte_count)
194 data = self.read_bytes(self.reg_ep1_out_fifo, byte_count)
197 print(self.app_name, "read", bytes_as_hex(data), "from endpoint",
204 print(self.app_name, "stalling endpoint 0")
206 self.write_register(self.reg_ep_stalls, 0x23)
208 def service_irqs(self):
210 irq = self.read_register(self.reg_endpoint_irq)
213 print(self.app_name, "read endpoint irq: 0x%02x" % irq)
216 if irq & ~ (self.is_in0_buffer_avail \
217 | self.is_in2_buffer_avail | self.is_in3_buffer_avail):
218 print(self.app_name, "notable irq: 0x%02x" % irq)
220 if irq & self.is_setup_data_avail:
221 self.clear_irq_bit(self.reg_endpoint_irq, self.is_setup_data_avail)
223 b = self.read_bytes(self.reg_setup_data_fifo, 8)
224 req = USBDeviceRequest(b)
225 self.connected_device.handle_request(req)
227 if irq & self.is_out1_data_avail:
228 data = self.read_from_endpoint(1)
230 self.connected_device.handle_data_available(1, data)
231 self.clear_irq_bit(self.reg_endpoint_irq, self.is_out1_data_avail)
233 if irq & self.is_in2_buffer_avail:
234 self.connected_device.handle_buffer_available(2)
236 if irq & self.is_in3_buffer_avail:
237 self.connected_device.handle_buffer_available(3)