loragw_i2c.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. / _____) _ | |
  3. ( (____ _____ ____ _| |_ _____ ____| |__
  4. \____ \| ___ | (_ _) ___ |/ ___) _ \
  5. _____) ) ____| | | || |_| ____( (___| | | |
  6. (______/|_____)_|_|_| \__)_____)\____)_| |_|
  7. (C)2019 Semtech
  8. Description:
  9. Host specific functions to address the LoRa concentrator I2C peripherals.
  10. License: Revised BSD License, see LICENSE.TXT file include in the project
  11. */
  12. /* -------------------------------------------------------------------------- */
  13. /* --- DEPENDANCIES --------------------------------------------------------- */
  14. #include <stdint.h> /* C99 types */
  15. #include <stdio.h> /* printf fprintf */
  16. #include <unistd.h> /* lseek, close */
  17. #include <fcntl.h> /* open */
  18. #include <errno.h> /* errno */
  19. #include <sys/ioctl.h>
  20. #include <linux/i2c.h>
  21. #include <linux/i2c-dev.h>
  22. #include "loragw_i2c.h"
  23. #include "loragw_aux.h"
  24. /* -------------------------------------------------------------------------- */
  25. /* --- PRIVATE MACROS ------------------------------------------------------- */
  26. #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
  27. #if DEBUG_I2C == 1
  28. #define DEBUG_MSG(str) fprintf(stdout, str)
  29. #define DEBUG_PRINTF(fmt, args...) fprintf(stdout,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
  30. #define CHECK_NULL(a) if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return LGW_I2C_ERROR;}
  31. #else
  32. #define DEBUG_MSG(str)
  33. #define DEBUG_PRINTF(fmt, args...)
  34. #define CHECK_NULL(a) if(a==NULL){return LGW_I2C_ERROR;}
  35. #endif
  36. /* -------------------------------------------------------------------------- */
  37. /* --- PRIVATE CONSTANTS ---------------------------------------------------- */
  38. /* -------------------------------------------------------------------------- */
  39. /* --- PUBLIC FUNCTIONS DEFINITION ------------------------------------------ */
  40. int i2c_linuxdev_open(const char *path, uint8_t device_addr, int *i2c_fd) {
  41. int dev;
  42. /* Check input variables */
  43. if (path == NULL) {
  44. DEBUG_MSG("ERROR: null pointer path\n");
  45. return LGW_I2C_ERROR;
  46. }
  47. if (i2c_fd == NULL) {
  48. DEBUG_MSG("ERROR: null pointer i2c_fd\n");
  49. return LGW_I2C_ERROR;
  50. }
  51. /* Open I2C device */
  52. dev = open(path, O_RDWR);
  53. if (dev < 0) {
  54. DEBUG_PRINTF("ERROR: Failed to open I2C %s - %s\n", path, strerror(errno));
  55. return LGW_I2C_ERROR;
  56. }
  57. /* Setting I2C device mode to slave */
  58. if (ioctl(dev, I2C_SLAVE, device_addr) < 0) {
  59. DEBUG_PRINTF("ERROR: Failed to acquire bus access and/or talk to slave - %s\n", strerror(errno));
  60. return LGW_I2C_ERROR;
  61. }
  62. DEBUG_PRINTF("INFO: I2C port opened successfully (%s, 0x%02X)\n", path, device_addr);
  63. *i2c_fd = dev; /* return file descriptor index */
  64. return LGW_I2C_SUCCESS;
  65. }
  66. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  67. int i2c_linuxdev_read(int i2c_fd, uint8_t device_addr, uint8_t reg_addr, uint8_t *data) {
  68. uint8_t *inbuff, outbuff;
  69. struct i2c_rdwr_ioctl_data packets;
  70. struct i2c_msg messages[2];
  71. outbuff = reg_addr;
  72. messages[0].addr = device_addr;
  73. messages[0].flags= 0;
  74. messages[0].len = sizeof(outbuff);
  75. messages[0].buf = &outbuff;
  76. inbuff = data;
  77. messages[1].addr = device_addr;
  78. messages[1].flags = I2C_M_RD;
  79. messages[1].len = sizeof(*inbuff);
  80. messages[1].buf = inbuff;
  81. packets.msgs = messages;
  82. packets.nmsgs = 2;
  83. if (ioctl(i2c_fd, I2C_RDWR, &packets) < 0) {
  84. DEBUG_PRINTF("ERROR: Read from I2C Device failed (%d, 0x%02x, 0x%02x) - %s\n", i2c_fd, device_addr, reg_addr, strerror(errno));
  85. return LGW_I2C_ERROR;
  86. }
  87. return LGW_I2C_SUCCESS;
  88. }
  89. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  90. int i2c_linuxdev_write(int i2c_fd, uint8_t device_addr, uint8_t reg_addr, uint8_t data) {
  91. unsigned char buff[2];
  92. struct i2c_rdwr_ioctl_data packets;
  93. struct i2c_msg messages[1];
  94. buff[0] = reg_addr;
  95. buff[1] = data;
  96. messages[0].addr = device_addr;
  97. messages[0].flags = 0;
  98. messages[0].len = sizeof(buff);
  99. messages[0].buf = buff;
  100. packets.msgs = messages;
  101. packets.nmsgs = 1;
  102. if (ioctl(i2c_fd, I2C_RDWR, &packets) < 0) {
  103. DEBUG_PRINTF("ERROR: Write to I2C Device failed (%d, 0x%02x, 0x%02x) - %s\n", i2c_fd, device_addr, reg_addr, strerror(errno));
  104. return LGW_I2C_ERROR;
  105. }
  106. return LGW_I2C_SUCCESS;
  107. }
  108. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  109. int i2c_linuxdev_write_buffer(int i2c_fd, uint8_t device_addr, uint8_t *buffer, uint8_t size) {
  110. struct i2c_rdwr_ioctl_data packets;
  111. struct i2c_msg messages[1];
  112. /* Check input parameters */
  113. CHECK_NULL(buffer);
  114. messages[0].addr = device_addr;
  115. messages[0].flags = 0;
  116. messages[0].len = size;
  117. messages[0].buf = buffer;
  118. packets.msgs = messages;
  119. packets.nmsgs = 1;
  120. if (ioctl(i2c_fd, I2C_RDWR, &packets) < 0) {
  121. DEBUG_PRINTF("ERROR: Write buffer to I2C Device failed (%d, 0x%02x) - %s\n", i2c_fd, device_addr, strerror(errno));
  122. return LGW_I2C_ERROR;
  123. }
  124. return LGW_I2C_SUCCESS;
  125. }
  126. /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
  127. int i2c_linuxdev_close(int i2c_fd) {
  128. int i;
  129. i = close(i2c_fd);
  130. if (i == 0) {
  131. DEBUG_MSG("INFO: I2C port closed successfully\n");
  132. return LGW_I2C_SUCCESS;
  133. } else {
  134. DEBUG_PRINTF("ERROR: Failed to close I2C - %s\n", strerror(errno));
  135. return LGW_I2C_ERROR;
  136. }
  137. }
  138. /* --- EOF ------------------------------------------------------------------ */