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      */
isQuerySucceeded()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      */
getCompletionStatus()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