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