1/* Copyright (c) 2011-2012, 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 /*#error uncomment this for compiler test!*/
29//#define ALOG_NDEBUG 0
30#define ALOG_NIDEBUG 0
31#define LOG_TAG "QualcommUsbCamera"
32
33#include <utils/Log.h>
34#include <utils/threads.h>
35#include <fcntl.h>
36#include <sys/mman.h>
37#include <sys/stat.h>
38#include <unistd.h>
39#include <sys/prctl.h>
40#include <sys/resource.h>
41#include <pthread.h>
42#include <linux/uvcvideo.h>
43
44#include "QCameraHAL.h"
45#include "QualcommUsbCamera.h"
46#include "QCameraUsbPriv.h"
47#include "QCameraMjpegDecode.h"
48#include "QCameraUsbParm.h"
49#include <gralloc_priv.h>
50#include <genlock.h>
51
52extern "C" {
53#include <sys/time.h>
54}
55
56camera_device_ops_t usbcam_camera_ops = {
57  set_preview_window:         android::usbcam_set_preview_window,
58  set_callbacks:              android::usbcam_set_CallBacks,
59  enable_msg_type:            android::usbcam_enable_msg_type,
60  disable_msg_type:           android::usbcam_disable_msg_type,
61  msg_type_enabled:           android::usbcam_msg_type_enabled,
62
63  start_preview:              android::usbcam_start_preview,
64  stop_preview:               android::usbcam_stop_preview,
65  preview_enabled:            android::usbcam_preview_enabled,
66  store_meta_data_in_buffers: android::usbcam_store_meta_data_in_buffers,
67
68  start_recording:            android::usbcam_start_recording,
69  stop_recording:             android::usbcam_stop_recording,
70  recording_enabled:          android::usbcam_recording_enabled,
71  release_recording_frame:    android::usbcam_release_recording_frame,
72
73  auto_focus:                 android::usbcam_auto_focus,
74  cancel_auto_focus:          android::usbcam_cancel_auto_focus,
75
76  take_picture:               android::usbcam_take_picture,
77  cancel_picture:             android::usbcam_cancel_picture,
78
79  set_parameters:             android::usbcam_set_parameters,
80  get_parameters:             android::usbcam_get_parameters,
81  put_parameters:             android::usbcam_put_parameters,
82  send_command:               android::usbcam_send_command,
83
84  release:                    android::usbcam_release,
85  dump:                       android::usbcam_dump,
86};
87
88#define CAPTURE                 1
89#define DISPLAY                 1
90#define CALL_BACK               1
91#define MEMSET                  0
92#define FREAD_JPEG_PICTURE      0
93#define JPEG_ON_USB_CAMERA      1
94#define FILE_DUMP_CAMERA        0
95#define FILE_DUMP_B4_DISP       0
96
97namespace android {
98
99static int initUsbCamera(               camera_hardware_t *camHal,
100                                        int width, int height,
101                                        int pixelFormat);
102static int startUsbCamCapture(          camera_hardware_t *camHal);
103static int stopUsbCamCapture(           camera_hardware_t *camHal);
104static int initV4L2mmap(                camera_hardware_t *camHal);
105static int unInitV4L2mmap(              camera_hardware_t *camHal);
106static int launch_preview_thread(       camera_hardware_t *camHal);
107static int launchTakePictureThread(     camera_hardware_t *camHal);
108static int initDisplayBuffers(          camera_hardware_t *camHal);
109static int deInitDisplayBuffers(        camera_hardware_t *camHal);
110static int stopPreviewInternal(         camera_hardware_t *camHal);
111static int get_buf_from_cam(            camera_hardware_t *camHal);
112static int put_buf_to_cam(              camera_hardware_t *camHal);
113static int prvwThreadTakePictureInternal(camera_hardware_t *camHal);
114static int get_buf_from_display( camera_hardware_t *camHal, int *buffer_id);
115static int put_buf_to_display(   camera_hardware_t *camHal, int buffer_id);
116static int convert_data_frm_cam_to_disp(camera_hardware_t *camHal, int buffer_id);
117static void * previewloop(void *);
118static void * takePictureThread(void *);
119static int convert_YUYV_to_420_NV12(char *in_buf, char *out_buf, int wd, int ht);
120static int get_uvc_device(char *devname);
121static int getPreviewCaptureFmt(camera_hardware_t *camHal);
122static int allocate_ion_memory(QCameraHalMemInfo_t *mem_info, int ion_type);
123static int deallocate_ion_memory(QCameraHalMemInfo_t *mem_info);
124static int ioctlLoop(int fd, int ioctlCmd, void *args);
125static int readFromFile(char* fileName, char* buffer, int bufferSize);
126static int fileDump(const char* fileName, char* data, int length, int* frm_cnt);
127static int encodeJpeg(                  camera_hardware_t *camHal);
128void jpegEncodeCb   (jpeg_job_status_t status,
129                       uint8_t thumbnailDroppedFlag,
130                       uint32_t client_hdl,
131                       uint32_t jobId,
132                       uint8_t* out_data,
133                       uint32_t data_size,
134                       void *userData);
135
136/* HAL function implementation goes here*/
137
138/**
139 * The functions need to be provided by the camera HAL.
140 *
141 * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo()
142 * and openCameraHardware() is 0 to N-1.
143 */
144
145extern "C" int usbcam_get_number_of_cameras()
146{
147    /* TBR: This is hardcoded currently to 1 USB camera */
148    int numCameras = 1;
149    ALOGI("%s: E", __func__);
150    ALOGI("%s: X", __func__);
151
152    return numCameras;
153}
154
155extern "C" int usbcam_get_camera_info(int camera_id, struct camera_info *info)
156{
157    int rc = -1;
158    ALOGI("%s: E", __func__);
159
160    /* TBR: This info is hardcoded currently irrespective of camera_id */
161    if(info) {
162        struct CameraInfo camInfo;
163        memset(&camInfo, -1, sizeof (struct CameraInfo));
164
165        info->facing = CAMERA_FACING_FRONT;//CAMERA_FACING_BACK;
166        info->orientation = 0;
167        rc = 0;
168    }
169    ALOGI("%s: X", __func__);
170    return rc;
171}
172
173/* HAL should return NULL handle if it fails to open camera hardware. */
174extern "C" int  usbcam_camera_device_open(
175  const struct hw_module_t* module, const char* id,
176          struct hw_device_t** hw_device)
177{
178    int rc = -1;
179    camera_device       *device = NULL;
180    camera_hardware_t   *camHal;
181    char                *dev_name;
182
183    ALOGI("%s: E", __func__);
184
185    /* initialize return handle value to NULL */
186    *hw_device = NULL;
187
188    camHal = new camera_hardware_t();
189    if(!camHal) {
190
191            ALOGE("%s:  end in no mem", __func__);
192            return -1;
193    }
194
195    rc = usbCamInitDefaultParameters(camHal);
196    if(0 != rc)
197    {
198        ALOGE("%s: usbCamInitDefaultParameters error", __func__);
199        return rc;
200    }
201#if CAPTURE
202
203    dev_name = camHal->dev_name;
204
205    rc = get_uvc_device(dev_name);
206    if(rc || *dev_name == '\0'){
207        ALOGE("%s: No UVC node found \n", __func__);
208        return -1;
209    }
210
211    camHal->fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
212
213    if (camHal->fd <  0) {
214        ALOGE("%s: Cannot open '%s'", __func__, dev_name);
215        free(camHal);
216        rc = -1;
217    }else{
218        rc = 0;
219    }
220
221#else /* CAPTURE */
222    rc = 0;
223#endif /* CAPTURE */
224
225    device                  = &camHal->hw_dev;
226    device->common.close    = usbcam_close_camera_device;
227    device->ops             = &usbcam_camera_ops;
228    device->priv            = (void *)camHal;
229    *hw_device              = &(device->common);
230
231    ALOGD("%s: camHal: %p", __func__, camHal);
232    ALOGI("%s: X %d", __func__, rc);
233
234    return rc;
235}
236
237extern "C"  int usbcam_close_camera_device( hw_device_t *hw_dev)
238{
239    ALOGI("%s: device =%p E", __func__, hw_dev);
240    int rc =  -1;
241    camera_device_t *device     = (camera_device_t *)hw_dev;
242
243    if(device) {
244        camera_hardware_t *camHal   = (camera_hardware_t *)device->priv;
245        if(camHal) {
246            rc = close(camHal->fd);
247            if(rc < 0) {
248                ALOGE("%s: close failed ", __func__);
249            }
250            camHal->fd = 0;
251            delete camHal;
252        }else{
253                ALOGE("%s: camHal is NULL pointer ", __func__);
254        }
255    }
256    ALOGI("%s: X device =%p, rc = %d", __func__, hw_dev, rc);
257    return rc;
258}
259
260int usbcam_set_preview_window(struct camera_device * device,
261        struct preview_stream_ops *window)
262{
263    ALOGI("%s: E", __func__);
264    int rc = 0;
265    camera_hardware_t *camHal;
266
267    VALIDATE_DEVICE_HDL(camHal, device, -1);
268    Mutex::Autolock autoLock(camHal->lock);
269
270    /* if window is already set, then de-init previous buffers */
271    if(camHal->window){
272        rc = deInitDisplayBuffers(camHal);
273        if(rc < 0) {
274            ALOGE("%s: deInitDisplayBuffers returned error", __func__);
275        }
276    }
277    camHal->window = window;
278
279    if(camHal->window){
280        rc = initDisplayBuffers(camHal);
281        if(rc < 0) {
282            ALOGE("%s: initDisplayBuffers returned error", __func__);
283        }
284    }
285    ALOGI("%s: X. rc = %d", __func__, rc);
286    return rc;
287}
288
289void usbcam_set_CallBacks(struct camera_device * device,
290        camera_notify_callback notify_cb,
291        camera_data_callback data_cb,
292        camera_data_timestamp_callback data_cb_timestamp,
293        camera_request_memory get_memory,
294        void *user)
295{
296    ALOGI("%s: E", __func__);
297    camera_hardware_t *camHal;
298
299    if(device && device->priv){
300        camHal = (camera_hardware_t *)device->priv;
301    }else{
302        ALOGE("%s: Null device or device->priv", __func__);
303        return;
304    }
305
306    Mutex::Autolock autoLock(camHal->lock);
307
308    camHal->notify_cb           = notify_cb;
309    camHal->data_cb             = data_cb;
310    camHal->data_cb_timestamp   = data_cb_timestamp;
311    camHal->get_memory          = get_memory;
312    camHal->cb_ctxt             = user;
313
314    ALOGI("%s: X", __func__);
315}
316
317void usbcam_enable_msg_type(struct camera_device * device, int32_t msg_type)
318{
319    ALOGI("%s: E", __func__);
320    ALOGI("%s: msg_type: %d", __func__, msg_type);
321
322    camera_hardware_t *camHal;
323
324    if(device && device->priv){
325        camHal = (camera_hardware_t *)device->priv;
326    }else{
327        ALOGE("%s: Null device or device->priv", __func__);
328        return;
329    }
330
331    Mutex::Autolock autoLock(camHal->lock);
332
333    camHal->msgEnabledFlag |= msg_type;
334
335    ALOGI("%s: X", __func__);
336}
337
338void usbcam_disable_msg_type(struct camera_device * device, int32_t msg_type)
339{
340    ALOGI("%s: E", __func__);
341    ALOGI("%s: msg_type: %d", __func__, msg_type);
342
343    camera_hardware_t *camHal;
344    if(device && device->priv){
345        camHal = (camera_hardware_t *)device->priv;
346    }else{
347        ALOGE("%s: Null device or device->priv", __func__);
348        return;
349    }
350
351    Mutex::Autolock autoLock(camHal->lock);
352
353    camHal->msgEnabledFlag &= ~msg_type;
354
355    ALOGI("%s: X", __func__);
356}
357
358int usbcam_msg_type_enabled(struct camera_device * device, int32_t msg_type)
359{
360    ALOGI("%s: E", __func__);
361
362    camera_hardware_t *camHal;
363    if(device && device->priv){
364        camHal = (camera_hardware_t *)device->priv;
365    }else{
366        ALOGE("%s: Null device or device->priv", __func__);
367        return -1;
368    }
369
370    Mutex::Autolock autoLock(camHal->lock);
371
372    ALOGI("%s: X", __func__);
373    return (camHal->msgEnabledFlag & msg_type);
374}
375
376int usbcam_start_preview(struct camera_device * device)
377{
378    ALOGI("%s: E", __func__);
379
380    int rc = -1;
381    camera_hardware_t *camHal = NULL;
382
383    VALIDATE_DEVICE_HDL(camHal, device, -1);
384    Mutex::Autolock autoLock(camHal->lock);
385
386    /* If preivew is already running, nothing to be done */
387    if(camHal->previewEnabledFlag){
388        ALOGI("%s: Preview is already running", __func__);
389        return 0;
390    }
391
392#if CAPTURE
393    rc = initUsbCamera(camHal, camHal->prevWidth,
394                        camHal->prevHeight, getPreviewCaptureFmt(camHal));
395    if(rc < 0) {
396        ALOGE("%s: Failed to intialize the device", __func__);
397    }else{
398        rc = startUsbCamCapture(camHal);
399        if(rc < 0) {
400            ALOGE("%s: Failed to startUsbCamCapture", __func__);
401        }else{
402            rc = launch_preview_thread(camHal);
403            if(rc < 0) {
404                ALOGE("%s: Failed to launch_preview_thread", __func__);
405            }
406        }
407    }
408#else /* CAPTURE */
409    rc = launch_preview_thread(camHal);
410    if(rc < 0) {
411        ALOGE("%s: Failed to launch_preview_thread", __func__);
412    }
413#endif /* CAPTURE */
414    /* if no errors, then set the flag */
415    if(!rc)
416        camHal->previewEnabledFlag = 1;
417
418    ALOGD("%s: X", __func__);
419    return rc;
420}
421
422void usbcam_stop_preview(struct camera_device * device)
423{
424    ALOGD("%s: E", __func__);
425
426    int rc = 0;
427    camera_hardware_t *camHal;
428
429    if(device && device->priv){
430        camHal = (camera_hardware_t *)device->priv;
431    }else{
432        ALOGE("%s: Null device or device->priv", __func__);
433        return;
434    }
435
436    Mutex::Autolock autoLock(camHal->lock);
437
438    rc = stopPreviewInternal(camHal);
439    if(rc)
440        ALOGE("%s: stopPreviewInternal returned error", __func__);
441
442    ALOGI("%s: X", __func__);
443    return;
444}
445
446/* This function is equivalent to is_preview_enabled */
447int usbcam_preview_enabled(struct camera_device * device)
448{
449    ALOGI("%s: E", __func__);
450    camera_hardware_t *camHal;
451
452    if(device && device->priv){
453        camHal = (camera_hardware_t *)device->priv;
454    }else{
455        ALOGE("%s: Null device or device->priv", __func__);
456        return -1;
457    }
458    Mutex::Autolock autoLock(camHal->lock);
459
460    ALOGI("%s: X", __func__);
461    return camHal->previewEnabledFlag;
462}
463
464/* TBD */
465int usbcam_store_meta_data_in_buffers(struct camera_device * device, int enable)
466{
467    ALOGI("%s: E", __func__);
468    int rc = 0;
469
470    ALOGI("%s: X", __func__);
471    return rc;
472}
473
474/* TBD */
475int usbcam_start_recording(struct camera_device * device)
476{
477    int rc = 0;
478    ALOGD("%s: E", __func__);
479
480    ALOGD("%s: X", __func__);
481
482    return rc;
483}
484
485/* TBD */
486void usbcam_stop_recording(struct camera_device * device)
487{
488    ALOGD("%s: E", __func__);
489
490    ALOGD("%s: X", __func__);
491}
492
493/* TBD */
494int usbcam_recording_enabled(struct camera_device * device)
495{
496    int rc = 0;
497    ALOGD("%s: E", __func__);
498
499    ALOGD("%s: X", __func__);
500    return rc;
501}
502
503/* TBD */
504void usbcam_release_recording_frame(struct camera_device * device,
505                const void *opaque)
506{
507    ALOGV("%s: E", __func__);
508
509    ALOGD("%s: X", __func__);
510}
511
512/* TBD */
513int usbcam_auto_focus(struct camera_device * device)
514{
515    ALOGD("%s: E", __func__);
516    int rc = 0;
517
518    ALOGD("%s: X", __func__);
519    return rc;
520}
521
522/* TBD */
523int usbcam_cancel_auto_focus(struct camera_device * device)
524{
525    int rc = 0;
526    ALOGD("%s: E", __func__);
527
528    ALOGD("%s: X", __func__);
529    return rc;
530}
531
532int usbcam_take_picture(struct camera_device * device)
533{
534    ALOGI("%s: E", __func__);
535    int rc = 0;
536    camera_hardware_t *camHal;
537
538    VALIDATE_DEVICE_HDL(camHal, device, -1);
539
540    Mutex::Autolock autoLock(camHal->lock);
541
542    /* If take picture is already in progress, nothing t be done */
543    if(camHal->takePictInProgress){
544        ALOGI("%s: Take picture already in progress", __func__);
545        return 0;
546    }
547
548    if(camHal->previewEnabledFlag)
549    {
550        rc = stopPreviewInternal(camHal);
551        if(rc){
552            ALOGE("%s: stopPreviewInternal returned error", __func__);
553        }
554        USB_CAM_CLOSE(camHal);
555        camHal->prvwStoppedForPicture = 1;
556    }
557    /* TBD: Need to handle any dependencies on video recording state */
558    rc = launchTakePictureThread(camHal);
559    if(rc)
560        ALOGE("%s: launchTakePictureThread error", __func__);
561
562#if 0
563    /* This implementation requests preview thread to take picture */
564    if(camHal->previewEnabledFlag)
565    {
566        camHal->prvwCmdPending++;
567        camHal->prvwCmd         = USB_CAM_PREVIEW_TAKEPIC;
568        ALOGD("%s: Take picture command set ", __func__);
569    }else{
570        ALOGE("%s: Take picture without preview started!", __func__);
571        rc = -1;
572    }
573#endif
574
575    if(!rc)
576        camHal->takePictInProgress = 1;
577
578    ALOGI("%s: X", __func__);
579    return rc;
580}
581
582/* TBD */
583int usbcam_cancel_picture(struct camera_device * device)
584
585{
586    ALOGI("%s: E", __func__);
587    int rc = 0;
588
589    ALOGI("%s: X", __func__);
590    return rc;
591}
592
593int usbcam_set_parameters(struct camera_device * device, const char *params)
594
595{
596    ALOGI("%s: E", __func__);
597    int rc = 0;
598    camera_hardware_t *camHal;
599
600    VALIDATE_DEVICE_HDL(camHal, device, -1);
601
602    Mutex::Autolock autoLock(camHal->lock);
603
604    rc = usbCamSetParameters(camHal, params);
605
606    ALOGI("%s: X", __func__);
607    return rc;
608}
609
610char* usbcam_get_parameters(struct camera_device * device)
611{
612    char *parms;
613    ALOGI("%s: E", __func__);
614
615    camera_hardware_t *camHal;
616    VALIDATE_DEVICE_HDL(camHal, device, NULL);
617
618    Mutex::Autolock autoLock(camHal->lock);
619
620    parms = usbCamGetParameters(camHal);
621
622    ALOGI("%s: X", __func__);
623    return parms;
624}
625
626void usbcam_put_parameters(struct camera_device * device, char *parm)
627
628{
629    ALOGI("%s: E", __func__);
630
631    camera_hardware_t *camHal;
632
633    if(device && device->priv){
634        camHal = (camera_hardware_t *)device->priv;
635    }else{
636        ALOGE("%s: Null device or device->priv", __func__);
637        return;
638    }
639
640    usbCamPutParameters(camHal, parm);
641
642    ALOGI("%s: X", __func__);
643    return;
644}
645
646/* TBD */
647int usbcam_send_command(struct camera_device * device,
648            int32_t cmd, int32_t arg1, int32_t arg2)
649{
650    int rc = 0;
651    ALOGI("%s: E", __func__);
652    ALOGI("%d", cmd);
653
654    ALOGI("%s: X", __func__);
655    return rc;
656}
657
658/* TBD */
659void usbcam_release(struct camera_device * device)
660{
661    ALOGI("%s: E", __func__);
662#if 0
663    Mutex::Autolock l(&mLock);
664
665    switch(mPreviewState) {
666    case QCAMERA_HAL_PREVIEW_STOPPED:
667        break;
668    case QCAMERA_HAL_PREVIEW_START:
669        break;
670    case QCAMERA_HAL_PREVIEW_STARTED:
671        stopPreviewInternal();
672    break;
673    case QCAMERA_HAL_RECORDING_STARTED:
674        stopRecordingInternal();
675        stopPreviewInternal();
676        break;
677    case QCAMERA_HAL_TAKE_PICTURE:
678        cancelPictureInternal();
679        break;
680    default:
681        break;
682    }
683    mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
684#endif
685    ALOGI("%s: X", __func__);
686}
687
688/* TBD */
689int usbcam_dump(struct camera_device * device, int fd)
690{
691    ALOGI("%s: E", __func__);
692    int rc = 0;
693
694    ALOGI("%s: X", __func__);
695    return rc;
696}
697/*****************************************************************************
698*  Static function definitions below
699*****************************************************************************/
700
701/******************************************************************************/
702/* No in place conversion supported. Output buffer and input MUST should be   */
703/* different input buffer for a 4x4 pixel video                             ***/
704/******                  YUYVYUYV          00 01 02 03 04 05 06 07 ************/
705/******                  YUYVYUYV          08 09 10 11 12 13 14 15 ************/
706/******                  YUYVYUYV          16 17 18 19 20 21 22 23 ************/
707/******                  YUYVYUYV          24 25 26 27 28 29 30 31 ************/
708/******************************************************************************/
709/* output generated by this function ******************************************/
710/************************** YYYY            00 02 04 06            ************/
711/************************** YYYY            08 10 12 14            ************/
712/************************** YYYY            16 18 20 22            ************/
713/************************** YYYY            24 26 28 30            ************/
714/************************** VUVU            03 01 07 05            ************/
715/************************** VUVU            19 17 23 21            ************/
716/******************************************************************************/
717
718static int convert_YUYV_to_420_NV12(char *in_buf, char *out_buf, int wd, int ht)
719{
720    int rc =0;
721    int row, col, uv_row;
722
723    ALOGD("%s: E", __func__);
724    /* Arrange Y */
725    for(row = 0; row < ht; row++)
726        for(col = 0; col < wd * 2; col += 2)
727        {
728            out_buf[row * wd + col / 2] = in_buf[row * wd * 2 + col];
729        }
730
731    /* Arrange UV */
732    for(row = 0, uv_row = ht; row < ht; row += 2, uv_row++)
733        for(col = 1; col < wd * 2; col += 4)
734        {
735            out_buf[uv_row * wd + col / 2]= in_buf[row * wd * 2 + col + 2];
736            out_buf[uv_row * wd + col / 2 + 1]  = in_buf[row * wd * 2 + col];
737        }
738
739    ALOGD("%s: X", __func__);
740    return rc;
741}
742
743/******************************************************************************
744 * Function: initDisplayBuffers
745 * Description: This function initializes the preview buffers
746 *
747 * Input parameters:
748 *   camHal              - camera HAL handle
749 *
750 * Return values:
751 *      0   Success
752 *      -1  Error
753 * Notes: none
754 *****************************************************************************/
755static int initDisplayBuffers(camera_hardware_t *camHal)
756{
757    preview_stream_ops    *mPreviewWindow;
758    struct ion_fd_data    ion_info_fd;
759    int                   numMinUndequeuedBufs = 0;
760    int                   rc = 0;
761    int                   gralloc_usage = 0;
762    int                   err;
763    int                   color=30;
764
765    ALOGD("%s: E", __func__);
766
767#if DISPLAY
768    if(camHal == NULL) {
769        ALOGE("%s: camHal = NULL", __func__);
770        return -1;
771    }
772
773    mPreviewWindow = camHal->window;
774    if(!mPreviewWindow) {
775        ALOGE("%s: mPreviewWindow = NULL", __func__);
776        return -1;
777    }
778
779    /************************************************************************/
780    /* - get_min_undequeued_buffer_count                                    */
781    /* - set_buffer_count                                                   */
782    /* - set_buffers_geometry                                               */
783    /* - set_usage                                                          */
784    /* - dequeue all the display buffers                                    */
785    /* - cancel buffers: release w/o displaying                             */
786    /************************************************************************/
787
788    /************************************************************************/
789    /* - get_min_undequeued_buffer_count                                    */
790    /************************************************************************/
791    if(mPreviewWindow->get_min_undequeued_buffer_count) {
792        rc = mPreviewWindow->get_min_undequeued_buffer_count(
793            mPreviewWindow, &numMinUndequeuedBufs);
794        if (0 != rc) {
795            ALOGE("%s: get_min_undequeued_buffer_count returned error", __func__);
796        }
797        else
798            ALOGD("%s: get_min_undequeued_buffer_count returned: %d ",
799               __func__, numMinUndequeuedBufs);
800    }
801    else
802        ALOGE("%s: get_min_undequeued_buffer_count is NULL pointer", __func__);
803
804    /************************************************************************/
805    /* - set_buffer_count                                                   */
806    /************************************************************************/
807    if(mPreviewWindow->set_buffer_count) {
808        camHal->previewMem.buffer_count = numMinUndequeuedBufs
809                                            + PRVW_DISP_BUF_CNT;
810        rc = mPreviewWindow->set_buffer_count(
811            mPreviewWindow,
812            camHal->previewMem.buffer_count);
813        if (rc != 0) {
814            ALOGE("%s: set_buffer_count returned error", __func__);
815        }else
816            ALOGD("%s: set_buffer_count returned success", __func__);
817    }else
818        ALOGE("%s: set_buffer_count is NULL pointer", __func__);
819
820    /************************************************************************/
821    /* - set_buffers_geometry                                               */
822    /************************************************************************/
823    if(mPreviewWindow->set_buffers_geometry) {
824        rc = mPreviewWindow->set_buffers_geometry(mPreviewWindow,
825                                                camHal->dispWidth,
826                                                camHal->dispHeight,
827                                                camHal->dispFormat);
828        if (rc != 0) {
829            ALOGE("%s: set_buffers_geometry returned error. %s (%d)",
830               __func__, strerror(-rc), -rc);
831        }else
832            ALOGD("%s: set_buffers_geometry returned success", __func__);
833    }else
834        ALOGE("%s: set_buffers_geometry is NULL pointer", __func__);
835
836    /************************************************************************/
837    /* - set_usage                                                          */
838    /************************************************************************/
839    gralloc_usage = CAMERA_GRALLOC_HEAP_ID | CAMERA_GRALLOC_FALLBACK_HEAP_ID |
840                    GRALLOC_USAGE_PRIVATE_UNCACHED;
841
842    if(mPreviewWindow->set_usage) {
843        rc = mPreviewWindow->set_usage(mPreviewWindow, gralloc_usage);
844        if (rc != 0) {
845            ALOGE("%s: set_usage returned error", __func__);
846        }else
847            ALOGD("%s: set_usage returned success", __func__);
848    }
849    else
850        ALOGE("%s: set_usage is NULL pointer", __func__);
851
852    /************************************************************************/
853    /* - dequeue all the display buffers                                    */
854    /************************************************************************/
855    for (int cnt = 0; cnt < camHal->previewMem.buffer_count; cnt++) {
856        int stride;
857        err = mPreviewWindow->dequeue_buffer(
858                mPreviewWindow,
859                &camHal->previewMem.buffer_handle[cnt],
860                &camHal->previewMem.stride[cnt]);
861        if(!err) {
862            ALOGD("%s: dequeue buf: %p\n",
863                 __func__, camHal->previewMem.buffer_handle[cnt]);
864
865            if(mPreviewWindow->lock_buffer) {
866                err = mPreviewWindow->lock_buffer(
867                    mPreviewWindow,
868                    camHal->previewMem.buffer_handle[cnt]);
869                ALOGD("%s: mPreviewWindow->lock_buffer success",
870                     __func__);
871            }
872
873            // lock the buffer using genlock
874            ALOGD("%s: camera call genlock_lock, hdl=%p",
875                __func__, (*camHal->previewMem.buffer_handle[cnt]));
876
877            if (GENLOCK_NO_ERROR !=
878                genlock_lock_buffer(
879                    (native_handle_t *) (*camHal->previewMem.buffer_handle[cnt]),
880                    GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT))
881            {
882                ALOGE("%s: genlock_lock_buffer(WRITE) failed",
883                    __func__);
884                camHal->previewMem.local_flag[cnt] = BUFFER_UNLOCKED;
885            }else {
886                ALOGD("%s: genlock_lock_buffer hdl =%p",
887                  __func__, *camHal->previewMem.buffer_handle[cnt]);
888                camHal->previewMem.local_flag[cnt] = BUFFER_LOCKED;
889            }
890
891            /* Store this buffer details in the context */
892            camHal->previewMem.private_buffer_handle[cnt] =
893                (struct private_handle_t *) (*camHal->previewMem.buffer_handle[cnt]);
894
895            ALOGD("%s: idx = %d, fd = %d, size = %d, offset = %d", __func__,
896                cnt, camHal->previewMem.private_buffer_handle[cnt]->fd,
897                camHal->previewMem.private_buffer_handle[cnt]->size,
898                camHal->previewMem.private_buffer_handle[cnt]->offset);
899
900            camHal->previewMem.camera_memory[cnt] =
901                camHal->get_memory(
902                    camHal->previewMem.private_buffer_handle[cnt]->fd,
903                    camHal->previewMem.private_buffer_handle[cnt]->size,
904                    1, camHal->cb_ctxt);
905
906            ALOGD("%s: data = %p, size = %d, handle = %p", __func__,
907                camHal->previewMem.camera_memory[cnt]->data,
908                camHal->previewMem.camera_memory[cnt]->size,
909                camHal->previewMem.camera_memory[cnt]->handle);
910
911#ifdef USE_ION
912            /* In case of ION usage, open ION fd */
913            camHal->previewMem.mem_info[cnt].main_ion_fd =
914                                                open("/dev/ion", O_RDONLY);
915            if (camHal->previewMem.mem_info[cnt].main_ion_fd < 0) {
916                ALOGE("%s: failed: could not open ion device\n", __func__);
917            }else{
918                memset(&ion_info_fd, 0, sizeof(ion_info_fd));
919                ion_info_fd.fd =
920                    camHal->previewMem.private_buffer_handle[cnt]->fd;
921                if (ioctl(camHal->previewMem.mem_info[cnt].main_ion_fd,
922                          ION_IOC_IMPORT, &ion_info_fd) < 0) {
923                    ALOGE("ION import failed\n");
924                }
925            }
926            camHal->previewMem.mem_info[cnt].fd =
927                camHal->previewMem.private_buffer_handle[cnt]->fd;
928            camHal->previewMem.mem_info[cnt].size =
929                camHal->previewMem.private_buffer_handle[cnt]->size;
930            camHal->previewMem.mem_info[cnt].handle = ion_info_fd.handle;
931
932#endif
933        }
934        else
935            ALOGE("%s: dequeue buf %d failed \n", __func__, cnt);
936    }
937    /************************************************************************/
938    /* - cancel buffers: queue w/o displaying                               */
939    /************************************************************************/
940    for (int cnt = 0; cnt < camHal->previewMem.buffer_count; cnt++) {
941        if (GENLOCK_FAILURE == genlock_unlock_buffer(
942                (native_handle_t *)(*(camHal->previewMem.buffer_handle[cnt])))){
943            ALOGE("%s: genlock_unlock_buffer failed: hdl =%p", __func__,
944                (*(camHal->previewMem.buffer_handle[cnt])) );
945        } else {
946            camHal->previewMem.local_flag[cnt] = BUFFER_UNLOCKED;
947            ALOGD("%s: genlock_unlock_buffer success: hdl = %p",
948               __func__, (*(camHal->previewMem.buffer_handle[cnt])));
949        }
950
951        err = mPreviewWindow->cancel_buffer(mPreviewWindow,
952            (buffer_handle_t *)camHal->previewMem.buffer_handle[cnt]);
953        if(!err) {
954            ALOGD("%s: cancel_buffer successful: %p\n",
955                 __func__, camHal->previewMem.buffer_handle[cnt]);
956        }else
957            ALOGE("%s: cancel_buffer failed: %p\n", __func__,
958                 camHal->previewMem.buffer_handle[cnt]);
959    }
960#else
961    rc = 0;
962#endif /* #if DISPLAY */
963    ALOGD("%s: X", __func__);
964    return rc;
965}
966
967/******************************************************************************
968 * Function: deInitDisplayBuffers
969 * Description: This function de-initializes all the display buffers allocated
970 *              in initDisplayBuffers
971 *
972 * Input parameters:
973 *   camHal              - camera HAL handle
974 *
975 * Return values:
976 *      0   Success
977 *      -1  Error
978 * Notes: none
979 *****************************************************************************/
980static int deInitDisplayBuffers(camera_hardware_t *camHal)
981{
982    int rc = 0;
983    preview_stream_ops    *previewWindow;
984
985    ALOGD("%s: E", __func__);
986
987    if(!camHal || !camHal->window) {
988      ALOGE("%s: camHal = NULL or window = NULL ", __func__);
989      return -1;
990    }
991
992    previewWindow = camHal->window;
993
994    /************************************************************************/
995    /* - Release all buffers that were acquired using get_memory            */
996    /* - If using ION memory, free ION related resources                    */
997    /* - genUnlock if buffer is genLocked                                   */
998    /* - Cancel buffers: queue w/o displaying                               */
999    /************************************************************************/
1000
1001#if DISPLAY
1002    for (int cnt = 0; cnt < camHal->previewMem.buffer_count; cnt++) {
1003
1004        /* Release all buffers that were acquired using get_memory */
1005        camHal->previewMem.camera_memory[cnt]->release(
1006                                camHal->previewMem.camera_memory[cnt]);
1007
1008#ifdef USE_ION
1009        /* If using ION memory, free ION related resources */
1010        struct ion_handle_data ion_handle;
1011        memset(&ion_handle, 0, sizeof(ion_handle));
1012        ion_handle.handle = camHal->previewMem.mem_info[cnt].handle;
1013        if (ioctl(camHal->previewMem.mem_info[cnt].main_ion_fd,
1014            ION_IOC_FREE, &ion_handle) < 0) {
1015            ALOGE("%s: ion free failed\n", __func__);
1016        }
1017        close(camHal->previewMem.mem_info[cnt].main_ion_fd);
1018#endif
1019
1020        /* genUnlock if buffer is genLocked */
1021        if(camHal->previewMem.local_flag[cnt] == BUFFER_LOCKED){
1022            if (GENLOCK_FAILURE == genlock_unlock_buffer(
1023                    (native_handle_t *)(*(camHal->previewMem.buffer_handle[cnt])))){
1024                ALOGE("%s: genlock_unlock_buffer failed: hdl =%p", __func__,
1025                    (*(camHal->previewMem.buffer_handle[cnt])) );
1026            } else {
1027                camHal->previewMem.local_flag[cnt] = BUFFER_UNLOCKED;
1028                ALOGD("%s: genlock_unlock_buffer success: hdl = %p",
1029                   __func__, (*(camHal->previewMem.buffer_handle[cnt])));
1030            }
1031        }
1032        /* cancel buffers: enqueue w/o displaying */
1033        rc = previewWindow->cancel_buffer(previewWindow,
1034            (buffer_handle_t *)camHal->previewMem.buffer_handle[cnt]);
1035        if(!rc) {
1036            ALOGD("%s: cancel_buffer successful: %p\n",
1037                 __func__, camHal->previewMem.buffer_handle[cnt]);
1038        }else
1039            ALOGE("%s: cancel_buffer failed: %p\n", __func__,
1040                 camHal->previewMem.buffer_handle[cnt]);
1041    }
1042#endif /* #if DISPLAY */
1043    memset(&camHal->previewMem, 0, sizeof(camHal->previewMem));
1044
1045    ALOGD("%s: X", __func__);
1046    return rc;
1047}
1048
1049/******************************************************************************
1050 * Function: getPreviewCaptureFmt
1051 * Description: This function implements the logic to decide appropriate
1052 *              capture format from the USB camera
1053 *
1054 * Input parameters:
1055 *   camHal              - camera HAL handle
1056 *
1057 * Return values:
1058 *      Capture format. Default (V4L2_PIX_FMT_MJPEG)
1059 *
1060 * Notes: none
1061 *****************************************************************************/
1062static int getPreviewCaptureFmt(camera_hardware_t *camHal)
1063{
1064    int     i = 0, mjpegSupported = 0, h264Supported = 0;
1065    struct v4l2_fmtdesc fmtdesc;
1066
1067    memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
1068
1069    /************************************************************************/
1070    /* - Query the camera for all supported formats                         */
1071    /* - Based on the resolution, pick an apporpriate format                */
1072    /************************************************************************/
1073
1074    /************************************************************************/
1075    /* - Query the camera for all supported formats                         */
1076    /************************************************************************/
1077    for(i = 0; ; i++) {
1078        fmtdesc.index = i;
1079        fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1080        if (-1 == ioctlLoop(camHal->fd, VIDIOC_ENUM_FMT, &fmtdesc)) {
1081            if (EINVAL == errno) {
1082                ALOGI("%s: Queried all formats till index %d\n", __func__, i);
1083                break;
1084            } else {
1085                ALOGE("%s: VIDIOC_ENUM_FMT failed", __func__);
1086            }
1087        }
1088        if(V4L2_PIX_FMT_MJPEG == fmtdesc.pixelformat){
1089            mjpegSupported = 1;
1090            ALOGI("%s: V4L2_PIX_FMT_MJPEG is supported", __func__ );
1091        }
1092        if(V4L2_PIX_FMT_H264 == fmtdesc.pixelformat){
1093            h264Supported = 1;
1094            ALOGI("%s: V4L2_PIX_FMT_H264 is supported", __func__ );
1095        }
1096
1097    }
1098
1099    /************************************************************************/
1100    /* - Based on the resolution, pick an apporpriate format                */
1101    /************************************************************************/
1102    //V4L2_PIX_FMT_MJPEG; V4L2_PIX_FMT_YUYV; V4L2_PIX_FMT_H264 = 0x34363248;
1103    camHal->captureFormat = V4L2_PIX_FMT_YUYV;
1104    if(camHal->prevWidth > 640){
1105        if(1 == mjpegSupported)
1106            camHal->captureFormat = V4L2_PIX_FMT_MJPEG;
1107        else if(1 == h264Supported)
1108            camHal->captureFormat = V4L2_PIX_FMT_H264;
1109    }
1110    ALOGI("%s: Capture format chosen: 0x%x. 0x%x:YUYV. 0x%x:MJPEG. 0x%x: H264",
1111        __func__, camHal->captureFormat, V4L2_PIX_FMT_YUYV,
1112        V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_H264);
1113
1114    return camHal->captureFormat;
1115}
1116
1117/******************************************************************************
1118 * Function: getMjpegdOutputFormat
1119 * Description: This function maps display pixel format enum to JPEG output
1120 *              format enum
1121 *
1122 * Input parameters:
1123 *   dispFormat              - Display pixel format
1124 *
1125 * Return values:
1126 *      (int)mjpegOutputFormat
1127 *
1128 * Notes: none
1129 *****************************************************************************/
1130static int getMjpegdOutputFormat(int dispFormat)
1131{
1132    int mjpegOutputFormat = YCRCBLP_H2V2;
1133
1134    if(HAL_PIXEL_FORMAT_YCrCb_420_SP == dispFormat)
1135        mjpegOutputFormat = YCRCBLP_H2V2;
1136
1137    return mjpegOutputFormat;
1138}
1139
1140/******************************************************************************
1141 * Function: ioctlLoop
1142 * Description: This function is a blocking call around ioctl
1143 *
1144 * Input parameters:
1145 *   fd             - IOCTL fd
1146 *   ioctlCmd       - IOCTL command
1147 *   args           - IOCTL arguments
1148 *
1149 * Return values:
1150 *      (int)mjpegOutputFormat
1151 *
1152 * Notes: none
1153 *****************************************************************************/
1154static int ioctlLoop(int fd, int ioctlCmd, void *args)
1155{
1156    int rc = -1;
1157
1158    while(1)
1159    {
1160        rc = ioctl(fd, ioctlCmd, args);
1161        if(!((-1 == rc) && (EINTR == errno)))
1162            break;
1163    }
1164    return rc;
1165}
1166
1167/******************************************************************************
1168 * Function: initV4L2mmap
1169 * Description: This function requests for V4L2 driver allocated buffers
1170 *
1171 * Input parameters:
1172 *   camHal              - camera HAL handle
1173 *
1174 * Return values:
1175 *   0      No error
1176 *   -1     Error
1177 *
1178 * Notes: none
1179 *****************************************************************************/
1180static int initV4L2mmap(camera_hardware_t *camHal)
1181{
1182    int rc = -1;
1183    struct v4l2_requestbuffers  reqBufs;
1184    struct v4l2_buffer          tempBuf;
1185
1186    ALOGD("%s: E", __func__);
1187    memset(&reqBufs, 0, sizeof(v4l2_requestbuffers));
1188    reqBufs.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1189    reqBufs.memory  = V4L2_MEMORY_MMAP;
1190    reqBufs.count   = PRVW_CAP_BUF_CNT;
1191
1192    if (-1 == ioctlLoop(camHal->fd, VIDIOC_REQBUFS, &reqBufs)) {
1193        if (EINVAL == errno) {
1194            ALOGE("%s: does not support memory mapping\n", __func__);
1195        } else {
1196            ALOGE("%s: VIDIOC_REQBUFS failed", __func__);
1197        }
1198    }
1199    ALOGD("%s: VIDIOC_REQBUFS success", __func__);
1200
1201    if (reqBufs.count < PRVW_CAP_BUF_CNT) {
1202        ALOGE("%s: Insufficient buffer memory on\n", __func__);
1203    }
1204
1205    camHal->buffers =
1206        ( bufObj* ) calloc(reqBufs.count, sizeof(bufObj));
1207
1208    if (!camHal->buffers) {
1209        ALOGE("%s: Out of memory\n", __func__);
1210    }
1211
1212    /* Store the indexes in the context. Useful during releasing */
1213    for (camHal->n_buffers = 0;
1214         camHal->n_buffers < reqBufs.count;
1215         camHal->n_buffers++) {
1216
1217        memset(&tempBuf, 0, sizeof(tempBuf));
1218
1219        tempBuf.index       = camHal->n_buffers;
1220        tempBuf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1221        tempBuf.memory      = V4L2_MEMORY_MMAP;
1222
1223        if (-1 == ioctlLoop(camHal->fd, VIDIOC_QUERYBUF, &tempBuf))
1224            ALOGE("%s: VIDIOC_QUERYBUF failed", __func__);
1225
1226        ALOGD("%s: VIDIOC_QUERYBUF success", __func__);
1227
1228        camHal->buffers[camHal->n_buffers].len = tempBuf.length;
1229        camHal->buffers[camHal->n_buffers].data =
1230        mmap(NULL /* start anywhere */,
1231                  tempBuf.length,
1232                  PROT_READ | PROT_WRITE,
1233                  MAP_SHARED,
1234                  camHal->fd, tempBuf.m.offset);
1235
1236        if (MAP_FAILED == camHal->buffers[camHal->n_buffers].data)
1237            ALOGE("%s: mmap failed", __func__);
1238    }
1239    ALOGD("%s: X", __func__);
1240    return 0;
1241}
1242
1243/******************************************************************************
1244 * Function: unInitV4L2mmap
1245 * Description: This function unmaps the V4L2 driver buffers
1246 *
1247 * Input parameters:
1248 *   camHal              - camera HAL handle
1249 *
1250 * Return values:
1251 *   0      No error
1252 *   -1     Error
1253 *
1254 * Notes: none
1255 *****************************************************************************/
1256static int unInitV4L2mmap(camera_hardware_t *camHal)
1257{
1258    int i, rc = 0;
1259    ALOGD("%s: E", __func__);
1260
1261    for (i = 0; i < camHal->n_buffers; i++)
1262        if (-1 == munmap(camHal->buffers[i].data, camHal->buffers[i].len)){
1263            ALOGE("%s: munmap failed for buffer: %d", __func__, i);
1264            rc = -1;
1265        }
1266
1267    ALOGD("%s: X", __func__);
1268    return rc;
1269}
1270
1271/******************************************************************************
1272 * Function: initUsbCamera
1273 * Description: This function sets the resolution and pixel format of the
1274 *              USB camera
1275 *
1276 * Input parameters:
1277 *  camHal              - camera HAL handle
1278 *  width               - picture width in pixels
1279 *  height              - picture height in pixels
1280 *  pixelFormat         - capture format for the camera
1281 *
1282 * Return values:
1283 *   0      No error
1284 *   -1     Error
1285 *
1286 * Notes: none
1287 *****************************************************************************/
1288static int initUsbCamera(camera_hardware_t *camHal, int width, int height,
1289                        int pixelFormat)
1290{
1291    int     rc = -1;
1292    struct  v4l2_capability     cap;
1293    struct  v4l2_cropcap        cropcap;
1294    struct  v4l2_crop           crop;
1295    struct  v4l2_format         v4l2format;
1296    unsigned int                min;
1297
1298    ALOGI("%s: E", __func__);
1299
1300    if (-1 == ioctlLoop(camHal->fd, VIDIOC_QUERYCAP, &cap)) {
1301        if (EINVAL == errno) {
1302            ALOGE( "%s: This is not V4L2 device\n", __func__);
1303            return -1;
1304        } else {
1305            ALOGE("%s: VIDIOC_QUERYCAP errno: %d", __func__, errno);
1306        }
1307    }
1308    ALOGD("%s: VIDIOC_QUERYCAP success", __func__);
1309
1310    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
1311        ALOGE("%s: This is not video capture device\n", __func__);
1312        return -1;
1313    }
1314
1315    if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
1316        ALOGE("%s: This does not support streaming i/o\n", __func__);
1317        return -1;
1318    }
1319
1320    /* Select video input, video standard and tune here. */
1321    memset(&cropcap, 0, sizeof(cropcap));
1322
1323    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1324
1325    if (0 == ioctlLoop(camHal->fd, VIDIOC_CROPCAP, &cropcap)) {
1326
1327        /* reset to default */
1328        crop.c = cropcap.defrect;
1329        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1330
1331        ALOGD("%s: VIDIOC_CROPCAP success", __func__);
1332        if (-1 == ioctlLoop(camHal->fd, VIDIOC_S_CROP, &crop)) {
1333        switch (errno) {
1334            case EINVAL:
1335            /* Cropping not supported. */
1336                break;
1337            default:
1338            /* Errors ignored. */
1339                break;
1340            }
1341        }
1342                ALOGD("%s: VIDIOC_S_CROP success", __func__);
1343
1344    } else {
1345        /* Errors ignored. */
1346               ALOGE("%s: VIDIOC_S_CROP failed", __func__);
1347    }
1348
1349
1350    memset(&v4l2format, 0, sizeof(v4l2format));
1351
1352    v4l2format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1353    {
1354        v4l2format.fmt.pix.field       = V4L2_FIELD_NONE;
1355        v4l2format.fmt.pix.pixelformat = pixelFormat;
1356        v4l2format.fmt.pix.width       = width;
1357        v4l2format.fmt.pix.height      = height;
1358
1359        if (-1 == ioctlLoop(camHal->fd, VIDIOC_S_FMT, &v4l2format))
1360        {
1361            ALOGE("%s: VIDIOC_S_FMT failed", __func__);
1362            return -1;
1363        }
1364        ALOGD("%s: VIDIOC_S_FMT success", __func__);
1365
1366        /* Note VIDIOC_S_FMT may change width and height. */
1367    }
1368
1369    /* TBR: In case of user pointer buffers, v4l2format.fmt.pix.sizeimage */
1370    /* might have to be calculated as per V4L2 sample application due to */
1371    /* open source driver bug */
1372
1373    rc = initV4L2mmap(camHal);
1374    ALOGI("%s: X", __func__);
1375    return rc;
1376}
1377
1378/******************************************************************************
1379 * Function: startUsbCamCapture
1380 * Description: This function queues buffer objects to the driver and sends
1381 *              STREAM ON command to the USB camera driver
1382 *
1383 * Input parameters:
1384 *   camHal              - camera HAL handle
1385 *
1386 * Return values:
1387 *   0      No error
1388 *   -1     Error
1389 *
1390 * Notes: none
1391 *****************************************************************************/
1392static int startUsbCamCapture(camera_hardware_t *camHal)
1393{
1394    int         rc = -1;
1395    unsigned    int i;
1396    enum        v4l2_buf_type   v4l2BufType;
1397    ALOGD("%s: E", __func__);
1398
1399    for (i = 0; i < camHal->n_buffers; ++i) {
1400        struct v4l2_buffer tempBuf;
1401
1402        memset(&tempBuf, 0, sizeof(tempBuf));
1403        tempBuf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1404        tempBuf.memory  = V4L2_MEMORY_MMAP;
1405        tempBuf.index   = i;
1406
1407        if (-1 == ioctlLoop(camHal->fd, VIDIOC_QBUF, &tempBuf))
1408            ALOGE("%s: VIDIOC_QBUF for %d buffer failed", __func__, i);
1409        else
1410            ALOGD("%s: VIDIOC_QBUF for %d buffer success", __func__, i);
1411    }
1412
1413    v4l2BufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1414    if (-1 == ioctlLoop(camHal->fd, VIDIOC_STREAMON, &v4l2BufType))
1415        ALOGE("%s: VIDIOC_STREAMON failed", __func__);
1416    else
1417    {
1418        ALOGD("%s: VIDIOC_STREAMON success", __func__);
1419        rc = 0;
1420    }
1421
1422    ALOGD("%s: X", __func__);
1423    return rc;
1424}
1425
1426/******************************************************************************
1427 * Function: stopUsbCamCapture
1428 * Description: This function sends STREAM OFF command to the USB camera driver
1429 *
1430 * Input parameters:
1431 *   camHal              - camera HAL handle
1432 *
1433 * Return values:
1434 *   0      No error
1435 *   -1     Error
1436 *
1437 * Notes: none
1438 *****************************************************************************/
1439static int stopUsbCamCapture(camera_hardware_t *camHal)
1440{
1441    int         rc = -1;
1442    unsigned    int i;
1443    enum        v4l2_buf_type   v4l2BufType;
1444    ALOGD("%s: E", __func__);
1445
1446    if(!camHal->fd){
1447        ALOGE("%s: camHal->fd = NULL ", __func__);
1448        return -1;
1449    }
1450    v4l2BufType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1451    if (-1 == ioctlLoop(camHal->fd, VIDIOC_STREAMOFF, &v4l2BufType)){
1452        ALOGE("%s: VIDIOC_STREAMOFF failed", __func__);
1453        rc = -1;
1454    }else{
1455        ALOGD("%s: VIDIOC_STREAMOFF success", __func__);
1456        rc = 0;
1457    }
1458
1459    ALOGD("%s: X", __func__);
1460    return rc;
1461}
1462
1463/******************************************************************************
1464 * Function: stopPreviewInternal
1465 * Description: This function sends EXIT command to prview loop thread,
1466 *              stops usb camera capture and uninitializes MMAP. This function
1467 *              assumes that calling function has locked camHal->lock
1468 *
1469 * Input parameters:
1470 *   camHal              - camera HAL handle
1471 *
1472 * Return values:
1473 *   0      No error
1474 *   -1     Error
1475 *
1476 * Notes: none
1477 *****************************************************************************/
1478static int stopPreviewInternal(camera_hardware_t *camHal)
1479{
1480    int rc = 0;
1481    ALOGD("%s: E", __func__);
1482
1483    if(camHal->previewEnabledFlag)
1484    {
1485        camHal->prvwCmdPending++;
1486        camHal->prvwCmd         = USB_CAM_PREVIEW_EXIT;
1487
1488        /* yield lock while waiting for the preview thread to exit */
1489        camHal->lock.unlock();
1490        if(pthread_join(camHal->previewThread, NULL)){
1491            ALOGE("%s: Error in pthread_join preview thread", __func__);
1492        }
1493        camHal->lock.lock();
1494
1495        if(stopUsbCamCapture(camHal)){
1496            ALOGE("%s: Error in stopUsbCamCapture", __func__);
1497            rc = -1;
1498        }
1499        if(unInitV4L2mmap(camHal)){
1500            ALOGE("%s: Error in stopUsbCamCapture", __func__);
1501            rc = -1;
1502        }
1503        camHal->previewEnabledFlag = 0;
1504    }
1505
1506    ALOGD("%s: X, rc: %d", __func__, rc);
1507    return rc;
1508}
1509#if 1
1510/******************************************************************************
1511 * Function: prvwThreadTakePictureInternal
1512 * Description: This function processes one camera frame to get JPEG encoded
1513 *              picture.
1514 *
1515 * Input parameters:
1516 *   camHal              - camera HAL handle
1517 *
1518 * Return values:
1519 *   0      No error
1520 *   -1     Error
1521 *
1522 * Notes: none
1523 *****************************************************************************/
1524static int prvwThreadTakePictureInternal(camera_hardware_t *camHal)
1525{
1526    int     rc = 0;
1527    QCameraHalMemInfo_t     *mem_info;
1528    ALOGD("%s: E", __func__);
1529
1530    /************************************************************************/
1531    /* - If requested for shutter notfication, callback                     */
1532    /* - Dequeue capture buffer from USB camera                             */
1533    /* - Send capture buffer to JPEG encoder for JPEG compression           */
1534    /* - If jpeg frames callback is requested, callback with jpeg buffers   */
1535    /* - Enqueue capture buffer back to USB camera                          */
1536    /************************************************************************/
1537
1538    /************************************************************************/
1539    /* - If requested for shutter notfication, callback                     */
1540    /************************************************************************/
1541    if (camHal->msgEnabledFlag & CAMERA_MSG_SHUTTER){
1542        camHal->lock.unlock();
1543        camHal->notify_cb(CAMERA_MSG_SHUTTER, 0, 0, camHal->cb_ctxt);
1544        camHal->lock.lock();
1545    }
1546
1547#if CAPTURE
1548    /************************************************************************/
1549    /* - Dequeue capture buffer from USB camera                             */
1550    /************************************************************************/
1551    if (0 == get_buf_from_cam(camHal))
1552        ALOGD("%s: get_buf_from_cam success", __func__);
1553    else
1554        ALOGE("%s: get_buf_from_cam error", __func__);
1555#endif
1556
1557    /************************************************************************/
1558    /* - Send capture buffer to JPEG encoder for JPEG compression           */
1559    /************************************************************************/
1560    /* Optimization: If camera capture is JPEG format, need not compress! */
1561    /* instead, just data copy from capture buffer to picture buffer */
1562    if(V4L2_PIX_FMT_MJPEG == camHal->captureFormat){
1563        /* allocate heap memory for JPEG output */
1564        mem_info = &camHal->pictMem.mem_info[0];
1565        mem_info->size = camHal->curCaptureBuf.bytesused;
1566        /* TBD: allocate_ion_memory
1567        rc = QCameraHardwareInterface::allocate_ion_memory(mem_info,
1568                            ((0x1 << CAMERA_ZSL_ION_HEAP_ID) |
1569                            (0x1 << CAMERA_ZSL_ION_FALLBACK_HEAP_ID)));
1570        */
1571        if(rc)
1572            ALOGE("%s: ION memory allocation failed", __func__);
1573
1574        camHal->pictMem.camera_memory[0] = camHal->get_memory(
1575                            mem_info->fd, mem_info->size, 1, camHal->cb_ctxt);
1576        if(!camHal->pictMem.camera_memory[0])
1577            ALOGE("%s: get_mem failed", __func__);
1578
1579        memcpy( camHal->pictMem.camera_memory[0]->data,
1580                (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
1581                camHal->curCaptureBuf.bytesused);
1582    }
1583
1584    /************************************************************************/
1585    /* - If jpeg frames callback is requested, callback with jpeg buffers   */
1586    /************************************************************************/
1587    if ((camHal->msgEnabledFlag & CAMERA_MSG_COMPRESSED_IMAGE) &&
1588            (camHal->data_cb)){
1589        camHal->lock.unlock();
1590        camHal->data_cb(CAMERA_MSG_COMPRESSED_IMAGE,
1591                        camHal->pictMem.camera_memory[0],
1592                        0, NULL, camHal->cb_ctxt);
1593        camHal->lock.lock();
1594    }
1595    /* release heap memory after the call back */
1596    if(camHal->pictMem.camera_memory[0])
1597        camHal->pictMem.camera_memory[0]->release(
1598            camHal->pictMem.camera_memory[0]);
1599
1600    /* TBD: deallocate_ion_memory */
1601    //rc = QCameraHardwareInterface::deallocate_ion_memory(mem_info);
1602    if(rc)
1603        ALOGE("%s: ION memory de-allocation failed", __func__);
1604
1605#if CAPTURE
1606    /************************************************************************/
1607    /* - Enqueue capture buffer back to USB camera                          */
1608    /************************************************************************/
1609       if(0 == put_buf_to_cam(camHal)) {
1610            ALOGD("%s: put_buf_to_cam success", __func__);
1611        }
1612        else
1613            ALOGE("%s: put_buf_to_cam error", __func__);
1614#endif
1615
1616    ALOGD("%s: X, rc: %d", __func__, rc);
1617    return rc;
1618}
1619#endif //#if 0
1620/******************************************************************************
1621 * Function: cache_ops
1622 * Description: This function calls ION ioctl for cache related operations
1623 *
1624 * Input parameters:
1625 *  mem_info                - QCameraHalMemInfo_t structure with ION info
1626 *  buf_ptr                 - Buffer pointer that needs to be cache operated
1627 *  cmd                     - Cache command - clean/invalidate
1628 *
1629 * Return values:
1630 *   MM_CAMERA_OK       No error
1631 *   -1                 Error
1632 *
1633 * Notes: none
1634 *****************************************************************************/
1635int cache_ops(QCameraHalMemInfo_t *mem_info,
1636                                    void *buf_ptr,
1637                                    unsigned int cmd)
1638{
1639    struct ion_flush_data cache_inv_data;
1640    struct ion_custom_data custom_data;
1641    int ret = MM_CAMERA_OK;
1642
1643#ifdef USE_ION
1644    if (NULL == mem_info) {
1645        ALOGE("%s: mem_info is NULL, return here", __func__);
1646        return -1;
1647    }
1648
1649    memset(&cache_inv_data, 0, sizeof(cache_inv_data));
1650    memset(&custom_data, 0, sizeof(custom_data));
1651    cache_inv_data.vaddr = buf_ptr;
1652    cache_inv_data.fd = mem_info->fd;
1653    cache_inv_data.handle = mem_info->handle;
1654    cache_inv_data.length = mem_info->size;
1655    custom_data.cmd = cmd;
1656    custom_data.arg = (unsigned long)&cache_inv_data;
1657
1658    ALOGD("%s: addr = %p, fd = %d, handle = %p length = %d, ION Fd = %d",
1659         __func__, cache_inv_data.vaddr, cache_inv_data.fd,
1660         cache_inv_data.handle, cache_inv_data.length,
1661         mem_info->main_ion_fd);
1662    if(mem_info->main_ion_fd > 0) {
1663        if(ioctl(mem_info->main_ion_fd, ION_IOC_CUSTOM, &custom_data) < 0) {
1664            ALOGE("%s: Cache Invalidate failed\n", __func__);
1665            ret = -1;
1666        }
1667    }
1668#endif
1669
1670    return ret;
1671}
1672
1673/******************************************************************************
1674 * Function: get_buf_from_cam
1675 * Description: This funtions gets/acquires 1 capture buffer from the camera
1676 *              driver. The fetched buffer is stored in curCaptureBuf
1677 *
1678 * Input parameters:
1679 *   camHal              - camera HAL handle
1680 *
1681 * Return values:
1682 *   0      No error
1683 *   -1     Error
1684 *
1685 * Notes: none
1686 *****************************************************************************/
1687static int get_buf_from_cam(camera_hardware_t *camHal)
1688{
1689    int rc = -1;
1690
1691    ALOGD("%s: E", __func__);
1692    {
1693        memset(&camHal->curCaptureBuf, 0, sizeof(camHal->curCaptureBuf));
1694
1695        camHal->curCaptureBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1696        camHal->curCaptureBuf.memory = V4L2_MEMORY_MMAP;
1697
1698        if (-1 == ioctlLoop(camHal->fd, VIDIOC_DQBUF, &camHal->curCaptureBuf)){
1699            switch (errno) {
1700            case EAGAIN:
1701                ALOGE("%s: EAGAIN error", __func__);
1702                return 1;
1703
1704            case EIO:
1705            /* Could ignore EIO, see spec. */
1706
1707            /* fall through */
1708
1709            default:
1710            ALOGE("%s: VIDIOC_DQBUF error", __func__);
1711            }
1712        }
1713        else
1714        {
1715            rc = 0;
1716            ALOGD("%s: VIDIOC_DQBUF: %d successful, %d bytes",
1717                 __func__, camHal->curCaptureBuf.index,
1718                 camHal->curCaptureBuf.bytesused);
1719        }
1720    }
1721    ALOGD("%s: X", __func__);
1722    return rc;
1723}
1724
1725/******************************************************************************
1726 * Function: put_buf_to_cam
1727 * Description: This funtion puts/releases 1 capture buffer back to the camera
1728 *              driver
1729 *
1730 * Input parameters:
1731 *   camHal              - camera HAL handle
1732 *
1733 * Return values:
1734 *   0      No error
1735 *   -1     Error
1736 *
1737 * Notes: none
1738 *****************************************************************************/
1739static int put_buf_to_cam(camera_hardware_t *camHal)
1740{
1741    ALOGD("%s: E", __func__);
1742
1743    camHal->curCaptureBuf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1744    camHal->curCaptureBuf.memory      = V4L2_MEMORY_MMAP;
1745
1746
1747    if (-1 == ioctlLoop(camHal->fd, VIDIOC_QBUF, &camHal->curCaptureBuf))
1748    {
1749        ALOGE("%s: VIDIOC_QBUF failed ", __func__);
1750        return 1;
1751    }
1752    ALOGD("%s: X", __func__);
1753    return 0;
1754}
1755
1756/******************************************************************************
1757 * Function: put_buf_to_cam
1758 * Description: This funtion gets/acquires 1 display buffer from the display
1759 *              window
1760 *
1761 * Input parameters:
1762 *  camHal                  - camera HAL handle
1763 *  buffer_id               - Buffer id pointer. The id of buffer obtained
1764 *                              by this function is returned in this arg
1765 *
1766 * Return values:
1767 *   0      No error
1768 *   -1     Error
1769 *
1770 * Notes: none
1771 *****************************************************************************/
1772static int get_buf_from_display(camera_hardware_t *camHal, int *buffer_id)
1773{
1774    int                     err = 0;
1775    preview_stream_ops      *mPreviewWindow = NULL;
1776    int                     stride = 0, cnt = 0;
1777    buffer_handle_t         *buffer_handle = NULL;
1778    struct private_handle_t *private_buffer_handle = NULL;
1779
1780    ALOGD("%s: E", __func__);
1781
1782    if (camHal == NULL) {
1783        ALOGE("%s: camHal = NULL", __func__);
1784        return -1;
1785    }
1786
1787    mPreviewWindow = camHal->window;
1788    if( mPreviewWindow == NULL) {
1789        ALOGE("%s: mPreviewWindow = NULL", __func__);
1790        return -1;
1791    }
1792    err = mPreviewWindow->dequeue_buffer(mPreviewWindow,
1793                                    &buffer_handle,
1794                                    &stride);
1795    if(!err) {
1796        ALOGD("%s: dequeue buf buffer_handle: %p\n", __func__, buffer_handle);
1797
1798        ALOGD("%s: mPreviewWindow->lock_buffer: %p",
1799             __func__, mPreviewWindow->lock_buffer);
1800        if(mPreviewWindow->lock_buffer) {
1801            err = mPreviewWindow->lock_buffer(mPreviewWindow, buffer_handle);
1802            ALOGD("%s: mPreviewWindow->lock_buffer success", __func__);
1803        }
1804        ALOGD("%s: camera call genlock_lock, hdl=%p",
1805             __func__, (*buffer_handle));
1806
1807        if (GENLOCK_NO_ERROR !=
1808            genlock_lock_buffer((native_handle_t *)(*buffer_handle),
1809                                GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) {
1810           ALOGE("%s: genlock_lock_buffer(WRITE) failed", __func__);
1811       } else {
1812         ALOGD("%s: genlock_lock_buffer hdl =%p", __func__, *buffer_handle);
1813       }
1814
1815        private_buffer_handle = (struct private_handle_t *)(*buffer_handle);
1816
1817        ALOGD("%s: fd = %d, size = %d, offset = %d, stride = %d",
1818             __func__, private_buffer_handle->fd,
1819        private_buffer_handle->size, private_buffer_handle->offset, stride);
1820
1821        for(cnt = 0; cnt < camHal->previewMem.buffer_count + 2; cnt++) {
1822            if(private_buffer_handle->fd ==
1823               camHal->previewMem.private_buffer_handle[cnt]->fd) {
1824                *buffer_id = cnt;
1825                ALOGD("%s: deQueued fd = %d, index: %d",
1826                     __func__, private_buffer_handle->fd, cnt);
1827                break;
1828            }
1829        }
1830    }
1831    else
1832        ALOGE("%s: dequeue buf failed \n", __func__);
1833
1834    ALOGD("%s: X", __func__);
1835
1836    return err;
1837}
1838
1839/******************************************************************************
1840 * Function: put_buf_to_display
1841 * Description: This funtion puts/enqueues 1 buffer back to the display window
1842 *
1843 * Input parameters:
1844 *  camHal                  - camera HAL handle
1845 *  buffer_id               - id of the buffer that needs to be enqueued
1846 *
1847 * Return values:
1848 *   0      No error
1849 *   -1     Error
1850 *
1851 * Notes: none
1852 *****************************************************************************/
1853static int put_buf_to_display(camera_hardware_t *camHal, int buffer_id)
1854{
1855    int err = 0;
1856    preview_stream_ops    *mPreviewWindow;
1857
1858    ALOGD("%s: E", __func__);
1859
1860    if (camHal == NULL) {
1861        ALOGE("%s: camHal = NULL", __func__);
1862        return -1;
1863    }
1864
1865    mPreviewWindow = camHal->window;
1866    if( mPreviewWindow == NULL) {
1867        ALOGE("%s: mPreviewWindow = NULL", __func__);
1868        return -1;
1869    }
1870
1871    if (GENLOCK_FAILURE ==
1872        genlock_unlock_buffer(
1873            (native_handle_t *)
1874            (*(camHal->previewMem.buffer_handle[buffer_id])))) {
1875       ALOGE("%s: genlock_unlock_buffer failed: hdl =%p",
1876            __func__, (*(camHal->previewMem.buffer_handle[buffer_id])) );
1877    } else {
1878      ALOGD("%s: genlock_unlock_buffer success: hdl =%p",
1879           __func__, (*(camHal->previewMem.buffer_handle[buffer_id])) );
1880    }
1881
1882    /* Cache clean the output buffer so that cache is written back */
1883    cache_ops(&camHal->previewMem.mem_info[buffer_id],
1884                         (void *)camHal->previewMem.camera_memory[buffer_id]->data,
1885                         ION_IOC_CLEAN_CACHES);
1886                         /*
1887    cache_ops(&camHal->previewMem.mem_info[buffer_id],
1888                         (void *)camHal->previewMem.camera_memory[buffer_id]->data,
1889                         ION_IOC_CLEAN_INV_CACHES);
1890*/
1891    err = mPreviewWindow->enqueue_buffer(mPreviewWindow,
1892      (buffer_handle_t *)camHal->previewMem.buffer_handle[buffer_id]);
1893    if(!err) {
1894        ALOGD("%s: enqueue buf successful: %p\n",
1895             __func__, camHal->previewMem.buffer_handle[buffer_id]);
1896    }else
1897        ALOGE("%s: enqueue buf failed: %p\n",
1898             __func__, camHal->previewMem.buffer_handle[buffer_id]);
1899
1900    ALOGD("%s: X", __func__);
1901
1902    return err;
1903}
1904
1905/******************************************************************************
1906 * Function: put_buf_to_display
1907 * Description: This funtion transfers the content from capture buffer to
1908 *              preiew display buffer after appropriate conversion
1909 *
1910 * Input parameters:
1911 *  camHal                  - camera HAL handle
1912 *  buffer_id               - id of the buffer that needs to be enqueued
1913 *
1914 * Return values:
1915 *   0      No error
1916 *   -1     Error
1917 *
1918 * Notes: none
1919 *****************************************************************************/
1920static int convert_data_frm_cam_to_disp(camera_hardware_t *camHal, int buffer_id)
1921{
1922    int rc = -1;
1923
1924    if(!camHal) {
1925        ALOGE("%s: camHal is NULL", __func__);
1926        return -1;
1927    }
1928    /* If input and output are raw formats, but different color format, */
1929    /* call color conversion routine                                    */
1930    if( (V4L2_PIX_FMT_YUYV == camHal->captureFormat) &&
1931        (HAL_PIXEL_FORMAT_YCrCb_420_SP == camHal->dispFormat))
1932    {
1933        convert_YUYV_to_420_NV12(
1934            (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
1935            (char *)camHal->previewMem.camera_memory[buffer_id]->data,
1936            camHal->prevWidth,
1937            camHal->prevHeight);
1938        ALOGD("%s: Copied %d bytes from camera buffer %d to display buffer: %d",
1939             __func__, camHal->curCaptureBuf.bytesused,
1940             camHal->curCaptureBuf.index, buffer_id);
1941        rc = 0;
1942    }
1943
1944    /* If camera buffer is MJPEG encoded, call mjpeg decode call */
1945    if(V4L2_PIX_FMT_MJPEG == camHal->captureFormat)
1946    {
1947        if(NULL == camHal->mjpegd)
1948        {
1949            rc = mjpegDecoderInit(&camHal->mjpegd);
1950            if(rc < 0)
1951                ALOGE("%s: mjpegDecoderInit Error: %d", __func__, rc);
1952        }
1953        if(camHal->mjpegd)
1954        {
1955            rc = mjpegDecode(
1956                (void*)camHal->mjpegd,
1957                (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
1958                camHal->curCaptureBuf.bytesused,
1959                (char *)camHal->previewMem.camera_memory[buffer_id]->data,
1960                (char *)camHal->previewMem.camera_memory[buffer_id]->data +
1961                    camHal->prevWidth * camHal->prevHeight,
1962                getMjpegdOutputFormat(camHal->dispFormat));
1963            if(rc < 0)
1964                ALOGE("%s: mjpegDecode Error: %d", __func__, rc);
1965        }
1966    }
1967    return rc;
1968}
1969
1970/******************************************************************************
1971 * Function: launch_preview_thread
1972 * Description: This is a wrapper function to start preview thread
1973 *
1974 * Input parameters:
1975 *  camHal                  - camera HAL handle
1976 *
1977 * Return values:
1978 *   0      No error
1979 *   -1     Error
1980 *
1981 * Notes: none
1982 *****************************************************************************/
1983static int launch_preview_thread(camera_hardware_t *camHal)
1984{
1985    ALOGD("%s: E", __func__);
1986    int rc = 0;
1987
1988    if(!camHal) {
1989        ALOGE("%s: camHal is NULL", __func__);
1990        return -1;
1991    }
1992
1993    pthread_attr_t attr;
1994    pthread_attr_init(&attr);
1995    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1996    pthread_create(&camHal->previewThread, &attr, previewloop, camHal);
1997
1998    ALOGD("%s: X", __func__);
1999    return rc;
2000}
2001
2002/******************************************************************************
2003 * Function: launch_preview_thread
2004 * Description: This is thread funtion for preivew loop
2005 *
2006 * Input parameters:
2007 *  hcamHal                 - camera HAL handle
2008 *
2009 * Return values:
2010 *   0      No error
2011 *   -1     Error
2012 *
2013 * Notes: none
2014 *****************************************************************************/
2015static void * previewloop(void *hcamHal)
2016{
2017    int                 rc;
2018    int                 buffer_id   = 0;
2019    pid_t               tid         = 0;
2020    camera_hardware_t   *camHal     = NULL;
2021    int                 msgType     = 0;
2022    camera_memory_t     *data       = NULL;
2023    camera_frame_metadata_t *metadata= NULL;
2024    camera_memory_t     *previewMem = NULL;
2025
2026    camHal = (camera_hardware_t *)hcamHal;
2027    ALOGD("%s: E", __func__);
2028
2029    if(!camHal) {
2030        ALOGE("%s: camHal is NULL", __func__);
2031        return NULL ;
2032    }
2033
2034    tid  = gettid();
2035    /* TBR: Set appropriate thread priority */
2036    androidSetThreadPriority(tid, ANDROID_PRIORITY_NORMAL);
2037    prctl(PR_SET_NAME, (unsigned long)"Camera HAL preview thread", 0, 0, 0);
2038
2039    /************************************************************************/
2040    /* - Time wait (select) on camera fd for input read buffer              */
2041    /* - Check if any preview thread commands are set. If set, process      */
2042    /* - Dequeue display buffer from surface                                */
2043    /* - Dequeue capture buffer from USB camera                             */
2044    /* - Convert capture format to display format                           */
2045    /* - If preview frames callback is requested, callback with prvw buffers*/
2046    /* - Enqueue display buffer back to surface                             */
2047    /* - Enqueue capture buffer back to USB camera                          */
2048    /************************************************************************/
2049    while(1) {
2050        fd_set fds;
2051        struct timeval tv;
2052        int r = 0;
2053
2054        FD_ZERO(&fds);
2055#if CAPTURE
2056        FD_SET(camHal->fd, &fds);
2057#endif /* CAPTURE */
2058
2059    /************************************************************************/
2060    /* - Time wait (select) on camera fd for input read buffer              */
2061    /************************************************************************/
2062        tv.tv_sec = 0;
2063        tv.tv_usec = 500000;
2064
2065        ALOGD("%s: b4 select on camHal->fd + 1,fd: %d", __func__, camHal->fd);
2066#if CAPTURE
2067        r = select(camHal->fd + 1, &fds, NULL, NULL, &tv);
2068#else
2069        r = select(1, NULL, NULL, NULL, &tv);
2070#endif /* CAPTURE */
2071        ALOGD("%s: after select : %d", __func__, camHal->fd);
2072
2073        if (-1 == r) {
2074            if (EINTR == errno)
2075                continue;
2076            ALOGE("%s: FDSelect error: %d", __func__, errno);
2077        }
2078
2079        if (0 == r) {
2080            ALOGD("%s: select timeout\n", __func__);
2081        }
2082
2083        /* Protect the context for one iteration of preview loop */
2084        /* this gets unlocked at the end of the while */
2085        Mutex::Autolock autoLock(camHal->lock);
2086
2087    /************************************************************************/
2088    /* - Check if any preview thread commands are set. If set, process      */
2089    /************************************************************************/
2090        if(camHal->prvwCmdPending)
2091        {
2092            /* command is serviced. Hence command pending = 0  */
2093            camHal->prvwCmdPending--;
2094            //sempost(ack)
2095            if(USB_CAM_PREVIEW_EXIT == camHal->prvwCmd){
2096                /* unlock before exiting the thread */
2097                camHal->lock.unlock();
2098                ALOGI("%s: Exiting coz USB_CAM_PREVIEW_EXIT", __func__);
2099                return (void *)0;
2100            }else if(USB_CAM_PREVIEW_TAKEPIC == camHal->prvwCmd){
2101                rc = prvwThreadTakePictureInternal(camHal);
2102                if(rc)
2103                    ALOGE("%s: prvwThreadTakePictureInternal returned error",
2104                    __func__);
2105            }
2106        }
2107
2108        /* Null check on preview window. If null, sleep */
2109        if(!camHal->window) {
2110            ALOGD("%s: sleeping coz camHal->window = NULL",__func__);
2111            camHal->lock.unlock();
2112            sleep(2);
2113            continue;
2114        }
2115#if DISPLAY
2116    /************************************************************************/
2117    /* - Dequeue display buffer from surface                                */
2118    /************************************************************************/
2119        if(0 == get_buf_from_display(camHal, &buffer_id)) {
2120            ALOGD("%s: get_buf_from_display success: %d",
2121                 __func__, buffer_id);
2122        }else{
2123            ALOGE("%s: get_buf_from_display failed. Skipping the loop",
2124                 __func__);
2125            continue;
2126        }
2127#endif
2128
2129#if CAPTURE
2130    /************************************************************************/
2131    /* - Dequeue capture buffer from USB camera                             */
2132    /************************************************************************/
2133        if (0 == get_buf_from_cam(camHal))
2134            ALOGD("%s: get_buf_from_cam success", __func__);
2135        else
2136            ALOGE("%s: get_buf_from_cam error", __func__);
2137#endif
2138
2139#if FILE_DUMP_CAMERA
2140        /* Debug code to dump frames from camera */
2141        {
2142            static int frame_cnt = 0;
2143            /* currently hardcoded for Bytes-Per-Pixel = 1.5 */
2144            fileDump("/data/USBcam.yuv",
2145            (char*)camHal->buffers[camHal->curCaptureBuf.index].data,
2146            camHal->prevWidth * camHal->prevHeight * 1.5,
2147            &frame_cnt);
2148        }
2149#endif
2150
2151#if MEMSET
2152        static int color = 30;
2153        color += 50;
2154        if(color > 200) {
2155            color = 30;
2156        }
2157        ALOGE("%s: Setting to the color: %d\n", __func__, color);
2158        /* currently hardcoded for format of type Bytes-Per-Pixel = 1.5 */
2159        memset(camHal->previewMem.camera_memory[buffer_id]->data,
2160               color, camHal->dispWidth * camHal->dispHeight * 1.5 + 2 * 1024);
2161#else
2162        convert_data_frm_cam_to_disp(camHal, buffer_id);
2163        ALOGD("%s: Copied data to buffer_id: %d", __func__, buffer_id);
2164#endif
2165
2166#if FILE_DUMP_B4_DISP
2167        /* Debug code to dump display buffers */
2168        {
2169            static int frame_cnt = 0;
2170            /* currently hardcoded for Bytes-Per-Pixel = 1.5 */
2171            fileDump("/data/display.yuv",
2172                (char*) camHal->previewMem.camera_memory[buffer_id]->data,
2173                camHal->dispWidth * camHal->dispHeight * 1.5,
2174                &frame_cnt);
2175            ALOGD("%s: Written buf_index: %d ", __func__, buffer_id);
2176        }
2177#endif
2178
2179#if DISPLAY
2180    /************************************************************************/
2181    /* - Enqueue display buffer back to surface                             */
2182    /************************************************************************/
2183       if(0 == put_buf_to_display(camHal, buffer_id)) {
2184            ALOGD("%s: put_buf_to_display success: %d", __func__, buffer_id);
2185        }
2186        else
2187            ALOGE("%s: put_buf_to_display error", __func__);
2188#endif
2189
2190#if CAPTURE
2191     /************************************************************************/
2192    /* - Enqueue capture buffer back to USB camera                          */
2193    /************************************************************************/
2194       if(0 == put_buf_to_cam(camHal)) {
2195            ALOGD("%s: put_buf_to_cam success", __func__);
2196        }
2197        else
2198            ALOGE("%s: put_buf_to_cam error", __func__);
2199#endif
2200
2201#if CALL_BACK
2202    /************************************************************************/
2203    /* - If preview frames callback is requested, callback with prvw buffers*/
2204    /************************************************************************/
2205        /* TBD: change the 1.5 hardcoding to Bytes Per Pixel */
2206        int previewBufSize = camHal->prevWidth * camHal->prevHeight * 1.5;
2207
2208        msgType |=  CAMERA_MSG_PREVIEW_FRAME;
2209
2210        if(previewBufSize !=
2211            camHal->previewMem.private_buffer_handle[buffer_id]->size) {
2212
2213            previewMem = camHal->get_memory(
2214                camHal->previewMem.private_buffer_handle[buffer_id]->fd,
2215                previewBufSize,
2216                1,
2217                camHal->cb_ctxt);
2218
2219              if (!previewMem || !previewMem->data) {
2220                  ALOGE("%s: get_memory failed.\n", __func__);
2221              }
2222              else {
2223                  data = previewMem;
2224                  ALOGD("%s: GetMemory successful. data = %p",
2225                            __func__, data);
2226                  ALOGD("%s: previewBufSize = %d, priv_buf_size: %d",
2227                    __func__, previewBufSize,
2228                    camHal->previewMem.private_buffer_handle[buffer_id]->size);
2229              }
2230        }
2231        else{
2232            data =   camHal->previewMem.camera_memory[buffer_id];
2233            ALOGD("%s: No GetMemory, no invalid fmt. data = %p, idx=%d",
2234                __func__, data, buffer_id);
2235        }
2236        /* Unlock and lock around the callback. */
2237        /* Sometimes 'disable_msg' is issued in the callback context, */
2238        /* leading to deadlock */
2239        camHal->lock.unlock();
2240        if((camHal->msgEnabledFlag & CAMERA_MSG_PREVIEW_FRAME) &&
2241            camHal->data_cb){
2242            ALOGD("%s: before data callback", __func__);
2243            camHal->data_cb(msgType, data, 0,metadata, camHal->cb_ctxt);
2244            ALOGD("%s: after data callback: %p", __func__, camHal->data_cb);
2245        }
2246        camHal->lock.lock();
2247        if (previewMem)
2248            previewMem->release(previewMem);
2249#endif
2250
2251    }//while(1)
2252    ALOGD("%s: X", __func__);
2253    return (void *)0;
2254}
2255
2256/******************************************************************************
2257 * Function: get_uvc_device
2258 * Description: This function loops through /dev/video entries and probes with
2259 *              UVCIOC query. If the device responds to the query, then it is
2260 *              detected as UVC webcam
2261 * Input parameters:
2262 *   devname             - String pointer. The function return dev entry
2263 *                          name in this string
2264 * Return values:
2265 *      0   Success
2266 *      -1  Error
2267 * Notes: none
2268 *****************************************************************************/
2269static int get_uvc_device(char *devname)
2270{
2271    char    temp_devname[FILENAME_LENGTH];
2272    FILE    *fp = NULL;
2273    int     i = 0, ret = 0, fd;
2274
2275    ALOGD("%s: E", __func__);
2276#if 1
2277    strncpy(devname, "/dev/video1", FILENAME_LENGTH);
2278
2279/*
2280    struct          stat st;
2281
2282    strncpy(dev_name, "/dev/video1", FILENAME_LENGTH);
2283    if (-1 == stat(dev_name, &st)) {
2284        ALOGE("%s: Cannot identify '%s': %d, %s\n",
2285             __func__, dev_name, errno, strerror(errno));
2286    }
2287
2288    if (!S_ISCHR(st.st_mode)) {
2289        ALOGE("%s: %s is no device\n", __func__, dev_name);
2290        rc = -1;
2291    }
2292*/
2293
2294#else
2295
2296    *devname = '\0';
2297    /************************************************************************/
2298    /* - List all /dev/video* entries to a file                             */
2299    /* - Open the video list file and loop through the list                 */
2300    /* - Send UVC specific control query and check the response             */
2301    /* - If device responds to the query as success, device is UVC webcam   */
2302    /************************************************************************/
2303
2304    /************************************************************************/
2305    /* - List all /dev/video* entries to a file                             */
2306    /************************************************************************/
2307    /* Temporarily commented out. This logic doesnt seem to be working */
2308    //system("ls > /data/video_dev_list");
2309
2310    /************************************************************************/
2311    /* - Open the video list file and loop through the list                 */
2312    /************************************************************************/
2313
2314    /* Temporarily commented out. This logic doesnt seem to be working */
2315    /*
2316    fp = fopen("/data/video_dev_list", "rb");
2317    if(!fp) {
2318        ALOGE("%s: Error in opening /data/video_dev_list ", __func__);
2319        return -1;
2320    }
2321    */
2322
2323    /* Temporarily commented out. Looping logic changed due to issue in */
2324    /* executing system("ls > /data/video_dev_list") */
2325    //while(EOF != fscanf(fp, "%s", devname)){
2326    while(1){
2327        uvc_xu_control_query    xqry;
2328
2329        sprintf(temp_devname, "/dev/video%d", i);
2330        ALOGD("%s: Probing %s \n", __func__, temp_devname);
2331
2332        fd = open(temp_devname, O_RDWR /* required */ | O_NONBLOCK, 0);
2333        if(-1 != fd){
2334            memset(&xqry, 0, sizeof(uvc_xu_control_query));
2335            ret = ioctl(fd, UVCIOC_CTRL_QUERY, &xqry);
2336            ALOGD("%s: UVCIOC ret: %d, errno: %d", __func__, ret, errno);
2337            /****************************************************************/
2338            /* if UVCIOC is executed successfully, ret = 0                  */
2339            /* if UVCIOC is executed but Control Unit = 0 does not exist,   */
2340            /*      ret = -1 and errno = ENOENT                             */
2341            /* if UVCIOC doesnot execute, ret = -1 and errno = EINVAL       */
2342            /****************************************************************/
2343            if((0 == ret) || (ret && (ENOENT == errno))){
2344                ALOGD("%s: Found UVC node: %s\n", __func__, temp_devname);
2345                strncpy(devname, temp_devname, FILENAME_LENGTH);
2346                /* Exit the loop at the first UVC node detection */
2347                break;
2348            }
2349            close(fd);
2350        }
2351        /* Temporarily logic to probe video0 to video10 nodes */
2352        if(i++ > 10)
2353        {
2354            if(fp)
2355                fclose(fp);
2356            break;
2357        }
2358    }
2359#endif /* #if 0 */
2360    ALOGD("%s: X", __func__);
2361    return 0;
2362} /* get_uvc_device */
2363
2364/******************************************************************************
2365 * Function: fileDump
2366 * Description: This is a utility function to dump buffers into a file
2367 *
2368 * Input parameters:
2369 *  fn              - File name string
2370 *  data            - pointer to character buffer that needs to be dumped
2371 *  length          - Length of the buffer to be dumped
2372 *  frm_cnt         - Pointer to frame count. This count is incremented by this
2373 *                      function on successful file write
2374 * Return values:
2375 *      0   Success
2376 *      -1  Error
2377 * Notes: none
2378 *****************************************************************************/
2379static int fileDump(const char* fn, char* data, int length, int* frm_cnt)
2380{
2381
2382    FILE *fp = NULL;
2383    if (0 == *frm_cnt) {
2384        fp = fopen(fn, "wb");
2385        if (NULL == fp) {
2386            ALOGE("%s: Error in opening %s", __func__, fn);
2387        }
2388        fclose(fp);
2389    }
2390    fp = fopen(fn, "ab");
2391    if (NULL == fp) {
2392        ALOGE("%s: Error in opening %s", __func__, fn);
2393    }
2394    fwrite(data, 1, length, fp);
2395    fclose(fp);
2396    (*frm_cnt)++;
2397    ALOGD("%s: Written %d bytes for frame:%d, in %s",
2398        __func__, length, *frm_cnt, fn);
2399
2400    return 0;
2401}
2402
2403/******************************************************************************
2404 * Function: launchTakePictureThread
2405 * Description: This is a wrapper function to start take picture thread
2406 *
2407 * Input parameters:
2408 *  camHal                  - camera HAL handle
2409 *
2410 * Return values:
2411 *   0      No error
2412 *   -1     Error
2413 *
2414 * Notes: none
2415 *****************************************************************************/
2416static int launchTakePictureThread(camera_hardware_t *camHal)
2417{
2418    ALOGD("%s: E", __func__);
2419    int rc = 0;
2420
2421    if(!camHal) {
2422        ALOGE("%s: camHal is NULL", __func__);
2423        return -1;
2424    }
2425
2426    pthread_attr_t attr;
2427    pthread_attr_init(&attr);
2428    /* create the thread in detatched state, when the thread exits all */
2429    /* memory resources are freed up */
2430    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
2431    pthread_create(&camHal->takePictureThread, &attr, takePictureThread, camHal);
2432
2433    ALOGD("%s: X", __func__);
2434    return rc;
2435}
2436
2437/******************************************************************************
2438 * Function: takePictureThread
2439 * Description: This function is associated with take picture thread
2440 *
2441 * Input parameters:
2442 *  camHal                  - camera HAL handle
2443 *
2444 * Return values:
2445 *   0      No error
2446 *   -1     Error
2447 *
2448 * Notes: none
2449 *****************************************************************************/
2450static void * takePictureThread(void *hcamHal)
2451{
2452    int                 rc = 0;
2453    int                 buffer_id   = 0;
2454    pid_t               tid         = 0;
2455    camera_hardware_t   *camHal     = NULL;
2456    int                 msgType     = 0;
2457    int                 jpegLength  = 0;
2458    QCameraHalMemInfo_t *mem_info   = NULL;
2459
2460    camHal = (camera_hardware_t *)hcamHal;
2461    ALOGI("%s: E", __func__);
2462
2463    if(!camHal) {
2464        ALOGE("%s: camHal is NULL", __func__);
2465        return NULL ;
2466    }
2467
2468    tid  = gettid();
2469    /* TBR: Set appropriate thread priority */
2470    androidSetThreadPriority(tid, ANDROID_PRIORITY_NORMAL);
2471    prctl(PR_SET_NAME, (unsigned long)"Camera HAL preview thread", 0, 0, 0);
2472
2473    /************************************************************************/
2474    /* - If requested for shutter notfication, notify                       */
2475    /* - Initialize USB camera with snapshot parameters                     */
2476    /* - Time wait (select) on camera fd for camera frame availability      */
2477    /* - Dequeue capture buffer from USB camera                             */
2478    /* - Send capture buffer to JPEG encoder for JPEG compression           */
2479    /* - If jpeg frames callback is requested, callback with jpeg buffers   */
2480    /* - Enqueue capture buffer back to USB camera                          */
2481    /* - Free USB camera resources and close camera                         */
2482    /* - If preview was stopped for taking picture, restart the preview     */
2483    /************************************************************************/
2484
2485    Mutex::Autolock autoLock(camHal->lock);
2486    /************************************************************************/
2487    /* - If requested for shutter notfication, notify                       */
2488    /************************************************************************/
2489#if 0 /* TBD: Temporarily commented out due to an issue. Sometimes it takes */
2490    /* long time to get back the lock once unlocked and notify callback */
2491    if (camHal->msgEnabledFlag & CAMERA_MSG_SHUTTER){
2492        camHal->lock.unlock();
2493        camHal->notify_cb(CAMERA_MSG_SHUTTER, 0, 0, camHal->cb_ctxt);
2494        camHal->lock.lock();
2495    }
2496#endif
2497    /************************************************************************/
2498    /* - Initialize USB camera with snapshot parameters                     */
2499    /************************************************************************/
2500    USB_CAM_OPEN(camHal);
2501
2502#if JPEG_ON_USB_CAMERA
2503    rc = initUsbCamera(camHal, camHal->pictWidth, camHal->pictHeight,
2504                        V4L2_PIX_FMT_MJPEG);
2505#else
2506    rc = initUsbCamera(camHal, camHal->pictWidth, camHal->pictHeight,
2507                        V4L2_PIX_FMT_YUYV);
2508#endif
2509    ERROR_CHECK_EXIT_THREAD(rc, "initUsbCamera");
2510
2511    rc = startUsbCamCapture(camHal);
2512    ERROR_CHECK_EXIT_THREAD(rc, "startUsbCamCapture");
2513
2514    /************************************************************************/
2515    /* - Time wait (select) on camera fd for camera frame availability      */
2516    /************************************************************************/
2517    {
2518        fd_set fds;
2519        struct timeval tv;
2520        int r = 0;
2521
2522        FD_ZERO(&fds);
2523        FD_SET(camHal->fd, &fds);
2524
2525        tv.tv_sec = 1;
2526        tv.tv_usec = 0;
2527
2528        do{
2529            ALOGD("%s: b4 select on camHal->fd : %d", __func__, camHal->fd);
2530            r = select(camHal->fd + 1, &fds, NULL, NULL, &tv);
2531            ALOGD("%s: after select", __func__);
2532        }while((0 == r) || ((-1 == r) && (EINTR == errno)));
2533
2534        if ((-1 == r) && (EINTR != errno)){
2535            ALOGE("%s: FDSelect ret = %d error: %d", __func__, r, errno);
2536            return (void *)-1;
2537        }
2538
2539    }
2540    /************************************************************************/
2541    /* - Dequeue capture buffer from USB camera                             */
2542    /************************************************************************/
2543    if (0 == get_buf_from_cam(camHal))
2544        ALOGD("%s: get_buf_from_cam success", __func__);
2545    else
2546        ALOGE("%s: get_buf_from_cam error", __func__);
2547
2548    /************************************************************************/
2549    /* - Send capture buffer to JPEG encoder for JPEG compression           */
2550    /************************************************************************/
2551    mem_info = &camHal->pictMem.mem_info[0];
2552    mem_info->size = MAX_JPEG_BUFFER_SIZE;
2553
2554    rc = allocate_ion_memory(mem_info,
2555                        ((0x1 << CAMERA_ZSL_ION_HEAP_ID) |
2556                        (0x1 << CAMERA_ZSL_ION_FALLBACK_HEAP_ID)));
2557    if(rc)
2558        ALOGE("%s: ION memory allocation failed", __func__);
2559
2560    camHal->pictMem.camera_memory[0] = camHal->get_memory(
2561                        mem_info->fd, mem_info->size, 1, camHal->cb_ctxt);
2562    if(!camHal->pictMem.camera_memory[0])
2563        ALOGE("%s: get_mem failed", __func__);
2564
2565#if FREAD_JPEG_PICTURE
2566    jpegLength = readFromFile("/data/tempVGA.jpeg",
2567                    (char*)camHal->pictMem.camera_memory[0]->data,
2568                    camHal->pictMem.camera_memory[0]->size);
2569    camHal->pictMem.camera_memory[0]->size = jpegLength;
2570
2571#elif JPEG_ON_USB_CAMERA
2572    memcpy((char*)camHal->pictMem.camera_memory[0]->data,
2573            (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
2574            camHal->curCaptureBuf.bytesused);
2575    camHal->pictMem.camera_memory[0]->size = camHal->curCaptureBuf.bytesused;
2576    jpegLength = camHal->curCaptureBuf.bytesused;
2577
2578#else
2579    rc = encodeJpeg(camHal);
2580    ERROR_CHECK_EXIT_THREAD(rc, "jpeg_encode");
2581#endif
2582    if(jpegLength <= 0)
2583        ALOGI("%s: jpegLength : %d", __func__, jpegLength);
2584
2585     ALOGD("%s: jpegLength : %d", __func__, jpegLength);
2586    /************************************************************************/
2587    /* - If jpeg frames callback is requested, callback with jpeg buffers   */
2588    /************************************************************************/
2589    /* TBD: CAMERA_MSG_RAW_IMAGE data call back */
2590
2591    if ((camHal->msgEnabledFlag & CAMERA_MSG_COMPRESSED_IMAGE) &&
2592            (camHal->data_cb)){
2593        /* Unlock temporarily, callback might call HAL api in turn */
2594        camHal->lock.unlock();
2595
2596        camHal->data_cb(CAMERA_MSG_COMPRESSED_IMAGE,
2597                        camHal->pictMem.camera_memory[0],
2598                        0, NULL, camHal->cb_ctxt);
2599        camHal->lock.lock();
2600    }
2601
2602    /* release heap memory after the call back */
2603    if(camHal->pictMem.camera_memory[0])
2604        camHal->pictMem.camera_memory[0]->release(
2605            camHal->pictMem.camera_memory[0]);
2606
2607    rc = deallocate_ion_memory(mem_info);
2608    if(rc)
2609        ALOGE("%s: ION memory de-allocation failed", __func__);
2610
2611    /************************************************************************/
2612    /* - Enqueue capture buffer back to USB camera                          */
2613    /************************************************************************/
2614    if(0 == put_buf_to_cam(camHal)) {
2615        ALOGD("%s: put_buf_to_cam success", __func__);
2616    }
2617    else
2618        ALOGE("%s: put_buf_to_cam error", __func__);
2619
2620    /************************************************************************/
2621    /* - Free USB camera resources and close camera                         */
2622    /************************************************************************/
2623    rc = stopUsbCamCapture(camHal);
2624    ERROR_CHECK_EXIT_THREAD(rc, "stopUsbCamCapture");
2625
2626    rc = unInitV4L2mmap(camHal);
2627    ERROR_CHECK_EXIT_THREAD(rc, "unInitV4L2mmap");
2628
2629    USB_CAM_CLOSE(camHal);
2630    /************************************************************************/
2631    /* - If preview was stopped for taking picture, restart the preview     */
2632    /************************************************************************/
2633    if(camHal->prvwStoppedForPicture)
2634    {
2635        struct camera_device    device;
2636        device.priv = (void *)camHal;
2637
2638        USB_CAM_OPEN(camHal);
2639        /* Unlock temporarily coz usbcam_start_preview has a lock */
2640        camHal->lock.unlock();
2641        rc = usbcam_start_preview(&device);
2642        if(rc)
2643            ALOGE("%s: start_preview error after take picture", __func__);
2644        camHal->lock.lock();
2645        camHal->prvwStoppedForPicture = 0;
2646    }
2647
2648    /* take picture activity is done */
2649    camHal->takePictInProgress = 0;
2650
2651    ALOGI("%s: X", __func__);
2652    return (void *)0;
2653}
2654
2655/******************************************************************************
2656 * Function: allocate_ion_memory
2657 * Description: This function is allocates ION memory
2658 *
2659 * Input parameters:
2660 *  camHal                  - camera HAL handle
2661 *
2662 * Return values:
2663 *   0      No error
2664 *   -1     Error
2665 *
2666 * Notes: none
2667 *****************************************************************************/
2668static int allocate_ion_memory(QCameraHalMemInfo_t *mem_info, int ion_type)
2669{
2670    int                         rc = 0;
2671    struct ion_handle_data      handle_data;
2672    struct ion_allocation_data  alloc;
2673    struct ion_fd_data          ion_info_fd;
2674    int                         main_ion_fd = 0;
2675
2676    main_ion_fd = open("/dev/ion", O_RDONLY);
2677    if (main_ion_fd <= 0) {
2678        ALOGE("Ion dev open failed %s\n", strerror(errno));
2679        goto ION_OPEN_FAILED;
2680    }
2681
2682    memset(&alloc, 0, sizeof(alloc));
2683    alloc.len = mem_info->size;
2684    /* to make it page size aligned */
2685    alloc.len = (alloc.len + 4095) & (~4095);
2686    alloc.align = 4096;
2687    alloc.flags = ION_FLAG_CACHED;
2688    alloc.heap_id_mask = ion_type;
2689    rc = ioctl(main_ion_fd, ION_IOC_ALLOC, &alloc);
2690    if (rc < 0) {
2691        ALOGE("ION allocation failed\n");
2692        goto ION_ALLOC_FAILED;
2693    }
2694
2695    memset(&ion_info_fd, 0, sizeof(ion_info_fd));
2696    ion_info_fd.handle = alloc.handle;
2697    rc = ioctl(main_ion_fd, ION_IOC_SHARE, &ion_info_fd);
2698    if (rc < 0) {
2699        ALOGE("ION map failed %s\n", strerror(errno));
2700        goto ION_MAP_FAILED;
2701    }
2702
2703    mem_info->main_ion_fd = main_ion_fd;
2704    mem_info->fd = ion_info_fd.fd;
2705    mem_info->handle = ion_info_fd.handle;
2706    mem_info->size = alloc.len;
2707    return 0;
2708
2709ION_MAP_FAILED:
2710    memset(&handle_data, 0, sizeof(handle_data));
2711    handle_data.handle = ion_info_fd.handle;
2712    ioctl(main_ion_fd, ION_IOC_FREE, &handle_data);
2713ION_ALLOC_FAILED:
2714    close(main_ion_fd);
2715ION_OPEN_FAILED:
2716    return -1;
2717}
2718
2719/******************************************************************************
2720 * Function: deallocate_ion_memory
2721 * Description: This function de allocates ION memory
2722 *
2723 * Input parameters:
2724 *  camHal                  - camera HAL handle
2725 *
2726 * Return values:
2727 *   0      No error
2728 *   -1     Error
2729 *
2730 * Notes: none
2731 *****************************************************************************/
2732static int deallocate_ion_memory(QCameraHalMemInfo_t *mem_info)
2733{
2734  struct ion_handle_data handle_data;
2735  int rc = 0;
2736
2737  if (mem_info->fd > 0) {
2738      close(mem_info->fd);
2739      mem_info->fd = 0;
2740  }
2741
2742  if (mem_info->main_ion_fd > 0) {
2743      memset(&handle_data, 0, sizeof(handle_data));
2744      handle_data.handle = mem_info->handle;
2745      ioctl(mem_info->main_ion_fd, ION_IOC_FREE, &handle_data);
2746      close(mem_info->main_ion_fd);
2747      mem_info->main_ion_fd = 0;
2748  }
2749  return rc;
2750}
2751
2752/******************************************************************************
2753 * Function: readFromFile
2754 * Description: This function reads data from the given file into given buffer
2755 *
2756 * Input parameters:
2757 *  camHal                  - camera HAL handle
2758 *
2759 * Return values:
2760 *   int    bytesRead
2761 *
2762 * Notes: none
2763 *****************************************************************************/
2764static int readFromFile(char* fileName, char* buffer, int bufferSize)
2765{
2766    int bytesRead = 0, fileSize = 0;
2767    FILE *fp;
2768
2769    fp = fopen(fileName, "rb");
2770    if(!fp){
2771        ALOGE("%s: Error in opening %s ", __func__, fileName);
2772        return bytesRead;
2773    }
2774
2775    /* If file is bigger for given buffer, exit */
2776    if (fileSize > bufferSize){
2777        ALOGE("%s: Error %d > %d", __func__, fileSize, bufferSize);
2778        return bytesRead;
2779    }
2780
2781    bytesRead = fread(buffer, 1, bufferSize, fp);
2782    ALOGD(" %s: bytesRead: %d", __func__, bytesRead);
2783
2784    return bytesRead;
2785}
2786
2787/******************************************************************************
2788 * Function: encodeJpeg
2789 * Description: This function initializes Jpeg encoder and calls jpeg encoder
2790 *              call and waits for the encode to complete
2791 *
2792 * Input parameters:
2793 *  camHal                  - camera HAL handle
2794 *
2795 * Return values:
2796 *   0  No Error
2797 *  -1  Error
2798 *
2799 * Notes: none
2800 *****************************************************************************/
2801int encodeJpeg(camera_hardware_t *camHal)
2802{
2803    int                 rc = 0;
2804    mm_jpeg_ops_t       mmJpegOps;
2805    int                 jpegEncHdl  = 0;
2806    mm_jpeg_job         mmJpegJob;
2807    src_image_buffer_info   *srcBuf = NULL;
2808    QCameraHalMemInfo_t jpegInMemInfo;
2809    camera_memory_t*    jpegInMem;
2810    uint32_t            jobId;
2811
2812    ALOGI("%s: E", __func__);
2813
2814    /************************************************************************/
2815    /* - Allocate Jpeg input buffer from ION memory                         */
2816    /************************************************************************/
2817    jpegInMemInfo.size = camHal->pictWidth * camHal->pictHeight * 2;
2818    rc = allocate_ion_memory(&jpegInMemInfo,
2819                        ((0x1 << CAMERA_ZSL_ION_HEAP_ID) |
2820                        (0x1 << CAMERA_ZSL_ION_FALLBACK_HEAP_ID)));
2821    ERROR_CHECK_EXIT(rc, "allocate_ion_memory");
2822
2823    jpegInMem = camHal->get_memory(
2824                        jpegInMemInfo.fd, jpegInMemInfo.size, 1, camHal->cb_ctxt);
2825    if(!jpegInMem){
2826        ALOGE("%s: get_mem failed", __func__);
2827        return -1;
2828    }
2829
2830    rc = convert_YUYV_to_420_NV12(
2831        (char *)camHal->buffers[camHal->curCaptureBuf.index].data,
2832        (char *)jpegInMem->data, camHal->pictWidth, camHal->pictHeight);
2833    ERROR_CHECK_EXIT(rc, "convert_YUYV_to_420_NV12");
2834    /************************************************************************/
2835    /* - Populate JPEG encoding parameters from the camHal context          */
2836    /************************************************************************/
2837    memset(&mmJpegJob, 0, sizeof(mmJpegJob));
2838
2839    mmJpegJob.job_type              = JPEG_JOB_TYPE_ENCODE;
2840    mmJpegJob.encode_job.jpeg_cb    = jpegEncodeCb;
2841    mmJpegJob.encode_job.userdata   = (void *)camHal;
2842    /* TBD: Rotation to be set from settings sent from app */
2843    mmJpegJob.encode_job.encode_parm.rotation           = 0;
2844    mmJpegJob.encode_job.encode_parm.exif_numEntries    = 0;
2845    mmJpegJob.encode_job.encode_parm.exif_data          = NULL;
2846
2847    /* TBD: Add thumbnail support */
2848    mmJpegJob.encode_job.encode_parm.buf_info.src_imgs.src_img_num = 1;
2849    mmJpegJob.encode_job.encode_parm.buf_info.src_imgs.is_video_frame = 0;
2850
2851    /* Fill main image information */
2852    srcBuf = &mmJpegJob.encode_job.encode_parm.buf_info.src_imgs.src_img[0];
2853    srcBuf->type                = JPEG_SRC_IMAGE_TYPE_MAIN;
2854    srcBuf->img_fmt             = JPEG_SRC_IMAGE_FMT_YUV;
2855    /* TBD: convert from YUYV to CRCBH2V2 */
2856    srcBuf->color_format        = MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2;
2857    srcBuf->num_bufs            = 1;
2858    srcBuf->src_image[0].fd        = jpegInMemInfo.fd;
2859    srcBuf->src_image[0].buf_vaddr = (uint8_t*)jpegInMem->data;
2860    //srcBuf->src_image[0].offset    = 0;
2861    srcBuf->src_dim.width       = camHal->pictWidth;
2862    srcBuf->src_dim.height      = camHal->pictHeight;
2863    srcBuf->out_dim.width       = camHal->pictWidth;
2864    srcBuf->out_dim.height      = camHal->pictHeight;
2865    srcBuf->crop.offset_x       = 0;
2866    srcBuf->crop.offset_y       = 0;
2867    srcBuf->crop.width          = srcBuf->src_dim.width;
2868    srcBuf->crop.height         = srcBuf->src_dim.height;
2869    srcBuf->quality             = camHal->pictJpegQlty;
2870
2871    /* TBD:Fill thumbnail image information */
2872
2873    /* Fill out buf information */
2874    mmJpegJob.encode_job.encode_parm.buf_info.sink_img.buf_vaddr =
2875                            (uint8_t*)camHal->pictMem.camera_memory[0]->data;
2876    mmJpegJob.encode_job.encode_parm.buf_info.sink_img.fd = 0;
2877    /* TBD: hard coded for 1.5 bytes per pixel */
2878    mmJpegJob.encode_job.encode_parm.buf_info.sink_img.buf_len =
2879                            camHal->pictWidth * camHal->pictHeight * 1.5;
2880
2881    /************************************************************************/
2882    /* - Initialize jpeg encoder and call Jpeg encoder start                */
2883    /************************************************************************/
2884    memset(&mmJpegOps, 0, sizeof(mm_jpeg_ops_t));
2885    jpegEncHdl = jpeg_open(&mmJpegOps);
2886    if(!jpegEncHdl){
2887        ALOGE("%s: Failed to open Jpeg Encoder instance", __func__);
2888    }else
2889        ALOGD("%s: jpegEncHdl = %d", __func__, jpegEncHdl);
2890
2891    camHal->jpegEncInProgress = 1;
2892    rc = mmJpegOps.start_job(jpegEncHdl, &mmJpegJob, &jobId);
2893
2894    /************************************************************************/
2895    /* - Wait for JPEG encoder to complete encoding                         */
2896    /************************************************************************/
2897    pthread_mutex_init(&camHal->jpegEncMutex, NULL);
2898    pthread_cond_init(&camHal->jpegEncCond, NULL);
2899
2900    pthread_mutex_lock(&camHal->jpegEncMutex);
2901    while(camHal->jpegEncInProgress)
2902        pthread_cond_wait(&camHal->jpegEncCond, &camHal->jpegEncMutex);
2903    pthread_mutex_unlock(&camHal->jpegEncMutex);
2904
2905    /************************************************************************/
2906    /* - De-allocate Jpeg input buffer from ION memory                      */
2907    /************************************************************************/
2908    if(jpegInMem)
2909        jpegInMem->release(jpegInMem);
2910
2911    rc = deallocate_ion_memory(&jpegInMemInfo);
2912    if(rc)
2913        ALOGE("%s: ION memory de-allocation failed", __func__);
2914
2915    ALOGI("%s: X rc = %d", __func__, rc);
2916    return rc;
2917}
2918
2919/******************************************************************************
2920 * Function: jpegEncodeCb
2921 * Description: This is a call back function registered with JPEG encoder.
2922 *              Jpeg encoder calls this function on completion of encoding
2923 *
2924 * Input parameters:
2925 *  camHal                  - camera HAL handle
2926 *
2927 * Return values:
2928 *   0  No Error
2929 *  -1  Error
2930 *
2931 * Notes: none
2932 *****************************************************************************/
2933void jpegEncodeCb   (jpeg_job_status_t status,
2934                       uint8_t thumbnailDroppedFlag,
2935                       uint32_t client_hdl,
2936                       uint32_t jobId,
2937                       uint8_t* out_data,
2938                       uint32_t data_size,
2939                       void *userData)
2940{
2941    int rc = 0;
2942    camera_hardware_t *camHal = NULL;
2943
2944    ALOGI("%s: E status = %d", __func__, status);
2945
2946    camHal = (camera_hardware_t*) userData;
2947
2948    if(JPEG_JOB_STATUS_DONE == status){
2949        ALOGD("%s: JPEG encode successful. out_data:%p, size: %d", __func__,
2950            out_data, data_size);
2951        camHal->jpegEncInProgress = 0;
2952    }
2953
2954    pthread_mutex_lock(&camHal->jpegEncMutex);
2955    pthread_cond_signal(&camHal->jpegEncCond);
2956    pthread_mutex_unlock(&camHal->jpegEncMutex);
2957
2958    ALOGI("%s: X", __func__);
2959    return;
2960}
2961
2962/******************************************************************************/
2963}; // namespace android
2964