272 lines
11 KiB
C
272 lines
11 KiB
C
/* *****************************************************************************
|
|
* libp7/stream.h -- libp7 stream interface.
|
|
* Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
|
|
*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
* 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 <libp7/types.h>
|
|
# 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 */
|