static void btpan_tap_fd_signaled(int fd, int type, int flags, uint32_t user_id) { char packet[MAX_PACKET_SIZE]; tETH_HDR eth_hdr; if(flags & SOCK_THREAD_FD_EXCEPTION) { BTIF_TRACE_ERROR1("pan tap fd:%d exception", fd); } else if(flags & SOCK_THREAD_FD_RD) { /* debug("tab fd read trigged, data"); */ int size = read(fd, packet, MAX_PACKET_SIZE); /* debug("tap fd read trigged, read size:%d", size); */ memcpy(ð_hdr, &packet, sizeof(tETH_HDR)); /* debug("eth src = %02x:%02x:%02x:%02x:%02x:%02x", */ /* eth_hdr.h_src[0], eth_hdr.h_src[1], eth_hdr.h_src[2], eth_hdr.h_src[3], */ /* eth_hdr.h_src[4], eth_hdr.h_src[5]); */ /* debug("eth dest = %02x:%02x:%02x:%02x:%02x:%02x", */ /* eth_hdr.h_dest[0], eth_hdr.h_dest[1], eth_hdr.h_dest[2], eth_hdr.h_dest[3], */ /* eth_hdr.h_dest[4], eth_hdr.h_dest[5]); */ //dump_bin("eth packet received", packet, size); if(should_forward(ð_hdr)) { forward_bnep(ð_hdr, packet + sizeof(tETH_HDR), size - sizeof(tETH_HDR)); } btsock_thread_add_fd(pth, fd, 0, SOCK_THREAD_FD_RD | SOCK_THREAD_ADD_FD_SYNC, 0); } }
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; } } }