Home | History | Annotate | Download | only in tml
      1 /*
      2  * Copyright (C) 2010-2014 NXP Semiconductors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * DAL independent message queue implementation for Android (can be used under
     19  * Linux too)
     20  */
     21 
     22 #include <errno.h>
     23 #include <linux/ipc.h>
     24 #include <phDal4Nfc_messageQueueLib.h>
     25 #include <phNxpLog.h>
     26 #include <pthread.h>
     27 #include <semaphore.h>
     28 
     29 typedef struct phDal4Nfc_message_queue_item {
     30   phLibNfc_Message_t nMsg;
     31   struct phDal4Nfc_message_queue_item* pPrev;
     32   struct phDal4Nfc_message_queue_item* pNext;
     33 } phDal4Nfc_message_queue_item_t;
     34 
     35 typedef struct phDal4Nfc_message_queue {
     36   phDal4Nfc_message_queue_item_t* pItems;
     37   pthread_mutex_t nCriticalSectionMutex;
     38   sem_t nProcessSemaphore;
     39 
     40 } phDal4Nfc_message_queue_t;
     41 
     42 /*******************************************************************************
     43 **
     44 ** Function         phDal4Nfc_msgget
     45 **
     46 ** Description      Allocates message queue
     47 **
     48 ** Parameters       Ignored, included only for Linux queue API compatibility
     49 **
     50 ** Returns          (int) value of pQueue if successful
     51 **                  -1, if failed to allocate memory or to init mutex
     52 **
     53 *******************************************************************************/
     54 intptr_t phDal4Nfc_msgget(key_t key, int msgflg) {
     55   phDal4Nfc_message_queue_t* pQueue;
     56   UNUSED(key);
     57   UNUSED(msgflg);
     58   pQueue =
     59       (phDal4Nfc_message_queue_t*)malloc(sizeof(phDal4Nfc_message_queue_t));
     60   if (pQueue == NULL) return -1;
     61   memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t));
     62   if (pthread_mutex_init(&pQueue->nCriticalSectionMutex, NULL) == -1) {
     63     free(pQueue);
     64     return -1;
     65   }
     66   if (sem_init(&pQueue->nProcessSemaphore, 0, 0) == -1) {
     67     free(pQueue);
     68     return -1;
     69   }
     70 
     71   return ((intptr_t)pQueue);
     72 }
     73 
     74 /*******************************************************************************
     75 **
     76 ** Function         phDal4Nfc_msgrelease
     77 **
     78 ** Description      Releases message queue
     79 **
     80 ** Parameters       msqid - message queue handle
     81 **
     82 ** Returns          None
     83 **
     84 *******************************************************************************/
     85 void phDal4Nfc_msgrelease(intptr_t msqid) {
     86   phDal4Nfc_message_queue_t* pQueue = (phDal4Nfc_message_queue_t*)msqid;
     87 
     88   if (pQueue != NULL) {
     89     sem_post(&pQueue->nProcessSemaphore);
     90     usleep(3000);
     91     if (sem_destroy(&pQueue->nProcessSemaphore)) {
     92       NXPLOG_TML_E("Failed to destroy semaphore (errno=0x%08x)", errno);
     93     }
     94     pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
     95 
     96     free(pQueue);
     97   }
     98 
     99   return;
    100 }
    101 
    102 /*******************************************************************************
    103 **
    104 ** Function         phDal4Nfc_msgctl
    105 **
    106 ** Description      Destroys message queue
    107 **
    108 ** Parameters       msqid - message queue handle
    109 **                  cmd, buf - ignored, included only for Linux queue API
    110 **                  compatibility
    111 **
    112 ** Returns          0,  if successful
    113 **                  -1, if invalid handle is passed
    114 **
    115 *******************************************************************************/
    116 int phDal4Nfc_msgctl(intptr_t msqid, int cmd, void* buf) {
    117   phDal4Nfc_message_queue_t* pQueue;
    118   phDal4Nfc_message_queue_item_t* p;
    119   UNUSED(cmd);
    120   UNUSED(buf);
    121   if (msqid == 0) return -1;
    122 
    123   pQueue = (phDal4Nfc_message_queue_t*)msqid;
    124   pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    125   if (pQueue->pItems != NULL) {
    126     p = pQueue->pItems;
    127     while (p->pNext != NULL) {
    128       p = p->pNext;
    129     }
    130     while (p->pPrev != NULL) {
    131       p = p->pPrev;
    132       free(p->pNext);
    133       p->pNext = NULL;
    134     }
    135     free(p);
    136   }
    137   pQueue->pItems = NULL;
    138   pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    139   pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
    140   free(pQueue);
    141 
    142   return 0;
    143 }
    144 
    145 /*******************************************************************************
    146 **
    147 ** Function         phDal4Nfc_msgsnd
    148 **
    149 ** Description      Sends a message to the queue. The message will be added at
    150 **                  the end of the queue as appropriate for FIFO policy
    151 **
    152 ** Parameters       msqid  - message queue handle
    153 **                  msgp   - message to be sent
    154 **                  msgsz  - message size
    155 **                  msgflg - ignored
    156 **
    157 ** Returns          0,  if successful
    158 **                  -1, if invalid parameter passed or failed to allocate memory
    159 **
    160 *******************************************************************************/
    161 intptr_t phDal4Nfc_msgsnd(intptr_t msqid, phLibNfc_Message_t* msg, int msgflg) {
    162   phDal4Nfc_message_queue_t* pQueue;
    163   phDal4Nfc_message_queue_item_t* p;
    164   phDal4Nfc_message_queue_item_t* pNew;
    165   UNUSED(msgflg);
    166   if ((msqid == 0) || (msg == NULL)) return -1;
    167 
    168   pQueue = (phDal4Nfc_message_queue_t*)msqid;
    169   pNew = (phDal4Nfc_message_queue_item_t*)malloc(
    170       sizeof(phDal4Nfc_message_queue_item_t));
    171   if (pNew == NULL) return -1;
    172   memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t));
    173   memcpy(&pNew->nMsg, msg, sizeof(phLibNfc_Message_t));
    174   pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    175 
    176   if (pQueue->pItems != NULL) {
    177     p = pQueue->pItems;
    178     while (p->pNext != NULL) {
    179       p = p->pNext;
    180     }
    181     p->pNext = pNew;
    182     pNew->pPrev = p;
    183   } else {
    184     pQueue->pItems = pNew;
    185   }
    186   pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    187 
    188   sem_post(&pQueue->nProcessSemaphore);
    189 
    190   return 0;
    191 }
    192 
    193 /*******************************************************************************
    194 **
    195 ** Function         phDal4Nfc_msgrcv
    196 **
    197 ** Description      Gets the oldest message from the queue.
    198 **                  If the queue is empty the function waits (blocks on a mutex)
    199 **                  until a message is posted to the queue with phDal4Nfc_msgsnd
    200 **
    201 ** Parameters       msqid  - message queue handle
    202 **                  msgp   - message to be received
    203 **                  msgsz  - message size
    204 **                  msgtyp - ignored
    205 **                  msgflg - ignored
    206 **
    207 ** Returns          0,  if successful
    208 **                  -1, if invalid parameter passed
    209 **
    210 *******************************************************************************/
    211 int phDal4Nfc_msgrcv(intptr_t msqid, phLibNfc_Message_t* msg, long msgtyp,
    212                      int msgflg) {
    213   phDal4Nfc_message_queue_t* pQueue;
    214   phDal4Nfc_message_queue_item_t* p;
    215   UNUSED(msgflg);
    216   UNUSED(msgtyp);
    217   if ((msqid == 0) || (msg == NULL)) return -1;
    218 
    219   pQueue = (phDal4Nfc_message_queue_t*)msqid;
    220 
    221   sem_wait(&pQueue->nProcessSemaphore);
    222 
    223   pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    224 
    225   if (pQueue->pItems != NULL) {
    226     memcpy(msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t));
    227     p = pQueue->pItems->pNext;
    228     free(pQueue->pItems);
    229     pQueue->pItems = p;
    230   }
    231   pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    232 
    233   return 0;
    234 }
    235