xhci/context/
mod.rs

1//! The xHCI Contexts.
2//!
3//! The size of each Context type is the same as the actual Context size.
4//!
5//! To make it possible to make a reference to Contexts regardless of Context's size, all Contexts
6//! implement handler traits that implement methods to access and modify fields. Refer to the
7//! documentation of each trait for the available methods.
8//!
9//! # Examples
10//!
11//! ```no_run
12//! use xhci::{context, context::InputHandler};
13//!
14//! let mut input = context::Input::new_32byte();
15//! let input_control = input.control_mut();
16//! input_control.set_add_context_flag(0);
17//! input_control.set_add_context_flag(1);
18//!
19//! # let port_id = 3;
20//! let device = input.device_mut();
21//! let slot = device.slot_mut();
22//! slot.set_context_entries(1);
23//! slot.set_root_hub_port_number(port_id);
24//! ```
25
26#[macro_use]
27mod macros;
28
29use bit_field::BitField;
30use core::convert::TryInto;
31use core::fmt;
32use num_derive::FromPrimitive;
33use num_traits::FromPrimitive;
34
35/// The number of Endpoint Contexts in a Device Context.
36pub const NUM_OF_ENDPOINT_CONTEXTS: usize = 31;
37
38/// 32 byte Input Context.
39pub type Input32Byte = Input<8>;
40/// 64 byte Input Context.
41pub type Input64Byte = Input<16>;
42
43/// 32 byte Input Control Context.
44pub type InputControl32Byte = InputControl<8>;
45/// 64 byte Input Control Context.
46pub type InputControl64Byte = InputControl<16>;
47
48/// 32 byte Device Context.
49pub type Device32Byte = Device<8>;
50/// 64 byte Device Context.
51pub type Device64Byte = Device<16>;
52
53/// 32 byte Slot Context.
54pub type Slot32Byte = Slot<8>;
55/// 64 byte Slot Context.
56pub type Slot64Byte = Slot<16>;
57
58/// 32 byte Endpoint Context.
59pub type Endpoint32Byte = Endpoint<8>;
60/// 64 byte Endpoint Context.
61pub type Endpoint64Byte = Endpoint<16>;
62
63/// Input Context.
64///
65/// Refer to [`InputHandler`] for the available methods.
66#[repr(C)]
67#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
68pub struct Input<const N: usize> {
69    control: InputControl<N>,
70    device: Device<N>,
71}
72impl_constructor!(Input, "Input");
73impl<const N: usize> Input<N> {
74    const fn new() -> Self {
75        Self {
76            control: InputControl::new(),
77            device: Device::new(),
78        }
79    }
80}
81impl<const N: usize> InputHandler for Input<N> {
82    fn control(&self) -> &dyn InputControlHandler {
83        &self.control
84    }
85
86    fn control_mut(&mut self) -> &mut dyn InputControlHandler {
87        &mut self.control
88    }
89
90    fn device(&self) -> &dyn DeviceHandler {
91        &self.device
92    }
93
94    fn device_mut(&mut self) -> &mut dyn DeviceHandler {
95        &mut self.device
96    }
97}
98
99/// A trait to handle Input Context.
100pub trait InputHandler {
101    /// Returns a handler of Input Control Context.
102    fn control(&self) -> &dyn InputControlHandler;
103
104    /// Returns a mutable handler of Input Control Context.
105    fn control_mut(&mut self) -> &mut dyn InputControlHandler;
106
107    /// Returns a handler of Device Context.
108    fn device(&self) -> &dyn DeviceHandler;
109
110    /// Returns a mutable handler of Device Context.
111    fn device_mut(&mut self) -> &mut dyn DeviceHandler;
112}
113
114/// Input Control Context.
115///
116/// Refer to [`InputControlHandler`] for the available methods.
117#[repr(transparent)]
118#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
119pub struct InputControl<const N: usize>([u32; N]);
120impl_constructor!(InputControl, "Input Control");
121impl<const N: usize> InputControl<N> {
122    const fn new() -> Self {
123        Self([0; N])
124    }
125}
126impl<const N: usize> AsRef<[u32]> for InputControl<N> {
127    fn as_ref(&self) -> &[u32] {
128        &self.0
129    }
130}
131impl<const N: usize> AsMut<[u32]> for InputControl<N> {
132    fn as_mut(&mut self) -> &mut [u32] {
133        &mut self.0
134    }
135}
136impl<const N: usize> InputControlHandler for InputControl<N> {}
137impl<const N: usize> fmt::Debug for InputControl<N> {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        f.debug_struct("InputControl")
140            .field("Drop Context flags", &self.0[0])
141            .field("Add Context flags", &self.0[1])
142            .field("configuration_value", &self.configuration_value())
143            .field("interface_number", &self.interface_number())
144            .field("alternate_setting", &self.alternate_setting())
145            .finish()
146    }
147}
148
149/// A trait to handle Input Control Context.
150pub trait InputControlHandler: AsRef<[u32]> + AsMut<[u32]> {
151    /// Returns the `i`th Drop Context flag. `i` starts from 0.
152    ///
153    /// # Panics
154    ///
155    /// This method panics if `i < 2 || i > 31`.
156    #[must_use]
157    fn drop_context_flag(&self, i: usize) -> bool {
158        self.ensure_drop_context_index_within_range(i);
159
160        self.as_ref()[0].get_bit(i)
161    }
162
163    /// Sets the `i`th Drop Context flag. `i` starts from 0.
164    ///
165    /// # Panics
166    ///
167    /// This method panics if `i < 2 || i > 31`.
168    fn set_drop_context_flag(&mut self, i: usize) {
169        self.ensure_drop_context_index_within_range(i);
170
171        self.as_mut()[0].set_bit(i, true);
172    }
173
174    /// Clears the `i`th Drop Context flag. `i` starts from 0.
175    ///
176    /// # Panics
177    ///
178    /// This method panics if `i < 2 || i > 31`.
179    fn clear_drop_context_flag(&mut self, i: usize) {
180        self.ensure_drop_context_index_within_range(i);
181
182        self.as_mut()[0].set_bit(i, false);
183    }
184
185    /// Returns the `i`th Add Context flag. `i` starts from 0.
186    ///
187    /// # Panics
188    ///
189    /// This method panics if `i > 31`.
190    #[must_use]
191    fn add_context_flag(&self, i: usize) -> bool {
192        self.ensure_add_context_index_within_range(i);
193
194        self.as_ref()[1].get_bit(i)
195    }
196
197    /// Sets the `i`th Add Context flag. `i` starts from 0.
198    ///
199    /// # Panics
200    ///
201    /// This method panics if `i > 31`.
202    fn set_add_context_flag(&mut self, i: usize) {
203        self.ensure_add_context_index_within_range(i);
204
205        self.as_mut()[1].set_bit(i, true);
206    }
207
208    /// Clears the `i`th Add Context flag. `i` starts from 0.
209    ///
210    /// # Panics
211    ///
212    /// This method panics if `i > 31`.
213    fn clear_add_context_flag(&mut self, i: usize) {
214        self.ensure_add_context_index_within_range(i);
215
216        self.as_mut()[1].set_bit(i, false);
217    }
218
219    rw_field_cx!([7](0..=7), configuration_value, "Configuration Value", u8);
220    rw_field_cx!([7](8..=15), interface_number, "Interface Number", u8);
221    rw_field_cx!([7](16..=23), alternate_setting, "Alternate Setting", u8);
222
223    #[doc(hidden)]
224    fn ensure_drop_context_index_within_range(&self, i: usize) {
225        assert!(
226            (2..=31).contains(&i),
227            "The index of Drop Context flag must be within 2..=31."
228        );
229    }
230
231    #[doc(hidden)]
232    fn ensure_add_context_index_within_range(&self, i: usize) {
233        assert!(
234            i <= 31,
235            "The index of Add Context flag must be less than 32."
236        );
237    }
238}
239
240/// Device Context.
241///
242/// Refer to [`DeviceHandler`] for the available methods.
243#[repr(C)]
244#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
245pub struct Device<const N: usize> {
246    slot: Slot<N>,
247    endpoints: [Endpoint<N>; NUM_OF_ENDPOINT_CONTEXTS],
248}
249impl_constructor!(Device, "Device");
250impl<const N: usize> Device<N> {
251    const fn new() -> Self {
252        Self {
253            slot: Slot::new(),
254            endpoints: [Endpoint::new(); NUM_OF_ENDPOINT_CONTEXTS],
255        }
256    }
257
258    fn assert_dci(dci: usize) {
259        assert_ne!(
260            dci, 0,
261            "Call `DeviceHandler::slot` to get a handler of Slot Context.`"
262        );
263        assert!(dci <= 31, "DCI must be less than 32.");
264    }
265}
266impl<const N: usize> DeviceHandler for Device<N> {
267    fn slot(&self) -> &dyn SlotHandler {
268        &self.slot
269    }
270
271    fn slot_mut(&mut self) -> &mut dyn SlotHandler {
272        &mut self.slot
273    }
274
275    fn endpoint(&self, dci: usize) -> &dyn EndpointHandler {
276        Self::assert_dci(dci);
277
278        &self.endpoints[dci - 1]
279    }
280
281    fn endpoint_mut(&mut self, dci: usize) -> &mut dyn EndpointHandler {
282        Self::assert_dci(dci);
283
284        &mut self.endpoints[dci - 1]
285    }
286}
287
288/// A trait to handle Device Context.
289pub trait DeviceHandler {
290    /// Returns a handler of Slot Context.
291    fn slot(&self) -> &dyn SlotHandler;
292
293    /// Returns a mutable handler of Slot Context.
294    fn slot_mut(&mut self) -> &mut dyn SlotHandler;
295
296    /// Returns a handler of Endpoint Context.
297    ///
298    /// # Panics
299    ///
300    /// This method panics if `dci > 31 || dci == 0`. Call [`DeviceHandler::slot`] if you want a
301    /// handler of Slot Context.
302    fn endpoint(&self, dci: usize) -> &dyn EndpointHandler;
303
304    /// Returns a mutable handler of Endpoint Context.
305    ///
306    /// # Panics
307    ///
308    /// This method panics if `dci > 31 || dci == 0`. Call [`DeviceHandler::slot_mut`] if you want
309    /// a mutable handler of Slot Context.
310    fn endpoint_mut(&mut self, dci: usize) -> &mut dyn EndpointHandler;
311}
312
313/// Slot Context.
314///
315/// Refer to [`SlotHandler`] for the available methods.
316#[repr(transparent)]
317#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
318pub struct Slot<const N: usize>([u32; N]);
319impl_constructor!(Slot, "Slot");
320impl<const N: usize> Slot<N> {
321    const fn new() -> Self {
322        Self([0; N])
323    }
324}
325impl<const N: usize> AsRef<[u32]> for Slot<N> {
326    fn as_ref(&self) -> &[u32] {
327        &self.0
328    }
329}
330impl<const N: usize> AsMut<[u32]> for Slot<N> {
331    fn as_mut(&mut self) -> &mut [u32] {
332        &mut self.0
333    }
334}
335impl<const N: usize> SlotHandler for Slot<N> {}
336impl_debug_from_methods_cx! {
337    Slot {
338        route_string,
339        speed,
340        multi_tt,
341        hub,
342        context_entries,
343        max_exit_latency,
344        root_hub_port_number,
345        number_of_ports,
346        parent_hub_slot_id,
347        parent_port_number,
348        tt_think_time,
349        interrupter_target,
350        usb_device_address,
351        slot_state,
352    }
353}
354
355/// A trait to handle Slot Context.
356pub trait SlotHandler: AsRef<[u32]> + AsMut<[u32]> {
357    rw_field_cx!([0](0..=19), route_string, "Route String", u32);
358    rw_field_cx!([0](20..=23), speed, "Speed", u8);
359    rw_bit_cx!([0](25), multi_tt, "Multi-TT");
360    rw_bit_cx!([0](26), hub, "Hub");
361    rw_field_cx!([0](27..=31), context_entries, "Context Entries", u8);
362
363    rw_field_cx!([1](0..=15), max_exit_latency, "Max Exit Latency", u16);
364    rw_field_cx!(
365        [1](16..=23),
366        root_hub_port_number,
367        "Root Hub Port Number",
368        u8
369    );
370    rw_field_cx!([1](24..=31), number_of_ports, "Number of Ports", u8);
371
372    rw_field_cx!([2](0..=7), parent_hub_slot_id, "Parent Hub Slot ID", u8);
373    rw_field_cx!([2](8..=15), parent_port_number, "Parent Port Number", u8);
374    rw_field_cx!([2](16..=17), tt_think_time, "TT Think Time", u8);
375    rw_field_cx!([2](22..=31), interrupter_target, "Interrupter Target", u16);
376
377    rw_field_cx!([3](0..=7), usb_device_address, "USB Device Address", u8);
378    /// Returns Slot State.
379    ///
380    /// # Panics
381    ///
382    /// This method panics if the Slot State represents Reserved.
383    #[must_use]
384    fn slot_state(&self) -> SlotState {
385        let v = self.as_ref()[3].get_bits(27..=31);
386        let s = FromPrimitive::from_u32(v);
387        s.expect("Slot State represents Reserved.")
388    }
389
390    /// Sets Slot State.
391    fn set_slot_state(&mut self, state: SlotState) {
392        self.as_mut()[3].set_bits(27..=31, state as _);
393    }
394}
395
396/// Endpoint Context.
397///
398/// Refer to [`EndpointHandler`] for the available methods.
399#[repr(transparent)]
400#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
401pub struct Endpoint<const N: usize>([u32; N]);
402impl_constructor!(Endpoint, "Endpoint");
403impl<const N: usize> Endpoint<N> {
404    const fn new() -> Self {
405        Self([0; N])
406    }
407}
408impl<const N: usize> AsRef<[u32]> for Endpoint<N> {
409    fn as_ref(&self) -> &[u32] {
410        &self.0
411    }
412}
413impl<const N: usize> AsMut<[u32]> for Endpoint<N> {
414    fn as_mut(&mut self) -> &mut [u32] {
415        &mut self.0
416    }
417}
418impl<const N: usize> EndpointHandler for Endpoint<N> {}
419impl_debug_from_methods_cx! {
420    Endpoint {
421        endpoint_state,
422        mult,
423        max_primary_streams,
424        linear_stream_array,
425        interval,
426        max_endpoint_service_time_interval_payload_high,
427        error_count,
428        endpoint_type,
429        host_initiate_disable,
430        max_burst_size,
431        max_packet_size,
432        dequeue_cycle_state,
433        tr_dequeue_pointer,
434        average_trb_length,
435        max_endpoint_service_time_interval_payload_low,
436    }
437}
438
439/// A trait to handle Endpoint Context.
440pub trait EndpointHandler: AsRef<[u32]> + AsMut<[u32]> {
441    /// Returns Endpoint State.
442    ///
443    /// # Panics
444    ///
445    /// This method panics if the Endpoint State represents Reserved.
446    #[must_use]
447    fn endpoint_state(&self) -> EndpointState {
448        let v = self.as_ref()[0].get_bits(0..=2);
449        let s = FromPrimitive::from_u32(v);
450        s.expect("Endpoint State represents Reserved.")
451    }
452
453    /// Sets Endpoint State.
454    fn set_endpoint_state(&mut self, s: EndpointState) {
455        self.as_mut()[0].set_bits(0..=2, s as _);
456    }
457
458    rw_field_cx!([0](8..=9), mult, "Mult", u8);
459    rw_field_cx!([0](10..=14), max_primary_streams, "Max Primary Streams", u8);
460    rw_bit_cx!([0](15), linear_stream_array, "Linear Stream Array");
461    rw_field_cx!([0](16..=23), interval, "Interval", u8);
462    rw_field_cx!(
463        [0](24..=31),
464        max_endpoint_service_time_interval_payload_high,
465        "Max Endpoint Service Time Interval Payload High",
466        u8
467    );
468
469    rw_field_cx!([1](1..=2), error_count, "Error Count", u8);
470    /// Returns Endpoint Type.
471    #[must_use]
472    fn endpoint_type(&self) -> EndpointType {
473        let v = self.as_ref()[1].get_bits(3..=5);
474        let t = FromPrimitive::from_u32(v);
475        t.expect("Invalid Endpoint Type.")
476    }
477
478    /// Sets Endpoint Type.
479    fn set_endpoint_type(&mut self, t: EndpointType) {
480        self.as_mut()[1].set_bits(3..=5, t as _);
481    }
482
483    rw_bit_cx!([1](7), host_initiate_disable, "Host Initiate Disable");
484    rw_field_cx!([1](8..=15), max_burst_size, "Max Burst Size", u8);
485    rw_field_cx!([1](16..=31), max_packet_size, "Max Packet Size", u16);
486
487    rw_bit_cx!([2](0), dequeue_cycle_state, "Dequeue Cycle State");
488
489    /// Returns the TR Dequeue Pointer.
490    #[must_use]
491    fn tr_dequeue_pointer(&self) -> u64 {
492        let l: u64 = self.as_ref()[2].into();
493        let u: u64 = self.as_ref()[3].into();
494
495        (u << 32) | l
496    }
497
498    /// Sets the TR Dequeue Pointer.
499    ///
500    /// # Panics
501    ///
502    /// This method panics if `addr` is not 64-byte aligned.
503    fn set_tr_dequeue_pointer(&mut self, a: u64) {
504        assert_eq!(a % 64, 0, "TR Dequeue Pointer must be 64-byte aligned.");
505
506        let l: u32 = a.get_bits(0..32).try_into().unwrap();
507        let u: u32 = a.get_bits(32..64).try_into().unwrap();
508
509        self.as_mut()[2] = l;
510        self.as_mut()[3] = u;
511    }
512
513    rw_field_cx!([4](0..=15), average_trb_length, "Average TRB Length", u16);
514    rw_field_cx!(
515        [4](16..=31),
516        max_endpoint_service_time_interval_payload_low,
517        "Max Endpoint Service Time Interval Payload Low",
518        u16
519    );
520}
521
522/// Slot State.
523#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)]
524pub enum SlotState {
525    /// Disabled/Enabled.
526    DisabledEnabled = 0,
527    /// Default.
528    Default = 1,
529    /// Addressed.
530    Addressed = 2,
531    /// Configured.
532    Configured = 3,
533}
534
535/// Endpoint State.
536///
537/// The descriptions of each variant are taken from Table 6-8 of eXtensible Host Controller Interface for Universal Serial Bus(xHCI) Requirements Specification May2019 Revision 1.2.
538#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)]
539pub enum EndpointState {
540    /// The endpoint is not operational.
541    Disabled = 0,
542    /// The endpoint is operational, either waiting for a doorbell ring or processing TDs.
543    Running = 1,
544    /// The endpoint is halted due to a Halt condition detected on the USB.
545    Halted = 2,
546    /// The endpoint is not running due to a Stop Endpoint Command or recovering from a Halt
547    /// condition.
548    Stopped = 3,
549    /// The endpoint is not running due to a TRB Erorr.
550    Error = 4,
551}
552
553/// Endpoint Type.
554#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, FromPrimitive)]
555pub enum EndpointType {
556    /// Not Valid.
557    NotValid = 0,
558    /// Isoch Out.
559    IsochOut = 1,
560    /// Bulk Out.
561    BulkOut = 2,
562    /// Interrupt Out.
563    InterruptOut = 3,
564    /// Control Bidirectional.
565    Control = 4,
566    /// Isoch In.
567    IsochIn = 5,
568    /// Bulk In.
569    BulkIn = 6,
570    /// Interrupt In.
571    InterruptIn = 7,
572}