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