diff --git a/scapy/contrib/bluetooth_vsc_barrot.py b/scapy/contrib/bluetooth_vsc_barrot.py index cf369772a03..07403b1208c 100644 --- a/scapy/contrib/bluetooth_vsc_barrot.py +++ b/scapy/contrib/bluetooth_vsc_barrot.py @@ -11,6 +11,8 @@ from scapy.packet import Packet, bind_layers from scapy.fields import ( ByteField, + ConditionalField, + LEMACField, StrFixedLenField, XLEShortField, XLEIntField, @@ -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). @@ -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.""" @@ -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) @@ -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, diff --git a/test/contrib/bluetooth_vsc_barrot.uts b/test/contrib/bluetooth_vsc_barrot.uts index 292614f434d..86e52d92859 100644 --- a/test/contrib/bluetooth_vsc_barrot.uts +++ b/test/contrib/bluetooth_vsc_barrot.uts @@ -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