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