Compare commits
No commits in common. "4b5a8196c37502110f09e2f055bab5ea622242e9" and "bd426199f81b470733eac81f0e7d19c050985ef2" have entirely different histories.
4b5a8196c3
...
bd426199f8
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ namespace Kernel
|
||||||
Debug,
|
Debug,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Mouse,
|
Mouse,
|
||||||
Joystick,
|
|
||||||
SCSI,
|
SCSI,
|
||||||
NVMeController,
|
NVMeController,
|
||||||
NVMeNamespace,
|
NVMeNamespace,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
Mouse,
|
Mouse,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
Joystick,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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&);
|
||||||
|
|
@ -60,8 +46,8 @@ namespace Kernel
|
||||||
|
|
||||||
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 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ namespace Kernel
|
||||||
|
|
||||||
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; }
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
const uint32_t indices_per_fs_block = blksize() / sizeof(uint32_t);
|
|
||||||
|
|
||||||
if (depth == 0)
|
|
||||||
{
|
{
|
||||||
if (block == 0)
|
if (block == 0)
|
||||||
{
|
|
||||||
if (!allocate)
|
|
||||||
return BAN::Optional<uint32_t>();
|
return BAN::Optional<uint32_t>();
|
||||||
|
ASSERT(depth >= 1);
|
||||||
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());
|
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());
|
|
||||||
|
|
||||||
bool needs_write = false;
|
|
||||||
|
|
||||||
if (block != 0)
|
|
||||||
TRY(m_fs.read_block(block, block_buffer));
|
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()));
|
const uint32_t indices_per_block = blksize() / sizeof(uint32_t);
|
||||||
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));
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
const uint32_t block_offset = offset % block_size;
|
uint32_t block_offset = offset % block_size;
|
||||||
const uint32_t to_copy = BAN::Math::min<uint32_t>(block_size - block_offset, to_write);
|
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))
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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))
|
if (s_mice.size() < minor(m_rdev))
|
||||||
MUST(s_mice.resize(minor(m_rdev)));
|
MUST(s_mice.resize(minor(m_rdev)));
|
||||||
s_mice[minor(m_rdev) - 1] = MUST(get_weak_ptr());
|
s_mice[minor(m_rdev) - 1] = MUST(get_weak_ptr());
|
||||||
break;
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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, [¤t, byte] {
|
PageTable::with_fast_page(m_paddr + page_index * PAGE_SIZE, [¤t, 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);
|
||||||
|
|
|
||||||
|
|
@ -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 port = 0xC000; port < 0xFFFF; port++)
|
for (uint32_t temp = 0xC000; temp < 0xFFFF && port == NetworkSocket::PORT_NONE; temp++)
|
||||||
if (!m_bound_sockets.contains(port))
|
if (!m_bound_sockets.contains(temp))
|
||||||
return port;
|
port = temp;
|
||||||
|
if (port == NetworkSocket::PORT_NONE)
|
||||||
|
{
|
||||||
dwarnln("No ports available");
|
dwarnln("No ports available");
|
||||||
return BAN::Error::from_errno(EAGAIN);
|
return BAN::Error::from_errno(EAGAIN);
|
||||||
}
|
}
|
||||||
|
dprintln_if(DEBUG_IPV4, "using port {}", port);
|
||||||
|
|
||||||
BAN::ErrorOr<void> IPv4Layer::bind_socket_with_target(BAN::RefPtr<NetworkSocket> socket, const sockaddr* target, socklen_t target_len)
|
struct sockaddr_in target;
|
||||||
{
|
target.sin_family = AF_INET;
|
||||||
if (!target || target_len < (socklen_t)sizeof(sockaddr_in))
|
target.sin_port = BAN::host_to_network_endian(port);
|
||||||
return BAN::Error::from_errno(EINVAL);
|
target.sin_addr.s_addr = sockaddr_in.sin_addr.s_addr;
|
||||||
if (target->sa_family != AF_INET)
|
return bind_socket_to_address(socket, (sockaddr*)&target, sizeof(sockaddr_in));
|
||||||
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);
|
||||||
TRY([&sockaddr_in]() -> BAN::ErrorOr<void> {
|
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 };
|
const auto ipv4 = BAN::IPv4Address { sockaddr_in.sin_addr.s_addr };
|
||||||
|
|
||||||
if (ipv4 == 0)
|
BAN::RefPtr<NetworkInterface> bind_interface;
|
||||||
return {};
|
for (auto interface : NetworkManager::get().interfaces())
|
||||||
|
|
||||||
const auto& all_interfaces = NetworkManager::get().interfaces();
|
|
||||||
for (const auto& interface : all_interfaces)
|
|
||||||
{
|
{
|
||||||
switch (interface->type())
|
if (interface->type() != NetworkInterface::Type::Loopback)
|
||||||
{
|
bind_interface = interface;
|
||||||
case NetworkInterface::Type::Ethernet:
|
|
||||||
if (ipv4 == interface->get_ipv4_address())
|
|
||||||
return {};
|
|
||||||
break;
|
|
||||||
case NetworkInterface::Type::Loopback:
|
|
||||||
const auto netmask = interface->get_netmask();
|
const auto netmask = interface->get_netmask();
|
||||||
if (ipv4.mask(netmask) == interface->get_ipv4_address().mask(netmask))
|
if (ipv4.mask(netmask) != interface->get_ipv4_address().mask(netmask))
|
||||||
return {};
|
continue;
|
||||||
|
bind_interface = interface;
|
||||||
break;
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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,7 +290,20 @@ 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()
|
void Scheduler::reschedule_if_idle()
|
||||||
|
{
|
||||||
|
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||||
|
if (!m_current && !m_run_queue.empty())
|
||||||
|
Processor::yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scheduler::timer_interrupt()
|
||||||
|
{
|
||||||
|
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||||
|
|
||||||
|
if (Processor::is_smp_enabled())
|
||||||
|
do_load_balancing();
|
||||||
|
|
||||||
{
|
{
|
||||||
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||||
while (!m_block_queue.empty() && current_ns >= m_block_queue.front()->wake_time_ns)
|
while (!m_block_queue.empty() && current_ns >= m_block_queue.front()->wake_time_ns)
|
||||||
|
|
@ -310,29 +320,6 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::reschedule_if_idle()
|
|
||||||
{
|
|
||||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
|
||||||
|
|
||||||
if (m_current != nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_run_queue.empty())
|
|
||||||
wake_up_sleeping_threads();
|
|
||||||
|
|
||||||
if (!m_run_queue.empty())
|
|
||||||
Processor::yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scheduler::timer_interrupt()
|
|
||||||
{
|
|
||||||
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
|
||||||
|
|
||||||
if (Processor::is_smp_enabled())
|
|
||||||
do_load_balancing();
|
|
||||||
|
|
||||||
wake_up_sleeping_threads();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||||
if (current_ns >= m_last_reschedule_ns + s_reschedule_interval_ns)
|
if (current_ns >= m_last_reschedule_ns + s_reschedule_interval_ns)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,91 +21,53 @@ 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 (index >= m_cache.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto& cache = m_cache[index];
|
|
||||||
if (cache.first_sector != page_cache_start)
|
|
||||||
return false;
|
|
||||||
if (!(cache.sector_mask & (1 << page_cache_offset)))
|
if (!(cache.sector_mask & (1 << page_cache_offset)))
|
||||||
return false;
|
continue;
|
||||||
|
|
||||||
PageTable::with_fast_page(cache.paddr, [&] {
|
PageTable::with_fast_page(cache.paddr, [&] {
|
||||||
memcpy(buffer.data(), PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), m_sector_size);
|
memcpy(buffer.data(), PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), m_sector_size);
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
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();
|
|
||||||
if (paddr == 0)
|
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
|
||||||
|
|
||||||
PageCache cache {
|
|
||||||
.paddr = paddr,
|
|
||||||
.first_sector = page_cache_start,
|
|
||||||
.sector_mask = 0,
|
|
||||||
.dirty_mask = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (auto ret = m_cache.insert(index, cache); ret.is_error())
|
|
||||||
{
|
|
||||||
Heap::get().release_page(paddr);
|
|
||||||
return ret.error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& cache = m_cache[index];
|
auto& cache = m_cache[index];
|
||||||
|
|
||||||
|
if (cache.first_sector + sectors_per_page <= page_cache_start)
|
||||||
|
continue;
|
||||||
|
if (cache.first_sector > page_cache_start)
|
||||||
|
break;
|
||||||
|
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
|
@ -118,17 +79,32 @@ namespace Kernel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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, [&] {
|
||||||
|
memcpy(PageTable::fast_page_as_ptr(page_cache_offset * m_sector_size), buffer.data(), m_sector_size);
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
|
||||||
|
|
||||||
PageCache temp_cache;
|
|
||||||
|
|
||||||
{
|
|
||||||
RWLockWRGuard _(m_rw_lock);
|
|
||||||
|
|
||||||
if (index >= m_cache.size())
|
|
||||||
return {};
|
|
||||||
auto& cache = m_cache[index];
|
auto& cache = m_cache[index];
|
||||||
if (cache.dirty_mask == 0)
|
if (cache.dirty_mask == 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
@ -137,35 +113,20 @@ namespace Kernel
|
||||||
memcpy(m_sync_cache.data(), PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
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;
|
||||||
uint8_t sector_count = 0;
|
uint8_t sector_count = 0;
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
:
|
:
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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];
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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,10 +651,6 @@ Rectangle Terminal::handle_csi(char ch)
|
||||||
Rectangle should_invalidate;
|
Rectangle should_invalidate;
|
||||||
|
|
||||||
auto& texture = m_window->texture();
|
auto& texture = m_window->texture();
|
||||||
|
|
||||||
switch (m_csi_info.param)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
case 'A':
|
case 'A':
|
||||||
|
|
@ -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,26 +934,10 @@ Rectangle Terminal::handle_csi(char ch)
|
||||||
case 'u':
|
case 'u':
|
||||||
m_cursor = m_saved_cursor;
|
m_cursor = m_saved_cursor;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
|
||||||
if (m_csi_info.fields[0] != 6)
|
|
||||||
{
|
|
||||||
dprintln("TODO: CSI {} n", m_csi_info.fields[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
char buffer[2 + 10 + 1 + 10 + 2];
|
|
||||||
sprintf(buffer, "\e[%u;%uR", m_cursor.y + 1, m_cursor.x + 1);
|
|
||||||
write(m_shell_info.pts_master, buffer, strlen(buffer));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dprintln("TODO: CSI {}", ch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '?':
|
|
||||||
switch (ch)
|
|
||||||
{
|
|
||||||
case 'h':
|
case 'h':
|
||||||
case 'l':
|
case 'l':
|
||||||
|
if (m_csi_info.question)
|
||||||
|
{
|
||||||
switch (m_csi_info.fields[0])
|
switch (m_csi_info.fields[0])
|
||||||
{
|
{
|
||||||
case 25:
|
case 25:
|
||||||
|
|
@ -982,36 +947,28 @@ Rectangle Terminal::handle_csi(char ch)
|
||||||
m_brackted_paste_mode = (ch == 'h');
|
m_brackted_paste_mode = (ch == 'h');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dprintln("TODO: CSI ? {} {}", m_csi_info.fields[0], ch);
|
dwarnln("unsupported ANSI CSI ? {} {}", m_csi_info.fields[0], ch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dprintln("TODO: CSI ? {}", ch);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
case '>':
|
|
||||||
switch (ch)
|
|
||||||
{
|
{
|
||||||
case 'c':
|
dwarnln("unsupported ANSI CSI {} {}", m_csi_info.fields[0], ch);
|
||||||
write(m_shell_info.pts_master, "\e[>0;10;1c", 10);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dprintln("TODO: CSI > {}", ch);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '=':
|
case 'n':
|
||||||
switch (ch)
|
if (m_csi_info.fields[0] != 6)
|
||||||
{
|
{
|
||||||
case 'c':
|
dprintln("unsupported ANSI CSI n");
|
||||||
write(m_shell_info.pts_master, "\eP!|00000000\e\\", 14);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dprintln("TODO: CSI = {}", ch);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
char buffer[2 + 10 + 1 + 10 + 2];
|
||||||
|
sprintf(buffer, "\e[%u;%uR", m_cursor.y + 1, m_cursor.x + 1);
|
||||||
|
write(m_shell_info.pts_master, buffer, strlen(buffer));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintln("TODO: CSI {}", ch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,87 +57,65 @@ 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)
|
||||||
{
|
|
||||||
case 'h':
|
|
||||||
fprintf(stderr, "usage: %s [OPTIONS]... FILE...\n", argv[0]);
|
|
||||||
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;
|
recursive = true;
|
||||||
break;
|
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
|
||||||
case 'f':
|
usage(argv[0], 0);
|
||||||
force = true;
|
else
|
||||||
interactive = false;
|
{
|
||||||
break;
|
fprintf(stderr, "unrecognized argument %s. use --help for more information\n", argv[i]);
|
||||||
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;
|
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;
|
struct stat st;
|
||||||
if (stat(argv[i], &st) == -1)
|
if (stat(argv[i], &st) == -1)
|
||||||
{
|
{
|
||||||
if (force && errno == ENOENT)
|
|
||||||
continue;
|
|
||||||
perror(argv[i]);
|
perror(argv[i]);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interactive && !prompt_removal(argv[i], st))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (S_ISDIR(st.st_mode))
|
if (S_ISDIR(st.st_mode))
|
||||||
{
|
{
|
||||||
errno = EISDIR;
|
fprintf(stderr, "%s: %s\n", argv[i], strerror(EISDIR));
|
||||||
perror(argv[i]);
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -180,6 +126,6 @@ int main(int argc, char** argv)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue