test_i2c.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * c-periphery
  3. * https://github.com/vsergeev/c-periphery
  4. * License: MIT
  5. */
  6. #include "test.h"
  7. #include <stdlib.h>
  8. #include <stdbool.h>
  9. #include <string.h>
  10. #include <errno.h>
  11. #include <unistd.h>
  12. #include <fcntl.h>
  13. #include <sys/stat.h>
  14. #include "../src/i2c.h"
  15. const char *i2c_bus_path;
  16. void test_arguments(void) {
  17. ptest();
  18. /* No real argument validation needed in the i2c wrapper */
  19. }
  20. void test_open_config_close(void) {
  21. i2c_t *i2c;
  22. ptest();
  23. /* Allocate I2C */
  24. i2c = i2c_new();
  25. passert(i2c != NULL);
  26. /* Open invalid i2c bus */
  27. passert(i2c_open(i2c, "/foo/bar") == I2C_ERROR_OPEN);
  28. /* Open legitimate i2c bus */
  29. passert(i2c_open(i2c, i2c_bus_path) == 0);
  30. passert(i2c_close(i2c) == 0);
  31. /* Free I2C */
  32. i2c_free(i2c);
  33. }
  34. void test_loopback(void) {
  35. ptest();
  36. printf("No general way to do a loopback test for I2C without a real component, skipping...\n");
  37. }
  38. bool getc_yes(void) {
  39. char buf[4];
  40. fgets(buf, sizeof(buf), stdin);
  41. return (buf[0] == 'y' || buf[0] == 'Y');
  42. }
  43. void test_interactive(void) {
  44. char str[256];
  45. i2c_t *i2c;
  46. uint8_t msg1[] = { 0xaa, 0xbb, 0xcc, 0xdd };
  47. struct i2c_msg msgs[1];
  48. ptest();
  49. /* Allocate I2C */
  50. i2c = i2c_new();
  51. passert(i2c != NULL);
  52. passert(i2c_open(i2c, i2c_bus_path) == 0);
  53. printf("Starting interactive test. Get out your logic analyzer, buddy!\n");
  54. printf("Press enter to continue...\n");
  55. getc(stdin);
  56. /* Check tostring */
  57. passert(i2c_tostring(i2c, str, sizeof(str)) > 0);
  58. printf("I2C description: %s\n", str);
  59. printf("I2C description looks OK? y/n\n");
  60. passert(getc_yes());
  61. /* There isn't much we can do without assuming a device on the other end,
  62. * because I2C needs an acknowledgement bit on each transferred byte.
  63. *
  64. * But we can send a transaction and expect it to time out. */
  65. /* S [ 0x7a W ] [0xaa] [0xbb] [0xcc] [0xdd] */
  66. msgs[0].addr = 0x7a;
  67. msgs[0].flags = 0; /* Write */
  68. msgs[0].len = sizeof(msg1);
  69. msgs[0].buf = msg1;
  70. printf("Press enter to start transfer...");
  71. getc(stdin);
  72. passert(i2c_transfer(i2c, msgs, 1) < 0);
  73. passert(i2c_errno(i2c) == EREMOTEIO);
  74. passert(i2c_close(i2c) == 0);
  75. printf("I2C transfer occurred? y/n\n");
  76. passert(getc_yes());
  77. /* Free I2C */
  78. i2c_free(i2c);
  79. }
  80. int main(int argc, char *argv[]) {
  81. if (argc < 2) {
  82. fprintf(stderr, "Usage: %s <I2C device>\n\n", argv[0]);
  83. fprintf(stderr, "[1/4] Arguments test: No requirements.\n");
  84. fprintf(stderr, "[2/4] Open/close test: I2C device should be real.\n");
  85. fprintf(stderr, "[3/4] Loopback test: No test.\n");
  86. fprintf(stderr, "[4/4] Interactive test: I2C bus should be observed with an oscilloscope or logic analyzer.\n\n");
  87. fprintf(stderr, "Hint: for Raspberry Pi 3, enable I2C1 with:\n");
  88. fprintf(stderr, " $ echo \"dtparam=i2c_arm=on\" | sudo tee -a /boot/config.txt\n");
  89. fprintf(stderr, " $ sudo reboot\n");
  90. fprintf(stderr, "Use pins I2C1 SDA (header pin 2) and I2C1 SCL (header pin 3),\n");
  91. fprintf(stderr, "and run this test with:\n");
  92. fprintf(stderr, " %s /dev/i2c-1\n\n", argv[0]);
  93. exit(1);
  94. }
  95. i2c_bus_path = argv[1];
  96. test_arguments();
  97. printf(" " STR_OK " Arguments test passed.\n\n");
  98. test_open_config_close();
  99. printf(" " STR_OK " Open/close test passed.\n\n");
  100. test_loopback();
  101. printf(" " STR_OK " Loopback test passed.\n\n");
  102. test_interactive();
  103. printf(" " STR_OK " Interactive test passed.\n\n");
  104. printf("All tests passed!\n");
  105. return 0;
  106. }