Home | History | Annotate | Download | only in Linux_x86
      1 /*
      2  * Copyright (C) 2010 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  * \file phDalNfc_messageQueueLib.c
     19  * \brief DAL independant message queue implementation for android (can be used under linux too)
     20  *
     21  * Project: Trusted NFC Linux Lignt
     22  *
     23  * $Date: 13 aug 2009
     24  * $Author: Jonathan roux
     25  * $Revision: 1.0 $
     26  *
     27  */
     28 
     29 #include <pthread.h>
     30 #ifdef ANDROID
     31 #include <linux/ipc.h>
     32 #else
     33 #include <sys/msg.h>
     34 #endif
     35 
     36 #include <semaphore.h>
     37 
     38 #include <phDal4Nfc.h>
     39 #include <phOsalNfc.h>
     40 #include <phDal4Nfc_DeferredCall.h>
     41 #include <phDal4Nfc_messageQueueLib.h>
     42 
     43 typedef struct phDal4Nfc_message_queue_item
     44 {
     45    phLibNfc_Message_t nMsg;
     46    struct phDal4Nfc_message_queue_item * pPrev;
     47    struct phDal4Nfc_message_queue_item * pNext;
     48 } phDal4Nfc_message_queue_item_t;
     49 
     50 
     51 typedef struct phDal4Nfc_message_queue
     52 {
     53    phDal4Nfc_message_queue_item_t * pItems;
     54    pthread_mutex_t          nCriticalSectionMutex;
     55    sem_t                    nProcessSemaphore;
     56 
     57 } phDal4Nfc_message_queue_t;
     58 
     59 
     60 /**
     61  * \ingroup grp_nfc_dal
     62  *
     63  * \brief DAL message get function
     64  * This function allocates the message queue. The parameters are ignored, this is
     65  * just to keep the same api as Linux queue.
     66  *
     67  * \retval -1                                   Can not allocate memory or can not init mutex.
     68 *  \retval handle                               The handle on the message queue.
     69  */
     70 intptr_t phDal4Nfc_msgget ( key_t key, int msgflg )
     71 {
     72    phDal4Nfc_message_queue_t * pQueue;
     73    pQueue = (phDal4Nfc_message_queue_t *) phOsalNfc_GetMemory(sizeof(phDal4Nfc_message_queue_t));
     74    if (pQueue == NULL)
     75       return -1;
     76    memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t));
     77    if (pthread_mutex_init (&pQueue->nCriticalSectionMutex, NULL) == -1)
     78       return -1;
     79    if (sem_init (&pQueue->nProcessSemaphore, 0, 0) == -1)
     80       return -1;
     81    return ((intptr_t)pQueue);
     82 }
     83 
     84 /**
     85  * \ingroup grp_nfc_dal
     86  *
     87  * \brief DAL message control function
     88  * This function destroys the message queue. The cmd and buf parameters are ignored,
     89  * this is just to keep the same api as Linux queue.
     90  *
     91  * \param[in]       msqid     The handle of the message queue.
     92  *
     93  * \retval 0                                    If success.
     94  * \retval -1                                   Bad passed parameter
     95  */
     96 int phDal4Nfc_msgctl ( intptr_t msqid, int cmd, void *buf )
     97 {
     98    phDal4Nfc_message_queue_t * pQueue;
     99    phDal4Nfc_message_queue_item_t * p;
    100 
    101    if (msqid == 0)
    102       return -1;
    103 
    104    pQueue = (phDal4Nfc_message_queue_t *)msqid;
    105    pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    106    if (pQueue->pItems != NULL)
    107    {
    108       p = pQueue->pItems;
    109       while(p->pNext != NULL) { p = p->pNext; }
    110       while(p->pPrev != NULL)
    111       {
    112          p = p->pPrev;
    113          phOsalNfc_FreeMemory(p->pNext);
    114          p->pNext = NULL;
    115       }
    116       phOsalNfc_FreeMemory(p);
    117    }
    118    pQueue->pItems = NULL;
    119    pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    120    pthread_mutex_destroy(&pQueue->nCriticalSectionMutex);
    121    phOsalNfc_FreeMemory(pQueue);
    122    return 0;
    123 }
    124 
    125 /**
    126  * \ingroup grp_nfc_dal
    127  *
    128  * \brief DAL message send function
    129  * Use this function to send a message to the queue. The message will be added at the end of
    130  * the queue with respect to FIFO policy. The msgflg parameter is ignored.
    131  *
    132  * \param[in]       msqid     The handle of the message queue.
    133  * \param[in]       msgp      The message to send.
    134  * \param[in]       msgsz     The message size.
    135  *
    136  * \retval 0                                    If success.
    137  * \retval -1                                   Bad passed parameter, or can not allocate memory
    138  */
    139 int phDal4Nfc_msgsnd (intptr_t msqid, void * msgp, size_t msgsz, int msgflg)
    140 {
    141    phDal4Nfc_message_queue_t * pQueue;
    142    phDal4Nfc_message_queue_item_t * p;
    143    phDal4Nfc_message_queue_item_t * pNew;
    144 
    145    if ((msqid == 0) || (msgp == NULL) || (msgsz == 0))
    146       return -1;
    147 
    148    if (msgsz != sizeof(phLibNfc_Message_t))
    149       return -1;
    150 
    151    pQueue = (phDal4Nfc_message_queue_t *)msqid;
    152    pNew = (phDal4Nfc_message_queue_item_t *)phOsalNfc_GetMemory(sizeof(phDal4Nfc_message_queue_item_t));
    153    if (pNew == NULL)
    154       return -1;
    155    memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t));
    156    memcpy(&pNew->nMsg, &((phDal4Nfc_Message_Wrapper_t*)msgp)->msg, sizeof(phLibNfc_Message_t));
    157    pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    158    if (pQueue->pItems != NULL)
    159    {
    160       p = pQueue->pItems;
    161       while(p->pNext != NULL) { p = p->pNext; }
    162       p->pNext = pNew;
    163       pNew->pPrev = p;
    164    }
    165    else
    166    {
    167       pQueue->pItems = pNew;
    168    }
    169    pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    170 
    171    sem_post(&pQueue->nProcessSemaphore);
    172    return 0;
    173 }
    174 
    175 /**
    176  * \ingroup grp_nfc_dal
    177  *
    178  * \brief DAL message receive function
    179  * The call to this function will get the older message from the queue. If the queue is empty the function waits
    180  * (blocks on a mutex) until a message is posted to the queue with phDal4Nfc_msgsnd.
    181  * The msgtyp and msgflg parameters are ignored.
    182  *
    183  * \param[in]       msqid     The handle of the message queue.
    184  * \param[out]      msgp      The received message.
    185  * \param[in]       msgsz     The message size.
    186  *
    187  * \retval 0                                    If success.
    188  * \retval -1                                   Bad passed parameter.
    189  */
    190 int phDal4Nfc_msgrcv (intptr_t msqid, void * msgp, size_t msgsz, long msgtyp, int msgflg)
    191 {
    192    phDal4Nfc_message_queue_t * pQueue;
    193    phDal4Nfc_message_queue_item_t * p;
    194 
    195    if ((msqid == 0) || (msgp == NULL))
    196       return -1;
    197 
    198    if (msgsz != sizeof(phLibNfc_Message_t))
    199       return -1;
    200 
    201    pQueue = (phDal4Nfc_message_queue_t *)msqid;
    202    sem_wait(&pQueue->nProcessSemaphore);
    203    pthread_mutex_lock(&pQueue->nCriticalSectionMutex);
    204    if (pQueue->pItems != NULL)
    205    {
    206       memcpy(&((phDal4Nfc_Message_Wrapper_t*)msgp)->msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t));
    207       p = pQueue->pItems->pNext;
    208       phOsalNfc_FreeMemory(pQueue->pItems);
    209       pQueue->pItems = p;
    210    }
    211    pthread_mutex_unlock(&pQueue->nCriticalSectionMutex);
    212    return 0;
    213 }
    214 
    215 
    216 
    217 
    218 
    219