Skip to content

Commit

Permalink
update parsing for ACL handles, implement new HCI commands
Browse files Browse the repository at this point in the history
Signed-off-by: Connor Rigby <[email protected]>
  • Loading branch information
ConnorRigby committed Sep 21, 2023
1 parent 03e71a1 commit 464eae6
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 18 deletions.
12 changes: 3 additions & 9 deletions lib/blue_heron/acl.ex
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
defmodule BlueHeron.ACL do
alias BlueHeron.ACL
require Logger

defstruct [:handle, :flags, :data]

def deserialize(
<<lower_handle, pb::2, bc::2, upper_handle::4, length::little-16,
acl_data::binary-size(length)>>
) do
def deserialize(<<handle::little-12, pb::2, bc::2, length::little-16,acl_data::binary-size(length)>>) do
data = BlueHeron.L2Cap.deserialize(acl_data)

<<handle::little-12>> = <<lower_handle, upper_handle::4>>

%ACL{
handle: handle,
flags: %{pb: pb, bc: bc},
Expand All @@ -24,8 +19,7 @@ defmodule BlueHeron.ACL do

def serialize(%ACL{data: data, handle: handle, flags: %{pb: pb, bc: bc}}) do
length = byte_size(data)
<<lower_handle, upper_handle::4>> = <<handle::little-12>>
<<lower_handle, pb::2, bc::2, upper_handle::4, length::little-16, data::binary-size(length)>>
<<handle::little-12, pb::2, bc::2, length::little-16, data::binary-size(length)>>
end

def serialize(binary) when is_binary(binary), do: binary
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule BlueHeron.HCI.Command.ControllerAndBaseband.SetControllerToHostFlowControl do
use BlueHeron.HCI.Command.ControllerAndBaseband, ocf: 0x0031

defparameters [flow_control_enable: 0]

defimpl BlueHeron.HCI.Serializable do
def serialize(%{opcode: opcode, flow_control_enable: flow_control_enable}) do
<<opcode::binary, 1, flow_control_enable>>
end
end

@impl BlueHeron.HCI.Command
def deserialize(<<@opcode::binary, 0>>) do
# This is a pretty useless function because there aren't
# any parameters to actually parse out of this, but we
# can at least assert its correct with matching
%__MODULE__{}
end

@impl BlueHeron.HCI.Command
def deserialize_return_parameters(<<status>>) do
%{status: status}
end

@impl true
def serialize_return_parameters(%{status: status}) do
<<BlueHeron.ErrorCode.to_code!(status)>>
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule BlueHeron.HCI.Command.LEController.ReadLocalSupportedFeatures do
use BlueHeron.HCI.Command.LEController, ocf: 0x0003

defparameters []

defimpl BlueHeron.HCI.Serializable do
def serialize(command) do
<<command.opcode::binary, 0>>
end
end

@impl BlueHeron.HCI.Command
def deserialize(<<@opcode::binary, 0>>) do
new()
end

@impl BlueHeron.HCI.Command
def deserialize_return_parameters(<<status, le_features::little-64>>) do
%{status: status, le_features: le_features}
end

@impl BlueHeron.HCI.Command
def serialize_return_parameters(%{status: status, le_features: features}) do
<<BlueHeron.ErrorCode.to_code!(status), features::little-64>>
end
end
26 changes: 26 additions & 0 deletions lib/blue_heron/hci/commands/le_controller/set_event_mask.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule BlueHeron.HCI.Command.LEController.SetEventMask do
use BlueHeron.HCI.Command.LEController, ocf: 0x08

defparameters mask: 0x00

defimpl BlueHeron.HCI.Serializable do
def serialize(command) do
<<command.opcode::binary, 8, command.mask::little-64>>
end
end

@impl BlueHeron.HCI.Command
def deserialize(<<@opcode::binary, _, mask::little-64>>) do
new(mask: mask)
end

@impl BlueHeron.HCI.Command
def deserialize_return_parameters(<<status>>) do
%{status: status}
end

@impl BlueHeron.HCI.Command
def serialize_return_parameters(%{status: status}) do
<<BlueHeron.ErrorCode.to_code!(status)>>
end
end
6 changes: 3 additions & 3 deletions lib/blue_heron/hci/commands/link_control/disconnect.ex
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
defmodule BlueHeron.HCI.Command.LinkControl.Disconnect do
use BlueHeron.HCI.Command.LinkControl, ocf: 0x0006

defparameters [:connection_handle, :reason]
defparameters [reason: 0x16, connection_handle: 0]

defimpl BlueHeron.HCI.Serializable do
def serialize(%{opcode: opcode, connection_handle: handle}) do
bin = <<handle::little-16, 0x16>>
def serialize(%{opcode: opcode, connection_handle: handle, reason: reason}) do
bin = <<handle::little-16, reason>>
size = byte_size(bin)
<<opcode::binary, size, bin::binary>>
end
Expand Down
3 changes: 2 additions & 1 deletion lib/blue_heron/hci/event.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ defmodule BlueHeron.HCI.Event do
Event.InquiryComplete,
Event.LEMeta.AdvertisingReport,
Event.LEMeta.ConnectionComplete,
Event.LEMeta.LongTermKeyRequest
Event.LEMeta.LongTermKeyRequest,
Event.LEMeta.ConnectionUpdateComplete
]

def __modules__(), do: @modules
Expand Down
7 changes: 2 additions & 5 deletions lib/blue_heron/hci/events/le_meta/connection_complete.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,8 @@ defmodule BlueHeron.HCI.Event.LEMeta.ConnectionComplete do
def deserialize(<<@code, _size, @subevent_code, bin::binary>>) do
<<
status,
lower_handle,
_::4,
upper_handle::4,
connection_handle::little-12,
0x00::4,
role,
peer_address_type,
peer_address::little-48,
Expand All @@ -76,8 +75,6 @@ defmodule BlueHeron.HCI.Event.LEMeta.ConnectionComplete do
master_clock_accuracy
>> = bin

<<connection_handle::little-12>> = <<lower_handle, upper_handle::4>>

%__MODULE__{
subevent_code: @subevent_code,
status: status,
Expand Down
41 changes: 41 additions & 0 deletions lib/blue_heron/hci/events/le_meta/connection_update_complete.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
defmodule BlueHeron.HCI.Event.LEMeta.ConnectionUpdateComplete do
use BlueHeron.HCI.Event.LEMeta, subevent_code: 0x3

defparameters [
:subevent_code,
:connection_handle,
:connection_interval,
:peripheral_latency,
:supervision_timeout,
:status
]

defimpl BlueHeron.HCI.Serializable do
def serialize(cc) do
raise(RuntimeError, "fixme")
end
end

@impl BlueHeron.HCI.Event
def deserialize(<<@code, _size, @subevent_code, bin::binary>>) do
<<
status,
connection_handle::little-12,
_unused::4,
connection_interval::little-16,
peripheral_latency::little-16,
supervision_timeout::little-16
>> = bin

%__MODULE__{
subevent_code: @subevent_code,
connection_handle: connection_handle,
connection_interval: connection_interval,
peripheral_latency: peripheral_latency,
supervision_timeout: supervision_timeout,
status: status
}
end

def deserialize(bin), do: {:error, bin}
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
defmodule BlueHeron.HCI.Event.LEMeta.EnhancedConnectionCompleteV1 do
use BlueHeron.HCI.Event.LEMeta, subevent_code: 0xA

defparameters [
:subevent_code,
:status,
:connection_handle,
:role,
:peer_address_type,
:peer_address,
:local_resolvable_private_address,
:peer_resolvable_private_address,
:connection_interval,
:peripheral_latency,
:supervision_timeout,
:central_clock_accuracy,
]

defimpl BlueHeron.HCI.Serializable do
def serialize(cc) do
<<lower_handle, upper_handle::4>> = <<cc.connection_handle::little-12>>
connection_handle = <<lower_handle, 0::4, upper_handle::4>>

bin = <<
cc.subevent_code,
cc.status,
connection_handle::binary,
cc.role,
cc.peer_address_type,
cc.peer_address::little-48,
cc.connection_interval::little-16,
cc.connection_latency::little-16,
cc.supervision_timeout::little-16,
cc.master_clock_accuracy
>>

size = byte_size(bin)

<<cc.code, size, bin::binary>>
end
end

@impl BlueHeron.HCI.Event
def deserialize(<<@code, _size, @subevent_code, bin::binary>>) do
<<
status,
lower_handle,
_::4,
upper_handle::4,
role,
peer_address_type,
peer_address::little-48,
local_resolvable_private_address::little-48,
peer_resolvable_private_address::little-48,
connection_interval::little-16,
peripheral_latency::little-16,
supervision_timeout::little-16,
central_clock_accuracy
>> = bin

<<connection_handle::little-12>> = <<lower_handle, upper_handle::4>>

%__MODULE__{
subevent_code: @subevent_code,
status: status,
connection_handle: connection_handle,
role: role,
peer_address_type: peer_address_type,
peer_address: peer_address,
connection_interval: connection_interval,
peripheral_latency: peripheral_latency,
supervision_timeout: supervision_timeout,
central_clock_accuracy: central_clock_accuracy,
local_resolvable_private_address: local_resolvable_private_address,
peer_resolvable_private_address: peer_resolvable_private_address,
}
end

def deserialize(bin), do: {:error, bin}
end

0 comments on commit 464eae6

Please sign in to comment.