Drop arduino support: SINGLE_THREAD
[iotivity.git] / resource / csdk / connectivity / src / nfc_adapter / canfcadapter.c
1 /* *****************************************************************
2  * Copyright 2015 Samsung Electronics All Rights Reserved.
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 #include "canfcadapter.h"
18
19 #include "canfcinterface.h"
20 #include "caqueueingthread.h"
21 #include "caadapterutils.h"
22 #include "octhread.h"
23 #include "uarraylist.h"
24 #include "caremotehandler.h"
25 #include "experimental/logger.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28
29 /**
30  * Logging tag for module name
31  */
32 #define TAG "NFC_ADAP"
33
34 /**
35  * Holds inter thread nfc data information.
36  */
37
38 typedef struct
39 {
40     CAEndpoint_t *remoteEndpoint;
41     void *data;
42     uint32_t dataLen;
43 } CANFCData;
44
45 /**
46  * Reference to threadpool.
47  */
48 static ca_thread_pool_t g_nfcThreadPool = NULL;
49
50 /**
51  * Queue handle for Send Data
52  */
53 static CAQueueingThread_t *g_sendQueueHandle = NULL;
54
55 /**
56  * Network Packet Received Callback to CA
57  */
58 static CANetworkPacketReceivedCallback g_packetReceivedCallback = NULL;
59
60 /**
61  *  Adapter Changed Callback to CA
62  */
63 static CAAdapterChangeCallback g_adapterStateCallback = NULL;
64
65 /**
66  * error Callback to CA adapter
67  */
68 static CAErrorHandleCallback g_errorCallback = NULL;
69
70 static void CANFCPacketReceivedCB(const CASecureEndpoint_t *endpoint, const void *data,
71                                   size_t dataLength);
72
73 static CAResult_t CANFCInitializeQueueHandles();
74
75 static void CANFCDeinitializeQueueHandles();
76
77 static void CANFCSendDataThread(void *threadData);
78
79 CANFCData *CACreateNFCData(const CAEndpoint_t *remoteEndpoint, const void *data,
80                            uint32_t dataLength);
81
82 void CAFreeNFCData(CANFCData *ipData);
83
84 static void CANFCDataDestroyer(void *data, uint32_t size);
85
86 CAResult_t CANFCInitializeQueueHandles()
87 {
88     OIC_LOG(DEBUG, TAG, "IN");
89
90     // Check if the message queue is already initialized
91     if (g_sendQueueHandle)
92     {
93         OIC_LOG(DEBUG, TAG, "send queue handle is already initialized!");
94         return CA_STATUS_OK;
95     }
96
97     // Create send message queue
98     g_sendQueueHandle = OICCalloc(1, sizeof(*g_sendQueueHandle));
99     if (!g_sendQueueHandle)
100     {
101         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
102         return CA_MEMORY_ALLOC_FAILED;
103     }
104
105     if (CA_STATUS_OK
106         != CAQueueingThreadInitialize(g_sendQueueHandle, (const ca_thread_pool_t) g_nfcThreadPool,
107                                       CANFCSendDataThread, CANFCDataDestroyer))
108     {
109         OIC_LOG(ERROR, TAG, "Failed to Initialize send queue thread");
110         OICFree(g_sendQueueHandle);
111         g_sendQueueHandle = NULL;
112         return CA_STATUS_FAILED;
113     }
114
115     OIC_LOG(DEBUG, TAG, "OUT");
116     return CA_STATUS_OK;
117 }
118
119 void CANFCDeinitializeQueueHandles()
120 {
121     OIC_LOG(DEBUG, TAG, "IN");
122
123     CAQueueingThreadDestroy(g_sendQueueHandle);
124     OICFree(g_sendQueueHandle);
125     g_sendQueueHandle = NULL;
126
127     OIC_LOG(DEBUG, TAG, "OUT");
128 }
129
130 void CANFCConnectionStateCB(const char *nfcAddress, CANetworkStatus_t status)
131 {
132     OIC_LOG(DEBUG, TAG, "Currently Not Supported");
133
134     (void)nfcAddress;
135     (void)status;
136 }
137
138 void CANFCPacketReceivedCB(const CASecureEndpoint_t *sep, const void *data, size_t dataLength)
139 {
140     OIC_LOG(DEBUG, TAG, "IN");
141
142     VERIFY_NON_NULL_VOID(sep, TAG, "endpoint is NULL");
143     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
144
145     if (0 == dataLength)
146     {
147         OIC_LOG(ERROR, TAG, "Invalid call, data length is 0");
148         return;
149     }
150
151     OIC_LOG_V(DEBUG, TAG, "Address: %s, port:%d", sep->endpoint.addr, sep->endpoint.port);
152
153     if (g_packetReceivedCallback)
154     {
155         g_packetReceivedCallback(sep, data, dataLength);
156     }
157
158     OIC_LOG(DEBUG, TAG, "OUT");
159 }
160
161 void CANFCErrorHandler(const CAEndpoint_t *endpoint, const void *data, size_t dataLength,
162                        CAResult_t result)
163 {
164     OIC_LOG(DEBUG, TAG, "IN");
165
166     VERIFY_NON_NULL_VOID(endpoint, TAG, "endpoint is NULL");
167
168     VERIFY_NON_NULL_VOID(data, TAG, "data is NULL");
169     if (g_errorCallback)
170     {
171         g_errorCallback(endpoint, data, dataLength, result);
172     }
173     OIC_LOG(DEBUG, TAG, "OUT");
174 }
175
176 CAResult_t CAInitializeNFC(CARegisterConnectivityCallback registerCallback,
177                            CANetworkPacketReceivedCallback packetReceivedCallback,
178                            CAAdapterChangeCallback netCallback,
179                            CAErrorHandleCallback errorCallback, ca_thread_pool_t handle)
180 {
181     OIC_LOG(DEBUG, TAG, "IN");
182     VERIFY_NON_NULL(registerCallback, TAG, "registerCallback");
183     VERIFY_NON_NULL(packetReceivedCallback, TAG, "packetReceivedCallback");
184     VERIFY_NON_NULL(netCallback, TAG, "netCallback");
185     VERIFY_NON_NULL(handle, TAG, "thread pool handle");
186
187     g_adapterStateCallback = netCallback;
188     g_packetReceivedCallback = packetReceivedCallback;
189     g_errorCallback = errorCallback;
190
191     g_nfcThreadPool = handle;
192
193     CAResult_t result = CAInitializeNfcServer();
194     if (CA_STATUS_OK != result)
195     {
196         OIC_LOG(ERROR, TAG, "CAInitializeNfcServer failed");
197         return result;
198     }
199
200     CANFCSetPacketReceiveCallback(CANFCPacketReceivedCB);
201     static const CAConnectivityHandler_t nfcHandler =
202         {
203             .startAdapter = CAStartNFC,
204             .stopAdapter = CAStopNFC,
205             .startListenServer = CAStartNFCListeningServer,
206             .stopListenServer = CAStopNFCListeningServer,
207             .startDiscoveryServer = CAStartNFCDiscoveryServer,
208             .sendData = CASendNFCUnicastData,
209             .sendDataToAll = CASendNFCMulticastData,
210             .GetnetInfo = CAGetNFCInterfaceInformation,
211             .readData = CAReadNFCData,
212             .terminate = CATerminateNFC,
213             .cType = CA_ADAPTER_NFC
214         };
215     registerCallback(nfcHandler);
216
217     OIC_LOG(INFO, TAG, "OUT Intialize NFC is Success");
218     return CA_STATUS_OK;
219 }
220
221 CAResult_t CAStartNFC()
222 {
223
224     OIC_LOG(DEBUG, TAG, "IN");
225     CAResult_t res = CANFCInitializeQueueHandles();
226
227     if (CA_STATUS_OK != res)
228     {
229         OIC_LOG(ERROR, TAG, "Failed to Initialize Queue Handle");
230         return res;
231     }
232
233     res = CAQueueingThreadStart(g_sendQueueHandle);
234     // Start send queue thread
235     if (CA_STATUS_OK != res)
236     {
237         OIC_LOG(ERROR, TAG, "Failed to Start Send Data Thread");
238         return res;
239     }
240
241     OIC_LOG(DEBUG, TAG, "OUT");
242     return CA_STATUS_OK;
243 }
244
245 CAResult_t CAStartNFCListeningServer()
246 {
247     OIC_LOG(DEBUG, TAG, "IN");
248
249     CAResult_t ret = CANFCStartServer();
250     if (CA_STATUS_OK != ret)
251     {
252         OIC_LOG_V(ERROR, TAG, "Failed to start server![%d]", ret);
253         return ret;
254     }
255
256     OIC_LOG(DEBUG, TAG, "OUT");
257     return CA_STATUS_OK;
258 }
259
260 CAResult_t CAStopNFCListeningServer()
261 {
262     CANFCStopServer();
263     return CA_STATUS_OK;
264 }
265
266 CAResult_t CAStartNFCDiscoveryServer()
267 {
268     return CAStartNFCListeningServer();
269 }
270
271 static int32_t CAQueueNFCData(const CAEndpoint_t *endpoint, const void *data,
272                               uint32_t dataLength)
273 {
274     OIC_LOG(DEBUG, TAG, "IN");
275
276     VERIFY_NON_NULL_RET(endpoint, TAG, "remoteEndpoint", -1);
277     VERIFY_NON_NULL_RET(data, TAG, "data", -1);
278
279     if (0 == dataLength)
280     {
281         OIC_LOG(ERROR, TAG, "Invalid Data Length");
282         return -1;
283     }
284
285     VERIFY_NON_NULL_RET(g_sendQueueHandle, TAG, "sendQueueHandle", -1);
286     // Create NFCData to add to queue
287     CANFCData *nfcData = CACreateNFCData(endpoint, data, dataLength);
288     if (!nfcData)
289     {
290         OIC_LOG(ERROR, TAG, "Failed to create ipData!");
291         return -1;
292     }
293     // Add message to send queue
294     CAQueueingThreadAddData(g_sendQueueHandle, nfcData, sizeof(CANFCData));
295
296     OIC_LOG(DEBUG, TAG, "OUT");
297     return dataLength;
298
299 }
300
301 int32_t CASendNFCUnicastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength,
302                              CADataType_t dataType)
303 {
304     (void)dataType;
305     return CAQueueNFCData(endpoint, data, dataLength);
306 }
307
308 int32_t CASendNFCMulticastData(const CAEndpoint_t *endpoint, const void *data, uint32_t dataLength,
309                                CADataType_t dataType)
310 {
311     (void)dataType;
312     return CAQueueNFCData(endpoint, data, dataLength);
313 }
314
315 CAResult_t CAReadNFCData()
316 {
317 #if 0
318     OIC_LOG(DEBUG, TAG, "IN");
319     CANFCPullData();
320     OIC_LOG(DEBUG, TAG, "OUT");
321 #endif
322     return CA_STATUS_OK;
323 }
324
325 CAResult_t CAStopNFC()
326 {
327     OIC_LOG(DEBUG, TAG, "IN");
328
329     if (g_sendQueueHandle && g_sendQueueHandle->threadMutex)
330     {
331         CAQueueingThreadStop(g_sendQueueHandle);
332     }
333
334     CANFCDeinitializeQueueHandles();
335
336     CANFCStopServer();
337
338     OIC_LOG(DEBUG, TAG, "OUT");
339
340     return CA_STATUS_OK;
341 }
342
343 void CATerminateNFC()
344 {
345
346     OIC_LOG(DEBUG, TAG, "IN");
347     CANFCSetPacketReceiveCallback(NULL);
348     CANFCDeinitializeQueueHandles();
349
350     OIC_LOG(DEBUG, TAG, "OUT");
351 }
352
353 void CANFCSendDataThread(void *threadData)
354 {
355     OIC_LOG(DEBUG, TAG, "IN");
356     CANFCData *nfcData = (CANFCData *) threadData;
357     if (!nfcData)
358     {
359         OIC_LOG(ERROR, TAG, "Invalid ip data!");
360         return;
361     }
362
363     CANFCSendData(nfcData->remoteEndpoint, nfcData->data, nfcData->dataLen);
364     OIC_LOG(DEBUG, TAG, "OUT");
365 }
366
367 CANFCData *CACreateNFCData(const CAEndpoint_t *remoteEndpoint, const void *data,
368                            uint32_t dataLength)
369 {
370     VERIFY_NON_NULL_RET(data, TAG, "NFCData is NULL", NULL);
371
372     CANFCData *nfcData = (CANFCData *) OICCalloc(1,sizeof(*nfcData));
373     if (!nfcData)
374     {
375         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
376         return NULL;
377     }
378
379     nfcData->remoteEndpoint = CACloneEndpoint(remoteEndpoint);
380     nfcData->data = (void *) OICMalloc(dataLength);
381     if (!nfcData->data)
382     {
383         OIC_LOG(ERROR, TAG, "Memory allocation failed!");
384         CAFreeNFCData(nfcData);
385         return NULL;
386     }
387
388     memcpy(nfcData->data, data, dataLength);
389     nfcData->dataLen = dataLength;
390
391     return nfcData;
392
393 }
394
395 void CAFreeNFCData(CANFCData *nfcData)
396 {
397     if (nfcData)
398     {
399         CAFreeEndpoint(nfcData->remoteEndpoint);
400         OICFree(nfcData->data);
401         OICFree(nfcData);
402     }
403 }
404
405 void CANFCDataDestroyer(void *data, uint32_t size)
406 {
407     CANFCData *nfcData = (CANFCData *) data;
408
409     CAFreeNFCData(nfcData);
410     (void)size;
411 }
412
413 CAResult_t CAGetNFCInterfaceInformation(CAEndpoint_t **info, size_t *size)
414 {
415     OIC_LOG(DEBUG, TAG, "CAGetNFCInterfaceInformation not supported");
416     if (!info || !size)
417     {
418         OIC_LOG(ERROR, TAG, "CAGetNFCInterfaceInformation : Invalid Input");
419         return CA_STATUS_FAILED;
420     }
421
422     return CA_STATUS_OK;
423 }