From e03d04208c00160d70903983ec295832056b0867 Mon Sep 17 00:00:00 2001 From: Ayush Garg Date: Wed, 23 Feb 2022 16:28:48 +0530 Subject: [PATCH] LE CoC: Add support for L2CAP_LE type socket in bt-service 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 --- bt-service/CMakeLists.txt | 1 + bt-service/services/bt-request-handler.c | 139 +++++++++++- bt-service/services/bt-service-event-sender.c | 6 + .../services/device/bt-service-core-device.c | 2 +- .../services/include/bt-service-core-device.h | 2 +- bt-service/services/include/bt-service-l2cap-le.h | 38 ++++ bt-service/services/include/bt-service-socket.h | 1 + bt-service/services/l2cap_le/bt-service-l2cap-le.c | 240 +++++++++++++++++++++ bt-service/services/socket/bt-service-socket.c | 40 +++- include/bluetooth-api.h | 27 ++- include/bt-internal-types.h | 20 +- 11 files changed, 500 insertions(+), 16 deletions(-) create mode 100644 bt-service/services/include/bt-service-l2cap-le.h create mode 100644 bt-service/services/l2cap_le/bt-service-l2cap-le.c diff --git a/bt-service/CMakeLists.txt b/bt-service/CMakeLists.txt index 0c9c020..f5e6875 100644 --- a/bt-service/CMakeLists.txt +++ b/bt-service/CMakeLists.txt @@ -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") diff --git a/bt-service/services/bt-request-handler.c b/bt-service/services/bt-request-handler.c index 3452c3c..458a314 100644 --- a/bt-service/services/bt-request-handler.c +++ b/bt-service/services/bt-request-handler.c @@ -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: diff --git a/bt-service/services/bt-service-event-sender.c b/bt-service/services/bt-service-event-sender.c index 2b84f8f..d16b7b3 100644 --- a/bt-service/services/bt-service-event-sender.c +++ b/bt-service/services/bt-service-event-sender.c @@ -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; diff --git a/bt-service/services/device/bt-service-core-device.c b/bt-service/services/device/bt-service-core-device.c index cfb454a..0280a10 100644 --- a/bt-service/services/device/bt-service-core-device.c +++ b/bt-service/services/device/bt-service-core-device.c @@ -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; diff --git a/bt-service/services/include/bt-service-core-device.h b/bt-service/services/include/bt-service-core-device.h index 7b07ce4..afdc084 100755 --- a/bt-service/services/include/bt-service-core-device.h +++ b/bt-service/services/include/bt-service-core-device.h @@ -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 index 0000000..21a6d0e --- /dev/null +++ b/bt-service/services/include/bt-service-l2cap-le.h @@ -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 +#include +#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__ */ diff --git a/bt-service/services/include/bt-service-socket.h b/bt-service/services/include/bt-service-socket.h index ca64135..fa6a6b6 100644 --- a/bt-service/services/include/bt-service-socket.h +++ b/bt-service/services/include/bt-service-socket.h @@ -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 index 0000000..90880bc --- /dev/null +++ b/bt-service/services/l2cap_le/bt-service-l2cap-le.c @@ -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 +#include +#include +#include +#include +#include + +#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; +} diff --git a/bt-service/services/socket/bt-service-socket.c b/bt-service/services/socket/bt-service-socket.c index 444c757..ef772a7 100644 --- a/bt-service/services/socket/bt-service-socket.c +++ b/bt-service/services/socket/bt-service-socket.c @@ -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; diff --git a/include/bluetooth-api.h b/include/bluetooth-api.h index d0a6785..399638d 100644 --- a/include/bluetooth-api.h +++ b/include/bluetooth-api.h @@ -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 { diff --git a/include/bt-internal-types.h b/include/bt-internal-types.h index 5026c9b..3397adc 100644 --- a/include/bt-internal-types.h +++ b/include/bt-internal-types.h @@ -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" -- 2.7.4