1/*
2Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7    * Redistributions of source code must retain the above copyright
8      notice, this list of conditions and the following disclaimer.
9    * Redistributions in binary form must reproduce the above
10      copyright notice, this list of conditions and the following
11      disclaimer in the documentation and/or other materials provided
12      with the distribution.
13    * Neither the name of The Linux Foundation nor the names of its
14      contributors may be used to endorse or promote products derived
15      from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#include <pthread.h>
31#include "mm_camera_dbg.h"
32#include <errno.h>
33#include <stdbool.h>
34#include <sys/ioctl.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <fcntl.h>
38#include <poll.h>
39#include <dlfcn.h>
40#include "mm_qcamera_main_menu.h"
41#include "mm_qcamera_app.h"
42
43
44mm_camera_app_t my_cam_app;
45
46static pthread_mutex_t app_mutex;
47static int thread_status = 0;
48static pthread_cond_t app_cond_v;
49
50#define MM_QCAMERA_APP_WAIT_TIME 1000000000
51
52int mm_camera_app_timedwait()
53{
54    int rc = 0;
55    pthread_mutex_lock(&app_mutex);
56    if(false == thread_status) {
57        struct timespec tw;
58        memset(&tw, 0, sizeof tw);
59        tw.tv_sec = 0;
60        tw.tv_nsec = time(0) + MM_QCAMERA_APP_WAIT_TIME;
61
62        //pthread_cond_wait(&app_cond_v, &app_mutex);
63        rc = pthread_cond_timedwait(&app_cond_v, &app_mutex,&tw);
64        thread_status = false;
65    }
66    pthread_mutex_unlock(&app_mutex);
67    return rc;
68}
69
70int mm_camera_app_wait()
71{
72    int rc = 0;
73    pthread_mutex_lock(&app_mutex);
74    if(false == thread_status){
75        pthread_cond_wait(&app_cond_v, &app_mutex);
76        thread_status = false;
77    }
78    pthread_mutex_unlock(&app_mutex);
79    return rc;
80}
81
82void mm_camera_app_done()
83{
84  pthread_mutex_lock(&app_mutex);
85  thread_status = true;
86  pthread_cond_signal(&app_cond_v);
87  pthread_mutex_unlock(&app_mutex);
88}
89
90
91mm_camera_app_obj_t *mm_app_get_cam_obj(int8_t cam_id)
92{
93    mm_camera_app_obj_t *temp = my_cam_app.obj[cam_id];
94    return temp;
95}
96
97void mm_app_user_ptr(int use_user_ptr)
98{
99    my_cam_app.use_user_ptr = use_user_ptr;
100}
101
102void mm_app_set_dim_def(cam_ctrl_dimension_t *dim)
103{
104    dim->display_width = WVGA_WIDTH;
105    dim->display_height = WVGA_HEIGHT;
106    input_display.user_input_display_width = dim->display_width;
107    input_display.user_input_display_height = dim->display_height;
108    dim->video_width = WVGA_WIDTH;
109    dim->video_width = CEILING32(dim->video_width);
110    dim->video_height = WVGA_HEIGHT;
111    dim->orig_video_width = dim->video_width;
112    dim->orig_video_height = dim->video_height;
113    dim->picture_width = MP1_WIDTH;
114    dim->picture_height = MP1_HEIGHT;
115    dim->orig_picture_dx = dim->picture_width;
116    dim->orig_picture_dy = dim->picture_height;
117    dim->ui_thumbnail_height = QVGA_HEIGHT;
118    dim->ui_thumbnail_width = QVGA_WIDTH;
119    dim->thumbnail_height = dim->ui_thumbnail_height;
120    dim->thumbnail_width = dim->ui_thumbnail_width;
121    dim->orig_picture_width = dim->picture_width;
122    dim->orig_picture_height = dim->picture_height;
123    dim->orig_thumb_width = dim->thumbnail_width;
124    dim->orig_thumb_height = dim->thumbnail_height;
125    dim->raw_picture_height = MP1_HEIGHT;
126    dim->raw_picture_width = MP1_WIDTH;
127    dim->hjr_xtra_buff_for_bayer_filtering;
128    dim->prev_format = CAMERA_YUV_420_NV21;
129    dim->enc_format = CAMERA_YUV_420_NV12;
130    dim->thumb_format = CAMERA_YUV_420_NV21;
131    dim->main_img_format = CAMERA_YUV_420_NV21;
132    dim->prev_padding_format = CAMERA_PAD_TO_4K;
133    dim->display_luma_width = dim->display_width;
134    dim->display_luma_height = dim->display_height;
135    dim->display_chroma_width = dim->display_width;
136    dim->display_chroma_height = dim->display_height;
137    dim->video_luma_width = dim->orig_video_width;
138    dim->video_luma_height = dim->orig_video_height;
139    dim->video_chroma_width = dim->orig_video_width;
140    dim->video_chroma_height = dim->orig_video_height;
141    dim->thumbnail_luma_width = dim->thumbnail_width;
142    dim->thumbnail_luma_height = dim->thumbnail_height;
143    dim->thumbnail_chroma_width = dim->thumbnail_width;
144    dim->thumbnail_chroma_height = dim->thumbnail_height;
145    dim->main_img_luma_width = dim->picture_width;
146    dim->main_img_luma_height = dim->picture_height;
147    dim->main_img_chroma_width = dim->picture_width;
148    dim->main_img_chroma_height = dim->picture_height;
149}
150
151int mm_app_load_hal()
152{
153  memset(&my_cam_app, 0, sizeof(my_cam_app));
154  memset(&my_cam_app.hal_lib, 0, sizeof(hal_interface_lib_t));
155#if defined(_MSM7630_)
156   my_cam_app.hal_lib.ptr = dlopen("/usr/lib/hw/camera.msm7630.so", RTLD_LAZY);
157#elif defined(_MSM7627A_)
158   my_cam_app.hal_lib.ptr = dlopen("/usr/lib/hw/camera.msm7627A.so", RTLD_LAZY);
159#else
160  //my_cam_app.hal_lib.ptr = dlopen("hw/camera.msm8960.so", RTLD_NOW);
161   my_cam_app.hal_lib.ptr = dlopen("libmmcamera_interface_badger.so", RTLD_NOW);
162#endif
163  if (!my_cam_app.hal_lib.ptr) {
164    CDBG_ERROR("%s Error opening HAL library %s\n", __func__, dlerror());
165    return -1;
166  }
167  *(void **)&(my_cam_app.hal_lib.mm_camera_query) =
168        dlsym(my_cam_app.hal_lib.ptr,
169              "camera_query");
170  *(void **)&(my_cam_app.hal_lib.mm_camera_open) =
171        dlsym(my_cam_app.hal_lib.ptr,
172              "camera_open");
173  return 0;
174}
175
176int mm_app_init()
177{
178    int rc = MM_CAMERA_OK;
179    CDBG("%s:BEGIN\n", __func__);
180    my_cam_app.cam_info =  (mm_camera_info_t *)my_cam_app.hal_lib.mm_camera_query(&my_cam_app.num_cameras);
181    if(my_cam_app.cam_info == NULL) {
182        CDBG_ERROR("%s: Failed to query camera\n", __func__);
183        rc = -1;
184    }
185    CDBG("%s:END, num_cameras = %d\n", __func__, my_cam_app.num_cameras);
186    return rc;
187}
188
189static void notify_evt_cb(uint32_t camera_handle,
190                         mm_camera_event_t *evt,void *user_data)
191{
192    CDBG("%s:E evt = %d",__func__,evt->event_type);
193
194    switch(evt->event_type)
195    {
196        case MM_CAMERA_EVT_TYPE_CH:
197        break;
198        case MM_CAMERA_EVT_TYPE_CTRL:
199            break;
200        case MM_CAMERA_EVT_TYPE_STATS:
201            break;
202        case MM_CAMERA_EVT_TYPE_INFO:
203        break;
204        default:
205            break;
206    }
207    CDBG("%s:X",__func__);
208}
209
210int mm_app_open(uint8_t cam_id)
211{
212    int rc = MM_CAMERA_OK;
213    mm_camera_app_obj_t *pme = NULL;
214    int i;
215    mm_camera_event_type_t evt;
216
217    pme = mm_app_get_cam_obj(cam_id);
218
219    CDBG("%s:BEGIN\n", __func__);
220    if(pme != NULL) {
221        CDBG("%s:cam already open.nop\n",__func__);
222        goto end;
223    }
224    my_cam_app.cam_open = cam_id;
225    my_cam_app.obj[cam_id] = (mm_camera_app_obj_t *)malloc(sizeof(mm_camera_app_obj_t));
226    pme = my_cam_app.obj[cam_id];
227
228    pme->mem_cam = (mm_camear_mem_vtbl_t *)malloc(sizeof(mm_camear_mem_vtbl_t));
229    memset(pme->mem_cam,0,sizeof(mm_camear_mem_vtbl_t));
230    pme->mem_cam->user_data = pme;
231
232    pme->cam = my_cam_app.hal_lib.mm_camera_open(cam_id,pme->mem_cam);
233    if(pme->cam == NULL) {
234        CDBG("%s:dev open error=%d\n", __func__, rc);
235        memset(pme,0, sizeof(pme));
236        return -1;
237    }
238    CDBG("Open Camera id = %d handle = %d",cam_id,pme->cam->camera_handle);
239
240    pme->ch_id = cam_id;
241    pme->open_flag = true;
242    mm_app_set_dim_def(&pme->dim);
243
244    for (i = 0; i < MM_CAMERA_EVT_TYPE_MAX; i++) {
245        evt = (mm_camera_event_type_t) i;
246        pme->cam->ops->register_event_notify(pme->cam->camera_handle,notify_evt_cb,pme,evt);
247    }
248    pme->cam_state = CAMERA_STATE_OPEN;
249    pme->cam_mode = CAMERA_MODE;
250    pme->fullSizeSnapshot = 0;
251
252    pme->ch_id = pme->cam->ops->ch_acquire(pme->cam->camera_handle);
253    CDBG("Channel Acquired Successfully %d",pme->ch_id);
254end:
255    CDBG("%s:END, rc=%d\n", __func__, rc);
256    return rc;
257}
258
259int mm_app_close(int8_t cam_id)
260{
261    int rc = MM_CAMERA_OK;
262    mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
263
264    CDBG("%s:BEGIN\n", __func__);
265    if(!pme->cam) {
266        CDBG("%s:cam already closed. nop\n",__func__);
267        goto end;
268    }
269
270    pme->cam->ops->ch_release(pme->cam->camera_handle,pme->ch_id);
271    pme->cam->ops->camera_close(pme->cam->camera_handle);
272    pme->open_flag = false;
273    pme->cam = NULL;
274    pme->my_id = 0;
275    free(pme->mem_cam);
276    pme->mem_cam = NULL;
277    memset(&pme->dim, 0, sizeof(pme->dim));
278    memset(&pme->dim, 0, sizeof(pme->dim));
279
280    free(pme);
281    pme = NULL;
282    my_cam_app.obj[cam_id] = NULL;
283
284end:
285    CDBG("%s:END, rc=%d\n", __func__, rc);
286    return rc;
287}
288
289void switchRes(int cam_id)
290{
291    int rc = MM_CAMERA_OK;
292    mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
293    switch(pme->cam_state) {
294    case CAMERA_STATE_RECORD:
295    if(MM_CAMERA_OK != stopRecording(cam_id)){
296        CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
297        return -1;
298    }
299    case CAMERA_STATE_PREVIEW:
300        if(MM_CAMERA_OK !=  mm_app_stop_preview(cam_id)){
301            CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__);
302            return -1;
303        }
304        break;
305    case CAMERA_STATE_SNAPSHOT:
306    default:
307        break;
308    }
309}
310void switchCamera(int cam_id)
311{
312    int rc = MM_CAMERA_OK;
313    mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
314
315    if(my_cam_app.cam_open == cam_id){
316        return;
317    }
318
319    switch(pme->cam_state) {
320        case CAMERA_STATE_RECORD:
321            if(MM_CAMERA_OK != stopRecording(cam_id)){
322                CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
323                return -1;
324            }
325        case CAMERA_STATE_PREVIEW:
326            if(MM_CAMERA_OK !=  mm_app_stop_preview(cam_id)){
327                CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__);
328                return -1;
329            }
330            break;
331        case CAMERA_STATE_SNAPSHOT:
332        default:
333            break;
334    }
335
336    mm_app_close(my_cam_app.cam_open);
337    mm_app_open(cam_id);
338}
339
340int mm_app_set_dim(int8_t cam_id, cam_ctrl_dimension_t *dim)
341{
342    int rc = MM_CAMERA_OK;
343    mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
344
345    CDBG("%s:BEGIN\n", __func__);
346
347    memcpy(&pme->dim, dim, sizeof(cam_ctrl_dimension_t));
348    if(MM_CAMERA_OK != (rc = pme->cam->ops->set_parm(
349            pme->cam->camera_handle,MM_CAMERA_PARM_DIMENSION, &pme->dim)))
350    {
351        CDBG_ERROR("%s: set dimension err=%d\n", __func__, rc);
352    }
353    CDBG("%s:END, rc=%d\n", __func__, rc);
354    return rc;
355}
356
357int mm_app_get_dim(int8_t cam_id, cam_ctrl_dimension_t *dim)
358{
359    int rc = MM_CAMERA_OK;
360#if 0
361    mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
362    CDBG("%s:BEGIN\n", __func__);
363    if(pme->open_flag != true) {
364        CDBG("%s: dev not open yet\n", __func__);
365        rc = -MM_CAMERA_E_INVALID_OPERATION;
366        goto end;
367    }
368    /* now we only use the upper portion. TBD: needs to be fixed later */
369    //memcpy(&pme->dim, dim, sizeof(cam_ctrl_dimension_t));
370    if(MM_CAMERA_OK != (rc = pme->cam->cfg->get_parm(pme->cam,
371                                                    MM_CAMERA_PARM_DIMENSION, &pme->dim))) {
372        CDBG("%s: set dimension err=%d\n", __func__, rc);
373    }
374    CDBG("%s: raw_w=%d,raw_h=%d\n",
375            __func__, pme->dim.orig_picture_width, pme->dim.orig_picture_height);
376    if(dim)
377    memcpy(dim, &pme->dim, sizeof(cam_ctrl_dimension_t));
378
379end:
380    CDBG("%s:END, rc=%d\n", __func__, rc);
381#endif
382    return rc;
383}
384
385void mm_app_close_ch(int cam_id, int ch_type)
386{
387    mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
388
389    pme->cam->ops->ch_release(pme->cam->camera_handle,pme->ch_id);
390    CDBG("%s:END,cam_id = %d, ch = %d\n", __func__, cam_id, ch_type);
391
392}
393
394int mm_app_unit_test()
395{
396    my_cam_app.run_sanity = 1;
397    mm_app_unit_test_entry(&my_cam_app);
398    return 0;
399}
400
401int mm_app_dual_test()
402{
403    my_cam_app.run_sanity = 1;
404    mm_app_dual_test_entry(&my_cam_app);
405    return 0;
406}
407