1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! Interface for implementing drivers
//!
//! Drivers are instantiated by application code and passed to the [`UsbHost::poll`](crate::UsbHost::poll) function.
//!
//! The methods defined in this trait are then called by by the UsbHost at the appropriate times.
//!
//! All of these methods are called on *all* of the drivers (with the exception fo the [`configure`](Driver::configure) method).
//!
//! Drivers must interpret the `dev_addr` parameter (and `pipe_id` where applicable) to determine if the event
//! targets one of the devices that the driver is controlling.
//!
//! In general multiple drivers can communicate with the same device, except that only one driver can decide which device
//! configuration to set.
//!
//! ## Walkthrough for a newly connected device
//!
//! 1. Initially the device has no address, so the host enters **enumeration**
//! 2. When enumeration has succeeded, the host calls [`attached`](Driver::attached), informing drivers that a new device is available, and enters **discovery** phase
//! 3. During discovery, the host requests the *device descriptor* from the device, and subsequently requests the *configuration descriptor* for each of
//! the configurations that the device supports. All of these descriptors are parsed into `descriptor_type` and `data` and passed to the [`descriptor`](Driver::descriptor) method one-by-one.
//! When requesting a configuration descriptor, the device sends *all* of the nested descriptors (interface, endpoint, class specifics, ...) as well.
//! The discovery logic separates these descriptors and passes each of them to the [`descriptor`](Driver::descriptor) method separately.
//! 4. When all descriptors have been fetched, the host enters the **configuration** phase.
//! 5. During configuration, the host calls [`configure`](Driver::configure) on each of the drivers *until one of them returns a value*.
//! The value must be a valid configuration value (i.e. come from a [`ConfigurationDescriptor::value`](crate::descriptor::ConfigurationDescriptor::value)).
//! 6. If all of the drivers' `configure` calls returned `None` (no driver is interested in it), the host enteres **dormant** state.
//! Otherwise the host calls [`configured`](Driver::configured) on *all* of the drivers and enteres **configured** state.
//! 7. The [`configured`](Driver::configured) callback informs the driver about the chosen configuration, and gives access to the host interface,
//! to allow the driver to set up pipes for the device's endpoints.
//! Currently only **control pipes** and **interrupt pipes** are supported.
//!
//! This concludes the configuration phase. If the device ends up in **configured** state (one of the drivers selected a configuration),
//! drivers can communicate with the device from now on.
//!
//! ## Communicating with the device
//!
//! Drivers cannot initiate communication through the host on their own, they must be given access to the `UsbHost` instance by application code to do so.
//!
//! For this purpose the driver should define function specific methods on the driver object, which take a `&mut UsbHost<B>`.
//!
//! Communication may only happen through the pipes which were created by the [`Driver::configured`] callback. Pipes are identified by a [`PipeId`].
//!
//! ### Control transfers
//!
//! To initiate a control transfer, the driver must have created a control pipe ([`create_control_pipe`](crate::UsbHost::create_control_pipe)).
//!
//! That pipe can then be passed to [`control_in`](crate::UsbHost::control_in) or [`control_out`](crate::UsbHost::control_out), to initiate a transfer.
//!
//! Example:
//! ```ignore
//! // our driver keeps track of only one device, and a single pipe
//! struct MyDriver {
//! dev_addr: Option<DeviceAddress>,
//! control_pipe: Option<PipeId>,
//! }
//!
//! impl<B: HostBus> Driver<B> for MyDriver {
//! fn configured(&mut self, dev_addr: DeviceAddress, _value: u8, host: &mut UsbHost) {
//! self.dev_addr = Some(dev_addr);
//! // NOTE: the host can only handle a fixed number of pipes. If it runs out of pipes, None is returned.
//! self.control_pipe = host.create_control_pipe(dev_addr);
//! }
//!
//! // remaining methods omitted for brevity...
//! }
//!
//! impl MyDriver {
//! // driver specific method, which will be called by application code
//! fn turn_on_led<B: HostBus>(&mut self, host: &mut UsbHost<B>) -> Result<(), ControlError> {
//! if let (Some(dev_addr), Some(control_pipe)) = (self.dev_addr, self.control_pipe) {
//! host.control_out(
//! // device being addressed
//! Some(dev_addr),
//! // control pipe to use
//! Some(control_pipe),
//! // setup packet (function specific)
//! SetupPacket::new(UsbDirection::Out, /* ... */),
//! // data to send (function specific)
//! &[/* ... */],
//! )?;
//! }
//! Ok(())
//! }
//! }
//! ```
//!
//!
//!
use crateHostBus;
use crate;
use crate::;
/// The Driver trait
///
/// See [module-level documentation](`crate::driver`) for details.
///