#include <string.h>
#include <bluetooth.h>
+#include <bluetooth_internal.h>
#include "caedrinterface.h"
#include "camutex.h"
#include "cacommon.h"
#include "caedrdevicelist.h"
+#define MICROSECS_PER_SEC 1000000
+
+/**
+ * Maximum CoAP over TCP header length
+ * to know the total data length.
+ */
+#define EDR_MAX_HEADER_LEN 6
+
/**
- * @var g_edrDeviceListMutex
- * @brief Mutex to synchronize the access to Bluetooth device information list.
+ * Mutex to synchronize the access to Bluetooth device information list.
*/
static ca_mutex g_edrDeviceListMutex = NULL;
/**
- * @var g_edrDeviceList
- * @brief Peer Bluetooth device information list.
+ * Peer Bluetooth device information list.
*/
static EDRDeviceList *g_edrDeviceList = NULL;
/**
- * @var gEDRNetworkChangeCallback
- * @brief Maintains the callback to be notified when data received from remote Bluetooth device
+ * Maintains the callback to be notified when data received from remote
+ * Bluetooth device.
*/
static CAEDRDataReceivedCallback g_edrPacketReceivedCallback = NULL;
/**
- * @var g_edrErrorHandler
- * @brief Error callback to update error in EDR
+ * Error callback to update error in EDR.
*/
static CAEDRErrorHandleCallback g_edrErrorHandler = NULL;
+
/**
- * @fn CAEDRManagerInitializeMutex
- * @brief This function creates mutex.
+ * Pending multicast data list to be sent.
*/
-static void CAEDRManagerInitializeMutex(void);
+static u_arraylist_t *g_multicastDataList = NULL;
/**
- * @fn CAEDRManagerTerminateMutex
- * @brief This function frees mutex.
+ * Mutex to synchronize the access to Pending multicast data list.
*/
-static void CAEDRManagerTerminateMutex(void);
+static ca_mutex g_multicastDataListMutex = NULL;
/**
- * @fn CAEDRDataRecvCallback
- * @brief This callback is registered to recieve data on any open RFCOMM connection.
+ * To Store Adapter Mode information
*/
-static void CAEDRDataRecvCallback(bt_socket_received_data_s *data, void *userData);
+static bool g_isDiscoveryServer = false;
/**
- * @brief This function starts device discovery.
- * @return NONE
+ * This function creates mutex.
*/
-static CAResult_t CAEDRStartDeviceDiscovery(void);
+static CAResult_t CAEDRManagerInitializeMutex(void);
/**
- * @fn CAEDRStopServiceSearch
- * @brief This function stops any ongoing service sevice search.
+ * This function frees mutex.
+ */
+static void CAEDRManagerTerminateMutex(void);
+
+/**
+ * This callback is registered to recieve data on any open RFCOMM connection.
+ */
+static void CAEDRDataRecvCallback(bt_socket_received_data_s *data, void *userData);
+
+/**
+ * This function stops any ongoing service sevice search.
*/
static CAResult_t CAEDRStopServiceSearch(void);
/**
- * @fn CAEDRStopDeviceDiscovery
- * @brief This function stops device discovery.
+ * This function stops device discovery.
*/
static CAResult_t CAEDRStopDeviceDiscovery(void);
/**
- * @fn CAEDRStartServiceSearch
- * @brief This function searches for OIC service for remote Bluetooth device.
+ * This function searches for OIC service for remote Bluetooth device.
*/
static CAResult_t CAEDRStartServiceSearch(const char *remoteAddress);
/**
- * @fn CAEDRDeviceDiscoveryCallback
- * @brief This callback is registered to recieve all bluetooth nearby devices when device
- * scan is initiated.
+ * This callback is registered to recieve all bluetooth nearby devices
+ * when device scan is initiated.
*/
static void CAEDRDeviceDiscoveryCallback(int result,
bt_adapter_device_discovery_state_e state,
void *userData);
/**
- * @fn CAEDRServiceSearchedCallback
- * @brief This callback is registered to recieve all the services remote bluetooth device supports
- * when service search initiated.
+ * This callback is registered to recieve all the services remote
+ * bluetooth device supports when service search initiated.
*/
static void CAEDRServiceSearchedCallback(int result, bt_device_sdp_info_s *sdpInfo,
void *userData);
/**
- * @fn CAEDRSocketConnectionStateCallback
- * @brief This callback is registered to receive bluetooth RFCOMM connection state changes.
+ * This callback is registered to receive bluetooth RFCOMM connection
+ * state changes.
*/
static void CAEDRSocketConnectionStateCallback(int result,
bt_socket_connection_state_e state,
bt_socket_connection_s *connection, void *userData);
/**
- * @fn CAEDRClientConnect
- * @brief Establishes RFCOMM connection with remote bluetooth device
+ * Establishes RFCOMM connection with remote bluetooth device.
*/
static CAResult_t CAEDRClientConnect(const char *remoteAddress, const char *serviceUUID);
/**
- * @fn CAEDRClientDisconnect
- * @brief Disconnect RFCOMM client socket connection
+ * Disconnect RFCOMM client socket connection.
*/
static CAResult_t CAEDRClientDisconnect(const int32_t clientID);
device->socketFD = connection->socket_fd;
while (device->pendingDataList)
{
- uint32_t sentData = 0;
EDRData *edrData = device->pendingDataList->data;
res = CAEDRSendData(device->socketFD, edrData->data,
- edrData->dataLength, &sentData);
+ edrData->dataLength);
if (CA_STATUS_OK != res)
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to send pending data [%s]",
case BT_ADAPTER_DEVICE_DISCOVERY_FINISHED:
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Discovery finished!");
+ ca_mutex_lock(g_multicastDataListMutex);
+ u_arraylist_destroy(g_multicastDataList);
+ g_multicastDataList = NULL;
+ ca_mutex_unlock(g_multicastDataListMutex);
}
break;
ca_mutex_unlock(g_edrDeviceListMutex);
return;
}
+
+ int lengthData = u_arraylist_length(g_multicastDataList);
+ for(int len = 0; len < lengthData; len++)
+ {
+ // Adding to pending list
+ EDRData *multicastData =
+ (EDRData *)u_arraylist_get(g_multicastDataList, len);
+ if (NULL == multicastData)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "multicastData is NULL");
+ continue;
+ }
+ result = CAAddEDRDataToList(&device->pendingDataList, multicastData->data,
+ multicastData->dataLength);
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, EDR_ADAPTER_TAG,
+ "Failed to add data to pending list[%d]", result);
+ continue;
+ }
+ }
+ if (lengthData)
+ {
+ result = CAEDRClientConnect(device->remoteAddress, device->serviceUUID);
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG_V(ERROR, EDR_ADAPTER_TAG,
+ "Failed to make RFCOMM connection[%d]", result);
+
+ //Remove the data which added to pending list
+ CARemoveEDRDataFromList(&device->pendingDataList);
+ }
+ }
device->serviceSearched = true;
ca_mutex_unlock(g_edrDeviceListMutex);
}
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
-
bool isDiscoveryStarted = false;
// Check the device discovery state
}
}
+ g_isDiscoveryServer = true;
+
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
bt_socket_set_connection_state_changed_cb(CAEDRSocketConnectionStateCallback, NULL);
bt_socket_set_data_received_cb(CAEDRDataRecvCallback, NULL);
- // Start device discovery
- CAResult_t result = CAEDRStartDeviceDiscovery();
- if(CA_STATUS_OK != result)
- {
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Failed to Start Device discovery");
- return CA_STATUS_FAILED;
- }
-
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
-void CAEDRManagerInitializeMutex(void)
+CAResult_t CAEDRManagerInitializeMutex(void)
{
+ CAResult_t result = CA_STATUS_OK;
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
if (!g_edrDeviceListMutex)
g_edrDeviceListMutex = ca_mutex_new();
}
+ if (!g_multicastDataListMutex)
+ {
+ g_multicastDataListMutex = ca_mutex_new();
+ }
+
+ if (!g_edrDeviceListMutex || !g_multicastDataListMutex)
+ {
+ result = CA_STATUS_NOT_INITIALIZED;
+ }
+
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
+
+ return result;
}
void CAEDRManagerTerminateMutex(void)
g_edrDeviceListMutex = NULL;
}
+ if (g_multicastDataListMutex)
+ {
+ ca_mutex_free(g_multicastDataListMutex);
+ g_multicastDataListMutex = NULL;
+ }
+
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
-void CAEDRInitializeClient(ca_thread_pool_t handle)
+CAResult_t CAEDRClientInitialize()
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
- CAEDRManagerInitializeMutex();
+ CAResult_t result = CAEDRManagerInitializeMutex();
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
+ return result;
}
void CAEDRClientTerminate()
ca_mutex_unlock(g_edrDeviceListMutex);
}
+ if (g_multicastDataListMutex)
+ {
+ ca_mutex_lock(g_multicastDataListMutex);
+ u_arraylist_destroy(g_multicastDataList);
+ g_multicastDataList = NULL;
+ ca_mutex_unlock(g_multicastDataListMutex);
+ }
+
// Free the mutex
CAEDRManagerTerminateMutex();
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
}
-CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress, const char *serviceUUID,
- const void *data, uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendUnicastData(const char *remoteAddress,
+ const uint8_t *data,
+ uint32_t dataLength)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
// Input validation
VERIFY_NON_NULL(remoteAddress, EDR_ADAPTER_TAG, "Remote address is null");
- VERIFY_NON_NULL(serviceUUID, EDR_ADAPTER_TAG, "service UUID is null");
VERIFY_NON_NULL(data, EDR_ADAPTER_TAG, "Data is null");
- VERIFY_NON_NULL(sentLength, EDR_ADAPTER_TAG, "Sent data length holder is null");
if (0 >= dataLength)
{
// Make a rfcomm connection with remote BT Device
if (device->serviceSearched &&
- CA_STATUS_OK != CAEDRClientConnect(remoteAddress, serviceUUID))
+ CA_STATUS_OK != CAEDRClientConnect(remoteAddress, OIC_EDR_SERVICE_ID))
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to make RFCOMM connection!");
CARemoveEDRDeviceFromList(&g_edrDeviceList, remoteAddress);
return CA_STATUS_FAILED;
}
- *sentLength = dataLength;
}
else
{
- result = CAEDRSendData(device->socketFD, data, dataLength, sentLength);
+ result = CAEDRSendData(device->socketFD, data, dataLength);
if (CA_STATUS_OK != result)
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Failed to send data!");
return CA_STATUS_OK;
}
-CAResult_t CAEDRClientSendMulticastData(const char *serviceUUID, const void *data,
- uint32_t dataLength, uint32_t *sentLength)
+CAResult_t CAEDRClientSendMulticastData(const uint8_t *data,
+ uint32_t dataLength)
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
// Input validation
- VERIFY_NON_NULL(serviceUUID, EDR_ADAPTER_TAG, "service UUID is null");
VERIFY_NON_NULL(data, EDR_ADAPTER_TAG, "Data is null");
- VERIFY_NON_NULL(sentLength, EDR_ADAPTER_TAG, "Sent data length holder is null");
if (0 >= dataLength)
{
return CA_STATUS_INVALID_PARAM;
}
- *sentLength = dataLength;
-
// Send the packet to all OIC devices
ca_mutex_lock(g_edrDeviceListMutex);
+
EDRDeviceList *curList = g_edrDeviceList;
CAResult_t result = CA_STATUS_FAILED;
while (curList != NULL)
if (-1 == device->socketFD)
{
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN1");
// Check if the device service search is finished
if (false == device->serviceSearched)
{
CARemoveEDRDataFromList(&device->pendingDataList);
continue;
}
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN2");
}
else
{
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN3");
- result = CAEDRSendData(device->socketFD, data, dataLength, sentLength);
+ result = CAEDRSendData(device->socketFD, data, dataLength);
if (CA_STATUS_OK != result)
{
OIC_LOG_V(ERROR, EDR_ADAPTER_TAG, "Failed to send data to [%s] !",
device->remoteAddress);
}
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN4");
}
}
+
ca_mutex_unlock(g_edrDeviceListMutex);
+ if(g_isDiscoveryServer)
+ {
+ // Start the device Discovery.
+ result = CAEDRStartDeviceDiscovery();
+ if (CA_STATUS_OK == result)
+ {
+ OIC_LOG(INFO, EDR_ADAPTER_TAG, "Add the data to the multicast data list");
+
+ EDRData *multicastData = (EDRData *)OICCalloc(1, sizeof(EDRData));
+ if (NULL == multicastData)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Malloc failed");
+ goto exit;
+ }
+ multicastData->data = OICCalloc(1, dataLength);
+ if (NULL == multicastData->data)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Malloc failed");
+ goto exit;
+ }
+ memcpy(multicastData->data, data, dataLength);
+ multicastData->dataLength = dataLength;
+
+ // Add the data to pending multicast data list.
+ ca_mutex_lock(g_multicastDataListMutex);
+ if (NULL == g_multicastDataList)
+ {
+ g_multicastDataList = u_arraylist_create();
+ }
+ u_arraylist_add(g_multicastDataList, (void *)multicastData);
+ ca_mutex_unlock(g_multicastDataListMutex);
+ }
+ }
+
+exit:
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
return CA_STATUS_OK;
}
}
ca_mutex_unlock(g_edrDeviceListMutex);
+ //: TODO Need to check if 'check required for socket still connected or not'
if (!device)
{
OIC_LOG(ERROR, EDR_ADAPTER_TAG, "There is no device!");
return;
}
- uint32_t sentLength = 0;
+ CAConnectedDeviceInfo_t *deviceInfo =
+ (CAConnectedDeviceInfo_t *) CAEDRGetDeviceInfoFromAddress(device->remoteAddress);
- g_edrPacketReceivedCallback(device->remoteAddress, data->data,
- (uint32_t)data->data_size, &sentLength);
+ if (!deviceInfo)
+ {
+ OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Received Data from new device");
+ deviceInfo = (CAConnectedDeviceInfo_t *) OICCalloc(1, sizeof(*deviceInfo));
+ if (!deviceInfo)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Out of memory");
+ return;
+ }
- OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
-}
+ deviceInfo->state = STATE_CONNECTED;
+ deviceInfo->recvData = NULL;
+ deviceInfo->recvDataLen = 0;
+ deviceInfo->totalDataLen = 0;
+ result = CAEDRAddDeviceInfoToList(device->remoteAddress, deviceInfo);
+ if (CA_STATUS_OK != result)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "Could not add device info to list!");
+ OICFree(deviceInfo);
+ return;
+ }
+ }
+ if (!deviceInfo->recvData)
+ {
+ OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "Callocing deviceInfo->recvData");
+ deviceInfo->recvData = OICCalloc(data->data_size, sizeof(uint8_t));
+ if (!deviceInfo->recvData)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "out of memory");
+ return;
+ }
+ }
+
+ memcpy(deviceInfo->recvData + deviceInfo->recvDataLen, (const char*)data->data,
+ data->data_size);
+ deviceInfo->recvDataLen += data->data_size;
+
+ if (!deviceInfo->totalDataLen)
+ {
+ coap_transport_type transport = coap_get_tcp_header_type_from_initbyte(
+ ((unsigned char *)deviceInfo->recvData)[0] >> 4);
+ size_t headerLen = coap_get_tcp_header_length_for_transport(transport);
+
+ if (deviceInfo->recvDataLen >= headerLen)
+ {
+ // get actual data length from coap over tcp header
+ deviceInfo->totalDataLen = coap_get_total_message_length(deviceInfo->recvData,
+ deviceInfo->recvDataLen);
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG, "total data length [%d] bytes", deviceInfo->totalDataLen);
+
+ uint8_t *newBuf = OICRealloc(deviceInfo->recvData, deviceInfo->totalDataLen);
+ if (!newBuf)
+ {
+ OIC_LOG(ERROR, EDR_ADAPTER_TAG, "out of memory");
+ //Memory free
+ return;
+ }
+ deviceInfo->recvData = newBuf;
+ }
+ }
+
+ if (deviceInfo->totalDataLen == deviceInfo->recvDataLen)
+ {
+ if (g_edrPacketReceivedCallback)
+ {
+ OIC_LOG_V(DEBUG, EDR_ADAPTER_TAG,"data will be sent to callback routine: %s, %d",
+ deviceInfo->recvData, deviceInfo->recvDataLen);
+ uint32_t sentLength = 0;
+ g_edrPacketReceivedCallback(device->remoteAddress, (void*) deviceInfo->recvData,
+ deviceInfo->recvDataLen, &sentLength);
+
+ OICFree(deviceInfo->recvData);
+ deviceInfo->recvData = NULL;
+ deviceInfo->recvDataLen = 0;
+ deviceInfo->totalDataLen = 0;
+ }
+ }
+
+ OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "OUT");
+}