Add nuttx to the system framework, which is 10.1.0

This commit is contained in:
TangYiwen123
2021-06-09 14:33:15 +08:00
parent 06c351e27c
commit 804bd57aa0
5000 changed files with 1488544 additions and 0 deletions
@@ -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.