blob: 16443211fef076c55aac56f4f29c968dff36f84d
1 | /* |
2 | * Copyright (C) 2011 The Android Open Source Project |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #ifndef HW_EMULATOR_CAMERA_QEMU_CLIENT_H |
18 | #define HW_EMULATOR_CAMERA_QEMU_CLIENT_H |
19 | |
20 | /* |
21 | * Contains declaration of classes that encapsulate connection to camera services |
22 | * in the emulator via qemu pipe. |
23 | */ |
24 | |
25 | #include <hardware/qemud.h> |
26 | |
27 | namespace android { |
28 | |
29 | /**************************************************************************** |
30 | * Qemu query |
31 | ***************************************************************************/ |
32 | |
33 | /* Encapsulates a query to the emulator. |
34 | * Guest exchanges data with the emulator via queries sent over the qemu pipe. |
35 | * The queries as well as replies to the queries are all strings (except for the |
36 | * 'frame' query where reply is a framebuffer). |
37 | * Each query is formatted as such: |
38 | * |
39 | * "<query name>[ <parameters>]", |
40 | * |
41 | * where <query name> is a string representing query name, and <parameters> are |
42 | * optional parameters for the query. If parameters are present, they must be |
43 | * separated from the query name with a single space, and they must be formatted |
44 | * as such: |
45 | * |
46 | * "<name1>=<value1> <name2>=<value2> ... <nameN>=<valueN>" |
47 | * |
48 | * I.e.: |
49 | * - Every parameter must have a name, and a value. |
50 | * - Name and value must be separated with '='. |
51 | * - No spaces are allowed around '=' separating name and value. |
52 | * - Parameters must be separated with a single space character. |
53 | * - No '=' character is allowed in name and in value. |
54 | * |
55 | * There are certain restrictions on strings used in the query: |
56 | * - Spaces are allowed only as separators. |
57 | * - '=' are allowed only to divide parameter names from parameter values. |
58 | * |
59 | * Emulator replies to each query in two chunks: |
60 | * - 8 bytes encoding the payload size as a string containing hexadecimal |
61 | * representation of the payload size value. This is done in order to simplify |
62 | * dealing with different endianness on the host, and on the guest. |
63 | * - Payload, whose size is defined by the first chunk. |
64 | * |
65 | * Every payload always begins with two characters, encoding the result of the |
66 | * query: |
67 | * - 'ok' Encoding the success |
68 | * - 'ko' Encoding a failure. |
69 | * After that payload may have optional data. If payload has more data following |
70 | * the query result, there is a ':' character separating them. If payload carries |
71 | * only the result, it always ends with a zero-terminator. So, payload 'ok'/'ko' |
72 | * prefix is always 3 bytes long: it either includes a zero-terminator, if there |
73 | * is no data, or a ':' separator. |
74 | */ |
75 | class QemuQuery { |
76 | public: |
77 | /* Constructs an uninitialized QemuQuery instance. */ |
78 | QemuQuery(); |
79 | |
80 | /* Constructs and initializes QemuQuery instance for a query. |
81 | * Param: |
82 | * query_string - Query string. This constructor can also be used to |
83 | * construct a query that doesn't have parameters. In this case query |
84 | * name can be passed as a parameter here. |
85 | */ |
86 | explicit QemuQuery(const char* query_string); |
87 | |
88 | /* Constructs and initializes QemuQuery instance for a query with parameters. |
89 | * Param: |
90 | * query_name - Query name. |
91 | * query_param - Query parameters. Can be NULL. |
92 | */ |
93 | QemuQuery(const char* query_name, const char* query_param); |
94 | |
95 | /* Destructs QemuQuery instance. */ |
96 | ~QemuQuery(); |
97 | |
98 | /**************************************************************************** |
99 | * Public API |
100 | ***************************************************************************/ |
101 | |
102 | /* Creates new query. |
103 | * Note: this method will reset this instance prior to creating a new query |
104 | * in order to discard possible "leftovers" from the previous query. |
105 | * Param: |
106 | * query_name - Query name. |
107 | * query_param - Query parameters. Can be NULL. |
108 | * Return: |
109 | * NO_ERROR on success, or an appropriate error status. |
110 | */ |
111 | status_t createQuery(const char* name, const char* param); |
112 | |
113 | /* Completes the query after a reply from the emulator. |
114 | * This method will parse the reply buffer, and calculate the final query |
115 | * status, which depends not only on the transport success / failure, but |
116 | * also on 'ok' / 'ko' in the reply buffer. |
117 | * Param: |
118 | * status - Query delivery status. This status doesn't necessarily reflects |
119 | * the final query status (which is defined by 'ok'/'ko' prefix in the |
120 | * reply buffer). This status simply states whether or not the query has |
121 | * been sent, and a reply has been received successfuly. However, if |
122 | * this status indicates a failure, it means that the entire query has |
123 | * failed. |
124 | * Return: |
125 | * NO_ERROR on success, or an appropriate error status on failure. Note that |
126 | * status returned here just signals whether or not the method has succeeded. |
127 | * Use isQuerySucceeded() / getCompletionStatus() methods of this class to |
128 | * check the final query status. |
129 | */ |
130 | status_t completeQuery(status_t status); |
131 | |
132 | /* Resets the query from a previous use. */ |
133 | void resetQuery(); |
134 | |
135 | /* Checks if query has succeeded. |
136 | * Note that this method must be called after completeQuery() method of this |
137 | * class has been executed. |
138 | */ |
139 | inline bool isQuerySucceeded() const { |
140 | return mQueryDeliveryStatus == NO_ERROR && mReplyStatus != 0; |
141 | } |
142 | |
143 | /* Gets final completion status of the query. |
144 | * Note that this method must be called after completeQuery() method of this |
145 | * class has been executed. |
146 | * Return: |
147 | * NO_ERROR if query has succeeded, or an appropriate error status on query |
148 | * failure. |
149 | */ |
150 | inline status_t getCompletionStatus() const { |
151 | if (mQueryDeliveryStatus == NO_ERROR) { |
152 | if (mReplyStatus) { |
153 | return NO_ERROR; |
154 | } else { |
155 | return EINVAL; |
156 | } |
157 | } else { |
158 | return mQueryDeliveryStatus; |
159 | } |
160 | } |
161 | |
162 | /**************************************************************************** |
163 | * Public data memebers |
164 | ***************************************************************************/ |
165 | |
166 | public: |
167 | /* Query string. */ |
168 | char* mQuery; |
169 | /* Query delivery status. */ |
170 | status_t mQueryDeliveryStatus; |
171 | /* Reply buffer */ |
172 | char* mReplyBuffer; |
173 | /* Reply data (past 'ok'/'ko'). If NULL, there were no data in reply. */ |
174 | char* mReplyData; |
175 | /* Reply buffer size. */ |
176 | size_t mReplySize; |
177 | /* Reply data size. */ |
178 | size_t mReplyDataSize; |
179 | /* Reply status: 1 - ok, 0 - ko. */ |
180 | int mReplyStatus; |
181 | |
182 | /**************************************************************************** |
183 | * Private data memebers |
184 | ***************************************************************************/ |
185 | |
186 | protected: |
187 | /* Preallocated buffer for small queries. */ |
188 | char mQueryPrealloc[256]; |
189 | }; |
190 | |
191 | /**************************************************************************** |
192 | * Qemu client base |
193 | ***************************************************************************/ |
194 | |
195 | /* Encapsulates a connection to the 'camera' service in the emulator via qemu |
196 | * pipe. |
197 | */ |
198 | class QemuClient { |
199 | public: |
200 | /* Constructs QemuClient instance. */ |
201 | QemuClient(); |
202 | |
203 | /* Destructs QemuClient instance. */ |
204 | virtual ~QemuClient(); |
205 | |
206 | /**************************************************************************** |
207 | * Qemu client API |
208 | ***************************************************************************/ |
209 | |
210 | public: |
211 | /* Connects to the 'camera' service in the emulator via qemu pipe. |
212 | * Param: |
213 | * param - Parameters to pass to the camera service. There are two types of |
214 | * camera services implemented by the emulator. The first one is a |
215 | * 'camera factory' type of service that provides list of cameras |
216 | * connected to the host. Another one is an 'emulated camera' type of |
217 | * service that provides interface to a camera connected to the host. At |
218 | * the connection time emulator makes distinction between the two by |
219 | * looking at connection parameters: no parameters means connection to |
220 | * the 'factory' service, while connection with parameters means |
221 | * connection to an 'emulated camera' service, where camera is identified |
222 | * by one of the connection parameters. So, passing NULL, or an empty |
223 | * string to this method will establish a connection with the 'factory' |
224 | * service, while not empty string passed here will establish connection |
225 | * with an 'emulated camera' service. Parameters defining the emulated |
226 | * camera must be formatted as such: |
227 | * |
228 | * "name=<device name> [inp_channel=<input channel #>]", |
229 | * |
230 | * where 'device name' is a required parameter defining name of the |
231 | * camera device, and 'input channel' is an optional parameter (positive |
232 | * integer), defining the input channel to use on the camera device. |
233 | * Note that device name passed here must have been previously obtained |
234 | * from the factory service using 'list' query. |
235 | * Return: |
236 | * NO_ERROR on success, or an appropriate error status. |
237 | */ |
238 | virtual status_t connectClient(const char* param); |
239 | |
240 | /* Disconnects from the service. */ |
241 | virtual void disconnectClient(); |
242 | |
243 | /* Sends data to the service. |
244 | * Param: |
245 | * data, data_size - Data to send. |
246 | * Return: |
247 | * NO_ERROR on success, or an appropriate error status on failure. |
248 | */ |
249 | virtual status_t sendMessage(const void* data, size_t data_size); |
250 | |
251 | /* Receives data from the service. |
252 | * This method assumes that data to receive will come in two chunks: 8 |
253 | * characters encoding the payload size in hexadecimal string, followed by |
254 | * the paylod (if any). |
255 | * This method will allocate data buffer where to receive the response. |
256 | * Param: |
257 | * data - Upon success contains address of the allocated data buffer with |
258 | * the data received from the service. The caller is responsible for |
259 | * freeing allocated data buffer. |
260 | * data_size - Upon success contains size of the data received from the |
261 | * service. |
262 | * Return: |
263 | * NO_ERROR on success, or an appropriate error status on failure. |
264 | */ |
265 | virtual status_t receiveMessage(void** data, size_t* data_size); |
266 | |
267 | /* Sends a query, and receives a response from the service. |
268 | * Param: |
269 | * query - Query to send to the service. When this method returns, the query |
270 | * is completed, and all its relevant data members are properly initialized. |
271 | * Return: |
272 | * NO_ERROR on success, or an appropriate error status on failure. Note that |
273 | * status returned here is not the final query status. Use isQuerySucceeded(), |
274 | * or getCompletionStatus() method on the query object to see if it has |
275 | * succeeded. However, if this method returns a failure, it means that the |
276 | * query has failed, and there is no guarantee that its data members are |
277 | * properly initialized (except for the 'mQueryDeliveryStatus', which is |
278 | * always in the proper state). |
279 | */ |
280 | virtual status_t doQuery(QemuQuery* query); |
281 | |
282 | /**************************************************************************** |
283 | * Data members |
284 | ***************************************************************************/ |
285 | |
286 | protected: |
287 | /* Qemu pipe handle. */ |
288 | int mPipeFD; |
289 | |
290 | private: |
291 | /* Camera service name. */ |
292 | static const char mCameraServiceName[]; |
293 | }; |
294 | |
295 | /**************************************************************************** |
296 | * Qemu client for the 'factory' service. |
297 | ***************************************************************************/ |
298 | |
299 | /* Encapsulates QemuClient for the 'factory' service. */ |
300 | class FactoryQemuClient : public QemuClient { |
301 | public: |
302 | /* Constructs FactoryQemuClient instance. */ |
303 | FactoryQemuClient(); |
304 | |
305 | /* Destructs FactoryQemuClient instance. */ |
306 | ~FactoryQemuClient(); |
307 | |
308 | /**************************************************************************** |
309 | * Public API |
310 | ***************************************************************************/ |
311 | |
312 | public: |
313 | /* Lists camera devices connected to the host. |
314 | * Param: |
315 | * list - Upon success contains a list of cameras connected to the host. The |
316 | * list returned here is represented as a string, containing multiple |
317 | * lines separated with '\n', where each line represents a camera. Each |
318 | * camera line is formatted as such: |
319 | * |
320 | * "name=<device name> channel=<num> pix=<num> framedims=<dimensions>\n" |
321 | * |
322 | * Where: |
323 | * - 'name' is the name of the camera device attached to the host. This |
324 | * name must be used for subsequent connection to the 'emulated camera' |
325 | * service for that camera. |
326 | * - 'channel' - input channel number (positive int) to use to communicate |
327 | * with the camera. |
328 | * - 'pix' - pixel format (a "fourcc" uint), chosen for the video frames |
329 | * by the camera service. |
330 | * - 'framedims' contains a list of frame dimensions supported by the |
331 | * camera for the chosen pixel format. Each etry in the list is in form |
332 | * '<width>x<height>', where 'width' and 'height' are numeric values |
333 | * for width and height of a supported frame dimension. Entries in |
334 | * this list are separated with ',' with no spaces between the entries. |
335 | * Return: |
336 | * NO_ERROR on success, or an appropriate error status on failure. |
337 | */ |
338 | status_t listCameras(char** list); |
339 | |
340 | /**************************************************************************** |
341 | * Names of the queries available for the emulated camera factory. |
342 | ***************************************************************************/ |
343 | |
344 | private: |
345 | /* List cameras connected to the host. */ |
346 | static const char mQueryList[]; |
347 | }; |
348 | |
349 | /**************************************************************************** |
350 | * Qemu client for an 'emulated camera' service. |
351 | ***************************************************************************/ |
352 | |
353 | /* Encapsulates QemuClient for an 'emulated camera' service. |
354 | */ |
355 | class CameraQemuClient : public QemuClient { |
356 | public: |
357 | /* Constructs CameraQemuClient instance. */ |
358 | CameraQemuClient(); |
359 | |
360 | /* Destructs CameraQemuClient instance. */ |
361 | ~CameraQemuClient(); |
362 | |
363 | /**************************************************************************** |
364 | * Public API |
365 | ***************************************************************************/ |
366 | |
367 | public: |
368 | /* Queries camera connection. |
369 | * Return: |
370 | * NO_ERROR on success, or an appropriate error status on failure. |
371 | */ |
372 | status_t queryConnect(); |
373 | |
374 | /* Queries camera disconnection. |
375 | * Return: |
376 | * NO_ERROR on success, or an appropriate error status on failure. |
377 | */ |
378 | status_t queryDisconnect(); |
379 | |
380 | /* Queries camera to start capturing video. |
381 | * Param: |
382 | * pixel_format - Pixel format that is used by the client to push video |
383 | * frames to the camera framework. |
384 | * width, height - Frame dimensions, requested by the framework. |
385 | * Return: |
386 | * NO_ERROR on success, or an appropriate error status on failure. |
387 | */ |
388 | status_t queryStart(uint32_t pixel_format, int width, int height); |
389 | |
390 | /* Queries camera to stop capturing video. |
391 | * Return: |
392 | * NO_ERROR on success, or an appropriate error status on failure. |
393 | */ |
394 | status_t queryStop(); |
395 | |
396 | /* Queries camera for the next video frame. |
397 | * Param: |
398 | * vframe, vframe_size - Define buffer, allocated to receive a video frame. |
399 | * Any of these parameters can be 0, indicating that the caller is |
400 | * interested only in preview frame. |
401 | * pframe, pframe_size - Define buffer, allocated to receive a preview frame. |
402 | * Any of these parameters can be 0, indicating that the caller is |
403 | * interested only in video frame. |
404 | * r_scale, g_scale, b_scale - White balance scale. |
405 | * exposure_comp - Expsoure compensation. |
406 | * Return: |
407 | * NO_ERROR on success, or an appropriate error status on failure. |
408 | */ |
409 | status_t queryFrame(void* vframe, |
410 | void* pframe, |
411 | size_t vframe_size, |
412 | size_t pframe_size, |
413 | float r_scale, |
414 | float g_scale, |
415 | float b_scale, |
416 | float exposure_comp); |
417 | |
418 | /**************************************************************************** |
419 | * Names of the queries available for the emulated camera. |
420 | ***************************************************************************/ |
421 | |
422 | private: |
423 | /* Connect to the camera. */ |
424 | static const char mQueryConnect[]; |
425 | /* Disconnect from the camera. */ |
426 | static const char mQueryDisconnect[]; |
427 | /* Start video capturing. */ |
428 | static const char mQueryStart[]; |
429 | /* Stop video capturing. */ |
430 | static const char mQueryStop[]; |
431 | /* Query frame(s). */ |
432 | static const char mQueryFrame[]; |
433 | }; |
434 | |
435 | }; /* namespace android */ |
436 | |
437 | #endif /* HW_EMULATOR_CAMERA_QEMU_CLIENT_H */ |
438 |