|
1 #include "Python.h" |
|
2 #include "structmember.h" |
|
3 #include "hw/hw.h" |
|
4 #include "sysemu.h" |
|
5 #include "devtree.h" |
|
6 #include "qemu-char.h" |
|
7 #include "display_state.h" |
|
8 #include "hw/gui.h" |
|
9 #include "hw/fb_render_engine.h" |
|
10 #include "qemu-timer.h" |
|
11 |
|
12 static void qemu_py_die(void) |
|
13 { |
|
14 PyErr_Print(); |
|
15 exit(1); |
|
16 } |
|
17 |
|
18 #define qemu_py_assert(x) do { if (!(x)) { qemu_py_die(); } } while (0) |
|
19 |
|
20 static void qemu_py_load_module(const char *name) |
|
21 { |
|
22 PyObject *module; |
|
23 module = PyImport_ImportModule(name); |
|
24 if (!module) |
|
25 qemu_py_die(); |
|
26 } |
|
27 |
|
28 static int64_t qemu_py_int64_from_pynum(PyObject *ob) |
|
29 { |
|
30 if (PyInt_Check(ob)) |
|
31 return PyInt_AsLong(ob); |
|
32 return PyLong_AsLongLong(ob); |
|
33 } |
|
34 |
|
35 static uint64_t qemu_py_uint64_from_pynum(PyObject *ob) |
|
36 { |
|
37 if (PyInt_Check(ob)) |
|
38 return PyInt_AsUnsignedLongMask(ob); |
|
39 return PyLong_AsUnsignedLongLongMask(ob); |
|
40 } |
|
41 |
|
42 typedef struct { |
|
43 PyObject_HEAD |
|
44 PyObject *size; |
|
45 PyObject *readl; |
|
46 PyObject *writel; |
|
47 } qemu_py_ioregion; |
|
48 |
|
49 static void qemu_py_ioregion_dealloc(qemu_py_ioregion *self) |
|
50 { |
|
51 Py_CLEAR(self->size); |
|
52 Py_CLEAR(self->readl); |
|
53 Py_CLEAR(self->writel); |
|
54 self->ob_type->tp_free((PyObject*)self); |
|
55 } |
|
56 |
|
57 static int qemu_py_ioregion_init(qemu_py_ioregion *self, PyObject *args, |
|
58 PyObject *kwds) |
|
59 { |
|
60 static char *kwlist[] = {"size", "readl", "writel", NULL}; |
|
61 PyObject *obsize; |
|
62 PyObject *readl; |
|
63 PyObject *writel; |
|
64 |
|
65 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, |
|
66 &obsize, &readl, &writel)) |
|
67 return -1; |
|
68 |
|
69 Py_INCREF(obsize); |
|
70 self->size = obsize; |
|
71 Py_INCREF(readl); |
|
72 self->readl = readl; |
|
73 Py_INCREF(writel); |
|
74 self->writel = writel; |
|
75 |
|
76 return 0; |
|
77 } |
|
78 |
|
79 static PyMemberDef qemu_py_ioregion_members[] = { |
|
80 {"size", T_OBJECT, offsetof(qemu_py_ioregion, size), 0, |
|
81 "size"}, |
|
82 {"readl", T_OBJECT, offsetof(qemu_py_ioregion, readl), 0, |
|
83 "32-bit read"}, |
|
84 {"writel", T_OBJECT, offsetof(qemu_py_ioregion, writel), 0, |
|
85 "32-bit write"}, |
|
86 {NULL} /* Sentinel */ |
|
87 }; |
|
88 |
|
89 static PyTypeObject qemu_py_ioregionType = { |
|
90 PyObject_HEAD_INIT(NULL) |
|
91 0, /* ob_size */ |
|
92 "qemu.ioregion", /* tp_name */ |
|
93 sizeof(qemu_py_ioregion), /* tp_basicsize */ |
|
94 0, /* tp_itemsize */ |
|
95 (destructor)qemu_py_ioregion_dealloc, /* tp_dealloc */ |
|
96 0, /* tp_print */ |
|
97 0, /* tp_getattr */ |
|
98 0, /* tp_setattr */ |
|
99 0, /* tp_compare */ |
|
100 0, /* tp_repr */ |
|
101 0, /* tp_as_number */ |
|
102 0, /* tp_as_sequence */ |
|
103 0, /* tp_as_mapping */ |
|
104 0, /* tp_hash */ |
|
105 0, /* tp_call */ |
|
106 0, /* tp_str */ |
|
107 0, /* tp_getattro */ |
|
108 0, /* tp_setattro */ |
|
109 0, /* tp_as_buffer */ |
|
110 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
111 "QEMU IORegion", /* tp_doc */ |
|
112 0, /* tp_traverse */ |
|
113 0, /* tp_clear */ |
|
114 0, /* tp_richcompare */ |
|
115 0, /* tp_weaklistoffset */ |
|
116 0, /* tp_iter */ |
|
117 0, /* tp_iternext */ |
|
118 0, /* tp_methods */ |
|
119 qemu_py_ioregion_members, /* tp_members */ |
|
120 0, /* tp_getset */ |
|
121 0, /* tp_base */ |
|
122 0, /* tp_dict */ |
|
123 0, /* tp_descr_get */ |
|
124 0, /* tp_descr_set */ |
|
125 0, /* tp_dictoffset */ |
|
126 (initproc)qemu_py_ioregion_init, /* tp_init */ |
|
127 0, /* tp_alloc */ |
|
128 0, /* tp_new */ |
|
129 }; |
|
130 |
|
131 typedef struct { |
|
132 PyObject_HEAD |
|
133 QEMUFile *f; |
|
134 } qemu_py_file; |
|
135 |
|
136 static void qemu_py_file_dealloc(qemu_py_file *self) |
|
137 { |
|
138 self->f = NULL; |
|
139 self->ob_type->tp_free((PyObject*)self); |
|
140 } |
|
141 |
|
142 static int qemu_py_file_init(qemu_py_file *self, PyObject *args, |
|
143 PyObject *kwds) |
|
144 { |
|
145 static char *kwlist[] = {"f", NULL}; |
|
146 PyObject *obdata; |
|
147 |
|
148 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obdata)) |
|
149 return -1; |
|
150 |
|
151 self->f = PyCObject_AsVoidPtr(obdata); |
|
152 if (PyErr_Occurred()) |
|
153 return -1; |
|
154 |
|
155 return 0; |
|
156 } |
|
157 |
|
158 static PyObject *qemu_py_file_get_u32(qemu_py_file *self, PyObject *args) |
|
159 { |
|
160 uint32_t val; |
|
161 |
|
162 if (self->f) { |
|
163 val = qemu_get_be32(self->f); |
|
164 return PyLong_FromUnsignedLong(val); |
|
165 } |
|
166 Py_RETURN_NONE; |
|
167 } |
|
168 |
|
169 static PyObject *qemu_py_file_put_u32(qemu_py_file *self, |
|
170 PyObject *args, PyObject *kwds) |
|
171 { |
|
172 static char *kwlist[] = {"value", NULL}; |
|
173 PyObject *obval; |
|
174 uint32_t val; |
|
175 |
|
176 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obval)) |
|
177 return NULL; |
|
178 |
|
179 val = qemu_py_uint64_from_pynum(obval); |
|
180 if (PyErr_Occurred()) |
|
181 return NULL; |
|
182 |
|
183 if (self->f) |
|
184 qemu_put_be32(self->f, val); |
|
185 |
|
186 Py_RETURN_NONE; |
|
187 } |
|
188 |
|
189 static PyObject *qemu_py_file_get_u64(qemu_py_file *self, PyObject *args) |
|
190 { |
|
191 uint64_t val; |
|
192 |
|
193 if (self->f) { |
|
194 val = qemu_get_be64(self->f); |
|
195 return PyLong_FromUnsignedLongLong(val); |
|
196 } |
|
197 Py_RETURN_NONE; |
|
198 } |
|
199 |
|
200 static PyObject *qemu_py_file_get_s64(qemu_py_file *self, PyObject *args) |
|
201 { |
|
202 int64_t val; |
|
203 |
|
204 if (self->f) { |
|
205 val = qemu_get_be64(self->f); |
|
206 return PyLong_FromLongLong(val); |
|
207 } |
|
208 Py_RETURN_NONE; |
|
209 } |
|
210 |
|
211 static PyObject *qemu_py_file_put_u64(qemu_py_file *self, |
|
212 PyObject *args, PyObject *kwds) |
|
213 { |
|
214 static char *kwlist[] = {"value", NULL}; |
|
215 PyObject *obval; |
|
216 uint64_t val; |
|
217 |
|
218 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obval)) |
|
219 return NULL; |
|
220 |
|
221 val = qemu_py_uint64_from_pynum(obval); |
|
222 if (PyErr_Occurred()) |
|
223 return NULL; |
|
224 |
|
225 if (self->f) |
|
226 qemu_put_be64(self->f, val); |
|
227 |
|
228 Py_RETURN_NONE; |
|
229 } |
|
230 |
|
231 static PyObject *qemu_py_file_put_s64(qemu_py_file *self, |
|
232 PyObject *args, PyObject *kwds) |
|
233 { |
|
234 static char *kwlist[] = {"value", NULL}; |
|
235 PyObject *obval; |
|
236 int64_t val; |
|
237 |
|
238 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obval)) |
|
239 return NULL; |
|
240 |
|
241 val = qemu_py_int64_from_pynum(obval); |
|
242 if (PyErr_Occurred()) |
|
243 return NULL; |
|
244 |
|
245 if (self->f) |
|
246 qemu_put_be64(self->f, val); |
|
247 |
|
248 Py_RETURN_NONE; |
|
249 } |
|
250 |
|
251 static PyMethodDef qemu_py_file_methods[] = { |
|
252 {"get_u32", (PyCFunction)qemu_py_file_get_u32, METH_NOARGS, |
|
253 "Read unsigned 32-bit value"}, |
|
254 {"put_u32", (PyCFunction)qemu_py_file_put_u32, METH_VARARGS|METH_KEYWORDS, |
|
255 "Write unsigned 32-bit value"}, |
|
256 {"get_u64", (PyCFunction)qemu_py_file_get_u64, METH_NOARGS, |
|
257 "Read unsigned 64-bit value"}, |
|
258 {"put_u64", (PyCFunction)qemu_py_file_put_u64, METH_VARARGS|METH_KEYWORDS, |
|
259 "Write unsigned 64-bit value"}, |
|
260 {"get_s64", (PyCFunction)qemu_py_file_get_s64, METH_NOARGS, |
|
261 "Read signed 64-bit value"}, |
|
262 {"put_s64", (PyCFunction)qemu_py_file_put_s64, METH_VARARGS|METH_KEYWORDS, |
|
263 "Write signed 64-bit value"}, |
|
264 {NULL} /* Sentinel */ |
|
265 }; |
|
266 |
|
267 static PyTypeObject qemu_py_fileType = { |
|
268 PyObject_HEAD_INIT(NULL) |
|
269 0, /* ob_size */ |
|
270 "qemu.file", /* tp_name */ |
|
271 sizeof(qemu_py_file), /* tp_basicsize */ |
|
272 0, /* tp_itemsize */ |
|
273 (destructor)qemu_py_file_dealloc, /* tp_dealloc */ |
|
274 0, /* tp_print */ |
|
275 0, /* tp_getattr */ |
|
276 0, /* tp_setattr */ |
|
277 0, /* tp_compare */ |
|
278 0, /* tp_repr */ |
|
279 0, /* tp_as_number */ |
|
280 0, /* tp_as_sequence */ |
|
281 0, /* tp_as_mapping */ |
|
282 0, /* tp_hash */ |
|
283 0, /* tp_call */ |
|
284 0, /* tp_str */ |
|
285 0, /* tp_getattro */ |
|
286 0, /* tp_setattro */ |
|
287 0, /* tp_as_buffer */ |
|
288 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
289 "QEMU File Object", /* tp_doc */ |
|
290 0, /* tp_traverse */ |
|
291 0, /* tp_clear */ |
|
292 0, /* tp_richcompare */ |
|
293 0, /* tp_weaklistoffset */ |
|
294 0, /* tp_iter */ |
|
295 0, /* tp_iternext */ |
|
296 qemu_py_file_methods, /* tp_methods */ |
|
297 0, /* tp_members */ |
|
298 0, /* tp_getset */ |
|
299 0, /* tp_base */ |
|
300 0, /* tp_dict */ |
|
301 0, /* tp_descr_get */ |
|
302 0, /* tp_descr_set */ |
|
303 0, /* tp_dictoffset */ |
|
304 (initproc)qemu_py_file_init, /* tp_init */ |
|
305 0, /* tp_alloc */ |
|
306 0, /* tp_new */ |
|
307 }; |
|
308 |
|
309 typedef struct { |
|
310 PyObject_HEAD |
|
311 ptimer_state *ptimer; |
|
312 } qemu_py_ptimer; |
|
313 |
|
314 static void qemu_py_ptimer_dealloc(qemu_py_ptimer *self) |
|
315 { |
|
316 self->ptimer = NULL; |
|
317 self->ob_type->tp_free((PyObject*)self); |
|
318 } |
|
319 |
|
320 static void qemu_py_ptimer_tick(void *opaque) |
|
321 { |
|
322 PyObject *fn = opaque; |
|
323 PyObject *obval; |
|
324 |
|
325 obval = PyObject_CallFunctionObjArgs(fn, NULL); |
|
326 qemu_py_assert(obval); |
|
327 Py_DECREF(obval); |
|
328 } |
|
329 |
|
330 static int qemu_py_ptimer_init(qemu_py_ptimer *self, PyObject *args, |
|
331 PyObject *kwds) |
|
332 { |
|
333 static char *kwlist[] = {"tick", "freq", NULL}; |
|
334 PyObject *tick; |
|
335 PyObject *obfreq = NULL; |
|
336 uint64_t freq; |
|
337 QEMUBH *bh; |
|
338 |
|
339 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, |
|
340 &tick, &obfreq)) |
|
341 return -1; |
|
342 |
|
343 if (!PyCallable_Check(tick)) { |
|
344 PyErr_SetString(PyExc_TypeError, "tick handler must be callable"); |
|
345 return -1; |
|
346 } |
|
347 if (obfreq) { |
|
348 freq = qemu_py_uint64_from_pynum(obfreq); |
|
349 if (PyErr_Occurred()) |
|
350 return -1; |
|
351 } else { |
|
352 freq = 0; |
|
353 } |
|
354 Py_INCREF(tick); |
|
355 bh = qemu_bh_new(qemu_py_ptimer_tick, tick); |
|
356 self->ptimer = ptimer_init(bh); |
|
357 if (freq) |
|
358 ptimer_set_freq(self->ptimer, freq); |
|
359 |
|
360 return 0; |
|
361 } |
|
362 |
|
363 static PyObject *qemu_py_ptimer_run(qemu_py_ptimer *self, |
|
364 PyObject *args, PyObject *kwds) |
|
365 { |
|
366 static char *kwlist[] = {"oneshot", NULL}; |
|
367 int oneshot; |
|
368 |
|
369 if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &oneshot)) |
|
370 return NULL; |
|
371 |
|
372 ptimer_run(self->ptimer, oneshot != 0); |
|
373 Py_RETURN_NONE; |
|
374 } |
|
375 |
|
376 static PyObject *qemu_py_ptimer_stop(qemu_py_ptimer *self, PyObject *args) |
|
377 { |
|
378 ptimer_stop(self->ptimer); |
|
379 Py_RETURN_NONE; |
|
380 } |
|
381 |
|
382 static PyObject *qemu_py_ptimer_set_limit(qemu_py_ptimer *self, |
|
383 PyObject *args, PyObject *kwds) |
|
384 { |
|
385 static char *kwlist[] = {"limit", "reload", NULL}; |
|
386 PyObject *oblimit; |
|
387 uint64_t limit; |
|
388 int reload; |
|
389 |
|
390 if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &oblimit, |
|
391 &reload)) |
|
392 return NULL; |
|
393 |
|
394 limit = qemu_py_uint64_from_pynum(oblimit); |
|
395 if (PyErr_Occurred()) |
|
396 return NULL; |
|
397 |
|
398 ptimer_set_limit(self->ptimer, limit, reload != 0); |
|
399 |
|
400 Py_RETURN_NONE; |
|
401 } |
|
402 |
|
403 static PyObject *qemu_py_ptimer_get(qemu_py_ptimer *self, |
|
404 PyObject *args, PyObject *kwds) |
|
405 { |
|
406 static char *kwlist[] = {"f", NULL}; |
|
407 qemu_py_file *f; |
|
408 |
|
409 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, |
|
410 &qemu_py_fileType, &f)) |
|
411 return NULL; |
|
412 |
|
413 qemu_get_ptimer(f->f, self->ptimer); |
|
414 |
|
415 Py_RETURN_NONE; |
|
416 } |
|
417 |
|
418 static PyObject *qemu_py_ptimer_put(qemu_py_ptimer *self, |
|
419 PyObject *args, PyObject *kwds) |
|
420 { |
|
421 static char *kwlist[] = {"f", NULL}; |
|
422 qemu_py_file *f; |
|
423 |
|
424 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, |
|
425 &qemu_py_fileType, &f)) |
|
426 return NULL; |
|
427 |
|
428 qemu_put_ptimer(f->f, self->ptimer); |
|
429 |
|
430 Py_RETURN_NONE; |
|
431 } |
|
432 |
|
433 static PyObject *qemu_py_ptimer_get_count(qemu_py_ptimer *self, void *closure) |
|
434 { |
|
435 return PyLong_FromUnsignedLongLong(ptimer_get_count(self->ptimer)); |
|
436 } |
|
437 |
|
438 static int qemu_py_ptimer_set_count(qemu_py_ptimer *self, PyObject *obval, |
|
439 void *closure) |
|
440 { |
|
441 uint64_t val; |
|
442 if (obval == NULL) { |
|
443 PyErr_SetString(PyExc_TypeError, "Cannot delete ptimer count"); |
|
444 return -1; |
|
445 } |
|
446 |
|
447 val = qemu_py_uint64_from_pynum(obval); |
|
448 if (PyErr_Occurred()) |
|
449 return -1; |
|
450 |
|
451 ptimer_set_count(self->ptimer, val); |
|
452 |
|
453 return 0; |
|
454 } |
|
455 |
|
456 static PyGetSetDef qemu_py_ptimer_getseters [] = { |
|
457 {"count", (getter)qemu_py_ptimer_get_count, |
|
458 (setter)qemu_py_ptimer_set_count, |
|
459 "current counter value", NULL}, |
|
460 {NULL} /* Sentinel */ |
|
461 }; |
|
462 |
|
463 static PyMethodDef qemu_py_ptimer_methods[] = { |
|
464 {"run", (PyCFunction)qemu_py_ptimer_run, METH_VARARGS|METH_KEYWORDS, |
|
465 "Start timer"}, |
|
466 {"stop", (PyCFunction)qemu_py_ptimer_stop, METH_NOARGS, |
|
467 "Stop timer"}, |
|
468 {"set_limit", (PyCFunction)qemu_py_ptimer_set_limit, |
|
469 METH_VARARGS|METH_KEYWORDS, |
|
470 "Set reload value"}, |
|
471 {"get", (PyCFunction)qemu_py_ptimer_get, METH_VARARGS|METH_KEYWORDS, |
|
472 "Restore state"}, |
|
473 {"put", (PyCFunction)qemu_py_ptimer_put, METH_VARARGS|METH_KEYWORDS, |
|
474 "Save state"}, |
|
475 {NULL} /* Sentinel */ |
|
476 }; |
|
477 |
|
478 static PyTypeObject qemu_py_ptimerType = { |
|
479 PyObject_HEAD_INIT(NULL) |
|
480 0, /* ob_size */ |
|
481 "qemu.ptimer", /* tp_name */ |
|
482 sizeof(qemu_py_ptimer), /* tp_basicsize */ |
|
483 0, /* tp_itemsize */ |
|
484 (destructor)qemu_py_ptimer_dealloc, /* tp_dealloc */ |
|
485 0, /* tp_print */ |
|
486 0, /* tp_getattr */ |
|
487 0, /* tp_setattr */ |
|
488 0, /* tp_compare */ |
|
489 0, /* tp_repr */ |
|
490 0, /* tp_as_number */ |
|
491 0, /* tp_as_sequence */ |
|
492 0, /* tp_as_mapping */ |
|
493 0, /* tp_hash */ |
|
494 0, /* tp_call */ |
|
495 0, /* tp_str */ |
|
496 0, /* tp_getattro */ |
|
497 0, /* tp_setattro */ |
|
498 0, /* tp_as_buffer */ |
|
499 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
500 "QEMU Periodic Timer", /* tp_doc */ |
|
501 0, /* tp_traverse */ |
|
502 0, /* tp_clear */ |
|
503 0, /* tp_richcompare */ |
|
504 0, /* tp_weaklistoffset */ |
|
505 0, /* tp_iter */ |
|
506 0, /* tp_iternext */ |
|
507 qemu_py_ptimer_methods, /* tp_methods */ |
|
508 0, /* tp_members */ |
|
509 qemu_py_ptimer_getseters, /* tp_getset */ |
|
510 0, /* tp_base */ |
|
511 0, /* tp_dict */ |
|
512 0, /* tp_descr_get */ |
|
513 0, /* tp_descr_set */ |
|
514 0, /* tp_dictoffset */ |
|
515 (initproc)qemu_py_ptimer_init, /* tp_init */ |
|
516 0, /* tp_alloc */ |
|
517 0, /* tp_new */ |
|
518 }; |
|
519 |
|
520 typedef struct { |
|
521 PyObject_HEAD |
|
522 render_data *rdata; |
|
523 } qemu_py_palette; |
|
524 |
|
525 static void qemu_py_palette_dealloc(qemu_py_palette *self) |
|
526 { |
|
527 self->rdata = NULL; |
|
528 self->ob_type->tp_free((PyObject*)self); |
|
529 } |
|
530 |
|
531 static int qemu_py_palette_init(qemu_py_palette *self, PyObject *args, |
|
532 PyObject *kwds) |
|
533 { |
|
534 static char *kwlist[] = {"rdata", NULL}; |
|
535 PyObject *obdata; |
|
536 |
|
537 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obdata)) |
|
538 return -1; |
|
539 |
|
540 self->rdata = PyCObject_AsVoidPtr(obdata); |
|
541 if (PyErr_Occurred()) |
|
542 return -1; |
|
543 |
|
544 return 0; |
|
545 } |
|
546 |
|
547 static Py_ssize_t qemu_py_palette_len(PyObject *o) |
|
548 { |
|
549 return 256; |
|
550 } |
|
551 |
|
552 static PyObject *qemu_py_palette_getitem(PyObject *o, Py_ssize_t i) |
|
553 { |
|
554 qemu_py_palette *self = (qemu_py_palette *)o; |
|
555 |
|
556 if (i < 0 || i >= 256) { |
|
557 PyErr_SetString(PyExc_ValueError, "Palette index must be 0-255"); |
|
558 return NULL; |
|
559 } |
|
560 |
|
561 return PyLong_FromUnsignedLong(get_palette_value(self->rdata, i)); |
|
562 } |
|
563 |
|
564 static int qemu_py_palette_setitem(PyObject *o, Py_ssize_t i, PyObject *obval) |
|
565 { |
|
566 qemu_py_palette *self = (qemu_py_palette *)o; |
|
567 uint32_t val; |
|
568 |
|
569 if (i < 0 || i >= 256) { |
|
570 PyErr_SetString(PyExc_ValueError, "Palette index must be 0-255"); |
|
571 return -1; |
|
572 } |
|
573 |
|
574 val = PyLong_AsUnsignedLongMask(obval); |
|
575 if (PyErr_Occurred()) |
|
576 return -1; |
|
577 set_palette_value(self->rdata, i, val); |
|
578 return 0; |
|
579 } |
|
580 |
|
581 static PySequenceMethods qemu_py_palette_seq = { |
|
582 .sq_length = qemu_py_palette_len, |
|
583 .sq_item = qemu_py_palette_getitem, |
|
584 .sq_ass_item = qemu_py_palette_setitem |
|
585 }; |
|
586 |
|
587 static PyTypeObject qemu_py_paletteType = { |
|
588 PyObject_HEAD_INIT(NULL) |
|
589 0, /* ob_size */ |
|
590 "qemu.palette", /* tp_name */ |
|
591 sizeof(qemu_py_palette), /* tp_basicsize */ |
|
592 0, /* tp_itemsize */ |
|
593 (destructor)qemu_py_palette_dealloc, /* tp_dealloc */ |
|
594 0, /* tp_print */ |
|
595 0, /* tp_getattr */ |
|
596 0, /* tp_setattr */ |
|
597 0, /* tp_compare */ |
|
598 0, /* tp_repr */ |
|
599 0, /* tp_as_number */ |
|
600 &qemu_py_palette_seq, /* tp_as_sequence */ |
|
601 0, /* tp_as_mapping */ |
|
602 0, /* tp_hash */ |
|
603 0, /* tp_call */ |
|
604 0, /* tp_str */ |
|
605 0, /* tp_getattro */ |
|
606 0, /* tp_setattro */ |
|
607 0, /* tp_as_buffer */ |
|
608 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
609 "QEMU Framebuffer Palette", /* tp_doc */ |
|
610 0, /* tp_traverse */ |
|
611 0, /* tp_clear */ |
|
612 0, /* tp_richcompare */ |
|
613 0, /* tp_weaklistoffset */ |
|
614 0, /* tp_iter */ |
|
615 0, /* tp_iternext */ |
|
616 0, /* tp_methods */ |
|
617 0, /* tp_members */ |
|
618 0, /* tp_getset */ |
|
619 0, /* tp_base */ |
|
620 0, /* tp_dict */ |
|
621 0, /* tp_descr_get */ |
|
622 0, /* tp_descr_set */ |
|
623 0, /* tp_dictoffset */ |
|
624 (initproc)qemu_py_palette_init, /* tp_init */ |
|
625 0, /* tp_alloc */ |
|
626 0, /* tp_new */ |
|
627 }; |
|
628 |
|
629 typedef struct { |
|
630 PyObject_HEAD |
|
631 render_data *rdata; |
|
632 DisplayState *ds; |
|
633 PyObject *update_cb; |
|
634 PyObject *palette; |
|
635 int need_update; |
|
636 } qemu_py_render; |
|
637 |
|
638 static void qemu_py_render_dealloc(qemu_py_render *self) |
|
639 { |
|
640 if (self->rdata) |
|
641 destroy_render_data(self->rdata); |
|
642 self->rdata = NULL; |
|
643 Py_CLEAR(self->palette); |
|
644 self->ob_type->tp_free((PyObject*)self); |
|
645 } |
|
646 |
|
647 static void qemu_py_update_display(void *opaque) |
|
648 { |
|
649 qemu_py_render *self = opaque; |
|
650 PyObject *obval; |
|
651 PyObject *fn; |
|
652 int do_update; |
|
653 |
|
654 if (nographic || ds_get_bits_per_pixel(self->ds) == 0) |
|
655 return; |
|
656 |
|
657 fn = self->update_cb; |
|
658 |
|
659 if (fn && PyCallable_Check(fn)) { |
|
660 obval = PyObject_CallFunctionObjArgs(fn, NULL); |
|
661 qemu_py_assert(obval); |
|
662 do_update = PyInt_AsLong(obval); |
|
663 qemu_py_assert(!PyErr_Occurred()); |
|
664 Py_DECREF(obval); |
|
665 |
|
666 if (!do_update) |
|
667 return; |
|
668 } |
|
669 |
|
670 render(self->ds, self->rdata, self->need_update); |
|
671 self->need_update = 0; |
|
672 } |
|
673 |
|
674 static void qemu_py_invalidate_display(void *opaque) |
|
675 { |
|
676 qemu_py_render *self = opaque; |
|
677 self->need_update = 1; |
|
678 } |
|
679 |
|
680 static int qemu_py_render_init(qemu_py_render *self, PyObject *args, |
|
681 PyObject *kwds) |
|
682 { |
|
683 static char *kwlist[] = {"name", "width", "height", NULL}; |
|
684 int width; |
|
685 int height; |
|
686 char *name; |
|
687 PyObject *ob; |
|
688 |
|
689 if (!PyArg_ParseTupleAndKeywords(args, kwds, "sii", kwlist, |
|
690 &name, &width, &height)) |
|
691 return -1; |
|
692 |
|
693 self->ds = gui_get_graphic_console(name, |
|
694 qemu_py_update_display, |
|
695 qemu_py_invalidate_display, |
|
696 NULL, self); |
|
697 |
|
698 if (!self->ds) { |
|
699 PyErr_SetString(PyExc_AssertionError, "Display creation failed"); |
|
700 return -1; |
|
701 } |
|
702 |
|
703 if (width && height) { |
|
704 if (!gui_resize_vt(self->ds, width, height)) { |
|
705 /* can't resize */ |
|
706 width = height = 0; |
|
707 } |
|
708 } |
|
709 if (!width) |
|
710 width = ds_get_width(self->ds); |
|
711 if (!height) |
|
712 height = ds_get_height(self->ds); |
|
713 |
|
714 self->rdata = create_render_data(); |
|
715 set_cols(self->rdata, width); |
|
716 set_rows(self->rdata, height); |
|
717 |
|
718 ob = PyCObject_FromVoidPtr(self->rdata, NULL); |
|
719 if (!ob) |
|
720 return -1; |
|
721 self->palette = |
|
722 PyObject_CallFunctionObjArgs((PyObject *)&qemu_py_paletteType, |
|
723 ob, NULL); |
|
724 if (!self->palette) |
|
725 return -1; |
|
726 Py_DECREF(ob); |
|
727 return 0; |
|
728 } |
|
729 |
|
730 static PyObject *qemu_py_render_get(qemu_py_render *self, |
|
731 PyObject *args, PyObject *kwds) |
|
732 { |
|
733 static char *kwlist[] = {"f", NULL}; |
|
734 qemu_py_file *f; |
|
735 |
|
736 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, |
|
737 &qemu_py_fileType, &f)) |
|
738 return NULL; |
|
739 |
|
740 qemu_get_render_data(f->f, self->rdata); |
|
741 |
|
742 Py_RETURN_NONE; |
|
743 } |
|
744 |
|
745 static PyObject *qemu_py_render_put(qemu_py_render *self, |
|
746 PyObject *args, PyObject *kwds) |
|
747 { |
|
748 static char *kwlist[] = {"f", NULL}; |
|
749 qemu_py_file *f; |
|
750 |
|
751 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", kwlist, |
|
752 &qemu_py_fileType, &f)) |
|
753 return NULL; |
|
754 |
|
755 qemu_put_render_data(f->f, self->rdata); |
|
756 |
|
757 Py_RETURN_NONE; |
|
758 } |
|
759 |
|
760 static PyMemberDef qemu_py_render_members[] = { |
|
761 {"update", T_OBJECT, offsetof(qemu_py_render, update_cb), 0, |
|
762 "Display update callback"}, |
|
763 {"palette", T_OBJECT, offsetof(qemu_py_render, palette), 0, |
|
764 "palette"}, |
|
765 {NULL} /* Sentinel */ |
|
766 }; |
|
767 |
|
768 enum { |
|
769 QEMU_PY_FB_BASE, |
|
770 QEMU_PY_FB_WIDTH, |
|
771 QEMU_PY_FB_HEIGHT, |
|
772 QEMU_PY_FB_ORIENTATION, |
|
773 QEMU_PY_FB_BLANK, |
|
774 QEMU_PY_FB_BPP, |
|
775 QEMU_PY_FB_COLOR_ORDER, |
|
776 QEMU_PY_FB_BYTE_ORDER, |
|
777 QEMU_PY_FB_PIXEL_ORDER, |
|
778 QEMU_PY_FB_ROW_PITCH |
|
779 }; |
|
780 |
|
781 static PyObject * |
|
782 qemu_py_render_getattr(qemu_py_render *self, void *closure) |
|
783 { |
|
784 /* FIXME: should be target_phys_addr_t? */ |
|
785 uint32_t val; |
|
786 render_data *rdata = self->rdata; |
|
787 |
|
788 switch ((size_t)closure) { |
|
789 case QEMU_PY_FB_BASE: |
|
790 val = get_fb_base_in_target(rdata); |
|
791 break; |
|
792 case QEMU_PY_FB_WIDTH: |
|
793 val = get_cols(rdata); |
|
794 break; |
|
795 case QEMU_PY_FB_HEIGHT: |
|
796 val = get_rows(rdata); |
|
797 break; |
|
798 case QEMU_PY_FB_ORIENTATION: |
|
799 val = get_orientation(rdata); |
|
800 break; |
|
801 case QEMU_PY_FB_BLANK: |
|
802 val = get_blank_mode(rdata); |
|
803 break; |
|
804 case QEMU_PY_FB_BPP: |
|
805 switch (get_src_bpp(rdata)) { |
|
806 case BPP_SRC_1: val = 1; break; |
|
807 case BPP_SRC_2: val = 2; break; |
|
808 case BPP_SRC_4: val = 4; break; |
|
809 case BPP_SRC_8: val = 8; break; |
|
810 case BPP_SRC_15: val = 15; break; |
|
811 case BPP_SRC_16: val = 16; break; |
|
812 case BPP_SRC_24: val = 24; break; |
|
813 case BPP_SRC_32: val = 32; break; |
|
814 default: val = 0; break; |
|
815 } |
|
816 break; |
|
817 case QEMU_PY_FB_COLOR_ORDER: |
|
818 val = get_color_order(rdata); |
|
819 break; |
|
820 case QEMU_PY_FB_BYTE_ORDER: |
|
821 val = get_byte_order(rdata); |
|
822 break; |
|
823 case QEMU_PY_FB_PIXEL_ORDER: |
|
824 val = get_pixel_order(rdata); |
|
825 break; |
|
826 case QEMU_PY_FB_ROW_PITCH: |
|
827 val = get_row_pitch(rdata); |
|
828 break; |
|
829 default: |
|
830 val = -1; |
|
831 } |
|
832 return PyLong_FromUnsignedLong(val); |
|
833 } |
|
834 |
|
835 static int |
|
836 qemu_py_render_setattr(qemu_py_render *self, PyObject *obval, void *closure) |
|
837 { |
|
838 /* FIXME: should be target_phys_addr_t? */ |
|
839 uint32_t val; |
|
840 render_data *rdata = self->rdata; |
|
841 |
|
842 if (obval == NULL) { |
|
843 PyErr_SetString(PyExc_TypeError, "Cannot delete attribute"); |
|
844 return -1; |
|
845 } |
|
846 |
|
847 val = PyInt_AsUnsignedLongMask(obval); |
|
848 if (PyErr_Occurred()) |
|
849 return -1; |
|
850 |
|
851 switch ((size_t)closure) { |
|
852 case QEMU_PY_FB_BASE: |
|
853 set_fb_base_from_target(rdata, val); |
|
854 break; |
|
855 case QEMU_PY_FB_WIDTH: |
|
856 set_cols(rdata, val); |
|
857 break; |
|
858 case QEMU_PY_FB_HEIGHT: |
|
859 set_rows(rdata, val); |
|
860 break; |
|
861 case QEMU_PY_FB_ORIENTATION: |
|
862 set_orientation(rdata, val); |
|
863 break; |
|
864 case QEMU_PY_FB_BLANK: |
|
865 set_blank_mode(rdata, val); |
|
866 break; |
|
867 case QEMU_PY_FB_BPP: |
|
868 switch (val) { |
|
869 case 1: val = BPP_SRC_1; break; |
|
870 case 2: val = BPP_SRC_2; break; |
|
871 case 4: val = BPP_SRC_4; break; |
|
872 case 8: val = BPP_SRC_8; break; |
|
873 case 15: val = BPP_SRC_15; break; |
|
874 case 16: val = BPP_SRC_16; break; |
|
875 case 24: val = BPP_SRC_24; break; |
|
876 case 32: val = BPP_SRC_32; break; |
|
877 default: val = get_src_bpp(rdata); break; |
|
878 } |
|
879 set_src_bpp(rdata, val); |
|
880 break; |
|
881 case QEMU_PY_FB_COLOR_ORDER: |
|
882 set_color_order(rdata, val); |
|
883 break; |
|
884 case QEMU_PY_FB_BYTE_ORDER: |
|
885 set_byte_order(rdata, val); |
|
886 break; |
|
887 case QEMU_PY_FB_PIXEL_ORDER: |
|
888 set_pixel_order(rdata, val); |
|
889 break; |
|
890 case QEMU_PY_FB_ROW_PITCH: |
|
891 set_row_pitch(rdata, val); |
|
892 break; |
|
893 default: |
|
894 val = -1; |
|
895 break; |
|
896 } |
|
897 return 0; |
|
898 } |
|
899 |
|
900 static PyGetSetDef qemu_py_render_getseters [] = { |
|
901 {"base", (getter)qemu_py_render_getattr, |
|
902 (setter)qemu_py_render_setattr, |
|
903 "base address", (void *)(size_t)QEMU_PY_FB_BASE}, |
|
904 {"width", (getter)qemu_py_render_getattr, |
|
905 (setter)qemu_py_render_setattr, |
|
906 "screen width", (void *)(size_t)QEMU_PY_FB_WIDTH}, |
|
907 {"height", (getter)qemu_py_render_getattr, |
|
908 (setter)qemu_py_render_setattr, |
|
909 "screen height", (void *)(size_t)QEMU_PY_FB_HEIGHT}, |
|
910 {"orientation", (getter)qemu_py_render_getattr, |
|
911 (setter)qemu_py_render_setattr, |
|
912 "screen orientation", (void *)(size_t)QEMU_PY_FB_ORIENTATION}, |
|
913 {"blank", (getter)qemu_py_render_getattr, |
|
914 (setter)qemu_py_render_setattr, |
|
915 "blanking mode", (void *)(size_t)QEMU_PY_FB_BLANK}, |
|
916 {"bpp", (getter)qemu_py_render_getattr, |
|
917 (setter)qemu_py_render_setattr, |
|
918 "color depth", (void *)(size_t)QEMU_PY_FB_BPP}, |
|
919 {"color_order", (getter)qemu_py_render_getattr, |
|
920 (setter)qemu_py_render_setattr, |
|
921 "color order", (void *)(size_t)QEMU_PY_FB_COLOR_ORDER}, |
|
922 {"byte_order", (getter)qemu_py_render_getattr, |
|
923 (setter)qemu_py_render_setattr, |
|
924 "byte order", (void *)(size_t)QEMU_PY_FB_BYTE_ORDER}, |
|
925 {"pixel_order", (getter)qemu_py_render_getattr, |
|
926 (setter)qemu_py_render_setattr, |
|
927 "pixel packing order", (void *)(size_t)QEMU_PY_FB_PIXEL_ORDER}, |
|
928 {"row_pitch", (getter)qemu_py_render_getattr, |
|
929 (setter)qemu_py_render_setattr, |
|
930 "row pitch", (void *)(size_t)QEMU_PY_FB_ROW_PITCH}, |
|
931 {NULL} /* Sentinel */ |
|
932 |
|
933 }; |
|
934 |
|
935 static PyMethodDef qemu_py_render_methods[] = { |
|
936 {"get", (PyCFunction)qemu_py_render_get, METH_VARARGS|METH_KEYWORDS, |
|
937 "Restore state"}, |
|
938 {"put", (PyCFunction)qemu_py_render_put, METH_VARARGS|METH_KEYWORDS, |
|
939 "Save state"}, |
|
940 {NULL} /* Sentinel */ |
|
941 }; |
|
942 |
|
943 static PyTypeObject qemu_py_renderType = { |
|
944 PyObject_HEAD_INIT(NULL) |
|
945 0, /* ob_size */ |
|
946 "qemu.render", /* tp_name */ |
|
947 sizeof(qemu_py_render), /* tp_basicsize */ |
|
948 0, /* tp_itemsize */ |
|
949 (destructor)qemu_py_render_dealloc, /* tp_dealloc */ |
|
950 0, /* tp_print */ |
|
951 0, /* tp_getattr */ |
|
952 0, /* tp_setattr */ |
|
953 0, /* tp_compare */ |
|
954 0, /* tp_repr */ |
|
955 0, /* tp_as_number */ |
|
956 0, /* tp_as_sequence */ |
|
957 0, /* tp_as_mapping */ |
|
958 0, /* tp_hash */ |
|
959 0, /* tp_call */ |
|
960 0, /* tp_str */ |
|
961 0, /* tp_getattro */ |
|
962 0, /* tp_setattro */ |
|
963 0, /* tp_as_buffer */ |
|
964 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
965 "QEMU Framebuffer Render Engine", /* tp_doc */ |
|
966 0, /* tp_traverse */ |
|
967 0, /* tp_clear */ |
|
968 0, /* tp_richcompare */ |
|
969 0, /* tp_weaklistoffset */ |
|
970 0, /* tp_iter */ |
|
971 0, /* tp_iternext */ |
|
972 qemu_py_render_methods, /* tp_methods */ |
|
973 qemu_py_render_members, /* tp_members */ |
|
974 qemu_py_render_getseters, /* tp_getset */ |
|
975 0, /* tp_base */ |
|
976 0, /* tp_dict */ |
|
977 0, /* tp_descr_get */ |
|
978 0, /* tp_descr_set */ |
|
979 0, /* tp_dictoffset */ |
|
980 (initproc)qemu_py_render_init, /* tp_init */ |
|
981 0, /* tp_alloc */ |
|
982 0, /* tp_new */ |
|
983 }; |
|
984 |
|
985 |
|
986 typedef struct { |
|
987 PyObject_HEAD |
|
988 CharDriverState *chr; |
|
989 PyObject *can_receive_cb; |
|
990 PyObject *receive_cb; |
|
991 PyObject *event_cb; |
|
992 } qemu_py_chardev; |
|
993 |
|
994 static void qemu_py_chardev_dealloc(qemu_py_chardev *self) |
|
995 { |
|
996 Py_CLEAR(self->can_receive_cb); |
|
997 Py_CLEAR(self->receive_cb); |
|
998 Py_CLEAR(self->event_cb); |
|
999 self->ob_type->tp_free((PyObject*)self); |
|
1000 } |
|
1001 |
|
1002 static int qemu_py_chardev_can_receive(void *opaque) |
|
1003 { |
|
1004 qemu_py_chardev *self = opaque; |
|
1005 PyObject *obval; |
|
1006 int val; |
|
1007 |
|
1008 if (!self->can_receive_cb) |
|
1009 return 0; |
|
1010 |
|
1011 obval = PyObject_CallFunctionObjArgs(self->can_receive_cb, NULL); |
|
1012 qemu_py_assert(obval); |
|
1013 val = PyInt_AsLong(obval); |
|
1014 qemu_py_assert(!PyErr_Occurred()); |
|
1015 Py_DECREF(obval); |
|
1016 return val; |
|
1017 } |
|
1018 |
|
1019 static void qemu_py_chardev_receive(void *opaque, const uint8_t *buf, int size) |
|
1020 { |
|
1021 qemu_py_chardev *self = opaque; |
|
1022 PyObject *obval; |
|
1023 PyObject *obbuf; |
|
1024 |
|
1025 if (!self->receive_cb) |
|
1026 return; |
|
1027 |
|
1028 obbuf = PyBuffer_FromMemory((void *)buf, size); |
|
1029 qemu_py_assert(obbuf); |
|
1030 obval = PyObject_CallFunctionObjArgs(self->receive_cb, obbuf, NULL); |
|
1031 Py_DECREF(obbuf); |
|
1032 qemu_py_assert(obval); |
|
1033 Py_DECREF(obval); |
|
1034 } |
|
1035 |
|
1036 static void qemu_py_chardev_event(void *opaque, int event) |
|
1037 { |
|
1038 qemu_py_chardev *self = opaque; |
|
1039 PyObject *obval; |
|
1040 PyObject *obevent; |
|
1041 |
|
1042 if (!self->event_cb) |
|
1043 return; |
|
1044 |
|
1045 obevent = PyInt_FromLong(event); |
|
1046 qemu_py_assert(obevent); |
|
1047 obval = PyObject_CallFunctionObjArgs(self->event_cb, obevent, NULL); |
|
1048 Py_DECREF(obevent); |
|
1049 qemu_py_assert(obval); |
|
1050 Py_DECREF(obval); |
|
1051 } |
|
1052 |
|
1053 static int qemu_py_chardev_init(qemu_py_chardev *self, PyObject *args, |
|
1054 PyObject *kwds) |
|
1055 { |
|
1056 static char *kwlist[] = {"chardev", NULL}; |
|
1057 PyObject *obchr; |
|
1058 |
|
1059 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obchr)) |
|
1060 return -1; |
|
1061 |
|
1062 self->chr = PyCObject_AsVoidPtr(obchr); |
|
1063 if (PyErr_Occurred()) |
|
1064 return -1; |
|
1065 |
|
1066 if (self->chr) { |
|
1067 qemu_chr_add_handlers(self->chr, qemu_py_chardev_can_receive, |
|
1068 qemu_py_chardev_receive, |
|
1069 qemu_py_chardev_event, self); |
|
1070 } |
|
1071 |
|
1072 return 0; |
|
1073 } |
|
1074 |
|
1075 static PyObject *qemu_py_chardev_set_handlers(qemu_py_chardev *self, |
|
1076 PyObject *args, PyObject *kwds) |
|
1077 { |
|
1078 static char *kwlist[] = {"can_receive", "receive", "event", NULL}; |
|
1079 PyObject *obcan_receive; |
|
1080 PyObject *obreceive; |
|
1081 PyObject *obevent = Py_None; |
|
1082 |
|
1083 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, |
|
1084 &obcan_receive, &obreceive, &obevent)) |
|
1085 return NULL; |
|
1086 |
|
1087 if (!self->chr) |
|
1088 Py_RETURN_NONE; |
|
1089 |
|
1090 Py_CLEAR(self->can_receive_cb); |
|
1091 Py_CLEAR(self->receive_cb); |
|
1092 Py_CLEAR(self->event_cb); |
|
1093 if (!PyCallable_Check(obcan_receive)) { |
|
1094 PyErr_SetString(PyExc_TypeError, |
|
1095 "can_receive handler must be callable"); |
|
1096 return NULL; |
|
1097 } |
|
1098 self->can_receive_cb = obcan_receive; |
|
1099 Py_INCREF(obcan_receive); |
|
1100 if (!PyCallable_Check(obreceive)) { |
|
1101 PyErr_SetString(PyExc_TypeError, "receive handler must be callable"); |
|
1102 return NULL; |
|
1103 } |
|
1104 self->receive_cb = obreceive; |
|
1105 Py_INCREF(obreceive); |
|
1106 if (obevent != Py_None) { |
|
1107 if (!PyCallable_Check(obreceive)) { |
|
1108 PyErr_SetString(PyExc_TypeError, "event handler must be callable"); |
|
1109 return NULL; |
|
1110 } |
|
1111 self->event_cb = obevent; |
|
1112 Py_INCREF(obevent); |
|
1113 } |
|
1114 Py_RETURN_NONE; |
|
1115 } |
|
1116 |
|
1117 static PyObject *qemu_py_chardev_write(qemu_py_chardev *self, |
|
1118 PyObject *args, PyObject *kwds) |
|
1119 { |
|
1120 static char *kwlist[] = {"data", NULL}; |
|
1121 PyObject *obdata; |
|
1122 |
|
1123 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obdata)) |
|
1124 return NULL; |
|
1125 |
|
1126 if (!self->chr) |
|
1127 Py_RETURN_NONE; |
|
1128 |
|
1129 if (PyString_Check(obdata)) { |
|
1130 char *data; |
|
1131 Py_ssize_t len; |
|
1132 if (PyString_AsStringAndSize(obdata, &data, &len) < 0) |
|
1133 return NULL; |
|
1134 qemu_chr_write(self->chr, (uint8_t *)data, len); |
|
1135 } else { |
|
1136 uint8_t ch; |
|
1137 ch = PyInt_AsLong(obdata); |
|
1138 if (PyErr_Occurred()) |
|
1139 return NULL; |
|
1140 qemu_chr_write(self->chr, &ch, 1); |
|
1141 } |
|
1142 Py_RETURN_NONE; |
|
1143 } |
|
1144 |
|
1145 static PyMemberDef qemu_py_chardev_members[] = { |
|
1146 {NULL} /* Sentinel */ |
|
1147 }; |
|
1148 |
|
1149 static PyMethodDef qemu_py_chardev_methods[] = { |
|
1150 {"set_handlers", (PyCFunction)qemu_py_chardev_set_handlers, |
|
1151 METH_VARARGS|METH_KEYWORDS, |
|
1152 "Set event handlers"}, |
|
1153 {"write", (PyCFunction)qemu_py_chardev_write, METH_VARARGS|METH_KEYWORDS, |
|
1154 "Write a byte or string"}, |
|
1155 {NULL} /* Sentinel */ |
|
1156 }; |
|
1157 |
|
1158 static PyTypeObject qemu_py_chardevType = { |
|
1159 PyObject_HEAD_INIT(NULL) |
|
1160 0, /* ob_size */ |
|
1161 "qemu.chardev", /* tp_name */ |
|
1162 sizeof(qemu_py_chardev), /* tp_basicsize */ |
|
1163 0, /* tp_itemsize */ |
|
1164 (destructor)qemu_py_chardev_dealloc, /* tp_dealloc */ |
|
1165 0, /* tp_print */ |
|
1166 0, /* tp_getattr */ |
|
1167 0, /* tp_setattr */ |
|
1168 0, /* tp_compare */ |
|
1169 0, /* tp_repr */ |
|
1170 0, /* tp_as_number */ |
|
1171 0, /* tp_as_sequence */ |
|
1172 0, /* tp_as_mapping */ |
|
1173 0, /* tp_hash */ |
|
1174 0, /* tp_call */ |
|
1175 0, /* tp_str */ |
|
1176 0, /* tp_getattro */ |
|
1177 0, /* tp_setattro */ |
|
1178 0, /* tp_as_buffer */ |
|
1179 Py_TPFLAGS_DEFAULT, /* tp_flags */ |
|
1180 "QEMU Character Device", /* tp_doc */ |
|
1181 0, /* tp_traverse */ |
|
1182 0, /* tp_clear */ |
|
1183 0, /* tp_richcompare */ |
|
1184 0, /* tp_weaklistoffset */ |
|
1185 0, /* tp_iter */ |
|
1186 0, /* tp_iternext */ |
|
1187 qemu_py_chardev_methods, /* tp_methods */ |
|
1188 qemu_py_chardev_members, /* tp_members */ |
|
1189 0, /* tp_getset */ |
|
1190 0, /* tp_base */ |
|
1191 0, /* tp_dict */ |
|
1192 0, /* tp_descr_get */ |
|
1193 0, /* tp_descr_set */ |
|
1194 0, /* tp_dictoffset */ |
|
1195 (initproc)qemu_py_chardev_init, /* tp_init */ |
|
1196 0, /* tp_alloc */ |
|
1197 0, /* tp_new */ |
|
1198 }; |
|
1199 |
|
1200 |
|
1201 typedef struct { |
|
1202 PyObject_HEAD |
|
1203 QEMUDevice *qdev; |
|
1204 } qemu_py_devclass; |
|
1205 |
|
1206 static void qemu_py_devclass_dealloc(qemu_py_devclass *self) |
|
1207 { |
|
1208 self->ob_type->tp_free((PyObject*)self); |
|
1209 } |
|
1210 |
|
1211 static int qemu_py_devclass_init(qemu_py_devclass *self, PyObject *args, |
|
1212 PyObject *kwds) |
|
1213 { |
|
1214 static char *kwlist[] = {"qdev", NULL}; |
|
1215 PyObject *obqdev; |
|
1216 |
|
1217 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obqdev)) |
|
1218 return -1; |
|
1219 |
|
1220 self->qdev = PyCObject_AsVoidPtr(obqdev); |
|
1221 if (PyErr_Occurred()) |
|
1222 return -1; |
|
1223 |
|
1224 return 0; |
|
1225 } |
|
1226 |
|
1227 |
|
1228 /* FIXME: Turn ths into an actual IRQ object? */ |
|
1229 static PyObject *qemu_py_set_irq_level(qemu_py_devclass *self, PyObject *args) |
|
1230 { |
|
1231 int ok; |
|
1232 int irq_num; |
|
1233 int level; |
|
1234 |
|
1235 ok = PyArg_ParseTuple(args, "ii", &irq_num, &level); |
|
1236 if (!ok) |
|
1237 return NULL; |
|
1238 |
|
1239 if (!self->qdev) { |
|
1240 PyErr_SetString(PyExc_ValueError, "device not initialized"); |
|
1241 return NULL; |
|
1242 } |
|
1243 qdev_set_irq_level(self->qdev, irq_num, level); |
|
1244 |
|
1245 Py_RETURN_NONE; |
|
1246 } |
|
1247 |
|
1248 /* PyLong_AsUnsignedLongLongMask doesn't seem to work on Int objects. |
|
1249 This wrapper automatically picks the right routine. */ |
|
1250 static target_phys_addr_t qemu_py_physaddr_from_pynum(PyObject *ob) |
|
1251 { |
|
1252 if (PyInt_Check(ob)) |
|
1253 return PyInt_AsUnsignedLongMask(ob); |
|
1254 return PyLong_AsUnsignedLongLongMask(ob); |
|
1255 } |
|
1256 |
|
1257 static PyObject *qemu_py_dma_readb(qemu_py_chardev *self, PyObject *args, |
|
1258 PyObject *kwds) |
|
1259 { |
|
1260 static char *kwlist[] = {"addr", NULL}; |
|
1261 PyObject *obaddr; |
|
1262 target_phys_addr_t addr; |
|
1263 |
|
1264 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obaddr)) |
|
1265 return NULL; |
|
1266 |
|
1267 addr = qemu_py_physaddr_from_pynum(obaddr); |
|
1268 if (PyErr_Occurred()) |
|
1269 return NULL; |
|
1270 |
|
1271 return PyInt_FromLong(ldub_phys(addr)); |
|
1272 } |
|
1273 |
|
1274 static PyObject *qemu_py_dma_writeb(qemu_py_chardev *self, PyObject *args, |
|
1275 PyObject *kwds) |
|
1276 { |
|
1277 static char *kwlist[] = {"addr", "value", NULL}; |
|
1278 PyObject *obaddr; |
|
1279 PyObject *obval; |
|
1280 target_phys_addr_t addr; |
|
1281 uint8_t val; |
|
1282 |
|
1283 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, |
|
1284 &obaddr, &obval)) |
|
1285 return NULL; |
|
1286 |
|
1287 addr = qemu_py_physaddr_from_pynum(obaddr); |
|
1288 if (PyErr_Occurred()) |
|
1289 return NULL; |
|
1290 |
|
1291 val = PyInt_AsLong(obval); |
|
1292 if (PyErr_Occurred()) |
|
1293 return NULL; |
|
1294 |
|
1295 stb_phys(addr, val); |
|
1296 |
|
1297 Py_RETURN_NONE; |
|
1298 } |
|
1299 |
|
1300 static PyObject *qemu_py_dma_readl(qemu_py_chardev *self, PyObject *args, |
|
1301 PyObject *kwds) |
|
1302 { |
|
1303 static char *kwlist[] = {"addr", NULL}; |
|
1304 PyObject *obaddr; |
|
1305 target_phys_addr_t addr; |
|
1306 uint8_t buf[4]; |
|
1307 uint32_t val; |
|
1308 |
|
1309 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &obaddr)) |
|
1310 return NULL; |
|
1311 |
|
1312 addr = qemu_py_physaddr_from_pynum(obaddr); |
|
1313 if (PyErr_Occurred()) |
|
1314 return NULL; |
|
1315 |
|
1316 if (addr & 3) { |
|
1317 cpu_physical_memory_read(addr, buf, 4); |
|
1318 val = ldl_p(buf); |
|
1319 } else { |
|
1320 val = ldl_phys(addr); |
|
1321 } |
|
1322 return PyLong_FromUnsignedLong(val); |
|
1323 } |
|
1324 |
|
1325 static PyObject *qemu_py_dma_writel(qemu_py_chardev *self, PyObject *args, |
|
1326 PyObject *kwds) |
|
1327 { |
|
1328 static char *kwlist[] = {"addr", "value", NULL}; |
|
1329 PyObject *obaddr; |
|
1330 PyObject *obval; |
|
1331 target_phys_addr_t addr; |
|
1332 uint8_t buf[4]; |
|
1333 uint32_t val; |
|
1334 |
|
1335 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, |
|
1336 &obaddr, &obval)) |
|
1337 return NULL; |
|
1338 |
|
1339 addr = qemu_py_physaddr_from_pynum(obaddr); |
|
1340 if (PyErr_Occurred()) |
|
1341 return NULL; |
|
1342 |
|
1343 val = PyInt_AsLong(obval); |
|
1344 if (PyErr_Occurred()) |
|
1345 return NULL; |
|
1346 |
|
1347 if (addr & 3) { |
|
1348 stl_p(buf, val); |
|
1349 cpu_physical_memory_write(addr, buf, 4); |
|
1350 } else { |
|
1351 stl_phys(addr, val); |
|
1352 } |
|
1353 |
|
1354 Py_RETURN_NONE; |
|
1355 } |
|
1356 |
|
1357 static void qemu_py_set_irq_input(void *opaque, int irq, int level) |
|
1358 { |
|
1359 PyObject *fn = opaque; |
|
1360 PyObject *obirq; |
|
1361 PyObject *oblevel; |
|
1362 PyObject *obval; |
|
1363 |
|
1364 obirq = PyInt_FromLong(irq); |
|
1365 qemu_py_assert(obirq); |
|
1366 oblevel = level ? Py_True : Py_False; |
|
1367 Py_INCREF(oblevel); |
|
1368 obval = PyObject_CallFunctionObjArgs(fn, obirq, oblevel, NULL); |
|
1369 qemu_py_assert(obval); |
|
1370 Py_DECREF(obval); |
|
1371 Py_DECREF(obirq); |
|
1372 Py_DECREF(oblevel); |
|
1373 } |
|
1374 |
|
1375 static PyObject *qemu_py_create_interrupts(qemu_py_devclass *self, |
|
1376 PyObject *args, PyObject *kwds) |
|
1377 { |
|
1378 static char *kwlist[] = {"callback", "count", NULL}; |
|
1379 PyObject *obcallback; |
|
1380 int count; |
|
1381 |
|
1382 if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, |
|
1383 &obcallback, &count)) |
|
1384 return NULL; |
|
1385 |
|
1386 if (!PyCallable_Check(obcallback)) { |
|
1387 PyErr_SetString(PyExc_TypeError, "irq handler must be callable"); |
|
1388 return NULL; |
|
1389 } |
|
1390 |
|
1391 Py_INCREF(obcallback); |
|
1392 qdev_create_interrupts(self->qdev, qemu_py_set_irq_input, obcallback, |
|
1393 count); |
|
1394 |
|
1395 Py_RETURN_NONE; |
|
1396 } |
|
1397 |
|
1398 static PyObject *qemu_py_dummy_loadsave(qemu_py_devclass *self, PyObject *args) |
|
1399 { |
|
1400 Py_RETURN_NONE; |
|
1401 } |
|
1402 |
|
1403 static PyMemberDef qemu_py_devclass_members[] = { |
|
1404 #if 0 |
|
1405 {"irqs", T_INT, offsetof(qemu_py_devclass, num_irqs), 0, |
|
1406 "Number of irqs"}, |
|
1407 #endif |
|
1408 {NULL} /* Sentinel */ |
|
1409 }; |
|
1410 |
|
1411 static PyMethodDef qemu_py_devclass_methods[] = { |
|
1412 {"set_irq_level", (PyCFunction)qemu_py_set_irq_level, METH_VARARGS, |
|
1413 "Set IRQ state"}, |
|
1414 {"create_interrupts", (PyCFunction)qemu_py_create_interrupts, |
|
1415 METH_VARARGS|METH_KEYWORDS, |
|
1416 "Create IRQ inputs"}, |
|
1417 {"dma_readb", (PyCFunction)qemu_py_dma_readb, METH_VARARGS|METH_KEYWORDS, |
|
1418 "Read a byte from system memory"}, |
|
1419 {"dma_writeb", (PyCFunction)qemu_py_dma_writeb, METH_VARARGS|METH_KEYWORDS, |
|
1420 "Write a byte to system memory"}, |
|
1421 {"dma_readl", (PyCFunction)qemu_py_dma_readl, METH_VARARGS|METH_KEYWORDS, |
|
1422 "Read a 32-bit word from system memory"}, |
|
1423 {"dma_writel", (PyCFunction)qemu_py_dma_writel, METH_VARARGS|METH_KEYWORDS, |
|
1424 "Write a 32-bit word to system memory"}, |
|
1425 {"load", (PyCFunction)qemu_py_dummy_loadsave, METH_VARARGS, |
|
1426 "load snapshot state"}, |
|
1427 {"save", (PyCFunction)qemu_py_dummy_loadsave, METH_VARARGS, |
|
1428 "save snapshot state"}, |
|
1429 {NULL} /* Sentinel */ |
|
1430 }; |
|
1431 |
|
1432 static PyTypeObject qemu_py_devclassType = { |
|
1433 PyObject_HEAD_INIT(NULL) |
|
1434 0, /* ob_size */ |
|
1435 "qemu.devclass", /* tp_name */ |
|
1436 sizeof(qemu_py_devclass), /* tp_basicsize */ |
|
1437 0, /* tp_itemsize */ |
|
1438 (destructor)qemu_py_devclass_dealloc, /* tp_dealloc */ |
|
1439 0, /* tp_print */ |
|
1440 0, /* tp_getattr */ |
|
1441 0, /* tp_setattr */ |
|
1442 0, /* tp_compare */ |
|
1443 0, /* tp_repr */ |
|
1444 0, /* tp_as_number */ |
|
1445 0, /* tp_as_sequence */ |
|
1446 0, /* tp_as_mapping */ |
|
1447 0, /* tp_hash */ |
|
1448 0, /* tp_call */ |
|
1449 0, /* tp_str */ |
|
1450 0, /* tp_getattro */ |
|
1451 0, /* tp_setattro */ |
|
1452 0, /* tp_as_buffer */ |
|
1453 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ |
|
1454 "QEMU device class objects", /* tp_doc */ |
|
1455 0, /* tp_traverse */ |
|
1456 0, /* tp_clear */ |
|
1457 0, /* tp_richcompare */ |
|
1458 0, /* tp_weaklistoffset */ |
|
1459 0, /* tp_iter */ |
|
1460 0, /* tp_iternext */ |
|
1461 qemu_py_devclass_methods, /* tp_methods */ |
|
1462 qemu_py_devclass_members, /* tp_members */ |
|
1463 0, /* tp_getset */ |
|
1464 0, /* tp_base */ |
|
1465 0, /* tp_dict */ |
|
1466 0, /* tp_descr_get */ |
|
1467 0, /* tp_descr_set */ |
|
1468 0, /* tp_dictoffset */ |
|
1469 (initproc)qemu_py_devclass_init, /* tp_init */ |
|
1470 0, /* tp_alloc */ |
|
1471 0, /* tp_new */ |
|
1472 }; |
|
1473 |
|
1474 typedef struct |
|
1475 { |
|
1476 PyObject *dev; |
|
1477 int n; |
|
1478 PyObject *region; |
|
1479 } qemu_py_callback_info; |
|
1480 |
|
1481 static uint32_t qemu_py_read(void *opaque, target_phys_addr_t offset) |
|
1482 { |
|
1483 qemu_py_callback_info *info = opaque; |
|
1484 PyObject *r; |
|
1485 PyObject *fn; |
|
1486 PyObject *oboffset; |
|
1487 PyObject *obval; |
|
1488 uint32_t val; |
|
1489 |
|
1490 r = info->region; |
|
1491 qemu_py_assert(r); |
|
1492 fn = PyObject_GetAttrString(r, "readl"); |
|
1493 qemu_py_assert(fn); |
|
1494 oboffset = PyInt_FromLong(offset); |
|
1495 obval = PyObject_CallFunctionObjArgs(fn, info->dev, oboffset, NULL); |
|
1496 Py_DECREF(oboffset); |
|
1497 Py_DECREF(fn); |
|
1498 qemu_py_assert(obval); |
|
1499 val = PyLong_AsUnsignedLongMask(obval); |
|
1500 qemu_py_assert(!PyErr_Occurred()); |
|
1501 Py_DECREF(obval); |
|
1502 return val; |
|
1503 } |
|
1504 |
|
1505 static void qemu_py_write(void *opaque, target_phys_addr_t offset, |
|
1506 uint32_t value) |
|
1507 { |
|
1508 qemu_py_callback_info *info = opaque; |
|
1509 PyObject *r; |
|
1510 PyObject *fn; |
|
1511 PyObject *oboffset; |
|
1512 PyObject *obval; |
|
1513 |
|
1514 r = info->region; |
|
1515 qemu_py_assert(r); |
|
1516 fn = PyObject_GetAttrString(r, "writel"); |
|
1517 qemu_py_assert(fn); |
|
1518 oboffset = PyInt_FromLong(offset); |
|
1519 obval = PyLong_FromUnsignedLong(value); |
|
1520 PyObject_CallFunctionObjArgs(fn, info->dev, oboffset, obval, NULL); |
|
1521 Py_DECREF(oboffset); |
|
1522 Py_DECREF(obval); |
|
1523 Py_DECREF(fn); |
|
1524 qemu_py_assert(!PyErr_Occurred()); |
|
1525 } |
|
1526 |
|
1527 static CPUReadMemoryFunc *qemu_py_readfn[] = { |
|
1528 qemu_py_read, |
|
1529 qemu_py_read, |
|
1530 qemu_py_read |
|
1531 }; |
|
1532 |
|
1533 static CPUWriteMemoryFunc *qemu_py_writefn[] = { |
|
1534 qemu_py_write, |
|
1535 qemu_py_write, |
|
1536 qemu_py_write |
|
1537 }; |
|
1538 |
|
1539 static void qemu_py_dev_create(QEMUDevice *dev) |
|
1540 { |
|
1541 PyObject *ob; |
|
1542 PyObject *devclass; |
|
1543 PyObject *regions; |
|
1544 PyObject *obqdev; |
|
1545 qemu_py_devclass *self; |
|
1546 qemu_py_callback_info *callbacks; |
|
1547 Py_ssize_t pos; |
|
1548 PyObject *properties; |
|
1549 PyObject *key; |
|
1550 PyObject *value; |
|
1551 int num_regions; |
|
1552 int i; |
|
1553 |
|
1554 devclass = qdev_get_class_opaque(dev); |
|
1555 obqdev = PyCObject_FromVoidPtr(dev, NULL); |
|
1556 ob = PyObject_CallFunctionObjArgs(devclass, obqdev, NULL); |
|
1557 qemu_py_assert(ob); |
|
1558 Py_DECREF(obqdev); |
|
1559 self = (qemu_py_devclass *)ob; |
|
1560 self->qdev = dev; |
|
1561 qdev_set_opaque(dev, ob); |
|
1562 |
|
1563 value = PyString_FromString(qdev_get_name(dev)); |
|
1564 PyObject_SetAttrString(ob, "name", value); |
|
1565 |
|
1566 regions = PyObject_GetAttrString(devclass, "regions"); |
|
1567 qemu_py_assert(regions); |
|
1568 num_regions = PyList_Size(regions); |
|
1569 callbacks = qemu_mallocz(num_regions * sizeof(callbacks[0])); |
|
1570 for (i = 0; i < num_regions; i++) { |
|
1571 callbacks[i].dev = ob; |
|
1572 callbacks[i].n = i; |
|
1573 callbacks[i].region = PyList_GetItem(regions, i); |
|
1574 Py_INCREF(callbacks[i].region); |
|
1575 qdev_set_region_opaque(dev, i, &callbacks[i]); |
|
1576 } |
|
1577 Py_DECREF(regions); |
|
1578 |
|
1579 properties = PyObject_GetAttrString(devclass, "properties"); |
|
1580 qemu_py_assert(properties); |
|
1581 pos = 0; |
|
1582 while (PyDict_Next(properties, &pos, &key, &value)) { |
|
1583 char *key_name = PyString_AsString(key); |
|
1584 qemu_py_assert(key_name); |
|
1585 if (strcmp(key_name, "chardev") == 0) { |
|
1586 CharDriverState *chr; |
|
1587 PyObject *obchr; |
|
1588 chr = qdev_get_chardev(dev); |
|
1589 obchr = PyCObject_FromVoidPtr(chr, NULL); |
|
1590 qemu_py_assert(obchr); |
|
1591 value = |
|
1592 PyObject_CallFunctionObjArgs((PyObject *)&qemu_py_chardevType, |
|
1593 obchr, NULL); |
|
1594 qemu_py_assert(value); |
|
1595 Py_DECREF(obchr); |
|
1596 } else if (PyLong_Check(value) || PyInt_Check(value)) { |
|
1597 long intval; |
|
1598 intval = qdev_get_property_int(dev, key_name); |
|
1599 value = PyInt_FromLong(intval); |
|
1600 } else { |
|
1601 const char *strval; |
|
1602 strval = qdev_get_property_string(dev, key_name); |
|
1603 value = PyString_FromString(strval); |
|
1604 } |
|
1605 if (PyDict_SetItem(properties, key, value) < 0) { |
|
1606 Py_DECREF(value); |
|
1607 } |
|
1608 |
|
1609 } |
|
1610 Py_DECREF(properties); |
|
1611 |
|
1612 PyObject_CallMethod(ob, "create", NULL); |
|
1613 qemu_py_assert(!PyErr_Occurred()); |
|
1614 } |
|
1615 |
|
1616 static PyObject *qemu_py_create_file(QEMUFile *f) |
|
1617 { |
|
1618 PyObject *obfile; |
|
1619 PyObject *obarg; |
|
1620 |
|
1621 obarg = PyCObject_FromVoidPtr(f, NULL); |
|
1622 if (!obarg) |
|
1623 return NULL; |
|
1624 obfile = PyObject_CallFunctionObjArgs((PyObject *)&qemu_py_fileType, |
|
1625 obarg, NULL); |
|
1626 Py_DECREF(obarg); |
|
1627 return obfile; |
|
1628 } |
|
1629 |
|
1630 static void qemu_py_save(QEMUFile *f, void *opaque) |
|
1631 { |
|
1632 PyObject *self = opaque; |
|
1633 PyObject *obfile; |
|
1634 PyObject *obresult; |
|
1635 |
|
1636 |
|
1637 obfile = qemu_py_create_file(f); |
|
1638 qemu_py_assert(obfile); |
|
1639 obresult = PyObject_CallMethod(self, "save", "O", obfile); |
|
1640 qemu_py_assert(obresult); |
|
1641 Py_DECREF(obfile); |
|
1642 Py_DECREF(obresult); |
|
1643 } |
|
1644 |
|
1645 static int qemu_py_load(QEMUFile *f, void *opaque, int version_id) |
|
1646 { |
|
1647 PyObject *self = opaque; |
|
1648 PyObject *obfile; |
|
1649 PyObject *obresult; |
|
1650 |
|
1651 if (version_id != 1) |
|
1652 return -EINVAL; |
|
1653 |
|
1654 obfile = qemu_py_create_file(f); |
|
1655 qemu_py_assert(obfile); |
|
1656 obresult = PyObject_CallMethod(self, "load", "O", obfile); |
|
1657 /* TODO: Graceful error handling. */ |
|
1658 qemu_py_assert(obresult); |
|
1659 Py_DECREF(obfile); |
|
1660 Py_DECREF(obresult); |
|
1661 |
|
1662 return 0; |
|
1663 } |
|
1664 |
|
1665 static PyObject *qemu_py_register_device(PyObject *self, PyObject *args) |
|
1666 { |
|
1667 int ok; |
|
1668 QEMUDeviceClass *dc; |
|
1669 PyObject *devclass; |
|
1670 PyObject *regions; |
|
1671 PyObject *attr; |
|
1672 PyObject *properties; |
|
1673 Py_ssize_t pos; |
|
1674 PyObject *key; |
|
1675 PyObject *value; |
|
1676 int i; |
|
1677 char *name; |
|
1678 int num_irqs; |
|
1679 |
|
1680 ok = PyArg_ParseTuple(args, "O", &devclass); |
|
1681 if (!ok) |
|
1682 return NULL; |
|
1683 |
|
1684 if (!PyType_Check(devclass) |
|
1685 || !PyObject_IsSubclass(devclass, (PyObject *)&qemu_py_devclassType)) { |
|
1686 |
|
1687 PyErr_SetString(PyExc_TypeError, "Expected qemu.devclass derivative"); |
|
1688 return NULL; |
|
1689 } |
|
1690 |
|
1691 Py_INCREF(devclass); |
|
1692 |
|
1693 attr = PyObject_GetAttrString(devclass, "irqs"); |
|
1694 if (!attr) |
|
1695 return NULL; |
|
1696 num_irqs = PyInt_AsLong(attr); |
|
1697 if (PyErr_Occurred()) |
|
1698 return NULL; |
|
1699 Py_DECREF(attr); |
|
1700 |
|
1701 attr = PyObject_GetAttrString(devclass, "name"); |
|
1702 if (!attr) |
|
1703 return NULL; |
|
1704 name = PyString_AsString(attr); |
|
1705 if (PyErr_Occurred()) |
|
1706 return NULL; |
|
1707 |
|
1708 dc = qdev_new(name, qemu_py_dev_create, num_irqs); |
|
1709 |
|
1710 Py_DECREF(attr); |
|
1711 |
|
1712 qdev_add_class_opaque(dc, devclass); |
|
1713 |
|
1714 regions = PyObject_GetAttrString(devclass, "regions"); |
|
1715 if (!regions) |
|
1716 return NULL; |
|
1717 if (!PyList_Check(regions)) { |
|
1718 PyErr_SetString(PyExc_TypeError, "devclass.regions must be a list"); |
|
1719 return NULL; |
|
1720 } |
|
1721 for (i = 0; i < PyList_Size(regions); i++) { |
|
1722 target_phys_addr_t size; |
|
1723 PyObject *r; |
|
1724 |
|
1725 r = PyList_GetItem(regions, i); |
|
1726 if (!r) |
|
1727 return NULL; |
|
1728 |
|
1729 attr = PyObject_GetAttrString(r, "size"); |
|
1730 size = PyInt_AsLong(attr); |
|
1731 if (PyErr_Occurred()) |
|
1732 return NULL; |
|
1733 qdev_add_registers(dc, qemu_py_readfn, qemu_py_writefn, size); |
|
1734 Py_DECREF(attr); |
|
1735 } |
|
1736 Py_DECREF(regions); |
|
1737 |
|
1738 properties = PyObject_GetAttrString(devclass, "properties"); |
|
1739 if (!properties) |
|
1740 return NULL; |
|
1741 if (!PyDict_Check(properties)) { |
|
1742 Py_DECREF(properties); |
|
1743 PyErr_SetString(PyExc_TypeError, |
|
1744 "qemu.devclass.properties must be a dict"); |
|
1745 return NULL; |
|
1746 } |
|
1747 pos = 0; |
|
1748 while (PyDict_Next(properties, &pos, &key, &value)) { |
|
1749 char *key_name = PyString_AsString(key); |
|
1750 if (!key_name) |
|
1751 goto bad_property; |
|
1752 if (strcmp(key_name, "chardev") == 0) { |
|
1753 qdev_add_chardev(dc); |
|
1754 } else if (PyString_Check(value)) { |
|
1755 qdev_add_property_string(dc, key_name, PyString_AsString(value)); |
|
1756 } else if (PyLong_Check(value) || PyInt_Check(value)) { |
|
1757 long intval; |
|
1758 intval = PyLong_AsLong(value); |
|
1759 if (PyErr_Occurred()) |
|
1760 goto bad_property; |
|
1761 qdev_add_property_int(dc, key_name, PyLong_AsLong(value)); |
|
1762 } else { |
|
1763 PyErr_SetString(PyExc_TypeError, |
|
1764 "qemu.devclass.properties value must be int or string"); |
|
1765 bad_property: |
|
1766 Py_DECREF(properties); |
|
1767 return NULL; |
|
1768 } |
|
1769 } |
|
1770 Py_DECREF(properties); |
|
1771 |
|
1772 /* TODO: Implement savevm versioning. */ |
|
1773 qdev_add_savevm(dc, 1, qemu_py_save, qemu_py_load); |
|
1774 |
|
1775 Py_RETURN_NONE; |
|
1776 } |
|
1777 |
|
1778 static PyObject *qemu_py_get_clock(PyObject *self, PyObject *args) |
|
1779 { |
|
1780 return PyLong_FromUnsignedLongLong((uint64_t)qemu_get_clock(vm_clock)); |
|
1781 } |
|
1782 |
|
1783 static PyObject *qemu_py_start_time(PyObject *self, PyObject *args) |
|
1784 { |
|
1785 struct tm tm; |
|
1786 uint64_t t; |
|
1787 qemu_get_timedate(&tm, 0); |
|
1788 t = mktimegm(&tm); |
|
1789 return PyLong_FromUnsignedLongLong(t); |
|
1790 } |
|
1791 |
|
1792 static void qemu_py_keyboard_event(void *opaque, int keycode) |
|
1793 { |
|
1794 PyObject *fn = opaque; |
|
1795 PyObject *obval; |
|
1796 PyObject *obkey; |
|
1797 |
|
1798 obkey = PyInt_FromLong(keycode); |
|
1799 obval = PyObject_CallFunctionObjArgs(fn, obkey, NULL); |
|
1800 qemu_py_assert(obval); |
|
1801 Py_DECREF(obkey); |
|
1802 Py_DECREF(obval); |
|
1803 } |
|
1804 |
|
1805 static PyObject *qemu_py_register_keyboard(PyObject *self, PyObject *args, |
|
1806 PyObject *kwds) |
|
1807 { |
|
1808 static char *kwlist[] = {"handler", NULL}; |
|
1809 PyObject *fn; |
|
1810 |
|
1811 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &fn)) |
|
1812 return NULL; |
|
1813 |
|
1814 if (!PyCallable_Check(fn)) { |
|
1815 PyErr_SetString(PyExc_TypeError, "keyboard handler must be callable"); |
|
1816 return NULL; |
|
1817 } |
|
1818 |
|
1819 Py_INCREF(fn); |
|
1820 gui_register_dev_key_callback(qemu_py_keyboard_event, fn); |
|
1821 |
|
1822 Py_RETURN_NONE; |
|
1823 } |
|
1824 |
|
1825 static void qemu_py_mouse_event(void *opaque, int dx, int dy, int dz, |
|
1826 int buttons) |
|
1827 { |
|
1828 PyObject *fn = opaque; |
|
1829 PyObject *obval; |
|
1830 PyObject *obx; |
|
1831 PyObject *oby; |
|
1832 PyObject *obz; |
|
1833 PyObject *obbuttons; |
|
1834 |
|
1835 obx = PyInt_FromLong(dx); |
|
1836 oby = PyInt_FromLong(dy); |
|
1837 obz = PyInt_FromLong(dz); |
|
1838 obbuttons = PyInt_FromLong(buttons); |
|
1839 obval = PyObject_CallFunctionObjArgs(fn, obx, oby, obz, obbuttons, NULL); |
|
1840 qemu_py_assert(obval); |
|
1841 Py_DECREF(obx); |
|
1842 Py_DECREF(oby); |
|
1843 Py_DECREF(obz); |
|
1844 Py_DECREF(obbuttons); |
|
1845 Py_DECREF(obval); |
|
1846 } |
|
1847 |
|
1848 static PyObject *qemu_py_register_mouse(PyObject *self, PyObject *args, |
|
1849 PyObject *kwds) |
|
1850 { |
|
1851 static char *kwlist[] = {"handler", "absolute", NULL}; |
|
1852 PyObject *fn; |
|
1853 int absolute; |
|
1854 |
|
1855 if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &fn, &absolute)) |
|
1856 return NULL; |
|
1857 |
|
1858 if (!PyCallable_Check(fn)) { |
|
1859 PyErr_SetString(PyExc_TypeError, "mouse handler must be callable"); |
|
1860 return NULL; |
|
1861 } |
|
1862 |
|
1863 Py_INCREF(fn); |
|
1864 gui_register_mouse_event_handler(qemu_py_mouse_event, fn, absolute, "dev"); |
|
1865 |
|
1866 Py_RETURN_NONE; |
|
1867 } |
|
1868 |
|
1869 static PyMethodDef qemu_py_methods[] = |
|
1870 { |
|
1871 {"register_device", qemu_py_register_device, METH_VARARGS, |
|
1872 "Register new device class"}, |
|
1873 {"get_clock", qemu_py_get_clock, METH_NOARGS, |
|
1874 "Get current virtual time"}, |
|
1875 {"start_time", qemu_py_start_time, METH_NOARGS, |
|
1876 "Get VM start time (seconds sice epoch)"}, |
|
1877 {"register_keyboard", (PyCFunction)qemu_py_register_keyboard, |
|
1878 METH_VARARGS|METH_KEYWORDS, |
|
1879 "Register keyboard event handler"}, |
|
1880 {"register_mouse", (PyCFunction)qemu_py_register_mouse, |
|
1881 METH_VARARGS|METH_KEYWORDS, |
|
1882 "Register mouse event handler"}, |
|
1883 {NULL} |
|
1884 }; |
|
1885 |
|
1886 static void qemu_py_add_class(PyObject *module, const char *name, |
|
1887 PyTypeObject *type) |
|
1888 { |
|
1889 if (!type->tp_new) |
|
1890 type->tp_new = PyType_GenericNew; |
|
1891 if (PyType_Ready(type) < 0) |
|
1892 qemu_py_die(); |
|
1893 Py_INCREF(type); |
|
1894 PyModule_AddObject(module, name, (PyObject *)type); |
|
1895 } |
|
1896 |
|
1897 static void qemu_py_init_interface(void) |
|
1898 { |
|
1899 PyObject *m; |
|
1900 m = Py_InitModule("qemu", qemu_py_methods); |
|
1901 |
|
1902 /* FIXME: Add default attributes to qemu_py_devclass. */ |
|
1903 qemu_py_add_class(m, "devclass", &qemu_py_devclassType); |
|
1904 qemu_py_add_class(m, "ioregion", &qemu_py_ioregionType); |
|
1905 qemu_py_add_class(m, "chardev", &qemu_py_chardevType); |
|
1906 qemu_py_add_class(m, "render", &qemu_py_renderType); |
|
1907 qemu_py_add_class(m, "palette", &qemu_py_paletteType); |
|
1908 qemu_py_add_class(m, "ptimer", &qemu_py_ptimerType); |
|
1909 qemu_py_add_class(m, "file", &qemu_py_fileType); |
|
1910 } |
|
1911 |
|
1912 #define PLUGIN_INIT_SCRIPT "import sys\nsys.path.insert(0, \"%s/plugins\")" |
|
1913 void qemu_python_init(char *argv0) |
|
1914 { |
|
1915 char *buf; |
|
1916 Py_SetProgramName(argv0); |
|
1917 Py_Initialize(); |
|
1918 |
|
1919 /* Nasty hack to look for plugin modules. */ |
|
1920 buf = qemu_mallocz(strlen(bios_dir) + strlen(PLUGIN_INIT_SCRIPT)); |
|
1921 sprintf(buf, PLUGIN_INIT_SCRIPT, bios_dir); |
|
1922 #ifdef _WIN32 |
|
1923 { |
|
1924 char *p; |
|
1925 /* Windows path separators (backslash) are interpreted as escape |
|
1926 characters in a python string. Fortunately python also accepts |
|
1927 unix path separators (forward slash), so use those instead. */ |
|
1928 for (p = buf; *p; p++) { |
|
1929 if (*p == '\\') |
|
1930 *p = '/'; |
|
1931 } |
|
1932 } |
|
1933 #endif |
|
1934 PyRun_SimpleString(buf); |
|
1935 qemu_free(buf); |
|
1936 |
|
1937 qemu_py_init_interface(); |
|
1938 |
|
1939 qemu_py_load_module("qemu_arm_plugins"); |
|
1940 } |