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
35static bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *uuid, int channel, int *sock_fd, int flags);
36static 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
38static void btsock_signaled(int fd, int type, int flags, uint32_t user_id);
39
40static int thread_handle = -1;
41static thread_t *thread;
42
43btsock_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
54bt_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
93error:;
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
102void 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
117static 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
146static 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
175static 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