58 lines
1.5 KiB
Python
58 lines
1.5 KiB
Python
import errno
|
|
import struct
|
|
|
|
import usb.core
|
|
import usb.util
|
|
from usb.core import USBError
|
|
|
|
VENDOR_ID = 0x191A
|
|
PRODUCT_ID = 0x8003
|
|
ENDPOINT = 1
|
|
|
|
|
|
class PatliteDevice:
|
|
def __init__(self):
|
|
self._dev = None
|
|
|
|
def connect(self):
|
|
dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)
|
|
if dev is None:
|
|
raise RuntimeError(
|
|
f"Patlite not found (vendor={VENDOR_ID:#06x}, product={PRODUCT_ID:#06x})"
|
|
)
|
|
|
|
try:
|
|
if dev.is_kernel_driver_active(0):
|
|
dev.detach_kernel_driver(0)
|
|
dev.set_configuration()
|
|
except USBError as exc:
|
|
if exc.errno == errno.EACCES:
|
|
raise RuntimeError(
|
|
"USB access denied. On headless hosts, run ./scripts/install-udev.sh, "
|
|
"then 'newgrp patlite' (or re-login), unplug/replug the Patlite, and retry."
|
|
) from exc
|
|
raise
|
|
|
|
self._dev = dev
|
|
|
|
def close(self):
|
|
if self._dev is not None:
|
|
self.send(0x00, 0x00, 0x00)
|
|
usb.util.dispose_resources(self._dev)
|
|
self._dev = None
|
|
|
|
def send(self, ry: int, gb: int, w: int):
|
|
if self._dev is None:
|
|
return
|
|
data = struct.pack(
|
|
"BBBBBBBx",
|
|
0x00,
|
|
0x00,
|
|
0x0F,
|
|
0x00,
|
|
ry & 0xFF,
|
|
gb & 0xFF,
|
|
w & 0xFF,
|
|
)
|
|
self._dev.write(ENDPOINT, data)
|