1 /******************************************************************************
2  *
3  *  Copyright (C) 2014 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #define LOG_TAG "bt_btif_sock"
20 
21 #include <assert.h>
22 #include <hardware/bluetooth.h>
23 #include <hardware/bt_sock.h>
24 
25 #include "bta_api.h"
26 #include "btif_common.h"
27 #include "btif_sock_rfc.h"
28 #include "btif_sock_sco.h"
29 #include "btif_sock_thread.h"
30 #include "btif_sock_l2cap.h"
31 #include "btif_sock_sdp.h"
32 #include "btif_util.h"
33 #include "osi/include/thread.h"
34 
35 static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *uuid, int channel, int *sock_fd, int flags);
36 static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t *uuid, int channel, int *sock_fd, int flags);
37 
38 static void btsock_signaled(int fd, int type, int flags, uint32_t user_id);
39 
40 static int thread_handle = -1;
41 static thread_t *thread;
42 
btif_sock_get_interface(void)43 btsock_interface_t *btif_sock_get_interface(void) {
44   static btsock_interface_t interface = {
45     sizeof(interface),
46     btsock_listen,
47     btsock_connect
48   };
49 
50 
51   return &interface;
52 }
53 
btif_sock_init(void)54 bt_status_t btif_sock_init(void) {
55   assert(thread_handle == -1);
56   assert(thread == NULL);
57 
58   btsock_thread_init();
59   thread_handle = btsock_thread_create(btsock_signaled, NULL);
60   if (thread_handle == -1) {
61     LOG_ERROR("%s unable to create btsock_thread.", __func__);
62     goto error;
63   }
64 
65   bt_status_t status = btsock_rfc_init(thread_handle);
66   if (status != BT_STATUS_SUCCESS) {
67     LOG_ERROR("%s error initializing RFCOMM sockets: %d", __func__, status);
68     goto error;
69   }
70 
71   status = btsock_l2cap_init(thread_handle);
72   if (status != BT_STATUS_SUCCESS) {
73     LOG_ERROR("%s error initializing L2CAP sockets: %d", __func__, status);
74     goto error;
75   }
76 
77   thread = thread_new("btif_sock");
78   if (!thread) {
79     LOG_ERROR("%s error creating new thread.", __func__);
80     btsock_rfc_cleanup();
81     goto error;
82   }
83 
84   status = btsock_sco_init(thread);
85   if (status != BT_STATUS_SUCCESS) {
86     LOG_ERROR("%s error initializing SCO sockets: %d", __func__, status);
87     btsock_rfc_cleanup();
88     goto error;
89   }
90 
91   return BT_STATUS_SUCCESS;
92 
93 error:;
94   thread_free(thread);
95   thread = NULL;
96   if (thread_handle != -1)
97     btsock_thread_exit(thread_handle);
98   thread_handle = -1;
99   return BT_STATUS_FAIL;
100 }
101 
btif_sock_cleanup(void)102 void btif_sock_cleanup(void) {
103   if (thread_handle == -1)
104     return;
105 
106   thread_stop(thread);
107   thread_join(thread);
108   btsock_thread_exit(thread_handle);
109   btsock_rfc_cleanup();
110   btsock_sco_cleanup();
111   btsock_l2cap_cleanup();
112   thread_free(thread);
113   thread_handle = -1;
114   thread = NULL;
115 }
116 
btsock_listen(btsock_type_t type,const char * service_name,const uint8_t * service_uuid,int channel,int * sock_fd,int flags)117 static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *service_uuid, int channel, int *sock_fd, int flags) {
118   if((flags & BTSOCK_FLAG_NO_SDP) == 0) {
119       assert(service_uuid != NULL || channel > 0);
120       assert(sock_fd != NULL);
121   }
122 
123   *sock_fd = INVALID_FD;
124   bt_status_t status = BT_STATUS_FAIL;
125 
126   switch (type) {
127     case BTSOCK_RFCOMM:
128       status = btsock_rfc_listen(service_name, service_uuid, channel, sock_fd, flags);
129       break;
130     case BTSOCK_L2CAP:
131       status = btsock_l2cap_listen(service_name, channel, sock_fd, flags);
132       break;
133 
134     case BTSOCK_SCO:
135       status = btsock_sco_listen(sock_fd, flags);
136       break;
137 
138     default:
139       LOG_ERROR("%s unknown/unsupported socket type: %d", __func__, type);
140       status = BT_STATUS_UNSUPPORTED;
141       break;
142   }
143   return status;
144 }
145 
btsock_connect(const bt_bdaddr_t * bd_addr,btsock_type_t type,const uint8_t * uuid,int channel,int * sock_fd,int flags)146 static bt_status_t btsock_connect(const bt_bdaddr_t *bd_addr, btsock_type_t type, const uint8_t *uuid, int channel, int *sock_fd, int flags) {
147   assert(uuid != NULL || channel > 0);
148   assert(bd_addr != NULL);
149   assert(sock_fd != NULL);
150 
151   *sock_fd = INVALID_FD;
152   bt_status_t status = BT_STATUS_FAIL;
153 
154   switch (type) {
155     case BTSOCK_RFCOMM:
156       status = btsock_rfc_connect(bd_addr, uuid, channel, sock_fd, flags);
157       break;
158 
159     case BTSOCK_L2CAP:
160       status = btsock_l2cap_connect(bd_addr, channel, sock_fd, flags);
161       break;
162 
163     case BTSOCK_SCO:
164       status = btsock_sco_connect(bd_addr, sock_fd, flags);
165       break;
166 
167     default:
168       LOG_ERROR("%s unknown/unsupported socket type: %d", __func__, type);
169       status = BT_STATUS_UNSUPPORTED;
170       break;
171   }
172   return status;
173 }
174 
btsock_signaled(int fd,int type,int flags,uint32_t user_id)175 static void btsock_signaled(int fd, int type, int flags, uint32_t user_id) {
176   switch (type) {
177     case BTSOCK_RFCOMM:
178       btsock_rfc_signaled(fd, flags, user_id);
179       break;
180     case BTSOCK_L2CAP:
181       btsock_l2cap_signaled(fd, flags, user_id);
182       break;
183     default:
184       assert(false && "Invalid socket type");
185       break;
186   }
187 }
188