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/packetio.h

302 lines
11 KiB
C

/* *****************************************************************************
* libp7/packetio.h -- libp7 Packet I/O 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/>.
*
* Aside from the public and easy interface described in `libp7.h`, you may
* want to have more control on the communication. This file is the one: it
* allows you to exchange packets directly, using Protocol 7 (libp7 internals
* will take care of the odd details).
*
* Once the communication is initialized (`p7_init` with the `P7_ACTIVE` flag
* takes care of that), the Protocol 7 is basically a set of packet flows.
*
* A first example of packet flow is: the client sends a command (e.g. delete
* a file), and the server sends back an ACK (command has been executed)
* or the error if there is one (e.g. the command is not implemented, or the
* file doesn't exist).
*
* Another example of packet flow is: the client sends a command (e.g. file
* listing), the server accepts, the client sends a ROLESWP so that it becomes
* a server and the server becomes the client. The calculator (now client) will
* then send (sub-)commands (e.g. "here is a file entry"), then the client
* will ACK to each one, until the calculator finally sends a ROLESWAP to tell
* he has finished.
*
* Yet another example of packet flow (but there are others) is: the client
* sends a command (e.g. send a file), the server ACKs, then the client will
* send the data (libp7 takes care of that with the `p7_send_filestream`
* function).
*
* A last example of packet flow (but there may be others) is: the client
* sends a command (e.g. receive a file), the server ACKs, then the client
* sends a ROLESWP, and the calculator will use a sub-packet flow (e.g. file
* sending) to send the data, and will send a ROLESWP when it's done.
*
* This is just a preview of what you can do with the protocol and the library.
* You should check out the library sources, more importantly the `protocol`
* module, if you want examples :)
* ************************************************************************** */
#ifndef LIBP7_PACKETIO_H
# define LIBP7_PACKETIO_H
# include <libp7/types.h>
# include <libp7/stream.h> /* for constants */
# ifdef __cplusplus
extern "C" {
# endif
/* ************************************************************************** */
/* Enumerations - give sense to those numbers! */
/* ************************************************************************** */
/* The packet type. */
# define p7_pt_cmd 0x01
# define p7_pt_data 0x02
# define p7_pt_roleswp 0x03
# define p7_pt_check 0x05
# define p7_pt_ack 0x06
# define p7_pt_ohp 0x0B
# define p7_pt_error 0x15
# define p7_pt_terminate 0x18
/* The packet screen type - adapted from a string. */
# define p7_pscr_typ01 0
/* In case a file exists, what should we do? */
# define p7_ow_confirm 0x00
# define p7_ow_terminate 0x01
# define p7_ow_force 0x02
/* The error codes */
# define p7_err_resend 0x01
# define p7_err_overwrite 0x02
# define p7_err_dont_overwrite 0x03
# define p7_err_other 0x04
# define p7_err_fullmem 0x05
/* The termination types */
# define p7_term_default 0x00
# define p7_term_user 0x01
# define p7_term_timeouts 0x02
# define p7_term_overwrite 0x03
/* types -- because those were enums before */
typedef int p7_packettype_t;
typedef int p7_packetscreen_t;
typedef int p7_commandoverwrite_t;
typedef int p7_errcode_t;
typedef int p7_termtype_t;
/* ************************************************************************** */
/* Commands */
/* ************************************************************************** */
/* Commands have an OW field (overwrite action), an MCS type field,
* a FILESIZE field, and six arguments.
*
* The utility of an argument or not depends on the command, but the places
* of the arguments stay the same:
*
* # | Argument signification
* --+-----------------------
* 1 | Directory name
* 2 | File name
* 3 | New directory name
* 4 | New file name
* 5 | Storage device name
* 6 | ??? (unused everywhere)
*
* An exception seems to be that argument #2 in commands 0x_2
* (rename directory) is the new directory name (but maybe that's a typo).
*
* Also, command 0x56 has a completely different data format that the others
* commands (and even other packets in general, as it finishes with a binary
* zero, for some reason). */
/* Main commands */
int p7_send_cmd(p7_handle_t *handle, p7ushort_t subtype);
int p7_send_cmd_data(p7_handle_t *handle, p7ushort_t subtype,
int overwrite, p7ushort_t datatype, p7uint_t filesize,
const char *arg1, const char *arg2, const char *arg3,
const char *arg4, const char *arg5, const char *arg6);
/* Command models
* - Simple command */
# define p7cmd(C, CODE) \
static inline int p7_send_cmd##C(p7_handle_t *handle) { \
return (p7_send_cmd(handle, CODE)); }
/* - Command for a storage device */
# define p7cmd_dev(C, CODE) \
static inline int p7_send_cmd##C(p7_handle_t *handle, const char *devname) { \
return (p7_send_cmd_data(handle, CODE, 0, 0, 0, \
NULL, NULL, NULL, NULL, devname, NULL)); }
/* - Command for interacting with a directory */
# define p7cmd_dir(C, CODE) \
static inline int p7_send_cmd##C(p7_handle_t *handle, \
const char *dirname, const char *devname) { \
return (p7_send_cmd_data(handle, CODE, 0, 0, 0, \
dirname, NULL, NULL, NULL, devname, NULL)); }
/* - Command for renaming a directory */
# define p7cmd_rendir(C, CODE) \
static inline int p7_send_cmd##C(p7_handle_t *handle, \
const char *dirname, const char *newdir, const char *devname) { \
return (p7_send_cmd_data(handle, CODE, 0, 0, 0, \
dirname, newdir, NULL, NULL, devname, NULL)); }
/* - Command for interacting with a file */
# define p7cmd_file(C, CODE) \
static inline int p7_send_cmd##C(p7_handle_t *handle, \
const char *dirname, const char *filename, const char *devname) { \
return (p7_send_cmd_data(handle, CODE, 0, 0, 0, \
dirname, filename, NULL, NULL, devname, NULL)); }
/* - Command for sending a file */
# define p7cmd_send(C, CODE) \
static inline int p7_send_cmd##C(p7_handle_t *handle, \
int ow, p7uint_t fs, \
const char *dirname, const char *filename, const char *devname) { \
return (p7_send_cmd_data(handle, CODE, ow, 0, fs, \
dirname, filename, NULL, NULL, devname, NULL)); }
/* - Command for copying a file */
# define p7cmd_copy(C, CODE) \
static inline int p7_send_cmd##C(p7_handle_t *handle, \
const char *dirname, const char *filename, \
const char *newdir, const char *newname, const char *devname) { \
return (p7_send_cmd_data(handle, CODE, 0, 0, 0, \
dirname, filename, newdir, newname, devname, NULL)); }
/* - Command for renaming a file */
# define p7cmd_rename(C, CODE) \
static inline int p7_send_cmd##C(p7_handle_t *handle, \
const char *dirname, const char *filename, \
const char *newname, const char *devname) { \
return (p7_send_cmd_data(handle, CODE, 0, 0, 0, \
dirname, filename, NULL, newname, devname, NULL)); }
/* Command definitions
* Remember that these are only for the ease of use; you can use the macros
* to implement more commands without putting them here. */
p7cmd(sys_getinfo, 0x01)
p7cmd(mcs_reqallinfo, 0x2D)
p7cmd(bak_reqram, 0x2F)
p7cmd(bak_putram, 0x30)
p7cmd_dir(fls_mkdir, 0x40)
p7cmd_dir(fls_rmdir, 0x41)
p7cmd_dir(fls_mvdir, 0x42)
p7cmd_dir(fls_cwd, 0x43)
p7cmd_file(fls_reqfile, 0x44)
p7cmd_send(fls_sendfile, 0x45)
p7cmd_file(fls_delfile, 0x46)
p7cmd_rename(fls_renamefile, 0x47)
p7cmd_copy(fls_copyfile, 0x48)
p7cmd_dev(fls_reset, 0x4A)
p7cmd_dev(fls_reqcapacity, 0x4B)
p7cmd_dev(fls_reqallinfo, 0x4D)
p7cmd_dev(fls_opt, 0x51)
p7cmd(bak_reqrom, 0x4F)
p7cmd(bak_putrom, 0x50)
p7cmd(bak_reqcwe, 0x52)
p7cmd(bak_putcwe, 0x53)
p7cmd(bak_reqboot, 0x54)
p7cmd(bak_putboot, 0x55)
/* These functions are kept as functions because they're more complex */
int p7_send_cmdsys_setlink(p7_handle_t *handle,
int baudrate, int parity, int stopbits);
int p7_send_cmdosu_upandrun(p7_handle_t *handle,
p7uint_t upsize, p7uint_t loadaddr, p7uint_t straddr);
/* get and send some data using buffers */
int p7_send_buffer(p7_handle_t *handle, const p7_buffer_t *buffer,
int shift, p7_disp_t disp);
int p7_get_buffer(p7_handle_t *handle, const p7_buffer_t *buffer, p7uint_t size,
int shift, p7_disp_t disp);
/* get and send some data using memory areas */
int p7_send_data(p7_handle_t *handle, const void *vbuf, p7uint_t size,
int shift, void (*disp)(p7ushort_t, p7ushort_t));
int p7_get_data(p7_handle_t *handle, void *buf, p7uint_t size,
int shift, p7_disp_t disp);
/* ************************************************************************** */
/* Other packets */
/* ************************************************************************** */
/* Send raw packets (you shouldn't use that directly) */
int p7_send_basic(p7_handle_t *handle,
p7_packettype_t type, p7ushort_t subtype, int resp);
int p7_send_ext(p7_handle_t *handle,
p7_packettype_t type, p7ushort_t subtype,
const void *data, p7ushort_t size, int resp);
/* Errors */
static inline int p7_send_err(p7_handle_t *handle, int code) {
return (p7_send_basic(handle, p7_pt_error, code, 1)); }
/* Acknowledgements */
int p7_send_ack(p7_handle_t *handle, int resp);
int p7_send_eack(p7_handle_t *handle, p7_server_t *info);
/* Answers to overwrite */
int p7_confirm_ow(p7_handle_t *handle);
# define p7_deny_ow(H) p7_send_err((H), p7_err_dont_overwrite)
/* Roleswap */
int p7_send_roleswp(p7_handle_t *handle);
/* Terminations */
int p7_send_term_because(p7_handle_t *handle, int reason);
# define p7_send_term(H) p7_send_term_because((H), p7_term_default)
/* ************************************************************************** */
/* Answer to command packets */
/* ************************************************************************** */
# define MAX_COMMAND_ARGUMENT_SIZE 256
# define MAX_VRAM_SIZE 1024 /* increase in case of other vram formats */
# define MAX_VRAM_WIDTH 128
# define MAX_VRAM_HEIGHT 64
# define MAX_RAWDATA_SIZE 256
/* The decoded packet representation. */
typedef struct {
/* main info */
unsigned int type;
int extended;
/* error, termination, check */
int code, initial;
/* commands */
int ow; int mcstype; p7uint_t filesize;
char *args[6]; char _argsdata[6][MAX_COMMAND_ARGUMENT_SIZE + 1];
p7uint_t uploadsize, loadaddr, straddr; /* 0x56 */
/* data */
p7ushort_t id, total;
unsigned char data[MAX_RAWDATA_SIZE];
p7ushort_t data_size;
/* server information */
p7_server_t info;
/* screen */
p7_packetscreen_t scrtype;
unsigned char vram[MAX_VRAM_SIZE];
} p7_packet_t;
/* Extract this representation from the handle */
const p7_packet_t *p7_get_response(p7_handle_t *handle);
# ifdef __cplusplus
}
# endif
#endif /* LIBP7_PACKETIO_H */