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