Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / caleadapter_singlethread.c
1 /******************************************************************
2 *
3 * Copyright 2014 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************/
20 #include "caleadapter_singlethread.h"
21
22 #include "caleinterface_singlethread.h"
23 #include "cableserver.h"
24 #include "logger.h"
25 #include "caadapterutils.h"
26 #include "camsgparser.h"
27
28 #define TAG "LAD"
29
30 /**
31  * @def MAX_EVENT_COUNT
32  * @brief Maximum number of tries to get the event on BLE Shield address.
33  */
34 #define MAX_EVENT_COUNT 20
35
36 static CANetworkChangeCallback g_networkCallback = NULL;
37 static bool g_serverRunning = false;
38 static CANetworkPacketReceivedCallback g_respCallback;
39 static char *g_coapBuffer = NULL;
40 static uint32_t g_dataLen = 0;
41 static uint32_t g_packetDataLen = 0;
42
43 /**
44  * @brief API to register for BLE network notification.
45  * @param net_callback - network notification callback.
46  * @return - Error Code
47  */
48 CAResult_t LERegisterNetworkNotifications(CANetworkChangeCallback netCallback);
49
50 /**
51  * @brief API to send received data to upper layer.
52  * @param[in] data - data received from BLE characteristics.
53  * @param[in] dataLen - received data Length.
54  * @param[in] senderAdrs - sender Address.
55  * @param[in] senderPort - sender port.
56  * @return - Error Code
57  */
58 void CANotifyCallback(const void *data, int32_t dataLen, const char *senderAdrs,
59                       int32_t senderPort);
60
61 /**
62  * @brief API to read the data from characteristics and invoke notifyCallback.
63  * @return - void
64  */
65 void CACheckData();
66
67 /**
68  * @brief API to Send the data.
69  * @return - Number of bytes sent. -1 on error.
70  */
71 int32_t CASendLEData(const void *data, uint32_t dataLen);
72
73 CAResult_t CAInitializeLE(CARegisterConnectivityCallback registerCallback,
74                           CANetworkPacketReceivedCallback reqRespCallback,
75                           CANetworkChangeCallback netCallback)
76 {
77     OIC_LOG(DEBUG, TAG, "IN");
78     if (NULL == registerCallback || NULL == reqRespCallback || NULL == netCallback)
79     {
80         OIC_LOG(ERROR, TAG, "i/p null");
81         return CA_STATUS_INVALID_PARAM;
82     }
83
84     CAResult_t result = CALEInitializeNetworkMonitor();
85     if (CA_STATUS_OK != result)
86     {
87         OIC_LOG_V(ERROR, TAG, "n/w init fail: %d", result);
88         return CA_STATUS_FAILED;
89     }
90
91     g_respCallback = reqRespCallback;
92     LERegisterNetworkNotifications(netCallback);
93     CAConnectivityHandler_t connHandler;
94     connHandler.startAdapter = CAStartLE;
95     connHandler.startListenServer = CAStartLEListeningServer;
96     connHandler.startDiscoveryServer = CAStartLEDiscoveryServer;
97     connHandler.sendData = CASendLEUnicastData;
98     connHandler.sendDataToAll = CASendLEMulticastData;
99     connHandler.GetnetInfo = CAGetLEInterfaceInformation;
100     connHandler.readData = CAReadLEData;
101     connHandler.stopAdapter = CAStopLE;
102     connHandler.terminate = CATerminateLE;
103     registerCallback(connHandler, CA_LE);
104     OIC_LOG(DEBUG, TAG, "OUT");
105     return CA_STATUS_OK;
106 }
107
108 CAResult_t CAStartLE()
109 {
110     OIC_LOG(DEBUG, TAG, "IN");
111     OIC_LOG(DEBUG, TAG, "OUT");
112     return CA_STATUS_OK;
113 }
114
115 CAResult_t CAStartLEListeningServer()
116 {
117     OIC_LOG(DEBUG, TAG, "IN");
118     CAResult_t result = CAInitializeBle();
119     if (CA_STATUS_OK != result)
120     {
121         OIC_LOG_V(ERROR, TAG, "ble init fail: %d", result);
122         return CA_STATUS_FAILED;
123     }
124     /**
125      * Below for loop is to process the BLE Events received from BLE Shield.
126      * BLE Events includes BLE Shield Address Added as a patch to RBL Library.
127      */
128     for (int iter = 0; iter < MAX_EVENT_COUNT; iter++)
129     {
130         CACheckData();
131     }
132
133     g_serverRunning = true;
134     OIC_LOG(DEBUG, TAG, "OUT");
135     return CA_STATUS_OK;
136 }
137
138 CAResult_t CAStartLEDiscoveryServer()
139 {
140     OIC_LOG(DEBUG, TAG, "IN");
141     OIC_LOG(DEBUG, TAG, "OUT");
142     return CA_STATUS_OK;
143 }
144
145 CAResult_t CAStartLENotifyServer()
146 {
147     OIC_LOG(DEBUG, TAG, "IN");
148     OIC_LOG(DEBUG, TAG, "OUT");
149     return CA_STATUS_OK;
150 }
151
152 uint32_t CASendLENotification(const CARemoteEndpoint_t *endpoint, const void *data,
153                               uint32_t dataLen)
154 {
155     OIC_LOG(DEBUG, TAG, "IN");
156     OIC_LOG(DEBUG, TAG, "OUT");
157     return 1;
158 }
159
160 int32_t CASendLEUnicastData(const CARemoteEndpoint_t *remoteEndpoint, const void *data,
161                             uint32_t dataLen)
162 {
163     OIC_LOG(DEBUG, TAG, "IN");
164     if (NULL == remoteEndpoint || NULL == data || dataLen == 0)
165     {
166         OIC_LOG(ERROR, TAG, "i/p null");
167         return -1;
168     }
169     OIC_LOG(DEBUG, TAG, "OUT");
170     return CASendLEData(data, dataLen);
171 }
172
173 int32_t CASendLEMulticastData(const void *data, uint32_t dataLen)
174 {
175     OIC_LOG(DEBUG, TAG, "IN");
176     if (NULL == data || 0 == dataLen)
177     {
178         OIC_LOG(ERROR, TAG, "i/p null");
179         return -1;
180     }
181
182     OIC_LOG(DEBUG, TAG, "OUT");
183     return CASendLEData(data, dataLen);
184 }
185
186 CAResult_t CAGetLEInterfaceInformation(CALocalConnectivity_t **info, uint32_t *size)
187 {
188     OIC_LOG(DEBUG, TAG, "IN");
189
190     if (NULL == info || NULL == size)
191     {
192         OIC_LOG(ERROR, TAG, "i/p null");
193         return CA_STATUS_INVALID_PARAM;
194     }
195
196     char *leAddress = NULL;
197     CAResult_t res = CAGetLEAddress(&leAddress);
198     if (CA_STATUS_OK != res)
199     {
200         OIC_LOG(ERROR, TAG, "CAGetLEAddress has failed");
201         return res;
202     }
203
204     if (NULL == leAddress)
205     {
206         OIC_LOG(ERROR, TAG, "Failed to get Le addr");
207         return CA_STATUS_FAILED;
208     }
209
210     OIC_LOG_V(DEBUG, TAG, "leAddress = %s", leAddress);
211
212     /**
213      * Create local endpoint using util function
214      */
215     (*info) = CAAdapterCreateLocalEndpoint(CA_LE, leAddress);
216     if (NULL == (*info))
217     {
218         OIC_LOG(ERROR, TAG, "malloc fail");
219         return CA_MEMORY_ALLOC_FAILED;
220     }
221
222     (*size) = 1;
223     if (*leAddress)
224     {
225         OICFree(leAddress);
226     }
227     OIC_LOG(DEBUG, TAG, "OUT");
228     return CA_STATUS_OK;
229 }
230
231 CAResult_t CAReadLEData()
232 {
233     if (true == g_serverRunning)
234     {
235         CACheckData();
236     }
237     return CA_STATUS_OK;
238 }
239
240 CAResult_t CAStopLE()
241 {
242     OIC_LOG(DEBUG, TAG, "IN");
243     CAStopBleGattServer();
244     OIC_LOG(DEBUG, TAG, "OUT");
245     return CA_STATUS_OK;
246 }
247
248 void CATerminateLE()
249 {
250     OIC_LOG(DEBUG, TAG, "IN");
251     g_respCallback = NULL;
252     LERegisterNetworkNotifications(NULL);
253     CAResult_t result = CATerminateBle();
254     if (CA_STATUS_OK != result)
255     {
256         OIC_LOG(ERROR, TAG, "ble terminate fail");
257         return;
258     }
259
260     CALETerminateNetworkMonitor();
261     g_serverRunning = false;
262     OIC_LOG(DEBUG, TAG, "OUT");
263     return;
264 }
265
266 CAResult_t LERegisterNetworkNotifications(CANetworkChangeCallback netCallback)
267 {
268     OIC_LOG(DEBUG, TAG, "IN");
269     g_networkCallback = netCallback;
270     OIC_LOG(DEBUG, TAG, "OUT");
271     return CA_STATUS_OK;
272 }
273
274 CAResult_t CAStartBleGattServer()
275 {
276     OIC_LOG(DEBUG, TAG, "IN");
277     // Done at time of setup i.e. in initializeBle api
278     OIC_LOG(DEBUG, TAG, "OUT");
279     return CA_STATUS_OK;
280 }
281
282 CAResult_t CAStopBleGattServer()
283 {
284     OIC_LOG(DEBUG, TAG, "IN");
285     // There is no server running to stop.
286     OIC_LOG(DEBUG, TAG, "OUT");
287     return CA_STATUS_OK;
288 }
289
290 void CANotifyCallback(const void *data, int32_t dataLen, const char *senderAdrs, int32_t senderPort)
291 {
292     OIC_LOG(DEBUG, TAG, "IN");
293     if (g_respCallback)
294     {
295
296         /* Cannot get Address as of now */
297         CARemoteEndpoint_t endPoint;
298         endPoint.resourceUri = "";     // will be filled by upper layer
299         endPoint.transportType= CA_LE;
300
301         g_respCallback(&endPoint, data, dataLen);
302     }
303     OIC_LOG(DEBUG, TAG, "OUT");
304 }
305
306 void CACheckData()
307 {
308     CABleDoEvents();
309
310     if (CAIsBleDataAvailable())
311     {
312         // Allocate Memory for COAP Buffer and do ParseHeader
313         if (NULL == g_coapBuffer)
314         {
315             OIC_LOG(DEBUG, TAG, "IN");
316             char headerArray[CA_HEADER_LENGTH] = "";
317             while (CAIsBleDataAvailable() && g_dataLen < CA_HEADER_LENGTH)
318             {
319                 headerArray[g_dataLen++] = CAReadBleData();
320             }
321
322             g_packetDataLen = CAParseHeader(headerArray);
323
324             if (g_packetDataLen > COAP_MAX_PDU_SIZE)
325             {
326                 OIC_LOG(ERROR, TAG, "len > pdu_size");
327                 return;
328             }
329
330             g_coapBuffer = (char *)OICCalloc((size_t)g_packetDataLen, sizeof(char));
331             if (NULL == g_coapBuffer)
332             {
333                 OIC_LOG(ERROR, TAG, "malloc");
334                 return;
335             }
336
337             OIC_LOG(DEBUG, TAG, "OUT");
338             g_dataLen = 0;
339         }
340
341         OIC_LOG(DEBUG, TAG, "IN");
342         while (CAIsBleDataAvailable())
343         {
344             OIC_LOG(DEBUG, TAG, "In While loop");
345             g_coapBuffer[g_dataLen++] = CAReadBleData();
346             if (g_dataLen == g_packetDataLen)
347             {
348                 OIC_LOG(DEBUG, TAG, "Read Comp BLE Pckt");
349                 g_coapBuffer[g_dataLen] = '\0';
350                 if (g_dataLen > 0)
351                 {
352                     OIC_LOG_V(DEBUG, TAG, "recv dataLen=%d", g_dataLen);
353                     CANotifyCallback((void *)g_coapBuffer, g_dataLen, "", 0);
354                 }
355                 g_dataLen = 0;
356                 OICFree(g_coapBuffer);
357                 g_coapBuffer = NULL;
358                 break;
359             }
360         }
361         OIC_LOG(DEBUG, TAG, "OUT");
362     }
363     else
364     {
365         OIC_LOG(DEBUG, TAG, "NoData");
366     }
367     return;
368 }
369
370 int32_t CASendLEData(const void *data, uint32_t dataLen)
371 {
372     OIC_LOG(DEBUG, TAG, "IN");
373     char header[CA_HEADER_LENGTH] = {0};
374
375     CAResult_t result = CAGenerateHeader(header, dataLen);
376
377     if (CA_STATUS_OK != result)
378     {
379         OIC_LOG(ERROR, TAG, "Generate header failed");
380         return -1;
381     }
382
383     if (!CAIsBleConnected())
384     {
385         OIC_LOG(ERROR, TAG, "le not conn");
386         return -1;
387     }
388
389     result = CAUpdateCharacteristicsToAllGattClients(header, CA_HEADER_LENGTH);
390     if (CA_STATUS_OK != result)
391     {
392         OIC_LOG(ERROR, TAG, "Update characteristics failed");
393         return -1;
394     }
395
396     int32_t dataLimit = dataLen / CA_SUPPORTED_BLE_MTU_SIZE;
397     for (int32_t iter = 0; iter < dataLimit; iter++)
398     {
399         result = CAUpdateCharacteristicsToAllGattClients((data +
400                                                          (iter * CA_SUPPORTED_BLE_MTU_SIZE)),
401                                                          CA_SUPPORTED_BLE_MTU_SIZE);
402         if (CA_STATUS_OK != result)
403         {
404             OIC_LOG(ERROR, TAG, "Update characteristics failed");
405             return -1;
406         }
407         CABleDoEvents();
408     }
409
410     uint8_t remainingLen = dataLen % CA_SUPPORTED_BLE_MTU_SIZE;
411     if(remainingLen)
412     {
413         result = CAUpdateCharacteristicsToAllGattClients((data +
414                                                          (dataLimit * CA_SUPPORTED_BLE_MTU_SIZE)),
415                                                          remainingLen);
416         if (CA_STATUS_OK != result)
417         {
418             OIC_LOG(ERROR, TAG, "Update characteristics failed");
419             return -1;
420         }
421         CABleDoEvents();
422     }
423
424     OIC_LOG(DEBUG, TAG, "writebytes done");
425     OIC_LOG(DEBUG, TAG, "OUT");
426     // Arduino BLEWrite doesnot return value. So, Return the received DataLength
427     return dataLen;
428 }
429