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