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);
}
Ejemplo n.º 3
0
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);
}