xref: /btstack/src/classic/bnep.c (revision 37e1b22048c5dc562e27aa1edc93fa4a6eda5cb4)
13deb3ec6SMatthias Ringwald /*
23deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
33deb3ec6SMatthias Ringwald  *
43deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
53deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
63deb3ec6SMatthias Ringwald  * are met:
73deb3ec6SMatthias Ringwald  *
83deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
93deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
103deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
113deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
123deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
133deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
143deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
153deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
163deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
173deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
183deb3ec6SMatthias Ringwald  *    monetary gain.
193deb3ec6SMatthias Ringwald  *
203deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
213deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
223deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
253deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
263deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
273deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
283deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
293deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
303deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
313deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
323deb3ec6SMatthias Ringwald  *
333deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
343deb3ec6SMatthias Ringwald  * [email protected]
353deb3ec6SMatthias Ringwald  *
363deb3ec6SMatthias Ringwald  */
373deb3ec6SMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "bnep.c"
39ab2c6ae4SMatthias Ringwald 
403deb3ec6SMatthias Ringwald /*
413deb3ec6SMatthias Ringwald  * bnep.c
423deb3ec6SMatthias Ringwald  * Author: Ole Reinhardt <[email protected]>
433deb3ec6SMatthias Ringwald  *
443deb3ec6SMatthias Ringwald  */
453deb3ec6SMatthias Ringwald 
463deb3ec6SMatthias Ringwald #include <stdint.h>
4784e3541eSMilanka Ringwald #include <string.h> // memcpy
483deb3ec6SMatthias Ringwald 
4984e3541eSMilanka Ringwald #include "bluetooth_psm.h"
50235946f1SMatthias Ringwald #include "bluetooth_sdp.h"
5184e3541eSMilanka Ringwald #include "bnep.h"
520e2df43fSMatthias Ringwald #include "btstack_debug.h"
530e2df43fSMatthias Ringwald #include "btstack_event.h"
540e2df43fSMatthias Ringwald #include "btstack_memory.h"
55eb886013SMatthias Ringwald #include "btstack_util.h"
5659c6af15SMatthias Ringwald #include "classic/core.h"
573edc84c5SMatthias Ringwald #include "classic/sdp_util.h"
583deb3ec6SMatthias Ringwald #include "hci.h"
590e2df43fSMatthias Ringwald #include "hci_cmd.h"
603deb3ec6SMatthias Ringwald #include "hci_dump.h"
613deb3ec6SMatthias Ringwald #include "l2cap.h"
623deb3ec6SMatthias Ringwald 
639951ad9cSMatthias Ringwald #define BNEP_EXT_FLAG                                   0x80
649951ad9cSMatthias Ringwald #define BNEP_TYPE_MASK                                  0x7F
659951ad9cSMatthias Ringwald #define BNEP_TYPE(header)                               ((header) & BNEP_TYPE_MASK)
669951ad9cSMatthias Ringwald #define BNEP_HEADER_HAS_EXT(x)                          (((x) & BNEP_EXT_FLAG) == BNEP_EXT_FLAG)
679951ad9cSMatthias Ringwald 
689951ad9cSMatthias Ringwald /* BNEP packet types */
699951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_GENERAL_ETHERNET                  0x00
709951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_CONTROL                           0x01
719951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET               0x02
729951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY   0x03
739951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY     0x04
749951ad9cSMatthias Ringwald 
759951ad9cSMatthias Ringwald /* BNEP control types */
769951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD        0x00
779951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST      0x01
789951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE     0x02
799951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET           0x03
809951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE      0x04
819951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET         0x05
829951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE    0x06
839951ad9cSMatthias Ringwald 
849951ad9cSMatthias Ringwald /* BNEP extension header types */
859951ad9cSMatthias Ringwald #define BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL          0x00
869951ad9cSMatthias Ringwald 
879951ad9cSMatthias Ringwald /* BNEP setup response codes */
889951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_SUCCESS                         0x0000
899951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_DEST_UUID               0x0001
909951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_SOURCE_UUID             0x0002
919951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_SERVICE_UUID_SIZE       0x0003
929951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_CONNECTION_NOT_ALLOWED          0x0004
939951ad9cSMatthias Ringwald 
949951ad9cSMatthias Ringwald /* BNEP filter response codes */
959951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_SUCCESS                        0x0000
969951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_UNSUPPORTED_REQUEST            0x0001
979951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_INVALID_RANGE              0x0002
989951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS           0x0003
999951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_SECURITY                   0x0004
1009951ad9cSMatthias Ringwald 
1013deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_TIMEOUT_MS 10000
1023deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_MAX_RETRIES 1
1033deb3ec6SMatthias Ringwald 
1048f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_services = NULL;
1058f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_channels = NULL;
1063deb3ec6SMatthias Ringwald 
1073deb3ec6SMatthias Ringwald static gap_security_level_t bnep_security_level;
1083deb3ec6SMatthias Ringwald 
1093deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid);
1103deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel);
1113deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout);
1123deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event);
1134e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t cid);
114*37e1b220SMatthias Ringwald 
115*37e1b220SMatthias Ringwald static void bnep_emit_open_channel_complete(bnep_channel_t *channel, uint8_t status, uint8_t setup_connection_response)
1163deb3ec6SMatthias Ringwald {
1170c249750SMatthias 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);
1180c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1190c249750SMatthias Ringwald 
120*37e1b220SMatthias Ringwald     uint8_t event[3 + sizeof(bd_addr_t) + 4 * sizeof(uint16_t) + 3];
121423c667cSMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_OPENED;
1223deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
1233deb3ec6SMatthias Ringwald     event[2] = status;
124423c667cSMatthias Ringwald     little_endian_store_16(event, 3, channel->l2cap_cid);
125423c667cSMatthias Ringwald     little_endian_store_16(event, 5, channel->uuid_source);
126423c667cSMatthias Ringwald     little_endian_store_16(event, 7, channel->uuid_dest);
127423c667cSMatthias Ringwald     little_endian_store_16(event, 9, channel->max_frame_size);
128fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[11]);
12932b46fecSMatthias Ringwald     little_endian_store_16(event, 17, channel->con_handle);
130*37e1b220SMatthias Ringwald     event[19] = setup_connection_response;
1319da9850bSMatthias Ringwald     hci_dump_btstack_event( event, sizeof(event));
1320c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1333deb3ec6SMatthias Ringwald }
1343deb3ec6SMatthias Ringwald 
1353deb3ec6SMatthias Ringwald static void bnep_emit_channel_timeout(bnep_channel_t *channel)
1363deb3ec6SMatthias Ringwald {
1370c249750SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_TIMEOUT bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler);
1380c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1390c249750SMatthias Ringwald 
140423c667cSMatthias Ringwald     uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t) + sizeof(uint8_t)];
1413deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_TIMEOUT;
1423deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
143423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
144423c667cSMatthias Ringwald     little_endian_store_16(event, 4, channel->uuid_source);
145423c667cSMatthias Ringwald     little_endian_store_16(event, 6, channel->uuid_dest);
146fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[8]);
147423c667cSMatthias Ringwald     event[14] = channel->state;
1489da9850bSMatthias Ringwald     hci_dump_btstack_event( event, sizeof(event));
1490c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1503deb3ec6SMatthias Ringwald }
1513deb3ec6SMatthias Ringwald 
1523deb3ec6SMatthias Ringwald static void bnep_emit_channel_closed(bnep_channel_t *channel)
1533deb3ec6SMatthias Ringwald {
1540c249750SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_CLOSED bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler);
1550c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1560c249750SMatthias Ringwald 
157423c667cSMatthias Ringwald     uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t)];
1583deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_CLOSED;
1593deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
160423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
161423c667cSMatthias Ringwald     little_endian_store_16(event, 4, channel->uuid_source);
162423c667cSMatthias Ringwald     little_endian_store_16(event, 6, channel->uuid_dest);
163fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[8]);
1649da9850bSMatthias Ringwald     hci_dump_btstack_event( event, sizeof(event));
1650c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1663deb3ec6SMatthias Ringwald }
1673deb3ec6SMatthias Ringwald 
1683deb3ec6SMatthias Ringwald static void bnep_emit_ready_to_send(bnep_channel_t *channel)
1693deb3ec6SMatthias Ringwald {
1700c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1710c249750SMatthias Ringwald 
172423c667cSMatthias Ringwald     uint8_t event[4];
1732d4c8c04SMatthias Ringwald     event[0] = BNEP_EVENT_CAN_SEND_NOW;
1743deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
175423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
1769da9850bSMatthias Ringwald     hci_dump_btstack_event( event, sizeof(event));
1770c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1783deb3ec6SMatthias Ringwald }
1793deb3ec6SMatthias Ringwald 
1803deb3ec6SMatthias Ringwald /* Send BNEP connection request */
1813deb3ec6SMatthias Ringwald static int bnep_send_command_not_understood(bnep_channel_t *channel, uint8_t control_type)
1823deb3ec6SMatthias Ringwald {
1833deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
1843deb3ec6SMatthias Ringwald     uint16_t pos = 0;
1853deb3ec6SMatthias Ringwald     int      err = 0;
1863deb3ec6SMatthias Ringwald 
1873deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
1883deb3ec6SMatthias Ringwald         return -1; // TODO
1893deb3ec6SMatthias Ringwald     }
1903deb3ec6SMatthias Ringwald 
1913deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
1923deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
1933deb3ec6SMatthias Ringwald 
1943deb3ec6SMatthias Ringwald     /* Setup control packet type */
1953deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
1963deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD;
1973deb3ec6SMatthias Ringwald 
1983deb3ec6SMatthias Ringwald     /* Add not understood control type */
1993deb3ec6SMatthias Ringwald     bnep_out_buffer[pos++] = control_type;
2003deb3ec6SMatthias Ringwald 
2013deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2023deb3ec6SMatthias Ringwald 
2033deb3ec6SMatthias Ringwald     if (err) {
2043deb3ec6SMatthias Ringwald         // TODO: Log error
2053deb3ec6SMatthias Ringwald     }
2063deb3ec6SMatthias Ringwald     return err;
2073deb3ec6SMatthias Ringwald }
2083deb3ec6SMatthias Ringwald 
2093deb3ec6SMatthias Ringwald 
2103deb3ec6SMatthias Ringwald /* Send BNEP connection request */
2113deb3ec6SMatthias Ringwald static int bnep_send_connection_request(bnep_channel_t *channel, uint16_t uuid_source, uint16_t uuid_dest)
2123deb3ec6SMatthias Ringwald {
2133deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2143deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2153deb3ec6SMatthias Ringwald     int      err = 0;
2163deb3ec6SMatthias Ringwald 
2173deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2183deb3ec6SMatthias Ringwald         return -1; // TODO
2193deb3ec6SMatthias Ringwald     }
2203deb3ec6SMatthias Ringwald 
2213deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2223deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2233deb3ec6SMatthias Ringwald 
2243deb3ec6SMatthias Ringwald     /* Setup control packet type */
2253deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2263deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST;
2273deb3ec6SMatthias Ringwald 
2283deb3ec6SMatthias Ringwald     /* Add UUID Size */
2293deb3ec6SMatthias Ringwald     bnep_out_buffer[pos++] = 2;
2303deb3ec6SMatthias Ringwald 
2313deb3ec6SMatthias Ringwald     /* Add dest and source UUID */
232f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, uuid_dest);
2333deb3ec6SMatthias Ringwald     pos += 2;
2343deb3ec6SMatthias Ringwald 
235f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, uuid_source);
2363deb3ec6SMatthias Ringwald     pos += 2;
2373deb3ec6SMatthias Ringwald 
2383deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2393deb3ec6SMatthias Ringwald 
2403deb3ec6SMatthias Ringwald     if (err) {
2413deb3ec6SMatthias Ringwald         // TODO: Log error
2423deb3ec6SMatthias Ringwald     }
2433deb3ec6SMatthias Ringwald     return err;
2443deb3ec6SMatthias Ringwald }
2453deb3ec6SMatthias Ringwald 
2463deb3ec6SMatthias Ringwald /* Send BNEP connection response */
2473deb3ec6SMatthias Ringwald static int bnep_send_connection_response(bnep_channel_t *channel, uint16_t response_code)
2483deb3ec6SMatthias Ringwald {
2493deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2503deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2513deb3ec6SMatthias Ringwald     int      err = 0;
2523deb3ec6SMatthias Ringwald 
2533deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2543deb3ec6SMatthias Ringwald         return -1; // TODO
2553deb3ec6SMatthias Ringwald     }
2563deb3ec6SMatthias Ringwald 
2573deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2583deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2593deb3ec6SMatthias Ringwald 
2603deb3ec6SMatthias Ringwald     /* Setup control packet type */
2613deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2623deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE;
2633deb3ec6SMatthias Ringwald 
2643deb3ec6SMatthias Ringwald     /* Add response code */
265f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
2663deb3ec6SMatthias Ringwald     pos += 2;
2673deb3ec6SMatthias Ringwald 
2683deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2693deb3ec6SMatthias Ringwald 
2703deb3ec6SMatthias Ringwald     if (err) {
2713deb3ec6SMatthias Ringwald         // TODO: Log error
2723deb3ec6SMatthias Ringwald     }
2733deb3ec6SMatthias Ringwald     return err;
2743deb3ec6SMatthias Ringwald }
2753deb3ec6SMatthias Ringwald 
2763deb3ec6SMatthias Ringwald /* Send BNEP filter net type set message */
2773deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_set(bnep_channel_t *channel, bnep_net_filter_t *filter, uint16_t len)
2783deb3ec6SMatthias Ringwald {
2793deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2803deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2813deb3ec6SMatthias Ringwald     int      err = 0;
2823deb3ec6SMatthias Ringwald     int      i;
2833deb3ec6SMatthias Ringwald 
2843deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2853deb3ec6SMatthias Ringwald         return -1;
2863deb3ec6SMatthias Ringwald     }
2873deb3ec6SMatthias Ringwald 
2883deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2893deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2903deb3ec6SMatthias Ringwald 
2913deb3ec6SMatthias Ringwald     /* Setup control packet type */
2923deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2933deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET;
2943deb3ec6SMatthias Ringwald 
295f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, len * 2 * 2);
2963deb3ec6SMatthias Ringwald     pos += 2;
2973deb3ec6SMatthias Ringwald 
2983deb3ec6SMatthias Ringwald     for (i = 0; i < len; i ++) {
299f8fbdce0SMatthias Ringwald         big_endian_store_16(bnep_out_buffer, pos, filter[i].range_start);
3003deb3ec6SMatthias Ringwald         pos += 2;
301f8fbdce0SMatthias Ringwald         big_endian_store_16(bnep_out_buffer, pos, filter[i].range_end);
3023deb3ec6SMatthias Ringwald         pos += 2;
3033deb3ec6SMatthias Ringwald     }
3043deb3ec6SMatthias Ringwald 
3053deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
3063deb3ec6SMatthias Ringwald 
3073deb3ec6SMatthias Ringwald     if (err) {
3083deb3ec6SMatthias Ringwald         // TODO: Log error
3093deb3ec6SMatthias Ringwald     }
3103deb3ec6SMatthias Ringwald     return err;
3113deb3ec6SMatthias Ringwald }
3123deb3ec6SMatthias Ringwald 
3133deb3ec6SMatthias Ringwald /* Send BNEP filter net type response message */
3143deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_response(bnep_channel_t *channel, uint16_t response_code)
3153deb3ec6SMatthias Ringwald {
3163deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
3173deb3ec6SMatthias Ringwald     uint16_t pos = 0;
3183deb3ec6SMatthias Ringwald     int      err = 0;
3193deb3ec6SMatthias Ringwald 
3203deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3213deb3ec6SMatthias Ringwald         return -1;
3223deb3ec6SMatthias Ringwald     }
3233deb3ec6SMatthias Ringwald 
3243deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
3253deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
3263deb3ec6SMatthias Ringwald 
3273deb3ec6SMatthias Ringwald     /* Setup control packet type */
3283deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3293deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE;
3303deb3ec6SMatthias Ringwald 
3313deb3ec6SMatthias Ringwald     /* Add response code */
332f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
3333deb3ec6SMatthias Ringwald     pos += 2;
3343deb3ec6SMatthias Ringwald 
3353deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
3363deb3ec6SMatthias Ringwald 
3373deb3ec6SMatthias Ringwald     if (err) {
3383deb3ec6SMatthias Ringwald         // TODO: Log error
3393deb3ec6SMatthias Ringwald     }
3403deb3ec6SMatthias Ringwald     return err;
3413deb3ec6SMatthias Ringwald }
3423deb3ec6SMatthias Ringwald 
3433deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address set message */
3443deb3ec6SMatthias Ringwald 
3453deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_set(bnep_channel_t *channel, bnep_multi_filter_t *filter, uint16_t len)
3463deb3ec6SMatthias Ringwald {
3473deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
3483deb3ec6SMatthias Ringwald     uint16_t pos = 0;
3493deb3ec6SMatthias Ringwald     int      err = 0;
3503deb3ec6SMatthias Ringwald     int      i;
3513deb3ec6SMatthias Ringwald 
3523deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3533deb3ec6SMatthias Ringwald         return -1;
3543deb3ec6SMatthias Ringwald     }
3553deb3ec6SMatthias Ringwald 
3563deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
3573deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
3583deb3ec6SMatthias Ringwald 
3593deb3ec6SMatthias Ringwald     /* Setup control packet type */
3603deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3613deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET;
3623deb3ec6SMatthias Ringwald 
363f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, len * 2 * ETHER_ADDR_LEN);
3643deb3ec6SMatthias Ringwald     pos += 2;
3653deb3ec6SMatthias Ringwald 
3663deb3ec6SMatthias Ringwald     for (i = 0; i < len; i ++) {
367058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_start);
3683deb3ec6SMatthias Ringwald         pos += ETHER_ADDR_LEN;
369058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_end);
3703deb3ec6SMatthias Ringwald         pos += ETHER_ADDR_LEN;
3713deb3ec6SMatthias Ringwald     }
3723deb3ec6SMatthias Ringwald 
3733deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
3743deb3ec6SMatthias Ringwald 
3753deb3ec6SMatthias Ringwald     if (err) {
3763deb3ec6SMatthias Ringwald         // TODO: Log error
3773deb3ec6SMatthias Ringwald     }
3783deb3ec6SMatthias Ringwald     return err;
3793deb3ec6SMatthias Ringwald }
3803deb3ec6SMatthias Ringwald 
3813deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address response message */
3823deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_response(bnep_channel_t *channel, uint16_t response_code)
3833deb3ec6SMatthias Ringwald {
3843deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
3853deb3ec6SMatthias Ringwald     uint16_t pos = 0;
3863deb3ec6SMatthias Ringwald     int      err = 0;
3873deb3ec6SMatthias Ringwald 
3883deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3893deb3ec6SMatthias Ringwald         return -1;
3903deb3ec6SMatthias Ringwald     }
3913deb3ec6SMatthias Ringwald 
3923deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
3933deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
3943deb3ec6SMatthias Ringwald 
3953deb3ec6SMatthias Ringwald     /* Setup control packet type */
3963deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3973deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE;
3983deb3ec6SMatthias Ringwald 
3993deb3ec6SMatthias Ringwald     /* Add response code */
400f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
4013deb3ec6SMatthias Ringwald     pos += 2;
4023deb3ec6SMatthias Ringwald 
4033deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
4043deb3ec6SMatthias Ringwald 
4053deb3ec6SMatthias Ringwald     if (err) {
4063deb3ec6SMatthias Ringwald         // TODO: Log error
4073deb3ec6SMatthias Ringwald     }
4083deb3ec6SMatthias Ringwald     return err;
4093deb3ec6SMatthias Ringwald }
4103deb3ec6SMatthias Ringwald 
4113deb3ec6SMatthias Ringwald int bnep_can_send_packet_now(uint16_t bnep_cid)
4123deb3ec6SMatthias Ringwald {
4133deb3ec6SMatthias Ringwald     bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
4143deb3ec6SMatthias Ringwald 
4153deb3ec6SMatthias Ringwald     if (!channel){
4163deb3ec6SMatthias Ringwald         log_error("bnep_can_send_packet_now cid 0x%02x doesn't exist!", bnep_cid);
4173deb3ec6SMatthias Ringwald         return 0;
4183deb3ec6SMatthias Ringwald     }
4193deb3ec6SMatthias Ringwald 
4200b9d7e78SMatthias Ringwald     return l2cap_can_send_packet_now(channel->l2cap_cid);
4211ed1a3bdSMatthias Ringwald }
4221ed1a3bdSMatthias Ringwald 
4231ed1a3bdSMatthias Ringwald void bnep_request_can_send_now_event(uint16_t bnep_cid)
4241ed1a3bdSMatthias Ringwald {
4251ed1a3bdSMatthias Ringwald     bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
4261ed1a3bdSMatthias Ringwald 
4271ed1a3bdSMatthias Ringwald     if (!channel){
4281ed1a3bdSMatthias Ringwald         log_error("bnep_request_can_send_now_event cid 0x%02x doesn't exist!", bnep_cid);
4291ed1a3bdSMatthias Ringwald         return;
4301ed1a3bdSMatthias Ringwald     }
4311ed1a3bdSMatthias Ringwald 
4321ed1a3bdSMatthias Ringwald     channel->waiting_for_can_send_now = 1;
4331ed1a3bdSMatthias Ringwald     l2cap_request_can_send_now_event(bnep_cid);
4343deb3ec6SMatthias Ringwald }
4353deb3ec6SMatthias Ringwald 
4363deb3ec6SMatthias Ringwald 
4373deb3ec6SMatthias Ringwald static int bnep_filter_protocol(bnep_channel_t *channel, uint16_t network_protocol_type)
4383deb3ec6SMatthias Ringwald {
4393deb3ec6SMatthias Ringwald 	int i;
4403deb3ec6SMatthias Ringwald 
4413deb3ec6SMatthias Ringwald     if (channel->net_filter_count == 0) {
4423deb3ec6SMatthias Ringwald         /* No filter set */
4433deb3ec6SMatthias Ringwald         return 1;
4443deb3ec6SMatthias Ringwald     }
4453deb3ec6SMatthias Ringwald 
4463deb3ec6SMatthias Ringwald     for (i = 0; i < channel->net_filter_count; i ++) {
4473deb3ec6SMatthias Ringwald         if ((network_protocol_type >= channel->net_filter[i].range_start) &&
4483deb3ec6SMatthias Ringwald             (network_protocol_type <= channel->net_filter[i].range_end)) {
4493deb3ec6SMatthias Ringwald             return 1;
4503deb3ec6SMatthias Ringwald         }
4513deb3ec6SMatthias Ringwald     }
4523deb3ec6SMatthias Ringwald 
4533deb3ec6SMatthias Ringwald     return 0;
4543deb3ec6SMatthias Ringwald }
4553deb3ec6SMatthias Ringwald 
4563deb3ec6SMatthias Ringwald static int bnep_filter_multicast(bnep_channel_t *channel, bd_addr_t addr_dest)
4573deb3ec6SMatthias Ringwald {
4583deb3ec6SMatthias Ringwald 	int i;
4593deb3ec6SMatthias Ringwald 
4603deb3ec6SMatthias Ringwald     /* Check if the multicast flag is set int the destination address */
4613deb3ec6SMatthias Ringwald 	if ((addr_dest[0] & 0x01) == 0x00) {
4623deb3ec6SMatthias Ringwald         /* Not a multicast frame, do not apply filtering and send it in any case */
4633deb3ec6SMatthias Ringwald 		return 1;
4643deb3ec6SMatthias Ringwald     }
4653deb3ec6SMatthias Ringwald 
4663deb3ec6SMatthias Ringwald     if (channel->multicast_filter_count == 0) {
4673deb3ec6SMatthias Ringwald         /* No filter set */
4683deb3ec6SMatthias Ringwald         return 1;
4693deb3ec6SMatthias Ringwald     }
4703deb3ec6SMatthias Ringwald 
4713deb3ec6SMatthias Ringwald 	for (i = 0; i < channel->multicast_filter_count; i ++) {
4723deb3ec6SMatthias Ringwald 		if ((memcmp(addr_dest, channel->multicast_filter[i].addr_start, sizeof(bd_addr_t)) >= 0) &&
4733deb3ec6SMatthias Ringwald 		    (memcmp(addr_dest, channel->multicast_filter[i].addr_end, sizeof(bd_addr_t)) <= 0)) {
4743deb3ec6SMatthias Ringwald 			return 1;
4753deb3ec6SMatthias Ringwald         }
4763deb3ec6SMatthias Ringwald 	}
4773deb3ec6SMatthias Ringwald 
4783deb3ec6SMatthias Ringwald 	return 0;
4793deb3ec6SMatthias Ringwald }
4803deb3ec6SMatthias Ringwald 
4813deb3ec6SMatthias Ringwald 
4823deb3ec6SMatthias Ringwald /* Send BNEP ethernet packet */
4833deb3ec6SMatthias Ringwald int bnep_send(uint16_t bnep_cid, uint8_t *packet, uint16_t len)
4843deb3ec6SMatthias Ringwald {
4853deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
4863deb3ec6SMatthias Ringwald     uint8_t        *bnep_out_buffer = NULL;
4873deb3ec6SMatthias Ringwald     uint16_t        pos = 0;
4883deb3ec6SMatthias Ringwald     uint16_t        pos_out = 0;
4893deb3ec6SMatthias Ringwald     uint16_t        payload_len;
4903deb3ec6SMatthias Ringwald     int             err = 0;
4913deb3ec6SMatthias Ringwald     int             has_source;
4923deb3ec6SMatthias Ringwald     int             has_dest;
4933deb3ec6SMatthias Ringwald 
4943deb3ec6SMatthias Ringwald     bd_addr_t       addr_dest;
4953deb3ec6SMatthias Ringwald     bd_addr_t       addr_source;
4963deb3ec6SMatthias Ringwald     uint16_t        network_protocol_type;
4973deb3ec6SMatthias Ringwald 
4983deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
4993deb3ec6SMatthias Ringwald     if (channel == NULL) {
5003deb3ec6SMatthias Ringwald         log_error("bnep_send cid 0x%02x doesn't exist!", bnep_cid);
5013deb3ec6SMatthias Ringwald         return 1;
5023deb3ec6SMatthias Ringwald     }
5033deb3ec6SMatthias Ringwald 
5043deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
5053deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
5063deb3ec6SMatthias Ringwald     }
5073deb3ec6SMatthias Ringwald 
5083deb3ec6SMatthias Ringwald     /* Check for free ACL buffers */
5093deb3ec6SMatthias Ringwald     if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
5103deb3ec6SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
5113deb3ec6SMatthias Ringwald     }
5123deb3ec6SMatthias Ringwald 
5133deb3ec6SMatthias Ringwald     /* Extract destination and source address from the ethernet packet */
5143deb3ec6SMatthias Ringwald     pos = 0;
515058e3d6bSMatthias Ringwald     bd_addr_copy(addr_dest, &packet[pos]);
5163deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
517058e3d6bSMatthias Ringwald     bd_addr_copy(addr_source, &packet[pos]);
5183deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
519f8fbdce0SMatthias Ringwald     network_protocol_type = big_endian_read_16(packet, pos);
5203deb3ec6SMatthias Ringwald     pos += sizeof(uint16_t);
5213deb3ec6SMatthias Ringwald 
5223deb3ec6SMatthias Ringwald     payload_len = len - pos;
5233deb3ec6SMatthias Ringwald 
5243deb3ec6SMatthias Ringwald 	if (network_protocol_type == ETHERTYPE_VLAN) {	/* IEEE 802.1Q tag header */
5253deb3ec6SMatthias Ringwald 		if (payload_len < 4) {
5263deb3ec6SMatthias Ringwald             /* Omit this packet */
5273deb3ec6SMatthias Ringwald 			return 0;
5283deb3ec6SMatthias Ringwald         }
5293deb3ec6SMatthias Ringwald         /* The "real" network protocol type is 4 bytes ahead in a VLAN packet */
530f8fbdce0SMatthias Ringwald 		network_protocol_type = big_endian_read_16(packet, pos + 2);
5313deb3ec6SMatthias Ringwald 	}
5323deb3ec6SMatthias Ringwald 
5333deb3ec6SMatthias Ringwald     /* Check network protocol and multicast filters before sending */
5343deb3ec6SMatthias Ringwald     if (!bnep_filter_protocol(channel, network_protocol_type) ||
5353deb3ec6SMatthias Ringwald         !bnep_filter_multicast(channel, addr_dest)) {
5363deb3ec6SMatthias Ringwald         /* Packet did not pass filter... */
5373deb3ec6SMatthias Ringwald         if ((network_protocol_type == ETHERTYPE_VLAN) &&
5383deb3ec6SMatthias Ringwald             (payload_len >= 4)) {
5393deb3ec6SMatthias Ringwald             /* The packet has been tagged as a with IEE 802.1Q tag and has been filtered out.
5403deb3ec6SMatthias Ringwald                According to the spec the IEE802.1Q tag header shall be sended without ethernet payload.
5413deb3ec6SMatthias Ringwald                So limit the payload_len to 4.
5423deb3ec6SMatthias Ringwald              */
5433deb3ec6SMatthias Ringwald             payload_len = 4;
5443deb3ec6SMatthias Ringwald         } else {
5453deb3ec6SMatthias Ringwald             /* Packet is not tagged with IEE802.1Q header and was filtered out. Omit this packet */
5463deb3ec6SMatthias Ringwald             return 0;
5473deb3ec6SMatthias Ringwald         }
5483deb3ec6SMatthias Ringwald     }
5493deb3ec6SMatthias Ringwald 
5503deb3ec6SMatthias Ringwald     /* Reserve l2cap packet buffer */
5513deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
5523deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
5533deb3ec6SMatthias Ringwald 
5543deb3ec6SMatthias Ringwald     /* Check if source address is the same as our local address and if the
5553deb3ec6SMatthias Ringwald        destination address is the same as the remote addr. Maybe we can use
5563deb3ec6SMatthias Ringwald        the compressed data format
5573deb3ec6SMatthias Ringwald      */
5583deb3ec6SMatthias Ringwald     has_source = (memcmp(addr_source, channel->local_addr, ETHER_ADDR_LEN) != 0);
5593deb3ec6SMatthias Ringwald     has_dest = (memcmp(addr_dest, channel->remote_addr, ETHER_ADDR_LEN) != 0);
5603deb3ec6SMatthias Ringwald 
5613deb3ec6SMatthias Ringwald     /* Check for MTU limits */
5623deb3ec6SMatthias Ringwald     if (payload_len > channel->max_frame_size) {
5633deb3ec6SMatthias Ringwald         log_error("bnep_send: Max frame size (%d) exceeded: %d", channel->max_frame_size, payload_len);
5643deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
5653deb3ec6SMatthias Ringwald     }
5663deb3ec6SMatthias Ringwald 
5673deb3ec6SMatthias Ringwald     /* Fill in the package type depending on the given source and destination address */
5683deb3ec6SMatthias Ringwald     if (has_source && has_dest) {
5693deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_GENERAL_ETHERNET;
5703deb3ec6SMatthias Ringwald     } else
5713deb3ec6SMatthias Ringwald     if (has_source && !has_dest) {
5723deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY;
5733deb3ec6SMatthias Ringwald     } else
5743deb3ec6SMatthias Ringwald     if (!has_source && has_dest) {
5753deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY;
5763deb3ec6SMatthias Ringwald     } else {
5773deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET;
5783deb3ec6SMatthias Ringwald     }
5793deb3ec6SMatthias Ringwald 
5803deb3ec6SMatthias Ringwald     /* Add the destination address if needed */
5813deb3ec6SMatthias Ringwald     if (has_dest) {
582058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos_out, addr_dest);
5833deb3ec6SMatthias Ringwald         pos_out += sizeof(bd_addr_t);
5843deb3ec6SMatthias Ringwald     }
5853deb3ec6SMatthias Ringwald 
5863deb3ec6SMatthias Ringwald     /* Add the source address if needed */
5873deb3ec6SMatthias Ringwald     if (has_source) {
588058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos_out, addr_source);
5893deb3ec6SMatthias Ringwald         pos_out += sizeof(bd_addr_t);
5903deb3ec6SMatthias Ringwald     }
5913deb3ec6SMatthias Ringwald 
5923deb3ec6SMatthias Ringwald     /* Add protocol type */
593f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos_out, network_protocol_type);
5943deb3ec6SMatthias Ringwald     pos_out += 2;
5953deb3ec6SMatthias Ringwald 
5963deb3ec6SMatthias Ringwald     /* TODO: Add extension headers, if we may support them at a later stage */
5973deb3ec6SMatthias Ringwald     /* Add the payload and then send out the package */
5986535961aSMatthias Ringwald     (void)memcpy(bnep_out_buffer + pos_out, packet + pos, payload_len);
5993deb3ec6SMatthias Ringwald     pos_out += payload_len;
6003deb3ec6SMatthias Ringwald 
6013deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos_out);
6023deb3ec6SMatthias Ringwald 
6033deb3ec6SMatthias Ringwald     if (err) {
6043deb3ec6SMatthias Ringwald         log_error("bnep_send: error %d", err);
6053deb3ec6SMatthias Ringwald     }
6063deb3ec6SMatthias Ringwald     return err;
6073deb3ec6SMatthias Ringwald }
6083deb3ec6SMatthias Ringwald 
6093deb3ec6SMatthias Ringwald 
6103deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
6113deb3ec6SMatthias Ringwald int bnep_set_net_type_filter(uint16_t bnep_cid, bnep_net_filter_t *filter, uint16_t len)
6123deb3ec6SMatthias Ringwald {
6133deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
6143deb3ec6SMatthias Ringwald 
6153deb3ec6SMatthias Ringwald     if (filter == NULL) {
6163deb3ec6SMatthias Ringwald         return -1;
6173deb3ec6SMatthias Ringwald     }
6183deb3ec6SMatthias Ringwald 
6193deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
6203deb3ec6SMatthias Ringwald     if (channel == NULL) {
6213deb3ec6SMatthias Ringwald         log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
6223deb3ec6SMatthias Ringwald         return 1;
6233deb3ec6SMatthias Ringwald     }
6243deb3ec6SMatthias Ringwald 
6253deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
6263deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
6273deb3ec6SMatthias Ringwald     }
6283deb3ec6SMatthias Ringwald 
6293deb3ec6SMatthias Ringwald     if (len > MAX_BNEP_NETFILTER_OUT) {
6303deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
6313deb3ec6SMatthias Ringwald     }
6323deb3ec6SMatthias Ringwald 
6333deb3ec6SMatthias Ringwald     channel->net_filter_out = filter;
6343deb3ec6SMatthias Ringwald     channel->net_filter_out_count = len;
6353deb3ec6SMatthias Ringwald 
6364e366553SMatthias Ringwald     /* Set flag to send out the network protocol type filter set request */
6373deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
6384e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
6393deb3ec6SMatthias Ringwald 
6403deb3ec6SMatthias Ringwald     return 0;
6413deb3ec6SMatthias Ringwald }
6423deb3ec6SMatthias Ringwald 
6433deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
6443deb3ec6SMatthias Ringwald int bnep_set_multicast_filter(uint16_t bnep_cid,  bnep_multi_filter_t *filter, uint16_t len)
6453deb3ec6SMatthias Ringwald {
6463deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
6473deb3ec6SMatthias Ringwald 
6483deb3ec6SMatthias Ringwald     if (filter == NULL) {
6493deb3ec6SMatthias Ringwald         return -1;
6503deb3ec6SMatthias Ringwald     }
6513deb3ec6SMatthias Ringwald 
6523deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
6533deb3ec6SMatthias Ringwald     if (channel == NULL) {
6543deb3ec6SMatthias Ringwald         log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
6553deb3ec6SMatthias Ringwald         return 1;
6563deb3ec6SMatthias Ringwald     }
6573deb3ec6SMatthias Ringwald 
6583deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
6593deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
6603deb3ec6SMatthias Ringwald     }
6613deb3ec6SMatthias Ringwald 
66266b1fcb3SMatthias Ringwald     if (len > MAX_BNEP_MULTICAST_FILTER_OUT) {
6633deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
6643deb3ec6SMatthias Ringwald     }
6653deb3ec6SMatthias Ringwald 
6663deb3ec6SMatthias Ringwald     channel->multicast_filter_out = filter;
6673deb3ec6SMatthias Ringwald     channel->multicast_filter_out_count = len;
6683deb3ec6SMatthias Ringwald 
6694e366553SMatthias Ringwald     /* Set flag to send out the multicast filter set request */
6703deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
6714e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
6723deb3ec6SMatthias Ringwald 
6733deb3ec6SMatthias Ringwald     return 0;
6743deb3ec6SMatthias Ringwald }
6753deb3ec6SMatthias Ringwald 
6763deb3ec6SMatthias Ringwald /* BNEP timeout timer helper function */
677ec820d77SMatthias Ringwald static void bnep_channel_timer_handler(btstack_timer_source_t *timer)
6783deb3ec6SMatthias Ringwald {
67991a977e8SMatthias Ringwald     bnep_channel_t *channel = btstack_run_loop_get_timer_context(timer);
6803deb3ec6SMatthias Ringwald     // retry send setup connection at least one time
6813deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE){
6823deb3ec6SMatthias Ringwald         if (channel->retry_count < BNEP_CONNECTION_MAX_RETRIES){
6833deb3ec6SMatthias Ringwald             channel->retry_count++;
6843deb3ec6SMatthias Ringwald             bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
6853deb3ec6SMatthias Ringwald             bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
6864e366553SMatthias Ringwald             l2cap_request_can_send_now_event(channel->l2cap_cid);
6873deb3ec6SMatthias Ringwald             return;
6883deb3ec6SMatthias Ringwald         }
6893deb3ec6SMatthias Ringwald     }
6903deb3ec6SMatthias Ringwald 
6913deb3ec6SMatthias Ringwald     log_info( "bnep_channel_timeout_handler callback: shutting down connection!");
6923deb3ec6SMatthias Ringwald     bnep_emit_channel_timeout(channel);
6933deb3ec6SMatthias Ringwald     bnep_channel_finalize(channel);
6943deb3ec6SMatthias Ringwald }
6953deb3ec6SMatthias Ringwald 
6963deb3ec6SMatthias Ringwald 
6973deb3ec6SMatthias Ringwald static void bnep_channel_stop_timer(bnep_channel_t *channel)
6983deb3ec6SMatthias Ringwald {
6993deb3ec6SMatthias Ringwald     if (channel->timer_active) {
700528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&channel->timer);
7013deb3ec6SMatthias Ringwald         channel->timer_active = 0;
7023deb3ec6SMatthias Ringwald     }
7033deb3ec6SMatthias Ringwald }
7043deb3ec6SMatthias Ringwald 
7053deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout)
7063deb3ec6SMatthias Ringwald {
7073deb3ec6SMatthias Ringwald     /* Stop any eventually running timeout timer */
7083deb3ec6SMatthias Ringwald     bnep_channel_stop_timer(channel);
7093deb3ec6SMatthias Ringwald 
7103deb3ec6SMatthias Ringwald     /* Start bnep channel timeout check timer */
711528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&channel->timer, timeout);
71291a977e8SMatthias Ringwald     btstack_run_loop_set_timer_handler(&channel->timer, bnep_channel_timer_handler);
71391a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&channel->timer, channel);
714528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&channel->timer);
7153deb3ec6SMatthias Ringwald     channel->timer_active = 1;
7163deb3ec6SMatthias Ringwald }
7173deb3ec6SMatthias Ringwald 
7183deb3ec6SMatthias Ringwald /* BNEP statemachine functions */
7193deb3ec6SMatthias Ringwald 
7203deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
7213deb3ec6SMatthias Ringwald     channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var | event);
7223deb3ec6SMatthias Ringwald }
7233deb3ec6SMatthias Ringwald inline static void bnep_channel_state_remove(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
7243deb3ec6SMatthias Ringwald     channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var & ~event);
7253deb3ec6SMatthias Ringwald }
7263deb3ec6SMatthias Ringwald 
7273deb3ec6SMatthias Ringwald static uint16_t bnep_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
7283deb3ec6SMatthias Ringwald 
7293deb3ec6SMatthias Ringwald     /* Assume a standard BNEP header, containing BNEP Type (1 Byte), dest and
7303deb3ec6SMatthias Ringwald        source address (6 bytes each) and networking protocol type (2 bytes)
7313deb3ec6SMatthias Ringwald      */
7323deb3ec6SMatthias Ringwald     uint16_t max_frame_size = l2cap_mtu - 15; // 15 bytes BNEP header
7333deb3ec6SMatthias Ringwald 
7343deb3ec6SMatthias Ringwald     log_info("bnep_max_frame_size_for_l2cap_mtu:  %u -> %u", l2cap_mtu, max_frame_size);
7353deb3ec6SMatthias Ringwald     return max_frame_size;
7363deb3ec6SMatthias Ringwald }
7373deb3ec6SMatthias Ringwald 
7383deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_create_for_addr(bd_addr_t addr)
7393deb3ec6SMatthias Ringwald {
7403deb3ec6SMatthias Ringwald     /* Allocate new channel structure */
7413deb3ec6SMatthias Ringwald     bnep_channel_t *channel = btstack_memory_bnep_channel_get();
7423deb3ec6SMatthias Ringwald     if (!channel) {
7433deb3ec6SMatthias Ringwald         return NULL;
7443deb3ec6SMatthias Ringwald     }
7453deb3ec6SMatthias Ringwald 
7463deb3ec6SMatthias Ringwald     channel->state = BNEP_CHANNEL_STATE_CLOSED;
7473deb3ec6SMatthias Ringwald     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
74873988a59SMatthias Ringwald     bd_addr_copy(channel->remote_addr, addr);
74915a95bd5SMatthias Ringwald     gap_local_bd_addr(channel->local_addr);
7503deb3ec6SMatthias Ringwald 
7513deb3ec6SMatthias Ringwald     channel->net_filter_count = 0;
7523deb3ec6SMatthias Ringwald     channel->multicast_filter_count = 0;
7533deb3ec6SMatthias Ringwald     channel->retry_count = 0;
7543deb3ec6SMatthias Ringwald 
7553deb3ec6SMatthias Ringwald     /* Finally add it to the channel list */
756665d90f2SMatthias Ringwald     btstack_linked_list_add(&bnep_channels, (btstack_linked_item_t *) channel);
7573deb3ec6SMatthias Ringwald 
7583deb3ec6SMatthias Ringwald     return channel;
7593deb3ec6SMatthias Ringwald }
7603deb3ec6SMatthias Ringwald 
7613deb3ec6SMatthias Ringwald static bnep_channel_t* bnep_channel_for_addr(bd_addr_t addr)
7623deb3ec6SMatthias Ringwald {
763665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
764665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){
7653deb3ec6SMatthias Ringwald         bnep_channel_t *channel = ((bnep_channel_t *) it);
766058e3d6bSMatthias Ringwald         if (bd_addr_cmp(addr, channel->remote_addr) == 0) {
7673deb3ec6SMatthias Ringwald             return channel;
7683deb3ec6SMatthias Ringwald         }
7693deb3ec6SMatthias Ringwald     }
7703deb3ec6SMatthias Ringwald     return NULL;
7713deb3ec6SMatthias Ringwald }
7723deb3ec6SMatthias Ringwald 
7733deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid)
7743deb3ec6SMatthias Ringwald {
775665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
776665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){
7773deb3ec6SMatthias Ringwald         bnep_channel_t *channel = ((bnep_channel_t *) it);
7783deb3ec6SMatthias Ringwald         if (channel->l2cap_cid == l2cap_cid) {
7793deb3ec6SMatthias Ringwald             return channel;
7803deb3ec6SMatthias Ringwald         }
7813deb3ec6SMatthias Ringwald     }
7823deb3ec6SMatthias Ringwald     return NULL;
7833deb3ec6SMatthias Ringwald }
7843deb3ec6SMatthias Ringwald 
7853deb3ec6SMatthias Ringwald static bnep_service_t * bnep_service_for_uuid(uint16_t uuid)
7863deb3ec6SMatthias Ringwald {
787665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
788665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_services; it ; it = it->next){
7893deb3ec6SMatthias Ringwald         bnep_service_t * service = ((bnep_service_t *) it);
7903deb3ec6SMatthias Ringwald         if ( service->service_uuid == uuid){
7913deb3ec6SMatthias Ringwald             return service;
7923deb3ec6SMatthias Ringwald         }
7933deb3ec6SMatthias Ringwald     }
7943deb3ec6SMatthias Ringwald     return NULL;
7953deb3ec6SMatthias Ringwald }
7963deb3ec6SMatthias Ringwald 
7973deb3ec6SMatthias Ringwald static void bnep_channel_free(bnep_channel_t *channel)
7983deb3ec6SMatthias Ringwald {
799665d90f2SMatthias Ringwald     btstack_linked_list_remove( &bnep_channels, (btstack_linked_item_t *) channel);
8003deb3ec6SMatthias Ringwald     btstack_memory_bnep_channel_free(channel);
8013deb3ec6SMatthias Ringwald }
8023deb3ec6SMatthias Ringwald 
8033deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel)
8043deb3ec6SMatthias Ringwald {
8053deb3ec6SMatthias Ringwald     uint16_t l2cap_cid;
8063deb3ec6SMatthias Ringwald 
8073deb3ec6SMatthias Ringwald     /* Inform application about closed channel */
8083deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
8093deb3ec6SMatthias Ringwald         bnep_emit_channel_closed(channel);
8103deb3ec6SMatthias Ringwald     }
8113deb3ec6SMatthias Ringwald 
8123deb3ec6SMatthias Ringwald     l2cap_cid = channel->l2cap_cid;
8133deb3ec6SMatthias Ringwald 
8143deb3ec6SMatthias Ringwald     /* Stop any eventually running timer */
8153deb3ec6SMatthias Ringwald     bnep_channel_stop_timer(channel);
8163deb3ec6SMatthias Ringwald 
8173deb3ec6SMatthias Ringwald     /* Free ressources and then close the l2cap channel */
8183deb3ec6SMatthias Ringwald     bnep_channel_free(channel);
819b93f8966SMatthias Ringwald     l2cap_disconnect(l2cap_cid);
8203deb3ec6SMatthias Ringwald }
8213deb3ec6SMatthias Ringwald 
8223deb3ec6SMatthias Ringwald static int bnep_handle_connection_request(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
8233deb3ec6SMatthias Ringwald {
8243deb3ec6SMatthias Ringwald     uint16_t uuid_size;
825bb015fa7SMatthias Ringwald     uint16_t uuid_offset = 0; // avoid "may be unitialized when used" in clang
8263deb3ec6SMatthias Ringwald     uuid_size = packet[1];
8273deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_SETUP_SUCCESS;
8283deb3ec6SMatthias Ringwald     bnep_service_t * service;
8293deb3ec6SMatthias Ringwald 
8303deb3ec6SMatthias Ringwald     /* Sanity check packet size */
831a1df452eSMatthias Ringwald     if (size < (1 + 1 + (2 * uuid_size))) {
8323deb3ec6SMatthias Ringwald         return 0;
8333deb3ec6SMatthias Ringwald     }
8343deb3ec6SMatthias Ringwald 
8353deb3ec6SMatthias Ringwald     if ((channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
8363deb3ec6SMatthias Ringwald         (channel->state != BNEP_CHANNEL_STATE_CONNECTED)) {
8373deb3ec6SMatthias Ringwald         /* Ignore a connection request if not waiting for or still connected */
8383deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_REQUEST: ignored in state %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
8393deb3ec6SMatthias Ringwald         return 0;
8403deb3ec6SMatthias Ringwald     }
8413deb3ec6SMatthias Ringwald 
8423deb3ec6SMatthias Ringwald      /* Extract source and destination UUID and convert them to UUID16 format */
8433deb3ec6SMatthias Ringwald     switch (uuid_size) {
8443deb3ec6SMatthias Ringwald         case 2:  /* UUID16  */
8453deb3ec6SMatthias Ringwald             uuid_offset = 0;
8463deb3ec6SMatthias Ringwald             break;
8473deb3ec6SMatthias Ringwald         case 4:  /* UUID32  */
8483deb3ec6SMatthias Ringwald         case 16: /* UUID128 */
8493deb3ec6SMatthias Ringwald             uuid_offset = 2;
8503deb3ec6SMatthias Ringwald             break;
8513deb3ec6SMatthias Ringwald         default:
8523deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid UUID size %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
8533deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_SERVICE_UUID_SIZE;
8543deb3ec6SMatthias Ringwald             break;
8553deb3ec6SMatthias Ringwald     }
8563deb3ec6SMatthias Ringwald 
857d4d9523fSMatthias Ringwald     /* Check bits 16-31 of UUID */
858d4d9523fSMatthias Ringwald     if (uuid_size > 2){
859d4d9523fSMatthias Ringwald         uint16_t dest_prefix = big_endian_read_16(packet, 2);
860d4d9523fSMatthias Ringwald         if (dest_prefix != 0){
861d4d9523fSMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID;
862d4d9523fSMatthias Ringwald         }
863d4d9523fSMatthias Ringwald         uint16_t src_prefix = big_endian_read_16(packet, 2 + uuid_size);
864d4d9523fSMatthias Ringwald         if (src_prefix != 0){
865d4d9523fSMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID;
866d4d9523fSMatthias Ringwald         }
867d4d9523fSMatthias Ringwald     }
868d4d9523fSMatthias Ringwald 
869d4d9523fSMatthias Ringwald     /* check bits 32-127 of UUID */
870d4d9523fSMatthias Ringwald     if (uuid_size == 16){
871d4d9523fSMatthias Ringwald         if (uuid_has_bluetooth_prefix(&packet[2]) == false){
872d4d9523fSMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID;
873d4d9523fSMatthias Ringwald         }
874d4d9523fSMatthias Ringwald         if (uuid_has_bluetooth_prefix(&packet[2+16]) == false){
875d4d9523fSMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID;
876d4d9523fSMatthias Ringwald         }
877d4d9523fSMatthias Ringwald     }
878d4d9523fSMatthias Ringwald 
8793deb3ec6SMatthias Ringwald     /* Check source and destination UUIDs for valid combinations */
8803deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_SETUP_SUCCESS) {
881f8fbdce0SMatthias Ringwald         channel->uuid_dest = big_endian_read_16(packet, 2 + uuid_offset);
882f8fbdce0SMatthias Ringwald         channel->uuid_source = big_endian_read_16(packet, 2 + uuid_offset + uuid_size);
8833deb3ec6SMatthias Ringwald 
884235946f1SMatthias Ringwald         if ((channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU) &&
885235946f1SMatthias Ringwald             (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_NAP) &&
886235946f1SMatthias Ringwald             (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_GN)) {
8873deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid destination service UUID: %04x", channel->uuid_dest);
8883deb3ec6SMatthias Ringwald             channel->uuid_dest = 0;
8893deb3ec6SMatthias Ringwald         }
890235946f1SMatthias Ringwald         if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) &&
891235946f1SMatthias Ringwald             (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_NAP) &&
892235946f1SMatthias Ringwald             (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_GN)) {
8933deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid source service UUID: %04x", channel->uuid_source);
8943deb3ec6SMatthias Ringwald             channel->uuid_source = 0;
8953deb3ec6SMatthias Ringwald         }
8963deb3ec6SMatthias Ringwald 
8973deb3ec6SMatthias Ringwald         /* Check if we have registered a service for the requested destination UUID */
8983deb3ec6SMatthias Ringwald         service = bnep_service_for_uuid(channel->uuid_dest);
8993deb3ec6SMatthias Ringwald         if (service == NULL) {
9003deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID;
9010c249750SMatthias Ringwald         } else {
9020c249750SMatthias Ringwald             // use packet handler for service
9030c249750SMatthias Ringwald             channel->packet_handler = service->packet_handler;
9040c249750SMatthias Ringwald 
905235946f1SMatthias Ringwald             if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) && (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU)) {
9063deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID;
9073deb3ec6SMatthias Ringwald             }
9083deb3ec6SMatthias Ringwald         }
9090c249750SMatthias Ringwald     }
9103deb3ec6SMatthias Ringwald 
9113deb3ec6SMatthias Ringwald     /* Set flag to send out the connection response on next statemachine cycle */
9123deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
9133deb3ec6SMatthias Ringwald     channel->response_code = response_code;
9144e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
9153deb3ec6SMatthias Ringwald 
9163deb3ec6SMatthias Ringwald     /* Return the number of processed package bytes = BNEP Type, BNEP Control Type, UUID-Size + 2 * UUID */
917c1ab6cc1SMatthias Ringwald     return 1 + 1 + (2 * uuid_size);
9183deb3ec6SMatthias Ringwald }
9193deb3ec6SMatthias Ringwald 
9203deb3ec6SMatthias Ringwald static int bnep_handle_connection_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9213deb3ec6SMatthias Ringwald {
9223deb3ec6SMatthias Ringwald 
9233deb3ec6SMatthias Ringwald     /* Sanity check packet size */
924c1ab6cc1SMatthias Ringwald     if (size < (1 + 2)) {
9253deb3ec6SMatthias Ringwald         return 0;
9263deb3ec6SMatthias Ringwald     }
9273deb3ec6SMatthias Ringwald 
9283deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE) {
9293deb3ec6SMatthias Ringwald         /* Ignore a connection response in any state but WAIT_FOR_CONNECTION_RESPONSE */
9303deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_RESPONSE: Ignored in channel state %d", channel->state);
9313deb3ec6SMatthias Ringwald         return 1 + 2;
9323deb3ec6SMatthias Ringwald     }
9333deb3ec6SMatthias Ringwald 
934*37e1b220SMatthias Ringwald     uint16_t response_code = big_endian_read_16(packet, 1);
9353deb3ec6SMatthias Ringwald 
9363deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_SETUP_SUCCESS) {
9373deb3ec6SMatthias Ringwald         log_info("BNEP_CONNECTION_RESPONSE: Channel established to %s", bd_addr_to_str(channel->remote_addr));
9383deb3ec6SMatthias Ringwald         channel->state = BNEP_CHANNEL_STATE_CONNECTED;
9393deb3ec6SMatthias Ringwald         /* Stop timeout timer! */
9403deb3ec6SMatthias Ringwald         bnep_channel_stop_timer(channel);
941*37e1b220SMatthias Ringwald         bnep_emit_open_channel_complete(channel, ERROR_CODE_SUCCESS, response_code);
9423deb3ec6SMatthias Ringwald     } else {
9433deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_RESPONSE: Connection to %s failed. Err: %d", bd_addr_to_str(channel->remote_addr), response_code);
944*37e1b220SMatthias Ringwald         bnep_emit_open_channel_complete(channel, BNEP_SETUP_CONNECTION_ERROR, response_code);
9453deb3ec6SMatthias Ringwald         bnep_channel_finalize(channel);
9463deb3ec6SMatthias Ringwald     }
9473deb3ec6SMatthias Ringwald     return 1 + 2;
9483deb3ec6SMatthias Ringwald }
9493deb3ec6SMatthias Ringwald 
9503deb3ec6SMatthias Ringwald static int bnep_can_handle_extensions(bnep_channel_t * channel){
9513deb3ec6SMatthias Ringwald     /* Extension are primarily handled in CONNECTED state */
9523deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) return 1;
9533deb3ec6SMatthias Ringwald     /* and if we've received connection request, but haven't sent the reponse yet. */
9543deb3ec6SMatthias Ringwald     if ((channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
9553deb3ec6SMatthias Ringwald         (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE)) {
9563deb3ec6SMatthias Ringwald         return 1;
9573deb3ec6SMatthias Ringwald     }
9583deb3ec6SMatthias Ringwald     return 0;
9593deb3ec6SMatthias Ringwald }
9603deb3ec6SMatthias Ringwald 
9613deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9623deb3ec6SMatthias Ringwald {
9633deb3ec6SMatthias Ringwald     uint16_t list_length;
9643deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
9653deb3ec6SMatthias Ringwald 
9663deb3ec6SMatthias Ringwald     /* Sanity check packet size */
9673deb3ec6SMatthias Ringwald     if (size < 3) {
9683deb3ec6SMatthias Ringwald         return 0;
9693deb3ec6SMatthias Ringwald     }
9703deb3ec6SMatthias Ringwald 
971f8fbdce0SMatthias Ringwald     list_length = big_endian_read_16(packet, 1);
9723deb3ec6SMatthias Ringwald     /* Sanity check packet size again with known package size */
973c1ab6cc1SMatthias Ringwald     if (size < (3 + list_length)) {
9743deb3ec6SMatthias Ringwald         return 0;
9753deb3ec6SMatthias Ringwald     }
9763deb3ec6SMatthias Ringwald 
9773deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
9783deb3ec6SMatthias Ringwald         log_error("BNEP_FILTER_NET_TYPE_SET: Ignored in channel state %d", channel->state);
9793deb3ec6SMatthias Ringwald         return 3 + list_length;
9803deb3ec6SMatthias Ringwald     }
9813deb3ec6SMatthias Ringwald 
9823deb3ec6SMatthias Ringwald     /* Check if we have enough space for more filters */
9833deb3ec6SMatthias Ringwald     if ((list_length / (2*2)) > MAX_BNEP_NETFILTER) {
9843deb3ec6SMatthias Ringwald         log_info("BNEP_FILTER_NET_TYPE_SET: Too many filter");
9853deb3ec6SMatthias Ringwald         response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
9863deb3ec6SMatthias Ringwald     } else {
9873deb3ec6SMatthias Ringwald         int i;
9883deb3ec6SMatthias Ringwald         channel->net_filter_count = 0;
9893deb3ec6SMatthias Ringwald         /* There is still enough space, copy the filters to our filter list */
990ef907034SMatthias Ringwald         /* There is still enough space, copy the filters to our filter list */
991c1ab6cc1SMatthias Ringwald         for (i = 0; i < (list_length / (2 * 2)); i ++) {
992c1ab6cc1SMatthias Ringwald             channel->net_filter[channel->net_filter_count].range_start = big_endian_read_16(packet, 1 + 2 + (i * 4));
993c1ab6cc1SMatthias Ringwald             channel->net_filter[channel->net_filter_count].range_end = big_endian_read_16(packet, 1 + 2 + (i * 4) + 2);
9943deb3ec6SMatthias Ringwald             if (channel->net_filter[channel->net_filter_count].range_start > channel->net_filter[channel->net_filter_count].range_end) {
9953deb3ec6SMatthias Ringwald                 /* Invalid filter range, ignore this filter rule */
9963deb3ec6SMatthias Ringwald                 log_error("BNEP_FILTER_NET_TYPE_SET: Invalid filter: start: %d, end: %d",
9973deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_start,
9983deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_end);
9993deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
10003deb3ec6SMatthias Ringwald             } else {
10013deb3ec6SMatthias Ringwald                 /* Valid filter, increase the filter count */
10023deb3ec6SMatthias Ringwald                 log_info("BNEP_FILTER_NET_TYPE_SET: Add filter: start: %d, end: %d",
10033deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_start,
10043deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_end);
10053deb3ec6SMatthias Ringwald                 channel->net_filter_count ++;
10063deb3ec6SMatthias Ringwald             }
10073deb3ec6SMatthias Ringwald         }
10083deb3ec6SMatthias Ringwald     }
10093deb3ec6SMatthias Ringwald 
10103deb3ec6SMatthias Ringwald     /* Set flag to send out the set net filter response on next statemachine cycle */
10113deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
10123deb3ec6SMatthias Ringwald     channel->response_code = response_code;
10134e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
10143deb3ec6SMatthias Ringwald 
10153deb3ec6SMatthias Ringwald     return 3 + list_length;
10163deb3ec6SMatthias Ringwald }
10173deb3ec6SMatthias Ringwald 
10183deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
10193deb3ec6SMatthias Ringwald {
10203deb3ec6SMatthias Ringwald 	uint16_t response_code;
10213deb3ec6SMatthias Ringwald 
10223deb3ec6SMatthias Ringwald     // TODO: Currently we do not support setting a network filter.
10233deb3ec6SMatthias Ringwald 
10243deb3ec6SMatthias Ringwald     /* Sanity check packet size */
1025c1ab6cc1SMatthias Ringwald     if (size < (1 + 2)) {
10263deb3ec6SMatthias Ringwald         return 0;
10273deb3ec6SMatthias Ringwald     }
10283deb3ec6SMatthias Ringwald 
10293deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
10303deb3ec6SMatthias Ringwald         log_error("BNEP_FILTER_NET_TYPE_RESPONSE: Ignored in channel state %d", channel->state);
10313deb3ec6SMatthias Ringwald         return 1 + 2;
10323deb3ec6SMatthias Ringwald     }
10333deb3ec6SMatthias Ringwald 
1034f8fbdce0SMatthias Ringwald     response_code = big_endian_read_16(packet, 1);
10353deb3ec6SMatthias Ringwald 
10363deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_FILTER_SUCCESS) {
10373deb3ec6SMatthias Ringwald         log_info("BNEP_FILTER_NET_TYPE_RESPONSE: Net filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
10383deb3ec6SMatthias Ringwald     } else {
10393deb3ec6SMatthias 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);
10403deb3ec6SMatthias Ringwald     }
10413deb3ec6SMatthias Ringwald 
10423deb3ec6SMatthias Ringwald     return 1 + 2;
10433deb3ec6SMatthias Ringwald }
10443deb3ec6SMatthias Ringwald 
10453deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
10463deb3ec6SMatthias Ringwald {
10473deb3ec6SMatthias Ringwald     uint16_t list_length;
10483deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
10493deb3ec6SMatthias Ringwald 
10503deb3ec6SMatthias Ringwald     /* Sanity check packet size */
10513deb3ec6SMatthias Ringwald     if (size < 3) {
10523deb3ec6SMatthias Ringwald         return 0;
10533deb3ec6SMatthias Ringwald     }
10543deb3ec6SMatthias Ringwald 
1055f8fbdce0SMatthias Ringwald     list_length = big_endian_read_16(packet, 1);
10563deb3ec6SMatthias Ringwald     /* Sanity check packet size again with known package size */
1057c1ab6cc1SMatthias Ringwald     if (size < (3 + list_length)) {
10583deb3ec6SMatthias Ringwald         return 0;
10593deb3ec6SMatthias Ringwald     }
10603deb3ec6SMatthias Ringwald 
10613deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
10623deb3ec6SMatthias Ringwald         log_error("BNEP_MULTI_ADDR_SET: Ignored in channel state %d", channel->state);
10633deb3ec6SMatthias Ringwald         return 3 + list_length;
10643deb3ec6SMatthias Ringwald     }
10653deb3ec6SMatthias Ringwald 
10663deb3ec6SMatthias Ringwald     /* Check if we have enough space for more filters */
1067b56e8b56SMatthias Ringwald 	uint16_t list_count = list_length / (2 * ETHER_ADDR_LEN);
1068b56e8b56SMatthias Ringwald     if (list_count > MAX_BNEP_MULTICAST_FILTER) {
10693deb3ec6SMatthias Ringwald         log_info("BNEP_MULTI_ADDR_SET: Too many filter");
10703deb3ec6SMatthias Ringwald         response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
10713deb3ec6SMatthias Ringwald     } else {
10723deb3ec6SMatthias Ringwald         unsigned int i;
10733deb3ec6SMatthias Ringwald         channel->multicast_filter_count = 0;
10743deb3ec6SMatthias Ringwald         /* There is enough space, copy the filters to our filter list */
1075b56e8b56SMatthias Ringwald         for (i = 0; i < list_count; i ++) {
1076c1ab6cc1SMatthias Ringwald             bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_start, packet + 1 + 2 + (i * ETHER_ADDR_LEN * 2));
1077c1ab6cc1SMatthias Ringwald             bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_end, packet + 1 + 2 + (i * ETHER_ADDR_LEN * 2) + ETHER_ADDR_LEN);
10783deb3ec6SMatthias Ringwald 
10793deb3ec6SMatthias Ringwald             if (memcmp(channel->multicast_filter[channel->multicast_filter_count].addr_start,
10803deb3ec6SMatthias Ringwald                        channel->multicast_filter[channel->multicast_filter_count].addr_end, ETHER_ADDR_LEN) > 0) {
10813deb3ec6SMatthias Ringwald                 /* Invalid filter range, ignore this filter rule */
10823deb3ec6SMatthias Ringwald                 log_error("BNEP_MULTI_ADDR_SET: Invalid filter: start: %s",
10833deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
10843deb3ec6SMatthias Ringwald                 log_error("BNEP_MULTI_ADDR_SET: Invalid filter: end: %s",
10853deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
10863deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
10873deb3ec6SMatthias Ringwald             } else {
10883deb3ec6SMatthias Ringwald                 /* Valid filter, increase the filter count */
10893deb3ec6SMatthias Ringwald                 log_info("BNEP_MULTI_ADDR_SET: Add filter: start: %s",
10903deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
10913deb3ec6SMatthias Ringwald                 log_info("BNEP_MULTI_ADDR_SET: Add filter: end: %s",
10923deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
10933deb3ec6SMatthias Ringwald                 channel->multicast_filter_count ++;
10943deb3ec6SMatthias Ringwald             }
10953deb3ec6SMatthias Ringwald         }
10963deb3ec6SMatthias Ringwald     }
10973deb3ec6SMatthias Ringwald     /* Set flag to send out the set multi addr response on next statemachine cycle */
10983deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
10993deb3ec6SMatthias Ringwald     channel->response_code = response_code;
11004e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
11013deb3ec6SMatthias Ringwald 
11023deb3ec6SMatthias Ringwald     return 3 + list_length;
11033deb3ec6SMatthias Ringwald }
11043deb3ec6SMatthias Ringwald 
11053deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
11063deb3ec6SMatthias Ringwald {
11073deb3ec6SMatthias Ringwald 	uint16_t response_code;
11083deb3ec6SMatthias Ringwald 
11093deb3ec6SMatthias Ringwald     // TODO: Currently we do not support setting multicast address filter.
11103deb3ec6SMatthias Ringwald 
11113deb3ec6SMatthias Ringwald     /* Sanity check packet size */
1112c1ab6cc1SMatthias Ringwald     if (size < (1 + 2)) {
11133deb3ec6SMatthias Ringwald         return 0;
11143deb3ec6SMatthias Ringwald     }
11153deb3ec6SMatthias Ringwald 
11163deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
11173deb3ec6SMatthias Ringwald         log_error("BNEP_MULTI_ADDR_RESPONSE: Ignored in channel state %d", channel->state);
11183deb3ec6SMatthias Ringwald         return 1 + 2;
11193deb3ec6SMatthias Ringwald     }
11203deb3ec6SMatthias Ringwald 
1121f8fbdce0SMatthias Ringwald     response_code = big_endian_read_16(packet, 1);
11223deb3ec6SMatthias Ringwald 
11233deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_FILTER_SUCCESS) {
11243deb3ec6SMatthias Ringwald         log_info("BNEP_MULTI_ADDR_RESPONSE: Multicast address filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
11253deb3ec6SMatthias Ringwald     } else {
11263deb3ec6SMatthias 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);
11273deb3ec6SMatthias Ringwald     }
11283deb3ec6SMatthias Ringwald 
11293deb3ec6SMatthias Ringwald     return 1 + 2;
11303deb3ec6SMatthias Ringwald }
11313deb3ec6SMatthias Ringwald 
11323deb3ec6SMatthias 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)
11333deb3ec6SMatthias Ringwald {
11343deb3ec6SMatthias Ringwald     uint16_t pos = 0;
11353deb3ec6SMatthias Ringwald 
1136f2e45468SMatthias 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)
11373deb3ec6SMatthias Ringwald     /* In-place modify the package and add the ethernet header in front of the payload.
11383deb3ec6SMatthias Ringwald      * WARNING: This modifies the data in front of the payload and may overwrite 14 bytes there!
11393deb3ec6SMatthias Ringwald      */
11400e588213SMatthias Ringwald     uint8_t *ethernet_packet = payload - (2 * sizeof(bd_addr_t)) - sizeof(uint16_t);
11413deb3ec6SMatthias Ringwald     /* Restore the ethernet packet header */
1142058e3d6bSMatthias Ringwald     bd_addr_copy(ethernet_packet + pos, addr_dest);
11433deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1144058e3d6bSMatthias Ringwald     bd_addr_copy(ethernet_packet + pos, addr_source);
11453deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1146f8fbdce0SMatthias Ringwald     big_endian_store_16(ethernet_packet, pos, network_protocol_type);
11473deb3ec6SMatthias Ringwald     /* Payload is just in place... */
11483deb3ec6SMatthias Ringwald #else
1149f2e45468SMatthias Ringwald #error "BNEP requires HCI_INCOMING_PRE_BUFFER_SIZE >= 6. Please update bstack_config.h"
11503deb3ec6SMatthias Ringwald #endif
11513deb3ec6SMatthias Ringwald 
11523deb3ec6SMatthias Ringwald     /* Notify application layer and deliver the ethernet packet */
1153c9bf9c27SMatthias Ringwald     if (channel->packet_handler){
1154c9bf9c27SMatthias Ringwald         (*channel->packet_handler)(BNEP_DATA_PACKET, channel->l2cap_cid, ethernet_packet,
11550e588213SMatthias Ringwald                                    size + sizeof(uint16_t) + (2 * sizeof(bd_addr_t)) );
1156c9bf9c27SMatthias Ringwald     }
11573deb3ec6SMatthias Ringwald 
11583deb3ec6SMatthias Ringwald     return size;
11593deb3ec6SMatthias Ringwald }
11603deb3ec6SMatthias Ringwald 
11613deb3ec6SMatthias Ringwald static int bnep_handle_control_packet(bnep_channel_t *channel, uint8_t *packet, uint16_t size, int is_extension)
11623deb3ec6SMatthias Ringwald {
11633deb3ec6SMatthias Ringwald     uint16_t len = 0;
11643deb3ec6SMatthias Ringwald 
1165b85ad952SMatthias Ringwald     if (size > 0) {
1166b85ad952SMatthias Ringwald 
1167b85ad952SMatthias Ringwald         uint8_t bnep_control_type = packet[0];
11683deb3ec6SMatthias Ringwald         /* Save last control type. Needed by statemachin in case of unknown control code */
11693deb3ec6SMatthias Ringwald 
11703deb3ec6SMatthias Ringwald         channel->last_control_type = bnep_control_type;
11713deb3ec6SMatthias Ringwald         log_info("BNEP_CONTROL: Type: %d, size: %d, is_extension: %d", bnep_control_type, size, is_extension);
11723deb3ec6SMatthias Ringwald         switch (bnep_control_type) {
11733deb3ec6SMatthias Ringwald             case BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD:
11743deb3ec6SMatthias Ringwald                 /* The last command we send was not understood. We should close the connection */
1175b85ad952SMatthias Ringwald                 log_error("BNEP_CONTROL: Received COMMAND_NOT_UNDERSTOOD: l2cap_cid: %d, cmd: %d", channel->l2cap_cid,
1176b85ad952SMatthias Ringwald                           packet[3]);
11773deb3ec6SMatthias Ringwald                 bnep_channel_finalize(channel);
11783deb3ec6SMatthias Ringwald                 len = 2; // Length of command not understood packet - bnep-type field
11793deb3ec6SMatthias Ringwald                 break;
11803deb3ec6SMatthias Ringwald             case BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST:
11813deb3ec6SMatthias Ringwald                 if (is_extension) {
11823deb3ec6SMatthias Ringwald                     /* Connection requests are not allowed to be send in an extension header
11833deb3ec6SMatthias Ringwald                      *  ignore, do not set "COMMAND_NOT_UNDERSTOOD"
11843deb3ec6SMatthias Ringwald                      */
1185b85ad952SMatthias Ringwald                     log_error("BNEP_CONTROL: Received SETUP_CONNECTION_REQUEST in extension header: l2cap_cid: %d",
1186b85ad952SMatthias Ringwald                               channel->l2cap_cid);
11873deb3ec6SMatthias Ringwald                     return 0;
11883deb3ec6SMatthias Ringwald                 } else {
11893deb3ec6SMatthias Ringwald                     len = bnep_handle_connection_request(channel, packet, size);
11903deb3ec6SMatthias Ringwald                 }
11913deb3ec6SMatthias Ringwald                 break;
11923deb3ec6SMatthias Ringwald             case BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE:
11933deb3ec6SMatthias Ringwald                 if (is_extension) {
11943deb3ec6SMatthias Ringwald                     /* Connection requests are not allowed to be send in an
11953deb3ec6SMatthias Ringwald                      * extension header, ignore, do not set "COMMAND_NOT_UNDERSTOOD"
11963deb3ec6SMatthias Ringwald                      */
1197b85ad952SMatthias Ringwald                     log_error("BNEP_CONTROL: Received SETUP_CONNECTION_RESPONSE in extension header: l2cap_cid: %d",
1198b85ad952SMatthias Ringwald                               channel->l2cap_cid);
11993deb3ec6SMatthias Ringwald                     return 0;
12003deb3ec6SMatthias Ringwald                 } else {
12013deb3ec6SMatthias Ringwald                     len = bnep_handle_connection_response(channel, packet, size);
12023deb3ec6SMatthias Ringwald                 }
12033deb3ec6SMatthias Ringwald                 break;
12043deb3ec6SMatthias Ringwald             case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET:
12053deb3ec6SMatthias Ringwald                 len = bnep_handle_filter_net_type_set(channel, packet, size);
12063deb3ec6SMatthias Ringwald                 break;
12073deb3ec6SMatthias Ringwald             case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE:
12083deb3ec6SMatthias Ringwald                 len = bnep_handle_filter_net_type_response(channel, packet, size);
12093deb3ec6SMatthias Ringwald                 break;
12103deb3ec6SMatthias Ringwald             case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET:
12113deb3ec6SMatthias Ringwald                 len = bnep_handle_multi_addr_set(channel, packet, size);
12123deb3ec6SMatthias Ringwald                 break;
12133deb3ec6SMatthias Ringwald             case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE:
12143deb3ec6SMatthias Ringwald                 len = bnep_handle_multi_addr_response(channel, packet, size);
12153deb3ec6SMatthias Ringwald                 break;
12163deb3ec6SMatthias Ringwald             default:
1217b85ad952SMatthias Ringwald                 log_error("BNEP_CONTROL: Invalid bnep control type: l2cap_cid: %d, cmd: %d", channel->l2cap_cid,
1218b85ad952SMatthias Ringwald                           bnep_control_type);
12193deb3ec6SMatthias Ringwald                 len = 0;
12203deb3ec6SMatthias Ringwald                 break;
12213deb3ec6SMatthias Ringwald         }
1222b85ad952SMatthias Ringwald     }
12233deb3ec6SMatthias Ringwald 
12243deb3ec6SMatthias Ringwald     if (len == 0) {
12253deb3ec6SMatthias Ringwald         /* In case the command could not be handled, send a
12263deb3ec6SMatthias Ringwald            COMMAND_NOT_UNDERSTOOD message.
12273deb3ec6SMatthias Ringwald            Set flag to process the request in the next statemachine loop
12283deb3ec6SMatthias Ringwald          */
12293deb3ec6SMatthias Ringwald         bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
12304e366553SMatthias Ringwald         l2cap_request_can_send_now_event(channel->l2cap_cid);
12313deb3ec6SMatthias Ringwald     }
12323deb3ec6SMatthias Ringwald 
12333deb3ec6SMatthias Ringwald     return len;
12343deb3ec6SMatthias Ringwald }
12353deb3ec6SMatthias Ringwald 
12363deb3ec6SMatthias Ringwald /**
12373deb3ec6SMatthias Ringwald  * @return handled packet
12383deb3ec6SMatthias Ringwald  */
12393deb3ec6SMatthias Ringwald static int bnep_hci_event_handler(uint8_t *packet, uint16_t size)
12403deb3ec6SMatthias Ringwald {
1241f21eb74fSMatthias Ringwald     UNUSED(size);   // ok: handling own l2cap events
12429ec2630cSMatthias Ringwald 
12433deb3ec6SMatthias Ringwald     bd_addr_t event_addr;
12443deb3ec6SMatthias Ringwald     uint16_t  psm;
12453deb3ec6SMatthias Ringwald     uint16_t  l2cap_cid;
12463deb3ec6SMatthias Ringwald     hci_con_handle_t con_handle;
12473deb3ec6SMatthias Ringwald     bnep_channel_t  *channel = NULL;
12483deb3ec6SMatthias Ringwald     uint8_t   status;
12493deb3ec6SMatthias Ringwald 
12500e2df43fSMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
12513deb3ec6SMatthias Ringwald 
125284e3541eSMilanka Ringwald         /* Accept an incoming L2CAP connection on BLUETOOTH_PSM_BNEP */
12533deb3ec6SMatthias Ringwald         case L2CAP_EVENT_INCOMING_CONNECTION:
12543deb3ec6SMatthias Ringwald             /* L2CAP event data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16) */
1255724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], event_addr);
1256f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet,  8);
1257f8fbdce0SMatthias Ringwald             psm        = little_endian_read_16(packet, 10);
1258f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 12);
12593deb3ec6SMatthias Ringwald 
126084e3541eSMilanka Ringwald             if (psm != BLUETOOTH_PSM_BNEP) break;
12613deb3ec6SMatthias Ringwald 
12623deb3ec6SMatthias Ringwald             channel = bnep_channel_for_addr(event_addr);
12633deb3ec6SMatthias Ringwald 
12643deb3ec6SMatthias Ringwald             if (channel) {
126584e3541eSMilanka Ringwald                 log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => decline - channel already exists", l2cap_cid);
12667ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
12673deb3ec6SMatthias Ringwald                 return 1;
12683deb3ec6SMatthias Ringwald             }
12693deb3ec6SMatthias Ringwald 
12703deb3ec6SMatthias Ringwald             /* Create a new BNEP channel instance (incoming) */
12713deb3ec6SMatthias Ringwald             channel = bnep_channel_create_for_addr(event_addr);
12723deb3ec6SMatthias Ringwald 
12733deb3ec6SMatthias Ringwald             if (!channel) {
127484e3541eSMilanka Ringwald                 log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => decline - no memory left", l2cap_cid);
12757ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
12763deb3ec6SMatthias Ringwald                 return 1;
12773deb3ec6SMatthias Ringwald             }
12783deb3ec6SMatthias Ringwald 
12793deb3ec6SMatthias Ringwald             /* Assign connection handle and l2cap cid */
12803deb3ec6SMatthias Ringwald             channel->con_handle = con_handle;
12813deb3ec6SMatthias Ringwald             channel->l2cap_cid = l2cap_cid;
12823deb3ec6SMatthias Ringwald 
12833deb3ec6SMatthias Ringwald             /* Set channel into accept state */
12843deb3ec6SMatthias Ringwald             channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST;
12853deb3ec6SMatthias Ringwald 
12863deb3ec6SMatthias Ringwald             /* Start connection timeout timer */
12873deb3ec6SMatthias Ringwald             bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
12883deb3ec6SMatthias Ringwald 
128984e3541eSMilanka Ringwald             log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PSM_BNEP => accept", l2cap_cid);
1290ce8f182eSMatthias Ringwald             l2cap_accept_connection(l2cap_cid);
12913deb3ec6SMatthias Ringwald             return 1;
12923deb3ec6SMatthias Ringwald 
12933deb3ec6SMatthias Ringwald         /* Outgoing L2CAP connection has been opened -> store l2cap_cid, remote_addr */
12943deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_OPENED:
12953deb3ec6SMatthias Ringwald             status = packet[2];
129684e3541eSMilanka Ringwald             log_info("L2CAP_EVENT_CHANNEL_OPENED for BLUETOOTH_PSM_BNEP, status %u", status);
12973deb3ec6SMatthias Ringwald 
12983deb3ec6SMatthias Ringwald             /* Get the bnep channel fpr remote address */
1299f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet, 9);
1300f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 13);
1301724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[3], event_addr);
13023deb3ec6SMatthias Ringwald             channel = bnep_channel_for_addr(event_addr);
13033deb3ec6SMatthias Ringwald             if (!channel) {
13043deb3ec6SMatthias Ringwald                 log_error("L2CAP_EVENT_CHANNEL_OPENED but no BNEP channel prepared");
13053deb3ec6SMatthias Ringwald                 return 1;
13063deb3ec6SMatthias Ringwald             }
13073deb3ec6SMatthias Ringwald 
13083deb3ec6SMatthias Ringwald             /* On L2CAP open error discard everything */
13093deb3ec6SMatthias Ringwald             if (status) {
13103deb3ec6SMatthias Ringwald                 /* Emit bnep_open_channel_complete with status and free channel */
1311*37e1b220SMatthias Ringwald                 bnep_emit_open_channel_complete(channel, status, 0);
13123deb3ec6SMatthias Ringwald 
13133deb3ec6SMatthias Ringwald                 /* Free BNEP channel mempory */
13143deb3ec6SMatthias Ringwald                 bnep_channel_free(channel);
13153deb3ec6SMatthias Ringwald                 return 1;
13163deb3ec6SMatthias Ringwald             }
13173deb3ec6SMatthias Ringwald 
13183deb3ec6SMatthias Ringwald             switch (channel->state){
13193deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_CLOSED:
13203deb3ec6SMatthias Ringwald                     log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
13213deb3ec6SMatthias Ringwald 
13223deb3ec6SMatthias Ringwald                     bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
13233deb3ec6SMatthias Ringwald 
13243deb3ec6SMatthias Ringwald                     /* Assign connection handle and l2cap cid */
13253deb3ec6SMatthias Ringwald                     channel->l2cap_cid  = l2cap_cid;
13263deb3ec6SMatthias Ringwald                     channel->con_handle = con_handle;
13273deb3ec6SMatthias Ringwald 
13283deb3ec6SMatthias Ringwald                     /* Initiate the connection request */
13293deb3ec6SMatthias Ringwald                     channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
13303deb3ec6SMatthias Ringwald                     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
1331f8fbdce0SMatthias Ringwald                     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
13324e366553SMatthias Ringwald                     l2cap_request_can_send_now_event(channel->l2cap_cid);
13333deb3ec6SMatthias Ringwald                     break;
13343deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
13353deb3ec6SMatthias Ringwald                     /* New information: channel mtu */
1336f8fbdce0SMatthias Ringwald                     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
13373deb3ec6SMatthias Ringwald                     break;
13383deb3ec6SMatthias Ringwald                 default:
13393deb3ec6SMatthias Ringwald                     log_error("L2CAP_EVENT_CHANNEL_OPENED: Invalid state: %d", channel->state);
13403deb3ec6SMatthias Ringwald                     break;
13413deb3ec6SMatthias Ringwald             }
13423deb3ec6SMatthias Ringwald             return 1;
13433deb3ec6SMatthias Ringwald 
13441b89a84bSMatthias Ringwald         case L2CAP_EVENT_CAN_SEND_NOW:
13454e366553SMatthias Ringwald             bnep_handle_can_send_now(l2cap_event_can_send_now_get_local_cid(packet));
13463deb3ec6SMatthias Ringwald             break;
13473deb3ec6SMatthias Ringwald 
13483deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_CLOSED:
13493deb3ec6SMatthias Ringwald             // data: event (8), len(8), channel (16)
1350f8fbdce0SMatthias Ringwald             l2cap_cid   = little_endian_read_16(packet, 2);
13513deb3ec6SMatthias Ringwald             channel = bnep_channel_for_l2cap_cid(l2cap_cid);
13523deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, channel %p", l2cap_cid, channel);
13533deb3ec6SMatthias Ringwald 
13543deb3ec6SMatthias Ringwald             if (!channel) {
13553deb3ec6SMatthias Ringwald                 break;
13563deb3ec6SMatthias Ringwald             }
13573deb3ec6SMatthias Ringwald 
13583deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", channel->state);
13593deb3ec6SMatthias Ringwald             switch (channel->state) {
13603deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
13613deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE:
13623deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_CONNECTED:
13633deb3ec6SMatthias Ringwald                     bnep_channel_finalize(channel);
13643deb3ec6SMatthias Ringwald                     return 1;
13653deb3ec6SMatthias Ringwald                 default:
13663deb3ec6SMatthias Ringwald                     break;
13673deb3ec6SMatthias Ringwald             }
13683deb3ec6SMatthias Ringwald             break;
13693deb3ec6SMatthias Ringwald         default:
13703deb3ec6SMatthias Ringwald             break;
13713deb3ec6SMatthias Ringwald     }
13723deb3ec6SMatthias Ringwald     return 0;
13733deb3ec6SMatthias Ringwald }
13743deb3ec6SMatthias Ringwald 
13753deb3ec6SMatthias Ringwald static int bnep_l2cap_packet_handler(uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
13763deb3ec6SMatthias Ringwald {
13773deb3ec6SMatthias Ringwald     int             rc = 0;
13783deb3ec6SMatthias Ringwald     uint8_t         bnep_type;
13793deb3ec6SMatthias Ringwald     uint8_t         bnep_header_has_ext;
13803deb3ec6SMatthias Ringwald     uint8_t         extension_type;
13813deb3ec6SMatthias Ringwald     uint16_t        pos = 0;
13823deb3ec6SMatthias Ringwald     bd_addr_t       addr_source;
13833deb3ec6SMatthias Ringwald     bd_addr_t       addr_dest;
13843deb3ec6SMatthias Ringwald     uint16_t        network_protocol_type = 0xffff;
13853deb3ec6SMatthias Ringwald     bnep_channel_t *channel = NULL;
13863deb3ec6SMatthias Ringwald 
13873deb3ec6SMatthias Ringwald     /* Get the bnep channel for this package */
13883deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(l2cap_cid);
13893deb3ec6SMatthias Ringwald     if (!channel) {
13903deb3ec6SMatthias Ringwald         return rc;
13913deb3ec6SMatthias Ringwald     }
13923deb3ec6SMatthias Ringwald 
13933deb3ec6SMatthias Ringwald     /* Sort out short packages */
13943deb3ec6SMatthias Ringwald     if (size < 2) {
13953deb3ec6SMatthias Ringwald         return rc;
13963deb3ec6SMatthias Ringwald     }
13973deb3ec6SMatthias Ringwald 
13983deb3ec6SMatthias Ringwald     bnep_type = BNEP_TYPE(packet[pos]);
13993deb3ec6SMatthias Ringwald     bnep_header_has_ext = BNEP_HEADER_HAS_EXT(packet[pos]);
14003deb3ec6SMatthias Ringwald     pos ++;
14013deb3ec6SMatthias Ringwald 
14023deb3ec6SMatthias Ringwald     switch(bnep_type) {
14033deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_GENERAL_ETHERNET:
1404b85ad952SMatthias Ringwald             if ((pos + 14) > size) {
1405b85ad952SMatthias Ringwald                 return rc;
1406b85ad952SMatthias Ringwald             }
1407058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, &packet[pos]);
14083deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1409058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, &packet[pos]);
14103deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1411f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
14123deb3ec6SMatthias Ringwald             pos += 2;
14133deb3ec6SMatthias Ringwald             break;
14143deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET:
1415b85ad952SMatthias Ringwald             if ((pos + 2) > size) {
1416b85ad952SMatthias Ringwald                 return rc;
1417b85ad952SMatthias Ringwald             }
1418058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, channel->local_addr);
1419058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, channel->remote_addr);
1420f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
14213deb3ec6SMatthias Ringwald             pos += 2;
14223deb3ec6SMatthias Ringwald             break;
14233deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY:
1424b85ad952SMatthias Ringwald             if ((pos + 8) > size) {
1425b85ad952SMatthias Ringwald                 return rc;
1426b85ad952SMatthias Ringwald             }
1427058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, channel->local_addr);
1428058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, &packet[pos]);
14293deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1430f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
14313deb3ec6SMatthias Ringwald             pos += 2;
14323deb3ec6SMatthias Ringwald             break;
14333deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY:
1434b85ad952SMatthias Ringwald             if ((pos + 8) > size) {
1435b85ad952SMatthias Ringwald                 return rc;
1436b85ad952SMatthias Ringwald             }
1437058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, &packet[pos]);
14383deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1439058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, channel->remote_addr);
1440f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
14413deb3ec6SMatthias Ringwald             pos += 2;
14423deb3ec6SMatthias Ringwald             break;
14433deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_CONTROL:
14443deb3ec6SMatthias Ringwald             rc = bnep_handle_control_packet(channel, packet + pos, size - pos, 0);
1445b85ad952SMatthias Ringwald             if (rc == 0){
1446b85ad952SMatthias Ringwald                 // invalid control packet
1447b85ad952SMatthias Ringwald                 return 0;
1448b85ad952SMatthias Ringwald             }
14493deb3ec6SMatthias Ringwald             pos += rc;
14503deb3ec6SMatthias Ringwald             break;
14513deb3ec6SMatthias Ringwald         default:
14523deb3ec6SMatthias Ringwald             break;
14533deb3ec6SMatthias Ringwald     }
14543deb3ec6SMatthias Ringwald 
14553deb3ec6SMatthias Ringwald     if (bnep_header_has_ext) {
14563deb3ec6SMatthias Ringwald         do {
14573deb3ec6SMatthias Ringwald             uint8_t ext_len;
14583deb3ec6SMatthias Ringwald 
1459b85ad952SMatthias Ringwald             if (pos + 2 > size) {
1460b85ad952SMatthias Ringwald                 return rc;
1461b85ad952SMatthias Ringwald             }
1462b85ad952SMatthias Ringwald 
14633deb3ec6SMatthias Ringwald             /* Read extension type and check for further extensions */
14643deb3ec6SMatthias Ringwald             extension_type        = BNEP_TYPE(packet[pos]);
14653deb3ec6SMatthias Ringwald             bnep_header_has_ext   = BNEP_HEADER_HAS_EXT(packet[pos]);
14663deb3ec6SMatthias Ringwald             pos ++;
14673deb3ec6SMatthias Ringwald 
14683deb3ec6SMatthias Ringwald             /* Read extension header length */
14693deb3ec6SMatthias Ringwald             ext_len = packet[pos];
14703deb3ec6SMatthias Ringwald             pos ++;
14713deb3ec6SMatthias Ringwald 
1472c1ab6cc1SMatthias Ringwald             if ((size - pos) < ext_len) {
14733deb3ec6SMatthias Ringwald                 return 0;
14743deb3ec6SMatthias Ringwald             }
14753deb3ec6SMatthias Ringwald 
14763deb3ec6SMatthias Ringwald             switch (extension_type) {
14773deb3ec6SMatthias Ringwald                 case BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL:
14783deb3ec6SMatthias Ringwald                     if (ext_len != bnep_handle_control_packet(channel, packet + pos, ext_len, 1)) {
14793deb3ec6SMatthias Ringwald                         log_error("BNEP pkt handler: Ignore invalid control packet in extension header");
14803deb3ec6SMatthias Ringwald                     }
14813deb3ec6SMatthias Ringwald 
14823deb3ec6SMatthias Ringwald                     pos += ext_len;
14833deb3ec6SMatthias Ringwald                     break;
14843deb3ec6SMatthias Ringwald 
14853deb3ec6SMatthias Ringwald                 default:
1486b85ad952SMatthias Ringwald                     /* Extension header type unknown. Unknown extension SHALL be forwarded
1487b85ad952SMatthias Ringwald                      * in any way. But who shall handle these extension packets?
14883deb3ec6SMatthias Ringwald                      * For now: We ignore them and just drop them!
14893deb3ec6SMatthias Ringwald                      */
14903deb3ec6SMatthias Ringwald                     log_error("BNEP pkt handler: Unknown extension type ignored, data dropped!");
14913deb3ec6SMatthias Ringwald                     pos += ext_len;
14923deb3ec6SMatthias Ringwald                     break;
14933deb3ec6SMatthias Ringwald             }
14943deb3ec6SMatthias Ringwald 
14953deb3ec6SMatthias Ringwald         } while (bnep_header_has_ext);
14963deb3ec6SMatthias Ringwald     }
14973deb3ec6SMatthias Ringwald 
1498c1ab6cc1SMatthias Ringwald     if ((bnep_type != BNEP_PKT_TYPE_CONTROL) && (network_protocol_type != 0xffff)) {
14993deb3ec6SMatthias Ringwald         if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
15003deb3ec6SMatthias Ringwald             rc = bnep_handle_ethernet_packet(channel, addr_dest, addr_source, network_protocol_type, packet + pos, size - pos);
15013deb3ec6SMatthias Ringwald         } else {
15023deb3ec6SMatthias Ringwald             rc = 0;
15033deb3ec6SMatthias Ringwald         }
15043deb3ec6SMatthias Ringwald     }
15053deb3ec6SMatthias Ringwald 
15063deb3ec6SMatthias Ringwald     return rc;
15073deb3ec6SMatthias Ringwald 
15083deb3ec6SMatthias Ringwald }
15093deb3ec6SMatthias Ringwald 
15103deb3ec6SMatthias Ringwald void bnep_packet_handler(uint8_t packet_type, uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
15113deb3ec6SMatthias Ringwald {
15123deb3ec6SMatthias Ringwald     switch (packet_type) {
15133deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
1514bef9a6fcSMatthias Ringwald             bnep_hci_event_handler(packet, size);
15153deb3ec6SMatthias Ringwald             break;
15163deb3ec6SMatthias Ringwald         case L2CAP_DATA_PACKET:
1517bef9a6fcSMatthias Ringwald             bnep_l2cap_packet_handler(l2cap_cid, packet, size);
15183deb3ec6SMatthias Ringwald             break;
15193deb3ec6SMatthias Ringwald         default:
15203deb3ec6SMatthias Ringwald             break;
15213deb3ec6SMatthias Ringwald     }
15223deb3ec6SMatthias Ringwald }
15233deb3ec6SMatthias Ringwald 
15243deb3ec6SMatthias Ringwald static void bnep_channel_state_machine(bnep_channel_t* channel, bnep_channel_event_t *event)
15253deb3ec6SMatthias Ringwald {
1526b42623deSMatthias Ringwald     log_debug("bnep_state_machine: state %u, state var: %02x, event %u", channel->state, channel->state_var, event->type);
15273deb3ec6SMatthias Ringwald 
15283deb3ec6SMatthias Ringwald     if (event->type == BNEP_CH_EVT_READY_TO_SEND) {
15293deb3ec6SMatthias Ringwald         /* Send outstanding packets. */
15303deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD) {
15313deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
15323deb3ec6SMatthias Ringwald             bnep_send_command_not_understood(channel, channel->last_control_type);
15333deb3ec6SMatthias Ringwald             return;
15343deb3ec6SMatthias Ringwald         }
15353deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST) {
15363deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
15373deb3ec6SMatthias Ringwald             channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
15383deb3ec6SMatthias Ringwald             bnep_send_connection_request(channel, channel->uuid_source, channel->uuid_dest);
15393deb3ec6SMatthias Ringwald         }
15403deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE) {
15413deb3ec6SMatthias Ringwald             int emit_connected = 0;
15423deb3ec6SMatthias Ringwald             if ((channel->state == BNEP_CHANNEL_STATE_CLOSED) ||
15433deb3ec6SMatthias Ringwald                 (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST)) {
15443deb3ec6SMatthias Ringwald                 /* Set channel state to STATE_CONNECTED */
15453deb3ec6SMatthias Ringwald                 channel->state = BNEP_CHANNEL_STATE_CONNECTED;
15463deb3ec6SMatthias Ringwald                 /* Stop timeout timer! */
15473deb3ec6SMatthias Ringwald                 bnep_channel_stop_timer(channel);
15483deb3ec6SMatthias Ringwald                 emit_connected = 1;
15493deb3ec6SMatthias Ringwald             }
15503deb3ec6SMatthias Ringwald 
15513deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
15523deb3ec6SMatthias Ringwald             bnep_send_connection_response(channel, channel->response_code);
15533deb3ec6SMatthias Ringwald             if (emit_connected){
1554*37e1b220SMatthias Ringwald                 bnep_emit_open_channel_complete(channel, ERROR_CODE_SUCCESS, 0);
15553deb3ec6SMatthias Ringwald             }
15563deb3ec6SMatthias Ringwald             return;
15573deb3ec6SMatthias Ringwald         }
15583deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET) {
15593deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
15603deb3ec6SMatthias Ringwald             if ((channel->net_filter_out_count > 0) && (channel->net_filter_out != NULL)) {
15613deb3ec6SMatthias Ringwald                 bnep_send_filter_net_type_set(channel, channel->net_filter_out, channel->net_filter_out_count);
15623deb3ec6SMatthias Ringwald                 channel->net_filter_out_count = 0;
15633deb3ec6SMatthias Ringwald                 channel->net_filter_out = NULL;
15643deb3ec6SMatthias Ringwald             }
15653deb3ec6SMatthias Ringwald             return;
15663deb3ec6SMatthias Ringwald         }
15673deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE) {
15683deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
15693deb3ec6SMatthias Ringwald             bnep_send_filter_net_type_response(channel, channel->response_code);
15703deb3ec6SMatthias Ringwald             return;
15713deb3ec6SMatthias Ringwald         }
15723deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET) {
15733deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
15743deb3ec6SMatthias Ringwald             if ((channel->multicast_filter_out_count > 0) && (channel->multicast_filter_out != NULL)) {
15753deb3ec6SMatthias Ringwald                 bnep_send_filter_multi_addr_set(channel, channel->multicast_filter_out, channel->multicast_filter_out_count);
15763deb3ec6SMatthias Ringwald                 channel->multicast_filter_out_count = 0;
15773deb3ec6SMatthias Ringwald                 channel->multicast_filter_out = NULL;
15783deb3ec6SMatthias Ringwald             }
15793deb3ec6SMatthias Ringwald             return;
15803deb3ec6SMatthias Ringwald         }
15813deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE) {
15823deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
15833deb3ec6SMatthias Ringwald             bnep_send_filter_multi_addr_response(channel, channel->response_code);
15843deb3ec6SMatthias Ringwald             return;
15853deb3ec6SMatthias Ringwald         }
15863deb3ec6SMatthias Ringwald 
15873deb3ec6SMatthias Ringwald         /* If the event was not yet handled, notify the application layer */
15881ed1a3bdSMatthias Ringwald         if (channel->waiting_for_can_send_now){
15891ed1a3bdSMatthias Ringwald             channel->waiting_for_can_send_now = 0;
15903deb3ec6SMatthias Ringwald             bnep_emit_ready_to_send(channel);
15913deb3ec6SMatthias Ringwald         }
15923deb3ec6SMatthias Ringwald     }
15931ed1a3bdSMatthias Ringwald }
15943deb3ec6SMatthias Ringwald 
15954e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t l2cap_cid){
1596665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
1597665d90f2SMatthias Ringwald     btstack_linked_item_t *next;
15983deb3ec6SMatthias Ringwald 
1599665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = next){
16003deb3ec6SMatthias Ringwald         next = it->next;    // be prepared for removal of channel in state machine
16013deb3ec6SMatthias Ringwald         bnep_channel_t * channel = ((bnep_channel_t *) it);
16024e366553SMatthias Ringwald         if (channel->l2cap_cid != l2cap_cid) continue;
16034e366553SMatthias Ringwald         //
16043deb3ec6SMatthias Ringwald         bnep_channel_event_t channel_event = { BNEP_CH_EVT_READY_TO_SEND };
16053deb3ec6SMatthias Ringwald         bnep_channel_state_machine(channel, &channel_event);
16064e366553SMatthias Ringwald 
16074e366553SMatthias Ringwald         if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
16084e366553SMatthias Ringwald             l2cap_request_can_send_now_event(channel->l2cap_cid);
16094e366553SMatthias Ringwald             return;
16103deb3ec6SMatthias Ringwald         }
16113deb3ec6SMatthias Ringwald     }
16124e366553SMatthias Ringwald }
16134e366553SMatthias Ringwald 
16143deb3ec6SMatthias Ringwald 
16153deb3ec6SMatthias Ringwald /* BNEP BTStack API */
16163deb3ec6SMatthias Ringwald void bnep_init(void)
16173deb3ec6SMatthias Ringwald {
161878315a58SMatthias Ringwald     bnep_security_level = gap_get_security_level();
16193deb3ec6SMatthias Ringwald }
16203deb3ec6SMatthias Ringwald 
162151e0db05SMatthias Ringwald void bnep_deinit(void){
1622ed47fef4SMatthias Ringwald     bnep_services = NULL;
1623ed47fef4SMatthias Ringwald     bnep_channels = NULL;
1624ed47fef4SMatthias Ringwald     bnep_security_level = 0;
162551e0db05SMatthias Ringwald }
162651e0db05SMatthias Ringwald 
16273deb3ec6SMatthias Ringwald void bnep_set_required_security_level(gap_security_level_t security_level)
16283deb3ec6SMatthias Ringwald {
16293deb3ec6SMatthias Ringwald     bnep_security_level = security_level;
16303deb3ec6SMatthias Ringwald }
16313deb3ec6SMatthias Ringwald 
16320c249750SMatthias 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)
16333deb3ec6SMatthias Ringwald {
16343deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
16353deb3ec6SMatthias Ringwald     log_info("BNEP_CONNECT addr %s", bd_addr_to_str(addr));
16363deb3ec6SMatthias Ringwald 
16373deb3ec6SMatthias Ringwald     channel = bnep_channel_create_for_addr(addr);
16383deb3ec6SMatthias Ringwald     if (channel == NULL) {
16393deb3ec6SMatthias Ringwald         return -1;
16403deb3ec6SMatthias Ringwald     }
16413deb3ec6SMatthias Ringwald 
16423deb3ec6SMatthias Ringwald     channel->uuid_source    = uuid_src;
16433deb3ec6SMatthias Ringwald     channel->uuid_dest      = uuid_dest;
16440c249750SMatthias Ringwald     channel->packet_handler = packet_handler;
16453deb3ec6SMatthias Ringwald 
164690a28bdeSMatthias Ringwald     uint8_t status = l2cap_create_channel(bnep_packet_handler, addr, l2cap_psm, l2cap_max_mtu(), NULL);
164790a28bdeSMatthias Ringwald     if (status){
164890a28bdeSMatthias Ringwald         return -1;
164990a28bdeSMatthias Ringwald     }
16503deb3ec6SMatthias Ringwald     return 0;
16513deb3ec6SMatthias Ringwald }
16523deb3ec6SMatthias Ringwald 
16533deb3ec6SMatthias Ringwald void bnep_disconnect(bd_addr_t addr)
16543deb3ec6SMatthias Ringwald {
16553deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
16563deb3ec6SMatthias Ringwald     log_info("BNEP_DISCONNECT");
16573deb3ec6SMatthias Ringwald 
16583deb3ec6SMatthias Ringwald     channel = bnep_channel_for_addr(addr);
16593deb3ec6SMatthias Ringwald 
16603deb3ec6SMatthias Ringwald     bnep_channel_finalize(channel);
16613deb3ec6SMatthias Ringwald }
16623deb3ec6SMatthias Ringwald 
16633deb3ec6SMatthias Ringwald 
16640c249750SMatthias Ringwald uint8_t bnep_register_service(btstack_packet_handler_t packet_handler, uint16_t service_uuid, uint16_t max_frame_size)
16653deb3ec6SMatthias Ringwald {
16663deb3ec6SMatthias Ringwald     log_info("BNEP_REGISTER_SERVICE mtu %d", max_frame_size);
16673deb3ec6SMatthias Ringwald 
16683deb3ec6SMatthias Ringwald     /* Check if we already registered a service */
16693deb3ec6SMatthias Ringwald     bnep_service_t * service = bnep_service_for_uuid(service_uuid);
16703deb3ec6SMatthias Ringwald     if (service) {
16710cc6429eSMatthias Ringwald         return BNEP_SERVICE_ALREADY_REGISTERED;
16723deb3ec6SMatthias Ringwald     }
16733deb3ec6SMatthias Ringwald 
16743deb3ec6SMatthias Ringwald     /* Only alow one the three service types: PANU, NAP, GN */
1675235946f1SMatthias Ringwald     if ((service_uuid != BLUETOOTH_SERVICE_CLASS_PANU) &&
1676235946f1SMatthias Ringwald         (service_uuid != BLUETOOTH_SERVICE_CLASS_NAP) &&
1677235946f1SMatthias Ringwald         (service_uuid != BLUETOOTH_SERVICE_CLASS_GN)) {
16783deb3ec6SMatthias Ringwald         log_info("BNEP_REGISTER_SERVICE: Invalid service UUID: %04x", service_uuid);
16790cc6429eSMatthias Ringwald         return BNEP_SERVICE_ALREADY_REGISTERED; // TODO: define own error
16803deb3ec6SMatthias Ringwald     }
16813deb3ec6SMatthias Ringwald 
16823deb3ec6SMatthias Ringwald     /* Allocate service memory */
16833deb3ec6SMatthias Ringwald     service = (bnep_service_t*) btstack_memory_bnep_service_get();
16843deb3ec6SMatthias Ringwald     if (!service) {
16850cc6429eSMatthias Ringwald         return BTSTACK_MEMORY_ALLOC_FAILED;
16863deb3ec6SMatthias Ringwald     }
16873deb3ec6SMatthias Ringwald 
16883deb3ec6SMatthias Ringwald     /* register with l2cap if not registered before, max MTU */
168984e3541eSMilanka Ringwald     l2cap_register_service(bnep_packet_handler, BLUETOOTH_PSM_BNEP, 0xffff, bnep_security_level);
16903deb3ec6SMatthias Ringwald 
16913deb3ec6SMatthias Ringwald     /* Setup the service struct */
16923deb3ec6SMatthias Ringwald     service->max_frame_size = max_frame_size;
16933deb3ec6SMatthias Ringwald     service->service_uuid    = service_uuid;
16940c249750SMatthias Ringwald     service->packet_handler = packet_handler;
16950c249750SMatthias Ringwald 
16963deb3ec6SMatthias Ringwald 
16973deb3ec6SMatthias Ringwald     /* Add to services list */
1698665d90f2SMatthias Ringwald     btstack_linked_list_add(&bnep_services, (btstack_linked_item_t *) service);
16993deb3ec6SMatthias Ringwald 
17000cc6429eSMatthias Ringwald     return 0;
17013deb3ec6SMatthias Ringwald }
17023deb3ec6SMatthias Ringwald 
17033deb3ec6SMatthias Ringwald void bnep_unregister_service(uint16_t service_uuid)
17043deb3ec6SMatthias Ringwald {
17053deb3ec6SMatthias Ringwald     log_info("BNEP_UNREGISTER_SERVICE #%04x", service_uuid);
17063deb3ec6SMatthias Ringwald 
17073deb3ec6SMatthias Ringwald     bnep_service_t *service = bnep_service_for_uuid(service_uuid);
17083deb3ec6SMatthias Ringwald     if (!service) {
17093deb3ec6SMatthias Ringwald         return;
17103deb3ec6SMatthias Ringwald     }
17113deb3ec6SMatthias Ringwald 
1712665d90f2SMatthias Ringwald     btstack_linked_list_remove(&bnep_services, (btstack_linked_item_t *) service);
17133deb3ec6SMatthias Ringwald     btstack_memory_bnep_service_free(service);
17143deb3ec6SMatthias Ringwald     service = NULL;
17153deb3ec6SMatthias Ringwald 
171684e3541eSMilanka Ringwald     l2cap_unregister_service(BLUETOOTH_PSM_BNEP);
17173deb3ec6SMatthias Ringwald }
17183deb3ec6SMatthias Ringwald 
1719