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