Files
OpenCellular/common/message.c
Simon Glass 220a5a496d Update keyboard scanning for stm32 to use messages
Provide the required plumbing for the stm32 keyboard scan code so that
the message layer will pick up keyboard scans.

The design is as follows:
- When a change in keyboard state is detected, the keyboard matrix
  scanning code will call the board-specific board_keyboard_scan_ready()
  function to interrupt the AP.
- The AP will initiate a CMDC_KEY_STATE transaction over SPI or I2C
- The SPI or I2C driver will call message_process_cmd() to process the
  command
- This in turn will call keyboard_get_scan() to get the latest scan data

For SPI:
- The AP will initiate an 20-byte (or longer) SPI transaction
- The EC will see the command, and provide the keyboard state in response,
  with the response being part of the same transaction

For I2C:
- The AP will initiate a 1-byte write to set the EC mode.
- The AP will then initiate an 18-byte read, and the EC will send the
  message including keyboard state

BUG=chromium-os:28925
TEST=build on daisy and discovery; run on daisy
Change-Id: I905ef9d567e43d85fb851052f67586eff58e1167
Signed-off-by: Simon Glass <sjg@chromium.org>
2012-04-11 16:28:53 -07:00

94 lines
2.2 KiB
C

/*
* This handles incoming commands and provides responses.
*
* Copyright (c) 2012 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.
*
* EC <--> AP message handling.
*/
#include "board.h"
#include "message.h"
#include "keyboard_scan.h"
#include "util.h"
/* Our ID message - Matrix KeyBoard Protocol */
static const char proto_id[] = "Google Chrome MKBP v1";
/**
* Get the response to a given command
*
* @param cmd Command byte to respond to
* @param buffp Buffer to use for data, or it can be updated to
* point to a new buffer
* @param max_len Number of bytes free at *buffp for the response.
* If the supplied buffer is used, this size must not
* be exceeded.
* @return number of bytes in response (which is in *buffp), or -1 on error
*/
static int message_get_response(int cmd, uint8_t **buffp, int max_len)
{
/*
* Invalid commands are ignored, just returning a stream of 0xff
* bytes.
*/
switch (cmd & MSG_CMD_MASK) {
case CMDC_NOP:
return 0;
case CMDC_ID:
*buffp = (char *)proto_id;
return sizeof(proto_id) - 1;
case CMDC_KEY_STATE:
return keyboard_get_scan(buffp, max_len);
default:
return -1;
}
return 0;
}
int message_process_cmd(int cmd, uint8_t *out_msg, int max_len)
{
uint8_t *msg;
int msg_len;
int need_copy;
int sum = 0;
int len;
int i;
msg = out_msg + MSG_HEADER_BYTES;
msg_len = message_get_response(cmd, &msg, max_len - MSG_PROTO_BYTES);
if (msg_len < 0)
return msg_len;
/*
* We add MSG_PROTO_BYTES bytes of overhead: truncate the reply
* if needed.
*/
if (msg_len + MSG_PROTO_BYTES > max_len)
msg_len = max_len - MSG_PROTO_BYTES;
len = msg_len + 4;
ASSERT(msg_len >= 0 && msg_len < 0xffff);
need_copy = msg != out_msg + MSG_HEADER_BYTES;
ASSERT(!need_copy ||
msg + msg_len < out_msg ||
msg > out_msg + sizeof(out_msg));
out_msg[0] = MSG_HEADER;
out_msg[1] = len & 0xff;
out_msg[2] = (len >> 8) & 0xff;
sum += MSG_HEADER + len + (len >> 8);
for (i = 0; i < msg_len; i++) {
if (need_copy)
out_msg[i + 3] = *msg;
sum += *msg;
}
out_msg[i + 3] = sum & 0xff;
out_msg[i + 4] = MSG_PREAMBLE;
return msg_len + MSG_PROTO_BYTES;
}