l2cap.c (1b3d75dd09bd13fc456e9ad04b08496c01e79c6f) l2cap.c (f3cc96b2bc44d02238c180af869980c7f264a90a)
1/*
2 * Copyright (C) 2014 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 3070 unchanged lines hidden (view full) ---

3079 //@TODO: implement other signaling packets, e.g. re-configure
3080 break;
3081 default:
3082 break;
3083 }
3084 // log_info("new state %u", channel->state);
3085}
3086
1/*
2 * Copyright (C) 2014 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright

--- 3070 unchanged lines hidden (view full) ---

3079 //@TODO: implement other signaling packets, e.g. re-configure
3080 break;
3081 default:
3082 break;
3083 }
3084 // log_info("new state %u", channel->state);
3085}
3086
3087static void l2cap_handle_information_request_complete(hci_connection_t * connection){
3087
3088
3089 connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE;
3090
3091 // trigger connection request
3092 btstack_linked_list_iterator_t it;
3093 btstack_linked_list_iterator_init(&it, &l2cap_channels);
3094 while (btstack_linked_list_iterator_has_next(&it)){
3095 l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
3096 if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue;
3097 if (channel->con_handle != connection->con_handle) continue;
3098
3099 // incoming connection: ask user for channel configuration, esp. if ertm will be mandatory
3100 if (channel->state == L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES){
3101 channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
3102 l2cap_emit_incoming_connection(channel);
3103 continue;
3104 }
3105
3106 // outgoing connection
3107 if (channel->state == L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES){
3108
3109#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
3110 // if ERTM was requested, but is not listed in extended feature mask:
3111 if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){
3112
3113 if (channel->ertm_mandatory){
3114 // bail if ERTM is mandatory
3115 channel->state = L2CAP_STATE_CLOSED;
3116 // map l2cap connection response result to BTstack status enumeration
3117 l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTED);
3118 // discard channel
3119 btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel);
3120 l2cap_free_channel_entry(channel);
3121 continue;
3122
3123 } else {
3124 // fallback to Basic mode
3125 l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED);
3126 channel->mode = L2CAP_CHANNEL_MODE_BASIC;
3127 }
3128 }
3129#endif
3130
3131 // respond to connection request
3132 channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
3133 continue;
3134 }
3135 }
3136}
3137
3138
3088// @pre command len is valid, see check in l2cap_acl_classic_handler
3089static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t * command){
3139// @pre command len is valid, see check in l2cap_acl_classic_handler
3140static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t * command){
3090
3091 btstack_linked_list_iterator_t it;
3092
3093 // get code, signalind identifier and command len
3094 uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET];
3095 uint8_t sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET];
3096 uint16_t cmd_len = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET);
3097
3098 // not for a particular channel, and not CONNECTION_REQUEST, ECHO_[REQUEST|RESPONSE], INFORMATION_RESPONSE
3099 if ((code < 1) || (code == ECHO_RESPONSE) || (code > INFORMATION_RESPONSE)){

--- 36 unchanged lines hidden (view full) ---

3136 // get extended features from response if valid
3137 connection->l2cap_state.extended_feature_mask = 0;
3138 if (cmd_len >= 6) {
3139 uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
3140 uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2);
3141 if (result == 0 && info_type == L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED) {
3142 connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4);
3143 }
3141
3142 // get code, signalind identifier and command len
3143 uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET];
3144 uint8_t sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET];
3145 uint16_t cmd_len = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET);
3146
3147 // not for a particular channel, and not CONNECTION_REQUEST, ECHO_[REQUEST|RESPONSE], INFORMATION_RESPONSE
3148 if ((code < 1) || (code == ECHO_RESPONSE) || (code > INFORMATION_RESPONSE)){

--- 36 unchanged lines hidden (view full) ---

3185 // get extended features from response if valid
3186 connection->l2cap_state.extended_feature_mask = 0;
3187 if (cmd_len >= 6) {
3188 uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
3189 uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2);
3190 if (result == 0 && info_type == L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED) {
3191 connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4);
3192 }
3193 log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask);
3144 }
3194 }
3145 connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE;
3146 log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask);
3147
3195
3148 // trigger connection request
3149 btstack_linked_list_iterator_init(&it, &l2cap_channels);
3150 while (btstack_linked_list_iterator_has_next(&it)){
3151 l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
3152 if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue;
3153 if (channel->con_handle != handle) continue;
3154
3155 // incoming connection: ask user for channel configuration, esp. if ertm will be mandatory
3156 if (channel->state == L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES){
3157 channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
3158 l2cap_emit_incoming_connection(channel);
3159 continue;
3160 }
3161
3162 // outgoing connection
3163 if (channel->state == L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES){
3164
3165 // if ERTM was requested, but is not listed in extended feature mask:
3166 if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){
3167
3168 if (channel->ertm_mandatory){
3169 // bail if ERTM is mandatory
3170 channel->state = L2CAP_STATE_CLOSED;
3171 // map l2cap connection response result to BTstack status enumeration
3172 l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTED);
3173 // discard channel
3174 btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel);
3175 l2cap_free_channel_entry(channel);
3176 continue;
3177
3178 } else {
3179 // fallback to Basic mode
3180 l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED);
3181 channel->mode = L2CAP_CHANNEL_MODE_BASIC;
3182 }
3183 }
3184
3185 // respond to connection request
3186 channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
3187 continue;
3188 }
3189 }
3196 // information request complete
3197 l2cap_handle_information_request_complete(connection);
3190 return;
3191 }
3192#endif
3193
3194 default:
3195 break;
3196 }
3197
3198 // Get potential destination CID
3199 uint16_t dest_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
3200
3201 // Find channel for this sig_id and connection handle
3198 return;
3199 }
3200#endif
3201
3202 default:
3203 break;
3204 }
3205
3206 // Get potential destination CID
3207 uint16_t dest_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
3208
3209 // Find channel for this sig_id and connection handle
3210 btstack_linked_list_iterator_t it;
3202 btstack_linked_list_iterator_init(&it, &l2cap_channels);
3203 while (btstack_linked_list_iterator_has_next(&it)){
3204 l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
3205 if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue;
3206 if (channel->con_handle != handle) continue;
3207 if (code & 1) {
3208 // match odd commands (responses) by previous signaling identifier
3209 if (channel->local_sig_id == sig_id) {

--- 1225 unchanged lines hidden ---
3211 btstack_linked_list_iterator_init(&it, &l2cap_channels);
3212 while (btstack_linked_list_iterator_has_next(&it)){
3213 l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
3214 if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue;
3215 if (channel->con_handle != handle) continue;
3216 if (code & 1) {
3217 // match odd commands (responses) by previous signaling identifier
3218 if (channel->local_sig_id == sig_id) {

--- 1225 unchanged lines hidden ---