Compare commits

..

No commits in common. "4b5a8196c37502110f09e2f055bab5ea622242e9" and "bd426199f81b470733eac81f0e7d19c050985ef2" have entirely different histories.

47 changed files with 468 additions and 1671 deletions

View File

@ -108,7 +108,6 @@ set(KERNEL_SOURCES
kernel/USB/Controller.cpp kernel/USB/Controller.cpp
kernel/USB/Device.cpp kernel/USB/Device.cpp
kernel/USB/HID/HIDDriver.cpp kernel/USB/HID/HIDDriver.cpp
kernel/USB/HID/Joystick.cpp
kernel/USB/HID/Keyboard.cpp kernel/USB/HID/Keyboard.cpp
kernel/USB/HID/Mouse.cpp kernel/USB/HID/Mouse.cpp
kernel/USB/Hub/HubDriver.cpp kernel/USB/Hub/HubDriver.cpp

View File

@ -16,7 +16,6 @@ namespace Kernel
Debug, Debug,
Keyboard, Keyboard,
Mouse, Mouse,
Joystick,
SCSI, SCSI,
NVMeController, NVMeController,
NVMeNamespace, NVMeNamespace,

View File

@ -61,8 +61,8 @@ namespace Kernel
// NOTE: the inode might have more blocks than what this suggests if it has been shrinked // NOTE: the inode might have more blocks than what this suggests if it has been shrinked
uint32_t max_used_data_block_count() const { return size() / blksize(); } uint32_t max_used_data_block_count() const { return size() / blksize(); }
BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t& block, uint32_t index, uint32_t depth, bool allocate); BAN::ErrorOr<BAN::Optional<uint32_t>> block_from_indirect_block(uint32_t block, uint32_t index, uint32_t depth);
BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index, bool allocate); BAN::ErrorOr<BAN::Optional<uint32_t>> fs_block_of_data_block_index(uint32_t data_block_index);
BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name); BAN::ErrorOr<void> link_inode_to_directory(Ext2Inode&, BAN::StringView name);
BAN::ErrorOr<void> remove_inode_from_directory(BAN::StringView name, bool cleanup_directory); BAN::ErrorOr<void> remove_inode_from_directory(BAN::StringView name, bool cleanup_directory);
@ -72,6 +72,8 @@ namespace Kernel
BAN::ErrorOr<void> cleanup_default_links(); BAN::ErrorOr<void> cleanup_default_links();
BAN::ErrorOr<void> cleanup_from_fs(); BAN::ErrorOr<void> cleanup_from_fs();
BAN::ErrorOr<uint32_t> allocate_new_block_to_indirect_block(uint32_t& block, uint32_t index, uint32_t depth);
BAN::ErrorOr<uint32_t> allocate_new_block(uint32_t data_block_index);
BAN::ErrorOr<void> sync(); BAN::ErrorOr<void> sync();
uint32_t block_group() const; uint32_t block_group() const;
@ -84,26 +86,6 @@ namespace Kernel
{} {}
static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t); static BAN::ErrorOr<BAN::RefPtr<Ext2Inode>> create(Ext2FS&, uint32_t);
private:
struct ScopedSync
{
ScopedSync(Ext2Inode& inode)
: inode(inode)
, inode_info(inode.m_inode)
{ }
~ScopedSync()
{
if (memcmp(&inode.m_inode, &inode_info, sizeof(Ext2::Inode)) == 0)
return;
if (auto ret = inode.sync(); ret.is_error())
dwarnln("failed to sync inode: {}", ret.error());
}
Ext2Inode& inode;
Ext2::Inode inode_info;
};
private: private:
Ext2FS& m_fs; Ext2FS& m_fs;
Ext2::Inode m_inode; Ext2::Inode m_inode;

View File

@ -15,7 +15,6 @@ namespace Kernel
{ {
Mouse, Mouse,
Keyboard, Keyboard,
Joystick,
}; };
public: public:

View File

@ -1,97 +0,0 @@
#pragma once
#include <kernel/Lock/Mutex.h>
#include <kernel/Lock/LockGuard.h>
namespace Kernel
{
class RWLock
{
BAN_NON_COPYABLE(RWLock);
BAN_NON_MOVABLE(RWLock);
public:
RWLock() = default;
void rd_lock()
{
LockGuard _(m_mutex);
while (m_writers_waiting > 0 || m_writer_active)
m_thread_blocker.block_indefinite(&m_mutex);
m_readers_active++;
}
void rd_unlock()
{
LockGuard _(m_mutex);
if (--m_readers_active == 0)
m_thread_blocker.unblock();
}
void wr_lock()
{
LockGuard _(m_mutex);
m_writers_waiting++;
while (m_readers_active > 0 || m_writer_active)
m_thread_blocker.block_indefinite(&m_mutex);
m_writers_waiting--;
m_writer_active = true;
}
void wr_unlock()
{
LockGuard _(m_mutex);
m_writer_active = false;
m_thread_blocker.unblock();
}
private:
Mutex m_mutex;
ThreadBlocker m_thread_blocker;
uint32_t m_readers_active { 0 };
uint32_t m_writers_waiting { 0 };
bool m_writer_active { false };
};
class RWLockRDGuard
{
BAN_NON_COPYABLE(RWLockRDGuard);
BAN_NON_MOVABLE(RWLockRDGuard);
public:
RWLockRDGuard(RWLock& lock)
: m_lock(lock)
{
m_lock.rd_lock();
}
~RWLockRDGuard()
{
m_lock.rd_unlock();
}
private:
RWLock& m_lock;
};
class RWLockWRGuard
{
BAN_NON_COPYABLE(RWLockWRGuard);
BAN_NON_MOVABLE(RWLockWRGuard);
public:
RWLockWRGuard(RWLock& lock)
: m_lock(lock)
{
m_lock.wr_lock();
}
~RWLockWRGuard()
{
m_lock.wr_unlock();
}
private:
RWLock& m_lock;
};
}

View File

@ -45,7 +45,7 @@ namespace Kernel
void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan); void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
virtual void unbind_socket(uint16_t port) override; virtual void unbind_socket(uint16_t port) override;
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) override; virtual BAN::ErrorOr<void> bind_socket_to_unused(BAN::RefPtr<NetworkSocket>, const sockaddr* send_address, socklen_t send_address_len) override;
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override; virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override;
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) override; virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) override;
@ -59,8 +59,6 @@ namespace Kernel
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const; void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const;
BAN::ErrorOr<in_port_t> find_free_port();
void packet_handle_task(); void packet_handle_task();
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ByteSpan); BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ByteSpan);

View File

@ -23,7 +23,7 @@ namespace Kernel
virtual ~NetworkLayer() {} virtual ~NetworkLayer() {}
virtual void unbind_socket(uint16_t port) = 0; virtual void unbind_socket(uint16_t port) = 0;
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) = 0; virtual BAN::ErrorOr<void> bind_socket_to_unused(BAN::RefPtr<NetworkSocket>, const sockaddr* send_address, socklen_t send_address_len) = 0;
virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0; virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0;
virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) = 0; virtual BAN::ErrorOr<void> get_socket_address(BAN::RefPtr<NetworkSocket>, sockaddr* address, socklen_t* address_len) = 0;

View File

@ -5,8 +5,6 @@
#include <kernel/Networking/NetworkInterface.h> #include <kernel/Networking/NetworkInterface.h>
#include <kernel/Networking/NetworkLayer.h> #include <kernel/Networking/NetworkLayer.h>
#include <netinet/in.h>
namespace Kernel namespace Kernel
{ {
@ -26,10 +24,10 @@ namespace Kernel
static constexpr uint16_t PORT_NONE = 0; static constexpr uint16_t PORT_NONE = 0;
public: public:
void bind_address_and_port(const sockaddr*, socklen_t); void bind_interface_and_port(NetworkInterface*, uint16_t port);
~NetworkSocket(); ~NetworkSocket();
BAN::ErrorOr<BAN::RefPtr<NetworkInterface>> interface(const sockaddr* target, socklen_t target_len); NetworkInterface& interface() { ASSERT(m_interface); return *m_interface; }
virtual size_t protocol_header_size() const = 0; virtual size_t protocol_header_size() const = 0;
virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) = 0; virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) = 0;
@ -37,19 +35,7 @@ namespace Kernel
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0; virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0;
bool is_bound() const { return m_address_len >= static_cast<socklen_t>(sizeof(sa_family_t)) && m_address.ss_family != AF_UNSPEC; } bool is_bound() const { return m_interface != nullptr; }
in_port_t bound_port() const
{
ASSERT(is_bound());
ASSERT(m_address.ss_family == AF_INET && m_address_len >= static_cast<socklen_t>(sizeof(sockaddr_in)));
return BAN::network_endian_to_host(reinterpret_cast<const sockaddr_in*>(&m_address)->sin_port);
}
const sockaddr* address() const { return reinterpret_cast<const sockaddr*>(&m_address); }
socklen_t address_len() const { return m_address_len; }
private:
bool can_interface_send_to(const NetworkInterface&, const sockaddr*, socklen_t) const;
protected: protected:
NetworkSocket(NetworkLayer&, const Socket::Info&); NetworkSocket(NetworkLayer&, const Socket::Info&);
@ -59,9 +45,9 @@ namespace Kernel
virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override = 0; virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override = 0;
protected: protected:
NetworkLayer& m_network_layer; NetworkLayer& m_network_layer;
sockaddr_storage m_address { .ss_family = AF_UNSPEC, .ss_storage = {} }; NetworkInterface* m_interface = nullptr;
socklen_t m_address_len { 0 }; uint16_t m_port { PORT_NONE };
}; };
} }

View File

@ -57,9 +57,8 @@ namespace Kernel
static ProcessorID current_id() { return read_gs_sized<ProcessorID>(offsetof(Processor, m_id)); } static ProcessorID current_id() { return read_gs_sized<ProcessorID>(offsetof(Processor, m_id)); }
static ProcessorID id_from_index(size_t index); static ProcessorID id_from_index(size_t index);
static uint8_t count() { return s_processor_count; } static uint8_t count() { return s_processor_count; }
static bool is_smp_enabled() { return s_is_smp_enabled; } static bool is_smp_enabled() { return s_is_smp_enabled; }
static void set_smp_enabled() { s_is_smp_enabled = true; }
static void wait_until_processors_ready(); static void wait_until_processors_ready();
static void toggle_should_print_cpu_load() { s_should_print_cpu_load = !s_should_print_cpu_load; } static void toggle_should_print_cpu_load() { s_should_print_cpu_load = !s_should_print_cpu_load; }

View File

@ -82,8 +82,6 @@ namespace Kernel
void update_most_loaded_node_queue(SchedulerQueue::Node*, SchedulerQueue* target_queue); void update_most_loaded_node_queue(SchedulerQueue::Node*, SchedulerQueue* target_queue);
void remove_node_from_most_loaded(SchedulerQueue::Node*); void remove_node_from_most_loaded(SchedulerQueue::Node*);
void wake_up_sleeping_threads();
void do_load_balancing(); void do_load_balancing();
class ProcessorID find_least_loaded_processor() const; class ProcessorID find_least_loaded_processor() const;

View File

@ -1,9 +1,8 @@
#pragma once #pragma once
#include <kernel/Memory/DMARegion.h> #include <kernel/ThreadBlocker.h>
#include <kernel/Storage/ATA/AHCI/Definitions.h> #include <kernel/Storage/ATA/AHCI/Definitions.h>
#include <kernel/Storage/ATA/ATADevice.h> #include <kernel/Storage/ATA/ATADevice.h>
#include <kernel/ThreadBlocker.h>
namespace Kernel namespace Kernel
{ {
@ -35,8 +34,6 @@ namespace Kernel
BAN::ErrorOr<void> block_until_command_completed(uint32_t command_slot); BAN::ErrorOr<void> block_until_command_completed(uint32_t command_slot);
private: private:
Mutex m_mutex;
BAN::RefPtr<AHCIController> m_controller; BAN::RefPtr<AHCIController> m_controller;
volatile HBAPortMemorySpace* const m_port; volatile HBAPortMemorySpace* const m_port;

View File

@ -3,7 +3,6 @@
#include <BAN/Array.h> #include <BAN/Array.h>
#include <BAN/ByteSpan.h> #include <BAN/ByteSpan.h>
#include <BAN/Vector.h> #include <BAN/Vector.h>
#include <kernel/Lock/RWLock.h>
#include <kernel/Memory/Types.h> #include <kernel/Memory/Types.h>
namespace Kernel namespace Kernel
@ -29,8 +28,6 @@ namespace Kernel
private: private:
BAN::ErrorOr<void> sync_cache_index(size_t index); BAN::ErrorOr<void> sync_cache_index(size_t index);
size_t find_sector_cache_index(uint64_t sector) const;
private: private:
struct PageCache struct PageCache
{ {
@ -38,13 +35,9 @@ namespace Kernel
uint64_t first_sector { 0 }; uint64_t first_sector { 0 };
uint8_t sector_mask { 0 }; uint8_t sector_mask { 0 };
uint8_t dirty_mask { 0 }; uint8_t dirty_mask { 0 };
bool syncing { false };
}; };
private: private:
RWLock m_rw_lock;
Mutex m_sync_mutex;
const size_t m_sector_size; const size_t m_sector_size;
StorageDevice& m_device; StorageDevice& m_device;
BAN::Vector<PageCache> m_cache; BAN::Vector<PageCache> m_cache;

View File

@ -51,6 +51,7 @@ namespace Kernel
virtual bool has_hungup_impl() const override { return false; } virtual bool has_hungup_impl() const override { return false; }
private: private:
Mutex m_mutex;
BAN::Optional<DiskCache> m_disk_cache; BAN::Optional<DiskCache> m_disk_cache;
BAN::Vector<BAN::RefPtr<Partition>> m_partitions; BAN::Vector<BAN::RefPtr<Partition>> m_partitions;

View File

@ -55,8 +55,6 @@ namespace Kernel
{} {}
virtual ~USBHIDDevice() = default; virtual ~USBHIDDevice() = default;
virtual BAN::ErrorOr<void> initialize() { return {}; }
virtual void start_report() = 0; virtual void start_report() = 0;
virtual void stop_report() = 0; virtual void stop_report() = 0;

View File

@ -1,43 +0,0 @@
#pragma once
#include <kernel/USB/HID/HIDDriver.h>
#include <LibInput/Joystick.h>
namespace Kernel
{
class USBJoystick final : public USBHIDDevice
{
BAN_NON_COPYABLE(USBJoystick);
BAN_NON_MOVABLE(USBJoystick);
public:
BAN::ErrorOr<void> initialize() override;
void start_report() override;
void stop_report() override;
void handle_array(uint16_t usage_page, uint16_t usage) override;
void handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) override;
void handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max) override;
protected:
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
bool can_read_impl() const override { return true; }
private:
USBJoystick(USBHIDDriver&);
~USBJoystick() = default;
private:
USBHIDDriver& m_driver;
SpinLock m_state_lock;
InterruptState m_interrupt_state;
LibInput::JoystickState m_state {};
friend class BAN::RefPtr<USBJoystick>;
};
}

View File

@ -56,98 +56,52 @@ namespace Kernel
return &m_fs; return &m_fs;
} }
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block(uint32_t& block, uint32_t index, uint32_t depth, bool allocate) BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::block_from_indirect_block(uint32_t block, uint32_t index, uint32_t depth)
{ {
const uint32_t inode_blocks_per_fs_block = blksize() / 512; if (block == 0)
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t); return BAN::Optional<uint32_t>();
ASSERT(depth >= 1);
if (depth == 0)
{
if (block == 0)
{
if (!allocate)
return BAN::Optional<uint32_t>();
block = TRY(m_fs.reserve_free_block(block_group()));
m_inode.blocks += inode_blocks_per_fs_block;
auto block_buffer = TRY(m_fs.get_block_buffer());
memset(block_buffer.data(), 0x00, block_buffer.size());
TRY(m_fs.write_block(block, block_buffer));
}
return BAN::Optional<uint32_t>(block);
}
auto block_buffer = TRY(m_fs.get_block_buffer()); auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(block, block_buffer));
bool needs_write = false; const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
if (block != 0)
TRY(m_fs.read_block(block, block_buffer));
else
{
if (!allocate)
return BAN::Optional<uint32_t>();
block = TRY(m_fs.reserve_free_block(block_group()));
m_inode.blocks += inode_blocks_per_fs_block;
memset(block_buffer.data(), 0, block_buffer.size());
needs_write = true;
}
uint32_t divisor = 1; uint32_t divisor = 1;
for (uint32_t i = 1; i < depth; i++) for (uint32_t i = 1; i < depth; i++)
divisor *= indices_per_fs_block; divisor *= indices_per_block;
uint32_t& new_block = block_buffer.span().as_span<uint32_t>()[(index / divisor) % indices_per_fs_block]; const uint32_t next_block = block_buffer.span().as_span<uint32_t>()[(index / divisor) % indices_per_block];
const auto old_block = new_block; if (next_block == 0)
return BAN::Optional<uint32_t>();
if (depth == 1)
return BAN::Optional<uint32_t>(next_block);
const auto result = TRY(block_from_indirect_block(new_block, index, depth - 1, allocate)); return block_from_indirect_block(next_block, index, depth - 1);
if (needs_write || old_block != new_block)
TRY(m_fs.write_block(block, block_buffer));
return result;
} }
BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index(uint32_t data_block_index, bool allocate) BAN::ErrorOr<BAN::Optional<uint32_t>> Ext2Inode::fs_block_of_data_block_index(uint32_t data_block_index)
{ {
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
const uint32_t indices_per_block = blksize() / sizeof(uint32_t); const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
if (data_block_index < 12) if (data_block_index < 12)
{ {
if (m_inode.block[data_block_index] != 0) if (m_inode.block[data_block_index] == 0)
return BAN::Optional<uint32_t>(m_inode.block[data_block_index]);
if (!allocate)
return BAN::Optional<uint32_t>(); return BAN::Optional<uint32_t>();
return BAN::Optional<uint32_t>(m_inode.block[data_block_index]);
auto block_buffer = TRY(m_fs.get_block_buffer());
memset(block_buffer.data(), 0, block_buffer.size());
const auto block = TRY(m_fs.reserve_free_block(block_group()));
TRY(m_fs.write_block(block, block_buffer));
m_inode.block[data_block_index] = block;
m_inode.blocks += inode_blocks_per_fs_block;
return BAN::Optional<uint32_t>(block);
} }
data_block_index -= 12; data_block_index -= 12;
if (data_block_index < indices_per_block) if (data_block_index < indices_per_block)
return block_from_indirect_block(m_inode.block[12], data_block_index, 1, allocate); return block_from_indirect_block(m_inode.block[12], data_block_index, 1);
data_block_index -= indices_per_block; data_block_index -= indices_per_block;
if (data_block_index < indices_per_block * indices_per_block) if (data_block_index < indices_per_block * indices_per_block)
return block_from_indirect_block(m_inode.block[13], data_block_index, 2, allocate); return block_from_indirect_block(m_inode.block[13], data_block_index, 2);
data_block_index -= indices_per_block * indices_per_block; data_block_index -= indices_per_block * indices_per_block;
if (data_block_index < indices_per_block * indices_per_block * indices_per_block) if (data_block_index < indices_per_block * indices_per_block * indices_per_block)
return block_from_indirect_block(m_inode.block[14], data_block_index, 3, allocate); return block_from_indirect_block(m_inode.block[14], data_block_index, 3);
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
@ -198,8 +152,6 @@ namespace Kernel
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= m_inode.size) if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= m_inode.size)
return 0; return 0;
ScopedSync _(*this);
uint32_t count = buffer.size(); uint32_t count = buffer.size();
if (offset + buffer.size() > m_inode.size) if (offset + buffer.size() > m_inode.size)
count = m_inode.size - offset; count = m_inode.size - offset;
@ -215,7 +167,7 @@ namespace Kernel
for (uint32_t data_block_index = first_block; data_block_index < last_block; data_block_index++) for (uint32_t data_block_index = first_block; data_block_index < last_block; data_block_index++)
{ {
auto block_index = TRY(fs_block_of_data_block_index(data_block_index, false)); auto block_index = TRY(fs_block_of_data_block_index(data_block_index));
if (block_index.has_value()) if (block_index.has_value())
TRY(m_fs.read_block(block_index.value(), block_buffer)); TRY(m_fs.read_block(block_index.value(), block_buffer));
else else
@ -244,8 +196,6 @@ namespace Kernel
if (m_inode.size < offset + buffer.size()) if (m_inode.size < offset + buffer.size())
TRY(truncate_impl(offset + buffer.size())); TRY(truncate_impl(offset + buffer.size()));
ScopedSync _(*this);
const uint32_t block_size = blksize(); const uint32_t block_size = blksize();
auto block_buffer = TRY(m_fs.get_block_buffer()); auto block_buffer = TRY(m_fs.get_block_buffer());
@ -256,13 +206,17 @@ namespace Kernel
// Write partial block // Write partial block
if (offset % block_size) if (offset % block_size)
{ {
const auto block_index = TRY(fs_block_of_data_block_index(offset / block_size, true)); auto block_index = TRY(fs_block_of_data_block_index(offset / block_size));
ASSERT(block_index.has_value()); if (block_index.has_value())
TRY(m_fs.read_block(block_index.value(), block_buffer));
else
{
block_index = TRY(allocate_new_block(offset / block_size));;
memset(block_buffer.data(), 0x00, block_buffer.size());
}
TRY(m_fs.read_block(block_index.value(), block_buffer)); uint32_t block_offset = offset % block_size;
uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, to_write);
const uint32_t block_offset = offset % block_size;
const uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, to_write);
memcpy(block_buffer.data() + block_offset, buffer.data(), to_copy); memcpy(block_buffer.data() + block_offset, buffer.data(), to_copy);
TRY(m_fs.write_block(block_index.value(), block_buffer)); TRY(m_fs.write_block(block_index.value(), block_buffer));
@ -274,8 +228,9 @@ namespace Kernel
while (to_write >= block_size) while (to_write >= block_size)
{ {
const auto block_index = TRY(fs_block_of_data_block_index(offset / block_size, true)); auto block_index = TRY(fs_block_of_data_block_index(offset / block_size));
ASSERT(block_index.has_value()); if (!block_index.has_value())
block_index = TRY(allocate_new_block(offset / block_size));
memcpy(block_buffer.data(), buffer.data() + written, block_buffer.size()); memcpy(block_buffer.data(), buffer.data() + written, block_buffer.size());
TRY(m_fs.write_block(block_index.value(), block_buffer)); TRY(m_fs.write_block(block_index.value(), block_buffer));
@ -287,10 +242,14 @@ namespace Kernel
if (to_write > 0) if (to_write > 0)
{ {
const auto block_index = TRY(fs_block_of_data_block_index(offset / block_size, true)); auto block_index = TRY(fs_block_of_data_block_index(offset / block_size));
ASSERT(block_index.has_value()); if (block_index.has_value())
TRY(m_fs.read_block(block_index.value(), block_buffer));
TRY(m_fs.read_block(block_index.value(), block_buffer)); else
{
block_index = TRY(allocate_new_block(offset / block_size));
memset(block_buffer.data(), 0x00, block_buffer.size());
}
memcpy(block_buffer.data(), buffer.data() + written, to_write); memcpy(block_buffer.data(), buffer.data() + written, to_write);
TRY(m_fs.write_block(block_index.value(), block_buffer)); TRY(m_fs.write_block(block_index.value(), block_buffer));
@ -381,7 +340,7 @@ namespace Kernel
BAN::ErrorOr<void> Ext2Inode::fsync_impl() BAN::ErrorOr<void> Ext2Inode::fsync_impl()
{ {
for (size_t i = 0; i < max_used_data_block_count(); i++) for (size_t i = 0; i < max_used_data_block_count(); i++)
if (const auto fs_block = TRY(fs_block_of_data_block_index(i, false)); fs_block.has_value()) if (const auto fs_block = TRY(fs_block_of_data_block_index(i)); fs_block.has_value())
TRY(m_fs.sync_block(fs_block.value())); TRY(m_fs.sync_block(fs_block.value()));
return {}; return {};
} }
@ -453,12 +412,12 @@ done:
if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= max_used_data_block_count()) if (static_cast<BAN::make_unsigned_t<decltype(offset)>>(offset) >= max_used_data_block_count())
return 0; return 0;
const auto block_index = TRY(fs_block_of_data_block_index(offset, false)); // FIXME: can we actually assume directories have all their blocks allocated
if (!block_index.has_value()) const uint32_t block_index = TRY(fs_block_of_data_block_index(offset)).value();
return BAN::Error::from_errno(ENODATA);
auto block_buffer = TRY(m_fs.get_block_buffer()); auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(block_index.value(), block_buffer));
TRY(m_fs.read_block(block_index, block_buffer));
// First determine if we have big enough list // First determine if we have big enough list
size_t entry_count = 0; size_t entry_count = 0;
@ -722,7 +681,7 @@ done:
goto needs_new_block; goto needs_new_block;
// Try to insert inode to last data block // Try to insert inode to last data block
block_index = TRY(fs_block_of_data_block_index(data_block_count - 1, true)).value(); block_index = TRY(fs_block_of_data_block_index(data_block_count - 1)).value();
TRY(m_fs.read_block(block_index, block_buffer)); TRY(m_fs.read_block(block_index, block_buffer));
while (entry_offset < block_size) while (entry_offset < block_size)
@ -753,7 +712,7 @@ done:
} }
needs_new_block: needs_new_block:
block_index = TRY(fs_block_of_data_block_index(data_block_count, true)).value(); block_index = TRY(allocate_new_block(data_block_count));
m_inode.size += blksize(); m_inode.size += blksize();
memset(block_buffer.data(), 0x00, block_buffer.size()); memset(block_buffer.data(), 0x00, block_buffer.size());
@ -772,10 +731,9 @@ needs_new_block:
// Confirm that this doesn't contain anything else than '.' or '..' // Confirm that this doesn't contain anything else than '.' or '..'
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
{ {
const auto block_index = TRY(fs_block_of_data_block_index(i, false)); // FIXME: can we actually assume directories have all their blocks allocated
if (!block_index.has_value()) const uint32_t block_index = TRY(fs_block_of_data_block_index(i)).value();
continue; TRY(m_fs.read_block(block_index, block_buffer));
TRY(m_fs.read_block(block_index.value(), block_buffer));
blksize_t offset = 0; blksize_t offset = 0;
while (offset < blksize()) while (offset < blksize())
@ -809,10 +767,9 @@ needs_new_block:
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
{ {
const auto block_index = TRY(fs_block_of_data_block_index(i, false)); // FIXME: can we actually assume directories have all their blocks allocated
if (!block_index.has_value()) const uint32_t block_index = TRY(fs_block_of_data_block_index(i)).value();
continue; TRY(m_fs.read_block(block_index, block_buffer));
TRY(m_fs.read_block(block_index.value(), block_buffer));
bool modified = false; bool modified = false;
@ -847,7 +804,7 @@ needs_new_block:
} }
if (modified) if (modified)
TRY(m_fs.write_block(block_index.value(), block_buffer)); TRY(m_fs.write_block(block_index, block_buffer));
} }
return {}; return {};
@ -866,10 +823,9 @@ needs_new_block:
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
{ {
const auto block_index = TRY(fs_block_of_data_block_index(i, false)); // FIXME: can we actually assume directories have all their blocks allocated
if (!block_index.has_value()) const uint32_t block_index = TRY(fs_block_of_data_block_index(i)).value();
continue; TRY(m_fs.read_block(block_index, block_buffer));
TRY(m_fs.read_block(block_index.value(), block_buffer));
blksize_t offset = 0; blksize_t offset = 0;
while (offset < blksize()) while (offset < blksize())
@ -903,7 +859,7 @@ needs_new_block:
// FIXME: This should expand the last inode if exists // FIXME: This should expand the last inode if exists
entry.inode = 0; entry.inode = 0;
TRY(m_fs.write_block(block_index.value(), block_buffer)); TRY(m_fs.write_block(block_index, block_buffer));
} }
offset += entry.rec_len; offset += entry.rec_len;
} }
@ -918,6 +874,73 @@ needs_new_block:
return {}; return {};
} }
BAN::ErrorOr<uint32_t> Ext2Inode::allocate_new_block_to_indirect_block(uint32_t& block, uint32_t index, uint32_t depth)
{
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
if (depth == 0)
ASSERT(block == 0);
if (block == 0)
{
block = TRY(m_fs.reserve_free_block(block_group()));
m_inode.blocks += inode_blocks_per_fs_block;
auto block_buffer = TRY(m_fs.get_block_buffer());
memset(block_buffer.data(), 0x00, block_buffer.size());
TRY(m_fs.write_block(block, block_buffer));
}
if (depth == 0)
return block;
auto block_buffer = TRY(m_fs.get_block_buffer());
TRY(m_fs.read_block(block, block_buffer));
uint32_t divisor = 1;
for (uint32_t i = 1; i < depth; i++)
divisor *= indices_per_fs_block;
uint32_t& new_block = block_buffer.span().as_span<uint32_t>()[(index / divisor) % indices_per_fs_block];
uint32_t allocated_block = TRY(allocate_new_block_to_indirect_block(new_block, index, depth - 1));
TRY(m_fs.write_block(block, block_buffer));
TRY(sync());
return allocated_block;
}
BAN::ErrorOr<uint32_t> Ext2Inode::allocate_new_block(uint32_t data_block_index)
{
const uint32_t inode_blocks_per_fs_block = blksize() / 512;
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
if (data_block_index < 12)
{
ASSERT(m_inode.block[data_block_index] == 0);
m_inode.block[data_block_index] = TRY(m_fs.reserve_free_block(block_group()));
m_inode.blocks += inode_blocks_per_fs_block;
TRY(sync());
return m_inode.block[data_block_index];
}
data_block_index -= 12;
if (data_block_index < indices_per_fs_block)
return TRY(allocate_new_block_to_indirect_block(m_inode.block[12], data_block_index, 1));
data_block_index -= indices_per_fs_block;
if (data_block_index < indices_per_fs_block * indices_per_fs_block)
return TRY(allocate_new_block_to_indirect_block(m_inode.block[13], data_block_index, 2));
data_block_index -= indices_per_fs_block * indices_per_fs_block;
if (data_block_index < indices_per_fs_block * indices_per_fs_block * indices_per_fs_block)
return TRY(allocate_new_block_to_indirect_block(m_inode.block[14], data_block_index, 3));
ASSERT_NOT_REACHED();
}
BAN::ErrorOr<void> Ext2Inode::sync() BAN::ErrorOr<void> Ext2Inode::sync()
{ {
auto inode_location = TRY(m_fs.locate_inode(ino())); auto inode_location = TRY(m_fs.locate_inode(ino()));
@ -941,10 +964,9 @@ needs_new_block:
for (uint32_t i = 0; i < max_used_data_block_count(); i++) for (uint32_t i = 0; i < max_used_data_block_count(); i++)
{ {
const auto block_index = TRY(fs_block_of_data_block_index(i, false)); // FIXME: can we actually assume directories have all their blocks allocated
if (!block_index.has_value()) const uint32_t block_index = TRY(fs_block_of_data_block_index(i)).value();
continue; TRY(m_fs.read_block(block_index, block_buffer));
TRY(m_fs.read_block(block_index.value(), block_buffer));
BAN::ConstByteSpan entry_span = block_buffer.span(); BAN::ConstByteSpan entry_span = block_buffer.span();
while (entry_span.size() >= sizeof(Ext2::LinkedDirectoryEntry)) while (entry_span.size() >= sizeof(Ext2::LinkedDirectoryEntry))

View File

@ -123,8 +123,6 @@ namespace Kernel
void TmpInode::free_all_blocks() void TmpInode::free_all_blocks()
{ {
if (mode().iflnk() && m_inode_info.size <= sizeof(TmpInodeInfo::block))
goto free_all_blocks_done;
for (size_t i = 0; i < TmpInodeInfo::direct_block_count; i++) for (size_t i = 0; i < TmpInodeInfo::direct_block_count; i++)
if (m_inode_info.block[i]) if (m_inode_info.block[i])
m_fs.free_block(m_inode_info.block[i]); m_fs.free_block(m_inode_info.block[i]);
@ -134,7 +132,6 @@ namespace Kernel
free_indirect_blocks(block, 2); free_indirect_blocks(block, 2);
if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 2]) if (size_t block = m_inode_info.block[TmpInodeInfo::direct_block_count + 2])
free_indirect_blocks(block, 3); free_indirect_blocks(block, 3);
free_all_blocks_done:
for (auto& block : m_inode_info.block) for (auto& block : m_inode_info.block)
block = 0; block = 0;
} }

View File

@ -174,7 +174,7 @@ namespace Kernel
MUST(s_instance->mount(root_creds, &ProcFileSystem::get(), "/proc"_sv)); MUST(s_instance->mount(root_creds, &ProcFileSystem::get(), "/proc"_sv));
auto tmpfs = MUST(TmpFileSystem::create(-1, 01777, 0, 0)); auto tmpfs = MUST(TmpFileSystem::create(-1, 0777, 0, 0));
MUST(s_instance->mount(root_creds, tmpfs, "/tmp"_sv)); MUST(s_instance->mount(root_creds, tmpfs, "/tmp"_sv));
} }

View File

@ -3,7 +3,6 @@
#include <kernel/Input/InputDevice.h> #include <kernel/Input/InputDevice.h>
#include <kernel/Lock/SpinLockAsMutex.h> #include <kernel/Lock/SpinLockAsMutex.h>
#include <LibInput/Joystick.h>
#include <LibInput/KeyEvent.h> #include <LibInput/KeyEvent.h>
#include <LibInput/MouseEvent.h> #include <LibInput/MouseEvent.h>
@ -19,8 +18,6 @@ namespace Kernel
static BAN::Vector<BAN::WeakPtr<InputDevice>> s_mice; static BAN::Vector<BAN::WeakPtr<InputDevice>> s_mice;
static BAN::RefPtr<MouseDevice> s_mouse_device; static BAN::RefPtr<MouseDevice> s_mouse_device;
static BAN::Vector<BAN::WeakPtr<InputDevice>> s_joysticks;
static const char* get_name_format(InputDevice::Type type) static const char* get_name_format(InputDevice::Type type)
{ {
switch (type) switch (type)
@ -29,8 +26,6 @@ namespace Kernel
return "keyboard{}"; return "keyboard{}";
case InputDevice::Type::Mouse: case InputDevice::Type::Mouse:
return "mouse{}"; return "mouse{}";
case InputDevice::Type::Joystick:
return "joystick{}";
} }
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
@ -49,11 +44,6 @@ namespace Kernel
if (!s_mice[i].valid()) if (!s_mice[i].valid())
return makedev(DeviceNumber::Mouse, i + 1); return makedev(DeviceNumber::Mouse, i + 1);
return makedev(DeviceNumber::Mouse, s_mice.size() + 1); return makedev(DeviceNumber::Mouse, s_mice.size() + 1);
case InputDevice::Type::Joystick:
for (size_t i = 0; i < s_joysticks.size(); i++)
if (!s_joysticks[i].valid())
return makedev(DeviceNumber::Joystick, i + 1);
return makedev(DeviceNumber::Joystick, s_joysticks.size() + 1);
} }
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
@ -66,8 +56,6 @@ namespace Kernel
return sizeof(LibInput::RawKeyEvent); return sizeof(LibInput::RawKeyEvent);
case InputDevice::Type::Mouse: case InputDevice::Type::Mouse:
return sizeof(LibInput::MouseEvent); return sizeof(LibInput::MouseEvent);
case InputDevice::Type::Joystick:
return sizeof(LibInput::JoystickEvent);
} }
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
@ -81,23 +69,18 @@ namespace Kernel
{ {
MUST(m_event_buffer.resize(m_event_size * m_max_event_count, 0)); MUST(m_event_buffer.resize(m_event_size * m_max_event_count, 0));
switch (m_type) if (m_type == Type::Keyboard)
{ {
case Type::Keyboard: if (s_keyboards.size() < minor(m_rdev))
if (s_keyboards.size() < minor(m_rdev)) MUST(s_keyboards.resize(minor(m_rdev)));
MUST(s_keyboards.resize(minor(m_rdev))); s_keyboards[minor(m_rdev) - 1] = MUST(get_weak_ptr());
s_keyboards[minor(m_rdev) - 1] = MUST(get_weak_ptr()); }
break;
case Type::Mouse: if (m_type == Type::Mouse)
if (s_mice.size() < minor(m_rdev)) {
MUST(s_mice.resize(minor(m_rdev))); if (s_mice.size() < minor(m_rdev))
s_mice[minor(m_rdev) - 1] = MUST(get_weak_ptr()); MUST(s_mice.resize(minor(m_rdev)));
break; s_mice[minor(m_rdev) - 1] = MUST(get_weak_ptr());
case Type::Joystick:
if (s_joysticks.size() < minor(m_rdev))
MUST(s_joysticks.resize(minor(m_rdev)));
s_joysticks[minor(m_rdev) - 1] = MUST(get_weak_ptr());
break;
} }
} }

View File

@ -98,9 +98,8 @@ namespace Kernel
[this](size_t buffer_bit) -> bool [this](size_t buffer_bit) -> bool
{ {
const size_t page_index = buffer_bit / bits_per_page; const size_t page_index = buffer_bit / bits_per_page;
const size_t bit_index = buffer_bit % bits_per_page; const size_t byte = buffer_bit / 8;
const size_t byte = bit_index / 8; const size_t bit = buffer_bit % 8;
const size_t bit = bit_index % 8;
uint8_t current; uint8_t current;
PageTable::with_fast_page(m_paddr + page_index * PAGE_SIZE, [&current, byte] { PageTable::with_fast_page(m_paddr + page_index * PAGE_SIZE, [&current, byte] {
@ -114,9 +113,8 @@ namespace Kernel
[this](size_t buffer_bit) -> void [this](size_t buffer_bit) -> void
{ {
const size_t page_index = buffer_bit / bits_per_page; const size_t page_index = buffer_bit / bits_per_page;
const size_t bit_index = buffer_bit % bits_per_page; const size_t byte = buffer_bit / 8;
const size_t byte = bit_index / 8; const size_t bit = buffer_bit % 8;
const size_t bit = bit_index % 8;
PageTable::with_fast_page(m_paddr + page_index * PAGE_SIZE, [byte, bit] { PageTable::with_fast_page(m_paddr + page_index * PAGE_SIZE, [byte, bit] {
volatile uint8_t& current = PageTable::fast_page_as_sized<volatile uint8_t>(byte); volatile uint8_t& current = PageTable::fast_page_as_sized<volatile uint8_t>(byte);
current = current | (1u << bit); current = current | (1u << bit);

View File

@ -75,58 +75,35 @@ namespace Kernel
m_bound_sockets.remove(it); m_bound_sockets.remove(it);
} }
BAN::ErrorOr<in_port_t> IPv4Layer::find_free_port() BAN::ErrorOr<void> IPv4Layer::bind_socket_to_unused(BAN::RefPtr<NetworkSocket> socket, const sockaddr* address, socklen_t address_len)
{ {
if (!address || address_len < (socklen_t)sizeof(sockaddr_in))
return BAN::Error::from_errno(EINVAL);
if (address->sa_family != AF_INET)
return BAN::Error::from_errno(EAFNOSUPPORT);
auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(address);
SpinLockGuard _(m_bound_socket_lock); SpinLockGuard _(m_bound_socket_lock);
for (uint32_t i = 0; i < 100; i++) uint16_t port = NetworkSocket::PORT_NONE;
if (uint32_t port = 0xC000 | (Random::get_u32() & 0x3FFF); !m_bound_sockets.contains(port)) for (uint32_t i = 0; i < 100 && port == NetworkSocket::PORT_NONE; i++)
return port; if (uint32_t temp = 0xC000 | (Random::get_u32() & 0x3FFF); !m_bound_sockets.contains(temp))
port = temp;
for (uint32_t temp = 0xC000; temp < 0xFFFF && port == NetworkSocket::PORT_NONE; temp++)
if (!m_bound_sockets.contains(temp))
port = temp;
if (port == NetworkSocket::PORT_NONE)
{
dwarnln("No ports available");
return BAN::Error::from_errno(EAGAIN);
}
dprintln_if(DEBUG_IPV4, "using port {}", port);
for (uint32_t port = 0xC000; port < 0xFFFF; port++) struct sockaddr_in target;
if (!m_bound_sockets.contains(port)) target.sin_family = AF_INET;
return port; target.sin_port = BAN::host_to_network_endian(port);
target.sin_addr.s_addr = sockaddr_in.sin_addr.s_addr;
dwarnln("No ports available"); return bind_socket_to_address(socket, (sockaddr*)&target, sizeof(sockaddr_in));
return BAN::Error::from_errno(EAGAIN);
}
BAN::ErrorOr<void> IPv4Layer::bind_socket_with_target(BAN::RefPtr<NetworkSocket> socket, const sockaddr* target, socklen_t target_len)
{
if (!target || target_len < (socklen_t)sizeof(sockaddr_in))
return BAN::Error::from_errno(EINVAL);
if (target->sa_family != AF_INET)
return BAN::Error::from_errno(EAFNOSUPPORT);
auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(target);
auto interface =
TRY([&sockaddr_in]() -> BAN::ErrorOr<BAN::RefPtr<NetworkInterface>> {
const auto ipv4 = BAN::IPv4Address { sockaddr_in.sin_addr.s_addr };
// try to find an interface in the same subnet
const auto& all_interfaces = NetworkManager::get().interfaces();
for (const auto& interface : all_interfaces)
{
const auto netmask = interface->get_netmask();
if (ipv4.mask(netmask) == interface->get_ipv4_address().mask(netmask))
return interface;
}
// fallback to non-loopback interface
// FIXME: make sure target is reachable
for (const auto& interface : all_interfaces)
if (interface->type() != NetworkInterface::Type::Loopback)
return interface;
return BAN::Error::from_errno(EHOSTUNREACH);
}());
// FIXME: race condition with port allocation/binding
struct sockaddr_in bind_address;
bind_address.sin_family = AF_INET;
bind_address.sin_port = BAN::host_to_network_endian(TRY(find_free_port()));
bind_address.sin_addr.s_addr = interface->get_ipv4_address().raw;
return bind_socket_to_address(socket, (sockaddr*)&bind_address, sizeof(bind_address));
} }
BAN::ErrorOr<void> IPv4Layer::bind_socket_to_address(BAN::RefPtr<NetworkSocket> socket, const sockaddr* address, socklen_t address_len) BAN::ErrorOr<void> IPv4Layer::bind_socket_to_address(BAN::RefPtr<NetworkSocket> socket, const sockaddr* address, socklen_t address_len)
@ -137,47 +114,33 @@ namespace Kernel
return BAN::Error::from_errno(EAFNOSUPPORT); return BAN::Error::from_errno(EAFNOSUPPORT);
auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(address); auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(address);
const uint16_t port = BAN::host_to_network_endian(sockaddr_in.sin_port);
if (port == NetworkSocket::PORT_NONE)
return bind_socket_to_unused(socket, address, address_len);
const auto ipv4 = BAN::IPv4Address { sockaddr_in.sin_addr.s_addr };
TRY([&sockaddr_in]() -> BAN::ErrorOr<void> { BAN::RefPtr<NetworkInterface> bind_interface;
const auto ipv4 = BAN::IPv4Address { sockaddr_in.sin_addr.s_addr }; for (auto interface : NetworkManager::get().interfaces())
{
if (ipv4 == 0) if (interface->type() != NetworkInterface::Type::Loopback)
return {}; bind_interface = interface;
const auto netmask = interface->get_netmask();
const auto& all_interfaces = NetworkManager::get().interfaces(); if (ipv4.mask(netmask) != interface->get_ipv4_address().mask(netmask))
for (const auto& interface : all_interfaces) continue;
{ bind_interface = interface;
switch (interface->type()) break;
{ }
case NetworkInterface::Type::Ethernet:
if (ipv4 == interface->get_ipv4_address())
return {};
break;
case NetworkInterface::Type::Loopback:
const auto netmask = interface->get_netmask();
if (ipv4.mask(netmask) == interface->get_ipv4_address().mask(netmask))
return {};
break;
}
}
if (!bind_interface)
return BAN::Error::from_errno(EADDRNOTAVAIL); return BAN::Error::from_errno(EADDRNOTAVAIL);
}());
struct sockaddr_in bind_address;
memcpy(&bind_address, address, sizeof(sockaddr_in));
SpinLockGuard _(m_bound_socket_lock); SpinLockGuard _(m_bound_socket_lock);
if (bind_address.sin_port == 0)
bind_address.sin_port = TRY(find_free_port());
const uint16_t port = BAN::host_to_network_endian(bind_address.sin_port);
if (m_bound_sockets.contains(port)) if (m_bound_sockets.contains(port))
return BAN::Error::from_errno(EADDRINUSE); return BAN::Error::from_errno(EADDRINUSE);
TRY(m_bound_sockets.insert(port, TRY(socket->get_weak_ptr()))); TRY(m_bound_sockets.insert(port, TRY(socket->get_weak_ptr())));
socket->bind_address_and_port(reinterpret_cast<struct sockaddr*>(&bind_address), sizeof(bind_address)); socket->bind_interface_and_port(bind_interface.ptr(), port);
return {}; return {};
} }
@ -210,36 +173,18 @@ namespace Kernel
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
if (address == nullptr || address_len != sizeof(sockaddr_in)) if (address == nullptr || address_len != sizeof(sockaddr_in))
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
auto interface = TRY(socket.interface(address, address_len));
auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(address); auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(address);
auto dst_port = BAN::host_to_network_endian(sockaddr_in.sin_port); auto dst_port = BAN::host_to_network_endian(sockaddr_in.sin_port);
auto dst_ipv4 = BAN::IPv4Address { sockaddr_in.sin_addr.s_addr }; auto dst_ipv4 = BAN::IPv4Address { sockaddr_in.sin_addr.s_addr };
auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(*interface, dst_ipv4)); auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(socket.interface(), dst_ipv4));
if (interface->type() == NetworkInterface::Type::Loopback)
{
BAN::RefPtr<NetworkSocket> receiver;
{
SpinLockGuard _(m_bound_socket_lock);
auto receiver_it = m_bound_sockets.find(dst_port);
if (receiver_it != m_bound_sockets.end())
receiver = receiver_it->value.lock();
}
if (!receiver)
return BAN::Error::from_errno(EADDRNOTAVAIL);
TRY(socket.interface(receiver->address(), receiver->address_len()));
}
BAN::Vector<uint8_t> packet_buffer; BAN::Vector<uint8_t> packet_buffer;
TRY(packet_buffer.resize(buffer.size() + sizeof(IPv4Header) + socket.protocol_header_size())); TRY(packet_buffer.resize(buffer.size() + sizeof(IPv4Header) + socket.protocol_header_size()));
auto packet = BAN::ByteSpan { packet_buffer.span() }; auto packet = BAN::ByteSpan { packet_buffer.span() };
auto pseudo_header = PseudoHeader { auto pseudo_header = PseudoHeader {
.src_ipv4 = interface->get_ipv4_address(), .src_ipv4 = socket.interface().get_ipv4_address(),
.dst_ipv4 = dst_ipv4, .dst_ipv4 = dst_ipv4,
.protocol = socket.protocol() .protocol = socket.protocol()
}; };
@ -256,12 +201,12 @@ namespace Kernel
); );
add_ipv4_header( add_ipv4_header(
packet, packet,
interface->get_ipv4_address(), socket.interface().get_ipv4_address(),
dst_ipv4, dst_ipv4,
socket.protocol() socket.protocol()
); );
TRY(interface->send_bytes(dst_mac, EtherType::IPv4, packet)); TRY(socket.interface().send_bytes(dst_mac, EtherType::IPv4, packet));
return buffer.size(); return buffer.size();
} }

View File

@ -15,97 +15,12 @@ namespace Kernel
{ {
} }
bool NetworkSocket::can_interface_send_to(const NetworkInterface& interface, const sockaddr* target, socklen_t target_len) const void NetworkSocket::bind_interface_and_port(NetworkInterface* interface, uint16_t port)
{ {
ASSERT(target); ASSERT(!m_interface);
ASSERT(target_len >= static_cast<socklen_t>(sizeof(sockaddr_in))); ASSERT(interface);
ASSERT(target->sa_family == AF_INET); m_interface = interface;
m_port = port;
const auto target_ipv4 = BAN::IPv4Address {
reinterpret_cast<const sockaddr_in*>(target)->sin_addr.s_addr
};
switch (interface.type())
{
case NetworkInterface::Type::Ethernet:
// FIXME: this is not really correct :D
return target_ipv4.octets[0] != IN_LOOPBACKNET;
case NetworkInterface::Type::Loopback:
return target_ipv4.octets[0] == IN_LOOPBACKNET;
}
ASSERT_NOT_REACHED();
}
BAN::ErrorOr<BAN::RefPtr<NetworkInterface>> NetworkSocket::interface(const sockaddr* target, socklen_t target_len)
{
ASSERT(m_network_layer.domain() == NetworkSocket::Domain::INET);
ASSERT(is_bound());
if (target != nullptr)
{
ASSERT(target_len >= static_cast<socklen_t>(sizeof(sockaddr_in)));
ASSERT(target->sa_family == AF_INET);
}
const auto& all_interfaces = NetworkManager::get().interfaces();
const auto bound_ipv4 = BAN::IPv4Address {
reinterpret_cast<const sockaddr_in*>(&m_address)->sin_addr.s_addr
};
// find the bound interface
if (bound_ipv4 != 0)
{
for (const auto& interface : all_interfaces)
{
const auto netmask = interface->get_netmask();
if (bound_ipv4.mask(netmask) != interface->get_ipv4_address().mask(netmask))
continue;
if (target && !can_interface_send_to(*interface, target, target_len))
continue;
return interface;
}
return BAN::Error::from_errno(EADDRNOTAVAIL);
}
// try to find an interface in the same subnet as target
if (target != nullptr)
{
const auto target_ipv4 = BAN::IPv4Address {
reinterpret_cast<const sockaddr_in*>(target)->sin_addr.s_addr
};
for (const auto& interface : all_interfaces)
{
const auto netmask = interface->get_netmask();
if (target_ipv4.mask(netmask) == interface->get_ipv4_address().mask(netmask))
return interface;
}
}
// return any interface (prefer non-loopback)
for (const auto& interface : all_interfaces)
if (interface->type() != NetworkInterface::Type::Loopback)
if (!target || can_interface_send_to(*interface, target, target_len))
return interface;
for (const auto& interface : all_interfaces)
if (interface->type() == NetworkInterface::Type::Loopback)
if (!target || can_interface_send_to(*interface, target, target_len))
return interface;
return BAN::Error::from_errno(EHOSTUNREACH);
}
void NetworkSocket::bind_address_and_port(const sockaddr* addr, socklen_t addr_len)
{
ASSERT(!is_bound());
ASSERT(addr->sa_family != AF_UNSPEC);
ASSERT(addr_len <= static_cast<socklen_t>(sizeof(sockaddr_storage)));
memcpy(&m_address, addr, addr_len);
m_address_len = addr_len;
} }
BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg) BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg)
@ -115,8 +30,12 @@ namespace Kernel
dprintln("No argument provided"); dprintln("No argument provided");
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }
if (m_interface == nullptr)
{
dprintln("No interface bound");
return BAN::Error::from_errno(EADDRNOTAVAIL);
}
auto interface = TRY(this->interface(nullptr, 0));
auto* ifreq = reinterpret_cast<struct ifreq*>(arg); auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
switch (request) switch (request)
@ -125,7 +44,7 @@ namespace Kernel
{ {
auto& ifru_addr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr); auto& ifru_addr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
ifru_addr.sin_family = AF_INET; ifru_addr.sin_family = AF_INET;
ifru_addr.sin_addr.s_addr = interface->get_ipv4_address().raw; ifru_addr.sin_addr.s_addr = m_interface->get_ipv4_address().raw;
return 0; return 0;
} }
case SIOCSIFADDR: case SIOCSIFADDR:
@ -133,15 +52,15 @@ namespace Kernel
auto& ifru_addr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr); auto& ifru_addr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_addr);
if (ifru_addr.sin_family != AF_INET) if (ifru_addr.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL); return BAN::Error::from_errno(EADDRNOTAVAIL);
interface->set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr }); m_interface->set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr });
dprintln("IPv4 address set to {}", interface->get_ipv4_address()); dprintln("IPv4 address set to {}", m_interface->get_ipv4_address());
return 0; return 0;
} }
case SIOCGIFNETMASK: case SIOCGIFNETMASK:
{ {
auto& ifru_netmask = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask); auto& ifru_netmask = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
ifru_netmask.sin_family = AF_INET; ifru_netmask.sin_family = AF_INET;
ifru_netmask.sin_addr.s_addr = interface->get_netmask().raw; ifru_netmask.sin_addr.s_addr = m_interface->get_netmask().raw;
return 0; return 0;
} }
case SIOCSIFNETMASK: case SIOCSIFNETMASK:
@ -149,15 +68,15 @@ namespace Kernel
auto& ifru_netmask = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask); auto& ifru_netmask = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_netmask);
if (ifru_netmask.sin_family != AF_INET) if (ifru_netmask.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL); return BAN::Error::from_errno(EADDRNOTAVAIL);
interface->set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr }); m_interface->set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr });
dprintln("Netmask set to {}", interface->get_netmask()); dprintln("Netmask set to {}", m_interface->get_netmask());
return 0; return 0;
} }
case SIOCGIFGWADDR: case SIOCGIFGWADDR:
{ {
auto& ifru_gwaddr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr); auto& ifru_gwaddr = *reinterpret_cast<sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
ifru_gwaddr.sin_family = AF_INET; ifru_gwaddr.sin_family = AF_INET;
ifru_gwaddr.sin_addr.s_addr = interface->get_gateway().raw; ifru_gwaddr.sin_addr.s_addr = m_interface->get_gateway().raw;
return 0; return 0;
} }
case SIOCSIFGWADDR: case SIOCSIFGWADDR:
@ -165,13 +84,13 @@ namespace Kernel
auto& ifru_gwaddr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr); auto& ifru_gwaddr = *reinterpret_cast<const sockaddr_in*>(&ifreq->ifr_ifru.ifru_gwaddr);
if (ifru_gwaddr.sin_family != AF_INET) if (ifru_gwaddr.sin_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL); return BAN::Error::from_errno(EADDRNOTAVAIL);
interface->set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr }); m_interface->set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr });
dprintln("Gateway set to {}", interface->get_gateway()); dprintln("Gateway set to {}", m_interface->get_gateway());
return 0; return 0;
} }
case SIOCGIFHWADDR: case SIOCGIFHWADDR:
{ {
auto mac_address = interface->get_mac_address(); auto mac_address = m_interface->get_mac_address();
ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET; ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET;
memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address)); memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address));
return 0; return 0;
@ -179,9 +98,9 @@ namespace Kernel
case SIOCGIFNAME: case SIOCGIFNAME:
{ {
auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name; auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name;
ASSERT(interface->name().size() < sizeof(ifrn_name)); ASSERT(m_interface->name().size() < sizeof(ifrn_name));
memcpy(ifrn_name, interface->name().data(), interface->name().size()); memcpy(ifrn_name, m_interface->name().data(), m_interface->name().size());
ifrn_name[interface->name().size()] = '\0'; ifrn_name[m_interface->name().size()] = '\0';
return 0; return 0;
} }
default: default:

View File

@ -95,8 +95,8 @@ namespace Kernel
} }
return_inode->m_mutex.lock(); return_inode->m_mutex.lock();
memcpy(&return_inode->m_address, &connection.target.address, connection.target.address_len); return_inode->m_port = m_port;
return_inode->m_address_len = connection.target.address_len; return_inode->m_interface = m_interface;
return_inode->m_listen_parent = this; return_inode->m_listen_parent = this;
return_inode->m_connection_info.emplace(connection.target); return_inode->m_connection_info.emplace(connection.target);
return_inode->m_recv_window.start_seq = connection.target_start_seq; return_inode->m_recv_window.start_seq = connection.target_start_seq;
@ -152,18 +152,13 @@ namespace Kernel
}; };
if (!is_bound()) if (!is_bound())
TRY(m_network_layer.bind_socket_with_target(this, address, address_len)); TRY(m_network_layer.bind_socket_to_unused(this, address, address_len));
m_connection_info.emplace(sockaddr_storage {}, address_len, true); m_connection_info.emplace(sockaddr_storage {}, address_len, true);
memcpy(&m_connection_info->address, address, address_len); memcpy(&m_connection_info->address, address, address_len);
m_next_flags = SYN; m_next_flags = SYN;
if (m_network_layer.sendto(*this, {}, address, address_len).is_error()) TRY(m_network_layer.sendto(*this, {}, address, address_len));
{
set_connection_as_closed();
return BAN::Error::from_errno(ECONNREFUSED);
}
m_next_flags = 0; m_next_flags = 0;
m_state = State::SynSent; m_state = State::SynSent;
@ -415,8 +410,8 @@ namespace Kernel
memset(&header, 0, sizeof(TCPHeader)); memset(&header, 0, sizeof(TCPHeader));
memset(header.options, TCPOption::End, m_tcp_options_bytes); memset(header.options, TCPOption::End, m_tcp_options_bytes);
header.src_port = bound_port();
header.dst_port = dst_port; header.dst_port = dst_port;
header.src_port = m_port;
header.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte; header.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte;
header.ack_number = m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte; header.ack_number = m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte;
header.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t); header.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t);
@ -428,15 +423,7 @@ namespace Kernel
if (m_state == State::Closed || m_state == State::SynReceived) if (m_state == State::Closed || m_state == State::SynReceived)
{ {
const sockaddr_in target { add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, m_interface->payload_mtu() - m_network_layer.header_size());
.sin_family = AF_INET,
.sin_port = dst_port,
.sin_addr = { .s_addr = pseudo_header.dst_ipv4.raw },
.sin_zero = {},
};
auto interface = MUST(this->interface(reinterpret_cast<const sockaddr*>(&target), sizeof(target)));
add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, interface->payload_mtu() - m_network_layer.header_size());
if (m_connection_info->has_window_scale) if (m_connection_info->has_window_scale)
add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale_shift); add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale_shift);
@ -464,16 +451,11 @@ namespace Kernel
if (sender->sa_family == AF_INET) if (sender->sa_family == AF_INET)
{ {
auto interface_or_error = interface(sender, sender_len);
if (interface_or_error.is_error())
return;
auto interface = interface_or_error.release_value();
auto& addr_in = *reinterpret_cast<const sockaddr_in*>(sender); auto& addr_in = *reinterpret_cast<const sockaddr_in*>(sender);
checksum = calculate_internet_checksum(buffer, checksum = calculate_internet_checksum(buffer,
PseudoHeader { PseudoHeader {
.src_ipv4 = BAN::IPv4Address(addr_in.sin_addr.s_addr), .src_ipv4 = BAN::IPv4Address(addr_in.sin_addr.s_addr),
.dst_ipv4 = interface->get_ipv4_address(), .dst_ipv4 = m_interface->get_ipv4_address(),
.protocol = NetworkProtocol::TCP, .protocol = NetworkProtocol::TCP,
.extra = buffer.size() .extra = buffer.size()
} }
@ -681,11 +663,11 @@ namespace Kernel
// NOTE: Only listen socket can unbind the socket as // NOTE: Only listen socket can unbind the socket as
// listen socket is always alive to redirect packets // listen socket is always alive to redirect packets
if (!m_listen_parent) if (!m_listen_parent)
m_network_layer.unbind_socket(bound_port()); m_network_layer.unbind_socket(m_port);
else else
m_listen_parent->remove_listen_child(this); m_listen_parent->remove_listen_child(this);
m_address.ss_family = AF_UNSPEC; m_interface = nullptr;
m_address_len = 0; m_port = PORT_NONE;
dprintln_if(DEBUG_TCP, "Socket unbound"); dprintln_if(DEBUG_TCP, "Socket unbound");
} }

View File

@ -30,15 +30,15 @@ namespace Kernel
UDPSocket::~UDPSocket() UDPSocket::~UDPSocket()
{ {
if (is_bound()) if (is_bound())
m_network_layer.unbind_socket(bound_port()); m_network_layer.unbind_socket(m_port);
m_address.ss_family = AF_UNSPEC; m_port = PORT_NONE;
m_address_len = 0; m_interface = nullptr;
} }
void UDPSocket::add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) void UDPSocket::add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader)
{ {
auto& header = packet.as<UDPHeader>(); auto& header = packet.as<UDPHeader>();
header.src_port = bound_port(); header.src_port = m_port;
header.dst_port = dst_port; header.dst_port = dst_port;
header.length = packet.size(); header.length = packet.size();
header.checksum = 0; header.checksum = 0;
@ -115,6 +115,7 @@ namespace Kernel
dprintln("No interface bound"); dprintln("No interface bound");
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }
ASSERT(m_port != PORT_NONE);
SpinLockGuard guard(m_packet_lock); SpinLockGuard guard(m_packet_lock);
@ -175,7 +176,7 @@ namespace Kernel
dwarnln("ignoring sendmsg control message"); dwarnln("ignoring sendmsg control message");
if (!is_bound()) if (!is_bound())
TRY(m_network_layer.bind_socket_with_target(this, static_cast<sockaddr*>(message.msg_name), message.msg_namelen)); TRY(m_network_layer.bind_socket_to_unused(this, static_cast<sockaddr*>(message.msg_name), message.msg_namelen));
const size_t total_send_size = const size_t total_send_size =
[&message]() -> size_t { [&message]() -> size_t {

View File

@ -214,7 +214,7 @@ namespace Kernel
open_file.descriptor_flags = 0; open_file.descriptor_flags = 0;
open_file.inode()->on_clone(open_file.status_flags()); open_file.inode()->on_clone(open_file.status_flags());
return fildes2; return fildes;
} }
BAN::ErrorOr<int> OpenFileDescriptorSet::fcntl(int fd, int cmd, uintptr_t extra) BAN::ErrorOr<int> OpenFileDescriptorSet::fcntl(int fd, int cmd, uintptr_t extra)

View File

@ -189,6 +189,8 @@ namespace Kernel
__builtin_ia32_pause(); __builtin_ia32_pause();
} }
} }
s_is_smp_enabled = true;
} }
void Processor::handle_ipi() void Processor::handle_ipi()

View File

@ -136,9 +136,6 @@ namespace Kernel
while (s_schedulers_initialized < Processor::count()) while (s_schedulers_initialized < Processor::count())
__builtin_ia32_pause(); __builtin_ia32_pause();
if (Processor::count() > 1)
Processor::set_smp_enabled();
return {}; return {};
} }
@ -293,34 +290,10 @@ namespace Kernel
m_current->last_start_ns = SystemTimer::get().ns_since_boot(); m_current->last_start_ns = SystemTimer::get().ns_since_boot();
} }
void Scheduler::wake_up_sleeping_threads()
{
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
while (!m_block_queue.empty() && current_ns >= m_block_queue.front()->wake_time_ns)
{
auto* node = m_block_queue.pop_front();
{
SpinLockGuard _(node->blocker_lock);
if (node->blocker)
node->blocker->remove_blocked_thread(node);
}
node->blocked = false;
update_most_loaded_node_queue(node, &m_run_queue);
m_run_queue.add_thread_to_back(node);
}
}
void Scheduler::reschedule_if_idle() void Scheduler::reschedule_if_idle()
{ {
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled); ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
if (!m_current && !m_run_queue.empty())
if (m_current != nullptr)
return;
if (m_run_queue.empty())
wake_up_sleeping_threads();
if (!m_run_queue.empty())
Processor::yield(); Processor::yield();
} }
@ -331,7 +304,21 @@ namespace Kernel
if (Processor::is_smp_enabled()) if (Processor::is_smp_enabled())
do_load_balancing(); do_load_balancing();
wake_up_sleeping_threads(); {
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
while (!m_block_queue.empty() && current_ns >= m_block_queue.front()->wake_time_ns)
{
auto* node = m_block_queue.pop_front();
{
SpinLockGuard _(node->blocker_lock);
if (node->blocker)
node->blocker->remove_blocked_thread(node);
}
node->blocked = false;
update_most_loaded_node_queue(node, &m_run_queue);
m_run_queue.add_thread_to_back(node);
}
}
{ {
const uint64_t current_ns = SystemTimer::get().ns_since_boot(); const uint64_t current_ns = SystemTimer::get().ns_since_boot();

View File

@ -1,4 +1,3 @@
#include <kernel/Lock/LockGuard.h>
#include <kernel/Scheduler.h> #include <kernel/Scheduler.h>
#include <kernel/Storage/ATA/AHCI/Controller.h> #include <kernel/Storage/ATA/AHCI/Controller.h>
#include <kernel/Storage/ATA/AHCI/Device.h> #include <kernel/Storage/ATA/AHCI/Device.h>
@ -183,8 +182,6 @@ namespace Kernel
BAN::ErrorOr<void> AHCIDevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer) BAN::ErrorOr<void> AHCIDevice::read_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer)
{ {
LockGuard _(m_mutex);
ASSERT(buffer.size() >= sector_count * sector_size()); ASSERT(buffer.size() >= sector_count * sector_size());
const size_t sectors_per_page = PAGE_SIZE / sector_size(); const size_t sectors_per_page = PAGE_SIZE / sector_size();
for (uint64_t sector_off = 0; sector_off < sector_count; sector_off += sectors_per_page) for (uint64_t sector_off = 0; sector_off < sector_count; sector_off += sectors_per_page)
@ -200,8 +197,6 @@ namespace Kernel
BAN::ErrorOr<void> AHCIDevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer) BAN::ErrorOr<void> AHCIDevice::write_sectors_impl(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer)
{ {
LockGuard _(m_mutex);
ASSERT(buffer.size() >= sector_count * sector_size()); ASSERT(buffer.size() >= sector_count * sector_size());
const size_t sectors_per_page = PAGE_SIZE / sector_size(); const size_t sectors_per_page = PAGE_SIZE / sector_size();
for (uint64_t sector_off = 0; sector_off < sector_count; sector_off += sectors_per_page) for (uint64_t sector_off = 0; sector_off < sector_count; sector_off += sectors_per_page)

View File

@ -1,4 +1,3 @@
#include <BAN/ScopeGuard.h>
#include <kernel/BootInfo.h> #include <kernel/BootInfo.h>
#include <kernel/Memory/Heap.h> #include <kernel/Memory/Heap.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
@ -22,133 +21,96 @@ namespace Kernel
release_all_pages(); release_all_pages();
} }
size_t DiskCache::find_sector_cache_index(uint64_t sector) const
{
const uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
const uint64_t page_cache_offset = sector % sectors_per_page;
const uint64_t page_cache_start = sector - page_cache_offset;
size_t l = 0, r = m_cache.size();
while (l < r)
{
const size_t mid = (l + r) / 2;
if (m_cache[mid].first_sector == page_cache_start)
return mid;
if (m_cache[mid].first_sector < page_cache_start)
l = mid + 1;
else
r = mid;
}
return l;
}
bool DiskCache::read_from_cache(uint64_t sector, BAN::ByteSpan buffer) bool DiskCache::read_from_cache(uint64_t sector, BAN::ByteSpan buffer)
{ {
ASSERT(buffer.size() >= m_sector_size); ASSERT(buffer.size() >= m_sector_size);
const uint64_t sectors_per_page = PAGE_SIZE / m_sector_size; uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
const uint64_t page_cache_offset = sector % sectors_per_page; uint64_t page_cache_offset = sector % sectors_per_page;
const uint64_t page_cache_start = sector - page_cache_offset; uint64_t page_cache_start = sector - page_cache_offset;
RWLockRDGuard _(m_rw_lock); for (auto& cache : m_cache)
{
if (cache.first_sector + sectors_per_page <= page_cache_start)
continue;
if (cache.first_sector > page_cache_start)
break;
const auto index = find_sector_cache_index(sector); if (!(cache.sector_mask & (1 << page_cache_offset)))
if (index >= m_cache.size()) continue;
return false;
const auto& cache = m_cache[index]; PageTable::with_fast_page(cache.paddr, [&] {
if (cache.first_sector != page_cache_start) memcpy(buffer.data(), PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), m_sector_size);
return false; });
if (!(cache.sector_mask & (1 << page_cache_offset)))
return false;
PageTable::with_fast_page(cache.paddr, [&] { return true;
memcpy(buffer.data(), PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), m_sector_size); }
});
return true; return false;
}; };
BAN::ErrorOr<void> DiskCache::write_to_cache(uint64_t sector, BAN::ConstByteSpan buffer, bool dirty) BAN::ErrorOr<void> DiskCache::write_to_cache(uint64_t sector, BAN::ConstByteSpan buffer, bool dirty)
{ {
ASSERT(buffer.size() >= m_sector_size); ASSERT(buffer.size() >= m_sector_size);
uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
uint64_t page_cache_offset = sector % sectors_per_page;
uint64_t page_cache_start = sector - page_cache_offset;
const uint64_t sectors_per_page = PAGE_SIZE / m_sector_size; size_t index = 0;
const uint64_t page_cache_offset = sector % sectors_per_page;
const uint64_t page_cache_start = sector - page_cache_offset;
RWLockWRGuard _(m_rw_lock); // Search the cache if the have this sector in memory
for (; index < m_cache.size(); index++)
const auto index = find_sector_cache_index(sector);
if (index >= m_cache.size() || m_cache[index].first_sector != page_cache_start)
{ {
paddr_t paddr = Heap::get().take_free_page(); auto& cache = m_cache[index];
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
PageCache cache { if (cache.first_sector + sectors_per_page <= page_cache_start)
.paddr = paddr, continue;
.first_sector = page_cache_start, if (cache.first_sector > page_cache_start)
.sector_mask = 0, break;
.dirty_mask = 0,
};
if (auto ret = m_cache.insert(index, cache); ret.is_error()) PageTable::with_fast_page(cache.paddr, [&] {
{ memcpy(PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
Heap::get().release_page(paddr); });
return ret.error();
} cache.sector_mask |= 1 << page_cache_offset;
if (dirty)
cache.dirty_mask |= 1 << page_cache_offset;
return {};
} }
auto& cache = m_cache[index]; // Try to add new page to the cache
paddr_t paddr = Heap::get().take_free_page();
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
PageCache cache;
cache.paddr = paddr;
cache.first_sector = page_cache_start;
cache.sector_mask = 1 << page_cache_offset;
cache.dirty_mask = dirty ? cache.sector_mask : 0;
if (auto ret = m_cache.insert(index, cache); ret.is_error())
{
Heap::get().release_page(paddr);
return ret.error();
}
PageTable::with_fast_page(cache.paddr, [&] { PageTable::with_fast_page(cache.paddr, [&] {
memcpy(PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), buffer.data(), m_sector_size); memcpy(PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
}); });
cache.sector_mask |= 1 << page_cache_offset;
if (dirty)
cache.dirty_mask |= 1 << page_cache_offset;
return {}; return {};
} }
BAN::ErrorOr<void> DiskCache::sync_cache_index(size_t index) BAN::ErrorOr<void> DiskCache::sync_cache_index(size_t index)
{ {
LockGuard _(m_sync_mutex); auto& cache = m_cache[index];
if (cache.dirty_mask == 0)
return {};
PageCache temp_cache; PageTable::with_fast_page(cache.paddr, [&] {
memcpy(m_sync_cache.data(), PageTable::fast_page_as_ptr(), PAGE_SIZE);
{
RWLockWRGuard _(m_rw_lock);
if (index >= m_cache.size())
return {};
auto& cache = m_cache[index];
if (cache.dirty_mask == 0)
return {};
PageTable::with_fast_page(cache.paddr, [&] {
memcpy(m_sync_cache.data(), PageTable::fast_page_as_ptr(), PAGE_SIZE);
});
temp_cache = cache;
cache.dirty_mask = 0;
cache.syncing = true;
}
// restores dirty mask if write to disk fails
BAN::ScopeGuard dirty_guard([&] {
RWLockWRGuard _(m_rw_lock);
const auto new_index = find_sector_cache_index(temp_cache.first_sector);
ASSERT(new_index < m_cache.size() && m_cache[new_index].first_sector == temp_cache.first_sector);
m_cache[new_index].dirty_mask |= temp_cache.dirty_mask;
m_cache[new_index].syncing = false;
}); });
uint8_t sector_start = 0; uint8_t sector_start = 0;
@ -156,16 +118,15 @@ namespace Kernel
while (sector_start + sector_count <= PAGE_SIZE / m_sector_size) while (sector_start + sector_count <= PAGE_SIZE / m_sector_size)
{ {
if (temp_cache.dirty_mask & (1 << (sector_start + sector_count))) if (cache.dirty_mask & (1 << (sector_start + sector_count)))
sector_count++; sector_count++;
else if (sector_count == 0) else if (sector_count == 0)
sector_start++; sector_start++;
else else
{ {
dprintln_if(DEBUG_DISK_SYNC, "syncing {}->{}", temp_cache.first_sector + sector_start, temp_cache.first_sector + sector_start + sector_count); dprintln_if(DEBUG_DISK_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size); auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size);
TRY(m_device.write_sectors_impl(temp_cache.first_sector + sector_start, sector_count, data_slice)); TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
temp_cache.dirty_mask &= ~(((1 << sector_count) - 1) << sector_start);
sector_start += sector_count + 1; sector_start += sector_count + 1;
sector_count = 0; sector_count = 0;
} }
@ -173,12 +134,13 @@ namespace Kernel
if (sector_count > 0) if (sector_count > 0)
{ {
dprintln_if(DEBUG_DISK_SYNC, "syncing {}->{}", temp_cache.first_sector + sector_start, temp_cache.first_sector + sector_start + sector_count); dprintln_if(DEBUG_DISK_SYNC, "syncing {}->{}", cache.first_sector + sector_start, cache.first_sector + sector_start + sector_count);
auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size); auto data_slice = m_sync_cache.span().slice(sector_start * m_sector_size, sector_count * m_sector_size);
TRY(m_device.write_sectors_impl(temp_cache.first_sector + sector_start, sector_count, data_slice)); TRY(m_device.write_sectors_impl(cache.first_sector + sector_start, sector_count, data_slice));
temp_cache.dirty_mask &= ~(((1 << sector_count) - 1) << sector_start);
} }
cache.dirty_mask = 0;
return {}; return {};
} }
@ -196,17 +158,19 @@ namespace Kernel
if (g_disable_disk_write) if (g_disable_disk_write)
return {}; return {};
m_rw_lock.rd_lock(); uint64_t sectors_per_page = PAGE_SIZE / m_sector_size;
for (size_t i = find_sector_cache_index(sector); i < m_cache.size(); i++) uint64_t page_cache_offset = sector % sectors_per_page;
uint64_t page_cache_start = sector - page_cache_offset;
for (size_t i = 0; i < m_cache.size(); i++)
{ {
auto& cache = m_cache[i]; auto& cache = m_cache[i];
if (cache.first_sector >= sector + block_count) if (cache.first_sector + sectors_per_page <= page_cache_start)
continue;
if (cache.first_sector * sectors_per_page >= page_cache_start * sectors_per_page + block_count)
break; break;
m_rw_lock.rd_unlock();
TRY(sync_cache_index(i)); TRY(sync_cache_index(i));
m_rw_lock.rd_lock();
} }
m_rw_lock.rd_unlock();
return {}; return {};
} }
@ -216,12 +180,10 @@ namespace Kernel
// NOTE: There might not actually be page_count pages after this // NOTE: There might not actually be page_count pages after this
// function returns. The synchronization must be done elsewhere. // function returns. The synchronization must be done elsewhere.
RWLockWRGuard _(m_rw_lock);
size_t released = 0; size_t released = 0;
for (size_t i = 0; i < m_cache.size() && released < page_count;) for (size_t i = 0; i < m_cache.size() && released < page_count;)
{ {
if (!m_cache[i].syncing && m_cache[i].dirty_mask == 0) if (m_cache[i].dirty_mask == 0)
{ {
Heap::get().release_page(m_cache[i].paddr); Heap::get().release_page(m_cache[i].paddr);
m_cache.remove(i); m_cache.remove(i);

View File

@ -211,12 +211,14 @@ namespace Kernel
void StorageDevice::add_disk_cache() void StorageDevice::add_disk_cache()
{ {
LockGuard _(m_mutex);
ASSERT(!m_disk_cache.has_value()); ASSERT(!m_disk_cache.has_value());
m_disk_cache.emplace(sector_size(), *this); m_disk_cache.emplace(sector_size(), *this);
} }
size_t StorageDevice::drop_disk_cache() size_t StorageDevice::drop_disk_cache()
{ {
LockGuard _(m_mutex);
if (m_disk_cache.has_value()) if (m_disk_cache.has_value())
return m_disk_cache->release_pages(-1); return m_disk_cache->release_pages(-1);
return 0; return 0;
@ -224,6 +226,7 @@ namespace Kernel
BAN::ErrorOr<void> StorageDevice::sync_disk_cache() BAN::ErrorOr<void> StorageDevice::sync_disk_cache()
{ {
LockGuard _(m_mutex);
if (m_disk_cache.has_value()) if (m_disk_cache.has_value())
TRY(m_disk_cache->sync()); TRY(m_disk_cache->sync());
return {}; return {};
@ -233,6 +236,8 @@ namespace Kernel
{ {
ASSERT(buffer.size() >= sector_count * sector_size()); ASSERT(buffer.size() >= sector_count * sector_size());
LockGuard _(m_mutex);
if (!m_disk_cache.has_value()) if (!m_disk_cache.has_value())
return read_sectors_impl(lba, sector_count, buffer); return read_sectors_impl(lba, sector_count, buffer);
@ -270,6 +275,8 @@ namespace Kernel
{ {
ASSERT(buffer.size() >= sector_count * sector_size()); ASSERT(buffer.size() >= sector_count * sector_size());
LockGuard _(m_mutex);
if (g_disable_disk_write) if (g_disable_disk_write)
{ {
if (!m_disk_cache.has_value()) if (!m_disk_cache.has_value())

View File

@ -636,12 +636,12 @@ namespace Kernel
: reinterpret_cast<vaddr_t>(handler.sa_handler); : reinterpret_cast<vaddr_t>(handler.sa_handler);
has_sa_restart = !!(handler.sa_flags & SA_RESTART); has_sa_restart = !!(handler.sa_flags & SA_RESTART);
if (handler.sa_flags & SA_RESETHAND)
handler = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 };
const auto& alt_stack = m_signal_alt_stack; const auto& alt_stack = m_signal_alt_stack;
if (alt_stack.ss_flags != SS_DISABLE && (handler.sa_flags & SA_ONSTACK) && !currently_on_alternate_stack()) if (alt_stack.ss_flags != SS_DISABLE && (handler.sa_flags & SA_ONSTACK) && !currently_on_alternate_stack())
signal_stack_top = reinterpret_cast<vaddr_t>(alt_stack.ss_sp) + alt_stack.ss_size; signal_stack_top = reinterpret_cast<vaddr_t>(alt_stack.ss_sp) + alt_stack.ss_size;
if (handler.sa_flags & SA_RESETHAND)
handler = { .sa_handler = SIG_DFL, .sa_mask = 0, .sa_flags = 0 };
} }
m_signal_pending_mask &= ~(1ull << signal); m_signal_pending_mask &= ~(1ull << signal);

View File

@ -3,7 +3,6 @@
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/USB/HID/HIDDriver.h> #include <kernel/USB/HID/HIDDriver.h>
#include <kernel/USB/HID/Joystick.h>
#include <kernel/USB/HID/Keyboard.h> #include <kernel/USB/HID/Keyboard.h>
#include <kernel/USB/HID/Mouse.h> #include <kernel/USB/HID/Mouse.h>
@ -209,10 +208,6 @@ namespace Kernel
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }
for (auto& report : m_device_inputs)
if (report.device && report.device->initialize().is_error())
report.device.clear();
m_device.send_data_buffer(m_data_endpoint_id, m_data_buffer->paddr(), m_data_buffer->size()); m_device.send_data_buffer(m_data_endpoint_id, m_data_buffer->paddr(), m_data_buffer->size());
return {}; return {};
@ -261,10 +256,6 @@ namespace Kernel
report.device = TRY(BAN::RefPtr<USBMouse>::create()); report.device = TRY(BAN::RefPtr<USBMouse>::create());
dprintln("Initialized an USB Mouse"); dprintln("Initialized an USB Mouse");
break; break;
case 0x04:
report.device = TRY(BAN::RefPtr<USBJoystick>::create(*this));
dprintln("Initialized an USB Joystick");
break;
case 0x06: case 0x06:
report.device = TRY(BAN::RefPtr<USBKeyboard>::create(*this, BAN::move(outputs))); report.device = TRY(BAN::RefPtr<USBKeyboard>::create(*this, BAN::move(outputs)));
dprintln("Initialized an USB Keyboard"); dprintln("Initialized an USB Keyboard");
@ -385,13 +376,13 @@ namespace Kernel
continue; continue;
} }
const uint32_t usage_base = input.usage_id ? input.usage_id : input.usage_minimum;
const bool relative = !!(input.flags & 0x04); const bool relative = !!(input.flags & 0x04);
const bool variable = !!(input.flags & 0x02); const bool variable = !!(input.flags & 0x02);
const auto usage = input.usage_id ? input.usage_id : (input.usage_minimum + (variable ? i : logical));
if (!variable) if (!variable)
device_input.device->handle_array(input.usage_page, usage); device_input.device->handle_array(input.usage_page, usage_base + logical);
else else
{ {
const int64_t physical = const int64_t physical =
@ -401,9 +392,9 @@ namespace Kernel
input.physical_minimum; input.physical_minimum;
if (relative) if (relative)
device_input.device->handle_variable(input.usage_page, usage, physical); device_input.device->handle_variable(input.usage_page, usage_base + i, physical);
else else
device_input.device->handle_variable_absolute(input.usage_page, usage, physical, input.physical_minimum, input.physical_maximum); device_input.device->handle_variable_absolute(input.usage_page, usage_base + i, physical, input.physical_minimum, input.physical_maximum);
} }
bit_offset += input.report_size; bit_offset += input.report_size;
@ -604,16 +595,15 @@ namespace Kernel
break; break;
case 0b1010: // collection case 0b1010: // collection
{ {
if (local_state.usage_stack.size() > 1) if (local_state.usage_stack.size() != 1)
{ {
dwarnln("Multiple usages specified for a collection"); dwarnln("{} usages specified for collection", local_state.usage_stack.empty() ? "No" : "Multiple");
return BAN::Error::from_errno(EFAULT); return BAN::Error::from_errno(EFAULT);
} }
uint16_t usage_page = 0; uint16_t usage_page = 0;
if (global_state.usage_page.has_value()) if (global_state.usage_page.has_value())
usage_page = global_state.usage_page.value(); usage_page = global_state.usage_page.value();
if (!local_state.usage_stack.empty() && local_state.usage_stack.front() >> 16) if (local_state.usage_stack.front() >> 16)
usage_page = local_state.usage_stack.front() >> 16; usage_page = local_state.usage_stack.front() >> 16;
if (usage_page == 0) if (usage_page == 0)
{ {
@ -622,11 +612,8 @@ namespace Kernel
} }
TRY(collection_stack.emplace_back()); TRY(collection_stack.emplace_back());
collection_stack.back().type = report_data[1];
collection_stack.back().usage_page = usage_page; collection_stack.back().usage_page = usage_page;
if (!local_state.usage_stack.empty()) collection_stack.back().usage_id = local_state.usage_stack.front();
collection_stack.back().usage_id = local_state.usage_stack.front();
break; break;
} }
case 0b1100: // end collection case 0b1100: // end collection

View File

@ -1,114 +0,0 @@
#include <kernel/Input/InputDevice.h>
#include <kernel/USB/HID/Joystick.h>
namespace Kernel
{
USBJoystick::USBJoystick(USBHIDDriver& driver)
: USBHIDDevice(InputDevice::Type::Joystick)
, m_driver(driver)
{
}
BAN::ErrorOr<void> USBJoystick::initialize()
{
// TODO: this is not a generic USB HID joystick driver but one for PS3 controller.
// this may still work with other HID joysticks so i won't limit this only
// based on the device.
// linux hid-sony.c
auto temp_region = TRY(DMARegion::create(17));
USBDeviceRequest request;
// move ps3 controller to "operational" state
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Class | USB::RequestType::Interface;
request.bRequest = 0x01;
request.wValue = 0x03F2;
request.wIndex = m_driver.interface().descriptor.bInterfaceNumber;
request.wLength = 17;
TRY(m_driver.device().send_request(request, temp_region->paddr()));
// some compatible controllers need this too
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Class | USB::RequestType::Interface;
request.bRequest = 0x01;
request.wValue = 0x03F5;
request.wIndex = m_driver.interface().descriptor.bInterfaceNumber;
request.wLength = 8;
TRY(m_driver.device().send_request(request, temp_region->paddr()));
return {};
}
void USBJoystick::start_report()
{
m_interrupt_state = m_state_lock.lock();
for (auto& axis : m_state.axis)
axis = {};
for (auto& button : m_state.buttons)
button = false;
}
void USBJoystick::stop_report()
{
m_state_lock.unlock(m_interrupt_state);
}
void USBJoystick::handle_array(uint16_t usage_page, uint16_t usage)
{
(void)usage;
dprintln("Unsupported array {2H}", usage_page);
}
void USBJoystick::handle_variable(uint16_t usage_page, uint16_t usage, int64_t state)
{
(void)usage;
(void)state;
dprintln("Unsupported relative usage page {2H}", usage_page);
}
void USBJoystick::handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max)
{
switch (usage_page)
{
case 0x01:
switch (usage)
{
case 0x01:
// TODO: PS3 controller sends some extra data with this usage
break;
case 0x30:
m_state.axis[0] = { state, min, max };
break;
case 0x31:
m_state.axis[1] = { state, min, max };
break;
case 0x32:
m_state.axis[2] = { state, min, max };
break;
case 0x35:
m_state.axis[3] = { state, min, max };
break;
}
break;
case 0x09:
if (usage > 0 && usage <= sizeof(m_state.buttons))
m_state.buttons[usage - 1] = state;
break;
default:
dprintln("Unsupported absolute usage page {2H}", usage_page);
break;
}
}
BAN::ErrorOr<size_t> USBJoystick::read_impl(off_t, BAN::ByteSpan buffer)
{
SpinLockGuard _(m_state_lock);
const size_t to_copy = BAN::Math::min(buffer.size(), sizeof(m_state));
memcpy(buffer.data(), &m_state, to_copy);
return to_copy;
}
}

View File

@ -3,7 +3,7 @@
NAME='SDL2' NAME='SDL2'
VERSION='2.32.8' VERSION='2.32.8'
DOWNLOAD_URL="https://github.com/libsdl-org/SDL/releases/download/release-$VERSION/SDL2-$VERSION.tar.gz#0ca83e9c9b31e18288c7ec811108e58bac1f1bb5ec6577ad386830eac51c787e" DOWNLOAD_URL="https://github.com/libsdl-org/SDL/releases/download/release-$VERSION/SDL2-$VERSION.tar.gz#0ca83e9c9b31e18288c7ec811108e58bac1f1bb5ec6577ad386830eac51c787e"
DEPENDENCIES=('mesa' 'libiconv') DEPENDENCIES=('mesa')
configure() { configure() {
$BANAN_CMAKE --fresh -S . -B build -G Ninja \ $BANAN_CMAKE --fresh -S . -B build -G Ninja \
@ -11,7 +11,7 @@ configure() {
-DCMAKE_INSTALL_PREFIX='/usr' \ -DCMAKE_INSTALL_PREFIX='/usr' \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DSDL_LIBSAMPLERATE=OFF \ -DSDL_LIBSAMPLERATE=OFF \
-DSDL_STATIC=OFF \ -DSDL_PTHREADS_SEM=OFF \
|| exit 1 || exit 1
} }

View File

@ -1,6 +1,6 @@
diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake
--- SDL2-2.32.8/cmake/sdlplatform.cmake 2024-08-14 13:35:43.000000000 +0300 --- SDL2-2.32.8/cmake/sdlplatform.cmake 2024-08-14 13:35:43.000000000 +0300
+++ SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake 2026-01-03 19:50:45.777185459 +0200 +++ SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake 2025-11-22 00:45:00.922311100 +0200
@@ -28,6 +28,8 @@ @@ -28,6 +28,8 @@
set(SDL_CMAKE_PLATFORM AIX) set(SDL_CMAKE_PLATFORM AIX)
elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*") elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*")
@ -12,7 +12,7 @@ diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplat
endif() endif()
diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
--- SDL2-2.32.8/CMakeLists.txt 2025-06-03 02:00:39.000000000 +0300 --- SDL2-2.32.8/CMakeLists.txt 2025-06-03 02:00:39.000000000 +0300
+++ SDL2-2.32.8-banan_os/CMakeLists.txt 2026-01-03 19:51:02.494165302 +0200 +++ SDL2-2.32.8-banan_os/CMakeLists.txt 2025-11-22 00:45:00.923441418 +0200
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
set(SDL2_SUBPROJECT ON) set(SDL2_SUBPROJECT ON)
endif() endif()
@ -31,7 +31,7 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
if(SDL_AUDIO) if(SDL_AUDIO)
if(SYSV5 OR SOLARIS OR HPUX) if(SYSV5 OR SOLARIS OR HPUX)
set(SDL_AUDIO_DRIVER_SUNAUDIO 1) set(SDL_AUDIO_DRIVER_SUNAUDIO 1)
@@ -2459,6 +2459,64 @@ @@ -2459,6 +2459,57 @@
CheckPTHREAD() CheckPTHREAD()
list(APPEND EXTRA_LIBS root be media game device textencoding) list(APPEND EXTRA_LIBS root be media game device textencoding)
@ -50,13 +50,6 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
+ list(APPEND EXTRA_LIBS audio) + list(APPEND EXTRA_LIBS audio)
+ endif() + endif()
+ +
+ if(SDL_JOYSTICK)
+ set(SDL_JOYSTICK_BANANOS 1)
+ file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/banan_os/*.cpp)
+ list(APPEND SOURCE_FILES ${JOYSTICK_SOURCES})
+ set(HAVE_SDL_JOYSTICK TRUE)
+ endif()
+
+ if(SDL_VIDEO) + if(SDL_VIDEO)
+ set(SDL_VIDEO_DRIVER_BANANOS 1) + set(SDL_VIDEO_DRIVER_BANANOS 1)
+ file(GLOB VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/banan_os/*.cpp) + file(GLOB VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/banan_os/*.cpp)
@ -98,7 +91,7 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c) file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c)
diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SDL_config.h.cmake diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SDL_config.h.cmake
--- SDL2-2.32.8/include/SDL_config.h.cmake 2025-01-01 17:47:53.000000000 +0200 --- SDL2-2.32.8/include/SDL_config.h.cmake 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_config.h.cmake 2026-01-03 19:55:22.679890924 +0200 +++ SDL2-2.32.8-banan_os/include/SDL_config.h.cmake 2025-11-22 00:45:00.924001549 +0200
@@ -307,6 +307,7 @@ @@ -307,6 +307,7 @@
#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@ #cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@
#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@ #cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@
@ -107,15 +100,7 @@ diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SD
#cmakedefine SDL_AUDIO_DRIVER_JACK @SDL_AUDIO_DRIVER_JACK@ #cmakedefine SDL_AUDIO_DRIVER_JACK @SDL_AUDIO_DRIVER_JACK@
#cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@ #cmakedefine SDL_AUDIO_DRIVER_JACK_DYNAMIC @SDL_AUDIO_DRIVER_JACK_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@ #cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@
@@ -337,6 +338,7 @@ @@ -406,6 +407,7 @@
#cmakedefine SDL_INPUT_WSCONS @SDL_INPUT_WSCONS@
#cmakedefine SDL_JOYSTICK_ANDROID @SDL_JOYSTICK_ANDROID@
#cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@
+#cmakedefine SDL_JOYSTICK_BANANOS @SDL_JOYSTICK_BANANOS@
#cmakedefine SDL_JOYSTICK_WGI @SDL_JOYSTICK_WGI@
#cmakedefine SDL_JOYSTICK_DINPUT @SDL_JOYSTICK_DINPUT@
#cmakedefine SDL_JOYSTICK_XINPUT @SDL_JOYSTICK_XINPUT@
@@ -406,6 +408,7 @@
#cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@ #cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@
#cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@ #cmakedefine SDL_VIDEO_DRIVER_EMSCRIPTEN @SDL_VIDEO_DRIVER_EMSCRIPTEN@
#cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@ #cmakedefine SDL_VIDEO_DRIVER_HAIKU @SDL_VIDEO_DRIVER_HAIKU@
@ -125,7 +110,7 @@ diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SD
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@ #cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_platform.h diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_platform.h
--- SDL2-2.32.8/include/SDL_platform.h 2025-01-01 17:47:53.000000000 +0200 --- SDL2-2.32.8/include/SDL_platform.h 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_platform.h 2026-01-03 19:50:45.778818009 +0200 +++ SDL2-2.32.8-banan_os/include/SDL_platform.h 2025-11-22 00:45:00.924303894 +0200
@@ -36,6 +36,10 @@ @@ -36,6 +36,10 @@
#undef __HAIKU__ #undef __HAIKU__
#define __HAIKU__ 1 #define __HAIKU__ 1
@ -139,7 +124,7 @@ diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_pl
#define __BSDI__ 1 #define __BSDI__ 1
diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp 1970-01-01 02:00:00.000000000 +0200 --- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp 2026-01-03 19:50:45.779146754 +0200 +++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp 2025-11-22 00:45:00.924702550 +0200
@@ -0,0 +1,150 @@ @@ -0,0 +1,150 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -293,7 +278,7 @@ diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp SDL2-2.32.8-bana
+#endif +#endif
diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h 1970-01-01 02:00:00.000000000 +0200 --- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h 2026-01-03 19:50:45.779253053 +0200 +++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h 2025-11-22 00:45:00.924820303 +0200
@@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -331,7 +316,7 @@ diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h SDL2-2.32.8-banan_
+}; +};
diff -ruN SDL2-2.32.8/src/audio/SDL_audio.c SDL2-2.32.8-banan_os/src/audio/SDL_audio.c diff -ruN SDL2-2.32.8/src/audio/SDL_audio.c SDL2-2.32.8-banan_os/src/audio/SDL_audio.c
--- SDL2-2.32.8/src/audio/SDL_audio.c 2025-01-01 17:47:53.000000000 +0200 --- SDL2-2.32.8/src/audio/SDL_audio.c 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/SDL_audio.c 2026-01-03 19:50:45.779381073 +0200 +++ SDL2-2.32.8-banan_os/src/audio/SDL_audio.c 2025-11-22 00:45:00.925178591 +0200
@@ -87,6 +87,9 @@ @@ -87,6 +87,9 @@
#ifdef SDL_AUDIO_DRIVER_HAIKU #ifdef SDL_AUDIO_DRIVER_HAIKU
&HAIKUAUDIO_bootstrap, &HAIKUAUDIO_bootstrap,
@ -344,7 +329,7 @@ diff -ruN SDL2-2.32.8/src/audio/SDL_audio.c SDL2-2.32.8-banan_os/src/audio/SDL_a
#endif #endif
diff -ruN SDL2-2.32.8/src/audio/SDL_sysaudio.h SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h diff -ruN SDL2-2.32.8/src/audio/SDL_sysaudio.h SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h
--- SDL2-2.32.8/src/audio/SDL_sysaudio.h 2025-01-01 17:47:53.000000000 +0200 --- SDL2-2.32.8/src/audio/SDL_sysaudio.h 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h 2026-01-03 19:50:45.779975705 +0200 +++ SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h 2025-11-22 00:45:00.925759535 +0200
@@ -196,6 +196,7 @@ @@ -196,6 +196,7 @@
extern AudioBootStrap WINMM_bootstrap; extern AudioBootStrap WINMM_bootstrap;
extern AudioBootStrap PAUDIO_bootstrap; extern AudioBootStrap PAUDIO_bootstrap;
@ -353,345 +338,9 @@ diff -ruN SDL2-2.32.8/src/audio/SDL_sysaudio.h SDL2-2.32.8-banan_os/src/audio/SD
extern AudioBootStrap COREAUDIO_bootstrap; extern AudioBootStrap COREAUDIO_bootstrap;
extern AudioBootStrap DISKAUDIO_bootstrap; extern AudioBootStrap DISKAUDIO_bootstrap;
extern AudioBootStrap DUMMYAUDIO_bootstrap; extern AudioBootStrap DUMMYAUDIO_bootstrap;
diff -ruN SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp SDL2-2.32.8-banan_os/src/joystick/banan_os/SDL_banan_os_joystick.cpp
--- SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/joystick/banan_os/SDL_banan_os_joystick.cpp 2026-01-03 19:51:21.437329388 +0200
@@ -0,0 +1,308 @@
+/*
+Simple DirectMedia Layer
+Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifdef SDL_JOYSTICK_BANANOS
+
+#include <BAN/Math.h>
+
+#include <LibInput/Joystick.h>
+
+extern "C"
+{
+
+#include "SDL_joystick.h"
+#include "../SDL_sysjoystick.h"
+#include "../SDL_joystick_c.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define MAX_JOYSTICKS 16
+
+struct joystick_hwdata
+{
+ int fd;
+};
+
+static int s_joystick_count = 0;
+static char* s_joystick_path[MAX_JOYSTICKS];
+
+static void BANANOS_JoystickDetect(void);
+
+static int BANANOS_JoystickInit(void)
+{
+ s_joystick_count = 0;
+
+ for (int i = 0; i < MAX_JOYSTICKS; i++)
+ {
+ char path[PATH_MAX];
+ sprintf(path, "/dev/joystick%d", i);
+
+ struct stat st;
+ if (stat(path, &st) == -1)
+ continue;
+
+ s_joystick_path[i] = SDL_strdup(path);
+ if (s_joystick_path[i] == NULL)
+ continue;
+ s_joystick_count++;
+ }
+
+ return 0;
+}
+
+static int BANANOS_JoystickGetCount(void)
+{
+ return s_joystick_count;
+}
+
+static void BANANOS_JoystickDetect(void)
+{
+}
+
+static const char* BANANOS_JoystickGetDeviceName(int device_index)
+{
+ return s_joystick_path[device_index] + strlen("/dev/");
+}
+
+static const char* BANANOS_JoystickGetDevicePath(int device_index)
+{
+ return s_joystick_path[device_index];
+}
+
+static int BANANOS_JoystickGetDeviceSteamVirtualGamepadSlot(int device_index)
+{
+ (void)device_index;
+ return -1;
+}
+
+static int BANANOS_JoystickGetDevicePlayerIndex(int device_index)
+{
+ (void)device_index;
+ return -1;
+}
+
+static void BANANOS_JoystickSetDevicePlayerIndex(int device_index, int player_index)
+{
+ (void)device_index;
+ (void)player_index;
+}
+
+static SDL_JoystickID BANANOS_JoystickGetDeviceInstanceID(int device_index)
+{
+ return device_index;
+}
+
+static void BANANOS_JoystickClose(SDL_Joystick* joystick)
+{
+ if (joystick->hwdata == NULL)
+ return;
+
+ if (joystick->hwdata->fd != -1)
+ close(joystick->hwdata->fd);
+ SDL_free(joystick->hwdata);
+}
+
+static int BANANOS_JoystickOpen(SDL_Joystick* joystick, int device_index)
+{
+ joystick->instance_id = device_index;
+ joystick->hwdata = static_cast<joystick_hwdata*>(SDL_calloc(1, sizeof(joystick_hwdata)));
+ if (joystick->hwdata == NULL)
+ return SDL_OutOfMemory();
+
+ joystick->hwdata->fd = open(s_joystick_path[device_index], O_RDONLY);
+ if (joystick->hwdata->fd == -1)
+ {
+ BANANOS_JoystickClose(joystick);
+ return SDL_SetError("Unable to open joystick");
+ }
+
+ joystick->nbuttons = sizeof(LibInput::JoystickState::buttons) / sizeof(*LibInput::JoystickState::buttons);
+ joystick->naxes = sizeof(LibInput::JoystickState::axis) / sizeof(*LibInput::JoystickState::axis);
+ joystick->nhats = 0;
+
+ return 0;
+}
+
+static void BANANOS_JoystickUpdate(SDL_Joystick *joystick)
+{
+ LibInput::JoystickState state;
+ if (read(joystick->hwdata->fd, &state, sizeof(state)) < static_cast<ssize_t>(sizeof(state)))
+ return;
+
+ const auto map_joystick_value =
+ [](const LibInput::JoystickState::Axis& axis) -> Sint16
+ {
+ if (axis.min == axis.max)
+ return 0;
+ const float mapped = (axis.value - axis.min) * 65534.0f / (axis.max - axis.min) - 32767.0f;
+ return BAN::Math::clamp<Sint32>(mapped, -32767, 32767);
+ };
+
+ for (int i = 0; i < joystick->naxes; i++)
+ SDL_PrivateJoystickAxis(joystick, i, map_joystick_value(state.axis[i]));
+
+ for (int i = 0; i < joystick->nbuttons; i++)
+ SDL_PrivateJoystickButton(joystick, i, state.buttons[i]);
+}
+
+static void BANANOS_JoystickQuit(void)
+{
+ for (int i = 0; i < s_joystick_count; i++)
+ SDL_free(s_joystick_path[i]);
+}
+
+static SDL_JoystickGUID BANANOS_JoystickGetDeviceGUID(int device_index)
+{
+ return SDL_CreateJoystickGUIDForName(BANANOS_JoystickGetDeviceName(device_index));
+}
+
+static int BANANOS_JoystickRumble(SDL_Joystick* joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
+{
+ (void)joystick;
+ (void)low_frequency_rumble;
+ (void)high_frequency_rumble;
+ return SDL_Unsupported();
+}
+
+static int BANANOS_JoystickRumbleTriggers(SDL_Joystick* joystick, Uint16 left_rumble, Uint16 right_rumble)
+{
+ (void)joystick;
+ (void)left_rumble;
+ (void)right_rumble;
+ return SDL_Unsupported();
+}
+
+static SDL_bool BANANOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping* out)
+{
+ (void)device_index;
+
+ // FIXME: this is hardcoded to a PS3 controller layout :D
+
+ memset(out, 0, sizeof(SDL_GamepadMapping));
+
+#define BANANOS_MAP_BUTTON(name, button) \
+ out->name.kind = EMappingKind_Button; \
+ out->name.target = button
+
+#define BANANOS_MAP_AXIS(name, axis) \
+ out->name.kind = EMappingKind_Axis; \
+ out->name.target = axis
+
+ BANANOS_MAP_BUTTON(a, 14);
+ BANANOS_MAP_BUTTON(b, 13);
+ BANANOS_MAP_BUTTON(x, 15);
+ BANANOS_MAP_BUTTON(y, 12);
+
+ BANANOS_MAP_BUTTON(back, 0);
+ BANANOS_MAP_BUTTON(guide, 16);
+ BANANOS_MAP_BUTTON(start, 3);
+
+ BANANOS_MAP_BUTTON(leftstick, 1);
+ BANANOS_MAP_BUTTON(rightstick, 2);
+
+ BANANOS_MAP_BUTTON(leftshoulder, 10);
+ BANANOS_MAP_BUTTON(rightshoulder, 11);
+
+ BANANOS_MAP_BUTTON(dpup, 4);
+ BANANOS_MAP_BUTTON(dpdown, 6);
+ BANANOS_MAP_BUTTON(dpleft, 7);
+ BANANOS_MAP_BUTTON(dpright, 5);
+
+ BANANOS_MAP_AXIS(leftx, 0);
+ BANANOS_MAP_AXIS(lefty, 1);
+ BANANOS_MAP_AXIS(rightx, 2);
+ BANANOS_MAP_AXIS(righty, 3);
+
+ // TODO: these should probably be axis
+ BANANOS_MAP_BUTTON(lefttrigger, 8);
+ BANANOS_MAP_BUTTON(righttrigger, 9);
+
+#undef BANANOS_MAP_BUTTON
+#undef BANANOS_MAP_AXIS
+
+ return SDL_TRUE;
+}
+
+static Uint32 BANANOS_JoystickGetCapabilities(SDL_Joystick* joystick)
+{
+ (void)joystick;
+ return 0;
+}
+
+static int BANANOS_JoystickSetLED(SDL_Joystick* joystick, Uint8 red, Uint8 green, Uint8 blue)
+{
+ (void)joystick;
+ (void)red;
+ (void)green;
+ (void)blue;
+ return SDL_Unsupported();
+}
+
+static int BANANOS_JoystickSendEffect(SDL_Joystick* joystick, const void* data, int size)
+{
+ (void)joystick;
+ (void)data;
+ (void)size;
+ return SDL_Unsupported();
+}
+
+static int BANANOS_JoystickSetSensorsEnabled(SDL_Joystick* joystick, SDL_bool enabled)
+{
+ (void)joystick;
+ (void)enabled;
+ return SDL_Unsupported();
+}
+
+SDL_JoystickDriver SDL_BANANOS_JoystickDriver =
+{
+ BANANOS_JoystickInit,
+ BANANOS_JoystickGetCount,
+ BANANOS_JoystickDetect,
+ BANANOS_JoystickGetDeviceName,
+ BANANOS_JoystickGetDevicePath,
+ BANANOS_JoystickGetDeviceSteamVirtualGamepadSlot,
+ BANANOS_JoystickGetDevicePlayerIndex,
+ BANANOS_JoystickSetDevicePlayerIndex,
+ BANANOS_JoystickGetDeviceGUID,
+ BANANOS_JoystickGetDeviceInstanceID,
+ BANANOS_JoystickOpen,
+ BANANOS_JoystickRumble,
+ BANANOS_JoystickRumbleTriggers,
+ BANANOS_JoystickGetCapabilities,
+ BANANOS_JoystickSetLED,
+ BANANOS_JoystickSendEffect,
+ BANANOS_JoystickSetSensorsEnabled,
+ BANANOS_JoystickUpdate,
+ BANANOS_JoystickClose,
+ BANANOS_JoystickQuit,
+ BANANOS_JoystickGetGamepadMapping
+};
+
+} // extern "C"
+
+#endif /* SDL_JOYSTICK_BANANOS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/joystick/SDL_joystick.c SDL2-2.32.8-banan_os/src/joystick/SDL_joystick.c
--- SDL2-2.32.8/src/joystick/SDL_joystick.c 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/joystick/SDL_joystick.c 2026-01-03 19:52:38.740921854 +0200
@@ -85,6 +85,9 @@
#ifdef SDL_JOYSTICK_HAIKU
&SDL_HAIKU_JoystickDriver,
#endif
+#ifdef SDL_JOYSTICK_BANANOS
+ &SDL_BANANOS_JoystickDriver,
+#endif
#ifdef SDL_JOYSTICK_USBHID /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */
&SDL_BSD_JoystickDriver,
#endif
diff -ruN SDL2-2.32.8/src/joystick/SDL_sysjoystick.h SDL2-2.32.8-banan_os/src/joystick/SDL_sysjoystick.h
--- SDL2-2.32.8/src/joystick/SDL_sysjoystick.h 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/joystick/SDL_sysjoystick.h 2026-01-03 19:52:50.906765671 +0200
@@ -235,6 +235,7 @@
/* The available joystick drivers */
extern SDL_JoystickDriver SDL_ANDROID_JoystickDriver;
+extern SDL_JoystickDriver SDL_BANANOS_JoystickDriver;
extern SDL_JoystickDriver SDL_BSD_JoystickDriver;
extern SDL_JoystickDriver SDL_DARWIN_JoystickDriver;
extern SDL_JoystickDriver SDL_DUMMY_JoystickDriver;
diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp
--- SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200 --- SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2026-01-03 19:50:45.780251300 +0200 +++ SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2025-11-22 00:45:00.926117334 +0200
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -725,7 +374,7 @@ diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/
+ +
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp 1970-01-01 02:00:00.000000000 +0200 --- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp 2026-01-03 19:50:45.780447206 +0200 +++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp 2025-11-22 01:10:01.840984523 +0200
@@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -780,7 +429,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp SDL2-2.32.8-
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h 1970-01-01 02:00:00.000000000 +0200 --- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h 2026-01-03 19:50:45.780567334 +0200 +++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h 2025-11-22 01:10:16.932880273 +0200
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -827,7 +476,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h SDL2-2.32.8-ba
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200 --- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2026-01-03 19:50:45.780690325 +0200 +++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2025-11-22 00:45:00.926337964 +0200
@@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -891,7 +540,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200 --- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2026-01-03 19:50:45.780815551 +0200 +++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2025-11-22 00:45:00.926434625 +0200
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -940,7 +589,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200 --- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2026-01-03 19:50:45.780934771 +0200 +++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2025-11-22 01:08:26.204647073 +0200
@@ -0,0 +1,729 @@ @@ -0,0 +1,729 @@
+/* +/*
+ Simple DirectMedia Layer + Simple DirectMedia Layer
@ -1673,7 +1322,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+/* vi: set ts=4 sw=4 expandtab: */ +/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h
--- SDL2-2.32.8/src/video/SDL_sysvideo.h 2025-05-20 00:24:41.000000000 +0300 --- SDL2-2.32.8/src/video/SDL_sysvideo.h 2025-05-20 00:24:41.000000000 +0300
+++ SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h 2026-01-03 19:50:45.781358361 +0200 +++ SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h 2025-11-22 00:45:00.927152737 +0200
@@ -462,6 +462,7 @@ @@ -462,6 +462,7 @@
extern VideoBootStrap WINDOWS_bootstrap; extern VideoBootStrap WINDOWS_bootstrap;
extern VideoBootStrap WINRT_bootstrap; extern VideoBootStrap WINRT_bootstrap;
@ -1684,7 +1333,7 @@ diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SD
extern VideoBootStrap Android_bootstrap; extern VideoBootStrap Android_bootstrap;
diff -ruN SDL2-2.32.8/src/video/SDL_video.c SDL2-2.32.8-banan_os/src/video/SDL_video.c diff -ruN SDL2-2.32.8/src/video/SDL_video.c SDL2-2.32.8-banan_os/src/video/SDL_video.c
--- SDL2-2.32.8/src/video/SDL_video.c 2025-05-20 00:24:41.000000000 +0300 --- SDL2-2.32.8/src/video/SDL_video.c 2025-05-20 00:24:41.000000000 +0300
+++ SDL2-2.32.8-banan_os/src/video/SDL_video.c 2026-01-03 19:50:45.782037083 +0200 +++ SDL2-2.32.8-banan_os/src/video/SDL_video.c 2025-11-22 00:45:00.928264617 +0200
@@ -96,6 +96,9 @@ @@ -96,6 +96,9 @@
#ifdef SDL_VIDEO_DRIVER_HAIKU #ifdef SDL_VIDEO_DRIVER_HAIKU
&HAIKU_bootstrap, &HAIKU_bootstrap,

View File

@ -1,8 +1,8 @@
#!/bin/bash ../install.sh #!/bin/bash ../install.sh
NAME='ca-certificates' NAME='ca-certificates'
VERSION='2025-12-02' VERSION='2024-07-02'
DOWNLOAD_URL="https://curl.se/ca/cacert-$VERSION.pem#f1407d974c5ed87d544bd931a278232e13925177e239fca370619aba63c757b4" DOWNLOAD_URL="https://curl.se/ca/cacert-$VERSION.pem#1bf458412568e134a4514f5e170a328d11091e071c7110955c9884ed87972ac9"
configure() { configure() {
: :

View File

@ -1,8 +1,8 @@
#!/bin/bash ../install.sh #!/bin/bash ../install.sh
NAME='curl' NAME='curl'
VERSION='8.17.0' VERSION='8.11.1'
DOWNLOAD_URL="https://curl.se/download/curl-$VERSION.tar.xz#955f6e729ad6b3566260e8fef68620e76ba3c31acf0a18524416a185acf77992" DOWNLOAD_URL="https://curl.se/download/curl-$VERSION.tar.gz#a889ac9dbba3644271bd9d1302b5c22a088893719b72be3487bc3d401e5c4e80"
DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd') DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
CONFIG_SUB=('config.sub') CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
@ -10,7 +10,6 @@ CONFIGURE_OPTIONS=(
'--disable-ipv6' '--disable-ipv6'
'--disable-docs' '--disable-docs'
'--disable-ntlm' '--disable-ntlm'
'--disable-static'
'--enable-optimize' '--enable-optimize'
'--with-openssl' '--with-openssl'
'--with-zlib' '--with-zlib'

View File

@ -1,18 +1,7 @@
diff -ruN curl-8.17.0/configure curl-8.17.0-banan_os/configure diff -ruN curl-8.11.1/configure curl-8.11.1-banan_os/configure
--- curl-8.17.0/configure 2025-11-05 09:00:46.000000000 +0200 --- curl-8.11.1/configure 2024-12-11 09:08:12.000000000 +0200
+++ curl-8.17.0-banan_os/configure 2025-12-31 18:52:05.140006351 +0200 +++ curl-8.11.1-banan_os/configure 2025-01-22 18:29:34.167111729 +0200
@@ -9487,6 +9487,10 @@ @@ -15537,6 +15537,16 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -15245,6 +15249,16 @@
esac esac
;; ;;

View File

@ -1,8 +1,8 @@
#!/bin/bash ../install.sh #!/bin/bash ../install.sh
NAME='git' NAME='git'
VERSION='2.52.0' VERSION='2.48.1'
DOWNLOAD_URL="https://www.kernel.org/pub/software/scm/git/git-$VERSION.tar.xz#3cd8fee86f69a949cb610fee8cd9264e6873d07fa58411f6060b3d62729ed7c5" DOWNLOAD_URL="https://www.kernel.org/pub/software/scm/git/git-$VERSION.tar.gz#51b4d03b1e311ba673591210f94f24a4c5781453e1eb188822e3d9cdc04c2212"
DEPENDENCIES=('zlib' 'openssl' 'curl') DEPENDENCIES=('zlib' 'openssl' 'curl')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'--with-curl' '--with-curl'
@ -11,3 +11,7 @@ CONFIGURE_OPTIONS=(
ac_cv_snprintf_returns_bogus=no ac_cv_snprintf_returns_bogus=no
ac_cv_lib_curl_curl_global_init=yes ac_cv_lib_curl_curl_global_init=yes
) )
build() {
make -j$(nproc) CURL_LDFLAGS='-lcurl -lssl -lcrypto -lz -lzstd' || exit 1
}

View File

@ -19,12 +19,6 @@ int sem_init(sem_t* sem, int pshared, unsigned value)
return 0; return 0;
} }
int sem_getvalue(sem_t* __restrict sem, int* __restrict sval)
{
*sval = BAN::atomic_load(sem->value);
return 0;
}
int sem_post(sem_t* sem) int sem_post(sem_t* sem)
{ {
const auto old = BAN::atomic_fetch_add(sem->value, 1); const auto old = BAN::atomic_fetch_add(sem->value, 1);

View File

@ -1,28 +0,0 @@
#pragma once
#include <stdint.h>
namespace LibInput
{
// TODO: not used but here if we ever make controller
// support generating events instead of being polled
struct JoystickEvent
{
};
struct JoystickState
{
struct Axis
{
int64_t value;
int64_t min;
int64_t max;
};
Axis axis[4];
bool buttons[32];
};
}

View File

@ -632,9 +632,9 @@ Rectangle Terminal::handle_csi(char ch)
return {}; return {};
} }
if (ch == '?' || ch == '>' || ch == '=') if (ch == '?')
{ {
m_csi_info.param = ch; m_csi_info.question = true;
return {}; return {};
} }
@ -651,12 +651,8 @@ Rectangle Terminal::handle_csi(char ch)
Rectangle should_invalidate; Rectangle should_invalidate;
auto& texture = m_window->texture(); auto& texture = m_window->texture();
switch (ch)
switch (m_csi_info.param)
{ {
case 0:
switch (ch)
{
case 'A': case 'A':
if (m_csi_info.fields[0] == -1) if (m_csi_info.fields[0] == -1)
m_csi_info.fields[0] = 1; m_csi_info.fields[0] = 1;
@ -677,18 +673,6 @@ Rectangle Terminal::handle_csi(char ch)
m_csi_info.fields[0] = 1; m_csi_info.fields[0] = 1;
m_cursor.x = BAN::Math::max<int32_t>(m_cursor.x - m_csi_info.fields[0], 0); m_cursor.x = BAN::Math::max<int32_t>(m_cursor.x - m_csi_info.fields[0], 0);
break; break;
case 'E':
if (m_csi_info.fields[0] == -1)
m_csi_info.fields[0] = 1;
m_cursor.y = BAN::Math::min<int32_t>(m_cursor.y + m_csi_info.fields[0], rows() - 1);
m_cursor.x = 0;
break;
case 'F':
if (m_csi_info.fields[0] == -1)
m_csi_info.fields[0] = 1;
m_cursor.y = BAN::Math::max<int32_t>(m_cursor.y - m_csi_info.fields[0], 0);
m_cursor.x = 0;
break;
case 'G': case 'G':
m_cursor.x = BAN::Math::clamp<int32_t>(m_csi_info.fields[0], 1, cols()) - 1; m_cursor.x = BAN::Math::clamp<int32_t>(m_csi_info.fields[0], 1, cols()) - 1;
break; break;
@ -923,9 +907,6 @@ Rectangle Terminal::handle_csi(char ch)
for (int32_t i = 0; i < m_csi_info.fields[0]; i++) for (int32_t i = 0; i < m_csi_info.fields[0]; i++)
should_invalidate = should_invalidate.get_bounding_box(putcodepoint(m_last_graphic_char)); should_invalidate = should_invalidate.get_bounding_box(putcodepoint(m_last_graphic_char));
break; break;
case 'c':
write(m_shell_info.pts_master, "\e[?1;0c", 7);
break;
case 'd': case 'd':
m_cursor.y = BAN::Math::clamp<int32_t>(m_csi_info.fields[0], 1, rows()) - 1; m_cursor.y = BAN::Math::clamp<int32_t>(m_csi_info.fields[0], 1, rows()) - 1;
break; break;
@ -934,7 +915,7 @@ Rectangle Terminal::handle_csi(char ch)
{ {
if (m_csi_info.fields[1] != 5 && m_csi_info.fields[1] != 2) if (m_csi_info.fields[1] != 5 && m_csi_info.fields[1] != 2)
{ {
dprintln("TODO: SGR {}", m_csi_info.fields[1]); dprintln("unsupported ANSI SGR {}", m_csi_info.fields[1]);
break; break;
} }
const auto color = (m_csi_info.fields[1] == 5) const auto color = (m_csi_info.fields[1] == 5)
@ -953,10 +934,33 @@ Rectangle Terminal::handle_csi(char ch)
case 'u': case 'u':
m_cursor = m_saved_cursor; m_cursor = m_saved_cursor;
break; break;
case 'h':
case 'l':
if (m_csi_info.question)
{
switch (m_csi_info.fields[0])
{
case 25:
m_cursor_shown = (ch == 'h');
break;
case 2004:
m_brackted_paste_mode = (ch == 'h');
break;
default:
dwarnln("unsupported ANSI CSI ? {} {}", m_csi_info.fields[0], ch);
break;
}
}
else
{
dwarnln("unsupported ANSI CSI {} {}", m_csi_info.fields[0], ch);
break;
}
break;
case 'n': case 'n':
if (m_csi_info.fields[0] != 6) if (m_csi_info.fields[0] != 6)
{ {
dprintln("TODO: CSI {} n", m_csi_info.fields[0]); dprintln("unsupported ANSI CSI n");
break; break;
} }
char buffer[2 + 10 + 1 + 10 + 2]; char buffer[2 + 10 + 1 + 10 + 2];
@ -966,53 +970,6 @@ Rectangle Terminal::handle_csi(char ch)
default: default:
dprintln("TODO: CSI {}", ch); dprintln("TODO: CSI {}", ch);
break; break;
}
break;
case '?':
switch (ch)
{
case 'h':
case 'l':
switch (m_csi_info.fields[0])
{
case 25:
m_cursor_shown = (ch == 'h');
break;
case 2004:
m_brackted_paste_mode = (ch == 'h');
break;
default:
dprintln("TODO: CSI ? {} {}", m_csi_info.fields[0], ch);
break;
}
break;
default:
dprintln("TODO: CSI ? {}", ch);
break;
}
break;
case '>':
switch (ch)
{
case 'c':
write(m_shell_info.pts_master, "\e[>0;10;1c", 10);
break;
default:
dprintln("TODO: CSI > {}", ch);
break;
}
break;
case '=':
switch (ch)
{
case 'c':
write(m_shell_info.pts_master, "\eP!|00000000\e\\", 14);
break;
default:
dprintln("TODO: CSI = {}", ch);
break;
}
break;
} }
m_state = State::Normal; m_state = State::Normal;
@ -1174,7 +1131,7 @@ Rectangle Terminal::putchar(uint8_t ch)
m_csi_info = { m_csi_info = {
.fields = { -1, -1, -1, -1, -1 }, .fields = { -1, -1, -1, -1, -1 },
.index = 0, .index = 0,
.param = '\0', .question = false,
}; };
return {}; return {};
} }

View File

@ -79,7 +79,7 @@ private:
static constexpr size_t max_fields = 5; static constexpr size_t max_fields = 5;
int32_t fields[max_fields]; int32_t fields[max_fields];
size_t index; size_t index;
char param; bool question;
}; };
struct Cell struct Cell

View File

@ -1,50 +1,20 @@
#include <BAN/String.h> #include <BAN/String.h>
#include <dirent.h> #include <dirent.h>
#include <getopt.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
bool prompt_removal(const char* path, struct stat st) bool delete_recursive(const char* path)
{
const char* type = "file";
if (S_ISREG(st.st_mode))
type = st.st_size ? "regular file" : "regular empty file";
else if (S_ISDIR(st.st_mode))
type = "directory";
else if (S_ISCHR(st.st_mode))
type = "character special file";
else if (S_ISBLK(st.st_mode))
type = "block special file";
else if (S_ISLNK(st.st_mode))
type = "symbolic link";
else if (S_ISFIFO(st.st_mode))
type = "fifo";
fprintf(stderr, "remove %s '%s'? ", type, path);
char buffer[128];
if (fgets(buffer, sizeof(buffer), stdin) == nullptr)
return false;
return buffer[0] == 'Y' || buffer[0] == 'y';
}
bool delete_recursive(const char* path, bool force, bool interactive)
{ {
struct stat st; struct stat st;
if (stat(path, &st) == -1) if (stat(path, &st) == -1)
{ {
if (force && errno == ENOENT)
return true;
perror(path); perror(path);
return false; return false;
} }
if (interactive && !prompt_removal(path, st))
return true;
bool ret = true; bool ret = true;
if (S_ISDIR(st.st_mode)) if (S_ISDIR(st.st_mode))
@ -62,13 +32,11 @@ bool delete_recursive(const char* path, bool force, bool interactive)
if (dirent->d_type == DT_DIR) if (dirent->d_type == DT_DIR)
{ {
if (!delete_recursive(dirent_path.data(), force, interactive)) if (!delete_recursive(dirent_path.data()))
ret = false; ret = false;
} }
else else
{ {
if (interactive && !prompt_removal(dirent_path.data(), st))
continue;
if (unlink(dirent_path.data()) == -1) if (unlink(dirent_path.data()) == -1)
{ {
perror(dirent_path.data()); perror(dirent_path.data());
@ -89,97 +57,75 @@ bool delete_recursive(const char* path, bool force, bool interactive)
return ret; return ret;
} }
void usage(const char* argv0, int ret)
{
FILE* out = (ret == 0) ? stdout : stderr;
fprintf(out, "usage: %s [OPTIONS]... FILE...\n", argv0);
fprintf(out, " remove each FILE\n");
fprintf(out, "OPTIONS:\n");
fprintf(out, " -r remove directories and their contents recursively\n");
fprintf(out, " -h, --help show this message and exit\n");
exit(ret);
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
bool force = false;
bool interactive = false;
bool recursive = false; bool recursive = false;
for (;;) int i = 1;
for (; i < argc; i++)
{ {
static option long_options[] { if (argv[i][0] != '-')
{ "recursive", no_argument, nullptr, 'r' },
{ "interactive", no_argument, nullptr, 'i' },
{ "force", no_argument, nullptr, 'f' },
{ "help", no_argument, nullptr, 'h' },
};
int ch = getopt_long(argc, argv, "rRifh", long_options, nullptr);
if (ch == -1)
break; break;
switch (ch) if (strcmp(argv[i], "-r") == 0)
recursive = true;
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
usage(argv[0], 0);
else
{ {
case 'h': fprintf(stderr, "unrecognized argument %s. use --help for more information\n", argv[i]);
fprintf(stderr, "usage: %s [OPTIONS]... FILE...\n", argv[0]); return 1;
fprintf(stderr, " remove each FILE\n");
fprintf(stderr, "OPTIONS:\n");
fprintf(stderr, " -r, -R, --recursive remove directories and their contents recursively\n");
fprintf(stderr, " -i, --interactive prompt removal for all files\n");
fprintf(stderr, " -f, --force ignore nonexistent files and never prompt\n");
fprintf(stderr, " -h, --help show this message and exit\n");
return 0;
case 'r': case 'R':
recursive = true;
break;
case 'f':
force = true;
interactive = false;
break;
case 'i':
force = false;
interactive = true;
break;
case '?':
fprintf(stderr, "invalid option %c\n", optopt);
fprintf(stderr, "see '%s --help' for usage\n", argv[0]);
return 1;
} }
} }
if (optind >= argc && !force) if (i >= argc)
{ {
fprintf(stderr, "missing operand. use --help for more information\n"); fprintf(stderr, "missing operand. use --help for more information\n");
return 1; return 1;
} }
int ret = 0; int ret = 0;
for (int i = optind; i < argc; i++) for (; i < argc; i++)
{ {
if (recursive) if (recursive)
{ {
if (!delete_recursive(argv[i], force, interactive)) if (!delete_recursive(argv[i]))
ret = 1; ret = 1;
continue;
} }
else
struct stat st;
if (stat(argv[i], &st) == -1)
{ {
if (force && errno == ENOENT) struct stat st;
if (stat(argv[i], &st) == -1)
{
perror(argv[i]);
ret = 1;
continue; continue;
perror(argv[i]); }
ret = 1;
continue;
}
if (interactive && !prompt_removal(argv[i], st)) if (S_ISDIR(st.st_mode))
continue; {
fprintf(stderr, "%s: %s\n", argv[i], strerror(EISDIR));
ret = 1;
continue;
}
if (S_ISDIR(st.st_mode)) if (unlink(argv[i]) == -1)
{ {
errno = EISDIR; perror(argv[i]);
perror(argv[i]); ret = 1;
ret = 1; }
continue;
}
if (unlink(argv[i]) == -1)
{
perror(argv[i]);
ret = 1;
} }
} }
return ret; return ret;
} }

View File

@ -2,7 +2,6 @@ set(USERSPACE_TESTS
test-fork test-fork
test-framebuffer test-framebuffer
test-globals test-globals
test-joystick
test-mmap-shared test-mmap-shared
test-mouse test-mouse
test-popen test-popen

View File

@ -1,10 +0,0 @@
set(SOURCES
main.cpp
)
add_executable(test-joystick ${SOURCES})
banan_include_headers(test-joystick ban)
banan_include_headers(test-joystick libinput)
banan_link_library(test-joystick libc)
install(TARGETS test-joystick OPTIONAL)

View File

@ -1,184 +0,0 @@
#include <BAN/Math.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/framebuffer.h>
#include <sys/mman.h>
#include <termios.h>
#include <LibInput/Joystick.h>
framebuffer_info_t fb_info;
void* fb_mmap = nullptr;
int joystick_fd = -1;
termios original_termios {};
void draw_circle(int cx, int cy, int r, uint32_t color)
{
int min_x = BAN::Math::max<int>(cx - r, 0);
int max_x = BAN::Math::min<int>(cx + r + 1, fb_info.width);
int min_y = BAN::Math::max<int>(cy - r, 0);
int max_y = BAN::Math::min<int>(cy + r + 1, fb_info.height);
for (int y = min_y; y < max_y; y++)
{
for (int x = min_x; x < max_x; x++)
{
int dx = x - cx;
int dy = y - cy;
if (dx * dx + dy * dy > r * r)
continue;
static_cast<uint32_t*>(fb_mmap)[y * fb_info.width + x] = color;
}
}
}
void cleanup()
{
if (fb_mmap)
munmap(fb_mmap, fb_info.height * fb_info.width * (BANAN_FB_BPP / 8));
if (joystick_fd != -1)
close(joystick_fd);
if (original_termios.c_lflag & ECHO)
tcsetattr(STDIN_FILENO, TCSANOW, &original_termios);
}
int map_joystick(const LibInput::JoystickState::Axis& axis, float min, float max)
{
if (axis.min == axis.max)
return (min + max) / 2;
return (axis.value - axis.min) * (max - min) / (axis.max - axis.min) + min;
}
int main(int argc, char** argv)
{
const char* fb_path = "/dev/fb0";
const char* joystick_path = "/dev/joystick0";
if (argc == 1)
;
else if (argc == 3)
{
fb_path = argv[1];
joystick_path = argv[2];
}
else
{
fprintf(stderr, "usage: %s [FB_PATH JOYSTICK_PATH]", argv[0]);
return 1;
}
signal(SIGINT, [](int) { exit(0); });
if (atexit(cleanup) == -1)
{
perror("atexit");
return 1;
}
if (BANAN_FB_BPP != 32)
{
fprintf(stderr, "unsupported bpp\n");
return 1;
}
int fb_fd = open(fb_path, O_RDWR);
if (fb_fd == -1)
{
fprintf(stderr, "open: ");
perror(fb_path);
return 1;
}
if (pread(fb_fd, &fb_info, sizeof(fb_info), -1) == -1)
{
fprintf(stderr, "read: ");
perror(fb_path);
return 1;
}
size_t fb_bytes = fb_info.width * fb_info.height * (BANAN_FB_BPP / 8);
fb_mmap = mmap(nullptr, fb_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
close(fb_fd);
if (fb_mmap == MAP_FAILED)
{
fprintf(stderr, "mmap: ");
perror(fb_path);
return 1;
}
joystick_fd = open(joystick_path, O_RDONLY);
if (joystick_fd == -1)
{
fprintf(stderr, "open: ");
perror(joystick_path);
return 1;
}
if (tcgetattr(STDIN_FILENO, &original_termios) == -1)
{
perror("tcgetattr");
return 1;
}
termios termios = original_termios;
termios.c_lflag &= ~ECHO;
if (tcsetattr(STDIN_FILENO, TCSANOW, &termios) == -1)
{
perror("tcsetattr");
return 1;
}
uint32_t color = 0xFF0000;
int circle_x = fb_info.width / 2;
int circle_y = fb_info.height / 2;
int radius = 10;
// clear screen and render
memset(fb_mmap, 0x00, fb_bytes);
draw_circle(circle_x, circle_y, radius, color);
msync(fb_mmap, fb_bytes, MS_SYNC);
while (true)
{
LibInput::JoystickState state {};
if (read(joystick_fd, &state, sizeof(state)) == -1)
{
fprintf(stderr, "read: ");
perror(joystick_path);
return 1;
}
const int dx = map_joystick(state.axis[0], -50, 50);
const int dy = map_joystick(state.axis[1], -50, 50);
const int dr = map_joystick(state.axis[3], 5, -5);
draw_circle(circle_x, circle_y, radius, 0x000000);
if (BAN::Math::abs(dx) >= 10)
circle_x = BAN::Math::clamp<int>(circle_x + dx, 0, fb_info.width);
if (BAN::Math::abs(dy) >= 10)
circle_y = BAN::Math::clamp<int>(circle_y + dy, 0, fb_info.height);
radius = BAN::Math::clamp<int>(radius + dr, 1, 100);
if (state.buttons[12])
color = 0xFF0000;
if (state.buttons[13])
color = 0x00FF00;
if (state.buttons[14])
color = 0x0000FF;
if (state.buttons[15])
color = 0xFFFFFF;
draw_circle(circle_x, circle_y, radius, color);
msync(fb_mmap, fb_bytes, MS_SYNC);
usleep(16666);
msync(fb_mmap, fb_bytes, MS_SYNC);
}
}