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