2 // Copyright 2015 The Android Open Source Project
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "hci_transport"
19 #include "vendor_libs/test_vendor_lib/include/hci_transport.h"
22 #include "stack/include/hcidefs.h"
23 #include "osi/include/log.h"
25 #include <sys/ioctl.h>
26 #include <sys/socket.h>
34 // The maximum number of events in the epoll event buffer.
35 const int kMaxEpollEvents = 10;
38 namespace test_vendor_lib {
40 // Global HciTransport instance used in the vendor library.
41 // TODO(dennischeng): Should this be moved to an unnamed namespace?
42 HciTransport* g_transporter = nullptr;
44 HciTransport::HciTransport() : epoll_fd_(-1), connected_(false) {}
46 HciTransport::~HciTransport() {
50 bool HciTransport::ConfigEpoll() {
51 epoll_fd_ = epoll_create1(EPOLL_CLOEXEC);
53 event.events = EPOLLIN;
54 event.data.fd = socketpair_fds_[0];
55 return epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, socketpair_fds_[0], &event) >= 0;
58 int HciTransport::GetHciFd() const {
59 return socketpair_fds_[1];
63 HciTransport* HciTransport::Get() {
64 // Initialize should have been called already.
65 // TODO(dennischeng): use CHECK and DCHECK when libbase is imported.
66 assert(g_transporter);
71 void HciTransport::Initialize() {
72 // Multiple calls to Initialize should not be made.
73 // TODO(dennischeng): use CHECK and DCHECK when libbase is imported.
74 assert(!g_transporter);
75 g_transporter = new HciTransport();
79 void HciTransport::CleanUp() {
81 g_transporter = nullptr;
84 bool HciTransport::Connect() {
86 LOG_ERROR(LOG_TAG, "Error: transporter is already connected.");
90 // TODO(dennischeng): Use SOCK_SEQPACKET here.
91 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, socketpair_fds_) < 0) {
92 LOG_ERROR(LOG_TAG, "Error: creating socketpair in HciTransport.");
96 // Set the descriptor for the packet stream object. |packet_stream_| will take
97 // ownership of the descriptor.
98 packet_stream_.SetFd(socketpair_fds_[0]);
100 // Initialize epoll instance and set the file descriptor to listen on.
101 if (ConfigEpoll() < 0) {
102 LOG_ERROR(LOG_TAG, "Error: registering hci listener with epoll instance.");
110 bool HciTransport::Listen() {
111 epoll_event event_buffer[kMaxEpollEvents];
114 // Check for ready events.
115 if ((num_ready = epoll_wait(epoll_fd_, event_buffer, kMaxEpollEvents, -1)) <
117 LOG_ERROR(LOG_TAG, "Error: epoll wait.");
121 return ReceiveReadyPackets(*event_buffer, num_ready);
124 bool HciTransport::ReceiveReadyPackets(const epoll_event& event_buffer,
126 for (int i = 0; i < num_ready; ++i) {
127 // Event has data ready to be read.
128 if ((&event_buffer)[i].events & EPOLLIN) {
129 LOG_INFO(LOG_TAG, "Event ready in HciTransport.");
130 serial_data_type_t packet_type = packet_stream_.ReceivePacketType();
132 switch (packet_type) {
133 case (DATA_TYPE_COMMAND): {
134 ReceiveReadyCommand();
138 case (DATA_TYPE_ACL): {
139 LOG_INFO(LOG_TAG, "ACL data packets not currently supported.");
143 case (DATA_TYPE_SCO): {
144 LOG_INFO(LOG_TAG, "SCO data packets not currently supported.");
148 // TODO(dennischeng): Add debug level assert here.
151 "Error received an invalid packet type from the HCI.");
160 void HciTransport::ReceiveReadyCommand() {
161 std::unique_ptr<CommandPacket> command =
162 packet_stream_.ReceiveCommand();
163 command_callback_(std::move(command));
166 void HciTransport::RegisterCommandCallback(
167 std::function<void(std::unique_ptr<CommandPacket>)> callback) {
168 command_callback_ = callback;
171 void HciTransport::SendEvent(const EventPacket& event) {
172 packet_stream_.SendEvent(event);
175 } // namespace test_vendor_lib