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