Statistics
| Branch: | Revision:

root / hw / qdev-properties.c @ 4e4fa398

History | View | Annotate | Download (30.4 kB)

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(DeviceState *dev, Visitor *v, void *opaque,
59
                    const char *name, Error **errp)
60
{
61
    Property *prop = opaque;
62
    uint32_t *p = qdev_get_prop_ptr(dev, prop);
63
    bool value = (*p & qdev_get_prop_mask(prop)) != 0;
64

    
65
    visit_type_bool(v, &value, name, errp);
66
}
67

    
68
static void set_bit(DeviceState *dev, Visitor *v, void *opaque,
69
                    const char *name, Error **errp)
70
{
71
    Property *prop = opaque;
72
    Error *local_err = NULL;
73
    bool value;
74

    
75
    if (dev->state != DEV_STATE_CREATED) {
76
        error_set(errp, QERR_PERMISSION_DENIED);
77
        return;
78
    }
79

    
80
    visit_type_bool(v, &value, name, &local_err);
81
    if (local_err) {
82
        error_propagate(errp, local_err);
83
        return;
84
    }
85
    bit_prop_set(dev, prop, value);
86
}
87

    
88
PropertyInfo qdev_prop_bit = {
89
    .name  = "boolean",
90
    .legacy_name  = "on/off",
91
    .type  = PROP_TYPE_BIT,
92
    .size  = sizeof(uint32_t),
93
    .parse = parse_bit,
94
    .print = print_bit,
95
    .get   = get_bit,
96
    .set   = set_bit,
97
};
98

    
99
/* --- 8bit integer --- */
100

    
101
static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
102
{
103
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
104
    char *end;
105

    
106
    /* accept both hex and decimal */
107
    *ptr = strtoul(str, &end, 0);
108
    if ((*end != '\0') || (end == str)) {
109
        return -EINVAL;
110
    }
111

    
112
    return 0;
113
}
114

    
115
static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
116
{
117
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
118
    return snprintf(dest, len, "%" PRIu8, *ptr);
119
}
120

    
121
static void get_int8(DeviceState *dev, Visitor *v, void *opaque,
122
                     const char *name, Error **errp)
123
{
124
    Property *prop = opaque;
125
    int8_t *ptr = qdev_get_prop_ptr(dev, prop);
126
    int64_t value;
127

    
128
    value = *ptr;
129
    visit_type_int(v, &value, name, errp);
130
}
131

    
132
static void set_int8(DeviceState *dev, Visitor *v, void *opaque,
133
                      const char *name, Error **errp)
134
{
135
    Property *prop = opaque;
136
    int8_t *ptr = qdev_get_prop_ptr(dev, prop);
137
    Error *local_err = NULL;
138
    int64_t value;
139

    
140
    if (dev->state != DEV_STATE_CREATED) {
141
        error_set(errp, QERR_PERMISSION_DENIED);
142
        return;
143
    }
144

    
145
    visit_type_int(v, &value, name, &local_err);
146
    if (local_err) {
147
        error_propagate(errp, local_err);
148
        return;
149
    }
150
    if (value > prop->info->min && value <= prop->info->max) {
151
        *ptr = value;
152
    } else {
153
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
154
                  dev->id?:"", name, value, prop->info->min,
155
                  prop->info->max);
156
    }
157
}
158

    
159
PropertyInfo qdev_prop_uint8 = {
160
    .name  = "uint8",
161
    .type  = PROP_TYPE_UINT8,
162
    .size  = sizeof(uint8_t),
163
    .parse = parse_uint8,
164
    .print = print_uint8,
165
    .get   = get_int8,
166
    .set   = set_int8,
167
    .min   = 0,
168
    .max   = 255,
169
};
170

    
171
/* --- 8bit hex value --- */
172

    
173
static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
174
{
175
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
176
    char *end;
177

    
178
    *ptr = strtoul(str, &end, 16);
179
    if ((*end != '\0') || (end == str)) {
180
        return -EINVAL;
181
    }
182

    
183
    return 0;
184
}
185

    
186
static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
187
{
188
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
189
    return snprintf(dest, len, "0x%" PRIx8, *ptr);
190
}
191

    
192
PropertyInfo qdev_prop_hex8 = {
193
    .name  = "uint8",
194
    .legacy_name  = "hex8",
195
    .type  = PROP_TYPE_UINT8,
196
    .size  = sizeof(uint8_t),
197
    .parse = parse_hex8,
198
    .print = print_hex8,
199
    .get   = get_int8,
200
    .set   = set_int8,
201
    .min   = 0,
202
    .max   = 255,
203
};
204

    
205
/* --- 16bit integer --- */
206

    
207
static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
208
{
209
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
210
    char *end;
211

    
212
    /* accept both hex and decimal */
213
    *ptr = strtoul(str, &end, 0);
214
    if ((*end != '\0') || (end == str)) {
215
        return -EINVAL;
216
    }
217

    
218
    return 0;
219
}
220

    
221
static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
222
{
223
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
224
    return snprintf(dest, len, "%" PRIu16, *ptr);
225
}
226

    
227
static void get_int16(DeviceState *dev, Visitor *v, void *opaque,
228
                      const char *name, Error **errp)
229
{
230
    Property *prop = opaque;
231
    int16_t *ptr = qdev_get_prop_ptr(dev, prop);
232
    int64_t value;
233

    
234
    value = *ptr;
235
    visit_type_int(v, &value, name, errp);
236
}
237

    
238
static void set_int16(DeviceState *dev, Visitor *v, void *opaque,
239
                      const char *name, Error **errp)
240
{
241
    Property *prop = opaque;
242
    int16_t *ptr = qdev_get_prop_ptr(dev, prop);
243
    Error *local_err = NULL;
244
    int64_t value;
245

    
246
    if (dev->state != DEV_STATE_CREATED) {
247
        error_set(errp, QERR_PERMISSION_DENIED);
248
        return;
249
    }
250

    
251
    visit_type_int(v, &value, name, &local_err);
252
    if (local_err) {
253
        error_propagate(errp, local_err);
254
        return;
255
    }
256
    if (value > prop->info->min && value <= prop->info->max) {
257
        *ptr = value;
258
    } else {
259
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
260
                  dev->id?:"", name, value, prop->info->min,
261
                  prop->info->max);
262
    }
263
}
264

    
265
PropertyInfo qdev_prop_uint16 = {
266
    .name  = "uint16",
267
    .type  = PROP_TYPE_UINT16,
268
    .size  = sizeof(uint16_t),
269
    .parse = parse_uint16,
270
    .print = print_uint16,
271
    .get   = get_int16,
272
    .set   = set_int16,
273
    .min   = 0,
274
    .max   = 65535,
275
};
276

    
277
/* --- 32bit integer --- */
278

    
279
static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
280
{
281
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
282
    char *end;
283

    
284
    /* accept both hex and decimal */
285
    *ptr = strtoul(str, &end, 0);
286
    if ((*end != '\0') || (end == str)) {
287
        return -EINVAL;
288
    }
289

    
290
    return 0;
291
}
292

    
293
static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
294
{
295
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
296
    return snprintf(dest, len, "%" PRIu32, *ptr);
297
}
298

    
299
static void get_int32(DeviceState *dev, Visitor *v, void *opaque,
300
                      const char *name, Error **errp)
301
{
302
    Property *prop = opaque;
303
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
304
    int64_t value;
305

    
306
    value = *ptr;
307
    visit_type_int(v, &value, name, errp);
308
}
309

    
310
static void set_int32(DeviceState *dev, Visitor *v, void *opaque,
311
                      const char *name, Error **errp)
312
{
313
    Property *prop = opaque;
314
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
315
    Error *local_err = NULL;
316
    int64_t value;
317

    
318
    if (dev->state != DEV_STATE_CREATED) {
319
        error_set(errp, QERR_PERMISSION_DENIED);
320
        return;
321
    }
322

    
323
    visit_type_int(v, &value, name, &local_err);
324
    if (local_err) {
325
        error_propagate(errp, local_err);
326
        return;
327
    }
328
    if (value > prop->info->min && value <= prop->info->max) {
329
        *ptr = value;
330
    } else {
331
        error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
332
                  dev->id?:"", name, value, prop->info->min,
333
                  prop->info->max);
334
    }
335
}
336

    
337
PropertyInfo qdev_prop_uint32 = {
338
    .name  = "uint32",
339
    .type  = PROP_TYPE_UINT32,
340
    .size  = sizeof(uint32_t),
341
    .parse = parse_uint32,
342
    .print = print_uint32,
343
    .get   = get_int32,
344
    .set   = set_int32,
345
    .min   = 0,
346
    .max   = 0xFFFFFFFFULL,
347
};
348

    
349
static int parse_int32(DeviceState *dev, Property *prop, const char *str)
350
{
351
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
352
    char *end;
353

    
354
    *ptr = strtol(str, &end, 10);
355
    if ((*end != '\0') || (end == str)) {
356
        return -EINVAL;
357
    }
358

    
359
    return 0;
360
}
361

    
362
static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
363
{
364
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
365
    return snprintf(dest, len, "%" PRId32, *ptr);
366
}
367

    
368
PropertyInfo qdev_prop_int32 = {
369
    .name  = "int32",
370
    .type  = PROP_TYPE_INT32,
371
    .size  = sizeof(int32_t),
372
    .parse = parse_int32,
373
    .print = print_int32,
374
    .get   = get_int32,
375
    .set   = set_int32,
376
    .min   = -0x80000000LL,
377
    .max   = 0x7FFFFFFFLL,
378
};
379

    
380
/* --- 32bit hex value --- */
381

    
382
static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
383
{
384
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
385
    char *end;
386

    
387
    *ptr = strtoul(str, &end, 16);
388
    if ((*end != '\0') || (end == str)) {
389
        return -EINVAL;
390
    }
391

    
392
    return 0;
393
}
394

    
395
static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
396
{
397
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
398
    return snprintf(dest, len, "0x%" PRIx32, *ptr);
399
}
400

    
401
PropertyInfo qdev_prop_hex32 = {
402
    .name  = "uint32",
403
    .legacy_name  = "hex32",
404
    .type  = PROP_TYPE_UINT32,
405
    .size  = sizeof(uint32_t),
406
    .parse = parse_hex32,
407
    .print = print_hex32,
408
    .get   = get_int32,
409
    .set   = set_int32,
410
    .min   = 0,
411
    .max   = 0xFFFFFFFFULL,
412
};
413

    
414
/* --- 64bit integer --- */
415

    
416
static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
417
{
418
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
419
    char *end;
420

    
421
    /* accept both hex and decimal */
422
    *ptr = strtoull(str, &end, 0);
423
    if ((*end != '\0') || (end == str)) {
424
        return -EINVAL;
425
    }
426

    
427
    return 0;
428
}
429

    
430
static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
431
{
432
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
433
    return snprintf(dest, len, "%" PRIu64, *ptr);
434
}
435

    
436
static void get_int64(DeviceState *dev, Visitor *v, void *opaque,
437
                      const char *name, Error **errp)
438
{
439
    Property *prop = opaque;
440
    int64_t *ptr = qdev_get_prop_ptr(dev, prop);
441

    
442
    visit_type_int(v, ptr, name, errp);
443
}
444

    
445
static void set_int64(DeviceState *dev, Visitor *v, void *opaque,
446
                      const char *name, Error **errp)
447
{
448
    Property *prop = opaque;
449
    int64_t *ptr = qdev_get_prop_ptr(dev, prop);
450

    
451
    if (dev->state != DEV_STATE_CREATED) {
452
        error_set(errp, QERR_PERMISSION_DENIED);
453
        return;
454
    }
455

    
456
    visit_type_int(v, ptr, name, errp);
457
}
458

    
459
PropertyInfo qdev_prop_uint64 = {
460
    .name  = "uint64",
461
    .type  = PROP_TYPE_UINT64,
462
    .size  = sizeof(uint64_t),
463
    .parse = parse_uint64,
464
    .print = print_uint64,
465
    .get   = get_int64,
466
    .set   = set_int64,
467
};
468

    
469
/* --- 64bit hex value --- */
470

    
471
static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
472
{
473
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
474
    char *end;
475

    
476
    *ptr = strtoull(str, &end, 16);
477
    if ((*end != '\0') || (end == str)) {
478
        return -EINVAL;
479
    }
480

    
481
    return 0;
482
}
483

    
484
static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
485
{
486
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
487
    return snprintf(dest, len, "0x%" PRIx64, *ptr);
488
}
489

    
490
PropertyInfo qdev_prop_hex64 = {
491
    .name  = "uint64",
492
    .legacy_name  = "hex64",
493
    .type  = PROP_TYPE_UINT64,
494
    .size  = sizeof(uint64_t),
495
    .parse = parse_hex64,
496
    .print = print_hex64,
497
    .get   = get_int64,
498
    .set   = set_int64,
499
};
500

    
501
/* --- string --- */
502

    
503
static int parse_string(DeviceState *dev, Property *prop, const char *str)
504
{
505
    char **ptr = qdev_get_prop_ptr(dev, prop);
506

    
507
    if (*ptr)
508
        g_free(*ptr);
509
    *ptr = g_strdup(str);
510
    return 0;
511
}
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(DeviceState *dev, Visitor *v, void *opaque,
527
                       const char *name, Error **errp)
528
{
529
    Property *prop = opaque;
530
    char **ptr = qdev_get_prop_ptr(dev, prop);
531

    
532
    if (!*ptr) {
533
        char *str = (char *)"";
534
        visit_type_str(v, &str, name, errp);
535
    } else {
536
        visit_type_str(v, ptr, name, errp);
537
    }
538
}
539

    
540
static void set_string(DeviceState *dev, Visitor *v, void *opaque,
541
                       const char *name, Error **errp)
542
{
543
    Property *prop = opaque;
544
    char **ptr = qdev_get_prop_ptr(dev, prop);
545
    Error *local_err = NULL;
546
    char *str;
547

    
548
    if (dev->state != DEV_STATE_CREATED) {
549
        error_set(errp, QERR_PERMISSION_DENIED);
550
        return;
551
    }
552

    
553
    visit_type_str(v, &str, name, &local_err);
554
    if (local_err) {
555
        error_propagate(errp, local_err);
556
        return;
557
    }
558
    if (!*str) {
559
        g_free(str);
560
        str = NULL;
561
    }
562
    if (*ptr) {
563
        g_free(*ptr);
564
    }
565
    *ptr = str;
566
}
567

    
568
PropertyInfo qdev_prop_string = {
569
    .name  = "string",
570
    .type  = PROP_TYPE_STRING,
571
    .size  = sizeof(char*),
572
    .parse = parse_string,
573
    .print = print_string,
574
    .free  = free_string,
575
    .get   = get_string,
576
    .set   = set_string,
577
};
578

    
579
/* --- drive --- */
580

    
581
static int parse_drive(DeviceState *dev, Property *prop, const char *str)
582
{
583
    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
584
    BlockDriverState *bs;
585

    
586
    bs = bdrv_find(str);
587
    if (bs == NULL)
588
        return -ENOENT;
589
    if (bdrv_attach_dev(bs, dev) < 0)
590
        return -EEXIST;
591
    *ptr = bs;
592
    return 0;
593
}
594

    
595
static void free_drive(DeviceState *dev, Property *prop)
596
{
597
    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
598

    
599
    if (*ptr) {
600
        bdrv_detach_dev(*ptr, dev);
601
        blockdev_auto_del(*ptr);
602
    }
603
}
604

    
605
static int print_drive(DeviceState *dev, Property *prop, char *dest, size_t len)
606
{
607
    BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
608
    return snprintf(dest, len, "%s",
609
                    *ptr ? bdrv_get_device_name(*ptr) : "<null>");
610
}
611

    
612
static void get_generic(DeviceState *dev, Visitor *v, void *opaque,
613
                       const char *name, Error **errp)
614
{
615
    Property *prop = opaque;
616
    void **ptr = qdev_get_prop_ptr(dev, prop);
617
    char buffer[1024];
618
    char *p = buffer;
619

    
620
    buffer[0] = 0;
621
    if (*ptr) {
622
        prop->info->print(dev, prop, buffer, sizeof(buffer));
623
    }
624
    visit_type_str(v, &p, name, errp);
625
}
626

    
627
static void set_generic(DeviceState *dev, Visitor *v, void *opaque,
628
                        const char *name, Error **errp)
629
{
630
    Property *prop = opaque;
631
    Error *local_err = NULL;
632
    char *str;
633
    int ret;
634

    
635
    if (dev->state != DEV_STATE_CREATED) {
636
        error_set(errp, QERR_PERMISSION_DENIED);
637
        return;
638
    }
639

    
640
    visit_type_str(v, &str, name, &local_err);
641
    if (local_err) {
642
        error_propagate(errp, local_err);
643
        return;
644
    }
645
    if (!*str) {
646
        g_free(str);
647
        error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
648
        return;
649
    }
650
    ret = prop->info->parse(dev, prop, str);
651
    error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
652
    g_free(str);
653
}
654

    
655
PropertyInfo qdev_prop_drive = {
656
    .name  = "drive",
657
    .type  = PROP_TYPE_DRIVE,
658
    .size  = sizeof(BlockDriverState *),
659
    .parse = parse_drive,
660
    .print = print_drive,
661
    .get   = get_generic,
662
    .set   = set_generic,
663
    .free  = free_drive,
664
};
665

    
666
/* --- character device --- */
667

    
668
static int parse_chr(DeviceState *dev, Property *prop, const char *str)
669
{
670
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
671

    
672
    *ptr = qemu_chr_find(str);
673
    if (*ptr == NULL) {
674
        return -ENOENT;
675
    }
676
    if ((*ptr)->avail_connections < 1) {
677
        return -EEXIST;
678
    }
679
    --(*ptr)->avail_connections;
680
    return 0;
681
}
682

    
683
static void free_chr(DeviceState *dev, Property *prop)
684
{
685
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
686

    
687
    if (*ptr) {
688
        qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
689
    }
690
}
691

    
692

    
693
static int print_chr(DeviceState *dev, Property *prop, char *dest, size_t len)
694
{
695
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
696

    
697
    if (*ptr && (*ptr)->label) {
698
        return snprintf(dest, len, "%s", (*ptr)->label);
699
    } else {
700
        return snprintf(dest, len, "<null>");
701
    }
702
}
703

    
704
PropertyInfo qdev_prop_chr = {
705
    .name  = "chr",
706
    .type  = PROP_TYPE_CHR,
707
    .size  = sizeof(CharDriverState*),
708
    .parse = parse_chr,
709
    .print = print_chr,
710
    .get   = get_generic,
711
    .set   = set_generic,
712
    .free  = free_chr,
713
};
714

    
715
/* --- netdev device --- */
716

    
717
static int parse_netdev(DeviceState *dev, Property *prop, const char *str)
718
{
719
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
720

    
721
    *ptr = qemu_find_netdev(str);
722
    if (*ptr == NULL)
723
        return -ENOENT;
724
    if ((*ptr)->peer) {
725
        return -EEXIST;
726
    }
727
    return 0;
728
}
729

    
730
static int print_netdev(DeviceState *dev, Property *prop, char *dest, size_t len)
731
{
732
    VLANClientState **ptr = qdev_get_prop_ptr(dev, prop);
733

    
734
    if (*ptr && (*ptr)->name) {
735
        return snprintf(dest, len, "%s", (*ptr)->name);
736
    } else {
737
        return snprintf(dest, len, "<null>");
738
    }
739
}
740

    
741
PropertyInfo qdev_prop_netdev = {
742
    .name  = "netdev",
743
    .type  = PROP_TYPE_NETDEV,
744
    .size  = sizeof(VLANClientState*),
745
    .parse = parse_netdev,
746
    .print = print_netdev,
747
    .get   = get_generic,
748
    .set   = set_generic,
749
};
750

    
751
/* --- vlan --- */
752

    
753
static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
754
{
755
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
756
    int id;
757

    
758
    if (sscanf(str, "%d", &id) != 1)
759
        return -EINVAL;
760
    *ptr = qemu_find_vlan(id, 1);
761
    if (*ptr == NULL)
762
        return -ENOENT;
763
    return 0;
764
}
765

    
766
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
767
{
768
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
769

    
770
    if (*ptr) {
771
        return snprintf(dest, len, "%d", (*ptr)->id);
772
    } else {
773
        return snprintf(dest, len, "<null>");
774
    }
775
}
776

    
777
static void get_vlan(DeviceState *dev, Visitor *v, void *opaque,
778
                     const char *name, Error **errp)
779
{
780
    Property *prop = opaque;
781
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
782
    int64_t id;
783

    
784
    id = *ptr ? (*ptr)->id : -1;
785
    visit_type_int(v, &id, name, errp);
786
}
787

    
788
static void set_vlan(DeviceState *dev, Visitor *v, void *opaque,
789
                     const char *name, Error **errp)
790
{
791
    Property *prop = opaque;
792
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
793
    Error *local_err = NULL;
794
    int64_t id;
795
    VLANState *vlan;
796

    
797
    if (dev->state != DEV_STATE_CREATED) {
798
        error_set(errp, QERR_PERMISSION_DENIED);
799
        return;
800
    }
801

    
802
    visit_type_int(v, &id, name, &local_err);
803
    if (local_err) {
804
        error_propagate(errp, local_err);
805
        return;
806
    }
807
    if (id == -1) {
808
        *ptr = NULL;
809
        return;
810
    }
811
    vlan = qemu_find_vlan(id, 1);
812
    if (!vlan) {
813
        error_set(errp, QERR_INVALID_PARAMETER_VALUE,
814
                  name, prop->info->name);
815
        return;
816
    }
817
    *ptr = vlan;
818
}
819

    
820
PropertyInfo qdev_prop_vlan = {
821
    .name  = "vlan",
822
    .type  = PROP_TYPE_VLAN,
823
    .size  = sizeof(VLANClientState*),
824
    .parse = parse_vlan,
825
    .print = print_vlan,
826
    .get   = get_vlan,
827
    .set   = set_vlan,
828
};
829

    
830
/* --- pointer --- */
831

    
832
/* Not a proper property, just for dirty hacks.  TODO Remove it!  */
833
PropertyInfo qdev_prop_ptr = {
834
    .name  = "ptr",
835
    .type  = PROP_TYPE_PTR,
836
    .size  = sizeof(void*),
837
};
838

    
839
/* --- mac address --- */
840

    
841
/*
842
 * accepted syntax versions:
843
 *   01:02:03:04:05:06
844
 *   01-02-03-04-05-06
845
 */
846
static int parse_mac(DeviceState *dev, Property *prop, const char *str)
847
{
848
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
849
    int i, pos;
850
    char *p;
851

    
852
    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
853
        if (!qemu_isxdigit(str[pos]))
854
            return -EINVAL;
855
        if (!qemu_isxdigit(str[pos+1]))
856
            return -EINVAL;
857
        if (i == 5) {
858
            if (str[pos+2] != '\0')
859
                return -EINVAL;
860
        } else {
861
            if (str[pos+2] != ':' && str[pos+2] != '-')
862
                return -EINVAL;
863
        }
864
        mac->a[i] = strtol(str+pos, &p, 16);
865
    }
866
    return 0;
867
}
868

    
869
static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
870
{
871
    MACAddr *mac = qdev_get_prop_ptr(dev, prop);
872

    
873
    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
874
                    mac->a[0], mac->a[1], mac->a[2],
875
                    mac->a[3], mac->a[4], mac->a[5]);
876
}
877

    
878
PropertyInfo qdev_prop_macaddr = {
879
    .name  = "macaddr",
880
    .type  = PROP_TYPE_MACADDR,
881
    .size  = sizeof(MACAddr),
882
    .parse = parse_mac,
883
    .print = print_mac,
884
    .get   = get_generic,
885
    .set   = set_generic,
886
};
887

    
888

    
889
/* --- lost tick policy --- */
890

    
891
static const struct {
892
    const char *name;
893
    LostTickPolicy code;
894
} lost_tick_policy_table[] = {
895
    { .name = "discard", .code = LOST_TICK_DISCARD },
896
    { .name = "delay", .code = LOST_TICK_DELAY },
897
    { .name = "merge", .code = LOST_TICK_MERGE },
898
    { .name = "slew", .code = LOST_TICK_SLEW },
899
};
900

    
901
static int parse_lost_tick_policy(DeviceState *dev, Property *prop,
902
                                  const char *str)
903
{
904
    LostTickPolicy *ptr = qdev_get_prop_ptr(dev, prop);
905
    int i;
906

    
907
    for (i = 0; i < ARRAY_SIZE(lost_tick_policy_table); i++) {
908
        if (!strcasecmp(str, lost_tick_policy_table[i].name)) {
909
            *ptr = lost_tick_policy_table[i].code;
910
            break;
911
        }
912
    }
913
    if (i == ARRAY_SIZE(lost_tick_policy_table)) {
914
        return -EINVAL;
915
    }
916
    return 0;
917
}
918

    
919
static int print_lost_tick_policy(DeviceState *dev, Property *prop, char *dest,
920
                                  size_t len)
921
{
922
    LostTickPolicy *ptr = qdev_get_prop_ptr(dev, prop);
923

    
924
    return snprintf(dest, len, "%s", lost_tick_policy_table[*ptr].name);
925
}
926

    
927
PropertyInfo qdev_prop_losttickpolicy = {
928
    .name  = "lost_tick_policy",
929
    .type  = PROP_TYPE_LOSTTICKPOLICY,
930
    .size  = sizeof(LostTickPolicy),
931
    .parse = parse_lost_tick_policy,
932
    .print = print_lost_tick_policy,
933
    .get   = get_generic,
934
    .set   = set_generic,
935
};
936

    
937
/* --- pci address --- */
938

    
939
/*
940
 * bus-local address, i.e. "$slot" or "$slot.$fn"
941
 */
942
static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
943
{
944
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
945
    unsigned int slot, fn, n;
946

    
947
    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
948
        fn = 0;
949
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
950
            return -EINVAL;
951
        }
952
    }
953
    if (str[n] != '\0')
954
        return -EINVAL;
955
    if (fn > 7)
956
        return -EINVAL;
957
    if (slot > 31)
958
        return -EINVAL;
959
    *ptr = slot << 3 | fn;
960
    return 0;
961
}
962

    
963
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
964
{
965
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
966

    
967
    if (*ptr == -1) {
968
        return snprintf(dest, len, "<unset>");
969
    } else {
970
        return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
971
    }
972
}
973

    
974
static void get_pci_devfn(DeviceState *dev, Visitor *v, void *opaque,
975
                          const char *name, Error **errp)
976
{
977
    Property *prop = opaque;
978
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
979
    char buffer[32];
980
    char *p = buffer;
981

    
982
    buffer[0] = 0;
983
    if (*ptr != -1) {
984
        snprintf(buffer, sizeof(buffer), "%02x.%x", *ptr >> 3, *ptr & 7);
985
    }
986
    visit_type_str(v, &p, name, errp);
987
}
988

    
989
PropertyInfo qdev_prop_pci_devfn = {
990
    .name  = "pci-devfn",
991
    .type  = PROP_TYPE_UINT32,
992
    .size  = sizeof(uint32_t),
993
    .parse = parse_pci_devfn,
994
    .print = print_pci_devfn,
995
    .get   = get_pci_devfn,
996
    .set   = set_generic,
997
};
998

    
999
/* --- public helpers --- */
1000

    
1001
static Property *qdev_prop_walk(Property *props, const char *name)
1002
{
1003
    if (!props)
1004
        return NULL;
1005
    while (props->name) {
1006
        if (strcmp(props->name, name) == 0)
1007
            return props;
1008
        props++;
1009
    }
1010
    return NULL;
1011
}
1012

    
1013
static Property *qdev_prop_find(DeviceState *dev, const char *name)
1014
{
1015
    Property *prop;
1016

    
1017
    /* device properties */
1018
    prop = qdev_prop_walk(qdev_get_info(dev)->props, name);
1019
    if (prop)
1020
        return prop;
1021

    
1022
    /* bus properties */
1023
    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
1024
    if (prop)
1025
        return prop;
1026

    
1027
    return NULL;
1028
}
1029

    
1030
int qdev_prop_exists(DeviceState *dev, const char *name)
1031
{
1032
    return qdev_prop_find(dev, name) ? true : false;
1033
}
1034

    
1035
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1036
                                    Property *prop, const char *value)
1037
{
1038
    switch (ret) {
1039
    case -EEXIST:
1040
        error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
1041
                  object_get_typename(OBJECT(dev)), prop->name, value);
1042
        break;
1043
    default:
1044
    case -EINVAL:
1045
        error_set(errp, QERR_PROPERTY_VALUE_BAD,
1046
                  object_get_typename(OBJECT(dev)), prop->name, value);
1047
        break;
1048
    case -ENOENT:
1049
        error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
1050
                  object_get_typename(OBJECT(dev)), prop->name, value);
1051
        break;
1052
    case 0:
1053
        break;
1054
    }
1055
}
1056

    
1057
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1058
{
1059
    Property *prop;
1060
    int ret;
1061

    
1062
    prop = qdev_prop_find(dev, name);
1063
    /*
1064
     * TODO Properties without a parse method are just for dirty
1065
     * hacks.  qdev_prop_ptr is the only such PropertyInfo.  It's
1066
     * marked for removal.  The test !prop->info->parse should be
1067
     * removed along with it.
1068
     */
1069
    if (!prop || !prop->info->parse) {
1070
        qerror_report(QERR_PROPERTY_NOT_FOUND, object_get_typename(OBJECT(dev)), name);
1071
        return -1;
1072
    }
1073
    ret = prop->info->parse(dev, prop, value);
1074
    if (ret < 0) {
1075
        Error *err;
1076
        error_set_from_qdev_prop_error(&err, ret, dev, prop, value);
1077
        qerror_report_err(err);
1078
        error_free(err);
1079
        return -1;
1080
    }
1081
    return 0;
1082
}
1083

    
1084
void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
1085
{
1086
    Property *prop;
1087

    
1088
    prop = qdev_prop_find(dev, name);
1089
    if (!prop) {
1090
        fprintf(stderr, "%s: property \"%s.%s\" not found\n",
1091
                __FUNCTION__, object_get_typename(OBJECT(dev)), name);
1092
        abort();
1093
    }
1094
    if (prop->info->type != type) {
1095
        fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
1096
                __FUNCTION__, object_get_typename(OBJECT(dev)), name);
1097
        abort();
1098
    }
1099
    qdev_prop_cpy(dev, prop, src);
1100
}
1101

    
1102
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1103
{
1104
    qdev_prop_set(dev, name, &value, PROP_TYPE_BIT);
1105
}
1106

    
1107
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1108
{
1109
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT8);
1110
}
1111

    
1112
void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1113
{
1114
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
1115
}
1116

    
1117
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1118
{
1119
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
1120
}
1121

    
1122
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1123
{
1124
    qdev_prop_set(dev, name, &value, PROP_TYPE_INT32);
1125
}
1126

    
1127
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1128
{
1129
    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
1130
}
1131

    
1132
void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
1133
{
1134
    qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
1135
}
1136

    
1137
int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
1138
{
1139
    int res;
1140

    
1141
    res = bdrv_attach_dev(value, dev);
1142
    if (res < 0) {
1143
        error_report("Can't attach drive %s to %s.%s: %s",
1144
                     bdrv_get_device_name(value),
1145
                     dev->id ? dev->id : object_get_typename(OBJECT(dev)),
1146
                     name, strerror(-res));
1147
        return -1;
1148
    }
1149
    qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
1150
    return 0;
1151
}
1152

    
1153
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1154
{
1155
    if (qdev_prop_set_drive(dev, name, value) < 0) {
1156
        exit(1);
1157
    }
1158
}
1159
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1160
{
1161
    qdev_prop_set(dev, name, &value, PROP_TYPE_CHR);
1162
}
1163

    
1164
void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value)
1165
{
1166
    qdev_prop_set(dev, name, &value, PROP_TYPE_NETDEV);
1167
}
1168

    
1169
void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value)
1170
{
1171
    qdev_prop_set(dev, name, &value, PROP_TYPE_VLAN);
1172
}
1173

    
1174
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1175
{
1176
    qdev_prop_set(dev, name, value, PROP_TYPE_MACADDR);
1177
}
1178

    
1179
void qdev_prop_set_losttickpolicy(DeviceState *dev, const char *name,
1180
                                  LostTickPolicy *value)
1181
{
1182
    qdev_prop_set(dev, name, value, PROP_TYPE_LOSTTICKPOLICY);
1183
}
1184

    
1185
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1186
{
1187
    qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
1188
}
1189

    
1190
void qdev_prop_set_defaults(DeviceState *dev, Property *props)
1191
{
1192
    if (!props)
1193
        return;
1194
    while (props->name) {
1195
        if (props->defval) {
1196
            qdev_prop_cpy(dev, props, props->defval);
1197
        }
1198
        props++;
1199
    }
1200
}
1201

    
1202
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
1203

    
1204
static void qdev_prop_register_global(GlobalProperty *prop)
1205
{
1206
    QTAILQ_INSERT_TAIL(&global_props, prop, next);
1207
}
1208

    
1209
void qdev_prop_register_global_list(GlobalProperty *props)
1210
{
1211
    int i;
1212

    
1213
    for (i = 0; props[i].driver != NULL; i++) {
1214
        qdev_prop_register_global(props+i);
1215
    }
1216
}
1217

    
1218
void qdev_prop_set_globals(DeviceState *dev)
1219
{
1220
    GlobalProperty *prop;
1221

    
1222
    QTAILQ_FOREACH(prop, &global_props, next) {
1223
        if (strcmp(object_get_typename(OBJECT(dev)), prop->driver) != 0 &&
1224
            strcmp(qdev_get_info(dev)->bus_info->name, prop->driver) != 0) {
1225
            continue;
1226
        }
1227
        if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
1228
            exit(1);
1229
        }
1230
    }
1231
}
1232

    
1233
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1234
{
1235
    GlobalProperty *g;
1236

    
1237
    g = g_malloc0(sizeof(*g));
1238
    g->driver   = qemu_opt_get(opts, "driver");
1239
    g->property = qemu_opt_get(opts, "property");
1240
    g->value    = qemu_opt_get(opts, "value");
1241
    qdev_prop_register_global(g);
1242
    return 0;
1243
}
1244

    
1245
void qemu_add_globals(void)
1246
{
1247
    qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
1248
}