2020-10-14 22:21:33 -04:00
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
2021-01-07 13:09:11 -05:00
|
|
|
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
|
|
|
|
2021-01-07 12:19:57 -05: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))
|
|
|
|
|
|
2021-01-07 12:19:57 -05:00
|
|
|
data = b""
|
2021-01-07 13:09:11 -05:00
|
|
|
first = True
|
2021-01-07 12:19:57 -05:00
|
|
|
|
|
|
|
|
while retries > 0:
|
|
|
|
|
retries -= 1
|
2021-01-07 13:09:11 -05:00
|
|
|
if not first:
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
|
first = False
|
2021-01-07 12:19:57 -05:00
|
|
|
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):
|
2021-01-11 17:08:21 -05:00
|
|
|
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():
|
2020-12-21 03:32:06 -05:00
|
|
|
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))
|
2020-12-21 03:32:06 -05:00
|
|
|
|
2021-01-11 17:08:21 -05:00
|
|
|
if sideload_vid == sideload_pid == 0:
|
|
|
|
|
filtered.append(VialDummyKeyboard())
|
|
|
|
|
|
2020-10-14 15:16:14 -04:00
|
|
|
return filtered
|
2020-12-02 11:11:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def chunks(data, sz):
|
|
|
|
|
for i in range(0, len(data), sz):
|
|
|
|
|
yield data[i:i+sz]
|
2021-01-06 10:59:48 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
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))
|