xref: /btstack/src/classic/bnep.c (revision 32b46fec1df77000b2e383d209074f4c2866ebdf)
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
233deb3ec6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
243deb3ec6SMatthias Ringwald  * RINGWALD 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 <stdio.h>
473deb3ec6SMatthias Ringwald #include <stdlib.h>
483deb3ec6SMatthias Ringwald #include <string.h> // memcpy
493deb3ec6SMatthias Ringwald #include <stdint.h>
503deb3ec6SMatthias Ringwald 
510e2df43fSMatthias Ringwald #include "bnep.h"
52235946f1SMatthias Ringwald #include "bluetooth_sdp.h"
530e2df43fSMatthias Ringwald #include "btstack_debug.h"
540e2df43fSMatthias Ringwald #include "btstack_event.h"
550e2df43fSMatthias Ringwald #include "btstack_memory.h"
56eb886013SMatthias Ringwald #include "btstack_util.h"
5759c6af15SMatthias Ringwald #include "classic/core.h"
583edc84c5SMatthias Ringwald #include "classic/sdp_util.h"
593deb3ec6SMatthias Ringwald #include "hci.h"
600e2df43fSMatthias Ringwald #include "hci_cmd.h"
613deb3ec6SMatthias Ringwald #include "hci_dump.h"
623deb3ec6SMatthias Ringwald #include "l2cap.h"
633deb3ec6SMatthias Ringwald 
643deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_TIMEOUT_MS 10000
653deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_MAX_RETRIES 1
663deb3ec6SMatthias Ringwald 
678f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_services = NULL;
688f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_channels = NULL;
693deb3ec6SMatthias Ringwald 
703deb3ec6SMatthias Ringwald static gap_security_level_t bnep_security_level;
713deb3ec6SMatthias Ringwald 
723deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid);
733deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel);
743deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout);
753deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event);
764e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t cid);
773deb3ec6SMatthias Ringwald static void bnep_emit_open_channel_complete(bnep_channel_t *channel, uint8_t status)
783deb3ec6SMatthias Ringwald {
790c249750SMatthias 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);
800c249750SMatthias Ringwald     if (!channel->packet_handler) return;
810c249750SMatthias Ringwald 
82*32b46fecSMatthias Ringwald     uint8_t event[3 + sizeof(bd_addr_t) + 4 * sizeof(uint16_t) + 2];
83423c667cSMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_OPENED;
843deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
853deb3ec6SMatthias Ringwald     event[2] = status;
86423c667cSMatthias Ringwald     little_endian_store_16(event, 3, channel->l2cap_cid);
87423c667cSMatthias Ringwald     little_endian_store_16(event, 5, channel->uuid_source);
88423c667cSMatthias Ringwald     little_endian_store_16(event, 7, channel->uuid_dest);
89423c667cSMatthias Ringwald     little_endian_store_16(event, 9, channel->max_frame_size);
90fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[11]);
91*32b46fecSMatthias Ringwald     little_endian_store_16(event, 17, channel->con_handle);
923deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
930c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
943deb3ec6SMatthias Ringwald }
953deb3ec6SMatthias Ringwald 
963deb3ec6SMatthias Ringwald static void bnep_emit_channel_timeout(bnep_channel_t *channel)
973deb3ec6SMatthias Ringwald {
980c249750SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_TIMEOUT bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler);
990c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1000c249750SMatthias Ringwald 
101423c667cSMatthias Ringwald     uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t) + sizeof(uint8_t)];
1023deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_TIMEOUT;
1033deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
104423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
105423c667cSMatthias Ringwald     little_endian_store_16(event, 4, channel->uuid_source);
106423c667cSMatthias Ringwald     little_endian_store_16(event, 6, channel->uuid_dest);
107fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[8]);
108423c667cSMatthias Ringwald     event[14] = channel->state;
1093deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
1100c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1113deb3ec6SMatthias Ringwald }
1123deb3ec6SMatthias Ringwald 
1133deb3ec6SMatthias Ringwald static void bnep_emit_channel_closed(bnep_channel_t *channel)
1143deb3ec6SMatthias Ringwald {
1150c249750SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_CLOSED bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler);
1160c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1170c249750SMatthias Ringwald 
118423c667cSMatthias Ringwald     uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t)];
1193deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_CLOSED;
1203deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
121423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
122423c667cSMatthias Ringwald     little_endian_store_16(event, 4, channel->uuid_source);
123423c667cSMatthias Ringwald     little_endian_store_16(event, 6, channel->uuid_dest);
124fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[8]);
1253deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
1260c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1273deb3ec6SMatthias Ringwald }
1283deb3ec6SMatthias Ringwald 
1293deb3ec6SMatthias Ringwald static void bnep_emit_ready_to_send(bnep_channel_t *channel)
1303deb3ec6SMatthias Ringwald {
1310c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1320c249750SMatthias Ringwald 
133423c667cSMatthias Ringwald     uint8_t event[4];
1342d4c8c04SMatthias Ringwald     event[0] = BNEP_EVENT_CAN_SEND_NOW;
1353deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
136423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
1373deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
1380c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1393deb3ec6SMatthias Ringwald }
1403deb3ec6SMatthias Ringwald 
1413deb3ec6SMatthias Ringwald /* Send BNEP connection request */
1423deb3ec6SMatthias Ringwald static int bnep_send_command_not_understood(bnep_channel_t *channel, uint8_t control_type)
1433deb3ec6SMatthias Ringwald {
1443deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
1453deb3ec6SMatthias Ringwald     uint16_t pos = 0;
1463deb3ec6SMatthias Ringwald     int      err = 0;
1473deb3ec6SMatthias Ringwald 
1483deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
1493deb3ec6SMatthias Ringwald         return -1; // TODO
1503deb3ec6SMatthias Ringwald     }
1513deb3ec6SMatthias Ringwald 
1523deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
1533deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
1543deb3ec6SMatthias Ringwald 
1553deb3ec6SMatthias Ringwald     /* Setup control packet type */
1563deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
1573deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD;
1583deb3ec6SMatthias Ringwald 
1593deb3ec6SMatthias Ringwald     /* Add not understood control type */
1603deb3ec6SMatthias Ringwald     bnep_out_buffer[pos++] = control_type;
1613deb3ec6SMatthias Ringwald 
1623deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
1633deb3ec6SMatthias Ringwald 
1643deb3ec6SMatthias Ringwald     if (err) {
1653deb3ec6SMatthias Ringwald         // TODO: Log error
1663deb3ec6SMatthias Ringwald     }
1673deb3ec6SMatthias Ringwald     return err;
1683deb3ec6SMatthias Ringwald }
1693deb3ec6SMatthias Ringwald 
1703deb3ec6SMatthias Ringwald 
1713deb3ec6SMatthias Ringwald /* Send BNEP connection request */
1723deb3ec6SMatthias Ringwald static int bnep_send_connection_request(bnep_channel_t *channel, uint16_t uuid_source, uint16_t uuid_dest)
1733deb3ec6SMatthias Ringwald {
1743deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
1753deb3ec6SMatthias Ringwald     uint16_t pos = 0;
1763deb3ec6SMatthias Ringwald     int      err = 0;
1773deb3ec6SMatthias Ringwald 
1783deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
1793deb3ec6SMatthias Ringwald         return -1; // TODO
1803deb3ec6SMatthias Ringwald     }
1813deb3ec6SMatthias Ringwald 
1823deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
1833deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
1843deb3ec6SMatthias Ringwald 
1853deb3ec6SMatthias Ringwald     /* Setup control packet type */
1863deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
1873deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST;
1883deb3ec6SMatthias Ringwald 
1893deb3ec6SMatthias Ringwald     /* Add UUID Size */
1903deb3ec6SMatthias Ringwald     bnep_out_buffer[pos++] = 2;
1913deb3ec6SMatthias Ringwald 
1923deb3ec6SMatthias Ringwald     /* Add dest and source UUID */
193f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, uuid_dest);
1943deb3ec6SMatthias Ringwald     pos += 2;
1953deb3ec6SMatthias Ringwald 
196f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, uuid_source);
1973deb3ec6SMatthias Ringwald     pos += 2;
1983deb3ec6SMatthias Ringwald 
1993deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2003deb3ec6SMatthias Ringwald 
2013deb3ec6SMatthias Ringwald     if (err) {
2023deb3ec6SMatthias Ringwald         // TODO: Log error
2033deb3ec6SMatthias Ringwald     }
2043deb3ec6SMatthias Ringwald     return err;
2053deb3ec6SMatthias Ringwald }
2063deb3ec6SMatthias Ringwald 
2073deb3ec6SMatthias Ringwald /* Send BNEP connection response */
2083deb3ec6SMatthias Ringwald static int bnep_send_connection_response(bnep_channel_t *channel, uint16_t response_code)
2093deb3ec6SMatthias Ringwald {
2103deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2113deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2123deb3ec6SMatthias Ringwald     int      err = 0;
2133deb3ec6SMatthias Ringwald 
2143deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2153deb3ec6SMatthias Ringwald         return -1; // TODO
2163deb3ec6SMatthias Ringwald     }
2173deb3ec6SMatthias Ringwald 
2183deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2193deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2203deb3ec6SMatthias Ringwald 
2213deb3ec6SMatthias Ringwald     /* Setup control packet type */
2223deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2233deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE;
2243deb3ec6SMatthias Ringwald 
2253deb3ec6SMatthias Ringwald     /* Add response code */
226f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
2273deb3ec6SMatthias Ringwald     pos += 2;
2283deb3ec6SMatthias Ringwald 
2293deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2303deb3ec6SMatthias Ringwald 
2313deb3ec6SMatthias Ringwald     if (err) {
2323deb3ec6SMatthias Ringwald         // TODO: Log error
2333deb3ec6SMatthias Ringwald     }
2343deb3ec6SMatthias Ringwald     return err;
2353deb3ec6SMatthias Ringwald }
2363deb3ec6SMatthias Ringwald 
2373deb3ec6SMatthias Ringwald /* Send BNEP filter net type set message */
2383deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_set(bnep_channel_t *channel, bnep_net_filter_t *filter, uint16_t len)
2393deb3ec6SMatthias Ringwald {
2403deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2413deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2423deb3ec6SMatthias Ringwald     int      err = 0;
2433deb3ec6SMatthias Ringwald     int      i;
2443deb3ec6SMatthias Ringwald 
2453deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2463deb3ec6SMatthias Ringwald         return -1;
2473deb3ec6SMatthias Ringwald     }
2483deb3ec6SMatthias Ringwald 
2493deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2503deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2513deb3ec6SMatthias Ringwald 
2523deb3ec6SMatthias Ringwald     /* Setup control packet type */
2533deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2543deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET;
2553deb3ec6SMatthias Ringwald 
256f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, len * 2 * 2);
2573deb3ec6SMatthias Ringwald     pos += 2;
2583deb3ec6SMatthias Ringwald 
2593deb3ec6SMatthias Ringwald     for (i = 0; i < len; i ++) {
260f8fbdce0SMatthias Ringwald         big_endian_store_16(bnep_out_buffer, pos, filter[i].range_start);
2613deb3ec6SMatthias Ringwald         pos += 2;
262f8fbdce0SMatthias Ringwald         big_endian_store_16(bnep_out_buffer, pos, filter[i].range_end);
2633deb3ec6SMatthias Ringwald         pos += 2;
2643deb3ec6SMatthias Ringwald     }
2653deb3ec6SMatthias Ringwald 
2663deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2673deb3ec6SMatthias Ringwald 
2683deb3ec6SMatthias Ringwald     if (err) {
2693deb3ec6SMatthias Ringwald         // TODO: Log error
2703deb3ec6SMatthias Ringwald     }
2713deb3ec6SMatthias Ringwald     return err;
2723deb3ec6SMatthias Ringwald }
2733deb3ec6SMatthias Ringwald 
2743deb3ec6SMatthias Ringwald /* Send BNEP filter net type response message */
2753deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_response(bnep_channel_t *channel, uint16_t response_code)
2763deb3ec6SMatthias Ringwald {
2773deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2783deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2793deb3ec6SMatthias Ringwald     int      err = 0;
2803deb3ec6SMatthias Ringwald 
2813deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2823deb3ec6SMatthias Ringwald         return -1;
2833deb3ec6SMatthias Ringwald     }
2843deb3ec6SMatthias Ringwald 
2853deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2863deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2873deb3ec6SMatthias Ringwald 
2883deb3ec6SMatthias Ringwald     /* Setup control packet type */
2893deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2903deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE;
2913deb3ec6SMatthias Ringwald 
2923deb3ec6SMatthias Ringwald     /* Add response code */
293f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
2943deb3ec6SMatthias Ringwald     pos += 2;
2953deb3ec6SMatthias Ringwald 
2963deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2973deb3ec6SMatthias Ringwald 
2983deb3ec6SMatthias Ringwald     if (err) {
2993deb3ec6SMatthias Ringwald         // TODO: Log error
3003deb3ec6SMatthias Ringwald     }
3013deb3ec6SMatthias Ringwald     return err;
3023deb3ec6SMatthias Ringwald }
3033deb3ec6SMatthias Ringwald 
3043deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address set message */
3053deb3ec6SMatthias Ringwald 
3063deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_set(bnep_channel_t *channel, bnep_multi_filter_t *filter, uint16_t len)
3073deb3ec6SMatthias Ringwald {
3083deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
3093deb3ec6SMatthias Ringwald     uint16_t pos = 0;
3103deb3ec6SMatthias Ringwald     int      err = 0;
3113deb3ec6SMatthias Ringwald     int      i;
3123deb3ec6SMatthias Ringwald 
3133deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3143deb3ec6SMatthias Ringwald         return -1;
3153deb3ec6SMatthias Ringwald     }
3163deb3ec6SMatthias Ringwald 
3173deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
3183deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
3193deb3ec6SMatthias Ringwald 
3203deb3ec6SMatthias Ringwald     /* Setup control packet type */
3213deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3223deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET;
3233deb3ec6SMatthias Ringwald 
324f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, len * 2 * ETHER_ADDR_LEN);
3253deb3ec6SMatthias Ringwald     pos += 2;
3263deb3ec6SMatthias Ringwald 
3273deb3ec6SMatthias Ringwald     for (i = 0; i < len; i ++) {
328058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_start);
3293deb3ec6SMatthias Ringwald         pos += ETHER_ADDR_LEN;
330058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_end);
3313deb3ec6SMatthias Ringwald         pos += ETHER_ADDR_LEN;
3323deb3ec6SMatthias Ringwald     }
3333deb3ec6SMatthias Ringwald 
3343deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
3353deb3ec6SMatthias Ringwald 
3363deb3ec6SMatthias Ringwald     if (err) {
3373deb3ec6SMatthias Ringwald         // TODO: Log error
3383deb3ec6SMatthias Ringwald     }
3393deb3ec6SMatthias Ringwald     return err;
3403deb3ec6SMatthias Ringwald }
3413deb3ec6SMatthias Ringwald 
3423deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address response message */
3433deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_response(bnep_channel_t *channel, uint16_t response_code)
3443deb3ec6SMatthias Ringwald {
3453deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
3463deb3ec6SMatthias Ringwald     uint16_t pos = 0;
3473deb3ec6SMatthias Ringwald     int      err = 0;
3483deb3ec6SMatthias Ringwald 
3493deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3503deb3ec6SMatthias Ringwald         return -1;
3513deb3ec6SMatthias Ringwald     }
3523deb3ec6SMatthias Ringwald 
3533deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
3543deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
3553deb3ec6SMatthias Ringwald 
3563deb3ec6SMatthias Ringwald     /* Setup control packet type */
3573deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3583deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE;
3593deb3ec6SMatthias Ringwald 
3603deb3ec6SMatthias Ringwald     /* Add response code */
361f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
3623deb3ec6SMatthias Ringwald     pos += 2;
3633deb3ec6SMatthias Ringwald 
3643deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
3653deb3ec6SMatthias Ringwald 
3663deb3ec6SMatthias Ringwald     if (err) {
3673deb3ec6SMatthias Ringwald         // TODO: Log error
3683deb3ec6SMatthias Ringwald     }
3693deb3ec6SMatthias Ringwald     return err;
3703deb3ec6SMatthias Ringwald }
3713deb3ec6SMatthias Ringwald 
3723deb3ec6SMatthias Ringwald int bnep_can_send_packet_now(uint16_t bnep_cid)
3733deb3ec6SMatthias Ringwald {
3743deb3ec6SMatthias Ringwald     bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
3753deb3ec6SMatthias Ringwald 
3763deb3ec6SMatthias Ringwald     if (!channel){
3773deb3ec6SMatthias Ringwald         log_error("bnep_can_send_packet_now cid 0x%02x doesn't exist!", bnep_cid);
3783deb3ec6SMatthias Ringwald         return 0;
3793deb3ec6SMatthias Ringwald     }
3803deb3ec6SMatthias Ringwald 
3810b9d7e78SMatthias Ringwald     return l2cap_can_send_packet_now(channel->l2cap_cid);
3821ed1a3bdSMatthias Ringwald }
3831ed1a3bdSMatthias Ringwald 
3841ed1a3bdSMatthias Ringwald void bnep_request_can_send_now_event(uint16_t bnep_cid)
3851ed1a3bdSMatthias Ringwald {
3861ed1a3bdSMatthias Ringwald     bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
3871ed1a3bdSMatthias Ringwald 
3881ed1a3bdSMatthias Ringwald     if (!channel){
3891ed1a3bdSMatthias Ringwald         log_error("bnep_request_can_send_now_event cid 0x%02x doesn't exist!", bnep_cid);
3901ed1a3bdSMatthias Ringwald         return;
3911ed1a3bdSMatthias Ringwald     }
3921ed1a3bdSMatthias Ringwald 
3931ed1a3bdSMatthias Ringwald     channel->waiting_for_can_send_now = 1;
3941ed1a3bdSMatthias Ringwald     l2cap_request_can_send_now_event(bnep_cid);
3953deb3ec6SMatthias Ringwald }
3963deb3ec6SMatthias Ringwald 
3973deb3ec6SMatthias Ringwald 
3983deb3ec6SMatthias Ringwald static int bnep_filter_protocol(bnep_channel_t *channel, uint16_t network_protocol_type)
3993deb3ec6SMatthias Ringwald {
4003deb3ec6SMatthias Ringwald 	int i;
4013deb3ec6SMatthias Ringwald 
4023deb3ec6SMatthias Ringwald     if (channel->net_filter_count == 0) {
4033deb3ec6SMatthias Ringwald         /* No filter set */
4043deb3ec6SMatthias Ringwald         return 1;
4053deb3ec6SMatthias Ringwald     }
4063deb3ec6SMatthias Ringwald 
4073deb3ec6SMatthias Ringwald     for (i = 0; i < channel->net_filter_count; i ++) {
4083deb3ec6SMatthias Ringwald         if ((network_protocol_type >= channel->net_filter[i].range_start) &&
4093deb3ec6SMatthias Ringwald             (network_protocol_type <= channel->net_filter[i].range_end)) {
4103deb3ec6SMatthias Ringwald             return 1;
4113deb3ec6SMatthias Ringwald         }
4123deb3ec6SMatthias Ringwald     }
4133deb3ec6SMatthias Ringwald 
4143deb3ec6SMatthias Ringwald     return 0;
4153deb3ec6SMatthias Ringwald }
4163deb3ec6SMatthias Ringwald 
4173deb3ec6SMatthias Ringwald static int bnep_filter_multicast(bnep_channel_t *channel, bd_addr_t addr_dest)
4183deb3ec6SMatthias Ringwald {
4193deb3ec6SMatthias Ringwald 	int i;
4203deb3ec6SMatthias Ringwald 
4213deb3ec6SMatthias Ringwald     /* Check if the multicast flag is set int the destination address */
4223deb3ec6SMatthias Ringwald 	if ((addr_dest[0] & 0x01) == 0x00) {
4233deb3ec6SMatthias Ringwald         /* Not a multicast frame, do not apply filtering and send it in any case */
4243deb3ec6SMatthias Ringwald 		return 1;
4253deb3ec6SMatthias Ringwald     }
4263deb3ec6SMatthias Ringwald 
4273deb3ec6SMatthias Ringwald     if (channel->multicast_filter_count == 0) {
4283deb3ec6SMatthias Ringwald         /* No filter set */
4293deb3ec6SMatthias Ringwald         return 1;
4303deb3ec6SMatthias Ringwald     }
4313deb3ec6SMatthias Ringwald 
4323deb3ec6SMatthias Ringwald 	for (i = 0; i < channel->multicast_filter_count; i ++) {
4333deb3ec6SMatthias Ringwald 		if ((memcmp(addr_dest, channel->multicast_filter[i].addr_start, sizeof(bd_addr_t)) >= 0) &&
4343deb3ec6SMatthias Ringwald 		    (memcmp(addr_dest, channel->multicast_filter[i].addr_end, sizeof(bd_addr_t)) <= 0)) {
4353deb3ec6SMatthias Ringwald 			return 1;
4363deb3ec6SMatthias Ringwald         }
4373deb3ec6SMatthias Ringwald 	}
4383deb3ec6SMatthias Ringwald 
4393deb3ec6SMatthias Ringwald 	return 0;
4403deb3ec6SMatthias Ringwald }
4413deb3ec6SMatthias Ringwald 
4423deb3ec6SMatthias Ringwald 
4433deb3ec6SMatthias Ringwald /* Send BNEP ethernet packet */
4443deb3ec6SMatthias Ringwald int bnep_send(uint16_t bnep_cid, uint8_t *packet, uint16_t len)
4453deb3ec6SMatthias Ringwald {
4463deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
4473deb3ec6SMatthias Ringwald     uint8_t        *bnep_out_buffer = NULL;
4483deb3ec6SMatthias Ringwald     uint16_t        pos = 0;
4493deb3ec6SMatthias Ringwald     uint16_t        pos_out = 0;
4503deb3ec6SMatthias Ringwald     uint16_t        payload_len;
4513deb3ec6SMatthias Ringwald     int             err = 0;
4523deb3ec6SMatthias Ringwald     int             has_source;
4533deb3ec6SMatthias Ringwald     int             has_dest;
4543deb3ec6SMatthias Ringwald 
4553deb3ec6SMatthias Ringwald     bd_addr_t       addr_dest;
4563deb3ec6SMatthias Ringwald     bd_addr_t       addr_source;
4573deb3ec6SMatthias Ringwald     uint16_t        network_protocol_type;
4583deb3ec6SMatthias Ringwald 
4593deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
4603deb3ec6SMatthias Ringwald     if (channel == NULL) {
4613deb3ec6SMatthias Ringwald         log_error("bnep_send cid 0x%02x doesn't exist!", bnep_cid);
4623deb3ec6SMatthias Ringwald         return 1;
4633deb3ec6SMatthias Ringwald     }
4643deb3ec6SMatthias Ringwald 
4653deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
4663deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
4673deb3ec6SMatthias Ringwald     }
4683deb3ec6SMatthias Ringwald 
4693deb3ec6SMatthias Ringwald     /* Check for free ACL buffers */
4703deb3ec6SMatthias Ringwald     if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
4713deb3ec6SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
4723deb3ec6SMatthias Ringwald     }
4733deb3ec6SMatthias Ringwald 
4743deb3ec6SMatthias Ringwald     /* Extract destination and source address from the ethernet packet */
4753deb3ec6SMatthias Ringwald     pos = 0;
476058e3d6bSMatthias Ringwald     bd_addr_copy(addr_dest, &packet[pos]);
4773deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
478058e3d6bSMatthias Ringwald     bd_addr_copy(addr_source, &packet[pos]);
4793deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
480f8fbdce0SMatthias Ringwald     network_protocol_type = big_endian_read_16(packet, pos);
4813deb3ec6SMatthias Ringwald     pos += sizeof(uint16_t);
4823deb3ec6SMatthias Ringwald 
4833deb3ec6SMatthias Ringwald     payload_len = len - pos;
4843deb3ec6SMatthias Ringwald 
4853deb3ec6SMatthias Ringwald 	if (network_protocol_type == ETHERTYPE_VLAN) {	/* IEEE 802.1Q tag header */
4863deb3ec6SMatthias Ringwald 		if (payload_len < 4) {
4873deb3ec6SMatthias Ringwald             /* Omit this packet */
4883deb3ec6SMatthias Ringwald 			return 0;
4893deb3ec6SMatthias Ringwald         }
4903deb3ec6SMatthias Ringwald         /* The "real" network protocol type is 4 bytes ahead in a VLAN packet */
491f8fbdce0SMatthias Ringwald 		network_protocol_type = big_endian_read_16(packet, pos + 2);
4923deb3ec6SMatthias Ringwald 	}
4933deb3ec6SMatthias Ringwald 
4943deb3ec6SMatthias Ringwald     /* Check network protocol and multicast filters before sending */
4953deb3ec6SMatthias Ringwald     if (!bnep_filter_protocol(channel, network_protocol_type) ||
4963deb3ec6SMatthias Ringwald         !bnep_filter_multicast(channel, addr_dest)) {
4973deb3ec6SMatthias Ringwald         /* Packet did not pass filter... */
4983deb3ec6SMatthias Ringwald         if ((network_protocol_type == ETHERTYPE_VLAN) &&
4993deb3ec6SMatthias Ringwald             (payload_len >= 4)) {
5003deb3ec6SMatthias Ringwald             /* The packet has been tagged as a with IEE 802.1Q tag and has been filtered out.
5013deb3ec6SMatthias Ringwald                According to the spec the IEE802.1Q tag header shall be sended without ethernet payload.
5023deb3ec6SMatthias Ringwald                So limit the payload_len to 4.
5033deb3ec6SMatthias Ringwald              */
5043deb3ec6SMatthias Ringwald             payload_len = 4;
5053deb3ec6SMatthias Ringwald         } else {
5063deb3ec6SMatthias Ringwald             /* Packet is not tagged with IEE802.1Q header and was filtered out. Omit this packet */
5073deb3ec6SMatthias Ringwald             return 0;
5083deb3ec6SMatthias Ringwald         }
5093deb3ec6SMatthias Ringwald     }
5103deb3ec6SMatthias Ringwald 
5113deb3ec6SMatthias Ringwald     /* Reserve l2cap packet buffer */
5123deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
5133deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
5143deb3ec6SMatthias Ringwald 
5153deb3ec6SMatthias Ringwald     /* Check if source address is the same as our local address and if the
5163deb3ec6SMatthias Ringwald        destination address is the same as the remote addr. Maybe we can use
5173deb3ec6SMatthias Ringwald        the compressed data format
5183deb3ec6SMatthias Ringwald      */
5193deb3ec6SMatthias Ringwald     has_source = (memcmp(addr_source, channel->local_addr, ETHER_ADDR_LEN) != 0);
5203deb3ec6SMatthias Ringwald     has_dest = (memcmp(addr_dest, channel->remote_addr, ETHER_ADDR_LEN) != 0);
5213deb3ec6SMatthias Ringwald 
5223deb3ec6SMatthias Ringwald     /* Check for MTU limits */
5233deb3ec6SMatthias Ringwald     if (payload_len > channel->max_frame_size) {
5243deb3ec6SMatthias Ringwald         log_error("bnep_send: Max frame size (%d) exceeded: %d", channel->max_frame_size, payload_len);
5253deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
5263deb3ec6SMatthias Ringwald     }
5273deb3ec6SMatthias Ringwald 
5283deb3ec6SMatthias Ringwald     /* Fill in the package type depending on the given source and destination address */
5293deb3ec6SMatthias Ringwald     if (has_source && has_dest) {
5303deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_GENERAL_ETHERNET;
5313deb3ec6SMatthias Ringwald     } else
5323deb3ec6SMatthias Ringwald     if (has_source && !has_dest) {
5333deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY;
5343deb3ec6SMatthias Ringwald     } else
5353deb3ec6SMatthias Ringwald     if (!has_source && has_dest) {
5363deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY;
5373deb3ec6SMatthias Ringwald     } else {
5383deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET;
5393deb3ec6SMatthias Ringwald     }
5403deb3ec6SMatthias Ringwald 
5413deb3ec6SMatthias Ringwald     /* Add the destination address if needed */
5423deb3ec6SMatthias Ringwald     if (has_dest) {
543058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos_out, addr_dest);
5443deb3ec6SMatthias Ringwald         pos_out += sizeof(bd_addr_t);
5453deb3ec6SMatthias Ringwald     }
5463deb3ec6SMatthias Ringwald 
5473deb3ec6SMatthias Ringwald     /* Add the source address if needed */
5483deb3ec6SMatthias Ringwald     if (has_source) {
549058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos_out, addr_source);
5503deb3ec6SMatthias Ringwald         pos_out += sizeof(bd_addr_t);
5513deb3ec6SMatthias Ringwald     }
5523deb3ec6SMatthias Ringwald 
5533deb3ec6SMatthias Ringwald     /* Add protocol type */
554f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos_out, network_protocol_type);
5553deb3ec6SMatthias Ringwald     pos_out += 2;
5563deb3ec6SMatthias Ringwald 
5573deb3ec6SMatthias Ringwald     /* TODO: Add extension headers, if we may support them at a later stage */
5583deb3ec6SMatthias Ringwald     /* Add the payload and then send out the package */
5593deb3ec6SMatthias Ringwald     memcpy(bnep_out_buffer + pos_out, packet + pos, payload_len);
5603deb3ec6SMatthias Ringwald     pos_out += payload_len;
5613deb3ec6SMatthias Ringwald 
5623deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos_out);
5633deb3ec6SMatthias Ringwald 
5643deb3ec6SMatthias Ringwald     if (err) {
5653deb3ec6SMatthias Ringwald         log_error("bnep_send: error %d", err);
5663deb3ec6SMatthias Ringwald     }
5673deb3ec6SMatthias Ringwald     return err;
5683deb3ec6SMatthias Ringwald }
5693deb3ec6SMatthias Ringwald 
5703deb3ec6SMatthias Ringwald 
5713deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
5723deb3ec6SMatthias Ringwald int bnep_set_net_type_filter(uint16_t bnep_cid, bnep_net_filter_t *filter, uint16_t len)
5733deb3ec6SMatthias Ringwald {
5743deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
5753deb3ec6SMatthias Ringwald 
5763deb3ec6SMatthias Ringwald     if (filter == NULL) {
5773deb3ec6SMatthias Ringwald         return -1;
5783deb3ec6SMatthias Ringwald     }
5793deb3ec6SMatthias Ringwald 
5803deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
5813deb3ec6SMatthias Ringwald     if (channel == NULL) {
5823deb3ec6SMatthias Ringwald         log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
5833deb3ec6SMatthias Ringwald         return 1;
5843deb3ec6SMatthias Ringwald     }
5853deb3ec6SMatthias Ringwald 
5863deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
5873deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
5883deb3ec6SMatthias Ringwald     }
5893deb3ec6SMatthias Ringwald 
5903deb3ec6SMatthias Ringwald     if (len > MAX_BNEP_NETFILTER_OUT) {
5913deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
5923deb3ec6SMatthias Ringwald     }
5933deb3ec6SMatthias Ringwald 
5943deb3ec6SMatthias Ringwald     channel->net_filter_out = filter;
5953deb3ec6SMatthias Ringwald     channel->net_filter_out_count = len;
5963deb3ec6SMatthias Ringwald 
5974e366553SMatthias Ringwald     /* Set flag to send out the network protocol type filter set request */
5983deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
5994e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
6003deb3ec6SMatthias Ringwald 
6013deb3ec6SMatthias Ringwald     return 0;
6023deb3ec6SMatthias Ringwald }
6033deb3ec6SMatthias Ringwald 
6043deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
6053deb3ec6SMatthias Ringwald int bnep_set_multicast_filter(uint16_t bnep_cid,  bnep_multi_filter_t *filter, uint16_t len)
6063deb3ec6SMatthias Ringwald {
6073deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
6083deb3ec6SMatthias Ringwald 
6093deb3ec6SMatthias Ringwald     if (filter == NULL) {
6103deb3ec6SMatthias Ringwald         return -1;
6113deb3ec6SMatthias Ringwald     }
6123deb3ec6SMatthias Ringwald 
6133deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
6143deb3ec6SMatthias Ringwald     if (channel == NULL) {
6153deb3ec6SMatthias Ringwald         log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
6163deb3ec6SMatthias Ringwald         return 1;
6173deb3ec6SMatthias Ringwald     }
6183deb3ec6SMatthias Ringwald 
6193deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
6203deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
6213deb3ec6SMatthias Ringwald     }
6223deb3ec6SMatthias Ringwald 
62366b1fcb3SMatthias Ringwald     if (len > MAX_BNEP_MULTICAST_FILTER_OUT) {
6243deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
6253deb3ec6SMatthias Ringwald     }
6263deb3ec6SMatthias Ringwald 
6273deb3ec6SMatthias Ringwald     channel->multicast_filter_out = filter;
6283deb3ec6SMatthias Ringwald     channel->multicast_filter_out_count = len;
6293deb3ec6SMatthias Ringwald 
6304e366553SMatthias Ringwald     /* Set flag to send out the multicast filter set request */
6313deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
6324e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
6333deb3ec6SMatthias Ringwald 
6343deb3ec6SMatthias Ringwald     return 0;
6353deb3ec6SMatthias Ringwald }
6363deb3ec6SMatthias Ringwald 
6373deb3ec6SMatthias Ringwald /* BNEP timeout timer helper function */
638ec820d77SMatthias Ringwald static void bnep_channel_timer_handler(btstack_timer_source_t *timer)
6393deb3ec6SMatthias Ringwald {
64091a977e8SMatthias Ringwald     bnep_channel_t *channel = btstack_run_loop_get_timer_context(timer);
6413deb3ec6SMatthias Ringwald     // retry send setup connection at least one time
6423deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE){
6433deb3ec6SMatthias Ringwald         if (channel->retry_count < BNEP_CONNECTION_MAX_RETRIES){
6443deb3ec6SMatthias Ringwald             channel->retry_count++;
6453deb3ec6SMatthias Ringwald             bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
6463deb3ec6SMatthias Ringwald             bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
6474e366553SMatthias Ringwald             l2cap_request_can_send_now_event(channel->l2cap_cid);
6483deb3ec6SMatthias Ringwald             return;
6493deb3ec6SMatthias Ringwald         }
6503deb3ec6SMatthias Ringwald     }
6513deb3ec6SMatthias Ringwald 
6523deb3ec6SMatthias Ringwald     log_info( "bnep_channel_timeout_handler callback: shutting down connection!");
6533deb3ec6SMatthias Ringwald     bnep_emit_channel_timeout(channel);
6543deb3ec6SMatthias Ringwald     bnep_channel_finalize(channel);
6553deb3ec6SMatthias Ringwald }
6563deb3ec6SMatthias Ringwald 
6573deb3ec6SMatthias Ringwald 
6583deb3ec6SMatthias Ringwald static void bnep_channel_stop_timer(bnep_channel_t *channel)
6593deb3ec6SMatthias Ringwald {
6603deb3ec6SMatthias Ringwald     if (channel->timer_active) {
661528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&channel->timer);
6623deb3ec6SMatthias Ringwald         channel->timer_active = 0;
6633deb3ec6SMatthias Ringwald     }
6643deb3ec6SMatthias Ringwald }
6653deb3ec6SMatthias Ringwald 
6663deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout)
6673deb3ec6SMatthias Ringwald {
6683deb3ec6SMatthias Ringwald     /* Stop any eventually running timeout timer */
6693deb3ec6SMatthias Ringwald     bnep_channel_stop_timer(channel);
6703deb3ec6SMatthias Ringwald 
6713deb3ec6SMatthias Ringwald     /* Start bnep channel timeout check timer */
672528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&channel->timer, timeout);
67391a977e8SMatthias Ringwald     btstack_run_loop_set_timer_handler(&channel->timer, bnep_channel_timer_handler);
67491a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&channel->timer, channel);
675528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&channel->timer);
6763deb3ec6SMatthias Ringwald     channel->timer_active = 1;
6773deb3ec6SMatthias Ringwald }
6783deb3ec6SMatthias Ringwald 
6793deb3ec6SMatthias Ringwald /* BNEP statemachine functions */
6803deb3ec6SMatthias Ringwald 
6813deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
6823deb3ec6SMatthias Ringwald     channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var | event);
6833deb3ec6SMatthias Ringwald }
6843deb3ec6SMatthias Ringwald inline static void bnep_channel_state_remove(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
6853deb3ec6SMatthias Ringwald     channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var & ~event);
6863deb3ec6SMatthias Ringwald }
6873deb3ec6SMatthias Ringwald 
6883deb3ec6SMatthias Ringwald static uint16_t bnep_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
6893deb3ec6SMatthias Ringwald 
6903deb3ec6SMatthias Ringwald     /* Assume a standard BNEP header, containing BNEP Type (1 Byte), dest and
6913deb3ec6SMatthias Ringwald        source address (6 bytes each) and networking protocol type (2 bytes)
6923deb3ec6SMatthias Ringwald      */
6933deb3ec6SMatthias Ringwald     uint16_t max_frame_size = l2cap_mtu - 15; // 15 bytes BNEP header
6943deb3ec6SMatthias Ringwald 
6953deb3ec6SMatthias Ringwald     log_info("bnep_max_frame_size_for_l2cap_mtu:  %u -> %u", l2cap_mtu, max_frame_size);
6963deb3ec6SMatthias Ringwald     return max_frame_size;
6973deb3ec6SMatthias Ringwald }
6983deb3ec6SMatthias Ringwald 
6993deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_create_for_addr(bd_addr_t addr)
7003deb3ec6SMatthias Ringwald {
7013deb3ec6SMatthias Ringwald     /* Allocate new channel structure */
7023deb3ec6SMatthias Ringwald     bnep_channel_t *channel = btstack_memory_bnep_channel_get();
7033deb3ec6SMatthias Ringwald     if (!channel) {
7043deb3ec6SMatthias Ringwald         return NULL;
7053deb3ec6SMatthias Ringwald     }
7063deb3ec6SMatthias Ringwald 
7073deb3ec6SMatthias Ringwald     channel->state = BNEP_CHANNEL_STATE_CLOSED;
7083deb3ec6SMatthias Ringwald     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
70973988a59SMatthias Ringwald     bd_addr_copy(channel->remote_addr, addr);
71015a95bd5SMatthias Ringwald     gap_local_bd_addr(channel->local_addr);
7113deb3ec6SMatthias Ringwald 
7123deb3ec6SMatthias Ringwald     channel->net_filter_count = 0;
7133deb3ec6SMatthias Ringwald     channel->multicast_filter_count = 0;
7143deb3ec6SMatthias Ringwald     channel->retry_count = 0;
7153deb3ec6SMatthias Ringwald 
7163deb3ec6SMatthias Ringwald     /* Finally add it to the channel list */
717665d90f2SMatthias Ringwald     btstack_linked_list_add(&bnep_channels, (btstack_linked_item_t *) channel);
7183deb3ec6SMatthias Ringwald 
7193deb3ec6SMatthias Ringwald     return channel;
7203deb3ec6SMatthias Ringwald }
7213deb3ec6SMatthias Ringwald 
7223deb3ec6SMatthias Ringwald static bnep_channel_t* bnep_channel_for_addr(bd_addr_t addr)
7233deb3ec6SMatthias Ringwald {
724665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
725665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){
7263deb3ec6SMatthias Ringwald         bnep_channel_t *channel = ((bnep_channel_t *) it);
727058e3d6bSMatthias Ringwald         if (bd_addr_cmp(addr, channel->remote_addr) == 0) {
7283deb3ec6SMatthias Ringwald             return channel;
7293deb3ec6SMatthias Ringwald         }
7303deb3ec6SMatthias Ringwald     }
7313deb3ec6SMatthias Ringwald     return NULL;
7323deb3ec6SMatthias Ringwald }
7333deb3ec6SMatthias Ringwald 
7343deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid)
7353deb3ec6SMatthias Ringwald {
736665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
737665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){
7383deb3ec6SMatthias Ringwald         bnep_channel_t *channel = ((bnep_channel_t *) it);
7393deb3ec6SMatthias Ringwald         if (channel->l2cap_cid == l2cap_cid) {
7403deb3ec6SMatthias Ringwald             return channel;
7413deb3ec6SMatthias Ringwald         }
7423deb3ec6SMatthias Ringwald     }
7433deb3ec6SMatthias Ringwald     return NULL;
7443deb3ec6SMatthias Ringwald }
7453deb3ec6SMatthias Ringwald 
7463deb3ec6SMatthias Ringwald static bnep_service_t * bnep_service_for_uuid(uint16_t uuid)
7473deb3ec6SMatthias Ringwald {
748665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
749665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_services; it ; it = it->next){
7503deb3ec6SMatthias Ringwald         bnep_service_t * service = ((bnep_service_t *) it);
7513deb3ec6SMatthias Ringwald         if ( service->service_uuid == uuid){
7523deb3ec6SMatthias Ringwald             return service;
7533deb3ec6SMatthias Ringwald         }
7543deb3ec6SMatthias Ringwald     }
7553deb3ec6SMatthias Ringwald     return NULL;
7563deb3ec6SMatthias Ringwald }
7573deb3ec6SMatthias Ringwald 
7583deb3ec6SMatthias Ringwald static void bnep_channel_free(bnep_channel_t *channel)
7593deb3ec6SMatthias Ringwald {
760665d90f2SMatthias Ringwald     btstack_linked_list_remove( &bnep_channels, (btstack_linked_item_t *) channel);
7613deb3ec6SMatthias Ringwald     btstack_memory_bnep_channel_free(channel);
7623deb3ec6SMatthias Ringwald }
7633deb3ec6SMatthias Ringwald 
7643deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel)
7653deb3ec6SMatthias Ringwald {
7663deb3ec6SMatthias Ringwald     uint16_t l2cap_cid;
7673deb3ec6SMatthias Ringwald 
7683deb3ec6SMatthias Ringwald     /* Inform application about closed channel */
7693deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
7703deb3ec6SMatthias Ringwald         bnep_emit_channel_closed(channel);
7713deb3ec6SMatthias Ringwald     }
7723deb3ec6SMatthias Ringwald 
7733deb3ec6SMatthias Ringwald     l2cap_cid = channel->l2cap_cid;
7743deb3ec6SMatthias Ringwald 
7753deb3ec6SMatthias Ringwald     /* Stop any eventually running timer */
7763deb3ec6SMatthias Ringwald     bnep_channel_stop_timer(channel);
7773deb3ec6SMatthias Ringwald 
7783deb3ec6SMatthias Ringwald     /* Free ressources and then close the l2cap channel */
7793deb3ec6SMatthias Ringwald     bnep_channel_free(channel);
780ce8f182eSMatthias Ringwald     l2cap_disconnect(l2cap_cid, 0x13);
7813deb3ec6SMatthias Ringwald }
7823deb3ec6SMatthias Ringwald 
7833deb3ec6SMatthias Ringwald static int bnep_handle_connection_request(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
7843deb3ec6SMatthias Ringwald {
7853deb3ec6SMatthias Ringwald     uint16_t uuid_size;
786bb015fa7SMatthias Ringwald     uint16_t uuid_offset = 0; // avoid "may be unitialized when used" in clang
7873deb3ec6SMatthias Ringwald     uuid_size = packet[1];
7883deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_SETUP_SUCCESS;
7893deb3ec6SMatthias Ringwald     bnep_service_t * service;
7903deb3ec6SMatthias Ringwald 
7913deb3ec6SMatthias Ringwald     /* Sanity check packet size */
7923deb3ec6SMatthias Ringwald     if (size < 1 + 1 + 2 * uuid_size) {
7933deb3ec6SMatthias Ringwald         return 0;
7943deb3ec6SMatthias Ringwald     }
7953deb3ec6SMatthias Ringwald 
7963deb3ec6SMatthias Ringwald     if ((channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
7973deb3ec6SMatthias Ringwald         (channel->state != BNEP_CHANNEL_STATE_CONNECTED)) {
7983deb3ec6SMatthias Ringwald         /* Ignore a connection request if not waiting for or still connected */
7993deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_REQUEST: ignored in state %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
8003deb3ec6SMatthias Ringwald         return 0;
8013deb3ec6SMatthias Ringwald     }
8023deb3ec6SMatthias Ringwald 
8033deb3ec6SMatthias Ringwald      /* Extract source and destination UUID and convert them to UUID16 format */
8043deb3ec6SMatthias Ringwald     switch (uuid_size) {
8053deb3ec6SMatthias Ringwald         case 2:  /* UUID16  */
8063deb3ec6SMatthias Ringwald             uuid_offset = 0;
8073deb3ec6SMatthias Ringwald             break;
8083deb3ec6SMatthias Ringwald         case 4:  /* UUID32  */
8093deb3ec6SMatthias Ringwald         case 16: /* UUID128 */
8103deb3ec6SMatthias Ringwald             uuid_offset = 2;
8113deb3ec6SMatthias Ringwald             break;
8123deb3ec6SMatthias Ringwald         default:
8133deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid UUID size %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
8143deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_SERVICE_UUID_SIZE;
8153deb3ec6SMatthias Ringwald             break;
8163deb3ec6SMatthias Ringwald     }
8173deb3ec6SMatthias Ringwald 
8183deb3ec6SMatthias Ringwald     /* Check source and destination UUIDs for valid combinations */
8193deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_SETUP_SUCCESS) {
820f8fbdce0SMatthias Ringwald         channel->uuid_dest = big_endian_read_16(packet, 2 + uuid_offset);
821f8fbdce0SMatthias Ringwald         channel->uuid_source = big_endian_read_16(packet, 2 + uuid_offset + uuid_size);
8223deb3ec6SMatthias Ringwald 
823235946f1SMatthias Ringwald         if ((channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU) &&
824235946f1SMatthias Ringwald             (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_NAP) &&
825235946f1SMatthias Ringwald             (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_GN)) {
8263deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid destination service UUID: %04x", channel->uuid_dest);
8273deb3ec6SMatthias Ringwald             channel->uuid_dest = 0;
8283deb3ec6SMatthias Ringwald         }
829235946f1SMatthias Ringwald         if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) &&
830235946f1SMatthias Ringwald             (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_NAP) &&
831235946f1SMatthias Ringwald             (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_GN)) {
8323deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid source service UUID: %04x", channel->uuid_source);
8333deb3ec6SMatthias Ringwald             channel->uuid_source = 0;
8343deb3ec6SMatthias Ringwald         }
8353deb3ec6SMatthias Ringwald 
8363deb3ec6SMatthias Ringwald         /* Check if we have registered a service for the requested destination UUID */
8373deb3ec6SMatthias Ringwald         service = bnep_service_for_uuid(channel->uuid_dest);
8383deb3ec6SMatthias Ringwald         if (service == NULL) {
8393deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID;
8400c249750SMatthias Ringwald         } else {
8410c249750SMatthias Ringwald             // use packet handler for service
8420c249750SMatthias Ringwald             channel->packet_handler = service->packet_handler;
8430c249750SMatthias Ringwald 
844235946f1SMatthias Ringwald             if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) && (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU)) {
8453deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID;
8463deb3ec6SMatthias Ringwald             }
8473deb3ec6SMatthias Ringwald         }
8480c249750SMatthias Ringwald     }
8493deb3ec6SMatthias Ringwald 
8503deb3ec6SMatthias Ringwald     /* Set flag to send out the connection response on next statemachine cycle */
8513deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
8523deb3ec6SMatthias Ringwald     channel->response_code = response_code;
8534e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
8543deb3ec6SMatthias Ringwald 
8553deb3ec6SMatthias Ringwald     /* Return the number of processed package bytes = BNEP Type, BNEP Control Type, UUID-Size + 2 * UUID */
8563deb3ec6SMatthias Ringwald     return 1 + 1 + 2 * uuid_size;
8573deb3ec6SMatthias Ringwald }
8583deb3ec6SMatthias Ringwald 
8593deb3ec6SMatthias Ringwald static int bnep_handle_connection_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
8603deb3ec6SMatthias Ringwald {
8613deb3ec6SMatthias Ringwald     uint16_t response_code;
8623deb3ec6SMatthias Ringwald 
8633deb3ec6SMatthias Ringwald     /* Sanity check packet size */
8643deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
8653deb3ec6SMatthias Ringwald         return 0;
8663deb3ec6SMatthias Ringwald     }
8673deb3ec6SMatthias Ringwald 
8683deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE) {
8693deb3ec6SMatthias Ringwald         /* Ignore a connection response in any state but WAIT_FOR_CONNECTION_RESPONSE */
8703deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_RESPONSE: Ignored in channel state %d", channel->state);
8713deb3ec6SMatthias Ringwald         return 1 + 2;
8723deb3ec6SMatthias Ringwald     }
8733deb3ec6SMatthias Ringwald 
874f8fbdce0SMatthias Ringwald     response_code = big_endian_read_16(packet, 1);
8753deb3ec6SMatthias Ringwald 
8763deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_SETUP_SUCCESS) {
8773deb3ec6SMatthias Ringwald         log_info("BNEP_CONNECTION_RESPONSE: Channel established to %s", bd_addr_to_str(channel->remote_addr));
8783deb3ec6SMatthias Ringwald         channel->state = BNEP_CHANNEL_STATE_CONNECTED;
8793deb3ec6SMatthias Ringwald         /* Stop timeout timer! */
8803deb3ec6SMatthias Ringwald         bnep_channel_stop_timer(channel);
8813deb3ec6SMatthias Ringwald         bnep_emit_open_channel_complete(channel, 0);
8823deb3ec6SMatthias Ringwald     } else {
8833deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_RESPONSE: Connection to %s failed. Err: %d", bd_addr_to_str(channel->remote_addr), response_code);
8843deb3ec6SMatthias Ringwald         bnep_channel_finalize(channel);
8853deb3ec6SMatthias Ringwald     }
8863deb3ec6SMatthias Ringwald     return 1 + 2;
8873deb3ec6SMatthias Ringwald }
8883deb3ec6SMatthias Ringwald 
8893deb3ec6SMatthias Ringwald static int bnep_can_handle_extensions(bnep_channel_t * channel){
8903deb3ec6SMatthias Ringwald     /* Extension are primarily handled in CONNECTED state */
8913deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) return 1;
8923deb3ec6SMatthias Ringwald     /* and if we've received connection request, but haven't sent the reponse yet. */
8933deb3ec6SMatthias Ringwald     if ((channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
8943deb3ec6SMatthias Ringwald         (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE)) {
8953deb3ec6SMatthias Ringwald         return 1;
8963deb3ec6SMatthias Ringwald     }
8973deb3ec6SMatthias Ringwald     return 0;
8983deb3ec6SMatthias Ringwald }
8993deb3ec6SMatthias Ringwald 
9003deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9013deb3ec6SMatthias Ringwald {
9023deb3ec6SMatthias Ringwald     uint16_t list_length;
9033deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
9043deb3ec6SMatthias Ringwald 
9053deb3ec6SMatthias Ringwald     /* Sanity check packet size */
9063deb3ec6SMatthias Ringwald     if (size < 3) {
9073deb3ec6SMatthias Ringwald         return 0;
9083deb3ec6SMatthias Ringwald     }
9093deb3ec6SMatthias Ringwald 
910f8fbdce0SMatthias Ringwald     list_length = big_endian_read_16(packet, 1);
9113deb3ec6SMatthias Ringwald     /* Sanity check packet size again with known package size */
9123deb3ec6SMatthias Ringwald     if (size < 3 + list_length) {
9133deb3ec6SMatthias Ringwald         return 0;
9143deb3ec6SMatthias Ringwald     }
9153deb3ec6SMatthias Ringwald 
9163deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
9173deb3ec6SMatthias Ringwald         log_error("BNEP_FILTER_NET_TYPE_SET: Ignored in channel state %d", channel->state);
9183deb3ec6SMatthias Ringwald         return 3 + list_length;
9193deb3ec6SMatthias Ringwald     }
9203deb3ec6SMatthias Ringwald 
9213deb3ec6SMatthias Ringwald     /* Check if we have enough space for more filters */
9223deb3ec6SMatthias Ringwald     if ((list_length / (2*2)) > MAX_BNEP_NETFILTER) {
9233deb3ec6SMatthias Ringwald         log_info("BNEP_FILTER_NET_TYPE_SET: Too many filter");
9243deb3ec6SMatthias Ringwald         response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
9253deb3ec6SMatthias Ringwald     } else {
9263deb3ec6SMatthias Ringwald         int i;
9273deb3ec6SMatthias Ringwald         channel->net_filter_count = 0;
9283deb3ec6SMatthias Ringwald         /* There is still enough space, copy the filters to our filter list */
929ef907034SMatthias Ringwald         /* There is still enough space, copy the filters to our filter list */
9303deb3ec6SMatthias Ringwald         for (i = 0; i < list_length / (2 * 2); i ++) {
931f8fbdce0SMatthias Ringwald             channel->net_filter[channel->net_filter_count].range_start = big_endian_read_16(packet, 1 + 2 + i * 4);
932f8fbdce0SMatthias Ringwald             channel->net_filter[channel->net_filter_count].range_end = big_endian_read_16(packet, 1 + 2 + i * 4 + 2);
9333deb3ec6SMatthias Ringwald             if (channel->net_filter[channel->net_filter_count].range_start > channel->net_filter[channel->net_filter_count].range_end) {
9343deb3ec6SMatthias Ringwald                 /* Invalid filter range, ignore this filter rule */
9353deb3ec6SMatthias Ringwald                 log_error("BNEP_FILTER_NET_TYPE_SET: Invalid filter: start: %d, end: %d",
9363deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_start,
9373deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_end);
9383deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
9393deb3ec6SMatthias Ringwald             } else {
9403deb3ec6SMatthias Ringwald                 /* Valid filter, increase the filter count */
9413deb3ec6SMatthias Ringwald                 log_info("BNEP_FILTER_NET_TYPE_SET: Add filter: start: %d, end: %d",
9423deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_start,
9433deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_end);
9443deb3ec6SMatthias Ringwald                 channel->net_filter_count ++;
9453deb3ec6SMatthias Ringwald             }
9463deb3ec6SMatthias Ringwald         }
9473deb3ec6SMatthias Ringwald     }
9483deb3ec6SMatthias Ringwald 
9493deb3ec6SMatthias Ringwald     /* Set flag to send out the set net filter response on next statemachine cycle */
9503deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
9513deb3ec6SMatthias Ringwald     channel->response_code = response_code;
9524e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
9533deb3ec6SMatthias Ringwald 
9543deb3ec6SMatthias Ringwald     return 3 + list_length;
9553deb3ec6SMatthias Ringwald }
9563deb3ec6SMatthias Ringwald 
9573deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9583deb3ec6SMatthias Ringwald {
9593deb3ec6SMatthias Ringwald 	uint16_t response_code;
9603deb3ec6SMatthias Ringwald 
9613deb3ec6SMatthias Ringwald     // TODO: Currently we do not support setting a network filter.
9623deb3ec6SMatthias Ringwald 
9633deb3ec6SMatthias Ringwald     /* Sanity check packet size */
9643deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
9653deb3ec6SMatthias Ringwald         return 0;
9663deb3ec6SMatthias Ringwald     }
9673deb3ec6SMatthias Ringwald 
9683deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
9693deb3ec6SMatthias Ringwald         log_error("BNEP_FILTER_NET_TYPE_RESPONSE: Ignored in channel state %d", channel->state);
9703deb3ec6SMatthias Ringwald         return 1 + 2;
9713deb3ec6SMatthias Ringwald     }
9723deb3ec6SMatthias Ringwald 
973f8fbdce0SMatthias Ringwald     response_code = big_endian_read_16(packet, 1);
9743deb3ec6SMatthias Ringwald 
9753deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_FILTER_SUCCESS) {
9763deb3ec6SMatthias Ringwald         log_info("BNEP_FILTER_NET_TYPE_RESPONSE: Net filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
9773deb3ec6SMatthias Ringwald     } else {
9783deb3ec6SMatthias 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);
9793deb3ec6SMatthias Ringwald     }
9803deb3ec6SMatthias Ringwald 
9813deb3ec6SMatthias Ringwald     return 1 + 2;
9823deb3ec6SMatthias Ringwald }
9833deb3ec6SMatthias Ringwald 
9843deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9853deb3ec6SMatthias Ringwald {
9863deb3ec6SMatthias Ringwald     uint16_t list_length;
9873deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
9883deb3ec6SMatthias Ringwald 
9893deb3ec6SMatthias Ringwald     /* Sanity check packet size */
9903deb3ec6SMatthias Ringwald     if (size < 3) {
9913deb3ec6SMatthias Ringwald         return 0;
9923deb3ec6SMatthias Ringwald     }
9933deb3ec6SMatthias Ringwald 
994f8fbdce0SMatthias Ringwald     list_length = big_endian_read_16(packet, 1);
9953deb3ec6SMatthias Ringwald     /* Sanity check packet size again with known package size */
9963deb3ec6SMatthias Ringwald     if (size < 3 + list_length) {
9973deb3ec6SMatthias Ringwald         return 0;
9983deb3ec6SMatthias Ringwald     }
9993deb3ec6SMatthias Ringwald 
10003deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
10013deb3ec6SMatthias Ringwald         log_error("BNEP_MULTI_ADDR_SET: Ignored in channel state %d", channel->state);
10023deb3ec6SMatthias Ringwald         return 3 + list_length;
10033deb3ec6SMatthias Ringwald     }
10043deb3ec6SMatthias Ringwald 
10053deb3ec6SMatthias Ringwald     /* Check if we have enough space for more filters */
10063deb3ec6SMatthias Ringwald     if ((list_length / (2 * ETHER_ADDR_LEN)) > MAX_BNEP_MULTICAST_FILTER) {
10073deb3ec6SMatthias Ringwald         log_info("BNEP_MULTI_ADDR_SET: Too many filter");
10083deb3ec6SMatthias Ringwald         response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
10093deb3ec6SMatthias Ringwald     } else {
10103deb3ec6SMatthias Ringwald         unsigned int i;
10113deb3ec6SMatthias Ringwald         channel->multicast_filter_count = 0;
10123deb3ec6SMatthias Ringwald         /* There is enough space, copy the filters to our filter list */
10133deb3ec6SMatthias Ringwald         for (i = 0; i < list_length / (2 * ETHER_ADDR_LEN); i ++) {
1014058e3d6bSMatthias Ringwald             bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_start, packet + 1 + 2 + i * ETHER_ADDR_LEN * 2);
1015058e3d6bSMatthias Ringwald             bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_end, packet + 1 + 2 + i * ETHER_ADDR_LEN * 2 + ETHER_ADDR_LEN);
10163deb3ec6SMatthias Ringwald 
10173deb3ec6SMatthias Ringwald             if (memcmp(channel->multicast_filter[channel->multicast_filter_count].addr_start,
10183deb3ec6SMatthias Ringwald                        channel->multicast_filter[channel->multicast_filter_count].addr_end, ETHER_ADDR_LEN) > 0) {
10193deb3ec6SMatthias Ringwald                 /* Invalid filter range, ignore this filter rule */
10203deb3ec6SMatthias Ringwald                 log_error("BNEP_MULTI_ADDR_SET: Invalid filter: start: %s",
10213deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
10223deb3ec6SMatthias Ringwald                 log_error("BNEP_MULTI_ADDR_SET: Invalid filter: end: %s",
10233deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
10243deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
10253deb3ec6SMatthias Ringwald             } else {
10263deb3ec6SMatthias Ringwald                 /* Valid filter, increase the filter count */
10273deb3ec6SMatthias Ringwald                 log_info("BNEP_MULTI_ADDR_SET: Add filter: start: %s",
10283deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
10293deb3ec6SMatthias Ringwald                 log_info("BNEP_MULTI_ADDR_SET: Add filter: end: %s",
10303deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
10313deb3ec6SMatthias Ringwald                 channel->multicast_filter_count ++;
10323deb3ec6SMatthias Ringwald             }
10333deb3ec6SMatthias Ringwald         }
10343deb3ec6SMatthias Ringwald     }
10353deb3ec6SMatthias Ringwald     /* Set flag to send out the set multi addr response on next statemachine cycle */
10363deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
10373deb3ec6SMatthias Ringwald     channel->response_code = response_code;
10384e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
10393deb3ec6SMatthias Ringwald 
10403deb3ec6SMatthias Ringwald     return 3 + list_length;
10413deb3ec6SMatthias Ringwald }
10423deb3ec6SMatthias Ringwald 
10433deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
10443deb3ec6SMatthias Ringwald {
10453deb3ec6SMatthias Ringwald 	uint16_t response_code;
10463deb3ec6SMatthias Ringwald 
10473deb3ec6SMatthias Ringwald     // TODO: Currently we do not support setting multicast address filter.
10483deb3ec6SMatthias Ringwald 
10493deb3ec6SMatthias Ringwald     /* Sanity check packet size */
10503deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
10513deb3ec6SMatthias Ringwald         return 0;
10523deb3ec6SMatthias Ringwald     }
10533deb3ec6SMatthias Ringwald 
10543deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
10553deb3ec6SMatthias Ringwald         log_error("BNEP_MULTI_ADDR_RESPONSE: Ignored in channel state %d", channel->state);
10563deb3ec6SMatthias Ringwald         return 1 + 2;
10573deb3ec6SMatthias Ringwald     }
10583deb3ec6SMatthias Ringwald 
1059f8fbdce0SMatthias Ringwald     response_code = big_endian_read_16(packet, 1);
10603deb3ec6SMatthias Ringwald 
10613deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_FILTER_SUCCESS) {
10623deb3ec6SMatthias Ringwald         log_info("BNEP_MULTI_ADDR_RESPONSE: Multicast address filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
10633deb3ec6SMatthias Ringwald     } else {
10643deb3ec6SMatthias 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);
10653deb3ec6SMatthias Ringwald     }
10663deb3ec6SMatthias Ringwald 
10673deb3ec6SMatthias Ringwald     return 1 + 2;
10683deb3ec6SMatthias Ringwald }
10693deb3ec6SMatthias Ringwald 
10703deb3ec6SMatthias 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)
10713deb3ec6SMatthias Ringwald {
10723deb3ec6SMatthias Ringwald     uint16_t pos = 0;
10733deb3ec6SMatthias Ringwald 
1074f2e45468SMatthias 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)
10753deb3ec6SMatthias Ringwald     /* In-place modify the package and add the ethernet header in front of the payload.
10763deb3ec6SMatthias Ringwald      * WARNING: This modifies the data in front of the payload and may overwrite 14 bytes there!
10773deb3ec6SMatthias Ringwald      */
10783deb3ec6SMatthias Ringwald     uint8_t *ethernet_packet = payload - 2 * sizeof(bd_addr_t) - sizeof(uint16_t);
10793deb3ec6SMatthias Ringwald     /* Restore the ethernet packet header */
1080058e3d6bSMatthias Ringwald     bd_addr_copy(ethernet_packet + pos, addr_dest);
10813deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1082058e3d6bSMatthias Ringwald     bd_addr_copy(ethernet_packet + pos, addr_source);
10833deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1084f8fbdce0SMatthias Ringwald     big_endian_store_16(ethernet_packet, pos, network_protocol_type);
10853deb3ec6SMatthias Ringwald     /* Payload is just in place... */
10863deb3ec6SMatthias Ringwald #else
1087f2e45468SMatthias Ringwald #error "BNEP requires HCI_INCOMING_PRE_BUFFER_SIZE >= 6. Please update bstack_config.h"
10883deb3ec6SMatthias Ringwald #endif
10893deb3ec6SMatthias Ringwald 
10903deb3ec6SMatthias Ringwald     /* Notify application layer and deliver the ethernet packet */
1091c9bf9c27SMatthias Ringwald     if (channel->packet_handler){
1092c9bf9c27SMatthias Ringwald         (*channel->packet_handler)(BNEP_DATA_PACKET, channel->l2cap_cid, ethernet_packet,
1093c9bf9c27SMatthias Ringwald                                    size + sizeof(uint16_t) + 2 * sizeof(bd_addr_t));
1094c9bf9c27SMatthias Ringwald     }
10953deb3ec6SMatthias Ringwald 
10963deb3ec6SMatthias Ringwald     return size;
10973deb3ec6SMatthias Ringwald }
10983deb3ec6SMatthias Ringwald 
10993deb3ec6SMatthias Ringwald static int bnep_handle_control_packet(bnep_channel_t *channel, uint8_t *packet, uint16_t size, int is_extension)
11003deb3ec6SMatthias Ringwald {
11013deb3ec6SMatthias Ringwald     uint16_t len = 0;
11023deb3ec6SMatthias Ringwald     uint8_t  bnep_control_type;
11033deb3ec6SMatthias Ringwald 
11043deb3ec6SMatthias Ringwald     bnep_control_type = packet[0];
11053deb3ec6SMatthias Ringwald     /* Save last control type. Needed by statemachin in case of unknown control code */
11063deb3ec6SMatthias Ringwald 
11073deb3ec6SMatthias Ringwald     channel->last_control_type = bnep_control_type;
11083deb3ec6SMatthias Ringwald     log_info("BNEP_CONTROL: Type: %d, size: %d, is_extension: %d", bnep_control_type, size, is_extension);
11093deb3ec6SMatthias Ringwald     switch (bnep_control_type) {
11103deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD:
11113deb3ec6SMatthias Ringwald             /* The last command we send was not understood. We should close the connection */
11123deb3ec6SMatthias Ringwald             log_error("BNEP_CONTROL: Received COMMAND_NOT_UNDERSTOOD: l2cap_cid: %d, cmd: %d", channel->l2cap_cid, packet[3]);
11133deb3ec6SMatthias Ringwald             bnep_channel_finalize(channel);
11143deb3ec6SMatthias Ringwald             len = 2; // Length of command not understood packet - bnep-type field
11153deb3ec6SMatthias Ringwald             break;
11163deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST:
11173deb3ec6SMatthias Ringwald             if (is_extension) {
11183deb3ec6SMatthias Ringwald                 /* Connection requests are not allowed to be send in an extension header
11193deb3ec6SMatthias Ringwald                  *  ignore, do not set "COMMAND_NOT_UNDERSTOOD"
11203deb3ec6SMatthias Ringwald                  */
11213deb3ec6SMatthias Ringwald                 log_error("BNEP_CONTROL: Received SETUP_CONNECTION_REQUEST in extension header: l2cap_cid: %d", channel->l2cap_cid);
11223deb3ec6SMatthias Ringwald                 return 0;
11233deb3ec6SMatthias Ringwald             } else {
11243deb3ec6SMatthias Ringwald                 len = bnep_handle_connection_request(channel, packet, size);
11253deb3ec6SMatthias Ringwald             }
11263deb3ec6SMatthias Ringwald             break;
11273deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE:
11283deb3ec6SMatthias Ringwald             if (is_extension) {
11293deb3ec6SMatthias Ringwald                 /* Connection requests are not allowed to be send in an
11303deb3ec6SMatthias Ringwald                  * extension header, ignore, do not set "COMMAND_NOT_UNDERSTOOD"
11313deb3ec6SMatthias Ringwald                  */
11323deb3ec6SMatthias Ringwald                 log_error("BNEP_CONTROL: Received SETUP_CONNECTION_RESPONSE in extension header: l2cap_cid: %d", channel->l2cap_cid);
11333deb3ec6SMatthias Ringwald                 return 0;
11343deb3ec6SMatthias Ringwald             } else {
11353deb3ec6SMatthias Ringwald                 len = bnep_handle_connection_response(channel, packet, size);
11363deb3ec6SMatthias Ringwald             }
11373deb3ec6SMatthias Ringwald             break;
11383deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET:
11393deb3ec6SMatthias Ringwald             len = bnep_handle_filter_net_type_set(channel, packet, size);
11403deb3ec6SMatthias Ringwald             break;
11413deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE:
11423deb3ec6SMatthias Ringwald             len = bnep_handle_filter_net_type_response(channel, packet, size);
11433deb3ec6SMatthias Ringwald             break;
11443deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET:
11453deb3ec6SMatthias Ringwald             len = bnep_handle_multi_addr_set(channel, packet, size);
11463deb3ec6SMatthias Ringwald             break;
11473deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE:
11483deb3ec6SMatthias Ringwald             len = bnep_handle_multi_addr_response(channel, packet, size);
11493deb3ec6SMatthias Ringwald             break;
11503deb3ec6SMatthias Ringwald         default:
11513deb3ec6SMatthias Ringwald             log_error("BNEP_CONTROL: Invalid bnep control type: l2cap_cid: %d, cmd: %d", channel->l2cap_cid, bnep_control_type);
11523deb3ec6SMatthias Ringwald             len = 0;
11533deb3ec6SMatthias Ringwald             break;
11543deb3ec6SMatthias Ringwald     }
11553deb3ec6SMatthias Ringwald 
11563deb3ec6SMatthias Ringwald     if (len == 0) {
11573deb3ec6SMatthias Ringwald         /* In case the command could not be handled, send a
11583deb3ec6SMatthias Ringwald            COMMAND_NOT_UNDERSTOOD message.
11593deb3ec6SMatthias Ringwald            Set flag to process the request in the next statemachine loop
11603deb3ec6SMatthias Ringwald          */
11613deb3ec6SMatthias Ringwald         bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
11624e366553SMatthias Ringwald         l2cap_request_can_send_now_event(channel->l2cap_cid);
11633deb3ec6SMatthias Ringwald     }
11643deb3ec6SMatthias Ringwald 
11653deb3ec6SMatthias Ringwald     return len;
11663deb3ec6SMatthias Ringwald }
11673deb3ec6SMatthias Ringwald 
11683deb3ec6SMatthias Ringwald /**
11693deb3ec6SMatthias Ringwald  * @return handled packet
11703deb3ec6SMatthias Ringwald  */
11713deb3ec6SMatthias Ringwald static int bnep_hci_event_handler(uint8_t *packet, uint16_t size)
11723deb3ec6SMatthias Ringwald {
1173f21eb74fSMatthias Ringwald     UNUSED(size);   // ok: handling own l2cap events
11749ec2630cSMatthias Ringwald 
11753deb3ec6SMatthias Ringwald     bd_addr_t event_addr;
11763deb3ec6SMatthias Ringwald     uint16_t  psm;
11773deb3ec6SMatthias Ringwald     uint16_t  l2cap_cid;
11783deb3ec6SMatthias Ringwald     hci_con_handle_t con_handle;
11793deb3ec6SMatthias Ringwald     bnep_channel_t  *channel = NULL;
11803deb3ec6SMatthias Ringwald     uint8_t   status;
11813deb3ec6SMatthias Ringwald 
11820e2df43fSMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
11833deb3ec6SMatthias Ringwald 
1184235946f1SMatthias Ringwald         /* Accept an incoming L2CAP connection on BLUETOOTH_PROTOCOL_BNEP */
11853deb3ec6SMatthias Ringwald         case L2CAP_EVENT_INCOMING_CONNECTION:
11863deb3ec6SMatthias Ringwald             /* L2CAP event data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16) */
1187724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], event_addr);
1188f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet,  8);
1189f8fbdce0SMatthias Ringwald             psm        = little_endian_read_16(packet, 10);
1190f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 12);
11913deb3ec6SMatthias Ringwald 
1192235946f1SMatthias Ringwald             if (psm != BLUETOOTH_PROTOCOL_BNEP) break;
11933deb3ec6SMatthias Ringwald 
11943deb3ec6SMatthias Ringwald             channel = bnep_channel_for_addr(event_addr);
11953deb3ec6SMatthias Ringwald 
11963deb3ec6SMatthias Ringwald             if (channel) {
1197235946f1SMatthias Ringwald                 log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PROTOCOL_BNEP => decline - channel already exists", l2cap_cid);
11987ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
11993deb3ec6SMatthias Ringwald                 return 1;
12003deb3ec6SMatthias Ringwald             }
12013deb3ec6SMatthias Ringwald 
12023deb3ec6SMatthias Ringwald             /* Create a new BNEP channel instance (incoming) */
12033deb3ec6SMatthias Ringwald             channel = bnep_channel_create_for_addr(event_addr);
12043deb3ec6SMatthias Ringwald 
12053deb3ec6SMatthias Ringwald             if (!channel) {
1206235946f1SMatthias Ringwald                 log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PROTOCOL_BNEP => decline - no memory left", l2cap_cid);
12077ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
12083deb3ec6SMatthias Ringwald                 return 1;
12093deb3ec6SMatthias Ringwald             }
12103deb3ec6SMatthias Ringwald 
12113deb3ec6SMatthias Ringwald             /* Assign connection handle and l2cap cid */
12123deb3ec6SMatthias Ringwald             channel->con_handle = con_handle;
12133deb3ec6SMatthias Ringwald             channel->l2cap_cid = l2cap_cid;
12143deb3ec6SMatthias Ringwald 
12153deb3ec6SMatthias Ringwald             /* Set channel into accept state */
12163deb3ec6SMatthias Ringwald             channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST;
12173deb3ec6SMatthias Ringwald 
12183deb3ec6SMatthias Ringwald             /* Start connection timeout timer */
12193deb3ec6SMatthias Ringwald             bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
12203deb3ec6SMatthias Ringwald 
1221235946f1SMatthias Ringwald             log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PROTOCOL_BNEP => accept", l2cap_cid);
1222ce8f182eSMatthias Ringwald             l2cap_accept_connection(l2cap_cid);
12233deb3ec6SMatthias Ringwald             return 1;
12243deb3ec6SMatthias Ringwald 
12253deb3ec6SMatthias Ringwald         /* Outgoing L2CAP connection has been opened -> store l2cap_cid, remote_addr */
12263deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_OPENED:
1227235946f1SMatthias Ringwald             /* Check if the l2cap channel has been opened for BLUETOOTH_PROTOCOL_BNEP */
1228235946f1SMatthias Ringwald             if (little_endian_read_16(packet, 11) != BLUETOOTH_PROTOCOL_BNEP) {
12293deb3ec6SMatthias Ringwald                 break;
12303deb3ec6SMatthias Ringwald             }
12313deb3ec6SMatthias Ringwald 
12323deb3ec6SMatthias Ringwald             status = packet[2];
1233235946f1SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_OPENED for BLUETOOTH_PROTOCOL_BNEP, status %u", status);
12343deb3ec6SMatthias Ringwald 
12353deb3ec6SMatthias Ringwald             /* Get the bnep channel fpr remote address */
1236f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet, 9);
1237f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 13);
1238724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[3], event_addr);
12393deb3ec6SMatthias Ringwald             channel = bnep_channel_for_addr(event_addr);
12403deb3ec6SMatthias Ringwald             if (!channel) {
12413deb3ec6SMatthias Ringwald                 log_error("L2CAP_EVENT_CHANNEL_OPENED but no BNEP channel prepared");
12423deb3ec6SMatthias Ringwald                 return 1;
12433deb3ec6SMatthias Ringwald             }
12443deb3ec6SMatthias Ringwald 
12453deb3ec6SMatthias Ringwald             /* On L2CAP open error discard everything */
12463deb3ec6SMatthias Ringwald             if (status) {
12473deb3ec6SMatthias Ringwald                 /* Emit bnep_open_channel_complete with status and free channel */
12483deb3ec6SMatthias Ringwald                 bnep_emit_open_channel_complete(channel, status);
12493deb3ec6SMatthias Ringwald 
12503deb3ec6SMatthias Ringwald                 /* Free BNEP channel mempory */
12513deb3ec6SMatthias Ringwald                 bnep_channel_free(channel);
12523deb3ec6SMatthias Ringwald                 return 1;
12533deb3ec6SMatthias Ringwald             }
12543deb3ec6SMatthias Ringwald 
12553deb3ec6SMatthias Ringwald             switch (channel->state){
12563deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_CLOSED:
12573deb3ec6SMatthias Ringwald                     log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
12583deb3ec6SMatthias Ringwald 
12593deb3ec6SMatthias Ringwald                     bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
12603deb3ec6SMatthias Ringwald 
12613deb3ec6SMatthias Ringwald                     /* Assign connection handle and l2cap cid */
12623deb3ec6SMatthias Ringwald                     channel->l2cap_cid  = l2cap_cid;
12633deb3ec6SMatthias Ringwald                     channel->con_handle = con_handle;
12643deb3ec6SMatthias Ringwald 
12653deb3ec6SMatthias Ringwald                     /* Initiate the connection request */
12663deb3ec6SMatthias Ringwald                     channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
12673deb3ec6SMatthias Ringwald                     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
1268f8fbdce0SMatthias Ringwald                     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
12694e366553SMatthias Ringwald                     l2cap_request_can_send_now_event(channel->l2cap_cid);
12703deb3ec6SMatthias Ringwald                     break;
12713deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
12723deb3ec6SMatthias Ringwald                     /* New information: channel mtu */
1273f8fbdce0SMatthias Ringwald                     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
12743deb3ec6SMatthias Ringwald                     break;
12753deb3ec6SMatthias Ringwald                 default:
12763deb3ec6SMatthias Ringwald                     log_error("L2CAP_EVENT_CHANNEL_OPENED: Invalid state: %d", channel->state);
12773deb3ec6SMatthias Ringwald                     break;
12783deb3ec6SMatthias Ringwald             }
12793deb3ec6SMatthias Ringwald             return 1;
12803deb3ec6SMatthias Ringwald 
12811b89a84bSMatthias Ringwald         case L2CAP_EVENT_CAN_SEND_NOW:
12824e366553SMatthias Ringwald             bnep_handle_can_send_now(l2cap_event_can_send_now_get_local_cid(packet));
12833deb3ec6SMatthias Ringwald             break;
12843deb3ec6SMatthias Ringwald 
12853deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_CLOSED:
12863deb3ec6SMatthias Ringwald             // data: event (8), len(8), channel (16)
1287f8fbdce0SMatthias Ringwald             l2cap_cid   = little_endian_read_16(packet, 2);
12883deb3ec6SMatthias Ringwald             channel = bnep_channel_for_l2cap_cid(l2cap_cid);
12893deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, channel %p", l2cap_cid, channel);
12903deb3ec6SMatthias Ringwald 
12913deb3ec6SMatthias Ringwald             if (!channel) {
12923deb3ec6SMatthias Ringwald                 break;
12933deb3ec6SMatthias Ringwald             }
12943deb3ec6SMatthias Ringwald 
12953deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", channel->state);
12963deb3ec6SMatthias Ringwald             switch (channel->state) {
12973deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
12983deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE:
12993deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_CONNECTED:
13003deb3ec6SMatthias Ringwald                     bnep_channel_finalize(channel);
13013deb3ec6SMatthias Ringwald                     return 1;
13023deb3ec6SMatthias Ringwald                 default:
13033deb3ec6SMatthias Ringwald                     break;
13043deb3ec6SMatthias Ringwald             }
13053deb3ec6SMatthias Ringwald             break;
13063deb3ec6SMatthias Ringwald         default:
13073deb3ec6SMatthias Ringwald             break;
13083deb3ec6SMatthias Ringwald     }
13093deb3ec6SMatthias Ringwald     return 0;
13103deb3ec6SMatthias Ringwald }
13113deb3ec6SMatthias Ringwald 
13123deb3ec6SMatthias Ringwald static int bnep_l2cap_packet_handler(uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
13133deb3ec6SMatthias Ringwald {
13143deb3ec6SMatthias Ringwald     int             rc = 0;
13153deb3ec6SMatthias Ringwald     uint8_t         bnep_type;
13163deb3ec6SMatthias Ringwald     uint8_t         bnep_header_has_ext;
13173deb3ec6SMatthias Ringwald     uint8_t         extension_type;
13183deb3ec6SMatthias Ringwald     uint16_t        pos = 0;
13193deb3ec6SMatthias Ringwald     bd_addr_t       addr_source;
13203deb3ec6SMatthias Ringwald     bd_addr_t       addr_dest;
13213deb3ec6SMatthias Ringwald     uint16_t        network_protocol_type = 0xffff;
13223deb3ec6SMatthias Ringwald     bnep_channel_t *channel = NULL;
13233deb3ec6SMatthias Ringwald 
13243deb3ec6SMatthias Ringwald     /* Get the bnep channel for this package */
13253deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(l2cap_cid);
13263deb3ec6SMatthias Ringwald     if (!channel) {
13273deb3ec6SMatthias Ringwald         return rc;
13283deb3ec6SMatthias Ringwald     }
13293deb3ec6SMatthias Ringwald 
13303deb3ec6SMatthias Ringwald     /* Sort out short packages */
13313deb3ec6SMatthias Ringwald     if (size < 2) {
13323deb3ec6SMatthias Ringwald         return rc;
13333deb3ec6SMatthias Ringwald     }
13343deb3ec6SMatthias Ringwald 
13353deb3ec6SMatthias Ringwald     bnep_type = BNEP_TYPE(packet[pos]);
13363deb3ec6SMatthias Ringwald     bnep_header_has_ext = BNEP_HEADER_HAS_EXT(packet[pos]);
13373deb3ec6SMatthias Ringwald     pos ++;
13383deb3ec6SMatthias Ringwald 
13393deb3ec6SMatthias Ringwald     switch(bnep_type) {
13403deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_GENERAL_ETHERNET:
1341058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, &packet[pos]);
13423deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1343058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, &packet[pos]);
13443deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1345f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
13463deb3ec6SMatthias Ringwald             pos += 2;
13473deb3ec6SMatthias Ringwald             break;
13483deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET:
1349058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, channel->local_addr);
1350058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, channel->remote_addr);
1351f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
13523deb3ec6SMatthias Ringwald             pos += 2;
13533deb3ec6SMatthias Ringwald             break;
13543deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY:
1355058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, channel->local_addr);
1356058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, &packet[pos]);
13573deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1358f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
13593deb3ec6SMatthias Ringwald             pos += 2;
13603deb3ec6SMatthias Ringwald             break;
13613deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY:
1362058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, &packet[pos]);
13633deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1364058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, channel->remote_addr);
1365f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
13663deb3ec6SMatthias Ringwald             pos += 2;
13673deb3ec6SMatthias Ringwald             break;
13683deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_CONTROL:
13693deb3ec6SMatthias Ringwald             rc = bnep_handle_control_packet(channel, packet + pos, size - pos, 0);
13703deb3ec6SMatthias Ringwald             pos += rc;
13713deb3ec6SMatthias Ringwald             break;
13723deb3ec6SMatthias Ringwald         default:
13733deb3ec6SMatthias Ringwald             break;
13743deb3ec6SMatthias Ringwald     }
13753deb3ec6SMatthias Ringwald 
13763deb3ec6SMatthias Ringwald     if (bnep_header_has_ext) {
13773deb3ec6SMatthias Ringwald         do {
13783deb3ec6SMatthias Ringwald             uint8_t ext_len;
13793deb3ec6SMatthias Ringwald 
13803deb3ec6SMatthias Ringwald             /* Read extension type and check for further extensions */
13813deb3ec6SMatthias Ringwald             extension_type        = BNEP_TYPE(packet[pos]);
13823deb3ec6SMatthias Ringwald             bnep_header_has_ext   = BNEP_HEADER_HAS_EXT(packet[pos]);
13833deb3ec6SMatthias Ringwald             pos ++;
13843deb3ec6SMatthias Ringwald 
13853deb3ec6SMatthias Ringwald             /* Read extension header length */
13863deb3ec6SMatthias Ringwald             ext_len = packet[pos];
13873deb3ec6SMatthias Ringwald             pos ++;
13883deb3ec6SMatthias Ringwald 
13893deb3ec6SMatthias Ringwald             if (size - pos < ext_len) {
13903deb3ec6SMatthias Ringwald                 log_error("BNEP pkt handler: Invalid extension length! Packet ignored");
13913deb3ec6SMatthias Ringwald                 /* Invalid packet size! */
13923deb3ec6SMatthias Ringwald                 return 0;
13933deb3ec6SMatthias Ringwald             }
13943deb3ec6SMatthias Ringwald 
13953deb3ec6SMatthias Ringwald             switch (extension_type) {
13963deb3ec6SMatthias Ringwald                 case BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL:
13973deb3ec6SMatthias Ringwald                     if (ext_len != bnep_handle_control_packet(channel, packet + pos, ext_len, 1)) {
13983deb3ec6SMatthias Ringwald                         log_error("BNEP pkt handler: Ignore invalid control packet in extension header");
13993deb3ec6SMatthias Ringwald                     }
14003deb3ec6SMatthias Ringwald 
14013deb3ec6SMatthias Ringwald                     pos += ext_len;
14023deb3ec6SMatthias Ringwald                     break;
14033deb3ec6SMatthias Ringwald 
14043deb3ec6SMatthias Ringwald                 default:
14053deb3ec6SMatthias Ringwald                     /* Extension header type unknown. Unknown extension SHALL be
14063deb3ec6SMatthias Ringwald 			         * SHALL be forwarded in any way. But who shall handle these
14073deb3ec6SMatthias Ringwald                      * extension packets?
14083deb3ec6SMatthias Ringwald                      * For now: We ignore them and just drop them!
14093deb3ec6SMatthias Ringwald                      */
14103deb3ec6SMatthias Ringwald                     log_error("BNEP pkt handler: Unknown extension type ignored, data dropped!");
14113deb3ec6SMatthias Ringwald                     pos += ext_len;
14123deb3ec6SMatthias Ringwald                     break;
14133deb3ec6SMatthias Ringwald             }
14143deb3ec6SMatthias Ringwald 
14153deb3ec6SMatthias Ringwald         } while (bnep_header_has_ext);
14163deb3ec6SMatthias Ringwald     }
14173deb3ec6SMatthias Ringwald 
14183deb3ec6SMatthias Ringwald     if (bnep_type != BNEP_PKT_TYPE_CONTROL && network_protocol_type != 0xffff) {
14193deb3ec6SMatthias Ringwald         if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
14203deb3ec6SMatthias Ringwald             rc = bnep_handle_ethernet_packet(channel, addr_dest, addr_source, network_protocol_type, packet + pos, size - pos);
14213deb3ec6SMatthias Ringwald         } else {
14223deb3ec6SMatthias Ringwald             rc = 0;
14233deb3ec6SMatthias Ringwald         }
14243deb3ec6SMatthias Ringwald     }
14253deb3ec6SMatthias Ringwald 
14263deb3ec6SMatthias Ringwald     return rc;
14273deb3ec6SMatthias Ringwald 
14283deb3ec6SMatthias Ringwald }
14293deb3ec6SMatthias Ringwald 
14303deb3ec6SMatthias Ringwald void bnep_packet_handler(uint8_t packet_type, uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
14313deb3ec6SMatthias Ringwald {
14323deb3ec6SMatthias Ringwald     switch (packet_type) {
14333deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
1434bef9a6fcSMatthias Ringwald             bnep_hci_event_handler(packet, size);
14353deb3ec6SMatthias Ringwald             break;
14363deb3ec6SMatthias Ringwald         case L2CAP_DATA_PACKET:
1437bef9a6fcSMatthias Ringwald             bnep_l2cap_packet_handler(l2cap_cid, packet, size);
14383deb3ec6SMatthias Ringwald             break;
14393deb3ec6SMatthias Ringwald         default:
14403deb3ec6SMatthias Ringwald             break;
14413deb3ec6SMatthias Ringwald     }
14423deb3ec6SMatthias Ringwald }
14433deb3ec6SMatthias Ringwald 
14443deb3ec6SMatthias Ringwald static void bnep_channel_state_machine(bnep_channel_t* channel, bnep_channel_event_t *event)
14453deb3ec6SMatthias Ringwald {
1446b42623deSMatthias Ringwald     log_debug("bnep_state_machine: state %u, state var: %02x, event %u", channel->state, channel->state_var, event->type);
14473deb3ec6SMatthias Ringwald 
14483deb3ec6SMatthias Ringwald     if (event->type == BNEP_CH_EVT_READY_TO_SEND) {
14493deb3ec6SMatthias Ringwald         /* Send outstanding packets. */
14503deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD) {
14513deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
14523deb3ec6SMatthias Ringwald             bnep_send_command_not_understood(channel, channel->last_control_type);
14533deb3ec6SMatthias Ringwald             return;
14543deb3ec6SMatthias Ringwald         }
14553deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST) {
14563deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
14573deb3ec6SMatthias Ringwald             channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
14583deb3ec6SMatthias Ringwald             bnep_send_connection_request(channel, channel->uuid_source, channel->uuid_dest);
14593deb3ec6SMatthias Ringwald         }
14603deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE) {
14613deb3ec6SMatthias Ringwald             int emit_connected = 0;
14623deb3ec6SMatthias Ringwald             if ((channel->state == BNEP_CHANNEL_STATE_CLOSED) ||
14633deb3ec6SMatthias Ringwald                 (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST)) {
14643deb3ec6SMatthias Ringwald                 /* Set channel state to STATE_CONNECTED */
14653deb3ec6SMatthias Ringwald                 channel->state = BNEP_CHANNEL_STATE_CONNECTED;
14663deb3ec6SMatthias Ringwald                 /* Stop timeout timer! */
14673deb3ec6SMatthias Ringwald                 bnep_channel_stop_timer(channel);
14683deb3ec6SMatthias Ringwald                 emit_connected = 1;
14693deb3ec6SMatthias Ringwald             }
14703deb3ec6SMatthias Ringwald 
14713deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
14723deb3ec6SMatthias Ringwald             bnep_send_connection_response(channel, channel->response_code);
14733deb3ec6SMatthias Ringwald             if (emit_connected){
14743deb3ec6SMatthias Ringwald                 bnep_emit_open_channel_complete(channel, 0);
14753deb3ec6SMatthias Ringwald             }
14763deb3ec6SMatthias Ringwald             return;
14773deb3ec6SMatthias Ringwald         }
14783deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET) {
14793deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
14803deb3ec6SMatthias Ringwald             if ((channel->net_filter_out_count > 0) && (channel->net_filter_out != NULL)) {
14813deb3ec6SMatthias Ringwald                 bnep_send_filter_net_type_set(channel, channel->net_filter_out, channel->net_filter_out_count);
14823deb3ec6SMatthias Ringwald                 channel->net_filter_out_count = 0;
14833deb3ec6SMatthias Ringwald                 channel->net_filter_out = NULL;
14843deb3ec6SMatthias Ringwald             }
14853deb3ec6SMatthias Ringwald             return;
14863deb3ec6SMatthias Ringwald         }
14873deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE) {
14883deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
14893deb3ec6SMatthias Ringwald             bnep_send_filter_net_type_response(channel, channel->response_code);
14903deb3ec6SMatthias Ringwald             return;
14913deb3ec6SMatthias Ringwald         }
14923deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET) {
14933deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
14943deb3ec6SMatthias Ringwald             if ((channel->multicast_filter_out_count > 0) && (channel->multicast_filter_out != NULL)) {
14953deb3ec6SMatthias Ringwald                 bnep_send_filter_multi_addr_set(channel, channel->multicast_filter_out, channel->multicast_filter_out_count);
14963deb3ec6SMatthias Ringwald                 channel->multicast_filter_out_count = 0;
14973deb3ec6SMatthias Ringwald                 channel->multicast_filter_out = NULL;
14983deb3ec6SMatthias Ringwald             }
14993deb3ec6SMatthias Ringwald             return;
15003deb3ec6SMatthias Ringwald         }
15013deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE) {
15023deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
15033deb3ec6SMatthias Ringwald             bnep_send_filter_multi_addr_response(channel, channel->response_code);
15043deb3ec6SMatthias Ringwald             return;
15053deb3ec6SMatthias Ringwald         }
15063deb3ec6SMatthias Ringwald 
15073deb3ec6SMatthias Ringwald         /* If the event was not yet handled, notify the application layer */
15081ed1a3bdSMatthias Ringwald         if (channel->waiting_for_can_send_now){
15091ed1a3bdSMatthias Ringwald             channel->waiting_for_can_send_now = 0;
15103deb3ec6SMatthias Ringwald             bnep_emit_ready_to_send(channel);
15113deb3ec6SMatthias Ringwald         }
15123deb3ec6SMatthias Ringwald     }
15131ed1a3bdSMatthias Ringwald }
15143deb3ec6SMatthias Ringwald 
15154e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t l2cap_cid){
1516665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
1517665d90f2SMatthias Ringwald     btstack_linked_item_t *next;
15183deb3ec6SMatthias Ringwald 
1519665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = next){
15203deb3ec6SMatthias Ringwald         next = it->next;    // be prepared for removal of channel in state machine
15213deb3ec6SMatthias Ringwald         bnep_channel_t * channel = ((bnep_channel_t *) it);
15224e366553SMatthias Ringwald         if (channel->l2cap_cid != l2cap_cid) continue;
15234e366553SMatthias Ringwald         //
15243deb3ec6SMatthias Ringwald         bnep_channel_event_t channel_event = { BNEP_CH_EVT_READY_TO_SEND };
15253deb3ec6SMatthias Ringwald         bnep_channel_state_machine(channel, &channel_event);
15264e366553SMatthias Ringwald 
15274e366553SMatthias Ringwald         if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
15284e366553SMatthias Ringwald             l2cap_request_can_send_now_event(channel->l2cap_cid);
15294e366553SMatthias Ringwald             return;
15303deb3ec6SMatthias Ringwald         }
15313deb3ec6SMatthias Ringwald     }
15324e366553SMatthias Ringwald }
15334e366553SMatthias Ringwald 
15343deb3ec6SMatthias Ringwald 
15353deb3ec6SMatthias Ringwald /* BNEP BTStack API */
15363deb3ec6SMatthias Ringwald void bnep_init(void)
15373deb3ec6SMatthias Ringwald {
153845a58b30SMatthias Ringwald     bnep_security_level = LEVEL_2;
15393deb3ec6SMatthias Ringwald }
15403deb3ec6SMatthias Ringwald 
15413deb3ec6SMatthias Ringwald void bnep_set_required_security_level(gap_security_level_t security_level)
15423deb3ec6SMatthias Ringwald {
15433deb3ec6SMatthias Ringwald     bnep_security_level = security_level;
15443deb3ec6SMatthias Ringwald }
15453deb3ec6SMatthias Ringwald 
15460c249750SMatthias 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)
15473deb3ec6SMatthias Ringwald {
15483deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
15493deb3ec6SMatthias Ringwald     log_info("BNEP_CONNECT addr %s", bd_addr_to_str(addr));
15503deb3ec6SMatthias Ringwald 
15513deb3ec6SMatthias Ringwald     channel = bnep_channel_create_for_addr(addr);
15523deb3ec6SMatthias Ringwald     if (channel == NULL) {
15533deb3ec6SMatthias Ringwald         return -1;
15543deb3ec6SMatthias Ringwald     }
15553deb3ec6SMatthias Ringwald 
15563deb3ec6SMatthias Ringwald     channel->uuid_source    = uuid_src;
15573deb3ec6SMatthias Ringwald     channel->uuid_dest      = uuid_dest;
15580c249750SMatthias Ringwald     channel->packet_handler = packet_handler;
15593deb3ec6SMatthias Ringwald 
156090a28bdeSMatthias Ringwald     uint8_t status = l2cap_create_channel(bnep_packet_handler, addr, l2cap_psm, l2cap_max_mtu(), NULL);
156190a28bdeSMatthias Ringwald     if (status){
156290a28bdeSMatthias Ringwald         return -1;
156390a28bdeSMatthias Ringwald     }
15643deb3ec6SMatthias Ringwald     return 0;
15653deb3ec6SMatthias Ringwald }
15663deb3ec6SMatthias Ringwald 
15673deb3ec6SMatthias Ringwald void bnep_disconnect(bd_addr_t addr)
15683deb3ec6SMatthias Ringwald {
15693deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
15703deb3ec6SMatthias Ringwald     log_info("BNEP_DISCONNECT");
15713deb3ec6SMatthias Ringwald 
15723deb3ec6SMatthias Ringwald     channel = bnep_channel_for_addr(addr);
15733deb3ec6SMatthias Ringwald 
15743deb3ec6SMatthias Ringwald     bnep_channel_finalize(channel);
15753deb3ec6SMatthias Ringwald }
15763deb3ec6SMatthias Ringwald 
15773deb3ec6SMatthias Ringwald 
15780c249750SMatthias Ringwald uint8_t bnep_register_service(btstack_packet_handler_t packet_handler, uint16_t service_uuid, uint16_t max_frame_size)
15793deb3ec6SMatthias Ringwald {
15803deb3ec6SMatthias Ringwald     log_info("BNEP_REGISTER_SERVICE mtu %d", max_frame_size);
15813deb3ec6SMatthias Ringwald 
15823deb3ec6SMatthias Ringwald     /* Check if we already registered a service */
15833deb3ec6SMatthias Ringwald     bnep_service_t * service = bnep_service_for_uuid(service_uuid);
15843deb3ec6SMatthias Ringwald     if (service) {
15850cc6429eSMatthias Ringwald         return BNEP_SERVICE_ALREADY_REGISTERED;
15863deb3ec6SMatthias Ringwald     }
15873deb3ec6SMatthias Ringwald 
15883deb3ec6SMatthias Ringwald     /* Only alow one the three service types: PANU, NAP, GN */
1589235946f1SMatthias Ringwald     if ((service_uuid != BLUETOOTH_SERVICE_CLASS_PANU) &&
1590235946f1SMatthias Ringwald         (service_uuid != BLUETOOTH_SERVICE_CLASS_NAP) &&
1591235946f1SMatthias Ringwald         (service_uuid != BLUETOOTH_SERVICE_CLASS_GN)) {
15923deb3ec6SMatthias Ringwald         log_info("BNEP_REGISTER_SERVICE: Invalid service UUID: %04x", service_uuid);
15930cc6429eSMatthias Ringwald         return BNEP_SERVICE_ALREADY_REGISTERED; // TODO: define own error
15943deb3ec6SMatthias Ringwald     }
15953deb3ec6SMatthias Ringwald 
15963deb3ec6SMatthias Ringwald     /* Allocate service memory */
15973deb3ec6SMatthias Ringwald     service = (bnep_service_t*) btstack_memory_bnep_service_get();
15983deb3ec6SMatthias Ringwald     if (!service) {
15990cc6429eSMatthias Ringwald         return BTSTACK_MEMORY_ALLOC_FAILED;
16003deb3ec6SMatthias Ringwald     }
16013deb3ec6SMatthias Ringwald 
16023deb3ec6SMatthias Ringwald     /* register with l2cap if not registered before, max MTU */
1603235946f1SMatthias Ringwald     l2cap_register_service(bnep_packet_handler, BLUETOOTH_PROTOCOL_BNEP, 0xffff, bnep_security_level);
16043deb3ec6SMatthias Ringwald 
16053deb3ec6SMatthias Ringwald     /* Setup the service struct */
16063deb3ec6SMatthias Ringwald     service->max_frame_size = max_frame_size;
16073deb3ec6SMatthias Ringwald     service->service_uuid    = service_uuid;
16080c249750SMatthias Ringwald     service->packet_handler = packet_handler;
16090c249750SMatthias Ringwald 
16103deb3ec6SMatthias Ringwald 
16113deb3ec6SMatthias Ringwald     /* Add to services list */
1612665d90f2SMatthias Ringwald     btstack_linked_list_add(&bnep_services, (btstack_linked_item_t *) service);
16133deb3ec6SMatthias Ringwald 
16140cc6429eSMatthias Ringwald     return 0;
16153deb3ec6SMatthias Ringwald }
16163deb3ec6SMatthias Ringwald 
16173deb3ec6SMatthias Ringwald void bnep_unregister_service(uint16_t service_uuid)
16183deb3ec6SMatthias Ringwald {
16193deb3ec6SMatthias Ringwald     log_info("BNEP_UNREGISTER_SERVICE #%04x", service_uuid);
16203deb3ec6SMatthias Ringwald 
16213deb3ec6SMatthias Ringwald     bnep_service_t *service = bnep_service_for_uuid(service_uuid);
16223deb3ec6SMatthias Ringwald     if (!service) {
16233deb3ec6SMatthias Ringwald         return;
16243deb3ec6SMatthias Ringwald     }
16253deb3ec6SMatthias Ringwald 
1626665d90f2SMatthias Ringwald     btstack_linked_list_remove(&bnep_services, (btstack_linked_item_t *) service);
16273deb3ec6SMatthias Ringwald     btstack_memory_bnep_service_free(service);
16283deb3ec6SMatthias Ringwald     service = NULL;
16293deb3ec6SMatthias Ringwald 
1630235946f1SMatthias Ringwald     l2cap_unregister_service(BLUETOOTH_PROTOCOL_BNEP);
16313deb3ec6SMatthias Ringwald }
16323deb3ec6SMatthias Ringwald 
1633