Add nuttx to the system framework, which is 10.1.0
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
############################################################################
|
||||
# apps/wireless/bluetooth/Make.defs
|
||||
# Adds selected applications to apps/ build
|
||||
#
|
||||
# Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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.
|
||||
# 3. Neither the name NuttX 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 OWNER 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(wildcard $(APPDIR)/wireless/bluetooth/*/Make.defs)
|
||||
@@ -0,0 +1,38 @@
|
||||
############################################################################
|
||||
# apps/wireless/bluetooth/Makefile
|
||||
#
|
||||
# Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
# Author: Sebastien Lorquet <sebastien@lorquet.fr>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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.
|
||||
# 3. Neither the name NuttX 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 OWNER 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
MENUDESC = "Bluetooth applications"
|
||||
|
||||
include $(APPDIR)/Directory.mk
|
||||
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see misc/tools/kconfig-language.txt.
|
||||
#
|
||||
|
||||
config BTSAK
|
||||
tristate "Bluetooth Swiss Army Knife"
|
||||
default n
|
||||
---help---
|
||||
Enable the Bluetooth Swiss Army Knife
|
||||
|
||||
if BTSAK
|
||||
|
||||
config BTSAK_PROGNAME
|
||||
string "Program name"
|
||||
default "bt"
|
||||
---help---
|
||||
This is the name of the program that will be used when the NSH ELF
|
||||
program is installed.
|
||||
|
||||
config BTSAK_PRIORITY
|
||||
int "btsak task priority"
|
||||
default 100
|
||||
|
||||
config BTSAK_STACKSIZE
|
||||
int "btsak stack size"
|
||||
default DEFAULT_TASK_STACKSIZE
|
||||
|
||||
if NET_6LOWPAN && !NET_BLUETOOTH
|
||||
|
||||
config BTSAK_DEFAULT_PORT
|
||||
int "Default Port"
|
||||
default 61616
|
||||
---help---
|
||||
The default port to be used for commands when using btsak through a
|
||||
Pv6 network interface (ex. wpan0). Port is 61616 because 6LoWPAN has
|
||||
special compression for port 61616-61631
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,39 @@
|
||||
############################################################################
|
||||
# apps/wireless/bluetooth/btsak/Make.defs
|
||||
# Adds selected applications to apps/ build
|
||||
#
|
||||
# Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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.
|
||||
# 3. Neither the name NuttX 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 OWNER 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_BTSAK),)
|
||||
CONFIGURED_APPS += $(APPDIR)/wireless/bluetooth/btsak
|
||||
endif
|
||||
@@ -0,0 +1,51 @@
|
||||
############################################################################
|
||||
# apps/wireless/bluetooth/btsak/Makefile
|
||||
#
|
||||
# Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. 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.
|
||||
# 3. Neither the name NuttX 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 OWNER 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
# Bluetooth SAK (swiss army knife )
|
||||
|
||||
CSRCS = btsak_advertise.c btsak_features.c btsak_gatt.c btsak_info.c
|
||||
CSRCS += btsak_scan.c btsak_security.c
|
||||
MAINSRC = btsak_main.c
|
||||
|
||||
# Application info
|
||||
|
||||
PROGNAME = $(CONFIG_BTSAK_PROGNAME)
|
||||
PRIORITY = $(CONFIG_BTSAK_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_BTSAK_STACKSIZE)
|
||||
MODULE = $(CONFIG_BTSAK)
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
@@ -0,0 +1,140 @@
|
||||
# Wireless / Bluetooth / `btsak` Bluetooth Swiss Army Knife
|
||||
|
||||
## Commands
|
||||
|
||||
```
|
||||
Command: help
|
||||
Description: Should overall command help
|
||||
Usage: bt <ifname> help
|
||||
```
|
||||
|
||||
```
|
||||
Command: info
|
||||
Description: Show Bluetooth driver information
|
||||
Usage: bt <ifname> info [-h]
|
||||
```
|
||||
|
||||
```
|
||||
Command: features
|
||||
Description: Show Bluetooth driver information
|
||||
Usage: bt <ifname> features [-h] [le]
|
||||
Where: le - Selects LE features vs BR/EDR features
|
||||
```
|
||||
|
||||
```
|
||||
Command: scan
|
||||
Description: Bluetooth scan commands
|
||||
Usage: bt <ifname> scan [-h] <start [-d]|get|stop>
|
||||
Where: start - Starts scanning. The -d option enables duplicate
|
||||
filtering.
|
||||
get - Shows new accumulated scan results
|
||||
stop - Stops scanning
|
||||
```
|
||||
|
||||
```
|
||||
Command: advertise
|
||||
Description: Bluetooth advertise commands
|
||||
Usage: bt <ifname> advertise [-h] <start|stop>
|
||||
Where: start - Starts advertising
|
||||
stop - Stops advertising
|
||||
```
|
||||
|
||||
```
|
||||
Command: security
|
||||
Description: Enable security (encryption) for a connection:
|
||||
If device is paired, key encryption will be enabled. If
|
||||
the link is already encrypted with sufficiently strong
|
||||
key this command does nothing.
|
||||
|
||||
If the device is not paired pairing will be initiated. If
|
||||
the device is paired and keys are too weak but input output
|
||||
capabilities allow for strong enough keys pairing will be
|
||||
initiated.
|
||||
|
||||
This command may return error if required level of security
|
||||
is not possible to achieve due to local or remote device
|
||||
limitation (eg input output capabilities).
|
||||
Usage: bt <ifname> security [-h] <addr> public|private <level>
|
||||
Where: <addr> - The 6-byte address of the connected peer
|
||||
<level> - Security level, on of:
|
||||
|
||||
low - No encryption and no authentication
|
||||
medium - Encryption and no authentication (no MITM)
|
||||
high - Encryption and authentication (MITM)
|
||||
fips - Authenticated LE secure connections and encryption
|
||||
```
|
||||
|
||||
```
|
||||
Command: gatt
|
||||
Description: Generic Attribute (GATT) commands
|
||||
Usage: bt <ifname> gatt [-h] <cmd> [option [option [option...]]]
|
||||
Where: See "GATT Commands" below
|
||||
```
|
||||
|
||||
## GATT Commands
|
||||
|
||||
```
|
||||
Command: exchange-mtu
|
||||
Description: Set MTU to out maximum and negotiate MTU with peer
|
||||
Usage: bt <ifname> gatt exchange-mtu [-h] <addr> public|private
|
||||
```
|
||||
|
||||
```
|
||||
Command: mget
|
||||
Description: Get the pass/fail result of the last GATT 'exchange-mtu' command
|
||||
Usage: bt <ifname> gatt mget [-h]
|
||||
```
|
||||
|
||||
```
|
||||
Command: discover
|
||||
Description: Initiate discovery
|
||||
Usage: bt <ifname> gatt discover [-h] <addr> public|private <uuid16> [<start> [<end>]]
|
||||
```
|
||||
|
||||
```
|
||||
Command: characteristic
|
||||
Description: Initiate characteristics discovery
|
||||
Usage: bt <ifname> gatt characteristic [-h] <addr> public|private [<start> [<end>]]
|
||||
```
|
||||
|
||||
```
|
||||
Command: descriptor
|
||||
Description: Initiate characteristics discovery
|
||||
Usage: bt <ifname> gatt descriptor [-h] <addr> public|private [<start> [<end>]]
|
||||
```
|
||||
|
||||
```
|
||||
Command: dget
|
||||
Description: Get the result of the last discovery action
|
||||
Usage: bt <ifname> gatt dget [-h]
|
||||
```
|
||||
|
||||
```
|
||||
Command: read
|
||||
Description: Initiate a GATT read operation.
|
||||
Usage: bt <ifname> gatt read [-h] <addr> public|private <handle> [<offset>]
|
||||
```
|
||||
|
||||
```
|
||||
Command: read-multiple
|
||||
Description: Initiate a GATT read-multiple operation.
|
||||
Usage: bt <ifname> gatt read-multiple [-h] <addr> public|private <handle> [<handle> [<handle>]..]
|
||||
```
|
||||
|
||||
```
|
||||
Command: rget
|
||||
Description: Get the data resulting from the last read operation
|
||||
Usage: bt <ifname> gatt rget [-h]
|
||||
```
|
||||
|
||||
```
|
||||
Command: write
|
||||
Description: Initiate a GATT write operation.
|
||||
Usage: bt <ifname> gatt write [-h] <addr> public|private <handle> <byte> [<byte> [<byte>]..]
|
||||
```
|
||||
|
||||
```
|
||||
Command: wget
|
||||
Description: Get the pass/fail result of the last GATT 'write' command
|
||||
Usage: bt <ifname> gatt wget [-h]
|
||||
```
|
||||
@@ -0,0 +1,275 @@
|
||||
/****************************************************************************
|
||||
* apps/wireless/bluetooth/btsak/btsak.h
|
||||
* Bluetooth Swiss Army Knife
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Based loosely on the i8sak IEEE 802.15.4 program by Anthony Merlino and
|
||||
* Sebastien Lorquet. Commands inspired for btshell example in the
|
||||
* Intel/Zephyr Arduino 101 package (BSD license).
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name NuttX 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 OWNER 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_EXAMPLES_WIRELESS_BLUETOOTH_BTSAK_BTSAK_H
|
||||
#define __APPS_EXAMPLES_WIRELESS_BLUETOOTH_BTSAK_BTSAK_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netpacket/bluetooth.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define BTSAK_MAX_IFNAME 12
|
||||
#define BTSAK_DAEMONNAME_FMT "btsak_%s"
|
||||
#define BTSAK_DAEMONNAME_PREFIX_LEN 6
|
||||
#define BTSAK_MAX_DAEMONNAME BTSAK_DAEMONNAME_PREFIX_LEN + BTSAK_MAX_IFNAME
|
||||
#define BTSAK_DEFAULT_EPADDR {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct btsak_s
|
||||
{
|
||||
FAR char *progname; /* Program name */
|
||||
FAR char *ifname; /* Interface name */
|
||||
bt_addr_t ep_btaddr; /* Blue tooth address */
|
||||
#if defined(CONFIG_NET_BLUETOOTH)
|
||||
struct sockaddr_l2 ep_sockaddr; /* AF_BLUETOOTH endpoint address */
|
||||
#elif defined(CONFIG_NET_6LOWPAN)
|
||||
struct sockaddr_in6 ep_sockaddr; /* IPv6 endpoint address */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_6LOWPAN
|
||||
static inline void btsak_update_ipv6addr(FAR struct btsak_s *btsak)
|
||||
{ dev->d_ipv6addr[0] = HTONS(0xfe80);
|
||||
dev->d_ipv6addr[1] = 0;
|
||||
dev->d_ipv6addr[2] = 0;
|
||||
dev->d_ipv6addr[3] = 0;
|
||||
dev->d_ipv6addr[4] = HTONS(0x0200);
|
||||
dev->d_ipv6addr[5] = (uint16_t)addr[0] << 8 | (uint16_t)addr[1];
|
||||
dev->d_ipv6addr[6] = (uint16_t)addr[2] << 8 | (uint16_t)addr[3];
|
||||
dev->d_ipv6addr[7] = (uint16_t)addr[4] << 8 | (uint16_t)addr[5];
|
||||
|
||||
btsak->ep_in6addr.sin6_addr.in6_u.u6_addr16[0] = HTONS(0xfe80);
|
||||
btsak->ep_in6addr.sin6_addr.in6_u.u6_addr16[1] = 0;
|
||||
btsak->ep_in6addr.sin6_addr.in6_u.u6_addr16[2] = 0;
|
||||
btsak->ep_in6addr.sin6_addr.in6_u.u6_addr16[3] = 0;
|
||||
btsak->ep_in6addr.sin6_addr.in6_u.u6_addr16[4] = HTONS(0x0200);
|
||||
btsak->ep_in6addr.sin6_addr.in6_u.u6_addr16[5] =
|
||||
((uint16_t)btsak->ep_btaddr.val[0] << 8 |
|
||||
(uint16_t)btsak->ep_btaddr.val[1]);
|
||||
btsak->ep_in6addr.sin6_addr.in6_u.u6_addr16[6] =
|
||||
((uint16_t)btsak->ep_btaddr.val[2] << 8 |
|
||||
(uint16_t)btsak->ep_btaddr.val[3]);
|
||||
btsak->ep_in6addr.sin6_addr.in6_u.u6_addr16[7] =
|
||||
((uint16_t)btsak->ep_btaddr.val[4] << 8 |
|
||||
(uint16_t)btsak->ep_btaddr.val[5]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_char2nibble
|
||||
*
|
||||
* Description:
|
||||
* Convert an hexadecimal character to a 4-bit nibble.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_char2nibble(char ch);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2long
|
||||
*
|
||||
* Description:
|
||||
* Convert a numeric string to an long value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long btsak_str2long(FAR const char *str);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2uint8
|
||||
*
|
||||
* Description:
|
||||
* Convert a numeric string to an uint8_t value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint8_t btsak_str2uint8(FAR const char *str);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2uint16
|
||||
*
|
||||
* Description:
|
||||
* Convert a numeric string to an uint16_t value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint16_t btsak_str2uint16(FAR const char *str);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2bool
|
||||
*
|
||||
* Description:
|
||||
* Convert a boolean name to a boolean value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool btsak_str2bool(FAR const char *str);
|
||||
|
||||
/****************************************************************************
|
||||
* Name : btsak_str2payload
|
||||
*
|
||||
* Description :
|
||||
* Parse string to get buffer of data. Buf is expected to be of size
|
||||
* BLUETOOTH_SMP_MTU or larger.
|
||||
*
|
||||
* Returns:
|
||||
* Positive length value of frame payload
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_str2payload(FAR const char *str, FAR uint8_t *buf);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2addr
|
||||
*
|
||||
* Description:
|
||||
* Convert a string of the form "xx:xx:xx:xx:xx:xx" 6-byte Bluetooth
|
||||
* address (where xx is a one or two character hexadecimal number sub-
|
||||
* string)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_str2addr(FAR const char *str, FAR uint8_t *addr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2addrtype
|
||||
*
|
||||
* Description:
|
||||
* Convert a string to an address type. String options are "public" or
|
||||
* "private".
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_str2addrtype(FAR const char *str, FAR uint8_t *addrtype);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2seclevel
|
||||
*
|
||||
* Description:
|
||||
* Convert a string to a security level. String options are "low",
|
||||
* "medium", "high", or "fips"
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_str2seclevel(FAR const char *str, FAR enum bt_security_e *level);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_socket
|
||||
*
|
||||
* Description:
|
||||
* Create a socket on the selected device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_socket(FAR struct btsak_s *btsak);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show program usage.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_showusage(FAR const char *progname, int exitcode);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_gatt_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show gatt command usage.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_gatt_showusage(FAR const char *progname, FAR const char *cmd,
|
||||
int exitcode);
|
||||
|
||||
/****************************************************************************
|
||||
* Command handlers
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_info(FAR struct btsak_s *btsak, int argc, FAR char *argv[]);
|
||||
void btsak_cmd_features(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_scan(FAR struct btsak_s *btsak, int argc, FAR char *argv[]);
|
||||
void btsak_cmd_advertise(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_security(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_gatt_exchange_mtu(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_connect(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_disconnect(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_discover(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_gatt_discover_characteristic(FAR struct btsak_s *btsak,
|
||||
int argc, FAR char *argv[]);
|
||||
void btsak_cmd_gatt_discover_descriptor(FAR struct btsak_s *btsak,
|
||||
int argc, FAR char *argv[]);
|
||||
void btsak_cmd_gatt_read(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_gatt_read_multiple(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
void btsak_cmd_gatt_write(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
|
||||
#endif /* __APPS_EXAMPLES_WIRELESS_BLUETOOTH_BTSAK_BTSAK_H */
|
||||
@@ -0,0 +1,243 @@
|
||||
/****************************************************************************
|
||||
* apps/wireless/bluetooth/btsak/btsak_advertise.c
|
||||
* Bluetooth Swiss Army Knife -- Advertise command
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Based loosely on the i8sak IEEE 802.15.4 program by Anthony Merlino and
|
||||
* Sebastien Lorquet. Commands inspired for btshell example in the
|
||||
* Intel/Zephyr Arduino 101 package (BSD license).
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name NuttX 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 OWNER 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/wireless/bluetooth/bt_core.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_hci.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_ioctl.h>
|
||||
|
||||
#include "btsak.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_advertise_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show usage of the advertise command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_advertise_showusage(FAR const char *progname,
|
||||
FAR const char *cmd, int exitcode)
|
||||
{
|
||||
fprintf(stderr, "%s: Advertise commands:\n", cmd);
|
||||
fprintf(stderr, "Usage:\n\n");
|
||||
fprintf(stderr, "\t%s <ifname> %s [-h] <start|stop>\n",
|
||||
progname, cmd);
|
||||
fprintf(stderr, "\nWhere the options do the following:\n\n");
|
||||
fprintf(stderr, "\tstart\t- Starts advertising (type ADV_IND).\n");
|
||||
fprintf(stderr, "\tstop\t- Stops advertising\n");
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_advertisestart
|
||||
*
|
||||
* Description:
|
||||
* Advertise start command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_cmd_advertisestart(FAR struct btsak_s *btsak, FAR char *cmd,
|
||||
int argc, FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
struct bt_eir_s ad[2]; /* Data for advertisement packets */
|
||||
struct bt_eir_s sd[2]; /* Data for scan response packets */
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
/* REVISIT: Should support all advertising type. Only ADV_IND is
|
||||
* supported:
|
||||
*
|
||||
* ADV_IND
|
||||
* Known as Advertising Indications (ADV_IND), where a peripheral device
|
||||
* requests connection to any central device (i.e., not directed at a
|
||||
* particular central device).
|
||||
* Example: A smart watch requesting connection to any central device.
|
||||
* ADV_DIRECT_IND
|
||||
* Similar to ADV_IND, yet the connection request is directed at a
|
||||
* specific central device.
|
||||
* Example: A smart watch requesting connection to a specific central
|
||||
* device.
|
||||
* ADV_NONCONN_IND
|
||||
* Non connectible devices, advertising information to any listening
|
||||
* device.
|
||||
* Example: Beacons in museums defining proximity to specific exhibits.
|
||||
* ADV_SCAN_IND
|
||||
* Similar to ADV_NONCONN_IND, with the option additional information via
|
||||
* scan responses.
|
||||
* Example: A warehouse pallet beacon allowing a central device to
|
||||
* request additional information about the pallet.
|
||||
*/
|
||||
|
||||
/* The data for advertisement and response packets are provided as arrays
|
||||
* terminated by an entry with len=2.
|
||||
*
|
||||
* REVISIT: To be useful for anything other than testing, there must
|
||||
* be some mechanism to specify the advertise and response data.
|
||||
*/
|
||||
|
||||
memset(&ad, 0, 2 * sizeof(struct bt_eir_s));
|
||||
ad[0].len = 2;
|
||||
ad[0].type = BT_EIR_FLAGS;
|
||||
ad[0].data[0] = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR;
|
||||
|
||||
memset(&sd, 0, 2 * sizeof(struct bt_eir_s));
|
||||
sd[1].len = sizeof("btsak");
|
||||
sd[1].type = BT_EIR_NAME_COMPLETE;
|
||||
strcpy((FAR char *)sd[1].data, "btsak");
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
btreq.btr_advtype = BT_LE_ADV_IND;
|
||||
btreq.btr_advad = ad;
|
||||
btreq.btr_advsd = sd;
|
||||
|
||||
/* Perform the IOCTL to start advertising */
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTADVSTART,
|
||||
(unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTADVSTART) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_advertisestop
|
||||
*
|
||||
* Description:
|
||||
* Advertise stop command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_cmd_advertisestop(FAR struct btsak_s *btsak, FAR char *cmd,
|
||||
int argc, FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
/* Perform the IOCTL to stop advertising */
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTADVSTOP,
|
||||
(unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTADVSTOP) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_advertise
|
||||
*
|
||||
* Description:
|
||||
* advertise [-h] <start [-d] |get|stop> command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_advertise(FAR struct btsak_s *btsak, int argc, FAR char *argv[])
|
||||
{
|
||||
int argind;
|
||||
|
||||
/* Verify that an option was provided */
|
||||
|
||||
argind = 1;
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing advertise command\n");
|
||||
btsak_advertise_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Check for command */
|
||||
|
||||
if (strcmp(argv[argind], "-h") == 0)
|
||||
{
|
||||
btsak_advertise_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
else if (strcmp(argv[argind], "start") == 0)
|
||||
{
|
||||
btsak_cmd_advertisestart(btsak, argv[0], argc - argind, &argv[argind]);
|
||||
}
|
||||
else if (strcmp(argv[argind], "stop") == 0)
|
||||
{
|
||||
btsak_cmd_advertisestop(btsak, argv[0], argc - argind, &argv[argind]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unrecognized advertise command: %s\n", argv[argind]);
|
||||
btsak_advertise_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/****************************************************************************
|
||||
* apps/wireless/bluetooth/btsak/btsak_features.c
|
||||
* Bluetooth Swiss Army Knife -- Info
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Based loosely on the i8sak IEEE 802.15.4 program by Anthony Merlino and
|
||||
* Sebastien Lorquet. Commands inspired for btshell example in the
|
||||
* Intel/Zephyr Arduino 101 package (BSD license).
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name NuttX 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 OWNER 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/wireless/bluetooth/bt_core.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_hci.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_ioctl.h>
|
||||
|
||||
#include "btsak.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_features_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show usage of the security command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_features_showusage(FAR const char *progname,
|
||||
FAR const char *cmd, int exitcode)
|
||||
{
|
||||
fprintf(stderr, "%s:\tShow Bluetooth device features\n", cmd);
|
||||
fprintf(stderr, "Usage:\n\n");
|
||||
fprintf(stderr, "\t%s <ifname> %s [-h] [le]\n\n",
|
||||
progname, cmd);
|
||||
fprintf(stderr, "Where\n");
|
||||
fprintf(stderr, "\tSelects LE features (vs BR/EDR features)\n");
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_features
|
||||
*
|
||||
* Description:
|
||||
* security command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_features(FAR struct btsak_s *btsak, int argc, FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
int sockfd;
|
||||
int cmd;
|
||||
int ret;
|
||||
|
||||
/* Check for help or LE options */
|
||||
|
||||
cmd = SIOCGBTFEAT;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
if (strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_features_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
else if (strcmp(argv[1], "le") == 0)
|
||||
{
|
||||
cmd = SIOCGBTLEFEAT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to stop advertising */
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, cmd, (unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(%04x) failed: %d\n",
|
||||
cmd, errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Page 0:\n");
|
||||
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
btreq.btr_features0[0], btreq.btr_features0[1],
|
||||
btreq.btr_features0[2], btreq.btr_features0[3],
|
||||
btreq.btr_features0[4], btreq.btr_features0[5],
|
||||
btreq.btr_features0[6], btreq.btr_features0[7]);
|
||||
printf("Page 1:\n");
|
||||
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
btreq.btr_features1[0], btreq.btr_features1[1],
|
||||
btreq.btr_features1[2], btreq.btr_features1[3],
|
||||
btreq.btr_features1[4], btreq.btr_features1[5],
|
||||
btreq.btr_features1[6], btreq.btr_features1[7]);
|
||||
printf("Page 2:\n");
|
||||
printf("\t%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
btreq.btr_features2[0], btreq.btr_features2[1],
|
||||
btreq.btr_features2[2], btreq.btr_features2[3],
|
||||
btreq.btr_features2[4], btreq.btr_features2[5],
|
||||
btreq.btr_features2[6], btreq.btr_features2[7]);
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
@@ -0,0 +1,610 @@
|
||||
/****************************************************************************
|
||||
* apps/wireless/bluetooth/btsak/btsak_gatt.c
|
||||
* Bluetooth Swiss Army Knife -- GATT commands
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Based loosely on the i8sak IEEE 802.15.4 program by Anthony Merlino and
|
||||
* Sebastien Lorquet. Commands inspired for btshell example in the
|
||||
* Intel/Zephyr Arduino 101 package (BSD license).
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name NuttX 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 OWNER 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/wireless/bluetooth/bt_core.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_gatt.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_ioctl.h>
|
||||
|
||||
#include "btsak.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_discover_common
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] <discover-cmd> [-h] <addr> public|private [<uuid16>]
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_cmd_discover_common(FAR struct btsak_s *btsak,
|
||||
int argc, FAR char *argv[],
|
||||
enum bt_gatt_discover_e type)
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
unsigned int argndx;
|
||||
int sockfd;
|
||||
int ret;
|
||||
FAR struct bt_discresonse_s *rsp;
|
||||
struct bt_discresonse_s result[CONFIG_BLUETOOTH_MAXDISCOVER];
|
||||
int i;
|
||||
|
||||
/* Check for help command */
|
||||
|
||||
if (argc == 2 && strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
argndx = (type == GATT_DISCOVER) ? 4 : 3;
|
||||
if (argc < argndx)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Invalid number of arguments. "
|
||||
"Found %d expected at least %u\n",
|
||||
argc - 1, argndx - 1);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
btreq.btr_dtype = (uint8_t)type;
|
||||
|
||||
ret = btsak_str2addr(argv[1], btreq.btr_dpeer.val);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for <addr>: %s\n", argv[1]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addrtype(argv[2], &btreq.btr_dpeer.type);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for address type: %s\n", argv[2]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (type == GATT_DISCOVER)
|
||||
{
|
||||
btreq.btr_duuid16 = btsak_str2uint16(argv[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
btreq.btr_duuid16 = 0;
|
||||
}
|
||||
|
||||
btreq.btr_dstart = 0x0001;
|
||||
btreq.btr_dend = 0xffff;
|
||||
|
||||
if (argc > argndx)
|
||||
{
|
||||
btreq.btr_dstart = btsak_str2uint16(argv[argndx]);
|
||||
argndx++;
|
||||
|
||||
if (argc > argndx)
|
||||
{
|
||||
btreq.btr_dend = btsak_str2uint16(argv[argndx]);
|
||||
argndx++;
|
||||
}
|
||||
|
||||
if (btreq.btr_dstart > btreq.btr_dend)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid handle range: %u-%u\n",
|
||||
btreq.btr_dstart, btreq.btr_dend);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to start the discovery */
|
||||
|
||||
btreq.btr_gnrsp = CONFIG_BLUETOOTH_MAXDISCOVER;
|
||||
btreq.btr_grsp = result;
|
||||
btreq.btr_indx = 0;
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTDISCOVER,
|
||||
(unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTDISCOVER) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Show the results that we obtained */
|
||||
|
||||
printf("Discovered %d handles:\n", btreq.btr_gnrsp);
|
||||
for (i = 0; i < btreq.btr_gnrsp; i++)
|
||||
{
|
||||
rsp = &result[i];
|
||||
printf("%d.\thandle 0x%04x perm: %02x\n",
|
||||
i, rsp->dr_handle, rsp->dr_perm);
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_connect_common
|
||||
*
|
||||
* Description:
|
||||
* Function used by the connect and disconnect commands.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_cmd_connect_common(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[], int cmd)
|
||||
{
|
||||
static struct btreq_s btreq;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
if (argc == 2 && strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Invalid number of arguments. Found %d expected 2\n",
|
||||
argc - 1);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addr(argv[1], &btreq.btr_rmtpeer.val[0]);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for <addr>: %s\n", argv[1]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addrtype(argv[2], &btreq.btr_rmtpeer.type);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for address type: %s\n", argv[2]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to start/end the connection */
|
||||
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, cmd, (unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBT%sCONNECT) failed: %d\n",
|
||||
cmd == SIOCBTCONNECT ? "" : "DIS", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Connect pending...\n");
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_read_common
|
||||
*
|
||||
* Description:
|
||||
* Function used by the read and read_multiple commands.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_cmd_read_common(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[], bool multiple)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int ret;
|
||||
int sockfd;
|
||||
uint8_t data[HCI_GATTRD_DATA];
|
||||
struct btreq_s btreq;
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
|
||||
if (argc < 4 || argc > 5)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Invalid number of arguments. "
|
||||
"Found %d expected 3 or 4\n",
|
||||
argc - 1);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addr(argv[1], btreq.btr_rdpeer.val);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for <addr>: %s\n", argv[1]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addrtype(argv[2], &btreq.btr_rdpeer.type);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for address type: %s\n", argv[2]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
btreq.btr_rdoffset = 0;
|
||||
btreq.btr_rdnhandles = multiple ? argc - 3 : 1;
|
||||
|
||||
if (!multiple && argc > 4)
|
||||
{
|
||||
btreq.btr_rdoffset = btsak_str2uint16(argv[4]);
|
||||
}
|
||||
|
||||
for (i = 0; i < btreq.btr_rdnhandles; i++)
|
||||
{
|
||||
btreq.btr_rdhandles[i] = btsak_str2uint16(argv[i + 3]);
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to start the read */
|
||||
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
btreq.btr_rdsize = HCI_GATTRD_DATA;
|
||||
btreq.btr_rddata = data;
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTGATTRD, (unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTGATTRD) failed: %d\n", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Show the results that we obtained */
|
||||
|
||||
printf("Read %d bytes:\n", btreq.btr_rdsize);
|
||||
for (i = 0; i < btreq.btr_rdsize; i += 16)
|
||||
{
|
||||
for (j = 0; j < 16 && (i + j) < btreq.btr_rdsize; j++)
|
||||
{
|
||||
if (j == 8)
|
||||
{
|
||||
putchar(' ');
|
||||
}
|
||||
|
||||
printf(" %02x", data[i + j]);
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt_exchange_mtu
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] exchange_mtu [-h] <addr> public|private command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_gatt_exchange_mtu(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
if (argc == 2 && strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Invalid number of arguments. Found %d expected 2\n",
|
||||
argc - 1);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addr(argv[1], btreq.btr_expeer.val);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for <addr>: %s\n", argv[1]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addrtype(argv[2], &btreq.btr_expeer.type);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for address type: %s\n", argv[2]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to start the MTU exchange */
|
||||
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTEXCHANGE,
|
||||
(unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTEXCHANGE) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("MTU Exchange %s\n",
|
||||
btreq.btr_exresult == 0 ? "succeeded" : "failed");
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_discover
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] discover [-h] <addr> public|private <uuid16> command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_discover(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[])
|
||||
{
|
||||
btsak_cmd_discover_common(btsak, argc, argv, GATT_DISCOVER);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt_discover_characteristic
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] characteristic [-h] <addr> public|private command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_gatt_discover_characteristic(FAR struct btsak_s *btsak,
|
||||
int argc, FAR char *argv[])
|
||||
{
|
||||
btsak_cmd_discover_common(btsak, argc, argv, GATT_DISCOVER_CHAR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt_discover_descriptor
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] descriptor [-h] <addr> public|private command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_gatt_discover_descriptor(FAR struct btsak_s *btsak,
|
||||
int argc, FAR char *argv[])
|
||||
{
|
||||
btsak_cmd_discover_common(btsak, argc, argv, GATT_DISCOVER_DESC);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt_read
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] read [-h] <addr> public|private <handle> [<offset>] command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_gatt_read(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[])
|
||||
{
|
||||
if (argc == 2 && strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
btsak_cmd_read_common(btsak, argc, argv, false);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt_read_multiple
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] read-multiple [-h] <addr> public|private <handle>
|
||||
* [<handle> [<handle>]..]
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_gatt_read_multiple(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[])
|
||||
{
|
||||
if (argc == 2 && strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Invalid number of arguments. "
|
||||
"Found %d expected at least 3\n",
|
||||
argc - 1);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
btsak_cmd_read_common(btsak, argc, argv, true);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt_write
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] write [-h] [-h] <addr> public|private <handle> <byte>
|
||||
* [<byte> [<byte>]..]
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_gatt_write(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
int sockfd;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (argc == 2 && strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (argc < 5)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"ERROR: Invalid number of arguments. "
|
||||
"Found %d expected at least 4\n",
|
||||
argc - 1);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addr(argv[1], btreq.btr_wrpeer.val);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for <addr>: %s\n", argv[1]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = btsak_str2addrtype(argv[2], &btreq.btr_wrpeer.type);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Bad value for address type: %s\n", argv[2]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
btreq.btr_wrhandle = btsak_str2uint16(argv[3]);
|
||||
btreq.btr_wrnbytes = argc - 4;
|
||||
|
||||
if (btreq.btr_wrnbytes > HCI_GATTWR_DATA)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Too much data. Limit is %u bytes\n",
|
||||
HCI_GATTWR_DATA);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < btreq.btr_wrnbytes; i++)
|
||||
{
|
||||
btreq.btr_wrdata[i] = btsak_str2uint8(argv[i + 4]);
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to start the read */
|
||||
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTGATTWR, (unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTGATTWR) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Write %s\n",
|
||||
btreq.btr_wrresult == 0 ? "succeeded" : "failed");
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt_connect
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] connect [-h] <addr> public|private
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_connect(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[])
|
||||
{
|
||||
btsak_cmd_connect_common(btsak, argc, argv, SIOCBTCONNECT);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt_connect
|
||||
*
|
||||
* Description:
|
||||
* gatt [-h] disconnect [-h] <addr> public|private
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_disconnect(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[])
|
||||
{
|
||||
btsak_cmd_connect_common(btsak, argc, argv, SIOCBTDISCONNECT);
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/****************************************************************************
|
||||
* apps/wireless/bluetooth/btsak/btsak_info.c
|
||||
* Bluetooth Swiss Army Knife -- Info
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Based loosely on the i8sak IEEE 802.15.4 program by Anthony Merlino and
|
||||
* Sebastien Lorquet. Commands inspired for btshell example in the
|
||||
* Intel/Zephyr Arduino 101 package (BSD license).
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name NuttX 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 OWNER 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/wireless/bluetooth/bt_core.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_hci.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_ioctl.h>
|
||||
|
||||
#include "btsak.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_info_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show usage of the security command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_info_showusage(FAR const char *progname,
|
||||
FAR const char *cmd, int exitcode)
|
||||
{
|
||||
fprintf(stderr, "%s:\tShow Bluetooth device information\n", cmd);
|
||||
fprintf(stderr, "Usage:\n\n");
|
||||
fprintf(stderr, "\t%s <ifname> %s [-h]\n",
|
||||
progname, cmd);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_info
|
||||
*
|
||||
* Description:
|
||||
* security command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_info(FAR struct btsak_s *btsak, int argc, FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
/* Check for help */
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_info_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to stop advertising */
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCGBTINFO, (unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCGBTINFO) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Device: %s\n", btsak->ifname);
|
||||
printf("BDAddr: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
btreq.btr_bdaddr.val[5], btreq.btr_bdaddr.val[4],
|
||||
btreq.btr_bdaddr.val[3], btreq.btr_bdaddr.val[2],
|
||||
btreq.btr_bdaddr.val[1], btreq.btr_bdaddr.val[0]);
|
||||
printf("Flags: %04x\n", btreq.btr_flags);
|
||||
printf("Free: %u\n", btreq.btr_num_cmd);
|
||||
printf(" ACL: %u\n", btreq.btr_num_acl);
|
||||
printf(" SCO: %u\n", btreq.btr_num_sco);
|
||||
printf("Max:\n");
|
||||
printf(" ACL: %u\n", btreq.btr_max_acl);
|
||||
printf(" SCO: %u\n", btreq.btr_max_sco);
|
||||
printf("MTU:\n");
|
||||
printf(" ACL: %u\n", btreq.btr_acl_mtu);
|
||||
printf(" SCO: %u\n", btreq.btr_sco_mtu);
|
||||
printf("Policy: %u\n", btreq.btr_link_policy);
|
||||
printf("Type: %u\n", btreq.btr_packet_type);
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
@@ -0,0 +1,725 @@
|
||||
/****************************************************************************
|
||||
* apps/wireless/bluetooth/btsak/btsak_main.c
|
||||
* Bluetooth Swiss Army Knife
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Based loosely on the i8sak IEEE 802.15.4 program by Anthony Merlino and
|
||||
* Sebastien Lorquet. Commands inspired for btshell example in the
|
||||
* Intel/Zephyr Arduino 101 package (BSD license).
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name NuttX 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 OWNER 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/wireless/bluetooth/bt_core.h>
|
||||
#include <nuttx/net/bluetooth.h>
|
||||
|
||||
#include "btsak.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Describes one command */
|
||||
|
||||
struct btsak_command_s
|
||||
{
|
||||
FAR const char *name;
|
||||
CODE void (*handler)(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[]);
|
||||
FAR const char *help;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_help(FAR struct btsak_s *btsak, int argc, FAR char *argv[]);
|
||||
void btsak_cmd_gatt(FAR struct btsak_s *btsak, int argc, FAR char *argv[]);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Alphabetical, except for help */
|
||||
|
||||
static const struct btsak_command_s g_btsak_commands[] =
|
||||
{
|
||||
{
|
||||
"help",
|
||||
(CODE void *)btsak_cmd_help,
|
||||
NULL
|
||||
},
|
||||
{"info",
|
||||
(CODE void *)btsak_cmd_info,
|
||||
"[-h]"
|
||||
},
|
||||
{"features",
|
||||
(CODE void *)btsak_cmd_features,
|
||||
"[-h] [le]"
|
||||
},
|
||||
{"scan",
|
||||
(CODE void *)btsak_cmd_scan,
|
||||
"[-h] <start [-d]|get|stop>"
|
||||
},
|
||||
{
|
||||
"advertise",
|
||||
(CODE void *)btsak_cmd_advertise,
|
||||
"[-h] <start|stop>"
|
||||
},
|
||||
{
|
||||
"security",
|
||||
(CODE void *)btsak_cmd_security,
|
||||
"[-h] <addr> public|private <level>"
|
||||
},
|
||||
{
|
||||
"gatt",
|
||||
(CODE void *)btsak_cmd_gatt,
|
||||
"[-h] <cmd> [option [option [option...]]]"
|
||||
}
|
||||
};
|
||||
|
||||
#define NCOMMANDS (sizeof(g_btsak_commands) / sizeof(struct btsak_command_s))
|
||||
|
||||
static const struct btsak_command_s g_btsak_gatt_commands[] =
|
||||
{
|
||||
{"exchange-mtu",
|
||||
(CODE void *)btsak_cmd_gatt_exchange_mtu,
|
||||
"[-h] <addr> public|private"
|
||||
},
|
||||
{
|
||||
"connect",
|
||||
(CODE void *)btsak_cmd_connect,
|
||||
"[-h] <addr> public|private"
|
||||
},
|
||||
{
|
||||
"disconnect",
|
||||
(CODE void *)btsak_cmd_disconnect,
|
||||
"[-h] <addr> public|private"
|
||||
},
|
||||
{
|
||||
"discover",
|
||||
(CODE void *)btsak_cmd_discover,
|
||||
"[-h] <addr> public|private <uuid16> [<start> [<end>]]"
|
||||
},
|
||||
{
|
||||
"characteristic",
|
||||
(CODE void *)btsak_cmd_gatt_discover_characteristic,
|
||||
"[-h] <addr> public|private [<start> [<end>]]"
|
||||
},
|
||||
{
|
||||
"descriptor",
|
||||
(CODE void *)btsak_cmd_gatt_discover_descriptor,
|
||||
"[-h] <addr> public|private [<start> [<end>]]"
|
||||
},
|
||||
{
|
||||
"read",
|
||||
(CODE void *)btsak_cmd_gatt_read,
|
||||
"[-h] <addr> public|private <handle> [<offset>]"
|
||||
},
|
||||
{
|
||||
"read-multiple",
|
||||
(CODE void *)btsak_cmd_gatt_read_multiple,
|
||||
"[-h] <addr> public|private <handle> [<handle> [<handle>]..]"
|
||||
},
|
||||
{
|
||||
"write",
|
||||
(CODE void *)btsak_cmd_gatt_write,
|
||||
"[-h] <addr> public|private <handle> <byte> [<byte> [<byte>]..]"
|
||||
}
|
||||
};
|
||||
|
||||
#define GATT_NCOMMANDS (sizeof(g_btsak_gatt_commands) / sizeof(struct btsak_command_s))
|
||||
|
||||
static const bt_addr_t g_default_epaddr =
|
||||
{
|
||||
BTSAK_DEFAULT_EPADDR
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_help
|
||||
*
|
||||
* Description:
|
||||
* Handle help command.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_help(FAR struct btsak_s *btsak, int argc, FAR char *argv[])
|
||||
{
|
||||
btsak_showusage(btsak->progname, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_gatt
|
||||
*
|
||||
* Description:
|
||||
* Handle gatt command.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_gatt(FAR struct btsak_s *btsak, int argc, FAR char *argv[])
|
||||
{
|
||||
FAR const struct btsak_command_s *cmd;
|
||||
int argind;
|
||||
int i;
|
||||
|
||||
/* Verify that a command was provided */
|
||||
|
||||
argind = 1;
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing gatt command\n");
|
||||
btsak_showusage(btsak->progname, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Check for help */
|
||||
|
||||
if (strcmp(argv[argind], "-h") == 0)
|
||||
{
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Find the command in the g_btsak_gatt_commands[] list */
|
||||
|
||||
cmd = NULL;
|
||||
for (i = 0; i < GATT_NCOMMANDS; i++)
|
||||
{
|
||||
FAR const struct btsak_command_s *gattcmd = &g_btsak_gatt_commands[i];
|
||||
if (strcmp(argv[argind], gattcmd->name) == 0)
|
||||
{
|
||||
cmd = gattcmd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unrecognized gatt command: %s\n",
|
||||
argv[argind]);
|
||||
btsak_gatt_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
cmd->handler(btsak, argc - argind, &argv[argind]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* bt_main
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR const struct btsak_command_s *cmd;
|
||||
struct btsak_s btsak;
|
||||
int argind;
|
||||
int i;
|
||||
|
||||
/* Initialize the default remote endpoint address */
|
||||
|
||||
memset(&btsak, 0, sizeof(struct btsak_s));
|
||||
BLUETOOTH_ADDRCOPY(btsak.ep_btaddr.val, g_default_epaddr.val);
|
||||
btsak.progname = argv[0];
|
||||
|
||||
/* Check if ifname was included */
|
||||
|
||||
argind = 1;
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing interface name\n");
|
||||
btsak_showusage(btsak.progname, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
btsak.ifname = argv[argind];
|
||||
argind++;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing command\n");
|
||||
btsak_showusage(btsak.progname, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Find the command in the g_btsak_command[] list */
|
||||
|
||||
cmd = NULL;
|
||||
for (i = 0; i < NCOMMANDS; i++)
|
||||
{
|
||||
FAR const struct btsak_command_s *btcmd = &g_btsak_commands[i];
|
||||
if (strcmp(argv[argind], btcmd->name) == 0)
|
||||
{
|
||||
cmd = btcmd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == NULL)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unrecognized command: %s\n", argv[argind]);
|
||||
btsak_showusage(btsak.progname, EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cmd->handler(&btsak, argc - argind, &argv[argind]);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_char2nibble
|
||||
*
|
||||
* Description:
|
||||
* Convert an hexadecimal character to a 4-bit nibble.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_char2nibble(char ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
{
|
||||
return ch - '0';
|
||||
}
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
{
|
||||
return ch - 'a' + 10;
|
||||
}
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
{
|
||||
return ch - 'A' + 10;
|
||||
}
|
||||
else if (ch == '\0')
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unexpected NUL terminator in hex string\n");
|
||||
return -EPIPE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unexpected end character in hex string\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2long
|
||||
*
|
||||
* Description:
|
||||
* Convert a numeric string to a long value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long btsak_str2long(FAR const char *str)
|
||||
{
|
||||
FAR char *endptr;
|
||||
long value;
|
||||
|
||||
value = strtol(str, &endptr, 0);
|
||||
if (endptr == NULL || *endptr != '\0')
|
||||
{
|
||||
fprintf(stderr, "ERROR: Garbage after numeric argument\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2int
|
||||
*
|
||||
* Description:
|
||||
* Convert a numeric string to an integer value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
long btsak_str2int(FAR const char *str)
|
||||
{
|
||||
long value = btsak_str2long(str);
|
||||
if (value > INT_MAX || value < INT_MIN)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Integer value out of range\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return (int)value;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2uint8
|
||||
*
|
||||
* Description:
|
||||
* Convert a numeric string to an uint8_t value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint8_t btsak_str2uint8(FAR const char *str)
|
||||
{
|
||||
long value = btsak_str2long(str);
|
||||
if (value < 0 || value > UINT8_MAX)
|
||||
{
|
||||
fprintf(stderr, "ERROR: 8-bit value out of range\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return (uint8_t)value;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2uint16
|
||||
*
|
||||
* Description:
|
||||
* Convert a numeric string to an uint16_t value
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
uint16_t btsak_str2uint16(FAR const char *str)
|
||||
{
|
||||
long value = btsak_str2long(str);
|
||||
if (value < 0 || value > UINT16_MAX)
|
||||
{
|
||||
fprintf(stderr, "ERROR: 16-bit value out of range\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return (uint16_t)value;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2bool
|
||||
*
|
||||
* Description:
|
||||
* Convert a boolean name to a boolean value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool btsak_str2bool(FAR const char *str)
|
||||
{
|
||||
if (strcasecmp(str, "true") == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (strcasecmp(str, "false") == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid boolean name: %s\n", str);
|
||||
fprintf(stderr, " Expected true or false\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name : btsak_str2payload
|
||||
*
|
||||
* Description :
|
||||
* Parse string to get buffer of data. Buf is expected to be of size
|
||||
* BLUETOOTH_SMP_MTU or larger.
|
||||
*
|
||||
* Returns:
|
||||
* Positive length value of frame payload
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_str2payload(FAR const char *str, FAR uint8_t *buf)
|
||||
{
|
||||
int str_len;
|
||||
int ret;
|
||||
int i = 0;
|
||||
|
||||
str_len = strlen(str);
|
||||
|
||||
/* Each byte is represented by 2 chars */
|
||||
|
||||
ret = str_len >> 1;
|
||||
|
||||
/* Check if the number of chars is a multiple of 2 and that the number of
|
||||
* bytes does not exceed the max MAC frame payload supported.
|
||||
*/
|
||||
|
||||
if ((str_len & 1) || (ret > BLUETOOTH_SMP_MTU))
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid payload\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Decode hex packet */
|
||||
|
||||
while (str_len > 0)
|
||||
{
|
||||
int dat;
|
||||
if (sscanf(str, "%2x", &dat) == 1)
|
||||
{
|
||||
buf[i++] = dat;
|
||||
str += 2;
|
||||
str_len -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid payload\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2addr
|
||||
*
|
||||
* Description:
|
||||
* Convert a string of the form "xx:xx:xx:xx:xx:xx" 6-byte Bluetooth
|
||||
* address (where xx is a one or two character hexadecimal number sub-
|
||||
* string)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_str2addr(FAR const char *str, FAR uint8_t *addr)
|
||||
{
|
||||
FAR const char *src = str;
|
||||
int nibble;
|
||||
uint8_t hex;
|
||||
char ch;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
ch = (char)*src++;
|
||||
nibble = btsak_char2nibble(ch);
|
||||
if (nibble < 0)
|
||||
{
|
||||
return nibble;
|
||||
}
|
||||
|
||||
hex = (uint8_t)nibble << 4;
|
||||
|
||||
ch = (char)*src++;
|
||||
nibble = btsak_char2nibble(ch);
|
||||
if (nibble < 0)
|
||||
{
|
||||
return nibble;
|
||||
}
|
||||
|
||||
hex |= (uint8_t)nibble;
|
||||
addr[5 - i] = hex;
|
||||
|
||||
if (i < 5)
|
||||
{
|
||||
ch = (char)*src++;
|
||||
if (ch != ':')
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2addrtype
|
||||
*
|
||||
* Description:
|
||||
* Convert a string to an address type. String options are "public" or
|
||||
* "private".
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_str2addrtype(FAR const char *str, FAR uint8_t *addrtype)
|
||||
{
|
||||
if (!strcasecmp(str, "public"))
|
||||
{
|
||||
*addrtype = BT_ADDR_LE_PUBLIC;
|
||||
}
|
||||
else if (!strcasecmp(str, "random"))
|
||||
{
|
||||
*addrtype = BT_ADDR_LE_RANDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_str2seclevel
|
||||
*
|
||||
* Description:
|
||||
* Convert a string to a security level. String options are "low",
|
||||
* "medium", "high", or "fips"
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_str2seclevel(FAR const char *str, FAR enum bt_security_e *level)
|
||||
{
|
||||
if (!strcasecmp(str, "low"))
|
||||
{
|
||||
*level = BT_SECURITY_LOW;
|
||||
}
|
||||
else if (!strcasecmp(str, "medium"))
|
||||
{
|
||||
*level = BT_SECURITY_MEDIUM;
|
||||
}
|
||||
else if (!strcasecmp(str, "high"))
|
||||
{
|
||||
*level = BT_SECURITY_HIGH;
|
||||
}
|
||||
else if (!strcasecmp(str, "fips"))
|
||||
{
|
||||
*level = BT_SECURITY_FIPS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_socket
|
||||
*
|
||||
* Description:
|
||||
* Create a socket on the selected device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int btsak_socket(FAR struct btsak_s *btsak)
|
||||
{
|
||||
int sockfd = -1;
|
||||
|
||||
/* Create the socket with the correct addressing */
|
||||
|
||||
BLUETOOTH_ADDRCOPY(btsak->ep_btaddr.val, g_default_epaddr.val);
|
||||
|
||||
#if defined(CONFIG_NET_BLUETOOTH)
|
||||
btsak->ep_sockaddr.l2_family = AF_BLUETOOTH;
|
||||
btsak->ep_sockaddr.l2_cid = 0; /* REVISIT */
|
||||
BLUETOOTH_ADDRCOPY(btsak->ep_sockaddr.l2_bdaddr.val, btsak->ep_btaddr.val);
|
||||
|
||||
sockfd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
|
||||
|
||||
#elif defined(CONFIG_NET_6LOWPAN)
|
||||
btsak->ep_sockaddr.sin6_family = AF_INET6;
|
||||
btsak->ep_sockaddr.sin6_port = HTONS(CONFIG_BTSAK_DEFAULT_PORT);
|
||||
btsak_update_ipv6addr(btsak);
|
||||
|
||||
sockfd = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
|
||||
#endif
|
||||
|
||||
if (sockfd < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: failed to create socket, errno=%d\n", errno);
|
||||
}
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show program usage.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_showusage(FAR const char *progname, int exitcode)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "\nUsage:\n\n");
|
||||
fprintf(stderr, "\t%s <ifname> <cmd> [option [option [option...]]]\n",
|
||||
progname);
|
||||
fprintf(stderr,
|
||||
"\nWhere <cmd> [option [option [option...]]] is one of:\n\n");
|
||||
|
||||
for (i = 0; i < NCOMMANDS; i++)
|
||||
{
|
||||
FAR const struct btsak_command_s *cmd = &g_btsak_commands[i];
|
||||
if (cmd->help != NULL)
|
||||
{
|
||||
fprintf(stderr, "\t%-10s\t%s\n", cmd->name, cmd->help);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "\t%s\n", cmd->name);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nUse the -h option on any command to get more info.\n");
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_gatt_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show gatt command usage.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_gatt_showusage(FAR const char *progname, FAR const char *cmd,
|
||||
int exitcode)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "%s: Generic Attribute (GATT) commands:\n", cmd);
|
||||
fprintf(stderr, "Usage:\n\n");
|
||||
fprintf(stderr,
|
||||
"\t%s <ifname> %s [-h] <cmd> [option [option [option...]]]\n",
|
||||
progname, cmd);
|
||||
fprintf(stderr,
|
||||
"\nWhere <cmd> [option [option [option...]]] is one of:\n\n");
|
||||
|
||||
for (i = 0; i < GATT_NCOMMANDS; i++)
|
||||
{
|
||||
FAR const struct btsak_command_s *gattcmd = &g_btsak_gatt_commands[i];
|
||||
if (gattcmd->help != NULL)
|
||||
{
|
||||
fprintf(stderr, "\t%-10s\t%s\n", gattcmd->name, gattcmd->help);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "\t%s\n", gattcmd->name);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nUse the -h option on any command to get more info.\n");
|
||||
exit(exitcode);
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
/****************************************************************************
|
||||
* apps/wireless/bluetooth/btsak/btsak_scan.c
|
||||
* Bluetooth Swiss Army Knife -- Scan command
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Based loosely on the i8sak IEEE 802.15.4 program by Anthony Merlino and
|
||||
* Sebastien Lorquet. Commands inspired for btshell example in the
|
||||
* Intel/Zephyr Arduino 101 package (BSD license).
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name NuttX 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 OWNER 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/wireless/bluetooth/bt_ioctl.h>
|
||||
|
||||
#include "btsak.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_scan_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show usage of the scan command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_scan_showusage(FAR const char *progname,
|
||||
FAR const char *cmd, int exitcode)
|
||||
{
|
||||
fprintf(stderr, "%s: Scan commands:\n", cmd);
|
||||
fprintf(stderr, "Usage:\n\n");
|
||||
fprintf(stderr, "\t%s <ifname> %s [-h] <start [-d]|get|stop>\n",
|
||||
progname, cmd);
|
||||
fprintf(stderr, "\nWhere the options do the following:\n\n");
|
||||
fprintf(stderr, "\tstart\t- Starts scanning. The -d option enables duplicate\n");
|
||||
fprintf(stderr, "\t\t filtering.\n");
|
||||
fprintf(stderr, "\tget\t- Shows new accumulated scan results\n");
|
||||
fprintf(stderr, "\tstop\t- Stops scanning\n");
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_scanstart
|
||||
*
|
||||
* Description:
|
||||
* Scan start command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_cmd_scanstart(FAR struct btsak_s *btsak, FAR char *cmd,
|
||||
int argc, FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
int argind;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
/* Check if an option was provided */
|
||||
|
||||
argind = 1;
|
||||
btreq.btr_dupenable = false;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
if (strcmp(argv[argind], "-d") == 0)
|
||||
{
|
||||
btreq.btr_dupenable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unrecognized option: %s\n",
|
||||
argv[argind]);
|
||||
btsak_scan_showusage(btsak->progname, cmd, EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform the IOCTL to start scanning */
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTSCANSTART,
|
||||
(unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTSCANSTART) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_scanget
|
||||
*
|
||||
* Description:
|
||||
* Scan get command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_cmd_scanget(FAR struct btsak_s *btsak, FAR char *cmd,
|
||||
int argc, FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
struct bt_scanresponse_s result[5];
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
/* Perform the IOCTL to get the scan results so far */
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
btreq.btr_nrsp = 5;
|
||||
btreq.btr_rsp = result;
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTSCANGET,
|
||||
(unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTSCANGET) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
|
||||
/* Show scan results */
|
||||
|
||||
else
|
||||
{
|
||||
FAR struct bt_scanresponse_s *rsp;
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
|
||||
printf("Scan result:\n");
|
||||
for (i = 0; i < btreq.btr_nrsp; i++)
|
||||
{
|
||||
rsp = &result[i];
|
||||
printf("%2d.\taddr: "
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x type: %d\n",
|
||||
i + 1,
|
||||
rsp->sr_addr.val[5], rsp->sr_addr.val[4],
|
||||
rsp->sr_addr.val[3], rsp->sr_addr.val[2],
|
||||
rsp->sr_addr.val[1], rsp->sr_addr.val[0],
|
||||
rsp->sr_addr.type);
|
||||
printf("\trssi: %d\n", rsp->sr_rssi);
|
||||
printf("\tresponse type: %u\n", rsp->sr_type);
|
||||
printf("\tadvertiser data:");
|
||||
|
||||
for (j = 0; j < rsp->sr_len; j += 16)
|
||||
{
|
||||
if (j > 0)
|
||||
{
|
||||
printf("\t ");
|
||||
}
|
||||
|
||||
for (k = 0; k < 16 && (j + k) < rsp->sr_len; k++)
|
||||
{
|
||||
printf(" %02x", rsp->sr_data[j + k]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_scanstop
|
||||
*
|
||||
* Description:
|
||||
* Scan stop command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_cmd_scanstop(FAR struct btsak_s *btsak, FAR char *cmd,
|
||||
int argc, FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
/* Perform the IOCTL to stop scanning and flush any buffered responses. */
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTSCANSTOP,
|
||||
(unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTSCANSTOP) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_scan
|
||||
*
|
||||
* Description:
|
||||
* scan [-h] <start [-d] |get|stop> command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_scan(FAR struct btsak_s *btsak, int argc, FAR char *argv[])
|
||||
{
|
||||
int argind;
|
||||
|
||||
/* Verify that an option was provided */
|
||||
|
||||
argind = 1;
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing scan command\n");
|
||||
btsak_scan_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Check for command */
|
||||
|
||||
if (strcmp(argv[argind], "-h") == 0)
|
||||
{
|
||||
btsak_scan_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
else if (strcmp(argv[argind], "start") == 0)
|
||||
{
|
||||
btsak_cmd_scanstart(btsak, argv[0], argc - argind, &argv[argind]);
|
||||
}
|
||||
else if (strcmp(argv[argind], "get") == 0)
|
||||
{
|
||||
btsak_cmd_scanget(btsak, argv[0], argc - argind, &argv[argind]);
|
||||
}
|
||||
else if (strcmp(argv[argind], "stop") == 0)
|
||||
{
|
||||
btsak_cmd_scanstop(btsak, argv[0], argc - argind, &argv[argind]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "ERROR: Unrecognized scan command: %s\n", argv[argind]);
|
||||
btsak_scan_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
/****************************************************************************
|
||||
* apps/wireless/bluetooth/btsak/btsak_security.c
|
||||
* Bluetooth Swiss Army Knife -- Security command
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Based loosely on the i8sak IEEE 802.15.4 program by Anthony Merlino and
|
||||
* Sebastien Lorquet. Commands inspired from btshell example in the
|
||||
* Intel/Zephyr Arduino 101 package (BSD license).
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <nuttx/wireless/bluetooth/bt_core.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_hci.h>
|
||||
#include <nuttx/wireless/bluetooth/bt_ioctl.h>
|
||||
|
||||
#include "btsak.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_security_showusage
|
||||
*
|
||||
* Description:
|
||||
* Show usage of the security command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void btsak_security_showusage(FAR const char *progname,
|
||||
FAR const char *cmd, int exitcode)
|
||||
{
|
||||
fprintf(stderr, "%s:\tEnable security (encryption) for a connection:\n",
|
||||
cmd);
|
||||
fprintf(stderr,
|
||||
"\tIf device is paired, key encryption will be enabled. If the "
|
||||
"link\n");
|
||||
fprintf(stderr,
|
||||
"\tis already encrypted with sufficiently strong key this "
|
||||
"function\n");
|
||||
fprintf(stderr,
|
||||
"\tdoes nothing.\n\n");
|
||||
fprintf(stderr,
|
||||
"\tIf the device is not paired pairing will be initiated. If the "
|
||||
"device\n");
|
||||
fprintf(stderr,
|
||||
"\tis paired and keys are too weak but input output capabilities "
|
||||
"allow\n");
|
||||
fprintf(stderr,
|
||||
"\tfor strong enough keys pairing will be initiated.\n\n");
|
||||
fprintf(stderr,
|
||||
"\tThis function may return error if required level of security "
|
||||
"is not\n");
|
||||
fprintf(stderr,
|
||||
"\tpossible to achieve due to local or remote device limitation "
|
||||
"(eg input\n");
|
||||
fprintf(stderr,
|
||||
"\toutput capabilities).\n\n");
|
||||
fprintf(stderr, "Usage:\n\n");
|
||||
fprintf(stderr, "\t%s <ifname> %s [-h] <addr> public|private <level>\n",
|
||||
progname, cmd);
|
||||
fprintf(stderr,
|
||||
"\nWhere:\n\n");
|
||||
fprintf(stderr,
|
||||
"\t<addr>\t- The 6-byte address of the connected peer\n");
|
||||
fprintf(stderr,
|
||||
"\t<level>\t- Security level, on of:\n\n");
|
||||
fprintf(stderr,
|
||||
"\t\tlow\t- No encryption and no authentication\n");
|
||||
fprintf(stderr,
|
||||
"\t\tmedium\t- Encryption and no authentication (no MITM)\n");
|
||||
fprintf(stderr,
|
||||
"\t\thigh\t- Encryption and authentication (MITM)\n");
|
||||
fprintf(stderr,
|
||||
"\t\tfips\t- Authenticated LE secure connections and "
|
||||
"encryption\n");
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: btsak_cmd_security
|
||||
*
|
||||
* Description:
|
||||
* security [-h] <start [-d] |get|stop> command
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void btsak_cmd_security(FAR struct btsak_s *btsak, int argc,
|
||||
FAR char *argv[])
|
||||
{
|
||||
struct btreq_s btreq;
|
||||
int sockfd;
|
||||
int ret;
|
||||
|
||||
/* Check for help */
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing required arguments\n");
|
||||
btsak_security_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "-h") == 0)
|
||||
{
|
||||
btsak_security_showusage(btsak->progname, argv[0], EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Verify that all required arguments were provided */
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Missing required arguments\n");
|
||||
btsak_security_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* The first argument must be an address of the form xx:xx:xx:xx:xx:xx */
|
||||
|
||||
memset(&btreq, 0, sizeof(struct btreq_s));
|
||||
strncpy(btreq.btr_name, btsak->ifname, IFNAMSIZ);
|
||||
|
||||
ret = btsak_str2addr(argv[1], btreq.btr_secaddr.val);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid address string: %s\n", argv[1]);
|
||||
btsak_security_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* The second address is the address type, either "public" or "random" */
|
||||
|
||||
ret = btsak_str2addrtype(argv[2], &btreq.btr_secaddr.type);
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Invalid address type: %s\n", argv[2]);
|
||||
btsak_security_showusage(btsak->progname, argv[0], EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* The third argument is the security level */
|
||||
|
||||
ret = btsak_str2seclevel(argv[3], &btreq.btr_seclevel);
|
||||
|
||||
/* Perform the IOCTL to stop advertising */
|
||||
|
||||
sockfd = btsak_socket(btsak);
|
||||
if (sockfd >= 0)
|
||||
{
|
||||
ret = ioctl(sockfd, SIOCBTSECURITY,
|
||||
(unsigned long)((uintptr_t)&btreq));
|
||||
if (ret < 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: ioctl(SIOCBTSECURITY) failed: %d\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
config NIMBLE
|
||||
bool "Apache nimBLE (BLE host-layer)"
|
||||
default n
|
||||
depends on !WIRELESS_BLUETOOTH_HOST
|
||||
---help---
|
||||
Enable Apache nimBLE Bluetooth Low Energy
|
||||
host-layer stack.
|
||||
|
||||
if NIMBLE
|
||||
config NIMBLE_REF
|
||||
string "Version"
|
||||
default "7b5b5e5b512133e50ef8a517b13e7269f9c821fd"
|
||||
---help---
|
||||
Git ref name to use when downloading from nimBLE repo
|
||||
endif
|
||||
@@ -0,0 +1,23 @@
|
||||
############################################################################
|
||||
# apps/wireless/bluetooth/nimble/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_NIMBLE),)
|
||||
CONFIGURED_APPS += $(APPDIR)/wireless/bluetooth/nimble
|
||||
endif
|
||||
@@ -0,0 +1,53 @@
|
||||
############################################################################
|
||||
# apps/wireless/bluetooth/nimble/Makefile
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
PRIORITY = 255
|
||||
STACKSIZE = 16384
|
||||
|
||||
NIMBLE_UNPACKDIR = mynewt-nimble
|
||||
NIMBLE_ROOT = $(APPDIR)/wireless/bluetooth/nimble/$(NIMBLE_UNPACKDIR)
|
||||
|
||||
-include $(NIMBLE_ROOT)/porting/examples/nuttx/Make.defs
|
||||
|
||||
CONFIG_NIMBLE_REF := $(patsubst "%",%,$(strip $(CONFIG_NIMBLE_REF)))
|
||||
NIMBLE_TAR := $(CONFIG_NIMBLE_REF).tar.gz
|
||||
NIMBLE_URL := https://github.com/apache/mynewt-nimble/archive/$(NIMBLE_TAR)
|
||||
|
||||
$(NIMBLE_TAR):
|
||||
$(Q) curl -L $(NIMBLE_URL) -o $(NIMBLE_TAR)
|
||||
|
||||
$(NIMBLE_UNPACKDIR): $(NIMBLE_TAR)
|
||||
$(Q) tar zxf $(NIMBLE_TAR)
|
||||
$(Q) mv mynewt-nimble-$(CONFIG_NIMBLE_REF) $(NIMBLE_UNPACKDIR)
|
||||
$(Q) touch $(NIMBLE_UNPACKDIR)
|
||||
|
||||
context:: $(NIMBLE_UNPACKDIR)
|
||||
|
||||
distclean::
|
||||
$(call DELFILE,$(NIMBLE_TAR))
|
||||
$(call DELDIR,$(NIMBLE_UNPACKDIR))
|
||||
|
||||
# nimBLE assumes this flag since it expects undefined macros to be zero value
|
||||
|
||||
CFLAGS += -Wno-undef
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
@@ -0,0 +1,75 @@
|
||||
# nimBLE for NuttX
|
||||
|
||||
This application will build nimBLE stack (host-only) as a library/application
|
||||
in NuttX.
|
||||
|
||||
# Porting Layer
|
||||
|
||||
nimBLE supports being built as part of different OS, not only their mynewt
|
||||
RTOS. A porting layer was written for NuttX, which was mostly a copy of
|
||||
the Linux porting layer.
|
||||
|
||||
## Modifying the porting layer
|
||||
|
||||
NuttX is supported in nimBLE by adding an entry in the porting layer
|
||||
used to support different OSs. However, nimBLE supports each OS
|
||||
by generating a configuration header (`syscfg.h`) from YAML configuration
|
||||
files. If you want to modify the porting layer and change its configuration
|
||||
you will need to regenerate this header. This process is a bit involved since
|
||||
nimBLE uses its own `newt` build tool to do so and also somewhat assumes it will
|
||||
be built for their mynewt OS, so it actually may fail to build completely but
|
||||
it will still get to generate the required files.
|
||||
|
||||
So, first is to get the newt tool:
|
||||
|
||||
$ cd apps/nimble
|
||||
$ git clone https://github.com/apache/mynewt-newt
|
||||
$ cd mynewt-newt
|
||||
|
||||
At the moment, you will probably require unstable version
|
||||
instead of a release so select a known working:
|
||||
|
||||
$ git checkout c14c47bb683d
|
||||
$ ./build.sh
|
||||
|
||||
There should be now a `newt` binary under `mynewt-newt/newt`.
|
||||
Extend your path so that it is visible:
|
||||
|
||||
$ export PATH=mynewt-newt/newt:$PATH
|
||||
|
||||
Now, create a `newt` project:
|
||||
|
||||
$ newt new foo
|
||||
|
||||
We want latest master version of mynewt OS and stack, so edit
|
||||
`foo/project.yml` and change the `vers` variable to `0.0.0`. Now
|
||||
do
|
||||
|
||||
$ cd foo/
|
||||
$ newt upgrade
|
||||
|
||||
Under `foo/repos` there will be a clone of both mynewt and nimble
|
||||
repo. Since this app already downloads nimble repo outside of `foo`,
|
||||
you can delete `foo/repos/apache-mynewt-nimble` and simply make a
|
||||
link to the `mynewt-nimble` directory, so that you can work on the
|
||||
nimBLE code directly.
|
||||
|
||||
Now you can make any changes to the `yml` files such as
|
||||
`porting/targets/nuttx/syscfg.yml`. Finally, you can build with:
|
||||
|
||||
$ newt build @apache-mynewt-nimble/porting/targets/nuttx
|
||||
|
||||
This will most likely fail to complete but the generated headers
|
||||
should be there. So now copy them to the appropriate location in
|
||||
the `nuttx` target directory:
|
||||
|
||||
$ cd foo/
|
||||
$ cp bin/@apache-mynewt-nimble/porting/targets/nuttx/generated/include/logcfg/logcfg.h \
|
||||
repos/apache-mynewt-nimble/porting/examples/nuttx/include/logcfg
|
||||
$ cp bin/@apache-mynewt-nimble/porting/targets/nuttx/generated/include/syscfg/syscfg.h \
|
||||
repos/apache-mynewt-nimble/porting/examples/nuttx/include/syscfg
|
||||
|
||||
If these changes are done to fix a problem with NuttX porting layer in nimBLE, you
|
||||
should open a pull-request to nimBLE repository to include the updated header files.
|
||||
It is recommended to mention the issue in NuttX mailing list first to ensure the change
|
||||
is needed.
|
||||
Reference in New Issue
Block a user