l2cap.c (b90eac910b0b2b6602bcf13f378371bb03d224a7) | l2cap.c (0defadfba97943ba06456750b9da8b2f958277a2) |
---|---|
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 --- 2737 unchanged lines hidden (view full) --- 2746 l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN); 2747 } 2748 return; 2749 2750#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 2751 case INFORMATION_RESPONSE: { 2752 hci_connection_t * connection = hci_connection_for_handle(handle); 2753 if (!connection) return; | 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 --- 2737 unchanged lines hidden (view full) --- 2746 l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN); 2747 } 2748 return; 2749 2750#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE 2751 case INFORMATION_RESPONSE: { 2752 hci_connection_t * connection = hci_connection_for_handle(handle); 2753 if (!connection) return; |
2754 if (cmd_len >= 4) { | 2754 if (connection->l2cap_state.information_state != L2CAP_INFORMATION_STATE_W4_EXTENDED_FEATURE_RESPONSE) return; 2755 2756 // get extended features from response if valid 2757 connection->l2cap_state.extended_feature_mask = 0; 2758 if (cmd_len >= 6) { |
2755 uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); | 2759 uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET); |
2756 uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2); 2757 if (result != 0) return; 2758 if (info_type != L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED) return; 2759 if (cmd_len >= 6) { 2760 connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE; | 2760 uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2); 2761 if (result == 0 && info_type == L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED) { |
2761 connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); | 2762 connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4); |
2762 log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask); 2763 // trigger connection request 2764 btstack_linked_list_iterator_init(&it, &l2cap_channels); 2765 while (btstack_linked_list_iterator_has_next(&it)){ 2766 l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2767 if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2768 if (channel->con_handle != handle) continue; 2769 // bail if ERTM was requested but is not supported 2770 if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){ 2771 if (channel->ertm_mandatory){ 2772 // channel closed 2773 channel->state = L2CAP_STATE_CLOSED; 2774 // map l2cap connection response result to BTstack status enumeration 2775 l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTED); 2776 // discard channel 2777 btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 2778 l2cap_free_channel_entry(channel); 2779 continue; 2780 } else { 2781 // fallback to Basic mode 2782 l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED); 2783 channel->mode = L2CAP_CHANNEL_MODE_BASIC; 2784 } 2785 } 2786 // start connecting 2787 if (channel->state == L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES){ 2788 channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST; 2789 } 2790 // respond to connection request 2791 if (channel->state == L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES){ 2792 channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; 2793 l2cap_emit_incoming_connection(channel); 2794 } | 2763 } 2764 } 2765 connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE; 2766 log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask); 2767 2768 // trigger connection request 2769 btstack_linked_list_iterator_init(&it, &l2cap_channels); 2770 while (btstack_linked_list_iterator_has_next(&it)){ 2771 l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it); 2772 if (!l2cap_is_dynamic_channel_type(channel->channel_type)) continue; 2773 if (channel->con_handle != handle) continue; 2774 // bail if ERTM was requested but is not supported 2775 if ((channel->mode == L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION) && ((connection->l2cap_state.extended_feature_mask & 0x08) == 0)){ 2776 if (channel->ertm_mandatory){ 2777 // channel closed 2778 channel->state = L2CAP_STATE_CLOSED; 2779 // map l2cap connection response result to BTstack status enumeration 2780 l2cap_handle_channel_open_failed(channel, L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTED); 2781 // discard channel 2782 btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel); 2783 l2cap_free_channel_entry(channel); 2784 continue; 2785 } else { 2786 // fallback to Basic mode 2787 l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_ERTM_BUFFER_RELEASED); 2788 channel->mode = L2CAP_CHANNEL_MODE_BASIC; |
2795 } | 2789 } |
2796 return; // cmd len valid | |
2797 } | 2790 } |
2791 // start connecting 2792 if (channel->state == L2CAP_STATE_WAIT_OUTGOING_EXTENDED_FEATURES){ 2793 channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST; 2794 } 2795 // respond to connection request 2796 if (channel->state == L2CAP_STATE_WAIT_INCOMING_EXTENDED_FEATURES){ 2797 channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT; 2798 l2cap_emit_incoming_connection(channel); 2799 } |
|
2798 } | 2800 } |
2799 l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN); | |
2800 return; 2801 } 2802#endif 2803 2804 default: 2805 break; 2806 } 2807 --- 1085 unchanged lines hidden --- | 2801 return; 2802 } 2803#endif 2804 2805 default: 2806 break; 2807 } 2808 --- 1085 unchanged lines hidden --- |