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
adb_device_reset(ADBDevice * d)44 static void adb_device_reset(ADBDevice *d)
45 {
46 device_cold_reset(DEVICE(d));
47 }
48
do_adb_request(ADBBusState * s,uint8_t * obuf,const uint8_t * buf,int len)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
adb_request(ADBBusState * s,uint8_t * obuf,const uint8_t * buf,int len)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
adb_poll(ADBBusState * s,uint8_t * obuf,uint16_t poll_mask)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
adb_set_autopoll_enabled(ADBBusState * s,bool enabled)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
adb_set_autopoll_rate_ms(ADBBusState * s,int rate_ms)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
adb_set_autopoll_mask(ADBBusState * s,uint16_t mask)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
adb_autopoll_block(ADBBusState * s)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
adb_autopoll_unblock(ADBBusState * s)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
adb_autopoll(void * opaque)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
adb_register_autopoll_callback(ADBBusState * s,void (* cb)(void * opaque),void * opaque)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
adb_bus_reset_hold(Object * obj,ResetType type)234 static void adb_bus_reset_hold(Object *obj, ResetType type)
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
adb_bus_realize(BusState * qbus,Error ** errp)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
adb_bus_unrealize(BusState * qbus)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
adb_bus_class_init(ObjectClass * klass,void * data)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
adb_device_realizefn(DeviceState * dev,Error ** errp)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
adb_device_class_init(ObjectClass * oc,void * data)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
adb_register_types(void)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