./services/bt-service-agent-util.c
./services/hid/bt-service-hidhost.c
./services/socket/bt-service-socket.c
+./services/rfcomm/bt-service-rfcomm.c
)
IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
#include <glib.h>
#include <dlog.h>
#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
#include <cynara-client.h>
#include <cynara-creds-gdbus.h>
#include "bt-service-dpm.h"
#endif
#include "bt-service-hidhost.h"
+#include "bt-service-rfcomm.h"
/* For maintaining Application Sync API call requests */
GSList *invocation_list = NULL;
break;
}
#endif
+ case BT_RFCOMM_CLIENT_CONNECT: {
+ bluetooth_device_address_t address = { {0} };
+ char *input_string;
+ int connect_type;
+
+ __bt_service_get_parameters(in_param1,
+ &address, sizeof(bluetooth_device_address_t));
+ input_string = (char *)g_variant_get_data(in_param2);
+ __bt_service_get_parameters(in_param3, &connect_type, sizeof(int));
+
+ if (connect_type == BT_RFCOMM_UUID)
+ result = _bt_rfcomm_connect_using_uuid(&address, input_string);
+ else
+ result = _bt_rfcomm_connect_using_channel(&address, input_string);
+
+ if (result != BLUETOOTH_ERROR_NONE) {
+ bluetooth_rfcomm_connection_t conn_info;
+
+ BT_ERR("BT_RFCOMM_CLIENT_CONNECT failed, send error");
+ memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
+ if (connect_type == BT_RFCOMM_UUID)
+ g_strlcpy(conn_info.uuid, input_string, BLUETOOTH_UUID_STRING_MAX);
+ else
+ g_strlcpy(conn_info.uuid, "not_used", BLUETOOTH_UUID_STRING_MAX);
+
+ conn_info.device_role = RFCOMM_ROLE_CLIENT;
+ conn_info.socket_fd = -1;
+ g_array_append_vals(*out_param1, &conn_info,
+ sizeof(bluetooth_rfcomm_connection_t));
+ } else {
+ sender = (char*)g_dbus_method_invocation_get_sender(context);
+ _bt_save_invocation_context(context, result, sender, function_name, NULL);
+ }
+ break;
+ }
default:
BT_INFO("UnSupported function [%d]", function_name);
result = BLUETOOTH_ERROR_NOT_SUPPORT;
g_variant_new("(iv)", result, out_var));
BT_DBG("-");
}
+
+void _bt_service_method_return_with_unix_fd_list(GDBusMethodInvocation *invocation,
+ GArray *out_param, int result, GUnixFDList *fd_list)
+{
+ GVariant *out_var;
+ BT_DBG("+");
+ out_var = g_variant_new_from_data((const GVariantType *)"ay",
+ out_param->data, out_param->len, TRUE, NULL, NULL);
+
+ g_dbus_method_invocation_return_value_with_unix_fd_list(invocation,
+ g_variant_new("(iv)", result, out_var), fd_list);
+ BT_DBG("-");
+}
if (hid_cb)
hid_cb(event_type, event_data);
break;
+ case OAL_EVENT_SOCKET_OUTGOING_CONNECTED:
+ case OAL_EVENT_SOCKET_DISCONNECTED:
+ if (socket_cb)
+ socket_cb(event_type, event_data);
+ break;
default:
BT_ERR("Unhandled Event: %d", event_type);
break;
*/
#include <string.h>
+#include <stdio.h>
#include <glib.h>
#include <dlog.h>
#include <gio/gio.h>
uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
}
+
+void _bt_service_convert_uuid_string_to_type(unsigned char *uuid, const char *str)
+{
+ int i = 0;
+ const char *ptr = str;
+
+ ret_if(str == NULL);
+ ret_if(uuid == NULL);
+
+ BT_DBG("+");
+
+ memcpy(uuid, BT_SERVICE_BASE_UUID, BT_UUID_LENGTH_MAX);
+
+ while (*ptr && i < BT_UUID_LENGTH_MAX) {
+ if (*ptr == '-') {
+ ptr++;
+ continue;
+ }
+
+ if (sscanf(ptr, "%02hhx", &(uuid[i])) != 1)
+ break;
+
+ i++;
+ ptr += 2;
+ }
+
+ BT_DBG("-");
+}
void _bt_service_method_return(GDBusMethodInvocation *invocation,
GArray *out_param, int result);
+
+void _bt_service_method_return_with_unix_fd_list(GDBusMethodInvocation *invocation,
+ GArray *out_param, int result, GUnixFDList *fd_list);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __BT_SERVICE_RFCOMM_CLIENT_H__
+#define __BT_SERVICE_RFCOMM_CLIENT_H__
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _bt_rfcomm_connect_using_uuid(bluetooth_device_address_t *device_address, char *remote_uuid);
+int _bt_rfcomm_connect_using_channel(bluetooth_device_address_t *device_address, char *chan_str);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __BT_SERVICE_RFCOMM_CLIENT_H__ */
extern "C" {
#endif
+#define SOCK_TYPE_RFCOMM 0
+#define SOCK_TYPE_SCO 1
+#define SOCK_TYPE_L2CAP 2
+
+typedef void (*bt_socket_client_conn_cb) (int result, int sock_fd, char *address, char *uuid, int chan);
+
int _bt_socket_init(void);
void _bt_socket_deinit(void);
+int _bt_socket_client_connect(int sock_type, char *address,
+ char *remote_uuid, int channel, bt_socket_client_conn_cb cb);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#define BT_NODE_NAME_LEN 50
+#define BT_UUID_LENGTH_MAX 16
#define BT_UUID_STRING_SIZE 37
+
+static const char BT_SERVICE_BASE_UUID[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb
+};
+
typedef struct {
int req_id;
int service_function;
void _bt_clear_request_list(void);
void _bt_service_convert_uuid_type_to_string(char *str, const unsigned char *uuid);
+void _bt_service_convert_uuid_string_to_type(unsigned char *uuid, const char *str);
#ifdef __cplusplus
}
--- /dev/null
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Author: Atul Kumar Rai <a.rai@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+#include <dlog.h>
+#include <string.h>
+
+
+#include "bluetooth-api.h"
+#include "bt-internal-types.h"
+#include "bt-request-handler.h"
+#include "bt-service-util.h"
+#include "bt-service-event.h"
+#include "bt-service-common.h"
+#include "bt-service-rfcomm.h"
+#include "bt-service-socket.h"
+
+static void __bt_rfcomm_reply_pending_request(int result,
+ int service_function, void *user_data, unsigned int size)
+{
+ GSList *l;
+ GArray *out_param;
+ invocation_info_t *req_info;
+
+ /* Get method invocation context */
+ for (l = _bt_get_invocation_list(); l != NULL; l = g_slist_next(l)) {
+ req_info = l->data;
+ if (req_info == NULL || req_info->service_function != service_function)
+ continue;
+
+ /* Create out param */
+ out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
+
+ switch(service_function) {
+ case BT_RFCOMM_CLIENT_CONNECT: {
+ GUnixFDList *fd_list = NULL;
+ GError *error = NULL;
+
+ g_array_append_vals(out_param, user_data, size);
+
+ if (BLUETOOTH_ERROR_NONE == result) {
+ bluetooth_rfcomm_connection_t *ptr = user_data;
+
+ fd_list = g_unix_fd_list_new();
+ g_unix_fd_list_append(fd_list, ptr->socket_fd, &error);
+ g_assert_no_error (error);
+ }
+
+ _bt_service_method_return_with_unix_fd_list(
+ req_info->context, out_param, result, fd_list);
+
+ g_object_unref(fd_list);
+ break;
+ }
+ default:
+ BT_ERR("Unknown Service function");
+ }
+
+ g_array_free(out_param, TRUE);
+ _bt_free_info_from_invocation_list(req_info);
+ }
+
+ return;
+}
+
+static void __bt_rfcomm_socket_conn_cb(int result, int sock_fd, char *address, char *uuid, int chan)
+{
+ bluetooth_rfcomm_connection_t conn_info;
+
+ ret_if(NULL == address);
+ ret_if(NULL == uuid);
+
+ BT_DBG("+");
+
+ BT_INFO("result: %d, socket_fd: %d, address: %s, uuid: %s, chan: %d",
+ result, sock_fd, address, uuid, chan);
+
+ /* Fill RFCOMM connection structure and send reply to pending request */
+ memset(&conn_info, 0x00, sizeof(bluetooth_rfcomm_connection_t));
+ conn_info.socket_fd = sock_fd;
+ conn_info.device_role = RFCOMM_ROLE_CLIENT;
+ g_strlcpy(conn_info.uuid, uuid, BLUETOOTH_UUID_STRING_MAX);
+ _bt_convert_addr_string_to_type(conn_info.device_addr.addr, address);
+
+ __bt_rfcomm_reply_pending_request(
+ result, BT_RFCOMM_CLIENT_CONNECT,
+ (void *)&conn_info, sizeof(bluetooth_rfcomm_connection_t));
+
+ /* Send BLUETOOTH_EVENT_RFCOMM_CONNECTED event to application */
+ if (result == BLUETOOTH_ERROR_NONE) {
+ GVariant *param;
+
+ param = g_variant_new("(issn)", BLUETOOTH_ERROR_NONE,
+ address, conn_info.uuid, sock_fd);
+ _bt_send_event(BT_RFCOMM_CLIENT_EVENT,
+ BLUETOOTH_EVENT_RFCOMM_CONNECTED, param);
+ }
+
+ BT_DBG("-");
+}
+
+int _bt_rfcomm_connect_using_uuid(bluetooth_device_address_t *device_address, char *remote_uuid)
+{
+ int result;
+ char address[BT_ADDRESS_STRING_SIZE] = { 0 };
+
+ BT_DBG("+");
+
+ retv_if(NULL == device_address, BLUETOOTH_ERROR_INVALID_PARAM);
+ retv_if(NULL == remote_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
+
+ _bt_convert_addr_type_to_string(address, device_address->addr);
+ BT_INFO("RFCOMM connect called for [%s], uuid: [%s]", address, remote_uuid);
+
+ result = _bt_socket_client_connect(SOCK_TYPE_RFCOMM,
+ address, remote_uuid, -1, __bt_rfcomm_socket_conn_cb);
+ if (BLUETOOTH_ERROR_NONE != result) {
+ BT_ERR("_bt_socket_client_connect failed");
+ return result;
+ }
+
+ BT_DBG("-");
+ return BLUETOOTH_ERROR_NONE;
+}
+
+/* Range of the Channel : 0 <= channel <= 30 */
+int _bt_rfcomm_connect_using_channel(bluetooth_device_address_t *device_address, char *chan_str)
+{
+ int channel;
+ int result = BLUETOOTH_ERROR_NONE;
+ char address[BT_ADDRESS_STRING_SIZE] = { 0 };
+
+ BT_DBG("+");
+
+ retv_if(NULL == device_address, BLUETOOTH_ERROR_INVALID_PARAM);
+ retv_if(NULL == chan_str, BLUETOOTH_ERROR_INVALID_PARAM);
+
+ _bt_convert_addr_type_to_string(address, device_address->addr);
+ channel = atoi(chan_str);
+ BT_INFO("RFCOMM connect called for [%s], channel: %d", address, channel);
+
+ result = _bt_socket_client_connect(SOCK_TYPE_RFCOMM,
+ address, NULL, channel, __bt_rfcomm_socket_conn_cb);
+ if (BLUETOOTH_ERROR_NONE != result) {
+ BT_ERR("_bt_socket_client_connect failed");
+ return result;
+ }
+
+ BT_DBG("-");
+ return result;
+}
#include "bt-service-common.h"
#include "bt-service-util.h"
#include "bt-service-event-receiver.h"
+#include "bt-service-socket.h"
+
+typedef struct {
+ int sock_fd;
+ int chan;
+ char uuid[BT_UUID_STRING_SIZE];
+ char address[BT_ADDRESS_STRING_SIZE];
+ bt_socket_client_conn_cb conn_cb;
+} bt_socket_info_t;
+
+bt_socket_info_t *pending_conn_info;
+
+/* Function to handle socket disconnection */
+void __handle_socket_disconnected(event_socket_client_conn_t *client_info)
+{
+ char address[BT_ADDRESS_STR_LEN];
+
+ ret_if(NULL == client_info);
+
+ BT_DBG("+");
+
+ _bt_convert_addr_type_to_string(address, client_info->address.addr);
+
+ /*
+ * In case of an already connected socket, if disconnection happens, it will
+ * automatically detected in corresponding i/o handler and events will be sent
+ * from there. So here we only handle connection fail case.
+ */
+ if (NULL != pending_conn_info &&
+ !strncasecmp(address, pending_conn_info->address, strlen(address))) {
+ /*
+ * Disconnection event is received for ongoing connection, invoke connection
+ * state callback with error.
+ */
+ BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
+ client_info->fd, address,
+ pending_conn_info->uuid,
+ pending_conn_info->chan);
+
+ pending_conn_info->conn_cb(BLUETOOTH_ERROR_INTERNAL, client_info->fd, address,
+ pending_conn_info->uuid, pending_conn_info->chan);
+
+ g_free(pending_conn_info);
+ pending_conn_info = NULL;
+ } else {
+ BT_INFO("Disconnected Address: [%s], socket_fd: %d", address, client_info->fd);
+ }
+
+ BT_DBG("-");
+}
+
+/* Handle outgoing client socket connection event */
+static void __handle_outgoing_client_socket_connected(event_socket_client_conn_t *client_info)
+{
+ char address[BT_ADDRESS_STR_LEN];
+
+ ret_if(NULL == client_info);
+ ret_if(NULL == pending_conn_info);
+
+ BT_DBG("+");
+
+ /*
+ * Only one socket connect req at a time is allowed, so received address
+ * should match with pending request.
+ */
+ _bt_convert_addr_type_to_string(address, client_info->address.addr);
+ if (strncasecmp(address, pending_conn_info->address, strlen(address))) {
+ BT_ERR("Address mismatch, Pending connection address: [%s]",
+ pending_conn_info->address);
+ BT_ERR("Client connection callback called with address: [%s]", address);
+ return;
+ }
+
+ BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
+ client_info->fd, address,
+ pending_conn_info->uuid,
+ pending_conn_info->chan);
+
+ pending_conn_info->conn_cb(BLUETOOTH_ERROR_NONE, client_info->fd, address,
+ pending_conn_info->uuid, pending_conn_info->chan);
+
+ g_free(pending_conn_info);
+ pending_conn_info = NULL;
+ BT_DBG("-");
+}
static void __bt_socket_event_handler(int event_type, gpointer event_data)
{
BT_INFO("OAL event = 0x%x, \n", event_type);
switch(event_type) {
+ case OAL_EVENT_SOCKET_OUTGOING_CONNECTED: {
+ event_socket_client_conn_t *client_info = event_data;
+
+ __handle_outgoing_client_socket_connected(client_info);
+ break;
+ }
+ case OAL_EVENT_SOCKET_DISCONNECTED: {
+ event_socket_client_conn_t *client_info = event_data;
+
+ __handle_socket_disconnected(client_info);
+ break;
+ }
default:
BT_ERR("Invalid event:%d\n", event_type);
break;
}
}
+int _bt_socket_client_connect(int sock_type, char *address,
+ char *remote_uuid, int channel, bt_socket_client_conn_cb cb)
+{
+ int sock_fd = -1;
+ bt_address_t bd;
+ oal_uuid_t uuid;
+
+ retv_if(NULL == address, BLUETOOTH_ERROR_INVALID_PARAM);
+ retv_if(NULL != pending_conn_info, BLUETOOTH_ERROR_DEVICE_BUSY);
+
+ BT_DBG("+");
+
+
+ BT_INFO("sock_type: %d, address: %s, remote_uuid: %s, channel: %d",
+ sock_type, address, remote_uuid, channel);
+
+ _bt_convert_addr_string_to_type(bd.addr, address);
+ if (remote_uuid)
+ _bt_service_convert_uuid_string_to_type(uuid.uuid, remote_uuid);
+ else
+ memset(&uuid, 0x00, sizeof(oal_uuid_t));
+
+ switch (sock_type) {
+ case SOCK_TYPE_RFCOMM:
+ sock_fd = socket_connect(OAL_SOCK_RFCOMM, &uuid, channel, &bd);
+ break;
+ default:
+ BT_ERR("Socket type: %d not supported");
+ return BLUETOOTH_ERROR_NOT_SUPPORT;
+ }
+
+ if(0 > sock_fd) {
+ BT_ERR("Bluetooth socket connect failed");
+ return BLUETOOTH_ERROR_CONNECTION_ERROR;
+ }
+
+ pending_conn_info = g_malloc0(sizeof(bt_socket_info_t));
+ pending_conn_info->sock_fd = sock_fd;
+ pending_conn_info->chan = channel;
+ pending_conn_info->conn_cb = cb;
+ g_strlcpy(pending_conn_info->address, address, BT_ADDRESS_STRING_SIZE);
+ g_strlcpy(pending_conn_info->uuid, remote_uuid, BT_UUID_STRING_SIZE);
+
+ BT_DBG("-");
+ return BLUETOOTH_ERROR_NONE;
+}
+
int _bt_socket_init(void)
{
BT_INFO("Socket Init");