static int mgmt_read_evt(int sk, int eindex) { int ret; unsigned char buf[MGMT_BUF_SIZE]; struct mgmt_hdr *hdr = (void *) buf; struct pollfd pfd = { .fd = sk, .events = POLLIN }; if((ret = poll(&pfd, 1, 5000)) <= 0) { fprintf(stderr, "Unable to poll management socket: %s (%d)\n", strerror(errno), errno); return -1; } if(pfd.revents != POLLIN) { fprintf(stderr, "Bad event from management socket\n"); return -1; } if((ret = read(sk, buf, sizeof(buf))) < 0) { fprintf(stderr, "Unable to read from management socket: %s (%d)\n", strerror(errno), errno); return -1; } /*int i; for(i=0; i<ret; ++i) { if(!(i%16)) { printf("\n"); } printf("0x%02x ", buf[i]); } printf("\n");*/ uint16_t opcode = btohs(bt_get_unaligned(&hdr->opcode)); uint16_t len = btohs(bt_get_unaligned(&hdr->len)); uint16_t index = btohs(bt_get_unaligned(&hdr->index)); if (ret != MGMT_HDR_SIZE + len) { fprintf(stderr, "Packet length mismatch. ret %d len %u\n", ret, len); return -1; } switch (opcode) { case MGMT_EV_CMD_COMPLETE: return mgmt_cmd_complete(sk, index, buf + MGMT_HDR_SIZE, len); default: fprintf(stderr, "Unknown Management opcode %u (index %u)\n", opcode, index); break; } return 0; }
static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data) { char buf[MGMT_BUF_SIZE]; struct mgmt_hdr *hdr = (void *) buf; int sk; ssize_t ret; uint16_t len, opcode; DBG("cond %d", cond); if (cond & G_IO_NVAL) return FALSE; sk = g_io_channel_unix_get_fd(io); if (cond & (G_IO_ERR | G_IO_HUP)) { error("Error on management socket"); return FALSE; } ret = read(sk, buf, sizeof(buf)); if (ret < 0) { error("Unable to read from management socket: %s (%d)", strerror(errno), errno); return TRUE; } DBG("Received %zd bytes from management socket", ret); if (ret < MGMT_HDR_SIZE) { error("Too small Management packet"); return TRUE; } opcode = btohs(bt_get_unaligned(&hdr->opcode)); len = btohs(bt_get_unaligned(&hdr->len)); if (ret != MGMT_HDR_SIZE + len) { error("Packet length mismatch. ret %zd len %u", ret, len); return TRUE; } switch (opcode) { case MGMT_EV_CMD_COMPLETE: mgmt_cmd_complete(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CMD_STATUS: mgmt_cmd_status(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONTROLLER_ERROR: mgmt_controller_error(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_INDEX_ADDED: mgmt_index_added(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_INDEX_REMOVED: mgmt_index_removed(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_POWERED: mgmt_powered(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DISCOVERABLE: mgmt_discoverable(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONNECTABLE: mgmt_connectable(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_PAIRABLE: mgmt_pairable(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_NEW_KEY: mgmt_new_key(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DEVICE_CONNECTED: mgmt_device_connected(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_DEVICE_DISCONNECTED: mgmt_device_disconnected(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_CONNECT_FAILED: mgmt_connect_failed(sk, buf + MGMT_HDR_SIZE, len); break; case MGMT_EV_PIN_CODE_REQUEST: mgmt_pin_code_request(sk, buf + MGMT_HDR_SIZE, len); break; default: error("Unknown Management opcode %u", opcode); break; } return TRUE; }