From 6441afaf9a08c013e9cd6cb711d812b362732cb3 Mon Sep 17 00:00:00 2001 From: "Thomas \"Cakeisalie5\" Touhey" Date: Tue, 7 Feb 2017 17:54:11 +0100 Subject: [PATCH] Modified way streams are managed. --- PORTING.md | 13 ++++-- include/libp7.h | 52 ++------------------- include/libp7/buffer.h | 1 + include/libp7/internals.h | 23 ---------- include/libp7/packetio.h | 2 +- include/libp7/stream.h | 44 +++++++++++++++++- include/libp7/types.h | 77 +++++++++++++++++++++++++++++++ src/core/init.c | 37 ++++++++------- src/stream/libusb.c | 26 ++--------- src/stream/streams.c | 96 ++++++++++++++++++++++++--------------- src/stream/tty.c | 93 ------------------------------------- src/stream/windows.c | 57 +++++++++++------------ 12 files changed, 242 insertions(+), 279 deletions(-) create mode 100644 include/libp7/types.h delete mode 100644 src/stream/tty.c diff --git a/PORTING.md b/PORTING.md index fb017e7..e5957fd 100644 --- a/PORTING.md +++ b/PORTING.md @@ -5,7 +5,7 @@ platform's libc, such as endianness correcting or sleeping, in the internal headers located in `include/libp7/internals/`, and make a custom stream adapted for your platform and prototype it. -Libp7 streams are the libp7 abstraction between it and the calculator device. +libp7 streams are the libp7 abstraction between it and the calculator device. You can check out the current streams in `src/stream/`. Currently supported streams are libc FILEs, Unix-like streams (with file descriptors), Microsoft Windows's libc streams (`HANDLE`s) and libusb streams (which can be disabled @@ -13,10 +13,13 @@ by passing `--no-libusb` to the configure script). Each stream must implement a function to connect to the device using `p7_sinit`, and functions to read and write, and eventually one to set communication settings from cross-platform values defined by libp7. You should really check out `p7_sinit`'s manpage. -A placebo function is advised. + +You should as well make up a constant like `P7_DISABLED_` +(e.g. `P7_DISABLED_LIBUSB`, `P7_DISABLED_STREAMS`, `P7_DISABLED_WINDOWS`), +and define it in `libp7/stream.h` aside with the prototypes of your functions. Once this is done, you will want to hook your stream to one of the libp7 standard initialization functions: `p7_init` or `p7_cominit`. In order to do -this, you should add your initialization function's prototype in -`include/libp7/internals.h` near the others, and add it to one of the functions' -content (see what's already there). +this, you should add it your functions to the content of at least one of these +two functions. Platform-specific things are preferred in your stream's source +file. diff --git a/include/libp7.h b/include/libp7.h index 6d69a7a..64c5bac 100644 --- a/include/libp7.h +++ b/include/libp7.h @@ -9,60 +9,22 @@ /* ************************************************************************** */ #ifndef LIBP7_H # define LIBP7_H -# if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) \ - && !defined(__WINDOWS__) -# define __WINDOWS__ -# endif - # include +# include # include -# include -/* integer types */ -# define PRIuP7SHORT PRIuFAST16 -# define PRIxP7SHORT PRIxFAST16 -typedef uint_fast16_t p7ushort_t; -# define PRIuP7INT PRIuFAST32 -# define PRIxP7INT PRIxFAST32 -typedef uint_fast32_t p7uint_t; - -# include -# include /* PRI*FAST* */ +/* allocate handle in stack */ # ifdef __WINDOWS__ # include # else # include # endif +# define p7_alloca_handle() (alloca(p7_handle_size)) # ifdef __cplusplus extern "C" { # endif -/* ************************************************************************** */ -/* Types */ -/* ************************************************************************** */ -/* handles - from streams, include `libp7/stream.h` */ -struct p7_handle_s; -typedef struct p7_handle_s p7_handle_t; -extern const size_t p7_handle_size; -# define p7_alloca_handle() (alloca(p7_handle_size)) - -/* A version ("xx.xx.xx" + type) */ -typedef struct { - unsigned int major; - unsigned int minor; - unsigned int rev; -} p7_version_t; - -/* CASIOWIN entry */ -typedef struct { - /* version */ - p7_version_t version; - - /* syscall table address */ - p7uint_t syscall_table_offset; -} p7_casiowin_entry_t; - /* ************************************************************************** */ /* libp7 errors */ /* ************************************************************************** */ @@ -130,14 +92,6 @@ int p7_validate_dirname(const char *dirname); int p7_init(p7_handle_t **handle, unsigned int flags); int p7_cominit(p7_handle_t **handle, unsigned int flags, int com); -/* Testing initialization */ -# ifndef P7_DISABLED_FILE -int p7_finit(p7_handle_t **handle, unsigned int flags, - FILE *readstream, FILE *writestream); -# endif -int p7_fdinit(p7_handle_t **handle, unsigned int flags, - const char *name, int readfd, int writefd); - /* De-initialization */ void p7_exit(p7_handle_t *handle); /* ************************************************************************** */ diff --git a/include/libp7/buffer.h b/include/libp7/buffer.h index c4cbcbc..9e720e1 100644 --- a/include/libp7/buffer.h +++ b/include/libp7/buffer.h @@ -9,6 +9,7 @@ /* ************************************************************************** */ #ifndef LIBP7_BUFFER_H # define LIBP7_BUFFER_H +# include /* This file is there so it is possible to use a custom buffer for file * transferring. There are two use cases: diff --git a/include/libp7/internals.h b/include/libp7/internals.h index a6be967..4f60500 100644 --- a/include/libp7/internals.h +++ b/include/libp7/internals.h @@ -16,24 +16,6 @@ # include # define DEFAULT_BAUDRATE P7_B9600 -/* ************************************************************************** */ -/* Macros and platform-specific functions */ -/* ************************************************************************** */ -/* MS-Windows <3 (srsly) */ -# if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) \ - && !defined(__WINDOWS__) -# define __WINDOWS__ -# endif - -/* Some printf types */ -# if defined(_WIN64) -# define PRIuSIZE "l64u" -# elif defined(_WIN32) -# define PRIuSIZE "u" -# else -# define PRIuSIZE "zu" -# endif - /* Macros */ # ifndef min # define min(A, B) ((A) < (B) ? (A) : (B)) @@ -148,11 +130,6 @@ struct p7_handle_s { char _name[10]; }; -/* Sub-initialization functions */ -int p7_libusbinit(p7_handle_t **handle, unsigned int flags); -int p7_winit(p7_handle_t **handle, unsigned int flags, const char *path); -int p7_cinit(p7_handle_t **handle, unsigned int flags, const char *path); - /* sub-sub-init utils */ # ifndef P7_DISABLED_FILE int _p7_finit(p7_handle_t **handle, unsigned int flags, diff --git a/include/libp7/packetio.h b/include/libp7/packetio.h index 854782f..f5c6da3 100644 --- a/include/libp7/packetio.h +++ b/include/libp7/packetio.h @@ -9,7 +9,7 @@ /* ************************************************************************** */ #ifndef LIBP7_PACKETIO_H # define LIBP7_PACKETIO_H -# include +# include # include /* for P7_B* */ # ifdef __cplusplus extern "C" { diff --git a/include/libp7/stream.h b/include/libp7/stream.h index 2e67023..fa2ea3b 100644 --- a/include/libp7/stream.h +++ b/include/libp7/stream.h @@ -9,7 +9,7 @@ /* ************************************************************************** */ #ifndef LIBP7_STREAM_H # define LIBP7_STREAM_H -# include +# include # ifdef __cplusplus extern "C" { # endif @@ -24,7 +24,7 @@ extern "C" { * These functions take the uncasted cookie and the required arguments for * the actions (`timeout` is in milliseconds). They should return the libp7 * error code, or 0 if no error. There is no partial success: you manage to - * send the full buffer, or you do not. + * receive/send the full buffer, or you do not. * * some of the streams managed by default already have buffering, so this * implementation doesn't add another layer of it. @@ -66,6 +66,46 @@ int p7_read(p7_stream_t *stream, void *dest, size_t size, unsigned int timeout); int p7_write(p7_stream_t *stream, const void *data, size_t size); int p7_setcomm(p7_stream_t *stream, int speed, int parity, int stopbits); +/* ************************************************************************** */ +/* Built-in streams */ +/* ************************************************************************** */ +/* FILE stream */ +# ifndef P7_DISABLED_FILE +int p7_finit(p7_handle_t **handle, unsigned int flags, + FILE *readstream, FILE *writestream); +# endif + +/* STREAMS device */ +# if defined(__linux__) +int p7_fdinit(p7_handle_t **handle, unsigned int flags, + const char *name, int readfd, int writefd); +int p7_fdcominit(p7_handle_t **handle, unsigned int flags, int com); +# else +# define P7_DISABLED_STREAMS +# endif + +/* libusb initialization */ +# ifndef P7_DISABLED_LIBUSB +int p7_libusbinit(p7_handle_t **handle, unsigned int flags); +# endif + +/* Microsoft Windows initialization */ +# ifdef __WINDOWS__ +int p7_winit(p7_handle_t **handle, unsigned int flags, const char *path); +int p7_wcominit(p7_handle_t **handle, unsigned int flags, int com); +# else +# define P7_DISABLED_WINDOWS +# endif + +/* Check if there is serial/usb on this platform */ +# if defined(P7_DISABLED_STREAMS) && defined(P7_DISABLED_WINDOWS) +# define P7_NOSERIAL +# endif +# if defined(P7_DISABLED_LIBUSB) && defined(P7_DISABLED_STREAMS) \ + && defined(P7_DISABLED_WINDOWS) +# define P7_NOUSB +# endif + # ifdef __cplusplus } # endif diff --git a/include/libp7/types.h b/include/libp7/types.h new file mode 100644 index 0000000..a46cd97 --- /dev/null +++ b/include/libp7/types.h @@ -0,0 +1,77 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* libp7/types.h |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: libp7 | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/02/07 16:52:51 |___/ */ +/* */ +/* ************************************************************************** */ +#ifndef LIBP7_TYPES_H +# define LIBP7_TYPES_H +# if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) \ + && !defined(__WINDOWS__) +# define __WINDOWS__ +# endif + +/* Main includes */ +# include +# include +# include +# ifdef __cplusplus +extern "C" { +# endif + +/* ************************************************************************** */ +/* Integer types */ +/* ************************************************************************** */ +/* integer types */ +# define PRIuP7SHORT PRIuFAST16 +# define PRIxP7SHORT PRIxFAST16 +typedef uint_fast16_t p7ushort_t; +# define PRIuP7INT PRIuFAST32 +# define PRIxP7INT PRIxFAST32 +typedef uint_fast32_t p7uint_t; + +/* Size_t-related printf format */ +# ifndef PRIuSIZE +# if defined(_WIN64) +# define PRIuSIZE "l64u" +# elif defined(_WIN32) +# define PRIuSIZE "u" +# else +# define PRIuSIZE "zu" +# endif +# endif + +/* ************************************************************************** */ +/* Handles - these are actually private */ +/* ************************************************************************** */ +struct p7_handle_s; +typedef struct p7_handle_s p7_handle_t; +extern const size_t p7_handle_size; + +/* ************************************************************************** */ +/* Other types */ +/* ************************************************************************** */ +/* Version (xx.xx.xxxx) */ +typedef struct { + unsigned int major; + unsigned int minor; + unsigned int rev; +} p7_version_t; + +/* CASIOWIN entry - the OS entry the bootcode reads to run it */ +typedef struct { + /* version */ + p7_version_t version; + + /* syscall table address */ + p7uint_t syscall_table_offset; +} p7_casiowin_entry_t; + +# ifdef __cplusplus +} +# endif +# include +#endif /* LIBP7_TYPES_H */ diff --git a/src/core/init.c b/src/core/init.c index abd059d..34b8297 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -22,6 +22,12 @@ int p7_init(p7_handle_t **handle, unsigned int flags) { +#ifdef P7_NOUSB + (void)handle; + (void)flags; + return (p7_error_nocalc); +#else + int err = p7_error_nocalc; int tries = INIT_TRIES; int failed = 0; @@ -33,23 +39,22 @@ int p7_init(p7_handle_t **handle, unsigned int flags) } /* platform-specific communication methods */ -#if defined(__linux__) - logr_info("Looking for specific Linux drivers"); - err = p7_cinit(handle, flags, NULL); -#elif defined(__WINDOWS__) - logr_info("Looking for specific MS-Windows drivers"); +# if !defined(P7_DISABLED_STREAMS) + err = p7_fdinit(handle, flags, NULL, -1, -1); +# elif !defined(P7_DISABLED_WINDOWS) err = p7_winit(handle, flags, NULL); -#endif - +# endif /* check error */ if (err != p7_error_nocalc) return (err); /* libusb communication methods - more or less platform-independent */ +# if !defined(P7_DISABLED_LIBUSB) logr_info("Looking for general libusb devices"); err = p7_libusbinit(handle, flags); if (err != p7_error_nocalc) return (err); +# endif /* wait a little */ logr_error("didn't find the calculator!"); @@ -58,6 +63,7 @@ int p7_init(p7_handle_t **handle, unsigned int flags) /* no found calc, by the look of it. */ return (p7_error_nocalc); +#endif } /** @@ -72,7 +78,7 @@ int p7_init(p7_handle_t **handle, unsigned int flags) int p7_cominit(p7_handle_t **handle, unsigned int flags, int com) { -#if !defined(__linux__) && !defined(__WINDOWS__) +#ifdef P7_NOSERIAL (void)handle; (void)active; (void)check; @@ -93,17 +99,10 @@ int p7_cominit(p7_handle_t **handle, unsigned int flags, int com) } /* platform-specific communication methods */ -# if defined(__linux__) - logr_info("Looking for specific Linux device"); - char compath[20]; - sprintf(compath, "/dev/ttyUSB%d", com - 1); - err = p7_cinit(handle, flags, compath); -# elif defined(__WINDOWS__) - logr_info("Looking for specific MS-Windows device"); - char compath[20]; - if (com <= 9) sprintf(compath, "COM%d", com); - else sprintf(compath, "\\\\?\\COM%d", com); - err = p7_winit(handle, flags, compath); +# if !defined(P7_DISABLED_STREAMS) + err = p7_fdcominit(handle, flags, com); +# elif !defined(P7_DISABLED_WINDOWS) + err = p7_wcominit(handle, flags, com); # endif /* check error */ diff --git a/src/stream/libusb.c b/src/stream/libusb.c index 10ce0c4..3a1bdcf 100644 --- a/src/stream/libusb.c +++ b/src/stream/libusb.c @@ -8,10 +8,11 @@ /* */ /* ************************************************************************** */ #include -#include -#include #ifndef P7_DISABLED_LIBUSB # include +# include +# include + /* ************************************************************************** */ /* Cookie structure */ /* ************************************************************************** */ @@ -291,25 +292,4 @@ fail: return (err); } -/* ************************************************************************** */ -/* Without libusb: placebos */ -/* ************************************************************************** */ -#else - -/** - * p7_libusbinit: - * Initialize libp7 with USB device [not] using libusb. Placebo. - * - * @arg handle the handle to create. - * @arg flags the flags. - * @return the error code (0 if you're a knoop). - */ - -int p7_libusbinit(p7_handle_t **handle, unsigned int flags) -{ - (void)handle; - (void)flags; - return (p7_error_nocalc); -} - #endif diff --git a/src/stream/streams.c b/src/stream/streams.c index f683b6e..193803f 100644 --- a/src/stream/streams.c +++ b/src/stream/streams.c @@ -8,19 +8,70 @@ /* */ /* ************************************************************************** */ #include -#include +#ifndef P7_DISABLED_STREAMS +# include +# include +# include +# include +# include +# include +# include +# ifdef __linux__ +/* ************************************************************************** */ +/* Serial devices on Linux */ +/* ************************************************************************** */ +/** + * p7_fdcominit: + * Initialize serial communication. + * + * @arg handle the link to the handle. + * @arg flags the flags. + * @arg com the com port. + * @return the error code (0 if ok) + */ + +int p7_fdcominit(p7_handle_t **handle, unsigned int flags, int com) +{ + /* prepare the path */ + logr_info("Looking for specific Linux devices."); + char path[20]; sprintf(path, "/dev/ttyUSB%d", com - 1); + + /* open the stream */ + int fd = open(path, O_RDWR | O_NOCTTY); + if (fd < 0) switch (errno) { + /* no such device */ + case ENODEV: case ENOENT: case ENXIO: + case EPIPE: case ESPIPE: + logr_error("couldn't open calculator"); + return (p7_error_nocalc); + + /* no access */ + case EACCES: + logr_error("permission denied"); + return (p7_error_noaccess); + + /* default */ + default: + logr_error("unknown error: %s (0x%X)", strerror(errno), errno); + return (p7_error_unknown); + } + + /* check if we have got the thing */ + if (fd < 0) switch (errno) { + case ENOENT: return (p7_error_nocalc); + case EACCES: return (p7_error_noaccess); + default: return (p7_error_nocalc); + } + + /* init to real */ + return (p7_fdinit(handle, flags, NULL, fd, fd)); +} + +# endif /* ************************************************************************** */ /* *nix streams device initialization and callbacks */ /* ************************************************************************** */ -#ifdef __linux__ -# include -# include -# include -# include -# include -# include - /* the cookie */ # define BUFSIZE 2048 typedef struct { @@ -279,31 +330,4 @@ test_failed: return (err); } -/* ************************************************************************** */ -/* Use a file descriptor on other systems (placebo) */ -/* ************************************************************************** */ -#else -/** - * p7_fdinit: - * Initialize libp7 with a file descriptor. Placebo. - * - * @arg handle the handle to create - * @arg flags the flags. - * @arg name the name of the handle. - * @arg readfd the read file descriptor. - * @arg writefd the write file descriptor. - * @return the error (0 if ok) - */ - -int p7_fdinit(p7_handle_t **handle, unsigned int flags, - const char *name, int readfd, int writefd) -{ - (void)handle; - (void)flags; - (void)name; - (void)readfd; - (void)writefd; - return (p7_error_nocalc); -} - #endif diff --git a/src/stream/tty.c b/src/stream/tty.c deleted file mode 100644 index a617859..0000000 --- a/src/stream/tty.c +++ /dev/null @@ -1,93 +0,0 @@ -/* ************************************************************************** */ -/* _____ _ */ -/* streams/tty.c |_ _|__ _ _| |__ ___ _ _ */ -/* | Project: libp7 | |/ _ \| | | | '_ \ / _ \ | | | */ -/* | | (_) | |_| | | | | __/ |_| | */ -/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ -/* Last updated: 2017/01/04 15:01:48 |___/ */ -/* */ -/* ************************************************************************** */ -#include -#include - -/* ************************************************************************** */ -/* *nix serial device initialization and callbacks */ -/* ************************************************************************** */ -#ifdef __linux__ -# include -# include - -/** - * p7_cinit: - * Initialize libp7 with char device. - * - * @arg handle the handle to create - * @arg flags the flags. - * @arg path path to char device. - * @return the error (0 if ok) - */ - -int p7_cinit(p7_handle_t **handle, unsigned int flags, const char *path) -{ - int fd = -1; - - /* if no path, as there are no native drivers, we're fucked */ - if (!path) return (p7_error_nocalc); - - /* open the stream */ - fd = open(path, O_RDWR | O_NOCTTY); - if (fd < 0) switch (errno) { - /* no such device */ - case ENODEV: case ENOENT: case ENXIO: - case EPIPE: case ESPIPE: - logr_error("couldn't open calculator"); - return (p7_error_nocalc); - - /* no access */ - case EACCES: - logr_error("permission denied"); - return (p7_error_noaccess); - - /* default */ - default: - logr_error("unknown error: %s (0x%X)", strerror(errno), errno); - return (p7_error_unknown); - } - - /* check if we have got the thing */ - if (!path) return (p7_error_nocalc); - if (fd < 0) switch (errno) { - case ENOENT: return (p7_error_nocalc); - case EACCES: return (p7_error_noaccess); - default: return (p7_error_nocalc); - } - - /* init to real */ - return (p7_fdinit(handle, flags, NULL, fd, fd)); -} - -/* ************************************************************************** */ -/* Use a character device on other systems (placebo) */ -/* ************************************************************************** */ -#else -/** - * p7_cinit: - * Initialize libp7 with char device. Placebo. - * - * @arg handle the handle to create - * @arg flags the flags - * @arg path path to char device. - * @arg tries number of tries (0 means default). - * @return the error (0 if ok) - */ - -int p7_cinit(p7_handle_t **handle, unsigned int flags, - const char *path) -{ - (void)handle; - (void)flags; - (void)path; - return (p7_error_nocalc); -} - -#endif diff --git a/src/stream/windows.c b/src/stream/windows.c index 7d15bcb..ec2fb30 100644 --- a/src/stream/windows.c +++ b/src/stream/windows.c @@ -8,16 +8,40 @@ /* */ /* ************************************************************************** */ #include - -/* ************************************************************************** */ -/* Find devices on Microsoft Windows */ -/* ************************************************************************** */ -#ifdef __WINDOWS__ +#ifndef P7_DISABLED_WINDOWS # include # include # include # include +/* ************************************************************************** */ +/* Open a serial device */ +/* ************************************************************************** */ +/** + * p7_wcominit: + * Initialize using a MS-Windows serial device. + * + * @arg handle the handle to make. + * @arg flags the flags. + * @arg com the com port number. + * @return the error code (0 if ok). + */ + +int p7_wcominit(p7_handle_t **handle, unsigned int flags, int com) +{ + /* make up the serial device path */ + logr_info("Looking for specific MS-Windows devices"); + char path[20]; + if (com <= 9) sprintf(path, "COM%d", com); + else sprintf(path, "\\\\?\\COM%d", com); + + /* initialize */ + return (p7_winit(handle, flags, path)); +} + +/* ************************************************************************** */ +/* Find devices on Microsoft Windows */ +/* ************************************************************************** */ /** * wfind: * Find the Microsoft Windows device path. @@ -384,27 +408,4 @@ int p7_winit(p7_handle_t **handle, unsigned int flags, const char *path) free(p); return (err); } -/* ************************************************************************** */ -/* Not on windows: placebo */ -/* ************************************************************************** */ -#else - -/** - * p7_winit: - * Initialize libp7 [not] using the Microsoft Windows API. Placebo. - * - * @arg handle the handle to create. - * @arg flags the flags. - * @arg path the MS-Windows device path. - * @return the error code (0 if you're a knoop). - */ - -int p7_winit(p7_handle_t **handle, unsigned int flags, const char *path) -{ - (void)handle; - (void)flags; - (void)path; - return (p7_error_nocalc); -} - #endif