diff options
author | Vic Yang <victoryang@chromium.org> | 2014-10-20 23:31:28 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-10-24 01:37:58 +0000 |
commit | d1ed75815efe513449c653d28fe7bd3c53a3441d (patch) | |
tree | 48a256c4154ad8f195ef5447abce6eeb99e3fd42 /common/mkbp_event.c | |
parent | be2ed33b1976e407d107b20e90441a194f7b5fb7 (diff) | |
download | chrome-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.c | 95 |
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)); + |