diff --git a/poetry.lock b/poetry.lock index d24bf15..9d8953c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1023,6 +1023,21 @@ files = [ pyobjc-core = ">=11.1" pyobjc-framework-Cocoa = ">=11.1" +[[package]] +name = "pyserial" +version = "3.5" +description = "Python Serial Port Extension" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0"}, + {file = "pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb"}, +] + +[package.extras] +cp2110 = ["hidapi"] + [[package]] name = "pytest" version = "8.4.1" @@ -1489,6 +1504,9 @@ files = [ {file = "winrt_runtime-3.2.1-cp313-cp313-win32.whl", hash = "sha256:44e2733bc709b76c554aee6c7fe079443b8306b2e661e82eecfebe8b9d71e4d1"}, {file = "winrt_runtime-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:3c1fdcaeedeb2920dc3b9039db64089a6093cad2be56a3e64acc938849245a6d"}, {file = "winrt_runtime-3.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:28f3dab083412625ff4d2b46e81246932e6bebddf67bea7f05e01712f54e6159"}, + {file = "winrt_runtime-3.2.1-cp314-cp314-win32.whl", hash = "sha256:9b6298375468ac2f6815d0c008a059fc16508c8f587e824c7936ed9216480dad"}, + {file = "winrt_runtime-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:e36e587ab5fd681ee472cd9a5995743f75107a1a84d749c64f7e490bc86bc814"}, + {file = "winrt_runtime-3.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:35d6241a2ebd5598e4788e69768b8890ee1eee401a819865767a1fbdd3e9a650"}, {file = "winrt_runtime-3.2.1-cp39-cp39-win32.whl", hash = "sha256:07c0cb4a53a4448c2cb7597b62ae8c94343c289eeebd8f83f946eb2c817bde01"}, {file = "winrt_runtime-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:1856325ca3354b45e0789cf279be9a882134085d34214946db76110d98391efa"}, {file = "winrt_runtime-3.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:cf237858de1d62e4c9b132c66b52028a7a3e8534e8ab90b0e29a68f24f7be39d"}, @@ -1519,6 +1537,9 @@ files = [ {file = "winrt_windows_devices_bluetooth-3.2.1-cp313-cp313-win32.whl", hash = "sha256:12b0a16fb36ce0b42243ca81f22a6b53fbb344ed7ea07a6eeec294604f0505e4"}, {file = "winrt_windows_devices_bluetooth-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:6703dfbe444ee22426738830fb305c96a728ea9ccce905acfdf811d81045fdb3"}, {file = "winrt_windows_devices_bluetooth-3.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:2cf8a0bfc9103e32dc7237af15f84be06c791f37711984abdca761f6318bbdb2"}, + {file = "winrt_windows_devices_bluetooth-3.2.1-cp314-cp314-win32.whl", hash = "sha256:de36ded53ca3ba12fc6dd4deb14b779acc391447726543815df4800348aad63a"}, + {file = "winrt_windows_devices_bluetooth-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:3295d932cc93259d5ccb23a41e3a3af4c78ce5d6a6223b2b7638985f604fa34c"}, + {file = "winrt_windows_devices_bluetooth-3.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:1f61c178766a1bbce0669f44790c6161ff4669404c477b4aedaa576348f9e102"}, {file = "winrt_windows_devices_bluetooth-3.2.1-cp39-cp39-win32.whl", hash = "sha256:32fc355bfdc5d6b3b1875df16eaf12f9b9fc0445e01177833c27d9a4fc0d50b6"}, {file = "winrt_windows_devices_bluetooth-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:b886ef1fc0ed49163ae6c2422dd5cb8dd4709da7972af26c8627e211872818d0"}, {file = "winrt_windows_devices_bluetooth-3.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:8643afa53f9fb8fe3b05967227f86f0c8e1d7b822289e60a848c6368acc977d2"}, @@ -1552,6 +1573,9 @@ files = [ {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp313-cp313-win32.whl", hash = "sha256:4122348ea525a914e85615647a0b54ae8b2f42f92cdbf89c5a12eea53ef6ed90"}, {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:b66410c04b8dae634a7e4b615c3b7f8adda9c7d4d6902bcad5b253da1a684943"}, {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:07af19b1d252ddb9dd3eb2965118bc2b7cabff4dda6e499341b765e5038ca61d"}, + {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp314-cp314-win32.whl", hash = "sha256:2985565c265b3f9eab625361b0e40e88c94b03d89f5171f36146f2e88b3ee214"}, + {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:d102f3fac64fde32332e370969dfbc6f37b405d8cc055d9da30d14d07449a3c2"}, + {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:ffeb5e946cd42c32c6999a62e240d6730c653cdfb7b49c7839afba375e20a62a"}, {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp39-cp39-win32.whl", hash = "sha256:6c4747d2e5b0e2ef24e9b84a848cf8fc50fb5b268a2086b5ee8680206d1e0197"}, {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:18d4c5d8b80ee2d29cc13c2fc1353fdb3c0f620c8083701c9b9ecf5e6c503c8d"}, {file = "winrt_windows_devices_bluetooth_advertisement-3.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:75dd856611d847299078d56aee60e319df52975b931c992cd1d32ad5143fe772"}, @@ -1585,6 +1609,9 @@ files = [ {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp313-cp313-win32.whl", hash = "sha256:b1879c8dcf46bd2110b9ad4b0b185f4e2a5f95170d014539203a5fee2b2115f0"}, {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d8d89f01e9b6931fb48217847caac3227a0aeb38a5b7782af71c2e7b262ec30"}, {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:4e71207bb89798016b1795bb15daf78afe45529f2939b3b9e78894cfe650b383"}, + {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp314-cp314-win32.whl", hash = "sha256:d5f83739ca370f0baf52b0400aebd6240ab80150081fbfba60fd6e7b2e7b4c5f"}, + {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:13786a5853a933de140d456cd818696e1121c7c296ae7b7af262fc5d2cffb851"}, + {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:5140682da2860f6a55eb6faf9e980724dc457c2e4b4b35a10e1cebd8fc97d892"}, {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp39-cp39-win32.whl", hash = "sha256:963339a0161f9970b577a6193924be783978d11693da48b41a025f61b3c5562a"}, {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:d43615c5dfa939dd30fe80dc0649434a13cc7cf0294ad0d7283d5a9f48c6ce86"}, {file = "winrt_windows_devices_bluetooth_genericattributeprofile-3.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:8e70fa970997e2e67a8a4172bc00b0b2a79b5ff5bb2668f79cf10b3fd63d3974"}, @@ -1618,6 +1645,9 @@ files = [ {file = "winrt_windows_devices_enumeration-3.2.1-cp313-cp313-win32.whl", hash = "sha256:14a71cdcc84f624c209cbb846ed6bd9767a9a9437b2bf26b48ac9a91599da6e9"}, {file = "winrt_windows_devices_enumeration-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:6ca40d334734829e178ad46375275c4f7b5d6d2d4fc2e8879690452cbfb36015"}, {file = "winrt_windows_devices_enumeration-3.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:2d14d187f43e4409c7814b7d1693c03a270e77489b710d92fcbbaeca5de260d4"}, + {file = "winrt_windows_devices_enumeration-3.2.1-cp314-cp314-win32.whl", hash = "sha256:e087364273ed7c717cd0191fed4be9def6fdf229fe9b536a4b8d0228f7814106"}, + {file = "winrt_windows_devices_enumeration-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:0da1ddb8285d97a6775c36265d7157acf1bbcb88bcc9a7ce9a4549906c822472"}, + {file = "winrt_windows_devices_enumeration-3.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:09bf07e74e897e97a49a9275d0a647819254ddb74142806bbbcf4777ed240a22"}, {file = "winrt_windows_devices_enumeration-3.2.1-cp39-cp39-win32.whl", hash = "sha256:986e8d651b769a0e60d2834834bdd3f6959f6a88caa0c9acb917797e6b43a588"}, {file = "winrt_windows_devices_enumeration-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:10da7d403ac4afd385fe13bd5808c9a5dd616a8ef31ca5c64cea3f87673661c1"}, {file = "winrt_windows_devices_enumeration-3.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:679e471d21ac22cb50de1bf4dfc4c0c3f5da9f3e3fbc7f08dcacfe9de9d6dd58"}, @@ -1651,6 +1681,9 @@ files = [ {file = "winrt_windows_foundation-3.2.1-cp313-cp313-win32.whl", hash = "sha256:3998dc58ed50ecbdbabace1cdef3a12920b725e32a5806d648ad3f4829d5ba46"}, {file = "winrt_windows_foundation-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:6e98617c1e46665c7a56ce3f5d28e252798416d1ebfee3201267a644a4e3c479"}, {file = "winrt_windows_foundation-3.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:2a8c1204db5c352f6a563130a5a41d25b887aff7897bb677d4ff0b660315aad4"}, + {file = "winrt_windows_foundation-3.2.1-cp314-cp314-win32.whl", hash = "sha256:35e973ab3c77c2a943e139302256c040e017fd6ff1a75911c102964603bba1da"}, + {file = "winrt_windows_foundation-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:a22a7ebcec0d262e60119cff728f32962a02df60471ded8b2735a655eccc0ef5"}, + {file = "winrt_windows_foundation-3.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:3be7fbae829b98a6a946db4fbaf356b11db1fbcbb5d4f37e7a73ac6b25de8b87"}, {file = "winrt_windows_foundation-3.2.1-cp39-cp39-win32.whl", hash = "sha256:14d5191725301498e4feb744d91f5b46ce317bf3d28370efda407d5c87f4423b"}, {file = "winrt_windows_foundation-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:de5e4f61d253a91ba05019dbf4338c43f962bdad935721ced5e7997933994af5"}, {file = "winrt_windows_foundation-3.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:ebbf6e8168398c9ed0c72c8bdde95a406b9fbb9a23e3705d4f0fe28e5a209705"}, @@ -1684,6 +1717,9 @@ files = [ {file = "winrt_windows_foundation_collections-3.2.1-cp313-cp313-win32.whl", hash = "sha256:4267a711b63476d36d39227883aeb3fb19ac92b88a9fc9973e66fbce1fd4aed9"}, {file = "winrt_windows_foundation_collections-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:5e12a6e75036ee90484c33e204b85fb6785fcc9e7c8066ad65097301f48cdd10"}, {file = "winrt_windows_foundation_collections-3.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:34b556255562f1b36d07fba933c2bcd9f0db167fa96727a6cbb4717b152ad7a2"}, + {file = "winrt_windows_foundation_collections-3.2.1-cp314-cp314-win32.whl", hash = "sha256:33188ed2d63e844c8adfbb82d1d3d461d64aaf78d225ce9c5930421b413c45ab"}, + {file = "winrt_windows_foundation_collections-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:d4cfece7e9c0ead2941e55a1da82f20d2b9c8003bb7a8853bb7f999b539f80a4"}, + {file = "winrt_windows_foundation_collections-3.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:3884146fea13727510458f6a14040b7632d5d90127028b9bfd503c6c655d0c01"}, {file = "winrt_windows_foundation_collections-3.2.1-cp39-cp39-win32.whl", hash = "sha256:20610f098b84c87765018cbc71471092197881f3b92e5d06158fad3bfcea2563"}, {file = "winrt_windows_foundation_collections-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:e9739775320ac4c0238e1775d94a54e886d621f9995977e65d4feb8b3778c111"}, {file = "winrt_windows_foundation_collections-3.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:e4c6bddb1359d5014ceb45fe2ecd838d4afeb1184f2ea202c2d21037af0d08a3"}, @@ -1717,6 +1753,9 @@ files = [ {file = "winrt_windows_storage_streams-3.2.1-cp313-cp313-win32.whl", hash = "sha256:401bb44371720dc43bd1e78662615a2124372e7d5d9d65dfa8f77877bbcb8163"}, {file = "winrt_windows_storage_streams-3.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:202c5875606398b8bfaa2a290831458bb55f2196a39c1d4e5fa88a03d65ef915"}, {file = "winrt_windows_storage_streams-3.2.1-cp313-cp313-win_arm64.whl", hash = "sha256:ca3c5ec0aab60895006bf61053a1aca6418bc7f9a27a34791ba3443b789d230d"}, + {file = "winrt_windows_storage_streams-3.2.1-cp314-cp314-win32.whl", hash = "sha256:5cd0dbad86fcc860366f6515fce97177b7eaa7069da261057be4813819ba37ee"}, + {file = "winrt_windows_storage_streams-3.2.1-cp314-cp314-win_amd64.whl", hash = "sha256:3c5bf41d725369b9986e6d64bad7079372b95c329897d684f955d7028c7f27a0"}, + {file = "winrt_windows_storage_streams-3.2.1-cp314-cp314-win_arm64.whl", hash = "sha256:293e09825559d0929bbe5de01e1e115f7a6283d8996ab55652e5af365f032987"}, {file = "winrt_windows_storage_streams-3.2.1-cp39-cp39-win32.whl", hash = "sha256:1c630cfdece58fcf82e4ed86c826326123529836d6d4d855ae8e9ceeff67b627"}, {file = "winrt_windows_storage_streams-3.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:d7ff22434a4829d616a04b068a191ac79e008f6c27541bb178c1f6f1fe7a1657"}, {file = "winrt_windows_storage_streams-3.2.1-cp39-cp39-win_arm64.whl", hash = "sha256:fa90244191108f85f6f7afb43a11d365aca4e0722fe8adc62fb4d2c678d0993d"}, @@ -1732,4 +1771,4 @@ all = ["winrt-Windows.Foundation.Collections[all] (>=3.2.1.0,<3.3.0.0)", "winrt- [metadata] lock-version = "2.1" python-versions = ">=3.10" -content-hash = "f72f31d5e94d97b2cda640772bd557c5f66f0461a2b6e9aac573afbf2e201a26" +content-hash = "c9e2d8c27cf3dd9a8a848464c8328d53f53b618ef0a0198d5d9e2699e8f53b8d" diff --git a/pybricksdev/_vendored/pynxt/lowlevel.py b/pybricksdev/_vendored/pynxt/lowlevel.py deleted file mode 100644 index bcc112b..0000000 --- a/pybricksdev/_vendored/pynxt/lowlevel.py +++ /dev/null @@ -1,74 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Copyright 2006 David Anderson - -import time - -import usb - -USB_BULK_OUT_EP = 0x1 -USB_BULK_IN_EP = 0x82 - - -def enumerate_usb(): - """Return a generator yielding all attached USB devices.""" - busses = usb.busses() - for bus in busses: - devices = bus.devices - for dev in devices: - yield dev - - -def get_device(vendor_id, product_id, version=0, timeout=None): - """Return the first device matching the given vendor/product ID.""" - while True: - for dev in enumerate_usb(): - if ( - dev.idVendor == vendor_id - and dev.idProduct == product_id - and dev.iSerialNumber == version - ): - return UsbBrick(dev) - if timeout is None or timeout <= 0: - return None - sleep_time = min(1.0, timeout) - time.sleep(sleep_time) - timeout -= sleep_time - - -class UsbBrick(object): - def __init__(self, dev): - self._dev = dev - - def __del__(self): - try: - self.close() - except Exception: - pass - - def open(self, interface, configuration=1, detach_kernel_driver=False): - self._iface = interface - self._config = configuration - self._hdl = self._dev.open() - if detach_kernel_driver: - self._hdl.detachKernelDriver(interface) - self._hdl.setConfiguration(configuration) - self._hdl.claimInterface(interface) - - def close(self): - self._hdl.releaseInterface() - del self._hdl - - def read(self, size, timeout=100): - """Read the given amount of data from the device and return it.""" - # For some reason, bulkRead returns a tuple of longs. This is - # dumb, so we convert it back to a string before returning, - # kthx. - try: - data = self._hdl.bulkRead(USB_BULK_IN_EP, size, timeout) - except usb.USBError: - return None - return "".join(chr(x) for x in data) - - def write(self, data, timeout=100): - """Write the given amount of data to the device.""" - return self._hdl.bulkWrite(USB_BULK_OUT_EP, data, timeout) diff --git a/pybricksdev/_vendored/pynxt/samba.py b/pybricksdev/_vendored/pynxt/samba.py index 576415b..033271c 100644 --- a/pybricksdev/_vendored/pynxt/samba.py +++ b/pybricksdev/_vendored/pynxt/samba.py @@ -1,77 +1,110 @@ -# SPDX-License-Identifier: GPL-2.0-only -# Copyright 2006 David Anderson - import struct +import time -from pybricksdev._vendored.pynxt import lowlevel +import serial +from serial.tools import list_ports ATMEL_VENDOR_ID = 0x03EB SAMBA_PRODUCT_ID = 0x6124 -SAMBA_USB_INTERFACE = 1 class SambaOpenError(Exception): - """An error occured while opening a connection to SAM-BA""" + """An error occurred while opening a connection to SAM-BA""" def _command(code, address): - return "%c%08X#" % (code, address) + return f"{code}{address:08X}#".encode("ascii") def _command2(code, address, value): - return "%c%08X,%08X#" % (code, address, value) + return f"{code}{address:08X},{value:08X}#".encode("ascii") -class SambaBrick(object): +class SambaBrick: def __init__(self): - self.usb = None + self.ser = None + + def open(self, timeout=5): + # enumerate serial ports (Web Serial equivalent of chooser) + matches = [ + p + for p in list_ports.comports() + if p.vid == ATMEL_VENDOR_ID and p.pid == SAMBA_PRODUCT_ID + ] + + if not matches: + raise SambaOpenError("No SAM-BA device found (03eb:6124).") + + if len(matches) > 1: + raise SambaOpenError( + "Multiple SAM-BA devices found; cannot choose automatically." + ) + + port = matches[0].device - def __del__(self): try: - self.close() - except Exception: - pass - - def open(self, timeout=None): - self.usb = lowlevel.get_device( - ATMEL_VENDOR_ID, SAMBA_PRODUCT_ID, timeout=timeout - ) - if not self.usb: - raise SambaOpenError("Could not find a SAM-BA brick to connect to") - self.usb.open(SAMBA_USB_INTERFACE, detach_kernel_driver=True) + self.ser = serial.Serial( + port=port, + timeout=timeout, + write_timeout=timeout, + exclusive=True, + ) + except serial.SerialException as e: + raise SambaOpenError(str(e)) + + # Give CDC ACM time to settle (mirrors browser behavior) + time.sleep(0.1) + + self.ser.reset_input_buffer() + self.ser.reset_output_buffer() # Initial SAM-BA handshake. - self.usb.write("N#") - res = self.usb.read(2) - if res != "\n\r": - raise SambaOpenError("Incorrect handshake response") + self._write(b"N#") + res = self._read_exact(2) + + if res != b"\n\r": + raise SambaOpenError(f"Incorrect handshake response: {res!r}") def close(self): - self.usb.close() - self.usb = None + if self.ser: + self.ser.close() + self.ser = None + + def _write(self, data: bytes): + self.ser.write(data) + self.ser.flush() + + def _read_exact(self, n: int) -> bytes: + buf = bytearray() + while len(buf) < n: + chunk = self.ser.read(n - len(buf)) + if not chunk: + raise SambaOpenError("Timeout while reading from SAM-BA") + buf.extend(chunk) + return bytes(buf) def write_byte(self, address, byte): - assert 0 <= byte <= 255 - self.usb.write(_command2("O", address, byte)) + assert 0 <= byte <= 0xFF + self._write(_command2("O", address, byte)) def write_halfword(self, address, halfword): - assert 0 <= halfword <= (2**16 - 1) - self.usb.write(_command2("H", address, halfword)) + assert 0 <= halfword <= 0xFFFF + self._write(_command2("H", address, halfword)) def write_word(self, address, word): - assert 0 <= word <= (2**32 - 1) - self.usb.write(_command2("W", address, word)) + assert 0 <= word <= 0xFFFFFFFF + self._write(_command2("W", address, word)) def write_buffer(self, address, data): - self.usb.write(_command2("S", address, len(data))) - self.usb.write(data) + self._write(_command2("S", address, len(data))) + self._write(data) def _read_common(self, code, address, size, struct_code): assert size in (1, 2, 4) - self.usb.write(_command2(code, address, size)) + self._write(_command2(code, address, size)) - res = self.usb.read(size).encode() - return struct.unpack("<%c" % struct_code, res)[0] + raw = self._read_exact(size) + return struct.unpack("<" + struct_code, raw)[0] def read_byte(self, address): return self._read_common("o", address, 1, "B") @@ -80,15 +113,15 @@ def read_halfword(self, address): return self._read_common("h", address, 2, "H") def read_word(self, address): - return self._read_common("w", address, 4, "L") + return self._read_common("w", address, 4, "I") def read_buffer(self, address, len): - self.usb.write(_command2("R", address, len)) - return self.usb.read(len) + self._write(_command2("R", address, len)) + return self._read_exact(len) def jump(self, address): - self.usb.write(_command("G", address)) + self._write(_command("G", address)) def version(self): - self.usb.write("V#") - return self.usb.read(4) + self._write(b"V#") + return self._read_exact(4) diff --git a/pyproject.toml b/pyproject.toml index 7d2e5e5..8ea4ab3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ reactivex = {version = ">=4.0.4", python = "<4"} hidapi = ">=0.14.0" pybricks = {version = ">=3", allow-prereleases = true, python = "<4"} questionary = {version = ">=2.1.1", python = "<4"} +pyserial = "^3.5" [tool.poetry.group.lint.dependencies] black = ">=23,<25"