mirror of
https://github.com/solokeys/openpgp.git
synced 2026-03-11 17:15:00 -07:00
449 lines
9.1 KiB
C++
449 lines
9.1 KiB
C++
/*
|
|
Copyright 2019 SoloKeys Developers
|
|
|
|
Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
|
http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
|
http://opensource.org/licenses/MIT>, at your option. This file may not be
|
|
copied, modified, or distributed except according to those terms.
|
|
*/
|
|
|
|
#include <sys/time.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <netinet/in.h>
|
|
#include <time.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <fcntl.h>
|
|
#include <dirent.h>
|
|
#include <fnmatch.h>
|
|
#include "opgpdevice.h"
|
|
|
|
#define SPIFFS_MODE
|
|
|
|
#ifdef SPIFFS_MODE
|
|
#include <spiffs.h>
|
|
static spiffs fs;
|
|
static uint8_t fsbuf[2048*10] = {0};
|
|
static char *SpiffsFileName = (char *)"filesystem.spiffs";
|
|
#endif
|
|
|
|
#define LOG_PAGE_SIZE 64
|
|
|
|
bool ifileexist(char* name);
|
|
int ireadfile(char* name, uint8_t * buf, size_t max_size, size_t *size);
|
|
int iwritefile(char* name, uint8_t * buf, size_t size);
|
|
int sprintfs();
|
|
|
|
static u8_t spiffs_work_buf[LOG_PAGE_SIZE * 2];
|
|
static u8_t spiffs_fds[32 * 4];
|
|
static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE + 32) * 4];
|
|
|
|
static s32_t hw_spiffs_read(u32_t addr, u32_t size, u8_t *dst) {
|
|
memcpy(dst, fsbuf + addr, size);
|
|
return SPIFFS_OK;
|
|
}
|
|
|
|
static s32_t hw_spiffs_write(u32_t addr, u32_t size, u8_t *src) {
|
|
memcpy(fsbuf + addr, src, size);
|
|
return SPIFFS_OK;
|
|
}
|
|
|
|
static s32_t hw_spiffs_erase(u32_t addr, u32_t size) {
|
|
memset(fsbuf + addr, 0xff, size);
|
|
return SPIFFS_OK;
|
|
}
|
|
|
|
void hw_spiffs_mount() {
|
|
spiffs_config cfg;
|
|
cfg.phys_size = 10*2048; // use all spi flash
|
|
cfg.phys_addr = 0; // start spiffs at start of spi flash
|
|
cfg.phys_erase_block = 2048; // according to datasheet
|
|
cfg.log_block_size = 2048; // let us not complicate things
|
|
cfg.log_page_size = LOG_PAGE_SIZE; // as we said
|
|
|
|
cfg.hal_read_f = hw_spiffs_read;
|
|
cfg.hal_write_f = hw_spiffs_write;
|
|
cfg.hal_erase_f = hw_spiffs_erase;
|
|
|
|
int res = SPIFFS_mount(&fs,
|
|
&cfg,
|
|
spiffs_work_buf,
|
|
spiffs_fds,
|
|
sizeof(spiffs_fds),
|
|
spiffs_cache_buf,
|
|
sizeof(spiffs_cache_buf),
|
|
0);
|
|
printf("mount res: %i\n", res);
|
|
|
|
if (res || !SPIFFS_mounted(&fs)) {
|
|
res = SPIFFS_format(&fs);
|
|
printf("format res: %i\n", res);
|
|
}
|
|
|
|
uint32_t total = 0;
|
|
uint32_t used = 0;
|
|
SPIFFS_info(&fs, &total, &used);
|
|
printf("Mounted OK. Memory total: %d used: %d\n", total, used);
|
|
sprintfs();
|
|
}
|
|
|
|
int hwinit() {
|
|
#ifdef SPIFFS_MODE
|
|
memset(fsbuf, 0xff, sizeof(fsbuf));
|
|
|
|
if (ifileexist(SpiffsFileName)) {
|
|
size_t size = 0;
|
|
ireadfile(SpiffsFileName, fsbuf, sizeof(fsbuf), &size);
|
|
if (size != sizeof(fsbuf))
|
|
memset(fsbuf, 0xff, sizeof(fsbuf));
|
|
|
|
printf("Loaded OK\n");
|
|
}
|
|
|
|
hw_spiffs_mount();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
int spiffs_save() {
|
|
return iwritefile(SpiffsFileName, fsbuf, sizeof(fsbuf));
|
|
}
|
|
|
|
int udp_server()
|
|
{
|
|
static int run_already = 0;
|
|
static int fd = -1;
|
|
if (run_already && fd >= 0) return fd;
|
|
run_already = 1;
|
|
|
|
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
|
|
perror( "socket failed" );
|
|
return 1;
|
|
}
|
|
|
|
struct timeval read_timeout;
|
|
read_timeout.tv_sec = 0;
|
|
read_timeout.tv_usec = 10;
|
|
if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &read_timeout, sizeof(struct timeval)) != 0)
|
|
{
|
|
perror( "setsockopt" );
|
|
exit(1);
|
|
}
|
|
|
|
struct sockaddr_in serveraddr;
|
|
memset( &serveraddr, 0, sizeof(serveraddr) );
|
|
serveraddr.sin_family = AF_INET;
|
|
serveraddr.sin_port = htons( 8111 );
|
|
serveraddr.sin_addr.s_addr = htonl( INADDR_ANY );
|
|
|
|
if ( bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
|
|
perror( "bind failed" );
|
|
exit(1);
|
|
}
|
|
return fd;
|
|
}
|
|
|
|
int udp_recv(int fd, uint8_t * buf, int size)
|
|
{
|
|
|
|
fd_set input;
|
|
FD_ZERO(&input);
|
|
FD_SET(fd, &input);
|
|
struct timeval timeout;
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = 100;
|
|
int n = select(fd + 1, &input, NULL, NULL, &timeout);
|
|
if (n == -1) {
|
|
perror("select\n");
|
|
exit(1);
|
|
} else if (n == 0)
|
|
return 0;
|
|
if (!FD_ISSET(fd, &input))
|
|
{
|
|
|
|
}
|
|
int length = recvfrom( fd, buf, size, 0, NULL, 0 );
|
|
if ( length < 0 ) {
|
|
perror( "recvfrom failed" );
|
|
exit(1);
|
|
}
|
|
return length;
|
|
}
|
|
|
|
|
|
void udp_send(int fd, uint8_t * buf, int size)
|
|
{
|
|
struct sockaddr_in serveraddr;
|
|
memset( &serveraddr, 0, sizeof(serveraddr) );
|
|
serveraddr.sin_family = AF_INET;
|
|
serveraddr.sin_port = htons( 7112 );
|
|
serveraddr.sin_addr.s_addr = htonl( 0x7f000001 ); // (127.0.0.1)
|
|
|
|
if (sendto( fd, buf, size, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
|
|
perror( "sendto failed" );
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
static int fd = 0;
|
|
void ccid_init()
|
|
{
|
|
fd = udp_server();
|
|
}
|
|
|
|
uint32_t ccid_recv(uint8_t * msg)
|
|
{
|
|
int l;
|
|
l = udp_recv(fd, msg, 1024);
|
|
return l;
|
|
}
|
|
|
|
void ccid_send(uint8_t * msg, uint32_t sz)
|
|
{
|
|
udp_send(fd, msg, sz);
|
|
}
|
|
|
|
void make_work_directory(char* dir) {
|
|
if (access(dir, F_OK) != 0) {
|
|
mkdir(dir, 0777);
|
|
}
|
|
}
|
|
|
|
bool ifileexist(char* name) {
|
|
char fname[100] = {0};
|
|
char dir[] = "./data/";
|
|
make_work_directory(dir);
|
|
|
|
strcpy(fname, dir);
|
|
strcat(fname, name);
|
|
|
|
// check if it exist and have read permission
|
|
if (access(fname, R_OK) != 0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool sfileexist(char* name) {
|
|
spiffs_DIR d;
|
|
struct spiffs_dirent e;
|
|
struct spiffs_dirent *pe = &e;
|
|
|
|
SPIFFS_opendir(&fs, "/", &d);
|
|
while ((pe = SPIFFS_readdir(&d, pe))) {
|
|
if (0 == strcmp(name, (char *)pe->name)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool fileexist(char* name) {
|
|
#ifdef SPIFFS_MODE
|
|
return sfileexist(name);
|
|
#else
|
|
return ifileexist(name);
|
|
#endif
|
|
}
|
|
|
|
int ireadfile(char* name, uint8_t * buf, size_t max_size, size_t *size) {
|
|
|
|
char fname[100] = {0};
|
|
char dir[] = "./data/";
|
|
make_work_directory(dir);
|
|
|
|
strcpy(fname, dir);
|
|
strcat(fname, name);
|
|
|
|
// check if it exist and have read permission
|
|
if (access(fname, R_OK) != 0)
|
|
return 1;
|
|
|
|
FILE *f = fopen(fname, "r");
|
|
if (f <= 0)
|
|
return 2;
|
|
|
|
*size = fread(buf, 1, max_size, f);
|
|
fclose(f);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sreadfile(char* name, uint8_t * buf, size_t max_size, size_t *size) {
|
|
*size = 0;
|
|
|
|
spiffs_file fd = SPIFFS_open(&fs, name, SPIFFS_RDWR, 0);
|
|
if (fd < 0)
|
|
return fd;
|
|
|
|
int res = SPIFFS_read(&fs, fd, buf, max_size);
|
|
|
|
*size = res;
|
|
int cres = SPIFFS_close(&fs, fd) < 0;
|
|
if (cres < 0)
|
|
return cres;
|
|
|
|
return (res >= 0) ? 0 : res;
|
|
}
|
|
|
|
int readfile(char* name, uint8_t * buf, size_t max_size, size_t *size) {
|
|
#ifdef SPIFFS_MODE
|
|
return sreadfile(name, buf, max_size, size);
|
|
#else
|
|
return ireadfile(name, buf, max_size, size);
|
|
#endif
|
|
}
|
|
|
|
int iwritefile(char* name, uint8_t * buf, size_t size) {
|
|
char fname[100] = {0};
|
|
char dir[] = "./data/";
|
|
make_work_directory(dir);
|
|
|
|
strcpy(fname, dir);
|
|
strcat(fname, name);
|
|
|
|
FILE *f = fopen(fname, "w");
|
|
if (f <= 0)
|
|
return 2;
|
|
|
|
size_t sz = fwrite(buf, 1, size, f);
|
|
fclose(f);
|
|
|
|
if (sz != size)
|
|
return 3;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int swritefile(char* name, uint8_t * buf, size_t size) {
|
|
spiffs_file fd = SPIFFS_open(&fs, name, SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0);
|
|
if (fd < 0)
|
|
return fd;
|
|
|
|
int res = SPIFFS_write(&fs, fd, buf, size);
|
|
|
|
int cres = SPIFFS_close(&fs, fd) < 0;
|
|
if (cres < 0)
|
|
return cres;
|
|
|
|
// debug only!
|
|
spiffs_save();
|
|
|
|
return (res >= 0) ? 0 : res;
|
|
}
|
|
|
|
int writefile(char* name, uint8_t * buf, size_t size) {
|
|
#ifdef SPIFFS_MODE
|
|
return swritefile(name, buf, size);
|
|
#else
|
|
return iwritefile(name, buf, size);
|
|
#endif
|
|
}
|
|
|
|
int ideletefile(char* name) {
|
|
char fname[100] = {0};
|
|
char dir[] = "./data/";
|
|
make_work_directory(dir);
|
|
|
|
strcpy(fname, dir);
|
|
strcat(fname, name);
|
|
|
|
remove(fname);
|
|
return 0;
|
|
}
|
|
int deletefile(char* name) {
|
|
#ifdef SPIFFS_MODE
|
|
return SPIFFS_remove(&fs, name);
|
|
#else
|
|
return ideletefile(name);
|
|
#endif
|
|
}
|
|
|
|
int ideletefiles(char* name) {
|
|
char fname[100] = {0};
|
|
char dir[] = "./data/";
|
|
make_work_directory(dir);
|
|
|
|
DIR *dirp=opendir(dir);
|
|
struct dirent entry;
|
|
struct dirent *dp=&entry;
|
|
while((dp = readdir(dirp)))
|
|
{
|
|
if((fnmatch(name, dp->d_name,0)) == 0)
|
|
{
|
|
strcpy(fname, dir);
|
|
strcat(fname, dp->d_name);
|
|
remove(fname);
|
|
}
|
|
}
|
|
closedir(dirp);
|
|
|
|
strcpy(fname, dir);
|
|
strcat(fname, name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sprintfs() {
|
|
spiffs_DIR d;
|
|
struct spiffs_dirent e;
|
|
struct spiffs_dirent *pe = &e;
|
|
|
|
uint32_t total = 0;
|
|
uint32_t used = 0;
|
|
SPIFFS_info(&fs, &total, &used);
|
|
printf_device("Memory total: %d used: %d\n", total, used);
|
|
|
|
SPIFFS_opendir(&fs, "/", &d);
|
|
while ((pe = SPIFFS_readdir(&d, pe))) {
|
|
printf_device(" [%4d] %s\n", pe->size, pe->name);
|
|
}
|
|
SPIFFS_closedir(&d);
|
|
return 0;
|
|
}
|
|
|
|
int sdeletefiles(char* name) {
|
|
spiffs_DIR d;
|
|
struct spiffs_dirent e;
|
|
struct spiffs_dirent *pe = &e;
|
|
int res;
|
|
|
|
sprintfs();
|
|
|
|
SPIFFS_opendir(&fs, "/", &d);
|
|
while ((pe = SPIFFS_readdir(&d, pe))) {
|
|
if ((fnmatch(name, (char *)pe->name, 0)) == 0) {
|
|
fd = SPIFFS_open_by_dirent(&fs, pe, SPIFFS_RDWR, 0);
|
|
if (fd < 0)
|
|
return SPIFFS_errno(&fs);
|
|
res = SPIFFS_fremove(&fs, fd);
|
|
if (res < 0)
|
|
return SPIFFS_errno(&fs);
|
|
}
|
|
}
|
|
SPIFFS_closedir(&d);
|
|
return 0;
|
|
}
|
|
|
|
int deletefiles(char* name) {
|
|
#ifdef SPIFFS_MODE
|
|
return sdeletefiles(name);
|
|
#else
|
|
return ideletefiles(name);
|
|
#endif
|
|
}
|
|
|
|
int hwreboot() {
|
|
|
|
return 0;
|
|
}
|
|
|