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 7 #define TYPE_I2C_ECHO "i2c-echo" 8 OBJECT_DECLARE_SIMPLE_TYPE(I2CEchoState, I2C_ECHO) 9 10 enum i2c_echo_state { 11 I2C_ECHO_STATE_IDLE, 12 I2C_ECHO_STATE_REQUEST_MASTER, 13 I2C_ECHO_STATE_START_SEND, 14 I2C_ECHO_STATE_ACK, 15 }; 16 17 typedef struct I2CEchoState { 18 I2CSlave parent_obj; 19 20 I2CBus *bus; 21 22 enum i2c_echo_state state; 23 QEMUBH *bh; 24 25 unsigned int pos; 26 uint8_t data[3]; 27 } I2CEchoState; 28 29 static void i2c_echo_bh(void *opaque) 30 { 31 I2CEchoState *state = opaque; 32 33 switch (state->state) { 34 case I2C_ECHO_STATE_IDLE: 35 return; 36 37 case I2C_ECHO_STATE_REQUEST_MASTER: 38 i2c_bus_master(state->bus, state->bh); 39 state->state = I2C_ECHO_STATE_START_SEND; 40 return; 41 42 case I2C_ECHO_STATE_START_SEND: 43 if (i2c_start_send_async(state->bus, state->data[0])) { 44 goto release_bus; 45 } 46 47 state->pos++; 48 state->state = I2C_ECHO_STATE_ACK; 49 return; 50 51 case I2C_ECHO_STATE_ACK: 52 if (state->pos > 2) { 53 break; 54 } 55 56 if (i2c_send_async(state->bus, state->data[state->pos++])) { 57 break; 58 } 59 60 return; 61 } 62 63 64 i2c_end_transfer(state->bus); 65 release_bus: 66 i2c_bus_release(state->bus); 67 68 state->state = I2C_ECHO_STATE_IDLE; 69 } 70 71 static int i2c_echo_event(I2CSlave *s, enum i2c_event event) 72 { 73 I2CEchoState *state = I2C_ECHO(s); 74 75 switch (event) { 76 case I2C_START_RECV: 77 state->pos = 0; 78 79 break; 80 81 case I2C_START_SEND: 82 state->pos = 0; 83 84 break; 85 86 case I2C_FINISH: 87 state->pos = 0; 88 state->state = I2C_ECHO_STATE_REQUEST_MASTER; 89 qemu_bh_schedule(state->bh); 90 91 break; 92 93 case I2C_NACK: 94 break; 95 96 default: 97 return -1; 98 } 99 100 return 0; 101 } 102 103 static uint8_t i2c_echo_recv(I2CSlave *s) 104 { 105 I2CEchoState *state = I2C_ECHO(s); 106 107 if (state->pos > 2) { 108 return 0xff; 109 } 110 111 return state->data[state->pos++]; 112 } 113 114 static int i2c_echo_send(I2CSlave *s, uint8_t data) 115 { 116 I2CEchoState *state = I2C_ECHO(s); 117 118 if (state->pos > 2) { 119 return -1; 120 } 121 122 state->data[state->pos++] = data; 123 124 return 0; 125 } 126 127 static void i2c_echo_realize(DeviceState *dev, Error **errp) 128 { 129 I2CEchoState *state = I2C_ECHO(dev); 130 BusState *bus = qdev_get_parent_bus(dev); 131 132 state->bus = I2C_BUS(bus); 133 state->bh = qemu_bh_new(i2c_echo_bh, state); 134 135 return; 136 } 137 138 static void i2c_echo_class_init(ObjectClass *oc, void *data) 139 { 140 I2CSlaveClass *sc = I2C_SLAVE_CLASS(oc); 141 DeviceClass *dc = DEVICE_CLASS(oc); 142 143 dc->realize = i2c_echo_realize; 144 145 sc->event = i2c_echo_event; 146 sc->recv = i2c_echo_recv; 147 sc->send = i2c_echo_send; 148 } 149 150 static const TypeInfo i2c_echo = { 151 .name = TYPE_I2C_ECHO, 152 .parent = TYPE_I2C_SLAVE, 153 .instance_size = sizeof(I2CEchoState), 154 .class_init = i2c_echo_class_init, 155 }; 156 157 static void register_types(void) 158 { 159 type_register_static(&i2c_echo); 160 } 161 162 type_init(register_types); 163