qemu

Форк
0
/
i2c-echo.c 
166 строк · 3.1 Кб
1
/*
2
 * Example I2C device using asynchronous I2C send.
3
 *
4
 * Copyright (C) 2023 Samsung Electronics Co., Ltd. All Rights Reserved.
5
 *
6
 * This work is licensed under the terms of the GNU GPL, version 2.  See
7
 * the COPYING file in the top-level directory.
8
 *
9
 */
10

11
#include "qemu/osdep.h"
12
#include "qemu/timer.h"
13
#include "qemu/main-loop.h"
14
#include "block/aio.h"
15
#include "hw/i2c/i2c.h"
16

17
#define TYPE_I2C_ECHO "i2c-echo"
18
OBJECT_DECLARE_SIMPLE_TYPE(I2CEchoState, I2C_ECHO)
19

20
enum i2c_echo_state {
21
    I2C_ECHO_STATE_IDLE,
22
    I2C_ECHO_STATE_START_SEND,
23
    I2C_ECHO_STATE_ACK,
24
};
25

26
typedef struct I2CEchoState {
27
    I2CSlave parent_obj;
28

29
    I2CBus *bus;
30

31
    enum i2c_echo_state state;
32
    QEMUBH *bh;
33

34
    unsigned int pos;
35
    uint8_t data[3];
36
} I2CEchoState;
37

38
static void i2c_echo_bh(void *opaque)
39
{
40
    I2CEchoState *state = opaque;
41

42
    switch (state->state) {
43
    case I2C_ECHO_STATE_IDLE:
44
        return;
45

46
    case I2C_ECHO_STATE_START_SEND:
47
        if (i2c_start_send_async(state->bus, state->data[0])) {
48
            goto release_bus;
49
        }
50

51
        state->pos++;
52
        state->state = I2C_ECHO_STATE_ACK;
53
        return;
54

55
    case I2C_ECHO_STATE_ACK:
56
        if (state->pos > 2) {
57
            break;
58
        }
59

60
        if (i2c_send_async(state->bus, state->data[state->pos++])) {
61
            break;
62
        }
63

64
        return;
65
    }
66

67

68
    i2c_end_transfer(state->bus);
69
release_bus:
70
    i2c_bus_release(state->bus);
71

72
    state->state = I2C_ECHO_STATE_IDLE;
73
}
74

75
static int i2c_echo_event(I2CSlave *s, enum i2c_event event)
76
{
77
    I2CEchoState *state = I2C_ECHO(s);
78

79
    switch (event) {
80
    case I2C_START_RECV:
81
        state->pos = 0;
82

83
        break;
84

85
    case I2C_START_SEND:
86
        state->pos = 0;
87

88
        break;
89

90
    case I2C_FINISH:
91
        state->pos = 0;
92
        state->state = I2C_ECHO_STATE_START_SEND;
93
        i2c_bus_master(state->bus, state->bh);
94

95
        break;
96

97
    case I2C_NACK:
98
        break;
99

100
    default:
101
        return -1;
102
    }
103

104
    return 0;
105
}
106

107
static uint8_t i2c_echo_recv(I2CSlave *s)
108
{
109
    I2CEchoState *state = I2C_ECHO(s);
110

111
    if (state->pos > 2) {
112
        return 0xff;
113
    }
114

115
    return state->data[state->pos++];
116
}
117

118
static int i2c_echo_send(I2CSlave *s, uint8_t data)
119
{
120
    I2CEchoState *state = I2C_ECHO(s);
121

122
    if (state->pos > 2) {
123
        return -1;
124
    }
125

126
    state->data[state->pos++] = data;
127

128
    return 0;
129
}
130

131
static void i2c_echo_realize(DeviceState *dev, Error **errp)
132
{
133
    I2CEchoState *state = I2C_ECHO(dev);
134
    BusState *bus = qdev_get_parent_bus(dev);
135

136
    state->bus = I2C_BUS(bus);
137
    state->bh = qemu_bh_new(i2c_echo_bh, state);
138

139
    return;
140
}
141

142
static void i2c_echo_class_init(ObjectClass *oc, void *data)
143
{
144
    I2CSlaveClass *sc = I2C_SLAVE_CLASS(oc);
145
    DeviceClass *dc = DEVICE_CLASS(oc);
146

147
    dc->realize = i2c_echo_realize;
148

149
    sc->event = i2c_echo_event;
150
    sc->recv = i2c_echo_recv;
151
    sc->send = i2c_echo_send;
152
}
153

154
static const TypeInfo i2c_echo = {
155
    .name = TYPE_I2C_ECHO,
156
    .parent = TYPE_I2C_SLAVE,
157
    .instance_size = sizeof(I2CEchoState),
158
    .class_init = i2c_echo_class_init,
159
};
160

161
static void register_types(void)
162
{
163
    type_register_static(&i2c_echo);
164
}
165

166
type_init(register_types);
167

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.