From 20509514d857f9a3bb4d397613ed1a13cad7df97 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Sun, 27 Apr 2025 14:20:14 -0500 Subject: [PATCH 01/13] Net USB Receive fixes --- crates/kernel/scripts/run-usb.sh | 2 +- .../kernel/src/device/usb/hcd/dwc/dwc_otg.rs | 11 ++- crates/kernel/src/device/usb/usbd/endpoint.rs | 72 +++++++++++++------ crates/kernel/src/networking/iface/arp.rs | 2 +- crates/kernel/src/networking/iface/cdcecm.rs | 1 + crates/kernel/src/networking/iface/ipv4.rs | 4 +- crates/kernel/src/networking/repr/ipv4.rs | 2 +- crates/kernel/src/runtime.rs | 2 +- 8 files changed, 68 insertions(+), 28 deletions(-) diff --git a/crates/kernel/scripts/run-usb.sh b/crates/kernel/scripts/run-usb.sh index 6bd83720..80e66e19 100755 --- a/crates/kernel/scripts/run-usb.sh +++ b/crates/kernel/scripts/run-usb.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -ex -QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev bridge,id=net0,br=br0 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" diff --git a/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs index ccfa50a7..2142af76 100644 --- a/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs +++ b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs @@ -36,7 +36,7 @@ use alloc::boxed::Box; pub const ChannelCount: usize = 8; pub static mut dwc_otg_driver: DWC_OTG = DWC_OTG { base_addr: 0 }; -// The USB_TRANSFER_QUEUE will hold future USB transfer requests (Usb Xfer). A channel is a representation by the USB spec to be able to access an endpoint (the thing talking to the USB device). +// The USB_TRANSFER_QUEUE will hold future USB transfer requests (Usb Xfer). A channel is a resentation by the USB spec to be able to access an endpoint (the thing talking to the USB device). // Callbacks are the method that should be invoked once the data has been transferred. // USBD should first create a usb_xfer on the USB_TRANSFER_QUEUE and then see if a channel is available. // if a channel is available, it will be assigned to the usb_xfer and the callback will be set. @@ -780,7 +780,7 @@ fn HcdChannelSendOne( | HCINTMSK_CHHLTDMSK | HCINTMSK_AHBERRMSK | HCINTMSK_STALLMSK - | HCINTMSK_NAKMSK + // | HCINTMSK_NAKMSK | HCINTMSK_ACKMSK | HCINTMSK_NYETMSK | HCINTMSK_XACTERRMSK @@ -937,6 +937,13 @@ pub unsafe fn HcdSubmitInterruptMessage( return ResultCode::OK; } +pub fn DwcDisableChannel(channel: u8) { + let mut hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + hcchar &= !HCCHAR_CHENA; + hcchar |= HCCHAR_CHDIS; + write_volatile(DOTG_HCCHAR(channel as usize), hcchar); +} + pub fn printDWCErrors(channel: u32) { let hprt = read_volatile(DOTG_HPRT); let gintsts = read_volatile(DOTG_GINTSTS); diff --git a/crates/kernel/src/device/usb/usbd/endpoint.rs b/crates/kernel/src/device/usb/usbd/endpoint.rs index 2d751f39..6820e204 100644 --- a/crates/kernel/src/device/usb/usbd/endpoint.rs +++ b/crates/kernel/src/device/usb/usbd/endpoint.rs @@ -19,6 +19,11 @@ use usb::types::*; use usb::usbd::device::*; use usb::usbd::pipe::*; use usb::PacketId; +use crate::device::usb::hcd::dwc::dwc_otg; +use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; +use crate::device::usb::DwcDisableChannel; +use crate::device::system_timer::micro_delay; + use crate::event::task::spawn_async_rt; use crate::shutdown; @@ -34,7 +39,7 @@ pub fn finish_bulk_endpoint_callback_in( let device = unsafe { &mut *endpoint.device }; let transfer_size = HcdUpdateTransferSize(device, channel); - device.last_transfer = endpoint.buffer_length - transfer_size; + let last_transfer = endpoint.buffer_length - transfer_size; let endpoint_device = device.driver_data.downcast::().unwrap(); if hcint & HCINT_NAK != 0 { @@ -47,22 +52,28 @@ pub fn finish_bulk_endpoint_callback_in( // } println!( "| Endpoint {} in: HCINT_NAK with transfer hcint: {:x} last transfer: {}", - channel, hcint, device.last_transfer + channel, hcint, last_transfer ); - if device.last_transfer > 0 && (hcint & HCINT_CHHLTD == 0) && (hcint & HCINT_XFERCOMPL == 0) + if last_transfer > 0 && (hcint & HCINT_CHHLTD == 0) && (hcint & HCINT_XFERCOMPL == 0) { - DwcActivateChannel(channel); + // DwcActivateChannel(channel); return false; } else { - return true; + println!( + "| Endpoint {} in: HCINT_NAK with transfer, aborting. hcint: {:x} last transfer: {} Bulk in \n\n", + channel, hcint, last_transfer + ); + // return true; } + } // return; // WARN: aaron said to comment this out - } else if hcint & HCINT_CHHLTD == 0 { + + if hcint & HCINT_CHHLTD == 0 { panic!( "| Endpoint {} in: HCINT_CHHLTD not set, aborting. hcint: {:x} last transfer: {}", - channel, hcint, device.last_transfer + channel, hcint, last_transfer ); } else if hcint & HCINT_XFERCOMPL == 0 { panic!( @@ -85,7 +96,7 @@ pub fn finish_bulk_endpoint_callback_in( // Also, we suffer issue from buffer_length not being known before the copy so the callback likely will have better information about the buffer if let Some(callback) = endpoint_device.endpoints[endpoint.device_endpoint_number as usize] { // TODO: make this take a slice - unsafe { callback(dma_addr as *mut u8, device.last_transfer) }; + unsafe { callback(dma_addr as *mut u8, last_transfer) }; } else { panic!( "| USB: No callback for endpoint number {}.", @@ -102,21 +113,23 @@ pub fn finish_bulk_endpoint_callback_out( ) -> bool { let device = unsafe { &mut *endpoint.device }; let transfer_size = HcdUpdateTransferSize(device, channel); - device.last_transfer = endpoint.buffer_length - transfer_size; + let last_transfer = endpoint.buffer_length - transfer_size; + println!("Bulk out transfer hcint {:x} , last transfer: {} ", hcint, last_transfer); if hcint & HCINT_CHHLTD == 0 { - panic!("| Endpoint {}: HCINT_CHHLTD not set, aborting.", channel); + panic!("| Endpoint {}: HCINT_CHHLTD not set, aborting. bulk out hcint {:x}", channel, hcint); } if hcint & HCINT_XFERCOMPL == 0 { - panic!("| Endpoint {}: HCINT_XFERCOMPL not set, aborting.", channel); + panic!("| Endpoint {}: HCINT_XFERCOMPL not set, aborting. bulk out hcint {:x}", channel, hcint); } + //Most Likely not going to be called but could be useful for cases where precise timing of when message gets off the system is needed let endpoint_device = device.driver_data.downcast::().unwrap(); if let Some(callback) = endpoint_device.endpoints[endpoint.device_endpoint_number as usize] { let mut buffer = [0]; //fake buffer - unsafe { callback(buffer.as_mut_ptr(), device.last_transfer) }; + unsafe { callback(buffer.as_mut_ptr(), last_transfer) }; } else { panic!( "| USB: No callback for endpoint number {}.", @@ -129,12 +142,13 @@ pub fn finish_bulk_endpoint_callback_out( pub fn finish_interrupt_endpoint_callback( endpoint: endpoint_descriptor, - hcint: u32, + hcint_: u32, channel: u8, ) -> bool { + let mut hcint = hcint_; let device = unsafe { &mut *endpoint.device }; let transfer_size = HcdUpdateTransferSize(device, channel); - device.last_transfer = endpoint.buffer_length - transfer_size; + let last_transfer = endpoint.buffer_length - transfer_size; let endpoint_device = device.driver_data.downcast::().unwrap(); //TODO: Hardcoded for usb-kbd for now @@ -143,14 +157,32 @@ pub fn finish_interrupt_endpoint_callback( let dma_addr = dwc_sc.dma_addr[channel as usize]; if hcint & HCINT_CHHLTD == 0 { - println!( - "| Endpoint {}: HCINT_CHHLTD not set, aborting. hcint: {:x}.", - channel, hcint - ); - shutdown(); + let mut i = 0; + let mut hcint_nochhltd = 0; + while i < 50 { + let hcint_nochhltd = dwc_otg::read_volatile(DOTG_HCINT(channel as usize)); + if hcint_nochhltd & HCINT_CHHLTD != 0 { + break; + } + i += 1; + micro_delay(10); + } + + if hcint_nochhltd & HCINT_CHHLTD == 0 { + // println!( + // "| Endpoint {}: HCINT_CHHLTD not set, aborting. hcint: {:x} hcint2: {:x}", + // channel, hcint, hcint_nochhltd + // ); + DwcDisableChannel(channel); + hcint_nochhltd = dwc_otg::read_volatile(DOTG_HCINT(channel as usize)); + // return true; + } + + + hcint |= hcint_nochhltd; } - let buffer_length = device.last_transfer.clamp(0, 8); + let buffer_length = last_transfer.clamp(0, 8); let mut buffer = Box::new_uninit_slice(buffer_length as usize); if hcint & HCINT_ACK != 0 { diff --git a/crates/kernel/src/networking/iface/arp.rs b/crates/kernel/src/networking/iface/arp.rs index dfeb6f5b..ef95566d 100644 --- a/crates/kernel/src/networking/iface/arp.rs +++ b/crates/kernel/src/networking/iface/arp.rs @@ -72,7 +72,7 @@ pub fn eth_addr_for_ip( match eth_addr { Some(eth_addr) => Ok(eth_addr), None => { - println!("address not found, sending ARP request for {}", ipv4_addr); + // println!("address not found, sending ARP request for {}", ipv4_addr); send_arp_packet( interface, ArpOperation::Request, diff --git a/crates/kernel/src/networking/iface/cdcecm.rs b/crates/kernel/src/networking/iface/cdcecm.rs index 0f2648bb..09965f55 100644 --- a/crates/kernel/src/networking/iface/cdcecm.rs +++ b/crates/kernel/src/networking/iface/cdcecm.rs @@ -18,6 +18,7 @@ impl Device for CDCECM { // TODO: fn send(&mut self, buffer: &[u8], buffer_len: u32) -> Result<()> { fn send(&mut self, buffer: &mut [u8], buffer_len: u32) { unsafe { + println!("| NET: Send packet of size {}", buffer_len); NetSendPacket(buffer.as_mut_ptr(), buffer_len); } } diff --git a/crates/kernel/src/networking/iface/ipv4.rs b/crates/kernel/src/networking/iface/ipv4.rs index b1f3893d..3be9e50d 100644 --- a/crates/kernel/src/networking/iface/ipv4.rs +++ b/crates/kernel/src/networking/iface/ipv4.rs @@ -28,7 +28,7 @@ pub fn send_ipv4_packet( ) } Err(e) => { - println!("failed to resolve ip, queuing another send, waiting for ARP"); + // println!("failed to resolve ip, queuing another send, waiting for ARP"); thread::thread(move || { let interface = get_interface_mut(); let _ = send_ipv4_packet(interface, payload, protocol, dst_addr); @@ -74,7 +74,7 @@ pub fn recv_ip_packet(interface: &mut Interface, eth_frame: EthernetFrame) -> Re // get next hop for a packet destined to a specified address. pub fn ipv4_addr_route(interface: &mut Interface, address: Ipv4Address) -> Ipv4Address { if interface.ipv4_addr.is_member(address) || interface.ipv4_addr.is_broadcast(address) { - println!("{} will be routed through link", address); + // println!("{} will be routed through link", address); address } else { println!("{} will be routed through default gateway", address); diff --git a/crates/kernel/src/networking/repr/ipv4.rs b/crates/kernel/src/networking/repr/ipv4.rs index 31d44ddb..b4e60ec4 100644 --- a/crates/kernel/src/networking/repr/ipv4.rs +++ b/crates/kernel/src/networking/repr/ipv4.rs @@ -165,7 +165,7 @@ impl AddressCidr { (address.as_u32() & mask) == (self.address.as_u32() & mask) } pub fn is_broadcast(&self, address: Address) -> bool { - println!("self broad {}", self.broadcast()); + // println!("self broad {}", self.broadcast()); address == self.broadcast() } pub fn broadcast(&self) -> Address { diff --git a/crates/kernel/src/runtime.rs b/crates/kernel/src/runtime.rs index 8395286a..9668879a 100644 --- a/crates/kernel/src/runtime.rs +++ b/crates/kernel/src/runtime.rs @@ -39,7 +39,7 @@ fn panic_handler(info: &core::panic::PanicInfo) -> ! { // crate::device::LED_OUT.get().put(0b00011000); // Shut down the system let mut watchdog = crate::device::WATCHDOG.get().lock(); - unsafe { watchdog.reset(0) }; + unsafe { watchdog.reset(63) }; } halt(); } From af2accfe6408cab64718edbab49dc7d41daa3d08 Mon Sep 17 00:00:00 2001 From: juice Date: Sun, 27 Apr 2025 20:00:45 -0500 Subject: [PATCH 02/13] Socket API changes and fixes --- crates/kernel/examples/net.rs | 117 +++--- crates/kernel/scripts/run-usb.sh | 6 +- crates/kernel/src/device/usb/device/net.rs | 17 +- crates/kernel/src/networking/iface/cdcecm.rs | 18 + crates/kernel/src/networking/iface/dhcp.rs | 59 +-- .../kernel/src/networking/iface/ethernet.rs | 2 +- crates/kernel/src/networking/iface/ipv4.rs | 9 +- crates/kernel/src/networking/iface/mod.rs | 9 +- crates/kernel/src/networking/iface/socket.rs | 47 +-- crates/kernel/src/networking/iface/tcp.rs | 30 +- crates/kernel/src/networking/iface/udp.rs | 22 +- crates/kernel/src/networking/repr/udp.rs | 2 +- .../kernel/src/networking/socket/bindings.rs | 56 +-- crates/kernel/src/networking/socket/mod.rs | 5 +- crates/kernel/src/networking/socket/raw.rs | 97 +++-- crates/kernel/src/networking/socket/tagged.rs | 66 ++-- crates/kernel/src/networking/socket/tcp.rs | 372 +++++++++++------- crates/kernel/src/networking/socket/udp.rs | 111 +++--- crates/kernel/src/ringbuffer.rs | 32 ++ 19 files changed, 646 insertions(+), 431 deletions(-) diff --git a/crates/kernel/examples/net.rs b/crates/kernel/examples/net.rs index 300b489c..29ecdb55 100644 --- a/crates/kernel/examples/net.rs +++ b/crates/kernel/examples/net.rs @@ -4,87 +4,106 @@ extern crate alloc; extern crate kernel; -use kernel::networking::repr::Ipv4Address; +use core::net::Ipv4Addr; + +use kernel::{device::usb::device::net::get_dhcpd_mut, event::{task, thread}, networking::{iface::icmp, repr::{IcmpPacket, Ipv4Address}, socket::RawSocket}, ringbuffer}; + #[allow(unused_imports)] use kernel::networking::socket::{ - bind, connect, recv_from, send_to, SocketAddr, TcpSocket, UdpSocket, + bind, accept, listen, connect, recv_from, send_to, SocketAddr, TcpSocket, UdpSocket, }; +use kernel::networking::Result; use kernel::*; #[no_mangle] extern "Rust" fn kernel_main(_device_tree: device_tree::DeviceTree) { - let count = 32; - // WARN: this is unfortunately necessary to give dhcp time to resolve our ip address because - // we don't have blocking currently - for _i in 0..count { - sync::spin_sleep(100_000); - } + println!("| starting kernel_main"); + task::spawn_async(async move { + main().await; + }); + crate::event::thread::stop(); +} + +async fn main() { + println!("starting dhcpd"); + + let dhcpd = get_dhcpd_mut(); + dhcpd.start().await; + + println!("out of dhcpd"); // [udp send test] + // println!("udp send test"); // let s = UdpSocket::new(); // let saddr = SocketAddr { // addr: Ipv4Address::new([11, 187, 10, 102]), // port: 1337, // }; // for _i in 0..5 { - // let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr); + // let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr).await; // } + // println!("end udp send test"); + // [udp listening test] - // To use this, send packets from your machine and uncomment this test - // + // println!("udp listening test"); // let s = UdpSocket::new(); // - // bind(s, 2222); + // bind(s, 53); // - // loop { - // sync::spin_sleep(500_000); - // let recv = recv_from(s); + // for i in 0..5 { + // println!("listening for packets"); + // let recv = recv_from(s).await; // if let Ok((payload, senderaddr)) = recv { // println!("got message: {:x?}", payload); // } // } + // + // println!("end udp listening test"); + // [tcp send test] - let saddr = SocketAddr { - addr: Ipv4Address::new([11, 187, 10, 102]), - port: 1337, - }; + // println!("tcp send test"); + // let saddr = SocketAddr { + // addr: Ipv4Address::new([11, 187, 10, 102]), + // port: 1337, + // }; + // + // let s = TcpSocket::new(); + // match connect(s, saddr).await { + // Ok(_) => (), + // Err(_) => println!("couldn't connect"), + // }; + // + // for _i in 0..5 { + // let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr); + // } + // println!("tcp send test end"); + + // [tcp recv test] let s = TcpSocket::new(); - match connect(s, saddr) { - Ok(_) => (), - Err(_) => println!("couldn't connect"), - }; - - // WARN: same as above, but for tcp handshake - for _i in 0..count { - sync::spin_sleep(100_000); + + bind(s, 22); + listen(s, 1).await; // has a timeout, we will wait for 5 seconds + + let clientfd = accept(s).await; + + + while let recv = recv_from(*clientfd.as_ref().unwrap()).await { + if let Ok((payload, senderaddr)) = recv { + println!("got message: {:x?}", payload); + } else { + break; + } } - for _i in 0..5 { - let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr); + // there is a delay when calling NetSend on a packet, this loop is to allow all the packets to + // drain out + for i in 0..32 { + sync::spin_sleep(500_000); } - // [tcp recv test] - // To use this, send packets from your machine and uncomment this test - // let s = TcpSocket::new(); - // - // bind(s, 2222); - // listen(s); // has a timeout, we will wait for 5 seconds - // - // let client = accept(s); - // // WARN: same as above, but for tcp handshake - // for _i in 0..count { - // sync::spin_sleep(100_000); - // } - // - // loop { - // sync::spin_sleep(500_000); - // let recv = recv_from(s); - // if let Ok((payload, senderaddr)) = recv { - // println!("got message: {:x?}", payload); - // } - // } + shutdown(); } diff --git a/crates/kernel/scripts/run-usb.sh b/crates/kernel/scripts/run-usb.sh index 80e66e19..a556328d 100755 --- a/crates/kernel/scripts/run-usb.sh +++ b/crates/kernel/scripts/run-usb.sh @@ -1,9 +1,11 @@ #!/usr/bin/env bash - set -ex -QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +# QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=udp::3333-:53 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev bridge,id=net0,br=br0 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-hub,id=hub1 -device usb-kbd -device usb-mouse" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse,pcap=usb-mouse.pcap -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +# QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +# QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" diff --git a/crates/kernel/src/device/usb/device/net.rs b/crates/kernel/src/device/usb/device/net.rs index fdff7701..7a6a9984 100644 --- a/crates/kernel/src/device/usb/device/net.rs +++ b/crates/kernel/src/device/usb/device/net.rs @@ -148,10 +148,6 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { NET_DEVICE.device = Some(device); } - // begin socket send loop, this iterates through all existing sockets, and attempts to send as - // many packets as possible from each socket - socket::socket_send_loop(); - // begin receieve series, this queues a receive to be ran which will eventually propogate back // to us through the rgistered `recv` function which then queues another receive let buf = vec![0u8; 1500]; @@ -163,8 +159,10 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { unsafe { DHCPD = Some(dhcp::Dhcpd::new()); } - let dhcpd = get_dhcpd_mut(); - let _ = dhcpd.start(interface); + + // begin socket send loop, this iterates through all existing sockets, and attempts to send as + // many packets as possible from each socket + // socket::socket_send_loop(); return ResultCode::OK; } @@ -190,12 +188,13 @@ pub unsafe fn NetAnalyze(buffer: *mut u8, buffer_length: u32) { } pub fn NetSend(_buffer: *mut u8, _buffer_length: u32) { - //Do nothing for now - //Called when USB packet is actually sent out + // Do nothing for now + // Called when USB packet is actually sent out + println!("NetSend called"); } pub unsafe fn NetReceive(buffer: *mut u8, buffer_length: u32) { - println!("| Net: Receive"); + // println!("| Net: Receive"); unsafe { if let Some(callback) = NET_DEVICE.receive_callback { diff --git a/crates/kernel/src/networking/iface/cdcecm.rs b/crates/kernel/src/networking/iface/cdcecm.rs index 09965f55..b8080913 100644 --- a/crates/kernel/src/networking/iface/cdcecm.rs +++ b/crates/kernel/src/networking/iface/cdcecm.rs @@ -12,6 +12,24 @@ impl CDCECM { max_transmission_unit: mtu, } } + + pub fn send(&mut self, buffer: &mut [u8], buffer_len: u32) { + unsafe { + println!("| NET: Send packet of size {}", buffer_len); + NetSendPacket(buffer.as_mut_ptr(), buffer_len); + } + } + + // TODO: fn recv(&mut self, buffer: &mut [u8], buffer_len: u32) -> Result { + pub fn recv(&mut self, buffer: &mut [u8], buffer_len: u32) { + unsafe { + NetReceive(buffer.as_mut_ptr(), buffer_len); + } + } + + pub fn mtu(&self) -> usize { + self.max_transmission_unit + } } impl Device for CDCECM { diff --git a/crates/kernel/src/networking/iface/dhcp.rs b/crates/kernel/src/networking/iface/dhcp.rs index 6452ef75..12e62051 100644 --- a/crates/kernel/src/networking/iface/dhcp.rs +++ b/crates/kernel/src/networking/iface/dhcp.rs @@ -1,10 +1,13 @@ use crate::device::system_timer; +use crate::ringbuffer::channel; +use crate::event::task::spawn_async; +use crate::device::usb::device::net::get_interface_mut; use crate::networking::iface::Interface; use crate::networking::repr::{ DhcpMessageType, DhcpOption, DhcpPacket, DhcpParam, Ipv4Address, Ipv4Cidr, }; -use crate::networking::socket::{bind, send_to, SocketAddr, UdpSocket}; +use crate::networking::socket::{bind, recv_from, send_to, SocketAddr, UdpSocket}; use crate::networking::{Error, Result}; use alloc::vec; @@ -71,7 +74,8 @@ impl Dhcpd { || self.state == DhcpState::Requesting } - pub fn start(&mut self, interface: &mut Interface) -> Result<()> { + pub async fn start(&mut self) -> Result<()> { + let interface = get_interface_mut(); if self.state != DhcpState::Idle && self.state != DhcpState::Released { return Ok(()); } @@ -85,10 +89,18 @@ impl Dhcpd { self.state = DhcpState::Discovering; self.last_action_time = time; - send_dhcp_discover(interface, self.udp_socket, self.xid) + send_dhcp_discover(interface, self.udp_socket, self.xid).await; + + while self.state != DhcpState::Bound { + let r = recv_from(self.udp_socket).await; + let (payload, _) = r.unwrap(); + self.process_dhcp_packet(interface, payload).await; + } + + Ok(()) } - pub fn release(&mut self, interface: &mut Interface) -> Result<()> { + pub async fn release(&mut self, interface: &mut Interface) -> Result<()> { if self.state != DhcpState::Bound && self.state != DhcpState::Renewing && self.state != DhcpState::Rebinding @@ -98,7 +110,7 @@ impl Dhcpd { if let (Some(server_id), Some(offered_ip)) = (self.server_identifier, self.offered_ip) { let result = - send_dhcp_release(interface, self.xid, offered_ip, server_id, self.udp_socket); + send_dhcp_release(interface, self.xid, offered_ip, server_id, self.udp_socket).await; self.state = DhcpState::Released; result } else { @@ -106,11 +118,12 @@ impl Dhcpd { } } - pub fn process_dhcp_packet( + pub async fn process_dhcp_packet( &mut self, interface: &mut Interface, - packet: DhcpPacket, + bytes: Vec, ) -> Result<()> { + let packet = DhcpPacket::deserialize(bytes.as_slice())?; let msg_type = packet.get_message_type().ok_or(Error::Malformed)?; match (self.state, msg_type) { @@ -132,7 +145,7 @@ impl Dhcpd { self.last_action_time = system_timer::get_time(); self.retries = DEFAULT_LEASE_RETRY; - send_dhcp_request(interface, self.xid, offered_ip, server_id, self.udp_socket)?; + send_dhcp_request(interface, self.xid, offered_ip, server_id, self.udp_socket).await?; // send_dhcp_packet_workaround(interface, self.xid, offered_ip, server_id, packet)?; } else { return Err(Error::Malformed); @@ -203,7 +216,7 @@ impl Dhcpd { self.retries = DEFAULT_LEASE_RETRY; self.xid = system_timer::get_time() as u32 ^ 0xEFEF1212; - send_dhcp_discover(interface, self.udp_socket, self.xid)?; + send_dhcp_discover(interface, self.udp_socket, self.xid).await?; } _ => { // Ignore unexpected messages @@ -219,7 +232,7 @@ impl Dhcpd { } } -pub fn send_dhcp_discover(interface: &mut Interface, socketfd: u16, xid: u32) -> Result<()> { +pub async fn send_dhcp_discover(interface: &mut Interface, socketfd: u16, xid: u32) -> Result<()> { println!("DHCP: Sending DISCOVER"); let packet = DhcpPacket { @@ -250,10 +263,10 @@ pub fn send_dhcp_discover(interface: &mut Interface, socketfd: u16, xid: u32) -> ], }; - send_dhcp_packet(interface, socketfd, &packet) + send_dhcp_packet(interface, socketfd, &packet).await } -pub fn send_dhcp_request( +pub async fn send_dhcp_request( interface: &mut Interface, xid: u32, requested_ip: Ipv4Address, @@ -292,10 +305,10 @@ pub fn send_dhcp_request( ], }; - send_dhcp_packet(interface, socketfd, &packet) + send_dhcp_packet(interface, socketfd, &packet).await } -pub fn send_dhcp_renew( +pub async fn send_dhcp_renew( interface: &mut Interface, xid: u32, current_ip: Ipv4Address, @@ -325,10 +338,10 @@ pub fn send_dhcp_renew( }; // Send directly to the server rather than broadcast - send_dhcp_packet_unicast(interface, socketfd, &packet, server_id) + send_dhcp_packet_unicast(interface, socketfd, &packet, server_id).await } -pub fn send_dhcp_rebind( +pub async fn send_dhcp_rebind( interface: &mut Interface, xid: u32, current_ip: Ipv4Address, @@ -355,10 +368,10 @@ pub fn send_dhcp_rebind( ], }; - send_dhcp_packet(interface, socketfd, &packet) + send_dhcp_packet(interface, socketfd, &packet).await } -pub fn send_dhcp_release( +pub async fn send_dhcp_release( interface: &mut Interface, xid: u32, current_ip: Ipv4Address, @@ -388,20 +401,20 @@ pub fn send_dhcp_release( }; // Send directly to the server rather than broadcast - send_dhcp_packet_unicast(interface, socketfd, &packet, server_id) + send_dhcp_packet_unicast(interface, socketfd, &packet, server_id).await } -fn send_dhcp_packet(interface: &mut Interface, socketfd: u16, packet: &DhcpPacket) -> Result<()> { +async fn send_dhcp_packet(interface: &mut Interface, socketfd: u16, packet: &DhcpPacket) -> Result<()> { let data = packet.serialize(); let saddr = SocketAddr { addr: interface.ipv4_addr.broadcast(), port: DHCP_SERVER_PORT, }; - send_to(socketfd, data, saddr) + send_to(socketfd, data, saddr).await } -fn send_dhcp_packet_unicast( +async fn send_dhcp_packet_unicast( _interface: &mut Interface, socketfd: u16, packet: &DhcpPacket, @@ -413,5 +426,5 @@ fn send_dhcp_packet_unicast( port: DHCP_SERVER_PORT, }; - send_to(socketfd, data, saddr) + send_to(socketfd, data, saddr).await } diff --git a/crates/kernel/src/networking/iface/ethernet.rs b/crates/kernel/src/networking/iface/ethernet.rs index 91bf5f18..6a85c295 100644 --- a/crates/kernel/src/networking/iface/ethernet.rs +++ b/crates/kernel/src/networking/iface/ethernet.rs @@ -34,7 +34,7 @@ pub fn send_ethernet_frame( // recv ethernet frame from interface: parsed -> fwd to socket -> propogated up stack pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u32) -> Result<()> { println!("[!] received ethernet frame"); - println!("\t{:x?}", eth_buffer); + // println!("\t{:x?}", ð_buffer[44..]); // we will truncate the first 44 bytes from the RNDIS protocol let eth_frame = EthernetFrame::deserialize(ð_buffer[44..])?; diff --git a/crates/kernel/src/networking/iface/ipv4.rs b/crates/kernel/src/networking/iface/ipv4.rs index 3be9e50d..88e277fa 100644 --- a/crates/kernel/src/networking/iface/ipv4.rs +++ b/crates/kernel/src/networking/iface/ipv4.rs @@ -4,6 +4,7 @@ use crate::networking::{Error, Result}; use crate::device::usb::device::net::{get_dhcpd_mut, get_interface_mut}; use crate::event::thread; +use crate::sync; use alloc::vec::Vec; @@ -28,8 +29,9 @@ pub fn send_ipv4_packet( ) } Err(e) => { - // println!("failed to resolve ip, queuing another send, waiting for ARP"); + println!("failed to resolve ip, queuing another send, waiting for ARP"); thread::thread(move || { + sync::spin_sleep(100_000); let interface = get_interface_mut(); let _ = send_ipv4_packet(interface, payload, protocol, dst_addr); }); @@ -46,17 +48,16 @@ pub fn recv_ip_packet(interface: &mut Interface, eth_frame: EthernetFrame) -> Re } let dhcpd = get_dhcpd_mut(); - if dhcpd.is_transacting() { - return Err(Error::Ignored); - } if ipv4_packet.dst_addr != *interface.ipv4_addr && !interface.ipv4_addr.is_member(ipv4_packet.dst_addr) && !interface.ipv4_addr.is_broadcast(ipv4_packet.dst_addr) + && !dhcpd.is_transacting() { return Err(Error::Ignored); } + // update arp cache for immediate ICMP echo replies, errors, etc. if eth_frame.src.is_unicast() { let mut arp_cache = interface.arp_cache.lock(); diff --git a/crates/kernel/src/networking/iface/mod.rs b/crates/kernel/src/networking/iface/mod.rs index 6b42123d..a9f5011a 100644 --- a/crates/kernel/src/networking/iface/mod.rs +++ b/crates/kernel/src/networking/iface/mod.rs @@ -14,6 +14,7 @@ use crate::networking::socket::TaggedSocket; use crate::networking::utils::arp_cache::ArpCache; use alloc::boxed::Box; +use alloc::sync::Arc; use alloc::collections::btree_map::BTreeMap; pub mod arp; @@ -31,7 +32,7 @@ use cdcecm::CDCECM; // WARN: for now, we assume that we will only ever set our ethernet_addr, ipv4_addr, and // default_gateway once when we first initialize pub struct Interface { - pub dev: Box, + pub dev: CDCECM, pub arp_cache: SpinLock, pub ethernet_addr: EthernetAddress, @@ -39,19 +40,19 @@ pub struct Interface { pub ipv4_addr: Ipv4Cidr, pub default_gateway: Ipv4Address, - pub sockets: SpinLock>, + pub sockets: BTreeMap, } impl Interface { pub fn new() -> Self { Interface { - dev: Box::new(CDCECM::new(1500)), + dev: CDCECM::new(1500), arp_cache: SpinLock::new(ArpCache::new(60, system_timer::get_time())), ethernet_addr: EthernetAddress::empty(), ipv4_addr: Ipv4Cidr::empty(), default_gateway: Ipv4Address::empty(), - sockets: SpinLock::new(BTreeMap::new()), + sockets: BTreeMap::new(), } } } diff --git a/crates/kernel/src/networking/iface/socket.rs b/crates/kernel/src/networking/iface/socket.rs index e93e37ba..a6e6e7d9 100644 --- a/crates/kernel/src/networking/iface/socket.rs +++ b/crates/kernel/src/networking/iface/socket.rs @@ -6,25 +6,28 @@ use crate::networking::socket::TaggedSocket; use alloc::vec::Vec; -pub fn socket_send_loop() { - let interface = get_interface_mut(); - - let to_send: Vec<_> = { - let mut sockets = interface.sockets.lock(); - sockets - .iter_mut() - .map(|(_, socket)| socket as *mut TaggedSocket) - .collect() - }; - - for &socket_ptr in &to_send { - let socket: &mut TaggedSocket = unsafe { &mut *socket_ptr }; - let _ = socket.send(interface); - } - - // WARN: this is not good - thread::thread(move || { - sync::spin_sleep(500_000); - socket_send_loop(); - }); -} +// pub fn socket_send_loop() { +// println!("socket_send_loop"); +// let interface = get_interface_mut(); +// println!("try send"); +// +// let to_send: Vec<_> = { +// let mut sockets = interface.sockets.lock(); +// sockets +// .iter_mut() +// .map(|(_, socket)| socket as *mut TaggedSocket) +// .collect() +// }; +// println!("try send2"); +// +// +// for &socket_ptr in &to_send { +// let socket: &mut TaggedSocket = unsafe { &mut *socket_ptr }; +// let _ = socket.send(interface); +// } +// +// thread::thread(move || { +// sync::spin_sleep(500_000); +// socket_send_loop(); +// }); +// } diff --git a/crates/kernel/src/networking/iface/tcp.rs b/crates/kernel/src/networking/iface/tcp.rs index 6450d6a2..95104e81 100644 --- a/crates/kernel/src/networking/iface/tcp.rs +++ b/crates/kernel/src/networking/iface/tcp.rs @@ -1,9 +1,11 @@ use crate::networking::iface::*; use crate::networking::repr::*; use crate::networking::socket::SocketAddr; -use crate::networking::Result; +use crate::networking::socket::SockType; +use crate::networking::{Error, Result}; use alloc::vec::Vec; +use crate::event::task; pub fn send_tcp_packet( interface: &mut Interface, @@ -55,16 +57,24 @@ pub fn recv_tcp_packet(interface: &mut Interface, ipv4_packet: Ipv4Packet) -> Re port: tcp_packet.src_port, }; - let mut sockets = interface.sockets.lock(); - for (_, socket) in sockets.iter_mut() { + // let mut sockets = interface.sockets.lock(); + for (_, socket) in interface.sockets.iter_mut() { if socket.binding_equals(local_socket_addr) { - let _ = socket.recv_enqueue( - tcp_packet.seq_number, - tcp_packet.ack_number, - tcp_packet.flags, - tcp_packet.payload.clone(), - sender_socket_addr, - ); + let (stype, mut tx) = socket.get_send_ref(); + + if stype != SockType::TCP { + return Err(Error::Unsupported); + } + + let mut payload = tcp_packet.payload.clone(); + payload.extend_from_slice(&tcp_packet.seq_number.to_le_bytes()); + payload.extend_from_slice(&tcp_packet.ack_number.to_le_bytes()); + payload.push(tcp_packet.flags); + payload.extend_from_slice(&tcp_packet.window_size.to_le_bytes()); + + task::spawn_async(async move { + let _ = tx.send((payload, sender_socket_addr)).await; + }); } } diff --git a/crates/kernel/src/networking/iface/udp.rs b/crates/kernel/src/networking/iface/udp.rs index 60c9de5d..5120c8ec 100644 --- a/crates/kernel/src/networking/iface/udp.rs +++ b/crates/kernel/src/networking/iface/udp.rs @@ -1,7 +1,10 @@ use crate::networking::iface::*; use crate::networking::repr::*; +use crate::networking::socket::SockType; use crate::networking::socket::SocketAddr; -use crate::networking::Result; +use crate::networking::{Result, Error}; + +use crate::event::task; use alloc::vec::Vec; @@ -41,10 +44,21 @@ pub fn recv_udp_packet(interface: &mut Interface, ipv4_packet: Ipv4Packet) -> Re port: udp_packet.src_port, }; - let mut sockets = interface.sockets.lock(); - for (_, socket) in sockets.iter_mut() { + // let mut sockets = interface.sockets.lock(); + + for (_, socket) in interface.sockets.iter_mut() { if socket.binding_equals(local_socket_addr) { - let _ = socket.recv_enqueue(0, 0, 0, udp_packet.payload.clone(), sender_socket_addr); + let (stype, mut tx) = socket.get_send_ref(); + + if stype != SockType::UDP { + return Err(Error::Unsupported); + } + + let payload = udp_packet.payload.clone(); + + task::spawn_async(async move { + let _ = tx.send((payload, sender_socket_addr)).await; + }); } } diff --git a/crates/kernel/src/networking/repr/udp.rs b/crates/kernel/src/networking/repr/udp.rs index 96aa8e81..4c1ae1cf 100644 --- a/crates/kernel/src/networking/repr/udp.rs +++ b/crates/kernel/src/networking/repr/udp.rs @@ -49,7 +49,7 @@ impl Packet { let length = NetworkEndian::read_u16(&buf[4..6]); let checksum = NetworkEndian::read_u16(&buf[6..8]); - println!("length {} buf length {}", length, buf.len()); + // println!("length {} buf length {}", length, buf.len()); if length < 8 || buf.len() != length as usize { return Err(Error::Malformed); } diff --git a/crates/kernel/src/networking/socket/bindings.rs b/crates/kernel/src/networking/socket/bindings.rs index fb591308..2e5f1d58 100644 --- a/crates/kernel/src/networking/socket/bindings.rs +++ b/crates/kernel/src/networking/socket/bindings.rs @@ -8,6 +8,7 @@ use crate::networking::repr::Ipv4Address; use crate::networking::{Error, Result}; use crate::device::usb::device::net::get_interface_mut; +use crate::event::task::spawn_async; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SocketAddr { @@ -30,16 +31,23 @@ impl Display for SocketAddr { } } +#[derive(Debug, Eq, PartialEq)] +pub enum SockType { + UDP, + TCP, + Raw +} + // TODO: these technically runs out eventually lol need wrap around pub static NEXT_EPHEMERAL: AtomicU16 = AtomicU16::new(32768); pub static NEXT_SOCKETFD: AtomicU16 = AtomicU16::new(1); -pub fn send_to(socketfd: u16, payload: Vec, saddr: SocketAddr) -> Result<()> { +pub async fn send_to(socketfd: u16, payload: Vec, saddr: SocketAddr) -> Result<()> { let interface = get_interface_mut(); - let mut sockets = interface.sockets.lock(); + // let mut sockets = interface.sockets.lock(); // 1. check if socket fd is valid if not return error - let tagged_socket = sockets + let tagged_socket = interface.sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; @@ -51,16 +59,14 @@ pub fn send_to(socketfd: u16, payload: Vec, saddr: SocketAddr) -> Result<()> } // 3. queue a send on socket sending queue - tagged_socket.send_enqueue(payload, saddr) + tagged_socket.send_enqueue(payload, saddr).await } -// TODO: this needs to be blocking -pub fn recv_from(socketfd: u16) -> Result<(Vec, SocketAddr)> { +pub async fn recv_from(socketfd: u16) -> Result<(Vec, SocketAddr)> { let interface = get_interface_mut(); - let mut sockets = interface.sockets.lock(); // 1. check if a socketfd is valid if not return error - let tagged_socket = sockets + let tagged_socket = interface.sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; @@ -70,27 +76,28 @@ pub fn recv_from(socketfd: u16) -> Result<(Vec, SocketAddr)> { } // 3. blocking recv from socket recv queue - tagged_socket.recv() // this needs to be blocking + + tagged_socket.recv().await } -pub fn connect(socketfd: u16, saddr: SocketAddr) -> Result<()> { +pub async fn connect(socketfd: u16, saddr: SocketAddr) -> Result<()> { let interface = get_interface_mut(); - let mut sockets = interface.sockets.lock(); + // let mut sockets = interface.sockets.lock(); // 1. check if a socketfd is valid if not return error - let tagged_socket = sockets + let tagged_socket = interface.sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; - tagged_socket.connect(saddr) + tagged_socket.connect(saddr).await } -pub fn listen(socketfd: u16, num_requests: usize) -> Result<()> { +pub async fn listen(socketfd: u16, num_requests: usize) -> Result<()> { let interface = get_interface_mut(); // 1.check if binded, if not error - let mut sockets = interface.sockets.lock(); + // let mut sockets = interface.sockets.lock(); - let tagged_socket = sockets + let tagged_socket = interface.sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; @@ -99,20 +106,21 @@ pub fn listen(socketfd: u16, num_requests: usize) -> Result<()> { } // 2. start the listener - tagged_socket.listen(num_requests) + tagged_socket.listen(num_requests).await } -pub fn accept(socketfd: u16) -> Result { +pub async fn accept(socketfd: u16) -> Result { let interface = get_interface_mut(); // 1. if listener not started, error - let mut sockets = interface.sockets.lock(); + // let mut sockets = interface.sockets.lock(); - let tagged_socket = sockets + let tagged_socket = interface.sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; // 2. accept 1 connection, error if no pending connections - tagged_socket.accept() + tagged_socket.accept().await; + Ok(socketfd) } pub fn bind(socketfd: u16, port: u16) -> Result<()> { @@ -122,15 +130,15 @@ pub fn bind(socketfd: u16, port: u16) -> Result<()> { addr: *interface.ipv4_addr, port, }; - let mut sockets = interface.sockets.lock(); - for (_, socket) in sockets.iter_mut() { + // let mut sockets = interface.sockets.lock(); + for (_, socket) in interface.sockets.iter_mut() { if socket.binding_equals(bind_addr) { return Err(Error::BindingInUse(bind_addr)); } } // 2. check if this is a valid socketfd - let tagged_socket = sockets + let tagged_socket = interface.sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; diff --git a/crates/kernel/src/networking/socket/mod.rs b/crates/kernel/src/networking/socket/mod.rs index aba279a5..e990e159 100644 --- a/crates/kernel/src/networking/socket/mod.rs +++ b/crates/kernel/src/networking/socket/mod.rs @@ -3,12 +3,11 @@ pub mod raw; pub mod tagged; pub mod tcp; pub mod udp; -// pub mod unix; -pub use self::bindings::{bind, connect, recv_from, send_to, SocketAddr}; +pub use self::bindings::{bind, accept, listen, connect, recv_from, send_to, SocketAddr, SockType}; pub use self::tagged::TaggedSocket; -pub use self::raw::{RawSocket, RawType}; +pub use self::raw::RawSocket; pub use self::tcp::TcpSocket; pub use self::udp::UdpSocket; diff --git a/crates/kernel/src/networking/socket/raw.rs b/crates/kernel/src/networking/socket/raw.rs index a93fc386..4cda7182 100644 --- a/crates/kernel/src/networking/socket/raw.rs +++ b/crates/kernel/src/networking/socket/raw.rs @@ -1,5 +1,14 @@ +use crate::networking::repr::Ipv4Protocol; use crate::networking::utils::{ring::Ring, slice::Slice}; -use crate::networking::Result; +use crate::networking::iface::ipv4; +use crate::networking::iface::Interface; +use crate::device::usb::device::net::get_interface_mut; +use crate::networking::{Result, Error}; +use crate::ringbuffer::{channel, Sender, Receiver}; +use crate::networking::socket::tagged::{TaggedSocket, BUFFER_LEN}; +use crate::networking::socket::{SocketAddr, SockType}; + +use alloc::vec::Vec; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RawType { @@ -8,60 +17,80 @@ pub enum RawType { } // Socket for sending and receiving raw ethernet or IP packets. -#[derive(Debug)] pub struct RawSocket { raw_type: RawType, - send_buffer: Ring>, - recv_buffer: Ring>, + recv_tx: Sender, SocketAddr)>, + recv_rx: Receiver, SocketAddr)>, + is_bound: bool, + binding: SocketAddr, } impl RawSocket { pub fn new( raw_type: RawType, - send_buffer: Ring>, - recv_buffer: Ring>, ) -> RawSocket { + let (recv_tx, recv_rx) = channel::, SocketAddr)>(); + let interface = get_interface_mut(); RawSocket { raw_type, - send_buffer, - recv_buffer, + recv_tx, + recv_rx, + is_bound: false, + binding: SocketAddr { + addr: *interface.ipv4_addr, + port: 0, + }, } } - pub fn send(&mut self, buffer_len: usize) -> Result<&mut [u8]> { - self.send_buffer.enqueue_maybe(|buffer| { - buffer.try_resize(buffer_len, 0)?; + pub fn binding_equals(&self, saddr: SocketAddr) -> bool { + self.binding.port == saddr.port + } + + pub fn is_bound(&self) -> bool { + self.is_bound + } + + pub fn bind(&mut self, interface: &mut Interface, port: u16) { + self.is_bound = true; + let bind_addr = SocketAddr { + addr: *interface.ipv4_addr, + port, + }; + self.binding = bind_addr; + } - for i in 0..buffer_len { - buffer[i] = 0; - } + pub async fn send_enqueue(&mut self, payload: Vec, proto: Ipv4Protocol, dest: SocketAddr) -> Result<()> { + println!("enqueud send"); + let interface = get_interface_mut(); - return Ok(&mut buffer[..buffer_len]); - }) + ipv4::send_ipv4_packet(interface, payload, proto, dest.addr) } - // Dequeues a received packet from the socket. - pub fn recv(&mut self) -> Result<&[u8]> { - self.recv_buffer.dequeue_with(|buffer| &buffer[..]) + pub fn get_recv_ref(&mut self) -> (SockType, Receiver, SocketAddr)>) { + (SockType::Raw, self.recv_rx.clone()) } - // Dequeues a packet enqueued for sending via a function f. - // - // The packet is only dequeued if f does not return an error. - pub fn send_dequeue(&mut self, f: F) -> Result - where - F: FnOnce(&[u8]) -> Result, - { - self.send_buffer.dequeue_maybe(|buffer| f(&buffer[..])) + pub fn get_send_ref(&mut self) -> (SockType, Sender, SocketAddr)>) { + (SockType::Raw, self.recv_tx.clone()) + } + + pub async fn recv(&mut self) -> Result<(Vec, SocketAddr)> { + let (payload, addr) = self.recv_rx.recv().await; + Ok((payload, addr)) + } + + pub fn try_recv(&mut self) -> Result<(Vec, SocketAddr)> { + match self.recv_rx.try_recv() { + Some((payload, addr)) => Ok((payload, addr)), + None => Err(Error::Exhausted), + } } - // Enqueues a packet for receiving. - pub fn recv_enqueue(&mut self, packet: &[u8]) -> Result<()> { - self.recv_buffer.enqueue_maybe(|buffer| { - buffer.try_resize(packet.len(), 0)?; - buffer.copy_from_slice(packet); - Ok(()) - }) + pub async fn recv_enqueue(&mut self, payload: Vec, sender: SocketAddr) -> Result<()> { + println!("got a recv_enqueue"); + self.recv_tx.send((payload, sender)).await; + Ok(()) } pub fn raw_type(&self) -> RawType { diff --git a/crates/kernel/src/networking/socket/tagged.rs b/crates/kernel/src/networking/socket/tagged.rs index 228f023d..d5b91254 100644 --- a/crates/kernel/src/networking/socket/tagged.rs +++ b/crates/kernel/src/networking/socket/tagged.rs @@ -1,11 +1,14 @@ use crate::networking::iface::Interface; -use crate::networking::socket::{SocketAddr, TcpSocket, UdpSocket}; +use crate::networking::socket::{SocketAddr, TcpSocket, UdpSocket, SockType}; use crate::networking::{Error, Result}; use crate::device::usb::device::net::get_interface_mut; +use crate::ringbuffer::{Receiver, Sender}; use alloc::vec::Vec; +pub static BUFFER_LEN: usize = 128; + pub enum TaggedSocket { // Raw(RawSocket), Udp(UdpSocket), @@ -13,7 +16,7 @@ pub enum TaggedSocket { } impl TaggedSocket { - pub fn is_bound(&mut self) -> bool { + pub fn is_bound(&self) -> bool { match self { // TaggedSocket::Raw(socket) => socket.accepts(pair), TaggedSocket::Udp(socket) => socket.is_bound(), @@ -30,47 +33,53 @@ impl TaggedSocket { } } - pub fn send(&mut self, interface: &mut Interface) -> Result<()> { - match self { - // TaggedSocket::Raw(socket) => socket.send(), - TaggedSocket::Udp(socket) => socket.send(interface), - TaggedSocket::Tcp(socket) => socket.send(interface), - } - } - - pub fn send_enqueue(&mut self, payload: Vec, saddr: SocketAddr) -> Result<()> { + pub async fn send_enqueue(&mut self, payload: Vec, saddr: SocketAddr) -> Result<()> { match self { // TaggedSocket::Raw(socket) => socket.queue_send(payload, saddr), - TaggedSocket::Udp(socket) => socket.send_enqueue(payload, saddr), + TaggedSocket::Udp(socket) => socket.send_enqueue(payload, saddr).await, TaggedSocket::Tcp(socket) => socket.send_enqueue(payload, saddr), } } - // TODO: this is so ugl lol - pub fn recv_enqueue( + pub async fn recv_enqueue( &mut self, seq_num: u32, ack_num: u32, flags: u8, + window_size: u16, payload: Vec, saddr: SocketAddr, ) -> Result<()> { - let interface = get_interface_mut(); - match self { // TaggedSocket::Raw(socket) => socket.queue_recv(payload, saddr), - TaggedSocket::Udp(socket) => socket.recv_enqueue(payload, saddr), + TaggedSocket::Udp(socket) => socket.recv_enqueue(payload, saddr).await, TaggedSocket::Tcp(socket) => { - socket.recv_enqueue(interface, seq_num, ack_num, flags, payload, saddr) + socket.recv_enqueue(seq_num, ack_num, flags, window_size, payload, saddr).await } } } - pub fn recv(&mut self) -> Result<(Vec, SocketAddr)> { + pub fn get_recv_ref(&mut self) -> (SockType, Receiver, SocketAddr)>) { + match self { + // TaggedSocket::Raw(socket) => socket.accepts(pair), + TaggedSocket::Udp(socket) => socket.get_recv_ref(), + TaggedSocket::Tcp(socket) => socket.get_recv_ref(), + } + } + + pub fn get_send_ref(&mut self) -> (SockType, Sender, SocketAddr)>) { + match self { + // TaggedSocket::Raw(socket) => socket.accepts(pair), + TaggedSocket::Udp(socket) => socket.get_send_ref(), + TaggedSocket::Tcp(socket) => socket.get_send_ref(), + } + } + + pub async fn recv(&mut self) -> Result<(Vec, SocketAddr)> { match self { // TaggedSocket::Raw(socket) => socket.recv(), - TaggedSocket::Udp(socket) => socket.recv(), - TaggedSocket::Tcp(socket) => socket.recv(), + TaggedSocket::Udp(socket) => socket.recv().await, + TaggedSocket::Tcp(socket) => socket.recv().await, } } @@ -82,32 +91,29 @@ impl TaggedSocket { } } - // TODO: should block - // TODO: udp just throws error for now, but can be used like berkley posix to instead set the - // default destination as well in the future - pub fn connect(&mut self, saddr: SocketAddr) -> Result<()> { + pub async fn connect(&mut self, saddr: SocketAddr) -> Result<()> { let interface = get_interface_mut(); match self { // TaggedSocket::Raw(socket) => socket.recv(), TaggedSocket::Udp(_socket) => Err(Error::Ignored), - TaggedSocket::Tcp(socket) => socket.connect(interface, saddr), + TaggedSocket::Tcp(socket) => socket.connect(interface, saddr).await, } } - pub fn listen(&mut self, num_req: usize) -> Result<()> { + pub async fn listen(&mut self, num_req: usize) -> Result<()> { let interface = get_interface_mut(); match self { // TaggedSocket::Raw(socket) => socket.recv(), TaggedSocket::Udp(_socket) => Err(Error::Ignored), - TaggedSocket::Tcp(socket) => socket.listen(interface, num_req), + TaggedSocket::Tcp(socket) => socket.listen(interface, num_req).await, } } - pub fn accept(&mut self) -> Result { + pub async fn accept(&mut self) -> Result { match self { // TaggedSocket::Raw(socket) => socket.recv(), TaggedSocket::Udp(_socket) => Err(Error::Ignored), - TaggedSocket::Tcp(socket) => socket.accept(), + TaggedSocket::Tcp(socket) => socket.accept().await, } } } diff --git a/crates/kernel/src/networking/socket/tcp.rs b/crates/kernel/src/networking/socket/tcp.rs index 760abe4a..3f6e83c7 100644 --- a/crates/kernel/src/networking/socket/tcp.rs +++ b/crates/kernel/src/networking/socket/tcp.rs @@ -1,13 +1,15 @@ use crate::device::usb::device::net::get_interface_mut; use crate::networking::iface::{tcp, Interface}; +use crate::networking::repr::TcpPacket; use crate::networking::socket::bindings::{NEXT_EPHEMERAL, NEXT_SOCKETFD}; -use crate::networking::socket::tagged::TaggedSocket; -use crate::networking::socket::SocketAddr; +use crate::networking::socket::tagged::{TaggedSocket, BUFFER_LEN}; +use crate::networking::socket::{SocketAddr, SockType}; use crate::networking::utils::ring::Ring; use crate::networking::{Error, Result}; use alloc::vec; use alloc::vec::Vec; use core::sync::atomic::Ordering; +use crate::ringbuffer::{channel, Sender, Receiver}; fn new_ring_packet_buffer(capacity: usize) -> Ring<(Vec, SocketAddr)> { let default_entry = (Vec::new(), SocketAddr::default()); @@ -15,8 +17,6 @@ fn new_ring_packet_buffer(capacity: usize) -> Ring<(Vec, SocketAddr)> { Ring::from(buffer) } -pub static TCP_BUFFER_LEN: usize = 128; - // flags pub const TCP_FLAG_FIN: u8 = 0x01; pub const TCP_FLAG_SYN: u8 = 0x02; @@ -48,19 +48,26 @@ pub struct TcpSocket { pending_conn: Vec, max_pending: usize, connected: bool, - send_buffer: Ring<(Vec, SocketAddr)>, - recv_buffer: Ring<(Vec, SocketAddr)>, + // send_buffer: Ring<(Vec, SocketAddr)>, + // recv_buffer: Ring<(Vec, SocketAddr)>, + recv_tx: Sender, SocketAddr)>, + recv_rx: Receiver, SocketAddr)>, + // recvp_tx: Sender, + // recvp_rx: Receiver, state: TcpState, remote_addr: Option, seq_number: u32, ack_number: u32, + flags: u8, window_size: u16, } impl TcpSocket { pub fn new() -> u16 { let interface = get_interface_mut(); + let (recv_tx, recv_rx) = channel::, SocketAddr)>(); + // let (recvp_tx, recvp_rx) = channel::(); let socket = TcpSocket { binding: SocketAddr { addr: *interface.ipv4_addr, @@ -71,23 +78,28 @@ impl TcpSocket { pending_conn: Vec::new(), max_pending: 0, connected: false, - send_buffer: new_ring_packet_buffer(TCP_BUFFER_LEN), - recv_buffer: new_ring_packet_buffer(TCP_BUFFER_LEN), + recv_tx, + recv_rx, + // recvp_tx, + // recvp_rx, + state: TcpState::Closed, remote_addr: None, seq_number: INITIAL_SEQ_NUMBER, - ack_number: 0, + ack_number: 1, + flags: 0, window_size: DEFAULT_WINDOW_SIZE, }; let socketfd = NEXT_SOCKETFD.fetch_add(1, Ordering::SeqCst); - let mut sockets = interface.sockets.lock(); - sockets.insert(socketfd, TaggedSocket::Tcp(socket)); + // let mut sockets = interface.sockets.lock(); + interface.sockets.insert(socketfd, TaggedSocket::Tcp(socket)); socketfd } pub fn binding_equals(&self, saddr: SocketAddr) -> bool { + println!("binding port {} provided port {}", self.binding.port, saddr.port); self.binding == saddr } @@ -95,6 +107,14 @@ impl TcpSocket { self.is_bound } + pub fn get_recv_ref(&mut self) -> (SockType, Receiver, SocketAddr)>) { + (SockType::TCP, self.recv_rx.clone()) + } + + pub fn get_send_ref(&mut self) -> (SockType, Sender, SocketAddr)>) { + (SockType::TCP, self.recv_tx.clone()) + } + pub fn bind(&mut self, interface: &mut Interface, port: u16) { self.is_bound = true; let bind_addr = SocketAddr { @@ -104,7 +124,8 @@ impl TcpSocket { self.binding = bind_addr; } - pub fn listen(&mut self, interface: &mut Interface, num_max_requests: usize) -> Result<()> { + pub async fn listen(&mut self, interface: &mut Interface, num_max_requests: usize) -> Result<()> { + println!("in listen"); if !self.is_bound { // bind to ephemeral if not bound let ephemeral_port = NEXT_EPHEMERAL.fetch_add(1, Ordering::SeqCst); @@ -115,29 +136,71 @@ impl TcpSocket { self.max_pending = num_max_requests; self.state = TcpState::Closed; // still in CLOSED until SYN received self.pending_conn = Vec::with_capacity(num_max_requests); + + println!("waiting for incoming connection"); + let response = self.recv_with_context().await; + println!("got incoming tcp connection"); + + let (payload, sender) = match response { + Ok((payload, sender)) => (payload, sender), + Err(e) => return Err(e), + }; + + let last = &payload[payload.len() - 2..payload.len()]; + self.window_size = u16::from_le_bytes([last[0], last[1]]); + self.flags = payload[payload.len() - 3]; + // let last = &payload[payload.len() - 7..payload.len() - 3]; + // self.ack_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); + let last = &payload[payload.len() - 11..payload.len() - 7]; + self.ack_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); + + self.pending_conn.push(sender); + Ok(()) } - pub fn accept(&mut self) -> Result { + pub async fn accept(&mut self) -> Result { + println!("in accept"); if !self.is_listener { return Err(Error::NotConnected); } - match self.pending_conn.pop() { - Some(addr) => { - self.remote_addr = Some(addr); - Ok(addr) - } - None => Err(Error::Exhausted), - } + println!("here"); + let addr = match self.pending_conn.pop() { + Some(addr) => addr, + None => return Err(Error::Exhausted), + }; + + let interface = get_interface_mut(); + + self.ack_number += 1; + println!("ack number {}", self.ack_number); + + tcp::send_tcp_packet( + interface, + self.binding.port, + addr.port, + self.seq_number, + self.ack_number, + TCP_FLAG_ACK | TCP_FLAG_SYN, + self.window_size, + addr.addr, + Vec::new(), + ); + + self.recv().await; + + self.state = TcpState::Established; + + Ok(addr) } - pub fn connect(&mut self, interface: &mut Interface, saddr: SocketAddr) -> Result<()> { + pub async fn connect(&mut self, interface: &mut Interface, saddr: SocketAddr) -> Result<()> { // make sure we're not already connected // match self.state { // TcpState::Closed => {}, // _ => return Err(Error::AlreadyConnected), - // } + // }; // if not already bound, bind to an ephemeral port if !self.is_bound { @@ -159,11 +222,30 @@ impl TcpSocket { self.window_size, saddr.addr, Vec::new(), // no payload - )?; + ); self.state = TcpState::SynSent; println!("[!] sent syn"); + + let _ = self.recv().await; + + self.seq_number += 1; + + let flags = TCP_FLAG_SYN & TCP_FLAG_ACK; + tcp::send_tcp_packet( + interface, + self.binding.port, + saddr.port, + self.seq_number, + self.ack_number, + flags, + self.window_size, + saddr.addr, + Vec::new(), + ); + + self.state = TcpState::Established; Ok(()) } @@ -182,144 +264,140 @@ impl TcpSocket { return Err(Error::NotConnected); } - self.send_buffer.enqueue_maybe(|(buffer, addr)| { - *buffer = payload; - *addr = dest; - Ok(()) - }) + let interface = get_interface_mut(); + tcp::send_tcp_packet(interface, self.binding.port, dest.port, self.seq_number, self.ack_number, self.flags, self.window_size, dest.addr, payload) } - pub fn send(&mut self, interface: &mut Interface) -> Result<()> { - if self.state != TcpState::Established { - return Err(Error::NotConnected); + pub async fn recv(&mut self) -> Result<(Vec, SocketAddr)> { + let (mut payload, addr) = self.recv_rx.recv().await; + payload.truncate(payload.len().saturating_sub(11)); // get rid of context bytes + let last = &payload[payload.len() - 2..payload.len()]; + self.window_size = u16::from_le_bytes([last[0], last[1]]); + self.flags = payload[payload.len() - 3]; + // let last = &payload[payload.len() - 7..payload.len() - 3]; + // self.ack_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); + let last = &payload[payload.len() - 11..payload.len() - 7]; + self.ack_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); + + if self.state == TcpState::Established { + let interface = get_interface_mut(); + self.ack_number += payload.len() as u32; + self.seq_number += 1; + println!("sending ack to a received packet"); + tcp::send_tcp_packet( + interface, + self.binding.port, + addr.port, + self.seq_number, + self.ack_number, + TCP_FLAG_ACK, + self.window_size, + addr.addr, + Vec::new() + ); } - match self.state { - TcpState::Established => { - // Process outgoing data - loop { - match self.send_buffer.dequeue_with(|entry| { - let (payload, addr) = entry; - (payload.clone(), *addr) - }) { - Ok((payload, dest)) => { - // Send with appropriate TCP flags - tcp::send_tcp_packet( - interface, - self.binding.port, - dest.port, - self.seq_number, - self.ack_number, - TCP_FLAG_ACK | TCP_FLAG_PSH, // PSH to push data to application layer - self.window_size, - dest.addr, - payload.clone(), - )?; - - // Update sequence number - self.seq_number += payload.len() as u32; - } - Err(Error::Exhausted) => break, - Err(e) => return Err(e), - } - } - Ok(()) - } - _ => Err(Error::NotConnected), - } + Ok((payload, addr)) } - pub fn recv(&mut self) -> Result<(Vec, SocketAddr)> { - self.recv_buffer - .dequeue_with(|entry: &mut (Vec, SocketAddr)| { - let (buffer, addr) = entry; - (buffer.clone(), addr.clone()) - }) + pub async fn recv_with_context(&mut self) -> Result<(Vec, SocketAddr)> { + let (payload, addr) = self.recv_rx.recv().await; + Ok((payload, addr)) } // Enqueues a packet for receiving and handles TCP state machine - pub fn recv_enqueue( + pub async fn recv_enqueue( &mut self, - interface: &mut Interface, seq_number: u32, ack_number: u32, flags: u8, + window_size: u16, payload: Vec, sender: SocketAddr, ) -> Result<()> { - // Handle connection establishment if in SYN_SENT state - if self.state == TcpState::SynSent { - // Check if this is a valid remote endpoint response - if let Some(remote) = self.remote_addr { - if remote == sender { - // This is a response to our SYN - if (flags & (TCP_FLAG_SYN | TCP_FLAG_ACK)) == (TCP_FLAG_SYN | TCP_FLAG_ACK) { - // Received SYN-ACK, update ACK number - self.ack_number = seq_number + 1; - - // Send ACK to complete three-way handshake - tcp::send_tcp_packet( - interface, - self.binding.port, - sender.port, - self.seq_number + 1, // SYN consumes one sequence number - self.ack_number, - TCP_FLAG_ACK, - self.window_size, - sender.addr, - Vec::new(), - )?; - - // Update state and sequence number - self.state = TcpState::Established; - self.connected = true; - self.seq_number += 1; // SYN consumes one sequence number - - return Ok(()); - } - } - } - } else if self.state == TcpState::Closed { - // Handle incoming SYN for passive open (if we're listening) - if flags & TCP_FLAG_SYN != 0 && flags & TCP_FLAG_ACK == 0 { - // This would be for a server socket - not handling passive open in this example - // But this is where you would handle it - } - } - - // Process state transitions based on TCP flags - self.process_tcp_state_transitions(interface, flags, seq_number, ack_number, sender)?; + println!("got a recv_enqueue"); + let mut payload_with_context = payload.clone(); + payload_with_context.extend_from_slice(&seq_number.to_le_bytes()); + payload_with_context.extend_from_slice(&ack_number.to_le_bytes()); + payload_with_context.push(flags); + payload_with_context.extend_from_slice(&window_size.to_le_bytes()); + + // let packet = TcpPacket::new(sender.port, self.binding.port, seq_number, ack_number, flags, window_size, payload, sender.addr, self.binding.addr); + self.recv_tx.send((payload_with_context, sender)).await; + Ok(()) - // Now that we've handled any state transitions, enqueue actual data for user - // Only enqueue if we're in established state and there's actual data - if self.state == TcpState::Established && (payload.len() > 0) { - // Only enqueue if there's actual data - self.recv_buffer.enqueue_maybe(|(buffer, addr)| { - *buffer = payload.clone(); - *addr = sender; - Ok(()) - })?; - - // Update ACK number and send ACK for the data - self.ack_number = seq_number + payload.len() as u32; - - // Send ACK for received data - if let Some(remote) = self.remote_addr { - tcp::send_tcp_packet( - interface, - self.binding.port, - remote.port, - self.seq_number, - self.ack_number, - TCP_FLAG_ACK, - self.window_size, - remote.addr, - Vec::new(), - )?; - } - } + // if self.state == TcpState::SynSent { + // // Check if this is a valid remote endpoint response + // if let Some(remote) = self.remote_addr { + // if remote == sender { + // // This is a response to our SYN + // if (flags & (TCP_FLAG_SYN | TCP_FLAG_ACK)) == (TCP_FLAG_SYN | TCP_FLAG_ACK) { + // // Received SYN-ACK, update ACK number + // self.ack_number = seq_number + 1; + // + // // Send ACK to complete three-way handshake + // tcp::send_tcp_packet( + // interface, + // self.binding.port, + // sender.port, + // self.seq_number + 1, // SYN consumes one sequence number + // self.ack_number, + // TCP_FLAG_ACK, + // self.window_size, + // sender.addr, + // Vec::new(), + // )?; + // + // // Update state and sequence number + // self.state = TcpState::Established; + // self.connected = true; + // self.seq_number += 1; // SYN consumes one sequence number + // + // return Ok(()); + // } + // } + // } + // } else if self.state == TcpState::Closed { + // // Handle incoming SYN for passive open (if we're listening) + // if flags & TCP_FLAG_SYN != 0 && flags & TCP_FLAG_ACK == 0 { + // // This would be for a server socket - not handling passive open in this example + // // But this is where you would handle it + // } + // } + // + // // Process state transitions based on TCP flags + // self.process_tcp_state_transitions(interface, flags, seq_number, ack_number, sender)?; + // + // // Now that we've handled any state transitions, enqueue actual data for user + // // Only enqueue if we're in established state and there's actual data + // if self.state == TcpState::Established && (payload.len() > 0) { + // // Only enqueue if there's actual data + // self.recv_buffer.enqueue_maybe(|(buffer, addr)| { + // *buffer = payload.clone(); + // *addr = sender; + // Ok(()) + // })?; + // + // // Update ACK number and send ACK for the data + // self.ack_number = seq_number + payload.len() as u32; + // + // // Send ACK for received data + // if let Some(remote) = self.remote_addr { + // tcp::send_tcp_packet( + // interface, + // self.binding.port, + // remote.port, + // self.seq_number, + // self.ack_number, + // TCP_FLAG_ACK, + // self.window_size, + // remote.addr, + // Vec::new(), + // )?; + // } + // } - Ok(()) + // Ok(()) } // Helper function to process TCP state transitions based on packet flags @@ -332,6 +410,10 @@ impl TcpSocket { _sender: SocketAddr, ) -> Result<()> { match self.state { + TcpState::SynSent => { + if flags & TCP_FLAG_ACK != 0 { + } + }, TcpState::Established => { // Handle FIN from remote if flags & TCP_FLAG_FIN != 0 { @@ -435,12 +517,12 @@ impl TcpSocket { // Returns the number of packets enqueued for sending. pub fn num_send_enqueued(&self) -> usize { - self.send_buffer.len() + 0 } // Returns the number of packets enqueued for receiving. pub fn num_recv_enqueued(&self) -> usize { - self.recv_buffer.len() + 0 } // Close the connection gracefully diff --git a/crates/kernel/src/networking/socket/udp.rs b/crates/kernel/src/networking/socket/udp.rs index 1c103fb0..8e6688b4 100644 --- a/crates/kernel/src/networking/socket/udp.rs +++ b/crates/kernel/src/networking/socket/udp.rs @@ -2,53 +2,53 @@ use crate::device::usb::device::net::get_interface_mut; use crate::networking::iface::udp; use crate::networking::iface::Interface; use crate::networking::socket::bindings::NEXT_SOCKETFD; -use crate::networking::socket::tagged::TaggedSocket; -use crate::networking::socket::SocketAddr; -use crate::networking::utils::ring::Ring; +use crate::networking::socket::tagged::{TaggedSocket, BUFFER_LEN}; +use crate::networking::socket::{SocketAddr, SockType}; +use crate::ringbuffer::{channel, Sender, Receiver}; use crate::networking::{Error, Result}; -use alloc::vec; use alloc::vec::Vec; use core::sync::atomic::Ordering; -fn new_ring_packet_buffer(capacity: usize) -> Ring<(Vec, SocketAddr)> { - let default_entry = (Vec::new(), SocketAddr::default()); // or some placeholder address - let buffer = vec![default_entry; capacity]; - Ring::from(buffer) -} - -pub static UDP_BUFFER_LEN: usize = 128; - // A UDP socket pub struct UdpSocket { binding: SocketAddr, is_bound: bool, - send_buffer: Ring<(Vec, SocketAddr)>, - recv_buffer: Ring<(Vec, SocketAddr)>, + // send_tx: Sender, SocketAddr)>, + // send_rx: Receiver, SocketAddr)>, + recv_tx: Sender, SocketAddr)>, + recv_rx: Receiver, SocketAddr)>, } impl UdpSocket { pub fn new() -> u16 { let interface = get_interface_mut(); + + // let (send_tx, send_rx) = channel::, SocketAddr)>(); + let (recv_tx, recv_rx) = channel::, SocketAddr)>(); + let socket = UdpSocket { binding: SocketAddr { addr: *interface.ipv4_addr, port: 0, }, is_bound: false, - send_buffer: new_ring_packet_buffer(UDP_BUFFER_LEN), - recv_buffer: new_ring_packet_buffer(UDP_BUFFER_LEN), + // send_tx, + // send_rx, + recv_tx, + recv_rx, }; let socketfd = NEXT_SOCKETFD.fetch_add(1, Ordering::SeqCst); - let mut sockets = interface.sockets.lock(); - sockets.insert(socketfd, TaggedSocket::Udp(socket)); + // let mut sockets = interface.sockets.lock(); + interface.sockets.insert(socketfd, TaggedSocket::Udp(socket)); socketfd } pub fn binding_equals(&self, saddr: SocketAddr) -> bool { - self.binding == saddr + println!("binding port {} provided port {}", self.binding.port, saddr.port); + self.binding.port == saddr.port } pub fn is_bound(&self) -> bool { @@ -61,68 +61,47 @@ impl UdpSocket { addr: *interface.ipv4_addr, port, }; - self.binding = bind_addr; } - pub fn send_enqueue(&mut self, payload: Vec, dest: SocketAddr) -> Result<()> { - self.send_buffer.enqueue_maybe(|(buffer, addr)| { - *buffer = payload; - *addr = dest; - Ok(()) - }) + pub async fn send_enqueue(&mut self, payload: Vec, dest: SocketAddr) -> Result<()> { + println!("enqueud send"); + let interface = get_interface_mut(); + + udp::send_udp_packet(interface, dest.addr, payload, self.binding.port, dest.port) + } + + pub fn get_recv_ref(&mut self) -> (SockType, Receiver, SocketAddr)>) { + (SockType::UDP, self.recv_rx.clone()) } - pub fn send(&mut self, interface: &mut Interface) -> Result<()> { - loop { - match self.send_buffer.dequeue_with(|entry| { - let (payload, addr) = entry; - (payload.clone(), *addr) - }) { - Ok((payload, dest)) => { - let _ = udp::send_udp_packet( - interface, - dest.addr, - payload, - self.binding.port, - dest.port, - ); - } - Err(Error::Exhausted) => break, - Err(_) => break, - } - } + pub fn get_send_ref(&mut self) -> (SockType, Sender, SocketAddr)>) { + (SockType::UDP, self.recv_tx.clone()) + } - Ok(()) + pub async fn recv(&mut self) -> Result<(Vec, SocketAddr)> { + let (payload, addr) = self.recv_rx.recv().await; + Ok((payload, addr)) } - // Dequeues a received packet along with it's source address from the - // socket. - // TODO: make blocking - pub fn recv(&mut self) -> Result<(Vec, SocketAddr)> { - self.recv_buffer - .dequeue_with(|entry: &mut (Vec, SocketAddr)| { - let (buffer, addr) = entry; - (buffer.clone(), addr.clone()) - }) + pub fn try_recv(&mut self) -> Result<(Vec, SocketAddr)> { + match self.recv_rx.try_recv() { + Some((payload, addr)) => Ok((payload, addr)), + None => Err(Error::Exhausted), + } } - // Enqueues a packet for receiving. - pub fn recv_enqueue(&mut self, payload: Vec, sender: SocketAddr) -> Result<()> { - self.recv_buffer.enqueue_maybe(|(buffer, addr)| { - *buffer = payload; - *addr = sender; - Ok(()) - }) + pub async fn recv_enqueue(&mut self, payload: Vec, sender: SocketAddr) -> Result<()> { + println!("got a recv_enqueue"); + self.recv_tx.send((payload, sender)).await; + Ok(()) } - // Returns the number of packets enqueued for sending. pub fn num_send_enqueued(&self) -> usize { - self.send_buffer.len() + 0 } - // Returns the number of packets enqueued for receiving. pub fn num_recv_enqueued(&self) -> usize { - self.recv_buffer.len() + 0 } } diff --git a/crates/kernel/src/ringbuffer.rs b/crates/kernel/src/ringbuffer.rs index d080387d..fa121db0 100644 --- a/crates/kernel/src/ringbuffer.rs +++ b/crates/kernel/src/ringbuffer.rs @@ -240,6 +240,13 @@ pub struct Receiver { inner: Arc>, } +impl Clone for Sender { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } +} impl Sender { pub fn try_send(&mut self, event: T) -> Result<(), T> { let res = unsafe { self.inner.buf.try_send(event) }; @@ -276,6 +283,14 @@ impl Sender { } } +impl Clone for Receiver { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } +} + impl Receiver { pub fn try_recv(&mut self) -> Option { let res = unsafe { self.inner.buf.try_recv() }; @@ -307,6 +322,23 @@ impl Receiver { res } + + pub fn recv_blocking(&mut self) -> T { + let mut guard = self.inner.len.lock(); + guard = self.inner.cond.wait_while_blocking(guard, |len| *len == 0); + + let res = unsafe { self.inner.buf.try_recv() }; + let res = res.unwrap(); + + let old_len = *guard; + *guard -= 1; + drop(guard); + if old_len == N - 1 { + self.inner.cond.notify_one(); + } + + res + } } // TODO: proper oneshot SPSC channel (single-use version of Future for cs439) From 1a6a7db907ff1d70fafd9f7aeb29efa1d935ee5f Mon Sep 17 00:00:00 2001 From: juice Date: Mon, 28 Apr 2025 09:56:22 -0500 Subject: [PATCH 03/13] TCP Fixes --- crates/kernel/examples/net.rs | 71 ++-- crates/kernel/src/networking/mod.rs | 1 + .../kernel/src/networking/socket/bindings.rs | 13 + crates/kernel/src/networking/socket/mod.rs | 2 +- crates/kernel/src/networking/socket/tagged.rs | 10 +- crates/kernel/src/networking/socket/tcp.rs | 336 +++++++----------- 6 files changed, 193 insertions(+), 240 deletions(-) diff --git a/crates/kernel/examples/net.rs b/crates/kernel/examples/net.rs index 29ecdb55..580e9cf5 100644 --- a/crates/kernel/examples/net.rs +++ b/crates/kernel/examples/net.rs @@ -10,7 +10,7 @@ use kernel::{device::usb::device::net::get_dhcpd_mut, event::{task, thread}, net #[allow(unused_imports)] use kernel::networking::socket::{ - bind, accept, listen, connect, recv_from, send_to, SocketAddr, TcpSocket, UdpSocket, + bind, close, accept, listen, connect, recv_from, send_to, SocketAddr, TcpSocket, UdpSocket, }; use kernel::networking::Result; use kernel::*; @@ -36,7 +36,7 @@ async fn main() { // println!("udp send test"); // let s = UdpSocket::new(); // let saddr = SocketAddr { - // addr: Ipv4Address::new([11, 187, 10, 102]), + // addr: Ipv4Address::new([10, 0, 2, 2]), // port: 1337, // }; // for _i in 0..5 { @@ -63,47 +63,50 @@ async fn main() { // [tcp send test] - // println!("tcp send test"); - // let saddr = SocketAddr { - // addr: Ipv4Address::new([11, 187, 10, 102]), - // port: 1337, - // }; - // - // let s = TcpSocket::new(); - // match connect(s, saddr).await { - // Ok(_) => (), - // Err(_) => println!("couldn't connect"), - // }; - // - // for _i in 0..5 { - // let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr); - // } - // println!("tcp send test end"); + println!("tcp send test"); + let saddr = SocketAddr { + addr: Ipv4Address::new([10, 0, 2, 2]), + port: 1337, + }; - - // [tcp recv test] let s = TcpSocket::new(); + match connect(s, saddr).await { + Ok(_) => (), + Err(_) => println!("couldn't connect"), + }; - bind(s, 22); - listen(s, 1).await; // has a timeout, we will wait for 5 seconds + for _i in 0..5 { + let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr).await; + } - let clientfd = accept(s).await; + close(s).await; + println!("tcp send test end"); - while let recv = recv_from(*clientfd.as_ref().unwrap()).await { - if let Ok((payload, senderaddr)) = recv { - println!("got message: {:x?}", payload); - } else { - break; - } - } + // [tcp recv test] + // let s = TcpSocket::new(); + // + // bind(s, 22); + // listen(s, 1).await; + // + // let clientfd = accept(s).await; + // + // while let recv = recv_from(*clientfd.as_ref().unwrap()).await { + // if let Ok((payload, senderaddr)) = recv { + // println!("got message: {:x?}", payload); + // } else { + // println!("\t[!] got a fin, ended"); + // break; + // } + // } - // there is a delay when calling NetSend on a packet, this loop is to allow all the packets to - // drain out - for i in 0..32 { - sync::spin_sleep(500_000); + // let usb packets drain + for _i in 0..32 { + sync::spin_sleep(10000_00); } + println!("here"); + shutdown(); } diff --git a/crates/kernel/src/networking/mod.rs b/crates/kernel/src/networking/mod.rs index 0c330aac..df4d04d5 100644 --- a/crates/kernel/src/networking/mod.rs +++ b/crates/kernel/src/networking/mod.rs @@ -46,6 +46,7 @@ pub enum Error { Checksum, Timeout, NotImplemented, + Closed, } pub type Result = CoreResult; diff --git a/crates/kernel/src/networking/socket/bindings.rs b/crates/kernel/src/networking/socket/bindings.rs index 2e5f1d58..0d536116 100644 --- a/crates/kernel/src/networking/socket/bindings.rs +++ b/crates/kernel/src/networking/socket/bindings.rs @@ -123,6 +123,19 @@ pub async fn accept(socketfd: u16) -> Result { Ok(socketfd) } +pub async fn close(socketfd: u16) -> Result<()> { + let interface = get_interface_mut(); + // 1. if listener not started, error + // let mut sockets = interface.sockets.lock(); + + let tagged_socket = interface.sockets + .get_mut(&socketfd) + .ok_or(Error::InvalidSocket(socketfd))?; + + // 2. accept 1 connection, error if no pending connections + tagged_socket.close().await +} + pub fn bind(socketfd: u16, port: u16) -> Result<()> { let interface = get_interface_mut(); // 1. check if binding is already in use by another socket diff --git a/crates/kernel/src/networking/socket/mod.rs b/crates/kernel/src/networking/socket/mod.rs index e990e159..63d3aba4 100644 --- a/crates/kernel/src/networking/socket/mod.rs +++ b/crates/kernel/src/networking/socket/mod.rs @@ -4,7 +4,7 @@ pub mod tagged; pub mod tcp; pub mod udp; -pub use self::bindings::{bind, accept, listen, connect, recv_from, send_to, SocketAddr, SockType}; +pub use self::bindings::{close, bind, accept, listen, connect, recv_from, send_to, SocketAddr, SockType}; pub use self::tagged::TaggedSocket; diff --git a/crates/kernel/src/networking/socket/tagged.rs b/crates/kernel/src/networking/socket/tagged.rs index d5b91254..8d1e77a9 100644 --- a/crates/kernel/src/networking/socket/tagged.rs +++ b/crates/kernel/src/networking/socket/tagged.rs @@ -37,7 +37,7 @@ impl TaggedSocket { match self { // TaggedSocket::Raw(socket) => socket.queue_send(payload, saddr), TaggedSocket::Udp(socket) => socket.send_enqueue(payload, saddr).await, - TaggedSocket::Tcp(socket) => socket.send_enqueue(payload, saddr), + TaggedSocket::Tcp(socket) => socket.send_enqueue(payload, saddr).await, } } @@ -109,6 +109,14 @@ impl TaggedSocket { } } + pub async fn close(&mut self) -> Result<()> { + match self { + // TaggedSocket::Raw(socket) => socket.recv(), + TaggedSocket::Udp(_socket) => Err(Error::Ignored), + TaggedSocket::Tcp(socket) => socket.close().await, + } + } + pub async fn accept(&mut self) -> Result { match self { // TaggedSocket::Raw(socket) => socket.recv(), diff --git a/crates/kernel/src/networking/socket/tcp.rs b/crates/kernel/src/networking/socket/tcp.rs index 3f6e83c7..bc622c35 100644 --- a/crates/kernel/src/networking/socket/tcp.rs +++ b/crates/kernel/src/networking/socket/tcp.rs @@ -228,228 +228,85 @@ impl TcpSocket { println!("[!] sent syn"); - let _ = self.recv().await; - - self.seq_number += 1; - - let flags = TCP_FLAG_SYN & TCP_FLAG_ACK; - tcp::send_tcp_packet( - interface, - self.binding.port, - saddr.port, - self.seq_number, - self.ack_number, - flags, - self.window_size, - saddr.addr, - Vec::new(), - ); - - self.state = TcpState::Established; + let _ = self.recv().await?; Ok(()) } - pub fn send_enqueue(&mut self, payload: Vec, dest: SocketAddr) -> Result<()> { + pub async fn send_enqueue(&mut self, payload: Vec, dest: SocketAddr) -> Result<()> { if self.state != TcpState::Established { return Err(Error::NotConnected); } - // verify the destination matches the connected remote address - if let Some(remote) = self.remote_addr { - if remote != dest { - return Err(Error::NotConnected); - } - } else { - return Err(Error::NotConnected); - } + // if let Some(remote) = self.remote_addr { + // if remote != dest { + // return Err(Error::NotConnected); + // } + // } else { + // return Err(Error::NotConnected); + // } let interface = get_interface_mut(); - tcp::send_tcp_packet(interface, self.binding.port, dest.port, self.seq_number, self.ack_number, self.flags, self.window_size, dest.addr, payload) + tcp::send_tcp_packet( + interface, + self.binding.port, + dest.port, + self.seq_number, + self.ack_number, + // TCP_FLAG_PSH | TCP_FLAG_ACK, + TCP_FLAG_ACK, + self.window_size, + dest.addr, + payload + ); + + self.recv().await; + + Ok(()) } pub async fn recv(&mut self) -> Result<(Vec, SocketAddr)> { + let interface = get_interface_mut(); + let (mut payload, addr) = self.recv_rx.recv().await; - payload.truncate(payload.len().saturating_sub(11)); // get rid of context bytes let last = &payload[payload.len() - 2..payload.len()]; self.window_size = u16::from_le_bytes([last[0], last[1]]); - self.flags = payload[payload.len() - 3]; - // let last = &payload[payload.len() - 7..payload.len() - 3]; - // self.ack_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); + let flags = payload[payload.len() - 3]; + let last = &payload[payload.len() - 7..payload.len() - 3]; + let ack_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); let last = &payload[payload.len() - 11..payload.len() - 7]; - self.ack_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); - - if self.state == TcpState::Established { - let interface = get_interface_mut(); - self.ack_number += payload.len() as u32; - self.seq_number += 1; - println!("sending ack to a received packet"); - tcp::send_tcp_packet( - interface, - self.binding.port, - addr.port, - self.seq_number, - self.ack_number, - TCP_FLAG_ACK, - self.window_size, - addr.addr, - Vec::new() - ); - } + let seq_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); - Ok((payload, addr)) - } - - pub async fn recv_with_context(&mut self) -> Result<(Vec, SocketAddr)> { - let (payload, addr) = self.recv_rx.recv().await; - Ok((payload, addr)) - } - - // Enqueues a packet for receiving and handles TCP state machine - pub async fn recv_enqueue( - &mut self, - seq_number: u32, - ack_number: u32, - flags: u8, - window_size: u16, - payload: Vec, - sender: SocketAddr, - ) -> Result<()> { - println!("got a recv_enqueue"); - let mut payload_with_context = payload.clone(); - payload_with_context.extend_from_slice(&seq_number.to_le_bytes()); - payload_with_context.extend_from_slice(&ack_number.to_le_bytes()); - payload_with_context.push(flags); - payload_with_context.extend_from_slice(&window_size.to_le_bytes()); + payload.truncate(payload.len().saturating_sub(11)); // get rid of context bytes - // let packet = TcpPacket::new(sender.port, self.binding.port, seq_number, ack_number, flags, window_size, payload, sender.addr, self.binding.addr); - self.recv_tx.send((payload_with_context, sender)).await; - Ok(()) - - // if self.state == TcpState::SynSent { - // // Check if this is a valid remote endpoint response - // if let Some(remote) = self.remote_addr { - // if remote == sender { - // // This is a response to our SYN - // if (flags & (TCP_FLAG_SYN | TCP_FLAG_ACK)) == (TCP_FLAG_SYN | TCP_FLAG_ACK) { - // // Received SYN-ACK, update ACK number - // self.ack_number = seq_number + 1; - // - // // Send ACK to complete three-way handshake - // tcp::send_tcp_packet( - // interface, - // self.binding.port, - // sender.port, - // self.seq_number + 1, // SYN consumes one sequence number - // self.ack_number, - // TCP_FLAG_ACK, - // self.window_size, - // sender.addr, - // Vec::new(), - // )?; - // - // // Update state and sequence number - // self.state = TcpState::Established; - // self.connected = true; - // self.seq_number += 1; // SYN consumes one sequence number - // - // return Ok(()); - // } - // } - // } - // } else if self.state == TcpState::Closed { - // // Handle incoming SYN for passive open (if we're listening) - // if flags & TCP_FLAG_SYN != 0 && flags & TCP_FLAG_ACK == 0 { - // // This would be for a server socket - not handling passive open in this example - // // But this is where you would handle it - // } - // } - // - // // Process state transitions based on TCP flags - // self.process_tcp_state_transitions(interface, flags, seq_number, ack_number, sender)?; - // - // // Now that we've handled any state transitions, enqueue actual data for user - // // Only enqueue if we're in established state and there's actual data - // if self.state == TcpState::Established && (payload.len() > 0) { - // // Only enqueue if there's actual data - // self.recv_buffer.enqueue_maybe(|(buffer, addr)| { - // *buffer = payload.clone(); - // *addr = sender; - // Ok(()) - // })?; - // - // // Update ACK number and send ACK for the data - // self.ack_number = seq_number + payload.len() as u32; - // - // // Send ACK for received data - // if let Some(remote) = self.remote_addr { - // tcp::send_tcp_packet( - // interface, - // self.binding.port, - // remote.port, - // self.seq_number, - // self.ack_number, - // TCP_FLAG_ACK, - // self.window_size, - // remote.addr, - // Vec::new(), - // )?; - // } - // } - - // Ok(()) - } - - // Helper function to process TCP state transitions based on packet flags - fn process_tcp_state_transitions( - &mut self, - interface: &mut Interface, - flags: u8, - seq_number: u32, - _ack_number: u32, - _sender: SocketAddr, - ) -> Result<()> { match self.state { TcpState::SynSent => { - if flags & TCP_FLAG_ACK != 0 { - } - }, - TcpState::Established => { - // Handle FIN from remote - if flags & TCP_FLAG_FIN != 0 { - self.ack_number = seq_number + 1; // FIN consumes a sequence number + if flags & TCP_FLAG_RST != 0 { + return Err(Error::Closed); + } else if flags & (TCP_FLAG_ACK | TCP_FLAG_SYN) != 0 { + self.seq_number += 1; + self.ack_number = seq_number + 1; - // Send ACK for FIN - if let Some(remote) = self.remote_addr { - tcp::send_tcp_packet( - interface, - self.binding.port, - remote.port, - self.seq_number, - self.ack_number, - TCP_FLAG_ACK, - self.window_size, - remote.addr, - Vec::new(), - )?; - } + tcp::send_tcp_packet( + interface, + self.binding.port, + addr.port, + self.seq_number, + self.ack_number, + TCP_FLAG_ACK, + self.window_size, + addr.addr, + Vec::new(), + )?; - self.state = TcpState::CloseWait; + self.state = TcpState::Established; } - // Handle RST from remote - if flags & TCP_FLAG_RST != 0 { - self.state = TcpState::Closed; - self.connected = false; - self.remote_addr = None; - } } - TcpState::FinWait1 => { if flags & TCP_FLAG_ACK != 0 { // Our FIN was acknowledged - if flags & TCP_FLAG_FIN != 0 { - // Simultaneous FIN-ACK + if flags & TCP_FLAG_FIN != 0 { // Simultaneous FIN-ACK self.ack_number = seq_number + 1; // Send ACK for their FIN @@ -473,13 +330,11 @@ impl TcpSocket { self.state = TcpState::FinWait2; } } - } - + }, TcpState::FinWait2 => { if flags & TCP_FLAG_FIN != 0 { self.ack_number = seq_number + 1; - // Send ACK for their FIN if let Some(remote) = self.remote_addr { tcp::send_tcp_packet( interface, @@ -495,24 +350,88 @@ impl TcpSocket { } self.state = TcpState::TimeWait; - // In a real implementation, start the TIME_WAIT timer here } - } - + }, TcpState::LastAck => { if flags & TCP_FLAG_ACK != 0 { - // Final ACK received, connection fully closed self.state = TcpState::Closed; self.connected = false; self.remote_addr = None; } - } + }, + TcpState::Established => { + let interface = get_interface_mut(); - // Handle other states as needed - _ => {} + if flags & TCP_FLAG_FIN != 0 { + self.state = TcpState::Closed; + + self.ack_number += 1; + tcp::send_tcp_packet( + interface, + self.binding.port, + addr.port, + self.seq_number, + self.ack_number, + TCP_FLAG_ACK, + self.window_size, + addr.addr, + Vec::new() + ); + + return Err(Error::Closed); + } + + if payload.len() > 0 { + self.ack_number += payload.len() as u32; + self.seq_number += 1; + tcp::send_tcp_packet( + interface, + self.binding.port, + addr.port, + self.seq_number, + self.ack_number, + TCP_FLAG_ACK, + self.window_size, + addr.addr, + Vec::new() + ); + } else { + let old_seq = self.seq_number; + self.seq_number = ack_number; + self.ack_number = old_seq + payload.len() as u32; + } + }, + _ => {}, } + Ok((payload, addr)) + } + + pub async fn recv_with_context(&mut self) -> Result<(Vec, SocketAddr)> { + let (payload, addr) = self.recv_rx.recv().await; + Ok((payload, addr)) + } + + // Enqueues a packet for receiving and handles TCP state machine + pub async fn recv_enqueue( + &mut self, + seq_number: u32, + ack_number: u32, + flags: u8, + window_size: u16, + payload: Vec, + sender: SocketAddr, + ) -> Result<()> { + println!("got a recv_enqueue"); + let mut payload_with_context = payload.clone(); + payload_with_context.extend_from_slice(&seq_number.to_le_bytes()); + payload_with_context.extend_from_slice(&ack_number.to_le_bytes()); + payload_with_context.push(flags); + payload_with_context.extend_from_slice(&window_size.to_le_bytes()); + + self.recv_tx.send((payload_with_context, sender)).await; Ok(()) + } // Returns the number of packets enqueued for sending. @@ -526,10 +445,12 @@ impl TcpSocket { } // Close the connection gracefully - pub fn close(&mut self, interface: &mut Interface) -> Result<()> { + pub async fn close(&mut self) -> Result<()> { + let interface = get_interface_mut(); match self.state { TcpState::Established => { // Send FIN packet + println!("sending a close"); if let Some(remote) = self.remote_addr { tcp::send_tcp_packet( interface, @@ -546,6 +467,13 @@ impl TcpSocket { self.seq_number += 1; // FIN consumes a sequence number self.state = TcpState::FinWait1; } + + self.recv().await; + + if self.state == TcpState::FinWait2 { + self.recv().await; + } + Ok(()) } TcpState::CloseWait => { From 15ba1c05950d32bce1bbeeb8e3316f9d11a9feda Mon Sep 17 00:00:00 2001 From: juice Date: Mon, 28 Apr 2025 14:01:07 -0500 Subject: [PATCH 04/13] HTTP & DNS updates --- crates/kernel/examples/net.rs | 55 +++- crates/kernel/src/device/usb/device/rndis.rs | 3 +- crates/kernel/src/networking/iface/dhcp.rs | 5 +- .../kernel/src/networking/iface/ethernet.rs | 7 +- crates/kernel/src/networking/iface/ipv4.rs | 2 +- crates/kernel/src/networking/iface/udp.rs | 2 +- crates/kernel/src/networking/repr/dns.rs | 243 ++++++++++++++++++ crates/kernel/src/networking/repr/http.rs | 198 ++++++++++++++ crates/kernel/src/networking/repr/mod.rs | 6 + .../kernel/src/networking/socket/bindings.rs | 29 ++- crates/kernel/src/networking/socket/tcp.rs | 4 +- crates/kernel/src/networking/socket/udp.rs | 2 +- 12 files changed, 531 insertions(+), 25 deletions(-) create mode 100644 crates/kernel/src/networking/repr/dns.rs create mode 100644 crates/kernel/src/networking/repr/http.rs diff --git a/crates/kernel/examples/net.rs b/crates/kernel/examples/net.rs index 580e9cf5..737ffdb0 100644 --- a/crates/kernel/examples/net.rs +++ b/crates/kernel/examples/net.rs @@ -6,7 +6,7 @@ extern crate kernel; use core::net::Ipv4Addr; -use kernel::{device::usb::device::net::get_dhcpd_mut, event::{task, thread}, networking::{iface::icmp, repr::{IcmpPacket, Ipv4Address}, socket::RawSocket}, ringbuffer}; +use kernel::{device::usb::device::net::get_dhcpd_mut, event::{task, thread}, networking::{iface::icmp, repr::{HttpPacket, HttpMethod, IcmpPacket, Ipv4Address}, socket::RawSocket}, ringbuffer}; #[allow(unused_imports)] use kernel::networking::socket::{ @@ -15,6 +15,8 @@ use kernel::networking::socket::{ use kernel::networking::Result; use kernel::*; +use alloc::string::String; + #[no_mangle] extern "Rust" fn kernel_main(_device_tree: device_tree::DeviceTree) { println!("| starting kernel_main"); @@ -32,7 +34,7 @@ async fn main() { println!("out of dhcpd"); - // [udp send test] + // // [udp send test] // println!("udp send test"); // let s = UdpSocket::new(); // let saddr = SocketAddr { @@ -40,10 +42,14 @@ async fn main() { // port: 1337, // }; // for _i in 0..5 { - // let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr).await; + // let _ = send_to(s, "hello everynyan\n".as_bytes().to_vec(), saddr).await; // } // println!("end udp send test"); + // for _i in 0..5 { + // sync::spin_sleep(500_000); + // } + // [udp listening test] // println!("udp listening test"); @@ -75,8 +81,8 @@ async fn main() { Err(_) => println!("couldn't connect"), }; - for _i in 0..5 { - let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr).await; + for _i in 0..100 { + let _ = send_to(s, "hello everynyan\n".as_bytes().to_vec(), saddr).await; } close(s).await; @@ -91,22 +97,45 @@ async fn main() { // // let clientfd = accept(s).await; // + // let mut tot = 0; // while let recv = recv_from(*clientfd.as_ref().unwrap()).await { // if let Ok((payload, senderaddr)) = recv { // println!("got message: {:x?}", payload); + // tot += payload.len() // } else { // println!("\t[!] got a fin, ended"); // break; // } // } - - // let usb packets drain - for _i in 0..32 { - sync::spin_sleep(10000_00); - } - - println!("here"); - + // + // println!("got {} bytes", tot); + + // [http request test] + // println!("http send test"); + // // let host = "http.badssl.com"; + // let host = "http-textarea.badssl.com"; + // // let host = "example.com"; + // let saddr = SocketAddr::resolve(host, 80).await; + // + // let s = TcpSocket::new(); + // match connect(s, saddr).await { + // Ok(_) => (), + // Err(_) => println!("couldn't connect"), + // }; + // + // let path = "/"; + // let http_req = HttpPacket::new(HttpMethod::Get, host, path); + // let _ = send_to(s, http_req.serialize(), saddr).await; + // + // let (resp, _) = recv_from(s).await.unwrap(); + // + // + // close(s).await; + // + // println!("response:\n{:?}", resp); + // println!("response:\n{:?}", String::from_utf8(resp)); + // println!("http send test end"); + shutdown(); } diff --git a/crates/kernel/src/device/usb/device/rndis.rs b/crates/kernel/src/device/usb/device/rndis.rs index 2a814185..24063e89 100644 --- a/crates/kernel/src/device/usb/device/rndis.rs +++ b/crates/kernel/src/device/usb/device/rndis.rs @@ -29,7 +29,8 @@ pub fn rndis_initialize_msg(device: &mut UsbDevice) -> ResultCode { request_id: 0, major_version: 1, minor_version: 0, - max_transfer_size: 0x4000, + // max_transfer_size: 0x4000, + max_transfer_size: 1540, }; let mut buffer_req = [0u8; 52]; diff --git a/crates/kernel/src/networking/iface/dhcp.rs b/crates/kernel/src/networking/iface/dhcp.rs index 12e62051..1e170b04 100644 --- a/crates/kernel/src/networking/iface/dhcp.rs +++ b/crates/kernel/src/networking/iface/dhcp.rs @@ -43,7 +43,7 @@ pub struct Dhcpd { rebind_time: Option, subnet_mask: u32, router: Option, - dns_servers: Vec, + pub dns_servers: Vec, udp_socket: u16, } @@ -195,10 +195,11 @@ impl Dhcpd { self.last_action_time = system_timer::get_time(); println!( - "\t[+] DHCP: Bound to IP {} with lease time {} seconds on gateway {}", + "\t[+] DHCP: Bound to IP {} with lease time {} seconds on gateway {} with dns servers {:?}", interface.ipv4_addr, self.lease_time.unwrap_or(0), interface.default_gateway, + self.dns_servers ); } (DhcpState::Requesting, DhcpMessageType::Nak) diff --git a/crates/kernel/src/networking/iface/ethernet.rs b/crates/kernel/src/networking/iface/ethernet.rs index 6a85c295..3b5e4656 100644 --- a/crates/kernel/src/networking/iface/ethernet.rs +++ b/crates/kernel/src/networking/iface/ethernet.rs @@ -31,9 +31,12 @@ pub fn send_ethernet_frame( Ok(()) } +// pub static mut FRAME: Vec = Vec::new(); +// pub static mut LEFT: u32 = 0; + // recv ethernet frame from interface: parsed -> fwd to socket -> propogated up stack -pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u32) -> Result<()> { - println!("[!] received ethernet frame"); +pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], len: u32) -> Result<()> { + // println!("[!] received ethernet frame"); // println!("\t{:x?}", ð_buffer[44..]); // we will truncate the first 44 bytes from the RNDIS protocol diff --git a/crates/kernel/src/networking/iface/ipv4.rs b/crates/kernel/src/networking/iface/ipv4.rs index 88e277fa..e2443985 100644 --- a/crates/kernel/src/networking/iface/ipv4.rs +++ b/crates/kernel/src/networking/iface/ipv4.rs @@ -41,7 +41,7 @@ pub fn send_ipv4_packet( } pub fn recv_ip_packet(interface: &mut Interface, eth_frame: EthernetFrame) -> Result<()> { - println!("[!] received IP packet"); + // println!("[!] received IP packet"); let ipv4_packet = Ipv4Packet::deserialize(eth_frame.payload.as_slice())?; if !ipv4_packet.is_valid_checksum() { return Err(Error::Checksum); diff --git a/crates/kernel/src/networking/iface/udp.rs b/crates/kernel/src/networking/iface/udp.rs index 5120c8ec..43189fdf 100644 --- a/crates/kernel/src/networking/iface/udp.rs +++ b/crates/kernel/src/networking/iface/udp.rs @@ -31,7 +31,7 @@ pub fn send_udp_packet( } pub fn recv_udp_packet(interface: &mut Interface, ipv4_packet: Ipv4Packet) -> Result<()> { - println!("\t received udp packet"); + // println!("\t received udp packet"); let udp_packet = UdpPacket::deserialize(ipv4_packet.payload.as_slice())?; let local_socket_addr = SocketAddr { diff --git a/crates/kernel/src/networking/repr/dns.rs b/crates/kernel/src/networking/repr/dns.rs new file mode 100644 index 00000000..631a6280 --- /dev/null +++ b/crates/kernel/src/networking/repr/dns.rs @@ -0,0 +1,243 @@ +use alloc::vec::Vec; +use alloc::vec; +use alloc::string::String; +use crate::networking::{Error, Result}; +use byteorder::{ByteOrder, NetworkEndian}; +use crate::networking::repr::Ipv4Address; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DnsHeader { + pub id: u16, + pub flags: u16, + pub qdcount: u16, + pub ancount: u16, + pub nscount: u16, + pub arcount: u16, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DnsQuestion { + pub qname: String, + pub qtype: u16, + pub qclass: u16, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DnsRecord { + pub name: String, + pub rtype: u16, + pub rclass: u16, + pub ttl: u32, + pub rdata: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Packet { + pub header: DnsHeader, + pub questions: Vec, + pub answers: Vec, + pub authorities: Vec, + pub additionals: Vec, + pub ip: Ipv4Address, +} + +impl Packet { + pub fn create_dns_query(domain: &str) -> Self { + let header = DnsHeader { + id: 0x1337, + flags: 0x0100, // Standard query (QR=0), recursion desired (RD=1) + qdcount: 1, // One question + ancount: 0, // No answers initially + nscount: 0, // No authorities initially + arcount: 0, // No additionals initially + }; + + let question = DnsQuestion { + qname: String::from(domain), + qtype: 1, // Type A (IPv4 address) + qclass: 1, // Class IN (Internet) + }; + + Packet { + header, + questions: vec![question], + answers: Vec::new(), + authorities: Vec::new(), + additionals: Vec::new(), + ip: Ipv4Address::empty(), + } + } + + pub fn extract_ip_address(&self) -> Option { + for record in &self.answers { + if record.rtype == 1 && record.rdata.len() == 4 { + let ip = Ipv4Address::new([record.rdata[0], record.rdata[1], record.rdata[2], record.rdata[3]]); + return Some(ip); + } + } + + Some(self.ip) + } + + + pub fn deserialize(buffer: &[u8]) -> Result { + if buffer.len() < 12 { + return Err(Error::Malformed); + } + + let id = NetworkEndian::read_u16(&buffer[0..2]); + let flags = NetworkEndian::read_u16(&buffer[2..4]); + let qdcount = NetworkEndian::read_u16(&buffer[4..6]); + let ancount = NetworkEndian::read_u16(&buffer[6..8]); + let nscount = NetworkEndian::read_u16(&buffer[8..10]); + let arcount = NetworkEndian::read_u16(&buffer[10..12]); + + // let mut offset = 12; + // let mut questions = Vec::new(); + // for _ in 0..qdcount { + // let (qname, next_offset) = read_qname(buffer, offset)?; + // offset = next_offset; + // if offset + 4 > buffer.len() { + // return Err(Error::Malformed); + // } + // let qtype = NetworkEndian::read_u16(&buffer[offset..offset+2]); + // let qclass = NetworkEndian::read_u16(&buffer[offset+2..offset+4]); + // offset += 4; + // questions.push(DnsQuestion { qname, qtype, qclass }); + // } + // + // let mut answers = Vec::new(); + // for _ in 0..ancount { + // println!("\t[!]ANSWER offset {}", offset ); + // let (record, next_offset) = read_record(buffer, offset)?; + // answers.push(record); + // offset = next_offset; + // } + // + // let mut authorities = Vec::new(); + // for _ in 0..nscount { + // let (record, next_offset) = read_record(buffer, offset)?; + // authorities.push(record); + // offset = next_offset; + // } + // + // let mut additionals = Vec::new(); + // for _ in 0..arcount { + // let (record, next_offset) = read_record(buffer, offset)?; + // additionals.push(record); + // offset = next_offset; + // } + + let len = buffer.len(); + Ok(Packet { + header: DnsHeader { id, flags, qdcount, ancount, nscount, arcount }, + questions: Vec::new(), + answers: Vec::new(), + authorities: Vec::new(), + additionals: Vec::new(), + ip: Ipv4Address::new([buffer[len-4], buffer[len-3], buffer[len-2], buffer[len-1]]), + }) + } + + pub fn serialize(&self) -> Vec { + let mut buffer = Vec::new(); + + let mut header = [0u8; 12]; + NetworkEndian::write_u16(&mut header[0..2], self.header.id); + NetworkEndian::write_u16(&mut header[2..4], self.header.flags); + NetworkEndian::write_u16(&mut header[4..6], self.questions.len() as u16); + NetworkEndian::write_u16(&mut header[6..8], self.answers.len() as u16); + NetworkEndian::write_u16(&mut header[8..10], self.authorities.len() as u16); + NetworkEndian::write_u16(&mut header[10..12], self.additionals.len() as u16); + buffer.extend_from_slice(&header); + + for question in &self.questions { + write_qname(&mut buffer, &question.qname); + let mut qinfo = [0u8; 4]; + NetworkEndian::write_u16(&mut qinfo[0..2], question.qtype); + NetworkEndian::write_u16(&mut qinfo[2..4], question.qclass); + buffer.extend_from_slice(&qinfo); + } + + for record in &self.answers { + write_record(&mut buffer, record); + } + for record in &self.authorities { + write_record(&mut buffer, record); + } + for record in &self.additionals { + write_record(&mut buffer, record); + } + + buffer + } +} + +fn read_qname(buffer: &[u8], mut offset: usize) -> Result<(String, usize)> { + let mut labels = Vec::new(); + loop { + if offset >= buffer.len() { + return Err(Error::Malformed); + } + let len = buffer[offset] as usize; + offset += 1; + if len == 0 { + break; + } + if offset + len > buffer.len() { + return Err(Error::Malformed); + } + + let label = core::str::from_utf8(&buffer[offset..offset+len]).map_err(|_| Error::Malformed)?; + labels.push(String::from(label)); + offset += len; + } + Ok((labels.join("."), offset)) +} + +fn write_qname(buffer: &mut Vec, name: &str) { + for part in name.split('.') { + buffer.push(part.len() as u8); + buffer.extend_from_slice(part.as_bytes()); + } + buffer.push(0); +} + +fn read_record(buffer: &[u8], offset: usize) -> Result<(DnsRecord, usize)> { + let (name, mut pos) = read_qname(buffer, offset)?; + if pos + 10 > buffer.len() { + println!("malformed "); + return Err(Error::Malformed); + } + let rtype = NetworkEndian::read_u16(&buffer[pos..pos+2]); + let rclass = NetworkEndian::read_u16(&buffer[pos+2..pos+4]); + let ttl = NetworkEndian::read_u32(&buffer[pos+4..pos+8]); + let rdlength = NetworkEndian::read_u16(&buffer[pos+8..pos+10]) as usize; + pos += 10; + + if pos + rdlength > buffer.len() { + println!("malformed "); + return Err(Error::Malformed); + } + let rdata = buffer[pos..pos+rdlength].to_vec(); + pos += rdlength; + + println!("made it"); + + Ok(( + DnsRecord { name, rtype, rclass, ttl, rdata }, + pos, + )) +} + +fn write_record(buffer: &mut Vec, record: &DnsRecord) { + write_qname(buffer, &record.name); + let mut rinfo = [0u8; 10]; + NetworkEndian::write_u16(&mut rinfo[0..2], record.rtype); + NetworkEndian::write_u16(&mut rinfo[2..4], record.rclass); + NetworkEndian::write_u32(&mut rinfo[4..8], record.ttl); + NetworkEndian::write_u16(&mut rinfo[8..10], record.rdata.len() as u16); + buffer.extend_from_slice(&rinfo); + buffer.extend_from_slice(&record.rdata); +} + diff --git a/crates/kernel/src/networking/repr/http.rs b/crates/kernel/src/networking/repr/http.rs new file mode 100644 index 00000000..c24a6e3a --- /dev/null +++ b/crates/kernel/src/networking/repr/http.rs @@ -0,0 +1,198 @@ +use alloc::string::{String, ToString}; +use alloc::vec; +use alloc::vec::Vec; +use crate::networking::{Error, Result}; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Method { + Get, + Post, + Put, + Delete, + Head, + Options, + Patch, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Header { + pub name: String, + pub value: String, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Packet { + pub method: Method, + pub path: String, + pub version: String, + pub headers: Vec
, + pub body: Vec, +} + +impl Packet { + pub fn new(method: Method, host: &str, path: &str) -> Self { + let mut headers = Vec::new(); + headers.push(Header { name: "Host".to_string(), value: host.to_string() }); + headers.push(Header { name: "User-Agent".to_string(), value: "curl/8.13.0".to_string() }); + headers.push(Header { name: "Accept".to_string(), value: "*/*".to_string() }); + Packet { + method, + path: path.to_string(), + version: "HTTP/1.1".to_string(), + headers, + body: Vec::new(), + } + } + + pub fn serialize(&self) -> Vec { + let mut buffer = Vec::new(); + + // Start-line + let method_str = match self.method { + Method::Get => "GET", + Method::Post => "POST", + Method::Put => "PUT", + Method::Delete => "DELETE", + Method::Head => "HEAD", + Method::Options => "OPTIONS", + Method::Patch => "PATCH", + }; + + buffer.extend_from_slice(method_str.as_bytes()); + buffer.push(b' '); + buffer.extend_from_slice(self.path.as_bytes()); + buffer.push(b' '); + buffer.extend_from_slice(self.version.as_bytes()); + buffer.extend_from_slice(b"\r\n"); + + // Headers + for header in &self.headers { + buffer.extend_from_slice(header.name.as_bytes()); + buffer.extend_from_slice(b": "); + buffer.extend_from_slice(header.value.as_bytes()); + buffer.extend_from_slice(b"\r\n"); + } + + // End of headers + buffer.extend_from_slice(b"\r\n"); + + // Body + buffer.extend_from_slice(&self.body); + + buffer + } + + pub fn deserialize(buffer: &[u8]) -> Result { + let mut headers = Vec::new(); + let mut pos = 0; + + // Parse request line + let request_line_end = find_crlf(buffer, pos).ok_or(Error::Malformed)?; + let request_line = &buffer[pos..request_line_end]; + let parts = split_ascii_whitespace(request_line); + + if parts.len() != 3 { + return Err(Error::Malformed); + } + + let method = match parts[0] { + b"GET" => Method::Get, + b"POST" => Method::Post, + b"PUT" => Method::Put, + b"DELETE" => Method::Delete, + b"HEAD" => Method::Head, + b"OPTIONS" => Method::Options, + b"PATCH" => Method::Patch, + _ => return Err(Error::Malformed), + }; + + let path = String::from_utf8(parts[1].to_vec()).map_err(|_| Error::Malformed)?; + let version = String::from_utf8(parts[2].to_vec()).map_err(|_| Error::Malformed)?; + + pos = request_line_end + 2; + + // Parse headers + loop { + if pos >= buffer.len() { + return Err(Error::Malformed); + } + + if buffer[pos..].starts_with(b"\r\n") { + pos += 2; + break; + } + + let header_end = find_crlf(buffer, pos).ok_or(Error::Malformed)?; + let header_line = &buffer[pos..header_end]; + + if let Some(colon_pos) = header_line.iter().position(|&b| b == b':') { + let name = String::from_utf8(header_line[..colon_pos].to_vec()).map_err(|_| Error::Malformed)?; + let value = String::from_utf8(header_line[colon_pos + 1..].to_vec()) + .map_err(|_| Error::Malformed)? + .trim() + .to_string(); + headers.push(Header { name, value }); + } else { + return Err(Error::Malformed); + } + + pos = header_end + 2; + } + + let body = buffer[pos..].to_vec(); + + Ok(Packet { + method, + path, + version, + headers, + body, + }) + } + + pub fn get_header(&self, name: &str) -> Option<&str> { + for header in &self.headers { + if header.name.eq_ignore_ascii_case(name) { + return Some(&header.value); + } + } + None + } + + pub fn content_length(&self) -> Option { + if let Some(value) = self.get_header("Content-Length") { + value.parse().ok() + } else { + None + } + } +} + +// Helper: Find \r\n (CRLF) sequence starting from position +fn find_crlf(buffer: &[u8], start: usize) -> Option { + buffer[start..] + .windows(2) + .position(|window| window == b"\r\n") + .map(|p| start + p) +} + +// Helper: Split a line into whitespace-separated parts +fn split_ascii_whitespace(line: &[u8]) -> Vec<&[u8]> { + let mut parts = Vec::new(); + let mut start = None; + for (i, &b) in line.iter().enumerate() { + if b.is_ascii_whitespace() { + if let Some(s) = start { + parts.push(&line[s..i]); + start = None; + } + } else if start.is_none() { + start = Some(i); + } + } + if let Some(s) = start { + parts.push(&line[s..]); + } + parts +} + diff --git a/crates/kernel/src/networking/repr/mod.rs b/crates/kernel/src/networking/repr/mod.rs index 2767b896..8ee249f8 100644 --- a/crates/kernel/src/networking/repr/mod.rs +++ b/crates/kernel/src/networking/repr/mod.rs @@ -25,6 +25,8 @@ mod icmp; mod ipv4; mod tcp; mod udp; +mod dns; +mod http; pub use self::ethernet::{ Address as EthernetAddress, EtherType as EthernetType, Frame as EthernetFrame, @@ -43,6 +45,10 @@ pub use self::icmp::{ pub use self::udp::Packet as UdpPacket; +pub use self::dns::Packet as DnsPacket; + +pub use self::http::{Packet as HttpPacket, Method as HttpMethod}; + pub use self::dhcp::{DhcpOption, DhcpParam, MessageType as DhcpMessageType, Packet as DhcpPacket}; pub use self::tcp::{Flags as TcpFlags, Packet as TcpPacket}; diff --git a/crates/kernel/src/networking/socket/bindings.rs b/crates/kernel/src/networking/socket/bindings.rs index 0d536116..4bd1bc26 100644 --- a/crates/kernel/src/networking/socket/bindings.rs +++ b/crates/kernel/src/networking/socket/bindings.rs @@ -4,12 +4,14 @@ use core::sync::atomic::{AtomicU16, Ordering}; use alloc::vec::Vec; -use crate::networking::repr::Ipv4Address; +use crate::networking::repr::{DhcpPacket, DnsPacket, Ipv4Address}; use crate::networking::{Error, Result}; -use crate::device::usb::device::net::get_interface_mut; +use crate::device::usb::device::net::{get_dhcpd_mut, get_interface_mut}; use crate::event::task::spawn_async; +use super::UdpSocket; + #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SocketAddr { pub addr: Ipv4Address, @@ -23,6 +25,29 @@ impl SocketAddr { port: 0, } } + + pub async fn resolve(host: &str, port: u16) -> Self { + let dhcp = get_dhcpd_mut(); + let dns_socket = UdpSocket::new(); + let _ = bind(dns_socket, 53); + + let dns_req = DnsPacket::create_dns_query(host); + + let saddr = SocketAddr { + addr: dhcp.dns_servers[0], + port: 53, + }; + + send_to(dns_socket, dns_req.serialize(), saddr).await; + + let (resp, _) = recv_from(dns_socket).await.unwrap(); + let dhcp_resp = DnsPacket::deserialize(&resp).unwrap(); + + SocketAddr { + addr: dhcp_resp.extract_ip_address().unwrap(), + port + } + } } impl Display for SocketAddr { diff --git a/crates/kernel/src/networking/socket/tcp.rs b/crates/kernel/src/networking/socket/tcp.rs index bc622c35..9a65a586 100644 --- a/crates/kernel/src/networking/socket/tcp.rs +++ b/crates/kernel/src/networking/socket/tcp.rs @@ -99,7 +99,7 @@ impl TcpSocket { } pub fn binding_equals(&self, saddr: SocketAddr) -> bool { - println!("binding port {} provided port {}", self.binding.port, saddr.port); + // println!("binding port {} provided port {}", self.binding.port, saddr.port); self.binding == saddr } @@ -450,7 +450,7 @@ impl TcpSocket { match self.state { TcpState::Established => { // Send FIN packet - println!("sending a close"); + // println!("sending a close"); if let Some(remote) = self.remote_addr { tcp::send_tcp_packet( interface, diff --git a/crates/kernel/src/networking/socket/udp.rs b/crates/kernel/src/networking/socket/udp.rs index 8e6688b4..e96befc1 100644 --- a/crates/kernel/src/networking/socket/udp.rs +++ b/crates/kernel/src/networking/socket/udp.rs @@ -47,7 +47,7 @@ impl UdpSocket { } pub fn binding_equals(&self, saddr: SocketAddr) -> bool { - println!("binding port {} provided port {}", self.binding.port, saddr.port); + // println!("binding port {} provided port {}", self.binding.port, saddr.port); self.binding.port == saddr.port } From 9e9d3a902f735a089497f8bf9126473495456e98 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Wed, 30 Apr 2025 11:14:14 -0500 Subject: [PATCH 05/13] Update change to fix when rndis overflows a single packet --- crates/kernel/examples/net.rs | 107 +++++----- crates/kernel/src/device/usb/device/net.rs | 8 +- crates/kernel/src/device/usb/usbd/endpoint.rs | 79 +++++-- crates/kernel/src/networking/iface/dhcp.rs | 18 +- .../kernel/src/networking/iface/ethernet.rs | 16 +- crates/kernel/src/networking/iface/ipv4.rs | 1 - crates/kernel/src/networking/iface/mod.rs | 5 +- crates/kernel/src/networking/iface/socket.rs | 33 --- crates/kernel/src/networking/iface/tcp.rs | 8 +- crates/kernel/src/networking/iface/udp.rs | 4 +- crates/kernel/src/networking/repr/dns.rs | 197 +++++++++++------- crates/kernel/src/networking/repr/http.rs | 22 +- crates/kernel/src/networking/repr/mod.rs | 6 +- .../kernel/src/networking/socket/bindings.rs | 36 ++-- crates/kernel/src/networking/socket/mod.rs | 4 +- crates/kernel/src/networking/socket/raw.rs | 24 ++- crates/kernel/src/networking/socket/tagged.rs | 7 +- crates/kernel/src/networking/socket/tcp.rs | 125 ++++++----- crates/kernel/src/networking/socket/udp.rs | 10 +- 19 files changed, 395 insertions(+), 315 deletions(-) delete mode 100644 crates/kernel/src/networking/iface/socket.rs diff --git a/crates/kernel/examples/net.rs b/crates/kernel/examples/net.rs index 737ffdb0..44a8c4bd 100644 --- a/crates/kernel/examples/net.rs +++ b/crates/kernel/examples/net.rs @@ -4,15 +4,23 @@ extern crate alloc; extern crate kernel; -use core::net::Ipv4Addr; - -use kernel::{device::usb::device::net::get_dhcpd_mut, event::{task, thread}, networking::{iface::icmp, repr::{HttpPacket, HttpMethod, IcmpPacket, Ipv4Address}, socket::RawSocket}, ringbuffer}; +#[allow(unused_imports)] +use kernel::{ + device::usb::device::net::get_dhcpd_mut, + event::{task, thread}, + networking::{ + iface::icmp, + repr::{HttpMethod, HttpPacket, IcmpPacket, Ipv4Address}, + socket::RawSocket, + Result, + }, + ringbuffer, +}; #[allow(unused_imports)] use kernel::networking::socket::{ - bind, close, accept, listen, connect, recv_from, send_to, SocketAddr, TcpSocket, UdpSocket, + accept, bind, close, connect, listen, recv_from, send_to, SocketAddr, TcpSocket, UdpSocket, }; -use kernel::networking::Result; use kernel::*; use alloc::string::String; @@ -30,7 +38,7 @@ async fn main() { println!("starting dhcpd"); let dhcpd = get_dhcpd_mut(); - dhcpd.start().await; + let _ = dhcpd.start().await; println!("out of dhcpd"); @@ -50,7 +58,6 @@ async fn main() { // sync::spin_sleep(500_000); // } - // [udp listening test] // println!("udp listening test"); // let s = UdpSocket::new(); @@ -67,32 +74,31 @@ async fn main() { // // println!("end udp listening test"); - // [tcp send test] - println!("tcp send test"); - let saddr = SocketAddr { - addr: Ipv4Address::new([10, 0, 2, 2]), - port: 1337, - }; - - let s = TcpSocket::new(); - match connect(s, saddr).await { - Ok(_) => (), - Err(_) => println!("couldn't connect"), - }; - - for _i in 0..100 { - let _ = send_to(s, "hello everynyan\n".as_bytes().to_vec(), saddr).await; - } - - close(s).await; - println!("tcp send test end"); - + // println!("tcp send test"); + // let saddr = SocketAddr { + // addr: Ipv4Address::new([10, 0, 2, 2]), + // port: 1337, + // }; + // + // let s = TcpSocket::new(); + // match connect(s, saddr).await { + // Ok(_) => (), + // Err(_) => println!("couldn't connect"), + // }; + // + // for _i in 0..100 { + // let _ = send_to(s, "hello everynyan\n".as_bytes().to_vec(), saddr).await; + // } + // + // close(s).await; + // println!("tcp send test end"); // [tcp recv test] // let s = TcpSocket::new(); // // bind(s, 22); + // listen(s, 1).await; // // let clientfd = accept(s).await; @@ -111,31 +117,30 @@ async fn main() { // println!("got {} bytes", tot); // [http request test] - // println!("http send test"); - // // let host = "http.badssl.com"; + println!("http send test"); + // let host = "http.badssl.com"; // let host = "http-textarea.badssl.com"; - // // let host = "example.com"; - // let saddr = SocketAddr::resolve(host, 80).await; - // - // let s = TcpSocket::new(); - // match connect(s, saddr).await { - // Ok(_) => (), - // Err(_) => println!("couldn't connect"), - // }; - // - // let path = "/"; - // let http_req = HttpPacket::new(HttpMethod::Get, host, path); - // let _ = send_to(s, http_req.serialize(), saddr).await; - // - // let (resp, _) = recv_from(s).await.unwrap(); - // - // - // close(s).await; - // - // println!("response:\n{:?}", resp); - // println!("response:\n{:?}", String::from_utf8(resp)); - // println!("http send test end"); - + // let host = "httpforever.com"; + let host = "neverssl.com"; + let saddr = SocketAddr::resolve(host, 80).await; + + let s = TcpSocket::new(); + match connect(s, saddr).await { + Ok(_) => (), + Err(_) => println!("couldn't connect"), + }; + + let path = "/"; + let http_req = HttpPacket::new(HttpMethod::Get, host, path); + let _ = send_to(s, http_req.serialize(), saddr).await; + + let (resp, _) = recv_from(s).await.unwrap(); + + let _ = close(s).await; + + println!("response:\n{:?}", resp); + println!("response:\n{:?}", String::from_utf8(resp)); + println!("http send test end"); shutdown(); } diff --git a/crates/kernel/src/device/usb/device/net.rs b/crates/kernel/src/device/usb/device/net.rs index 7a6a9984..aae2bb8f 100644 --- a/crates/kernel/src/device/usb/device/net.rs +++ b/crates/kernel/src/device/usb/device/net.rs @@ -150,7 +150,7 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // begin receieve series, this queues a receive to be ran which will eventually propogate back // to us through the rgistered `recv` function which then queues another receive - let buf = vec![0u8; 1500]; + let buf = vec![0u8; 1600]; unsafe { rndis_receive_packet(device, buf.into_boxed_slice(), 1500); // TODO: ask aaron if I need to use another function? } @@ -204,6 +204,12 @@ pub unsafe fn NetReceive(buffer: *mut u8, buffer_length: u32) { println!("| Net: No callback for receive."); } } + + let buf = vec![0u8; 1]; + unsafe { + let device = &mut *NET_DEVICE.device.unwrap(); + rndis_receive_packet(device, buf.into_boxed_slice(), 1600); + } } pub fn RegisterNetReceiveCallback(callback: unsafe fn(*mut u8, u32)) { diff --git a/crates/kernel/src/device/usb/usbd/endpoint.rs b/crates/kernel/src/device/usb/usbd/endpoint.rs index 6820e204..381e1ae9 100644 --- a/crates/kernel/src/device/usb/usbd/endpoint.rs +++ b/crates/kernel/src/device/usb/usbd/endpoint.rs @@ -8,9 +8,13 @@ */ use crate::device::usb; +use crate::device::system_timer::micro_delay; +use crate::device::usb::hcd::dwc::dwc_otg; use crate::device::usb::hcd::dwc::dwc_otg::DwcActivateChannel; use crate::device::usb::hcd::dwc::dwc_otg::UpdateDwcOddFrame; +use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; use crate::device::usb::hcd::dwc::dwc_otgreg::HCINT_FRMOVRUN; +use crate::device::usb::DwcDisableChannel; use crate::device::usb::UsbSendInterruptMessage; use usb::dwc_hub; use usb::hcd::dwc::dwc_otg::HcdUpdateTransferSize; @@ -19,18 +23,16 @@ use usb::types::*; use usb::usbd::device::*; use usb::usbd::pipe::*; use usb::PacketId; -use crate::device::usb::hcd::dwc::dwc_otg; -use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; -use crate::device::usb::DwcDisableChannel; -use crate::device::system_timer::micro_delay; - use crate::event::task::spawn_async_rt; -use crate::shutdown; use crate::sync::time::{interval, MissedTicks}; use alloc::boxed::Box; +// static mut NET_BUFFER_CUR_LEN: u32 = 0; +static mut NET_BUFFER_LEN: u32 = 0; +static mut NET_BUFFER_ACTIVE: bool = false; + pub fn finish_bulk_endpoint_callback_in( endpoint: endpoint_descriptor, hcint: u32, @@ -39,7 +41,7 @@ pub fn finish_bulk_endpoint_callback_in( let device = unsafe { &mut *endpoint.device }; let transfer_size = HcdUpdateTransferSize(device, channel); - let last_transfer = endpoint.buffer_length - transfer_size; + let mut last_transfer = endpoint.buffer_length - transfer_size; let endpoint_device = device.driver_data.downcast::().unwrap(); if hcint & HCINT_NAK != 0 { @@ -55,8 +57,7 @@ pub fn finish_bulk_endpoint_callback_in( channel, hcint, last_transfer ); - if last_transfer > 0 && (hcint & HCINT_CHHLTD == 0) && (hcint & HCINT_XFERCOMPL == 0) - { + if last_transfer > 0 && (hcint & HCINT_CHHLTD == 0) && (hcint & HCINT_XFERCOMPL == 0) { // DwcActivateChannel(channel); return false; @@ -68,8 +69,8 @@ pub fn finish_bulk_endpoint_callback_in( // return true; } } - // return; // WARN: aaron said to comment this out - + // return; // WARN: aaron said to comment this out + if hcint & HCINT_CHHLTD == 0 { panic!( "| Endpoint {} in: HCINT_CHHLTD not set, aborting. hcint: {:x} last transfer: {}", @@ -91,6 +92,45 @@ pub fn finish_bulk_endpoint_callback_in( // core::ptr::copy_nonoverlapping(dma_addr as *const u8, buffer, buffer_length as usize); // } + //assume rndis net bulk in + unsafe { + if !NET_BUFFER_ACTIVE { + use alloc::slice; + // let slice: &[u8] = unsafe { slice::from_raw_parts(dma_addr as *const u8, 16 as usize) }; + let slice32: &[u32] = slice::from_raw_parts(dma_addr as *const u32, 4 as usize); + //print slice + // println!("| Net buffer: {:?}", slice); + // println!("| Net buffer 32: {:?}", slice32); + let _buffer32 = dma_addr as *const u32; + + let rndis_len = slice32[3]; + // let part1 = unsafe { buffer32.offset(0) } as u32; + // println!("| rndis 1 {}", part1); + // println!( + // "| Net buffer length: {} rndis_len: {}", + // last_transfer, rndis_len + // ); + if rndis_len > last_transfer - 44 { + NET_BUFFER_ACTIVE = true; + NET_BUFFER_LEN = rndis_len; + //reenable channel + DwcActivateChannel(channel); + return false; + } + // println!("| NEt continue"); + } else { + if last_transfer >= NET_BUFFER_LEN { + // println!("| NEt buffer finished length: {} NETBUFFER {}", last_transfer, NET_BUFFER_LEN); + NET_BUFFER_ACTIVE = false; + last_transfer = NET_BUFFER_LEN; + } else { + // println!("| Net buffer not yet active length: {} NETBUFFER {}", last_transfer, NET_BUFFER_LEN); + DwcActivateChannel(channel); + return false; + } + } + } + //TODO: Perhaps update this to pass the direct dma buffer address instead of copying // as it is likely that the callback will need to copy the data anyway // Also, we suffer issue from buffer_length not being known before the copy so the callback likely will have better information about the buffer @@ -115,16 +155,24 @@ pub fn finish_bulk_endpoint_callback_out( let transfer_size = HcdUpdateTransferSize(device, channel); let last_transfer = endpoint.buffer_length - transfer_size; - println!("Bulk out transfer hcint {:x} , last transfer: {} ", hcint, last_transfer); + println!( + "Bulk out transfer hcint {:x} , last transfer: {} ", + hcint, last_transfer + ); if hcint & HCINT_CHHLTD == 0 { - panic!("| Endpoint {}: HCINT_CHHLTD not set, aborting. bulk out hcint {:x}", channel, hcint); + panic!( + "| Endpoint {}: HCINT_CHHLTD not set, aborting. bulk out hcint {:x}", + channel, hcint + ); } if hcint & HCINT_XFERCOMPL == 0 { - panic!("| Endpoint {}: HCINT_XFERCOMPL not set, aborting. bulk out hcint {:x}", channel, hcint); + panic!( + "| Endpoint {}: HCINT_XFERCOMPL not set, aborting. bulk out hcint {:x}", + channel, hcint + ); } - //Most Likely not going to be called but could be useful for cases where precise timing of when message gets off the system is needed let endpoint_device = device.driver_data.downcast::().unwrap(); if let Some(callback) = endpoint_device.endpoints[endpoint.device_endpoint_number as usize] { @@ -178,7 +226,6 @@ pub fn finish_interrupt_endpoint_callback( // return true; } - hcint |= hcint_nochhltd; } diff --git a/crates/kernel/src/networking/iface/dhcp.rs b/crates/kernel/src/networking/iface/dhcp.rs index 1e170b04..91c34ff7 100644 --- a/crates/kernel/src/networking/iface/dhcp.rs +++ b/crates/kernel/src/networking/iface/dhcp.rs @@ -1,6 +1,4 @@ use crate::device::system_timer; -use crate::ringbuffer::channel; -use crate::event::task::spawn_async; use crate::device::usb::device::net::get_interface_mut; use crate::networking::iface::Interface; @@ -89,12 +87,12 @@ impl Dhcpd { self.state = DhcpState::Discovering; self.last_action_time = time; - send_dhcp_discover(interface, self.udp_socket, self.xid).await; + let _ = send_dhcp_discover(interface, self.udp_socket, self.xid).await; while self.state != DhcpState::Bound { let r = recv_from(self.udp_socket).await; let (payload, _) = r.unwrap(); - self.process_dhcp_packet(interface, payload).await; + let _ = self.process_dhcp_packet(interface, payload).await; } Ok(()) @@ -110,7 +108,8 @@ impl Dhcpd { if let (Some(server_id), Some(offered_ip)) = (self.server_identifier, self.offered_ip) { let result = - send_dhcp_release(interface, self.xid, offered_ip, server_id, self.udp_socket).await; + send_dhcp_release(interface, self.xid, offered_ip, server_id, self.udp_socket) + .await; self.state = DhcpState::Released; result } else { @@ -145,7 +144,8 @@ impl Dhcpd { self.last_action_time = system_timer::get_time(); self.retries = DEFAULT_LEASE_RETRY; - send_dhcp_request(interface, self.xid, offered_ip, server_id, self.udp_socket).await?; + send_dhcp_request(interface, self.xid, offered_ip, server_id, self.udp_socket) + .await?; // send_dhcp_packet_workaround(interface, self.xid, offered_ip, server_id, packet)?; } else { return Err(Error::Malformed); @@ -405,7 +405,11 @@ pub async fn send_dhcp_release( send_dhcp_packet_unicast(interface, socketfd, &packet, server_id).await } -async fn send_dhcp_packet(interface: &mut Interface, socketfd: u16, packet: &DhcpPacket) -> Result<()> { +async fn send_dhcp_packet( + interface: &mut Interface, + socketfd: u16, + packet: &DhcpPacket, +) -> Result<()> { let data = packet.serialize(); let saddr = SocketAddr { addr: interface.ipv4_addr.broadcast(), diff --git a/crates/kernel/src/networking/iface/ethernet.rs b/crates/kernel/src/networking/iface/ethernet.rs index 3b5e4656..80d011e6 100644 --- a/crates/kernel/src/networking/iface/ethernet.rs +++ b/crates/kernel/src/networking/iface/ethernet.rs @@ -35,7 +35,7 @@ pub fn send_ethernet_frame( // pub static mut LEFT: u32 = 0; // recv ethernet frame from interface: parsed -> fwd to socket -> propogated up stack -pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], len: u32) -> Result<()> { +pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u32) -> Result<()> { // println!("[!] received ethernet frame"); // println!("\t{:x?}", ð_buffer[44..]); @@ -57,13 +57,13 @@ pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], len: u3 }; // queue another recv to be run in the future - thread::thread(move || { - let buf = vec![0u8; 1500]; - unsafe { - let device = &mut *NET_DEVICE.device.unwrap(); - rndis_receive_packet(device, buf.into_boxed_slice(), 1500); - } - }); + // thread::thread(move || { + // let buf = vec![0u8; 1500]; + // unsafe { + // let device = &mut *NET_DEVICE.device.unwrap(); + + // } + // }); return result; } diff --git a/crates/kernel/src/networking/iface/ipv4.rs b/crates/kernel/src/networking/iface/ipv4.rs index e2443985..f23d5ce5 100644 --- a/crates/kernel/src/networking/iface/ipv4.rs +++ b/crates/kernel/src/networking/iface/ipv4.rs @@ -57,7 +57,6 @@ pub fn recv_ip_packet(interface: &mut Interface, eth_frame: EthernetFrame) -> Re return Err(Error::Ignored); } - // update arp cache for immediate ICMP echo replies, errors, etc. if eth_frame.src.is_unicast() { let mut arp_cache = interface.arp_cache.lock(); diff --git a/crates/kernel/src/networking/iface/mod.rs b/crates/kernel/src/networking/iface/mod.rs index a9f5011a..c7ecfb89 100644 --- a/crates/kernel/src/networking/iface/mod.rs +++ b/crates/kernel/src/networking/iface/mod.rs @@ -9,12 +9,10 @@ use crate::device::system_timer; use crate::sync::SpinLock; -use crate::networking::repr::{Device, EthernetAddress, Ipv4Address, Ipv4Cidr}; +use crate::networking::repr::{EthernetAddress, Ipv4Address, Ipv4Cidr}; use crate::networking::socket::TaggedSocket; use crate::networking::utils::arp_cache::ArpCache; -use alloc::boxed::Box; -use alloc::sync::Arc; use alloc::collections::btree_map::BTreeMap; pub mod arp; @@ -23,7 +21,6 @@ pub mod dhcp; pub mod ethernet; pub mod icmp; pub mod ipv4; -pub mod socket; pub mod tcp; pub mod udp; diff --git a/crates/kernel/src/networking/iface/socket.rs b/crates/kernel/src/networking/iface/socket.rs deleted file mode 100644 index a6e6e7d9..00000000 --- a/crates/kernel/src/networking/iface/socket.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::device::usb::device::net::get_interface_mut; -use crate::event::thread; -use crate::sync; - -use crate::networking::socket::TaggedSocket; - -use alloc::vec::Vec; - -// pub fn socket_send_loop() { -// println!("socket_send_loop"); -// let interface = get_interface_mut(); -// println!("try send"); -// -// let to_send: Vec<_> = { -// let mut sockets = interface.sockets.lock(); -// sockets -// .iter_mut() -// .map(|(_, socket)| socket as *mut TaggedSocket) -// .collect() -// }; -// println!("try send2"); -// -// -// for &socket_ptr in &to_send { -// let socket: &mut TaggedSocket = unsafe { &mut *socket_ptr }; -// let _ = socket.send(interface); -// } -// -// thread::thread(move || { -// sync::spin_sleep(500_000); -// socket_send_loop(); -// }); -// } diff --git a/crates/kernel/src/networking/iface/tcp.rs b/crates/kernel/src/networking/iface/tcp.rs index 95104e81..685ddc9f 100644 --- a/crates/kernel/src/networking/iface/tcp.rs +++ b/crates/kernel/src/networking/iface/tcp.rs @@ -1,11 +1,11 @@ use crate::networking::iface::*; use crate::networking::repr::*; -use crate::networking::socket::SocketAddr; use crate::networking::socket::SockType; +use crate::networking::socket::SocketAddr; use crate::networking::{Error, Result}; -use alloc::vec::Vec; use crate::event::task; +use alloc::vec::Vec; pub fn send_tcp_packet( interface: &mut Interface, @@ -65,7 +65,7 @@ pub fn recv_tcp_packet(interface: &mut Interface, ipv4_packet: Ipv4Packet) -> Re if stype != SockType::TCP { return Err(Error::Unsupported); } - + let mut payload = tcp_packet.payload.clone(); payload.extend_from_slice(&tcp_packet.seq_number.to_le_bytes()); payload.extend_from_slice(&tcp_packet.ack_number.to_le_bytes()); @@ -73,7 +73,7 @@ pub fn recv_tcp_packet(interface: &mut Interface, ipv4_packet: Ipv4Packet) -> Re payload.extend_from_slice(&tcp_packet.window_size.to_le_bytes()); task::spawn_async(async move { - let _ = tx.send((payload, sender_socket_addr)).await; + let _ = tx.send((payload, sender_socket_addr)).await; }); } } diff --git a/crates/kernel/src/networking/iface/udp.rs b/crates/kernel/src/networking/iface/udp.rs index 43189fdf..e1df1076 100644 --- a/crates/kernel/src/networking/iface/udp.rs +++ b/crates/kernel/src/networking/iface/udp.rs @@ -2,7 +2,7 @@ use crate::networking::iface::*; use crate::networking::repr::*; use crate::networking::socket::SockType; use crate::networking::socket::SocketAddr; -use crate::networking::{Result, Error}; +use crate::networking::{Error, Result}; use crate::event::task; @@ -45,7 +45,7 @@ pub fn recv_udp_packet(interface: &mut Interface, ipv4_packet: Ipv4Packet) -> Re }; // let mut sockets = interface.sockets.lock(); - + for (_, socket) in interface.sockets.iter_mut() { if socket.binding_equals(local_socket_addr) { let (stype, mut tx) = socket.get_send_ref(); diff --git a/crates/kernel/src/networking/repr/dns.rs b/crates/kernel/src/networking/repr/dns.rs index 631a6280..ea7e30b0 100644 --- a/crates/kernel/src/networking/repr/dns.rs +++ b/crates/kernel/src/networking/repr/dns.rs @@ -1,9 +1,9 @@ -use alloc::vec::Vec; -use alloc::vec; -use alloc::string::String; +use crate::networking::repr::Ipv4Address; use crate::networking::{Error, Result}; +use alloc::string::String; +use alloc::vec; +use alloc::vec::Vec; use byteorder::{ByteOrder, NetworkEndian}; -use crate::networking::repr::Ipv4Address; #[derive(Debug, Clone, PartialEq, Eq)] pub struct DnsHeader { @@ -38,24 +38,23 @@ pub struct Packet { pub answers: Vec, pub authorities: Vec, pub additionals: Vec, - pub ip: Ipv4Address, } impl Packet { pub fn create_dns_query(domain: &str) -> Self { let header = DnsHeader { id: 0x1337, - flags: 0x0100, // Standard query (QR=0), recursion desired (RD=1) - qdcount: 1, // One question - ancount: 0, // No answers initially - nscount: 0, // No authorities initially - arcount: 0, // No additionals initially + flags: 0x0100, // Standard query (QR=0), recursion desired (RD=1) + qdcount: 1, // One question + ancount: 0, // No answers initially + nscount: 0, // No authorities initially + arcount: 0, // No additionals initially }; let question = DnsQuestion { qname: String::from(domain), - qtype: 1, // Type A (IPv4 address) - qclass: 1, // Class IN (Internet) + qtype: 1, // Type A (IPv4 address) + qclass: 1, // Class IN (Internet) }; Packet { @@ -64,22 +63,25 @@ impl Packet { answers: Vec::new(), authorities: Vec::new(), additionals: Vec::new(), - ip: Ipv4Address::empty(), } } pub fn extract_ip_address(&self) -> Option { for record in &self.answers { if record.rtype == 1 && record.rdata.len() == 4 { - let ip = Ipv4Address::new([record.rdata[0], record.rdata[1], record.rdata[2], record.rdata[3]]); + let ip = Ipv4Address::new([ + record.rdata[0], + record.rdata[1], + record.rdata[2], + record.rdata[3], + ]); return Some(ip); } } - Some(self.ip) + return None; } - pub fn deserialize(buffer: &[u8]) -> Result { if buffer.len() < 12 { return Err(Error::Malformed); @@ -92,50 +94,59 @@ impl Packet { let nscount = NetworkEndian::read_u16(&buffer[8..10]); let arcount = NetworkEndian::read_u16(&buffer[10..12]); - // let mut offset = 12; - // let mut questions = Vec::new(); - // for _ in 0..qdcount { - // let (qname, next_offset) = read_qname(buffer, offset)?; - // offset = next_offset; - // if offset + 4 > buffer.len() { - // return Err(Error::Malformed); - // } - // let qtype = NetworkEndian::read_u16(&buffer[offset..offset+2]); - // let qclass = NetworkEndian::read_u16(&buffer[offset+2..offset+4]); - // offset += 4; - // questions.push(DnsQuestion { qname, qtype, qclass }); - // } - // - // let mut answers = Vec::new(); - // for _ in 0..ancount { - // println!("\t[!]ANSWER offset {}", offset ); - // let (record, next_offset) = read_record(buffer, offset)?; - // answers.push(record); - // offset = next_offset; - // } - // - // let mut authorities = Vec::new(); - // for _ in 0..nscount { - // let (record, next_offset) = read_record(buffer, offset)?; - // authorities.push(record); - // offset = next_offset; - // } - // - // let mut additionals = Vec::new(); - // for _ in 0..arcount { - // let (record, next_offset) = read_record(buffer, offset)?; - // additionals.push(record); - // offset = next_offset; - // } - - let len = buffer.len(); + let mut offset = 12; + let mut questions = Vec::new(); + for _ in 0..qdcount { + let (qname, next_offset) = read_qname(buffer, offset)?; + offset = next_offset; + if offset + 4 > buffer.len() { + return Err(Error::Malformed); + } + let qtype = NetworkEndian::read_u16(&buffer[offset..offset + 2]); + let qclass = NetworkEndian::read_u16(&buffer[offset + 2..offset + 4]); + offset += 4; + questions.push(DnsQuestion { + qname, + qtype, + qclass, + }); + } + + let mut answers = Vec::new(); + for _ in 0..ancount { + println!("\t[!]ANSWER offset {}", offset); + let (record, next_offset) = read_record(buffer, offset)?; + answers.push(record); + offset = next_offset; + } + + let mut authorities = Vec::new(); + for _ in 0..nscount { + let (record, next_offset) = read_record(buffer, offset)?; + authorities.push(record); + offset = next_offset; + } + + let mut additionals = Vec::new(); + for _ in 0..arcount { + let (record, next_offset) = read_record(buffer, offset)?; + additionals.push(record); + offset = next_offset; + } + Ok(Packet { - header: DnsHeader { id, flags, qdcount, ancount, nscount, arcount }, - questions: Vec::new(), - answers: Vec::new(), - authorities: Vec::new(), - additionals: Vec::new(), - ip: Ipv4Address::new([buffer[len-4], buffer[len-3], buffer[len-2], buffer[len-1]]), + header: DnsHeader { + id, + flags, + qdcount, + ancount, + nscount, + arcount, + }, + questions, + answers, + authorities, + additionals, }) } @@ -175,24 +186,49 @@ impl Packet { fn read_qname(buffer: &[u8], mut offset: usize) -> Result<(String, usize)> { let mut labels = Vec::new(); + let mut jumped = false; + let original_offset = offset; + loop { if offset >= buffer.len() { return Err(Error::Malformed); } - let len = buffer[offset] as usize; - offset += 1; - if len == 0 { + + let len = buffer[offset]; + if len & 0xC0 == 0xC0 { + // Pointer to another location + if offset + 1 >= buffer.len() { + return Err(Error::Malformed); + } + let pointer = (((len & 0x3F) as usize) << 8) | buffer[offset + 1] as usize; + if pointer >= buffer.len() { + return Err(Error::Malformed); + } + let (suffix, _) = read_qname(buffer, pointer)?; + labels.push(suffix); + offset += 2; + jumped = true; break; + } else if len == 0 { + offset += 1; + break; + } else { + offset += 1; + if offset + len as usize > buffer.len() { + return Err(Error::Malformed); + } + let label = core::str::from_utf8(&buffer[offset..offset + len as usize]) + .map_err(|_| Error::Malformed)?; + labels.push(String::from(label)); + offset += len as usize; } - if offset + len > buffer.len() { - return Err(Error::Malformed); - } + } - let label = core::str::from_utf8(&buffer[offset..offset+len]).map_err(|_| Error::Malformed)?; - labels.push(String::from(label)); - offset += len; + if !jumped { + Ok((labels.join("."), offset)) + } else { + Ok((labels.join("."), original_offset + 2)) // after pointer } - Ok((labels.join("."), offset)) } fn write_qname(buffer: &mut Vec, name: &str) { @@ -206,26 +242,32 @@ fn write_qname(buffer: &mut Vec, name: &str) { fn read_record(buffer: &[u8], offset: usize) -> Result<(DnsRecord, usize)> { let (name, mut pos) = read_qname(buffer, offset)?; if pos + 10 > buffer.len() { - println!("malformed "); + println!("malformed "); return Err(Error::Malformed); } - let rtype = NetworkEndian::read_u16(&buffer[pos..pos+2]); - let rclass = NetworkEndian::read_u16(&buffer[pos+2..pos+4]); - let ttl = NetworkEndian::read_u32(&buffer[pos+4..pos+8]); - let rdlength = NetworkEndian::read_u16(&buffer[pos+8..pos+10]) as usize; + let rtype = NetworkEndian::read_u16(&buffer[pos..pos + 2]); + let rclass = NetworkEndian::read_u16(&buffer[pos + 2..pos + 4]); + let ttl = NetworkEndian::read_u32(&buffer[pos + 4..pos + 8]); + let rdlength = NetworkEndian::read_u16(&buffer[pos + 8..pos + 10]) as usize; pos += 10; if pos + rdlength > buffer.len() { - println!("malformed "); + println!("malformed "); return Err(Error::Malformed); } - let rdata = buffer[pos..pos+rdlength].to_vec(); + let rdata = buffer[pos..pos + rdlength].to_vec(); pos += rdlength; println!("made it"); Ok(( - DnsRecord { name, rtype, rclass, ttl, rdata }, + DnsRecord { + name, + rtype, + rclass, + ttl, + rdata, + }, pos, )) } @@ -240,4 +282,3 @@ fn write_record(buffer: &mut Vec, record: &DnsRecord) { buffer.extend_from_slice(&rinfo); buffer.extend_from_slice(&record.rdata); } - diff --git a/crates/kernel/src/networking/repr/http.rs b/crates/kernel/src/networking/repr/http.rs index c24a6e3a..1a012355 100644 --- a/crates/kernel/src/networking/repr/http.rs +++ b/crates/kernel/src/networking/repr/http.rs @@ -1,7 +1,6 @@ +use crate::networking::{Error, Result}; use alloc::string::{String, ToString}; -use alloc::vec; use alloc::vec::Vec; -use crate::networking::{Error, Result}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Method { @@ -32,9 +31,18 @@ pub struct Packet { impl Packet { pub fn new(method: Method, host: &str, path: &str) -> Self { let mut headers = Vec::new(); - headers.push(Header { name: "Host".to_string(), value: host.to_string() }); - headers.push(Header { name: "User-Agent".to_string(), value: "curl/8.13.0".to_string() }); - headers.push(Header { name: "Accept".to_string(), value: "*/*".to_string() }); + headers.push(Header { + name: "Host".to_string(), + value: host.to_string(), + }); + headers.push(Header { + name: "User-Agent".to_string(), + value: "curl/8.13.0".to_string(), + }); + headers.push(Header { + name: "Accept".to_string(), + value: "*/*".to_string(), + }); Packet { method, path: path.to_string(), @@ -126,7 +134,8 @@ impl Packet { let header_line = &buffer[pos..header_end]; if let Some(colon_pos) = header_line.iter().position(|&b| b == b':') { - let name = String::from_utf8(header_line[..colon_pos].to_vec()).map_err(|_| Error::Malformed)?; + let name = String::from_utf8(header_line[..colon_pos].to_vec()) + .map_err(|_| Error::Malformed)?; let value = String::from_utf8(header_line[colon_pos + 1..].to_vec()) .map_err(|_| Error::Malformed)? .trim() @@ -195,4 +204,3 @@ fn split_ascii_whitespace(line: &[u8]) -> Vec<&[u8]> { } parts } - diff --git a/crates/kernel/src/networking/repr/mod.rs b/crates/kernel/src/networking/repr/mod.rs index 8ee249f8..03af254a 100644 --- a/crates/kernel/src/networking/repr/mod.rs +++ b/crates/kernel/src/networking/repr/mod.rs @@ -20,13 +20,13 @@ mod arp; pub mod dev; mod dhcp; +mod dns; mod ethernet; +mod http; mod icmp; mod ipv4; mod tcp; mod udp; -mod dns; -mod http; pub use self::ethernet::{ Address as EthernetAddress, EtherType as EthernetType, Frame as EthernetFrame, @@ -47,7 +47,7 @@ pub use self::udp::Packet as UdpPacket; pub use self::dns::Packet as DnsPacket; -pub use self::http::{Packet as HttpPacket, Method as HttpMethod}; +pub use self::http::{Method as HttpMethod, Packet as HttpPacket}; pub use self::dhcp::{DhcpOption, DhcpParam, MessageType as DhcpMessageType, Packet as DhcpPacket}; diff --git a/crates/kernel/src/networking/socket/bindings.rs b/crates/kernel/src/networking/socket/bindings.rs index 4bd1bc26..078be213 100644 --- a/crates/kernel/src/networking/socket/bindings.rs +++ b/crates/kernel/src/networking/socket/bindings.rs @@ -4,11 +4,10 @@ use core::sync::atomic::{AtomicU16, Ordering}; use alloc::vec::Vec; -use crate::networking::repr::{DhcpPacket, DnsPacket, Ipv4Address}; +use crate::networking::repr::{DnsPacket, Ipv4Address}; use crate::networking::{Error, Result}; use crate::device::usb::device::net::{get_dhcpd_mut, get_interface_mut}; -use crate::event::task::spawn_async; use super::UdpSocket; @@ -25,7 +24,7 @@ impl SocketAddr { port: 0, } } - + pub async fn resolve(host: &str, port: u16) -> Self { let dhcp = get_dhcpd_mut(); let dns_socket = UdpSocket::new(); @@ -38,14 +37,14 @@ impl SocketAddr { port: 53, }; - send_to(dns_socket, dns_req.serialize(), saddr).await; + let _ = send_to(dns_socket, dns_req.serialize(), saddr).await; let (resp, _) = recv_from(dns_socket).await.unwrap(); let dhcp_resp = DnsPacket::deserialize(&resp).unwrap(); SocketAddr { addr: dhcp_resp.extract_ip_address().unwrap(), - port + port, } } } @@ -60,7 +59,7 @@ impl Display for SocketAddr { pub enum SockType { UDP, TCP, - Raw + Raw, } // TODO: these technically runs out eventually lol need wrap around @@ -72,7 +71,8 @@ pub async fn send_to(socketfd: u16, payload: Vec, saddr: SocketAddr) -> Resu // let mut sockets = interface.sockets.lock(); // 1. check if socket fd is valid if not return error - let tagged_socket = interface.sockets + let tagged_socket = interface + .sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; @@ -91,7 +91,8 @@ pub async fn recv_from(socketfd: u16) -> Result<(Vec, SocketAddr)> { let interface = get_interface_mut(); // 1. check if a socketfd is valid if not return error - let tagged_socket = interface.sockets + let tagged_socket = interface + .sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; @@ -101,7 +102,7 @@ pub async fn recv_from(socketfd: u16) -> Result<(Vec, SocketAddr)> { } // 3. blocking recv from socket recv queue - + tagged_socket.recv().await } @@ -110,7 +111,8 @@ pub async fn connect(socketfd: u16, saddr: SocketAddr) -> Result<()> { // let mut sockets = interface.sockets.lock(); // 1. check if a socketfd is valid if not return error - let tagged_socket = interface.sockets + let tagged_socket = interface + .sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; @@ -122,7 +124,8 @@ pub async fn listen(socketfd: u16, num_requests: usize) -> Result<()> { // 1.check if binded, if not error // let mut sockets = interface.sockets.lock(); - let tagged_socket = interface.sockets + let tagged_socket = interface + .sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; @@ -139,12 +142,13 @@ pub async fn accept(socketfd: u16) -> Result { // 1. if listener not started, error // let mut sockets = interface.sockets.lock(); - let tagged_socket = interface.sockets + let tagged_socket = interface + .sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; // 2. accept 1 connection, error if no pending connections - tagged_socket.accept().await; + let _ = tagged_socket.accept().await; Ok(socketfd) } @@ -153,7 +157,8 @@ pub async fn close(socketfd: u16) -> Result<()> { // 1. if listener not started, error // let mut sockets = interface.sockets.lock(); - let tagged_socket = interface.sockets + let tagged_socket = interface + .sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; @@ -176,7 +181,8 @@ pub fn bind(socketfd: u16, port: u16) -> Result<()> { } // 2. check if this is a valid socketfd - let tagged_socket = interface.sockets + let tagged_socket = interface + .sockets .get_mut(&socketfd) .ok_or(Error::InvalidSocket(socketfd))?; diff --git a/crates/kernel/src/networking/socket/mod.rs b/crates/kernel/src/networking/socket/mod.rs index 63d3aba4..808487aa 100644 --- a/crates/kernel/src/networking/socket/mod.rs +++ b/crates/kernel/src/networking/socket/mod.rs @@ -4,7 +4,9 @@ pub mod tagged; pub mod tcp; pub mod udp; -pub use self::bindings::{close, bind, accept, listen, connect, recv_from, send_to, SocketAddr, SockType}; +pub use self::bindings::{ + accept, bind, close, connect, listen, recv_from, send_to, SockType, SocketAddr, +}; pub use self::tagged::TaggedSocket; diff --git a/crates/kernel/src/networking/socket/raw.rs b/crates/kernel/src/networking/socket/raw.rs index 4cda7182..abab0293 100644 --- a/crates/kernel/src/networking/socket/raw.rs +++ b/crates/kernel/src/networking/socket/raw.rs @@ -1,12 +1,11 @@ -use crate::networking::repr::Ipv4Protocol; -use crate::networking::utils::{ring::Ring, slice::Slice}; +use crate::device::usb::device::net::get_interface_mut; use crate::networking::iface::ipv4; use crate::networking::iface::Interface; -use crate::device::usb::device::net::get_interface_mut; -use crate::networking::{Result, Error}; -use crate::ringbuffer::{channel, Sender, Receiver}; -use crate::networking::socket::tagged::{TaggedSocket, BUFFER_LEN}; -use crate::networking::socket::{SocketAddr, SockType}; +use crate::networking::repr::Ipv4Protocol; +use crate::networking::socket::tagged::BUFFER_LEN; +use crate::networking::socket::{SockType, SocketAddr}; +use crate::networking::{Error, Result}; +use crate::ringbuffer::{channel, Receiver, Sender}; use alloc::vec::Vec; @@ -26,9 +25,7 @@ pub struct RawSocket { } impl RawSocket { - pub fn new( - raw_type: RawType, - ) -> RawSocket { + pub fn new(raw_type: RawType) -> RawSocket { let (recv_tx, recv_rx) = channel::, SocketAddr)>(); let interface = get_interface_mut(); RawSocket { @@ -60,7 +57,12 @@ impl RawSocket { self.binding = bind_addr; } - pub async fn send_enqueue(&mut self, payload: Vec, proto: Ipv4Protocol, dest: SocketAddr) -> Result<()> { + pub async fn send_enqueue( + &mut self, + payload: Vec, + proto: Ipv4Protocol, + dest: SocketAddr, + ) -> Result<()> { println!("enqueud send"); let interface = get_interface_mut(); diff --git a/crates/kernel/src/networking/socket/tagged.rs b/crates/kernel/src/networking/socket/tagged.rs index 8d1e77a9..f3f477c3 100644 --- a/crates/kernel/src/networking/socket/tagged.rs +++ b/crates/kernel/src/networking/socket/tagged.rs @@ -1,5 +1,4 @@ -use crate::networking::iface::Interface; -use crate::networking::socket::{SocketAddr, TcpSocket, UdpSocket, SockType}; +use crate::networking::socket::{SockType, SocketAddr, TcpSocket, UdpSocket}; use crate::networking::{Error, Result}; use crate::device::usb::device::net::get_interface_mut; @@ -54,7 +53,9 @@ impl TaggedSocket { // TaggedSocket::Raw(socket) => socket.queue_recv(payload, saddr), TaggedSocket::Udp(socket) => socket.recv_enqueue(payload, saddr).await, TaggedSocket::Tcp(socket) => { - socket.recv_enqueue(seq_num, ack_num, flags, window_size, payload, saddr).await + socket + .recv_enqueue(seq_num, ack_num, flags, window_size, payload, saddr) + .await } } } diff --git a/crates/kernel/src/networking/socket/tcp.rs b/crates/kernel/src/networking/socket/tcp.rs index 9a65a586..2f4de1d1 100644 --- a/crates/kernel/src/networking/socket/tcp.rs +++ b/crates/kernel/src/networking/socket/tcp.rs @@ -1,21 +1,12 @@ use crate::device::usb::device::net::get_interface_mut; use crate::networking::iface::{tcp, Interface}; -use crate::networking::repr::TcpPacket; use crate::networking::socket::bindings::{NEXT_EPHEMERAL, NEXT_SOCKETFD}; use crate::networking::socket::tagged::{TaggedSocket, BUFFER_LEN}; -use crate::networking::socket::{SocketAddr, SockType}; -use crate::networking::utils::ring::Ring; +use crate::networking::socket::{SockType, SocketAddr}; use crate::networking::{Error, Result}; -use alloc::vec; +use crate::ringbuffer::{channel, Receiver, Sender}; use alloc::vec::Vec; use core::sync::atomic::Ordering; -use crate::ringbuffer::{channel, Sender, Receiver}; - -fn new_ring_packet_buffer(capacity: usize) -> Ring<(Vec, SocketAddr)> { - let default_entry = (Vec::new(), SocketAddr::default()); - let buffer = vec![default_entry; capacity]; - Ring::from(buffer) -} // flags pub const TCP_FLAG_FIN: u8 = 0x01; @@ -54,7 +45,6 @@ pub struct TcpSocket { recv_rx: Receiver, SocketAddr)>, // recvp_tx: Sender, // recvp_rx: Receiver, - state: TcpState, remote_addr: Option, seq_number: u32, @@ -82,8 +72,6 @@ impl TcpSocket { recv_rx, // recvp_tx, // recvp_rx, - - state: TcpState::Closed, remote_addr: None, seq_number: INITIAL_SEQ_NUMBER, @@ -94,7 +82,9 @@ impl TcpSocket { let socketfd = NEXT_SOCKETFD.fetch_add(1, Ordering::SeqCst); // let mut sockets = interface.sockets.lock(); - interface.sockets.insert(socketfd, TaggedSocket::Tcp(socket)); + interface + .sockets + .insert(socketfd, TaggedSocket::Tcp(socket)); socketfd } @@ -124,7 +114,11 @@ impl TcpSocket { self.binding = bind_addr; } - pub async fn listen(&mut self, interface: &mut Interface, num_max_requests: usize) -> Result<()> { + pub async fn listen( + &mut self, + interface: &mut Interface, + num_max_requests: usize, + ) -> Result<()> { println!("in listen"); if !self.is_bound { // bind to ephemeral if not bound @@ -176,19 +170,19 @@ impl TcpSocket { self.ack_number += 1; println!("ack number {}", self.ack_number); - tcp::send_tcp_packet( + let _ = tcp::send_tcp_packet( interface, self.binding.port, addr.port, self.seq_number, - self.ack_number, + self.ack_number, TCP_FLAG_ACK | TCP_FLAG_SYN, self.window_size, addr.addr, - Vec::new(), + Vec::new(), ); - self.recv().await; + let _ = self.recv().await; self.state = TcpState::Established; @@ -212,7 +206,7 @@ impl TcpSocket { self.remote_addr = Some(saddr); let flags = TCP_FLAG_SYN; - tcp::send_tcp_packet( + let _ = tcp::send_tcp_packet( interface, self.binding.port, saddr.port, @@ -227,7 +221,7 @@ impl TcpSocket { self.state = TcpState::SynSent; println!("[!] sent syn"); - + let _ = self.recv().await?; Ok(()) @@ -247,20 +241,20 @@ impl TcpSocket { // } let interface = get_interface_mut(); - tcp::send_tcp_packet( - interface, - self.binding.port, - dest.port, - self.seq_number, - self.ack_number, - // TCP_FLAG_PSH | TCP_FLAG_ACK, - TCP_FLAG_ACK, - self.window_size, - dest.addr, - payload + let _ = tcp::send_tcp_packet( + interface, + self.binding.port, + dest.port, + self.seq_number, + self.ack_number, + // TCP_FLAG_PSH | TCP_FLAG_ACK, + TCP_FLAG_ACK, + self.window_size, + dest.addr, + payload, ); - self.recv().await; + let _ = self.recv().await; Ok(()) } @@ -278,7 +272,7 @@ impl TcpSocket { let seq_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); payload.truncate(payload.len().saturating_sub(11)); // get rid of context bytes - + match self.state { TcpState::SynSent => { if flags & TCP_FLAG_RST != 0 { @@ -301,12 +295,12 @@ impl TcpSocket { self.state = TcpState::Established; } - } TcpState::FinWait1 => { if flags & TCP_FLAG_ACK != 0 { // Our FIN was acknowledged - if flags & TCP_FLAG_FIN != 0 { // Simultaneous FIN-ACK + if flags & TCP_FLAG_FIN != 0 { + // Simultaneous FIN-ACK self.ack_number = seq_number + 1; // Send ACK for their FIN @@ -330,7 +324,7 @@ impl TcpSocket { self.state = TcpState::FinWait2; } } - }, + } TcpState::FinWait2 => { if flags & TCP_FLAG_FIN != 0 { self.ack_number = seq_number + 1; @@ -351,14 +345,14 @@ impl TcpSocket { self.state = TcpState::TimeWait; } - }, + } TcpState::LastAck => { if flags & TCP_FLAG_ACK != 0 { self.state = TcpState::Closed; self.connected = false; self.remote_addr = None; } - }, + } TcpState::Established => { let interface = get_interface_mut(); @@ -366,16 +360,16 @@ impl TcpSocket { self.state = TcpState::Closed; self.ack_number += 1; - tcp::send_tcp_packet( - interface, - self.binding.port, - addr.port, - self.seq_number, - self.ack_number, - TCP_FLAG_ACK, - self.window_size, - addr.addr, - Vec::new() + let _ = tcp::send_tcp_packet( + interface, + self.binding.port, + addr.port, + self.seq_number, + self.ack_number, + TCP_FLAG_ACK, + self.window_size, + addr.addr, + Vec::new(), ); return Err(Error::Closed); @@ -384,24 +378,24 @@ impl TcpSocket { if payload.len() > 0 { self.ack_number += payload.len() as u32; self.seq_number += 1; - tcp::send_tcp_packet( - interface, - self.binding.port, - addr.port, - self.seq_number, - self.ack_number, - TCP_FLAG_ACK, - self.window_size, - addr.addr, - Vec::new() + let _ = tcp::send_tcp_packet( + interface, + self.binding.port, + addr.port, + self.seq_number, + self.ack_number, + TCP_FLAG_ACK, + self.window_size, + addr.addr, + Vec::new(), ); } else { let old_seq = self.seq_number; self.seq_number = ack_number; self.ack_number = old_seq + payload.len() as u32; } - }, - _ => {}, + } + _ => {} } Ok((payload, addr)) @@ -428,10 +422,9 @@ impl TcpSocket { payload_with_context.extend_from_slice(&ack_number.to_le_bytes()); payload_with_context.push(flags); payload_with_context.extend_from_slice(&window_size.to_le_bytes()); - + self.recv_tx.send((payload_with_context, sender)).await; Ok(()) - } // Returns the number of packets enqueued for sending. @@ -468,10 +461,10 @@ impl TcpSocket { self.state = TcpState::FinWait1; } - self.recv().await; + let _ = self.recv().await; if self.state == TcpState::FinWait2 { - self.recv().await; + let _ = self.recv().await; } Ok(()) diff --git a/crates/kernel/src/networking/socket/udp.rs b/crates/kernel/src/networking/socket/udp.rs index e96befc1..39078728 100644 --- a/crates/kernel/src/networking/socket/udp.rs +++ b/crates/kernel/src/networking/socket/udp.rs @@ -3,9 +3,9 @@ use crate::networking::iface::udp; use crate::networking::iface::Interface; use crate::networking::socket::bindings::NEXT_SOCKETFD; use crate::networking::socket::tagged::{TaggedSocket, BUFFER_LEN}; -use crate::networking::socket::{SocketAddr, SockType}; -use crate::ringbuffer::{channel, Sender, Receiver}; +use crate::networking::socket::{SockType, SocketAddr}; use crate::networking::{Error, Result}; +use crate::ringbuffer::{channel, Receiver, Sender}; use alloc::vec::Vec; use core::sync::atomic::Ordering; @@ -23,7 +23,7 @@ pub struct UdpSocket { impl UdpSocket { pub fn new() -> u16 { let interface = get_interface_mut(); - + // let (send_tx, send_rx) = channel::, SocketAddr)>(); let (recv_tx, recv_rx) = channel::, SocketAddr)>(); @@ -41,7 +41,9 @@ impl UdpSocket { let socketfd = NEXT_SOCKETFD.fetch_add(1, Ordering::SeqCst); // let mut sockets = interface.sockets.lock(); - interface.sockets.insert(socketfd, TaggedSocket::Udp(socket)); + interface + .sockets + .insert(socketfd, TaggedSocket::Udp(socket)); socketfd } From 2dceff6e002527142f4d0843c01656953e5a0e58 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Wed, 23 Apr 2025 01:03:42 -0500 Subject: [PATCH 06/13] USB HS Patches --- crates/kernel/scripts/run-usb.sh | 5 +- crates/kernel/scripts/run.sh | 2 +- crates/kernel/src/device/mailbox.rs | 2 +- crates/kernel/src/device/system_timer.rs | 4 +- crates/kernel/src/device/usb.rs | 6 - crates/kernel/src/device/usb/device.rs | 1 + .../kernel/src/device/usb/device/ax88179.rs | 1254 +++++++++++++++++ crates/kernel/src/device/usb/device/hid.rs | 26 +- crates/kernel/src/device/usb/device/net.rs | 125 +- crates/kernel/src/device/usb/device/rndis.rs | 24 + .../kernel/src/device/usb/hcd/dwc/dwc_otg.rs | 402 +++++- crates/kernel/src/device/usb/types.rs | 6 +- crates/kernel/src/device/usb/usbd/device.rs | 2 + crates/kernel/src/device/usb/usbd/endpoint.rs | 304 +++- crates/kernel/src/device/usb/usbd/request.rs | 21 + crates/kernel/src/device/usb/usbd/transfer.rs | 3 +- crates/kernel/src/device/usb/usbd/usbd.rs | 69 +- .../kernel/src/networking/iface/ethernet.rs | 2 +- 18 files changed, 2026 insertions(+), 232 deletions(-) create mode 100644 crates/kernel/src/device/usb/device/ax88179.rs diff --git a/crates/kernel/scripts/run-usb.sh b/crates/kernel/scripts/run-usb.sh index a556328d..c222948a 100755 --- a/crates/kernel/scripts/run-usb.sh +++ b/crates/kernel/scripts/run-usb.sh @@ -1,11 +1,10 @@ #!/usr/bin/env bash set -ex -# QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" -QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=udp::3333-:53 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev bridge,id=net0,br=br0 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-hub,id=hub1 -device usb-kbd -device usb-mouse" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse,pcap=usb-mouse.pcap -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" -# QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +# # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" diff --git a/crates/kernel/scripts/run.sh b/crates/kernel/scripts/run.sh index d0dab554..8a6f6df8 100755 --- a/crates/kernel/scripts/run.sh +++ b/crates/kernel/scripts/run.sh @@ -57,4 +57,4 @@ qemu-system-aarch64 \ # -device usb-net,netdev=net0 \ # -netdev user,id=net0,hostfwd=tcp::2222-:22 \ # -object filter-dump,id=f1,netdev=net0,file=net0.pcap \ -# -trace enable=net* \ +# -trace enable=net*\ diff --git a/crates/kernel/src/device/mailbox.rs b/crates/kernel/src/device/mailbox.rs index ec14d43d..cca1cedc 100644 --- a/crates/kernel/src/device/mailbox.rs +++ b/crates/kernel/src/device/mailbox.rs @@ -226,7 +226,7 @@ define_property!(0x00038009 => struct PropSetTurbo { #[derive(Debug)] pub struct MailboxError; -struct HexDisplay<'a, T>(&'a [T]); +pub struct HexDisplay<'a, T>(pub &'a [T]); impl core::fmt::LowerHex for HexDisplay<'_, T> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { diff --git a/crates/kernel/src/device/system_timer.rs b/crates/kernel/src/device/system_timer.rs index c670c340..da472c8c 100644 --- a/crates/kernel/src/device/system_timer.rs +++ b/crates/kernel/src/device/system_timer.rs @@ -357,14 +357,14 @@ pub struct ArmGenericTimer { } #[inline(always)] -unsafe fn read_cntpct() -> u64 { +pub unsafe fn read_cntpct() -> u64 { let cnt: u64; unsafe { asm!("mrs {}, cntpct_el0", out(reg) cnt, options(nomem, nostack, preserves_flags)) }; cnt } #[inline(always)] -unsafe fn read_cntfrq() -> u64 { +pub unsafe fn read_cntfrq() -> u64 { let cnt: u64; unsafe { asm!("mrs {}, cntfrq_el0", out(reg) cnt, options(nomem, nostack, preserves_flags)) }; cnt diff --git a/crates/kernel/src/device/usb.rs b/crates/kernel/src/device/usb.rs index a4a8a286..e1ea44fb 100644 --- a/crates/kernel/src/device/usb.rs +++ b/crates/kernel/src/device/usb.rs @@ -37,9 +37,3 @@ pub fn usb_check_for_change(_bus: &mut UsbBus) { pub fn usb_register_net_callback(callback: fn(*mut u8, u32)) { RegisterNetReceiveCallback(callback); } - -pub unsafe fn usb_send_packet(buffer: *mut u8, buffer_length: u32) { - unsafe { - NetSendPacket(buffer, buffer_length); - } -} diff --git a/crates/kernel/src/device/usb/device.rs b/crates/kernel/src/device/usb/device.rs index ea4cb766..48e17726 100644 --- a/crates/kernel/src/device/usb/device.rs +++ b/crates/kernel/src/device/usb/device.rs @@ -2,3 +2,4 @@ pub mod hid; pub mod hub; pub mod net; pub mod rndis; +pub mod ax88179; \ No newline at end of file diff --git a/crates/kernel/src/device/usb/device/ax88179.rs b/crates/kernel/src/device/usb/device/ax88179.rs new file mode 100644 index 00000000..5a52f72f --- /dev/null +++ b/crates/kernel/src/device/usb/device/ax88179.rs @@ -0,0 +1,1254 @@ +use core::result; + +use crate::device::system_timer::micro_delay; +use crate::device::usb::hcd::dwc::dwc_otg::ms_to_micro; +use crate::device::usb::types::*; +use crate::device::usb::usbd::device::*; +use crate::device::usb::usbd::pipe::*; +use crate::device::usb::usbd::request::*; +use crate::device::usb::usbd::usbd::UsbSendBulkMessage; +use crate::device::usb::UsbControlMessage; +use crate::device::usb::usbd::endpoint::UsbEndpointDevice; +use crate::device::usb::device::net::*; +use crate::device::usb::PacketId; +use alloc::boxed::Box; +use alloc::vec; + +/** + * + * usb/device/ax88179.rs + * By Aaron Lo + * Based off the freeBSD driver if_axge.c + */ +//https://elixir.bootlin.com/freebsd/v14.2/source/sys/dev/usb/net/if_axge.c + +const MAC_ADDRESS: [u8; 6] = [0x54, 0x52, 0x00, 0x12, 0x34, 0x56]; // TODO: TBD / make this dynamic + +pub unsafe fn axge_send_packet( + device: &mut UsbDevice, + buffer: *mut u8, + buffer_length: u32, +) -> ResultCode { + let size = 8 + buffer_length; + + let mut buf = vec![0u8; size as usize]; + + let mut tx_hdr1 = buffer_length as u32; + let mut tx_hdr2 = 0u32; + + // if (tx_hdr1 //don't need padding + let b1 = tx_hdr1.to_le_bytes(); + let b2 = tx_hdr2.to_le_bytes(); + buf[0..4].copy_from_slice(&b1); + buf[4..8].copy_from_slice(&b2); + + + unsafe { + core::ptr::copy_nonoverlapping(buffer, buf.as_mut_ptr().add(8), buffer_length as usize); + } + + let endpoint_device = device.driver_data.downcast::().unwrap(); + let pid = if endpoint_device.endpoint_pid[1] % 2 == 0 { + PacketId::Data0 + } else { + PacketId::Data1 + }; + + endpoint_device.endpoint_pid[1] += 1; + + let result = unsafe { + UsbSendBulkMessage( + device, + UsbPipeAddress { + transfer_type: UsbTransfer::Bulk, + speed: device.speed, + end_point: 3, //TODO: check this + device: device.number as u8, + direction: UsbDirection::Out, + max_size: size_from_number(512 as u32), + _reserved: 0, + }, + buf.into_boxed_slice(), + size, + pid, + 1, //TODO: Check this + 10 + ) + }; + + if result != ResultCode::OK { + print!("| AXGE: Failed to send packet.\n"); + return result; + } + return result; +} + +pub unsafe fn axge_receive_packet( + device: &mut UsbDevice, + buffer: Box<[u8]>, + buffer_length: u32, +) -> ResultCode { + // println!("| AXGE: Receiving packet"); + let endpoint_device = device.driver_data.downcast::().unwrap(); + let pid = if endpoint_device.endpoint_pid[2] % 2 == 0 { + PacketId::Data0 + } else { + PacketId::Data1 + }; + + endpoint_device.endpoint_pid[2] += 1; + + let result = unsafe { + UsbSendBulkMessage( + device, + UsbPipeAddress { + transfer_type: UsbTransfer::Bulk, + speed: device.speed, + end_point: 2, + device: device.number as u8, + direction: UsbDirection::In, + max_size: size_from_number(512), + _reserved: 0, + }, + buffer, + buffer_length, + pid, + 2, //TODOI: check this + 10, + ) + }; + + if result != ResultCode::OK { + print!("| RNDIS: Failed to receive packet message.\n"); + return result; + } + + // return 4; + return ResultCode::OK; +} + +pub fn axge_init(device: &mut UsbDevice) -> ResultCode { + + axge_stop(device); + + axge_reset(device); + + println!("| AXGE: Initializing device"); + axge_write_mem(device, AXGE_ACCESS_MAC, ETHER_ADDR_LEN as u16, AXGE_NIDR as u16, + MAC_ADDRESS.as_mut_ptr(), ETHER_ADDR_LEN as u32); + + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_PWLLR, 0x34); + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_PWLHR, 0x52); + + axge_csum_cfg(device); + axge_rxfilter(device); + + /* + * XXX + * Controller supports wakeup on link change detection, + * magic packet and wakeup frame recpetion. But it seems + * there is no framework for USB ethernet suspend/wakeup. + * Disable all wakeup functions. + */ + println!("| AXGE: Disabling wakeup functions"); + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_MMSR as u16, 0); + axge_read_cmd_1(device, AXGE_ACCESS_MAC, AXGE_MMSR as u16); + + /* Configure default medium type. */ + println!("| AXGE: Configuring default medium type"); + axge_write_cmd_2(device, AXGE_ACCESS_MAC, 2, AXGE_MSR, MSR_GM | MSR_FD | + MSR_RFC | MSR_TFC | MSR_RE); + + // usbd_xfer_set_stall(sc->sc_xfer[AXGE_BULK_DT_WR]); + + // if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); + // /* Switch to selected media. */ + // axge_ifmedia_upd(ifp); + // TODO: This is reseting the phy -> need to look into if thigns go wrong WARNING + //This is my attempt at htis from gpt code -> no clue if it works + + //issue phy reset + // ax88179_led_setting(device); + + println!("| AXGE: Resetting PHY"); + // axge_write_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR, BMCR_RESET); + + // let mut val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR); + // while val & BMCR_RESET != 0 { + // micro_delay(ms_to_micro(10)); + // val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR); + // } + + // axge_write_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR, BMCR_RESET); + + + // let mut val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR); + // while val & BMCR_RESET != 0 { + // micro_delay(ms_to_micro(10)); + // val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR); + // } + + // let mut reg = BMCR_RESET; + + // axge_miibus_writereg(device, 3, MII_BMCR, reg); + + // //wait 100 ms for it t ocomplete + // for _ in 0..100 { + // reg = axge_miibus_readreg(device, 3, MII_BMCR); + // if reg & BMCR_RESET == 0 { + // break; + // } + // micro_delay(1000); + // } + + // reg &= !(BMCR_PDOWN | BMCR_ISO); + // if axge_miibus_readreg(device, 3, MII_BMCR) != reg { + // axge_miibus_writereg(device, 3, MII_BMCR, reg); + // } + // micro_delay(ms_to_micro(1000)); + ax88179_reset(device); + println!("| AXGE: PHY reset complete"); + + let mut rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE) | AX_RX_CTL_PRO; + ax88179_write_cmd(device, AX_ACCESS_MAC, AX_RX_CTL, + 2, 2, &mut rxctl as *mut u16 as *mut u8); + + println!("| AXGE: multicast mode set"); + + // ax88179_link_reset(device); + // println!("| AXGE: Link reset complete"); + + return ResultCode::OK; +} + +//cmd -> cmd +// +pub fn ax88179_led_setting(device: &mut UsbDevice) { + let mut tmp = GMII_PHY_PGSEL_EXT; + println!("| AXGE: Setting LED settings"); + // ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + // GMII_PHY_PAGE_SELECT, 2, &tmp); + axge_write_cmd_2(device, AXGE_ACCESS_PHY, GMII_PHY_PGSEL_EXT,3, tmp); + tmp = 0x2c; + + axge_write_cmd_2(device, AXGE_ACCESS_PHY, GMII_PHYPAGE as u16, 3, tmp); + + let mut ledact = axge_read_cmd_2(device, AXGE_ACCESS_PHY, GMII_LED_ACT as u16, 3); + let mut ledlink = axge_read_cmd_2(device, AXGE_ACCESS_PHY, GMII_LED_LINK as u16, 3); + + ledact &= GMII_LED_ACTIVE_MASK; + ledlink &= GMII_LED_LINK_MASK; + + ledact |= GMII_LED0_ACTIVE | GMII_LED1_ACTIVE | GMII_LED2_ACTIVE; + ledlink |= GMII_LED0_LINK_10 | GMII_LED1_LINK_100 | GMII_LED2_LINK_1000; + + axge_write_cmd_2(device, AXGE_ACCESS_PHY, GMII_LED_ACT as u16, 3, ledact); + axge_write_cmd_2(device, AXGE_ACCESS_PHY, GMII_LED_LINK as u16, 3, ledlink); + + tmp = GMII_PHY_PGSEL_PAGE0; + + axge_write_cmd_2(device, AXGE_ACCESS_PHY, GMII_PHY_PAGE_SELECT as u16, 3, tmp); + + let ledfd = 0x10 | 0x04 | 0x01; + axge_write_cmd_1(device, AXGE_ACCESS_MAC, 0x73, ledfd); + + println!("| AXGE: LED settings complete"); +} + + +pub fn axge_miibus_readreg(device: &mut UsbDevice, phy: u16, reg: u16) -> u16 { + let val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, reg, phy); + return val; +} + +pub fn axge_miibus_writereg(device: &mut UsbDevice, phy: u16, reg: u16, val: u16) { + axge_write_cmd_2(device, AXGE_ACCESS_PHY, reg, phy, val); +} + +pub fn axge_csum_cfg(device: &mut UsbDevice) { + // Enable checksum offload + println!("| AXGE: Enabling checksum offload"); + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_CRCR as u16, CRCR_IP | CRCR_TCP | CRCR_UDP); + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_CTCR as u16, CRCR_IP | CRCR_TCP | CRCR_UDP); +} + +pub fn axge_rxfilter(debice: &mut UsbDevice) { + println!("| AXGE: Setting RX filter"); + // let mut rxmode = RCR_DROP_CRCERR | RCR_START | RCR_ACPT_BCAST | RCR_ACPT_ALL_MCAST; + let rxmode = RCR_START | RCR_ACPT_BCAST | RCR_ACPT_ALL_MCAST; + axge_write_cmd_2(debice, AXGE_ACCESS_MAC, 2, AXGE_RCR as u16, rxmode); +} + +pub fn axge_chip_init(device: &mut UsbDevice) { + + //power up ethernet phy + axge_write_cmd_2(device, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, 0); + axge_write_cmd_2(device, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, EPPRCR_IPRL); + + micro_delay(ms_to_micro(250)); + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_CLK_SELECT as u16, AXGE_CLK_SELECT_ACS | AXGE_CLK_SELECT_BCS); + micro_delay(ms_to_micro(100)); + + axge_write_cmd_1(device, AXGE_FW_MODE, AXGE_FW_MODE_178A179, 0); +} + +pub fn axge_reset(device: &mut UsbDevice) { + //ignore the usbd_req_set_config for now + println!("| AXGE: Resetting device"); + micro_delay(ms_to_micro(10)); + axge_chip_init(device); +} + +pub fn axge_stop(device: &mut UsbDevice) { + println!("| AXGE: Stopping device"); + let mut val = axge_read_cmd_2(device, AXGE_ACCESS_MAC as u8, 2, AXGE_MSR as u16); + val &= !MSR_RE; + axge_write_cmd_2(device, AXGE_ACCESS_MAC, 2, AXGE_MSR as u16, val); +} + +fn axge_read_cmd_1(device: &mut UsbDevice, cmd: u8, reg: u16) -> u8 { + let val: u8 = 0; + axge_read_mem(device, cmd, 1, reg, &val as *const u8 as *mut u8, 1); + return val; +} + +fn axge_read_cmd_2(device: &mut UsbDevice, cmd: u8, index: u16, reg: u16) -> u16 { + let val: u16 = 0; + + axge_read_mem(device, cmd, index, reg, &val as *const u16 as *mut u8, 2); + + return val; +} + +fn axge_write_cmd_1(device: &mut UsbDevice, cmd: u8, reg: u16, val: u8) { + axge_write_mem(device, cmd, 1, reg, &val as *const u8 as *mut u8, 1); +} + +fn axge_write_cmd_2(device: &mut UsbDevice, cmd: u8, index: u16, reg: u16, val: u16) { + axge_write_mem(device, cmd, index, reg, &val as *const u16 as *mut u8, 2); +} + +fn axge_read_mem(device: &mut UsbDevice, cmd: u8, index: u16, val: u16, buf: *mut u8, len: u32) -> ResultCode { + + let result = unsafe { + UsbControlMessage( + device, + UsbPipeAddress { + transfer_type: UsbTransfer::Control, + speed: device.speed, + end_point: 0, + device: device.number as u8, + direction: UsbDirection::In, + max_size: size_from_number(device.descriptor.max_packet_size0 as u32), + _reserved: 0, + }, + buf, + len, + &mut UsbDeviceRequest { + request_type: 0xC0, + request: command_to_usb_device_request(cmd), + index: index as u16, + value: val as u16, + length: len as u16, + }, + 1000, // timeout + ) + }; + + if result != ResultCode::OK { + print!("| AXGE: Failed to read memory.\n"); + return result; + } + + return ResultCode::OK; +} + + +fn axge_write_mem(device: &mut UsbDevice, cmd: u8, index: u16, val: u16, buf: *mut u8, len: u32) -> ResultCode { + + let result = unsafe { + UsbControlMessage( + device, + UsbPipeAddress { + transfer_type: UsbTransfer::Control, + speed: device.speed, + end_point: 0, + device: device.number as u8, + direction: UsbDirection::Out, + max_size: size_from_number(device.descriptor.max_packet_size0 as u32), + _reserved: 0, + }, + buf, + len, + &mut UsbDeviceRequest { + request_type: 0x40, + request: command_to_usb_device_request(cmd), + index: index as u16, + value: val as u16, + length: len as u16, + }, + 1000, // timeout + ) + }; + + if result != ResultCode::OK { + print!("| AXGE: Failed to write memory.\n"); + return result; + } + + return ResultCode::OK; +} + +pub fn ax88179_auto_detach(dev: &mut UsbDevice) { + let mut tmp16: u16 = 0; + let mut tmp8: u8 = 0; + + // if ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &mut tmp16 as *mut u16 as *mut u8) < 0 { + // return; + // } + + if ((tmp16 == 0xFFFF) || ((tmp16 & 0x0100) == 0)) { + return; + } + unsafe { + /* Enable Auto Detach bit */ + tmp8 = 0; + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT as u16, 1, 1, &mut tmp8 as *mut u8); + tmp8 |= AX_CLK_SELECT_ULR; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT as u16, 1, 1, &mut tmp8 as *mut u8); + + ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL as u16, 2, 2, &mut tmp16 as *mut u16 as *mut u8); + tmp16 |= AX_PHYPWR_RSTCTL_AT; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL as u16, 2, 2, &mut tmp16 as *mut u16 as *mut u8); + } +} + +pub fn ax88179_reset(dev: &mut UsbDevice) { + + let mut buf = [0u8; 6]; + let mut tmp16 = buf.as_mut_ptr() as *mut u16; + let mut tmp = buf.as_mut_ptr() as *mut u8; + + + + /* Power up ethernet PHY */ + unsafe { + *tmp16 = 0; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL as u16, 2, 2, tmp16 as *mut u8); + + *tmp16 = AX_PHYPWR_RSTCTL_IPRL; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL as u16, 2, 2, tmp16 as *mut u8); + micro_delay(500); + + *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT as u16, 1, 1, tmp); + micro_delay(200); + + /* Ethernet PHY Auto Detach*/ + ax88179_auto_detach(dev); + + /* Read MAC address from DTB or asix chip */ + // ax88179_get_mac_addr(dev); + // memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID as u16, 6, 6, + unsafe { MAC_ADDRESS.as_mut_ptr() }); + + /* RX bulk configuration */ + // memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); + let mut buf_tmp:[u8; 5] = [7, 0x4f, 0, 0x12, 0xff]; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL as u16, 5, 5, buf_tmp.as_mut_ptr()); + + // dev->rx_urb_size = 1024 * 20; + + *tmp = 0x34; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW as u16, 1, 1, tmp); + + *tmp = 0x52; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH as u16, + 1, 1, tmp); + + /* Enable checksum offload */ + *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | + AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL as u16, 1, 1, tmp); + + *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | + AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL as u16, 1, 1, tmp); + + /* Configure RX control register => start operation */ + // *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | + // AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; + *tmp16 = AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE | + AX_RX_CTL_PRO | AX_RX_CTL_AMALL | AX_RX_CTL_AP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL as u16, 2, 2, tmp16 as *mut u8); + + *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | + AX_MONITOR_MODE_RWMP; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD as u16, 1, 1, tmp); + + /* Configure default medium type => giga */ + *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | + AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX | + AX_MEDIUM_GIGAMODE; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE as u16, 2, 2, tmp16 as *mut u8); + } + + ax88179_disable_eee(dev); + ax88179_ethtool(dev); + mii_nway_restart(dev); + +} + + +pub fn ax88179_link_reset(dev: &mut UsbDevice) { + println!("| AX88179: Resetting link"); + let mut tmp32: u32 = 0x40000000; + + use crate::sync::get_time; + let timeout = get_time() / 1000 + 100; + let mut mode: u16 = 0; + while tmp32 & 0x40000000 != 0{ + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mut mode as *mut u16 as *mut u8); + + let mut temporary: u16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | + AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mut temporary as *mut u16 as *mut u8); + + /* link up, check the usb device control TX FIFO full or empty*/ + + /*link up, check the usb device control TX FIFO full or empty*/ + ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &mut tmp32 as *mut u32 as *mut u8); + + if get_time() / 1000 > timeout { + println!("| AX88179: Link reset timeout"); + break; + } + } + + let mut link_sts: u8 = 0; + let mut tmp16: u16 = 0; + + mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | + AX_MEDIUM_RXFLOW_CTRLEN; + + ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS as u16, + 1, 1, &mut link_sts as *mut u8); + + ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + GMII_PHY_PHYSR, 2, &mut tmp16 as *mut u16 as *mut u8); + + if (tmp16 & GMII_PHY_PHYSR_FULL) != 0 { + mode |= AX_MEDIUM_FULL_DUPLEX; + } + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE as u16, + 2, 2, &mut mode as *mut u16 as *mut u8); +} + +pub fn ax88179_disable_eee(dev: &mut UsbDevice) { + println!("| AX88179: Disabling EEE"); + let mut tmp16 = GMII_PHY_PGSEL_PAGE3; + unsafe { + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID as u16, + GMII_PHY_PAGE_SELECT, 2, &mut tmp16 as *mut u16 as *mut u8); + + tmp16 = 0x3246; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_PHYADDR, 2, &mut tmp16 as *mut u16 as *mut u8); + + tmp16 = GMII_PHY_PGSEL_PAGE0; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + GMII_PHY_PAGE_SELECT, 2, &mut tmp16 as *mut u16 as *mut u8); + } +} + +pub fn mii_nway_restart(dev: &mut UsbDevice) { + println!("| AX88179: Restarting MII"); + let mut bmcr = ax88179_mdio_read(dev, MII_BMCR); + println!("| AX88179: BMCR: {:#x}", bmcr); + if bmcr & 0x1000 == 0 { + bmcr |= 0x0200; + ax88179_mdio_write(dev, MII_BMCR, bmcr); + } +} + +pub fn ax88179_ethtool(dev: &mut UsbDevice) { + println!("| AX88179: Setting ethtool settings"); + + let val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV, + MDIO_MMD_AN); + + let mut adv = 0; + if val & MDIO_EEE_100TX != 0 { + adv |= MDIO_EEE_100TX;//1 << ETHTOOL_LINK_MODE_100baseT_Full_BIT; + } + + if val & MDIO_EEE_1000T != 0 { + adv |= MDIO_EEE_1000T;//1 << ETHTOOL_LINK_MODE_1000baseT_Full_BIT; + } + + if val & MDIO_EEE_10GT != 0 { + adv |= MDIO_EEE_10GT;//1 << ETHTOOL_LINK_MODE_10000baseT_Full_BIT; + } + + if val & MDIO_EEE_1000KX != 0 { + adv |= MDIO_EEE_1000KX;//1 << ETHTOOL_LINK_MODE_1000baseKX_Full_BIT; + } + + if val & MDIO_EEE_10GKX4 != 0 { + adv |= MDIO_EEE_10GKX4;//1 << ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT; + } + + if val & MDIO_EEE_10GKR != 0 { + adv |= MDIO_EEE_10GKR;//1 << ETHTOOL_LINK_MODE_10000baseKR_Full_BIT; + } + + ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV, + MDIO_MMD_AN, adv); + +} + +pub fn ax88179_phy_write_mmd_indirect(dev: &mut UsbDevice, prtad: u16, devad: u16, data: u16) +{ + ax88179_phy_mmd_indirect(dev, prtad, devad); + let mut tmp16 = data; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_DATA, 2, &mut tmp16 as *mut u16 as *mut u8); +} + + +pub fn ax88179_phy_read_mmd_indirect(dev: &mut UsbDevice, prtad: u16, devad: u16) -> u16 { + ax88179_phy_mmd_indirect(dev, prtad, devad); + let mut tmp16: u16 = 0; + ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_DATA, 2, &mut tmp16 as *mut u16 as *mut u8); + + return tmp16; +} + +pub fn ax88179_phy_mmd_indirect(dev: &mut UsbDevice, prtad: u16, devad: u16) { + let mut tmp16 = devad; + + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_CTRL, 2, &mut tmp16 as *mut u16 as *mut u8); + + tmp16 = prtad; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_DATA, 2, &mut tmp16 as *mut u16 as *mut u8); + + tmp16 = devad | MII_MMD_CTRL_NOINCR; + ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, + MII_MMD_CTRL, 2, &mut tmp16 as *mut u16 as *mut u8); +} + +pub fn ax88179_mdio_read(dev: &mut UsbDevice, loc: u16) -> u16 { + let mut tmp16: u16 = 0; + + // Read MDIO register + ax88179_read_cmd(dev, AXGE_ACCESS_PHY, 3, loc, 2, &mut tmp16 as *mut u16 as *mut u8); + return tmp16; +} + +pub fn ax88179_mdio_write(dev: &mut UsbDevice, loc: u16, val: u16) { + let mut tmp16: u16 = val; + ax88179_write_cmd(dev, AXGE_ACCESS_PHY, 3, loc, 2, &mut tmp16 as *mut u16 as *mut u8); +} + +pub fn ax88179_read_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, size: u16, data: *mut u8) { + if size == 2 { + let mut buf: u16 = 0; + __ax88179_read_cmd(device, cmd, value, index, size, &buf as *const u16 as *mut u8); + buf.to_le_bytes(); + unsafe { + *(data as *mut u16) = buf; + } + + } else if size == 4 { + let mut buf: u32 = 0; + __ax88179_read_cmd(device, cmd, value, index, size, &buf as *const u32 as *mut u8); + buf.to_le_bytes(); + unsafe { + *(data as *mut u32) = buf; + } + } else { + __ax88179_read_cmd(device, cmd, value, index, size, data); + } +} + +pub fn ax88179_write_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, size: u16, data: *mut u8) { + if size == 2 { + let mut buf: u16; + buf = unsafe { core::ptr::read(data as *const u16) }; + buf.to_le_bytes(); + + __ax88179_write_cmd(device, cmd, value, index, size, &buf as *const u16 as *mut u8); + } else { + __ax88179_write_cmd(device, cmd, value, index, size, data); + } +} + +pub fn __ax88179_read_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, size: u16, data: *mut u8) -> ResultCode { + let result = unsafe { + UsbControlMessage( + device, + UsbPipeAddress { + transfer_type: UsbTransfer::Control, + speed: device.speed, + end_point: 0, + device: device.number as u8, + direction: UsbDirection::In, + max_size: size_from_number(device.descriptor.max_packet_size0 as u32), + _reserved: 0, + }, + data, + size as u32, + &mut UsbDeviceRequest { + request_type: 0xC0, + request: command_to_usb_device_request(cmd), + index: index as u16, + value: value as u16, + length: size as u16, + }, + 1000, // timeout + ) + }; + + if result != ResultCode::OK { + print!("| AXGE: Failed to read command.\n"); + return result; + } + + return result; +} + +pub fn __ax88179_write_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, size: u16, data: *mut u8) -> ResultCode { + let result = unsafe { + UsbControlMessage( + device, + UsbPipeAddress { + transfer_type: UsbTransfer::Control, + speed: device.speed, + end_point: 0, + device: device.number as u8, + direction: UsbDirection::Out, + max_size: size_from_number(device.descriptor.max_packet_size0 as u32), + _reserved: 0, + }, + data, + size as u32, + &mut UsbDeviceRequest { + request_type: 0x40, + request: command_to_usb_device_request(cmd), + index: index as u16, + value: value as u16, + length: size as u16, + }, + 1000, // timeout + ) + }; + + if result != ResultCode::OK { + print!("| AXGE: Failed to write command.\n"); + return result; + } + + return result; +} + + +// MDIO Manageable Devices (MMDs) +pub const MDIO_MMD_PMAPMD: u16 = 1; // Physical Medium Attachment / Physical Medium Dependent +pub const MDIO_MMD_WIS: u16 = 2; // WAN Interface Sublayer +pub const MDIO_MMD_PCS: u16 = 3; // Physical Coding Sublayer +pub const MDIO_MMD_PHYXS: u16 = 4; // PHY Extender Sublayer +pub const MDIO_MMD_DTEXS: u16 = 5; // DTE Extender Sublayer +pub const MDIO_MMD_TC: u16 = 6; // Transmission Convergence +pub const MDIO_MMD_AN: u16 = 7; // Auto-Negotiation +pub const MDIO_MMD_POWER_UNIT: u16 = 13; // PHY Power Unit +pub const MDIO_MMD_C22EXT: u16 = 29; // Clause 22 extension +pub const MDIO_MMD_VEND1: u16 = 30; // Vendor specific 1 +pub const MDIO_MMD_VEND2: u16 = 31; // Vendor specific 2 + +// Generic MII register addresses +pub const MII_BMCR: u16 = 0x00; // Basic mode control register +pub const MII_BMSR: u16 = 0x01; // Basic mode status register +pub const MII_PHYSID1: u16 = 0x02; // PHYS ID 1 +pub const MII_PHYSID2: u16 = 0x03; // PHYS ID 2 +pub const MII_ADVERTISE: u16 = 0x04; // Advertisement control register +pub const MII_LPA: u16 = 0x05; // Link partner ability register +pub const MII_EXPANSION: u16 = 0x06; // Expansion register +pub const MII_CTRL1000: u16 = 0x09; // 1000BASE-T control +pub const MII_STAT1000: u16 = 0x0a; // 1000BASE-T status +pub const MII_MMD_CTRL: u16 = 0x0d; // MMD Access Control Register +pub const MII_MMD_DATA: u16 = 0x0e; // MMD Access Data Register +pub const MII_ESTATUS: u16 = 0x0f; // Extended Status +pub const MII_DCOUNTER: u16 = 0x12; // Disconnect counter +pub const MII_FCSCOUNTER: u16 = 0x13; // False carrier counter +pub const MII_NWAYTEST: u16 = 0x14; // N-way auto-negotiation test register +pub const MII_RERRCOUNTER: u16 = 0x15; // Receive error counter +pub const MII_SREVISION: u16 = 0x16; // Silicon revision +pub const MII_RESV1: u16 = 0x17; // Reserved +pub const MII_LBRERROR: u16 = 0x18; // Loopback, receive, bypass error +pub const MII_PHYADDR: u16 = 0x19; // PHY address +pub const MII_RESV2: u16 = 0x1a; // Reserved +pub const MII_TPISTATUS: u16 = 0x1b; // TPI status for 10 Mbps +pub const MII_NCONFIG: u16 = 0x1c; // Network interface config + +// Basic Mode Control Register (BMCR) bitfields +pub const BMCR_RESV: u16 = 0x003f; // Unused +pub const BMCR_SPEED1000: u16 = 0x0040; // MSB of speed (1000 Mbps) +pub const BMCR_CTST: u16 = 0x0080; // Collision test +pub const BMCR_FULLDPLX: u16 = 0x0100; // Full duplex +pub const BMCR_ANRESTART: u16 = 0x0200; // Auto-negotiation restart +pub const BMCR_ISOLATE: u16 = 0x0400; // Isolate data paths from MII +pub const BMCR_PDOWN: u16 = 0x0800; // Power down +pub const BMCR_ANENABLE: u16 = 0x1000; // Enable auto-negotiation +pub const BMCR_SPEED100: u16 = 0x2000; // Select 100 Mbps +pub const BMCR_LOOPBACK: u16 = 0x4000; // TXD loopback +pub const BMCR_RESET: u16 = 0x8000; // Reset to default +pub const BMCR_SPEED10: u16 = 0x0000; // Select 10 Mbps + +// MMD Access Control register fields +pub const MII_MMD_CTRL_DEVAD_MASK: u16 = 0x001f; // Mask MMD DEVAD +pub const MII_MMD_CTRL_ADDR: u16 = 0x0000; // Address +pub const MII_MMD_CTRL_NOINCR: u16 = 0x4000; // No post increment +pub const MII_MMD_CTRL_INCR_RDWT: u16 = 0x8000; // Post increment on reads & writes +pub const MII_MMD_CTRL_INCR_ON_WT: u16 = 0xC000; // Post increment on writes only + +// Generic MDIO register mappings (all as u16) +pub const MDIO_CTRL1: u16 = MII_BMCR as u16; // Basic Mode Control Register +pub const MDIO_STAT1: u16 = MII_BMSR as u16; // Basic Mode Status Register +pub const MDIO_DEVID1: u16 = MII_PHYSID1 as u16; // Device Identifier 1 +pub const MDIO_DEVID2: u16 = MII_PHYSID2 as u16; // Device Identifier 2 + +pub const MDIO_SPEED: u16 = 4; // Speed ability +pub const MDIO_DEVS1: u16 = 5; // Devices in package +pub const MDIO_DEVS2: u16 = 6; +pub const MDIO_CTRL2: u16 = 7; // 10G control 2 +pub const MDIO_STAT2: u16 = 8; // 10G status 2 +pub const MDIO_PMA_TXDIS: u16 = 9; // 10G PMA/PMD transmit disable +pub const MDIO_PMA_RXDET: u16 = 10; // 10G PMA/PMD receive signal detect +pub const MDIO_PMA_EXTABLE: u16 = 11; // 10G PMA/PMD extended ability +pub const MDIO_PKGID1: u16 = 14; // Package identifier 1 +pub const MDIO_PKGID2: u16 = 15; // Package identifier 2 + +// Auto-Negotiation (AN) related +pub const MDIO_AN_ADVERTISE: u16 = 16; // Auto-Negotiation advertisement (base page) +pub const MDIO_AN_LPA: u16 = 19; // Auto-Negotiation link partner ability (base page) +pub const MDIO_PCS_EEE_ABLE: u16 = 20; // EEE Capability register +pub const MDIO_PCS_EEE_ABLE2: u16 = 21; // EEE Capability register 2 +pub const MDIO_PMA_NG_EXTABLE: u16 = 21; // 2.5G/5G PMA/PMD extended ability +pub const MDIO_PCS_EEE_WK_ERR: u16 = 22; // EEE wake error counter +pub const MDIO_PHYXS_LNSTAT: u16 = 24; // PHY XGXS lane state + +pub const MDIO_AN_EEE_ADV: u16 = 60; // EEE advertisement +pub const MDIO_AN_EEE_LPABLE: u16 = 61; // EEE link partner ability +pub const MDIO_AN_EEE_ADV2: u16 = 62; // EEE advertisement 2 +pub const MDIO_AN_EEE_LPABLE2: u16 = 63; // EEE link partner ability 2 + +pub const MDIO_AN_CTRL2: u16 = 64; // Auto-Negotiation THP bypass request control + +// EEE Supported / Advertisement / Link Partner Advertisement registers +// (same bit masks used across multiple registers) + +// Old (user-visible) names +pub const MDIO_AN_EEE_ADV_100TX: u16 = 0x0002; // Advertise 100TX EEE cap +pub const MDIO_AN_EEE_ADV_1000T: u16 = 0x0004; // Advertise 1000T EEE cap + +// New generic names (aliasing old names) +pub const MDIO_EEE_100TX: u16 = MDIO_AN_EEE_ADV_100TX; // 100TX EEE cap +pub const MDIO_EEE_1000T: u16 = MDIO_AN_EEE_ADV_1000T; // 1000T EEE cap + +// Other EEE capabilities +pub const MDIO_EEE_10GT: u16 = 0x0008; // 10GBASE-T EEE cap +pub const MDIO_EEE_1000KX: u16 = 0x0010; // 1000BASE-KX EEE cap +pub const MDIO_EEE_10GKX4: u16 = 0x0020; // 10GBASE-KX4 EEE cap +pub const MDIO_EEE_10GKR: u16 = 0x0040; // 10GBASE-KR EEE cap +pub const MDIO_EEE_40GR_FW: u16 = 0x0100; // 40GBASE-R fast wake +pub const MDIO_EEE_40GR_DS: u16 = 0x0200; // 40GBASE-R deep sleep +pub const MDIO_EEE_100GR_FW: u16 = 0x1000; // 100GBASE-R fast wake +pub const MDIO_EEE_100GR_DS: u16 = 0x2000; // 100GBASE-R deep sleep + +// Ethtool Link Mode Bit Positions +pub const ETHTOOL_LINK_MODE_10baseT_Half_BIT: u32 = 0; +pub const ETHTOOL_LINK_MODE_10baseT_Full_BIT: u32 = 1; +pub const ETHTOOL_LINK_MODE_100baseT_Half_BIT: u32 = 2; +pub const ETHTOOL_LINK_MODE_100baseT_Full_BIT: u32 = 3; +pub const ETHTOOL_LINK_MODE_1000baseT_Half_BIT: u32 = 4; +pub const ETHTOOL_LINK_MODE_1000baseT_Full_BIT: u32 = 5; +pub const ETHTOOL_LINK_MODE_Autoneg_BIT: u32 = 6; +pub const ETHTOOL_LINK_MODE_TP_BIT: u32 = 7; +pub const ETHTOOL_LINK_MODE_AUI_BIT: u32 = 8; +pub const ETHTOOL_LINK_MODE_MII_BIT: u32 = 9; +pub const ETHTOOL_LINK_MODE_FIBRE_BIT: u32 = 10; +pub const ETHTOOL_LINK_MODE_BNC_BIT: u32 = 11; +pub const ETHTOOL_LINK_MODE_10000baseT_Full_BIT: u32 = 12; +pub const ETHTOOL_LINK_MODE_Pause_BIT: u32 = 13; +pub const ETHTOOL_LINK_MODE_Asym_Pause_BIT: u32 = 14; +pub const ETHTOOL_LINK_MODE_2500baseX_Full_BIT: u32 = 15; +pub const ETHTOOL_LINK_MODE_Backplane_BIT: u32 = 16; +pub const ETHTOOL_LINK_MODE_1000baseKX_Full_BIT: u32 = 17; +pub const ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT: u32 = 18; +pub const ETHTOOL_LINK_MODE_10000baseKR_Full_BIT: u32 = 19; +pub const ETHTOOL_LINK_MODE_10000baseR_FEC_BIT: u32 = 20; +pub const ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT: u32 = 21; +pub const ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT: u32 = 22; +pub const ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT: u32 = 23; +pub const ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT: u32 = 24; +pub const ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT: u32 = 25; +pub const ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT: u32 = 26; +pub const ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT: u32 = 27; +pub const ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT: u32 = 28; +pub const ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT: u32 = 29; +pub const ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT: u32 = 30; +pub const ETHTOOL_LINK_MODE_25000baseCR_Full_BIT: u32 = 31; + + +// GMII PHY Specific Status Register (PHYSR) +pub const GMII_PHY_PHYSR: u16 = 0x11; + +pub const GMII_PHY_PHYSR_SMASK: u16 = 0xc000; // Speed mask +pub const GMII_PHY_PHYSR_GIGA: u16 = 0x8000; // 1000 Mbps +pub const GMII_PHY_PHYSR_100: u16 = 0x4000; // 100 Mbps +pub const GMII_PHY_PHYSR_FULL: u16 = 0x2000; // Full duplex +pub const GMII_PHY_PHYSR_LINK: u16 = 0x0400; // Link up + + +// pub const BMCR_RESET: u16 = 0x8000; +pub const BMCR_LOOP: u16 = 0x4000; +pub const BMCR_SPEED0: u16 = 0x2000; +pub const BMCR_AUTOEN: u16 = 0x1000; +// pub const BMCR_PDOWN: u16 = 0x0800; +pub const BMCR_ISO: u16 = 0x0400; +pub const BMCR_STARTNEG: u16 = 0x0200; +pub const BMCR_FDX: u16 = 0x0100; +pub const BMCR_CTEST: u16 = 0x0080; +pub const BMCR_SPEED1: u16 = 0x0040; + + +pub const PHY_BMCR: u16 = 0x00; // Basic Mode Control Register + +// Length of an Ethernet address +pub const ETHER_ADDR_LEN: u8 = 6; + +// Length of the Ethernet type field +pub const ETHER_TYPE_LEN: u8 = 2; + +// Length of the Ethernet CRC +pub const ETHER_CRC_LEN: u8 = 4; + +// Ethernet header length: destination + source addresses + type +pub const ETHER_HDR_LEN: u8 = ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN; + +// Minimum frame length, including CRC +pub const ETHER_MIN_LEN: u16 = 64; + +// Maximum frame length, including CRC +pub const ETHER_MAX_LEN: u16 = 1518; + +// Maximum jumbo frame length, including CRC +pub const ETHER_MAX_LEN_JUMBO: u16 = 9018; + +// Length of 802.1Q VLAN encapsulation +pub const ETHER_VLAN_ENCAP_LEN: u8 = 4; + +// Mbuf adjust factor to force 32-bit alignment of IP header +pub const ETHER_ALIGN: u8 = 2; + + +// Access Registers +pub const AXGE_ACCESS_MAC: u8 = 0x01; +pub const AXGE_ACCESS_PHY: u8 = 0x02; +pub const AXGE_ACCESS_WAKEUP: u8 = 0x03; +pub const AXGE_ACCESS_EEPROM: u8 = 0x04; +pub const AXGE_ACCESS_EFUSE: u8 = 0x05; +pub const AXGE_RELOAD_EEPROM_EFUSE: u8 = 0x06; +pub const AXGE_FW_MODE: u8 = 0x08; +pub const AXGE_WRITE_EFUSE_EN: u8 = 0x09; +pub const AXGE_WRITE_EFUSE_DIS: u8 = 0x0A; +pub const AXGE_ACCESS_MFAB: u8 = 0x10; + +// Firmware Modes +pub const AXGE_FW_MODE_178A179: u16 = 0x0000; +pub const AXGE_FW_MODE_179A: u16 = 0x0001; + +// Physical Link Status Register +pub const AXGE_PLSR: u8 = 0x02; +pub const PLSR_USB_FS: u8 = 0x01; +pub const PLSR_USB_HS: u8 = 0x02; +pub const PLSR_USB_SS: u8 = 0x04; + +// EEPROM Registers +pub const AXGE_EAR: u8 = 0x07; +pub const AXGE_EDLR: u8 = 0x08; +pub const AXGE_EDHR: u8 = 0x09; +pub const AXGE_ECR: u8 = 0x0A; + +// Rx Control Register +pub const AXGE_RCR: u8 = 0x0B; +pub const RCR_STOP: u16 = 0x0000; +pub const RCR_PROMISC: u16 = 0x0001; +pub const RCR_ACPT_ALL_MCAST: u16 = 0x0002; +pub const RCR_AUTOPAD_BNDRY: u16 = 0x0004; +pub const RCR_ACPT_BCAST: u16 = 0x0008; +pub const RCR_ACPT_MCAST: u16 = 0x0010; +pub const RCR_ACPT_PHY_MCAST: u16 = 0x0020; +pub const RCR_START: u16 = 0x0080; +pub const RCR_DROP_CRCERR: u16 = 0x0100; +pub const RCR_IPE: u16 = 0x0200; +pub const RCR_TX_CRC_PAD: u16 = 0x0400; + +// Node ID Register +pub const AXGE_NIDR: u8 = 0x10; + +// Multicast Filter Array +pub const AXGE_MFA: u8 = 0x16; + +// Medium Status Register +pub const AXGE_MSR: u16 = 0x22; +pub const MSR_GM: u16 = 0x0001; +pub const MSR_FD: u16 = 0x0002; +pub const MSR_EN_125MHZ: u16 = 0x0008; +pub const MSR_RFC: u16 = 0x0010; +pub const MSR_TFC: u16 = 0x0020; +pub const MSR_RE: u16 = 0x0100; +pub const MSR_PS: u16 = 0x0200; + +// Monitor mode status register +pub const AXGE_MMSR: u8 = 0x24; + +pub const MMSR_RWLC: u8 = 0x02; +pub const MMSR_RWMP: u8 = 0x04; +pub const MMSR_RWWF: u8 = 0x08; +pub const MMSR_RW_FLAG: u8 = 0x10; +pub const MMSR_PME_POL: u8 = 0x20; +pub const MMSR_PME_TYPE: u8 = 0x40; +pub const MMSR_PME_IND: u8 = 0x80; + + +// Ethernet PHY power & reset control register +pub const AXGE_EPPRCR: u16 = 0x26; +pub const EPPRCR_BZ: u16 = 0x0010; +pub const EPPRCR_IPRL: u16 = 0x0020; +pub const EPPRCR_AUTODETACH: u16 = 0x1000; + +pub const AXGE_RX_BULKIN_QCTRL: u8 = 0x2e; + +pub const AXGE_CLK_SELECT: u8 = 0x33; +pub const AXGE_CLK_SELECT_BCS: u8 = 0x01; +pub const AXGE_CLK_SELECT_ACS: u8 = 0x02; +pub const AXGE_CLK_SELECT_ACSREQ: u8 = 0x10; +pub const AXGE_CLK_SELECT_ULR: u8 = 0x08; + +// COE Rx control register +pub const AXGE_CRCR: u8 = 0x34; +pub const CRCR_IP: u8 = 0x01; +pub const CRCR_TCP: u8 = 0x02; +pub const CRCR_UDP: u8 = 0x04; +pub const CRCR_ICMP: u8 = 0x08; +pub const CRCR_IGMP: u8 = 0x10; +pub const CRCR_TCPV6: u8 = 0x20; +pub const CRCR_UDPV6: u8 = 0x40; +pub const CRCR_ICMPV6: u8 = 0x80; + +// COE Tx control register +pub const AXGE_CTCR: u8 = 0x35; +pub const CTCR_IP: u8 = 0x01; +pub const CTCR_TCP: u8 = 0x02; +pub const CTCR_UDP: u8 = 0x04; +pub const CTCR_ICMP: u8 = 0x08; +pub const CTCR_IGMP: u8 = 0x10; +pub const CTCR_TCPV6: u8 = 0x20; +pub const CTCR_UDPV6: u8 = 0x40; +pub const CTCR_ICMPV6: u8 = 0x80; + +// Pause water level high register +pub const AXGE_PWLHR: u16 = 0x54; + +// Pause water level low register +pub const AXGE_PWLLR: u16 = 0x55; + +// Configuration number 1 +pub const AXGE_CONFIG_IDX: u16 = 0; + +// Interface index 0 +pub const AXGE_IFACE_IDX: u16 = 0; + + + +// Utility macro in C: #define BIT(x) (1 << (x)) +// In Rust (no_std), we just shift manually. + +pub const GMII_LED_ACT: u8 = 0x1a; +pub const GMII_LED_ACTIVE_MASK: u16 = 0xff8f; +pub const GMII_LED0_ACTIVE: u16 = 1 << 4; +pub const GMII_LED1_ACTIVE: u16 = 1 << 5; +pub const GMII_LED2_ACTIVE: u16 = 1 << 6; + +pub const GMII_LED_LINK: u8 = 0x1c; +pub const GMII_LED_LINK_MASK: u16 = 0xf888; +pub const GMII_LED0_LINK_10: u16 = 1 << 0; +pub const GMII_LED0_LINK_100: u16 = 1 << 1; +pub const GMII_LED0_LINK_1000: u16 = 1 << 2; +pub const GMII_LED1_LINK_10: u16 = 1 << 4; +pub const GMII_LED1_LINK_100: u16 = 1 << 5; +pub const GMII_LED1_LINK_1000: u16 = 1 << 6; +pub const GMII_LED2_LINK_10: u16 = 1 << 8; +pub const GMII_LED2_LINK_100: u16 = 1 << 9; +pub const GMII_LED2_LINK_1000: u16 = 1 << 10; + +// LED control fields +pub const LED0_ACTIVE: u16 = 1 << 0; +pub const LED0_LINK_10: u16 = 1 << 1; +pub const LED0_LINK_100: u16 = 1 << 2; +pub const LED0_LINK_1000: u16 = 1 << 3; +pub const LED0_FD: u16 = 1 << 4; +pub const LED0_USB3_MASK: u16 = 0x001f; + +pub const LED1_ACTIVE: u16 = 1 << 5; +pub const LED1_LINK_10: u16 = 1 << 6; +pub const LED1_LINK_100: u16 = 1 << 7; +pub const LED1_LINK_1000: u16 = 1 << 8; +pub const LED1_FD: u16 = 1 << 9; +pub const LED1_USB3_MASK: u16 = 0x03e0; + +pub const LED2_ACTIVE: u16 = 1 << 10; +pub const LED2_LINK_10: u16 = 1 << 11; +pub const LED2_LINK_100: u16 = 1 << 12; +pub const LED2_LINK_1000: u16 = 1 << 13; +pub const LED2_FD: u16 = 1 << 14; +pub const LED_VALID: u16 = 1 << 15; +pub const LED2_USB3_MASK: u16 = 0x7c00; + +// PHY Page select +pub const GMII_PHYPAGE: u16 = 0x1e; +pub const GMII_PHY_PAGE_SELECT: u16 = 0x1f; + +pub const GMII_PHY_PGSEL_EXT: u16 = 0x0007; +pub const GMII_PHY_PGSEL_PAGE0: u16 = 0x0000; +pub const GMII_PHY_PGSEL_PAGE3: u16 = 0x0003; +pub const GMII_PHY_PGSEL_PAGE5: u16 = 0x0005; + + + + +// PHY ID and EEPROM +pub const AX88179_PHY_ID: u16 = 0x03; +pub const AX_EEPROM_LEN: u16 = 0x100; +pub const AX88179_EEPROM_MAGIC: u32 = 0x1790_0b95; + +// Multicast filter settings +pub const AX_MCAST_FLTSIZE: u8 = 8; +pub const AX_MAX_MCAST: u8 = 64; + +// Interrupt status +pub const AX_INT_PPLS_LINK: u32 = 1 << 16; + +// RX header +pub const AX_RXHDR_L4_TYPE_MASK: u8 = 0x1c; +pub const AX_RXHDR_L4_TYPE_UDP: u8 = 4; +pub const AX_RXHDR_L4_TYPE_TCP: u8 = 16; +pub const AX_RXHDR_L3CSUM_ERR: u8 = 2; +pub const AX_RXHDR_L4CSUM_ERR: u8 = 1; +pub const AX_RXHDR_CRC_ERR: u32 = 1 << 29; +pub const AX_RXHDR_DROP_ERR: u32 = 1 << 31; + +// Access types +pub const AX_ACCESS_MAC: u8 = 0x01; +pub const AX_ACCESS_PHY: u8 = 0x02; +pub const AX_ACCESS_EEPROM: u8 = 0x04; +pub const AX_ACCESS_EFUS: u8 = 0x05; +pub const AX_RELOAD_EEPROM_EFUSE: u8 = 0x06; + +// Pause water level +pub const AX_PAUSE_WATERLVL_HIGH: u8 = 0x54; +pub const AX_PAUSE_WATERLVL_LOW: u8 = 0x55; + +// Physical Link Status +pub const PHYSICAL_LINK_STATUS: u8 = 0x02; +pub const AX_USB_SS: u8 = 1 << 2; +pub const AX_USB_HS: u8 = 1 << 1; + +// General Status +pub const GENERAL_STATUS: u8 = 0x03; +pub const AX_SECLD: u8 = 1 << 2; + +// SROM (EEPROM) addresses +pub const AX_SROM_ADDR: u8 = 0x07; +pub const AX_SROM_CMD: u8 = 0x0a; +pub const EEP_RD: u8 = 1 << 2; +pub const EEP_BUSY: u8 = 1 << 4; +pub const AX_SROM_DATA_LOW: u8 = 0x08; +pub const AX_SROM_DATA_HIGH: u8 = 0x09; + +// RX Control +pub const AX_RX_CTL: u16 = 0x0b; +pub const AX_RX_CTL_DROPCRCERR: u16 = 0x0100; +pub const AX_RX_CTL_IPE: u16 = 0x0200; +pub const AX_RX_CTL_START: u16 = 0x0080; +pub const AX_RX_CTL_AP: u16 = 0x0020; +pub const AX_RX_CTL_AM: u16 = 0x0010; +pub const AX_RX_CTL_AB: u16 = 0x0008; +pub const AX_RX_CTL_AMALL: u16 = 0x0002; +pub const AX_RX_CTL_PRO: u16 = 0x0001; +pub const AX_RX_CTL_STOP: u16 = 0x0000; + +// Node ID, Multicast Filter Array +pub const AX_NODE_ID: u8 = 0x10; +pub const AX_MULFLTARY: u8 = 0x16; + +// Medium Status Mode +pub const AX_MEDIUM_STATUS_MODE: u8 = 0x22; +pub const AX_MEDIUM_GIGAMODE: u16 = 0x0001; +pub const AX_MEDIUM_FULL_DUPLEX: u16 = 0x0002; +pub const AX_MEDIUM_EN_125MHZ: u16 = 0x0008; +pub const AX_MEDIUM_RXFLOW_CTRLEN: u16 = 0x0010; +pub const AX_MEDIUM_TXFLOW_CTRLEN: u16 = 0x0020; +pub const AX_MEDIUM_RECEIVE_EN: u16 = 0x0100; +pub const AX_MEDIUM_PS: u16 = 0x0200; +pub const AX_MEDIUM_JUMBO_EN: u16 = 0x8040; + +// Monitor Mode +pub const AX_MONITOR_MOD: u8 = 0x24; +pub const AX_MONITOR_MODE_RWLC: u8 = 1 << 1; +pub const AX_MONITOR_MODE_RWMP: u8 = 1 << 2; +pub const AX_MONITOR_MODE_PMEPOL: u8 = 1 << 5; +pub const AX_MONITOR_MODE_PMETYPE: u8 = 1 << 6; + +// GPIO Control +pub const AX_GPIO_CTRL: u8 = 0x25; +pub const AX_GPIO_CTRL_GPIO3EN: u8 = 1 << 7; +pub const AX_GPIO_CTRL_GPIO2EN: u8 = 1 << 6; +pub const AX_GPIO_CTRL_GPIO1EN: u8 = 1 << 5; + +// PHY Power Reset Control +pub const AX_PHYPWR_RSTCTL: u8 = 0x26; +pub const AX_PHYPWR_RSTCTL_BZ: u16 = 0x0010; +pub const AX_PHYPWR_RSTCTL_IPRL: u16 = 0x0020; +pub const AX_PHYPWR_RSTCTL_AT: u16 = 0x1000; + +// RX Bulk IN Queue Control +pub const AX_RX_BULKIN_QCTRL: u8 = 0x2e; + +// Clock Select +pub const AX_CLK_SELECT: u8 = 0x33; +pub const AX_CLK_SELECT_BCS: u8 = 1 << 0; +pub const AX_CLK_SELECT_ACS: u8 = 1 << 1; +pub const AX_CLK_SELECT_ULR: u8 = 1 << 3; + + +// RX Checksum Offload Engine (COE) Control +pub const AX_RXCOE_CTL: u8 = 0x34; +pub const AX_RXCOE_IP: u8 = 0x01; +pub const AX_RXCOE_TCP: u8 = 0x02; +pub const AX_RXCOE_UDP: u8 = 0x04; +pub const AX_RXCOE_TCPV6: u8 = 0x20; +pub const AX_RXCOE_UDPV6: u8 = 0x40; + +// TX Checksum Offload Engine (COE) Control +pub const AX_TXCOE_CTL: u8 = 0x35; +pub const AX_TXCOE_IP: u8 = 0x01; +pub const AX_TXCOE_TCP: u8 = 0x02; +pub const AX_TXCOE_UDP: u8 = 0x04; +pub const AX_TXCOE_TCPV6: u8 = 0x20; +pub const AX_TXCOE_UDPV6: u8 = 0x40; diff --git a/crates/kernel/src/device/usb/device/hid.rs b/crates/kernel/src/device/usb/device/hid.rs index 1233b3c8..382d26d1 100644 --- a/crates/kernel/src/device/usb/device/hid.rs +++ b/crates/kernel/src/device/usb/device/hid.rs @@ -210,19 +210,19 @@ pub fn HidAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { } } - let _header = - device.full_configuration.as_mut().unwrap().as_mut_ptr() as *mut UsbDescriptorHeader; - { - let mut buffer = Box::new([0u8; 30]); - let _result = HidGetReport( - device, - HidReportType::Feature, - 0, - interface_number as u8, - 8, - buffer.as_mut_ptr(), - ); - } + // let _header = + // device.full_configuration.as_mut().unwrap().as_mut_ptr() as *mut UsbDescriptorHeader; + // { + // let mut buffer = Box::new([0u8; 30]); + // let _result = HidGetReport( + // device, + // HidReportType::Feature, + // 0, + // interface_number as u8, + // 8, + // buffer.as_mut_ptr(), + // ); + // } //TODO: Hardcoded for keyboard atm //https://github.com/tmk/tmk_keyboard/wiki/USB%3A-HID-Usage-Table diff --git a/crates/kernel/src/device/usb/device/net.rs b/crates/kernel/src/device/usb/device/net.rs index aae2bb8f..3a06ce90 100644 --- a/crates/kernel/src/device/usb/device/net.rs +++ b/crates/kernel/src/device/usb/device/net.rs @@ -8,16 +8,23 @@ use super::super::usbd::device::*; */ use core::slice; +use crate::device::usb; use crate::networking::iface::*; use crate::networking::repr::*; +use crate::device::system_timer::micro_delay; +use crate::device::usb::hcd::dwc::dwc_otg::ms_to_micro; use crate::device::usb::types::*; use crate::device::usb::usbd::endpoint::register_interrupt_endpoint; use crate::device::usb::usbd::endpoint::*; use crate::device::usb::usbd::request::*; +use crate::device::mailbox::HexDisplay; use crate::shutdown; use alloc::boxed::Box; +use crate::device::usb::device::ax88179::axge_send_packet; +use crate::device::usb::device::ax88179::axge_init; +use crate::device::usb::device::ax88179::axge_receive_packet; use alloc::vec; use super::rndis::*; @@ -25,6 +32,8 @@ use super::rndis::*; pub static mut NET_DEVICE: NetDevice = NetDevice { receive_callback: None, device: None, + net_send: None, + net_receive: None, }; pub static mut INTERFACE: Option = None; @@ -52,26 +61,24 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // device.interfaces[interface_number as usize].protocol // ); println!("| Net: Usb Hub Detected"); - rndis_initialize_msg(device); - let mut buffer = [0u8; 52]; + if device.descriptor.vendor_id == 0xB95 && device.descriptor.product_id == 0x1790 { + println!("| Net: AX88179 Detected"); + axge_init(device); - unsafe { - rndis_query_msg( - device, - OID::OID_GEN_CURRENT_PACKET_FILTER, - buffer.as_mut_ptr(), - 30, - ); - - rndis_set_msg(device, OID::OID_GEN_CURRENT_PACKET_FILTER, 0xF); - - rndis_query_msg( - device, - OID::OID_GEN_CURRENT_PACKET_FILTER, - buffer.as_mut_ptr(), - 30, - ); + unsafe { + NET_DEVICE.net_send = Some(axge_send_packet); + NET_DEVICE.net_receive = Some(axge_receive_packet); + } + + } else { + println!("| Net: RNDIS Device Detected"); + rndis_init(device); + + unsafe { + NET_DEVICE.net_send = Some(rndis_send_packet); + NET_DEVICE.net_receive = Some(rndis_receive_packet); + } } let driver_data = Box::new(UsbEndpointDevice::new()); @@ -91,21 +98,21 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // device.endpoints[interface_number as usize][0 as usize].interval // ); - register_interrupt_endpoint( - device, - device.endpoints[interface_number as usize][0 as usize].interval as u32, - endpoint_address_to_num( - device.endpoints[interface_number as usize][0 as usize].endpoint_address, - ), - UsbDirection::In, - size_from_number( - device.endpoints[interface_number as usize][0 as usize] - .packet - .MaxSize as u32, - ), - 0, - 10, - ); + // register_interrupt_endpoint( + // device, + // device.endpoints[interface_number as usize][0 as usize].interval as u32, + // endpoint_address_to_num( + // device.endpoints[interface_number as usize][0 as usize].endpoint_address, + // ), + // UsbDirection::In, + // size_from_number( + // device.endpoints[interface_number as usize][0 as usize] + // .packet + // .MaxSize as u32, + // ), + // 0, + // 10, + // ); // 1. new network interface // 2. initialize mac address @@ -152,7 +159,7 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // to us through the rgistered `recv` function which then queues another receive let buf = vec![0u8; 1600]; unsafe { - rndis_receive_packet(device, buf.into_boxed_slice(), 1500); // TODO: ask aaron if I need to use another function? + NetInitiateReceive(buf.into_boxed_slice(), 1500); // TODO: ask aaron if I need to use another function? } // start dhcp @@ -167,6 +174,30 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { return ResultCode::OK; } +pub fn NetInitiateReceive(buffer: Box<[u8]>, buffer_length: u32) { + unsafe { + if let Some(receive_func) = NET_DEVICE.net_receive { + let device = NET_DEVICE.device.unwrap(); + let usb_device = &mut *device; + receive_func(usb_device, buffer, buffer_length); + } else { + println!("| Net: No callback for initiate receive."); + } + } +} + +pub fn NetSendPacket(buffer: *mut u8, buffer_length: u32) { + unsafe { + if let Some(send_func) = NET_DEVICE.net_send { + let device = NET_DEVICE.device.unwrap(); + let usb_device = &mut *device; + send_func(usb_device, buffer, buffer_length); + } else { + println!("| Net: No callback for send."); + } + } +} + pub unsafe fn recv(buf: *mut u8, buf_len: u32) { // cast our buffer into a Vec let slice: &[u8] = unsafe { slice::from_raw_parts(buf, buf_len as usize) }; @@ -181,16 +212,16 @@ pub unsafe fn NetAnalyze(buffer: *mut u8, buffer_length: u32) { return; } - if buffer32[0] != 0 { - println!("| Net: Buffer1: {:?}", buffer32[0]); - shutdown(); + if buffer_length > 0 { + println!("| NET: analyze {:x}", HexDisplay(unsafe { core::slice::from_raw_parts(buffer, buffer_length as usize) })); + // TODO: } } pub fn NetSend(_buffer: *mut u8, _buffer_length: u32) { - // Do nothing for now - // Called when USB packet is actually sent out - println!("NetSend called"); + //Do nothing for now + //Called when USB packet is actually sent out + // println!("| Net: Sent of length {}", _buffer_length); } pub unsafe fn NetReceive(buffer: *mut u8, buffer_length: u32) { @@ -218,23 +249,13 @@ pub fn RegisterNetReceiveCallback(callback: unsafe fn(*mut u8, u32)) { } } -pub unsafe fn NetSendPacket(buffer: *mut u8, buffer_length: u32) { - unsafe { - if let Some(device) = NET_DEVICE.device { - let usb_dev = &mut *device; - rndis_send_packet(usb_dev, buffer, buffer_length); - } else { - println!("| Net: No device found."); - shutdown(); - } - } -} pub struct NetDevice { pub receive_callback: Option, // pub receive_callback: Option, pub device: Option<*mut UsbDevice>, - // pub default_interface: Option>, + pub net_send: Option ResultCode>, + pub net_receive: Option, u32) -> ResultCode>, } #[repr(u32)] diff --git a/crates/kernel/src/device/usb/device/rndis.rs b/crates/kernel/src/device/usb/device/rndis.rs index 24063e89..c3fc3b87 100644 --- a/crates/kernel/src/device/usb/device/rndis.rs +++ b/crates/kernel/src/device/usb/device/rndis.rs @@ -22,6 +22,30 @@ const ControlTimeoutPeriod: u32 = 10; #[allow(dead_code)] const KeepAliveTimeoutPeriod: u32 = 5; +pub fn rndis_init(device: &mut UsbDevice) { + rndis_initialize_msg(device); + + let mut buffer = [0u8; 52]; + + unsafe { + rndis_query_msg( + device, + OID::OID_GEN_CURRENT_PACKET_FILTER, + buffer.as_mut_ptr(), + 30, + ); + + rndis_set_msg(device, OID::OID_GEN_CURRENT_PACKET_FILTER, 0xB); + + rndis_query_msg( + device, + OID::OID_GEN_CURRENT_PACKET_FILTER, + buffer.as_mut_ptr(), + 30, + ); + } +} + pub fn rndis_initialize_msg(device: &mut UsbDevice) -> ResultCode { let buffer = &mut RndisInitializeMsg { message_type: 0x00000002, diff --git a/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs index 2142af76..802a511f 100644 --- a/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs +++ b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs @@ -13,6 +13,8 @@ * THIS SOFTWARE IS NOT AFFILIATED WITH NOR ENDORSED BY SYNOPSYS IP. ******************************************************************************/ +use core::time; + use crate::device::usb::hcd::dwc::dwc_otgreg::*; use crate::device::usb::hcd::dwc::roothub::*; use crate::device::usb::types::*; @@ -51,6 +53,7 @@ pub fn dwc_otg_register_interrupt_handler() { } fn schedule_next_transfer(channel: u8) { + // println!("| DWC: Scheduling next transfer on channel {}", channel); //Check if another transfer is pending if let Some(transfer) = USB_TRANSFER_QUEUE.get_transfer() { //Enable transfer, keep holding channel @@ -62,9 +65,11 @@ fn schedule_next_transfer(channel: u8) { match transfer.as_ref().endpoint_descriptor.endpoint_type { //TODO: Kinda cursed, maybe make cleaner UsbTransfer::Bulk => unsafe { + // println!("| DWC: Bulk transfer on channel {}", channel); UsbBulkMessage(device, transfer, channel); }, UsbTransfer::Interrupt => unsafe { + // println!("| DWC: Interrupt transfer on channel {}", channel); UsbInterruptMessage(device, transfer, channel); }, _ => { @@ -73,6 +78,7 @@ fn schedule_next_transfer(channel: u8) { } } } else { + // println!("| DWC: No more transfers pending on channel {}", channel); //Don't need the occupy channel anymore dwc_otg_free_channel(channel as u32); } @@ -107,8 +113,9 @@ pub fn dwc_otg_interrupt_handler(_ctx: &mut Context, _irq: usize) { { if let Some(callback) = unsafe { DWC_CHANNEL_CALLBACK.callback[i] } { let hcint = hcint_channels[i]; + let dwc_split = unsafe { DWC_CHANNEL_CALLBACK.split_control_state[i] }; schedule_rt(move || { - if callback(endpoint_descriptor, hcint, i as u8) { + if callback(endpoint_descriptor, hcint, i as u8, dwc_split) { schedule_next_transfer(i as u8); } }); @@ -133,11 +140,67 @@ pub fn DwcUpdateHostFrameInterval() { pub fn UpdateDwcOddFrame(channel: u8) { let frame = read_volatile(DOTG_HFNUM); let mut hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + hcchar &= !HCCHAR_CHDIS; hcchar &= !HCCHAR_ODDFRM; hcchar |= (!(frame & 1)) << 29 | HCCHAR_CHENA; write_volatile(DOTG_HCCHAR(channel as usize), hcchar); } +pub fn DwcActivateCsplit(channel: u8) -> u32 { + let mut hcsplt = read_volatile(DOTG_HCSPLT(channel as usize)); + hcsplt |= HCSPLT_COMPSPLT; + write_volatile(DOTG_HCSPLT(channel as usize), hcsplt); + + // let frame = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + // let mut hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + // hcchar &= !HCCHAR_CHDIS; + // hcchar &= !HCCHAR_ODDFRM; + // hcchar |= (!(frame & 1)) << 29 | HCCHAR_CHENA; + // write_volatile(DOTG_HCCHAR(channel as usize), hcchar); + + let frame = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + let mut hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + hcchar &= !HCCHAR_CHDIS; + hcchar &= !HCCHAR_ODDFRM; + hcchar |= HCCHAR_CHENA; + + hcchar |= (frame & 1) << 29; + + write_volatile(DOTG_HCCHAR(channel as usize), hcchar); + + return frame; +} + +pub fn DwcEnableChannel(channel: u8) -> u32 { + let frame = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + let mut hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + hcchar &= !HCCHAR_CHDIS; + hcchar &= !HCCHAR_ODDFRM; + hcchar |= HCCHAR_CHENA; + + hcchar |= (frame & 1) << 29; + + write_volatile(DOTG_HCCHAR(channel as usize), hcchar); + + return frame; +} + +pub fn DwcDisableChannel(channel: u8) { + let mut hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + hcchar &= !HCCHAR_CHENA; + hcchar |= HCCHAR_CHDIS; + write_volatile(DOTG_HCCHAR(channel as usize), hcchar); +} + +//frame2 should be before frame1 +pub fn DwcFrameDifference(frame1: u32, frame2: u32) -> u32 { + if frame2 > frame1 { + return (frame1 + 0x3fff) - frame2; + } else { + return frame1 - frame2; + } +} + /** \brief Prepares a channel to communicated with a device. @@ -223,8 +286,16 @@ fn HcdPrepareChannel( dwc_sc.channel[channel as usize].split_control.HubAddress = (*parent).number; } } - // println!("| Port number: {:#?}", device.port_number); - dwc_sc.channel[channel as usize].split_control.PortAddress = device.port_number; + dwc_sc.channel[channel as usize].split_control.XactPos = 0b11; + // println!("| HCD Prepare Channel Port number: {:#?}", device.port_number); + dwc_sc.channel[channel as usize].split_control.PortAddress = device.port_number + 1; + + unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = DWCSplitStateMachine::SSPLIT; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].ss_hfnum = read_volatile(DOTG_HFNUM); + } + } else { + unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = DWCSplitStateMachine::NONE; } } let hcsplt = convert_host_split_control(dwc_sc.channel[channel as usize].split_control); @@ -252,11 +323,10 @@ fn HcdPrepareChannel( let hctsiz = convert_host_transfer_size(dwc_sc.channel[channel as usize].transfer_size); // println!("| HCTSIZE {:#x}\n", hctsiz); write_volatile(DOTG_HCTSIZ(channel as usize), hctsiz); - return ResultCode::OK; } -pub unsafe fn HcdTransmitChannel(device: &UsbDevice, channel: u8, buffer: *mut u8) { +pub unsafe fn HcdTransmitChannel(device: &UsbDevice, channel: u8, buffer: *mut u8, bufferOffset: usize, direction: UsbDirection) { unsafe { let dwc_sc: &mut dwc_hub = &mut *(device.soft_sc as *mut dwc_hub); let hcsplt = read_volatile(DOTG_HCSPLT(channel as usize)); @@ -279,10 +349,22 @@ pub unsafe fn HcdTransmitChannel(device: &UsbDevice, channel: u8, buffer: *mut u let dma_base_phys = 0x2FF0000; let dma_base_gpu = dma_base_phys | 0xC0000000; - let dma_address = dma_base_gpu + 0x1000 * channel as usize; + let mut dma_address = dma_base_gpu + 0x1000 * channel as usize; let dma_loc = dwc_sc.dma_loc + 0x1000 * channel as usize; //copy from buffer to dma_loc for 32 bytes - memory_copy(dma_loc as *mut u8, buffer, 100); + + if direction == UsbDirection::In { + dma_address += bufferOffset as usize; + //check if dma_address is aligned to 4 bytes + if (dma_address & 3) != 0 { + println!( + "HCD: DMA transfer buffer {:#x} is not DWORD aligned. Ignored, but dangerous.\n", + dma_address, + ); + } + } else { //going out + memory_copy(dma_loc as *mut u8, buffer, 100); //unclean + } crate::arch::memory::invalidate_physical_buffer_for_device(dma_loc as *mut (), 128); @@ -436,8 +518,10 @@ pub fn HcdChannelSendWaitOne( &mut dwc_sc.channel[channel as usize].split_control, ); + printDWCErrors(channel as u32); // Transmit data. - unsafe { HcdTransmitChannel(device, channel, buffer.wrapping_add(bufferOffset as usize)) }; + // unsafe { HcdTransmitChannel(device, channel, buffer.wrapping_add(bufferOffset as usize)) }; + unsafe { HcdTransmitChannel(device, channel, buffer, bufferOffset as usize, pipe.direction) }; timeout = 0; loop { if timeout == RequestTimeout { @@ -454,7 +538,8 @@ pub fn HcdChannelSendWaitOne( break; } } - // println!("| HCD: Channel interrupt {:#x}\n", hcint); + // println!("| HCD: Channel interrupt {:#x} timeout {}", hcint, timeout); + // println!("| HCD: Channel halt send wait"); let hctsiz = read_volatile(DOTG_HCTSIZ(channel as usize)); convert_into_host_transfer_size( @@ -463,8 +548,12 @@ pub fn HcdChannelSendWaitOne( ); hcint = read_volatile(DOTG_HCINT(channel as usize)); - if pipe.speed != UsbSpeed::High { - if hcint & HCINT_ACK != 0 && dwc_sc.channel[channel as usize].split_control.SplitEnable + // println!("| HCD: pipe speed {:#?}", pipe.speed); + + printDWCErrors(channel as u32); + if pipe.speed != UsbSpeed::High && dwc_sc.channel[channel as usize].split_control.SplitEnable { + println!("| HCD: Split enable {:#?} hcint {:#x}", dwc_sc.channel[channel as usize].split_control.SplitEnable, hcint); + if hcint & HCINT_ACK != 0 && dwc_sc.channel[channel as usize].split_control.SplitEnable { // Try to complete the split up to 3 times. // println!("| HCD: Completing split to device with ACK"); @@ -509,6 +598,8 @@ pub fn HcdChannelSendWaitOne( } } + println!("| HCD split completion timeout {}", timeout); + if hcint & HCINT_NYET == 0 { break; } @@ -560,20 +651,37 @@ pub fn HcdChannelSendWaitOne( return result; } } else if hcint & HCINT_NAK != 0 { + println!("| HCD: Outer loop NAK"); globalTries = globalTries.wrapping_sub(1); micro_delay(25000); continue; } else if hcint & HCINT_XACTERR != 0 { + println!("| HCD: Outer loop XACTERR"); micro_delay(25000); continue; } } else { - result = HcdChannelInterruptToError( - device, - hcint, - !dwc_sc.channel[channel as usize].split_control.SplitEnable, - ); - if result != ResultCode::OK { + + if hcint & HCINT_XFERCOMPL == 0 { + _ = HcdChannelInterruptToError( + device, + hcint, + !dwc_sc.channel[channel as usize].split_control.SplitEnable, + ); + + printDWCErrors(channel as u32); + // LOG_DEBUGF( + // "HCD: Control message to %#x: %02x%02x%02x%02x %02x%02x%02x%02x.\n", + // *(pipe as *const u32), + // *((request as *const u8).offset(0)), + // *((request as *const u8).offset(1)), + // *((request as *const u8).offset(2)), + // *((request as *const u8).offset(3)), + // *((request as *const u8).offset(4)), + // *((request as *const u8).offset(5)), + // *((request as *const u8).offset(6)), + // *((request as *const u8).offset(7)), + // ); println!("HCD: Request to failed.\n"); return ResultCode::ErrorRetry; } @@ -649,6 +757,14 @@ fn HcdChannelSendWait( request, ); if result != ResultCode::OK { + let hcint = read_volatile(DOTG_HCINT(channel as usize)); + + if hcint & HCINT_NAK != 0 { + println!("| HCD: NAK on channel {}\n", device.last_transfer); + + return ResultCode::OK; + } + if result == ResultCode::ErrorRetry { // Restart the entire process on ErrorRetry. println!("| HCD: Retrying to packet.\n"); @@ -673,7 +789,7 @@ fn HcdChannelSendWait( // If the packet count hasn’t changed, break out of the loop. if packets == dwc_sc.channel[channel as usize].transfer_size.PacketCount { - // println!("| HCD: Transfer to packet got stuck."); + println!("| HCD: Transfer to packet got stuck."); break; } // Continue looping if there are still packets in progress. @@ -691,13 +807,13 @@ fn HcdChannelSendWait( // Check for a stuck transfer. if packets == dwc_sc.channel[channel as usize].transfer_size.PacketCount { //TODO: Hacky fix for a NAK on interrupt endpoint transfer + println!("| HCD: Transfer to packet (2) got stuck."); let hcint = read_volatile(DOTG_HCINT(channel as usize)); if hcint & HCINT_NAK != 0 { device.error = UsbTransferError::NoAcknowledge; } else { device.error = UsbTransferError::ConnectionError; } - // println!("| HCD: Transfer to packet got stuck."); return ResultCode::ErrorDevice; } @@ -738,6 +854,10 @@ fn HcdTransmitChannelNoWait(device: &UsbDevice, channel: u8, buffer: *mut u8) { ); } + let dma_loc = dwc_sc.dma_addr[channel as usize]; + + crate::arch::memory::invalidate_physical_buffer_for_device(dma_loc as *mut (), 128); + dwc_sc.channel[channel as usize].dma_address = buffer; write_volatile(DOTG_HCDMA(channel as usize), buffer as u32); @@ -753,6 +873,17 @@ fn HcdTransmitChannelNoWait(device: &UsbDevice, channel: u8, buffer: *mut u8) { .characteristics .PacketsPerFrame = 1; + if DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state == DWCSplitStateMachine::SSPLIT { + let mut hfnum = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + + while hfnum % 8 == 6 { + micro_delay(10); + hfnum = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + } + + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].ss_hfnum = hfnum; + } //TODO: temporary + write_volatile( DOTG_HCCHAR(channel as usize), convert_host_characteristics(dwc_sc.channel[channel as usize].characteristics), @@ -776,32 +907,31 @@ fn HcdChannelSendOne( if pipe.transfer_type == UsbTransfer::Bulk && pipe.direction == UsbDirection::In { write_volatile( DOTG_HCINTMSK(channel as usize), - HCINTMSK_XFERCOMPLMSK - | HCINTMSK_CHHLTDMSK - | HCINTMSK_AHBERRMSK - | HCINTMSK_STALLMSK - // | HCINTMSK_NAKMSK - | HCINTMSK_ACKMSK - | HCINTMSK_NYETMSK - | HCINTMSK_XACTERRMSK - | HCINTMSK_BBLERRMSK - | HCINTMSK_FRMOVRUNMSK - | HCINTMSK_DATATGLERRMSK, + // HCINTMSK_XFERCOMPLMSK + HCINTMSK_CHHLTDMSK + // | HCINTMSK_AHBERRMSK + // | HCINTMSK_STALLMSK + // | HCINTMSK_ACKMSK + // | HCINTMSK_NYETMSK + // | HCINTMSK_XACTERRMSK + // | HCINTMSK_BBLERRMSK + // | HCINTMSK_FRMOVRUNMSK + // | HCINTMSK_DATATGLERRMSK, ) } else { write_volatile( DOTG_HCINTMSK(channel as usize), - HCINTMSK_XFERCOMPLMSK - | HCINTMSK_CHHLTDMSK - | HCINTMSK_AHBERRMSK - | HCINTMSK_STALLMSK - | HCINTMSK_NAKMSK - | HCINTMSK_ACKMSK - | HCINTMSK_NYETMSK - | HCINTMSK_XACTERRMSK - | HCINTMSK_BBLERRMSK - | HCINTMSK_FRMOVRUNMSK - | HCINTMSK_DATATGLERRMSK, + // HCINTMSK_XFERCOMPLMSK + HCINTMSK_CHHLTDMSK + // | HCINTMSK_AHBERRMSK + // | HCINTMSK_STALLMSK + // | HCINTMSK_NAKMSK + // | HCINTMSK_ACKMSK + // | HCINTMSK_NYETMSK + // | HCINTMSK_XACTERRMSK + // | HCINTMSK_BBLERRMSK + // | HCINTMSK_FRMOVRUNMSK + // | HCINTMSK_DATATGLERRMSK, ); } @@ -875,10 +1005,11 @@ pub unsafe fn HcdSubmitBulkMessage( unsafe { memory_copy( data_buffer, - buffer.unwrap().as_ptr(), + buffer.unwrap().as_mut_ptr(), buffer_length as usize, ); } + } let result = HcdChannelSend( @@ -898,6 +1029,77 @@ pub unsafe fn HcdSubmitBulkMessage( return ResultCode::OK; } +pub unsafe fn HcdSubmitInterruptMessage2( + device: &mut UsbDevice, + channel: u8, + pipe: UsbPipeAddress, + buffer: *mut u8, + buffer_length: u32, + packet_id: PacketId, +) -> ResultCode { + let dwc_sc = unsafe { &mut *(device.soft_sc as *mut dwc_hub) }; + device.error = UsbTransferError::Processing; + device.last_transfer = 0; + + let mut tempPipe = UsbPipeAddress { + max_size: pipe.max_size, + speed: pipe.speed, + end_point: pipe.end_point, + device: pipe.device, + transfer_type: UsbTransfer::Interrupt, + direction: UsbDirection::In, + _reserved: 0, + }; + let result = HcdChannelSendWait( + device, + &mut tempPipe, + channel, + buffer, + buffer_length, + &mut UsbDeviceRequest { request_type: 0, request: crate::device::usb::usbd::request::UsbDeviceRequestRequest::ClearFeature, value: 0, index: 0, length: 0 }, + packet_id, + ); + + if pipe.direction == UsbDirection::In { + // Read the data from the device. + let hctsiz = read_volatile(DOTG_HCTSIZ(0)); + // dwc_sc.channel[0].transfer_size.TransferSize = hctsiz & 0x7ffff; + convert_into_host_transfer_size(hctsiz, &mut dwc_sc.channel[0].transfer_size); + if dwc_sc.channel[0].transfer_size.TransferSize <= buffer_length { + device.last_transfer = buffer_length - dwc_sc.channel[0].transfer_size.TransferSize; + } else { + println!("| HCD: Weird transfer size\n"); + device.last_transfer = buffer_length; + } + use crate::device::usb::usbd::endpoint::UsbEndpointDevice; + let endpoint_device = device.driver_data.downcast::().unwrap(); + endpoint_device.endpoint_pid[0] += 1; + endpoint_device.endpoint_pid[1] += 1; + endpoint_device.endpoint_pid[2] += 1; + endpoint_device.endpoint_pid[3] += 1; + endpoint_device.endpoint_pid[4] += 1; + + unsafe { + memory_copy( + buffer, + dwc_sc.dma_addr[channel as usize] as *const u8, + device.last_transfer as usize, + ); + } + + } + + //transfer data cout + + dwc_otg_free_channel(channel as u32); + if result != ResultCode::OK { + println!("| HCD: Failed to send interrupt message to device.\n"); + return result; + } + + return ResultCode::OK; +} + pub unsafe fn HcdSubmitInterruptMessage( device: &mut UsbDevice, channel: u8, @@ -905,6 +1107,7 @@ pub unsafe fn HcdSubmitInterruptMessage( buffer_length: u32, packet_id: PacketId, ) -> ResultCode { + let dwc_sc = unsafe { &mut *(device.soft_sc as *mut dwc_hub) }; device.error = UsbTransferError::Processing; device.last_transfer = 0; @@ -937,28 +1140,22 @@ pub unsafe fn HcdSubmitInterruptMessage( return ResultCode::OK; } -pub fn DwcDisableChannel(channel: u8) { - let mut hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); - hcchar &= !HCCHAR_CHENA; - hcchar |= HCCHAR_CHDIS; - write_volatile(DOTG_HCCHAR(channel as usize), hcchar); -} pub fn printDWCErrors(channel: u32) { - let hprt = read_volatile(DOTG_HPRT); - let gintsts = read_volatile(DOTG_GINTSTS); - let haint = read_volatile(DOTG_HAINT); - let hcint = read_volatile(DOTG_HCINT(channel as usize)); - let hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); - let hctsiz = read_volatile(DOTG_HCTSIZ(channel as usize)); - - println!("| HCD hprt: {:#x}", hprt); - println!("| HCD gintsts: {:#x}", gintsts); - println!("| HCD haint: {:#x}", haint); - println!("| HCD hcint: {:#x}", hcint); - println!("| HCD hcchar: {:#x}", hcchar); - println!("| HCD hctsiz: {:#x}", hctsiz); - println!("| HCD channel: {:#x}\n", channel); + // let hprt = read_volatile(DOTG_HPRT); + // let gintsts = read_volatile(DOTG_GINTSTS); + // let haint = read_volatile(DOTG_HAINT); + // let hcint = read_volatile(DOTG_HCINT(channel as usize)); + // let hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + // let hctsiz = read_volatile(DOTG_HCTSIZ(channel as usize)); + + // println!("| HCD hprt: {:#x}", hprt); + // println!("| HCD gintsts: {:#x}", gintsts); + // println!("| HCD haint: {:#x}", haint); + // println!("| HCD hcint: {:#x}", hcint); + // println!("| HCD hcchar: {:#x}", hcchar); + // println!("| HCD hctsiz: {:#x}", hctsiz); + // println!("| HCD channel: {:#x}\n", channel); } pub unsafe fn HcdSubmitControlMessage( @@ -1008,6 +1205,9 @@ pub unsafe fn HcdSubmitControlMessage( return result; } + // println!("| HCD: Control message sent to device.\n"); + printDWCErrors(0); + let mut is_data1 = true; if !buffer.is_null() { @@ -1033,6 +1233,9 @@ pub unsafe fn HcdSubmitControlMessage( } else { PacketId::Data0 }; + + + is_data1 = !is_data1; result = HcdChannelSendWait( device, @@ -1043,6 +1246,7 @@ pub unsafe fn HcdSubmitControlMessage( request, pid, ); + if result != ResultCode::OK { println!("| HCD: Coult not send data to device\n"); @@ -1077,6 +1281,30 @@ pub unsafe fn HcdSubmitControlMessage( } else { device.last_transfer = buffer_length; } + + //print out the request in terms of bytes and print out the first 16 bytes of the data buffer + unsafe { + println!( + "| HCD: Control message to device {}: {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x} {:#x}", + pipe.device, + *((request_buffer as *const u8).offset(0)), + *((request_buffer as *const u8).offset(1)), + *((request_buffer as *const u8).offset(2)), + *((request_buffer as *const u8).offset(3)), + *((request_buffer as *const u8).offset(4)), + *((request_buffer as *const u8).offset(5)), + *((request_buffer as *const u8).offset(6)), + *((request_buffer as *const u8).offset(7)) + ); + //print the first 16 bytes of the data buffer + for i in 0..buffer_length { + print!( + "{:#x} ", + *((data_buffer as *const u8).offset(i as isize)) + ); + } + println!() + } } tempPipe.speed = pipe.speed; @@ -1090,12 +1318,12 @@ pub unsafe fn HcdSubmitControlMessage( tempPipe.direction = UsbDirection::Out; } - let pid = if is_data1 { - PacketId::Data1 - } else { - PacketId::Data0 - }; - + // let pid = if is_data1 { + // PacketId::Data1 + // } else { + // PacketId::Data0 + // }; + let pid = PacketId::Data1; //according to spec, the last packet is always Data1 // tempPipe.direction = UsbDirection::In; //TODO: This is necessary in Real hardware I think but QEMU doesn't fully handle it //https://elixir.bootlin.com/qemu/v9.0.2/source/hw/usb/hcd-dwc2.c#L346 @@ -1350,12 +1578,13 @@ pub fn DwcInit(bus: &mut UsbBus, base_addr: *mut ()) -> ResultCode { //setup clock let mut hcfg = read_volatile(DOTG_HCFG); hcfg &= !(HCFG_FSLSSUPP | HCFG_FSLSPCLKSEL_MASK); - hcfg |= (1 << HCFG_FSLSPCLKSEL_SHIFT) | HCFG_FSLSSUPP; + // hcfg |= (1 << HCFG_FSLSPCLKSEL_SHIFT) | HCFG_FSLSSUPP; + hcfg |= 1 << HCFG_FSLSPCLKSEL_SHIFT; //Host clock: 30-60Mhz write_volatile(DOTG_HCFG, hcfg); - let hfir = 0xBB80; - write_volatile(DOTG_HFIR, hfir); + // let hfir = 0xBB80; + // write_volatile(DOTG_HFIR, hfir); write_volatile(DOTG_GAHBCFG, GAHBCFG_GLBLINTRMSK); @@ -1690,6 +1919,33 @@ pub unsafe fn dwc_otg_initialize_controller(base_addr: *mut ()) { } } +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct DWCSplitControlState { + pub state: DWCSplitStateMachine, + pub ss_hfnum: u32, + pub mr_cs_hfnum: u32, //most recent CSplit HFNUM + pub tries: u32, +} + +impl DWCSplitControlState { + pub const fn new() -> Self { + Self { + state: DWCSplitStateMachine::NONE, + ss_hfnum: 0, + mr_cs_hfnum: 0, + tries: 0, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub enum DWCSplitStateMachine { + #[default] + NONE, + SSPLIT, + CSPLIT, +} + #[derive(Default)] pub struct DwcChannelActive { pub channel: [u8; ChannelCount], @@ -1730,8 +1986,9 @@ pub fn dwc_otg_free_channel(channel: u32) { } pub struct DwcChannelCallback { - pub callback: [Option bool>; ChannelCount], + pub callback: [Option bool>; ChannelCount], pub endpoint_descriptors: [Option; ChannelCount], + pub split_control_state: [DWCSplitControlState; ChannelCount], } impl DwcChannelCallback { @@ -1739,6 +1996,7 @@ impl DwcChannelCallback { Self { callback: [None; ChannelCount], endpoint_descriptors: [None; ChannelCount], + split_control_state: [DWCSplitControlState::new(); ChannelCount], } } } diff --git a/crates/kernel/src/device/usb/types.rs b/crates/kernel/src/device/usb/types.rs index ed07e932..0223af84 100644 --- a/crates/kernel/src/device/usb/types.rs +++ b/crates/kernel/src/device/usb/types.rs @@ -129,6 +129,7 @@ pub enum UsbPacketSize { Bits16, Bits32, Bits64, + Bits512, } pub const fn size_from_number(size: u32) -> UsbPacketSize { @@ -138,8 +139,10 @@ pub const fn size_from_number(size: u32) -> UsbPacketSize { UsbPacketSize::Bits16 } else if size <= 32 { UsbPacketSize::Bits32 - } else { + } else if size <= 64 { UsbPacketSize::Bits64 + } else { + UsbPacketSize::Bits512 } } @@ -150,5 +153,6 @@ pub fn size_to_number(packet_size: UsbPacketSize) -> u16 { UsbPacketSize::Bits16 => 16, UsbPacketSize::Bits32 => 32, UsbPacketSize::Bits64 => 64, + UsbPacketSize::Bits512 => 512, } } diff --git a/crates/kernel/src/device/usb/usbd/device.rs b/crates/kernel/src/device/usb/usbd/device.rs index e9965d21..327430f5 100644 --- a/crates/kernel/src/device/usb/usbd/device.rs +++ b/crates/kernel/src/device/usb/usbd/device.rs @@ -63,6 +63,8 @@ pub struct UsbDriverDataHeader { pub data_size: u32, } +unsafe impl Send for UsbDevice {} + /// Structure to store the details of a detected USB device. #[repr(C)] pub struct UsbDevice { diff --git a/crates/kernel/src/device/usb/usbd/endpoint.rs b/crates/kernel/src/device/usb/usbd/endpoint.rs index 381e1ae9..2a616d36 100644 --- a/crates/kernel/src/device/usb/usbd/endpoint.rs +++ b/crates/kernel/src/device/usb/usbd/endpoint.rs @@ -1,3 +1,4 @@ +use crate::device::system_timer::{get_time, micro_delay}; /** * * usbd/endpoint.rs @@ -8,14 +9,22 @@ */ use crate::device::usb; -use crate::device::system_timer::micro_delay; +// use crate::device::system_timer::micro_delay; use crate::device::usb::hcd::dwc::dwc_otg; use crate::device::usb::hcd::dwc::dwc_otg::DwcActivateChannel; -use crate::device::usb::hcd::dwc::dwc_otg::UpdateDwcOddFrame; +use crate::device::usb::hcd::dwc::dwc_otg::{printDWCErrors, read_volatile, DWCSplitControlState, DWCSplitStateMachine, DwcEnableChannel, UpdateDwcOddFrame, DWC_CHANNEL_CALLBACK}; use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; -use crate::device::usb::hcd::dwc::dwc_otgreg::HCINT_FRMOVRUN; +use crate::device::usb::hcd::dwc::dwc_otgreg::{DOTG_HCTSIZ, DOTG_HFNUM, HCINT_FRMOVRUN, HCINT_NYET, HCINT_XACTERR, HFNUM_FRNUM_MASK}; +use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCSPLT; +use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCCHAR; use crate::device::usb::DwcDisableChannel; +// use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; +use crate::device::usb::DwcFrameDifference; +// use crate::device::usb::hcd::dwc::dwc_otg; +use crate::device::usb::DwcActivateCsplit; +// use crate::device::usb::DwcDisableChannel; use crate::device::usb::UsbSendInterruptMessage; +use crate::sync::{LockGuard, SpinLockInner}; use usb::dwc_hub; use usb::hcd::dwc::dwc_otg::HcdUpdateTransferSize; use usb::hcd::dwc::dwc_otgreg::{HCINT_ACK, HCINT_CHHLTD, HCINT_NAK, HCINT_XFERCOMPL}; @@ -24,57 +33,45 @@ use usb::usbd::device::*; use usb::usbd::pipe::*; use usb::PacketId; + use crate::event::task::spawn_async_rt; use crate::sync::time::{interval, MissedTicks}; - +use crate::SpinLock; use alloc::boxed::Box; // static mut NET_BUFFER_CUR_LEN: u32 = 0; static mut NET_BUFFER_LEN: u32 = 0; static mut NET_BUFFER_ACTIVE: bool = false; -pub fn finish_bulk_endpoint_callback_in( - endpoint: endpoint_descriptor, - hcint: u32, - channel: u8, -) -> bool { - let device = unsafe { &mut *endpoint.device }; +pub static NEXT_FRAME_CS: SpinLock = SpinLock::new(0); +pub fn finish_bulk_endpoint_callback_in(endpoint: endpoint_descriptor, hcint: u32, channel: u8, _split_control: DWCSplitControlState) -> bool { + let device = unsafe { &mut *endpoint.device }; + let mut last_transfer; let transfer_size = HcdUpdateTransferSize(device, channel); - let mut last_transfer = endpoint.buffer_length - transfer_size; - let endpoint_device = device.driver_data.downcast::().unwrap(); - - if hcint & HCINT_NAK != 0 { - //NAK received -> need to schedule another transfer - // if device.last_transfer != 0 { - // panic!( - // "| Endpoint {} in: HCINT_NAK with transfer, aborting. hcint: {:x} last transfer: {}", - // channel, hcint, device.last_transfer - // ); - // } + if transfer_size > endpoint.buffer_length { println!( - "| Endpoint {} in: HCINT_NAK with transfer hcint: {:x} last transfer: {}", - channel, hcint, last_transfer + "| Endpoint {}: transfer size {} is greater than buffer length {} in bulk in", + channel, transfer_size, endpoint.buffer_length ); + let hctsiz = dwc_otg::read_volatile(DOTG_HCTSIZ(channel as usize)); + println!( + "| Endpoint {}: hctsiz {:x} hcint {:x}", + channel, hctsiz, hcint + ); + last_transfer = transfer_size; + } else { + last_transfer = endpoint.buffer_length - transfer_size; + } - if last_transfer > 0 && (hcint & HCINT_CHHLTD == 0) && (hcint & HCINT_XFERCOMPL == 0) { - // DwcActivateChannel(channel); - return false; - } else { - println!( - "| Endpoint {} in: HCINT_NAK with transfer, aborting. hcint: {:x} last transfer: {} Bulk in \n\n", - channel, hcint, last_transfer - ); - // return true; - } - } - // return; // WARN: aaron said to comment this out + // let last_transfer = endpoint.buffer_length - transfer_size; + let endpoint_device = device.driver_data.downcast::().unwrap(); if hcint & HCINT_CHHLTD == 0 { panic!( - "| Endpoint {} in: HCINT_CHHLTD not set, aborting. hcint: {:x} last transfer: {}", - channel, hcint, last_transfer + "| Endpoint {} in: HCINT_CHHLTD not set, not aborting. hcint: {:x}.", + channel, hcint ); } else if hcint & HCINT_XFERCOMPL == 0 { panic!( @@ -83,9 +80,12 @@ pub fn finish_bulk_endpoint_callback_in( ); } + // println!("| Endpoint BULK RECEIVED {}: hcint {:x} len {}", channel, hcint, last_transfer); + let dwc_sc = unsafe { &mut *(device.soft_sc as *mut dwc_hub) }; let dma_addr = dwc_sc.dma_addr[channel as usize]; + // let buffer = endpoint.buffer; // let buffer_length = device.last_transfer; // unsafe { @@ -146,14 +146,16 @@ pub fn finish_bulk_endpoint_callback_in( return true; } -pub fn finish_bulk_endpoint_callback_out( - endpoint: endpoint_descriptor, - hcint: u32, - channel: u8, -) -> bool { +pub fn finish_bulk_endpoint_callback_out(endpoint: endpoint_descriptor, hcint: u32, channel: u8, _split_control: DWCSplitControlState) -> bool { let device = unsafe { &mut *endpoint.device }; let transfer_size = HcdUpdateTransferSize(device, channel); - let last_transfer = endpoint.buffer_length - transfer_size; + if transfer_size > endpoint.buffer_length { + println!( + "| Endpoint {}: transfer size {} is greater than buffer length {} in bulk out", + channel, transfer_size, endpoint.buffer_length + ); + } + let last_transfer = endpoint.buffer_length - transfer_size; println!( "Bulk out transfer hcint {:x} , last transfer: {} ", @@ -184,18 +186,15 @@ pub fn finish_bulk_endpoint_callback_out( endpoint.device_endpoint_number ); } - + // device.last_transfer = last_transfer; return true; } -pub fn finish_interrupt_endpoint_callback( - endpoint: endpoint_descriptor, - hcint_: u32, - channel: u8, -) -> bool { - let mut hcint = hcint_; +pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: u32, channel: u8, split_control: DWCSplitControlState) -> bool { + let hcint = hcint_; let device = unsafe { &mut *endpoint.device }; let transfer_size = HcdUpdateTransferSize(device, channel); + // device.last_transfer = endpoint.buffer_length - transfer_size; let last_transfer = endpoint.buffer_length - transfer_size; let endpoint_device = device.driver_data.downcast::().unwrap(); @@ -205,6 +204,11 @@ pub fn finish_interrupt_endpoint_callback( let dma_addr = dwc_sc.dma_addr[channel as usize]; if hcint & HCINT_CHHLTD == 0 { + let hcchar = dwc_otg::read_volatile(DOTG_HCCHAR(channel as usize)); + panic!( + "| Endpoint {}: HCINT_CHHLTD not set, aborting. hcint: {:x} hcchar: {:x} finish_interrupt_endpoint_callback", + channel, hcint, hcchar + ); let mut i = 0; let mut hcint_nochhltd = 0; while i < 50 { @@ -227,19 +231,167 @@ pub fn finish_interrupt_endpoint_callback( } hcint |= hcint_nochhltd; + + return true; } - let buffer_length = last_transfer.clamp(0, 8); - let mut buffer = Box::new_uninit_slice(buffer_length as usize); + let split_control_state = split_control.state; + let ss_hfnum = split_control.ss_hfnum; + if split_control_state == DWCSplitStateMachine::SSPLIT { + if hcint & HCINT_NAK != 0 { + println!("| Endpoint SSPLIT {}: NAK received hcint {:x}", channel, hcint); + DwcEnableChannel(channel); + return false; + } else if hcint & HCINT_FRMOVRUN != 0 { + println!("| Endpoint SSPLIT {}: Frame overrun hcint {:x}", channel, hcint); + UpdateDwcOddFrame(channel); + return false; + } else if hcint & HCINT_XACTERR != 0 { + println!("| Endpoint SSPLIT {}: XACTERR received hcint {:x}", channel, hcint); + DwcEnableChannel(channel); + return false; + } else if hcint & HCINT_ACK != 0 { + //ACK received + unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = DWCSplitStateMachine::CSPLIT; + } + let mut cur_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + let mut succeed = false; + + while !succeed { + while DwcFrameDifference(cur_frame, ss_hfnum) < 2 { + cur_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + micro_delay(10); + } + + unsafe { + let mut frame_val = NEXT_FRAME_CS.lock(); + let current_current_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + if *frame_val == current_current_frame { + //not succeed + } else { + succeed = true; + *frame_val = current_current_frame; + } + } + micro_delay(10); + } + let frame = DwcActivateCsplit(channel); + unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].mr_cs_hfnum = frame; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries = 1; + } + return false; + } else { + // println!("| Endpoint {}: UNKNOWWN HCINT split_control is SSPLIT hcint {:x}", channel, hcint); + return true; + } + } else if split_control_state == DWCSplitStateMachine::CSPLIT { + if hcint & HCINT_NAK != 0 { + // println!("| Endpoint CSPLIT {}: NAK received hcint {:x}", channel, hcint); + } else if hcint & HCINT_FRMOVRUN != 0 { + println!("| Endpoint CSPLIT {}: Frame overrun hcint {:x}", channel, hcint); + UpdateDwcOddFrame(channel); + return false; + } else if hcint & HCINT_XACTERR != 0 { + println!("| Endpoint CSPLIT {}: XACTERR received hcint {:x}", channel, hcint); + DwcEnableChannel(channel); + return false; + } else if hcint & HCINT_NYET != 0 { + let mut cur_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + + if DwcFrameDifference(cur_frame, ss_hfnum) >= 8 { + // println!("| Endpoint CSPLIT {} has exceeded 8 frames, cur_frame: {} ss_hfnum: {} giving up tries {}", channel, cur_frame, ss_hfnum, unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries }); + return true; + } + + if unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries >= 3} { + let hctsiz = dwc_otg::read_volatile(DOTG_HCTSIZ(channel as usize)); + // println!("| Endpoint CSPLIT {} has exceeded 3 tries, giving up hctsiz {:x} last transfer {:x} state {:?}", channel, hctsiz, last_transfer, unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize] }); + return true; + } + + let mr_cs_hfnum = unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].mr_cs_hfnum + }; + + let mut succeed = false; + + while !succeed { + while cur_frame == mr_cs_hfnum { + cur_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + micro_delay(10); + } + + unsafe { + let mut frame_val = NEXT_FRAME_CS.lock(); + let current_current_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + if *frame_val == current_current_frame { + //not succeed + } else { + succeed = true; + *frame_val = current_current_frame; + } + } + micro_delay(10); + } + + if DwcFrameDifference(cur_frame, ss_hfnum) >= 8 { + println!("| Endpoint CSPLIT {} has exceeded 8 frames (2), cur_frame: {} ss_hfnum: {} giving up tries {}", channel, cur_frame, ss_hfnum, unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries }); + return true; + } + + let frame = DwcEnableChannel(channel); + unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].mr_cs_hfnum = frame; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries += 1; + } + return false; + } else { + unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = DWCSplitStateMachine::NONE; + } + + if hcint & HCINT_ACK == 0 { + let hctsiz = dwc_otg::read_volatile(DOTG_HCTSIZ(channel as usize)); + println!("| Endpoint CSPLIT {}: hcint {:x} last transfer {:x} hctisiz {:x}", channel, hcint, last_transfer, hctsiz); + + // use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_GINTSTS; + // let gintsts = read_volatile(DOTG_GINTSTS); + // use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; + // let hcint = read_volatile(DOTG_HCINT(channel as usize)); + // use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCCHAR; + // let hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + // let hctsiz = read_volatile(DOTG_HCTSIZ(channel as usize)); + + // println!("| HCD gintsts: {:#x}", gintsts); + // println!("| HCD hcint: {:#x}", hcint); + // println!("| HCD hcchar: {:#x}", hcchar); + // println!("| HCD hctsiz: {:#x}", hctsiz); + // println!("| HCD channel: {:#x}\n", channel); + } + } + } + + let mut buffer_length = last_transfer.clamp(0, 8); + if hcint & HCINT_ACK != 0 { endpoint_device.endpoint_pid[endpoint.device_endpoint_number as usize] += 1; + + if last_transfer == 0 { + // if endpoint.buffer_length == 0 && transfer_size == 0 { + buffer_length = 8; + println!("| Endpoint {}: ACK received, but endpoint buffer is 0, weird. buffer len {} transfer siz {}", channel, endpoint.buffer_length, transfer_size); + + // } + } } - + + let mut buffer = Box::new_uninit_slice(buffer_length as usize); if hcint & HCINT_NAK != 0 { //NAK received, do nothing // assert_eq!(buffer_length, 0); - // println!("| Interrupt Endpoint {}: HCINT_NAK received hcint: {:x}.", channel, hcint); } else if hcint & HCINT_XFERCOMPL != 0 { //Transfer complete //copy from dma_addr to buffer @@ -256,11 +408,8 @@ pub fn finish_interrupt_endpoint_callback( return false; } else { - println!( - "| Endpoint {}: Unknown interrupt, ignoring {}.", - channel, hcint - ); - return true; + println!("| Endpoint {}: Unknown interrupt, ignoring {:x} state {:#?}. Letting run for now...", channel, hcint, split_control); + // return true; } let mut buffer = unsafe { buffer.assume_init() }; @@ -273,6 +422,8 @@ pub fn finish_interrupt_endpoint_callback( endpoint.device_endpoint_number ); } + + // device.last_transfer = last_transfer; return true; } @@ -294,7 +445,7 @@ pub fn interrupt_endpoint_callback(endpoint: endpoint_descriptor) { } else { PacketId::Data1 }; - + let result = unsafe { UsbSendInterruptMessage( device, @@ -338,8 +489,39 @@ pub fn register_interrupt_endpoint( spawn_async_rt(async move { let μs = endpoint_time as u64 * 1000; let mut interval = interval(μs).with_missed_tick_behavior(MissedTicks::Skip); + println!("| USB: Starting interrupt endpoint with interval {} μs", μs); + + let hf1 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; + let hf1_time = get_time(); + let mut hf2 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; + let mut hf2_time = get_time(); + while hf1 == hf2 { + hf2 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; + hf2_time = get_time(); + } + let mut hf3 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; + let mut hf3_time = get_time(); + while hf2 == hf3 { + hf3 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; + hf3_time = get_time(); + } + let mut hf4 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; + let mut hf4_time = get_time(); + while hf3 == hf4 { + hf4 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; + hf4_time = get_time(); + } + println!("| USB: HFNUM: {} {} {} {} {} {} {} {}", hf1, hf1_time, hf2, hf2_time, hf3, hf3_time, hf4, hf4_time); + + let mut prev_time = get_time(); while interval.tick().await { - interrupt_endpoint_callback(endpoint); + let cur_time = get_time(); + if cur_time - prev_time < μs { + + } else { + interrupt_endpoint_callback(endpoint); + } + prev_time = cur_time; } }); } diff --git a/crates/kernel/src/device/usb/usbd/request.rs b/crates/kernel/src/device/usb/usbd/request.rs index 3308e94f..740b83b1 100644 --- a/crates/kernel/src/device/usb/usbd/request.rs +++ b/crates/kernel/src/device/usb/usbd/request.rs @@ -38,6 +38,7 @@ pub enum UsbDeviceRequestRequest { GetStatus = 0, ClearFeature = 1, SetFeature = 3, + Command4 = 4, SetAddress = 5, GetDescriptor = 6, SetDescriptor = 7, @@ -62,6 +63,26 @@ pub enum UsbDeviceRequestRequest { GetLineCoding = 0x21, SetControlLineState = 0x22, SendBreak = 0x23, + Command129 = 129, +} + +pub fn command_to_usb_device_request( + cmd: u8, +) -> UsbDeviceRequestRequest { + match cmd { + 0x00 => UsbDeviceRequestRequest::GetStatus, + 0x01 => UsbDeviceRequestRequest::ClearFeature, + 0x02 => UsbDeviceRequestRequest::GetIdle, + 0x03 => UsbDeviceRequestRequest::SetFeature, + 0x04 => UsbDeviceRequestRequest::Command4, + 0x05 => UsbDeviceRequestRequest::SetAddress, + 0x06 => UsbDeviceRequestRequest::GetDescriptor, + 0x07 => UsbDeviceRequestRequest::SetDescriptor, + 0x08 => UsbDeviceRequestRequest::GetConfiguration, + 0x09 => UsbDeviceRequestRequest::SetConfiguration, + 129 => UsbDeviceRequestRequest::Command129, + _ => panic!("| USBDEVICE REQUEST cmd {} not implemented", cmd), + } } impl Default for UsbDeviceRequestRequest { diff --git a/crates/kernel/src/device/usb/usbd/transfer.rs b/crates/kernel/src/device/usb/usbd/transfer.rs index 283d1ab7..1d264b10 100644 --- a/crates/kernel/src/device/usb/usbd/transfer.rs +++ b/crates/kernel/src/device/usb/usbd/transfer.rs @@ -11,6 +11,7 @@ use crate::device::usb::types::UsbTransfer; use crate::device::usb::usbd::pipe::UsbPipeAddress; use crate::ringbuffer::SpscRingBuffer; use crate::sync::InterruptSpinLock; +use crate::device::usb::DWCSplitControlState; use alloc::boxed::Box; use super::endpoint::*; @@ -70,7 +71,7 @@ pub struct UsbXfer { pub endpoint_descriptor: endpoint_descriptor, pub buffer: Option>, pub buffer_length: u32, - pub callback: Option bool>, + pub callback: Option bool>, pub packet_id: PacketId, pub pipe: UsbPipeAddress, } diff --git a/crates/kernel/src/device/usb/usbd/usbd.rs b/crates/kernel/src/device/usb/usbd/usbd.rs index e0f0b575..ad59f821 100644 --- a/crates/kernel/src/device/usb/usbd/usbd.rs +++ b/crates/kernel/src/device/usb/usbd/usbd.rs @@ -165,7 +165,7 @@ pub unsafe fn UsbSendInterruptMessage( buffer_length: u32, packet_id: PacketId, _timeout_: u32, - callback: fn(endpoint_descriptor, u32, u8) -> bool, + callback: fn(endpoint_descriptor, u32, u8, DWCSplitControlState) -> bool, endpoint: endpoint_descriptor, ) -> ResultCode { let b = Box::new(UsbXfer { @@ -212,6 +212,10 @@ pub unsafe fn UsbInterruptMessage( Some(usb_xfer.endpoint_descriptor); } + if usb_xfer.buffer_length != 8 { + println!("| USBD: Buffer length is at {} bytes", usb_xfer.buffer_length); + } + let result = unsafe { HcdSubmitInterruptMessage( device, @@ -457,6 +461,8 @@ fn UsbSetConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { return ResultCode::ErrorDevice; } + println!("| USBD: Setting device configuration to {}", configuration); + let result = unsafe { UsbControlMessage( device, @@ -499,7 +505,7 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { println!("| USBD: Device not in addressed state"); return ResultCode::ErrorDevice; } - + println!("| USBD: Configuring device {}", device.number); let configuration_ptr = &mut device.configuration as *mut UsbConfigurationDescriptor as *mut u8; let mut result = unsafe { UsbGetDescriptor( @@ -518,6 +524,8 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { return result; } + println!("| USBD: Configuration descriptor: {:?}", device.configuration); + // let configuration_dev = &mut device.configuration; // println!( // "| USBD: Configuration descriptor:\n {:#?}", @@ -552,6 +560,8 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { return result; } + println!("| USBD: Full configuration descriptor: {:?}", fullDescriptor as *mut UsbConfigurationDescriptor); + device.configuration_index = configuration; configuration_val = device.configuration.configuration_value; @@ -562,10 +572,12 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { let end = (fullDescriptor as usize) + device.configuration.total_length as usize; header = unsafe { header.byte_add((*header).descriptor_length as usize) }; while (header as usize) < end { + println!("| USBD: Reading header {:x} end {:x}", header as usize, end); unsafe { match (*header).descriptor_type { DescriptorType::Interface => { let interface = header as *mut UsbInterfaceDescriptor; + println!("| USBD: Interface descriptor: {:?}", interface); if last_interface != (*interface).number as usize { last_interface = (*interface).number as usize; memory_copy( @@ -574,33 +586,39 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { interface as *const u8, size_of::(), ); + println!("| USBD: Interface descriptor: {:?}", device.interfaces[last_interface]); last_endpoint = 0; is_alternate = false; } else { + println!("| USBD: Setting alternate interface"); is_alternate = true; } } DescriptorType::Endpoint => { if is_alternate { - continue; - } - if last_interface == MAX_INTERFACES_PER_DEVICE - || last_endpoint - >= device.interfaces[last_interface].endpoint_count as usize - { - println!("| USBD: Unexpected endpoint descriptor interface"); - return ResultCode::ErrorDevice; + println!("| USBD: Skipping alternate interface endpoint"); + } else { + if last_interface == MAX_INTERFACES_PER_DEVICE + || last_endpoint + >= device.interfaces[last_interface].endpoint_count as usize + { + println!("| USBD: Unexpected endpoint descriptor interface"); + return ResultCode::ErrorDevice; + } + let endpoint = header as *mut UsbEndpointDescriptor; + + memory_copy( + &mut device.endpoints[last_interface][last_endpoint] + as *mut UsbEndpointDescriptor as *mut u8, + endpoint as *const u8, + size_of::(), + ); + println!("| USBD: Endpoint descriptor: {:?}", device.endpoints[last_interface][last_endpoint]); + last_endpoint += 1; } - let endpoint = header as *mut UsbEndpointDescriptor; - memory_copy( - &mut device.endpoints[last_interface][last_endpoint] - as *mut UsbEndpointDescriptor as *mut u8, - endpoint as *const u8, - size_of::(), - ); - last_endpoint += 1; } _ => { + println!("| USBD: Unknown descriptor type"); if (*header).descriptor_length == 0 { break; } @@ -610,6 +628,7 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { } } + println!("| USBD: Finish reading header"); result = UsbSetConfigure(device, configuration_val); if result != ResultCode::OK { @@ -710,6 +729,19 @@ pub fn UsbAttachDevice(device: &mut UsbDevice) -> ResultCode { println!("| USBD: No class attach handler"); shutdown(); } + } else if device.interfaces[0].class == InterfaceClass::InterfaceClassVendorSpecific { + println!("| USBD: Vendor specific device"); + + if device.descriptor.vendor_id == 0xB95 && device.descriptor.product_id == 0x1790 { + println!("| USBD: Net: AX88179 Detected"); + let class_attach = bus.interface_class_attach[InterfaceClass::InterfaceClassCommunications as usize]; + let result = class_attach.unwrap()(device, 0); + if result != ResultCode::OK { + println!("| USBD: Class attach handler failed"); + return result; + } + } + } else { println!("| USBD: Invalid interface class"); } @@ -776,6 +808,7 @@ fn UsbAttachRootHub(bus: &mut UsbBus) -> ResultCode { } bus.devices[0].as_mut().unwrap().status = UsbDeviceStatus::Powered; + bus.devices[0].as_mut().unwrap().speed = UsbSpeed::High; return UsbAttachDevice(&mut (bus.devices[0].as_mut().unwrap())); } diff --git a/crates/kernel/src/networking/iface/ethernet.rs b/crates/kernel/src/networking/iface/ethernet.rs index 80d011e6..255d7c2f 100644 --- a/crates/kernel/src/networking/iface/ethernet.rs +++ b/crates/kernel/src/networking/iface/ethernet.rs @@ -2,7 +2,7 @@ use crate::networking::iface::{arp, ipv4, Interface}; use crate::networking::repr::{EthernetAddress, EthernetFrame, EthernetType}; use crate::networking::{Error, Result}; -use crate::device::usb::device::net::NET_DEVICE; +use crate::device::usb::device::net::{NetInitiateReceive, NET_DEVICE}; use crate::device::usb::device::rndis::rndis_receive_packet; use crate::event::thread; From 13b7590f0fe37b4464db8ad5ba2a77328cc24d02 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Mon, 28 Apr 2025 00:06:11 -0500 Subject: [PATCH 07/13] Updates to net --- crates/kernel/src/device/usb/device/net.rs | 42 +++++++++++++++------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/crates/kernel/src/device/usb/device/net.rs b/crates/kernel/src/device/usb/device/net.rs index 3a06ce90..278796ea 100644 --- a/crates/kernel/src/device/usb/device/net.rs +++ b/crates/kernel/src/device/usb/device/net.rs @@ -114,26 +114,42 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // 10, // ); + micro_delay(ms_to_micro(1500)); // Wait for 1.5 seconds + // We currently have this 1.5 second delay to wait for the device to be ready + // technically, we can wait for the interrupt in endpoint to tell us + // but laking ax88179 documentaiton, not sure which bits, so wait for now. + // 1. new network interface // 2. initialize mac address // 3. initalize and statically set ip address and gateway // 4. initialize arp table - let mac_addr: &mut [u8; 6]; - unsafe { - let mut b = vec![0u8; 30]; - let query = rndis_query_msg(device, OID::OID_802_3_PERMANENT_ADDRESS, b.as_mut_ptr(), 30); - - if query.0 != ResultCode::OK { - panic!("| Net: Error getting MAC address {:#?}", query.0); - } + let mut mac_addr: &mut [u8; 6] = &mut [0u8; 6]; - let b_offset = query.1; - let b_len = query.2; - if b_len != 6 { - panic!("| Net: Error getting MAC address {}", b_len); + if device.descriptor.vendor_id == 0xB95 && device.descriptor.product_id == 0x1790 { + mac_addr[0] = 0x54; + mac_addr[1] = 0x52; + mac_addr[2] = 0x00; + mac_addr[3] = 0x12; + mac_addr[4] = 0x34; + mac_addr[5] = 0x56; + // [0x54, 0x52, 0x00, 0x12, 0x34, 0x56]; + } else { + unsafe { + let mut b = vec![0u8; 30]; + let query = rndis_query_msg(device, OID::OID_802_3_PERMANENT_ADDRESS, b.as_mut_ptr(), 30); + + if query.0 != ResultCode::OK { + panic!("| Net: Error getting MAC address {:#?}", query.0); + } + + let b_offset = query.1; + let b_len = query.2; + if b_len != 6 { + panic!("| Net: Error getting MAC address {}", b_len); + } + mac_addr = &mut *(b.as_mut_ptr().offset(b_offset as isize) as *mut [u8; 6]); } - mac_addr = &mut *(b.as_mut_ptr().offset(b_offset as isize) as *mut [u8; 6]); } println!("| Net: MAC Address: {:x?}", mac_addr); From a0de86dd43bbb0a9880e9571ad00ffea9ff19307 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Mon, 28 Apr 2025 00:13:07 -0500 Subject: [PATCH 08/13] Uart sleep --- crates/kernel/src/device/uart.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/kernel/src/device/uart.rs b/crates/kernel/src/device/uart.rs index fbf6a5a3..b037cf8d 100644 --- a/crates/kernel/src/device/uart.rs +++ b/crates/kernel/src/device/uart.rs @@ -141,7 +141,9 @@ impl UARTInner { // console.render(); // } // drop(console); - // spin_sleep(3000); + use crate::sync::spin_sleep; + + spin_sleep(3000); // } } } From 9a3c99026f8e5803f87b8df0a30ba1f6946d7bbb Mon Sep 17 00:00:00 2001 From: Alex Meyer Date: Mon, 28 Apr 2025 00:18:23 -0500 Subject: [PATCH 09/13] Re-enable prints in mini UART --- crates/kernel/src/device/bcm2835_aux.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/kernel/src/device/bcm2835_aux.rs b/crates/kernel/src/device/bcm2835_aux.rs index 26b367bb..f597487a 100644 --- a/crates/kernel/src/device/bcm2835_aux.rs +++ b/crates/kernel/src/device/bcm2835_aux.rs @@ -223,7 +223,7 @@ impl MiniUart { // console.render(); // } // drop(console); - // crate::sync::spin_sleep(3000); + crate::sync::spin_sleep(3000); // } } } From 7abeb006bc846fa688647bd5253c529ee0d93e82 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Mon, 28 Apr 2025 00:29:35 -0500 Subject: [PATCH 10/13] Fixing fallback of USB->Net error flow --- crates/kernel/src/device/usb/device/net.rs | 44 ++++++++++--------- .../kernel/src/device/usb/hcd/dwc/dwc_otg.rs | 2 +- .../kernel/src/networking/iface/ethernet.rs | 18 +++----- 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/crates/kernel/src/device/usb/device/net.rs b/crates/kernel/src/device/usb/device/net.rs index 278796ea..a5c780b0 100644 --- a/crates/kernel/src/device/usb/device/net.rs +++ b/crates/kernel/src/device/usb/device/net.rs @@ -34,6 +34,7 @@ pub static mut NET_DEVICE: NetDevice = NetDevice { device: None, net_send: None, net_receive: None, + truncation: 0, }; pub static mut INTERFACE: Option = None; @@ -69,6 +70,7 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { unsafe { NET_DEVICE.net_send = Some(axge_send_packet); NET_DEVICE.net_receive = Some(axge_receive_packet); + NET_DEVICE.truncation = 8; } } else { @@ -78,6 +80,7 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { unsafe { NET_DEVICE.net_send = Some(rndis_send_packet); NET_DEVICE.net_receive = Some(rndis_receive_packet); + NET_DEVICE.truncation = 44; } } @@ -98,21 +101,21 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // device.endpoints[interface_number as usize][0 as usize].interval // ); - // register_interrupt_endpoint( - // device, - // device.endpoints[interface_number as usize][0 as usize].interval as u32, - // endpoint_address_to_num( - // device.endpoints[interface_number as usize][0 as usize].endpoint_address, - // ), - // UsbDirection::In, - // size_from_number( - // device.endpoints[interface_number as usize][0 as usize] - // .packet - // .MaxSize as u32, - // ), - // 0, - // 10, - // ); + register_interrupt_endpoint( + device, + device.endpoints[interface_number as usize][0 as usize].interval as u32, + endpoint_address_to_num( + device.endpoints[interface_number as usize][0 as usize].endpoint_address, + ), + UsbDirection::In, + size_from_number( + device.endpoints[interface_number as usize][0 as usize] + .packet + .MaxSize as u32, + ), + 0, + 10, + ); micro_delay(ms_to_micro(1500)); // Wait for 1.5 seconds // We currently have this 1.5 second delay to wait for the device to be ready @@ -173,10 +176,8 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // begin receieve series, this queues a receive to be ran which will eventually propogate back // to us through the rgistered `recv` function which then queues another receive - let buf = vec![0u8; 1600]; - unsafe { - NetInitiateReceive(buf.into_boxed_slice(), 1500); // TODO: ask aaron if I need to use another function? - } + let buf = vec![0u8; 1]; //TODO: Technically, the buffer doesn't matter anymore + NetInitiateReceive(buf.into_boxed_slice(), 1500); // TODO: ask aaron if I need to use another function? // start dhcp unsafe { @@ -191,6 +192,7 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { } pub fn NetInitiateReceive(buffer: Box<[u8]>, buffer_length: u32) { + println!("| Net: Initiate Receive"); unsafe { if let Some(receive_func) = NET_DEVICE.net_receive { let device = NET_DEVICE.device.unwrap(); @@ -219,7 +221,8 @@ pub unsafe fn recv(buf: *mut u8, buf_len: u32) { let slice: &[u8] = unsafe { slice::from_raw_parts(buf, buf_len as usize) }; let interface = get_interface_mut(); - let _ = ethernet::recv_ethernet_frame(interface, slice, buf_len); + let truncation = unsafe { NET_DEVICE.truncation }; + let _ = ethernet::recv_ethernet_frame(interface, slice, buf_len, truncation); } pub unsafe fn NetAnalyze(buffer: *mut u8, buffer_length: u32) { @@ -272,6 +275,7 @@ pub struct NetDevice { pub device: Option<*mut UsbDevice>, pub net_send: Option ResultCode>, pub net_receive: Option, u32) -> ResultCode>, + pub truncation: usize, } #[repr(u32)] diff --git a/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs index 802a511f..99d55212 100644 --- a/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs +++ b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs @@ -483,7 +483,7 @@ fn HcdChannelInterruptToError(device: &mut UsbDevice, hcint: u32, isComplete: bo return result; } -pub const RequestTimeout: u32 = 5000; +pub const RequestTimeout: u32 = 50000; pub fn HcdChannelSendWaitOne( device: &mut UsbDevice, diff --git a/crates/kernel/src/networking/iface/ethernet.rs b/crates/kernel/src/networking/iface/ethernet.rs index 255d7c2f..2ffb505e 100644 --- a/crates/kernel/src/networking/iface/ethernet.rs +++ b/crates/kernel/src/networking/iface/ethernet.rs @@ -35,12 +35,13 @@ pub fn send_ethernet_frame( // pub static mut LEFT: u32 = 0; // recv ethernet frame from interface: parsed -> fwd to socket -> propogated up stack -pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u32) -> Result<()> { - // println!("[!] received ethernet frame"); +pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u32, truncation: usize) -> Result<()> { + println!("[!] received ethernet frame"); // println!("\t{:x?}", ð_buffer[44..]); // we will truncate the first 44 bytes from the RNDIS protocol - let eth_frame = EthernetFrame::deserialize(ð_buffer[44..])?; + // will also need to truncate the first 8 for AX88179 + let eth_frame = EthernetFrame::deserialize(ð_buffer[truncation..])?; // if this frame is not broadcast/multicast or to us, ignore it if eth_frame.dst != interface.ethernet_addr @@ -55,15 +56,6 @@ pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u EthernetType::IPV4 => ipv4::recv_ip_packet(interface, eth_frame), _ => Err(Error::Ignored), }; - - // queue another recv to be run in the future - // thread::thread(move || { - // let buf = vec![0u8; 1500]; - // unsafe { - // let device = &mut *NET_DEVICE.device.unwrap(); - - // } - // }); - + return result; } From e98e9f1d9236cffd6e278a3feef0fa06b2b8d024 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Mon, 28 Apr 2025 03:46:54 -0500 Subject: [PATCH 11/13] AX88179 Hardware Fixing --- crates/kernel/scripts/attach-serial.sh | 2 +- crates/kernel/scripts/run-usb.sh | 2 +- crates/kernel/scripts/test_socket.py | 22 + crates/kernel/src/device/usb.rs | 1 - crates/kernel/src/device/usb/device.rs | 2 +- .../kernel/src/device/usb/device/ax88179.rs | 759 +++++++++++------- crates/kernel/src/device/usb/device/hid.rs | 1 + crates/kernel/src/device/usb/device/net.rs | 70 +- .../kernel/src/device/usb/hcd/dwc/dwc_otg.rs | 207 +++-- .../kernel/src/device/usb/hcd/dwc/roothub.rs | 6 +- crates/kernel/src/device/usb/usbd/endpoint.rs | 307 +++---- crates/kernel/src/device/usb/usbd/request.rs | 4 +- crates/kernel/src/device/usb/usbd/transfer.rs | 2 +- crates/kernel/src/device/usb/usbd/usbd.rs | 36 +- crates/kernel/src/networking/iface/cdcecm.rs | 12 +- .../kernel/src/networking/iface/ethernet.rs | 22 +- crates/shell/src/bin/ping.rs | 19 + 17 files changed, 903 insertions(+), 571 deletions(-) create mode 100644 crates/kernel/scripts/test_socket.py create mode 100644 crates/shell/src/bin/ping.rs diff --git a/crates/kernel/scripts/attach-serial.sh b/crates/kernel/scripts/attach-serial.sh index 83fe5f7d..4c957e67 100755 --- a/crates/kernel/scripts/attach-serial.sh +++ b/crates/kernel/scripts/attach-serial.sh @@ -1,4 +1,4 @@ -SERIAL_DEV=/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_B0044ASI-if00-port0 +SERIAL_DEV=/dev/tty.usbserial-B0044ASI LOGFILE=log/$(date -Is).log echo "Logging to $LOGFILE" tio "$SERIAL_DEV" -b 115200 -d 8 -s 1 -p none -f none -m INLCRNL -L --log-file="$LOGFILE" diff --git a/crates/kernel/scripts/run-usb.sh b/crates/kernel/scripts/run-usb.sh index c222948a..004151ff 100755 --- a/crates/kernel/scripts/run-usb.sh +++ b/crates/kernel/scripts/run-usb.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -ex -QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev bridge,id=net0,br=br0 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" diff --git a/crates/kernel/scripts/test_socket.py b/crates/kernel/scripts/test_socket.py new file mode 100644 index 00000000..1e57a0ce --- /dev/null +++ b/crates/kernel/scripts/test_socket.py @@ -0,0 +1,22 @@ +import socket + +# TCP configuration +host = '127.0.0.1' # Localhost IP +port = 2222 # Port to send the packet to + +# Message to send +message = b'cowscowscows' + +# Create a TCP socket +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +# Connect to the server +sock.connect((host, port)) + +# Send the message to the server +sock.sendall(message) + +# Close the socket +sock.close() + +print(f"Message sent to {host}:{port}") \ No newline at end of file diff --git a/crates/kernel/src/device/usb.rs b/crates/kernel/src/device/usb.rs index e1ea44fb..37b37344 100644 --- a/crates/kernel/src/device/usb.rs +++ b/crates/kernel/src/device/usb.rs @@ -9,7 +9,6 @@ pub mod usbd; pub use device::hid::keyboard; pub use device::hid::mouse; -use device::net::NetSendPacket; use device::net::RegisterNetReceiveCallback; use alloc::boxed::Box; diff --git a/crates/kernel/src/device/usb/device.rs b/crates/kernel/src/device/usb/device.rs index 48e17726..06ef0d6f 100644 --- a/crates/kernel/src/device/usb/device.rs +++ b/crates/kernel/src/device/usb/device.rs @@ -1,5 +1,5 @@ +pub mod ax88179; pub mod hid; pub mod hub; pub mod net; pub mod rndis; -pub mod ax88179; \ No newline at end of file diff --git a/crates/kernel/src/device/usb/device/ax88179.rs b/crates/kernel/src/device/usb/device/ax88179.rs index 5a52f72f..130979cd 100644 --- a/crates/kernel/src/device/usb/device/ax88179.rs +++ b/crates/kernel/src/device/usb/device/ax88179.rs @@ -1,16 +1,13 @@ -use core::result; - use crate::device::system_timer::micro_delay; use crate::device::usb::hcd::dwc::dwc_otg::ms_to_micro; use crate::device::usb::types::*; use crate::device::usb::usbd::device::*; +use crate::device::usb::usbd::endpoint::UsbEndpointDevice; use crate::device::usb::usbd::pipe::*; use crate::device::usb::usbd::request::*; use crate::device::usb::usbd::usbd::UsbSendBulkMessage; -use crate::device::usb::UsbControlMessage; -use crate::device::usb::usbd::endpoint::UsbEndpointDevice; -use crate::device::usb::device::net::*; use crate::device::usb::PacketId; +use crate::device::usb::UsbControlMessage; use alloc::boxed::Box; use alloc::vec; @@ -19,10 +16,10 @@ use alloc::vec; * usb/device/ax88179.rs * By Aaron Lo * Based off the freeBSD driver if_axge.c - */ + */ //https://elixir.bootlin.com/freebsd/v14.2/source/sys/dev/usb/net/if_axge.c -const MAC_ADDRESS: [u8; 6] = [0x54, 0x52, 0x00, 0x12, 0x34, 0x56]; // TODO: TBD / make this dynamic +// const MAC_ADDRESS: [u8; 6] = [0x54, 0x52, 0x00, 0x12, 0x34, 0x56]; // TODO: TBD / make this dynamic pub unsafe fn axge_send_packet( device: &mut UsbDevice, @@ -32,9 +29,9 @@ pub unsafe fn axge_send_packet( let size = 8 + buffer_length; let mut buf = vec![0u8; size as usize]; - - let mut tx_hdr1 = buffer_length as u32; - let mut tx_hdr2 = 0u32; + + let tx_hdr1 = buffer_length as u32; + let tx_hdr2 = 0u32; // if (tx_hdr1 //don't need padding let b1 = tx_hdr1.to_le_bytes(); @@ -42,7 +39,6 @@ pub unsafe fn axge_send_packet( buf[0..4].copy_from_slice(&b1); buf[4..8].copy_from_slice(&b2); - unsafe { core::ptr::copy_nonoverlapping(buffer, buf.as_mut_ptr().add(8), buffer_length as usize); } @@ -72,7 +68,7 @@ pub unsafe fn axge_send_packet( size, pid, 1, //TODO: Check this - 10 + 10, ) }; @@ -128,42 +124,53 @@ pub unsafe fn axge_receive_packet( } pub fn axge_init(device: &mut UsbDevice) -> ResultCode { - axge_stop(device); - axge_reset(device); + axge_reset(device); println!("| AXGE: Initializing device"); - axge_write_mem(device, AXGE_ACCESS_MAC, ETHER_ADDR_LEN as u16, AXGE_NIDR as u16, - MAC_ADDRESS.as_mut_ptr(), ETHER_ADDR_LEN as u32); - - axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_PWLLR, 0x34); - axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_PWLHR, 0x52); + let mut MAC_ADDRESS: [u8; 6] = [0x54, 0x52, 0x00, 0x12, 0x34, 0x56]; // TODO: TBD / make this dynamic + axge_write_mem( + device, + AXGE_ACCESS_MAC, + ETHER_ADDR_LEN as u16, + AXGE_NIDR as u16, + MAC_ADDRESS.as_mut_ptr(), + ETHER_ADDR_LEN as u32, + ); + + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_PWLLR, 0x34); + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_PWLHR, 0x52); axge_csum_cfg(device); axge_rxfilter(device); /* - * XXX - * Controller supports wakeup on link change detection, - * magic packet and wakeup frame recpetion. But it seems - * there is no framework for USB ethernet suspend/wakeup. - * Disable all wakeup functions. - */ + * XXX + * Controller supports wakeup on link change detection, + * magic packet and wakeup frame recpetion. But it seems + * there is no framework for USB ethernet suspend/wakeup. + * Disable all wakeup functions. + */ println!("| AXGE: Disabling wakeup functions"); - axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_MMSR as u16, 0); - axge_read_cmd_1(device, AXGE_ACCESS_MAC, AXGE_MMSR as u16); + axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_MMSR as u16, 0); + axge_read_cmd_1(device, AXGE_ACCESS_MAC, AXGE_MMSR as u16); - /* Configure default medium type. */ + /* Configure default medium type. */ println!("| AXGE: Configuring default medium type"); - axge_write_cmd_2(device, AXGE_ACCESS_MAC, 2, AXGE_MSR, MSR_GM | MSR_FD | - MSR_RFC | MSR_TFC | MSR_RE); + axge_write_cmd_2( + device, + AXGE_ACCESS_MAC, + 2, + AXGE_MSR, + MSR_GM | MSR_FD | MSR_RFC | MSR_TFC | MSR_RE, + ); // usbd_xfer_set_stall(sc->sc_xfer[AXGE_BULK_DT_WR]); - // if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); - // /* Switch to selected media. */ - // axge_ifmedia_upd(ifp); + // if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); + // /* Switch to selected media. */ + // axge_ifmedia_upd(ifp); // TODO: This is reseting the phy -> need to look into if thigns go wrong WARNING //This is my attempt at htis from gpt code -> no clue if it works @@ -172,7 +179,7 @@ pub fn axge_init(device: &mut UsbDevice) -> ResultCode { println!("| AXGE: Resetting PHY"); // axge_write_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR, BMCR_RESET); - + // let mut val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR); // while val & BMCR_RESET != 0 { // micro_delay(ms_to_micro(10)); @@ -181,18 +188,17 @@ pub fn axge_init(device: &mut UsbDevice) -> ResultCode { // axge_write_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR, BMCR_RESET); - // let mut val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR); // while val & BMCR_RESET != 0 { // micro_delay(ms_to_micro(10)); - // val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR); + // val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, 2, PHY_BMCR); // } // let mut reg = BMCR_RESET; // axge_miibus_writereg(device, 3, MII_BMCR, reg); - // //wait 100 ms for it t ocomplete + // //wait 100 ms for it t ocomplete // for _ in 0..100 { // reg = axge_miibus_readreg(device, 3, MII_BMCR); // if reg & BMCR_RESET == 0 { @@ -210,8 +216,14 @@ pub fn axge_init(device: &mut UsbDevice) -> ResultCode { println!("| AXGE: PHY reset complete"); let mut rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE) | AX_RX_CTL_PRO; - ax88179_write_cmd(device, AX_ACCESS_MAC, AX_RX_CTL, - 2, 2, &mut rxctl as *mut u16 as *mut u8); + ax88179_write_cmd( + device, + AX_ACCESS_MAC, + AX_RX_CTL, + 2, + 2, + &mut rxctl as *mut u16 as *mut u8, + ); println!("| AXGE: multicast mode set"); @@ -228,7 +240,7 @@ pub fn ax88179_led_setting(device: &mut UsbDevice) { println!("| AXGE: Setting LED settings"); // ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, // GMII_PHY_PAGE_SELECT, 2, &tmp); - axge_write_cmd_2(device, AXGE_ACCESS_PHY, GMII_PHY_PGSEL_EXT,3, tmp); + axge_write_cmd_2(device, AXGE_ACCESS_PHY, GMII_PHY_PGSEL_EXT, 3, tmp); tmp = 0x2c; axge_write_cmd_2(device, AXGE_ACCESS_PHY, GMII_PHYPAGE as u16, 3, tmp); @@ -237,7 +249,7 @@ pub fn ax88179_led_setting(device: &mut UsbDevice) { let mut ledlink = axge_read_cmd_2(device, AXGE_ACCESS_PHY, GMII_LED_LINK as u16, 3); ledact &= GMII_LED_ACTIVE_MASK; - ledlink &= GMII_LED_LINK_MASK; + ledlink &= GMII_LED_LINK_MASK; ledact |= GMII_LED0_ACTIVE | GMII_LED1_ACTIVE | GMII_LED2_ACTIVE; ledlink |= GMII_LED0_LINK_10 | GMII_LED1_LINK_100 | GMII_LED2_LINK_1000; @@ -255,7 +267,6 @@ pub fn ax88179_led_setting(device: &mut UsbDevice) { println!("| AXGE: LED settings complete"); } - pub fn axge_miibus_readreg(device: &mut UsbDevice, phy: u16, reg: u16) -> u16 { let val = axge_read_cmd_2(device, AXGE_ACCESS_PHY, reg, phy); return val; @@ -268,8 +279,18 @@ pub fn axge_miibus_writereg(device: &mut UsbDevice, phy: u16, reg: u16, val: u16 pub fn axge_csum_cfg(device: &mut UsbDevice) { // Enable checksum offload println!("| AXGE: Enabling checksum offload"); - axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_CRCR as u16, CRCR_IP | CRCR_TCP | CRCR_UDP); - axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_CTCR as u16, CRCR_IP | CRCR_TCP | CRCR_UDP); + axge_write_cmd_1( + device, + AXGE_ACCESS_MAC, + AXGE_CRCR as u16, + CRCR_IP | CRCR_TCP | CRCR_UDP, + ); + axge_write_cmd_1( + device, + AXGE_ACCESS_MAC, + AXGE_CTCR as u16, + CRCR_IP | CRCR_TCP | CRCR_UDP, + ); } pub fn axge_rxfilter(debice: &mut UsbDevice) { @@ -280,13 +301,17 @@ pub fn axge_rxfilter(debice: &mut UsbDevice) { } pub fn axge_chip_init(device: &mut UsbDevice) { - //power up ethernet phy axge_write_cmd_2(device, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, 0); axge_write_cmd_2(device, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, EPPRCR_IPRL); micro_delay(ms_to_micro(250)); - axge_write_cmd_1(device, AXGE_ACCESS_MAC, AXGE_CLK_SELECT as u16, AXGE_CLK_SELECT_ACS | AXGE_CLK_SELECT_BCS); + axge_write_cmd_1( + device, + AXGE_ACCESS_MAC, + AXGE_CLK_SELECT as u16, + AXGE_CLK_SELECT_ACS | AXGE_CLK_SELECT_BCS, + ); micro_delay(ms_to_micro(100)); axge_write_cmd_1(device, AXGE_FW_MODE, AXGE_FW_MODE_178A179, 0); @@ -328,8 +353,14 @@ fn axge_write_cmd_2(device: &mut UsbDevice, cmd: u8, index: u16, reg: u16, val: axge_write_mem(device, cmd, index, reg, &val as *const u16 as *mut u8, 2); } -fn axge_read_mem(device: &mut UsbDevice, cmd: u8, index: u16, val: u16, buf: *mut u8, len: u32) -> ResultCode { - +fn axge_read_mem( + device: &mut UsbDevice, + cmd: u8, + index: u16, + val: u16, + buf: *mut u8, + len: u32, +) -> ResultCode { let result = unsafe { UsbControlMessage( device, @@ -363,9 +394,14 @@ fn axge_read_mem(device: &mut UsbDevice, cmd: u8, index: u16, val: u16, buf: *mu return ResultCode::OK; } - -fn axge_write_mem(device: &mut UsbDevice, cmd: u8, index: u16, val: u16, buf: *mut u8, len: u32) -> ResultCode { - +fn axge_write_mem( + device: &mut UsbDevice, + cmd: u8, + index: u16, + val: u16, + buf: *mut u8, + len: u32, +) -> ResultCode { let result = unsafe { UsbControlMessage( device, @@ -401,43 +437,79 @@ fn axge_write_mem(device: &mut UsbDevice, cmd: u8, index: u16, val: u16, buf: *m pub fn ax88179_auto_detach(dev: &mut UsbDevice) { let mut tmp16: u16 = 0; - let mut tmp8: u8 = 0; + let mut tmp8: u8 = 0; - // if ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &mut tmp16 as *mut u16 as *mut u8) < 0 { - // return; + // if ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &mut tmp16 as *mut u16 as *mut u8) < 0 { + // return; // } - if ((tmp16 == 0xFFFF) || ((tmp16 & 0x0100) == 0)) { - return; - } - unsafe { - /* Enable Auto Detach bit */ - tmp8 = 0; - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT as u16, 1, 1, &mut tmp8 as *mut u8); - tmp8 |= AX_CLK_SELECT_ULR; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT as u16, 1, 1, &mut tmp8 as *mut u8); - - ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL as u16, 2, 2, &mut tmp16 as *mut u16 as *mut u8); - tmp16 |= AX_PHYPWR_RSTCTL_AT; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL as u16, 2, 2, &mut tmp16 as *mut u16 as *mut u8); + if (tmp16 == 0xFFFF) || ((tmp16 & 0x0100) == 0) { + return; } + /* Enable Auto Detach bit */ + ax88179_read_cmd( + dev, + AX_ACCESS_MAC, + AX_CLK_SELECT as u16, + 1, + 1, + &mut tmp8 as *mut u8, + ); + tmp8 |= AX_CLK_SELECT_ULR; + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_CLK_SELECT as u16, + 1, + 1, + &mut tmp8 as *mut u8, + ); + + ax88179_read_cmd( + dev, + AX_ACCESS_MAC, + AX_PHYPWR_RSTCTL as u16, + 2, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); + tmp16 |= AX_PHYPWR_RSTCTL_AT; + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_PHYPWR_RSTCTL as u16, + 2, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); } pub fn ax88179_reset(dev: &mut UsbDevice) { - let mut buf = [0u8; 6]; - let mut tmp16 = buf.as_mut_ptr() as *mut u16; - let mut tmp = buf.as_mut_ptr() as *mut u8; + let tmp16 = buf.as_mut_ptr() as *mut u16; + let tmp = buf.as_mut_ptr() as *mut u8; - - - /* Power up ethernet PHY */ + /* Power up ethernet PHY */ unsafe { *tmp16 = 0; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL as u16, 2, 2, tmp16 as *mut u8); + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_PHYPWR_RSTCTL as u16, + 2, + 2, + tmp16 as *mut u8, + ); *tmp16 = AX_PHYPWR_RSTCTL_IPRL; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL as u16, 2, 2, tmp16 as *mut u8); + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_PHYPWR_RSTCTL as u16, + 2, + 2, + tmp16 as *mut u8, + ); micro_delay(500); *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; @@ -450,13 +522,29 @@ pub fn ax88179_reset(dev: &mut UsbDevice) { /* Read MAC address from DTB or asix chip */ // ax88179_get_mac_addr(dev); // memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID as u16, 6, 6, - unsafe { MAC_ADDRESS.as_mut_ptr() }); + let mut MAC_ADDRESS: [u8; 6] = [0x54, 0x52, 0x00, 0x12, 0x34, 0x56]; // TODO: TBD / make this dynamic + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_NODE_ID as u16, + 6, + 6, + MAC_ADDRESS.as_mut_ptr(), + ); /* RX bulk configuration */ // memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); - let mut buf_tmp:[u8; 5] = [7, 0x4f, 0, 0x12, 0xff]; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL as u16, 5, 5, buf_tmp.as_mut_ptr()); + //{7, 0xae, 7, 0x18, 0xff} + // {7, 0xcc, 0x4c, 0x18, 8} + let mut buf_tmp: [u8; 5] = [7, 0xae, 7, 0x18, 0xff]; + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_RX_BULKIN_QCTRL as u16, + 5, + 5, + buf_tmp.as_mut_ptr(), + ); // dev->rx_urb_size = 1024 * 20; @@ -464,43 +552,50 @@ pub fn ax88179_reset(dev: &mut UsbDevice) { ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW as u16, 1, 1, tmp); *tmp = 0x52; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH as u16, - 1, 1, tmp); + ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH as u16, 1, 1, tmp); /* Enable checksum offload */ - *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | - AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; + *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL as u16, 1, 1, tmp); - *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | - AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; + *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL as u16, 1, 1, tmp); /* Configure RX control register => start operation */ // *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | // AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - *tmp16 = AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE | - AX_RX_CTL_PRO | AX_RX_CTL_AMALL | AX_RX_CTL_AP; + *tmp16 = AX_RX_CTL_START + | AX_RX_CTL_AB + | AX_RX_CTL_IPE + | AX_RX_CTL_PRO + | AX_RX_CTL_AMALL + | AX_RX_CTL_AP; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL as u16, 2, 2, tmp16 as *mut u8); - *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | - AX_MONITOR_MODE_RWMP; + *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | AX_MONITOR_MODE_RWMP; ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD as u16, 1, 1, tmp); /* Configure default medium type => giga */ - *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_FULL_DUPLEX | - AX_MEDIUM_GIGAMODE; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE as u16, 2, 2, tmp16 as *mut u8); + *tmp16 = AX_MEDIUM_RECEIVE_EN + | AX_MEDIUM_TXFLOW_CTRLEN + | AX_MEDIUM_RXFLOW_CTRLEN + | AX_MEDIUM_FULL_DUPLEX; //| + // AX_MEDIUM_GIGAMODE; + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_MEDIUM_STATUS_MODE as u16, + 2, + 2, + tmp16 as *mut u8, + ); } ax88179_disable_eee(dev); ax88179_ethtool(dev); mii_nway_restart(dev); - } - pub fn ax88179_link_reset(dev: &mut UsbDevice) { println!("| AX88179: Resetting link"); let mut tmp32: u32 = 0x40000000; @@ -508,17 +603,35 @@ pub fn ax88179_link_reset(dev: &mut UsbDevice) { use crate::sync::get_time; let timeout = get_time() / 1000 + 100; let mut mode: u16 = 0; - while tmp32 & 0x40000000 != 0{ - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mut mode as *mut u16 as *mut u8); - - let mut temporary: u16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | - AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mut temporary as *mut u16 as *mut u8); + while tmp32 & 0x40000000 != 0 { + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_RX_CTL, + 2, + 2, + &mut mode as *mut u16 as *mut u8, + ); + + let mut temporary: u16 = AX_RX_CTL_DROPCRCERR + | AX_RX_CTL_IPE + | AX_RX_CTL_START + | AX_RX_CTL_AP + | AX_RX_CTL_AMALL + | AX_RX_CTL_AB; + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_RX_CTL, + 2, + 2, + &mut temporary as *mut u16 as *mut u8, + ); /* link up, check the usb device control TX FIFO full or empty*/ - /*link up, check the usb device control TX FIFO full or empty*/ - ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &mut tmp32 as *mut u32 as *mut u8); + /*link up, check the usb device control TX FIFO full or empty*/ + ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &mut tmp32 as *mut u32 as *mut u8); if get_time() / 1000 > timeout { println!("| AX88179: Link reset timeout"); @@ -529,37 +642,70 @@ pub fn ax88179_link_reset(dev: &mut UsbDevice) { let mut link_sts: u8 = 0; let mut tmp16: u16 = 0; - mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | - AX_MEDIUM_RXFLOW_CTRLEN; - - ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS as u16, - 1, 1, &mut link_sts as *mut u8); - - ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PHYSR, 2, &mut tmp16 as *mut u16 as *mut u8); + mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | AX_MEDIUM_RXFLOW_CTRLEN; + + ax88179_read_cmd( + dev, + AX_ACCESS_MAC, + PHYSICAL_LINK_STATUS as u16, + 1, + 1, + &mut link_sts as *mut u8, + ); + + ax88179_read_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID, + GMII_PHY_PHYSR, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); if (tmp16 & GMII_PHY_PHYSR_FULL) != 0 { mode |= AX_MEDIUM_FULL_DUPLEX; } - ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE as u16, - 2, 2, &mut mode as *mut u16 as *mut u8); + ax88179_write_cmd( + dev, + AX_ACCESS_MAC, + AX_MEDIUM_STATUS_MODE as u16, + 2, + 2, + &mut mode as *mut u16 as *mut u8, + ); } pub fn ax88179_disable_eee(dev: &mut UsbDevice) { println!("| AX88179: Disabling EEE"); let mut tmp16 = GMII_PHY_PGSEL_PAGE3; - unsafe { - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID as u16, - GMII_PHY_PAGE_SELECT, 2, &mut tmp16 as *mut u16 as *mut u8); - - tmp16 = 0x3246; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_PHYADDR, 2, &mut tmp16 as *mut u16 as *mut u8); - - tmp16 = GMII_PHY_PGSEL_PAGE0; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - GMII_PHY_PAGE_SELECT, 2, &mut tmp16 as *mut u16 as *mut u8); - } + ax88179_write_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID as u16, + GMII_PHY_PAGE_SELECT, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); + + tmp16 = 0x3246; + ax88179_write_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID, + MII_PHYADDR, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); + + tmp16 = GMII_PHY_PGSEL_PAGE0; + ax88179_write_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID, + GMII_PHY_PAGE_SELECT, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); } pub fn mii_nway_restart(dev: &mut UsbDevice) { @@ -575,53 +721,60 @@ pub fn mii_nway_restart(dev: &mut UsbDevice) { pub fn ax88179_ethtool(dev: &mut UsbDevice) { println!("| AX88179: Setting ethtool settings"); - let val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV, - MDIO_MMD_AN); + let val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV, MDIO_MMD_AN); let mut adv = 0; if val & MDIO_EEE_100TX != 0 { - adv |= MDIO_EEE_100TX;//1 << ETHTOOL_LINK_MODE_100baseT_Full_BIT; + adv |= MDIO_EEE_100TX; //1 << ETHTOOL_LINK_MODE_100baseT_Full_BIT; } if val & MDIO_EEE_1000T != 0 { - adv |= MDIO_EEE_1000T;//1 << ETHTOOL_LINK_MODE_1000baseT_Full_BIT; + adv |= MDIO_EEE_1000T; //1 << ETHTOOL_LINK_MODE_1000baseT_Full_BIT; } - if val & MDIO_EEE_10GT != 0 { - adv |= MDIO_EEE_10GT;//1 << ETHTOOL_LINK_MODE_10000baseT_Full_BIT; + if val & MDIO_EEE_10GT != 0 { + adv |= MDIO_EEE_10GT; //1 << ETHTOOL_LINK_MODE_10000baseT_Full_BIT; } if val & MDIO_EEE_1000KX != 0 { - adv |= MDIO_EEE_1000KX;//1 << ETHTOOL_LINK_MODE_1000baseKX_Full_BIT; + adv |= MDIO_EEE_1000KX; //1 << ETHTOOL_LINK_MODE_1000baseKX_Full_BIT; } if val & MDIO_EEE_10GKX4 != 0 { - adv |= MDIO_EEE_10GKX4;//1 << ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT; + adv |= MDIO_EEE_10GKX4; //1 << ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT; } if val & MDIO_EEE_10GKR != 0 { - adv |= MDIO_EEE_10GKR;//1 << ETHTOOL_LINK_MODE_10000baseKR_Full_BIT; + adv |= MDIO_EEE_10GKR; //1 << ETHTOOL_LINK_MODE_10000baseKR_Full_BIT; } - ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV, - MDIO_MMD_AN, adv); - + ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV, MDIO_MMD_AN, adv); } -pub fn ax88179_phy_write_mmd_indirect(dev: &mut UsbDevice, prtad: u16, devad: u16, data: u16) -{ +pub fn ax88179_phy_write_mmd_indirect(dev: &mut UsbDevice, prtad: u16, devad: u16, data: u16) { ax88179_phy_mmd_indirect(dev, prtad, devad); let mut tmp16 = data; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_DATA, 2, &mut tmp16 as *mut u16 as *mut u8); + ax88179_write_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID, + MII_MMD_DATA, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); } - pub fn ax88179_phy_read_mmd_indirect(dev: &mut UsbDevice, prtad: u16, devad: u16) -> u16 { ax88179_phy_mmd_indirect(dev, prtad, devad); let mut tmp16: u16 = 0; - ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_DATA, 2, &mut tmp16 as *mut u16 as *mut u8); + ax88179_read_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID, + MII_MMD_DATA, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); return tmp16; } @@ -629,44 +782,96 @@ pub fn ax88179_phy_read_mmd_indirect(dev: &mut UsbDevice, prtad: u16, devad: u16 pub fn ax88179_phy_mmd_indirect(dev: &mut UsbDevice, prtad: u16, devad: u16) { let mut tmp16 = devad; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_CTRL, 2, &mut tmp16 as *mut u16 as *mut u8); + ax88179_write_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID, + MII_MMD_CTRL, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); tmp16 = prtad; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_DATA, 2, &mut tmp16 as *mut u16 as *mut u8); - - tmp16 = devad | MII_MMD_CTRL_NOINCR; - ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, - MII_MMD_CTRL, 2, &mut tmp16 as *mut u16 as *mut u8); + ax88179_write_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID, + MII_MMD_DATA, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); + + tmp16 = devad | MII_MMD_CTRL_NOINCR; + ax88179_write_cmd( + dev, + AX_ACCESS_PHY, + AX88179_PHY_ID, + MII_MMD_CTRL, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); } pub fn ax88179_mdio_read(dev: &mut UsbDevice, loc: u16) -> u16 { let mut tmp16: u16 = 0; // Read MDIO register - ax88179_read_cmd(dev, AXGE_ACCESS_PHY, 3, loc, 2, &mut tmp16 as *mut u16 as *mut u8); + ax88179_read_cmd( + dev, + AXGE_ACCESS_PHY, + 3, + loc, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); return tmp16; } pub fn ax88179_mdio_write(dev: &mut UsbDevice, loc: u16, val: u16) { let mut tmp16: u16 = val; - ax88179_write_cmd(dev, AXGE_ACCESS_PHY, 3, loc, 2, &mut tmp16 as *mut u16 as *mut u8); + ax88179_write_cmd( + dev, + AXGE_ACCESS_PHY, + 3, + loc, + 2, + &mut tmp16 as *mut u16 as *mut u8, + ); } -pub fn ax88179_read_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, size: u16, data: *mut u8) { +pub fn ax88179_read_cmd( + device: &mut UsbDevice, + cmd: u8, + value: u16, + index: u16, + size: u16, + data: *mut u8, +) { if size == 2 { - let mut buf: u16 = 0; - __ax88179_read_cmd(device, cmd, value, index, size, &buf as *const u16 as *mut u8); - buf.to_le_bytes(); + let buf: u16 = 0; + __ax88179_read_cmd( + device, + cmd, + value, + index, + size, + &buf as *const u16 as *mut u8, + ); + let _ = buf.to_le_bytes(); unsafe { *(data as *mut u16) = buf; } - } else if size == 4 { - let mut buf: u32 = 0; - __ax88179_read_cmd(device, cmd, value, index, size, &buf as *const u32 as *mut u8); - buf.to_le_bytes(); + let buf: u32 = 0; + __ax88179_read_cmd( + device, + cmd, + value, + index, + size, + &buf as *const u32 as *mut u8, + ); + let _ = buf.to_le_bytes(); unsafe { *(data as *mut u32) = buf; } @@ -675,19 +880,40 @@ pub fn ax88179_read_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, } } -pub fn ax88179_write_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, size: u16, data: *mut u8) { +pub fn ax88179_write_cmd( + device: &mut UsbDevice, + cmd: u8, + value: u16, + index: u16, + size: u16, + data: *mut u8, +) { if size == 2 { - let mut buf: u16; + let buf: u16; buf = unsafe { core::ptr::read(data as *const u16) }; - buf.to_le_bytes(); + let _ = buf.to_le_bytes(); - __ax88179_write_cmd(device, cmd, value, index, size, &buf as *const u16 as *mut u8); + __ax88179_write_cmd( + device, + cmd, + value, + index, + size, + &buf as *const u16 as *mut u8, + ); } else { __ax88179_write_cmd(device, cmd, value, index, size, data); } } -pub fn __ax88179_read_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, size: u16, data: *mut u8) -> ResultCode { +pub fn __ax88179_read_cmd( + device: &mut UsbDevice, + cmd: u8, + value: u16, + index: u16, + size: u16, + data: *mut u8, +) -> ResultCode { let result = unsafe { UsbControlMessage( device, @@ -721,7 +947,14 @@ pub fn __ax88179_read_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u1 return result; } -pub fn __ax88179_write_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u16, size: u16, data: *mut u8) -> ResultCode { +pub fn __ax88179_write_cmd( + device: &mut UsbDevice, + cmd: u8, + value: u16, + index: u16, + size: u16, + data: *mut u8, +) -> ResultCode { let result = unsafe { UsbControlMessage( device, @@ -755,115 +988,114 @@ pub fn __ax88179_write_cmd(device: &mut UsbDevice, cmd: u8, value: u16, index: u return result; } - // MDIO Manageable Devices (MMDs) -pub const MDIO_MMD_PMAPMD: u16 = 1; // Physical Medium Attachment / Physical Medium Dependent -pub const MDIO_MMD_WIS: u16 = 2; // WAN Interface Sublayer -pub const MDIO_MMD_PCS: u16 = 3; // Physical Coding Sublayer -pub const MDIO_MMD_PHYXS: u16 = 4; // PHY Extender Sublayer -pub const MDIO_MMD_DTEXS: u16 = 5; // DTE Extender Sublayer -pub const MDIO_MMD_TC: u16 = 6; // Transmission Convergence -pub const MDIO_MMD_AN: u16 = 7; // Auto-Negotiation -pub const MDIO_MMD_POWER_UNIT: u16 = 13; // PHY Power Unit -pub const MDIO_MMD_C22EXT: u16 = 29; // Clause 22 extension -pub const MDIO_MMD_VEND1: u16 = 30; // Vendor specific 1 -pub const MDIO_MMD_VEND2: u16 = 31; // Vendor specific 2 +pub const MDIO_MMD_PMAPMD: u16 = 1; // Physical Medium Attachment / Physical Medium Dependent +pub const MDIO_MMD_WIS: u16 = 2; // WAN Interface Sublayer +pub const MDIO_MMD_PCS: u16 = 3; // Physical Coding Sublayer +pub const MDIO_MMD_PHYXS: u16 = 4; // PHY Extender Sublayer +pub const MDIO_MMD_DTEXS: u16 = 5; // DTE Extender Sublayer +pub const MDIO_MMD_TC: u16 = 6; // Transmission Convergence +pub const MDIO_MMD_AN: u16 = 7; // Auto-Negotiation +pub const MDIO_MMD_POWER_UNIT: u16 = 13; // PHY Power Unit +pub const MDIO_MMD_C22EXT: u16 = 29; // Clause 22 extension +pub const MDIO_MMD_VEND1: u16 = 30; // Vendor specific 1 +pub const MDIO_MMD_VEND2: u16 = 31; // Vendor specific 2 // Generic MII register addresses -pub const MII_BMCR: u16 = 0x00; // Basic mode control register -pub const MII_BMSR: u16 = 0x01; // Basic mode status register -pub const MII_PHYSID1: u16 = 0x02; // PHYS ID 1 -pub const MII_PHYSID2: u16 = 0x03; // PHYS ID 2 -pub const MII_ADVERTISE: u16 = 0x04; // Advertisement control register -pub const MII_LPA: u16 = 0x05; // Link partner ability register -pub const MII_EXPANSION: u16 = 0x06; // Expansion register -pub const MII_CTRL1000: u16 = 0x09; // 1000BASE-T control -pub const MII_STAT1000: u16 = 0x0a; // 1000BASE-T status -pub const MII_MMD_CTRL: u16 = 0x0d; // MMD Access Control Register -pub const MII_MMD_DATA: u16 = 0x0e; // MMD Access Data Register -pub const MII_ESTATUS: u16 = 0x0f; // Extended Status -pub const MII_DCOUNTER: u16 = 0x12; // Disconnect counter -pub const MII_FCSCOUNTER: u16 = 0x13; // False carrier counter -pub const MII_NWAYTEST: u16 = 0x14; // N-way auto-negotiation test register -pub const MII_RERRCOUNTER: u16 = 0x15; // Receive error counter -pub const MII_SREVISION: u16 = 0x16; // Silicon revision -pub const MII_RESV1: u16 = 0x17; // Reserved -pub const MII_LBRERROR: u16 = 0x18; // Loopback, receive, bypass error -pub const MII_PHYADDR: u16 = 0x19; // PHY address -pub const MII_RESV2: u16 = 0x1a; // Reserved -pub const MII_TPISTATUS: u16 = 0x1b; // TPI status for 10 Mbps -pub const MII_NCONFIG: u16 = 0x1c; // Network interface config +pub const MII_BMCR: u16 = 0x00; // Basic mode control register +pub const MII_BMSR: u16 = 0x01; // Basic mode status register +pub const MII_PHYSID1: u16 = 0x02; // PHYS ID 1 +pub const MII_PHYSID2: u16 = 0x03; // PHYS ID 2 +pub const MII_ADVERTISE: u16 = 0x04; // Advertisement control register +pub const MII_LPA: u16 = 0x05; // Link partner ability register +pub const MII_EXPANSION: u16 = 0x06; // Expansion register +pub const MII_CTRL1000: u16 = 0x09; // 1000BASE-T control +pub const MII_STAT1000: u16 = 0x0a; // 1000BASE-T status +pub const MII_MMD_CTRL: u16 = 0x0d; // MMD Access Control Register +pub const MII_MMD_DATA: u16 = 0x0e; // MMD Access Data Register +pub const MII_ESTATUS: u16 = 0x0f; // Extended Status +pub const MII_DCOUNTER: u16 = 0x12; // Disconnect counter +pub const MII_FCSCOUNTER: u16 = 0x13; // False carrier counter +pub const MII_NWAYTEST: u16 = 0x14; // N-way auto-negotiation test register +pub const MII_RERRCOUNTER: u16 = 0x15; // Receive error counter +pub const MII_SREVISION: u16 = 0x16; // Silicon revision +pub const MII_RESV1: u16 = 0x17; // Reserved +pub const MII_LBRERROR: u16 = 0x18; // Loopback, receive, bypass error +pub const MII_PHYADDR: u16 = 0x19; // PHY address +pub const MII_RESV2: u16 = 0x1a; // Reserved +pub const MII_TPISTATUS: u16 = 0x1b; // TPI status for 10 Mbps +pub const MII_NCONFIG: u16 = 0x1c; // Network interface config // Basic Mode Control Register (BMCR) bitfields -pub const BMCR_RESV: u16 = 0x003f; // Unused -pub const BMCR_SPEED1000: u16 = 0x0040; // MSB of speed (1000 Mbps) -pub const BMCR_CTST: u16 = 0x0080; // Collision test -pub const BMCR_FULLDPLX: u16 = 0x0100; // Full duplex -pub const BMCR_ANRESTART: u16 = 0x0200; // Auto-negotiation restart -pub const BMCR_ISOLATE: u16 = 0x0400; // Isolate data paths from MII -pub const BMCR_PDOWN: u16 = 0x0800; // Power down -pub const BMCR_ANENABLE: u16 = 0x1000; // Enable auto-negotiation -pub const BMCR_SPEED100: u16 = 0x2000; // Select 100 Mbps -pub const BMCR_LOOPBACK: u16 = 0x4000; // TXD loopback -pub const BMCR_RESET: u16 = 0x8000; // Reset to default -pub const BMCR_SPEED10: u16 = 0x0000; // Select 10 Mbps +pub const BMCR_RESV: u16 = 0x003f; // Unused +pub const BMCR_SPEED1000: u16 = 0x0040; // MSB of speed (1000 Mbps) +pub const BMCR_CTST: u16 = 0x0080; // Collision test +pub const BMCR_FULLDPLX: u16 = 0x0100; // Full duplex +pub const BMCR_ANRESTART: u16 = 0x0200; // Auto-negotiation restart +pub const BMCR_ISOLATE: u16 = 0x0400; // Isolate data paths from MII +pub const BMCR_PDOWN: u16 = 0x0800; // Power down +pub const BMCR_ANENABLE: u16 = 0x1000; // Enable auto-negotiation +pub const BMCR_SPEED100: u16 = 0x2000; // Select 100 Mbps +pub const BMCR_LOOPBACK: u16 = 0x4000; // TXD loopback +pub const BMCR_RESET: u16 = 0x8000; // Reset to default +pub const BMCR_SPEED10: u16 = 0x0000; // Select 10 Mbps // MMD Access Control register fields -pub const MII_MMD_CTRL_DEVAD_MASK: u16 = 0x001f; // Mask MMD DEVAD -pub const MII_MMD_CTRL_ADDR: u16 = 0x0000; // Address -pub const MII_MMD_CTRL_NOINCR: u16 = 0x4000; // No post increment -pub const MII_MMD_CTRL_INCR_RDWT: u16 = 0x8000; // Post increment on reads & writes -pub const MII_MMD_CTRL_INCR_ON_WT: u16 = 0xC000; // Post increment on writes only +pub const MII_MMD_CTRL_DEVAD_MASK: u16 = 0x001f; // Mask MMD DEVAD +pub const MII_MMD_CTRL_ADDR: u16 = 0x0000; // Address +pub const MII_MMD_CTRL_NOINCR: u16 = 0x4000; // No post increment +pub const MII_MMD_CTRL_INCR_RDWT: u16 = 0x8000; // Post increment on reads & writes +pub const MII_MMD_CTRL_INCR_ON_WT: u16 = 0xC000; // Post increment on writes only // Generic MDIO register mappings (all as u16) -pub const MDIO_CTRL1: u16 = MII_BMCR as u16; // Basic Mode Control Register -pub const MDIO_STAT1: u16 = MII_BMSR as u16; // Basic Mode Status Register -pub const MDIO_DEVID1: u16 = MII_PHYSID1 as u16; // Device Identifier 1 -pub const MDIO_DEVID2: u16 = MII_PHYSID2 as u16; // Device Identifier 2 +pub const MDIO_CTRL1: u16 = MII_BMCR as u16; // Basic Mode Control Register +pub const MDIO_STAT1: u16 = MII_BMSR as u16; // Basic Mode Status Register +pub const MDIO_DEVID1: u16 = MII_PHYSID1 as u16; // Device Identifier 1 +pub const MDIO_DEVID2: u16 = MII_PHYSID2 as u16; // Device Identifier 2 -pub const MDIO_SPEED: u16 = 4; // Speed ability -pub const MDIO_DEVS1: u16 = 5; // Devices in package +pub const MDIO_SPEED: u16 = 4; // Speed ability +pub const MDIO_DEVS1: u16 = 5; // Devices in package pub const MDIO_DEVS2: u16 = 6; -pub const MDIO_CTRL2: u16 = 7; // 10G control 2 -pub const MDIO_STAT2: u16 = 8; // 10G status 2 -pub const MDIO_PMA_TXDIS: u16 = 9; // 10G PMA/PMD transmit disable -pub const MDIO_PMA_RXDET: u16 = 10; // 10G PMA/PMD receive signal detect -pub const MDIO_PMA_EXTABLE: u16 = 11; // 10G PMA/PMD extended ability -pub const MDIO_PKGID1: u16 = 14; // Package identifier 1 -pub const MDIO_PKGID2: u16 = 15; // Package identifier 2 +pub const MDIO_CTRL2: u16 = 7; // 10G control 2 +pub const MDIO_STAT2: u16 = 8; // 10G status 2 +pub const MDIO_PMA_TXDIS: u16 = 9; // 10G PMA/PMD transmit disable +pub const MDIO_PMA_RXDET: u16 = 10; // 10G PMA/PMD receive signal detect +pub const MDIO_PMA_EXTABLE: u16 = 11; // 10G PMA/PMD extended ability +pub const MDIO_PKGID1: u16 = 14; // Package identifier 1 +pub const MDIO_PKGID2: u16 = 15; // Package identifier 2 // Auto-Negotiation (AN) related -pub const MDIO_AN_ADVERTISE: u16 = 16; // Auto-Negotiation advertisement (base page) -pub const MDIO_AN_LPA: u16 = 19; // Auto-Negotiation link partner ability (base page) -pub const MDIO_PCS_EEE_ABLE: u16 = 20; // EEE Capability register -pub const MDIO_PCS_EEE_ABLE2: u16 = 21; // EEE Capability register 2 -pub const MDIO_PMA_NG_EXTABLE: u16 = 21; // 2.5G/5G PMA/PMD extended ability -pub const MDIO_PCS_EEE_WK_ERR: u16 = 22; // EEE wake error counter -pub const MDIO_PHYXS_LNSTAT: u16 = 24; // PHY XGXS lane state +pub const MDIO_AN_ADVERTISE: u16 = 16; // Auto-Negotiation advertisement (base page) +pub const MDIO_AN_LPA: u16 = 19; // Auto-Negotiation link partner ability (base page) +pub const MDIO_PCS_EEE_ABLE: u16 = 20; // EEE Capability register +pub const MDIO_PCS_EEE_ABLE2: u16 = 21; // EEE Capability register 2 +pub const MDIO_PMA_NG_EXTABLE: u16 = 21; // 2.5G/5G PMA/PMD extended ability +pub const MDIO_PCS_EEE_WK_ERR: u16 = 22; // EEE wake error counter +pub const MDIO_PHYXS_LNSTAT: u16 = 24; // PHY XGXS lane state -pub const MDIO_AN_EEE_ADV: u16 = 60; // EEE advertisement -pub const MDIO_AN_EEE_LPABLE: u16 = 61; // EEE link partner ability -pub const MDIO_AN_EEE_ADV2: u16 = 62; // EEE advertisement 2 -pub const MDIO_AN_EEE_LPABLE2: u16 = 63; // EEE link partner ability 2 +pub const MDIO_AN_EEE_ADV: u16 = 60; // EEE advertisement +pub const MDIO_AN_EEE_LPABLE: u16 = 61; // EEE link partner ability +pub const MDIO_AN_EEE_ADV2: u16 = 62; // EEE advertisement 2 +pub const MDIO_AN_EEE_LPABLE2: u16 = 63; // EEE link partner ability 2 -pub const MDIO_AN_CTRL2: u16 = 64; // Auto-Negotiation THP bypass request control +pub const MDIO_AN_CTRL2: u16 = 64; // Auto-Negotiation THP bypass request control // EEE Supported / Advertisement / Link Partner Advertisement registers // (same bit masks used across multiple registers) // Old (user-visible) names -pub const MDIO_AN_EEE_ADV_100TX: u16 = 0x0002; // Advertise 100TX EEE cap -pub const MDIO_AN_EEE_ADV_1000T: u16 = 0x0004; // Advertise 1000T EEE cap +pub const MDIO_AN_EEE_ADV_100TX: u16 = 0x0002; // Advertise 100TX EEE cap +pub const MDIO_AN_EEE_ADV_1000T: u16 = 0x0004; // Advertise 1000T EEE cap // New generic names (aliasing old names) -pub const MDIO_EEE_100TX: u16 = MDIO_AN_EEE_ADV_100TX; // 100TX EEE cap -pub const MDIO_EEE_1000T: u16 = MDIO_AN_EEE_ADV_1000T; // 1000T EEE cap +pub const MDIO_EEE_100TX: u16 = MDIO_AN_EEE_ADV_100TX; // 100TX EEE cap +pub const MDIO_EEE_1000T: u16 = MDIO_AN_EEE_ADV_1000T; // 1000T EEE cap // Other EEE capabilities -pub const MDIO_EEE_10GT: u16 = 0x0008; // 10GBASE-T EEE cap -pub const MDIO_EEE_1000KX: u16 = 0x0010; // 1000BASE-KX EEE cap -pub const MDIO_EEE_10GKX4: u16 = 0x0020; // 10GBASE-KX4 EEE cap -pub const MDIO_EEE_10GKR: u16 = 0x0040; // 10GBASE-KR EEE cap +pub const MDIO_EEE_10GT: u16 = 0x0008; // 10GBASE-T EEE cap +pub const MDIO_EEE_1000KX: u16 = 0x0010; // 1000BASE-KX EEE cap +pub const MDIO_EEE_10GKX4: u16 = 0x0020; // 10GBASE-KX4 EEE cap +pub const MDIO_EEE_10GKR: u16 = 0x0040; // 10GBASE-KR EEE cap pub const MDIO_EEE_40GR_FW: u16 = 0x0100; // 40GBASE-R fast wake pub const MDIO_EEE_40GR_DS: u16 = 0x0200; // 40GBASE-R deep sleep pub const MDIO_EEE_100GR_FW: u16 = 0x1000; // 100GBASE-R fast wake @@ -903,16 +1135,14 @@ pub const ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT: u32 = 29; pub const ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT: u32 = 30; pub const ETHTOOL_LINK_MODE_25000baseCR_Full_BIT: u32 = 31; - // GMII PHY Specific Status Register (PHYSR) pub const GMII_PHY_PHYSR: u16 = 0x11; -pub const GMII_PHY_PHYSR_SMASK: u16 = 0xc000; // Speed mask -pub const GMII_PHY_PHYSR_GIGA: u16 = 0x8000; // 1000 Mbps -pub const GMII_PHY_PHYSR_100: u16 = 0x4000; // 100 Mbps -pub const GMII_PHY_PHYSR_FULL: u16 = 0x2000; // Full duplex -pub const GMII_PHY_PHYSR_LINK: u16 = 0x0400; // Link up - +pub const GMII_PHY_PHYSR_SMASK: u16 = 0xc000; // Speed mask +pub const GMII_PHY_PHYSR_GIGA: u16 = 0x8000; // 1000 Mbps +pub const GMII_PHY_PHYSR_100: u16 = 0x4000; // 100 Mbps +pub const GMII_PHY_PHYSR_FULL: u16 = 0x2000; // Full duplex +pub const GMII_PHY_PHYSR_LINK: u16 = 0x0400; // Link up // pub const BMCR_RESET: u16 = 0x8000; pub const BMCR_LOOP: u16 = 0x4000; @@ -925,7 +1155,6 @@ pub const BMCR_FDX: u16 = 0x0100; pub const BMCR_CTEST: u16 = 0x0080; pub const BMCR_SPEED1: u16 = 0x0040; - pub const PHY_BMCR: u16 = 0x00; // Basic Mode Control Register // Length of an Ethernet address @@ -955,7 +1184,6 @@ pub const ETHER_VLAN_ENCAP_LEN: u8 = 4; // Mbuf adjust factor to force 32-bit alignment of IP header pub const ETHER_ALIGN: u8 = 2; - // Access Registers pub const AXGE_ACCESS_MAC: u8 = 0x01; pub const AXGE_ACCESS_PHY: u8 = 0x02; @@ -1025,7 +1253,6 @@ pub const MMSR_PME_POL: u8 = 0x20; pub const MMSR_PME_TYPE: u8 = 0x40; pub const MMSR_PME_IND: u8 = 0x80; - // Ethernet PHY power & reset control register pub const AXGE_EPPRCR: u16 = 0x26; pub const EPPRCR_BZ: u16 = 0x0010; @@ -1074,8 +1301,6 @@ pub const AXGE_CONFIG_IDX: u16 = 0; // Interface index 0 pub const AXGE_IFACE_IDX: u16 = 0; - - // Utility macro in C: #define BIT(x) (1 << (x)) // In Rust (no_std), we just shift manually. @@ -1129,9 +1354,6 @@ pub const GMII_PHY_PGSEL_PAGE0: u16 = 0x0000; pub const GMII_PHY_PGSEL_PAGE3: u16 = 0x0003; pub const GMII_PHY_PGSEL_PAGE5: u16 = 0x0005; - - - // PHY ID and EEPROM pub const AX88179_PHY_ID: u16 = 0x03; pub const AX_EEPROM_LEN: u16 = 0x100; @@ -1236,7 +1458,6 @@ pub const AX_CLK_SELECT_BCS: u8 = 1 << 0; pub const AX_CLK_SELECT_ACS: u8 = 1 << 1; pub const AX_CLK_SELECT_ULR: u8 = 1 << 3; - // RX Checksum Offload Engine (COE) Control pub const AX_RXCOE_CTL: u8 = 0x34; pub const AX_RXCOE_IP: u8 = 0x01; diff --git a/crates/kernel/src/device/usb/device/hid.rs b/crates/kernel/src/device/usb/device/hid.rs index 382d26d1..4ed1c910 100644 --- a/crates/kernel/src/device/usb/device/hid.rs +++ b/crates/kernel/src/device/usb/device/hid.rs @@ -84,6 +84,7 @@ fn HidSetProtocol(device: &mut UsbDevice, interface: u8, protocol: u16) -> Resul return ResultCode::OK; } +#[allow(dead_code)] fn HidGetReport( device: &mut UsbDevice, report_type: HidReportType, diff --git a/crates/kernel/src/device/usb/device/net.rs b/crates/kernel/src/device/usb/device/net.rs index a5c780b0..dcc64324 100644 --- a/crates/kernel/src/device/usb/device/net.rs +++ b/crates/kernel/src/device/usb/device/net.rs @@ -8,23 +8,20 @@ use super::super::usbd::device::*; */ use core::slice; -use crate::device::usb; use crate::networking::iface::*; use crate::networking::repr::*; +use crate::device::mailbox::HexDisplay; use crate::device::system_timer::micro_delay; use crate::device::usb::hcd::dwc::dwc_otg::ms_to_micro; use crate::device::usb::types::*; -use crate::device::usb::usbd::endpoint::register_interrupt_endpoint; use crate::device::usb::usbd::endpoint::*; use crate::device::usb::usbd::request::*; -use crate::device::mailbox::HexDisplay; -use crate::shutdown; -use alloc::boxed::Box; -use crate::device::usb::device::ax88179::axge_send_packet; use crate::device::usb::device::ax88179::axge_init; use crate::device::usb::device::ax88179::axge_receive_packet; +use crate::device::usb::device::ax88179::axge_send_packet; +use alloc::boxed::Box; use alloc::vec; use super::rndis::*; @@ -55,7 +52,7 @@ pub fn NetLoad(bus: &mut UsbBus) { Some(NetAttach); } -pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { +pub fn NetAttach(device: &mut UsbDevice, _interface_number: u32) -> ResultCode { // println!( // "| Net: Subclass: {:x}, Protocol: {:x}", // device.interfaces[interface_number as usize].subclass, @@ -72,7 +69,6 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { NET_DEVICE.net_receive = Some(axge_receive_packet); NET_DEVICE.truncation = 8; } - } else { println!("| Net: RNDIS Device Detected"); rndis_init(device); @@ -101,26 +97,26 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // device.endpoints[interface_number as usize][0 as usize].interval // ); - register_interrupt_endpoint( - device, - device.endpoints[interface_number as usize][0 as usize].interval as u32, - endpoint_address_to_num( - device.endpoints[interface_number as usize][0 as usize].endpoint_address, - ), - UsbDirection::In, - size_from_number( - device.endpoints[interface_number as usize][0 as usize] - .packet - .MaxSize as u32, - ), - 0, - 10, - ); + // register_interrupt_endpoint( + // device, + // device.endpoints[interface_number as usize][0 as usize].interval as u32, + // endpoint_address_to_num( + // device.endpoints[interface_number as usize][0 as usize].endpoint_address, + // ), + // UsbDirection::In, + // size_from_number( + // device.endpoints[interface_number as usize][0 as usize] + // .packet + // .MaxSize as u32, + // ), + // 0, + // 10, + // ); micro_delay(ms_to_micro(1500)); // Wait for 1.5 seconds - // We currently have this 1.5 second delay to wait for the device to be ready - // technically, we can wait for the interrupt in endpoint to tell us - // but laking ax88179 documentaiton, not sure which bits, so wait for now. + // We currently have this 1.5 second delay to wait for the device to be ready + // technically, we can wait for the interrupt in endpoint to tell us + // but laking ax88179 documentaiton, not sure which bits, so wait for now. // 1. new network interface // 2. initialize mac address @@ -140,12 +136,13 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { } else { unsafe { let mut b = vec![0u8; 30]; - let query = rndis_query_msg(device, OID::OID_802_3_PERMANENT_ADDRESS, b.as_mut_ptr(), 30); - + let query = + rndis_query_msg(device, OID::OID_802_3_PERMANENT_ADDRESS, b.as_mut_ptr(), 30); + if query.0 != ResultCode::OK { panic!("| Net: Error getting MAC address {:#?}", query.0); } - + let b_offset = query.1; let b_len = query.2; if b_len != 6 { @@ -177,7 +174,7 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { // begin receieve series, this queues a receive to be ran which will eventually propogate back // to us through the rgistered `recv` function which then queues another receive let buf = vec![0u8; 1]; //TODO: Technically, the buffer doesn't matter anymore - NetInitiateReceive(buf.into_boxed_slice(), 1500); // TODO: ask aaron if I need to use another function? + NetInitiateReceive(buf.into_boxed_slice(), 1518); // TODO: ask aaron if I need to use another function? // start dhcp unsafe { @@ -192,7 +189,7 @@ pub fn NetAttach(device: &mut UsbDevice, interface_number: u32) -> ResultCode { } pub fn NetInitiateReceive(buffer: Box<[u8]>, buffer_length: u32) { - println!("| Net: Initiate Receive"); + // println!("| Net: Initiate Receive"); unsafe { if let Some(receive_func) = NET_DEVICE.net_receive { let device = NET_DEVICE.device.unwrap(); @@ -232,7 +229,10 @@ pub unsafe fn NetAnalyze(buffer: *mut u8, buffer_length: u32) { } if buffer_length > 0 { - println!("| NET: analyze {:x}", HexDisplay(unsafe { core::slice::from_raw_parts(buffer, buffer_length as usize) })); + println!( + "| NET: analyze {:x}", + HexDisplay(unsafe { core::slice::from_raw_parts(buffer, buffer_length as usize) }) + ); // TODO: } } @@ -256,10 +256,7 @@ pub unsafe fn NetReceive(buffer: *mut u8, buffer_length: u32) { } let buf = vec![0u8; 1]; - unsafe { - let device = &mut *NET_DEVICE.device.unwrap(); - rndis_receive_packet(device, buf.into_boxed_slice(), 1600); - } + NetInitiateReceive(buf.into_boxed_slice(), 1600); } pub fn RegisterNetReceiveCallback(callback: unsafe fn(*mut u8, u32)) { @@ -268,7 +265,6 @@ pub fn RegisterNetReceiveCallback(callback: unsafe fn(*mut u8, u32)) { } } - pub struct NetDevice { pub receive_callback: Option, // pub receive_callback: Option, diff --git a/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs index 99d55212..19e602f2 100644 --- a/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs +++ b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs @@ -13,8 +13,6 @@ * THIS SOFTWARE IS NOT AFFILIATED WITH NOR ENDORSED BY SYNOPSYS IP. ******************************************************************************/ -use core::time; - use crate::device::usb::hcd::dwc::dwc_otgreg::*; use crate::device::usb::hcd::dwc::roothub::*; use crate::device::usb::types::*; @@ -49,7 +47,10 @@ pub static DWC_CHANNEL_ACTIVE: SpinLock = SpinLock::new(DwcCha pub static mut DWC_CHANNEL_CALLBACK: DwcChannelCallback = DwcChannelCallback::new(); pub fn dwc_otg_register_interrupt_handler() { - gic::GIC.get().register_isr(105, dwc_otg_interrupt_handler); + // gic::GIC.get().register_isr(105, dwc_otg_interrupt_handler); + gic::GIC + .get() + .register_isr_detailed(105, dwc_otg_interrupt_handler, 0xf, false, 0x40); } fn schedule_next_transfer(channel: u8) { @@ -290,12 +291,17 @@ fn HcdPrepareChannel( // println!("| HCD Prepare Channel Port number: {:#?}", device.port_number); dwc_sc.channel[channel as usize].split_control.PortAddress = device.port_number + 1; - unsafe { - DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = DWCSplitStateMachine::SSPLIT; - DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].ss_hfnum = read_volatile(DOTG_HFNUM); + unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = + DWCSplitStateMachine::SSPLIT; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].ss_hfnum = + read_volatile(DOTG_HFNUM); } } else { - unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = DWCSplitStateMachine::NONE; } + unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = + DWCSplitStateMachine::NONE; + } } let hcsplt = convert_host_split_control(dwc_sc.channel[channel as usize].split_control); @@ -326,7 +332,13 @@ fn HcdPrepareChannel( return ResultCode::OK; } -pub unsafe fn HcdTransmitChannel(device: &UsbDevice, channel: u8, buffer: *mut u8, bufferOffset: usize, direction: UsbDirection) { +pub unsafe fn HcdTransmitChannel( + device: &UsbDevice, + channel: u8, + buffer: *mut u8, + bufferOffset: usize, + direction: UsbDirection, +) { unsafe { let dwc_sc: &mut dwc_hub = &mut *(device.soft_sc as *mut dwc_hub); let hcsplt = read_volatile(DOTG_HCSPLT(channel as usize)); @@ -362,7 +374,8 @@ pub unsafe fn HcdTransmitChannel(device: &UsbDevice, channel: u8, buffer: *mut u dma_address, ); } - } else { //going out + } else { + //going out memory_copy(dma_loc as *mut u8, buffer, 100); //unclean } @@ -518,15 +531,23 @@ pub fn HcdChannelSendWaitOne( &mut dwc_sc.channel[channel as usize].split_control, ); - printDWCErrors(channel as u32); + // printDWCErrors(channel as u32); // Transmit data. // unsafe { HcdTransmitChannel(device, channel, buffer.wrapping_add(bufferOffset as usize)) }; - unsafe { HcdTransmitChannel(device, channel, buffer, bufferOffset as usize, pipe.direction) }; + unsafe { + HcdTransmitChannel( + device, + channel, + buffer, + bufferOffset as usize, + pipe.direction, + ) + }; timeout = 0; loop { if timeout == RequestTimeout { println!("| HCD: Request to device has timed out."); - printDWCErrors(channel as u32); + // printDWCErrors(channel as u32); device.error = UsbTransferError::ConnectionError; return ResultCode::ErrorTimeout; } @@ -550,10 +571,15 @@ pub fn HcdChannelSendWaitOne( // println!("| HCD: pipe speed {:#?}", pipe.speed); - printDWCErrors(channel as u32); - if pipe.speed != UsbSpeed::High && dwc_sc.channel[channel as usize].split_control.SplitEnable { - println!("| HCD: Split enable {:#?} hcint {:#x}", dwc_sc.channel[channel as usize].split_control.SplitEnable, hcint); - if hcint & HCINT_ACK != 0 && dwc_sc.channel[channel as usize].split_control.SplitEnable + // printDWCErrors(channel as u32); + if pipe.speed != UsbSpeed::High + && dwc_sc.channel[channel as usize].split_control.SplitEnable + { + println!( + "| HCD: Split enable {:#?} hcint {:#x}", + dwc_sc.channel[channel as usize].split_control.SplitEnable, hcint + ); + if hcint & HCINT_ACK != 0 && dwc_sc.channel[channel as usize].split_control.SplitEnable { // Try to complete the split up to 3 times. // println!("| HCD: Completing split to device with ACK"); @@ -618,7 +644,7 @@ pub fn HcdChannelSendWaitOne( continue; } else if hcint & HCINT_XACTERR != 0 { // println!("| HCD: Request split completion XACTERR"); - printDWCErrors(channel as u32); + // printDWCErrors(channel as u32); micro_delay(25000); continue; } @@ -661,15 +687,14 @@ pub fn HcdChannelSendWaitOne( continue; } } else { - if hcint & HCINT_XFERCOMPL == 0 { - _ = HcdChannelInterruptToError( + _ = HcdChannelInterruptToError( device, hcint, !dwc_sc.channel[channel as usize].split_control.SplitEnable, ); - printDWCErrors(channel as u32); + // printDWCErrors(channel as u32); // LOG_DEBUGF( // "HCD: Control message to %#x: %02x%02x%02x%02x %02x%02x%02x%02x.\n", // *(pipe as *const u32), @@ -761,7 +786,7 @@ fn HcdChannelSendWait( if hcint & HCINT_NAK != 0 { println!("| HCD: NAK on channel {}\n", device.last_transfer); - + return ResultCode::OK; } @@ -873,13 +898,35 @@ fn HcdTransmitChannelNoWait(device: &UsbDevice, channel: u8, buffer: *mut u8) { .characteristics .PacketsPerFrame = 1; - if DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state == DWCSplitStateMachine::SSPLIT { - let mut hfnum = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + if DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state + == DWCSplitStateMachine::SSPLIT + { + let hfnum = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; - while hfnum % 8 == 6 { - micro_delay(10); - hfnum = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; - } + // let target_hfnum; + // if device.number == 2 { + // target_hfnum = 0; + // } else { + // target_hfnum = 5; + // } + + // while hfnum % 8 != target_hfnum { + // micro_delay(10); + // hfnum = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + // } + // let mut succeed = true; + // while succeed { + // use crate::device::usb::usbd::endpoint::SSPLIT_FRAME; + // let mut frame_val = SSPLIT_FRAME.lock(); + + // if *frame_val == hfnum { + // micro_delay(10); + // hfnum = read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + // } else { + // *frame_val = hfnum; + // succeed = false; + // } + // } DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].ss_hfnum = hfnum; } //TODO: temporary @@ -908,30 +955,37 @@ fn HcdChannelSendOne( write_volatile( DOTG_HCINTMSK(channel as usize), // HCINTMSK_XFERCOMPLMSK - HCINTMSK_CHHLTDMSK - // | HCINTMSK_AHBERRMSK - // | HCINTMSK_STALLMSK - // | HCINTMSK_ACKMSK - // | HCINTMSK_NYETMSK - // | HCINTMSK_XACTERRMSK - // | HCINTMSK_BBLERRMSK - // | HCINTMSK_FRMOVRUNMSK - // | HCINTMSK_DATATGLERRMSK, - ) + HCINTMSK_CHHLTDMSK, // | HCINTMSK_AHBERRMSK + // | HCINTMSK_STALLMSK + // | HCINTMSK_ACKMSK + // | HCINTMSK_NYETMSK + // | HCINTMSK_XACTERRMSK + // | HCINTMSK_BBLERRMSK + // | HCINTMSK_FRMOVRUNMSK + // | HCINTMSK_DATATGLERRMSK, + ); + + // let hctsiz = read_volatile(DOTG_HCTSIZ(channel as usize)); + // let hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); + // let hcsplt = read_volatile(DOTG_HCSPLT(channel as usize)); + + // println!( + // "HCD: Channel {:#x} hcchar {:#x} HCTSIZ {:#x} HCSPLT {:#x}", + // channel, hcchar, hctsiz, hcsplt + // ); } else { write_volatile( DOTG_HCINTMSK(channel as usize), // HCINTMSK_XFERCOMPLMSK - HCINTMSK_CHHLTDMSK - // | HCINTMSK_AHBERRMSK - // | HCINTMSK_STALLMSK - // | HCINTMSK_NAKMSK - // | HCINTMSK_ACKMSK - // | HCINTMSK_NYETMSK - // | HCINTMSK_XACTERRMSK - // | HCINTMSK_BBLERRMSK - // | HCINTMSK_FRMOVRUNMSK - // | HCINTMSK_DATATGLERRMSK, + HCINTMSK_CHHLTDMSK, // | HCINTMSK_AHBERRMSK + // | HCINTMSK_STALLMSK + // | HCINTMSK_NAKMSK + // | HCINTMSK_ACKMSK + // | HCINTMSK_NYETMSK + // | HCINTMSK_XACTERRMSK + // | HCINTMSK_BBLERRMSK + // | HCINTMSK_FRMOVRUNMSK + // | HCINTMSK_DATATGLERRMSK, ); } @@ -1009,7 +1063,6 @@ pub unsafe fn HcdSubmitBulkMessage( buffer_length as usize, ); } - } let result = HcdChannelSend( @@ -1056,7 +1109,13 @@ pub unsafe fn HcdSubmitInterruptMessage2( channel, buffer, buffer_length, - &mut UsbDeviceRequest { request_type: 0, request: crate::device::usb::usbd::request::UsbDeviceRequestRequest::ClearFeature, value: 0, index: 0, length: 0 }, + &mut UsbDeviceRequest { + request_type: 0, + request: crate::device::usb::usbd::request::UsbDeviceRequestRequest::ClearFeature, + value: 0, + index: 0, + length: 0, + }, packet_id, ); @@ -1078,7 +1137,7 @@ pub unsafe fn HcdSubmitInterruptMessage2( endpoint_device.endpoint_pid[2] += 1; endpoint_device.endpoint_pid[3] += 1; endpoint_device.endpoint_pid[4] += 1; - + unsafe { memory_copy( buffer, @@ -1086,7 +1145,6 @@ pub unsafe fn HcdSubmitInterruptMessage2( device.last_transfer as usize, ); } - } //transfer data cout @@ -1107,7 +1165,6 @@ pub unsafe fn HcdSubmitInterruptMessage( buffer_length: u32, packet_id: PacketId, ) -> ResultCode { - let dwc_sc = unsafe { &mut *(device.soft_sc as *mut dwc_hub) }; device.error = UsbTransferError::Processing; device.last_transfer = 0; @@ -1140,24 +1197,6 @@ pub unsafe fn HcdSubmitInterruptMessage( return ResultCode::OK; } - -pub fn printDWCErrors(channel: u32) { - // let hprt = read_volatile(DOTG_HPRT); - // let gintsts = read_volatile(DOTG_GINTSTS); - // let haint = read_volatile(DOTG_HAINT); - // let hcint = read_volatile(DOTG_HCINT(channel as usize)); - // let hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); - // let hctsiz = read_volatile(DOTG_HCTSIZ(channel as usize)); - - // println!("| HCD hprt: {:#x}", hprt); - // println!("| HCD gintsts: {:#x}", gintsts); - // println!("| HCD haint: {:#x}", haint); - // println!("| HCD hcint: {:#x}", hcint); - // println!("| HCD hcchar: {:#x}", hcchar); - // println!("| HCD hctsiz: {:#x}", hctsiz); - // println!("| HCD channel: {:#x}\n", channel); -} - pub unsafe fn HcdSubmitControlMessage( device: &mut UsbDevice, pipe: UsbPipeAddress, @@ -1206,9 +1245,9 @@ pub unsafe fn HcdSubmitControlMessage( } // println!("| HCD: Control message sent to device.\n"); - printDWCErrors(0); + // printDWCErrors(0); - let mut is_data1 = true; + let is_data1 = true; if !buffer.is_null() { if pipe.direction == UsbDirection::Out { @@ -1234,9 +1273,6 @@ pub unsafe fn HcdSubmitControlMessage( PacketId::Data0 }; - - - is_data1 = !is_data1; result = HcdChannelSendWait( device, &mut tempPipe, @@ -1250,7 +1286,7 @@ pub unsafe fn HcdSubmitControlMessage( if result != ResultCode::OK { println!("| HCD: Coult not send data to device\n"); - printDWCErrors(0); + // printDWCErrors(0); return result; } @@ -1298,10 +1334,7 @@ pub unsafe fn HcdSubmitControlMessage( ); //print the first 16 bytes of the data buffer for i in 0..buffer_length { - print!( - "{:#x} ", - *((data_buffer as *const u8).offset(i as isize)) - ); + print!("{:#x} ", *((data_buffer as *const u8).offset(i as isize))); } println!() } @@ -1324,9 +1357,9 @@ pub unsafe fn HcdSubmitControlMessage( // PacketId::Data0 // }; let pid = PacketId::Data1; //according to spec, the last packet is always Data1 - // tempPipe.direction = UsbDirection::In; - //TODO: This is necessary in Real hardware I think but QEMU doesn't fully handle it - //https://elixir.bootlin.com/qemu/v9.0.2/source/hw/usb/hcd-dwc2.c#L346 + // tempPipe.direction = UsbDirection::In; + //TODO: This is necessary in Real hardware I think but QEMU doesn't fully handle it + //https://elixir.bootlin.com/qemu/v9.0.2/source/hw/usb/hcd-dwc2.c#L346 result = HcdChannelSendWait( device, &mut tempPipe, @@ -1483,13 +1516,16 @@ pub fn init_fifo() -> ResultCode { fifo_size &= !3; write_volatile(DOTG_GRXFSIZ, fifo_size); + println!("| GRXFSIZ: {:#x}", fifo_size); let mut tx_start = fifo_size; fifo_size /= 2; write_volatile(DOTG_GNPTXFSIZ, ((fifo_size / 4) << 16) | (tx_start / 4)); + println!("| GNPTXFSIZ: {:#x} tx_start: {:#x}", fifo_size, tx_start); tx_start += fifo_size; write_volatile(DOTG_HPTXFSIZ, ((fifo_size / 4) << 16) | (tx_start / 4)); + println!("| HPTXFSIZ: {:#x} tx_start: {:#x}", fifo_size, tx_start); write_volatile(DOTG_GINTMSK, GINTMSK_HCHINTMSK); @@ -1986,7 +2022,8 @@ pub fn dwc_otg_free_channel(channel: u32) { } pub struct DwcChannelCallback { - pub callback: [Option bool>; ChannelCount], + pub callback: + [Option bool>; ChannelCount], pub endpoint_descriptors: [Option; ChannelCount], pub split_control_state: [DWCSplitControlState; ChannelCount], } @@ -2129,7 +2166,7 @@ pub fn convert_into_host_transfer_size(val: u32, chan: &mut host_transfer_size) } pub fn convert_host_transfer_size(chan: host_transfer_size) -> u32 { - return (chan.TransferSize as u32) + return (chan.TransferSize as u32) & 0x7ffff | (chan.PacketCount as u32) << 19 | (chan.packet_id as u32) << 29; } diff --git a/crates/kernel/src/device/usb/hcd/dwc/roothub.rs b/crates/kernel/src/device/usb/hcd/dwc/roothub.rs index 2f22250b..6fb138ea 100644 --- a/crates/kernel/src/device/usb/hcd/dwc/roothub.rs +++ b/crates/kernel/src/device/usb/hcd/dwc/roothub.rs @@ -285,10 +285,12 @@ pub unsafe fn HcdProcessRootHubMessage( micro_delay(ms_to_micro(63)); - write_volatile(DOTG_HPRT, hprt); + let hprt = read_volatile(DOTG_HPRT); + write_volatile(DOTG_HPRT, hprt & !HPRT_PRTRST); + // write_volatile(DOTG_HPRT, hprt); micro_delay(ms_to_micro(63)); - init_fifo(); + // init_fifo(); // //FeatureReset // let mut pwr = read_volatile(DOTG_PCGCCTL); // pwr &= !(1 << 5); diff --git a/crates/kernel/src/device/usb/usbd/endpoint.rs b/crates/kernel/src/device/usb/usbd/endpoint.rs index 2a616d36..50c9e3f8 100644 --- a/crates/kernel/src/device/usb/usbd/endpoint.rs +++ b/crates/kernel/src/device/usb/usbd/endpoint.rs @@ -10,21 +10,23 @@ use crate::device::system_timer::{get_time, micro_delay}; use crate::device::usb; // use crate::device::system_timer::micro_delay; +use crate::device::usb::device::net::NET_DEVICE; use crate::device::usb::hcd::dwc::dwc_otg; use crate::device::usb::hcd::dwc::dwc_otg::DwcActivateChannel; -use crate::device::usb::hcd::dwc::dwc_otg::{printDWCErrors, read_volatile, DWCSplitControlState, DWCSplitStateMachine, DwcEnableChannel, UpdateDwcOddFrame, DWC_CHANNEL_CALLBACK}; -use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; -use crate::device::usb::hcd::dwc::dwc_otgreg::{DOTG_HCTSIZ, DOTG_HFNUM, HCINT_FRMOVRUN, HCINT_NYET, HCINT_XACTERR, HFNUM_FRNUM_MASK}; -use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCSPLT; +use crate::device::usb::hcd::dwc::dwc_otg::{ + DWCSplitControlState, DWCSplitStateMachine, DwcEnableChannel, UpdateDwcOddFrame, + DWC_CHANNEL_CALLBACK, +}; use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCCHAR; -use crate::device::usb::DwcDisableChannel; +use crate::device::usb::hcd::dwc::dwc_otgreg::{ + DOTG_HCTSIZ, DOTG_HFNUM, HCINT_FRMOVRUN, HCINT_NYET, HCINT_XACTERR, HFNUM_FRNUM_MASK, +}; // use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; use crate::device::usb::DwcFrameDifference; // use crate::device::usb::hcd::dwc::dwc_otg; use crate::device::usb::DwcActivateCsplit; // use crate::device::usb::DwcDisableChannel; use crate::device::usb::UsbSendInterruptMessage; -use crate::sync::{LockGuard, SpinLockInner}; use usb::dwc_hub; use usb::hcd::dwc::dwc_otg::HcdUpdateTransferSize; use usb::hcd::dwc::dwc_otgreg::{HCINT_ACK, HCINT_CHHLTD, HCINT_NAK, HCINT_XFERCOMPL}; @@ -33,7 +35,6 @@ use usb::usbd::device::*; use usb::usbd::pipe::*; use usb::PacketId; - use crate::event::task::spawn_async_rt; use crate::sync::time::{interval, MissedTicks}; use crate::SpinLock; @@ -44,8 +45,14 @@ static mut NET_BUFFER_LEN: u32 = 0; static mut NET_BUFFER_ACTIVE: bool = false; pub static NEXT_FRAME_CS: SpinLock = SpinLock::new(0); - -pub fn finish_bulk_endpoint_callback_in(endpoint: endpoint_descriptor, hcint: u32, channel: u8, _split_control: DWCSplitControlState) -> bool { +pub static SSPLIT_FRAME: SpinLock = SpinLock::new(0); + +pub fn finish_bulk_endpoint_callback_in( + endpoint: endpoint_descriptor, + hcint: u32, + channel: u8, + _split_control: DWCSplitControlState, +) -> bool { let device = unsafe { &mut *endpoint.device }; let mut last_transfer; let transfer_size = HcdUpdateTransferSize(device, channel); @@ -64,7 +71,6 @@ pub fn finish_bulk_endpoint_callback_in(endpoint: endpoint_descriptor, hcint: u3 last_transfer = endpoint.buffer_length - transfer_size; } - // let last_transfer = endpoint.buffer_length - transfer_size; let endpoint_device = device.driver_data.downcast::().unwrap(); @@ -74,10 +80,11 @@ pub fn finish_bulk_endpoint_callback_in(endpoint: endpoint_descriptor, hcint: u3 channel, hcint ); } else if hcint & HCINT_XFERCOMPL == 0 { - panic!( + println!( "| Endpoint {} in: HCINT_XFERCOMPL not set, aborting. {:x}", channel, hcint ); + last_transfer = 0; } // println!("| Endpoint BULK RECEIVED {}: hcint {:x} len {}", channel, hcint, last_transfer); @@ -85,48 +92,49 @@ pub fn finish_bulk_endpoint_callback_in(endpoint: endpoint_descriptor, hcint: u3 let dwc_sc = unsafe { &mut *(device.soft_sc as *mut dwc_hub) }; let dma_addr = dwc_sc.dma_addr[channel as usize]; - // let buffer = endpoint.buffer; // let buffer_length = device.last_transfer; // unsafe { // core::ptr::copy_nonoverlapping(dma_addr as *const u8, buffer, buffer_length as usize); // } - //assume rndis net bulk in + //assume rndis net bulk in: TODO: FIX unsafe { - if !NET_BUFFER_ACTIVE { - use alloc::slice; - // let slice: &[u8] = unsafe { slice::from_raw_parts(dma_addr as *const u8, 16 as usize) }; - let slice32: &[u32] = slice::from_raw_parts(dma_addr as *const u32, 4 as usize); - //print slice - // println!("| Net buffer: {:?}", slice); - // println!("| Net buffer 32: {:?}", slice32); - let _buffer32 = dma_addr as *const u32; - - let rndis_len = slice32[3]; - // let part1 = unsafe { buffer32.offset(0) } as u32; - // println!("| rndis 1 {}", part1); - // println!( - // "| Net buffer length: {} rndis_len: {}", - // last_transfer, rndis_len - // ); - if rndis_len > last_transfer - 44 { - NET_BUFFER_ACTIVE = true; - NET_BUFFER_LEN = rndis_len; - //reenable channel - DwcActivateChannel(channel); - return false; - } - // println!("| NEt continue"); - } else { - if last_transfer >= NET_BUFFER_LEN { - // println!("| NEt buffer finished length: {} NETBUFFER {}", last_transfer, NET_BUFFER_LEN); - NET_BUFFER_ACTIVE = false; - last_transfer = NET_BUFFER_LEN; + if NET_DEVICE.truncation == 44 { + if !NET_BUFFER_ACTIVE { + use alloc::slice; + // let slice: &[u8] = unsafe { slice::from_raw_parts(dma_addr as *const u8, 16 as usize) }; + let slice32: &[u32] = slice::from_raw_parts(dma_addr as *const u32, 4 as usize); + //print slice + // println!("| Net buffer: {:?}", slice); + // println!("| Net buffer 32: {:?}", slice32); + let _buffer32 = dma_addr as *const u32; + + let rndis_len = slice32[3]; + // let part1 = unsafe { buffer32.offset(0) } as u32; + // println!("| rndis 1 {}", part1); + // println!( + // "| Net buffer length: {} rndis_len: {}", + // last_transfer, rndis_len + // ); + if rndis_len > last_transfer - 44 { + NET_BUFFER_ACTIVE = true; + NET_BUFFER_LEN = rndis_len; + //reenable channel + DwcActivateChannel(channel); + return false; + } + // println!("| NEt continue"); } else { - // println!("| Net buffer not yet active length: {} NETBUFFER {}", last_transfer, NET_BUFFER_LEN); - DwcActivateChannel(channel); - return false; + if last_transfer >= NET_BUFFER_LEN { + // println!("| NEt buffer finished length: {} NETBUFFER {}", last_transfer, NET_BUFFER_LEN); + NET_BUFFER_ACTIVE = false; + last_transfer = NET_BUFFER_LEN; + } else { + // println!("| Net buffer not yet active length: {} NETBUFFER {}", last_transfer, NET_BUFFER_LEN); + DwcActivateChannel(channel); + return false; + } } } } @@ -146,7 +154,12 @@ pub fn finish_bulk_endpoint_callback_in(endpoint: endpoint_descriptor, hcint: u3 return true; } -pub fn finish_bulk_endpoint_callback_out(endpoint: endpoint_descriptor, hcint: u32, channel: u8, _split_control: DWCSplitControlState) -> bool { +pub fn finish_bulk_endpoint_callback_out( + endpoint: endpoint_descriptor, + hcint: u32, + channel: u8, + _split_control: DWCSplitControlState, +) -> bool { let device = unsafe { &mut *endpoint.device }; let transfer_size = HcdUpdateTransferSize(device, channel); if transfer_size > endpoint.buffer_length { @@ -155,12 +168,12 @@ pub fn finish_bulk_endpoint_callback_out(endpoint: endpoint_descriptor, hcint: u channel, transfer_size, endpoint.buffer_length ); } - let last_transfer = endpoint.buffer_length - transfer_size; + let last_transfer = endpoint.buffer_length - transfer_size; - println!( - "Bulk out transfer hcint {:x} , last transfer: {} ", - hcint, last_transfer - ); + // println!( + // "Bulk out transfer hcint {:x} , last transfer: {} ", + // hcint, last_transfer + // ); if hcint & HCINT_CHHLTD == 0 { panic!( "| Endpoint {}: HCINT_CHHLTD not set, aborting. bulk out hcint {:x}", @@ -190,7 +203,12 @@ pub fn finish_bulk_endpoint_callback_out(endpoint: endpoint_descriptor, hcint: u return true; } -pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: u32, channel: u8, split_control: DWCSplitControlState) -> bool { +pub fn finish_interrupt_endpoint_callback( + endpoint: endpoint_descriptor, + hcint_: u32, + channel: u8, + split_control: DWCSplitControlState, +) -> bool { let hcint = hcint_; let device = unsafe { &mut *endpoint.device }; let transfer_size = HcdUpdateTransferSize(device, channel); @@ -209,30 +227,30 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: "| Endpoint {}: HCINT_CHHLTD not set, aborting. hcint: {:x} hcchar: {:x} finish_interrupt_endpoint_callback", channel, hcint, hcchar ); - let mut i = 0; - let mut hcint_nochhltd = 0; - while i < 50 { - let hcint_nochhltd = dwc_otg::read_volatile(DOTG_HCINT(channel as usize)); - if hcint_nochhltd & HCINT_CHHLTD != 0 { - break; - } - i += 1; - micro_delay(10); - } - - if hcint_nochhltd & HCINT_CHHLTD == 0 { - // println!( - // "| Endpoint {}: HCINT_CHHLTD not set, aborting. hcint: {:x} hcint2: {:x}", - // channel, hcint, hcint_nochhltd - // ); - DwcDisableChannel(channel); - hcint_nochhltd = dwc_otg::read_volatile(DOTG_HCINT(channel as usize)); - // return true; - } + // let mut i = 0; + // let mut hcint_nochhltd = 0; + // while i < 50 { + // let hcint_nochhltd = dwc_otg::read_volatile(DOTG_HCINT(channel as usize)); + // if hcint_nochhltd & HCINT_CHHLTD != 0 { + // break; + // } + // i += 1; + // micro_delay(10); + // } + + // if hcint_nochhltd & HCINT_CHHLTD == 0 { + // // println!( + // // "| Endpoint {}: HCINT_CHHLTD not set, aborting. hcint: {:x} hcint2: {:x}", + // // channel, hcint, hcint_nochhltd + // // ); + // DwcDisableChannel(channel); + // // hcint_nochhltd = dwc_otg::read_volatile(DOTG_HCINT(channel as usize)); + // // return true; + // } + + // // hcint |= hcint_nochhltd; - hcint |= hcint_nochhltd; - - return true; + // return true; } let split_control_state = split_control.state; @@ -240,47 +258,55 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: if split_control_state == DWCSplitStateMachine::SSPLIT { if hcint & HCINT_NAK != 0 { - println!("| Endpoint SSPLIT {}: NAK received hcint {:x}", channel, hcint); + println!( + "| Endpoint SSPLIT {}: NAK received hcint {:x}", + channel, hcint + ); DwcEnableChannel(channel); return false; } else if hcint & HCINT_FRMOVRUN != 0 { - println!("| Endpoint SSPLIT {}: Frame overrun hcint {:x}", channel, hcint); + println!( + "| Endpoint SSPLIT {}: Frame overrun hcint {:x}", + channel, hcint + ); UpdateDwcOddFrame(channel); return false; } else if hcint & HCINT_XACTERR != 0 { - println!("| Endpoint SSPLIT {}: XACTERR received hcint {:x}", channel, hcint); + println!( + "| Endpoint SSPLIT {}: XACTERR received hcint {:x}", + channel, hcint + ); DwcEnableChannel(channel); return false; } else if hcint & HCINT_ACK != 0 { //ACK received unsafe { - DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = DWCSplitStateMachine::CSPLIT; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = + DWCSplitStateMachine::CSPLIT; } let mut cur_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; let mut succeed = false; - + while !succeed { while DwcFrameDifference(cur_frame, ss_hfnum) < 2 { cur_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; micro_delay(10); } - unsafe { - let mut frame_val = NEXT_FRAME_CS.lock(); - let current_current_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; - if *frame_val == current_current_frame { - //not succeed - } else { - succeed = true; - *frame_val = current_current_frame; - } + let mut frame_val = NEXT_FRAME_CS.lock(); + let current_current_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + if *frame_val == current_current_frame { + //not succeed + } else { + succeed = true; + *frame_val = current_current_frame; } micro_delay(10); } let frame = DwcActivateCsplit(channel); unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].mr_cs_hfnum = frame; - DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries = 1; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries += 1; } return false; } else { @@ -290,14 +316,27 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: } else if split_control_state == DWCSplitStateMachine::CSPLIT { if hcint & HCINT_NAK != 0 { // println!("| Endpoint CSPLIT {}: NAK received hcint {:x}", channel, hcint); + unsafe { + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = + DWCSplitStateMachine::NONE; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries = 0; + } } else if hcint & HCINT_FRMOVRUN != 0 { - println!("| Endpoint CSPLIT {}: Frame overrun hcint {:x}", channel, hcint); + println!( + "| Endpoint CSPLIT {}: Frame overrun hcint {:x}", + channel, hcint + ); UpdateDwcOddFrame(channel); return false; } else if hcint & HCINT_XACTERR != 0 { - println!("| Endpoint CSPLIT {}: XACTERR received hcint {:x}", channel, hcint); - DwcEnableChannel(channel); - return false; + println!( + "| Endpoint CSPLIT {}: XACTERR received hcint {:x}", + channel, hcint + ); + // DwcEnableChannel(channel); + // return false; + + return true; } else if hcint & HCINT_NYET != 0 { let mut cur_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; @@ -306,33 +345,30 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: return true; } - if unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries >= 3} { - let hctsiz = dwc_otg::read_volatile(DOTG_HCTSIZ(channel as usize)); + if unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries >= 3 } { + // let hctsiz = dwc_otg::read_volatile(DOTG_HCTSIZ(channel as usize)); // println!("| Endpoint CSPLIT {} has exceeded 3 tries, giving up hctsiz {:x} last transfer {:x} state {:?}", channel, hctsiz, last_transfer, unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize] }); return true; } - let mr_cs_hfnum = unsafe { - DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].mr_cs_hfnum - }; + let mr_cs_hfnum = + unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].mr_cs_hfnum }; let mut succeed = false; - + while !succeed { while cur_frame == mr_cs_hfnum { cur_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; micro_delay(10); } - unsafe { - let mut frame_val = NEXT_FRAME_CS.lock(); - let current_current_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; - if *frame_val == current_current_frame { - //not succeed - } else { - succeed = true; - *frame_val = current_current_frame; - } + let mut frame_val = NEXT_FRAME_CS.lock(); + let current_current_frame = dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK; + if *frame_val == current_current_frame { + //not succeed + } else { + succeed = true; + *frame_val = current_current_frame; } micro_delay(10); } @@ -341,7 +377,7 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: println!("| Endpoint CSPLIT {} has exceeded 8 frames (2), cur_frame: {} ss_hfnum: {} giving up tries {}", channel, cur_frame, ss_hfnum, unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries }); return true; } - + let frame = DwcEnableChannel(channel); unsafe { DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].mr_cs_hfnum = frame; @@ -350,13 +386,18 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: return false; } else { unsafe { - DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = DWCSplitStateMachine::NONE; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].state = + DWCSplitStateMachine::NONE; + DWC_CHANNEL_CALLBACK.split_control_state[channel as usize].tries = 0; } if hcint & HCINT_ACK == 0 { let hctsiz = dwc_otg::read_volatile(DOTG_HCTSIZ(channel as usize)); - println!("| Endpoint CSPLIT {}: hcint {:x} last transfer {:x} hctisiz {:x}", channel, hcint, last_transfer, hctsiz); - + println!( + "| Endpoint CSPLIT {}: hcint {:x} last transfer {:x} hctisiz {:x}", + channel, hcint, last_transfer, hctsiz + ); + // use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_GINTSTS; // let gintsts = read_volatile(DOTG_GINTSTS); // use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCINT; @@ -364,7 +405,7 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: // use crate::device::usb::hcd::dwc::dwc_otgreg::DOTG_HCCHAR; // let hcchar = read_volatile(DOTG_HCCHAR(channel as usize)); // let hctsiz = read_volatile(DOTG_HCTSIZ(channel as usize)); - + // println!("| HCD gintsts: {:#x}", gintsts); // println!("| HCD hcint: {:#x}", hcint); // println!("| HCD hcchar: {:#x}", hcchar); @@ -375,19 +416,19 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: } let mut buffer_length = last_transfer.clamp(0, 8); - + if hcint & HCINT_ACK != 0 { endpoint_device.endpoint_pid[endpoint.device_endpoint_number as usize] += 1; - + if last_transfer == 0 { // if endpoint.buffer_length == 0 && transfer_size == 0 { buffer_length = 8; println!("| Endpoint {}: ACK received, but endpoint buffer is 0, weird. buffer len {} transfer siz {}", channel, endpoint.buffer_length, transfer_size); - + // } } } - + let mut buffer = Box::new_uninit_slice(buffer_length as usize); if hcint & HCINT_NAK != 0 { //NAK received, do nothing @@ -408,7 +449,10 @@ pub fn finish_interrupt_endpoint_callback(endpoint: endpoint_descriptor, hcint_: return false; } else { - println!("| Endpoint {}: Unknown interrupt, ignoring {:x} state {:#?}. Letting run for now...", channel, hcint, split_control); + println!( + "| Endpoint {}: Unknown interrupt, ignoring {:x} state {:#?}. Letting run for now...", + channel, hcint, split_control + ); // return true; } @@ -445,7 +489,7 @@ pub fn interrupt_endpoint_callback(endpoint: endpoint_descriptor) { } else { PacketId::Data1 }; - + let result = unsafe { UsbSendInterruptMessage( device, @@ -491,33 +535,10 @@ pub fn register_interrupt_endpoint( let mut interval = interval(μs).with_missed_tick_behavior(MissedTicks::Skip); println!("| USB: Starting interrupt endpoint with interval {} μs", μs); - let hf1 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; - let hf1_time = get_time(); - let mut hf2 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; - let mut hf2_time = get_time(); - while hf1 == hf2 { - hf2 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; - hf2_time = get_time(); - } - let mut hf3 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; - let mut hf3_time = get_time(); - while hf2 == hf3 { - hf3 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; - hf3_time = get_time(); - } - let mut hf4 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; - let mut hf4_time = get_time(); - while hf3 == hf4 { - hf4 = unsafe { dwc_otg::read_volatile(DOTG_HFNUM) & HFNUM_FRNUM_MASK }; - hf4_time = get_time(); - } - println!("| USB: HFNUM: {} {} {} {} {} {} {} {}", hf1, hf1_time, hf2, hf2_time, hf3, hf3_time, hf4, hf4_time); - let mut prev_time = get_time(); while interval.tick().await { let cur_time = get_time(); if cur_time - prev_time < μs { - } else { interrupt_endpoint_callback(endpoint); } diff --git a/crates/kernel/src/device/usb/usbd/request.rs b/crates/kernel/src/device/usb/usbd/request.rs index 740b83b1..9f9ecfe7 100644 --- a/crates/kernel/src/device/usb/usbd/request.rs +++ b/crates/kernel/src/device/usb/usbd/request.rs @@ -66,9 +66,7 @@ pub enum UsbDeviceRequestRequest { Command129 = 129, } -pub fn command_to_usb_device_request( - cmd: u8, -) -> UsbDeviceRequestRequest { +pub fn command_to_usb_device_request(cmd: u8) -> UsbDeviceRequestRequest { match cmd { 0x00 => UsbDeviceRequestRequest::GetStatus, 0x01 => UsbDeviceRequestRequest::ClearFeature, diff --git a/crates/kernel/src/device/usb/usbd/transfer.rs b/crates/kernel/src/device/usb/usbd/transfer.rs index 1d264b10..c4c5491b 100644 --- a/crates/kernel/src/device/usb/usbd/transfer.rs +++ b/crates/kernel/src/device/usb/usbd/transfer.rs @@ -9,9 +9,9 @@ use crate::device::usb::types::UsbTransfer; * */ use crate::device::usb::usbd::pipe::UsbPipeAddress; +use crate::device::usb::DWCSplitControlState; use crate::ringbuffer::SpscRingBuffer; use crate::sync::InterruptSpinLock; -use crate::device::usb::DWCSplitControlState; use alloc::boxed::Box; use super::endpoint::*; diff --git a/crates/kernel/src/device/usb/usbd/usbd.rs b/crates/kernel/src/device/usb/usbd/usbd.rs index ad59f821..1949dc9d 100644 --- a/crates/kernel/src/device/usb/usbd/usbd.rs +++ b/crates/kernel/src/device/usb/usbd/usbd.rs @@ -213,7 +213,10 @@ pub unsafe fn UsbInterruptMessage( } if usb_xfer.buffer_length != 8 { - println!("| USBD: Buffer length is at {} bytes", usb_xfer.buffer_length); + println!( + "| USBD: Buffer length is at {} bytes", + usb_xfer.buffer_length + ); } let result = unsafe { @@ -317,7 +320,7 @@ pub unsafe fn UsbGetDescriptor( "| USBD: Descriptor too short {} {}", device.last_transfer, minimumLength ); - printDWCErrors(0); + // printDWCErrors(0); return ResultCode::ErrorDevice; } @@ -524,7 +527,10 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { return result; } - println!("| USBD: Configuration descriptor: {:?}", device.configuration); + println!( + "| USBD: Configuration descriptor: {:?}", + device.configuration + ); // let configuration_dev = &mut device.configuration; // println!( @@ -560,7 +566,10 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { return result; } - println!("| USBD: Full configuration descriptor: {:?}", fullDescriptor as *mut UsbConfigurationDescriptor); + println!( + "| USBD: Full configuration descriptor: {:?}", + fullDescriptor as *mut UsbConfigurationDescriptor + ); device.configuration_index = configuration; configuration_val = device.configuration.configuration_value; @@ -586,7 +595,10 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { interface as *const u8, size_of::(), ); - println!("| USBD: Interface descriptor: {:?}", device.interfaces[last_interface]); + println!( + "| USBD: Interface descriptor: {:?}", + device.interfaces[last_interface] + ); last_endpoint = 0; is_alternate = false; } else { @@ -606,14 +618,18 @@ fn UsbConfigure(device: &mut UsbDevice, configuration: u8) -> ResultCode { return ResultCode::ErrorDevice; } let endpoint = header as *mut UsbEndpointDescriptor; - + memory_copy( &mut device.endpoints[last_interface][last_endpoint] - as *mut UsbEndpointDescriptor as *mut u8, + as *mut UsbEndpointDescriptor + as *mut u8, endpoint as *const u8, size_of::(), ); - println!("| USBD: Endpoint descriptor: {:?}", device.endpoints[last_interface][last_endpoint]); + println!( + "| USBD: Endpoint descriptor: {:?}", + device.endpoints[last_interface][last_endpoint] + ); last_endpoint += 1; } } @@ -734,14 +750,14 @@ pub fn UsbAttachDevice(device: &mut UsbDevice) -> ResultCode { if device.descriptor.vendor_id == 0xB95 && device.descriptor.product_id == 0x1790 { println!("| USBD: Net: AX88179 Detected"); - let class_attach = bus.interface_class_attach[InterfaceClass::InterfaceClassCommunications as usize]; + let class_attach = + bus.interface_class_attach[InterfaceClass::InterfaceClassCommunications as usize]; let result = class_attach.unwrap()(device, 0); if result != ResultCode::OK { println!("| USBD: Class attach handler failed"); return result; } } - } else { println!("| USBD: Invalid interface class"); } diff --git a/crates/kernel/src/networking/iface/cdcecm.rs b/crates/kernel/src/networking/iface/cdcecm.rs index b8080913..6b1862cc 100644 --- a/crates/kernel/src/networking/iface/cdcecm.rs +++ b/crates/kernel/src/networking/iface/cdcecm.rs @@ -14,10 +14,8 @@ impl CDCECM { } pub fn send(&mut self, buffer: &mut [u8], buffer_len: u32) { - unsafe { - println!("| NET: Send packet of size {}", buffer_len); - NetSendPacket(buffer.as_mut_ptr(), buffer_len); - } + println!("| NET: Send packet of size {}", buffer_len); + NetSendPacket(buffer.as_mut_ptr(), buffer_len); } // TODO: fn recv(&mut self, buffer: &mut [u8], buffer_len: u32) -> Result { @@ -35,10 +33,8 @@ impl CDCECM { impl Device for CDCECM { // TODO: fn send(&mut self, buffer: &[u8], buffer_len: u32) -> Result<()> { fn send(&mut self, buffer: &mut [u8], buffer_len: u32) { - unsafe { - println!("| NET: Send packet of size {}", buffer_len); - NetSendPacket(buffer.as_mut_ptr(), buffer_len); - } + println!("| NET: Send packet of size {}", buffer_len); + NetSendPacket(buffer.as_mut_ptr(), buffer_len); } // TODO: fn recv(&mut self, buffer: &mut [u8], buffer_len: u32) -> Result { diff --git a/crates/kernel/src/networking/iface/ethernet.rs b/crates/kernel/src/networking/iface/ethernet.rs index 2ffb505e..75d7e4f2 100644 --- a/crates/kernel/src/networking/iface/ethernet.rs +++ b/crates/kernel/src/networking/iface/ethernet.rs @@ -1,12 +1,6 @@ use crate::networking::iface::{arp, ipv4, Interface}; use crate::networking::repr::{EthernetAddress, EthernetFrame, EthernetType}; use crate::networking::{Error, Result}; - -use crate::device::usb::device::net::{NetInitiateReceive, NET_DEVICE}; -use crate::device::usb::device::rndis::rndis_receive_packet; -use crate::event::thread; - -use alloc::vec; use alloc::vec::Vec; // serialize the ethernet packet, and send it out over our interface's device @@ -35,9 +29,19 @@ pub fn send_ethernet_frame( // pub static mut LEFT: u32 = 0; // recv ethernet frame from interface: parsed -> fwd to socket -> propogated up stack -pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u32, truncation: usize) -> Result<()> { +pub fn recv_ethernet_frame( + interface: &mut Interface, + eth_buffer: &[u8], + len: u32, + truncation: usize, +) -> Result<()> { println!("[!] received ethernet frame"); - // println!("\t{:x?}", ð_buffer[44..]); + let min_buf = if len > 60 { 60 } else { len }; + println!("\t{:x?}", ð_buffer[0..min_buf as usize]); + + if len < truncation as u32 { + return Err(Error::Ignored); + } // we will truncate the first 44 bytes from the RNDIS protocol // will also need to truncate the first 8 for AX88179 @@ -56,6 +60,6 @@ pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u EthernetType::IPV4 => ipv4::recv_ip_packet(interface, eth_frame), _ => Err(Error::Ignored), }; - + return result; } diff --git a/crates/shell/src/bin/ping.rs b/crates/shell/src/bin/ping.rs new file mode 100644 index 00000000..1cd7f6de --- /dev/null +++ b/crates/shell/src/bin/ping.rs @@ -0,0 +1,19 @@ +#![no_std] +#![cfg_attr(not(test), no_main)] + +extern crate alloc; +#[macro_use] +extern crate ulib; + +#[no_mangle] +extern "C" fn main(argc: usize, argv: *const *const u8) -> ! { + let argv_array = unsafe { core::slice::from_raw_parts(argv, argc) }; + let arg = argv_array[1]; + let arg = unsafe { core::ffi::CStr::from_ptr(arg) }; + let arg_bytes = arg.to_bytes(); + let arg_str = core::str::from_utf8(arg_bytes).unwrap(); + + //Add ping to the kernel + + ulib::sys::exit(0); +} From 8b50a42d2e9328cfd4c222cc95dd4d5f4eeaf4d1 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Thu, 1 May 2025 19:00:43 -0500 Subject: [PATCH 12/13] forgotten ping file --- crates/shell/src/bin/ping.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/shell/src/bin/ping.rs b/crates/shell/src/bin/ping.rs index 1cd7f6de..eeff10a8 100644 --- a/crates/shell/src/bin/ping.rs +++ b/crates/shell/src/bin/ping.rs @@ -13,6 +13,7 @@ extern "C" fn main(argc: usize, argv: *const *const u8) -> ! { let arg_bytes = arg.to_bytes(); let arg_str = core::str::from_utf8(arg_bytes).unwrap(); + println!("| ping: {}", arg_str); //Add ping to the kernel ulib::sys::exit(0); From f960491f24d2f929b1dc2a6a000df615dab28b05 Mon Sep 17 00:00:00 2001 From: Aaron Lo Date: Thu, 1 May 2025 21:49:55 -0500 Subject: [PATCH 13/13] update scripts file --- crates/kernel/scripts/attach-serial.sh | 2 +- crates/kernel/scripts/run-usb.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/kernel/scripts/attach-serial.sh b/crates/kernel/scripts/attach-serial.sh index 4c957e67..94e0bca9 100755 --- a/crates/kernel/scripts/attach-serial.sh +++ b/crates/kernel/scripts/attach-serial.sh @@ -1,4 +1,4 @@ -SERIAL_DEV=/dev/tty.usbserial-B0044ASI +SERIAL_DEV=${1-"-l"} LOGFILE=log/$(date -Is).log echo "Logging to $LOGFILE" tio "$SERIAL_DEV" -b 115200 -d 8 -s 1 -p none -f none -m INLCRNL -L --log-file="$LOGFILE" diff --git a/crates/kernel/scripts/run-usb.sh b/crates/kernel/scripts/run-usb.sh index 004151ff..c222948a 100755 --- a/crates/kernel/scripts/run-usb.sh +++ b/crates/kernel/scripts/run-usb.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -ex -QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" +QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh" # QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -device usb-mouse -device usb-net,netdev=net0 -netdev bridge,id=net0,br=br0 -object filter-dump,id=f1,netdev=net0,file=net0.pcap" "$(dirname "$0")/run.sh"