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"
42 char uuid[BT_UUID_STRING_SIZE];
43 char address[BT_ADDRESS_STRING_SIZE];
44 bt_socket_client_conn_cb conn_cb;
47 static bt_socket_info_t *pending_conn_info;
49 /* Function to handle socket disconnection */
50 void __handle_socket_disconnected(event_socket_client_conn_t *client_info)
52 char address[BT_ADDRESS_STRING_SIZE];
54 ret_if(NULL == client_info);
58 _bt_convert_addr_type_to_string(address, client_info->address.addr);
61 * In case of an already connected socket, if disconnection happens, it will
62 * automatically detected in corresponding i/o handler and events will be sent
63 * from there. So here we only handle connection fail case.
65 if (NULL != pending_conn_info &&
66 !strncasecmp(address, pending_conn_info->address, strlen(address))) {
68 * Disconnection event is received for ongoing connection, invoke connection
69 * state callback with error.
71 BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
72 client_info->fd, address,
73 pending_conn_info->uuid,
74 pending_conn_info->chan);
76 pending_conn_info->conn_cb(BLUETOOTH_ERROR_INTERNAL, client_info->fd, address,
77 pending_conn_info->uuid, pending_conn_info->chan);
79 g_free(pending_conn_info);
80 pending_conn_info = NULL;
82 BT_INFO("Disconnected Address: [%s], socket_fd: %d", address, client_info->fd);
88 /* Handle outgoing client socket connection event */
89 static void __handle_outgoing_client_socket_connected(event_socket_client_conn_t *client_info)
91 char address[BT_ADDRESS_STRING_SIZE];
93 ret_if(NULL == client_info);
94 ret_if(NULL == pending_conn_info);
99 * Only one socket connect req at a time is allowed, so received address
100 * should match with pending request.
102 _bt_convert_addr_type_to_string(address, client_info->address.addr);
103 if (strncasecmp(address, pending_conn_info->address, strlen(address))) {
104 BT_ERR("Address mismatch, Pending connection address: [%s]",
105 pending_conn_info->address);
106 BT_ERR("Client connection callback called with address: [%s]", address);
110 BT_INFO("socket_fd: %d, address: %s, uuid: %s, channel: %d",
111 client_info->fd, address,
112 pending_conn_info->uuid,
113 pending_conn_info->chan);
115 pending_conn_info->conn_cb(BLUETOOTH_ERROR_NONE, client_info->fd, address,
116 pending_conn_info->uuid, pending_conn_info->chan);
118 g_free(pending_conn_info);
119 pending_conn_info = NULL;
123 static void __handle_socket_authorization_request(event_socket_authorize_req_t *auth_event)
125 char address[BT_ADDRESS_STRING_SIZE];
126 char uuid_str[BT_UUID_STRING_SIZE];
127 int result = BLUETOOTH_ERROR_NONE;
128 char name[BT_NAME_LENGTH_MAX + 1] = {0, };
129 char path[BT_NAME_LENGTH_MAX + 1] = {0, };
134 _bt_convert_addr_type_to_string(address, auth_event->address.addr);
135 _bt_service_convert_uuid_type_to_string(uuid_str, auth_event->uuid.uuid);
136 memcpy(name, auth_event->name, BT_NAME_LENGTH_MAX);
137 memcpy(path, auth_event->path, BT_NAME_LENGTH_MAX);
139 BT_INFO("Address: %s, UUID: %s, Name: %s, Path: %s, Fd: %d", address, uuid_str, name, path, fd);
140 _bt_send_event(BT_RFCOMM_SERVER_EVENT,
141 BLUETOOTH_EVENT_RFCOMM_AUTHORIZE,
142 g_variant_new("(issssn)", result, address, uuid_str, name, path, fd));
146 static void __bt_socket_event_handler(int event_type, gpointer event_data)
148 BT_INFO("OAL event = 0x%x, \n", event_type);
150 switch (event_type) {
151 case OAL_EVENT_SOCKET_OUTGOING_CONNECTED: {
152 event_socket_client_conn_t *client_info = event_data;
154 __handle_outgoing_client_socket_connected(client_info);
157 case OAL_EVENT_SOCKET_DISCONNECTED: {
158 event_socket_client_conn_t *client_info = event_data;
160 __handle_socket_disconnected(client_info);
163 case OAL_EVENT_SOCKET_AUTHORIZE_REQUEST: {
164 BT_INFO("Socket Authorization Request");
165 __handle_socket_authorization_request((event_socket_authorize_req_t *)event_data);
169 BT_ERR("Invalid event:%d\n", event_type);
174 int _bt_socket_client_connect(int sock_type, char *address,
175 char *remote_uuid, int channel, bt_socket_client_conn_cb cb)
181 retv_if(NULL == address, BLUETOOTH_ERROR_INVALID_PARAM);
182 retv_if(NULL != pending_conn_info, BLUETOOTH_ERROR_DEVICE_BUSY);
187 BT_INFO("sock_type: %d, address: %s, remote_uuid: %s, channel: %d",
188 sock_type, address, remote_uuid, channel);
190 _bt_convert_addr_string_to_type(bd.addr, address);
192 _bt_service_convert_uuid_string_to_type(uuid.uuid, remote_uuid);
194 memset(&uuid, 0x00, sizeof(oal_uuid_t));
197 case SOCK_TYPE_RFCOMM:
198 sock_fd = socket_connect(OAL_SOCK_RFCOMM, &uuid, channel, &bd);
201 BT_ERR("Socket type: %d not supported", sock_type);
202 return BLUETOOTH_ERROR_NOT_SUPPORT;
206 BT_ERR("Bluetooth socket connect failed");
207 return BLUETOOTH_ERROR_CONNECTION_ERROR;
210 pending_conn_info = g_malloc0(sizeof(bt_socket_info_t));
211 pending_conn_info->sock_fd = sock_fd;
212 pending_conn_info->chan = channel;
213 pending_conn_info->conn_cb = cb;
214 g_strlcpy(pending_conn_info->address, address, BT_ADDRESS_STRING_SIZE);
216 if (remote_uuid != NULL)
217 g_strlcpy(pending_conn_info->uuid, remote_uuid, BT_UUID_STRING_SIZE);
219 memset(pending_conn_info->uuid, 0x00, BT_UUID_STRING_SIZE);
222 return BLUETOOTH_ERROR_NONE;
225 int _bt_socket_listen(int sock_type, char *svc_name, char *server_uuid, int channel)
230 retv_if(NULL == svc_name, BLUETOOTH_ERROR_INVALID_PARAM);
231 retv_if(NULL == server_uuid, BLUETOOTH_ERROR_INVALID_PARAM);
233 BT_INFO("sock_type: %d, svc_name: %s, uuid: %s, channel: %d",
234 sock_type, svc_name, server_uuid, channel);
236 _bt_service_convert_uuid_string_to_type(uuid.uuid, server_uuid);
239 case SOCK_TYPE_RFCOMM:
240 sock_fd = socket_listen(OAL_SOCK_RFCOMM, &uuid, svc_name, channel);
243 BT_ERR("Socket type: %d not supported", sock_type);
244 return BLUETOOTH_ERROR_NOT_SUPPORT;
248 BT_ERR("Bluetooth socket create failed");
249 return BLUETOOTH_ERROR_INTERNAL;
255 int _bt_socket_init(void)
258 BT_INFO("Socket Init");
260 result = socket_enable();
261 if (result != OAL_STATUS_SUCCESS) {
262 BT_ERR("Socket init failed");
263 return _bt_convert_oal_status_to_bt_error(result);
266 /* Register SOCKET event handler */
267 _bt_service_register_event_handler_callback(BT_SOCKET_MODULE, __bt_socket_event_handler);
268 return BLUETOOTH_ERROR_NONE;
271 void _bt_socket_deinit(void)
273 BT_INFO("Socket de-init");
275 if (OAL_STATUS_SUCCESS != socket_disable())
276 BT_ERR("Socket de-init failed");
278 /* Un-register SOCKET event handler */
279 _bt_service_unregister_event_handler_callback(BT_SOCKET_MODULE);