qemu/hw/qdev-properties.c
<<
>>
Prefs
   1#include "qdev.h"
   2
   3void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
   4{
   5    void *ptr = dev;
   6    ptr += prop->offset;
   7    return ptr;
   8}
   9
  10/* --- 16bit integer --- */
  11
  12static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
  13{
  14    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
  15    const char *fmt;
  16
  17    /* accept both hex and decimal */
  18    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx16 : "%" PRIu16;
  19    if (sscanf(str, fmt, ptr) != 1)
  20        return -1;
  21    return 0;
  22}
  23
  24static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
  25{
  26    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
  27    return snprintf(dest, len, "%" PRIu16, *ptr);
  28}
  29
  30PropertyInfo qdev_prop_uint16 = {
  31    .name  = "uint16",
  32    .type  = PROP_TYPE_UINT16,
  33    .size  = sizeof(uint16_t),
  34    .parse = parse_uint16,
  35    .print = print_uint16,
  36};
  37
  38/* --- 32bit integer --- */
  39
  40static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
  41{
  42    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
  43    const char *fmt;
  44
  45    /* accept both hex and decimal */
  46    fmt = strncasecmp(str, "0x",2) == 0 ? "%" PRIx32 : "%" PRIu32;
  47    if (sscanf(str, fmt, ptr) != 1)
  48        return -1;
  49    return 0;
  50}
  51
  52static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
  53{
  54    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
  55    return snprintf(dest, len, "%" PRIu32, *ptr);
  56}
  57
  58PropertyInfo qdev_prop_uint32 = {
  59    .name  = "uint32",
  60    .type  = PROP_TYPE_UINT32,
  61    .size  = sizeof(uint32_t),
  62    .parse = parse_uint32,
  63    .print = print_uint32,
  64};
  65
  66/* --- 32bit hex value --- */
  67
  68static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
  69{
  70    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
  71
  72    if (sscanf(str, "%" PRIx32, ptr) != 1)
  73        return -1;
  74    return 0;
  75}
  76
  77static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
  78{
  79    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
  80    return snprintf(dest, len, "0x%" PRIx32, *ptr);
  81}
  82
  83PropertyInfo qdev_prop_hex32 = {
  84    .name  = "hex32",
  85    .type  = PROP_TYPE_UINT32,
  86    .size  = sizeof(uint32_t),
  87    .parse = parse_hex32,
  88    .print = print_hex32,
  89};
  90
  91/* --- pointer --- */
  92
  93static int print_ptr(DeviceState *dev, Property *prop, char *dest, size_t len)
  94{
  95    void **ptr = qdev_get_prop_ptr(dev, prop);
  96    return snprintf(dest, len, "<%p>", *ptr);
  97}
  98
  99PropertyInfo qdev_prop_ptr = {
 100    .name  = "ptr",
 101    .type  = PROP_TYPE_PTR,
 102    .size  = sizeof(void*),
 103    .print = print_ptr,
 104};
 105
 106/* --- mac address --- */
 107
 108/*
 109 * accepted syntax versions:
 110 *   01:02:03:04:05:06
 111 *   01-02-03-04-05-06
 112 */
 113static int parse_mac(DeviceState *dev, Property *prop, const char *str)
 114{
 115    uint8_t *mac = qdev_get_prop_ptr(dev, prop);
 116    int i, pos;
 117    char *p;
 118
 119    for (i = 0, pos = 0; i < 6; i++, pos += 3) {
 120        if (!qemu_isxdigit(str[pos]))
 121            return -1;
 122        if (!qemu_isxdigit(str[pos+1]))
 123            return -1;
 124        if (i == 5 && str[pos+2] != '\0')
 125            return -1;
 126        if (str[pos+2] != ':' && str[pos+2] != '-')
 127            return -1;
 128        mac[i] = strtol(str+pos, &p, 16);
 129    }
 130    return 0;
 131}
 132
 133static int print_mac(DeviceState *dev, Property *prop, char *dest, size_t len)
 134{
 135    uint8_t *mac = qdev_get_prop_ptr(dev, prop);
 136    return snprintf(dest, len, "%02x:%02x:%02x:%02x:%02x:%02x",
 137                    mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 138}
 139
 140PropertyInfo qdev_prop_macaddr = {
 141    .name  = "mac-addr",
 142    .type  = PROP_TYPE_MACADDR,
 143    .size  = 6,
 144    .parse = parse_mac,
 145    .print = print_mac,
 146};
 147
 148/* --- public helpers --- */
 149
 150static Property *qdev_prop_walk(Property *props, const char *name)
 151{
 152    if (!props)
 153        return NULL;
 154    while (props->name) {
 155        if (strcmp(props->name, name) == 0)
 156            return props;
 157        props++;
 158    }
 159    return NULL;
 160}
 161
 162static Property *qdev_prop_find(DeviceState *dev, const char *name)
 163{
 164    Property *prop;
 165
 166    /* device properties */
 167    prop = qdev_prop_walk(dev->info->props, name);
 168    if (prop)
 169        return prop;
 170
 171    /* bus properties */
 172    prop = qdev_prop_walk(dev->parent_bus->info->props, name);
 173    if (prop)
 174        return prop;
 175
 176    return NULL;
 177}
 178
 179int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
 180{
 181    Property *prop;
 182
 183    prop = qdev_prop_find(dev, name);
 184    if (!prop) {
 185        fprintf(stderr, "property \"%s.%s\" not found\n",
 186                dev->info->name, name);
 187        return -1;
 188    }
 189    if (!prop->info->parse) {
 190        fprintf(stderr, "property \"%s.%s\" has no parser\n",
 191                dev->info->name, name);
 192        return -1;
 193    }
 194    return prop->info->parse(dev, prop, value);
 195}
 196
 197void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)
 198{
 199    Property *prop;
 200    void *dst;
 201
 202    prop = qdev_prop_find(dev, name);
 203    if (!prop) {
 204        fprintf(stderr, "%s: property \"%s.%s\" not found\n",
 205                __FUNCTION__, dev->info->name, name);
 206        abort();
 207    }
 208    if (prop->info->type != type) {
 209        fprintf(stderr, "%s: property \"%s.%s\" type mismatch\n",
 210                __FUNCTION__, dev->info->name, name);
 211        abort();
 212    }
 213    dst = qdev_get_prop_ptr(dev, prop);
 214    memcpy(dst, src, prop->info->size);
 215}
 216
 217void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
 218{
 219    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT16);
 220}
 221
 222void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
 223{
 224    qdev_prop_set(dev, name, &value, PROP_TYPE_UINT32);
 225}
 226
 227void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
 228{
 229    qdev_prop_set(dev, name, &value, PROP_TYPE_PTR);
 230}
 231
 232void qdev_prop_set_defaults(DeviceState *dev, Property *props)
 233{
 234    char *dst;
 235
 236    if (!props)
 237        return;
 238    while (props->name) {
 239        if (props->defval) {
 240            dst = qdev_get_prop_ptr(dev, props);
 241            memcpy(dst, props->defval, props->info->size);
 242        }
 243        props++;
 244    }
 245}
 246
 247static CompatProperty *compat_props;
 248
 249void qdev_prop_register_compat(CompatProperty *props)
 250{
 251    compat_props = props;
 252}
 253
 254void qdev_prop_set_compat(DeviceState *dev)
 255{
 256    CompatProperty *prop;
 257
 258    if (!compat_props) {
 259        return;
 260    }
 261    for (prop = compat_props; prop->driver != NULL; prop++) {
 262        if (strcmp(dev->info->name, prop->driver) != 0) {
 263            continue;
 264        }
 265        if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
 266            abort();
 267        }
 268    }
 269}
 270