@@ -376,9 +376,10 @@ def compose(self) -> ComposeResult:
376376 id = "doctor-banner" ,
377377 )
378378
379+ chip_info = f" [bold]Chip:[/] { self ._chip } " if self ._chip else " "
379380 yield Static (
380- f" [bold]Chip:[/] { self . _chip } [bold]Port:[/] { self ._port } \n "
381- " [bold yellow]Power-cycle the camera, then press Start [/]" ,
381+ f"{ chip_info } [bold]Port:[/] { self ._port } \n "
382+ " [dim]Connects to running agent, or uploads if needed [/]" ,
382383 id = "setup-panel" ,
383384 )
384385 yield Button (
@@ -463,28 +464,51 @@ def _upload_and_scan(self) -> None:
463464 self .run_worker (self ._do_upload_and_connect (), exclusive = True )
464465
465466 async def _do_upload_and_connect (self ) -> None :
466- """Upload agent via boot protocol, then connect and scan ."""
467+ """Try connecting to running agent first, upload if needed ."""
467468 import asyncio as aio
468469
469470 from defib .agent .client import FlashAgentClient , get_agent_binary
470- from defib .firmware import get_cached_path , download_firmware , has_firmware
471- from defib .profiles .loader import load_profile
472- from defib .protocol .hisilicon_standard import HiSiliconStandard
473- from defib .recovery .events import ProgressEvent
474471 from defib .transport .serial import SerialTransport
475472
476473 chip = self ._chip
477474 port = self ._port
478475
479- # Find agent binary
476+ # Try connecting to a running agent first
477+ try :
478+ transport = await SerialTransport .create (port )
479+ except Exception as e :
480+ self ._log (f"[red]Port error:[/] { e } " )
481+ return
482+
483+ self ._log ("Checking for running agent..." )
484+ client = FlashAgentClient (transport , chip )
485+ if await client .connect (timeout = 3.0 ):
486+ info = await client .get_info ()
487+ if info :
488+ self ._log ("[green]Agent already running![/]" )
489+ await self ._connected (transport , client , info )
490+ return
491+
492+ # No agent running — upload
493+ await transport .close ()
494+ if not chip :
495+ self ._log ("[red]No agent running and no chip selected — "
496+ "go back and select a chip to upload[/]" )
497+ return
498+
499+ self ._log ("No agent found. Uploading..." )
500+
480501 agent_path = get_agent_binary (chip )
481502 if not agent_path :
482503 self ._log (f"[red]No agent binary for '{ chip } '[/]" )
483504 return
484-
485505 agent_data = agent_path .read_bytes ()
486506
487- # Get SPL from cached U-Boot (download if needed)
507+ from defib .firmware import get_cached_path , download_firmware , has_firmware
508+ from defib .profiles .loader import load_profile
509+ from defib .protocol .hisilicon_standard import HiSiliconStandard
510+ from defib .recovery .events import ProgressEvent
511+
488512 try :
489513 profile = load_profile (chip )
490514 except Exception as e :
@@ -510,21 +534,16 @@ async def _do_upload_and_connect(self) -> None:
510534 f"SPL: { len (spl_data )} bytes"
511535 )
512536
513- # Open serial port
514- try :
515- transport = await SerialTransport .create (port )
516- except Exception as e :
517- self ._log (f"[red]Port error:[/] { e } " )
518- return
537+ transport = await SerialTransport .create (port )
519538
520- # Handshake + upload via boot protocol
521539 protocol = HiSiliconStandard ()
522540 protocol .set_profile (profile )
523541
524542 def on_progress (e : ProgressEvent ) -> None :
525543 if e .message :
526544 self ._log (f" { e .message } " )
527545
546+ self ._log ("[yellow]Waiting for bootrom — power-cycle now![/]" )
528547 hs = await protocol .handshake (transport , on_progress )
529548 if not hs .success :
530549 self ._log ("[red]Handshake failed[/]" )
@@ -541,7 +560,6 @@ def on_progress(e: ProgressEvent) -> None:
541560
542561 self ._log ("[green]Agent uploaded![/] Waiting for READY..." )
543562
544- # Reconnect and wait for agent
545563 await transport .close ()
546564 await aio .sleep (2 )
547565 transport = await SerialTransport .create (port )
@@ -553,8 +571,17 @@ def on_progress(e: ProgressEvent) -> None:
553571 return
554572
555573 info = await client .get_info ()
574+ await self ._connected (transport , client , info )
575+
576+ async def _connected (
577+ self , transport : object , client : object , info : dict , # type: ignore[type-arg]
578+ ) -> None :
579+ """Set up state after successful agent connection and start scan."""
580+ from defib .agent .client import FlashAgentClient
581+
582+ c : FlashAgentClient = client # type: ignore[assignment]
556583 self ._transport = transport
557- self ._client = client
584+ self ._client = c
558585 self ._flash_size = int (info .get ("flash_size" , 0 ))
559586 self ._sector_size = int (info .get ("sector_size" , 0x10000 ))
560587 self ._num_sectors = self ._flash_size // self ._sector_size if self ._sector_size else 0
0 commit comments