static void bt_hid_send_data(const void *buf, uint16_t len) { const struct hal_cmd_hidhost_send_data *cmd = buf; struct hid_device *dev; GSList *l; bdaddr_t dst; int i, fd; uint8_t *req; uint8_t req_size; uint8_t status; DBG(""); if (len != sizeof(*cmd) + cmd->len) { error("Invalid hid send data size (%u bytes), terminating", len); raise(SIGTERM); return; } android2bdaddr(&cmd->bdaddr, &dst); l = g_slist_find_custom(devices, &dst, device_cmp); if (!l) { status = HAL_STATUS_FAILED; goto failed; } dev = l->data; if (!(dev->intr_io)) { status = HAL_STATUS_FAILED; goto failed; } req_size = 1 + (cmd->len / 2); req = g_try_malloc0(req_size); if (!req) { status = HAL_STATUS_NOMEM; goto failed; } req[0] = HID_MSG_DATA | HID_DATA_TYPE_OUTPUT; /* Report data coming to HAL is in ascii format, HAL sends * data in hex to daemon, so convert to binary. */ for (i = 0; i < (req_size - 1); i++) sscanf((char *) &(cmd->data)[i * 2], "%hhx", &(req + 1)[i]); fd = g_io_channel_unix_get_fd(dev->intr_io); if (write(fd, req, req_size) < 0) { error("error writing data to HID device: %s (%d)", strerror(errno), errno); g_free(req); status = HAL_STATUS_FAILED; goto failed; } g_free(req); status = HAL_STATUS_SUCCESS; failed: ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA, status); }
static void bt_hid_get_report(const void *buf, uint16_t len) { const struct hal_cmd_hidhost_get_report *cmd = buf; struct hid_device *dev; GSList *l; bdaddr_t dst; int fd; uint8_t *req; uint8_t req_size; uint8_t status; DBG(""); switch (cmd->type) { case HAL_HIDHOST_INPUT_REPORT: case HAL_HIDHOST_OUTPUT_REPORT: case HAL_HIDHOST_FEATURE_REPORT: break; default: status = HAL_STATUS_INVALID; goto failed; } android2bdaddr(&cmd->bdaddr, &dst); l = g_slist_find_custom(devices, &dst, device_cmp); if (!l) { status = HAL_STATUS_FAILED; goto failed; } dev = l->data; req_size = (cmd->buf_size > 0) ? 4 : 2; req = g_try_malloc0(req_size); if (!req) { status = HAL_STATUS_NOMEM; goto failed; } req[0] = HID_MSG_GET_REPORT | cmd->type; req[1] = cmd->id; if (cmd->buf_size > 0) { req[0] = req[0] | HID_GET_REPORT_SIZE_FIELD; bt_put_le16(cmd->buf_size, &req[2]); } fd = g_io_channel_unix_get_fd(dev->ctrl_io); if (write(fd, req, req_size) < 0) { error("error writing hid_get_report: %s (%d)", strerror(errno), errno); g_free(req); status = HAL_STATUS_FAILED; goto failed; } dev->last_hid_msg = HID_MSG_GET_REPORT; g_free(req); status = HAL_STATUS_SUCCESS; failed: ipc_send_rsp(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT, status); }
static void bt_pan_connect(const void *buf, uint16_t len) { const struct hal_cmd_pan_connect *cmd = buf; struct pan_device *dev; uint8_t status; bdaddr_t dst; char addr[18]; GSList *l; GError *gerr = NULL; DBG(""); switch (cmd->local_role) { case HAL_PAN_ROLE_NAP: if (cmd->remote_role != HAL_PAN_ROLE_PANU) { status = HAL_STATUS_UNSUPPORTED; goto failed; } break; case HAL_PAN_ROLE_PANU: if (cmd->remote_role != HAL_PAN_ROLE_NAP && cmd->remote_role != HAL_PAN_ROLE_PANU) { status = HAL_STATUS_UNSUPPORTED; goto failed; } break; default: status = HAL_STATUS_UNSUPPORTED; goto failed; } android2bdaddr(&cmd->bdaddr, &dst); l = g_slist_find_custom(devices, &dst, device_cmp); if (l) { status = HAL_STATUS_FAILED; goto failed; } dev = g_new0(struct pan_device, 1); bacpy(&dev->dst, &dst); local_role = cmd->local_role; dev->role = cmd->remote_role; ba2str(&dev->dst, addr); DBG("connecting to %s %s", addr, dev->iface); dev->io = bt_io_connect(connect_cb, dev, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, &adapter_addr, BT_IO_OPT_DEST_BDADDR, &dev->dst, BT_IO_OPT_PSM, BNEP_PSM, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_OMTU, BNEP_MTU, BT_IO_OPT_IMTU, BNEP_MTU, BT_IO_OPT_INVALID); if (!dev->io) { error("%s", gerr->message); g_error_free(gerr); g_free(dev); status = HAL_STATUS_FAILED; goto failed; } devices = g_slist_append(devices, dev); bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING); status = HAL_STATUS_SUCCESS; failed: ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT, status); }