1f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng//
2f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// Copyright 2015 The Android Open Source Project
3f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng//
4f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// Licensed under the Apache License, Version 2.0 (the "License");
5f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// you may not use this file except in compliance with the License.
6f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// You may obtain a copy of the License at
7f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng//
8f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// http://www.apache.org/licenses/LICENSE-2.0
9f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng//
10f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// Unless required by applicable law or agreed to in writing, software
11f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// distributed under the License is distributed on an "AS IS" BASIS,
12f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// See the License for the specific language governing permissions and
14f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng// limitations under the License.
15f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng//
16f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
17f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng#define LOG_TAG "hci_transport"
18f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
19f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng#include "vendor_libs/test_vendor_lib/include/hci_transport.h"
20f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
21a7077ee9b7482708fa7272837a527f64bb470988Dennis Cheng#include "base/logging.h"
22bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng#include "base/bind.h"
23bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng#include "base/thread_task_runner_handle.h"
24f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
25a7077ee9b7482708fa7272837a527f64bb470988Dennis Chengextern "C" {
26f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng#include <sys/socket.h>
27a7077ee9b7482708fa7272837a527f64bb470988Dennis Cheng
28a7077ee9b7482708fa7272837a527f64bb470988Dennis Cheng#include "stack/include/hcidefs.h"
29a7077ee9b7482708fa7272837a527f64bb470988Dennis Cheng#include "osi/include/log.h"
30f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng}  // extern "C"
31f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
32f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Chengnamespace test_vendor_lib {
33f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
34bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis ChengHciTransport::HciTransport() : weak_ptr_factory_(this) {}
35bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng
362fc0eba951081bddd15a3482f2189a9125dac48aDennis Chengvoid HciTransport::CloseHciFd() {
372d96c88025c80d4d7e0e341cfdbf278596340b66Dennis Cheng  hci_fd_.reset(nullptr);
382fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng}
392fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng
402e00ba9b74536ce9a0d1adf78f92e6478563e49bDennis Chengvoid HciTransport::CloseVendorFd() {
412e00ba9b74536ce9a0d1adf78f92e6478563e49bDennis Cheng  vendor_fd_.reset(nullptr);
422e00ba9b74536ce9a0d1adf78f92e6478563e49bDennis Cheng}
432e00ba9b74536ce9a0d1adf78f92e6478563e49bDennis Cheng
44f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Chengint HciTransport::GetHciFd() const {
452fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng  return hci_fd_->get();
46f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng}
47f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
48b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Chengint HciTransport::GetVendorFd() const {
492fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng  return vendor_fd_->get();
50f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng}
51f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
52b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Chengbool HciTransport::SetUp() {
532fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng  int socketpair_fds[2];
54f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng  // TODO(dennischeng): Use SOCK_SEQPACKET here.
552fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng  const int success = socketpair(AF_LOCAL, SOCK_STREAM, 0, socketpair_fds);
566f5f0540f1557c87349d9f3378a90979c175ed1dDennis Cheng  if (success < 0)
572fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng    return false;
582fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng  hci_fd_.reset(new base::ScopedFD(socketpair_fds[0]));
592fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng  vendor_fd_.reset(new base::ScopedFD(socketpair_fds[1]));
602fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng  return true;
61f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng}
62f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
63b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Chengvoid HciTransport::OnFileCanReadWithoutBlocking(int fd) {
648bb61fe28ac339276acf1b5b1616a6e56e2cccacDennis Cheng  CHECK(fd == GetVendorFd());
652d96c88025c80d4d7e0e341cfdbf278596340b66Dennis Cheng  LOG_INFO(LOG_TAG, "Event ready in HciTransport on fd: %d.", fd);
663c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng
672d96c88025c80d4d7e0e341cfdbf278596340b66Dennis Cheng  const serial_data_type_t packet_type = packet_stream_.ReceivePacketType(fd);
683c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng  switch (packet_type) {
693c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    case (DATA_TYPE_COMMAND): {
703c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng      ReceiveReadyCommand();
71b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Cheng      break;
723c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    }
733c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng
743c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    case (DATA_TYPE_ACL): {
753c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng      LOG_INFO(LOG_TAG, "ACL data packets not currently supported.");
76b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Cheng      break;
773c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    }
783c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng
793c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    case (DATA_TYPE_SCO): {
803c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng      LOG_INFO(LOG_TAG, "SCO data packets not currently supported.");
81b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Cheng      break;
823c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    }
833c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng
843c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    // TODO(dennischeng): Add debug level assert here.
853c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    default: {
86b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Cheng      LOG_INFO(LOG_TAG, "Error received an invalid packet type from the HCI.");
872fc0eba951081bddd15a3482f2189a9125dac48aDennis Cheng      break;
883c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng    }
893c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng  }
903c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng}
913c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng
923c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Chengvoid HciTransport::ReceiveReadyCommand() const {
93f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng  std::unique_ptr<CommandPacket> command =
942d96c88025c80d4d7e0e341cfdbf278596340b66Dennis Cheng      packet_stream_.ReceiveCommand(GetVendorFd());
953c0ea3e5a5aca269283854d8f2f584ad0699c951Dennis Cheng  LOG_INFO(LOG_TAG, "Received command packet.");
96b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Cheng  command_handler_(std::move(command));
97f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng}
98f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
99b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Chengvoid HciTransport::RegisterCommandHandler(
100f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng    std::function<void(std::unique_ptr<CommandPacket>)> callback) {
101b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Cheng  command_handler_ = callback;
102f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng}
103f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
104b2d45eb7cbd4f2de5f0101915981a87392ccf625Dennis Chengvoid HciTransport::OnFileCanWriteWithoutBlocking(int fd) {
1058bb61fe28ac339276acf1b5b1616a6e56e2cccacDennis Cheng  CHECK(fd == GetVendorFd());
106bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng  if (!outbound_events_.empty()) {
1077a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    base::TimeTicks current_time = base::TimeTicks::Now();
1087a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    auto it = outbound_events_.begin();
1097a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    // Check outbound events for events that can be sent, i.e. events with a
1107a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    // timestamp before the current time. Stop sending events when
1117a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    // |packet_stream_| fails writing.
1127a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    for (auto it = outbound_events_.begin(); it != outbound_events_.end();) {
1137a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng      if ((*it)->GetTimeStamp() > current_time) {
1147a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng        ++it;
1157a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng        continue;
1167a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng      }
1177a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng      if (!packet_stream_.SendEvent((*it)->GetEvent(), fd))
1187a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng        return;
1197a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng      it = outbound_events_.erase(it);
1207a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    }
121bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng  }
122bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng}
123bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng
1247a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Chengvoid HciTransport::AddEventToOutboundEvents(
1257a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    std::unique_ptr<TimeStampedEvent> event) {
1267a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  outbound_events_.push_back(std::move(event));
1277a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng}
1287a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng
1297a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Chengvoid HciTransport::PostEventResponse(std::unique_ptr<EventPacket> event) {
1302e00ba9b74536ce9a0d1adf78f92e6478563e49bDennis Cheng  AddEventToOutboundEvents(
1312e00ba9b74536ce9a0d1adf78f92e6478563e49bDennis Cheng      std::make_unique<TimeStampedEvent>(std::move(event)));
132bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng}
133bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng
134bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Chengvoid HciTransport::PostDelayedEventResponse(std::unique_ptr<EventPacket> event,
135bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng                                            base::TimeDelta delay) {
1367a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  // TODO(dennischeng): When it becomes available for MessageLoopForIO, use the
1377a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  // thread's task runner to post |PostEventResponse| as a delayed task, being
1387a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  // sure to CHECK the appropriate task runner attributes using
1397a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  // base::ThreadTaskRunnerHandle.
1407a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng
1417a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  // The system does not support high resolution timing and the clock could be
1427a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  // as coarse as ~15.6 ms so the event is sent without a delay to avoid
1437a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  // inconsistent event responses.
1447a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  if (!base::TimeTicks::IsHighResolution()) {
1457a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    LOG_INFO(LOG_TAG,
1467a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng              "System does not support high resolution timing. Sending event "
1477a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng              "without delay.");
1487a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    PostEventResponse(std::move(event));
1497a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  }
150bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng
151bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng  LOG_INFO(LOG_TAG, "Posting event response with delay of %lld ms.",
152bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng           delay.InMilliseconds());
153bf7db3143fda4dc8391c92ec25dc93b9725ec225Dennis Cheng
1547a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  AddEventToOutboundEvents(
1557a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng      std::make_unique<TimeStampedEvent>(std::move(event), delay));
1567a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng}
1577a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng
1587a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis ChengHciTransport::TimeStampedEvent::TimeStampedEvent(
1597a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    std::unique_ptr<EventPacket> event, base::TimeDelta delay)
1607a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    : event_(std::move(event)), time_stamp_(base::TimeTicks::Now() + delay) {}
1617a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng
1627a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis ChengHciTransport::TimeStampedEvent::TimeStampedEvent(
1637a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    std::unique_ptr<EventPacket> event)
1647a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng    : event_(std::move(event)), time_stamp_(base::TimeTicks::UnixEpoch()) {}
1657a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng
1667a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Chengconst base::TimeTicks& HciTransport::TimeStampedEvent::GetTimeStamp() const {
1677a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  return time_stamp_;
1687a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng}
1697a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng
1707a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Chengconst EventPacket& HciTransport::TimeStampedEvent::GetEvent() {
1717a87e719982e874c1d23e106a4dbc8dd2ede97bdDennis Cheng  return *(event_.get());
172f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng}
173f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng
174f3b1820e1676261886a6537e1f6abac6a35ed6d4Dennis Cheng}  // namespace test_vendor_lib
175