diff --git a/crates/kernel/examples/net.rs b/crates/kernel/examples/net.rs index 300b489c..44a8c4bd 100644 --- a/crates/kernel/examples/net.rs +++ b/crates/kernel/examples/net.rs @@ -4,87 +4,143 @@ extern crate alloc; extern crate kernel; -use kernel::networking::repr::Ipv4Address; +#[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, connect, recv_from, send_to, SocketAddr, TcpSocket, UdpSocket, + accept, bind, close, connect, listen, recv_from, send_to, SocketAddr, TcpSocket, UdpSocket, }; use kernel::*; +use alloc::string::String; + #[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); - } - - // [udp send test] + 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(); + let _ = 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]), + // addr: Ipv4Address::new([10, 0, 2, 2]), // port: 1337, // }; // for _i in 0..5 { - // let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr); + // 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] - // 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, - }; - - 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); - } - - for _i in 0..5 { - let _ = send_to(s, "hello everynyan".as_bytes().to_vec(), saddr); - } + // 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] - // 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 + // bind(s, 22); + + // listen(s, 1).await; // - // let client = accept(s); - // // WARN: same as above, but for tcp handshake - // for _i in 0..count { - // sync::spin_sleep(100_000); - // } + // let clientfd = accept(s).await; // - // loop { - // sync::spin_sleep(500_000); - // let recv = recv_from(s); + // 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; // } // } + // + // println!("got {} bytes", tot); + + // [http request test] + println!("http send test"); + // let host = "http.badssl.com"; + // let host = "http-textarea.badssl.com"; + // 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/scripts/attach-serial.sh b/crates/kernel/scripts/attach-serial.sh index 83fe5f7d..94e0bca9 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=${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 6bd83720..c222948a 100755 --- a/crates/kernel/scripts/run-usb.sh +++ b/crates/kernel/scripts/run-usb.sh @@ -1,5 +1,4 @@ #!/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="-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" @@ -7,3 +6,5 @@ QEMU_DISPLAY=${QEMU_DISPLAY-"default"} QEMU_DEVICES="-usb -device usb-kbd -devic # 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/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/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/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); // } } } 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/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); // } } } diff --git a/crates/kernel/src/device/usb.rs b/crates/kernel/src/device/usb.rs index a4a8a286..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; @@ -37,9 +36,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..06ef0d6f 100644 --- a/crates/kernel/src/device/usb/device.rs +++ b/crates/kernel/src/device/usb/device.rs @@ -1,3 +1,4 @@ +pub mod ax88179; pub mod hid; pub mod hub; pub mod net; 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..130979cd --- /dev/null +++ b/crates/kernel/src/device/usb/device/ax88179.rs @@ -0,0 +1,1475 @@ +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::PacketId; +use crate::device::usb::UsbControlMessage; +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 tx_hdr1 = buffer_length as u32; + let 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"); + 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. + */ + 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; + } + /* 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 tmp16 = buf.as_mut_ptr() as *mut u16; + let 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); + 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); + //{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; + + *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; + 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 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 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; + } + } 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 buf: u16; + buf = unsafe { core::ptr::read(data as *const u16) }; + let _ = 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..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, @@ -210,19 +211,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 fdff7701..dcc64324 100644 --- a/crates/kernel/src/device/usb/device/net.rs +++ b/crates/kernel/src/device/usb/device/net.rs @@ -11,12 +11,16 @@ use core::slice; 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::shutdown; +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; @@ -25,6 +29,9 @@ use super::rndis::*; pub static mut NET_DEVICE: NetDevice = NetDevice { receive_callback: None, device: None, + net_send: None, + net_receive: None, + truncation: 0, }; pub static mut INTERFACE: Option = None; @@ -45,33 +52,32 @@ 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, // 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); + NET_DEVICE.truncation = 8; + } + } 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); + NET_DEVICE.truncation = 44; + } } let driver_data = Box::new(UsbEndpointDevice::new()); @@ -91,42 +97,59 @@ 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. // 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]; + + 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]); } - - 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]); } println!("| Net: MAC Address: {:x?}", mac_addr); @@ -148,33 +171,55 @@ 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]; - unsafe { - rndis_receive_packet(device, 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(), 1518); // TODO: ask aaron if I need to use another function? // start dhcp 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; } +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(); + 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) }; 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) { @@ -183,19 +228,23 @@ 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!("| Net: Sent of length {}", _buffer_length); } 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 { @@ -205,6 +254,9 @@ pub unsafe fn NetReceive(buffer: *mut u8, buffer_length: u32) { println!("| Net: No callback for receive."); } } + + let buf = vec![0u8; 1]; + NetInitiateReceive(buf.into_boxed_slice(), 1600); } pub fn RegisterNetReceiveCallback(callback: unsafe fn(*mut u8, u32)) { @@ -213,23 +265,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>, + pub truncation: usize, } #[repr(u32)] diff --git a/crates/kernel/src/device/usb/device/rndis.rs b/crates/kernel/src/device/usb/device/rndis.rs index 2a814185..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, @@ -29,7 +53,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/device/usb/hcd/dwc/dwc_otg.rs b/crates/kernel/src/device/usb/hcd/dwc/dwc_otg.rs index ccfa50a7..19e602f2 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. @@ -47,10 +47,14 @@ 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) { + // 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 +66,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 +79,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 +114,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 +141,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 +287,21 @@ 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 +329,16 @@ 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 +361,23 @@ 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); @@ -401,7 +496,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, @@ -436,13 +531,23 @@ 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 { println!("| HCD: Request to device has timed out."); - printDWCErrors(channel as u32); + // printDWCErrors(channel as u32); device.error = UsbTransferError::ConnectionError; return ResultCode::ErrorTimeout; } @@ -454,7 +559,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,7 +569,16 @@ pub fn HcdChannelSendWaitOne( ); hcint = read_volatile(DOTG_HCINT(channel as usize)); - if pipe.speed != UsbSpeed::High { + // 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. @@ -509,6 +624,8 @@ pub fn HcdChannelSendWaitOne( } } + println!("| HCD split completion timeout {}", timeout); + if hcint & HCINT_NYET == 0 { break; } @@ -527,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; } @@ -560,20 +677,36 @@ 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 +782,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 +814,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 +832,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 +879,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 +898,39 @@ 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 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 + write_volatile( DOTG_HCCHAR(channel as usize), convert_host_characteristics(dwc_sc.channel[channel as usize].characteristics), @@ -776,32 +954,38 @@ 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, + ); + + // 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_XFERCOMPLMSK + HCINTMSK_CHHLTDMSK, // | HCINTMSK_AHBERRMSK + // | HCINTMSK_STALLMSK + // | HCINTMSK_NAKMSK + // | HCINTMSK_ACKMSK + // | HCINTMSK_NYETMSK + // | HCINTMSK_XACTERRMSK + // | HCINTMSK_BBLERRMSK + // | HCINTMSK_FRMOVRUNMSK + // | HCINTMSK_DATATGLERRMSK, ); } @@ -875,7 +1059,7 @@ pub unsafe fn HcdSubmitBulkMessage( unsafe { memory_copy( data_buffer, - buffer.unwrap().as_ptr(), + buffer.unwrap().as_mut_ptr(), buffer_length as usize, ); } @@ -898,6 +1082,82 @@ 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, @@ -937,23 +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, @@ -1001,7 +1244,10 @@ pub unsafe fn HcdSubmitControlMessage( return result; } - let mut is_data1 = true; + // println!("| HCD: Control message sent to device.\n"); + // printDWCErrors(0); + + let is_data1 = true; if !buffer.is_null() { if pipe.direction == UsbDirection::Out { @@ -1026,7 +1272,7 @@ pub unsafe fn HcdSubmitControlMessage( } else { PacketId::Data0 }; - is_data1 = !is_data1; + result = HcdChannelSendWait( device, &mut tempPipe, @@ -1036,10 +1282,11 @@ pub unsafe fn HcdSubmitControlMessage( request, pid, ); + if result != ResultCode::OK { println!("| HCD: Coult not send data to device\n"); - printDWCErrors(0); + // printDWCErrors(0); return result; } @@ -1070,6 +1317,27 @@ 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; @@ -1083,15 +1351,15 @@ pub unsafe fn HcdSubmitControlMessage( tempPipe.direction = UsbDirection::Out; } - let pid = if is_data1 { - PacketId::Data1 - } else { - PacketId::Data0 - }; - - // 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 + // 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 result = HcdChannelSendWait( device, &mut tempPipe, @@ -1248,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); @@ -1343,12 +1614,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); @@ -1683,6 +1955,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], @@ -1723,8 +2022,10 @@ 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 { @@ -1732,6 +2033,7 @@ impl DwcChannelCallback { Self { callback: [None; ChannelCount], endpoint_descriptors: [None; ChannelCount], + split_control_state: [DWCSplitControlState::new(); ChannelCount], } } } @@ -1864,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/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 2d751f39..50c9e3f8 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,9 +9,23 @@ */ 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::UpdateDwcOddFrame; -use crate::device::usb::hcd::dwc::dwc_otgreg::HCINT_FRMOVRUN; +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::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 usb::dwc_hub; use usb::hcd::dwc::dwc_otg::HcdUpdateTransferSize; @@ -21,56 +36,59 @@ use usb::usbd::pipe::*; use usb::PacketId; use crate::event::task::spawn_async_rt; -use crate::shutdown; 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 static NEXT_FRAME_CS: SpinLock = SpinLock::new(0); +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); - device.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 {}: 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 {} in: HCINT_NAK with transfer hcint: {:x} last transfer: {}", - channel, hcint, device.last_transfer + "| Endpoint {}: hctsiz {:x} hcint {:x}", + channel, hctsiz, hcint ); + last_transfer = transfer_size; + } else { + last_transfer = endpoint.buffer_length - transfer_size; + } - if device.last_transfer > 0 && (hcint & HCINT_CHHLTD == 0) && (hcint & HCINT_XFERCOMPL == 0) - { - DwcActivateChannel(channel); + // let last_transfer = endpoint.buffer_length - transfer_size; + let endpoint_device = device.driver_data.downcast::().unwrap(); - return false; - } else { - 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 + "| Endpoint {} in: HCINT_CHHLTD not set, not aborting. hcint: {:x}.", + 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); + let dwc_sc = unsafe { &mut *(device.soft_sc as *mut dwc_hub) }; let dma_addr = dwc_sc.dma_addr[channel as usize]; @@ -80,12 +98,53 @@ 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: TODO: FIX + unsafe { + 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 { + 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 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 {}.", @@ -99,42 +158,62 @@ 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); - device.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: {} ", + // 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 {}.", endpoint.device_endpoint_number ); } - + // device.last_transfer = last_transfer; return true; } pub fn finish_interrupt_endpoint_callback( endpoint: endpoint_descriptor, - hcint: u32, + 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; + // 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,24 +222,217 @@ 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 + 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 ); - 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; + + // return true; } - let buffer_length = device.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); + } + + 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); + 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 + ); + UpdateDwcOddFrame(channel); + return false; + } else if hcint & HCINT_XACTERR != 0 { + 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; + + 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); + } + + 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; + 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 + ); + + // 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 @@ -178,10 +450,10 @@ pub fn finish_interrupt_endpoint_callback( return false; } else { println!( - "| Endpoint {}: Unknown interrupt, ignoring {}.", - channel, hcint + "| Endpoint {}: Unknown interrupt, ignoring {:x} state {:#?}. Letting run for now...", + channel, hcint, split_control ); - return true; + // return true; } let mut buffer = unsafe { buffer.assume_init() }; @@ -194,6 +466,8 @@ pub fn finish_interrupt_endpoint_callback( endpoint.device_endpoint_number ); } + + // device.last_transfer = last_transfer; return true; } @@ -259,8 +533,16 @@ 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 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..9f9ecfe7 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,24 @@ 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..c4c5491b 100644 --- a/crates/kernel/src/device/usb/usbd/transfer.rs +++ b/crates/kernel/src/device/usb/usbd/transfer.rs @@ -9,6 +9,7 @@ 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 alloc::boxed::Box; @@ -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..1949dc9d 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,13 @@ 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, @@ -313,7 +320,7 @@ pub unsafe fn UsbGetDescriptor( "| USBD: Descriptor too short {} {}", device.last_transfer, minimumLength ); - printDWCErrors(0); + // printDWCErrors(0); return ResultCode::ErrorDevice; } @@ -457,6 +464,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 +508,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 +527,11 @@ 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 +566,11 @@ 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 +581,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 +595,46 @@ 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 +644,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 +745,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 +824,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/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..6b1862cc 100644 --- a/crates/kernel/src/networking/iface/cdcecm.rs +++ b/crates/kernel/src/networking/iface/cdcecm.rs @@ -12,14 +12,29 @@ impl CDCECM { max_transmission_unit: mtu, } } + + pub fn send(&mut self, buffer: &mut [u8], buffer_len: u32) { + 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 { // TODO: fn send(&mut self, buffer: &[u8], buffer_len: u32) -> Result<()> { fn send(&mut self, buffer: &mut [u8], buffer_len: u32) { - unsafe { - 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/dhcp.rs b/crates/kernel/src/networking/iface/dhcp.rs index 6452ef75..91c34ff7 100644 --- a/crates/kernel/src/networking/iface/dhcp.rs +++ b/crates/kernel/src/networking/iface/dhcp.rs @@ -1,10 +1,11 @@ use crate::device::system_timer; +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; @@ -40,7 +41,7 @@ pub struct Dhcpd { rebind_time: Option, subnet_mask: u32, router: Option, - dns_servers: Vec, + pub dns_servers: Vec, udp_socket: u16, } @@ -71,7 +72,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 +87,18 @@ impl Dhcpd { self.state = DhcpState::Discovering; self.last_action_time = time; - send_dhcp_discover(interface, self.udp_socket, self.xid) + 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(); + let _ = 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 +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); + send_dhcp_release(interface, self.xid, offered_ip, server_id, self.udp_socket) + .await; self.state = DhcpState::Released; result } else { @@ -106,11 +117,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 +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)?; + 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); @@ -182,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) @@ -203,7 +217,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 +233,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 +264,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 +306,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 +339,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 +369,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 +402,24 @@ 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 +431,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..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::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 @@ -31,13 +25,27 @@ 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<()> { +pub fn recv_ethernet_frame( + interface: &mut Interface, + eth_buffer: &[u8], + len: u32, + truncation: usize, +) -> Result<()> { println!("[!] received ethernet frame"); - println!("\t{:x?}", eth_buffer); + 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 - 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 @@ -53,14 +61,5 @@ pub fn recv_ethernet_frame(interface: &mut Interface, eth_buffer: &[u8], _len: u _ => 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(); - rndis_receive_packet(device, buf.into_boxed_slice(), 1500); - } - }); - return result; } diff --git a/crates/kernel/src/networking/iface/ipv4.rs b/crates/kernel/src/networking/iface/ipv4.rs index b1f3893d..f23d5ce5 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; @@ -30,6 +31,7 @@ pub fn send_ipv4_packet( Err(e) => { 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); }); @@ -39,20 +41,18 @@ 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); } 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); } @@ -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/iface/mod.rs b/crates/kernel/src/networking/iface/mod.rs index 6b42123d..c7ecfb89 100644 --- a/crates/kernel/src/networking/iface/mod.rs +++ b/crates/kernel/src/networking/iface/mod.rs @@ -9,11 +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::collections::btree_map::BTreeMap; pub mod arp; @@ -22,7 +21,6 @@ pub mod dhcp; pub mod ethernet; pub mod icmp; pub mod ipv4; -pub mod socket; pub mod tcp; pub mod udp; @@ -31,7 +29,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 +37,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 deleted file mode 100644 index e93e37ba..00000000 --- a/crates/kernel/src/networking/iface/socket.rs +++ /dev/null @@ -1,30 +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() { - 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(); - }); -} diff --git a/crates/kernel/src/networking/iface/tcp.rs b/crates/kernel/src/networking/iface/tcp.rs index 6450d6a2..685ddc9f 100644 --- a/crates/kernel/src/networking/iface/tcp.rs +++ b/crates/kernel/src/networking/iface/tcp.rs @@ -1,8 +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::{Error, Result}; +use crate::event::task; use alloc::vec::Vec; pub fn send_tcp_packet( @@ -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..e1df1076 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::{Error, Result}; + +use crate::event::task; use alloc::vec::Vec; @@ -28,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 { @@ -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/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/repr/dns.rs b/crates/kernel/src/networking/repr/dns.rs new file mode 100644 index 00000000..ea7e30b0 --- /dev/null +++ b/crates/kernel/src/networking/repr/dns.rs @@ -0,0 +1,284 @@ +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}; + +#[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, +} + +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(), + } + } + + 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); + } + } + + return None; + } + + 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; + } + + Ok(Packet { + header: DnsHeader { + id, + flags, + qdcount, + ancount, + nscount, + arcount, + }, + questions, + answers, + authorities, + additionals, + }) + } + + 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(); + let mut jumped = false; + let original_offset = offset; + + loop { + if offset >= buffer.len() { + return Err(Error::Malformed); + } + + 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 !jumped { + Ok((labels.join("."), offset)) + } else { + Ok((labels.join("."), original_offset + 2)) // after pointer + } +} + +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..1a012355 --- /dev/null +++ b/crates/kernel/src/networking/repr/http.rs @@ -0,0 +1,206 @@ +use crate::networking::{Error, Result}; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; + +#[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/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/networking/repr/mod.rs b/crates/kernel/src/networking/repr/mod.rs index 2767b896..03af254a 100644 --- a/crates/kernel/src/networking/repr/mod.rs +++ b/crates/kernel/src/networking/repr/mod.rs @@ -20,7 +20,9 @@ mod arp; pub mod dev; mod dhcp; +mod dns; mod ethernet; +mod http; mod icmp; mod ipv4; mod tcp; @@ -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::{Method as HttpMethod, Packet as HttpPacket}; + 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/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..078be213 100644 --- a/crates/kernel/src/networking/socket/bindings.rs +++ b/crates/kernel/src/networking/socket/bindings.rs @@ -4,10 +4,12 @@ use core::sync::atomic::{AtomicU16, Ordering}; use alloc::vec::Vec; -use crate::networking::repr::Ipv4Address; +use crate::networking::repr::{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 super::UdpSocket; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct SocketAddr { @@ -22,6 +24,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, + }; + + 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, + } + } } impl Display for SocketAddr { @@ -30,16 +55,24 @@ 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 +84,15 @@ 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 +102,30 @@ 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 +134,36 @@ 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 async fn accept(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 + let _ = tagged_socket.accept().await; + Ok(socketfd) } -pub fn accept(socketfd: u16) -> Result { +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 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.close().await } pub fn bind(socketfd: u16, port: u16) -> Result<()> { @@ -122,15 +173,16 @@ 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..808487aa 100644 --- a/crates/kernel/src/networking/socket/mod.rs +++ b/crates/kernel/src/networking/socket/mod.rs @@ -3,12 +3,13 @@ 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::{ + accept, bind, close, connect, listen, recv_from, send_to, SockType, SocketAddr, +}; 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..abab0293 100644 --- a/crates/kernel/src/networking/socket/raw.rs +++ b/crates/kernel/src/networking/socket/raw.rs @@ -1,5 +1,13 @@ -use crate::networking::utils::{ring::Ring, slice::Slice}; -use crate::networking::Result; +use crate::device::usb::device::net::get_interface_mut; +use crate::networking::iface::ipv4; +use crate::networking::iface::Interface; +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; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RawType { @@ -8,60 +16,83 @@ 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 { + pub fn new(raw_type: RawType) -> 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..f3f477c3 100644 --- a/crates/kernel/src/networking/socket/tagged.rs +++ b/crates/kernel/src/networking/socket/tagged.rs @@ -1,11 +1,13 @@ -use crate::networking::iface::Interface; -use crate::networking::socket::{SocketAddr, TcpSocket, UdpSocket}; +use crate::networking::socket::{SockType, SocketAddr, TcpSocket, UdpSocket}; 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 +15,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 +32,55 @@ 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::Tcp(socket) => socket.send_enqueue(payload, saddr), + TaggedSocket::Udp(socket) => socket.send_enqueue(payload, saddr).await, + TaggedSocket::Tcp(socket) => socket.send_enqueue(payload, saddr).await, } } - // 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 +92,37 @@ 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 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 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..2f4de1d1 100644 --- a/crates/kernel/src/networking/socket/tcp.rs +++ b/crates/kernel/src/networking/socket/tcp.rs @@ -1,22 +1,13 @@ use crate::device::usb::device::net::get_interface_mut; use crate::networking::iface::{tcp, Interface}; use crate::networking::socket::bindings::{NEXT_EPHEMERAL, 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::{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; -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) -} - -pub static TCP_BUFFER_LEN: usize = 128; - // flags pub const TCP_FLAG_FIN: u8 = 0x01; pub const TCP_FLAG_SYN: u8 = 0x02; @@ -48,19 +39,25 @@ 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 +68,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 +97,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 +114,12 @@ 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 +130,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); + + let _ = 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(), + ); + + let _ = 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 { @@ -149,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, @@ -159,210 +216,86 @@ impl TcpSocket { self.window_size, saddr.addr, Vec::new(), // no payload - )?; + ); self.state = TcpState::SynSent; println!("[!] sent syn"); + 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); - } - - self.send_buffer.enqueue_maybe(|(buffer, addr)| { - *buffer = payload; - *addr = dest; - Ok(()) - }) - } - - pub fn send(&mut self, interface: &mut Interface) -> Result<()> { - if self.state != TcpState::Established { - return Err(Error::NotConnected); - } + // if let Some(remote) = self.remote_addr { + // if remote != dest { + // return Err(Error::NotConnected); + // } + // } else { + // return Err(Error::NotConnected); + // } - 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(), - )?; + let interface = get_interface_mut(); + 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, + ); - // Update sequence number - self.seq_number += payload.len() as u32; - } - Err(Error::Exhausted) => break, - Err(e) => return Err(e), - } - } - Ok(()) - } - _ => Err(Error::NotConnected), - } - } + let _ = self.recv().await; - 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()) - }) + Ok(()) } - // Enqueues a packet for receiving and handles TCP state machine - pub fn recv_enqueue( - &mut self, - interface: &mut Interface, - seq_number: u32, - ack_number: u32, - flags: u8, - 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)?; + pub async fn recv(&mut self) -> Result<(Vec, SocketAddr)> { + let interface = get_interface_mut(); - // 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(), - )?; - } - } + let (mut payload, addr) = self.recv_rx.recv().await; + let last = &payload[payload.len() - 2..payload.len()]; + self.window_size = u16::from_le_bytes([last[0], last[1]]); + 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]; + let seq_number = u32::from_le_bytes([last[0], last[1], last[2], last[3]]); - Ok(()) - } + payload.truncate(payload.len().saturating_sub(11)); // get rid of context bytes - // 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::Established => { - // Handle FIN from remote - if flags & TCP_FLAG_FIN != 0 { - self.ack_number = seq_number + 1; // FIN consumes a sequence number + TcpState::SynSent => { + 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; - } - - // Handle RST from remote - if flags & TCP_FLAG_RST != 0 { - self.state = TcpState::Closed; - self.connected = false; - self.remote_addr = None; + self.state = TcpState::Established; } } - TcpState::FinWait1 => { if flags & TCP_FLAG_ACK != 0 { // Our FIN was acknowledged @@ -392,12 +325,10 @@ impl TcpSocket { } } } - 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, @@ -413,41 +344,106 @@ 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(); + + if flags & TCP_FLAG_FIN != 0 { + self.state = TcpState::Closed; + + self.ack_number += 1; + 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(), + ); - // Handle other states as needed + return Err(Error::Closed); + } + + if payload.len() > 0 { + self.ack_number += payload.len() as u32; + self.seq_number += 1; + 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)) + } + + 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. 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 - 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, @@ -464,6 +460,13 @@ impl TcpSocket { self.seq_number += 1; // FIN consumes a sequence number self.state = TcpState::FinWait1; } + + let _ = self.recv().await; + + if self.state == TcpState::FinWait2 { + let _ = self.recv().await; + } + Ok(()) } TcpState::CloseWait => { diff --git a/crates/kernel/src/networking/socket/udp.rs b/crates/kernel/src/networking/socket/udp.rs index 1c103fb0..39078728 100644 --- a/crates/kernel/src/networking/socket/udp.rs +++ b/crates/kernel/src/networking/socket/udp.rs @@ -2,53 +2,55 @@ 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::{SockType, SocketAddr}; use crate::networking::{Error, Result}; +use crate::ringbuffer::{channel, Receiver, Sender}; -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 +63,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 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_recv_ref(&mut self) -> (SockType, Receiver, SocketAddr)>) { + (SockType::UDP, self.recv_rx.clone()) + } - Ok(()) + pub fn get_send_ref(&mut self) -> (SockType, Sender, SocketAddr)>) { + (SockType::UDP, self.recv_tx.clone()) } - // 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 async fn recv(&mut self) -> Result<(Vec, SocketAddr)> { + let (payload, addr) = self.recv_rx.recv().await; + Ok((payload, addr)) } - // 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 fn try_recv(&mut self) -> Result<(Vec, SocketAddr)> { + match self.recv_rx.try_recv() { + Some((payload, addr)) => Ok((payload, addr)), + None => Err(Error::Exhausted), + } + } + + 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) 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(); } diff --git a/crates/shell/src/bin/ping.rs b/crates/shell/src/bin/ping.rs new file mode 100644 index 00000000..eeff10a8 --- /dev/null +++ b/crates/shell/src/bin/ping.rs @@ -0,0 +1,20 @@ +#![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(); + + println!("| ping: {}", arg_str); + //Add ping to the kernel + + ulib::sys::exit(0); +}