diff --git a/project.xcodeproj/project.pbxproj b/project.xcodeproj/project.pbxproj index 0cfd264e7..4a8556492 100644 --- a/project.xcodeproj/project.pbxproj +++ b/project.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 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 */; }; 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 */; }; 9C7ECBB50FCC95DD0085DAC5 /* hci_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECBB40FCC95DD0085DAC5 /* hci_dump.c */; }; 9C88500E0FBF6702004980E4 /* l2cap.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C88500C0FBF6702004980E4 /* l2cap.c */; }; @@ -199,7 +198,6 @@ 9CC813A50FFC0A51002816F9 /* daemon.c in Sources */, 9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */, 9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */, - 9C7B5B7F100D04450065D87E /* test.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/src/btstack.c b/src/btstack.c index 7dc20d81d..04ba14452 100644 --- a/src/btstack.c +++ b/src/btstack.c @@ -8,25 +8,168 @@ #include "btstack.h" +#include "run_loop.h" +#include +#include +#include +#include + +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 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 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 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 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 void bt_register_event_packet_handler(void (*handler)(uint8_t *packet, int size)){ -} -void bt_register_acl_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)){ + acl_packet_handler = handler; } diff --git a/src/hci.c b/src/hci.c index cf6221875..91d0d4de2 100644 --- a/src/hci.c +++ b/src/hci.c @@ -159,7 +159,7 @@ static hci_connection_t *link_for_addr(bd_addr_t addr){ /** * 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){ @@ -213,10 +213,10 @@ static void event_handler(uint8_t *packet, int size){ } /** 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; } -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; } @@ -345,17 +345,12 @@ int hci_send_cmd_packet(uint8_t *packet, int size){ return hci_stack.hci_transport->send_cmd_packet(packet, size); } -/** - * 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; +uint16_t hci_create_cmd_internal(uint8_t *hci_cmd_buffer, hci_cmd_t *cmd, va_list argptr){ + hci_cmd_buffer[0] = cmd->opcode & 0xff; hci_cmd_buffer[1] = cmd->opcode >> 8; int pos = 3; - - va_list argptr; - va_start(argptr, cmd); + const char *format = cmd->format; uint16_t word; uint32_t longword; @@ -413,7 +408,26 @@ int hci_send_cmd(hci_cmd_t *cmd, ...){ } format++; }; - va_end(argptr); 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); } \ No newline at end of file diff --git a/src/hci.h b/src/hci.h index 4e6415c09..2020d5fea 100644 --- a/src/hci.h +++ b/src/hci.h @@ -9,6 +9,7 @@ #include #include +#include #include "hci_transport.h" #include "bt_control.h" @@ -143,8 +144,8 @@ typedef struct { uint8_t num_acl_packets; /* callback to L2CAP layer */ - void (*event_packet_handler)(uint8_t *packet, int size); - void (*acl_packet_handler) (uint8_t *packet, int size); + void (*event_packet_handler)(uint8_t *packet, uint16_t size); + void (*acl_packet_handler) (uint8_t *packet, uint16_t size); /* hci state machine */ HCI_STATE state; @@ -157,9 +158,9 @@ typedef struct { // set up HCI 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 int hci_power_control(HCI_POWER_MODE mode); @@ -174,7 +175,9 @@ uint32_t hci_run(); // 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_packet(uint8_t *packet, int size); diff --git a/src/socket_server.c b/src/socket_server.c index 2d3df1e9a..47e22a37b 100644 --- a/src/socket_server.c +++ b/src/socket_server.c @@ -145,12 +145,14 @@ int socket_server_send_packet_all(uint8_t type, uint8_t *packet, uint16_t size){ return 0; } -int socket_server_send_event_all(uint8_t *packet, uint16_t size){ - return socket_server_send_packet_all( HCI_EVENT_PACKET, packet, size); +void socket_server_send_event_all(uint8_t *packet, uint16_t size){ + socket_server_send_packet_all( HCI_EVENT_PACKET, packet, size); + return; } -int socket_server_send_acl_all(uint8_t *packet, uint16_t size){ - return socket_server_send_packet_all( HCI_ACL_DATA_PACKET, packet, size); +void socket_server_send_acl_all(uint8_t *packet, uint16_t 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; // create tcp socket - struct sockaddr_in addr; if ((ds->fd = socket (PF_INET, SOCK_STREAM, 0)) < 0) { printf ("Error creating socket ...(%s)\n", strerror(errno)); free(ds); @@ -211,6 +212,7 @@ data_source_t * socket_server_create_tcp(int port){ printf ("Socket created\n"); + struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (port); memset (&addr.sin_addr, 0, sizeof (addr.sin_addr)); diff --git a/src/socket_server.h b/src/socket_server.h index 3231c8e0f..5a468632d 100644 --- a/src/socket_server.h +++ b/src/socket_server.h @@ -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) ); -int 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_event_all(uint8_t *packet, uint16_t size); +void socket_server_send_acl_all(uint8_t *packet, uint16_t size); // send ACL packet int hci_send_acl_packet(uint8_t *packet, int size);