1 // Copyright 2023 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 #pragma once 16 #include <lib/fit/function.h> 17 #include <pw_async/dispatcher.h> 18 #include <pw_async/task.h> 19 20 #include <list> 21 #include <memory> 22 #include <optional> 23 #include <queue> 24 #include <unordered_map> 25 #include <unordered_set> 26 27 #include "pw_bluetooth/controller.h" 28 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h" 29 #include "pw_bluetooth_sapphire/internal/host/common/identifier.h" 30 #include "pw_bluetooth_sapphire/internal/host/common/inspectable.h" 31 #include "pw_bluetooth_sapphire/internal/host/common/macros.h" 32 #include "pw_bluetooth_sapphire/internal/host/common/smart_task.h" 33 #include "pw_bluetooth_sapphire/internal/host/common/trace.h" 34 #include "pw_bluetooth_sapphire/internal/host/common/weak_self.h" 35 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h" 36 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h" 37 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h" 38 39 namespace bt::hci { 40 41 // Represents the HCI Bluetooth command channel. Manages HCI command and event 42 // packet control flow. CommandChannel is expected to remain allocated as long 43 // as the host exists. On fatal errors, it is put into an inactive state where 44 // no packets are processed, but it may continue to be accessed by higher layers 45 // until shutdown completes. 46 class CommandChannel final { 47 public: 48 // Starts listening for HCI commands and starts handling commands and events. 49 explicit CommandChannel(pw::bluetooth::Controller* hci, 50 pw::async::Dispatcher& dispatcher); 51 52 ~CommandChannel(); 53 54 // Used to identify an individual HCI command<->event transaction. 55 using TransactionId = size_t; 56 57 enum class EventType { 58 kHciEvent, 59 kLEMetaEvent, 60 kVendorEvent, 61 }; 62 63 // Queues the given |command_packet| to be sent to the controller and returns 64 // a transaction ID. 65 // 66 // This call takes ownership of the contents of |command_packet|. 67 // |command_packet| MUST represent a valid HCI command packet. 68 // 69 // |callback| will be called with all events related to the transaction, 70 // unless the transaction is removed with RemoveQueuedCommand. If the command 71 // results in a CommandStatus event, it will be sent to this callback before 72 // the event with |complete_event_code| is sent. 73 // 74 // Synchronous transactions complete with a CommandComplete HCI event. This 75 // function is the only way to receive a CommandComplete event. 76 // 77 // Most asynchronous transactions return the CommandStatus event and another 78 // event to indicate completion, which should be indicated in 79 // |complete_event_code|. 80 // 81 // If |complete_event_code| is set to kCommandStatus, the transaction is 82 // considered complete when the CommandStatus event is received. 83 // 84 // |complete_event_code| cannot be a code that has been registered for events 85 // via AddEventHandler or its related methods. 86 // 87 // Returns a ID unique to the command transaction, or zero if the parameters 88 // are invalid. This ID will be supplied to |callback| in its |id| parameter 89 // to identify the transaction. 90 // 91 // NOTE: Commands queued are not guaranteed to be finished or sent in order, 92 // although commands with the same opcode will be sent in order, and commands 93 // with the same |complete_event_code| and |subevent_code| will be sent in 94 // order. If strict ordering of commands is required, use 95 // SequentialCommandRunner or callbacks for sequencing. 96 // 97 // See Bluetooth Core Spec v5.0, Volume 2, Part E, Section 4.4 "Command Flow 98 // Control" for more information about the HCI command flow control. 99 using CommandCallback = 100 fit::function<void(TransactionId id, const EventPacket& event_packet)>; 101 TransactionId SendCommand(CommandPacket command_packet, 102 CommandCallback callback, 103 hci_spec::EventCode complete_event_code = 104 hci_spec::kCommandCompleteEventCode); 105 106 // As SendCommand, but the transaction completes on the LE Meta Event. 107 // |le_meta_subevent_code| is a LE Meta Event subevent code as described in 108 // Core Spec v5.2, Vol 4, Part E, Sec 7.7.65. 109 // 110 // |le_meta_subevent_code| cannot be a code that has been registered for 111 // events via AddLEMetaEventHandler. 112 TransactionId SendLeAsyncCommand(CommandPacket command_packet, 113 CommandCallback callback, 114 hci_spec::EventCode le_meta_subevent_code); 115 116 // As SendCommand, but will wait to run this command until there are no 117 // commands with with opcodes specified in |exclude| from executing. This is 118 // useful to prevent running different commands that cannot run concurrently 119 // (i.e. Inquiry and Connect). Two commands with the same opcode will never 120 // run simultaneously. 121 TransactionId SendExclusiveCommand( 122 CommandPacket command_packet, 123 CommandCallback callback, 124 hci_spec::EventCode complete_event_code = 125 hci_spec::kCommandCompleteEventCode, 126 std::unordered_set<hci_spec::OpCode> exclusions = {}); 127 128 // As SendExclusiveCommand, but the transaction completes on the LE Meta Event 129 // with subevent code |le_meta_subevent_code|. 130 TransactionId SendLeAsyncExclusiveCommand( 131 CommandPacket command_packet, 132 CommandCallback callback, 133 std::optional<hci_spec::EventCode> le_meta_subevent_code, 134 std::unordered_set<hci_spec::OpCode> exclusions = {}); 135 136 // If the command identified by |id| has not been sent to the controller, 137 // remove it from the send queue and return true. In this case, its 138 // CommandCallback will not be notified. If the command identified by |id| has 139 // already been sent to the controller or if it does not exist, this has no 140 // effect and returns false. 141 [[nodiscard]] bool RemoveQueuedCommand(TransactionId id); 142 143 // Used to identify an individual HCI event handler that was registered with 144 // this CommandChannel. 145 using EventHandlerId = size_t; 146 147 // Return values for EventCallbacks. 148 enum class EventCallbackResult { 149 // Continue handling this event. 150 kContinue, 151 152 // Remove this event handler. 153 // NOTE: The event callback may still be called again after it has been 154 // removed if the handler 155 // has already been posted to the dispatcher for subsequent events. 156 kRemove 157 }; 158 159 // Callbacks invoked to report generic HCI events excluding CommandComplete 160 // and CommandStatus events. 161 using EventCallback = 162 fit::function<EventCallbackResult(const EventPacket& event_packet)>; 163 164 // Registers an event handler for HCI events that match |event_code|. Incoming 165 // HCI event packets that are not associated with a pending command sequence 166 // will be posted on the given |dispatcher| via the given |event_callback|. 167 // The returned ID can be used to unregister a previously registered event 168 // handler. 169 // 170 // |event_callback| will be invoked for all HCI event packets that match 171 // |event_code|, except for: 172 // 173 // - HCI_CommandStatus events 174 // - HCI_CommandComplete events 175 // - The completion event of the currently pending command packet, if any 176 // 177 // Returns an ID if the handler was successfully registered. Returns zero in 178 // case of an error. 179 // 180 // Multiple handlers can be registered for a given |event_code| at a time. All 181 // handlers that are registered will be called with a reference to the event. 182 // 183 // If an asynchronous command is queued which completes on |event_code|, this 184 // method returns zero. It is good practice to avoid using asynchronous 185 // commands and event handlers for the same event code. SendCommand allows 186 // for queueing multiple asynchronous commands with the same callback. 187 // Alternately a long-lived event handler can be registered with Commands 188 // completing on CommandStatus. 189 // 190 // The following values for |event_code| cannot be passed to this method: 191 // 192 // - HCI_Command_Complete event code 193 // - HCI_Command_Status event code 194 // - HCI_LE_Meta event code (use AddLEMetaEventHandler instead) 195 // - HCI_Vendor_Debug event code (use AddVendorEventHandler instead) 196 EventHandlerId AddEventHandler(hci_spec::EventCode event_code, 197 EventCallback event_callback); 198 199 // Works just like AddEventHandler but the passed in event code is only valid 200 // within the LE Meta Event sub-event code namespace. |event_callback| will 201 // get invoked whenever the controller sends a LE Meta Event with a matching 202 // subevent code. 203 EventHandlerId AddLEMetaEventHandler( 204 hci_spec::EventCode le_meta_subevent_code, EventCallback event_callback); 205 206 // Works just like AddEventHandler but the passed in event code is only valid 207 // for vendor related debugging events. The event_callback will get invoked 208 // whenever the controller sends one of these vendor debugging events with a 209 // matching subevent code. 210 EventHandlerId AddVendorEventHandler(hci_spec::EventCode vendor_subevent_code, 211 EventCallback event_callback); 212 213 // Removes a previously registered event handler. Does nothing if an event 214 // handler with the given |id| could not be found. 215 void RemoveEventHandler(EventHandlerId id); 216 217 // Set callback that will be called when a command times out after 218 // kCommandTimeout. This is distinct from channel closure. set_channel_timeout_cb(fit::closure timeout_cb)219 void set_channel_timeout_cb(fit::closure timeout_cb) { 220 channel_timeout_cb_ = std::move(timeout_cb); 221 } 222 223 // Attach command_channel inspect node as a child node of |parent|. 224 static constexpr const char* kInspectNodeName = "command_channel"; 225 void AttachInspect(inspect::Node& parent, 226 const std::string& name = kInspectNodeName); 227 228 using WeakPtr = WeakSelf<CommandChannel>::WeakPtr; AsWeakPtr()229 WeakPtr AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } 230 231 private: 232 TransactionId SendExclusiveCommandInternal( 233 CommandPacket command_packet, 234 CommandCallback callback, 235 hci_spec::EventCode complete_event_code, 236 std::optional<hci_spec::EventCode> le_meta_subevent_code = std::nullopt, 237 std::unordered_set<hci_spec::OpCode> exclusions = {}); 238 239 // Data related to a queued or running command. 240 // 241 // When a command is sent to the controller, it is placed in the 242 // pending_transactions_ map. It remains in the pending_transactions_ map 243 // until it is completed - asynchronous commands remain until their 244 // complete_event_code_ is received. 245 // 246 // There are a number of reasons a command may be queued before sending: 247 // 248 // - An asynchronous command is waiting on the same event code 249 // - A command with an opcode that is in the exclusions set for this 250 // transaction is pending 251 // - We cannot send any commands because of the limit of outstanding command 252 // packets from the 253 // controller Queued commands are held in the send_queue_ and are sent when 254 // possible, FIFO (but skipping commands that cannot be sent) 255 class TransactionData { 256 public: 257 TransactionData(CommandChannel* channel, 258 TransactionId id, 259 hci_spec::OpCode opcode, 260 hci_spec::EventCode complete_event_code, 261 std::optional<hci_spec::EventCode> le_meta_subevent_code, 262 std::unordered_set<hci_spec::OpCode> exclusions, 263 CommandCallback callback); 264 ~TransactionData(); 265 266 // Starts the transaction timer, which will call 267 // CommandChannel::OnCommandTimeout if it's not completed in time. 268 void StartTimer(); 269 270 // Completes the transaction with |event|. For asynchronous commands, this 271 // should be called with the status event (the complete event is handled 272 // separately by the event handler). 273 void Complete(std::unique_ptr<EventPacket> event); 274 275 // Cancels the transaction timeout and erases the callback so it isn't 276 // called upon destruction. 277 void Cancel(); 278 279 // Makes an EventCallback that calls |callback_| correctly. 280 EventCallback MakeCallback(); 281 complete_event_code()282 hci_spec::EventCode complete_event_code() const { 283 return complete_event_code_; 284 } le_meta_subevent_code()285 std::optional<hci_spec::EventCode> le_meta_subevent_code() const { 286 return le_meta_subevent_code_; 287 } opcode()288 hci_spec::OpCode opcode() const { return opcode_; } id()289 TransactionId id() const { return transaction_id_; } 290 291 // The set of opcodes in progress that will hold this transaction in queue. exclusions()292 const std::unordered_set<hci_spec::OpCode>& exclusions() const { 293 return exclusions_; 294 } 295 handler_id()296 EventHandlerId handler_id() const { return handler_id_; } set_handler_id(EventHandlerId id)297 void set_handler_id(EventHandlerId id) { handler_id_ = id; } 298 299 private: 300 CommandChannel* channel_; 301 TransactionId transaction_id_; 302 hci_spec::OpCode opcode_; 303 hci_spec::EventCode complete_event_code_; 304 std::optional<hci_spec::EventCode> le_meta_subevent_code_; 305 std::unordered_set<hci_spec::OpCode> exclusions_; 306 CommandCallback callback_; 307 bt::SmartTask timeout_task_; 308 309 // If non-zero, the id of the handler registered for this transaction. 310 // Always zero if this transaction is synchronous. 311 EventHandlerId handler_id_; 312 313 BT_DISALLOW_COPY_ASSIGN_AND_MOVE(TransactionData); 314 }; 315 316 // Adds an internal event handler for |data| if one does not exist yet and 317 // another transaction is not waiting on the same event. Used to add expiring 318 // event handlers for asynchronous commands. 319 void MaybeAddTransactionHandler(TransactionData* data); 320 321 // Represents a queued command packet. 322 struct QueuedCommand { 323 QueuedCommand(CommandPacket command_packet, 324 std::unique_ptr<TransactionData> data); 325 QueuedCommand() = delete; 326 327 QueuedCommand(QueuedCommand&& other) = default; 328 QueuedCommand& operator=(QueuedCommand&& other) = default; 329 330 CommandPacket packet; 331 std::unique_ptr<TransactionData> data; 332 }; 333 334 // Data stored for each event handler registered. 335 struct EventHandlerData { 336 EventHandlerId handler_id; 337 hci_spec::EventCode event_code; 338 339 // Defines how event_code should be interpreted. For example, if the 340 // event_type is kLEMetaEvent, the event_code is an LE Meta Subevent code. 341 EventType event_type; 342 343 // For asynchronous transaction event handlers, the pending command opcode. 344 // kNoOp if this is a static event handler. 345 hci_spec::OpCode pending_opcode; 346 347 EventCallback event_callback; 348 349 // Returns true if handler is for async command transaction, or false if 350 // handler is a static event handler. is_asyncEventHandlerData351 bool is_async() const { return pending_opcode != hci_spec::kNoOp; } 352 }; 353 354 // Finds the event handler for |code|. Returns nullptr if one doesn't exist. 355 EventHandlerData* FindEventHandler(hci_spec::EventCode code); 356 357 // Finds the LE Meta Event handler for |le_meta_subevent_code|. Returns 358 // nullptr if one doesn't exist. 359 EventHandlerData* FindLEMetaEventHandler( 360 hci_spec::EventCode le_meta_subevent_code); 361 362 // Finds the Vendor Event handler for |vendor_subevent_code|. Returns nullptr 363 // if one doesn't exist. 364 EventHandlerData* FindVendorEventHandler( 365 hci_spec::EventCode vendor_subevent_code); 366 367 // Removes internal event handler structures for |id|. 368 void RemoveEventHandlerInternal(EventHandlerId id); 369 370 // Sends any queued commands that can be processed unambiguously and complete. 371 void TrySendQueuedCommands(); 372 373 // Sends |command|, adding an internal event handler if asynchronous. 374 void SendQueuedCommand(QueuedCommand&& cmd); 375 376 // Creates a new event handler entry in the event handler map and returns its 377 // ID. The event_code should correspond to the event_type provided. For 378 // example, if event_type is kLEMetaEvent, then event_code will be interpreted 379 // as a LE Meta Subevent code. 380 EventHandlerId NewEventHandler(hci_spec::EventCode event_code, 381 EventType event_type, 382 hci_spec::OpCode pending_opcode, 383 EventCallback event_callback); 384 385 // Notifies any matching event handler for |event|. 386 void NotifyEventHandler(std::unique_ptr<EventPacket> event); 387 388 // Notifies handlers for Command Status and Command Complete Events. This 389 // function marks opcodes that have transactions pending as complete by 390 // removing them and calling their callbacks. 391 void UpdateTransaction(std::unique_ptr<EventPacket> event); 392 393 // Event handler. 394 void OnEvent(pw::span<const std::byte> buffer); 395 396 // Called when a command times out. Notifies upper layers of the error. 397 void OnCommandTimeout(TransactionId transaction_id); 398 399 // True if CommandChannel is still processing packets. Set to false upon fatal 400 // errors. 401 bool active_ = true; 402 403 // Opcodes of commands that we have sent to the controller but not received a 404 // status update from. New commands with these opcodes can't be sent because 405 // they are indistinguishable from ones we need to get the result of. 406 std::unordered_map<hci_spec::OpCode, std::unique_ptr<TransactionData>> 407 pending_transactions_; 408 409 // TransactionId counter. 410 UintInspectable<TransactionId> next_transaction_id_; 411 412 // EventHandlerId counter. 413 UintInspectable<size_t> next_event_handler_id_; 414 415 // The HCI we use to send/receive HCI commands/events. 416 pw::bluetooth::Controller* hci_; 417 418 // Callback called when a command times out. 419 fit::closure channel_timeout_cb_; 420 421 // The HCI command queue. This queue is not necessarily sent in order, but 422 // commands with the same opcode or that wait on the same completion event 423 // code are sent first-in, first-out. 424 std::list<QueuedCommand> send_queue_; 425 426 // Contains the current count of commands we ae allowed to send to the 427 // controller. This is decremented when we send a command and updated when we 428 // receive a CommandStatus or CommandComplete event with the Num HCI Command 429 // Packets parameter. 430 // 431 // Accessed only from the I/O thread and thus not guarded. 432 UintInspectable<size_t> allowed_command_packets_; 433 434 // Mapping from event handler IDs to handler data. 435 std::unordered_map<EventHandlerId, EventHandlerData> event_handler_id_map_; 436 437 // Mapping from event code to the event handlers that were registered to 438 // handle that event code. 439 std::unordered_multimap<hci_spec::EventCode, EventHandlerId> 440 event_code_handlers_; 441 442 // Mapping from LE Meta Event Subevent code to the event handlers that were 443 // registered to handle that event code. 444 std::unordered_multimap<hci_spec::EventCode, EventHandlerId> 445 le_meta_subevent_code_handlers_; 446 447 // Mapping from Vendor Subevent code to the event handlers that were 448 // registered to handle that event code. 449 std::unordered_multimap<hci_spec::EventCode, EventHandlerId> 450 vendor_subevent_code_handlers_; 451 452 // Command channel inspect node. 453 inspect::Node command_channel_node_; 454 455 pw::async::Dispatcher& dispatcher_; 456 457 // As events can arrive in the event thread at any time, we should invalidate 458 // our weak pointers early. 459 WeakSelf<CommandChannel> weak_ptr_factory_; 460 461 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(CommandChannel); 462 }; 463 464 } // namespace bt::hci 465