| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- // SPDX-License-Identifier: Apache-2.0
- /*
- * Copyright (C) 2013 Intel Corporation
- *
- */
- #include <stdbool.h>
- #include <stddef.h>
- #include <string.h>
- #include <stdlib.h>
- #include "hal-log.h"
- #include "hal.h"
- #include "hal-msg.h"
- #include "ipc-common.h"
- #include "hal-ipc.h"
- static const bthh_callbacks_t *cbacks;
- static bool interface_ready(void)
- {
- return cbacks != NULL;
- }
- static void handle_conn_state(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_hidhost_conn_state *ev = buf;
- if (cbacks->connection_state_cb)
- cbacks->connection_state_cb((bt_bdaddr_t *) ev->bdaddr,
- ev->state);
- }
- static void handle_info(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_hidhost_info *ev = buf;
- bthh_hid_info_t info;
- info.attr_mask = ev->attr;
- info.sub_class = ev->subclass;
- info.app_id = ev->app_id;
- info.vendor_id = ev->vendor;
- info.product_id = ev->product;
- info.version = ev->version;
- info.ctry_code = ev->country;
- info.dl_len = ev->descr_len;
- memcpy(info.dsc_list, ev->descr, info.dl_len);
- if (cbacks->hid_info_cb)
- cbacks->hid_info_cb((bt_bdaddr_t *) ev->bdaddr, info);
- }
- static void handle_proto_mode(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_hidhost_proto_mode *ev = buf;
- if (cbacks->protocol_mode_cb)
- cbacks->protocol_mode_cb((bt_bdaddr_t *) ev->bdaddr,
- ev->status, ev->mode);
- }
- static void handle_idle_time(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_hidhost_idle_time *ev = buf;
- if (cbacks->idle_time_cb)
- cbacks->idle_time_cb((bt_bdaddr_t *) ev->bdaddr, ev->status,
- ev->idle_rate);
- }
- static void handle_get_report(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_hidhost_get_report *ev = buf;
- if (len != sizeof(*ev) + ev->len) {
- error("invalid get report event, aborting");
- exit(EXIT_FAILURE);
- }
- if (cbacks->get_report_cb)
- cbacks->get_report_cb((bt_bdaddr_t *) ev->bdaddr, ev->status,
- ev->data, ev->len);
- }
- static void handle_virtual_unplug(void *buf, uint16_t len, int fd)
- {
- struct hal_ev_hidhost_virtual_unplug *ev = buf;
- if (cbacks->virtual_unplug_cb)
- cbacks->virtual_unplug_cb((bt_bdaddr_t *) ev->bdaddr,
- ev->status);
- }
- static void handle_handshake(void *buf, uint16_t len, int fd)
- {
- #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
- struct hal_ev_hidhost_handshake *ev = buf;
- if (cbacks->handshake_cb)
- cbacks->handshake_cb((bt_bdaddr_t *) ev->bdaddr, ev->status);
- #endif
- }
- /*
- * handlers will be called from notification thread context,
- * index in table equals to 'opcode - HAL_MINIMUM_EVENT'
- */
- static const struct hal_ipc_handler ev_handlers[] = {
- /* HAL_EV_HIDHOST_CONN_STATE */
- { handle_conn_state, false, sizeof(struct hal_ev_hidhost_conn_state) },
- /* HAL_EV_HIDHOST_INFO */
- { handle_info, false, sizeof(struct hal_ev_hidhost_info) },
- /* HAL_EV_HIDHOST_PROTO_MODE */
- { handle_proto_mode, false, sizeof(struct hal_ev_hidhost_proto_mode) },
- /* HAL_EV_HIDHOST_IDLE_TIME */
- { handle_idle_time, false, sizeof(struct hal_ev_hidhost_idle_time) },
- /* HAL_EV_HIDHOST_GET_REPORT */
- { handle_get_report, true, sizeof(struct hal_ev_hidhost_get_report) },
- /* HAL_EV_HIDHOST_VIRTUAL_UNPLUG */
- { handle_virtual_unplug, false,
- sizeof(struct hal_ev_hidhost_virtual_unplug) },
- { handle_handshake, false, sizeof(struct hal_ev_hidhost_handshake) },
- };
- static bt_status_t hidhost_connect(bt_bdaddr_t *bd_addr)
- {
- struct hal_cmd_hidhost_connect cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_CONNECT,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t disconnect(bt_bdaddr_t *bd_addr)
- {
- struct hal_cmd_hidhost_disconnect cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_DISCONNECT,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t virtual_unplug(bt_bdaddr_t *bd_addr)
- {
- struct hal_cmd_hidhost_virtual_unplug cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST,
- HAL_OP_HIDHOST_VIRTUAL_UNPLUG,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t set_info(bt_bdaddr_t *bd_addr, bthh_hid_info_t hid_info)
- {
- struct hal_cmd_hidhost_set_info cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
- cmd.attr = hid_info.attr_mask;
- cmd.subclass = hid_info.sub_class;
- cmd.app_id = hid_info.app_id;
- cmd.vendor = hid_info.vendor_id;
- cmd.product = hid_info.product_id;
- cmd.country = hid_info.ctry_code;
- cmd.descr_len = hid_info.dl_len;
- memcpy(cmd.descr, hid_info.dsc_list, cmd.descr_len);
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_INFO,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t get_protocol(bt_bdaddr_t *bd_addr,
- bthh_protocol_mode_t protocol_mode)
- {
- struct hal_cmd_hidhost_get_protocol cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
- /* type match IPC type */
- cmd.mode = protocol_mode;
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST,
- HAL_OP_HIDHOST_GET_PROTOCOL,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t set_protocol(bt_bdaddr_t *bd_addr,
- bthh_protocol_mode_t protocol_mode)
- {
- struct hal_cmd_hidhost_set_protocol cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
- /* type match IPC type */
- cmd.mode = protocol_mode;
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST,
- HAL_OP_HIDHOST_SET_PROTOCOL,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t get_report(bt_bdaddr_t *bd_addr,
- bthh_report_type_t report_type,
- uint8_t report_id,
- int buffer_size)
- {
- struct hal_cmd_hidhost_get_report cmd;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
- cmd.id = report_id;
- cmd.buf_size = buffer_size;
- /* type match IPC type */
- cmd.type = report_type;
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_GET_REPORT,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- }
- static bt_status_t set_report(bt_bdaddr_t *bd_addr,
- bthh_report_type_t report_type,
- char *report)
- {
- uint8_t buf[IPC_MTU];
- struct hal_cmd_hidhost_set_report *cmd = (void *) buf;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr || !report)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
- cmd->len = strlen(report);
- memcpy(cmd->data, report, cmd->len);
- /* type match IPC type */
- cmd->type = report_type;
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SET_REPORT,
- sizeof(*cmd) + cmd->len, buf, NULL, NULL, NULL);
- }
- static bt_status_t send_data(bt_bdaddr_t *bd_addr, char *data)
- {
- uint8_t buf[IPC_MTU];
- struct hal_cmd_hidhost_send_data *cmd = (void *) buf;
- DBG("");
- if (!interface_ready())
- return BT_STATUS_NOT_READY;
- if (!bd_addr || !data)
- return BT_STATUS_PARM_INVALID;
- memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
- cmd->len = strlen(data);
- memcpy(cmd->data, data, cmd->len);
- return hal_ipc_cmd(HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_SEND_DATA,
- sizeof(*cmd) + cmd->len, buf, NULL, NULL, NULL);
- }
- static bt_status_t init(bthh_callbacks_t *callbacks)
- {
- struct hal_cmd_register_module cmd;
- int ret;
- DBG("");
- if (interface_ready())
- return BT_STATUS_DONE;
- /* store reference to user callbacks */
- cbacks = callbacks;
- hal_ipc_register(HAL_SERVICE_ID_HIDHOST, ev_handlers,
- sizeof(ev_handlers)/sizeof(ev_handlers[0]));
- cmd.service_id = HAL_SERVICE_ID_HIDHOST;
- cmd.mode = HAL_MODE_DEFAULT;
- cmd.max_clients = 1;
- ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- if (ret != BT_STATUS_SUCCESS) {
- cbacks = NULL;
- hal_ipc_unregister(HAL_SERVICE_ID_HIDHOST);
- }
- return ret;
- }
- static void cleanup(void)
- {
- struct hal_cmd_unregister_module cmd;
- DBG("");
- if (!interface_ready())
- return;
- cmd.service_id = HAL_SERVICE_ID_HIDHOST;
- hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
- sizeof(cmd), &cmd, NULL, NULL, NULL);
- hal_ipc_unregister(HAL_SERVICE_ID_HIDHOST);
- cbacks = NULL;
- }
- static bthh_interface_t hidhost_if = {
- .size = sizeof(hidhost_if),
- .init = init,
- .connect = hidhost_connect,
- .disconnect = disconnect,
- .virtual_unplug = virtual_unplug,
- .set_info = set_info,
- .get_protocol = get_protocol,
- .set_protocol = set_protocol,
- .get_report = get_report,
- .set_report = set_report,
- .send_data = send_data,
- .cleanup = cleanup
- };
- bthh_interface_t *bt_get_hidhost_interface(void)
- {
- return &hidhost_if;
- }
|