From c8e4258af80ac01c2b8c90df5fb94a264ad985db Mon Sep 17 00:00:00 2001 From: "matthias.ringwald" Date: Sun, 2 Aug 2009 13:20:32 +0000 Subject: [PATCH] improve hci connection handling -> suppress create connection requests for connections already open and just emit connection complete event --- example/test.c | 21 +++++-- project.xcodeproj/project.pbxproj | 14 +---- src/daemon.c | 4 +- src/hci.c | 100 +++++++++++++++++++++++------- src/hci.h | 18 +++++- src/hci_cmds.h | 2 + src/l2cap.c | 23 ++++--- src/l2cap.h | 1 + 8 files changed, 132 insertions(+), 51 deletions(-) diff --git a/example/test.c b/example/test.c index b6a005380..c82c3c164 100644 --- a/example/test.c +++ b/example/test.c @@ -46,12 +46,23 @@ void event_handler(uint8_t *packet, uint16_t size){ // inform about new l2cap connection if (packet[0] == HCI_EVENT_L2CAP_CHANNEL_OPENED){ - uint16_t source_cid = READ_BT_16(packet, 4); - printf("Channel successfully opened, handle 0x%02x, source cid 0x%02x, dest cid 0x%02x\n", READ_BT_16(packet, 2), source_cid, READ_BT_16(packet, 6));; + bd_addr_t addr; + bt_flip_addr(addr, &packet[2]); + uint16_t psm = READ_BT_16(packet, 10); + uint16_t source_cid = READ_BT_16(packet, 8); + printf("Channel successfully opened: "); + print_bd_addr(addr); + printf(", handle 0x%02x, psm 0x%02x, source cid 0x%02x, dest cid 0x%02x\n", + READ_BT_16(packet, 8), psm, source_cid, READ_BT_16(packet, 14)); - // request acceleration data.. probably has to be sent to control channel 0x11 instead of 0x13 - // uint8_t setMode33[] = { 0x52, 0x12, 0x00, 0x33 }; - // l2cap_send( source_cid, setMode33, sizeof(setMode33)); + if (psm == 0x13) { + // interupt channel openedn succesfully, now open control channel, too. + bt_send_cmd(&l2cap_create_channel, addr, 0x11); + } else { + // request acceleration data.. probably has to be sent to control channel 0x11 instead of 0x13 + uint8_t setMode33[] = { 0x52, 0x12, 0x00, 0x33 }; + l2cap_send( source_cid, setMode33, sizeof(setMode33)); + } } } diff --git a/project.xcodeproj/project.pbxproj b/project.xcodeproj/project.pbxproj index 1c0250a39..9852687f0 100644 --- a/project.xcodeproj/project.pbxproj +++ b/project.xcodeproj/project.pbxproj @@ -12,27 +12,22 @@ 9C00F7D81019082F008DAB17 /* hci_cmds.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7D61019082F008DAB17 /* hci_cmds.c */; }; 9C00F86410191097008DAB17 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F86210191097008DAB17 /* utils.c */; }; 9C00F86510191097008DAB17 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F86210191097008DAB17 /* utils.c */; }; - 9C00F87310191130008DAB17 /* l2cap_signaling.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F87210191130008DAB17 /* l2cap_signaling.c */; }; 9C00F87410191130008DAB17 /* l2cap_signaling.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F87210191130008DAB17 /* l2cap_signaling.c */; }; 9C05FC971020D3F300255261 /* socket_connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7301017ACC3008DAB17 /* socket_connection.c */; }; 9C1F0E9A0FDAE023008F472F /* run_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C1F0E980FDAE023008F472F /* run_loop.c */; }; 9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C2071F210014D3200A07EA4 /* hci_transport_usb.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 */; }; 9C7B5AC0100BD3340065D87E /* linked_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5ABF100BD3340065D87E /* linked_list.c */; }; - 9C7B5D00100FC9AA0065D87E /* bt_control_iphone.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECB820FCC85650085DAC5 /* bt_control_iphone.c */; }; 9C7B5D01100FC9AE0065D87E /* btstack.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A10FFC0774002816F9 /* btstack.c */; }; - 9C7B5D02100FC9B50065D87E /* hci.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC340FA906F700ABEF05 /* hci.c */; }; 9C7B5D03100FC9BB0065D87E /* test.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5B7E100D04450065D87E /* test.c */; }; - 9C7B5D04100FC9C20065D87E /* hci_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7ECBB40FCC95DD0085DAC5 /* hci_dump.c */; }; 9C7B5D0D100FC9CE0065D87E /* linked_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C7B5ABF100BD3340065D87E /* linked_list.c */; }; 9C7B5D0E100FC9D00065D87E /* run_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C1F0E980FDAE023008F472F /* run_loop.c */; }; - 9C7B5D12100FC9F00065D87E /* l2cap.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C88500C0FBF6702004980E4 /* l2cap.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 */; }; 9CC813A20FFC0774002816F9 /* btstack.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A10FFC0774002816F9 /* btstack.c */; }; 9CC813A50FFC0A51002816F9 /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A40FFC0A51002816F9 /* daemon.c */; }; + 9CCE6CEA1025BD0000FCE9F4 /* hci.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC340FA906F700ABEF05 /* hci.c */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -236,7 +231,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9C46FC390FA906F700ABEF05 /* hci.c in Sources */, 9C46FC3A0FA906F700ABEF05 /* hci_transport_h4.c in Sources */, 9C88500E0FBF6702004980E4 /* l2cap.c in Sources */, 9C7ECB840FCC85650085DAC5 /* bt_control_iphone.c in Sources */, @@ -250,6 +244,7 @@ 9C00F7D71019082F008DAB17 /* hci_cmds.c in Sources */, 9C00F86510191097008DAB17 /* utils.c in Sources */, 9C00F87410191130008DAB17 /* l2cap_signaling.c in Sources */, + 9CCE6CEA1025BD0000FCE9F4 /* hci.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -257,17 +252,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9C7B5D00100FC9AA0065D87E /* bt_control_iphone.c in Sources */, 9C7B5D01100FC9AE0065D87E /* btstack.c in Sources */, - 9C7B5D02100FC9B50065D87E /* hci.c in Sources */, 9C7B5D03100FC9BB0065D87E /* test.c in Sources */, - 9C7B5D04100FC9C20065D87E /* hci_dump.c in Sources */, 9C7B5D0D100FC9CE0065D87E /* linked_list.c in Sources */, 9C7B5D0E100FC9D00065D87E /* run_loop.c in Sources */, - 9C7B5D12100FC9F00065D87E /* l2cap.c in Sources */, 9C00F7D81019082F008DAB17 /* hci_cmds.c in Sources */, 9C00F86410191097008DAB17 /* utils.c in Sources */, - 9C00F87310191130008DAB17 /* l2cap_signaling.c in Sources */, 9C05FC971020D3F300255261 /* socket_connection.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/src/daemon.c b/src/daemon.c index 92dfda2c8..ae4bb7526 100644 --- a/src/daemon.c +++ b/src/daemon.c @@ -112,8 +112,8 @@ int main (int argc, const char * argv[]){ // @TODO: allow configuration per HCI CMD // use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT - // hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER); - hci_dump_open(NULL, HCI_DUMP_STDOUT); + hci_dump_open("/tmp/hci_dump.pklg", HCI_DUMP_PACKETLOGGER); + // hci_dump_open(NULL, HCI_DUMP_STDOUT); // init HCI hci_init(transport, &config, control); diff --git a/src/hci.c b/src/hci.c index aedbb2937..8d8c6b344 100644 --- a/src/hci.c +++ b/src/hci.c @@ -18,6 +18,21 @@ // the STACK is here static hci_stack_t hci_stack; +/** + * create connection for given address + * + * @return connection OR NULL, if not found + */ +static hci_connection_t * create_connection_for_addr(bd_addr_t addr){ + hci_connection_t * conn = malloc( sizeof(hci_connection_t) ); + if (!conn) return NULL; + BD_ADDR_COPY(conn->address, addr); + conn->con_handle = 0xffff; + conn->flags = 0; + linked_list_add(&hci_stack.connections, (linked_item_t *) conn); + return conn; +} + /** * get connection for given address * @@ -48,6 +63,7 @@ static hci_connection_t * connection_for_handle(hci_con_handle_t con_handle){ return NULL; } + /** * Dummy handler called by HCI */ @@ -70,6 +86,7 @@ static bt_control_t null_control = { null_control_name }; + static void acl_handler(uint8_t *packet, int size){ hci_stack.acl_packet_handler(packet, size); @@ -91,15 +108,10 @@ static void event_handler(uint8_t *packet, int size){ if (packet[0] == HCI_EVENT_CONNECTION_COMPLETE) { if (!packet[2]){ bt_flip_addr(addr, &packet[5]); + printf("Connection_complete "); print_bd_addr(addr); printf("\n"); hci_connection_t * conn = connection_for_address(addr); - if (!conn) { - conn = malloc( sizeof(hci_connection_t) ); - if (conn) { - linked_list_add(&hci_stack.connections, (linked_item_t *) conn); - } - } if (conn) { - BD_ADDR_COPY(conn->address, addr); + conn->state = OPEN; conn->con_handle = READ_BT_16(packet, 3); conn->flags = 0; printf("New connection: handle %u, ", conn->con_handle); @@ -195,15 +207,6 @@ void hci_init(hci_transport_t *transport, void *config, bt_control_t *control){ transport->register_acl_packet_handler( acl_handler); } -void hci_emit_state(){ - uint8_t event[3]; - event[0] = HCI_EVENT_BTSTACK_STATE; - event[1] = 1; - event[2] = hci_stack.state; - hci_dump_packet( HCI_EVENT_PACKET, 0, event, 3); - hci_stack.event_packet_handler(event, 3); -} - int hci_power_control(HCI_POWER_MODE power_mode){ if (power_mode == HCI_POWER_ON) { @@ -285,11 +288,42 @@ int hci_send_acl_packet(uint8_t *packet, int size){ } int hci_send_cmd_packet(uint8_t *packet, int size){ - if (READ_CMD_OGF(packet) != OGF_BTSTACK) { - hci_stack.num_cmd_packets--; - return hci_stack.hci_transport->send_cmd_packet(packet, size); + bd_addr_t addr; + hci_connection_t * conn; + // house-keeping + + // create_connection? + if (IS_COMMAND(packet, hci_create_connection)){ + bt_flip_addr(addr, &packet[3]); + printf("Create_connection to "); print_bd_addr(addr); printf("\n"); + conn = connection_for_address(addr); + if (conn) { + // if connection exists + if (conn->state == OPEN) { + // if OPEN, emit connection complete command + hci_emit_connection_complete(conn); + } + // otherwise, just ignore + return 0; // don't sent packet to controller + + } else{ + conn = create_connection_for_addr(addr); + if (conn){ + // create connection struct and register, state = SENT_CREATE_CONNECTION + conn->state = SENT_CREATE_CONNECTION; + } + } } - return 0; + + // accept connection + + // reject connection + + // close_connection? + // set state = SENT_DISCONNECT + + hci_stack.num_cmd_packets--; + return hci_stack.hci_transport->send_cmd_packet(packet, size); } /** @@ -302,4 +336,28 @@ int hci_send_cmd(hci_cmd_t *cmd, ...){ 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 +} + +void hci_emit_state(){ + uint8_t len = 3; + uint8_t event[len]; + event[0] = HCI_EVENT_BTSTACK_STATE; + event[1] = 1; + event[2] = hci_stack.state; + hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); + hci_stack.event_packet_handler(event, len); +} + +void hci_emit_connection_complete(hci_connection_t *conn){ + uint8_t len = 13; + uint8_t event[len]; + event[0] = HCI_EVENT_CONNECTION_COMPLETE; + event[2] = 0; // status = OK + bt_store_16(event, 3, conn->con_handle); + bt_flip_addr(&event[5], conn->address); + event[11] = 1; // ACL connection + event[12] = 0; // encryption disabled + hci_dump_packet( HCI_EVENT_PACKET, 0, event, len); + hci_stack.event_packet_handler(event, len); +} + diff --git a/src/hci.h b/src/hci.h index 0d79cb797..7c71de85d 100644 --- a/src/hci.h +++ b/src/hci.h @@ -24,7 +24,16 @@ typedef enum { SEND_PIN_CODE_RESPONSE = 1 << 1 } hci_connection_flags_t; -typedef struct hci_connection { +typedef enum { + SENT_CREATE_CONNECTION = 1, + RECEIVED_CONNECTION_REQUEST, + ACCEPTED_CONNECTION_REQUEST, + REJECTED_CONNECTION_REQUEST, + OPEN, + SENT_DISCONNECT +} CONNECTION_STATE; + +typedef struct { // linked list - assert: first field linked_item_t item; @@ -33,9 +42,13 @@ typedef struct hci_connection { // module handle hci_con_handle_t con_handle; + + // state + CONNECTION_STATE state; // errands hci_connection_flags_t flags; + } hci_connection_t; /** @@ -81,7 +94,7 @@ void hci_register_acl_packet_handler (void (*handler)(uint8_t *packet, uint16_t int hci_power_control(HCI_POWER_MODE mode); /** - * run the hci daemon loop once + * run the hci control loop once */ void hci_run(); @@ -96,3 +109,4 @@ int hci_send_acl_packet(uint8_t *packet, int size); // void hci_emit_state(); +void hci_emit_connection_complete(hci_connection_t *conn); diff --git a/src/hci_cmds.h b/src/hci_cmds.h index e5a43c841..15d4916e9 100644 --- a/src/hci_cmds.h +++ b/src/hci_cmds.h @@ -85,6 +85,8 @@ #define COMMAND_COMPLETE_EVENT(event,cmd) ( event[0] == HCI_EVENT_COMMAND_COMPLETE && READ_BT_16(event,3) == cmd.opcode) +#define IS_COMMAND(packet, command) (READ_BT_16(packet,0) == command.opcode) + /** * Default INQ Mode */ diff --git a/src/l2cap.c b/src/l2cap.c index 0ef3e7085..56e96df28 100644 --- a/src/l2cap.c +++ b/src/l2cap.c @@ -160,21 +160,26 @@ void l2cap_signaling_handler(l2cap_channel_t *channel, uint8_t *packet, uint16_t l2cap_send_signaling_packet(channel->handle, CONFIGURE_RESPONSE, identifier, channel->dest_cid, 0, 0, size - 16, &packet[16]); channel->state = L2CAP_STATE_OPEN; - - // notify client - uint8_t event[8]; - event[0] = HCI_EVENT_L2CAP_CHANNEL_OPENED; - event[1] = 6; - bt_store_16(event, 2, channel->handle); - bt_store_16(event, 4, channel->source_cid); - bt_store_16(event, 6, channel->dest_cid); - socket_connection_send_packet(channel->connection, HCI_EVENT_PACKET, 0, event, sizeof(event)); + l2cap_emit_channel_opened(channel); break; } break; } } +// notify client +void l2cap_emit_channel_opened(l2cap_channel_t *channel) { + uint8_t event[16]; + event[0] = HCI_EVENT_L2CAP_CHANNEL_OPENED; + event[1] = sizeof(event) - 2; + bt_flip_addr(&event[2], channel->address); + bt_store_16(event, 8, channel->handle); + bt_store_16(event, 10, channel->psm); + bt_store_16(event, 12, channel->source_cid); + bt_store_16(event, 14, channel->dest_cid); + socket_connection_send_packet(channel->connection, HCI_EVENT_PACKET, 0, event, sizeof(event)); +} + void l2cap_acl_handler( uint8_t *packet, uint16_t size ){ // Get Channel ID and command code diff --git a/src/l2cap.h b/src/l2cap.h index 7f3fe3ced..71023a251 100644 --- a/src/l2cap.h +++ b/src/l2cap.h @@ -55,3 +55,4 @@ void l2cap_acl_handler( uint8_t *packet, uint16_t size ); void l2cap_event_handler( uint8_t *packet, uint16_t size ); +void l2cap_emit_channel_opened(l2cap_channel_t *channel);