/* (c) Azq2, 03 Feb 2013 */
#include "main.h"
char atheader[] = "AT%FS,";
char log_buffer[512];
FILE *fp = 0;
int last_offset = 0;
int lprintf(const char *format, ...) {
if (!format)
return EOF;
va_list arg_ptr;
va_start(arg_ptr, format);
int ret = vsprintf(log_buffer, format, arg_ptr);
va_end(arg_ptr);
FILE *fp = fopen(LOG_FILE, "a+");
if (fp) {
fwrite(log_buffer, 1, strlen(log_buffer), fp);
fclose(fp);
}
return ret;
}
unsigned char hex2char(unsigned char hex) {
switch (hex) {
case '0': return 0x00;
case '1': return 0x01;
case '2': return 0x02;
case '3': return 0x03;
case '4': return 0x04;
case '5': return 0x05;
case '6': return 0x06;
case '7': return 0x07;
case '8': return 0x08;
case '9': return 0x09;
case 'A': return 0x0A;
case 'a': return 0x0A;
case 'B': return 0x0B;
case 'b': return 0x0B;
case 'C': return 0x0C;
case 'c': return 0x0C;
case 'D': return 0x0D;
case 'd': return 0x0D;
case 'E': return 0x0E;
case 'e': return 0x0E;
case 'F': return 0x0F;
case 'f': return 0x0F;
default : return 0x00;
}
}
int at_handler(ATC *atc) {
char buff[1024];
int offset = strlen(atheader);
if (strlen(atc -> at_command) < offset + 1)
return 0;
switch (atc_reqcheck(atc)) {
case 1: case 2: case 3: case 4:
switch (atc -> at_command[offset]) {
// Сброс
case '!':
{
// lprintf("[ATFS] Reset!\r\n", atc -> at_command);
if (fp) {
// flock(fileno(fp), LOCK_UN);
fclose(fp);
fp = 0;
}
last_offset = 0;
atc_sendanswer(atc -> dev, ATFS_ANSWER_OK, 0);
}
break;
// Запустить эльф
case 'X':
{
unsigned int start, ret, error;
char *argv[2];
argv[0] = strdup(atc -> at_command + offset + 1);
argv[1] = NULL;
strcpy(argv[0], atc -> at_command + offset + 1);
error = execelf(atc -> at_command + offset + 1, 1, argv, &start, &ret);
// lprintf("[ATFS] Exec elf \"%s\", error=%d, start=0x%08X, return=0x%08X\n", atc -> at_command + offset + 1, error, start, ret);
sprintf(buff, "%08X%08X%08X", error, start, ret);
atc_sendanswer(atc -> dev, buff, 0);
if (argv[0]) {
free(argv[0]);
argv[0] = NULL;
}
}
break;
// Окрыть файл
case 'O':
{
char path[512], mode[8];
if (fp) {
// flock(fileno(fp), LOCK_UN);
fclose(fp);
fp = NULL;
}
if (sscanf(atc -> at_command + offset + 1, "%[^,],%s", mode, path) == 2) {
fp = fopen(path, mode);
if (!fp) {
atc_sendanswer(atc -> dev, ATFS_ANSWER_FATAL_ERROR, 0);
lprintf("[ATFS] Can't open file: \"%s\" with attributes \"%s\"\n", path, mode);
} else {
// flock(fileno(fp), LOCK_EX);
atc_sendanswer(atc -> dev, ATFS_ANSWER_OK, 0);
// lprintf("[ATFS] Open file, mode=\"%s\", path=\"%s\"\n", mode, path);
}
} else {
atc_sendanswer(atc -> dev, ATFS_ANSWER_FATAL_ERROR, 0);
lprintf("[ATFS] Invalid args: \"%s\"\r\n", atc -> at_command + offset + 1);
}
}
break;
// Записать в файл
case 'W':
{
char *buff;
unsigned char *decoded_buff;
unsigned int addr, size, crc, buff_crc, buff_size;
if (fp) {
if (sscanf(atc -> at_command + offset + 1, "%08X%08X%08X", &addr, &size, &crc) == 3) {
// lprintf("[ATFS] Write data, size=%d, crc=%08X\n", size, crc);
buff = atc -> at_command + offset + 1 + 24;
buff_size = strlen(buff);
if (buff_size % 2 == 0 && size == buff_size / 2) {
buff_crc = crc32((unsigned char *)buff, buff_size);
if (crc == buff_crc) {
if (last_offset > addr) {
lprintf("[ATFS] Block %08X-%08X may be already writed!\n", addr, addr + size);
atc_sendanswer(atc -> dev, ATFS_ANSWER_OK, 0);
break;
}
decoded_buff = malloc(buff_size / 2);
for (int i = 0, j = 0; i < buff_size; i += 2)
decoded_buff[j++] = hex2char(buff[i]) << 4 | hex2char(buff[i + 1]);
int writted = fwrite(decoded_buff, 1, buff_size / 2, fp);
if (writted == buff_size / 2) {
atc_sendanswer(atc -> dev, ATFS_ANSWER_OK, 0);
last_offset = addr;
// lprintf("[ATFS] Writted %d bytes!\n", writted);
} else {
atc_sendanswer(atc -> dev, ATFS_ANSWER_FATAL_ERROR, 0);
lprintf("[ATFS] Can't write block! Written only % bytes of %d\n", writted, buff_size / 2);
}
if (decoded_buff != 0) {
free(decoded_buff);
decoded_buff = 0;
}
} else {
atc_sendanswer(atc -> dev, ATFS_ANSWER_ERROR, 0);
lprintf("[ATFS] Invalid crc32! %08X != %08X\n", crc, buff_crc);
}
} else {
atc_sendanswer(atc -> dev, ATFS_ANSWER_ERROR, 0);
if (buff_size % 2 != 0)
lprintf("[ATFS] Block size is not a multiple of 2. \n", buff_size, size);
lprintf("[ATFS] Received only %d bytes of %d\n", buff_size / 2, size);
}
} else {
atc_sendanswer(atc -> dev, ATFS_ANSWER_FATAL_ERROR, 0);
lprintf("[ATFS] Invalid args: %s\r\n", atc -> at_command);
}
} else {
atc_sendanswer(atc -> dev, ATFS_ANSWER_FATAL_ERROR, 0);
lprintf("[ATFS] Write file: file already not opened!\r\n");
}
}
break;
default:
atc_sendanswer(atc -> dev, ATFS_ANSWER_FATAL_ERROR, 0);
lprintf("[ATFS] Invalid command: %s\r\n", atc -> at_command);
break;
}
break;
default:
sprintf(buff, "Invalid AT command: %s\r\n", atc -> at_command);
atc_sendanswer(atc -> dev, buff, 0);
lprintf(buff);
break;
}
return 0;
}
int main(int argc, char *argv[]) {
unlock_mem_access();
ats -> string = atheader;
ats -> handler = at_handler;
lock_mem_access();
return 0;
}