mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-04-11 00:44:27 +00:00
untested code for BTstack lib connection to BTdaemon
This commit is contained in:
parent
fd7ed8d4e2
commit
1cd208ad37
@ -14,7 +14,6 @@
|
|||||||
9C46FC390FA906F700ABEF05 /* hci.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC340FA906F700ABEF05 /* hci.c */; };
|
9C46FC390FA906F700ABEF05 /* hci.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC340FA906F700ABEF05 /* hci.c */; };
|
||||||
9C46FC3A0FA906F700ABEF05 /* hci_transport_h4.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC360FA906F700ABEF05 /* hci_transport_h4.c */; };
|
9C46FC3A0FA906F700ABEF05 /* hci_transport_h4.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC360FA906F700ABEF05 /* hci_transport_h4.c */; };
|
||||||
9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5ABF100BD3340065D87E /* linked_list.c */; };
|
9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5ABF100BD3340065D87E /* linked_list.c */; };
|
||||||
9C7B5B7F100D04450065D87E /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5B7E100D04450065D87E /* test.c */; };
|
|
||||||
9C7ECB840FCC85650085DAC5 /* bt_control_iphone.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECB820FCC85650085DAC5 /* bt_control_iphone.c */; };
|
9C7ECB840FCC85650085DAC5 /* bt_control_iphone.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECB820FCC85650085DAC5 /* bt_control_iphone.c */; };
|
||||||
9C7ECBB50FCC95DD0085DAC5 /* hci_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECBB40FCC95DD0085DAC5 /* hci_dump.c */; };
|
9C7ECBB50FCC95DD0085DAC5 /* hci_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECBB40FCC95DD0085DAC5 /* hci_dump.c */; };
|
||||||
9C88500E0FBF6702004980E4 /* l2cap.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C88500C0FBF6702004980E4 /* l2cap.c */; };
|
9C88500E0FBF6702004980E4 /* l2cap.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C88500C0FBF6702004980E4 /* l2cap.c */; };
|
||||||
@ -199,7 +198,6 @@
|
|||||||
9CC813A50FFC0A51002816F9 /* daemon.c in Sources */,
|
9CC813A50FFC0A51002816F9 /* daemon.c in Sources */,
|
||||||
9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */,
|
9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */,
|
||||||
9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */,
|
9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */,
|
||||||
9C7B5B7F100D04450065D87E /* test.c in Sources */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
147
src/btstack.c
147
src/btstack.c
@ -8,25 +8,168 @@
|
|||||||
|
|
||||||
#include "btstack.h"
|
#include "btstack.h"
|
||||||
|
|
||||||
|
#include "run_loop.h"
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
typedef struct packet_header {
|
||||||
|
uint16_t length;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t data[0];
|
||||||
|
} packet_header_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SOCKET_W4_HEADER,
|
||||||
|
SOCKET_W4_DATA,
|
||||||
|
} SOCKET_STATE;
|
||||||
|
|
||||||
|
typedef struct connection {
|
||||||
|
data_source_t ds; // used for run loop
|
||||||
|
linked_item_t item; // used for connection list
|
||||||
|
SOCKET_STATE state;
|
||||||
|
uint16_t bytes_read;
|
||||||
|
uint16_t bytes_to_read;
|
||||||
|
uint8_t buffer[3+3+255]; // max HCI CMD + packet_header
|
||||||
|
} connection_t;
|
||||||
|
|
||||||
|
uint8_t hci_cmd_buffer[3+255];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void dummy_handler(uint8_t *packet, int size);
|
||||||
|
static int btstack_socket_process(struct data_source *ds, int ready);
|
||||||
|
|
||||||
|
static int btstack_socket = -1;
|
||||||
|
static connection_t *btstack_connection = NULL;
|
||||||
|
static const int btstack_port = 1919;
|
||||||
|
|
||||||
|
/* callback to L2CAP layer */
|
||||||
|
static void (*event_packet_handler)(uint8_t *packet, int size) = dummy_handler;
|
||||||
|
static void (*acl_packet_handler) (uint8_t *packet, int size) = dummy_handler;
|
||||||
|
|
||||||
|
|
||||||
// init BTstack library
|
// init BTstack library
|
||||||
int bt_open(){
|
int bt_open(){
|
||||||
|
// TCP
|
||||||
|
struct protoent* tcp = getprotobyname("tcp");
|
||||||
|
btstack_socket = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
|
||||||
|
if(btstack_socket == -1){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// localhost
|
||||||
|
struct sockaddr_in btdaemon_address;
|
||||||
|
btdaemon_address.sin_family = AF_INET;
|
||||||
|
btdaemon_address.sin_port = htons(btstack_port);
|
||||||
|
struct hostent* localhost = gethostbyname("localhost");
|
||||||
|
if(!localhost){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// connect
|
||||||
|
char* addr = localhost->h_addr_list[0];
|
||||||
|
memcpy(&btdaemon_address.sin_addr.s_addr, addr, sizeof addr);
|
||||||
|
if(connect(btstack_socket, (struct sockaddr*)&btdaemon_address, sizeof btdaemon_address) == -1){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init state machine
|
||||||
|
btstack_connection->state = SOCKET_W4_HEADER;
|
||||||
|
btstack_connection->bytes_read = 0;
|
||||||
|
btstack_connection->bytes_to_read = 2;
|
||||||
|
|
||||||
|
// register with run loop
|
||||||
|
btstack_connection = malloc( sizeof(connection_t));
|
||||||
|
if (btstack_connection == NULL) return -1;
|
||||||
|
btstack_connection->ds.fd = btstack_socket;
|
||||||
|
btstack_connection->ds.process = btstack_socket_process;
|
||||||
|
run_loop_add(&btstack_connection->ds);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// stop using BTstack library
|
// stop using BTstack library
|
||||||
int bt_close(){
|
int bt_close(){
|
||||||
|
if (btstack_socket < 0) return 0;
|
||||||
|
shutdown(btstack_socket, SHUT_RDWR);
|
||||||
|
if (btstack_connection) {
|
||||||
|
run_loop_remove(&btstack_connection->ds);
|
||||||
|
free( btstack_connection );
|
||||||
|
btstack_connection = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// run_loop based data handling
|
||||||
|
int btstack_socket_process(struct data_source *ds, int ready) {
|
||||||
|
connection_t *conn = (connection_t *) ds;
|
||||||
|
int bytes_read = read(ds->fd, &conn->buffer[conn->bytes_read],
|
||||||
|
sizeof(packet_header_t) - conn->bytes_read);
|
||||||
|
if (bytes_read <= 0){
|
||||||
|
// free
|
||||||
|
run_loop_remove(&conn->ds);
|
||||||
|
free(conn);
|
||||||
|
// TODO notify client of cailed daemon connection!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
conn->bytes_read += bytes_read;
|
||||||
|
conn->bytes_to_read -= bytes_read;
|
||||||
|
if (conn->bytes_to_read > 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (conn->state){
|
||||||
|
case SOCKET_W4_HEADER:
|
||||||
|
conn->state = SOCKET_W4_DATA;
|
||||||
|
conn->bytes_to_read = READ_BT_16( conn->buffer, 0) + sizeof(packet_header_t);
|
||||||
|
break;
|
||||||
|
case SOCKET_W4_DATA:
|
||||||
|
// process packet !!!
|
||||||
|
switch (conn->buffer[2]){
|
||||||
|
case HCI_EVENT_PACKET:
|
||||||
|
(*event_packet_handler)(&conn->buffer[3], READ_BT_16( conn->buffer, 0));
|
||||||
|
break;
|
||||||
|
case HCI_ACL_DATA_PACKET:
|
||||||
|
(*acl_packet_handler)(&conn->buffer[3], READ_BT_16( conn->buffer, 0));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for next packet
|
||||||
|
conn->state = SOCKET_W4_HEADER;
|
||||||
|
conn->bytes_read = 0;
|
||||||
|
conn->bytes_to_read = sizeof(packet_header_t);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// send hci cmd packet
|
// send hci cmd packet
|
||||||
int bt_send_cmd(hci_cmd_t *cmd, ...){
|
int bt_send_cmd(hci_cmd_t *cmd, ...){
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, cmd);
|
||||||
|
uint16_t len = hci_create_cmd_internal(hci_cmd_buffer, cmd, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
return len;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send hci acl packet
|
// send hci acl packet
|
||||||
int bt_send_acl_packet(uint8_t *packet, int size){
|
int bt_send_acl_packet(uint8_t *packet, int size){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dummy_handler(uint8_t *packet, int size){
|
||||||
}
|
}
|
||||||
|
|
||||||
// register packet and event handler
|
// register packet and event handler
|
||||||
void bt_register_event_packet_handler(void (*handler)(uint8_t *packet, int size)){
|
void bt_register_event_packet_handler(void (*handler)(uint8_t *packet, int size)){
|
||||||
}
|
event_packet_handler = handler;
|
||||||
void bt_register_acl_packet_handler (void (*handler)(uint8_t *packet, int size)){
|
}
|
||||||
|
|
||||||
|
void bt_register_acl_packet_handler (void (*handler)(uint8_t *packet, int size)){
|
||||||
|
acl_packet_handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
src/hci.c
40
src/hci.c
@ -159,7 +159,7 @@ static hci_connection_t *link_for_addr(bd_addr_t addr){
|
|||||||
/**
|
/**
|
||||||
* Handler called by HCI transport
|
* Handler called by HCI transport
|
||||||
*/
|
*/
|
||||||
static void dummy_handler(uint8_t *packet, int size){
|
static void dummy_handler(uint8_t *packet, uint16_t size){
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acl_handler(uint8_t *packet, int size){
|
static void acl_handler(uint8_t *packet, int size){
|
||||||
@ -213,10 +213,10 @@ static void event_handler(uint8_t *packet, int size){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Register L2CAP handlers */
|
/** Register L2CAP handlers */
|
||||||
void hci_register_event_packet_handler(void (*handler)(uint8_t *packet, int size)){
|
void hci_register_event_packet_handler(void (*handler)(uint8_t *packet, uint16_t size)){
|
||||||
hci_stack.event_packet_handler = handler;
|
hci_stack.event_packet_handler = handler;
|
||||||
}
|
}
|
||||||
void hci_register_acl_packet_handler (void (*handler)(uint8_t *packet, int size)){
|
void hci_register_acl_packet_handler (void (*handler)(uint8_t *packet, uint16_t size)){
|
||||||
hci_stack.acl_packet_handler = handler;
|
hci_stack.acl_packet_handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,17 +345,12 @@ int hci_send_cmd_packet(uint8_t *packet, int size){
|
|||||||
return hci_stack.hci_transport->send_cmd_packet(packet, size);
|
return hci_stack.hci_transport->send_cmd_packet(packet, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
uint16_t hci_create_cmd_internal(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, va_list argptr){
|
||||||
* pre: numcmds >= 0 - it's allowed to send a command to the controller
|
|
||||||
*/
|
|
||||||
int hci_send_cmd(hci_cmd_t *cmd, ...){
|
|
||||||
uint8_t * hci_cmd_buffer = hci_stack.hci_cmd_buffer;
|
|
||||||
hci_cmd_buffer[0] = cmd->opcode & 0xff;
|
hci_cmd_buffer[0] = cmd->opcode & 0xff;
|
||||||
hci_cmd_buffer[1] = cmd->opcode >> 8;
|
hci_cmd_buffer[1] = cmd->opcode >> 8;
|
||||||
int pos = 3;
|
int pos = 3;
|
||||||
|
|
||||||
va_list argptr;
|
|
||||||
va_start(argptr, cmd);
|
|
||||||
const char *format = cmd->format;
|
const char *format = cmd->format;
|
||||||
uint16_t word;
|
uint16_t word;
|
||||||
uint32_t longword;
|
uint32_t longword;
|
||||||
@ -413,7 +408,26 @@ int hci_send_cmd(hci_cmd_t *cmd, ...){
|
|||||||
}
|
}
|
||||||
format++;
|
format++;
|
||||||
};
|
};
|
||||||
va_end(argptr);
|
|
||||||
hci_cmd_buffer[2] = pos - 3;
|
hci_cmd_buffer[2] = pos - 3;
|
||||||
return hci_send_cmd_packet(hci_cmd_buffer, pos);
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t hci_create_cmd(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, ...){
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, cmd);
|
||||||
|
uint16_t len = hci_create_cmd_internal(hci_cmd_buffer, cmd, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pre: numcmds >= 0 - it's allowed to send a command to the controller
|
||||||
|
*/
|
||||||
|
int hci_send_cmd(hci_cmd_t *cmd, ...){
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, cmd);
|
||||||
|
uint8_t * hci_cmd_buffer = hci_stack.hci_cmd_buffer;
|
||||||
|
uint16_t size = hci_create_cmd_internal(hci_stack.hci_cmd_buffer, cmd, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
return hci_send_cmd_packet(hci_cmd_buffer, size);
|
||||||
}
|
}
|
13
src/hci.h
13
src/hci.h
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "hci_transport.h"
|
#include "hci_transport.h"
|
||||||
#include "bt_control.h"
|
#include "bt_control.h"
|
||||||
@ -143,8 +144,8 @@ typedef struct {
|
|||||||
uint8_t num_acl_packets;
|
uint8_t num_acl_packets;
|
||||||
|
|
||||||
/* callback to L2CAP layer */
|
/* callback to L2CAP layer */
|
||||||
void (*event_packet_handler)(uint8_t *packet, int size);
|
void (*event_packet_handler)(uint8_t *packet, uint16_t size);
|
||||||
void (*acl_packet_handler) (uint8_t *packet, int size);
|
void (*acl_packet_handler) (uint8_t *packet, uint16_t size);
|
||||||
|
|
||||||
/* hci state machine */
|
/* hci state machine */
|
||||||
HCI_STATE state;
|
HCI_STATE state;
|
||||||
@ -157,9 +158,9 @@ typedef struct {
|
|||||||
// set up HCI
|
// set up HCI
|
||||||
void hci_init(hci_transport_t *transport, void *config, bt_control_t *control);
|
void hci_init(hci_transport_t *transport, void *config, bt_control_t *control);
|
||||||
|
|
||||||
void hci_register_event_packet_handler(void (*handler)(uint8_t *packet, int size));
|
void hci_register_event_packet_handler(void (*handler)(uint8_t *packet, uint16_t size));
|
||||||
|
|
||||||
void hci_register_acl_packet_handler (void (*handler)(uint8_t *packet, int size));
|
void hci_register_acl_packet_handler (void (*handler)(uint8_t *packet, uint16_t size));
|
||||||
|
|
||||||
// power control
|
// power control
|
||||||
int hci_power_control(HCI_POWER_MODE mode);
|
int hci_power_control(HCI_POWER_MODE mode);
|
||||||
@ -174,7 +175,9 @@ uint32_t hci_run();
|
|||||||
//
|
//
|
||||||
void hexdump(void *data, int size);
|
void hexdump(void *data, int size);
|
||||||
|
|
||||||
// create and send hci command packet based on a template and a list of parameters
|
// create and send hci command packets based on a template and a list of parameters
|
||||||
|
uint16_t hci_create_cmd_internal(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, va_list argptr);
|
||||||
|
uint16_t hci_create_cmd(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, ...);
|
||||||
int hci_send_cmd(hci_cmd_t *cmd, ...);
|
int hci_send_cmd(hci_cmd_t *cmd, ...);
|
||||||
int hci_send_cmd_packet(uint8_t *packet, int size);
|
int hci_send_cmd_packet(uint8_t *packet, int size);
|
||||||
|
|
||||||
|
@ -145,12 +145,14 @@ int socket_server_send_packet_all(uint8_t type, uint8_t *packet, uint16_t size){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_server_send_event_all(uint8_t *packet, uint16_t size){
|
void socket_server_send_event_all(uint8_t *packet, uint16_t size){
|
||||||
return socket_server_send_packet_all( HCI_EVENT_PACKET, packet, size);
|
socket_server_send_packet_all( HCI_EVENT_PACKET, packet, size);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int socket_server_send_acl_all(uint8_t *packet, uint16_t size){
|
void socket_server_send_acl_all(uint8_t *packet, uint16_t size){
|
||||||
return socket_server_send_packet_all( HCI_ACL_DATA_PACKET, packet, size);
|
socket_server_send_packet_all( HCI_ACL_DATA_PACKET, packet, size);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -202,7 +204,6 @@ data_source_t * socket_server_create_tcp(int port){
|
|||||||
ds->process = socket_server_accept;
|
ds->process = socket_server_accept;
|
||||||
|
|
||||||
// create tcp socket
|
// create tcp socket
|
||||||
struct sockaddr_in addr;
|
|
||||||
if ((ds->fd = socket (PF_INET, SOCK_STREAM, 0)) < 0) {
|
if ((ds->fd = socket (PF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
printf ("Error creating socket ...(%s)\n", strerror(errno));
|
printf ("Error creating socket ...(%s)\n", strerror(errno));
|
||||||
free(ds);
|
free(ds);
|
||||||
@ -211,6 +212,7 @@ data_source_t * socket_server_create_tcp(int port){
|
|||||||
|
|
||||||
printf ("Socket created\n");
|
printf ("Socket created\n");
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
addr.sin_family = AF_INET;
|
addr.sin_family = AF_INET;
|
||||||
addr.sin_port = htons (port);
|
addr.sin_port = htons (port);
|
||||||
memset (&addr.sin_addr, 0, sizeof (addr.sin_addr));
|
memset (&addr.sin_addr, 0, sizeof (addr.sin_addr));
|
||||||
|
@ -25,8 +25,8 @@ data_source_t * socket_server_create_unix(char *path);
|
|||||||
*/
|
*/
|
||||||
void socket_server_register_process_callback( int (*process_callback)(struct data_source *ds, int ready) );
|
void socket_server_register_process_callback( int (*process_callback)(struct data_source *ds, int ready) );
|
||||||
|
|
||||||
int socket_server_send_event_all(uint8_t *packet, uint16_t size);
|
void socket_server_send_event_all(uint8_t *packet, uint16_t size);
|
||||||
int socket_server_send_acl_all(uint8_t *packet, uint16_t size);
|
void socket_server_send_acl_all(uint8_t *packet, uint16_t size);
|
||||||
|
|
||||||
// send ACL packet
|
// send ACL packet
|
||||||
int hci_send_acl_packet(uint8_t *packet, int size);
|
int hci_send_acl_packet(uint8_t *packet, int size);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user