Skip to content

Commit df4f518

Browse files
authored
Merge pull request #1116 from makermelissa/fix-generic-linux-spi-write-readinto-slice
Fix generic Linux SPI write_readinto slice
2 parents ddc4686 + 33f4566 commit df4f518

2 files changed

Lines changed: 62 additions & 4 deletions

File tree

src/adafruit_blinka/microcontroller/generic_linux/spi.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,7 @@ def readinto(self, buf, start=0, end=None, write_value=0):
113113
def write_readinto(
114114
self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
115115
):
116-
"""Perform a half-duplex write from buffer_out and then
117-
read data into buffer_in
118-
"""
116+
"""Write to and read from SPI at the same time."""
119117
if buffer_out is None or buffer_in is None:
120118
return
121119
if len(buffer_out) < 1 or len(buffer_in) < 1:
@@ -132,7 +130,7 @@ def write_readinto(
132130
self._spi.max_speed_hz = self.baudrate
133131
self._spi.mode = self.mode
134132
self._spi.bits_per_word = self.bits
135-
data = self._spi.transfer(list(buffer_out[out_start : out_end + 1]))
133+
data = self._spi.transfer(list(buffer_out[out_start:out_end]))
136134
for i in range((in_end - in_start)):
137135
buffer_in[i + in_start] = data[i]
138136
# self._spi.close()

tests/test_generic_linux_spi.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# SPDX-FileCopyrightText: 2026 Melissa LeBlanc-Williams for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
import sys
5+
import types
6+
from unittest import mock
7+
8+
9+
class FakePureIOSPI:
10+
last_instance = None
11+
12+
def __init__(self, device):
13+
self.device = device
14+
self.max_speed_hz = None
15+
self.mode = None
16+
self.bits_per_word = None
17+
self.transfers = []
18+
FakePureIOSPI.last_instance = self
19+
20+
def transfer(self, data):
21+
self.transfers.append(data)
22+
return [value + 0x10 for value in data]
23+
24+
25+
def make_fake_detector():
26+
return types.SimpleNamespace(
27+
chip=types.SimpleNamespace(id="test-chip"),
28+
board=types.SimpleNamespace(id="test-board"),
29+
)
30+
31+
32+
fake_platformdetect = types.ModuleType("adafruit_platformdetect")
33+
fake_platformdetect.Detector = make_fake_detector
34+
sys.modules.setdefault("adafruit_platformdetect", fake_platformdetect)
35+
36+
fake_pureio = types.ModuleType("Adafruit_PureIO")
37+
fake_pureio.spi = types.SimpleNamespace(SPI=FakePureIOSPI)
38+
sys.modules.setdefault("Adafruit_PureIO", fake_pureio)
39+
40+
# pylint: disable=wrong-import-position
41+
from adafruit_blinka.microcontroller.generic_linux import ( # noqa: E402
42+
spi as generic_linux_spi,
43+
)
44+
45+
46+
@mock.patch.object(generic_linux_spi.spi, "SPI", FakePureIOSPI)
47+
def test_write_readinto_uses_exclusive_out_end():
48+
FakePureIOSPI.last_instance = None
49+
spi = generic_linux_spi.SPI((0, 0))
50+
spi.init(baudrate=1000000, polarity=1, phase=1, bits=8)
51+
52+
buffer_out = bytearray([0x10, 0x20, 0x30, 0x40])
53+
buffer_in = bytearray([0x00, 0x00, 0x00, 0x00])
54+
55+
spi.write_readinto(
56+
buffer_out, buffer_in, out_start=1, out_end=3, in_start=1, in_end=3
57+
)
58+
59+
assert FakePureIOSPI.last_instance.transfers == [[0x20, 0x30]]
60+
assert buffer_in == bytearray([0x00, 0x30, 0x40, 0x00])

0 commit comments

Comments
 (0)