summaryrefslogtreecommitdiff
path: root/chip/ish/hid_subsys.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/ish/hid_subsys.c')
-rw-r--r--chip/ish/hid_subsys.c447
1 files changed, 0 insertions, 447 deletions
diff --git a/chip/ish/hid_subsys.c b/chip/ish/hid_subsys.c
deleted file mode 100644
index bd3f331fdc..0000000000
--- a/chip/ish/hid_subsys.c
+++ /dev/null
@@ -1,447 +0,0 @@
-/* Copyright 2018 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "compile_time_macros.h"
-#include "console.h"
-#include "heci_client.h"
-#include "hid_device.h"
-#include "util.h"
-
-#ifdef HID_SUBSYS_DEBUG
-#define CPUTS(outstr) cputs(CC_LPC, outstr)
-#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args)
-#else
-#define CPUTS(outstr)
-#define CPRINTS(format, args...)
-#define CPRINTF(format, args...)
-#endif
-
-#define __packed __attribute__((packed))
-
-#define HECI_CLIENT_HID_GUID { 0x33AECD58, 0xB679, 0x4E54,\
- { 0x9B, 0xD9, 0xA0, 0x4D, 0x34, 0xF0, 0xC2, 0x26 } }
-
-#define HID_SUBSYS_MAX_HID_DEVICES 3
-
-/*
- * the following enum values and data structures with __packed are used for
- * communicating with host driver and they are copied from host driver.
- */
-enum {
- HID_GET_HID_DESCRIPTOR = 0,
- HID_GET_REPORT_DESCRIPTOR,
- HID_GET_FEATURE_REPORT,
- HID_SET_FEATURE_REPORT,
- HID_GET_INPUT_REPORT,
- HID_PUBLISH_INPUT_REPORT,
- HID_PUBLISH_INPUT_REPORT_LIST, /* TODO: need to support batch report */
-
- HID_HID_CLIENT_READY_CMD = 30,
- HID_HID_COMMAND_MAX = 31,
-
- HID_DM_COMMAND_BASE,
- HID_DM_ENUM_DEVICES,
- HID_DM_ADD_DEVICE,
- HID_COMMAND_LAST
-};
-
-struct hid_device_info {
- uint32_t dev_id;
- uint8_t dev_class;
- uint16_t pid;
- uint16_t vid;
-} __packed;
-
-struct hid_enum_payload {
- uint8_t num_of_hid_devices;
- struct hid_device_info dev_info[0];
-} __packed;
-
-#define COMMAND_MASK 0x7F
-#define RESPONSE_FLAG 0x80
-struct hid_msg_hdr {
- uint8_t command; /* bit 7 is used to indicate "response" */
- uint8_t device_id;
- uint8_t status;
- uint8_t flags;
- uint16_t size;
-} __packed;
-
-struct hid_msg {
- struct hid_msg_hdr hdr;
- uint8_t payload[HID_SUBSYS_MAX_PAYLOAD_SIZE];
-} __packed;
-
-struct hid_subsys_hid_device {
- struct hid_device_info info;
- const struct hid_callbacks *cbs;
- int can_send_hid_input;
-
- void *data;
-};
-
-struct hid_subsystem {
- heci_handle_t heci_handle;
-
- uint32_t num_of_hid_devices;
- struct hid_subsys_hid_device hid_devices[HID_SUBSYS_MAX_HID_DEVICES];
-};
-
-static struct hid_subsystem hid_subsys_ctx = {
- .heci_handle = HECI_INVALID_HANDLE,
-};
-
-#define handle_to_dev_id(_handle) ((uintptr_t)(_handle))
-#define dev_id_to_handle(_dev_id) ((hid_handle_t)(uintptr_t)(_dev_id))
-
-static inline hid_handle_t device_index_to_handle(int device_index)
-{
- return (hid_handle_t)(uintptr_t)(device_index + 1);
-}
-
-static inline int is_valid_handle(hid_handle_t handle)
-{
- return (uintptr_t)handle > 0 &&
- (uintptr_t)handle <= hid_subsys_ctx.num_of_hid_devices;
-}
-
-static inline
-struct hid_subsys_hid_device *handle_to_hid_device(hid_handle_t handle)
-{
- if (!is_valid_handle(handle))
- return NULL;
-
- return &hid_subsys_ctx.hid_devices[(uintptr_t)handle - 1];
-}
-
-
-hid_handle_t hid_subsys_register_device(const struct hid_device *dev_info)
-{
- struct hid_subsys_hid_device *hid_device;
- hid_handle_t handle;
- int ret, hid_device_index;
-
- if (hid_subsys_ctx.num_of_hid_devices >= HID_SUBSYS_MAX_HID_DEVICES)
- return HID_INVALID_HANDLE;
-
- hid_device_index = hid_subsys_ctx.num_of_hid_devices++;
-
- handle = device_index_to_handle(hid_device_index);
-
- hid_device = &hid_subsys_ctx.hid_devices[hid_device_index];
-
- hid_device->info.dev_class = dev_info->dev_class;
- hid_device->info.pid = dev_info->pid;
- hid_device->info.vid = dev_info->vid;
- hid_device->info.dev_id = handle_to_dev_id(handle);
-
- hid_device->cbs = dev_info->cbs;
-
- if (dev_info->cbs->initialize) {
- ret = dev_info->cbs->initialize(handle);
- if (ret) {
- CPRINTF("initialize error %d\n", ret);
- hid_subsys_ctx.num_of_hid_devices--;
- return HID_INVALID_HANDLE;
- }
- }
-
- return handle;
-}
-
-int hid_subsys_send_input_report(const hid_handle_t handle, uint8_t *buf,
- const size_t buf_size)
-{
- struct hid_subsys_hid_device *hid_device;
- struct hid_msg_hdr hid_msg_hdr = {0};
- struct heci_msg_item msg_item[2];
- struct heci_msg_list msg_list;
-
- hid_device = handle_to_hid_device(handle);
- if (!hid_device)
- return -EC_ERROR_INVAL;
-
- if (buf_size > HID_SUBSYS_MAX_PAYLOAD_SIZE)
- return -EC_ERROR_OVERFLOW;
-
- if (hid_subsys_ctx.heci_handle == HECI_INVALID_HANDLE)
- return -HID_SUBSYS_ERR_NOT_READY;
-
- if (!hid_device->can_send_hid_input)
- return -HID_SUBSYS_ERR_NOT_READY;
-
- hid_msg_hdr.command = HID_PUBLISH_INPUT_REPORT;
- hid_msg_hdr.device_id = hid_device->info.dev_id;
- hid_msg_hdr.size = buf_size;
-
- msg_item[0].size = sizeof(hid_msg_hdr);
- msg_item[0].buf = (uint8_t *)&hid_msg_hdr;
-
- msg_item[1].size = buf_size;
- msg_item[1].buf = buf;
-
- msg_list.num_of_items = 2;
- msg_list.items[0] = &msg_item[0];
- msg_list.items[1] = &msg_item[1];
-
- heci_send_msgs(hid_subsys_ctx.heci_handle, &msg_list);
-
- return 0;
-}
-
-int hid_subsys_set_device_data(const hid_handle_t handle, void *data)
-{
- struct hid_subsys_hid_device *hid_device;
-
- hid_device = handle_to_hid_device(handle);
- if (!hid_device)
- return -EC_ERROR_INVAL;
-
- hid_device->data = data;
-
- return 0;
-}
-
-void *hid_subsys_get_device_data(const hid_handle_t handle)
-{
- struct hid_subsys_hid_device *hid_device;
-
- hid_device = handle_to_hid_device(handle);
- if (!hid_device)
- return NULL;
-
- return hid_device->data;
-}
-
-static int handle_hid_device_msg(struct hid_msg *hid_msg)
-{
- int ret = 0, payload_size, buf_size;
- uint8_t *payload;
- struct hid_subsys_hid_device *hid_dev;
- const struct hid_callbacks *cbs;
- hid_handle_t handle;
-
- handle = dev_id_to_handle(hid_msg->hdr.device_id);
- hid_dev = handle_to_hid_device(handle);
-
- if (!hid_dev) {
- /*
- * use HID_HID_COMMAND_MAX as error message.
- * host driver will reset ISH.
- */
- hid_msg->hdr.size = 0;
- hid_msg->hdr.status = 0;
- hid_msg->hdr.command |= RESPONSE_FLAG | HID_HID_COMMAND_MAX;
- hid_msg->hdr.flags = 0;
-
- heci_send_msg(hid_subsys_ctx.heci_handle, (uint8_t *)hid_msg,
- sizeof(hid_msg->hdr));
-
- return 0;
- }
-
- cbs = hid_dev->cbs;
-
- payload = hid_msg->payload;
- payload_size = hid_msg->hdr.size; /* input data */
- buf_size = sizeof(hid_msg->payload); /* buffer to be written by cb */
-
- /*
- * re-use hid_msg from host for reply.
- */
- switch (hid_msg->hdr.command & COMMAND_MASK) {
- case HID_GET_HID_DESCRIPTOR:
- if (cbs->get_hid_descriptor)
- ret = cbs->get_hid_descriptor(handle, payload,
- buf_size);
-
- break;
- case HID_GET_REPORT_DESCRIPTOR:
- if (cbs->get_report_descriptor)
- ret = cbs->get_report_descriptor(handle, payload,
- buf_size);
-
- hid_dev->can_send_hid_input = 1;
-
- break;
-
- case HID_GET_FEATURE_REPORT:
- if (cbs->get_feature_report)
- ret = cbs->get_feature_report(handle, payload[0],
- payload, buf_size);
-
- break;
-
- case HID_SET_FEATURE_REPORT:
- if (cbs->set_feature_report) {
- ret = cbs->set_feature_report(handle,
- payload[0],
- payload,
- payload_size);
- /*
- * if no error, reply only with the report id.
- * re-use the first byte of payload
- * from host that has report id
- */
- if (ret >= 0)
- ret = sizeof(uint8_t);
- }
-
- break;
- case HID_GET_INPUT_REPORT:
- if (cbs->get_input_report)
- ret = cbs->get_input_report(handle, payload[0],
- payload, buf_size);
-
- break;
-
- default:
- CPRINTF("invalid hid command %d, ignoring request\n",
- hid_msg->hdr.command & COMMAND_MASK);
- ret = -1; /* send error */
- }
-
- if (ret > 0) {
- hid_msg->hdr.size = ret;
- hid_msg->hdr.status = 0;
- } else { /* error in callback */
- /*
- * Note : errors of HID device should be transferred
- * through their HID formatted data.
- */
- hid_msg->hdr.size = 0;
- hid_msg->hdr.status = -ret;
- }
-
- hid_msg->hdr.command |= RESPONSE_FLAG;
- hid_msg->hdr.flags = 0;
-
- heci_send_msg(hid_subsys_ctx.heci_handle, (uint8_t *)hid_msg,
- sizeof(hid_msg->hdr) + hid_msg->hdr.size);
-
- return 0;
-}
-
-static int handle_hid_subsys_msg(struct hid_msg *hid_msg)
-{
- int size = 0, i;
- struct hid_enum_payload *enum_payload;
-
- switch (hid_msg->hdr.command & COMMAND_MASK) {
- case HID_DM_ENUM_DEVICES:
- enum_payload = (struct hid_enum_payload *)hid_msg->payload;
-
- for (i = 0; i < hid_subsys_ctx.num_of_hid_devices; i++) {
- enum_payload->dev_info[i] =
- hid_subsys_ctx.hid_devices[i].info;
- }
-
- enum_payload->num_of_hid_devices =
- hid_subsys_ctx.num_of_hid_devices;
-
- /* reply payload size */
- size = sizeof(enum_payload->num_of_hid_devices);
- size += enum_payload->num_of_hid_devices *
- sizeof(enum_payload->dev_info[0]);
-
- break;
-
- default:
- CPRINTF("invalid hid command %d, ignoring request\n",
- hid_msg->hdr.command & COMMAND_MASK);
- size = -1; /* send error */
- }
-
- if (size > 0) {
- hid_msg->hdr.size = size;
- hid_msg->hdr.status = 0;
- } else { /* error in callback */
- hid_msg->hdr.size = 0;
- hid_msg->hdr.status = -size;
- }
-
- hid_msg->hdr.command |= RESPONSE_FLAG;
- hid_msg->hdr.flags = 0;
-
- heci_send_msg(hid_subsys_ctx.heci_handle, (uint8_t *)hid_msg,
- sizeof(hid_msg->hdr) + hid_msg->hdr.size);
-
- return 0;
-}
-
-static void hid_subsys_new_msg_received(const heci_handle_t handle,
- uint8_t *msg, const size_t msg_size)
-{
- struct hid_msg *hid_msg = (struct hid_msg *)msg;
-
- /* workaround, since Host driver doesn't set size properly */
- if (hid_msg->hdr.size == 0 && msg_size > sizeof(hid_msg->hdr))
- hid_msg->hdr.size = msg_size - sizeof(hid_msg->hdr);
-
- if (hid_msg->hdr.size > HID_SUBSYS_MAX_PAYLOAD_SIZE) {
- CPRINTF("too big payload size : %d. discard heci msg\n",
- hid_msg->hdr);
- return; /* invalid hdr. discard */
- }
-
- if (hid_msg->hdr.device_id)
- handle_hid_device_msg(hid_msg);
- else
- handle_hid_subsys_msg(hid_msg);
-}
-
-static int hid_subsys_initialize(const heci_handle_t heci_handle)
-{
- hid_subsys_ctx.heci_handle = heci_handle;
-
- return 0;
-}
-
-/* return zero if resume request handled successfully */
-static int hid_subsys_resume(const heci_handle_t heci_handle)
-{
- int i, ret = 0;
-
- for (i = 0; i < hid_subsys_ctx.num_of_hid_devices; i++) {
- if (hid_subsys_ctx.hid_devices[i].cbs->resume)
- ret |= hid_subsys_ctx.hid_devices[i].cbs->resume(
- device_index_to_handle(i));
- }
-
- return ret;
-}
-
-/* return zero if suspend request handled successfully */
-static int hid_subsys_suspend(const heci_handle_t heci_handle)
-{
- int i, ret = 0;
-
- for (i = hid_subsys_ctx.num_of_hid_devices - 1; i >= 0; i--) {
- if (hid_subsys_ctx.hid_devices[i].cbs->suspend)
- ret |= hid_subsys_ctx.hid_devices[i].cbs->suspend(
- device_index_to_handle(i));
- }
-
- return ret;
-}
-
-static const struct heci_client_callbacks hid_subsys_heci_cbs = {
- .initialize = hid_subsys_initialize,
- .new_msg_received = hid_subsys_new_msg_received,
- .suspend = hid_subsys_suspend,
- .resume = hid_subsys_resume,
-};
-
-static const struct heci_client hid_subsys_heci_client = {
- .protocol_id = HECI_CLIENT_HID_GUID,
- .max_msg_size = HECI_MAX_MSG_SIZE,
- .protocol_ver = 1,
- .max_n_of_connections = 1,
-
- .cbs = &hid_subsys_heci_cbs,
-};
-
-HECI_CLIENT_ENTRY(hid_subsys_heci_client);