l2cap ertm: allow SDU of szie MPS in first packet that contains L2CAP SDU Length

This commit is contained in:
Matthias Ringwald 2018-10-03 17:16:00 +02:00
parent 031381f9e3
commit f6fb536452
8 changed files with 44 additions and 20 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed ### Fixed
- L2CAP: fix issue with outgoing connection before read remote supported complete when other channels exist - L2CAP: fix issue with outgoing connection before read remote supported complete when other channels exist
- L2CAP ERTM: allow SDU of szie MPS in first packet that contains L2CAP SDU Length
- HFP: decline incoming RFCOMM connection after outgoing connection was started - HFP: decline incoming RFCOMM connection after outgoing connection was started
## Changes September 2018 ## Changes September 2018

View File

@ -160,7 +160,7 @@ static void le_streamer_setup(void){
uint8_t adv_type = 0; uint8_t adv_type = 0;
bd_addr_t null_addr; bd_addr_t null_addr;
memset(null_addr, 0, 6); memset(null_addr, 0, 6);
gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 0x07, 0x00); gap_advertisements_set_params(adv_int_min, adv_int_max, adv_type, 0, null_addr, 1, 0x00);
gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data); gap_advertisements_set_data(adv_data_len, (uint8_t*) adv_data);
gap_advertisements_enable(1); gap_advertisements_enable(1);

View File

@ -221,7 +221,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
// service query complete, look for characteristic // service query complete, look for characteristic
state = TC_W4_CHARACTERISTIC_RX_RESULT; state = TC_W4_CHARACTERISTIC_RX_RESULT;
printf("Search for LE Streamer RX characteristic.\n"); printf("Search for LE Streamer RX characteristic.\n");
gatt_client_discover_characteristics_for_service_by_uuid128(handle_gatt_client_event, connection_handle, &le_streamer_service, le_streamer_characteristic_rx_uuid); gatt_client_discover_characteristics_for_service_by_uuid16(handle_gatt_client_event, connection_handle, &le_streamer_service, 0xff01);
break; break;
default: default:
break; break;
@ -240,7 +240,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint
break; break;
} }
// rx characteristiic found, look for tx characteristic // rx characteristiic found, look for tx characteristic
state = TC_W4_CHARACTERISTIC_TX_RESULT; state = TC_W4_CHARACTERISTIC_RX_RESULT;
printf("Search for LE Streamer TX characteristic.\n"); printf("Search for LE Streamer TX characteristic.\n");
gatt_client_discover_characteristics_for_service_by_uuid128(handle_gatt_client_event, connection_handle, &le_streamer_service, le_streamer_characteristic_tx_uuid); gatt_client_discover_characteristics_for_service_by_uuid128(handle_gatt_client_event, connection_handle, &le_streamer_service, le_streamer_characteristic_tx_uuid);
break; break;
@ -362,7 +362,7 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
case GAP_EVENT_ADVERTISING_REPORT: case GAP_EVENT_ADVERTISING_REPORT:
if (state != TC_W4_SCAN_RESULT) return; if (state != TC_W4_SCAN_RESULT) return;
// check name in advertisement // check name in advertisement
if (!advertisement_report_contains_name("LE Streamer", packet)) return; if (!advertisement_report_contains_name("ESP_GATTS_DEMO", packet)) return;
// store address and type // store address and type
gap_event_advertising_report_get_address(packet, le_streamer_addr); gap_event_advertising_report_get_address(packet, le_streamer_addr);
le_streamer_addr_type = gap_event_advertising_report_get_address_type(packet); le_streamer_addr_type = gap_event_advertising_report_get_address_type(packet);
@ -385,7 +385,8 @@ static void hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
// query primary services // query primary services
printf("Search for LE Streamer service.\n"); printf("Search for LE Streamer service.\n");
state = TC_W4_SERVICE_RESULT; state = TC_W4_SERVICE_RESULT;
gatt_client_discover_primary_services_by_uuid128(handle_gatt_client_event, connection_handle, le_streamer_service_uuid); gatt_client_discover_primary_services_by_uuid16(handle_gatt_client_event, connection_handle, 0x00ff);
// gatt_client_discover_primary_services_by_uuid128(handle_gatt_client_event, connection_handle, le_streamer_service_uuid);
break; break;
case HCI_EVENT_DISCONNECTION_COMPLETE: case HCI_EVENT_DISCONNECTION_COMPLETE:
// unregister listener // unregister listener

View File

@ -72,7 +72,7 @@ static bd_addr_t remote_addr;
// Nexus 7 "30-85-A9-54-2E-78" // Nexus 7 "30-85-A9-54-2E-78"
// iPhone SE "BC:EC:5D:E6:15:03" // iPhone SE "BC:EC:5D:E6:15:03"
// PTS "001BDC080AA5" // PTS "001BDC080AA5"
static char * remote_addr_string = "BC:EC:5D:E6:15:03"; static char * remote_addr_string = "001BDC080AA5";
static char * phone_number = "911"; static char * phone_number = "911";

View File

@ -59,7 +59,7 @@
static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void handle_query_rfcomm_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
// static bd_addr_t remote = {0x04,0x0C,0xCE,0xE4,0x85,0xD3}; // static bd_addr_t remote = {0x04,0x0C,0xCE,0xE4,0x85,0xD3};
static bd_addr_t remote = {0x84, 0x38, 0x35, 0x65, 0xD1, 0x15}; static bd_addr_t remote = {0x00, 0x1A, 0x7D, 0xDA, 0x71, 0x01};
static uint8_t service_index = 0; static uint8_t service_index = 0;
static uint8_t channel_nr[10]; static uint8_t channel_nr[10];

View File

@ -60,7 +60,7 @@
// goep_client.c // goep_client.c
// //
// #define ENABLE_GOEP_L2CAP #define ENABLE_GOEP_L2CAP
typedef enum { typedef enum {
GOEP_INIT, GOEP_INIT,
@ -97,15 +97,15 @@ static const unsigned int attribute_value_buffer_size = sizeof(attribute_value);
static uint8_t goep_packet_buffer[100]; static uint8_t goep_packet_buffer[100];
#ifdef ENABLE_GOEP_L2CAP #ifdef ENABLE_GOEP_L2CAP
static uint8_t ertm_buffer[1000]; static uint8_t ertm_buffer[2000];
static l2cap_ertm_config_t ertm_config = { static l2cap_ertm_config_t ertm_config = {
1, // ertm mandatory 1, // ertm mandatory
2, // max transmit, some tests require > 1 2, // max transmit, some tests require > 1
2000, 2000,
12000, 12000,
144, // l2cap ertm mtu 250, // l2cap ertm mtu
4, 2,
4, 2,
}; };
#endif #endif
@ -376,7 +376,7 @@ static void goep_client_add_variable_header(uint16_t goep_cid, uint8_t header_ty
goep_client_packet_append(header_data, header_data_length); goep_client_packet_append(header_data, header_data_length);
} }
#if 0 #if 1
static void goep_client_add_byte_header(uint16_t goep_cid, uint8_t header_type, uint8_t value){ static void goep_client_add_byte_header(uint16_t goep_cid, uint8_t header_type, uint8_t value){
UNUSED(goep_cid); UNUSED(goep_cid);
uint8_t header[2]; uint8_t header[2];
@ -481,7 +481,7 @@ void goep_client_create_disconnect_request(uint16_t goep_cid){
void goep_client_create_get_request(uint16_t goep_cid){ void goep_client_create_get_request(uint16_t goep_cid){
goep_client_packet_init(goep_cid, OBEX_OPCODE_GET | OBEX_OPCODE_FINAL_BIT_MASK); goep_client_packet_init(goep_cid, OBEX_OPCODE_GET | OBEX_OPCODE_FINAL_BIT_MASK);
goep_client_packet_add_connection_id(goep_cid); goep_client_packet_add_connection_id(goep_cid);
// goep_client_add_byte_header(goep_cid, OBEX_HEADER_SINGLE_RESPONSE_MODE, 0x01); goep_client_add_byte_header(goep_cid, OBEX_HEADER_SINGLE_RESPONSE_MODE, 0x01);
} }
void goep_client_create_set_path_request(uint16_t goep_cid, uint8_t flags){ void goep_client_create_set_path_request(uint16_t goep_cid, uint8_t flags){

View File

@ -279,8 +279,8 @@ static void pbap_handle_can_send_now(void){
case PBAP_W2_PULL_PHONEBOOK: case PBAP_W2_PULL_PHONEBOOK:
case PBAP_W2_GET_PHONEBOOK_SIZE: case PBAP_W2_GET_PHONEBOOK_SIZE:
goep_client_create_get_request(pbap_client->goep_cid); goep_client_create_get_request(pbap_client->goep_cid);
goep_client_add_header_name(pbap_client->goep_cid, "telecom/pb.vcf");
goep_client_add_header_type(pbap_client->goep_cid, pbap_phonebook_type); goep_client_add_header_type(pbap_client->goep_cid, pbap_phonebook_type);
goep_client_add_header_name(pbap_client->goep_cid, pbap_phonebook_name);
if (pbap_client->state == PBAP_W2_GET_PHONEBOOK_SIZE){ if (pbap_client->state == PBAP_W2_GET_PHONEBOOK_SIZE){
// Regular TLV wih 1-byte len // Regular TLV wih 1-byte len
application_parameters[0] = PBAP_APPLICATION_PARAMETER_MAX_LIST_COUNT; application_parameters[0] = PBAP_APPLICATION_PARAMETER_MAX_LIST_COUNT;
@ -290,6 +290,13 @@ static void pbap_handle_can_send_now(void){
// state // state
pbap_client->state = PBAP_W4_GET_PHONEBOOK_SIZE_COMPLETE; pbap_client->state = PBAP_W4_GET_PHONEBOOK_SIZE_COMPLETE;
} else { } else {
#if 1
// Regular TLV wih 1-byte len
application_parameters[0] = PBAP_APPLICATION_PARAMETER_MAX_LIST_COUNT;
application_parameters[1] = 2;
big_endian_store_16(application_parameters, 2, 0xffff);
goep_client_add_header_application_parameters(pbap_client->goep_cid, 4, &application_parameters[0]);
#endif
// state // state
pbap_client->state = PBAP_W4_PHONEBOOK; pbap_client->state = PBAP_W4_PHONEBOOK;
} }

View File

@ -3200,11 +3200,26 @@ static void l2cap_acl_classic_handler(hci_con_handle_t handle, uint8_t *packet,
} }
// get SDU // get SDU
const uint8_t * sdu_data = &packet[COMPLETE_L2CAP_HEADER+2]; const uint8_t * payload_data = &packet[COMPLETE_L2CAP_HEADER+2];
uint16_t sdu_len = size-(COMPLETE_L2CAP_HEADER+2+fcs_size); uint16_t payload_len = size-(COMPLETE_L2CAP_HEADER+2+fcs_size);
// assert SDU size is smaller or equal to our buffers // assert SDU size is smaller or equal to our buffers
if (sdu_len > l2cap_channel->local_mps) break; uint16_t max_payload_size = 0;
switch (sar){
case L2CAP_SEGMENTATION_AND_REASSEMBLY_UNSEGMENTED_L2CAP_SDU:
case L2CAP_SEGMENTATION_AND_REASSEMBLY_START_OF_L2CAP_SDU:
// SDU Length + MPS
max_payload_size = l2cap_channel->local_mps + 2;
break;
case L2CAP_SEGMENTATION_AND_REASSEMBLY_CONTINUATION_OF_L2CAP_SDU:
case L2CAP_SEGMENTATION_AND_REASSEMBLY_END_OF_L2CAP_SDU:
max_payload_size = l2cap_channel->local_mps;
break;
}
if (payload_len > max_payload_size){
log_info("payload len %u > max payload %u -> drop packet", payload_len, max_payload_size);
break;
}
// check ordering // check ordering
if (l2cap_channel->expected_tx_seq == tx_seq){ if (l2cap_channel->expected_tx_seq == tx_seq){
@ -3213,7 +3228,7 @@ static void l2cap_acl_classic_handler(hci_con_handle_t handle, uint8_t *packet,
l2cap_channel->req_seq = l2cap_channel->expected_tx_seq; l2cap_channel->req_seq = l2cap_channel->expected_tx_seq;
// process SDU // process SDU
l2cap_ertm_handle_in_sequence_sdu(l2cap_channel, sar, sdu_data, sdu_len); l2cap_ertm_handle_in_sequence_sdu(l2cap_channel, sar, payload_data, payload_len);
// process stored segments // process stored segments
while (1){ while (1){
@ -3243,7 +3258,7 @@ static void l2cap_acl_classic_handler(hci_con_handle_t handle, uint8_t *packet,
int delta = (tx_seq - l2cap_channel->expected_tx_seq) & 0x3f; int delta = (tx_seq - l2cap_channel->expected_tx_seq) & 0x3f;
if (delta < 2){ if (delta < 2){
// store segment // store segment
l2cap_ertm_handle_out_of_sequence_sdu(l2cap_channel, sar, delta, sdu_data, sdu_len); l2cap_ertm_handle_out_of_sequence_sdu(l2cap_channel, sar, delta, payload_data, payload_len);
log_info("Received unexpected frame TxSeq %u but expected %u -> send S-SREJ", tx_seq, l2cap_channel->expected_tx_seq); log_info("Received unexpected frame TxSeq %u but expected %u -> send S-SREJ", tx_seq, l2cap_channel->expected_tx_seq);
l2cap_channel->send_supervisor_frame_selective_reject = 1; l2cap_channel->send_supervisor_frame_selective_reject = 1;