2015-02-06 10:45:10 +00:00
/*
* Copyright ( C ) 2014 BlueKitchen GmbH
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. Neither the name of the copyright holders nor the names of
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
* 4. Any redistribution , use , or modification is done solely for
* personal benefit and not for any commercial purpose or for
* monetary gain .
*
* THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
* ` ` AS IS ' ' AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL MATTHIAS
* RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS
* OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY ,
* OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE .
*
* Please inquire about commercial licensing options at
* contact @ bluekitchen - gmbh . com
*
*/
2017-03-24 23:39:20 +01:00
# define __BTSTACK_FILE__ "panu_demo.c"
2014-10-20 10:06:23 +00:00
/*
* panu_demo . c
2015-02-06 10:45:10 +00:00
* Author : Ole Reinhardt < ole . reinhardt @ kernelconcepts . de >
2014-10-20 10:06:23 +00:00
*/
2015-04-24 23:08:52 +02:00
/* EXAMPLE_START(panu_demo): PANU Demo
*
2015-04-25 23:45:55 +02:00
* @ text This example implements both a PANU client and a server . In server mode , it
2015-04-26 12:59:22 +02:00
* sets up a BNEP server and registers a PANU SDP record and waits for incoming connections .
2015-04-25 23:45:55 +02:00
* In client mode , it connects to a remote device , does an SDP Query to identify the PANU
2015-04-26 12:59:22 +02:00
* service and initiates a BNEP connection .
2015-04-24 23:08:52 +02:00
*/
2016-01-21 15:41:16 +01:00
# include "btstack_config.h"
2014-10-20 10:06:23 +00:00
2014-12-21 21:59:27 +00:00
# include <arpa/inet.h>
# include <errno.h>
# include <fcntl.h>
# include <ifaddrs.h>
2014-10-20 10:06:23 +00:00
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2014-12-21 21:59:27 +00:00
# include <net/if_arp.h>
2015-01-02 01:13:44 +00:00
# ifdef __APPLE__
# include <net/if.h>
2014-12-21 21:59:27 +00:00
# include <net/if_types.h>
2015-01-02 01:13:44 +00:00
2014-12-21 21:59:27 +00:00
# include <netinet/if_ether.h>
# include <netinet/in.h>
2015-01-02 01:13:44 +00:00
# endif
2014-12-21 21:59:27 +00:00
# include <sys/ioctl.h>
# include <sys/param.h>
2014-10-27 11:50:12 +00:00
# include <sys/socket.h>
2014-12-21 21:59:27 +00:00
# include <sys/stat.h>
# include <sys/types.h>
2014-12-18 13:22:03 +00:00
# ifdef __linux
2014-10-27 11:50:12 +00:00
# include <linux/if.h>
# include <linux/if_tun.h>
2014-12-18 13:22:03 +00:00
# endif
2017-05-22 11:34:34 +02:00
# include "btstack.h"
2014-10-20 10:06:23 +00:00
2014-10-27 11:50:12 +00:00
static int record_id = - 1 ;
static uint16_t bnep_l2cap_psm = 0 ;
2014-12-04 09:40:43 +00:00
static uint32_t bnep_remote_uuid = 0 ;
2014-10-27 11:50:12 +00:00
static uint16_t bnep_version = 0 ;
2014-10-28 01:16:57 +00:00
static uint16_t bnep_cid = 0 ;
2014-10-20 10:06:23 +00:00
static uint8_t attribute_value [ 1000 ] ;
2014-11-18 21:37:23 +00:00
static const unsigned int attribute_value_buffer_size = sizeof ( attribute_value ) ;
2014-10-20 10:06:23 +00:00
//static bd_addr_t remote = {0x04,0x0C,0xCE,0xE4,0x85,0xD3};
2015-01-04 00:19:18 +00:00
// static bd_addr_t remote = {0xE0,0x06,0xE6,0xBB,0x95,0x79}; // Ole Thinkpad
2014-12-21 21:59:27 +00:00
static bd_addr_t remote = { 0x84 , 0x38 , 0x35 , 0x65 , 0xD1 , 0x15 } ; // MacBook 2013
2014-10-20 10:06:23 +00:00
2014-10-27 11:50:12 +00:00
static int tap_fd = - 1 ;
static uint8_t network_buffer [ BNEP_MTU_MIN ] ;
static size_t network_buffer_len = 0 ;
2014-12-21 21:59:27 +00:00
# ifdef __APPLE__
// tuntaposx provides fixed set of tapX devices
static const char * tap_dev = " /dev/tap0 " ;
static char tap_dev_name [ 16 ] = " tap0 " ;
# endif
# ifdef __linux
// Linux uses single control device to bring up tunX or tapX interface
static const char * tap_dev = " /dev/net/tun " ;
2015-01-04 00:19:18 +00:00
static char tap_dev_name [ 16 ] = " bnep%d " ;
2014-12-21 21:59:27 +00:00
# endif
2016-01-20 16:00:45 +01:00
static btstack_data_source_t tap_dev_ds ;
2016-02-03 21:55:36 +01:00
static btstack_packet_callback_registration_t hci_event_callback_registration ;
2014-12-18 13:22:03 +00:00
2015-04-27 00:02:07 +02:00
/* @section Main application configuration
*
* @ text In the application configuration , L2CAP and BNEP are initialized and a BNEP service , for server mode ,
* is registered , before the Bluetooth stack gets started , as shown in Listing PanuSetup .
*/
/* LISTING_START(PanuSetup): Panu setup */
2015-11-13 21:57:19 +01:00
static void packet_handler ( uint8_t packet_type , uint16_t channel , uint8_t * packet , uint16_t size ) ;
2016-04-01 11:41:58 +02:00
static void handle_sdp_client_query_result ( uint8_t packet_type , uint16_t channel , uint8_t * packet , uint16_t size ) ;
2015-04-27 00:02:07 +02:00
2015-05-13 10:30:46 +02:00
static void panu_setup ( void ) {
2016-02-03 21:55:36 +01:00
// register for HCI events
2016-02-04 17:45:02 +01:00
hci_event_callback_registration . callback = & packet_handler ;
2016-02-03 21:55:36 +01:00
hci_add_event_handler ( & hci_event_callback_registration ) ;
2015-04-27 00:02:07 +02:00
// Initialize L2CAP
l2cap_init ( ) ;
// Initialise BNEP
bnep_init ( ) ;
// Minimum L2CAP MTU for bnep is 1691 bytes
2017-03-26 22:19:18 +02:00
bnep_register_service ( packet_handler , BLUETOOTH_SERVICE_CLASS_PANU , 1691 ) ;
2015-04-27 00:02:07 +02:00
}
/* LISTING_END */
2015-04-24 23:08:52 +02:00
/* @section TUN / TAP interface routines
2015-04-25 23:45:55 +02:00
*
2015-04-26 12:59:22 +02:00
* @ text This example requires a TUN / TAP interface to connect the Bluetooth network interface
2015-04-25 23:45:55 +02:00
* with the native system . It has been tested on Linux and OS X , but should work on any
* system that provides TUN / TAP with minor modifications .
2015-04-24 23:08:52 +02:00
*
2015-04-27 00:02:07 +02:00
* On Linux , TUN / TAP is available by default . On OS X , tuntaposx from
2015-04-25 23:45:55 +02:00
* http : //tuntaposx.sourceforge.net needs to be installed.
*
2015-06-05 11:57:37 +02:00
* The * tap_alloc * function sets up a virtual network interface with the given Bluetooth Address .
2015-04-25 23:45:55 +02:00
* It is rather low - level as it sets up and configures a network interface .
2015-04-24 23:08:52 +02:00
*/
2014-10-27 11:50:12 +00:00
2015-12-16 14:29:23 +01:00
static int tap_alloc ( char * dev , bd_addr_t bd_addr )
2014-10-27 11:50:12 +00:00
{
struct ifreq ifr ;
int fd_dev ;
int fd_socket ;
2014-12-21 21:59:27 +00:00
if ( ( fd_dev = open ( tap_dev , O_RDWR ) ) < 0 ) {
fprintf ( stderr , " TAP: Error opening %s: %s \n " , tap_dev , strerror ( errno ) ) ;
2014-10-27 11:50:12 +00:00
return - 1 ;
}
2014-12-21 21:59:27 +00:00
# ifdef __linux
2014-10-27 11:50:12 +00:00
memset ( & ifr , 0 , sizeof ( ifr ) ) ;
2015-04-24 23:08:52 +02:00
2014-10-27 11:50:12 +00:00
ifr . ifr_flags = IFF_TAP | IFF_NO_PI ;
if ( * dev ) {
strncpy ( ifr . ifr_name , dev , IFNAMSIZ ) ;
}
2014-12-21 21:59:27 +00:00
int err ;
2014-10-27 11:50:12 +00:00
if ( ( err = ioctl ( fd_dev , TUNSETIFF , ( void * ) & ifr ) ) < 0 ) {
fprintf ( stderr , " TAP: Error setting device name: %s \n " , strerror ( errno ) ) ;
close ( fd_dev ) ;
return - 1 ;
}
strcpy ( dev , ifr . ifr_name ) ;
2014-12-21 21:59:27 +00:00
# endif
# ifdef __APPLE__
dev = tap_dev_name ;
# endif
2014-10-27 11:50:12 +00:00
fd_socket = socket ( PF_INET , SOCK_DGRAM , IPPROTO_IP ) ;
if ( fd_socket < 0 ) {
close ( fd_dev ) ;
fprintf ( stderr , " TAP: Error opening netlink socket: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
2015-04-24 23:08:52 +02:00
// Configure the MAC address of the newly created bnep(x)
// device to the local bd_address
2014-10-27 11:50:12 +00:00
memset ( & ifr , 0 , sizeof ( struct ifreq ) ) ;
strcpy ( ifr . ifr_name , dev ) ;
2014-12-21 21:59:27 +00:00
# ifdef __linux
2014-10-27 11:50:12 +00:00
ifr . ifr_hwaddr . sa_family = ARPHRD_ETHER ;
2014-12-21 21:59:27 +00:00
memcpy ( ifr . ifr_hwaddr . sa_data , bd_addr , sizeof ( bd_addr_t ) ) ;
2014-10-27 11:50:12 +00:00
if ( ioctl ( fd_socket , SIOCSIFHWADDR , & ifr ) = = - 1 ) {
close ( fd_dev ) ;
close ( fd_socket ) ;
fprintf ( stderr , " TAP: Error setting hw addr: %s \n " , strerror ( errno ) ) ;
exit ( 1 ) ;
return - 1 ;
}
2014-12-21 21:59:27 +00:00
# endif
# ifdef __APPLE__
ifr . ifr_addr . sa_len = ETHER_ADDR_LEN ;
ifr . ifr_addr . sa_family = AF_LINK ;
( void ) memcpy ( ifr . ifr_addr . sa_data , bd_addr , ETHER_ADDR_LEN ) ;
if ( ioctl ( fd_socket , SIOCSIFLLADDR , & ifr ) = = - 1 ) {
close ( fd_dev ) ;
close ( fd_socket ) ;
fprintf ( stderr , " TAP: Error setting hw addr: %s \n " , strerror ( errno ) ) ;
exit ( 1 ) ;
return - 1 ;
}
# endif
2014-10-27 11:50:12 +00:00
2015-04-24 23:08:52 +02:00
// Bring the interface up
2014-10-27 11:50:12 +00:00
if ( ioctl ( fd_socket , SIOCGIFFLAGS , & ifr ) = = - 1 ) {
close ( fd_dev ) ;
close ( fd_socket ) ;
fprintf ( stderr , " TAP: Error reading interface flags: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
if ( ( ifr . ifr_flags & IFF_UP ) = = 0 ) {
ifr . ifr_flags | = IFF_UP ;
if ( ioctl ( fd_socket , SIOCSIFFLAGS , & ifr ) = = - 1 ) {
close ( fd_dev ) ;
close ( fd_socket ) ;
fprintf ( stderr , " TAP: Error set IFF_UP: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
}
close ( fd_socket ) ;
return fd_dev ;
}
2015-04-25 23:45:55 +02:00
/*
2015-04-27 00:02:07 +02:00
* @ text Listing processTapData shows how a packet is received from the TAP network interface
2015-04-26 12:59:22 +02:00
* and forwarded over the BNEP connection .
2015-04-25 23:45:55 +02:00
*
* After successfully reading a network packet , the call to
2015-06-05 11:57:37 +02:00
* the * bnep_can_send_packet_now * function checks , if BTstack can forward
2015-04-25 23:45:55 +02:00
* a network packet now . If that ' s not possible , the received data stays
* in the network buffer and the data source elements is removed from the
2015-06-05 11:57:37 +02:00
* run loop . The * process_tap_dev_data * function will not be called until
2015-04-26 12:59:22 +02:00
* the data source is registered again . This provides a basic flow control .
2015-04-25 23:45:55 +02:00
*/
/* LISTING_START(processTapData): Process incoming network packets */
2016-04-01 11:41:58 +02:00
static void process_tap_dev_data ( btstack_data_source_t * ds , btstack_data_source_callback_type_t callback_type )
2014-10-27 11:50:12 +00:00
{
2017-01-07 22:11:48 +01:00
UNUSED ( ds ) ;
UNUSED ( callback_type ) ;
2014-10-27 11:50:12 +00:00
ssize_t len ;
len = read ( ds - > fd , network_buffer , sizeof ( network_buffer ) ) ;
2015-04-25 23:45:55 +02:00
if ( len < = 0 ) {
2014-10-27 11:50:12 +00:00
fprintf ( stderr , " TAP: Error while reading: %s \n " , strerror ( errno ) ) ;
2016-04-01 11:41:58 +02:00
return ;
2014-10-27 11:50:12 +00:00
}
2014-10-28 01:16:57 +00:00
2015-04-25 23:45:55 +02:00
network_buffer_len = len ;
2014-10-28 01:16:57 +00:00
if ( bnep_can_send_packet_now ( bnep_cid ) ) {
bnep_send ( bnep_cid , network_buffer , network_buffer_len ) ;
network_buffer_len = 0 ;
} else {
2015-04-24 23:08:52 +02:00
// park the current network packet
2016-01-20 15:58:46 +01:00
btstack_run_loop_remove_data_source ( & tap_dev_ds ) ;
2014-10-28 01:16:57 +00:00
}
2016-04-01 11:41:58 +02:00
return ;
2014-10-27 11:50:12 +00:00
}
2015-04-25 23:45:55 +02:00
/* LISTING_END */
2014-10-27 11:50:12 +00:00
2015-04-24 23:08:52 +02:00
// PANU client routines
2015-12-16 14:29:23 +01:00
static char * get_string_from_data_element ( uint8_t * element ) {
2014-10-20 10:06:23 +00:00
de_size_t de_size = de_get_size_type ( element ) ;
int pos = de_get_header_size ( element ) ;
int len = 0 ;
switch ( de_size ) {
case DE_SIZE_VAR_8 :
len = element [ 1 ] ;
break ;
case DE_SIZE_VAR_16 :
2016-01-31 00:07:32 +01:00
len = big_endian_read_16 ( element , 1 ) ;
2014-10-20 10:06:23 +00:00
break ;
default :
break ;
}
char * str = ( char * ) malloc ( len + 1 ) ;
memcpy ( str , & element [ pos ] , len ) ;
str [ len ] = ' \0 ' ;
return str ;
}
2015-04-24 23:16:02 +02:00
/* @section SDP parser callback
2015-04-25 23:45:55 +02:00
*
2015-06-24 16:47:05 +02:00
* @ text The SDP parsers retrieves the BNEP PAN UUID as explained in
2015-06-24 17:21:05 +02:00
* Section [ on SDP BNEP Query example ] ( # sec : sdpbnepqueryExample } .
2015-04-24 23:16:02 +02:00
*/
2016-04-01 11:41:58 +02:00
static void handle_sdp_client_query_result ( uint8_t packet_type , uint16_t channel , uint8_t * packet , uint16_t size ) {
2016-01-29 21:31:07 +01:00
2017-01-07 22:11:48 +01:00
UNUSED ( packet_type ) ;
UNUSED ( channel ) ;
UNUSED ( size ) ;
2014-10-27 11:50:12 +00:00
des_iterator_t des_list_it ;
des_iterator_t prot_it ;
2014-11-18 21:37:29 +00:00
char * str ;
2014-10-20 10:06:23 +00:00
2016-02-19 14:52:36 +01:00
switch ( hci_event_packet_get_type ( packet ) ) {
2016-01-30 23:58:36 +01:00
case SDP_EVENT_QUERY_ATTRIBUTE_VALUE :
2015-04-24 23:08:52 +02:00
// Handle new SDP record
2016-02-03 16:10:30 +01:00
if ( sdp_event_query_attribute_byte_get_record_id ( packet ) ! = record_id ) {
record_id = sdp_event_query_attribute_byte_get_record_id ( packet ) ;
2014-10-20 10:06:23 +00:00
printf ( " SDP Record: Nr: %d \n " , record_id ) ;
}
2016-02-03 16:10:30 +01:00
if ( sdp_event_query_attribute_byte_get_attribute_length ( packet ) < = attribute_value_buffer_size ) {
attribute_value [ sdp_event_query_attribute_byte_get_data_offset ( packet ) ] = sdp_event_query_attribute_byte_get_data ( packet ) ;
2014-10-20 10:06:23 +00:00
2016-02-03 16:10:30 +01:00
if ( ( uint16_t ) ( sdp_event_query_attribute_byte_get_data_offset ( packet ) + 1 ) = = sdp_event_query_attribute_byte_get_attribute_length ( packet ) ) {
2014-10-20 10:06:23 +00:00
2016-02-03 16:10:30 +01:00
switch ( sdp_event_query_attribute_byte_get_attribute_id ( packet ) ) {
2017-03-26 22:19:18 +02:00
case BLUETOOTH_ATTRIBUTE_SERVICE_CLASS_ID_LIST :
2014-10-27 11:50:12 +00:00
if ( de_get_element_type ( attribute_value ) ! = DE_DES ) break ;
for ( des_iterator_init ( & des_list_it , attribute_value ) ; des_iterator_has_more ( & des_list_it ) ; des_iterator_next ( & des_list_it ) ) {
uint8_t * element = des_iterator_get_element ( & des_list_it ) ;
if ( de_get_element_type ( element ) ! = DE_UUID ) continue ;
2014-12-04 09:40:43 +00:00
uint32_t uuid = de_get_uuid32 ( element ) ;
2014-10-27 11:50:12 +00:00
switch ( uuid ) {
2017-03-26 22:19:18 +02:00
case BLUETOOTH_SERVICE_CLASS_PANU :
case BLUETOOTH_SERVICE_CLASS_NAP :
case BLUETOOTH_SERVICE_CLASS_GN :
2016-02-03 16:10:30 +01:00
printf ( " SDP Attribute 0x%04x: BNEP PAN protocol UUID: %04x \n " , sdp_event_query_attribute_byte_get_attribute_id ( packet ) , uuid ) ;
2014-10-27 11:50:12 +00:00
bnep_remote_uuid = uuid ;
break ;
default :
break ;
}
}
break ;
2014-10-20 10:06:23 +00:00
case 0x0100 :
case 0x0101 :
2014-11-18 21:37:29 +00:00
str = get_string_from_data_element ( attribute_value ) ;
2016-02-03 16:10:30 +01:00
printf ( " SDP Attribute: 0x%04x: %s \n " , sdp_event_query_attribute_byte_get_attribute_id ( packet ) , str ) ;
2014-11-18 21:37:29 +00:00
free ( str ) ;
2014-10-20 10:06:23 +00:00
break ;
2017-03-26 22:19:18 +02:00
case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST : {
2016-02-03 16:10:30 +01:00
printf ( " SDP Attribute: 0x%04x \n " , sdp_event_query_attribute_byte_get_attribute_id ( packet ) ) ;
2014-10-20 10:06:23 +00:00
for ( des_iterator_init ( & des_list_it , attribute_value ) ; des_iterator_has_more ( & des_list_it ) ; des_iterator_next ( & des_list_it ) ) {
uint8_t * des_element ;
uint8_t * element ;
2014-12-04 09:40:43 +00:00
uint32_t uuid ;
2014-10-20 10:06:23 +00:00
if ( des_iterator_get_type ( & des_list_it ) ! = DE_DES ) continue ;
des_element = des_iterator_get_element ( & des_list_it ) ;
des_iterator_init ( & prot_it , des_element ) ;
element = des_iterator_get_element ( & prot_it ) ;
if ( de_get_element_type ( element ) ! = DE_UUID ) continue ;
2014-12-04 09:40:43 +00:00
uuid = de_get_uuid32 ( element ) ;
2014-10-20 10:06:23 +00:00
switch ( uuid ) {
2017-03-26 22:19:18 +02:00
case BLUETOOTH_PROTOCOL_L2CAP :
2014-10-20 10:06:23 +00:00
if ( ! des_iterator_has_more ( & prot_it ) ) continue ;
des_iterator_next ( & prot_it ) ;
2014-10-27 11:50:12 +00:00
de_element_get_uint16 ( des_iterator_get_element ( & prot_it ) , & bnep_l2cap_psm ) ;
2014-10-20 10:06:23 +00:00
break ;
2017-03-26 22:19:18 +02:00
case BLUETOOTH_PROTOCOL_BNEP :
2014-10-20 10:06:23 +00:00
if ( ! des_iterator_has_more ( & prot_it ) ) continue ;
des_iterator_next ( & prot_it ) ;
de_element_get_uint16 ( des_iterator_get_element ( & prot_it ) , & bnep_version ) ;
break ;
default :
break ;
}
}
2014-10-27 11:50:12 +00:00
printf ( " l2cap_psm 0x%04x, bnep_version 0x%04x \n " , bnep_l2cap_psm , bnep_version ) ;
2014-10-28 01:16:57 +00:00
2014-10-20 10:06:23 +00:00
/* Create BNEP connection */
2017-03-25 22:51:28 +01:00
bnep_connect ( packet_handler , remote , bnep_l2cap_psm , BLUETOOTH_SERVICE_CLASS_PANU , bnep_remote_uuid ) ;
2014-10-20 10:06:23 +00:00
}
break ;
default :
break ;
}
}
} else {
2016-02-03 16:10:30 +01:00
fprintf ( stderr , " SDP attribute value buffer size exceeded: available %d, required %d \n " , attribute_value_buffer_size , sdp_event_query_attribute_byte_get_attribute_length ( packet ) ) ;
2014-10-20 10:06:23 +00:00
}
break ;
2016-01-30 23:58:36 +01:00
case SDP_EVENT_QUERY_COMPLETE :
2016-02-03 16:10:30 +01:00
fprintf ( stderr , " General query done with status %d. \n " , sdp_event_query_complete_get_status ( packet ) ) ;
2014-10-20 10:06:23 +00:00
break ;
}
}
2015-04-25 23:45:55 +02:00
/*
* @ section Packet Handler
*
* @ text The packet handler responds to various HCI Events .
*/
2015-04-26 11:25:41 +02:00
/* LISTING_START(packetHandler): Packet Handler */
2015-11-13 21:57:19 +01:00
static void packet_handler ( uint8_t packet_type , uint16_t channel , uint8_t * packet , uint16_t size )
2014-10-20 10:06:23 +00:00
{
2015-04-25 23:45:55 +02:00
/* LISTING_PAUSE */
2017-01-07 22:11:48 +01:00
UNUSED ( channel ) ;
2014-10-27 11:50:12 +00:00
int rc ;
uint8_t event ;
2014-10-20 10:06:23 +00:00
bd_addr_t event_addr ;
2015-03-24 08:44:48 +00:00
bd_addr_t local_addr ;
2014-10-20 10:06:23 +00:00
uint16_t uuid_source ;
uint16_t uuid_dest ;
uint16_t mtu ;
2014-10-27 11:50:12 +00:00
2015-04-25 23:45:55 +02:00
/* LISTING_RESUME */
2014-10-20 10:06:23 +00:00
switch ( packet_type ) {
case HCI_EVENT_PACKET :
2016-02-19 14:52:36 +01:00
event = hci_event_packet_get_type ( packet ) ;
2014-10-27 11:50:12 +00:00
switch ( event ) {
2015-04-26 12:59:22 +02:00
/* @text When BTSTACK_EVENT_STATE with state HCI_STATE_WORKING
2015-04-25 23:45:55 +02:00
* is received and the example is started in client mode , the remote SDP BNEP query is started .
*/
2014-10-20 10:06:23 +00:00
case BTSTACK_EVENT_STATE :
2016-04-01 12:27:13 +02:00
if ( btstack_event_state_get_state ( packet ) = = HCI_STATE_WORKING ) {
2014-10-20 10:06:23 +00:00
printf ( " Start SDP BNEP query. \n " ) ;
2017-03-26 22:19:18 +02:00
sdp_client_query_uuid16 ( & handle_sdp_client_query_result , remote , BLUETOOTH_PROTOCOL_BNEP ) ;
2014-10-20 10:06:23 +00:00
}
break ;
2015-04-25 23:45:55 +02:00
/* LISTING_PAUSE */
2014-10-20 10:06:23 +00:00
case HCI_EVENT_PIN_CODE_REQUEST :
// inform about pin code request
printf ( " Pin code request - using '0000' \n " ) ;
2016-04-01 14:04:14 +02:00
hci_event_pin_code_request_get_bd_addr ( packet , event_addr ) ;
2017-05-22 11:34:34 +02:00
gap_pin_code_response ( event_addr , " 0000 " ) ;
2014-10-20 10:06:23 +00:00
break ;
case HCI_EVENT_USER_CONFIRMATION_REQUEST :
// inform about user confirmation request
2016-01-31 00:07:32 +01:00
printf ( " SSP User Confirmation Request with numeric value '%06u' \n " , little_endian_read_32 ( packet , 8 ) ) ;
2014-10-20 10:06:23 +00:00
printf ( " SSP User Confirmation Auto accept \n " ) ;
break ;
2015-04-25 23:45:55 +02:00
/* LISTING_RESUME */
2015-04-26 11:25:41 +02:00
2016-04-01 11:41:58 +02:00
/* @text BNEP_EVENT_CHANNEL_OPENED is received after a BNEP connection was established or
2015-12-16 14:29:23 +01:00
* or when the connection fails . The status field returns the error code .
*
2015-04-27 00:02:07 +02:00
* The TAP network interface is then configured . A data source is set up and registered with the
2015-04-25 23:45:55 +02:00
* run loop to receive Ethernet packets from the TAP interface .
*
* The event contains both the source and destination UUIDs , as well as the MTU for this connection and
2015-04-27 00:02:07 +02:00
* the BNEP Channel ID , which is used for sending Ethernet packets over BNEP .
2015-12-16 14:29:23 +01:00
*/
2016-04-01 11:41:58 +02:00
case BNEP_EVENT_CHANNEL_OPENED :
2016-04-01 14:49:31 +02:00
if ( bnep_event_channel_opened_get_status ( packet ) ) {
printf ( " BNEP channel open failed, status %02x \n " , bnep_event_channel_opened_get_status ( packet ) ) ;
2014-10-20 10:06:23 +00:00
} else {
2016-04-01 14:49:31 +02:00
bnep_cid = bnep_event_channel_opened_get_bnep_cid ( packet ) ;
uuid_source = bnep_event_channel_opened_get_source_uuid ( packet ) ;
uuid_dest = bnep_event_channel_opened_get_destination_uuid ( packet ) ;
mtu = bnep_event_channel_opened_get_mtu ( packet ) ;
2014-10-27 11:50:12 +00:00
//bt_flip_addr(event_addr, &packet[9]);
2016-04-01 11:41:58 +02:00
memcpy ( & event_addr , & packet [ 11 ] , sizeof ( bd_addr_t ) ) ;
2014-10-27 11:50:12 +00:00
printf ( " BNEP connection open succeeded to %s source UUID 0x%04x dest UUID: 0x%04x, max frame size %u \n " , bd_addr_to_str ( event_addr ) , uuid_source , uuid_dest , mtu ) ;
/* Create the tap interface */
2016-02-18 17:12:57 +01:00
gap_local_bd_addr ( local_addr ) ;
2015-12-16 14:29:23 +01:00
tap_fd = tap_alloc ( tap_dev_name , local_addr ) ;
2014-10-27 11:50:12 +00:00
if ( tap_fd < 0 ) {
printf ( " Creating BNEP tap device failed: %s \n " , strerror ( errno ) ) ;
} else {
2014-10-28 01:16:57 +00:00
printf ( " BNEP device \" %s \" allocated. \n " , tap_dev_name ) ;
2014-10-27 11:50:12 +00:00
/* Create and register a new runloop data source */
2016-03-24 21:56:47 +01:00
btstack_run_loop_set_data_source_fd ( & tap_dev_ds , tap_fd ) ;
2016-04-01 11:41:58 +02:00
btstack_run_loop_set_data_source_handler ( & tap_dev_ds , & process_tap_dev_data ) ;
2016-01-20 15:58:46 +01:00
btstack_run_loop_add_data_source ( & tap_dev_ds ) ;
2014-10-27 11:50:12 +00:00
}
2014-10-20 10:06:23 +00:00
}
break ;
2015-04-25 23:45:55 +02:00
2015-04-26 12:59:22 +02:00
/* @text If there is a timeout during the connection setup, BNEP_EVENT_CHANNEL_TIMEOUT will be received
2015-04-27 00:02:07 +02:00
* and the BNEP connection will be closed
2015-04-25 23:45:55 +02:00
*/
2014-11-13 00:28:01 +00:00
case BNEP_EVENT_CHANNEL_TIMEOUT :
printf ( " BNEP channel timeout! Channel will be closed \n " ) ;
break ;
2015-04-25 23:45:55 +02:00
2015-04-27 00:02:07 +02:00
/* @text BNEP_EVENT_CHANNEL_CLOSED is received when the connection gets closed.
2015-04-25 23:45:55 +02:00
*/
2014-10-20 10:06:23 +00:00
case BNEP_EVENT_CHANNEL_CLOSED :
printf ( " BNEP channel closed \n " ) ;
2016-01-20 15:58:46 +01:00
btstack_run_loop_remove_data_source ( & tap_dev_ds ) ;
2014-10-27 11:50:12 +00:00
if ( tap_fd > 0 ) {
close ( tap_fd ) ;
tap_fd = - 1 ;
}
2014-10-20 10:06:23 +00:00
break ;
2016-03-31 15:18:39 +02:00
/* @text BNEP_EVENT_CAN_SEND_NOW indicates that a new packet can be send. This triggers the retry of a
2015-04-25 23:45:55 +02:00
* parked network packet . If this succeeds , the data source element is added to the run loop again .
*/
2016-03-31 15:18:39 +02:00
case BNEP_EVENT_CAN_SEND_NOW :
2015-04-24 23:08:52 +02:00
// Check for parked network packets and send it out now
2014-10-28 01:16:57 +00:00
if ( network_buffer_len > 0 ) {
bnep_send ( bnep_cid , network_buffer , network_buffer_len ) ;
network_buffer_len = 0 ;
2015-04-24 23:08:52 +02:00
// Re-add the tap device data source
2016-01-20 15:58:46 +01:00
btstack_run_loop_add_data_source ( & tap_dev_ds ) ;
2014-10-28 01:16:57 +00:00
}
break ;
2014-10-20 10:06:23 +00:00
default :
break ;
}
2014-10-27 11:50:12 +00:00
break ;
2015-04-25 23:45:55 +02:00
2015-04-26 12:59:22 +02:00
/* @text Ethernet packets from the remote device are received in the packet handler with type BNEP_DATA_PACKET.
2015-04-25 23:45:55 +02:00
* It is forwarded to the TAP interface .
*/
2014-10-27 11:50:12 +00:00
case BNEP_DATA_PACKET :
2015-04-24 23:08:52 +02:00
// Write out the ethernet frame to the tap device
2014-10-27 11:50:12 +00:00
if ( tap_fd > 0 ) {
rc = write ( tap_fd , packet , size ) ;
if ( rc < 0 ) {
fprintf ( stderr , " TAP: Could not write to TAP device: %s \n " , strerror ( errno ) ) ;
} else
if ( rc ! = size ) {
fprintf ( stderr , " TAP: Package written only partially %d of %d bytes \n " , rc , size ) ;
}
}
break ;
2014-10-20 10:06:23 +00:00
default :
break ;
}
}
2015-04-26 11:25:41 +02:00
/* LISTING_END */
2014-10-20 10:06:23 +00:00
2015-04-27 00:02:07 +02:00
2014-11-14 20:42:29 +00:00
int btstack_main ( int argc , const char * argv [ ] ) ;
int btstack_main ( int argc , const char * argv [ ] ) {
2014-10-20 10:06:23 +00:00
2017-05-22 22:04:20 +02:00
( void ) argc ;
( void ) argv ;
2017-01-07 22:11:48 +01:00
2014-10-20 10:06:23 +00:00
printf ( " Client HCI init done \n " ) ;
2014-12-21 21:59:27 +00:00
2015-04-27 00:02:07 +02:00
panu_setup ( ) ;
2015-04-24 23:08:52 +02:00
// Turn on the device
2014-10-20 10:06:23 +00:00
hci_power_control ( HCI_POWER_ON ) ;
return 0 ;
}
2015-02-06 10:45:10 +00:00
2015-04-24 23:08:52 +02:00
/* EXAMPLE_END */
2015-02-06 10:45:10 +00:00
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */