xref: /openbmc/qemu/hw/input/adb.c (revision 28004fb7)
1 /*
2  * QEMU ADB support
3  *
4  * Copyright (c) 2004 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 #include "qemu/osdep.h"
26 #include "hw/input/adb.h"
27 #include "hw/qdev-properties.h"
28 #include "migration/vmstate.h"
29 #include "qemu/module.h"
30 #include "qemu/timer.h"
31 #include "adb-internal.h"
32 #include "trace.h"
33 
34 /* error codes */
35 #define ADB_RET_NOTPRESENT (-2)
36 
37 static const char *adb_commands[] = {
38     "RESET", "FLUSH", "(Reserved 0x2)", "(Reserved 0x3)",
39     "Reserved (0x4)", "(Reserved 0x5)", "(Reserved 0x6)", "(Reserved 0x7)",
40     "LISTEN r0", "LISTEN r1", "LISTEN r2", "LISTEN r3",
41     "TALK r0", "TALK r1", "TALK r2", "TALK r3",
42 };
43 
44 static void adb_device_reset(ADBDevice *d)
45 {
46     device_cold_reset(DEVICE(d));
47 }
48 
49 static int do_adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf,
50                           int len)
51 {
52     ADBDevice *d;
53     ADBDeviceClass *adc;
54     int devaddr, cmd, olen, i;
55 
56     cmd = buf[0] & 0xf;
57     if (cmd == ADB_BUSRESET) {
58         for (i = 0; i < s->nb_devices; i++) {
59             d = s->devices[i];
60             adb_device_reset(d);
61         }
62         s->status = 0;
63         return 0;
64     }
65 
66     s->pending = 0;
67     for (i = 0; i < s->nb_devices; i++) {
68         d = s->devices[i];
69         adc = ADB_DEVICE_GET_CLASS(d);
70 
71         if (adc->devhasdata(d)) {
72             s->pending |= (1 << d->devaddr);
73         }
74     }
75 
76     s->status = 0;
77     devaddr = buf[0] >> 4;
78     for (i = 0; i < s->nb_devices; i++) {
79         d = s->devices[i];
80         adc = ADB_DEVICE_GET_CLASS(d);
81 
82         if (d->devaddr == devaddr) {
83             olen = adc->devreq(d, obuf, buf, len);
84             if (!olen) {
85                 s->status |= ADB_STATUS_BUSTIMEOUT;
86             }
87             return olen;
88         }
89     }
90 
91     s->status |= ADB_STATUS_BUSTIMEOUT;
92     return ADB_RET_NOTPRESENT;
93 }
94 
95 int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
96 {
97     int ret;
98 
99     trace_adb_bus_request(buf[0] >> 4, adb_commands[buf[0] & 0xf], len);
100 
101     assert(s->autopoll_blocked);
102 
103     ret = do_adb_request(s, obuf, buf, len);
104 
105     trace_adb_bus_request_done(buf[0] >> 4, adb_commands[buf[0] & 0xf], ret);
106     return ret;
107 }
108 
109 int adb_poll(ADBBusState *s, uint8_t *obuf, uint16_t poll_mask)
110 {
111     ADBDevice *d;
112     int olen, i;
113     uint8_t buf[1];
114 
115     olen = 0;
116     for (i = 0; i < s->nb_devices; i++) {
117         if (s->poll_index >= s->nb_devices) {
118             s->poll_index = 0;
119         }
120         d = s->devices[s->poll_index];
121         if ((1 << d->devaddr) & poll_mask) {
122             buf[0] = ADB_READREG | (d->devaddr << 4);
123             olen = do_adb_request(s, obuf + 1, buf, 1);
124             /* if there is data, we poll again the same device */
125             if (olen > 0) {
126                 s->status |= ADB_STATUS_POLLREPLY;
127                 obuf[0] = buf[0];
128                 olen++;
129                 return olen;
130             }
131         }
132         s->poll_index++;
133     }
134     return olen;
135 }
136 
137 void adb_set_autopoll_enabled(ADBBusState *s, bool enabled)
138 {
139     if (s->autopoll_enabled != enabled) {
140         s->autopoll_enabled = enabled;
141         if (s->autopoll_enabled) {
142             timer_mod(s->autopoll_timer,
143                       qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
144                       s->autopoll_rate_ms);
145         } else {
146             timer_del(s->autopoll_timer);
147         }
148     }
149 }
150 
151 void adb_set_autopoll_rate_ms(ADBBusState *s, int rate_ms)
152 {
153     s->autopoll_rate_ms = rate_ms;
154 
155     if (s->autopoll_enabled) {
156         timer_mod(s->autopoll_timer,
157                   qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
158                   s->autopoll_rate_ms);
159     }
160 }
161 
162 void adb_set_autopoll_mask(ADBBusState *s, uint16_t mask)
163 {
164     if (s->autopoll_mask != mask) {
165         s->autopoll_mask = mask;
166         if (s->autopoll_enabled && s->autopoll_mask) {
167             timer_mod(s->autopoll_timer,
168                       qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
169                       s->autopoll_rate_ms);
170         } else {
171             timer_del(s->autopoll_timer);
172         }
173     }
174 }
175 
176 void adb_autopoll_block(ADBBusState *s)
177 {
178     s->autopoll_blocked = true;
179     trace_adb_bus_autopoll_block(s->autopoll_blocked);
180 
181     if (s->autopoll_enabled) {
182         timer_del(s->autopoll_timer);
183     }
184 }
185 
186 void adb_autopoll_unblock(ADBBusState *s)
187 {
188     s->autopoll_blocked = false;
189     trace_adb_bus_autopoll_block(s->autopoll_blocked);
190 
191     if (s->autopoll_enabled) {
192         timer_mod(s->autopoll_timer,
193                   qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
194                   s->autopoll_rate_ms);
195     }
196 }
197 
198 static void adb_autopoll(void *opaque)
199 {
200     ADBBusState *s = opaque;
201 
202     if (!s->autopoll_blocked) {
203         trace_adb_bus_autopoll_cb(s->autopoll_mask);
204         s->autopoll_cb(s->autopoll_cb_opaque);
205         trace_adb_bus_autopoll_cb_done(s->autopoll_mask);
206     }
207 
208     timer_mod(s->autopoll_timer,
209               qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
210               s->autopoll_rate_ms);
211 }
212 
213 void adb_register_autopoll_callback(ADBBusState *s, void (*cb)(void *opaque),
214                                     void *opaque)
215 {
216     s->autopoll_cb = cb;
217     s->autopoll_cb_opaque = opaque;
218 }
219 
220 static const VMStateDescription vmstate_adb_bus = {
221     .name = "adb_bus",
222     .version_id = 0,
223     .minimum_version_id = 0,
224     .fields = (const VMStateField[]) {
225         VMSTATE_TIMER_PTR(autopoll_timer, ADBBusState),
226         VMSTATE_BOOL(autopoll_enabled, ADBBusState),
227         VMSTATE_UINT8(autopoll_rate_ms, ADBBusState),
228         VMSTATE_UINT16(autopoll_mask, ADBBusState),
229         VMSTATE_BOOL(autopoll_blocked, ADBBusState),
230         VMSTATE_END_OF_LIST()
231     }
232 };
233 
234 static void adb_bus_reset_hold(Object *obj)
235 {
236     ADBBusState *adb_bus = ADB_BUS(obj);
237 
238     adb_bus->autopoll_enabled = false;
239     adb_bus->autopoll_mask = 0xffff;
240     adb_bus->autopoll_rate_ms = 20;
241 }
242 
243 static void adb_bus_realize(BusState *qbus, Error **errp)
244 {
245     ADBBusState *adb_bus = ADB_BUS(qbus);
246 
247     adb_bus->autopoll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, adb_autopoll,
248                                            adb_bus);
249 
250     vmstate_register_any(NULL, &vmstate_adb_bus, adb_bus);
251 }
252 
253 static void adb_bus_unrealize(BusState *qbus)
254 {
255     ADBBusState *adb_bus = ADB_BUS(qbus);
256 
257     timer_del(adb_bus->autopoll_timer);
258 
259     vmstate_unregister(NULL, &vmstate_adb_bus, adb_bus);
260 }
261 
262 static void adb_bus_class_init(ObjectClass *klass, void *data)
263 {
264     BusClass *k = BUS_CLASS(klass);
265     ResettableClass *rc = RESETTABLE_CLASS(klass);
266 
267     k->realize = adb_bus_realize;
268     k->unrealize = adb_bus_unrealize;
269     rc->phases.hold = adb_bus_reset_hold;
270 }
271 
272 static const TypeInfo adb_bus_type_info = {
273     .name = TYPE_ADB_BUS,
274     .parent = TYPE_BUS,
275     .instance_size = sizeof(ADBBusState),
276     .class_init = adb_bus_class_init,
277 };
278 
279 const VMStateDescription vmstate_adb_device = {
280     .name = "adb_device",
281     .version_id = 0,
282     .minimum_version_id = 0,
283     .fields = (const VMStateField[]) {
284         VMSTATE_INT32(devaddr, ADBDevice),
285         VMSTATE_INT32(handler, ADBDevice),
286         VMSTATE_END_OF_LIST()
287     }
288 };
289 
290 static void adb_device_realizefn(DeviceState *dev, Error **errp)
291 {
292     ADBDevice *d = ADB_DEVICE(dev);
293     ADBBusState *bus = ADB_BUS(qdev_get_parent_bus(dev));
294 
295     if (bus->nb_devices >= MAX_ADB_DEVICES) {
296         return;
297     }
298 
299     bus->devices[bus->nb_devices++] = d;
300 }
301 
302 static void adb_device_class_init(ObjectClass *oc, void *data)
303 {
304     DeviceClass *dc = DEVICE_CLASS(oc);
305 
306     dc->realize = adb_device_realizefn;
307     dc->bus_type = TYPE_ADB_BUS;
308 }
309 
310 static const TypeInfo adb_device_type_info = {
311     .name = TYPE_ADB_DEVICE,
312     .parent = TYPE_DEVICE,
313     .class_size = sizeof(ADBDeviceClass),
314     .instance_size = sizeof(ADBDevice),
315     .abstract = true,
316     .class_init = adb_device_class_init,
317 };
318 
319 static void adb_register_types(void)
320 {
321     type_register_static(&adb_bus_type_info);
322     type_register_static(&adb_device_type_info);
323 }
324 
325 type_init(adb_register_types)
326