Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

Commit 28d6b1c

Browse files
authored
Merge pull request #340 from jumpstarter-dev/sdwire-fix
SDWire: record stable device link by id instead of diskseq
2 parents fc63e79 + 0256430 commit 28d6b1c

1 file changed

Lines changed: 41 additions & 25 deletions

File tree

  • packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire

packages/jumpstarter-driver-sdwire/jumpstarter_driver_sdwire/driver.py

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,30 @@ class SDWire(StorageMuxFlasherInterface, Driver):
2121

2222
storage_device: str | None = field(default=None)
2323

24+
def effective_storage_device(self):
25+
if self.storage_device is None:
26+
context = pyudev.Context()
27+
for udevice in (
28+
context.list_devices(subsystem="usb")
29+
.match_attribute("busnum", self.dev.bus)
30+
.match_attribute("devnum", self.dev.address)
31+
):
32+
# find siblings block device
33+
for block in filter(lambda d: d.subsystem == "block", udevice.parent.children):
34+
# find stable device link under by-diskseq
35+
for storage_device in filter(
36+
lambda link: link.startswith("/dev/disk/by-diskseq/"), block.device_links
37+
):
38+
return storage_device
39+
return None
40+
else:
41+
return self.storage_device
42+
2443
def __post_init__(self):
2544
if hasattr(super(), "__post_init__"):
2645
super().__post_init__()
2746

2847
for dev in usb.core.find(idVendor=0x04E8, idProduct=0x6001, find_all=True):
29-
if self.storage_device is None:
30-
context = pyudev.Context()
31-
# find matching udev device
32-
for udevice in (
33-
context.list_devices(subsystem="usb")
34-
.match_attribute("busnum", dev.bus)
35-
.match_attribute("devnum", dev.address)
36-
):
37-
# find siblings block device
38-
for block in filter(lambda d: d.subsystem == "block", udevice.parent.children):
39-
# find stable device link under by-diskseq
40-
for storage_device in filter(
41-
lambda link: link.startswith("/dev/disk/by-diskseq/"), block.device_links
42-
):
43-
self.storage_device = storage_device
44-
45-
if self.storage_device is None:
46-
raise FileNotFoundError("failed to find sdcard driver on sd-wire device")
47-
4848
product = usb.util.get_string(dev, dev.iProduct)
4949
serial = usb.util.get_string(dev, dev.iSerialNumber)
5050

@@ -60,6 +60,9 @@ def __post_init__(self):
6060
bInterfaceProtocol=0xFF,
6161
)
6262

63+
if self.effective_storage_device() is None:
64+
raise FileNotFoundError("failed to find sdcard driver on sd-wire device")
65+
6366
return
6467

6568
raise FileNotFoundError("failed to find sd-wire device")
@@ -100,30 +103,43 @@ def off(self):
100103

101104
async def wait_for_storage_device(self):
102105
with fail_after(10):
106+
storage_device = self.effective_storage_device()
107+
103108
while True:
104109
# https://stackoverflow.com/a/2774125
105-
fd = os.open(self.storage_device, os.O_WRONLY)
106110
try:
111+
fd = os.open(storage_device, os.O_WRONLY)
107112
if os.lseek(fd, 0, os.SEEK_END) > 0:
108113
break
114+
except OSError as e:
115+
match e.errno:
116+
case 123: # No medium found
117+
pass
118+
case 5: # Input/output error
119+
pass
120+
case _:
121+
raise
109122
finally:
110-
os.close(fd)
123+
if "fd" in locals():
124+
os.close(fd)
111125
await sleep(1)
112126

127+
return storage_device
128+
113129
@export
114130
async def write(self, src: str):
115131
self.host()
116-
await self.wait_for_storage_device()
117-
async with await FileWriteStream.from_path(self.storage_device) as stream:
132+
storage_device = await self.wait_for_storage_device()
133+
async with await FileWriteStream.from_path(storage_device) as stream:
118134
async with self.resource(src) as res:
119135
async for chunk in res:
120136
await stream.send(chunk)
121137

122138
@export
123139
async def read(self, dst: str):
124140
self.host()
125-
await self.wait_for_storage_device()
126-
async with await FileReadStream.from_path(self.storage_device) as stream:
141+
storage_device = await self.wait_for_storage_device()
142+
async with await FileReadStream.from_path(storage_device) as stream:
127143
async with self.resource(dst) as res:
128144
async for chunk in stream:
129145
await res.send(chunk)

0 commit comments

Comments
 (0)