Class: Rpremote::Flasher

Inherits:
Object
  • Object
show all
Defined in:
lib/rpremote/flasher.rb,
sig/rpremote.rbs

Defined Under Namespace

Classes: Error, InvalidTargetError, MountNotFoundError, Result, TimeoutError

Constant Summary collapse

DEFAULT_VOLUMES_ROOT =

Returns:

  • (String)
"/Volumes"
DEFAULT_TIMEOUT =

Returns:

  • (Float)
20.0
INFO_FILE =

Returns:

  • (String)
"INFO_UF2.TXT"
UF2_BLOCK_SIZE =
512
UF2_MAGIC_START0 =
0x0A324655
UF2_MAGIC_START1 =
0x9E5D5157
UF2_MAGIC_END =
0x0AB16F30

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(volumes_root: DEFAULT_VOLUMES_ROOT, timeout: DEFAULT_TIMEOUT, mount_probe: nil, port_probe: nil, sleeper: nil) ⇒ Flasher

Returns a new instance of Flasher.

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/rpremote/flasher.rb', line 24

def initialize(
  volumes_root: DEFAULT_VOLUMES_ROOT,
  timeout: DEFAULT_TIMEOUT,
  mount_probe: nil,
  port_probe: nil,
  sleeper: nil
)
  @volumes_root = volumes_root
  @timeout = Float(timeout)
  @mount_probe = mount_probe || ->(path) { Dir.exist?(path) }
  @port_probe = port_probe || -> { Device.main_port }
  @sleeper = sleeper || ->(seconds) { sleep(seconds) }
  raise ArgumentError, "timeout must be positive" unless @timeout.positive?
end

Instance Attribute Details

#timeoutFloat (readonly)

Returns the value of attribute timeout.

Returns:

  • (Float)


22
23
24
# File 'lib/rpremote/flasher.rb', line 22

def timeout
  @timeout
end

#volumes_rootString (readonly)

Returns the value of attribute volumes_root.

Returns:

  • (String)


22
23
24
# File 'lib/rpremote/flasher.rb', line 22

def volumes_root
  @volumes_root
end

Instance Method Details

#find_mount(explicit_mount = nil) ⇒ String

Parameters:

  • explicit_mount (String, nil) (defaults to: nil)

Returns:

  • (String)


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/rpremote/flasher.rb', line 49

def find_mount(explicit_mount = nil)
  return validate_mount!(File.expand_path(explicit_mount)) if explicit_mount

  matches = Dir.glob(File.join(volumes_root, "*")).select do |path|
    Dir.exist?(path) && valid_target?(path)
  end
  case matches.length
  when 0
    raise MountNotFoundError,
          "Pico 2 BOOTSEL drive not found; reconnect it while holding BOOTSEL or use --mount DIR"
  when 1
    matches.first
  else
    raise MountNotFoundError, "multiple Pico 2 BOOTSEL drives found; use --mount DIR"
  end
end

#flash(uf2_path, mount: nil, port: nil) ⇒ Result

Parameters:

  • uf2_path (String)
  • mount: (String, nil) (defaults to: nil)
  • port: (String, nil) (defaults to: nil)

Returns:



39
40
41
42
43
44
45
46
47
# File 'lib/rpremote/flasher.rb', line 39

def flash(uf2_path, mount: nil, port: nil)
  validate_firmware!(uf2_path)
  target = find_mount(mount)
  destination = File.join(target, File.basename(uf2_path))
  copy_firmware(uf2_path, destination)
  wait_until("BOOTSEL drive to disappear") { !mount_probe.call(target) }
  detected_port = wait_until("R2P2 serial port to appear") { detect_port(port) }
  Result.new(mount: target, destination: destination, port: detected_port)
end