• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use super::interrupter::Interrupter;
6 use super::transfer_ring_controller::{TransferRingController, TransferRingControllerError};
7 use super::usb_hub::{self, UsbHub};
8 use super::xhci_abi::{
9     AddressDeviceCommandTrb, ConfigureEndpointCommandTrb, DequeuePtr, DeviceContext,
10     DeviceSlotState, EndpointContext, EndpointState, EvaluateContextCommandTrb,
11     InputControlContext, SlotContext, TrbCompletionCode, DEVICE_CONTEXT_ENTRY_SIZE,
12 };
13 use super::xhci_regs::{valid_slot_id, MAX_PORTS, MAX_SLOTS};
14 use crate::register_space::Register;
15 use crate::usb::host_backend::error::Error as HostBackendProviderError;
16 use crate::usb::xhci::ring_buffer_stop_cb::{fallible_closure, RingBufferStopCallback};
17 use crate::utils::{EventLoop, FailHandle};
18 use base::error;
19 use bit_field::Error as BitFieldError;
20 use remain::sorted;
21 use std::mem::size_of;
22 use std::sync::atomic::{AtomicBool, Ordering};
23 use std::sync::Arc;
24 use sync::Mutex;
25 use thiserror::Error;
26 use vm_memory::{GuestAddress, GuestMemory, GuestMemoryError};
27 
28 #[sorted]
29 #[derive(Error, Debug)]
30 pub enum Error {
31     #[error("bad device context: {0}")]
32     BadDeviceContextAddr(GuestAddress),
33     #[error("bad input context address: {0}")]
34     BadInputContextAddr(GuestAddress),
35     #[error("device slot get a bad port id: {0}")]
36     BadPortId(u8),
37     #[error("callback failed")]
38     CallbackFailed,
39     #[error("failed to create transfer controller: {0}")]
40     CreateTransferController(TransferRingControllerError),
41     #[error("failed to get endpoint state: {0}")]
42     GetEndpointState(BitFieldError),
43     #[error("failed to get port: {0}")]
44     GetPort(u8),
45     #[error("failed to get slot context state: {0}")]
46     GetSlotContextState(BitFieldError),
47     #[error("failed to get trc: {0}")]
48     GetTrc(u8),
49     #[error("failed to read guest memory: {0}")]
50     ReadGuestMemory(GuestMemoryError),
51     #[error("failed to reset port: {0}")]
52     ResetPort(HostBackendProviderError),
53     #[error("failed to upgrade weak reference")]
54     WeakReferenceUpgrade,
55     #[error("failed to write guest memory: {0}")]
56     WriteGuestMemory(GuestMemoryError),
57 }
58 
59 type Result<T> = std::result::Result<T, Error>;
60 
61 /// See spec 4.5.1 for dci.
62 /// index 0: Control endpoint. Device Context Index: 1.
63 /// index 1: Endpoint 1 out. Device Context Index: 2
64 /// index 2: Endpoint 1 in. Device Context Index: 3.
65 /// index 3: Endpoint 2 out. Device Context Index: 4
66 /// ...
67 /// index 30: Endpoint 15 in. Device Context Index: 31
68 pub const TRANSFER_RING_CONTROLLERS_INDEX_END: usize = 31;
69 /// End of device context index.
70 pub const DCI_INDEX_END: u8 = (TRANSFER_RING_CONTROLLERS_INDEX_END + 1) as u8;
71 /// Device context index of first transfer endpoint.
72 pub const FIRST_TRANSFER_ENDPOINT_DCI: u8 = 2;
73 
valid_endpoint_id(endpoint_id: u8) -> bool74 fn valid_endpoint_id(endpoint_id: u8) -> bool {
75     endpoint_id < DCI_INDEX_END && endpoint_id > 0
76 }
77 
78 #[derive(Clone)]
79 pub struct DeviceSlots {
80     fail_handle: Arc<dyn FailHandle>,
81     hub: Arc<UsbHub>,
82     slots: Vec<Arc<DeviceSlot>>,
83 }
84 
85 impl DeviceSlots {
new( fail_handle: Arc<dyn FailHandle>, dcbaap: Register<u64>, hub: Arc<UsbHub>, interrupter: Arc<Mutex<Interrupter>>, event_loop: Arc<EventLoop>, mem: GuestMemory, ) -> DeviceSlots86     pub fn new(
87         fail_handle: Arc<dyn FailHandle>,
88         dcbaap: Register<u64>,
89         hub: Arc<UsbHub>,
90         interrupter: Arc<Mutex<Interrupter>>,
91         event_loop: Arc<EventLoop>,
92         mem: GuestMemory,
93     ) -> DeviceSlots {
94         let mut slots = Vec::new();
95         for slot_id in 1..=MAX_SLOTS {
96             slots.push(Arc::new(DeviceSlot::new(
97                 slot_id,
98                 dcbaap.clone(),
99                 hub.clone(),
100                 interrupter.clone(),
101                 event_loop.clone(),
102                 mem.clone(),
103             )));
104         }
105         DeviceSlots {
106             fail_handle,
107             hub,
108             slots,
109         }
110     }
111 
112     /// Note that slot id starts from 1. Slot index start from 0.
slot(&self, slot_id: u8) -> Option<Arc<DeviceSlot>>113     pub fn slot(&self, slot_id: u8) -> Option<Arc<DeviceSlot>> {
114         if valid_slot_id(slot_id) {
115             Some(self.slots[slot_id as usize - 1].clone())
116         } else {
117             error!(
118                 "trying to index a wrong slot id {}, max slot = {}",
119                 slot_id, MAX_SLOTS
120             );
121             None
122         }
123     }
124 
125     /// Reset the device connected to a specific port.
reset_port(&self, port_id: u8) -> Result<()>126     pub fn reset_port(&self, port_id: u8) -> Result<()> {
127         if let Some(port) = self.hub.get_port(port_id) {
128             if let Some(backend_device) = port.get_backend_device().as_mut() {
129                 backend_device.reset().map_err(Error::ResetPort)?;
130             }
131         }
132 
133         // No device on port, so nothing to reset.
134         Ok(())
135     }
136 
137     /// Stop all device slots and reset them.
stop_all_and_reset<C: FnMut() + 'static + Send>(&self, mut callback: C)138     pub fn stop_all_and_reset<C: FnMut() + 'static + Send>(&self, mut callback: C) {
139         usb_debug!("stopping all device slots and resetting host hub");
140         let slots = self.slots.clone();
141         let hub = self.hub.clone();
142         let auto_callback = RingBufferStopCallback::new(fallible_closure(
143             self.fail_handle.clone(),
144             move || -> std::result::Result<(), usb_hub::Error> {
145                 for slot in &slots {
146                     slot.reset();
147                 }
148                 hub.reset()?;
149                 callback();
150                 Ok(())
151             },
152         ));
153         self.stop_all(auto_callback);
154     }
155 
156     /// Stop all devices. The auto callback will be executed when all trc is stopped. It could
157     /// happen asynchronously, if there are any pending transfers.
stop_all(&self, auto_callback: RingBufferStopCallback)158     pub fn stop_all(&self, auto_callback: RingBufferStopCallback) {
159         for slot in &self.slots {
160             slot.stop_all_trc(auto_callback.clone());
161         }
162     }
163 
164     /// Disable a slot. This might happen asynchronously, if there is any pending transfers. The
165     /// callback will be invoked when slot is actually disabled.
disable_slot< C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send, >( &self, slot_id: u8, cb: C, ) -> Result<()>166     pub fn disable_slot<
167         C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send,
168     >(
169         &self,
170         slot_id: u8,
171         cb: C,
172     ) -> Result<()> {
173         usb_debug!("device slot {} is being disabled", slot_id);
174         DeviceSlot::disable(
175             self.fail_handle.clone(),
176             &self.slots[slot_id as usize - 1],
177             cb,
178         )
179     }
180 
181     /// Reset a slot. This is a shortcut call for DeviceSlot::reset_slot.
reset_slot< C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send, >( &self, slot_id: u8, cb: C, ) -> Result<()>182     pub fn reset_slot<
183         C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send,
184     >(
185         &self,
186         slot_id: u8,
187         cb: C,
188     ) -> Result<()> {
189         usb_debug!("device slot {} is resetting", slot_id);
190         DeviceSlot::reset_slot(
191             self.fail_handle.clone(),
192             &self.slots[slot_id as usize - 1],
193             cb,
194         )
195     }
196 
stop_endpoint< C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send, >( &self, slot_id: u8, endpoint_id: u8, cb: C, ) -> Result<()>197     pub fn stop_endpoint<
198         C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send,
199     >(
200         &self,
201         slot_id: u8,
202         endpoint_id: u8,
203         cb: C,
204     ) -> Result<()> {
205         self.slots[slot_id as usize - 1].stop_endpoint(self.fail_handle.clone(), endpoint_id, cb)
206     }
207 }
208 
209 // Usb port id. Valid ids starts from 1, to MAX_PORTS.
210 struct PortId(Mutex<u8>);
211 
212 impl PortId {
new() -> Self213     fn new() -> Self {
214         PortId(Mutex::new(0))
215     }
216 
set(&self, value: u8) -> Result<()>217     fn set(&self, value: u8) -> Result<()> {
218         if !(1..=MAX_PORTS).contains(&value) {
219             return Err(Error::BadPortId(value));
220         }
221         *self.0.lock() = value;
222         Ok(())
223     }
224 
reset(&self)225     fn reset(&self) {
226         *self.0.lock() = 0;
227     }
228 
get(&self) -> Result<u8>229     fn get(&self) -> Result<u8> {
230         let val = *self.0.lock();
231         if val == 0 {
232             return Err(Error::BadPortId(val));
233         }
234         Ok(val)
235     }
236 }
237 
238 pub struct DeviceSlot {
239     slot_id: u8,
240     port_id: PortId, // Valid port id starts from 1, to MAX_PORTS.
241     dcbaap: Register<u64>,
242     hub: Arc<UsbHub>,
243     interrupter: Arc<Mutex<Interrupter>>,
244     event_loop: Arc<EventLoop>,
245     mem: GuestMemory,
246     enabled: AtomicBool,
247     transfer_ring_controllers: Mutex<Vec<Option<Arc<TransferRingController>>>>,
248 }
249 
250 impl DeviceSlot {
251     /// Create a new device slot.
new( slot_id: u8, dcbaap: Register<u64>, hub: Arc<UsbHub>, interrupter: Arc<Mutex<Interrupter>>, event_loop: Arc<EventLoop>, mem: GuestMemory, ) -> Self252     pub fn new(
253         slot_id: u8,
254         dcbaap: Register<u64>,
255         hub: Arc<UsbHub>,
256         interrupter: Arc<Mutex<Interrupter>>,
257         event_loop: Arc<EventLoop>,
258         mem: GuestMemory,
259     ) -> Self {
260         let transfer_ring_controllers = vec![None; TRANSFER_RING_CONTROLLERS_INDEX_END];
261         DeviceSlot {
262             slot_id,
263             port_id: PortId::new(),
264             dcbaap,
265             hub,
266             interrupter,
267             event_loop,
268             mem,
269             enabled: AtomicBool::new(false),
270             transfer_ring_controllers: Mutex::new(transfer_ring_controllers),
271         }
272     }
273 
get_trc(&self, i: usize) -> Option<Arc<TransferRingController>>274     fn get_trc(&self, i: usize) -> Option<Arc<TransferRingController>> {
275         let trcs = self.transfer_ring_controllers.lock();
276         trcs[i].clone()
277     }
278 
set_trc(&self, i: usize, trc: Option<Arc<TransferRingController>>)279     fn set_trc(&self, i: usize, trc: Option<Arc<TransferRingController>>) {
280         let mut trcs = self.transfer_ring_controllers.lock();
281         trcs[i] = trc;
282     }
283 
trc_len(&self) -> usize284     fn trc_len(&self) -> usize {
285         self.transfer_ring_controllers.lock().len()
286     }
287 
288     /// The arguments are identical to the fields in each doorbell register. The
289     /// target value:
290     /// 1: Reserved
291     /// 2: Control endpoint
292     /// 3: Endpoint 1 out
293     /// 4: Endpoint 1 in
294     /// 5: Endpoint 2 out
295     /// ...
296     /// 32: Endpoint 15 in
297     ///
298     /// Steam ID will be useful when host controller support streams.
299     /// The stream ID must be zero for endpoints that do not have streams
300     /// configured.
301     /// This function will return false if it fails to trigger transfer ring start.
ring_doorbell(&self, target: u8, _stream_id: u16) -> Result<bool>302     pub fn ring_doorbell(&self, target: u8, _stream_id: u16) -> Result<bool> {
303         if !valid_endpoint_id(target) {
304             error!(
305                 "device slot {}: Invalid target written to doorbell register. target: {}",
306                 self.slot_id, target
307             );
308             return Ok(false);
309         }
310         usb_debug!(
311             "device slot {}: ding-dong. who is that? target = {}",
312             self.slot_id,
313             target
314         );
315         // See DCI in spec.
316         let endpoint_index = (target - 1) as usize;
317         let transfer_ring_controller = match self.get_trc(endpoint_index) {
318             Some(tr) => tr,
319             None => {
320                 error!("Device endpoint is not inited");
321                 return Ok(false);
322             }
323         };
324         let context = self.get_device_context()?;
325         if context.endpoint_context[endpoint_index]
326             .get_endpoint_state()
327             .map_err(Error::GetEndpointState)?
328             == EndpointState::Running
329         {
330             usb_debug!("endpoint is started, start transfer ring");
331             transfer_ring_controller.start();
332         } else {
333             error!("doorbell rung when endpoint is not started");
334         }
335         Ok(true)
336     }
337 
338     /// Enable the slot. This function returns false if it's already enabled.
enable(&self) -> bool339     pub fn enable(&self) -> bool {
340         let was_already_enabled = self.enabled.swap(true, Ordering::SeqCst);
341         if was_already_enabled {
342             error!("device slot is already enabled");
343         } else {
344             usb_debug!("device slot {} enabled", self.slot_id);
345         }
346         !was_already_enabled
347     }
348 
349     /// Disable this device slot. If the slot is not enabled, callback will be invoked immediately
350     /// with error. Otherwise, callback will be invoked when all trc is stopped.
disable<C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send>( fail_handle: Arc<dyn FailHandle>, slot: &Arc<DeviceSlot>, mut callback: C, ) -> Result<()>351     pub fn disable<C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send>(
352         fail_handle: Arc<dyn FailHandle>,
353         slot: &Arc<DeviceSlot>,
354         mut callback: C,
355     ) -> Result<()> {
356         if slot.enabled.load(Ordering::SeqCst) {
357             let slot_weak = Arc::downgrade(slot);
358             let auto_callback =
359                 RingBufferStopCallback::new(fallible_closure(fail_handle, move || {
360                     // Slot should still be alive when the callback is invoked. If it's not, there
361                     // must be a bug somewhere.
362                     let slot = slot_weak.upgrade().ok_or(Error::WeakReferenceUpgrade)?;
363                     let mut device_context = slot.get_device_context()?;
364                     device_context
365                         .slot_context
366                         .set_slot_state(DeviceSlotState::DisabledOrEnabled);
367                     slot.set_device_context(device_context)?;
368                     slot.reset();
369                     usb_debug!(
370                         "device slot {}: all trc disabled, sending trb",
371                         slot.slot_id
372                     );
373                     callback(TrbCompletionCode::Success).map_err(|_| Error::CallbackFailed)
374                 }));
375             slot.stop_all_trc(auto_callback);
376             Ok(())
377         } else {
378             callback(TrbCompletionCode::SlotNotEnabledError).map_err(|_| Error::CallbackFailed)
379         }
380     }
381 
382     // Assigns the device address and initializes slot and endpoint 0 context.
set_address(&self, trb: &AddressDeviceCommandTrb) -> Result<TrbCompletionCode>383     pub fn set_address(&self, trb: &AddressDeviceCommandTrb) -> Result<TrbCompletionCode> {
384         if !self.enabled.load(Ordering::SeqCst) {
385             error!(
386                 "trying to set address to a disabled device slot {}",
387                 self.slot_id
388             );
389             return Ok(TrbCompletionCode::SlotNotEnabledError);
390         }
391         let device_context = self.get_device_context()?;
392         let state = device_context
393             .slot_context
394             .get_slot_state()
395             .map_err(Error::GetSlotContextState)?;
396         match state {
397             DeviceSlotState::DisabledOrEnabled => {}
398             DeviceSlotState::Default if !trb.get_block_set_address_request() => {}
399             _ => {
400                 error!("slot {} has unexpected slot state", self.slot_id);
401                 return Ok(TrbCompletionCode::ContextStateError);
402             }
403         }
404 
405         // Copy all fields of the slot context and endpoint 0 context from the input context
406         // to the output context.
407         let input_context_ptr = GuestAddress(trb.get_input_context_pointer());
408         // Copy slot context.
409         self.copy_context(input_context_ptr, 0)?;
410         // Copy control endpoint context.
411         self.copy_context(input_context_ptr, 1)?;
412 
413         // Read back device context.
414         let mut device_context = self.get_device_context()?;
415         let port_id = device_context.slot_context.get_root_hub_port_number();
416         self.port_id.set(port_id)?;
417         usb_debug!(
418             "port id {} is assigned to slot id {}",
419             port_id,
420             self.slot_id
421         );
422 
423         // Initialize the control endpoint. Endpoint id = 1.
424         self.set_trc(
425             0,
426             Some(
427                 TransferRingController::new(
428                     self.mem.clone(),
429                     self.hub.get_port(port_id).ok_or(Error::GetPort(port_id))?,
430                     self.event_loop.clone(),
431                     self.interrupter.clone(),
432                     self.slot_id,
433                     1,
434                 )
435                 .map_err(Error::CreateTransferController)?,
436             ),
437         );
438 
439         // Assign slot ID as device address if block_set_address_request is not set.
440         if trb.get_block_set_address_request() {
441             device_context
442                 .slot_context
443                 .set_slot_state(DeviceSlotState::Default);
444         } else {
445             let port = self.hub.get_port(port_id).ok_or(Error::GetPort(port_id))?;
446             match port.get_backend_device().as_mut() {
447                 Some(backend) => {
448                     backend.set_address(self.slot_id as u32);
449                 }
450                 None => {
451                     return Ok(TrbCompletionCode::TransactionError);
452                 }
453             }
454 
455             device_context
456                 .slot_context
457                 .set_usb_device_address(self.slot_id);
458             device_context
459                 .slot_context
460                 .set_slot_state(DeviceSlotState::Addressed);
461         }
462 
463         // TODO(jkwang) trc should always exists. Fix this.
464         self.get_trc(0)
465             .ok_or(Error::GetTrc(0))?
466             .set_dequeue_pointer(
467                 device_context.endpoint_context[0]
468                     .get_tr_dequeue_pointer()
469                     .get_gpa(),
470             );
471 
472         self.get_trc(0)
473             .ok_or(Error::GetTrc(0))?
474             .set_consumer_cycle_state(device_context.endpoint_context[0].get_dequeue_cycle_state());
475 
476         usb_debug!("Setting endpoint 0 to running");
477         device_context.endpoint_context[0].set_endpoint_state(EndpointState::Running);
478         self.set_device_context(device_context)?;
479         Ok(TrbCompletionCode::Success)
480     }
481 
482     // Adds or drops multiple endpoints in the device slot.
configure_endpoint( &self, trb: &ConfigureEndpointCommandTrb, ) -> Result<TrbCompletionCode>483     pub fn configure_endpoint(
484         &self,
485         trb: &ConfigureEndpointCommandTrb,
486     ) -> Result<TrbCompletionCode> {
487         usb_debug!("configuring endpoint");
488         let input_control_context = if trb.get_deconfigure() {
489             // From section 4.6.6 of the xHCI spec:
490             // Setting the deconfigure (DC) flag to '1' in the Configure Endpoint Command
491             // TRB is equivalent to setting Input Context Drop Context flags 2-31 to '1'
492             // and Add Context 2-31 flags to '0'.
493             let mut c = InputControlContext::new();
494             c.set_add_context_flags(0);
495             c.set_drop_context_flags(0xfffffffc);
496             c
497         } else {
498             self.mem
499                 .read_obj_from_addr(GuestAddress(trb.get_input_context_pointer()))
500                 .map_err(Error::ReadGuestMemory)?
501         };
502 
503         for device_context_index in 1..DCI_INDEX_END {
504             if input_control_context.drop_context_flag(device_context_index) {
505                 self.drop_one_endpoint(device_context_index)?;
506             }
507             if input_control_context.add_context_flag(device_context_index) {
508                 self.copy_context(
509                     GuestAddress(trb.get_input_context_pointer()),
510                     device_context_index,
511                 )?;
512                 self.add_one_endpoint(device_context_index)?;
513             }
514         }
515 
516         if trb.get_deconfigure() {
517             self.set_state(DeviceSlotState::Addressed)?;
518         } else {
519             self.set_state(DeviceSlotState::Configured)?;
520         }
521         Ok(TrbCompletionCode::Success)
522     }
523 
524     // Evaluates the device context by reading new values for certain fields of
525     // the slot context and/or control endpoint context.
evaluate_context(&self, trb: &EvaluateContextCommandTrb) -> Result<TrbCompletionCode>526     pub fn evaluate_context(&self, trb: &EvaluateContextCommandTrb) -> Result<TrbCompletionCode> {
527         if !self.enabled.load(Ordering::SeqCst) {
528             return Ok(TrbCompletionCode::SlotNotEnabledError);
529         }
530         // TODO(jkwang) verify this
531         // The spec has multiple contradictions about validating context parameters in sections
532         // 4.6.7, 6.2.3.3. To keep things as simple as possible we do no further validation here.
533         let input_control_context: InputControlContext = self
534             .mem
535             .read_obj_from_addr(GuestAddress(trb.get_input_context_pointer()))
536             .map_err(Error::ReadGuestMemory)?;
537 
538         let mut device_context = self.get_device_context()?;
539         if input_control_context.add_context_flag(0) {
540             let input_slot_context: SlotContext = self
541                 .mem
542                 .read_obj_from_addr(GuestAddress(
543                     trb.get_input_context_pointer() + DEVICE_CONTEXT_ENTRY_SIZE as u64,
544                 ))
545                 .map_err(Error::ReadGuestMemory)?;
546             device_context
547                 .slot_context
548                 .set_interrupter_target(input_slot_context.get_interrupter_target());
549 
550             device_context
551                 .slot_context
552                 .set_max_exit_latency(input_slot_context.get_max_exit_latency());
553         }
554 
555         // From 6.2.3.3: "Endpoint Contexts 2 throught 31 shall not be evaluated by the Evaluate
556         // Context Command".
557         if input_control_context.add_context_flag(1) {
558             let ep0_context: EndpointContext = self
559                 .mem
560                 .read_obj_from_addr(GuestAddress(
561                     trb.get_input_context_pointer() + 2 * DEVICE_CONTEXT_ENTRY_SIZE as u64,
562                 ))
563                 .map_err(Error::ReadGuestMemory)?;
564             device_context.endpoint_context[0]
565                 .set_max_packet_size(ep0_context.get_max_packet_size());
566         }
567         self.set_device_context(device_context)?;
568         Ok(TrbCompletionCode::Success)
569     }
570 
571     /// Reset the device slot to default state and deconfigures all but the
572     /// control endpoint.
reset_slot< C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send, >( fail_handle: Arc<dyn FailHandle>, slot: &Arc<DeviceSlot>, mut callback: C, ) -> Result<()>573     pub fn reset_slot<
574         C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send,
575     >(
576         fail_handle: Arc<dyn FailHandle>,
577         slot: &Arc<DeviceSlot>,
578         mut callback: C,
579     ) -> Result<()> {
580         let weak_s = Arc::downgrade(slot);
581         let auto_callback =
582             RingBufferStopCallback::new(fallible_closure(fail_handle, move || -> Result<()> {
583                 let s = weak_s.upgrade().ok_or(Error::WeakReferenceUpgrade)?;
584                 for i in FIRST_TRANSFER_ENDPOINT_DCI..DCI_INDEX_END {
585                     s.drop_one_endpoint(i)?;
586                 }
587                 let mut ctx = s.get_device_context()?;
588                 ctx.slot_context.set_slot_state(DeviceSlotState::Default);
589                 ctx.slot_context.set_context_entries(1);
590                 ctx.slot_context.set_root_hub_port_number(0);
591                 s.set_device_context(ctx)?;
592                 callback(TrbCompletionCode::Success).map_err(|_| Error::CallbackFailed)?;
593                 Ok(())
594             }));
595         slot.stop_all_trc(auto_callback);
596         Ok(())
597     }
598 
599     /// Stop all transfer ring controllers.
stop_all_trc(&self, auto_callback: RingBufferStopCallback)600     pub fn stop_all_trc(&self, auto_callback: RingBufferStopCallback) {
601         for i in 0..self.trc_len() {
602             if let Some(trc) = self.get_trc(i) {
603                 trc.stop(auto_callback.clone());
604             }
605         }
606     }
607 
608     /// Stop a endpoint.
stop_endpoint< C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send, >( &self, fail_handle: Arc<dyn FailHandle>, endpoint_id: u8, mut cb: C, ) -> Result<()>609     pub fn stop_endpoint<
610         C: FnMut(TrbCompletionCode) -> std::result::Result<(), ()> + 'static + Send,
611     >(
612         &self,
613         fail_handle: Arc<dyn FailHandle>,
614         endpoint_id: u8,
615         mut cb: C,
616     ) -> Result<()> {
617         if !valid_endpoint_id(endpoint_id) {
618             error!("trb indexing wrong endpoint id");
619             return cb(TrbCompletionCode::TrbError).map_err(|_| Error::CallbackFailed);
620         }
621         let index = endpoint_id - 1;
622         match self.get_trc(index as usize) {
623             Some(trc) => {
624                 usb_debug!("stopping endpoint");
625                 let auto_cb = RingBufferStopCallback::new(fallible_closure(
626                     fail_handle,
627                     move || -> Result<()> {
628                         cb(TrbCompletionCode::Success).map_err(|_| Error::CallbackFailed)
629                     },
630                 ));
631                 trc.stop(auto_cb);
632             }
633             None => {
634                 error!("endpoint at index {} is not started", index);
635                 cb(TrbCompletionCode::ContextStateError).map_err(|_| Error::CallbackFailed)?;
636             }
637         }
638         Ok(())
639     }
640 
641     /// Set transfer ring dequeue pointer.
set_tr_dequeue_ptr(&self, endpoint_id: u8, ptr: u64) -> Result<TrbCompletionCode>642     pub fn set_tr_dequeue_ptr(&self, endpoint_id: u8, ptr: u64) -> Result<TrbCompletionCode> {
643         if !valid_endpoint_id(endpoint_id) {
644             error!("trb indexing wrong endpoint id");
645             return Ok(TrbCompletionCode::TrbError);
646         }
647         let index = (endpoint_id - 1) as usize;
648         match self.get_trc(index) {
649             Some(trc) => {
650                 trc.set_dequeue_pointer(GuestAddress(ptr));
651                 let mut ctx = self.get_device_context()?;
652                 ctx.endpoint_context[index]
653                     .set_tr_dequeue_pointer(DequeuePtr::new(GuestAddress(ptr)));
654                 self.set_device_context(ctx)?;
655                 Ok(TrbCompletionCode::Success)
656             }
657             None => {
658                 error!("set tr dequeue ptr failed due to no trc started");
659                 Ok(TrbCompletionCode::ContextStateError)
660             }
661         }
662     }
663 
664     // Reset and reset_slot are different.
665     // Reset_slot handles command ring `reset slot` command. It will reset the slot state.
666     // Reset handles xhci reset. It will destroy everything.
reset(&self)667     fn reset(&self) {
668         for i in 0..self.trc_len() {
669             self.set_trc(i, None);
670         }
671         usb_debug!("reseting device slot {}!", self.slot_id);
672         self.enabled.store(false, Ordering::SeqCst);
673         self.port_id.reset();
674     }
675 
add_one_endpoint(&self, device_context_index: u8) -> Result<()>676     fn add_one_endpoint(&self, device_context_index: u8) -> Result<()> {
677         usb_debug!(
678             "adding one endpoint, device context index {}",
679             device_context_index
680         );
681         let mut device_context = self.get_device_context()?;
682         let transfer_ring_index = (device_context_index - 1) as usize;
683         let trc = TransferRingController::new(
684             self.mem.clone(),
685             self.hub
686                 .get_port(self.port_id.get()?)
687                 .ok_or(Error::GetPort(self.port_id.get()?))?,
688             self.event_loop.clone(),
689             self.interrupter.clone(),
690             self.slot_id,
691             device_context_index,
692         )
693         .map_err(Error::CreateTransferController)?;
694         trc.set_dequeue_pointer(
695             device_context.endpoint_context[transfer_ring_index]
696                 .get_tr_dequeue_pointer()
697                 .get_gpa(),
698         );
699         trc.set_consumer_cycle_state(
700             device_context.endpoint_context[transfer_ring_index].get_dequeue_cycle_state(),
701         );
702         self.set_trc(transfer_ring_index, Some(trc));
703         device_context.endpoint_context[transfer_ring_index]
704             .set_endpoint_state(EndpointState::Running);
705         self.set_device_context(device_context)
706     }
707 
drop_one_endpoint(&self, device_context_index: u8) -> Result<()>708     fn drop_one_endpoint(&self, device_context_index: u8) -> Result<()> {
709         let endpoint_index = (device_context_index - 1) as usize;
710         self.set_trc(endpoint_index, None);
711         let mut ctx = self.get_device_context()?;
712         ctx.endpoint_context[endpoint_index].set_endpoint_state(EndpointState::Disabled);
713         self.set_device_context(ctx)
714     }
715 
get_device_context(&self) -> Result<DeviceContext>716     fn get_device_context(&self) -> Result<DeviceContext> {
717         let ctx = self
718             .mem
719             .read_obj_from_addr(self.get_device_context_addr()?)
720             .map_err(Error::ReadGuestMemory)?;
721         usb_debug!("read device ctx: {:?}", ctx);
722         Ok(ctx)
723     }
724 
set_device_context(&self, device_context: DeviceContext) -> Result<()>725     fn set_device_context(&self, device_context: DeviceContext) -> Result<()> {
726         self.mem
727             .write_obj_at_addr(device_context, self.get_device_context_addr()?)
728             .map_err(Error::WriteGuestMemory)
729     }
730 
copy_context( &self, input_context_ptr: GuestAddress, device_context_index: u8, ) -> Result<()>731     fn copy_context(
732         &self,
733         input_context_ptr: GuestAddress,
734         device_context_index: u8,
735     ) -> Result<()> {
736         // Note that it could be slot context or device context. They have the same size. Won't
737         // make a difference here.
738         let ctx: EndpointContext = self
739             .mem
740             .read_obj_from_addr(
741                 input_context_ptr
742                     .checked_add(
743                         (device_context_index as u64 + 1) * DEVICE_CONTEXT_ENTRY_SIZE as u64,
744                     )
745                     .ok_or(Error::BadInputContextAddr(input_context_ptr))?,
746             )
747             .map_err(Error::ReadGuestMemory)?;
748         usb_debug!("context being copied {:?}", ctx);
749         let device_context_ptr = self.get_device_context_addr()?;
750         self.mem
751             .write_obj_at_addr(
752                 ctx,
753                 device_context_ptr
754                     .checked_add(device_context_index as u64 * DEVICE_CONTEXT_ENTRY_SIZE as u64)
755                     .ok_or(Error::BadDeviceContextAddr(device_context_ptr))?,
756             )
757             .map_err(Error::WriteGuestMemory)
758     }
759 
get_device_context_addr(&self) -> Result<GuestAddress>760     fn get_device_context_addr(&self) -> Result<GuestAddress> {
761         let addr: u64 = self
762             .mem
763             .read_obj_from_addr(GuestAddress(
764                 self.dcbaap.get_value() + size_of::<u64>() as u64 * self.slot_id as u64,
765             ))
766             .map_err(Error::ReadGuestMemory)?;
767         Ok(GuestAddress(addr))
768     }
769 
set_state(&self, state: DeviceSlotState) -> Result<()>770     fn set_state(&self, state: DeviceSlotState) -> Result<()> {
771         let mut ctx = self.get_device_context()?;
772         ctx.slot_context.set_slot_state(state);
773         self.set_device_context(ctx)
774     }
775 }
776