/* * Copyright (C) 2010 NXP Semiconductors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * \file phDalNfc_messageQueueLib.c * \brief DAL independant message queue implementation for android (can be used under linux too) * * Project: Trusted NFC Linux Lignt * * $Date: 13 aug 2009 * $Author: Jonathan roux * $Revision: 1.0 $ * */ #include <pthread.h> #ifdef ANDROID #include <linux/ipc.h> #else #include <sys/msg.h> #endif #include <semaphore.h> #include <phDal4Nfc.h> #include <phOsalNfc.h> #include <phDal4Nfc_DeferredCall.h> #include <phDal4Nfc_messageQueueLib.h> typedef struct phDal4Nfc_message_queue_item { phLibNfc_Message_t nMsg; struct phDal4Nfc_message_queue_item * pPrev; struct phDal4Nfc_message_queue_item * pNext; } phDal4Nfc_message_queue_item_t; typedef struct phDal4Nfc_message_queue { phDal4Nfc_message_queue_item_t * pItems; pthread_mutex_t nCriticalSectionMutex; sem_t nProcessSemaphore; } phDal4Nfc_message_queue_t; /** * \ingroup grp_nfc_dal * * \brief DAL message get function * This function allocates the message queue. The parameters are ignored, this is * just to keep the same api as Linux queue. * * \retval -1 Can not allocate memory or can not init mutex. * \retval handle The handle on the message queue. */ intptr_t phDal4Nfc_msgget ( key_t key, int msgflg ) { phDal4Nfc_message_queue_t * pQueue; pQueue = (phDal4Nfc_message_queue_t *) phOsalNfc_GetMemory(sizeof(phDal4Nfc_message_queue_t)); if (pQueue == NULL) return -1; memset(pQueue, 0, sizeof(phDal4Nfc_message_queue_t)); if (pthread_mutex_init (&pQueue->nCriticalSectionMutex, NULL) == -1) return -1; if (sem_init (&pQueue->nProcessSemaphore, 0, 0) == -1) return -1; return ((intptr_t)pQueue); } /** * \ingroup grp_nfc_dal * * \brief DAL message control function * This function destroys the message queue. The cmd and buf parameters are ignored, * this is just to keep the same api as Linux queue. * * \param[in] msqid The handle of the message queue. * * \retval 0 If success. * \retval -1 Bad passed parameter */ int phDal4Nfc_msgctl ( intptr_t msqid, int cmd, void *buf ) { phDal4Nfc_message_queue_t * pQueue; phDal4Nfc_message_queue_item_t * p; if (msqid == 0) return -1; pQueue = (phDal4Nfc_message_queue_t *)msqid; pthread_mutex_lock(&pQueue->nCriticalSectionMutex); if (pQueue->pItems != NULL) { p = pQueue->pItems; while(p->pNext != NULL) { p = p->pNext; } while(p->pPrev != NULL) { p = p->pPrev; phOsalNfc_FreeMemory(p->pNext); p->pNext = NULL; } phOsalNfc_FreeMemory(p); } pQueue->pItems = NULL; pthread_mutex_unlock(&pQueue->nCriticalSectionMutex); pthread_mutex_destroy(&pQueue->nCriticalSectionMutex); phOsalNfc_FreeMemory(pQueue); return 0; } /** * \ingroup grp_nfc_dal * * \brief DAL message send function * Use this function to send a message to the queue. The message will be added at the end of * the queue with respect to FIFO policy. The msgflg parameter is ignored. * * \param[in] msqid The handle of the message queue. * \param[in] msgp The message to send. * \param[in] msgsz The message size. * * \retval 0 If success. * \retval -1 Bad passed parameter, or can not allocate memory */ int phDal4Nfc_msgsnd (intptr_t msqid, void * msgp, size_t msgsz, int msgflg) { phDal4Nfc_message_queue_t * pQueue; phDal4Nfc_message_queue_item_t * p; phDal4Nfc_message_queue_item_t * pNew; if ((msqid == 0) || (msgp == NULL) || (msgsz == 0)) return -1; if (msgsz != sizeof(phLibNfc_Message_t)) return -1; pQueue = (phDal4Nfc_message_queue_t *)msqid; pNew = (phDal4Nfc_message_queue_item_t *)phOsalNfc_GetMemory(sizeof(phDal4Nfc_message_queue_item_t)); if (pNew == NULL) return -1; memset(pNew, 0, sizeof(phDal4Nfc_message_queue_item_t)); memcpy(&pNew->nMsg, &((phDal4Nfc_Message_Wrapper_t*)msgp)->msg, sizeof(phLibNfc_Message_t)); pthread_mutex_lock(&pQueue->nCriticalSectionMutex); if (pQueue->pItems != NULL) { p = pQueue->pItems; while(p->pNext != NULL) { p = p->pNext; } p->pNext = pNew; pNew->pPrev = p; } else { pQueue->pItems = pNew; } pthread_mutex_unlock(&pQueue->nCriticalSectionMutex); sem_post(&pQueue->nProcessSemaphore); return 0; } /** * \ingroup grp_nfc_dal * * \brief DAL message receive function * The call to this function will get the older message from the queue. If the queue is empty the function waits * (blocks on a mutex) until a message is posted to the queue with phDal4Nfc_msgsnd. * The msgtyp and msgflg parameters are ignored. * * \param[in] msqid The handle of the message queue. * \param[out] msgp The received message. * \param[in] msgsz The message size. * * \retval 0 If success. * \retval -1 Bad passed parameter. */ int phDal4Nfc_msgrcv (intptr_t msqid, void * msgp, size_t msgsz, long msgtyp, int msgflg) { phDal4Nfc_message_queue_t * pQueue; phDal4Nfc_message_queue_item_t * p; if ((msqid == 0) || (msgp == NULL)) return -1; if (msgsz != sizeof(phLibNfc_Message_t)) return -1; pQueue = (phDal4Nfc_message_queue_t *)msqid; sem_wait(&pQueue->nProcessSemaphore); pthread_mutex_lock(&pQueue->nCriticalSectionMutex); if (pQueue->pItems != NULL) { memcpy(&((phDal4Nfc_Message_Wrapper_t*)msgp)->msg, &(pQueue->pItems)->nMsg, sizeof(phLibNfc_Message_t)); p = pQueue->pItems->pNext; phOsalNfc_FreeMemory(pQueue->pItems); pQueue->pItems = p; } pthread_mutex_unlock(&pQueue->nCriticalSectionMutex); return 0; }