LE CoC: Add support for L2CAP_LE type socket in bt-service 53/271753/2
authorAyush Garg <ayush.garg@samsung.com>
Wed, 23 Feb 2022 10:58:48 +0000 (16:28 +0530)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 28 Feb 2022 05:18:01 +0000 (10:48 +0530)
This patch adds the following:
- Implement methods to connect and listen to SOCK_TYPE_L2CAP_LE
Socket.
- Implement methods to authorize(accept/reject) incoming L2CAP_LE
connection.

Change-Id: If47da01dc9a867d892ced3f847927213da9b66cf
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
bt-service/CMakeLists.txt
bt-service/services/bt-request-handler.c
bt-service/services/bt-service-event-sender.c
bt-service/services/device/bt-service-core-device.c
bt-service/services/include/bt-service-core-device.h
bt-service/services/include/bt-service-l2cap-le.h [new file with mode: 0644]
bt-service/services/include/bt-service-socket.h
bt-service/services/l2cap_le/bt-service-l2cap-le.c [new file with mode: 0644]
bt-service/services/socket/bt-service-socket.c
include/bluetooth-api.h
include/bt-internal-types.h

index 0c9c020..f5e6875 100644 (file)
@@ -41,6 +41,7 @@ SET(SRCS
 ./services/mesh/bt-service-mesh-config-client.c
 ./services/mesh/bt-service-mesh-model.c
 ./services/tds/bt-service-tds.c
+./services/l2cap_le/bt-service-l2cap-le.c
 )
 
 IF("$ENV{CFLAGS}" MATCHES "-DTIZEN_FEATURE_BT_OBEX")
index 3452c3c..458a314 100644 (file)
@@ -62,6 +62,8 @@
 
 #include "bt-service-battery-monitor.h"
 
+#include "bt-service-l2cap-le.h"
+
 #ifdef TIZEN_FEATURE_BT_PAN_NAP
 #include "bt-service-network.h"
 #endif
@@ -247,7 +249,9 @@ static gboolean __bt_is_sync_function(int service_function)
                        || service_function == BT_MESH_NETWORK_UPDATE_NETKEY
                        || service_function == BT_MESH_NETWORK_ADD_APPKEY
                        || service_function == BT_MESH_NETWORK_DELETE_APPKEY
-                       || service_function == BT_MESH_NETWORK_UPDATE_APPKEY)
+                       || service_function == BT_MESH_NETWORK_UPDATE_APPKEY
+                       || service_function == BT_L2CAP_LE_LISTEN_AND_ACCEPT
+                       || service_function == BT_L2CAP_LE_LISTEN)
                return TRUE;
        else
                return FALSE;
@@ -1544,14 +1548,14 @@ int __bt_bluez_request(int function_name,
                char *address;
 
                address = (char *)g_variant_get_data(in_param1);
-               result = _bt_rfcomm_reply_conn_authorization(address, TRUE);
+               result = _bt_socket_reply_conn_authorization(address, TRUE);
                break;
        }
        case BT_RFCOMM_REJECT_CONNECTION: {
                char *address;
 
                address = (char *)g_variant_get_data(in_param1);
-               result = _bt_rfcomm_reply_conn_authorization(address, FALSE);
+               result = _bt_socket_reply_conn_authorization(address, FALSE);
                break;
        }
        case BT_RFCOMM_REMOVE_SOCKET: {
@@ -4424,6 +4428,121 @@ normal:
                                requester_unique_creds, sender, &network, out_param1);
                break;
        }
+       case BT_L2CAP_LE_CLIENT_CONNECT: {
+               bluetooth_device_address_t address = { {0} };
+               int psm;
+
+               __bt_service_get_parameters(in_param1,
+                               &address, sizeof(bluetooth_device_address_t));
+
+               __bt_service_get_parameters(in_param2, &psm, sizeof(int));
+
+               result = _bt_l2cap_le_connect_using_psm(&address, psm);
+
+               if (result != BLUETOOTH_ERROR_NONE) {
+                       bluetooth_l2cap_le_connection_t conn_info;
+
+                       BT_ERR("BT_L2CAP_LE_CLIENT_CONNECT failed, send error errcode %d", result);
+                       memset(&conn_info, 0x00, sizeof(bluetooth_l2cap_le_connection_t));
+                       conn_info.device_role = L2CAP_LE_ROLE_CLIENT;
+                       conn_info.socket_fd = -1;
+                       conn_info.psm = psm;
+                       g_array_append_vals(*out_param1, &conn_info,
+                                       sizeof(bluetooth_l2cap_le_connection_t));
+               } else {
+                       bluetooth_l2cap_le_connection_t *conn_info;
+
+                       BT_INFO("BT_L2CAP_LE_CLIENT_CONNECT success, save context");
+                       sender = (char*)g_dbus_method_invocation_get_sender(context);
+                       conn_info = g_malloc0(sizeof(bluetooth_l2cap_le_connection_t));
+                       conn_info->socket_fd = -1;
+                       conn_info->device_role = L2CAP_LE_ROLE_CLIENT;
+                       conn_info->psm = psm;
+
+                       memcpy(&conn_info->device_addr, &address, sizeof(bluetooth_device_address_t));
+
+                       _bt_save_invocation_context(context, result, sender, function_name, (gpointer)conn_info);
+               }
+               break;
+       }
+       case BT_L2CAP_LE_SOCKET_DISCONNECT: {
+               /*
+                * Bluetooth L2CAP_LE socket disconnection will be done from bt-api, call to bt-service
+                * is only used for privilege check, so return BLUETOOTH_ERROR_NONE from here.
+                */
+               result = BLUETOOTH_ERROR_NONE;
+               break;
+       }
+       case BT_L2CAP_LE_SOCKET_WRITE: {
+               /*
+                * This call to bt-service is only used for privilege check, so return
+                * BLUETOOTH_ERROR_NONE from here.
+                */
+               result = BLUETOOTH_ERROR_NONE;
+               break;
+       }
+       case BT_L2CAP_LE_CREATE_SOCKET: {
+               /*
+                * This call to bt-service is only used for privilege check, so return
+                * BLUETOOTH_ERROR_NONE from here.
+                */
+               result = BLUETOOTH_ERROR_NONE;
+               break;
+       }
+       case BT_L2CAP_LE_LISTEN_AND_ACCEPT: {
+               int socket_fd = -1;
+               int psm;
+
+               __bt_service_get_parameters(in_param1, &psm, sizeof(int));
+
+               socket_fd = _bt_l2cap_le_socket_listen(psm, true);
+               if (socket_fd > 0) {
+                       result = BLUETOOTH_ERROR_NONE;
+                       _bt_save_invocation_context(context,
+                                       result, sender, function_name, NULL);
+               } else {
+                       g_array_append_vals(*out_param1, &socket_fd, sizeof(int));
+               }
+               break;
+       }
+       case BT_L2CAP_LE_LISTEN: {
+               int socket_fd = -1;
+               int psm;
+
+               __bt_service_get_parameters(in_param1, &psm, sizeof(int));
+
+               socket_fd = _bt_l2cap_le_socket_listen(psm, false);
+               if (socket_fd > 0) {
+                       result = BLUETOOTH_ERROR_NONE;
+                       _bt_save_invocation_context(context, result,
+                                       sender, function_name, NULL);
+               } else {
+                       g_array_append_vals(*out_param1, &socket_fd, sizeof(int));
+               }
+               break;
+       }
+       case BT_L2CAP_LE_ACCEPT_CONNECTION: {
+               char *address;
+
+               address = (char *)g_variant_get_data(in_param1);
+               result = _bt_socket_reply_conn_authorization(address, TRUE);
+               break;
+       }
+       case BT_L2CAP_LE_REJECT_CONNECTION: {
+               char *address;
+
+               address = (char *)g_variant_get_data(in_param1);
+               result = _bt_socket_reply_conn_authorization(address, FALSE);
+               break;
+       }
+       case BT_L2CAP_LE_REMOVE_SOCKET: {
+               /*
+                * This call to bt-service is only used for privilege check, so return
+                * BLUETOOTH_ERROR_NONE from here.
+                */
+               result = BLUETOOTH_ERROR_NONE;
+               break;
+       }
        default:
                BT_INFO("UnSupported function [%d]", function_name);
                result = BLUETOOTH_ERROR_NOT_SUPPORT;
@@ -5418,6 +5537,14 @@ gboolean __bt_service_check_privilege(int function_name,
 
        case BT_RFCOMM_LISTEN_AND_ACCEPT:
 
+       case BT_L2CAP_LE_CLIENT_CONNECT:
+       case BT_L2CAP_LE_CLIENT_CANCEL_CONNECT:
+       case BT_L2CAP_LE_SOCKET_DISCONNECT:
+       case BT_L2CAP_LE_SOCKET_WRITE:
+       case BT_L2CAP_LE_CREATE_SOCKET:
+       case BT_L2CAP_LE_REMOVE_SOCKET:
+       case BT_L2CAP_LE_LISTEN_AND_ACCEPT:
+
        ret_val = cynara_check(p_cynara, client_creds, client_session, user_creds,
                                                BT_PRIVILEGE_PUBLIC);
 
@@ -5570,6 +5697,10 @@ gboolean __bt_service_check_privilege(int function_name,
        case BT_MESH_MODEL_GET_PUBLICATION:
        case BT_MESH_NETWORK_GET_GROUPS:
 
+       case BT_L2CAP_LE_ACCEPT_CONNECTION:
+       case BT_L2CAP_LE_REJECT_CONNECTION:
+       case BT_L2CAP_LE_LISTEN:
+
        ret_val = cynara_check(p_cynara, client_creds, client_session, user_creds,
                                BT_PRIVILEGE_PLATFORM);
 
@@ -5621,6 +5752,8 @@ gboolean __bt_service_check_privilege(int function_name,
        case BT_OPP_GET_TRANSFER_PROGRESS:
        case BT_AVRCP_CONTROL_GET_PROPERTY:
        case BT_AVRCP_GET_TRACK_INFO:
+
+       case BT_L2CAP_LE_IS_PSM_AVAILABLE:
                /* Non-privilege control */
                break;
        default:
index 2b84f8f..d16b7b3 100644 (file)
@@ -132,6 +132,9 @@ int _bt_send_event(int event_type, int event, GVariant *param)
        case BT_MESH_EVENT:
                path = BT_MESH_PATH;
                break;
+       case BT_L2CAP_LE_SERVER_EVENT:
+               path = BT_L2CAP_LE_SERVER_PATH;
+               break;
        default:
                BT_ERR("Unknown event");
                return BLUETOOTH_ERROR_INTERNAL;
@@ -580,6 +583,9 @@ int _bt_send_event(int event_type, int event, GVariant *param)
        case BLUETOOTH_EVENT_MESH_JOIN_COMPLETED:
                signal = BT_MESH_JOIN_COMPLETED;
                break;
+       case BLUETOOTH_EVENT_L2CAP_LE_AUTHORIZE:
+               signal = BT_CONNECTION_AUTHORIZED;
+               break;
        default:
                BT_ERR("Unknown event");
                return BLUETOOTH_ERROR_INTERNAL;
index cfb454a..0280a10 100644 (file)
@@ -2099,7 +2099,7 @@ gboolean _bt_is_device_connected(bluetooth_device_address_t *device_address, int
        return is_connected;
 }
 
-int _bt_rfcomm_reply_conn_authorization(char *address, gboolean reply)
+int _bt_socket_reply_conn_authorization(char *address, gboolean reply)
 {
        bt_address_t bd_addr;
        int res;
index 7b07ce4..afdc084 100755 (executable)
@@ -85,7 +85,7 @@ int _bt_set_authorization(bluetooth_device_address_t *device_address,
 
 gboolean _bt_is_device_connected(bluetooth_device_address_t *device_address, int svc_type);
 
-int _bt_rfcomm_reply_conn_authorization(char *address, gboolean reply);
+int _bt_socket_reply_conn_authorization(char *address, gboolean reply);
 
 int _bt_get_bonded_device_info(bluetooth_device_address_t *dev_addr);
 
diff --git a/bt-service/services/include/bt-service-l2cap-le.h b/bt-service/services/include/bt-service-l2cap-le.h
new file mode 100644 (file)
index 0000000..21a6d0e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __BT_SERVICE_L2CAP_LE_CLIENT_H__
+#define __BT_SERVICE_L2CAP_LE_CLIENT_H__
+
+#include <glib.h>
+#include <sys/types.h>
+#include "bluetooth-api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _bt_l2cap_le_connect_using_psm(bluetooth_device_address_t *device_address,
+                                       int psm);
+int _bt_l2cap_le_socket_listen(int psm, bool accept);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __BT_SERVICE_L2CAP_LE_CLIENT_H__ */
index ca64135..fa6a6b6 100644 (file)
@@ -33,6 +33,7 @@ extern "C" {
 #define SOCK_TYPE_RFCOMM 0
 #define SOCK_TYPE_SCO 1
 #define SOCK_TYPE_L2CAP        2
+#define SOCK_TYPE_L2CAP_LE 3
 
 typedef void (*bt_socket_client_conn_cb) (int result, int sock_fd, char *address, char *uuid, int chan);
 
diff --git a/bt-service/services/l2cap_le/bt-service-l2cap-le.c b/bt-service/services/l2cap_le/bt-service-l2cap-le.c
new file mode 100644 (file)
index 0000000..90880bc
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Bluetooth-frwk
+ *
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *             http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#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-l2cap-le.h"
+#include "bt-service-socket.h"
+
+#define L2CAP_LE_PSM_MAX 0xFFFF
+
+static void __bt_l2cap_le_reply_pending_request(int result,
+                               int service_function, void *user_data, unsigned int size)
+{
+       GSList *l;
+       GArray *out_param;
+       invocation_info_t *req_info;
+
+       BT_INFO("service function %d", service_function);
+       /* Get method invocation context */
+       for (l = _bt_get_invocation_list(); l != NULL; ) {
+               req_info = l->data;
+               l = g_slist_next(l);
+               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_L2CAP_LE_CLIENT_CONNECT: {
+                       BT_INFO("l2cap_le_client_connect");
+                       GUnixFDList *fd_list = NULL;
+                       GError *error = NULL;
+                       char conn_addr[BT_ADDRESS_STRING_SIZE];
+                       char req_addr[BT_ADDRESS_STRING_SIZE];
+                       bluetooth_l2cap_le_connection_t *ptr = user_data;
+                       bluetooth_l2cap_le_connection_t *info = req_info->user_data;
+
+                       if (!info || !ptr) {
+                               BT_ERR("info: %p, ptr: %p can't be NULL", info, ptr);
+                               break;
+                       }
+
+                       /* Check if connect address matched with requested address */
+                       _bt_convert_addr_type_to_string(conn_addr, ptr->device_addr.addr);
+                       _bt_convert_addr_type_to_string(req_addr, info->device_addr.addr);
+                       if (strncasecmp(conn_addr, req_addr, BT_ADDRESS_STRING_SIZE)) {
+                               BT_INFO("l2cap_le address don't match, connected addr: [%s], requested addr: [%s]",
+                                               conn_addr, req_addr);
+                               break;
+                       }
+
+                       /* Check if connect psm matched with requested psm */
+                       if (ptr->psm != info->psm) {
+                               BT_INFO("l2cap_le psm don't match, connected psm: [%d], requested psm: [%d]",
+                                               ptr->psm, info->psm);
+                               break;
+                       }
+
+                       g_array_append_vals(out_param, user_data, size);
+
+                       if (BLUETOOTH_ERROR_NONE == result) {
+                               fd_list = g_unix_fd_list_new();
+                               g_unix_fd_list_append(fd_list, ptr->socket_fd, &error);
+                               g_assert_no_error(error);
+                               close(ptr->socket_fd);
+                       }
+
+                       _bt_service_method_return_with_unix_fd_list(
+                                       req_info->context, out_param, result, fd_list);
+                       if (fd_list)
+                               g_object_unref(fd_list);
+
+                       _bt_free_info_from_invocation_list(req_info);
+                       g_array_free(out_param, TRUE);
+                       break;
+               }
+               case BT_L2CAP_LE_LISTEN_AND_ACCEPT:
+               case BT_L2CAP_LE_LISTEN: {
+                       GUnixFDList *fd_list = NULL;
+                       GError *error = NULL;
+                       int *socket_fd = user_data;
+
+                       BT_INFO("Server socket fd: %d", *socket_fd);
+
+                       g_array_append_vals(out_param, user_data, size);
+
+                       /* Add socket fd to unix_fd_list */
+                       fd_list = g_unix_fd_list_new();
+                       g_unix_fd_list_append(fd_list, *socket_fd, &error);
+                       g_assert_no_error(error);
+
+                       _bt_service_method_return_with_unix_fd_list(
+                                       req_info->context, out_param, result, fd_list);
+
+                       close(*socket_fd);
+                       g_object_unref(fd_list);
+
+                       _bt_free_info_from_invocation_list(req_info);
+                       g_array_free(out_param, TRUE);
+                       break;
+               }
+               default:
+                       BT_ERR("Unknown Service function");
+               }
+       }
+
+       return;
+}
+
+static void __bt_l2cap_le_socket_conn_cb(int result, int sock_fd,
+                                       char *uuid, char *address, int psm)
+{
+       bluetooth_l2cap_le_connection_t conn_info;
+
+       ret_if(NULL == address);
+
+       BT_DBG("+");
+
+       BT_INFO("result: %d, socket_fd: %d, address: %s, psm: %d", result,
+                                       sock_fd, address, psm);
+
+       /* Fill l2cap_le connection structure and send reply to pending request */
+       memset(&conn_info, 0x00, sizeof(bluetooth_l2cap_le_connection_t));
+       conn_info.socket_fd = sock_fd;
+       conn_info.device_role = L2CAP_LE_ROLE_CLIENT;
+       conn_info.psm = psm;
+
+       _bt_convert_addr_string_to_type(conn_info.device_addr.addr, address);
+
+       __bt_l2cap_le_reply_pending_request(
+                       result, BT_L2CAP_LE_CLIENT_CONNECT,
+                       (void *)&conn_info, sizeof(bluetooth_l2cap_le_connection_t));
+
+       BT_DBG("-");
+}
+
+int _bt_l2cap_le_connect_using_psm(bluetooth_device_address_t *device_address,
+                                       int psm)
+{
+       int result = BLUETOOTH_ERROR_NONE;
+       char address[BT_ADDRESS_STRING_SIZE] = { 0 };
+
+       BT_DBG("+");
+
+       retv_if(NULL == device_address, BLUETOOTH_ERROR_INVALID_PARAM);
+
+       if (psm <= 0 || psm > L2CAP_LE_PSM_MAX)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       _bt_convert_addr_type_to_string(address, device_address->addr);
+
+       BT_INFO("L2CAP_LE socket connect called for [%s], psm: %d", address, psm);
+
+       result = _bt_socket_client_connect(SOCK_TYPE_L2CAP_LE,
+                                       address, NULL, psm, __bt_l2cap_le_socket_conn_cb);
+       if (BLUETOOTH_ERROR_NONE != result) {
+               BT_ERR("_bt_socket_client_connect failed errorcode %d", result);
+               return result;
+       }
+
+       BT_DBG("-");
+       return result;
+}
+
+gboolean __bt_send_l2cap_le_server_fd(gpointer user_data)
+{
+       BT_DBG("+");
+
+       __bt_l2cap_le_reply_pending_request(BLUETOOTH_ERROR_NONE,
+                       BT_L2CAP_LE_LISTEN, user_data, sizeof(int));
+
+       g_free(user_data);
+       BT_DBG("-");
+       return FALSE;
+}
+
+gboolean __bt_send_l2cap_le_server_fd_with_accept(gpointer user_data)
+{
+       BT_DBG("+");
+
+       __bt_l2cap_le_reply_pending_request(BLUETOOTH_ERROR_NONE,
+                       BT_L2CAP_LE_LISTEN_AND_ACCEPT, user_data, sizeof(int));
+
+       g_free(user_data);
+       BT_DBG("-");
+       return FALSE;
+}
+
+int _bt_l2cap_le_socket_listen(int psm, bool accept)
+{
+       int sock_fd;
+
+       BT_DBG("+");
+
+       if (psm < 0 || psm > L2CAP_LE_PSM_MAX)
+               return BLUETOOTH_ERROR_INVALID_PARAM;
+
+       BT_INFO("l2cap_le listen socket called with psm: [%d]", psm);
+       sock_fd = _bt_socket_listen(SOCK_TYPE_L2CAP_LE, NULL, NULL, psm);
+       if (sock_fd < 0) {
+               BT_ERR("_bt_socket_listen failed");
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       if (accept == false)
+               g_idle_add(__bt_send_l2cap_le_server_fd, g_memdup2(&sock_fd, sizeof(int)));
+       else
+               g_idle_add(__bt_send_l2cap_le_server_fd_with_accept, g_memdup2(&sock_fd, sizeof(int)));
+
+       BT_DBG("-");
+       return sock_fd;
+}
index 444c757..ef772a7 100644 (file)
@@ -36,6 +36,8 @@
 #include "bt-service-socket.h"
 #include "bt-service-event.h"
 
+#define L2CAP_LE_UUID_SUBSTR "FFFFFFFF-FFFF-FFFF-FFFF-"
+
 typedef struct {
        int sock_fd;
        int chan;
@@ -127,7 +129,8 @@ static void __handle_socket_authorization_request(event_socket_authorize_req_t *
        int result = BLUETOOTH_ERROR_NONE;
        char name[BT_NAME_LENGTH_MAX + 1] = {0, };
        char path[BT_NAME_LENGTH_MAX + 1] = {0, };
-       int fd;
+       const char *value;
+       int fd, psm;
 
        BT_DBG("+");
 
@@ -137,9 +140,20 @@ static void __handle_socket_authorization_request(event_socket_authorize_req_t *
        memcpy(path, auth_event->path, BT_NAME_LENGTH_MAX);
        fd = auth_event->fd;
        BT_INFO("Address: %s, UUID: %s, Name: %s, Path: %s, Fd: %d", address, uuid_str, name, path, fd);
-       _bt_send_event(BT_RFCOMM_SERVER_EVENT,
-                       BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
-                       g_variant_new("(issssn)", result, address, uuid_str, name, path, fd));
+
+       if (!strncmp(uuid_str, L2CAP_LE_UUID_SUBSTR, strlen(L2CAP_LE_UUID_SUBSTR))) {
+               BT_INFO("sending L2CAP_LE authorize event");
+               value = uuid_str + strlen(L2CAP_LE_UUID_SUBSTR);
+               psm = atoi(value);
+               _bt_send_event(BT_L2CAP_LE_SERVER_EVENT,
+                               BLUETOOTH_EVENT_L2CAP_LE_AUTHORIZE,
+                               g_variant_new("(isi)", result, address, psm));
+       } else {
+               BT_INFO("sending rfcomm authorize event");
+               _bt_send_event(BT_RFCOMM_SERVER_EVENT,
+                               BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
+                               g_variant_new("(issssn)", result, address, uuid_str, name, path, fd));
+       }
        BT_DBG("-");
 }
 
@@ -197,6 +211,9 @@ int _bt_socket_client_connect(int sock_type, char *address,
        case SOCK_TYPE_RFCOMM:
                sock_fd = socket_connect(OAL_SOCK_RFCOMM, &uuid, channel, &bd);
                break;
+       case SOCK_TYPE_L2CAP_LE:
+               sock_fd = socket_connect(OAL_SOCK_L2CAP_LE, NULL, channel, &bd);
+               break;
        default:
                BT_ERR("Socket type: %d not supported", sock_type);
                return BLUETOOTH_ERROR_NOT_SUPPORT;
@@ -227,18 +244,23 @@ int _bt_socket_listen(int sock_type, char *svc_name, char *server_uuid, int chan
        int sock_fd;
        oal_uuid_t uuid;
 
-       retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
-       retv_if(NULL == server_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
+       if (sock_type != SOCK_TYPE_L2CAP_LE) {
+               retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
+               retv_if(NULL == server_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
 
-       BT_INFO("sock_type: %d, svc_name: %s, uuid: %s, channel: %d",
-                       sock_type, svc_name, server_uuid, channel);
+               BT_INFO("sock_type: %d, svc_name: %s, uuid: %s, channel: %d",
+                               sock_type, svc_name, server_uuid, channel);
 
-       _bt_service_convert_uuid_string_to_type(uuid.uuid, server_uuid);
+               _bt_service_convert_uuid_string_to_type(uuid.uuid, server_uuid);
+       }
 
        switch (sock_type) {
        case SOCK_TYPE_RFCOMM:
                sock_fd = socket_listen(OAL_SOCK_RFCOMM, &uuid, svc_name, channel);
                break;
+       case SOCK_TYPE_L2CAP_LE:
+               sock_fd = socket_listen(OAL_SOCK_L2CAP_LE, NULL, NULL, channel);
+               break;
        default:
                BT_ERR("Socket type: %d not supported", sock_type);
                return BLUETOOTH_ERROR_NOT_SUPPORT;
index d0a6785..399638d 100644 (file)
@@ -77,6 +77,12 @@ extern "C" {
 #define RFCOMM_ROBOT_PROFILE_CHANNEL 22
 
 /**
+ * This is L2cap LE Socket Connected event role
+ */
+#define L2CAP_LE_ROLE_SERVER 1
+#define L2CAP_LE_ROLE_CLIENT 2
+
+/**
  * This is maximum length for search value string for PBAP Phonebook Search
  */
 #define BLUETOOTH_PBAP_MAX_SEARCH_VALUE_LENGTH 100
@@ -717,6 +723,8 @@ typedef struct {
                                                                /**< Base ID for MAP events */
 #define BLUETOOTH_EVENT_MESH_BASE  ((int)(BLUETOOTH_EVENT_MAP_BASE + 0x0020))
                                                                /**< Base ID for MAP events */
+#define BLUETOOTH_EVENT_L2CAP_LE_BASE  ((int)(BLUETOOTH_EVENT_MESH_BASE + 0x0040))
+                                                               /**< Base ID for L2CAP_LE events */
 
 /**
  * Bluetooth event type
@@ -965,7 +973,13 @@ typedef enum {
        BLUETOOTH_EVENT_MESH_MODEL_SUBSCRIPTION_CONFGURED,
        BLUETOOTH_EVENT_MESH_MODEL_VIRTUAL_SUBSCRIPTION_CONFGURED,
        BLUETOOTH_EVENT_MESH_MODEL_PUBLICATION_STATUS,
-       BLUETOOTH_EVENT_MESH_JOIN_COMPLETED
+       BLUETOOTH_EVENT_MESH_JOIN_COMPLETED,
+       BLUETOOTH_EVENT_L2CAP_LE_DATA_RECEIVED = BLUETOOTH_EVENT_L2CAP_LE_BASE,
+                                               /**< L2CAP_LE data receive event */
+       BLUETOOTH_EVENT_L2CAP_LE_CONNECTED,     /**< L2CAP_LE server/client connect */
+       BLUETOOTH_EVENT_L2CAP_LE_DISCONNECTED,  /**< L2CAP_LE server/client disconnect */
+       BLUETOOTH_EVENT_L2CAP_LE_AUTHORIZE,
+       BLUETOOTH_EVENT_L2CAP_LE_SERVER_REMOVED
 } bluetooth_event_type_t;
 
  /**
@@ -1464,6 +1478,17 @@ typedef struct {
 } bluetooth_rfcomm_connection_request_t;
 
 /**
+ * Stucture to l2cap_le connection
+ */
+typedef struct {
+       int socket_fd; /**< the socket fd */
+       int server_id; /* Server id */
+       int device_role; /** < Device role - L2CAP_LE_ROLE_SERVER or L2CAP_LE_ROLE_CLIENT */
+       bluetooth_device_address_t device_addr; /**< device address */
+       int psm;
+} bluetooth_l2cap_le_connection_t;
+
+/**
  * HDP QOS types
  */
 typedef enum {
index 5026c9b..3397adc 100644 (file)
@@ -93,6 +93,8 @@ typedef enum {
        BT_HDP_EVENT,
        BT_AUDIO_AVC_EVENT,
        BT_MESH_EVENT,
+       BT_L2CAP_LE_CLIENT_EVENT,
+       BT_L2CAP_LE_SERVER_EVENT,
        /* Will be added */
 } bt_event_type_t;
 
@@ -164,6 +166,7 @@ typedef enum {
 #define BT_FUNC_TDS_BASE ((int)(BT_FUNC_MAP_BASE + 0x0020))
 #define BT_FUNC_OTP_BASE ((int)(BT_FUNC_TDS_BASE + 0x0020))
 #define BT_FUNC_MESH_BASE ((int)(BT_FUNC_OTP_BASE + 0x0020))
+#define BT_FUNC_L2CAP_LE_BASE ((int)(BT_FUNC_MESH_BASE + 0x0040))
 
 typedef enum {
        BT_CHECK_ADAPTER = BT_FUNC_BASE,
@@ -508,7 +511,19 @@ typedef enum {
        BT_MESH_NETWORK_REMOVE_GROUP,
        BT_MESH_NETWORK_GET_GROUPS,
        BT_MESH_MODEL_CONFIG_GROUP_SUB,
-       BT_MESH_MODEL_CONFIG_VIRTUAL_GROUP_SUB
+       BT_MESH_MODEL_CONFIG_VIRTUAL_GROUP_SUB,
+       BT_L2CAP_LE_CLIENT_CONNECT = BT_FUNC_L2CAP_LE_BASE,
+       BT_L2CAP_LE_CLIENT_CANCEL_CONNECT,
+       BT_L2CAP_LE_CLIENT_IS_CONNECTED,
+       BT_L2CAP_LE_SOCKET_DISCONNECT,
+       BT_L2CAP_LE_SOCKET_WRITE,
+       BT_L2CAP_LE_CREATE_SOCKET,
+       BT_L2CAP_LE_REMOVE_SOCKET,
+       BT_L2CAP_LE_LISTEN_AND_ACCEPT,
+       BT_L2CAP_LE_LISTEN,
+       BT_L2CAP_LE_IS_PSM_AVAILABLE,
+       BT_L2CAP_LE_ACCEPT_CONNECTION,
+       BT_L2CAP_LE_REJECT_CONNECTION
 } bt_function_t;
 
 typedef struct {
@@ -577,6 +592,9 @@ typedef struct {
 
 #define BT_MESH_PATH "/org/projectx/bt/mesh"
 
+#define BT_L2CAP_LE_CLIENT_PATH "/org/projectx/bt/l2cap_le_client"
+#define BT_L2CAP_LE_SERVER_PATH "/org/projectx/bt/l2cap_le_server"
+
 #define BT_ENABLED "Enabled"
 #define BT_DISABLED "Disabled"
 #define BT_DISABLED_BATTERY_DATA "AdapterDisabledBatteryData"