4 * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Author: Atul Rai <a.rai@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 #include <sys/types.h>
28 #include <oal-event.h>
29 #include <oal-socket.h>
31 /* bt-service headers */
32 #include "bt-internal-types.h"
33 #include "bt-service-common.h"
34 #include "bt-service-util.h"
35 #include "bt-service-event-receiver.h"
36 #include "bt-service-socket.h"
37 #include "bt-service-event.h"
39 #define L2CAP_LE_UUID_SUBSTR "FFFFFFFF-FFFF-FFFF-FFFF-"
44 char uuid[BT_UUID_STRING_SIZE];
45 char address[BT_ADDRESS_STRING_SIZE];
46 bt_socket_client_conn_cb conn_cb;
49 static bt_socket_info_t *pending_conn_info;
51 /* Function to handle socket disconnection */
52 void __handle_socket_disconnected(event_socket_client_conn_t *client_info)
54 char address[BT_ADDRESS_STRING_SIZE];
56 ret_if(NULL == client_info);
60 _bt_convert_addr_type_to_string(address, client_info->address.addr);
63 * In case of an already connected socket, if disconnection happens, it will
64 * automatically detected in corresponding i/o handler and events will be sent
65 * from there. So here we only handle connection fail case.
67 if (NULL != pending_conn_info &&
68 !strncasecmp(address, pending_conn_info->address, strlen(address))) {
70 * Disconnection event is received for ongoing connection, invoke connection
71 * state callback with error.
73 BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
74 client_info->fd, address,
75 pending_conn_info->uuid,
76 pending_conn_info->chan);
78 pending_conn_info->conn_cb(BLUETOOTH_ERROR_INTERNAL, client_info->fd, address,
79 pending_conn_info->uuid, pending_conn_info->chan);
81 g_free(pending_conn_info);
82 pending_conn_info = NULL;
84 BT_INFO("Disconnected Address: [%s], socket_fd: %d", address, client_info->fd);
90 /* Handle outgoing client socket connection event */
91 static void __handle_outgoing_client_socket_connected(event_socket_client_conn_t *client_info)
93 char address[BT_ADDRESS_STRING_SIZE];
95 ret_if(NULL == client_info);
96 ret_if(NULL == pending_conn_info);
101 * Only one socket connect req at a time is allowed, so received address
102 * should match with pending request.
104 _bt_convert_addr_type_to_string(address, client_info->address.addr);
105 if (strncasecmp(address, pending_conn_info->address, strlen(address))) {
106 BT_ERR("Address mismatch, Pending connection address: [%s]",
107 pending_conn_info->address);
108 BT_ERR("Client connection callback called with address: [%s]", address);
112 BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
113 client_info->fd, address,
114 pending_conn_info->uuid,
115 pending_conn_info->chan);
117 pending_conn_info->conn_cb(BLUETOOTH_ERROR_NONE, client_info->fd, address,
118 pending_conn_info->uuid, pending_conn_info->chan);
120 g_free(pending_conn_info);
121 pending_conn_info = NULL;
125 static void __handle_socket_authorization_request(event_socket_authorize_req_t *auth_event)
127 char address[BT_ADDRESS_STRING_SIZE];
128 char uuid_str[BT_UUID_STRING_SIZE];
129 int result = BLUETOOTH_ERROR_NONE;
130 char name[BT_NAME_LENGTH_MAX + 1] = {0, };
131 char path[BT_NAME_LENGTH_MAX + 1] = {0, };
137 _bt_convert_addr_type_to_string(address, auth_event->address.addr);
138 _bt_service_convert_uuid_type_to_string(uuid_str, auth_event->uuid.uuid);
139 memcpy(name, auth_event->name, BT_NAME_LENGTH_MAX);
140 memcpy(path, auth_event->path, BT_NAME_LENGTH_MAX);
142 BT_INFO("Address: %s, UUID: %s, Name: %s, Path: %s, Fd: %d", address, uuid_str, name, path, fd);
144 if (!strncmp(uuid_str, L2CAP_LE_UUID_SUBSTR, strlen(L2CAP_LE_UUID_SUBSTR))) {
145 BT_INFO("sending L2CAP_LE authorize event");
146 value = uuid_str + strlen(L2CAP_LE_UUID_SUBSTR);
148 _bt_send_event(BT_L2CAP_LE_SERVER_EVENT,
149 BLUETOOTH_EVENT_L2CAP_LE_AUTHORIZE,
150 g_variant_new("(isi)", result, address, psm));
152 BT_INFO("sending rfcomm authorize event");
153 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
154 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
155 g_variant_new("(issssn)", result, address, uuid_str, name, path, fd));
160 static void __bt_socket_event_handler(int event_type, gpointer event_data)
162 BT_INFO("OAL event = 0x%x, \n", event_type);
164 switch (event_type) {
165 case OAL_EVENT_SOCKET_OUTGOING_CONNECTED: {
166 event_socket_client_conn_t *client_info = event_data;
168 __handle_outgoing_client_socket_connected(client_info);
171 case OAL_EVENT_SOCKET_DISCONNECTED: {
172 event_socket_client_conn_t *client_info = event_data;
174 __handle_socket_disconnected(client_info);
177 case OAL_EVENT_SOCKET_AUTHORIZE_REQUEST: {
178 BT_INFO("Socket Authorization Request");
179 __handle_socket_authorization_request((event_socket_authorize_req_t *)event_data);
183 BT_ERR("Invalid event:%d\n", event_type);
188 int _bt_socket_client_connect(int sock_type, char *address,
189 char *remote_uuid, int channel, bt_socket_client_conn_cb cb)
195 retv_if(NULL == address, BLUETOOTH_ERROR_INVALID_PARAM);
196 retv_if(NULL != pending_conn_info, BLUETOOTH_ERROR_DEVICE_BUSY);
201 BT_INFO("sock_type: %d, address: %s, remote_uuid: %s, channel: %d",
202 sock_type, address, remote_uuid, channel);
204 _bt_convert_addr_string_to_type(bd.addr, address);
206 _bt_service_convert_uuid_string_to_type(uuid.uuid, remote_uuid);
208 memset(&uuid, 0x00, sizeof(oal_uuid_t));
211 case SOCK_TYPE_RFCOMM:
212 sock_fd = socket_connect(OAL_SOCK_RFCOMM, &uuid, channel, &bd);
214 case SOCK_TYPE_L2CAP_LE:
215 sock_fd = socket_connect(OAL_SOCK_L2CAP_LE, NULL, channel, &bd);
218 BT_ERR("Socket type: %d not supported", sock_type);
219 return BLUETOOTH_ERROR_NOT_SUPPORT;
223 BT_ERR("Bluetooth socket connect failed");
224 return BLUETOOTH_ERROR_CONNECTION_ERROR;
227 pending_conn_info = g_malloc0(sizeof(bt_socket_info_t));
228 pending_conn_info->sock_fd = sock_fd;
229 pending_conn_info->chan = channel;
230 pending_conn_info->conn_cb = cb;
231 g_strlcpy(pending_conn_info->address, address, BT_ADDRESS_STRING_SIZE);
233 if (remote_uuid != NULL)
234 g_strlcpy(pending_conn_info->uuid, remote_uuid, BT_UUID_STRING_SIZE);
236 memset(pending_conn_info->uuid, 0x00, BT_UUID_STRING_SIZE);
239 return BLUETOOTH_ERROR_NONE;
242 int _bt_socket_listen(int sock_type, char *svc_name, char *server_uuid, int channel)
247 if (sock_type != SOCK_TYPE_L2CAP_LE) {
248 retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
249 retv_if(NULL == server_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
251 BT_INFO("sock_type: %d, svc_name: %s, uuid: %s, channel: %d",
252 sock_type, svc_name, server_uuid, channel);
254 _bt_service_convert_uuid_string_to_type(uuid.uuid, server_uuid);
258 case SOCK_TYPE_RFCOMM:
259 sock_fd = socket_listen(OAL_SOCK_RFCOMM, &uuid, svc_name, channel);
261 case SOCK_TYPE_L2CAP_LE:
262 sock_fd = socket_listen(OAL_SOCK_L2CAP_LE, NULL, NULL, channel);
265 BT_ERR("Socket type: %d not supported", sock_type);
266 return BLUETOOTH_ERROR_NOT_SUPPORT;
270 BT_ERR("Bluetooth socket create failed");
271 return BLUETOOTH_ERROR_INTERNAL;
277 int _bt_socket_init(void)
280 BT_INFO("Socket Init");
282 result = socket_enable();
283 if (result != OAL_STATUS_SUCCESS) {
284 BT_ERR("Socket init failed");
285 return _bt_convert_oal_status_to_bt_error(result);
288 /* Register SOCKET event handler */
289 _bt_service_register_event_handler_callback(BT_SOCKET_MODULE, __bt_socket_event_handler);
290 return BLUETOOTH_ERROR_NONE;
293 void _bt_socket_deinit(void)
295 BT_INFO("Socket de-init");
297 if (OAL_STATUS_SUCCESS != socket_disable())
298 BT_ERR("Socket de-init failed");
300 /* Un-register SOCKET event handler */
301 _bt_service_unregister_event_handler_callback(BT_SOCKET_MODULE);