summaryrefslogtreecommitdiff
path: root/common/usb_i2c.c
diff options
context:
space:
mode:
authorChun-Ta Lin <itspeter@google.com>2017-05-18 14:44:55 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-06-05 07:55:32 -0700
commitd5c08763e12cff3207696ec53232cf6eb3303096 (patch)
treecfa7abd458a477260d2621066bd5af9fed24d2b4 /common/usb_i2c.c
parentce65199e5ed75bf8ab4cc3a4f9abae85f63f1a02 (diff)
downloadchrome-ec-d5c08763e12cff3207696ec53232cf6eb3303096.tar.gz
usb_i2c: extend the protocol to support larger payload
The default USB packet has a maximum size of 64 bytes, however, we need to support some USB over I2C write transaction that exceed this default. To support so with protocol backwards-compatible in mind, we enable a config option CONFIG_USB_I2C_MAX_WRITE_COUNT that will enlarge the USB RX queue. BRANCH=none BUG=b:35587174 TEST=Complete presubmit test. TEST=Manually update elan trackpad firmware with interrupt disabled. Change-Id: Ia8983b036b7297f7ca673459ae34b7e5ecd2ee01 Reviewed-on: https://chromium-review.googlesource.com/513642 Commit-Ready: Chun-ta Lin <itspeter@chromium.org> Tested-by: Chun-ta Lin <itspeter@chromium.org> Reviewed-by: Chun-ta Lin <itspeter@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Diffstat (limited to 'common/usb_i2c.c')
-rw-r--r--common/usb_i2c.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/common/usb_i2c.c b/common/usb_i2c.c
index 4c8350e910..64d7135a89 100644
--- a/common/usb_i2c.c
+++ b/common/usb_i2c.c
@@ -50,12 +50,32 @@ static void usb_i2c_write_packet(struct usb_i2c_config const *config,
QUEUE_ADD_UNITS(config->tx_queue, config->buffer, count);
}
-void usb_i2c_deferred(struct usb_i2c_config const *config)
+static uint8_t usb_i2c_executable(struct usb_i2c_config const *config)
{
/*
- * And if there is a USB packet waiting we process it and generate a
- * response.
+ * In order to support larger write payload, we need to peek
+ * the queue to see if we need to wait for more data.
*/
+
+ uint8_t write_count;
+
+ if (queue_peek_units(config->consumer.queue, &write_count, 2, 1) == 1
+ && (write_count + 4) > queue_count(config->consumer.queue)) {
+ /*
+ * Feed me more data, please.
+ * Reuse the buffer in usb_i2c_config to send ACK packet.
+ */
+ config->buffer[0] = USB_I2C_SUCCESS;
+ config->buffer[1] = 0;
+ usb_i2c_write_packet(config, 4);
+ return 0;
+ }
+ return 1;
+}
+
+void usb_i2c_execute(struct usb_i2c_config const *config)
+{
+ /* Payload is ready to execute. */
uint8_t count = usb_i2c_read_packet(config);
int portindex = (config->buffer[0] >> 0) & 0xff;
/* Convert 7-bit slave address to chromium EC 8-bit address. */
@@ -70,8 +90,8 @@ void usb_i2c_deferred(struct usb_i2c_config const *config)
if (!count || (!read_count && !write_count))
return;
- if (write_count > USB_I2C_MAX_WRITE_COUNT ||
- write_count != (count - 4)) {
+ if (write_count > CONFIG_USB_I2C_MAX_WRITE_COUNT ||
+ write_count != (count - 4)) {
config->buffer[0] = USB_I2C_WRITE_COUNT_INVALID;
} else if (read_count > USB_I2C_MAX_READ_COUNT) {
config->buffer[0] = USB_I2C_READ_COUNT_INVALID;
@@ -86,10 +106,16 @@ void usb_i2c_deferred(struct usb_i2c_config const *config)
(uint8_t *)(config->buffer + 2),
read_count, I2C_XFER_SINGLE));
}
-
usb_i2c_write_packet(config, read_count + 4);
}
+void usb_i2c_deferred(struct usb_i2c_config const *config)
+{
+ /* Check if we can proceed the queue. */
+ if (usb_i2c_executable(config))
+ usb_i2c_execute(config);
+}
+
static void usb_i2c_written(struct consumer const *consumer, size_t count)
{
struct usb_i2c_config const *config =