improve hci connection handling -> suppress create connection requests for connections already open and just emit connection complete event

This commit is contained in:
matthias.ringwald 2009-08-02 13:20:32 +00:00
parent 9dbf9f9329
commit c8e4258af8
8 changed files with 132 additions and 51 deletions

View File

@ -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));
}
}
}

View File

@ -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;

View File

@ -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);

100
src/hci.c
View File

@ -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);
}
}
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);
}

View File

@ -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);

View File

@ -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
*/

View File

@ -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

View File

@ -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);