Skip to content

Instantly share code, notes, and snippets.

@zvecr
Last active May 7, 2022 00:03
Show Gist options
  • Save zvecr/50d66016f61a2f4c424008517d898565 to your computer and use it in GitHub Desktop.
Save zvecr/50d66016f61a2f4c424008517d898565 to your computer and use it in GitHub Desktop.
Virtual XAP device
#!/usr/bin/env python
from uhid import UHIDDevice, PolledBlockingUHID
import gzip
import json
def xap_compress(conf):
return gzip.compress(json.dumps(conf).encode('utf-8'), compresslevel=9)
XAP_BUFFER_SIZE = 64
XAP_DESCRIPTOR = [
0x06, 0x51, 0xFF, # Usage Page (Vendor Defined)
0x09, 0x58, # Usage (Vendor Defined)
0xA1, 0x01, # Collection (Application)
# Data to host
0x09, 0x62, # Usage (Vendor Defined)
0x15, 0x00, # Logical Minimum (0)
0x26, 0xFF, 0x00, # Logical Maximum (255)
0x95, XAP_BUFFER_SIZE, # Report Count
0x75, 0x08, # Report Size (8)
0x81, 0x02, # Input (Data, Variable, Absolute)
# Data from host
0x09, 0x63, # Usage (Vendor Defined)
0x15, 0x00, # Logical Minimum (0)
0x26, 0xFF, 0x00, # Logical Maximum (255)
0x95, XAP_BUFFER_SIZE, # Report Count
0x75, 0x08, # Report Size (8)
0x91, 0x02, # Output (Data, Variable, Absolute)
0xC0 # End Collection
]
XAP_INFO_JSON = xap_compress({
'asdf':'blah',
})
XAP_RESP = {
b'\x00\x00': b'\x00\x00\x02\x00', # version -> 0.2.0
b'\x00\x03': b'\x02', # secure status -> unlocked
b'\x00\x04': b'', # request unlock
b'\x01\x05': len(XAP_INFO_JSON).to_bytes(4, byteorder='little'), # info.json len
b'\x01\x06\x00\x00': XAP_INFO_JSON[:64], # info.json chunk 0
b'\x01\x06 \x00': XAP_INFO_JSON[64:64], # info.json chunk 1
b'\x01\x08': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
}
def main():
device = UHIDDevice(0xFEED, 0x0001, 'XAP_Mock', XAP_DESCRIPTOR, backend=PolledBlockingUHID)
def respond(data, report_type):
req = data[3:3 + int(data[2])]
ret_data = list(XAP_RESP[bytes(req)])
ret = data[:2] + [1, len(ret_data)] + ret_data + ([0] * (XAP_BUFFER_SIZE - 4 - len(ret_data)))
device.send_input(ret)
device.receive_output = respond
device.wait_for_start()
device.dispatch()
if __name__ == '__main__':
import logging
logging.basicConfig(level=logging.INFO)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment