77
g_assert_cmphex(value, ==, 0xEF);
78
}
79
80
+/* Verify the power-on reset defaults. */
81
+static void test_reset_defaults(void *obj, void *data, QGuestAllocator *alloc)
82
+{
83
+ QI2CDevice *i2cdev = (QI2CDevice *)obj;
84
+
85
+ /* Prescalers, PWM duty cycles and LED selectors (all LEDs off) */
86
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_PSC0), ==, 0xFF);
87
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_PWM0), ==, 0x80);
88
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_PSC1), ==, 0xFF);
89
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_PWM1), ==, 0x80);
90
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_LS0), ==, 0x55);
91
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_LS1), ==, 0x55);
92
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_LS2), ==, 0x55);
93
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_LS3), ==, 0x55);
94
+
95
+ /* All LEDs off, so every pin floats high through its pull-up */
96
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_INPUT0), ==, 0xFF);
97
+ g_assert_cmphex(i2c_get8(i2cdev, PCA9552_INPUT1), ==, 0xFF);
98
+}
99
+
100
+/*
101
+ * The PCA9552 only advances the command pointer when the AI bit is set, and
102
+ * it wraps modulo the full 10-register map.
103
+ */
104
+static void test_autoinc_requires_ai_bit(void *obj, void *data,
105
+ QGuestAllocator *alloc)
106
+{
107
+ QI2CDevice *i2cdev = (QI2CDevice *)obj;
108
+ uint8_t reg;
109
+ uint8_t resp;
110
+
111
+ /*
112
+ * With the AI bit, reading from LS3 (register 9) rolls over to INPUT0
113
+ * (register 0), not to a sibling in a register pair. All LEDs are off
114
+ * after reset so the input ports read 0xFF.
115
+ */
116
+ reg = PCA9552_LS3 | PCA9552_AUTOINC;
117
+ qi2c_send(i2cdev, ®, 1);
118
+ qi2c_recv(i2cdev, &resp, 1); /* LS3 */
119
+ g_assert_cmphex(resp, ==, 0x55);
120
+ qi2c_recv(i2cdev, &resp, 1); /* wraps to INPUT0 */
121
+ g_assert_cmphex(resp, ==, 0xFF);
122
+ qi2c_recv(i2cdev, &resp, 1); /* INPUT1 */
123
+ g_assert_cmphex(resp, ==, 0xFF);
124
+
125
+ /*
126
+ * Without the AI bit the pointer must not advance: repeated reads keep
127
+ * returning the same register.
128
+ */
129
+ i2c_set8(i2cdev, PCA9552_LS0, 0x54);
130
+ reg = PCA9552_LS0;
131
+ qi2c_send(i2cdev, ®, 1);
132
+ qi2c_recv(i2cdev, &resp, 1);
133
+ g_assert_cmphex(resp, ==, 0x54);
134
+ qi2c_recv(i2cdev, &resp, 1);
135
+ g_assert_cmphex(resp, ==, 0x54);
136
+}
137
+
138
+/*
139
+ * The PCA9552 decodes a 4-bit command and has no register past LS3 (9), so
140
+ * addressing register 0x0A reads back 0xFF.
141
+ */
142
+static void test_command_out_of_range(void *obj, void *data,
143
+ QGuestAllocator *alloc)
144
+{
145
+ QI2CDevice *i2cdev = (QI2CDevice *)obj;
146
+
147
+ g_assert_cmphex(i2c_get8(i2cdev, 0x0A), ==, 0xFF);
148
+}
149
+
150
static void pca9552_register_nodes(void)
151
{
152
QOSGraphEdgeOptions opts = {
159
160
qos_add_test("tx-rx", "pca9552", send_and_receive, NULL);
161
qos_add_test("rx-autoinc", "pca9552", receive_autoinc, NULL);
162
+ qos_add_test("reset-defaults", "pca9552", test_reset_defaults, NULL);
163
+ qos_add_test("autoinc-requires-ai-bit", "pca9552",
164
+ test_autoinc_requires_ai_bit, NULL);
165
+ qos_add_test("command-out-of-range", "pca9552", test_command_out_of_range,
166
+ NULL);
167
}
168
+
169
libqos_init(pca9552_register_nodes);