• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #define LOG_TAG "android.hardware.bluetooth@1.0.hikey"
18 
19 #include "bluetooth_hci.h"
20 
21 #include <android-base/logging.h>
22 #include <sys/ioctl.h>
23 #include <sys/socket.h>
24 #include <unistd.h>
25 #include <utils/Log.h>
26 
27 namespace android {
28 namespace hardware {
29 namespace bluetooth {
30 namespace V1_0 {
31 namespace hikey {
32 
33 using android::hardware::hidl_vec;
34 
BluetoothHci()35 BluetoothHci::BluetoothHci()
36     : deathRecipient(new BluetoothDeathRecipient(this)) {}
37 
initialize(const::android::sp<IBluetoothHciCallbacks> & cb)38 Return<void> BluetoothHci::initialize(
39     const ::android::sp<IBluetoothHciCallbacks>& cb) {
40   ALOGI("BluetoothHci::initialize()");
41 
42   hci_tty_fd_ = open("/dev/hci_tty", O_RDWR);
43   if (hci_tty_fd_ < 0) {
44     ALOGE("%s: Can't open hci_tty (%s)", __func__, strerror(errno));
45     cb->initializationComplete(Status::INITIALIZATION_ERROR);
46     return Void();
47   }
48 
49   event_cb_ = cb;
50   event_cb_->linkToDeath(deathRecipient, 0);
51 
52   hci_ = new hci::H4Protocol(
53       hci_tty_fd_,
54       [cb](const hidl_vec<uint8_t>& packet) { cb->hciEventReceived(packet); },
55       [cb](const hidl_vec<uint8_t>& packet) { cb->aclDataReceived(packet); },
56       [cb](const hidl_vec<uint8_t>& packet) { cb->scoDataReceived(packet); });
57 
58   // Use a socket pair to enforce the TI FIONREAD requirement.
59   int sockfd[2];
60   socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
61   int shim_fd = sockfd[0];
62   int for_hci = sockfd[1];
63 
64   fd_watcher_.WatchFdForNonBlockingReads(hci_tty_fd_, [this, shim_fd](int fd) {
65     int tty_bytes = 0;
66     if (TEMP_FAILURE_RETRY(ioctl(fd, FIONREAD, &tty_bytes)))
67       ALOGE("%s:FIONREAD %s", __func__, strerror(errno));
68     ALOGV("%s:tty_bytes = %d", __func__, tty_bytes);
69 
70     uint8_t* tmp_buffer = new uint8_t[tty_bytes];
71     size_t bytes_read = TEMP_FAILURE_RETRY(read(fd, tmp_buffer, tty_bytes));
72     CHECK(static_cast<int>(bytes_read) == tty_bytes);
73     size_t bytes_written =
74         TEMP_FAILURE_RETRY(write(shim_fd, tmp_buffer, tty_bytes));
75     CHECK(static_cast<int>(bytes_written) == tty_bytes);
76     delete[] tmp_buffer;
77   });
78 
79   fd_watcher_.WatchFdForNonBlockingReads(
80       for_hci, [this](int fd) { hci_->OnDataReady(fd); });
81 
82   cb->initializationComplete(Status::SUCCESS);
83   return Void();
84 }
85 
close()86 Return<void> BluetoothHci::close() {
87   ALOGI("BluetoothHci::close()");
88 
89   if (hci_tty_fd_ >= 0) {
90     fd_watcher_.StopWatchingFileDescriptors();
91     ::close(hci_tty_fd_);
92     hci_tty_fd_ = -1;
93   }
94 
95   event_cb_->unlinkToDeath(deathRecipient);
96 
97   if (hci_ != nullptr) {
98     delete hci_;
99     hci_ = nullptr;
100   }
101 
102   return Void();
103 }
104 
sendHciCommand(const hidl_vec<uint8_t> & packet)105 Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& packet) {
106   hci_->Send(HCI_PACKET_TYPE_COMMAND, packet.data(), packet.size());
107   return Void();
108 }
109 
sendAclData(const hidl_vec<uint8_t> & packet)110 Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& packet) {
111   hci_->Send(HCI_PACKET_TYPE_ACL_DATA, packet.data(), packet.size());
112   return Void();
113 }
114 
sendScoData(const hidl_vec<uint8_t> & packet)115 Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& packet) {
116   hci_->Send(HCI_PACKET_TYPE_SCO_DATA, packet.data(), packet.size());
117   return Void();
118 }
119 
120 }  // namespace hikey
121 }  // namespace V1_0
122 }  // namespace bluetooth
123 }  // namespace hardware
124 }  // namespace android
125