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
*
*/
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-28 01:16:57 +00:00
*
2014-10-20 10:06:23 +00:00
*/
2015-04-24 23:08:52 +02:00
/* EXAMPLE_START(panu_demo): PANU Demo
*
*/
2014-10-20 10:06:23 +00:00
# include "btstack-config.h"
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 <unistd.h>
# 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
2014-10-20 10:06:23 +00:00
# include <btstack/hci_cmds.h>
# include <btstack/run_loop.h>
2014-12-12 08:42:35 +00:00
# include <btstack/sdp_util.h>
2014-10-20 10:06:23 +00:00
# include "hci.h"
# include "btstack_memory.h"
# include "hci_dump.h"
# include "l2cap.h"
# include "sdp_parser.h"
2014-10-27 11:50:12 +00:00
# include "sdp_client.h"
# include "sdp_query_util.h"
# include "pan.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
2014-10-27 11:50:12 +00:00
static data_source_t tap_dev_ds ;
2014-12-18 13:22:03 +00:00
2015-04-24 23:08:52 +02:00
/* @section TUN / TAP interface routines
*
* @ text Available on Linux by default , assumes tuntaposx on OS X
* interface name : set to " bnepX " on linux , same as tapX on OS X ,
* see https : //www.kernel.org/doc/Documentation/networking/tuntap.txt
*
* Flags :
* - IFF_TUN : TUN device ( no Ethernet headers )
* - IFF_TAP : TAP device
* - IFF_NO_PI : Do not provide packet information
*/
2014-10-27 11:50:12 +00:00
int tap_alloc ( char * dev , bd_addr_t bd_addr )
{
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 ;
}
int process_tap_dev_data ( struct data_source * ds )
{
ssize_t len ;
len = read ( ds - > fd , network_buffer , sizeof ( network_buffer ) ) ;
if ( len > 0 ) {
network_buffer_len = len ;
} else {
fprintf ( stderr , " TAP: Error while reading: %s \n " , strerror ( errno ) ) ;
}
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
2014-10-28 01:16:57 +00:00
run_loop_remove_data_source ( & tap_dev_ds ) ;
}
2014-10-27 11:50:12 +00:00
return 0 ;
}
2015-04-24 23:08:52 +02:00
// PANU client routines
2014-10-20 10:06:23 +00:00
char * get_string_from_data_element ( uint8_t * element ) {
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 :
len = READ_NET_16 ( element , 1 ) ;
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
*
*/
2014-10-20 10:06:23 +00:00
static void handle_sdp_client_query_result ( sdp_query_event_t * event )
{
sdp_query_attribute_value_event_t * value_event ;
sdp_query_complete_event_t * complete_event ;
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
switch ( event - > type ) {
case SDP_QUERY_ATTRIBUTE_VALUE :
value_event = ( sdp_query_attribute_value_event_t * ) event ;
2015-04-24 23:08:52 +02:00
// Handle new SDP record
2014-10-20 10:06:23 +00:00
if ( value_event - > record_id ! = record_id ) {
record_id = value_event - > record_id ;
printf ( " SDP Record: Nr: %d \n " , record_id ) ;
}
if ( value_event - > attribute_length < = attribute_value_buffer_size ) {
attribute_value [ value_event - > data_offset ] = value_event - > data ;
if ( ( uint16_t ) ( value_event - > data_offset + 1 ) = = value_event - > attribute_length ) {
2014-10-27 11:50:12 +00:00
switch ( value_event - > attribute_id ) {
case SDP_ServiceClassIDList :
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 ) {
2015-02-13 09:28:39 +00:00
case SDP_PANU :
case SDP_NAP :
case SDP_GN :
2014-10-27 11:50:12 +00:00
printf ( " SDP Attribute 0x%04x: BNEP PAN protocol UUID: %04x \n " , value_event - > attribute_id , uuid ) ;
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 ) ;
printf ( " SDP Attribute: 0x%04x: %s \n " , value_event - > attribute_id , str ) ;
free ( str ) ;
2014-10-20 10:06:23 +00:00
break ;
2014-10-27 11:50:12 +00:00
case 0x0004 : {
2014-10-20 10:06:23 +00:00
printf ( " SDP Attribute: 0x%04x \n " , value_event - > attribute_id ) ;
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 ) {
2015-02-13 09:28:39 +00:00
case SDP_L2CAPProtocol :
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 ;
2015-02-13 09:28:39 +00:00
case SDP_BNEPProtocol :
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 */
2014-10-27 11:50:12 +00:00
bnep_connect ( NULL , & remote , bnep_l2cap_psm , bnep_remote_uuid ) ;
2014-10-20 10:06:23 +00:00
}
break ;
default :
break ;
}
}
} else {
fprintf ( stderr , " SDP attribute value buffer size exceeded: available %d, required %d \n " , attribute_value_buffer_size , value_event - > attribute_length ) ;
}
break ;
case SDP_QUERY_COMPLETE :
complete_event = ( sdp_query_complete_event_t * ) event ;
fprintf ( stderr , " General query done with status %d. \n " , complete_event - > status ) ;
break ;
}
}
static void packet_handler ( void * connection , uint8_t packet_type , uint16_t channel , uint8_t * packet , uint16_t size )
{
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
2014-10-20 10:06:23 +00:00
switch ( packet_type ) {
case HCI_EVENT_PACKET :
2014-10-27 11:50:12 +00:00
event = packet [ 0 ] ;
switch ( event ) {
2014-10-20 10:06:23 +00:00
case BTSTACK_EVENT_STATE :
/* BT Stack activated, get started */
if ( packet [ 2 ] = = HCI_STATE_WORKING ) {
/* Send a general query for BNEP Protocol ID */
printf ( " Start SDP BNEP query. \n " ) ;
2015-02-13 09:28:39 +00:00
sdp_general_query_for_uuid ( remote , SDP_BNEPProtocol ) ;
2014-10-20 10:06:23 +00:00
}
break ;
case HCI_EVENT_COMMAND_COMPLETE :
if ( COMMAND_COMPLETE_EVENT ( packet , hci_read_bd_addr ) ) {
bt_flip_addr ( event_addr , & packet [ 6 ] ) ;
printf ( " BD-ADDR: %s \n " , bd_addr_to_str ( event_addr ) ) ;
break ;
}
break ;
case HCI_EVENT_PIN_CODE_REQUEST :
// inform about pin code request
printf ( " Pin code request - using '0000' \n " ) ;
bt_flip_addr ( event_addr , & packet [ 2 ] ) ;
hci_send_cmd ( & hci_pin_code_request_reply , & event_addr , 4 , " 0000 " ) ;
break ;
case HCI_EVENT_USER_CONFIRMATION_REQUEST :
// inform about user confirmation request
printf ( " SSP User Confirmation Request with numeric value '%06u' \n " , READ_BT_32 ( packet , 8 ) ) ;
printf ( " SSP User Confirmation Auto accept \n " ) ;
break ;
case BNEP_EVENT_INCOMING_CONNECTION :
2014-11-19 01:01:22 +00:00
// data: event(8), len(8), bnep source uuid (16), bnep destination uuid (16), remote_address (48)
uuid_source = READ_BT_16 ( packet , 2 ) ;
uuid_dest = READ_BT_16 ( packet , 4 ) ;
mtu = READ_BT_16 ( packet , 6 ) ;
2014-10-28 01:16:57 +00:00
bnep_cid = channel ;
2014-11-19 01:01:22 +00:00
memcpy ( & event_addr , & packet [ 8 ] , sizeof ( bd_addr_t ) ) ;
2014-10-27 11:50:12 +00:00
printf ( " BNEP connection from %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 ) ;
2014-11-19 01:01:16 +00:00
/* Create the tap interface */
2015-03-24 08:44:48 +00:00
hci_local_bd_addr ( local_addr ) ;
tap_fd = tap_alloc ( tap_dev_name , local_addr ) ;
2014-11-19 01:01:16 +00:00
if ( tap_fd < 0 ) {
printf ( " Creating BNEP tap device failed: %s \n " , strerror ( errno ) ) ;
} else {
printf ( " BNEP device \" %s \" allocated. \n " , tap_dev_name ) ;
/* Create and register a new runloop data source */
tap_dev_ds . fd = tap_fd ;
tap_dev_ds . process = process_tap_dev_data ;
run_loop_add_data_source ( & tap_dev_ds ) ;
}
2014-10-20 10:06:23 +00:00
break ;
case BNEP_EVENT_OPEN_CHANNEL_COMPLETE :
if ( packet [ 2 ] ) {
printf ( " BNEP channel open failed, status %02x \n " , packet [ 2 ] ) ;
} else {
// data: event(8), len(8), status (8), bnep source uuid (16), bnep destination uuid (16), remote_address (48)
uuid_source = READ_BT_16 ( packet , 3 ) ;
uuid_dest = READ_BT_16 ( packet , 5 ) ;
mtu = READ_BT_16 ( packet , 7 ) ;
2014-10-28 01:16:57 +00:00
bnep_cid = channel ;
2014-10-27 11:50:12 +00:00
//bt_flip_addr(event_addr, &packet[9]);
memcpy ( & event_addr , & packet [ 9 ] , sizeof ( bd_addr_t ) ) ;
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 */
tap_fd = tap_alloc ( tap_dev_name , * hci_local_bd_addr ( ) ) ;
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 */
tap_dev_ds . fd = tap_fd ;
tap_dev_ds . process = process_tap_dev_data ;
run_loop_add_data_source ( & tap_dev_ds ) ;
}
2014-10-20 10:06:23 +00:00
}
break ;
2014-11-13 00:28:01 +00:00
case BNEP_EVENT_CHANNEL_TIMEOUT :
printf ( " BNEP channel timeout! Channel will be closed \n " ) ;
break ;
2014-10-20 10:06:23 +00:00
case BNEP_EVENT_CHANNEL_CLOSED :
printf ( " BNEP channel closed \n " ) ;
2014-10-27 11:50:12 +00:00
run_loop_remove_data_source ( & tap_dev_ds ) ;
if ( tap_fd > 0 ) {
close ( tap_fd ) ;
tap_fd = - 1 ;
}
2014-10-20 10:06:23 +00:00
break ;
2014-10-28 01:16:57 +00:00
case BNEP_EVENT_READY_TO_SEND :
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
2014-10-28 01:16:57 +00:00
run_loop_add_data_source ( & tap_dev_ds ) ;
}
break ;
2014-10-20 10:06:23 +00:00
default :
break ;
}
2014-10-27 11:50:12 +00:00
break ;
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 ;
}
}
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
printf ( " Client HCI init done \n " ) ;
2014-12-21 21:59:27 +00:00
2015-04-24 23:08:52 +02:00
// Initialize L2CAP
2014-10-20 10:06:23 +00:00
l2cap_init ( ) ;
l2cap_register_packet_handler ( packet_handler ) ;
2015-04-24 23:08:52 +02:00
// Initialise BNEP
2014-10-20 10:06:23 +00:00
bnep_init ( ) ;
bnep_register_packet_handler ( packet_handler ) ;
2015-04-24 23:08:52 +02:00
// Minimum L2CAP MTU for bnep is 1691 bytes
bnep_register_service ( NULL , SDP_PANU , 1691 ) ;
2014-10-20 10:06:23 +00:00
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 ) ;
2015-04-24 23:08:52 +02:00
// Initialise SDP
2014-10-20 10:06:23 +00:00
sdp_parser_init ( ) ;
sdp_parser_register_callback ( handle_sdp_client_query_result ) ;
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 -*- */