diff options
Diffstat (limited to 'circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci')
5 files changed, 330 insertions, 0 deletions
diff --git a/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/__init__.py b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/__init__.py new file mode 100644 index 0000000..8f8006e --- /dev/null +++ b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/__init__.py @@ -0,0 +1,29 @@ +# Copyright (c) 2015, Nordic Semiconductor +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of Nordic Semiconductor ASA nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Package marker file.""" diff --git a/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/codec.py b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/codec.py new file mode 100644 index 0000000..bebd790 --- /dev/null +++ b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/codec.py @@ -0,0 +1,76 @@ +# Copyright (c) 2015, Nordic Semiconductor +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of Nordic Semiconductor ASA nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +UART_HEADER_OCTET_COUNT = 4 + + +class ThreeWireUartPacket(object): + """ + This class encapsulate a three wire uart packet according to Bluetooth specification + version 4.0 [Vol 4] part D. + """ + def __init__(self): + self.ack = None # Acknowledgement number + self.seq = None # Sequence number + self.di = None # Data integrity present + self.rp = None # Reliable packet + self.type = None # Packet type + self.length = None # Payload Length + self.checksum = None # Header checksum + self.payload = None # Payload + + @staticmethod + def decode(packet): + """ + Decodes a packet from a str encoded array + + :param packet_bytes: A str encoded array + :return: TheeWireUartPacket + """ + + decoded_packet = ThreeWireUartPacket() + + packet_bytes = bytearray(packet) + + decoded_packet.ack = (packet_bytes[0] & int('38', 16)) >> 3 + decoded_packet.seq = (packet_bytes[0] & int('07', 16)) + decoded_packet.di = (packet_bytes[0] & int('40', 16)) >> 6 + decoded_packet.rp = (packet_bytes[0] & int('80', 16)) >> 7 + decoded_packet.type = (packet_bytes[1] & int('0F', 16)) + decoded_packet.length = ((packet_bytes[1] & int('F0', 16)) >> 4) + (packet_bytes[2] * 16) + + checksum = packet_bytes[0] + checksum = checksum + packet_bytes[1] + checksum = checksum + packet_bytes[2] + checksum &= int('FF', 16) + decoded_packet.checksum = (~checksum + 1) & int('FF', 16) + + if decoded_packet.length > 0: + decoded_packet.payload = packet_bytes[UART_HEADER_OCTET_COUNT:-1] + + return decoded_packet diff --git a/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/slip.py b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/slip.py new file mode 100644 index 0000000..e2a525f --- /dev/null +++ b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/slip.py @@ -0,0 +1,115 @@ +# Copyright (c) 2015, Nordic Semiconductor +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of Nordic Semiconductor ASA nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import logging + +logger = logging.getLogger(__name__) + + +class Slip(object): + def __init__(self): + self.SLIP_END = '\xc0' + self.SLIP_ESC = '\xdb' + self.SLIP_ESC_END = '\xdc' + self.SLIP_ESC_ESC = '\xdd' + + self.started = False + self.escaped = False + self.stream = '' + self.packet = '' + + def append(self, data): + """ + Append a new + :param data: Append a new block of data to do decoding on when calling decode. + The developer may add more than one SLIP packet before calling decode. + :return: + """ + self.stream += data + + def decode(self): + """ + Decodes a package according to http://en.wikipedia.org/wiki/Serial_Line_Internet_Protocol + :return Slip: A list of decoded slip packets + """ + packet_list = list() + + for char in self.stream: + if char == self.SLIP_END: + if self.started: + if len(self.packet) > 0: + self.started = False + packet_list.append(self.packet) + self.packet = '' + else: + self.started = True + self.packet = '' + elif char == self.SLIP_ESC: + self.escaped = True + elif char == self.SLIP_ESC_END: + if self.escaped: + self.packet += self.SLIP_END + self.escaped = False + else: + self.packet += char + elif char == self.SLIP_ESC_ESC: + if self.escaped: + self.packet += self.SLIP_ESC + self.escaped = False + else: + self.packet += char + else: + if self.escaped: + logging.error("Error in SLIP packet, ignoring error.") + self.packet = '' + self.escaped = False + else: + self.packet += char + + self.stream = '' + + return packet_list + + def encode(self, packet): + """ + Encode a packet according to SLIP. + :param packet: A str array that represents the package + :return: str array with an encoded SLIP packet + """ + encoded = self.SLIP_END + + for char in packet: + if char == self.SLIP_END: + encoded += self.SLIP_ESC + self.SLIP_ESC_END + elif char == self.SLIP_ESC: + encoded += self.SLIP_ESC + self.SLIP_ESC_ESC + else: + encoded += char + encoded += self.SLIP_END + + return encoded diff --git a/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/tests/__init__.py b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/tests/__init__.py new file mode 100644 index 0000000..8f8006e --- /dev/null +++ b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/tests/__init__.py @@ -0,0 +1,29 @@ +# Copyright (c) 2015, Nordic Semiconductor +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of Nordic Semiconductor ASA nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Package marker file.""" diff --git a/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/tests/test_codec.py b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/tests/test_codec.py new file mode 100644 index 0000000..c7d6f26 --- /dev/null +++ b/circuitpython/lib/nrfutil/nordicsemi/bluetooth/hci/tests/test_codec.py @@ -0,0 +1,81 @@ +# Copyright (c) 2015, Nordic Semiconductor +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of Nordic Semiconductor ASA nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import json +import unittest +from nordicsemi.bluetooth.hci.slip import Slip +from nordicsemi.bluetooth.hci import codec + + +class TestInitPacket(unittest.TestCase): + def setUp(self): + pass + + def test_decode_packet(self): + # TODO: extend this test, this tests only a small portion of the slip/hci decoding + # These are packets read from Device Monitoring Studio + # during communication between serializer application and firmware + read_packets = [ + " C0 10 00 00 F0 C0 C0 D1 6E 00 C1 01 86 00 00 00 00 17 63 C0", + " C0 D2 DE 02 4E 02 1B 00 FF FF 01 17 FE B4 9A 9D E1 B0 F8 02" + " 01 06 11 07 1B C5 D5 A5 02 00 A9 B7 E2 11 A4 C6 00 FE E7 74" + " 09 09 49 44 54 57 32 31 38 48 5A BB C0", + " C0 D3 EE 00 3F 02 1B 00 FF FF 01 17 FE B4 9A 9D E1 AF 01 F1 62 C0", + " C0 D4 DE 02 4C 02 1B 00 FF FF 01 17 FE B4 9A 9D E1 B1 F8 02 01 06" + " 11 07 1B C5 D5 A5 02 00 A9 B7 E2 11 A4 C6 00 FE E7 74 09 09 49 44 54 57 32 31 38 48 6E C8 C0" + ] + + slip = Slip() + output = list() + + for uart_packet in read_packets: + hex_string = uart_packet.replace(" ", "") + hex_data = hex_string.decode("hex") + slip.append(hex_data) + + packets = slip.decode() + + for packet in packets: + output.append(codec.ThreeWireUartPacket.decode(packet)) + + self.assertEqual(len(output), 5) + + packet_index = 0 + self.assertEqual(output[packet_index].seq, 0) + + packet_index += 1 + self.assertEqual(output[packet_index].seq, 1) + + packet_index += 1 + self.assertEqual(output[packet_index].seq, 2) + + packet_index += 1 + self.assertEqual(output[packet_index].seq, 3) + + packet_index += 1 + self.assertEqual(output[packet_index].seq, 4) |