summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2013-09-26 17:39:40 +0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-09-27 04:33:33 +0000
commit4de56d4a7f2fb9fb459f31a8e8f1616e54852157 (patch)
tree1b35b453482fe64a0d43a81df0af9a6f7373e413
parent09de4c720d790a7243808e82264e8a1bb122a99d (diff)
downloadchrome-ec-4de56d4a7f2fb9fb459f31a8e8f1616e54852157.tar.gz
Test interface for detaching fake I2C devices
This provides an interface to detach and re-attach fake I2C devices, which can be used to test I2C connection failure. BUG=chrome-os-partner:19235 TEST=Pass sbs_charging test along with the next CL BRANCH=None Change-Id: Ibfee79b13d45e62377d894aa28547e77bef2189e Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/170752 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--chip/host/i2c.c76
-rw-r--r--include/test_util.h21
2 files changed, 97 insertions, 0 deletions
diff --git a/chip/host/i2c.c b/chip/host/i2c.c
index 072d4564f8..3f8a8b8241 100644
--- a/chip/host/i2c.c
+++ b/chip/host/i2c.c
@@ -5,15 +5,83 @@
* Dummy I2C driver for unit test.
*/
+#include "hooks.h"
#include "i2c.h"
#include "link_defs.h"
#include "test_util.h"
+#define MAX_DETACHED_DEV_COUNT 3
+
+struct i2c_dev {
+ int port;
+ int slave_addr;
+ int valid;
+};
+
+static struct i2c_dev detached_devs[MAX_DETACHED_DEV_COUNT];
+
+static void detach_init(void)
+{
+ int i;
+ for (i = 0; i < MAX_DETACHED_DEV_COUNT; ++i)
+ detached_devs[i].valid = 0;
+}
+DECLARE_HOOK(HOOK_INIT, detach_init, HOOK_PRIO_FIRST);
+
+int test_detach_i2c(int port, int slave_addr)
+{
+ int i;
+
+ for (i = 0; i < MAX_DETACHED_DEV_COUNT; ++i)
+ if (detached_devs[i].valid == 0)
+ break;
+
+ if (i == MAX_DETACHED_DEV_COUNT)
+ return EC_ERROR_OVERFLOW;
+
+ detached_devs[i].port = port;
+ detached_devs[i].slave_addr = slave_addr;
+ detached_devs[i].valid = 1;
+
+ return EC_SUCCESS;
+}
+
+int test_attach_i2c(int port, int slave_addr)
+{
+ int i;
+
+ for (i = 0; i < MAX_DETACHED_DEV_COUNT; ++i)
+ if (detached_devs[i].valid &&
+ detached_devs[i].port == port &&
+ detached_devs[i].slave_addr == slave_addr)
+ break;
+
+ if (i == MAX_DETACHED_DEV_COUNT)
+ return EC_ERROR_INVAL;
+
+ detached_devs[i].valid = 0;
+ return EC_SUCCESS;
+}
+
+static int test_check_detached(int port, int slave_addr)
+{
+ int i;
+
+ for (i = 0; i < MAX_DETACHED_DEV_COUNT; ++i)
+ if (detached_devs[i].valid &&
+ detached_devs[i].port == port &&
+ detached_devs[i].slave_addr == slave_addr)
+ return 1;
+ return 0;
+}
+
int i2c_read16(int port, int slave_addr, int offset, int *data)
{
const struct test_i2c_read_dev *p;
int rv;
+ if (test_check_detached(port, slave_addr))
+ return EC_ERROR_UNKNOWN;
for (p = __test_i2c_read16; p < __test_i2c_read16_end; ++p) {
rv = p->routine(port, slave_addr, offset, data);
if (rv != EC_ERROR_INVAL)
@@ -27,6 +95,8 @@ int i2c_write16(int port, int slave_addr, int offset, int data)
const struct test_i2c_write_dev *p;
int rv;
+ if (test_check_detached(port, slave_addr))
+ return EC_ERROR_UNKNOWN;
for (p = __test_i2c_write16; p < __test_i2c_write16_end; ++p) {
rv = p->routine(port, slave_addr, offset, data);
if (rv != EC_ERROR_INVAL)
@@ -40,6 +110,8 @@ int i2c_read8(int port, int slave_addr, int offset, int *data)
const struct test_i2c_read_dev *p;
int rv;
+ if (test_check_detached(port, slave_addr))
+ return EC_ERROR_UNKNOWN;
for (p = __test_i2c_read8; p < __test_i2c_read8_end; ++p) {
rv = p->routine(port, slave_addr, offset, data);
if (rv != EC_ERROR_INVAL)
@@ -53,6 +125,8 @@ int i2c_write8(int port, int slave_addr, int offset, int data)
const struct test_i2c_write_dev *p;
int rv;
+ if (test_check_detached(port, slave_addr))
+ return EC_ERROR_UNKNOWN;
for (p = __test_i2c_write8; p < __test_i2c_write8_end; ++p) {
rv = p->routine(port, slave_addr, offset, data);
if (rv != EC_ERROR_INVAL)
@@ -67,6 +141,8 @@ int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data,
const struct test_i2c_read_string_dev *p;
int rv;
+ if (test_check_detached(port, slave_addr))
+ return EC_ERROR_UNKNOWN;
for (p = __test_i2c_read_string; p < __test_i2c_read_string_end; ++p) {
rv = p->routine(port, slave_addr, offset, data, len);
if (rv != EC_ERROR_INVAL)
diff --git a/include/test_util.h b/include/test_util.h
index a05165148e..1dc737b986 100644
--- a/include/test_util.h
+++ b/include/test_util.h
@@ -218,4 +218,25 @@ struct test_i2c_write_dev {
__attribute__((section(".rodata.test_i2c.read_string"))) \
= {routine}
+/*
+ * Detach an I2C device. Once detached, any read/write command regarding the
+ * specified port and slave address returns error.
+ *
+ * @param port The port that the detached device is connected to
+ * @param slave_addr The address of the detached device
+ * @return EC_SUCCESS if detached; EC_ERROR_OVERFLOW if too many devices are
+ * detached.
+ */
+int test_detach_i2c(int port, int slave_addr);
+
+/*
+ * Re-attach an I2C device.
+ *
+ * @param port The port that the detached device is connected to
+ * @param slave_addr The address of the detached device
+ * @return EC_SUCCESS if re-attached; EC_ERROR_INVAL if the specified device
+ * is not a detached device.
+ */
+int test_attach_i2c(int port, int slave_addr);
+
#endif /* __CROS_EC_TEST_UTIL_H */