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 filter response codes */
889951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_SUCCESS 0x0000
899951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_UNSUPPORTED_REQUEST 0x0001
909951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_INVALID_RANGE 0x0002
919951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS 0x0003
929951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_SECURITY 0x0004
939951ad9cSMatthias Ringwald
943deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_TIMEOUT_MS 10000
953deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_MAX_RETRIES 1
963deb3ec6SMatthias Ringwald
978f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_services = NULL;
988f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_channels = NULL;
993deb3ec6SMatthias Ringwald
1003deb3ec6SMatthias Ringwald static gap_security_level_t bnep_security_level;
1013deb3ec6SMatthias Ringwald
1023deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid);
1033deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel);
1043deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout);
1053deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event);
1064e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t cid);
10737e1b220SMatthias Ringwald
bnep_emit_open_channel_complete(bnep_channel_t * channel,uint8_t status,uint8_t setup_connection_response)10837e1b220SMatthias Ringwald static void bnep_emit_open_channel_complete(bnep_channel_t *channel, uint8_t status, uint8_t setup_connection_response)
1093deb3ec6SMatthias Ringwald {
1100c249750SMatthias 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);
1110c249750SMatthias Ringwald if (!channel->packet_handler) return;
1120c249750SMatthias Ringwald
11337e1b220SMatthias Ringwald uint8_t event[3 + sizeof(bd_addr_t) + 4 * sizeof(uint16_t) + 3];
114423c667cSMatthias Ringwald event[0] = BNEP_EVENT_CHANNEL_OPENED;
1153deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2;
1163deb3ec6SMatthias Ringwald event[2] = status;
117423c667cSMatthias Ringwald little_endian_store_16(event, 3, channel->l2cap_cid);
118423c667cSMatthias Ringwald little_endian_store_16(event, 5, channel->uuid_source);
119423c667cSMatthias Ringwald little_endian_store_16(event, 7, channel->uuid_dest);
120423c667cSMatthias Ringwald little_endian_store_16(event, 9, channel->max_frame_size);
121fb389631SMatthias Ringwald reverse_bd_addr(channel->remote_addr, &event[11]);
12232b46fecSMatthias Ringwald little_endian_store_16(event, 17, channel->con_handle);
12337e1b220SMatthias Ringwald event[19] = setup_connection_response;
1249da9850bSMatthias Ringwald hci_dump_btstack_event( event, sizeof(event));
1250c249750SMatthias Ringwald (*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1263deb3ec6SMatthias Ringwald }
1273deb3ec6SMatthias Ringwald
bnep_emit_channel_timeout(bnep_channel_t * channel)1283deb3ec6SMatthias Ringwald static void bnep_emit_channel_timeout(bnep_channel_t *channel)
1293deb3ec6SMatthias Ringwald {
1300c249750SMatthias Ringwald log_info("BNEP_EVENT_CHANNEL_TIMEOUT bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler);
1310c249750SMatthias Ringwald if (!channel->packet_handler) return;
1320c249750SMatthias Ringwald
133423c667cSMatthias Ringwald uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t) + sizeof(uint8_t)];
1343deb3ec6SMatthias Ringwald event[0] = BNEP_EVENT_CHANNEL_TIMEOUT;
1353deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2;
136423c667cSMatthias Ringwald little_endian_store_16(event, 2, channel->l2cap_cid);
137423c667cSMatthias Ringwald little_endian_store_16(event, 4, channel->uuid_source);
138423c667cSMatthias Ringwald little_endian_store_16(event, 6, channel->uuid_dest);
139fb389631SMatthias Ringwald reverse_bd_addr(channel->remote_addr, &event[8]);
140423c667cSMatthias Ringwald event[14] = channel->state;
1419da9850bSMatthias Ringwald hci_dump_btstack_event( event, sizeof(event));
1420c249750SMatthias Ringwald (*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1433deb3ec6SMatthias Ringwald }
1443deb3ec6SMatthias Ringwald
bnep_emit_channel_closed(bnep_channel_t * channel)1453deb3ec6SMatthias Ringwald static void bnep_emit_channel_closed(bnep_channel_t *channel)
1463deb3ec6SMatthias Ringwald {
1470c249750SMatthias Ringwald log_info("BNEP_EVENT_CHANNEL_CLOSED bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler);
1480c249750SMatthias Ringwald if (!channel->packet_handler) return;
1490c249750SMatthias Ringwald
150423c667cSMatthias Ringwald uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t)];
1513deb3ec6SMatthias Ringwald event[0] = BNEP_EVENT_CHANNEL_CLOSED;
1523deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2;
153423c667cSMatthias Ringwald little_endian_store_16(event, 2, channel->l2cap_cid);
154423c667cSMatthias Ringwald little_endian_store_16(event, 4, channel->uuid_source);
155423c667cSMatthias Ringwald little_endian_store_16(event, 6, channel->uuid_dest);
156fb389631SMatthias Ringwald reverse_bd_addr(channel->remote_addr, &event[8]);
1579da9850bSMatthias Ringwald hci_dump_btstack_event( event, sizeof(event));
1580c249750SMatthias Ringwald (*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1593deb3ec6SMatthias Ringwald }
1603deb3ec6SMatthias Ringwald
bnep_emit_ready_to_send(bnep_channel_t * channel)1613deb3ec6SMatthias Ringwald static void bnep_emit_ready_to_send(bnep_channel_t *channel)
1623deb3ec6SMatthias Ringwald {
1630c249750SMatthias Ringwald if (!channel->packet_handler) return;
1640c249750SMatthias Ringwald
165423c667cSMatthias Ringwald uint8_t event[4];
1662d4c8c04SMatthias Ringwald event[0] = BNEP_EVENT_CAN_SEND_NOW;
1673deb3ec6SMatthias Ringwald event[1] = sizeof(event) - 2;
168423c667cSMatthias Ringwald little_endian_store_16(event, 2, channel->l2cap_cid);
1699da9850bSMatthias Ringwald hci_dump_btstack_event( event, sizeof(event));
1700c249750SMatthias Ringwald (*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1713deb3ec6SMatthias Ringwald }
1723deb3ec6SMatthias Ringwald
1733deb3ec6SMatthias Ringwald /* Send BNEP connection request */
bnep_send_command_not_understood(bnep_channel_t * channel,uint8_t control_type)1743deb3ec6SMatthias Ringwald static int bnep_send_command_not_understood(bnep_channel_t *channel, uint8_t control_type)
1753deb3ec6SMatthias Ringwald {
1763deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL;
1773deb3ec6SMatthias Ringwald uint16_t pos = 0;
1783deb3ec6SMatthias Ringwald int err = 0;
1793deb3ec6SMatthias Ringwald
1803deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
1813deb3ec6SMatthias Ringwald return -1; // TODO
1823deb3ec6SMatthias Ringwald }
1833deb3ec6SMatthias Ringwald
1843deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer();
1853deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer();
1863deb3ec6SMatthias Ringwald
1873deb3ec6SMatthias Ringwald /* Setup control packet type */
1883deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
1893deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD;
1903deb3ec6SMatthias Ringwald
1913deb3ec6SMatthias Ringwald /* Add not understood control type */
1923deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = control_type;
1933deb3ec6SMatthias Ringwald
1943deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos);
1953deb3ec6SMatthias Ringwald
1963deb3ec6SMatthias Ringwald if (err) {
1973deb3ec6SMatthias Ringwald // TODO: Log error
1983deb3ec6SMatthias Ringwald }
1993deb3ec6SMatthias Ringwald return err;
2003deb3ec6SMatthias Ringwald }
2013deb3ec6SMatthias Ringwald
2023deb3ec6SMatthias Ringwald
2033deb3ec6SMatthias Ringwald /* Send BNEP connection request */
bnep_send_connection_request(bnep_channel_t * channel,uint16_t uuid_source,uint16_t uuid_dest)2043deb3ec6SMatthias Ringwald static int bnep_send_connection_request(bnep_channel_t *channel, uint16_t uuid_source, uint16_t uuid_dest)
2053deb3ec6SMatthias Ringwald {
2063deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL;
2073deb3ec6SMatthias Ringwald uint16_t pos = 0;
2083deb3ec6SMatthias Ringwald int err = 0;
2093deb3ec6SMatthias Ringwald
2103deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2113deb3ec6SMatthias Ringwald return -1; // TODO
2123deb3ec6SMatthias Ringwald }
2133deb3ec6SMatthias Ringwald
2143deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer();
2153deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer();
2163deb3ec6SMatthias Ringwald
2173deb3ec6SMatthias Ringwald /* Setup control packet type */
2183deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2193deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST;
2203deb3ec6SMatthias Ringwald
2213deb3ec6SMatthias Ringwald /* Add UUID Size */
2223deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = 2;
2233deb3ec6SMatthias Ringwald
2243deb3ec6SMatthias Ringwald /* Add dest and source UUID */
225f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, uuid_dest);
2263deb3ec6SMatthias Ringwald pos += 2;
2273deb3ec6SMatthias Ringwald
228f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, uuid_source);
2293deb3ec6SMatthias Ringwald pos += 2;
2303deb3ec6SMatthias Ringwald
2313deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos);
2323deb3ec6SMatthias Ringwald
2333deb3ec6SMatthias Ringwald if (err) {
2343deb3ec6SMatthias Ringwald // TODO: Log error
2353deb3ec6SMatthias Ringwald }
2363deb3ec6SMatthias Ringwald return err;
2373deb3ec6SMatthias Ringwald }
2383deb3ec6SMatthias Ringwald
2393deb3ec6SMatthias Ringwald /* Send BNEP connection response */
bnep_send_connection_response(bnep_channel_t * channel,uint16_t response_code)2403deb3ec6SMatthias Ringwald static int bnep_send_connection_response(bnep_channel_t *channel, uint16_t response_code)
2413deb3ec6SMatthias Ringwald {
2423deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL;
2433deb3ec6SMatthias Ringwald uint16_t pos = 0;
2443deb3ec6SMatthias Ringwald int err = 0;
2453deb3ec6SMatthias Ringwald
2463deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2473deb3ec6SMatthias Ringwald return -1; // TODO
2483deb3ec6SMatthias Ringwald }
2493deb3ec6SMatthias Ringwald
2503deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer();
2513deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer();
2523deb3ec6SMatthias Ringwald
2533deb3ec6SMatthias Ringwald /* Setup control packet type */
2543deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2553deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE;
2563deb3ec6SMatthias Ringwald
2573deb3ec6SMatthias Ringwald /* Add response code */
258f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, response_code);
2593deb3ec6SMatthias Ringwald pos += 2;
2603deb3ec6SMatthias Ringwald
2613deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos);
2623deb3ec6SMatthias Ringwald
2633deb3ec6SMatthias Ringwald if (err) {
2643deb3ec6SMatthias Ringwald // TODO: Log error
2653deb3ec6SMatthias Ringwald }
2663deb3ec6SMatthias Ringwald return err;
2673deb3ec6SMatthias Ringwald }
2683deb3ec6SMatthias Ringwald
2693deb3ec6SMatthias Ringwald /* Send BNEP filter net type set message */
bnep_send_filter_net_type_set(bnep_channel_t * channel,bnep_net_filter_t * filter,uint16_t len)2703deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_set(bnep_channel_t *channel, bnep_net_filter_t *filter, uint16_t len)
2713deb3ec6SMatthias Ringwald {
2723deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL;
2733deb3ec6SMatthias Ringwald uint16_t pos = 0;
2743deb3ec6SMatthias Ringwald int err = 0;
2753deb3ec6SMatthias Ringwald int i;
2763deb3ec6SMatthias Ringwald
2773deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2783deb3ec6SMatthias Ringwald return -1;
2793deb3ec6SMatthias Ringwald }
2803deb3ec6SMatthias Ringwald
2813deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer();
2823deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer();
2833deb3ec6SMatthias Ringwald
2843deb3ec6SMatthias Ringwald /* Setup control packet type */
2853deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2863deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET;
2873deb3ec6SMatthias Ringwald
288f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, len * 2 * 2);
2893deb3ec6SMatthias Ringwald pos += 2;
2903deb3ec6SMatthias Ringwald
2913deb3ec6SMatthias Ringwald for (i = 0; i < len; i ++) {
292f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, filter[i].range_start);
2933deb3ec6SMatthias Ringwald pos += 2;
294f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, filter[i].range_end);
2953deb3ec6SMatthias Ringwald pos += 2;
2963deb3ec6SMatthias Ringwald }
2973deb3ec6SMatthias Ringwald
2983deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos);
2993deb3ec6SMatthias Ringwald
3003deb3ec6SMatthias Ringwald if (err) {
3013deb3ec6SMatthias Ringwald // TODO: Log error
3023deb3ec6SMatthias Ringwald }
3033deb3ec6SMatthias Ringwald return err;
3043deb3ec6SMatthias Ringwald }
3053deb3ec6SMatthias Ringwald
3063deb3ec6SMatthias Ringwald /* Send BNEP filter net type response message */
bnep_send_filter_net_type_response(bnep_channel_t * channel,uint16_t response_code)3073deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_response(bnep_channel_t *channel, uint16_t response_code)
3083deb3ec6SMatthias Ringwald {
3093deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL;
3103deb3ec6SMatthias Ringwald uint16_t pos = 0;
3113deb3ec6SMatthias Ringwald int err = 0;
3123deb3ec6SMatthias Ringwald
3133deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3143deb3ec6SMatthias Ringwald return -1;
3153deb3ec6SMatthias Ringwald }
3163deb3ec6SMatthias Ringwald
3173deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer();
3183deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer();
3193deb3ec6SMatthias Ringwald
3203deb3ec6SMatthias Ringwald /* Setup control packet type */
3213deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3223deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE;
3233deb3ec6SMatthias Ringwald
3243deb3ec6SMatthias Ringwald /* Add response code */
325f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, response_code);
3263deb3ec6SMatthias Ringwald pos += 2;
3273deb3ec6SMatthias Ringwald
3283deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos);
3293deb3ec6SMatthias Ringwald
3303deb3ec6SMatthias Ringwald if (err) {
3313deb3ec6SMatthias Ringwald // TODO: Log error
3323deb3ec6SMatthias Ringwald }
3333deb3ec6SMatthias Ringwald return err;
3343deb3ec6SMatthias Ringwald }
3353deb3ec6SMatthias Ringwald
3363deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address set message */
3373deb3ec6SMatthias Ringwald
bnep_send_filter_multi_addr_set(bnep_channel_t * channel,bnep_multi_filter_t * filter,uint16_t len)3383deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_set(bnep_channel_t *channel, bnep_multi_filter_t *filter, uint16_t len)
3393deb3ec6SMatthias Ringwald {
3403deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL;
3413deb3ec6SMatthias Ringwald uint16_t pos = 0;
3423deb3ec6SMatthias Ringwald int err = 0;
3433deb3ec6SMatthias Ringwald int i;
3443deb3ec6SMatthias Ringwald
3453deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3463deb3ec6SMatthias Ringwald return -1;
3473deb3ec6SMatthias Ringwald }
3483deb3ec6SMatthias Ringwald
3493deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer();
3503deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer();
3513deb3ec6SMatthias Ringwald
3523deb3ec6SMatthias Ringwald /* Setup control packet type */
3533deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3543deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET;
3553deb3ec6SMatthias Ringwald
356f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, len * 2 * ETHER_ADDR_LEN);
3573deb3ec6SMatthias Ringwald pos += 2;
3583deb3ec6SMatthias Ringwald
3593deb3ec6SMatthias Ringwald for (i = 0; i < len; i ++) {
360058e3d6bSMatthias Ringwald bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_start);
3613deb3ec6SMatthias Ringwald pos += ETHER_ADDR_LEN;
362058e3d6bSMatthias Ringwald bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_end);
3633deb3ec6SMatthias Ringwald pos += ETHER_ADDR_LEN;
3643deb3ec6SMatthias Ringwald }
3653deb3ec6SMatthias Ringwald
3663deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos);
3673deb3ec6SMatthias Ringwald
3683deb3ec6SMatthias Ringwald if (err) {
3693deb3ec6SMatthias Ringwald // TODO: Log error
3703deb3ec6SMatthias Ringwald }
3713deb3ec6SMatthias Ringwald return err;
3723deb3ec6SMatthias Ringwald }
3733deb3ec6SMatthias Ringwald
3743deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address response message */
bnep_send_filter_multi_addr_response(bnep_channel_t * channel,uint16_t response_code)3753deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_response(bnep_channel_t *channel, uint16_t response_code)
3763deb3ec6SMatthias Ringwald {
3773deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL;
3783deb3ec6SMatthias Ringwald uint16_t pos = 0;
3793deb3ec6SMatthias Ringwald int err = 0;
3803deb3ec6SMatthias Ringwald
3813deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3823deb3ec6SMatthias Ringwald return -1;
3833deb3ec6SMatthias Ringwald }
3843deb3ec6SMatthias Ringwald
3853deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer();
3863deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer();
3873deb3ec6SMatthias Ringwald
3883deb3ec6SMatthias Ringwald /* Setup control packet type */
3893deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3903deb3ec6SMatthias Ringwald bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE;
3913deb3ec6SMatthias Ringwald
3923deb3ec6SMatthias Ringwald /* Add response code */
393f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos, response_code);
3943deb3ec6SMatthias Ringwald pos += 2;
3953deb3ec6SMatthias Ringwald
3963deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos);
3973deb3ec6SMatthias Ringwald
3983deb3ec6SMatthias Ringwald if (err) {
3993deb3ec6SMatthias Ringwald // TODO: Log error
4003deb3ec6SMatthias Ringwald }
4013deb3ec6SMatthias Ringwald return err;
4023deb3ec6SMatthias Ringwald }
4033deb3ec6SMatthias Ringwald
bnep_can_send_packet_now(uint16_t bnep_cid)4043deb3ec6SMatthias Ringwald int bnep_can_send_packet_now(uint16_t bnep_cid)
4053deb3ec6SMatthias Ringwald {
4063deb3ec6SMatthias Ringwald bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
4073deb3ec6SMatthias Ringwald
4083deb3ec6SMatthias Ringwald if (!channel){
4093deb3ec6SMatthias Ringwald log_error("bnep_can_send_packet_now cid 0x%02x doesn't exist!", bnep_cid);
4103deb3ec6SMatthias Ringwald return 0;
4113deb3ec6SMatthias Ringwald }
4123deb3ec6SMatthias Ringwald
4130b9d7e78SMatthias Ringwald return l2cap_can_send_packet_now(channel->l2cap_cid);
4141ed1a3bdSMatthias Ringwald }
4151ed1a3bdSMatthias Ringwald
bnep_request_can_send_now_event(uint16_t bnep_cid)4161ed1a3bdSMatthias Ringwald void bnep_request_can_send_now_event(uint16_t bnep_cid)
4171ed1a3bdSMatthias Ringwald {
4181ed1a3bdSMatthias Ringwald bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
4191ed1a3bdSMatthias Ringwald
4201ed1a3bdSMatthias Ringwald if (!channel){
4211ed1a3bdSMatthias Ringwald log_error("bnep_request_can_send_now_event cid 0x%02x doesn't exist!", bnep_cid);
4221ed1a3bdSMatthias Ringwald return;
4231ed1a3bdSMatthias Ringwald }
4241ed1a3bdSMatthias Ringwald
4251ed1a3bdSMatthias Ringwald channel->waiting_for_can_send_now = 1;
4261ed1a3bdSMatthias Ringwald l2cap_request_can_send_now_event(bnep_cid);
4273deb3ec6SMatthias Ringwald }
4283deb3ec6SMatthias Ringwald
4293deb3ec6SMatthias Ringwald
bnep_filter_protocol(bnep_channel_t * channel,uint16_t network_protocol_type)4303deb3ec6SMatthias Ringwald static int bnep_filter_protocol(bnep_channel_t *channel, uint16_t network_protocol_type)
4313deb3ec6SMatthias Ringwald {
4323deb3ec6SMatthias Ringwald int i;
4333deb3ec6SMatthias Ringwald
4343deb3ec6SMatthias Ringwald if (channel->net_filter_count == 0) {
4353deb3ec6SMatthias Ringwald /* No filter set */
4363deb3ec6SMatthias Ringwald return 1;
4373deb3ec6SMatthias Ringwald }
4383deb3ec6SMatthias Ringwald
4393deb3ec6SMatthias Ringwald for (i = 0; i < channel->net_filter_count; i ++) {
4403deb3ec6SMatthias Ringwald if ((network_protocol_type >= channel->net_filter[i].range_start) &&
4413deb3ec6SMatthias Ringwald (network_protocol_type <= channel->net_filter[i].range_end)) {
4423deb3ec6SMatthias Ringwald return 1;
4433deb3ec6SMatthias Ringwald }
4443deb3ec6SMatthias Ringwald }
4453deb3ec6SMatthias Ringwald
4463deb3ec6SMatthias Ringwald return 0;
4473deb3ec6SMatthias Ringwald }
4483deb3ec6SMatthias Ringwald
bnep_filter_multicast(bnep_channel_t * channel,bd_addr_t addr_dest)4493deb3ec6SMatthias Ringwald static int bnep_filter_multicast(bnep_channel_t *channel, bd_addr_t addr_dest)
4503deb3ec6SMatthias Ringwald {
4513deb3ec6SMatthias Ringwald int i;
4523deb3ec6SMatthias Ringwald
4533deb3ec6SMatthias Ringwald /* Check if the multicast flag is set int the destination address */
4543deb3ec6SMatthias Ringwald if ((addr_dest[0] & 0x01) == 0x00) {
4553deb3ec6SMatthias Ringwald /* Not a multicast frame, do not apply filtering and send it in any case */
4563deb3ec6SMatthias Ringwald return 1;
4573deb3ec6SMatthias Ringwald }
4583deb3ec6SMatthias Ringwald
4593deb3ec6SMatthias Ringwald if (channel->multicast_filter_count == 0) {
4603deb3ec6SMatthias Ringwald /* No filter set */
4613deb3ec6SMatthias Ringwald return 1;
4623deb3ec6SMatthias Ringwald }
4633deb3ec6SMatthias Ringwald
4643deb3ec6SMatthias Ringwald for (i = 0; i < channel->multicast_filter_count; i ++) {
4653deb3ec6SMatthias Ringwald if ((memcmp(addr_dest, channel->multicast_filter[i].addr_start, sizeof(bd_addr_t)) >= 0) &&
4663deb3ec6SMatthias Ringwald (memcmp(addr_dest, channel->multicast_filter[i].addr_end, sizeof(bd_addr_t)) <= 0)) {
4673deb3ec6SMatthias Ringwald return 1;
4683deb3ec6SMatthias Ringwald }
4693deb3ec6SMatthias Ringwald }
4703deb3ec6SMatthias Ringwald
4713deb3ec6SMatthias Ringwald return 0;
4723deb3ec6SMatthias Ringwald }
4733deb3ec6SMatthias Ringwald
4743deb3ec6SMatthias Ringwald
4753deb3ec6SMatthias Ringwald /* Send BNEP ethernet packet */
bnep_send(uint16_t bnep_cid,uint8_t * packet,uint16_t len)4763deb3ec6SMatthias Ringwald int bnep_send(uint16_t bnep_cid, uint8_t *packet, uint16_t len)
4773deb3ec6SMatthias Ringwald {
4783deb3ec6SMatthias Ringwald bnep_channel_t *channel;
4793deb3ec6SMatthias Ringwald uint8_t *bnep_out_buffer = NULL;
4803deb3ec6SMatthias Ringwald uint16_t pos = 0;
4813deb3ec6SMatthias Ringwald uint16_t pos_out = 0;
4823deb3ec6SMatthias Ringwald uint16_t payload_len;
4833deb3ec6SMatthias Ringwald int err = 0;
4843deb3ec6SMatthias Ringwald int has_source;
4853deb3ec6SMatthias Ringwald int has_dest;
4863deb3ec6SMatthias Ringwald
4873deb3ec6SMatthias Ringwald bd_addr_t addr_dest;
4883deb3ec6SMatthias Ringwald bd_addr_t addr_source;
4893deb3ec6SMatthias Ringwald uint16_t network_protocol_type;
4903deb3ec6SMatthias Ringwald
4913deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(bnep_cid);
4923deb3ec6SMatthias Ringwald if (channel == NULL) {
4933deb3ec6SMatthias Ringwald log_error("bnep_send cid 0x%02x doesn't exist!", bnep_cid);
4943deb3ec6SMatthias Ringwald return 1;
4953deb3ec6SMatthias Ringwald }
4963deb3ec6SMatthias Ringwald
4973deb3ec6SMatthias Ringwald if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
4983deb3ec6SMatthias Ringwald return BNEP_CHANNEL_NOT_CONNECTED;
4993deb3ec6SMatthias Ringwald }
5003deb3ec6SMatthias Ringwald
5013deb3ec6SMatthias Ringwald /* Check for free ACL buffers */
5023deb3ec6SMatthias Ringwald if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
5033deb3ec6SMatthias Ringwald return BTSTACK_ACL_BUFFERS_FULL;
5043deb3ec6SMatthias Ringwald }
5053deb3ec6SMatthias Ringwald
5063deb3ec6SMatthias Ringwald /* Extract destination and source address from the ethernet packet */
5073deb3ec6SMatthias Ringwald pos = 0;
508058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, &packet[pos]);
5093deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t);
510058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, &packet[pos]);
5113deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t);
512f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos);
5133deb3ec6SMatthias Ringwald pos += sizeof(uint16_t);
5143deb3ec6SMatthias Ringwald
5153deb3ec6SMatthias Ringwald payload_len = len - pos;
5163deb3ec6SMatthias Ringwald
5173deb3ec6SMatthias Ringwald if (network_protocol_type == ETHERTYPE_VLAN) { /* IEEE 802.1Q tag header */
5183deb3ec6SMatthias Ringwald if (payload_len < 4) {
5193deb3ec6SMatthias Ringwald /* Omit this packet */
5203deb3ec6SMatthias Ringwald return 0;
5213deb3ec6SMatthias Ringwald }
5223deb3ec6SMatthias Ringwald /* The "real" network protocol type is 4 bytes ahead in a VLAN packet */
523f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos + 2);
5243deb3ec6SMatthias Ringwald }
5253deb3ec6SMatthias Ringwald
5263deb3ec6SMatthias Ringwald /* Check network protocol and multicast filters before sending */
5273deb3ec6SMatthias Ringwald if (!bnep_filter_protocol(channel, network_protocol_type) ||
5283deb3ec6SMatthias Ringwald !bnep_filter_multicast(channel, addr_dest)) {
5293deb3ec6SMatthias Ringwald /* Packet did not pass filter... */
5303deb3ec6SMatthias Ringwald if ((network_protocol_type == ETHERTYPE_VLAN) &&
5313deb3ec6SMatthias Ringwald (payload_len >= 4)) {
5323deb3ec6SMatthias Ringwald /* The packet has been tagged as a with IEE 802.1Q tag and has been filtered out.
5333deb3ec6SMatthias Ringwald According to the spec the IEE802.1Q tag header shall be sended without ethernet payload.
5343deb3ec6SMatthias Ringwald So limit the payload_len to 4.
5353deb3ec6SMatthias Ringwald */
5363deb3ec6SMatthias Ringwald payload_len = 4;
5373deb3ec6SMatthias Ringwald } else {
5383deb3ec6SMatthias Ringwald /* Packet is not tagged with IEE802.1Q header and was filtered out. Omit this packet */
5393deb3ec6SMatthias Ringwald return 0;
5403deb3ec6SMatthias Ringwald }
5413deb3ec6SMatthias Ringwald }
5423deb3ec6SMatthias Ringwald
5433deb3ec6SMatthias Ringwald /* Reserve l2cap packet buffer */
5443deb3ec6SMatthias Ringwald l2cap_reserve_packet_buffer();
5453deb3ec6SMatthias Ringwald bnep_out_buffer = l2cap_get_outgoing_buffer();
5463deb3ec6SMatthias Ringwald
5473deb3ec6SMatthias Ringwald /* Check if source address is the same as our local address and if the
5483deb3ec6SMatthias Ringwald destination address is the same as the remote addr. Maybe we can use
5493deb3ec6SMatthias Ringwald the compressed data format
5503deb3ec6SMatthias Ringwald */
5513deb3ec6SMatthias Ringwald has_source = (memcmp(addr_source, channel->local_addr, ETHER_ADDR_LEN) != 0);
5523deb3ec6SMatthias Ringwald has_dest = (memcmp(addr_dest, channel->remote_addr, ETHER_ADDR_LEN) != 0);
5533deb3ec6SMatthias Ringwald
5543deb3ec6SMatthias Ringwald /* Check for MTU limits */
5553deb3ec6SMatthias Ringwald if (payload_len > channel->max_frame_size) {
5563deb3ec6SMatthias Ringwald log_error("bnep_send: Max frame size (%d) exceeded: %d", channel->max_frame_size, payload_len);
5573deb3ec6SMatthias Ringwald return BNEP_DATA_LEN_EXCEEDS_MTU;
5583deb3ec6SMatthias Ringwald }
5593deb3ec6SMatthias Ringwald
5603deb3ec6SMatthias Ringwald /* Fill in the package type depending on the given source and destination address */
5613deb3ec6SMatthias Ringwald if (has_source && has_dest) {
5623deb3ec6SMatthias Ringwald bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_GENERAL_ETHERNET;
5633deb3ec6SMatthias Ringwald } else
5643deb3ec6SMatthias Ringwald if (has_source && !has_dest) {
5653deb3ec6SMatthias Ringwald bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY;
5663deb3ec6SMatthias Ringwald } else
5673deb3ec6SMatthias Ringwald if (!has_source && has_dest) {
5683deb3ec6SMatthias Ringwald bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY;
5693deb3ec6SMatthias Ringwald } else {
5703deb3ec6SMatthias Ringwald bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET;
5713deb3ec6SMatthias Ringwald }
5723deb3ec6SMatthias Ringwald
5733deb3ec6SMatthias Ringwald /* Add the destination address if needed */
5743deb3ec6SMatthias Ringwald if (has_dest) {
575058e3d6bSMatthias Ringwald bd_addr_copy(bnep_out_buffer + pos_out, addr_dest);
5763deb3ec6SMatthias Ringwald pos_out += sizeof(bd_addr_t);
5773deb3ec6SMatthias Ringwald }
5783deb3ec6SMatthias Ringwald
5793deb3ec6SMatthias Ringwald /* Add the source address if needed */
5803deb3ec6SMatthias Ringwald if (has_source) {
581058e3d6bSMatthias Ringwald bd_addr_copy(bnep_out_buffer + pos_out, addr_source);
5823deb3ec6SMatthias Ringwald pos_out += sizeof(bd_addr_t);
5833deb3ec6SMatthias Ringwald }
5843deb3ec6SMatthias Ringwald
5853deb3ec6SMatthias Ringwald /* Add protocol type */
586f8fbdce0SMatthias Ringwald big_endian_store_16(bnep_out_buffer, pos_out, network_protocol_type);
5873deb3ec6SMatthias Ringwald pos_out += 2;
5883deb3ec6SMatthias Ringwald
5893deb3ec6SMatthias Ringwald /* TODO: Add extension headers, if we may support them at a later stage */
5903deb3ec6SMatthias Ringwald /* Add the payload and then send out the package */
5916535961aSMatthias Ringwald (void)memcpy(bnep_out_buffer + pos_out, packet + pos, payload_len);
5923deb3ec6SMatthias Ringwald pos_out += payload_len;
5933deb3ec6SMatthias Ringwald
5943deb3ec6SMatthias Ringwald err = l2cap_send_prepared(channel->l2cap_cid, pos_out);
5953deb3ec6SMatthias Ringwald
5963deb3ec6SMatthias Ringwald if (err) {
5973deb3ec6SMatthias Ringwald log_error("bnep_send: error %d", err);
5983deb3ec6SMatthias Ringwald }
5993deb3ec6SMatthias Ringwald return err;
6003deb3ec6SMatthias Ringwald }
6013deb3ec6SMatthias Ringwald
6023deb3ec6SMatthias Ringwald
6033deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
bnep_set_net_type_filter(uint16_t bnep_cid,bnep_net_filter_t * filter,uint16_t len)6043deb3ec6SMatthias Ringwald int bnep_set_net_type_filter(uint16_t bnep_cid, bnep_net_filter_t *filter, uint16_t len)
6053deb3ec6SMatthias Ringwald {
6063deb3ec6SMatthias Ringwald bnep_channel_t *channel;
6073deb3ec6SMatthias Ringwald
6083deb3ec6SMatthias Ringwald if (filter == NULL) {
6093deb3ec6SMatthias Ringwald return -1;
6103deb3ec6SMatthias Ringwald }
6113deb3ec6SMatthias Ringwald
6123deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(bnep_cid);
6133deb3ec6SMatthias Ringwald if (channel == NULL) {
6143deb3ec6SMatthias Ringwald log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
6153deb3ec6SMatthias Ringwald return 1;
6163deb3ec6SMatthias Ringwald }
6173deb3ec6SMatthias Ringwald
6183deb3ec6SMatthias Ringwald if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
6193deb3ec6SMatthias Ringwald return BNEP_CHANNEL_NOT_CONNECTED;
6203deb3ec6SMatthias Ringwald }
6213deb3ec6SMatthias Ringwald
6223deb3ec6SMatthias Ringwald if (len > MAX_BNEP_NETFILTER_OUT) {
6233deb3ec6SMatthias Ringwald return BNEP_DATA_LEN_EXCEEDS_MTU;
6243deb3ec6SMatthias Ringwald }
6253deb3ec6SMatthias Ringwald
6263deb3ec6SMatthias Ringwald channel->net_filter_out = filter;
6273deb3ec6SMatthias Ringwald channel->net_filter_out_count = len;
6283deb3ec6SMatthias Ringwald
6294e366553SMatthias Ringwald /* Set flag to send out the network protocol type filter set request */
6303deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
6314e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
6323deb3ec6SMatthias Ringwald
6333deb3ec6SMatthias Ringwald return 0;
6343deb3ec6SMatthias Ringwald }
6353deb3ec6SMatthias Ringwald
6363deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
bnep_set_multicast_filter(uint16_t bnep_cid,bnep_multi_filter_t * filter,uint16_t len)6373deb3ec6SMatthias Ringwald int bnep_set_multicast_filter(uint16_t bnep_cid, bnep_multi_filter_t *filter, uint16_t len)
6383deb3ec6SMatthias Ringwald {
6393deb3ec6SMatthias Ringwald bnep_channel_t *channel;
6403deb3ec6SMatthias Ringwald
6413deb3ec6SMatthias Ringwald if (filter == NULL) {
6423deb3ec6SMatthias Ringwald return -1;
6433deb3ec6SMatthias Ringwald }
6443deb3ec6SMatthias Ringwald
6453deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(bnep_cid);
6463deb3ec6SMatthias Ringwald if (channel == NULL) {
6473deb3ec6SMatthias Ringwald log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
6483deb3ec6SMatthias Ringwald return 1;
6493deb3ec6SMatthias Ringwald }
6503deb3ec6SMatthias Ringwald
6513deb3ec6SMatthias Ringwald if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
6523deb3ec6SMatthias Ringwald return BNEP_CHANNEL_NOT_CONNECTED;
6533deb3ec6SMatthias Ringwald }
6543deb3ec6SMatthias Ringwald
65566b1fcb3SMatthias Ringwald if (len > MAX_BNEP_MULTICAST_FILTER_OUT) {
6563deb3ec6SMatthias Ringwald return BNEP_DATA_LEN_EXCEEDS_MTU;
6573deb3ec6SMatthias Ringwald }
6583deb3ec6SMatthias Ringwald
6593deb3ec6SMatthias Ringwald channel->multicast_filter_out = filter;
6603deb3ec6SMatthias Ringwald channel->multicast_filter_out_count = len;
6613deb3ec6SMatthias Ringwald
6624e366553SMatthias Ringwald /* Set flag to send out the multicast filter set request */
6633deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
6644e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
6653deb3ec6SMatthias Ringwald
6663deb3ec6SMatthias Ringwald return 0;
6673deb3ec6SMatthias Ringwald }
6683deb3ec6SMatthias Ringwald
6693deb3ec6SMatthias Ringwald /* BNEP timeout timer helper function */
bnep_channel_timer_handler(btstack_timer_source_t * timer)670ec820d77SMatthias Ringwald static void bnep_channel_timer_handler(btstack_timer_source_t *timer)
6713deb3ec6SMatthias Ringwald {
67291a977e8SMatthias Ringwald bnep_channel_t *channel = btstack_run_loop_get_timer_context(timer);
6733deb3ec6SMatthias Ringwald // retry send setup connection at least one time
6743deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE){
6753deb3ec6SMatthias Ringwald if (channel->retry_count < BNEP_CONNECTION_MAX_RETRIES){
6763deb3ec6SMatthias Ringwald channel->retry_count++;
6773deb3ec6SMatthias Ringwald bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
6783deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
6794e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
6803deb3ec6SMatthias Ringwald return;
6813deb3ec6SMatthias Ringwald }
6823deb3ec6SMatthias Ringwald }
6833deb3ec6SMatthias Ringwald
6843deb3ec6SMatthias Ringwald log_info( "bnep_channel_timeout_handler callback: shutting down connection!");
6853deb3ec6SMatthias Ringwald bnep_emit_channel_timeout(channel);
6863deb3ec6SMatthias Ringwald bnep_channel_finalize(channel);
6873deb3ec6SMatthias Ringwald }
6883deb3ec6SMatthias Ringwald
6893deb3ec6SMatthias Ringwald
bnep_channel_stop_timer(bnep_channel_t * channel)6903deb3ec6SMatthias Ringwald static void bnep_channel_stop_timer(bnep_channel_t *channel)
6913deb3ec6SMatthias Ringwald {
6923deb3ec6SMatthias Ringwald if (channel->timer_active) {
693528a4a3bSMatthias Ringwald btstack_run_loop_remove_timer(&channel->timer);
6943deb3ec6SMatthias Ringwald channel->timer_active = 0;
6953deb3ec6SMatthias Ringwald }
6963deb3ec6SMatthias Ringwald }
6973deb3ec6SMatthias Ringwald
bnep_channel_start_timer(bnep_channel_t * channel,int timeout)6983deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout)
6993deb3ec6SMatthias Ringwald {
7003deb3ec6SMatthias Ringwald /* Stop any eventually running timeout timer */
7013deb3ec6SMatthias Ringwald bnep_channel_stop_timer(channel);
7023deb3ec6SMatthias Ringwald
7033deb3ec6SMatthias Ringwald /* Start bnep channel timeout check timer */
704528a4a3bSMatthias Ringwald btstack_run_loop_set_timer(&channel->timer, timeout);
70591a977e8SMatthias Ringwald btstack_run_loop_set_timer_handler(&channel->timer, bnep_channel_timer_handler);
70691a977e8SMatthias Ringwald btstack_run_loop_set_timer_context(&channel->timer, channel);
707528a4a3bSMatthias Ringwald btstack_run_loop_add_timer(&channel->timer);
7083deb3ec6SMatthias Ringwald channel->timer_active = 1;
7093deb3ec6SMatthias Ringwald }
7103deb3ec6SMatthias Ringwald
7113deb3ec6SMatthias Ringwald /* BNEP statemachine functions */
7123deb3ec6SMatthias Ringwald
bnep_channel_state_add(bnep_channel_t * channel,BNEP_CHANNEL_STATE_VAR event)7133deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
7143deb3ec6SMatthias Ringwald channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var | event);
7153deb3ec6SMatthias Ringwald }
bnep_channel_state_remove(bnep_channel_t * channel,BNEP_CHANNEL_STATE_VAR event)7163deb3ec6SMatthias Ringwald inline static void bnep_channel_state_remove(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
7173deb3ec6SMatthias Ringwald channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var & ~event);
7183deb3ec6SMatthias Ringwald }
7193deb3ec6SMatthias Ringwald
bnep_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu)7203deb3ec6SMatthias Ringwald static uint16_t bnep_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
7213deb3ec6SMatthias Ringwald
7223deb3ec6SMatthias Ringwald /* Assume a standard BNEP header, containing BNEP Type (1 Byte), dest and
7233deb3ec6SMatthias Ringwald source address (6 bytes each) and networking protocol type (2 bytes)
7243deb3ec6SMatthias Ringwald */
7253deb3ec6SMatthias Ringwald uint16_t max_frame_size = l2cap_mtu - 15; // 15 bytes BNEP header
7263deb3ec6SMatthias Ringwald
7273deb3ec6SMatthias Ringwald log_info("bnep_max_frame_size_for_l2cap_mtu: %u -> %u", l2cap_mtu, max_frame_size);
7283deb3ec6SMatthias Ringwald return max_frame_size;
7293deb3ec6SMatthias Ringwald }
7303deb3ec6SMatthias Ringwald
bnep_channel_create_for_addr(bd_addr_t addr)7313deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_create_for_addr(bd_addr_t addr)
7323deb3ec6SMatthias Ringwald {
7333deb3ec6SMatthias Ringwald /* Allocate new channel structure */
7343deb3ec6SMatthias Ringwald bnep_channel_t *channel = btstack_memory_bnep_channel_get();
7353deb3ec6SMatthias Ringwald if (!channel) {
7363deb3ec6SMatthias Ringwald return NULL;
7373deb3ec6SMatthias Ringwald }
7383deb3ec6SMatthias Ringwald
7393deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_CLOSED;
7403deb3ec6SMatthias Ringwald channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
74173988a59SMatthias Ringwald bd_addr_copy(channel->remote_addr, addr);
74215a95bd5SMatthias Ringwald gap_local_bd_addr(channel->local_addr);
7433deb3ec6SMatthias Ringwald
7443deb3ec6SMatthias Ringwald channel->net_filter_count = 0;
7453deb3ec6SMatthias Ringwald channel->multicast_filter_count = 0;
7463deb3ec6SMatthias Ringwald channel->retry_count = 0;
7473deb3ec6SMatthias Ringwald
7483deb3ec6SMatthias Ringwald /* Finally add it to the channel list */
749665d90f2SMatthias Ringwald btstack_linked_list_add(&bnep_channels, (btstack_linked_item_t *) channel);
7503deb3ec6SMatthias Ringwald
7513deb3ec6SMatthias Ringwald return channel;
7523deb3ec6SMatthias Ringwald }
7533deb3ec6SMatthias Ringwald
bnep_channel_for_addr(bd_addr_t addr)7543deb3ec6SMatthias Ringwald static bnep_channel_t* bnep_channel_for_addr(bd_addr_t addr)
7553deb3ec6SMatthias Ringwald {
756665d90f2SMatthias Ringwald btstack_linked_item_t *it;
757665d90f2SMatthias Ringwald for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){
7583deb3ec6SMatthias Ringwald bnep_channel_t *channel = ((bnep_channel_t *) it);
759058e3d6bSMatthias Ringwald if (bd_addr_cmp(addr, channel->remote_addr) == 0) {
7603deb3ec6SMatthias Ringwald return channel;
7613deb3ec6SMatthias Ringwald }
7623deb3ec6SMatthias Ringwald }
7633deb3ec6SMatthias Ringwald return NULL;
7643deb3ec6SMatthias Ringwald }
7653deb3ec6SMatthias Ringwald
bnep_channel_for_l2cap_cid(uint16_t l2cap_cid)7663deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid)
7673deb3ec6SMatthias Ringwald {
768665d90f2SMatthias Ringwald btstack_linked_item_t *it;
769665d90f2SMatthias Ringwald for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){
7703deb3ec6SMatthias Ringwald bnep_channel_t *channel = ((bnep_channel_t *) it);
7713deb3ec6SMatthias Ringwald if (channel->l2cap_cid == l2cap_cid) {
7723deb3ec6SMatthias Ringwald return channel;
7733deb3ec6SMatthias Ringwald }
7743deb3ec6SMatthias Ringwald }
7753deb3ec6SMatthias Ringwald return NULL;
7763deb3ec6SMatthias Ringwald }
7773deb3ec6SMatthias Ringwald
bnep_service_for_uuid(uint16_t uuid)7783deb3ec6SMatthias Ringwald static bnep_service_t * bnep_service_for_uuid(uint16_t uuid)
7793deb3ec6SMatthias Ringwald {
780665d90f2SMatthias Ringwald btstack_linked_item_t *it;
781665d90f2SMatthias Ringwald for (it = (btstack_linked_item_t *) bnep_services; it ; it = it->next){
7823deb3ec6SMatthias Ringwald bnep_service_t * service = ((bnep_service_t *) it);
7833deb3ec6SMatthias Ringwald if ( service->service_uuid == uuid){
7843deb3ec6SMatthias Ringwald return service;
7853deb3ec6SMatthias Ringwald }
7863deb3ec6SMatthias Ringwald }
7873deb3ec6SMatthias Ringwald return NULL;
7883deb3ec6SMatthias Ringwald }
7893deb3ec6SMatthias Ringwald
bnep_channel_free(bnep_channel_t * channel)7903deb3ec6SMatthias Ringwald static void bnep_channel_free(bnep_channel_t *channel)
7913deb3ec6SMatthias Ringwald {
792665d90f2SMatthias Ringwald btstack_linked_list_remove( &bnep_channels, (btstack_linked_item_t *) channel);
7933deb3ec6SMatthias Ringwald btstack_memory_bnep_channel_free(channel);
7943deb3ec6SMatthias Ringwald }
7953deb3ec6SMatthias Ringwald
bnep_channel_finalize(bnep_channel_t * channel)7963deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel)
7973deb3ec6SMatthias Ringwald {
7983deb3ec6SMatthias Ringwald uint16_t l2cap_cid;
7993deb3ec6SMatthias Ringwald
8003deb3ec6SMatthias Ringwald /* Inform application about closed channel */
8013deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
8023deb3ec6SMatthias Ringwald bnep_emit_channel_closed(channel);
8033deb3ec6SMatthias Ringwald }
8043deb3ec6SMatthias Ringwald
8053deb3ec6SMatthias Ringwald l2cap_cid = channel->l2cap_cid;
8063deb3ec6SMatthias Ringwald
8073deb3ec6SMatthias Ringwald /* Stop any eventually running timer */
8083deb3ec6SMatthias Ringwald bnep_channel_stop_timer(channel);
8093deb3ec6SMatthias Ringwald
8103deb3ec6SMatthias Ringwald /* Free ressources and then close the l2cap channel */
8113deb3ec6SMatthias Ringwald bnep_channel_free(channel);
812b93f8966SMatthias Ringwald l2cap_disconnect(l2cap_cid);
8133deb3ec6SMatthias Ringwald }
8143deb3ec6SMatthias Ringwald
bnep_handle_connection_request(bnep_channel_t * channel,uint8_t * packet,uint16_t size)8153deb3ec6SMatthias Ringwald static int bnep_handle_connection_request(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
8163deb3ec6SMatthias Ringwald {
8173deb3ec6SMatthias Ringwald uint16_t uuid_size;
818bb015fa7SMatthias Ringwald uint16_t uuid_offset = 0; // avoid "may be unitialized when used" in clang
8193deb3ec6SMatthias Ringwald uuid_size = packet[1];
820*fe3c1d93SMatthias Ringwald uint16_t response_code = BNEP_SETUP_CONNECTION_RESPONSE_SUCCESS;
8213deb3ec6SMatthias Ringwald bnep_service_t * service;
8223deb3ec6SMatthias Ringwald
8233deb3ec6SMatthias Ringwald /* Sanity check packet size */
824a1df452eSMatthias Ringwald if (size < (1 + 1 + (2 * uuid_size))) {
8253deb3ec6SMatthias Ringwald return 0;
8263deb3ec6SMatthias Ringwald }
8273deb3ec6SMatthias Ringwald
8283deb3ec6SMatthias Ringwald if ((channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
8293deb3ec6SMatthias Ringwald (channel->state != BNEP_CHANNEL_STATE_CONNECTED)) {
8303deb3ec6SMatthias Ringwald /* Ignore a connection request if not waiting for or still connected */
8313deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_REQUEST: ignored in state %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
8323deb3ec6SMatthias Ringwald return 0;
8333deb3ec6SMatthias Ringwald }
8343deb3ec6SMatthias Ringwald
8353deb3ec6SMatthias Ringwald /* Extract source and destination UUID and convert them to UUID16 format */
8363deb3ec6SMatthias Ringwald switch (uuid_size) {
8373deb3ec6SMatthias Ringwald case 2: /* UUID16 */
8383deb3ec6SMatthias Ringwald uuid_offset = 0;
8393deb3ec6SMatthias Ringwald break;
8403deb3ec6SMatthias Ringwald case 4: /* UUID32 */
8413deb3ec6SMatthias Ringwald case 16: /* UUID128 */
8423deb3ec6SMatthias Ringwald uuid_offset = 2;
8433deb3ec6SMatthias Ringwald break;
8443deb3ec6SMatthias Ringwald default:
8453deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_REQUEST: Invalid UUID size %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
846*fe3c1d93SMatthias Ringwald response_code = BNEP_SETUP_CONNECTION_RESPONSE_INVALID_SERVICE_UUID_SIZE;
8473deb3ec6SMatthias Ringwald break;
8483deb3ec6SMatthias Ringwald }
8493deb3ec6SMatthias Ringwald
850d4d9523fSMatthias Ringwald /* Check bits 16-31 of UUID */
851d4d9523fSMatthias Ringwald if (uuid_size > 2){
852d4d9523fSMatthias Ringwald uint16_t dest_prefix = big_endian_read_16(packet, 2);
853d4d9523fSMatthias Ringwald if (dest_prefix != 0){
854*fe3c1d93SMatthias Ringwald response_code = BNEP_SETUP_CONNECTION_RESPONSE_INVALID_DEST_UUID;
855d4d9523fSMatthias Ringwald }
856d4d9523fSMatthias Ringwald uint16_t src_prefix = big_endian_read_16(packet, 2 + uuid_size);
857d4d9523fSMatthias Ringwald if (src_prefix != 0){
858*fe3c1d93SMatthias Ringwald response_code = BNEP_SETUP_CONNECTION_RESPONSE_INVALID_SOURCE_UUID;
859d4d9523fSMatthias Ringwald }
860d4d9523fSMatthias Ringwald }
861d4d9523fSMatthias Ringwald
862d4d9523fSMatthias Ringwald /* check bits 32-127 of UUID */
863d4d9523fSMatthias Ringwald if (uuid_size == 16){
864d4d9523fSMatthias Ringwald if (uuid_has_bluetooth_prefix(&packet[2]) == false){
865*fe3c1d93SMatthias Ringwald response_code = BNEP_SETUP_CONNECTION_RESPONSE_INVALID_DEST_UUID;
866d4d9523fSMatthias Ringwald }
867d4d9523fSMatthias Ringwald if (uuid_has_bluetooth_prefix(&packet[2+16]) == false){
868*fe3c1d93SMatthias Ringwald response_code = BNEP_SETUP_CONNECTION_RESPONSE_INVALID_SOURCE_UUID;
869d4d9523fSMatthias Ringwald }
870d4d9523fSMatthias Ringwald }
871d4d9523fSMatthias Ringwald
8723deb3ec6SMatthias Ringwald /* Check source and destination UUIDs for valid combinations */
873*fe3c1d93SMatthias Ringwald if (response_code == BNEP_SETUP_CONNECTION_RESPONSE_SUCCESS) {
874f8fbdce0SMatthias Ringwald channel->uuid_dest = big_endian_read_16(packet, 2 + uuid_offset);
875f8fbdce0SMatthias Ringwald channel->uuid_source = big_endian_read_16(packet, 2 + uuid_offset + uuid_size);
8763deb3ec6SMatthias Ringwald
877235946f1SMatthias Ringwald if ((channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU) &&
878235946f1SMatthias Ringwald (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_NAP) &&
879235946f1SMatthias Ringwald (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_GN)) {
8803deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_REQUEST: Invalid destination service UUID: %04x", channel->uuid_dest);
8813deb3ec6SMatthias Ringwald channel->uuid_dest = 0;
8823deb3ec6SMatthias Ringwald }
883235946f1SMatthias Ringwald if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) &&
884235946f1SMatthias Ringwald (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_NAP) &&
885235946f1SMatthias Ringwald (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_GN)) {
8863deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_REQUEST: Invalid source service UUID: %04x", channel->uuid_source);
8873deb3ec6SMatthias Ringwald channel->uuid_source = 0;
8883deb3ec6SMatthias Ringwald }
8893deb3ec6SMatthias Ringwald
8903deb3ec6SMatthias Ringwald /* Check if we have registered a service for the requested destination UUID */
8913deb3ec6SMatthias Ringwald service = bnep_service_for_uuid(channel->uuid_dest);
8923deb3ec6SMatthias Ringwald if (service == NULL) {
893*fe3c1d93SMatthias Ringwald response_code = BNEP_SETUP_CONNECTION_RESPONSE_INVALID_DEST_UUID;
8940c249750SMatthias Ringwald } else {
8950c249750SMatthias Ringwald // use packet handler for service
8960c249750SMatthias Ringwald channel->packet_handler = service->packet_handler;
8970c249750SMatthias Ringwald
898235946f1SMatthias Ringwald if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) && (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU)) {
899*fe3c1d93SMatthias Ringwald response_code = BNEP_SETUP_CONNECTION_RESPONSE_INVALID_SOURCE_UUID;
9003deb3ec6SMatthias Ringwald }
9013deb3ec6SMatthias Ringwald }
9020c249750SMatthias Ringwald }
9033deb3ec6SMatthias Ringwald
9043deb3ec6SMatthias Ringwald /* Set flag to send out the connection response on next statemachine cycle */
9053deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
9063deb3ec6SMatthias Ringwald channel->response_code = response_code;
9074e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
9083deb3ec6SMatthias Ringwald
9093deb3ec6SMatthias Ringwald /* Return the number of processed package bytes = BNEP Type, BNEP Control Type, UUID-Size + 2 * UUID */
910c1ab6cc1SMatthias Ringwald return 1 + 1 + (2 * uuid_size);
9113deb3ec6SMatthias Ringwald }
9123deb3ec6SMatthias Ringwald
bnep_handle_connection_response(bnep_channel_t * channel,uint8_t * packet,uint16_t size)9133deb3ec6SMatthias Ringwald static int bnep_handle_connection_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9143deb3ec6SMatthias Ringwald {
9153deb3ec6SMatthias Ringwald
9163deb3ec6SMatthias Ringwald /* Sanity check packet size */
917c1ab6cc1SMatthias Ringwald if (size < (1 + 2)) {
9183deb3ec6SMatthias Ringwald return 0;
9193deb3ec6SMatthias Ringwald }
9203deb3ec6SMatthias Ringwald
9213deb3ec6SMatthias Ringwald if (channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE) {
9223deb3ec6SMatthias Ringwald /* Ignore a connection response in any state but WAIT_FOR_CONNECTION_RESPONSE */
9233deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_RESPONSE: Ignored in channel state %d", channel->state);
9243deb3ec6SMatthias Ringwald return 1 + 2;
9253deb3ec6SMatthias Ringwald }
9263deb3ec6SMatthias Ringwald
92737e1b220SMatthias Ringwald uint16_t response_code = big_endian_read_16(packet, 1);
9283deb3ec6SMatthias Ringwald
929*fe3c1d93SMatthias Ringwald if (response_code == BNEP_SETUP_CONNECTION_RESPONSE_SUCCESS) {
9303deb3ec6SMatthias Ringwald log_info("BNEP_CONNECTION_RESPONSE: Channel established to %s", bd_addr_to_str(channel->remote_addr));
9313deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_CONNECTED;
9323deb3ec6SMatthias Ringwald /* Stop timeout timer! */
9333deb3ec6SMatthias Ringwald bnep_channel_stop_timer(channel);
93437e1b220SMatthias Ringwald bnep_emit_open_channel_complete(channel, ERROR_CODE_SUCCESS, response_code);
9353deb3ec6SMatthias Ringwald } else {
9363deb3ec6SMatthias Ringwald log_error("BNEP_CONNECTION_RESPONSE: Connection to %s failed. Err: %d", bd_addr_to_str(channel->remote_addr), response_code);
93737e1b220SMatthias Ringwald bnep_emit_open_channel_complete(channel, BNEP_SETUP_CONNECTION_ERROR, response_code);
9383deb3ec6SMatthias Ringwald bnep_channel_finalize(channel);
9393deb3ec6SMatthias Ringwald }
9403deb3ec6SMatthias Ringwald return 1 + 2;
9413deb3ec6SMatthias Ringwald }
9423deb3ec6SMatthias Ringwald
bnep_can_handle_extensions(bnep_channel_t * channel)9433deb3ec6SMatthias Ringwald static int bnep_can_handle_extensions(bnep_channel_t * channel){
9443deb3ec6SMatthias Ringwald /* Extension are primarily handled in CONNECTED state */
9453deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) return 1;
9463deb3ec6SMatthias Ringwald /* and if we've received connection request, but haven't sent the reponse yet. */
9473deb3ec6SMatthias Ringwald if ((channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
9483deb3ec6SMatthias Ringwald (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE)) {
9493deb3ec6SMatthias Ringwald return 1;
9503deb3ec6SMatthias Ringwald }
9513deb3ec6SMatthias Ringwald return 0;
9523deb3ec6SMatthias Ringwald }
9533deb3ec6SMatthias Ringwald
bnep_handle_filter_net_type_set(bnep_channel_t * channel,uint8_t * packet,uint16_t size)9543deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9553deb3ec6SMatthias Ringwald {
9563deb3ec6SMatthias Ringwald uint16_t list_length;
9573deb3ec6SMatthias Ringwald uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
9583deb3ec6SMatthias Ringwald
9593deb3ec6SMatthias Ringwald /* Sanity check packet size */
9603deb3ec6SMatthias Ringwald if (size < 3) {
9613deb3ec6SMatthias Ringwald return 0;
9623deb3ec6SMatthias Ringwald }
9633deb3ec6SMatthias Ringwald
964f8fbdce0SMatthias Ringwald list_length = big_endian_read_16(packet, 1);
9653deb3ec6SMatthias Ringwald /* Sanity check packet size again with known package size */
966c1ab6cc1SMatthias Ringwald if (size < (3 + list_length)) {
9673deb3ec6SMatthias Ringwald return 0;
9683deb3ec6SMatthias Ringwald }
9693deb3ec6SMatthias Ringwald
9703deb3ec6SMatthias Ringwald if (!bnep_can_handle_extensions(channel)){
9713deb3ec6SMatthias Ringwald log_error("BNEP_FILTER_NET_TYPE_SET: Ignored in channel state %d", channel->state);
9723deb3ec6SMatthias Ringwald return 3 + list_length;
9733deb3ec6SMatthias Ringwald }
9743deb3ec6SMatthias Ringwald
9753deb3ec6SMatthias Ringwald /* Check if we have enough space for more filters */
9763deb3ec6SMatthias Ringwald if ((list_length / (2*2)) > MAX_BNEP_NETFILTER) {
9773deb3ec6SMatthias Ringwald log_info("BNEP_FILTER_NET_TYPE_SET: Too many filter");
9783deb3ec6SMatthias Ringwald response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
9793deb3ec6SMatthias Ringwald } else {
9803deb3ec6SMatthias Ringwald int i;
9813deb3ec6SMatthias Ringwald channel->net_filter_count = 0;
9823deb3ec6SMatthias Ringwald /* There is still enough space, copy the filters to our filter list */
983ef907034SMatthias Ringwald /* There is still enough space, copy the filters to our filter list */
984c1ab6cc1SMatthias Ringwald for (i = 0; i < (list_length / (2 * 2)); i ++) {
985c1ab6cc1SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_start = big_endian_read_16(packet, 1 + 2 + (i * 4));
986c1ab6cc1SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_end = big_endian_read_16(packet, 1 + 2 + (i * 4) + 2);
9873deb3ec6SMatthias Ringwald if (channel->net_filter[channel->net_filter_count].range_start > channel->net_filter[channel->net_filter_count].range_end) {
9883deb3ec6SMatthias Ringwald /* Invalid filter range, ignore this filter rule */
9893deb3ec6SMatthias Ringwald log_error("BNEP_FILTER_NET_TYPE_SET: Invalid filter: start: %d, end: %d",
9903deb3ec6SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_start,
9913deb3ec6SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_end);
9923deb3ec6SMatthias Ringwald response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
9933deb3ec6SMatthias Ringwald } else {
9943deb3ec6SMatthias Ringwald /* Valid filter, increase the filter count */
9953deb3ec6SMatthias Ringwald log_info("BNEP_FILTER_NET_TYPE_SET: Add filter: start: %d, end: %d",
9963deb3ec6SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_start,
9973deb3ec6SMatthias Ringwald channel->net_filter[channel->net_filter_count].range_end);
9983deb3ec6SMatthias Ringwald channel->net_filter_count ++;
9993deb3ec6SMatthias Ringwald }
10003deb3ec6SMatthias Ringwald }
10013deb3ec6SMatthias Ringwald }
10023deb3ec6SMatthias Ringwald
10033deb3ec6SMatthias Ringwald /* Set flag to send out the set net filter response on next statemachine cycle */
10043deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
10053deb3ec6SMatthias Ringwald channel->response_code = response_code;
10064e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
10073deb3ec6SMatthias Ringwald
10083deb3ec6SMatthias Ringwald return 3 + list_length;
10093deb3ec6SMatthias Ringwald }
10103deb3ec6SMatthias Ringwald
bnep_handle_filter_net_type_response(bnep_channel_t * channel,uint8_t * packet,uint16_t size)10113deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
10123deb3ec6SMatthias Ringwald {
10133deb3ec6SMatthias Ringwald uint16_t response_code;
10143deb3ec6SMatthias Ringwald
10153deb3ec6SMatthias Ringwald // TODO: Currently we do not support setting a network filter.
10163deb3ec6SMatthias Ringwald
10173deb3ec6SMatthias Ringwald /* Sanity check packet size */
1018c1ab6cc1SMatthias Ringwald if (size < (1 + 2)) {
10193deb3ec6SMatthias Ringwald return 0;
10203deb3ec6SMatthias Ringwald }
10213deb3ec6SMatthias Ringwald
10223deb3ec6SMatthias Ringwald if (!bnep_can_handle_extensions(channel)){
10233deb3ec6SMatthias Ringwald log_error("BNEP_FILTER_NET_TYPE_RESPONSE: Ignored in channel state %d", channel->state);
10243deb3ec6SMatthias Ringwald return 1 + 2;
10253deb3ec6SMatthias Ringwald }
10263deb3ec6SMatthias Ringwald
1027f8fbdce0SMatthias Ringwald response_code = big_endian_read_16(packet, 1);
10283deb3ec6SMatthias Ringwald
10293deb3ec6SMatthias Ringwald if (response_code == BNEP_RESP_FILTER_SUCCESS) {
10303deb3ec6SMatthias Ringwald log_info("BNEP_FILTER_NET_TYPE_RESPONSE: Net filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
10313deb3ec6SMatthias Ringwald } else {
10323deb3ec6SMatthias 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);
10333deb3ec6SMatthias Ringwald }
10343deb3ec6SMatthias Ringwald
10353deb3ec6SMatthias Ringwald return 1 + 2;
10363deb3ec6SMatthias Ringwald }
10373deb3ec6SMatthias Ringwald
bnep_handle_multi_addr_set(bnep_channel_t * channel,uint8_t * packet,uint16_t size)10383deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
10393deb3ec6SMatthias Ringwald {
10403deb3ec6SMatthias Ringwald uint16_t list_length;
10413deb3ec6SMatthias Ringwald uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
10423deb3ec6SMatthias Ringwald
10433deb3ec6SMatthias Ringwald /* Sanity check packet size */
10443deb3ec6SMatthias Ringwald if (size < 3) {
10453deb3ec6SMatthias Ringwald return 0;
10463deb3ec6SMatthias Ringwald }
10473deb3ec6SMatthias Ringwald
1048f8fbdce0SMatthias Ringwald list_length = big_endian_read_16(packet, 1);
10493deb3ec6SMatthias Ringwald /* Sanity check packet size again with known package size */
1050c1ab6cc1SMatthias Ringwald if (size < (3 + list_length)) {
10513deb3ec6SMatthias Ringwald return 0;
10523deb3ec6SMatthias Ringwald }
10533deb3ec6SMatthias Ringwald
10543deb3ec6SMatthias Ringwald if (!bnep_can_handle_extensions(channel)){
10553deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_SET: Ignored in channel state %d", channel->state);
10563deb3ec6SMatthias Ringwald return 3 + list_length;
10573deb3ec6SMatthias Ringwald }
10583deb3ec6SMatthias Ringwald
10593deb3ec6SMatthias Ringwald /* Check if we have enough space for more filters */
1060b56e8b56SMatthias Ringwald uint16_t list_count = list_length / (2 * ETHER_ADDR_LEN);
1061b56e8b56SMatthias Ringwald if (list_count > MAX_BNEP_MULTICAST_FILTER) {
10623deb3ec6SMatthias Ringwald log_info("BNEP_MULTI_ADDR_SET: Too many filter");
10633deb3ec6SMatthias Ringwald response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
10643deb3ec6SMatthias Ringwald } else {
10653deb3ec6SMatthias Ringwald unsigned int i;
10663deb3ec6SMatthias Ringwald channel->multicast_filter_count = 0;
10673deb3ec6SMatthias Ringwald /* There is enough space, copy the filters to our filter list */
1068b56e8b56SMatthias Ringwald for (i = 0; i < list_count; i ++) {
1069c1ab6cc1SMatthias Ringwald bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_start, packet + 1 + 2 + (i * ETHER_ADDR_LEN * 2));
1070c1ab6cc1SMatthias Ringwald bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_end, packet + 1 + 2 + (i * ETHER_ADDR_LEN * 2) + ETHER_ADDR_LEN);
10713deb3ec6SMatthias Ringwald
10723deb3ec6SMatthias Ringwald if (memcmp(channel->multicast_filter[channel->multicast_filter_count].addr_start,
10733deb3ec6SMatthias Ringwald channel->multicast_filter[channel->multicast_filter_count].addr_end, ETHER_ADDR_LEN) > 0) {
10743deb3ec6SMatthias Ringwald /* Invalid filter range, ignore this filter rule */
10753deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_SET: Invalid filter: start: %s",
10763deb3ec6SMatthias Ringwald bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
10773deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_SET: Invalid filter: end: %s",
10783deb3ec6SMatthias Ringwald bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
10793deb3ec6SMatthias Ringwald response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
10803deb3ec6SMatthias Ringwald } else {
10813deb3ec6SMatthias Ringwald /* Valid filter, increase the filter count */
10823deb3ec6SMatthias Ringwald log_info("BNEP_MULTI_ADDR_SET: Add filter: start: %s",
10833deb3ec6SMatthias Ringwald bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
10843deb3ec6SMatthias Ringwald log_info("BNEP_MULTI_ADDR_SET: Add filter: end: %s",
10853deb3ec6SMatthias Ringwald bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
10863deb3ec6SMatthias Ringwald channel->multicast_filter_count ++;
10873deb3ec6SMatthias Ringwald }
10883deb3ec6SMatthias Ringwald }
10893deb3ec6SMatthias Ringwald }
10903deb3ec6SMatthias Ringwald /* Set flag to send out the set multi addr response on next statemachine cycle */
10913deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
10923deb3ec6SMatthias Ringwald channel->response_code = response_code;
10934e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
10943deb3ec6SMatthias Ringwald
10953deb3ec6SMatthias Ringwald return 3 + list_length;
10963deb3ec6SMatthias Ringwald }
10973deb3ec6SMatthias Ringwald
bnep_handle_multi_addr_response(bnep_channel_t * channel,uint8_t * packet,uint16_t size)10983deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
10993deb3ec6SMatthias Ringwald {
11003deb3ec6SMatthias Ringwald uint16_t response_code;
11013deb3ec6SMatthias Ringwald
11023deb3ec6SMatthias Ringwald // TODO: Currently we do not support setting multicast address filter.
11033deb3ec6SMatthias Ringwald
11043deb3ec6SMatthias Ringwald /* Sanity check packet size */
1105c1ab6cc1SMatthias Ringwald if (size < (1 + 2)) {
11063deb3ec6SMatthias Ringwald return 0;
11073deb3ec6SMatthias Ringwald }
11083deb3ec6SMatthias Ringwald
11093deb3ec6SMatthias Ringwald if (!bnep_can_handle_extensions(channel)){
11103deb3ec6SMatthias Ringwald log_error("BNEP_MULTI_ADDR_RESPONSE: Ignored in channel state %d", channel->state);
11113deb3ec6SMatthias Ringwald return 1 + 2;
11123deb3ec6SMatthias Ringwald }
11133deb3ec6SMatthias Ringwald
1114f8fbdce0SMatthias Ringwald response_code = big_endian_read_16(packet, 1);
11153deb3ec6SMatthias Ringwald
11163deb3ec6SMatthias Ringwald if (response_code == BNEP_RESP_FILTER_SUCCESS) {
11173deb3ec6SMatthias Ringwald log_info("BNEP_MULTI_ADDR_RESPONSE: Multicast address filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
11183deb3ec6SMatthias Ringwald } else {
11193deb3ec6SMatthias 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);
11203deb3ec6SMatthias Ringwald }
11213deb3ec6SMatthias Ringwald
11223deb3ec6SMatthias Ringwald return 1 + 2;
11233deb3ec6SMatthias Ringwald }
11243deb3ec6SMatthias Ringwald
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)11253deb3ec6SMatthias 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)
11263deb3ec6SMatthias Ringwald {
11273deb3ec6SMatthias Ringwald uint16_t pos = 0;
11283deb3ec6SMatthias Ringwald
1129f2e45468SMatthias 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)
11303deb3ec6SMatthias Ringwald /* In-place modify the package and add the ethernet header in front of the payload.
11313deb3ec6SMatthias Ringwald * WARNING: This modifies the data in front of the payload and may overwrite 14 bytes there!
11323deb3ec6SMatthias Ringwald */
11330e588213SMatthias Ringwald uint8_t *ethernet_packet = payload - (2 * sizeof(bd_addr_t)) - sizeof(uint16_t);
11343deb3ec6SMatthias Ringwald /* Restore the ethernet packet header */
1135058e3d6bSMatthias Ringwald bd_addr_copy(ethernet_packet + pos, addr_dest);
11363deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t);
1137058e3d6bSMatthias Ringwald bd_addr_copy(ethernet_packet + pos, addr_source);
11383deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t);
1139f8fbdce0SMatthias Ringwald big_endian_store_16(ethernet_packet, pos, network_protocol_type);
11403deb3ec6SMatthias Ringwald /* Payload is just in place... */
11413deb3ec6SMatthias Ringwald #else
1142f2e45468SMatthias Ringwald #error "BNEP requires HCI_INCOMING_PRE_BUFFER_SIZE >= 6. Please update bstack_config.h"
11433deb3ec6SMatthias Ringwald #endif
11443deb3ec6SMatthias Ringwald
11453deb3ec6SMatthias Ringwald /* Notify application layer and deliver the ethernet packet */
1146c9bf9c27SMatthias Ringwald if (channel->packet_handler){
1147c9bf9c27SMatthias Ringwald (*channel->packet_handler)(BNEP_DATA_PACKET, channel->l2cap_cid, ethernet_packet,
11480e588213SMatthias Ringwald size + sizeof(uint16_t) + (2 * sizeof(bd_addr_t)) );
1149c9bf9c27SMatthias Ringwald }
11503deb3ec6SMatthias Ringwald
11513deb3ec6SMatthias Ringwald return size;
11523deb3ec6SMatthias Ringwald }
11533deb3ec6SMatthias Ringwald
bnep_handle_control_packet(bnep_channel_t * channel,uint8_t * packet,uint16_t size,int is_extension)11543deb3ec6SMatthias Ringwald static int bnep_handle_control_packet(bnep_channel_t *channel, uint8_t *packet, uint16_t size, int is_extension)
11553deb3ec6SMatthias Ringwald {
11563deb3ec6SMatthias Ringwald uint16_t len = 0;
11573deb3ec6SMatthias Ringwald
1158b85ad952SMatthias Ringwald if (size > 0) {
1159b85ad952SMatthias Ringwald
1160b85ad952SMatthias Ringwald uint8_t bnep_control_type = packet[0];
11613deb3ec6SMatthias Ringwald /* Save last control type. Needed by statemachin in case of unknown control code */
11623deb3ec6SMatthias Ringwald
11633deb3ec6SMatthias Ringwald channel->last_control_type = bnep_control_type;
11643deb3ec6SMatthias Ringwald log_info("BNEP_CONTROL: Type: %d, size: %d, is_extension: %d", bnep_control_type, size, is_extension);
11653deb3ec6SMatthias Ringwald switch (bnep_control_type) {
11663deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD:
11673deb3ec6SMatthias Ringwald /* The last command we send was not understood. We should close the connection */
1168b85ad952SMatthias Ringwald log_error("BNEP_CONTROL: Received COMMAND_NOT_UNDERSTOOD: l2cap_cid: %d, cmd: %d", channel->l2cap_cid,
1169b85ad952SMatthias Ringwald packet[3]);
11703deb3ec6SMatthias Ringwald bnep_channel_finalize(channel);
11713deb3ec6SMatthias Ringwald len = 2; // Length of command not understood packet - bnep-type field
11723deb3ec6SMatthias Ringwald break;
11733deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST:
11743deb3ec6SMatthias Ringwald if (is_extension) {
11753deb3ec6SMatthias Ringwald /* Connection requests are not allowed to be send in an extension header
11763deb3ec6SMatthias Ringwald * ignore, do not set "COMMAND_NOT_UNDERSTOOD"
11773deb3ec6SMatthias Ringwald */
1178b85ad952SMatthias Ringwald log_error("BNEP_CONTROL: Received SETUP_CONNECTION_REQUEST in extension header: l2cap_cid: %d",
1179b85ad952SMatthias Ringwald channel->l2cap_cid);
11803deb3ec6SMatthias Ringwald return 0;
11813deb3ec6SMatthias Ringwald } else {
11823deb3ec6SMatthias Ringwald len = bnep_handle_connection_request(channel, packet, size);
11833deb3ec6SMatthias Ringwald }
11843deb3ec6SMatthias Ringwald break;
11853deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE:
11863deb3ec6SMatthias Ringwald if (is_extension) {
11873deb3ec6SMatthias Ringwald /* Connection requests are not allowed to be send in an
11883deb3ec6SMatthias Ringwald * extension header, ignore, do not set "COMMAND_NOT_UNDERSTOOD"
11893deb3ec6SMatthias Ringwald */
1190b85ad952SMatthias Ringwald log_error("BNEP_CONTROL: Received SETUP_CONNECTION_RESPONSE in extension header: l2cap_cid: %d",
1191b85ad952SMatthias Ringwald channel->l2cap_cid);
11923deb3ec6SMatthias Ringwald return 0;
11933deb3ec6SMatthias Ringwald } else {
11943deb3ec6SMatthias Ringwald len = bnep_handle_connection_response(channel, packet, size);
11953deb3ec6SMatthias Ringwald }
11963deb3ec6SMatthias Ringwald break;
11973deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET:
11983deb3ec6SMatthias Ringwald len = bnep_handle_filter_net_type_set(channel, packet, size);
11993deb3ec6SMatthias Ringwald break;
12003deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE:
12013deb3ec6SMatthias Ringwald len = bnep_handle_filter_net_type_response(channel, packet, size);
12023deb3ec6SMatthias Ringwald break;
12033deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET:
12043deb3ec6SMatthias Ringwald len = bnep_handle_multi_addr_set(channel, packet, size);
12053deb3ec6SMatthias Ringwald break;
12063deb3ec6SMatthias Ringwald case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE:
12073deb3ec6SMatthias Ringwald len = bnep_handle_multi_addr_response(channel, packet, size);
12083deb3ec6SMatthias Ringwald break;
12093deb3ec6SMatthias Ringwald default:
1210b85ad952SMatthias Ringwald log_error("BNEP_CONTROL: Invalid bnep control type: l2cap_cid: %d, cmd: %d", channel->l2cap_cid,
1211b85ad952SMatthias Ringwald bnep_control_type);
12123deb3ec6SMatthias Ringwald len = 0;
12133deb3ec6SMatthias Ringwald break;
12143deb3ec6SMatthias Ringwald }
1215b85ad952SMatthias Ringwald }
12163deb3ec6SMatthias Ringwald
12173deb3ec6SMatthias Ringwald if (len == 0) {
12183deb3ec6SMatthias Ringwald /* In case the command could not be handled, send a
12193deb3ec6SMatthias Ringwald COMMAND_NOT_UNDERSTOOD message.
12203deb3ec6SMatthias Ringwald Set flag to process the request in the next statemachine loop
12213deb3ec6SMatthias Ringwald */
12223deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
12234e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
12243deb3ec6SMatthias Ringwald }
12253deb3ec6SMatthias Ringwald
12263deb3ec6SMatthias Ringwald return len;
12273deb3ec6SMatthias Ringwald }
12283deb3ec6SMatthias Ringwald
12293deb3ec6SMatthias Ringwald /**
12303deb3ec6SMatthias Ringwald * @return handled packet
12313deb3ec6SMatthias Ringwald */
bnep_hci_event_handler(uint8_t * packet,uint16_t size)12323deb3ec6SMatthias Ringwald static int bnep_hci_event_handler(uint8_t *packet, uint16_t size)
12333deb3ec6SMatthias Ringwald {
1234f21eb74fSMatthias Ringwald UNUSED(size); // ok: handling own l2cap events
12359ec2630cSMatthias Ringwald
12363deb3ec6SMatthias Ringwald bd_addr_t event_addr;
12373deb3ec6SMatthias Ringwald uint16_t psm;
12383deb3ec6SMatthias Ringwald uint16_t l2cap_cid;
12393deb3ec6SMatthias Ringwald hci_con_handle_t con_handle;
12403deb3ec6SMatthias Ringwald bnep_channel_t *channel = NULL;
12413deb3ec6SMatthias Ringwald uint8_t status;
12423deb3ec6SMatthias Ringwald
12430e2df43fSMatthias Ringwald switch (hci_event_packet_get_type(packet)) {
12443deb3ec6SMatthias Ringwald
124584e3541eSMilanka Ringwald /* Accept an incoming L2CAP connection on BLUETOOTH_PSM_BNEP */
12463deb3ec6SMatthias Ringwald case L2CAP_EVENT_INCOMING_CONNECTION:
12473deb3ec6SMatthias Ringwald /* L2CAP event data: event(8), len(8), address(48), handle (16), psm (16), source cid(16) dest cid(16) */
1248724d70a2SMatthias Ringwald reverse_bd_addr(&packet[2], event_addr);
1249f8fbdce0SMatthias Ringwald con_handle = little_endian_read_16(packet, 8);
1250f8fbdce0SMatthias Ringwald psm = little_endian_read_16(packet, 10);
1251f8fbdce0SMatthias Ringwald l2cap_cid = little_endian_read_16(packet, 12);
12523deb3ec6SMatthias Ringwald
125384e3541eSMilanka Ringwald if (psm != BLUETOOTH_PSM_BNEP) break;
12543deb3ec6SMatthias Ringwald
12553deb3ec6SMatthias Ringwald channel = bnep_channel_for_addr(event_addr);
12563deb3ec6SMatthias Ringwald
12573deb3ec6SMatthias Ringwald if (channel) {
125884e3541eSMilanka Ringwald log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => decline - channel already exists", l2cap_cid);
12597ef6a7bbSMatthias Ringwald l2cap_decline_connection(l2cap_cid);
12603deb3ec6SMatthias Ringwald return 1;
12613deb3ec6SMatthias Ringwald }
12623deb3ec6SMatthias Ringwald
12633deb3ec6SMatthias Ringwald /* Create a new BNEP channel instance (incoming) */
12643deb3ec6SMatthias Ringwald channel = bnep_channel_create_for_addr(event_addr);
12653deb3ec6SMatthias Ringwald
12663deb3ec6SMatthias Ringwald if (!channel) {
126784e3541eSMilanka Ringwald log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => decline - no memory left", l2cap_cid);
12687ef6a7bbSMatthias Ringwald l2cap_decline_connection(l2cap_cid);
12693deb3ec6SMatthias Ringwald return 1;
12703deb3ec6SMatthias Ringwald }
12713deb3ec6SMatthias Ringwald
12723deb3ec6SMatthias Ringwald /* Assign connection handle and l2cap cid */
12733deb3ec6SMatthias Ringwald channel->con_handle = con_handle;
12743deb3ec6SMatthias Ringwald channel->l2cap_cid = l2cap_cid;
12753deb3ec6SMatthias Ringwald
12763deb3ec6SMatthias Ringwald /* Set channel into accept state */
12773deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST;
12783deb3ec6SMatthias Ringwald
12793deb3ec6SMatthias Ringwald /* Start connection timeout timer */
12803deb3ec6SMatthias Ringwald bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
12813deb3ec6SMatthias Ringwald
128284e3541eSMilanka Ringwald log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => accept", l2cap_cid);
1283ce8f182eSMatthias Ringwald l2cap_accept_connection(l2cap_cid);
12843deb3ec6SMatthias Ringwald return 1;
12853deb3ec6SMatthias Ringwald
12863deb3ec6SMatthias Ringwald /* Outgoing L2CAP connection has been opened -> store l2cap_cid, remote_addr */
12873deb3ec6SMatthias Ringwald case L2CAP_EVENT_CHANNEL_OPENED:
12883deb3ec6SMatthias Ringwald status = packet[2];
128984e3541eSMilanka Ringwald log_info("L2CAP_EVENT_CHANNEL_OPENED for BLUETOOTH_PSM_BNEP, status %u", status);
12903deb3ec6SMatthias Ringwald
12913deb3ec6SMatthias Ringwald /* Get the bnep channel fpr remote address */
1292f8fbdce0SMatthias Ringwald con_handle = little_endian_read_16(packet, 9);
1293f8fbdce0SMatthias Ringwald l2cap_cid = little_endian_read_16(packet, 13);
1294724d70a2SMatthias Ringwald reverse_bd_addr(&packet[3], event_addr);
12953deb3ec6SMatthias Ringwald channel = bnep_channel_for_addr(event_addr);
12963deb3ec6SMatthias Ringwald if (!channel) {
12973deb3ec6SMatthias Ringwald log_error("L2CAP_EVENT_CHANNEL_OPENED but no BNEP channel prepared");
12983deb3ec6SMatthias Ringwald return 1;
12993deb3ec6SMatthias Ringwald }
13003deb3ec6SMatthias Ringwald
13013deb3ec6SMatthias Ringwald /* On L2CAP open error discard everything */
13023deb3ec6SMatthias Ringwald if (status) {
13033deb3ec6SMatthias Ringwald /* Emit bnep_open_channel_complete with status and free channel */
130437e1b220SMatthias Ringwald bnep_emit_open_channel_complete(channel, status, 0);
13053deb3ec6SMatthias Ringwald
13063deb3ec6SMatthias Ringwald /* Free BNEP channel mempory */
13073deb3ec6SMatthias Ringwald bnep_channel_free(channel);
13083deb3ec6SMatthias Ringwald return 1;
13093deb3ec6SMatthias Ringwald }
13103deb3ec6SMatthias Ringwald
13113deb3ec6SMatthias Ringwald switch (channel->state){
13123deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_CLOSED:
13133deb3ec6SMatthias Ringwald log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
13143deb3ec6SMatthias Ringwald
13153deb3ec6SMatthias Ringwald bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
13163deb3ec6SMatthias Ringwald
13173deb3ec6SMatthias Ringwald /* Assign connection handle and l2cap cid */
13183deb3ec6SMatthias Ringwald channel->l2cap_cid = l2cap_cid;
13193deb3ec6SMatthias Ringwald channel->con_handle = con_handle;
13203deb3ec6SMatthias Ringwald
13213deb3ec6SMatthias Ringwald /* Initiate the connection request */
13223deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
13233deb3ec6SMatthias Ringwald bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
1324f8fbdce0SMatthias Ringwald channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
13254e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
13263deb3ec6SMatthias Ringwald break;
13273deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
13283deb3ec6SMatthias Ringwald /* New information: channel mtu */
1329f8fbdce0SMatthias Ringwald channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
13303deb3ec6SMatthias Ringwald break;
13313deb3ec6SMatthias Ringwald default:
13323deb3ec6SMatthias Ringwald log_error("L2CAP_EVENT_CHANNEL_OPENED: Invalid state: %d", channel->state);
13333deb3ec6SMatthias Ringwald break;
13343deb3ec6SMatthias Ringwald }
13353deb3ec6SMatthias Ringwald return 1;
13363deb3ec6SMatthias Ringwald
13371b89a84bSMatthias Ringwald case L2CAP_EVENT_CAN_SEND_NOW:
13384e366553SMatthias Ringwald bnep_handle_can_send_now(l2cap_event_can_send_now_get_local_cid(packet));
13393deb3ec6SMatthias Ringwald break;
13403deb3ec6SMatthias Ringwald
13413deb3ec6SMatthias Ringwald case L2CAP_EVENT_CHANNEL_CLOSED:
13423deb3ec6SMatthias Ringwald // data: event (8), len(8), channel (16)
1343f8fbdce0SMatthias Ringwald l2cap_cid = little_endian_read_16(packet, 2);
13443deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(l2cap_cid);
13453deb3ec6SMatthias Ringwald log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, channel %p", l2cap_cid, channel);
13463deb3ec6SMatthias Ringwald
13473deb3ec6SMatthias Ringwald if (!channel) {
13483deb3ec6SMatthias Ringwald break;
13493deb3ec6SMatthias Ringwald }
13503deb3ec6SMatthias Ringwald
13513deb3ec6SMatthias Ringwald log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", channel->state);
13523deb3ec6SMatthias Ringwald switch (channel->state) {
13533deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
13543deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE:
13553deb3ec6SMatthias Ringwald case BNEP_CHANNEL_STATE_CONNECTED:
13563deb3ec6SMatthias Ringwald bnep_channel_finalize(channel);
13573deb3ec6SMatthias Ringwald return 1;
13583deb3ec6SMatthias Ringwald default:
13593deb3ec6SMatthias Ringwald break;
13603deb3ec6SMatthias Ringwald }
13613deb3ec6SMatthias Ringwald break;
13623deb3ec6SMatthias Ringwald default:
13633deb3ec6SMatthias Ringwald break;
13643deb3ec6SMatthias Ringwald }
13653deb3ec6SMatthias Ringwald return 0;
13663deb3ec6SMatthias Ringwald }
13673deb3ec6SMatthias Ringwald
bnep_l2cap_packet_handler(uint16_t l2cap_cid,uint8_t * packet,uint16_t size)13683deb3ec6SMatthias Ringwald static int bnep_l2cap_packet_handler(uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
13693deb3ec6SMatthias Ringwald {
13703deb3ec6SMatthias Ringwald int rc = 0;
13713deb3ec6SMatthias Ringwald uint8_t bnep_type;
13723deb3ec6SMatthias Ringwald uint8_t bnep_header_has_ext;
13733deb3ec6SMatthias Ringwald uint8_t extension_type;
13743deb3ec6SMatthias Ringwald uint16_t pos = 0;
13753deb3ec6SMatthias Ringwald bd_addr_t addr_source;
13763deb3ec6SMatthias Ringwald bd_addr_t addr_dest;
13773deb3ec6SMatthias Ringwald uint16_t network_protocol_type = 0xffff;
13783deb3ec6SMatthias Ringwald bnep_channel_t *channel = NULL;
13793deb3ec6SMatthias Ringwald
13803deb3ec6SMatthias Ringwald /* Get the bnep channel for this package */
13813deb3ec6SMatthias Ringwald channel = bnep_channel_for_l2cap_cid(l2cap_cid);
13823deb3ec6SMatthias Ringwald if (!channel) {
13833deb3ec6SMatthias Ringwald return rc;
13843deb3ec6SMatthias Ringwald }
13853deb3ec6SMatthias Ringwald
13863deb3ec6SMatthias Ringwald /* Sort out short packages */
13873deb3ec6SMatthias Ringwald if (size < 2) {
13883deb3ec6SMatthias Ringwald return rc;
13893deb3ec6SMatthias Ringwald }
13903deb3ec6SMatthias Ringwald
13913deb3ec6SMatthias Ringwald bnep_type = BNEP_TYPE(packet[pos]);
13923deb3ec6SMatthias Ringwald bnep_header_has_ext = BNEP_HEADER_HAS_EXT(packet[pos]);
13933deb3ec6SMatthias Ringwald pos ++;
13943deb3ec6SMatthias Ringwald
13953deb3ec6SMatthias Ringwald switch(bnep_type) {
13963deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_GENERAL_ETHERNET:
1397b85ad952SMatthias Ringwald if ((pos + 14) > size) {
1398b85ad952SMatthias Ringwald return rc;
1399b85ad952SMatthias Ringwald }
1400058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, &packet[pos]);
14013deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t);
1402058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, &packet[pos]);
14033deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t);
1404f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos);
14053deb3ec6SMatthias Ringwald pos += 2;
14063deb3ec6SMatthias Ringwald break;
14073deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_COMPRESSED_ETHERNET:
1408b85ad952SMatthias Ringwald if ((pos + 2) > size) {
1409b85ad952SMatthias Ringwald return rc;
1410b85ad952SMatthias Ringwald }
1411058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, channel->local_addr);
1412058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, channel->remote_addr);
1413f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos);
14143deb3ec6SMatthias Ringwald pos += 2;
14153deb3ec6SMatthias Ringwald break;
14163deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY:
1417b85ad952SMatthias Ringwald if ((pos + 8) > size) {
1418b85ad952SMatthias Ringwald return rc;
1419b85ad952SMatthias Ringwald }
1420058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, channel->local_addr);
1421058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, &packet[pos]);
14223deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t);
1423f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos);
14243deb3ec6SMatthias Ringwald pos += 2;
14253deb3ec6SMatthias Ringwald break;
14263deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY:
1427b85ad952SMatthias Ringwald if ((pos + 8) > size) {
1428b85ad952SMatthias Ringwald return rc;
1429b85ad952SMatthias Ringwald }
1430058e3d6bSMatthias Ringwald bd_addr_copy(addr_dest, &packet[pos]);
14313deb3ec6SMatthias Ringwald pos += sizeof(bd_addr_t);
1432058e3d6bSMatthias Ringwald bd_addr_copy(addr_source, channel->remote_addr);
1433f8fbdce0SMatthias Ringwald network_protocol_type = big_endian_read_16(packet, pos);
14343deb3ec6SMatthias Ringwald pos += 2;
14353deb3ec6SMatthias Ringwald break;
14363deb3ec6SMatthias Ringwald case BNEP_PKT_TYPE_CONTROL:
14373deb3ec6SMatthias Ringwald rc = bnep_handle_control_packet(channel, packet + pos, size - pos, 0);
1438b85ad952SMatthias Ringwald if (rc == 0){
1439b85ad952SMatthias Ringwald // invalid control packet
1440b85ad952SMatthias Ringwald return 0;
1441b85ad952SMatthias Ringwald }
14423deb3ec6SMatthias Ringwald pos += rc;
14433deb3ec6SMatthias Ringwald break;
14443deb3ec6SMatthias Ringwald default:
14453deb3ec6SMatthias Ringwald break;
14463deb3ec6SMatthias Ringwald }
14473deb3ec6SMatthias Ringwald
14483deb3ec6SMatthias Ringwald if (bnep_header_has_ext) {
14493deb3ec6SMatthias Ringwald do {
14503deb3ec6SMatthias Ringwald uint8_t ext_len;
14513deb3ec6SMatthias Ringwald
1452b85ad952SMatthias Ringwald if (pos + 2 > size) {
1453b85ad952SMatthias Ringwald return rc;
1454b85ad952SMatthias Ringwald }
1455b85ad952SMatthias Ringwald
14563deb3ec6SMatthias Ringwald /* Read extension type and check for further extensions */
14573deb3ec6SMatthias Ringwald extension_type = BNEP_TYPE(packet[pos]);
14583deb3ec6SMatthias Ringwald bnep_header_has_ext = BNEP_HEADER_HAS_EXT(packet[pos]);
14593deb3ec6SMatthias Ringwald pos ++;
14603deb3ec6SMatthias Ringwald
14613deb3ec6SMatthias Ringwald /* Read extension header length */
14623deb3ec6SMatthias Ringwald ext_len = packet[pos];
14633deb3ec6SMatthias Ringwald pos ++;
14643deb3ec6SMatthias Ringwald
1465c1ab6cc1SMatthias Ringwald if ((size - pos) < ext_len) {
14663deb3ec6SMatthias Ringwald return 0;
14673deb3ec6SMatthias Ringwald }
14683deb3ec6SMatthias Ringwald
14693deb3ec6SMatthias Ringwald switch (extension_type) {
14703deb3ec6SMatthias Ringwald case BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL:
14713deb3ec6SMatthias Ringwald if (ext_len != bnep_handle_control_packet(channel, packet + pos, ext_len, 1)) {
14723deb3ec6SMatthias Ringwald log_error("BNEP pkt handler: Ignore invalid control packet in extension header");
14733deb3ec6SMatthias Ringwald }
14743deb3ec6SMatthias Ringwald
14753deb3ec6SMatthias Ringwald pos += ext_len;
14763deb3ec6SMatthias Ringwald break;
14773deb3ec6SMatthias Ringwald
14783deb3ec6SMatthias Ringwald default:
1479b85ad952SMatthias Ringwald /* Extension header type unknown. Unknown extension SHALL be forwarded
1480b85ad952SMatthias Ringwald * in any way. But who shall handle these extension packets?
14813deb3ec6SMatthias Ringwald * For now: We ignore them and just drop them!
14823deb3ec6SMatthias Ringwald */
14833deb3ec6SMatthias Ringwald log_error("BNEP pkt handler: Unknown extension type ignored, data dropped!");
14843deb3ec6SMatthias Ringwald pos += ext_len;
14853deb3ec6SMatthias Ringwald break;
14863deb3ec6SMatthias Ringwald }
14873deb3ec6SMatthias Ringwald
14883deb3ec6SMatthias Ringwald } while (bnep_header_has_ext);
14893deb3ec6SMatthias Ringwald }
14903deb3ec6SMatthias Ringwald
1491c1ab6cc1SMatthias Ringwald if ((bnep_type != BNEP_PKT_TYPE_CONTROL) && (network_protocol_type != 0xffff)) {
14923deb3ec6SMatthias Ringwald if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
14933deb3ec6SMatthias Ringwald rc = bnep_handle_ethernet_packet(channel, addr_dest, addr_source, network_protocol_type, packet + pos, size - pos);
14943deb3ec6SMatthias Ringwald } else {
14953deb3ec6SMatthias Ringwald rc = 0;
14963deb3ec6SMatthias Ringwald }
14973deb3ec6SMatthias Ringwald }
14983deb3ec6SMatthias Ringwald
14993deb3ec6SMatthias Ringwald return rc;
15003deb3ec6SMatthias Ringwald
15013deb3ec6SMatthias Ringwald }
15023deb3ec6SMatthias Ringwald
bnep_packet_handler(uint8_t packet_type,uint16_t l2cap_cid,uint8_t * packet,uint16_t size)15033deb3ec6SMatthias Ringwald void bnep_packet_handler(uint8_t packet_type, uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
15043deb3ec6SMatthias Ringwald {
15053deb3ec6SMatthias Ringwald switch (packet_type) {
15063deb3ec6SMatthias Ringwald case HCI_EVENT_PACKET:
1507bef9a6fcSMatthias Ringwald bnep_hci_event_handler(packet, size);
15083deb3ec6SMatthias Ringwald break;
15093deb3ec6SMatthias Ringwald case L2CAP_DATA_PACKET:
1510bef9a6fcSMatthias Ringwald bnep_l2cap_packet_handler(l2cap_cid, packet, size);
15113deb3ec6SMatthias Ringwald break;
15123deb3ec6SMatthias Ringwald default:
15133deb3ec6SMatthias Ringwald break;
15143deb3ec6SMatthias Ringwald }
15153deb3ec6SMatthias Ringwald }
15163deb3ec6SMatthias Ringwald
bnep_channel_state_machine(bnep_channel_t * channel,bnep_channel_event_t * event)15173deb3ec6SMatthias Ringwald static void bnep_channel_state_machine(bnep_channel_t* channel, bnep_channel_event_t *event)
15183deb3ec6SMatthias Ringwald {
1519b42623deSMatthias Ringwald log_debug("bnep_state_machine: state %u, state var: %02x, event %u", channel->state, channel->state_var, event->type);
15203deb3ec6SMatthias Ringwald
15213deb3ec6SMatthias Ringwald if (event->type == BNEP_CH_EVT_READY_TO_SEND) {
15223deb3ec6SMatthias Ringwald /* Send outstanding packets. */
15233deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD) {
15243deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
15253deb3ec6SMatthias Ringwald bnep_send_command_not_understood(channel, channel->last_control_type);
15263deb3ec6SMatthias Ringwald return;
15273deb3ec6SMatthias Ringwald }
15283deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST) {
15293deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
15303deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
15313deb3ec6SMatthias Ringwald bnep_send_connection_request(channel, channel->uuid_source, channel->uuid_dest);
15323deb3ec6SMatthias Ringwald }
15333deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE) {
15343deb3ec6SMatthias Ringwald int emit_connected = 0;
15353deb3ec6SMatthias Ringwald if ((channel->state == BNEP_CHANNEL_STATE_CLOSED) ||
15363deb3ec6SMatthias Ringwald (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST)) {
15373deb3ec6SMatthias Ringwald /* Set channel state to STATE_CONNECTED */
15383deb3ec6SMatthias Ringwald channel->state = BNEP_CHANNEL_STATE_CONNECTED;
15393deb3ec6SMatthias Ringwald /* Stop timeout timer! */
15403deb3ec6SMatthias Ringwald bnep_channel_stop_timer(channel);
15413deb3ec6SMatthias Ringwald emit_connected = 1;
15423deb3ec6SMatthias Ringwald }
15433deb3ec6SMatthias Ringwald
15443deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
15453deb3ec6SMatthias Ringwald bnep_send_connection_response(channel, channel->response_code);
15463deb3ec6SMatthias Ringwald if (emit_connected){
154737e1b220SMatthias Ringwald bnep_emit_open_channel_complete(channel, ERROR_CODE_SUCCESS, 0);
15483deb3ec6SMatthias Ringwald }
15493deb3ec6SMatthias Ringwald return;
15503deb3ec6SMatthias Ringwald }
15513deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET) {
15523deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
15533deb3ec6SMatthias Ringwald if ((channel->net_filter_out_count > 0) && (channel->net_filter_out != NULL)) {
15543deb3ec6SMatthias Ringwald bnep_send_filter_net_type_set(channel, channel->net_filter_out, channel->net_filter_out_count);
15553deb3ec6SMatthias Ringwald channel->net_filter_out_count = 0;
15563deb3ec6SMatthias Ringwald channel->net_filter_out = NULL;
15573deb3ec6SMatthias Ringwald }
15583deb3ec6SMatthias Ringwald return;
15593deb3ec6SMatthias Ringwald }
15603deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE) {
15613deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
15623deb3ec6SMatthias Ringwald bnep_send_filter_net_type_response(channel, channel->response_code);
15633deb3ec6SMatthias Ringwald return;
15643deb3ec6SMatthias Ringwald }
15653deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET) {
15663deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
15673deb3ec6SMatthias Ringwald if ((channel->multicast_filter_out_count > 0) && (channel->multicast_filter_out != NULL)) {
15683deb3ec6SMatthias Ringwald bnep_send_filter_multi_addr_set(channel, channel->multicast_filter_out, channel->multicast_filter_out_count);
15693deb3ec6SMatthias Ringwald channel->multicast_filter_out_count = 0;
15703deb3ec6SMatthias Ringwald channel->multicast_filter_out = NULL;
15713deb3ec6SMatthias Ringwald }
15723deb3ec6SMatthias Ringwald return;
15733deb3ec6SMatthias Ringwald }
15743deb3ec6SMatthias Ringwald if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE) {
15753deb3ec6SMatthias Ringwald bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
15763deb3ec6SMatthias Ringwald bnep_send_filter_multi_addr_response(channel, channel->response_code);
15773deb3ec6SMatthias Ringwald return;
15783deb3ec6SMatthias Ringwald }
15793deb3ec6SMatthias Ringwald
15803deb3ec6SMatthias Ringwald /* If the event was not yet handled, notify the application layer */
15811ed1a3bdSMatthias Ringwald if (channel->waiting_for_can_send_now){
15821ed1a3bdSMatthias Ringwald channel->waiting_for_can_send_now = 0;
15833deb3ec6SMatthias Ringwald bnep_emit_ready_to_send(channel);
15843deb3ec6SMatthias Ringwald }
15853deb3ec6SMatthias Ringwald }
15861ed1a3bdSMatthias Ringwald }
15873deb3ec6SMatthias Ringwald
bnep_handle_can_send_now(uint16_t l2cap_cid)15884e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t l2cap_cid){
1589665d90f2SMatthias Ringwald btstack_linked_item_t *it;
1590665d90f2SMatthias Ringwald btstack_linked_item_t *next;
15913deb3ec6SMatthias Ringwald
1592665d90f2SMatthias Ringwald for (it = (btstack_linked_item_t *) bnep_channels; it ; it = next){
15933deb3ec6SMatthias Ringwald next = it->next; // be prepared for removal of channel in state machine
15943deb3ec6SMatthias Ringwald bnep_channel_t * channel = ((bnep_channel_t *) it);
15954e366553SMatthias Ringwald if (channel->l2cap_cid != l2cap_cid) continue;
15964e366553SMatthias Ringwald //
15973deb3ec6SMatthias Ringwald bnep_channel_event_t channel_event = { BNEP_CH_EVT_READY_TO_SEND };
15983deb3ec6SMatthias Ringwald bnep_channel_state_machine(channel, &channel_event);
15994e366553SMatthias Ringwald
16004e366553SMatthias Ringwald if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
16014e366553SMatthias Ringwald l2cap_request_can_send_now_event(channel->l2cap_cid);
16024e366553SMatthias Ringwald return;
16033deb3ec6SMatthias Ringwald }
16043deb3ec6SMatthias Ringwald }
16054e366553SMatthias Ringwald }
16064e366553SMatthias Ringwald
16073deb3ec6SMatthias Ringwald
16083deb3ec6SMatthias Ringwald /* BNEP BTStack API */
bnep_init(void)16093deb3ec6SMatthias Ringwald void bnep_init(void)
16103deb3ec6SMatthias Ringwald {
161178315a58SMatthias Ringwald bnep_security_level = gap_get_security_level();
16123deb3ec6SMatthias Ringwald }
16133deb3ec6SMatthias Ringwald
bnep_deinit(void)161451e0db05SMatthias Ringwald void bnep_deinit(void){
1615ed47fef4SMatthias Ringwald bnep_services = NULL;
1616ed47fef4SMatthias Ringwald bnep_channels = NULL;
1617ed47fef4SMatthias Ringwald bnep_security_level = 0;
161851e0db05SMatthias Ringwald }
161951e0db05SMatthias Ringwald
bnep_set_required_security_level(gap_security_level_t security_level)16203deb3ec6SMatthias Ringwald void bnep_set_required_security_level(gap_security_level_t security_level)
16213deb3ec6SMatthias Ringwald {
16223deb3ec6SMatthias Ringwald bnep_security_level = security_level;
16233deb3ec6SMatthias Ringwald }
16243deb3ec6SMatthias Ringwald
bnep_connect(btstack_packet_handler_t packet_handler,bd_addr_t addr,uint16_t l2cap_psm,uint16_t uuid_src,uint16_t uuid_dest)16250c249750SMatthias 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)
16263deb3ec6SMatthias Ringwald {
16273deb3ec6SMatthias Ringwald bnep_channel_t *channel;
16283deb3ec6SMatthias Ringwald log_info("BNEP_CONNECT addr %s", bd_addr_to_str(addr));
16293deb3ec6SMatthias Ringwald
16303deb3ec6SMatthias Ringwald channel = bnep_channel_create_for_addr(addr);
16313deb3ec6SMatthias Ringwald if (channel == NULL) {
16323deb3ec6SMatthias Ringwald return -1;
16333deb3ec6SMatthias Ringwald }
16343deb3ec6SMatthias Ringwald
16353deb3ec6SMatthias Ringwald channel->uuid_source = uuid_src;
16363deb3ec6SMatthias Ringwald channel->uuid_dest = uuid_dest;
16370c249750SMatthias Ringwald channel->packet_handler = packet_handler;
16383deb3ec6SMatthias Ringwald
163990a28bdeSMatthias Ringwald uint8_t status = l2cap_create_channel(bnep_packet_handler, addr, l2cap_psm, l2cap_max_mtu(), NULL);
164090a28bdeSMatthias Ringwald if (status){
164190a28bdeSMatthias Ringwald return -1;
164290a28bdeSMatthias Ringwald }
16433deb3ec6SMatthias Ringwald return 0;
16443deb3ec6SMatthias Ringwald }
16453deb3ec6SMatthias Ringwald
bnep_disconnect(bd_addr_t addr)16463deb3ec6SMatthias Ringwald void bnep_disconnect(bd_addr_t addr)
16473deb3ec6SMatthias Ringwald {
16483deb3ec6SMatthias Ringwald bnep_channel_t *channel;
16493deb3ec6SMatthias Ringwald log_info("BNEP_DISCONNECT");
16503deb3ec6SMatthias Ringwald
16513deb3ec6SMatthias Ringwald channel = bnep_channel_for_addr(addr);
16523deb3ec6SMatthias Ringwald
16533deb3ec6SMatthias Ringwald bnep_channel_finalize(channel);
16543deb3ec6SMatthias Ringwald }
16553deb3ec6SMatthias Ringwald
16563deb3ec6SMatthias Ringwald
bnep_register_service(btstack_packet_handler_t packet_handler,uint16_t service_uuid,uint16_t max_frame_size)16570c249750SMatthias Ringwald uint8_t bnep_register_service(btstack_packet_handler_t packet_handler, uint16_t service_uuid, uint16_t max_frame_size)
16583deb3ec6SMatthias Ringwald {
16593deb3ec6SMatthias Ringwald log_info("BNEP_REGISTER_SERVICE mtu %d", max_frame_size);
16603deb3ec6SMatthias Ringwald
16613deb3ec6SMatthias Ringwald /* Check if we already registered a service */
16623deb3ec6SMatthias Ringwald bnep_service_t * service = bnep_service_for_uuid(service_uuid);
16633deb3ec6SMatthias Ringwald if (service) {
16640cc6429eSMatthias Ringwald return BNEP_SERVICE_ALREADY_REGISTERED;
16653deb3ec6SMatthias Ringwald }
16663deb3ec6SMatthias Ringwald
16673deb3ec6SMatthias Ringwald /* Only alow one the three service types: PANU, NAP, GN */
1668235946f1SMatthias Ringwald if ((service_uuid != BLUETOOTH_SERVICE_CLASS_PANU) &&
1669235946f1SMatthias Ringwald (service_uuid != BLUETOOTH_SERVICE_CLASS_NAP) &&
1670235946f1SMatthias Ringwald (service_uuid != BLUETOOTH_SERVICE_CLASS_GN)) {
16713deb3ec6SMatthias Ringwald log_info("BNEP_REGISTER_SERVICE: Invalid service UUID: %04x", service_uuid);
16720cc6429eSMatthias Ringwald return BNEP_SERVICE_ALREADY_REGISTERED; // TODO: define own error
16733deb3ec6SMatthias Ringwald }
16743deb3ec6SMatthias Ringwald
16753deb3ec6SMatthias Ringwald /* Allocate service memory */
16763deb3ec6SMatthias Ringwald service = (bnep_service_t*) btstack_memory_bnep_service_get();
16773deb3ec6SMatthias Ringwald if (!service) {
16780cc6429eSMatthias Ringwald return BTSTACK_MEMORY_ALLOC_FAILED;
16793deb3ec6SMatthias Ringwald }
16803deb3ec6SMatthias Ringwald
16813deb3ec6SMatthias Ringwald /* register with l2cap if not registered before, max MTU */
168284e3541eSMilanka Ringwald l2cap_register_service(bnep_packet_handler, BLUETOOTH_PSM_BNEP, 0xffff, bnep_security_level);
16833deb3ec6SMatthias Ringwald
16843deb3ec6SMatthias Ringwald /* Setup the service struct */
16853deb3ec6SMatthias Ringwald service->max_frame_size = max_frame_size;
16863deb3ec6SMatthias Ringwald service->service_uuid = service_uuid;
16870c249750SMatthias Ringwald service->packet_handler = packet_handler;
16880c249750SMatthias Ringwald
16893deb3ec6SMatthias Ringwald
16903deb3ec6SMatthias Ringwald /* Add to services list */
1691665d90f2SMatthias Ringwald btstack_linked_list_add(&bnep_services, (btstack_linked_item_t *) service);
16923deb3ec6SMatthias Ringwald
16930cc6429eSMatthias Ringwald return 0;
16943deb3ec6SMatthias Ringwald }
16953deb3ec6SMatthias Ringwald
bnep_unregister_service(uint16_t service_uuid)16963deb3ec6SMatthias Ringwald void bnep_unregister_service(uint16_t service_uuid)
16973deb3ec6SMatthias Ringwald {
16983deb3ec6SMatthias Ringwald log_info("BNEP_UNREGISTER_SERVICE #%04x", service_uuid);
16993deb3ec6SMatthias Ringwald
17003deb3ec6SMatthias Ringwald bnep_service_t *service = bnep_service_for_uuid(service_uuid);
17013deb3ec6SMatthias Ringwald if (!service) {
17023deb3ec6SMatthias Ringwald return;
17033deb3ec6SMatthias Ringwald }
17043deb3ec6SMatthias Ringwald
1705665d90f2SMatthias Ringwald btstack_linked_list_remove(&bnep_services, (btstack_linked_item_t *) service);
17063deb3ec6SMatthias Ringwald btstack_memory_bnep_service_free(service);
17073deb3ec6SMatthias Ringwald service = NULL;
17083deb3ec6SMatthias Ringwald
170984e3541eSMilanka Ringwald l2cap_unregister_service(BLUETOOTH_PSM_BNEP);
17103deb3ec6SMatthias Ringwald }
17113deb3ec6SMatthias Ringwald
1712