]> Repositories - Adafruit_Blinka-hackapet.git/commitdiff
mcp2221: allow empty i2c payload
authorFrancois Gervais <francoisgervais@gmail.com>
Sun, 15 Aug 2021 02:49:37 +0000 (22:49 -0400)
committerFrancois Gervais <francoisgervais@gmail.com>
Sun, 15 Aug 2021 02:49:37 +0000 (22:49 -0400)
This fix allow sending I2C transactions with an empty payload.

Before this change, sending an empty payload is bogus as it won't transfer
anything but will still try to get the status of the transaction. It will
basically get the current status of the bus.

One way to manifest this problem is when connecting to a device.

On I2CDevice() init, it will probe the device by sending en empty payload
message. This actually works fine if the bus is in a good state like on
first use. It won't actually send the probe out but we will read the
good initial state and things will go smoothly from here.

However if we start by initializing a device with an address at which
there is no device, it won't send the empty payload probe but will fail
later on as there is no device at that address.

At this point the bus is basically in DoS as trying to init a device
will again not send the empty payload but now since the bus is in the
error state it will fail even if the device is in fact present.

src/adafruit_blinka/microcontroller/mcp2221/mcp2221.py

index 30f45f6e8bc7e0b1d7dbb6e50bc537515c8fdefb..e5b24bb119c34344b29d5c71a921a1c0097527d6 100644 (file)
@@ -198,7 +198,7 @@ class MCP2221:
         length = end - start
         retries = 0
 
         length = end - start
         retries = 0
 
-        while (end - start) > 0:
+        while (end - start) > 0 or not buffer:
             chunk = min(end - start, MCP2221_MAX_I2C_DATA_LEN)
             # write out current chunk
             resp = self._hid_xfer(
             chunk = min(end - start, MCP2221_MAX_I2C_DATA_LEN)
             # write out current chunk
             resp = self._hid_xfer(
@@ -223,6 +223,8 @@ class MCP2221:
             # yay chunk sent!
             while self._i2c_state() == RESP_I2C_PARTIALDATA:
                 time.sleep(0.001)
             # yay chunk sent!
             while self._i2c_state() == RESP_I2C_PARTIALDATA:
                 time.sleep(0.001)
+            if not buffer:
+                break
             start += chunk
             retries = 0
 
             start += chunk
             retries = 0