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