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