Home | History | Annotate | Download | only in src
      1 /*
      2 Copyright (c) 2012, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are
      6 met:
      7     * Redistributions of source code must retain the above copyright
      8       notice, this list of conditions and the following disclaimer.
      9     * Redistributions in binary form must reproduce the above
     10       copyright notice, this list of conditions and the following
     11       disclaimer in the documentation and/or other materials provided
     12       with the distribution.
     13     * Neither the name of The Linux Foundation nor the names of its
     14       contributors may be used to endorse or promote products derived
     15       from this software without specific prior written permission.
     16 
     17 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 
     30 #include <pthread.h>
     31 #include <errno.h>
     32 #include <sys/ioctl.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <fcntl.h>
     36 #include <semaphore.h>
     37 
     38 #include "mm_camera_dbg.h"
     39 #include "mm_camera_interface.h"
     40 #include "mm_camera.h"
     41 
     42 #if 0
     43 #undef CDBG
     44 #undef LOG_TAG
     45 #define CDBG ALOGE
     46 #define LOG_TAG "NotifyLogs"
     47 #endif
     48 
     49 int32_t mm_camera_queue_init(mm_camera_queue_t* queue)
     50 {
     51     pthread_mutex_init(&queue->lock, NULL);
     52     cam_list_init(&queue->head.list);
     53     queue->size = 0;
     54     return 0;
     55 }
     56 
     57 int32_t mm_camera_queue_enq(mm_camera_queue_t* queue, void* data)
     58 {
     59     mm_camera_q_node_t* node =
     60         (mm_camera_q_node_t *)malloc(sizeof(mm_camera_q_node_t));
     61     if (NULL == node) {
     62         CDBG_ERROR("%s: No memory for mm_camera_q_node_t", __func__);
     63         return -1;
     64     }
     65 
     66     memset(node, 0, sizeof(mm_camera_q_node_t));
     67     node->data = data;
     68 
     69     pthread_mutex_lock(&queue->lock);
     70     cam_list_add_tail_node(&node->list, &queue->head.list);
     71     queue->size++;
     72     pthread_mutex_unlock(&queue->lock);
     73 
     74     return 0;
     75 
     76 }
     77 
     78 void* mm_camera_queue_deq(mm_camera_queue_t* queue)
     79 {
     80     mm_camera_q_node_t* node = NULL;
     81     void* data = NULL;
     82     struct cam_list *head = NULL;
     83     struct cam_list *pos = NULL;
     84 
     85     pthread_mutex_lock(&queue->lock);
     86     head = &queue->head.list;
     87     pos = head->next;
     88     if (pos != head) {
     89         node = member_of(pos, mm_camera_q_node_t, list);
     90         cam_list_del_node(&node->list);
     91         queue->size--;
     92     }
     93     pthread_mutex_unlock(&queue->lock);
     94 
     95     if (NULL != node) {
     96         data = node->data;
     97         free(node);
     98     }
     99 
    100     return data;
    101 }
    102 
    103 int32_t mm_camera_queue_deinit(mm_camera_queue_t* queue)
    104 {
    105     mm_camera_queue_flush(queue);
    106     pthread_mutex_destroy(&queue->lock);
    107     return 0;
    108 }
    109 
    110 int32_t mm_camera_queue_flush(mm_camera_queue_t* queue)
    111 {
    112     mm_camera_q_node_t* node = NULL;
    113     void* data = NULL;
    114     struct cam_list *head = NULL;
    115     struct cam_list *pos = NULL;
    116 
    117     pthread_mutex_lock(&queue->lock);
    118     head = &queue->head.list;
    119     pos = head->next;
    120 
    121     while(pos != head) {
    122         node = member_of(pos, mm_camera_q_node_t, list);
    123         cam_list_del_node(&node->list);
    124         queue->size--;
    125 
    126         /* TODO later to consider ptr inside data */
    127         /* for now we only assume there is no ptr inside data
    128          * so we free data directly */
    129         if (NULL != node->data) {
    130             free(node->data);
    131         }
    132         free(node);
    133         pos = pos->next;
    134     }
    135     queue->size = 0;
    136     pthread_mutex_unlock(&queue->lock);
    137     return 0;
    138 }
    139 
    140 static void *mm_camera_cmd_thread(void *data)
    141 {
    142     int rc = 0;
    143     int running = 1;
    144     int ret;
    145     mm_camera_cmd_thread_t *cmd_thread =
    146                 (mm_camera_cmd_thread_t *)data;
    147     mm_camera_cmdcb_t* node = NULL;
    148 
    149     do {
    150         do {
    151             ret = sem_wait(&cmd_thread->cmd_sem);
    152             if (ret != 0 && errno != EINVAL) {
    153                 CDBG_ERROR("%s: sem_wait error (%s)",
    154                            __func__, strerror(errno));
    155                 return NULL;
    156             }
    157         } while (ret != 0);
    158 
    159         /* we got notified about new cmd avail in cmd queue */
    160         node = (mm_camera_cmdcb_t*)mm_camera_queue_deq(&cmd_thread->cmd_queue);
    161         if (node != NULL) {
    162             switch (node->cmd_type) {
    163             case MM_CAMERA_CMD_TYPE_EVT_CB:
    164             case MM_CAMERA_CMD_TYPE_DATA_CB:
    165             case MM_CAMERA_CMD_TYPE_ASYNC_CB:
    166             case MM_CAMERA_CMD_TYPE_REQ_DATA_CB:
    167                 if (NULL != cmd_thread->cb) {
    168                     cmd_thread->cb(node, cmd_thread->user_data);
    169                 }
    170                 break;
    171             case MM_CAMERA_CMD_TYPE_EXIT:
    172             default:
    173                 running = 0;
    174                 break;
    175             }
    176             free(node);
    177         }
    178     } while (running);
    179     return NULL;
    180 }
    181 
    182 int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,
    183                                     mm_camera_cmd_cb_t cb,
    184                                     void* user_data)
    185 {
    186     int32_t rc = 0;
    187 
    188     sem_init(&cmd_thread->cmd_sem, 0, 0);
    189     mm_camera_queue_init(&cmd_thread->cmd_queue);
    190     cmd_thread->cb = cb;
    191     cmd_thread->user_data = user_data;
    192 
    193     /* launch the thread */
    194     pthread_create(&cmd_thread->cmd_pid,
    195                    NULL,
    196                    mm_camera_cmd_thread,
    197                    (void *)cmd_thread);
    198     return rc;
    199 }
    200 
    201 int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread)
    202 {
    203     int32_t rc = 0;
    204     mm_camera_buf_info_t  buf_info;
    205     mm_camera_cmdcb_t* node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
    206     if (NULL == node) {
    207         CDBG_ERROR("%s: No memory for mm_camera_cmdcb_t", __func__);
    208         return -1;
    209     }
    210 
    211     memset(node, 0, sizeof(mm_camera_cmdcb_t));
    212     node->cmd_type = MM_CAMERA_CMD_TYPE_EXIT;
    213 
    214     mm_camera_queue_enq(&cmd_thread->cmd_queue, node);
    215     sem_post(&cmd_thread->cmd_sem);
    216 
    217     /* wait until cmd thread exits */
    218     if (pthread_join(cmd_thread->cmd_pid, NULL) != 0) {
    219         CDBG("%s: pthread dead already\n", __func__);
    220     }
    221     mm_camera_queue_deinit(&cmd_thread->cmd_queue);
    222 
    223     sem_destroy(&cmd_thread->cmd_sem);
    224     memset(cmd_thread, 0, sizeof(mm_camera_cmd_thread_t));
    225     return rc;
    226 }
    227 
    228