From 10e3ca30a52517dedd1f7c7d53c59a74928d35ed Mon Sep 17 00:00:00 2001 From: runger1101001 Date: Mon, 4 Nov 2024 00:56:00 +0100 Subject: [PATCH 1/6] get/set GPIOs - still untested, waiting for my EVM to arrive to try it --- src/cy_serial_bridge/driver.py | 74 +++++++++++++++++++++++++++ src/cy_serial_bridge/usb_constants.py | 8 ++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/cy_serial_bridge/driver.py b/src/cy_serial_bridge/driver.py index 57ad05a..57c449e 100644 --- a/src/cy_serial_bridge/driver.py +++ b/src/cy_serial_bridge/driver.py @@ -364,6 +364,80 @@ def read_user_flash(self, addr: int, size: int) -> bytearray: result_bytes.extend(page_bytes) return result_bytes + + + def is_gpio_output(self, gpio_nr: int) -> bool: + """ + Check if a GPIO pin is in output mode. + + :param pin: GPIO pin number to check + :return: True if the pin is an output pin, False otherwise + """ + + # TODO implement by checking it in the active configuration block + return True + + + def is_gpio_input(self, gpio_nr: int) -> bool: + """ + Check if a GPIO pin is in input mode. + + :param pin: GPIO pin number to check + :return: True if the pin is an input pin, False otherwise + """ + + # TODO implement by checking it in the active configuration block + return True + + + def set_gpio(self, gpio_nr: int, value: int) -> None: + """ + Set the value of a GPIO pin. + + :param pin: GPIO pin number to set + :param value: Value to set the pin to + """ + + if not self.is_gpio_output(gpio_nr): + message = f"GPIO {gpio_nr} is not usable!" + raise CySerialBridgeError(message) + if value != 0 and value != 1: + value = 1 + self.dev.controlWrite( + request_type=CY_VENDOR_REQUEST_HOST_TO_DEVICE, + request=CyVendorCmds.CY_GPIO_SET_VALUE_CMD, + value=gpio_nr, + index=value, + data=[], + timeout=self.timeout + ) + # TODO check for errors + + + def get_gpio(self, gpio_nr: int) -> int: + """ + Get the value of a GPIO pin. + TODO can we also read the value of output pins? if not, we should add a method to read the initial state of the pin + + :param pin: GPIO pin number to get + :return: Value of the pin + """ + + if not self.is_gpio_input(gpio_nr): + message = f"GPIO {gpio_nr} is not usable!" + raise CySerialBridgeError(message) + result_bytes = self.dev.controlRead( + request_type=CY_VENDOR_REQUEST_DEVICE_TO_HOST, + request=CyVendorCmds.CY_GPIO_GET_VALUE_CMD, + value=gpio_nr, + index=0, + length=CY_GET_GPIO_LEN, + timeout=self.timeout + ) + if len(result_bytes) != CY_GET_GPIO_LEN or result_bytes[0] != 0: + message = f"Error getting GPIO {gpio_nr}" + raise CySerialBridgeError(message) + return result_bytes[1] class CyMfgrIface(CySerBridgeBase): diff --git a/src/cy_serial_bridge/usb_constants.py b/src/cy_serial_bridge/usb_constants.py index c26b105..956c3fc 100644 --- a/src/cy_serial_bridge/usb_constants.py +++ b/src/cy_serial_bridge/usb_constants.py @@ -86,8 +86,13 @@ class CyVendorCmds(IntEnum): CY_JTAG_READ_CMD = 0xD2 CY_JTAG_WRITE_CMD = 0xD3 + # From Infineon's forums on Mar 24, 2023, here: https://community.infineon.com/t5/USB-low-full-high-speed/CY7C65215-Get-Set-GPIO-Config/td-p/336658 + # "CY_GPIO_GET_CONFIG_CMD is maintaining in CyUSBCommon.h but it has not been implemented at the + # hoist side and Silicon so this will not work, we apologize for the confusion with this code + # will remove this in the upcoming release so it does not create confusion to the user." CY_GPIO_GET_CONFIG_CMD = 0xD8 CY_GPIO_SET_CONFIG_CMD = 0xD9 + # GET_VALUE and SET_VALUE are implemented and can be used CY_GPIO_GET_VALUE_CMD = 0xDA CY_GPIO_SET_VALUE_CMD = 0xDB @@ -191,7 +196,8 @@ class CyUart(IntEnum): CY_GET_SILICON_ID_LEN = 4 CY_GET_FIRMWARE_VERSION_LEN = 8 CY_GET_SIGNATURE_LEN = 4 - +CY_GET_GPIO_LEN = 2 +CY_SET_GPIO_LEN = 1 # PHDC related macros class CyPhdc(IntEnum): From a5ff197e689f139512fdaf4e524760a4b98725cc Mon Sep 17 00:00:00 2001 From: runger1101001 Date: Wed, 6 Nov 2024 00:06:46 +0100 Subject: [PATCH 2/6] GPIO getting/setting is working on my CY7C65215 --- src/cy_serial_bridge/driver.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cy_serial_bridge/driver.py b/src/cy_serial_bridge/driver.py index 57c449e..b4c1d9d 100644 --- a/src/cy_serial_bridge/driver.py +++ b/src/cy_serial_bridge/driver.py @@ -380,7 +380,9 @@ def is_gpio_output(self, gpio_nr: int) -> bool: def is_gpio_input(self, gpio_nr: int) -> bool: """ - Check if a GPIO pin is in input mode. + Check if a GPIO pin is readable. + We can read the value of input or output pins, but + not if they are tristated or in some other mode. :param pin: GPIO pin number to check :return: True if the pin is an input pin, False otherwise @@ -412,13 +414,11 @@ def set_gpio(self, gpio_nr: int, value: int) -> None: timeout=self.timeout ) # TODO check for errors - + def get_gpio(self, gpio_nr: int) -> int: """ Get the value of a GPIO pin. - TODO can we also read the value of output pins? if not, we should add a method to read the initial state of the pin - :param pin: GPIO pin number to get :return: Value of the pin """ From 29d41f5f36bf4a1b79c29606b992e599308974cb Mon Sep 17 00:00:00 2001 From: runger1101001 Date: Sun, 10 Nov 2024 09:24:16 +0100 Subject: [PATCH 3/6] mod cy_scb_context (to be improved) and add gpio to CLI --- src/cy_serial_bridge/cli.py | 62 ++++++++++++++++++++++++++ src/cy_serial_bridge/cy_scb_context.py | 16 ++++--- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/cy_serial_bridge/cli.py b/src/cy_serial_bridge/cli.py index b8a8fdd..32f6247 100644 --- a/src/cy_serial_bridge/cli.py +++ b/src/cy_serial_bridge/cli.py @@ -544,6 +544,68 @@ def serial_term( term.close() +# GPIO command +# --------------------------------------------------------------------------------------------- + +GpioArgument = typer.Argument( + help="GPIOs to get/set. A string in the format 'io1 io4 io2=0 io3=1'." +) + +class GpioOutputStyle(str, enum.Enum): + """ + Enum of output styles for the GPIO command + """ + ASCII = "ascii" + PLAIN = "plain" + JSON = "json" + +GpioOutputStyleOption = typer.Option("--output-style", help="Output style to use", case_sensitive=False) + + +@app.command(help="Set/Get GPIO pins on the CY7C65215") +def gpio( + gpio_opt: Annotated[str, GpioArgument] = "", outstyle: Annotated[GpioOutputStyle, GpioOutputStyleOption] = GpioOutputStyle.ASCII +) -> None: + with cast( + cy_serial_bridge.driver.CyMfgrIface, + context.open_device( + global_opt.vid, global_opt.pid, cy_serial_bridge.OpenMode.MFGR_INTERFACE, global_opt.serial_number + ), + ) as dev: + if outstyle == GpioOutputStyle.JSON: + print("[") + dev.connect() + gpio_opts = gpio_opt.split() + first = True + for opt in gpio_opts: + if "=" in opt: + pin, value = opt.split("=") + pin = int(pin.strip("io")) + value = int(value) + dev.set_gpio(pin, value) + else: + pin = int(opt.strip("io")) + value = dev.get_gpio(pin) + if outstyle == GpioOutputStyle.ASCII: + if not first: + print(" ", end="") + print(f"io{pin}={value}", end="") + elif outstyle == GpioOutputStyle.PLAIN: + print(f"{value}") + elif outstyle == GpioOutputStyle.JSON: + if not first: + print(",") + print(f'{{"pin": {pin}, "value": {value}}}', end="") + first = False + dev.disconnect() + if outstyle == GpioOutputStyle.JSON: + print("") + print("]") + elif outstyle == GpioOutputStyle.ASCII: + print("") + + + def main() -> None: app() diff --git a/src/cy_serial_bridge/cy_scb_context.py b/src/cy_serial_bridge/cy_scb_context.py index 4473bff..bd3a4b2 100644 --- a/src/cy_serial_bridge/cy_scb_context.py +++ b/src/cy_serial_bridge/cy_scb_context.py @@ -110,7 +110,8 @@ def list_devices( # CY7C652xx devices always have either two or three interfaces: potentially one for the USB CDC COM port, # one for the actual USB-serial bridge, and one for the configuration interface. - if cfg.getNumInterfaces() != 2 and cfg.getNumInterfaces() != 3: + # CY7C65215 and CY7C65215A devices have (up to?) 4 interfaces. + if cfg.getNumInterfaces() != 2 and cfg.getNumInterfaces() != 3 and cfg.getNumInterfaces() != 4: continue usb_cdc_interface_settings: usb1.USBInterfaceSetting | None = None @@ -118,6 +119,7 @@ def list_devices( scb_interface_settings: usb1.USBInterfaceSetting | None = None mfg_interface_settings: usb1.USBInterfaceSetting + # CY7C65215 devices could have 0-2 CDC interfaces, up to one on each SCB if cfg.getNumInterfaces() == 3 and cfg[0][0].getClass() == USBClass.CDC: # USB CDC mode usb_cdc_interface_settings = cfg[0][0] @@ -136,8 +138,9 @@ def list_devices( else: # USB vendor mode - scb_interface_settings = cfg[0][0] - mfg_interface_settings = cfg[1][0] + scb_interface_settings = cfg[2][0] + #mfg_interface_settings = cfg[1][0] + mfg_interface_settings = cfg[3][0] # CY7C65215 devices have MFG on interface #4 # Check SCB interface -- the Class should be 0xFF (vendor defined/no rules) # and the SubClass value gives the CyType @@ -153,21 +156,22 @@ def list_devices( # Check SCB endpoints if scb_interface_settings.getNumEndpoints() != 3: continue + # Bulk host-to-dev endpoint if ( - scb_interface_settings[0].getAddress() != 0x01 + not (scb_interface_settings[0].getAddress() in [0x01, 0x04]) or (scb_interface_settings[0].getAttributes() & 0x3) != 2 ): continue # Bulk dev-to-host endpoint if ( - scb_interface_settings[1].getAddress() != 0x82 + not (scb_interface_settings[1].getAddress() in [0x82, 0x85]) or (scb_interface_settings[1].getAttributes() & 0x3) != 2 ): continue # Interrupt dev-to-host endpoint if ( - scb_interface_settings[2].getAddress() != 0x83 + not (scb_interface_settings[2].getAddress() in [0x83, 0x86]) or (scb_interface_settings[2].getAttributes() & 0x3) != 3 ): continue From d8f8f51d050c6d3a795a8946325f71b1a7f3cba0 Mon Sep 17 00:00:00 2001 From: runger1101001 Date: Sun, 10 Nov 2024 09:24:40 +0100 Subject: [PATCH 4/6] bump project version --- pyproject.toml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6c2eba3..5921891 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,10 +3,11 @@ name = "cy_serial_bridge" # this is used by Ruff to disable "upgrade to feature x" inspections where x was added # after the given version requires-python = ">=3.10" -version = "0.3.2" +version = "0.3.3" description = "Pure Python driver for using and reconfiguring the CY7C652xx family of USB to SPI/I2C/UART bridge ICs." authors = [ {name = "Jamie Smith", email = "smit109@usc.edu"}, + {name = "Richard Unger", email = "runger1@gmail.com"}, ] readme = "README.md" license = {text = "LGPL"} @@ -15,7 +16,7 @@ classifiers = [ # 3 - Alpha # 4 - Beta # 5 - Production/Stable - "Development Status :: 3 - Beta", + "Development Status :: 3 - Alpha", # Indicate who your project is intended for "Intended Audience :: Developers", @@ -33,7 +34,7 @@ classifiers = [ [tool.poetry] name = "cy_serial_bridge" -version = "0.3.2" +version = "0.3.3" description = "Pure Python driver for using and reconfiguring the CY7C652xx family of USB to SPI/I2C/UART bridge ICs." authors = ["Jamie Smith "] readme = "README.md" @@ -45,6 +46,7 @@ repository = 'https://github.com/mbed-ce/cy_serial_bridge/' [tool.poetry.scripts] cy_serial_cli = 'cy_serial_bridge.cli:main' +cy_flash = 'cy_serial_bridge.flash:main' [tool.poetry.urls] "Tracker" = 'https://github.com/mbed-ce/cy_serial_bridge/issues' From af0dd7f38bde9ccb3b81a561263d1909b0b9d1e7 Mon Sep 17 00:00:00 2001 From: runger1101001 Date: Wed, 27 Nov 2024 17:04:31 +0100 Subject: [PATCH 5/6] updating to work with CY7C65215 --- src/cy_serial_bridge/cli.py | 2 +- src/cy_serial_bridge/cy_scb_context.py | 155 ++++++++++++++----------- src/cy_serial_bridge/usb_constants.py | 2 +- 3 files changed, 91 insertions(+), 68 deletions(-) diff --git a/src/cy_serial_bridge/cli.py b/src/cy_serial_bridge/cli.py index 32f6247..52eeeb4 100644 --- a/src/cy_serial_bridge/cli.py +++ b/src/cy_serial_bridge/cli.py @@ -562,7 +562,7 @@ class GpioOutputStyle(str, enum.Enum): GpioOutputStyleOption = typer.Option("--output-style", help="Output style to use", case_sensitive=False) -@app.command(help="Set/Get GPIO pins on the CY7C65215") +@app.command(help="Set/Get GPIO pins on the CY7C652xx") def gpio( gpio_opt: Annotated[str, GpioArgument] = "", outstyle: Annotated[GpioOutputStyle, GpioOutputStyleOption] = GpioOutputStyle.ASCII ) -> None: diff --git a/src/cy_serial_bridge/cy_scb_context.py b/src/cy_serial_bridge/cy_scb_context.py index bd3a4b2..6947e40 100644 --- a/src/cy_serial_bridge/cy_scb_context.py +++ b/src/cy_serial_bridge/cy_scb_context.py @@ -72,6 +72,63 @@ def _find_serial_port_name_for_serno(serial_number: str) -> str | None: return None + + + def identify_interface(self, intf: usb1.USBInterface) -> CyType|None: + """ + Identify the current interface of a device. + + This is useful for determining the current mode of a device, as the interface is the only part of the device + that can be queried without opening it. + """ + if intf[0].getClass() == USBClass.CDC: + if intf[0].getSubClass() == 0x2: + return CyType.UART_CDC + # elif intf[0].getSubClass() == ?? + # return CyType.SPI_CDC + elif intf[0].getClass() == 0x0A: + if intf[0].getSubClass() == 0x0: + return CyType.CDC_DATA + elif intf[0].getClass() == 0xFF: + # Check manufacturer interface. + # It has a defined class/subclass and has no endpoints + if intf[0].getNumEndpoints() != 0: + return None + if intf[0].getSubClass() == CyType.MFG: + return CyType.MFG + elif intf[0].getClass() == USBClass.VENDOR: + if intf[0].getSubClass() not in { + CyType.UART_VENDOR.value, + CyType.SPI.value, + CyType.I2C.value, + CyType.JTAG.value, + }: + return None + if intf[0].getNumEndpoints() != 3: + return None + # Bulk host-to-dev endpoint + if ( + not (intf[0].getAddress() in [0x01, 0x04]) + or (intf[0].getAttributes() & 0x3) != 2 + ): + return None + # Bulk dev-to-host endpoint + if ( + not (intf[1].getAddress() in [0x82, 0x85]) + or (intf[1].getAttributes() & 0x3) != 2 + ): + return None + # Interrupt dev-to-host endpoint + if ( + not (intf[2].getAddress() in [0x83, 0x86]) + or (intf[2].getAttributes() & 0x3) != 3 + ): + return None + return CyType(intf[0].getSubClass()) + return None + + + def list_devices( self, vid_pids: Set[tuple[int, int]] | None = DEFAULT_VIDS_PIDS, @@ -111,6 +168,7 @@ def list_devices( # CY7C652xx devices always have either two or three interfaces: potentially one for the USB CDC COM port, # one for the actual USB-serial bridge, and one for the configuration interface. # CY7C65215 and CY7C65215A devices have (up to?) 4 interfaces. + # CY7C65215 devices could have 0-2 CDC interfaces, up to one on each SCB if cfg.getNumInterfaces() != 2 and cfg.getNumInterfaces() != 3 and cfg.getNumInterfaces() != 4: continue @@ -119,74 +177,39 @@ def list_devices( scb_interface_settings: usb1.USBInterfaceSetting | None = None mfg_interface_settings: usb1.USBInterfaceSetting - # CY7C65215 devices could have 0-2 CDC interfaces, up to one on each SCB - if cfg.getNumInterfaces() == 3 and cfg[0][0].getClass() == USBClass.CDC: - # USB CDC mode - usb_cdc_interface_settings = cfg[0][0] - cdc_data_interface_settings = cfg[1][0] - mfg_interface_settings = cfg[2][0] - - # Check USB CDC interface - if usb_cdc_interface_settings.getSubClass() != 0x2: - continue - - # Check CDC Data interface - if cdc_data_interface_settings.getClass() != 0x0A or cdc_data_interface_settings.getSubClass() != 0x0: - continue - - curr_cytype = CyType.UART_CDC - - else: - # USB vendor mode - scb_interface_settings = cfg[2][0] - #mfg_interface_settings = cfg[1][0] - mfg_interface_settings = cfg[3][0] # CY7C65215 devices have MFG on interface #4 - - # Check SCB interface -- the Class should be 0xFF (vendor defined/no rules) - # and the SubClass value gives the CyType - if scb_interface_settings.getClass() != USBClass.VENDOR: - continue - if scb_interface_settings.getSubClass() not in { - CyType.UART_VENDOR.value, - CyType.SPI.value, - CyType.I2C.value, - }: - continue - - # Check SCB endpoints - if scb_interface_settings.getNumEndpoints() != 3: - continue - - # Bulk host-to-dev endpoint - if ( - not (scb_interface_settings[0].getAddress() in [0x01, 0x04]) - or (scb_interface_settings[0].getAttributes() & 0x3) != 2 - ): - continue - # Bulk dev-to-host endpoint - if ( - not (scb_interface_settings[1].getAddress() in [0x82, 0x85]) - or (scb_interface_settings[1].getAttributes() & 0x3) != 2 - ): - continue - # Interrupt dev-to-host endpoint - if ( - not (scb_interface_settings[2].getAddress() in [0x83, 0x86]) - or (scb_interface_settings[2].getAttributes() & 0x3) != 3 - ): - continue - - curr_cytype = CyType(scb_interface_settings.getSubClass()) - - # Check manufacturer interface. - # It has a defined class/subclass and has no endpoints - if mfg_interface_settings.getClass() != 0xFF: - continue - if mfg_interface_settings.getSubClass() != CyType.MFG: - continue - if mfg_interface_settings.getNumEndpoints() != 0: + for i in range(cfg.getNumInterfaces()): + type = self.identify_interface(cfg[i]) + if type == None: + pass # TODO verbose output + else: + match(type): + case CyType.UART_CDC: # TODO we could have two of these! + usb_cdc_interface_settings = cfg[i][0] + curr_cytype = CyType.UART_CDC + case CyType.CDC_DATA: + cdc_data_interface_settings = cfg[i][0] + case CyType.MFG: + mfg_interface_settings = cfg[i][0] + case CyType.I2C: # TODO we could have two of these! + scb_interface_settings = cfg[i][0] + curr_cytype = CyType.I2C + case CyType.SPI: + scb_interface_settings = cfg[i][0] + curr_cytype = CyType.SPI + case CyType.JTAG: + scb_interface_settings = cfg[i][0] + curr_cytype = CyType.JTAG + case CyType.UART_VENDOR: + scb_interface_settings = cfg[i][0] + curr_cytype = CyType.UART_VENDOR + + if curr_cytype is None or mfg_interface_settings is None \ + or (scb_interface_settings is None and usb_cdc_interface_settings is None): + # TODO verbose output continue + if mfg_interface_settings is not None: curr_cytype = CyType.MFG + # If we got all the way here, it looks like a CY6C652xx device! # Record attributes and add it to the list list_entry = DiscoveredDevice( diff --git a/src/cy_serial_bridge/usb_constants.py b/src/cy_serial_bridge/usb_constants.py index 956c3fc..ce133d8 100644 --- a/src/cy_serial_bridge/usb_constants.py +++ b/src/cy_serial_bridge/usb_constants.py @@ -59,7 +59,7 @@ class CyType(IntEnum): 6 # Used to indicate a device which is in CDC UART mode (which will automatically work using an OS driver) ) UART_PHDC = 7 # Used to indicate a device which is in PHDC (Personal Healthcare Device Class) UART mode - + CDC_DATA = 8 # Used to indicate the CDC data interface (which is a separate interface from the CDC UART interface) class CyVendorCmds(IntEnum): CY_GET_VERSION_CMD = 0xB0 From de2a5fb31aa3e97a1a1733f06b3417d506e0c944 Mon Sep 17 00:00:00 2001 From: runger1101001 Date: Wed, 27 Nov 2024 17:45:45 +0100 Subject: [PATCH 6/6] remove unimplemented functions, change to bool --- src/cy_serial_bridge/driver.py | 42 ++++------------------------------ 1 file changed, 4 insertions(+), 38 deletions(-) diff --git a/src/cy_serial_bridge/driver.py b/src/cy_serial_bridge/driver.py index b4c1d9d..c0609a9 100644 --- a/src/cy_serial_bridge/driver.py +++ b/src/cy_serial_bridge/driver.py @@ -364,35 +364,9 @@ def read_user_flash(self, addr: int, size: int) -> bytearray: result_bytes.extend(page_bytes) return result_bytes - - def is_gpio_output(self, gpio_nr: int) -> bool: - """ - Check if a GPIO pin is in output mode. - - :param pin: GPIO pin number to check - :return: True if the pin is an output pin, False otherwise - """ - - # TODO implement by checking it in the active configuration block - return True - - - def is_gpio_input(self, gpio_nr: int) -> bool: - """ - Check if a GPIO pin is readable. - We can read the value of input or output pins, but - not if they are tristated or in some other mode. - - :param pin: GPIO pin number to check - :return: True if the pin is an input pin, False otherwise - """ - # TODO implement by checking it in the active configuration block - return True - - - def set_gpio(self, gpio_nr: int, value: int) -> None: + def set_gpio(self, gpio_nr: int, value: bool) -> None: """ Set the value of a GPIO pin. @@ -400,32 +374,24 @@ def set_gpio(self, gpio_nr: int, value: int) -> None: :param value: Value to set the pin to """ - if not self.is_gpio_output(gpio_nr): - message = f"GPIO {gpio_nr} is not usable!" - raise CySerialBridgeError(message) - if value != 0 and value != 1: - value = 1 self.dev.controlWrite( request_type=CY_VENDOR_REQUEST_HOST_TO_DEVICE, request=CyVendorCmds.CY_GPIO_SET_VALUE_CMD, value=gpio_nr, - index=value, + index=1 if value==True else 0, data=[], timeout=self.timeout ) # TODO check for errors - def get_gpio(self, gpio_nr: int) -> int: + def get_gpio(self, gpio_nr: int) -> bool: """ Get the value of a GPIO pin. :param pin: GPIO pin number to get :return: Value of the pin """ - if not self.is_gpio_input(gpio_nr): - message = f"GPIO {gpio_nr} is not usable!" - raise CySerialBridgeError(message) result_bytes = self.dev.controlRead( request_type=CY_VENDOR_REQUEST_DEVICE_TO_HOST, request=CyVendorCmds.CY_GPIO_GET_VALUE_CMD, @@ -437,7 +403,7 @@ def get_gpio(self, gpio_nr: int) -> int: if len(result_bytes) != CY_GET_GPIO_LEN or result_bytes[0] != 0: message = f"Error getting GPIO {gpio_nr}" raise CySerialBridgeError(message) - return result_bytes[1] + return (result_bytes[1]==1) class CyMfgrIface(CySerBridgeBase):