]> git.proxmox.com Git - mirror_qemu.git/blob - hw/qdev-properties.c
qdev: remove parse/print methods for mac properties
[mirror_qemu.git] / hw / qdev-properties.c
1 #include "net.h"
2 #include "qdev.h"
3 #include "qerror.h"
4 #include "blockdev.h"
5
6 void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
7 {
8 void *ptr = dev;
9 ptr += prop->offset;
10 return ptr;
11 }
12
13 static uint32_t qdev_get_prop_mask(Property *prop)
14 {
15 assert(prop->info->type == PROP_TYPE_BIT);
16 return 0x1 << prop->bitnr;
17 }
18
19 static void bit_prop_set(DeviceState *dev, Property *props, bool val)
20 {
21 uint32_t *p = qdev_get_prop_ptr(dev, props);
22 uint32_t mask = qdev_get_prop_mask(props);
23 if (val)
24 *p |= mask;
25 else
26 *p &= ~mask;
27 }
28
29 static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src)
30 {
31 if (props->info->type == PROP_TYPE_BIT) {
32 bool *defval = src;
33 bit_prop_set(dev, props, *defval);
34 } else {
35 char *dst = qdev_get_prop_ptr(dev, props);
36 memcpy(dst, src, props->info->size);
37 }
38 }
39
40 /* Bit */
41 static int parse_bit(DeviceState *dev, Property *prop, const char *str)
42 {
43 if (!strcasecmp(str, "on"))
44 bit_prop_set(dev, prop, true);
45 else if (!strcasecmp(str, "off"))
46 bit_prop_set(dev, prop, false);
47 else
48 return -EINVAL;
49 return 0;
50 }
51
52 static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
53 {
54 uint32_t *p = qdev_get_prop_ptr(dev, prop);
55 return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
56 }
57
58 static void get_bit(Object *obj, Visitor *v, void *opaque,
59 const char *name, Error **errp)
60 {
61 DeviceState *dev = DEVICE(obj);
62 Property *prop = opaque;
63 uint32_t *p = qdev_get_prop_ptr(dev, prop);
64 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
65
66 visit_type_bool(v, &value, name, errp);
67 }
68
69 static void set_bit(Object *obj, Visitor *v, void *opaque,
70 const char *name, Error **errp)
71 {
72 DeviceState *dev = DEVICE(obj);
73 Property *prop = opaque;
74 Error *local_err = NULL;
75 bool value;
76
77 if (dev->state != DEV_STATE_CREATED) {
78 error_set(errp, QERR_PERMISSION_DENIED);
79 return;
80 }
81
82 visit_type_bool(v, &value, name, &local_err);
83 if (local_err) {
84 error_propagate(errp, local_err);
85 return;
86 }
87 bit_prop_set(dev, prop, value);
88 }
89
90 PropertyInfo qdev_prop_bit = {
91 .name = "boolean",
92 .legacy_name = "on/off",
93 .type = PROP_TYPE_BIT,
94 .size = sizeof(uint32_t),
95 .parse = parse_bit,
96 .print = print_bit,
97 .get = get_bit,
98 .set = set_bit,
99 };
100
101 /* --- 8bit integer --- */
102
103 static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
104 {
105 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
106 char *end;
107
108 /* accept both hex and decimal */
109 *ptr = strtoul(str, &end, 0);
110 if ((*end != '\0') || (end == str)) {
111 return -EINVAL;
112 }
113
114 return 0;
115 }
116
117 static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
118 {
119 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
120 return snprintf(dest, len, "%" PRIu8, *ptr);
121 }
122
123 static void get_int8(Object *obj, Visitor *v, void *opaque,
124 const char *name, Error **errp)
125 {
126 DeviceState *dev = DEVICE(obj);
127 Property *prop = opaque;
128 int8_t *ptr = qdev_get_prop_ptr(dev, prop);
129 int64_t value;
130
131 value = *ptr;
132 visit_type_int(v, &value, name, errp);
133 }
134
135 static void set_int8(Object *obj, Visitor *v, void *opaque,
136 const char *name, Error **errp)
137 {
138 DeviceState *dev = DEVICE(obj);
139 Property *prop = opaque;
140 int8_t *ptr = qdev_get_prop_ptr(dev, prop);
141 Error *local_err = NULL;
142 int64_t value;
143
144 if (dev->state != DEV_STATE_CREATED) {
145 error_set(errp, QERR_PERMISSION_DENIED);
146 return;
147 }
148
149 visit_type_int(v, &value, name, &local_err);
150 if (local_err) {
151 error_propagate(errp, local_err);
152 return;
153 }
154 if (value > prop->info->min && value <= prop->info->max) {
155 *ptr = value;
156 } else {
157 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
158 dev->id?:"", name, value, prop->info->min,
159 prop->info->max);
160 }
161 }
162
163 PropertyInfo qdev_prop_uint8 = {
164 .name = "uint8",
165 .type = PROP_TYPE_UINT8,
166 .size = sizeof(uint8_t),
167 .parse = parse_uint8,
168 .print = print_uint8,
169 .get = get_int8,
170 .set = set_int8,
171 .min = 0,
172 .max = 255,
173 };
174
175 /* --- 8bit hex value --- */
176
177 static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
178 {
179 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
180 char *end;
181
182 *ptr = strtoul(str, &end, 16);
183 if ((*end != '\0') || (end == str)) {
184 return -EINVAL;
185 }
186
187 return 0;
188 }
189
190 static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
191 {
192 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
193 return snprintf(dest, len, "0x%" PRIx8, *ptr);
194 }
195
196 PropertyInfo qdev_prop_hex8 = {
197 .name = "uint8",
198 .legacy_name = "hex8",
199 .type = PROP_TYPE_UINT8,
200 .size = sizeof(uint8_t),
201 .parse = parse_hex8,
202 .print = print_hex8,
203 .get = get_int8,
204 .set = set_int8,
205 .min = 0,
206 .max = 255,
207 };
208
209 /* --- 16bit integer --- */
210
211 static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
212 {
213 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
214 char *end;
215
216 /* accept both hex and decimal */
217 *ptr = strtoul(str, &end, 0);
218 if ((*end != '\0') || (end == str)) {
219 return -EINVAL;
220 }
221
222 return 0;
223 }
224
225 static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
226 {
227 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
228 return snprintf(dest, len, "%" PRIu16, *ptr);
229 }
230
231 static void get_int16(Object *obj, Visitor *v, void *opaque,
232 const char *name, Error **errp)
233 {
234 DeviceState *dev = DEVICE(obj);
235 Property *prop = opaque;
236 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
237 int64_t value;
238
239 value = *ptr;
240 visit_type_int(v, &value, name, errp);
241 }
242
243 static void set_int16(Object *obj, Visitor *v, void *opaque,
244 const char *name, Error **errp)
245 {
246 DeviceState *dev = DEVICE(obj);
247 Property *prop = opaque;
248 int16_t *ptr = qdev_get_prop_ptr(dev, prop);
249 Error *local_err = NULL;
250 int64_t value;
251
252 if (dev->state != DEV_STATE_CREATED) {
253 error_set(errp, QERR_PERMISSION_DENIED);
254 return;
255 }
256
257 visit_type_int(v, &value, name, &local_err);
258 if (local_err) {
259 error_propagate(errp, local_err);
260 return;
261 }
262 if (value > prop->info->min && value <= prop->info->max) {
263 *ptr = value;
264 } else {
265 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
266 dev->id?:"", name, value, prop->info->min,
267 prop->info->max);
268 }
269 }
270
271 PropertyInfo qdev_prop_uint16 = {
272 .name = "uint16",
273 .type = PROP_TYPE_UINT16,
274 .size = sizeof(uint16_t),
275 .parse = parse_uint16,
276 .print = print_uint16,
277 .get = get_int16,
278 .set = set_int16,
279 .min = 0,
280 .max = 65535,
281 };
282
283 /* --- 32bit integer --- */
284
285 static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
286 {
287 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
288 char *end;
289
290 /* accept both hex and decimal */
291 *ptr = strtoul(str, &end, 0);
292 if ((*end != '\0') || (end == str)) {
293 return -EINVAL;
294 }
295
296 return 0;
297 }
298
299 static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
300 {
301 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
302 return snprintf(dest, len, "%" PRIu32, *ptr);
303 }
304
305 static void get_int32(Object *obj, Visitor *v, void *opaque,
306 const char *name, Error **errp)
307 {
308 DeviceState *dev = DEVICE(obj);
309 Property *prop = opaque;
310 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
311 int64_t value;
312
313 value = *ptr;
314 visit_type_int(v, &value, name, errp);
315 }
316
317 static void set_int32(Object *obj, Visitor *v, void *opaque,
318 const char *name, Error **errp)
319 {
320 DeviceState *dev = DEVICE(obj);
321 Property *prop = opaque;
322 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
323 Error *local_err = NULL;
324 int64_t value;
325
326 if (dev->state != DEV_STATE_CREATED) {
327 error_set(errp, QERR_PERMISSION_DENIED);
328 return;
329 }
330
331 visit_type_int(v, &value, name, &local_err);
332 if (local_err) {
333 error_propagate(errp, local_err);
334 return;
335 }
336 if (value > prop->info->min && value <= prop->info->max) {
337 *ptr = value;
338 } else {
339 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
340 dev->id?:"", name, value, prop->info->min,
341 prop->info->max);
342 }
343 }
344
345 PropertyInfo qdev_prop_uint32 = {
346 .name = "uint32",
347 .type = PROP_TYPE_UINT32,
348 .size = sizeof(uint32_t),
349 .parse = parse_uint32,
350 .print = print_uint32,
351 .get = get_int32,
352 .set = set_int32,
353 .min = 0,
354 .max = 0xFFFFFFFFULL,
355 };
356
357 static int parse_int32(DeviceState *dev, Property *prop, const char *str)
358 {
359 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
360 char *end;
361
362 *ptr = strtol(str, &end, 10);
363 if ((*end != '\0') || (end == str)) {
364 return -EINVAL;
365 }
366
367 return 0;
368 }
369
370 static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
371 {
372 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
373 return snprintf(dest, len, "%" PRId32, *ptr);
374 }
375
376 PropertyInfo qdev_prop_int32 = {
377 .name = "int32",
378 .type = PROP_TYPE_INT32,
379 .size = sizeof(int32_t),
380 .parse = parse_int32,
381 .print = print_int32,
382 .get = get_int32,
383 .set = set_int32,
384 .min = -0x80000000LL,
385 .max = 0x7FFFFFFFLL,
386 };
387
388 /* --- 32bit hex value --- */
389
390 static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
391 {
392 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
393 char *end;
394
395 *ptr = strtoul(str, &end, 16);
396 if ((*end != '\0') || (end == str)) {
397 return -EINVAL;
398 }
399
400 return 0;
401 }
402
403 static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
404 {
405 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
406 return snprintf(dest, len, "0x%" PRIx32, *ptr);
407 }
408
409 PropertyInfo qdev_prop_hex32 = {
410 .name = "uint32",
411 .legacy_name = "hex32",
412 .type = PROP_TYPE_UINT32,
413 .size = sizeof(uint32_t),
414 .parse = parse_hex32,
415 .print = print_hex32,
416 .get = get_int32,
417 .set = set_int32,
418 .min = 0,
419 .max = 0xFFFFFFFFULL,
420 };
421
422 /* --- 64bit integer --- */
423
424 static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
425 {
426 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
427 char *end;
428
429 /* accept both hex and decimal */
430 *ptr = strtoull(str, &end, 0);
431 if ((*end != '\0') || (end == str)) {
432 return -EINVAL;
433 }
434
435 return 0;
436 }
437
438 static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
439 {
440 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
441 return snprintf(dest, len, "%" PRIu64, *ptr);
442 }
443
444 static void get_int64(Object *obj, Visitor *v, void *opaque,
445 const char *name, Error **errp)
446 {
447 DeviceState *dev = DEVICE(obj);
448 Property *prop = opaque;
449 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
450
451 visit_type_int(v, ptr, name, errp);
452 }
453
454 static void set_int64(Object *obj, Visitor *v, void *opaque,
455 const char *name, Error **errp)
456 {
457 DeviceState *dev = DEVICE(obj);
458 Property *prop = opaque;
459 int64_t *ptr = qdev_get_prop_ptr(dev, prop);
460
461 if (dev->state != DEV_STATE_CREATED) {
462 error_set(errp, QERR_PERMISSION_DENIED);
463 return;
464 }
465
466 visit_type_int(v, ptr, name, errp);
467 }
468
469 PropertyInfo qdev_prop_uint64 = {
470 .name = "uint64",
471 .type = PROP_TYPE_UINT64,
472 .size = sizeof(uint64_t),
473 .parse = parse_uint64,
474 .print = print_uint64,
475 .get = get_int64,
476 .set = set_int64,
477 };
478
479 /* --- 64bit hex value --- */
480
481 static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
482 {
483 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
484 char *end;
485
486 *ptr = strtoull(str, &end, 16);
487 if ((*end != '\0') || (end == str)) {
488 return -EINVAL;
489 }
490
491 return 0;
492 }
493
494 static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
495 {
496 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
497 return snprintf(dest, len, "0x%" PRIx64, *ptr);
498 }
499
500 PropertyInfo qdev_prop_hex64 = {
501 .name = "uint64",
502 .legacy_name = "hex64",
503 .type = PROP_TYPE_UINT64,
504 .size = sizeof(uint64_t),
505 .parse = parse_hex64,
506 .print = print_hex64,
507 .get = get_int64,
508 .set = set_int64,
509 };
510
511 /* --- string --- */
512
513 static void free_string(DeviceState *dev, Property *prop)
514 {
515 g_free(*(char **)qdev_get_prop_ptr(dev, prop));
516 }
517
518 static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
519 {
520 char **ptr = qdev_get_prop_ptr(dev, prop);
521 if (!*ptr)
522 return snprintf(dest, len, "<null>");
523 return snprintf(dest, len, "\"%s\"", *ptr);
524 }
525
526 static void get_string(Object *obj, Visitor *v, void *opaque,
527 const char *name, Error **errp)
528 {
529 DeviceState *dev = DEVICE(obj);
530 Property *prop = opaque;
531 char **ptr = qdev_get_prop_ptr(dev, prop);
532
533 if (!*ptr) {
534 char *str = (char *)"";
535 visit_type_str(v, &str, name, errp);
536 } else {
537 visit_type_str(v, ptr, name, errp);
538 }
539 }
540
541 static void set_string(Object *obj, Visitor *v, void *opaque,
542 const char *name, Error **errp)
543 {
544 DeviceState *dev = DEVICE(obj);
545 Property *prop = opaque;
546 char **ptr = qdev_get_prop_ptr(dev, prop);
547 Error *local_err = NULL;
548 char *str;
549
550 if (dev->state != DEV_STATE_CREATED) {
551 error_set(errp, QERR_PERMISSION_DENIED);
552 return;
553 }
554
555 visit_type_str(v, &str, name, &local_err);
556 if (local_err) {
557 error_propagate(errp, local_err);
558 return;
559 }
560 if (!*str) {
561 g_free(str);
562 str = NULL;
563 }
564 if (*ptr) {
565 g_free(*ptr);
566 }
567 *ptr = str;
568 }
569
570 PropertyInfo qdev_prop_string = {
571 .name = "string",
572 .type = PROP_TYPE_STRING,
573 .size = sizeof(char*),
574 .print = print_string,
575 .free = free_string,
576 .get = get_string,
577 .set = set_string,
578 };
579
580 /* --- drive --- */
581
582 static int parse_drive(DeviceState *dev, Property *prop, const char *str)
583 {
584 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
585 BlockDriverState *bs;
586
587 bs = bdrv_find(str);
588 if (bs == NULL)
589 return -ENOENT;
590 if (bdrv_attach_dev(bs, dev) < 0)
591 return -EEXIST;
592 *ptr = bs;
593 return 0;
594 }
595
596 static void free_drive(DeviceState *dev, Property *prop)
597 {
598 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
599
600 if (*ptr) {
601 bdrv_detach_dev(*ptr, dev);
602 blockdev_auto_del(*ptr);
603 }
604 }
605
606 static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
607 {
608 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
609 return snprintf(dest, len, "%s",
610 *ptr ? bdrv_get_device_name(*ptr) : "<null>");
611 }
612
613 static void get_generic(Object *obj, Visitor *v, void *opaque,
614 const char *name, Error **errp)
615 {
616 DeviceState *dev = DEVICE(obj);
617 Property *prop = opaque;
618 void **ptr = qdev_get_prop_ptr(dev, prop);
619 char buffer[1024];
620 char *p = buffer;
621
622 buffer[0] = 0;
623 if (*ptr) {
624 prop->info->print(dev, prop, buffer, sizeof(buffer));
625 }
626 visit_type_str(v, &p, name, errp);
627 }
628
629 static void set_generic(Object *obj, Visitor *v, void *opaque,
630 const char *name, Error **errp)
631 {
632 DeviceState *dev = DEVICE(obj);
633 Property *prop = opaque;
634 Error *local_err = NULL;
635 char *str;
636 int ret;
637
638 if (dev->state != DEV_STATE_CREATED) {
639 error_set(errp, QERR_PERMISSION_DENIED);
640 return;
641 }
642
643 visit_type_str(v, &str, name, &local_err);
644 if (local_err) {
645 error_propagate(errp, local_err);
646 return;
647 }
648 if (!*str) {
649 g_free(str);
650 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
651 return;
652 }
653 ret = prop->info->parse(dev, prop, str);
654 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
655 g_free(str);
656 }
657
658 PropertyInfo qdev_prop_drive = {
659 .name = "drive",
660 .type = PROP_TYPE_DRIVE,
661 .size = sizeof(BlockDriverState *),
662 .parse = parse_drive,
663 .print = print_drive,
664 .get = get_generic,
665 .set = set_generic,
666 .free = free_drive,
667 };
668
669 /* --- character device --- */
670
671 static int parse_chr(DeviceState *dev, Property *prop, const char *str)
672 {
673 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
674
675 *ptr = qemu_chr_find(str);
676 if (*ptr == NULL) {
677 return -ENOENT;
678 }
679 if ((*ptr)->avail_connections < 1) {
680 return -EEXIST;
681 }
682 --(*ptr)->avail_connections;
683 return 0;
684 }
685
686 static void free_chr(DeviceState *dev, Property *prop)
687 {
688 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
689
690 if (*ptr) {
691 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
692 }
693 }
694
695
696 static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
697 {
698 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
699
700 if (*ptr && (*ptr)->label) {
701 return snprintf(dest, len, "%s", (*ptr)->label);
702 } else {
703 return snprintf(dest, len, "<null>");
704 }
705 }
706
707 PropertyInfo qdev_prop_chr = {
708 .name = "chr",
709 .type = PROP_TYPE_CHR,
710 .size = sizeof(CharDriverState*),
711 .parse = parse_chr,
712 .print = print_chr,
713 .get = get_generic,
714 .set = set_generic,
715 .free = free_chr,
716 };
717
718 /* --- netdev device --- */
719
720 static int parse_netdev(DeviceState *dev, Property *prop, const char *str)
721 {
722 VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
723
724 *ptr = qemu_find_netdev(str);
725 if (*ptr == NULL)
726 return -ENOENT;
727 if ((*ptr)->peer) {
728 return -EEXIST;
729 }
730 return 0;
731 }
732
733 static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len)
734 {
735 VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
736
737 if (*ptr && (*ptr)->name) {
738 return snprintf(dest, len, "%s", (*ptr)->name);
739 } else {
740 return snprintf(dest, len, "<null>");
741 }
742 }
743
744 PropertyInfo qdev_prop_netdev = {
745 .name = "netdev",
746 .type = PROP_TYPE_NETDEV,
747 .size = sizeof(VLANClientState*),
748 .parse = parse_netdev,
749 .print = print_netdev,
750 .get = get_generic,
751 .set = set_generic,
752 };
753
754 /* --- vlan --- */
755
756 static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
757 {
758 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
759 int id;
760
761 if (sscanf(str, "%d", &id) != 1)
762 return -EINVAL;
763 *ptr = qemu_find_vlan(id, 1);
764 if (*ptr == NULL)
765 return -ENOENT;
766 return 0;
767 }
768
769 static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
770 {
771 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
772
773 if (*ptr) {
774 return snprintf(dest, len, "%d", (*ptr)->id);
775 } else {
776 return snprintf(dest, len, "<null>");
777 }
778 }
779
780 static void get_vlan(Object *obj, Visitor *v, void *opaque,
781 const char *name, Error **errp)
782 {
783 DeviceState *dev = DEVICE(obj);
784 Property *prop = opaque;
785 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
786 int64_t id;
787
788 id = *ptr ? (*ptr)->id : -1;
789 visit_type_int(v, &id, name, errp);
790 }
791
792 static void set_vlan(Object *obj, Visitor *v, void *opaque,
793 const char *name, Error **errp)
794 {
795 DeviceState *dev = DEVICE(obj);
796 Property *prop = opaque;
797 VLANState **ptr = qdev_get_prop_ptr(dev, prop);
798 Error *local_err = NULL;
799 int64_t id;
800 VLANState *vlan;
801
802 if (dev->state != DEV_STATE_CREATED) {
803 error_set(errp, QERR_PERMISSION_DENIED);
804 return;
805 }
806
807 visit_type_int(v, &id, name, &local_err);
808 if (local_err) {
809 error_propagate(errp, local_err);
810 return;
811 }
812 if (id == -1) {
813 *ptr = NULL;
814 return;
815 }
816 vlan = qemu_find_vlan(id, 1);
817 if (!vlan) {
818 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
819 name, prop->info->name);
820 return;
821 }
822 *ptr = vlan;
823 }
824
825 PropertyInfo qdev_prop_vlan = {
826 .name = "vlan",
827 .type = PROP_TYPE_VLAN,
828 .size = sizeof(VLANClientState*),
829 .parse = parse_vlan,
830 .print = print_vlan,
831 .get = get_vlan,
832 .set = set_vlan,
833 };
834
835 /* --- pointer --- */
836
837 /* Not a proper property, just for dirty hacks. TODO Remove it! */
838 PropertyInfo qdev_prop_ptr = {
839 .name = "ptr",
840 .type = PROP_TYPE_PTR,
841 .size = sizeof(void*),
842 };
843
844 /* --- mac address --- */
845
846 /*
847 * accepted syntax versions:
848 * 01:02:03:04:05:06
849 * 01-02-03-04-05-06
850 */
851 static void get_mac(Object *obj, Visitor *v, void *opaque,
852 const char *name, Error **errp)
853 {
854 DeviceState *dev = DEVICE(obj);
855 Property *prop = opaque;
856 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
857 char buffer[2 * 6 + 5 + 1];
858 char *p = buffer;
859
860 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
861 mac->a[0], mac->a[1], mac->a[2],
862 mac->a[3], mac->a[4], mac->a[5]);
863
864 visit_type_str(v, &p, name, errp);
865 }
866
867 static void set_mac(Object *obj, Visitor *v, void *opaque,
868 const char *name, Error **errp)
869 {
870 DeviceState *dev = DEVICE(obj);
871 Property *prop = opaque;
872 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
873 Error *local_err = NULL;
874 int i, pos;
875 char *str, *p;
876
877 if (dev->state != DEV_STATE_CREATED) {
878 error_set(errp, QERR_PERMISSION_DENIED);
879 return;
880 }
881
882 visit_type_str(v, &str, name, &local_err);
883 if (local_err) {
884 error_propagate(errp, local_err);
885 return;
886 }
887
888 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
889 if (!qemu_isxdigit(str[pos]))
890 goto inval;
891 if (!qemu_isxdigit(str[pos+1]))
892 goto inval;
893 if (i == 5) {
894 if (str[pos+2] != '\0')
895 goto inval;
896 } else {
897 if (str[pos+2] != ':' && str[pos+2] != '-')
898 goto inval;
899 }
900 mac->a[i] = strtol(str+pos, &p, 16);
901 }
902 return;
903
904 inval:
905 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
906 }
907
908 PropertyInfo qdev_prop_macaddr = {
909 .name = "macaddr",
910 .type = PROP_TYPE_MACADDR,
911 .size = sizeof(MACAddr),
912 .get = get_mac,
913 .set = set_mac,
914 };
915
916
917 /* --- lost tick policy --- */
918
919 static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
920 [LOST_TICK_DISCARD] = "discard",
921 [LOST_TICK_DELAY] = "delay",
922 [LOST_TICK_MERGE] = "merge",
923 [LOST_TICK_SLEW] = "slew",
924 [LOST_TICK_MAX] = NULL,
925 };
926
927 QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
928
929 static void get_enum(Object *obj, Visitor *v, void *opaque,
930 const char *name, Error **errp)
931 {
932 DeviceState *dev = DEVICE(obj);
933 Property *prop = opaque;
934 int *ptr = qdev_get_prop_ptr(dev, prop);
935
936 visit_type_enum(v, ptr, prop->info->enum_table,
937 prop->info->name, prop->name, errp);
938 }
939
940 static void set_enum(Object *obj, Visitor *v, void *opaque,
941 const char *name, Error **errp)
942 {
943 DeviceState *dev = DEVICE(obj);
944 Property *prop = opaque;
945 int *ptr = qdev_get_prop_ptr(dev, prop);
946
947 if (dev->state != DEV_STATE_CREATED) {
948 error_set(errp, QERR_PERMISSION_DENIED);
949 return;
950 }
951
952 visit_type_enum(v, ptr, prop->info->enum_table,
953 prop->info->name, prop->name, errp);
954 }
955
956 PropertyInfo qdev_prop_losttickpolicy = {
957 .name = "LostTickPolicy",
958 .type = PROP_TYPE_LOSTTICKPOLICY,
959 .size = sizeof(LostTickPolicy),
960 .enum_table = lost_tick_policy_table,
961 .get = get_enum,
962 .set = set_enum,
963 };
964
965 /* --- pci address --- */
966
967 /*
968 * bus-local address, i.e. "$slot" or "$slot.$fn"
969 */
970 static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
971 {
972 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
973 unsigned int slot, fn, n;
974
975 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
976 fn = 0;
977 if (sscanf(str, "%x%n", &slot, &n) != 1) {
978 return -EINVAL;
979 }
980 }
981 if (str[n] != '\0')
982 return -EINVAL;
983 if (fn > 7)
984 return -EINVAL;
985 if (slot > 31)
986 return -EINVAL;
987 *ptr = slot << 3 | fn;
988 return 0;
989 }
990
991 static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
992 {
993 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
994
995 if (*ptr == -1) {
996 return snprintf(dest, len, "<unset>");
997 } else {
998 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
999 }
1000 }
1001
1002 static void get_pci_devfn(Object *obj, Visitor *v, void *opaque,
1003 const char *name, Error **errp)
1004 {
1005 DeviceState *dev = DEVICE(obj);
1006 Property *prop = opaque;
1007 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
1008 char buffer[32];
1009 char *p = buffer;
1010
1011 buffer[0] = 0;
1012 if (*ptr != -1) {
1013 snprintf(buffer, sizeof(buffer), "%02x.%x", *ptr >> 3, *ptr & 7);
1014 }
1015 visit_type_str(v, &p, name, errp);
1016 }
1017
1018 PropertyInfo qdev_prop_pci_devfn = {
1019 .name = "pci-devfn",
1020 .type = PROP_TYPE_UINT32,
1021 .size = sizeof(uint32_t),
1022 .parse = parse_pci_devfn,
1023 .print = print_pci_devfn,
1024 .get = get_pci_devfn,
1025 .set = set_generic,
1026 };
1027
1028 /* --- public helpers --- */
1029
1030 static Property *qdev_prop_walk(Property *props, const char *name)
1031 {
1032 if (!props)
1033 return NULL;
1034 while (props->name) {
1035 if (strcmp(props->name, name) == 0)
1036 return props;
1037 props++;
1038 }
1039 return NULL;
1040 }
1041
1042 static Property *qdev_prop_find(DeviceState *dev, const char *name)
1043 {
1044 Property *prop;
1045
1046 /* device properties */
1047 prop = qdev_prop_walk(qdev_get_props(dev), name);
1048 if (prop)
1049 return prop;
1050
1051 /* bus properties */
1052 prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1053 if (prop)
1054 return prop;
1055
1056 return NULL;
1057 }
1058
1059 int qdev_prop_exists(DeviceState *dev, const char *name)
1060 {
1061 return qdev_prop_find(dev, name) ? true : false;
1062 }
1063
1064 void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1065 Property *prop, const char *value)
1066 {
1067 switch (ret) {
1068 case -EEXIST:
1069 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
1070 object_get_typename(OBJECT(dev)), prop->name, value);
1071 break;
1072 default:
1073 case -EINVAL:
1074 error_set(errp, QERR_PROPERTY_VALUE_BAD,
1075 object_get_typename(OBJECT(dev)), prop->name, value);
1076 break;
1077 case -ENOENT:
1078 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
1079 object_get_typename(OBJECT(dev)), prop->name, value);
1080 break;
1081 case 0:
1082 break;
1083 }
1084 }
1085
1086 int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1087 {
1088 char *legacy_name;
1089 Error *err = NULL;
1090
1091 legacy_name = g_strdup_printf("legacy-%s", name);
1092 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
1093 object_property_set_str(OBJECT(dev), value, legacy_name, &err);
1094 } else {
1095 object_property_set_str(OBJECT(dev), value, name, &err);
1096 }
1097 g_free(legacy_name);
1098
1099 if (err) {
1100 qerror_report_err(err);
1101 error_free(err);
1102 return -1;
1103 }
1104 return 0;
1105 }
1106
1107 void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
1108 {
1109 Property *prop;
1110
1111 prop = qdev_prop_find(dev, name);
1112 if (!prop) {
1113 fprintf(stderr, "%s: property \"%s.%s\" not found\n",
1114 __FUNCTION__, object_get_typename(OBJECT(dev)), name);
1115 abort();
1116 }
1117 if (prop->info->type != type) {
1118 fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
1119 __FUNCTION__, object_get_typename(OBJECT(dev)), name);
1120 abort();
1121 }
1122 qdev_prop_cpy(dev, prop, src);
1123 }
1124
1125 void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1126 {
1127 qdev_prop_set(dev, name, &value, PROP_TYPE_BIT);
1128 }
1129
1130 void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1131 {
1132 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
1133 }
1134
1135 void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1136 {
1137 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
1138 }
1139
1140 void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1141 {
1142 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
1143 }
1144
1145 void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1146 {
1147 qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
1148 }
1149
1150 void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1151 {
1152 qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
1153 }
1154
1155 void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1156 {
1157 qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
1158 }
1159
1160 int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
1161 {
1162 int res;
1163
1164 res = bdrv_attach_dev(value, dev);
1165 if (res < 0) {
1166 error_report("Can't attach drive %s to %s.%s: %s",
1167 bdrv_get_device_name(value),
1168 dev->id ? dev->id : object_get_typename(OBJECT(dev)),
1169 name, strerror(-res));
1170 return -1;
1171 }
1172 qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
1173 return 0;
1174 }
1175
1176 void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1177 {
1178 if (qdev_prop_set_drive(dev, name, value) < 0) {
1179 exit(1);
1180 }
1181 }
1182 void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1183 {
1184 qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
1185 }
1186
1187 void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1188 {
1189 qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
1190 }
1191
1192 void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1193 {
1194 qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
1195 }
1196
1197 void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1198 {
1199 qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
1200 }
1201
1202 void qdev_prop_set_losttickpolicy(DeviceState *dev, const char *name,
1203 LostTickPolicy *value)
1204 {
1205 qdev_prop_set(dev, name, value, PROP_TYPE_LOSTTICKPOLICY);
1206 }
1207
1208 void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1209 {
1210 qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
1211 }
1212
1213 void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1214 {
1215 if (!props)
1216 return;
1217 while (props->name) {
1218 if (props->defval) {
1219 qdev_prop_cpy(dev, props, props->defval);
1220 }
1221 props++;
1222 }
1223 }
1224
1225 static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
1226
1227 static void qdev_prop_register_global(GlobalProperty *prop)
1228 {
1229 QTAILQ_INSERT_TAIL(&global_props, prop, next);
1230 }
1231
1232 void qdev_prop_register_global_list(GlobalProperty *props)
1233 {
1234 int i;
1235
1236 for (i = 0; props[i].driver != NULL; i++) {
1237 qdev_prop_register_global(props+i);
1238 }
1239 }
1240
1241 void qdev_prop_set_globals(DeviceState *dev)
1242 {
1243 GlobalProperty *prop;
1244
1245 QTAILQ_FOREACH(prop, &global_props, next) {
1246 if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
1247 strcmp(qdev_get_bus_info(dev)->name, prop->driver) != 0) {
1248 continue;
1249 }
1250 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
1251 exit(1);
1252 }
1253 }
1254 }
1255
1256 static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1257 {
1258 GlobalProperty *g;
1259
1260 g = g_malloc0(sizeof(*g));
1261 g->driver = qemu_opt_get(opts, "driver");
1262 g->property = qemu_opt_get(opts, "property");
1263 g->value = qemu_opt_get(opts, "value");
1264 qdev_prop_register_global(g);
1265 return 0;
1266 }
1267
1268 void qemu_add_globals(void)
1269 {
1270 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
1271 }