vial/src/main/python/util.py

85 lines
2.3 KiB
Python
Raw Normal View History

2020-10-14 22:21:33 -04:00
# SPDX-License-Identifier: GPL-2.0-or-later
import time
2020-10-14 22:21:33 -04:00
2020-10-14 12:56:25 -04:00
from PyQt5.QtCore import QCoreApplication
2020-12-02 10:10:59 -05:00
from hidproxy import hid
2020-10-14 15:16:14 -04:00
2020-10-14 12:56:25 -04:00
tr = QCoreApplication.translate
2020-10-14 15:16:14 -04:00
2020-12-02 10:10:59 -05:00
# For Vial keyboard
2020-10-14 15:16:14 -04:00
VIAL_SERIAL_NUMBER_MAGIC = "vial:f64c2b3c"
2020-12-02 10:10:59 -05:00
# For bootloader
VIBL_SERIAL_NUMBER_MAGIC = "vibl:d4f8159c"
2020-10-14 15:16:14 -04:00
MSG_LEN = 32
2020-10-16 15:26:11 -04:00
def hid_send(dev, msg, retries=1):
2020-10-14 15:16:14 -04:00
if len(msg) > MSG_LEN:
raise RuntimeError("message must be less than 32 bytes")
msg += b"\x00" * (MSG_LEN - len(msg))
data = b""
first = True
while retries > 0:
retries -= 1
if not first:
time.sleep(0.5)
first = False
try:
# add 00 at start for hidapi report id
if dev.write(b"\x00" + msg) != MSG_LEN + 1:
continue
data = bytes(dev.read(MSG_LEN, timeout_ms=500))
if not data:
continue
except OSError:
continue
break
if not data:
raise RuntimeError("failed to communicate with the device")
return data
2020-10-14 15:16:14 -04:00
2020-10-16 15:26:11 -04:00
2020-10-14 15:16:14 -04:00
def is_rawhid(dev):
# TODO: this is only broken on linux, other platforms should be able to check usage_page
return dev["interface_number"] == 1
2020-10-16 15:26:11 -04:00
2021-01-11 01:51:24 -05:00
def find_vial_devices(via_stack_json, sideload_vid=None, sideload_pid=None):
from vial_device import VialBootloader, VialKeyboard, VialDummyKeyboard
2020-12-02 10:10:59 -05:00
2020-10-14 15:16:14 -04:00
filtered = []
for dev in hid.enumerate():
if dev["vendor_id"] == sideload_vid and dev["product_id"] == sideload_pid and is_rawhid(dev):
filtered.append(VialKeyboard(dev, sideload=True))
elif VIAL_SERIAL_NUMBER_MAGIC in dev["serial_number"] and is_rawhid(dev):
2020-12-02 10:10:59 -05:00
filtered.append(VialKeyboard(dev))
elif VIBL_SERIAL_NUMBER_MAGIC in dev["serial_number"]:
filtered.append(VialBootloader(dev))
2021-01-11 01:51:24 -05:00
elif str(dev["vendor_id"] * 65536 + dev["product_id"]) in via_stack_json["definitions"] and is_rawhid(dev):
filtered.append(VialKeyboard(dev, via_stack=True))
if sideload_vid == sideload_pid == 0:
filtered.append(VialDummyKeyboard())
2020-10-14 15:16:14 -04:00
return filtered
def chunks(data, sz):
for i in range(0, len(data), sz):
yield data[i:i+sz]
def pad_for_vibl(msg):
""" Pads message to vibl fixed 64-byte length """
if len(msg) > 64:
raise RuntimeError("vibl message too long")
return msg + b"\x00" * (64 - len(msg))