13deb3ec6SMatthias Ringwald /* 23deb3ec6SMatthias Ringwald * Copyright (C) 2014 BlueKitchen GmbH 33deb3ec6SMatthias Ringwald * 43deb3ec6SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 53deb3ec6SMatthias Ringwald * modification, are permitted provided that the following conditions 63deb3ec6SMatthias Ringwald * are met: 73deb3ec6SMatthias Ringwald * 83deb3ec6SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 93deb3ec6SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 103deb3ec6SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 113deb3ec6SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 123deb3ec6SMatthias Ringwald * documentation and/or other materials provided with the distribution. 133deb3ec6SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 143deb3ec6SMatthias Ringwald * contributors may be used to endorse or promote products derived 153deb3ec6SMatthias Ringwald * from this software without specific prior written permission. 163deb3ec6SMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 173deb3ec6SMatthias Ringwald * personal benefit and not for any commercial purpose or for 183deb3ec6SMatthias Ringwald * monetary gain. 193deb3ec6SMatthias Ringwald * 203deb3ec6SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 213deb3ec6SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 223deb3ec6SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 232fca4dadSMilanka Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 242fca4dadSMilanka Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 253deb3ec6SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 263deb3ec6SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 273deb3ec6SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 283deb3ec6SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 293deb3ec6SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 303deb3ec6SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 313deb3ec6SMatthias Ringwald * SUCH DAMAGE. 323deb3ec6SMatthias Ringwald * 333deb3ec6SMatthias Ringwald * Please inquire about commercial licensing options at 343deb3ec6SMatthias Ringwald * [email protected] 353deb3ec6SMatthias Ringwald * 363deb3ec6SMatthias Ringwald */ 373deb3ec6SMatthias Ringwald 38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "bnep.c" 39ab2c6ae4SMatthias Ringwald 403deb3ec6SMatthias Ringwald /* 413deb3ec6SMatthias Ringwald * bnep.c 423deb3ec6SMatthias Ringwald * Author: Ole Reinhardt <[email protected]> 433deb3ec6SMatthias Ringwald * 443deb3ec6SMatthias Ringwald */ 453deb3ec6SMatthias Ringwald 463deb3ec6SMatthias Ringwald #include <stdint.h> 4784e3541eSMilanka Ringwald #include <string.h> // memcpy 483deb3ec6SMatthias Ringwald 4984e3541eSMilanka Ringwald #include "bluetooth_psm.h" 50235946f1SMatthias Ringwald #include "bluetooth_sdp.h" 5184e3541eSMilanka Ringwald #include "bnep.h" 520e2df43fSMatthias Ringwald #include "btstack_debug.h" 530e2df43fSMatthias Ringwald #include "btstack_event.h" 540e2df43fSMatthias Ringwald #include "btstack_memory.h" 55eb886013SMatthias Ringwald #include "btstack_util.h" 5659c6af15SMatthias Ringwald #include "classic/core.h" 573edc84c5SMatthias Ringwald #include "classic/sdp_util.h" 583deb3ec6SMatthias Ringwald #include "hci.h" 590e2df43fSMatthias Ringwald #include "hci_cmd.h" 603deb3ec6SMatthias Ringwald #include "hci_dump.h" 613deb3ec6SMatthias Ringwald #include "l2cap.h" 623deb3ec6SMatthias Ringwald 639951ad9cSMatthias Ringwald #define BNEP_EXT_FLAG 0x80 649951ad9cSMatthias Ringwald #define BNEP_TYPE_MASK 0x7F 659951ad9cSMatthias Ringwald #define BNEP_TYPE(header) ((header) & BNEP_TYPE_MASK) 669951ad9cSMatthias Ringwald #define BNEP_HEADER_HAS_EXT(x) (((x) & BNEP_EXT_FLAG) == BNEP_EXT_FLAG) 679951ad9cSMatthias Ringwald 689951ad9cSMatthias Ringwald /* BNEP packet types */ 699951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_GENERAL_ETHERNET 0x00 709951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_CONTROL 0x01 719951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET 0x02 729951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY 0x03 739951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY 0x04 749951ad9cSMatthias Ringwald 759951ad9cSMatthias Ringwald /* BNEP control types */ 769951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD 0x00 779951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST 0x01 789951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE 0x02 799951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET 0x03 809951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE 0x04 819951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET 0x05 829951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE 0x06 839951ad9cSMatthias Ringwald 849951ad9cSMatthias Ringwald /* BNEP extension header types */ 859951ad9cSMatthias Ringwald #define BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL 0x00 869951ad9cSMatthias Ringwald 879951ad9cSMatthias Ringwald /* BNEP setup response codes */ 889951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_SUCCESS 0x0000 899951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_DEST_UUID 0x0001 909951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_SOURCE_UUID 0x0002 919951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_SERVICE_UUID_SIZE 0x0003 929951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_CONNECTION_NOT_ALLOWED 0x0004 939951ad9cSMatthias Ringwald 949951ad9cSMatthias Ringwald /* BNEP filter response codes */ 959951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_SUCCESS 0x0000 969951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_UNSUPPORTED_REQUEST 0x0001 979951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_INVALID_RANGE 0x0002 989951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS 0x0003 999951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_SECURITY 0x0004 1009951ad9cSMatthias Ringwald 1013deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_TIMEOUT_MS 10000 1023deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_MAX_RETRIES 1 1033deb3ec6SMatthias Ringwald 1048f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_services = NULL; 1058f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_channels = NULL; 1063deb3ec6SMatthias Ringwald 1073deb3ec6SMatthias Ringwald static gap_security_level_t bnep_security_level; 1083deb3ec6SMatthias Ringwald 1093deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid); 1103deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel); 1113deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout); 1123deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event); 1134e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t cid); 1143deb3ec6SMatthias Ringwald static void bnep_emit_open_channel_complete(bnep_channel_t *channel, uint8_t status) 1153deb3ec6SMatthias Ringwald { 1160c249750SMatthias Ringwald log_info("BNEP_EVENT_CHANNEL_OPENED status 0x%02x bd_addr: %s, handler %p", status, bd_addr_to_str(channel->remote_addr), channel->packet_handler); 1170c249750SMatthias Ringwald if (!channel->packet_handler) return; 1180c249750SMatthias Ringwald 11932b46fecSMatthias Ringwald uint8_t event[3 + sizeof(bd_addr_t) + 4 * sizeof(uint16_t) + 2]; 120423c667cSMatthias Ringwald event[0] = BNEP_EVENT_CHANNEL_OPENED; 1213deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2; 1223deb3ec6SMatthias Ringwald event[2] = status; 123423c667cSMatthias Ringwald little_endian_store_16(event, 3, channel->l2cap_cid); 124423c667cSMatthias Ringwald little_endian_store_16(event, 5, channel->uuid_source); 125423c667cSMatthias Ringwald little_endian_store_16(event, 7, channel->uuid_dest); 126423c667cSMatthias Ringwald little_endian_store_16(event, 9, channel->max_frame_size); 127fb389631SMatthias Ringwald reverse_bd_addr(channel->remote_addr, &event[11]); 12832b46fecSMatthias Ringwald little_endian_store_16(event, 17, channel->con_handle); 12992da54c4SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 1, event, sizeof(event)); 1300c249750SMatthias Ringwald (*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); 1313deb3ec6SMatthias Ringwald } 1323deb3ec6SMatthias Ringwald 1333deb3ec6SMatthias Ringwald static void bnep_emit_channel_timeout(bnep_channel_t *channel) 1343deb3ec6SMatthias Ringwald { 1350c249750SMatthias Ringwald log_info("BNEP_EVENT_CHANNEL_TIMEOUT bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler); 1360c249750SMatthias Ringwald if (!channel->packet_handler) return; 1370c249750SMatthias Ringwald 138423c667cSMatthias Ringwald uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t) + sizeof(uint8_t)]; 1393deb3ec6SMatthias Ringwald event[0] = BNEP_EVENT_CHANNEL_TIMEOUT; 1403deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2; 141423c667cSMatthias Ringwald little_endian_store_16(event, 2, channel->l2cap_cid); 142423c667cSMatthias Ringwald little_endian_store_16(event, 4, channel->uuid_source); 143423c667cSMatthias Ringwald little_endian_store_16(event, 6, channel->uuid_dest); 144fb389631SMatthias Ringwald reverse_bd_addr(channel->remote_addr, &event[8]); 145423c667cSMatthias Ringwald event[14] = channel->state; 14692da54c4SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 1, event, sizeof(event)); 1470c249750SMatthias Ringwald (*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); 1483deb3ec6SMatthias Ringwald } 1493deb3ec6SMatthias Ringwald 1503deb3ec6SMatthias Ringwald static void bnep_emit_channel_closed(bnep_channel_t *channel) 1513deb3ec6SMatthias Ringwald { 1520c249750SMatthias Ringwald log_info("BNEP_EVENT_CHANNEL_CLOSED bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler); 1530c249750SMatthias Ringwald if (!channel->packet_handler) return; 1540c249750SMatthias Ringwald 155423c667cSMatthias Ringwald uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t)]; 1563deb3ec6SMatthias Ringwald event[0] = BNEP_EVENT_CHANNEL_CLOSED; 1573deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2; 158423c667cSMatthias Ringwald little_endian_store_16(event, 2, channel->l2cap_cid); 159423c667cSMatthias Ringwald little_endian_store_16(event, 4, channel->uuid_source); 160423c667cSMatthias Ringwald little_endian_store_16(event, 6, channel->uuid_dest); 161fb389631SMatthias Ringwald reverse_bd_addr(channel->remote_addr, &event[8]); 16292da54c4SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 1, event, sizeof(event)); 1630c249750SMatthias Ringwald (*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); 1643deb3ec6SMatthias Ringwald } 1653deb3ec6SMatthias Ringwald 1663deb3ec6SMatthias Ringwald static void bnep_emit_ready_to_send(bnep_channel_t *channel) 1673deb3ec6SMatthias Ringwald { 1680c249750SMatthias Ringwald if (!channel->packet_handler) return; 1690c249750SMatthias Ringwald 170423c667cSMatthias Ringwald uint8_t event[4]; 1712d4c8c04SMatthias Ringwald event[0] = BNEP_EVENT_CAN_SEND_NOW; 1723deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2; 173423c667cSMatthias Ringwald little_endian_store_16(event, 2, channel->l2cap_cid); 17492da54c4SMatthias Ringwald hci_dump_packet( HCI_EVENT_PACKET, 1, event, sizeof(event)); 1750c249750SMatthias Ringwald (*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event)); 1763deb3ec6SMatthias Ringwald } 1773deb3ec6SMatthias Ringwald 1783deb3ec6SMatthias Ringwald /* Send BNEP connection request */ 1793deb3ec6SMatthias Ringwald static int bnep_send_command_not_understood(bnep_channel_t *channel, uint8_t control_type) 1803deb3ec6SMatthias Ringwald { 1813deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL; 1823deb3ec6SMatthias Ringwald uint16_t pos = 0; 1833deb3ec6SMatthias Ringwald int err = 0; 1843deb3ec6SMatthias Ringwald 1853deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) { 1863deb3ec6SMatthias Ringwald return -1; // TODO 1873deb3ec6SMatthias Ringwald } 1883deb3ec6SMatthias Ringwald 1893deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer(); 1903deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer(); 1913deb3ec6SMatthias Ringwald 1923deb3ec6SMatthias Ringwald /* Setup control packet type */ 1933deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL; 1943deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD; 1953deb3ec6SMatthias Ringwald 1963deb3ec6SMatthias Ringwald /* Add not understood control type */ 1973deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = control_type; 1983deb3ec6SMatthias Ringwald 1993deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos); 2003deb3ec6SMatthias Ringwald 2013deb3ec6SMatthias Ringwald if (err) { 2023deb3ec6SMatthias Ringwald // TODO: Log error 2033deb3ec6SMatthias Ringwald } 2043deb3ec6SMatthias Ringwald return err; 2053deb3ec6SMatthias Ringwald } 2063deb3ec6SMatthias Ringwald 2073deb3ec6SMatthias Ringwald 2083deb3ec6SMatthias Ringwald /* Send BNEP connection request */ 2093deb3ec6SMatthias Ringwald static int bnep_send_connection_request(bnep_channel_t *channel, uint16_t uuid_source, uint16_t uuid_dest) 2103deb3ec6SMatthias Ringwald { 2113deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL; 2123deb3ec6SMatthias Ringwald uint16_t pos = 0; 2133deb3ec6SMatthias Ringwald int err = 0; 2143deb3ec6SMatthias Ringwald 2153deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) { 2163deb3ec6SMatthias Ringwald return -1; // TODO 2173deb3ec6SMatthias Ringwald } 2183deb3ec6SMatthias Ringwald 2193deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer(); 2203deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer(); 2213deb3ec6SMatthias Ringwald 2223deb3ec6SMatthias Ringwald /* Setup control packet type */ 2233deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL; 2243deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST; 2253deb3ec6SMatthias Ringwald 2263deb3ec6SMatthias Ringwald /* Add UUID Size */ 2273deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = 2; 2283deb3ec6SMatthias Ringwald 2293deb3ec6SMatthias Ringwald /* Add dest and source UUID */ 230f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, uuid_dest); 2313deb3ec6SMatthias Ringwald pos += 2; 2323deb3ec6SMatthias Ringwald 233f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, uuid_source); 2343deb3ec6SMatthias Ringwald pos += 2; 2353deb3ec6SMatthias Ringwald 2363deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos); 2373deb3ec6SMatthias Ringwald 2383deb3ec6SMatthias Ringwald if (err) { 2393deb3ec6SMatthias Ringwald // TODO: Log error 2403deb3ec6SMatthias Ringwald } 2413deb3ec6SMatthias Ringwald return err; 2423deb3ec6SMatthias Ringwald } 2433deb3ec6SMatthias Ringwald 2443deb3ec6SMatthias Ringwald /* Send BNEP connection response */ 2453deb3ec6SMatthias Ringwald static int bnep_send_connection_response(bnep_channel_t *channel, uint16_t response_code) 2463deb3ec6SMatthias Ringwald { 2473deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL; 2483deb3ec6SMatthias Ringwald uint16_t pos = 0; 2493deb3ec6SMatthias Ringwald int err = 0; 2503deb3ec6SMatthias Ringwald 2513deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) { 2523deb3ec6SMatthias Ringwald return -1; // TODO 2533deb3ec6SMatthias Ringwald } 2543deb3ec6SMatthias Ringwald 2553deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer(); 2563deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer(); 2573deb3ec6SMatthias Ringwald 2583deb3ec6SMatthias Ringwald /* Setup control packet type */ 2593deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL; 2603deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE; 2613deb3ec6SMatthias Ringwald 2623deb3ec6SMatthias Ringwald /* Add response code */ 263f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, response_code); 2643deb3ec6SMatthias Ringwald pos += 2; 2653deb3ec6SMatthias Ringwald 2663deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos); 2673deb3ec6SMatthias Ringwald 2683deb3ec6SMatthias Ringwald if (err) { 2693deb3ec6SMatthias Ringwald // TODO: Log error 2703deb3ec6SMatthias Ringwald } 2713deb3ec6SMatthias Ringwald return err; 2723deb3ec6SMatthias Ringwald } 2733deb3ec6SMatthias Ringwald 2743deb3ec6SMatthias Ringwald /* Send BNEP filter net type set message */ 2753deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_set(bnep_channel_t *channel, bnep_net_filter_t *filter, uint16_t len) 2763deb3ec6SMatthias Ringwald { 2773deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL; 2783deb3ec6SMatthias Ringwald uint16_t pos = 0; 2793deb3ec6SMatthias Ringwald int err = 0; 2803deb3ec6SMatthias Ringwald int i; 2813deb3ec6SMatthias Ringwald 2823deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) { 2833deb3ec6SMatthias Ringwald return -1; 2843deb3ec6SMatthias Ringwald } 2853deb3ec6SMatthias Ringwald 2863deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer(); 2873deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer(); 2883deb3ec6SMatthias Ringwald 2893deb3ec6SMatthias Ringwald /* Setup control packet type */ 2903deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL; 2913deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET; 2923deb3ec6SMatthias Ringwald 293f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, len * 2 * 2); 2943deb3ec6SMatthias Ringwald pos += 2; 2953deb3ec6SMatthias Ringwald 2963deb3ec6SMatthias Ringwald for (i = 0; i < len; i ++) { 297f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, filter[i].range_start); 2983deb3ec6SMatthias Ringwald pos += 2; 299f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, filter[i].range_end); 3003deb3ec6SMatthias Ringwald pos += 2; 3013deb3ec6SMatthias Ringwald } 3023deb3ec6SMatthias Ringwald 3033deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos); 3043deb3ec6SMatthias Ringwald 3053deb3ec6SMatthias Ringwald if (err) { 3063deb3ec6SMatthias Ringwald // TODO: Log error 3073deb3ec6SMatthias Ringwald } 3083deb3ec6SMatthias Ringwald return err; 3093deb3ec6SMatthias Ringwald } 3103deb3ec6SMatthias Ringwald 3113deb3ec6SMatthias Ringwald /* Send BNEP filter net type response message */ 3123deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_response(bnep_channel_t *channel, uint16_t response_code) 3133deb3ec6SMatthias Ringwald { 3143deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL; 3153deb3ec6SMatthias Ringwald uint16_t pos = 0; 3163deb3ec6SMatthias Ringwald int err = 0; 3173deb3ec6SMatthias Ringwald 3183deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) { 3193deb3ec6SMatthias Ringwald return -1; 3203deb3ec6SMatthias Ringwald } 3213deb3ec6SMatthias Ringwald 3223deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer(); 3233deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer(); 3243deb3ec6SMatthias Ringwald 3253deb3ec6SMatthias Ringwald /* Setup control packet type */ 3263deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL; 3273deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE; 3283deb3ec6SMatthias Ringwald 3293deb3ec6SMatthias Ringwald /* Add response code */ 330f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, response_code); 3313deb3ec6SMatthias Ringwald pos += 2; 3323deb3ec6SMatthias Ringwald 3333deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos); 3343deb3ec6SMatthias Ringwald 3353deb3ec6SMatthias Ringwald if (err) { 3363deb3ec6SMatthias Ringwald // TODO: Log error 3373deb3ec6SMatthias Ringwald } 3383deb3ec6SMatthias Ringwald return err; 3393deb3ec6SMatthias Ringwald } 3403deb3ec6SMatthias Ringwald 3413deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address set message */ 3423deb3ec6SMatthias Ringwald 3433deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_set(bnep_channel_t *channel, bnep_multi_filter_t *filter, uint16_t len) 3443deb3ec6SMatthias Ringwald { 3453deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL; 3463deb3ec6SMatthias Ringwald uint16_t pos = 0; 3473deb3ec6SMatthias Ringwald int err = 0; 3483deb3ec6SMatthias Ringwald int i; 3493deb3ec6SMatthias Ringwald 3503deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) { 3513deb3ec6SMatthias Ringwald return -1; 3523deb3ec6SMatthias Ringwald } 3533deb3ec6SMatthias Ringwald 3543deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer(); 3553deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer(); 3563deb3ec6SMatthias Ringwald 3573deb3ec6SMatthias Ringwald /* Setup control packet type */ 3583deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL; 3593deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET; 3603deb3ec6SMatthias Ringwald 361f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, len * 2 * ETHER_ADDR_LEN); 3623deb3ec6SMatthias Ringwald pos += 2; 3633deb3ec6SMatthias Ringwald 3643deb3ec6SMatthias Ringwald for (i = 0; i < len; i ++) { 365058e3d6bSMatthias Ringwald bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_start); 3663deb3ec6SMatthias Ringwald pos += ETHER_ADDR_LEN; 367058e3d6bSMatthias Ringwald bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_end); 3683deb3ec6SMatthias Ringwald pos += ETHER_ADDR_LEN; 3693deb3ec6SMatthias Ringwald } 3703deb3ec6SMatthias Ringwald 3713deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos); 3723deb3ec6SMatthias Ringwald 3733deb3ec6SMatthias Ringwald if (err) { 3743deb3ec6SMatthias Ringwald // TODO: Log error 3753deb3ec6SMatthias Ringwald } 3763deb3ec6SMatthias Ringwald return err; 3773deb3ec6SMatthias Ringwald } 3783deb3ec6SMatthias Ringwald 3793deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address response message */ 3803deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_response(bnep_channel_t *channel, uint16_t response_code) 3813deb3ec6SMatthias Ringwald { 3823deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL; 3833deb3ec6SMatthias Ringwald uint16_t pos = 0; 3843deb3ec6SMatthias Ringwald int err = 0; 3853deb3ec6SMatthias Ringwald 3863deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) { 3873deb3ec6SMatthias Ringwald return -1; 3883deb3ec6SMatthias Ringwald } 3893deb3ec6SMatthias Ringwald 3903deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer(); 3913deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer(); 3923deb3ec6SMatthias Ringwald 3933deb3ec6SMatthias Ringwald /* Setup control packet type */ 3943deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL; 3953deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE; 3963deb3ec6SMatthias Ringwald 3973deb3ec6SMatthias Ringwald /* Add response code */ 398f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, response_code); 3993deb3ec6SMatthias Ringwald pos += 2; 4003deb3ec6SMatthias Ringwald 4013deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos); 4023deb3ec6SMatthias Ringwald 4033deb3ec6SMatthias Ringwald if (err) { 4043deb3ec6SMatthias Ringwald // TODO: Log error 4053deb3ec6SMatthias Ringwald } 4063deb3ec6SMatthias Ringwald return err; 4073deb3ec6SMatthias Ringwald } 4083deb3ec6SMatthias Ringwald 4093deb3ec6SMatthias Ringwald int bnep_can_send_packet_now(uint16_t bnep_cid) 4103deb3ec6SMatthias Ringwald { 4113deb3ec6SMatthias Ringwald bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid); 4123deb3ec6SMatthias Ringwald 4133deb3ec6SMatthias Ringwald if (!channel){ 4143deb3ec6SMatthias Ringwald log_error("bnep_can_send_packet_now cid 0x%02x doesn't exist!", bnep_cid); 4153deb3ec6SMatthias Ringwald return 0; 4163deb3ec6SMatthias Ringwald } 4173deb3ec6SMatthias Ringwald 4180b9d7e78SMatthias Ringwald return l2cap_can_send_packet_now(channel->l2cap_cid); 4191ed1a3bdSMatthias Ringwald } 4201ed1a3bdSMatthias Ringwald 4211ed1a3bdSMatthias Ringwald void bnep_request_can_send_now_event(uint16_t bnep_cid) 4221ed1a3bdSMatthias Ringwald { 4231ed1a3bdSMatthias Ringwald bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid); 4241ed1a3bdSMatthias Ringwald 4251ed1a3bdSMatthias Ringwald if (!channel){ 4261ed1a3bdSMatthias Ringwald log_error("bnep_request_can_send_now_event cid 0x%02x doesn't exist!", bnep_cid); 4271ed1a3bdSMatthias Ringwald return; 4281ed1a3bdSMatthias Ringwald } 4291ed1a3bdSMatthias Ringwald 4301ed1a3bdSMatthias Ringwald channel->waiting_for_can_send_now = 1; 4311ed1a3bdSMatthias Ringwald l2cap_request_can_send_now_event(bnep_cid); 4323deb3ec6SMatthias Ringwald } 4333deb3ec6SMatthias Ringwald 4343deb3ec6SMatthias Ringwald 4353deb3ec6SMatthias Ringwald static int bnep_filter_protocol(bnep_channel_t *channel, uint16_t network_protocol_type) 4363deb3ec6SMatthias Ringwald { 4373deb3ec6SMatthias Ringwald int i; 4383deb3ec6SMatthias Ringwald 4393deb3ec6SMatthias Ringwald if (channel->net_filter_count == 0) { 4403deb3ec6SMatthias Ringwald /* No filter set */ 4413deb3ec6SMatthias Ringwald return 1; 4423deb3ec6SMatthias Ringwald } 4433deb3ec6SMatthias Ringwald 4443deb3ec6SMatthias Ringwald for (i = 0; i < channel->net_filter_count; i ++) { 4453deb3ec6SMatthias Ringwald if ((network_protocol_type >= channel->net_filter[i].range_start) && 4463deb3ec6SMatthias Ringwald (network_protocol_type <= channel->net_filter[i].range_end)) { 4473deb3ec6SMatthias Ringwald return 1; 4483deb3ec6SMatthias Ringwald } 4493deb3ec6SMatthias Ringwald } 4503deb3ec6SMatthias Ringwald 4513deb3ec6SMatthias Ringwald return 0; 4523deb3ec6SMatthias Ringwald } 4533deb3ec6SMatthias Ringwald 4543deb3ec6SMatthias Ringwald static int bnep_filter_multicast(bnep_channel_t *channel, bd_addr_t addr_dest) 4553deb3ec6SMatthias Ringwald { 4563deb3ec6SMatthias Ringwald int i; 4573deb3ec6SMatthias Ringwald 4583deb3ec6SMatthias Ringwald /* Check if the multicast flag is set int the destination address */ 4593deb3ec6SMatthias Ringwald if ((addr_dest[0] & 0x01) == 0x00) { 4603deb3ec6SMatthias Ringwald /* Not a multicast frame, do not apply filtering and send it in any case */ 4613deb3ec6SMatthias Ringwald return 1; 4623deb3ec6SMatthias Ringwald } 4633deb3ec6SMatthias Ringwald 4643deb3ec6SMatthias Ringwald if (channel->multicast_filter_count == 0) { 4653deb3ec6SMatthias Ringwald /* No filter set */ 4663deb3ec6SMatthias Ringwald return 1; 4673deb3ec6SMatthias Ringwald } 4683deb3ec6SMatthias Ringwald 4693deb3ec6SMatthias Ringwald for (i = 0; i < channel->multicast_filter_count; i ++) { 4703deb3ec6SMatthias Ringwald if ((memcmp(addr_dest, channel->multicast_filter[i].addr_start, sizeof(bd_addr_t)) >= 0) && 4713deb3ec6SMatthias Ringwald (memcmp(addr_dest, channel->multicast_filter[i].addr_end, sizeof(bd_addr_t)) <= 0)) { 4723deb3ec6SMatthias Ringwald return 1; 4733deb3ec6SMatthias Ringwald } 4743deb3ec6SMatthias Ringwald } 4753deb3ec6SMatthias Ringwald 4763deb3ec6SMatthias Ringwald return 0; 4773deb3ec6SMatthias Ringwald } 4783deb3ec6SMatthias Ringwald 4793deb3ec6SMatthias Ringwald 4803deb3ec6SMatthias Ringwald /* Send BNEP ethernet packet */ 4813deb3ec6SMatthias Ringwald int bnep_send(uint16_t bnep_cid, uint8_t *packet, uint16_t len) 4823deb3ec6SMatthias Ringwald { 4833deb3ec6SMatthias Ringwald bnep_channel_t *channel; 4843deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL; 4853deb3ec6SMatthias Ringwald uint16_t pos = 0; 4863deb3ec6SMatthias Ringwald uint16_t pos_out = 0; 4873deb3ec6SMatthias Ringwald uint16_t payload_len; 4883deb3ec6SMatthias Ringwald int err = 0; 4893deb3ec6SMatthias Ringwald int has_source; 4903deb3ec6SMatthias Ringwald int has_dest; 4913deb3ec6SMatthias Ringwald 4923deb3ec6SMatthias Ringwald bd_addr_t addr_dest; 4933deb3ec6SMatthias Ringwald bd_addr_t addr_source; 4943deb3ec6SMatthias Ringwald uint16_t network_protocol_type; 4953deb3ec6SMatthias Ringwald 4963deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(bnep_cid); 4973deb3ec6SMatthias Ringwald if (channel == NULL) { 4983deb3ec6SMatthias Ringwald log_error("bnep_send cid 0x%02x doesn't exist!", bnep_cid); 4993deb3ec6SMatthias Ringwald return 1; 5003deb3ec6SMatthias Ringwald } 5013deb3ec6SMatthias Ringwald 5023deb3ec6SMatthias Ringwald if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) { 5033deb3ec6SMatthias Ringwald return BNEP_CHANNEL_NOT_CONNECTED; 5043deb3ec6SMatthias Ringwald } 5053deb3ec6SMatthias Ringwald 5063deb3ec6SMatthias Ringwald /* Check for free ACL buffers */ 5073deb3ec6SMatthias Ringwald if (!l2cap_can_send_packet_now(channel->l2cap_cid)) { 5083deb3ec6SMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL; 5093deb3ec6SMatthias Ringwald } 5103deb3ec6SMatthias Ringwald 5113deb3ec6SMatthias Ringwald /* Extract destination and source address from the ethernet packet */ 5123deb3ec6SMatthias Ringwald pos = 0; 513058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, &packet[pos]); 5143deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t); 515058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, &packet[pos]); 5163deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t); 517f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos); 5183deb3ec6SMatthias Ringwald pos += sizeof(uint16_t); 5193deb3ec6SMatthias Ringwald 5203deb3ec6SMatthias Ringwald payload_len = len - pos; 5213deb3ec6SMatthias Ringwald 5223deb3ec6SMatthias Ringwald if (network_protocol_type == ETHERTYPE_VLAN) { /* IEEE 802.1Q tag header */ 5233deb3ec6SMatthias Ringwald if (payload_len < 4) { 5243deb3ec6SMatthias Ringwald /* Omit this packet */ 5253deb3ec6SMatthias Ringwald return 0; 5263deb3ec6SMatthias Ringwald } 5273deb3ec6SMatthias Ringwald /* The "real" network protocol type is 4 bytes ahead in a VLAN packet */ 528f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos + 2); 5293deb3ec6SMatthias Ringwald } 5303deb3ec6SMatthias Ringwald 5313deb3ec6SMatthias Ringwald /* Check network protocol and multicast filters before sending */ 5323deb3ec6SMatthias Ringwald if (!bnep_filter_protocol(channel, network_protocol_type) || 5333deb3ec6SMatthias Ringwald !bnep_filter_multicast(channel, addr_dest)) { 5343deb3ec6SMatthias Ringwald /* Packet did not pass filter... */ 5353deb3ec6SMatthias Ringwald if ((network_protocol_type == ETHERTYPE_VLAN) && 5363deb3ec6SMatthias Ringwald (payload_len >= 4)) { 5373deb3ec6SMatthias Ringwald /* The packet has been tagged as a with IEE 802.1Q tag and has been filtered out. 5383deb3ec6SMatthias Ringwald According to the spec the IEE802.1Q tag header shall be sended without ethernet payload. 5393deb3ec6SMatthias Ringwald So limit the payload_len to 4. 5403deb3ec6SMatthias Ringwald */ 5413deb3ec6SMatthias Ringwald payload_len = 4; 5423deb3ec6SMatthias Ringwald } else { 5433deb3ec6SMatthias Ringwald /* Packet is not tagged with IEE802.1Q header and was filtered out. Omit this packet */ 5443deb3ec6SMatthias Ringwald return 0; 5453deb3ec6SMatthias Ringwald } 5463deb3ec6SMatthias Ringwald } 5473deb3ec6SMatthias Ringwald 5483deb3ec6SMatthias Ringwald /* Reserve l2cap packet buffer */ 5493deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer(); 5503deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer(); 5513deb3ec6SMatthias Ringwald 5523deb3ec6SMatthias Ringwald /* Check if source address is the same as our local address and if the 5533deb3ec6SMatthias Ringwald destination address is the same as the remote addr. Maybe we can use 5543deb3ec6SMatthias Ringwald the compressed data format 5553deb3ec6SMatthias Ringwald */ 5563deb3ec6SMatthias Ringwald has_source = (memcmp(addr_source, channel->local_addr, ETHER_ADDR_LEN) != 0); 5573deb3ec6SMatthias Ringwald has_dest = (memcmp(addr_dest, channel->remote_addr, ETHER_ADDR_LEN) != 0); 5583deb3ec6SMatthias Ringwald 5593deb3ec6SMatthias Ringwald /* Check for MTU limits */ 5603deb3ec6SMatthias Ringwald if (payload_len > channel->max_frame_size) { 5613deb3ec6SMatthias Ringwald log_error("bnep_send: Max frame size (%d) exceeded: %d", channel->max_frame_size, payload_len); 5623deb3ec6SMatthias Ringwald return BNEP_DATA_LEN_EXCEEDS_MTU; 5633deb3ec6SMatthias Ringwald } 5643deb3ec6SMatthias Ringwald 5653deb3ec6SMatthias Ringwald /* Fill in the package type depending on the given source and destination address */ 5663deb3ec6SMatthias Ringwald if (has_source && has_dest) { 5673deb3ec6SMatthias Ringwald bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_GENERAL_ETHERNET; 5683deb3ec6SMatthias Ringwald } else 5693deb3ec6SMatthias Ringwald if (has_source && !has_dest) { 5703deb3ec6SMatthias Ringwald bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY; 5713deb3ec6SMatthias Ringwald } else 5723deb3ec6SMatthias Ringwald if (!has_source && has_dest) { 5733deb3ec6SMatthias Ringwald bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY; 5743deb3ec6SMatthias Ringwald } else { 5753deb3ec6SMatthias Ringwald bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET; 5763deb3ec6SMatthias Ringwald } 5773deb3ec6SMatthias Ringwald 5783deb3ec6SMatthias Ringwald /* Add the destination address if needed */ 5793deb3ec6SMatthias Ringwald if (has_dest) { 580058e3d6bSMatthias Ringwald bd_addr_copy(bnep_out_buffer + pos_out, addr_dest); 5813deb3ec6SMatthias Ringwald pos_out += sizeof(bd_addr_t); 5823deb3ec6SMatthias Ringwald } 5833deb3ec6SMatthias Ringwald 5843deb3ec6SMatthias Ringwald /* Add the source address if needed */ 5853deb3ec6SMatthias Ringwald if (has_source) { 586058e3d6bSMatthias Ringwald bd_addr_copy(bnep_out_buffer + pos_out, addr_source); 5873deb3ec6SMatthias Ringwald pos_out += sizeof(bd_addr_t); 5883deb3ec6SMatthias Ringwald } 5893deb3ec6SMatthias Ringwald 5903deb3ec6SMatthias Ringwald /* Add protocol type */ 591f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos_out, network_protocol_type); 5923deb3ec6SMatthias Ringwald pos_out += 2; 5933deb3ec6SMatthias Ringwald 5943deb3ec6SMatthias Ringwald /* TODO: Add extension headers, if we may support them at a later stage */ 5953deb3ec6SMatthias Ringwald /* Add the payload and then send out the package */ 5966535961aSMatthias Ringwald (void)memcpy(bnep_out_buffer + pos_out, packet + pos, payload_len); 5973deb3ec6SMatthias Ringwald pos_out += payload_len; 5983deb3ec6SMatthias Ringwald 5993deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos_out); 6003deb3ec6SMatthias Ringwald 6013deb3ec6SMatthias Ringwald if (err) { 6023deb3ec6SMatthias Ringwald log_error("bnep_send: error %d", err); 6033deb3ec6SMatthias Ringwald } 6043deb3ec6SMatthias Ringwald return err; 6053deb3ec6SMatthias Ringwald } 6063deb3ec6SMatthias Ringwald 6073deb3ec6SMatthias Ringwald 6083deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */ 6093deb3ec6SMatthias Ringwald int bnep_set_net_type_filter(uint16_t bnep_cid, bnep_net_filter_t *filter, uint16_t len) 6103deb3ec6SMatthias Ringwald { 6113deb3ec6SMatthias Ringwald bnep_channel_t *channel; 6123deb3ec6SMatthias Ringwald 6133deb3ec6SMatthias Ringwald if (filter == NULL) { 6143deb3ec6SMatthias Ringwald return -1; 6153deb3ec6SMatthias Ringwald } 6163deb3ec6SMatthias Ringwald 6173deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(bnep_cid); 6183deb3ec6SMatthias Ringwald if (channel == NULL) { 6193deb3ec6SMatthias Ringwald log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid); 6203deb3ec6SMatthias Ringwald return 1; 6213deb3ec6SMatthias Ringwald } 6223deb3ec6SMatthias Ringwald 6233deb3ec6SMatthias Ringwald if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) { 6243deb3ec6SMatthias Ringwald return BNEP_CHANNEL_NOT_CONNECTED; 6253deb3ec6SMatthias Ringwald } 6263deb3ec6SMatthias Ringwald 6273deb3ec6SMatthias Ringwald if (len > MAX_BNEP_NETFILTER_OUT) { 6283deb3ec6SMatthias Ringwald return BNEP_DATA_LEN_EXCEEDS_MTU; 6293deb3ec6SMatthias Ringwald } 6303deb3ec6SMatthias Ringwald 6313deb3ec6SMatthias Ringwald channel->net_filter_out = filter; 6323deb3ec6SMatthias Ringwald channel->net_filter_out_count = len; 6333deb3ec6SMatthias Ringwald 6344e366553SMatthias Ringwald /* Set flag to send out the network protocol type filter set request */ 6353deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET); 6364e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 6373deb3ec6SMatthias Ringwald 6383deb3ec6SMatthias Ringwald return 0; 6393deb3ec6SMatthias Ringwald } 6403deb3ec6SMatthias Ringwald 6413deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */ 6423deb3ec6SMatthias Ringwald int bnep_set_multicast_filter(uint16_t bnep_cid, bnep_multi_filter_t *filter, uint16_t len) 6433deb3ec6SMatthias Ringwald { 6443deb3ec6SMatthias Ringwald bnep_channel_t *channel; 6453deb3ec6SMatthias Ringwald 6463deb3ec6SMatthias Ringwald if (filter == NULL) { 6473deb3ec6SMatthias Ringwald return -1; 6483deb3ec6SMatthias Ringwald } 6493deb3ec6SMatthias Ringwald 6503deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(bnep_cid); 6513deb3ec6SMatthias Ringwald if (channel == NULL) { 6523deb3ec6SMatthias Ringwald log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid); 6533deb3ec6SMatthias Ringwald return 1; 6543deb3ec6SMatthias Ringwald } 6553deb3ec6SMatthias Ringwald 6563deb3ec6SMatthias Ringwald if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) { 6573deb3ec6SMatthias Ringwald return BNEP_CHANNEL_NOT_CONNECTED; 6583deb3ec6SMatthias Ringwald } 6593deb3ec6SMatthias Ringwald 66066b1fcb3SMatthias Ringwald if (len > MAX_BNEP_MULTICAST_FILTER_OUT) { 6613deb3ec6SMatthias Ringwald return BNEP_DATA_LEN_EXCEEDS_MTU; 6623deb3ec6SMatthias Ringwald } 6633deb3ec6SMatthias Ringwald 6643deb3ec6SMatthias Ringwald channel->multicast_filter_out = filter; 6653deb3ec6SMatthias Ringwald channel->multicast_filter_out_count = len; 6663deb3ec6SMatthias Ringwald 6674e366553SMatthias Ringwald /* Set flag to send out the multicast filter set request */ 6683deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET); 6694e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 6703deb3ec6SMatthias Ringwald 6713deb3ec6SMatthias Ringwald return 0; 6723deb3ec6SMatthias Ringwald } 6733deb3ec6SMatthias Ringwald 6743deb3ec6SMatthias Ringwald /* BNEP timeout timer helper function */ 675ec820d77SMatthias Ringwald static void bnep_channel_timer_handler(btstack_timer_source_t *timer) 6763deb3ec6SMatthias Ringwald { 67791a977e8SMatthias Ringwald bnep_channel_t *channel = btstack_run_loop_get_timer_context(timer); 6783deb3ec6SMatthias Ringwald // retry send setup connection at least one time 6793deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE){ 6803deb3ec6SMatthias Ringwald if (channel->retry_count < BNEP_CONNECTION_MAX_RETRIES){ 6813deb3ec6SMatthias Ringwald channel->retry_count++; 6823deb3ec6SMatthias Ringwald bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS); 6833deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST); 6844e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 6853deb3ec6SMatthias Ringwald return; 6863deb3ec6SMatthias Ringwald } 6873deb3ec6SMatthias Ringwald } 6883deb3ec6SMatthias Ringwald 6893deb3ec6SMatthias Ringwald log_info( "bnep_channel_timeout_handler callback: shutting down connection!"); 6903deb3ec6SMatthias Ringwald bnep_emit_channel_timeout(channel); 6913deb3ec6SMatthias Ringwald bnep_channel_finalize(channel); 6923deb3ec6SMatthias Ringwald } 6933deb3ec6SMatthias Ringwald 6943deb3ec6SMatthias Ringwald 6953deb3ec6SMatthias Ringwald static void bnep_channel_stop_timer(bnep_channel_t *channel) 6963deb3ec6SMatthias Ringwald { 6973deb3ec6SMatthias Ringwald if (channel->timer_active) { 698528a4a3bSMatthias Ringwald btstack_run_loop_remove_timer(&channel->timer); 6993deb3ec6SMatthias Ringwald channel->timer_active = 0; 7003deb3ec6SMatthias Ringwald } 7013deb3ec6SMatthias Ringwald } 7023deb3ec6SMatthias Ringwald 7033deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout) 7043deb3ec6SMatthias Ringwald { 7053deb3ec6SMatthias Ringwald /* Stop any eventually running timeout timer */ 7063deb3ec6SMatthias Ringwald bnep_channel_stop_timer(channel); 7073deb3ec6SMatthias Ringwald 7083deb3ec6SMatthias Ringwald /* Start bnep channel timeout check timer */ 709528a4a3bSMatthias Ringwald btstack_run_loop_set_timer(&channel->timer, timeout); 71091a977e8SMatthias Ringwald btstack_run_loop_set_timer_handler(&channel->timer, bnep_channel_timer_handler); 71191a977e8SMatthias Ringwald btstack_run_loop_set_timer_context(&channel->timer, channel); 712528a4a3bSMatthias Ringwald btstack_run_loop_add_timer(&channel->timer); 7133deb3ec6SMatthias Ringwald channel->timer_active = 1; 7143deb3ec6SMatthias Ringwald } 7153deb3ec6SMatthias Ringwald 7163deb3ec6SMatthias Ringwald /* BNEP statemachine functions */ 7173deb3ec6SMatthias Ringwald 7183deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){ 7193deb3ec6SMatthias Ringwald channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var | event); 7203deb3ec6SMatthias Ringwald } 7213deb3ec6SMatthias Ringwald inline static void bnep_channel_state_remove(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){ 7223deb3ec6SMatthias Ringwald channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var & ~event); 7233deb3ec6SMatthias Ringwald } 7243deb3ec6SMatthias Ringwald 7253deb3ec6SMatthias Ringwald static uint16_t bnep_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){ 7263deb3ec6SMatthias Ringwald 7273deb3ec6SMatthias Ringwald /* Assume a standard BNEP header, containing BNEP Type (1 Byte), dest and 7283deb3ec6SMatthias Ringwald source address (6 bytes each) and networking protocol type (2 bytes) 7293deb3ec6SMatthias Ringwald */ 7303deb3ec6SMatthias Ringwald uint16_t max_frame_size = l2cap_mtu - 15; // 15 bytes BNEP header 7313deb3ec6SMatthias Ringwald 7323deb3ec6SMatthias Ringwald log_info("bnep_max_frame_size_for_l2cap_mtu: %u -> %u", l2cap_mtu, max_frame_size); 7333deb3ec6SMatthias Ringwald return max_frame_size; 7343deb3ec6SMatthias Ringwald } 7353deb3ec6SMatthias Ringwald 7363deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_create_for_addr(bd_addr_t addr) 7373deb3ec6SMatthias Ringwald { 7383deb3ec6SMatthias Ringwald /* Allocate new channel structure */ 7393deb3ec6SMatthias Ringwald bnep_channel_t *channel = btstack_memory_bnep_channel_get(); 7403deb3ec6SMatthias Ringwald if (!channel) { 7413deb3ec6SMatthias Ringwald return NULL; 7423deb3ec6SMatthias Ringwald } 7433deb3ec6SMatthias Ringwald 7443deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_CLOSED; 7453deb3ec6SMatthias Ringwald channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(l2cap_max_mtu()); 74673988a59SMatthias Ringwald bd_addr_copy(channel->remote_addr, addr); 74715a95bd5SMatthias Ringwald gap_local_bd_addr(channel->local_addr); 7483deb3ec6SMatthias Ringwald 7493deb3ec6SMatthias Ringwald channel->net_filter_count = 0; 7503deb3ec6SMatthias Ringwald channel->multicast_filter_count = 0; 7513deb3ec6SMatthias Ringwald channel->retry_count = 0; 7523deb3ec6SMatthias Ringwald 7533deb3ec6SMatthias Ringwald /* Finally add it to the channel list */ 754665d90f2SMatthias Ringwald btstack_linked_list_add(&bnep_channels, (btstack_linked_item_t *) channel); 7553deb3ec6SMatthias Ringwald 7563deb3ec6SMatthias Ringwald return channel; 7573deb3ec6SMatthias Ringwald } 7583deb3ec6SMatthias Ringwald 7593deb3ec6SMatthias Ringwald static bnep_channel_t* bnep_channel_for_addr(bd_addr_t addr) 7603deb3ec6SMatthias Ringwald { 761665d90f2SMatthias Ringwald btstack_linked_item_t *it; 762665d90f2SMatthias Ringwald for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){ 7633deb3ec6SMatthias Ringwald bnep_channel_t *channel = ((bnep_channel_t *) it); 764058e3d6bSMatthias Ringwald if (bd_addr_cmp(addr, channel->remote_addr) == 0) { 7653deb3ec6SMatthias Ringwald return channel; 7663deb3ec6SMatthias Ringwald } 7673deb3ec6SMatthias Ringwald } 7683deb3ec6SMatthias Ringwald return NULL; 7693deb3ec6SMatthias Ringwald } 7703deb3ec6SMatthias Ringwald 7713deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid) 7723deb3ec6SMatthias Ringwald { 773665d90f2SMatthias Ringwald btstack_linked_item_t *it; 774665d90f2SMatthias Ringwald for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){ 7753deb3ec6SMatthias Ringwald bnep_channel_t *channel = ((bnep_channel_t *) it); 7763deb3ec6SMatthias Ringwald if (channel->l2cap_cid == l2cap_cid) { 7773deb3ec6SMatthias Ringwald return channel; 7783deb3ec6SMatthias Ringwald } 7793deb3ec6SMatthias Ringwald } 7803deb3ec6SMatthias Ringwald return NULL; 7813deb3ec6SMatthias Ringwald } 7823deb3ec6SMatthias Ringwald 7833deb3ec6SMatthias Ringwald static bnep_service_t * bnep_service_for_uuid(uint16_t uuid) 7843deb3ec6SMatthias Ringwald { 785665d90f2SMatthias Ringwald btstack_linked_item_t *it; 786665d90f2SMatthias Ringwald for (it = (btstack_linked_item_t *) bnep_services; it ; it = it->next){ 7873deb3ec6SMatthias Ringwald bnep_service_t * service = ((bnep_service_t *) it); 7883deb3ec6SMatthias Ringwald if ( service->service_uuid == uuid){ 7893deb3ec6SMatthias Ringwald return service; 7903deb3ec6SMatthias Ringwald } 7913deb3ec6SMatthias Ringwald } 7923deb3ec6SMatthias Ringwald return NULL; 7933deb3ec6SMatthias Ringwald } 7943deb3ec6SMatthias Ringwald 7953deb3ec6SMatthias Ringwald static void bnep_channel_free(bnep_channel_t *channel) 7963deb3ec6SMatthias Ringwald { 797665d90f2SMatthias Ringwald btstack_linked_list_remove( &bnep_channels, (btstack_linked_item_t *) channel); 7983deb3ec6SMatthias Ringwald btstack_memory_bnep_channel_free(channel); 7993deb3ec6SMatthias Ringwald } 8003deb3ec6SMatthias Ringwald 8013deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel) 8023deb3ec6SMatthias Ringwald { 8033deb3ec6SMatthias Ringwald uint16_t l2cap_cid; 8043deb3ec6SMatthias Ringwald 8053deb3ec6SMatthias Ringwald /* Inform application about closed channel */ 8063deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) { 8073deb3ec6SMatthias Ringwald bnep_emit_channel_closed(channel); 8083deb3ec6SMatthias Ringwald } 8093deb3ec6SMatthias Ringwald 8103deb3ec6SMatthias Ringwald l2cap_cid = channel->l2cap_cid; 8113deb3ec6SMatthias Ringwald 8123deb3ec6SMatthias Ringwald /* Stop any eventually running timer */ 8133deb3ec6SMatthias Ringwald bnep_channel_stop_timer(channel); 8143deb3ec6SMatthias Ringwald 8153deb3ec6SMatthias Ringwald /* Free ressources and then close the l2cap channel */ 8163deb3ec6SMatthias Ringwald bnep_channel_free(channel); 817b93f8966SMatthias Ringwald l2cap_disconnect(l2cap_cid); 8183deb3ec6SMatthias Ringwald } 8193deb3ec6SMatthias Ringwald 8203deb3ec6SMatthias Ringwald static int bnep_handle_connection_request(bnep_channel_t *channel, uint8_t *packet, uint16_t size) 8213deb3ec6SMatthias Ringwald { 8223deb3ec6SMatthias Ringwald uint16_t uuid_size; 823bb015fa7SMatthias Ringwald uint16_t uuid_offset = 0; // avoid "may be unitialized when used" in clang 8243deb3ec6SMatthias Ringwald uuid_size = packet[1]; 8253deb3ec6SMatthias Ringwald uint16_t response_code = BNEP_RESP_SETUP_SUCCESS; 8263deb3ec6SMatthias Ringwald bnep_service_t * service; 8273deb3ec6SMatthias Ringwald 8283deb3ec6SMatthias Ringwald /* Sanity check packet size */ 829a1df452eSMatthias Ringwald if (size < (1 + 1 + (2 * uuid_size))) { 8303deb3ec6SMatthias Ringwald return 0; 8313deb3ec6SMatthias Ringwald } 8323deb3ec6SMatthias Ringwald 8333deb3ec6SMatthias Ringwald if ((channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) && 8343deb3ec6SMatthias Ringwald (channel->state != BNEP_CHANNEL_STATE_CONNECTED)) { 8353deb3ec6SMatthias Ringwald /* Ignore a connection request if not waiting for or still connected */ 8363deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_REQUEST: ignored in state %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid); 8373deb3ec6SMatthias Ringwald return 0; 8383deb3ec6SMatthias Ringwald } 8393deb3ec6SMatthias Ringwald 8403deb3ec6SMatthias Ringwald /* Extract source and destination UUID and convert them to UUID16 format */ 8413deb3ec6SMatthias Ringwald switch (uuid_size) { 8423deb3ec6SMatthias Ringwald case 2: /* UUID16 */ 8433deb3ec6SMatthias Ringwald uuid_offset = 0; 8443deb3ec6SMatthias Ringwald break; 8453deb3ec6SMatthias Ringwald case 4: /* UUID32 */ 8463deb3ec6SMatthias Ringwald case 16: /* UUID128 */ 8473deb3ec6SMatthias Ringwald uuid_offset = 2; 8483deb3ec6SMatthias Ringwald break; 8493deb3ec6SMatthias Ringwald default: 8503deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_REQUEST: Invalid UUID size %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid); 8513deb3ec6SMatthias Ringwald response_code = BNEP_RESP_SETUP_INVALID_SERVICE_UUID_SIZE; 8523deb3ec6SMatthias Ringwald break; 8533deb3ec6SMatthias Ringwald } 8543deb3ec6SMatthias Ringwald 855*d4d9523fSMatthias Ringwald /* Check bits 16-31 of UUID */ 856*d4d9523fSMatthias Ringwald if (uuid_size > 2){ 857*d4d9523fSMatthias Ringwald uint16_t dest_prefix = big_endian_read_16(packet, 2); 858*d4d9523fSMatthias Ringwald if (dest_prefix != 0){ 859*d4d9523fSMatthias Ringwald response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID; 860*d4d9523fSMatthias Ringwald } 861*d4d9523fSMatthias Ringwald uint16_t src_prefix = big_endian_read_16(packet, 2 + uuid_size); 862*d4d9523fSMatthias Ringwald if (src_prefix != 0){ 863*d4d9523fSMatthias Ringwald response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID; 864*d4d9523fSMatthias Ringwald } 865*d4d9523fSMatthias Ringwald } 866*d4d9523fSMatthias Ringwald 867*d4d9523fSMatthias Ringwald /* check bits 32-127 of UUID */ 868*d4d9523fSMatthias Ringwald if (uuid_size == 16){ 869*d4d9523fSMatthias Ringwald if (uuid_has_bluetooth_prefix(&packet[2]) == false){ 870*d4d9523fSMatthias Ringwald response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID; 871*d4d9523fSMatthias Ringwald } 872*d4d9523fSMatthias Ringwald if (uuid_has_bluetooth_prefix(&packet[2+16]) == false){ 873*d4d9523fSMatthias Ringwald response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID; 874*d4d9523fSMatthias Ringwald } 875*d4d9523fSMatthias Ringwald } 876*d4d9523fSMatthias Ringwald 8773deb3ec6SMatthias Ringwald /* Check source and destination UUIDs for valid combinations */ 8783deb3ec6SMatthias Ringwald if (response_code == BNEP_RESP_SETUP_SUCCESS) { 879f8fbdce0SMatthias Ringwald channel->uuid_dest = big_endian_read_16(packet, 2 + uuid_offset); 880f8fbdce0SMatthias Ringwald channel->uuid_source = big_endian_read_16(packet, 2 + uuid_offset + uuid_size); 8813deb3ec6SMatthias Ringwald 882235946f1SMatthias Ringwald if ((channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU) && 883235946f1SMatthias Ringwald (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_NAP) && 884235946f1SMatthias Ringwald (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_GN)) { 8853deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_REQUEST: Invalid destination service UUID: %04x", channel->uuid_dest); 8863deb3ec6SMatthias Ringwald channel->uuid_dest = 0; 8873deb3ec6SMatthias Ringwald } 888235946f1SMatthias Ringwald if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) && 889235946f1SMatthias Ringwald (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_NAP) && 890235946f1SMatthias Ringwald (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_GN)) { 8913deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_REQUEST: Invalid source service UUID: %04x", channel->uuid_source); 8923deb3ec6SMatthias Ringwald channel->uuid_source = 0; 8933deb3ec6SMatthias Ringwald } 8943deb3ec6SMatthias Ringwald 8953deb3ec6SMatthias Ringwald /* Check if we have registered a service for the requested destination UUID */ 8963deb3ec6SMatthias Ringwald service = bnep_service_for_uuid(channel->uuid_dest); 8973deb3ec6SMatthias Ringwald if (service == NULL) { 8983deb3ec6SMatthias Ringwald response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID; 8990c249750SMatthias Ringwald } else { 9000c249750SMatthias Ringwald // use packet handler for service 9010c249750SMatthias Ringwald channel->packet_handler = service->packet_handler; 9020c249750SMatthias Ringwald 903235946f1SMatthias Ringwald if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) && (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU)) { 9043deb3ec6SMatthias Ringwald response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID; 9053deb3ec6SMatthias Ringwald } 9063deb3ec6SMatthias Ringwald } 9070c249750SMatthias Ringwald } 9083deb3ec6SMatthias Ringwald 9093deb3ec6SMatthias Ringwald /* Set flag to send out the connection response on next statemachine cycle */ 9103deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE); 9113deb3ec6SMatthias Ringwald channel->response_code = response_code; 9124e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 9133deb3ec6SMatthias Ringwald 9143deb3ec6SMatthias Ringwald /* Return the number of processed package bytes = BNEP Type, BNEP Control Type, UUID-Size + 2 * UUID */ 915c1ab6cc1SMatthias Ringwald return 1 + 1 + (2 * uuid_size); 9163deb3ec6SMatthias Ringwald } 9173deb3ec6SMatthias Ringwald 9183deb3ec6SMatthias Ringwald static int bnep_handle_connection_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size) 9193deb3ec6SMatthias Ringwald { 9203deb3ec6SMatthias Ringwald uint16_t response_code; 9213deb3ec6SMatthias Ringwald 9223deb3ec6SMatthias Ringwald /* Sanity check packet size */ 923c1ab6cc1SMatthias Ringwald if (size < (1 + 2)) { 9243deb3ec6SMatthias Ringwald return 0; 9253deb3ec6SMatthias Ringwald } 9263deb3ec6SMatthias Ringwald 9273deb3ec6SMatthias Ringwald if (channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE) { 9283deb3ec6SMatthias Ringwald /* Ignore a connection response in any state but WAIT_FOR_CONNECTION_RESPONSE */ 9293deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_RESPONSE: Ignored in channel state %d", channel->state); 9303deb3ec6SMatthias Ringwald return 1 + 2; 9313deb3ec6SMatthias Ringwald } 9323deb3ec6SMatthias Ringwald 933f8fbdce0SMatthias Ringwald response_code = big_endian_read_16(packet, 1); 9343deb3ec6SMatthias Ringwald 9353deb3ec6SMatthias Ringwald if (response_code == BNEP_RESP_SETUP_SUCCESS) { 9363deb3ec6SMatthias Ringwald log_info("BNEP_CONNECTION_RESPONSE: Channel established to %s", bd_addr_to_str(channel->remote_addr)); 9373deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_CONNECTED; 9383deb3ec6SMatthias Ringwald /* Stop timeout timer! */ 9393deb3ec6SMatthias Ringwald bnep_channel_stop_timer(channel); 9403deb3ec6SMatthias Ringwald bnep_emit_open_channel_complete(channel, 0); 9413deb3ec6SMatthias Ringwald } else { 9423deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_RESPONSE: Connection to %s failed. Err: %d", bd_addr_to_str(channel->remote_addr), response_code); 9433deb3ec6SMatthias Ringwald bnep_channel_finalize(channel); 9443deb3ec6SMatthias Ringwald } 9453deb3ec6SMatthias Ringwald return 1 + 2; 9463deb3ec6SMatthias Ringwald } 9473deb3ec6SMatthias Ringwald 9483deb3ec6SMatthias Ringwald static int bnep_can_handle_extensions(bnep_channel_t * channel){ 9493deb3ec6SMatthias Ringwald /* Extension are primarily handled in CONNECTED state */ 9503deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) return 1; 9513deb3ec6SMatthias Ringwald /* and if we've received connection request, but haven't sent the reponse yet. */ 9523deb3ec6SMatthias Ringwald if ((channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) && 9533deb3ec6SMatthias Ringwald (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE)) { 9543deb3ec6SMatthias Ringwald return 1; 9553deb3ec6SMatthias Ringwald } 9563deb3ec6SMatthias Ringwald return 0; 9573deb3ec6SMatthias Ringwald } 9583deb3ec6SMatthias Ringwald 9593deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size) 9603deb3ec6SMatthias Ringwald { 9613deb3ec6SMatthias Ringwald uint16_t list_length; 9623deb3ec6SMatthias Ringwald uint16_t response_code = BNEP_RESP_FILTER_SUCCESS; 9633deb3ec6SMatthias Ringwald 9643deb3ec6SMatthias Ringwald /* Sanity check packet size */ 9653deb3ec6SMatthias Ringwald if (size < 3) { 9663deb3ec6SMatthias Ringwald return 0; 9673deb3ec6SMatthias Ringwald } 9683deb3ec6SMatthias Ringwald 969f8fbdce0SMatthias Ringwald list_length = big_endian_read_16(packet, 1); 9703deb3ec6SMatthias Ringwald /* Sanity check packet size again with known package size */ 971c1ab6cc1SMatthias Ringwald if (size < (3 + list_length)) { 9723deb3ec6SMatthias Ringwald return 0; 9733deb3ec6SMatthias Ringwald } 9743deb3ec6SMatthias Ringwald 9753deb3ec6SMatthias Ringwald if (!bnep_can_handle_extensions(channel)){ 9763deb3ec6SMatthias Ringwald log_error("BNEP_FILTER_NET_TYPE_SET: Ignored in channel state %d", channel->state); 9773deb3ec6SMatthias Ringwald return 3 + list_length; 9783deb3ec6SMatthias Ringwald } 9793deb3ec6SMatthias Ringwald 9803deb3ec6SMatthias Ringwald /* Check if we have enough space for more filters */ 9813deb3ec6SMatthias Ringwald if ((list_length / (2*2)) > MAX_BNEP_NETFILTER) { 9823deb3ec6SMatthias Ringwald log_info("BNEP_FILTER_NET_TYPE_SET: Too many filter"); 9833deb3ec6SMatthias Ringwald response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS; 9843deb3ec6SMatthias Ringwald } else { 9853deb3ec6SMatthias Ringwald int i; 9863deb3ec6SMatthias Ringwald channel->net_filter_count = 0; 9873deb3ec6SMatthias Ringwald /* There is still enough space, copy the filters to our filter list */ 988ef907034SMatthias Ringwald /* There is still enough space, copy the filters to our filter list */ 989c1ab6cc1SMatthias Ringwald for (i = 0; i < (list_length / (2 * 2)); i ++) { 990c1ab6cc1SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_start = big_endian_read_16(packet, 1 + 2 + (i * 4)); 991c1ab6cc1SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_end = big_endian_read_16(packet, 1 + 2 + (i * 4) + 2); 9923deb3ec6SMatthias Ringwald if (channel->net_filter[channel->net_filter_count].range_start > channel->net_filter[channel->net_filter_count].range_end) { 9933deb3ec6SMatthias Ringwald /* Invalid filter range, ignore this filter rule */ 9943deb3ec6SMatthias Ringwald log_error("BNEP_FILTER_NET_TYPE_SET: Invalid filter: start: %d, end: %d", 9953deb3ec6SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_start, 9963deb3ec6SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_end); 9973deb3ec6SMatthias Ringwald response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE; 9983deb3ec6SMatthias Ringwald } else { 9993deb3ec6SMatthias Ringwald /* Valid filter, increase the filter count */ 10003deb3ec6SMatthias Ringwald log_info("BNEP_FILTER_NET_TYPE_SET: Add filter: start: %d, end: %d", 10013deb3ec6SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_start, 10023deb3ec6SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_end); 10033deb3ec6SMatthias Ringwald channel->net_filter_count ++; 10043deb3ec6SMatthias Ringwald } 10053deb3ec6SMatthias Ringwald } 10063deb3ec6SMatthias Ringwald } 10073deb3ec6SMatthias Ringwald 10083deb3ec6SMatthias Ringwald /* Set flag to send out the set net filter response on next statemachine cycle */ 10093deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE); 10103deb3ec6SMatthias Ringwald channel->response_code = response_code; 10114e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 10123deb3ec6SMatthias Ringwald 10133deb3ec6SMatthias Ringwald return 3 + list_length; 10143deb3ec6SMatthias Ringwald } 10153deb3ec6SMatthias Ringwald 10163deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size) 10173deb3ec6SMatthias Ringwald { 10183deb3ec6SMatthias Ringwald uint16_t response_code; 10193deb3ec6SMatthias Ringwald 10203deb3ec6SMatthias Ringwald // TODO: Currently we do not support setting a network filter. 10213deb3ec6SMatthias Ringwald 10223deb3ec6SMatthias Ringwald /* Sanity check packet size */ 1023c1ab6cc1SMatthias Ringwald if (size < (1 + 2)) { 10243deb3ec6SMatthias Ringwald return 0; 10253deb3ec6SMatthias Ringwald } 10263deb3ec6SMatthias Ringwald 10273deb3ec6SMatthias Ringwald if (!bnep_can_handle_extensions(channel)){ 10283deb3ec6SMatthias Ringwald log_error("BNEP_FILTER_NET_TYPE_RESPONSE: Ignored in channel state %d", channel->state); 10293deb3ec6SMatthias Ringwald return 1 + 2; 10303deb3ec6SMatthias Ringwald } 10313deb3ec6SMatthias Ringwald 1032f8fbdce0SMatthias Ringwald response_code = big_endian_read_16(packet, 1); 10333deb3ec6SMatthias Ringwald 10343deb3ec6SMatthias Ringwald if (response_code == BNEP_RESP_FILTER_SUCCESS) { 10353deb3ec6SMatthias Ringwald log_info("BNEP_FILTER_NET_TYPE_RESPONSE: Net filter set successfully for %s", bd_addr_to_str(channel->remote_addr)); 10363deb3ec6SMatthias Ringwald } else { 10373deb3ec6SMatthias Ringwald log_error("BNEP_FILTER_NET_TYPE_RESPONSE: Net filter setting for %s failed. Err: %d", bd_addr_to_str(channel->remote_addr), response_code); 10383deb3ec6SMatthias Ringwald } 10393deb3ec6SMatthias Ringwald 10403deb3ec6SMatthias Ringwald return 1 + 2; 10413deb3ec6SMatthias Ringwald } 10423deb3ec6SMatthias Ringwald 10433deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size) 10443deb3ec6SMatthias Ringwald { 10453deb3ec6SMatthias Ringwald uint16_t list_length; 10463deb3ec6SMatthias Ringwald uint16_t response_code = BNEP_RESP_FILTER_SUCCESS; 10473deb3ec6SMatthias Ringwald 10483deb3ec6SMatthias Ringwald /* Sanity check packet size */ 10493deb3ec6SMatthias Ringwald if (size < 3) { 10503deb3ec6SMatthias Ringwald return 0; 10513deb3ec6SMatthias Ringwald } 10523deb3ec6SMatthias Ringwald 1053f8fbdce0SMatthias Ringwald list_length = big_endian_read_16(packet, 1); 10543deb3ec6SMatthias Ringwald /* Sanity check packet size again with known package size */ 1055c1ab6cc1SMatthias Ringwald if (size < (3 + list_length)) { 10563deb3ec6SMatthias Ringwald return 0; 10573deb3ec6SMatthias Ringwald } 10583deb3ec6SMatthias Ringwald 10593deb3ec6SMatthias Ringwald if (!bnep_can_handle_extensions(channel)){ 10603deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_SET: Ignored in channel state %d", channel->state); 10613deb3ec6SMatthias Ringwald return 3 + list_length; 10623deb3ec6SMatthias Ringwald } 10633deb3ec6SMatthias Ringwald 10643deb3ec6SMatthias Ringwald /* Check if we have enough space for more filters */ 1065b56e8b56SMatthias Ringwald uint16_t list_count = list_length / (2 * ETHER_ADDR_LEN); 1066b56e8b56SMatthias Ringwald if (list_count > MAX_BNEP_MULTICAST_FILTER) { 10673deb3ec6SMatthias Ringwald log_info("BNEP_MULTI_ADDR_SET: Too many filter"); 10683deb3ec6SMatthias Ringwald response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS; 10693deb3ec6SMatthias Ringwald } else { 10703deb3ec6SMatthias Ringwald unsigned int i; 10713deb3ec6SMatthias Ringwald channel->multicast_filter_count = 0; 10723deb3ec6SMatthias Ringwald /* There is enough space, copy the filters to our filter list */ 1073b56e8b56SMatthias Ringwald for (i = 0; i < list_count; i ++) { 1074c1ab6cc1SMatthias Ringwald bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_start, packet + 1 + 2 + (i * ETHER_ADDR_LEN * 2)); 1075c1ab6cc1SMatthias Ringwald bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_end, packet + 1 + 2 + (i * ETHER_ADDR_LEN * 2) + ETHER_ADDR_LEN); 10763deb3ec6SMatthias Ringwald 10773deb3ec6SMatthias Ringwald if (memcmp(channel->multicast_filter[channel->multicast_filter_count].addr_start, 10783deb3ec6SMatthias Ringwald channel->multicast_filter[channel->multicast_filter_count].addr_end, ETHER_ADDR_LEN) > 0) { 10793deb3ec6SMatthias Ringwald /* Invalid filter range, ignore this filter rule */ 10803deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_SET: Invalid filter: start: %s", 10813deb3ec6SMatthias Ringwald bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start)); 10823deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_SET: Invalid filter: end: %s", 10833deb3ec6SMatthias Ringwald bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end)); 10843deb3ec6SMatthias Ringwald response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE; 10853deb3ec6SMatthias Ringwald } else { 10863deb3ec6SMatthias Ringwald /* Valid filter, increase the filter count */ 10873deb3ec6SMatthias Ringwald log_info("BNEP_MULTI_ADDR_SET: Add filter: start: %s", 10883deb3ec6SMatthias Ringwald bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start)); 10893deb3ec6SMatthias Ringwald log_info("BNEP_MULTI_ADDR_SET: Add filter: end: %s", 10903deb3ec6SMatthias Ringwald bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end)); 10913deb3ec6SMatthias Ringwald channel->multicast_filter_count ++; 10923deb3ec6SMatthias Ringwald } 10933deb3ec6SMatthias Ringwald } 10943deb3ec6SMatthias Ringwald } 10953deb3ec6SMatthias Ringwald /* Set flag to send out the set multi addr response on next statemachine cycle */ 10963deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE); 10973deb3ec6SMatthias Ringwald channel->response_code = response_code; 10984e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 10993deb3ec6SMatthias Ringwald 11003deb3ec6SMatthias Ringwald return 3 + list_length; 11013deb3ec6SMatthias Ringwald } 11023deb3ec6SMatthias Ringwald 11033deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size) 11043deb3ec6SMatthias Ringwald { 11053deb3ec6SMatthias Ringwald uint16_t response_code; 11063deb3ec6SMatthias Ringwald 11073deb3ec6SMatthias Ringwald // TODO: Currently we do not support setting multicast address filter. 11083deb3ec6SMatthias Ringwald 11093deb3ec6SMatthias Ringwald /* Sanity check packet size */ 1110c1ab6cc1SMatthias Ringwald if (size < (1 + 2)) { 11113deb3ec6SMatthias Ringwald return 0; 11123deb3ec6SMatthias Ringwald } 11133deb3ec6SMatthias Ringwald 11143deb3ec6SMatthias Ringwald if (!bnep_can_handle_extensions(channel)){ 11153deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_RESPONSE: Ignored in channel state %d", channel->state); 11163deb3ec6SMatthias Ringwald return 1 + 2; 11173deb3ec6SMatthias Ringwald } 11183deb3ec6SMatthias Ringwald 1119f8fbdce0SMatthias Ringwald response_code = big_endian_read_16(packet, 1); 11203deb3ec6SMatthias Ringwald 11213deb3ec6SMatthias Ringwald if (response_code == BNEP_RESP_FILTER_SUCCESS) { 11223deb3ec6SMatthias Ringwald log_info("BNEP_MULTI_ADDR_RESPONSE: Multicast address filter set successfully for %s", bd_addr_to_str(channel->remote_addr)); 11233deb3ec6SMatthias Ringwald } else { 11243deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_RESPONSE: Multicast address filter setting for %s failed. Err: %d", bd_addr_to_str(channel->remote_addr), response_code); 11253deb3ec6SMatthias Ringwald } 11263deb3ec6SMatthias Ringwald 11273deb3ec6SMatthias Ringwald return 1 + 2; 11283deb3ec6SMatthias Ringwald } 11293deb3ec6SMatthias Ringwald 11303deb3ec6SMatthias Ringwald static int bnep_handle_ethernet_packet(bnep_channel_t *channel, bd_addr_t addr_dest, bd_addr_t addr_source, uint16_t network_protocol_type, uint8_t *payload, uint16_t size) 11313deb3ec6SMatthias Ringwald { 11323deb3ec6SMatthias Ringwald uint16_t pos = 0; 11333deb3ec6SMatthias Ringwald 1134f2e45468SMatthias Ringwald #if defined(HCI_INCOMING_PRE_BUFFER_SIZE) && (HCI_INCOMING_PRE_BUFFER_SIZE >= 14 - 8) // 2 * sizeof(bd_addr_t) + sizeof(uint16_t) - L2CAP Header (4) - ACL Header (4) 11353deb3ec6SMatthias Ringwald /* In-place modify the package and add the ethernet header in front of the payload. 11363deb3ec6SMatthias Ringwald * WARNING: This modifies the data in front of the payload and may overwrite 14 bytes there! 11373deb3ec6SMatthias Ringwald */ 11380e588213SMatthias Ringwald uint8_t *ethernet_packet = payload - (2 * sizeof(bd_addr_t)) - sizeof(uint16_t); 11393deb3ec6SMatthias Ringwald /* Restore the ethernet packet header */ 1140058e3d6bSMatthias Ringwald bd_addr_copy(ethernet_packet + pos, addr_dest); 11413deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t); 1142058e3d6bSMatthias Ringwald bd_addr_copy(ethernet_packet + pos, addr_source); 11433deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t); 1144f8fbdce0SMatthias Ringwald big_endian_store_16(ethernet_packet, pos, network_protocol_type); 11453deb3ec6SMatthias Ringwald /* Payload is just in place... */ 11463deb3ec6SMatthias Ringwald #else 1147f2e45468SMatthias Ringwald #error "BNEP requires HCI_INCOMING_PRE_BUFFER_SIZE >= 6. Please update bstack_config.h" 11483deb3ec6SMatthias Ringwald #endif 11493deb3ec6SMatthias Ringwald 11503deb3ec6SMatthias Ringwald /* Notify application layer and deliver the ethernet packet */ 1151c9bf9c27SMatthias Ringwald if (channel->packet_handler){ 1152c9bf9c27SMatthias Ringwald (*channel->packet_handler)(BNEP_DATA_PACKET, channel->l2cap_cid, ethernet_packet, 11530e588213SMatthias Ringwald size + sizeof(uint16_t) + (2 * sizeof(bd_addr_t)) ); 1154c9bf9c27SMatthias Ringwald } 11553deb3ec6SMatthias Ringwald 11563deb3ec6SMatthias Ringwald return size; 11573deb3ec6SMatthias Ringwald } 11583deb3ec6SMatthias Ringwald 11593deb3ec6SMatthias Ringwald static int bnep_handle_control_packet(bnep_channel_t *channel, uint8_t *packet, uint16_t size, int is_extension) 11603deb3ec6SMatthias Ringwald { 11613deb3ec6SMatthias Ringwald uint16_t len = 0; 11623deb3ec6SMatthias Ringwald 1163b85ad952SMatthias Ringwald if (size > 0) { 1164b85ad952SMatthias Ringwald 1165b85ad952SMatthias Ringwald uint8_t bnep_control_type = packet[0]; 11663deb3ec6SMatthias Ringwald /* Save last control type. Needed by statemachin in case of unknown control code */ 11673deb3ec6SMatthias Ringwald 11683deb3ec6SMatthias Ringwald channel->last_control_type = bnep_control_type; 11693deb3ec6SMatthias Ringwald log_info("BNEP_CONTROL: Type: %d, size: %d, is_extension: %d", bnep_control_type, size, is_extension); 11703deb3ec6SMatthias Ringwald switch (bnep_control_type) { 11713deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD: 11723deb3ec6SMatthias Ringwald /* The last command we send was not understood. We should close the connection */ 1173b85ad952SMatthias Ringwald log_error("BNEP_CONTROL: Received COMMAND_NOT_UNDERSTOOD: l2cap_cid: %d, cmd: %d", channel->l2cap_cid, 1174b85ad952SMatthias Ringwald packet[3]); 11753deb3ec6SMatthias Ringwald bnep_channel_finalize(channel); 11763deb3ec6SMatthias Ringwald len = 2; // Length of command not understood packet - bnep-type field 11773deb3ec6SMatthias Ringwald break; 11783deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST: 11793deb3ec6SMatthias Ringwald if (is_extension) { 11803deb3ec6SMatthias Ringwald /* Connection requests are not allowed to be send in an extension header 11813deb3ec6SMatthias Ringwald * ignore, do not set "COMMAND_NOT_UNDERSTOOD" 11823deb3ec6SMatthias Ringwald */ 1183b85ad952SMatthias Ringwald log_error("BNEP_CONTROL: Received SETUP_CONNECTION_REQUEST in extension header: l2cap_cid: %d", 1184b85ad952SMatthias Ringwald channel->l2cap_cid); 11853deb3ec6SMatthias Ringwald return 0; 11863deb3ec6SMatthias Ringwald } else { 11873deb3ec6SMatthias Ringwald len = bnep_handle_connection_request(channel, packet, size); 11883deb3ec6SMatthias Ringwald } 11893deb3ec6SMatthias Ringwald break; 11903deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE: 11913deb3ec6SMatthias Ringwald if (is_extension) { 11923deb3ec6SMatthias Ringwald /* Connection requests are not allowed to be send in an 11933deb3ec6SMatthias Ringwald * extension header, ignore, do not set "COMMAND_NOT_UNDERSTOOD" 11943deb3ec6SMatthias Ringwald */ 1195b85ad952SMatthias Ringwald log_error("BNEP_CONTROL: Received SETUP_CONNECTION_RESPONSE in extension header: l2cap_cid: %d", 1196b85ad952SMatthias Ringwald channel->l2cap_cid); 11973deb3ec6SMatthias Ringwald return 0; 11983deb3ec6SMatthias Ringwald } else { 11993deb3ec6SMatthias Ringwald len = bnep_handle_connection_response(channel, packet, size); 12003deb3ec6SMatthias Ringwald } 12013deb3ec6SMatthias Ringwald break; 12023deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET: 12033deb3ec6SMatthias Ringwald len = bnep_handle_filter_net_type_set(channel, packet, size); 12043deb3ec6SMatthias Ringwald break; 12053deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE: 12063deb3ec6SMatthias Ringwald len = bnep_handle_filter_net_type_response(channel, packet, size); 12073deb3ec6SMatthias Ringwald break; 12083deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET: 12093deb3ec6SMatthias Ringwald len = bnep_handle_multi_addr_set(channel, packet, size); 12103deb3ec6SMatthias Ringwald break; 12113deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE: 12123deb3ec6SMatthias Ringwald len = bnep_handle_multi_addr_response(channel, packet, size); 12133deb3ec6SMatthias Ringwald break; 12143deb3ec6SMatthias Ringwald default: 1215b85ad952SMatthias Ringwald log_error("BNEP_CONTROL: Invalid bnep control type: l2cap_cid: %d, cmd: %d", channel->l2cap_cid, 1216b85ad952SMatthias Ringwald bnep_control_type); 12173deb3ec6SMatthias Ringwald len = 0; 12183deb3ec6SMatthias Ringwald break; 12193deb3ec6SMatthias Ringwald } 1220b85ad952SMatthias Ringwald } 12213deb3ec6SMatthias Ringwald 12223deb3ec6SMatthias Ringwald if (len == 0) { 12233deb3ec6SMatthias Ringwald /* In case the command could not be handled, send a 12243deb3ec6SMatthias Ringwald COMMAND_NOT_UNDERSTOOD message. 12253deb3ec6SMatthias Ringwald Set flag to process the request in the next statemachine loop 12263deb3ec6SMatthias Ringwald */ 12273deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD); 12284e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 12293deb3ec6SMatthias Ringwald } 12303deb3ec6SMatthias Ringwald 12313deb3ec6SMatthias Ringwald return len; 12323deb3ec6SMatthias Ringwald } 12333deb3ec6SMatthias Ringwald 12343deb3ec6SMatthias Ringwald /** 12353deb3ec6SMatthias Ringwald * @return handled packet 12363deb3ec6SMatthias Ringwald */ 12373deb3ec6SMatthias Ringwald static int bnep_hci_event_handler(uint8_t *packet, uint16_t size) 12383deb3ec6SMatthias Ringwald { 1239f21eb74fSMatthias Ringwald UNUSED(size); // ok: handling own l2cap events 12409ec2630cSMatthias Ringwald 12413deb3ec6SMatthias Ringwald bd_addr_t event_addr; 12423deb3ec6SMatthias Ringwald uint16_t psm; 12433deb3ec6SMatthias Ringwald uint16_t l2cap_cid; 12443deb3ec6SMatthias Ringwald hci_con_handle_t con_handle; 12453deb3ec6SMatthias Ringwald bnep_channel_t *channel = NULL; 12463deb3ec6SMatthias Ringwald uint8_t status; 12473deb3ec6SMatthias Ringwald 12480e2df43fSMatthias Ringwald switch (hci_event_packet_get_type(packet)) { 12493deb3ec6SMatthias Ringwald 125084e3541eSMilanka Ringwald /* Accept an incoming L2CAP connection on BLUETOOTH_PSM_BNEP */ 12513deb3ec6SMatthias Ringwald case L2CAP_EVENT_INCOMING_CONNECTION: 12523deb3ec6SMatthias Ringwald /* L2CAP event data: event(8), len(8), address(48), handle (16), psm (16), source cid(16) dest cid(16) */ 1253724d70a2SMatthias Ringwald reverse_bd_addr(&packet[2], event_addr); 1254f8fbdce0SMatthias Ringwald con_handle = little_endian_read_16(packet, 8); 1255f8fbdce0SMatthias Ringwald psm = little_endian_read_16(packet, 10); 1256f8fbdce0SMatthias Ringwald l2cap_cid = little_endian_read_16(packet, 12); 12573deb3ec6SMatthias Ringwald 125884e3541eSMilanka Ringwald if (psm != BLUETOOTH_PSM_BNEP) break; 12593deb3ec6SMatthias Ringwald 12603deb3ec6SMatthias Ringwald channel = bnep_channel_for_addr(event_addr); 12613deb3ec6SMatthias Ringwald 12623deb3ec6SMatthias Ringwald if (channel) { 126384e3541eSMilanka Ringwald log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => decline - channel already exists", l2cap_cid); 12647ef6a7bbSMatthias Ringwald l2cap_decline_connection(l2cap_cid); 12653deb3ec6SMatthias Ringwald return 1; 12663deb3ec6SMatthias Ringwald } 12673deb3ec6SMatthias Ringwald 12683deb3ec6SMatthias Ringwald /* Create a new BNEP channel instance (incoming) */ 12693deb3ec6SMatthias Ringwald channel = bnep_channel_create_for_addr(event_addr); 12703deb3ec6SMatthias Ringwald 12713deb3ec6SMatthias Ringwald if (!channel) { 127284e3541eSMilanka Ringwald log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => decline - no memory left", l2cap_cid); 12737ef6a7bbSMatthias Ringwald l2cap_decline_connection(l2cap_cid); 12743deb3ec6SMatthias Ringwald return 1; 12753deb3ec6SMatthias Ringwald } 12763deb3ec6SMatthias Ringwald 12773deb3ec6SMatthias Ringwald /* Assign connection handle and l2cap cid */ 12783deb3ec6SMatthias Ringwald channel->con_handle = con_handle; 12793deb3ec6SMatthias Ringwald channel->l2cap_cid = l2cap_cid; 12803deb3ec6SMatthias Ringwald 12813deb3ec6SMatthias Ringwald /* Set channel into accept state */ 12823deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST; 12833deb3ec6SMatthias Ringwald 12843deb3ec6SMatthias Ringwald /* Start connection timeout timer */ 12853deb3ec6SMatthias Ringwald bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS); 12863deb3ec6SMatthias Ringwald 128784e3541eSMilanka Ringwald log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => accept", l2cap_cid); 1288ce8f182eSMatthias Ringwald l2cap_accept_connection(l2cap_cid); 12893deb3ec6SMatthias Ringwald return 1; 12903deb3ec6SMatthias Ringwald 12913deb3ec6SMatthias Ringwald /* Outgoing L2CAP connection has been opened -> store l2cap_cid, remote_addr */ 12923deb3ec6SMatthias Ringwald case L2CAP_EVENT_CHANNEL_OPENED: 12933deb3ec6SMatthias Ringwald status = packet[2]; 129484e3541eSMilanka Ringwald log_info("L2CAP_EVENT_CHANNEL_OPENED for BLUETOOTH_PSM_BNEP, status %u", status); 12953deb3ec6SMatthias Ringwald 12963deb3ec6SMatthias Ringwald /* Get the bnep channel fpr remote address */ 1297f8fbdce0SMatthias Ringwald con_handle = little_endian_read_16(packet, 9); 1298f8fbdce0SMatthias Ringwald l2cap_cid = little_endian_read_16(packet, 13); 1299724d70a2SMatthias Ringwald reverse_bd_addr(&packet[3], event_addr); 13003deb3ec6SMatthias Ringwald channel = bnep_channel_for_addr(event_addr); 13013deb3ec6SMatthias Ringwald if (!channel) { 13023deb3ec6SMatthias Ringwald log_error("L2CAP_EVENT_CHANNEL_OPENED but no BNEP channel prepared"); 13033deb3ec6SMatthias Ringwald return 1; 13043deb3ec6SMatthias Ringwald } 13053deb3ec6SMatthias Ringwald 13063deb3ec6SMatthias Ringwald /* On L2CAP open error discard everything */ 13073deb3ec6SMatthias Ringwald if (status) { 13083deb3ec6SMatthias Ringwald /* Emit bnep_open_channel_complete with status and free channel */ 13093deb3ec6SMatthias Ringwald bnep_emit_open_channel_complete(channel, status); 13103deb3ec6SMatthias Ringwald 13113deb3ec6SMatthias Ringwald /* Free BNEP channel mempory */ 13123deb3ec6SMatthias Ringwald bnep_channel_free(channel); 13133deb3ec6SMatthias Ringwald return 1; 13143deb3ec6SMatthias Ringwald } 13153deb3ec6SMatthias Ringwald 13163deb3ec6SMatthias Ringwald switch (channel->state){ 13173deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_CLOSED: 13183deb3ec6SMatthias Ringwald log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection"); 13193deb3ec6SMatthias Ringwald 13203deb3ec6SMatthias Ringwald bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS); 13213deb3ec6SMatthias Ringwald 13223deb3ec6SMatthias Ringwald /* Assign connection handle and l2cap cid */ 13233deb3ec6SMatthias Ringwald channel->l2cap_cid = l2cap_cid; 13243deb3ec6SMatthias Ringwald channel->con_handle = con_handle; 13253deb3ec6SMatthias Ringwald 13263deb3ec6SMatthias Ringwald /* Initiate the connection request */ 13273deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE; 13283deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST); 1329f8fbdce0SMatthias Ringwald channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17)); 13304e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 13313deb3ec6SMatthias Ringwald break; 13323deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST: 13333deb3ec6SMatthias Ringwald /* New information: channel mtu */ 1334f8fbdce0SMatthias Ringwald channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17)); 13353deb3ec6SMatthias Ringwald break; 13363deb3ec6SMatthias Ringwald default: 13373deb3ec6SMatthias Ringwald log_error("L2CAP_EVENT_CHANNEL_OPENED: Invalid state: %d", channel->state); 13383deb3ec6SMatthias Ringwald break; 13393deb3ec6SMatthias Ringwald } 13403deb3ec6SMatthias Ringwald return 1; 13413deb3ec6SMatthias Ringwald 13421b89a84bSMatthias Ringwald case L2CAP_EVENT_CAN_SEND_NOW: 13434e366553SMatthias Ringwald bnep_handle_can_send_now(l2cap_event_can_send_now_get_local_cid(packet)); 13443deb3ec6SMatthias Ringwald break; 13453deb3ec6SMatthias Ringwald 13463deb3ec6SMatthias Ringwald case L2CAP_EVENT_CHANNEL_CLOSED: 13473deb3ec6SMatthias Ringwald // data: event (8), len(8), channel (16) 1348f8fbdce0SMatthias Ringwald l2cap_cid = little_endian_read_16(packet, 2); 13493deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(l2cap_cid); 13503deb3ec6SMatthias Ringwald log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, channel %p", l2cap_cid, channel); 13513deb3ec6SMatthias Ringwald 13523deb3ec6SMatthias Ringwald if (!channel) { 13533deb3ec6SMatthias Ringwald break; 13543deb3ec6SMatthias Ringwald } 13553deb3ec6SMatthias Ringwald 13563deb3ec6SMatthias Ringwald log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", channel->state); 13573deb3ec6SMatthias Ringwald switch (channel->state) { 13583deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST: 13593deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE: 13603deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_CONNECTED: 13613deb3ec6SMatthias Ringwald bnep_channel_finalize(channel); 13623deb3ec6SMatthias Ringwald return 1; 13633deb3ec6SMatthias Ringwald default: 13643deb3ec6SMatthias Ringwald break; 13653deb3ec6SMatthias Ringwald } 13663deb3ec6SMatthias Ringwald break; 13673deb3ec6SMatthias Ringwald default: 13683deb3ec6SMatthias Ringwald break; 13693deb3ec6SMatthias Ringwald } 13703deb3ec6SMatthias Ringwald return 0; 13713deb3ec6SMatthias Ringwald } 13723deb3ec6SMatthias Ringwald 13733deb3ec6SMatthias Ringwald static int bnep_l2cap_packet_handler(uint16_t l2cap_cid, uint8_t *packet, uint16_t size) 13743deb3ec6SMatthias Ringwald { 13753deb3ec6SMatthias Ringwald int rc = 0; 13763deb3ec6SMatthias Ringwald uint8_t bnep_type; 13773deb3ec6SMatthias Ringwald uint8_t bnep_header_has_ext; 13783deb3ec6SMatthias Ringwald uint8_t extension_type; 13793deb3ec6SMatthias Ringwald uint16_t pos = 0; 13803deb3ec6SMatthias Ringwald bd_addr_t addr_source; 13813deb3ec6SMatthias Ringwald bd_addr_t addr_dest; 13823deb3ec6SMatthias Ringwald uint16_t network_protocol_type = 0xffff; 13833deb3ec6SMatthias Ringwald bnep_channel_t *channel = NULL; 13843deb3ec6SMatthias Ringwald 13853deb3ec6SMatthias Ringwald /* Get the bnep channel for this package */ 13863deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(l2cap_cid); 13873deb3ec6SMatthias Ringwald if (!channel) { 13883deb3ec6SMatthias Ringwald return rc; 13893deb3ec6SMatthias Ringwald } 13903deb3ec6SMatthias Ringwald 13913deb3ec6SMatthias Ringwald /* Sort out short packages */ 13923deb3ec6SMatthias Ringwald if (size < 2) { 13933deb3ec6SMatthias Ringwald return rc; 13943deb3ec6SMatthias Ringwald } 13953deb3ec6SMatthias Ringwald 13963deb3ec6SMatthias Ringwald bnep_type = BNEP_TYPE(packet[pos]); 13973deb3ec6SMatthias Ringwald bnep_header_has_ext = BNEP_HEADER_HAS_EXT(packet[pos]); 13983deb3ec6SMatthias Ringwald pos ++; 13993deb3ec6SMatthias Ringwald 14003deb3ec6SMatthias Ringwald switch(bnep_type) { 14013deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_GENERAL_ETHERNET: 1402b85ad952SMatthias Ringwald if ((pos + 14) > size) { 1403b85ad952SMatthias Ringwald return rc; 1404b85ad952SMatthias Ringwald } 1405058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, &packet[pos]); 14063deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t); 1407058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, &packet[pos]); 14083deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t); 1409f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos); 14103deb3ec6SMatthias Ringwald pos += 2; 14113deb3ec6SMatthias Ringwald break; 14123deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_COMPRESSED_ETHERNET: 1413b85ad952SMatthias Ringwald if ((pos + 2) > size) { 1414b85ad952SMatthias Ringwald return rc; 1415b85ad952SMatthias Ringwald } 1416058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, channel->local_addr); 1417058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, channel->remote_addr); 1418f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos); 14193deb3ec6SMatthias Ringwald pos += 2; 14203deb3ec6SMatthias Ringwald break; 14213deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY: 1422b85ad952SMatthias Ringwald if ((pos + 8) > size) { 1423b85ad952SMatthias Ringwald return rc; 1424b85ad952SMatthias Ringwald } 1425058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, channel->local_addr); 1426058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, &packet[pos]); 14273deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t); 1428f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos); 14293deb3ec6SMatthias Ringwald pos += 2; 14303deb3ec6SMatthias Ringwald break; 14313deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY: 1432b85ad952SMatthias Ringwald if ((pos + 8) > size) { 1433b85ad952SMatthias Ringwald return rc; 1434b85ad952SMatthias Ringwald } 1435058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, &packet[pos]); 14363deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t); 1437058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, channel->remote_addr); 1438f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos); 14393deb3ec6SMatthias Ringwald pos += 2; 14403deb3ec6SMatthias Ringwald break; 14413deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_CONTROL: 14423deb3ec6SMatthias Ringwald rc = bnep_handle_control_packet(channel, packet + pos, size - pos, 0); 1443b85ad952SMatthias Ringwald if (rc == 0){ 1444b85ad952SMatthias Ringwald // invalid control packet 1445b85ad952SMatthias Ringwald return 0; 1446b85ad952SMatthias Ringwald } 14473deb3ec6SMatthias Ringwald pos += rc; 14483deb3ec6SMatthias Ringwald break; 14493deb3ec6SMatthias Ringwald default: 14503deb3ec6SMatthias Ringwald break; 14513deb3ec6SMatthias Ringwald } 14523deb3ec6SMatthias Ringwald 14533deb3ec6SMatthias Ringwald if (bnep_header_has_ext) { 14543deb3ec6SMatthias Ringwald do { 14553deb3ec6SMatthias Ringwald uint8_t ext_len; 14563deb3ec6SMatthias Ringwald 1457b85ad952SMatthias Ringwald if (pos + 2 > size) { 1458b85ad952SMatthias Ringwald return rc; 1459b85ad952SMatthias Ringwald } 1460b85ad952SMatthias Ringwald 14613deb3ec6SMatthias Ringwald /* Read extension type and check for further extensions */ 14623deb3ec6SMatthias Ringwald extension_type = BNEP_TYPE(packet[pos]); 14633deb3ec6SMatthias Ringwald bnep_header_has_ext = BNEP_HEADER_HAS_EXT(packet[pos]); 14643deb3ec6SMatthias Ringwald pos ++; 14653deb3ec6SMatthias Ringwald 14663deb3ec6SMatthias Ringwald /* Read extension header length */ 14673deb3ec6SMatthias Ringwald ext_len = packet[pos]; 14683deb3ec6SMatthias Ringwald pos ++; 14693deb3ec6SMatthias Ringwald 1470c1ab6cc1SMatthias Ringwald if ((size - pos) < ext_len) { 14713deb3ec6SMatthias Ringwald return 0; 14723deb3ec6SMatthias Ringwald } 14733deb3ec6SMatthias Ringwald 14743deb3ec6SMatthias Ringwald switch (extension_type) { 14753deb3ec6SMatthias Ringwald case BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL: 14763deb3ec6SMatthias Ringwald if (ext_len != bnep_handle_control_packet(channel, packet + pos, ext_len, 1)) { 14773deb3ec6SMatthias Ringwald log_error("BNEP pkt handler: Ignore invalid control packet in extension header"); 14783deb3ec6SMatthias Ringwald } 14793deb3ec6SMatthias Ringwald 14803deb3ec6SMatthias Ringwald pos += ext_len; 14813deb3ec6SMatthias Ringwald break; 14823deb3ec6SMatthias Ringwald 14833deb3ec6SMatthias Ringwald default: 1484b85ad952SMatthias Ringwald /* Extension header type unknown. Unknown extension SHALL be forwarded 1485b85ad952SMatthias Ringwald * in any way. But who shall handle these extension packets? 14863deb3ec6SMatthias Ringwald * For now: We ignore them and just drop them! 14873deb3ec6SMatthias Ringwald */ 14883deb3ec6SMatthias Ringwald log_error("BNEP pkt handler: Unknown extension type ignored, data dropped!"); 14893deb3ec6SMatthias Ringwald pos += ext_len; 14903deb3ec6SMatthias Ringwald break; 14913deb3ec6SMatthias Ringwald } 14923deb3ec6SMatthias Ringwald 14933deb3ec6SMatthias Ringwald } while (bnep_header_has_ext); 14943deb3ec6SMatthias Ringwald } 14953deb3ec6SMatthias Ringwald 1496c1ab6cc1SMatthias Ringwald if ((bnep_type != BNEP_PKT_TYPE_CONTROL) && (network_protocol_type != 0xffff)) { 14973deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) { 14983deb3ec6SMatthias Ringwald rc = bnep_handle_ethernet_packet(channel, addr_dest, addr_source, network_protocol_type, packet + pos, size - pos); 14993deb3ec6SMatthias Ringwald } else { 15003deb3ec6SMatthias Ringwald rc = 0; 15013deb3ec6SMatthias Ringwald } 15023deb3ec6SMatthias Ringwald } 15033deb3ec6SMatthias Ringwald 15043deb3ec6SMatthias Ringwald return rc; 15053deb3ec6SMatthias Ringwald 15063deb3ec6SMatthias Ringwald } 15073deb3ec6SMatthias Ringwald 15083deb3ec6SMatthias Ringwald void bnep_packet_handler(uint8_t packet_type, uint16_t l2cap_cid, uint8_t *packet, uint16_t size) 15093deb3ec6SMatthias Ringwald { 15103deb3ec6SMatthias Ringwald switch (packet_type) { 15113deb3ec6SMatthias Ringwald case HCI_EVENT_PACKET: 1512bef9a6fcSMatthias Ringwald bnep_hci_event_handler(packet, size); 15133deb3ec6SMatthias Ringwald break; 15143deb3ec6SMatthias Ringwald case L2CAP_DATA_PACKET: 1515bef9a6fcSMatthias Ringwald bnep_l2cap_packet_handler(l2cap_cid, packet, size); 15163deb3ec6SMatthias Ringwald break; 15173deb3ec6SMatthias Ringwald default: 15183deb3ec6SMatthias Ringwald break; 15193deb3ec6SMatthias Ringwald } 15203deb3ec6SMatthias Ringwald } 15213deb3ec6SMatthias Ringwald 15223deb3ec6SMatthias Ringwald static void bnep_channel_state_machine(bnep_channel_t* channel, bnep_channel_event_t *event) 15233deb3ec6SMatthias Ringwald { 1524b42623deSMatthias Ringwald log_debug("bnep_state_machine: state %u, state var: %02x, event %u", channel->state, channel->state_var, event->type); 15253deb3ec6SMatthias Ringwald 15263deb3ec6SMatthias Ringwald if (event->type == BNEP_CH_EVT_READY_TO_SEND) { 15273deb3ec6SMatthias Ringwald /* Send outstanding packets. */ 15283deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD) { 15293deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD); 15303deb3ec6SMatthias Ringwald bnep_send_command_not_understood(channel, channel->last_control_type); 15313deb3ec6SMatthias Ringwald return; 15323deb3ec6SMatthias Ringwald } 15333deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST) { 15343deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST); 15353deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE; 15363deb3ec6SMatthias Ringwald bnep_send_connection_request(channel, channel->uuid_source, channel->uuid_dest); 15373deb3ec6SMatthias Ringwald } 15383deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE) { 15393deb3ec6SMatthias Ringwald int emit_connected = 0; 15403deb3ec6SMatthias Ringwald if ((channel->state == BNEP_CHANNEL_STATE_CLOSED) || 15413deb3ec6SMatthias Ringwald (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST)) { 15423deb3ec6SMatthias Ringwald /* Set channel state to STATE_CONNECTED */ 15433deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_CONNECTED; 15443deb3ec6SMatthias Ringwald /* Stop timeout timer! */ 15453deb3ec6SMatthias Ringwald bnep_channel_stop_timer(channel); 15463deb3ec6SMatthias Ringwald emit_connected = 1; 15473deb3ec6SMatthias Ringwald } 15483deb3ec6SMatthias Ringwald 15493deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE); 15503deb3ec6SMatthias Ringwald bnep_send_connection_response(channel, channel->response_code); 15513deb3ec6SMatthias Ringwald if (emit_connected){ 15523deb3ec6SMatthias Ringwald bnep_emit_open_channel_complete(channel, 0); 15533deb3ec6SMatthias Ringwald } 15543deb3ec6SMatthias Ringwald return; 15553deb3ec6SMatthias Ringwald } 15563deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET) { 15573deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET); 15583deb3ec6SMatthias Ringwald if ((channel->net_filter_out_count > 0) && (channel->net_filter_out != NULL)) { 15593deb3ec6SMatthias Ringwald bnep_send_filter_net_type_set(channel, channel->net_filter_out, channel->net_filter_out_count); 15603deb3ec6SMatthias Ringwald channel->net_filter_out_count = 0; 15613deb3ec6SMatthias Ringwald channel->net_filter_out = NULL; 15623deb3ec6SMatthias Ringwald } 15633deb3ec6SMatthias Ringwald return; 15643deb3ec6SMatthias Ringwald } 15653deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE) { 15663deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE); 15673deb3ec6SMatthias Ringwald bnep_send_filter_net_type_response(channel, channel->response_code); 15683deb3ec6SMatthias Ringwald return; 15693deb3ec6SMatthias Ringwald } 15703deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET) { 15713deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET); 15723deb3ec6SMatthias Ringwald if ((channel->multicast_filter_out_count > 0) && (channel->multicast_filter_out != NULL)) { 15733deb3ec6SMatthias Ringwald bnep_send_filter_multi_addr_set(channel, channel->multicast_filter_out, channel->multicast_filter_out_count); 15743deb3ec6SMatthias Ringwald channel->multicast_filter_out_count = 0; 15753deb3ec6SMatthias Ringwald channel->multicast_filter_out = NULL; 15763deb3ec6SMatthias Ringwald } 15773deb3ec6SMatthias Ringwald return; 15783deb3ec6SMatthias Ringwald } 15793deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE) { 15803deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE); 15813deb3ec6SMatthias Ringwald bnep_send_filter_multi_addr_response(channel, channel->response_code); 15823deb3ec6SMatthias Ringwald return; 15833deb3ec6SMatthias Ringwald } 15843deb3ec6SMatthias Ringwald 15853deb3ec6SMatthias Ringwald /* If the event was not yet handled, notify the application layer */ 15861ed1a3bdSMatthias Ringwald if (channel->waiting_for_can_send_now){ 15871ed1a3bdSMatthias Ringwald channel->waiting_for_can_send_now = 0; 15883deb3ec6SMatthias Ringwald bnep_emit_ready_to_send(channel); 15893deb3ec6SMatthias Ringwald } 15903deb3ec6SMatthias Ringwald } 15911ed1a3bdSMatthias Ringwald } 15923deb3ec6SMatthias Ringwald 15934e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t l2cap_cid){ 1594665d90f2SMatthias Ringwald btstack_linked_item_t *it; 1595665d90f2SMatthias Ringwald btstack_linked_item_t *next; 15963deb3ec6SMatthias Ringwald 1597665d90f2SMatthias Ringwald for (it = (btstack_linked_item_t *) bnep_channels; it ; it = next){ 15983deb3ec6SMatthias Ringwald next = it->next; // be prepared for removal of channel in state machine 15993deb3ec6SMatthias Ringwald bnep_channel_t * channel = ((bnep_channel_t *) it); 16004e366553SMatthias Ringwald if (channel->l2cap_cid != l2cap_cid) continue; 16014e366553SMatthias Ringwald // 16023deb3ec6SMatthias Ringwald bnep_channel_event_t channel_event = { BNEP_CH_EVT_READY_TO_SEND }; 16033deb3ec6SMatthias Ringwald bnep_channel_state_machine(channel, &channel_event); 16044e366553SMatthias Ringwald 16054e366553SMatthias Ringwald if (!l2cap_can_send_packet_now(channel->l2cap_cid)) { 16064e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid); 16074e366553SMatthias Ringwald return; 16083deb3ec6SMatthias Ringwald } 16093deb3ec6SMatthias Ringwald } 16104e366553SMatthias Ringwald } 16114e366553SMatthias Ringwald 16123deb3ec6SMatthias Ringwald 16133deb3ec6SMatthias Ringwald /* BNEP BTStack API */ 16143deb3ec6SMatthias Ringwald void bnep_init(void) 16153deb3ec6SMatthias Ringwald { 161678315a58SMatthias Ringwald bnep_security_level = gap_get_security_level(); 16173deb3ec6SMatthias Ringwald } 16183deb3ec6SMatthias Ringwald 161951e0db05SMatthias Ringwald void bnep_deinit(void){ 1620ed47fef4SMatthias Ringwald bnep_services = NULL; 1621ed47fef4SMatthias Ringwald bnep_channels = NULL; 1622ed47fef4SMatthias Ringwald bnep_security_level = 0; 162351e0db05SMatthias Ringwald } 162451e0db05SMatthias Ringwald 16253deb3ec6SMatthias Ringwald void bnep_set_required_security_level(gap_security_level_t security_level) 16263deb3ec6SMatthias Ringwald { 16273deb3ec6SMatthias Ringwald bnep_security_level = security_level; 16283deb3ec6SMatthias Ringwald } 16293deb3ec6SMatthias Ringwald 16300c249750SMatthias Ringwald int bnep_connect(btstack_packet_handler_t packet_handler, bd_addr_t addr, uint16_t l2cap_psm, uint16_t uuid_src, uint16_t uuid_dest) 16313deb3ec6SMatthias Ringwald { 16323deb3ec6SMatthias Ringwald bnep_channel_t *channel; 16333deb3ec6SMatthias Ringwald log_info("BNEP_CONNECT addr %s", bd_addr_to_str(addr)); 16343deb3ec6SMatthias Ringwald 16353deb3ec6SMatthias Ringwald channel = bnep_channel_create_for_addr(addr); 16363deb3ec6SMatthias Ringwald if (channel == NULL) { 16373deb3ec6SMatthias Ringwald return -1; 16383deb3ec6SMatthias Ringwald } 16393deb3ec6SMatthias Ringwald 16403deb3ec6SMatthias Ringwald channel->uuid_source = uuid_src; 16413deb3ec6SMatthias Ringwald channel->uuid_dest = uuid_dest; 16420c249750SMatthias Ringwald channel->packet_handler = packet_handler; 16433deb3ec6SMatthias Ringwald 164490a28bdeSMatthias Ringwald uint8_t status = l2cap_create_channel(bnep_packet_handler, addr, l2cap_psm, l2cap_max_mtu(), NULL); 164590a28bdeSMatthias Ringwald if (status){ 164690a28bdeSMatthias Ringwald return -1; 164790a28bdeSMatthias Ringwald } 16483deb3ec6SMatthias Ringwald return 0; 16493deb3ec6SMatthias Ringwald } 16503deb3ec6SMatthias Ringwald 16513deb3ec6SMatthias Ringwald void bnep_disconnect(bd_addr_t addr) 16523deb3ec6SMatthias Ringwald { 16533deb3ec6SMatthias Ringwald bnep_channel_t *channel; 16543deb3ec6SMatthias Ringwald log_info("BNEP_DISCONNECT"); 16553deb3ec6SMatthias Ringwald 16563deb3ec6SMatthias Ringwald channel = bnep_channel_for_addr(addr); 16573deb3ec6SMatthias Ringwald 16583deb3ec6SMatthias Ringwald bnep_channel_finalize(channel); 16593deb3ec6SMatthias Ringwald } 16603deb3ec6SMatthias Ringwald 16613deb3ec6SMatthias Ringwald 16620c249750SMatthias Ringwald uint8_t bnep_register_service(btstack_packet_handler_t packet_handler, uint16_t service_uuid, uint16_t max_frame_size) 16633deb3ec6SMatthias Ringwald { 16643deb3ec6SMatthias Ringwald log_info("BNEP_REGISTER_SERVICE mtu %d", max_frame_size); 16653deb3ec6SMatthias Ringwald 16663deb3ec6SMatthias Ringwald /* Check if we already registered a service */ 16673deb3ec6SMatthias Ringwald bnep_service_t * service = bnep_service_for_uuid(service_uuid); 16683deb3ec6SMatthias Ringwald if (service) { 16690cc6429eSMatthias Ringwald return BNEP_SERVICE_ALREADY_REGISTERED; 16703deb3ec6SMatthias Ringwald } 16713deb3ec6SMatthias Ringwald 16723deb3ec6SMatthias Ringwald /* Only alow one the three service types: PANU, NAP, GN */ 1673235946f1SMatthias Ringwald if ((service_uuid != BLUETOOTH_SERVICE_CLASS_PANU) && 1674235946f1SMatthias Ringwald (service_uuid != BLUETOOTH_SERVICE_CLASS_NAP) && 1675235946f1SMatthias Ringwald (service_uuid != BLUETOOTH_SERVICE_CLASS_GN)) { 16763deb3ec6SMatthias Ringwald log_info("BNEP_REGISTER_SERVICE: Invalid service UUID: %04x", service_uuid); 16770cc6429eSMatthias Ringwald return BNEP_SERVICE_ALREADY_REGISTERED; // TODO: define own error 16783deb3ec6SMatthias Ringwald } 16793deb3ec6SMatthias Ringwald 16803deb3ec6SMatthias Ringwald /* Allocate service memory */ 16813deb3ec6SMatthias Ringwald service = (bnep_service_t*) btstack_memory_bnep_service_get(); 16823deb3ec6SMatthias Ringwald if (!service) { 16830cc6429eSMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED; 16843deb3ec6SMatthias Ringwald } 16853deb3ec6SMatthias Ringwald 16863deb3ec6SMatthias Ringwald /* register with l2cap if not registered before, max MTU */ 168784e3541eSMilanka Ringwald l2cap_register_service(bnep_packet_handler, BLUETOOTH_PSM_BNEP, 0xffff, bnep_security_level); 16883deb3ec6SMatthias Ringwald 16893deb3ec6SMatthias Ringwald /* Setup the service struct */ 16903deb3ec6SMatthias Ringwald service->max_frame_size = max_frame_size; 16913deb3ec6SMatthias Ringwald service->service_uuid = service_uuid; 16920c249750SMatthias Ringwald service->packet_handler = packet_handler; 16930c249750SMatthias Ringwald 16943deb3ec6SMatthias Ringwald 16953deb3ec6SMatthias Ringwald /* Add to services list */ 1696665d90f2SMatthias Ringwald btstack_linked_list_add(&bnep_services, (btstack_linked_item_t *) service); 16973deb3ec6SMatthias Ringwald 16980cc6429eSMatthias Ringwald return 0; 16993deb3ec6SMatthias Ringwald } 17003deb3ec6SMatthias Ringwald 17013deb3ec6SMatthias Ringwald void bnep_unregister_service(uint16_t service_uuid) 17023deb3ec6SMatthias Ringwald { 17033deb3ec6SMatthias Ringwald log_info("BNEP_UNREGISTER_SERVICE #%04x", service_uuid); 17043deb3ec6SMatthias Ringwald 17053deb3ec6SMatthias Ringwald bnep_service_t *service = bnep_service_for_uuid(service_uuid); 17063deb3ec6SMatthias Ringwald if (!service) { 17073deb3ec6SMatthias Ringwald return; 17083deb3ec6SMatthias Ringwald } 17093deb3ec6SMatthias Ringwald 1710665d90f2SMatthias Ringwald btstack_linked_list_remove(&bnep_services, (btstack_linked_item_t *) service); 17113deb3ec6SMatthias Ringwald btstack_memory_bnep_service_free(service); 17123deb3ec6SMatthias Ringwald service = NULL; 17133deb3ec6SMatthias Ringwald 171484e3541eSMilanka Ringwald l2cap_unregister_service(BLUETOOTH_PSM_BNEP); 17153deb3ec6SMatthias Ringwald } 17163deb3ec6SMatthias Ringwald 1717