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