Skip to content

Commit

Permalink
WIP 1
Browse files Browse the repository at this point in the history
  • Loading branch information
danielspofford committed May 1, 2019
1 parent 6d3206b commit a74c10c
Show file tree
Hide file tree
Showing 24 changed files with 332 additions and 113 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 1.0.*

## Breaking Changes

- [Adapter] `c::send_command/2` -> `c::cast/2`
- [HCI] remove `t::command/0` in favor of `binary()`
- [HCI] `command/2` now prepends its return with a `<<1>>`
- [Transport] remove `t::command/0` in favor of `binary()`
- [Transport] `send_command/2` -> `cast/2` (the backing `handle_call`s were
upadted as well)
- [UART] `send_command/2` -> `cast/2` (the backing `handle_call`s were upadted
as well)
- [UART] `cast/2` no longer prepends its `bin`s with a `<<1>>`

## Enhancements

- [Changelog] now Harald has one
- [HCI] `opcode/2` no longer guards `ogf` and `ocf` values because vendor
specific commands may fall outside of those bounds
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
[![CircleCI](https://circleci.com/gh/verypossible/harald.svg?style=svg)](https://circleci.com/gh/verypossible/harald)
[![Coverage Status](https://coveralls.io/repos/github/verypossible/harald/badge.svg)](https://coveralls.io/github/verypossible/harald)

[Documentation](https://hexdocs.pm/harald)

An Elixir Bluetooth Host library.

Active early development, reliable semantic versioning.

[Documentation](https://hexdocs.pm/harald).
127 changes: 127 additions & 0 deletions lib/harald/chip/ti/bts.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
defmodule Harald.Chip.TI.BTS do
@moduledoc """
Parsing functionality for BTS files.
Reference: http://www.ti.com/tool/WL18XX-BT-SP
"""

require Logger

@action_send_command 1

@action_wait_event 2

@action_serial 3

@action_delay 4

@action_run_script 5

@action_remarks 6

@doc """
Parses the BTS file at `path`.
Only send and delay actions are returned.
"""
def parse(path) do
<<
_magic::binary-size(4),
_version::little-size(32),
_future::size(192),
actions::binary
>> = File.read!(path)

reduce_actions(actions)
end

defp reduce_actions(bin, actions \\ [])

defp reduce_actions(<<>>, actions), do: Enum.reverse(actions)

defp reduce_actions(
<<
@action_send_command::little-size(16),
size::little-size(16),
data::binary-size(size),
rest::binary
>>,
actions
) do
debug(:send, data)
reduce_actions(rest, [data | actions])
end

defp reduce_actions(
<<
@action_wait_event::little-size(16),
size::little-size(16),
data::binary-size(size),
rest::binary
>>,
actions
) do
debug(:wait, data)
reduce_actions(rest, actions)
end

defp reduce_actions(
<<
@action_serial::little-size(16),
size::little-size(16),
data::binary-size(size),
rest::binary
>>,
actions
) do
debug(:serial, data)
reduce_actions(rest, actions)
end

defp reduce_actions(
<<
@action_delay::little-size(16),
size::little-size(16),
data::binary-size(size),
rest::binary
>>,
actions
) do
debug(:delay, data)
reduce_actions(rest, [data | actions])
end

defp reduce_actions(
<<
@action_run_script::little-size(16),
size::little-size(16),
data::binary-size(size),
rest::binary
>>,
actions
) do
debug(:run_script, data)
reduce_actions(rest, actions)
end

defp reduce_actions(
<<
@action_remarks::little-size(16),
size::little-size(16),
data::binary-size(size),
rest::binary
>>,
actions
) do
debug(:remarks, data)
reduce_actions(rest, actions)
end

defp debug(:remarks, bin) do
:ok = Logger.debug("remarks " <> String.replace(bin, <<0>>, <<>>))
end

defp debug(label, bin) do
:ok = Logger.debug(String.pad_trailing("#{label}", 10, " ") <> inspect(bin))
end
end
33 changes: 33 additions & 0 deletions lib/harald/chip/ti/wilink_8.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
defmodule Harald.Chip.TI.WiLink8 do
@moduledoc """
Setup functionality for the TI WiLink 8.
"""

alias Harald.Chip.TI.BTS
require Logger

def setup(_namespace, args) do
bts_path = Keyword.fetch!(args, :bts_path)
gpio_bt_en = Keyword.fetch!(args, :gpio_bt_en)
{:ok, pin_ref} = Circuits.GPIO.open(gpio_bt_en, :output)
Circuits.GPIO.write(pin_ref, 0)
Process.sleep(5)
Circuits.GPIO.write(pin_ref, 1)
Process.sleep(200)

hci_commands =
bts_path
|> BTS.parse()
|> Enum.filter(fn <<1, opcode::size(16), _::binary>> ->
<<x::little-size(16)>> = <<opcode::size(16)>>

case x do
65334 -> false
64780 -> false
_ -> true
end
end)

{:ok, hci_commands}
end
end
2 changes: 1 addition & 1 deletion lib/harald/data_type/manufacturer_behaviour.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Harald.ManufacturerDataBehaviour do
defmodule Harald.DataType.ManufacturerDataBehaviour do
@moduledoc """
Defines a behaviour that manufacturer data modules should implement.
"""
Expand Down
10 changes: 7 additions & 3 deletions lib/harald/data_type/manufacturer_data.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Harald.ManufacturerData do
defmodule Harald.DataType.ManufacturerData do
@moduledoc """
> The Manufacturer Specific data type is used for manufacturer specific data.
Expand All @@ -8,7 +8,7 @@ defmodule Harald.ManufacturerData do
`Harald.ManufacturerDataBehaviour` and `Harald.Serializable` behaviours.
"""

alias Harald.ManufacturerData.Apple
alias Harald.DataType.ManufacturerData.Apple
require Harald.AssignedNumbers.CompanyIdentifiers, as: CompanyIdentifiers

@modules [Apple]
Expand Down Expand Up @@ -46,13 +46,17 @@ defmodule Harald.ManufacturerData do

@doc """
Deserializes a manufacturer data binary.
iex> deserialize(<<76, 0, 2, 21, 172, 185, 137, 206, 253, 163, 76, 179, 137, 41, 101, 34, 252, 127, 2, 42, 181, 255, 224, 255, 225>>)
{:ok, {"Apple, Inc.", {"iBeacon", %{major: 46591, minor: 57599, tx_power: 225, uuid: 229590585283448776073135497520678371882}}}}
"""
def deserialize(binary)

Enum.each(@modules, fn
module ->
def deserialize(
<<unquote(CompanyIdentifiers.id(module.company()))::little, sub_bin::binary>> = bin
<<unquote(CompanyIdentifiers.id(module.company()))::little-size(16), sub_bin::binary>> =
bin
) do
case unquote(module).deserialize(sub_bin) do
{:ok, data} -> {:ok, {unquote(module).company, data}}
Expand Down
4 changes: 2 additions & 2 deletions lib/harald/data_type/manufacturer_data/apple.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Harald.ManufacturerData.Apple do
defmodule Harald.DataType.ManufacturerData.Apple do
@moduledoc """
Serialization module for Apple.
Expand All @@ -7,7 +7,7 @@ defmodule Harald.ManufacturerData.Apple do
Reference: https://en.wikipedia.org/wiki/IBeacon#Packet_Structure_Byte_Map
"""

alias Harald.{ManufacturerDataBehaviour, Serializable}
alias Harald.{DataType.ManufacturerDataBehaviour, Serializable}

@behaviour ManufacturerDataBehaviour

Expand Down
15 changes: 6 additions & 9 deletions lib/harald/hci.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,23 @@ defmodule Harald.HCI do

@type opts :: binary() | [opt()]

@type command :: <<_::8, _::_*8>>

@spec opcode(ogf(), ocf()) :: opcode()
def opcode(ogf, ocf) when ogf < 64 and ocf < 1024 do
def opcode(ogf, ocf) do
<<opcode::size(16)>> = <<ogf::size(6), ocf::size(10)>>
<<opcode::little-size(16)>>
end

@spec command(opcode(), opts()) :: command()
def command(opcode, opts \\ "")
@spec command(opcode(), opts()) :: binary()
def command(opcode, opts \\ <<>>)

def command(opcode, [_ | _] = opts) do
opts_bin = for o <- opts, into: "", do: to_bin(o)

opts_bin = for o <- opts, into: <<>>, do: to_bin(o)
command(opcode, opts_bin)
end

def command(opcode, opts) do
s = byte_size(opts)
opcode <> <<s::size(8)>> <> opts
size = byte_size(opts)
<<1, opcode::binary, size, opts::binary>>
end

@doc """
Expand Down
4 changes: 2 additions & 2 deletions lib/harald/hci/controller_and_baseband.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ defmodule Harald.HCI.ControllerAndBaseband do
> the BR/EDR Controller. See Section 6.23.
iex> read_local_name()
<<20, 12, 0>>
<<1, 20, 12, 0>>
"""
@spec read_local_name :: HCI.command()
@spec read_local_name :: binary()
def read_local_name, do: @ogf |> HCI.opcode(0x0014) |> HCI.command()
end
24 changes: 14 additions & 10 deletions lib/harald/hci/event/le_meta/advertising_report/device.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ defmodule Harald.HCI.Event.LEMeta.AdvertisingReport.Device do
"""

alias Harald.HCI.{ArrayedData, Event.LEMeta.AdvertisingReport.Device}
alias Harald.{ManufacturerData, Serializable, Transport.UART.Framing}
alias Harald.{DataType.ManufacturerData, Serializable, Transport.UART.Framing}
require Harald.AssignedNumbers.GenericAccessProfile, as: GenericAccessProfile

@enforce_keys [:event_type, :address_type, :address, :data, :rss]
Expand Down Expand Up @@ -325,17 +325,21 @@ defmodule Harald.HCI.Event.LEMeta.AdvertisingReport.Device do
end

def deserialize_ads(<<GenericAccessProfile.id("Service Data - 32-bit UUID"), bin::binary>>) do
<<
uuid::little-size(32),
data::binary
>> = bin
case bin do
<<
uuid::little-size(32),
data::binary
>> ->
service_data_32 = %{
uuid: uuid,
data: data
}

service_data_32 = %{
uuid: uuid,
data: data
}
{:ok, {"Service Data - 32-bit UUID", service_data_32}}

{:ok, {"Service Data - 32-bit UUID", service_data_32}}
_ ->
{:error, bin}
end
end

def deserialize_ads(<<type, bin::bits>>) when type in GenericAccessProfile.ids() do
Expand Down
12 changes: 6 additions & 6 deletions lib/harald/hci/le_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ defmodule Harald.HCI.LEController do
Bluetooth Core Spec v5
iex> set_enable_scan(true)
<<12, 32, 2, 1, 0>>
<<1, 12, 32, 2, 1, 0>>
iex> set_enable_scan(false)
<<12, 32, 2, 0, 0>>
<<1, 12, 32, 2, 0, 0>>
"""
@spec set_enable_scan(HCI.opt(), HCI.opt()) :: HCI.command()
@spec set_enable_scan(HCI.opt(), HCI.opt()) :: binary()
def set_enable_scan(enable, filter_duplicates \\ false) do
@ogf |> HCI.opcode(0x000C) |> HCI.command([enable, filter_duplicates])
end
Expand All @@ -61,7 +61,7 @@ defmodule Harald.HCI.LEController do
Refer to the spec to read more regarding the parameter values.
iex> set_scan_parameters(le_scan_type: 0x01)
<<11, 32, 7, 1, 16, 0, 16, 0, 0, 0>>
<<1, 11, 32, 7, 1, 16, 0, 16, 0, 0, 0>>
iex> set_scan_parameters(
iex> le_scan_type: 0x01,
Expand All @@ -70,9 +70,9 @@ defmodule Harald.HCI.LEController do
iex> own_address_type: 0x01,
iex> scanning_filter_policy: 0x01
iex> )
<<11, 32, 7, 1, 4, 0, 4, 0, 1, 1>>
<<1, 11, 32, 7, 1, 4, 0, 4, 0, 1, 1>>
"""
@spec set_scan_parameters(keyword) :: HCI.command()
@spec set_scan_parameters(keyword) :: binary()
def set_scan_parameters(new_params) do
# Defaults according to the Bluetooth Core Spec v5.
params =
Expand Down
14 changes: 10 additions & 4 deletions lib/harald/hci/packet.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ defmodule Harald.HCI.Packet do
Functions and definitions relevant to HCI packets.
"""

@type_command 0x01

@type_event 0x04

@doc """
Returns a keyword list definition of HCI packet types.
Expand All @@ -11,10 +15,12 @@ defmodule Harald.HCI.Packet do
"""
def types do
[
# command: 0x01,
# acl_data: 0x02,
# synchronous_data: 0x03,
event: 0x04
# command: @type_command
event: @type_event
]
end

def type(:command), do: @type_command

def type(:event), do: @type_event
end
Loading

0 comments on commit a74c10c

Please sign in to comment.