xref: /btstack/src/classic/bnep.c (revision 9951ad9c4f1f93b124ebc72ec8a4261178530c65)
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 
64*9951ad9cSMatthias Ringwald #define BNEP_EXT_FLAG                                   0x80
65*9951ad9cSMatthias Ringwald #define BNEP_TYPE_MASK                                  0x7F
66*9951ad9cSMatthias Ringwald #define BNEP_TYPE(header)                               ((header) & BNEP_TYPE_MASK)
67*9951ad9cSMatthias Ringwald #define BNEP_HEADER_HAS_EXT(x)                          (((x) & BNEP_EXT_FLAG) == BNEP_EXT_FLAG)
68*9951ad9cSMatthias Ringwald 
69*9951ad9cSMatthias Ringwald /* BNEP packet types */
70*9951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_GENERAL_ETHERNET                  0x00
71*9951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_CONTROL                           0x01
72*9951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET               0x02
73*9951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY   0x03
74*9951ad9cSMatthias Ringwald #define BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY     0x04
75*9951ad9cSMatthias Ringwald 
76*9951ad9cSMatthias Ringwald /* BNEP control types */
77*9951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD        0x00
78*9951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST      0x01
79*9951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE     0x02
80*9951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET           0x03
81*9951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE      0x04
82*9951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET         0x05
83*9951ad9cSMatthias Ringwald #define BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE    0x06
84*9951ad9cSMatthias Ringwald 
85*9951ad9cSMatthias Ringwald /* BNEP extension header types */
86*9951ad9cSMatthias Ringwald #define BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL          0x00
87*9951ad9cSMatthias Ringwald 
88*9951ad9cSMatthias Ringwald /* BNEP setup response codes */
89*9951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_SUCCESS                         0x0000
90*9951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_DEST_UUID               0x0001
91*9951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_SOURCE_UUID             0x0002
92*9951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_INVALID_SERVICE_UUID_SIZE       0x0003
93*9951ad9cSMatthias Ringwald #define BNEP_RESP_SETUP_CONNECTION_NOT_ALLOWED          0x0004
94*9951ad9cSMatthias Ringwald 
95*9951ad9cSMatthias Ringwald /* BNEP filter response codes */
96*9951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_SUCCESS                        0x0000
97*9951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_UNSUPPORTED_REQUEST            0x0001
98*9951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_INVALID_RANGE              0x0002
99*9951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS           0x0003
100*9951ad9cSMatthias Ringwald #define BNEP_RESP_FILTER_ERR_SECURITY                   0x0004
101*9951ad9cSMatthias Ringwald 
1023deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_TIMEOUT_MS 10000
1033deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_MAX_RETRIES 1
1043deb3ec6SMatthias Ringwald 
1058f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_services = NULL;
1068f2a52f4SMatthias Ringwald static btstack_linked_list_t bnep_channels = NULL;
1073deb3ec6SMatthias Ringwald 
1083deb3ec6SMatthias Ringwald static gap_security_level_t bnep_security_level;
1093deb3ec6SMatthias Ringwald 
1103deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid);
1113deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel);
1123deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout);
1133deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event);
1144e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t cid);
1153deb3ec6SMatthias Ringwald static void bnep_emit_open_channel_complete(bnep_channel_t *channel, uint8_t status)
1163deb3ec6SMatthias Ringwald {
1170c249750SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_OPENED status 0x%02x bd_addr: %s, handler %p", status, bd_addr_to_str(channel->remote_addr), channel->packet_handler);
1180c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1190c249750SMatthias Ringwald 
12032b46fecSMatthias Ringwald     uint8_t event[3 + sizeof(bd_addr_t) + 4 * sizeof(uint16_t) + 2];
121423c667cSMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_OPENED;
1223deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
1233deb3ec6SMatthias Ringwald     event[2] = status;
124423c667cSMatthias Ringwald     little_endian_store_16(event, 3, channel->l2cap_cid);
125423c667cSMatthias Ringwald     little_endian_store_16(event, 5, channel->uuid_source);
126423c667cSMatthias Ringwald     little_endian_store_16(event, 7, channel->uuid_dest);
127423c667cSMatthias Ringwald     little_endian_store_16(event, 9, channel->max_frame_size);
128fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[11]);
12932b46fecSMatthias Ringwald     little_endian_store_16(event, 17, channel->con_handle);
1303deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
1310c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1323deb3ec6SMatthias Ringwald }
1333deb3ec6SMatthias Ringwald 
1343deb3ec6SMatthias Ringwald static void bnep_emit_channel_timeout(bnep_channel_t *channel)
1353deb3ec6SMatthias Ringwald {
1360c249750SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_TIMEOUT bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler);
1370c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1380c249750SMatthias Ringwald 
139423c667cSMatthias Ringwald     uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t) + sizeof(uint8_t)];
1403deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_TIMEOUT;
1413deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
142423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
143423c667cSMatthias Ringwald     little_endian_store_16(event, 4, channel->uuid_source);
144423c667cSMatthias Ringwald     little_endian_store_16(event, 6, channel->uuid_dest);
145fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[8]);
146423c667cSMatthias Ringwald     event[14] = channel->state;
1473deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
1480c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1493deb3ec6SMatthias Ringwald }
1503deb3ec6SMatthias Ringwald 
1513deb3ec6SMatthias Ringwald static void bnep_emit_channel_closed(bnep_channel_t *channel)
1523deb3ec6SMatthias Ringwald {
1530c249750SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_CLOSED bd_addr: %s, handler %p", bd_addr_to_str(channel->remote_addr), channel->packet_handler);
1540c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1550c249750SMatthias Ringwald 
156423c667cSMatthias Ringwald     uint8_t event[2 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t)];
1573deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_CLOSED;
1583deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
159423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
160423c667cSMatthias Ringwald     little_endian_store_16(event, 4, channel->uuid_source);
161423c667cSMatthias Ringwald     little_endian_store_16(event, 6, channel->uuid_dest);
162fb389631SMatthias Ringwald     reverse_bd_addr(channel->remote_addr, &event[8]);
1633deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
1640c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1653deb3ec6SMatthias Ringwald }
1663deb3ec6SMatthias Ringwald 
1673deb3ec6SMatthias Ringwald static void bnep_emit_ready_to_send(bnep_channel_t *channel)
1683deb3ec6SMatthias Ringwald {
1690c249750SMatthias Ringwald     if (!channel->packet_handler) return;
1700c249750SMatthias Ringwald 
171423c667cSMatthias Ringwald     uint8_t event[4];
1722d4c8c04SMatthias Ringwald     event[0] = BNEP_EVENT_CAN_SEND_NOW;
1733deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
174423c667cSMatthias Ringwald     little_endian_store_16(event, 2, channel->l2cap_cid);
1753deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
1760c249750SMatthias Ringwald 	(*channel->packet_handler)(HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
1773deb3ec6SMatthias Ringwald }
1783deb3ec6SMatthias Ringwald 
1793deb3ec6SMatthias Ringwald /* Send BNEP connection request */
1803deb3ec6SMatthias Ringwald static int bnep_send_command_not_understood(bnep_channel_t *channel, uint8_t control_type)
1813deb3ec6SMatthias Ringwald {
1823deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
1833deb3ec6SMatthias Ringwald     uint16_t pos = 0;
1843deb3ec6SMatthias Ringwald     int      err = 0;
1853deb3ec6SMatthias Ringwald 
1863deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
1873deb3ec6SMatthias Ringwald         return -1; // TODO
1883deb3ec6SMatthias Ringwald     }
1893deb3ec6SMatthias Ringwald 
1903deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
1913deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
1923deb3ec6SMatthias Ringwald 
1933deb3ec6SMatthias Ringwald     /* Setup control packet type */
1943deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
1953deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD;
1963deb3ec6SMatthias Ringwald 
1973deb3ec6SMatthias Ringwald     /* Add not understood control type */
1983deb3ec6SMatthias Ringwald     bnep_out_buffer[pos++] = control_type;
1993deb3ec6SMatthias Ringwald 
2003deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2013deb3ec6SMatthias Ringwald 
2023deb3ec6SMatthias Ringwald     if (err) {
2033deb3ec6SMatthias Ringwald         // TODO: Log error
2043deb3ec6SMatthias Ringwald     }
2053deb3ec6SMatthias Ringwald     return err;
2063deb3ec6SMatthias Ringwald }
2073deb3ec6SMatthias Ringwald 
2083deb3ec6SMatthias Ringwald 
2093deb3ec6SMatthias Ringwald /* Send BNEP connection request */
2103deb3ec6SMatthias Ringwald static int bnep_send_connection_request(bnep_channel_t *channel, uint16_t uuid_source, uint16_t uuid_dest)
2113deb3ec6SMatthias Ringwald {
2123deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2133deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2143deb3ec6SMatthias Ringwald     int      err = 0;
2153deb3ec6SMatthias Ringwald 
2163deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2173deb3ec6SMatthias Ringwald         return -1; // TODO
2183deb3ec6SMatthias Ringwald     }
2193deb3ec6SMatthias Ringwald 
2203deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2213deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2223deb3ec6SMatthias Ringwald 
2233deb3ec6SMatthias Ringwald     /* Setup control packet type */
2243deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2253deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST;
2263deb3ec6SMatthias Ringwald 
2273deb3ec6SMatthias Ringwald     /* Add UUID Size */
2283deb3ec6SMatthias Ringwald     bnep_out_buffer[pos++] = 2;
2293deb3ec6SMatthias Ringwald 
2303deb3ec6SMatthias Ringwald     /* Add dest and source UUID */
231f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, uuid_dest);
2323deb3ec6SMatthias Ringwald     pos += 2;
2333deb3ec6SMatthias Ringwald 
234f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, uuid_source);
2353deb3ec6SMatthias Ringwald     pos += 2;
2363deb3ec6SMatthias Ringwald 
2373deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2383deb3ec6SMatthias Ringwald 
2393deb3ec6SMatthias Ringwald     if (err) {
2403deb3ec6SMatthias Ringwald         // TODO: Log error
2413deb3ec6SMatthias Ringwald     }
2423deb3ec6SMatthias Ringwald     return err;
2433deb3ec6SMatthias Ringwald }
2443deb3ec6SMatthias Ringwald 
2453deb3ec6SMatthias Ringwald /* Send BNEP connection response */
2463deb3ec6SMatthias Ringwald static int bnep_send_connection_response(bnep_channel_t *channel, uint16_t response_code)
2473deb3ec6SMatthias Ringwald {
2483deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2493deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2503deb3ec6SMatthias Ringwald     int      err = 0;
2513deb3ec6SMatthias Ringwald 
2523deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2533deb3ec6SMatthias Ringwald         return -1; // TODO
2543deb3ec6SMatthias Ringwald     }
2553deb3ec6SMatthias Ringwald 
2563deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2573deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2583deb3ec6SMatthias Ringwald 
2593deb3ec6SMatthias Ringwald     /* Setup control packet type */
2603deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2613deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE;
2623deb3ec6SMatthias Ringwald 
2633deb3ec6SMatthias Ringwald     /* Add response code */
264f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
2653deb3ec6SMatthias Ringwald     pos += 2;
2663deb3ec6SMatthias Ringwald 
2673deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
2683deb3ec6SMatthias Ringwald 
2693deb3ec6SMatthias Ringwald     if (err) {
2703deb3ec6SMatthias Ringwald         // TODO: Log error
2713deb3ec6SMatthias Ringwald     }
2723deb3ec6SMatthias Ringwald     return err;
2733deb3ec6SMatthias Ringwald }
2743deb3ec6SMatthias Ringwald 
2753deb3ec6SMatthias Ringwald /* Send BNEP filter net type set message */
2763deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_set(bnep_channel_t *channel, bnep_net_filter_t *filter, uint16_t len)
2773deb3ec6SMatthias Ringwald {
2783deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
2793deb3ec6SMatthias Ringwald     uint16_t pos = 0;
2803deb3ec6SMatthias Ringwald     int      err = 0;
2813deb3ec6SMatthias Ringwald     int      i;
2823deb3ec6SMatthias Ringwald 
2833deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
2843deb3ec6SMatthias Ringwald         return -1;
2853deb3ec6SMatthias Ringwald     }
2863deb3ec6SMatthias Ringwald 
2873deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
2883deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
2893deb3ec6SMatthias Ringwald 
2903deb3ec6SMatthias Ringwald     /* Setup control packet type */
2913deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
2923deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET;
2933deb3ec6SMatthias Ringwald 
294f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, len * 2 * 2);
2953deb3ec6SMatthias Ringwald     pos += 2;
2963deb3ec6SMatthias Ringwald 
2973deb3ec6SMatthias Ringwald     for (i = 0; i < len; i ++) {
298f8fbdce0SMatthias Ringwald         big_endian_store_16(bnep_out_buffer, pos, filter[i].range_start);
2993deb3ec6SMatthias Ringwald         pos += 2;
300f8fbdce0SMatthias Ringwald         big_endian_store_16(bnep_out_buffer, pos, filter[i].range_end);
3013deb3ec6SMatthias Ringwald         pos += 2;
3023deb3ec6SMatthias Ringwald     }
3033deb3ec6SMatthias Ringwald 
3043deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
3053deb3ec6SMatthias Ringwald 
3063deb3ec6SMatthias Ringwald     if (err) {
3073deb3ec6SMatthias Ringwald         // TODO: Log error
3083deb3ec6SMatthias Ringwald     }
3093deb3ec6SMatthias Ringwald     return err;
3103deb3ec6SMatthias Ringwald }
3113deb3ec6SMatthias Ringwald 
3123deb3ec6SMatthias Ringwald /* Send BNEP filter net type response message */
3133deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_response(bnep_channel_t *channel, uint16_t response_code)
3143deb3ec6SMatthias Ringwald {
3153deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
3163deb3ec6SMatthias Ringwald     uint16_t pos = 0;
3173deb3ec6SMatthias Ringwald     int      err = 0;
3183deb3ec6SMatthias Ringwald 
3193deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3203deb3ec6SMatthias Ringwald         return -1;
3213deb3ec6SMatthias Ringwald     }
3223deb3ec6SMatthias Ringwald 
3233deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
3243deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
3253deb3ec6SMatthias Ringwald 
3263deb3ec6SMatthias Ringwald     /* Setup control packet type */
3273deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3283deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE;
3293deb3ec6SMatthias Ringwald 
3303deb3ec6SMatthias Ringwald     /* Add response code */
331f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
3323deb3ec6SMatthias Ringwald     pos += 2;
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 set message */
3433deb3ec6SMatthias Ringwald 
3443deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_set(bnep_channel_t *channel, bnep_multi_filter_t *filter, uint16_t len)
3453deb3ec6SMatthias Ringwald {
3463deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
3473deb3ec6SMatthias Ringwald     uint16_t pos = 0;
3483deb3ec6SMatthias Ringwald     int      err = 0;
3493deb3ec6SMatthias Ringwald     int      i;
3503deb3ec6SMatthias Ringwald 
3513deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3523deb3ec6SMatthias Ringwald         return -1;
3533deb3ec6SMatthias Ringwald     }
3543deb3ec6SMatthias Ringwald 
3553deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
3563deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
3573deb3ec6SMatthias Ringwald 
3583deb3ec6SMatthias Ringwald     /* Setup control packet type */
3593deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3603deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET;
3613deb3ec6SMatthias Ringwald 
362f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, len * 2 * ETHER_ADDR_LEN);
3633deb3ec6SMatthias Ringwald     pos += 2;
3643deb3ec6SMatthias Ringwald 
3653deb3ec6SMatthias Ringwald     for (i = 0; i < len; i ++) {
366058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_start);
3673deb3ec6SMatthias Ringwald         pos += ETHER_ADDR_LEN;
368058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos, filter[i].addr_end);
3693deb3ec6SMatthias Ringwald         pos += ETHER_ADDR_LEN;
3703deb3ec6SMatthias Ringwald     }
3713deb3ec6SMatthias Ringwald 
3723deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
3733deb3ec6SMatthias Ringwald 
3743deb3ec6SMatthias Ringwald     if (err) {
3753deb3ec6SMatthias Ringwald         // TODO: Log error
3763deb3ec6SMatthias Ringwald     }
3773deb3ec6SMatthias Ringwald     return err;
3783deb3ec6SMatthias Ringwald }
3793deb3ec6SMatthias Ringwald 
3803deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address response message */
3813deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_response(bnep_channel_t *channel, uint16_t response_code)
3823deb3ec6SMatthias Ringwald {
3833deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
3843deb3ec6SMatthias Ringwald     uint16_t pos = 0;
3853deb3ec6SMatthias Ringwald     int      err = 0;
3863deb3ec6SMatthias Ringwald 
3873deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
3883deb3ec6SMatthias Ringwald         return -1;
3893deb3ec6SMatthias Ringwald     }
3903deb3ec6SMatthias Ringwald 
3913deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
3923deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
3933deb3ec6SMatthias Ringwald 
3943deb3ec6SMatthias Ringwald     /* Setup control packet type */
3953deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
3963deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE;
3973deb3ec6SMatthias Ringwald 
3983deb3ec6SMatthias Ringwald     /* Add response code */
399f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos, response_code);
4003deb3ec6SMatthias Ringwald     pos += 2;
4013deb3ec6SMatthias Ringwald 
4023deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
4033deb3ec6SMatthias Ringwald 
4043deb3ec6SMatthias Ringwald     if (err) {
4053deb3ec6SMatthias Ringwald         // TODO: Log error
4063deb3ec6SMatthias Ringwald     }
4073deb3ec6SMatthias Ringwald     return err;
4083deb3ec6SMatthias Ringwald }
4093deb3ec6SMatthias Ringwald 
4103deb3ec6SMatthias Ringwald int bnep_can_send_packet_now(uint16_t bnep_cid)
4113deb3ec6SMatthias Ringwald {
4123deb3ec6SMatthias Ringwald     bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
4133deb3ec6SMatthias Ringwald 
4143deb3ec6SMatthias Ringwald     if (!channel){
4153deb3ec6SMatthias Ringwald         log_error("bnep_can_send_packet_now cid 0x%02x doesn't exist!", bnep_cid);
4163deb3ec6SMatthias Ringwald         return 0;
4173deb3ec6SMatthias Ringwald     }
4183deb3ec6SMatthias Ringwald 
4190b9d7e78SMatthias Ringwald     return l2cap_can_send_packet_now(channel->l2cap_cid);
4201ed1a3bdSMatthias Ringwald }
4211ed1a3bdSMatthias Ringwald 
4221ed1a3bdSMatthias Ringwald void bnep_request_can_send_now_event(uint16_t bnep_cid)
4231ed1a3bdSMatthias Ringwald {
4241ed1a3bdSMatthias Ringwald     bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
4251ed1a3bdSMatthias Ringwald 
4261ed1a3bdSMatthias Ringwald     if (!channel){
4271ed1a3bdSMatthias Ringwald         log_error("bnep_request_can_send_now_event cid 0x%02x doesn't exist!", bnep_cid);
4281ed1a3bdSMatthias Ringwald         return;
4291ed1a3bdSMatthias Ringwald     }
4301ed1a3bdSMatthias Ringwald 
4311ed1a3bdSMatthias Ringwald     channel->waiting_for_can_send_now = 1;
4321ed1a3bdSMatthias Ringwald     l2cap_request_can_send_now_event(bnep_cid);
4333deb3ec6SMatthias Ringwald }
4343deb3ec6SMatthias Ringwald 
4353deb3ec6SMatthias Ringwald 
4363deb3ec6SMatthias Ringwald static int bnep_filter_protocol(bnep_channel_t *channel, uint16_t network_protocol_type)
4373deb3ec6SMatthias Ringwald {
4383deb3ec6SMatthias Ringwald 	int i;
4393deb3ec6SMatthias Ringwald 
4403deb3ec6SMatthias Ringwald     if (channel->net_filter_count == 0) {
4413deb3ec6SMatthias Ringwald         /* No filter set */
4423deb3ec6SMatthias Ringwald         return 1;
4433deb3ec6SMatthias Ringwald     }
4443deb3ec6SMatthias Ringwald 
4453deb3ec6SMatthias Ringwald     for (i = 0; i < channel->net_filter_count; i ++) {
4463deb3ec6SMatthias Ringwald         if ((network_protocol_type >= channel->net_filter[i].range_start) &&
4473deb3ec6SMatthias Ringwald             (network_protocol_type <= channel->net_filter[i].range_end)) {
4483deb3ec6SMatthias Ringwald             return 1;
4493deb3ec6SMatthias Ringwald         }
4503deb3ec6SMatthias Ringwald     }
4513deb3ec6SMatthias Ringwald 
4523deb3ec6SMatthias Ringwald     return 0;
4533deb3ec6SMatthias Ringwald }
4543deb3ec6SMatthias Ringwald 
4553deb3ec6SMatthias Ringwald static int bnep_filter_multicast(bnep_channel_t *channel, bd_addr_t addr_dest)
4563deb3ec6SMatthias Ringwald {
4573deb3ec6SMatthias Ringwald 	int i;
4583deb3ec6SMatthias Ringwald 
4593deb3ec6SMatthias Ringwald     /* Check if the multicast flag is set int the destination address */
4603deb3ec6SMatthias Ringwald 	if ((addr_dest[0] & 0x01) == 0x00) {
4613deb3ec6SMatthias Ringwald         /* Not a multicast frame, do not apply filtering and send it in any case */
4623deb3ec6SMatthias Ringwald 		return 1;
4633deb3ec6SMatthias Ringwald     }
4643deb3ec6SMatthias Ringwald 
4653deb3ec6SMatthias Ringwald     if (channel->multicast_filter_count == 0) {
4663deb3ec6SMatthias Ringwald         /* No filter set */
4673deb3ec6SMatthias Ringwald         return 1;
4683deb3ec6SMatthias Ringwald     }
4693deb3ec6SMatthias Ringwald 
4703deb3ec6SMatthias Ringwald 	for (i = 0; i < channel->multicast_filter_count; i ++) {
4713deb3ec6SMatthias Ringwald 		if ((memcmp(addr_dest, channel->multicast_filter[i].addr_start, sizeof(bd_addr_t)) >= 0) &&
4723deb3ec6SMatthias Ringwald 		    (memcmp(addr_dest, channel->multicast_filter[i].addr_end, sizeof(bd_addr_t)) <= 0)) {
4733deb3ec6SMatthias Ringwald 			return 1;
4743deb3ec6SMatthias Ringwald         }
4753deb3ec6SMatthias Ringwald 	}
4763deb3ec6SMatthias Ringwald 
4773deb3ec6SMatthias Ringwald 	return 0;
4783deb3ec6SMatthias Ringwald }
4793deb3ec6SMatthias Ringwald 
4803deb3ec6SMatthias Ringwald 
4813deb3ec6SMatthias Ringwald /* Send BNEP ethernet packet */
4823deb3ec6SMatthias Ringwald int bnep_send(uint16_t bnep_cid, uint8_t *packet, uint16_t len)
4833deb3ec6SMatthias Ringwald {
4843deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
4853deb3ec6SMatthias Ringwald     uint8_t        *bnep_out_buffer = NULL;
4863deb3ec6SMatthias Ringwald     uint16_t        pos = 0;
4873deb3ec6SMatthias Ringwald     uint16_t        pos_out = 0;
4883deb3ec6SMatthias Ringwald     uint16_t        payload_len;
4893deb3ec6SMatthias Ringwald     int             err = 0;
4903deb3ec6SMatthias Ringwald     int             has_source;
4913deb3ec6SMatthias Ringwald     int             has_dest;
4923deb3ec6SMatthias Ringwald 
4933deb3ec6SMatthias Ringwald     bd_addr_t       addr_dest;
4943deb3ec6SMatthias Ringwald     bd_addr_t       addr_source;
4953deb3ec6SMatthias Ringwald     uint16_t        network_protocol_type;
4963deb3ec6SMatthias Ringwald 
4973deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
4983deb3ec6SMatthias Ringwald     if (channel == NULL) {
4993deb3ec6SMatthias Ringwald         log_error("bnep_send cid 0x%02x doesn't exist!", bnep_cid);
5003deb3ec6SMatthias Ringwald         return 1;
5013deb3ec6SMatthias Ringwald     }
5023deb3ec6SMatthias Ringwald 
5033deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
5043deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
5053deb3ec6SMatthias Ringwald     }
5063deb3ec6SMatthias Ringwald 
5073deb3ec6SMatthias Ringwald     /* Check for free ACL buffers */
5083deb3ec6SMatthias Ringwald     if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
5093deb3ec6SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
5103deb3ec6SMatthias Ringwald     }
5113deb3ec6SMatthias Ringwald 
5123deb3ec6SMatthias Ringwald     /* Extract destination and source address from the ethernet packet */
5133deb3ec6SMatthias Ringwald     pos = 0;
514058e3d6bSMatthias Ringwald     bd_addr_copy(addr_dest, &packet[pos]);
5153deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
516058e3d6bSMatthias Ringwald     bd_addr_copy(addr_source, &packet[pos]);
5173deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
518f8fbdce0SMatthias Ringwald     network_protocol_type = big_endian_read_16(packet, pos);
5193deb3ec6SMatthias Ringwald     pos += sizeof(uint16_t);
5203deb3ec6SMatthias Ringwald 
5213deb3ec6SMatthias Ringwald     payload_len = len - pos;
5223deb3ec6SMatthias Ringwald 
5233deb3ec6SMatthias Ringwald 	if (network_protocol_type == ETHERTYPE_VLAN) {	/* IEEE 802.1Q tag header */
5243deb3ec6SMatthias Ringwald 		if (payload_len < 4) {
5253deb3ec6SMatthias Ringwald             /* Omit this packet */
5263deb3ec6SMatthias Ringwald 			return 0;
5273deb3ec6SMatthias Ringwald         }
5283deb3ec6SMatthias Ringwald         /* The "real" network protocol type is 4 bytes ahead in a VLAN packet */
529f8fbdce0SMatthias Ringwald 		network_protocol_type = big_endian_read_16(packet, pos + 2);
5303deb3ec6SMatthias Ringwald 	}
5313deb3ec6SMatthias Ringwald 
5323deb3ec6SMatthias Ringwald     /* Check network protocol and multicast filters before sending */
5333deb3ec6SMatthias Ringwald     if (!bnep_filter_protocol(channel, network_protocol_type) ||
5343deb3ec6SMatthias Ringwald         !bnep_filter_multicast(channel, addr_dest)) {
5353deb3ec6SMatthias Ringwald         /* Packet did not pass filter... */
5363deb3ec6SMatthias Ringwald         if ((network_protocol_type == ETHERTYPE_VLAN) &&
5373deb3ec6SMatthias Ringwald             (payload_len >= 4)) {
5383deb3ec6SMatthias Ringwald             /* The packet has been tagged as a with IEE 802.1Q tag and has been filtered out.
5393deb3ec6SMatthias Ringwald                According to the spec the IEE802.1Q tag header shall be sended without ethernet payload.
5403deb3ec6SMatthias Ringwald                So limit the payload_len to 4.
5413deb3ec6SMatthias Ringwald              */
5423deb3ec6SMatthias Ringwald             payload_len = 4;
5433deb3ec6SMatthias Ringwald         } else {
5443deb3ec6SMatthias Ringwald             /* Packet is not tagged with IEE802.1Q header and was filtered out. Omit this packet */
5453deb3ec6SMatthias Ringwald             return 0;
5463deb3ec6SMatthias Ringwald         }
5473deb3ec6SMatthias Ringwald     }
5483deb3ec6SMatthias Ringwald 
5493deb3ec6SMatthias Ringwald     /* Reserve l2cap packet buffer */
5503deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
5513deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
5523deb3ec6SMatthias Ringwald 
5533deb3ec6SMatthias Ringwald     /* Check if source address is the same as our local address and if the
5543deb3ec6SMatthias Ringwald        destination address is the same as the remote addr. Maybe we can use
5553deb3ec6SMatthias Ringwald        the compressed data format
5563deb3ec6SMatthias Ringwald      */
5573deb3ec6SMatthias Ringwald     has_source = (memcmp(addr_source, channel->local_addr, ETHER_ADDR_LEN) != 0);
5583deb3ec6SMatthias Ringwald     has_dest = (memcmp(addr_dest, channel->remote_addr, ETHER_ADDR_LEN) != 0);
5593deb3ec6SMatthias Ringwald 
5603deb3ec6SMatthias Ringwald     /* Check for MTU limits */
5613deb3ec6SMatthias Ringwald     if (payload_len > channel->max_frame_size) {
5623deb3ec6SMatthias Ringwald         log_error("bnep_send: Max frame size (%d) exceeded: %d", channel->max_frame_size, payload_len);
5633deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
5643deb3ec6SMatthias Ringwald     }
5653deb3ec6SMatthias Ringwald 
5663deb3ec6SMatthias Ringwald     /* Fill in the package type depending on the given source and destination address */
5673deb3ec6SMatthias Ringwald     if (has_source && has_dest) {
5683deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_GENERAL_ETHERNET;
5693deb3ec6SMatthias Ringwald     } else
5703deb3ec6SMatthias Ringwald     if (has_source && !has_dest) {
5713deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY;
5723deb3ec6SMatthias Ringwald     } else
5733deb3ec6SMatthias Ringwald     if (!has_source && has_dest) {
5743deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY;
5753deb3ec6SMatthias Ringwald     } else {
5763deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET;
5773deb3ec6SMatthias Ringwald     }
5783deb3ec6SMatthias Ringwald 
5793deb3ec6SMatthias Ringwald     /* Add the destination address if needed */
5803deb3ec6SMatthias Ringwald     if (has_dest) {
581058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos_out, addr_dest);
5823deb3ec6SMatthias Ringwald         pos_out += sizeof(bd_addr_t);
5833deb3ec6SMatthias Ringwald     }
5843deb3ec6SMatthias Ringwald 
5853deb3ec6SMatthias Ringwald     /* Add the source address if needed */
5863deb3ec6SMatthias Ringwald     if (has_source) {
587058e3d6bSMatthias Ringwald         bd_addr_copy(bnep_out_buffer + pos_out, addr_source);
5883deb3ec6SMatthias Ringwald         pos_out += sizeof(bd_addr_t);
5893deb3ec6SMatthias Ringwald     }
5903deb3ec6SMatthias Ringwald 
5913deb3ec6SMatthias Ringwald     /* Add protocol type */
592f8fbdce0SMatthias Ringwald     big_endian_store_16(bnep_out_buffer, pos_out, network_protocol_type);
5933deb3ec6SMatthias Ringwald     pos_out += 2;
5943deb3ec6SMatthias Ringwald 
5953deb3ec6SMatthias Ringwald     /* TODO: Add extension headers, if we may support them at a later stage */
5963deb3ec6SMatthias Ringwald     /* Add the payload and then send out the package */
5973deb3ec6SMatthias Ringwald     memcpy(bnep_out_buffer + pos_out, packet + pos, payload_len);
5983deb3ec6SMatthias Ringwald     pos_out += payload_len;
5993deb3ec6SMatthias Ringwald 
6003deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos_out);
6013deb3ec6SMatthias Ringwald 
6023deb3ec6SMatthias Ringwald     if (err) {
6033deb3ec6SMatthias Ringwald         log_error("bnep_send: error %d", err);
6043deb3ec6SMatthias Ringwald     }
6053deb3ec6SMatthias Ringwald     return err;
6063deb3ec6SMatthias Ringwald }
6073deb3ec6SMatthias Ringwald 
6083deb3ec6SMatthias Ringwald 
6093deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
6103deb3ec6SMatthias Ringwald int bnep_set_net_type_filter(uint16_t bnep_cid, bnep_net_filter_t *filter, uint16_t len)
6113deb3ec6SMatthias Ringwald {
6123deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
6133deb3ec6SMatthias Ringwald 
6143deb3ec6SMatthias Ringwald     if (filter == NULL) {
6153deb3ec6SMatthias Ringwald         return -1;
6163deb3ec6SMatthias Ringwald     }
6173deb3ec6SMatthias Ringwald 
6183deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
6193deb3ec6SMatthias Ringwald     if (channel == NULL) {
6203deb3ec6SMatthias Ringwald         log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
6213deb3ec6SMatthias Ringwald         return 1;
6223deb3ec6SMatthias Ringwald     }
6233deb3ec6SMatthias Ringwald 
6243deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
6253deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
6263deb3ec6SMatthias Ringwald     }
6273deb3ec6SMatthias Ringwald 
6283deb3ec6SMatthias Ringwald     if (len > MAX_BNEP_NETFILTER_OUT) {
6293deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
6303deb3ec6SMatthias Ringwald     }
6313deb3ec6SMatthias Ringwald 
6323deb3ec6SMatthias Ringwald     channel->net_filter_out = filter;
6333deb3ec6SMatthias Ringwald     channel->net_filter_out_count = len;
6343deb3ec6SMatthias Ringwald 
6354e366553SMatthias Ringwald     /* Set flag to send out the network protocol type filter set request */
6363deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
6374e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
6383deb3ec6SMatthias Ringwald 
6393deb3ec6SMatthias Ringwald     return 0;
6403deb3ec6SMatthias Ringwald }
6413deb3ec6SMatthias Ringwald 
6423deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
6433deb3ec6SMatthias Ringwald int bnep_set_multicast_filter(uint16_t bnep_cid,  bnep_multi_filter_t *filter, uint16_t len)
6443deb3ec6SMatthias Ringwald {
6453deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
6463deb3ec6SMatthias Ringwald 
6473deb3ec6SMatthias Ringwald     if (filter == NULL) {
6483deb3ec6SMatthias Ringwald         return -1;
6493deb3ec6SMatthias Ringwald     }
6503deb3ec6SMatthias Ringwald 
6513deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
6523deb3ec6SMatthias Ringwald     if (channel == NULL) {
6533deb3ec6SMatthias Ringwald         log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
6543deb3ec6SMatthias Ringwald         return 1;
6553deb3ec6SMatthias Ringwald     }
6563deb3ec6SMatthias Ringwald 
6573deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
6583deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
6593deb3ec6SMatthias Ringwald     }
6603deb3ec6SMatthias Ringwald 
66166b1fcb3SMatthias Ringwald     if (len > MAX_BNEP_MULTICAST_FILTER_OUT) {
6623deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
6633deb3ec6SMatthias Ringwald     }
6643deb3ec6SMatthias Ringwald 
6653deb3ec6SMatthias Ringwald     channel->multicast_filter_out = filter;
6663deb3ec6SMatthias Ringwald     channel->multicast_filter_out_count = len;
6673deb3ec6SMatthias Ringwald 
6684e366553SMatthias Ringwald     /* Set flag to send out the multicast filter set request */
6693deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
6704e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
6713deb3ec6SMatthias Ringwald 
6723deb3ec6SMatthias Ringwald     return 0;
6733deb3ec6SMatthias Ringwald }
6743deb3ec6SMatthias Ringwald 
6753deb3ec6SMatthias Ringwald /* BNEP timeout timer helper function */
676ec820d77SMatthias Ringwald static void bnep_channel_timer_handler(btstack_timer_source_t *timer)
6773deb3ec6SMatthias Ringwald {
67891a977e8SMatthias Ringwald     bnep_channel_t *channel = btstack_run_loop_get_timer_context(timer);
6793deb3ec6SMatthias Ringwald     // retry send setup connection at least one time
6803deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE){
6813deb3ec6SMatthias Ringwald         if (channel->retry_count < BNEP_CONNECTION_MAX_RETRIES){
6823deb3ec6SMatthias Ringwald             channel->retry_count++;
6833deb3ec6SMatthias Ringwald             bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
6843deb3ec6SMatthias Ringwald             bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
6854e366553SMatthias Ringwald             l2cap_request_can_send_now_event(channel->l2cap_cid);
6863deb3ec6SMatthias Ringwald             return;
6873deb3ec6SMatthias Ringwald         }
6883deb3ec6SMatthias Ringwald     }
6893deb3ec6SMatthias Ringwald 
6903deb3ec6SMatthias Ringwald     log_info( "bnep_channel_timeout_handler callback: shutting down connection!");
6913deb3ec6SMatthias Ringwald     bnep_emit_channel_timeout(channel);
6923deb3ec6SMatthias Ringwald     bnep_channel_finalize(channel);
6933deb3ec6SMatthias Ringwald }
6943deb3ec6SMatthias Ringwald 
6953deb3ec6SMatthias Ringwald 
6963deb3ec6SMatthias Ringwald static void bnep_channel_stop_timer(bnep_channel_t *channel)
6973deb3ec6SMatthias Ringwald {
6983deb3ec6SMatthias Ringwald     if (channel->timer_active) {
699528a4a3bSMatthias Ringwald         btstack_run_loop_remove_timer(&channel->timer);
7003deb3ec6SMatthias Ringwald         channel->timer_active = 0;
7013deb3ec6SMatthias Ringwald     }
7023deb3ec6SMatthias Ringwald }
7033deb3ec6SMatthias Ringwald 
7043deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout)
7053deb3ec6SMatthias Ringwald {
7063deb3ec6SMatthias Ringwald     /* Stop any eventually running timeout timer */
7073deb3ec6SMatthias Ringwald     bnep_channel_stop_timer(channel);
7083deb3ec6SMatthias Ringwald 
7093deb3ec6SMatthias Ringwald     /* Start bnep channel timeout check timer */
710528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&channel->timer, timeout);
71191a977e8SMatthias Ringwald     btstack_run_loop_set_timer_handler(&channel->timer, bnep_channel_timer_handler);
71291a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&channel->timer, channel);
713528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&channel->timer);
7143deb3ec6SMatthias Ringwald     channel->timer_active = 1;
7153deb3ec6SMatthias Ringwald }
7163deb3ec6SMatthias Ringwald 
7173deb3ec6SMatthias Ringwald /* BNEP statemachine functions */
7183deb3ec6SMatthias Ringwald 
7193deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
7203deb3ec6SMatthias Ringwald     channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var | event);
7213deb3ec6SMatthias Ringwald }
7223deb3ec6SMatthias Ringwald inline static void bnep_channel_state_remove(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
7233deb3ec6SMatthias Ringwald     channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var & ~event);
7243deb3ec6SMatthias Ringwald }
7253deb3ec6SMatthias Ringwald 
7263deb3ec6SMatthias Ringwald static uint16_t bnep_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
7273deb3ec6SMatthias Ringwald 
7283deb3ec6SMatthias Ringwald     /* Assume a standard BNEP header, containing BNEP Type (1 Byte), dest and
7293deb3ec6SMatthias Ringwald        source address (6 bytes each) and networking protocol type (2 bytes)
7303deb3ec6SMatthias Ringwald      */
7313deb3ec6SMatthias Ringwald     uint16_t max_frame_size = l2cap_mtu - 15; // 15 bytes BNEP header
7323deb3ec6SMatthias Ringwald 
7333deb3ec6SMatthias Ringwald     log_info("bnep_max_frame_size_for_l2cap_mtu:  %u -> %u", l2cap_mtu, max_frame_size);
7343deb3ec6SMatthias Ringwald     return max_frame_size;
7353deb3ec6SMatthias Ringwald }
7363deb3ec6SMatthias Ringwald 
7373deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_create_for_addr(bd_addr_t addr)
7383deb3ec6SMatthias Ringwald {
7393deb3ec6SMatthias Ringwald     /* Allocate new channel structure */
7403deb3ec6SMatthias Ringwald     bnep_channel_t *channel = btstack_memory_bnep_channel_get();
7413deb3ec6SMatthias Ringwald     if (!channel) {
7423deb3ec6SMatthias Ringwald         return NULL;
7433deb3ec6SMatthias Ringwald     }
7443deb3ec6SMatthias Ringwald 
7453deb3ec6SMatthias Ringwald     channel->state = BNEP_CHANNEL_STATE_CLOSED;
7463deb3ec6SMatthias Ringwald     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
74773988a59SMatthias Ringwald     bd_addr_copy(channel->remote_addr, addr);
74815a95bd5SMatthias Ringwald     gap_local_bd_addr(channel->local_addr);
7493deb3ec6SMatthias Ringwald 
7503deb3ec6SMatthias Ringwald     channel->net_filter_count = 0;
7513deb3ec6SMatthias Ringwald     channel->multicast_filter_count = 0;
7523deb3ec6SMatthias Ringwald     channel->retry_count = 0;
7533deb3ec6SMatthias Ringwald 
7543deb3ec6SMatthias Ringwald     /* Finally add it to the channel list */
755665d90f2SMatthias Ringwald     btstack_linked_list_add(&bnep_channels, (btstack_linked_item_t *) channel);
7563deb3ec6SMatthias Ringwald 
7573deb3ec6SMatthias Ringwald     return channel;
7583deb3ec6SMatthias Ringwald }
7593deb3ec6SMatthias Ringwald 
7603deb3ec6SMatthias Ringwald static bnep_channel_t* bnep_channel_for_addr(bd_addr_t addr)
7613deb3ec6SMatthias Ringwald {
762665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
763665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){
7643deb3ec6SMatthias Ringwald         bnep_channel_t *channel = ((bnep_channel_t *) it);
765058e3d6bSMatthias Ringwald         if (bd_addr_cmp(addr, channel->remote_addr) == 0) {
7663deb3ec6SMatthias Ringwald             return channel;
7673deb3ec6SMatthias Ringwald         }
7683deb3ec6SMatthias Ringwald     }
7693deb3ec6SMatthias Ringwald     return NULL;
7703deb3ec6SMatthias Ringwald }
7713deb3ec6SMatthias Ringwald 
7723deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid)
7733deb3ec6SMatthias Ringwald {
774665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
775665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = it->next){
7763deb3ec6SMatthias Ringwald         bnep_channel_t *channel = ((bnep_channel_t *) it);
7773deb3ec6SMatthias Ringwald         if (channel->l2cap_cid == l2cap_cid) {
7783deb3ec6SMatthias Ringwald             return channel;
7793deb3ec6SMatthias Ringwald         }
7803deb3ec6SMatthias Ringwald     }
7813deb3ec6SMatthias Ringwald     return NULL;
7823deb3ec6SMatthias Ringwald }
7833deb3ec6SMatthias Ringwald 
7843deb3ec6SMatthias Ringwald static bnep_service_t * bnep_service_for_uuid(uint16_t uuid)
7853deb3ec6SMatthias Ringwald {
786665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
787665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_services; it ; it = it->next){
7883deb3ec6SMatthias Ringwald         bnep_service_t * service = ((bnep_service_t *) it);
7893deb3ec6SMatthias Ringwald         if ( service->service_uuid == uuid){
7903deb3ec6SMatthias Ringwald             return service;
7913deb3ec6SMatthias Ringwald         }
7923deb3ec6SMatthias Ringwald     }
7933deb3ec6SMatthias Ringwald     return NULL;
7943deb3ec6SMatthias Ringwald }
7953deb3ec6SMatthias Ringwald 
7963deb3ec6SMatthias Ringwald static void bnep_channel_free(bnep_channel_t *channel)
7973deb3ec6SMatthias Ringwald {
798665d90f2SMatthias Ringwald     btstack_linked_list_remove( &bnep_channels, (btstack_linked_item_t *) channel);
7993deb3ec6SMatthias Ringwald     btstack_memory_bnep_channel_free(channel);
8003deb3ec6SMatthias Ringwald }
8013deb3ec6SMatthias Ringwald 
8023deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel)
8033deb3ec6SMatthias Ringwald {
8043deb3ec6SMatthias Ringwald     uint16_t l2cap_cid;
8053deb3ec6SMatthias Ringwald 
8063deb3ec6SMatthias Ringwald     /* Inform application about closed channel */
8073deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
8083deb3ec6SMatthias Ringwald         bnep_emit_channel_closed(channel);
8093deb3ec6SMatthias Ringwald     }
8103deb3ec6SMatthias Ringwald 
8113deb3ec6SMatthias Ringwald     l2cap_cid = channel->l2cap_cid;
8123deb3ec6SMatthias Ringwald 
8133deb3ec6SMatthias Ringwald     /* Stop any eventually running timer */
8143deb3ec6SMatthias Ringwald     bnep_channel_stop_timer(channel);
8153deb3ec6SMatthias Ringwald 
8163deb3ec6SMatthias Ringwald     /* Free ressources and then close the l2cap channel */
8173deb3ec6SMatthias Ringwald     bnep_channel_free(channel);
818ce8f182eSMatthias Ringwald     l2cap_disconnect(l2cap_cid, 0x13);
8193deb3ec6SMatthias Ringwald }
8203deb3ec6SMatthias Ringwald 
8213deb3ec6SMatthias Ringwald static int bnep_handle_connection_request(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
8223deb3ec6SMatthias Ringwald {
8233deb3ec6SMatthias Ringwald     uint16_t uuid_size;
824bb015fa7SMatthias Ringwald     uint16_t uuid_offset = 0; // avoid "may be unitialized when used" in clang
8253deb3ec6SMatthias Ringwald     uuid_size = packet[1];
8263deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_SETUP_SUCCESS;
8273deb3ec6SMatthias Ringwald     bnep_service_t * service;
8283deb3ec6SMatthias Ringwald 
8293deb3ec6SMatthias Ringwald     /* Sanity check packet size */
8303deb3ec6SMatthias Ringwald     if (size < 1 + 1 + 2 * uuid_size) {
8313deb3ec6SMatthias Ringwald         return 0;
8323deb3ec6SMatthias Ringwald     }
8333deb3ec6SMatthias Ringwald 
8343deb3ec6SMatthias Ringwald     if ((channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
8353deb3ec6SMatthias Ringwald         (channel->state != BNEP_CHANNEL_STATE_CONNECTED)) {
8363deb3ec6SMatthias Ringwald         /* Ignore a connection request if not waiting for or still connected */
8373deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_REQUEST: ignored in state %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
8383deb3ec6SMatthias Ringwald         return 0;
8393deb3ec6SMatthias Ringwald     }
8403deb3ec6SMatthias Ringwald 
8413deb3ec6SMatthias Ringwald      /* Extract source and destination UUID and convert them to UUID16 format */
8423deb3ec6SMatthias Ringwald     switch (uuid_size) {
8433deb3ec6SMatthias Ringwald         case 2:  /* UUID16  */
8443deb3ec6SMatthias Ringwald             uuid_offset = 0;
8453deb3ec6SMatthias Ringwald             break;
8463deb3ec6SMatthias Ringwald         case 4:  /* UUID32  */
8473deb3ec6SMatthias Ringwald         case 16: /* UUID128 */
8483deb3ec6SMatthias Ringwald             uuid_offset = 2;
8493deb3ec6SMatthias Ringwald             break;
8503deb3ec6SMatthias Ringwald         default:
8513deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid UUID size %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
8523deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_SERVICE_UUID_SIZE;
8533deb3ec6SMatthias Ringwald             break;
8543deb3ec6SMatthias Ringwald     }
8553deb3ec6SMatthias Ringwald 
8563deb3ec6SMatthias Ringwald     /* Check source and destination UUIDs for valid combinations */
8573deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_SETUP_SUCCESS) {
858f8fbdce0SMatthias Ringwald         channel->uuid_dest = big_endian_read_16(packet, 2 + uuid_offset);
859f8fbdce0SMatthias Ringwald         channel->uuid_source = big_endian_read_16(packet, 2 + uuid_offset + uuid_size);
8603deb3ec6SMatthias Ringwald 
861235946f1SMatthias Ringwald         if ((channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU) &&
862235946f1SMatthias Ringwald             (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_NAP) &&
863235946f1SMatthias Ringwald             (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_GN)) {
8643deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid destination service UUID: %04x", channel->uuid_dest);
8653deb3ec6SMatthias Ringwald             channel->uuid_dest = 0;
8663deb3ec6SMatthias Ringwald         }
867235946f1SMatthias Ringwald         if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) &&
868235946f1SMatthias Ringwald             (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_NAP) &&
869235946f1SMatthias Ringwald             (channel->uuid_source != BLUETOOTH_SERVICE_CLASS_GN)) {
8703deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid source service UUID: %04x", channel->uuid_source);
8713deb3ec6SMatthias Ringwald             channel->uuid_source = 0;
8723deb3ec6SMatthias Ringwald         }
8733deb3ec6SMatthias Ringwald 
8743deb3ec6SMatthias Ringwald         /* Check if we have registered a service for the requested destination UUID */
8753deb3ec6SMatthias Ringwald         service = bnep_service_for_uuid(channel->uuid_dest);
8763deb3ec6SMatthias Ringwald         if (service == NULL) {
8773deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID;
8780c249750SMatthias Ringwald         } else {
8790c249750SMatthias Ringwald             // use packet handler for service
8800c249750SMatthias Ringwald             channel->packet_handler = service->packet_handler;
8810c249750SMatthias Ringwald 
882235946f1SMatthias Ringwald             if ((channel->uuid_source != BLUETOOTH_SERVICE_CLASS_PANU) && (channel->uuid_dest != BLUETOOTH_SERVICE_CLASS_PANU)) {
8833deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID;
8843deb3ec6SMatthias Ringwald             }
8853deb3ec6SMatthias Ringwald         }
8860c249750SMatthias Ringwald     }
8873deb3ec6SMatthias Ringwald 
8883deb3ec6SMatthias Ringwald     /* Set flag to send out the connection response on next statemachine cycle */
8893deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
8903deb3ec6SMatthias Ringwald     channel->response_code = response_code;
8914e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
8923deb3ec6SMatthias Ringwald 
8933deb3ec6SMatthias Ringwald     /* Return the number of processed package bytes = BNEP Type, BNEP Control Type, UUID-Size + 2 * UUID */
8943deb3ec6SMatthias Ringwald     return 1 + 1 + 2 * uuid_size;
8953deb3ec6SMatthias Ringwald }
8963deb3ec6SMatthias Ringwald 
8973deb3ec6SMatthias Ringwald static int bnep_handle_connection_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
8983deb3ec6SMatthias Ringwald {
8993deb3ec6SMatthias Ringwald     uint16_t response_code;
9003deb3ec6SMatthias Ringwald 
9013deb3ec6SMatthias Ringwald     /* Sanity check packet size */
9023deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
9033deb3ec6SMatthias Ringwald         return 0;
9043deb3ec6SMatthias Ringwald     }
9053deb3ec6SMatthias Ringwald 
9063deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE) {
9073deb3ec6SMatthias Ringwald         /* Ignore a connection response in any state but WAIT_FOR_CONNECTION_RESPONSE */
9083deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_RESPONSE: Ignored in channel state %d", channel->state);
9093deb3ec6SMatthias Ringwald         return 1 + 2;
9103deb3ec6SMatthias Ringwald     }
9113deb3ec6SMatthias Ringwald 
912f8fbdce0SMatthias Ringwald     response_code = big_endian_read_16(packet, 1);
9133deb3ec6SMatthias Ringwald 
9143deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_SETUP_SUCCESS) {
9153deb3ec6SMatthias Ringwald         log_info("BNEP_CONNECTION_RESPONSE: Channel established to %s", bd_addr_to_str(channel->remote_addr));
9163deb3ec6SMatthias Ringwald         channel->state = BNEP_CHANNEL_STATE_CONNECTED;
9173deb3ec6SMatthias Ringwald         /* Stop timeout timer! */
9183deb3ec6SMatthias Ringwald         bnep_channel_stop_timer(channel);
9193deb3ec6SMatthias Ringwald         bnep_emit_open_channel_complete(channel, 0);
9203deb3ec6SMatthias Ringwald     } else {
9213deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_RESPONSE: Connection to %s failed. Err: %d", bd_addr_to_str(channel->remote_addr), response_code);
9223deb3ec6SMatthias Ringwald         bnep_channel_finalize(channel);
9233deb3ec6SMatthias Ringwald     }
9243deb3ec6SMatthias Ringwald     return 1 + 2;
9253deb3ec6SMatthias Ringwald }
9263deb3ec6SMatthias Ringwald 
9273deb3ec6SMatthias Ringwald static int bnep_can_handle_extensions(bnep_channel_t * channel){
9283deb3ec6SMatthias Ringwald     /* Extension are primarily handled in CONNECTED state */
9293deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) return 1;
9303deb3ec6SMatthias Ringwald     /* and if we've received connection request, but haven't sent the reponse yet. */
9313deb3ec6SMatthias Ringwald     if ((channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
9323deb3ec6SMatthias Ringwald         (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE)) {
9333deb3ec6SMatthias Ringwald         return 1;
9343deb3ec6SMatthias Ringwald     }
9353deb3ec6SMatthias Ringwald     return 0;
9363deb3ec6SMatthias Ringwald }
9373deb3ec6SMatthias Ringwald 
9383deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9393deb3ec6SMatthias Ringwald {
9403deb3ec6SMatthias Ringwald     uint16_t list_length;
9413deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
9423deb3ec6SMatthias Ringwald 
9433deb3ec6SMatthias Ringwald     /* Sanity check packet size */
9443deb3ec6SMatthias Ringwald     if (size < 3) {
9453deb3ec6SMatthias Ringwald         return 0;
9463deb3ec6SMatthias Ringwald     }
9473deb3ec6SMatthias Ringwald 
948f8fbdce0SMatthias Ringwald     list_length = big_endian_read_16(packet, 1);
9493deb3ec6SMatthias Ringwald     /* Sanity check packet size again with known package size */
9503deb3ec6SMatthias Ringwald     if (size < 3 + list_length) {
9513deb3ec6SMatthias Ringwald         return 0;
9523deb3ec6SMatthias Ringwald     }
9533deb3ec6SMatthias Ringwald 
9543deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
9553deb3ec6SMatthias Ringwald         log_error("BNEP_FILTER_NET_TYPE_SET: Ignored in channel state %d", channel->state);
9563deb3ec6SMatthias Ringwald         return 3 + list_length;
9573deb3ec6SMatthias Ringwald     }
9583deb3ec6SMatthias Ringwald 
9593deb3ec6SMatthias Ringwald     /* Check if we have enough space for more filters */
9603deb3ec6SMatthias Ringwald     if ((list_length / (2*2)) > MAX_BNEP_NETFILTER) {
9613deb3ec6SMatthias Ringwald         log_info("BNEP_FILTER_NET_TYPE_SET: Too many filter");
9623deb3ec6SMatthias Ringwald         response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
9633deb3ec6SMatthias Ringwald     } else {
9643deb3ec6SMatthias Ringwald         int i;
9653deb3ec6SMatthias Ringwald         channel->net_filter_count = 0;
9663deb3ec6SMatthias Ringwald         /* There is still enough space, copy the filters to our filter list */
967ef907034SMatthias Ringwald         /* There is still enough space, copy the filters to our filter list */
9683deb3ec6SMatthias Ringwald         for (i = 0; i < list_length / (2 * 2); i ++) {
969f8fbdce0SMatthias Ringwald             channel->net_filter[channel->net_filter_count].range_start = big_endian_read_16(packet, 1 + 2 + i * 4);
970f8fbdce0SMatthias Ringwald             channel->net_filter[channel->net_filter_count].range_end = big_endian_read_16(packet, 1 + 2 + i * 4 + 2);
9713deb3ec6SMatthias Ringwald             if (channel->net_filter[channel->net_filter_count].range_start > channel->net_filter[channel->net_filter_count].range_end) {
9723deb3ec6SMatthias Ringwald                 /* Invalid filter range, ignore this filter rule */
9733deb3ec6SMatthias Ringwald                 log_error("BNEP_FILTER_NET_TYPE_SET: Invalid filter: start: %d, end: %d",
9743deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_start,
9753deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_end);
9763deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
9773deb3ec6SMatthias Ringwald             } else {
9783deb3ec6SMatthias Ringwald                 /* Valid filter, increase the filter count */
9793deb3ec6SMatthias Ringwald                 log_info("BNEP_FILTER_NET_TYPE_SET: Add filter: start: %d, end: %d",
9803deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_start,
9813deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_end);
9823deb3ec6SMatthias Ringwald                 channel->net_filter_count ++;
9833deb3ec6SMatthias Ringwald             }
9843deb3ec6SMatthias Ringwald         }
9853deb3ec6SMatthias Ringwald     }
9863deb3ec6SMatthias Ringwald 
9873deb3ec6SMatthias Ringwald     /* Set flag to send out the set net filter response on next statemachine cycle */
9883deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
9893deb3ec6SMatthias Ringwald     channel->response_code = response_code;
9904e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
9913deb3ec6SMatthias Ringwald 
9923deb3ec6SMatthias Ringwald     return 3 + list_length;
9933deb3ec6SMatthias Ringwald }
9943deb3ec6SMatthias Ringwald 
9953deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
9963deb3ec6SMatthias Ringwald {
9973deb3ec6SMatthias Ringwald 	uint16_t response_code;
9983deb3ec6SMatthias Ringwald 
9993deb3ec6SMatthias Ringwald     // TODO: Currently we do not support setting a network filter.
10003deb3ec6SMatthias Ringwald 
10013deb3ec6SMatthias Ringwald     /* Sanity check packet size */
10023deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
10033deb3ec6SMatthias Ringwald         return 0;
10043deb3ec6SMatthias Ringwald     }
10053deb3ec6SMatthias Ringwald 
10063deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
10073deb3ec6SMatthias Ringwald         log_error("BNEP_FILTER_NET_TYPE_RESPONSE: Ignored in channel state %d", channel->state);
10083deb3ec6SMatthias Ringwald         return 1 + 2;
10093deb3ec6SMatthias Ringwald     }
10103deb3ec6SMatthias Ringwald 
1011f8fbdce0SMatthias Ringwald     response_code = big_endian_read_16(packet, 1);
10123deb3ec6SMatthias Ringwald 
10133deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_FILTER_SUCCESS) {
10143deb3ec6SMatthias Ringwald         log_info("BNEP_FILTER_NET_TYPE_RESPONSE: Net filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
10153deb3ec6SMatthias Ringwald     } else {
10163deb3ec6SMatthias 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);
10173deb3ec6SMatthias Ringwald     }
10183deb3ec6SMatthias Ringwald 
10193deb3ec6SMatthias Ringwald     return 1 + 2;
10203deb3ec6SMatthias Ringwald }
10213deb3ec6SMatthias Ringwald 
10223deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
10233deb3ec6SMatthias Ringwald {
10243deb3ec6SMatthias Ringwald     uint16_t list_length;
10253deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
10263deb3ec6SMatthias Ringwald 
10273deb3ec6SMatthias Ringwald     /* Sanity check packet size */
10283deb3ec6SMatthias Ringwald     if (size < 3) {
10293deb3ec6SMatthias Ringwald         return 0;
10303deb3ec6SMatthias Ringwald     }
10313deb3ec6SMatthias Ringwald 
1032f8fbdce0SMatthias Ringwald     list_length = big_endian_read_16(packet, 1);
10333deb3ec6SMatthias Ringwald     /* Sanity check packet size again with known package size */
10343deb3ec6SMatthias Ringwald     if (size < 3 + list_length) {
10353deb3ec6SMatthias Ringwald         return 0;
10363deb3ec6SMatthias Ringwald     }
10373deb3ec6SMatthias Ringwald 
10383deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
10393deb3ec6SMatthias Ringwald         log_error("BNEP_MULTI_ADDR_SET: Ignored in channel state %d", channel->state);
10403deb3ec6SMatthias Ringwald         return 3 + list_length;
10413deb3ec6SMatthias Ringwald     }
10423deb3ec6SMatthias Ringwald 
10433deb3ec6SMatthias Ringwald     /* Check if we have enough space for more filters */
10443deb3ec6SMatthias Ringwald     if ((list_length / (2 * ETHER_ADDR_LEN)) > MAX_BNEP_MULTICAST_FILTER) {
10453deb3ec6SMatthias Ringwald         log_info("BNEP_MULTI_ADDR_SET: Too many filter");
10463deb3ec6SMatthias Ringwald         response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
10473deb3ec6SMatthias Ringwald     } else {
10483deb3ec6SMatthias Ringwald         unsigned int i;
10493deb3ec6SMatthias Ringwald         channel->multicast_filter_count = 0;
10503deb3ec6SMatthias Ringwald         /* There is enough space, copy the filters to our filter list */
10513deb3ec6SMatthias Ringwald         for (i = 0; i < list_length / (2 * ETHER_ADDR_LEN); i ++) {
1052058e3d6bSMatthias Ringwald             bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_start, packet + 1 + 2 + i * ETHER_ADDR_LEN * 2);
1053058e3d6bSMatthias Ringwald             bd_addr_copy(channel->multicast_filter[channel->multicast_filter_count].addr_end, packet + 1 + 2 + i * ETHER_ADDR_LEN * 2 + ETHER_ADDR_LEN);
10543deb3ec6SMatthias Ringwald 
10553deb3ec6SMatthias Ringwald             if (memcmp(channel->multicast_filter[channel->multicast_filter_count].addr_start,
10563deb3ec6SMatthias Ringwald                        channel->multicast_filter[channel->multicast_filter_count].addr_end, ETHER_ADDR_LEN) > 0) {
10573deb3ec6SMatthias Ringwald                 /* Invalid filter range, ignore this filter rule */
10583deb3ec6SMatthias Ringwald                 log_error("BNEP_MULTI_ADDR_SET: Invalid filter: start: %s",
10593deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
10603deb3ec6SMatthias Ringwald                 log_error("BNEP_MULTI_ADDR_SET: Invalid filter: end: %s",
10613deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
10623deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
10633deb3ec6SMatthias Ringwald             } else {
10643deb3ec6SMatthias Ringwald                 /* Valid filter, increase the filter count */
10653deb3ec6SMatthias Ringwald                 log_info("BNEP_MULTI_ADDR_SET: Add filter: start: %s",
10663deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
10673deb3ec6SMatthias Ringwald                 log_info("BNEP_MULTI_ADDR_SET: Add filter: end: %s",
10683deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
10693deb3ec6SMatthias Ringwald                 channel->multicast_filter_count ++;
10703deb3ec6SMatthias Ringwald             }
10713deb3ec6SMatthias Ringwald         }
10723deb3ec6SMatthias Ringwald     }
10733deb3ec6SMatthias Ringwald     /* Set flag to send out the set multi addr response on next statemachine cycle */
10743deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
10753deb3ec6SMatthias Ringwald     channel->response_code = response_code;
10764e366553SMatthias Ringwald     l2cap_request_can_send_now_event(channel->l2cap_cid);
10773deb3ec6SMatthias Ringwald 
10783deb3ec6SMatthias Ringwald     return 3 + list_length;
10793deb3ec6SMatthias Ringwald }
10803deb3ec6SMatthias Ringwald 
10813deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
10823deb3ec6SMatthias Ringwald {
10833deb3ec6SMatthias Ringwald 	uint16_t response_code;
10843deb3ec6SMatthias Ringwald 
10853deb3ec6SMatthias Ringwald     // TODO: Currently we do not support setting multicast address filter.
10863deb3ec6SMatthias Ringwald 
10873deb3ec6SMatthias Ringwald     /* Sanity check packet size */
10883deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
10893deb3ec6SMatthias Ringwald         return 0;
10903deb3ec6SMatthias Ringwald     }
10913deb3ec6SMatthias Ringwald 
10923deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
10933deb3ec6SMatthias Ringwald         log_error("BNEP_MULTI_ADDR_RESPONSE: Ignored in channel state %d", channel->state);
10943deb3ec6SMatthias Ringwald         return 1 + 2;
10953deb3ec6SMatthias Ringwald     }
10963deb3ec6SMatthias Ringwald 
1097f8fbdce0SMatthias Ringwald     response_code = big_endian_read_16(packet, 1);
10983deb3ec6SMatthias Ringwald 
10993deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_FILTER_SUCCESS) {
11003deb3ec6SMatthias Ringwald         log_info("BNEP_MULTI_ADDR_RESPONSE: Multicast address filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
11013deb3ec6SMatthias Ringwald     } else {
11023deb3ec6SMatthias 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);
11033deb3ec6SMatthias Ringwald     }
11043deb3ec6SMatthias Ringwald 
11053deb3ec6SMatthias Ringwald     return 1 + 2;
11063deb3ec6SMatthias Ringwald }
11073deb3ec6SMatthias Ringwald 
11083deb3ec6SMatthias 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)
11093deb3ec6SMatthias Ringwald {
11103deb3ec6SMatthias Ringwald     uint16_t pos = 0;
11113deb3ec6SMatthias Ringwald 
1112f2e45468SMatthias 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)
11133deb3ec6SMatthias Ringwald     /* In-place modify the package and add the ethernet header in front of the payload.
11143deb3ec6SMatthias Ringwald      * WARNING: This modifies the data in front of the payload and may overwrite 14 bytes there!
11153deb3ec6SMatthias Ringwald      */
11163deb3ec6SMatthias Ringwald     uint8_t *ethernet_packet = payload - 2 * sizeof(bd_addr_t) - sizeof(uint16_t);
11173deb3ec6SMatthias Ringwald     /* Restore the ethernet packet header */
1118058e3d6bSMatthias Ringwald     bd_addr_copy(ethernet_packet + pos, addr_dest);
11193deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1120058e3d6bSMatthias Ringwald     bd_addr_copy(ethernet_packet + pos, addr_source);
11213deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1122f8fbdce0SMatthias Ringwald     big_endian_store_16(ethernet_packet, pos, network_protocol_type);
11233deb3ec6SMatthias Ringwald     /* Payload is just in place... */
11243deb3ec6SMatthias Ringwald #else
1125f2e45468SMatthias Ringwald #error "BNEP requires HCI_INCOMING_PRE_BUFFER_SIZE >= 6. Please update bstack_config.h"
11263deb3ec6SMatthias Ringwald #endif
11273deb3ec6SMatthias Ringwald 
11283deb3ec6SMatthias Ringwald     /* Notify application layer and deliver the ethernet packet */
1129c9bf9c27SMatthias Ringwald     if (channel->packet_handler){
1130c9bf9c27SMatthias Ringwald         (*channel->packet_handler)(BNEP_DATA_PACKET, channel->l2cap_cid, ethernet_packet,
1131c9bf9c27SMatthias Ringwald                                    size + sizeof(uint16_t) + 2 * sizeof(bd_addr_t));
1132c9bf9c27SMatthias Ringwald     }
11333deb3ec6SMatthias Ringwald 
11343deb3ec6SMatthias Ringwald     return size;
11353deb3ec6SMatthias Ringwald }
11363deb3ec6SMatthias Ringwald 
11373deb3ec6SMatthias Ringwald static int bnep_handle_control_packet(bnep_channel_t *channel, uint8_t *packet, uint16_t size, int is_extension)
11383deb3ec6SMatthias Ringwald {
11393deb3ec6SMatthias Ringwald     uint16_t len = 0;
11403deb3ec6SMatthias Ringwald     uint8_t  bnep_control_type;
11413deb3ec6SMatthias Ringwald 
11423deb3ec6SMatthias Ringwald     bnep_control_type = packet[0];
11433deb3ec6SMatthias Ringwald     /* Save last control type. Needed by statemachin in case of unknown control code */
11443deb3ec6SMatthias Ringwald 
11453deb3ec6SMatthias Ringwald     channel->last_control_type = bnep_control_type;
11463deb3ec6SMatthias Ringwald     log_info("BNEP_CONTROL: Type: %d, size: %d, is_extension: %d", bnep_control_type, size, is_extension);
11473deb3ec6SMatthias Ringwald     switch (bnep_control_type) {
11483deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD:
11493deb3ec6SMatthias Ringwald             /* The last command we send was not understood. We should close the connection */
11503deb3ec6SMatthias Ringwald             log_error("BNEP_CONTROL: Received COMMAND_NOT_UNDERSTOOD: l2cap_cid: %d, cmd: %d", channel->l2cap_cid, packet[3]);
11513deb3ec6SMatthias Ringwald             bnep_channel_finalize(channel);
11523deb3ec6SMatthias Ringwald             len = 2; // Length of command not understood packet - bnep-type field
11533deb3ec6SMatthias Ringwald             break;
11543deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST:
11553deb3ec6SMatthias Ringwald             if (is_extension) {
11563deb3ec6SMatthias Ringwald                 /* Connection requests are not allowed to be send in an extension header
11573deb3ec6SMatthias Ringwald                  *  ignore, do not set "COMMAND_NOT_UNDERSTOOD"
11583deb3ec6SMatthias Ringwald                  */
11593deb3ec6SMatthias Ringwald                 log_error("BNEP_CONTROL: Received SETUP_CONNECTION_REQUEST in extension header: l2cap_cid: %d", channel->l2cap_cid);
11603deb3ec6SMatthias Ringwald                 return 0;
11613deb3ec6SMatthias Ringwald             } else {
11623deb3ec6SMatthias Ringwald                 len = bnep_handle_connection_request(channel, packet, size);
11633deb3ec6SMatthias Ringwald             }
11643deb3ec6SMatthias Ringwald             break;
11653deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE:
11663deb3ec6SMatthias Ringwald             if (is_extension) {
11673deb3ec6SMatthias Ringwald                 /* Connection requests are not allowed to be send in an
11683deb3ec6SMatthias Ringwald                  * extension header, ignore, do not set "COMMAND_NOT_UNDERSTOOD"
11693deb3ec6SMatthias Ringwald                  */
11703deb3ec6SMatthias Ringwald                 log_error("BNEP_CONTROL: Received SETUP_CONNECTION_RESPONSE in extension header: l2cap_cid: %d", channel->l2cap_cid);
11713deb3ec6SMatthias Ringwald                 return 0;
11723deb3ec6SMatthias Ringwald             } else {
11733deb3ec6SMatthias Ringwald                 len = bnep_handle_connection_response(channel, packet, size);
11743deb3ec6SMatthias Ringwald             }
11753deb3ec6SMatthias Ringwald             break;
11763deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET:
11773deb3ec6SMatthias Ringwald             len = bnep_handle_filter_net_type_set(channel, packet, size);
11783deb3ec6SMatthias Ringwald             break;
11793deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE:
11803deb3ec6SMatthias Ringwald             len = bnep_handle_filter_net_type_response(channel, packet, size);
11813deb3ec6SMatthias Ringwald             break;
11823deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET:
11833deb3ec6SMatthias Ringwald             len = bnep_handle_multi_addr_set(channel, packet, size);
11843deb3ec6SMatthias Ringwald             break;
11853deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE:
11863deb3ec6SMatthias Ringwald             len = bnep_handle_multi_addr_response(channel, packet, size);
11873deb3ec6SMatthias Ringwald             break;
11883deb3ec6SMatthias Ringwald         default:
11893deb3ec6SMatthias Ringwald             log_error("BNEP_CONTROL: Invalid bnep control type: l2cap_cid: %d, cmd: %d", channel->l2cap_cid, bnep_control_type);
11903deb3ec6SMatthias Ringwald             len = 0;
11913deb3ec6SMatthias Ringwald             break;
11923deb3ec6SMatthias Ringwald     }
11933deb3ec6SMatthias Ringwald 
11943deb3ec6SMatthias Ringwald     if (len == 0) {
11953deb3ec6SMatthias Ringwald         /* In case the command could not be handled, send a
11963deb3ec6SMatthias Ringwald            COMMAND_NOT_UNDERSTOOD message.
11973deb3ec6SMatthias Ringwald            Set flag to process the request in the next statemachine loop
11983deb3ec6SMatthias Ringwald          */
11993deb3ec6SMatthias Ringwald         bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
12004e366553SMatthias Ringwald         l2cap_request_can_send_now_event(channel->l2cap_cid);
12013deb3ec6SMatthias Ringwald     }
12023deb3ec6SMatthias Ringwald 
12033deb3ec6SMatthias Ringwald     return len;
12043deb3ec6SMatthias Ringwald }
12053deb3ec6SMatthias Ringwald 
12063deb3ec6SMatthias Ringwald /**
12073deb3ec6SMatthias Ringwald  * @return handled packet
12083deb3ec6SMatthias Ringwald  */
12093deb3ec6SMatthias Ringwald static int bnep_hci_event_handler(uint8_t *packet, uint16_t size)
12103deb3ec6SMatthias Ringwald {
1211f21eb74fSMatthias Ringwald     UNUSED(size);   // ok: handling own l2cap events
12129ec2630cSMatthias Ringwald 
12133deb3ec6SMatthias Ringwald     bd_addr_t event_addr;
12143deb3ec6SMatthias Ringwald     uint16_t  psm;
12153deb3ec6SMatthias Ringwald     uint16_t  l2cap_cid;
12163deb3ec6SMatthias Ringwald     hci_con_handle_t con_handle;
12173deb3ec6SMatthias Ringwald     bnep_channel_t  *channel = NULL;
12183deb3ec6SMatthias Ringwald     uint8_t   status;
12193deb3ec6SMatthias Ringwald 
12200e2df43fSMatthias Ringwald     switch (hci_event_packet_get_type(packet)) {
12213deb3ec6SMatthias Ringwald 
1222235946f1SMatthias Ringwald         /* Accept an incoming L2CAP connection on BLUETOOTH_PROTOCOL_BNEP */
12233deb3ec6SMatthias Ringwald         case L2CAP_EVENT_INCOMING_CONNECTION:
12243deb3ec6SMatthias Ringwald             /* L2CAP event data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16) */
1225724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[2], event_addr);
1226f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet,  8);
1227f8fbdce0SMatthias Ringwald             psm        = little_endian_read_16(packet, 10);
1228f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 12);
12293deb3ec6SMatthias Ringwald 
1230235946f1SMatthias Ringwald             if (psm != BLUETOOTH_PROTOCOL_BNEP) break;
12313deb3ec6SMatthias Ringwald 
12323deb3ec6SMatthias Ringwald             channel = bnep_channel_for_addr(event_addr);
12333deb3ec6SMatthias Ringwald 
12343deb3ec6SMatthias Ringwald             if (channel) {
1235235946f1SMatthias Ringwald                 log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PROTOCOL_BNEP => decline - channel already exists", l2cap_cid);
12367ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
12373deb3ec6SMatthias Ringwald                 return 1;
12383deb3ec6SMatthias Ringwald             }
12393deb3ec6SMatthias Ringwald 
12403deb3ec6SMatthias Ringwald             /* Create a new BNEP channel instance (incoming) */
12413deb3ec6SMatthias Ringwald             channel = bnep_channel_create_for_addr(event_addr);
12423deb3ec6SMatthias Ringwald 
12433deb3ec6SMatthias Ringwald             if (!channel) {
1244235946f1SMatthias Ringwald                 log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PROTOCOL_BNEP => decline - no memory left", l2cap_cid);
12457ef6a7bbSMatthias Ringwald                 l2cap_decline_connection(l2cap_cid);
12463deb3ec6SMatthias Ringwald                 return 1;
12473deb3ec6SMatthias Ringwald             }
12483deb3ec6SMatthias Ringwald 
12493deb3ec6SMatthias Ringwald             /* Assign connection handle and l2cap cid */
12503deb3ec6SMatthias Ringwald             channel->con_handle = con_handle;
12513deb3ec6SMatthias Ringwald             channel->l2cap_cid = l2cap_cid;
12523deb3ec6SMatthias Ringwald 
12533deb3ec6SMatthias Ringwald             /* Set channel into accept state */
12543deb3ec6SMatthias Ringwald             channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST;
12553deb3ec6SMatthias Ringwald 
12563deb3ec6SMatthias Ringwald             /* Start connection timeout timer */
12573deb3ec6SMatthias Ringwald             bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
12583deb3ec6SMatthias Ringwald 
1259235946f1SMatthias Ringwald             log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for BLUETOOTH_PROTOCOL_BNEP => accept", l2cap_cid);
1260ce8f182eSMatthias Ringwald             l2cap_accept_connection(l2cap_cid);
12613deb3ec6SMatthias Ringwald             return 1;
12623deb3ec6SMatthias Ringwald 
12633deb3ec6SMatthias Ringwald         /* Outgoing L2CAP connection has been opened -> store l2cap_cid, remote_addr */
12643deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_OPENED:
1265235946f1SMatthias Ringwald             /* Check if the l2cap channel has been opened for BLUETOOTH_PROTOCOL_BNEP */
1266235946f1SMatthias Ringwald             if (little_endian_read_16(packet, 11) != BLUETOOTH_PROTOCOL_BNEP) {
12673deb3ec6SMatthias Ringwald                 break;
12683deb3ec6SMatthias Ringwald             }
12693deb3ec6SMatthias Ringwald 
12703deb3ec6SMatthias Ringwald             status = packet[2];
1271235946f1SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_OPENED for BLUETOOTH_PROTOCOL_BNEP, status %u", status);
12723deb3ec6SMatthias Ringwald 
12733deb3ec6SMatthias Ringwald             /* Get the bnep channel fpr remote address */
1274f8fbdce0SMatthias Ringwald             con_handle = little_endian_read_16(packet, 9);
1275f8fbdce0SMatthias Ringwald             l2cap_cid  = little_endian_read_16(packet, 13);
1276724d70a2SMatthias Ringwald             reverse_bd_addr(&packet[3], event_addr);
12773deb3ec6SMatthias Ringwald             channel = bnep_channel_for_addr(event_addr);
12783deb3ec6SMatthias Ringwald             if (!channel) {
12793deb3ec6SMatthias Ringwald                 log_error("L2CAP_EVENT_CHANNEL_OPENED but no BNEP channel prepared");
12803deb3ec6SMatthias Ringwald                 return 1;
12813deb3ec6SMatthias Ringwald             }
12823deb3ec6SMatthias Ringwald 
12833deb3ec6SMatthias Ringwald             /* On L2CAP open error discard everything */
12843deb3ec6SMatthias Ringwald             if (status) {
12853deb3ec6SMatthias Ringwald                 /* Emit bnep_open_channel_complete with status and free channel */
12863deb3ec6SMatthias Ringwald                 bnep_emit_open_channel_complete(channel, status);
12873deb3ec6SMatthias Ringwald 
12883deb3ec6SMatthias Ringwald                 /* Free BNEP channel mempory */
12893deb3ec6SMatthias Ringwald                 bnep_channel_free(channel);
12903deb3ec6SMatthias Ringwald                 return 1;
12913deb3ec6SMatthias Ringwald             }
12923deb3ec6SMatthias Ringwald 
12933deb3ec6SMatthias Ringwald             switch (channel->state){
12943deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_CLOSED:
12953deb3ec6SMatthias Ringwald                     log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
12963deb3ec6SMatthias Ringwald 
12973deb3ec6SMatthias Ringwald                     bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
12983deb3ec6SMatthias Ringwald 
12993deb3ec6SMatthias Ringwald                     /* Assign connection handle and l2cap cid */
13003deb3ec6SMatthias Ringwald                     channel->l2cap_cid  = l2cap_cid;
13013deb3ec6SMatthias Ringwald                     channel->con_handle = con_handle;
13023deb3ec6SMatthias Ringwald 
13033deb3ec6SMatthias Ringwald                     /* Initiate the connection request */
13043deb3ec6SMatthias Ringwald                     channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
13053deb3ec6SMatthias Ringwald                     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
1306f8fbdce0SMatthias Ringwald                     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
13074e366553SMatthias Ringwald                     l2cap_request_can_send_now_event(channel->l2cap_cid);
13083deb3ec6SMatthias Ringwald                     break;
13093deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
13103deb3ec6SMatthias Ringwald                     /* New information: channel mtu */
1311f8fbdce0SMatthias Ringwald                     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(little_endian_read_16(packet, 17));
13123deb3ec6SMatthias Ringwald                     break;
13133deb3ec6SMatthias Ringwald                 default:
13143deb3ec6SMatthias Ringwald                     log_error("L2CAP_EVENT_CHANNEL_OPENED: Invalid state: %d", channel->state);
13153deb3ec6SMatthias Ringwald                     break;
13163deb3ec6SMatthias Ringwald             }
13173deb3ec6SMatthias Ringwald             return 1;
13183deb3ec6SMatthias Ringwald 
13191b89a84bSMatthias Ringwald         case L2CAP_EVENT_CAN_SEND_NOW:
13204e366553SMatthias Ringwald             bnep_handle_can_send_now(l2cap_event_can_send_now_get_local_cid(packet));
13213deb3ec6SMatthias Ringwald             break;
13223deb3ec6SMatthias Ringwald 
13233deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_CLOSED:
13243deb3ec6SMatthias Ringwald             // data: event (8), len(8), channel (16)
1325f8fbdce0SMatthias Ringwald             l2cap_cid   = little_endian_read_16(packet, 2);
13263deb3ec6SMatthias Ringwald             channel = bnep_channel_for_l2cap_cid(l2cap_cid);
13273deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, channel %p", l2cap_cid, channel);
13283deb3ec6SMatthias Ringwald 
13293deb3ec6SMatthias Ringwald             if (!channel) {
13303deb3ec6SMatthias Ringwald                 break;
13313deb3ec6SMatthias Ringwald             }
13323deb3ec6SMatthias Ringwald 
13333deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", channel->state);
13343deb3ec6SMatthias Ringwald             switch (channel->state) {
13353deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
13363deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE:
13373deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_CONNECTED:
13383deb3ec6SMatthias Ringwald                     bnep_channel_finalize(channel);
13393deb3ec6SMatthias Ringwald                     return 1;
13403deb3ec6SMatthias Ringwald                 default:
13413deb3ec6SMatthias Ringwald                     break;
13423deb3ec6SMatthias Ringwald             }
13433deb3ec6SMatthias Ringwald             break;
13443deb3ec6SMatthias Ringwald         default:
13453deb3ec6SMatthias Ringwald             break;
13463deb3ec6SMatthias Ringwald     }
13473deb3ec6SMatthias Ringwald     return 0;
13483deb3ec6SMatthias Ringwald }
13493deb3ec6SMatthias Ringwald 
13503deb3ec6SMatthias Ringwald static int bnep_l2cap_packet_handler(uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
13513deb3ec6SMatthias Ringwald {
13523deb3ec6SMatthias Ringwald     int             rc = 0;
13533deb3ec6SMatthias Ringwald     uint8_t         bnep_type;
13543deb3ec6SMatthias Ringwald     uint8_t         bnep_header_has_ext;
13553deb3ec6SMatthias Ringwald     uint8_t         extension_type;
13563deb3ec6SMatthias Ringwald     uint16_t        pos = 0;
13573deb3ec6SMatthias Ringwald     bd_addr_t       addr_source;
13583deb3ec6SMatthias Ringwald     bd_addr_t       addr_dest;
13593deb3ec6SMatthias Ringwald     uint16_t        network_protocol_type = 0xffff;
13603deb3ec6SMatthias Ringwald     bnep_channel_t *channel = NULL;
13613deb3ec6SMatthias Ringwald 
13623deb3ec6SMatthias Ringwald     /* Get the bnep channel for this package */
13633deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(l2cap_cid);
13643deb3ec6SMatthias Ringwald     if (!channel) {
13653deb3ec6SMatthias Ringwald         return rc;
13663deb3ec6SMatthias Ringwald     }
13673deb3ec6SMatthias Ringwald 
13683deb3ec6SMatthias Ringwald     /* Sort out short packages */
13693deb3ec6SMatthias Ringwald     if (size < 2) {
13703deb3ec6SMatthias Ringwald         return rc;
13713deb3ec6SMatthias Ringwald     }
13723deb3ec6SMatthias Ringwald 
13733deb3ec6SMatthias Ringwald     bnep_type = BNEP_TYPE(packet[pos]);
13743deb3ec6SMatthias Ringwald     bnep_header_has_ext = BNEP_HEADER_HAS_EXT(packet[pos]);
13753deb3ec6SMatthias Ringwald     pos ++;
13763deb3ec6SMatthias Ringwald 
13773deb3ec6SMatthias Ringwald     switch(bnep_type) {
13783deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_GENERAL_ETHERNET:
1379058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, &packet[pos]);
13803deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1381058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, &packet[pos]);
13823deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1383f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
13843deb3ec6SMatthias Ringwald             pos += 2;
13853deb3ec6SMatthias Ringwald             break;
13863deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET:
1387058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, channel->local_addr);
1388058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, channel->remote_addr);
1389f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
13903deb3ec6SMatthias Ringwald             pos += 2;
13913deb3ec6SMatthias Ringwald             break;
13923deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY:
1393058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, channel->local_addr);
1394058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, &packet[pos]);
13953deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1396f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
13973deb3ec6SMatthias Ringwald             pos += 2;
13983deb3ec6SMatthias Ringwald             break;
13993deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY:
1400058e3d6bSMatthias Ringwald             bd_addr_copy(addr_dest, &packet[pos]);
14013deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1402058e3d6bSMatthias Ringwald             bd_addr_copy(addr_source, channel->remote_addr);
1403f8fbdce0SMatthias Ringwald             network_protocol_type = big_endian_read_16(packet, pos);
14043deb3ec6SMatthias Ringwald             pos += 2;
14053deb3ec6SMatthias Ringwald             break;
14063deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_CONTROL:
14073deb3ec6SMatthias Ringwald             rc = bnep_handle_control_packet(channel, packet + pos, size - pos, 0);
14083deb3ec6SMatthias Ringwald             pos += rc;
14093deb3ec6SMatthias Ringwald             break;
14103deb3ec6SMatthias Ringwald         default:
14113deb3ec6SMatthias Ringwald             break;
14123deb3ec6SMatthias Ringwald     }
14133deb3ec6SMatthias Ringwald 
14143deb3ec6SMatthias Ringwald     if (bnep_header_has_ext) {
14153deb3ec6SMatthias Ringwald         do {
14163deb3ec6SMatthias Ringwald             uint8_t ext_len;
14173deb3ec6SMatthias Ringwald 
14183deb3ec6SMatthias Ringwald             /* Read extension type and check for further extensions */
14193deb3ec6SMatthias Ringwald             extension_type        = BNEP_TYPE(packet[pos]);
14203deb3ec6SMatthias Ringwald             bnep_header_has_ext   = BNEP_HEADER_HAS_EXT(packet[pos]);
14213deb3ec6SMatthias Ringwald             pos ++;
14223deb3ec6SMatthias Ringwald 
14233deb3ec6SMatthias Ringwald             /* Read extension header length */
14243deb3ec6SMatthias Ringwald             ext_len = packet[pos];
14253deb3ec6SMatthias Ringwald             pos ++;
14263deb3ec6SMatthias Ringwald 
14273deb3ec6SMatthias Ringwald             if (size - pos < ext_len) {
14283deb3ec6SMatthias Ringwald                 log_error("BNEP pkt handler: Invalid extension length! Packet ignored");
14293deb3ec6SMatthias Ringwald                 /* Invalid packet size! */
14303deb3ec6SMatthias Ringwald                 return 0;
14313deb3ec6SMatthias Ringwald             }
14323deb3ec6SMatthias Ringwald 
14333deb3ec6SMatthias Ringwald             switch (extension_type) {
14343deb3ec6SMatthias Ringwald                 case BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL:
14353deb3ec6SMatthias Ringwald                     if (ext_len != bnep_handle_control_packet(channel, packet + pos, ext_len, 1)) {
14363deb3ec6SMatthias Ringwald                         log_error("BNEP pkt handler: Ignore invalid control packet in extension header");
14373deb3ec6SMatthias Ringwald                     }
14383deb3ec6SMatthias Ringwald 
14393deb3ec6SMatthias Ringwald                     pos += ext_len;
14403deb3ec6SMatthias Ringwald                     break;
14413deb3ec6SMatthias Ringwald 
14423deb3ec6SMatthias Ringwald                 default:
14433deb3ec6SMatthias Ringwald                     /* Extension header type unknown. Unknown extension SHALL be
14443deb3ec6SMatthias Ringwald 			         * SHALL be forwarded in any way. But who shall handle these
14453deb3ec6SMatthias Ringwald                      * extension packets?
14463deb3ec6SMatthias Ringwald                      * For now: We ignore them and just drop them!
14473deb3ec6SMatthias Ringwald                      */
14483deb3ec6SMatthias Ringwald                     log_error("BNEP pkt handler: Unknown extension type ignored, data dropped!");
14493deb3ec6SMatthias Ringwald                     pos += ext_len;
14503deb3ec6SMatthias Ringwald                     break;
14513deb3ec6SMatthias Ringwald             }
14523deb3ec6SMatthias Ringwald 
14533deb3ec6SMatthias Ringwald         } while (bnep_header_has_ext);
14543deb3ec6SMatthias Ringwald     }
14553deb3ec6SMatthias Ringwald 
14563deb3ec6SMatthias Ringwald     if (bnep_type != BNEP_PKT_TYPE_CONTROL && network_protocol_type != 0xffff) {
14573deb3ec6SMatthias Ringwald         if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
14583deb3ec6SMatthias Ringwald             rc = bnep_handle_ethernet_packet(channel, addr_dest, addr_source, network_protocol_type, packet + pos, size - pos);
14593deb3ec6SMatthias Ringwald         } else {
14603deb3ec6SMatthias Ringwald             rc = 0;
14613deb3ec6SMatthias Ringwald         }
14623deb3ec6SMatthias Ringwald     }
14633deb3ec6SMatthias Ringwald 
14643deb3ec6SMatthias Ringwald     return rc;
14653deb3ec6SMatthias Ringwald 
14663deb3ec6SMatthias Ringwald }
14673deb3ec6SMatthias Ringwald 
14683deb3ec6SMatthias Ringwald void bnep_packet_handler(uint8_t packet_type, uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
14693deb3ec6SMatthias Ringwald {
14703deb3ec6SMatthias Ringwald     switch (packet_type) {
14713deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
1472bef9a6fcSMatthias Ringwald             bnep_hci_event_handler(packet, size);
14733deb3ec6SMatthias Ringwald             break;
14743deb3ec6SMatthias Ringwald         case L2CAP_DATA_PACKET:
1475bef9a6fcSMatthias Ringwald             bnep_l2cap_packet_handler(l2cap_cid, packet, size);
14763deb3ec6SMatthias Ringwald             break;
14773deb3ec6SMatthias Ringwald         default:
14783deb3ec6SMatthias Ringwald             break;
14793deb3ec6SMatthias Ringwald     }
14803deb3ec6SMatthias Ringwald }
14813deb3ec6SMatthias Ringwald 
14823deb3ec6SMatthias Ringwald static void bnep_channel_state_machine(bnep_channel_t* channel, bnep_channel_event_t *event)
14833deb3ec6SMatthias Ringwald {
1484b42623deSMatthias Ringwald     log_debug("bnep_state_machine: state %u, state var: %02x, event %u", channel->state, channel->state_var, event->type);
14853deb3ec6SMatthias Ringwald 
14863deb3ec6SMatthias Ringwald     if (event->type == BNEP_CH_EVT_READY_TO_SEND) {
14873deb3ec6SMatthias Ringwald         /* Send outstanding packets. */
14883deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD) {
14893deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
14903deb3ec6SMatthias Ringwald             bnep_send_command_not_understood(channel, channel->last_control_type);
14913deb3ec6SMatthias Ringwald             return;
14923deb3ec6SMatthias Ringwald         }
14933deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST) {
14943deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
14953deb3ec6SMatthias Ringwald             channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
14963deb3ec6SMatthias Ringwald             bnep_send_connection_request(channel, channel->uuid_source, channel->uuid_dest);
14973deb3ec6SMatthias Ringwald         }
14983deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE) {
14993deb3ec6SMatthias Ringwald             int emit_connected = 0;
15003deb3ec6SMatthias Ringwald             if ((channel->state == BNEP_CHANNEL_STATE_CLOSED) ||
15013deb3ec6SMatthias Ringwald                 (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST)) {
15023deb3ec6SMatthias Ringwald                 /* Set channel state to STATE_CONNECTED */
15033deb3ec6SMatthias Ringwald                 channel->state = BNEP_CHANNEL_STATE_CONNECTED;
15043deb3ec6SMatthias Ringwald                 /* Stop timeout timer! */
15053deb3ec6SMatthias Ringwald                 bnep_channel_stop_timer(channel);
15063deb3ec6SMatthias Ringwald                 emit_connected = 1;
15073deb3ec6SMatthias Ringwald             }
15083deb3ec6SMatthias Ringwald 
15093deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
15103deb3ec6SMatthias Ringwald             bnep_send_connection_response(channel, channel->response_code);
15113deb3ec6SMatthias Ringwald             if (emit_connected){
15123deb3ec6SMatthias Ringwald                 bnep_emit_open_channel_complete(channel, 0);
15133deb3ec6SMatthias Ringwald             }
15143deb3ec6SMatthias Ringwald             return;
15153deb3ec6SMatthias Ringwald         }
15163deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET) {
15173deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
15183deb3ec6SMatthias Ringwald             if ((channel->net_filter_out_count > 0) && (channel->net_filter_out != NULL)) {
15193deb3ec6SMatthias Ringwald                 bnep_send_filter_net_type_set(channel, channel->net_filter_out, channel->net_filter_out_count);
15203deb3ec6SMatthias Ringwald                 channel->net_filter_out_count = 0;
15213deb3ec6SMatthias Ringwald                 channel->net_filter_out = NULL;
15223deb3ec6SMatthias Ringwald             }
15233deb3ec6SMatthias Ringwald             return;
15243deb3ec6SMatthias Ringwald         }
15253deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE) {
15263deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
15273deb3ec6SMatthias Ringwald             bnep_send_filter_net_type_response(channel, channel->response_code);
15283deb3ec6SMatthias Ringwald             return;
15293deb3ec6SMatthias Ringwald         }
15303deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET) {
15313deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
15323deb3ec6SMatthias Ringwald             if ((channel->multicast_filter_out_count > 0) && (channel->multicast_filter_out != NULL)) {
15333deb3ec6SMatthias Ringwald                 bnep_send_filter_multi_addr_set(channel, channel->multicast_filter_out, channel->multicast_filter_out_count);
15343deb3ec6SMatthias Ringwald                 channel->multicast_filter_out_count = 0;
15353deb3ec6SMatthias Ringwald                 channel->multicast_filter_out = NULL;
15363deb3ec6SMatthias Ringwald             }
15373deb3ec6SMatthias Ringwald             return;
15383deb3ec6SMatthias Ringwald         }
15393deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE) {
15403deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
15413deb3ec6SMatthias Ringwald             bnep_send_filter_multi_addr_response(channel, channel->response_code);
15423deb3ec6SMatthias Ringwald             return;
15433deb3ec6SMatthias Ringwald         }
15443deb3ec6SMatthias Ringwald 
15453deb3ec6SMatthias Ringwald         /* If the event was not yet handled, notify the application layer */
15461ed1a3bdSMatthias Ringwald         if (channel->waiting_for_can_send_now){
15471ed1a3bdSMatthias Ringwald             channel->waiting_for_can_send_now = 0;
15483deb3ec6SMatthias Ringwald             bnep_emit_ready_to_send(channel);
15493deb3ec6SMatthias Ringwald         }
15503deb3ec6SMatthias Ringwald     }
15511ed1a3bdSMatthias Ringwald }
15523deb3ec6SMatthias Ringwald 
15534e366553SMatthias Ringwald static void bnep_handle_can_send_now(uint16_t l2cap_cid){
1554665d90f2SMatthias Ringwald     btstack_linked_item_t *it;
1555665d90f2SMatthias Ringwald     btstack_linked_item_t *next;
15563deb3ec6SMatthias Ringwald 
1557665d90f2SMatthias Ringwald     for (it = (btstack_linked_item_t *) bnep_channels; it ; it = next){
15583deb3ec6SMatthias Ringwald         next = it->next;    // be prepared for removal of channel in state machine
15593deb3ec6SMatthias Ringwald         bnep_channel_t * channel = ((bnep_channel_t *) it);
15604e366553SMatthias Ringwald         if (channel->l2cap_cid != l2cap_cid) continue;
15614e366553SMatthias Ringwald         //
15623deb3ec6SMatthias Ringwald         bnep_channel_event_t channel_event = { BNEP_CH_EVT_READY_TO_SEND };
15633deb3ec6SMatthias Ringwald         bnep_channel_state_machine(channel, &channel_event);
15644e366553SMatthias Ringwald 
15654e366553SMatthias Ringwald         if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
15664e366553SMatthias Ringwald             l2cap_request_can_send_now_event(channel->l2cap_cid);
15674e366553SMatthias Ringwald             return;
15683deb3ec6SMatthias Ringwald         }
15693deb3ec6SMatthias Ringwald     }
15704e366553SMatthias Ringwald }
15714e366553SMatthias Ringwald 
15723deb3ec6SMatthias Ringwald 
15733deb3ec6SMatthias Ringwald /* BNEP BTStack API */
15743deb3ec6SMatthias Ringwald void bnep_init(void)
15753deb3ec6SMatthias Ringwald {
157645a58b30SMatthias Ringwald     bnep_security_level = LEVEL_2;
15773deb3ec6SMatthias Ringwald }
15783deb3ec6SMatthias Ringwald 
15793deb3ec6SMatthias Ringwald void bnep_set_required_security_level(gap_security_level_t security_level)
15803deb3ec6SMatthias Ringwald {
15813deb3ec6SMatthias Ringwald     bnep_security_level = security_level;
15823deb3ec6SMatthias Ringwald }
15833deb3ec6SMatthias Ringwald 
15840c249750SMatthias 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)
15853deb3ec6SMatthias Ringwald {
15863deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
15873deb3ec6SMatthias Ringwald     log_info("BNEP_CONNECT addr %s", bd_addr_to_str(addr));
15883deb3ec6SMatthias Ringwald 
15893deb3ec6SMatthias Ringwald     channel = bnep_channel_create_for_addr(addr);
15903deb3ec6SMatthias Ringwald     if (channel == NULL) {
15913deb3ec6SMatthias Ringwald         return -1;
15923deb3ec6SMatthias Ringwald     }
15933deb3ec6SMatthias Ringwald 
15943deb3ec6SMatthias Ringwald     channel->uuid_source    = uuid_src;
15953deb3ec6SMatthias Ringwald     channel->uuid_dest      = uuid_dest;
15960c249750SMatthias Ringwald     channel->packet_handler = packet_handler;
15973deb3ec6SMatthias Ringwald 
159890a28bdeSMatthias Ringwald     uint8_t status = l2cap_create_channel(bnep_packet_handler, addr, l2cap_psm, l2cap_max_mtu(), NULL);
159990a28bdeSMatthias Ringwald     if (status){
160090a28bdeSMatthias Ringwald         return -1;
160190a28bdeSMatthias Ringwald     }
16023deb3ec6SMatthias Ringwald     return 0;
16033deb3ec6SMatthias Ringwald }
16043deb3ec6SMatthias Ringwald 
16053deb3ec6SMatthias Ringwald void bnep_disconnect(bd_addr_t addr)
16063deb3ec6SMatthias Ringwald {
16073deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
16083deb3ec6SMatthias Ringwald     log_info("BNEP_DISCONNECT");
16093deb3ec6SMatthias Ringwald 
16103deb3ec6SMatthias Ringwald     channel = bnep_channel_for_addr(addr);
16113deb3ec6SMatthias Ringwald 
16123deb3ec6SMatthias Ringwald     bnep_channel_finalize(channel);
16133deb3ec6SMatthias Ringwald }
16143deb3ec6SMatthias Ringwald 
16153deb3ec6SMatthias Ringwald 
16160c249750SMatthias Ringwald uint8_t bnep_register_service(btstack_packet_handler_t packet_handler, uint16_t service_uuid, uint16_t max_frame_size)
16173deb3ec6SMatthias Ringwald {
16183deb3ec6SMatthias Ringwald     log_info("BNEP_REGISTER_SERVICE mtu %d", max_frame_size);
16193deb3ec6SMatthias Ringwald 
16203deb3ec6SMatthias Ringwald     /* Check if we already registered a service */
16213deb3ec6SMatthias Ringwald     bnep_service_t * service = bnep_service_for_uuid(service_uuid);
16223deb3ec6SMatthias Ringwald     if (service) {
16230cc6429eSMatthias Ringwald         return BNEP_SERVICE_ALREADY_REGISTERED;
16243deb3ec6SMatthias Ringwald     }
16253deb3ec6SMatthias Ringwald 
16263deb3ec6SMatthias Ringwald     /* Only alow one the three service types: PANU, NAP, GN */
1627235946f1SMatthias Ringwald     if ((service_uuid != BLUETOOTH_SERVICE_CLASS_PANU) &&
1628235946f1SMatthias Ringwald         (service_uuid != BLUETOOTH_SERVICE_CLASS_NAP) &&
1629235946f1SMatthias Ringwald         (service_uuid != BLUETOOTH_SERVICE_CLASS_GN)) {
16303deb3ec6SMatthias Ringwald         log_info("BNEP_REGISTER_SERVICE: Invalid service UUID: %04x", service_uuid);
16310cc6429eSMatthias Ringwald         return BNEP_SERVICE_ALREADY_REGISTERED; // TODO: define own error
16323deb3ec6SMatthias Ringwald     }
16333deb3ec6SMatthias Ringwald 
16343deb3ec6SMatthias Ringwald     /* Allocate service memory */
16353deb3ec6SMatthias Ringwald     service = (bnep_service_t*) btstack_memory_bnep_service_get();
16363deb3ec6SMatthias Ringwald     if (!service) {
16370cc6429eSMatthias Ringwald         return BTSTACK_MEMORY_ALLOC_FAILED;
16383deb3ec6SMatthias Ringwald     }
16393deb3ec6SMatthias Ringwald 
16403deb3ec6SMatthias Ringwald     /* register with l2cap if not registered before, max MTU */
1641235946f1SMatthias Ringwald     l2cap_register_service(bnep_packet_handler, BLUETOOTH_PROTOCOL_BNEP, 0xffff, bnep_security_level);
16423deb3ec6SMatthias Ringwald 
16433deb3ec6SMatthias Ringwald     /* Setup the service struct */
16443deb3ec6SMatthias Ringwald     service->max_frame_size = max_frame_size;
16453deb3ec6SMatthias Ringwald     service->service_uuid    = service_uuid;
16460c249750SMatthias Ringwald     service->packet_handler = packet_handler;
16470c249750SMatthias Ringwald 
16483deb3ec6SMatthias Ringwald 
16493deb3ec6SMatthias Ringwald     /* Add to services list */
1650665d90f2SMatthias Ringwald     btstack_linked_list_add(&bnep_services, (btstack_linked_item_t *) service);
16513deb3ec6SMatthias Ringwald 
16520cc6429eSMatthias Ringwald     return 0;
16533deb3ec6SMatthias Ringwald }
16543deb3ec6SMatthias Ringwald 
16553deb3ec6SMatthias Ringwald void bnep_unregister_service(uint16_t service_uuid)
16563deb3ec6SMatthias Ringwald {
16573deb3ec6SMatthias Ringwald     log_info("BNEP_UNREGISTER_SERVICE #%04x", service_uuid);
16583deb3ec6SMatthias Ringwald 
16593deb3ec6SMatthias Ringwald     bnep_service_t *service = bnep_service_for_uuid(service_uuid);
16603deb3ec6SMatthias Ringwald     if (!service) {
16613deb3ec6SMatthias Ringwald         return;
16623deb3ec6SMatthias Ringwald     }
16633deb3ec6SMatthias Ringwald 
1664665d90f2SMatthias Ringwald     btstack_linked_list_remove(&bnep_services, (btstack_linked_item_t *) service);
16653deb3ec6SMatthias Ringwald     btstack_memory_bnep_service_free(service);
16663deb3ec6SMatthias Ringwald     service = NULL;
16673deb3ec6SMatthias Ringwald 
1668235946f1SMatthias Ringwald     l2cap_unregister_service(BLUETOOTH_PROTOCOL_BNEP);
16693deb3ec6SMatthias Ringwald }
16703deb3ec6SMatthias Ringwald 
1671