]>
Commit | Line | Data |
---|---|---|
14b41872 | 1 | #include "sysemu.h" |
1503fff3 | 2 | #include "net.h" |
ee6847d1 GH |
3 | #include "qdev.h" |
4 | ||
5 | void *qdev_get_prop_ptr(DeviceState *dev, Property *prop) | |
6 | { | |
7 | void *ptr = dev; | |
8 | ptr += prop->offset; | |
9 | return ptr; | |
10 | } | |
11 | ||
d2364ee4 MT |
12 | static uint32_t qdev_get_prop_mask(Property *prop) |
13 | { | |
14 | assert(prop->info->type == PROP_TYPE_BIT); | |
15 | return 0x1 << prop->bitnr; | |
16 | } | |
17 | ||
18 | static void bit_prop_set(DeviceState *dev, Property *props, bool val) | |
19 | { | |
20 | uint32_t *p = qdev_get_prop_ptr(dev, props); | |
21 | uint32_t mask = qdev_get_prop_mask(props); | |
22 | if (val) | |
dbd48324 | 23 | *p |= mask; |
d2364ee4 MT |
24 | else |
25 | *p &= ~mask; | |
26 | } | |
27 | ||
28 | static void qdev_prop_cpy(DeviceState *dev, Property *props, void *src) | |
29 | { | |
30 | if (props->info->type == PROP_TYPE_BIT) { | |
31 | bool *defval = src; | |
32 | bit_prop_set(dev, props, *defval); | |
33 | } else { | |
34 | char *dst = qdev_get_prop_ptr(dev, props); | |
35 | memcpy(dst, src, props->info->size); | |
36 | } | |
37 | } | |
38 | ||
39 | /* Bit */ | |
40 | static int parse_bit(DeviceState *dev, Property *prop, const char *str) | |
41 | { | |
42 | if (!strncasecmp(str, "on", 2)) | |
43 | bit_prop_set(dev, prop, true); | |
44 | else if (!strncasecmp(str, "off", 3)) | |
45 | bit_prop_set(dev, prop, false); | |
46 | else | |
6bf38816 | 47 | return -EINVAL; |
d2364ee4 MT |
48 | return 0; |
49 | } | |
50 | ||
51 | static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len) | |
52 | { | |
53 | uint8_t *p = qdev_get_prop_ptr(dev, prop); | |
54 | return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off"); | |
55 | } | |
56 | ||
57 | PropertyInfo qdev_prop_bit = { | |
58 | .name = "on/off", | |
59 | .type = PROP_TYPE_BIT, | |
60 | .size = sizeof(uint32_t), | |
61 | .parse = parse_bit, | |
62 | .print = print_bit, | |
63 | }; | |
64 | ||
c7cc172d JQ |
65 | /* --- 8bit integer --- */ |
66 | ||
67 | static int parse_uint8(DeviceState *dev, Property *prop, const char *str) | |
68 | { | |
69 | uint8_t *ptr = qdev_get_prop_ptr(dev, prop); | |
70 | const char *fmt; | |
71 | ||
72 | /* accept both hex and decimal */ | |
73 | fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx8 : "%" PRIu8; | |
74 | if (sscanf(str, fmt, ptr) != 1) | |
6bf38816 | 75 | return -EINVAL; |
c7cc172d JQ |
76 | return 0; |
77 | } | |
78 | ||
79 | static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len) | |
80 | { | |
81 | uint8_t *ptr = qdev_get_prop_ptr(dev, prop); | |
82 | return snprintf(dest, len, "%" PRIu8, *ptr); | |
83 | } | |
84 | ||
85 | PropertyInfo qdev_prop_uint8 = { | |
86 | .name = "uint8", | |
87 | .type = PROP_TYPE_UINT8, | |
88 | .size = sizeof(uint8_t), | |
89 | .parse = parse_uint8, | |
90 | .print = print_uint8, | |
91 | }; | |
92 | ||
ee6847d1 GH |
93 | /* --- 16bit integer --- */ |
94 | ||
95 | static int parse_uint16(DeviceState *dev, Property *prop, const char *str) | |
96 | { | |
97 | uint16_t *ptr = qdev_get_prop_ptr(dev, prop); | |
98 | const char *fmt; | |
99 | ||
100 | /* accept both hex and decimal */ | |
101 | fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16; | |
102 | if (sscanf(str, fmt, ptr) != 1) | |
6bf38816 | 103 | return -EINVAL; |
ee6847d1 GH |
104 | return 0; |
105 | } | |
106 | ||
107 | static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len) | |
108 | { | |
109 | uint16_t *ptr = qdev_get_prop_ptr(dev, prop); | |
110 | return snprintf(dest, len, "%" PRIu16, *ptr); | |
111 | } | |
112 | ||
113 | PropertyInfo qdev_prop_uint16 = { | |
114 | .name = "uint16", | |
115 | .type = PROP_TYPE_UINT16, | |
116 | .size = sizeof(uint16_t), | |
117 | .parse = parse_uint16, | |
118 | .print = print_uint16, | |
119 | }; | |
120 | ||
121 | /* --- 32bit integer --- */ | |
122 | ||
123 | static int parse_uint32(DeviceState *dev, Property *prop, const char *str) | |
124 | { | |
125 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
126 | const char *fmt; | |
127 | ||
128 | /* accept both hex and decimal */ | |
129 | fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32; | |
130 | if (sscanf(str, fmt, ptr) != 1) | |
6bf38816 | 131 | return -EINVAL; |
ee6847d1 GH |
132 | return 0; |
133 | } | |
134 | ||
135 | static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len) | |
136 | { | |
137 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
138 | return snprintf(dest, len, "%" PRIu32, *ptr); | |
139 | } | |
140 | ||
141 | PropertyInfo qdev_prop_uint32 = { | |
142 | .name = "uint32", | |
143 | .type = PROP_TYPE_UINT32, | |
144 | .size = sizeof(uint32_t), | |
145 | .parse = parse_uint32, | |
146 | .print = print_uint32, | |
147 | }; | |
148 | ||
316940b0 GH |
149 | static int parse_int32(DeviceState *dev, Property *prop, const char *str) |
150 | { | |
151 | int32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
152 | ||
153 | if (sscanf(str, "%" PRId32, ptr) != 1) | |
6bf38816 | 154 | return -EINVAL; |
316940b0 GH |
155 | return 0; |
156 | } | |
157 | ||
158 | static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len) | |
159 | { | |
160 | int32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
161 | return snprintf(dest, len, "%" PRId32, *ptr); | |
162 | } | |
163 | ||
164 | PropertyInfo qdev_prop_int32 = { | |
165 | .name = "int32", | |
166 | .type = PROP_TYPE_INT32, | |
167 | .size = sizeof(int32_t), | |
168 | .parse = parse_int32, | |
169 | .print = print_int32, | |
170 | }; | |
171 | ||
ee6847d1 GH |
172 | /* --- 32bit hex value --- */ |
173 | ||
174 | static int parse_hex32(DeviceState *dev, Property *prop, const char *str) | |
175 | { | |
176 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
177 | ||
178 | if (sscanf(str, "%" PRIx32, ptr) != 1) | |
6bf38816 | 179 | return -EINVAL; |
ee6847d1 GH |
180 | return 0; |
181 | } | |
182 | ||
183 | static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len) | |
184 | { | |
185 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
186 | return snprintf(dest, len, "0x%" PRIx32, *ptr); | |
187 | } | |
188 | ||
189 | PropertyInfo qdev_prop_hex32 = { | |
190 | .name = "hex32", | |
191 | .type = PROP_TYPE_UINT32, | |
192 | .size = sizeof(uint32_t), | |
193 | .parse = parse_hex32, | |
194 | .print = print_hex32, | |
195 | }; | |
196 | ||
5a053d1f BS |
197 | /* --- 64bit integer --- */ |
198 | ||
199 | static int parse_uint64(DeviceState *dev, Property *prop, const char *str) | |
200 | { | |
201 | uint64_t *ptr = qdev_get_prop_ptr(dev, prop); | |
202 | const char *fmt; | |
203 | ||
204 | /* accept both hex and decimal */ | |
205 | fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx64 : "%" PRIu64; | |
206 | if (sscanf(str, fmt, ptr) != 1) | |
6bf38816 | 207 | return -EINVAL; |
5a053d1f BS |
208 | return 0; |
209 | } | |
210 | ||
211 | static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len) | |
212 | { | |
213 | uint64_t *ptr = qdev_get_prop_ptr(dev, prop); | |
214 | return snprintf(dest, len, "%" PRIu64, *ptr); | |
215 | } | |
216 | ||
217 | PropertyInfo qdev_prop_uint64 = { | |
218 | .name = "uint64", | |
219 | .type = PROP_TYPE_UINT64, | |
220 | .size = sizeof(uint64_t), | |
221 | .parse = parse_uint64, | |
222 | .print = print_uint64, | |
223 | }; | |
224 | ||
225 | /* --- 64bit hex value --- */ | |
226 | ||
227 | static int parse_hex64(DeviceState *dev, Property *prop, const char *str) | |
228 | { | |
229 | uint64_t *ptr = qdev_get_prop_ptr(dev, prop); | |
230 | ||
231 | if (sscanf(str, "%" PRIx64, ptr) != 1) | |
6bf38816 | 232 | return -EINVAL; |
5a053d1f BS |
233 | return 0; |
234 | } | |
235 | ||
236 | static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len) | |
237 | { | |
238 | uint64_t *ptr = qdev_get_prop_ptr(dev, prop); | |
239 | return snprintf(dest, len, "0x%" PRIx64, *ptr); | |
240 | } | |
241 | ||
242 | PropertyInfo qdev_prop_hex64 = { | |
243 | .name = "hex64", | |
244 | .type = PROP_TYPE_UINT64, | |
245 | .size = sizeof(uint64_t), | |
246 | .parse = parse_hex64, | |
247 | .print = print_hex64, | |
248 | }; | |
249 | ||
59419663 GH |
250 | /* --- string --- */ |
251 | ||
252 | static int parse_string(DeviceState *dev, Property *prop, const char *str) | |
253 | { | |
254 | char **ptr = qdev_get_prop_ptr(dev, prop); | |
255 | ||
256 | if (*ptr) | |
257 | qemu_free(*ptr); | |
258 | *ptr = qemu_strdup(str); | |
259 | return 0; | |
260 | } | |
261 | ||
262 | static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len) | |
263 | { | |
264 | char **ptr = qdev_get_prop_ptr(dev, prop); | |
265 | if (!*ptr) | |
266 | return snprintf(dest, len, "<null>"); | |
267 | return snprintf(dest, len, "\"%s\"", *ptr); | |
268 | } | |
269 | ||
270 | PropertyInfo qdev_prop_string = { | |
271 | .name = "string", | |
272 | .type = PROP_TYPE_STRING, | |
273 | .size = sizeof(char*), | |
274 | .parse = parse_string, | |
275 | .print = print_string, | |
276 | }; | |
277 | ||
14b41872 GH |
278 | /* --- drive --- */ |
279 | ||
280 | static int parse_drive(DeviceState *dev, Property *prop, const char *str) | |
281 | { | |
282 | DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); | |
283 | ||
284 | *ptr = drive_get_by_id(str); | |
285 | if (*ptr == NULL) | |
6bf38816 | 286 | return -ENOENT; |
14b41872 GH |
287 | return 0; |
288 | } | |
289 | ||
290 | static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len) | |
291 | { | |
292 | DriveInfo **ptr = qdev_get_prop_ptr(dev, prop); | |
41b5e892 | 293 | return snprintf(dest, len, "%s", (*ptr) ? (*ptr)->id : "<null>"); |
14b41872 GH |
294 | } |
295 | ||
296 | PropertyInfo qdev_prop_drive = { | |
297 | .name = "drive", | |
298 | .type = PROP_TYPE_DRIVE, | |
299 | .size = sizeof(DriveInfo*), | |
300 | .parse = parse_drive, | |
301 | .print = print_drive, | |
302 | }; | |
303 | ||
313feaab GH |
304 | /* --- character device --- */ |
305 | ||
06113719 GH |
306 | static int parse_chr(DeviceState *dev, Property *prop, const char *str) |
307 | { | |
308 | CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); | |
309 | ||
310 | *ptr = qemu_chr_find(str); | |
311 | if (*ptr == NULL) | |
6bf38816 | 312 | return -ENOENT; |
06113719 GH |
313 | return 0; |
314 | } | |
315 | ||
313feaab GH |
316 | static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len) |
317 | { | |
318 | CharDriverState **ptr = qdev_get_prop_ptr(dev, prop); | |
bc19fcaa BS |
319 | |
320 | if (*ptr && (*ptr)->label) { | |
321 | return snprintf(dest, len, "%s", (*ptr)->label); | |
322 | } else { | |
323 | return snprintf(dest, len, "<null>"); | |
324 | } | |
313feaab GH |
325 | } |
326 | ||
327 | PropertyInfo qdev_prop_chr = { | |
328 | .name = "chr", | |
329 | .type = PROP_TYPE_CHR, | |
330 | .size = sizeof(CharDriverState*), | |
06113719 | 331 | .parse = parse_chr, |
313feaab GH |
332 | .print = print_chr, |
333 | }; | |
334 | ||
2ef924b4 GH |
335 | /* --- netdev device --- */ |
336 | ||
337 | static int parse_netdev(DeviceState *dev, Property *prop, const char *str) | |
338 | { | |
339 | VLANClientState **ptr = qdev_get_prop_ptr(dev, prop); | |
340 | ||
341 | *ptr = qemu_find_netdev(str); | |
342 | if (*ptr == NULL) | |
6bf38816 | 343 | return -ENOENT; |
27f3f8a3 MA |
344 | if ((*ptr)->peer) { |
345 | return -EEXIST; | |
346 | } | |
2ef924b4 GH |
347 | return 0; |
348 | } | |
349 | ||
350 | static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len) | |
351 | { | |
352 | VLANClientState **ptr = qdev_get_prop_ptr(dev, prop); | |
353 | ||
354 | if (*ptr && (*ptr)->name) { | |
355 | return snprintf(dest, len, "%s", (*ptr)->name); | |
356 | } else { | |
357 | return snprintf(dest, len, "<null>"); | |
358 | } | |
359 | } | |
360 | ||
361 | PropertyInfo qdev_prop_netdev = { | |
362 | .name = "netdev", | |
363 | .type = PROP_TYPE_NETDEV, | |
364 | .size = sizeof(VLANClientState*), | |
365 | .parse = parse_netdev, | |
366 | .print = print_netdev, | |
367 | }; | |
368 | ||
851bec09 GH |
369 | /* --- vlan --- */ |
370 | ||
371 | static int parse_vlan(DeviceState *dev, Property *prop, const char *str) | |
372 | { | |
373 | VLANState **ptr = qdev_get_prop_ptr(dev, prop); | |
374 | int id; | |
375 | ||
376 | if (sscanf(str, "%d", &id) != 1) | |
6bf38816 | 377 | return -EINVAL; |
851bec09 GH |
378 | *ptr = qemu_find_vlan(id, 1); |
379 | if (*ptr == NULL) | |
6bf38816 | 380 | return -ENOENT; |
851bec09 GH |
381 | return 0; |
382 | } | |
383 | ||
384 | static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len) | |
385 | { | |
386 | VLANState **ptr = qdev_get_prop_ptr(dev, prop); | |
387 | ||
388 | if (*ptr) { | |
389 | return snprintf(dest, len, "%d", (*ptr)->id); | |
390 | } else { | |
391 | return snprintf(dest, len, "<null>"); | |
392 | } | |
393 | } | |
394 | ||
395 | PropertyInfo qdev_prop_vlan = { | |
396 | .name = "vlan", | |
397 | .type = PROP_TYPE_VLAN, | |
398 | .size = sizeof(VLANClientState*), | |
399 | .parse = parse_vlan, | |
400 | .print = print_vlan, | |
401 | }; | |
402 | ||
ee6847d1 GH |
403 | /* --- pointer --- */ |
404 | ||
405 | static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len) | |
406 | { | |
407 | void **ptr = qdev_get_prop_ptr(dev, prop); | |
408 | return snprintf(dest, len, "<%p>", *ptr); | |
409 | } | |
410 | ||
411 | PropertyInfo qdev_prop_ptr = { | |
412 | .name = "ptr", | |
413 | .type = PROP_TYPE_PTR, | |
414 | .size = sizeof(void*), | |
415 | .print = print_ptr, | |
416 | }; | |
417 | ||
418 | /* --- mac address --- */ | |
419 | ||
420 | /* | |
421 | * accepted syntax versions: | |
422 | * 01:02:03:04:05:06 | |
423 | * 01-02-03-04-05-06 | |
424 | */ | |
425 | static int parse_mac(DeviceState *dev, Property *prop, const char *str) | |
426 | { | |
1503fff3 | 427 | MACAddr *mac = qdev_get_prop_ptr(dev, prop); |
ee6847d1 GH |
428 | int i, pos; |
429 | char *p; | |
430 | ||
431 | for (i = 0, pos = 0; i < 6; i++, pos += 3) { | |
88e150a5 | 432 | if (!qemu_isxdigit(str[pos])) |
6bf38816 | 433 | return -EINVAL; |
88e150a5 | 434 | if (!qemu_isxdigit(str[pos+1])) |
6bf38816 | 435 | return -EINVAL; |
1503fff3 GH |
436 | if (i == 5) { |
437 | if (str[pos+2] != '\0') | |
6bf38816 | 438 | return -EINVAL; |
1503fff3 GH |
439 | } else { |
440 | if (str[pos+2] != ':' && str[pos+2] != '-') | |
6bf38816 | 441 | return -EINVAL; |
1503fff3 GH |
442 | } |
443 | mac->a[i] = strtol(str+pos, &p, 16); | |
ee6847d1 GH |
444 | } |
445 | return 0; | |
446 | } | |
447 | ||
448 | static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len) | |
449 | { | |
1503fff3 GH |
450 | MACAddr *mac = qdev_get_prop_ptr(dev, prop); |
451 | ||
ee6847d1 | 452 | return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x", |
1503fff3 GH |
453 | mac->a[0], mac->a[1], mac->a[2], |
454 | mac->a[3], mac->a[4], mac->a[5]); | |
ee6847d1 GH |
455 | } |
456 | ||
457 | PropertyInfo qdev_prop_macaddr = { | |
1503fff3 | 458 | .name = "macaddr", |
ee6847d1 | 459 | .type = PROP_TYPE_MACADDR, |
1503fff3 | 460 | .size = sizeof(MACAddr), |
ee6847d1 GH |
461 | .parse = parse_mac, |
462 | .print = print_mac, | |
463 | }; | |
464 | ||
05cb5fe4 GH |
465 | /* --- pci address --- */ |
466 | ||
467 | /* | |
468 | * bus-local address, i.e. "$slot" or "$slot.$fn" | |
469 | */ | |
470 | static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str) | |
471 | { | |
472 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
473 | unsigned int slot, fn, n; | |
474 | ||
475 | if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) { | |
476 | fn = 0; | |
477 | if (sscanf(str, "%x%n", &slot, &n) != 1) { | |
6bf38816 | 478 | return -EINVAL; |
05cb5fe4 GH |
479 | } |
480 | } | |
481 | if (str[n] != '\0') | |
6bf38816 | 482 | return -EINVAL; |
05cb5fe4 | 483 | if (fn > 7) |
6bf38816 | 484 | return -EINVAL; |
05cb5fe4 GH |
485 | *ptr = slot << 3 | fn; |
486 | return 0; | |
487 | } | |
488 | ||
489 | static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len) | |
490 | { | |
491 | uint32_t *ptr = qdev_get_prop_ptr(dev, prop); | |
492 | ||
73538c31 | 493 | if (*ptr == -1) { |
05cb5fe4 GH |
494 | return snprintf(dest, len, "<unset>"); |
495 | } else { | |
496 | return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7); | |
497 | } | |
498 | } | |
499 | ||
500 | PropertyInfo qdev_prop_pci_devfn = { | |
501 | .name = "pci-devfn", | |
502 | .type = PROP_TYPE_UINT32, | |
503 | .size = sizeof(uint32_t), | |
504 | .parse = parse_pci_devfn, | |
505 | .print = print_pci_devfn, | |
506 | }; | |
507 | ||
ee6847d1 GH |
508 | /* --- public helpers --- */ |
509 | ||
510 | static Property *qdev_prop_walk(Property *props, const char *name) | |
511 | { | |
512 | if (!props) | |
513 | return NULL; | |
514 | while (props->name) { | |
515 | if (strcmp(props->name, name) == 0) | |
516 | return props; | |
517 | props++; | |
518 | } | |
519 | return NULL; | |
520 | } | |
521 | ||
522 | static Property *qdev_prop_find(DeviceState *dev, const char *name) | |
523 | { | |
524 | Property *prop; | |
525 | ||
526 | /* device properties */ | |
527 | prop = qdev_prop_walk(dev->info->props, name); | |
528 | if (prop) | |
529 | return prop; | |
530 | ||
531 | /* bus properties */ | |
532 | prop = qdev_prop_walk(dev->parent_bus->info->props, name); | |
533 | if (prop) | |
534 | return prop; | |
535 | ||
536 | return NULL; | |
537 | } | |
538 | ||
d8ed79ae GH |
539 | int qdev_prop_exists(DeviceState *dev, const char *name) |
540 | { | |
541 | return qdev_prop_find(dev, name) ? true : false; | |
542 | } | |
543 | ||
ee6847d1 GH |
544 | int qdev_prop_parse(DeviceState *dev, const char *name, const char *value) |
545 | { | |
546 | Property *prop; | |
6bf38816 | 547 | int ret; |
ee6847d1 GH |
548 | |
549 | prop = qdev_prop_find(dev, name); | |
550 | if (!prop) { | |
5137b6ac MA |
551 | fprintf(stderr, "property \"%s.%s\" not found\n", |
552 | dev->info->name, name); | |
ee6847d1 GH |
553 | return -1; |
554 | } | |
555 | if (!prop->info->parse) { | |
556 | fprintf(stderr, "property \"%s.%s\" has no parser\n", | |
557 | dev->info->name, name); | |
558 | return -1; | |
559 | } | |
6bf38816 MA |
560 | ret = prop->info->parse(dev, prop, value); |
561 | if (ret < 0) { | |
562 | switch (ret) { | |
27f3f8a3 MA |
563 | case -EEXIST: |
564 | fprintf(stderr, "property \"%s.%s\": \"%s\" is already in use\n", | |
565 | dev->info->name, name, value); | |
566 | break; | |
6bf38816 MA |
567 | default: |
568 | case -EINVAL: | |
569 | fprintf(stderr, "property \"%s.%s\": failed to parse \"%s\"\n", | |
570 | dev->info->name, name, value); | |
571 | break; | |
572 | case -ENOENT: | |
573 | fprintf(stderr, "property \"%s.%s\": could not find \"%s\"\n", | |
574 | dev->info->name, name, value); | |
575 | break; | |
576 | } | |
9ef5c4bf GH |
577 | return -1; |
578 | } | |
579 | return 0; | |
ee6847d1 GH |
580 | } |
581 | ||
582 | void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type) | |
583 | { | |
584 | Property *prop; | |
ee6847d1 GH |
585 | |
586 | prop = qdev_prop_find(dev, name); | |
587 | if (!prop) { | |
588 | fprintf(stderr, "%s: property \"%s.%s\" not found\n", | |
589 | __FUNCTION__, dev->info->name, name); | |
590 | abort(); | |
591 | } | |
592 | if (prop->info->type != type) { | |
593 | fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n", | |
594 | __FUNCTION__, dev->info->name, name); | |
595 | abort(); | |
596 | } | |
d2364ee4 | 597 | qdev_prop_cpy(dev, prop, src); |
ee6847d1 GH |
598 | } |
599 | ||
c7cc172d JQ |
600 | void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value) |
601 | { | |
602 | qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8); | |
603 | } | |
604 | ||
ee6847d1 GH |
605 | void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value) |
606 | { | |
607 | qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16); | |
608 | } | |
609 | ||
610 | void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value) | |
611 | { | |
612 | qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32); | |
613 | } | |
614 | ||
316940b0 GH |
615 | void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value) |
616 | { | |
617 | qdev_prop_set(dev, name, &value, PROP_TYPE_INT32); | |
618 | } | |
619 | ||
5a053d1f BS |
620 | void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value) |
621 | { | |
622 | qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64); | |
623 | } | |
624 | ||
14b41872 GH |
625 | void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value) |
626 | { | |
627 | qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE); | |
628 | } | |
629 | ||
313feaab GH |
630 | void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value) |
631 | { | |
632 | qdev_prop_set(dev, name, &value, PROP_TYPE_CHR); | |
633 | } | |
634 | ||
2ef924b4 GH |
635 | void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value) |
636 | { | |
637 | qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV); | |
638 | } | |
639 | ||
851bec09 GH |
640 | void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value) |
641 | { | |
642 | qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN); | |
643 | } | |
644 | ||
1503fff3 GH |
645 | void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value) |
646 | { | |
647 | qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR); | |
648 | } | |
649 | ||
ee6847d1 GH |
650 | void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) |
651 | { | |
652 | qdev_prop_set(dev, name, &value, PROP_TYPE_PTR); | |
653 | } | |
654 | ||
655 | void qdev_prop_set_defaults(DeviceState *dev, Property *props) | |
656 | { | |
ee6847d1 GH |
657 | if (!props) |
658 | return; | |
659 | while (props->name) { | |
660 | if (props->defval) { | |
d2364ee4 | 661 | qdev_prop_cpy(dev, props, props->defval); |
ee6847d1 GH |
662 | } |
663 | props++; | |
664 | } | |
665 | } | |
666 | ||
458fb679 | 667 | static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props); |
b6b61144 | 668 | |
458fb679 | 669 | void qdev_prop_register_global(GlobalProperty *prop) |
b6b61144 | 670 | { |
458fb679 | 671 | QTAILQ_INSERT_TAIL(&global_props, prop, next); |
b6b61144 GH |
672 | } |
673 | ||
458fb679 | 674 | void qdev_prop_register_global_list(GlobalProperty *props) |
b6b61144 | 675 | { |
458fb679 | 676 | int i; |
b6b61144 | 677 | |
458fb679 GH |
678 | for (i = 0; props[i].driver != NULL; i++) { |
679 | qdev_prop_register_global(props+i); | |
b6b61144 | 680 | } |
458fb679 GH |
681 | } |
682 | ||
683 | void qdev_prop_set_globals(DeviceState *dev) | |
684 | { | |
685 | GlobalProperty *prop; | |
686 | ||
687 | QTAILQ_FOREACH(prop, &global_props, next) { | |
07a8de35 GH |
688 | if (strcmp(dev->info->name, prop->driver) != 0 && |
689 | strcmp(dev->info->bus_info->name, prop->driver) != 0) { | |
b6b61144 GH |
690 | continue; |
691 | } | |
692 | if (qdev_prop_parse(dev, prop->property, prop->value) != 0) { | |
9ef5c4bf | 693 | exit(1); |
b6b61144 GH |
694 | } |
695 | } | |
696 | } |