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