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  */
phDal4Nfc_msgget(key_t key,int msgflg)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  */
phDal4Nfc_msgctl(intptr_t msqid,int cmd,void * buf)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  */
phDal4Nfc_msgsnd(intptr_t msqid,void * msgp,size_t msgsz,int msgflg)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  */
phDal4Nfc_msgrcv(intptr_t msqid,void * msgp,size_t msgsz,long msgtyp,int msgflg)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