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