1 /* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30 #include <pthread.h>
31 #include <errno.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <poll.h>
37
38 #include <cam_semaphore.h>
39
40 #include "mm_camera_dbg.h"
41 #include "mm_camera_sock.h"
42 #include "mm_camera_interface.h"
43 #include "mm_camera.h"
44
45 #define SET_PARM_BIT32(parm, parm_arr) \
46 (parm_arr[parm/32] |= (1<<(parm%32)))
47
48 #define GET_PARM_BIT32(parm, parm_arr) \
49 ((parm_arr[parm/32]>>(parm%32))& 0x1)
50
51 /* internal function declare */
52 int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
53 uint8_t reg_flag);
54 int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
55 mm_camera_event_t *event);
56
57 /*===========================================================================
58 * FUNCTION : mm_camera_util_get_channel_by_handler
59 *
60 * DESCRIPTION: utility function to get a channel object from its handle
61 *
62 * PARAMETERS :
63 * @cam_obj: ptr to a camera object
64 * @handler: channel handle
65 *
66 * RETURN : ptr to a channel object.
67 * NULL if failed.
68 *==========================================================================*/
mm_camera_util_get_channel_by_handler(mm_camera_obj_t * cam_obj,uint32_t handler)69 mm_channel_t * mm_camera_util_get_channel_by_handler(
70 mm_camera_obj_t * cam_obj,
71 uint32_t handler)
72 {
73 int i;
74 mm_channel_t *ch_obj = NULL;
75 for(i = 0; i < MM_CAMERA_CHANNEL_MAX; i++) {
76 if (handler == cam_obj->ch[i].my_hdl) {
77 ch_obj = &cam_obj->ch[i];
78 break;
79 }
80 }
81 return ch_obj;
82 }
83
84 /*===========================================================================
85 * FUNCTION : mm_camera_util_chip_is_a_family
86 *
87 * DESCRIPTION: utility function to check if the host is A family chip
88 *
89 * PARAMETERS :
90 *
91 * RETURN : TRUE if A family.
92 * FALSE otherwise.
93 *==========================================================================*/
mm_camera_util_chip_is_a_family(void)94 uint8_t mm_camera_util_chip_is_a_family(void)
95 {
96 int id = 0;
97 FILE *fp;
98 if ((fp = fopen("/sys/devices/system/soc/soc0/id", "r")) != NULL) {
99 fscanf(fp, "%d", &id);
100 fclose(fp);
101 }
102 if (id == 126)
103 return FALSE;
104 else
105 return TRUE;
106 }
107
108 /*===========================================================================
109 * FUNCTION : mm_camera_dispatch_app_event
110 *
111 * DESCRIPTION: dispatch event to apps who regitster for event notify
112 *
113 * PARAMETERS :
114 * @cmd_cb: ptr to a struct storing event info
115 * @user_data: user data ptr (camera object)
116 *
117 * RETURN : none
118 *==========================================================================*/
mm_camera_dispatch_app_event(mm_camera_cmdcb_t * cmd_cb,void * user_data)119 static void mm_camera_dispatch_app_event(mm_camera_cmdcb_t *cmd_cb,
120 void* user_data)
121 {
122 mm_camera_cmd_thread_name("mm_cam_event");
123 int i;
124 mm_camera_event_t *event = &cmd_cb->u.evt;
125 mm_camera_obj_t * my_obj = (mm_camera_obj_t *)user_data;
126 if (NULL != my_obj) {
127 pthread_mutex_lock(&my_obj->cb_lock);
128 for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
129 if(my_obj->evt.evt[i].evt_cb) {
130 my_obj->evt.evt[i].evt_cb(
131 my_obj->my_hdl,
132 event,
133 my_obj->evt.evt[i].user_data);
134 }
135 }
136 pthread_mutex_unlock(&my_obj->cb_lock);
137 }
138 }
139
140 /*===========================================================================
141 * FUNCTION : mm_camera_event_notify
142 *
143 * DESCRIPTION: callback to handle event notify from kernel. This call will
144 * dequeue event from kernel.
145 *
146 * PARAMETERS :
147 * @user_data: user data ptr (camera object)
148 *
149 * RETURN : none
150 *==========================================================================*/
mm_camera_event_notify(void * user_data)151 static void mm_camera_event_notify(void* user_data)
152 {
153 struct v4l2_event ev;
154 struct msm_v4l2_event_data *msm_evt = NULL;
155 int rc;
156 mm_camera_event_t evt;
157 memset(&evt, 0, sizeof(mm_camera_event_t));
158
159 mm_camera_obj_t *my_obj = (mm_camera_obj_t*)user_data;
160 if (NULL != my_obj) {
161 /* read evt */
162 memset(&ev, 0, sizeof(ev));
163 rc = ioctl(my_obj->ctrl_fd, VIDIOC_DQEVENT, &ev);
164
165 if (rc >= 0 && ev.id == MSM_CAMERA_MSM_NOTIFY) {
166 msm_evt = (struct msm_v4l2_event_data *)ev.u.data;
167 switch (msm_evt->command) {
168 case CAM_EVENT_TYPE_MAP_UNMAP_DONE:
169 pthread_mutex_lock(&my_obj->evt_lock);
170 my_obj->evt_rcvd.server_event_type = msm_evt->command;
171 my_obj->evt_rcvd.status = msm_evt->status;
172 pthread_cond_signal(&my_obj->evt_cond);
173 pthread_mutex_unlock(&my_obj->evt_lock);
174 break;
175 case MSM_CAMERA_PRIV_SHUTDOWN:
176 {
177 evt.server_event_type = CAM_EVENT_TYPE_DAEMON_DIED;
178 mm_camera_enqueue_evt(my_obj, &evt);
179 }
180 break;
181 default:
182 break;
183 }
184 }
185 }
186 }
187
188 /*===========================================================================
189 * FUNCTION : mm_camera_enqueue_evt
190 *
191 * DESCRIPTION: enqueue received event into event queue to be processed by
192 * event thread.
193 *
194 * PARAMETERS :
195 * @my_obj : ptr to a camera object
196 * @event : event to be queued
197 *
198 * RETURN : int32_t type of status
199 * 0 -- success
200 * -1 -- failure
201 *==========================================================================*/
mm_camera_enqueue_evt(mm_camera_obj_t * my_obj,mm_camera_event_t * event)202 int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
203 mm_camera_event_t *event)
204 {
205 int32_t rc = 0;
206 mm_camera_cmdcb_t *node = NULL;
207
208 node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
209 if (NULL != node) {
210 memset(node, 0, sizeof(mm_camera_cmdcb_t));
211 node->cmd_type = MM_CAMERA_CMD_TYPE_EVT_CB;
212 node->u.evt = *event;
213
214 /* enqueue to evt cmd thread */
215 cam_queue_enq(&(my_obj->evt_thread.cmd_queue), node);
216 /* wake up evt cmd thread */
217 cam_sem_post(&(my_obj->evt_thread.cmd_sem));
218 } else {
219 CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
220 rc = -1;
221 }
222
223 return rc;
224 }
225
226 /*===========================================================================
227 * FUNCTION : mm_camera_open
228 *
229 * DESCRIPTION: open a camera
230 *
231 * PARAMETERS :
232 * @my_obj : ptr to a camera object
233 *
234 * RETURN : int32_t type of status
235 * 0 -- success
236 * -1 -- failure
237 *==========================================================================*/
mm_camera_open(mm_camera_obj_t * my_obj)238 int32_t mm_camera_open(mm_camera_obj_t *my_obj)
239 {
240 char dev_name[MM_CAMERA_DEV_NAME_LEN];
241 int32_t rc = 0;
242 int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
243 uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
244 unsigned int cam_idx = 0;
245
246 CDBG("%s: begin\n", __func__);
247
248 snprintf(dev_name, sizeof(dev_name), "/dev/%s",
249 mm_camera_util_get_dev_name(my_obj->my_hdl));
250 sscanf(dev_name, "/dev/video%u", &cam_idx);
251 CDBG_HIGH("%s: dev name = %s, cam_idx = %d", __func__, dev_name, cam_idx);
252
253 do{
254 n_try--;
255 my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
256 CDBG("%s: ctrl_fd = %d, errno == %d", __func__, my_obj->ctrl_fd, errno);
257 if((my_obj->ctrl_fd > 0) || (errno != EIO) || (n_try <= 0 )) {
258 CDBG_HIGH("%s: opened, break out while loop", __func__);
259 break;
260 }
261 CDBG_HIGH("%s:failed with I/O error retrying after %d milli-seconds",
262 __func__, sleep_msec);
263 usleep(sleep_msec * 1000);
264 }while (n_try > 0);
265
266 if (my_obj->ctrl_fd <= 0) {
267 CDBG_ERROR("%s: cannot open control fd of '%s' (%s)\n",
268 __func__, dev_name, strerror(errno));
269 rc = -1;
270 goto on_error;
271 }
272
273 /* open domain socket*/
274 n_try = MM_CAMERA_DEV_OPEN_TRIES;
275 do {
276 n_try--;
277 my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
278 CDBG("%s: ds_fd = %d, errno = %d", __func__, my_obj->ds_fd, errno);
279 if((my_obj->ds_fd > 0) || (n_try <= 0 )) {
280 CDBG("%s: opened, break out while loop", __func__);
281 break;
282 }
283 CDBG("%s:failed with I/O error retrying after %d milli-seconds",
284 __func__, sleep_msec);
285 usleep(sleep_msec * 1000);
286 } while (n_try > 0);
287
288 if (my_obj->ds_fd <= 0) {
289 CDBG_ERROR("%s: cannot open domain socket fd of '%s'(%s)\n",
290 __func__, dev_name, strerror(errno));
291 rc = -1;
292 goto on_error;
293 }
294 pthread_mutex_init(&my_obj->msg_lock, NULL);
295
296 pthread_mutex_init(&my_obj->cb_lock, NULL);
297 pthread_mutex_init(&my_obj->evt_lock, NULL);
298 pthread_cond_init(&my_obj->evt_cond, NULL);
299
300 CDBG("%s : Launch evt Thread in Cam Open",__func__);
301 mm_camera_cmd_thread_launch(&my_obj->evt_thread,
302 mm_camera_dispatch_app_event,
303 (void *)my_obj);
304
305 /* launch event poll thread
306 * we will add evt fd into event poll thread upon user first register for evt */
307 CDBG("%s : Launch evt Poll Thread in Cam Open", __func__);
308 mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
309 MM_CAMERA_POLL_TYPE_EVT);
310 mm_camera_evt_sub(my_obj, TRUE);
311
312 CDBG("%s: end (rc = %d)\n", __func__, rc);
313 /* we do not need to unlock cam_lock here before return
314 * because for open, it's done within intf_lock */
315 return rc;
316
317 on_error:
318 if (my_obj->ctrl_fd > 0) {
319 close(my_obj->ctrl_fd);
320 my_obj->ctrl_fd = 0;
321 }
322 if (my_obj->ds_fd > 0) {
323 mm_camera_socket_close(my_obj->ds_fd);
324 my_obj->ds_fd = 0;
325 }
326
327 /* we do not need to unlock cam_lock here before return
328 * because for open, it's done within intf_lock */
329 return rc;
330 }
331
332 /*===========================================================================
333 * FUNCTION : mm_camera_close
334 *
335 * DESCRIPTION: enqueue received event into event queue to be processed by
336 * event thread.
337 *
338 * PARAMETERS :
339 * @my_obj : ptr to a camera object
340 * @event : event to be queued
341 *
342 * RETURN : int32_t type of status
343 * 0 -- success
344 * -1 -- failure
345 *==========================================================================*/
mm_camera_close(mm_camera_obj_t * my_obj)346 int32_t mm_camera_close(mm_camera_obj_t *my_obj)
347 {
348 CDBG("%s : unsubscribe evt", __func__);
349 mm_camera_evt_sub(my_obj, FALSE);
350
351 CDBG("%s : Close evt Poll Thread in Cam Close",__func__);
352 mm_camera_poll_thread_release(&my_obj->evt_poll_thread);
353
354 CDBG("%s : Close evt cmd Thread in Cam Close",__func__);
355 mm_camera_cmd_thread_release(&my_obj->evt_thread);
356
357 if(my_obj->ctrl_fd > 0) {
358 close(my_obj->ctrl_fd);
359 my_obj->ctrl_fd = 0;
360 }
361 if(my_obj->ds_fd > 0) {
362 mm_camera_socket_close(my_obj->ds_fd);
363 my_obj->ds_fd = 0;
364 }
365 pthread_mutex_destroy(&my_obj->msg_lock);
366
367 pthread_mutex_destroy(&my_obj->cb_lock);
368 pthread_mutex_destroy(&my_obj->evt_lock);
369 pthread_cond_destroy(&my_obj->evt_cond);
370
371 pthread_mutex_unlock(&my_obj->cam_lock);
372 return 0;
373 }
374
375 /*===========================================================================
376 * FUNCTION : mm_camera_register_event_notify_internal
377 *
378 * DESCRIPTION: internal implementation for registering callback for event notify.
379 *
380 * PARAMETERS :
381 * @my_obj : ptr to a camera object
382 * @evt_cb : callback to be registered to handle event notify
383 * @user_data: user data ptr
384 *
385 * RETURN : int32_t type of status
386 * 0 -- success
387 * -1 -- failure
388 *==========================================================================*/
mm_camera_register_event_notify_internal(mm_camera_obj_t * my_obj,mm_camera_event_notify_t evt_cb,void * user_data)389 int32_t mm_camera_register_event_notify_internal(mm_camera_obj_t *my_obj,
390 mm_camera_event_notify_t evt_cb,
391 void * user_data)
392 {
393 int i;
394 int rc = -1;
395 mm_camera_evt_obj_t *evt_array = NULL;
396
397 pthread_mutex_lock(&my_obj->cb_lock);
398 evt_array = &my_obj->evt;
399 if(evt_cb) {
400 /* this is reg case */
401 for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
402 if(evt_array->evt[i].user_data == NULL) {
403 evt_array->evt[i].evt_cb = evt_cb;
404 evt_array->evt[i].user_data = user_data;
405 evt_array->reg_count++;
406 rc = 0;
407 break;
408 }
409 }
410 } else {
411 /* this is unreg case */
412 for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
413 if(evt_array->evt[i].user_data == user_data) {
414 evt_array->evt[i].evt_cb = NULL;
415 evt_array->evt[i].user_data = NULL;
416 evt_array->reg_count--;
417 rc = 0;
418 break;
419 }
420 }
421 }
422
423 pthread_mutex_unlock(&my_obj->cb_lock);
424 return rc;
425 }
426
427 /*===========================================================================
428 * FUNCTION : mm_camera_register_event_notify
429 *
430 * DESCRIPTION: registering a callback for event notify.
431 *
432 * PARAMETERS :
433 * @my_obj : ptr to a camera object
434 * @evt_cb : callback to be registered to handle event notify
435 * @user_data: user data ptr
436 *
437 * RETURN : int32_t type of status
438 * 0 -- success
439 * -1 -- failure
440 *==========================================================================*/
mm_camera_register_event_notify(mm_camera_obj_t * my_obj,mm_camera_event_notify_t evt_cb,void * user_data)441 int32_t mm_camera_register_event_notify(mm_camera_obj_t *my_obj,
442 mm_camera_event_notify_t evt_cb,
443 void * user_data)
444 {
445 int rc = -1;
446 rc = mm_camera_register_event_notify_internal(my_obj,
447 evt_cb,
448 user_data);
449 pthread_mutex_unlock(&my_obj->cam_lock);
450 return rc;
451 }
452
453 /*===========================================================================
454 * FUNCTION : mm_camera_qbuf
455 *
456 * DESCRIPTION: enqueue buffer back to kernel
457 *
458 * PARAMETERS :
459 * @my_obj : camera object
460 * @ch_id : channel handle
461 * @buf : buf ptr to be enqueued
462 *
463 * RETURN : int32_t type of status
464 * 0 -- success
465 * -1 -- failure
466 *==========================================================================*/
mm_camera_qbuf(mm_camera_obj_t * my_obj,uint32_t ch_id,mm_camera_buf_def_t * buf)467 int32_t mm_camera_qbuf(mm_camera_obj_t *my_obj,
468 uint32_t ch_id,
469 mm_camera_buf_def_t *buf)
470 {
471 int rc = -1;
472 mm_channel_t * ch_obj = NULL;
473 ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id);
474
475 pthread_mutex_unlock(&my_obj->cam_lock);
476
477 /* we always assume qbuf will be done before channel/stream is fully stopped
478 * because qbuf is done within dataCB context
479 * in order to avoid deadlock, we are not locking ch_lock for qbuf */
480 if (NULL != ch_obj) {
481 rc = mm_channel_qbuf(ch_obj, buf);
482 }
483
484 return rc;
485 }
486
487 /*===========================================================================
488 * FUNCTION : mm_camera_query_capability
489 *
490 * DESCRIPTION: query camera capability
491 *
492 * PARAMETERS :
493 * @my_obj: camera object
494 *
495 * RETURN : int32_t type of status
496 * 0 -- success
497 * -1 -- failure
498 *==========================================================================*/
mm_camera_query_capability(mm_camera_obj_t * my_obj)499 int32_t mm_camera_query_capability(mm_camera_obj_t *my_obj)
500 {
501 int32_t rc = 0;
502 struct v4l2_capability cap;
503
504 /* get camera capabilities */
505 memset(&cap, 0, sizeof(cap));
506 rc = ioctl(my_obj->ctrl_fd, VIDIOC_QUERYCAP, &cap);
507 if (rc != 0) {
508 CDBG_ERROR("%s: cannot get camera capabilities, rc = %d\n", __func__, rc);
509 }
510
511 pthread_mutex_unlock(&my_obj->cam_lock);
512 return rc;
513
514 }
515
516 /*===========================================================================
517 * FUNCTION : mm_camera_set_parms
518 *
519 * DESCRIPTION: set parameters per camera
520 *
521 * PARAMETERS :
522 * @my_obj : camera object
523 * @parms : ptr to a param struct to be set to server
524 *
525 * RETURN : int32_t type of status
526 * 0 -- success
527 * -1 -- failure
528 * NOTE : Assume the parms struct buf is already mapped to server via
529 * domain socket. Corresponding fields of parameters to be set
530 * are already filled in by upper layer caller.
531 *==========================================================================*/
mm_camera_set_parms(mm_camera_obj_t * my_obj,parm_buffer_t * parms)532 int32_t mm_camera_set_parms(mm_camera_obj_t *my_obj,
533 parm_buffer_t *parms)
534 {
535 int32_t rc = -1;
536 int32_t value = 0;
537 if (parms != NULL) {
538 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value);
539 }
540 pthread_mutex_unlock(&my_obj->cam_lock);
541 return rc;
542 }
543
544 /*===========================================================================
545 * FUNCTION : mm_camera_get_parms
546 *
547 * DESCRIPTION: get parameters per camera
548 *
549 * PARAMETERS :
550 * @my_obj : camera object
551 * @parms : ptr to a param struct to be get from server
552 *
553 * RETURN : int32_t type of status
554 * 0 -- success
555 * -1 -- failure
556 * NOTE : Assume the parms struct buf is already mapped to server via
557 * domain socket. Parameters to be get from server are already
558 * filled in by upper layer caller. After this call, corresponding
559 * fields of requested parameters will be filled in by server with
560 * detailed information.
561 *==========================================================================*/
mm_camera_get_parms(mm_camera_obj_t * my_obj,parm_buffer_t * parms)562 int32_t mm_camera_get_parms(mm_camera_obj_t *my_obj,
563 parm_buffer_t *parms)
564 {
565 int32_t rc = -1;
566 int32_t value = 0;
567 if (parms != NULL) {
568 rc = mm_camera_util_g_ctrl(my_obj->ctrl_fd, CAM_PRIV_PARM, &value);
569 }
570 pthread_mutex_unlock(&my_obj->cam_lock);
571 return rc;
572 }
573
574 /*===========================================================================
575 * FUNCTION : mm_camera_do_auto_focus
576 *
577 * DESCRIPTION: performing auto focus
578 *
579 * PARAMETERS :
580 * @camera_handle: camera handle
581 *
582 * RETURN : int32_t type of status
583 * 0 -- success
584 * -1 -- failure
585 * NOTE : if this call success, we will always assume there will
586 * be an auto_focus event following up.
587 *==========================================================================*/
mm_camera_do_auto_focus(mm_camera_obj_t * my_obj)588 int32_t mm_camera_do_auto_focus(mm_camera_obj_t *my_obj)
589 {
590 int32_t rc = -1;
591 int32_t value = 0;
592 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_DO_AUTO_FOCUS, &value);
593 pthread_mutex_unlock(&my_obj->cam_lock);
594 return rc;
595 }
596
597 /*===========================================================================
598 * FUNCTION : mm_camera_cancel_auto_focus
599 *
600 * DESCRIPTION: cancel auto focus
601 *
602 * PARAMETERS :
603 * @camera_handle: camera handle
604 *
605 * RETURN : int32_t type of status
606 * 0 -- success
607 * -1 -- failure
608 *==========================================================================*/
mm_camera_cancel_auto_focus(mm_camera_obj_t * my_obj)609 int32_t mm_camera_cancel_auto_focus(mm_camera_obj_t *my_obj)
610 {
611 int32_t rc = -1;
612 int32_t value = 0;
613 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_CANCEL_AUTO_FOCUS, &value);
614 pthread_mutex_unlock(&my_obj->cam_lock);
615 return rc;
616 }
617
618 /*===========================================================================
619 * FUNCTION : mm_camera_prepare_snapshot
620 *
621 * DESCRIPTION: prepare hardware for snapshot
622 *
623 * PARAMETERS :
624 * @my_obj : camera object
625 * @do_af_flag : flag indicating if AF is needed
626 *
627 * RETURN : int32_t type of status
628 * 0 -- success
629 * -1 -- failure
630 *==========================================================================*/
mm_camera_prepare_snapshot(mm_camera_obj_t * my_obj,int32_t do_af_flag)631 int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj,
632 int32_t do_af_flag)
633 {
634 int32_t rc = -1;
635 int32_t value = do_af_flag;
636 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, CAM_PRIV_PREPARE_SNAPSHOT, &value);
637 pthread_mutex_unlock(&my_obj->cam_lock);
638 return rc;
639 }
640
641 /*===========================================================================
642 * FUNCTION : mm_camera_start_zsl_snapshot
643 *
644 * DESCRIPTION: start zsl snapshot
645 *
646 * PARAMETERS :
647 * @my_obj : camera object
648 *
649 * RETURN : int32_t type of status
650 * 0 -- success
651 * -1 -- failure
652 *==========================================================================*/
mm_camera_start_zsl_snapshot(mm_camera_obj_t * my_obj)653 int32_t mm_camera_start_zsl_snapshot(mm_camera_obj_t *my_obj)
654 {
655 int32_t rc = -1;
656 int32_t value = 0;
657
658 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
659 CAM_PRIV_START_ZSL_SNAPSHOT, &value);
660
661 pthread_mutex_unlock(&my_obj->cam_lock);
662 return rc;
663 }
664
665 /*===========================================================================
666 * FUNCTION : mm_camera_stop_zsl_snapshot
667 *
668 * DESCRIPTION: stop zsl capture
669 *
670 * PARAMETERS :
671 * @my_obj : camera object
672 *
673 * RETURN : int32_t type of status
674 * 0 -- success
675 * -1 -- failure
676 *==========================================================================*/
mm_camera_stop_zsl_snapshot(mm_camera_obj_t * my_obj)677 int32_t mm_camera_stop_zsl_snapshot(mm_camera_obj_t *my_obj)
678 {
679 int32_t rc = -1;
680 int32_t value;
681 rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
682 CAM_PRIV_STOP_ZSL_SNAPSHOT, &value);
683 pthread_mutex_unlock(&my_obj->cam_lock);
684 return rc;
685 }
686
687 /*===========================================================================
688 * FUNCTION : mm_camera_add_channel
689 *
690 * DESCRIPTION: add a channel
691 *
692 * PARAMETERS :
693 * @my_obj : camera object
694 * @attr : bundle attribute of the channel if needed
695 * @channel_cb : callback function for bundle data notify
696 * @userdata : user data ptr
697 *
698 * RETURN : uint32_t type of channel handle
699 * 0 -- invalid channel handle, meaning the op failed
700 * >0 -- successfully added a channel with a valid handle
701 * NOTE : if no bundle data notify is needed, meaning each stream in the
702 * channel will have its own stream data notify callback, then
703 * attr, channel_cb, and userdata can be NULL. In this case,
704 * no matching logic will be performed in channel for the bundling.
705 *==========================================================================*/
mm_camera_add_channel(mm_camera_obj_t * my_obj,mm_camera_channel_attr_t * attr,mm_camera_buf_notify_t channel_cb,void * userdata)706 uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj,
707 mm_camera_channel_attr_t *attr,
708 mm_camera_buf_notify_t channel_cb,
709 void *userdata)
710 {
711 mm_channel_t *ch_obj = NULL;
712 uint8_t ch_idx = 0;
713 uint32_t ch_hdl = 0;
714
715 for(ch_idx = 0; ch_idx < MM_CAMERA_CHANNEL_MAX; ch_idx++) {
716 if (MM_CHANNEL_STATE_NOTUSED == my_obj->ch[ch_idx].state) {
717 ch_obj = &my_obj->ch[ch_idx];
718 break;
719 }
720 }
721
722 if (NULL != ch_obj) {
723 /* initialize channel obj */
724 memset(ch_obj, 0, sizeof(mm_channel_t));
725 ch_hdl = mm_camera_util_generate_handler(ch_idx);
726 ch_obj->my_hdl = ch_hdl;
727 ch_obj->state = MM_CHANNEL_STATE_STOPPED;
728 ch_obj->cam_obj = my_obj;
729 pthread_mutex_init(&ch_obj->ch_lock, NULL);
730 mm_channel_init(ch_obj, attr, channel_cb, userdata);
731 }
732
733 pthread_mutex_unlock(&my_obj->cam_lock);
734
735 return ch_hdl;
736 }
737
738 /*===========================================================================
739 * FUNCTION : mm_camera_del_channel
740 *
741 * DESCRIPTION: delete a channel by its handle
742 *
743 * PARAMETERS :
744 * @my_obj : camera object
745 * @ch_id : channel handle
746 *
747 * RETURN : int32_t type of status
748 * 0 -- success
749 * -1 -- failure
750 * NOTE : all streams in the channel should be stopped already before
751 * this channel can be deleted.
752 *==========================================================================*/
mm_camera_del_channel(mm_camera_obj_t * my_obj,uint32_t ch_id)753 int32_t mm_camera_del_channel(mm_camera_obj_t *my_obj,
754 uint32_t ch_id)
755 {
756 int32_t rc = -1;
757 mm_channel_t * ch_obj =
758 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
759
760 if (NULL != ch_obj) {
761 pthread_mutex_lock(&ch_obj->ch_lock);
762 pthread_mutex_unlock(&my_obj->cam_lock);
763
764 rc = mm_channel_fsm_fn(ch_obj,
765 MM_CHANNEL_EVT_DELETE,
766 NULL,
767 NULL);
768
769 pthread_mutex_destroy(&ch_obj->ch_lock);
770 memset(ch_obj, 0, sizeof(mm_channel_t));
771 } else {
772 pthread_mutex_unlock(&my_obj->cam_lock);
773 }
774 return rc;
775 }
776
777 /*===========================================================================
778 * FUNCTION : mm_camera_get_bundle_info
779 *
780 * DESCRIPTION: query bundle info of the channel
781 *
782 * PARAMETERS :
783 * @my_obj : camera object
784 * @ch_id : channel handle
785 * @bundle_info : bundle info to be filled in
786 *
787 * RETURN : int32_t type of status
788 * 0 -- success
789 * -1 -- failure
790 * NOTE : all streams in the channel should be stopped already before
791 * this channel can be deleted.
792 *==========================================================================*/
mm_camera_get_bundle_info(mm_camera_obj_t * my_obj,uint32_t ch_id,cam_bundle_config_t * bundle_info)793 int32_t mm_camera_get_bundle_info(mm_camera_obj_t *my_obj,
794 uint32_t ch_id,
795 cam_bundle_config_t *bundle_info)
796 {
797 int32_t rc = -1;
798 mm_channel_t * ch_obj =
799 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
800
801 if (NULL != ch_obj) {
802 pthread_mutex_lock(&ch_obj->ch_lock);
803 pthread_mutex_unlock(&my_obj->cam_lock);
804
805 rc = mm_channel_fsm_fn(ch_obj,
806 MM_CHANNEL_EVT_GET_BUNDLE_INFO,
807 (void *)bundle_info,
808 NULL);
809 } else {
810 pthread_mutex_unlock(&my_obj->cam_lock);
811 }
812 return rc;
813 }
814
815 /*===========================================================================
816 * FUNCTION : mm_camera_add_stream
817 *
818 * DESCRIPTION: add a stream into a channel
819 *
820 * PARAMETERS :
821 * @my_obj : camera object
822 * @ch_id : channel handle
823 *
824 * RETURN : uint32_t type of stream handle
825 * 0 -- invalid stream handle, meaning the op failed
826 * >0 -- successfully added a stream with a valid handle
827 *==========================================================================*/
mm_camera_add_stream(mm_camera_obj_t * my_obj,uint32_t ch_id)828 uint32_t mm_camera_add_stream(mm_camera_obj_t *my_obj,
829 uint32_t ch_id)
830 {
831 uint32_t s_hdl = 0;
832 mm_channel_t * ch_obj =
833 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
834
835 if (NULL != ch_obj) {
836 pthread_mutex_lock(&ch_obj->ch_lock);
837 pthread_mutex_unlock(&my_obj->cam_lock);
838
839 mm_channel_fsm_fn(ch_obj,
840 MM_CHANNEL_EVT_ADD_STREAM,
841 NULL,
842 (void*)&s_hdl);
843 } else {
844 pthread_mutex_unlock(&my_obj->cam_lock);
845 }
846
847 return s_hdl;
848 }
849
850 /*===========================================================================
851 * FUNCTION : mm_camera_del_stream
852 *
853 * DESCRIPTION: delete a stream by its handle
854 *
855 * PARAMETERS :
856 * @my_obj : camera object
857 * @ch_id : channel handle
858 * @stream_id : stream handle
859 *
860 * RETURN : int32_t type of status
861 * 0 -- success
862 * -1 -- failure
863 * NOTE : stream should be stopped already before it can be deleted.
864 *==========================================================================*/
mm_camera_del_stream(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id)865 int32_t mm_camera_del_stream(mm_camera_obj_t *my_obj,
866 uint32_t ch_id,
867 uint32_t stream_id)
868 {
869 int32_t rc = -1;
870 mm_channel_t * ch_obj =
871 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
872
873 if (NULL != ch_obj) {
874 pthread_mutex_lock(&ch_obj->ch_lock);
875 pthread_mutex_unlock(&my_obj->cam_lock);
876
877 rc = mm_channel_fsm_fn(ch_obj,
878 MM_CHANNEL_EVT_DEL_STREAM,
879 (void*)stream_id,
880 NULL);
881 } else {
882 pthread_mutex_unlock(&my_obj->cam_lock);
883 }
884
885 return rc;
886 }
887
888 /*===========================================================================
889 * FUNCTION : mm_camera_config_stream
890 *
891 * DESCRIPTION: configure a stream
892 *
893 * PARAMETERS :
894 * @my_obj : camera object
895 * @ch_id : channel handle
896 * @stream_id : stream handle
897 * @config : stream configuration
898 *
899 * RETURN : int32_t type of status
900 * 0 -- success
901 * -1 -- failure
902 *==========================================================================*/
mm_camera_config_stream(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id,mm_camera_stream_config_t * config)903 int32_t mm_camera_config_stream(mm_camera_obj_t *my_obj,
904 uint32_t ch_id,
905 uint32_t stream_id,
906 mm_camera_stream_config_t *config)
907 {
908 int32_t rc = -1;
909 mm_channel_t * ch_obj =
910 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
911 mm_evt_paylod_config_stream_t payload;
912
913 if (NULL != ch_obj) {
914 pthread_mutex_lock(&ch_obj->ch_lock);
915 pthread_mutex_unlock(&my_obj->cam_lock);
916
917 memset(&payload, 0, sizeof(mm_evt_paylod_config_stream_t));
918 payload.stream_id = stream_id;
919 payload.config = config;
920 rc = mm_channel_fsm_fn(ch_obj,
921 MM_CHANNEL_EVT_CONFIG_STREAM,
922 (void*)&payload,
923 NULL);
924 } else {
925 pthread_mutex_unlock(&my_obj->cam_lock);
926 }
927
928 return rc;
929 }
930
931 /*===========================================================================
932 * FUNCTION : mm_camera_start_channel
933 *
934 * DESCRIPTION: start a channel, which will start all streams in the channel
935 *
936 * PARAMETERS :
937 * @my_obj : camera object
938 * @ch_id : channel handle
939 *
940 * RETURN : int32_t type of status
941 * 0 -- success
942 * -1 -- failure
943 *==========================================================================*/
mm_camera_start_channel(mm_camera_obj_t * my_obj,uint32_t ch_id)944 int32_t mm_camera_start_channel(mm_camera_obj_t *my_obj,
945 uint32_t ch_id)
946 {
947 int32_t rc = -1;
948 mm_channel_t * ch_obj =
949 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
950
951 if (NULL != ch_obj) {
952 pthread_mutex_lock(&ch_obj->ch_lock);
953 pthread_mutex_unlock(&my_obj->cam_lock);
954
955 rc = mm_channel_fsm_fn(ch_obj,
956 MM_CHANNEL_EVT_START,
957 NULL,
958 NULL);
959 } else {
960 pthread_mutex_unlock(&my_obj->cam_lock);
961 }
962
963 return rc;
964 }
965
966 /*===========================================================================
967 * FUNCTION : mm_camera_stop_channel
968 *
969 * DESCRIPTION: stop a channel, which will stop all streams in the channel
970 *
971 * PARAMETERS :
972 * @my_obj : camera object
973 * @ch_id : channel handle
974 *
975 * RETURN : int32_t type of status
976 * 0 -- success
977 * -1 -- failure
978 *==========================================================================*/
mm_camera_stop_channel(mm_camera_obj_t * my_obj,uint32_t ch_id)979 int32_t mm_camera_stop_channel(mm_camera_obj_t *my_obj,
980 uint32_t ch_id)
981 {
982 int32_t rc = 0;
983 mm_channel_t * ch_obj =
984 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
985
986 if (NULL != ch_obj) {
987 pthread_mutex_lock(&ch_obj->ch_lock);
988 pthread_mutex_unlock(&my_obj->cam_lock);
989
990 rc = mm_channel_fsm_fn(ch_obj,
991 MM_CHANNEL_EVT_STOP,
992 NULL,
993 NULL);
994 } else {
995 pthread_mutex_unlock(&my_obj->cam_lock);
996 }
997 return rc;
998 }
999
1000 /*===========================================================================
1001 * FUNCTION : mm_camera_request_super_buf
1002 *
1003 * DESCRIPTION: for burst mode in bundle, reuqest certain amount of matched
1004 * frames from superbuf queue
1005 *
1006 * PARAMETERS :
1007 * @my_obj : camera object
1008 * @ch_id : channel handle
1009 * @num_buf_requested : number of matched frames needed
1010 *
1011 * RETURN : int32_t type of status
1012 * 0 -- success
1013 * -1 -- failure
1014 *==========================================================================*/
mm_camera_request_super_buf(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t num_buf_requested)1015 int32_t mm_camera_request_super_buf(mm_camera_obj_t *my_obj,
1016 uint32_t ch_id,
1017 uint32_t num_buf_requested)
1018 {
1019 int32_t rc = -1;
1020 mm_channel_t * ch_obj =
1021 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1022
1023 if (NULL != ch_obj) {
1024 pthread_mutex_lock(&ch_obj->ch_lock);
1025 pthread_mutex_unlock(&my_obj->cam_lock);
1026
1027 rc = mm_channel_fsm_fn(ch_obj,
1028 MM_CHANNEL_EVT_REQUEST_SUPER_BUF,
1029 (void*)num_buf_requested,
1030 NULL);
1031 } else {
1032 pthread_mutex_unlock(&my_obj->cam_lock);
1033 }
1034
1035 return rc;
1036 }
1037
1038 /*===========================================================================
1039 * FUNCTION : mm_camera_cancel_super_buf_request
1040 *
1041 * DESCRIPTION: for burst mode in bundle, cancel the reuqest for certain amount
1042 * of matched frames from superbuf queue
1043 *
1044 * PARAMETERS :
1045 * @my_obj : camera object
1046 * @ch_id : channel handle
1047 *
1048 * RETURN : int32_t type of status
1049 * 0 -- success
1050 * -1 -- failure
1051 *==========================================================================*/
mm_camera_cancel_super_buf_request(mm_camera_obj_t * my_obj,uint32_t ch_id)1052 int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj, uint32_t ch_id)
1053 {
1054 int32_t rc = -1;
1055 mm_channel_t * ch_obj =
1056 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1057
1058 if (NULL != ch_obj) {
1059 pthread_mutex_lock(&ch_obj->ch_lock);
1060 pthread_mutex_unlock(&my_obj->cam_lock);
1061
1062 rc = mm_channel_fsm_fn(ch_obj,
1063 MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF,
1064 NULL,
1065 NULL);
1066 } else {
1067 pthread_mutex_unlock(&my_obj->cam_lock);
1068 }
1069
1070 return rc;
1071 }
1072
1073 /*===========================================================================
1074 * FUNCTION : mm_camera_flush_super_buf_queue
1075 *
1076 * DESCRIPTION: flush out all frames in the superbuf queue
1077 *
1078 * PARAMETERS :
1079 * @my_obj : camera object
1080 * @ch_id : channel handle
1081 *
1082 * RETURN : int32_t type of status
1083 * 0 -- success
1084 * -1 -- failure
1085 *==========================================================================*/
mm_camera_flush_super_buf_queue(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t frame_idx)1086 int32_t mm_camera_flush_super_buf_queue(mm_camera_obj_t *my_obj, uint32_t ch_id,
1087 uint32_t frame_idx)
1088 {
1089 int32_t rc = -1;
1090 mm_channel_t * ch_obj =
1091 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1092
1093 if (NULL != ch_obj) {
1094 pthread_mutex_lock(&ch_obj->ch_lock);
1095 pthread_mutex_unlock(&my_obj->cam_lock);
1096
1097 rc = mm_channel_fsm_fn(ch_obj,
1098 MM_CHANNEL_EVT_FLUSH_SUPER_BUF_QUEUE,
1099 (void *)frame_idx,
1100 NULL);
1101 } else {
1102 pthread_mutex_unlock(&my_obj->cam_lock);
1103 }
1104
1105 return rc;
1106 }
1107
1108 /*===========================================================================
1109 * FUNCTION : mm_camera_config_channel_notify
1110 *
1111 * DESCRIPTION: configures the channel notification mode
1112 *
1113 * PARAMETERS :
1114 * @my_obj : camera object
1115 * @ch_id : channel handle
1116 * @notify_mode : notification mode
1117 *
1118 * RETURN : int32_t type of status
1119 * 0 -- success
1120 * -1 -- failure
1121 *==========================================================================*/
mm_camera_config_channel_notify(mm_camera_obj_t * my_obj,uint32_t ch_id,mm_camera_super_buf_notify_mode_t notify_mode)1122 int32_t mm_camera_config_channel_notify(mm_camera_obj_t *my_obj,
1123 uint32_t ch_id,
1124 mm_camera_super_buf_notify_mode_t notify_mode)
1125 {
1126 int32_t rc = -1;
1127 mm_channel_t * ch_obj =
1128 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1129
1130 if (NULL != ch_obj) {
1131 pthread_mutex_lock(&ch_obj->ch_lock);
1132 pthread_mutex_unlock(&my_obj->cam_lock);
1133
1134 rc = mm_channel_fsm_fn(ch_obj,
1135 MM_CHANNEL_EVT_CONFIG_NOTIFY_MODE,
1136 (void *)notify_mode,
1137 NULL);
1138 } else {
1139 pthread_mutex_unlock(&my_obj->cam_lock);
1140 }
1141
1142 return rc;
1143 }
1144
1145 /*===========================================================================
1146 * FUNCTION : mm_camera_set_stream_parms
1147 *
1148 * DESCRIPTION: set parameters per stream
1149 *
1150 * PARAMETERS :
1151 * @my_obj : camera object
1152 * @ch_id : channel handle
1153 * @s_id : stream handle
1154 * @parms : ptr to a param struct to be set to server
1155 *
1156 * RETURN : int32_t type of status
1157 * 0 -- success
1158 * -1 -- failure
1159 * NOTE : Assume the parms struct buf is already mapped to server via
1160 * domain socket. Corresponding fields of parameters to be set
1161 * are already filled in by upper layer caller.
1162 *==========================================================================*/
mm_camera_set_stream_parms(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t s_id,cam_stream_parm_buffer_t * parms)1163 int32_t mm_camera_set_stream_parms(mm_camera_obj_t *my_obj,
1164 uint32_t ch_id,
1165 uint32_t s_id,
1166 cam_stream_parm_buffer_t *parms)
1167 {
1168 int32_t rc = -1;
1169 mm_evt_paylod_set_get_stream_parms_t payload;
1170 mm_channel_t * ch_obj =
1171 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1172
1173 if (NULL != ch_obj) {
1174 pthread_mutex_lock(&ch_obj->ch_lock);
1175 pthread_mutex_unlock(&my_obj->cam_lock);
1176
1177 memset(&payload, 0, sizeof(payload));
1178 payload.stream_id = s_id;
1179 payload.parms = parms;
1180
1181 rc = mm_channel_fsm_fn(ch_obj,
1182 MM_CHANNEL_EVT_SET_STREAM_PARM,
1183 (void *)&payload,
1184 NULL);
1185 } else {
1186 pthread_mutex_unlock(&my_obj->cam_lock);
1187 }
1188
1189 return rc;
1190 }
1191
1192 /*===========================================================================
1193 * FUNCTION : mm_camera_get_stream_parms
1194 *
1195 * DESCRIPTION: get parameters per stream
1196 *
1197 * PARAMETERS :
1198 * @my_obj : camera object
1199 * @ch_id : channel handle
1200 * @s_id : stream handle
1201 * @parms : ptr to a param struct to be get from server
1202 *
1203 * RETURN : int32_t type of status
1204 * 0 -- success
1205 * -1 -- failure
1206 * NOTE : Assume the parms struct buf is already mapped to server via
1207 * domain socket. Parameters to be get from server are already
1208 * filled in by upper layer caller. After this call, corresponding
1209 * fields of requested parameters will be filled in by server with
1210 * detailed information.
1211 *==========================================================================*/
mm_camera_get_stream_parms(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t s_id,cam_stream_parm_buffer_t * parms)1212 int32_t mm_camera_get_stream_parms(mm_camera_obj_t *my_obj,
1213 uint32_t ch_id,
1214 uint32_t s_id,
1215 cam_stream_parm_buffer_t *parms)
1216 {
1217 int32_t rc = -1;
1218 mm_evt_paylod_set_get_stream_parms_t payload;
1219 mm_channel_t * ch_obj =
1220 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1221
1222 if (NULL != ch_obj) {
1223 pthread_mutex_lock(&ch_obj->ch_lock);
1224 pthread_mutex_unlock(&my_obj->cam_lock);
1225
1226 memset(&payload, 0, sizeof(payload));
1227 payload.stream_id = s_id;
1228 payload.parms = parms;
1229
1230 rc = mm_channel_fsm_fn(ch_obj,
1231 MM_CHANNEL_EVT_GET_STREAM_PARM,
1232 (void *)&payload,
1233 NULL);
1234 } else {
1235 pthread_mutex_unlock(&my_obj->cam_lock);
1236 }
1237
1238 return rc;
1239 }
1240
1241 /*===========================================================================
1242 * FUNCTION : mm_camera_do_stream_action
1243 *
1244 * DESCRIPTION: request server to perform stream based action. Maybe removed later
1245 * if the functionality is included in mm_camera_set_parms
1246 *
1247 * PARAMETERS :
1248 * @my_obj : camera object
1249 * @ch_id : channel handle
1250 * @s_id : stream handle
1251 * @actions : ptr to an action struct buf to be performed by server
1252 *
1253 * RETURN : int32_t type of status
1254 * 0 -- success
1255 * -1 -- failure
1256 * NOTE : Assume the action struct buf is already mapped to server via
1257 * domain socket. Actions to be performed by server are already
1258 * filled in by upper layer caller.
1259 *==========================================================================*/
mm_camera_do_stream_action(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id,void * actions)1260 int32_t mm_camera_do_stream_action(mm_camera_obj_t *my_obj,
1261 uint32_t ch_id,
1262 uint32_t stream_id,
1263 void *actions)
1264 {
1265 int32_t rc = -1;
1266 mm_evt_paylod_do_stream_action_t payload;
1267 mm_channel_t * ch_obj =
1268 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1269
1270 if (NULL != ch_obj) {
1271 pthread_mutex_lock(&ch_obj->ch_lock);
1272 pthread_mutex_unlock(&my_obj->cam_lock);
1273
1274 memset(&payload, 0, sizeof(payload));
1275 payload.stream_id = stream_id;
1276 payload.actions = actions;
1277
1278 rc = mm_channel_fsm_fn(ch_obj,
1279 MM_CHANNEL_EVT_DO_STREAM_ACTION,
1280 (void*)&payload,
1281 NULL);
1282 } else {
1283 pthread_mutex_unlock(&my_obj->cam_lock);
1284 }
1285
1286 return rc;
1287 }
1288
1289 /*===========================================================================
1290 * FUNCTION : mm_camera_map_stream_buf
1291 *
1292 * DESCRIPTION: mapping stream buffer via domain socket to server
1293 *
1294 * PARAMETERS :
1295 * @my_obj : camera object
1296 * @ch_id : channel handle
1297 * @s_id : stream handle
1298 * @buf_type : type of buffer to be mapped. could be following values:
1299 * CAM_MAPPING_BUF_TYPE_STREAM_BUF
1300 * CAM_MAPPING_BUF_TYPE_STREAM_INFO
1301 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1302 * @buf_idx : index of buffer within the stream buffers, only valid if
1303 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1304 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1305 * @plane_idx : plane index. If all planes share the same fd,
1306 * plane_idx = -1; otherwise, plean_idx is the
1307 * index to plane (0..num_of_planes)
1308 * @fd : file descriptor of the buffer
1309 * @size : size of the buffer
1310 *
1311 * RETURN : int32_t type of status
1312 * 0 -- success
1313 * -1 -- failure
1314 *==========================================================================*/
mm_camera_map_stream_buf(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id,uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx,int fd,uint32_t size)1315 int32_t mm_camera_map_stream_buf(mm_camera_obj_t *my_obj,
1316 uint32_t ch_id,
1317 uint32_t stream_id,
1318 uint8_t buf_type,
1319 uint32_t buf_idx,
1320 int32_t plane_idx,
1321 int fd,
1322 uint32_t size)
1323 {
1324 int32_t rc = -1;
1325 mm_evt_paylod_map_stream_buf_t payload;
1326 mm_channel_t * ch_obj =
1327 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1328
1329 if (NULL != ch_obj) {
1330 pthread_mutex_lock(&ch_obj->ch_lock);
1331 pthread_mutex_unlock(&my_obj->cam_lock);
1332
1333 memset(&payload, 0, sizeof(payload));
1334 payload.stream_id = stream_id;
1335 payload.buf_type = buf_type;
1336 payload.buf_idx = buf_idx;
1337 payload.plane_idx = plane_idx;
1338 payload.fd = fd;
1339 payload.size = size;
1340 rc = mm_channel_fsm_fn(ch_obj,
1341 MM_CHANNEL_EVT_MAP_STREAM_BUF,
1342 (void*)&payload,
1343 NULL);
1344 } else {
1345 pthread_mutex_unlock(&my_obj->cam_lock);
1346 }
1347
1348 return rc;
1349 }
1350
1351 /*===========================================================================
1352 * FUNCTION : mm_camera_unmap_stream_buf
1353 *
1354 * DESCRIPTION: unmapping stream buffer via domain socket to server
1355 *
1356 * PARAMETERS :
1357 * @my_obj : camera object
1358 * @ch_id : channel handle
1359 * @s_id : stream handle
1360 * @buf_type : type of buffer to be mapped. could be following values:
1361 * CAM_MAPPING_BUF_TYPE_STREAM_BUF
1362 * CAM_MAPPING_BUF_TYPE_STREAM_INFO
1363 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1364 * @buf_idx : index of buffer within the stream buffers, only valid if
1365 * buf_type is CAM_MAPPING_BUF_TYPE_STREAM_BUF or
1366 * CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF
1367 * @plane_idx : plane index. If all planes share the same fd,
1368 * plane_idx = -1; otherwise, plean_idx is the
1369 * index to plane (0..num_of_planes)
1370 *
1371 * RETURN : int32_t type of status
1372 * 0 -- success
1373 * -1 -- failure
1374 *==========================================================================*/
mm_camera_unmap_stream_buf(mm_camera_obj_t * my_obj,uint32_t ch_id,uint32_t stream_id,uint8_t buf_type,uint32_t buf_idx,int32_t plane_idx)1375 int32_t mm_camera_unmap_stream_buf(mm_camera_obj_t *my_obj,
1376 uint32_t ch_id,
1377 uint32_t stream_id,
1378 uint8_t buf_type,
1379 uint32_t buf_idx,
1380 int32_t plane_idx)
1381 {
1382 int32_t rc = -1;
1383 mm_evt_paylod_unmap_stream_buf_t payload;
1384 mm_channel_t * ch_obj =
1385 mm_camera_util_get_channel_by_handler(my_obj, ch_id);
1386
1387 if (NULL != ch_obj) {
1388 pthread_mutex_lock(&ch_obj->ch_lock);
1389 pthread_mutex_unlock(&my_obj->cam_lock);
1390
1391 memset(&payload, 0, sizeof(payload));
1392 payload.stream_id = stream_id;
1393 payload.buf_type = buf_type;
1394 payload.buf_idx = buf_idx;
1395 payload.plane_idx = plane_idx;
1396 rc = mm_channel_fsm_fn(ch_obj,
1397 MM_CHANNEL_EVT_UNMAP_STREAM_BUF,
1398 (void*)&payload,
1399 NULL);
1400 } else {
1401 pthread_mutex_unlock(&my_obj->cam_lock);
1402 }
1403
1404 return rc;
1405 }
1406
1407 /*===========================================================================
1408 * FUNCTION : mm_camera_evt_sub
1409 *
1410 * DESCRIPTION: subscribe/unsubscribe event notify from kernel
1411 *
1412 * PARAMETERS :
1413 * @my_obj : camera object
1414 * @reg_flag : 1 -- subscribe ; 0 -- unsubscribe
1415 *
1416 * RETURN : int32_t type of status
1417 * 0 -- success
1418 * -1 -- failure
1419 *==========================================================================*/
mm_camera_evt_sub(mm_camera_obj_t * my_obj,uint8_t reg_flag)1420 int32_t mm_camera_evt_sub(mm_camera_obj_t * my_obj,
1421 uint8_t reg_flag)
1422 {
1423 int32_t rc = 0;
1424 struct v4l2_event_subscription sub;
1425
1426 memset(&sub, 0, sizeof(sub));
1427 sub.type = MSM_CAMERA_V4L2_EVENT_TYPE;
1428 sub.id = MSM_CAMERA_MSM_NOTIFY;
1429 if(FALSE == reg_flag) {
1430 /* unsubscribe */
1431 rc = ioctl(my_obj->ctrl_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
1432 if (rc < 0) {
1433 CDBG_ERROR("%s: unsubscribe event rc = %d", __func__, rc);
1434 return rc;
1435 }
1436 /* remove evt fd from the polling thraed when unreg the last event */
1437 rc = mm_camera_poll_thread_del_poll_fd(&my_obj->evt_poll_thread,
1438 my_obj->my_hdl,
1439 mm_camera_sync_call);
1440 } else {
1441 rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
1442 if (rc < 0) {
1443 CDBG_ERROR("%s: subscribe event rc = %d", __func__, rc);
1444 return rc;
1445 }
1446 /* add evt fd to polling thread when subscribe the first event */
1447 rc = mm_camera_poll_thread_add_poll_fd(&my_obj->evt_poll_thread,
1448 my_obj->my_hdl,
1449 my_obj->ctrl_fd,
1450 mm_camera_event_notify,
1451 (void*)my_obj,
1452 mm_camera_sync_call);
1453 }
1454 return rc;
1455 }
1456
1457 /*===========================================================================
1458 * FUNCTION : mm_camera_util_wait_for_event
1459 *
1460 * DESCRIPTION: utility function to wait for certain events
1461 *
1462 * PARAMETERS :
1463 * @my_obj : camera object
1464 * @evt_mask : mask for events to be waited. Any of event in the mask would
1465 * trigger the wait to end
1466 * @status : status of the event
1467 *
1468 * RETURN : none
1469 *==========================================================================*/
mm_camera_util_wait_for_event(mm_camera_obj_t * my_obj,uint32_t evt_mask,int32_t * status)1470 void mm_camera_util_wait_for_event(mm_camera_obj_t *my_obj,
1471 uint32_t evt_mask,
1472 int32_t *status)
1473 {
1474 pthread_mutex_lock(&my_obj->evt_lock);
1475 while (!(my_obj->evt_rcvd.server_event_type & evt_mask)) {
1476 pthread_cond_wait(&my_obj->evt_cond, &my_obj->evt_lock);
1477 }
1478 *status = my_obj->evt_rcvd.status;
1479 /* reset local storage for recieved event for next event */
1480 memset(&my_obj->evt_rcvd, 0, sizeof(mm_camera_event_t));
1481 pthread_mutex_unlock(&my_obj->evt_lock);
1482 }
1483
1484 /*===========================================================================
1485 * FUNCTION : mm_camera_util_sendmsg
1486 *
1487 * DESCRIPTION: utility function to send msg via domain socket
1488 *
1489 * PARAMETERS :
1490 * @my_obj : camera object
1491 * @msg : message to be sent
1492 * @buf_size : size of the message to be sent
1493 * @sendfd : >0 if any file descriptor need to be passed across process
1494 *
1495 * RETURN : int32_t type of status
1496 * 0 -- success
1497 * -1 -- failure
1498 *==========================================================================*/
mm_camera_util_sendmsg(mm_camera_obj_t * my_obj,void * msg,uint32_t buf_size,int sendfd)1499 int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj,
1500 void *msg,
1501 uint32_t buf_size,
1502 int sendfd)
1503 {
1504 int32_t rc = -1;
1505 int32_t status;
1506
1507 /* need to lock msg_lock, since sendmsg until reposonse back is deemed as one operation*/
1508 pthread_mutex_lock(&my_obj->msg_lock);
1509 if(mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd) > 0) {
1510 /* wait for event that mapping/unmapping is done */
1511 mm_camera_util_wait_for_event(my_obj, CAM_EVENT_TYPE_MAP_UNMAP_DONE, &status);
1512 if (MSM_CAMERA_STATUS_SUCCESS == status) {
1513 rc = 0;
1514 }
1515 }
1516 pthread_mutex_unlock(&my_obj->msg_lock);
1517 return rc;
1518 }
1519
1520 /*===========================================================================
1521 * FUNCTION : mm_camera_map_buf
1522 *
1523 * DESCRIPTION: mapping camera buffer via domain socket to server
1524 *
1525 * PARAMETERS :
1526 * @my_obj : camera object
1527 * @buf_type : type of buffer to be mapped. could be following values:
1528 * CAM_MAPPING_BUF_TYPE_CAPABILITY
1529 * CAM_MAPPING_BUF_TYPE_SETPARM_BUF
1530 * CAM_MAPPING_BUF_TYPE_GETPARM_BUF
1531 * @fd : file descriptor of the buffer
1532 * @size : size of the buffer
1533 *
1534 * RETURN : int32_t type of status
1535 * 0 -- success
1536 * -1 -- failure
1537 *==========================================================================*/
mm_camera_map_buf(mm_camera_obj_t * my_obj,uint8_t buf_type,int fd,uint32_t size)1538 int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,
1539 uint8_t buf_type,
1540 int fd,
1541 uint32_t size)
1542 {
1543 int32_t rc = 0;
1544 cam_sock_packet_t packet;
1545 memset(&packet, 0, sizeof(cam_sock_packet_t));
1546 packet.msg_type = CAM_MAPPING_TYPE_FD_MAPPING;
1547 packet.payload.buf_map.type = buf_type;
1548 packet.payload.buf_map.fd = fd;
1549 packet.payload.buf_map.size = size;
1550 rc = mm_camera_util_sendmsg(my_obj,
1551 &packet,
1552 sizeof(cam_sock_packet_t),
1553 fd);
1554 pthread_mutex_unlock(&my_obj->cam_lock);
1555 return rc;
1556 }
1557
1558 /*===========================================================================
1559 * FUNCTION : mm_camera_unmap_buf
1560 *
1561 * DESCRIPTION: unmapping camera buffer via domain socket to server
1562 *
1563 * PARAMETERS :
1564 * @my_obj : camera object
1565 * @buf_type : type of buffer to be mapped. could be following values:
1566 * CAM_MAPPING_BUF_TYPE_CAPABILITY
1567 * CAM_MAPPING_BUF_TYPE_SETPARM_BUF
1568 * CAM_MAPPING_BUF_TYPE_GETPARM_BUF
1569 *
1570 * RETURN : int32_t type of status
1571 * 0 -- success
1572 * -1 -- failure
1573 *==========================================================================*/
mm_camera_unmap_buf(mm_camera_obj_t * my_obj,uint8_t buf_type)1574 int32_t mm_camera_unmap_buf(mm_camera_obj_t *my_obj,
1575 uint8_t buf_type)
1576 {
1577 int32_t rc = 0;
1578 cam_sock_packet_t packet;
1579 memset(&packet, 0, sizeof(cam_sock_packet_t));
1580 packet.msg_type = CAM_MAPPING_TYPE_FD_UNMAPPING;
1581 packet.payload.buf_unmap.type = buf_type;
1582 rc = mm_camera_util_sendmsg(my_obj,
1583 &packet,
1584 sizeof(cam_sock_packet_t),
1585 0);
1586 pthread_mutex_unlock(&my_obj->cam_lock);
1587 return rc;
1588 }
1589
1590 /*===========================================================================
1591 * FUNCTION : mm_camera_util_s_ctrl
1592 *
1593 * DESCRIPTION: utility function to send v4l2 ioctl for s_ctrl
1594 *
1595 * PARAMETERS :
1596 * @fd : file descritpor for sending ioctl
1597 * @id : control id
1598 * @value : value of the ioctl to be sent
1599 *
1600 * RETURN : int32_t type of status
1601 * 0 -- success
1602 * -1 -- failure
1603 *==========================================================================*/
mm_camera_util_s_ctrl(int32_t fd,uint32_t id,int32_t * value)1604 int32_t mm_camera_util_s_ctrl(int32_t fd, uint32_t id, int32_t *value)
1605 {
1606 int rc = 0;
1607 struct v4l2_control control;
1608
1609 memset(&control, 0, sizeof(control));
1610 control.id = id;
1611 if (value != NULL) {
1612 control.value = *value;
1613 }
1614 rc = ioctl(fd, VIDIOC_S_CTRL, &control);
1615
1616 CDBG("%s: fd=%d, S_CTRL, id=0x%x, value = 0x%x, rc = %d\n",
1617 __func__, fd, id, (uint32_t)value, rc);
1618 if (value != NULL) {
1619 *value = control.value;
1620 }
1621 return (rc >= 0)? 0 : -1;
1622 }
1623
1624 /*===========================================================================
1625 * FUNCTION : mm_camera_util_g_ctrl
1626 *
1627 * DESCRIPTION: utility function to send v4l2 ioctl for g_ctrl
1628 *
1629 * PARAMETERS :
1630 * @fd : file descritpor for sending ioctl
1631 * @id : control id
1632 * @value : value of the ioctl to be sent
1633 *
1634 * RETURN : int32_t type of status
1635 * 0 -- success
1636 * -1 -- failure
1637 *==========================================================================*/
mm_camera_util_g_ctrl(int32_t fd,uint32_t id,int32_t * value)1638 int32_t mm_camera_util_g_ctrl( int32_t fd, uint32_t id, int32_t *value)
1639 {
1640 int rc = 0;
1641 struct v4l2_control control;
1642
1643 memset(&control, 0, sizeof(control));
1644 control.id = id;
1645 if (value != NULL) {
1646 control.value = *value;
1647 }
1648 rc = ioctl(fd, VIDIOC_G_CTRL, &control);
1649 CDBG("%s: fd=%d, G_CTRL, id=0x%x, rc = %d\n", __func__, fd, id, rc);
1650 if (value != NULL) {
1651 *value = control.value;
1652 }
1653 return (rc >= 0)? 0 : -1;
1654 }
1655