From a7473022f2e724b17eb0f89f62400840edd9c95f Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Tue, 7 Nov 2017 16:42:06 +0100 Subject: [PATCH] network: extract POSIX network code into btstack_network_posix and use in panu_demo --- example/panu_demo.c | 255 ++++++------------------------------------ port/libusb/Makefile | 2 +- src/btstack.h | 3 +- src/btstack_network.h | 10 +- 4 files changed, 41 insertions(+), 229 deletions(-) diff --git a/example/panu_demo.c b/example/panu_demo.c index 42f457a34..6e97cc9cb 100644 --- a/example/panu_demo.c +++ b/example/panu_demo.c @@ -52,39 +52,9 @@ * Note: currently supported only on Linux and Mac. */ -#include "btstack_config.h" - -#include -#include -#include -#include -#include #include -#include -#include -#include - -#include - -#ifdef __APPLE__ -#include -#include - -#include -#include -#endif - -#include -#include -#include -#include -#include - -#ifdef __linux -#include -#include -#endif +#include "btstack_config.h" #include "btstack.h" static int record_id = -1; @@ -100,31 +70,18 @@ static uint32_t sdp_bnep_remote_uuid = 0; static uint8_t attribute_value[1000]; static const unsigned int attribute_value_buffer_size = sizeof(attribute_value); -// MBP 2016 static const char * remote_addr_string = "F4-0F-24-3B-1B-E1"; -// Wiko Sunny -static const char * remote_addr_string = "A0:4C:5B:0F:B2:42"; +// MBP 2016 +static const char * remote_addr_string = "F4-0F-24-3B-1B-E1"; +// Wiko Sunny static const char * remote_addr_string = "A0:4C:5B:0F:B2:42"; + static bd_addr_t remote_addr; -static int tap_fd = -1; -static uint8_t network_buffer[BNEP_MTU_MIN]; -static size_t network_buffer_len = 0; - -#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"; -static char tap_dev_name[16] = "bnep%d"; -#endif - - -static btstack_data_source_t tap_dev_ds; static btstack_packet_callback_registration_t hci_event_callback_registration; +// outgoing network packet +static const uint8_t * network_buffer; +static uint16_t network_buffer_len; + /* @section Main application configuration * * @text In the application configuration, L2CAP and BNEP are initialized and a BNEP service, for server mode, @@ -134,6 +91,7 @@ static btstack_packet_callback_registration_t hci_event_callback_registration; /* LISTING_START(PanuSetup): Panu setup */ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +static void network_send_packet_callback(const uint8_t * packet, uint16_t size); static void panu_setup(void){ @@ -146,146 +104,12 @@ static void panu_setup(void){ // Initialise BNEP bnep_init(); + // Minimum L2CAP MTU for bnep is 1691 bytes bnep_register_service(packet_handler, BLUETOOTH_SERVICE_CLASS_PANU, 1691); -} -/* LISTING_END */ -/* @section TUN / TAP interface routines - * - * @text This example requires a TUN/TAP interface to connect the Bluetooth network interface - * 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. - * - * On Linux, TUN/TAP is available by default. On OS X, tuntaposx from - * http://tuntaposx.sourceforge.net needs to be installed. - * - * The *tap_alloc* function sets up a virtual network interface with the given Bluetooth Address. - * It is rather low-level as it sets up and configures a network interface. - */ - -static int tap_alloc(char *dev, bd_addr_t bd_addr) -{ - struct ifreq ifr; - int fd_dev; - int fd_socket; - - if( (fd_dev = open(tap_dev, O_RDWR)) < 0 ) { - fprintf(stderr, "TAP: Error opening %s: %s\n", tap_dev, strerror(errno)); - return -1; - } - -#ifdef __linux - memset(&ifr, 0, sizeof(ifr)); - - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - if( *dev ) { - strncpy(ifr.ifr_name, dev, IFNAMSIZ); - } - - int err; - 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); -#endif -#ifdef __APPLE__ - dev = tap_dev_name; -#endif - - 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; - } - - // Configure the MAC address of the newly created bnep(x) - // device to the local bd_address - memset (&ifr, 0, sizeof(struct ifreq)); - strcpy(ifr.ifr_name, dev); -#ifdef __linux - ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; - memcpy(ifr.ifr_hwaddr.sa_data, bd_addr, sizeof(bd_addr_t)); - 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; - } -#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 - - // Bring the interface up - 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; -} - -/* - * @text Listing processTapData shows how a packet is received from the TAP network interface - * and forwarded over the BNEP connection. - * - * After successfully reading a network packet, the call to - * the *bnep_can_send_packet_now* function checks, if BTstack can forward - * 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 - * run loop. The *process_tap_dev_data* function will not be called until - * the data source is registered again. This provides a basic flow control. - */ - -/* LISTING_START(processTapData): Process incoming network packets */ -static void process_tap_dev_data(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type) -{ - UNUSED(ds); - UNUSED(callback_type); - - ssize_t len; - len = read(ds->fd, network_buffer, sizeof(network_buffer)); - if (len <= 0){ - fprintf(stderr, "TAP: Error while reading: %s\n", strerror(errno)); - return; - } - - network_buffer_len = len; - - // disable reading from netif - btstack_run_loop_disable_data_source_callbacks(&tap_dev_ds, DATA_SOURCE_CALLBACK_READ); - - // request permission to send - bnep_request_can_send_now_event(bnep_cid); + // Initialize network interface + btstack_network_init(&network_send_packet_callback); } /* LISTING_END */ @@ -443,14 +267,12 @@ static void handle_sdp_client_query_result(uint8_t packet_type, uint16_t channel * @text The packet handler responds to various HCI Events. */ - /* LISTING_START(packetHandler): Packet Handler */ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { /* LISTING_PAUSE */ UNUSED(channel); - int rc; uint8_t event; bd_addr_t event_addr; bd_addr_t local_addr; @@ -506,22 +328,11 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack 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); - //bt_flip_addr(event_addr, &packet[9]); memcpy(&event_addr, &packet[11], 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 */ + /* Setup network interface */ gap_local_bd_addr(local_addr); - tap_fd = tap_alloc(tap_dev_name, local_addr); - 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 */ - btstack_run_loop_set_data_source_fd(&tap_dev_ds, tap_fd); - btstack_run_loop_set_data_source_handler(&tap_dev_ds, &process_tap_dev_data); - btstack_run_loop_add_data_source(&tap_dev_ds); - btstack_run_loop_enable_data_source_callbacks(&tap_dev_ds, DATA_SOURCE_CALLBACK_READ); - } + btstack_network_up(local_addr); } break; @@ -536,11 +347,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack */ case BNEP_EVENT_CHANNEL_CLOSED: printf("BNEP channel closed\n"); - btstack_run_loop_remove_data_source(&tap_dev_ds); - if (tap_fd > 0) { - close(tap_fd); - tap_fd = -1; - } + btstack_network_down(); break; /* @text BNEP_EVENT_CAN_SEND_NOW indicates that a new packet can be send. This triggers the send of a @@ -548,10 +355,9 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack */ case BNEP_EVENT_CAN_SEND_NOW: if (network_buffer_len > 0) { - bnep_send(bnep_cid, network_buffer, network_buffer_len); + bnep_send(bnep_cid, (uint8_t*) network_buffer, network_buffer_len); network_buffer_len = 0; - // Re-enable the tap device data source - btstack_run_loop_enable_data_source_callbacks(&tap_dev_ds, DATA_SOURCE_CALLBACK_READ); + btstack_network_packet_sent(); } break; @@ -564,16 +370,8 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack * It is forwarded to the TAP interface. */ case BNEP_DATA_PACKET: - // Write out the ethernet frame to the tap device - 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); - } - } + // Write out the ethernet frame to the network interface + btstack_network_process_packet(packet, size); break; default: @@ -582,6 +380,19 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack } /* LISTING_END */ +/* + * @section Network packet handler + * + * @text A pointer to the network packet is stored and a BNEP_EVENT_CAN_SEND_NOW requested + */ + +/* LISTING_START(networkPacketHandler): Network Packet Handler */ +static void network_send_packet_callback(const uint8_t * packet, uint16_t size){ + network_buffer = packet; + network_buffer_len = size; + bnep_request_can_send_now_event(bnep_cid); +} +/* LISTING_END */ int btstack_main(int argc, const char * argv[]); int btstack_main(int argc, const char * argv[]){ diff --git a/port/libusb/Makefile b/port/libusb/Makefile index b1b4b74c0..2c8149de7 100644 --- a/port/libusb/Makefile +++ b/port/libusb/Makefile @@ -3,7 +3,7 @@ BTSTACK_ROOT = ../.. CORE += main.c btstack_stdin_posix.c -COMMON += hci_transport_h2_libusb.c btstack_run_loop_posix.c le_device_db_fs.c btstack_link_key_db_fs.c wav_util.c +COMMON += hci_transport_h2_libusb.c btstack_run_loop_posix.c le_device_db_fs.c btstack_link_key_db_fs.c wav_util.c btstack_network_posix.c include ${BTSTACK_ROOT}/example/Makefile.inc diff --git a/src/btstack.h b/src/btstack.h index b3915d2a6..b1ac5d417 100644 --- a/src/btstack.h +++ b/src/btstack.h @@ -59,6 +59,7 @@ #include "btstack_linked_list.h" #include "btstack_memory.h" #include "btstack_memory_pool.h" +#include "btstack_network.h" #include "btstack_run_loop.h" #include "btstack_stdin.h" #include "btstack_util.h" @@ -112,4 +113,4 @@ // #endif #endif // __BTSTACK_H - \ No newline at end of file + diff --git a/src/btstack_network.h b/src/btstack_network.h index 08781d8d2..421dfd97e 100644 --- a/src/btstack_network.h +++ b/src/btstack_network.h @@ -43,14 +43,14 @@ #define __BTSTACK_NETWORK_H #include -#include "btstack_defines.h" +#include "bluetooth.h" #if defined __cplusplus extern "C" { #endif /** - * @brief Initialise network interface + * @brief Initialize network interface * @param send_packet_callback */ void btstack_network_init(void (*send_packet_callback)(const uint8_t * packet, uint16_t size)); @@ -63,7 +63,7 @@ void btstack_network_init(void (*send_packet_callback)(const uint8_t * packet, u int btstack_network_up(bd_addr_t network_address); /** - * @brief Bring up network interfacd + * @brief Shut down network interfacd * @param network_address * @return 0 if ok */ @@ -74,10 +74,10 @@ int btstack_network_down(void); * @param packet * @param size */ -uint8_t btstack_network_process_packet(const uint8_t * packet, uint16_t size); +void btstack_network_process_packet(const uint8_t * packet, uint16_t size); /** - * @brief Notify network interface that packet from send_packet_callback was sent and the next packet could be delivered + * @brief Notify network interface that packet from send_packet_callback was sent and the next packet can be delivered. */ void btstack_network_packet_sent(void);