From 5400ef419aa40eafb8cb3a0375c2f696097f7ca3 Mon Sep 17 00:00:00 2001 From: Zachary Date: Sun, 27 Oct 2024 20:23:14 -0700 Subject: [PATCH] Temporarily added partial posix libraris from Odin because posix support for Linux isn't done in Odin yet --- libusb.odin | 34 +++------------ posix/poll.odin | 98 +++++++++++++++++++++++++++++++++++++++++++ posix/posix.odin | 72 +++++++++++++++++++++++++++++++ posix/sys_select.odin | 35 ++++++++++++++++ 4 files changed, 211 insertions(+), 28 deletions(-) create mode 100644 posix/poll.odin create mode 100644 posix/posix.odin create mode 100644 posix/sys_select.odin diff --git a/libusb.odin b/libusb.odin index af336eb..9a1bf5e 100644 --- a/libusb.odin +++ b/libusb.odin @@ -2,7 +2,8 @@ package libusb import "core:c" import "core:fmt" -import "core:sys/posix" +//TODO: Switch to sys/posix when linux support is finished +import "posix" //TODO: Probably want to switch this to being statically linked foreign import lib "system:usb-1.0" @@ -1076,7 +1077,7 @@ HOTPLUG_NO_FLAGS :: 0 * Wildcard matching for hotplug events */ HOTPLUG_MATCH_ANY :: -1 -Hotplug_Callback :: #type proc "c" ( +Hotplug_Callback_Fn :: #type proc "c" ( ctx: Context, device: ^Device, event: Hotplug_Event, @@ -1092,32 +1093,9 @@ Transfer_Type :: enum c.int { STREAM = 4, } -/** \ingroup libusb_asyncio - * Transfer status codes */ -Transfer_Status :: enum c.int { - /** Transfer completed without error. Note that this does not indicate - * that the entire amount of requested data was transferred. */ - COMPLETED, - /** Transfer failed */ - ERROR, - /** Transfer timed out */ - TIMED_OUT, - /** Transfer was cancelled */ - CANCELLED, - /** For bulk/interrupt endpoints: halt condition detected (endpoint - * stalled). For control endpoints: control request not supported. */ - STALL, - /** Device was disconnected */ - NO_DEVICE, - /** Device sent more data than requested */ - OVERFLOW, - /* NB! Remember to update libusb_error_name() - when adding new status codes here. */ -} - Poll_Fd :: struct { /** Numeric file descriptor */ - fd: posix.FD, + fd: c.int, /** Event flags to poll for from . POLLIN indicates that you * should monitor this file descriptor for becoming ready to read from, * and POLLOUT indicates that you should monitor this file descriptor for @@ -1125,9 +1103,9 @@ Poll_Fd :: struct { events: posix.Poll_Event, } -Poll_FD_Added_CB :: #type proc "c" (fd: posix.FD, events: posix.Poll_Event, user_date: rawptr) +Poll_FD_Added_CB :: #type proc "c" (fd: c.int, events: posix.Poll_Event, user_date: rawptr) -Poll_FD_Removed_CB :: #type proc "c" (fd: posix.FD, user_data: rawptr) +Poll_FD_Removed_CB :: #type proc "c" (fd: c.int, user_data: rawptr) @(default_calling_convention = "c", link_prefix = "libusb_") foreign lib { diff --git a/posix/poll.odin b/posix/poll.odin new file mode 100644 index 0000000..9e38afe --- /dev/null +++ b/posix/poll.odin @@ -0,0 +1,98 @@ +package posix + +import "base:intrinsics" + +import "core:c" + +when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +// poll.h - definitions for the poll() function + +foreign lib { + /* + For each pointer in fds, poll() shall examine the given descriptor for the events. + poll will identify on which descriptors writes or reads can be done. + + Returns: -1 (setting errno) on failure, 0 on timeout, the amount of fds that have been changed on success. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html ]] + */ + poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> c.int --- +} + +nfds_t :: c.uint + +Poll_Event_Bits :: enum c.short { + // Data other than high-priority data may be read without blocking. + IN = log2(POLLIN), + // Normal data may be read without blocking. + RDNORM = log2(POLLRDNORM), + // Priority data may be read without blocking. + RDBAND = log2(POLLRDBAND), + // High priority data may be read without blocking. + PRI = log2(POLLPRI), + + // Normal data may be written without blocking. + OUT = log2(POLLOUT), + // Equivalent to POLLOUT. + WRNORM = log2(POLLWRNORM), + // Priority data may be written. + WRBAND = log2(POLLWRBAND), + + // An error has occurred (revents only). + ERR = log2(POLLERR), + // Device hsa been disconnected (revents only). + HUP = log2(POLLHUP), + // Invalid fd member (revents only). + NVAL = log2(POLLNVAL), +} +Poll_Event :: bit_set[Poll_Event_Bits; c.short] + +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { + + pollfd :: struct { + fd: FD, /* [PSX] the following descriptor being polled */ + events: Poll_Event, /* [PSX] the input event flags */ + revents: Poll_Event, /* [PSX] the output event flags */ + } + + POLLIN :: 0x0001 + POLLRDNORM :: 0x0040 + POLLRDBAND :: 0x0080 + POLLPRI :: 0x0002 + POLLOUT :: 0x0004 + POLLWRNORM :: POLLOUT + POLLWRBAND :: 0x0100 + + POLLERR :: 0x0008 + POLLHUP :: 0x0010 + POLLNVAL :: 0x0020 + +} else when ODIN_OS == .Linux { + + pollfd :: struct { + fd: FD, /* [PSX] the following descriptor being polled */ + events: Poll_Event, /* [PSX] the input event flags */ + revents: Poll_Event, /* [PSX] the output event flags */ + } + + POLLIN :: 0x0001 + POLLRDNORM :: 0x0040 + POLLRDBAND :: 0x0080 + POLLPRI :: 0x0002 + POLLOUT :: 0x0004 + POLLWRNORM :: 0x0100 + POLLWRBAND :: 0x0200 + + POLLERR :: 0x0008 + POLLHUP :: 0x0010 + POLLNVAL :: 0x0020 + +} else { + #panic("posix is unimplemented for the current target") +} + diff --git a/posix/posix.odin b/posix/posix.odin new file mode 100644 index 0000000..44486e4 --- /dev/null +++ b/posix/posix.odin @@ -0,0 +1,72 @@ +/* +Raw bindings for most POSIX APIs. + +Targets glibc and musl compatibility. + +APIs that have been left out are due to not being useful, +being fully replaced (and better) by other Odin packages, +or when one of the targets hasn't implemented the API or option. + +The struct fields that are cross-platform are documented with `[PSX]`. +Accessing these fields on one target should be the same on others. +Other fields are implementation specific. + +Most macros have been reimplemented in Odin with inlined functions. + +Unimplemented headers: +- aio.h +- complex.h | See `core:c/libc` and our own complex types +- cpio.h +- ctype.h | See `core:c/libc` for most of it +- ndbm.h +- fenv.h +- float.h +- fmtmsg.h +- ftw.h +- semaphore.h | See `core:sync` +- inttypes.h | See `core:c` +- iso646.h | Impossible +- math.h | See `core:c/libc` +- mqueue.h | Targets don't seem to have implemented it +- regex.h | See `core:regex` +- search.h | Not useful in Odin +- spawn.h | Use `fork`, `execve`, etc. +- stdarg.h | See `core:c/libc` +- stdint.h | See `core:c` +- stropts.h +- syslog.h +- pthread.h | Only the actual threads API is bound, see `core:sync` for synchronization primitives +- string.h | Most of this is not useful in Odin, only a select few symbols are bound +- tar.h +- tgmath.h +- trace.h +- wchar.h +- wctype.h + +*/ +package posix + +import "base:intrinsics" + +import "core:c" + +result :: enum c.int { + // Use `errno` and `strerror` for more information. + FAIL = -1, + // Operation succeeded. + OK = 0, +} + +FD :: distinct c.int + +@(private) +log2 :: intrinsics.constant_log2 + +when ODIN_OS == .Darwin && ODIN_ARCH == .amd64 { + @(private) + INODE_SUFFIX :: "$INODE64" +} else { + @(private) + INODE_SUFFIX :: "" +} + diff --git a/posix/sys_select.odin b/posix/sys_select.odin new file mode 100644 index 0000000..eba3490 --- /dev/null +++ b/posix/sys_select.odin @@ -0,0 +1,35 @@ +package posix + +import "base:intrinsics" + +import "core:c" +import "core:c/libc" + +when ODIN_OS == .Darwin { + foreign import lib "system:System.framework" +} else { + foreign import lib "system:c" +} + +// sys/select.h - select types + +when ODIN_OS == .NetBSD { + LPSELECT :: "__pselect50" + LSELECT :: "__select50" +} else { + LPSELECT :: "pselect" + LSELECT :: "select" +} + +when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { + + suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD else c.long) + + timeval :: struct { + tv_sec: libc.time_t, /* [PSX] seconds */ + tv_usec: suseconds_t, /* [PSX] microseconds */ + } + +} else { + #panic("posix is unimplemented for the current target") +}