Skip to content

Commit

Permalink
SIM: Add support Linux HCI Socket as BLE adaptor
Browse files Browse the repository at this point in the history
Signed-off-by: Brennan Ashton <[email protected]>
  • Loading branch information
btashton committed Aug 27, 2020
1 parent 4076674 commit 333efb0
Show file tree
Hide file tree
Showing 10 changed files with 576 additions and 0 deletions.
10 changes: 10 additions & 0 deletions arch/sim/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -475,4 +475,14 @@ config SIM_QSPIFLASH_PAGESIZE
"wrap" causing the initial data sent to be overwritten.
This is consistent with standard SPI FLASH operation.

config SIM_HCISOCKET
bool "Attach Host Bluetooth"
default false
depends on (WIRELESS_BLUETOOTH && HOST_LINUX)
---help---
Attached the local bluetooth device to the simulation
target via HCI_CHANNEL_USER. This gives NuttX full
control of the device, but is abstracted from the
physical interface which is still handled by Linux.

endif # ARCH_SIM
5 changes: 5 additions & 0 deletions arch/sim/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ else ifeq ($(CONFIG_SIM_NETDEV_VPNKIT),y)
HOSTSRCS += protocol.c negotiate.c
endif

ifeq ($(CONFIG_SIM_HCISOCKET),y)
HOSTSRCS += up_hcisocket_host.c
CSRCS += up_hcisocket.c
endif

ifeq ($(CONFIG_RPTUN),y)
CSRCS += up_rptun.c
endif
Expand Down
235 changes: 235 additions & 0 deletions arch/sim/src/sim/up_hcisocket.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
/****************************************************************************
* arch/sim/src/sim/up_hcisocket.c
*
* 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.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <sys/types.h>

#include <sys/socket.h>

#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <nuttx/wireless/bluetooth/bt_driver.h>
#include <nuttx/net/bluetooth.h>

#include "up_internal.h"
#include "up_hcisocket_host.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/* HCI data types as defined by Linux Kernel */

#define HCI_COMMAND_PKT 0x01
#define HCI_ACLDATA_PKT 0x02
#define HCI_SCODATA_PKT 0x03
#define HCI_EVENT_PKT 0x04
#define HCI_ISODATA_PKT 0x05
#define HCI_DIAG_PKT 0xf0
#define HCI_VENDOR_PKT 0xff

/****************************************************************************
* Private Types
****************************************************************************/

/****************************************************************************
* Private Function Prototypes
****************************************************************************/

static int bthcisock_send(FAR const struct bt_driver_s *dev,
FAR struct bt_buf_s *buf);
static int bthcisock_open(FAR const struct bt_driver_s *dev);

/****************************************************************************
* Private Data
****************************************************************************/

static const struct bt_driver_s g_bt_hcisock =
{
0, /* head_reserve */
bthcisock_open, /* open */
bthcisock_send /* send */
};

static int bt_fd = -1; /* Host HCI socket fd */
static int host_dev_id = 0; /* Host HCI interface number */

/* This frame buffer is used to handle the frame read from the host
* NOTE: This is smaller than what the Linux kernel lists as its max frame
* so we will need to resolve that at some point.
*/

static uint8_t bt_frame[BLUETOOTH_MAX_FRAMELEN + 1];

/****************************************************************************
* Private Functions
****************************************************************************/

static int bthcisock_send(FAR const struct bt_driver_s *dev,
FAR struct bt_buf_s *buf)
{
uint8_t pkt_type;

switch (buf->type)
{
case BT_CMD:
{
pkt_type = HCI_COMMAND_PKT;
break;
}

case BT_ACL_OUT:
{
pkt_type = HCI_ACLDATA_PKT;
break;
}

default:
{
wlerr("Unexpected HCI packet type %d", buf->type);
return buf->len;
}
}

if (bthcisock_host_send(bt_fd, pkt_type, buf->data, buf->len) < 0)
{
return -1;
}

bthcisock_read();

return buf->len;
}

static int bthcisock_open(FAR const struct bt_driver_s *dev)
{
int fd = bthcisock_host_open(host_dev_id);
if (fd < 0)
{
return -1;
}

bt_fd = fd;
return OK;
}

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: bthcisock_register
*
* Description:
* Register the Linux HCI interface with the Bluetooth stack
*
* Input Parameters:
* dev_id: This is the interface number known to the Linux Kernel
*
* Returned Value:
* Zero is returned on success; a negated errno value is returned on any
* failure.
*
****************************************************************************/

int bthcisock_register(int dev_id)
{
/* Register the driver with the Bluetooth stack */

host_dev_id = dev_id;
return bt_netdev_register(&g_bt_hcisock);
}

/****************************************************************************
* Name: bthcisock_read
*
* Description:
* Register the Linux HCI interface with the Bluetooth stack
*
* Input Parameters:
* None
*
* Returned Value:
* Zero is returned on success; a negated errno value is returned on any
* failure.
*
****************************************************************************/

int bthcisock_read()
{
struct bt_buf_s *outbuf;
enum bt_buf_type_e buf_type;
uint8_t type;
size_t len;

if (bt_fd < 0)
{
/* Internal socket has not yet been created */

return -EBADF;
}

len = bthcisock_host_read(bt_fd, &type, bt_frame, sizeof(bt_frame));
if (len < 0)
{
/* Failed to read, but that is likely because there is no packet */

return OK;
}

switch (type)
{
case HCI_EVENT_PKT:
{
buf_type = BT_EVT;
break;
}

case HCI_ACLDATA_PKT:
{
buf_type = BT_ACL_IN;
break;
}

default:
return OK;
}

outbuf = bt_buf_alloc(buf_type, NULL, 0);
if (outbuf == NULL)
{
wlerr("ERROR: Failed to allocate buffer\n");
return -ENOMEM;
}

/* First byte represents the type, so we strip that off */

outbuf->len = len - 1;
memcpy(outbuf->data, &bt_frame[1], outbuf->len);
bt_hci_receive(outbuf);
return OK;
}
Loading

0 comments on commit 333efb0

Please sign in to comment.