cake
/
libp7
Archived
1
0
Fork 1
This repository has been archived on 2024-03-16. You can view files and clone it, but cannot push or open issues or pull requests.
libp7/include/libp7/stream.h

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 */