i2c-echo.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "qemu/osdep.h"
  2. #include "qemu/timer.h"
  3. #include "qemu/main-loop.h"
  4. #include "block/aio.h"
  5. #include "hw/i2c/i2c.h"
  6. #define TYPE_I2C_ECHO "i2c-echo"
  7. OBJECT_DECLARE_SIMPLE_TYPE(I2CEchoState, I2C_ECHO)
  8. enum i2c_echo_state {
  9. I2C_ECHO_STATE_IDLE,
  10. I2C_ECHO_STATE_START_SEND,
  11. I2C_ECHO_STATE_ACK,
  12. };
  13. typedef struct I2CEchoState {
  14. I2CSlave parent_obj;
  15. I2CBus *bus;
  16. enum i2c_echo_state state;
  17. QEMUBH *bh;
  18. unsigned int pos;
  19. uint8_t data[3];
  20. } I2CEchoState;
  21. static void i2c_echo_bh(void *opaque)
  22. {
  23. I2CEchoState *state = opaque;
  24. switch (state->state) {
  25. case I2C_ECHO_STATE_IDLE:
  26. return;
  27. case I2C_ECHO_STATE_START_SEND:
  28. if (i2c_start_send_async(state->bus, state->data[0])) {
  29. goto release_bus;
  30. }
  31. state->pos++;
  32. state->state = I2C_ECHO_STATE_ACK;
  33. return;
  34. case I2C_ECHO_STATE_ACK:
  35. if (state->pos > 2) {
  36. break;
  37. }
  38. if (i2c_send_async(state->bus, state->data[state->pos++])) {
  39. break;
  40. }
  41. return;
  42. }
  43. i2c_end_transfer(state->bus);
  44. release_bus:
  45. i2c_bus_release(state->bus);
  46. state->state = I2C_ECHO_STATE_IDLE;
  47. }
  48. static int i2c_echo_event(I2CSlave *s, enum i2c_event event)
  49. {
  50. I2CEchoState *state = I2C_ECHO(s);
  51. switch (event) {
  52. case I2C_START_RECV:
  53. state->pos = 0;
  54. break;
  55. case I2C_START_SEND:
  56. state->pos = 0;
  57. break;
  58. case I2C_FINISH:
  59. state->pos = 0;
  60. state->state = I2C_ECHO_STATE_START_SEND;
  61. i2c_bus_master(state->bus, state->bh);
  62. break;
  63. case I2C_NACK:
  64. break;
  65. default:
  66. return -1;
  67. }
  68. return 0;
  69. }
  70. static uint8_t i2c_echo_recv(I2CSlave *s)
  71. {
  72. I2CEchoState *state = I2C_ECHO(s);
  73. if (state->pos > 2) {
  74. return 0xff;
  75. }
  76. return state->data[state->pos++];
  77. }
  78. static int i2c_echo_send(I2CSlave *s, uint8_t data)
  79. {
  80. I2CEchoState *state = I2C_ECHO(s);
  81. if (state->pos > 2) {
  82. return -1;
  83. }
  84. state->data[state->pos++] = data;
  85. return 0;
  86. }
  87. static void i2c_echo_realize(DeviceState *dev, Error **errp)
  88. {
  89. I2CEchoState *state = I2C_ECHO(dev);
  90. BusState *bus = qdev_get_parent_bus(dev);
  91. state->bus = I2C_BUS(bus);
  92. state->bh = qemu_bh_new(i2c_echo_bh, state);
  93. return;
  94. }
  95. static void i2c_echo_class_init(ObjectClass *oc, void *data)
  96. {
  97. I2CSlaveClass *sc = I2C_SLAVE_CLASS(oc);
  98. DeviceClass *dc = DEVICE_CLASS(oc);
  99. dc->realize = i2c_echo_realize;
  100. sc->event = i2c_echo_event;
  101. sc->recv = i2c_echo_recv;
  102. sc->send = i2c_echo_send;
  103. }
  104. static const TypeInfo i2c_echo = {
  105. .name = TYPE_I2C_ECHO,
  106. .parent = TYPE_I2C_SLAVE,
  107. .instance_size = sizeof(I2CEchoState),
  108. .class_init = i2c_echo_class_init,
  109. };
  110. static void register_types(void)
  111. {
  112. type_register_static(&i2c_echo);
  113. }
  114. type_init(register_types);