summaryrefslogtreecommitdiff
path: root/common/mkbp_event.c
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-10-20 23:31:28 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-24 01:37:58 +0000
commitd1ed75815efe513449c653d28fe7bd3c53a3441d (patch)
tree48a256c4154ad8f195ef5447abce6eeb99e3fd42 /common/mkbp_event.c
parentbe2ed33b1976e407d107b20e90441a194f7b5fb7 (diff)
downloadchrome-ec-d1ed75815efe513449c653d28fe7bd3c53a3441d.tar.gz
MKBP event signalling implementation
This implements a new API for EC modules to define MKBP event sources and send MKBP event to the AP. Also, a new host command EC_CMD_GET_NEXT_EVENT is added for the AP to query the pending MKBP events. Each event type may have custom event data sent along with the event. BRANCH=None BUG=chrome-os-partner:33194 TEST=Enable MKBP event on Ryu. Set a host event from EC console, run 'ectool nextevent', and see MKBP event 0x01 (HOST_EVENT) and the set host event. Signed-off-by: Vic Yang <victoryang@chromium.org> Change-Id: I28a1b7e826bcc102bbe39016c9bb3e37d125664c Reviewed-on: https://chromium-review.googlesource.com/224905 Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'common/mkbp_event.c')
-rw-r--r--common/mkbp_event.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/common/mkbp_event.c b/common/mkbp_event.c
new file mode 100644
index 0000000000..d78db48a2d
--- /dev/null
+++ b/common/mkbp_event.c
@@ -0,0 +1,95 @@
+/* Copyright (c) 2014 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.
+ *
+ * Event handling in MKBP keyboard protocol
+ */
+
+#include "atomic.h"
+#include "gpio.h"
+#include "host_command.h"
+#include "link_defs.h"
+#include "mkbp_event.h"
+#include "util.h"
+
+static uint32_t events;
+
+static void set_event(uint8_t event_type)
+{
+ atomic_or(&events, 1 << event_type);
+}
+
+static void clear_event(uint8_t event_type)
+{
+ atomic_clear(&events, 1 << event_type);
+}
+
+static int event_is_set(uint8_t event_type)
+{
+ return events & (1 << event_type);
+}
+
+/**
+ * Assert host keyboard interrupt line.
+ */
+static void set_host_interrupt(int active)
+{
+ /* interrupt host by using active low EC_INT signal */
+ gpio_set_level(GPIO_EC_INT, !active);
+}
+
+void mkbp_send_event(uint8_t event_type)
+{
+ set_event(event_type);
+ set_host_interrupt(1);
+}
+
+static int mkbp_get_next_event(struct host_cmd_handler_args *args)
+{
+ static int last;
+ int i, data_size, evt;
+ uint8_t *resp = args->response;
+ const struct mkbp_event_source *src;
+
+ /*
+ * Find the next event to service. We do this in a round-robin
+ * way to make sure no event gets starved.
+ */
+ for (i = 0; i < EC_MKBP_EVENT_COUNT; ++i)
+ if (event_is_set((last + i) % EC_MKBP_EVENT_COUNT))
+ break;
+
+ if (i == EC_MKBP_EVENT_COUNT)
+ return EC_RES_ERROR;
+
+ evt = (i + last) % EC_MKBP_EVENT_COUNT;
+ last = evt + 1;
+
+ /*
+ * Clear the event before retrieving the event data in case the
+ * event source wants to send the same event.
+ */
+ clear_event(evt);
+
+ for (src = __mkbp_evt_srcs; src < __mkbp_evt_srcs_end; ++src)
+ if (src->event_type == evt)
+ break;
+
+ if (src == __mkbp_evt_srcs_end)
+ return EC_RES_ERROR;
+
+ resp[0] = evt; /* Event type */
+ data_size = src->get_data(resp + 1);
+ if (data_size < 0)
+ return EC_RES_ERROR;
+ args->response_size = 1 + data_size;
+
+ if (!events)
+ set_host_interrupt(0);
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_GET_NEXT_EVENT,
+ mkbp_get_next_event,
+ EC_VER_MASK(0));
+