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