cake
/
libcasio
Archived
1
1
Fork 0
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.
libcasio/lib/link/seven/send.c

254 lines
7.1 KiB
C

/* ****************************************************************************
* link/seven/send.c -- prepare and send a packet.
* Copyright (C) 2016-2017 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
*
* This file is part of libcasio.
* libcasio 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.
*
* libcasio 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 libcasio; if not, see <http://www.gnu.org/licenses/>.
*
* These functions are the one used behind the others to send a packet.
* ************************************************************************* */
#include "../link.h"
#include <stdio.h>
#include <string.h>
#define checksub8(BUF, SIZE) \
casio_checksum_sub(&((char*)(BUF))[1], (SIZE) - 3, 0)
/* Internal macros. */
#define buffer \
handle->casio_link_send_buffers[handle->casio_link_flags \
& casio_linkflag_sendalt]
#define buffer_size \
handle->casio_link_send_buffers_size[handle->casio_link_flags \
& casio_linkflag_sendalt]
#define switch_buffer() \
if (handle->casio_link_flags & casio_linkflag_shifted) \
handle->casio_link_flags = \
( handle->casio_link_flags & ~casio_linkflag_sendalt) | \
(~handle->casio_link_flags & casio_linkflag_sendalt);
/* ---
* Main functions.
* --- */
/**
* casio_seven_send_buf:
* Send a buffer.
*
* @arg handle the link handle
* @arg buf the buffer to send (NULL if normal buffer)
* @arg bufsize the buffer size
* @arg resp check response (is yes for 99.9% of the cases)
* @return if worked (0 if none)
*/
CASIO_LOCAL int casio_seven_send_buf(casio_link_t *handle,
const unsigned char *buf, size_t bufsize, int resp)
{
int err; int wasresend = 0, resp_err = 0, retries = 3;
/* check if handler is initialized */
if (!handle) return (casio_error_init);
/* check if user wants to shift
* with hack: if `buf` is non-NULL, we simply want to send
* a custom packet */
if (!buf && !resp) {
if (handle->casio_link_flags & casio_linkflag_shifted)
return (casio_error_shift);
else handle->casio_link_flags |= casio_linkflag_shifted;
}
/* get buffer */
if (!buf) {
buf = buffer;
bufsize = buffer_size;
}
/* sending loop */
while (1) {
/* log resend request */
if (wasresend) {
if (--retries < 0) {
msg((ll_error,
"Three retries in a row? Something is wrong."));
return (casio_error_damned);
}
switch_buffer();
buf = buffer; bufsize = buffer_size;
msg((ll_warn, "resend request was received, resend it goes"));
}
/* send prepared packet */
err = casio_write(handle->casio_link_stream, buf, bufsize, 0);
if (err) return (err);
/* set wasreset for logging */
wasresend = 1;
/* check if we want an answer */
if (!resp) break;
if ((resp_err = casio_seven_receive(handle, 1)))
break;
if (response.casio_seven_packet_type == casio_seven_type_nak
&& response.casio_seven_packet_code == casio_seven_err_resend)
continue;
break;
}
/* packet sending is finished */
if (!resp_err && handle->casio_link_curr_type == casio_seven_type_swp)
handle->casio_link_flags &= ~casio_linkflag_active;
return (resp_err);
}
/**
* casio_seven_send_basic:
* Send a non-extended packet.
*
* @arg handle the link handle
* @arg type the packet type
* @arg subtype the packet subtype
* @arg resp check response (is yes for 99.9% of the cases)
* @return if worked (0 if none)
*/
int CASIO_EXPORT casio_seven_send_basic(casio_link_t *handle,
casio_seven_type_t type, unsigned int subtype, int resp)
{
/* change buffer and prepare packet */
switch_buffer();
buffer[0] = (unsigned char)type;
casio_putascii(&buffer[1], subtype, 2);
buffer[3] = '0';
casio_putascii(&buffer[4], checksub8(buffer, 6), 2);
buffer_size = 6;
/* log packet */
msg((ll_info, "sending the following basic packet :"));
mem((ll_info, buffer, buffer_size));
/* send it */
handle->casio_link_curr_type = type;
return (casio_seven_send_buf(handle, NULL, 0, resp));
}
/**
* casio_seven_send_ext:
* Send an extended packet.
*
* @arg handle the link handle
* @arg type the packet type
* @arg subtype the packet subtype
* @arg data the packet data
* @arg size the packet data size
* @arg resp check response (is yes for 99.9% of the cases)
* @return if it worked
*/
int CASIO_EXPORT casio_seven_send_ext(casio_link_t *handle,
casio_seven_type_t type, unsigned int subtype,
const void *data, unsigned int size, int resp)
{
/* check if should be a binary zero at end of packet */
int binary_zero = (type == casio_seven_type_cmd
&& subtype == casio_seven_cmdosu_upandrun);
/* change buffer and prepare packet */
switch_buffer();
/* - first infos - */
buffer[0] = (unsigned char)type;
casio_putascii(&buffer[1], subtype, 2);
buffer[3] = '1';
/* - data - */
size = casio_seven_encoderaw(&buffer[8], data, size);
casio_putascii(&buffer[4], size, 4);
/* - checksum - */
casio_putascii(&buffer[8 + size], checksub8(buffer, 8 + size + 2), 2);
buffer_size = 8 + size + 2;
if (binary_zero) { buffer[buffer_size] = 0; buffer_size++; }
/* log packet */
msg((ll_info, "sending the following extended packet :"));
mem((ll_info, buffer, buffer_size));
/* send it */
handle->casio_link_curr_type = type;
return (casio_seven_send_buf(handle, NULL, 0, resp));
}
/**
* casio_seven_send_again:
* Send the last packet again.
*
* Useful for when resending wasn't managed in one of the previous functions.
* Only used for unshifting right now.
*
* @arg handle the link handle
* @return if it worked
*/
int CASIO_EXPORT casio_seven_send_again(casio_link_t *handle)
{
/* log packet */
msg((ll_info, "sending again the following packet :"));
mem((ll_info, buffer, buffer_size));
/* send it */
return (casio_seven_send_buf(handle, NULL, 0, 1));
}
/* ---
* Special packets.
* --- */
/**
* casio_seven_send_err_resend:
* Resend the resend error.
*
* @arg handle the handle to send the resend error for.
* @return the error code (0 if ok).
*/
int CASIO_EXPORT casio_seven_send_err_resend(casio_link_t *handle)
{
static const unsigned char resend_buf[] =
{casio_seven_type_nak, '0', '1', '0', '6', 'F', 0};
/* send packet */
msg((ll_info, "sending resend packet:"));
mem((ll_info, resend_buf, 6));
return (casio_seven_send_buf(handle, resend_buf, 6, 0));
}
/**
* casio_seven_send_timeout_check:
* Send a timeout check.
*
* @arg handle the handle to send the timeout check for.
* @return the error code (0 if ok).
*/
int CASIO_EXPORT casio_seven_send_timeout_check(casio_link_t *handle)
{
static const unsigned char check_buf[] =
{casio_seven_type_chk, '0', '1', '0', '6', 'F', 0};
/* send packet */
msg((ll_info, "sending timeout check packet:"));
mem((ll_info, check_buf, 6));
return (casio_seven_send_buf(handle, check_buf, 6, 0));
}