Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions scapy/contrib/bluetooth_vsc_barrot.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from scapy.packet import Packet, bind_layers
from scapy.fields import (
ByteField,
ConditionalField,
LEMACField,
StrFixedLenField,
XLEShortField,
XLEIntField,
Expand Down Expand Up @@ -51,6 +53,23 @@ class HCI_Cmd_VSC_Barrot_Read_Signature(Packet):
name = "Barrot Read Signature"


class HCI_Cmd_VSC_Barrot_Bd_Param(Packet):
"""
Barrot BD Param (cmd 0x05).

Sets the device bluetooth address to the 6 bytes ``bd_addr`` field. When
``bd_addr`` is left unset, nothing is set. Either way the device responds
with its bluetooth address.
"""
name = "Barrot HCI BD Param"
fields_desc = [
ConditionalField(
LEMACField("bd_addr", None),
lambda p: p.fields.get("bd_addr") is not None or len(p.original) >= 6
),
]


class HCI_Cmd_VSC_Barrot_Bus_Write(Packet):
"""
Barrot Bus Write (cmd 0x0E).
Expand Down Expand Up @@ -138,6 +157,18 @@ class HCI_Cmd_Complete_VSC_Barrot_Read_Signature(Packet):
fields_desc = [XStrFixedLenField("signature", b"\x00" * 32, 32)]


class HCI_Cmd_Complete_VSC_Barrot_Bd_Param(Packet):
"""
BD Param (cmd 0x05) command complete: the 6 bytes bluetooth address of
the device in ``bd_addr``.

When answering an address change, the address reported is the new one, if
it was set correctly.
"""
name = "Barrot HCI BD Param complete"
fields_desc = [LEMACField("bd_addr", None)]


class HCI_Cmd_Complete_VSC_Barrot_Bus_Read(Packet):
"""Bus Read (cmd 0x0F) command complete: the ``length`` bytes read from
the memory bus."""
Expand All @@ -160,6 +191,7 @@ class HCI_Cmd_Complete_VSC_Barrot_Flash_Read(Packet):
bind_layers(HCI_Command_Hdr, HCI_Cmd_VSC_Barrot, ogf=0x3F, ocf=0x080)
bind_layers(HCI_Cmd_VSC_Barrot, HCI_Cmd_VSC_Barrot_Read_Chip_Version, cmd=0x01)
bind_layers(HCI_Cmd_VSC_Barrot, HCI_Cmd_VSC_Barrot_Read_Signature, cmd=0x03)
bind_layers(HCI_Cmd_VSC_Barrot, HCI_Cmd_VSC_Barrot_Bd_Param, cmd=0x05)
bind_layers(HCI_Cmd_VSC_Barrot, HCI_Cmd_VSC_Barrot_Bus_Write, cmd=0x0E)
bind_layers(HCI_Cmd_VSC_Barrot, HCI_Cmd_VSC_Barrot_Bus_Read, cmd=0x0F)
bind_layers(HCI_Cmd_VSC_Barrot, HCI_Cmd_VSC_Barrot_Flash_Write, cmd=0x11)
Expand All @@ -171,6 +203,8 @@ class HCI_Cmd_Complete_VSC_Barrot_Flash_Read(Packet):
HCI_Cmd_Complete_VSC_Barrot_Read_Chip_Version, cmd=0x01)
bind_layers(HCI_Evt_VSC_Barrot_Command_Complete,
HCI_Cmd_Complete_VSC_Barrot_Read_Signature, cmd=0x03)
bind_layers(HCI_Evt_VSC_Barrot_Command_Complete,
HCI_Cmd_Complete_VSC_Barrot_Bd_Param, cmd=0x05)
bind_layers(HCI_Evt_VSC_Barrot_Command_Complete,
HCI_Cmd_Complete_VSC_Barrot_Bus_Read, cmd=0x0F)
bind_layers(HCI_Evt_VSC_Barrot_Command_Complete,
Expand Down
49 changes: 49 additions & 0 deletions test/contrib/bluetooth_vsc_barrot.uts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,55 @@ assert evt[HCI_Event_Command_Complete].status == 0
sig = evt[HCI_Cmd_Complete_VSC_Barrot_Read_Signature].signature
assert len(sig) == 32
assert sig == bytes.fromhex("26f71f00cf59b76f7ba01712190f208052300712d2d12c169a3b57b193632026")


+ Barrot BD Param (cmd 0x05)

= BD Param without an address only queries the device
cmd = HCI_Command_Hdr() / HCI_Cmd_VSC_Barrot() / HCI_Cmd_VSC_Barrot_Bd_Param()
assert cmd.opcode == 0xfc80
assert cmd.cmd == 0x05
# 80fc(op) 02(len) 0500(cmd id LE), no address bytes
assert raw(cmd) == b'\x80\xfc\x02\x05\x00'

= BD Param with an address build + dissect
cmd = HCI_Command_Hdr() / HCI_Cmd_VSC_Barrot() / HCI_Cmd_VSC_Barrot_Bd_Param(bd_addr="11:22:33:44:55:66")
r = raw(cmd)
# 80fc(op) 08(len) 0500(cmd id LE) 665544332211(addr LE)
assert r == b'\x80\xfc\x08\x05\x00\x66\x55\x44\x33\x22\x11'
p = HCI_Command_Hdr(r)
assert HCI_Cmd_VSC_Barrot_Bd_Param in p
assert p[HCI_Cmd_VSC_Barrot_Bd_Param].bd_addr == "11:22:33:44:55:66"

= The address bytes alone dissect as an address, not as a payload
p = HCI_Cmd_VSC_Barrot_Bd_Param(bytes.fromhex("665544332211"))
assert p.bd_addr == "11:22:33:44:55:66"
assert not p.payload

= A queried BD Param carries no address once dissected
# nothing follows the cmd id, so scapy stops at the subcommand layer
p = HCI_Command_Hdr(b'\x80\xfc\x02\x05\x00')
assert p[HCI_Cmd_VSC_Barrot].cmd == 0x05
assert HCI_Cmd_VSC_Barrot_Bd_Param not in p


+ Barrot BD Param command complete (opcode 0xFC80, echoed cmd 0x05)

= Dissect a BD Param Command Complete
# 04(evt) 0e(cmd complete) len=0a num=01 op=80fc status=00 cmd=0500 addr=665544332211
evt = HCI_Hdr(bytes.fromhex("040e0a0180fc000500665544332211"))
assert HCI_Cmd_Complete_VSC_Barrot_Bd_Param in evt
assert evt[HCI_Event_Command_Complete].status == 0
assert evt[HCI_Evt_VSC_Barrot_Command_Complete].cmd == 0x05
assert evt[HCI_Cmd_Complete_VSC_Barrot_Bd_Param].bd_addr == "11:22:33:44:55:66"

= A non-BD-Param command complete does not mis-parse as an address
# echoed cmd id 0x0f (bus read) must not bind to the BD Param complete class
evt = HCI_Hdr(bytes.fromhex("040e0c0180fc000f00665544332211"))
assert evt[HCI_Evt_VSC_Barrot_Command_Complete].cmd == 0x0f
assert HCI_Cmd_Complete_VSC_Barrot_Bd_Param not in evt


+ Barrot Bus Write (cmd 0x0E)

= Bus write build + dissect
Expand Down
Loading