• 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 
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