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 int 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 ((int)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 ( int 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 (int 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 (int 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