15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
3fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati *  Copyright (C) 2014 Google, Inc.
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19985d4b6986b787839ba72470f96be841f7721a17Marie Janssen#define LOG_TAG "bt_btif_sock"
20985d4b6986b787839ba72470f96be841f7721a17Marie Janssen
21fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati#include <assert.h>
22db554581079863974af8e1289646f5deea6fc044Marie Janssen
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <hardware/bluetooth.h>
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <hardware/bt_sock.h>
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bta_api.h"
27fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati#include "btif_common.h"
28db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "btif_sock_l2cap.h"
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btif_sock_rfc.h"
30e93ac125b887651e835fe59f4d1f9b3c5baa844cIan McKellar#include "btif_sock_sco.h"
318372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz#include "btif_sock_sdp.h"
32db554581079863974af8e1289646f5deea6fc044Marie Janssen#include "btif_sock_thread.h"
330229bd4f183266b103daa18cf95c175aabe87217Adam Lesinski#include "btif_uid.h"
34fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati#include "btif_util.h"
350f9b91e150e153229235c163861198e23600e636Sharvil Nanavati#include "osi/include/thread.h"
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
370229bd4f183266b103daa18cf95c175aabe87217Adam Lesinskistatic bt_status_t btsock_listen(btsock_type_t type, const char *service_name, const uint8_t *uuid, int channel, int *sock_fd, int flags, int app_uid);
380229bd4f183266b103daa18cf95c175aabe87217Adam Lesinskistatic 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, int app_uid);
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Projectstatic void btsock_signaled(int fd, int type, int flags, uint32_t user_id);
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
42fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavatistatic int thread_handle = -1;
43c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavatistatic thread_t *thread;
44fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
45fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavatibtsock_interface_t *btif_sock_get_interface(void) {
46fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  static btsock_interface_t interface = {
47fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    sizeof(interface),
48fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    btsock_listen,
49fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    btsock_connect
50fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  };
51fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
528372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz
53fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  return &interface;
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
55fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
560229bd4f183266b103daa18cf95c175aabe87217Adam Lesinskibt_status_t btif_sock_init(uid_set_t* uid_set) {
57fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  assert(thread_handle == -1);
58c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  assert(thread == NULL);
59fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
60fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  btsock_thread_init();
61fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  thread_handle = btsock_thread_create(btsock_signaled, NULL);
62fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  if (thread_handle == -1) {
63db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "%s unable to create btsock_thread.", __func__);
64c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati    goto error;
65fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  }
66fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
670229bd4f183266b103daa18cf95c175aabe87217Adam Lesinski  bt_status_t status = btsock_rfc_init(thread_handle, uid_set);
68fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  if (status != BT_STATUS_SUCCESS) {
69db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "%s error initializing RFCOMM sockets: %d", __func__, status);
70c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati    goto error;
71c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  }
72c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati
730229bd4f183266b103daa18cf95c175aabe87217Adam Lesinski  status = btsock_l2cap_init(thread_handle, uid_set);
748372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz  if (status != BT_STATUS_SUCCESS) {
75db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "%s error initializing L2CAP sockets: %d", __func__, status);
768372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz    goto error;
778372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz  }
788372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz
79c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  thread = thread_new("btif_sock");
80c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  if (!thread) {
81db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "%s error creating new thread.", __func__);
82c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati    btsock_rfc_cleanup();
83c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati    goto error;
84fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  }
85fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
86c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  status = btsock_sco_init(thread);
87fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  if (status != BT_STATUS_SUCCESS) {
88db554581079863974af8e1289646f5deea6fc044Marie Janssen    LOG_ERROR(LOG_TAG, "%s error initializing SCO sockets: %d", __func__, status);
895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    btsock_rfc_cleanup();
90c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati    goto error;
91fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  }
92fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
93fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  return BT_STATUS_SUCCESS;
94c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati
95c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavatierror:;
96c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  thread_free(thread);
97c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  thread = NULL;
98c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  if (thread_handle != -1)
99c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati    btsock_thread_exit(thread_handle);
100c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  thread_handle = -1;
1010229bd4f183266b103daa18cf95c175aabe87217Adam Lesinski  uid_set = NULL;
102c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  return BT_STATUS_FAIL;
1035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
105fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavativoid btif_sock_cleanup(void) {
106fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  if (thread_handle == -1)
107fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    return;
108fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
109c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  thread_stop(thread);
110c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  thread_join(thread);
111fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  btsock_thread_exit(thread_handle);
112fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  btsock_rfc_cleanup();
113fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  btsock_sco_cleanup();
1148372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz  btsock_l2cap_cleanup();
115c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  thread_free(thread);
116fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  thread_handle = -1;
117c8aaee2c9393ef28fdbdcf28be80172f387205fcSharvil Nanavati  thread = NULL;
1185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
119fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
1200229bd4f183266b103daa18cf95c175aabe87217Adam Lesinskistatic 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, int app_uid) {
1218372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz  if((flags & BTSOCK_FLAG_NO_SDP) == 0) {
1228372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz      assert(service_uuid != NULL || channel > 0);
1238372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz      assert(sock_fd != NULL);
1248372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz  }
125fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
126fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  *sock_fd = INVALID_FD;
127fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  bt_status_t status = BT_STATUS_FAIL;
128fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
129fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  switch (type) {
130fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    case BTSOCK_RFCOMM:
1310229bd4f183266b103daa18cf95c175aabe87217Adam Lesinski      status = btsock_rfc_listen(service_name, service_uuid, channel, sock_fd, flags, app_uid);
132fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      break;
1338372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz    case BTSOCK_L2CAP:
1340229bd4f183266b103daa18cf95c175aabe87217Adam Lesinski      status = btsock_l2cap_listen(service_name, channel, sock_fd, flags, app_uid);
1358372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz      break;
136fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
137fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    case BTSOCK_SCO:
138fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      status = btsock_sco_listen(sock_fd, flags);
139fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      break;
140fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
141fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    default:
142db554581079863974af8e1289646f5deea6fc044Marie Janssen      LOG_ERROR(LOG_TAG, "%s unknown/unsupported socket type: %d", __func__, type);
143fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      status = BT_STATUS_UNSUPPORTED;
144fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      break;
145fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  }
146fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  return status;
1475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
148fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
1490229bd4f183266b103daa18cf95c175aabe87217Adam Lesinskistatic 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, int app_uid) {
150fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  assert(uuid != NULL || channel > 0);
151fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  assert(bd_addr != NULL);
152fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  assert(sock_fd != NULL);
153fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
154fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  *sock_fd = INVALID_FD;
155fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  bt_status_t status = BT_STATUS_FAIL;
156fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
157fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  switch (type) {
158fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    case BTSOCK_RFCOMM:
1590229bd4f183266b103daa18cf95c175aabe87217Adam Lesinski      status = btsock_rfc_connect(bd_addr, uuid, channel, sock_fd, flags, app_uid);
160fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      break;
161fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
1628372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz    case BTSOCK_L2CAP:
1630229bd4f183266b103daa18cf95c175aabe87217Adam Lesinski      status = btsock_l2cap_connect(bd_addr, channel, sock_fd, flags, app_uid);
1648372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz      break;
1658372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz
166fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    case BTSOCK_SCO:
167fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      status = btsock_sco_connect(bd_addr, sock_fd, flags);
168fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      break;
169fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
170fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    default:
171db554581079863974af8e1289646f5deea6fc044Marie Janssen      LOG_ERROR(LOG_TAG, "%s unknown/unsupported socket type: %d", __func__, type);
172fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      status = BT_STATUS_UNSUPPORTED;
173fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      break;
174fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  }
175fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  return status;
176fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati}
177fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati
178fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavatistatic void btsock_signaled(int fd, int type, int flags, uint32_t user_id) {
179fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  switch (type) {
180fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    case BTSOCK_RFCOMM:
181fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      btsock_rfc_signaled(fd, flags, user_id);
182fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      break;
1838372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz    case BTSOCK_L2CAP:
1848372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz      btsock_l2cap_signaled(fd, flags, user_id);
1858372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz      break;
186fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati    default:
187fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      assert(false && "Invalid socket type");
188fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati      break;
189fe4ec6ba40c011cfd3599d45fbda3c6575a07189Sharvil Nanavati  }
1905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
191