QAPI patches for 2016-03-04
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJW2qsnAAoJEDhwtADrkYZTAOEP/1vKrqTk2+VxW1x33NQ9NpFq bjBgwx9CRgV/CBoQ874EfAUTMnN96JmP//gq/KVFri83PEe0WnZRPnvlOi2UDHLa rV+wZJ4C7bnot+WzPV6HqqmB6G9LLokOzUJqp+4I+rTWoAOXvsOyOXVLpA12G6iu JAU96H5WOOf4i5ZjagIWT3qL67cWFMa+Ba+LzKEPHNcXmPPi7L1VDl75bJuGj7yz FMRsiJH2gAh0dL5rL/fdfZuXJa/qmwdAHfJeyRiu2yBXtJfcfEnpJbBgfGCoiBWc YH+Xpi1ChmhuawpIKlW9bYoNYqIR3LjBq8SAApec2+xa2eoz3gpMqqnH0Hs+ESbR o6CH6WqXEakvwYaW2GwwTVoGOW7d/7Y3eqs0vIki0FMZCRKDFz1MAPOiW3HB7p2s VCBcx27rQ08PmtsU9bUQ0tftzsye8MbycNcBvzKdoXpj1FI3ISpNgnxWwD6EDFYE o2WWOH2aP1cTso86sddn3K921QcQOrzyIun9/hLX9u0/4/i/Zf1QlZjuCw/NIYza xcoVVLTALwTi1OWjVarXnqr2oUGnjevaP3fQuYPWYvCQX8OD5bi5OePcdhzmSgUR TZ/qUUvpRM/MuP9smLwAWSqstvMN/VH+MrSqLrIVwetV9sdJbGaqlBhNLTV3lJPA u59bzZsSKJeDxEk/qCDn =HcD7 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2016-03-04' into staging QAPI patches for 2016-03-04 # gpg: Signature made Sat 05 Mar 2016 09:47:19 GMT using RSA key ID EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" * remotes/armbru/tags/pull-qapi-2016-03-04: qapi: Drop useless 'data' member of unions chardev: Drop useless ChardevDummy type qapi: Avoid use of 'data' member of QAPI unions ui: Shorten references into InputEvent util: Shorten references into SocketAddress chardev: Shorten references into ChardevBackend qapi: Update docs to match recent generator changes qapi-visit: Expose visit_type_FOO_members() qapi: Rename 'fields' to 'members' in generated C code qapi: Rename 'fields' to 'members' in generator qapi-dealloc: Reduce use outside of generated code qmp-shell: fix pretty printing of JSON responses Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
1464ad45cd
|
@ -567,7 +567,7 @@ static CharDriverState *chr_baum_init(const char *id,
|
||||||
ChardevReturn *ret,
|
ChardevReturn *ret,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.braille);
|
ChardevCommon *common = backend->u.braille;
|
||||||
BaumDriverState *baum;
|
BaumDriverState *baum;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
brlapi_handle_t *handle;
|
brlapi_handle_t *handle;
|
||||||
|
|
|
@ -68,7 +68,7 @@ static CharDriverState *qemu_chr_open_msmouse(const char *id,
|
||||||
ChardevReturn *ret,
|
ChardevReturn *ret,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.msmouse);
|
ChardevCommon *common = backend->u.msmouse;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
|
|
||||||
chr = qemu_chr_alloc(common, errp);
|
chr = qemu_chr_alloc(common, errp);
|
||||||
|
|
14
block/nbd.c
14
block/nbd.c
|
@ -204,18 +204,20 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict *options, char **export,
|
||||||
saddr = g_new0(SocketAddress, 1);
|
saddr = g_new0(SocketAddress, 1);
|
||||||
|
|
||||||
if (qdict_haskey(options, "path")) {
|
if (qdict_haskey(options, "path")) {
|
||||||
|
UnixSocketAddress *q_unix;
|
||||||
saddr->type = SOCKET_ADDRESS_KIND_UNIX;
|
saddr->type = SOCKET_ADDRESS_KIND_UNIX;
|
||||||
saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
q_unix = saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||||
saddr->u.q_unix->path = g_strdup(qdict_get_str(options, "path"));
|
q_unix->path = g_strdup(qdict_get_str(options, "path"));
|
||||||
qdict_del(options, "path");
|
qdict_del(options, "path");
|
||||||
} else {
|
} else {
|
||||||
|
InetSocketAddress *inet;
|
||||||
saddr->type = SOCKET_ADDRESS_KIND_INET;
|
saddr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
saddr->u.inet = g_new0(InetSocketAddress, 1);
|
inet = saddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||||
saddr->u.inet->host = g_strdup(qdict_get_str(options, "host"));
|
inet->host = g_strdup(qdict_get_str(options, "host"));
|
||||||
if (!qdict_get_try_str(options, "port")) {
|
if (!qdict_get_try_str(options, "port")) {
|
||||||
saddr->u.inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
|
inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
|
||||||
} else {
|
} else {
|
||||||
saddr->u.inet->port = g_strdup(qdict_get_str(options, "port"));
|
inet->port = g_strdup(qdict_get_str(options, "port"));
|
||||||
}
|
}
|
||||||
qdict_del(options, "host");
|
qdict_del(options, "host");
|
||||||
qdict_del(options, "port");
|
qdict_del(options, "port");
|
||||||
|
|
31
blockdev.c
31
blockdev.c
|
@ -1202,15 +1202,11 @@ void hmp_commit(Monitor *mon, const QDict *qdict)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blockdev_do_action(TransactionActionKind type, void *data,
|
static void blockdev_do_action(TransactionAction *action, Error **errp)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
TransactionAction action;
|
|
||||||
TransactionActionList list;
|
TransactionActionList list;
|
||||||
|
|
||||||
action.type = type;
|
list.value = action;
|
||||||
action.u.data = data;
|
|
||||||
list.value = &action;
|
|
||||||
list.next = NULL;
|
list.next = NULL;
|
||||||
qmp_transaction(&list, false, NULL, errp);
|
qmp_transaction(&list, false, NULL, errp);
|
||||||
}
|
}
|
||||||
|
@ -1236,8 +1232,11 @@ void qmp_blockdev_snapshot_sync(bool has_device, const char *device,
|
||||||
.has_mode = has_mode,
|
.has_mode = has_mode,
|
||||||
.mode = mode,
|
.mode = mode,
|
||||||
};
|
};
|
||||||
blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
|
TransactionAction action = {
|
||||||
&snapshot, errp);
|
.type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
|
||||||
|
.u.blockdev_snapshot_sync = &snapshot,
|
||||||
|
};
|
||||||
|
blockdev_do_action(&action, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_blockdev_snapshot(const char *node, const char *overlay,
|
void qmp_blockdev_snapshot(const char *node, const char *overlay,
|
||||||
|
@ -1247,9 +1246,11 @@ void qmp_blockdev_snapshot(const char *node, const char *overlay,
|
||||||
.node = (char *) node,
|
.node = (char *) node,
|
||||||
.overlay = (char *) overlay
|
.overlay = (char *) overlay
|
||||||
};
|
};
|
||||||
|
TransactionAction action = {
|
||||||
blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
|
.type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
|
||||||
&snapshot_data, errp);
|
.u.blockdev_snapshot = &snapshot_data,
|
||||||
|
};
|
||||||
|
blockdev_do_action(&action, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_blockdev_snapshot_internal_sync(const char *device,
|
void qmp_blockdev_snapshot_internal_sync(const char *device,
|
||||||
|
@ -1260,9 +1261,11 @@ void qmp_blockdev_snapshot_internal_sync(const char *device,
|
||||||
.device = (char *) device,
|
.device = (char *) device,
|
||||||
.name = (char *) name
|
.name = (char *) name
|
||||||
};
|
};
|
||||||
|
TransactionAction action = {
|
||||||
blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
|
.type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
|
||||||
&snapshot, errp);
|
.u.blockdev_snapshot_internal_sync = &snapshot,
|
||||||
|
};
|
||||||
|
blockdev_do_action(&action, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
= How to use the QAPI code generator =
|
= How to use the QAPI code generator =
|
||||||
|
|
||||||
Copyright IBM Corp. 2011
|
Copyright IBM Corp. 2011
|
||||||
Copyright (C) 2012-2015 Red Hat, Inc.
|
Copyright (C) 2012-2016 Red Hat, Inc.
|
||||||
|
|
||||||
This work is licensed under the terms of the GNU GPL, version 2 or
|
This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
later. See the COPYING file in the top-level directory.
|
later. See the COPYING file in the top-level directory.
|
||||||
|
@ -52,7 +52,7 @@ schema. The documentation is delimited between two lines of ##, then
|
||||||
the first line names the expression, an optional overview is provided,
|
the first line names the expression, an optional overview is provided,
|
||||||
then individual documentation about each member of 'data' is provided,
|
then individual documentation about each member of 'data' is provided,
|
||||||
and finally, a 'Since: x.y.z' tag lists the release that introduced
|
and finally, a 'Since: x.y.z' tag lists the release that introduced
|
||||||
the expression. Optional fields are tagged with the phrase
|
the expression. Optional members are tagged with the phrase
|
||||||
'#optional', often with their default value; and extensions added
|
'#optional', often with their default value; and extensions added
|
||||||
after the expression was first released are also given a '(since
|
after the expression was first released are also given a '(since
|
||||||
x.y.z)' comment. For example:
|
x.y.z)' comment. For example:
|
||||||
|
@ -108,15 +108,15 @@ user-defined type names, while built-in types are lowercase. Type
|
||||||
definitions should not end in 'Kind', as this namespace is used for
|
definitions should not end in 'Kind', as this namespace is used for
|
||||||
creating implicit C enums for visiting union types, or in 'List', as
|
creating implicit C enums for visiting union types, or in 'List', as
|
||||||
this namespace is used for creating array types. Command names,
|
this namespace is used for creating array types. Command names,
|
||||||
and field names within a type, should be all lower case with words
|
and member names within a type, should be all lower case with words
|
||||||
separated by a hyphen. However, some existing older commands and
|
separated by a hyphen. However, some existing older commands and
|
||||||
complex types use underscore; when extending such expressions,
|
complex types use underscore; when extending such expressions,
|
||||||
consistency is preferred over blindly avoiding underscore. Event
|
consistency is preferred over blindly avoiding underscore. Event
|
||||||
names should be ALL_CAPS with words separated by underscore. Field
|
names should be ALL_CAPS with words separated by underscore. Member
|
||||||
names cannot start with 'has-' or 'has_', as this is reserved for
|
names cannot start with 'has-' or 'has_', as this is reserved for
|
||||||
tracking optional fields.
|
tracking optional members.
|
||||||
|
|
||||||
Any name (command, event, type, field, or enum value) beginning with
|
Any name (command, event, type, member, or enum value) beginning with
|
||||||
"x-" is marked experimental, and may be withdrawn or changed
|
"x-" is marked experimental, and may be withdrawn or changed
|
||||||
incompatibly in a future release. All names must begin with a letter,
|
incompatibly in a future release. All names must begin with a letter,
|
||||||
and contain only ASCII letters, digits, dash, and underscore. There
|
and contain only ASCII letters, digits, dash, and underscore. There
|
||||||
|
@ -127,7 +127,7 @@ the vendor), even if the rest of the name uses dash (example:
|
||||||
__com.redhat_drive-mirror). Names beginning with 'q_' are reserved
|
__com.redhat_drive-mirror). Names beginning with 'q_' are reserved
|
||||||
for the generator: QMP names that resemble C keywords or other
|
for the generator: QMP names that resemble C keywords or other
|
||||||
problematic strings will be munged in C to use this prefix. For
|
problematic strings will be munged in C to use this prefix. For
|
||||||
example, a field named "default" in qapi becomes "q_default" in the
|
example, a member named "default" in qapi becomes "q_default" in the
|
||||||
generated C code.
|
generated C code.
|
||||||
|
|
||||||
In the rest of this document, usage lines are given for each
|
In the rest of this document, usage lines are given for each
|
||||||
|
@ -217,17 +217,18 @@ and must continue to work).
|
||||||
|
|
||||||
On output structures (only mentioned in the 'returns' side of a command),
|
On output structures (only mentioned in the 'returns' side of a command),
|
||||||
changing from mandatory to optional is in general unsafe (older clients may be
|
changing from mandatory to optional is in general unsafe (older clients may be
|
||||||
expecting the field, and could crash if it is missing), although it can be done
|
expecting the member, and could crash if it is missing), although it
|
||||||
if the only way that the optional argument will be omitted is when it is
|
can be done if the only way that the optional argument will be omitted
|
||||||
triggered by the presence of a new input flag to the command that older clients
|
is when it is triggered by the presence of a new input flag to the
|
||||||
don't know to send. Changing from optional to mandatory is safe.
|
command that older clients don't know to send. Changing from optional
|
||||||
|
to mandatory is safe.
|
||||||
|
|
||||||
A structure that is used in both input and output of various commands
|
A structure that is used in both input and output of various commands
|
||||||
must consider the backwards compatibility constraints of both directions
|
must consider the backwards compatibility constraints of both directions
|
||||||
of use.
|
of use.
|
||||||
|
|
||||||
A struct definition can specify another struct as its base.
|
A struct definition can specify another struct as its base.
|
||||||
In this case, the fields of the base type are included as top-level fields
|
In this case, the members of the base type are included as top-level members
|
||||||
of the new struct's dictionary in the Client JSON Protocol wire
|
of the new struct's dictionary in the Client JSON Protocol wire
|
||||||
format. An example definition is:
|
format. An example definition is:
|
||||||
|
|
||||||
|
@ -237,7 +238,7 @@ format. An example definition is:
|
||||||
'data': { '*backing': 'str' } }
|
'data': { '*backing': 'str' } }
|
||||||
|
|
||||||
An example BlockdevOptionsGenericCOWFormat object on the wire could use
|
An example BlockdevOptionsGenericCOWFormat object on the wire could use
|
||||||
both fields like this:
|
both members like this:
|
||||||
|
|
||||||
{ "file": "/some/place/my-image",
|
{ "file": "/some/place/my-image",
|
||||||
"backing": "/some/place/my-backing-file" }
|
"backing": "/some/place/my-backing-file" }
|
||||||
|
@ -262,7 +263,7 @@ The enum constants will be named by using a heuristic to turn the
|
||||||
type name into a set of underscore separated words. For the example
|
type name into a set of underscore separated words. For the example
|
||||||
above, 'MyEnum' will turn into 'MY_ENUM' giving a constant name
|
above, 'MyEnum' will turn into 'MY_ENUM' giving a constant name
|
||||||
of 'MY_ENUM_VALUE1' for the first value. If the default heuristic
|
of 'MY_ENUM_VALUE1' for the first value. If the default heuristic
|
||||||
does not result in a desirable name, the optional 'prefix' field
|
does not result in a desirable name, the optional 'prefix' member
|
||||||
can be used when defining the enum.
|
can be used when defining the enum.
|
||||||
|
|
||||||
The enumeration values are passed as strings over the Client JSON
|
The enumeration values are passed as strings over the Client JSON
|
||||||
|
@ -275,9 +276,9 @@ converting between strings and enum values. Since the wire format
|
||||||
always passes by name, it is acceptable to reorder or add new
|
always passes by name, it is acceptable to reorder or add new
|
||||||
enumeration members in any location without breaking clients of Client
|
enumeration members in any location without breaking clients of Client
|
||||||
JSON Protocol; however, removing enum values would break
|
JSON Protocol; however, removing enum values would break
|
||||||
compatibility. For any struct that has a field that will only contain
|
compatibility. For any struct that has a member that will only contain
|
||||||
a finite set of string values, using an enum type for that field is
|
a finite set of string values, using an enum type for that member is
|
||||||
better than open-coding the field to be type 'str'.
|
better than open-coding the member to be type 'str'.
|
||||||
|
|
||||||
|
|
||||||
=== Union types ===
|
=== Union types ===
|
||||||
|
@ -305,8 +306,8 @@ values to data types like in this example:
|
||||||
'qcow2': 'Qcow2Options' } }
|
'qcow2': 'Qcow2Options' } }
|
||||||
|
|
||||||
In the Client JSON Protocol, a simple union is represented by a
|
In the Client JSON Protocol, a simple union is represented by a
|
||||||
dictionary that contains the 'type' field as a discriminator, and a
|
dictionary that contains the 'type' member as a discriminator, and a
|
||||||
'data' field that is of the specified data type corresponding to the
|
'data' member that is of the specified data type corresponding to the
|
||||||
discriminator value, as in these examples:
|
discriminator value, as in these examples:
|
||||||
|
|
||||||
{ "type": "file", "data" : { "filename": "/some/place/my-image" } }
|
{ "type": "file", "data" : { "filename": "/some/place/my-image" } }
|
||||||
|
@ -321,14 +322,14 @@ enum. The value for each branch can be of any type.
|
||||||
|
|
||||||
A flat union definition specifies a struct as its base, and
|
A flat union definition specifies a struct as its base, and
|
||||||
avoids nesting on the wire. All branches of the union must be
|
avoids nesting on the wire. All branches of the union must be
|
||||||
complex types, and the top-level fields of the union dictionary on
|
complex types, and the top-level members of the union dictionary on
|
||||||
the wire will be combination of fields from both the base type and the
|
the wire will be combination of members from both the base type and the
|
||||||
appropriate branch type (when merging two dictionaries, there must be
|
appropriate branch type (when merging two dictionaries, there must be
|
||||||
no keys in common). The 'discriminator' field must be the name of an
|
no keys in common). The 'discriminator' member must be the name of an
|
||||||
enum-typed member of the base struct.
|
enum-typed member of the base struct.
|
||||||
|
|
||||||
The following example enhances the above simple union example by
|
The following example enhances the above simple union example by
|
||||||
adding a common field 'readonly', renaming the discriminator to
|
adding a common member 'readonly', renaming the discriminator to
|
||||||
something more applicable, and reducing the number of {} required on
|
something more applicable, and reducing the number of {} required on
|
||||||
the wire:
|
the wire:
|
||||||
|
|
||||||
|
@ -353,8 +354,8 @@ the user, but because it must map to a base member with enum type, the
|
||||||
code generator can ensure that branches exist for all values of the
|
code generator can ensure that branches exist for all values of the
|
||||||
enum (although the order of the keys need not match the declaration of
|
enum (although the order of the keys need not match the declaration of
|
||||||
the enum). In the resulting generated C data types, a flat union is
|
the enum). In the resulting generated C data types, a flat union is
|
||||||
represented as a struct with the base member fields included directly,
|
represented as a struct with the base members included directly, and
|
||||||
and then a union of structures for each branch of the struct.
|
then a union of structures for each branch of the struct.
|
||||||
|
|
||||||
A simple union can always be re-written as a flat union where the base
|
A simple union can always be re-written as a flat union where the base
|
||||||
class has a single member named 'type', and where each branch of the
|
class has a single member named 'type', and where each branch of the
|
||||||
|
@ -424,10 +425,10 @@ string name of a complex type, or a dictionary that declares an
|
||||||
anonymous type with the same semantics as a 'struct' expression, with
|
anonymous type with the same semantics as a 'struct' expression, with
|
||||||
one exception noted below when 'gen' is used.
|
one exception noted below when 'gen' is used.
|
||||||
|
|
||||||
The 'returns' member describes what will appear in the "return" field
|
The 'returns' member describes what will appear in the "return" member
|
||||||
of a Client JSON Protocol reply on successful completion of a command.
|
of a Client JSON Protocol reply on successful completion of a command.
|
||||||
The member is optional from the command declaration; if absent, the
|
The member is optional from the command declaration; if absent, the
|
||||||
"return" field will be an empty dictionary. If 'returns' is present,
|
"return" member will be an empty dictionary. If 'returns' is present,
|
||||||
it must be the string name of a complex or built-in type, a
|
it must be the string name of a complex or built-in type, a
|
||||||
one-element array containing the name of a complex or built-in type,
|
one-element array containing the name of a complex or built-in type,
|
||||||
with one exception noted below when 'gen' is used. Although it is
|
with one exception noted below when 'gen' is used. Although it is
|
||||||
|
@ -435,7 +436,7 @@ permitted to have the 'returns' member name a built-in type or an
|
||||||
array of built-in types, any command that does this cannot be extended
|
array of built-in types, any command that does this cannot be extended
|
||||||
to return additional information in the future; thus, new commands
|
to return additional information in the future; thus, new commands
|
||||||
should strongly consider returning a dictionary-based type or an array
|
should strongly consider returning a dictionary-based type or an array
|
||||||
of dictionaries, even if the dictionary only contains one field at the
|
of dictionaries, even if the dictionary only contains one member at the
|
||||||
present.
|
present.
|
||||||
|
|
||||||
All commands in Client JSON Protocol use a dictionary to report
|
All commands in Client JSON Protocol use a dictionary to report
|
||||||
|
@ -478,7 +479,7 @@ response is not possible (although the command will still return a
|
||||||
normal dictionary error on failure). When a successful reply is not
|
normal dictionary error on failure). When a successful reply is not
|
||||||
possible, the command expression should include the optional key
|
possible, the command expression should include the optional key
|
||||||
'success-response' with boolean value false. So far, only QGA makes
|
'success-response' with boolean value false. So far, only QGA makes
|
||||||
use of this field.
|
use of this member.
|
||||||
|
|
||||||
|
|
||||||
=== Events ===
|
=== Events ===
|
||||||
|
@ -656,7 +657,7 @@ Union types
|
||||||
|
|
||||||
{ "name": "BlockdevOptions", "meta-type": "object",
|
{ "name": "BlockdevOptions", "meta-type": "object",
|
||||||
"members": [
|
"members": [
|
||||||
{ "name": "kind", "type": "BlockdevOptionsKind" } ],
|
{ "name": "type", "type": "BlockdevOptionsKind" } ],
|
||||||
"tag": "type",
|
"tag": "type",
|
||||||
"variants": [
|
"variants": [
|
||||||
{ "case": "file", "type": ":obj-FileOptions-wrapper" },
|
{ "case": "file", "type": ":obj-FileOptions-wrapper" },
|
||||||
|
@ -722,33 +723,38 @@ the names of built-in types. Clients should examine member
|
||||||
|
|
||||||
== Code generation ==
|
== Code generation ==
|
||||||
|
|
||||||
Schemas are fed into four scripts to generate all the code/files that,
|
Schemas are fed into five scripts to generate all the code/files that,
|
||||||
paired with the core QAPI libraries, comprise everything required to
|
paired with the core QAPI libraries, comprise everything required to
|
||||||
take JSON commands read in by a Client JSON Protocol server, unmarshal
|
take JSON commands read in by a Client JSON Protocol server, unmarshal
|
||||||
the arguments into the underlying C types, call into the corresponding
|
the arguments into the underlying C types, call into the corresponding
|
||||||
C function, and map the response back to a Client JSON Protocol
|
C function, map the response back to a Client JSON Protocol response
|
||||||
response to be returned to the user.
|
to be returned to the user, and introspect the commands.
|
||||||
|
|
||||||
As an example, we'll use the following schema, which describes a single
|
As an example, we'll use the following schema, which describes a
|
||||||
complex user-defined type (which will produce a C struct, along with a list
|
single complex user-defined type, along with command which takes a
|
||||||
node structure that can be used to chain together a list of such types in
|
list of that type as a parameter, and returns a single element of that
|
||||||
case we want to accept/return a list of this type with a command), and a
|
type. The user is responsible for writing the implementation of
|
||||||
command which takes that type as a parameter and returns the same type:
|
qmp_my_command(); everything else is produced by the generator.
|
||||||
|
|
||||||
$ cat example-schema.json
|
$ cat example-schema.json
|
||||||
{ 'struct': 'UserDefOne',
|
{ 'struct': 'UserDefOne',
|
||||||
'data': { 'integer': 'int', 'string': 'str' } }
|
'data': { 'integer': 'int', '*string': 'str' } }
|
||||||
|
|
||||||
{ 'command': 'my-command',
|
{ 'command': 'my-command',
|
||||||
'data': {'arg1': 'UserDefOne'},
|
'data': { 'arg1': ['UserDefOne'] },
|
||||||
'returns': 'UserDefOne' }
|
'returns': 'UserDefOne' }
|
||||||
|
|
||||||
{ 'event': 'MY_EVENT' }
|
{ 'event': 'MY_EVENT' }
|
||||||
|
|
||||||
|
For a more thorough look at generated code, the testsuite includes
|
||||||
|
tests/qapi-schema/qapi-schema-tests.json that covers more examples of
|
||||||
|
what the generator will accept, and compiles the resulting C code as
|
||||||
|
part of 'make check-unit'.
|
||||||
|
|
||||||
=== scripts/qapi-types.py ===
|
=== scripts/qapi-types.py ===
|
||||||
|
|
||||||
Used to generate the C types defined by a schema. The following files are
|
Used to generate the C types defined by a schema, along with
|
||||||
created:
|
supporting code. The following files are created:
|
||||||
|
|
||||||
$(prefix)qapi-types.h - C types corresponding to types defined in
|
$(prefix)qapi-types.h - C types corresponding to types defined in
|
||||||
the schema you pass in
|
the schema you pass in
|
||||||
|
@ -763,38 +769,6 @@ Example:
|
||||||
|
|
||||||
$ python scripts/qapi-types.py --output-dir="qapi-generated" \
|
$ python scripts/qapi-types.py --output-dir="qapi-generated" \
|
||||||
--prefix="example-" example-schema.json
|
--prefix="example-" example-schema.json
|
||||||
$ cat qapi-generated/example-qapi-types.c
|
|
||||||
[Uninteresting stuff omitted...]
|
|
||||||
|
|
||||||
void qapi_free_UserDefOne(UserDefOne *obj)
|
|
||||||
{
|
|
||||||
QapiDeallocVisitor *qdv;
|
|
||||||
Visitor *v;
|
|
||||||
|
|
||||||
if (!obj) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qdv = qapi_dealloc_visitor_new();
|
|
||||||
v = qapi_dealloc_get_visitor(qdv);
|
|
||||||
visit_type_UserDefOne(v, &obj, NULL, NULL);
|
|
||||||
qapi_dealloc_visitor_cleanup(qdv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void qapi_free_UserDefOneList(UserDefOneList *obj)
|
|
||||||
{
|
|
||||||
QapiDeallocVisitor *qdv;
|
|
||||||
Visitor *v;
|
|
||||||
|
|
||||||
if (!obj) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qdv = qapi_dealloc_visitor_new();
|
|
||||||
v = qapi_dealloc_get_visitor(qdv);
|
|
||||||
visit_type_UserDefOneList(v, &obj, NULL, NULL);
|
|
||||||
qapi_dealloc_visitor_cleanup(qdv);
|
|
||||||
}
|
|
||||||
$ cat qapi-generated/example-qapi-types.h
|
$ cat qapi-generated/example-qapi-types.h
|
||||||
[Uninteresting stuff omitted...]
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
@ -809,29 +783,59 @@ Example:
|
||||||
|
|
||||||
struct UserDefOne {
|
struct UserDefOne {
|
||||||
int64_t integer;
|
int64_t integer;
|
||||||
|
bool has_string;
|
||||||
char *string;
|
char *string;
|
||||||
};
|
};
|
||||||
|
|
||||||
void qapi_free_UserDefOne(UserDefOne *obj);
|
void qapi_free_UserDefOne(UserDefOne *obj);
|
||||||
|
|
||||||
struct UserDefOneList {
|
struct UserDefOneList {
|
||||||
union {
|
|
||||||
UserDefOne *value;
|
|
||||||
uint64_t padding;
|
|
||||||
};
|
|
||||||
UserDefOneList *next;
|
UserDefOneList *next;
|
||||||
|
UserDefOne *value;
|
||||||
};
|
};
|
||||||
|
|
||||||
void qapi_free_UserDefOneList(UserDefOneList *obj);
|
void qapi_free_UserDefOneList(UserDefOneList *obj);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
$ cat qapi-generated/example-qapi-types.c
|
||||||
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
void qapi_free_UserDefOne(UserDefOne *obj)
|
||||||
|
{
|
||||||
|
QapiDeallocVisitor *qdv;
|
||||||
|
Visitor *v;
|
||||||
|
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdv = qapi_dealloc_visitor_new();
|
||||||
|
v = qapi_dealloc_get_visitor(qdv);
|
||||||
|
visit_type_UserDefOne(v, NULL, &obj, NULL);
|
||||||
|
qapi_dealloc_visitor_cleanup(qdv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void qapi_free_UserDefOneList(UserDefOneList *obj)
|
||||||
|
{
|
||||||
|
QapiDeallocVisitor *qdv;
|
||||||
|
Visitor *v;
|
||||||
|
|
||||||
|
if (!obj) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qdv = qapi_dealloc_visitor_new();
|
||||||
|
v = qapi_dealloc_get_visitor(qdv);
|
||||||
|
visit_type_UserDefOneList(v, NULL, &obj, NULL);
|
||||||
|
qapi_dealloc_visitor_cleanup(qdv);
|
||||||
|
}
|
||||||
|
|
||||||
=== scripts/qapi-visit.py ===
|
=== scripts/qapi-visit.py ===
|
||||||
|
|
||||||
Used to generate the visitor functions used to walk through and convert
|
Used to generate the visitor functions used to walk through and
|
||||||
a QObject (as provided by QMP) to a native C data structure and
|
convert between a native QAPI C data structure and some other format
|
||||||
vice-versa, as well as the visitor function used to dealloc a complex
|
(such as QObject); the generated functions are named visit_type_FOO()
|
||||||
schema-defined C type.
|
and visit_type_FOO_members().
|
||||||
|
|
||||||
The following files are generated:
|
The following files are generated:
|
||||||
|
|
||||||
|
@ -848,41 +852,62 @@ Example:
|
||||||
|
|
||||||
$ python scripts/qapi-visit.py --output-dir="qapi-generated"
|
$ python scripts/qapi-visit.py --output-dir="qapi-generated"
|
||||||
--prefix="example-" example-schema.json
|
--prefix="example-" example-schema.json
|
||||||
|
$ cat qapi-generated/example-qapi-visit.h
|
||||||
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
#ifndef EXAMPLE_QAPI_VISIT_H
|
||||||
|
#define EXAMPLE_QAPI_VISIT_H
|
||||||
|
|
||||||
|
[Visitors for built-in types omitted...]
|
||||||
|
|
||||||
|
void visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp);
|
||||||
|
void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp);
|
||||||
|
void visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp);
|
||||||
|
|
||||||
|
#endif
|
||||||
$ cat qapi-generated/example-qapi-visit.c
|
$ cat qapi-generated/example-qapi-visit.c
|
||||||
[Uninteresting stuff omitted...]
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
static void visit_type_UserDefOne_fields(Visitor *v, UserDefOne **obj, Error **errp)
|
void visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error **errp)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
visit_type_int(v, &(*obj)->integer, "integer", &err);
|
visit_type_int(v, "integer", &obj->integer, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
visit_type_str(v, &(*obj)->string, "string", &err);
|
if (visit_optional(v, "string", &obj->has_string)) {
|
||||||
if (err) {
|
visit_type_str(v, "string", &obj->string, &err);
|
||||||
goto out;
|
if (err) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_UserDefOne(Visitor *v, UserDefOne **obj, const char *name, Error **errp)
|
void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, Error **errp)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
visit_start_struct(v, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), &err);
|
visit_start_struct(v, name, (void **)obj, sizeof(UserDefOne), &err);
|
||||||
if (!err) {
|
if (err) {
|
||||||
if (*obj) {
|
goto out;
|
||||||
visit_type_UserDefOne_fields(v, obj, errp);
|
|
||||||
}
|
|
||||||
visit_end_struct(v, &err);
|
|
||||||
}
|
}
|
||||||
|
if (!*obj) {
|
||||||
|
goto out_obj;
|
||||||
|
}
|
||||||
|
visit_type_UserDefOne_members(v, *obj, &err);
|
||||||
|
error_propagate(errp, err);
|
||||||
|
err = NULL;
|
||||||
|
out_obj:
|
||||||
|
visit_end_struct(v, &err);
|
||||||
|
out:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit_type_UserDefOneList(Visitor *v, UserDefOneList **obj, const char *name, Error **errp)
|
void visit_type_UserDefOneList(Visitor *v, const char *name, UserDefOneList **obj, Error **errp)
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
GenericList *i, **prev;
|
GenericList *i, **prev;
|
||||||
|
@ -893,35 +918,24 @@ Example:
|
||||||
}
|
}
|
||||||
|
|
||||||
for (prev = (GenericList **)obj;
|
for (prev = (GenericList **)obj;
|
||||||
!err && (i = visit_next_list(v, prev, &err)) != NULL;
|
!err && (i = visit_next_list(v, prev, sizeof(**obj))) != NULL;
|
||||||
prev = &i) {
|
prev = &i) {
|
||||||
UserDefOneList *native_i = (UserDefOneList *)i;
|
UserDefOneList *native_i = (UserDefOneList *)i;
|
||||||
visit_type_UserDefOne(v, &native_i->value, NULL, &err);
|
visit_type_UserDefOne(v, NULL, &native_i->value, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_propagate(errp, err);
|
visit_end_list(v);
|
||||||
err = NULL;
|
|
||||||
visit_end_list(v, &err);
|
|
||||||
out:
|
out:
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
$ cat qapi-generated/example-qapi-visit.h
|
|
||||||
[Uninteresting stuff omitted...]
|
|
||||||
|
|
||||||
#ifndef EXAMPLE_QAPI_VISIT_H
|
|
||||||
#define EXAMPLE_QAPI_VISIT_H
|
|
||||||
|
|
||||||
[Visitors for built-in types omitted...]
|
|
||||||
|
|
||||||
void visit_type_UserDefOne(Visitor *v, UserDefOne **obj, const char *name, Error **errp);
|
|
||||||
void visit_type_UserDefOneList(Visitor *v, UserDefOneList **obj, const char *name, Error **errp);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
=== scripts/qapi-commands.py ===
|
=== scripts/qapi-commands.py ===
|
||||||
|
|
||||||
Used to generate the marshaling/dispatch functions for the commands defined
|
Used to generate the marshaling/dispatch functions for the commands
|
||||||
in the schema. The following files are generated:
|
defined in the schema. The generated code implements
|
||||||
|
qmp_marshal_COMMAND() (mentioned in qmp-commands.hx, and registered
|
||||||
|
automatically), and declares qmp_COMMAND() that the user must
|
||||||
|
implement. The following files are generated:
|
||||||
|
|
||||||
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
|
$(prefix)qmp-marshal.c: command marshal/dispatch functions for each
|
||||||
QMP command defined in the schema. Functions
|
QMP command defined in the schema. Functions
|
||||||
|
@ -939,6 +953,19 @@ Example:
|
||||||
|
|
||||||
$ python scripts/qapi-commands.py --output-dir="qapi-generated"
|
$ python scripts/qapi-commands.py --output-dir="qapi-generated"
|
||||||
--prefix="example-" example-schema.json
|
--prefix="example-" example-schema.json
|
||||||
|
$ cat qapi-generated/example-qmp-commands.h
|
||||||
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
#ifndef EXAMPLE_QMP_COMMANDS_H
|
||||||
|
#define EXAMPLE_QMP_COMMANDS_H
|
||||||
|
|
||||||
|
#include "example-qapi-types.h"
|
||||||
|
#include "qapi/qmp/qdict.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
|
UserDefOne *qmp_my_command(UserDefOneList *arg1, Error **errp);
|
||||||
|
|
||||||
|
#endif
|
||||||
$ cat qapi-generated/example-qmp-marshal.c
|
$ cat qapi-generated/example-qmp-marshal.c
|
||||||
[Uninteresting stuff omitted...]
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
@ -950,7 +977,7 @@ Example:
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
|
||||||
v = qmp_output_get_visitor(qov);
|
v = qmp_output_get_visitor(qov);
|
||||||
visit_type_UserDefOne(v, &ret_in, "unused", &err);
|
visit_type_UserDefOne(v, "unused", &ret_in, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -961,7 +988,7 @@ Example:
|
||||||
qmp_output_visitor_cleanup(qov);
|
qmp_output_visitor_cleanup(qov);
|
||||||
qdv = qapi_dealloc_visitor_new();
|
qdv = qapi_dealloc_visitor_new();
|
||||||
v = qapi_dealloc_get_visitor(qdv);
|
v = qapi_dealloc_get_visitor(qdv);
|
||||||
visit_type_UserDefOne(v, &ret_in, "unused", NULL);
|
visit_type_UserDefOne(v, "unused", &ret_in, NULL);
|
||||||
qapi_dealloc_visitor_cleanup(qdv);
|
qapi_dealloc_visitor_cleanup(qdv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -972,10 +999,10 @@ Example:
|
||||||
QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
|
QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
|
||||||
QapiDeallocVisitor *qdv;
|
QapiDeallocVisitor *qdv;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
UserDefOne *arg1 = NULL;
|
UserDefOneList *arg1 = NULL;
|
||||||
|
|
||||||
v = qmp_input_get_visitor(qiv);
|
v = qmp_input_get_visitor(qiv);
|
||||||
visit_type_UserDefOne(v, &arg1, "arg1", &err);
|
visit_type_UserDefOneList(v, "arg1", &arg1, &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -992,7 +1019,7 @@ Example:
|
||||||
qmp_input_visitor_cleanup(qiv);
|
qmp_input_visitor_cleanup(qiv);
|
||||||
qdv = qapi_dealloc_visitor_new();
|
qdv = qapi_dealloc_visitor_new();
|
||||||
v = qapi_dealloc_get_visitor(qdv);
|
v = qapi_dealloc_get_visitor(qdv);
|
||||||
visit_type_UserDefOne(v, &arg1, "arg1", NULL);
|
visit_type_UserDefOneList(v, "arg1", &arg1, NULL);
|
||||||
qapi_dealloc_visitor_cleanup(qdv);
|
qapi_dealloc_visitor_cleanup(qdv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1002,24 +1029,12 @@ Example:
|
||||||
}
|
}
|
||||||
|
|
||||||
qapi_init(qmp_init_marshal);
|
qapi_init(qmp_init_marshal);
|
||||||
$ cat qapi-generated/example-qmp-commands.h
|
|
||||||
[Uninteresting stuff omitted...]
|
|
||||||
|
|
||||||
#ifndef EXAMPLE_QMP_COMMANDS_H
|
|
||||||
#define EXAMPLE_QMP_COMMANDS_H
|
|
||||||
|
|
||||||
#include "example-qapi-types.h"
|
|
||||||
#include "qapi/qmp/qdict.h"
|
|
||||||
#include "qapi/error.h"
|
|
||||||
|
|
||||||
UserDefOne *qmp_my_command(UserDefOne *arg1, Error **errp);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
=== scripts/qapi-event.py ===
|
=== scripts/qapi-event.py ===
|
||||||
|
|
||||||
Used to generate the event-related C code defined by a schema. The
|
Used to generate the event-related C code defined by a schema, with
|
||||||
following files are created:
|
implementations for qapi_event_send_FOO(). The following files are
|
||||||
|
created:
|
||||||
|
|
||||||
$(prefix)qapi-event.h - Function prototypes for each event type, plus an
|
$(prefix)qapi-event.h - Function prototypes for each event type, plus an
|
||||||
enumeration of all event names
|
enumeration of all event names
|
||||||
|
@ -1029,6 +1044,27 @@ Example:
|
||||||
|
|
||||||
$ python scripts/qapi-event.py --output-dir="qapi-generated"
|
$ python scripts/qapi-event.py --output-dir="qapi-generated"
|
||||||
--prefix="example-" example-schema.json
|
--prefix="example-" example-schema.json
|
||||||
|
$ cat qapi-generated/example-qapi-event.h
|
||||||
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
#ifndef EXAMPLE_QAPI_EVENT_H
|
||||||
|
#define EXAMPLE_QAPI_EVENT_H
|
||||||
|
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qapi/qmp/qdict.h"
|
||||||
|
#include "example-qapi-types.h"
|
||||||
|
|
||||||
|
|
||||||
|
void qapi_event_send_my_event(Error **errp);
|
||||||
|
|
||||||
|
typedef enum example_QAPIEvent {
|
||||||
|
EXAMPLE_QAPI_EVENT_MY_EVENT = 0,
|
||||||
|
EXAMPLE_QAPI_EVENT__MAX = 1,
|
||||||
|
} example_QAPIEvent;
|
||||||
|
|
||||||
|
extern const char *const example_QAPIEvent_lookup[];
|
||||||
|
|
||||||
|
#endif
|
||||||
$ cat qapi-generated/example-qapi-event.c
|
$ cat qapi-generated/example-qapi-event.c
|
||||||
[Uninteresting stuff omitted...]
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
@ -1054,27 +1090,6 @@ Example:
|
||||||
[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
|
[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
|
||||||
[EXAMPLE_QAPI_EVENT__MAX] = NULL,
|
[EXAMPLE_QAPI_EVENT__MAX] = NULL,
|
||||||
};
|
};
|
||||||
$ cat qapi-generated/example-qapi-event.h
|
|
||||||
[Uninteresting stuff omitted...]
|
|
||||||
|
|
||||||
#ifndef EXAMPLE_QAPI_EVENT_H
|
|
||||||
#define EXAMPLE_QAPI_EVENT_H
|
|
||||||
|
|
||||||
#include "qapi/error.h"
|
|
||||||
#include "qapi/qmp/qdict.h"
|
|
||||||
#include "example-qapi-types.h"
|
|
||||||
|
|
||||||
|
|
||||||
void qapi_event_send_my_event(Error **errp);
|
|
||||||
|
|
||||||
typedef enum example_QAPIEvent {
|
|
||||||
EXAMPLE_QAPI_EVENT_MY_EVENT = 0,
|
|
||||||
EXAMPLE_QAPI_EVENT__MAX = 1,
|
|
||||||
} example_QAPIEvent;
|
|
||||||
|
|
||||||
extern const char *const example_QAPIEvent_lookup[];
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
=== scripts/qapi-introspect.py ===
|
=== scripts/qapi-introspect.py ===
|
||||||
|
|
||||||
|
@ -1089,17 +1104,6 @@ Example:
|
||||||
|
|
||||||
$ python scripts/qapi-introspect.py --output-dir="qapi-generated"
|
$ python scripts/qapi-introspect.py --output-dir="qapi-generated"
|
||||||
--prefix="example-" example-schema.json
|
--prefix="example-" example-schema.json
|
||||||
$ cat qapi-generated/example-qmp-introspect.c
|
|
||||||
[Uninteresting stuff omitted...]
|
|
||||||
|
|
||||||
const char example_qmp_schema_json[] = "["
|
|
||||||
"{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, "
|
|
||||||
"{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"2\"}, "
|
|
||||||
"{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, "
|
|
||||||
"{\"members\": [{\"name\": \"arg1\", \"type\": \"2\"}], \"meta-type\": \"object\", \"name\": \"1\"}, "
|
|
||||||
"{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
|
|
||||||
"{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, "
|
|
||||||
"{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}]";
|
|
||||||
$ cat qapi-generated/example-qmp-introspect.h
|
$ cat qapi-generated/example-qmp-introspect.h
|
||||||
[Uninteresting stuff omitted...]
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
@ -1109,3 +1113,15 @@ Example:
|
||||||
extern const char example_qmp_schema_json[];
|
extern const char example_qmp_schema_json[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
$ cat qapi-generated/example-qmp-introspect.c
|
||||||
|
[Uninteresting stuff omitted...]
|
||||||
|
|
||||||
|
const char example_qmp_schema_json[] = "["
|
||||||
|
"{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, "
|
||||||
|
"{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"2\"}, "
|
||||||
|
"{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, "
|
||||||
|
"{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], \"meta-type\": \"object\", \"name\": \"1\"}, "
|
||||||
|
"{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"default\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
|
||||||
|
"{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": \"[2]\"}, "
|
||||||
|
"{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, "
|
||||||
|
"{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}]";
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
0. About This Document
|
0. About This Document
|
||||||
======================
|
======================
|
||||||
|
|
||||||
Copyright (C) 2009-2015 Red Hat, Inc.
|
Copyright (C) 2009-2016 Red Hat, Inc.
|
||||||
|
|
||||||
This work is licensed under the terms of the GNU GPL, version 2 or
|
This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
later. See the COPYING file in the top-level directory.
|
later. See the COPYING file in the top-level directory.
|
||||||
|
@ -277,7 +277,7 @@ However, Clients must not assume any particular:
|
||||||
- Amount of errors generated by a command, that is, new errors can be added
|
- Amount of errors generated by a command, that is, new errors can be added
|
||||||
to any existing command in newer versions of the Server
|
to any existing command in newer versions of the Server
|
||||||
|
|
||||||
Any command or field name beginning with "x-" is deemed experimental,
|
Any command or member name beginning with "x-" is deemed experimental,
|
||||||
and may be withdrawn or changed in an incompatible manner in a future
|
and may be withdrawn or changed in an incompatible manner in a future
|
||||||
release.
|
release.
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "hw/nvram/fw_cfg.h"
|
#include "hw/nvram/fw_cfg.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
#include "qapi/opts-visitor.h"
|
#include "qapi/opts-visitor.h"
|
||||||
#include "qapi/dealloc-visitor.h"
|
|
||||||
#include "qapi-visit.h"
|
#include "qapi-visit.h"
|
||||||
#include "qapi-event.h"
|
#include "qapi-event.h"
|
||||||
|
|
||||||
|
@ -297,15 +296,7 @@ void acpi_table_add(const QemuOpts *opts, Error **errp)
|
||||||
out:
|
out:
|
||||||
g_free(blob);
|
g_free(blob);
|
||||||
g_strfreev(pathnames);
|
g_strfreev(pathnames);
|
||||||
|
qapi_free_AcpiTableOptions(hdrs);
|
||||||
if (hdrs != NULL) {
|
|
||||||
QapiDeallocVisitor *dv;
|
|
||||||
|
|
||||||
dv = qapi_dealloc_visitor_new();
|
|
||||||
visit_type_AcpiTableOptions(qapi_dealloc_get_visitor(dv), NULL, &hdrs,
|
|
||||||
NULL);
|
|
||||||
qapi_dealloc_visitor_cleanup(dv);
|
|
||||||
}
|
|
||||||
|
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -842,14 +842,16 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
|
||||||
{
|
{
|
||||||
ChannelState *s = (ChannelState *)dev;
|
ChannelState *s = (ChannelState *)dev;
|
||||||
int qcode, keycode;
|
int qcode, keycode;
|
||||||
|
InputKeyEvent *key;
|
||||||
|
|
||||||
assert(evt->type == INPUT_EVENT_KIND_KEY);
|
assert(evt->type == INPUT_EVENT_KIND_KEY);
|
||||||
qcode = qemu_input_key_value_to_qcode(evt->u.key->key);
|
key = evt->u.key;
|
||||||
|
qcode = qemu_input_key_value_to_qcode(key->key);
|
||||||
trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
|
trace_escc_sunkbd_event_in(qcode, QKeyCode_lookup[qcode],
|
||||||
evt->u.key->down);
|
key->down);
|
||||||
|
|
||||||
if (qcode == Q_KEY_CODE_CAPS_LOCK) {
|
if (qcode == Q_KEY_CODE_CAPS_LOCK) {
|
||||||
if (evt->u.key->down) {
|
if (key->down) {
|
||||||
s->caps_lock_mode ^= 1;
|
s->caps_lock_mode ^= 1;
|
||||||
if (s->caps_lock_mode == 2) {
|
if (s->caps_lock_mode == 2) {
|
||||||
return; /* Drop second press */
|
return; /* Drop second press */
|
||||||
|
@ -863,7 +865,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qcode == Q_KEY_CODE_NUM_LOCK) {
|
if (qcode == Q_KEY_CODE_NUM_LOCK) {
|
||||||
if (evt->u.key->down) {
|
if (key->down) {
|
||||||
s->num_lock_mode ^= 1;
|
s->num_lock_mode ^= 1;
|
||||||
if (s->num_lock_mode == 2) {
|
if (s->num_lock_mode == 2) {
|
||||||
return; /* Drop second press */
|
return; /* Drop second press */
|
||||||
|
@ -877,7 +879,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
|
||||||
}
|
}
|
||||||
|
|
||||||
keycode = qcode_to_keycode[qcode];
|
keycode = qcode_to_keycode[qcode];
|
||||||
if (!evt->u.key->down) {
|
if (!key->down) {
|
||||||
keycode |= 0x80;
|
keycode |= 0x80;
|
||||||
}
|
}
|
||||||
trace_escc_sunkbd_event_out(keycode);
|
trace_escc_sunkbd_event_out(keycode);
|
||||||
|
|
|
@ -116,37 +116,42 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
|
||||||
};
|
};
|
||||||
HIDState *hs = (HIDState *)dev;
|
HIDState *hs = (HIDState *)dev;
|
||||||
HIDPointerEvent *e;
|
HIDPointerEvent *e;
|
||||||
|
InputMoveEvent *move;
|
||||||
|
InputBtnEvent *btn;
|
||||||
|
|
||||||
assert(hs->n < QUEUE_LENGTH);
|
assert(hs->n < QUEUE_LENGTH);
|
||||||
e = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK];
|
e = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK];
|
||||||
|
|
||||||
switch (evt->type) {
|
switch (evt->type) {
|
||||||
case INPUT_EVENT_KIND_REL:
|
case INPUT_EVENT_KIND_REL:
|
||||||
if (evt->u.rel->axis == INPUT_AXIS_X) {
|
move = evt->u.rel;
|
||||||
e->xdx += evt->u.rel->value;
|
if (move->axis == INPUT_AXIS_X) {
|
||||||
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
|
e->xdx += move->value;
|
||||||
e->ydy += evt->u.rel->value;
|
} else if (move->axis == INPUT_AXIS_Y) {
|
||||||
|
e->ydy += move->value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INPUT_EVENT_KIND_ABS:
|
case INPUT_EVENT_KIND_ABS:
|
||||||
if (evt->u.rel->axis == INPUT_AXIS_X) {
|
move = evt->u.abs;
|
||||||
e->xdx = evt->u.rel->value;
|
if (move->axis == INPUT_AXIS_X) {
|
||||||
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
|
e->xdx = move->value;
|
||||||
e->ydy = evt->u.rel->value;
|
} else if (move->axis == INPUT_AXIS_Y) {
|
||||||
|
e->ydy = move->value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INPUT_EVENT_KIND_BTN:
|
case INPUT_EVENT_KIND_BTN:
|
||||||
if (evt->u.btn->down) {
|
btn = evt->u.btn;
|
||||||
e->buttons_state |= bmap[evt->u.btn->button];
|
if (btn->down) {
|
||||||
if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
|
e->buttons_state |= bmap[btn->button];
|
||||||
|
if (btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||||
e->dz--;
|
e->dz--;
|
||||||
} else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
} else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||||
e->dz++;
|
e->dz++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
e->buttons_state &= ~bmap[evt->u.btn->button];
|
e->buttons_state &= ~bmap[btn->button];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -223,9 +228,10 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
|
||||||
HIDState *hs = (HIDState *)dev;
|
HIDState *hs = (HIDState *)dev;
|
||||||
int scancodes[3], i, count;
|
int scancodes[3], i, count;
|
||||||
int slot;
|
int slot;
|
||||||
|
InputKeyEvent *key = evt->u.key;
|
||||||
|
|
||||||
count = qemu_input_key_value_to_scancode(evt->u.key->key,
|
count = qemu_input_key_value_to_scancode(key->key,
|
||||||
evt->u.key->down,
|
key->down,
|
||||||
scancodes);
|
scancodes);
|
||||||
if (hs->n + count > QUEUE_LENGTH) {
|
if (hs->n + count > QUEUE_LENGTH) {
|
||||||
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
|
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
|
||||||
|
|
|
@ -182,10 +182,11 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
|
||||||
{
|
{
|
||||||
PS2KbdState *s = (PS2KbdState *)dev;
|
PS2KbdState *s = (PS2KbdState *)dev;
|
||||||
int scancodes[3], i, count;
|
int scancodes[3], i, count;
|
||||||
|
InputKeyEvent *key = evt->u.key;
|
||||||
|
|
||||||
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
|
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
|
||||||
count = qemu_input_key_value_to_scancode(evt->u.key->key,
|
count = qemu_input_key_value_to_scancode(key->key,
|
||||||
evt->u.key->down,
|
key->down,
|
||||||
scancodes);
|
scancodes);
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
ps2_put_keycode(s, scancodes[i]);
|
ps2_put_keycode(s, scancodes[i]);
|
||||||
|
@ -389,6 +390,8 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
|
||||||
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
||||||
};
|
};
|
||||||
PS2MouseState *s = (PS2MouseState *)dev;
|
PS2MouseState *s = (PS2MouseState *)dev;
|
||||||
|
InputMoveEvent *move;
|
||||||
|
InputBtnEvent *btn;
|
||||||
|
|
||||||
/* check if deltas are recorded when disabled */
|
/* check if deltas are recorded when disabled */
|
||||||
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
|
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
|
||||||
|
@ -396,23 +399,25 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
|
||||||
|
|
||||||
switch (evt->type) {
|
switch (evt->type) {
|
||||||
case INPUT_EVENT_KIND_REL:
|
case INPUT_EVENT_KIND_REL:
|
||||||
if (evt->u.rel->axis == INPUT_AXIS_X) {
|
move = evt->u.rel;
|
||||||
s->mouse_dx += evt->u.rel->value;
|
if (move->axis == INPUT_AXIS_X) {
|
||||||
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
|
s->mouse_dx += move->value;
|
||||||
s->mouse_dy -= evt->u.rel->value;
|
} else if (move->axis == INPUT_AXIS_Y) {
|
||||||
|
s->mouse_dy -= move->value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case INPUT_EVENT_KIND_BTN:
|
case INPUT_EVENT_KIND_BTN:
|
||||||
if (evt->u.btn->down) {
|
btn = evt->u.btn;
|
||||||
s->mouse_buttons |= bmap[evt->u.btn->button];
|
if (btn->down) {
|
||||||
if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
|
s->mouse_buttons |= bmap[btn->button];
|
||||||
|
if (btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||||
s->mouse_dz--;
|
s->mouse_dz--;
|
||||||
} else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
} else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||||
s->mouse_dz++;
|
s->mouse_dz++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s->mouse_buttons &= ~bmap[evt->u.btn->button];
|
s->mouse_buttons &= ~bmap[btn->button];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -191,46 +191,53 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
|
||||||
VirtIOInput *vinput = VIRTIO_INPUT(dev);
|
VirtIOInput *vinput = VIRTIO_INPUT(dev);
|
||||||
virtio_input_event event;
|
virtio_input_event event;
|
||||||
int qcode;
|
int qcode;
|
||||||
|
InputKeyEvent *key;
|
||||||
|
InputMoveEvent *move;
|
||||||
|
InputBtnEvent *btn;
|
||||||
|
|
||||||
switch (evt->type) {
|
switch (evt->type) {
|
||||||
case INPUT_EVENT_KIND_KEY:
|
case INPUT_EVENT_KIND_KEY:
|
||||||
qcode = qemu_input_key_value_to_qcode(evt->u.key->key);
|
key = evt->u.key;
|
||||||
|
qcode = qemu_input_key_value_to_qcode(key->key);
|
||||||
if (qcode && keymap_qcode[qcode]) {
|
if (qcode && keymap_qcode[qcode]) {
|
||||||
event.type = cpu_to_le16(EV_KEY);
|
event.type = cpu_to_le16(EV_KEY);
|
||||||
event.code = cpu_to_le16(keymap_qcode[qcode]);
|
event.code = cpu_to_le16(keymap_qcode[qcode]);
|
||||||
event.value = cpu_to_le32(evt->u.key->down ? 1 : 0);
|
event.value = cpu_to_le32(key->down ? 1 : 0);
|
||||||
virtio_input_send(vinput, &event);
|
virtio_input_send(vinput, &event);
|
||||||
} else {
|
} else {
|
||||||
if (evt->u.key->down) {
|
if (key->down) {
|
||||||
fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
|
fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
|
||||||
qcode, QKeyCode_lookup[qcode]);
|
qcode, QKeyCode_lookup[qcode]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_BTN:
|
case INPUT_EVENT_KIND_BTN:
|
||||||
if (keymap_button[evt->u.btn->button]) {
|
btn = evt->u.btn;
|
||||||
|
if (keymap_button[btn->button]) {
|
||||||
event.type = cpu_to_le16(EV_KEY);
|
event.type = cpu_to_le16(EV_KEY);
|
||||||
event.code = cpu_to_le16(keymap_button[evt->u.btn->button]);
|
event.code = cpu_to_le16(keymap_button[btn->button]);
|
||||||
event.value = cpu_to_le32(evt->u.btn->down ? 1 : 0);
|
event.value = cpu_to_le32(btn->down ? 1 : 0);
|
||||||
virtio_input_send(vinput, &event);
|
virtio_input_send(vinput, &event);
|
||||||
} else {
|
} else {
|
||||||
if (evt->u.btn->down) {
|
if (btn->down) {
|
||||||
fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
|
fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
|
||||||
evt->u.btn->button,
|
btn->button,
|
||||||
InputButton_lookup[evt->u.btn->button]);
|
InputButton_lookup[btn->button]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_REL:
|
case INPUT_EVENT_KIND_REL:
|
||||||
|
move = evt->u.rel;
|
||||||
event.type = cpu_to_le16(EV_REL);
|
event.type = cpu_to_le16(EV_REL);
|
||||||
event.code = cpu_to_le16(axismap_rel[evt->u.rel->axis]);
|
event.code = cpu_to_le16(axismap_rel[move->axis]);
|
||||||
event.value = cpu_to_le32(evt->u.rel->value);
|
event.value = cpu_to_le32(move->value);
|
||||||
virtio_input_send(vinput, &event);
|
virtio_input_send(vinput, &event);
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_ABS:
|
case INPUT_EVENT_KIND_ABS:
|
||||||
|
move = evt->u.abs;
|
||||||
event.type = cpu_to_le16(EV_ABS);
|
event.type = cpu_to_le16(EV_ABS);
|
||||||
event.code = cpu_to_le16(axismap_abs[evt->u.abs->axis]);
|
event.code = cpu_to_le16(axismap_abs[move->axis]);
|
||||||
event.value = cpu_to_le32(evt->u.abs->value);
|
event.value = cpu_to_le32(move->value);
|
||||||
virtio_input_send(vinput, &event);
|
virtio_input_send(vinput, &event);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
31
net/net.c
31
net/net.c
|
@ -42,7 +42,6 @@
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
#include "qapi-visit.h"
|
#include "qapi-visit.h"
|
||||||
#include "qapi/opts-visitor.h"
|
#include "qapi/opts-visitor.h"
|
||||||
#include "qapi/dealloc-visitor.h"
|
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "net/filter.h"
|
#include "net/filter.h"
|
||||||
#include "qapi/string-output-visitor.h"
|
#include "qapi/string-output-visitor.h"
|
||||||
|
@ -1043,38 +1042,28 @@ static int net_client_init1(const void *object, int is_netdev, Error **errp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void net_visit(Visitor *v, int is_netdev, void **object, Error **errp)
|
|
||||||
{
|
|
||||||
if (is_netdev) {
|
|
||||||
visit_type_Netdev(v, NULL, (Netdev **)object, errp);
|
|
||||||
} else {
|
|
||||||
visit_type_NetLegacy(v, NULL, (NetLegacy **)object, errp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
|
int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
|
||||||
{
|
{
|
||||||
void *object = NULL;
|
void *object = NULL;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
OptsVisitor *ov = opts_visitor_new(opts);
|
||||||
|
Visitor *v = opts_get_visitor(ov);
|
||||||
|
|
||||||
{
|
if (is_netdev) {
|
||||||
OptsVisitor *ov = opts_visitor_new(opts);
|
visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
|
||||||
|
} else {
|
||||||
net_visit(opts_get_visitor(ov), is_netdev, &object, &err);
|
visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
|
||||||
opts_visitor_cleanup(ov);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
ret = net_client_init1(object, is_netdev, &err);
|
ret = net_client_init1(object, is_netdev, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object) {
|
if (is_netdev) {
|
||||||
QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();
|
qapi_free_Netdev(object);
|
||||||
|
} else {
|
||||||
net_visit(qapi_dealloc_get_visitor(dv), is_netdev, &object, NULL);
|
qapi_free_NetLegacy(object);
|
||||||
qapi_dealloc_visitor_cleanup(dv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
|
|
9
numa.c
9
numa.c
|
@ -31,7 +31,6 @@
|
||||||
#include "include/exec/cpu-common.h" /* for RAM_ADDR_FMT */
|
#include "include/exec/cpu-common.h" /* for RAM_ADDR_FMT */
|
||||||
#include "qapi-visit.h"
|
#include "qapi-visit.h"
|
||||||
#include "qapi/opts-visitor.h"
|
#include "qapi/opts-visitor.h"
|
||||||
#include "qapi/dealloc-visitor.h"
|
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "sysemu/hostmem.h"
|
#include "sysemu/hostmem.h"
|
||||||
#include "qmp-commands.h"
|
#include "qmp-commands.h"
|
||||||
|
@ -243,13 +242,7 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
|
||||||
|
|
||||||
error:
|
error:
|
||||||
error_report_err(err);
|
error_report_err(err);
|
||||||
|
qapi_free_NumaOptions(object);
|
||||||
if (object) {
|
|
||||||
QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();
|
|
||||||
visit_type_NumaOptions(qapi_dealloc_get_visitor(dv), NULL, &object,
|
|
||||||
NULL);
|
|
||||||
qapi_dealloc_visitor_cleanup(dv);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3323,23 +3323,20 @@
|
||||||
#
|
#
|
||||||
# Since: 1.4 (testdev since 2.2)
|
# Since: 1.4 (testdev since 2.2)
|
||||||
##
|
##
|
||||||
{ 'struct': 'ChardevDummy', 'data': { },
|
|
||||||
'base': 'ChardevCommon' }
|
|
||||||
|
|
||||||
{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
|
{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
|
||||||
'serial' : 'ChardevHostdev',
|
'serial' : 'ChardevHostdev',
|
||||||
'parallel': 'ChardevHostdev',
|
'parallel': 'ChardevHostdev',
|
||||||
'pipe' : 'ChardevHostdev',
|
'pipe' : 'ChardevHostdev',
|
||||||
'socket' : 'ChardevSocket',
|
'socket' : 'ChardevSocket',
|
||||||
'udp' : 'ChardevUdp',
|
'udp' : 'ChardevUdp',
|
||||||
'pty' : 'ChardevDummy',
|
'pty' : 'ChardevCommon',
|
||||||
'null' : 'ChardevDummy',
|
'null' : 'ChardevCommon',
|
||||||
'mux' : 'ChardevMux',
|
'mux' : 'ChardevMux',
|
||||||
'msmouse': 'ChardevDummy',
|
'msmouse': 'ChardevCommon',
|
||||||
'braille': 'ChardevDummy',
|
'braille': 'ChardevCommon',
|
||||||
'testdev': 'ChardevDummy',
|
'testdev': 'ChardevCommon',
|
||||||
'stdio' : 'ChardevStdio',
|
'stdio' : 'ChardevStdio',
|
||||||
'console': 'ChardevDummy',
|
'console': 'ChardevCommon',
|
||||||
'spicevmc' : 'ChardevSpiceChannel',
|
'spicevmc' : 'ChardevSpiceChannel',
|
||||||
'spiceport' : 'ChardevSpicePort',
|
'spiceport' : 'ChardevSpicePort',
|
||||||
'vc' : 'ChardevVC',
|
'vc' : 'ChardevVC',
|
||||||
|
|
179
qemu-char.c
179
qemu-char.c
|
@ -420,7 +420,7 @@ static CharDriverState *qemu_chr_open_null(const char *id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.null);
|
ChardevCommon *common = backend->u.null;
|
||||||
|
|
||||||
chr = qemu_chr_alloc(common, errp);
|
chr = qemu_chr_alloc(common, errp);
|
||||||
if (!chr) {
|
if (!chr) {
|
||||||
|
@ -724,7 +724,7 @@ static CharDriverState *qemu_chr_open_mux(const char *id,
|
||||||
ChardevMux *mux = backend->u.mux;
|
ChardevMux *mux = backend->u.mux;
|
||||||
CharDriverState *chr, *drv;
|
CharDriverState *chr, *drv;
|
||||||
MuxDriver *d;
|
MuxDriver *d;
|
||||||
ChardevCommon *common = qapi_ChardevMux_base(backend->u.mux);
|
ChardevCommon *common = qapi_ChardevMux_base(mux);
|
||||||
|
|
||||||
drv = qemu_chr_find(mux->chardev);
|
drv = qemu_chr_find(mux->chardev);
|
||||||
if (drv == NULL) {
|
if (drv == NULL) {
|
||||||
|
@ -1043,7 +1043,7 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
|
||||||
char *filename_in;
|
char *filename_in;
|
||||||
char *filename_out;
|
char *filename_out;
|
||||||
const char *filename = opts->device;
|
const char *filename = opts->device;
|
||||||
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.pipe);
|
ChardevCommon *common = qapi_ChardevHostdev_base(opts);
|
||||||
|
|
||||||
|
|
||||||
filename_in = g_strdup_printf("%s.in", filename);
|
filename_in = g_strdup_printf("%s.in", filename);
|
||||||
|
@ -1123,7 +1123,7 @@ static CharDriverState *qemu_chr_open_stdio(const char *id,
|
||||||
ChardevStdio *opts = backend->u.stdio;
|
ChardevStdio *opts = backend->u.stdio;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
ChardevCommon *common = qapi_ChardevStdio_base(backend->u.stdio);
|
ChardevCommon *common = qapi_ChardevStdio_base(opts);
|
||||||
|
|
||||||
if (is_daemonized()) {
|
if (is_daemonized()) {
|
||||||
error_setg(errp, "cannot use stdio with -daemonize");
|
error_setg(errp, "cannot use stdio with -daemonize");
|
||||||
|
@ -1366,7 +1366,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
|
||||||
PtyCharDriver *s;
|
PtyCharDriver *s;
|
||||||
int master_fd, slave_fd;
|
int master_fd, slave_fd;
|
||||||
char pty_name[PATH_MAX];
|
char pty_name[PATH_MAX];
|
||||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.pty);
|
ChardevCommon *common = backend->u.pty;
|
||||||
|
|
||||||
master_fd = qemu_openpty_raw(&slave_fd, pty_name);
|
master_fd = qemu_openpty_raw(&slave_fd, pty_name);
|
||||||
if (master_fd < 0) {
|
if (master_fd < 0) {
|
||||||
|
@ -2141,7 +2141,7 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
|
||||||
const char *filename = opts->device;
|
const char *filename = opts->device;
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
WinCharState *s;
|
WinCharState *s;
|
||||||
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.pipe);
|
ChardevCommon *common = qapi_ChardevHostdev_base(opts);
|
||||||
|
|
||||||
chr = qemu_chr_alloc(common, errp);
|
chr = qemu_chr_alloc(common, errp);
|
||||||
if (!chr) {
|
if (!chr) {
|
||||||
|
@ -2183,7 +2183,7 @@ static CharDriverState *qemu_chr_open_win_con(const char *id,
|
||||||
ChardevReturn *ret,
|
ChardevReturn *ret,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.console);
|
ChardevCommon *common = backend->u.console;
|
||||||
return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE),
|
return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE),
|
||||||
common, errp);
|
common, errp);
|
||||||
}
|
}
|
||||||
|
@ -3216,7 +3216,7 @@ static CharDriverState *qemu_chr_open_ringbuf(const char *id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevRingbuf *opts = backend->u.ringbuf;
|
ChardevRingbuf *opts = backend->u.ringbuf;
|
||||||
ChardevCommon *common = qapi_ChardevRingbuf_base(backend->u.ringbuf);
|
ChardevCommon *common = qapi_ChardevRingbuf_base(opts);
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
RingBufCharDriver *d;
|
RingBufCharDriver *d;
|
||||||
|
|
||||||
|
@ -3506,26 +3506,29 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
const char *path = qemu_opt_get(opts, "path");
|
const char *path = qemu_opt_get(opts, "path");
|
||||||
|
ChardevFile *file;
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
error_setg(errp, "chardev: file: no filename given");
|
error_setg(errp, "chardev: file: no filename given");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backend->u.file = g_new0(ChardevFile, 1);
|
file = backend->u.file = g_new0(ChardevFile, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevFile_base(backend->u.file));
|
qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));
|
||||||
backend->u.file->out = g_strdup(path);
|
file->out = g_strdup(path);
|
||||||
|
|
||||||
backend->u.file->has_append = true;
|
file->has_append = true;
|
||||||
backend->u.file->append = qemu_opt_get_bool(opts, "append", false);
|
file->append = qemu_opt_get_bool(opts, "append", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
|
static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
backend->u.stdio = g_new0(ChardevStdio, 1);
|
ChardevStdio *stdio;
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevStdio_base(backend->u.stdio));
|
|
||||||
backend->u.stdio->has_signal = true;
|
stdio = backend->u.stdio = g_new0(ChardevStdio, 1);
|
||||||
backend->u.stdio->signal = qemu_opt_get_bool(opts, "signal", true);
|
qemu_chr_parse_common(opts, qapi_ChardevStdio_base(stdio));
|
||||||
|
stdio->has_signal = true;
|
||||||
|
stdio->signal = qemu_opt_get_bool(opts, "signal", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CHARDEV_SERIAL
|
#ifdef HAVE_CHARDEV_SERIAL
|
||||||
|
@ -3533,14 +3536,15 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
const char *device = qemu_opt_get(opts, "path");
|
const char *device = qemu_opt_get(opts, "path");
|
||||||
|
ChardevHostdev *serial;
|
||||||
|
|
||||||
if (device == NULL) {
|
if (device == NULL) {
|
||||||
error_setg(errp, "chardev: serial/tty: no device path given");
|
error_setg(errp, "chardev: serial/tty: no device path given");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backend->u.serial = g_new0(ChardevHostdev, 1);
|
serial = backend->u.serial = g_new0(ChardevHostdev, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.serial));
|
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));
|
||||||
backend->u.serial->device = g_strdup(device);
|
serial->device = g_strdup(device);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3549,14 +3553,15 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
const char *device = qemu_opt_get(opts, "path");
|
const char *device = qemu_opt_get(opts, "path");
|
||||||
|
ChardevHostdev *parallel;
|
||||||
|
|
||||||
if (device == NULL) {
|
if (device == NULL) {
|
||||||
error_setg(errp, "chardev: parallel: no device path given");
|
error_setg(errp, "chardev: parallel: no device path given");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backend->u.parallel = g_new0(ChardevHostdev, 1);
|
parallel = backend->u.parallel = g_new0(ChardevHostdev, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.parallel));
|
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(parallel));
|
||||||
backend->u.parallel->device = g_strdup(device);
|
parallel->device = g_strdup(device);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3564,28 +3569,30 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
const char *device = qemu_opt_get(opts, "path");
|
const char *device = qemu_opt_get(opts, "path");
|
||||||
|
ChardevHostdev *dev;
|
||||||
|
|
||||||
if (device == NULL) {
|
if (device == NULL) {
|
||||||
error_setg(errp, "chardev: pipe: no device path given");
|
error_setg(errp, "chardev: pipe: no device path given");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backend->u.pipe = g_new0(ChardevHostdev, 1);
|
dev = backend->u.pipe = g_new0(ChardevHostdev, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.pipe));
|
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));
|
||||||
backend->u.pipe->device = g_strdup(device);
|
dev->device = g_strdup(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
|
static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
|
ChardevRingbuf *ringbuf;
|
||||||
|
|
||||||
backend->u.ringbuf = g_new0(ChardevRingbuf, 1);
|
ringbuf = backend->u.ringbuf = g_new0(ChardevRingbuf, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(backend->u.ringbuf));
|
qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));
|
||||||
|
|
||||||
val = qemu_opt_get_size(opts, "size", 0);
|
val = qemu_opt_get_size(opts, "size", 0);
|
||||||
if (val != 0) {
|
if (val != 0) {
|
||||||
backend->u.ringbuf->has_size = true;
|
ringbuf->has_size = true;
|
||||||
backend->u.ringbuf->size = val;
|
ringbuf->size = val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3593,14 +3600,15 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
const char *chardev = qemu_opt_get(opts, "chardev");
|
const char *chardev = qemu_opt_get(opts, "chardev");
|
||||||
|
ChardevMux *mux;
|
||||||
|
|
||||||
if (chardev == NULL) {
|
if (chardev == NULL) {
|
||||||
error_setg(errp, "chardev: mux: no chardev given");
|
error_setg(errp, "chardev: mux: no chardev given");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
backend->u.mux = g_new0(ChardevMux, 1);
|
mux = backend->u.mux = g_new0(ChardevMux, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevMux_base(backend->u.mux));
|
qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux));
|
||||||
backend->u.mux->chardev = g_strdup(chardev);
|
mux->chardev = g_strdup(chardev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
||||||
|
@ -3616,6 +3624,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
||||||
const char *port = qemu_opt_get(opts, "port");
|
const char *port = qemu_opt_get(opts, "port");
|
||||||
const char *tls_creds = qemu_opt_get(opts, "tls-creds");
|
const char *tls_creds = qemu_opt_get(opts, "tls-creds");
|
||||||
SocketAddress *addr;
|
SocketAddress *addr;
|
||||||
|
ChardevSocket *sock;
|
||||||
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
if (!host) {
|
if (!host) {
|
||||||
|
@ -3633,39 +3642,42 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backend->u.socket = g_new0(ChardevSocket, 1);
|
sock = backend->u.socket = g_new0(ChardevSocket, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevSocket_base(backend->u.socket));
|
qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
|
||||||
|
|
||||||
backend->u.socket->has_nodelay = true;
|
sock->has_nodelay = true;
|
||||||
backend->u.socket->nodelay = do_nodelay;
|
sock->nodelay = do_nodelay;
|
||||||
backend->u.socket->has_server = true;
|
sock->has_server = true;
|
||||||
backend->u.socket->server = is_listen;
|
sock->server = is_listen;
|
||||||
backend->u.socket->has_telnet = true;
|
sock->has_telnet = true;
|
||||||
backend->u.socket->telnet = is_telnet;
|
sock->telnet = is_telnet;
|
||||||
backend->u.socket->has_wait = true;
|
sock->has_wait = true;
|
||||||
backend->u.socket->wait = is_waitconnect;
|
sock->wait = is_waitconnect;
|
||||||
backend->u.socket->has_reconnect = true;
|
sock->has_reconnect = true;
|
||||||
backend->u.socket->reconnect = reconnect;
|
sock->reconnect = reconnect;
|
||||||
backend->u.socket->tls_creds = g_strdup(tls_creds);
|
sock->tls_creds = g_strdup(tls_creds);
|
||||||
|
|
||||||
addr = g_new0(SocketAddress, 1);
|
addr = g_new0(SocketAddress, 1);
|
||||||
if (path) {
|
if (path) {
|
||||||
|
UnixSocketAddress *q_unix;
|
||||||
addr->type = SOCKET_ADDRESS_KIND_UNIX;
|
addr->type = SOCKET_ADDRESS_KIND_UNIX;
|
||||||
addr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
q_unix = addr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||||
addr->u.q_unix->path = g_strdup(path);
|
q_unix->path = g_strdup(path);
|
||||||
} else {
|
} else {
|
||||||
addr->type = SOCKET_ADDRESS_KIND_INET;
|
addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
addr->u.inet = g_new0(InetSocketAddress, 1);
|
addr->u.inet = g_new(InetSocketAddress, 1);
|
||||||
addr->u.inet->host = g_strdup(host);
|
*addr->u.inet = (InetSocketAddress) {
|
||||||
addr->u.inet->port = g_strdup(port);
|
.host = g_strdup(host),
|
||||||
addr->u.inet->has_to = qemu_opt_get(opts, "to");
|
.port = g_strdup(port),
|
||||||
addr->u.inet->to = qemu_opt_get_number(opts, "to", 0);
|
.has_to = qemu_opt_get(opts, "to"),
|
||||||
addr->u.inet->has_ipv4 = qemu_opt_get(opts, "ipv4");
|
.to = qemu_opt_get_number(opts, "to", 0),
|
||||||
addr->u.inet->ipv4 = qemu_opt_get_bool(opts, "ipv4", 0);
|
.has_ipv4 = qemu_opt_get(opts, "ipv4"),
|
||||||
addr->u.inet->has_ipv6 = qemu_opt_get(opts, "ipv6");
|
.ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
|
||||||
addr->u.inet->ipv6 = qemu_opt_get_bool(opts, "ipv6", 0);
|
.has_ipv6 = qemu_opt_get(opts, "ipv6"),
|
||||||
|
.ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
backend->u.socket->addr = addr;
|
sock->addr = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
|
static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
|
||||||
|
@ -3677,6 +3689,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
|
||||||
const char *localport = qemu_opt_get(opts, "localport");
|
const char *localport = qemu_opt_get(opts, "localport");
|
||||||
bool has_local = false;
|
bool has_local = false;
|
||||||
SocketAddress *addr;
|
SocketAddress *addr;
|
||||||
|
ChardevUdp *udp;
|
||||||
|
|
||||||
if (host == NULL || strlen(host) == 0) {
|
if (host == NULL || strlen(host) == 0) {
|
||||||
host = "localhost";
|
host = "localhost";
|
||||||
|
@ -3696,28 +3709,32 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
|
||||||
has_local = true;
|
has_local = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
backend->u.udp = g_new0(ChardevUdp, 1);
|
udp = backend->u.udp = g_new0(ChardevUdp, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevUdp_base(backend->u.udp));
|
qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));
|
||||||
|
|
||||||
addr = g_new0(SocketAddress, 1);
|
addr = g_new0(SocketAddress, 1);
|
||||||
addr->type = SOCKET_ADDRESS_KIND_INET;
|
addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
addr->u.inet = g_new0(InetSocketAddress, 1);
|
addr->u.inet = g_new(InetSocketAddress, 1);
|
||||||
addr->u.inet->host = g_strdup(host);
|
*addr->u.inet = (InetSocketAddress) {
|
||||||
addr->u.inet->port = g_strdup(port);
|
.host = g_strdup(host),
|
||||||
addr->u.inet->has_ipv4 = qemu_opt_get(opts, "ipv4");
|
.port = g_strdup(port),
|
||||||
addr->u.inet->ipv4 = qemu_opt_get_bool(opts, "ipv4", 0);
|
.has_ipv4 = qemu_opt_get(opts, "ipv4"),
|
||||||
addr->u.inet->has_ipv6 = qemu_opt_get(opts, "ipv6");
|
.ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
|
||||||
addr->u.inet->ipv6 = qemu_opt_get_bool(opts, "ipv6", 0);
|
.has_ipv6 = qemu_opt_get(opts, "ipv6"),
|
||||||
backend->u.udp->remote = addr;
|
.ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
|
||||||
|
};
|
||||||
|
udp->remote = addr;
|
||||||
|
|
||||||
if (has_local) {
|
if (has_local) {
|
||||||
backend->u.udp->has_local = true;
|
udp->has_local = true;
|
||||||
addr = g_new0(SocketAddress, 1);
|
addr = g_new0(SocketAddress, 1);
|
||||||
addr->type = SOCKET_ADDRESS_KIND_INET;
|
addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
addr->u.inet = g_new0(InetSocketAddress, 1);
|
addr->u.inet = g_new(InetSocketAddress, 1);
|
||||||
addr->u.inet->host = g_strdup(localaddr);
|
*addr->u.inet = (InetSocketAddress) {
|
||||||
addr->u.inet->port = g_strdup(localport);
|
.host = g_strdup(localaddr),
|
||||||
backend->u.udp->local = addr;
|
.port = g_strdup(localport),
|
||||||
|
};
|
||||||
|
udp->local = addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3800,7 +3817,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
|
||||||
} else {
|
} else {
|
||||||
ChardevCommon *cc = g_new0(ChardevCommon, 1);
|
ChardevCommon *cc = g_new0(ChardevCommon, 1);
|
||||||
qemu_chr_parse_common(opts, cc);
|
qemu_chr_parse_common(opts, cc);
|
||||||
backend->u.data = cc;
|
backend->u.null = cc; /* Any ChardevCommon member would work */
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qmp_chardev_add(bid ? bid : id, backend, errp);
|
ret = qmp_chardev_add(bid ? bid : id, backend, errp);
|
||||||
|
@ -4128,7 +4145,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevFile *file = backend->u.file;
|
ChardevFile *file = backend->u.file;
|
||||||
ChardevCommon *common = qapi_ChardevFile_base(backend->u.file);
|
ChardevCommon *common = qapi_ChardevFile_base(file);
|
||||||
HANDLE out;
|
HANDLE out;
|
||||||
|
|
||||||
if (file->has_in) {
|
if (file->has_in) {
|
||||||
|
@ -4151,7 +4168,7 @@ static CharDriverState *qmp_chardev_open_serial(const char *id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevHostdev *serial = backend->u.serial;
|
ChardevHostdev *serial = backend->u.serial;
|
||||||
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.serial);
|
ChardevCommon *common = qapi_ChardevHostdev_base(serial);
|
||||||
return qemu_chr_open_win_path(serial->device, common, errp);
|
return qemu_chr_open_win_path(serial->device, common, errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4175,7 +4192,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevFile *file = backend->u.file;
|
ChardevFile *file = backend->u.file;
|
||||||
ChardevCommon *common = qapi_ChardevFile_base(backend->u.file);
|
ChardevCommon *common = qapi_ChardevFile_base(file);
|
||||||
int flags, in = -1, out;
|
int flags, in = -1, out;
|
||||||
|
|
||||||
flags = O_WRONLY | O_CREAT | O_BINARY;
|
flags = O_WRONLY | O_CREAT | O_BINARY;
|
||||||
|
@ -4209,7 +4226,7 @@ static CharDriverState *qmp_chardev_open_serial(const char *id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevHostdev *serial = backend->u.serial;
|
ChardevHostdev *serial = backend->u.serial;
|
||||||
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.serial);
|
ChardevCommon *common = qapi_ChardevHostdev_base(serial);
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp);
|
fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp);
|
||||||
|
@ -4228,7 +4245,7 @@ static CharDriverState *qmp_chardev_open_parallel(const char *id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevHostdev *parallel = backend->u.parallel;
|
ChardevHostdev *parallel = backend->u.parallel;
|
||||||
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.parallel);
|
ChardevCommon *common = qapi_ChardevHostdev_base(parallel);
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
|
fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
|
||||||
|
@ -4280,7 +4297,7 @@ static CharDriverState *qmp_chardev_open_socket(const char *id,
|
||||||
bool is_telnet = sock->has_telnet ? sock->telnet : false;
|
bool is_telnet = sock->has_telnet ? sock->telnet : false;
|
||||||
bool is_waitconnect = sock->has_wait ? sock->wait : false;
|
bool is_waitconnect = sock->has_wait ? sock->wait : false;
|
||||||
int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
|
int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
|
||||||
ChardevCommon *common = qapi_ChardevSocket_base(backend->u.socket);
|
ChardevCommon *common = qapi_ChardevSocket_base(sock);
|
||||||
|
|
||||||
chr = qemu_chr_alloc(common, errp);
|
chr = qemu_chr_alloc(common, errp);
|
||||||
if (!chr) {
|
if (!chr) {
|
||||||
|
@ -4380,7 +4397,7 @@ static CharDriverState *qmp_chardev_open_udp(const char *id,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
ChardevUdp *udp = backend->u.udp;
|
ChardevUdp *udp = backend->u.udp;
|
||||||
ChardevCommon *common = qapi_ChardevUdp_base(backend->u.udp);
|
ChardevCommon *common = qapi_ChardevUdp_base(udp);
|
||||||
QIOChannelSocket *sioc = qio_channel_socket_new();
|
QIOChannelSocket *sioc = qio_channel_socket_new();
|
||||||
|
|
||||||
if (qio_channel_socket_dgram_sync(sioc,
|
if (qio_channel_socket_dgram_sync(sioc,
|
||||||
|
|
|
@ -380,13 +380,14 @@ static SocketAddress *nbd_build_socket_address(const char *sockpath,
|
||||||
saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||||
saddr->u.q_unix->path = g_strdup(sockpath);
|
saddr->u.q_unix->path = g_strdup(sockpath);
|
||||||
} else {
|
} else {
|
||||||
|
InetSocketAddress *inet;
|
||||||
saddr->type = SOCKET_ADDRESS_KIND_INET;
|
saddr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
saddr->u.inet = g_new0(InetSocketAddress, 1);
|
inet = saddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||||
saddr->u.inet->host = g_strdup(bindto);
|
inet->host = g_strdup(bindto);
|
||||||
if (port) {
|
if (port) {
|
||||||
saddr->u.inet->port = g_strdup(port);
|
inet->port = g_strdup(port);
|
||||||
} else {
|
} else {
|
||||||
saddr->u.inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
|
inet->port = g_strdup_printf("%d", NBD_DEFAULT_PORT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,20 +47,24 @@ static InputEvent *qapi_clone_InputEvent(InputEvent *src)
|
||||||
|
|
||||||
void replay_save_input_event(InputEvent *evt)
|
void replay_save_input_event(InputEvent *evt)
|
||||||
{
|
{
|
||||||
|
InputKeyEvent *key;
|
||||||
|
InputBtnEvent *btn;
|
||||||
|
InputMoveEvent *move;
|
||||||
replay_put_dword(evt->type);
|
replay_put_dword(evt->type);
|
||||||
|
|
||||||
switch (evt->type) {
|
switch (evt->type) {
|
||||||
case INPUT_EVENT_KIND_KEY:
|
case INPUT_EVENT_KIND_KEY:
|
||||||
replay_put_dword(evt->u.key->key->type);
|
key = evt->u.key;
|
||||||
|
replay_put_dword(key->key->type);
|
||||||
|
|
||||||
switch (evt->u.key->key->type) {
|
switch (key->key->type) {
|
||||||
case KEY_VALUE_KIND_NUMBER:
|
case KEY_VALUE_KIND_NUMBER:
|
||||||
replay_put_qword(evt->u.key->key->u.number);
|
replay_put_qword(key->key->u.number);
|
||||||
replay_put_byte(evt->u.key->down);
|
replay_put_byte(key->down);
|
||||||
break;
|
break;
|
||||||
case KEY_VALUE_KIND_QCODE:
|
case KEY_VALUE_KIND_QCODE:
|
||||||
replay_put_dword(evt->u.key->key->u.qcode);
|
replay_put_dword(key->key->u.qcode);
|
||||||
replay_put_byte(evt->u.key->down);
|
replay_put_byte(key->down);
|
||||||
break;
|
break;
|
||||||
case KEY_VALUE_KIND__MAX:
|
case KEY_VALUE_KIND__MAX:
|
||||||
/* keep gcc happy */
|
/* keep gcc happy */
|
||||||
|
@ -68,16 +72,19 @@ void replay_save_input_event(InputEvent *evt)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_BTN:
|
case INPUT_EVENT_KIND_BTN:
|
||||||
replay_put_dword(evt->u.btn->button);
|
btn = evt->u.btn;
|
||||||
replay_put_byte(evt->u.btn->down);
|
replay_put_dword(btn->button);
|
||||||
|
replay_put_byte(btn->down);
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_REL:
|
case INPUT_EVENT_KIND_REL:
|
||||||
replay_put_dword(evt->u.rel->axis);
|
move = evt->u.rel;
|
||||||
replay_put_qword(evt->u.rel->value);
|
replay_put_dword(move->axis);
|
||||||
|
replay_put_qword(move->value);
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_ABS:
|
case INPUT_EVENT_KIND_ABS:
|
||||||
replay_put_dword(evt->u.abs->axis);
|
move = evt->u.abs;
|
||||||
replay_put_qword(evt->u.abs->value);
|
replay_put_dword(move->axis);
|
||||||
|
replay_put_qword(move->value);
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND__MAX:
|
case INPUT_EVENT_KIND__MAX:
|
||||||
/* keep gcc happy */
|
/* keep gcc happy */
|
||||||
|
|
|
@ -111,7 +111,7 @@ def gen_marshal_input_visit(arg_type, dealloc=False):
|
||||||
v = qmp_input_get_visitor(qiv);
|
v = qmp_input_get_visitor(qiv);
|
||||||
''')
|
''')
|
||||||
|
|
||||||
ret += gen_visit_fields(arg_type.members, skiperr=dealloc)
|
ret += gen_visit_members(arg_type.members, skiperr=dealloc)
|
||||||
|
|
||||||
if dealloc:
|
if dealloc:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
@ -175,7 +175,7 @@ def gen_marshal(name, arg_type, ret_type):
|
||||||
ret += gen_marshal_input_visit(arg_type)
|
ret += gen_marshal_input_visit(arg_type)
|
||||||
ret += gen_call(name, arg_type, ret_type)
|
ret += gen_call(name, arg_type, ret_type)
|
||||||
|
|
||||||
# 'goto out' produced by gen_marshal_input_visit->gen_visit_fields()
|
# 'goto out' produced by gen_marshal_input_visit->gen_visit_members()
|
||||||
# for each arg_type member, and by gen_call() for ret_type
|
# for each arg_type member, and by gen_call() for ret_type
|
||||||
if (arg_type and arg_type.members) or ret_type:
|
if (arg_type and arg_type.members) or ret_type:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
|
@ -67,8 +67,8 @@ def gen_event_send(name, arg_type):
|
||||||
''',
|
''',
|
||||||
name=name)
|
name=name)
|
||||||
ret += gen_err_check()
|
ret += gen_err_check()
|
||||||
ret += gen_visit_fields(arg_type.members, need_cast=True,
|
ret += gen_visit_members(arg_type.members, need_cast=True,
|
||||||
label='out_obj')
|
label='out_obj')
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
out_obj:
|
out_obj:
|
||||||
visit_end_struct(v, err ? NULL : &err);
|
visit_end_struct(v, err ? NULL : &err);
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct %(c_name)s {
|
||||||
c_name=c_name(name), c_type=element_type.c_type())
|
c_name=c_name(name), c_type=element_type.c_type())
|
||||||
|
|
||||||
|
|
||||||
def gen_struct_fields(members):
|
def gen_struct_members(members):
|
||||||
ret = ''
|
ret = ''
|
||||||
for memb in members:
|
for memb in members:
|
||||||
if memb.optional:
|
if memb.optional:
|
||||||
|
@ -77,22 +77,22 @@ struct %(c_name)s {
|
||||||
/* Members inherited from %(c_name)s: */
|
/* Members inherited from %(c_name)s: */
|
||||||
''',
|
''',
|
||||||
c_name=base.c_name())
|
c_name=base.c_name())
|
||||||
ret += gen_struct_fields(base.members)
|
ret += gen_struct_members(base.members)
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
/* Own members: */
|
/* Own members: */
|
||||||
''')
|
''')
|
||||||
ret += gen_struct_fields(members)
|
ret += gen_struct_members(members)
|
||||||
|
|
||||||
if variants:
|
if variants:
|
||||||
ret += gen_variants(variants)
|
ret += gen_variants(variants)
|
||||||
|
|
||||||
# Make sure that all structs have at least one field; this avoids
|
# Make sure that all structs have at least one member; this avoids
|
||||||
# potential issues with attempting to malloc space for zero-length
|
# potential issues with attempting to malloc space for zero-length
|
||||||
# structs in C, and also incompatibility with C++ (where an empty
|
# structs in C, and also incompatibility with C++ (where an empty
|
||||||
# struct is size 1).
|
# struct is size 1).
|
||||||
if not (base and base.members) and not members and not variants:
|
if not (base and base.members) and not members and not variants:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
char qapi_dummy_field_for_empty_struct;
|
char qapi_dummy_for_empty_struct;
|
||||||
''')
|
''')
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
@ -116,17 +116,8 @@ static inline %(base)s *qapi_%(c_name)s_base(const %(c_name)s *obj)
|
||||||
|
|
||||||
|
|
||||||
def gen_variants(variants):
|
def gen_variants(variants):
|
||||||
# FIXME: What purpose does data serve, besides preventing a union that
|
|
||||||
# has a branch named 'data'? We use it in qapi-visit.py to decide
|
|
||||||
# whether to bypass the switch statement if visiting the discriminator
|
|
||||||
# failed; but since we 0-initialize structs, and cannot tell what
|
|
||||||
# branch of the union is in use if the discriminator is invalid, there
|
|
||||||
# should not be any data leaks even without a data pointer. Or, if
|
|
||||||
# 'data' is merely added to guarantee we don't have an empty union,
|
|
||||||
# shouldn't we enforce that at .json parse time?
|
|
||||||
ret = mcgen('''
|
ret = mcgen('''
|
||||||
union { /* union tag is @%(c_name)s */
|
union { /* union tag is @%(c_name)s */
|
||||||
void *data;
|
|
||||||
''',
|
''',
|
||||||
c_name=c_name(variants.tag_member.name))
|
c_name=c_name(variants.tag_member.name))
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,6 @@
|
||||||
from qapi import *
|
from qapi import *
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# visit_type_FOO_fields() is always emitted; track if a forward declaration
|
|
||||||
# or implementation has already been output.
|
|
||||||
struct_fields_seen = set()
|
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_decl(name, scalar=False):
|
def gen_visit_decl(name, scalar=False):
|
||||||
c_type = c_name(name) + ' *'
|
c_type = c_name(name) + ' *'
|
||||||
|
@ -30,46 +26,32 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_type)sobj, Error **
|
||||||
c_name=c_name(name), c_type=c_type)
|
c_name=c_name(name), c_type=c_type)
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_fields_decl(typ):
|
def gen_visit_members_decl(name):
|
||||||
if typ.name in struct_fields_seen:
|
|
||||||
return ''
|
|
||||||
struct_fields_seen.add(typ.name)
|
|
||||||
return mcgen('''
|
return mcgen('''
|
||||||
|
|
||||||
static void visit_type_%(c_type)s_fields(Visitor *v, %(c_type)s *obj, Error **errp);
|
void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp);
|
||||||
''',
|
''',
|
||||||
c_type=typ.c_name())
|
c_name=c_name(name))
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_struct_fields(name, base, members, variants):
|
def gen_visit_object_members(name, base, members, variants):
|
||||||
ret = ''
|
ret = mcgen('''
|
||||||
|
|
||||||
if base:
|
void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
|
||||||
ret += gen_visit_fields_decl(base)
|
|
||||||
if variants:
|
|
||||||
for var in variants.variants:
|
|
||||||
# Ugly special case for simple union TODO get rid of it
|
|
||||||
if not var.simple_union_type():
|
|
||||||
ret += gen_visit_fields_decl(var.type)
|
|
||||||
|
|
||||||
struct_fields_seen.add(name)
|
|
||||||
ret += mcgen('''
|
|
||||||
|
|
||||||
static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s *obj, Error **errp)
|
|
||||||
{
|
{
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
''',
|
''',
|
||||||
c_name=c_name(name))
|
c_name=c_name(name))
|
||||||
|
|
||||||
if base:
|
if base:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_type_%(c_type)s_fields(v, (%(c_type)s *)obj, &err);
|
visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, &err);
|
||||||
''',
|
''',
|
||||||
c_type=base.c_name())
|
c_type=base.c_name())
|
||||||
ret += gen_err_check()
|
ret += gen_err_check()
|
||||||
|
|
||||||
ret += gen_visit_fields(members, prefix='obj->')
|
ret += gen_visit_members(members, prefix='obj->')
|
||||||
|
|
||||||
if variants:
|
if variants:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
@ -94,7 +76,7 @@ static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s *obj, Error **er
|
||||||
c_name=c_name(var.name))
|
c_name=c_name(var.name))
|
||||||
else:
|
else:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
visit_type_%(c_type)s_fields(v, &obj->u.%(c_name)s, &err);
|
visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, &err);
|
||||||
''',
|
''',
|
||||||
c_type=var.type.c_name(),
|
c_type=var.type.c_name(),
|
||||||
c_name=c_name(var.name))
|
c_name=c_name(var.name))
|
||||||
|
@ -108,7 +90,7 @@ static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s *obj, Error **er
|
||||||
}
|
}
|
||||||
''')
|
''')
|
||||||
|
|
||||||
# 'goto out' produced for base, by gen_visit_fields() for each member,
|
# 'goto out' produced for base, by gen_visit_members() for each member,
|
||||||
# and if variants were present
|
# and if variants were present
|
||||||
if base or members or variants:
|
if base or members or variants:
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
@ -173,8 +155,6 @@ def gen_visit_alternate(name, variants):
|
||||||
for var in variants.variants:
|
for var in variants.variants:
|
||||||
if var.type.alternate_qtype() == 'QTYPE_QINT':
|
if var.type.alternate_qtype() == 'QTYPE_QINT':
|
||||||
promote_int = 'false'
|
promote_int = 'false'
|
||||||
if isinstance(var.type, QAPISchemaObjectType):
|
|
||||||
ret += gen_visit_fields_decl(var.type)
|
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
|
@ -202,7 +182,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
|
||||||
if (err) {
|
if (err) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
visit_type_%(c_type)s_fields(v, &(*obj)->u.%(c_name)s, &err);
|
visit_type_%(c_type)s_members(v, &(*obj)->u.%(c_name)s, &err);
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
visit_end_struct(v, &err);
|
visit_end_struct(v, &err);
|
||||||
|
@ -235,10 +215,10 @@ out:
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_object(name, base, members, variants):
|
def gen_visit_object(name, base, members, variants):
|
||||||
ret = gen_visit_struct_fields(name, base, members, variants)
|
ret = gen_visit_object_members(name, base, members, variants)
|
||||||
|
|
||||||
# FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
|
# FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
|
||||||
# *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
|
# *obj, but then visit_type_FOO_members() fails, we should clean up *obj
|
||||||
# rather than leaving it non-NULL. As currently written, the caller must
|
# rather than leaving it non-NULL. As currently written, the caller must
|
||||||
# call qapi_free_FOO() to avoid a memory leak of the partial FOO.
|
# call qapi_free_FOO() to avoid a memory leak of the partial FOO.
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
@ -254,7 +234,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
|
||||||
if (!*obj) {
|
if (!*obj) {
|
||||||
goto out_obj;
|
goto out_obj;
|
||||||
}
|
}
|
||||||
visit_type_%(c_name)s_fields(v, *obj, &err);
|
visit_type_%(c_name)s_members(v, *obj, &err);
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
err = NULL;
|
err = NULL;
|
||||||
out_obj:
|
out_obj:
|
||||||
|
@ -316,6 +296,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
|
||||||
self.defn += defn
|
self.defn += defn
|
||||||
|
|
||||||
def visit_object_type(self, name, info, base, members, variants):
|
def visit_object_type(self, name, info, base, members, variants):
|
||||||
|
self.decl += gen_visit_members_decl(name)
|
||||||
self.decl += gen_visit_decl(name)
|
self.decl += gen_visit_decl(name)
|
||||||
self.defn += gen_visit_object(name, base, members, variants)
|
self.defn += gen_visit_object(name, base, members, variants)
|
||||||
|
|
||||||
|
|
|
@ -326,7 +326,7 @@ class QAPISchemaParser(object):
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
def find_base_fields(base):
|
def find_base_members(base):
|
||||||
base_struct_define = find_struct(base)
|
base_struct_define = find_struct(base)
|
||||||
if not base_struct_define:
|
if not base_struct_define:
|
||||||
return None
|
return None
|
||||||
|
@ -355,11 +355,11 @@ def discriminator_find_enum_define(expr):
|
||||||
if not (discriminator and base):
|
if not (discriminator and base):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
base_fields = find_base_fields(base)
|
base_members = find_base_members(base)
|
||||||
if not base_fields:
|
if not base_members:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
discriminator_type = base_fields.get(discriminator)
|
discriminator_type = base_members.get(discriminator)
|
||||||
if not discriminator_type:
|
if not discriminator_type:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -567,14 +567,14 @@ def check_union(expr, expr_info):
|
||||||
raise QAPIExprError(expr_info,
|
raise QAPIExprError(expr_info,
|
||||||
"Flat union '%s' must have a base"
|
"Flat union '%s' must have a base"
|
||||||
% name)
|
% name)
|
||||||
base_fields = find_base_fields(base)
|
base_members = find_base_members(base)
|
||||||
assert base_fields
|
assert base_members
|
||||||
|
|
||||||
# The value of member 'discriminator' must name a non-optional
|
# The value of member 'discriminator' must name a non-optional
|
||||||
# member of the base struct.
|
# member of the base struct.
|
||||||
check_name(expr_info, "Discriminator of flat union '%s'" % name,
|
check_name(expr_info, "Discriminator of flat union '%s'" % name,
|
||||||
discriminator)
|
discriminator)
|
||||||
discriminator_type = base_fields.get(discriminator)
|
discriminator_type = base_members.get(discriminator)
|
||||||
if not discriminator_type:
|
if not discriminator_type:
|
||||||
raise QAPIExprError(expr_info,
|
raise QAPIExprError(expr_info,
|
||||||
"Discriminator '%s' is not a member of base "
|
"Discriminator '%s' is not a member of base "
|
||||||
|
@ -969,7 +969,7 @@ class QAPISchemaObjectType(QAPISchemaType):
|
||||||
assert self.variants.tag_member in self.members
|
assert self.variants.tag_member in self.members
|
||||||
self.variants.check_clash(schema, self.info, seen)
|
self.variants.check_clash(schema, self.info, seen)
|
||||||
|
|
||||||
# Check that the members of this type do not cause duplicate JSON fields,
|
# Check that the members of this type do not cause duplicate JSON members,
|
||||||
# and update seen to track the members seen so far. Report any errors
|
# and update seen to track the members seen so far. Report any errors
|
||||||
# on behalf of info, which is not necessarily self.info
|
# on behalf of info, which is not necessarily self.info
|
||||||
def check_clash(self, schema, info, seen):
|
def check_clash(self, schema, info, seen):
|
||||||
|
@ -1647,8 +1647,8 @@ def gen_err_check(label='out', skiperr=False):
|
||||||
label=label)
|
label=label)
|
||||||
|
|
||||||
|
|
||||||
def gen_visit_fields(members, prefix='', need_cast=False, skiperr=False,
|
def gen_visit_members(members, prefix='', need_cast=False, skiperr=False,
|
||||||
label='out'):
|
label='out'):
|
||||||
ret = ''
|
ret = ''
|
||||||
if skiperr:
|
if skiperr:
|
||||||
errparg = 'NULL'
|
errparg = 'NULL'
|
||||||
|
|
|
@ -70,7 +70,6 @@ import json
|
||||||
import ast
|
import ast
|
||||||
import readline
|
import readline
|
||||||
import sys
|
import sys
|
||||||
import pprint
|
|
||||||
|
|
||||||
class QMPCompleter(list):
|
class QMPCompleter(list):
|
||||||
def complete(self, text, state):
|
def complete(self, text, state):
|
||||||
|
@ -103,11 +102,11 @@ class FuzzyJSON(ast.NodeTransformer):
|
||||||
# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
|
# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
|
||||||
# _execute_cmd()). Let's design a better one.
|
# _execute_cmd()). Let's design a better one.
|
||||||
class QMPShell(qmp.QEMUMonitorProtocol):
|
class QMPShell(qmp.QEMUMonitorProtocol):
|
||||||
def __init__(self, address, pp=None):
|
def __init__(self, address, pretty=False):
|
||||||
qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
|
qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
|
||||||
self._greeting = None
|
self._greeting = None
|
||||||
self._completer = None
|
self._completer = None
|
||||||
self._pp = pp
|
self._pretty = pretty
|
||||||
self._transmode = False
|
self._transmode = False
|
||||||
self._actions = list()
|
self._actions = list()
|
||||||
|
|
||||||
|
@ -231,11 +230,11 @@ class QMPShell(qmp.QEMUMonitorProtocol):
|
||||||
return qmpcmd
|
return qmpcmd
|
||||||
|
|
||||||
def _print(self, qmp):
|
def _print(self, qmp):
|
||||||
jsobj = json.dumps(qmp)
|
indent = None
|
||||||
if self._pp is not None:
|
if self._pretty:
|
||||||
self._pp.pprint(jsobj)
|
indent = 4
|
||||||
else:
|
jsobj = json.dumps(qmp, indent=indent)
|
||||||
print str(jsobj)
|
print str(jsobj)
|
||||||
|
|
||||||
def _execute_cmd(self, cmdline):
|
def _execute_cmd(self, cmdline):
|
||||||
try:
|
try:
|
||||||
|
@ -377,7 +376,7 @@ def main():
|
||||||
addr = ''
|
addr = ''
|
||||||
qemu = None
|
qemu = None
|
||||||
hmp = False
|
hmp = False
|
||||||
pp = None
|
pretty = False
|
||||||
verbose = False
|
verbose = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -387,9 +386,7 @@ def main():
|
||||||
fail_cmdline(arg)
|
fail_cmdline(arg)
|
||||||
hmp = True
|
hmp = True
|
||||||
elif arg == "-p":
|
elif arg == "-p":
|
||||||
if pp is not None:
|
pretty = True
|
||||||
fail_cmdline(arg)
|
|
||||||
pp = pprint.PrettyPrinter(indent=4)
|
|
||||||
elif arg == "-v":
|
elif arg == "-v":
|
||||||
verbose = True
|
verbose = True
|
||||||
else:
|
else:
|
||||||
|
@ -398,7 +395,7 @@ def main():
|
||||||
if hmp:
|
if hmp:
|
||||||
qemu = HMPShell(arg)
|
qemu = HMPShell(arg)
|
||||||
else:
|
else:
|
||||||
qemu = QMPShell(arg, pp)
|
qemu = QMPShell(arg, pretty)
|
||||||
addr = arg
|
addr = arg
|
||||||
|
|
||||||
if qemu is None:
|
if qemu is None:
|
||||||
|
|
|
@ -358,7 +358,6 @@ qapi-schema += unicode-str.json
|
||||||
qapi-schema += union-base-no-discriminator.json
|
qapi-schema += union-base-no-discriminator.json
|
||||||
qapi-schema += union-branch-case.json
|
qapi-schema += union-branch-case.json
|
||||||
qapi-schema += union-clash-branches.json
|
qapi-schema += union-clash-branches.json
|
||||||
qapi-schema += union-clash-data.json
|
|
||||||
qapi-schema += union-empty.json
|
qapi-schema += union-empty.json
|
||||||
qapi-schema += union-invalid-base.json
|
qapi-schema += union-invalid-base.json
|
||||||
qapi-schema += union-optional-branch.json
|
qapi-schema += union-optional-branch.json
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
'base': 'UserDefZero',
|
'base': 'UserDefZero',
|
||||||
'data': { 'string': 'str', 'enum1': 'QEnumTwo' } }
|
'data': { 'string': 'str', 'enum1': 'QEnumTwo' } }
|
||||||
|
|
||||||
# this variant of UserDefFlatUnion defaults to a union that uses fields with
|
# this variant of UserDefFlatUnion defaults to a union that uses members with
|
||||||
# allocated types to test corner cases in the cleanup/dealloc visitor
|
# allocated types to test corner cases in the cleanup/dealloc visitor
|
||||||
{ 'union': 'UserDefFlatUnion2',
|
{ 'union': 'UserDefFlatUnion2',
|
||||||
'base': 'UserDefUnionBase2',
|
'base': 'UserDefUnionBase2',
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
0
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Union branch 'data'
|
|
||||||
# FIXME: this parses, but then fails to compile due to a duplicate 'data'
|
|
||||||
# (one from the branch name, another as a filler to avoid an empty union).
|
|
||||||
# we should either detect the collision at parse time, or change the
|
|
||||||
# generated struct to allow this to compile.
|
|
||||||
{ 'union': 'TestUnion',
|
|
||||||
'data': { 'data': 'int' } }
|
|
|
@ -1,9 +0,0 @@
|
||||||
object :empty
|
|
||||||
object :obj-int-wrapper
|
|
||||||
member data: int optional=False
|
|
||||||
enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
|
|
||||||
prefix QTYPE
|
|
||||||
object TestUnion
|
|
||||||
member type: TestUnionKind optional=False
|
|
||||||
case data: :obj-int-wrapper
|
|
||||||
enum TestUnionKind ['data']
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* QEMU I/O channel sockets test
|
* QEMU I/O channel sockets test
|
||||||
*
|
*
|
||||||
* Copyright (c) 2015 Red Hat, Inc.
|
* Copyright (c) 2015-2016 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -283,14 +283,18 @@ static void test_io_channel_ipv4(bool async)
|
||||||
SocketAddress *connect_addr = g_new0(SocketAddress, 1);
|
SocketAddress *connect_addr = g_new0(SocketAddress, 1);
|
||||||
|
|
||||||
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
listen_addr->u.inet = g_new0(InetSocketAddress, 1);
|
listen_addr->u.inet = g_new(InetSocketAddress, 1);
|
||||||
listen_addr->u.inet->host = g_strdup("127.0.0.1");
|
*listen_addr->u.inet = (InetSocketAddress) {
|
||||||
listen_addr->u.inet->port = NULL; /* Auto-select */
|
.host = g_strdup("127.0.0.1"),
|
||||||
|
.port = NULL, /* Auto-select */
|
||||||
|
};
|
||||||
|
|
||||||
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
connect_addr->u.inet = g_new0(InetSocketAddress, 1);
|
connect_addr->u.inet = g_new(InetSocketAddress, 1);
|
||||||
connect_addr->u.inet->host = g_strdup("127.0.0.1");
|
*connect_addr->u.inet = (InetSocketAddress) {
|
||||||
connect_addr->u.inet->port = NULL; /* Filled in later */
|
.host = g_strdup("127.0.0.1"),
|
||||||
|
.port = NULL, /* Filled in later */
|
||||||
|
};
|
||||||
|
|
||||||
test_io_channel(async, listen_addr, connect_addr, false);
|
test_io_channel(async, listen_addr, connect_addr, false);
|
||||||
|
|
||||||
|
@ -317,14 +321,18 @@ static void test_io_channel_ipv6(bool async)
|
||||||
SocketAddress *connect_addr = g_new0(SocketAddress, 1);
|
SocketAddress *connect_addr = g_new0(SocketAddress, 1);
|
||||||
|
|
||||||
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
listen_addr->u.inet = g_new0(InetSocketAddress, 1);
|
listen_addr->u.inet = g_new(InetSocketAddress, 1);
|
||||||
listen_addr->u.inet->host = g_strdup("::1");
|
*listen_addr->u.inet = (InetSocketAddress) {
|
||||||
listen_addr->u.inet->port = NULL; /* Auto-select */
|
.host = g_strdup("::1"),
|
||||||
|
.port = NULL, /* Auto-select */
|
||||||
|
};
|
||||||
|
|
||||||
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
connect_addr->u.inet = g_new0(InetSocketAddress, 1);
|
connect_addr->u.inet = g_new(InetSocketAddress, 1);
|
||||||
connect_addr->u.inet->host = g_strdup("::1");
|
*connect_addr->u.inet = (InetSocketAddress) {
|
||||||
connect_addr->u.inet->port = NULL; /* Filled in later */
|
.host = g_strdup("::1"),
|
||||||
|
.port = NULL, /* Filled in later */
|
||||||
|
};
|
||||||
|
|
||||||
test_io_channel(async, listen_addr, connect_addr, false);
|
test_io_channel(async, listen_addr, connect_addr, false);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "qemu/option.h" /* qemu_opts_parse() */
|
#include "qemu/option.h" /* qemu_opts_parse() */
|
||||||
#include "qapi/opts-visitor.h" /* opts_visitor_new() */
|
#include "qapi/opts-visitor.h" /* opts_visitor_new() */
|
||||||
#include "test-qapi-visit.h" /* visit_type_UserDefOptions() */
|
#include "test-qapi-visit.h" /* visit_type_UserDefOptions() */
|
||||||
#include "qapi/dealloc-visitor.h" /* qapi_dealloc_visitor_new() */
|
|
||||||
|
|
||||||
static QemuOptsList userdef_opts = {
|
static QemuOptsList userdef_opts = {
|
||||||
.name = "userdef",
|
.name = "userdef",
|
||||||
|
@ -55,14 +54,7 @@ setup_fixture(OptsVisitorFixture *f, gconstpointer test_data)
|
||||||
static void
|
static void
|
||||||
teardown_fixture(OptsVisitorFixture *f, gconstpointer test_data)
|
teardown_fixture(OptsVisitorFixture *f, gconstpointer test_data)
|
||||||
{
|
{
|
||||||
if (f->userdef != NULL) {
|
qapi_free_UserDefOptions(f->userdef);
|
||||||
QapiDeallocVisitor *dv;
|
|
||||||
|
|
||||||
dv = qapi_dealloc_visitor_new();
|
|
||||||
visit_type_UserDefOptions(qapi_dealloc_get_visitor(dv), NULL,
|
|
||||||
&f->userdef, NULL);
|
|
||||||
qapi_dealloc_visitor_cleanup(dv);
|
|
||||||
}
|
|
||||||
error_free(f->err);
|
error_free(f->err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,12 +110,13 @@ static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
|
||||||
{
|
{
|
||||||
QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
|
QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
|
||||||
int scancodes[3], i, count;
|
int scancodes[3], i, count;
|
||||||
|
InputKeyEvent *key = evt->u.key;
|
||||||
|
|
||||||
if (!entry || !entry->put_kbd) {
|
if (!entry || !entry->put_kbd) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
count = qemu_input_key_value_to_scancode(evt->u.key->key,
|
count = qemu_input_key_value_to_scancode(key->key,
|
||||||
evt->u.key->down,
|
key->down,
|
||||||
scancodes);
|
scancodes);
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
entry->put_kbd(entry->opaque, scancodes[i]);
|
entry->put_kbd(entry->opaque, scancodes[i]);
|
||||||
|
@ -150,23 +151,25 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
|
||||||
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
||||||
};
|
};
|
||||||
QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
|
QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
|
||||||
|
InputBtnEvent *btn;
|
||||||
|
InputMoveEvent *move;
|
||||||
|
|
||||||
switch (evt->type) {
|
switch (evt->type) {
|
||||||
case INPUT_EVENT_KIND_BTN:
|
case INPUT_EVENT_KIND_BTN:
|
||||||
if (evt->u.btn->down) {
|
btn = evt->u.btn;
|
||||||
s->buttons |= bmap[evt->u.btn->button];
|
if (btn->down) {
|
||||||
|
s->buttons |= bmap[btn->button];
|
||||||
} else {
|
} else {
|
||||||
s->buttons &= ~bmap[evt->u.btn->button];
|
s->buttons &= ~bmap[btn->button];
|
||||||
}
|
}
|
||||||
if (evt->u.btn->down && evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
|
if (btn->down && btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||||
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
|
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
|
||||||
s->axis[INPUT_AXIS_X],
|
s->axis[INPUT_AXIS_X],
|
||||||
s->axis[INPUT_AXIS_Y],
|
s->axis[INPUT_AXIS_Y],
|
||||||
-1,
|
-1,
|
||||||
s->buttons);
|
s->buttons);
|
||||||
}
|
}
|
||||||
if (evt->u.btn->down &&
|
if (btn->down && btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||||
evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
|
||||||
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
|
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
|
||||||
s->axis[INPUT_AXIS_X],
|
s->axis[INPUT_AXIS_X],
|
||||||
s->axis[INPUT_AXIS_Y],
|
s->axis[INPUT_AXIS_Y],
|
||||||
|
@ -175,10 +178,12 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_ABS:
|
case INPUT_EVENT_KIND_ABS:
|
||||||
s->axis[evt->u.abs->axis] = evt->u.abs->value;
|
move = evt->u.abs;
|
||||||
|
s->axis[move->axis] = move->value;
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_REL:
|
case INPUT_EVENT_KIND_REL:
|
||||||
s->axis[evt->u.rel->axis] += evt->u.rel->value;
|
move = evt->u.rel;
|
||||||
|
s->axis[move->axis] += move->value;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
56
ui/input.c
56
ui/input.c
|
@ -166,24 +166,25 @@ void qmp_input_send_event(bool has_device, const char *device,
|
||||||
|
|
||||||
static void qemu_input_transform_abs_rotate(InputEvent *evt)
|
static void qemu_input_transform_abs_rotate(InputEvent *evt)
|
||||||
{
|
{
|
||||||
|
InputMoveEvent *move = evt->u.abs;
|
||||||
switch (graphic_rotate) {
|
switch (graphic_rotate) {
|
||||||
case 90:
|
case 90:
|
||||||
if (evt->u.abs->axis == INPUT_AXIS_X) {
|
if (move->axis == INPUT_AXIS_X) {
|
||||||
evt->u.abs->axis = INPUT_AXIS_Y;
|
move->axis = INPUT_AXIS_Y;
|
||||||
} else if (evt->u.abs->axis == INPUT_AXIS_Y) {
|
} else if (move->axis == INPUT_AXIS_Y) {
|
||||||
evt->u.abs->axis = INPUT_AXIS_X;
|
move->axis = INPUT_AXIS_X;
|
||||||
evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value;
|
move->value = INPUT_EVENT_ABS_SIZE - 1 - move->value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 180:
|
case 180:
|
||||||
evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value;
|
move->value = INPUT_EVENT_ABS_SIZE - 1 - move->value;
|
||||||
break;
|
break;
|
||||||
case 270:
|
case 270:
|
||||||
if (evt->u.abs->axis == INPUT_AXIS_X) {
|
if (move->axis == INPUT_AXIS_X) {
|
||||||
evt->u.abs->axis = INPUT_AXIS_Y;
|
move->axis = INPUT_AXIS_Y;
|
||||||
evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value;
|
move->value = INPUT_EVENT_ABS_SIZE - 1 - move->value;
|
||||||
} else if (evt->u.abs->axis == INPUT_AXIS_Y) {
|
} else if (move->axis == INPUT_AXIS_Y) {
|
||||||
evt->u.abs->axis = INPUT_AXIS_X;
|
move->axis = INPUT_AXIS_X;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -193,22 +194,26 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
int qcode, idx = -1;
|
int qcode, idx = -1;
|
||||||
|
InputKeyEvent *key;
|
||||||
|
InputBtnEvent *btn;
|
||||||
|
InputMoveEvent *move;
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
idx = qemu_console_get_index(src);
|
idx = qemu_console_get_index(src);
|
||||||
}
|
}
|
||||||
switch (evt->type) {
|
switch (evt->type) {
|
||||||
case INPUT_EVENT_KIND_KEY:
|
case INPUT_EVENT_KIND_KEY:
|
||||||
switch (evt->u.key->key->type) {
|
key = evt->u.key;
|
||||||
|
switch (key->key->type) {
|
||||||
case KEY_VALUE_KIND_NUMBER:
|
case KEY_VALUE_KIND_NUMBER:
|
||||||
qcode = qemu_input_key_number_to_qcode(evt->u.key->key->u.number);
|
qcode = qemu_input_key_number_to_qcode(key->key->u.number);
|
||||||
name = QKeyCode_lookup[qcode];
|
name = QKeyCode_lookup[qcode];
|
||||||
trace_input_event_key_number(idx, evt->u.key->key->u.number,
|
trace_input_event_key_number(idx, key->key->u.number,
|
||||||
name, evt->u.key->down);
|
name, key->down);
|
||||||
break;
|
break;
|
||||||
case KEY_VALUE_KIND_QCODE:
|
case KEY_VALUE_KIND_QCODE:
|
||||||
name = QKeyCode_lookup[evt->u.key->key->u.qcode];
|
name = QKeyCode_lookup[key->key->u.qcode];
|
||||||
trace_input_event_key_qcode(idx, name, evt->u.key->down);
|
trace_input_event_key_qcode(idx, name, key->down);
|
||||||
break;
|
break;
|
||||||
case KEY_VALUE_KIND__MAX:
|
case KEY_VALUE_KIND__MAX:
|
||||||
/* keep gcc happy */
|
/* keep gcc happy */
|
||||||
|
@ -216,16 +221,19 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_BTN:
|
case INPUT_EVENT_KIND_BTN:
|
||||||
name = InputButton_lookup[evt->u.btn->button];
|
btn = evt->u.btn;
|
||||||
trace_input_event_btn(idx, name, evt->u.btn->down);
|
name = InputButton_lookup[btn->button];
|
||||||
|
trace_input_event_btn(idx, name, btn->down);
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_REL:
|
case INPUT_EVENT_KIND_REL:
|
||||||
name = InputAxis_lookup[evt->u.rel->axis];
|
move = evt->u.rel;
|
||||||
trace_input_event_rel(idx, name, evt->u.rel->value);
|
name = InputAxis_lookup[move->axis];
|
||||||
|
trace_input_event_rel(idx, name, move->value);
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND_ABS:
|
case INPUT_EVENT_KIND_ABS:
|
||||||
name = InputAxis_lookup[evt->u.abs->axis];
|
move = evt->u.abs;
|
||||||
trace_input_event_abs(idx, name, evt->u.abs->value);
|
name = InputAxis_lookup[move->axis];
|
||||||
|
trace_input_event_abs(idx, name, move->value);
|
||||||
break;
|
break;
|
||||||
case INPUT_EVENT_KIND__MAX:
|
case INPUT_EVENT_KIND__MAX:
|
||||||
/* keep gcc happy */
|
/* keep gcc happy */
|
||||||
|
@ -462,7 +470,7 @@ InputEvent *qemu_input_event_new_move(InputEventKind kind,
|
||||||
InputMoveEvent *move = g_new0(InputMoveEvent, 1);
|
InputMoveEvent *move = g_new0(InputMoveEvent, 1);
|
||||||
|
|
||||||
evt->type = kind;
|
evt->type = kind;
|
||||||
evt->u.data = move;
|
evt->u.rel = move; /* evt->u.rel is the same as evt->u.abs */
|
||||||
move->axis = axis;
|
move->axis = axis;
|
||||||
move->value = value;
|
move->value = value;
|
||||||
return evt;
|
return evt;
|
||||||
|
|
39
ui/vnc.c
39
ui/vnc.c
|
@ -3530,12 +3530,13 @@ void vnc_display_open(const char *id, Error **errp)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned long long baseport;
|
unsigned long long baseport;
|
||||||
|
InetSocketAddress *inet;
|
||||||
saddr->type = SOCKET_ADDRESS_KIND_INET;
|
saddr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
saddr->u.inet = g_new0(InetSocketAddress, 1);
|
inet = saddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||||
if (vnc[0] == '[' && vnc[hlen - 1] == ']') {
|
if (vnc[0] == '[' && vnc[hlen - 1] == ']') {
|
||||||
saddr->u.inet->host = g_strndup(vnc + 1, hlen - 2);
|
inet->host = g_strndup(vnc + 1, hlen - 2);
|
||||||
} else {
|
} else {
|
||||||
saddr->u.inet->host = g_strndup(vnc, hlen);
|
inet->host = g_strndup(vnc, hlen);
|
||||||
}
|
}
|
||||||
if (parse_uint_full(h + 1, &baseport, 10) < 0) {
|
if (parse_uint_full(h + 1, &baseport, 10) < 0) {
|
||||||
error_setg(errp, "can't convert to a number: %s", h + 1);
|
error_setg(errp, "can't convert to a number: %s", h + 1);
|
||||||
|
@ -3546,32 +3547,32 @@ void vnc_display_open(const char *id, Error **errp)
|
||||||
error_setg(errp, "port %s out of range", h + 1);
|
error_setg(errp, "port %s out of range", h + 1);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
saddr->u.inet->port = g_strdup_printf(
|
inet->port = g_strdup_printf(
|
||||||
"%d", (int)baseport + 5900);
|
"%d", (int)baseport + 5900);
|
||||||
|
|
||||||
if (to) {
|
if (to) {
|
||||||
saddr->u.inet->has_to = true;
|
inet->has_to = true;
|
||||||
saddr->u.inet->to = to + 5900;
|
inet->to = to + 5900;
|
||||||
}
|
}
|
||||||
saddr->u.inet->ipv4 = ipv4;
|
inet->ipv4 = ipv4;
|
||||||
saddr->u.inet->has_ipv4 = has_ipv4;
|
inet->has_ipv4 = has_ipv4;
|
||||||
saddr->u.inet->ipv6 = ipv6;
|
inet->ipv6 = ipv6;
|
||||||
saddr->u.inet->has_ipv6 = has_ipv6;
|
inet->has_ipv6 = has_ipv6;
|
||||||
|
|
||||||
if (vs->ws_enabled) {
|
if (vs->ws_enabled) {
|
||||||
wsaddr->type = SOCKET_ADDRESS_KIND_INET;
|
wsaddr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
wsaddr->u.inet = g_new0(InetSocketAddress, 1);
|
inet = wsaddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||||
wsaddr->u.inet->host = g_strdup(saddr->u.inet->host);
|
inet->host = g_strdup(saddr->u.inet->host);
|
||||||
wsaddr->u.inet->port = g_strdup(websocket);
|
inet->port = g_strdup(websocket);
|
||||||
|
|
||||||
if (to) {
|
if (to) {
|
||||||
wsaddr->u.inet->has_to = true;
|
inet->has_to = true;
|
||||||
wsaddr->u.inet->to = to;
|
inet->to = to;
|
||||||
}
|
}
|
||||||
wsaddr->u.inet->ipv4 = ipv4;
|
inet->ipv4 = ipv4;
|
||||||
wsaddr->u.inet->has_ipv4 = has_ipv4;
|
inet->has_ipv4 = has_ipv4;
|
||||||
wsaddr->u.inet->ipv6 = ipv6;
|
inet->ipv6 = ipv6;
|
||||||
wsaddr->u.inet->has_ipv6 = has_ipv6;
|
inet->has_ipv6 = has_ipv6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1003,6 +1003,7 @@ socket_sockaddr_to_address_inet(struct sockaddr_storage *sa,
|
||||||
char host[NI_MAXHOST];
|
char host[NI_MAXHOST];
|
||||||
char serv[NI_MAXSERV];
|
char serv[NI_MAXSERV];
|
||||||
SocketAddress *addr;
|
SocketAddress *addr;
|
||||||
|
InetSocketAddress *inet;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = getnameinfo((struct sockaddr *)sa, salen,
|
ret = getnameinfo((struct sockaddr *)sa, salen,
|
||||||
|
@ -1017,13 +1018,13 @@ socket_sockaddr_to_address_inet(struct sockaddr_storage *sa,
|
||||||
|
|
||||||
addr = g_new0(SocketAddress, 1);
|
addr = g_new0(SocketAddress, 1);
|
||||||
addr->type = SOCKET_ADDRESS_KIND_INET;
|
addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||||
addr->u.inet = g_new0(InetSocketAddress, 1);
|
inet = addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||||
addr->u.inet->host = g_strdup(host);
|
inet->host = g_strdup(host);
|
||||||
addr->u.inet->port = g_strdup(serv);
|
inet->port = g_strdup(serv);
|
||||||
if (sa->ss_family == AF_INET) {
|
if (sa->ss_family == AF_INET) {
|
||||||
addr->u.inet->has_ipv4 = addr->u.inet->ipv4 = true;
|
inet->has_ipv4 = inet->ipv4 = true;
|
||||||
} else {
|
} else {
|
||||||
addr->u.inet->has_ipv6 = addr->u.inet->ipv6 = true;
|
inet->has_ipv6 = inet->ipv6 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
|
|
Loading…
Reference in New Issue