Packages
grizzly
9.0.0
9.1.4
9.1.2
9.1.1
9.1.0
9.0.0
8.15.3
8.15.2
8.15.1
8.15.0
8.14.0
8.13.0
8.12.0
8.11.3
8.11.2
8.11.1
8.11.0
8.10.0
8.9.0
8.8.1
8.8.0
8.7.1
8.7.0
8.6.12
8.6.11
8.6.10
8.6.9
8.6.8
8.6.7
retired
8.6.6
8.6.5
8.6.4
8.6.3
8.6.2
8.6.1
8.6.0
8.5.3
8.5.2
8.5.1
8.5.0
8.4.0
8.3.0
8.2.3
8.2.2
8.2.1
8.2.0
8.1.0
8.0.1
8.0.0
7.4.3
7.4.2
7.4.1
7.4.0
7.3.0
7.2.0
7.1.4
7.1.3
7.1.2
7.1.1
7.1.0
7.0.4
7.0.3
7.0.2
7.0.1
7.0.0
6.8.8
6.8.7
6.8.6
6.8.5
6.8.4
6.8.3
6.8.2
6.8.1
6.8.0
6.7.1
6.7.0
6.6.1
6.6.0
6.5.1
6.5.0
6.4.0
6.3.0
6.2.0
6.1.1
6.1.0
6.0.1
6.0.0
5.4.1
5.4.0
5.3.0
5.2.8
5.2.7
5.2.6
5.2.5
5.2.4
5.2.3
5.2.2
5.2.1
5.2.0
5.1.2
5.1.1
5.1.0
5.0.2
5.0.1
5.0.0
4.0.1
4.0.0
3.0.0
2.1.0
2.0.0
1.0.1
1.0.0
0.22.7
0.22.6
0.22.5
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.1
0.21.0
0.20.2
0.20.1
0.20.0
0.19.1
0.19.0
0.18.3
0.18.2
0.18.1
0.18.0
0.17.7
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.2
0.16.1
0.16.0
0.15.11
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.8
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.9.0-rc.4
0.9.0-rc.3
0.9.0-rc.2
0.9.0-rc.1
0.9.0-rc.0
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.0
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.3
0.4.2
Elixir Z-Wave library
Current section
Files
Jump to
Current section
Files
lib/grizzly/firmware_updates/otw/bootloader_framing.ex
defmodule Grizzly.FirmwareUpdates.OTW.BootloaderFraming do
@moduledoc """
A Circuits.UART.Framing implementation for handling framing of data
exchanged with the Gecko bootloader during over-the-wire firmware updates.
"""
@behaviour Circuits.UART.Framing
# These are the control characters we'll receive from the Gecko bootloader
defguardp is_xmodem_control_char(byte) when byte in [0x06, 0x15, 0x18, ?C]
@impl Circuits.UART.Framing
def init(_args) do
{:ok, <<>>}
end
@impl Circuits.UART.Framing
def add_framing(data, _rx_buffer) when is_binary(data) do
{:ok, data, <<>>}
end
@impl Circuits.UART.Framing
def frame_timeout(buffer) do
{:ok, [buffer], <<>>}
end
@impl Circuits.UART.Framing
def flush(:transmit, rx_buffer), do: rx_buffer
def flush(:receive, _rx_buffer), do: <<>>
def flush(:both, _rx_buffer), do: <<>>
@impl Circuits.UART.Framing
def remove_framing(data, rx_buffer) do
process_data(rx_buffer <> data, [])
end
# If we get a single byte and it's a control character, emit it as a frame.
defp process_data(<<ctrl>>, frames) when is_xmodem_control_char(ctrl) do
{:ok, frames ++ [<<ctrl>>], <<>>}
end
# Whenever the input starts with a potential control character (ASCII ACK, NAK,
# CAN, or 'C'), emit the control character as a single-byte frame.
defp process_data(<<ctrl, rest::binary>>, frames) when is_xmodem_control_char(ctrl) do
process_data(rest, frames ++ [<<ctrl>>])
end
defp process_data(data, frames) when byte_size(data) >= 1 do
cond do
# If the entire buffer is printable, put it into the buffer. The Gecko bootloader
# sends a null character when it's ready for input.
String.printable?(data) ->
{:ok, frames, data}
# If the entire buffer is printable after stripping out null bytes, split
# on the null bytes and emit each printable segment as a frame.
String.printable?(String.replace(data, <<0>>, "")) ->
String.split(data, <<0>>, trim: true)
|> Enum.reduce({:ok, frames, <<>>}, fn segment, {status, frames, buffer} ->
if String.printable?(segment) do
{status, frames ++ [segment], buffer}
else
{status, frames, buffer <> segment}
end
end)
# Otherwise, try to detect a Z-Wave SAPI frame.
true ->
{:ok, frames ++ [data], <<>>}
end
end
# Rx buffer is empty. Emit all accumulated frames.
defp process_data(<<>>, frames) do
{:ok, frames, <<>>}
end
# Anything else gets emitted as a frame.
defp process_data(data, frames) do
{:ok, frames ++ [data], <<>>}
end
end