create rfcomm_create_channel and rfcomm_create_channel_with_initial_credits that don't use connection. use in daemon

This commit is contained in:
Matthias Ringwald 2015-11-13 21:01:26 +01:00
parent bc2c4f26a4
commit 5d1e858f3a
4 changed files with 136 additions and 19 deletions

View File

@ -602,6 +602,25 @@ static void send_l2cap_connection_open_failed(connection_t * connection, bd_addr
socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
}
static void send_rfcomm_create_channel_failed(void * connection, bd_addr_t addr, uint8_t server_channel, uint8_t status){
// emit error - see rfcom.c:rfcomm_emit_channel_open_failed_outgoing_memory(..)
uint8_t event[16];
memset(event, 0, sizeof(event));
uint8_t pos = 0;
event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE;
event[pos++] = sizeof(event) - 2;
event[pos++] = status;
bt_flip_addr(&event[pos], addr); pos += 6;
bt_store_16(event, pos, 0); pos += 2;
event[pos++] = server_channel;
bt_store_16(event, pos, 0); pos += 2; // channel ID
bt_store_16(event, pos, 0); pos += 2; // max frame size
hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
socket_connection_send_packet(connection, HCI_EVENT_PACKET, 0, event, sizeof(event));
}
linked_list_gatt_client_helper_t * daemon_setup_gatt_client_request(connection_t *connection, uint8_t *packet, int track_active_connection) {
hci_con_handle_t handle = READ_BT_16(packet, 3);
log_info("daemon_setup_gatt_client_request for handle 0x%02x", handle);
@ -823,13 +842,23 @@ static int btstack_command_handler(connection_t *connection, uint8_t *packet, ui
case RFCOMM_CREATE_CHANNEL:
bt_flip_addr(addr, &packet[3]);
rfcomm_channel = packet[9];
rfcomm_create_channel_internal( connection, addr, rfcomm_channel );
status = rfcomm_create_channel(addr, rfcomm_channel, &cid);
if (status){
send_rfcomm_create_channel_failed(connection, addr, rfcomm_channel, status);
} else {
daemon_add_client_rfcomm_channel(connection, cid);
}
break;
case RFCOMM_CREATE_CHANNEL_WITH_CREDITS:
bt_flip_addr(addr, &packet[3]);
rfcomm_channel = packet[9];
rfcomm_credits = packet[10];
rfcomm_create_channel_with_initial_credits_internal( connection, addr, rfcomm_channel, rfcomm_credits );
status = rfcomm_create_channel_with_initial_credits(addr, rfcomm_channel, rfcomm_credits, &cid );
if (status){
send_rfcomm_create_channel_failed(connection, addr, rfcomm_channel, status);
} else {
daemon_add_client_rfcomm_channel(connection, cid);
}
break;
case RFCOMM_DISCONNECT:
cid = READ_BT_16(packet, 3);
@ -1306,8 +1335,11 @@ static void daemon_packet_handler(void * connection, uint8_t packet_type, uint16
daemon_retry_parked();
break;
case RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE:
if (packet[2]) break;
daemon_add_client_rfcomm_channel(connection, READ_BT_16(packet, 9));
if (packet[2]) {
daemon_remove_client_rfcomm_channel(connection, READ_BT_16(packet, 13));
} else {
daemon_add_client_rfcomm_channel(connection, READ_BT_16(packet, 13));
}
break;
case RFCOMM_EVENT_CHANNEL_CLOSED:
daemon_remove_client_rfcomm_channel(connection, READ_BT_16(packet, 2));

View File

@ -335,7 +335,7 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
if (COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel) ) {
// inq successfully cancelled
// printLine("Connecting");
l2cap_create_channel_internal(NULL, l2cap_packet_handler, keyboard, PSM_HID_INTERRUPT, 150);
l2cap_create_channel(l2cap_packet_handler, keyboard, PSM_HID_INTERRUPT, 150);
break;
}
}

View File

@ -152,13 +152,13 @@ static void rfcomm_emit_channel_opened(rfcomm_channel_t *channel, uint8_t status
channel->dlci>>1, channel->rfcomm_cid, channel->max_frame_size);
uint8_t event[16];
uint8_t pos = 0;
event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE;
event[pos++] = sizeof(event) - 2;
event[pos++] = status;
bt_flip_addr(&event[pos], channel->multiplexer->remote_addr); pos += 6;
bt_store_16(event, pos, channel->multiplexer->con_handle); pos += 2;
event[pos++] = channel->dlci >> 1;
bt_store_16(event, pos, channel->rfcomm_cid); pos += 2; // channel ID
event[pos++] = RFCOMM_EVENT_OPEN_CHANNEL_COMPLETE; // 0
event[pos++] = sizeof(event) - 2; // 1
event[pos++] = status; // 2
bt_flip_addr(&event[pos], channel->multiplexer->remote_addr); pos += 6; // 3
bt_store_16(event, pos, channel->multiplexer->con_handle); pos += 2; // 9
event[pos++] = channel->dlci >> 1; // 11
bt_store_16(event, pos, channel->rfcomm_cid); pos += 2; // 12 - channel ID
bt_store_16(event, pos, channel->max_frame_size); pos += 2; // max frame size
hci_dump_packet(HCI_EVENT_PACKET, 0, event, sizeof(event));
(*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, pos);
@ -2232,6 +2232,69 @@ void rfcomm_create_channel_internal(void * connection, bd_addr_t addr, uint8_t s
rfcomm_create_channel2(connection, addr, server_channel, 0,RFCOMM_CREDITS);
}
static uint8_t rfcomm_create_channel3(bd_addr_t addr, uint8_t server_channel, uint8_t incoming_flow_control, uint8_t initial_credits, uint16_t * out_rfcomm_cid){
log_info("RFCOMM_CREATE_CHANNEL addr %s channel #%u init credits %u", bd_addr_to_str(addr), server_channel, initial_credits);
// create new multiplexer if necessary
uint8_t status = 0;
int new_multiplexer = 0;
rfcomm_channel_t * channel = NULL;
rfcomm_multiplexer_t * multiplexer = rfcomm_multiplexer_for_addr(addr);
if (!multiplexer) {
multiplexer = rfcomm_multiplexer_create_for_addr(addr);
if (!multiplexer){
status = BTSTACK_MEMORY_ALLOC_FAILED;
goto fail;
}
multiplexer->outgoing = 1;
multiplexer->state = RFCOMM_MULTIPLEXER_W4_CONNECT;
new_multiplexer = 1;
}
// prepare channel
channel = rfcomm_channel_create(multiplexer, NULL, server_channel);
if (!channel){
status = BTSTACK_MEMORY_ALLOC_FAILED;
goto fail;
}
// rfcomm_cid is already assigned by rfcomm_channel_create
channel->incoming_flow_control = incoming_flow_control;
channel->new_credits_incoming = initial_credits;
// return rfcomm_cid
*out_rfcomm_cid = channel->rfcomm_cid;
// start multiplexer setup
if (multiplexer->state != RFCOMM_MULTIPLEXER_OPEN) {
channel->state = RFCOMM_CHANNEL_W4_MULTIPLEXER;
uint16_t l2cap_cid = 0;
status = l2cap_create_channel(rfcomm_packet_handler, addr, PSM_RFCOMM, l2cap_max_mtu(), &l2cap_cid);
if (status) goto fail;
multiplexer->l2cap_cid = l2cap_cid;
return 0;
}
channel->state = RFCOMM_CHANNEL_SEND_UIH_PN;
// start connecting, if multiplexer is already up and running
rfcomm_run();
return 0;
fail:
if (new_multiplexer) btstack_memory_rfcomm_multiplexer_free(multiplexer);
if (channel) btstack_memory_rfcomm_channel_free(channel);
return status;
}
uint8_t rfcomm_create_channel_with_initial_credits(bd_addr_t addr, uint8_t server_channel, uint8_t initial_credits, uint16_t * out_rfcomm_cid){
return rfcomm_create_channel3(addr, server_channel, 1, initial_credits, out_rfcomm_cid);
}
uint8_t rfcomm_create_channel(bd_addr_t addr, uint8_t server_channel, uint16_t * out_rfcomm_cid){
return rfcomm_create_channel3(addr, server_channel, 0, RFCOMM_CREDITS, out_rfcomm_cid);
}
void rfcomm_disconnect_internal(uint16_t rfcomm_cid){
log_info("RFCOMM_DISCONNECT cid 0x%02x", rfcomm_cid);
rfcomm_channel_t * channel = rfcomm_channel_for_rfcomm_cid(rfcomm_cid);
@ -2243,7 +2306,6 @@ void rfcomm_disconnect_internal(uint16_t rfcomm_cid){
rfcomm_run();
}
static void rfcomm_register_service2(void * connection, uint8_t channel, uint16_t max_frame_size, uint8_t incoming_flow_control, uint8_t initial_credits){
log_info("RFCOMM_REGISTER_SERVICE channel #%u mtu %u flow_control %u credits %u",
channel, max_frame_size, incoming_flow_control, initial_credits);

View File

@ -382,15 +382,26 @@ void rfcomm_set_required_security_level(gap_security_level_t security_level);
*/
void rfcomm_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size));
/**
* @brief Creates RFCOMM connection (channel) to a given server channel on a remote device with baseband address. A new baseband connection will be initiated if necessary. This channel will automatically provide enough credits to the remote side
/*
* @brief Create RFCOMM connection to a given server channel on a remote deivce.
* This channel will automatically provide enough credits to the remote side.
* @param addr
* @param server_channel
* @param out_cid
* @result status
*/
void rfcomm_create_channel_internal(void * connection, bd_addr_t addr, uint8_t channel);
uint8_t rfcomm_create_channel(bd_addr_t addr, uint8_t server_channel, uint16_t * out_cid);
/**
* @brief Creates RFCOMM connection (channel) to a given server channel on a remote device with baseband address. new baseband connection will be initiated if necessary. This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided.
/*
* @brief Create RFCOMM connection to a given server channel on a remote deivce.
* This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided.
* @param addr
* @param server_channel
* @param initial_credits
* @param out_cid
* @result status
*/
void rfcomm_create_channel_with_initial_credits_internal(void * connection, bd_addr_t addr, uint8_t server_channel, uint8_t initial_credits);
uint8_t rfcomm_create_channel_with_initial_credits(bd_addr_t addr, uint8_t server_channel, uint8_t initial_credits, uint16_t * out_cid);
/**
* @brief Disconnects RFCOMM channel with given identifier.
@ -463,6 +474,18 @@ uint16_t rfcomm_get_max_frame_size(uint16_t rfcomm_cid);
int rfcomm_send_prepared(uint16_t rfcomm_cid, uint16_t len);
/* API_END */
// depreccated
/**
* @brief Creates RFCOMM connection (channel) to a given server channel on a remote device with baseband address. A new baseband connection will be initiated if necessary. This channel will automatically provide enough credits to the remote side
*/
void rfcomm_create_channel_internal(void * connection, bd_addr_t addr, uint8_t channel);
/**
* @brief Creates RFCOMM connection (channel) to a given server channel on a remote device with baseband address. new baseband connection will be initiated if necessary. This channel will use explicit credit management. During channel establishment, an initial amount of credits is provided.
*/
void rfcomm_create_channel_with_initial_credits_internal(void * connection, bd_addr_t addr, uint8_t server_channel, uint8_t initial_credits);
#if defined __cplusplus
}
#endif