Refactor XHCI driver
This commit is contained in:
+1
-3
@@ -1,5 +1,3 @@
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate syscall;
|
||||
@@ -27,7 +25,7 @@ fn main() {
|
||||
|
||||
match Xhci::new(address) {
|
||||
Ok(mut xhci) => {
|
||||
xhci.init();
|
||||
xhci.probe();
|
||||
},
|
||||
Err(err) => {
|
||||
println!("xhcid: error: {}", err);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
use syscall::io::Mmio;
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct CapabilityRegs {
|
||||
pub len: Mmio<u8>,
|
||||
_rsvd: Mmio<u8>,
|
||||
pub hci_ver: Mmio<u16>,
|
||||
pub hcs_params1: Mmio<u32>,
|
||||
pub hcs_params2: Mmio<u32>,
|
||||
pub hcs_params3: Mmio<u32>,
|
||||
pub hcc_params1: Mmio<u32>,
|
||||
pub db_offset: Mmio<u32>,
|
||||
pub rts_offset: Mmio<u32>,
|
||||
pub hcc_params2: Mmio<u32>
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
use syscall::error::Result;
|
||||
use syscall::io::Dma;
|
||||
|
||||
use super::event::EventRing;
|
||||
use super::trb::Trb;
|
||||
|
||||
pub struct CommandRing {
|
||||
pub trbs: Dma<[Trb; 256]>,
|
||||
pub events: EventRing,
|
||||
}
|
||||
|
||||
impl CommandRing {
|
||||
pub fn new() -> Result<CommandRing> {
|
||||
Ok(CommandRing {
|
||||
trbs: Dma::zeroed()?,
|
||||
events: EventRing::new()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn crcr(&self) -> u64 {
|
||||
self.trbs.physical() as u64 | 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
use syscall::error::Result;
|
||||
use syscall::io::Dma;
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct SlotContext {
|
||||
inner: [u8; 32]
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct EndpointContext {
|
||||
inner: [u8; 32]
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct DeviceContext {
|
||||
pub slot: SlotContext,
|
||||
pub endpoints: [EndpointContext; 15]
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct InputContext {
|
||||
pub drop_context: Mmio<u32>,
|
||||
pub add_context: Mmio<u32>,
|
||||
_rsvd: [Mmio<u32>; 5],
|
||||
pub control: Mmio<u32>,
|
||||
pub device: DeviceContext,
|
||||
}
|
||||
|
||||
pub struct DeviceList {
|
||||
pub dcbaa: Dma<[u64; 256]>,
|
||||
pub contexts: Vec<Dma<DeviceContext>>,
|
||||
}
|
||||
|
||||
impl DeviceList {
|
||||
pub fn new(max_slots: u8) -> Result<DeviceList> {
|
||||
let mut dcbaa = Dma::<[u64; 256]>::zeroed()?;
|
||||
let mut contexts = vec![];
|
||||
|
||||
// Create device context buffers for each slot
|
||||
for i in 0..max_slots as usize {
|
||||
println!(" - Setup dev ctx {}", i);
|
||||
let context: Dma<DeviceContext> = Dma::zeroed()?;
|
||||
dcbaa[i] = context.physical() as u64;
|
||||
contexts.push(context);
|
||||
}
|
||||
|
||||
Ok(DeviceList {
|
||||
dcbaa: dcbaa,
|
||||
contexts: contexts
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dcbaap(&self) -> u64 {
|
||||
self.dcbaa.physical() as u64
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
use syscall::io::{Io, Mmio};
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct Doorbell(Mmio<u32>);
|
||||
|
||||
impl Doorbell {
|
||||
pub fn read(&self) -> u32 {
|
||||
self.0.read()
|
||||
}
|
||||
|
||||
pub fn write(&mut self, data: u32) {
|
||||
self.0.write(data);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ use syscall::io::{Dma, Io, Mmio};
|
||||
|
||||
use super::trb::Trb;
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct EventRingSte {
|
||||
pub address: Mmio<u64>,
|
||||
pub size: Mmio<u16>,
|
||||
|
||||
+77
-199
@@ -1,154 +1,42 @@
|
||||
use std::slice;
|
||||
use syscall::error::Result;
|
||||
use syscall::io::{Dma, Mmio, Io};
|
||||
use syscall::io::Io;
|
||||
|
||||
mod capability;
|
||||
mod command;
|
||||
mod device;
|
||||
mod doorbell;
|
||||
mod event;
|
||||
mod operational;
|
||||
mod port;
|
||||
mod runtime;
|
||||
mod trb;
|
||||
|
||||
use self::event::*;
|
||||
use self::trb::*;
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct XhciCap {
|
||||
len: Mmio<u8>,
|
||||
_rsvd: Mmio<u8>,
|
||||
hci_ver: Mmio<u16>,
|
||||
hcs_params1: Mmio<u32>,
|
||||
hcs_params2: Mmio<u32>,
|
||||
hcs_params3: Mmio<u32>,
|
||||
hcc_params1: Mmio<u32>,
|
||||
db_offset: Mmio<u32>,
|
||||
rts_offset: Mmio<u32>,
|
||||
hcc_params2: Mmio<u32>
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct XhciOp {
|
||||
usb_cmd: Mmio<u32>,
|
||||
usb_sts: Mmio<u32>,
|
||||
page_size: Mmio<u32>,
|
||||
_rsvd: [Mmio<u32>; 2],
|
||||
dn_ctrl: Mmio<u32>,
|
||||
crcr: Mmio<u64>,
|
||||
_rsvd2: [Mmio<u32>; 4],
|
||||
dcbaap: Mmio<u64>,
|
||||
config: Mmio<u32>,
|
||||
}
|
||||
|
||||
pub struct XhciInterrupter {
|
||||
iman: Mmio<u32>,
|
||||
imod: Mmio<u32>,
|
||||
erstsz: Mmio<u32>,
|
||||
_rsvd: Mmio<u32>,
|
||||
erstba: Mmio<u64>,
|
||||
erdp: Mmio<u64>,
|
||||
}
|
||||
|
||||
pub struct XhciRun {
|
||||
mfindex: Mmio<u32>,
|
||||
_rsvd: [Mmio<u32>; 7],
|
||||
ints: [XhciInterrupter; 1024],
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
flags XhciPortFlags: u32 {
|
||||
const PORT_CCS = 1 << 0,
|
||||
const PORT_PED = 1 << 1,
|
||||
const PORT_OCA = 1 << 3,
|
||||
const PORT_PR = 1 << 4,
|
||||
const PORT_PP = 1 << 9,
|
||||
const PORT_PIC_AMB = 1 << 14,
|
||||
const PORT_PIC_GRN = 1 << 15,
|
||||
const PORT_LWS = 1 << 16,
|
||||
const PORT_CSC = 1 << 17,
|
||||
const PORT_PEC = 1 << 18,
|
||||
const PORT_WRC = 1 << 19,
|
||||
const PORT_OCC = 1 << 20,
|
||||
const PORT_PRC = 1 << 21,
|
||||
const PORT_PLC = 1 << 22,
|
||||
const PORT_CEC = 1 << 23,
|
||||
const PORT_CAS = 1 << 24,
|
||||
const PORT_WCE = 1 << 25,
|
||||
const PORT_WDE = 1 << 26,
|
||||
const PORT_WOE = 1 << 27,
|
||||
const PORT_DR = 1 << 30,
|
||||
const PORT_WPR = 1 << 31,
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct XhciPort {
|
||||
portsc : Mmio<u32>,
|
||||
portpmsc : Mmio<u32>,
|
||||
portli : Mmio<u32>,
|
||||
porthlpmc : Mmio<u32>,
|
||||
}
|
||||
|
||||
impl XhciPort {
|
||||
fn read(&self) -> u32 {
|
||||
self.portsc.read()
|
||||
}
|
||||
|
||||
fn state(&self) -> u32 {
|
||||
(self.read() & (0b1111 << 5)) >> 5
|
||||
}
|
||||
|
||||
fn speed(&self) -> u32 {
|
||||
(self.read() & (0b1111 << 10)) >> 10
|
||||
}
|
||||
|
||||
fn flags(&self) -> XhciPortFlags {
|
||||
XhciPortFlags::from_bits_truncate(self.read())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct XhciDoorbell(Mmio<u32>);
|
||||
|
||||
impl XhciDoorbell {
|
||||
fn read(&self) -> u32 {
|
||||
self.0.read()
|
||||
}
|
||||
|
||||
fn write(&mut self, data: u32) {
|
||||
self.0.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct XhciSlotContext {
|
||||
inner: [u8; 32]
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct XhciEndpointContext {
|
||||
inner: [u8; 32]
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct XhciDeviceContext {
|
||||
slot: XhciSlotContext,
|
||||
endpoints: [XhciEndpointContext; 15]
|
||||
}
|
||||
use self::capability::CapabilityRegs;
|
||||
use self::command::CommandRing;
|
||||
use self::device::DeviceList;
|
||||
use self::doorbell::Doorbell;
|
||||
use self::operational::OperationalRegs;
|
||||
use self::port::Port;
|
||||
use self::runtime::RuntimeRegs;
|
||||
|
||||
pub struct Xhci {
|
||||
cap: &'static mut XhciCap,
|
||||
op: &'static mut XhciOp,
|
||||
ports: &'static mut [XhciPort],
|
||||
dbs: &'static mut [XhciDoorbell],
|
||||
run: &'static mut XhciRun,
|
||||
dev_baa: Dma<[u64; 256]>,
|
||||
dev_ctxs: Vec<Dma<XhciDeviceContext>>,
|
||||
cmds: Dma<[Trb; 256]>,
|
||||
events: [EventRing; 1],
|
||||
cap: &'static mut CapabilityRegs,
|
||||
op: &'static mut OperationalRegs,
|
||||
ports: &'static mut [Port],
|
||||
dbs: &'static mut [Doorbell],
|
||||
run: &'static mut RuntimeRegs,
|
||||
devices: DeviceList,
|
||||
cmd: CommandRing,
|
||||
}
|
||||
|
||||
impl Xhci {
|
||||
pub fn new(address: usize) -> Result<Xhci> {
|
||||
let cap = unsafe { &mut *(address as *mut XhciCap) };
|
||||
let cap = unsafe { &mut *(address as *mut CapabilityRegs) };
|
||||
println!(" - CAP {:X}", address);
|
||||
|
||||
let op_base = address + cap.len.read() as usize;
|
||||
let op = unsafe { &mut *(op_base as *mut XhciOp) };
|
||||
let op = unsafe { &mut *(op_base as *mut OperationalRegs) };
|
||||
println!(" - OP {:X}", op_base);
|
||||
|
||||
let max_slots;
|
||||
@@ -174,27 +62,22 @@ impl Xhci {
|
||||
println!(" - Read max slots");
|
||||
// Read maximum slots and ports
|
||||
let hcs_params1 = cap.hcs_params1.read();
|
||||
max_slots = hcs_params1 & 0xFF;
|
||||
max_ports = (hcs_params1 & 0xFF000000) >> 24;
|
||||
max_slots = (hcs_params1 & 0xFF) as u8;
|
||||
max_ports = ((hcs_params1 & 0xFF000000) >> 24) as u8;
|
||||
|
||||
println!(" - Max Slots: {}, Max Ports {}", max_slots, max_ports);
|
||||
|
||||
println!(" - Set enabled slots");
|
||||
// Set enabled slots
|
||||
op.config.write(max_slots);
|
||||
println!(" - Enabled Slots: {}", op.config.read() & 0xFF);
|
||||
}
|
||||
|
||||
let port_base = op_base + 0x400;
|
||||
let ports = unsafe { slice::from_raw_parts_mut(port_base as *mut XhciPort, max_ports as usize) };
|
||||
let ports = unsafe { slice::from_raw_parts_mut(port_base as *mut Port, max_ports as usize) };
|
||||
println!(" - PORT {:X}", port_base);
|
||||
|
||||
let db_base = address + cap.db_offset.read() as usize;
|
||||
let dbs = unsafe { slice::from_raw_parts_mut(db_base as *mut XhciDoorbell, 256) };
|
||||
let dbs = unsafe { slice::from_raw_parts_mut(db_base as *mut Doorbell, 256) };
|
||||
println!(" - DOORBELL {:X}", db_base);
|
||||
|
||||
let run_base = address + cap.rts_offset.read() as usize;
|
||||
let run = unsafe { &mut *(run_base as *mut XhciRun) };
|
||||
let run = unsafe { &mut *(run_base as *mut RuntimeRegs) };
|
||||
println!(" - RUNTIME {:X}", run_base);
|
||||
|
||||
let mut xhci = Xhci {
|
||||
@@ -203,58 +86,53 @@ impl Xhci {
|
||||
ports: ports,
|
||||
dbs: dbs,
|
||||
run: run,
|
||||
dev_baa: Dma::zeroed()?,
|
||||
dev_ctxs: Vec::new(),
|
||||
cmds: Dma::zeroed()?,
|
||||
events: [
|
||||
EventRing::new()?
|
||||
],
|
||||
devices: DeviceList::new(max_slots)?,
|
||||
cmd: CommandRing::new()?,
|
||||
};
|
||||
|
||||
{
|
||||
// Create device context buffers for each slot
|
||||
for i in 0..max_slots as usize {
|
||||
println!(" - Setup dev ctx {}", i);
|
||||
let dev_ctx: Dma<XhciDeviceContext> = Dma::zeroed()?;
|
||||
xhci.dev_baa[i] = dev_ctx.physical() as u64;
|
||||
xhci.dev_ctxs.push(dev_ctx);
|
||||
}
|
||||
|
||||
println!(" - Write DCBAAP");
|
||||
// Set device context address array pointer
|
||||
xhci.op.dcbaap.write(xhci.dev_baa.physical() as u64);
|
||||
|
||||
println!(" - Write CRCR");
|
||||
// Set command ring control register
|
||||
xhci.op.crcr.write(xhci.cmds.physical() as u64 | 1);
|
||||
|
||||
println!(" - Write ERST");
|
||||
// Set event ring segment table registers
|
||||
xhci.run.ints[0].erstsz.write(1);
|
||||
xhci.run.ints[0].erstba.write(xhci.events[0].ste.physical() as u64);
|
||||
xhci.run.ints[0].erdp.write(xhci.events[0].trbs.physical() as u64);
|
||||
|
||||
println!(" - Start");
|
||||
// Set run/stop to 1
|
||||
xhci.op.usb_cmd.writef(1, true);
|
||||
|
||||
println!(" - Wait for running");
|
||||
// Wait until controller is running
|
||||
while xhci.op.usb_sts.readf(1) {
|
||||
println!(" - Waiting for XHCI running");
|
||||
}
|
||||
|
||||
println!(" - Ring doorbell");
|
||||
// Ring command doorbell
|
||||
xhci.dbs[0].write(0);
|
||||
|
||||
println!(" - XHCI initialized");
|
||||
}
|
||||
xhci.init(max_slots);
|
||||
|
||||
Ok(xhci)
|
||||
}
|
||||
|
||||
pub fn init(&mut self) {
|
||||
pub fn init(&mut self, max_slots: u8) {
|
||||
println!(" - Set enabled slots");
|
||||
// Set enabled slots
|
||||
self.op.config.write(max_slots as u32);
|
||||
println!(" - Enabled Slots: {}", self.op.config.read() & 0xFF);
|
||||
|
||||
println!(" - Write DCBAAP");
|
||||
// Set device context address array pointer
|
||||
self.op.dcbaap.write(self.devices.dcbaap());
|
||||
|
||||
println!(" - Write CRCR");
|
||||
// Set command ring control register
|
||||
self.op.crcr.write(self.cmd.crcr());
|
||||
|
||||
println!(" - Write ERST");
|
||||
// Set event ring segment table registers
|
||||
self.run.ints[0].erstsz.write(1);
|
||||
self.run.ints[0].erstba.write(self.cmd.events.ste.physical() as u64);
|
||||
self.run.ints[0].erdp.write(self.cmd.events.trbs.physical() as u64);
|
||||
|
||||
println!(" - Start");
|
||||
// Set run/stop to 1
|
||||
self.op.usb_cmd.writef(1, true);
|
||||
|
||||
println!(" - Wait for running");
|
||||
// Wait until controller is running
|
||||
while self.op.usb_sts.readf(1) {
|
||||
println!(" - Waiting for XHCI running");
|
||||
}
|
||||
|
||||
println!(" - Ring doorbell");
|
||||
// Ring command doorbell
|
||||
self.dbs[0].write(0);
|
||||
|
||||
println!(" - XHCI initialized");
|
||||
}
|
||||
|
||||
pub fn probe(&mut self) {
|
||||
for (i, port) in self.ports.iter().enumerate() {
|
||||
let data = port.read();
|
||||
let state = port.state();
|
||||
@@ -265,12 +143,12 @@ impl Xhci {
|
||||
|
||||
println!(" - Running Enable Slot command");
|
||||
|
||||
self.cmds[0].enable_slot(0, true);
|
||||
self.cmd.trbs[0].enable_slot(0, true);
|
||||
|
||||
println!(" - Command");
|
||||
println!(" - data: {:X}", self.cmds[0].data.read());
|
||||
println!(" - status: {:X}", self.cmds[0].status.read());
|
||||
println!(" - control: {:X}", self.cmds[0].control.read());
|
||||
println!(" - data: {:X}", self.cmd.trbs[0].data.read());
|
||||
println!(" - status: {:X}", self.cmd.trbs[0].status.read());
|
||||
println!(" - control: {:X}", self.cmd.trbs[0].control.read());
|
||||
|
||||
self.dbs[0].write(0);
|
||||
|
||||
@@ -280,8 +158,8 @@ impl Xhci {
|
||||
}
|
||||
|
||||
println!(" - Response");
|
||||
println!(" - data: {:X}", self.events[0].trbs[0].data.read());
|
||||
println!(" - status: {:X}", self.events[0].trbs[0].status.read());
|
||||
println!(" - control: {:X}", self.events[0].trbs[0].control.read());
|
||||
println!(" - data: {:X}", self.cmd.events.trbs[0].data.read());
|
||||
println!(" - status: {:X}", self.cmd.events.trbs[0].status.read());
|
||||
println!(" - control: {:X}", self.cmd.events.trbs[0].control.read());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
use syscall::io::Mmio;
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct OperationalRegs {
|
||||
pub usb_cmd: Mmio<u32>,
|
||||
pub usb_sts: Mmio<u32>,
|
||||
pub page_size: Mmio<u32>,
|
||||
_rsvd: [Mmio<u32>; 2],
|
||||
pub dn_ctrl: Mmio<u32>,
|
||||
pub crcr: Mmio<u64>,
|
||||
_rsvd2: [Mmio<u32>; 4],
|
||||
pub dcbaap: Mmio<u64>,
|
||||
pub config: Mmio<u32>,
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
use syscall::io::{Io, Mmio};
|
||||
|
||||
bitflags! {
|
||||
pub flags PortFlags: u32 {
|
||||
const PORT_CCS = 1 << 0,
|
||||
const PORT_PED = 1 << 1,
|
||||
const PORT_OCA = 1 << 3,
|
||||
const PORT_PR = 1 << 4,
|
||||
const PORT_PP = 1 << 9,
|
||||
const PORT_PIC_AMB = 1 << 14,
|
||||
const PORT_PIC_GRN = 1 << 15,
|
||||
const PORT_LWS = 1 << 16,
|
||||
const PORT_CSC = 1 << 17,
|
||||
const PORT_PEC = 1 << 18,
|
||||
const PORT_WRC = 1 << 19,
|
||||
const PORT_OCC = 1 << 20,
|
||||
const PORT_PRC = 1 << 21,
|
||||
const PORT_PLC = 1 << 22,
|
||||
const PORT_CEC = 1 << 23,
|
||||
const PORT_CAS = 1 << 24,
|
||||
const PORT_WCE = 1 << 25,
|
||||
const PORT_WDE = 1 << 26,
|
||||
const PORT_WOE = 1 << 27,
|
||||
const PORT_DR = 1 << 30,
|
||||
const PORT_WPR = 1 << 31,
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct Port {
|
||||
pub portsc : Mmio<u32>,
|
||||
pub portpmsc : Mmio<u32>,
|
||||
pub portli : Mmio<u32>,
|
||||
pub porthlpmc : Mmio<u32>,
|
||||
}
|
||||
|
||||
impl Port {
|
||||
pub fn read(&self) -> u32 {
|
||||
self.portsc.read()
|
||||
}
|
||||
|
||||
pub fn state(&self) -> u32 {
|
||||
(self.read() & (0b1111 << 5)) >> 5
|
||||
}
|
||||
|
||||
pub fn speed(&self) -> u32 {
|
||||
(self.read() & (0b1111 << 10)) >> 10
|
||||
}
|
||||
|
||||
pub fn flags(&self) -> PortFlags {
|
||||
PortFlags::from_bits_truncate(self.read())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
use syscall::io::Mmio;
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct Interrupter {
|
||||
pub iman: Mmio<u32>,
|
||||
pub imod: Mmio<u32>,
|
||||
pub erstsz: Mmio<u32>,
|
||||
_rsvd: Mmio<u32>,
|
||||
pub erstba: Mmio<u64>,
|
||||
pub erdp: Mmio<u64>,
|
||||
}
|
||||
|
||||
#[repr(packed)]
|
||||
pub struct RuntimeRegs {
|
||||
pub mfindex: Mmio<u32>,
|
||||
_rsvd: [Mmio<u32>; 7],
|
||||
pub ints: [Interrupter; 1024],
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
use std::cell::RefCell;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Weak;
|
||||
|
||||
use syscall::error::{Error, Result, EBADF, EINVAL, EPIPE};
|
||||
use syscall::flag::{F_GETFL, F_SETFL, O_ACCMODE};
|
||||
|
||||
use pty::Pty;
|
||||
use resource::Resource;
|
||||
|
||||
/// Read side of a pipe
|
||||
#[derive(Clone)]
|
||||
pub struct PtyTermios {
|
||||
pty: Weak<RefCell<Pty>>,
|
||||
flags: usize,
|
||||
}
|
||||
|
||||
impl PtyTermios {
|
||||
pub fn new(pty: Weak<RefCell<Pty>>, flags: usize) -> Self {
|
||||
PtyTermios {
|
||||
pty: pty,
|
||||
flags: flags,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource for PtyTermios {
|
||||
fn boxed_clone(&self) -> Box<Resource> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
|
||||
fn pty(&self) -> Weak<RefCell<Pty>> {
|
||||
self.pty.clone()
|
||||
}
|
||||
|
||||
fn flags(&self) -> usize {
|
||||
self.flags
|
||||
}
|
||||
|
||||
fn path(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
pty_lock.borrow_mut().path(buf)
|
||||
} else {
|
||||
Err(Error::new(EPIPE))
|
||||
}
|
||||
}
|
||||
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let pty = pty_lock.borrow();
|
||||
let termios: &[u8] = pty.termios.deref();
|
||||
|
||||
let mut i = 0;
|
||||
while i < buf.len() && i < termios.len() {
|
||||
buf[i] = termios[i];
|
||||
i += 1;
|
||||
}
|
||||
Ok(i)
|
||||
} else {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
if let Some(pty_lock) = self.pty.upgrade() {
|
||||
let mut pty = pty_lock.borrow_mut();
|
||||
let termios: &mut [u8] = pty.termios.deref_mut();
|
||||
|
||||
let mut i = 0;
|
||||
while i < buf.len() && i < termios.len() {
|
||||
termios[i] = buf[i];
|
||||
i += 1;
|
||||
}
|
||||
Ok(i)
|
||||
} else {
|
||||
Err(Error::new(EPIPE))
|
||||
}
|
||||
}
|
||||
|
||||
fn sync(&self) -> Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
|
||||
match cmd {
|
||||
F_GETFL => Ok(self.flags),
|
||||
F_SETFL => {
|
||||
self.flags = (self.flags & O_ACCMODE) | (arg & ! O_ACCMODE);
|
||||
Ok(0)
|
||||
},
|
||||
_ => Err(Error::new(EINVAL))
|
||||
}
|
||||
}
|
||||
|
||||
fn fevent(&self) -> Result<()> {
|
||||
Err(Error::new(EBADF))
|
||||
}
|
||||
|
||||
fn fevent_count(&self) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user