mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-27 06:35:20 +00:00
ble client: alow and guard exclusive connection establishment, parallel disconnects, and scanning
This commit is contained in:
parent
1573cd5f74
commit
7df3e0bf12
@ -46,6 +46,7 @@
|
||||
#include <string.h>
|
||||
#include <btstack/run_loop.h>
|
||||
#include <btstack/hci_cmds.h>
|
||||
#include <btstack/utils.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@ -65,24 +66,22 @@ typedef enum {
|
||||
IDLE,
|
||||
//
|
||||
START_SCAN,
|
||||
W4_SCAN_ACTIVE,
|
||||
W4_SCANNING,
|
||||
//
|
||||
SCAN_ACTIVE,
|
||||
SCANNING,
|
||||
//
|
||||
STOP_SCAN,
|
||||
W4_SCAN_STOPPED,
|
||||
// IDLE,
|
||||
W4_CONNECTED,
|
||||
CONNECTED,
|
||||
//
|
||||
DISCONNECT,
|
||||
W4_DISCONNECTED
|
||||
W4_SCAN_STOPPED
|
||||
} state_t;
|
||||
|
||||
|
||||
static state_t state = W4_ON;
|
||||
static linked_list_t le_connections = NULL;
|
||||
|
||||
void le_central_init(){
|
||||
state = W4_ON;
|
||||
le_connections = NULL;
|
||||
}
|
||||
|
||||
void (*le_central_callback)(le_central_event_t * event);
|
||||
|
||||
@ -108,48 +107,14 @@ void le_central_register_handler(void (*le_callback)(le_central_event_t* event))
|
||||
}
|
||||
}
|
||||
|
||||
static void hexdump2(void *data, int size){
|
||||
int i;
|
||||
for (i=0; i<size;i++){
|
||||
printf("%02X ", ((uint8_t *)data)[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void gatt_client_init(){
|
||||
le_connections = NULL;
|
||||
state = W4_ON;
|
||||
}
|
||||
|
||||
void le_central_start_scan(){
|
||||
if (state != IDLE) return;
|
||||
state = START_SCAN;
|
||||
gatt_client_run();
|
||||
}
|
||||
|
||||
void le_central_stop_scan(){
|
||||
if (state != SCAN_ACTIVE) return;
|
||||
state = STOP_SCAN;
|
||||
gatt_client_run();
|
||||
}
|
||||
|
||||
static void le_peripheral_init(le_peripheral_t *context){
|
||||
memset(context, 0, sizeof(le_peripheral_t));
|
||||
context->state = P_IDLE;
|
||||
}
|
||||
|
||||
void le_central_connect(le_peripheral_t *context, uint8_t addr_type, bd_addr_t addr){
|
||||
le_peripheral_init(context);
|
||||
context->state = P_W2_CONNECT;
|
||||
context->address_type = addr_type;
|
||||
memcpy (context->address, addr, 6);
|
||||
linked_list_add(&le_connections, (linked_item_t *) context);
|
||||
|
||||
if (state == SCAN_ACTIVE){
|
||||
le_central_stop_scan();
|
||||
}
|
||||
gatt_client_run();
|
||||
static void send_gatt_connection_complete_event(le_peripheral_t * peripheral, uint8_t status){
|
||||
le_peripheral_event_t event;
|
||||
event.type = GATT_CONNECTION_COMPLETE;
|
||||
event.device = peripheral;
|
||||
event.status = status;
|
||||
(*le_central_callback)((le_central_event_t*)&event);
|
||||
}
|
||||
|
||||
static le_peripheral_t * get_peripheral_for_handle(uint16_t handle){
|
||||
@ -178,6 +143,10 @@ static inline le_peripheral_t * get_peripheral_w4_disconnected(){
|
||||
return get_peripheral_with_state(P_W4_DISCONNECTED);
|
||||
}
|
||||
|
||||
static inline le_peripheral_t * get_peripheral_w4_connect_cancelled(){
|
||||
return get_peripheral_with_state(P_W4_CONNECT_CANCELLED);
|
||||
}
|
||||
|
||||
static inline le_peripheral_t * get_peripheral_w2_connect(){
|
||||
return get_peripheral_with_state(P_W2_CONNECT);
|
||||
}
|
||||
@ -190,84 +159,292 @@ static inline le_peripheral_t * get_peripheral_w2_exchange_MTU(){
|
||||
return get_peripheral_with_state(P_W2_EXCHANGE_MTU);
|
||||
}
|
||||
|
||||
|
||||
void le_central_cancel_connect(le_peripheral_t *context){
|
||||
if (context->state == P_IDLE) return;
|
||||
|
||||
if (context->state == P_W2_CONNECT){
|
||||
context->state = P_IDLE;
|
||||
return;
|
||||
static le_peripheral_t * get_peripheral_with_address(uint8_t addr_type, bd_addr_t addr){
|
||||
linked_item_t *it;
|
||||
for (it = (linked_item_t *) le_connections; it ; it = it->next){
|
||||
le_peripheral_t * peripheral = (le_peripheral_t *) it;
|
||||
if (BD_ADDR_CMP(addr, peripheral->address) == 0 && peripheral->address_type == addr_type){
|
||||
return peripheral;
|
||||
}
|
||||
}
|
||||
state = DISCONNECT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_advertising_packet(uint8_t *packet){
|
||||
int num_reports = packet[3];
|
||||
int i;
|
||||
int total_data_length = 0;
|
||||
int data_offset = 0;
|
||||
|
||||
for (i=0; i<num_reports;i++){
|
||||
total_data_length += packet[4+num_reports*8+i];
|
||||
}
|
||||
|
||||
for (i=0; i<num_reports;i++){
|
||||
ad_event_t advertisement_event;
|
||||
advertisement_event.type = GATT_ADVERTISEMENT;
|
||||
advertisement_event.event_type = packet[4+i];
|
||||
advertisement_event.address_type = packet[4+num_reports+i];
|
||||
bt_flip_addr(advertisement_event.address, &packet[4+num_reports*2+i*6]);
|
||||
advertisement_event.length = packet[4+num_reports*8+i];
|
||||
advertisement_event.data = &packet[4+num_reports*9+data_offset];
|
||||
data_offset += advertisement_event.length;
|
||||
advertisement_event.rssi = packet[4+num_reports*9+total_data_length + i];
|
||||
|
||||
(*le_central_callback)((le_central_event_t*)&advertisement_event);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_peripheral_list(){
|
||||
// only one connect is allowed, wait for result
|
||||
if (get_peripheral_w4_connected()) return;
|
||||
// only one cancel connect is allowed, wait for result
|
||||
if (get_peripheral_w4_connect_cancelled()) return;
|
||||
|
||||
if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
|
||||
if (!l2cap_can_send_conectionless_packet_now()) return;
|
||||
|
||||
linked_item_t *it;
|
||||
for (it = (linked_item_t *) le_connections; it ; it = it->next){
|
||||
le_peripheral_t * peripheral = (le_peripheral_t *) it;
|
||||
|
||||
switch (peripheral->state){
|
||||
case P_W2_CONNECT:
|
||||
peripheral->state = P_W4_CONNECTED;
|
||||
hci_send_cmd(&hci_le_create_connection,
|
||||
1000, // scan interval: 625 ms
|
||||
1000, // scan interval: 625 ms
|
||||
0, // don't use whitelist
|
||||
0, // peer address type: public
|
||||
peripheral->address, // remote bd addr
|
||||
peripheral->address_type, // random or public
|
||||
80, // conn interval min
|
||||
80, // conn interval max (3200 * 0.625)
|
||||
0, // conn latency
|
||||
2000, // supervision timeout
|
||||
0, // min ce length
|
||||
1000 // max ce length
|
||||
);
|
||||
return;
|
||||
|
||||
case P_W2_CANCEL_CONNECT:
|
||||
peripheral->state = P_W4_CONNECT_CANCELLED;
|
||||
hci_send_cmd(&hci_le_create_connection_cancel);
|
||||
return;
|
||||
case P_W2_EXCHANGE_MTU:
|
||||
{
|
||||
peripheral->state = P_W4_EXCHANGE_MTU;
|
||||
uint16_t mtu = l2cap_max_mtu_for_handle(peripheral->handle);
|
||||
uint8_t request[3];
|
||||
request[0] = ATT_EXCHANGE_MTU_REQUEST;
|
||||
bt_store_16(request, 1, mtu);
|
||||
l2cap_send_connectionless(peripheral->handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, request, sizeof(request));
|
||||
return;
|
||||
}
|
||||
|
||||
case P_W2_DISCONNECT:
|
||||
peripheral->state = P_W4_DISCONNECTED;
|
||||
hci_send_cmd(&hci_disconnect, peripheral->handle,0x13);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void le_central_start_scan(){
|
||||
if (state != IDLE) return;
|
||||
state = START_SCAN;
|
||||
gatt_client_run();
|
||||
}
|
||||
|
||||
void le_central_stop_scan(){
|
||||
if (state != SCANNING) return;
|
||||
state = STOP_SCAN;
|
||||
gatt_client_run();
|
||||
}
|
||||
|
||||
static void le_peripheral_init(le_peripheral_t *context, uint8_t addr_type, bd_addr_t addr){
|
||||
memset(context, 0, sizeof(le_peripheral_t));
|
||||
context->state = P_W2_CONNECT;
|
||||
context->address_type = addr_type;
|
||||
memcpy (context->address, addr, 6);
|
||||
}
|
||||
|
||||
le_command_status_t le_central_connect(le_peripheral_t *context, uint8_t addr_type, bd_addr_t addr){
|
||||
//TODO: align with hci connection list capacity
|
||||
le_peripheral_t * peripheral = get_peripheral_with_address(addr_type, addr);
|
||||
if (!peripheral) {
|
||||
le_peripheral_init(context, addr_type, addr);
|
||||
linked_list_add(&le_connections, (linked_item_t *) context);
|
||||
} else if (peripheral == context) {
|
||||
if (context->state != P_W2_CONNECT) return BLE_PERIPHERAL_IN_WRONG_STATE;
|
||||
} else {
|
||||
return BLE_PERIPHERAL_DIFFERENT_CONTEXT_FOR_ADDRESS_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
gatt_client_run();
|
||||
return BLE_PERIPHERAL_OK;
|
||||
}
|
||||
|
||||
le_command_status_t le_central_disconnect(le_peripheral_t *context){
|
||||
// printf("*** le_central_disconnect::CALLED DISCONNECT \n");
|
||||
|
||||
le_peripheral_t * peripheral = get_peripheral_with_address(context->address_type, context->address);
|
||||
if (!peripheral || (peripheral && peripheral != context)){
|
||||
return BLE_PERIPHERAL_DIFFERENT_CONTEXT_FOR_ADDRESS_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
switch(context->state){
|
||||
case P_W2_CONNECT:
|
||||
linked_list_remove(&le_connections, (linked_item_t *) context);
|
||||
send_gatt_connection_complete_event(context, 0);
|
||||
break;
|
||||
case P_W4_CONNECTED:
|
||||
case P_W2_CANCEL_CONNECT:
|
||||
// trigger cancel connect
|
||||
context->state = P_W2_CANCEL_CONNECT;
|
||||
break;
|
||||
case P_W2_EXCHANGE_MTU:
|
||||
case P_W4_EXCHANGE_MTU:
|
||||
case P_CONNECTED:
|
||||
case P_W2_DISCONNECT:
|
||||
// trigger disconnect
|
||||
context->state = P_W2_DISCONNECT;
|
||||
break;
|
||||
case P_W4_DISCONNECTED:
|
||||
case P_W4_CONNECT_CANCELLED:
|
||||
return BLE_PERIPHERAL_IN_WRONG_STATE;
|
||||
}
|
||||
gatt_client_run();
|
||||
return BLE_PERIPHERAL_OK;
|
||||
}
|
||||
|
||||
|
||||
static void gatt_client_run(){
|
||||
if (state == W4_ON) return;
|
||||
|
||||
handle_peripheral_list();
|
||||
|
||||
// check if command is send
|
||||
if (!hci_can_send_packet_now(HCI_COMMAND_DATA_PACKET)) return;
|
||||
if (!l2cap_can_send_conectionless_packet_now()) return;
|
||||
|
||||
le_peripheral_t * peripheral = NULL;
|
||||
// hadle peripherals list
|
||||
|
||||
switch(state){
|
||||
case IDLE:
|
||||
if (! (peripheral = get_peripheral_w2_connect()) ) break;
|
||||
|
||||
peripheral->state = P_W4_CONNECTED;
|
||||
state = W4_CONNECTED;
|
||||
|
||||
hci_send_cmd(&hci_le_create_connection,
|
||||
1000, // scan interval: 625 ms
|
||||
1000, // scan interval: 625 ms
|
||||
0, // don't use whitelist
|
||||
0, // peer address type: public
|
||||
peripheral->address, // remote bd addr
|
||||
peripheral->address_type, // random or public
|
||||
80, // conn interval min
|
||||
80, // conn interval max (3200 * 0.625)
|
||||
0, // conn latency
|
||||
2000, // supervision timeout
|
||||
0, // min ce length
|
||||
1000 // max ce length
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case START_SCAN:
|
||||
state = W4_SCAN_ACTIVE;
|
||||
state = W4_SCANNING;
|
||||
hci_send_cmd(&hci_le_set_scan_enable, 1, 0);
|
||||
break;
|
||||
return;
|
||||
|
||||
case STOP_SCAN:
|
||||
state = W4_SCAN_STOPPED;
|
||||
hci_send_cmd(&hci_le_set_scan_enable, 0, 0);
|
||||
break;
|
||||
case CONNECTED:{
|
||||
le_peripheral_t * peripheral = get_peripheral_w2_exchange_MTU();
|
||||
|
||||
if (!peripheral) break;
|
||||
return;
|
||||
|
||||
peripheral->state = P_W4_EXCHANGE_MTU;
|
||||
uint16_t mtu = l2cap_max_mtu_for_handle(peripheral->handle);
|
||||
|
||||
uint8_t request[3];
|
||||
request[0] = ATT_EXCHANGE_MTU_REQUEST;
|
||||
bt_store_16(request, 1, mtu);
|
||||
l2cap_send_connectionless(peripheral->handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, request, sizeof(request));
|
||||
break;
|
||||
}
|
||||
case DISCONNECT:
|
||||
peripheral->state = P_W4_DISCONNECTED;
|
||||
state = W4_DISCONNECTED;
|
||||
hci_send_cmd(&hci_le_create_connection_cancel);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_ad_event(ad_event_t e){
|
||||
printf("evt-type %u, addr-type %u, addr %s, rssi %u, length adv %u, data: ", e.event_type,
|
||||
e.address_type, bd_addr_to_str(e.address), e.rssi, e.length);
|
||||
hexdump2( e.data, e.length);
|
||||
|
||||
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
|
||||
if (packet_type != HCI_EVENT_PACKET) return;
|
||||
switch (packet[0]) {
|
||||
case BTSTACK_EVENT_STATE:
|
||||
// BTstack activated, get started
|
||||
if (packet[2] == HCI_STATE_WORKING) {
|
||||
printf("BTstack activated, get started!\n");
|
||||
state = IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_enable)){
|
||||
switch(state){
|
||||
case W4_SCANNING:
|
||||
state = SCANNING;
|
||||
break;
|
||||
case W4_SCAN_STOPPED:
|
||||
state = IDLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (COMMAND_COMPLETE_EVENT(packet, hci_le_create_connection_cancel)){
|
||||
// printf("packet_handler:: hci_le_create_connection_cancel: cancel connect\n");
|
||||
if (packet[3] != 0x0B) break;
|
||||
|
||||
// cancel connection failed, as connection already established
|
||||
le_peripheral_t * peripheral = get_peripheral_w4_connect_cancelled();
|
||||
peripheral->state = P_W2_DISCONNECT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
{
|
||||
uint16_t handle = READ_BT_16(packet,3);
|
||||
le_peripheral_t * peripheral = get_peripheral_for_handle(handle);
|
||||
if (!peripheral) break;
|
||||
|
||||
peripheral->state = P_W2_CONNECT;
|
||||
linked_list_remove(&le_connections, (linked_item_t *) peripheral);
|
||||
send_gatt_connection_complete_event(peripheral, packet[5]);
|
||||
// printf("Peripheral disconnected, and removed from list\n");
|
||||
break;
|
||||
}
|
||||
|
||||
case HCI_EVENT_LE_META:
|
||||
switch (packet[2]) {
|
||||
case HCI_SUBEVENT_LE_ADVERTISING_REPORT:
|
||||
if (state != SCANNING) break;
|
||||
handle_advertising_packet(packet);
|
||||
break;
|
||||
|
||||
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: {
|
||||
// deal with conn cancel, conn fail, conn success
|
||||
le_peripheral_t * peripheral;
|
||||
|
||||
// conn success/error?
|
||||
peripheral = get_peripheral_w4_connected();
|
||||
if (peripheral){
|
||||
if (packet[3]){
|
||||
// error
|
||||
linked_list_remove(&le_connections, (linked_item_t *) peripheral);
|
||||
} else {
|
||||
// success
|
||||
peripheral->state = P_W2_EXCHANGE_MTU;
|
||||
peripheral->handle = READ_BT_16(packet, 4);
|
||||
}
|
||||
send_gatt_connection_complete_event(peripheral, packet[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
// cancel success?
|
||||
peripheral = get_peripheral_w4_connect_cancelled();
|
||||
if (!peripheral) break;
|
||||
|
||||
linked_list_remove(&le_connections, (linked_item_t *) peripheral);
|
||||
send_gatt_connection_complete_event(peripheral, packet[3]);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gatt_client_run();
|
||||
}
|
||||
|
||||
|
||||
@ -278,138 +455,20 @@ static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pa
|
||||
case ATT_EXCHANGE_MTU_RESPONSE:
|
||||
{
|
||||
le_peripheral_t * peripheral = get_peripheral_for_handle(handle);
|
||||
|
||||
if (!peripheral) return;
|
||||
|
||||
uint16_t remote_rx_mtu = READ_BT_16(packet, 1);
|
||||
uint16_t local_rx_mtu = l2cap_max_mtu_for_handle(handle);
|
||||
peripheral->mtu = remote_rx_mtu < local_rx_mtu ? remote_rx_mtu : local_rx_mtu;
|
||||
|
||||
le_peripheral_event_t p_connected_event;
|
||||
p_connected_event.type = GATT_CONNECTION_COMPLETE;
|
||||
p_connected_event.device = peripheral;
|
||||
p_connected_event.status = 0;
|
||||
(*le_central_callback)((le_central_event_t*)&p_connected_event);
|
||||
|
||||
send_gatt_connection_complete_event(peripheral, 0);
|
||||
|
||||
peripheral->state = P_CONNECTED;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
switch (packet_type) {
|
||||
case HCI_EVENT_PACKET:
|
||||
switch (packet[0]) {
|
||||
|
||||
case BTSTACK_EVENT_STATE:
|
||||
// bt stack activated, get started
|
||||
if (packet[2] == HCI_STATE_WORKING) {
|
||||
printf("Working!\n");
|
||||
state = IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (COMMAND_COMPLETE_EVENT(packet, hci_le_set_scan_enable)){
|
||||
switch(state){
|
||||
case W4_SCAN_ACTIVE:
|
||||
state = SCAN_ACTIVE;
|
||||
break;
|
||||
case W4_SCAN_STOPPED:
|
||||
state = IDLE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HCI_EVENT_LE_META:
|
||||
switch (packet[2]) {
|
||||
case HCI_SUBEVENT_LE_ADVERTISING_REPORT:
|
||||
if (state != SCAN_ACTIVE) break;
|
||||
{
|
||||
int num_reports = packet[3];
|
||||
int i;
|
||||
int total_data_length = 0;
|
||||
int data_offset = 0;
|
||||
|
||||
for (i=0; i<num_reports;i++){
|
||||
total_data_length += packet[4+num_reports*8+i];
|
||||
}
|
||||
|
||||
for (i=0; i<num_reports;i++){
|
||||
ad_event_t advertisement_event;
|
||||
advertisement_event.type = GATT_ADVERTISEMENT;
|
||||
advertisement_event.event_type = packet[4+i];
|
||||
advertisement_event.address_type = packet[4+num_reports+i];
|
||||
bt_flip_addr(advertisement_event.address, &packet[4+num_reports*2+i*6]);
|
||||
advertisement_event.length = packet[4+num_reports*8+i];
|
||||
advertisement_event.data = &packet[4+num_reports*9+data_offset];
|
||||
data_offset += advertisement_event.length;
|
||||
advertisement_event.rssi = packet[4+num_reports*9+total_data_length + i];
|
||||
|
||||
(*le_central_callback)((le_central_event_t*)&advertisement_event);
|
||||
|
||||
dump_ad_event(advertisement_event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:{
|
||||
switch (state){
|
||||
case W4_CONNECTED:{
|
||||
le_peripheral_t * peripheral = get_peripheral_w4_connected();
|
||||
|
||||
if (packet[3] != 0) {
|
||||
le_peripheral_event_t p_connected_event;
|
||||
p_connected_event.type = GATT_CONNECTION_COMPLETE;
|
||||
p_connected_event.device = peripheral;
|
||||
p_connected_event.status = packet[3];
|
||||
(*le_central_callback)((le_central_event_t*)&p_connected_event);
|
||||
return;
|
||||
}
|
||||
|
||||
state = CONNECTED;
|
||||
peripheral->state = P_W2_EXCHANGE_MTU;
|
||||
|
||||
peripheral->handle = READ_BT_16(packet, 4);
|
||||
|
||||
printf("Connected: handle 0x%04x!\n", peripheral->handle);
|
||||
break;
|
||||
}
|
||||
|
||||
case W4_DISCONNECTED: {
|
||||
le_peripheral_t * peripheral = get_peripheral_w4_disconnected();
|
||||
state = IDLE;
|
||||
peripheral->state = P_IDLE;
|
||||
|
||||
le_peripheral_event_t p_disconnected_event;
|
||||
p_disconnected_event.type = GATT_CONNECTION_COMPLETE;
|
||||
p_disconnected_event.device = peripheral;
|
||||
p_disconnected_event.status = packet[3];
|
||||
|
||||
(*le_central_callback)((le_central_event_t*)&p_disconnected_event);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gatt_client_run();
|
||||
}
|
||||
|
||||
@ -435,11 +494,17 @@ void setup(void){
|
||||
l2cap_register_packet_handler(packet_handler);
|
||||
}
|
||||
|
||||
|
||||
// main == setup
|
||||
int main(void)
|
||||
{
|
||||
setup();
|
||||
|
||||
|
||||
/* test
|
||||
le_central_init();
|
||||
le_central_register_handler(handle_le_central_event);
|
||||
*/
|
||||
|
||||
// turn on!
|
||||
hci_power_control(HCI_POWER_ON);
|
||||
|
||||
@ -449,3 +514,96 @@ int main(void)
|
||||
// happy compiler!
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* test
|
||||
|
||||
static void dump_peripheral_state(peripheral_state_t p_state){
|
||||
switch(p_state) {
|
||||
case P_W2_CONNECT: printf("P_W2_CONNECT"); break;
|
||||
case P_W4_CONNECTED: printf("P_W4_CONNECTED"); break;
|
||||
case P_W2_EXCHANGE_MTU: printf("P_W2_EXCHANGE_MTU"); break;
|
||||
case P_W4_EXCHANGE_MTU: printf("P_W4_EXCHANGE_MTU"); break;
|
||||
case P_CONNECTED: printf("P_CONNECTED"); break;
|
||||
case P_W2_CANCEL_CONNECT: printf("P_W2_CANCEL_CONNECT"); break;
|
||||
case P_W4_CONNECT_CANCELLED: printf("P_W4_CONNECT_CANCELLED"); break;
|
||||
case P_W2_DISCONNECT: printf("P_W2_DISCONNECT"); break;
|
||||
case P_W4_DISCONNECTED: printf("P_W4_DISCONNECTED"); break;
|
||||
};
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void dump_state(){
|
||||
switch(state){
|
||||
case W4_ON: printf("W4_ON"); break;
|
||||
case IDLE: printf("IDLE"); break;
|
||||
case START_SCAN: printf("START_SCAN"); break;
|
||||
case W4_SCANNING: printf("W4_SCANNING"); break;
|
||||
case SCANNING: printf("SCANNING"); break;
|
||||
case STOP_SCAN: printf("STOP_SCAN"); break;
|
||||
case W4_SCAN_STOPPED: printf("W4_SCAN_STOPPED"); break;
|
||||
};
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void hexdump2(void *data, int size){
|
||||
int i;
|
||||
for (i=0; i<size;i++){
|
||||
printf("%02X ", ((uint8_t *)data)[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void dump_ad_event(ad_event_t* e){
|
||||
printf("evt-type %u, addr-type %u, addr %s, rssi %u, length adv %u, data: ", e->event_type,
|
||||
e->address_type, bd_addr_to_str(e->address), e->rssi, e->length);
|
||||
hexdump2( e->data, e->length);
|
||||
}
|
||||
|
||||
le_peripheral_t test_device;
|
||||
|
||||
static bd_addr_t test_device_addr = {0x1c, 0xba, 0x8c, 0x20, 0xc7, 0xf6};
|
||||
|
||||
|
||||
void test_client(){
|
||||
static int i = 0;
|
||||
|
||||
switch(i){
|
||||
case 0:
|
||||
le_central_start_scan();
|
||||
printf("--- test_client::calling start scan \n");
|
||||
break;
|
||||
case 20:
|
||||
printf("--- test_client::calling connect peripheral: status %d\n", le_central_connect(&test_device, 0, test_device_addr));
|
||||
break;
|
||||
case 40:
|
||||
i=-1;
|
||||
// le_central_stop_scan();
|
||||
printf("--- test_client::calling dissconnect peripheral: status %d\n", le_central_disconnect(&test_device));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
static void handle_le_central_event(le_central_event_t * event){
|
||||
ad_event_t * advertisement_event;
|
||||
le_peripheral_event_t * peripheral_event;
|
||||
switch (event->type){
|
||||
case GATT_ADVERTISEMENT:
|
||||
advertisement_event = (ad_event_t*) event;
|
||||
dump_ad_event(advertisement_event);
|
||||
break;
|
||||
case GATT_CONNECTION_COMPLETE:
|
||||
peripheral_event = (le_peripheral_event_t *) event;
|
||||
if (peripheral_event->status == 0){
|
||||
printf("handle_le_central_event::device is connected\n");
|
||||
} else {
|
||||
printf("handle_le_central_event::disconnected with status %02x \n", peripheral_event->status);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
@ -66,15 +66,27 @@ typedef struct ad_event {
|
||||
} ad_event_t;
|
||||
|
||||
typedef enum {
|
||||
P_IDLE,
|
||||
P_W2_CONNECT,
|
||||
P_W4_CONNECTED,
|
||||
|
||||
P_W2_EXCHANGE_MTU,
|
||||
P_W4_EXCHANGE_MTU,
|
||||
|
||||
P_CONNECTED,
|
||||
P_W4_DISCONNECTED
|
||||
|
||||
P_W2_CANCEL_CONNECT,
|
||||
P_W4_CONNECT_CANCELLED,
|
||||
P_W2_DISCONNECT,
|
||||
P_W4_DISCONNECTED,
|
||||
} peripheral_state_t;
|
||||
|
||||
typedef enum {
|
||||
BLE_PERIPHERAL_OK = 0,
|
||||
BLE_PERIPHERAL_IN_WRONG_STATE,
|
||||
BLE_PERIPHERAL_DIFFERENT_CONTEXT_FOR_ADDRESS_ALREADY_EXISTS
|
||||
} le_command_status_t;
|
||||
|
||||
|
||||
typedef struct le_peripheral{
|
||||
linked_item_t item;
|
||||
|
||||
@ -108,8 +120,8 @@ void le_central_start_scan();
|
||||
// { type (8), addr_type (8), addr(48), rssi(8), ad_len(8), ad_data(ad_len*8) }
|
||||
void le_central_stop_scan();
|
||||
|
||||
void le_central_connect(le_peripheral_t *context, uint8_t addr_type, bd_addr_t addr);
|
||||
void le_central_cancel_connect(le_peripheral_t *context);
|
||||
le_command_status_t le_central_connect(le_peripheral_t *context, uint8_t addr_type, bd_addr_t addr);
|
||||
le_command_status_t le_central_disconnect(le_peripheral_t *context);
|
||||
|
||||
void le_central_get_services(le_peripheral_t *context);
|
||||
void le_central_get_services_with_uuid16(le_peripheral_t *context, uint16_t uuid16);
|
||||
|
Loading…
x
Reference in New Issue
Block a user