2 * Open Adaptation Layer (OAL)
4 * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include <sys/types.h>
27 #include <sys/socket.h>
31 #include <oal-event.h>
32 #include <oal-manager.h>
33 #include "oal-internal.h"
35 #include "bluetooth.h"
37 #include "oal-socket.h"
38 #include "oal-utils.h"
40 #define CHECK_OAL_SOCKET_ENABLED() \
42 if (socket_api == NULL) { \
43 BT_ERR("Socket is not Initialized"); \
44 return OAL_STATUS_NOT_READY; \
50 #define SOCK_SHORT_LEN 2
51 #define SOCK_INT_LEN 4
52 #define SOCK_CONNECT_INFO_LEN 16
53 #define SOCK_BD_ADDR_LEN 6
60 GIOChannel *control_io;
66 static const btsock_interface_t* socket_api = NULL;
68 static int getInt(char *buf, int len)
72 if (len != SOCK_INT_LEN)
74 val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
78 static int getShort(char *buf, int len)
82 if (len != SOCK_SHORT_LEN)
84 val = buf[0] | (buf[1] << 8);
88 static int getBdaddr(char *buf, int len, bt_bdaddr_t *bd)
92 if (len != SOCK_BD_ADDR_LEN)
94 bd->address[0] = buf[0];
95 bd->address[1] = buf[1];
96 bd->address[2] = buf[2];
97 bd->address[3] = buf[3];
98 bd->address[4] = buf[4];
99 bd->address[5] = buf[5];
100 BT_DBG("Address: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
101 bd->address[0], bd->address[1], bd->address[2],
102 bd->address[3], bd->address[4], bd->address[5]);
105 static void remove_io_channel(guint gid, GIOChannel *gch)
108 g_io_channel_shutdown(gch, TRUE, NULL);
110 g_source_remove(gid);
113 static int socket_process_cmsg(struct msghdr *pMsg, int * data_fd)
115 struct cmsghdr *cmsgptr = NULL;
117 for (cmsgptr = CMSG_FIRSTHDR(pMsg);
118 cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(pMsg, cmsgptr)) {
120 if (cmsgptr->cmsg_level != SOL_SOCKET)
123 if (cmsgptr->cmsg_type == SCM_RIGHTS) {
124 int *pDescriptors = (int *)CMSG_DATA(cmsgptr);
125 int count = ((cmsgptr->cmsg_len - CMSG_LEN(0)) / sizeof(int));
128 BT_ERR("ERROR Invalid count of descriptors");
132 BT_DBG("Server, socket fd for connection: %d", pDescriptors[0]);
133 *data_fd = pDescriptors[0];
140 static int socket_read(int fd, char *buf, size_t len, int *data_fd)
145 struct cmsghdr cmsgbuf[2*sizeof(struct cmsghdr) + 0x100];
152 BT_INFO("socket_read, fd = %d", fd);
156 memset(&msg, 0, sizeof(msg));
157 memset(&iv, 0, sizeof(iv));
164 msg.msg_control = cmsgbuf;
165 msg.msg_controllen = sizeof(cmsgbuf);
167 flags = fcntl(fd, F_GETFL, 0);
168 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
169 BT_ERR("Not able to change socket nonblocking");
173 FD_ZERO(&toselect_fd);
174 FD_SET(fd, &toselect_fd);
178 ret = select(fd + 1, &toselect_fd, NULL, NULL, &wait);
180 fcntl(fd, F_SETFL, flags);
181 BT_ERR("Time out on selecy = %d", ret);
187 ret = recvmsg(fd, &msg, 0); //MSG_NOSIGNAL);
188 BT_DBG("socket_read, recvmsg ret = %d", ret);
189 if (ret < 0 && errno == EINTR) {
190 if (retryCount < MAX_RETRY) {
193 fcntl(fd, F_SETFL, flags);
198 if (ret < 0 && errno == EPIPE) {
199 // Treat this as an end of stream
200 fcntl(fd, F_SETFL, flags);
201 BT_ERR("EOS errno: %d", errno);
206 fcntl(fd, F_SETFL, flags);
207 BT_ERR("Ret errno: %d", errno);
211 /* FD_ISSET need not be checked */
212 fcntl(fd, F_SETFL, flags);
213 if ((msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) != 0) {
214 // To us, any of the above flags are a fatal error
215 BT_ERR("MSG Flags errno: %d", errno);
219 if (ret >= 0 && data_fd) {
220 BT_INFO("Connection received");
221 socket_process_cmsg(&msg, data_fd);
227 static int sock_wait_for_channel(int sock_fd)
230 char buf[SOCK_INT_LEN];
232 readlen = socket_read(sock_fd, buf, SOCK_INT_LEN, NULL);
233 return getInt(buf, readlen);
236 static int sock_wait_for_connect_signal(int sock_fd,
237 int *data_fd, bt_bdaddr_t *bd_addr)
240 char buf[SOCK_CONNECT_INFO_LEN];
241 int size = -1, channel = -1, status = -1;
244 readlen = socket_read(sock_fd, buf, SOCK_CONNECT_INFO_LEN, data_fd);
245 BT_DBG("Socket Read len: %d", readlen);
247 BT_WARN("Listen stopped");
248 return -1; /* This essentially means that the listen is stopped */
251 if (readlen != SOCK_CONNECT_INFO_LEN) {
252 BT_ERR("Read length is not same as socket info length");
256 size = getShort(&buf[len], SOCK_SHORT_LEN);
257 len += SOCK_SHORT_LEN;
258 if (size != SOCK_CONNECT_INFO_LEN)
261 getBdaddr(&buf[len], SOCK_BD_ADDR_LEN, bd_addr); len += SOCK_BD_ADDR_LEN;
262 channel = getInt(&buf[len], SOCK_INT_LEN); len += SOCK_INT_LEN;
263 status = getInt(&buf[len], SOCK_INT_LEN);
265 BT_INFO("BTSOCK CONNECTION ESTABLISHED REMOTE Channel:%d, Status:%d",
270 static int sock_wait_for_connection_setup(oal_client_info_t *p_oal_client_info)
275 /* First, wait for channel number */
276 channel = sock_wait_for_channel(p_oal_client_info->fd);
278 BT_ERR("ERROR, incorrect channel= %d", channel);
279 return OAL_STATUS_INTERNAL_ERROR;
282 BT_INFO("client channel= %d", channel);
284 /* Now, wait for connection signal */
285 ret = sock_wait_for_connect_signal(p_oal_client_info->fd,
286 NULL, (bt_bdaddr_t *)&p_oal_client_info->address);
288 BT_ERR("ERROR, sock_wait_for_connect_signal failed");
289 return OAL_STATUS_INTERNAL_ERROR;
292 return OAL_STATUS_SUCCESS;
296 * This function will be called only once as connection setup is done here
297 * and then data will be received directly in application context using fd
298 * passed in socket connection event.
300 static gboolean sockclient_thread(GIOChannel *gio, GIOCondition cond, gpointer data)
302 event_socket_client_conn_t *client_info_ev;
303 oal_client_info_t *p_oal_client_info = (oal_client_info_t *)data;
305 retv_if(p_oal_client_info == NULL, FALSE);
306 retv_if(p_oal_client_info->fd < 0, FALSE);
308 BT_DBG("Client fd= %d", p_oal_client_info->fd);
310 /* This memory will be freed by event dispatcher */
311 client_info_ev = g_new0(event_socket_client_conn_t, 1);
312 client_info_ev->fd = p_oal_client_info->fd;
313 client_info_ev->sock_type = p_oal_client_info->sock_type;
314 memcpy(&client_info_ev->address, &p_oal_client_info->address, sizeof(bt_address_t));
316 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
317 BT_INFO("Client disconnected-0x%X (fd = %d)",
318 cond, p_oal_client_info->fd);
322 if (OAL_STATUS_SUCCESS == sock_wait_for_connection_setup(p_oal_client_info)) {
323 BT_INFO("connection setup success");
324 send_event_bda_trace(OAL_EVENT_SOCKET_OUTGOING_CONNECTED, client_info_ev,
325 sizeof(event_socket_client_conn_t), &p_oal_client_info->address);
329 BT_ERR("ERROR, incorrect connection setup");
332 remove_io_channel(p_oal_client_info->control_id, p_oal_client_info->control_io);
333 send_event_bda_trace(OAL_EVENT_SOCKET_DISCONNECTED, client_info_ev,
334 sizeof(event_socket_client_conn_t), &p_oal_client_info->address);
336 g_free(p_oal_client_info);
340 int socket_connect(oal_sock_type_t sock_type, oal_uuid_t *p_uuid, int channel, bt_address_t* bd)
342 oal_client_info_t *p_oal_client_info = NULL;
346 API_TRACE("Socket connect: %s", bdt_bd2str(bd, &bdstr));
348 CHECK_OAL_SOCKET_ENABLED();
350 p_oal_client_info = g_new0(oal_client_info_t, 1);
353 case OAL_SOCK_RFCOMM:
355 socket_api->connect((const bt_bdaddr_t *)bd,
356 BTSOCK_RFCOMM, p_uuid->uuid, 0, &sock_fd, 0);
358 socket_api->connect((const bt_bdaddr_t *)bd,
359 BTSOCK_RFCOMM, NULL, channel, &sock_fd, 0);
362 BT_ERR("Socket type: %d not supported");
366 BT_ERR("Bluetooth socket connect failed");
370 BT_INFO("Bluetooth client socket created, sock_fd=%d", sock_fd);
372 p_oal_client_info->fd = sock_fd;
373 p_oal_client_info->sock_type = sock_type;
374 memcpy(&p_oal_client_info->address, bd, sizeof(bt_address_t));
375 p_oal_client_info->control_io = g_io_channel_unix_new(p_oal_client_info->fd);
376 p_oal_client_info->control_id = g_io_add_watch(p_oal_client_info->control_io,
377 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
378 sockclient_thread, p_oal_client_info);
379 g_io_channel_set_close_on_unref(p_oal_client_info->control_io, FALSE);
380 g_io_channel_unref(p_oal_client_info->control_io);
382 BT_DBG("Client watch added");
386 int socket_listen(oal_sock_type_t sock_type, oal_uuid_t *p_uuid, char *svc_name, int channel)
390 int ret = BT_STATUS_FAIL;
392 CHECK_OAL_SOCKET_ENABLED();
393 OAL_CHECK_PARAMETER(svc_name, return);
394 API_TRACE("svc_name: %s", svc_name);
397 case OAL_SOCK_RFCOMM:
399 ret = socket_api->listen(BTSOCK_RFCOMM,
400 svc_name, p_uuid->uuid, 0, &sock_fd, 0);
402 ret = socket_api->listen(BTSOCK_RFCOMM,
403 svc_name, p_uuid->uuid, channel, &sock_fd, 0);
406 BT_ERR("Socket type: %d not supported");
409 if (sock_fd < 0 || ret != BT_STATUS_SUCCESS) {
410 BT_ERR("Bluetooth socket creation failed");
414 BT_INFO("Bluetooth server socket created, sock_fd=%d", sock_fd);
416 /* Read server channel number sent by stack */
417 srv_channel = sock_wait_for_channel(sock_fd);
418 if (srv_channel < 0) {
419 BT_ERR("incorrect channel= %d", srv_channel);
423 BT_INFO("server channel= %d", srv_channel);
428 oal_status_t socket_enable()
430 const bt_interface_t *blued_api;
432 API_TRACE("Socket Init");
434 blued_api = adapter_get_stack_interface();
435 if (blued_api == NULL) {
436 BT_ERR("Stack is not initialized");
437 return OAL_STATUS_NOT_READY;
440 if (socket_api != NULL) {
441 BT_WARN("Socket Interface is already initialized...");
442 return OAL_STATUS_ALREADY_DONE;
445 socket_api = (const btsock_interface_t*)blued_api->get_profile_interface(BT_PROFILE_SOCKETS_ID);
447 BT_ERR("OAL Socket failed to initialize");
448 return OAL_STATUS_INTERNAL_ERROR;
451 BT_DBG("Socket successfully initiated");
452 return OAL_STATUS_SUCCESS ;
455 oal_status_t socket_disable(void)
458 API_TRACE("Socket Deinit");
460 CHECK_OAL_SOCKET_ENABLED();
462 return OAL_STATUS_SUCCESS;