-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SIM: Add support Linux HCI Socket as BLE adaptor
Signed-off-by: Brennan Ashton <[email protected]>
- Loading branch information
Showing
10 changed files
with
586 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
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; | ||
} |
Oops, something went wrong.