blob: 52deea4fd21bd1db8192c65c8b436a15cea26e14 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVICES_USB_DRIVERS_XHCI_REWRITE_XHCI_DEVICE_STATE_H_
#define SRC_DEVICES_USB_DRIVERS_XHCI_REWRITE_XHCI_DEVICE_STATE_H_
#include <optional>
#include "xhci-hub.h"
#include "xhci-transfer-ring.h"
#include "zircon/compiler.h"
namespace usb_xhci {
// The maximum number of endpoints a USB device can support
constexpr size_t kMaxEndpoints = 32;
class DeviceState {
public:
void Disconnect() __TA_REQUIRES(transaction_lock_) { disconnecting_ = true; }
void reset() __TA_REQUIRES(transaction_lock_) {
disconnecting_ = true;
input_context_.reset();
device_context_.reset();
slot_ = 0;
hub_.reset();
tr_.Deinit();
for (size_t i = 0; i < kMaxEndpoints; i++) {
rings_[i].DeinitIfActive();
}
}
void SetDeviceInformation(uint8_t slot, uint8_t port, const std::optional<HubInfo>& hub)
__TA_REQUIRES(transaction_lock_) {
slot_ = slot;
port_ = port;
hub_ = hub;
disconnecting_ = false;
}
// True if the device state has been initialized, false otherwise.
bool valid() { return slot_; }
uint8_t GetPort() { return port_; }
uint8_t GetSlot() { return slot_; }
std::optional<HubInfo>& GetHub() __TA_REQUIRES(transaction_lock_) { return hub_; }
bool IsDisconnecting() __TA_REQUIRES(transaction_lock_) { return disconnecting_; }
TransferRing& GetTransferRing() __TA_REQUIRES(transaction_lock_) { return tr_; }
TransferRing& GetTransferRing(size_t endpoint) __TA_REQUIRES(transaction_lock_) {
return rings_[endpoint];
}
std::unique_ptr<dma_buffer::PagedBuffer>& GetInputContext() __TA_REQUIRES(transaction_lock_) {
return input_context_;
}
std::unique_ptr<dma_buffer::PagedBuffer>& GetDeviceContext() __TA_REQUIRES(transaction_lock_) {
return device_context_;
}
TRBPromise AddressDeviceCommand(UsbXhci* hci, uint8_t slot_id, uint8_t port_id,
std::optional<HubInfo> hub_info, uint64_t* dcbaa,
EventRing* event_ring, CommandRing* command_ring,
ddk::MmioBuffer* mmio, bool bsr);
zx_status_t InitializeSlotBuffer(const UsbXhci& hci, uint8_t slot_id, uint8_t port_id,
const std::optional<HubInfo>& hub_info,
std::unique_ptr<dma_buffer::PagedBuffer>* out);
zx_status_t InitializeEndpointContext(const UsbXhci& hci, uint8_t slot_id, uint8_t port_id,
const std::optional<HubInfo>& hub_info,
dma_buffer::PagedBuffer* slot_context_buffer)
__TA_REQUIRES(transaction_lock_);
zx_status_t InitializeOutputContextBuffer(const UsbXhci& hci, uint8_t slot_id, uint8_t port_id,
const std::optional<HubInfo>& hub_info, uint64_t* dcbaa,
std::unique_ptr<dma_buffer::PagedBuffer>* out)
__TA_REQUIRES(transaction_lock_);
fbl::Mutex& transaction_lock() __TA_RETURN_CAPABILITY(transaction_lock_) {
return transaction_lock_;
}
private:
uint8_t slot_ = 0;
uint8_t port_ = 0;
fbl::Mutex transaction_lock_;
std::optional<HubInfo> hub_ __TA_GUARDED(transaction_lock_);
bool disconnecting_ __TA_GUARDED(transaction_lock_) = false;
TransferRing tr_ __TA_GUARDED(transaction_lock_);
TransferRing rings_[kMaxEndpoints] __TA_GUARDED(transaction_lock_);
std::unique_ptr<dma_buffer::PagedBuffer> input_context_ __TA_GUARDED(transaction_lock_);
std::unique_ptr<dma_buffer::PagedBuffer> device_context_ __TA_GUARDED(transaction_lock_);
};
} // namespace usb_xhci
#endif // SRC_DEVICES_USB_DRIVERS_XHCI_REWRITE_XHCI_DEVICE_STATE_H_