xref: /btstack/src/classic/bnep.c (revision 3deb3ec68039c68a16974dffc53343233662f909)
1*3deb3ec6SMatthias Ringwald /*
2*3deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*3deb3ec6SMatthias Ringwald  *
4*3deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*3deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*3deb3ec6SMatthias Ringwald  * are met:
7*3deb3ec6SMatthias Ringwald  *
8*3deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*3deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*3deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*3deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*3deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*3deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*3deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*3deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
16*3deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*3deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*3deb3ec6SMatthias Ringwald  *    monetary gain.
19*3deb3ec6SMatthias Ringwald  *
20*3deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*3deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*3deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*3deb3ec6SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*3deb3ec6SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*3deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*3deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*3deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*3deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*3deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*3deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*3deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
32*3deb3ec6SMatthias Ringwald  *
33*3deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
34*3deb3ec6SMatthias Ringwald  * [email protected]
35*3deb3ec6SMatthias Ringwald  *
36*3deb3ec6SMatthias Ringwald  */
37*3deb3ec6SMatthias Ringwald 
38*3deb3ec6SMatthias Ringwald /*
39*3deb3ec6SMatthias Ringwald  * bnep.c
40*3deb3ec6SMatthias Ringwald  * Author: Ole Reinhardt <[email protected]>
41*3deb3ec6SMatthias Ringwald  *
42*3deb3ec6SMatthias Ringwald  */
43*3deb3ec6SMatthias Ringwald 
44*3deb3ec6SMatthias Ringwald #include <stdio.h>
45*3deb3ec6SMatthias Ringwald #include <stdlib.h>
46*3deb3ec6SMatthias Ringwald #include <string.h> // memcpy
47*3deb3ec6SMatthias Ringwald #include <stdint.h>
48*3deb3ec6SMatthias Ringwald 
49*3deb3ec6SMatthias Ringwald #include "btstack.h"
50*3deb3ec6SMatthias Ringwald #include "hci_cmds.h"
51*3deb3ec6SMatthias Ringwald #include "utils.h"
52*3deb3ec6SMatthias Ringwald #include "sdp_util.h"
53*3deb3ec6SMatthias Ringwald 
54*3deb3ec6SMatthias Ringwald #include "btstack_memory.h"
55*3deb3ec6SMatthias Ringwald #include "hci.h"
56*3deb3ec6SMatthias Ringwald #include "hci_dump.h"
57*3deb3ec6SMatthias Ringwald #include "debug.h"
58*3deb3ec6SMatthias Ringwald #include "bnep.h"
59*3deb3ec6SMatthias Ringwald 
60*3deb3ec6SMatthias Ringwald #include "l2cap.h"
61*3deb3ec6SMatthias Ringwald 
62*3deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_TIMEOUT_MS 10000
63*3deb3ec6SMatthias Ringwald #define BNEP_CONNECTION_MAX_RETRIES 1
64*3deb3ec6SMatthias Ringwald 
65*3deb3ec6SMatthias Ringwald static linked_list_t bnep_services = NULL;
66*3deb3ec6SMatthias Ringwald static linked_list_t bnep_channels = NULL;
67*3deb3ec6SMatthias Ringwald 
68*3deb3ec6SMatthias Ringwald static gap_security_level_t bnep_security_level;
69*3deb3ec6SMatthias Ringwald 
70*3deb3ec6SMatthias Ringwald static void (*app_packet_handler)(void * connection, uint8_t packet_type,
71*3deb3ec6SMatthias Ringwald                                   uint16_t channel, uint8_t *packet, uint16_t size);
72*3deb3ec6SMatthias Ringwald 
73*3deb3ec6SMatthias Ringwald 
74*3deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid);
75*3deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel);
76*3deb3ec6SMatthias Ringwald static void bnep_run(void);
77*3deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout);
78*3deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event);
79*3deb3ec6SMatthias Ringwald 
80*3deb3ec6SMatthias Ringwald /* Emit service registered event */
81*3deb3ec6SMatthias Ringwald static void bnep_emit_service_registered(void *connection, uint8_t status, uint16_t service_uuid)
82*3deb3ec6SMatthias Ringwald {
83*3deb3ec6SMatthias Ringwald     log_info("BNEP_EVENT_SERVICE_REGISTERED status 0x%02x, uuid: 0x%04x", status, service_uuid);
84*3deb3ec6SMatthias Ringwald     uint8_t event[5];
85*3deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_SERVICE_REGISTERED;
86*3deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
87*3deb3ec6SMatthias Ringwald     event[2] = status;
88*3deb3ec6SMatthias Ringwald     bt_store_16(event, 3, service_uuid);
89*3deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
90*3deb3ec6SMatthias Ringwald 	(*app_packet_handler)(connection, HCI_EVENT_PACKET, 0, (uint8_t *) event, sizeof(event));
91*3deb3ec6SMatthias Ringwald }
92*3deb3ec6SMatthias Ringwald 
93*3deb3ec6SMatthias Ringwald static void bnep_emit_open_channel_complete(bnep_channel_t *channel, uint8_t status)
94*3deb3ec6SMatthias Ringwald {
95*3deb3ec6SMatthias Ringwald     log_info("BNEP_EVENT_OPEN_CHANNEL_COMPLETE status 0x%02x bd_addr: %s", status, bd_addr_to_str(channel->remote_addr));
96*3deb3ec6SMatthias Ringwald     uint8_t event[3 + sizeof(bd_addr_t) + 3 * sizeof(uint16_t)];
97*3deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_OPEN_CHANNEL_COMPLETE;
98*3deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
99*3deb3ec6SMatthias Ringwald     event[2] = status;
100*3deb3ec6SMatthias Ringwald     bt_store_16(event, 3, channel->uuid_source);
101*3deb3ec6SMatthias Ringwald     bt_store_16(event, 5, channel->uuid_dest);
102*3deb3ec6SMatthias Ringwald     bt_store_16(event, 7, channel->max_frame_size);
103*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(&event[9], channel->remote_addr);
104*3deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
105*3deb3ec6SMatthias Ringwald 	(*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, channel->l2cap_cid, (uint8_t *) event, sizeof(event));
106*3deb3ec6SMatthias Ringwald }
107*3deb3ec6SMatthias Ringwald 
108*3deb3ec6SMatthias Ringwald static void bnep_emit_channel_timeout(bnep_channel_t *channel)
109*3deb3ec6SMatthias Ringwald {
110*3deb3ec6SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_TIMEOUT bd_addr: %s", bd_addr_to_str(channel->remote_addr));
111*3deb3ec6SMatthias Ringwald     uint8_t event[2 + sizeof(bd_addr_t) + 2 * sizeof(uint16_t) + sizeof(uint8_t)];
112*3deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_TIMEOUT;
113*3deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
114*3deb3ec6SMatthias Ringwald     bt_store_16(event, 2, channel->uuid_source);
115*3deb3ec6SMatthias Ringwald     bt_store_16(event, 4, channel->uuid_dest);
116*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(&event[6], channel->remote_addr);
117*3deb3ec6SMatthias Ringwald     event[12] = channel->state;
118*3deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
119*3deb3ec6SMatthias Ringwald 	(*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, channel->l2cap_cid, (uint8_t *) event, sizeof(event));
120*3deb3ec6SMatthias Ringwald }
121*3deb3ec6SMatthias Ringwald 
122*3deb3ec6SMatthias Ringwald static void bnep_emit_channel_closed(bnep_channel_t *channel)
123*3deb3ec6SMatthias Ringwald {
124*3deb3ec6SMatthias Ringwald     log_info("BNEP_EVENT_CHANNEL_CLOSED bd_addr: %s", bd_addr_to_str(channel->remote_addr));
125*3deb3ec6SMatthias Ringwald     uint8_t event[2 + sizeof(bd_addr_t) + 2 * sizeof(uint16_t)];
126*3deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_CHANNEL_CLOSED;
127*3deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
128*3deb3ec6SMatthias Ringwald     bt_store_16(event, 2, channel->uuid_source);
129*3deb3ec6SMatthias Ringwald     bt_store_16(event, 4, channel->uuid_dest);
130*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(&event[6], channel->remote_addr);
131*3deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
132*3deb3ec6SMatthias Ringwald 	(*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, channel->l2cap_cid, (uint8_t *) event, sizeof(event));
133*3deb3ec6SMatthias Ringwald }
134*3deb3ec6SMatthias Ringwald 
135*3deb3ec6SMatthias Ringwald static void bnep_emit_ready_to_send(bnep_channel_t *channel)
136*3deb3ec6SMatthias Ringwald {
137*3deb3ec6SMatthias Ringwald     uint8_t event[2];
138*3deb3ec6SMatthias Ringwald     event[0] = BNEP_EVENT_READY_TO_SEND;
139*3deb3ec6SMatthias Ringwald     event[1] = sizeof(event) - 2;
140*3deb3ec6SMatthias Ringwald     hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
141*3deb3ec6SMatthias Ringwald 	(*app_packet_handler)(channel->connection, HCI_EVENT_PACKET, channel->l2cap_cid, (uint8_t *) event, sizeof(event));
142*3deb3ec6SMatthias Ringwald }
143*3deb3ec6SMatthias Ringwald 
144*3deb3ec6SMatthias Ringwald /* Send BNEP connection request */
145*3deb3ec6SMatthias Ringwald static int bnep_send_command_not_understood(bnep_channel_t *channel, uint8_t control_type)
146*3deb3ec6SMatthias Ringwald {
147*3deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
148*3deb3ec6SMatthias Ringwald     uint16_t pos = 0;
149*3deb3ec6SMatthias Ringwald     int      err = 0;
150*3deb3ec6SMatthias Ringwald 
151*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
152*3deb3ec6SMatthias Ringwald         return -1; // TODO
153*3deb3ec6SMatthias Ringwald     }
154*3deb3ec6SMatthias Ringwald 
155*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
156*3deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
157*3deb3ec6SMatthias Ringwald 
158*3deb3ec6SMatthias Ringwald     /* Setup control packet type */
159*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
160*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD;
161*3deb3ec6SMatthias Ringwald 
162*3deb3ec6SMatthias Ringwald     /* Add not understood control type */
163*3deb3ec6SMatthias Ringwald     bnep_out_buffer[pos++] = control_type;
164*3deb3ec6SMatthias Ringwald 
165*3deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
166*3deb3ec6SMatthias Ringwald 
167*3deb3ec6SMatthias Ringwald     if (err) {
168*3deb3ec6SMatthias Ringwald         // TODO: Log error
169*3deb3ec6SMatthias Ringwald     }
170*3deb3ec6SMatthias Ringwald     return err;
171*3deb3ec6SMatthias Ringwald }
172*3deb3ec6SMatthias Ringwald 
173*3deb3ec6SMatthias Ringwald 
174*3deb3ec6SMatthias Ringwald /* Send BNEP connection request */
175*3deb3ec6SMatthias Ringwald static int bnep_send_connection_request(bnep_channel_t *channel, uint16_t uuid_source, uint16_t uuid_dest)
176*3deb3ec6SMatthias Ringwald {
177*3deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
178*3deb3ec6SMatthias Ringwald     uint16_t pos = 0;
179*3deb3ec6SMatthias Ringwald     int      err = 0;
180*3deb3ec6SMatthias Ringwald 
181*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
182*3deb3ec6SMatthias Ringwald         return -1; // TODO
183*3deb3ec6SMatthias Ringwald     }
184*3deb3ec6SMatthias Ringwald 
185*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
186*3deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
187*3deb3ec6SMatthias Ringwald 
188*3deb3ec6SMatthias Ringwald     /* Setup control packet type */
189*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
190*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST;
191*3deb3ec6SMatthias Ringwald 
192*3deb3ec6SMatthias Ringwald     /* Add UUID Size */
193*3deb3ec6SMatthias Ringwald     bnep_out_buffer[pos++] = 2;
194*3deb3ec6SMatthias Ringwald 
195*3deb3ec6SMatthias Ringwald     /* Add dest and source UUID */
196*3deb3ec6SMatthias Ringwald     net_store_16(bnep_out_buffer, pos, uuid_dest);
197*3deb3ec6SMatthias Ringwald     pos += 2;
198*3deb3ec6SMatthias Ringwald 
199*3deb3ec6SMatthias Ringwald     net_store_16(bnep_out_buffer, pos, uuid_source);
200*3deb3ec6SMatthias Ringwald     pos += 2;
201*3deb3ec6SMatthias Ringwald 
202*3deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
203*3deb3ec6SMatthias Ringwald 
204*3deb3ec6SMatthias Ringwald     if (err) {
205*3deb3ec6SMatthias Ringwald         // TODO: Log error
206*3deb3ec6SMatthias Ringwald     }
207*3deb3ec6SMatthias Ringwald     return err;
208*3deb3ec6SMatthias Ringwald }
209*3deb3ec6SMatthias Ringwald 
210*3deb3ec6SMatthias Ringwald /* Send BNEP connection response */
211*3deb3ec6SMatthias Ringwald static int bnep_send_connection_response(bnep_channel_t *channel, uint16_t response_code)
212*3deb3ec6SMatthias Ringwald {
213*3deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
214*3deb3ec6SMatthias Ringwald     uint16_t pos = 0;
215*3deb3ec6SMatthias Ringwald     int      err = 0;
216*3deb3ec6SMatthias Ringwald 
217*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
218*3deb3ec6SMatthias Ringwald         return -1; // TODO
219*3deb3ec6SMatthias Ringwald     }
220*3deb3ec6SMatthias Ringwald 
221*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
222*3deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
223*3deb3ec6SMatthias Ringwald 
224*3deb3ec6SMatthias Ringwald     /* Setup control packet type */
225*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
226*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE;
227*3deb3ec6SMatthias Ringwald 
228*3deb3ec6SMatthias Ringwald     /* Add response code */
229*3deb3ec6SMatthias Ringwald     net_store_16(bnep_out_buffer, pos, response_code);
230*3deb3ec6SMatthias Ringwald     pos += 2;
231*3deb3ec6SMatthias Ringwald 
232*3deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
233*3deb3ec6SMatthias Ringwald 
234*3deb3ec6SMatthias Ringwald     if (err) {
235*3deb3ec6SMatthias Ringwald         // TODO: Log error
236*3deb3ec6SMatthias Ringwald     }
237*3deb3ec6SMatthias Ringwald     return err;
238*3deb3ec6SMatthias Ringwald }
239*3deb3ec6SMatthias Ringwald 
240*3deb3ec6SMatthias Ringwald /* Send BNEP filter net type set message */
241*3deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_set(bnep_channel_t *channel, bnep_net_filter_t *filter, uint16_t len)
242*3deb3ec6SMatthias Ringwald {
243*3deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
244*3deb3ec6SMatthias Ringwald     uint16_t pos = 0;
245*3deb3ec6SMatthias Ringwald     int      err = 0;
246*3deb3ec6SMatthias Ringwald     int      i;
247*3deb3ec6SMatthias Ringwald 
248*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
249*3deb3ec6SMatthias Ringwald         return -1;
250*3deb3ec6SMatthias Ringwald     }
251*3deb3ec6SMatthias Ringwald 
252*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
253*3deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
254*3deb3ec6SMatthias Ringwald 
255*3deb3ec6SMatthias Ringwald     /* Setup control packet type */
256*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
257*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET;
258*3deb3ec6SMatthias Ringwald 
259*3deb3ec6SMatthias Ringwald     net_store_16(bnep_out_buffer, pos, len * 2 * 2);
260*3deb3ec6SMatthias Ringwald     pos += 2;
261*3deb3ec6SMatthias Ringwald 
262*3deb3ec6SMatthias Ringwald     for (i = 0; i < len; i ++) {
263*3deb3ec6SMatthias Ringwald         net_store_16(bnep_out_buffer, pos, filter[i].range_start);
264*3deb3ec6SMatthias Ringwald         pos += 2;
265*3deb3ec6SMatthias Ringwald         net_store_16(bnep_out_buffer, pos, filter[i].range_end);
266*3deb3ec6SMatthias Ringwald         pos += 2;
267*3deb3ec6SMatthias Ringwald     }
268*3deb3ec6SMatthias Ringwald 
269*3deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
270*3deb3ec6SMatthias Ringwald 
271*3deb3ec6SMatthias Ringwald     if (err) {
272*3deb3ec6SMatthias Ringwald         // TODO: Log error
273*3deb3ec6SMatthias Ringwald     }
274*3deb3ec6SMatthias Ringwald     return err;
275*3deb3ec6SMatthias Ringwald }
276*3deb3ec6SMatthias Ringwald 
277*3deb3ec6SMatthias Ringwald /* Send BNEP filter net type response message */
278*3deb3ec6SMatthias Ringwald static int bnep_send_filter_net_type_response(bnep_channel_t *channel, uint16_t response_code)
279*3deb3ec6SMatthias Ringwald {
280*3deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
281*3deb3ec6SMatthias Ringwald     uint16_t pos = 0;
282*3deb3ec6SMatthias Ringwald     int      err = 0;
283*3deb3ec6SMatthias Ringwald 
284*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
285*3deb3ec6SMatthias Ringwald         return -1;
286*3deb3ec6SMatthias Ringwald     }
287*3deb3ec6SMatthias Ringwald 
288*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
289*3deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
290*3deb3ec6SMatthias Ringwald 
291*3deb3ec6SMatthias Ringwald     /* Setup control packet type */
292*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
293*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE;
294*3deb3ec6SMatthias Ringwald 
295*3deb3ec6SMatthias Ringwald     /* Add response code */
296*3deb3ec6SMatthias Ringwald     net_store_16(bnep_out_buffer, pos, response_code);
297*3deb3ec6SMatthias Ringwald     pos += 2;
298*3deb3ec6SMatthias Ringwald 
299*3deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
300*3deb3ec6SMatthias Ringwald 
301*3deb3ec6SMatthias Ringwald     if (err) {
302*3deb3ec6SMatthias Ringwald         // TODO: Log error
303*3deb3ec6SMatthias Ringwald     }
304*3deb3ec6SMatthias Ringwald     return err;
305*3deb3ec6SMatthias Ringwald }
306*3deb3ec6SMatthias Ringwald 
307*3deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address set message */
308*3deb3ec6SMatthias Ringwald 
309*3deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_set(bnep_channel_t *channel, bnep_multi_filter_t *filter, uint16_t len)
310*3deb3ec6SMatthias Ringwald {
311*3deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
312*3deb3ec6SMatthias Ringwald     uint16_t pos = 0;
313*3deb3ec6SMatthias Ringwald     int      err = 0;
314*3deb3ec6SMatthias Ringwald     int      i;
315*3deb3ec6SMatthias Ringwald 
316*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
317*3deb3ec6SMatthias Ringwald         return -1;
318*3deb3ec6SMatthias Ringwald     }
319*3deb3ec6SMatthias Ringwald 
320*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
321*3deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
322*3deb3ec6SMatthias Ringwald 
323*3deb3ec6SMatthias Ringwald     /* Setup control packet type */
324*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
325*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET;
326*3deb3ec6SMatthias Ringwald 
327*3deb3ec6SMatthias Ringwald     net_store_16(bnep_out_buffer, pos, len * 2 * ETHER_ADDR_LEN);
328*3deb3ec6SMatthias Ringwald     pos += 2;
329*3deb3ec6SMatthias Ringwald 
330*3deb3ec6SMatthias Ringwald     for (i = 0; i < len; i ++) {
331*3deb3ec6SMatthias Ringwald         BD_ADDR_COPY(bnep_out_buffer + pos, filter[i].addr_start);
332*3deb3ec6SMatthias Ringwald         pos += ETHER_ADDR_LEN;
333*3deb3ec6SMatthias Ringwald         BD_ADDR_COPY(bnep_out_buffer + pos, filter[i].addr_end);
334*3deb3ec6SMatthias Ringwald         pos += ETHER_ADDR_LEN;
335*3deb3ec6SMatthias Ringwald     }
336*3deb3ec6SMatthias Ringwald 
337*3deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
338*3deb3ec6SMatthias Ringwald 
339*3deb3ec6SMatthias Ringwald     if (err) {
340*3deb3ec6SMatthias Ringwald         // TODO: Log error
341*3deb3ec6SMatthias Ringwald     }
342*3deb3ec6SMatthias Ringwald     return err;
343*3deb3ec6SMatthias Ringwald }
344*3deb3ec6SMatthias Ringwald 
345*3deb3ec6SMatthias Ringwald /* Send BNEP filter multicast address response message */
346*3deb3ec6SMatthias Ringwald static int bnep_send_filter_multi_addr_response(bnep_channel_t *channel, uint16_t response_code)
347*3deb3ec6SMatthias Ringwald {
348*3deb3ec6SMatthias Ringwald     uint8_t *bnep_out_buffer = NULL;
349*3deb3ec6SMatthias Ringwald     uint16_t pos = 0;
350*3deb3ec6SMatthias Ringwald     int      err = 0;
351*3deb3ec6SMatthias Ringwald 
352*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CLOSED) {
353*3deb3ec6SMatthias Ringwald         return -1;
354*3deb3ec6SMatthias Ringwald     }
355*3deb3ec6SMatthias Ringwald 
356*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
357*3deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
358*3deb3ec6SMatthias Ringwald 
359*3deb3ec6SMatthias Ringwald     /* Setup control packet type */
360*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_PKT_TYPE_CONTROL;
361*3deb3ec6SMatthias Ringwald 	bnep_out_buffer[pos++] = BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE;
362*3deb3ec6SMatthias Ringwald 
363*3deb3ec6SMatthias Ringwald     /* Add response code */
364*3deb3ec6SMatthias Ringwald     net_store_16(bnep_out_buffer, pos, response_code);
365*3deb3ec6SMatthias Ringwald     pos += 2;
366*3deb3ec6SMatthias Ringwald 
367*3deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos);
368*3deb3ec6SMatthias Ringwald 
369*3deb3ec6SMatthias Ringwald     if (err) {
370*3deb3ec6SMatthias Ringwald         // TODO: Log error
371*3deb3ec6SMatthias Ringwald     }
372*3deb3ec6SMatthias Ringwald     return err;
373*3deb3ec6SMatthias Ringwald }
374*3deb3ec6SMatthias Ringwald 
375*3deb3ec6SMatthias Ringwald int bnep_can_send_packet_now(uint16_t bnep_cid)
376*3deb3ec6SMatthias Ringwald {
377*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel = bnep_channel_for_l2cap_cid(bnep_cid);
378*3deb3ec6SMatthias Ringwald 
379*3deb3ec6SMatthias Ringwald     if (!channel){
380*3deb3ec6SMatthias Ringwald         log_error("bnep_can_send_packet_now cid 0x%02x doesn't exist!", bnep_cid);
381*3deb3ec6SMatthias Ringwald         return 0;
382*3deb3ec6SMatthias Ringwald     }
383*3deb3ec6SMatthias Ringwald 
384*3deb3ec6SMatthias Ringwald     return l2cap_can_send_packet_now(channel->l2cap_cid);
385*3deb3ec6SMatthias Ringwald }
386*3deb3ec6SMatthias Ringwald 
387*3deb3ec6SMatthias Ringwald 
388*3deb3ec6SMatthias Ringwald static int bnep_filter_protocol(bnep_channel_t *channel, uint16_t network_protocol_type)
389*3deb3ec6SMatthias Ringwald {
390*3deb3ec6SMatthias Ringwald 	int i;
391*3deb3ec6SMatthias Ringwald 
392*3deb3ec6SMatthias Ringwald     if (channel->net_filter_count == 0) {
393*3deb3ec6SMatthias Ringwald         /* No filter set */
394*3deb3ec6SMatthias Ringwald         return 1;
395*3deb3ec6SMatthias Ringwald     }
396*3deb3ec6SMatthias Ringwald 
397*3deb3ec6SMatthias Ringwald     for (i = 0; i < channel->net_filter_count; i ++) {
398*3deb3ec6SMatthias Ringwald         if ((network_protocol_type >= channel->net_filter[i].range_start) &&
399*3deb3ec6SMatthias Ringwald             (network_protocol_type <= channel->net_filter[i].range_end)) {
400*3deb3ec6SMatthias Ringwald             return 1;
401*3deb3ec6SMatthias Ringwald         }
402*3deb3ec6SMatthias Ringwald     }
403*3deb3ec6SMatthias Ringwald 
404*3deb3ec6SMatthias Ringwald     return 0;
405*3deb3ec6SMatthias Ringwald }
406*3deb3ec6SMatthias Ringwald 
407*3deb3ec6SMatthias Ringwald static int bnep_filter_multicast(bnep_channel_t *channel, bd_addr_t addr_dest)
408*3deb3ec6SMatthias Ringwald {
409*3deb3ec6SMatthias Ringwald 	int i;
410*3deb3ec6SMatthias Ringwald 
411*3deb3ec6SMatthias Ringwald     /* Check if the multicast flag is set int the destination address */
412*3deb3ec6SMatthias Ringwald 	if ((addr_dest[0] & 0x01) == 0x00) {
413*3deb3ec6SMatthias Ringwald         /* Not a multicast frame, do not apply filtering and send it in any case */
414*3deb3ec6SMatthias Ringwald 		return 1;
415*3deb3ec6SMatthias Ringwald     }
416*3deb3ec6SMatthias Ringwald 
417*3deb3ec6SMatthias Ringwald     if (channel->multicast_filter_count == 0) {
418*3deb3ec6SMatthias Ringwald         /* No filter set */
419*3deb3ec6SMatthias Ringwald         return 1;
420*3deb3ec6SMatthias Ringwald     }
421*3deb3ec6SMatthias Ringwald 
422*3deb3ec6SMatthias Ringwald 	for (i = 0; i < channel->multicast_filter_count; i ++) {
423*3deb3ec6SMatthias Ringwald 		if ((memcmp(addr_dest, channel->multicast_filter[i].addr_start, sizeof(bd_addr_t)) >= 0) &&
424*3deb3ec6SMatthias Ringwald 		    (memcmp(addr_dest, channel->multicast_filter[i].addr_end, sizeof(bd_addr_t)) <= 0)) {
425*3deb3ec6SMatthias Ringwald 			return 1;
426*3deb3ec6SMatthias Ringwald         }
427*3deb3ec6SMatthias Ringwald 	}
428*3deb3ec6SMatthias Ringwald 
429*3deb3ec6SMatthias Ringwald 	return 0;
430*3deb3ec6SMatthias Ringwald }
431*3deb3ec6SMatthias Ringwald 
432*3deb3ec6SMatthias Ringwald 
433*3deb3ec6SMatthias Ringwald /* Send BNEP ethernet packet */
434*3deb3ec6SMatthias Ringwald int bnep_send(uint16_t bnep_cid, uint8_t *packet, uint16_t len)
435*3deb3ec6SMatthias Ringwald {
436*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
437*3deb3ec6SMatthias Ringwald     uint8_t        *bnep_out_buffer = NULL;
438*3deb3ec6SMatthias Ringwald     uint16_t        pos = 0;
439*3deb3ec6SMatthias Ringwald     uint16_t        pos_out = 0;
440*3deb3ec6SMatthias Ringwald     uint16_t        payload_len;
441*3deb3ec6SMatthias Ringwald     int             err = 0;
442*3deb3ec6SMatthias Ringwald     int             has_source;
443*3deb3ec6SMatthias Ringwald     int             has_dest;
444*3deb3ec6SMatthias Ringwald 
445*3deb3ec6SMatthias Ringwald     bd_addr_t       addr_dest;
446*3deb3ec6SMatthias Ringwald     bd_addr_t       addr_source;
447*3deb3ec6SMatthias Ringwald     uint16_t        network_protocol_type;
448*3deb3ec6SMatthias Ringwald 
449*3deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
450*3deb3ec6SMatthias Ringwald     if (channel == NULL) {
451*3deb3ec6SMatthias Ringwald         log_error("bnep_send cid 0x%02x doesn't exist!", bnep_cid);
452*3deb3ec6SMatthias Ringwald         return 1;
453*3deb3ec6SMatthias Ringwald     }
454*3deb3ec6SMatthias Ringwald 
455*3deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
456*3deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
457*3deb3ec6SMatthias Ringwald     }
458*3deb3ec6SMatthias Ringwald 
459*3deb3ec6SMatthias Ringwald     /* Check for free ACL buffers */
460*3deb3ec6SMatthias Ringwald     if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
461*3deb3ec6SMatthias Ringwald         return BTSTACK_ACL_BUFFERS_FULL;
462*3deb3ec6SMatthias Ringwald     }
463*3deb3ec6SMatthias Ringwald 
464*3deb3ec6SMatthias Ringwald     /* Extract destination and source address from the ethernet packet */
465*3deb3ec6SMatthias Ringwald     pos = 0;
466*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(addr_dest, &packet[pos]);
467*3deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
468*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(addr_source, &packet[pos]);
469*3deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
470*3deb3ec6SMatthias Ringwald     network_protocol_type = READ_NET_16(packet, pos);
471*3deb3ec6SMatthias Ringwald     pos += sizeof(uint16_t);
472*3deb3ec6SMatthias Ringwald 
473*3deb3ec6SMatthias Ringwald     payload_len = len - pos;
474*3deb3ec6SMatthias Ringwald 
475*3deb3ec6SMatthias Ringwald 	if (network_protocol_type == ETHERTYPE_VLAN) {	/* IEEE 802.1Q tag header */
476*3deb3ec6SMatthias Ringwald 		if (payload_len < 4) {
477*3deb3ec6SMatthias Ringwald             /* Omit this packet */
478*3deb3ec6SMatthias Ringwald 			return 0;
479*3deb3ec6SMatthias Ringwald         }
480*3deb3ec6SMatthias Ringwald         /* The "real" network protocol type is 4 bytes ahead in a VLAN packet */
481*3deb3ec6SMatthias Ringwald 		network_protocol_type = READ_NET_16(packet, pos + 2);
482*3deb3ec6SMatthias Ringwald 	}
483*3deb3ec6SMatthias Ringwald 
484*3deb3ec6SMatthias Ringwald     /* Check network protocol and multicast filters before sending */
485*3deb3ec6SMatthias Ringwald     if (!bnep_filter_protocol(channel, network_protocol_type) ||
486*3deb3ec6SMatthias Ringwald         !bnep_filter_multicast(channel, addr_dest)) {
487*3deb3ec6SMatthias Ringwald         /* Packet did not pass filter... */
488*3deb3ec6SMatthias Ringwald         if ((network_protocol_type == ETHERTYPE_VLAN) &&
489*3deb3ec6SMatthias Ringwald             (payload_len >= 4)) {
490*3deb3ec6SMatthias Ringwald             /* The packet has been tagged as a with IEE 802.1Q tag and has been filtered out.
491*3deb3ec6SMatthias Ringwald                According to the spec the IEE802.1Q tag header shall be sended without ethernet payload.
492*3deb3ec6SMatthias Ringwald                So limit the payload_len to 4.
493*3deb3ec6SMatthias Ringwald              */
494*3deb3ec6SMatthias Ringwald             payload_len = 4;
495*3deb3ec6SMatthias Ringwald         } else {
496*3deb3ec6SMatthias Ringwald             /* Packet is not tagged with IEE802.1Q header and was filtered out. Omit this packet */
497*3deb3ec6SMatthias Ringwald             return 0;
498*3deb3ec6SMatthias Ringwald         }
499*3deb3ec6SMatthias Ringwald     }
500*3deb3ec6SMatthias Ringwald 
501*3deb3ec6SMatthias Ringwald     /* Reserve l2cap packet buffer */
502*3deb3ec6SMatthias Ringwald     l2cap_reserve_packet_buffer();
503*3deb3ec6SMatthias Ringwald     bnep_out_buffer = l2cap_get_outgoing_buffer();
504*3deb3ec6SMatthias Ringwald 
505*3deb3ec6SMatthias Ringwald     /* Check if source address is the same as our local address and if the
506*3deb3ec6SMatthias Ringwald        destination address is the same as the remote addr. Maybe we can use
507*3deb3ec6SMatthias Ringwald        the compressed data format
508*3deb3ec6SMatthias Ringwald      */
509*3deb3ec6SMatthias Ringwald     has_source = (memcmp(addr_source, channel->local_addr, ETHER_ADDR_LEN) != 0);
510*3deb3ec6SMatthias Ringwald     has_dest = (memcmp(addr_dest, channel->remote_addr, ETHER_ADDR_LEN) != 0);
511*3deb3ec6SMatthias Ringwald 
512*3deb3ec6SMatthias Ringwald     /* Check for MTU limits */
513*3deb3ec6SMatthias Ringwald     if (payload_len > channel->max_frame_size) {
514*3deb3ec6SMatthias Ringwald         log_error("bnep_send: Max frame size (%d) exceeded: %d", channel->max_frame_size, payload_len);
515*3deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
516*3deb3ec6SMatthias Ringwald     }
517*3deb3ec6SMatthias Ringwald 
518*3deb3ec6SMatthias Ringwald     /* Fill in the package type depending on the given source and destination address */
519*3deb3ec6SMatthias Ringwald     if (has_source && has_dest) {
520*3deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_GENERAL_ETHERNET;
521*3deb3ec6SMatthias Ringwald     } else
522*3deb3ec6SMatthias Ringwald     if (has_source && !has_dest) {
523*3deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY;
524*3deb3ec6SMatthias Ringwald     } else
525*3deb3ec6SMatthias Ringwald     if (!has_source && has_dest) {
526*3deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY;
527*3deb3ec6SMatthias Ringwald     } else {
528*3deb3ec6SMatthias Ringwald         bnep_out_buffer[pos_out++] = BNEP_PKT_TYPE_COMPRESSED_ETHERNET;
529*3deb3ec6SMatthias Ringwald     }
530*3deb3ec6SMatthias Ringwald 
531*3deb3ec6SMatthias Ringwald     /* Add the destination address if needed */
532*3deb3ec6SMatthias Ringwald     if (has_dest) {
533*3deb3ec6SMatthias Ringwald         BD_ADDR_COPY(bnep_out_buffer + pos_out, addr_dest);
534*3deb3ec6SMatthias Ringwald         pos_out += sizeof(bd_addr_t);
535*3deb3ec6SMatthias Ringwald     }
536*3deb3ec6SMatthias Ringwald 
537*3deb3ec6SMatthias Ringwald     /* Add the source address if needed */
538*3deb3ec6SMatthias Ringwald     if (has_source) {
539*3deb3ec6SMatthias Ringwald         BD_ADDR_COPY(bnep_out_buffer + pos_out, addr_source);
540*3deb3ec6SMatthias Ringwald         pos_out += sizeof(bd_addr_t);
541*3deb3ec6SMatthias Ringwald     }
542*3deb3ec6SMatthias Ringwald 
543*3deb3ec6SMatthias Ringwald     /* Add protocol type */
544*3deb3ec6SMatthias Ringwald     net_store_16(bnep_out_buffer, pos_out, network_protocol_type);
545*3deb3ec6SMatthias Ringwald     pos_out += 2;
546*3deb3ec6SMatthias Ringwald 
547*3deb3ec6SMatthias Ringwald     /* TODO: Add extension headers, if we may support them at a later stage */
548*3deb3ec6SMatthias Ringwald     /* Add the payload and then send out the package */
549*3deb3ec6SMatthias Ringwald     memcpy(bnep_out_buffer + pos_out, packet + pos, payload_len);
550*3deb3ec6SMatthias Ringwald     pos_out += payload_len;
551*3deb3ec6SMatthias Ringwald 
552*3deb3ec6SMatthias Ringwald     err = l2cap_send_prepared(channel->l2cap_cid, pos_out);
553*3deb3ec6SMatthias Ringwald 
554*3deb3ec6SMatthias Ringwald     if (err) {
555*3deb3ec6SMatthias Ringwald         log_error("bnep_send: error %d", err);
556*3deb3ec6SMatthias Ringwald     }
557*3deb3ec6SMatthias Ringwald     return err;
558*3deb3ec6SMatthias Ringwald }
559*3deb3ec6SMatthias Ringwald 
560*3deb3ec6SMatthias Ringwald 
561*3deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
562*3deb3ec6SMatthias Ringwald int bnep_set_net_type_filter(uint16_t bnep_cid, bnep_net_filter_t *filter, uint16_t len)
563*3deb3ec6SMatthias Ringwald {
564*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
565*3deb3ec6SMatthias Ringwald 
566*3deb3ec6SMatthias Ringwald     if (filter == NULL) {
567*3deb3ec6SMatthias Ringwald         return -1;
568*3deb3ec6SMatthias Ringwald     }
569*3deb3ec6SMatthias Ringwald 
570*3deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
571*3deb3ec6SMatthias Ringwald     if (channel == NULL) {
572*3deb3ec6SMatthias Ringwald         log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
573*3deb3ec6SMatthias Ringwald         return 1;
574*3deb3ec6SMatthias Ringwald     }
575*3deb3ec6SMatthias Ringwald 
576*3deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
577*3deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
578*3deb3ec6SMatthias Ringwald     }
579*3deb3ec6SMatthias Ringwald 
580*3deb3ec6SMatthias Ringwald     if (len > MAX_BNEP_NETFILTER_OUT) {
581*3deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
582*3deb3ec6SMatthias Ringwald     }
583*3deb3ec6SMatthias Ringwald 
584*3deb3ec6SMatthias Ringwald     channel->net_filter_out = filter;
585*3deb3ec6SMatthias Ringwald     channel->net_filter_out_count = len;
586*3deb3ec6SMatthias Ringwald 
587*3deb3ec6SMatthias Ringwald     /* Set flag to send out the network protocol type filter set reqeuest on next statemachine cycle */
588*3deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
589*3deb3ec6SMatthias Ringwald     bnep_run();
590*3deb3ec6SMatthias Ringwald 
591*3deb3ec6SMatthias Ringwald     return 0;
592*3deb3ec6SMatthias Ringwald }
593*3deb3ec6SMatthias Ringwald 
594*3deb3ec6SMatthias Ringwald /* Set BNEP network protocol type filter */
595*3deb3ec6SMatthias Ringwald int bnep_set_multicast_filter(uint16_t bnep_cid,  bnep_multi_filter_t *filter, uint16_t len)
596*3deb3ec6SMatthias Ringwald {
597*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
598*3deb3ec6SMatthias Ringwald 
599*3deb3ec6SMatthias Ringwald     if (filter == NULL) {
600*3deb3ec6SMatthias Ringwald         return -1;
601*3deb3ec6SMatthias Ringwald     }
602*3deb3ec6SMatthias Ringwald 
603*3deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(bnep_cid);
604*3deb3ec6SMatthias Ringwald     if (channel == NULL) {
605*3deb3ec6SMatthias Ringwald         log_error("bnep_set_net_type_filter cid 0x%02x doesn't exist!", bnep_cid);
606*3deb3ec6SMatthias Ringwald         return 1;
607*3deb3ec6SMatthias Ringwald     }
608*3deb3ec6SMatthias Ringwald 
609*3deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_CONNECTED) {
610*3deb3ec6SMatthias Ringwald         return BNEP_CHANNEL_NOT_CONNECTED;
611*3deb3ec6SMatthias Ringwald     }
612*3deb3ec6SMatthias Ringwald 
613*3deb3ec6SMatthias Ringwald     if (len > MAX_BNEP_MULTICAST_FULTER_OUT) {
614*3deb3ec6SMatthias Ringwald         return BNEP_DATA_LEN_EXCEEDS_MTU;
615*3deb3ec6SMatthias Ringwald     }
616*3deb3ec6SMatthias Ringwald 
617*3deb3ec6SMatthias Ringwald     channel->multicast_filter_out = filter;
618*3deb3ec6SMatthias Ringwald     channel->multicast_filter_out_count = len;
619*3deb3ec6SMatthias Ringwald 
620*3deb3ec6SMatthias Ringwald     /* Set flag to send out the multicast filter set reqeuest on next statemachine cycle */
621*3deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
622*3deb3ec6SMatthias Ringwald     bnep_run();
623*3deb3ec6SMatthias Ringwald 
624*3deb3ec6SMatthias Ringwald     return 0;
625*3deb3ec6SMatthias Ringwald }
626*3deb3ec6SMatthias Ringwald 
627*3deb3ec6SMatthias Ringwald /* BNEP timeout timer helper function */
628*3deb3ec6SMatthias Ringwald static void bnep_channel_timer_handler(timer_source_t *timer)
629*3deb3ec6SMatthias Ringwald {
630*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel = (bnep_channel_t *)linked_item_get_user((linked_item_t *) timer);
631*3deb3ec6SMatthias Ringwald     // retry send setup connection at least one time
632*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE){
633*3deb3ec6SMatthias Ringwald         if (channel->retry_count < BNEP_CONNECTION_MAX_RETRIES){
634*3deb3ec6SMatthias Ringwald             channel->retry_count++;
635*3deb3ec6SMatthias Ringwald             bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
636*3deb3ec6SMatthias Ringwald             bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
637*3deb3ec6SMatthias Ringwald             bnep_run();
638*3deb3ec6SMatthias Ringwald             return;
639*3deb3ec6SMatthias Ringwald         }
640*3deb3ec6SMatthias Ringwald     }
641*3deb3ec6SMatthias Ringwald 
642*3deb3ec6SMatthias Ringwald     log_info( "bnep_channel_timeout_handler callback: shutting down connection!");
643*3deb3ec6SMatthias Ringwald     bnep_emit_channel_timeout(channel);
644*3deb3ec6SMatthias Ringwald     bnep_channel_finalize(channel);
645*3deb3ec6SMatthias Ringwald }
646*3deb3ec6SMatthias Ringwald 
647*3deb3ec6SMatthias Ringwald 
648*3deb3ec6SMatthias Ringwald static void bnep_channel_stop_timer(bnep_channel_t *channel)
649*3deb3ec6SMatthias Ringwald {
650*3deb3ec6SMatthias Ringwald     if (channel->timer_active) {
651*3deb3ec6SMatthias Ringwald         run_loop_remove_timer(&channel->timer);
652*3deb3ec6SMatthias Ringwald         channel->timer_active = 0;
653*3deb3ec6SMatthias Ringwald     }
654*3deb3ec6SMatthias Ringwald }
655*3deb3ec6SMatthias Ringwald 
656*3deb3ec6SMatthias Ringwald static void bnep_channel_start_timer(bnep_channel_t *channel, int timeout)
657*3deb3ec6SMatthias Ringwald {
658*3deb3ec6SMatthias Ringwald     /* Stop any eventually running timeout timer */
659*3deb3ec6SMatthias Ringwald     bnep_channel_stop_timer(channel);
660*3deb3ec6SMatthias Ringwald 
661*3deb3ec6SMatthias Ringwald     /* Start bnep channel timeout check timer */
662*3deb3ec6SMatthias Ringwald     run_loop_set_timer(&channel->timer, timeout);
663*3deb3ec6SMatthias Ringwald     channel->timer.process = bnep_channel_timer_handler;
664*3deb3ec6SMatthias Ringwald     linked_item_set_user((linked_item_t*) &channel->timer, channel);
665*3deb3ec6SMatthias Ringwald     run_loop_add_timer(&channel->timer);
666*3deb3ec6SMatthias Ringwald     channel->timer_active = 1;
667*3deb3ec6SMatthias Ringwald }
668*3deb3ec6SMatthias Ringwald 
669*3deb3ec6SMatthias Ringwald /* BNEP statemachine functions */
670*3deb3ec6SMatthias Ringwald 
671*3deb3ec6SMatthias Ringwald inline static void bnep_channel_state_add(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
672*3deb3ec6SMatthias Ringwald     channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var | event);
673*3deb3ec6SMatthias Ringwald }
674*3deb3ec6SMatthias Ringwald inline static void bnep_channel_state_remove(bnep_channel_t *channel, BNEP_CHANNEL_STATE_VAR event){
675*3deb3ec6SMatthias Ringwald     channel->state_var = (BNEP_CHANNEL_STATE_VAR) (channel->state_var & ~event);
676*3deb3ec6SMatthias Ringwald }
677*3deb3ec6SMatthias Ringwald 
678*3deb3ec6SMatthias Ringwald static uint16_t bnep_max_frame_size_for_l2cap_mtu(uint16_t l2cap_mtu){
679*3deb3ec6SMatthias Ringwald 
680*3deb3ec6SMatthias Ringwald     /* Assume a standard BNEP header, containing BNEP Type (1 Byte), dest and
681*3deb3ec6SMatthias Ringwald        source address (6 bytes each) and networking protocol type (2 bytes)
682*3deb3ec6SMatthias Ringwald      */
683*3deb3ec6SMatthias Ringwald     uint16_t max_frame_size = l2cap_mtu - 15; // 15 bytes BNEP header
684*3deb3ec6SMatthias Ringwald 
685*3deb3ec6SMatthias Ringwald     log_info("bnep_max_frame_size_for_l2cap_mtu:  %u -> %u", l2cap_mtu, max_frame_size);
686*3deb3ec6SMatthias Ringwald     return max_frame_size;
687*3deb3ec6SMatthias Ringwald }
688*3deb3ec6SMatthias Ringwald 
689*3deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_create_for_addr(bd_addr_t addr)
690*3deb3ec6SMatthias Ringwald {
691*3deb3ec6SMatthias Ringwald     /* Allocate new channel structure */
692*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel = btstack_memory_bnep_channel_get();
693*3deb3ec6SMatthias Ringwald     if (!channel) {
694*3deb3ec6SMatthias Ringwald         return NULL;
695*3deb3ec6SMatthias Ringwald     }
696*3deb3ec6SMatthias Ringwald 
697*3deb3ec6SMatthias Ringwald     /* Initialize the channel struct */
698*3deb3ec6SMatthias Ringwald     memset(channel, 0, sizeof(bnep_channel_t));
699*3deb3ec6SMatthias Ringwald 
700*3deb3ec6SMatthias Ringwald     channel->state = BNEP_CHANNEL_STATE_CLOSED;
701*3deb3ec6SMatthias Ringwald     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(l2cap_max_mtu());
702*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(&channel->remote_addr, addr);
703*3deb3ec6SMatthias Ringwald     hci_local_bd_addr(channel->local_addr);
704*3deb3ec6SMatthias Ringwald 
705*3deb3ec6SMatthias Ringwald     channel->net_filter_count = 0;
706*3deb3ec6SMatthias Ringwald     channel->multicast_filter_count = 0;
707*3deb3ec6SMatthias Ringwald     channel->retry_count = 0;
708*3deb3ec6SMatthias Ringwald 
709*3deb3ec6SMatthias Ringwald     /* Finally add it to the channel list */
710*3deb3ec6SMatthias Ringwald     linked_list_add(&bnep_channels, (linked_item_t *) channel);
711*3deb3ec6SMatthias Ringwald 
712*3deb3ec6SMatthias Ringwald     return channel;
713*3deb3ec6SMatthias Ringwald }
714*3deb3ec6SMatthias Ringwald 
715*3deb3ec6SMatthias Ringwald static bnep_channel_t* bnep_channel_for_addr(bd_addr_t addr)
716*3deb3ec6SMatthias Ringwald {
717*3deb3ec6SMatthias Ringwald     linked_item_t *it;
718*3deb3ec6SMatthias Ringwald     for (it = (linked_item_t *) bnep_channels; it ; it = it->next){
719*3deb3ec6SMatthias Ringwald         bnep_channel_t *channel = ((bnep_channel_t *) it);
720*3deb3ec6SMatthias Ringwald         if (BD_ADDR_CMP(addr, channel->remote_addr) == 0) {
721*3deb3ec6SMatthias Ringwald             return channel;
722*3deb3ec6SMatthias Ringwald         }
723*3deb3ec6SMatthias Ringwald     }
724*3deb3ec6SMatthias Ringwald     return NULL;
725*3deb3ec6SMatthias Ringwald }
726*3deb3ec6SMatthias Ringwald 
727*3deb3ec6SMatthias Ringwald static bnep_channel_t * bnep_channel_for_l2cap_cid(uint16_t l2cap_cid)
728*3deb3ec6SMatthias Ringwald {
729*3deb3ec6SMatthias Ringwald     linked_item_t *it;
730*3deb3ec6SMatthias Ringwald     for (it = (linked_item_t *) bnep_channels; it ; it = it->next){
731*3deb3ec6SMatthias Ringwald         bnep_channel_t *channel = ((bnep_channel_t *) it);
732*3deb3ec6SMatthias Ringwald         if (channel->l2cap_cid == l2cap_cid) {
733*3deb3ec6SMatthias Ringwald             return channel;
734*3deb3ec6SMatthias Ringwald         }
735*3deb3ec6SMatthias Ringwald     }
736*3deb3ec6SMatthias Ringwald     return NULL;
737*3deb3ec6SMatthias Ringwald }
738*3deb3ec6SMatthias Ringwald 
739*3deb3ec6SMatthias Ringwald static bnep_service_t * bnep_service_for_uuid(uint16_t uuid)
740*3deb3ec6SMatthias Ringwald {
741*3deb3ec6SMatthias Ringwald     linked_item_t *it;
742*3deb3ec6SMatthias Ringwald     for (it = (linked_item_t *) bnep_services; it ; it = it->next){
743*3deb3ec6SMatthias Ringwald         bnep_service_t * service = ((bnep_service_t *) it);
744*3deb3ec6SMatthias Ringwald         if ( service->service_uuid == uuid){
745*3deb3ec6SMatthias Ringwald             return service;
746*3deb3ec6SMatthias Ringwald         }
747*3deb3ec6SMatthias Ringwald     }
748*3deb3ec6SMatthias Ringwald     return NULL;
749*3deb3ec6SMatthias Ringwald }
750*3deb3ec6SMatthias Ringwald 
751*3deb3ec6SMatthias Ringwald static void bnep_channel_free(bnep_channel_t *channel)
752*3deb3ec6SMatthias Ringwald {
753*3deb3ec6SMatthias Ringwald     linked_list_remove( &bnep_channels, (linked_item_t *) channel);
754*3deb3ec6SMatthias Ringwald     btstack_memory_bnep_channel_free(channel);
755*3deb3ec6SMatthias Ringwald }
756*3deb3ec6SMatthias Ringwald 
757*3deb3ec6SMatthias Ringwald static void bnep_channel_finalize(bnep_channel_t *channel)
758*3deb3ec6SMatthias Ringwald {
759*3deb3ec6SMatthias Ringwald     uint16_t l2cap_cid;
760*3deb3ec6SMatthias Ringwald 
761*3deb3ec6SMatthias Ringwald     /* Inform application about closed channel */
762*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
763*3deb3ec6SMatthias Ringwald         bnep_emit_channel_closed(channel);
764*3deb3ec6SMatthias Ringwald     }
765*3deb3ec6SMatthias Ringwald 
766*3deb3ec6SMatthias Ringwald     l2cap_cid = channel->l2cap_cid;
767*3deb3ec6SMatthias Ringwald 
768*3deb3ec6SMatthias Ringwald     /* Stop any eventually running timer */
769*3deb3ec6SMatthias Ringwald     bnep_channel_stop_timer(channel);
770*3deb3ec6SMatthias Ringwald 
771*3deb3ec6SMatthias Ringwald     /* Free ressources and then close the l2cap channel */
772*3deb3ec6SMatthias Ringwald     bnep_channel_free(channel);
773*3deb3ec6SMatthias Ringwald     l2cap_disconnect_internal(l2cap_cid, 0x13);
774*3deb3ec6SMatthias Ringwald }
775*3deb3ec6SMatthias Ringwald 
776*3deb3ec6SMatthias Ringwald static int bnep_handle_connection_request(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
777*3deb3ec6SMatthias Ringwald {
778*3deb3ec6SMatthias Ringwald     uint16_t uuid_size;
779*3deb3ec6SMatthias Ringwald     uint16_t uuid_offset;
780*3deb3ec6SMatthias Ringwald     uuid_size = packet[1];
781*3deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_SETUP_SUCCESS;
782*3deb3ec6SMatthias Ringwald     bnep_service_t * service;
783*3deb3ec6SMatthias Ringwald 
784*3deb3ec6SMatthias Ringwald     /* Sanity check packet size */
785*3deb3ec6SMatthias Ringwald     if (size < 1 + 1 + 2 * uuid_size) {
786*3deb3ec6SMatthias Ringwald         return 0;
787*3deb3ec6SMatthias Ringwald     }
788*3deb3ec6SMatthias Ringwald 
789*3deb3ec6SMatthias Ringwald     if ((channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
790*3deb3ec6SMatthias Ringwald         (channel->state != BNEP_CHANNEL_STATE_CONNECTED)) {
791*3deb3ec6SMatthias Ringwald         /* Ignore a connection request if not waiting for or still connected */
792*3deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_REQUEST: ignored in state %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
793*3deb3ec6SMatthias Ringwald         return 0;
794*3deb3ec6SMatthias Ringwald     }
795*3deb3ec6SMatthias Ringwald 
796*3deb3ec6SMatthias Ringwald      /* Extract source and destination UUID and convert them to UUID16 format */
797*3deb3ec6SMatthias Ringwald     switch (uuid_size) {
798*3deb3ec6SMatthias Ringwald         case 2:  /* UUID16  */
799*3deb3ec6SMatthias Ringwald             uuid_offset = 0;
800*3deb3ec6SMatthias Ringwald             break;
801*3deb3ec6SMatthias Ringwald         case 4:  /* UUID32  */
802*3deb3ec6SMatthias Ringwald         case 16: /* UUID128 */
803*3deb3ec6SMatthias Ringwald             uuid_offset = 2;
804*3deb3ec6SMatthias Ringwald             break;
805*3deb3ec6SMatthias Ringwald         default:
806*3deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid UUID size %d, l2cap_cid: %d!", channel->state, channel->l2cap_cid);
807*3deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_SERVICE_UUID_SIZE;
808*3deb3ec6SMatthias Ringwald             break;
809*3deb3ec6SMatthias Ringwald     }
810*3deb3ec6SMatthias Ringwald 
811*3deb3ec6SMatthias Ringwald     /* Check source and destination UUIDs for valid combinations */
812*3deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_SETUP_SUCCESS) {
813*3deb3ec6SMatthias Ringwald         channel->uuid_dest = READ_NET_16(packet, 2 + uuid_offset);
814*3deb3ec6SMatthias Ringwald         channel->uuid_source = READ_NET_16(packet, 2 + uuid_offset + uuid_size);
815*3deb3ec6SMatthias Ringwald 
816*3deb3ec6SMatthias Ringwald         if ((channel->uuid_dest != SDP_PANU) &&
817*3deb3ec6SMatthias Ringwald             (channel->uuid_dest != SDP_NAP) &&
818*3deb3ec6SMatthias Ringwald             (channel->uuid_dest != SDP_GN)) {
819*3deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid destination service UUID: %04x", channel->uuid_dest);
820*3deb3ec6SMatthias Ringwald             channel->uuid_dest = 0;
821*3deb3ec6SMatthias Ringwald         }
822*3deb3ec6SMatthias Ringwald         if ((channel->uuid_source != SDP_PANU) &&
823*3deb3ec6SMatthias Ringwald             (channel->uuid_source != SDP_NAP) &&
824*3deb3ec6SMatthias Ringwald             (channel->uuid_source != SDP_GN)) {
825*3deb3ec6SMatthias Ringwald             log_error("BNEP_CONNECTION_REQUEST: Invalid source service UUID: %04x", channel->uuid_source);
826*3deb3ec6SMatthias Ringwald             channel->uuid_source = 0;
827*3deb3ec6SMatthias Ringwald         }
828*3deb3ec6SMatthias Ringwald 
829*3deb3ec6SMatthias Ringwald         /* Check if we have registered a service for the requested destination UUID */
830*3deb3ec6SMatthias Ringwald         service = bnep_service_for_uuid(channel->uuid_dest);
831*3deb3ec6SMatthias Ringwald         if (service == NULL) {
832*3deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_DEST_UUID;
833*3deb3ec6SMatthias Ringwald         } else
834*3deb3ec6SMatthias Ringwald         if ((channel->uuid_source != SDP_PANU) && (channel->uuid_dest != SDP_PANU)) {
835*3deb3ec6SMatthias Ringwald             response_code = BNEP_RESP_SETUP_INVALID_SOURCE_UUID;
836*3deb3ec6SMatthias Ringwald         }
837*3deb3ec6SMatthias Ringwald     }
838*3deb3ec6SMatthias Ringwald 
839*3deb3ec6SMatthias Ringwald     /* Set flag to send out the connection response on next statemachine cycle */
840*3deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
841*3deb3ec6SMatthias Ringwald     channel->response_code = response_code;
842*3deb3ec6SMatthias Ringwald 
843*3deb3ec6SMatthias Ringwald     /* Return the number of processed package bytes = BNEP Type, BNEP Control Type, UUID-Size + 2 * UUID */
844*3deb3ec6SMatthias Ringwald     return 1 + 1 + 2 * uuid_size;
845*3deb3ec6SMatthias Ringwald }
846*3deb3ec6SMatthias Ringwald 
847*3deb3ec6SMatthias Ringwald static int bnep_handle_connection_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
848*3deb3ec6SMatthias Ringwald {
849*3deb3ec6SMatthias Ringwald     uint16_t response_code;
850*3deb3ec6SMatthias Ringwald 
851*3deb3ec6SMatthias Ringwald     /* Sanity check packet size */
852*3deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
853*3deb3ec6SMatthias Ringwald         return 0;
854*3deb3ec6SMatthias Ringwald     }
855*3deb3ec6SMatthias Ringwald 
856*3deb3ec6SMatthias Ringwald     if (channel->state != BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE) {
857*3deb3ec6SMatthias Ringwald         /* Ignore a connection response in any state but WAIT_FOR_CONNECTION_RESPONSE */
858*3deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_RESPONSE: Ignored in channel state %d", channel->state);
859*3deb3ec6SMatthias Ringwald         return 1 + 2;
860*3deb3ec6SMatthias Ringwald     }
861*3deb3ec6SMatthias Ringwald 
862*3deb3ec6SMatthias Ringwald     response_code = READ_NET_16(packet, 1);
863*3deb3ec6SMatthias Ringwald 
864*3deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_SETUP_SUCCESS) {
865*3deb3ec6SMatthias Ringwald         log_info("BNEP_CONNECTION_RESPONSE: Channel established to %s", bd_addr_to_str(channel->remote_addr));
866*3deb3ec6SMatthias Ringwald         channel->state = BNEP_CHANNEL_STATE_CONNECTED;
867*3deb3ec6SMatthias Ringwald         /* Stop timeout timer! */
868*3deb3ec6SMatthias Ringwald         bnep_channel_stop_timer(channel);
869*3deb3ec6SMatthias Ringwald         bnep_emit_open_channel_complete(channel, 0);
870*3deb3ec6SMatthias Ringwald     } else {
871*3deb3ec6SMatthias Ringwald         log_error("BNEP_CONNECTION_RESPONSE: Connection to %s failed. Err: %d", bd_addr_to_str(channel->remote_addr), response_code);
872*3deb3ec6SMatthias Ringwald         bnep_channel_finalize(channel);
873*3deb3ec6SMatthias Ringwald     }
874*3deb3ec6SMatthias Ringwald     return 1 + 2;
875*3deb3ec6SMatthias Ringwald }
876*3deb3ec6SMatthias Ringwald 
877*3deb3ec6SMatthias Ringwald static int bnep_can_handle_extensions(bnep_channel_t * channel){
878*3deb3ec6SMatthias Ringwald     /* Extension are primarily handled in CONNECTED state */
879*3deb3ec6SMatthias Ringwald     if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) return 1;
880*3deb3ec6SMatthias Ringwald     /* and if we've received connection request, but haven't sent the reponse yet. */
881*3deb3ec6SMatthias Ringwald     if ((channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST) &&
882*3deb3ec6SMatthias Ringwald         (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE)) {
883*3deb3ec6SMatthias Ringwald         return 1;
884*3deb3ec6SMatthias Ringwald     }
885*3deb3ec6SMatthias Ringwald     return 0;
886*3deb3ec6SMatthias Ringwald }
887*3deb3ec6SMatthias Ringwald 
888*3deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
889*3deb3ec6SMatthias Ringwald {
890*3deb3ec6SMatthias Ringwald     uint16_t list_length;
891*3deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
892*3deb3ec6SMatthias Ringwald 
893*3deb3ec6SMatthias Ringwald     /* Sanity check packet size */
894*3deb3ec6SMatthias Ringwald     if (size < 3) {
895*3deb3ec6SMatthias Ringwald         return 0;
896*3deb3ec6SMatthias Ringwald     }
897*3deb3ec6SMatthias Ringwald 
898*3deb3ec6SMatthias Ringwald     list_length = READ_NET_16(packet, 1);
899*3deb3ec6SMatthias Ringwald     /* Sanity check packet size again with known package size */
900*3deb3ec6SMatthias Ringwald     if (size < 3 + list_length) {
901*3deb3ec6SMatthias Ringwald         return 0;
902*3deb3ec6SMatthias Ringwald     }
903*3deb3ec6SMatthias Ringwald 
904*3deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
905*3deb3ec6SMatthias Ringwald         log_error("BNEP_FILTER_NET_TYPE_SET: Ignored in channel state %d", channel->state);
906*3deb3ec6SMatthias Ringwald         return 3 + list_length;
907*3deb3ec6SMatthias Ringwald     }
908*3deb3ec6SMatthias Ringwald 
909*3deb3ec6SMatthias Ringwald     /* Check if we have enough space for more filters */
910*3deb3ec6SMatthias Ringwald     if ((list_length / (2*2)) > MAX_BNEP_NETFILTER) {
911*3deb3ec6SMatthias Ringwald         log_info("BNEP_FILTER_NET_TYPE_SET: Too many filter");
912*3deb3ec6SMatthias Ringwald         response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
913*3deb3ec6SMatthias Ringwald     } else {
914*3deb3ec6SMatthias Ringwald         int i;
915*3deb3ec6SMatthias Ringwald         channel->net_filter_count = 0;
916*3deb3ec6SMatthias Ringwald         /* There is still enough space, copy the filters to our filter list */
917*3deb3ec6SMatthias Ringwald         for (i = 0; i < list_length / (2 * 2); i ++) {
918*3deb3ec6SMatthias Ringwald             channel->net_filter[channel->net_filter_count].range_start = READ_NET_16(packet, 1 + 2 + i * 4);
919*3deb3ec6SMatthias Ringwald             channel->net_filter[channel->net_filter_count].range_end = READ_NET_16(packet, 1 + 2 + i * 4 + 2);
920*3deb3ec6SMatthias Ringwald             if (channel->net_filter[channel->net_filter_count].range_start > channel->net_filter[channel->net_filter_count].range_end) {
921*3deb3ec6SMatthias Ringwald                 /* Invalid filter range, ignore this filter rule */
922*3deb3ec6SMatthias Ringwald                 log_error("BNEP_FILTER_NET_TYPE_SET: Invalid filter: start: %d, end: %d",
923*3deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_start,
924*3deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_end);
925*3deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
926*3deb3ec6SMatthias Ringwald             } else {
927*3deb3ec6SMatthias Ringwald                 /* Valid filter, increase the filter count */
928*3deb3ec6SMatthias Ringwald                 log_info("BNEP_FILTER_NET_TYPE_SET: Add filter: start: %d, end: %d",
929*3deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_start,
930*3deb3ec6SMatthias Ringwald                          channel->net_filter[channel->net_filter_count].range_end);
931*3deb3ec6SMatthias Ringwald                 channel->net_filter_count ++;
932*3deb3ec6SMatthias Ringwald             }
933*3deb3ec6SMatthias Ringwald         }
934*3deb3ec6SMatthias Ringwald     }
935*3deb3ec6SMatthias Ringwald 
936*3deb3ec6SMatthias Ringwald     /* Set flag to send out the set net filter response on next statemachine cycle */
937*3deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
938*3deb3ec6SMatthias Ringwald     channel->response_code = response_code;
939*3deb3ec6SMatthias Ringwald 
940*3deb3ec6SMatthias Ringwald     return 3 + list_length;
941*3deb3ec6SMatthias Ringwald }
942*3deb3ec6SMatthias Ringwald 
943*3deb3ec6SMatthias Ringwald static int bnep_handle_filter_net_type_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
944*3deb3ec6SMatthias Ringwald {
945*3deb3ec6SMatthias Ringwald 	uint16_t response_code;
946*3deb3ec6SMatthias Ringwald 
947*3deb3ec6SMatthias Ringwald     // TODO: Currently we do not support setting a network filter.
948*3deb3ec6SMatthias Ringwald 
949*3deb3ec6SMatthias Ringwald     /* Sanity check packet size */
950*3deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
951*3deb3ec6SMatthias Ringwald         return 0;
952*3deb3ec6SMatthias Ringwald     }
953*3deb3ec6SMatthias Ringwald 
954*3deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
955*3deb3ec6SMatthias Ringwald         log_error("BNEP_FILTER_NET_TYPE_RESPONSE: Ignored in channel state %d", channel->state);
956*3deb3ec6SMatthias Ringwald         return 1 + 2;
957*3deb3ec6SMatthias Ringwald     }
958*3deb3ec6SMatthias Ringwald 
959*3deb3ec6SMatthias Ringwald     response_code = READ_NET_16(packet, 1);
960*3deb3ec6SMatthias Ringwald 
961*3deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_FILTER_SUCCESS) {
962*3deb3ec6SMatthias Ringwald         log_info("BNEP_FILTER_NET_TYPE_RESPONSE: Net filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
963*3deb3ec6SMatthias Ringwald     } else {
964*3deb3ec6SMatthias 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);
965*3deb3ec6SMatthias Ringwald     }
966*3deb3ec6SMatthias Ringwald 
967*3deb3ec6SMatthias Ringwald     return 1 + 2;
968*3deb3ec6SMatthias Ringwald }
969*3deb3ec6SMatthias Ringwald 
970*3deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_set(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
971*3deb3ec6SMatthias Ringwald {
972*3deb3ec6SMatthias Ringwald     uint16_t list_length;
973*3deb3ec6SMatthias Ringwald     uint16_t response_code = BNEP_RESP_FILTER_SUCCESS;
974*3deb3ec6SMatthias Ringwald 
975*3deb3ec6SMatthias Ringwald     /* Sanity check packet size */
976*3deb3ec6SMatthias Ringwald     if (size < 3) {
977*3deb3ec6SMatthias Ringwald         return 0;
978*3deb3ec6SMatthias Ringwald     }
979*3deb3ec6SMatthias Ringwald 
980*3deb3ec6SMatthias Ringwald     list_length = READ_NET_16(packet, 1);
981*3deb3ec6SMatthias Ringwald     /* Sanity check packet size again with known package size */
982*3deb3ec6SMatthias Ringwald     if (size < 3 + list_length) {
983*3deb3ec6SMatthias Ringwald         return 0;
984*3deb3ec6SMatthias Ringwald     }
985*3deb3ec6SMatthias Ringwald 
986*3deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
987*3deb3ec6SMatthias Ringwald         log_error("BNEP_MULTI_ADDR_SET: Ignored in channel state %d", channel->state);
988*3deb3ec6SMatthias Ringwald         return 3 + list_length;
989*3deb3ec6SMatthias Ringwald     }
990*3deb3ec6SMatthias Ringwald 
991*3deb3ec6SMatthias Ringwald     /* Check if we have enough space for more filters */
992*3deb3ec6SMatthias Ringwald     if ((list_length / (2 * ETHER_ADDR_LEN)) > MAX_BNEP_MULTICAST_FILTER) {
993*3deb3ec6SMatthias Ringwald         log_info("BNEP_MULTI_ADDR_SET: Too many filter");
994*3deb3ec6SMatthias Ringwald         response_code = BNEP_RESP_FILTER_ERR_TOO_MANY_FILTERS;
995*3deb3ec6SMatthias Ringwald     } else {
996*3deb3ec6SMatthias Ringwald         unsigned int i;
997*3deb3ec6SMatthias Ringwald         channel->multicast_filter_count = 0;
998*3deb3ec6SMatthias Ringwald         /* There is enough space, copy the filters to our filter list */
999*3deb3ec6SMatthias Ringwald         for (i = 0; i < list_length / (2 * ETHER_ADDR_LEN); i ++) {
1000*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(channel->multicast_filter[channel->multicast_filter_count].addr_start, packet + 1 + 2 + i * ETHER_ADDR_LEN * 2);
1001*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(channel->multicast_filter[channel->multicast_filter_count].addr_end, packet + 1 + 2 + i * ETHER_ADDR_LEN * 2 + ETHER_ADDR_LEN);
1002*3deb3ec6SMatthias Ringwald 
1003*3deb3ec6SMatthias Ringwald             if (memcmp(channel->multicast_filter[channel->multicast_filter_count].addr_start,
1004*3deb3ec6SMatthias Ringwald                        channel->multicast_filter[channel->multicast_filter_count].addr_end, ETHER_ADDR_LEN) > 0) {
1005*3deb3ec6SMatthias Ringwald                 /* Invalid filter range, ignore this filter rule */
1006*3deb3ec6SMatthias Ringwald                 log_error("BNEP_MULTI_ADDR_SET: Invalid filter: start: %s",
1007*3deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
1008*3deb3ec6SMatthias Ringwald                 log_error("BNEP_MULTI_ADDR_SET: Invalid filter: end: %s",
1009*3deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
1010*3deb3ec6SMatthias Ringwald                 response_code = BNEP_RESP_FILTER_ERR_INVALID_RANGE;
1011*3deb3ec6SMatthias Ringwald             } else {
1012*3deb3ec6SMatthias Ringwald                 /* Valid filter, increase the filter count */
1013*3deb3ec6SMatthias Ringwald                 log_info("BNEP_MULTI_ADDR_SET: Add filter: start: %s",
1014*3deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_start));
1015*3deb3ec6SMatthias Ringwald                 log_info("BNEP_MULTI_ADDR_SET: Add filter: end: %s",
1016*3deb3ec6SMatthias Ringwald                          bd_addr_to_str(channel->multicast_filter[channel->multicast_filter_count].addr_end));
1017*3deb3ec6SMatthias Ringwald                 channel->multicast_filter_count ++;
1018*3deb3ec6SMatthias Ringwald             }
1019*3deb3ec6SMatthias Ringwald         }
1020*3deb3ec6SMatthias Ringwald     }
1021*3deb3ec6SMatthias Ringwald     /* Set flag to send out the set multi addr response on next statemachine cycle */
1022*3deb3ec6SMatthias Ringwald     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
1023*3deb3ec6SMatthias Ringwald     channel->response_code = response_code;
1024*3deb3ec6SMatthias Ringwald 
1025*3deb3ec6SMatthias Ringwald     return 3 + list_length;
1026*3deb3ec6SMatthias Ringwald }
1027*3deb3ec6SMatthias Ringwald 
1028*3deb3ec6SMatthias Ringwald static int bnep_handle_multi_addr_response(bnep_channel_t *channel, uint8_t *packet, uint16_t size)
1029*3deb3ec6SMatthias Ringwald {
1030*3deb3ec6SMatthias Ringwald 	uint16_t response_code;
1031*3deb3ec6SMatthias Ringwald 
1032*3deb3ec6SMatthias Ringwald     // TODO: Currently we do not support setting multicast address filter.
1033*3deb3ec6SMatthias Ringwald 
1034*3deb3ec6SMatthias Ringwald     /* Sanity check packet size */
1035*3deb3ec6SMatthias Ringwald     if (size < 1 + 2) {
1036*3deb3ec6SMatthias Ringwald         return 0;
1037*3deb3ec6SMatthias Ringwald     }
1038*3deb3ec6SMatthias Ringwald 
1039*3deb3ec6SMatthias Ringwald     if (!bnep_can_handle_extensions(channel)){
1040*3deb3ec6SMatthias Ringwald         log_error("BNEP_MULTI_ADDR_RESPONSE: Ignored in channel state %d", channel->state);
1041*3deb3ec6SMatthias Ringwald         return 1 + 2;
1042*3deb3ec6SMatthias Ringwald     }
1043*3deb3ec6SMatthias Ringwald 
1044*3deb3ec6SMatthias Ringwald     response_code = READ_NET_16(packet, 1);
1045*3deb3ec6SMatthias Ringwald 
1046*3deb3ec6SMatthias Ringwald     if (response_code == BNEP_RESP_FILTER_SUCCESS) {
1047*3deb3ec6SMatthias Ringwald         log_info("BNEP_MULTI_ADDR_RESPONSE: Multicast address filter set successfully for %s", bd_addr_to_str(channel->remote_addr));
1048*3deb3ec6SMatthias Ringwald     } else {
1049*3deb3ec6SMatthias 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);
1050*3deb3ec6SMatthias Ringwald     }
1051*3deb3ec6SMatthias Ringwald 
1052*3deb3ec6SMatthias Ringwald     return 1 + 2;
1053*3deb3ec6SMatthias Ringwald }
1054*3deb3ec6SMatthias Ringwald 
1055*3deb3ec6SMatthias 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)
1056*3deb3ec6SMatthias Ringwald {
1057*3deb3ec6SMatthias Ringwald     uint16_t pos = 0;
1058*3deb3ec6SMatthias Ringwald 
1059*3deb3ec6SMatthias Ringwald #if (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)
1060*3deb3ec6SMatthias Ringwald     /* In-place modify the package and add the ethernet header in front of the payload.
1061*3deb3ec6SMatthias Ringwald      * WARNING: This modifies the data in front of the payload and may overwrite 14 bytes there!
1062*3deb3ec6SMatthias Ringwald      */
1063*3deb3ec6SMatthias Ringwald     uint8_t *ethernet_packet = payload - 2 * sizeof(bd_addr_t) - sizeof(uint16_t);
1064*3deb3ec6SMatthias Ringwald     /* Restore the ethernet packet header */
1065*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(ethernet_packet + pos, addr_dest);
1066*3deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1067*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(ethernet_packet + pos, addr_source);
1068*3deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1069*3deb3ec6SMatthias Ringwald     net_store_16(ethernet_packet, pos, network_protocol_type);
1070*3deb3ec6SMatthias Ringwald     /* Payload is just in place... */
1071*3deb3ec6SMatthias Ringwald #else
1072*3deb3ec6SMatthias Ringwald     /* Copy ethernet frame to statically allocated buffer. This solution is more
1073*3deb3ec6SMatthias Ringwald      * save, but needs an extra copy and more stack!
1074*3deb3ec6SMatthias Ringwald      */
1075*3deb3ec6SMatthias Ringwald     uint8_t ethernet_packet[BNEP_MTU_MIN];
1076*3deb3ec6SMatthias Ringwald 
1077*3deb3ec6SMatthias Ringwald     /* Restore the ethernet packet header */
1078*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(ethernet_packet + pos, addr_dest);
1079*3deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1080*3deb3ec6SMatthias Ringwald     BD_ADDR_COPY(ethernet_packet + pos, addr_source);
1081*3deb3ec6SMatthias Ringwald     pos += sizeof(bd_addr_t);
1082*3deb3ec6SMatthias Ringwald     net_store_16(ethernet_packet, pos, network_protocol_type);
1083*3deb3ec6SMatthias Ringwald     pos += 2;
1084*3deb3ec6SMatthias Ringwald     memcpy(ethernet_packet + pos, payload, size);
1085*3deb3ec6SMatthias Ringwald #endif
1086*3deb3ec6SMatthias Ringwald 
1087*3deb3ec6SMatthias Ringwald     /* Notify application layer and deliver the ethernet packet */
1088*3deb3ec6SMatthias Ringwald     (*app_packet_handler)(channel->connection, BNEP_DATA_PACKET, channel->uuid_source,
1089*3deb3ec6SMatthias Ringwald                           ethernet_packet, size + sizeof(uint16_t) + 2 * sizeof(bd_addr_t));
1090*3deb3ec6SMatthias Ringwald 
1091*3deb3ec6SMatthias Ringwald     return size;
1092*3deb3ec6SMatthias Ringwald }
1093*3deb3ec6SMatthias Ringwald 
1094*3deb3ec6SMatthias Ringwald static int bnep_handle_control_packet(bnep_channel_t *channel, uint8_t *packet, uint16_t size, int is_extension)
1095*3deb3ec6SMatthias Ringwald {
1096*3deb3ec6SMatthias Ringwald     uint16_t len = 0;
1097*3deb3ec6SMatthias Ringwald     uint8_t  bnep_control_type;
1098*3deb3ec6SMatthias Ringwald 
1099*3deb3ec6SMatthias Ringwald     bnep_control_type = packet[0];
1100*3deb3ec6SMatthias Ringwald     /* Save last control type. Needed by statemachin in case of unknown control code */
1101*3deb3ec6SMatthias Ringwald 
1102*3deb3ec6SMatthias Ringwald     channel->last_control_type = bnep_control_type;
1103*3deb3ec6SMatthias Ringwald     log_info("BNEP_CONTROL: Type: %d, size: %d, is_extension: %d", bnep_control_type, size, is_extension);
1104*3deb3ec6SMatthias Ringwald     switch (bnep_control_type) {
1105*3deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_COMMAND_NOT_UNDERSTOOD:
1106*3deb3ec6SMatthias Ringwald             /* The last command we send was not understood. We should close the connection */
1107*3deb3ec6SMatthias Ringwald             log_error("BNEP_CONTROL: Received COMMAND_NOT_UNDERSTOOD: l2cap_cid: %d, cmd: %d", channel->l2cap_cid, packet[3]);
1108*3deb3ec6SMatthias Ringwald             bnep_channel_finalize(channel);
1109*3deb3ec6SMatthias Ringwald             len = 2; // Length of command not understood packet - bnep-type field
1110*3deb3ec6SMatthias Ringwald             break;
1111*3deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_SETUP_CONNECTION_REQUEST:
1112*3deb3ec6SMatthias Ringwald             if (is_extension) {
1113*3deb3ec6SMatthias Ringwald                 /* Connection requests are not allowed to be send in an extension header
1114*3deb3ec6SMatthias Ringwald                  *  ignore, do not set "COMMAND_NOT_UNDERSTOOD"
1115*3deb3ec6SMatthias Ringwald                  */
1116*3deb3ec6SMatthias Ringwald                 log_error("BNEP_CONTROL: Received SETUP_CONNECTION_REQUEST in extension header: l2cap_cid: %d", channel->l2cap_cid);
1117*3deb3ec6SMatthias Ringwald                 return 0;
1118*3deb3ec6SMatthias Ringwald             } else {
1119*3deb3ec6SMatthias Ringwald                 len = bnep_handle_connection_request(channel, packet, size);
1120*3deb3ec6SMatthias Ringwald             }
1121*3deb3ec6SMatthias Ringwald             break;
1122*3deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_SETUP_CONNECTION_RESPONSE:
1123*3deb3ec6SMatthias Ringwald             if (is_extension) {
1124*3deb3ec6SMatthias Ringwald                 /* Connection requests are not allowed to be send in an
1125*3deb3ec6SMatthias Ringwald                  * extension header, ignore, do not set "COMMAND_NOT_UNDERSTOOD"
1126*3deb3ec6SMatthias Ringwald                  */
1127*3deb3ec6SMatthias Ringwald                 log_error("BNEP_CONTROL: Received SETUP_CONNECTION_RESPONSE in extension header: l2cap_cid: %d", channel->l2cap_cid);
1128*3deb3ec6SMatthias Ringwald                 return 0;
1129*3deb3ec6SMatthias Ringwald             } else {
1130*3deb3ec6SMatthias Ringwald                 len = bnep_handle_connection_response(channel, packet, size);
1131*3deb3ec6SMatthias Ringwald             }
1132*3deb3ec6SMatthias Ringwald             break;
1133*3deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_SET:
1134*3deb3ec6SMatthias Ringwald             len = bnep_handle_filter_net_type_set(channel, packet, size);
1135*3deb3ec6SMatthias Ringwald             break;
1136*3deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_NET_TYPE_RESPONSE:
1137*3deb3ec6SMatthias Ringwald             len = bnep_handle_filter_net_type_response(channel, packet, size);
1138*3deb3ec6SMatthias Ringwald             break;
1139*3deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_SET:
1140*3deb3ec6SMatthias Ringwald             len = bnep_handle_multi_addr_set(channel, packet, size);
1141*3deb3ec6SMatthias Ringwald             break;
1142*3deb3ec6SMatthias Ringwald         case BNEP_CONTROL_TYPE_FILTER_MULTI_ADDR_RESPONSE:
1143*3deb3ec6SMatthias Ringwald             len = bnep_handle_multi_addr_response(channel, packet, size);
1144*3deb3ec6SMatthias Ringwald             break;
1145*3deb3ec6SMatthias Ringwald         default:
1146*3deb3ec6SMatthias Ringwald             log_error("BNEP_CONTROL: Invalid bnep control type: l2cap_cid: %d, cmd: %d", channel->l2cap_cid, bnep_control_type);
1147*3deb3ec6SMatthias Ringwald             len = 0;
1148*3deb3ec6SMatthias Ringwald             break;
1149*3deb3ec6SMatthias Ringwald     }
1150*3deb3ec6SMatthias Ringwald 
1151*3deb3ec6SMatthias Ringwald     if (len == 0) {
1152*3deb3ec6SMatthias Ringwald         /* In case the command could not be handled, send a
1153*3deb3ec6SMatthias Ringwald            COMMAND_NOT_UNDERSTOOD message.
1154*3deb3ec6SMatthias Ringwald            Set flag to process the request in the next statemachine loop
1155*3deb3ec6SMatthias Ringwald          */
1156*3deb3ec6SMatthias Ringwald         bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
1157*3deb3ec6SMatthias Ringwald     }
1158*3deb3ec6SMatthias Ringwald 
1159*3deb3ec6SMatthias Ringwald     return len;
1160*3deb3ec6SMatthias Ringwald }
1161*3deb3ec6SMatthias Ringwald 
1162*3deb3ec6SMatthias Ringwald /**
1163*3deb3ec6SMatthias Ringwald  * @return handled packet
1164*3deb3ec6SMatthias Ringwald  */
1165*3deb3ec6SMatthias Ringwald static int bnep_hci_event_handler(uint8_t *packet, uint16_t size)
1166*3deb3ec6SMatthias Ringwald {
1167*3deb3ec6SMatthias Ringwald     bd_addr_t event_addr;
1168*3deb3ec6SMatthias Ringwald     uint16_t  psm;
1169*3deb3ec6SMatthias Ringwald     uint16_t  l2cap_cid;
1170*3deb3ec6SMatthias Ringwald     hci_con_handle_t con_handle;
1171*3deb3ec6SMatthias Ringwald     bnep_channel_t  *channel = NULL;
1172*3deb3ec6SMatthias Ringwald     uint8_t   status;
1173*3deb3ec6SMatthias Ringwald 
1174*3deb3ec6SMatthias Ringwald     switch (packet[0]) {
1175*3deb3ec6SMatthias Ringwald 
1176*3deb3ec6SMatthias Ringwald         /* Accept an incoming L2CAP connection on PSM_BNEP */
1177*3deb3ec6SMatthias Ringwald         case L2CAP_EVENT_INCOMING_CONNECTION:
1178*3deb3ec6SMatthias Ringwald             /* L2CAP event data: event(8), len(8), address(48), handle (16),  psm (16), source cid(16) dest cid(16) */
1179*3deb3ec6SMatthias Ringwald             bt_flip_addr(event_addr, &packet[2]);
1180*3deb3ec6SMatthias Ringwald             con_handle = READ_BT_16(packet,  8);
1181*3deb3ec6SMatthias Ringwald             psm        = READ_BT_16(packet, 10);
1182*3deb3ec6SMatthias Ringwald             l2cap_cid  = READ_BT_16(packet, 12);
1183*3deb3ec6SMatthias Ringwald 
1184*3deb3ec6SMatthias Ringwald             if (psm != PSM_BNEP) break;
1185*3deb3ec6SMatthias Ringwald 
1186*3deb3ec6SMatthias Ringwald             channel = bnep_channel_for_addr(event_addr);
1187*3deb3ec6SMatthias Ringwald 
1188*3deb3ec6SMatthias Ringwald             if (channel) {
1189*3deb3ec6SMatthias Ringwald                 log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_BNEP => decline - channel already exists", l2cap_cid);
1190*3deb3ec6SMatthias Ringwald                 l2cap_decline_connection_internal(l2cap_cid,  0x04);    // no resources available
1191*3deb3ec6SMatthias Ringwald                 return 1;
1192*3deb3ec6SMatthias Ringwald             }
1193*3deb3ec6SMatthias Ringwald 
1194*3deb3ec6SMatthias Ringwald             /* Create a new BNEP channel instance (incoming) */
1195*3deb3ec6SMatthias Ringwald             channel = bnep_channel_create_for_addr(event_addr);
1196*3deb3ec6SMatthias Ringwald 
1197*3deb3ec6SMatthias Ringwald             if (!channel) {
1198*3deb3ec6SMatthias Ringwald                 log_error("INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_BNEP => decline - no memory left", l2cap_cid);
1199*3deb3ec6SMatthias Ringwald                 l2cap_decline_connection_internal(l2cap_cid,  0x04);    // no resources available
1200*3deb3ec6SMatthias Ringwald                 return 1;
1201*3deb3ec6SMatthias Ringwald             }
1202*3deb3ec6SMatthias Ringwald 
1203*3deb3ec6SMatthias Ringwald             /* Assign connection handle and l2cap cid */
1204*3deb3ec6SMatthias Ringwald             channel->con_handle = con_handle;
1205*3deb3ec6SMatthias Ringwald             channel->l2cap_cid = l2cap_cid;
1206*3deb3ec6SMatthias Ringwald 
1207*3deb3ec6SMatthias Ringwald             /* Set channel into accept state */
1208*3deb3ec6SMatthias Ringwald             channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST;
1209*3deb3ec6SMatthias Ringwald 
1210*3deb3ec6SMatthias Ringwald             /* Start connection timeout timer */
1211*3deb3ec6SMatthias Ringwald             bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
1212*3deb3ec6SMatthias Ringwald 
1213*3deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_INCOMING_CONNECTION (l2cap_cid 0x%02x) for PSM_BNEP => accept", l2cap_cid);
1214*3deb3ec6SMatthias Ringwald             l2cap_accept_connection_internal(l2cap_cid);
1215*3deb3ec6SMatthias Ringwald             return 1;
1216*3deb3ec6SMatthias Ringwald 
1217*3deb3ec6SMatthias Ringwald         /* Outgoing L2CAP connection has been opened -> store l2cap_cid, remote_addr */
1218*3deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_OPENED:
1219*3deb3ec6SMatthias Ringwald             /* Check if the l2cap channel has been opened for PSM_BNEP */
1220*3deb3ec6SMatthias Ringwald             if (READ_BT_16(packet, 11) != PSM_BNEP) {
1221*3deb3ec6SMatthias Ringwald                 break;
1222*3deb3ec6SMatthias Ringwald             }
1223*3deb3ec6SMatthias Ringwald 
1224*3deb3ec6SMatthias Ringwald             status = packet[2];
1225*3deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_OPENED for PSM_BNEP, status %u", status);
1226*3deb3ec6SMatthias Ringwald 
1227*3deb3ec6SMatthias Ringwald             /* Get the bnep channel fpr remote address */
1228*3deb3ec6SMatthias Ringwald             con_handle = READ_BT_16(packet, 9);
1229*3deb3ec6SMatthias Ringwald             l2cap_cid  = READ_BT_16(packet, 13);
1230*3deb3ec6SMatthias Ringwald             bt_flip_addr(event_addr, &packet[3]);
1231*3deb3ec6SMatthias Ringwald             channel = bnep_channel_for_addr(event_addr);
1232*3deb3ec6SMatthias Ringwald             if (!channel) {
1233*3deb3ec6SMatthias Ringwald                 log_error("L2CAP_EVENT_CHANNEL_OPENED but no BNEP channel prepared");
1234*3deb3ec6SMatthias Ringwald                 return 1;
1235*3deb3ec6SMatthias Ringwald             }
1236*3deb3ec6SMatthias Ringwald 
1237*3deb3ec6SMatthias Ringwald             /* On L2CAP open error discard everything */
1238*3deb3ec6SMatthias Ringwald             if (status) {
1239*3deb3ec6SMatthias Ringwald                 /* Emit bnep_open_channel_complete with status and free channel */
1240*3deb3ec6SMatthias Ringwald                 bnep_emit_open_channel_complete(channel, status);
1241*3deb3ec6SMatthias Ringwald 
1242*3deb3ec6SMatthias Ringwald                 /* Free BNEP channel mempory */
1243*3deb3ec6SMatthias Ringwald                 bnep_channel_free(channel);
1244*3deb3ec6SMatthias Ringwald                 return 1;
1245*3deb3ec6SMatthias Ringwald             }
1246*3deb3ec6SMatthias Ringwald 
1247*3deb3ec6SMatthias Ringwald             switch (channel->state){
1248*3deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_CLOSED:
1249*3deb3ec6SMatthias Ringwald                     log_info("L2CAP_EVENT_CHANNEL_OPENED: outgoing connection");
1250*3deb3ec6SMatthias Ringwald 
1251*3deb3ec6SMatthias Ringwald                     bnep_channel_start_timer(channel, BNEP_CONNECTION_TIMEOUT_MS);
1252*3deb3ec6SMatthias Ringwald 
1253*3deb3ec6SMatthias Ringwald                     /* Assign connection handle and l2cap cid */
1254*3deb3ec6SMatthias Ringwald                     channel->l2cap_cid  = l2cap_cid;
1255*3deb3ec6SMatthias Ringwald                     channel->con_handle = con_handle;
1256*3deb3ec6SMatthias Ringwald 
1257*3deb3ec6SMatthias Ringwald                     /* Initiate the connection request */
1258*3deb3ec6SMatthias Ringwald                     channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
1259*3deb3ec6SMatthias Ringwald                     bnep_channel_state_add(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
1260*3deb3ec6SMatthias Ringwald                     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(READ_BT_16(packet, 17));
1261*3deb3ec6SMatthias Ringwald                     bnep_run();
1262*3deb3ec6SMatthias Ringwald                     break;
1263*3deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
1264*3deb3ec6SMatthias Ringwald                     /* New information: channel mtu */
1265*3deb3ec6SMatthias Ringwald                     channel->max_frame_size = bnep_max_frame_size_for_l2cap_mtu(READ_BT_16(packet, 17));
1266*3deb3ec6SMatthias Ringwald                     break;
1267*3deb3ec6SMatthias Ringwald                 default:
1268*3deb3ec6SMatthias Ringwald                     log_error("L2CAP_EVENT_CHANNEL_OPENED: Invalid state: %d", channel->state);
1269*3deb3ec6SMatthias Ringwald                     break;
1270*3deb3ec6SMatthias Ringwald             }
1271*3deb3ec6SMatthias Ringwald             return 1;
1272*3deb3ec6SMatthias Ringwald 
1273*3deb3ec6SMatthias Ringwald         case DAEMON_EVENT_HCI_PACKET_SENT:
1274*3deb3ec6SMatthias Ringwald             bnep_run();
1275*3deb3ec6SMatthias Ringwald             break;
1276*3deb3ec6SMatthias Ringwald 
1277*3deb3ec6SMatthias Ringwald         case L2CAP_EVENT_CHANNEL_CLOSED:
1278*3deb3ec6SMatthias Ringwald             // data: event (8), len(8), channel (16)
1279*3deb3ec6SMatthias Ringwald             l2cap_cid   = READ_BT_16(packet, 2);
1280*3deb3ec6SMatthias Ringwald             channel = bnep_channel_for_l2cap_cid(l2cap_cid);
1281*3deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED cid 0x%0x, channel %p", l2cap_cid, channel);
1282*3deb3ec6SMatthias Ringwald 
1283*3deb3ec6SMatthias Ringwald             if (!channel) {
1284*3deb3ec6SMatthias Ringwald                 break;
1285*3deb3ec6SMatthias Ringwald             }
1286*3deb3ec6SMatthias Ringwald 
1287*3deb3ec6SMatthias Ringwald             log_info("L2CAP_EVENT_CHANNEL_CLOSED state %u", channel->state);
1288*3deb3ec6SMatthias Ringwald             switch (channel->state) {
1289*3deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST:
1290*3deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE:
1291*3deb3ec6SMatthias Ringwald                 case BNEP_CHANNEL_STATE_CONNECTED:
1292*3deb3ec6SMatthias Ringwald                     bnep_channel_finalize(channel);
1293*3deb3ec6SMatthias Ringwald                     return 1;
1294*3deb3ec6SMatthias Ringwald                 default:
1295*3deb3ec6SMatthias Ringwald                     break;
1296*3deb3ec6SMatthias Ringwald             }
1297*3deb3ec6SMatthias Ringwald             break;
1298*3deb3ec6SMatthias Ringwald         default:
1299*3deb3ec6SMatthias Ringwald             bnep_run();
1300*3deb3ec6SMatthias Ringwald             break;
1301*3deb3ec6SMatthias Ringwald     }
1302*3deb3ec6SMatthias Ringwald     return 0;
1303*3deb3ec6SMatthias Ringwald }
1304*3deb3ec6SMatthias Ringwald 
1305*3deb3ec6SMatthias Ringwald static int bnep_l2cap_packet_handler(uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
1306*3deb3ec6SMatthias Ringwald {
1307*3deb3ec6SMatthias Ringwald     int             rc = 0;
1308*3deb3ec6SMatthias Ringwald     uint8_t         bnep_type;
1309*3deb3ec6SMatthias Ringwald     uint8_t         bnep_header_has_ext;
1310*3deb3ec6SMatthias Ringwald     uint8_t         extension_type;
1311*3deb3ec6SMatthias Ringwald     uint16_t        pos = 0;
1312*3deb3ec6SMatthias Ringwald     bd_addr_t       addr_source;
1313*3deb3ec6SMatthias Ringwald     bd_addr_t       addr_dest;
1314*3deb3ec6SMatthias Ringwald     uint16_t        network_protocol_type = 0xffff;
1315*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel = NULL;
1316*3deb3ec6SMatthias Ringwald 
1317*3deb3ec6SMatthias Ringwald     /* Get the bnep channel for this package */
1318*3deb3ec6SMatthias Ringwald     channel = bnep_channel_for_l2cap_cid(l2cap_cid);
1319*3deb3ec6SMatthias Ringwald     if (!channel) {
1320*3deb3ec6SMatthias Ringwald         return rc;
1321*3deb3ec6SMatthias Ringwald     }
1322*3deb3ec6SMatthias Ringwald 
1323*3deb3ec6SMatthias Ringwald     /* Sort out short packages */
1324*3deb3ec6SMatthias Ringwald     if (size < 2) {
1325*3deb3ec6SMatthias Ringwald         return rc;
1326*3deb3ec6SMatthias Ringwald     }
1327*3deb3ec6SMatthias Ringwald 
1328*3deb3ec6SMatthias Ringwald     bnep_type = BNEP_TYPE(packet[pos]);
1329*3deb3ec6SMatthias Ringwald     bnep_header_has_ext = BNEP_HEADER_HAS_EXT(packet[pos]);
1330*3deb3ec6SMatthias Ringwald     pos ++;
1331*3deb3ec6SMatthias Ringwald 
1332*3deb3ec6SMatthias Ringwald     switch(bnep_type) {
1333*3deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_GENERAL_ETHERNET:
1334*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(addr_dest, &packet[pos]);
1335*3deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1336*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(addr_source, &packet[pos]);
1337*3deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1338*3deb3ec6SMatthias Ringwald             network_protocol_type = READ_NET_16(packet, pos);
1339*3deb3ec6SMatthias Ringwald             pos += 2;
1340*3deb3ec6SMatthias Ringwald             break;
1341*3deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET:
1342*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(addr_dest, channel->local_addr);
1343*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(addr_source, channel->remote_addr);
1344*3deb3ec6SMatthias Ringwald             network_protocol_type = READ_NET_16(packet, pos);
1345*3deb3ec6SMatthias Ringwald             pos += 2;
1346*3deb3ec6SMatthias Ringwald             break;
1347*3deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY:
1348*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(addr_dest, channel->local_addr);
1349*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(addr_source, &packet[pos]);
1350*3deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1351*3deb3ec6SMatthias Ringwald             network_protocol_type = READ_NET_16(packet, pos);
1352*3deb3ec6SMatthias Ringwald             pos += 2;
1353*3deb3ec6SMatthias Ringwald             break;
1354*3deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_COMPRESSED_ETHERNET_DEST_ONLY:
1355*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(addr_dest, &packet[pos]);
1356*3deb3ec6SMatthias Ringwald             pos += sizeof(bd_addr_t);
1357*3deb3ec6SMatthias Ringwald             BD_ADDR_COPY(addr_source, channel->remote_addr);
1358*3deb3ec6SMatthias Ringwald             network_protocol_type = READ_NET_16(packet, pos);
1359*3deb3ec6SMatthias Ringwald             pos += 2;
1360*3deb3ec6SMatthias Ringwald             break;
1361*3deb3ec6SMatthias Ringwald         case BNEP_PKT_TYPE_CONTROL:
1362*3deb3ec6SMatthias Ringwald             rc = bnep_handle_control_packet(channel, packet + pos, size - pos, 0);
1363*3deb3ec6SMatthias Ringwald             pos += rc;
1364*3deb3ec6SMatthias Ringwald             break;
1365*3deb3ec6SMatthias Ringwald         default:
1366*3deb3ec6SMatthias Ringwald             break;
1367*3deb3ec6SMatthias Ringwald     }
1368*3deb3ec6SMatthias Ringwald 
1369*3deb3ec6SMatthias Ringwald     if (bnep_header_has_ext) {
1370*3deb3ec6SMatthias Ringwald         do {
1371*3deb3ec6SMatthias Ringwald             uint8_t ext_len;
1372*3deb3ec6SMatthias Ringwald 
1373*3deb3ec6SMatthias Ringwald             /* Read extension type and check for further extensions */
1374*3deb3ec6SMatthias Ringwald             extension_type        = BNEP_TYPE(packet[pos]);
1375*3deb3ec6SMatthias Ringwald             bnep_header_has_ext   = BNEP_HEADER_HAS_EXT(packet[pos]);
1376*3deb3ec6SMatthias Ringwald             pos ++;
1377*3deb3ec6SMatthias Ringwald 
1378*3deb3ec6SMatthias Ringwald             /* Read extension header length */
1379*3deb3ec6SMatthias Ringwald             ext_len = packet[pos];
1380*3deb3ec6SMatthias Ringwald             pos ++;
1381*3deb3ec6SMatthias Ringwald 
1382*3deb3ec6SMatthias Ringwald             if (size - pos < ext_len) {
1383*3deb3ec6SMatthias Ringwald                 log_error("BNEP pkt handler: Invalid extension length! Packet ignored");
1384*3deb3ec6SMatthias Ringwald                 /* Invalid packet size! */
1385*3deb3ec6SMatthias Ringwald                 return 0;
1386*3deb3ec6SMatthias Ringwald             }
1387*3deb3ec6SMatthias Ringwald 
1388*3deb3ec6SMatthias Ringwald             switch (extension_type) {
1389*3deb3ec6SMatthias Ringwald                 case BNEP_EXT_HEADER_TYPE_EXTENSION_CONTROL:
1390*3deb3ec6SMatthias Ringwald                     if (ext_len != bnep_handle_control_packet(channel, packet + pos, ext_len, 1)) {
1391*3deb3ec6SMatthias Ringwald                         log_error("BNEP pkt handler: Ignore invalid control packet in extension header");
1392*3deb3ec6SMatthias Ringwald                     }
1393*3deb3ec6SMatthias Ringwald 
1394*3deb3ec6SMatthias Ringwald                     pos += ext_len;
1395*3deb3ec6SMatthias Ringwald                     break;
1396*3deb3ec6SMatthias Ringwald 
1397*3deb3ec6SMatthias Ringwald                 default:
1398*3deb3ec6SMatthias Ringwald                     /* Extension header type unknown. Unknown extension SHALL be
1399*3deb3ec6SMatthias Ringwald 			         * SHALL be forwarded in any way. But who shall handle these
1400*3deb3ec6SMatthias Ringwald                      * extension packets?
1401*3deb3ec6SMatthias Ringwald                      * For now: We ignore them and just drop them!
1402*3deb3ec6SMatthias Ringwald                      */
1403*3deb3ec6SMatthias Ringwald                     log_error("BNEP pkt handler: Unknown extension type ignored, data dropped!");
1404*3deb3ec6SMatthias Ringwald                     pos += ext_len;
1405*3deb3ec6SMatthias Ringwald                     break;
1406*3deb3ec6SMatthias Ringwald             }
1407*3deb3ec6SMatthias Ringwald 
1408*3deb3ec6SMatthias Ringwald         } while (bnep_header_has_ext);
1409*3deb3ec6SMatthias Ringwald     }
1410*3deb3ec6SMatthias Ringwald 
1411*3deb3ec6SMatthias Ringwald     if (bnep_type != BNEP_PKT_TYPE_CONTROL && network_protocol_type != 0xffff) {
1412*3deb3ec6SMatthias Ringwald         if (channel->state == BNEP_CHANNEL_STATE_CONNECTED) {
1413*3deb3ec6SMatthias Ringwald             rc = bnep_handle_ethernet_packet(channel, addr_dest, addr_source, network_protocol_type, packet + pos, size - pos);
1414*3deb3ec6SMatthias Ringwald         } else {
1415*3deb3ec6SMatthias Ringwald             rc = 0;
1416*3deb3ec6SMatthias Ringwald         }
1417*3deb3ec6SMatthias Ringwald     }
1418*3deb3ec6SMatthias Ringwald 
1419*3deb3ec6SMatthias Ringwald     return rc;
1420*3deb3ec6SMatthias Ringwald 
1421*3deb3ec6SMatthias Ringwald }
1422*3deb3ec6SMatthias Ringwald 
1423*3deb3ec6SMatthias Ringwald void bnep_packet_handler(uint8_t packet_type, uint16_t l2cap_cid, uint8_t *packet, uint16_t size)
1424*3deb3ec6SMatthias Ringwald {
1425*3deb3ec6SMatthias Ringwald     int handled = 0;
1426*3deb3ec6SMatthias Ringwald     switch (packet_type) {
1427*3deb3ec6SMatthias Ringwald         case HCI_EVENT_PACKET:
1428*3deb3ec6SMatthias Ringwald             handled = bnep_hci_event_handler(packet, size);
1429*3deb3ec6SMatthias Ringwald             break;
1430*3deb3ec6SMatthias Ringwald         case L2CAP_DATA_PACKET:
1431*3deb3ec6SMatthias Ringwald             handled = bnep_l2cap_packet_handler(l2cap_cid, packet, size);
1432*3deb3ec6SMatthias Ringwald             break;
1433*3deb3ec6SMatthias Ringwald         default:
1434*3deb3ec6SMatthias Ringwald             break;
1435*3deb3ec6SMatthias Ringwald     }
1436*3deb3ec6SMatthias Ringwald 
1437*3deb3ec6SMatthias Ringwald     if (handled) {
1438*3deb3ec6SMatthias Ringwald         bnep_run();
1439*3deb3ec6SMatthias Ringwald         return;
1440*3deb3ec6SMatthias Ringwald     }
1441*3deb3ec6SMatthias Ringwald 
1442*3deb3ec6SMatthias Ringwald     /* Forward non l2cap packages to application handler */
1443*3deb3ec6SMatthias Ringwald     if (packet_type != L2CAP_DATA_PACKET) {
1444*3deb3ec6SMatthias Ringwald         (*app_packet_handler)(NULL, packet_type, l2cap_cid, packet, size);
1445*3deb3ec6SMatthias Ringwald         return;
1446*3deb3ec6SMatthias Ringwald     }
1447*3deb3ec6SMatthias Ringwald 
1448*3deb3ec6SMatthias Ringwald     bnep_run();
1449*3deb3ec6SMatthias Ringwald }
1450*3deb3ec6SMatthias Ringwald 
1451*3deb3ec6SMatthias Ringwald static void bnep_channel_state_machine(bnep_channel_t* channel, bnep_channel_event_t *event)
1452*3deb3ec6SMatthias Ringwald {
1453*3deb3ec6SMatthias Ringwald     log_info("bnep_state_machine: state %u, state var: %02x, event %u", channel->state, channel->state_var, event->type);
1454*3deb3ec6SMatthias Ringwald 
1455*3deb3ec6SMatthias Ringwald     if (event->type == BNEP_CH_EVT_READY_TO_SEND) {
1456*3deb3ec6SMatthias Ringwald         /* Send outstanding packets. */
1457*3deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD) {
1458*3deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_NOT_UNDERSTOOD);
1459*3deb3ec6SMatthias Ringwald             bnep_send_command_not_understood(channel, channel->last_control_type);
1460*3deb3ec6SMatthias Ringwald             return;
1461*3deb3ec6SMatthias Ringwald         }
1462*3deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST) {
1463*3deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_REQUEST);
1464*3deb3ec6SMatthias Ringwald             channel->state = BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_RESPONSE;
1465*3deb3ec6SMatthias Ringwald             bnep_send_connection_request(channel, channel->uuid_source, channel->uuid_dest);
1466*3deb3ec6SMatthias Ringwald         }
1467*3deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE) {
1468*3deb3ec6SMatthias Ringwald             int emit_connected = 0;
1469*3deb3ec6SMatthias Ringwald             if ((channel->state == BNEP_CHANNEL_STATE_CLOSED) ||
1470*3deb3ec6SMatthias Ringwald                 (channel->state == BNEP_CHANNEL_STATE_WAIT_FOR_CONNECTION_REQUEST)) {
1471*3deb3ec6SMatthias Ringwald                 /* Set channel state to STATE_CONNECTED */
1472*3deb3ec6SMatthias Ringwald                 channel->state = BNEP_CHANNEL_STATE_CONNECTED;
1473*3deb3ec6SMatthias Ringwald                 /* Stop timeout timer! */
1474*3deb3ec6SMatthias Ringwald                 bnep_channel_stop_timer(channel);
1475*3deb3ec6SMatthias Ringwald                 emit_connected = 1;
1476*3deb3ec6SMatthias Ringwald             }
1477*3deb3ec6SMatthias Ringwald 
1478*3deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_CONNECTION_RESPONSE);
1479*3deb3ec6SMatthias Ringwald             bnep_send_connection_response(channel, channel->response_code);
1480*3deb3ec6SMatthias Ringwald             if (emit_connected){
1481*3deb3ec6SMatthias Ringwald                 bnep_emit_open_channel_complete(channel, 0);
1482*3deb3ec6SMatthias Ringwald             }
1483*3deb3ec6SMatthias Ringwald             return;
1484*3deb3ec6SMatthias Ringwald         }
1485*3deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET) {
1486*3deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_SET);
1487*3deb3ec6SMatthias Ringwald             if ((channel->net_filter_out_count > 0) && (channel->net_filter_out != NULL)) {
1488*3deb3ec6SMatthias Ringwald                 bnep_send_filter_net_type_set(channel, channel->net_filter_out, channel->net_filter_out_count);
1489*3deb3ec6SMatthias Ringwald                 channel->net_filter_out_count = 0;
1490*3deb3ec6SMatthias Ringwald                 channel->net_filter_out = NULL;
1491*3deb3ec6SMatthias Ringwald             }
1492*3deb3ec6SMatthias Ringwald             return;
1493*3deb3ec6SMatthias Ringwald         }
1494*3deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE) {
1495*3deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_NET_TYPE_RESPONSE);
1496*3deb3ec6SMatthias Ringwald             bnep_send_filter_net_type_response(channel, channel->response_code);
1497*3deb3ec6SMatthias Ringwald             return;
1498*3deb3ec6SMatthias Ringwald         }
1499*3deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET) {
1500*3deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_SET);
1501*3deb3ec6SMatthias Ringwald             if ((channel->multicast_filter_out_count > 0) && (channel->multicast_filter_out != NULL)) {
1502*3deb3ec6SMatthias Ringwald                 bnep_send_filter_multi_addr_set(channel, channel->multicast_filter_out, channel->multicast_filter_out_count);
1503*3deb3ec6SMatthias Ringwald                 channel->multicast_filter_out_count = 0;
1504*3deb3ec6SMatthias Ringwald                 channel->multicast_filter_out = NULL;
1505*3deb3ec6SMatthias Ringwald             }
1506*3deb3ec6SMatthias Ringwald             return;
1507*3deb3ec6SMatthias Ringwald         }
1508*3deb3ec6SMatthias Ringwald         if (channel->state_var & BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE) {
1509*3deb3ec6SMatthias Ringwald             bnep_channel_state_remove(channel, BNEP_CHANNEL_STATE_VAR_SND_FILTER_MULTI_ADDR_RESPONSE);
1510*3deb3ec6SMatthias Ringwald             bnep_send_filter_multi_addr_response(channel, channel->response_code);
1511*3deb3ec6SMatthias Ringwald             return;
1512*3deb3ec6SMatthias Ringwald         }
1513*3deb3ec6SMatthias Ringwald 
1514*3deb3ec6SMatthias Ringwald 
1515*3deb3ec6SMatthias Ringwald         /* If the event was not yet handled, notify the application layer */
1516*3deb3ec6SMatthias Ringwald         bnep_emit_ready_to_send(channel);
1517*3deb3ec6SMatthias Ringwald     }
1518*3deb3ec6SMatthias Ringwald }
1519*3deb3ec6SMatthias Ringwald 
1520*3deb3ec6SMatthias Ringwald 
1521*3deb3ec6SMatthias Ringwald /* Process oustanding signaling tasks */
1522*3deb3ec6SMatthias Ringwald static void bnep_run(void)
1523*3deb3ec6SMatthias Ringwald {
1524*3deb3ec6SMatthias Ringwald     linked_item_t *it;
1525*3deb3ec6SMatthias Ringwald     linked_item_t *next;
1526*3deb3ec6SMatthias Ringwald 
1527*3deb3ec6SMatthias Ringwald     for (it = (linked_item_t *) bnep_channels; it ; it = next){
1528*3deb3ec6SMatthias Ringwald 
1529*3deb3ec6SMatthias Ringwald         next = it->next;    // be prepared for removal of channel in state machine
1530*3deb3ec6SMatthias Ringwald 
1531*3deb3ec6SMatthias Ringwald         bnep_channel_t * channel = ((bnep_channel_t *) it);
1532*3deb3ec6SMatthias Ringwald 
1533*3deb3ec6SMatthias Ringwald         if (!l2cap_can_send_packet_now(channel->l2cap_cid)) {
1534*3deb3ec6SMatthias Ringwald             continue;
1535*3deb3ec6SMatthias Ringwald         }
1536*3deb3ec6SMatthias Ringwald 
1537*3deb3ec6SMatthias Ringwald         bnep_channel_event_t channel_event = { BNEP_CH_EVT_READY_TO_SEND };
1538*3deb3ec6SMatthias Ringwald         bnep_channel_state_machine(channel, &channel_event);
1539*3deb3ec6SMatthias Ringwald     }
1540*3deb3ec6SMatthias Ringwald }
1541*3deb3ec6SMatthias Ringwald 
1542*3deb3ec6SMatthias Ringwald /* BNEP BTStack API */
1543*3deb3ec6SMatthias Ringwald void bnep_init(void)
1544*3deb3ec6SMatthias Ringwald {
1545*3deb3ec6SMatthias Ringwald     bnep_security_level = LEVEL_0;
1546*3deb3ec6SMatthias Ringwald }
1547*3deb3ec6SMatthias Ringwald 
1548*3deb3ec6SMatthias Ringwald void bnep_set_required_security_level(gap_security_level_t security_level)
1549*3deb3ec6SMatthias Ringwald {
1550*3deb3ec6SMatthias Ringwald     bnep_security_level = security_level;
1551*3deb3ec6SMatthias Ringwald }
1552*3deb3ec6SMatthias Ringwald 
1553*3deb3ec6SMatthias Ringwald /* Register application packet handler */
1554*3deb3ec6SMatthias Ringwald void bnep_register_packet_handler(void (*handler)(void * connection, uint8_t packet_type,
1555*3deb3ec6SMatthias Ringwald                                                     uint16_t channel, uint8_t *packet, uint16_t size)){
1556*3deb3ec6SMatthias Ringwald 	app_packet_handler = handler;
1557*3deb3ec6SMatthias Ringwald }
1558*3deb3ec6SMatthias Ringwald 
1559*3deb3ec6SMatthias Ringwald int bnep_connect(void * connection, bd_addr_t addr, uint16_t l2cap_psm, uint16_t uuid_src, uint16_t uuid_dest)
1560*3deb3ec6SMatthias Ringwald {
1561*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
1562*3deb3ec6SMatthias Ringwald     log_info("BNEP_CONNECT addr %s", bd_addr_to_str(addr));
1563*3deb3ec6SMatthias Ringwald 
1564*3deb3ec6SMatthias Ringwald     channel = bnep_channel_create_for_addr(addr);
1565*3deb3ec6SMatthias Ringwald     if (channel == NULL) {
1566*3deb3ec6SMatthias Ringwald         return -1;
1567*3deb3ec6SMatthias Ringwald     }
1568*3deb3ec6SMatthias Ringwald 
1569*3deb3ec6SMatthias Ringwald     channel->uuid_source = uuid_src;
1570*3deb3ec6SMatthias Ringwald     channel->uuid_dest   = uuid_dest;
1571*3deb3ec6SMatthias Ringwald 
1572*3deb3ec6SMatthias Ringwald     l2cap_create_channel_internal(connection, bnep_packet_handler, addr, l2cap_psm, l2cap_max_mtu());
1573*3deb3ec6SMatthias Ringwald 
1574*3deb3ec6SMatthias Ringwald     return 0;
1575*3deb3ec6SMatthias Ringwald }
1576*3deb3ec6SMatthias Ringwald 
1577*3deb3ec6SMatthias Ringwald void bnep_disconnect(bd_addr_t addr)
1578*3deb3ec6SMatthias Ringwald {
1579*3deb3ec6SMatthias Ringwald     bnep_channel_t *channel;
1580*3deb3ec6SMatthias Ringwald     log_info("BNEP_DISCONNECT");
1581*3deb3ec6SMatthias Ringwald 
1582*3deb3ec6SMatthias Ringwald     channel = bnep_channel_for_addr(addr);
1583*3deb3ec6SMatthias Ringwald 
1584*3deb3ec6SMatthias Ringwald     bnep_channel_finalize(channel);
1585*3deb3ec6SMatthias Ringwald 
1586*3deb3ec6SMatthias Ringwald     bnep_run();
1587*3deb3ec6SMatthias Ringwald }
1588*3deb3ec6SMatthias Ringwald 
1589*3deb3ec6SMatthias Ringwald 
1590*3deb3ec6SMatthias Ringwald void bnep_register_service(void * connection, uint16_t service_uuid, uint16_t max_frame_size)
1591*3deb3ec6SMatthias Ringwald {
1592*3deb3ec6SMatthias Ringwald     log_info("BNEP_REGISTER_SERVICE mtu %d", max_frame_size);
1593*3deb3ec6SMatthias Ringwald 
1594*3deb3ec6SMatthias Ringwald     /* Check if we already registered a service */
1595*3deb3ec6SMatthias Ringwald     bnep_service_t * service = bnep_service_for_uuid(service_uuid);
1596*3deb3ec6SMatthias Ringwald     if (service) {
1597*3deb3ec6SMatthias Ringwald         bnep_emit_service_registered(connection, BNEP_SERVICE_ALREADY_REGISTERED, service_uuid);
1598*3deb3ec6SMatthias Ringwald         return;
1599*3deb3ec6SMatthias Ringwald     }
1600*3deb3ec6SMatthias Ringwald 
1601*3deb3ec6SMatthias Ringwald     /* Only alow one the three service types: PANU, NAP, GN */
1602*3deb3ec6SMatthias Ringwald     if ((service_uuid != SDP_PANU) &&
1603*3deb3ec6SMatthias Ringwald         (service_uuid != SDP_NAP) &&
1604*3deb3ec6SMatthias Ringwald         (service_uuid != SDP_GN)) {
1605*3deb3ec6SMatthias Ringwald         log_info("BNEP_REGISTER_SERVICE: Invalid service UUID: %04x", service_uuid);
1606*3deb3ec6SMatthias Ringwald         return;
1607*3deb3ec6SMatthias Ringwald     }
1608*3deb3ec6SMatthias Ringwald 
1609*3deb3ec6SMatthias Ringwald     /* Allocate service memory */
1610*3deb3ec6SMatthias Ringwald     service = (bnep_service_t*) btstack_memory_bnep_service_get();
1611*3deb3ec6SMatthias Ringwald     if (!service) {
1612*3deb3ec6SMatthias Ringwald         bnep_emit_service_registered(connection, BTSTACK_MEMORY_ALLOC_FAILED, service_uuid);
1613*3deb3ec6SMatthias Ringwald         return;
1614*3deb3ec6SMatthias Ringwald     }
1615*3deb3ec6SMatthias Ringwald     memset(service, 0, sizeof(bnep_service_t));
1616*3deb3ec6SMatthias Ringwald 
1617*3deb3ec6SMatthias Ringwald     /* register with l2cap if not registered before, max MTU */
1618*3deb3ec6SMatthias Ringwald     l2cap_register_service_internal(NULL, bnep_packet_handler, PSM_BNEP, 0xffff, bnep_security_level);
1619*3deb3ec6SMatthias Ringwald 
1620*3deb3ec6SMatthias Ringwald     /* Setup the service struct */
1621*3deb3ec6SMatthias Ringwald     service->connection     = connection;
1622*3deb3ec6SMatthias Ringwald     service->max_frame_size = max_frame_size;
1623*3deb3ec6SMatthias Ringwald     service->service_uuid    = service_uuid;
1624*3deb3ec6SMatthias Ringwald 
1625*3deb3ec6SMatthias Ringwald     /* Add to services list */
1626*3deb3ec6SMatthias Ringwald     linked_list_add(&bnep_services, (linked_item_t *) service);
1627*3deb3ec6SMatthias Ringwald 
1628*3deb3ec6SMatthias Ringwald     /* Inform the application layer */
1629*3deb3ec6SMatthias Ringwald     bnep_emit_service_registered(connection, 0, service_uuid);
1630*3deb3ec6SMatthias Ringwald }
1631*3deb3ec6SMatthias Ringwald 
1632*3deb3ec6SMatthias Ringwald void bnep_unregister_service(uint16_t service_uuid)
1633*3deb3ec6SMatthias Ringwald {
1634*3deb3ec6SMatthias Ringwald     log_info("BNEP_UNREGISTER_SERVICE #%04x", service_uuid);
1635*3deb3ec6SMatthias Ringwald 
1636*3deb3ec6SMatthias Ringwald     bnep_service_t *service = bnep_service_for_uuid(service_uuid);
1637*3deb3ec6SMatthias Ringwald     if (!service) {
1638*3deb3ec6SMatthias Ringwald         return;
1639*3deb3ec6SMatthias Ringwald     }
1640*3deb3ec6SMatthias Ringwald 
1641*3deb3ec6SMatthias Ringwald     linked_list_remove(&bnep_services, (linked_item_t *) service);
1642*3deb3ec6SMatthias Ringwald     btstack_memory_bnep_service_free(service);
1643*3deb3ec6SMatthias Ringwald     service = NULL;
1644*3deb3ec6SMatthias Ringwald 
1645*3deb3ec6SMatthias Ringwald     l2cap_unregister_service_internal(NULL, PSM_BNEP);
1646*3deb3ec6SMatthias Ringwald }
1647*3deb3ec6SMatthias Ringwald 
1648