1// 2// Copyright 2015 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 "hci_transport" 18 19#include "vendor_libs/test_vendor_lib/include/hci_transport.h" 20 21#include "base/logging.h" 22#include "base/bind.h" 23#include "base/thread_task_runner_handle.h" 24 25extern "C" { 26#include <sys/socket.h> 27 28#include "stack/include/hcidefs.h" 29#include "osi/include/log.h" 30} // extern "C" 31 32namespace test_vendor_lib { 33 34HciTransport::HciTransport() : weak_ptr_factory_(this) {} 35 36void HciTransport::CloseHciFd() { 37 hci_fd_.reset(nullptr); 38} 39 40void HciTransport::CloseVendorFd() { 41 vendor_fd_.reset(nullptr); 42} 43 44int HciTransport::GetHciFd() const { 45 return hci_fd_->get(); 46} 47 48int HciTransport::GetVendorFd() const { 49 return vendor_fd_->get(); 50} 51 52bool HciTransport::SetUp() { 53 int socketpair_fds[2]; 54 // TODO(dennischeng): Use SOCK_SEQPACKET here. 55 const int success = socketpair(AF_LOCAL, SOCK_STREAM, 0, socketpair_fds); 56 if (success < 0) 57 return false; 58 hci_fd_.reset(new base::ScopedFD(socketpair_fds[0])); 59 vendor_fd_.reset(new base::ScopedFD(socketpair_fds[1])); 60 return true; 61} 62 63void HciTransport::OnFileCanReadWithoutBlocking(int fd) { 64 CHECK(fd == GetVendorFd()); 65 LOG_INFO(LOG_TAG, "Event ready in HciTransport on fd: %d.", fd); 66 67 const serial_data_type_t packet_type = packet_stream_.ReceivePacketType(fd); 68 switch (packet_type) { 69 case (DATA_TYPE_COMMAND): { 70 ReceiveReadyCommand(); 71 break; 72 } 73 74 case (DATA_TYPE_ACL): { 75 LOG_INFO(LOG_TAG, "ACL data packets not currently supported."); 76 break; 77 } 78 79 case (DATA_TYPE_SCO): { 80 LOG_INFO(LOG_TAG, "SCO data packets not currently supported."); 81 break; 82 } 83 84 // TODO(dennischeng): Add debug level assert here. 85 default: { 86 LOG_INFO(LOG_TAG, "Error received an invalid packet type from the HCI."); 87 break; 88 } 89 } 90} 91 92void HciTransport::ReceiveReadyCommand() const { 93 std::unique_ptr<CommandPacket> command = 94 packet_stream_.ReceiveCommand(GetVendorFd()); 95 LOG_INFO(LOG_TAG, "Received command packet."); 96 command_handler_(std::move(command)); 97} 98 99void HciTransport::RegisterCommandHandler( 100 std::function<void(std::unique_ptr<CommandPacket>)> callback) { 101 command_handler_ = callback; 102} 103 104void HciTransport::OnFileCanWriteWithoutBlocking(int fd) { 105 CHECK(fd == GetVendorFd()); 106 if (!outbound_events_.empty()) { 107 base::TimeTicks current_time = base::TimeTicks::Now(); 108 auto it = outbound_events_.begin(); 109 // Check outbound events for events that can be sent, i.e. events with a 110 // timestamp before the current time. Stop sending events when 111 // |packet_stream_| fails writing. 112 for (auto it = outbound_events_.begin(); it != outbound_events_.end();) { 113 if ((*it)->GetTimeStamp() > current_time) { 114 ++it; 115 continue; 116 } 117 if (!packet_stream_.SendEvent((*it)->GetEvent(), fd)) 118 return; 119 it = outbound_events_.erase(it); 120 } 121 } 122} 123 124void HciTransport::AddEventToOutboundEvents( 125 std::unique_ptr<TimeStampedEvent> event) { 126 outbound_events_.push_back(std::move(event)); 127} 128 129void HciTransport::PostEventResponse(std::unique_ptr<EventPacket> event) { 130 AddEventToOutboundEvents( 131 std::make_unique<TimeStampedEvent>(std::move(event))); 132} 133 134void HciTransport::PostDelayedEventResponse(std::unique_ptr<EventPacket> event, 135 base::TimeDelta delay) { 136 // TODO(dennischeng): When it becomes available for MessageLoopForIO, use the 137 // thread's task runner to post |PostEventResponse| as a delayed task, being 138 // sure to CHECK the appropriate task runner attributes using 139 // base::ThreadTaskRunnerHandle. 140 141 // The system does not support high resolution timing and the clock could be 142 // as coarse as ~15.6 ms so the event is sent without a delay to avoid 143 // inconsistent event responses. 144 if (!base::TimeTicks::IsHighResolution()) { 145 LOG_INFO(LOG_TAG, 146 "System does not support high resolution timing. Sending event " 147 "without delay."); 148 PostEventResponse(std::move(event)); 149 } 150 151 LOG_INFO(LOG_TAG, "Posting event response with delay of %lld ms.", 152 delay.InMilliseconds()); 153 154 AddEventToOutboundEvents( 155 std::make_unique<TimeStampedEvent>(std::move(event), delay)); 156} 157 158HciTransport::TimeStampedEvent::TimeStampedEvent( 159 std::unique_ptr<EventPacket> event, base::TimeDelta delay) 160 : event_(std::move(event)), time_stamp_(base::TimeTicks::Now() + delay) {} 161 162HciTransport::TimeStampedEvent::TimeStampedEvent( 163 std::unique_ptr<EventPacket> event) 164 : event_(std::move(event)), time_stamp_(base::TimeTicks::UnixEpoch()) {} 165 166const base::TimeTicks& HciTransport::TimeStampedEvent::GetTimeStamp() const { 167 return time_stamp_; 168} 169 170const EventPacket& HciTransport::TimeStampedEvent::GetEvent() { 171 return *(event_.get()); 172} 173 174} // namespace test_vendor_lib 175