caedrclient.c 33 KB
Newer Older
1
/* ****************************************************************
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * Copyright 2014 Samsung Electronics All Rights Reserved.
 *
 *
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************/

/**
22 23 24 25
 * @file
 *
 * This file provides the APIs to establish RFCOMM connection with remote
 * bluetooth device.
26
 */
27

28 29
#include <string.h>
#include <bluetooth.h>
30
#include <bluetooth_internal.h>
31 32

#include "caedrinterface.h"
33
#include "octhread.h"
34 35 36 37 38 39 40
#include "caedrendpoint.h"
#include "caadapterutils.h"
#include "caedrutils.h"
#include "logger.h"
#include "cacommon.h"
#include "caedrdevicelist.h"

41 42
#define MICROSECS_PER_SEC 1000000

43 44 45 46 47 48
/**
 * Maximum CoAP over TCP header length
 * to know the total data length.
 */
#define EDR_MAX_HEADER_LEN  6

49
/**
50
 * Mutex to synchronize the access to Bluetooth device information list.
51
 */
52
static oc_mutex g_edrDeviceListMutex = NULL;
53 54

/**
55
 * Peer Bluetooth device information list.
56
 */
57
static EDRDeviceList *g_edrDeviceList = NULL;
58 59

/**
60 61
 * Maintains the callback to be notified when data received from remote
 * Bluetooth device.
62
 */
63
static CAEDRDataReceivedCallback g_edrPacketReceivedCallback = NULL;
64

65
/**
66
 * Error callback to update error in EDR.
67 68
 */
static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
69

vimala.v's avatar
vimala.v committed
70 71 72 73 74 75 76 77
/**
 * Pending multicast data list to be sent.
 */
static u_arraylist_t *g_multicastDataList = NULL;

/**
 * Mutex to synchronize the access to Pending multicast data list.
 */
78
static oc_mutex g_multicastDataListMutex = NULL;
vimala.v's avatar
vimala.v committed
79

koushik.girijala's avatar
koushik.girijala committed
80 81 82 83 84
/**
 * To Store Adapter Mode information
 */
static bool g_isDiscoveryServer = false;

85
/**
86
 * This function creates mutex.
87
 */
88
static CAResult_t CAEDRManagerInitializeMutex(void);
89 90

/**
91
 * This function frees mutex.
92 93 94 95
 */
static void CAEDRManagerTerminateMutex(void);

/**
96
 * This callback is registered to recieve data on any open RFCOMM connection.
97 98 99 100
 */
static void CAEDRDataRecvCallback(bt_socket_received_data_s *data, void *userData);

/**
101
 * This function stops any ongoing service sevice search.
102 103 104 105
 */
static CAResult_t CAEDRStopServiceSearch(void);

/**
106
 * This function stops device discovery.
107 108 109 110
 */
static CAResult_t CAEDRStopDeviceDiscovery(void);

/**
111
 * This function searches for OIC service for remote Bluetooth device.
112 113 114 115
 */
static CAResult_t CAEDRStartServiceSearch(const char *remoteAddress);

/**
116 117
 * This callback is registered to recieve all bluetooth nearby devices
 * when device scan is initiated.
118 119 120 121 122 123 124
 */
static void CAEDRDeviceDiscoveryCallback(int result,
                                         bt_adapter_device_discovery_state_e state,
                                         bt_adapter_device_discovery_info_s *discoveryInfo,
                                         void *userData);

/**
125 126
 * This callback is registered to recieve all the services remote
 * bluetooth device supports when service search initiated.
127 128 129 130 131
 */
static void CAEDRServiceSearchedCallback(int result, bt_device_sdp_info_s *sdpInfo,
                                        void *userData);

/**
132 133
 * This callback is registered to receive bluetooth RFCOMM connection
 * state changes.
134
 */
135 136
static void CAEDRSocketConnectionStateCallback(int result,
                                    bt_socket_connection_state_e state,
137 138 139
                                              bt_socket_connection_s *connection, void *userData);

/**
140
 * Establishes RFCOMM connection with remote bluetooth device.
141 142 143 144
 */
static CAResult_t CAEDRClientConnect(const char *remoteAddress, const char *serviceUUID);

/**
145
 * Disconnect RFCOMM client socket connection.
146 147 148 149 150
 */
static CAResult_t CAEDRClientDisconnect(const int32_t clientID);

void CAEDRSetPacketReceivedCallback(CAEDRDataReceivedCallback packetReceivedCallback)
{
151
    g_edrPacketReceivedCallback = packetReceivedCallback;
152 153
}

154 155 156 157 158
void CAEDRSetErrorHandler(CAEDRErrorHandleCallback errorHandleCallback)
{
    g_edrErrorHandler = errorHandleCallback;
}

159 160 161
void CAEDRSocketConnectionStateCallback(int result, bt_socket_connection_state_e state,
                                       bt_socket_connection_s *connection, void *userData)
{
162
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
Jaewook Jung's avatar
Jaewook Jung committed
163
    OC_UNUSED(userData);
164 165 166 167 168 169 170 171 172 173 174 175 176 177

    EDRDevice *device = NULL;

    if (BT_ERROR_NONE != result || NULL == connection)
    {
        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Invalid connection state!, error num [%x]",
                  result);
        return;
    }

    switch (state)
    {
        case BT_SOCKET_CONNECTED:
            {
178
                oc_mutex_lock(g_edrDeviceListMutex);
179 180 181
                CAResult_t res = CAGetEDRDevice(g_edrDeviceList, connection->remote_address,
                                                   &device);
                if (CA_STATUS_OK != res)
182 183
                {
                    // Create the deviceinfo and add to list
184 185 186
                    res = CACreateAndAddToDeviceList(&g_edrDeviceList,
                            connection->remote_address, OIC_EDR_SERVICE_ID, &device);
                    if (CA_STATUS_OK != res)
187
                    {
188
                        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed add device to list ret[%d]", res);
189
                        oc_mutex_unlock(g_edrDeviceListMutex);
190 191 192 193 194
                        return;
                    }

                    if(!device)
                    {
195
                        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "EDRDevice is null!");
196
                        oc_mutex_unlock(g_edrDeviceListMutex);
197 198 199 200
                        return;
                    }

                    device->socketFD = connection->socket_fd;
201
                    oc_mutex_unlock(g_edrDeviceListMutex);
202 203 204
                    return;
                }

205 206
                if(!device)
                {
207
                    OIC_LOG(ERROR, EDR_ADAPTER_TAG, "EDRDevice is null!");
208
                    oc_mutex_unlock(g_edrDeviceListMutex);
209 210
                    return;
                }
211 212 213 214
                device->socketFD = connection->socket_fd;
                while (device->pendingDataList)
                {
                    EDRData *edrData = device->pendingDataList->data;
215 216
                    res = CAEDRSendData(device->socketFD, device->remoteAddress,
                                        edrData->data, edrData->dataLength);
217
                    if (CA_STATUS_OK != res)
218 219 220 221 222 223 224 225 226 227 228 229
                    {
                        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to send pending data [%s]",
                                  device->remoteAddress);

                        // Remove all the data from pending list
                        CADestroyEDRDataList(&device->pendingDataList);
                        break;
                    }

                    // Remove the data which send from pending list
                    CARemoveEDRDataFromList(&device->pendingDataList);
                }
230
                oc_mutex_unlock(g_edrDeviceListMutex);
231 232 233 234 235
            }
            break;

        case BT_SOCKET_DISCONNECTED:
            {
236
                oc_mutex_lock(g_edrDeviceListMutex);
237
                CARemoveEDRDeviceFromList(&g_edrDeviceList, connection->remote_address);
238
                oc_mutex_unlock(g_edrDeviceListMutex);
239 240
            }
            break;
241 242 243

        default:
            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Unknown Bluetooth Socket connection state");
244 245
    }

246
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
247 248 249 250 251 252
}


void CAEDRDeviceDiscoveryCallback(int result, bt_adapter_device_discovery_state_e state,
                                 bt_adapter_device_discovery_info_s *discoveryInfo, void *userData)
{
253
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
Jaewook Jung's avatar
Jaewook Jung committed
254
    OC_UNUSED(userData);
255 256 257 258 259 260 261 262 263 264 265 266 267 268

    EDRDevice *device = NULL;

    if (BT_ERROR_NONE != result)
    {
        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Received bad state!, error num [%x]",
                  result);
        return;
    }

    switch (state)
    {
        case BT_ADAPTER_DEVICE_DISCOVERY_STARTED:
            {
269
                OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Discovery started!");
270 271 272 273 274
            }
            break;

        case BT_ADAPTER_DEVICE_DISCOVERY_FINISHED:
            {
275
                OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Discovery finished!");
276
                oc_mutex_lock(g_multicastDataListMutex);
vimala.v's avatar
vimala.v committed
277 278
                u_arraylist_destroy(g_multicastDataList);
                g_multicastDataList = NULL;
279
                oc_mutex_unlock(g_multicastDataListMutex);
280 281 282 283 284 285 286
            }
            break;

        case BT_ADAPTER_DEVICE_DISCOVERY_FOUND:
            {
                OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "Device discovered [%s]!",
                          discoveryInfo->remote_name);
287
                if (true == CAEDRIsServiceSupported((const char **)discoveryInfo->service_uuid,
288 289 290 291
                                                        discoveryInfo->service_count,
                                                        OIC_EDR_SERVICE_ID))
                {
                    // Check if the deivce is already in the list
292
                    oc_mutex_lock(g_edrDeviceListMutex);
293 294
                    if (CA_STATUS_OK == CAGetEDRDevice(g_edrDeviceList,
                                                discoveryInfo->remote_address, &device))
295
                    {
296 297
                        if(!device)
                        {
298
                            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "EDRDevice is null!");
299
                            oc_mutex_unlock(g_edrDeviceListMutex);
300 301 302
                            return;
                        }
                        device->serviceSearched = true;
303
                        oc_mutex_unlock(g_edrDeviceListMutex);
304 305 306 307
                        return;
                    }

                    // Create the deviceinfo and add to list
308 309 310
                    CAResult_t res = CACreateAndAddToDeviceList(&g_edrDeviceList,
                            discoveryInfo->remote_address, OIC_EDR_SERVICE_ID, &device);
                    if (CA_STATUS_OK != res)
311
                    {
312
                        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to add device to list!");
313
                        oc_mutex_unlock(g_edrDeviceListMutex);
314 315 316
                        return;
                    }

317 318
                    if(!device)
                    {
319
                        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "EDRDevice is null!");
320
                        oc_mutex_unlock(g_edrDeviceListMutex);
321 322
                        return;
                    }
vimala.v's avatar
vimala.v committed
323

324 325
                    size_t lengthData = u_arraylist_length(g_multicastDataList);
                    for(size_t len = 0; len < lengthData; len++)
vimala.v's avatar
vimala.v committed
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
                    {
                        // Adding to pending list
                        EDRData *multicastData =
                            (EDRData *)u_arraylist_get(g_multicastDataList, len);
                        if (NULL == multicastData)
                        {
                            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "multicastData is NULL");
                            continue;
                        }
                        result = CAAddEDRDataToList(&device->pendingDataList, multicastData->data,
                                                    multicastData->dataLength);
                        if (CA_STATUS_OK != result)
                        {
                            OIC_LOG_V(ERROR, EDR_ADAPTER_TAG,
                                      "Failed to add data to pending list[%d]", result);
                            continue;
                        }
                    }
                    if (lengthData)
                    {
                        result = CAEDRClientConnect(device->remoteAddress, device->serviceUUID);
                        if (CA_STATUS_OK != result)
                        {
                            OIC_LOG_V(ERROR, EDR_ADAPTER_TAG,
                                      "Failed to make RFCOMM connection[%d]", result);

                            //Remove the data which added to pending list
                            CARemoveEDRDataFromList(&device->pendingDataList);
                        }
                    }
356
                    device->serviceSearched = true;
357
                    oc_mutex_unlock(g_edrDeviceListMutex);
358 359 360
                }
                else
                {
361
                    OIC_LOG(INFO, EDR_ADAPTER_TAG, "Device does not support OIC service!");
362 363 364
                }
            }
            break;
365 366

        default:
367
            OIC_LOG(INFO, EDR_ADAPTER_TAG, "Unknown Bluetooth Adapter device discovery state");
368 369
    }

370
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
371 372
}

373 374
void CAEDRServiceSearchedCallback(int32_t result,
                bt_device_sdp_info_s *sdpInfo,void *userData)
375
{
376
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
Jaewook Jung's avatar
Jaewook Jung committed
377 378
    OC_UNUSED(result);
    OC_UNUSED(userData);
379 380 381

    if (NULL == sdpInfo)
    {
382
        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "SDP info is null!");
383 384 385
        return;
    }

386
    oc_mutex_lock(g_edrDeviceListMutex);
387 388

    EDRDevice *device = NULL;
389 390
    CAResult_t res = CAGetEDRDevice(g_edrDeviceList, sdpInfo->remote_address, &device);
    if (CA_STATUS_OK == res && NULL != device)
391
    {
392
        if (device->serviceSearched)
393
        {
394
            OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Service is already searched for this device!");
395
            oc_mutex_unlock(g_edrDeviceListMutex);
396 397 398
            return;
        }

399
        if (true == CAEDRIsServiceSupported((const char **)sdpInfo->service_uuid,
400 401
                                           sdpInfo->service_count, OIC_EDR_SERVICE_ID))
        {
402 403 404
            device->serviceSearched = true;
            res = CAEDRClientConnect(sdpInfo->remote_address, OIC_EDR_SERVICE_ID);
            if (CA_STATUS_OK != res)
405
            {
406
                OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to make rfcomm connection!");
407 408

                // Remove the device from device list
409
                CARemoveEDRDeviceFromList(&g_edrDeviceList, sdpInfo->remote_address);
410 411 412 413
            }
        }
        else
        {
414
            OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Device does not contain OIC service!");
415 416

            // Remove device from list as it does not support OIC service
417
            CARemoveEDRDeviceFromList(&g_edrDeviceList, sdpInfo->remote_address);
418 419 420
        }
    }

421
    oc_mutex_unlock(g_edrDeviceListMutex);
422

423
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
424 425 426 427
}

CAResult_t CAEDRStartDeviceDiscovery(void)
{
428
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
429 430 431 432

    bool isDiscoveryStarted = false;

    // Check the device discovery state
433 434
    bt_error_e err = bt_adapter_is_discovering(&isDiscoveryStarted);
    if (BT_ERROR_NONE != err)
435 436 437 438 439 440 441 442 443
    {
        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to get discovery state!, error num [%x]",
                  err);
        return CA_STATUS_FAILED;
    }

    //Start device discovery if its not started
    if (false == isDiscoveryStarted)
    {
444 445
        err = bt_adapter_start_device_discovery();
        if (BT_ERROR_NONE != err)
446 447 448 449 450 451 452
        {
            OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Device discovery failed!, error num [%x]",
                      err);
            return CA_STATUS_FAILED;
        }
    }

koushik.girijala's avatar
koushik.girijala committed
453 454
    g_isDiscoveryServer = true;

455
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
456 457 458 459 460
    return CA_STATUS_OK;
}

CAResult_t CAEDRStopServiceSearch(void)
{
461
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
462

463
    bt_error_e err = bt_device_cancel_service_search();
464
    // Stop ongoing service search
465
    if (BT_ERROR_NONE != err)
466 467 468 469 470 471
    {
        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Get bonded device failed!, error num [%x]",
                  err);
        return CA_STATUS_FAILED;
    }

472
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
473 474 475 476 477
    return CA_STATUS_OK;
}

CAResult_t CAEDRStopDeviceDiscovery(void)
{
478
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
479 480

    bool isDiscoveryStarted = false;
481
    bt_error_e err = bt_adapter_is_discovering(&isDiscoveryStarted);
482
    // Check the device discovery state
483
    if (BT_ERROR_NONE != err)
484 485 486 487 488 489 490 491 492
    {
        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to get discovery state!, error num [%x]",
                  err);
        return CA_STATUS_FAILED;
    }

    //stop the device discovery process
    if (true == isDiscoveryStarted)
    {
493
        OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Stopping the device search process");
494 495 496 497 498 499 500
        if (BT_ERROR_NONE != (err = bt_adapter_stop_device_discovery()))
        {
            OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to stop discovery!, error num [%x]",
                      err);
        }
    }

501
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
502 503 504 505 506
    return CA_STATUS_OK;
}

CAResult_t CAEDRStartServiceSearch(const char *remoteAddress)
{
507
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
508 509 510

    // Input validation
    VERIFY_NON_NULL(remoteAddress, EDR_ADAPTER_TAG, "Remote address is null");
511
    if (!remoteAddress[0])
512
    {
513
        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Remote address is empty!");
514 515 516
        return CA_STATUS_INVALID_PARAM;
    }

517
    bt_error_e err = bt_device_start_service_search(remoteAddress);
518
    // Start searching for OIC service
519
    if (BT_ERROR_NONE != err)
520 521 522 523 524 525
    {
        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Get bonded device failed!, error num [%x]",
                  err);
        return CA_STATUS_FAILED;
    }

526
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
527 528 529 530 531
    return CA_STATUS_OK;
}

CAResult_t CAEDRClientSetCallbacks(void)
{
532
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
533 534 535 536 537 538 539

    // Register for discovery and rfcomm socket connection callbacks
    bt_adapter_set_device_discovery_state_changed_cb(CAEDRDeviceDiscoveryCallback, NULL);
    bt_device_set_service_searched_cb(CAEDRServiceSearchedCallback, NULL);
    bt_socket_set_connection_state_changed_cb(CAEDRSocketConnectionStateCallback, NULL);
    bt_socket_set_data_received_cb(CAEDRDataRecvCallback, NULL);

540
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
541 542 543 544 545 546
    return CA_STATUS_OK;
}


void CAEDRClientUnsetCallbacks(void)
{
547
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
548 549 550 551 552 553 554 555

    // Stop service search
    CAEDRStopServiceSearch();

    // Stop the device discovery process
    CAEDRStopDeviceDiscovery();

    // reset bluetooth adapter callbacks
556
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Resetting the callbacks");
557 558 559 560 561
    bt_adapter_unset_device_discovery_state_changed_cb();
    bt_device_unset_service_searched_cb();
    bt_socket_unset_connection_state_changed_cb();
    bt_socket_unset_data_received_cb();

562
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
563 564
}

565
CAResult_t CAEDRManagerInitializeMutex(void)
566
{
567
    CAResult_t result = CA_STATUS_OK;
568
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
569

570
    if (!g_edrDeviceListMutex)
571
    {
572
        g_edrDeviceListMutex = oc_mutex_new();
573 574
    }

vimala.v's avatar
vimala.v committed
575
    if (!g_multicastDataListMutex)
576
    {
577
        g_multicastDataListMutex = oc_mutex_new();
578 579
    }

580 581 582 583 584
    if (!g_edrDeviceListMutex || !g_multicastDataListMutex)
    {
        result = CA_STATUS_NOT_INITIALIZED;
    }

585
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
586 587

    return result;
588 589 590 591
}

void CAEDRManagerTerminateMutex(void)
{
592
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
593

594
    if (g_edrDeviceListMutex)
595
    {
596
        oc_mutex_free(g_edrDeviceListMutex);
597
        g_edrDeviceListMutex = NULL;
598 599
    }

vimala.v's avatar
vimala.v committed
600
    if (g_multicastDataListMutex)
601
    {
602
        oc_mutex_free(g_multicastDataListMutex);
vimala.v's avatar
vimala.v committed
603
        g_multicastDataListMutex = NULL;
604
    }
vimala.v's avatar
vimala.v committed
605

606
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
607 608
}

609
CAResult_t CAEDRClientInitialize()
610 611
{
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
612
    CAResult_t result = CAEDRManagerInitializeMutex();
613
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
614
    return result;
615 616
}

617
void CAEDRClientTerminate()
618 619 620 621
{
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");

    // Free EDRDevices list
622
    if (g_edrDeviceListMutex)
623
    {
624
        oc_mutex_lock(g_edrDeviceListMutex);
625
        CADestroyEDRDeviceList(&g_edrDeviceList);
626
        oc_mutex_unlock(g_edrDeviceListMutex);
627 628
    }

vimala.v's avatar
vimala.v committed
629 630
    if (g_multicastDataListMutex)
    {
631
        oc_mutex_lock(g_multicastDataListMutex);
vimala.v's avatar
vimala.v committed
632 633
        u_arraylist_destroy(g_multicastDataList);
        g_multicastDataList = NULL;
634
        oc_mutex_unlock(g_multicastDataListMutex);
vimala.v's avatar
vimala.v committed
635 636
    }

637 638 639 640 641 642 643
    // Free the mutex
    CAEDRManagerTerminateMutex();
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}

void CAEDRClientDisconnectAll(void)
{
644
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
645

646
    oc_mutex_lock(g_edrDeviceListMutex);
647

648
    EDRDeviceList *cur = g_edrDeviceList;
649 650 651 652 653 654 655
    while (cur != NULL)
    {
        EDRDevice *device = cur->device;
        cur = cur->next;

        if (device && 0 <= device->socketFD)
        {
656 657
            CAResult_t result = CAEDRClientDisconnect(device->socketFD);
            if (CA_STATUS_OK != result)
658 659 660 661 662 663 664 665 666
            {
                OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to disconnect with client :%s",
                          device->remoteAddress);
            }

            device->socketFD = -1;
        }
    }

667
    oc_mutex_unlock(g_edrDeviceListMutex);
668

669
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
670 671 672
}


673 674
CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress,
                                      const uint8_t *data,
jihwan.seo's avatar
jihwan.seo committed
675
                                      uint32_t dataLength)
676
{
677
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
678 679 680 681 682 683 684 685 686

    EDRDevice *device = NULL;

    // Input validation
    VERIFY_NON_NULL(remoteAddress, EDR_ADAPTER_TAG, "Remote address is null");
    VERIFY_NON_NULL(data, EDR_ADAPTER_TAG, "Data is null");

    if (0 >= dataLength)
    {
687
        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Invalid input: Negative data length!");
688 689 690 691
        return CA_STATUS_INVALID_PARAM;
    }

    // Check the connection existence with remote device
692
    oc_mutex_lock(g_edrDeviceListMutex);
693 694
    CAResult_t result = CAGetEDRDevice(g_edrDeviceList, remoteAddress, &device);
    if (CA_STATUS_OK != result)
695 696
    {
        // Create new device and add to list
697 698 699
        result = CACreateAndAddToDeviceList(&g_edrDeviceList, remoteAddress,
                                            OIC_EDR_SERVICE_ID, &device);
        if (CA_STATUS_OK != result)
700
        {
701
            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed create device and add to list!");
702

703
            oc_mutex_unlock(g_edrDeviceListMutex);
704 705 706 707
            return CA_STATUS_FAILED;
        }

        // Start the OIC service search newly created device
708 709
        result = CAEDRStartServiceSearch(remoteAddress);
        if (CA_STATUS_OK != result)
710
        {
711
            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to initiate service search!");
712 713

            // Remove device from list
714
            CARemoveEDRDeviceFromList(&g_edrDeviceList, remoteAddress);
715

716
            oc_mutex_unlock(g_edrDeviceListMutex);
717 718 719
            return CA_STATUS_FAILED;
        }
    }
720 721 722

    if(!device)
    {
723
        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "EDRDevice is null!");
724 725 726
        // Remove device from list
        CARemoveEDRDeviceFromList(&g_edrDeviceList, remoteAddress);

727
        oc_mutex_unlock(g_edrDeviceListMutex);
728 729 730
        return CA_STATUS_FAILED;
    }

731
    oc_mutex_unlock(g_edrDeviceListMutex);
732 733 734 735

    if (-1 == device->socketFD)
    {
        // Adding to pending list
736 737 738
        result = CAAddEDRDataToList(&device->pendingDataList, data,
                                              dataLength);
        if (CA_STATUS_OK != result)
739
        {
740
            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to add data to pending list!");
741 742

            //Remove device from list
743
            CARemoveEDRDeviceFromList(&g_edrDeviceList, remoteAddress);
744 745 746 747
            return CA_STATUS_FAILED;
        }

        // Make a rfcomm connection with remote BT Device
748
        if (device->serviceSearched &&
jihwan.seo's avatar
jihwan.seo committed
749
            CA_STATUS_OK != CAEDRClientConnect(remoteAddress, OIC_EDR_SERVICE_ID))
750
        {
751
            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to make RFCOMM connection!");
752 753

            //Remove device from list
754
            CARemoveEDRDeviceFromList(&g_edrDeviceList, remoteAddress);
755 756 757 758 759
            return CA_STATUS_FAILED;
        }
    }
    else
    {
760
        result = CAEDRSendData(device->socketFD, device->remoteAddress, data, dataLength);
761
        if (CA_STATUS_OK != result)
762
        {
763
            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to send data!");
764 765 766 767
            return CA_STATUS_FAILED;
        }
    }

768
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
769 770 771
    return CA_STATUS_OK;
}

772 773
CAResult_t CAEDRClientSendMulticastData(const uint8_t *data,
                                        uint32_t dataLength)
774
{
775
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
776 777 778 779 780 781

    // Input validation
    VERIFY_NON_NULL(data, EDR_ADAPTER_TAG, "Data is null");

    if (0 >= dataLength)
    {
782
        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Invalid input: Negative data length!");
783 784 785 786
        return CA_STATUS_INVALID_PARAM;
    }

    // Send the packet to all OIC devices
787
    oc_mutex_lock(g_edrDeviceListMutex);
788

789 790
    EDRDeviceList *curList = g_edrDeviceList;
    CAResult_t result = CA_STATUS_FAILED;
791 792 793 794 795 796 797
    while (curList != NULL)
    {
        EDRDevice *device = curList->device;
        curList = curList->next;

        if (!device)
        {
798
            OIC_LOG(ERROR, EDR_ADAPTER_TAG, "There is no device!");
799 800 801 802 803 804
            break;
        }

        if (-1 == device->socketFD)
        {
            // Check if the device service search is finished
805
            if (false == device->serviceSearched)
806
            {
807
                OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Device services are still unknown!");
808 809 810 811
                continue;
            }

            // Adding to pendding list
812 813 814
            result = CAAddEDRDataToList(&device->pendingDataList, data,
                                                  dataLength);
            if (CA_STATUS_OK != result)
815
            {
816
                OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to add data to pending list !");
817 818 819 820
                continue;
            }

            // Make a rfcomm connection with remote BT Device
821 822
            result = CAEDRClientConnect(device->remoteAddress, device->serviceUUID);
            if (CA_STATUS_OK != result)
823
            {
824
                OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to make RFCOMM connection !");
825 826 827 828 829 830 831 832

                //Remove the data which added to pending list
                CARemoveEDRDataFromList(&device->pendingDataList);
                continue;
            }
        }
        else
        {
833
            result = CAEDRSendData(device->socketFD, device->remoteAddress ,data, dataLength);
834
            if (CA_STATUS_OK != result)
835 836 837 838 839 840
            {
                OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to send data to [%s] !",
                          device->remoteAddress);
            }
        }
    }
vimala.v's avatar
vimala.v committed
841

842
    oc_mutex_unlock(g_edrDeviceListMutex);
843

koushik.girijala's avatar
koushik.girijala committed
844
    if(g_isDiscoveryServer)
vimala.v's avatar
vimala.v committed
845
    {
koushik.girijala's avatar
koushik.girijala committed
846 847 848
        // Start the device Discovery.
        result = CAEDRStartDeviceDiscovery();
        if (CA_STATUS_OK == result)
vimala.v's avatar
vimala.v committed
849
        {
koushik.girijala's avatar
koushik.girijala committed
850
            OIC_LOG(INFO, EDR_ADAPTER_TAG, "Add the data to the multicast data list");
vimala.v's avatar
vimala.v committed
851

koushik.girijala's avatar
koushik.girijala committed
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
            EDRData *multicastData = (EDRData *)OICCalloc(1, sizeof(EDRData));
            if (NULL == multicastData)
            {
                OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Malloc failed");
                goto exit;
            }
            multicastData->data = OICCalloc(1, dataLength);
            if (NULL == multicastData->data)
            {
                OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Malloc failed");
                goto exit;
            }
            memcpy(multicastData->data, data, dataLength);
            multicastData->dataLength = dataLength;

            // Add the data to pending multicast data list.
868
            oc_mutex_lock(g_multicastDataListMutex);
koushik.girijala's avatar
koushik.girijala committed
869 870 871 872 873
            if (NULL == g_multicastDataList)
            {
                g_multicastDataList = u_arraylist_create();
            }
            u_arraylist_add(g_multicastDataList, (void *)multicastData);
874
            oc_mutex_unlock(g_multicastDataListMutex);
vimala.v's avatar
vimala.v committed
875 876 877 878
        }
    }

exit:
879
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
880 881 882 883 884
    return CA_STATUS_OK;
}

CAResult_t CAEDRClientConnect(const char *remoteAddress, const char *serviceUUID)
{
885
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
886 887 888 889

    VERIFY_NON_NULL(remoteAddress, EDR_ADAPTER_TAG, "Remote address is null");
    VERIFY_NON_NULL(serviceUUID, EDR_ADAPTER_TAG, "Service UUID is null");

890
    size_t addressLen = strlen(remoteAddress);
891 892
    if (0 == addressLen || CA_MACADDR_SIZE - 1 != addressLen)
    {
893
        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Invalid input: Invalid remote address");
894 895 896
        return  CA_STATUS_INVALID_PARAM;
    }

897
    if (!serviceUUID[0])
898
    {
899
        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Invalid input: Empty service uuid");
900 901 902
        return  CA_STATUS_INVALID_PARAM;
    }

903 904
    bt_error_e err = bt_socket_connect_rfcomm(remoteAddress, serviceUUID);
    if (BT_ERROR_NONE != err)
905 906 907 908 909 910 911
    {
        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG,
                  "Failed to connect!, address [%s] error num [%x]",
                  remoteAddress, err);
        return CA_STATUS_FAILED;
    }

912
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
913 914 915 916 917
    return CA_STATUS_OK;
}

CAResult_t CAEDRClientDisconnect(const int32_t clientID)
{
918
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
919 920 921 922

    // Input validation
    if (0 > clientID)
    {
923
        OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Invalid input: negative client id");
924 925 926
        return CA_STATUS_INVALID_PARAM;
    }

927 928
    bt_error_e err = bt_socket_disconnect_rfcomm(clientID);
    if (BT_ERROR_NONE != err)
929 930 931 932 933 934
    {
        OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed close rfcomm client socket!, error num [%x]",
                  err);
        return CA_STATUS_FAILED;
    }

935
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
936 937 938 939 940
    return CA_STATUS_OK;
}

void CAEDRDataRecvCallback(bt_socket_received_data_s *data, void *userData)
{
941
    OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
Jaewook Jung's avatar
Jaewook Jung committed