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