mm_camera_channel.c revision ac60ceb3d854453ef06da396db70569c0c370d43
1/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30#include <pthread.h> 31#include <errno.h> 32#include <sys/ioctl.h> 33#include <sys/types.h> 34#include <sys/stat.h> 35#include <fcntl.h> 36#include <poll.h> 37#include <cam_semaphore.h> 38 39#include "mm_camera_dbg.h" 40#include "mm_camera_interface.h" 41#include "mm_camera.h" 42 43extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler); 44extern mm_channel_t * mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj, 45 uint32_t handler); 46 47/* internal function declare goes here */ 48int32_t mm_channel_qbuf(mm_channel_t *my_obj, 49 mm_camera_buf_def_t *buf); 50int32_t mm_channel_init(mm_channel_t *my_obj, 51 mm_camera_channel_attr_t *attr, 52 mm_camera_buf_notify_t channel_cb, 53 void *userdata); 54void mm_channel_release(mm_channel_t *my_obj); 55uint32_t mm_channel_add_stream(mm_channel_t *my_obj); 56int32_t mm_channel_del_stream(mm_channel_t *my_obj, 57 uint32_t stream_id); 58int32_t mm_channel_config_stream(mm_channel_t *my_obj, 59 uint32_t stream_id, 60 mm_camera_stream_config_t *config); 61int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj, 62 cam_bundle_config_t *bundle_info); 63int32_t mm_channel_start(mm_channel_t *my_obj); 64int32_t mm_channel_stop(mm_channel_t *my_obj); 65int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, 66 uint32_t num_buf_requested, uint32_t num_reto_buf_requested); 67int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj); 68int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, 69 uint32_t frame_idx); 70int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj, 71 mm_camera_super_buf_notify_mode_t notify_mode); 72int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj); 73int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj); 74int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj, mm_channel_queue_t * queue); 75int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj, 76 mm_evt_paylod_set_get_stream_parms_t *payload); 77int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj, 78 mm_evt_paylod_set_get_stream_parms_t *payload); 79int32_t mm_channel_do_stream_action(mm_channel_t *my_obj, 80 mm_evt_paylod_do_stream_action_t *payload); 81int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj, 82 mm_evt_paylod_map_stream_buf_t *payload); 83int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj, 84 mm_evt_paylod_unmap_stream_buf_t *payload); 85 86/* state machine function declare */ 87int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj, 88 mm_channel_evt_type_t evt, 89 void * in_val, 90 void * out_val); 91int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj, 92 mm_channel_evt_type_t evt, 93 void * in_val, 94 void * out_val); 95int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj, 96 mm_channel_evt_type_t evt, 97 void * in_val, 98 void * out_val); 99int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj, 100 mm_channel_evt_type_t evt, 101 void * in_val, 102 void * out_val); 103 104/* channel super queue functions */ 105int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue); 106int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue); 107int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj, 108 mm_channel_queue_t * queue, 109 mm_camera_buf_info_t *buf); 110mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue); 111int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t *my_obj, 112 mm_channel_queue_t *queue); 113int32_t mm_channel_superbuf_skip(mm_channel_t *my_obj, 114 mm_channel_queue_t *queue); 115 116static int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj, 117 mm_camera_generic_cmd_t *p_gen_cmd); 118int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj, 119 mm_channel_queue_t * queue); 120/*=========================================================================== 121 * FUNCTION : mm_channel_util_get_stream_by_handler 122 * 123 * DESCRIPTION: utility function to get a stream object from its handle 124 * 125 * PARAMETERS : 126 * @cam_obj: ptr to a channel object 127 * @handler: stream handle 128 * 129 * RETURN : ptr to a stream object. 130 * NULL if failed. 131 *==========================================================================*/ 132mm_stream_t * mm_channel_util_get_stream_by_handler( 133 mm_channel_t * ch_obj, 134 uint32_t handler) 135{ 136 int i; 137 mm_stream_t *s_obj = NULL; 138 for(i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 139 if ((MM_STREAM_STATE_NOTUSED != ch_obj->streams[i].state) && 140 (handler == ch_obj->streams[i].my_hdl)) { 141 s_obj = &ch_obj->streams[i]; 142 break; 143 } 144 } 145 return s_obj; 146} 147 148/*=========================================================================== 149 * FUNCTION : mm_channel_dispatch_super_buf 150 * 151 * DESCRIPTION: dispatch super buffer of bundle to registered user 152 * 153 * PARAMETERS : 154 * @cmd_cb : ptr storing matched super buf information 155 * @userdata: user data ptr 156 * 157 * RETURN : none 158 *==========================================================================*/ 159static void mm_channel_dispatch_super_buf(mm_camera_cmdcb_t *cmd_cb, 160 void* user_data) 161{ 162 mm_camera_cmd_thread_name("mm_cam_cb"); 163 mm_channel_t * my_obj = (mm_channel_t *)user_data; 164 165 if (NULL == my_obj) { 166 return; 167 } 168 169 if (MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB != cmd_cb->cmd_type) { 170 CDBG_ERROR("%s: Wrong cmd_type (%d) for super buf dataCB", 171 __func__, cmd_cb->cmd_type); 172 return; 173 } 174 175 if (my_obj->bundle.super_buf_notify_cb) { 176 my_obj->bundle.super_buf_notify_cb(&cmd_cb->u.superbuf, my_obj->bundle.user_data); 177 } 178} 179 180/*=========================================================================== 181 * FUNCTION : mm_channel_process_stream_buf 182 * 183 * DESCRIPTION: handle incoming buffer from stream in a bundle. In this function, 184 * matching logic will be performed on incoming stream frames. 185 * Will depends on the bundle attribute, either storing matched frames 186 * in the superbuf queue, or sending matched superbuf frames to upper 187 * layer through registered callback. 188 * 189 * PARAMETERS : 190 * @cmd_cb : ptr storing matched super buf information 191 * @userdata: user data ptr 192 * 193 * RETURN : none 194 *==========================================================================*/ 195static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb, 196 void *user_data) 197{ 198 mm_camera_cmd_thread_name("mm_cam_cmd"); 199 mm_camera_super_buf_notify_mode_t notify_mode; 200 mm_channel_queue_node_t *node = NULL; 201 mm_channel_t *ch_obj = (mm_channel_t *)user_data; 202 if (NULL == ch_obj) { 203 return; 204 } 205 if (MM_CAMERA_CMD_TYPE_DATA_CB == cmd_cb->cmd_type) { 206 /* comp_and_enqueue */ 207 mm_channel_superbuf_comp_and_enqueue( 208 ch_obj, 209 &ch_obj->bundle.superbuf_queue, 210 &cmd_cb->u.buf); 211 } else if (MM_CAMERA_CMD_TYPE_REQ_DATA_CB == cmd_cb->cmd_type) { 212 /* skip frames if needed */ 213 ch_obj->pending_cnt = cmd_cb->u.req_buf.num_buf_requested; 214 ch_obj->pending_retro_cnt = cmd_cb->u.req_buf.num_retro_buf_requested; 215 ch_obj->bWaitForPrepSnapshotDone = 0; 216 217 ALOGV("%s:[ZSL Retro] pending cnt (%d), retro count (%d)", 218 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt); 219 if (!ch_obj->pending_cnt || (ch_obj->pending_retro_cnt > ch_obj->pending_cnt)) { 220 ch_obj->pending_retro_cnt = ch_obj->pending_cnt; 221 } 222 if (ch_obj->pending_retro_cnt > 0) { 223 ALOGV("%s: [ZSL Retro] Resetting need Led Flash!!!", 224 __func__); 225 ch_obj->needLEDFlash = 0; 226 } 227 ch_obj->stopZslSnapshot = 0; 228 ch_obj->unLockAEC = 0; 229 230 mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue); 231 232 } else if (MM_CAMERA_CMD_TYPE_START_ZSL == cmd_cb->cmd_type) { 233 ch_obj->manualZSLSnapshot = TRUE; 234 mm_camera_start_zsl_snapshot(ch_obj->cam_obj); 235 } else if (MM_CAMERA_CMD_TYPE_STOP_ZSL == cmd_cb->cmd_type) { 236 ch_obj->manualZSLSnapshot = FALSE; 237 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj); 238 } else if (MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY == cmd_cb->cmd_type) { 239 ch_obj->bundle.superbuf_queue.attr.notify_mode = cmd_cb->u.notify_mode; 240 } else if (MM_CAMERA_CMD_TYPE_FLUSH_QUEUE == cmd_cb->cmd_type) { 241 ch_obj->bundle.superbuf_queue.expected_frame_id = cmd_cb->u.frame_idx; 242 mm_channel_superbuf_flush(ch_obj, &ch_obj->bundle.superbuf_queue); 243 return; 244 } else if (MM_CAMERA_CMD_TYPE_GENERAL == cmd_cb->cmd_type) { 245 CDBG_HIGH("%s:%d] MM_CAMERA_CMD_TYPE_GENERAL", __func__, __LINE__); 246 switch (cmd_cb->u.gen_cmd.type) { 247 case MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING: 248 case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING: { 249 int8_t start = cmd_cb->u.gen_cmd.payload[0]; 250 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_AF_BRACKETING %d", 251 __func__, __LINE__, start); 252 mm_channel_superbuf_flush(ch_obj, 253 &ch_obj->bundle.superbuf_queue); 254 255 if (start) { 256 CDBG_HIGH("%s:%d] need AE bracketing, start zsl snapshot", 257 __func__, __LINE__); 258 ch_obj->need3ABracketing = TRUE; 259 } else { 260 ch_obj->need3ABracketing = FALSE; 261 } 262 } 263 break; 264 case MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING: { 265 int8_t start = cmd_cb->u.gen_cmd.payload[0]; 266 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_FLASH_BRACKETING %d", 267 __func__, __LINE__, start); 268 if (start) { 269 CDBG_HIGH("%s:%d] need flash bracketing", 270 __func__, __LINE__); 271 ch_obj->isFlashBracketingEnabled = TRUE; 272 } else { 273 ch_obj->isFlashBracketingEnabled = FALSE; 274 } 275 } 276 break; 277 case MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X: { 278 int8_t start = cmd_cb->u.gen_cmd.payload[0]; 279 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X %d", 280 __func__, __LINE__, start); 281 if (start) { 282 CDBG_HIGH("%s:%d] need zoom 1x frame", 283 __func__, __LINE__); 284 ch_obj->isZoom1xFrameRequested = TRUE; 285 } else { 286 ch_obj->isZoom1xFrameRequested = FALSE; 287 } 288 } 289 break; 290 default: 291 CDBG_ERROR("%s:%d] Error: Invalid command", __func__, __LINE__); 292 break; 293 } 294 } 295 notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode; 296 297 if ((ch_obj->pending_cnt > 0) 298 && (ch_obj->needLEDFlash == TRUE || ch_obj->need3ABracketing == TRUE) 299 && (ch_obj->manualZSLSnapshot == FALSE) 300 && ch_obj->startZSlSnapshotCalled == FALSE) { 301 302 CDBG_HIGH("%s: need flash, start zsl snapshot", __func__); 303 mm_camera_start_zsl_snapshot(ch_obj->cam_obj); 304 ch_obj->startZSlSnapshotCalled = TRUE; 305 ch_obj->burstSnapNum = ch_obj->pending_cnt; 306 ch_obj->bWaitForPrepSnapshotDone = 0; 307 ch_obj->needLEDFlash = FALSE; 308 } else if (((ch_obj->pending_cnt == 0) || (ch_obj->stopZslSnapshot == 1)) 309 && (ch_obj->manualZSLSnapshot == FALSE) 310 && (ch_obj->startZSlSnapshotCalled == TRUE)) { 311 CDBG_HIGH("%s: Got picture cancelled, stop zsl snapshot", __func__); 312 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj); 313 // Unlock AEC 314 ch_obj->startZSlSnapshotCalled = FALSE; 315 ch_obj->needLEDFlash = FALSE; 316 ch_obj->burstSnapNum = 0; 317 ch_obj->stopZslSnapshot = 0; 318 ch_obj->bWaitForPrepSnapshotDone = 0; 319 ch_obj->unLockAEC = 1; 320 ch_obj->need3ABracketing = FALSE; 321 } 322 /* bufdone for overflowed bufs */ 323 mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue); 324 325 CDBG("%s: Super Buffer received, pending_cnt=%d", 326 __func__, ch_obj->pending_cnt); 327 /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */ 328 329 CDBG("%s: [ZSL Retro] Out loop pending cnt (%d), retro count (%d)", 330 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt); 331 while (((ch_obj->pending_cnt > 0) || 332 (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode)) && 333 (!ch_obj->bWaitForPrepSnapshotDone)) { 334 335 CDBG("%s: [ZSL Retro] In loop pending cnt (%d), retro count (%d)", 336 __func__, ch_obj->pending_cnt, ch_obj->pending_retro_cnt); 337 /* dequeue */ 338 node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue); 339 if (NULL != node) { 340 uint32_t bReady = 0; 341 /* decrease pending_cnt */ 342 if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) { 343 ch_obj->pending_cnt--; 344 if (ch_obj->pending_retro_cnt > 0) { 345 if (ch_obj->pending_retro_cnt == 1) { 346 ch_obj->bWaitForPrepSnapshotDone = 1; 347 // Retro Snaps are done.. 348 bReady = 1; 349 } 350 ch_obj->pending_retro_cnt--; 351 } 352 CDBG("%s: [ZSL Retro] Super Buffer received, Call client callback," 353 "pending_cnt=%d", __func__, ch_obj->pending_cnt); 354 355 if (((ch_obj->pending_cnt == 0) || 356 (ch_obj->stopZslSnapshot == 1)) && 357 (ch_obj->manualZSLSnapshot == FALSE) && 358 ch_obj->startZSlSnapshotCalled == TRUE) { 359 CDBG("%s: [ZSL Retro] Received all frames requested, stop zsl snapshot", __func__); 360 mm_camera_stop_zsl_snapshot(ch_obj->cam_obj); 361 ch_obj->startZSlSnapshotCalled = FALSE; 362 ch_obj->burstSnapNum = 0; 363 ch_obj->stopZslSnapshot = 0; 364 ch_obj->unLockAEC = 1; 365 366 } 367 } 368 /* dispatch superbuf */ 369 if (NULL != ch_obj->bundle.super_buf_notify_cb) { 370 uint8_t i; 371 mm_camera_cmdcb_t* cb_node = NULL; 372 373 CDBG("%s: Send superbuf to HAL, pending_cnt=%d", 374 __func__, ch_obj->pending_cnt); 375 376 /* send cam_sem_post to wake up cb thread to dispatch super buffer */ 377 cb_node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 378 if (NULL != cb_node) { 379 memset(cb_node, 0, sizeof(mm_camera_cmdcb_t)); 380 cb_node->cmd_type = MM_CAMERA_CMD_TYPE_SUPER_BUF_DATA_CB; 381 cb_node->u.superbuf.num_bufs = node->num_of_bufs; 382 for (i=0; i<node->num_of_bufs; i++) { 383 cb_node->u.superbuf.bufs[i] = node->super_buf[i].buf; 384 } 385 cb_node->u.superbuf.camera_handle = ch_obj->cam_obj->my_hdl; 386 cb_node->u.superbuf.ch_id = ch_obj->my_hdl; 387 cb_node->u.superbuf.bReadyForPrepareSnapshot = bReady; 388 if (ch_obj->unLockAEC == 1) { 389 cb_node->u.superbuf.bUnlockAEC = 1; 390 ALOGE("%s:[ZSL Retro] Unlocking AEC", __func__); 391 ch_obj->unLockAEC = 0; 392 } 393 394 /* enqueue to cb thread */ 395 cam_queue_enq(&(ch_obj->cb_thread.cmd_queue), cb_node); 396 /* wake up cb thread */ 397 cam_sem_post(&(ch_obj->cb_thread.cmd_sem)); 398 } else { 399 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 400 /* buf done with the nonuse super buf */ 401 for (i=0; i<node->num_of_bufs; i++) { 402 mm_channel_qbuf(ch_obj, node->super_buf[i].buf); 403 } 404 } 405 } else { 406 /* buf done with the nonuse super buf */ 407 uint8_t i; 408 for (i=0; i<node->num_of_bufs; i++) { 409 mm_channel_qbuf(ch_obj, node->super_buf[i].buf); 410 } 411 } 412 free(node); 413 } else { 414 /* no superbuf avail, break the loop */ 415 break; 416 } 417 } 418} 419 420/*=========================================================================== 421 * FUNCTION : mm_channel_fsm_fn 422 * 423 * DESCRIPTION: channel finite state machine entry function. Depends on channel 424 * state, incoming event will be handled differently. 425 * 426 * PARAMETERS : 427 * @my_obj : ptr to a channel object 428 * @evt : channel event to be processed 429 * @in_val : input event payload. Can be NULL if not needed. 430 * @out_val : output payload, Can be NULL if not needed. 431 * 432 * RETURN : int32_t type of status 433 * 0 -- success 434 * -1 -- failure 435 *==========================================================================*/ 436int32_t mm_channel_fsm_fn(mm_channel_t *my_obj, 437 mm_channel_evt_type_t evt, 438 void * in_val, 439 void * out_val) 440{ 441 int32_t rc = -1; 442 443 CDBG("%s : E state = %d", __func__, my_obj->state); 444 switch (my_obj->state) { 445 case MM_CHANNEL_STATE_NOTUSED: 446 rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val); 447 break; 448 case MM_CHANNEL_STATE_STOPPED: 449 rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val); 450 break; 451 case MM_CHANNEL_STATE_ACTIVE: 452 rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val); 453 break; 454 case MM_CHANNEL_STATE_PAUSED: 455 rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val); 456 break; 457 default: 458 CDBG("%s: Not a valid state (%d)", __func__, my_obj->state); 459 break; 460 } 461 462 /* unlock ch_lock */ 463 pthread_mutex_unlock(&my_obj->ch_lock); 464 CDBG("%s : X rc = %d", __func__, rc); 465 return rc; 466} 467 468/*=========================================================================== 469 * FUNCTION : mm_channel_fsm_fn_notused 470 * 471 * DESCRIPTION: channel finite state machine function to handle event 472 * in NOT_USED state. 473 * 474 * PARAMETERS : 475 * @my_obj : ptr to a channel object 476 * @evt : channel event to be processed 477 * @in_val : input event payload. Can be NULL if not needed. 478 * @out_val : output payload, Can be NULL if not needed. 479 * 480 * RETURN : int32_t type of status 481 * 0 -- success 482 * -1 -- failure 483 *==========================================================================*/ 484int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj, 485 mm_channel_evt_type_t evt, 486 void * in_val, 487 void * out_val) 488{ 489 int32_t rc = -1; 490 491 switch (evt) { 492 default: 493 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 494 __func__, my_obj->state, evt, in_val, out_val); 495 break; 496 } 497 498 return rc; 499} 500 501/*=========================================================================== 502 * FUNCTION : mm_channel_fsm_fn_stopped 503 * 504 * DESCRIPTION: channel finite state machine function to handle event 505 * in STOPPED state. 506 * 507 * PARAMETERS : 508 * @my_obj : ptr to a channel object 509 * @evt : channel event to be processed 510 * @in_val : input event payload. Can be NULL if not needed. 511 * @out_val : output payload, Can be NULL if not needed. 512 * 513 * RETURN : int32_t type of status 514 * 0 -- success 515 * -1 -- failure 516 *==========================================================================*/ 517int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj, 518 mm_channel_evt_type_t evt, 519 void * in_val, 520 void * out_val) 521{ 522 int32_t rc = 0; 523 CDBG("%s : E evt = %d", __func__, evt); 524 switch (evt) { 525 case MM_CHANNEL_EVT_ADD_STREAM: 526 { 527 uint32_t s_hdl = 0; 528 s_hdl = mm_channel_add_stream(my_obj); 529 *((uint32_t*)out_val) = s_hdl; 530 rc = 0; 531 } 532 break; 533 case MM_CHANNEL_EVT_DEL_STREAM: 534 { 535 uint32_t s_id = (uint32_t)in_val; 536 rc = mm_channel_del_stream(my_obj, s_id); 537 } 538 break; 539 case MM_CHANNEL_EVT_START: 540 { 541 rc = mm_channel_start(my_obj); 542 /* first stream started in stopped state 543 * move to active state */ 544 if (0 == rc) { 545 my_obj->state = MM_CHANNEL_STATE_ACTIVE; 546 } 547 } 548 break; 549 case MM_CHANNEL_EVT_CONFIG_STREAM: 550 { 551 mm_evt_paylod_config_stream_t *payload = 552 (mm_evt_paylod_config_stream_t *)in_val; 553 rc = mm_channel_config_stream(my_obj, 554 payload->stream_id, 555 payload->config); 556 } 557 break; 558 case MM_CHANNEL_EVT_GET_BUNDLE_INFO: 559 { 560 cam_bundle_config_t *payload = 561 (cam_bundle_config_t *)in_val; 562 rc = mm_channel_get_bundle_info(my_obj, payload); 563 } 564 break; 565 case MM_CHANNEL_EVT_DELETE: 566 { 567 mm_channel_release(my_obj); 568 rc = 0; 569 } 570 break; 571 case MM_CHANNEL_EVT_SET_STREAM_PARM: 572 { 573 mm_evt_paylod_set_get_stream_parms_t *payload = 574 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 575 rc = mm_channel_set_stream_parm(my_obj, payload); 576 } 577 break; 578 case MM_CHANNEL_EVT_GET_STREAM_PARM: 579 { 580 mm_evt_paylod_set_get_stream_parms_t *payload = 581 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 582 rc = mm_channel_get_stream_parm(my_obj, payload); 583 } 584 break; 585 case MM_CHANNEL_EVT_DO_STREAM_ACTION: 586 { 587 mm_evt_paylod_do_stream_action_t *payload = 588 (mm_evt_paylod_do_stream_action_t *)in_val; 589 rc = mm_channel_do_stream_action(my_obj, payload); 590 } 591 break; 592 case MM_CHANNEL_EVT_MAP_STREAM_BUF: 593 { 594 mm_evt_paylod_map_stream_buf_t *payload = 595 (mm_evt_paylod_map_stream_buf_t *)in_val; 596 rc = mm_channel_map_stream_buf(my_obj, payload); 597 } 598 break; 599 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF: 600 { 601 mm_evt_paylod_unmap_stream_buf_t *payload = 602 (mm_evt_paylod_unmap_stream_buf_t *)in_val; 603 rc = mm_channel_unmap_stream_buf(my_obj, payload); 604 } 605 break; 606 default: 607 CDBG_ERROR("%s: invalid state (%d) for evt (%d)", 608 __func__, my_obj->state, evt); 609 break; 610 } 611 CDBG("%s : E rc = %d", __func__, rc); 612 return rc; 613} 614 615/*=========================================================================== 616 * FUNCTION : mm_channel_fsm_fn_active 617 * 618 * DESCRIPTION: channel finite state machine function to handle event 619 * in ACTIVE state. 620 * 621 * PARAMETERS : 622 * @my_obj : ptr to a channel object 623 * @evt : channel event to be processed 624 * @in_val : input event payload. Can be NULL if not needed. 625 * @out_val : output payload, Can be NULL if not needed. 626 * 627 * RETURN : int32_t type of status 628 * 0 -- success 629 * -1 -- failure 630 *==========================================================================*/ 631int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj, 632 mm_channel_evt_type_t evt, 633 void * in_val, 634 void * out_val) 635{ 636 int32_t rc = 0; 637 638 CDBG("%s : E evt = %d", __func__, evt); 639 switch (evt) { 640 case MM_CHANNEL_EVT_STOP: 641 { 642 rc = mm_channel_stop(my_obj); 643 my_obj->state = MM_CHANNEL_STATE_STOPPED; 644 } 645 break; 646 case MM_CHANNEL_EVT_REQUEST_SUPER_BUF: 647 { 648 uint32_t num_buf_requested = (uint32_t)in_val; 649 uint32_t num_retro_buf_requested = (uint32_t)out_val; 650 rc = mm_channel_request_super_buf(my_obj, 651 num_buf_requested, num_retro_buf_requested); 652 } 653 break; 654 case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF: 655 { 656 rc = mm_channel_cancel_super_buf_request(my_obj); 657 } 658 break; 659 case MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE: 660 { 661 uint32_t frame_idx = (uint32_t)in_val; 662 rc = mm_channel_flush_super_buf_queue(my_obj, frame_idx); 663 } 664 break; 665 case MM_CHANNEL_EVT_START_ZSL_SNAPSHOT: 666 { 667 rc = mm_channel_start_zsl_snapshot(my_obj); 668 } 669 break; 670 case MM_CHANNEL_EVT_STOP_ZSL_SNAPSHOT: 671 { 672 rc = mm_channel_stop_zsl_snapshot(my_obj); 673 } 674 break; 675 case MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE: 676 { 677 mm_camera_super_buf_notify_mode_t notify_mode = ( mm_camera_super_buf_notify_mode_t ) in_val; 678 rc = mm_channel_config_notify_mode(my_obj, notify_mode); 679 } 680 break; 681 case MM_CHANNEL_EVT_SET_STREAM_PARM: 682 { 683 mm_evt_paylod_set_get_stream_parms_t *payload = 684 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 685 rc = mm_channel_set_stream_parm(my_obj, payload); 686 } 687 break; 688 case MM_CHANNEL_EVT_GET_STREAM_PARM: 689 { 690 mm_evt_paylod_set_get_stream_parms_t *payload = 691 (mm_evt_paylod_set_get_stream_parms_t *)in_val; 692 rc = mm_channel_get_stream_parm(my_obj, payload); 693 } 694 break; 695 case MM_CHANNEL_EVT_DO_STREAM_ACTION: 696 { 697 mm_evt_paylod_do_stream_action_t *payload = 698 (mm_evt_paylod_do_stream_action_t *)in_val; 699 rc = mm_channel_do_stream_action(my_obj, payload); 700 } 701 break; 702 case MM_CHANNEL_EVT_MAP_STREAM_BUF: 703 { 704 mm_evt_paylod_map_stream_buf_t *payload = 705 (mm_evt_paylod_map_stream_buf_t *)in_val; 706 if (payload != NULL) { 707 uint8_t type = payload->buf_type; 708 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) || 709 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) { 710 rc = mm_channel_map_stream_buf(my_obj, payload); 711 } 712 } else { 713 CDBG_ERROR("%s: cannot map regualr stream buf in active state", __func__); 714 } 715 } 716 break; 717 case MM_CHANNEL_EVT_UNMAP_STREAM_BUF: 718 { 719 mm_evt_paylod_unmap_stream_buf_t *payload = 720 (mm_evt_paylod_unmap_stream_buf_t *)in_val; 721 if (payload != NULL) { 722 uint8_t type = payload->buf_type; 723 if ((type == CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF) || 724 (type == CAM_MAPPING_BUF_TYPE_OFFLINE_META_BUF)) { 725 rc = mm_channel_unmap_stream_buf(my_obj, payload); 726 } 727 } else { 728 CDBG_ERROR("%s: cannot unmap regualr stream buf in active state", __func__); 729 } 730 } 731 break; 732 case MM_CHANNEL_EVT_AF_BRACKETING: 733 { 734 CDBG_HIGH("MM_CHANNEL_EVT_AF_BRACKETING"); 735 int32_t start_flag = ( int32_t ) in_val; 736 mm_camera_generic_cmd_t gen_cmd; 737 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING; 738 gen_cmd.payload[0] = start_flag; 739 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 740 } 741 break; 742 case MM_CHANNEL_EVT_AE_BRACKETING: 743 { 744 CDBG_HIGH("MM_CHANNEL_EVT_AE_BRACKETING"); 745 int32_t start_flag = ( int32_t ) in_val; 746 mm_camera_generic_cmd_t gen_cmd; 747 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING; 748 gen_cmd.payload[0] = start_flag; 749 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 750 } 751 break; 752 case MM_CHANNEL_EVT_FLASH_BRACKETING: 753 { 754 CDBG_HIGH("MM_CHANNEL_EVT_FLASH_BRACKETING"); 755 int32_t start_flag = ( int32_t ) in_val; 756 mm_camera_generic_cmd_t gen_cmd; 757 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING; 758 gen_cmd.payload[0] = start_flag; 759 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 760 } 761 break; 762 case MM_CHANNEL_EVT_ZOOM_1X: 763 { 764 CDBG_HIGH("MM_CHANNEL_EVT_ZOOM_1X"); 765 int32_t start_flag = ( int32_t ) in_val; 766 mm_camera_generic_cmd_t gen_cmd; 767 gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X; 768 gen_cmd.payload[0] = start_flag; 769 rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd); 770 } 771 break; 772 default: 773 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 774 __func__, my_obj->state, evt, in_val, out_val); 775 break; 776 } 777 CDBG("%s : X rc = %d", __func__, rc); 778 return rc; 779} 780 781/*=========================================================================== 782 * FUNCTION : mm_channel_fsm_fn_paused 783 * 784 * DESCRIPTION: channel finite state machine function to handle event 785 * in PAUSED state. 786 * 787 * PARAMETERS : 788 * @my_obj : ptr to a channel object 789 * @evt : channel event to be processed 790 * @in_val : input event payload. Can be NULL if not needed. 791 * @out_val : output payload, Can be NULL if not needed. 792 * 793 * RETURN : int32_t type of status 794 * 0 -- success 795 * -1 -- failure 796 *==========================================================================*/ 797int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj, 798 mm_channel_evt_type_t evt, 799 void * in_val, 800 void * out_val) 801{ 802 int32_t rc = 0; 803 804 /* currently we are not supporting pause/resume channel */ 805 CDBG_ERROR("%s: invalid state (%d) for evt (%d), in(%p), out(%p)", 806 __func__, my_obj->state, evt, in_val, out_val); 807 808 return rc; 809} 810 811/*=========================================================================== 812 * FUNCTION : mm_channel_init 813 * 814 * DESCRIPTION: initialize a channel 815 * 816 * PARAMETERS : 817 * @my_obj : channel object be to initialized 818 * @attr : bundle attribute of the channel if needed 819 * @channel_cb : callback function for bundle data notify 820 * @userdata : user data ptr 821 * 822 * RETURN : int32_t type of status 823 * 0 -- success 824 * -1 -- failure 825 * NOTE : if no bundle data notify is needed, meaning each stream in the 826 * channel will have its own stream data notify callback, then 827 * attr, channel_cb, and userdata can be NULL. In this case, 828 * no matching logic will be performed in channel for the bundling. 829 *==========================================================================*/ 830int32_t mm_channel_init(mm_channel_t *my_obj, 831 mm_camera_channel_attr_t *attr, 832 mm_camera_buf_notify_t channel_cb, 833 void *userdata) 834{ 835 int32_t rc = 0; 836 837 my_obj->bundle.super_buf_notify_cb = channel_cb; 838 my_obj->bundle.user_data = userdata; 839 if (NULL != attr) { 840 my_obj->bundle.superbuf_queue.attr = *attr; 841 } 842 843 CDBG("%s : Launch data poll thread in channel open", __func__); 844 mm_camera_poll_thread_launch(&my_obj->poll_thread[0], 845 MM_CAMERA_POLL_TYPE_DATA); 846 847 /* change state to stopped state */ 848 my_obj->state = MM_CHANNEL_STATE_STOPPED; 849 return rc; 850} 851 852/*=========================================================================== 853 * FUNCTION : mm_channel_release 854 * 855 * DESCRIPTION: release a channel resource. Channel state will move to UNUSED 856 * state after this call. 857 * 858 * PARAMETERS : 859 * @my_obj : channel object 860 * 861 * RETURN : none 862 *==========================================================================*/ 863void mm_channel_release(mm_channel_t *my_obj) 864{ 865 /* stop data poll thread */ 866 mm_camera_poll_thread_release(&my_obj->poll_thread[0]); 867 868 /* change state to notused state */ 869 my_obj->state = MM_CHANNEL_STATE_NOTUSED; 870} 871 872/*=========================================================================== 873 * FUNCTION : mm_channel_add_stream 874 * 875 * DESCRIPTION: add a stream into the channel 876 * 877 * PARAMETERS : 878 * @my_obj : channel object 879 * 880 * RETURN : uint32_t type of stream handle 881 * 0 -- invalid stream handle, meaning the op failed 882 * >0 -- successfully added a stream with a valid handle 883 *==========================================================================*/ 884uint32_t mm_channel_add_stream(mm_channel_t *my_obj) 885{ 886 int32_t rc = 0; 887 uint8_t idx = 0; 888 uint32_t s_hdl = 0; 889 mm_stream_t *stream_obj = NULL; 890 891 CDBG("%s : E", __func__); 892 /* check available stream */ 893 for (idx = 0; idx < MAX_STREAM_NUM_IN_BUNDLE; idx++) { 894 if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) { 895 stream_obj = &my_obj->streams[idx]; 896 break; 897 } 898 } 899 if (NULL == stream_obj) { 900 CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__); 901 return s_hdl; 902 } 903 904 /* initialize stream object */ 905 memset(stream_obj, 0, sizeof(mm_stream_t)); 906 stream_obj->my_hdl = mm_camera_util_generate_handler(idx); 907 stream_obj->ch_obj = my_obj; 908 pthread_mutex_init(&stream_obj->buf_lock, NULL); 909 pthread_mutex_init(&stream_obj->cb_lock, NULL); 910 stream_obj->state = MM_STREAM_STATE_INITED; 911 912 /* acquire stream */ 913 rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL); 914 if (0 == rc) { 915 s_hdl = stream_obj->my_hdl; 916 } else { 917 /* error during acquire, de-init */ 918 pthread_mutex_destroy(&stream_obj->buf_lock); 919 pthread_mutex_destroy(&stream_obj->cb_lock); 920 memset(stream_obj, 0, sizeof(mm_stream_t)); 921 } 922 CDBG("%s : stream handle = %d", __func__, s_hdl); 923 return s_hdl; 924} 925 926/*=========================================================================== 927 * FUNCTION : mm_channel_del_stream 928 * 929 * DESCRIPTION: delete a stream from the channel bu its handle 930 * 931 * PARAMETERS : 932 * @my_obj : channel object 933 * @stream_id : stream handle 934 * 935 * RETURN : int32_t type of status 936 * 0 -- success 937 * -1 -- failure 938 * NOTE : assume steam is stooped before it can be deleted 939 *==========================================================================*/ 940int32_t mm_channel_del_stream(mm_channel_t *my_obj, 941 uint32_t stream_id) 942{ 943 int rc = -1; 944 mm_stream_t * stream_obj = NULL; 945 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 946 947 if (NULL == stream_obj) { 948 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d", 949 __func__, stream_id); 950 return rc; 951 } 952 953 rc = mm_stream_fsm_fn(stream_obj, 954 MM_STREAM_EVT_RELEASE, 955 NULL, 956 NULL); 957 958 return rc; 959} 960 961/*=========================================================================== 962 * FUNCTION : mm_channel_config_stream 963 * 964 * DESCRIPTION: configure a stream 965 * 966 * PARAMETERS : 967 * @my_obj : channel object 968 * @stream_id : stream handle 969 * @config : stream configuration 970 * 971 * RETURN : int32_t type of status 972 * 0 -- success 973 * -1 -- failure 974 *==========================================================================*/ 975int32_t mm_channel_config_stream(mm_channel_t *my_obj, 976 uint32_t stream_id, 977 mm_camera_stream_config_t *config) 978{ 979 int rc = -1; 980 mm_stream_t * stream_obj = NULL; 981 CDBG("%s : E stream ID = %d", __func__, stream_id); 982 stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id); 983 984 if (NULL == stream_obj) { 985 CDBG_ERROR("%s :Invalid Stream Object for stream_id = %d", __func__, stream_id); 986 return rc; 987 } 988 989 /* set stream fmt */ 990 rc = mm_stream_fsm_fn(stream_obj, 991 MM_STREAM_EVT_SET_FMT, 992 (void *)config, 993 NULL); 994 CDBG("%s : X rc = %d",__func__,rc); 995 return rc; 996} 997 998/*=========================================================================== 999 * FUNCTION : mm_channel_get_bundle_info 1000 * 1001 * DESCRIPTION: query bundle info of the channel, which should include all 1002 * streams within this channel 1003 * 1004 * PARAMETERS : 1005 * @my_obj : channel object 1006 * @bundle_info : bundle info to be filled in 1007 * 1008 * RETURN : int32_t type of status 1009 * 0 -- success 1010 * -1 -- failure 1011 *==========================================================================*/ 1012int32_t mm_channel_get_bundle_info(mm_channel_t *my_obj, 1013 cam_bundle_config_t *bundle_info) 1014{ 1015 int i; 1016 mm_stream_t *s_obj = NULL; 1017 int32_t rc = 0; 1018 1019 memset(bundle_info, 0, sizeof(cam_bundle_config_t)); 1020 bundle_info->bundle_id = my_obj->my_hdl; 1021 bundle_info->num_of_streams = 0; 1022 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 1023 if (my_obj->streams[i].my_hdl > 0) { 1024 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1025 my_obj->streams[i].my_hdl); 1026 if (NULL != s_obj) { 1027 if (CAM_STREAM_TYPE_METADATA != s_obj->stream_info->stream_type) { 1028 bundle_info->stream_ids[bundle_info->num_of_streams++] = 1029 s_obj->server_stream_id; 1030 } 1031 } else { 1032 CDBG_ERROR("%s: cannot find stream obj (%d) by handler (%d)", 1033 __func__, i, my_obj->streams[i].my_hdl); 1034 rc = -1; 1035 break; 1036 } 1037 } 1038 } 1039 if (rc != 0) { 1040 /* error, reset to 0 */ 1041 memset(bundle_info, 0, sizeof(cam_bundle_config_t)); 1042 } 1043 return rc; 1044} 1045 1046/*=========================================================================== 1047 * FUNCTION : mm_channel_start 1048 * 1049 * DESCRIPTION: start a channel, which will start all streams in the channel 1050 * 1051 * PARAMETERS : 1052 * @my_obj : channel object 1053 * 1054 * RETURN : int32_t type of status 1055 * 0 -- success 1056 * -1 -- failure 1057 *==========================================================================*/ 1058int32_t mm_channel_start(mm_channel_t *my_obj) 1059{ 1060 int32_t rc = 0; 1061 int i, j; 1062 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL}; 1063 uint8_t num_streams_to_start = 0; 1064 mm_stream_t *s_obj = NULL; 1065 int meta_stream_idx = 0; 1066 1067 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 1068 if (my_obj->streams[i].my_hdl > 0) { 1069 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1070 my_obj->streams[i].my_hdl); 1071 if (NULL != s_obj) { 1072 /* remember meta data stream index */ 1073 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) { 1074 meta_stream_idx = num_streams_to_start; 1075 } 1076 s_objs[num_streams_to_start++] = s_obj; 1077 } 1078 } 1079 } 1080 1081 if (meta_stream_idx > 0 ) { 1082 /* always start meta data stream first, so switch the stream object with the first one */ 1083 s_obj = s_objs[0]; 1084 s_objs[0] = s_objs[meta_stream_idx]; 1085 s_objs[meta_stream_idx] = s_obj; 1086 } 1087 1088 if (NULL != my_obj->bundle.super_buf_notify_cb) { 1089 /* need to send up cb, therefore launch thread */ 1090 /* init superbuf queue */ 1091 mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue); 1092 my_obj->bundle.superbuf_queue.num_streams = num_streams_to_start; 1093 my_obj->bundle.superbuf_queue.expected_frame_id = 0; 1094 my_obj->bundle.superbuf_queue.expected_frame_id_without_led = 0; 1095 my_obj->bundle.superbuf_queue.led_off_start_frame_id = 0; 1096 my_obj->bundle.superbuf_queue.led_on_start_frame_id = 0; 1097 my_obj->bundle.superbuf_queue.led_on_num_frames = 0; 1098 1099 for (i = 0; i < num_streams_to_start; i++) { 1100 /* set bundled flag to streams */ 1101 s_objs[i]->is_bundled = 1; 1102 /* init bundled streams to invalid value -1 */ 1103 my_obj->bundle.superbuf_queue.bundled_streams[i] = s_objs[i]->my_hdl; 1104 } 1105 1106 /* launch cb thread for dispatching super buf through cb */ 1107 mm_camera_cmd_thread_launch(&my_obj->cb_thread, 1108 mm_channel_dispatch_super_buf, 1109 (void*)my_obj); 1110 1111 /* launch cmd thread for super buf dataCB */ 1112 mm_camera_cmd_thread_launch(&my_obj->cmd_thread, 1113 mm_channel_process_stream_buf, 1114 (void*)my_obj); 1115 1116 /* set flag to TRUE */ 1117 my_obj->bundle.is_active = TRUE; 1118 } 1119 1120 for (i = 0; i < num_streams_to_start; i++) { 1121 /* all streams within a channel should be started at the same time */ 1122 if (s_objs[i]->state == MM_STREAM_STATE_ACTIVE) { 1123 CDBG_ERROR("%s: stream already started idx(%d)", __func__, i); 1124 rc = -1; 1125 break; 1126 } 1127 1128 /* allocate buf */ 1129 rc = mm_stream_fsm_fn(s_objs[i], 1130 MM_STREAM_EVT_GET_BUF, 1131 NULL, 1132 NULL); 1133 if (0 != rc) { 1134 CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i); 1135 break; 1136 } 1137 1138 /* reg buf */ 1139 rc = mm_stream_fsm_fn(s_objs[i], 1140 MM_STREAM_EVT_REG_BUF, 1141 NULL, 1142 NULL); 1143 if (0 != rc) { 1144 CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i); 1145 break; 1146 } 1147 1148 /* start stream */ 1149 rc = mm_stream_fsm_fn(s_objs[i], 1150 MM_STREAM_EVT_START, 1151 NULL, 1152 NULL); 1153 if (0 != rc) { 1154 CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i); 1155 break; 1156 } 1157 } 1158 1159 /* error handling */ 1160 if (0 != rc) { 1161 for (j=0; j<=i; j++) { 1162 /* stop streams*/ 1163 mm_stream_fsm_fn(s_objs[j], 1164 MM_STREAM_EVT_STOP, 1165 NULL, 1166 NULL); 1167 1168 /* unreg buf */ 1169 mm_stream_fsm_fn(s_objs[j], 1170 MM_STREAM_EVT_UNREG_BUF, 1171 NULL, 1172 NULL); 1173 1174 /* put buf back */ 1175 mm_stream_fsm_fn(s_objs[j], 1176 MM_STREAM_EVT_PUT_BUF, 1177 NULL, 1178 NULL); 1179 } 1180 1181 /* destroy super buf cmd thread */ 1182 if (TRUE == my_obj->bundle.is_active) { 1183 /* first stop bundle thread */ 1184 mm_camera_cmd_thread_release(&my_obj->cmd_thread); 1185 mm_camera_cmd_thread_release(&my_obj->cb_thread); 1186 1187 /* deinit superbuf queue */ 1188 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue); 1189 1190 /* memset bundle info */ 1191 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t)); 1192 } 1193 } 1194 my_obj->bWaitForPrepSnapshotDone = 0; 1195 1196 return rc; 1197} 1198 1199/*=========================================================================== 1200 * FUNCTION : mm_channel_stop 1201 * 1202 * DESCRIPTION: stop a channel, which will stop all streams in the channel 1203 * 1204 * PARAMETERS : 1205 * @my_obj : channel object 1206 * 1207 * RETURN : int32_t type of status 1208 * 0 -- success 1209 * -1 -- failure 1210 *==========================================================================*/ 1211int32_t mm_channel_stop(mm_channel_t *my_obj) 1212{ 1213 int32_t rc = 0; 1214 int i; 1215 mm_stream_t *s_objs[MAX_STREAM_NUM_IN_BUNDLE] = {NULL}; 1216 uint8_t num_streams_to_stop = 0; 1217 mm_stream_t *s_obj = NULL; 1218 int meta_stream_idx = 0; 1219 1220 for (i = 0; i < MAX_STREAM_NUM_IN_BUNDLE; i++) { 1221 if (my_obj->streams[i].my_hdl > 0) { 1222 s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1223 my_obj->streams[i].my_hdl); 1224 if (NULL != s_obj) { 1225 /* remember meta data stream index */ 1226 if (s_obj->stream_info->stream_type == CAM_STREAM_TYPE_METADATA) { 1227 meta_stream_idx = num_streams_to_stop; 1228 } 1229 s_objs[num_streams_to_stop++] = s_obj; 1230 } 1231 } 1232 } 1233 1234 if (meta_stream_idx < num_streams_to_stop - 1 ) { 1235 /* always stop meta data stream last, so switch the stream object with the last one */ 1236 s_obj = s_objs[num_streams_to_stop - 1]; 1237 s_objs[num_streams_to_stop - 1] = s_objs[meta_stream_idx]; 1238 s_objs[meta_stream_idx] = s_obj; 1239 } 1240 1241 for (i = 0; i < num_streams_to_stop; i++) { 1242 /* stream off */ 1243 mm_stream_fsm_fn(s_objs[i], 1244 MM_STREAM_EVT_STOP, 1245 NULL, 1246 NULL); 1247 1248 /* unreg buf at kernel */ 1249 mm_stream_fsm_fn(s_objs[i], 1250 MM_STREAM_EVT_UNREG_BUF, 1251 NULL, 1252 NULL); 1253 } 1254 1255 /* destroy super buf cmd thread */ 1256 if (TRUE == my_obj->bundle.is_active) { 1257 /* first stop bundle thread */ 1258 mm_camera_cmd_thread_release(&my_obj->cmd_thread); 1259 mm_camera_cmd_thread_release(&my_obj->cb_thread); 1260 1261 /* deinit superbuf queue */ 1262 mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue); 1263 1264 /* memset bundle info */ 1265 memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t)); 1266 } 1267 1268 /* since all streams are stopped, we are safe to 1269 * release all buffers allocated in stream */ 1270 for (i = 0; i < num_streams_to_stop; i++) { 1271 /* put buf back */ 1272 mm_stream_fsm_fn(s_objs[i], 1273 MM_STREAM_EVT_PUT_BUF, 1274 NULL, 1275 NULL); 1276 } 1277 1278 return rc; 1279} 1280 1281/*=========================================================================== 1282 * FUNCTION : mm_channel_request_super_buf 1283 * 1284 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched 1285 * frames from superbuf queue 1286 * 1287 * PARAMETERS : 1288 * @my_obj : channel object 1289 * @num_buf_requested : number of matched frames needed 1290 * @num_retro_buf_requested : number of retro frames needed 1291 * 1292 * RETURN : int32_t type of status 1293 * 0 -- success 1294 * -1 -- failure 1295 *==========================================================================*/ 1296int32_t mm_channel_request_super_buf(mm_channel_t *my_obj, 1297 uint32_t num_buf_requested, uint32_t num_retro_buf_requested) 1298{ 1299 int32_t rc = 0; 1300 mm_camera_cmdcb_t* node = NULL; 1301 1302 /* set pending_cnt 1303 * will trigger dispatching super frames if pending_cnt > 0 */ 1304 /* send cam_sem_post to wake up cmd thread to dispatch super buffer */ 1305 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1306 if (NULL != node) { 1307 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1308 node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB; 1309 node->u.req_buf.num_buf_requested = num_buf_requested; 1310 node->u.req_buf.num_retro_buf_requested = num_retro_buf_requested; 1311 1312 /* enqueue to cmd thread */ 1313 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1314 1315 /* wake up cmd thread */ 1316 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1317 } else { 1318 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1319 rc = -1; 1320 } 1321 1322 return rc; 1323} 1324 1325/*=========================================================================== 1326 * FUNCTION : mm_channel_cancel_super_buf_request 1327 * 1328 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount 1329 * of matched frames from superbuf queue 1330 * 1331 * PARAMETERS : 1332 * @my_obj : channel object 1333 * 1334 * RETURN : int32_t type of status 1335 * 0 -- success 1336 * -1 -- failure 1337 *==========================================================================*/ 1338int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj) 1339{ 1340 int32_t rc = 0; 1341 /* reset pending_cnt */ 1342 rc = mm_channel_request_super_buf(my_obj, 0, 0); 1343 return rc; 1344} 1345 1346/*=========================================================================== 1347 * FUNCTION : mm_channel_flush_super_buf_queue 1348 * 1349 * DESCRIPTION: flush superbuf queue 1350 * 1351 * PARAMETERS : 1352 * @my_obj : channel object 1353 * @frame_idx : frame idx until which to flush all superbufs 1354 * 1355 * RETURN : int32_t type of status 1356 * 0 -- success 1357 * -1 -- failure 1358 *==========================================================================*/ 1359int32_t mm_channel_flush_super_buf_queue(mm_channel_t *my_obj, uint32_t frame_idx) 1360{ 1361 int32_t rc = 0; 1362 mm_camera_cmdcb_t* node = NULL; 1363 1364 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1365 if (NULL != node) { 1366 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1367 node->cmd_type = MM_CAMERA_CMD_TYPE_FLUSH_QUEUE; 1368 node->u.frame_idx = frame_idx; 1369 1370 /* enqueue to cmd thread */ 1371 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1372 1373 /* wake up cmd thread */ 1374 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1375 } else { 1376 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1377 rc = -1; 1378 } 1379 1380 return rc; 1381} 1382 1383/*=========================================================================== 1384 * FUNCTION : mm_channel_config_notify_mode 1385 * 1386 * DESCRIPTION: configure notification mode 1387 * 1388 * PARAMETERS : 1389 * @my_obj : channel object 1390 * @notify_mode : notification mode 1391 * 1392 * RETURN : int32_t type of status 1393 * 0 -- success 1394 * -1 -- failure 1395 *==========================================================================*/ 1396int32_t mm_channel_config_notify_mode(mm_channel_t *my_obj, 1397 mm_camera_super_buf_notify_mode_t notify_mode) 1398{ 1399 int32_t rc = 0; 1400 mm_camera_cmdcb_t* node = NULL; 1401 1402 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1403 if (NULL != node) { 1404 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1405 node->u.notify_mode = notify_mode; 1406 node->cmd_type = MM_CAMERA_CMD_TYPE_CONFIG_NOTIFY; 1407 1408 /* enqueue to cmd thread */ 1409 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1410 1411 /* wake up cmd thread */ 1412 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1413 } else { 1414 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1415 rc = -1; 1416 } 1417 1418 return rc; 1419} 1420 1421/*=========================================================================== 1422 * FUNCTION : mm_channel_start_zsl_snapshot 1423 * 1424 * DESCRIPTION: start zsl snapshot 1425 * 1426 * PARAMETERS : 1427 * @my_obj : channel object 1428 * 1429 * RETURN : int32_t type of status 1430 * 0 -- success 1431 * -1 -- failure 1432 *==========================================================================*/ 1433int32_t mm_channel_start_zsl_snapshot(mm_channel_t *my_obj) 1434{ 1435 int32_t rc = 0; 1436 mm_camera_cmdcb_t* node = NULL; 1437 1438 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1439 if (NULL != node) { 1440 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1441 node->cmd_type = MM_CAMERA_CMD_TYPE_START_ZSL; 1442 1443 /* enqueue to cmd thread */ 1444 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1445 1446 /* wake up cmd thread */ 1447 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1448 } else { 1449 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1450 rc = -1; 1451 } 1452 1453 return rc; 1454} 1455 1456/*=========================================================================== 1457 * FUNCTION : mm_channel_stop_zsl_snapshot 1458 * 1459 * DESCRIPTION: stop zsl snapshot 1460 * 1461 * PARAMETERS : 1462 * @my_obj : channel object 1463 * 1464 * RETURN : int32_t type of status 1465 * 0 -- success 1466 * -1 -- failure 1467 *==========================================================================*/ 1468int32_t mm_channel_stop_zsl_snapshot(mm_channel_t *my_obj) 1469{ 1470 int32_t rc = 0; 1471 mm_camera_cmdcb_t* node = NULL; 1472 1473 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 1474 if (NULL != node) { 1475 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 1476 node->cmd_type = MM_CAMERA_CMD_TYPE_STOP_ZSL; 1477 1478 /* enqueue to cmd thread */ 1479 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 1480 1481 /* wake up cmd thread */ 1482 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 1483 } else { 1484 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 1485 rc = -1; 1486 } 1487 1488 return rc; 1489} 1490 1491/*=========================================================================== 1492 * FUNCTION : mm_channel_qbuf 1493 * 1494 * DESCRIPTION: enqueue buffer back to kernel 1495 * 1496 * PARAMETERS : 1497 * @my_obj : channel object 1498 * @buf : buf ptr to be enqueued 1499 * 1500 * RETURN : int32_t type of status 1501 * 0 -- success 1502 * -1 -- failure 1503 *==========================================================================*/ 1504int32_t mm_channel_qbuf(mm_channel_t *my_obj, 1505 mm_camera_buf_def_t *buf) 1506{ 1507 int32_t rc = -1; 1508 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id); 1509 1510 if (NULL != s_obj) { 1511 rc = mm_stream_fsm_fn(s_obj, 1512 MM_STREAM_EVT_QBUF, 1513 (void *)buf, 1514 NULL); 1515 } 1516 1517 return rc; 1518} 1519 1520/*=========================================================================== 1521 * FUNCTION : mm_channel_set_stream_parms 1522 * 1523 * DESCRIPTION: set parameters per stream 1524 * 1525 * PARAMETERS : 1526 * @my_obj : channel object 1527 * @s_id : stream handle 1528 * @parms : ptr to a param struct to be set to server 1529 * 1530 * RETURN : int32_t type of status 1531 * 0 -- success 1532 * -1 -- failure 1533 * NOTE : Assume the parms struct buf is already mapped to server via 1534 * domain socket. Corresponding fields of parameters to be set 1535 * are already filled in by upper layer caller. 1536 *==========================================================================*/ 1537int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj, 1538 mm_evt_paylod_set_get_stream_parms_t *payload) 1539{ 1540 int32_t rc = -1; 1541 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1542 payload->stream_id); 1543 if (NULL != s_obj) { 1544 rc = mm_stream_fsm_fn(s_obj, 1545 MM_STREAM_EVT_SET_PARM, 1546 (void *)payload, 1547 NULL); 1548 } 1549 1550 return rc; 1551} 1552 1553/*=========================================================================== 1554 * FUNCTION : mm_channel_get_stream_parms 1555 * 1556 * DESCRIPTION: get parameters per stream 1557 * 1558 * PARAMETERS : 1559 * @my_obj : channel object 1560 * @s_id : stream handle 1561 * @parms : ptr to a param struct to be get from server 1562 * 1563 * RETURN : int32_t type of status 1564 * 0 -- success 1565 * -1 -- failure 1566 * NOTE : Assume the parms struct buf is already mapped to server via 1567 * domain socket. Parameters to be get from server are already 1568 * filled in by upper layer caller. After this call, corresponding 1569 * fields of requested parameters will be filled in by server with 1570 * detailed information. 1571 *==========================================================================*/ 1572int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj, 1573 mm_evt_paylod_set_get_stream_parms_t *payload) 1574{ 1575 int32_t rc = -1; 1576 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1577 payload->stream_id); 1578 if (NULL != s_obj) { 1579 rc = mm_stream_fsm_fn(s_obj, 1580 MM_STREAM_EVT_GET_PARM, 1581 (void *)payload, 1582 NULL); 1583 } 1584 1585 return rc; 1586} 1587 1588/*=========================================================================== 1589 * FUNCTION : mm_channel_do_stream_action 1590 * 1591 * DESCRIPTION: request server to perform stream based action. Maybe removed later 1592 * if the functionality is included in mm_camera_set_parms 1593 * 1594 * PARAMETERS : 1595 * @my_obj : channel object 1596 * @s_id : stream handle 1597 * @actions : ptr to an action struct buf to be performed by server 1598 * 1599 * RETURN : int32_t type of status 1600 * 0 -- success 1601 * -1 -- failure 1602 * NOTE : Assume the action struct buf is already mapped to server via 1603 * domain socket. Actions to be performed by server are already 1604 * filled in by upper layer caller. 1605 *==========================================================================*/ 1606int32_t mm_channel_do_stream_action(mm_channel_t *my_obj, 1607 mm_evt_paylod_do_stream_action_t *payload) 1608{ 1609 int32_t rc = -1; 1610 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1611 payload->stream_id); 1612 if (NULL != s_obj) { 1613 rc = mm_stream_fsm_fn(s_obj, 1614 MM_STREAM_EVT_DO_ACTION, 1615 (void *)payload, 1616 NULL); 1617 } 1618 1619 return rc; 1620} 1621 1622/*=========================================================================== 1623 * FUNCTION : mm_channel_map_stream_buf 1624 * 1625 * DESCRIPTION: mapping stream buffer via domain socket to server 1626 * 1627 * PARAMETERS : 1628 * @my_obj : channel object 1629 * @payload : ptr to payload for mapping 1630 * 1631 * RETURN : int32_t type of status 1632 * 0 -- success 1633 * -1 -- failure 1634 *==========================================================================*/ 1635int32_t mm_channel_map_stream_buf(mm_channel_t *my_obj, 1636 mm_evt_paylod_map_stream_buf_t *payload) 1637{ 1638 int32_t rc = -1; 1639 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1640 payload->stream_id); 1641 if (NULL != s_obj) { 1642 rc = mm_stream_map_buf(s_obj, 1643 payload->buf_type, 1644 payload->buf_idx, 1645 payload->plane_idx, 1646 payload->fd, 1647 payload->size); 1648 } 1649 1650 return rc; 1651} 1652 1653/*=========================================================================== 1654 * FUNCTION : mm_channel_unmap_stream_buf 1655 * 1656 * DESCRIPTION: unmapping stream buffer via domain socket to server 1657 * 1658 * PARAMETERS : 1659 * @my_obj : channel object 1660 * @payload : ptr to unmap payload 1661 * 1662 * RETURN : int32_t type of status 1663 * 0 -- success 1664 * -1 -- failure 1665 *==========================================================================*/ 1666int32_t mm_channel_unmap_stream_buf(mm_channel_t *my_obj, 1667 mm_evt_paylod_unmap_stream_buf_t *payload) 1668{ 1669 int32_t rc = -1; 1670 mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, 1671 payload->stream_id); 1672 if (NULL != s_obj) { 1673 rc = mm_stream_unmap_buf(s_obj, payload->buf_type, 1674 payload->buf_idx, payload->plane_idx); 1675 } 1676 1677 return rc; 1678} 1679 1680/*=========================================================================== 1681 * FUNCTION : mm_channel_superbuf_queue_init 1682 * 1683 * DESCRIPTION: initialize superbuf queue in the channel 1684 * 1685 * PARAMETERS : 1686 * @queue : ptr to superbuf queue to be initialized 1687 * 1688 * RETURN : int32_t type of status 1689 * 0 -- success 1690 * -1 -- failure 1691 *==========================================================================*/ 1692int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue) 1693{ 1694 return cam_queue_init(&queue->que); 1695} 1696 1697/*=========================================================================== 1698 * FUNCTION : mm_channel_superbuf_queue_deinit 1699 * 1700 * DESCRIPTION: deinitialize superbuf queue in the channel 1701 * 1702 * PARAMETERS : 1703 * @queue : ptr to superbuf queue to be deinitialized 1704 * 1705 * RETURN : int32_t type of status 1706 * 0 -- success 1707 * -1 -- failure 1708 *==========================================================================*/ 1709int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue) 1710{ 1711 return cam_queue_deinit(&queue->que); 1712} 1713 1714/*=========================================================================== 1715 * FUNCTION : mm_channel_util_seq_comp_w_rollover 1716 * 1717 * DESCRIPTION: utility function to handle sequence number comparison with rollover 1718 * 1719 * PARAMETERS : 1720 * @v1 : first value to be compared 1721 * @v2 : second value to be compared 1722 * 1723 * RETURN : int8_t type of comparison result 1724 * >0 -- v1 larger than v2 1725 * =0 -- vi equal to v2 1726 * <0 -- v1 smaller than v2 1727 *==========================================================================*/ 1728int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1, 1729 uint32_t v2) 1730{ 1731 int8_t ret = 0; 1732 1733 /* TODO: need to handle the case if v2 roll over to 0 */ 1734 if (v1 > v2) { 1735 ret = 1; 1736 } else if (v1 < v2) { 1737 ret = -1; 1738 } 1739 1740 return ret; 1741} 1742 1743/*=========================================================================== 1744 * FUNCTION : mm_channel_handle_metadata 1745 * 1746 * DESCRIPTION: Handle frame matching logic change due to metadata 1747 * 1748 * PARAMETERS : 1749 * @ch_obj : channel object 1750 * @queue : superbuf queue 1751 * @buf_info: new buffer from stream 1752 * 1753 * RETURN : int32_t type of status 1754 * 0 -- success 1755 * -1 -- failure 1756 *==========================================================================*/ 1757int32_t mm_channel_handle_metadata( 1758 mm_channel_t* ch_obj, 1759 mm_channel_queue_t * queue, 1760 mm_camera_buf_info_t *buf_info) 1761{ 1762 1763 int rc = 0 ; 1764 mm_stream_t* stream_obj = NULL; 1765 stream_obj = mm_channel_util_get_stream_by_handler(ch_obj, 1766 buf_info->stream_id); 1767 uint8_t is_prep_snapshot_done_valid = 0; 1768 uint8_t is_good_frame_idx_range_valid = 0; 1769 int32_t prep_snapshot_done_state; 1770 cam_frame_idx_range_t good_frame_idx_range; 1771 uint8_t is_crop_1x_found = 0; 1772 uint32_t snapshot_stream_id = 0; 1773 uint32_t i; 1774 1775 memset(&good_frame_idx_range, 0, sizeof(good_frame_idx_range)); 1776 1777 if (NULL == stream_obj) { 1778 CDBG_ERROR("%s: Invalid Stream Object for stream_id = %d", 1779 __func__, buf_info->stream_id); 1780 rc = -1; 1781 goto end; 1782 } 1783 if (NULL == stream_obj->stream_info) { 1784 CDBG_ERROR("%s: NULL stream info for stream_id = %d", 1785 __func__, buf_info->stream_id); 1786 rc = -1; 1787 goto end; 1788 } 1789 1790 if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) { 1791 const metadata_buffer_t *metadata; 1792 metadata = (const metadata_buffer_t *)buf_info->buf->buffer; 1793 1794 if (NULL == metadata) { 1795 CDBG_ERROR("%s: NULL metadata buffer for metadata stream", 1796 __func__); 1797 rc = -1; 1798 goto end; 1799 } 1800 CDBG("%s: E , expected frame id: %d", __func__, queue->expected_frame_id); 1801 1802 if (IS_META_AVAILABLE(CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata)) { 1803 prep_snapshot_done_state = *((int32_t*) 1804 POINTER_OF_META(CAM_INTF_META_PREP_SNAPSHOT_DONE, metadata)); 1805 is_prep_snapshot_done_valid = 1; 1806 CDBG("%s: prepare snapshot done valid ", __func__); 1807 } 1808 if (IS_META_AVAILABLE(CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata)){ 1809 good_frame_idx_range = *((cam_frame_idx_range_t*) 1810 POINTER_OF_META(CAM_INTF_META_GOOD_FRAME_IDX_RANGE, metadata)); 1811 is_good_frame_idx_range_valid = 1; 1812 CDBG("%s: good_frame_idx_range : min: %d, max: %d , num frames = %d", 1813 __func__, good_frame_idx_range.min_frame_idx, 1814 good_frame_idx_range.max_frame_idx, good_frame_idx_range.num_led_on_frames); 1815 } 1816 if (IS_META_AVAILABLE(CAM_INTF_META_CROP_DATA, metadata)) { 1817 cam_crop_data_t crop_data = *((cam_crop_data_t *) 1818 POINTER_OF_META(CAM_INTF_META_CROP_DATA, metadata)); 1819 1820 for (i=0; i<ARRAY_SIZE(ch_obj->streams); i++) { 1821 if (CAM_STREAM_TYPE_SNAPSHOT == 1822 ch_obj->streams[i].stream_info->stream_type) { 1823 snapshot_stream_id = ch_obj->streams[i].server_stream_id; 1824 break; 1825 } 1826 } 1827 1828 for (i=0; i<crop_data.num_of_streams; i++) { 1829 if (snapshot_stream_id == crop_data.crop_info[i].stream_id) { 1830 if (!crop_data.crop_info[i].crop.left && 1831 !crop_data.crop_info[i].crop.top) { 1832 is_crop_1x_found = 1; 1833 break; 1834 } 1835 } 1836 } 1837 } 1838 1839 if (is_prep_snapshot_done_valid && 1840 is_good_frame_idx_range_valid) { 1841 CDBG_ERROR("%s: prep_snapshot_done and good_idx_range shouldn't be " 1842 "valid at the same time", __func__); 1843 rc = -1; 1844 goto end; 1845 } 1846 1847 if (ch_obj->isZoom1xFrameRequested) { 1848 if (is_crop_1x_found) { 1849 ch_obj->isZoom1xFrameRequested = 0; 1850 queue->expected_frame_id = buf_info->frame_idx + 1; 1851 } else { 1852 queue->expected_frame_id += 100; 1853 /* Flush unwanted frames */ 1854 mm_channel_superbuf_flush_matched(ch_obj, queue); 1855 } 1856 goto end; 1857 } 1858 1859 if (is_prep_snapshot_done_valid) { 1860 ch_obj->bWaitForPrepSnapshotDone = 0; 1861 if (prep_snapshot_done_state == NEED_FUTURE_FRAME) { 1862 /* Set expected frame id to a future frame idx, large enough to wait 1863 * for good_frame_idx_range, and small enough to still capture an image */ 1864 const int max_future_frame_offset = 100; 1865 queue->expected_frame_id += max_future_frame_offset; 1866 CDBG("%s: [ZSL Retro] NEED_FUTURE_FRAME, expected frame id = %d ", 1867 __func__, queue->expected_frame_id); 1868 1869 mm_channel_superbuf_flush(ch_obj, queue); 1870 ch_obj->needLEDFlash = TRUE; 1871 } else { 1872 ch_obj->needLEDFlash = FALSE; 1873 } 1874 } else if (is_good_frame_idx_range_valid) { 1875 if (good_frame_idx_range.min_frame_idx > 1876 queue->expected_frame_id) { 1877 CDBG_HIGH("%s: [ZSL Retro] min_frame_idx %d is greater than expected_frame_id %d", 1878 __func__, good_frame_idx_range.min_frame_idx, 1879 queue->expected_frame_id); 1880 } 1881 queue->expected_frame_id = 1882 good_frame_idx_range.min_frame_idx; 1883 if((ch_obj->needLEDFlash == TRUE) && (ch_obj->burstSnapNum > 1)) { 1884 queue->expected_frame_id = 1885 good_frame_idx_range.min_frame_idx; 1886 queue->led_on_start_frame_id = 1887 good_frame_idx_range.min_frame_idx; 1888 queue->led_off_start_frame_id = 1889 good_frame_idx_range.max_frame_idx; 1890 queue->once = 0; 1891 queue->led_on_num_frames = 1892 good_frame_idx_range.num_led_on_frames; 1893 queue->frame_skip_count = good_frame_idx_range.frame_skip_count; 1894 CDBG("%s: [ZSL Retro] Need Flash, expected frame id = %d," 1895 " led_on start = %d, led off start = %d, led on frames = %d ", 1896 __func__, queue->expected_frame_id, queue->led_on_start_frame_id, 1897 queue->led_off_start_frame_id, queue->led_on_num_frames); 1898 } else { 1899 queue->expected_frame_id = 1900 good_frame_idx_range.min_frame_idx; 1901 CDBG("%s: [ZSL Retro]No flash, expected frame id = %d ", 1902 __func__, queue->expected_frame_id); 1903 } 1904 } else if(ch_obj->need3ABracketing && 1905 !is_good_frame_idx_range_valid) { 1906 /* Flush unwanted frames */ 1907 mm_channel_superbuf_flush_matched(ch_obj, queue); 1908 } 1909 if (ch_obj->isFlashBracketingEnabled && 1910 is_good_frame_idx_range_valid) { 1911 /* Flash bracketing needs two frames, with & without led flash. 1912 * in valid range min frame is with led flash and max frame is 1913 * without led flash */ 1914 queue->expected_frame_id = 1915 good_frame_idx_range.min_frame_idx; 1916 /* max frame is without led flash */ 1917 queue->expected_frame_id_without_led = 1918 good_frame_idx_range.max_frame_idx; 1919 1920 } else if (is_good_frame_idx_range_valid) { 1921 if (good_frame_idx_range.min_frame_idx > 1922 queue->expected_frame_id) { 1923 CDBG_HIGH("%s: min_frame_idx %d is greater than expected_frame_id %d", 1924 __func__, good_frame_idx_range.min_frame_idx, 1925 queue->expected_frame_id); 1926 } 1927 queue->expected_frame_id = 1928 good_frame_idx_range.min_frame_idx; 1929 ch_obj->need3ABracketing = FALSE; 1930 } 1931 1932 if((ch_obj->burstSnapNum > 1) && (ch_obj->needLEDFlash == TRUE) && 1933 !ch_obj->isFlashBracketingEnabled) { 1934 if((buf_info->frame_idx >= queue->led_off_start_frame_id) 1935 && !queue->once) { 1936 CDBG("%s: [ZSL Retro]Burst snap num = %d ", 1937 __func__, ch_obj->burstSnapNum); 1938 // Skip frames from LED OFF frame to get a good frame 1939 queue->expected_frame_id = queue->led_off_start_frame_id + queue->frame_skip_count; 1940 queue->once = 1; 1941 ch_obj->stopZslSnapshot = 1; 1942 CDBG("%s:[ZSL Retro]Reached max led on frames = %d , expected id = %d", 1943 __func__, buf_info->frame_idx, queue->expected_frame_id); 1944 } 1945 } 1946 } 1947end: 1948 return rc; 1949} 1950 1951/*=========================================================================== 1952 * FUNCTION : mm_channel_superbuf_comp_and_enqueue 1953 * 1954 * DESCRIPTION: implementation for matching logic for superbuf 1955 * 1956 * PARAMETERS : 1957 * @ch_obj : channel object 1958 * @queue : superbuf queue 1959 * @buf_info: new buffer from stream 1960 * 1961 * RETURN : int32_t type of status 1962 * 0 -- success 1963 * -1 -- failure 1964 *==========================================================================*/ 1965int32_t mm_channel_superbuf_comp_and_enqueue( 1966 mm_channel_t* ch_obj, 1967 mm_channel_queue_t *queue, 1968 mm_camera_buf_info_t *buf_info) 1969{ 1970 cam_node_t* node = NULL; 1971 struct cam_list *head = NULL; 1972 struct cam_list *pos = NULL; 1973 mm_channel_queue_node_t* super_buf = NULL; 1974 uint8_t buf_s_idx, i, found_super_buf, unmatched_bundles; 1975 struct cam_list *last_buf, *insert_before_buf; 1976 1977 CDBG("%s: E", __func__); 1978 for (buf_s_idx = 0; buf_s_idx < queue->num_streams; buf_s_idx++) { 1979 if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) { 1980 break; 1981 } 1982 } 1983 if (buf_s_idx == queue->num_streams) { 1984 CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id); 1985 return -1; 1986 } 1987 1988 if (mm_channel_handle_metadata(ch_obj, queue, buf_info) < 0) { 1989 mm_channel_qbuf(ch_obj, buf_info->buf); 1990 return -1; 1991 } 1992 #if 0 1993 mm_stream_t* stream_obj = mm_channel_util_get_stream_by_handler(ch_obj, 1994 buf_info->stream_id); 1995 1996 if (CAM_STREAM_TYPE_METADATA == stream_obj->stream_info->stream_type) { 1997 const metadata_buffer_t *metadata; 1998 metadata = (const metadata_buffer_t *)buf_info->buf->buffer; 1999 int32_t is_meta_valid = *((int32_t*)POINTER_OF(CAM_INTF_META_VALID, metadata)); 2000 CDBG("%s: meta_valid: %d\n", __func__, is_meta_valid); 2001 if (!is_meta_valid) { 2002 mm_channel_qbuf(ch_obj, buf_info->buf); 2003 return 0; 2004 } 2005 } 2006 #endif 2007 if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx, 2008 queue->expected_frame_id) < 0) { 2009 /* incoming buf is older than expected buf id, will discard it */ 2010 mm_channel_qbuf(ch_obj, buf_info->buf); 2011 return 0; 2012 } 2013 2014 if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) { 2015 /* TODO */ 2016 /* need to decide if we want to queue the frame based on focus or exposure 2017 * if frame not to be queued, we need to qbuf it back */ 2018 } 2019 2020 /* comp */ 2021 pthread_mutex_lock(&queue->que.lock); 2022 head = &queue->que.head.list; 2023 /* get the last one in the queue which is possibly having no matching */ 2024 pos = head->next; 2025 2026 found_super_buf = 0; 2027 unmatched_bundles = 0; 2028 last_buf = NULL; 2029 insert_before_buf = NULL; 2030 while (pos != head) { 2031 node = member_of(pos, cam_node_t, list); 2032 super_buf = (mm_channel_queue_node_t*)node->data; 2033 if (NULL != super_buf) { 2034 if (super_buf->matched) { 2035 /* find a matched super buf, move to next one */ 2036 pos = pos->next; 2037 continue; 2038 } else if ( buf_info->frame_idx == super_buf->frame_idx ) { 2039 /* have an unmatched super buf that matches our frame idx, 2040 * break the loop */ 2041 found_super_buf = 1; 2042 break; 2043 } else { 2044 unmatched_bundles++; 2045 if ( NULL == last_buf ) { 2046 if ( super_buf->frame_idx < buf_info->frame_idx ) { 2047 last_buf = pos; 2048 } 2049 } 2050 if ( NULL == insert_before_buf ) { 2051 if ( super_buf->frame_idx > buf_info->frame_idx ) { 2052 insert_before_buf = pos; 2053 } 2054 } 2055 pos = pos->next; 2056 } 2057 } 2058 } 2059 if ( found_super_buf ) { 2060 super_buf->super_buf[buf_s_idx] = *buf_info; 2061 2062 /* check if superbuf is all matched */ 2063 super_buf->matched = 1; 2064 for (i=0; i < super_buf->num_of_bufs; i++) { 2065 if (super_buf->super_buf[i].frame_idx == 0) { 2066 super_buf->matched = 0; 2067 break; 2068 } 2069 } 2070 2071 if (super_buf->matched) { 2072 if(ch_obj->isFlashBracketingEnabled) { 2073 queue->expected_frame_id = 2074 queue->expected_frame_id_without_led; 2075 if (buf_info->frame_idx >= 2076 queue->expected_frame_id_without_led) { 2077 ch_obj->isFlashBracketingEnabled = FALSE; 2078 } 2079 } else { 2080 queue->expected_frame_id = buf_info->frame_idx 2081 + queue->attr.post_frame_skip; 2082 } 2083 CDBG("%s: curr = %d, skip = %d , Expected Frame ID: %d", 2084 __func__, buf_info->frame_idx, 2085 queue->attr.post_frame_skip, queue->expected_frame_id); 2086 2087 queue->match_cnt++; 2088 /* Any older unmatched buffer need to be released */ 2089 if ( last_buf ) { 2090 while ( last_buf != pos ) { 2091 node = member_of(last_buf, cam_node_t, list); 2092 super_buf = (mm_channel_queue_node_t*)node->data; 2093 if (NULL != super_buf) { 2094 for (i=0; i<super_buf->num_of_bufs; i++) { 2095 if (super_buf->super_buf[i].frame_idx != 0) { 2096 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 2097 } 2098 } 2099 queue->que.size--; 2100 last_buf = last_buf->next; 2101 cam_list_del_node(&node->list); 2102 free(node); 2103 free(super_buf); 2104 } else { 2105 CDBG_ERROR(" %s : Invalid superbuf in queue!", __func__); 2106 break; 2107 } 2108 } 2109 } 2110 } 2111 } else { 2112 if ( ( queue->attr.max_unmatched_frames < unmatched_bundles ) && 2113 ( NULL == last_buf ) ) { 2114 /* incoming frame is older than the last bundled one */ 2115 mm_channel_qbuf(ch_obj, buf_info->buf); 2116 } else { 2117 if ( queue->attr.max_unmatched_frames < unmatched_bundles ) { 2118 /* release the oldest bundled superbuf */ 2119 node = member_of(last_buf, cam_node_t, list); 2120 super_buf = (mm_channel_queue_node_t*)node->data; 2121 for (i=0; i<super_buf->num_of_bufs; i++) { 2122 if (super_buf->super_buf[i].frame_idx != 0) { 2123 mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf); 2124 } 2125 } 2126 queue->que.size--; 2127 node = member_of(last_buf, cam_node_t, list); 2128 cam_list_del_node(&node->list); 2129 free(node); 2130 free(super_buf); 2131 } 2132 /* insert the new frame at the appropriate position. */ 2133 2134 mm_channel_queue_node_t *new_buf = NULL; 2135 cam_node_t* new_node = NULL; 2136 2137 new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t)); 2138 new_node = (cam_node_t*)malloc(sizeof(cam_node_t)); 2139 if (NULL != new_buf && NULL != new_node) { 2140 memset(new_buf, 0, sizeof(mm_channel_queue_node_t)); 2141 memset(new_node, 0, sizeof(cam_node_t)); 2142 new_node->data = (void *)new_buf; 2143 new_buf->num_of_bufs = queue->num_streams; 2144 new_buf->super_buf[buf_s_idx] = *buf_info; 2145 new_buf->frame_idx = buf_info->frame_idx; 2146 /* enqueue */ 2147 if ( insert_before_buf ) { 2148 cam_list_insert_before_node(&new_node->list, insert_before_buf); 2149 } else { 2150 cam_list_add_tail_node(&new_node->list, &queue->que.head.list); 2151 } 2152 queue->que.size++; 2153 2154 if(queue->num_streams == 1) { 2155 new_buf->matched = 1; 2156 2157 queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip; 2158 queue->match_cnt++; 2159 } 2160 } else { 2161 /* No memory */ 2162 if (NULL != new_buf) { 2163 free(new_buf); 2164 } 2165 if (NULL != new_node) { 2166 free(new_node); 2167 } 2168 /* qbuf the new buf since we cannot enqueue */ 2169 mm_channel_qbuf(ch_obj, buf_info->buf); 2170 } 2171 } 2172 } 2173 2174 pthread_mutex_unlock(&queue->que.lock); 2175 CDBG("%s: X", __func__); 2176 return 0; 2177} 2178 2179/*=========================================================================== 2180 * FUNCTION : mm_channel_superbuf_dequeue_internal 2181 * 2182 * DESCRIPTION: internal implementation for dequeue from the superbuf queue 2183 * 2184 * PARAMETERS : 2185 * @queue : superbuf queue 2186 * @matched_only : if dequeued buf should be matched 2187 * 2188 * RETURN : ptr to a node from superbuf queue 2189 *==========================================================================*/ 2190mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue, 2191 uint8_t matched_only) 2192{ 2193 cam_node_t* node = NULL; 2194 struct cam_list *head = NULL; 2195 struct cam_list *pos = NULL; 2196 mm_channel_queue_node_t* super_buf = NULL; 2197 2198 head = &queue->que.head.list; 2199 pos = head->next; 2200 if (pos != head) { 2201 /* get the first node */ 2202 node = member_of(pos, cam_node_t, list); 2203 super_buf = (mm_channel_queue_node_t*)node->data; 2204 if ( (NULL != super_buf) && 2205 (matched_only == TRUE) && 2206 (super_buf->matched == FALSE) ) { 2207 /* require to dequeue matched frame only, but this superbuf is not matched, 2208 simply set return ptr to NULL */ 2209 super_buf = NULL; 2210 } 2211 if (NULL != super_buf) { 2212 /* remove from the queue */ 2213 cam_list_del_node(&node->list); 2214 queue->que.size--; 2215 if (super_buf->matched == TRUE) { 2216 queue->match_cnt--; 2217 } 2218 free(node); 2219 } 2220 } 2221 2222 return super_buf; 2223} 2224 2225/*=========================================================================== 2226 * FUNCTION : mm_channel_superbuf_dequeue 2227 * 2228 * DESCRIPTION: dequeue from the superbuf queue 2229 * 2230 * PARAMETERS : 2231 * @queue : superbuf queue 2232 * 2233 * RETURN : ptr to a node from superbuf queue 2234 *==========================================================================*/ 2235mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue) 2236{ 2237 mm_channel_queue_node_t* super_buf = NULL; 2238 2239 pthread_mutex_lock(&queue->que.lock); 2240 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE); 2241 pthread_mutex_unlock(&queue->que.lock); 2242 2243 return super_buf; 2244} 2245 2246/*=========================================================================== 2247 * FUNCTION : mm_channel_superbuf_bufdone_overflow 2248 * 2249 * DESCRIPTION: keep superbuf queue no larger than watermark set by upper layer 2250 * via channel attribute 2251 * 2252 * PARAMETERS : 2253 * @my_obj : channel object 2254 * @queue : superbuf queue 2255 * 2256 * RETURN : int32_t type of status 2257 * 0 -- success 2258 * -1 -- failure 2259 *==========================================================================*/ 2260int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj, 2261 mm_channel_queue_t * queue) 2262{ 2263 int32_t rc = 0, i; 2264 mm_channel_queue_node_t* super_buf = NULL; 2265 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) { 2266 /* for continuous streaming mode, no overflow is needed */ 2267 return 0; 2268 } 2269 2270 CDBG("%s: before match_cnt=%d, water_mark=%d", 2271 __func__, queue->match_cnt, queue->attr.water_mark); 2272 /* bufdone overflowed bufs */ 2273 pthread_mutex_lock(&queue->que.lock); 2274 while (queue->match_cnt > queue->attr.water_mark) { 2275 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE); 2276 if (NULL != super_buf) { 2277 for (i=0; i<super_buf->num_of_bufs; i++) { 2278 if (NULL != super_buf->super_buf[i].buf) { 2279 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 2280 } 2281 } 2282 free(super_buf); 2283 } 2284 } 2285 pthread_mutex_unlock(&queue->que.lock); 2286 CDBG("%s: after match_cnt=%d, water_mark=%d", 2287 __func__, queue->match_cnt, queue->attr.water_mark); 2288 2289 return rc; 2290} 2291 2292/*=========================================================================== 2293 * FUNCTION : mm_channel_superbuf_skip 2294 * 2295 * DESCRIPTION: depends on the lookback configuration of the channel attribute, 2296 * unwanted superbufs will be removed from the superbuf queue. 2297 * 2298 * PARAMETERS : 2299 * @my_obj : channel object 2300 * @queue : superbuf queue 2301 * 2302 * RETURN : int32_t type of status 2303 * 0 -- success 2304 * -1 -- failure 2305 *==========================================================================*/ 2306int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj, 2307 mm_channel_queue_t * queue) 2308{ 2309 int32_t rc = 0, i; 2310 mm_channel_queue_node_t* super_buf = NULL; 2311 if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) { 2312 /* for continuous streaming mode, no skip is needed */ 2313 return 0; 2314 } 2315 2316 /* bufdone overflowed bufs */ 2317 pthread_mutex_lock(&queue->que.lock); 2318 while (queue->match_cnt > queue->attr.look_back) { 2319 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE); 2320 if (NULL != super_buf) { 2321 for (i=0; i<super_buf->num_of_bufs; i++) { 2322 if (NULL != super_buf->super_buf[i].buf) { 2323 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 2324 } 2325 } 2326 free(super_buf); 2327 } 2328 } 2329 pthread_mutex_unlock(&queue->que.lock); 2330 2331 return rc; 2332} 2333 2334/*=========================================================================== 2335 * FUNCTION : mm_channel_superbuf_flush 2336 * 2337 * DESCRIPTION: flush the superbuf queue. 2338 * 2339 * PARAMETERS : 2340 * @my_obj : channel object 2341 * @queue : superbuf queue 2342 * 2343 * RETURN : int32_t type of status 2344 * 0 -- success 2345 * -1 -- failure 2346 *==========================================================================*/ 2347int32_t mm_channel_superbuf_flush(mm_channel_t* my_obj, 2348 mm_channel_queue_t * queue) 2349{ 2350 int32_t rc = 0, i; 2351 mm_channel_queue_node_t* super_buf = NULL; 2352 2353 /* bufdone bufs */ 2354 pthread_mutex_lock(&queue->que.lock); 2355 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE); 2356 while (super_buf != NULL) { 2357 for (i=0; i<super_buf->num_of_bufs; i++) { 2358 if (NULL != super_buf->super_buf[i].buf) { 2359 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 2360 } 2361 } 2362 free(super_buf); 2363 super_buf = mm_channel_superbuf_dequeue_internal(queue, FALSE); 2364 } 2365 pthread_mutex_unlock(&queue->que.lock); 2366 2367 return rc; 2368} 2369 2370/*=========================================================================== 2371 * FUNCTION : mm_channel_proc_general_cmd 2372 * 2373 * DESCRIPTION: process general command 2374 * 2375 * PARAMETERS : 2376 * @my_obj : channel object 2377 * @notify_mode : notification mode 2378 * 2379 * RETURN : int32_t type of status 2380 * 0 -- success 2381 * -1 -- failure 2382 *==========================================================================*/ 2383int32_t mm_channel_proc_general_cmd(mm_channel_t *my_obj, 2384 mm_camera_generic_cmd_t *p_gen_cmd) 2385{ 2386 CDBG("%s: E",__func__); 2387 int32_t rc = 0; 2388 mm_camera_cmdcb_t* node = NULL; 2389 2390 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t)); 2391 if (NULL != node) { 2392 memset(node, 0, sizeof(mm_camera_cmdcb_t)); 2393 node->u.gen_cmd = *p_gen_cmd; 2394 node->cmd_type = MM_CAMERA_CMD_TYPE_GENERAL; 2395 2396 /* enqueue to cmd thread */ 2397 cam_queue_enq(&(my_obj->cmd_thread.cmd_queue), node); 2398 2399 /* wake up cmd thread */ 2400 cam_sem_post(&(my_obj->cmd_thread.cmd_sem)); 2401 } else { 2402 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__); 2403 rc = -1; 2404 } 2405 CDBG("%s: X",__func__); 2406 2407 return rc; 2408} 2409 2410/*=========================================================================== 2411 * FUNCTION : mm_channel_superbuf_flush_matched 2412 * 2413 * DESCRIPTION: flush matched buffers from the superbuf queue. 2414 * 2415 * PARAMETERS : 2416 * @my_obj : channel object 2417 * @queue : superbuf queue 2418 * 2419 * RETURN : int32_t type of status 2420 * 0 -- success 2421 * -1 -- failure 2422 *==========================================================================*/ 2423int32_t mm_channel_superbuf_flush_matched(mm_channel_t* my_obj, 2424 mm_channel_queue_t * queue) 2425{ 2426 int32_t rc = 0, i; 2427 mm_channel_queue_node_t* super_buf = NULL; 2428 2429 /* bufdone bufs */ 2430 pthread_mutex_lock(&queue->que.lock); 2431 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE); 2432 while (super_buf != NULL) { 2433 for (i=0; i<super_buf->num_of_bufs; i++) { 2434 if (NULL != super_buf->super_buf[i].buf) { 2435 mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf); 2436 } 2437 } 2438 free(super_buf); 2439 super_buf = mm_channel_superbuf_dequeue_internal(queue, TRUE); 2440 } 2441 pthread_mutex_unlock(&queue->que.lock); 2442 2443 return rc; 2444} 2445