replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / bt_le_adapter / ios / caleclient.m
1 /******************************************************************
2  *
3  * Copyright 2017 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 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include "caleclient.h"
26 #include "caleserver.h"
27 #include "caleutils.h"
28 #include "caleinterface.h"
29 #include "caadapterutils.h"
30
31 #include "logger.h"
32 #include "oic_malloc.h"
33 #include "oic_string.h"
34 #include "cathreadpool.h" /* for thread pool */
35 #include "octhread.h"
36 #include "uarraylist.h"
37
38 #define TAG PCF("OIC_CA_LE_CLIENT")
39
40 #define MICROSECS_PER_SEC 1000000
41 #define WAIT_TIME_WRITE_CHARACTERISTIC 10 * MICROSECS_PER_SEC
42
43 #define TV_ADV_DATA_MIN_LEN            26
44
45 #define TV_ADV_COMPANY_ID_INDEX1       0
46 #define TV_ADV_COMPANY_ID_INDEX2       1
47 #define TV_ADV_VERSION_INDEX           2
48 #define TV_ADV_SERVICE_TYPE_INDEX      3
49 #define PON_ADV_DEVICE_TYPE_INDEX      4
50 #define OOB_AV_ADV_DEVICE_TYPE_INDEX   4
51 #define OOB_TV_ADV_DEVICE_TYPE_INDEX   10
52 #define TV_ADV_SCAN_RESP_LEN_INDEX     4
53 #define TV_ADV_DEVICE_STATUS_INDEX     5
54
55 #define TV_ADV_PON_MAC_BYTE_1          7
56 #define TV_ADV_PON_MAC_BYTE_2          8
57 #define TV_ADV_PON_MAC_BYTE_3          9
58 #define TV_ADV_PON_MAC_BYTE_4          10
59 #define TV_ADV_PON_MAC_BYTE_5          11
60 #define TV_ADV_PON_MAC_BYTE_6          12
61
62 #define AV_ADV_OOB_MAC_BYTE_1          7
63 #define AV_ADV_OOB_MAC_BYTE_2          8
64 #define AV_ADV_OOB_MAC_BYTE_3          9
65 #define AV_ADV_OOB_MAC_BYTE_4          10
66 #define AV_ADV_OOB_MAC_BYTE_5          11
67 #define AV_ADV_OOB_MAC_BYTE_6          12
68
69 #define PON_TV_AV_DIFF                 3  // TV mac is 7-12 bytes, av mac is 10-15 bytes
70
71 #define TV_ADV_BD_ADDRTYPE_INDEX       19
72
73 #define TV_ADV_OOB_MAC_BYTE_1          20
74 #define TV_ADV_OOB_MAC_BYTE_2          21
75 #define TV_ADV_OOB_MAC_BYTE_3          22
76 #define TV_ADV_OOB_MAC_BYTE_4          23
77 #define TV_ADV_OOB_MAC_BYTE_5          24
78 #define TV_ADV_OOB_MAC_BYTE_6          25
79
80 #define TV_ADV_COMPANY_ID1             0x75
81 #define TV_ADV_COMPANY_ID2             0x00
82 #define TV_ADV_VERSION                 0x42
83
84 #define TV_ADV_SERVICE_ID_POWER        0x04
85 #define TV_ADV_SERVICE_ID_OOB          0x09
86
87 #define TV_ADV_DEVICE_TV               0x01
88 #define TV_ADV_DEVICE_STATUS_ON        0x01
89 #define TV_ADV_DEVICE_STATUS_UNKNOWN   0x20
90
91 #define TV_ADV_BD_ADDR_ID              0x01
92 #define TV_ADV_SCAN_RESP_LEN           0x06
93
94 #define DEVICE_TYPE_TV                 1
95 #define DEVICE_TYPE_AV                 3
96
97
98
99 static ca_thread_pool_t g_threadPoolHandle = NULL;
100
101 static u_arraylist_t *g_deviceList = NULL; // device list to have same UUID
102 static u_arraylist_t *g_gattObjectList = NULL;
103 static u_arraylist_t *g_deviceStateList = NULL;
104
105 static CAPacketReceiveCallback g_packetReceiveCallback = NULL;
106 static CABLEErrorHandleCallback g_clientErrorCallback;
107
108 static CAManagerAdapterStateChangeCallback g_caManagerAdapterStateChangeCallback = NULL;
109 static CAManagerConnectionCallback g_caManagerConnectionCallback = NULL;
110 static CAManagerServiceDiscoveredCallback g_caManagerServiceDiscoveredCallback = NULL;
111 static dispatch_queue_t g_caManagerQueue = NULL;
112
113 static NSString *mac_ref = @"AB:CD:EF:15:";
114 int mac_add = 4096;
115
116 static bool g_isStartedLEClient = false;
117 static bool g_isStartedScan = false;
118
119 static NSData* g_sendBuffer = nil;
120 static uint32_t g_targetCnt = 0;
121 static uint32_t g_currentSentCnt = 0;
122 static bool g_isFinishedSendData = false;
123 static oc_mutex g_SendFinishMutex = NULL;
124 static oc_mutex g_threadMutex = NULL;
125 static oc_cond g_threadCond = NULL;
126 static oc_cond g_deviceDescCond = NULL;
127
128 static oc_mutex g_threadSendMutex = NULL;
129 static oc_mutex g_threadWriteCharacteristicMutex = NULL;
130 static oc_cond g_threadWriteCharacteristicCond = NULL;
131 static bool g_isSignalSetFlag = false;
132
133 static oc_mutex g_bleReqRespClientCbMutex = NULL;
134 static oc_mutex g_bleServerBDAddressMutex = NULL;
135
136 static oc_mutex g_deviceListMutex = NULL;
137 static oc_mutex g_gattObjectMutex = NULL;
138 static oc_mutex g_deviceStateListMutex = NULL;
139
140 static oc_mutex g_deviceScanRetryDelayMutex = NULL;
141 static oc_cond g_deviceScanRetryDelayCond = NULL;
142
143 static oc_mutex g_scanMutex = NULL;
144 static oc_mutex waitMutex = NULL;
145
146 static oc_mutex g_initializeMutex = NULL;
147 static oc_cond g_initializeCond = NULL;
148
149 static CABLEDataReceivedCallback g_CABLEClientDataReceivedCallback = NULL;
150
151 @interface CBCentralIfClass:NSObject <CBCentralManagerDelegate>
152 @end
153 static id cbCentralIf;
154 NSMutableArray *centralMgrs;
155 NSMutableDictionary *cbPeripherals;
156 NSMutableDictionary *cbServices;
157 NSMutableDictionary *requestCharacs;
158 NSMutableDictionary *responseCharacs;
159 NSArray<CBUUID *> *g_uuidList;
160
161 @implementation CBCentralIfClass
162 static CBCentralManager *centralMgr = nil;
163
164 - (void) CALEClientCreateCentralManager{
165     centralMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil
166                                            options:[NSDictionary dictionaryWithObject:
167                                            [NSNumber numberWithInt:0]
168                                                   forKey:CBCentralManagerOptionShowPowerAlertKey]];
169
170     centralMgrs = [NSMutableArray new];
171
172     cbPeripherals = [[NSMutableDictionary alloc] init];
173     cbServices = [[NSMutableDictionary alloc] init];
174     requestCharacs = [[NSMutableDictionary alloc] init];
175     responseCharacs = [[NSMutableDictionary alloc] init];
176 }
177
178 - (CAResult_t) CALEClientStartScanImpl{
179     OIC_LOG(DEBUG, TAG, "[CBCtrl] In - CALEClientStartScanImpl");
180     if ([centralMgrs count] == 0){
181         OIC_LOG(ERROR, TAG, "[CBCtrl] central manager is not available");
182         return CA_ADAPTER_NOT_ENABLED;
183     }else{
184         CALEClientSetScanFlag(true);
185
186         [centralMgr scanForPeripheralsWithServices:nil
187                     options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@NO}];
188     }
189     return CA_STATUS_OK;
190 }
191
192 - (CAResult_t) CALEClientStartScanWithUUIDImpl: (NSArray<CBUUID*> *)uuids{
193     OIC_LOG(DEBUG, TAG, "[CBCtrl] In - CALEClientStartScanWithUUIDImpl");
194     if ([centralMgrs count] == 0){
195         OIC_LOG(ERROR, TAG, "[CBCtrl] central manager is not available");
196         return CA_ADAPTER_NOT_ENABLED;
197     }else{
198         CALEClientSetScanFlag(true);
199         [centralMgr scanForPeripheralsWithServices:uuids
200                                      options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}];
201     }
202     return CA_STATUS_OK;
203 }
204
205 - (CAResult_t) CALEClientStopScanImpl{
206     OIC_LOG(DEBUG, TAG, "[CBCtrl] In - CALEClientStopScanImpl");
207     if ([centralMgrs count] == 0){
208         OIC_LOG(ERROR, TAG, "[CBCtrl] central manager is not available");
209         return CA_ADAPTER_NOT_ENABLED;
210     }else{
211         CALEClientSetScanFlag(false);
212         [centralMgr stopScan];
213     }
214     return CA_STATUS_OK;
215 }
216
217 - (CAResult_t) CALEClientConnectImpl: (CBPeripheral *)peripheral{
218     if (peripheral == (id) [NSNull null]){
219         OIC_LOG(ERROR, TAG, "[CBCtrl] In - CALEClientConnectImpl: peripheral is null");
220     }else{
221         OIC_LOG(DEBUG, TAG, "[CBCtrl] In - CALEClientConnectImpl");
222         OIC_LOG_V(INFO, TAG, "peripheral name = %s", [[peripheral name] UTF8String]);
223
224         [centralMgr connectPeripheral: peripheral options:nil];
225         return CA_STATUS_OK;
226     }
227     return CA_STATUS_FAILED;
228 }
229
230 - (CAResult_t) CALEClientDiscoverServices: (CBPeripheral *)peripheral{
231     if (peripheral == (id) [NSNull null]){
232         OIC_LOG(ERROR, TAG, "[CBCtrl] In - CALEClientDiscoverServices: peripheral is null");
233     }else{
234         OIC_LOG_V(DEBUG, TAG, "[CBCtrl] In - CALEClientDiscoverServices: %s",
235                   [[cbPeripherals objectForKey:peripheral] UTF8String] );
236         OIC_LOG_V(INFO, TAG, "peripheral name = %s", [[peripheral name] UTF8String]);
237
238         [peripheral discoverServices:
239          @[[CBUUID UUIDWithString:[NSString stringWithUTF8String:OIC_GATT_SERVICE_UUID]]]];
240         return CA_STATUS_OK;
241     }
242     return CA_STATUS_FAILED;
243 }
244
245 -(CAResult_t) CALEClientSetNotifyCharacteristic: (CBPeripheral *)peripheral
246                                                : (CBCharacteristic *)characteristic{
247     if ((peripheral == (id) [NSNull null]) || (characteristic == (id) [NSNull null])){
248         OIC_LOG(ERROR, TAG, "[CBCtrl] CALEClientSetNotifyCharacteristic: parameter is null");
249     }else{
250         OIC_LOG(DEBUG, TAG, "[CBCtrl] CALEClientSetNotifyCharacteristic");
251         [peripheral setNotifyValue:YES forCharacteristic:characteristic];
252         return CA_STATUS_OK;
253     }
254     return CA_STATUS_FAILED;
255 }
256
257 - (void) CALEClientCancelPeripheralConnection: (CBPeripheral *)peripheral{
258     [centralMgr cancelPeripheralConnection:peripheral];
259 }
260
261 - (CAResult_t) CALEClientWriteValue:(CBPeripheral *)peripheral :(CBCharacteristic *)characteristic{
262     OIC_LOG(DEBUG, TAG, "[CBCtrl] CALEClientWriteRequest");
263     if ([characteristic.UUID isEqual: [CBUUID UUIDWithString:
264                            [NSString stringWithUTF8String:OIC_GATT_CHARACTERISTIC_REQUEST_UUID]]]){
265         if (g_sendBuffer == nil || g_sendBuffer == NULL || [g_sendBuffer length] <= 0){
266             OIC_LOG(ERROR, TAG, "[CBCtrl] g_sendbuffer size is 0!!!");
267             return CA_STATUS_FAILED;
268         }else{
269             NSUInteger len = [g_sendBuffer length];
270             OIC_LOG_V(DEBUG, TAG, "[CBCtrl] write data: size(%lu)", len);
271             uint8_t *data = (uint8_t*)malloc(len);
272             memcpy(data, [g_sendBuffer bytes], len);
273             OIC_LOG_BUFFER(DEBUG, TAG, data, len);
274             free(data);
275             [peripheral writeValue:g_sendBuffer
276                  forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
277             return CA_STATUS_OK;
278         }
279     }else{
280         OIC_LOG(ERROR, TAG, "[CBCtrl] requestUUID is different");
281     }
282     return CA_STATUS_FAILED;
283 }
284
285
286 - (NSString *) CALEClientGetMAC : (NSData*) data{
287
288     if([data length] >= TV_ADV_DATA_MIN_LEN)
289     {
290         const unsigned char *bytes = (unsigned char *)data.bytes;
291
292         int b1 = (int)bytes[TV_ADV_COMPANY_ID_INDEX1];
293         int b2 = (int)bytes[TV_ADV_COMPANY_ID_INDEX2];
294         int b4 = (int)bytes[TV_ADV_SERVICE_TYPE_INDEX];  //service type Power ON/OFF
295
296         if((b1 == TV_ADV_COMPANY_ID1) && (b2 == TV_ADV_COMPANY_ID2)
297            && (b4 == TV_ADV_SERVICE_ID_POWER))
298         {
299             // samsung && power service
300             int b5 = (int)bytes[PON_ADV_DEVICE_TYPE_INDEX];  //devive type, 1 = TV, 3 = AV
301             int index_offset = (b5 == DEVICE_TYPE_TV)? 0 : PON_TV_AV_DIFF;
302             NSMutableString* mac_address = [NSMutableString stringWithFormat:@""];
303             [mac_address appendFormat:@"%02x:%02x:%02x:%02x:%02x:%02x",
304              (int)bytes[TV_ADV_PON_MAC_BYTE_1 + index_offset],
305              (int)bytes[TV_ADV_PON_MAC_BYTE_2 + index_offset],
306              (int)bytes[TV_ADV_PON_MAC_BYTE_3 + index_offset],
307              (int)bytes[TV_ADV_PON_MAC_BYTE_4 + index_offset],
308              (int)bytes[TV_ADV_PON_MAC_BYTE_5 + index_offset],
309              (int)bytes[TV_ADV_PON_MAC_BYTE_6 + index_offset]];
310
311             OIC_LOG_V(INFO, TAG, "TV Power on/off MAC = %s", [mac_address UTF8String]);
312
313             return mac_address;
314         }
315
316         if((b1 == TV_ADV_COMPANY_ID1) && (b2 == TV_ADV_COMPANY_ID2)
317            && (b4 == TV_ADV_SERVICE_ID_OOB))
318         {
319             // samsung && oob
320             int b5 = (int)bytes[OOB_AV_ADV_DEVICE_TYPE_INDEX];  //devive type, 3 = AV // for TV this bit is in fact version number which is always 1 at this moment.
321                                                                 //at this moment, there is no definitive way to detect TV or AV from OOB advertisement.
322             NSMutableString* mac_address = [NSMutableString stringWithFormat:@""];
323
324             if(b5 == DEVICE_TYPE_AV)
325             {
326                 [mac_address appendFormat:@"%02x:%02x:%02x:%02x:%02x:%02x",
327                      (int)bytes[AV_ADV_OOB_MAC_BYTE_1],
328                      (int)bytes[AV_ADV_OOB_MAC_BYTE_2],
329                      (int)bytes[AV_ADV_OOB_MAC_BYTE_3],
330                      (int)bytes[AV_ADV_OOB_MAC_BYTE_4],
331                      (int)bytes[AV_ADV_OOB_MAC_BYTE_5],
332                      (int)bytes[AV_ADV_OOB_MAC_BYTE_6]];
333
334                 OIC_LOG_V(INFO, TAG, "AV OOB MAC = %s", [mac_address UTF8String]);
335             }
336             else
337             {
338                 [mac_address appendFormat:@"%02x:%02x:%02x:%02x:%02x:%02x",
339                      (int)bytes[TV_ADV_OOB_MAC_BYTE_1],
340                      (int)bytes[TV_ADV_OOB_MAC_BYTE_2],
341                      (int)bytes[TV_ADV_OOB_MAC_BYTE_3],
342                      (int)bytes[TV_ADV_OOB_MAC_BYTE_4],
343                      (int)bytes[TV_ADV_OOB_MAC_BYTE_5],
344                      (int)bytes[TV_ADV_OOB_MAC_BYTE_6]];
345
346                 OIC_LOG_V(INFO, TAG, "TV OOB MAC = %s", [mac_address UTF8String]);
347             }
348
349             return mac_address;
350         }
351     }
352
353     NSString *Hex = [NSString stringWithFormat:@"0x%X", mac_add];
354     NSString *Hex_add = [Hex substringFromIndex:2];
355     NSString *first_add = [Hex_add substringToIndex:2];
356     NSString *second_add = [Hex_add substringFromIndex:2];
357     NSString *comma = @":";
358
359     NSString *MAC;
360     MAC = [NSString stringWithString:mac_ref];
361     MAC = [MAC stringByAppendingString:first_add];
362     MAC = [MAC stringByAppendingString:comma];
363     MAC = [MAC stringByAppendingString:second_add];
364
365     OIC_LOG_V(INFO, TAG, "MAC: %s", [MAC UTF8String]);
366
367     if(mac_add == 65535){
368         mac_add=256;
369     }else{
370         mac_add++;
371     }
372
373     return MAC;
374 }
375
376 - (NSString *) CALEGetAddressFromBTDevice: (CBPeripheral *)peripheral{
377     if (peripheral == (id) [NSNull null]){
378         OIC_LOG(ERROR, TAG, "[CBCtrl] In - CALEGetAddressFromBTDevice: peripheral is null");
379     }else{
380         return [cbPeripherals objectForKey: peripheral];
381     }
382     return nil;
383 }
384
385 #pragma mark - CBCentralManagerDelegate
386 - (void)centralManagerDidUpdateState:(CBCentralManager *)central{
387     switch(central.state){
388         case CBCentralManagerStatePoweredOn:
389             OIC_LOG(DEBUG, TAG, "CBCentralManager update state --> Powered ON");
390
391             //if state callback is called before bt le client initialize done, wait signal.
392             if (!g_isStartedLEClient) {
393                 OIC_LOG(INFO, TAG, "wait for finishing initialize..");
394
395                 if (NULL == g_initializeMutex)
396                 {
397                     g_initializeMutex = oc_mutex_new();
398                     if (NULL == g_initializeMutex)
399                     {
400                         OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
401                     }
402                 }
403
404                 oc_mutex_lock(g_initializeMutex);
405                 oc_cond_wait(g_initializeCond, g_initializeMutex);
406                 oc_mutex_unlock(g_initializeMutex);
407             }
408
409             if (![centralMgrs containsObject: centralMgr]) {
410                 centralMgr = central;
411                 [centralMgrs addObject: centralMgr];
412             }
413
414             CALEClientSetFlagBTAdapter(true);
415             CALEClientNWStateChangeCallback(CALE_STATE_ON);
416
417             break;
418         case CBCentralManagerStateResetting:
419             OIC_LOG(DEBUG, TAG, "CBCentralManager update state --> StateResetting");
420             break;
421         case CBCentralManagerStateUnsupported:
422         case CBCentralManagerStateUnauthorized:
423         case CBCentralManagerStatePoweredOff:
424         default:
425             OIC_LOG(DEBUG, TAG, "CBCentralManager update state --> Not Available");
426             CALEClientSetFlagBTAdapter(false);
427             CALEClientResetDeviceStateForAll();
428
429             CALEClientRemoveAllGattObjs();
430             break;
431     }
432
433     if(g_caManagerQueue)
434     {
435         dispatch_async(g_caManagerQueue, ^{
436
437             if(g_caManagerAdapterStateChangeCallback)
438             {
439                 g_caManagerAdapterStateChangeCallback(central);
440             }
441         });
442     }
443 }
444
445 - (void)centralManager:(CBCentralManager *)central
446  didDiscoverPeripheral:(CBPeripheral *)peripheral
447      advertisementData:(NSDictionary<NSString*, id> *) advertisementData
448                   RSSI:(NSNumber *) RSSI{
449     if (g_isStartedLEClient){
450         OIC_LOG_V(INFO, TAG, "[CBCtrl] didDiscoverPeripheral : peripheral name = %s", [[peripheral name] UTF8String]);
451
452         if([cbPeripherals objectForKey:peripheral] == nil && [self isValidUUID:advertisementData])
453         {
454
455             if ([cbPeripherals count] > 0){
456                 OIC_LOG(DEBUG, TAG, "new peripheral");
457                 [cbPeripherals setObject:[cbCentralIf CALEClientGetMAC:
458                                           [advertisementData objectForKey:
459                                            CBAdvertisementDataManufacturerDataKey]]
460                                   forKey:peripheral];
461                 CALEClientAddScanDeviceToList(peripheral);
462             }else{
463                 if (nil != cbCentralIf){
464                     OIC_LOG(DEBUG, TAG, "1st discovered peripheral");
465                     [cbPeripherals setObject:[cbCentralIf CALEClientGetMAC:
466                                               [advertisementData objectForKey:
467                                                CBAdvertisementDataManufacturerDataKey]]
468                                       forKey: peripheral];
469                     CALEClientAddScanDeviceToList(peripheral);
470                 }
471             }
472         }
473     }else{
474         OIC_LOG(DEBUG, TAG, "[CBCtrl] g_isStertedLEClient == false");
475     }
476 }
477
478 - (void)centralManager:(CBCentralManager*)central
479   didConnectPeripheral:(CBPeripheral *)peripheral {
480     peripheral.delegate = self;
481
482     const char *address = [[cbCentralIf CALEGetAddressFromBTDevice: peripheral] UTF8String];
483     OIC_LOG_V(DEBUG, TAG, "[CBCtrl] didConnectPeripheral : connected peripheral = %s", address);
484
485     CALEState_t* curState = CALEClientGetStateInfo(address);
486     if (curState == NULL || curState->connectedState != STATE_CONNECTED) {
487         CALEClientUpdateDeviceState(address, STATE_CONNECTED,
488                                     STATE_CHARACTER_UNSET,STATE_SEND_NONE);
489
490         [cbCentralIf CALEClientDiscoverServices: peripheral];
491     }
492
493     if(g_caManagerQueue)
494     {
495         dispatch_async(g_caManagerQueue, ^{
496
497             if(g_caManagerConnectionCallback)
498             {
499                 g_caManagerConnectionCallback(peripheral, address, true, nil);
500             }
501         });
502     }
503
504 }
505
506 - (void)centralManager: (CBCentralManager *)central
507 didFailToConnectPeripheral: (CBPeripheral *)peripheral
508                  error:(NSError *)error{
509
510     OIC_LOG(ERROR, TAG, "[CBCtrl] didFailToConnectPeripheral & start scan");
511     if(error) {
512         OIC_LOG_V(ERROR, TAG, "didFailToConnectPeripheral, error desc = %s",
513                   [[error localizedDescription] UTF8String]);
514     }
515
516     CAResult_t res = CALEClientStartScan();
517     if (CA_STATUS_OK != res){
518         OIC_LOG(ERROR, TAG, "start scan error");
519         CALEClientSendFinish(peripheral);
520         return;
521     }
522
523     char *address = (char*)[[cbCentralIf CALEGetAddressFromBTDevice: peripheral] UTF8String];
524     if (!address){
525         CALEClientSendFinish(peripheral);
526         return;
527     }else{
528         res = CALEClientRemoveDeviceState(address);
529         if (CA_STATUS_OK != res){
530             OIC_LOG(ERROR, TAG, "removedevicestate error");
531             CALEClientSendFinish(peripheral);
532             return;
533         }
534     }
535 }
536
537 - (void)centralManager:(CBCentralManager *)central
538 didDisconnectPeripheral:(CBPeripheral *)peripheral
539                  error:(NSError *)error{
540
541     if(error) {
542         OIC_LOG_V(ERROR, TAG, "didDisconnectPeripheral, error desc = %s",
543                   [[error localizedDescription] UTF8String]);
544     }
545
546     NSString *nsAddr = [cbPeripherals objectForKey:peripheral];
547     const char *address = [nsAddr UTF8String];
548
549     if(address){
550         CALEClientUpdateDeviceState(address, STATE_DISCONNECTED,
551                                     STATE_CHARACTER_UNSET,STATE_SEND_NONE);
552         OIC_LOG_V(DEBUG, TAG, "[CBCtrl] didDisconnectPeripheral : Peripheral address = %s", address);
553
554         if(g_caManagerQueue)
555         {
556             dispatch_async(g_caManagerQueue, ^{
557
558                 if(g_caManagerConnectionCallback)
559                 {
560                     g_caManagerConnectionCallback(peripheral, address, false, error);
561                 }
562             });
563         }
564
565         CALEClientUpdateSendCnt();
566
567         if ( false == CALEClientGetAutoConnectFlag(address) )
568         {
569             CALEClientRemoveDeviceInScanDeviceList(nsAddr);
570         }
571     }
572 }
573
574 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
575     if (error){
576         OIC_LOG_V(ERROR, TAG, "didDiscoverServices, error desc = %s",
577                   [[error localizedDescription] UTF8String]);
578         CALEClientSendFinish(peripheral);
579         return;
580     }
581     const char *address = [CALEClientGetAddressFromGattObj(peripheral) UTF8String];
582
583     OIC_LOG_V(INFO, TAG, "found service for - %s %s", address, [[peripheral name] UTF8String]);
584
585     if (!address){
586         CALEClientSendFinish(peripheral);
587         return;
588     }
589
590     if (!CALEClientIsSetCharacteristic(address)){
591         char *serviceUUID = NULL;
592
593         OIC_LOG_V(ERROR, TAG, "didDiscoverServices, #services = %lu",[peripheral.services count]);
594
595         if ([peripheral.services count] == 0) {
596             OIC_LOG(ERROR, TAG, "didDiscoverServices, no service found from peripheral");
597             CALEClientSendFinish(peripheral);
598             return;
599         }
600         else {
601             for (CBService *service in peripheral.services){
602                 [cbServices setObject:service forKey:peripheral];
603
604                 OIC_LOG(INFO, TAG, "discover characteristics");
605
606                 [peripheral discoverCharacteristics:
607                  @[[CBUUID UUIDWithString:
608                     [NSString stringWithUTF8String:OIC_GATT_CHARACTERISTIC_REQUEST_UUID]],
609                    [CBUUID UUIDWithString:
610                     [NSString stringWithUTF8String:OIC_GATT_CHARACTERISTIC_RESPONSE_UUID]]]
611                  forService:service];
612             }
613         }
614     }else{
615         OIC_LOG(DEBUG, TAG, "already set characteristics");
616
617         if ( g_sendBuffer != nil ) {
618             CAResult_t res = CALEClientWriteCharacteristic(peripheral);
619             if (CA_STATUS_OK != res){
620                 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic failed");
621                 CALEClientSendFinish(peripheral);
622                 return;
623             }
624         }
625
626         if(g_caManagerQueue){
627             OIC_LOG(DEBUG, TAG, "Call caManagerServiceDiscoveredCallback");
628             dispatch_async(g_caManagerQueue, ^{
629
630                 if(g_caManagerServiceDiscoveredCallback)
631                 {
632                     g_caManagerServiceDiscoveredCallback(peripheral, address, error);
633                 }
634             });
635         }
636     }
637 }
638
639 - (void)peripheral: (CBPeripheral *)peripheral
640 didDiscoverCharacteristicsForService: (CBService *)service
641              error:(NSError *)error{
642
643     if(error){
644         OIC_LOG_V(ERROR, TAG, "[CBCtrl] didDiscoverCharacteristicsForService: error = %s",
645                   [[error localizedDescription] UTF8String]);
646         return;
647     }
648     OIC_LOG(DEBUG, TAG, "[CBCtrl] didDiscoverCharacteristicsForService");
649     const char *address = [[cbCentralIf CALEGetAddressFromBTDevice: peripheral] UTF8String];
650
651     for (CBCharacteristic *characteristic in service.characteristics){
652         if (!CALEClientIsSetCharacteristic(address)){
653             if ([characteristic.UUID isEqual:
654                  [CBUUID UUIDWithString:
655                   [NSString stringWithUTF8String:OIC_GATT_CHARACTERISTIC_RESPONSE_UUID]]]){
656                 OIC_LOG_V(DEBUG, TAG, "[CBCtrl] find RESPONSE characteristic @%s", address);
657                 [responseCharacs setObject:characteristic forKey:peripheral];
658
659                 CAResult_t res = CALEClientSetCharacteristicNotification(peripheral,
660                                                                          characteristic);
661                 if (CA_STATUS_OK != res){
662                     OIC_LOG(ERROR, TAG, "CALEClientSetCharacteristicNotification has failed");
663                     CALEClientSendFinish(peripheral);
664                     return;
665                 }
666             }
667
668             if ([characteristic.UUID isEqual:
669                  [CBUUID UUIDWithString:
670                   [NSString stringWithUTF8String:OIC_GATT_CHARACTERISTIC_REQUEST_UUID]]]){
671                      OIC_LOG_V(DEBUG, TAG, "[CBCtrl] find REQUEST characteristic @%s", address);
672                      [requestCharacs setObject:characteristic forKey:peripheral];
673
674                      CAResult_t res = CALEClientUpdateDeviceState(address, STATE_CONNECTED,
675                                                               STATE_CHARACTER_SET, STATE_SEND_NONE);
676
677                      if (CA_STATUS_OK != res){
678                          OIC_LOG(ERROR, TAG, "CALEClientUpdataeDeviceState has failed");
679                          CALEClientSendFinish(peripheral);
680                          return;
681                      }
682
683                      res = CALEClientAddGattobjToList(peripheral);
684                      if (CA_STATUS_OK != res){
685                          OIC_LOG(ERROR, TAG, "CALEClientAddGattobjToList has failed");
686                          CALEClientSendFinish(peripheral);
687                          return;
688                      }
689
690                      if ( g_sendBuffer != nil ) {
691                          res = CALEClientWriteCharacteristic(peripheral);
692                          if (CA_STATUS_OK != res){
693                              OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
694                              CALEClientSendFinish(peripheral);
695                              return;
696                          }
697                      }
698                  }
699         }else{
700             CAResult_t res = CALEClientWriteCharacteristic(peripheral);
701             if (CA_STATUS_OK != res){
702                 OIC_LOG(ERROR, TAG, "CALEClientWriteCharacteristic has failed");
703                 CALEClientSendFinish(peripheral);
704                 return;
705             }
706         }
707     }
708
709
710     if(g_caManagerQueue)
711     {
712         OIC_LOG(DEBUG, TAG, "Call caManagerServiceDiscoveredCallback");
713         dispatch_async(g_caManagerQueue, ^{
714
715             if(g_caManagerServiceDiscoveredCallback)
716             {
717                 g_caManagerServiceDiscoveredCallback(peripheral, address, error);
718             }
719         });
720     }
721
722 }
723
724 - (void)peripheral: (CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic
725                   :(CBCharacteristic *)characteristic error:(NSError *)error{
726     if(error){
727         OIC_LOG_V(ERROR, TAG, "didUpdateNotificationStateForCharacteristic error = %s",
728                   [[error localizedDescription] UTF8String]);
729     } else {
730         OIC_LOG(INFO, TAG, "didUpdateNotificationStateForCharacteristic");
731     }
732 }
733
734 - (void)peripheral: (CBPeripheral *)peripheral
735 didUpdateValueForCharacteristic: (CBCharacteristic *)characteristic
736              error:(NSError *)error{
737     if(error){
738         OIC_LOG_V(ERROR, TAG, "[CBCtrl] didUpdateValueForCharacteristic: ERROR = %s",
739                   [[error localizedDescription] UTF8String]);
740         return;
741     }
742
743     const char *address = [[cbPeripherals objectForKey: peripheral] UTF8String];
744     OIC_LOG_V(INFO, TAG, "[CBctrl] Update Value address: %s", address);
745
746     NSMutableData *nsData = [[NSMutableData alloc] init];
747     [nsData appendData:characteristic.value];
748     uint32_t len = [nsData length];
749     uint8_t *data = (uint8_t*) OICMalloc(len);
750     uint32_t sentLength = 0;
751     memcpy(data, (const uint8_t*)[nsData bytes], len);
752     [nsData release];
753     OIC_LOG_BUFFER(DEBUG, TAG, data, len);
754     oc_mutex_lock(g_bleServerBDAddressMutex);
755     g_CABLEClientDataReceivedCallback(address, data, len, &sentLength);
756     oc_mutex_unlock(g_bleServerBDAddressMutex);
757 }
758
759 -(bool) isValidUUID:(NSDictionary<NSString*, id> *) dict
760 {
761     NSData* dat = [dict objectForKey:CBAdvertisementDataManufacturerDataKey];
762     if([dat length] >= TV_ADV_DATA_MIN_LEN)
763     {
764         const unsigned char *bytes = (unsigned char *)dat.bytes;
765
766         int b1 = (int)bytes[TV_ADV_COMPANY_ID_INDEX1];
767         int b2 = (int)bytes[TV_ADV_COMPANY_ID_INDEX2];
768         int b3 = (int)bytes[TV_ADV_VERSION_INDEX];
769         int b4 = (int)bytes[TV_ADV_SERVICE_TYPE_INDEX];
770
771         if((b1 == TV_ADV_COMPANY_ID1) && (b2 == TV_ADV_COMPANY_ID2) && (b3 == TV_ADV_VERSION) &&
772            (b4 == TV_ADV_SERVICE_ID_POWER || b4 == TV_ADV_SERVICE_ID_OOB))
773         {
774
775             int b6 = (int)bytes[TV_ADV_DEVICE_STATUS_INDEX];
776             if((b4 == TV_ADV_SERVICE_ID_POWER) && (b6 == TV_ADV_DEVICE_STATUS_UNKNOWN))
777             {
778                 OIC_LOG(INFO, TAG, "discarded mode 4"); /*mac not available, dev status unknown
779                                               discard now to receive next adv_ind with status*/
780                 return false;
781             }
782
783             int b5 = (int)bytes[TV_ADV_SCAN_RESP_LEN_INDEX];
784             int b20 = (int)bytes[TV_ADV_BD_ADDRTYPE_INDEX]; //address type
785             if(b4 == TV_ADV_SERVICE_ID_OOB &&
786                (b5 == TV_ADV_SCAN_RESP_LEN || b20 == TV_ADV_DEVICE_STATUS_UNKNOWN))
787             {
788                 OIC_LOG_V(INFO, TAG, "discarded mode 9, b5 = %d", b5); /*mac not avilable
789                                  this is scan resp, discard now to receive next adv_ind*/
790                 return false;
791             }
792
793             OIC_LOG_V(INFO, TAG, "Custom advertisement with mac, service type = %d", b4);
794             return true;
795         }
796     }
797
798     NSArray* arr = [dict objectForKey:CBAdvertisementDataServiceUUIDsKey];
799     if([arr count] > 0)
800     {
801         for(CBUUID *serv in arr) {
802             if([serv isEqual:[CBUUID UUIDWithString:
803                               [NSString stringWithUTF8String:OIC_GATT_SERVICE_UUID]]]){
804
805                 OIC_LOG(INFO, TAG, "IoTivity Service Advertisement");
806                 return true;
807             }
808         }
809     }
810
811     return false;
812 }
813
814 @end
815
816
817 int ishexdigit(char var)
818 {
819     if(var <= '9')
820     {
821         if(var >= '0') {
822           return 1;
823         } else {
824           return 0;
825         }
826     }
827     else if(var <= 'F')
828     {
829         if(var >= 'A') {
830           return 1;
831         } else {
832           return 0;
833         }
834     }
835     else if(var <= 'f')
836     {
837         if(var >= 'a') {
838           return 1;
839         } else {
840           return 0;
841         }
842     }
843
844     return 0;
845 }
846
847 int isMAC(const char *address)
848 {
849     /*
850      * Check if the provided MAC address is valid.
851      * 1. The length of MAC address should always be 17.
852      * 2. Hyphens are expected at positions {3, 6, 9, 12, 15}.
853      * 3. The rest characters should be simple xdigits.
854      */
855     int hyphens[5] = {3, 6, 9, 12, 15};
856     if (strlen(address) != 17)
857     {
858         return 0;//Oops. The lenth doesn't match.
859     }
860
861     for (int i = 0, counter = 0; i < 17; i ++)
862     {
863         char var = address[i];
864         if (i == hyphens[counter] - 1)// Check if a hyphen is expected here.
865         {
866             // Yep. We need a hyphen here.
867             if (var != ':')
868             {
869                 return 0;// Oops. The character is not a hyphen.
870             }
871             else
872             {
873                 counter++;// Move on to the next expected hyphen position.
874             }
875         }
876         else
877         {
878             // Nope. The character here should be a simple xdigit
879             if (ishexdigit(var) == 0)
880             {
881                 return 0;// Oops. The current character is not a hyphen.
882             }
883         }
884     }
885     return 1;// Seen'em all!
886 }
887
888 CAResult_t CALEClientInitialize()
889 {
890     OIC_LOG(DEBUG, TAG, "IN - CALEClientInitialize");
891
892     CAResult_t ret = CALEClientInitGattMutexVaraibles();
893     if (CA_STATUS_OK != ret){
894         OIC_LOG(ERROR, TAG, "CALEClientInitGattMutexVaraibles has failed!");
895         CALEClientTerminateGattMutexVariables();
896
897         return ret;
898     }
899
900     // init cond for initialize logic
901     if (g_initializeCond == NULL) {
902         g_initializeCond = oc_cond_new();
903     }
904
905     cbCentralIf = [[CBCentralIfClass alloc] init];
906     [cbCentralIf CALEClientCreateCentralManager];
907
908     g_deviceDescCond = oc_cond_new();
909
910     // init mutex for send logic
911     g_threadCond = oc_cond_new();
912     g_threadWriteCharacteristicCond = oc_cond_new();
913     g_deviceScanRetryDelayCond = oc_cond_new();
914
915     CALEClientCreateDeviceList();
916
917     g_isStartedLEClient = true;
918
919     oc_cond_signal(g_initializeCond);
920
921     return CA_STATUS_OK;
922 }
923
924 void CALEClientTerminate()
925 {
926     OIC_LOG(DEBUG, TAG, "IN - CALEClientTerminate");
927
928     if (g_sendBuffer != nil){
929         g_sendBuffer = nil;
930     }
931
932     CAResult_t ret = CALEClientRemoveAllDeviceState();
933     if (CA_STATUS_OK != ret)
934     {
935         OIC_LOG(ERROR, TAG, "CALEClientRemoveAllDeviceState has failed");
936     }
937
938     ret = CALEClientRemoveAllScanDevices();
939     if (CA_STATUS_OK != ret)
940     {
941         OIC_LOG(ERROR, TAG, "CALEClientRemoveAllScanDevices has failed");
942     }
943
944     ret = CALEClientRemoveAllGattObjs();
945     if (CA_STATUS_OK != ret)
946     {
947         OIC_LOG(ERROR, TAG, "CALEClientRemoveAllGattObjs has failed");
948     }
949
950     CALEClientSetScanFlag(false);
951     CALEClientSetSendFinishFlag(true);
952
953     CALEClientTerminateGattMutexVariables();
954
955     oc_cond_free(g_deviceDescCond);
956     oc_cond_free(g_threadCond);
957     oc_cond_free(g_threadWriteCharacteristicCond);
958     oc_cond_free(g_deviceScanRetryDelayCond);
959     oc_cond_free(g_initializeCond);
960
961     g_deviceDescCond = NULL;
962     g_threadCond = NULL;
963     g_threadWriteCharacteristicCond = NULL;
964     g_deviceScanRetryDelayCond = NULL;
965     g_initializeCond = NULL;
966
967     g_isSignalSetFlag = false;
968
969     centralMgr.delegate = nil;
970     if ([centralMgrs count] != 0) {
971         for (CBCentralManager *mgr in centralMgrs){
972             [centralMgrs removeObject:mgr];
973         }
974     }
975
976     [cbCentralIf release];
977     cbCentralIf = nil;
978
979     OIC_LOG(DEBUG, TAG, "OUT - CALEClientTerminate");
980 }
981
982 void CALEClientSendFinish(CBPeripheral *peripheral)
983 {
984     OIC_LOG(DEBUG, TAG, "CALEClientSendFinish");
985
986     if (peripheral)
987     {
988         CAResult_t res = CALEClientDisconnect(peripheral);
989         if (CA_STATUS_OK != res)
990         {
991             OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
992         }
993     }
994     CALEClientUpdateSendCnt();
995 }
996
997 CAResult_t CALEClientSendUnicastMessage(const char* address,
998                                         const uint8_t* data,
999                                         const uint32_t dataLen)
1000 {
1001     OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessage(%s, %p)", address, data);
1002     VERIFY_NON_NULL(address, TAG, "address is null");
1003     VERIFY_NON_NULL(data, TAG, "data is null");
1004
1005     return CALEClientSendUnicastMessageImpl(address, data, dataLen);
1006 }
1007
1008 CAResult_t CALEClientSendMulticastMessage(const uint8_t* data,
1009                                           const uint32_t dataLen)
1010 {
1011     OIC_LOG_V(DEBUG, TAG, "CALEClientSendMulticastMessage(%p)", data);
1012     VERIFY_NON_NULL(data, TAG, "data is null");
1013
1014     CAResult_t ret = CALEClientSendMulticastMessageImpl(data, dataLen);
1015     if (CA_STATUS_OK != ret)
1016     {
1017         OIC_LOG(ERROR, TAG, "CALEClientSendMulticastMessageImpl has failed");
1018     }
1019
1020     return ret;
1021 }
1022
1023 CAResult_t CALEClientStartUnicastServer(const char* address)
1024 {
1025     OIC_LOG_V(DEBUG, TAG, "it is not needed in this platform (%s)", address);
1026
1027     return CA_NOT_SUPPORTED;
1028 }
1029
1030 CAResult_t CALEClientStartMulticastServer()
1031 {
1032     OIC_LOG(DEBUG, TAG, "it is not needed in this platform");
1033
1034     return CA_NOT_SUPPORTED;
1035 }
1036
1037 void CALEClientStopUnicastServer()
1038 {
1039     OIC_LOG(DEBUG, TAG, "CALEClientStopUnicastServer");
1040 }
1041
1042 void CALEClientStopMulticastServer()
1043 {
1044     OIC_LOG(DEBUG, TAG, "CALEClientStopMulticastServer");
1045 }
1046
1047 void CALEClientSetCallback(CAPacketReceiveCallback callback)
1048 {
1049     g_packetReceiveCallback = callback;
1050 }
1051
1052 void CALEClientSetCAManagerCallback(CAManagerAdapterStateChangeCallback adapterStateChangeCB,
1053                                     CAManagerConnectionCallback connectionCB,
1054                                     CAManagerServiceDiscoveredCallback serviceDiscoverdCB)
1055 {
1056     VERIFY_NON_NULL_VOID(adapterStateChangeCB, TAG, "adapterStateChangeCB is null");
1057     VERIFY_NON_NULL_VOID(connectionCB, TAG, "connectionCB is null");
1058     VERIFY_NON_NULL_VOID(serviceDiscoverdCB, TAG, "serviceDiscoverdCB is null");
1059
1060     if (!g_caManagerQueue) {
1061         g_caManagerQueue = dispatch_queue_create("com.caManager", DISPATCH_QUEUE_SERIAL);
1062     }
1063
1064     g_caManagerAdapterStateChangeCallback = adapterStateChangeCB;
1065     g_caManagerConnectionCallback = connectionCB;
1066     g_caManagerServiceDiscoveredCallback = serviceDiscoverdCB;
1067 }
1068
1069
1070 void CASetBLEClientErrorHandleCallback(CABLEErrorHandleCallback callback)
1071 {
1072     g_clientErrorCallback = callback;
1073 }
1074
1075 CAResult_t CALEClientIsThereScannedDevices(const char* address)
1076 {
1077     if (!g_deviceList)
1078     {
1079         OIC_LOG(ERROR, TAG, "CALEClientIsThereScannedDevices g_deviceList is null");
1080         return CA_STATUS_FAILED;
1081     }
1082
1083     if (0 == u_arraylist_length(g_deviceList) // multicast
1084         || (address && !CALEClientIsDeviceInScanDeviceList(address))) // unicast
1085     {
1086         // Wait for LE peripherals to be discovered.
1087
1088         // Number of times to wait for discovery to complete.
1089         static size_t const RETRIES = 7;
1090
1091         static uint64_t const TIMEOUT =
1092         3 * MICROSECS_PER_SEC;  // Microseconds
1093
1094         bool devicesDiscovered = false;
1095         for (size_t i = 0; i < RETRIES; ++i)
1096         {
1097             OIC_LOG(DEBUG, TAG, "waiting for target device");
1098             if (oc_cond_wait_for(g_deviceDescCond,
1099                                  g_threadSendMutex,
1100                                  TIMEOUT) == OC_WAIT_SUCCESS)
1101             {
1102                 oc_mutex_lock(g_deviceListMutex);
1103                 size_t scannedDeviceLen = u_arraylist_length(g_deviceList);
1104                 oc_mutex_unlock(g_deviceListMutex);
1105
1106                 if (0 < scannedDeviceLen)
1107                 {
1108                     if (!address  // multicast
1109                         || (address && CALEClientIsDeviceInScanDeviceList(address))) // unicast
1110                     {
1111                         devicesDiscovered = true;
1112                         break;
1113                     }
1114                     else
1115                     {
1116                         if (address)
1117                         {
1118                             OIC_LOG(INFO, TAG, "waiting..");
1119
1120                             oc_mutex_lock(g_deviceScanRetryDelayMutex);
1121                             if (oc_cond_wait_for(g_deviceScanRetryDelayCond,
1122                                                  g_deviceScanRetryDelayMutex,
1123                                                  MICROSECS_PER_SEC) == OC_WAIT_SUCCESS)
1124                             {
1125                                 OIC_LOG(INFO, TAG, "finish to waiting for target device");
1126                                 oc_mutex_unlock(g_deviceScanRetryDelayMutex);
1127                                 break;
1128                             }
1129                             oc_mutex_unlock(g_deviceScanRetryDelayMutex);
1130                             // time out
1131
1132                             // checking whether a target device is found while waiting for time-out.
1133                             if (CALEClientIsDeviceInScanDeviceList(address))
1134                             {
1135                                 devicesDiscovered = true;
1136                                 break;
1137                             }
1138                         }
1139                     }
1140                 }
1141             }
1142         }
1143
1144         // time out for scanning devices
1145         if (!devicesDiscovered)
1146         {
1147             return CA_STATUS_FAILED;
1148         }
1149     }
1150
1151     return CA_STATUS_OK;
1152 }
1153
1154
1155 CAResult_t CALEClientSendUnicastMessageImpl(const char* address,
1156                                             const uint8_t* data,
1157                                             const uint32_t dataLen)
1158 {
1159     OIC_LOG_V(DEBUG, TAG, "CALEClientSendUnicastMessageImpl: \n address: %s, data: %p",
1160               address, data);
1161     VERIFY_NON_NULL(address, TAG, "address is null");
1162     VERIFY_NON_NULL(data, TAG, "data is null");
1163
1164     oc_mutex_lock(g_threadSendMutex);
1165
1166     CALEClientSetSendFinishFlag(false);
1167
1168     CAResult_t ret = CALEClientIsThereScannedDevices(address);
1169     if (CA_STATUS_OK != ret)
1170     {
1171         OIC_LOG(INFO, TAG, "there is no scanned device");
1172         goto error_exit;
1173     }
1174
1175     const char *founded_address = NULL;
1176     uint32_t length = u_arraylist_length(g_deviceList);
1177     OIC_LOG_V(DEBUG, TAG, "g_deviceList : %d", length);
1178     int is_mac = isMAC(address);
1179     for (uint32_t index = 0; index < length; index++)
1180     {
1181         CBPeripheral *peripheral = (CBPeripheral *)u_arraylist_get(g_deviceList, index);
1182         if (!peripheral)
1183         {
1184             OIC_LOG(ERROR, TAG, "devicelist is empty");
1185             goto error_exit;
1186         }
1187
1188         const char *setAddress = NULL;
1189         if(is_mac == 0)
1190         {
1191             setAddress = [[[peripheral identifier] UUIDString] UTF8String];
1192         }
1193         else  //address
1194         {
1195             setAddress = [[cbCentralIf CALEGetAddressFromBTDevice: peripheral] UTF8String];
1196         }
1197
1198         if (!setAddress)
1199         {
1200             OIC_LOG(ERROR, TAG, "setAddress is null");
1201             if(is_mac == 0) { continue; }
1202             else { goto error_exit; }
1203         }
1204
1205         OIC_LOG_V(DEBUG, TAG, "remote device address is %s, scanned peripheral = %s", setAddress,
1206                   [[peripheral name] UTF8String]);
1207
1208         if (!strcmp(setAddress, address))
1209         {
1210             founded_address = [[cbCentralIf CALEGetAddressFromBTDevice: peripheral] UTF8String];
1211
1212             // connect to gatt server
1213             OIC_LOG(DEBUG, TAG, "CALEClientSendUnicastMessageImpl --> stop scan");
1214             ret = CALEClientStopScan();
1215             if (CA_STATUS_OK != ret)
1216             {
1217                 OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
1218                 goto error_exit;
1219             }
1220
1221             if (g_sendBuffer != nil ){
1222                 g_sendBuffer = nil;
1223             }
1224             g_sendBuffer = [NSData dataWithBytes:(const uint8_t*)data length:dataLen];
1225
1226             OIC_LOG_V(DEBUG,TAG, "unicast send data size: %lu", [g_sendBuffer length]);
1227             OIC_LOG_BUFFER(DEBUG,TAG,data,dataLen);
1228
1229             ret = CALEClientSendData(peripheral);
1230             if (CA_STATUS_OK != ret)
1231             {
1232                 OIC_LOG(ERROR, TAG, "CALEClientSendData in unicast is failed");
1233                 goto error_exit;
1234             }
1235
1236             OIC_LOG(INFO, TAG, "wake up");
1237             break;
1238         }
1239     }
1240
1241     OIC_LOG(DEBUG, TAG, "connection routine is finished for unicast");
1242
1243     // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
1244     // if there is no connection state.
1245     oc_mutex_lock(g_threadMutex);
1246     if (!g_isFinishedSendData)
1247     {
1248         OIC_LOG(DEBUG, TAG, "waiting send finish signal");
1249         oc_cond_wait(g_threadCond, g_threadMutex);
1250         OIC_LOG(DEBUG, TAG, "the data was sent");
1251     }
1252     oc_mutex_unlock(g_threadMutex);
1253
1254     // start LE Scan again
1255     ret = CALEClientStartScan();
1256     if (CA_STATUS_OK != ret)
1257     {
1258         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
1259         oc_mutex_unlock(g_threadSendMutex);
1260         return ret;
1261     }
1262
1263     oc_mutex_unlock(g_threadSendMutex);
1264     OIC_LOG(INFO, TAG, "unicast - send logic has finished");
1265     return CALECheckSendState(founded_address);
1266
1267     // error label.
1268 error_exit:
1269
1270     // start LE Scan again
1271     if (!CALEClientStartScan())
1272     {
1273         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
1274         oc_mutex_unlock(g_threadSendMutex);
1275         return CA_STATUS_FAILED;
1276     }
1277
1278     if (g_clientErrorCallback)
1279     {
1280         g_clientErrorCallback(address, data, dataLen, CA_SEND_FAILED);
1281     }
1282     oc_mutex_unlock(g_threadSendMutex);
1283     return CA_SEND_FAILED;
1284 }
1285
1286 CAResult_t CALEClientSendMulticastMessageImpl(const uint8_t* data,
1287                                               const uint32_t dataLen)
1288 {
1289     OIC_LOG_V(DEBUG, TAG, "CASendMulticastMessageImpl, send to, data: %p, %u", data, dataLen);
1290     VERIFY_NON_NULL(data, TAG, "data is null");
1291
1292     if (!g_deviceList)
1293     {
1294         OIC_LOG(ERROR, TAG, "g_deviceList is null");
1295         return CA_STATUS_FAILED;
1296     }
1297
1298     uint32_t length = 0;
1299     oc_cond waitCond = NULL;
1300
1301     oc_mutex_lock(g_threadSendMutex);
1302
1303     CALEClientSetSendFinishFlag(false);
1304
1305     OIC_LOG(DEBUG, TAG, "set byteArray for data");
1306
1307     CAResult_t res = CALEClientIsThereScannedDevices(NULL);
1308     if (CA_STATUS_OK != res)
1309     {
1310         OIC_LOG(INFO, TAG, "there is no scanned device");
1311         goto error_exit;
1312     }
1313
1314     // connect to gatt server
1315     OIC_LOG(DEBUG, TAG, "CALEClientSendMulticastMessageImpl --> stop scan");
1316     res = CALEClientStopScan();
1317     if (CA_STATUS_OK != res)
1318     {
1319         OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
1320         oc_mutex_unlock(g_threadSendMutex);
1321         return res;
1322     }
1323     length = u_arraylist_length(g_deviceList);
1324     g_targetCnt = length;
1325
1326     if ( g_sendBuffer != nil ){
1327         g_sendBuffer = nil;
1328     }
1329
1330     g_sendBuffer = [NSData dataWithBytes:(const uint8_t*)data length:dataLen];
1331
1332     OIC_LOG_V(DEBUG,TAG, "unicast send data size: %lu", [g_sendBuffer length]);
1333     OIC_LOG_BUFFER(DEBUG,TAG,data,dataLen);
1334
1335     for (uint32_t index = 0; index < length; index++)
1336     {
1337         OIC_LOG_V(DEBUG, TAG, "target cnt: %d/%d", index+1,length);
1338         CBPeripheral *peripheral = (CBPeripheral *)u_arraylist_get(g_deviceList, index);
1339         if (!peripheral)
1340         {
1341             OIC_LOG(ERROR, TAG, "peripheral is not available");
1342             continue;
1343         }
1344         else{
1345             CALEClientSendData(peripheral);
1346         }
1347     }
1348     OIC_LOG(DEBUG, TAG, "connection routine is finished for multicast");
1349
1350     // wait for finish to send data through "CALeGattServicesDiscoveredCallback"
1351     oc_mutex_lock(g_threadMutex);
1352     if (!g_isFinishedSendData)
1353     {
1354         OIC_LOG(DEBUG, TAG, "waiting send finish signal");
1355         oc_cond_wait(g_threadCond, g_threadMutex);
1356         OIC_LOG(DEBUG, TAG, "the data was sent");
1357     }
1358     oc_mutex_unlock(g_threadMutex);
1359
1360     // start LE Scan again
1361     res = CALEClientStartScan();
1362     if (CA_STATUS_OK != res)
1363     {
1364         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
1365         oc_mutex_unlock(g_threadSendMutex);
1366         return res;
1367     }
1368
1369     oc_mutex_unlock(g_threadSendMutex);
1370     OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
1371     return CA_STATUS_OK;
1372
1373 error_exit:
1374     res = CALEClientStartScan();
1375     if (CA_STATUS_OK != res)
1376     {
1377         OIC_LOG(ERROR, TAG, "CALEClientStartScan has failed");
1378         oc_mutex_unlock(g_threadSendMutex);
1379         return res;
1380     }
1381
1382     oc_mutex_unlock(g_threadSendMutex);
1383     OIC_LOG(DEBUG, TAG, "OUT - CALEClientSendMulticastMessageImpl");
1384     return CA_SEND_FAILED;
1385 }
1386
1387 CAResult_t CALECheckSendState(const char* address)
1388 {
1389     VERIFY_NON_NULL(address, TAG, "address is null");
1390
1391     oc_mutex_lock(g_deviceStateListMutex);
1392     CALEState_t* state = CALEClientGetStateInfo(address);
1393     if (NULL == state)
1394     {
1395         OIC_LOG(ERROR, TAG, "state is null");
1396         oc_mutex_unlock(g_deviceStateListMutex);
1397         return CA_SEND_FAILED;
1398     }
1399
1400     if (STATE_SEND_SUCCESS != state->sendState)
1401     {
1402         OIC_LOG(ERROR, TAG, "sendstate is not STATE_SEND_SUCCESS");
1403         oc_mutex_unlock(g_deviceStateListMutex);
1404         return CA_SEND_FAILED;
1405     }
1406
1407     OIC_LOG(INFO, TAG, "sendstate is STATE_SEND_SUCCESS");
1408     oc_mutex_unlock(g_deviceStateListMutex);
1409     return CA_STATUS_OK;
1410 }
1411
1412 CAResult_t CALEClientSendData(CBPeripheral *peripheral)//, CBService *service)
1413 {
1414     OIC_LOG(DEBUG, TAG, "IN - CALEClientSendData");
1415
1416     // get BLE address from bluetooth device object.
1417     CALEState_t* state = NULL;
1418     char *address = (char*)[[cbCentralIf CALEGetAddressFromBTDevice: peripheral] UTF8String];
1419     if (!address)
1420     {
1421         OIC_LOG(ERROR, TAG, "address is not available");
1422         return CA_STATUS_FAILED;
1423     }
1424     oc_mutex_lock(g_deviceStateListMutex);
1425     state = CALEClientGetStateInfo(address);
1426     oc_mutex_unlock(g_deviceStateListMutex);
1427
1428     if (!state)
1429     {
1430         OIC_LOG(DEBUG, TAG, "state is empty..start to connect LE");
1431
1432         // cancel previous connection request before connection
1433         // if there is gatt object in g_gattObjectList.
1434
1435         // connection request
1436         CAResult_t ret = CALEClientConnect(peripheral, false);
1437         if (CA_STATUS_OK != ret){
1438             OIC_LOG(ERROR, TAG, "CALEClientConnect failed");
1439             return ret;
1440         }
1441     }
1442     else
1443     {
1444         if (STATE_CONNECTED == state->connectedState)
1445         {
1446             OIC_LOG(INFO, TAG, "GATT has already connected");
1447
1448             CBPeripheral *tPeripheral = CALEClientGetGattObjInList(address);
1449             if (!tPeripheral)
1450             {
1451                 OIC_LOG(ERROR, TAG, "CALEClientGetGattObjInList has failed");
1452                 //return CA_STATUS_FAILED;
1453                 goto exit;
1454             }
1455
1456             CAResult_t ret = CALEClientWriteCharacteristic(peripheral);
1457             //CAResult_t ret = CALESetValueAndWriteCharacteristic(peripheral, service);
1458             if (CA_STATUS_OK != ret)
1459             {
1460                 OIC_LOG(ERROR, TAG, "WriteCharacteristic has failed");
1461                 return ret;
1462             }
1463         }
1464         else
1465         {
1466             OIC_LOG(INFO, TAG, "STATE_DISCONNECTED - start to connect LE");
1467
1468             // cancel previous connection request before connection
1469             // if there is gatt object in g_gattObjectList.
1470
1471             OIC_LOG(DEBUG, TAG, "start to connect LE");
1472             CAResult_t ret = CALEClientConnect(peripheral, CALEClientGetAutoConnectFlag(address));
1473             if (CA_STATUS_OK != ret){
1474                 OIC_LOG(ERROR, TAG, "CALEClientConnect failed");
1475                 return ret;
1476             }
1477         }
1478     }
1479
1480     return CA_STATUS_OK;
1481 exit:
1482     return CA_STATUS_OK;
1483 }
1484
1485 NSString *CALEClientGetAddressFromGattObj(CBPeripheral *peripheral)
1486 {
1487     VERIFY_NON_NULL_RET(peripheral, TAG, "peripheral is null", NULL);
1488
1489     return [cbPeripherals objectForKey: peripheral];
1490 }
1491
1492 /**
1493  * BLE layer
1494  */
1495 CAResult_t CALEClientGattClose(CBPeripheral *peripheral)
1496 {
1497     // GATT CLOSE
1498     OIC_LOG(DEBUG, TAG, "Gatt Close");
1499     [cbCentralIf CALEClientCancelPeripheralConnection:peripheral];
1500     return CA_STATUS_OK;
1501 }
1502
1503 CAResult_t CALEClientStartScan()
1504 {
1505     if (!CALEClientIsEnableBTAdapter())
1506     {
1507         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1508         return CA_ADAPTER_NOT_ENABLED;
1509     }
1510
1511     if (!g_isStartedLEClient)
1512     {
1513         OIC_LOG(ERROR, TAG, "LE client is not started");
1514         return CA_STATUS_FAILED;
1515     }
1516
1517     if (g_isStartedScan)
1518     {
1519         OIC_LOG(INFO, TAG, "scanning is already started");
1520         return CA_STATUS_OK;
1521     }
1522
1523     OIC_LOG(DEBUG, TAG, "CALEClientStartScan");
1524
1525     CAResult_t ret = CA_STATUS_OK;
1526
1527 #ifdef UUID_SCAN
1528     ret = CA_ADAPTER_NOT_ENABLE;
1529 #else
1530     ret = [cbCentralIf CALEClientStartScanImpl];
1531 #endif
1532     if (CA_STATUS_OK != ret)
1533     {
1534         if (CA_ADAPTER_NOT_ENABLED == ret)
1535         {
1536             OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1537         }
1538         else
1539         {
1540             OIC_LOG(ERROR, TAG, "start scan has failed");
1541         }
1542     }
1543
1544     return ret;
1545 }
1546
1547 CAResult_t CALEClientStopScan()
1548 {
1549     if (!g_isStartedScan)
1550     {
1551         OIC_LOG(INFO, TAG, "scanning is already stopped");
1552         return CA_STATUS_OK;
1553     }
1554
1555     CAResult_t ret = [cbCentralIf CALEClientStopScanImpl];
1556     if (CA_STATUS_OK != ret)
1557     {
1558         if (CA_ADAPTER_NOT_ENABLED == ret)
1559         {
1560             OIC_LOG(DEBUG, TAG, "Adapter is disabled");
1561         }
1562         else
1563         {
1564             OIC_LOG(ERROR, TAG, "CALEClientStopScanImpl has failed");
1565         }
1566     }
1567     else
1568     {
1569         CALEClientSetScanFlag(false);
1570     }
1571
1572     return ret;
1573 }
1574
1575 void CALEClientSetScanFlag(bool flag)
1576 {
1577     oc_mutex_lock(g_scanMutex);
1578     g_isStartedScan = flag;
1579     oc_mutex_unlock(g_scanMutex);
1580 }
1581
1582 CAResult_t CALEClientSetAutoConnectFlag(const char *address, bool flag)
1583 {
1584     OIC_LOG(DEBUG, TAG, "IN - CALEClientSetAutoConnectFlag");
1585
1586     oc_mutex_lock(g_deviceStateListMutex);
1587
1588     if (!address)
1589     {
1590         OIC_LOG(ERROR, TAG, "address is not available");
1591         return CA_STATUS_FAILED;
1592     }
1593
1594     if (CALEClientIsDeviceInList(address))
1595     {
1596         CALEState_t* curState = CALEClientGetStateInfo(address);
1597         if(!curState)
1598         {
1599             OIC_LOG(ERROR, TAG, "curState is null");
1600             oc_mutex_unlock(g_deviceStateListMutex);
1601             return CA_STATUS_FAILED;
1602         }
1603         OIC_LOG_V(INFO, TAG, "auto connect flag is set %d", flag);
1604
1605         curState->autoConnectFlag = flag;
1606     }
1607
1608     oc_mutex_unlock(g_deviceStateListMutex);
1609     OIC_LOG(DEBUG, TAG, "OUT - CALEClientSetAutoConnectFlag");
1610     return CA_STATUS_OK;
1611 }
1612
1613 bool CALEClientGetAutoConnectFlag(const char *address)
1614 {
1615     OIC_LOG(DEBUG, TAG, "IN - CALEClientGetAutoConnectFlag");
1616
1617     oc_mutex_lock(g_deviceStateListMutex);
1618
1619     if (!address)
1620     {
1621         OIC_LOG(ERROR, TAG, "address is not available");
1622         return false;
1623     }
1624
1625     CALEState_t* curState = CALEClientGetStateInfo(address);
1626     if(!curState)
1627     {
1628         OIC_LOG(INFO, TAG, "there is no information. auto connect flag is false");
1629         oc_mutex_unlock(g_deviceStateListMutex);
1630         return false;
1631     }
1632     OIC_LOG_V(INFO, TAG, "auto connect flag is %d", curState->autoConnectFlag);
1633
1634     oc_mutex_unlock(g_deviceStateListMutex);
1635
1636     OIC_LOG(DEBUG, TAG, "OUT - CALEClientGetAutoConnectFlag");
1637     return curState->autoConnectFlag;
1638 }
1639
1640 CAResult_t CALEClientConnect(CBPeripheral *peripheral, bool autoconnect)
1641 {
1642     OIC_LOG(DEBUG, TAG, "CALEClientConnect");
1643
1644     return [cbCentralIf CALEClientConnectImpl:peripheral];
1645 }
1646
1647 CAResult_t CALEClientDisconnect(CBPeripheral *peripheral)
1648 {
1649     OIC_LOG(DEBUG, TAG, "GATT DISCONNECT");
1650
1651     [cbCentralIf CALEClientCancelPeripheralConnection: peripheral];
1652     return CA_STATUS_OK;
1653 }
1654
1655 CAResult_t CALEClientConnectCancel(CBPeripheral *peripheral)
1656 {
1657     OIC_LOG(DEBUG, TAG, "GATT CONNECT CENCEL");
1658
1659     [cbCentralIf CALEClientCancelPeripheralConnection: peripheral];
1660     return CA_STATUS_OK;
1661 }
1662
1663 CAResult_t CALEClientDisconnectAll()
1664 {
1665     OIC_LOG(DEBUG, TAG, "CALEClientDisconnectAll");
1666
1667     if (!g_gattObjectList)
1668     {
1669         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1670         return CA_STATUS_OK;
1671     }
1672
1673     uint32_t length = u_arraylist_length(g_gattObjectList);
1674     OIC_LOG_V(DEBUG, TAG, "list length : %d", length);
1675     for (uint32_t index = 0; index < length; index++)
1676     {
1677         OIC_LOG(DEBUG, TAG, "start CALEClientDisconnectAll");
1678         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_gattObjectList, index);
1679
1680         CAResult_t res = CALEClientDisconnect(tPeripheral);
1681         if (CA_STATUS_OK != res)
1682         {
1683             OIC_LOG(ERROR, TAG, "CALEClientDisconnect has failed");
1684             continue;
1685         }
1686     }
1687
1688     return CA_STATUS_OK;
1689 }
1690
1691 CAResult_t CALEClientDisconnectforAddress(const char *remote_address)
1692 {
1693     OIC_LOG(DEBUG, TAG, "IN-CALEClientDisconnectforAddress");
1694
1695     if (!g_gattObjectList)
1696     {
1697         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
1698         return CA_STATUS_OK;
1699     }
1700
1701     uint32_t length = u_arraylist_length(g_gattObjectList);
1702     for (uint32_t index = 0; index < length; index++)
1703     {
1704         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_gattObjectList, index);
1705
1706         const char* setAddress = [[cbCentralIf CALEGetAddressFromBTDevice: tPeripheral] UTF8String];
1707         if (!setAddress)
1708         {
1709             OIC_LOG(ERROR, TAG, "setAddress is null");
1710             return CA_STATUS_FAILED;
1711         }
1712
1713         if (!strcmp(remote_address, setAddress))
1714         {
1715             CAResult_t res = CALEClientDisconnect(tPeripheral);
1716             if (CA_STATUS_OK != res)
1717             {
1718                 OIC_LOG(ERROR, TAG, "CALEClientDisconnect failed");
1719                 return CA_STATUS_FAILED;
1720             }
1721         }
1722     }
1723     OIC_LOG(DEBUG, TAG, "OUT-CALEClientDisconnectforAddress");
1724     return CA_STATUS_OK;
1725 }
1726
1727 CAResult_t CALEClientWriteCharacteristic(CBPeripheral *peripheral)
1728 {
1729     OIC_LOG(DEBUG, TAG, "IN - CALEClientWriteCharacteristic");
1730
1731     CBService *service = [cbServices objectForKey:peripheral];
1732     if (service == NULL){
1733         OIC_LOG(ERROR, TAG, "can't find service obj");
1734         return CA_STATUS_FAILED;
1735     }else{
1736         CBCharacteristic *requestCharacteristic = [requestCharacs objectForKey:peripheral];
1737         if (requestCharacteristic == NULL){
1738             OIC_LOG(ERROR, TAG, "can't find request characteristic obj");
1739             return CA_STATUS_FAILED;
1740         }else{
1741             CAResult_t ret = CALEClientWriteCharacteristicImpl(peripheral, requestCharacteristic);
1742             if (CA_STATUS_OK != ret){
1743                 CALEClientSendFinish(peripheral);
1744                 return CA_STATUS_FAILED;
1745             }
1746         }
1747     }
1748
1749     OIC_LOG(DEBUG, TAG, "OUT - CALEClientWriteCharacteristic");
1750     return CA_STATUS_OK;
1751 }
1752
1753 CAResult_t CALEClientWriteCharacteristicImpl(CBPeripheral *peripheral,
1754                                              CBCharacteristic *requestCharc)
1755 {
1756     OIC_LOG(DEBUG, TAG, "WRITE GATT CHARACTERISTIC");
1757
1758     if (!CALEClientIsEnableBTAdapter())
1759     {
1760         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1761         return CA_STATUS_FAILED;
1762     }
1763
1764     CAResult_t ret = [cbCentralIf CALEClientWriteValue: peripheral: requestCharc];
1765
1766     const char *address = [CALEClientGetAddressFromGattObj(peripheral) UTF8String];
1767     if (CA_STATUS_OK != ret){
1768         OIC_LOG(ERROR, TAG, "write characteristic failed");
1769         CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
1770                                     STATE_SEND_FAILED);
1771
1772         CALEClientSendFinish(peripheral);
1773         return CA_STATUS_FAILED;
1774     }else{
1775         OIC_LOG(DEBUG, TAG, "writeCharacteristic is called successfully");
1776         CALEClientUpdateDeviceState(address, STATE_CONNECTED, STATE_CHARACTER_SET,
1777                                     STATE_SEND_SUCCESS);
1778         CALEClientUpdateSendCnt();
1779     }
1780
1781     return CA_STATUS_OK;
1782 }
1783
1784 CAResult_t CALEClientSetCharacteristicNotification(CBPeripheral *peripheral,
1785                                                    CBCharacteristic *responsCharc)
1786 {
1787     if (!CALEClientIsEnableBTAdapter())
1788     {
1789         OIC_LOG(INFO, TAG, "BT adapter is not enabled");
1790         return CA_ADAPTER_NOT_ENABLED;
1791     }
1792
1793     [cbCentralIf CALEClientSetNotifyCharacteristic: peripheral: responsCharc];
1794
1795     return CA_STATUS_OK;
1796 }
1797
1798 void CALEClientCreateScanDeviceList()
1799 {
1800     OIC_LOG(DEBUG, TAG, "CALEClientCreateScanDeviceList");
1801
1802     oc_mutex_lock(g_deviceListMutex);
1803     // create new object array
1804     if (g_deviceList == NULL)
1805     {
1806         OIC_LOG(DEBUG, TAG, "Create device list");
1807
1808         g_deviceList = u_arraylist_create();
1809     }
1810     oc_mutex_unlock(g_deviceListMutex);
1811 }
1812
1813 CAResult_t CALEClientAddScanDeviceToList(CBPeripheral *peripheral)
1814 {
1815     oc_mutex_lock(g_deviceListMutex);
1816
1817     if (!g_deviceList)
1818     {
1819         OIC_LOG(ERROR, TAG, "gdevice_list is null");
1820
1821         CALEClientSetScanFlag(false);
1822         OIC_LOG(DEBUG, TAG, "CALEClientAddScanDeviceToList --> stop scan");
1823         if(CA_STATUS_OK != CALEClientStopScan())
1824         {
1825             OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
1826         }
1827
1828         oc_mutex_unlock(g_deviceListMutex);
1829         return CA_STATUS_FAILED;
1830     }
1831
1832     const char *remoteAddress = [[cbCentralIf CALEGetAddressFromBTDevice: peripheral] UTF8String];
1833     if (!remoteAddress)
1834     {
1835         OIC_LOG(ERROR, TAG, "remoteAddress is null");
1836         oc_mutex_unlock(g_deviceListMutex);
1837         return CA_STATUS_FAILED;
1838     }
1839
1840     if (!CALEClientIsDeviceInScanDeviceList(remoteAddress))
1841     {
1842         u_arraylist_add(g_deviceList, peripheral);
1843         oc_cond_signal(g_deviceDescCond);
1844         OIC_LOG_V(DEBUG, TAG, "Added this BT Device[%s] in the List", remoteAddress);
1845     }
1846
1847     oc_mutex_unlock(g_deviceListMutex);
1848
1849     return CA_STATUS_OK;
1850 }
1851
1852 bool CALEClientIsDeviceInScanDeviceList(const char* remoteAddress)
1853 {
1854     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
1855
1856     if (!g_deviceList)
1857     {
1858         OIC_LOG(DEBUG, TAG, "g_deviceList is null");
1859         return true;
1860     }
1861
1862     uint32_t length = u_arraylist_length(g_deviceList);
1863     int is_mac = isMAC(remoteAddress);
1864     for (uint32_t index = 0; index < length; index++)
1865     {
1866         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_deviceList, index);
1867
1868         if(is_mac == 1)
1869         {
1870             const char* setAddress = [[cbCentralIf CALEGetAddressFromBTDevice:
1871                                        tPeripheral] UTF8String];
1872
1873             if (!strcmp(remoteAddress, setAddress))
1874             {
1875                 return true;
1876             }
1877         }
1878         else
1879         {
1880             OIC_LOG(DEBUG, TAG, "this is uuid unicast!");
1881             const char* localUuid = [[[tPeripheral identifier] UUIDString] UTF8String];
1882
1883             if(localUuid == NULL)
1884             {
1885                 continue;
1886             }
1887
1888             if(!strcmp(remoteAddress, localUuid))
1889             {
1890                 OIC_LOG(DEBUG, TAG, "find same one!!!!");
1891                 return true;
1892             }
1893         }
1894     }
1895
1896     OIC_LOG(DEBUG, TAG, "there are no the device in list. we can add");
1897
1898     return false;
1899 }
1900
1901 CAResult_t CALEClientRemoveAllScanDevices()
1902 {
1903     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllScanDevices");
1904
1905     oc_mutex_lock(g_deviceListMutex);
1906
1907     if (!g_deviceList)
1908     {
1909         OIC_LOG(ERROR, TAG, "g_deviceList is null");
1910         oc_mutex_unlock(g_deviceListMutex);
1911         return CA_STATUS_FAILED;
1912     }
1913
1914     uint32_t length = u_arraylist_length(g_deviceList);
1915     for (uint32_t index = 0; index < length; index++)
1916     {
1917         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_deviceList, 0);
1918         tPeripheral.delegate = nil;
1919         [cbPeripherals removeObjectForKey: tPeripheral];
1920         u_arraylist_remove(g_deviceList, 0);
1921     }
1922
1923     OICFree(g_deviceList);
1924     g_deviceList = NULL;
1925
1926     oc_mutex_unlock(g_deviceListMutex);
1927     return CA_STATUS_OK;
1928 }
1929
1930 CAResult_t CALEClientRemoveDeviceInScanDeviceList(NSString *address)
1931 {
1932     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceInScanDeviceList");
1933     VERIFY_NON_NULL(address, TAG, "address is null");
1934     if (nil == address){
1935         OIC_LOG(INFO, TAG, "CALEClientRemoveDeviceInScanDeviceList address == nil");
1936         return CA_STATUS_FAILED;
1937     }
1938
1939     oc_mutex_lock(g_deviceListMutex);
1940
1941     if (!g_deviceList)
1942     {
1943         OIC_LOG(ERROR, TAG, "g_deviceList is null");
1944         oc_mutex_unlock(g_deviceListMutex);
1945         return CA_STATUS_FAILED;
1946     }
1947
1948     uint32_t length = u_arraylist_length(g_deviceList);
1949     for (uint32_t index = 0; index < length; index++)
1950     {
1951         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_deviceList, index);
1952
1953         NSString *setAddress = [cbCentralIf CALEGetAddressFromBTDevice: tPeripheral];
1954
1955         OIC_LOG_V(DEBUG, TAG, "removedeviceinscandevicelist -address: %s-setaddr: %s",
1956                   [address UTF8String], [setAddress UTF8String]);
1957
1958         if ([address isEqualToString:setAddress])
1959         {
1960             [cbPeripherals removeObjectForKey: tPeripheral];
1961             if (NULL == u_arraylist_remove(g_deviceList, index))
1962             {
1963                 OIC_LOG(ERROR, TAG, "List removal failed.");
1964                 oc_mutex_unlock(g_deviceListMutex);
1965                 return CA_STATUS_FAILED;
1966             }
1967             oc_mutex_unlock(g_deviceListMutex);
1968             return CA_STATUS_OK;
1969         }
1970     }
1971
1972     oc_mutex_unlock(g_deviceListMutex);
1973     OIC_LOG(DEBUG, TAG, "There are no object in the device list");
1974
1975     return CA_STATUS_OK;
1976 }
1977
1978 /**
1979  * Gatt Object List
1980  */
1981
1982 CAResult_t CALEClientAddGattobjToList(CBPeripheral *peripheral)
1983 {
1984     OIC_LOG(INFO, TAG, "CALEClientAddGattobjToList");
1985
1986     oc_mutex_lock(g_gattObjectMutex);
1987
1988     if (!g_gattObjectList)
1989     {
1990         OIC_LOG(ERROR, TAG, "g_gattObjectList is not available");
1991         oc_mutex_unlock(g_gattObjectMutex);
1992         return CA_STATUS_FAILED;
1993     }
1994
1995     NSString *remoteAddress = CALEClientGetAddressFromGattObj(peripheral);
1996     if (remoteAddress == nil || [remoteAddress isEqualToString:@"<null>"]
1997         || [remoteAddress isEqualToString:@"null"] || remoteAddress == (id)[NSNull null]
1998         || [[remoteAddress stringByTrimmingCharactersInSet:
1999              [NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""]){
2000         OIC_LOG(ERROR, TAG, "remoteAddress is null");
2001         oc_mutex_unlock(g_gattObjectMutex);
2002         return CA_STATUS_FAILED;
2003     }
2004
2005     const char *remoteAddr = [remoteAddress UTF8String];
2006     OIC_LOG_V(INFO, TAG, "remote address : %s", remoteAddr);
2007     if (!CALEClientIsGattObjInList(remoteAddr))
2008     {
2009         u_arraylist_add(g_gattObjectList, peripheral);
2010         OIC_LOG(INFO, TAG, "Set GATT Object to Array as Element");
2011     }
2012
2013     oc_mutex_unlock(g_gattObjectMutex);
2014     return CA_STATUS_OK;
2015 }
2016
2017 bool CALEClientIsGattObjInList(const char* remoteAddress)
2018 {
2019     OIC_LOG(DEBUG, TAG, "CALEClientIsGattObjInList");
2020
2021     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", true);
2022
2023     uint32_t length = u_arraylist_length(g_gattObjectList);
2024     for (uint32_t index = 0; index < length; index++)
2025     {
2026
2027         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_gattObjectList, index);
2028         if (!tPeripheral)
2029         {
2030             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2031             return true;
2032         }
2033
2034         NSString *setAddress = CALEClientGetAddressFromGattObj(tPeripheral);
2035         if (setAddress == nil || [setAddress isEqualToString:@"<null>"]
2036             || [setAddress isEqualToString:@"null"] || setAddress == (id)[NSNull null]
2037             || [[setAddress stringByTrimmingCharactersInSet:
2038                  [NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""]){
2039             OIC_LOG(ERROR, TAG, "setAddress is null");
2040             return true;
2041         }
2042
2043         const char* setAddr = [setAddress UTF8String];
2044         if (!setAddress)
2045         {
2046             OIC_LOG(ERROR, TAG, "setAddress is null");
2047             return true;
2048         }
2049
2050         if (!strcmp(remoteAddress, setAddr))
2051         {
2052             OIC_LOG(DEBUG, TAG, "the device is already set");
2053             return true;
2054         }
2055         else
2056         {
2057             continue;
2058         }
2059     }
2060
2061     OIC_LOG(DEBUG, TAG, "There are no GATT object in list. it can be added");
2062     return false;
2063 }
2064
2065 CBPeripheral *CALEClientGetGattObjInList(const char* remoteAddress)
2066 {
2067     OIC_LOG(DEBUG, TAG, "CALEClientGetGattObjInList");
2068     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2069
2070     oc_mutex_lock(g_gattObjectMutex);
2071     uint32_t length = u_arraylist_length(g_gattObjectList);
2072     for (uint32_t index = 0; index < length; index++)
2073     {
2074         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_gattObjectList, index);
2075         if (!tPeripheral)
2076         {
2077             OIC_LOG(ERROR, TAG, "peripheral is null");
2078             oc_mutex_unlock(g_gattObjectMutex);
2079             return NULL;
2080         }
2081
2082         NSString *setAddress = CALEClientGetAddressFromGattObj(tPeripheral);
2083         if (setAddress == nil || [setAddress isEqualToString:@"<null>"]
2084             || [setAddress isEqualToString:@"null"] || setAddress == (id)[NSNull null]
2085             || [[setAddress stringByTrimmingCharactersInSet:
2086                  [NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""]){
2087             OIC_LOG(ERROR, TAG, "setAddress is null");
2088             oc_mutex_unlock(g_gattObjectMutex);
2089             return NULL;
2090         }
2091
2092         const char* setAddr = [setAddress UTF8String];
2093         if (!setAddr)
2094         {
2095             OIC_LOG(ERROR, TAG, "setAddress is null");
2096             oc_mutex_unlock(g_gattObjectMutex);
2097             return NULL;
2098         }
2099
2100         if (!strcmp(remoteAddress, setAddr))
2101         {
2102             OIC_LOG(DEBUG, TAG, "the device is already set");
2103             oc_mutex_unlock(g_gattObjectMutex);
2104             return tPeripheral;
2105         }
2106     }
2107
2108     oc_mutex_unlock(g_gattObjectMutex);
2109     OIC_LOG(DEBUG, TAG, "There are no the gatt object in list");
2110     return NULL;
2111 }
2112
2113 CAResult_t CALEClientRemoveAllGattObjs()
2114 {
2115     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllGattObjs");
2116
2117     oc_mutex_lock(g_gattObjectMutex);
2118     if (!g_gattObjectList)
2119     {
2120         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2121         oc_mutex_unlock(g_gattObjectMutex);
2122         return CA_STATUS_OK;
2123     }
2124
2125     uint32_t length = u_arraylist_length(g_gattObjectList);
2126     for (uint32_t index = 0; index < length; index++)
2127     {
2128         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_gattObjectList, index);
2129         if (!tPeripheral)
2130         {
2131             OIC_LOG(ERROR, TAG, "tPeripheral is null");
2132             continue;
2133         }else{
2134             if (NULL == u_arraylist_remove(g_gattObjectList, index))
2135             {
2136                 OIC_LOG(ERROR, TAG, "List removal failed.");
2137                 oc_mutex_unlock(g_gattObjectMutex);
2138                 return CA_STATUS_FAILED;
2139             }
2140         }
2141     }
2142
2143     OICFree(g_gattObjectList);
2144     g_gattObjectList = NULL;
2145     OIC_LOG(INFO, TAG, "g_gattObjectList is removed");
2146     oc_mutex_unlock(g_gattObjectMutex);
2147     return CA_STATUS_OK;
2148 }
2149
2150 CAResult_t CALEClientRemoveGattObj(CBPeripheral *peripheral)
2151 {
2152     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObj");
2153
2154     oc_mutex_lock(g_gattObjectMutex);
2155     if (!g_gattObjectList)
2156     {
2157         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2158         oc_mutex_unlock(g_gattObjectMutex);
2159         return CA_STATUS_OK;
2160     }
2161
2162     uint32_t length = u_arraylist_length(g_gattObjectList);
2163     for (uint32_t index = 0; index < length; index++)
2164     {
2165         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_gattObjectList, index);
2166         if ([peripheral isEqual:tPeripheral]){
2167             if (NULL == u_arraylist_remove(g_gattObjectList, index))
2168             {
2169                 OIC_LOG(ERROR, TAG, "List removal failed.");
2170                 oc_mutex_unlock(g_gattObjectMutex);
2171                 return CA_STATUS_FAILED;
2172             }
2173         }
2174     }
2175
2176     oc_mutex_unlock(g_gattObjectMutex);
2177     OIC_LOG(DEBUG, TAG, "there are no target object");
2178     return CA_STATUS_OK;
2179 }
2180
2181 CAResult_t CALEClientRemoveGattObjForAddr(const char* remoteAddr)
2182 {
2183     OIC_LOG(DEBUG, TAG, "CALEClientRemoveGattObjForAddr");
2184     VERIFY_NON_NULL(remoteAddr, TAG, "addr is null");
2185
2186     oc_mutex_lock(g_gattObjectMutex);
2187     if (!g_gattObjectList)
2188     {
2189         OIC_LOG(DEBUG, TAG, "already removed for g_gattObjectList");
2190         oc_mutex_unlock(g_gattObjectMutex);
2191         return CA_STATUS_OK;
2192     }
2193
2194     uint32_t length = u_arraylist_length(g_gattObjectList);
2195     for (uint32_t index = 0; index < length; index++)
2196     {
2197         CBPeripheral *tPeripheral = (CBPeripheral *) u_arraylist_get(g_gattObjectList, index);
2198         if (!tPeripheral)
2199         {
2200             OIC_LOG(ERROR, TAG, "tPeripheral is null");
2201             oc_mutex_unlock(g_gattObjectMutex);
2202             return CA_STATUS_FAILED;
2203         }
2204
2205         NSString *setAddress = CALEClientGetAddressFromGattObj(tPeripheral);
2206         if (setAddress == nil || [setAddress isEqualToString:@"<null>"]
2207             || [setAddress isEqualToString:@"null"] || setAddress == (id)[NSNull null]
2208             || [[setAddress stringByTrimmingCharactersInSet:
2209                  [NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""]){
2210             OIC_LOG(ERROR, TAG, "setAddress is null");
2211             oc_mutex_unlock(g_gattObjectMutex);
2212             return CA_STATUS_FAILED;
2213         }
2214
2215         const char* setAddr = [setAddress UTF8String];
2216         if (!setAddr)
2217         {
2218             OIC_LOG(ERROR, TAG, "setAddress is null");
2219             oc_mutex_unlock(g_gattObjectMutex);
2220             return CA_STATUS_FAILED;
2221         }
2222
2223         if (!strcmp(setAddr, remoteAddr))
2224         {
2225             OIC_LOG_V(DEBUG, TAG, "remove object : %s", remoteAddr);
2226             if (NULL == u_arraylist_remove(g_gattObjectList, index))
2227             {
2228                 OIC_LOG(ERROR, TAG, "List removal failed.");
2229                 oc_mutex_unlock(g_gattObjectMutex);
2230                 return CA_STATUS_FAILED;
2231             }
2232             oc_mutex_unlock(g_gattObjectMutex);
2233             return CA_STATUS_OK;
2234         }
2235     }
2236
2237     oc_mutex_unlock(g_gattObjectMutex);
2238     OIC_LOG(DEBUG, TAG, "there are no target object");
2239     return CA_STATUS_FAILED;
2240 }
2241
2242 /**
2243  * BT State List
2244  */
2245
2246 CAResult_t CALEClientUpdateDeviceState(const char* address,
2247                                        uint32_t connectedState,
2248                                        uint16_t notificationState,
2249                                        uint16_t sendState)
2250 {
2251     VERIFY_NON_NULL(address, TAG, "address is null");
2252
2253     CALEState_t *newstate = (CALEState_t*) OICCalloc(1, sizeof(*newstate));
2254     if (!newstate)
2255     {
2256         OIC_LOG(ERROR, TAG, "out of memory");
2257         return CA_MEMORY_ALLOC_FAILED;
2258     }
2259
2260     if (strlen(address) > CA_MACADDR_SIZE)
2261     {
2262         OIC_LOG(ERROR, TAG, "address is not proper");
2263         OICFree(newstate);
2264         return CA_STATUS_FAILED;
2265     }
2266
2267     OICStrcpy(newstate->address, sizeof(newstate->address), address);
2268     newstate->connectedState = connectedState;
2269     newstate->notificationState = notificationState;
2270     newstate->sendState = sendState;
2271     return CALEClientAddDeviceStateToList(newstate);
2272 }
2273
2274 CAResult_t CALEClientAddDeviceStateToList(CALEState_t* state)
2275 {
2276     VERIFY_NON_NULL(state, TAG, "state is null");
2277
2278     oc_mutex_lock(g_deviceStateListMutex);
2279
2280     if (!g_deviceStateList)
2281     {
2282         OIC_LOG(ERROR, TAG, "gdevice_list is null");
2283         oc_mutex_unlock(g_deviceStateListMutex);
2284         return CA_STATUS_FAILED;
2285     }
2286
2287     if (CALEClientIsDeviceInList(state->address))
2288     {
2289         CALEState_t* curState = CALEClientGetStateInfo(state->address);
2290         if(!curState)
2291         {
2292             OIC_LOG(ERROR, TAG, "curState is null");
2293             oc_mutex_unlock(g_deviceStateListMutex);
2294             return CA_STATUS_FAILED;
2295         }
2296
2297         if (STATE_CHARACTER_NO_CHANGE == state->notificationState)
2298         {
2299             state->notificationState = curState->notificationState;
2300         }
2301         state->autoConnectFlag = curState->autoConnectFlag;
2302
2303         // delete previous state for update new state
2304         CAResult_t res = CALEClientRemoveDeviceState(state->address);
2305         if (CA_STATUS_OK != res)
2306         {
2307             OIC_LOG(ERROR, TAG, "CALEClientRemoveDeviceState has failed");
2308             oc_mutex_unlock(g_deviceStateListMutex);
2309             return res;
2310         }
2311     }
2312     u_arraylist_add(g_deviceStateList, state); // update new state
2313     OIC_LOG_V(INFO, TAG, "Set State Info to List : %d, %d, %s, %d",
2314               state->connectedState, state->notificationState,
2315               state->address, state->autoConnectFlag);
2316
2317     oc_mutex_unlock(g_deviceStateListMutex);
2318     return CA_STATUS_OK;
2319 }
2320
2321 bool CALEClientIsDeviceInList(const char* remoteAddress)
2322 {
2323     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2324
2325     if (!g_deviceStateList)
2326     {
2327         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2328         return false;
2329     }
2330
2331     uint32_t length = u_arraylist_length(g_deviceStateList);
2332     for (uint32_t index = 0; index < length; index++)
2333     {
2334         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2335         if (!state)
2336         {
2337             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2338             return false;
2339         }
2340
2341         if (!strcmp(remoteAddress, state->address))
2342         {
2343             OIC_LOG(DEBUG, TAG, "the device is already set");
2344             return true;
2345         }
2346     }
2347
2348     OIC_LOG(DEBUG, TAG, "there are no the device in list.");
2349     return false;
2350 }
2351
2352 CAResult_t CALEClientRemoveAllDeviceState()
2353 {
2354     OIC_LOG(DEBUG, TAG, "CALEClientRemoveAllDeviceState");
2355
2356     oc_mutex_lock(g_deviceStateListMutex);
2357     if (!g_deviceStateList)
2358     {
2359         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2360         oc_mutex_unlock(g_deviceStateListMutex);
2361         return CA_STATUS_FAILED;
2362     }
2363
2364     uint32_t length = u_arraylist_length(g_deviceStateList);
2365     for (uint32_t index = 0; index < length; index++)
2366     {
2367         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2368         if (!state)
2369         {
2370             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2371             continue;
2372         }else{
2373             u_arraylist_remove(g_deviceStateList, index);
2374         }
2375         OICFree(state);
2376     }
2377
2378     OICFree(g_deviceStateList);
2379     g_deviceStateList = NULL;
2380     oc_mutex_unlock(g_deviceStateListMutex);
2381
2382     return CA_STATUS_OK;
2383 }
2384
2385 CAResult_t CALEClientResetDeviceStateForAll()
2386 {
2387     OIC_LOG(DEBUG, TAG, "CALEClientResetDeviceStateForAll");
2388
2389     oc_mutex_lock(g_deviceStateListMutex);
2390     if (!g_deviceStateList)
2391     {
2392         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2393         oc_mutex_unlock(g_deviceStateListMutex);
2394         return CA_STATUS_FAILED;
2395     }
2396
2397     size_t length = u_arraylist_length(g_deviceStateList);
2398     for (size_t index = 0; index < length; index++)
2399     {
2400         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2401         if (!state)
2402         {
2403             OIC_LOG(ERROR, TAG, "jarrayObj is null");
2404             continue;
2405         }
2406
2407         // autoConnectFlag value will be not changed,
2408         // since it has reset only termination case.
2409         state->connectedState = STATE_DISCONNECTED;
2410         state->notificationState = STATE_CHARACTER_UNSET;
2411         state->sendState = STATE_SEND_NONE;
2412     }
2413     oc_mutex_unlock(g_deviceStateListMutex);
2414
2415     return CA_STATUS_OK;
2416 }
2417
2418 CAResult_t CALEClientRemoveDeviceState(const char* remoteAddress)
2419 {
2420     OIC_LOG(DEBUG, TAG, "CALEClientRemoveDeviceState");
2421     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
2422
2423     if (!g_deviceStateList)
2424     {
2425         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2426         return CA_STATUS_FAILED;
2427     }
2428
2429     uint32_t length = u_arraylist_length(g_deviceStateList);
2430     for (uint32_t index = 0; index < length; index++)
2431     {
2432         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2433         if (!state)
2434         {
2435             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2436             continue;
2437         }
2438
2439         if (!strcmp(state->address, remoteAddress))
2440         {
2441             OIC_LOG_V(DEBUG, TAG, "remove state : %s", state->address);
2442
2443             CALEState_t* targetState  = (CALEState_t*)u_arraylist_remove(g_deviceStateList,
2444                                                                          index);
2445             if (NULL == targetState)
2446             {
2447                 OIC_LOG(ERROR, TAG, "List removal failed.");
2448                 return CA_STATUS_FAILED;
2449             }
2450
2451             OICFree(targetState);
2452             return CA_STATUS_OK;
2453         }
2454     }
2455
2456     return CA_STATUS_OK;
2457 }
2458
2459 CALEState_t* CALEClientGetStateInfo(const char* remoteAddress)
2460 {
2461     OIC_LOG(DEBUG, TAG, "CALEClientGetStateInfo");
2462     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", NULL);
2463
2464     if (!g_deviceStateList)
2465     {
2466         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2467         return NULL;
2468     }
2469
2470     uint32_t length = u_arraylist_length(g_deviceStateList);
2471     OIC_LOG_V(DEBUG, TAG, "CALEClientGetStateInfo : %d", length);
2472
2473     for (uint32_t index = 0; index < length; index++)
2474     {
2475         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2476         if (!state)
2477         {
2478             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2479             continue;
2480         }
2481
2482         OIC_LOG_V(DEBUG, TAG, "target address : %s", remoteAddress);
2483         OIC_LOG_V(DEBUG, TAG, "state address : %s", state->address);
2484
2485         if (!strcmp(state->address, remoteAddress))
2486         {
2487             OIC_LOG_V(DEBUG, TAG, "get state : %s", remoteAddress);
2488             return state;
2489         }
2490     }
2491     return NULL;
2492 }
2493
2494 bool CALEClientIsConnectedDevice(const char* remoteAddress)
2495 {
2496     OIC_LOG(DEBUG, TAG, "CALEClientIsConnectedDevice");
2497     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2498
2499     oc_mutex_lock(g_deviceStateListMutex);
2500     if (!g_deviceStateList)
2501     {
2502         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2503         oc_mutex_unlock(g_deviceStateListMutex);
2504         return false;
2505     }
2506
2507     uint32_t length = u_arraylist_length(g_deviceStateList);
2508     for (uint32_t index = 0; index < length; index++)
2509     {
2510         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2511         if (!state)
2512         {
2513             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2514             continue;
2515         }
2516
2517         if (!strcmp(state->address, remoteAddress))
2518         {
2519             OIC_LOG(DEBUG, TAG, "check whether it is connected or not");
2520
2521             if (STATE_CONNECTED == state->connectedState)
2522             {
2523                 oc_mutex_unlock(g_deviceStateListMutex);
2524                 return true;
2525             }
2526             else
2527             {
2528                 oc_mutex_unlock(g_deviceStateListMutex);
2529                 return false;
2530             }
2531         }
2532     }
2533     oc_mutex_unlock(g_deviceStateListMutex);
2534     return false;
2535 }
2536
2537 bool CALEClientIsSetCharacteristic(const char* remoteAddress)//, const char* serviceId)
2538 {
2539     OIC_LOG(DEBUG, TAG, "CALEClientIsSetCharacteristic");
2540     VERIFY_NON_NULL_RET(remoteAddress, TAG, "remoteAddress is null", false);
2541
2542     oc_mutex_lock(g_deviceStateListMutex);
2543     if (!g_deviceStateList)
2544     {
2545         OIC_LOG(ERROR, TAG, "g_deviceStateList is null");
2546         oc_mutex_unlock(g_deviceStateListMutex);
2547         return false;
2548     }
2549
2550     uint32_t length = u_arraylist_length(g_deviceStateList);
2551     for (uint32_t index = 0; index < length; index++)
2552     {
2553         CALEState_t* state = (CALEState_t*) u_arraylist_get(g_deviceStateList, index);
2554         if (!state)
2555         {
2556             OIC_LOG(ERROR, TAG, "CALEState_t object is null");
2557             continue;
2558         }
2559
2560         if (!strcmp(state->address, remoteAddress))
2561         {
2562             OIC_LOG_V(DEBUG, TAG, "check whether it was set or not:%d", state->notificationState);
2563
2564             if (STATE_CHARACTER_SET == state->notificationState)
2565             {
2566                 oc_mutex_unlock(g_deviceStateListMutex);
2567                 OIC_LOG(DEBUG, TAG, "state->notificationState was set");
2568                 return true;
2569             }
2570             else
2571             {
2572                 oc_mutex_unlock(g_deviceStateListMutex);
2573                 OIC_LOG(DEBUG, TAG, "state->notificationState was not set");
2574                 return false;
2575             }
2576         }
2577     }
2578
2579     oc_mutex_unlock(g_deviceStateListMutex);
2580     return false;
2581 }
2582
2583 void CALEClientCreateDeviceList()
2584 {
2585     OIC_LOG(DEBUG, TAG, "CALEClientCreateDeviceList");
2586
2587     // create new object array
2588     if (!g_gattObjectList)
2589     {
2590         OIC_LOG(DEBUG, TAG, "Create g_gattObjectList");
2591
2592         g_gattObjectList = u_arraylist_create();
2593     }
2594
2595     if (!g_deviceStateList)
2596     {
2597         OIC_LOG(DEBUG, TAG, "Create g_deviceStateList");
2598
2599         g_deviceStateList = u_arraylist_create();
2600     }
2601
2602     if (!g_deviceList)
2603     {
2604         OIC_LOG(DEBUG, TAG, "Create g_deviceList");
2605
2606         g_deviceList = u_arraylist_create();
2607     }
2608 }
2609
2610 /**
2611  * Check Sent Count for remove g_sendBuffer
2612  */
2613 void CALEClientUpdateSendCnt()
2614 {
2615     OIC_LOG(DEBUG, TAG, "CALEClientUpdateSendCnt");
2616
2617     // mutex lock
2618     oc_mutex_lock(g_threadMutex);
2619
2620     g_currentSentCnt++;
2621
2622     if (g_targetCnt <= g_currentSentCnt)
2623     {
2624         g_targetCnt = 0;
2625         g_currentSentCnt = 0;
2626
2627         //init g_sendbuffer
2628         if (g_sendBuffer != nil ){//|| g_sendBuffer != NULL || [g_sendBuffer length] > 0){
2629             //[g_sendBuffer release];
2630             g_sendBuffer = nil;
2631         }
2632
2633         // notity the thread
2634         oc_cond_signal(g_threadCond);
2635
2636         CALEClientSetSendFinishFlag(true);
2637
2638         OIC_LOG(DEBUG, TAG, "set signal for send data");
2639     }
2640     // mutex unlock
2641     oc_mutex_unlock(g_threadMutex);
2642 }
2643
2644 CAResult_t CALEClientInitGattMutexVaraibles()
2645 {
2646     if (NULL == g_bleReqRespClientCbMutex)
2647     {
2648         g_bleReqRespClientCbMutex = oc_mutex_new();
2649         if (NULL == g_bleReqRespClientCbMutex)
2650         {
2651             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2652             return CA_STATUS_FAILED;
2653         }
2654     }
2655
2656     if (NULL == g_bleServerBDAddressMutex)
2657     {
2658         g_bleServerBDAddressMutex = oc_mutex_new();
2659         if (NULL == g_bleServerBDAddressMutex)
2660         {
2661             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2662             return CA_STATUS_FAILED;
2663         }
2664     }
2665
2666     if (NULL == g_threadMutex)
2667     {
2668         g_threadMutex = oc_mutex_new();
2669         if (NULL == g_threadMutex)
2670         {
2671             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2672             return CA_STATUS_FAILED;
2673         }
2674     }
2675
2676     if (NULL == g_threadSendMutex)
2677     {
2678         g_threadSendMutex = oc_mutex_new();
2679         if (NULL == g_threadSendMutex)
2680         {
2681             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2682             return CA_STATUS_FAILED;
2683         }
2684     }
2685
2686     if (NULL == g_deviceListMutex)
2687     {
2688         g_deviceListMutex = oc_mutex_new();
2689         if (NULL == g_deviceListMutex)
2690         {
2691             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2692             return CA_STATUS_FAILED;
2693         }
2694     }
2695
2696     if (NULL == g_gattObjectMutex)
2697     {
2698         g_gattObjectMutex = oc_mutex_new();
2699         if (NULL == g_gattObjectMutex)
2700         {
2701             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2702             return CA_STATUS_FAILED;
2703         }
2704     }
2705
2706     if (NULL == g_deviceStateListMutex)
2707     {
2708         g_deviceStateListMutex = oc_mutex_new();
2709         if (NULL == g_deviceStateListMutex)
2710         {
2711             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2712             return CA_STATUS_FAILED;
2713         }
2714     }
2715
2716     if (NULL == g_SendFinishMutex)
2717     {
2718         g_SendFinishMutex = oc_mutex_new();
2719         if (NULL == g_SendFinishMutex)
2720         {
2721             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2722             return CA_STATUS_FAILED;
2723         }
2724     }
2725
2726     if (NULL == g_scanMutex)
2727     {
2728         g_scanMutex = oc_mutex_new();
2729         if (NULL == g_scanMutex)
2730         {
2731             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2732             return CA_STATUS_FAILED;
2733         }
2734     }
2735
2736     if (NULL == waitMutex){
2737         waitMutex = oc_mutex_new();
2738     }
2739
2740     if (NULL == g_threadWriteCharacteristicMutex)
2741     {
2742         g_threadWriteCharacteristicMutex = oc_mutex_new();
2743         if (NULL == g_threadWriteCharacteristicMutex)
2744         {
2745             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2746             return CA_STATUS_FAILED;
2747         }
2748     }
2749
2750     if (NULL == g_deviceScanRetryDelayMutex)
2751     {
2752         g_deviceScanRetryDelayMutex = oc_mutex_new();
2753         if (NULL == g_deviceScanRetryDelayMutex)
2754         {
2755             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2756             return CA_STATUS_FAILED;
2757         }
2758     }
2759
2760     if (NULL == g_initializeMutex)
2761     {
2762         g_initializeMutex = oc_mutex_new();
2763         if (NULL == g_initializeMutex)
2764         {
2765             OIC_LOG(ERROR, TAG, "oc_mutex_new has failed");
2766             return CA_STATUS_FAILED;
2767         }
2768     }
2769
2770     return CA_STATUS_OK;
2771 }
2772
2773 void CALEClientTerminateGattMutexVariables()
2774 {
2775     oc_mutex_free(g_bleReqRespClientCbMutex);
2776     g_bleReqRespClientCbMutex = NULL;
2777
2778     oc_mutex_free(g_bleServerBDAddressMutex);
2779     g_bleServerBDAddressMutex = NULL;
2780
2781     oc_mutex_free(g_threadMutex);
2782     g_threadMutex = NULL;
2783
2784     oc_mutex_free(g_threadSendMutex);
2785     g_threadSendMutex = NULL;
2786
2787     oc_mutex_free(g_deviceListMutex);
2788     g_deviceListMutex = NULL;
2789
2790     oc_mutex_free(g_SendFinishMutex);
2791     g_SendFinishMutex = NULL;
2792
2793     oc_mutex_free(g_scanMutex);
2794     g_scanMutex = NULL;
2795
2796     oc_mutex_free(waitMutex);
2797     waitMutex = NULL;
2798
2799     oc_mutex_free(g_threadWriteCharacteristicMutex);
2800     g_threadWriteCharacteristicMutex = NULL;
2801
2802     oc_mutex_free(g_deviceScanRetryDelayMutex);
2803     g_deviceScanRetryDelayMutex = NULL;
2804
2805     oc_mutex_free(g_initializeMutex);
2806     g_initializeMutex = NULL;
2807 }
2808
2809 void CALEClientSetSendFinishFlag(bool flag)
2810 {
2811     OIC_LOG_V(DEBUG, TAG, "g_isFinishedSendData is %d", flag);
2812
2813     oc_mutex_lock(g_SendFinishMutex);
2814     g_isFinishedSendData = flag;
2815     oc_mutex_unlock(g_SendFinishMutex);
2816 }
2817
2818 /**
2819  * adapter common
2820  */
2821
2822 CAResult_t CAStartLEGattClient()
2823 {
2824     // init mutex for send logic
2825     if (!g_deviceDescCond)
2826     {
2827         g_deviceDescCond = oc_cond_new();
2828     }
2829
2830     if (!g_threadCond)
2831     {
2832         g_threadCond = oc_cond_new();
2833     }
2834
2835     if (!g_threadWriteCharacteristicCond)
2836     {
2837         g_threadWriteCharacteristicCond = oc_cond_new();
2838     }
2839
2840     g_isStartedLEClient = true;
2841     return CA_STATUS_OK;
2842 }
2843
2844 void CAStopLEGattClient()
2845 {
2846     OIC_LOG(DEBUG, TAG, "CAStopBLEGattClient");
2847
2848     g_isStartedLEClient = false;
2849
2850     CAResult_t ret = CALEClientDisconnectAll();
2851     if (CA_STATUS_OK != ret)
2852     {
2853         OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
2854     }
2855
2856     ret = CALEClientStopScan();
2857     if(CA_STATUS_OK != ret)
2858     {
2859         OIC_LOG(ERROR, TAG, "CALEClientStopScan has failed");
2860     }
2861
2862     oc_mutex_lock(g_threadMutex);
2863     OIC_LOG(DEBUG, TAG, "signal - connection cond");
2864     oc_cond_signal(g_threadCond);
2865     CALEClientSetSendFinishFlag(true);
2866     oc_mutex_unlock(g_threadMutex);
2867
2868     oc_mutex_lock(g_threadWriteCharacteristicMutex);
2869     OIC_LOG(DEBUG, TAG, "signal - WriteCharacteristic cond");
2870     oc_cond_signal(g_threadWriteCharacteristicCond);
2871     oc_mutex_unlock(g_threadWriteCharacteristicMutex);
2872
2873     oc_mutex_lock(g_deviceScanRetryDelayMutex);
2874     OIC_LOG(DEBUG, TAG, "signal - delay cond");
2875     oc_cond_signal(g_deviceScanRetryDelayCond);
2876     oc_mutex_unlock(g_deviceScanRetryDelayMutex);
2877
2878     oc_cond_signal(g_deviceDescCond);   //change
2879
2880     oc_cond_free(g_deviceDescCond);
2881     oc_cond_free(g_threadCond);
2882     oc_cond_free(g_threadWriteCharacteristicCond);
2883     oc_cond_free(g_deviceScanRetryDelayCond);
2884
2885     g_deviceDescCond = NULL;
2886     g_threadCond = NULL;
2887     g_threadWriteCharacteristicCond = NULL;
2888     g_deviceScanRetryDelayCond = NULL;
2889 }
2890
2891 CAResult_t CAInitializeLEGattClient()
2892 {
2893     OIC_LOG(DEBUG, TAG, "Initialize GATT Client");
2894     CALEClientInitialize();
2895     return CA_STATUS_OK;
2896 }
2897
2898 void CATerminateLEGattClient()
2899 {
2900     OIC_LOG(DEBUG, TAG, "Terminate GATT Client");
2901     CAStopLEGattClient();
2902     CALEClientTerminate();
2903 }
2904
2905 CAResult_t CAUpdateCharacteristicsToGattServer(const char *remoteAddress,
2906                                                const uint8_t  *data,
2907                                                uint32_t dataLen,
2908                                                CALETransferType_t type,
2909                                                int32_t position)
2910 {
2911     OIC_LOG(DEBUG, TAG, "call CALEClientSendUnicastMessage");
2912     VERIFY_NON_NULL(data, TAG, "data is null");
2913     VERIFY_NON_NULL(remoteAddress, TAG, "remoteAddress is null");
2914
2915     if (LE_UNICAST != type || position < 0)
2916     {
2917         OIC_LOG(ERROR, TAG, "this request is not unicast");
2918         return CA_STATUS_INVALID_PARAM;
2919     }
2920
2921     return CALEClientSendUnicastMessage(remoteAddress, data, dataLen);
2922 }
2923
2924 CAResult_t CAUpdateCharacteristicsToAllGattServers(const uint8_t *data, uint32_t dataLen)
2925 {
2926     OIC_LOG(DEBUG, TAG, "call CALEClientSendMulticastMessage");
2927     VERIFY_NON_NULL(data, TAG, "data is null");
2928
2929     return CALEClientSendMulticastMessage(data, dataLen);
2930 }
2931
2932 void CASetLEReqRespClientCallback(CABLEDataReceivedCallback callback)
2933 {
2934     oc_mutex_lock(g_bleReqRespClientCbMutex);
2935     g_CABLEClientDataReceivedCallback = callback;
2936     oc_mutex_unlock(g_bleReqRespClientCbMutex);
2937 }
2938
2939 void CASetLEClientThreadPoolHandle(ca_thread_pool_t handle)
2940 {
2941     g_threadPoolHandle = handle;
2942 }
2943
2944 CAResult_t CAGetLEAddress(char **local_address){
2945     return CA_NOT_SUPPORTED;
2946 }
2947
2948 void CALEClientSetFlagBTAdapter(bool state){
2949     isEnableBtAdapter = state;
2950 }
2951
2952 bool CALEClientIsEnableBTAdapter(){
2953     return isEnableBtAdapter;
2954 }