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 35 BluetoothHci::BluetoothHci() 36 : deathRecipient(new BluetoothDeathRecipient(this)) {} 37 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 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 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 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 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