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/eack.c

295 lines
9.4 KiB
C

/* ****************************************************************************
* link/seven/eack.c -- extended ACK management.
* 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/>.
* ************************************************************************* */
#include "../link.h"
#include <string.h>
/* ---
* Raw layout of an extended ack data.
* --- */
typedef struct {
/* hardware identifier - ASCII */
unsigned char hwid[8];
/* processor identifier - ASCII */
unsigned char cpuid[16];
/* preprogrammed ROM capacity - ASCII-dec (Ko) */
unsigned char preprog_rom_capacity[8];
/* flash ROM capacity - ASCII-dec (Ko) */
unsigned char flash_rom_capacity[8];
/* RAM capacity - ASCII-dec (Ko) */
unsigned char ram_capacity[8];
/* preprogrammed ROM version - "xx.xx.xxxx" + 0xff bytes */
unsigned char preprog_rom_version[16];
/* bootcode version - "xx.xx.xxxx" + 0xff bytes */
unsigned char bootcode_version[16];
/* bootcode offset - ASCII-hex */
unsigned char bootcode_offset[8];
/* bootcode size - ASCII-hex (Ko) */
unsigned char bootcode_size[8];
/* OS version - "xx.xx.xxxx" + 0xff bytes */
unsigned char os_version[16];
/* OS offset - ASCII-hex */
unsigned char os_offset[8];
/* OS size - ASCII-hex (Ko) */
unsigned char os_size[8];
/* protocol version - "x.xx" */
unsigned char protocol_version[4];
/* product ID */
unsigned char product_id[16];
/* name set by user in SYSTEM (if not in exam mode) */
unsigned char username[16];
} packetdata_ackext_t;
/* ---
* Utilities.
* --- */
/**
* version_of_string:
* Get version from 16-bytes char buffer.
*
* data is not a string as it doesn't finish with an '\0'.
*
* @arg ver the version destination
* @arg data the raw version data ("xx.xx.xx" + type)
*/
CASIO_LOCAL void version_of_string(casio_version_t *ver, const unsigned char *data)
{
casio_decode_version(ver, (const char*)data);
}
/**
* string_of_version:
* Put version in 16-bytes char buffer.
*
* @arg ver the version source.
* @arg data the raw version data destination ("xx.xx.xx" + type).
*/
CASIO_LOCAL void string_of_version(unsigned char *data,
const casio_version_t *ver)
{
casio_encode_version((char*)data, ver);
memset(&data[10], '\xFF', 6);
}
/* ---
* Send ACK packets.
* --- */
/**
* casio_seven_send_eack:
* Sends an extended ack.
*
* @arg handle the link handle
* @arg info the link information to return.
* @return the error code (0 if ok)
*/
int CASIO_EXPORT casio_seven_send_eack(casio_link_t *handle,
casio_link_info_t *info)
{
packetdata_ackext_t raw;
/* initialize the structure with 0xFFs */
memset(&raw, 0xFF, sizeof(packetdata_ackext_t));
/* put in the structure */
memcpy(raw.hwid, info->casio_link_info_hwid,
strnlen(info->casio_link_info_hwid, 8));
memcpy(raw.cpuid, info->casio_link_info_cpuid,
strnlen(info->casio_link_info_cpuid, 16));
if (!(info->casio_link_info_wiped & casio_link_info_wiped_preprog)) {
casio_putascii(raw.preprog_rom_capacity,
info->casio_link_info_rom_capacity, 8);
string_of_version(raw.preprog_rom_version,
&info->casio_link_info_rom_version);
}
casio_putascii(raw.flash_rom_capacity,
casio_gethex(info->casio_link_info_flash_rom_capacity / 1024), 8);
casio_putascii(raw.ram_capacity,
casio_gethex(info->casio_link_info_ram_capacity / 1024), 8);
if (!(info->casio_link_info_wiped & casio_link_info_wiped_bootcode)) {
string_of_version(raw.bootcode_version,
&info->casio_link_info_bootcode_version);
casio_putascii(raw.bootcode_offset,
info->casio_link_info_bootcode_offset, 8);
casio_putascii(raw.bootcode_size,
casio_gethex(info->casio_link_info_bootcode_size / 1024), 8);
}
if (!(info->casio_link_info_wiped & casio_link_info_wiped_os)) {
string_of_version(raw.os_version, &info->casio_link_info_os_version);
casio_putascii(raw.os_offset, info->casio_link_info_os_offset, 8);
casio_putascii(raw.os_size,
casio_gethex(info->casio_link_info_os_size / 1024), 8);
}
memcpy(raw.protocol_version, "7.00", 4);
memcpy(raw.product_id, info->casio_link_info_product_id,
strnlen(info->casio_link_info_product_id, 16));
memcpy(raw.username, info->casio_link_info_username,
strnlen(info->casio_link_info_username, 16));
/* send the packet */
return (casio_seven_send_ext(handle, casio_seven_type_ack, 0x02, &raw,
sizeof(packetdata_ackext_t), 1));
}
/* ---
* Decode an ACK packet.
* --- */
/**
* cpy_string:
* Copy a string terminated with 0xFFs, with a maximum size.
*
* @arg dest the destination string.
* @arg src the source string.
* @arg n the maximum size of the string.
*/
CASIO_LOCAL void cpy_string(char *dest, const char *src, size_t n)
{
const char *l = memchr(src, 0xFF, n);
memset(dest, 0, n + 1);
memcpy(dest, src, l ? (size_t)(l - src) : n);
}
/**
* casio_seven_decode_ack:
* Get data from ack data field.
*
* Layout is described in the fxReverse projet documentation.
*
* @arg handle the handle
* @arg data the raw data
* @arg data_size the raw data size
* @return if there was an error
*/
int CASIO_EXPORT casio_seven_decode_ack(casio_link_t *handle,
const unsigned char *data, unsigned int data_size)
{
casio_seven_packet_t *packet = &handle->casio_link_response;
casio_link_info_t *info = &packet->casio_seven_packet_info;
const packetdata_ackext_t *d = (const void*)data;
/* check the data size */
if (data_size != sizeof(packetdata_ackext_t)) return (1);
info->casio_link_info_wiped = 0;
/* log */
msg((ll_info, "ack packet is extended"));
/* hardware identifier */
cpy_string(info->casio_link_info_hwid, (const char*)d->hwid, 8);
msg((ll_info, "hardware identifier is '%s'", info->casio_link_info_hwid));
/* processor identifier */
cpy_string(info->casio_link_info_cpuid, (const char*)d->cpuid, 16);
msg((ll_info, "cpu identifier is '%s'", info->casio_link_info_cpuid));
/* preprogrammed ROM information is wiped */
if (d->preprog_rom_version[2] == 0xFF)
info->casio_link_info_wiped |= casio_link_info_wiped_preprog;
ifmsg(info->casio_link_info_wiped & casio_link_info_wiped_preprog,
(ll_info, "Preprogrammed ROM information looks wiped out!"))
elsemsg((ll_info, "Preprogrammed ROM version is %.10s",
d->preprog_rom_version))
/* preprogrammed ROM capacity */
info->casio_link_info_rom_capacity =
casio_getascii(d->preprog_rom_capacity, 8) * 1000;
msg((ll_info, "preprogrammed ROM capacity is %luo",
info->casio_link_info_rom_capacity));
/* preprogrammed ROM version */
version_of_string(&info->casio_link_info_rom_version,
d->preprog_rom_version);
/* flash ROM capacity */
info->casio_link_info_flash_rom_capacity =
casio_getdec(casio_getascii(d->flash_rom_capacity, 8)) * 1024;
msg((ll_info, "flash ROM capacity is %luKiB",
info->casio_link_info_flash_rom_capacity / 1024));
/* RAM capacity */
info->casio_link_info_ram_capacity =
casio_getdec(casio_getascii(d->ram_capacity, 8)) * 1024;
msg((ll_info, "RAM capacity is %luKiB",
info->casio_link_info_ram_capacity / 1024));
/* bootcode information is wiped */
if (d->bootcode_version[2] == 0xFF)
info->casio_link_info_wiped |= casio_link_info_wiped_bootcode;
ifmsg(info->casio_link_info_wiped & casio_link_info_wiped_bootcode,
(ll_info, "Bootcode information looks wiped out!"))
elsemsg((ll_info, "Bootcode version is %.10s", d->bootcode_version))
/* bootcode version */
version_of_string(&info->casio_link_info_bootcode_version,
d->bootcode_version);
/* bootcode offset */
info->casio_link_info_bootcode_offset =
casio_getascii(d->bootcode_offset, 8);
msg((ll_info, "bootcode offset is 0x%08lX",
info->casio_link_info_bootcode_offset));
/* bootcode size */
info->casio_link_info_bootcode_size =
casio_getdec(casio_getascii(d->bootcode_size, 8)) * 1024;
msg((ll_info, "bootcode size is %luKiB",
info->casio_link_info_bootcode_size / 1024));
/* OS information is wiped */
if (d->os_version[2] == 0xFF)
info->casio_link_info_wiped |= casio_link_info_wiped_os;
ifmsg(info->casio_link_info_wiped & casio_link_info_wiped_os,
(ll_info, "OS information looks wiped out!"))
elsemsg((ll_info, "OS version is %.10s", d->os_version))
/* OS version */
version_of_string(&info->casio_link_info_os_version, d->os_version);
/* OS offset */
info->casio_link_info_os_offset = casio_getascii(d->os_offset, 8);
msg((ll_info, "OS offset is 0x%08lX" , info->casio_link_info_os_offset));
/* OS size */
info->casio_link_info_os_size =
casio_getdec(casio_getascii(d->os_size, 8)) * 1024;
msg((ll_info, "OS size is %luKiB", info->casio_link_info_os_size / 1024));
/* product ID */
cpy_string(info->casio_link_info_product_id,
(const char*)d->product_id, 16);
msg((ll_info, "product ID is %s", info->casio_link_info_product_id));
/* username */
cpy_string(info->casio_link_info_username, (const char*)d->username, 16);
msg((ll_info, "username is %s", info->casio_link_info_username));
/* no error */
return (0);
}