1 /* ****************************************************************
3 * Copyright 2017 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
22 #include "cautilinterface.h"
23 #include "camanagerleinterface.h"
24 #include "camanagerleutil.h"
25 #include "caleautoconnector.h"
27 #include "cacommonutil.h"
28 #include "camanagerdevice.h"
29 #include "caleclient.h"
30 #include "caleutils.h"
31 #include "uarraylist.h"
33 #define TAG "OIC_CA_MANAGER_LE"
35 static const int SUPPORT_ADNROID_API_LEVEL = 18;
36 static const int AUTH_FAIL = 5;
37 static const int LINK_LOSS = 8;
38 static const int ACCEPT_TIMEOUT_EXCEPTION = 16;
39 static const int REMOTE_DISCONNECT = 19;
40 static const int LOCAL_DISCONNECT = 22;
41 static const int CONNECTION_FAILED_TO_BE_EASTABLISHED = 62;
42 static const int USER_REMOVED_BOND = 68;
44 static dispatch_queue_t g_caManagerAutoConnectQueue = NULL;
45 static NSMutableDictionary *g_candidateACList = NULL;
47 static void CAManagerAdapterStateChangeCB(CBCentralManager *central);
48 static void CAManagerLeGattConnectionStateChangeCB(CBPeripheral *peripheral,
49 const char *remote_address, bool connected, NSError *error);
50 static void CAManagerLeGattServiceDiscoveredCB(CBPeripheral *peripheral, const char *remote_address,
54 CAResult_t CASetLEClientAutoConnectionDeviceInfo(const char* address)
56 OIC_LOG(DEBUG, TAG, "CASetClientAutoConnectionDeviceInfo");
57 VERIFY_NON_NULL(address, TAG, "address");
59 OIC_LOG_V(DEBUG, TAG, "set [%s] for Auto Connection", address);
61 if (!CAManagerCheckBTAddress(address))
63 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
64 return CA_STATUS_FAILED;
67 // if there is target address in SharedPreference. it will be reseted.
68 if (CAManagerIsConnectedDeviceAddress(address))
70 if (!CAManagerRemoveConnectedDeviceAddress(address))
72 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
76 OIC_LOG(INFO, TAG, "Preference - remove success");
80 // check candidate AC list
81 if (g_candidateACList[@(address)] != nil) {
82 OIC_LOG_V(DEBUG, TAG, "Candidate device : %s", address);
84 if(!CAManagerIsConnectedDeviceAddress(address))
86 // if BLE address is matched each other
87 // this address will be added into auto connection list.
88 OIC_LOG(INFO, TAG, "AC list - address will be added into ACData list");
89 CBPeripheral *peripheral = (CBPeripheral *)g_candidateACList[@(address)];
91 CAManagerAddACData(address);
93 if(!CAManagerSetValueConnectedDeviceAddress(peripheral, address))
95 OIC_LOG(ERROR, TAG, "AC list - address is un-registered");
96 return CA_STATUS_FAILED;
99 [g_candidateACList removeObjectForKey:@(address)];
101 CAManagerSetAutoConnectionFlag(address, false);
103 // next connection will be requested as true flag
104 // after first connection
105 CALEClientSetAutoConnectFlag(address, true);
111 // it will be added new target address.
112 if (!CAManagerAddConnectedDeviceAddress(address))
114 OIC_LOG(ERROR, TAG, "Preference - putting has failed");
118 OIC_LOG(INFO, TAG, "Preference - putting success");
125 CAResult_t CAUnsetLEClientAutoConnectionDeviceInfo(const char* address)
127 OIC_LOG(DEBUG, TAG, "CAUnsetClientAutoConnectionDeviceInfo");
128 VERIFY_NON_NULL(address, TAG, "address");
130 OIC_LOG_V(DEBUG, TAG, "unset [%s] for Auto Connection", address);
132 if (!CAManagerCheckBTAddress(address))
134 OIC_LOG(ERROR, TAG, "this address is not BT address string format");
135 return CA_STATUS_FAILED;
138 // if there is target address in SharedPreference. it would be removed
139 if (CAManagerIsConnectedDeviceAddress(address))
141 if (!CAManagerRemoveConnectedDeviceAddress(address))
143 OIC_LOG(ERROR, TAG, "Preference - remove has failed");
147 OIC_LOG(INFO, TAG, "Preference - remove success");
151 // remove target device for auto connection
152 CAResult_t ret = CAManagerRemoveData(address);
153 if (CA_STATUS_OK != ret)
155 OIC_LOG(ERROR, TAG, "CAManagerRemoveData has failed");
158 CALEClientSetAutoConnectFlag(address, false);
163 CAResult_t CAManagerLEClientInitialize()
165 OIC_LOG(DEBUG, TAG, "CAManagerClientInitialize");
167 CAManagerInitMutexVaraibles();
168 CAManagerInitLEAutoConnection();
170 CAManagerCreateACDataList();
172 g_candidateACList = [[NSMutableDictionary alloc] init];
174 if (!g_caManagerAutoConnectQueue) {
175 g_caManagerAutoConnectQueue = dispatch_queue_create("com.caManager.AucoConnect",
176 DISPATCH_QUEUE_SERIAL);
179 //callback register to caleclient
180 CALEClientSetCAManagerCallback(CAManagerAdapterStateChangeCB,
181 CAManagerLeGattConnectionStateChangeCB,
182 CAManagerLeGattServiceDiscoveredCB);
184 // get last connected device list
186 ret = CAManagerGetConnectedDeviceAddress();
189 // create new set<String> object
190 ret = CAManagerCreateSetString();
193 OIC_LOG(DEBUG, TAG, "created new SetString");
197 OIC_LOG(ERROR, TAG, "CAManagerCreateSetString has failed");
198 return CA_STATUS_FAILED;
203 OIC_LOG(DEBUG, TAG, "get previous Set<String> object");
209 CAResult_t CAManagerLEClientTerminate()
211 OIC_LOG(DEBUG, TAG, "CAManagerClientTerminate");
213 // stop gatt connection
214 CAResult_t res = CALEClientDisconnectAll();
215 if (CA_STATUS_OK != res)
217 OIC_LOG(ERROR, TAG, "CALEClientDisconnectAll has failed");
220 res = CAManagerRemoveAllData();
221 if (CA_STATUS_OK != res)
223 OIC_LOG(ERROR, TAG, "CAManagerRemoveAllData has failed");
226 CAManagerTerminateLEAutoConnection();
227 CAManagerTerminateMutexVariables();
229 if (g_candidateACList)
231 [g_candidateACList removeAllObjects];
232 [g_candidateACList release];
233 g_candidateACList = nil;
236 res = CAManagerTerminateSetString();
237 if (CA_STATUS_OK != res)
239 OIC_LOG(ERROR, TAG, "CAManagerTerminateSetString has failed");
249 static void CAManagerAdapterStateChangeCB(CBCentralManager *central)
251 switch(central.state){
252 case CBCentralManagerStatePoweredOn:
254 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_on");
256 // when BT state is on. recovery flag has to be reset.
257 CAManagerSetBTRecovery(false);
259 // find target device for autoconnect
260 size_t length = CAManagerGetACDataLength();
261 OIC_LOG_V(DEBUG, TAG, "target device : %d", length);
262 for (size_t idx = 0; idx < length; idx++)
264 char *leAddress = CAManagerGetLEAddressFromACData(idx);
267 dispatch_async(g_caManagerAutoConnectQueue, ^{
268 CAResult_t res = CAManagerStartAutoConnection(leAddress);
269 if (CA_STATUS_OK != res)
271 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
279 case CBCentralManagerStatePoweredOff:
281 OIC_LOG(DEBUG, TAG, "AdapterStateChangedCallback : state_off");
283 // reset autoconnect flag for all target devices
284 size_t length = CAManagerGetACDataLength();
285 for (size_t idx = 0; idx < length; idx++)
287 char *address = CAManagerGetLEAddressFromACData(idx);
290 CAManagerSetAutoConnectionFlag(address, false);
291 CAManagerSignalToRetryCond(address); //cancel if auto connecting is processing
295 // check whether BT recovery is needed or not
296 if (CAManagerIsRecoveryFlagSet())
298 CAManagerProcessRecovery(STATE_OFF);
302 case CBCentralManagerStateUnsupported:
303 case CBCentralManagerStateUnauthorized:
304 case CBCentralManagerStateResetting:
310 static void CAManagerLeGattConnectionStateChangeCB(CBPeripheral *peripheral,
311 const char *remote_address, bool connected, NSError *error)
313 OIC_LOG_V(DEBUG, TAG, "peripheral : %s", [[peripheral name] UTF8String]);
314 OIC_LOG_V(DEBUG, TAG, "CAManagerLeGattConnectionStateChangeCB-remote_Address(%s),connected(%s)",
315 remote_address, connected ? "true":"false");
317 OIC_LOG_V(ERROR, TAG, "error : %s", [[error localizedDescription] UTF8String]);
320 VERIFY_NON_NULL_VOID(peripheral, TAG, "peripheral");
321 VERIFY_NON_NULL_VOID(remote_address, TAG, "remote_address");
325 OIC_LOG(DEBUG, TAG, "LE is connected");
328 OIC_LOG(DEBUG, TAG, "LE is disconnected");
330 if (!CAManagerIsMatchedACData(remote_address))
332 OIC_LOG_V(DEBUG, TAG, "this[%s] is not target address for Auto Connection",
337 CAManagerSetAutoConnectionFlag(remote_address, false);
339 dispatch_async(g_caManagerAutoConnectQueue, ^{
340 CAResult_t res = CAManagerStartAutoConnection(remote_address);
341 if (CA_STATUS_OK != res)
343 OIC_LOG(ERROR, TAG, "CAManagerStartAutoConnection has failed");
350 static void CAManagerLeGattServiceDiscoveredCB(CBPeripheral *peripheral,
351 const char *remote_address, NSError *error)
353 OIC_LOG(DEBUG, TAG, "CAManagerLeGattServiceDiscoveredCB");
356 OIC_LOG(ERROR, TAG, "error - CAManagerLeGattServiceDiscoveredCB");
360 VERIFY_NON_NULL_VOID(peripheral, TAG, "peripheral");
361 VERIFY_NON_NULL_VOID(remote_address, TAG, "remote_address");
363 OIC_LOG_V(DEBUG, TAG, "ServicesDiscovered device : %s", remote_address);
365 if (CAManagerIsConnectedDeviceAddress(remote_address))
367 // if BLE address is matched each other
368 // this address will be added into auto connection list.
369 OIC_LOG(INFO, TAG, "AC list - address will be added into ACData list");
370 CAManagerAddACData(remote_address);
372 if(!CAManagerSetValueConnectedDeviceAddress(peripheral, remote_address))
374 OIC_LOG(ERROR, TAG, "AC list - address is un-registered");
378 CAManagerSetAutoConnectionFlag(remote_address, false);
380 // next connection will be requested as true flag
381 // after first connection
382 CALEClientSetAutoConnectFlag(remote_address, true);
386 OIC_LOG(INFO, TAG, "AC list - device is not matched");
388 //store candidate AC peripheral
389 g_candidateACList[@(remote_address)] = peripheral;
392 CAManagerSignalToRetryCond(remote_address);
394 OIC_LOG(INFO, TAG, "ServicesDiscovery is successful");
397 void CAManagerLEStopScan()
399 OIC_LOG(DEBUG, TAG, "CAManagerLEStopScan");
400 CALEClientStopScan();
403 void CAManagerLEStartScan()
405 OIC_LOG(DEBUG, TAG, "CAManagerLEStartScan");
406 CALEClientStartScan();
409 void CAManagerLEDisconnect()
411 OIC_LOG(DEBUG, TAG, "CAManagerLEDisconnect");
412 CALEClientDisconnectAll();