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,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.braille);
|
||||
ChardevCommon *common = backend->u.braille;
|
||||
BaumDriverState *baum;
|
||||
CharDriverState *chr;
|
||||
brlapi_handle_t *handle;
|
||||
|
@ -68,7 +68,7 @@ static CharDriverState *qemu_chr_open_msmouse(const char *id,
|
||||
ChardevReturn *ret,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.msmouse);
|
||||
ChardevCommon *common = backend->u.msmouse;
|
||||
CharDriverState *chr;
|
||||
|
||||
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);
|
||||
|
||||
if (qdict_haskey(options, "path")) {
|
||||
UnixSocketAddress *q_unix;
|
||||
saddr->type = SOCKET_ADDRESS_KIND_UNIX;
|
||||
saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||
saddr->u.q_unix->path = g_strdup(qdict_get_str(options, "path"));
|
||||
q_unix = saddr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||
q_unix->path = g_strdup(qdict_get_str(options, "path"));
|
||||
qdict_del(options, "path");
|
||||
} else {
|
||||
InetSocketAddress *inet;
|
||||
saddr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
saddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
saddr->u.inet->host = g_strdup(qdict_get_str(options, "host"));
|
||||
inet = saddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
inet->host = g_strdup(qdict_get_str(options, "host"));
|
||||
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 {
|
||||
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, "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,
|
||||
Error **errp)
|
||||
static void blockdev_do_action(TransactionAction *action, Error **errp)
|
||||
{
|
||||
TransactionAction action;
|
||||
TransactionActionList list;
|
||||
|
||||
action.type = type;
|
||||
action.u.data = data;
|
||||
list.value = &action;
|
||||
list.value = action;
|
||||
list.next = NULL;
|
||||
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,
|
||||
.mode = mode,
|
||||
};
|
||||
blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_SYNC,
|
||||
&snapshot, errp);
|
||||
TransactionAction action = {
|
||||
.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,
|
||||
@ -1247,9 +1246,11 @@ void qmp_blockdev_snapshot(const char *node, const char *overlay,
|
||||
.node = (char *) node,
|
||||
.overlay = (char *) overlay
|
||||
};
|
||||
|
||||
blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
|
||||
&snapshot_data, errp);
|
||||
TransactionAction action = {
|
||||
.type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT,
|
||||
.u.blockdev_snapshot = &snapshot_data,
|
||||
};
|
||||
blockdev_do_action(&action, errp);
|
||||
}
|
||||
|
||||
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,
|
||||
.name = (char *) name
|
||||
};
|
||||
|
||||
blockdev_do_action(TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
|
||||
&snapshot, errp);
|
||||
TransactionAction action = {
|
||||
.type = TRANSACTION_ACTION_KIND_BLOCKDEV_SNAPSHOT_INTERNAL_SYNC,
|
||||
.u.blockdev_snapshot_internal_sync = &snapshot,
|
||||
};
|
||||
blockdev_do_action(&action, errp);
|
||||
}
|
||||
|
||||
SnapshotInfo *qmp_blockdev_snapshot_delete_internal_sync(const char *device,
|
||||
|
@ -1,7 +1,7 @@
|
||||
= How to use the QAPI code generator =
|
||||
|
||||
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
|
||||
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,
|
||||
then individual documentation about each member of 'data' is provided,
|
||||
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
|
||||
after the expression was first released are also given a '(since
|
||||
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
|
||||
creating implicit C enums for visiting union types, or in 'List', as
|
||||
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
|
||||
complex types use underscore; when extending such expressions,
|
||||
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
|
||||
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
|
||||
incompatibly in a future release. All names must begin with a letter,
|
||||
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
|
||||
for the generator: QMP names that resemble C keywords or other
|
||||
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.
|
||||
|
||||
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),
|
||||
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
|
||||
if the only way that the optional argument will be omitted is when it is
|
||||
triggered by the presence of a new input flag to the command that older clients
|
||||
don't know to send. Changing from optional to mandatory is safe.
|
||||
expecting the member, and could crash if it is missing), although it
|
||||
can be done if the only way that the optional argument will be omitted
|
||||
is when it is triggered by the presence of a new input flag to the
|
||||
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
|
||||
must consider the backwards compatibility constraints of both directions
|
||||
of use.
|
||||
|
||||
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
|
||||
format. An example definition is:
|
||||
|
||||
@ -237,7 +238,7 @@ format. An example definition is:
|
||||
'data': { '*backing': 'str' } }
|
||||
|
||||
An example BlockdevOptionsGenericCOWFormat object on the wire could use
|
||||
both fields like this:
|
||||
both members like this:
|
||||
|
||||
{ "file": "/some/place/my-image",
|
||||
"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
|
||||
above, 'MyEnum' will turn into 'MY_ENUM' giving a constant name
|
||||
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.
|
||||
|
||||
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
|
||||
enumeration members in any location without breaking clients of Client
|
||||
JSON Protocol; however, removing enum values would break
|
||||
compatibility. For any struct that has a field that will only contain
|
||||
a finite set of string values, using an enum type for that field is
|
||||
better than open-coding the field to be type 'str'.
|
||||
compatibility. For any struct that has a member that will only contain
|
||||
a finite set of string values, using an enum type for that member is
|
||||
better than open-coding the member to be type 'str'.
|
||||
|
||||
|
||||
=== Union types ===
|
||||
@ -305,8 +306,8 @@ values to data types like in this example:
|
||||
'qcow2': 'Qcow2Options' } }
|
||||
|
||||
In the Client JSON Protocol, a simple union is represented by a
|
||||
dictionary that contains the 'type' field as a discriminator, and a
|
||||
'data' field that is of the specified data type corresponding to the
|
||||
dictionary that contains the 'type' member as a discriminator, and a
|
||||
'data' member that is of the specified data type corresponding to the
|
||||
discriminator value, as in these examples:
|
||||
|
||||
{ "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
|
||||
avoids nesting on the wire. All branches of the union must be
|
||||
complex types, and the top-level fields of the union dictionary on
|
||||
the wire will be combination of fields from both the base type and the
|
||||
complex types, and the top-level members of the union dictionary on
|
||||
the wire will be combination of members from both the base type and the
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
represented as a struct with the base member fields included directly,
|
||||
and then a union of structures for each branch of the struct.
|
||||
represented as a struct with the base members included directly, and
|
||||
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
|
||||
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
|
||||
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.
|
||||
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
|
||||
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
|
||||
@ -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
|
||||
to return additional information in the future; thus, new commands
|
||||
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.
|
||||
|
||||
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
|
||||
possible, the command expression should include the optional key
|
||||
'success-response' with boolean value false. So far, only QGA makes
|
||||
use of this field.
|
||||
use of this member.
|
||||
|
||||
|
||||
=== Events ===
|
||||
@ -656,7 +657,7 @@ Union types
|
||||
|
||||
{ "name": "BlockdevOptions", "meta-type": "object",
|
||||
"members": [
|
||||
{ "name": "kind", "type": "BlockdevOptionsKind" } ],
|
||||
{ "name": "type", "type": "BlockdevOptionsKind" } ],
|
||||
"tag": "type",
|
||||
"variants": [
|
||||
{ "case": "file", "type": ":obj-FileOptions-wrapper" },
|
||||
@ -722,33 +723,38 @@ the names of built-in types. Clients should examine member
|
||||
|
||||
== 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
|
||||
take JSON commands read in by a Client JSON Protocol server, unmarshal
|
||||
the arguments into the underlying C types, call into the corresponding
|
||||
C function, and map the response back to a Client JSON Protocol
|
||||
response to be returned to the user.
|
||||
C function, map the response back to a Client JSON Protocol response
|
||||
to be returned to the user, and introspect the commands.
|
||||
|
||||
As an example, we'll use the following schema, which describes a single
|
||||
complex user-defined type (which will produce a C struct, along with a list
|
||||
node structure that can be used to chain together a list of such types in
|
||||
case we want to accept/return a list of this type with a command), and a
|
||||
command which takes that type as a parameter and returns the same type:
|
||||
As an example, we'll use the following schema, which describes a
|
||||
single complex user-defined type, along with command which takes a
|
||||
list of that type as a parameter, and returns a single element of that
|
||||
type. The user is responsible for writing the implementation of
|
||||
qmp_my_command(); everything else is produced by the generator.
|
||||
|
||||
$ cat example-schema.json
|
||||
{ 'struct': 'UserDefOne',
|
||||
'data': { 'integer': 'int', 'string': 'str' } }
|
||||
'data': { 'integer': 'int', '*string': 'str' } }
|
||||
|
||||
{ 'command': 'my-command',
|
||||
'data': {'arg1': 'UserDefOne'},
|
||||
'data': { 'arg1': ['UserDefOne'] },
|
||||
'returns': 'UserDefOne' }
|
||||
|
||||
{ '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 ===
|
||||
|
||||
Used to generate the C types defined by a schema. The following files are
|
||||
created:
|
||||
Used to generate the C types defined by a schema, along with
|
||||
supporting code. The following files are created:
|
||||
|
||||
$(prefix)qapi-types.h - C types corresponding to types defined in
|
||||
the schema you pass in
|
||||
@ -763,38 +769,6 @@ Example:
|
||||
|
||||
$ python scripts/qapi-types.py --output-dir="qapi-generated" \
|
||||
--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
|
||||
[Uninteresting stuff omitted...]
|
||||
|
||||
@ -809,29 +783,59 @@ Example:
|
||||
|
||||
struct UserDefOne {
|
||||
int64_t integer;
|
||||
bool has_string;
|
||||
char *string;
|
||||
};
|
||||
|
||||
void qapi_free_UserDefOne(UserDefOne *obj);
|
||||
|
||||
struct UserDefOneList {
|
||||
union {
|
||||
UserDefOne *value;
|
||||
uint64_t padding;
|
||||
};
|
||||
UserDefOneList *next;
|
||||
UserDefOne *value;
|
||||
};
|
||||
|
||||
void qapi_free_UserDefOneList(UserDefOneList *obj);
|
||||
|
||||
#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 ===
|
||||
|
||||
Used to generate the visitor functions used to walk through and convert
|
||||
a QObject (as provided by QMP) to a native C data structure and
|
||||
vice-versa, as well as the visitor function used to dealloc a complex
|
||||
schema-defined C type.
|
||||
Used to generate the visitor functions used to walk through and
|
||||
convert between a native QAPI C data structure and some other format
|
||||
(such as QObject); the generated functions are named visit_type_FOO()
|
||||
and visit_type_FOO_members().
|
||||
|
||||
The following files are generated:
|
||||
|
||||
@ -848,41 +852,62 @@ Example:
|
||||
|
||||
$ python scripts/qapi-visit.py --output-dir="qapi-generated"
|
||||
--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
|
||||
[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;
|
||||
|
||||
visit_type_int(v, &(*obj)->integer, "integer", &err);
|
||||
visit_type_int(v, "integer", &obj->integer, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
visit_type_str(v, &(*obj)->string, "string", &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
if (visit_optional(v, "string", &obj->has_string)) {
|
||||
visit_type_str(v, "string", &obj->string, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
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;
|
||||
|
||||
visit_start_struct(v, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), &err);
|
||||
if (!err) {
|
||||
if (*obj) {
|
||||
visit_type_UserDefOne_fields(v, obj, errp);
|
||||
}
|
||||
visit_end_struct(v, &err);
|
||||
visit_start_struct(v, name, (void **)obj, sizeof(UserDefOne), &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
GenericList *i, **prev;
|
||||
@ -893,35 +918,24 @@ Example:
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
err = NULL;
|
||||
visit_end_list(v, &err);
|
||||
visit_end_list(v);
|
||||
out:
|
||||
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 ===
|
||||
|
||||
Used to generate the marshaling/dispatch functions for the commands defined
|
||||
in the schema. The following files are generated:
|
||||
Used to generate the marshaling/dispatch functions for the commands
|
||||
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
|
||||
QMP command defined in the schema. Functions
|
||||
@ -939,6 +953,19 @@ Example:
|
||||
|
||||
$ python scripts/qapi-commands.py --output-dir="qapi-generated"
|
||||
--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
|
||||
[Uninteresting stuff omitted...]
|
||||
|
||||
@ -950,7 +977,7 @@ Example:
|
||||
Visitor *v;
|
||||
|
||||
v = qmp_output_get_visitor(qov);
|
||||
visit_type_UserDefOne(v, &ret_in, "unused", &err);
|
||||
visit_type_UserDefOne(v, "unused", &ret_in, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
@ -961,7 +988,7 @@ Example:
|
||||
qmp_output_visitor_cleanup(qov);
|
||||
qdv = qapi_dealloc_visitor_new();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -972,10 +999,10 @@ Example:
|
||||
QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
|
||||
QapiDeallocVisitor *qdv;
|
||||
Visitor *v;
|
||||
UserDefOne *arg1 = NULL;
|
||||
UserDefOneList *arg1 = NULL;
|
||||
|
||||
v = qmp_input_get_visitor(qiv);
|
||||
visit_type_UserDefOne(v, &arg1, "arg1", &err);
|
||||
visit_type_UserDefOneList(v, "arg1", &arg1, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
@ -992,7 +1019,7 @@ Example:
|
||||
qmp_input_visitor_cleanup(qiv);
|
||||
qdv = qapi_dealloc_visitor_new();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1002,24 +1029,12 @@ Example:
|
||||
}
|
||||
|
||||
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 ===
|
||||
|
||||
Used to generate the event-related C code defined by a schema. The
|
||||
following files are created:
|
||||
Used to generate the event-related C code defined by a schema, with
|
||||
implementations for qapi_event_send_FOO(). The following files are
|
||||
created:
|
||||
|
||||
$(prefix)qapi-event.h - Function prototypes for each event type, plus an
|
||||
enumeration of all event names
|
||||
@ -1029,6 +1044,27 @@ Example:
|
||||
|
||||
$ python scripts/qapi-event.py --output-dir="qapi-generated"
|
||||
--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
|
||||
[Uninteresting stuff omitted...]
|
||||
|
||||
@ -1054,27 +1090,6 @@ Example:
|
||||
[EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
|
||||
[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 ===
|
||||
|
||||
@ -1089,17 +1104,6 @@ Example:
|
||||
|
||||
$ python scripts/qapi-introspect.py --output-dir="qapi-generated"
|
||||
--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
|
||||
[Uninteresting stuff omitted...]
|
||||
|
||||
@ -1109,3 +1113,15 @@ Example:
|
||||
extern const char example_qmp_schema_json[];
|
||||
|
||||
#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
|
||||
======================
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
release.
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "qapi/dealloc-visitor.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi-event.h"
|
||||
|
||||
@ -297,15 +296,7 @@ void acpi_table_add(const QemuOpts *opts, Error **errp)
|
||||
out:
|
||||
g_free(blob);
|
||||
g_strfreev(pathnames);
|
||||
|
||||
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);
|
||||
}
|
||||
qapi_free_AcpiTableOptions(hdrs);
|
||||
|
||||
error_propagate(errp, err);
|
||||
}
|
||||
|
@ -842,14 +842,16 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
{
|
||||
ChannelState *s = (ChannelState *)dev;
|
||||
int qcode, keycode;
|
||||
InputKeyEvent *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],
|
||||
evt->u.key->down);
|
||||
key->down);
|
||||
|
||||
if (qcode == Q_KEY_CODE_CAPS_LOCK) {
|
||||
if (evt->u.key->down) {
|
||||
if (key->down) {
|
||||
s->caps_lock_mode ^= 1;
|
||||
if (s->caps_lock_mode == 2) {
|
||||
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 (evt->u.key->down) {
|
||||
if (key->down) {
|
||||
s->num_lock_mode ^= 1;
|
||||
if (s->num_lock_mode == 2) {
|
||||
return; /* Drop second press */
|
||||
@ -877,7 +879,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
}
|
||||
|
||||
keycode = qcode_to_keycode[qcode];
|
||||
if (!evt->u.key->down) {
|
||||
if (!key->down) {
|
||||
keycode |= 0x80;
|
||||
}
|
||||
trace_escc_sunkbd_event_out(keycode);
|
||||
|
@ -116,37 +116,42 @@ static void hid_pointer_event(DeviceState *dev, QemuConsole *src,
|
||||
};
|
||||
HIDState *hs = (HIDState *)dev;
|
||||
HIDPointerEvent *e;
|
||||
InputMoveEvent *move;
|
||||
InputBtnEvent *btn;
|
||||
|
||||
assert(hs->n < QUEUE_LENGTH);
|
||||
e = &hs->ptr.queue[(hs->head + hs->n) & QUEUE_MASK];
|
||||
|
||||
switch (evt->type) {
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
if (evt->u.rel->axis == INPUT_AXIS_X) {
|
||||
e->xdx += evt->u.rel->value;
|
||||
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
|
||||
e->ydy += evt->u.rel->value;
|
||||
move = evt->u.rel;
|
||||
if (move->axis == INPUT_AXIS_X) {
|
||||
e->xdx += move->value;
|
||||
} else if (move->axis == INPUT_AXIS_Y) {
|
||||
e->ydy += move->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_KIND_ABS:
|
||||
if (evt->u.rel->axis == INPUT_AXIS_X) {
|
||||
e->xdx = evt->u.rel->value;
|
||||
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
|
||||
e->ydy = evt->u.rel->value;
|
||||
move = evt->u.abs;
|
||||
if (move->axis == INPUT_AXIS_X) {
|
||||
e->xdx = move->value;
|
||||
} else if (move->axis == INPUT_AXIS_Y) {
|
||||
e->ydy = move->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
if (evt->u.btn->down) {
|
||||
e->buttons_state |= bmap[evt->u.btn->button];
|
||||
if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||
btn = evt->u.btn;
|
||||
if (btn->down) {
|
||||
e->buttons_state |= bmap[btn->button];
|
||||
if (btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||
e->dz--;
|
||||
} else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
} else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
e->dz++;
|
||||
}
|
||||
} else {
|
||||
e->buttons_state &= ~bmap[evt->u.btn->button];
|
||||
e->buttons_state &= ~bmap[btn->button];
|
||||
}
|
||||
break;
|
||||
|
||||
@ -223,9 +228,10 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
|
||||
HIDState *hs = (HIDState *)dev;
|
||||
int scancodes[3], i, count;
|
||||
int slot;
|
||||
InputKeyEvent *key = evt->u.key;
|
||||
|
||||
count = qemu_input_key_value_to_scancode(evt->u.key->key,
|
||||
evt->u.key->down,
|
||||
count = qemu_input_key_value_to_scancode(key->key,
|
||||
key->down,
|
||||
scancodes);
|
||||
if (hs->n + count > QUEUE_LENGTH) {
|
||||
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;
|
||||
int scancodes[3], i, count;
|
||||
InputKeyEvent *key = evt->u.key;
|
||||
|
||||
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
|
||||
count = qemu_input_key_value_to_scancode(evt->u.key->key,
|
||||
evt->u.key->down,
|
||||
count = qemu_input_key_value_to_scancode(key->key,
|
||||
key->down,
|
||||
scancodes);
|
||||
for (i = 0; i < count; 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,
|
||||
};
|
||||
PS2MouseState *s = (PS2MouseState *)dev;
|
||||
InputMoveEvent *move;
|
||||
InputBtnEvent *btn;
|
||||
|
||||
/* check if deltas are recorded when disabled */
|
||||
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
|
||||
@ -396,23 +399,25 @@ static void ps2_mouse_event(DeviceState *dev, QemuConsole *src,
|
||||
|
||||
switch (evt->type) {
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
if (evt->u.rel->axis == INPUT_AXIS_X) {
|
||||
s->mouse_dx += evt->u.rel->value;
|
||||
} else if (evt->u.rel->axis == INPUT_AXIS_Y) {
|
||||
s->mouse_dy -= evt->u.rel->value;
|
||||
move = evt->u.rel;
|
||||
if (move->axis == INPUT_AXIS_X) {
|
||||
s->mouse_dx += move->value;
|
||||
} else if (move->axis == INPUT_AXIS_Y) {
|
||||
s->mouse_dy -= move->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
if (evt->u.btn->down) {
|
||||
s->mouse_buttons |= bmap[evt->u.btn->button];
|
||||
if (evt->u.btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||
btn = evt->u.btn;
|
||||
if (btn->down) {
|
||||
s->mouse_buttons |= bmap[btn->button];
|
||||
if (btn->button == INPUT_BUTTON_WHEEL_UP) {
|
||||
s->mouse_dz--;
|
||||
} else if (evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
} else if (btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
s->mouse_dz++;
|
||||
}
|
||||
} else {
|
||||
s->mouse_buttons &= ~bmap[evt->u.btn->button];
|
||||
s->mouse_buttons &= ~bmap[btn->button];
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -191,46 +191,53 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
|
||||
VirtIOInput *vinput = VIRTIO_INPUT(dev);
|
||||
virtio_input_event event;
|
||||
int qcode;
|
||||
InputKeyEvent *key;
|
||||
InputMoveEvent *move;
|
||||
InputBtnEvent *btn;
|
||||
|
||||
switch (evt->type) {
|
||||
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]) {
|
||||
event.type = cpu_to_le16(EV_KEY);
|
||||
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);
|
||||
} else {
|
||||
if (evt->u.key->down) {
|
||||
if (key->down) {
|
||||
fprintf(stderr, "%s: unmapped key: %d [%s]\n", __func__,
|
||||
qcode, QKeyCode_lookup[qcode]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
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.code = cpu_to_le16(keymap_button[evt->u.btn->button]);
|
||||
event.value = cpu_to_le32(evt->u.btn->down ? 1 : 0);
|
||||
event.code = cpu_to_le16(keymap_button[btn->button]);
|
||||
event.value = cpu_to_le32(btn->down ? 1 : 0);
|
||||
virtio_input_send(vinput, &event);
|
||||
} else {
|
||||
if (evt->u.btn->down) {
|
||||
if (btn->down) {
|
||||
fprintf(stderr, "%s: unmapped button: %d [%s]\n", __func__,
|
||||
evt->u.btn->button,
|
||||
InputButton_lookup[evt->u.btn->button]);
|
||||
btn->button,
|
||||
InputButton_lookup[btn->button]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
move = evt->u.rel;
|
||||
event.type = cpu_to_le16(EV_REL);
|
||||
event.code = cpu_to_le16(axismap_rel[evt->u.rel->axis]);
|
||||
event.value = cpu_to_le32(evt->u.rel->value);
|
||||
event.code = cpu_to_le16(axismap_rel[move->axis]);
|
||||
event.value = cpu_to_le32(move->value);
|
||||
virtio_input_send(vinput, &event);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_ABS:
|
||||
move = evt->u.abs;
|
||||
event.type = cpu_to_le16(EV_ABS);
|
||||
event.code = cpu_to_le16(axismap_abs[evt->u.abs->axis]);
|
||||
event.value = cpu_to_le32(evt->u.abs->value);
|
||||
event.code = cpu_to_le16(axismap_abs[move->axis]);
|
||||
event.value = cpu_to_le32(move->value);
|
||||
virtio_input_send(vinput, &event);
|
||||
break;
|
||||
default:
|
||||
|
31
net/net.c
31
net/net.c
@ -42,7 +42,6 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "qapi/dealloc-visitor.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "net/filter.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)
|
||||
{
|
||||
void *object = NULL;
|
||||
Error *err = NULL;
|
||||
int ret = -1;
|
||||
OptsVisitor *ov = opts_visitor_new(opts);
|
||||
Visitor *v = opts_get_visitor(ov);
|
||||
|
||||
{
|
||||
OptsVisitor *ov = opts_visitor_new(opts);
|
||||
|
||||
net_visit(opts_get_visitor(ov), is_netdev, &object, &err);
|
||||
opts_visitor_cleanup(ov);
|
||||
if (is_netdev) {
|
||||
visit_type_Netdev(v, NULL, (Netdev **)&object, &err);
|
||||
} else {
|
||||
visit_type_NetLegacy(v, NULL, (NetLegacy **)&object, &err);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
ret = net_client_init1(object, is_netdev, &err);
|
||||
}
|
||||
|
||||
if (object) {
|
||||
QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();
|
||||
|
||||
net_visit(qapi_dealloc_get_visitor(dv), is_netdev, &object, NULL);
|
||||
qapi_dealloc_visitor_cleanup(dv);
|
||||
if (is_netdev) {
|
||||
qapi_free_Netdev(object);
|
||||
} else {
|
||||
qapi_free_NetLegacy(object);
|
||||
}
|
||||
|
||||
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 "qapi-visit.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "qapi/dealloc-visitor.h"
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/hostmem.h"
|
||||
#include "qmp-commands.h"
|
||||
@ -243,13 +242,7 @@ static int parse_numa(void *opaque, QemuOpts *opts, Error **errp)
|
||||
|
||||
error:
|
||||
error_report_err(err);
|
||||
|
||||
if (object) {
|
||||
QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();
|
||||
visit_type_NumaOptions(qapi_dealloc_get_visitor(dv), NULL, &object,
|
||||
NULL);
|
||||
qapi_dealloc_visitor_cleanup(dv);
|
||||
}
|
||||
qapi_free_NumaOptions(object);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -3323,23 +3323,20 @@
|
||||
#
|
||||
# Since: 1.4 (testdev since 2.2)
|
||||
##
|
||||
{ 'struct': 'ChardevDummy', 'data': { },
|
||||
'base': 'ChardevCommon' }
|
||||
|
||||
{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
|
||||
'serial' : 'ChardevHostdev',
|
||||
'parallel': 'ChardevHostdev',
|
||||
'pipe' : 'ChardevHostdev',
|
||||
'socket' : 'ChardevSocket',
|
||||
'udp' : 'ChardevUdp',
|
||||
'pty' : 'ChardevDummy',
|
||||
'null' : 'ChardevDummy',
|
||||
'pty' : 'ChardevCommon',
|
||||
'null' : 'ChardevCommon',
|
||||
'mux' : 'ChardevMux',
|
||||
'msmouse': 'ChardevDummy',
|
||||
'braille': 'ChardevDummy',
|
||||
'testdev': 'ChardevDummy',
|
||||
'msmouse': 'ChardevCommon',
|
||||
'braille': 'ChardevCommon',
|
||||
'testdev': 'ChardevCommon',
|
||||
'stdio' : 'ChardevStdio',
|
||||
'console': 'ChardevDummy',
|
||||
'console': 'ChardevCommon',
|
||||
'spicevmc' : 'ChardevSpiceChannel',
|
||||
'spiceport' : 'ChardevSpicePort',
|
||||
'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)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
ChardevCommon *common = qapi_ChardevDummy_base(backend->u.null);
|
||||
ChardevCommon *common = backend->u.null;
|
||||
|
||||
chr = qemu_chr_alloc(common, errp);
|
||||
if (!chr) {
|
||||
@ -724,7 +724,7 @@ static CharDriverState *qemu_chr_open_mux(const char *id,
|
||||
ChardevMux *mux = backend->u.mux;
|
||||
CharDriverState *chr, *drv;
|
||||
MuxDriver *d;
|
||||
ChardevCommon *common = qapi_ChardevMux_base(backend->u.mux);
|
||||
ChardevCommon *common = qapi_ChardevMux_base(mux);
|
||||
|
||||
drv = qemu_chr_find(mux->chardev);
|
||||
if (drv == NULL) {
|
||||
@ -1043,7 +1043,7 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
|
||||
char *filename_in;
|
||||
char *filename_out;
|
||||
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);
|
||||
@ -1123,7 +1123,7 @@ static CharDriverState *qemu_chr_open_stdio(const char *id,
|
||||
ChardevStdio *opts = backend->u.stdio;
|
||||
CharDriverState *chr;
|
||||
struct sigaction act;
|
||||
ChardevCommon *common = qapi_ChardevStdio_base(backend->u.stdio);
|
||||
ChardevCommon *common = qapi_ChardevStdio_base(opts);
|
||||
|
||||
if (is_daemonized()) {
|
||||
error_setg(errp, "cannot use stdio with -daemonize");
|
||||
@ -1366,7 +1366,7 @@ static CharDriverState *qemu_chr_open_pty(const char *id,
|
||||
PtyCharDriver *s;
|
||||
int master_fd, slave_fd;
|
||||
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);
|
||||
if (master_fd < 0) {
|
||||
@ -2141,7 +2141,7 @@ static CharDriverState *qemu_chr_open_pipe(const char *id,
|
||||
const char *filename = opts->device;
|
||||
CharDriverState *chr;
|
||||
WinCharState *s;
|
||||
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.pipe);
|
||||
ChardevCommon *common = qapi_ChardevHostdev_base(opts);
|
||||
|
||||
chr = qemu_chr_alloc(common, errp);
|
||||
if (!chr) {
|
||||
@ -2183,7 +2183,7 @@ static CharDriverState *qemu_chr_open_win_con(const char *id,
|
||||
ChardevReturn *ret,
|
||||
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),
|
||||
common, errp);
|
||||
}
|
||||
@ -3216,7 +3216,7 @@ static CharDriverState *qemu_chr_open_ringbuf(const char *id,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevRingbuf *opts = backend->u.ringbuf;
|
||||
ChardevCommon *common = qapi_ChardevRingbuf_base(backend->u.ringbuf);
|
||||
ChardevCommon *common = qapi_ChardevRingbuf_base(opts);
|
||||
CharDriverState *chr;
|
||||
RingBufCharDriver *d;
|
||||
|
||||
@ -3506,26 +3506,29 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
const char *path = qemu_opt_get(opts, "path");
|
||||
ChardevFile *file;
|
||||
|
||||
if (path == NULL) {
|
||||
error_setg(errp, "chardev: file: no filename given");
|
||||
return;
|
||||
}
|
||||
backend->u.file = g_new0(ChardevFile, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevFile_base(backend->u.file));
|
||||
backend->u.file->out = g_strdup(path);
|
||||
file = backend->u.file = g_new0(ChardevFile, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));
|
||||
file->out = g_strdup(path);
|
||||
|
||||
backend->u.file->has_append = true;
|
||||
backend->u.file->append = qemu_opt_get_bool(opts, "append", false);
|
||||
file->has_append = true;
|
||||
file->append = qemu_opt_get_bool(opts, "append", false);
|
||||
}
|
||||
|
||||
static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
backend->u.stdio = g_new0(ChardevStdio, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevStdio_base(backend->u.stdio));
|
||||
backend->u.stdio->has_signal = true;
|
||||
backend->u.stdio->signal = qemu_opt_get_bool(opts, "signal", true);
|
||||
ChardevStdio *stdio;
|
||||
|
||||
stdio = backend->u.stdio = g_new0(ChardevStdio, 1);
|
||||
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
|
||||
@ -3533,14 +3536,15 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
const char *device = qemu_opt_get(opts, "path");
|
||||
ChardevHostdev *serial;
|
||||
|
||||
if (device == NULL) {
|
||||
error_setg(errp, "chardev: serial/tty: no device path given");
|
||||
return;
|
||||
}
|
||||
backend->u.serial = g_new0(ChardevHostdev, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.serial));
|
||||
backend->u.serial->device = g_strdup(device);
|
||||
serial = backend->u.serial = g_new0(ChardevHostdev, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));
|
||||
serial->device = g_strdup(device);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3549,14 +3553,15 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
const char *device = qemu_opt_get(opts, "path");
|
||||
ChardevHostdev *parallel;
|
||||
|
||||
if (device == NULL) {
|
||||
error_setg(errp, "chardev: parallel: no device path given");
|
||||
return;
|
||||
}
|
||||
backend->u.parallel = g_new0(ChardevHostdev, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.parallel));
|
||||
backend->u.parallel->device = g_strdup(device);
|
||||
parallel = backend->u.parallel = g_new0(ChardevHostdev, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(parallel));
|
||||
parallel->device = g_strdup(device);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -3564,28 +3569,30 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
const char *device = qemu_opt_get(opts, "path");
|
||||
ChardevHostdev *dev;
|
||||
|
||||
if (device == NULL) {
|
||||
error_setg(errp, "chardev: pipe: no device path given");
|
||||
return;
|
||||
}
|
||||
backend->u.pipe = g_new0(ChardevHostdev, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(backend->u.pipe));
|
||||
backend->u.pipe->device = g_strdup(device);
|
||||
dev = backend->u.pipe = g_new0(ChardevHostdev, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));
|
||||
dev->device = g_strdup(device);
|
||||
}
|
||||
|
||||
static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
int val;
|
||||
ChardevRingbuf *ringbuf;
|
||||
|
||||
backend->u.ringbuf = g_new0(ChardevRingbuf, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(backend->u.ringbuf));
|
||||
ringbuf = backend->u.ringbuf = g_new0(ChardevRingbuf, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));
|
||||
|
||||
val = qemu_opt_get_size(opts, "size", 0);
|
||||
if (val != 0) {
|
||||
backend->u.ringbuf->has_size = true;
|
||||
backend->u.ringbuf->size = val;
|
||||
ringbuf->has_size = true;
|
||||
ringbuf->size = val;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3593,14 +3600,15 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
|
||||
Error **errp)
|
||||
{
|
||||
const char *chardev = qemu_opt_get(opts, "chardev");
|
||||
ChardevMux *mux;
|
||||
|
||||
if (chardev == NULL) {
|
||||
error_setg(errp, "chardev: mux: no chardev given");
|
||||
return;
|
||||
}
|
||||
backend->u.mux = g_new0(ChardevMux, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevMux_base(backend->u.mux));
|
||||
backend->u.mux->chardev = g_strdup(chardev);
|
||||
mux = backend->u.mux = g_new0(ChardevMux, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux));
|
||||
mux->chardev = g_strdup(chardev);
|
||||
}
|
||||
|
||||
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 *tls_creds = qemu_opt_get(opts, "tls-creds");
|
||||
SocketAddress *addr;
|
||||
ChardevSocket *sock;
|
||||
|
||||
if (!path) {
|
||||
if (!host) {
|
||||
@ -3633,39 +3642,42 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
||||
}
|
||||
}
|
||||
|
||||
backend->u.socket = g_new0(ChardevSocket, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevSocket_base(backend->u.socket));
|
||||
sock = backend->u.socket = g_new0(ChardevSocket, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
|
||||
|
||||
backend->u.socket->has_nodelay = true;
|
||||
backend->u.socket->nodelay = do_nodelay;
|
||||
backend->u.socket->has_server = true;
|
||||
backend->u.socket->server = is_listen;
|
||||
backend->u.socket->has_telnet = true;
|
||||
backend->u.socket->telnet = is_telnet;
|
||||
backend->u.socket->has_wait = true;
|
||||
backend->u.socket->wait = is_waitconnect;
|
||||
backend->u.socket->has_reconnect = true;
|
||||
backend->u.socket->reconnect = reconnect;
|
||||
backend->u.socket->tls_creds = g_strdup(tls_creds);
|
||||
sock->has_nodelay = true;
|
||||
sock->nodelay = do_nodelay;
|
||||
sock->has_server = true;
|
||||
sock->server = is_listen;
|
||||
sock->has_telnet = true;
|
||||
sock->telnet = is_telnet;
|
||||
sock->has_wait = true;
|
||||
sock->wait = is_waitconnect;
|
||||
sock->has_reconnect = true;
|
||||
sock->reconnect = reconnect;
|
||||
sock->tls_creds = g_strdup(tls_creds);
|
||||
|
||||
addr = g_new0(SocketAddress, 1);
|
||||
if (path) {
|
||||
UnixSocketAddress *q_unix;
|
||||
addr->type = SOCKET_ADDRESS_KIND_UNIX;
|
||||
addr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||
addr->u.q_unix->path = g_strdup(path);
|
||||
q_unix = addr->u.q_unix = g_new0(UnixSocketAddress, 1);
|
||||
q_unix->path = g_strdup(path);
|
||||
} else {
|
||||
addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
addr->u.inet->host = g_strdup(host);
|
||||
addr->u.inet->port = g_strdup(port);
|
||||
addr->u.inet->has_to = qemu_opt_get(opts, "to");
|
||||
addr->u.inet->to = qemu_opt_get_number(opts, "to", 0);
|
||||
addr->u.inet->has_ipv4 = qemu_opt_get(opts, "ipv4");
|
||||
addr->u.inet->ipv4 = qemu_opt_get_bool(opts, "ipv4", 0);
|
||||
addr->u.inet->has_ipv6 = qemu_opt_get(opts, "ipv6");
|
||||
addr->u.inet->ipv6 = qemu_opt_get_bool(opts, "ipv6", 0);
|
||||
addr->u.inet = g_new(InetSocketAddress, 1);
|
||||
*addr->u.inet = (InetSocketAddress) {
|
||||
.host = g_strdup(host),
|
||||
.port = g_strdup(port),
|
||||
.has_to = qemu_opt_get(opts, "to"),
|
||||
.to = qemu_opt_get_number(opts, "to", 0),
|
||||
.has_ipv4 = qemu_opt_get(opts, "ipv4"),
|
||||
.ipv4 = qemu_opt_get_bool(opts, "ipv4", 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,
|
||||
@ -3677,6 +3689,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
|
||||
const char *localport = qemu_opt_get(opts, "localport");
|
||||
bool has_local = false;
|
||||
SocketAddress *addr;
|
||||
ChardevUdp *udp;
|
||||
|
||||
if (host == NULL || strlen(host) == 0) {
|
||||
host = "localhost";
|
||||
@ -3696,28 +3709,32 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
|
||||
has_local = true;
|
||||
}
|
||||
|
||||
backend->u.udp = g_new0(ChardevUdp, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevUdp_base(backend->u.udp));
|
||||
udp = backend->u.udp = g_new0(ChardevUdp, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));
|
||||
|
||||
addr = g_new0(SocketAddress, 1);
|
||||
addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
addr->u.inet->host = g_strdup(host);
|
||||
addr->u.inet->port = g_strdup(port);
|
||||
addr->u.inet->has_ipv4 = qemu_opt_get(opts, "ipv4");
|
||||
addr->u.inet->ipv4 = qemu_opt_get_bool(opts, "ipv4", 0);
|
||||
addr->u.inet->has_ipv6 = qemu_opt_get(opts, "ipv6");
|
||||
addr->u.inet->ipv6 = qemu_opt_get_bool(opts, "ipv6", 0);
|
||||
backend->u.udp->remote = addr;
|
||||
addr->u.inet = g_new(InetSocketAddress, 1);
|
||||
*addr->u.inet = (InetSocketAddress) {
|
||||
.host = g_strdup(host),
|
||||
.port = g_strdup(port),
|
||||
.has_ipv4 = qemu_opt_get(opts, "ipv4"),
|
||||
.ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
|
||||
.has_ipv6 = qemu_opt_get(opts, "ipv6"),
|
||||
.ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
|
||||
};
|
||||
udp->remote = addr;
|
||||
|
||||
if (has_local) {
|
||||
backend->u.udp->has_local = true;
|
||||
udp->has_local = true;
|
||||
addr = g_new0(SocketAddress, 1);
|
||||
addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
addr->u.inet->host = g_strdup(localaddr);
|
||||
addr->u.inet->port = g_strdup(localport);
|
||||
backend->u.udp->local = addr;
|
||||
addr->u.inet = g_new(InetSocketAddress, 1);
|
||||
*addr->u.inet = (InetSocketAddress) {
|
||||
.host = g_strdup(localaddr),
|
||||
.port = g_strdup(localport),
|
||||
};
|
||||
udp->local = addr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3800,7 +3817,7 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
|
||||
} else {
|
||||
ChardevCommon *cc = g_new0(ChardevCommon, 1);
|
||||
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);
|
||||
@ -4128,7 +4145,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevFile *file = backend->u.file;
|
||||
ChardevCommon *common = qapi_ChardevFile_base(backend->u.file);
|
||||
ChardevCommon *common = qapi_ChardevFile_base(file);
|
||||
HANDLE out;
|
||||
|
||||
if (file->has_in) {
|
||||
@ -4151,7 +4168,7 @@ static CharDriverState *qmp_chardev_open_serial(const char *id,
|
||||
Error **errp)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4175,7 +4192,7 @@ static CharDriverState *qmp_chardev_open_file(const char *id,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevFile *file = backend->u.file;
|
||||
ChardevCommon *common = qapi_ChardevFile_base(backend->u.file);
|
||||
ChardevCommon *common = qapi_ChardevFile_base(file);
|
||||
int flags, in = -1, out;
|
||||
|
||||
flags = O_WRONLY | O_CREAT | O_BINARY;
|
||||
@ -4209,7 +4226,7 @@ static CharDriverState *qmp_chardev_open_serial(const char *id,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevHostdev *serial = backend->u.serial;
|
||||
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.serial);
|
||||
ChardevCommon *common = qapi_ChardevHostdev_base(serial);
|
||||
int fd;
|
||||
|
||||
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)
|
||||
{
|
||||
ChardevHostdev *parallel = backend->u.parallel;
|
||||
ChardevCommon *common = qapi_ChardevHostdev_base(backend->u.parallel);
|
||||
ChardevCommon *common = qapi_ChardevHostdev_base(parallel);
|
||||
int fd;
|
||||
|
||||
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_waitconnect = sock->has_wait ? sock->wait : false;
|
||||
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);
|
||||
if (!chr) {
|
||||
@ -4380,7 +4397,7 @@ static CharDriverState *qmp_chardev_open_udp(const char *id,
|
||||
Error **errp)
|
||||
{
|
||||
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();
|
||||
|
||||
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->path = g_strdup(sockpath);
|
||||
} else {
|
||||
InetSocketAddress *inet;
|
||||
saddr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
saddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
saddr->u.inet->host = g_strdup(bindto);
|
||||
inet = saddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
inet->host = g_strdup(bindto);
|
||||
if (port) {
|
||||
saddr->u.inet->port = g_strdup(port);
|
||||
inet->port = g_strdup(port);
|
||||
} 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)
|
||||
{
|
||||
InputKeyEvent *key;
|
||||
InputBtnEvent *btn;
|
||||
InputMoveEvent *move;
|
||||
replay_put_dword(evt->type);
|
||||
|
||||
switch (evt->type) {
|
||||
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:
|
||||
replay_put_qword(evt->u.key->key->u.number);
|
||||
replay_put_byte(evt->u.key->down);
|
||||
replay_put_qword(key->key->u.number);
|
||||
replay_put_byte(key->down);
|
||||
break;
|
||||
case KEY_VALUE_KIND_QCODE:
|
||||
replay_put_dword(evt->u.key->key->u.qcode);
|
||||
replay_put_byte(evt->u.key->down);
|
||||
replay_put_dword(key->key->u.qcode);
|
||||
replay_put_byte(key->down);
|
||||
break;
|
||||
case KEY_VALUE_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
@ -68,16 +72,19 @@ void replay_save_input_event(InputEvent *evt)
|
||||
}
|
||||
break;
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
replay_put_dword(evt->u.btn->button);
|
||||
replay_put_byte(evt->u.btn->down);
|
||||
btn = evt->u.btn;
|
||||
replay_put_dword(btn->button);
|
||||
replay_put_byte(btn->down);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
replay_put_dword(evt->u.rel->axis);
|
||||
replay_put_qword(evt->u.rel->value);
|
||||
move = evt->u.rel;
|
||||
replay_put_dword(move->axis);
|
||||
replay_put_qword(move->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_ABS:
|
||||
replay_put_dword(evt->u.abs->axis);
|
||||
replay_put_qword(evt->u.abs->value);
|
||||
move = evt->u.abs;
|
||||
replay_put_dword(move->axis);
|
||||
replay_put_qword(move->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
|
@ -111,7 +111,7 @@ def gen_marshal_input_visit(arg_type, dealloc=False):
|
||||
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:
|
||||
ret += mcgen('''
|
||||
@ -175,7 +175,7 @@ def gen_marshal(name, arg_type, ret_type):
|
||||
ret += gen_marshal_input_visit(arg_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
|
||||
if (arg_type and arg_type.members) or ret_type:
|
||||
ret += mcgen('''
|
||||
|
@ -67,8 +67,8 @@ def gen_event_send(name, arg_type):
|
||||
''',
|
||||
name=name)
|
||||
ret += gen_err_check()
|
||||
ret += gen_visit_fields(arg_type.members, need_cast=True,
|
||||
label='out_obj')
|
||||
ret += gen_visit_members(arg_type.members, need_cast=True,
|
||||
label='out_obj')
|
||||
ret += mcgen('''
|
||||
out_obj:
|
||||
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())
|
||||
|
||||
|
||||
def gen_struct_fields(members):
|
||||
def gen_struct_members(members):
|
||||
ret = ''
|
||||
for memb in members:
|
||||
if memb.optional:
|
||||
@ -77,22 +77,22 @@ struct %(c_name)s {
|
||||
/* Members inherited from %(c_name)s: */
|
||||
''',
|
||||
c_name=base.c_name())
|
||||
ret += gen_struct_fields(base.members)
|
||||
ret += gen_struct_members(base.members)
|
||||
ret += mcgen('''
|
||||
/* Own members: */
|
||||
''')
|
||||
ret += gen_struct_fields(members)
|
||||
ret += gen_struct_members(members)
|
||||
|
||||
if 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
|
||||
# structs in C, and also incompatibility with C++ (where an empty
|
||||
# struct is size 1).
|
||||
if not (base and base.members) and not members and not variants:
|
||||
ret += mcgen('''
|
||||
char qapi_dummy_field_for_empty_struct;
|
||||
char qapi_dummy_for_empty_struct;
|
||||
''')
|
||||
|
||||
ret += mcgen('''
|
||||
@ -116,17 +116,8 @@ static inline %(base)s *qapi_%(c_name)s_base(const %(c_name)s *obj)
|
||||
|
||||
|
||||
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('''
|
||||
union { /* union tag is @%(c_name)s */
|
||||
void *data;
|
||||
''',
|
||||
c_name=c_name(variants.tag_member.name))
|
||||
|
||||
|
@ -15,10 +15,6 @@
|
||||
from qapi import *
|
||||
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):
|
||||
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)
|
||||
|
||||
|
||||
def gen_visit_fields_decl(typ):
|
||||
if typ.name in struct_fields_seen:
|
||||
return ''
|
||||
struct_fields_seen.add(typ.name)
|
||||
def gen_visit_members_decl(name):
|
||||
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):
|
||||
ret = ''
|
||||
def gen_visit_object_members(name, base, members, variants):
|
||||
ret = mcgen('''
|
||||
|
||||
if base:
|
||||
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)
|
||||
void visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
c_name=c_name(name))
|
||||
|
||||
if base:
|
||||
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())
|
||||
ret += gen_err_check()
|
||||
|
||||
ret += gen_visit_fields(members, prefix='obj->')
|
||||
ret += gen_visit_members(members, prefix='obj->')
|
||||
|
||||
if variants:
|
||||
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))
|
||||
else:
|
||||
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_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
|
||||
if base or members or variants:
|
||||
ret += mcgen('''
|
||||
@ -173,8 +155,6 @@ def gen_visit_alternate(name, variants):
|
||||
for var in variants.variants:
|
||||
if var.type.alternate_qtype() == 'QTYPE_QINT':
|
||||
promote_int = 'false'
|
||||
if isinstance(var.type, QAPISchemaObjectType):
|
||||
ret += gen_visit_fields_decl(var.type)
|
||||
|
||||
ret += mcgen('''
|
||||
|
||||
@ -202,7 +182,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
|
||||
if (err) {
|
||||
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);
|
||||
err = NULL;
|
||||
visit_end_struct(v, &err);
|
||||
@ -235,10 +215,10 @@ out:
|
||||
|
||||
|
||||
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
|
||||
# *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
|
||||
# call qapi_free_FOO() to avoid a memory leak of the partial FOO.
|
||||
ret += mcgen('''
|
||||
@ -254,7 +234,7 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
|
||||
if (!*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);
|
||||
err = NULL;
|
||||
out_obj:
|
||||
@ -316,6 +296,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
|
||||
self.defn += defn
|
||||
|
||||
def visit_object_type(self, name, info, base, members, variants):
|
||||
self.decl += gen_visit_members_decl(name)
|
||||
self.decl += gen_visit_decl(name)
|
||||
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)
|
||||
if not base_struct_define:
|
||||
return None
|
||||
@ -355,11 +355,11 @@ def discriminator_find_enum_define(expr):
|
||||
if not (discriminator and base):
|
||||
return None
|
||||
|
||||
base_fields = find_base_fields(base)
|
||||
if not base_fields:
|
||||
base_members = find_base_members(base)
|
||||
if not base_members:
|
||||
return None
|
||||
|
||||
discriminator_type = base_fields.get(discriminator)
|
||||
discriminator_type = base_members.get(discriminator)
|
||||
if not discriminator_type:
|
||||
return None
|
||||
|
||||
@ -567,14 +567,14 @@ def check_union(expr, expr_info):
|
||||
raise QAPIExprError(expr_info,
|
||||
"Flat union '%s' must have a base"
|
||||
% name)
|
||||
base_fields = find_base_fields(base)
|
||||
assert base_fields
|
||||
base_members = find_base_members(base)
|
||||
assert base_members
|
||||
|
||||
# The value of member 'discriminator' must name a non-optional
|
||||
# member of the base struct.
|
||||
check_name(expr_info, "Discriminator of flat union '%s'" % name,
|
||||
discriminator)
|
||||
discriminator_type = base_fields.get(discriminator)
|
||||
discriminator_type = base_members.get(discriminator)
|
||||
if not discriminator_type:
|
||||
raise QAPIExprError(expr_info,
|
||||
"Discriminator '%s' is not a member of base "
|
||||
@ -969,7 +969,7 @@ class QAPISchemaObjectType(QAPISchemaType):
|
||||
assert self.variants.tag_member in self.members
|
||||
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
|
||||
# on behalf of info, which is not necessarily self.info
|
||||
def check_clash(self, schema, info, seen):
|
||||
@ -1647,8 +1647,8 @@ def gen_err_check(label='out', skiperr=False):
|
||||
label=label)
|
||||
|
||||
|
||||
def gen_visit_fields(members, prefix='', need_cast=False, skiperr=False,
|
||||
label='out'):
|
||||
def gen_visit_members(members, prefix='', need_cast=False, skiperr=False,
|
||||
label='out'):
|
||||
ret = ''
|
||||
if skiperr:
|
||||
errparg = 'NULL'
|
||||
|
@ -70,7 +70,6 @@ import json
|
||||
import ast
|
||||
import readline
|
||||
import sys
|
||||
import pprint
|
||||
|
||||
class QMPCompleter(list):
|
||||
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
|
||||
# _execute_cmd()). Let's design a better one.
|
||||
class QMPShell(qmp.QEMUMonitorProtocol):
|
||||
def __init__(self, address, pp=None):
|
||||
def __init__(self, address, pretty=False):
|
||||
qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
|
||||
self._greeting = None
|
||||
self._completer = None
|
||||
self._pp = pp
|
||||
self._pretty = pretty
|
||||
self._transmode = False
|
||||
self._actions = list()
|
||||
|
||||
@ -231,11 +230,11 @@ class QMPShell(qmp.QEMUMonitorProtocol):
|
||||
return qmpcmd
|
||||
|
||||
def _print(self, qmp):
|
||||
jsobj = json.dumps(qmp)
|
||||
if self._pp is not None:
|
||||
self._pp.pprint(jsobj)
|
||||
else:
|
||||
print str(jsobj)
|
||||
indent = None
|
||||
if self._pretty:
|
||||
indent = 4
|
||||
jsobj = json.dumps(qmp, indent=indent)
|
||||
print str(jsobj)
|
||||
|
||||
def _execute_cmd(self, cmdline):
|
||||
try:
|
||||
@ -377,7 +376,7 @@ def main():
|
||||
addr = ''
|
||||
qemu = None
|
||||
hmp = False
|
||||
pp = None
|
||||
pretty = False
|
||||
verbose = False
|
||||
|
||||
try:
|
||||
@ -387,9 +386,7 @@ def main():
|
||||
fail_cmdline(arg)
|
||||
hmp = True
|
||||
elif arg == "-p":
|
||||
if pp is not None:
|
||||
fail_cmdline(arg)
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
pretty = True
|
||||
elif arg == "-v":
|
||||
verbose = True
|
||||
else:
|
||||
@ -398,7 +395,7 @@ def main():
|
||||
if hmp:
|
||||
qemu = HMPShell(arg)
|
||||
else:
|
||||
qemu = QMPShell(arg, pp)
|
||||
qemu = QMPShell(arg, pretty)
|
||||
addr = arg
|
||||
|
||||
if qemu is None:
|
||||
|
@ -358,7 +358,6 @@ qapi-schema += unicode-str.json
|
||||
qapi-schema += union-base-no-discriminator.json
|
||||
qapi-schema += union-branch-case.json
|
||||
qapi-schema += union-clash-branches.json
|
||||
qapi-schema += union-clash-data.json
|
||||
qapi-schema += union-empty.json
|
||||
qapi-schema += union-invalid-base.json
|
||||
qapi-schema += union-optional-branch.json
|
||||
|
@ -77,7 +77,7 @@
|
||||
'base': 'UserDefZero',
|
||||
'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
|
||||
{ 'union': 'UserDefFlatUnion2',
|
||||
'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
|
||||
*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
* Copyright (c) 2015-2016 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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);
|
||||
|
||||
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
listen_addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
listen_addr->u.inet->host = g_strdup("127.0.0.1");
|
||||
listen_addr->u.inet->port = NULL; /* Auto-select */
|
||||
listen_addr->u.inet = g_new(InetSocketAddress, 1);
|
||||
*listen_addr->u.inet = (InetSocketAddress) {
|
||||
.host = g_strdup("127.0.0.1"),
|
||||
.port = NULL, /* Auto-select */
|
||||
};
|
||||
|
||||
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
connect_addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
connect_addr->u.inet->host = g_strdup("127.0.0.1");
|
||||
connect_addr->u.inet->port = NULL; /* Filled in later */
|
||||
connect_addr->u.inet = g_new(InetSocketAddress, 1);
|
||||
*connect_addr->u.inet = (InetSocketAddress) {
|
||||
.host = g_strdup("127.0.0.1"),
|
||||
.port = NULL, /* Filled in later */
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
listen_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
listen_addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
listen_addr->u.inet->host = g_strdup("::1");
|
||||
listen_addr->u.inet->port = NULL; /* Auto-select */
|
||||
listen_addr->u.inet = g_new(InetSocketAddress, 1);
|
||||
*listen_addr->u.inet = (InetSocketAddress) {
|
||||
.host = g_strdup("::1"),
|
||||
.port = NULL, /* Auto-select */
|
||||
};
|
||||
|
||||
connect_addr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
connect_addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
connect_addr->u.inet->host = g_strdup("::1");
|
||||
connect_addr->u.inet->port = NULL; /* Filled in later */
|
||||
connect_addr->u.inet = g_new(InetSocketAddress, 1);
|
||||
*connect_addr->u.inet = (InetSocketAddress) {
|
||||
.host = g_strdup("::1"),
|
||||
.port = NULL, /* Filled in later */
|
||||
};
|
||||
|
||||
test_io_channel(async, listen_addr, connect_addr, false);
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "qemu/option.h" /* qemu_opts_parse() */
|
||||
#include "qapi/opts-visitor.h" /* opts_visitor_new() */
|
||||
#include "test-qapi-visit.h" /* visit_type_UserDefOptions() */
|
||||
#include "qapi/dealloc-visitor.h" /* qapi_dealloc_visitor_new() */
|
||||
|
||||
static QemuOptsList userdef_opts = {
|
||||
.name = "userdef",
|
||||
@ -55,14 +54,7 @@ setup_fixture(OptsVisitorFixture *f, gconstpointer test_data)
|
||||
static void
|
||||
teardown_fixture(OptsVisitorFixture *f, gconstpointer test_data)
|
||||
{
|
||||
if (f->userdef != NULL) {
|
||||
QapiDeallocVisitor *dv;
|
||||
|
||||
dv = qapi_dealloc_visitor_new();
|
||||
visit_type_UserDefOptions(qapi_dealloc_get_visitor(dv), NULL,
|
||||
&f->userdef, NULL);
|
||||
qapi_dealloc_visitor_cleanup(dv);
|
||||
}
|
||||
qapi_free_UserDefOptions(f->userdef);
|
||||
error_free(f->err);
|
||||
}
|
||||
|
||||
|
@ -110,12 +110,13 @@ static void legacy_kbd_event(DeviceState *dev, QemuConsole *src,
|
||||
{
|
||||
QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev;
|
||||
int scancodes[3], i, count;
|
||||
InputKeyEvent *key = evt->u.key;
|
||||
|
||||
if (!entry || !entry->put_kbd) {
|
||||
return;
|
||||
}
|
||||
count = qemu_input_key_value_to_scancode(evt->u.key->key,
|
||||
evt->u.key->down,
|
||||
count = qemu_input_key_value_to_scancode(key->key,
|
||||
key->down,
|
||||
scancodes);
|
||||
for (i = 0; i < count; 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,
|
||||
};
|
||||
QEMUPutMouseEntry *s = (QEMUPutMouseEntry *)dev;
|
||||
InputBtnEvent *btn;
|
||||
InputMoveEvent *move;
|
||||
|
||||
switch (evt->type) {
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
if (evt->u.btn->down) {
|
||||
s->buttons |= bmap[evt->u.btn->button];
|
||||
btn = evt->u.btn;
|
||||
if (btn->down) {
|
||||
s->buttons |= bmap[btn->button];
|
||||
} 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->axis[INPUT_AXIS_X],
|
||||
s->axis[INPUT_AXIS_Y],
|
||||
-1,
|
||||
s->buttons);
|
||||
}
|
||||
if (evt->u.btn->down &&
|
||||
evt->u.btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
if (btn->down && btn->button == INPUT_BUTTON_WHEEL_DOWN) {
|
||||
s->qemu_put_mouse_event(s->qemu_put_mouse_event_opaque,
|
||||
s->axis[INPUT_AXIS_X],
|
||||
s->axis[INPUT_AXIS_Y],
|
||||
@ -175,10 +178,12 @@ static void legacy_mouse_event(DeviceState *dev, QemuConsole *src,
|
||||
}
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
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)
|
||||
{
|
||||
InputMoveEvent *move = evt->u.abs;
|
||||
switch (graphic_rotate) {
|
||||
case 90:
|
||||
if (evt->u.abs->axis == INPUT_AXIS_X) {
|
||||
evt->u.abs->axis = INPUT_AXIS_Y;
|
||||
} else if (evt->u.abs->axis == INPUT_AXIS_Y) {
|
||||
evt->u.abs->axis = INPUT_AXIS_X;
|
||||
evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value;
|
||||
if (move->axis == INPUT_AXIS_X) {
|
||||
move->axis = INPUT_AXIS_Y;
|
||||
} else if (move->axis == INPUT_AXIS_Y) {
|
||||
move->axis = INPUT_AXIS_X;
|
||||
move->value = INPUT_EVENT_ABS_SIZE - 1 - move->value;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
case 270:
|
||||
if (evt->u.abs->axis == INPUT_AXIS_X) {
|
||||
evt->u.abs->axis = INPUT_AXIS_Y;
|
||||
evt->u.abs->value = INPUT_EVENT_ABS_SIZE - 1 - evt->u.abs->value;
|
||||
} else if (evt->u.abs->axis == INPUT_AXIS_Y) {
|
||||
evt->u.abs->axis = INPUT_AXIS_X;
|
||||
if (move->axis == INPUT_AXIS_X) {
|
||||
move->axis = INPUT_AXIS_Y;
|
||||
move->value = INPUT_EVENT_ABS_SIZE - 1 - move->value;
|
||||
} else if (move->axis == INPUT_AXIS_Y) {
|
||||
move->axis = INPUT_AXIS_X;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -193,22 +194,26 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
|
||||
{
|
||||
const char *name;
|
||||
int qcode, idx = -1;
|
||||
InputKeyEvent *key;
|
||||
InputBtnEvent *btn;
|
||||
InputMoveEvent *move;
|
||||
|
||||
if (src) {
|
||||
idx = qemu_console_get_index(src);
|
||||
}
|
||||
switch (evt->type) {
|
||||
case INPUT_EVENT_KIND_KEY:
|
||||
switch (evt->u.key->key->type) {
|
||||
key = evt->u.key;
|
||||
switch (key->key->type) {
|
||||
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];
|
||||
trace_input_event_key_number(idx, evt->u.key->key->u.number,
|
||||
name, evt->u.key->down);
|
||||
trace_input_event_key_number(idx, key->key->u.number,
|
||||
name, key->down);
|
||||
break;
|
||||
case KEY_VALUE_KIND_QCODE:
|
||||
name = QKeyCode_lookup[evt->u.key->key->u.qcode];
|
||||
trace_input_event_key_qcode(idx, name, evt->u.key->down);
|
||||
name = QKeyCode_lookup[key->key->u.qcode];
|
||||
trace_input_event_key_qcode(idx, name, key->down);
|
||||
break;
|
||||
case KEY_VALUE_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
@ -216,16 +221,19 @@ static void qemu_input_event_trace(QemuConsole *src, InputEvent *evt)
|
||||
}
|
||||
break;
|
||||
case INPUT_EVENT_KIND_BTN:
|
||||
name = InputButton_lookup[evt->u.btn->button];
|
||||
trace_input_event_btn(idx, name, evt->u.btn->down);
|
||||
btn = evt->u.btn;
|
||||
name = InputButton_lookup[btn->button];
|
||||
trace_input_event_btn(idx, name, btn->down);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_REL:
|
||||
name = InputAxis_lookup[evt->u.rel->axis];
|
||||
trace_input_event_rel(idx, name, evt->u.rel->value);
|
||||
move = evt->u.rel;
|
||||
name = InputAxis_lookup[move->axis];
|
||||
trace_input_event_rel(idx, name, move->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND_ABS:
|
||||
name = InputAxis_lookup[evt->u.abs->axis];
|
||||
trace_input_event_abs(idx, name, evt->u.abs->value);
|
||||
move = evt->u.abs;
|
||||
name = InputAxis_lookup[move->axis];
|
||||
trace_input_event_abs(idx, name, move->value);
|
||||
break;
|
||||
case INPUT_EVENT_KIND__MAX:
|
||||
/* keep gcc happy */
|
||||
@ -462,7 +470,7 @@ InputEvent *qemu_input_event_new_move(InputEventKind kind,
|
||||
InputMoveEvent *move = g_new0(InputMoveEvent, 1);
|
||||
|
||||
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->value = value;
|
||||
return evt;
|
||||
|
39
ui/vnc.c
39
ui/vnc.c
@ -3530,12 +3530,13 @@ void vnc_display_open(const char *id, Error **errp)
|
||||
}
|
||||
} else {
|
||||
unsigned long long baseport;
|
||||
InetSocketAddress *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] == ']') {
|
||||
saddr->u.inet->host = g_strndup(vnc + 1, hlen - 2);
|
||||
inet->host = g_strndup(vnc + 1, hlen - 2);
|
||||
} else {
|
||||
saddr->u.inet->host = g_strndup(vnc, hlen);
|
||||
inet->host = g_strndup(vnc, hlen);
|
||||
}
|
||||
if (parse_uint_full(h + 1, &baseport, 10) < 0) {
|
||||
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);
|
||||
goto fail;
|
||||
}
|
||||
saddr->u.inet->port = g_strdup_printf(
|
||||
inet->port = g_strdup_printf(
|
||||
"%d", (int)baseport + 5900);
|
||||
|
||||
if (to) {
|
||||
saddr->u.inet->has_to = true;
|
||||
saddr->u.inet->to = to + 5900;
|
||||
inet->has_to = true;
|
||||
inet->to = to + 5900;
|
||||
}
|
||||
saddr->u.inet->ipv4 = ipv4;
|
||||
saddr->u.inet->has_ipv4 = has_ipv4;
|
||||
saddr->u.inet->ipv6 = ipv6;
|
||||
saddr->u.inet->has_ipv6 = has_ipv6;
|
||||
inet->ipv4 = ipv4;
|
||||
inet->has_ipv4 = has_ipv4;
|
||||
inet->ipv6 = ipv6;
|
||||
inet->has_ipv6 = has_ipv6;
|
||||
|
||||
if (vs->ws_enabled) {
|
||||
wsaddr->type = SOCKET_ADDRESS_KIND_INET;
|
||||
wsaddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
wsaddr->u.inet->host = g_strdup(saddr->u.inet->host);
|
||||
wsaddr->u.inet->port = g_strdup(websocket);
|
||||
inet = wsaddr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
inet->host = g_strdup(saddr->u.inet->host);
|
||||
inet->port = g_strdup(websocket);
|
||||
|
||||
if (to) {
|
||||
wsaddr->u.inet->has_to = true;
|
||||
wsaddr->u.inet->to = to;
|
||||
inet->has_to = true;
|
||||
inet->to = to;
|
||||
}
|
||||
wsaddr->u.inet->ipv4 = ipv4;
|
||||
wsaddr->u.inet->has_ipv4 = has_ipv4;
|
||||
wsaddr->u.inet->ipv6 = ipv6;
|
||||
wsaddr->u.inet->has_ipv6 = has_ipv6;
|
||||
inet->ipv4 = ipv4;
|
||||
inet->has_ipv4 = has_ipv4;
|
||||
inet->ipv6 = ipv6;
|
||||
inet->has_ipv6 = has_ipv6;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1003,6 +1003,7 @@ socket_sockaddr_to_address_inet(struct sockaddr_storage *sa,
|
||||
char host[NI_MAXHOST];
|
||||
char serv[NI_MAXSERV];
|
||||
SocketAddress *addr;
|
||||
InetSocketAddress *inet;
|
||||
int ret;
|
||||
|
||||
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->type = SOCKET_ADDRESS_KIND_INET;
|
||||
addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
addr->u.inet->host = g_strdup(host);
|
||||
addr->u.inet->port = g_strdup(serv);
|
||||
inet = addr->u.inet = g_new0(InetSocketAddress, 1);
|
||||
inet->host = g_strdup(host);
|
||||
inet->port = g_strdup(serv);
|
||||
if (sa->ss_family == AF_INET) {
|
||||
addr->u.inet->has_ipv4 = addr->u.inet->ipv4 = true;
|
||||
inet->has_ipv4 = inet->ipv4 = true;
|
||||
} else {
|
||||
addr->u.inet->has_ipv6 = addr->u.inet->ipv6 = true;
|
||||
inet->has_ipv6 = inet->ipv6 = true;
|
||||
}
|
||||
|
||||
return addr;
|
||||
|
Loading…
Reference in New Issue
Block a user