/* ***************************************************************************** * libp7/stream.h -- libp7 stream interface. * Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey * * This file is part of libp7. * libp7 is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3.0 of the License, * or (at your option) any later version. * * libp7 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libp7; if not, see . * * The libp7 stream abstraction is there so that the core code can be more * platform-agnostic (althrough platform-specific helpers are built-in for * popular platforms like Microsoft Windows or GNU/Linux distributions). * A stream is basically what separates libp7 from the calculator. * When data is read from the stream, what is expected is what the calculator * has sent, and when data is written to the stream, it is what the calculator * shall receive. * ************************************************************************** */ #ifndef LIBP7_STREAM_H # define LIBP7_STREAM_H # include # ifdef __cplusplus extern "C" { # endif /* forward structure declarations (don't mind) */ struct p7_streamsettings_s; typedef struct p7_streamsettings_s p7_streamsettings_t; struct p7_streamtimeouts_s; typedef struct p7_streamtimeouts_s p7_streamtimeouts_t; struct p7_scsi_s; typedef struct p7_scsi_s p7_scsi_t; /* ************************************************************************** */ /* Stream structure */ /* ************************************************************************** */ /* This is the main structure of a stream. It is basically only made of * callbacks the libp7 functions will use to interact with the other device. * In case of any error (buffer not fully read/written, invalid settings), * your callbacks will have to return one of the libp7 error codes. * There is no partial success. * * Once your stream is setup (and it should be open before calling `p7_sinit`), * the libp7 functions will call your `setcomm` and `settm` functions using * information from the protocol and given by the user to the initialization * function (you shouldn't use this information directly in yours). If your * device is not a serial device, you can forget it. * * If your stream is a character device, then when the user reads data, your * `read` callback is called, and when they write data, your `write` callback * is called. Notice that you receive the direct requests from the user: * if your stream requires buffering, you shall implement it yourself. * * If your stream is an SCSI device, then when the user makes a request, * your `scsi_request` callback with the request. * * On exit, your `close` callback is called. * Here are the flags: */ # define p7_streamflag_serial 0x0000 # define p7_streamflag_usb 0x0001 # define p7_streamflag_scsi 0x0002 # define p7_streamflag_uas (p7_streamflag_usb | p7_streamflag_scsi) /* Here are the callback types: */ typedef int (*p7_stream_close_t)(void*); typedef int (*p7_stream_setcomm_t)(void*, const p7_streamsettings_t*); typedef int (*p7_stream_settm_t)(void*, const p7_streamtimeouts_t*); typedef int (*p7_stream_read_t)(void*, unsigned char*, size_t); typedef int (*p7_stream_write_t)(void*, const unsigned char*, size_t); typedef int (*p7_stream_scsi_request_t)(void*, p7_scsi_t*); /* Here is the stream structure: */ typedef struct p7_stream_s { /* stream information */ unsigned int flags; void *cookie; /* main callbacks */ p7_stream_close_t close; /* settings callbacks */ p7_stream_setcomm_t setcomm; p7_stream_settm_t settm; /* character callbacks */ p7_stream_read_t read; p7_stream_write_t write; /* SCSI callbacks */ p7_stream_scsi_request_t scsi_request; } p7_stream_t; /* Warning: in your stream initialization function, you shouldn't initialize * your structure with zeroes, but set the flags with the type of callbacks * you're going to use, and set those callbacks (with something if you're using * them, or NULL if you're not). * * That's important for compatibility with older versions which didn't have * as many callbacks. */ /* ************************************************************************** */ /* Stream settings values and flags */ /* ************************************************************************** */ /* Here are the different baud speeds you can encounter, in bauds. * Note that one speed is not supported by all models. */ # define P7_B1200 1200 /* old models */ # define P7_B2400 2400 /* old models */ # define P7_B4800 4800 /* old models */ # define P7_B9600 9600 /* protocol seven default speed */ # define P7_B19200 19200 /* seven alternative speed */ # define P7_B38400 38400 /* algebrafx default speed */ # define P7_B57600 57600 /* seven alternative speed */ # define P7_B115200 115200 /* seven alternative speed */ /* Here are the control characters and other values you have in the * stream settings. */ # define P7_NCCS 0x02 /* number of control characters */ # define P7_XON 0x00 /* XON character: re-enable transmission */ # define P7_XOFF 0x01 /* XOFF character: disable transmission */ /* From here, those are all in the stream settings flags. * Here are the stop bits settings: */ # define P7_STOPBITSMASK 0x0001 # define P7_ONESTOPBIT 0x0000 /* one stop bit */ # define P7_TWOSTOPBITS 0x0001 /* two stop bits */ /* Here are the parity settings: */ # define P7_PARMASK 0x0006 # define P7_PARDIS 0x0000 /* disable parity checking */ # define P7_PARENB 0x0002 /* enable parity checking */ # define P7_PAREVEN 0x0000 /* even parity */ # define P7_PARODD 0x0004 /* odd parity */ /* Here are the DTR/RTS settings. * Notice that not all platforms implement this. Just do as you can. */ # define P7_DTRMASK 0x0018 # define P7_DTRCTL_DISABLE 0x0000 /* disable DTR */ # define P7_DTRCTL_ENABLE 0x0008 /* enable DTR */ # define P7_DTRCTL_HANDSHAKE 0x0010 /* enable DTR and handshake */ # define P7_DTRVAL(F) (((F) & P7_DTRMASK) >> 3) # define P7_RTSMASK 0x0060 # define P7_RTSCTL_DISABLE 0x0000 /* disable RTS */ # define P7_RTSCTL_ENABLE 0x0020 /* enable RTS */ # define P7_RTSCTL_HANDSHAKE 0x0040 /* enable RTS and handshake */ # define P7_RTSVAL(F) (((F) & P7_RTSMASK) >> 5) /* Here are the XON/XOFF software control settings. * XOFF disables the transmission temporarily, usually because the device at * the other end can't manage too much data too quickly. */ # define P7_XONMASK 0x0080 # define P7_XONCTL_DISABLE 0x0000 /* disable XON */ # define P7_XONCTL_ENABLE 0x0080 /* enable XON */ /* XON re-enables the transmission, probably because the device at the end * has finished processing the data you sent and is ready to process more. */ # define P7_XOFFMASK 0x0100 # define P7_XOFFCTL_DISABLE 0x0000 /* disable XOFF */ # define P7_XOFFCTL_ENABLE 0x0100 /* enable XOFF */ /* ************************************************************************** */ /* Stream settings */ /* ************************************************************************** */ /* Here is the stream settings structure: */ struct p7_streamsettings_s { /* flags - see the above section */ unsigned int flags; /* speed: one of the P7_B* constants */ unsigned int speed; /* characters */ unsigned char cc[P7_NCCS]; }; /* This structure will be sent to your `setcomm` callback to set serial * communication settings. * And here is the stream timeouts structure: */ struct p7_streamtimeouts_s { /* Initial read timeout */ unsigned int read; /* In-between bytes read timeout */ unsigned int read_bw; /* Total write timeout */ unsigned int write; }; /* This structure will be sent to your `settm` callback, usually after a state * change in the communication. Also, all timeouts are in milliseconds (ms). */ /* ************************************************************************** */ /* SCSI request */ /* ************************************************************************** */ /* CASIO's fx-CG devices, also known as Prizms or Graph 90+E, use SCSI aside * with Protocol 7.00 to communicate with the PC for things like file * transferring or screenstreaming (which use vendor-specific command slots). * As systems usually have some standard methods for SCSI, it is worth it * to implement an SCSI interface into P7 streams. * * This is libp7's SCSI request structure, inspired from Linux's * `sg_io_hdr_t` structure, except this structure is cross-platform. * Here is the different values for the data direction: */ # define p7_scsi_dxfer_none -1 /* no content */ # define p7_scsi_dxfer_to_dev -2 /* outgoing */ # define p7_scsi_dxfer_from_dev -3 /* incoming */ /* And here is the request structure: */ struct p7_scsi_s { /* command description */ int type, direction; unsigned int byte_transfer_length; unsigned long logical_block, allocation_length; unsigned char cbp[4], misc; /* raw data */ unsigned int cmd_len, data_len, sense_len; unsigned char cmd[16]; unsigned char *data; unsigned char *sense; /* TODO: output thingies? */ }; /* It will be sent to your `scsi_request` callback. */ /* ************************************************************************** */ /* Public stream functions */ /* ************************************************************************** */ /* Initialize a handle using a custom stream. */ extern int p7_sinit(p7_handle_t **h, unsigned int flags, const char *name, p7_stream_t stream, const p7_streamsettings_t *settings); /* Default stream serial settings utilities. * `p7_initcomm` initializes a stream settings structure. */ extern void p7_initcomm(p7_streamsettings_t *settings); /* Read and write data from and to a stream, set stream settings and timeouts. * You should use these functions instead of the callbacks directly. */ extern int p7_read(p7_stream_t *stream, void *dest, size_t size); extern int p7_write(p7_stream_t *stream, const void *data, size_t size); extern int p7_setcomm(p7_stream_t *stream, const p7_streamsettings_t *settings); extern int p7_settm(p7_stream_t *stream, const p7_streamtimeouts_t *timeouts); /* Skip bytes from a stream. */ extern int p7_skip(p7_stream_t *stream, size_t size); # ifdef __cplusplus } # endif #endif /* LIBP7_STREAM_H */