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 Linux too)
     19  */
     20 
     21 #include <pthread.h>
     22 #include <phNxpLog.h>
     23 #include <linux/ipc.h>
     24 #include <semaphore.h>
     25 #include <errno.h>
     26 #include <phDal4Nfc_messageQueueLib.h>
     27 
     28 
     29 typedef struct phDal4Nfc_message_queue_item
     30 {
     31     phLibNfc_Message_t nMsg;
     32     struct phDal4Nfc_message_queue_item * pPrev;
     33     struct phDal4Nfc_message_queue_item * pNext;
     34 } phDal4Nfc_message_queue_item_t;
     35 
     36 typedef struct phDal4Nfc_message_queue
     37 {
     38     phDal4Nfc_message_queue_item_t * pItems;
     39     pthread_mutex_t nCriticalSectionMutex;
     40     sem_t nProcessSemaphore;
     41 
     42 } phDal4Nfc_message_queue_t;
     43 
     44 /*******************************************************************************
     45 **
     46 ** Function         phDal4Nfc_msgget
     47 **
     48 ** Description      Allocates message queue
     49 **
     50 ** Parameters       Ignored, included only for Linux queue API compatibility
     51 **
     52 ** Returns          (int) value of pQueue if successful
     53 **                  -1, if failed to allocate memory or to init mutex
     54 **
     55 *******************************************************************************/
     56 intptr_t phDal4Nfc_msgget(key_t key, int msgflg)
     57 {
     58     phDal4Nfc_message_queue_t * pQueue;
     59     UNUSED(key);
     60     UNUSED(msgflg);
     61     pQueue = (phDal4Nfc_message_queue_t *) malloc(sizeof(phDal4Nfc_message_queue_t));
     62     if (pQueue == NULL)
     63         return -1;
     64     memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t));
     65     if (pthread_mutex_init(&pQueue->nCriticalSectionMutex, NULL) == -1)
     66     {
     67         free (pQueue);
     68         return -1;
     69     }
     70     if (sem_init(&pQueue->nProcessSemaphore, 0, 0) == -1)
     71     {
     72         free (pQueue);
     73         return -1;
     74     }
     75 
     76     return ((intptr_t) pQueue);
     77 }
     78 
     79 /*******************************************************************************
     80 **
     81 ** Function         phDal4Nfc_msgrelease
     82 **
     83 ** Description      Releases message queue
     84 **
     85 ** Parameters       msqid - message queue handle
     86 **
     87 ** Returns          None
     88 **
     89 *******************************************************************************/
     90 void phDal4Nfc_msgrelease(intptr_t msqid)
     91 {
     92     phDal4Nfc_message_queue_t * pQueue = (phDal4Nfc_message_queue_t*)msqid;
     93 
     94     if(pQueue != NULL)
     95     {
     96         sem_post(&pQueue->nProcessSemaphore);
     97         usleep(300000);
     98         if (sem_destroy(&pQueue->nProcessSemaphore))
     99         {
    100             NXPLOG_TML_E("Failed to destroy semaphore (errno=0x%08x)", errno);
    101         }
    102         pthread_mutex_destroy (&pQueue->nCriticalSectionMutex);
    103 
    104         free(pQueue);
    105     }
    106 
    107     return;
    108 }
    109 
    110 /*******************************************************************************
    111 **
    112 ** Function         phDal4Nfc_msgctl
    113 **
    114 ** Description      Destroys message queue
    115 **
    116 ** Parameters       msqid - message queue handle
    117 **                  cmd, buf - ignored, included only for Linux queue API compatibility
    118 **
    119 ** Returns          0,  if successful
    120 **                  -1, if invalid handle is passed
    121 **
    122 *******************************************************************************/
    123 int phDal4Nfc_msgctl(intptr_t msqid, int cmd, void *buf)
    124 {
    125     phDal4Nfc_message_queue_t * pQueue;
    126     phDal4Nfc_message_queue_item_t * p;
    127     UNUSED(cmd);
    128     UNUSED(buf);
    129     if (msqid == 0)
    130         return -1;
    131 
    132     pQueue = (phDal4Nfc_message_queue_t *) msqid;
    133     pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    134     if (pQueue->pItems != NULL)
    135     {
    136         p = pQueue->pItems;
    137         while (p->pNext != NULL)
    138         {
    139             p = p->pNext;
    140         }
    141         while (p->pPrev != NULL)
    142         {
    143             p = p->pPrev;
    144             free(p->pNext);
    145             p->pNext = NULL;
    146         }
    147         free(p);
    148     }
    149     pQueue->pItems = NULL;
    150     pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    151     pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
    152     free(pQueue);
    153 
    154     return 0;
    155 }
    156 
    157 /*******************************************************************************
    158 **
    159 ** Function         phDal4Nfc_msgsnd
    160 **
    161 ** Description      Sends a message to the queue. The message will be added at the end of
    162 **                  the queue as appropriate for FIFO policy
    163 **
    164 ** Parameters       msqid  - message queue handle
    165 **                  msgp   - message to be sent
    166 **                  msgsz  - message size
    167 **                  msgflg - ignored
    168 **
    169 ** Returns          0,  if successful
    170 **                  -1, if invalid parameter passed or failed to allocate memory
    171 **
    172 *******************************************************************************/
    173 intptr_t phDal4Nfc_msgsnd(intptr_t msqid, phLibNfc_Message_t * msg, int msgflg)
    174 {
    175     phDal4Nfc_message_queue_t * pQueue;
    176     phDal4Nfc_message_queue_item_t * p;
    177     phDal4Nfc_message_queue_item_t * pNew;
    178     UNUSED(msgflg);
    179     if ((msqid == 0) || (msg == NULL) )
    180         return -1;
    181 
    182 
    183     pQueue = (phDal4Nfc_message_queue_t *) msqid;
    184     pNew = (phDal4Nfc_message_queue_item_t *) malloc(sizeof(phDal4Nfc_message_queue_item_t));
    185     if (pNew == NULL)
    186         return -1;
    187     memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t));
    188     memcpy(&pNew->nMsg, msg, sizeof(phLibNfc_Message_t));
    189     pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    190 
    191     if (pQueue->pItems != NULL)
    192     {
    193         p = pQueue->pItems;
    194         while (p->pNext != NULL)
    195         {
    196             p = p->pNext;
    197         }
    198         p->pNext = pNew;
    199         pNew->pPrev = p;
    200     }
    201     else
    202     {
    203         pQueue->pItems = pNew;
    204     }
    205     pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    206 
    207     sem_post(&pQueue->nProcessSemaphore);
    208 
    209     return 0;
    210 }
    211 
    212 /*******************************************************************************
    213 **
    214 ** Function         phDal4Nfc_msgrcv
    215 **
    216 ** Description      Gets the oldest message from the queue.
    217 **                  If the queue is empty the function waits (blocks on a mutex)
    218 **                  until a message is posted to the queue with phDal4Nfc_msgsnd.
    219 **
    220 ** Parameters       msqid  - message queue handle
    221 **                  msgp   - message to be received
    222 **                  msgsz  - message size
    223 **                  msgtyp - ignored
    224 **                  msgflg - ignored
    225 **
    226 ** Returns          0,  if successful
    227 **                  -1, if invalid parameter passed
    228 **
    229 *******************************************************************************/
    230 int phDal4Nfc_msgrcv(intptr_t msqid, phLibNfc_Message_t * msg, long msgtyp, int msgflg)
    231 {
    232     phDal4Nfc_message_queue_t * pQueue;
    233     phDal4Nfc_message_queue_item_t * p;
    234     UNUSED(msgflg);
    235     UNUSED(msgtyp);
    236     if ((msqid == 0) || (msg == NULL))
    237         return -1;
    238 
    239     pQueue = (phDal4Nfc_message_queue_t *) msqid;
    240 
    241     sem_wait(&pQueue->nProcessSemaphore);
    242 
    243     pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    244 
    245     if (pQueue->pItems != NULL)
    246     {
    247         memcpy(msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t));
    248         p = pQueue->pItems->pNext;
    249         free(pQueue->pItems);
    250         pQueue->pItems = p;
    251     }
    252     pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    253 
    254     return 0;
    255 }
    256