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
27namespace 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 */
75class QemuQuery {
76public:
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
166public:
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
186protected:
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 */
198class QemuClient {
199public:
200    /* Constructs QemuClient instance. */
201    QemuClient();
202
203    /* Destructs QemuClient instance. */
204    virtual ~QemuClient();
205
206    /****************************************************************************
207     * Qemu client API
208     ***************************************************************************/
209
210public:
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
286protected:
287    /* Qemu pipe handle. */
288    int     mPipeFD;
289
290private:
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. */
300class FactoryQemuClient : public QemuClient {
301public:
302    /* Constructs FactoryQemuClient instance. */
303    FactoryQemuClient();
304
305    /* Destructs FactoryQemuClient instance. */
306    ~FactoryQemuClient();
307
308    /****************************************************************************
309     * Public API
310     ***************************************************************************/
311
312public:
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
344private:
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 */
355class CameraQemuClient : public QemuClient {
356public:
357    /* Constructs CameraQemuClient instance. */
358    CameraQemuClient();
359
360    /* Destructs CameraQemuClient instance. */
361    ~CameraQemuClient();
362
363    /****************************************************************************
364     * Public API
365     ***************************************************************************/
366
367public:
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
422private:
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