6e2c639af045f2f8ea09a82dbf73519bfe7c85a3
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / arduino / cableserver.cpp
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
21
22 //logger.h included first to avoid conflict with RBL library PROGMEM attribute
23 #include "logger.h"
24
25 #include "cableserver.h"
26
27 #include <Arduino.h>
28 #include <SPI.h>
29 #include <boards.h>
30 #include <RBL_nRF8001.h>
31
32 #include "pdu.h"
33 #include "caleinterface.h"
34 #include "oic_malloc.h"
35 #include "caadapterutils.h"
36
37 #define TAG "LES"
38 /**
39  * Maximum TCP header length.
40  */
41 #define TCP_MAX_HEADER_LENGTH 6
42
43 /**
44  * Maintains the callback to be notified on receival of network packets from other
45  * BLE devices
46  */
47 static CABLEDataReceivedCallback g_bleServerDataReceivedCallback = NULL;
48
49 /**
50  * Maximum number of tries to get the event on BLE Shield address.
51  */
52 #define MAX_EVENT_COUNT 20
53
54 static bool g_serverRunning = false;
55 static uint8_t *g_coapBuffer = NULL;
56
57 /**
58  * Actual length of data received.
59  */
60 static size_t g_receivedDataLen = 0;
61
62 /**
63  * Total Length of data that is being fragmented.
64  */
65 static size_t g_packetDataLen = 0;
66
67 void CAGetTCPHeaderDetails(unsigned char* recvBuffer, size_t *headerlen)
68 {
69     coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
70         ((unsigned char *)recvBuffer)[0] >> 4);
71     *headerlen = coap_get_tcp_header_length_for_transport(transport);
72 }
73
74 void CACheckLEDataInternal()
75 {
76     CALEDoEvents();
77
78     if (CAIsLEDataAvailable())
79     {
80         // Allocate Memory for COAP Buffer and do ParseHeader
81         if (NULL == g_coapBuffer)
82         {
83             OIC_LOG(DEBUG, TAG, "IN");
84             size_t bufSize = TCP_MAX_HEADER_LENGTH;
85             g_coapBuffer = (uint8_t *)OICCalloc(bufSize, 1);
86             if (NULL == g_coapBuffer)
87             {
88                 OIC_LOG(ERROR, TAG, "malloc");
89                 return;
90             }
91
92             g_coapBuffer[g_receivedDataLen++] = CALEReadData();
93             size_t headerLen;
94             CAGetTCPHeaderDetails(g_coapBuffer, &headerLen);
95             OIC_LOG_V(INFO, TAG, "hdr len %d", headerLen);
96             while (CAIsLEDataAvailable() && g_receivedDataLen < headerLen)
97             {
98                 g_coapBuffer[g_receivedDataLen++] = CALEReadData();
99             }
100
101             g_packetDataLen = coap_get_total_message_length(g_coapBuffer, g_receivedDataLen);
102             OIC_LOG_V(INFO, TAG, "pkt len %d", g_packetDataLen);
103             if (g_packetDataLen > COAP_MAX_PDU_SIZE)
104             {
105                 OIC_LOG(ERROR, TAG, "len > pdu_size");
106                 return;
107             }
108
109             bufSize = g_packetDataLen;
110             uint8_t *newBuf = (uint8_t *)OICRealloc(g_coapBuffer, bufSize);
111             if (NULL == newBuf)
112             {
113                 OIC_LOG(ERROR, TAG, "malloc");
114                 OICFree(g_coapBuffer);
115                 g_coapBuffer = NULL;
116                 return;
117             }
118             g_coapBuffer = newBuf;
119         }
120
121         while (CAIsLEDataAvailable())
122         {
123             OIC_LOG(DEBUG, TAG, "In While loop");
124             g_coapBuffer[g_receivedDataLen++] = CALEReadData();
125             if (g_receivedDataLen == g_packetDataLen)
126             {
127                 OIC_LOG(DEBUG, TAG, "Read Comp BLE Pckt");
128                 if (g_receivedDataLen > 0)
129                 {
130                     OIC_LOG_V(DEBUG, TAG, "recv dataLen=%u", g_receivedDataLen);
131                     uint32_t sentLength = 0;
132                     // g_coapBuffer getting freed by CAMesssageHandler
133                     g_bleServerDataReceivedCallback("", g_coapBuffer,
134                                                     g_receivedDataLen, &sentLength);
135                 }
136
137                 g_receivedDataLen = 0;
138                 OICFree(g_coapBuffer);
139                 g_coapBuffer = NULL;
140                 break;
141             }
142         }
143         OIC_LOG(DEBUG, TAG, "OUT");
144     }
145     else
146     {
147         OIC_LOG(DEBUG, TAG, "NoData");
148     }
149     return;
150 }
151
152 CAResult_t CALEInitialize()
153 {
154     OIC_LOG(DEBUG, TAG, "IN");
155
156     // Set your BLE Shield name here, max. length 10
157     ble_set_name(__OIC_DEVICE_NAME__);
158
159     OIC_LOG(DEBUG, TAG, "LEName Set");
160
161     ble_begin();
162
163     OIC_LOG(DEBUG, TAG, "OUT");
164     return CA_STATUS_OK;
165 }
166
167 void CASetLEServerThreadPoolHandle(ca_thread_pool_t handle)
168 {
169     OIC_LOG(DEBUG, TAG, "IN");
170     OIC_LOG(DEBUG, TAG, "OUT");
171 }
172
173 void CASetBLEServerErrorHandleCallback(CABLEErrorHandleCallback callback)
174 {
175     OIC_LOG(DEBUG, TAG, "IN");
176     OIC_LOG(DEBUG, TAG, "OUT");
177 }
178
179 unsigned char CAIsLEDataAvailable()
180 {
181     return ble_available();
182 }
183
184 unsigned char CAIsLEConnected()
185 {
186     return ble_connected();
187 }
188
189 uint8_t CALEReadData()
190 {
191     return (uint8_t)ble_read();
192 }
193
194 CAResult_t CALEDoEvents()
195 {
196     ble_do_events();
197     return CA_STATUS_OK;
198 }
199
200 CAResult_t CAUpdateCharacteristicsToAllGattClients(const uint8_t *char_value,
201                                                    uint32_t valueLength)
202 {
203     // ble_write_bytes() api can send only max of 255 bytes at a time
204     // This function shall never be called to send more than 255 bytes by the fragmentation logic.
205     // Currently ble_write_bytes api returns void.
206     ble_write_bytes((unsigned char *)char_value, (unsigned char)valueLength);
207     return CA_STATUS_OK;
208 }
209
210 void CASetLEReqRespServerCallback(CABLEDataReceivedCallback callback)
211 {
212     OIC_LOG(DEBUG, TAG, "IN");
213     g_bleServerDataReceivedCallback = callback;
214     OIC_LOG(DEBUG, TAG, "OUT");
215 }
216
217 CAResult_t CAStartLEGattServer()
218 {
219     OIC_LOG(DEBUG, TAG, "IN");
220     CAResult_t result = CALEInitialize();
221     if (CA_STATUS_OK != result)
222     {
223         OIC_LOG_V(ERROR, TAG, "ble init fail: %d", result);
224         return CA_STATUS_FAILED;
225     }
226     /**
227      * Below for loop is to process the BLE Events received from BLE Shield.
228      * BLE Events includes BLE Shield Address Added as a patch to RBL Library.
229      */
230     for (int iter = 0; iter < MAX_EVENT_COUNT; iter++)
231     {
232         CACheckLEDataInternal();
233     }
234
235     g_serverRunning = true;
236     OIC_LOG(DEBUG, TAG, "OUT");
237     return CA_STATUS_OK;
238 }
239
240 CAResult_t CAStopLEGattServer()
241 {
242     OIC_LOG(DEBUG, TAG, "IN");
243     CATerminateLEGattServer();
244     OIC_LOG(DEBUG, TAG, "OUT");
245     return CA_STATUS_OK;
246 }
247
248 CAResult_t CAInitializeLEGattServer()
249 {
250     OIC_LOG(DEBUG, TAG, "Initialize GATT Server");
251     return CA_STATUS_OK;
252 }
253
254 void CATerminateLEGattServer()
255 {
256     OIC_LOG(DEBUG, TAG, "IN");
257     if (true == g_serverRunning)
258     {
259         ble_radio_reset();
260         g_serverRunning = false;
261     }
262     OIC_LOG(DEBUG, TAG, "OUT");
263     return;
264 }
265
266 void CACheckLEData()
267 {
268     if (false == g_serverRunning)
269     {
270         OIC_LOG(ERROR, TAG, "Server is not running");
271         return;
272     }
273     CACheckLEDataInternal();
274 }