i2c-context.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * generic I2C slave access interface
  3. *
  4. * Copyright 2014-2016 Mikeqin <Fengling.Qin@gmail.com>
  5. * Copyright 2014 Zefir Kurtisi <zefir.kurtisi@gmail.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the Free
  9. * Software Foundation; either version 3 of the License, or (at your option)
  10. * any later version. See COPYING for more details.
  11. */
  12. #include <sys/ioctl.h>
  13. #include <errno.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <linux/i2c.h>
  19. #include <linux/i2c-dev.h>
  20. #include <stdint.h>
  21. #include <stdbool.h>
  22. #include <fcntl.h>
  23. #include <assert.h>
  24. #include "miner.h"
  25. #include "i2c-context.h"
  26. static bool i2c_slave_write(struct i2c_ctx *ctx, uint8_t reg, uint8_t val)
  27. {
  28. union i2c_smbus_data data;
  29. data.byte = val;
  30. struct i2c_smbus_ioctl_data args;
  31. args.read_write = I2C_SMBUS_WRITE;
  32. args.command = reg;
  33. args.size = I2C_SMBUS_BYTE_DATA;
  34. args.data = &data;
  35. if (ioctl(ctx->file, I2C_SMBUS, &args) == -1) {
  36. applog(LOG_INFO, "i2c 0x%02x: failed to write to fdesc %d: %s",
  37. ctx->addr, ctx->file, strerror(errno));
  38. return false;
  39. }
  40. applog(LOG_DEBUG, "I2C-W(0x%02x/0x%02x)=0x%02x", ctx->addr, reg, val);
  41. return true;
  42. }
  43. static bool i2c_slave_read(struct i2c_ctx *ctx, uint8_t reg, uint8_t *val)
  44. {
  45. union i2c_smbus_data data;
  46. struct i2c_smbus_ioctl_data args;
  47. args.read_write = I2C_SMBUS_READ;
  48. args.command = reg;
  49. args.size = I2C_SMBUS_BYTE_DATA;
  50. args.data = &data;
  51. if (ioctl(ctx->file, I2C_SMBUS, &args) == -1) {
  52. applog(LOG_INFO, "i2c 0x%02x: failed to read from fdesc %d: %s",
  53. ctx->addr, ctx->file, strerror(errno));
  54. return false;
  55. }
  56. *val = data.byte;
  57. applog(LOG_DEBUG, "I2C-R(0x%02x/0x%02x)=0x%02x", ctx->addr, reg, *val);
  58. return true;
  59. }
  60. static bool i2c_slave_write_raw(struct i2c_ctx *ctx, uint8_t *buf, uint32_t len)
  61. {
  62. /* SMBus cann't support write bytes > 32, use plain i2c write */
  63. if (len != write(ctx->file, buf, len)) {
  64. applog(LOG_INFO, "i2c 0x%02x: failed to write raw to fdesc %d: %s",
  65. ctx->addr, ctx->file, strerror(errno));
  66. return false;
  67. }
  68. applog(LOG_DEBUG, "I2C-W-RAW(0x%02x)", ctx->addr);
  69. return true;
  70. }
  71. static bool i2c_slave_read_raw(struct i2c_ctx *ctx, uint8_t *buf, uint32_t len)
  72. {
  73. /* SMBus cann't support read bytes > 32, use plain i2c read */
  74. if (len != read(ctx->file, buf, len)) {
  75. applog(LOG_INFO, "i2c 0x%02x: failed to read raw from fdesc %d: %s",
  76. ctx->addr, ctx->file, strerror(errno));
  77. return false;
  78. }
  79. applog(LOG_DEBUG, "I2C-R-RAW(0x%02x)", ctx->addr);
  80. return true;
  81. }
  82. static void i2c_slave_exit(struct i2c_ctx *ctx)
  83. {
  84. if (ctx->file == -1)
  85. return;
  86. close(ctx->file);
  87. free(ctx);
  88. }
  89. extern struct i2c_ctx *i2c_slave_open(char *i2c_bus, uint8_t slave_addr)
  90. {
  91. int file = open(i2c_bus, O_RDWR);
  92. if (file < 0) {
  93. applog(LOG_INFO, "Failed to open %s: %s", i2c_bus, strerror(errno));
  94. return NULL;
  95. }
  96. if (ioctl(file, I2C_SLAVE, slave_addr) < 0) {
  97. close(file);
  98. return NULL;
  99. }
  100. struct i2c_ctx *ctx = malloc(sizeof(*ctx));
  101. assert(ctx != NULL);
  102. ctx->addr = slave_addr;
  103. ctx->file = file;
  104. ctx->exit = i2c_slave_exit;
  105. ctx->read = i2c_slave_read;
  106. ctx->write = i2c_slave_write;
  107. ctx->read_raw = i2c_slave_read_raw;
  108. ctx->write_raw = i2c_slave_write_raw;
  109. return ctx;
  110. }