driver_pcal6416a.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdbool.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <fcntl.h>
  8. #include <errno.h>
  9. #include <sys/select.h>
  10. #include <linux/input.h>
  11. #include "read_conf_file.h"
  12. #include <assert.h>
  13. #include <linux/i2c.h>
  14. #include <linux/i2c-dev.h>
  15. #include "smbus.h"
  16. #include "driver_pcal6416a.h"
  17. /****************************************************************
  18. * Defines
  19. ****************************************************************/
  20. #define DEBUG_PCAL6416A_PRINTF (0)
  21. #if (DEBUG_PCAL6416A_PRINTF)
  22. #define DEBUG_PRINTF(...) printf(__VA_ARGS__);
  23. #else
  24. #define DEBUG_PRINTF(...)
  25. #endif
  26. /****************************************************************
  27. * Structures
  28. ****************************************************************/
  29. typedef struct {
  30. unsigned int address;
  31. char *name;
  32. } i2c_expander_t;
  33. /****************************************************************
  34. * Static variables
  35. ****************************************************************/
  36. static int fd_i2c_expander;
  37. static unsigned int i2c_expander_addr;
  38. static char i2c0_sysfs_filename[] = "/dev/i2c-0";
  39. static i2c_expander_t i2c_chip[] = {
  40. {PCAL9539A_I2C_ADDR, "PCAL9539A"},
  41. {PCAL6416A_I2C_ADDR, "PCAL6416A"},
  42. {0, NULL}
  43. };
  44. /****************************************************************
  45. * Static functions
  46. ****************************************************************/
  47. /****************************************************************
  48. * Public functions
  49. ****************************************************************/
  50. bool pcal6416a_init(void) {
  51. int i;
  52. if ((fd_i2c_expander = open(i2c0_sysfs_filename,O_RDWR)) < 0) {
  53. printf("Failed to open the I2C bus %s", i2c0_sysfs_filename);
  54. // ERROR HANDLING; you can check errno to see what went wrong
  55. return false;
  56. }
  57. /// Probing known I2C GPIO expander chips
  58. for (i = 0, i2c_expander_addr = 0; i2c_chip[i].address; i++) {
  59. if (ioctl(fd_i2c_expander, I2C_SLAVE_FORCE, i2c_chip[i]) < 0 ||
  60. pcal6416a_read_mask_interrupts() < 0) {
  61. DEBUG_PRINTF("In %s - Failed to acquire bus access and/or talk to slave %s at address 0x%02X.\n",
  62. __func__, i2c_chip[i].name, i2c_chip[i].address);
  63. } else {
  64. DEBUG_PRINTF("Found I2C gpio expander chip %s at address 0x%02X\n",
  65. i2c_chip[i].name, i2c_chip[i].address);
  66. i2c_expander_addr = i2c_chip[i].address;
  67. break;
  68. }
  69. }
  70. /// GPIO expander chip found?
  71. if(!i2c_expander_addr){
  72. printf("In %s - Failed to acquire bus access and/or talk to slave, exit\n", __func__);
  73. return false;
  74. }
  75. uint16_t val_enable_direction = 0xffff;
  76. i2c_smbus_write_word_data ( fd_i2c_expander , PCAL6416A_CONFIG , val_enable_direction );
  77. uint16_t val_enable_latch = 0x0000;
  78. i2c_smbus_write_word_data ( fd_i2c_expander , PCAL6416A_INPUT_LATCH , val_enable_latch );
  79. uint16_t val_enable_pullups = 0xffff;
  80. i2c_smbus_write_word_data ( fd_i2c_expander , PCAL6416A_EN_PULLUPDOWN , val_enable_pullups );
  81. uint16_t val_sel_pullups = 0xffff;
  82. i2c_smbus_write_word_data ( fd_i2c_expander , PCAL6416A_SEL_PULLUPDOWN , val_sel_pullups );
  83. //uint16_t val_enable_interrupts = 0x0000;
  84. uint16_t val_enable_interrupts = 0x0320;
  85. i2c_smbus_write_word_data ( fd_i2c_expander , PCAL6416A_INT_MASK , val_enable_interrupts );
  86. return true;
  87. }
  88. bool pcal6416a_deinit(void) {
  89. // Close I2C open interface
  90. close(fd_i2c_expander);
  91. return true;
  92. }
  93. int pcal6416a_read_mask_interrupts(void){
  94. int val_int = i2c_smbus_read_word_data ( fd_i2c_expander , PCAL6416A_INT_STATUS );
  95. if(val_int < 0){
  96. return val_int;
  97. }
  98. uint16_t val = val_int & 0xFFFF;
  99. DEBUG_PRINTF("READ PCAL6416A_INT_STATUS : 0x%04X\n",val);
  100. return (int) val;
  101. }
  102. int pcal6416a_read_mask_active_GPIOs(void){
  103. int val_int = i2c_smbus_read_word_data ( fd_i2c_expander , PCAL6416A_INPUT );
  104. if(val_int < 0){
  105. return val_int;
  106. }
  107. uint16_t val = val_int & 0xFFFF;
  108. val = 0xFFFF-val;
  109. DEBUG_PRINTF("READ PCAL6416A_INPUT (active GPIOs) : 0x%04X\n",val);
  110. return (int) val;
  111. }