source: rtems/testsuites/libtests/i2c01/init.c @ 08135c85

Last change on this file since 08135c85 was 08135c85, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 23, 2015 at 7:00:31 AM

i2c: Fix return status of i2c dev read/write

  • Property mode set to 100644
File size: 14.8 KB
Line 
1/*
2 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include <dev/i2c/i2c.h>
20#include <dev/i2c/eeprom.h>
21#include <dev/i2c/gpio-nxp-pca9535.h>
22#include <dev/i2c/switch-nxp-pca9548a.h>
23
24#include <sys/ioctl.h>
25#include <sys/stat.h>
26#include <errno.h>
27#include <fcntl.h>
28#include <stdlib.h>
29#include <string.h>
30#include <unistd.h>
31
32#include <rtems/libcsupport.h>
33
34#include "tmacros.h"
35
36const char rtems_test_name[] = "I2C 1";
37
38#define SPARE_ADDRESS_BITS 3
39
40#define DEVICE_SIMPLE_READ_WRITE (0UL << SPARE_ADDRESS_BITS)
41
42#define DEVICE_EEPROM (1UL << SPARE_ADDRESS_BITS)
43
44#define DEVICE_GPIO_NXP_PCA9535 (2UL << SPARE_ADDRESS_BITS)
45
46#define DEVICE_SWITCH_NXP_PCA9548A (3UL << SPARE_ADDRESS_BITS)
47
48#define EEPROM_SIZE 512
49
50typedef struct test_device test_device;
51
52struct test_device {
53  int (*transfer)(
54    i2c_bus *bus,
55    i2c_msg *msgs,
56    uint32_t msg_count,
57    test_device *dev
58  );
59};
60
61typedef struct {
62  test_device base;
63  char buf[3];
64} test_device_simple_read_write;
65
66typedef struct {
67  test_device base;
68  unsigned current_reg;
69  uint8_t regs[8];
70} test_device_gpio_nxp_pca9535;
71
72typedef struct {
73  test_device base;
74  bool eio;
75  unsigned current_address;
76  uint8_t data[EEPROM_SIZE];
77} test_device_eeprom;
78
79typedef struct {
80  test_device base;
81  uint8_t control;
82} test_device_switch_nxp_pca9548a;
83
84typedef struct {
85  i2c_bus base;
86  unsigned long clock;
87  test_device *devices[4];
88  test_device_simple_read_write simple_read_write;
89  test_device_gpio_nxp_pca9535 gpio_nxp_pca9535;
90  test_device_eeprom eeprom;
91  test_device_switch_nxp_pca9548a switch_nxp_pca9548a;
92} test_bus;
93
94static const char bus_path[] = "/dev/i2c-0";
95
96static const char gpio_nxp_pca9535_path[] = "/dev/i2c-0.gpio-nxp-pc9535-0";
97
98static const char eeprom_path[] = "/dev/i2c-0.eeprom-0";
99
100static const char switch_nxp_pca9548a_path[] =
101  "/dev/i2c-0.switch-nxp-pca9548a-0";
102
103static void cyclic_inc(unsigned *val, unsigned cycle)
104{
105  unsigned v = *val;
106  unsigned m = cycle - 1U;
107
108  *val = (v & ~m) + ((v + 1U) & m);
109}
110
111static int test_simple_read_write_transfer(
112  i2c_bus *bus,
113  i2c_msg *msgs,
114  uint32_t msg_count,
115  test_device *base
116)
117{
118  test_device_simple_read_write *dev = (test_device_simple_read_write *) base;
119
120  if (msg_count == 1 && msgs[0].len == sizeof(dev->buf)) {
121    if ((msgs[0].flags & I2C_M_RD) != 0) {
122      memcpy(msgs[0].buf, &dev->buf[0], sizeof(dev->buf));
123    } else {
124      memcpy(&dev->buf[0], msgs[0].buf, sizeof(dev->buf));
125    }
126
127    return 0;
128  } else {
129    return -EIO;
130  }
131}
132
133static int test_gpio_nxp_pca9535_transfer(
134  i2c_bus *bus,
135  i2c_msg *msgs,
136  uint32_t msg_count,
137  test_device *base
138)
139{
140  test_device_gpio_nxp_pca9535 *dev = (test_device_gpio_nxp_pca9535 *) base;
141  i2c_msg *first = &msgs[0];
142  i2c_msg *second = &msgs[1];
143  int i;
144
145  /* Get command byte */
146  if (
147    msg_count < 1
148      || (first->flags & I2C_M_RD) != 0
149      || first->len < 1
150  ) {
151    return -EIO;
152  }
153
154  dev->current_reg = first->buf[0];
155
156  if (first->len > 1) {
157    /* Write */
158
159    if (msg_count != 1) {
160      return -EIO;
161    }
162
163    for (i = 1; i < first->len; ++i) {
164      dev->regs[dev->current_reg] = first->buf[i];
165
166      /* Output is input */
167      if (dev->current_reg == 2) {
168        dev->regs[0] = first->buf[i];
169      } else if (dev->current_reg == 3) {
170        dev->regs[1] = first->buf[i];
171      }
172
173      cyclic_inc(&dev->current_reg, 2);
174    }
175  } else {
176    /* Read */
177
178    if (msg_count != 2) {
179      return -EIO;
180    }
181
182    for (i = 0; i < second->len; ++i) {
183      second->buf[i] = dev->regs[dev->current_reg];
184      cyclic_inc(&dev->current_reg, 2);
185    }
186  }
187
188  return 0;
189}
190
191static int test_eeprom_transfer(
192  i2c_bus *bus,
193  i2c_msg *msgs,
194  uint32_t msg_count,
195  test_device *base
196)
197{
198  test_device_eeprom *dev = (test_device_eeprom *) base;
199  i2c_msg *msg = &msgs[0];
200  uint32_t i;
201
202  if (dev->eio) {
203    return -EIO;
204  }
205
206  if (msg_count > 0 && (msg->flags & I2C_M_RD) == 0) {
207    if (msg->len < 1) {
208      return -EIO;
209    }
210
211    dev->current_address = msg->buf[0] | ((msg->addr & 0x1) << 8);
212    --msg->len;
213    ++msg->buf;
214  }
215
216  for (i = 0; i < msg_count; ++i) {
217    int j;
218
219    msg = &msgs[i];
220
221    if ((msg->flags & I2C_M_RD) != 0) {
222      for (j = 0; j < msg->len; ++j) {
223        msg->buf[j] = dev->data[dev->current_address];
224        cyclic_inc(&dev->current_address, sizeof(dev->data));
225      }
226    } else {
227      for (j = 0; j < msg->len; ++j) {
228        dev->data[dev->current_address] = msg->buf[j];
229        cyclic_inc(&dev->current_address, 8);
230      }
231    }
232  }
233
234  return 0;
235}
236
237static int test_switch_nxp_pca9548a_transfer(
238  i2c_bus *bus,
239  i2c_msg *msgs,
240  uint32_t msg_count,
241  test_device *base
242)
243{
244  test_device_switch_nxp_pca9548a *dev = (test_device_switch_nxp_pca9548a *) base;
245  uint32_t i;
246
247  for (i = 0; i < msg_count; ++i) {
248    i2c_msg *msg = &msgs[i];
249    int j;
250
251    if ((msg->flags & I2C_M_RD) != 0) {
252      for (j = 0; j < msg->len; ++j) {
253        msg->buf[j] = dev->control;
254      }
255    } else {
256      for (j = 0; j < msg->len; ++j) {
257        dev->control = msg->buf[j];
258      }
259    }
260  }
261
262  return 0;
263}
264
265static int test_transfer(i2c_bus *base, i2c_msg *msgs, uint32_t msg_count)
266{
267  test_bus *bus = (test_bus *) base;
268  uint16_t addr;
269  test_device *dev;
270
271  addr = msgs[0].addr >> SPARE_ADDRESS_BITS;
272  if (addr >= RTEMS_ARRAY_SIZE(bus->devices)) {
273    return -EIO;
274  }
275
276  dev = bus->devices[addr];
277
278  return (*dev->transfer)(&bus->base, msgs, msg_count, dev);
279}
280
281static int test_set_clock(i2c_bus *base, unsigned long clock)
282{
283  test_bus *bus = (test_bus *) base;
284
285  bus->clock = clock;
286
287  return 0;
288}
289
290static void test_destroy(i2c_bus *base)
291{
292  i2c_bus_destroy_and_free(base);
293}
294
295static void test_simple_read_write(test_bus *bus, int fd)
296{
297  static const char zero[] = { 0, 0, 0 };
298  static const char abc[] = { 'a', 'b', 'c' };
299
300  int rv;
301  char buf[3];
302  ssize_t n;
303
304  rv = ioctl(fd, I2C_SLAVE, DEVICE_SIMPLE_READ_WRITE);
305  rtems_test_assert(rv == 0);
306
307  errno = 0;
308  rv = ioctl(fd, 0xb00b);
309  rtems_test_assert(rv == -1);
310  rtems_test_assert(errno == ENOTTY);
311
312  errno = 0;
313  n = write(fd, &buf[0], 1000);
314  rtems_test_assert(n == -1);
315  rtems_test_assert(errno == EIO);
316
317  errno = 0;
318  n = read(fd, &buf[0], 1000);
319  rtems_test_assert(n == -1);
320  rtems_test_assert(errno == EIO);
321
322  rtems_test_assert(
323    memcmp(&bus->simple_read_write.buf[0], &zero[0], sizeof(buf)) == 0
324  );
325
326  n = write(fd, &abc[0], sizeof(buf));
327  rtems_test_assert(n == (ssize_t) sizeof(buf));
328
329  rtems_test_assert(
330    memcmp(&bus->simple_read_write.buf[0], &abc[0], sizeof(buf)) == 0
331  );
332
333  n = read(fd, &buf[0], sizeof(buf));
334  rtems_test_assert(n == (ssize_t) sizeof(buf));
335
336  rtems_test_assert(memcmp(&buf[0], &abc[0], sizeof(buf)) == 0);
337}
338
339static void test_gpio_nxp_pca9535(void)
340{
341  int rv;
342  int fd;
343  uint16_t val;
344
345  rv = i2c_dev_register_gpio_nxp_pca9535(
346    &bus_path[0],
347    &gpio_nxp_pca9535_path[0],
348    DEVICE_GPIO_NXP_PCA9535
349  );
350  rtems_test_assert(rv == 0);
351
352  fd = open(&gpio_nxp_pca9535_path[0], O_RDWR);
353  rtems_test_assert(fd >= 0);
354
355  rv = gpio_nxp_pca9535_get_input(fd, &val);
356  rtems_test_assert(rv == 0);
357  rtems_test_assert(val == 0);
358
359  rv = gpio_nxp_pca9535_get_output(fd, &val);
360  rtems_test_assert(rv == 0);
361  rtems_test_assert(val == 0);
362
363  rv = gpio_nxp_pca9535_set_output(fd, 0xa5ef);
364  rtems_test_assert(rv == 0);
365
366  rv = gpio_nxp_pca9535_get_input(fd, &val);
367  rtems_test_assert(rv == 0);
368  rtems_test_assert(val == 0xa5ef);
369
370  rv = gpio_nxp_pca9535_get_output(fd, &val);
371  rtems_test_assert(rv == 0);
372  rtems_test_assert(val == 0xa5ef);
373
374  rv = gpio_nxp_pca9535_clear_and_set_output(fd, 0x0ff0, 0x0170);
375  rtems_test_assert(rv == 0);
376
377  rv = gpio_nxp_pca9535_get_polarity_inversion(fd, &val);
378  rtems_test_assert(rv == 0);
379  rtems_test_assert(val == 0);
380
381  rv = gpio_nxp_pca9535_set_polarity_inversion(fd, 0x5afe);
382  rtems_test_assert(rv == 0);
383
384  rv = gpio_nxp_pca9535_get_config(fd, &val);
385  rtems_test_assert(rv == 0);
386  rtems_test_assert(val == 0);
387
388  rv = gpio_nxp_pca9535_set_config(fd, 0x2bcd);
389  rtems_test_assert(rv == 0);
390
391  rv = gpio_nxp_pca9535_get_input(fd, &val);
392  rtems_test_assert(rv == 0);
393  rtems_test_assert(val == 0xa17f);
394
395  rv = gpio_nxp_pca9535_get_output(fd, &val);
396  rtems_test_assert(rv == 0);
397  rtems_test_assert(val == 0xa17f);
398
399  rv = gpio_nxp_pca9535_get_polarity_inversion(fd, &val);
400  rtems_test_assert(rv == 0);
401  rtems_test_assert(val == 0x5afe);
402
403  rv = gpio_nxp_pca9535_get_config(fd, &val);
404  rtems_test_assert(rv == 0);
405  rtems_test_assert(val == 0x2bcd);
406
407  rv = close(fd);
408  rtems_test_assert(rv == 0);
409
410  rv = unlink(&gpio_nxp_pca9535_path[0]);
411  rtems_test_assert(rv == 0);
412}
413
414static void test_eeprom(test_bus *bus)
415{
416  int rv;
417  int fd_in;
418  int fd_out;
419  struct stat st;
420  uint8_t in[EEPROM_SIZE];
421  uint8_t out[EEPROM_SIZE];
422  ssize_t n;
423  off_t off;
424  size_t i;
425
426  rv = i2c_dev_register_eeprom(
427    &bus_path[0],
428    &eeprom_path[0],
429    DEVICE_EEPROM,
430    1,
431    8,
432    sizeof(out),
433    0
434  );
435  rtems_test_assert(rv == 0);
436
437  fd_in = open(&eeprom_path[0], O_RDWR);
438  rtems_test_assert(fd_in >= 0);
439
440  fd_out = open(&eeprom_path[0], O_RDWR);
441  rtems_test_assert(fd_out >= 0);
442
443  rv = fstat(fd_in, &st);
444  rtems_test_assert(rv == 0);
445  rtems_test_assert(st.st_blksize == 8);
446  rtems_test_assert(st.st_size == sizeof(out));
447
448  memset(&out[0], 0, sizeof(out));
449
450  bus->eeprom.eio = true;
451
452  errno = 0;
453  n = read(fd_in, &in[0], 1);
454  rtems_test_assert(n == -1);
455  rtems_test_assert(errno == EIO);
456
457  errno = 0;
458  n = write(fd_out, &out[0], 1);
459  rtems_test_assert(n == -1);
460  rtems_test_assert(errno == EIO);
461
462  bus->eeprom.eio = false;
463
464  n = read(fd_in, &in[0], sizeof(in) + 1);
465  rtems_test_assert(n == (ssize_t) sizeof(in));
466
467  rtems_test_assert(memcmp(&in[0], &out[0], sizeof(in)) == 0);
468
469  off = lseek(fd_in, 0, SEEK_CUR);
470  rtems_test_assert(off == sizeof(out));
471
472  for (i = 0; i < sizeof(out); ++i) {
473    off = lseek(fd_out, 0, SEEK_CUR);
474    rtems_test_assert(off == i);
475
476    out[i] = (uint8_t) i;
477
478    n = write(fd_out, &out[i], sizeof(out[i]));
479    rtems_test_assert(n == (ssize_t) sizeof(out[i]));
480
481    off = lseek(fd_in, 0, SEEK_SET);
482    rtems_test_assert(off == 0);
483
484    n = read(fd_in, &in[0], sizeof(in));
485    rtems_test_assert(n == (ssize_t) sizeof(in));
486
487    rtems_test_assert(memcmp(&in[0], &out[0], sizeof(in)) == 0);
488  }
489
490  rv = close(fd_in);
491  rtems_test_assert(rv == 0);
492
493  rv = close(fd_out);
494  rtems_test_assert(rv == 0);
495
496  rv = unlink(&eeprom_path[0]);
497  rtems_test_assert(rv == 0);
498}
499
500static void test_switch_nxp_pca9548a(void)
501{
502  int rv;
503  int fd;
504  uint8_t val;
505
506  rv = i2c_dev_register_switch_nxp_pca9548a(
507    &bus_path[0],
508    &switch_nxp_pca9548a_path[0],
509    DEVICE_SWITCH_NXP_PCA9548A
510  );
511  rtems_test_assert(rv == 0);
512
513  fd = open(&switch_nxp_pca9548a_path[0], O_RDWR);
514  rtems_test_assert(fd >= 0);
515
516  rv = switch_nxp_pca9548a_get_control(fd, &val);
517  rtems_test_assert(rv == 0);
518  rtems_test_assert(val == 0);
519
520  rv = switch_nxp_pca9548a_set_control(fd, 0xa5);
521  rtems_test_assert(rv == 0);
522
523  rv = switch_nxp_pca9548a_get_control(fd, &val);
524  rtems_test_assert(rv == 0);
525  rtems_test_assert(val == 0xa5);
526
527  rv = close(fd);
528  rtems_test_assert(rv == 0);
529
530  rv = unlink(&switch_nxp_pca9548a_path[0]);
531  rtems_test_assert(rv == 0);
532}
533
534static void test(void)
535{
536  rtems_resource_snapshot snapshot;
537  test_bus *bus;
538  int rv;
539  int fd;
540
541  rtems_resource_snapshot_take(&snapshot);
542
543  bus = (test_bus *) i2c_bus_alloc_and_init(sizeof(*bus));
544  rtems_test_assert(bus != NULL);
545
546  bus->base.transfer = test_transfer;
547  bus->base.set_clock = test_set_clock;
548  bus->base.destroy = test_destroy;
549  bus->base.functionality = I2C_FUNC_I2C | I2C_FUNC_PROTOCOL_MANGLING
550    | I2C_FUNC_NOSTART;
551
552  bus->simple_read_write.base.transfer = test_simple_read_write_transfer;
553  bus->devices[0] = &bus->simple_read_write.base;
554
555  bus->eeprom.base.transfer = test_eeprom_transfer;
556  bus->devices[1] = &bus->eeprom.base;
557
558  bus->gpio_nxp_pca9535.base.transfer = test_gpio_nxp_pca9535_transfer;
559  bus->devices[2] = &bus->gpio_nxp_pca9535.base;
560
561  bus->switch_nxp_pca9548a.base.transfer = test_switch_nxp_pca9548a_transfer;
562  bus->devices[3] = &bus->switch_nxp_pca9548a.base;
563
564  rv = i2c_bus_register(&bus->base, &bus_path[0]);
565  rtems_test_assert(rv == 0);
566
567  fd = open(&bus_path[0], O_RDWR);
568  rtems_test_assert(fd >= 0);
569
570  rtems_test_assert(bus->clock == 0);
571  rv = ioctl(fd, I2C_BUS_SET_CLOCK, 0xdeadbeefUL);
572  rtems_test_assert(rv == 0);
573  rtems_test_assert(bus->clock == 0xdeadbeef);
574
575  rv = ioctl(fd, I2C_BUS_OBTAIN);
576  rtems_test_assert(rv == 0);
577
578  rv = ioctl(fd, I2C_BUS_RELEASE);
579  rtems_test_assert(rv == 0);
580
581  rtems_test_assert(!bus->base.ten_bit_address);
582
583  rv = ioctl(fd, I2C_TENBIT, 1UL);
584  rtems_test_assert(rv == 0);
585  rtems_test_assert(bus->base.ten_bit_address);
586
587  rv = ioctl(fd, I2C_TENBIT, 0UL);
588  rtems_test_assert(rv == 0);
589  rtems_test_assert(!bus->base.ten_bit_address);
590
591  rtems_test_assert(!bus->base.use_pec);
592
593  rv = ioctl(fd, I2C_PEC, 1UL);
594  rtems_test_assert(rv == 0);
595  rtems_test_assert(bus->base.use_pec);
596
597  rv = ioctl(fd, I2C_PEC, 0UL);
598  rtems_test_assert(rv == 0);
599  rtems_test_assert(!bus->base.use_pec);
600
601  rv = ioctl(fd, I2C_SLAVE, 123UL);
602  rtems_test_assert(rv == 0);
603  rtems_test_assert(bus->base.default_address == 123);
604
605  rv = ioctl(fd, I2C_SLAVE_FORCE, 456UL);
606  rtems_test_assert(rv == 0);
607  rtems_test_assert(bus->base.default_address == 456);
608
609  rtems_test_assert(bus->base.retries == 0);
610
611  rv = ioctl(fd, I2C_RETRIES, 1UL);
612  rtems_test_assert(rv == 0);
613  rtems_test_assert(bus->base.retries == 1);
614
615  rv = ioctl(fd, I2C_RETRIES, 0UL);
616  rtems_test_assert(rv == 0);
617  rtems_test_assert(bus->base.retries == 0);
618
619  rtems_test_assert(bus->base.timeout == 0);
620
621  rv = ioctl(fd, I2C_TIMEOUT, 1UL);
622  rtems_test_assert(rv == 0);
623  rtems_test_assert(bus->base.timeout == 5);
624
625  rv = ioctl(fd, I2C_TIMEOUT, 0UL);
626  rtems_test_assert(rv == 0);
627  rtems_test_assert(bus->base.timeout == 0);
628
629  test_simple_read_write(bus, fd);
630  test_eeprom(bus);
631  test_gpio_nxp_pca9535();
632  test_switch_nxp_pca9548a();
633
634  rv = close(fd);
635  rtems_test_assert(rv == 0);
636
637  rv = unlink(&bus_path[0]);
638  rtems_test_assert(rv == 0);
639
640  rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
641}
642
643static void Init(rtems_task_argument arg)
644{
645  TEST_BEGIN();
646
647  test();
648
649  TEST_END();
650  rtems_test_exit(0);
651}
652
653#define CONFIGURE_MICROSECONDS_PER_TICK 2000
654
655#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
656#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
657
658#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 7
659
660#define CONFIGURE_MAXIMUM_TASKS 1
661
662#define CONFIGURE_MAXIMUM_SEMAPHORES 1
663
664#define CONFIGURE_INIT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE + 2 * EEPROM_SIZE)
665
666#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
667
668#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
669
670#define CONFIGURE_INIT
671
672#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.