@@ -138,7 +138,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_dom_suspend.o libxl_dom_save.o libxl_usb.o \
libxl_vtpm.o libxl_nic.o libxl_disk.o libxl_console.o \
libxl_cpupool.o libxl_mem.o libxl_sched.o libxl_tmem.o \
- libxl_domain.o \
+ libxl_domain.o libxl_vdispl.o \
$(LIBXL_OBJS-y)
LIBXL_OBJS += libxl_genid.o
LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
@@ -1833,6 +1833,27 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
int libxl_device_vtpm_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_vtpm *vtpm, libxl_vtpminfo *vtpminfo);
+/* Virtual displays */
+int libxl_device_vdispl_add(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_vdispl *displ,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vdispl_remove(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_vdispl *vdispl,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vdispl_destroy(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_vdispl *vdispl,
+ const libxl_asyncop_how *ao_how)
+ LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vdispl *libxl_device_vdispl_list(libxl_ctx *ctx, uint32_t domid,
+ int *num);
+void libxl_device_vdispl_list_free(libxl_device_vdispl* list, int num);
+int libxl_device_vdispl_getinfo(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_vdispl *vdispl,
+ libxl_vdisplinfo *vdisplinfo);
+
/* Keyboard */
int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb,
const libxl_asyncop_how *ao_how)
@@ -1422,6 +1422,8 @@ out:
#define libxl_device_dtdev_list NULL
#define libxl_device_dtdev_compare NULL
+#define libxl__device_from_dtdev NULL
+#define libxl__device_dtdev_setdefault NULL
static DEFINE_DEVICE_TYPE_STRUCT(dtdev);
const struct libxl_device_type *device_type_tbl[] = {
@@ -1432,6 +1434,7 @@ const struct libxl_device_type *device_type_tbl[] = {
&libxl__usbdev_devtype,
&libxl__pcidev_devtype,
&libxl__dtdev_devtype,
+ &libxl__vdispl_devtype,
NULL
};
@@ -18,7 +18,7 @@
#include "libxl_internal.h"
-static char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device)
+char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device)
{
char *dom_path = libxl__xs_get_dompath(gc, device->domid);
@@ -1776,6 +1776,182 @@ out:
return AO_CREATE_FAIL(rc);
}
+static int device_add_domain_config(libxl__gc *gc, uint32_t domid,
+ const struct libxl_device_type *dt,
+ void *type)
+{
+ int rc;
+ libxl_domain_config d_config;
+ libxl__domain_userdata_lock *lock = NULL;
+ int *num_dev;
+ int i;
+ void *item = NULL;
+
+ libxl_domain_config_init(&d_config);
+
+ lock = libxl__lock_domain_userdata(gc, domid);
+ if (!lock) {
+ rc = ERROR_LOCK_FAIL; goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ num_dev = libxl__device_type_get_num(dt, &d_config);
+
+ /* Check for existing device */
+ for (i = 0; i < *num_dev; i++) {
+ if (dt->compare(libxl__device_type_get_elem(dt, &d_config, i), type)) {
+ item = libxl__device_type_get_elem(dt, &d_config, i);
+ }
+ }
+
+ if (!item) {
+ void **devs= libxl__device_type_get_ptr(dt, &d_config);
+ *devs = libxl__realloc(NOGC, *devs,
+ dt->dev_elem_size * (*num_dev + 1));
+ item = libxl__device_type_get_elem(dt, &d_config, *num_dev);
+ (*num_dev)++;
+ } else {
+ dt->dispose(item);
+ }
+
+ dt->init(item);
+ dt->copy(CTX, item, type);
+
+ rc = libxl__dm_check_start(gc, &d_config, domid);
+ if (rc) goto out;
+
+ rc = libxl__set_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ rc = 0;
+
+out:
+ if (lock) libxl__unlock_domain_userdata(lock);
+ libxl_domain_config_dispose(&d_config);
+ return rc;
+}
+
+void libxl__device_add(libxl__egc *egc, uint32_t domid,
+ const struct libxl_device_type *dt, void *type,
+ libxl__ao_device *aodev)
+{
+ STATE_AO_GC(aodev->ao);
+ libxl__device *device;
+ int rc;
+
+ rc = dt->set_default(gc, domid, type);
+ if (rc) goto out;
+
+ GCNEW(device);
+ rc = dt->to_device(gc, domid, type, device);
+ if ( rc != 0 ) goto out;
+
+ rc = libxl__device_exists(gc, XBT_NULL, device);
+ if (rc < 0) goto out;
+ if (rc == 1) { /* already exists in xenstore */
+ LOGD(ERROR, domid, "device already exists in xenstore");
+ aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+ rc = ERROR_DEVICE_EXISTS;
+ goto out;
+ }
+
+ if (aodev->update_json) {
+ rc = device_add_domain_config(gc, domid, dt, type);
+ if (rc) goto out;
+ }
+
+ if (dt->set_xenstore_config) {
+ rc = dt->set_xenstore_config(gc, domid, type);
+ if (rc) goto out;
+ }
+
+ aodev->dev = device;
+ aodev->action = LIBXL__DEVICE_ACTION_ADD;
+ libxl__wait_device_connection(egc, aodev);
+
+ rc = 0;
+
+out:
+ aodev->rc = rc;
+ if(rc) aodev->callback(egc, aodev);
+ return;
+}
+
+void* libxl__device_list(const struct libxl_device_type *dt,
+ libxl_ctx *ctx, uint32_t domid, int *num)
+{
+ GC_INIT(ctx);
+
+ void *r = NULL;
+ void *list = NULL;
+ void *item = NULL;
+ char *libxl_path;
+ char *be_path;
+ char** dir = NULL;
+ unsigned int ndirs = 0;
+ int rc;
+
+ *num = 0;
+
+ libxl_path = GCSPRINTF("%s/device/%s",
+ libxl__xs_libxl_path(gc, domid), dt->type);
+
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
+
+ if (dir && ndirs) {
+ list = malloc(dt->dev_elem_size * ndirs);
+ void *end = (uint8_t*)list + ndirs * dt->dev_elem_size;
+ item = list;
+
+ while(item < end) {
+ be_path = libxl__xs_read(gc, XBT_NULL,
+ GCSPRINTF("%s/%s/backend",
+ libxl_path, *dir));
+
+ dt->init(item);
+
+ rc = dt->from_xenstore(gc, be_path, atoi(*dir), item);
+ if (rc) goto out;
+
+ item = (uint8_t*)item + dt->dev_elem_size;
+ ++dir;
+ }
+ }
+
+ *num = ndirs;
+ r = list;
+ list = NULL;
+
+out:
+
+ if (list) {
+ *num = 0;
+ while(item >= list) {
+ item = (uint8_t*)item - dt->dev_elem_size;
+ dt->dispose(item);
+ }
+ free(list);
+ }
+
+ GC_FREE;
+
+ return r;
+}
+
+void libxl__device_list_free(const struct libxl_device_type *dt,
+ void *list, int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ dt->dispose((uint8_t*)list + i * dt->dev_elem_size);
+ }
+
+ free(list);
+}
+
/*
* Local variables:
* mode: C
@@ -1204,6 +1204,7 @@ _hidden int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
libxl__device *device);
_hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents);
+_hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device);
_hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device);
_hidden char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
@@ -3473,11 +3474,17 @@ struct libxl_device_type {
void (*add)(libxl__egc *, libxl__ao *, uint32_t, libxl_domain_config *,
libxl__multidev *);
void *(*list)(libxl_ctx *, uint32_t, int *);
+ int (*set_default)(libxl__gc *, uint32_t, void *);
+ int (*to_device)(libxl__gc *, uint32_t, void *, libxl__device *);
+ void (*init)(void *);
+ void (*copy)(libxl_ctx *, void *, void *);
void (*dispose)(void *);
int (*compare)(void *, void *);
void (*merge)(libxl_ctx *, void *, void *);
int (*dm_needed)(void *, unsigned);
void (*update_config)(libxl__gc *, void *, void *);
+ int (*from_xenstore)(libxl__gc *, const char *, uint32_t, void *);
+ int (*set_xenstore_config)(libxl__gc *, uint32_t, void *);
};
#define DEFINE_DEVICE_TYPE_STRUCT_X(name, sname, ...) \
@@ -3489,6 +3496,14 @@ struct libxl_device_type {
.add = libxl__add_ ## name ## s, \
.list = (void *(*)(libxl_ctx *, uint32_t, int *)) \
libxl_device_ ## sname ## _list, \
+ .set_default = (int (*)(libxl__gc *, uint32_t, void *)) \
+ libxl__device_ ## sname ## _setdefault, \
+ .to_device = (int (*)(libxl__gc *, uint32_t, \
+ void *, libxl__device *)) \
+ libxl__device_from_ ## name, \
+ .init = (void (*)(void *))libxl_device_ ## sname ## _init, \
+ .copy = (void (*)(libxl_ctx *, void *, void *)) \
+ libxl_device_ ## sname ## _copy, \
.dispose = (void (*)(void *))libxl_device_ ## sname ## _dispose, \
.compare = (int (*)(void *, void *)) \
libxl_device_ ## sname ## _compare, \
@@ -3523,6 +3538,7 @@ extern const struct libxl_device_type libxl__vtpm_devtype;
extern const struct libxl_device_type libxl__usbctrl_devtype;
extern const struct libxl_device_type libxl__usbdev_devtype;
extern const struct libxl_device_type libxl__pcidev_devtype;
+extern const struct libxl_device_type libxl__vdispl_devtype;
extern const struct libxl_device_type *device_type_tbl[];
@@ -4339,6 +4355,14 @@ static inline bool libxl__acpi_defbool_val(const libxl_domain_build_info *b_info
return libxl_defbool_val(b_info->acpi) &&
libxl_defbool_val(b_info->u.hvm.acpi);
}
+
+void libxl__device_add(libxl__egc *egc, uint32_t domid,
+ const struct libxl_device_type *dt, void *type,
+ libxl__ao_device *aodev);
+void* libxl__device_list(const struct libxl_device_type *dt,
+ libxl_ctx *ctx, uint32_t domid, int *num);
+void libxl__device_list_free(const struct libxl_device_type *dt,
+ void *list, int num);
#endif
/*
@@ -738,7 +738,21 @@ libxl_device_vtpm = Struct("device_vtpm", [
("backend_domname", string),
("devid", libxl_devid),
("uuid", libxl_uuid),
-])
+ ])
+
+libxl_connector_param = Struct("connector_param", [
+ ("id", string),
+ ("width", uint32),
+ ("height", uint32)
+ ])
+
+libxl_device_vdispl = Struct("device_vdispl", [
+ ("backend_domid", libxl_domid),
+ ("backend_domname", string),
+ ("devid", libxl_devid),
+ ("be_alloc", bool),
+ ("connectors", Array(libxl_connector_param, "num_connectors"))
+ ])
libxl_device_channel = Struct("device_channel", [
("backend_domid", libxl_domid),
@@ -750,7 +764,7 @@ libxl_device_channel = Struct("device_channel", [
("pty", None),
("socket", Struct(None, [("path", string)])),
])),
-])
+ ])
libxl_domain_config = Struct("domain_config", [
("c_info", libxl_domain_create_info),
@@ -764,6 +778,7 @@ libxl_domain_config = Struct("domain_config", [
("vfbs", Array(libxl_device_vfb, "num_vfbs")),
("vkbs", Array(libxl_device_vkb, "num_vkbs")),
("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
+ ("vdispls", Array(libxl_device_vdispl, "num_vdispls")),
# a channel manifests as a console with a name,
# see docs/misc/channels.txt
("channels", Array(libxl_device_channel, "num_channels")),
@@ -860,6 +875,27 @@ libxl_physinfo = Struct("physinfo", [
("cap_hvm_directio", bool),
], dir=DIR_OUT)
+libxl_connectorinfo = Struct("connectorinfo", [
+ ("id", string),
+ ("width", uint32),
+ ("height", uint32),
+ ("req_evtch", integer),
+ ("req_rref", integer),
+ ("evt_evtch", integer),
+ ("evt_rref", integer),
+ ], dir=DIR_OUT)
+
+libxl_vdisplinfo = Struct("vdisplinfo", [
+ ("backend", string),
+ ("backend_id", uint32),
+ ("frontend", string),
+ ("frontend_id", uint32),
+ ("devid", libxl_devid),
+ ("state", integer),
+ ("be_alloc", bool),
+ ("connectors", Array(libxl_connectorinfo, "num_connectors"))
+ ], dir=DIR_OUT)
+
# NUMA node characteristics: size and free are how much memory it has, and how
# much of it is free, respectively. dists is an array of distances from this
# node to each other node.
@@ -25,6 +25,7 @@ libxl__device_kind = Enumeration("device_kind", [
(8, "VTPM"),
(9, "VUSB"),
(10, "QUSB"),
+ (11, "VDISPL")
])
libxl__console_backend = Enumeration("console_backend", [
@@ -1968,6 +1968,8 @@ void libxl_device_usbdev_list_free(libxl_device_usbdev *list, int nr)
DEFINE_DEVICE_TYPE_STRUCT(usbctrl,
.dm_needed = libxl_device_usbctrl_dm_needed
);
+
+#define libxl__device_from_usbdev NULL
DEFINE_DEVICE_TYPE_STRUCT(usbdev);
/*
@@ -78,6 +78,10 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_vtpm *vtpm);
int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_usbctrl *usbctrl);
+
+int libxl_devid_to_device_vdispl(libxl_ctx *ctx, uint32_t domid,
+ int devid, libxl_device_vdispl *vdispl);
+
int libxl_ctrlport_to_device_usbdev(libxl_ctx *ctx, uint32_t domid,
int ctrl, int port,
libxl_device_usbdev *usbdev);
new file mode 100644
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2016 EPAM Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h"
+
+#include "libxl_internal.h"
+
+static int libxl__device_vdispl_setdefault(libxl__gc *gc, uint32_t domid,
+ libxl_device_vdispl *vdispl)
+{
+ int rc;
+
+ rc = libxl__resolve_domid(gc, vdispl->backend_domname,
+ &vdispl->backend_domid);
+
+ if (vdispl->devid == -1) {
+ vdispl->devid = libxl__device_nextid(gc, domid, "vdispl");
+ }
+
+ return rc;
+}
+
+static int libxl__from_xenstore_vdispl(libxl__gc *gc, const char *be_path,
+ uint32_t devid,
+ libxl_device_vdispl *vdispl)
+{
+ vdispl->devid = devid;
+
+ return libxl__backendpath_parse_domid(gc, be_path, &vdispl->backend_domid);
+}
+
+static int libxl__device_from_vdispl(libxl__gc *gc, uint32_t domid,
+ libxl_device_vdispl *vdispl,
+ libxl__device *device)
+{
+ device->backend_devid = vdispl->devid;
+ device->backend_domid = vdispl->backend_domid;
+ device->backend_kind = LIBXL__DEVICE_KIND_VDISPL;
+ device->devid = vdispl->devid;
+ device->domid = domid;
+ device->kind = LIBXL__DEVICE_KIND_VDISPL;
+
+ return 0;
+}
+
+static int libxl__set_xenstore_connectors(libxl__gc *gc, xs_transaction_t t,
+ libxl__device *device,
+ libxl_device_vdispl *vdispl)
+{
+ struct xs_permissions perms[2];
+ char *frontend_path = NULL;
+ flexarray_t *connector;
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ int i;
+ int rc;
+
+ frontend_path = libxl__device_frontend_path(gc, device);
+
+ perms[0].id = device->domid;
+ perms[0].perms = XS_PERM_NONE;
+ perms[1].id = device->backend_domid;
+ perms[1].perms = XS_PERM_READ;
+
+ connector = flexarray_make(gc, 2, 1);
+ flexarray_append(connector, "resolution");
+ flexarray_append(connector, "");
+ flexarray_append(connector, "id");
+ flexarray_append(connector, "");
+
+ for (i = 0; i < vdispl->num_connectors; i++) {
+ char *connector_path = GCSPRINTF("%s/%d", frontend_path, i);
+
+ if (!xs_mkdir(ctx->xsh, t, connector_path)) {
+ rc = ERROR_FAIL; goto out;
+ }
+
+ if (!xs_set_permissions(ctx->xsh, t, connector_path, perms,
+ ARRAY_SIZE(perms))) {
+ rc = ERROR_FAIL; goto out;
+ }
+
+ flexarray_set(connector, 1,
+ GCSPRINTF("%dx%d", vdispl->connectors[i].width,
+ vdispl->connectors[i].height));
+ flexarray_set(connector, 3, vdispl->connectors[i].id);
+
+ rc = libxl__xs_writev(gc, t, connector_path,
+ libxl__xs_kvs_of_flexarray(gc, connector));
+ if (rc) goto out;
+ }
+
+ rc = 0;
+
+out:
+ return rc;
+}
+
+static int libxl__set_xenstore_vdispl(libxl__gc *gc, uint32_t domid,
+ libxl_device_vdispl *vdispl)
+{
+ flexarray_t *front;
+ flexarray_t *back;
+
+ front = flexarray_make(gc, 16, 1);
+ back = flexarray_make(gc, 16, 1);
+
+ flexarray_append(back, "frontend-id");
+ flexarray_append(back, GCSPRINTF("%d", domid));
+ flexarray_append(back, "online");
+ flexarray_append(back, "1");
+ flexarray_append(back, "state");
+ flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
+ flexarray_append(back, "handle");
+ flexarray_append(back, GCSPRINTF("%d", vdispl->devid));
+
+ flexarray_append(front, "backend-id");
+ flexarray_append(front, GCSPRINTF("%d", vdispl->backend_domid));
+ flexarray_append(front, "state");
+ flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
+ flexarray_append(front, "handle");
+ flexarray_append(front, GCSPRINTF("%d", vdispl->devid));
+ flexarray_append(front, "be_alloc");
+ flexarray_append(front, GCSPRINTF("%d", vdispl->be_alloc));
+
+ libxl__device *device;
+ xs_transaction_t t = XBT_NULL;
+ int rc;
+
+ GCNEW(device);
+
+ rc = libxl__device_from_vdispl(gc, domid, vdispl, device);
+ if (rc) goto out;
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+
+ rc = libxl__device_generic_add(gc, t, device,
+ libxl__xs_kvs_of_flexarray(gc, back),
+ libxl__xs_kvs_of_flexarray(gc, front),
+ NULL);
+ if (rc) goto out;
+
+ rc = libxl__set_xenstore_connectors(gc, t, device, vdispl);
+ if (rc) goto out;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc < 0) goto out;
+ }
+
+ rc = 0;
+
+out:
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
+}
+
+static void libxl__update_config_vdispl(libxl__gc *gc,
+ libxl_device_vdispl *dst,
+ libxl_device_vdispl *src)
+{
+ dst->devid = src->devid;
+ dst->be_alloc = src->be_alloc;
+}
+
+static int libxl_device_vdispl_compare(libxl_device_vdispl *d1,
+ libxl_device_vdispl *d2)
+{
+ return COMPARE_DEVID(d1, d2);
+}
+
+static void libxl__device_vdispl_add(libxl__egc *egc, uint32_t domid,
+ libxl_device_vdispl *vdispl,
+ libxl__ao_device *aodev)
+{
+ libxl__device_add(egc, domid, &libxl__vdispl_devtype, vdispl, aodev);
+}
+
+static int libxl__device_vdispl_getconnectors(libxl_ctx *ctx,
+ const char *path,
+ libxl_vdisplinfo *info)
+{
+ GC_INIT(ctx);
+ char *connector = NULL;
+ char *connector_path = NULL;
+ int i, rc;
+
+ GCNEW_ARRAY(connector_path, 128);
+
+ info->num_connectors = 0;
+
+ rc = snprintf(connector_path, 128, "%s/%d", path, info->num_connectors);
+ if (rc < 0) goto out;
+
+ while((connector = xs_read(ctx->xsh, XBT_NULL, connector_path, NULL))
+ != NULL) {
+ free(connector);
+
+ rc = snprintf(connector_path, 128, "%s/%d",
+ path, ++info->num_connectors);
+ if (rc < 0) goto out;
+ }
+
+ info->connectors = libxl__calloc(NOGC, info->num_connectors,
+ sizeof(*info->connectors));
+
+ for (i = 0; i < info->num_connectors; i++) {
+ char *value;
+
+ snprintf(connector_path, 128, "%s/%d/id", path, i);
+ info->connectors[i].id = xs_read(ctx->xsh, XBT_NULL,
+ connector_path, NULL);
+ if (info->connectors[i].id == NULL) { rc = ERROR_FAIL; goto out; }
+
+ snprintf(connector_path, 128, "%s/%d/resolution", path, i);
+ value = xs_read(ctx->xsh, XBT_NULL, connector_path, NULL);
+ if (value == NULL) { rc = ERROR_FAIL; goto out; }
+
+ rc = sscanf(value, "%ux%u", &info->connectors[i].width,
+ &info->connectors[i].height);
+ free(value);
+ if (rc != 2) {
+ rc = ERROR_FAIL; goto out;
+ }
+
+ snprintf(connector_path, 128, "%s/%d/req-ring-ref", path, i);
+ value = xs_read(ctx->xsh, XBT_NULL, connector_path, NULL);
+ info->connectors[i].req_rref = value ? strtoul(value, NULL, 10) : -1;
+ free(value);
+
+ snprintf(connector_path, 128, "%s/%d/req-event-channel", path, i);
+ value = xs_read(ctx->xsh, XBT_NULL, connector_path, NULL);
+ info->connectors[i].req_evtch = value ? strtoul(value, NULL, 10) : -1;
+ free(value);
+
+ snprintf(connector_path, 128, "%s/%d/evt-ring-ref", path, i);
+ value = xs_read(ctx->xsh, XBT_NULL, connector_path, NULL);
+ info->connectors[i].evt_rref = value ? strtoul(value, NULL, 10) : -1;
+ free(value);
+
+ snprintf(connector_path, 128, "%s/%d/evt-event-channel", path, i);
+ value = xs_read(ctx->xsh, XBT_NULL, connector_path, NULL);
+ info->connectors[i].evt_evtch = value ? strtoul(value, NULL, 10) : -1;
+ free(value);
+ }
+
+ rc = 0;
+
+out:
+ return rc;
+}
+
+libxl_device_vdispl *libxl_device_vdispl_list(libxl_ctx *ctx, uint32_t domid,
+ int *num)
+{
+ return libxl__device_list(&libxl__vdispl_devtype, ctx, domid, num);
+}
+
+void libxl_device_vdispl_list_free(libxl_device_vdispl* list, int num)
+{
+ libxl__device_list_free(&libxl__vdispl_devtype, list, num);
+}
+
+int libxl_device_vdispl_getinfo(libxl_ctx *ctx, uint32_t domid,
+ libxl_device_vdispl *vdispl,
+ libxl_vdisplinfo *info)
+{
+ GC_INIT(ctx);
+ char *libxl_path, *dompath, *devpath;
+ char *val;
+ int rc;
+
+ libxl_vdisplinfo_init(info);
+ dompath = libxl__xs_get_dompath(gc, domid);
+ info->devid = vdispl->devid;
+
+ devpath = GCSPRINTF("%s/device/vdispl/%d", dompath, info->devid);
+ libxl_path = GCSPRINTF("%s/device/vdispl/%d",
+ libxl__xs_libxl_path(gc, domid),
+ info->devid);
+ info->backend = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/backend", libxl_path),
+ NULL);
+ if (!info->backend) { rc = ERROR_FAIL; goto out; }
+
+ rc = libxl__backendpath_parse_domid(gc, info->backend, &info->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", devpath));
+ info->state = val ? strtoul(val, NULL, 10) : -1;
+
+ info->frontend = xs_read(ctx->xsh, XBT_NULL,
+ GCSPRINTF("%s/frontend", libxl_path),
+ NULL);
+ info->frontend_id = domid;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/be_alloc", devpath));
+ info->be_alloc = val ? strtoul(val, NULL, 10) : 0;
+
+ rc = libxl__device_vdispl_getconnectors(ctx, devpath, info);
+ if (rc) goto out;
+
+ rc = 0;
+
+out:
+ GC_FREE;
+ return rc;
+}
+
+int libxl_devid_to_device_vdispl(libxl_ctx *ctx, uint32_t domid,
+ int devid, libxl_device_vdispl *vdispl)
+{
+ libxl_device_vdispl *vdispls = NULL;
+ int n, i;
+ int rc;
+
+ libxl_device_vdispl_init(vdispl);
+
+ vdispls = libxl_device_vdispl_list(ctx, domid, &n);
+
+ if (!vdispls) { rc = ERROR_NOTFOUND; goto out; }
+
+ for (i = 0; i < n; ++i) {
+ if (devid == vdispls[i].devid) {
+ libxl_device_vdispl_copy(ctx, vdispl, &vdispls[i]);
+ rc = 0;
+ goto out;
+ }
+ }
+
+ rc = ERROR_NOTFOUND;
+
+out:
+
+ if (vdispls) {
+ libxl_device_vdispl_list_free(vdispls, n);
+ }
+ return rc;
+}
+
+LIBXL_DEFINE_DEVICE_ADD(vdispl)
+static LIBXL_DEFINE_DEVICES_ADD(vdispl)
+LIBXL_DEFINE_DEVICE_REMOVE(vdispl)
+
+DEFINE_DEVICE_TYPE_STRUCT(vdispl,
+ .update_config = (void (*)(libxl__gc *, void *, void *))
+ libxl__update_config_vdispl,
+ .from_xenstore = (int (*)(libxl__gc *, const char *, uint32_t, void *))
+ libxl__from_xenstore_vdispl,
+ .set_xenstore_config = (int (*)(libxl__gc *, uint32_t, void *))
+ libxl__set_xenstore_vdispl
+);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */