mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-02 13:14:51 +00:00
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>
This commit is contained in:
@@ -128,6 +128,10 @@
|
||||
#define CONFIG_BOARD_PRE_INIT
|
||||
#define CONFIG_WATCHDOG_HELP
|
||||
|
||||
/* Enlarge the allowed write count */
|
||||
#undef CONFIG_USB_I2C_MAX_WRITE_COUNT
|
||||
#define CONFIG_USB_I2C_MAX_WRITE_COUNT 124
|
||||
|
||||
/* No lid switch */
|
||||
#undef CONFIG_LID_SWITCH
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -2646,6 +2646,9 @@
|
||||
/* USB I2C config */
|
||||
#undef CONFIG_USB_I2C
|
||||
|
||||
/* Allowed write count for USB over I2C */
|
||||
#define CONFIG_USB_I2C_MAX_WRITE_COUNT 60
|
||||
|
||||
/*****************************************************************************/
|
||||
/* USB Power monitoring interface config */
|
||||
#undef CONFIG_USB_POWER
|
||||
|
||||
@@ -23,12 +23,13 @@
|
||||
*
|
||||
* slave address: 1 byte, i2c 7-bit bus address
|
||||
*
|
||||
* write count: 1 byte, zero based count of bytes to write
|
||||
* write count: 1 byte, zero based count of bytes to write. If write
|
||||
* count exceed 60 bytes, following packets are expected
|
||||
* to continue the payload without header.
|
||||
*
|
||||
* read count: 1 byte, zero based count of bytes to read
|
||||
*
|
||||
* data: write payload up to 60 bytes of data to write,
|
||||
* length must match write count
|
||||
* data: payload of data to write.
|
||||
*
|
||||
* Response:
|
||||
* +-------------+---+---+-----------------------+
|
||||
@@ -41,7 +42,7 @@
|
||||
* 0x0002: Busy, try again
|
||||
* This can happen if someone else has acquired the shared memory
|
||||
* buffer that the I2C driver uses as /dev/null
|
||||
* 0x0003: Write count invalid (> 60 bytes, or mismatch with payload)
|
||||
* 0x0003: Write count invalid (mismatch with merged payload)
|
||||
* 0x0004: Read count invalid (> 60 bytes)
|
||||
* 0x0005: The port specified is invalid.
|
||||
* 0x8000: Unknown error mask
|
||||
@@ -63,10 +64,11 @@ enum usb_i2c_error {
|
||||
};
|
||||
|
||||
|
||||
#define USB_I2C_MAX_WRITE_COUNT 60
|
||||
#define USB_I2C_MAX_READ_COUNT 60
|
||||
#define USB_I2C_CONFIG_BUFFER_SIZE \
|
||||
((CONFIG_USB_I2C_MAX_WRITE_COUNT+4) > USB_MAX_PACKET_SIZE ? \
|
||||
(CONFIG_USB_I2C_MAX_WRITE_COUNT+4) : USB_MAX_PACKET_SIZE)
|
||||
|
||||
BUILD_ASSERT(USB_MAX_PACKET_SIZE == (1 + 1 + 1 + 1 + USB_I2C_MAX_WRITE_COUNT));
|
||||
BUILD_ASSERT(USB_MAX_PACKET_SIZE == (2 + 1 + 1 + USB_I2C_MAX_READ_COUNT));
|
||||
|
||||
/*
|
||||
@@ -105,7 +107,8 @@ extern struct consumer_ops const usb_i2c_consumer_ops;
|
||||
INTERFACE_NAME, \
|
||||
ENDPOINT) \
|
||||
static uint16_t \
|
||||
CONCAT2(NAME, _buffer_)[USB_MAX_PACKET_SIZE/2]; \
|
||||
CONCAT2(NAME, _buffer_) \
|
||||
[USB_I2C_CONFIG_BUFFER_SIZE / 2]; \
|
||||
static void CONCAT2(NAME, _deferred_)(void); \
|
||||
DECLARE_DEFERRED(CONCAT2(NAME, _deferred_)); \
|
||||
static struct queue const CONCAT2(NAME, _to_usb_); \
|
||||
@@ -134,7 +137,7 @@ extern struct consumer_ops const usb_i2c_consumer_ops;
|
||||
QUEUE_DIRECT(USB_MAX_PACKET_SIZE, uint8_t, \
|
||||
null_producer, CONCAT2(NAME, _usb_).consumer); \
|
||||
static struct queue const CONCAT3(usb_to_, NAME, _) = \
|
||||
QUEUE_DIRECT(USB_MAX_PACKET_SIZE, uint8_t, \
|
||||
QUEUE_DIRECT(CONFIG_USB_I2C_MAX_WRITE_COUNT+4, uint8_t, \
|
||||
CONCAT2(NAME, _usb_).producer, NAME.consumer); \
|
||||
static void CONCAT2(NAME, _deferred_)(void) \
|
||||
{ usb_i2c_deferred(&NAME); }
|
||||
|
||||
Reference in New Issue
Block a user