static int tap_if_up(const char *devname, const bt_bdaddr_t *addr) { struct ifreq ifr; int sk, err; sk = socket(AF_INET, SOCK_DGRAM, 0); if (sk < 0) return -1; //set mac addr memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, devname, IFNAMSIZ - 1); err = ioctl(sk, SIOCGIFHWADDR, &ifr); if (err < 0) { BTIF_TRACE_ERROR("Could not get network hardware for interface:%s, errno:%s", devname, strerror(errno)); close(sk); return -1; } strncpy(ifr.ifr_name, devname, IFNAMSIZ - 1); memcpy(ifr.ifr_hwaddr.sa_data, addr->address, 6); /* The IEEE has specified that the most significant bit of the most significant byte is used to * determine a multicast address. If its a 1, that means multicast, 0 means unicast. * Kernel returns an error if we try to set a multicast address for the tun-tap ethernet interface. * Mask this bit to avoid any issue with auto generated address. */ if (ifr.ifr_hwaddr.sa_data[0] & 0x01) { BTIF_TRACE_WARNING("Not a unicast MAC address, force multicast bit flipping"); ifr.ifr_hwaddr.sa_data[0] &= ~0x01; } err = ioctl(sk, SIOCSIFHWADDR, (caddr_t)&ifr); if (err < 0) { BTIF_TRACE_ERROR("Could not set bt address for interface:%s, errno:%s", devname, strerror(errno)); close(sk); return -1; } //bring it up memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, devname, IF_NAMESIZE - 1); ifr.ifr_flags |= IFF_UP; ifr.ifr_flags |= IFF_MULTICAST; err = ioctl(sk, SIOCSIFFLAGS, (caddr_t) &ifr); if (err < 0) { BTIF_TRACE_ERROR("Could not bring up network interface:%s, errno:%d", devname, errno); close(sk); return -1; } close(sk); BTIF_TRACE_DEBUG("network interface: %s is up", devname); return 0; }
static void queue_int_add(connect_node_t *p_param) { connect_node_t *p_node = GKI_getbuf(sizeof(connect_node_t)); ASSERTC(p_node != NULL, "Failed to allocate new list node", 0); if (p_node) memcpy(p_node, p_param, sizeof(connect_node_t)); else { BTIF_TRACE_ERROR("%s, Failed to allocate new list node"); return; } if (!connect_queue) { connect_queue = list_new(GKI_freebuf); ASSERTC(connect_queue != NULL, "Failed to allocate list", 0); } if (connect_queue) list_append(connect_queue, p_node); else BTIF_TRACE_ERROR("%s, Failed to allocate list"); }
/***************************************************************************** ** ** Function btif_sm_get_state ** ** Description Fetches the current state of the state machine ** ** Returns Current state ** ******************************************************************************/ btif_sm_state_t btif_sm_get_state(btif_sm_handle_t handle) { btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; if (p_cb == NULL) { BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); return 0; } return p_cb->state; }
/***************************************************************************** ** ** Function btif_sm_shutdown ** ** Description Tears down the state machine ** ** Returns None ** ******************************************************************************/ void btif_sm_shutdown(btif_sm_handle_t handle) { btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; if (p_cb == NULL) { BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); return; } osi_free(p_cb); }
/***************************************************************************** ** ** Function btif_sm_dispatch ** ** Description Dispatches the 'event' along with 'data' to the current state handler ** ** Returns BT_STATUS_SUCCESS on success ** BT_STATUS_UNHANDLED if event was not processed ** BT_STATUS_FAIL otherwise ** ******************************************************************************/ bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event, void *data) { bt_status_t status = BT_STATUS_SUCCESS; btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; if (p_cb == NULL) { BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); return BT_STATUS_FAIL; } if (p_cb->p_handlers[p_cb->state](event, data, p_cb->index) == FALSE) return BT_STATUS_UNHANDLED; return status; }
btif_sm_handle_t btif_sm_init(const btif_sm_handler_t *p_handlers, btif_sm_state_t initial_state, int index) { btif_sm_cb_t *p_cb; if (p_handlers == NULL) { BTIF_TRACE_ERROR("%s : p_handlers is NULL", __FUNCTION__); return NULL; } p_cb = (btif_sm_cb_t *)osi_malloc(sizeof(btif_sm_cb_t)); p_cb->state = initial_state; p_cb->p_handlers = (btif_sm_handler_t*)p_handlers; p_cb->index = index; /* Send BTIF_SM_ENTER_EVT to the initial state */ p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL, index); return (btif_sm_handle_t)p_cb; }
int btpan_tap_open() { struct ifreq ifr; int fd, err; const char *clonedev = "/dev/tun"; /* open the clone device */ //system("insmod /system/lib/modules/tun.ko"); if( (fd = open(clonedev, O_RDWR)) < 0 ) { BTIF_TRACE_DEBUG("could not open %s, err:%d", clonedev, errno); return fd; } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strncpy(ifr.ifr_name, TAP_IF_NAME, IFNAMSIZ); /* try to create the device */ if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 )//|| tap_setup_ip(TAP_IF_NAME) == FALSE) { BTIF_TRACE_DEBUG("ioctl error:%d, errno:%s", err, strerror(errno)); close(fd); return err; } BTM_GetLocalDeviceAddr (local_addr); if(tap_if_up(TAP_IF_NAME, local_addr) == 0) { int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); return fd; } BTIF_TRACE_ERROR("can not bring up tap interface:%s", TAP_IF_NAME); close(fd); return -1; }
/***************************************************************************** ** ** Function btif_sm_change_state ** ** Description Make a transition to the new 'state'. The 'BTIF_SM_EXIT_EVT' ** shall be invoked before exiting the current state. The ** 'BTIF_SM_ENTER_EVT' shall be invoked before entering the new state ** ** Returns BT_STATUS_SUCCESS on success ** BT_STATUS_UNHANDLED if event was not processed ** BT_STATUS_FAIL otherwise ** ******************************************************************************/ bt_status_t btif_sm_change_state(btif_sm_handle_t handle, btif_sm_state_t state) { bt_status_t status = BT_STATUS_SUCCESS; btif_sm_cb_t *p_cb = (btif_sm_cb_t*)handle; if (p_cb == NULL) { BTIF_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); return BT_STATUS_FAIL; } /* Send exit event to the current state */ if (p_cb->p_handlers[p_cb->state](BTIF_SM_EXIT_EVT, NULL, p_cb->index) == FALSE) status = BT_STATUS_UNHANDLED; /* Change to the new state */ p_cb->state = state; /* Send enter event to the new state */ if (p_cb->p_handlers[p_cb->state](BTIF_SM_ENTER_EVT, NULL, p_cb->index) == FALSE) status = BT_STATUS_UNHANDLED; return status; }
int btpan_tap_open() { struct ifreq ifr; int fd, err; const char *clonedev = "/dev/tun"; /* open the clone device */ if ((fd = open(clonedev, O_RDWR)) < 0) { BTIF_TRACE_DEBUG("could not open %s, err:%d", clonedev, errno); return fd; } memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strncpy(ifr.ifr_name, TAP_IF_NAME, IFNAMSIZ); /* try to create the device */ if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) { BTIF_TRACE_DEBUG("ioctl error:%d, errno:%s", err, strerror(errno)); close(fd); return err; } if (tap_if_up(TAP_IF_NAME, controller_get_interface()->get_address()) == 0) { int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); return fd; } BTIF_TRACE_ERROR("can not bring up tap interface:%s", TAP_IF_NAME); close(fd); return INVALID_FD; }
static void btu_exec_tap_fd_read(void *p_param) { struct pollfd ufd; int fd = (int)p_param; if (fd == -1 || fd != btpan_cb.tap_fd) return; // Don't occupy BTU context too long, avoid GKI buffer overruns and // give other profiles a chance to run by limiting the amount of memory // PAN can use from the shared pool buffer. for(int i = 0; i < PAN_POOL_MAX && btif_is_enabled() && btpan_cb.flow; i++) { BT_HDR *buffer = (BT_HDR *)GKI_getpoolbuf(PAN_POOL_ID); if (!buffer) { BTIF_TRACE_WARNING("%s unable to allocate buffer for packet.", __func__); break; } buffer->offset = PAN_MINIMUM_OFFSET; buffer->len = GKI_get_buf_size(buffer) - sizeof(BT_HDR) - buffer->offset; UINT8 *packet = (UINT8 *)buffer + sizeof(BT_HDR) + buffer->offset; // If we don't have an undelivered packet left over, pull one from the TAP driver. // We save it in the congest_packet right away in case we can't deliver it in this // attempt. if (!btpan_cb.congest_packet_size) { ssize_t ret = read(fd, btpan_cb.congest_packet, sizeof(btpan_cb.congest_packet)); switch (ret) { case -1: BTIF_TRACE_ERROR("%s unable to read from driver: %s", __func__, strerror(errno)); GKI_freebuf(buffer); return; case 0: BTIF_TRACE_WARNING("%s end of file reached.", __func__); GKI_freebuf(buffer); return; default: btpan_cb.congest_packet_size = ret; break; } } memcpy(packet, btpan_cb.congest_packet, MIN(btpan_cb.congest_packet_size, buffer->len)); buffer->len = MIN(btpan_cb.congest_packet_size, buffer->len); if (buffer->len > sizeof(tETH_HDR) && should_forward((tETH_HDR *)packet)) { // Extract the ethernet header from the buffer since the PAN_WriteBuf inside // forward_bnep can't handle two pointers that point inside the same GKI buffer. tETH_HDR hdr; memcpy(&hdr, packet, sizeof(tETH_HDR)); // Skip the ethernet header. buffer->len -= sizeof(tETH_HDR); buffer->offset += sizeof(tETH_HDR); if (forward_bnep(&hdr, buffer) != FORWARD_CONGEST) btpan_cb.congest_packet_size = 0; } else { BTIF_TRACE_WARNING("%s dropping packet of length %d", __func__, buffer->len); btpan_cb.congest_packet_size = 0; GKI_freebuf(buffer); } // Bail out of the loop if reading from the TAP fd would block. ufd.fd = fd; ufd.events = POLLIN; ufd.revents = 0; if(poll(&ufd, 1, 0) <= 0 || IS_EXCEPTION(ufd.revents)) { btsock_thread_add_fd(pan_pth, fd, 0, SOCK_THREAD_FD_RD, 0); return; } } }
static void bta_pan_callback_transfer(UINT16 event, char *p_param) { tBTA_PAN *p_data = (tBTA_PAN *)p_param; switch(event) { case BTA_PAN_ENABLE_EVT: BTIF_TRACE_DEBUG("BTA_PAN_ENABLE_EVT"); break; case BTA_PAN_SET_ROLE_EVT: { int btpan_role = bta_role_to_btpan(p_data->set_role.role); bt_status_t status = p_data->set_role.status == BTA_PAN_SUCCESS ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; btpan_control_state_t state = btpan_role == 0 ? BTPAN_STATE_DISABLED : BTPAN_STATE_ENABLED; callback.control_state_cb(state, btpan_role, status, TAP_IF_NAME); break; } case BTA_PAN_OPENING_EVT: { btpan_conn_t* conn; bdstr_t bds; bd2str((bt_bdaddr_t*)p_data->opening.bd_addr, &bds); BTIF_TRACE_DEBUG("BTA_PAN_OPENING_EVT handle %d, addr: %s", p_data->opening.handle, bds); conn = btpan_find_conn_addr(p_data->opening.bd_addr); asrt(conn != NULL); if (conn) { conn->handle = p_data->opening.handle; int btpan_conn_local_role = bta_role_to_btpan(conn->local_role); int btpan_remote_role = bta_role_to_btpan(conn->remote_role); callback.connection_state_cb(BTPAN_STATE_CONNECTING, BT_STATUS_SUCCESS, (const bt_bdaddr_t*)p_data->opening.bd_addr, btpan_conn_local_role, btpan_remote_role); } else BTIF_TRACE_ERROR("connection not found"); break; } case BTA_PAN_OPEN_EVT: { /* debug("BTA_PAN_OPEN_EVT, open status:%d, bd_addr = [%02X:%02X:%02X:%02X:%02X:%02X]", */ /* p_data->open.status, */ /* p_data->open.bd_addr[0], p_data->open.bd_addr[1], p_data->open.bd_addr[2], */ /* p_data->open.bd_addr[3], p_data->open.bd_addr[4], p_data->open.bd_addr[5]); */ btpan_connection_state_t state; bt_status_t status; btpan_conn_t *conn = btpan_find_conn_handle(p_data->open.handle); ALOGV("%s pan connection open status: %d", __func__, p_data->open.status); if(p_data->open.status == BTA_PAN_SUCCESS) { state = BTPAN_STATE_CONNECTED; status = BT_STATUS_SUCCESS; } else { state = BTPAN_STATE_DISCONNECTED; status = BT_STATUS_FAIL; btpan_cleanup_conn(conn); } /* debug("BTA_PAN_OPEN_EVT handle:%d, conn:%p", p_data->open.handle, conn); */ /* debug("conn bta local_role:%d, bta remote role:%d", conn->local_role, conn->remote_role); */ int btpan_conn_local_role = bta_role_to_btpan(p_data->open.local_role); /* debug("bta local_role:%d, bta remote role:%d", p_data->open.local_role, p_data->open.peer_role); */ int btpan_remote_role = bta_role_to_btpan(p_data->open.peer_role); callback.connection_state_cb(state, status, (const bt_bdaddr_t*)p_data->open.bd_addr, btpan_conn_local_role, btpan_remote_role); break; } case BTA_PAN_CLOSE_EVT: { btpan_conn_t* conn = btpan_find_conn_handle(p_data->close.handle); ALOGI("%s: event = BTA_PAN_CLOSE_EVT handle %d", __FUNCTION__, p_data->close.handle); if(conn && conn->handle >= 0) { /* debug("BTA_PAN_CLOSE_EVT, conn local_role:%d, remote_role:%d", conn->local_role, conn->remote_role); */ int btpan_conn_local_role = bta_role_to_btpan(conn->local_role); int btpan_remote_role = bta_role_to_btpan(conn->remote_role); callback.connection_state_cb(BTPAN_STATE_DISCONNECTED, 0, (const bt_bdaddr_t*)conn->peer, btpan_conn_local_role, btpan_remote_role); btpan_cleanup_conn(conn); } else BTIF_TRACE_ERROR("pan handle not found (%d)", p_data->close.handle); break; } default: BTIF_TRACE_WARNING("Unknown pan event %d", event); break; } }