Home | History | Annotate | Download | only in src
      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 
     25 extern "C" {
     26 #include <sys/socket.h>
     27 
     28 #include "stack/include/hcidefs.h"
     29 #include "osi/include/log.h"
     30 }  // extern "C"
     31 
     32 namespace test_vendor_lib {
     33 
     34 HciTransport::HciTransport() : weak_ptr_factory_(this) {}
     35 
     36 void HciTransport::CloseHciFd() {
     37   hci_fd_.reset(nullptr);
     38 }
     39 
     40 void HciTransport::CloseVendorFd() {
     41   vendor_fd_.reset(nullptr);
     42 }
     43 
     44 int HciTransport::GetHciFd() const {
     45   return hci_fd_->get();
     46 }
     47 
     48 int HciTransport::GetVendorFd() const {
     49   return vendor_fd_->get();
     50 }
     51 
     52 bool 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 
     63 void 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 
     92 void 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 
     99 void HciTransport::RegisterCommandHandler(
    100     std::function<void(std::unique_ptr<CommandPacket>)> callback) {
    101   command_handler_ = callback;
    102 }
    103 
    104 void 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 
    124 void HciTransport::AddEventToOutboundEvents(
    125     std::unique_ptr<TimeStampedEvent> event) {
    126   outbound_events_.push_back(std::move(event));
    127 }
    128 
    129 void HciTransport::PostEventResponse(std::unique_ptr<EventPacket> event) {
    130   AddEventToOutboundEvents(
    131       std::make_unique<TimeStampedEvent>(std::move(event)));
    132 }
    133 
    134 void 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 
    158 HciTransport::TimeStampedEvent::TimeStampedEvent(
    159     std::unique_ptr<EventPacket> event, base::TimeDelta delay)
    160     : event_(std::move(event)), time_stamp_(base::TimeTicks::Now() + delay) {}
    161 
    162 HciTransport::TimeStampedEvent::TimeStampedEvent(
    163     std::unique_ptr<EventPacket> event)
    164     : event_(std::move(event)), time_stamp_(base::TimeTicks::UnixEpoch()) {}
    165 
    166 const base::TimeTicks& HciTransport::TimeStampedEvent::GetTimeStamp() const {
    167   return time_stamp_;
    168 }
    169 
    170 const EventPacket& HciTransport::TimeStampedEvent::GetEvent() {
    171   return *(event_.get());
    172 }
    173 
    174 }  // namespace test_vendor_lib
    175