-
Notifications
You must be signed in to change notification settings - Fork 8
/
device.py
122 lines (99 loc) · 3.45 KB
/
device.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import os
import sys
import traceback
os.environ['LIBUSB_DEBUG'] = 'debug'
import usb.core
from usb.core import USBError
import usb.util
import oled
DEFAULT_LEN = 642
TARGETS = [
{ "name": "apex7", "idVendor": 0x1038, "idProduct": 0x1612 },
{ "name": "apex7tkl", "idVendor": 0x1038, "idProduct": 0x1618 }
]
def find_device():
"""Find the first matching keyboard device in the TARGETS list"""
for target in TARGETS:
try:
dev = usb.core.find(idVendor = target['idVendor'], idProduct = target['idProduct'])
if dev is not None:
return target, dev
except USBError as e:
print(f"usb::find({target['name']}) failed: {e}")
raise Exception("Cannot find a matching device")
def detach_kernel(dev):
if dev.is_kernel_driver_active(1) == True:
try:
print("dev::detach_kernel_driver - interface 1")
dev.detach_kernel_driver(1)
return True
except USBError as e:
print("dev::detach_kernel_driver failed" + str(e))
return False
def reattach_kernel(dev, was_detached):
print("dev::dispose_resources")
usb.util.dispose_resources(dev)
if was_detached:
try:
print("dev::artach_kernel_driver - interface 1")
dev.attach_kernel_driver(1)
except USBError as e:
print("dev::attach_kernel_driver failed" + str(e))
class Device():
def __init__ (self):
self.target = None
self.handle = None
self._was_detached = None
def __enter__ (self):
self.target, self.handle = find_device()
self._was_detached = detach_kernel(self.handle)
return self
def __exit__ (self, type, value, tb):
reattach_kernel(self.handle, self._was_detached)
def pad(self, payload, maxlen=642):
if len(payload) < maxlen:
payload += [0x00] * (maxlen - len(payload))
return payload
def send(self, wValue = 0x300, reqType = 0x01, payload=None):
if payload is None:
raise Exception("payload cannot be null")
self.handle.ctrl_transfer(0x21,
0x09,
wValue,
reqType,
payload)
def send_colors(self, color_payload):
report = [0x3a, 0x69] + color_payload
report = self.pad(report, DEFAULT_LEN)
self.send(0x300, 0x01, report)
def set_config(self, config_id):
report = [0x89] + [config_id]
report = self.pad(report, 20)
self.send(0x200, 0x01, report)
def oled_blank(self, filename="./images/blank.png"):
self.oled_image(filename)
def oled_image(self, filename):
imagedata = oled.image_to_payload(filename)
report = oled.OLED_PREAMBLE + imagedata
self.send(0x300, 0x01, report)
def oled_text(self, text):
imagedata = oled.text_payload(text)
report = oled.OLED_PREAMBLE + imagedata
self.send(0x300, 0x01, report)
#printimage(full)
#payload_to_image(full, "payload.png")
#loaded = image_to_payload("payload.png")
#printimage(loaded)
#
#printimage(text_payload("Hello World\nLine 2\nLine3"))
#printimage(text_payload("Hello World\nLine 2\nOverflow 12345678901234567890"))
#
#cfg = dev.get_active_configuration()
#print("config", cfg)
#intf = cfg[(0, 0)]
#
#ep = usb.util.find_descriptor(intf,
# custom_match = \
# lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
#
#print("endpoint", ep)