Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 1 | = How to write QMP commands using the QAPI framework = |
| 2 | |
| 3 | This document is a step-by-step guide on how to write new QMP commands using |
| 4 | the QAPI framework. It also shows how to implement new style HMP commands. |
| 5 | |
| 6 | This document doesn't discuss QMP protocol level details, nor does it dive |
| 7 | into the QAPI framework implementation. |
| 8 | |
| 9 | For an in-depth introduction to the QAPI framework, please refer to |
| 10 | docs/qapi-code-gen.txt. For documentation about the QMP protocol, please |
| 11 | check the files in QMP/. |
| 12 | |
| 13 | == Overview == |
| 14 | |
| 15 | Generally speaking, the following steps should be taken in order to write a |
| 16 | new QMP command. |
| 17 | |
| 18 | 1. Write the command's and type(s) specification in the QAPI schema file |
| 19 | (qapi-schema.json in the root source directory) |
| 20 | |
| 21 | 2. Write the QMP command itself, which is a regular C function. Preferably, |
| 22 | the command should be exported by some QEMU subsystem. But it can also be |
| 23 | added to the qmp.c file |
| 24 | |
| 25 | 3. At this point the command can be tested under the QMP protocol |
| 26 | |
| 27 | 4. Write the HMP command equivalent. This is not required and should only be |
| 28 | done if it does make sense to have the functionality in HMP. The HMP command |
| 29 | is implemented in terms of the QMP command |
| 30 | |
| 31 | The following sections will demonstrate each of the steps above. We will start |
| 32 | very simple and get more complex as we progress. |
| 33 | |
| 34 | === Testing === |
| 35 | |
| 36 | For all the examples in the next sections, the test setup is the same and is |
| 37 | shown here. |
| 38 | |
| 39 | First, QEMU should be started as: |
| 40 | |
| 41 | # /path/to/your/source/qemu [...] \ |
| 42 | -chardev socket,id=qmp,port=4444,host=localhost,server \ |
| 43 | -mon chardev=qmp,mode=control,pretty=on |
| 44 | |
| 45 | Then, in a different terminal: |
| 46 | |
| 47 | $ telnet localhost 4444 |
| 48 | Trying 127.0.0.1... |
| 49 | Connected to localhost. |
| 50 | Escape character is '^]'. |
| 51 | { |
| 52 | "QMP": { |
| 53 | "version": { |
| 54 | "qemu": { |
| 55 | "micro": 50, |
| 56 | "minor": 15, |
| 57 | "major": 0 |
| 58 | }, |
| 59 | "package": "" |
| 60 | }, |
| 61 | "capabilities": [ |
| 62 | ] |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | The above output is the QMP server saying you're connected. The server is |
| 67 | actually in capabilities negotiation mode. To enter in command mode type: |
| 68 | |
| 69 | { "execute": "qmp_capabilities" } |
| 70 | |
| 71 | Then the server should respond: |
| 72 | |
| 73 | { |
| 74 | "return": { |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | Which is QMP's way of saying "the latest command executed OK and didn't return |
| 79 | any data". Now you're ready to enter the QMP example commands as explained in |
| 80 | the following sections. |
| 81 | |
| 82 | == Writing a command that doesn't return data == |
| 83 | |
| 84 | That's the most simple QMP command that can be written. Usually, this kind of |
| 85 | command carries some meaningful action in QEMU but here it will just print |
| 86 | "Hello, world" to the standard output. |
| 87 | |
| 88 | Our command will be called "hello-world". It takes no arguments, nor does it |
| 89 | return any data. |
| 90 | |
| 91 | The first step is to add the following line to the bottom of the |
| 92 | qapi-schema.json file: |
| 93 | |
| 94 | { 'command': 'hello-world' } |
| 95 | |
| 96 | The "command" keyword defines a new QMP command. It's an JSON object. All |
| 97 | schema entries are JSON objects. The line above will instruct the QAPI to |
| 98 | generate any prototypes and the necessary code to marshal and unmarshal |
| 99 | protocol data. |
| 100 | |
| 101 | The next step is to write the "hello-world" implementation. As explained |
| 102 | earlier, it's preferable for commands to live in QEMU subsystems. But |
| 103 | "hello-world" doesn't pertain to any, so we put its implementation in qmp.c: |
| 104 | |
| 105 | void qmp_hello_world(Error **errp) |
| 106 | { |
| 107 | printf("Hello, world!\n"); |
| 108 | } |
| 109 | |
| 110 | There are a few things to be noticed: |
| 111 | |
| 112 | 1. QMP command implementation functions must be prefixed with "qmp_" |
| 113 | 2. qmp_hello_world() returns void, this is in accordance with the fact that the |
| 114 | command doesn't return any data |
| 115 | 3. It takes an "Error **" argument. This is required. Later we will see how to |
| 116 | return errors and take additional arguments. The Error argument should not |
| 117 | be touched if the command doesn't return errors |
| 118 | 4. We won't add the function's prototype. That's automatically done by the QAPI |
| 119 | 5. Printing to the terminal is discouraged for QMP commands, we do it here |
| 120 | because it's the easiest way to demonstrate a QMP command |
| 121 | |
| 122 | Now a little hack is needed. As we're still using the old QMP server we need |
| 123 | to add the new command to its internal dispatch table. This step won't be |
| 124 | required in the near future. Open the qmp-commands.hx file and add the |
| 125 | following in the botton: |
| 126 | |
| 127 | { |
| 128 | .name = "hello-world", |
| 129 | .args_type = "", |
| 130 | .mhandler.cmd_new = qmp_marshal_input_hello_world, |
| 131 | }, |
| 132 | |
| 133 | You're done. Now build qemu, run it as suggested in the "Testing" section, |
| 134 | and then type the following QMP command: |
| 135 | |
| 136 | { "execute": "hello-world" } |
| 137 | |
| 138 | Then check the terminal running qemu and look for the "Hello, world" string. If |
| 139 | you don't see it then something went wrong. |
| 140 | |
| 141 | === Arguments === |
| 142 | |
| 143 | Let's add an argument called "message" to our "hello-world" command. The new |
| 144 | argument will contain the string to be printed to stdout. It's an optional |
| 145 | argument, if it's not present we print our default "Hello, World" string. |
| 146 | |
| 147 | The first change we have to do is to modify the command specification in the |
| 148 | schema file to the following: |
| 149 | |
| 150 | { 'command': 'hello-world', 'data': { '*message': 'str' } } |
| 151 | |
| 152 | Notice the new 'data' member in the schema. It's an JSON object whose each |
| 153 | element is an argument to the command in question. Also notice the asterisk, |
| 154 | it's used to mark the argument optional (that means that you shouldn't use it |
| 155 | for mandatory arguments). Finally, 'str' is the argument's type, which |
| 156 | stands for "string". The QAPI also supports integers, booleans, enumerations |
| 157 | and user defined types. |
| 158 | |
| 159 | Now, let's update our C implementation in qmp.c: |
| 160 | |
| 161 | void qmp_hello_world(bool has_message, const char *message, Error **errp) |
| 162 | { |
| 163 | if (has_message) { |
| 164 | printf("%s\n", message); |
| 165 | } else { |
| 166 | printf("Hello, world\n"); |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | There are two important details to be noticed: |
| 171 | |
| 172 | 1. All optional arguments are accompanied by a 'has_' boolean, which is set |
| 173 | if the optional argument is present or false otherwise |
| 174 | 2. The C implementation signature must follow the schema's argument ordering, |
| 175 | which is defined by the "data" member |
| 176 | |
| 177 | The last step is to update the qmp-commands.hx file: |
| 178 | |
| 179 | { |
| 180 | .name = "hello-world", |
| 181 | .args_type = "message:s?", |
| 182 | .mhandler.cmd_new = qmp_marshal_input_hello_world, |
| 183 | }, |
| 184 | |
| 185 | Notice that the "args_type" member got our "message" argument. The character |
| 186 | "s" stands for "string" and "?" means it's optional. This too must be ordered |
| 187 | according to the C implementation and schema file. You can look for more |
| 188 | examples in the qmp-commands.hx file if you need to define more arguments. |
| 189 | |
| 190 | Again, this step won't be required in the future. |
| 191 | |
| 192 | Time to test our new version of the "hello-world" command. Build qemu, run it as |
| 193 | described in the "Testing" section and then send two commands: |
| 194 | |
| 195 | { "execute": "hello-world" } |
| 196 | { |
| 197 | "return": { |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | { "execute": "hello-world", "arguments": { "message": "We love qemu" } } |
| 202 | { |
| 203 | "return": { |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | You should see "Hello, world" and "we love qemu" in the terminal running qemu, |
| 208 | if you don't see these strings, then something went wrong. |
| 209 | |
| 210 | === Errors === |
| 211 | |
| 212 | QMP commands should use the error interface exported by the error.h header |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 213 | file. Basically, errors are set by calling the error_set() function. |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 214 | |
| 215 | Let's say we don't accept the string "message" to contain the word "love". If |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 216 | it does contain it, we want the "hello-world" command to return an error: |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 217 | |
| 218 | void qmp_hello_world(bool has_message, const char *message, Error **errp) |
| 219 | { |
| 220 | if (has_message) { |
| 221 | if (strstr(message, "love")) { |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 222 | error_set(errp, ERROR_CLASS_GENERIC_ERROR, |
| 223 | "the word 'love' is not allowed"); |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 224 | return; |
| 225 | } |
| 226 | printf("%s\n", message); |
| 227 | } else { |
| 228 | printf("Hello, world\n"); |
| 229 | } |
| 230 | } |
| 231 | |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 232 | The first argument to the error_set() function is the Error pointer to pointer, |
| 233 | which is passed to all QMP functions. The second argument is a ErrorClass |
| 234 | value, which should be ERROR_CLASS_GENERIC_ERROR most of the time (more |
| 235 | details about error classes are given below). The third argument is a human |
| 236 | description of the error, this is a free-form printf-like string. |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 237 | |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 238 | Let's test the example above. Build qemu, run it as defined in the "Testing" |
| 239 | section, and then issue the following command: |
| 240 | |
| 241 | { "execute": "hello-world", "arguments": { "message": "all you need is love" } } |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 242 | |
| 243 | The QMP server's response should be: |
| 244 | |
| 245 | { |
| 246 | "error": { |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 247 | "class": "GenericError", |
| 248 | "desc": "the word 'love' is not allowed" |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 249 | } |
| 250 | } |
| 251 | |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 252 | As a general rule, all QMP errors should use ERROR_CLASS_GENERIC_ERROR. There |
| 253 | are two exceptions to this rule: |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 254 | |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 255 | 1. A non-generic ErrorClass value exists* for the failure you want to report |
| 256 | (eg. DeviceNotFound) |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 257 | |
Luiz Capitulino | adb2072 | 2012-08-06 11:35:22 -0300 | [diff] [blame] | 258 | 2. Management applications have to take special action on the failure you |
| 259 | want to report, hence you have to add a new ErrorClass value so that they |
| 260 | can check for it |
| 261 | |
| 262 | If the failure you want to report doesn't fall in one of the two cases above, |
| 263 | just report ERROR_CLASS_GENERIC_ERROR. |
| 264 | |
| 265 | * All existing ErrorClass values are defined in the qapi-schema.json file |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 266 | |
| 267 | === Command Documentation === |
| 268 | |
| 269 | There's only one step missing to make "hello-world"'s implementation complete, |
| 270 | and that's its documentation in the schema file. |
| 271 | |
| 272 | This is very important. No QMP command will be accepted in QEMU without proper |
| 273 | documentation. |
| 274 | |
| 275 | There are many examples of such documentation in the schema file already, but |
| 276 | here goes "hello-world"'s new entry for the qapi-schema.json file: |
| 277 | |
| 278 | ## |
| 279 | # @hello-world |
| 280 | # |
| 281 | # Print a client provided string to the standard output stream. |
| 282 | # |
| 283 | # @message: #optional string to be printed |
| 284 | # |
| 285 | # Returns: Nothing on success. |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 286 | # |
| 287 | # Notes: if @message is not provided, the "Hello, world" string will |
| 288 | # be printed instead |
| 289 | # |
| 290 | # Since: <next qemu stable release, eg. 1.0> |
| 291 | ## |
| 292 | { 'command': 'hello-world', 'data': { '*message': 'str' } } |
| 293 | |
| 294 | Please, note that the "Returns" clause is optional if a command doesn't return |
| 295 | any data nor any errors. |
| 296 | |
| 297 | === Implementing the HMP command === |
| 298 | |
| 299 | Now that the QMP command is in place, we can also make it available in the human |
| 300 | monitor (HMP). |
| 301 | |
| 302 | With the introduction of the QAPI, HMP commands make QMP calls. Most of the |
| 303 | time HMP commands are simple wrappers. All HMP commands implementation exist in |
| 304 | the hmp.c file. |
| 305 | |
| 306 | Here's the implementation of the "hello-world" HMP command: |
| 307 | |
| 308 | void hmp_hello_world(Monitor *mon, const QDict *qdict) |
| 309 | { |
| 310 | const char *message = qdict_get_try_str(qdict, "message"); |
| 311 | Error *errp = NULL; |
| 312 | |
| 313 | qmp_hello_world(!!message, message, &errp); |
| 314 | if (error_is_set(&errp)) { |
| 315 | monitor_printf(mon, "%s\n", error_get_pretty(errp)); |
| 316 | error_free(errp); |
| 317 | return; |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | Also, you have to add the function's prototype to the hmp.h file. |
| 322 | |
| 323 | There are three important points to be noticed: |
| 324 | |
| 325 | 1. The "mon" and "qdict" arguments are mandatory for all HMP functions. The |
| 326 | former is the monitor object. The latter is how the monitor passes |
| 327 | arguments entered by the user to the command implementation |
| 328 | 2. hmp_hello_world() performs error checking. In this example we just print |
| 329 | the error description to the user, but we could do more, like taking |
| 330 | different actions depending on the error qmp_hello_world() returns |
| 331 | 3. The "errp" variable must be initialized to NULL before performing the |
| 332 | QMP call |
| 333 | |
| 334 | There's one last step to actually make the command available to monitor users, |
| 335 | we should add it to the hmp-commands.hx file: |
| 336 | |
| 337 | { |
| 338 | .name = "hello-world", |
| 339 | .args_type = "message:s?", |
| 340 | .params = "hello-world [message]", |
| 341 | .help = "Print message to the standard output", |
| 342 | .mhandler.cmd = hmp_hello_world, |
| 343 | }, |
| 344 | |
| 345 | STEXI |
| 346 | @item hello_world @var{message} |
| 347 | @findex hello_world |
| 348 | Print message to the standard output |
| 349 | ETEXI |
| 350 | |
| 351 | To test this you have to open a user monitor and issue the "hello-world" |
| 352 | command. It might be instructive to check the command's documentation with |
| 353 | HMP's "help" command. |
| 354 | |
| 355 | Please, check the "-monitor" command-line option to know how to open a user |
| 356 | monitor. |
| 357 | |
| 358 | == Writing a command that returns data == |
| 359 | |
| 360 | A QMP command is capable of returning any data the QAPI supports like integers, |
| 361 | strings, booleans, enumerations and user defined types. |
| 362 | |
| 363 | In this section we will focus on user defined types. Please, check the QAPI |
| 364 | documentation for information about the other types. |
| 365 | |
| 366 | === User Defined Types === |
| 367 | |
| 368 | For this example we will write the query-alarm-clock command, which returns |
| 369 | information about QEMU's timer alarm. For more information about it, please |
| 370 | check the "-clock" command-line option. |
| 371 | |
| 372 | We want to return two pieces of information. The first one is the alarm clock's |
| 373 | name. The second one is when the next alarm will fire. The former information is |
| 374 | returned as a string, the latter is an integer in nanoseconds (which is not |
| 375 | very useful in practice, as the timer has probably already fired when the |
| 376 | information reaches the client). |
| 377 | |
| 378 | The best way to return that data is to create a new QAPI type, as shown below: |
| 379 | |
| 380 | ## |
| 381 | # @QemuAlarmClock |
| 382 | # |
| 383 | # QEMU alarm clock information. |
| 384 | # |
| 385 | # @clock-name: The alarm clock method's name. |
| 386 | # |
| 387 | # @next-deadline: #optional The time (in nanoseconds) the next alarm will fire. |
| 388 | # |
| 389 | # Since: 1.0 |
| 390 | ## |
| 391 | { 'type': 'QemuAlarmClock', |
| 392 | 'data': { 'clock-name': 'str', '*next-deadline': 'int' } } |
| 393 | |
| 394 | The "type" keyword defines a new QAPI type. Its "data" member contains the |
| 395 | type's members. In this example our members are the "clock-name" and the |
| 396 | "next-deadline" one, which is optional. |
| 397 | |
| 398 | Now let's define the query-alarm-clock command: |
| 399 | |
| 400 | ## |
| 401 | # @query-alarm-clock |
| 402 | # |
| 403 | # Return information about QEMU's alarm clock. |
| 404 | # |
| 405 | # Returns a @QemuAlarmClock instance describing the alarm clock method |
| 406 | # being currently used by QEMU (this is usually set by the '-clock' |
| 407 | # command-line option). |
| 408 | # |
| 409 | # Since: 1.0 |
| 410 | ## |
| 411 | { 'command': 'query-alarm-clock', 'returns': 'QemuAlarmClock' } |
| 412 | |
| 413 | Notice the "returns" keyword. As its name suggests, it's used to define the |
| 414 | data returned by a command. |
| 415 | |
| 416 | It's time to implement the qmp_query_alarm_clock() function, you can put it |
| 417 | in the qemu-timer.c file: |
| 418 | |
| 419 | QemuAlarmClock *qmp_query_alarm_clock(Error **errp) |
| 420 | { |
| 421 | QemuAlarmClock *clock; |
| 422 | int64_t deadline; |
| 423 | |
| 424 | clock = g_malloc0(sizeof(*clock)); |
| 425 | |
| 426 | deadline = qemu_next_alarm_deadline(); |
| 427 | if (deadline > 0) { |
| 428 | clock->has_next_deadline = true; |
| 429 | clock->next_deadline = deadline; |
| 430 | } |
| 431 | clock->clock_name = g_strdup(alarm_timer->name); |
| 432 | |
| 433 | return clock; |
| 434 | } |
| 435 | |
| 436 | There are a number of things to be noticed: |
| 437 | |
| 438 | 1. The QemuAlarmClock type is automatically generated by the QAPI framework, |
| 439 | its members correspond to the type's specification in the schema file |
| 440 | 2. As specified in the schema file, the function returns a QemuAlarmClock |
| 441 | instance and takes no arguments (besides the "errp" one, which is mandatory |
| 442 | for all QMP functions) |
| 443 | 3. The "clock" variable (which will point to our QAPI type instance) is |
| 444 | allocated by the regular g_malloc0() function. Note that we chose to |
Stefan Weil | dabdf39 | 2012-01-08 19:35:09 +0100 | [diff] [blame] | 445 | initialize the memory to zero. This is recommended for all QAPI types, as |
Luiz Capitulino | 4b389b5 | 2011-10-28 17:43:29 -0200 | [diff] [blame] | 446 | it helps avoiding bad surprises (specially with booleans) |
| 447 | 4. Remember that "next_deadline" is optional? All optional members have a |
| 448 | 'has_TYPE_NAME' member that should be properly set by the implementation, |
| 449 | as shown above |
| 450 | 5. Even static strings, such as "alarm_timer->name", should be dynamically |
| 451 | allocated by the implementation. This is so because the QAPI also generates |
| 452 | a function to free its types and it cannot distinguish between dynamically |
| 453 | or statically allocated strings |
| 454 | 6. You have to include the "qmp-commands.h" header file in qemu-timer.c, |
| 455 | otherwise qemu won't build |
| 456 | |
| 457 | The last step is to add the correspoding entry in the qmp-commands.hx file: |
| 458 | |
| 459 | { |
| 460 | .name = "query-alarm-clock", |
| 461 | .args_type = "", |
| 462 | .mhandler.cmd_new = qmp_marshal_input_query_alarm_clock, |
| 463 | }, |
| 464 | |
| 465 | Time to test the new command. Build qemu, run it as described in the "Testing" |
| 466 | section and try this: |
| 467 | |
| 468 | { "execute": "query-alarm-clock" } |
| 469 | { |
| 470 | "return": { |
| 471 | "next-deadline": 2368219, |
| 472 | "clock-name": "dynticks" |
| 473 | } |
| 474 | } |
| 475 | |
| 476 | ==== The HMP command ==== |
| 477 | |
| 478 | Here's the HMP counterpart of the query-alarm-clock command: |
| 479 | |
| 480 | void hmp_info_alarm_clock(Monitor *mon) |
| 481 | { |
| 482 | QemuAlarmClock *clock; |
| 483 | Error *errp = NULL; |
| 484 | |
| 485 | clock = qmp_query_alarm_clock(&errp); |
| 486 | if (error_is_set(&errp)) { |
| 487 | monitor_printf(mon, "Could not query alarm clock information\n"); |
| 488 | error_free(errp); |
| 489 | return; |
| 490 | } |
| 491 | |
| 492 | monitor_printf(mon, "Alarm clock method in use: '%s'\n", clock->clock_name); |
| 493 | if (clock->has_next_deadline) { |
| 494 | monitor_printf(mon, "Next alarm will fire in %" PRId64 " nanoseconds\n", |
| 495 | clock->next_deadline); |
| 496 | } |
| 497 | |
| 498 | qapi_free_QemuAlarmClock(clock); |
| 499 | } |
| 500 | |
| 501 | It's important to notice that hmp_info_alarm_clock() calls |
| 502 | qapi_free_QemuAlarmClock() to free the data returned by qmp_query_alarm_clock(). |
| 503 | For user defined types, the QAPI will generate a qapi_free_QAPI_TYPE_NAME() |
| 504 | function and that's what you have to use to free the types you define and |
| 505 | qapi_free_QAPI_TYPE_NAMEList() for list types (explained in the next section). |
| 506 | If the QMP call returns a string, then you should g_free() to free it. |
| 507 | |
| 508 | Also note that hmp_info_alarm_clock() performs error handling. That's not |
| 509 | strictly required if you're sure the QMP function doesn't return errors, but |
| 510 | it's good practice to always check for errors. |
| 511 | |
| 512 | Another important detail is that HMP's "info" commands don't go into the |
| 513 | hmp-commands.hx. Instead, they go into the info_cmds[] table, which is defined |
| 514 | in the monitor.c file. The entry for the "info alarmclock" follows: |
| 515 | |
| 516 | { |
| 517 | .name = "alarmclock", |
| 518 | .args_type = "", |
| 519 | .params = "", |
| 520 | .help = "show information about the alarm clock", |
| 521 | .mhandler.info = hmp_info_alarm_clock, |
| 522 | }, |
| 523 | |
| 524 | To test this, run qemu and type "info alarmclock" in the user monitor. |
| 525 | |
| 526 | === Returning Lists === |
| 527 | |
| 528 | For this example, we're going to return all available methods for the timer |
| 529 | alarm, which is pretty much what the command-line option "-clock ?" does, |
| 530 | except that we're also going to inform which method is in use. |
| 531 | |
| 532 | This first step is to define a new type: |
| 533 | |
| 534 | ## |
| 535 | # @TimerAlarmMethod |
| 536 | # |
| 537 | # Timer alarm method information. |
| 538 | # |
| 539 | # @method-name: The method's name. |
| 540 | # |
| 541 | # @current: true if this alarm method is currently in use, false otherwise |
| 542 | # |
| 543 | # Since: 1.0 |
| 544 | ## |
| 545 | { 'type': 'TimerAlarmMethod', |
| 546 | 'data': { 'method-name': 'str', 'current': 'bool' } } |
| 547 | |
| 548 | The command will be called "query-alarm-methods", here is its schema |
| 549 | specification: |
| 550 | |
| 551 | ## |
| 552 | # @query-alarm-methods |
| 553 | # |
| 554 | # Returns information about available alarm methods. |
| 555 | # |
| 556 | # Returns: a list of @TimerAlarmMethod for each method |
| 557 | # |
| 558 | # Since: 1.0 |
| 559 | ## |
| 560 | { 'command': 'query-alarm-methods', 'returns': ['TimerAlarmMethod'] } |
| 561 | |
| 562 | Notice the syntax for returning lists "'returns': ['TimerAlarmMethod']", this |
| 563 | should be read as "returns a list of TimerAlarmMethod instances". |
| 564 | |
| 565 | The C implementation follows: |
| 566 | |
| 567 | TimerAlarmMethodList *qmp_query_alarm_methods(Error **errp) |
| 568 | { |
| 569 | TimerAlarmMethodList *method_list = NULL; |
| 570 | const struct qemu_alarm_timer *p; |
| 571 | bool current = true; |
| 572 | |
| 573 | for (p = alarm_timers; p->name; p++) { |
| 574 | TimerAlarmMethodList *info = g_malloc0(sizeof(*info)); |
| 575 | info->value = g_malloc0(sizeof(*info->value)); |
| 576 | info->value->method_name = g_strdup(p->name); |
| 577 | info->value->current = current; |
| 578 | |
| 579 | current = false; |
| 580 | |
| 581 | info->next = method_list; |
| 582 | method_list = info; |
| 583 | } |
| 584 | |
| 585 | return method_list; |
| 586 | } |
| 587 | |
| 588 | The most important difference from the previous examples is the |
| 589 | TimerAlarmMethodList type, which is automatically generated by the QAPI from |
| 590 | the TimerAlarmMethod type. |
| 591 | |
| 592 | Each list node is represented by a TimerAlarmMethodList instance. We have to |
| 593 | allocate it, and that's done inside the for loop: the "info" pointer points to |
| 594 | an allocated node. We also have to allocate the node's contents, which is |
| 595 | stored in its "value" member. In our example, the "value" member is a pointer |
| 596 | to an TimerAlarmMethod instance. |
| 597 | |
| 598 | Notice that the "current" variable is used as "true" only in the first |
| 599 | interation of the loop. That's because the alarm timer method in use is the |
| 600 | first element of the alarm_timers array. Also notice that QAPI lists are handled |
| 601 | by hand and we return the head of the list. |
| 602 | |
| 603 | To test this you have to add the corresponding qmp-commands.hx entry: |
| 604 | |
| 605 | { |
| 606 | .name = "query-alarm-methods", |
| 607 | .args_type = "", |
| 608 | .mhandler.cmd_new = qmp_marshal_input_query_alarm_methods, |
| 609 | }, |
| 610 | |
| 611 | Now Build qemu, run it as explained in the "Testing" section and try our new |
| 612 | command: |
| 613 | |
| 614 | { "execute": "query-alarm-methods" } |
| 615 | { |
| 616 | "return": [ |
| 617 | { |
| 618 | "current": false, |
| 619 | "method-name": "unix" |
| 620 | }, |
| 621 | { |
| 622 | "current": true, |
| 623 | "method-name": "dynticks" |
| 624 | } |
| 625 | ] |
| 626 | } |
| 627 | |
| 628 | The HMP counterpart is a bit more complex than previous examples because it |
| 629 | has to traverse the list, it's shown below for reference: |
| 630 | |
| 631 | void hmp_info_alarm_methods(Monitor *mon) |
| 632 | { |
| 633 | TimerAlarmMethodList *method_list, *method; |
| 634 | Error *errp = NULL; |
| 635 | |
| 636 | method_list = qmp_query_alarm_methods(&errp); |
| 637 | if (error_is_set(&errp)) { |
| 638 | monitor_printf(mon, "Could not query alarm methods\n"); |
| 639 | error_free(errp); |
| 640 | return; |
| 641 | } |
| 642 | |
| 643 | for (method = method_list; method; method = method->next) { |
| 644 | monitor_printf(mon, "%c %s\n", method->value->current ? '*' : ' ', |
| 645 | method->value->method_name); |
| 646 | } |
| 647 | |
| 648 | qapi_free_TimerAlarmMethodList(method_list); |
| 649 | } |