266 lines
10 KiB
C
266 lines
10 KiB
C
/* *****************************************************************************
|
|
* libp7/internals.h -- libp7 private internals header.
|
|
* 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/>.
|
|
*
|
|
* This file is the main internals file, that the library sources will include.
|
|
* It contains all the private structures and functions. Also, it will not
|
|
* be installed with the public headers.
|
|
* ************************************************************************** */
|
|
#ifndef LIBP7_INTERNALS_H
|
|
# define LIBP7_INTERNALS_H
|
|
/* Microsoft Windows minimal version (Vista) */
|
|
# ifdef _WIN32_WINNT
|
|
# undef _WIN32_WINNT
|
|
# endif
|
|
# define _WIN32_WINNT 0x0600
|
|
|
|
# include <libp7.h>
|
|
# include <libp7/packetio.h>
|
|
# include <libp7/streams.h>
|
|
# include <libp7/internals/stdio_ext.h>
|
|
# include <libp7/internals/endian.h>
|
|
|
|
/* Macros */
|
|
# ifndef min
|
|
# define min(A, B) ((A) < (B) ? (A) : (B))
|
|
# endif
|
|
# ifndef max
|
|
# define max(A, B) ((A) > (B) ? (A) : (B))
|
|
# endif
|
|
/* ************************************************************************** */
|
|
/* Maximum buffer sizes */
|
|
/* ************************************************************************** */
|
|
/* The maximum size of the raw data field.
|
|
* > id (4 bytes) + total (4 bytes) + data */
|
|
|
|
# define MAX_RAWDFLD_SIZE (8 + MAX_RAWDATA_SIZE)
|
|
|
|
/* The maximum size of the encoded data field.
|
|
* > id (4 bytes) + total (4 bytes) + encoded data
|
|
*
|
|
* The worst case is where every byte has to be encoded (an '\' has to be
|
|
* added), so the size of the worst (biggest) case is MAX_RAWDFLD_SIZE * 2. */
|
|
|
|
# define MAX_ENCDFLD_SIZE (8 + (MAX_RAWDATA_SIZE * 2))
|
|
|
|
/* The maximum packet size. Used to be :
|
|
* > t + st + ext + encoded D field + checksum + null byte
|
|
* > 8 + MAX_ENCDFLD_SIZE + 2 + 1
|
|
*
|
|
* But with OHP (screen streaming) introduction, this size wasn't enough to
|
|
* store screen streaming packets. So we use the OHP packet size as a
|
|
* reference, even for normal protocol, in case user launches "normal" packet
|
|
* mode and the calculator sends OHP packets. The formula is:
|
|
*
|
|
* > ohp type + (subheader) + pic data + checksum */
|
|
|
|
# define MAX_PACKET_SIZE (6 + 18 + MAX_VRAM_SIZE + 2)
|
|
/* ************************************************************************** */
|
|
/* Timeouts */
|
|
/* ************************************************************************** */
|
|
/* Active timeout - waiting for a direct answer */
|
|
# define ACTIVE_TIMEOUT (10 * 1000)
|
|
|
|
/* Idle timeout - waiting for a command */
|
|
# define IDLE_TIMEOUT (6 * 60 * 1000)
|
|
/* ************************************************************************** */
|
|
/* Environments */
|
|
/* ************************************************************************** */
|
|
/* main structure */
|
|
typedef struct {
|
|
const char *model; /* model identifier */
|
|
const char *name; /* name */
|
|
unsigned int mask; /* the supported commands mask bit */
|
|
} p7_env_t;
|
|
|
|
/* environment functions */
|
|
extern p7_env_t *p7_get_env(const char *model);
|
|
extern int p7_command_is_supported(unsigned int code, const p7_env_t *env);
|
|
# define command_is_supported(N) p7_command_is_supported(N, handle->_env)
|
|
/* ************************************************************************** */
|
|
/* Handle-related */
|
|
/* ************************************************************************** */
|
|
/* handle flags */
|
|
# define p7_intflag_sendalt 0x0001 /* use alternative buffer (_buffers[1]) */
|
|
# define p7_intflag_alloc 0x0002 /* was allocated */
|
|
# define p7_intflag_active 0x0008 /* active status */
|
|
# define p7_intflag_shifted 0x0010 /* shift status */
|
|
# define p7_intflag_initializd 0x0020 /* initialized */
|
|
# define p7_intflag_terminated 0x0040 /* terminated */
|
|
# define p7_intflag_term 0x0080 /* should terminate at exit */
|
|
# define p7_intflag_nocheck 0x0100 /* should not read the next checksum */
|
|
# define p7_intflag_adjscreen 0x0200 /* adjust to get the screenstream begin */
|
|
# define p7_intflag_check 0x0400 /* make the initial check */
|
|
|
|
/* handle structure */
|
|
struct p7_handle_s {
|
|
/* flags - see above */
|
|
unsigned int _flags;
|
|
|
|
/* debug name, for multi-handle logging (e.g. `p7servtest` in p7utils)
|
|
* a space/null, 8 chars max, and imposed null char */
|
|
char _name[10];
|
|
|
|
/* stream settings */
|
|
p7_stream_t _stream;
|
|
p7_streamsettings_t _settings;
|
|
|
|
/* protocol 7.00-related core things */
|
|
const p7_env_t *_env; /* see `protocol/seven/devices.c` */
|
|
p7_packet_t _response;
|
|
p7_server_t _server;
|
|
p7ushort_t _last_sent_command;
|
|
p7_packet_t _response_data;
|
|
|
|
/* MCS head */
|
|
g1m_mcshead_t mcshead;
|
|
|
|
/* raw sending packet buffers */
|
|
unsigned char _send_buffers[2][MAX_PACKET_SIZE];
|
|
size_t _send_buffers_size[2];
|
|
|
|
/* raw reception packet buffer */
|
|
unsigned char _recv_buffer[MAX_PACKET_SIZE];
|
|
};
|
|
|
|
/* sub-sub-init utils */
|
|
# ifndef P7_DISABLED_FILE
|
|
extern int _p7_finit(p7_handle_t **handle, unsigned int flags,
|
|
FILE *rstream, FILE *wstream, int rstream_close);
|
|
# endif
|
|
/* ************************************************************************** */
|
|
/* Protocol 7.00 Packet I/O utilities */
|
|
/* ************************************************************************** */
|
|
/* start communication */
|
|
extern int p7_seven_start(p7_handle_t *handle);
|
|
extern int p7_seven_end(p7_handle_t *handle);
|
|
|
|
/* decode packets */
|
|
extern int p7_seven_decode_command(p7_handle_t *handle,
|
|
const unsigned char *data, size_t data_size);
|
|
extern int p7_seven_decode_ack(p7_handle_t *handle,
|
|
const unsigned char *data, size_t data_size);
|
|
extern int p7_seven_decode_data(p7_handle_t *handle,
|
|
const void *raw, p7ushort_t raw_size);
|
|
|
|
/* utilities */
|
|
extern int p7_seven_send_again(p7_handle_t *handle);
|
|
extern int p7_seven_recv(p7_handle_t *handle, int checksum);
|
|
|
|
/* Resend error packet (meant to be used with recv, not suited for public) */
|
|
extern int p7_seven_send_err_resend(p7_handle_t *handle);
|
|
|
|
/* active response */
|
|
# define response (handle->_response)
|
|
/* ************************************************************************** */
|
|
/* Macros */
|
|
/* ************************************************************************** */
|
|
/* check if handle is initialized */
|
|
# define chk_handle(H) \
|
|
if (!(H)) return (p7_error_uninitialized); \
|
|
if ((H)->_flags & p7_intflag_terminated) return (p7_error_terminated);
|
|
|
|
/* check if active */
|
|
# define chk_active(H) \
|
|
if (~(H)->_flags & p7_intflag_active) return (p7_error_active)
|
|
|
|
/* check if passive */
|
|
# define chk_passive(H) \
|
|
if ((H)->_flags & p7_intflag_active) return (p7_error_active)
|
|
|
|
/* check if filename is ok */
|
|
# define chk_filename(F) \
|
|
if ((F) && !p7_validate_filename(F)) return (p7_error_filename)
|
|
|
|
/* check if filename is there and ok */
|
|
# define chk_required_filename(F) \
|
|
if (!(F) || !p7_validate_filename(F)) return (p7_error_filename)
|
|
|
|
/* check if dirname is ok */
|
|
# define chk_dirname(D) \
|
|
if ((D) && !p7_validate_dirname(D)) return (p7_error_dirname)
|
|
|
|
/* check if mcs request head is ok */
|
|
# define chk_head(H) \
|
|
g1m_correct_mcsfile_head(H); \
|
|
if (!(H)->name[0]) return (p7_error_filename); \
|
|
if (!(H)->_group[0]) return (p7_error_groupname)
|
|
|
|
/* check if filestream is readable */
|
|
# define chk_isread(F) \
|
|
if (!(F) || !__freadable(F)) return (p7_error_noread)
|
|
|
|
/* check if filestream is writable */
|
|
# define chk_iswrite(F) \
|
|
if (!(F) || !__fwritable(F)) return (p7_error_nowrite)
|
|
|
|
/* check if filesize is ok */
|
|
# define chk_filesize(S) \
|
|
if (!(S)) return (p7_error_empty); \
|
|
if ((S) > UINT32_MAX) return (p7_error_fullmem)
|
|
|
|
/* check if buffer is readable */
|
|
# define chk_bufread(B) \
|
|
if (!(B) || !(B)->read) return (p7_error_noread)
|
|
|
|
/* check if buffer is writable */
|
|
# define chk_bufwrite(B) \
|
|
if (!(B) || !(B)->write) return (p7_error_nowrite)
|
|
|
|
/* check if memory buffer is valid and not empty */
|
|
# define chk_mem(M) \
|
|
if (!(M)) return (p7_error_nostream)
|
|
/* ************************************************************************** */
|
|
/* Memory buffer structure */
|
|
/* ************************************************************************** */
|
|
/* cursor structure */
|
|
typedef struct {
|
|
const void *mem;
|
|
size_t offset;
|
|
} p7_cursor_t;
|
|
|
|
/* Callbacks */
|
|
extern int p7_membuffer_read(void *cookie, unsigned char *dest, size_t size);
|
|
/* ************************************************************************** */
|
|
/* Utilities */
|
|
/* ************************************************************************** */
|
|
/* File/buffer callbacks */
|
|
# ifndef P7_DISABLED_FILE
|
|
extern int p7_filebuffer_read(void *cookie, unsigned char *dest, size_t size);
|
|
extern int p7_filebuffer_write(void *cookie, const unsigned char *data,
|
|
size_t size);
|
|
# endif
|
|
|
|
/* Encoding/decoding functions */
|
|
extern p7ushort_t p7_encode(void *fnal, const void *raw, p7ushort_t size);
|
|
extern p7ushort_t p7_decode(void *fnal, const void *encoded, p7ushort_t size);
|
|
|
|
/* Checksum function */
|
|
extern unsigned int p7_checksum(unsigned char *packet, p7ushort_t size);
|
|
|
|
/* ASCII-hex utilities */
|
|
extern void p7_putascii(unsigned char *p, p7uint_t i, int n);
|
|
extern p7uint_t p7_getascii(const unsigned char *p, int n);
|
|
extern p7uint_t p7_getdec(p7uint_t h);
|
|
extern p7uint_t p7_gethex(p7uint_t d);
|
|
|
|
/* SCSI command making function */
|
|
extern int p7_scsi_correct(p7_scsi_t *request);
|
|
|
|
# include <libp7/internals/log.h>
|
|
#endif
|