290 lines
14 KiB
C
290 lines
14 KiB
C
/* *****************************************************************************
|
|
* libp7/protocol/seven.h -- libp7 latest protocol 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 one of
|
|
* the ones: it allows you to exchange packets directly, using Protocol 7.00
|
|
* (libp7 internals will take care of the odd details).
|
|
* ************************************************************************** */
|
|
#ifndef LIBP7_PROTOCOL_SEVEN_H
|
|
# define LIBP7_PROTOCOL_SEVEN_H
|
|
# include <libp7/types.h>
|
|
# include <libp7/stream.h>
|
|
# ifdef __cplusplus
|
|
extern "C" {
|
|
# endif
|
|
|
|
/* ************************************************************************** */
|
|
/* Packets */
|
|
/* ************************************************************************** */
|
|
/* Protocol 7.00 (the latest proprietary protocol from CASIO) is a protocol
|
|
* using several-bytes packets. Every packet, at one exception we'll detail
|
|
* later, contains a type, a subtype, an optional payload, and a checksum.
|
|
*
|
|
* Here are the known packet types: */
|
|
|
|
typedef int p7_seven_type_t;
|
|
# define p7_seven_type_cmd 0x01 /* ask something (initiate a packet flow) */
|
|
# define p7_seven_type_data 0x02 /* send some data */
|
|
# define p7_seven_type_swp 0x03 /* change roles */
|
|
# define p7_seven_type_check 0x05 /* check if there is an interlocutor */
|
|
# define p7_seven_type_ack 0x06 /* acknowledge ('okay') */
|
|
# define p7_seven_type_ohp 0x0B /* screenstreaming packet */
|
|
# define p7_seven_type_nak 0x15 /* acknowledge negatively ('nope') */
|
|
# define p7_seven_type_end 0x18 /* end the communication */
|
|
|
|
/* And here are some aliases, for old code. */
|
|
|
|
# define p7_seven_type_roleswp p7_seven_type_swp
|
|
# define p7_seven_type_error p7_seven_type_nak
|
|
# define p7_seven_type_term p7_seven_type_end
|
|
# define p7_seven_type_terminate p7_seven_type_end
|
|
|
|
/* The subtype has a different meaning according to the type it is used with.
|
|
* For check packets, it can mean: */
|
|
|
|
# define p7_seven_chk_ini 0x00 /* initial check */
|
|
# define p7_seven_chk_wait 0x01 /* in-communication check, while waiting */
|
|
|
|
/* For ACK packets: */
|
|
|
|
# define p7_seven_ack_normal 0x00 /* normal ACK */
|
|
# define p7_seven_ack_ow 0x01 /* confirm overwrite */
|
|
# define p7_seven_ack_ext 0x02 /* extended ACK */
|
|
# define p7_seven_ack_term 0x03 /* ACK, end the communication (0x56) */
|
|
|
|
/* For NAK packets (error packets): */
|
|
|
|
typedef int p7_seven_err_t;
|
|
typedef p7_seven_err_t p7_seven_error_t;
|
|
# define p7_seven_err_resend 0x01 /* checksum/timeout error, resend */
|
|
# define p7_seven_err_overwrite 0x02 /* server response: confirm ow? */
|
|
# define p7_seven_err_dont_overwrite 0x03 /* denial */
|
|
# define p7_seven_err_other 0x04 /* generic error (other errors) */
|
|
# define p7_seven_err_fullmem 0x05 /* full memory (terminates comm'!) */
|
|
|
|
/* For END packets (terminate packets): */
|
|
|
|
typedef int p7_seven_term_t;
|
|
# define p7_seven_term_default 0x00 /* normal termination */
|
|
# define p7_seven_term_user 0x01 /* user has interrupted communication */
|
|
# define p7_seven_term_timeouts 0x02 /* terminated due to timeouts */
|
|
# define p7_seven_term_overwrite 0x03 /* in response to `p7_ow_terminate` */
|
|
|
|
/* I said there was an exception earlier on, I wasn't lying: screenstreaming
|
|
* packets have a different format than other packets. Basically, after the
|
|
* type, there is a five-letter subtype (such as "TYP01" or "TYPZ1"), and
|
|
* for some types, subheaders. libp7 translates this into a VRAM and a picture
|
|
* format, which you can see in the libp7 Protocol 7.00 packet
|
|
* representation.
|
|
*
|
|
* Note that the screenstreaming packet flow is totally different from
|
|
* the normal packet flow: it's just the calculator sending its screen
|
|
* repeateadly, not expecting any answer from the other side. */
|
|
/* ************************************************************************** */
|
|
/* Command payload */
|
|
/* ************************************************************************** */
|
|
/* The command has a payload which contain, even in the cases where they are
|
|
* not useful, the overwrite status (OW), the MCS raw data type (DT),
|
|
* the file size (FS), and the six arguments (of variable length,
|
|
* although they never are above 16 bytes long).
|
|
*
|
|
* Some commands have a completely different format than others, such as
|
|
* the 0x56 command (upload'n'run), which also finishes with a binary zero.
|
|
*
|
|
* The overwrite status (OW) is useful for when sending a file. It can basically
|
|
* say, using the codes: */
|
|
|
|
typedef int p7_seven_ow_t;
|
|
# define p7_seven_ow_confirm 0x00 /* ask for confirmation */
|
|
# define p7_seven_ow_terminate 0x01 /* terminate if the file exists */
|
|
# define p7_seven_ow_force 0x02 /* force overwriting */
|
|
|
|
/* With `p7_ow_confirm`, if the file exists, a `p7_err_overwrite` NAK packet,
|
|
* then, you will either confirm with an ACK packet, or infirm with a
|
|
* `p7_err_dont_overwrite` error packet.
|
|
*
|
|
* The MCS raw data type (DT) should be used with other arguments that are
|
|
* found within the arguments -- it is all documented in libg1m.
|
|
* The filesize (FS) is used when sending a file or file information only.
|
|
* For some commands (such as 0x4E), it can also be the free capacity.
|
|
*
|
|
* The arguments usually are:
|
|
*
|
|
* # | Argument signification | Alternative significations
|
|
* --+-------------------------+----------------------------------------
|
|
* 1 | Directory name | Setup entry name
|
|
* 2 | File name | New directory name (directory renaming)
|
|
* | | Setup entry content (ASCII-hex)
|
|
* 3 | New directory name | MCS group name
|
|
* 4 | New file name |
|
|
* 5 | Storage device name |
|
|
* 6 | ??? (unused everywhere) |
|
|
*
|
|
* Whether arguments are used or not depend on the command. */
|
|
/* ************************************************************************** */
|
|
/* libp7 packet representation */
|
|
/* ************************************************************************** */
|
|
/* The libp7 Protocol 7.00 packet representation includes all the data
|
|
* you could have in a packet. First, here are the buffer sizes: */
|
|
|
|
# define MAX_VRAM_SIZE 0x28800 /* format size * max_width * max_height */
|
|
# define MAX_VRAM_WIDTH 384 /* the maximum encountered VRAM width */
|
|
# define MAX_VRAM_HEIGHT 500 /* the maximum encountered VRAM height */
|
|
# define MAX_RAWDATA_SIZE 256 /* the maximum raw data size */
|
|
# define MAX_CMDARG_SIZE 256 /* the technical maximum argument size */
|
|
|
|
/* VRAM data isn't decoded directly by libp7 Protocol 7.00 Packet I/O utilities,
|
|
* although some functions such as `p7_getscreen` do decode it to a 32-bit
|
|
* pixel matrix (easier for the user, and extensible).
|
|
*
|
|
* Here are the known VRAM types you could get using libp7: */
|
|
|
|
# define p7_pictype_1bit 0x01
|
|
# define p7_pictype_2bit 0x02
|
|
# define p7_pictype_3bit 0x03
|
|
# define p7_pictype_16bit 0x10
|
|
typedef int p7_pictype_t;
|
|
/* ************************************************************************** */
|
|
/* libp7 Protocol 7.00 packet sending utilities */
|
|
/* ************************************************************************** */
|
|
/* These are the base functions to send a packet.
|
|
* Unless `resp` is zero, it will also get the response to the packet,
|
|
* and store its info in the handle's packet representation.
|
|
*
|
|
* You shouldn't use them directly to send a packet, but here they are: */
|
|
|
|
extern int p7_seven_send_basic(p7_handle_t *handle,
|
|
p7_seven_type_t type, p7ushort_t subtype, int resp);
|
|
extern int p7_seven_send_ext(p7_handle_t *handle,
|
|
p7_seven_type_t type, p7ushort_t subtype,
|
|
const void *data, p7ushort_t size, int resp);
|
|
|
|
/* Send checks.
|
|
* Initial checks are useful to check if there is another device speaking P7
|
|
* at the other end of the line.
|
|
* Waiting checks are for the other device which is waiting for a command
|
|
* not to timeout (which takes six minutes). */
|
|
|
|
extern int p7_seven_send_check(p7_handle_t *handle);
|
|
# define p7_seven_send_ini_check(H) \
|
|
(p7_seven_send_basic((H), p7_seven_type_check, p7_seven_chk_ini, 1))
|
|
|
|
/* Send acknowledgements (ACK packets).
|
|
* Basic ACK packets are used for plenty of things (`resp` should always be
|
|
* different from zero, as zero for this is used by data exchanging functions).
|
|
* Extended ACK is used for sending server information, usually as a response
|
|
* to the 0x01 command (sys_getinfo). */
|
|
|
|
# define p7_seven_send_ack(H, R) \
|
|
(p7_seven_send_basic((H), p7_seven_type_ack, 0x00, (R)))
|
|
# define p7_seven_confirm_ow(H) \
|
|
(p7_seven_send_basic((H), p7_seven_type_ack, 0x01, 1))
|
|
extern int p7_seven_send_eack(p7_handle_t *handle, p7_server_t *info);
|
|
|
|
/* Send negative acknowledgements (NAK packets).
|
|
* These are used to report errors. */
|
|
|
|
# define p7_seven_send_err(H, C) \
|
|
(p7_seven_send_basic((H), p7_seven_type_nak, (C), 1))
|
|
# define p7_seven_deny_ow(H) \
|
|
(p7_seven_send_err((H), p7_seven_err_dont_overwrite))
|
|
|
|
/* Send termination packets.
|
|
* Will end the communication from the handle point of view. */
|
|
|
|
# define p7_seven_send_term_because(H, R) \
|
|
(p7_seven_send_basic((H), p7_seven_type_end, (R), 1))
|
|
# define p7_seven_send_term(H) \
|
|
(p7_seven_send_term_because((H), p7_seven_term_default))
|
|
|
|
/* Send a roleswap notice.
|
|
* Will pass the handle in passive mode. */
|
|
|
|
# define p7_seven_send_roleswp(H) \
|
|
(p7_seven_send_basic((H), p7_seven_type_swp, 0, 1))
|
|
# define p7_seven_send_swp(H) (p7_seven_send_roleswp(H))
|
|
|
|
/* Here are the base functions for sending a command.
|
|
* There are specific command-sending in `libp7/protocol/seven/commands.h`,
|
|
* so if you're using a classical command, you should use them instead. */
|
|
|
|
extern int p7_seven_send_cmd(p7_handle_t *handle, p7ushort_t subtype);
|
|
extern int p7_seven_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);
|
|
|
|
# include <libp7/protocol/seven/commands.h>
|
|
/* ************************************************************************** */
|
|
/* Packet flows */
|
|
/* ************************************************************************** */
|
|
/* Once the communication is initialized (`p7_init` with the
|
|
* `p7_flag_active | p7_flag_check` flags takes care of that),
|
|
* Protocol 7.00 is basically a set of packet flows.
|
|
*
|
|
* A packet flow always start with a command from the active side to the
|
|
* passive side. Then, once the command is ACK-ed, according to the command,
|
|
* different packet flows can occur. Here are a few characteristic examples:
|
|
*
|
|
* - Simple action. For example, file removing require nothing after the
|
|
* command confirmation;
|
|
* - File sending. After the overwrite flow, the active side sends data
|
|
* packets containing the file data (`p7_send_buffer`/`p7_send_data`);
|
|
* - File receiving. The active side sends a role swap packet, then the
|
|
* server (now active) does the file sending procedure (with command). Once
|
|
* it has finished sending the file, it swaps roles again;
|
|
* - File listing. The active side sends a role swap packet, then the
|
|
* server (now active) sends file information commands for each entry.
|
|
* Once it has finished, it swap roles again.
|
|
*
|
|
* If you have finished doing what you wanted to do and the communication is
|
|
* still active, send an END packet, to which the other calculator should
|
|
* respond with an ACK. */
|
|
/* ************************************************************************** */
|
|
/* libp7 Protocol 7.00 packet flow utilities */
|
|
/* ************************************************************************** */
|
|
/* Send and receive data, using buffers (see `libp7/buffer.h`).
|
|
* This will automatically divide your data into packets, or make up the
|
|
* data from packets.
|
|
*
|
|
* Packet shifting (enabled with `shift != 0`) is a technique discovered by
|
|
* Nessotrin (from Planète Casio), and made accessible by Cakeisalie5 in
|
|
* libp7. It makes data exchanges quicker.
|
|
* It is advised not to use it for receiving data, or for sensitive
|
|
* data. */
|
|
|
|
extern int p7_seven_send_buffer(p7_handle_t *handle, const p7_buffer_t *buffer,
|
|
int shift, p7_disp_t disp);
|
|
extern int p7_seven_get_buffer(p7_handle_t *handle, const p7_buffer_t *buffer,
|
|
p7uint_t size, int shift, p7_disp_t disp);
|
|
|
|
/* Send and receive data, using memory areas.
|
|
* Beyond the buffer/memory difference, those and the previous ones are
|
|
* basically the same thing. */
|
|
|
|
extern int p7_seven_send_data(p7_handle_t *handle, const void *vbuf, \
|
|
p7uint_t size, int shift, void (*disp)(p7ushort_t, p7ushort_t));
|
|
extern int p7_seven_get_data(p7_handle_t *handle, void *buf, p7uint_t size,
|
|
int shift, p7_disp_t disp);
|
|
|
|
# ifdef __cplusplus
|
|
}
|
|
# endif
|
|
#endif /* LIBP7_PROTOCOL_SEVEN_H */
|