first commit

This commit is contained in:
pvvx 2017-04-22 16:54:00 +03:00
commit fa343db334
154 changed files with 18186 additions and 0 deletions

View file

@ -0,0 +1,258 @@
/*
* adc_tst.c
*
* Created on: 04/04/2017.
* Author: pvvx
*/
#include <platform_opts.h>
#include "rtl8195a.h"
#include "FreeRTOS.h"
#include "rtl8195a/rtl_libc.h"
//------------------------------------------------------------------------------
#include "objects.h"
#include "PinNames.h"
#include "hal_adc.h"
#include "analogin_api.h"
#include "strproc.h"
//------------------------------------------------------------------------------
analogin_t adc;
LOCAL void fATADI(int argc, char *argv[]) {
int count = 8;
int channel = 2;
union {
unsigned int ui[2];
unsigned short us[4];
}x;
uint16_t adcdat;
memset(&adc, 0, sizeof(adc));
// ConfigDebugErr |= (_DBG_ADC_|_DBG_GDMA_);
// ConfigDebugInfo |= (_DBG_ADC_|_DBG_GDMA_);
if (argc > 1) {
channel = atoi(argv[1]);
channel &= 0x03;
if(!channel) channel = 2;
}
if (argc > 2) {
count = atoi(argv[2]);
}
analogin_init(&adc, (channel+1) | (PORT_V << 4));
PSAL_ADC_HND pSalADCHND = &((&(adc.SalADCMngtAdpt))->pSalHndPriv->SalADCHndPriv);
uint32_t sum = 0;
for (uint32_t i = 1; i <= count; i++) {
RtkADCReceiveBuf(pSalADCHND, &x.ui);
adcdat = x.us[channel];
if((i % 8) == 0 || (i == count)) {
printf("0x%04x\n", adcdat);
} else {
printf("0x%04x, ", adcdat);
}
sum += adcdat;
}
analogin_deinit(&adc);
printf("ADC%d = 0x%04x\n", channel, sum / count);
// sys_adc_calibration(0, &channel, &count);
}
LOCAL void fATADD(int argc, char *argv[]) {
int count = 64;
int channel = 2;
uint16_t adcdat;
memset(&adc, 0, sizeof(adc));
// ConfigDebugErr |= (_DBG_ADC_|_DBG_GDMA_);
// ConfigDebugInfo |= (_DBG_ADC_|_DBG_GDMA_);
if (argc > 1) {
channel = atoi(argv[1]);
channel &= 0x03;
if(!channel) channel = 1;
}
if (argc > 2) {
count = atoi(argv[2]);
if (count <= 2) {
count = 64;
}
};
analogin_init(&adc, (channel+1) | (PORT_V << 4));
SAL_ADC_TRANSFER_BUF trbuf;
trbuf.pDataBuf = zalloc(count*4);
if(trbuf.pDataBuf) {
trbuf.DataLen = count/2; // x32 bit ?
trbuf.RSVD = 0;
adc.SalADCHndPriv.SalADCHndPriv.pRXBuf = &trbuf;
adc.SalADCHndPriv.SalADCHndPriv.OpType = ADC_DMA_TYPE;
adc.HalADCInitData.ADCEndian = ADC_DATA_ENDIAN_LITTLE; //ADC endian selection,
//but actually it's for 32-bit ADC data swap control
//1'b0: no swap,
//1'b1: swap the upper 16-bit and the lower 16-bit
// adc.HalADCInitData.ADCCompOnly = ADC_FEATURE_DISABLED; //ADC compare mode only enable (without FIFO enable)
// adc.HalADCInitData.ADCEnManul = ADC_FEATURE_ENABLED; // ADC_FEATURE_DISABLED; //ADC enable manually
// adc.HalADCInitData.ADCIdx = channel+1; //ADC index used (1..3 ?)
// adc.HalADCInitData.ADCBurstSz = 8; //ADC DMA operation threshold
// adc.HalADCInitData.ADCOneShotTD = 8; //ADC one shot mode threshold
// adc.HalADCInitData.ADCDataRate = 0; // 0xff; // ADC down sample data rate ??
adc.HalADCInitData.ADCAudioEn = ADC_FEATURE_ENABLED; //ADC audio mode enable // ADC_FEATURE_DISABLED
// adc.HalADCInitData.ADCOneShotEn = ADC_FEATURE_DISABLED; //ADC one shot mode threshold
adc.HalADCInitData.ADCInInput = ADC_FEATURE_ENABLED; //ADC Input is internal?
// adc.HalADCInitData.ADCEn = ADC_DISABLE; //ADC_ENABLE;
HalADCInit8195a(&adc.HalADCInitData);
/* Read Content */
HAL_ADC_READ32(REG_ADC_FIFO_READ);
HAL_ADC_READ32(REG_ADC_INTR_STS);
RtkADCReceive(&adc.SalADCHndPriv.SalADCHndPriv);
while(adc.SalADCHndPriv.SalADCHndPriv.DevSts != ADC_STS_IDLE);
uint16 * ptr = (uint16 *) trbuf.pDataBuf;
// RtkADCDMAInit(&adc.SalADCHndPriv.SalADCHndPriv);
for (uint32_t i = 1; i <= count; i++) {
if((i % 16) == 0 || (i == count)) {
printf("%04x\n", *ptr);
} else {
printf("%04x ", *ptr);
}
ptr++;
}
uint32_t sum = 0;
ptr = (uint16 *) trbuf.pDataBuf;
for (uint32_t i = 1; i <= count; i++) {
printf("%d\n", *ptr);
sum += *ptr;
ptr++;
if((i%512)==0) vTaskDelay(10);
}
/*
printf("OpType:\t\t%p\n", adc.SalADCHndPriv.SalADCHndPriv.OpType);
printf("pRXBuf:\t\t%p\n", adc.SalADCHndPriv.SalADCHndPriv.pRXBuf);
printf("pDataBuf:\t%p\n", adc.SalADCHndPriv.SalADCHndPriv.pRXBuf->pDataBuf);
printf("DataLen:\t%p\n", adc.SalADCHndPriv.SalADCHndPriv.pRXBuf->DataLen);
printf("ADCDataRate:\t%p\n", adc.HalADCInitData.ADCDataRate);
printf("ADCData:\t%p\n", adc.HalADCInitData.ADCData);
printf("ADCIdx:\t\t%p\n", adc.HalADCInitData.ADCIdx);
printf("ADCPWCtrl:\t%p\n", adc.HalADCInitData.ADCPWCtrl);
printf("ADCAnaParAd3:\t%p\n", adc.HalADCInitData.ADCAnaParAd3);
printf("ADC%d = 0x%04x\n", channel, analogin_read_u16(&adc));
printf("ADC%d = 0x%04x\n", channel, analogin_read_u16(&adc));
*/
analogin_deinit(&adc);
free(trbuf.pDataBuf);
printf("ADC%d = 0x%04x\n", channel, sum / count);
}
else {
error_printf("%s: malloc failed!\n", __func__);
};
// sys_adc_calibration(0, &channel, &count);
}
LOCAL void fATADC(int argc, char *argv[]) {
int count = 8;
int channel = 2;
uint16_t adcdat;
memset(&adc, 0, sizeof(adc));
// ConfigDebugErr |= (_DBG_ADC_|_DBG_GDMA_);
// ConfigDebugInfo |= (_DBG_ADC_|_DBG_GDMA_);
if (argc > 1) {
channel = atoi(argv[1]);
channel &= 0x03;
if(!channel) channel = 1;
}
if (argc > 2) {
count = atoi(argv[2]);
}
analogin_init(&adc, (channel+1) | (PORT_V << 4));
uint32_t sum = 0;
for (uint32_t i = 1; i <= count; i++) {
adcdat = analogin_read_u16(&adc);
if((i % 8) == 0 || (i == count)) {
printf("0x%04x\n", adcdat);
} else {
printf("0x%04x, ", adcdat);
}
sum += adcdat;
}
analogin_deinit(&adc);
printf("ADC%d = 0x%04x\n", channel, sum / count);
// sys_adc_calibration(0, &channel, &count);
}
LOCAL void fATSA(int argc, char *argv[]) {
// u32 tConfigDebugInfo = ConfigDebugInfo;
int channel;
char *ptmp;
u16 offset, gain, adcdat;
memset(&adc, 0, sizeof(adc));
if (argc < 2) {
printf("Usage: ATSA=CHANNEL(0~2)\n");
printf("Usage: ATSA=k_get\n");
printf("Usage: ATSA=k_set[offet(hex),gain(hex)]\n");
return;
}
if (strcmp(argv[1], "k_get") == 0) {
sys_adc_calibration(0, &offset, &gain);
// printf("[ATSA] offset = 0x%04X, gain = 0x%04X", offset, gain);
} else if (strcmp(argv[1], "k_set") == 0) {
if (argc != 4) {
printf("Usage: ATSA=k_set[offet(hex),gain(hex)]\n");
return;
}
offset = strtoul(argv[2], &ptmp, 16);
gain = strtoul(argv[3], &ptmp, 16);
sys_adc_calibration(1, &offset, &gain);
// printf("[ATSA] offset = 0x%04X, gain = 0x%04X", offset, gain);
} else {
channel = atoi(argv[1]);
if (channel < 0 || channel > 2) {
printf("Usage: ATSA=CHANNEL(0~2)\n");
return;
}
// Remove debug info massage
// ConfigDebugInfo = 0;
if (channel == 0)
analogin_init(&adc, AD_1);
else if (channel == 1)
analogin_init(&adc, AD_2);
else
analogin_init(&adc, AD_3);
// analogin_read_u16(&adc);
adcdat = analogin_read_u16(&adc) >> 4;
analogin_deinit(&adc);
// Recover debug info massage
// ConfigDebugInfo = tConfigDebugInfo;
printf("A%d = 0x%04X\n", channel, adcdat);
}
}
//------------------------------------------------------------------------------
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_adc[] = {
{ "ATADC", 0, fATADC, ": ADC Test" },
{ "ATADD", 0, fATADD, ": ADC DMA Test" },
{ "ATADI", 0, fATADI, ": ADC Irq Test" },
{ "ATSA" , 0, fATSA , ": ADC at" }
};

View file

@ -0,0 +1,359 @@
#include <platform_opts.h>
#ifdef CONFIG_AT_USR
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "at_cmd/log_service.h"
#include "at_cmd/atcmd_wifi.h"
#include <lwip_netconf.h>
#include "tcpip.h"
#include <dhcp/dhcps.h>
#include <wifi/wifi_conf.h>
#include <wifi/wifi_util.h>
#include "tcm_heap.h"
#include "rtl8195a/rtl_libc.h"
#include "sleep_ex_api.h"
#include "lwip/tcp_impl.h"
extern char str_rom_57ch3Dch0A[]; // "=========================================================\n" 57
#define printf rtl_printf // DiagPrintf
/* RAM/TCM/Heaps info */
extern void ShowMemInfo(void);
/*
void ShowMemInfo(void)
{
printf("\nCLK CPU\t\t%d Hz\nRAM heap\t%d bytes\nTCM heap\t%d bytes\n",
HalGetCpuClk(), xPortGetFreeHeapSize(), tcm_heap_freeSpace());
}
*/
//------------------------------------------------------------------------------
// Mem, Tasks info
//------------------------------------------------------------------------------
LOCAL void fATST(int argc, char *argv[]) {
ShowMemInfo();
#if 0 //CONFIG_DEBUG_LOG > 1
dump_mem_block_list();
tcm_heap_dump();
#endif;
printf("\n");
#if (configGENERATE_RUN_TIME_STATS == 1)
char *cBuffer = pvPortMalloc(512);
if(cBuffer != NULL) {
vTaskGetRunTimeStats((char *)cBuffer);
printf("%s", cBuffer);
}
vPortFree(cBuffer);
#endif
#if defined(configUSE_TRACE_FACILITY) && (configUSE_TRACE_FACILITY == 1) && (configUSE_STATS_FORMATTING_FUNCTIONS == 1)
{
char * pcWriteBuffer = malloc(1024);
if(pcWriteBuffer) {
vTaskList((char*)pcWriteBuffer);
printf("\nTask List:\n");
printf(&str_rom_57ch3Dch0A[7]); // "==========================================\n"
printf("Name\t Status Priority HighWaterMark TaskNumber\n%s\n", pcWriteBuffer);
free(pcWriteBuffer);
}
}
#endif
}
/*-------------------------------------------------------------------------------------
Копирует данные из области align(4) (flash, registers, ...) в область align(1) (ram)
--------------------------------------------------------------------------------------*/
extern void copy_align4_to_align1(unsigned char * pd, void * ps, unsigned int len);
/*
static void copy_align4_to_align1(unsigned char * pd, void * ps, unsigned int len)
{
union {
unsigned char uc[4];
unsigned int ud;
}tmp;
unsigned int *p = (unsigned int *)((unsigned int)ps & (~3));
unsigned int xlen = (unsigned int)ps & 3;
// unsigned int size = len;
if(xlen) {
tmp.ud = *p++;
while (len) {
len--;
*pd++ = tmp.uc[xlen++];
if(xlen & 4) break;
}
}
xlen = len >> 2;
while(xlen) {
tmp.ud = *p++;
*pd++ = tmp.uc[0];
*pd++ = tmp.uc[1];
*pd++ = tmp.uc[2];
*pd++ = tmp.uc[3];
xlen--;
}
if(len & 3) {
tmp.ud = *p;
pd[0] = tmp.uc[0];
if(len & 2) {
pd[1] = tmp.uc[1];
if(len & 1) {
pd[2] = tmp.uc[2];
}
}
}
// return size;
}
*/
int print_hex_dump(uint8_t *buf, int len, unsigned char k) {
uint32_t ss[2];
ss[0] = 0x78323025; // "%02x"
ss[1] = k; // ","...'\0'
uint8_t * ptr = buf;
int result = 0;
while (len--) {
if (len == 0)
ss[1] = 0;
result += printf((uint8_t *) &ss, *ptr++);
}
return result;
}
extern char str_rom_hex_addr[]; // in *.ld "[Addr] .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .A .B .C .D .E .F\n"
void dump_bytes(uint32 addr, int size)
{
uint8 buf[17];
u32 symbs_line = sizeof(buf)-1;
printf(str_rom_hex_addr);
while (size) {
if (symbs_line > size) symbs_line = size;
printf("%08X ", addr);
copy_align4_to_align1(buf, addr, symbs_line);
print_hex_dump(buf, symbs_line, ' ');
int i;
for(i = 0 ; i < symbs_line ; i++) {
if(buf[i] < 0x20 || buf[i] > 0x7E) {
buf[i] = '.';
}
}
buf[symbs_line] = 0;
i = (sizeof(buf)-1) - symbs_line;
while(i--) printf(" ");
printf(" %s\r\n", buf);
addr += symbs_line;
size -= symbs_line;
}
}
//------------------------------------------------------------------------------
// Dump byte register
//------------------------------------------------------------------------------
LOCAL void fATSB(int argc, char *argv[])
{
int size = 16;
uint32 addr = Strtoul(argv[1],0,16);
if (argc > 2) {
size = Strtoul(argv[2],0,10);
if (size <= 0 || size > 16384)
size = 16;
}
if(addr + size > SPI_FLASH_BASE) {
flash_turnon();
dump_bytes(addr, size);
SpicDisableRtl8195A();
}
else {
dump_bytes(addr, size);
}
}
//------------------------------------------------------------------------------
// Dump dword register
//------------------------------------------------------------------------------
LOCAL void fATSD(int argc, char *argv[])
{
/*
if (argc > 2) {
int size = Strtoul(argv[2],0,10);
if (size <= 0 || size > 16384)
argv[2] = "16";
}
*/
CmdDumpWord(argc-1, (unsigned char**)(argv+1));
}
//------------------------------------------------------------------------------
// Write dword register
//------------------------------------------------------------------------------
LOCAL void fATSW(int argc, char *argv[])
{
CmdWriteWord(argc-1, (unsigned char**)(argv+1));
}
/* Get one byte from the 4-byte address */
#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0])
#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1])
#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2])
#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3])
/* These are cast to u16_t, with the intent that they are often arguments
* to printf using the U16_F format from cc.h. */
#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr))
#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr))
#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr))
#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr))
#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
ip4_addr2_16(ipaddr), \
ip4_addr3_16(ipaddr), \
ip4_addr4_16(ipaddr)
#define IPSTR "%d.%d.%d.%d"
extern const char * const tcp_state_str[];
/*
static const char * const tcp_state_str[] = {
"CLOSED",
"LISTEN",
"SYN_SENT",
"SYN_RCVD",
"ESTABLISHED",
"FIN_WAIT_1",
"FIN_WAIT_2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"
};
*/
/******************************************************************************
* FunctionName : debug
* Parameters :
* Returns :
*******************************************************************************/
void print_udp_pcb(void)
{
struct udp_pcb *pcb;
bool prt_none = true;
rtl_printf("UDP pcbs:\n");
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
rtl_printf("flg:%02x\t" IPSTR ":%d\t" IPSTR ":%d\trecv:%p\n", pcb->flags, IP2STR(&pcb->local_ip), pcb->local_port, IP2STR(&pcb->remote_ip), pcb->remote_port, pcb->recv );
prt_none = false;
};
if(prt_none) rtl_printf("none\n");
}
/******************************************************************************
* FunctionName : debug
* Parameters :
* Returns :
*******************************************************************************/
void print_tcp_pcb(void)
{
struct tcp_pcb *pcb;
rtl_printf("Active PCB states:\n");
bool prt_none = true;
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
prt_none = false;
};
if(prt_none) rtl_printf("none\n");
rtl_printf("Listen PCB states:\n");
prt_none = true;
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
prt_none = false;
};
if(prt_none) rtl_printf("none\n");
rtl_printf("TIME-WAIT PCB states:\n");
prt_none = true;
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p \t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
prt_none = false;
};
if(prt_none) rtl_printf("none\n");
}
/******************************************************************************
* FunctionName : debug
* Parameters :
* Returns :
*******************************************************************************/
LOCAL void fATLW(int argc, char *argv[]) // Info Lwip
{
print_udp_pcb();
print_tcp_pcb();
}
//------------------------------------------------------------------------------
// Deep sleep
//------------------------------------------------------------------------------
LOCAL void fATDS(int argc, char *argv[])
{
uint32 sleep_ms = 10000;
if(argc > 1) sleep_ms = atoi(argv[1]);
#if 0
if(argc > 2) {
printf("%u ms waiting low level on PB_1 before launching Deep-Sleep...\n", sleep_ms);
// turn off log uart
HalDeinitLogUart(); // sys_log_uart_off();
// initialize wakeup pin
gpio_t gpio_wake;
gpio_init(&gpio_wake, PB_1);
gpio_dir(&gpio_wake, PIN_INPUT);
gpio_mode(&gpio_wake, PullDown);
TickType_t sttime = xTaskGetTickCount();
do {
if(gpio_read(&gpio_wake) == 0) {
// Enter deep sleep... Wait give rising edge at PB_1 to wakeup system.
deepsleep_ex(DSLEEP_WAKEUP_BY_GPIO, 0);
};
vTaskDelay(1);
} while(xTaskGetTickCount() - sttime < sleep_ms);
HalInitLogUart(); // sys_log_uart_on();
printf("No set pin low in deep sleep!\n");
}
else {
printf("Deep-Sleep %u ms\n", sleep_ms);
HalLogUartWaitTxFifoEmpty();
// Enter deep sleep... Wait timer ms
deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, sleep_ms);
}
#else
HalLogUartWaitTxFifoEmpty();
deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, sleep_ms);
#endif
}
/*------------------------------------------------------------------------------
* power saving mode
*----------------------------------------------------------------------------*/
LOCAL void fATSP(int argc, char *argv[])
{
if(argc > 2) {
switch (argv[1][0]) {
case 'a': // acquire
{
acquire_wakelock(atoi(argv[2]));
break;
}
case 'r': // release
{
release_wakelock(atoi(argv[2]));
break;
}
};
};
printf("WakeLock Status %d\n", get_wakelock_status());
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_at[] = {
{"ATST", 0, fATST, ": Memory info"},
{"ATLW", 0, fATLW, ": LwIP Info"},
{"ATSB", 1, fATSB, "=<ADDRES(hex)>[,COUNT(dec)]: Dump byte register"},
{"ATSD", 1, fATSD, "=<ADDRES(hex)>[,COUNT(dec)]: Dump dword register"},
{"ATSW", 2, fATSW, "=<ADDRES(hex)>,<DATA(hex)>: Set register"},
{"ATDS", 0, fATDS, "=[TIME(ms)]: Deep sleep"},
{"ATSP", 0, fATSP, "=<a,r>,<wakelock_status:1|2|4|8>: Power"}
};
#endif //#ifdef CONFIG_AT_USR

View file

@ -0,0 +1,38 @@
/*
* flash_tst.c
*
* Created on: 10/04/2017
* Author: pvvx
*/
#include <platform_opts.h>
#include "rtl8195a.h"
#include "flash_api.h"
#include "rtl8195a/rtl_libc.h"
extern void dump_bytes(uint32 addr, int size);
LOCAL void FlashDump(int argc, char *argv[]) {
if (argc > 1) {
int addr;
sscanf(argv[1], "%x", &addr);
int size = 16;
if (argc > 2) {
size = atoi(argv[2]);
if (size <= 0 || size > 16384) {
size = 16;
};
};
flash_turnon();
dump_bytes(addr + SPI_FLASH_BASE, size);
SpicDisableRtl8195A();
}
}
MON_RAM_TAB_SECTION COMMAND_TABLE console_flash_tst[] = {
{"FLASHDB", 1, FlashDump, ": <faddr(HEX)>[,size]: Flash Dump"}
};

View file

@ -0,0 +1,99 @@
/*
* test.c
*
* Created on: 12 марта 2017 г.
* Author: PVV
*/
#include <platform_opts.h>
#include "device.h"
#include "gpio_api.h" // mbed
#include "gpio_irq_api.h" // mbed
#include "gpio_irq_ex_api.h" // mbed
#include "timer_api.h"
#include "diag.h"
#include "main.h"
#include "hal_diag.h"
#include "rtl8195a/rtl_libc.h"
#define GPIO_LED_PIN PA_4
#define GPIO_IRQ_PIN PC_4
gpio_irq_t gpio_btn;
gpio_t gpio_led;
gtimer_t my_timer;
uint32_t lo_time_us, hi_time_us;
uint32_t lo_time_cnt, hi_time_cnt;
uint32_t old_tsf;
uint32_t lo, hi, fr;
uint32_t io_irq_count;
LOCAL void gpio_demo_irq_handler(uint32_t id, gpio_irq_event event) {
// gpio_irq_disable(&gpio_btn);
io_irq_count++;
uint32_t new_tsf = get_tsf();
uint32_t delta_us = (uint32_t) new_tsf - (uint32_t) old_tsf;
if (event & 1) {
lo_time_us += delta_us;
lo_time_cnt++;
gpio_irq_set(&gpio_btn, IRQ_LOW, 1);
} else {
hi_time_us += delta_us;
hi_time_cnt++;
gpio_irq_set(&gpio_btn, IRQ_HIGH, 1);
}
old_tsf = new_tsf;
// gpio_irq_enable(&gpio_btn);
}
LOCAL void timer1_timeout_handler(uint32_t id) {
if (lo_time_cnt && hi_time_cnt) {
lo = lo_time_us / lo_time_cnt;
hi = hi_time_us / hi_time_cnt;
fr = hi + lo;
lo_time_cnt = 0;
lo_time_us = 0;
hi_time_cnt = 0;
hi_time_us = 0;
printf("Period: %lu us, Lo: %lu us, Hi: %lu us\n", fr, lo, hi);
}
}
/**
* @brief Main program.
* @param None
* @retval None
*/
LOCAL void fATTT(int argc, char *argv[]) {
lo_time_cnt = 0;
lo_time_us = 0;
hi_time_cnt = 0;
hi_time_us = 0;
// Init LED control pin
gpio_init(&gpio_led, GPIO_LED_PIN);
gpio_dir(&gpio_led, PIN_OUTPUT); // Direction: Output
gpio_mode(&gpio_led, PullNone); // No pull
gpio_write(&gpio_led, 0);
// Initial Push Button pin as interrupt source
gpio_irq_init(&gpio_btn, GPIO_IRQ_PIN, gpio_demo_irq_handler,
(uint32_t) (&gpio_led));
gpio_irq_set(&gpio_btn, IRQ_FALL, 1); // Falling Edge Trigger
gpio_irq_enable(&gpio_btn);
// Initial a periodical timer
gtimer_init(&my_timer, TIMER1);
gtimer_start_periodical(&my_timer, 1000000, (void*) timer1_timeout_handler,
(uint32_t) &gpio_led);
}
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_test[] = { { "ATTT", 0,
fATTT, ": Test" } };

View file

@ -0,0 +1,39 @@
/*
* power_tst.c
*
* Created on: 04 апр. 2017 г.
* Author: PVV
*/
#include "rtl8195a.h"
#include "freertos_pmu.h"
#include "rtl8195a/rtl_libc.h"
/*------------------------------------------------------------------------------
* power saving mode
*----------------------------------------------------------------------------*/
void fATSP(int argc, char *argv[])
{
if(argc > 2) {
switch (argv[1][0]) {
case 'a': // acquire
{
acquire_wakelock(atoi(argv[2]));
break;
}
case 'r': // release
{
release_wakelock(atoi(argv[2]));
break;
}
}
}
printf("WakeLock Status %d\n", get_wakelock_status());
}
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_pwrs[] = {
{"ATSP", 0, fATSP, "=<a,r>,<wakelock_status:1|2|4|8>: Power"}
};

View file

@ -0,0 +1,59 @@
/*
* pwm_tst.c
*
* Created on: 19/04/2017.
* Author: pvvx
*/
#include <platform_opts.h>
#include "rtl8195a.h"
#include "FreeRTOS.h"
#include "rtl8195a/rtl_libc.h"
//#include "device.h"
#include "pwmout_api.h" // mbed
//#include "main.h"
#include "web_utils.h"
#include "objects.h"
#include "pinmap.h"
extern const PinMap PinMap_PWM[];
extern u32 gTimerRecord;
HAL_PWM_ADAPTER pwm_hal_adp;
LOCAL void fATPWM(int argc, char *argv[]) {
uint8_t pin = ahextoul(argv[1]);
uint32_t period = ahextoul(argv[2]);
uint32_t pulse = ahextoul(argv[3]);
uint32_t peripheral = pinmap_peripheral(pin, PinMap_PWM);
if(pwm_hal_adp.enable) {
HAL_Pwm_Disable(&pwm_hal_adp);
gTimerRecord &= ~(1 << pwm_hal_adp.gtimer_id);
rtl_memset((void *)&pwm_hal_adp, 0, sizeof(HAL_PWM_ADAPTER));
};
if((period) && (unlikely(peripheral != NC))
&& (HAL_Pwm_Init(&pwm_hal_adp, RTL_GET_PERI_IDX(peripheral), RTL_GET_PERI_SEL(peripheral)) == HAL_OK)) {
HAL_Pwm_SetDuty(&pwm_hal_adp, period, pulse);
HAL_Pwm_Enable(&pwm_hal_adp);
} else {
printf("Error parameters!");
};
}
LOCAL void fATWLED(int argc, char *argv[]) {
HalPinCtrlRtl8195A(WL_LED, 2, 1);
HalPinCtrlRtl8195A(EGTIM, ahextoul(argv[1]), 1);
}
//------------------------------------------------------------------------------
// atpwm=34,1048575,524287
// atpwm=34,122,61 (8.187kHz)
// atsw 40000368 85001002 (8.187kHz)
// atsd 40000360 6
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_adc[] = {
{ "ATWLED", 0, fATWLED, ": WLED Test" },
{ "ATPWM", 3, fATPWM, "=<pin>,<period>,<pulse>: PWM Test" }
};

View file

@ -0,0 +1,83 @@
/*
* spi_test.c
*/
#include <platform_opts.h>
#include "rtl8195a.h"
#include "spi_api.h"
#include "spi_ex_api.h"
#include "rtl8195a/rtl_libc.h"
#define SPI0_MOSI PC_2
#define SPI0_MISO PC_3
#define SPI0_SCLK PC_1
#define SPI0_CS PC_0
spi_t spi_master;
LOCAL void show_reg_spi(int i) {
rtl_printf("Regs SPI:\n");
for(int x = 0; x < 64 ; x += 4) {
rtl_printf("0x%08x ", HAL_SSI_READ32(i, x));
if((x & 0x0F) == 0x0C) rtl_printf("\n");
}
}
LOCAL void fATSSI(int argc, char *argv[])
{
int len = 128;
int count = 32;
int clk = 1000000;
int ssn = 0;
if(argc > 1) {
len = atoi(argv[1]);
if(len > 32768 || len <= 0) {
len = 128;
error_printf("%s: len = %u!\n", __func__, len);
};
};
if(argc > 2) {
count = atoi(argv[2]);
if(count > 10000 || count <= 0) {
count = 32;
error_printf("%s: count = %u!\n", __func__, count);
};
};
if(argc > 3) {
clk = atoi(argv[3]);
if(clk <= 0) {
clk = 1000000;
error_printf("%s: clk = %u!\n", __func__, clk);
};
};
if(argc > 4) {
ssn = atoi(argv[4]);
if(ssn > 7 || ssn < 0) {
ssn = 0;
error_printf("%s: ssn = %u!\n", __func__, ssn);
};
};
char* buff = pvPortMalloc(len);
if(buff) {
spi_init(&spi_master, SPI0_MOSI, SPI0_MISO, SPI0_SCLK, SPI0_CS); // CS заданный тут нигде не используется
spi_format(&spi_master, 16, 3, 0);
spi_frequency(&spi_master, clk);
spi_slave_select(&spi_master, ssn); // выбор CS
for(int i = 0; i < len; i++) buff[i] = (char)i;
while(count--) {
spi_master_write_stream(&spi_master, buff, len);
while(spi_busy(&spi_master));
rtl_printf("Master write: %d\n", count);
};
// show_reg_spi(spi_master.spi_adp.Index);
spi_free(&spi_master);
free(buff);
}
else {
error_printf("%s: error malloc!\n", __func__);
};
}
MON_RAM_TAB_SECTION COMMAND_TABLE console_commands_spitst[] = {
{"ATSSI", 0, fATSSI, "[len[,count[,clk[,ssn]]]]: Spi test"}
};

View file

@ -0,0 +1,338 @@
/*
* wifi_console.c
*
* Created on: 03/04/2017
* Author: pvvx
*/
#include <autoconf.h>
#include "FreeRTOS.h"
#include "diag.h"
#include "wifi_api.h"
#include "wifi_conf.h"
#include "rtl8195a/rtl_libc.h"
#include "hal_platform.h"
#include "section_config.h"
#include "hal_diag.h"
#include "lwip/netif.h"
extern struct netif xnetif[NET_IF_NUM];
//==========================================================
//--- CONSOLE --------------------------
// ATPN=<SSID>[,password[,encryption[,auto reconnect[,reconnect pause]]]: WIFI Connect to AP
LOCAL void fATPN(int argc, char *argv[]){
if(argc > 1) {
if(argv[1][0] == '?') {
show_wifi_st_cfg();
}
else {
strncpy(wifi_st_cfg.ssid, argv[1], NDIS_802_11_LENGTH_SSID);
if(argc > 2) {
strncpy(wifi_st_cfg.password, argv[2], NDIS_802_11_LENGTH_SSID);
int i = strlen(wifi_st_cfg.password);
if(i > 7) {
wifi_st_cfg.security_type = RTW_SECURITY_WPA2_AES_PSK;
}
else if(!i) {
wifi_st_cfg.security_type = RTW_SECURITY_OPEN;
}
else {
printf("password len < 8!\n");
wifi_st_cfg.security_type = RTW_SECURITY_OPEN;
}
}
else {
wifi_st_cfg.password[0] = 0;
wifi_st_cfg.security_type = RTW_SECURITY_OPEN;
}
if(argc > 3) {
wifi_ap_cfg.security_type = translate_rtw_security(atoi(argv[3]));
}
if(argc > 4) {
wifi_st_cfg.autoreconnect = atoi(argv[3]);
}
else wifi_st_cfg.autoreconnect = 0;
if(argc > 5) {
wifi_st_cfg.reconnect_pause = atoi(argv[3]);
}
else wifi_st_cfg.reconnect_pause = 5;
show_wifi_st_cfg();
wifi_run(wifi_run_mode | RTW_MODE_STA);
}
}
}
// ATPA=<SSID>[,password[,encryption[,channel[,hidden[,max connections]]]]]: Start WIFI AP
LOCAL void fATPA(int argc, char *argv[]){
if(argc > 1) {
if(argv[1][0] == '?') {
show_wifi_ap_cfg();
}
else {
strncpy(wifi_ap_cfg.ssid, argv[1], NDIS_802_11_LENGTH_SSID);
if(argc > 2) {
strncpy(wifi_ap_cfg.password, argv[2], NDIS_802_11_LENGTH_SSID);
int i = strlen(wifi_ap_cfg.password);
if(i > 7) {
wifi_ap_cfg.security_type = RTW_SECURITY_WPA2_AES_PSK;
}
else if(i == 0) {
wifi_ap_cfg.security_type = RTW_SECURITY_OPEN;
}
else {
printf("password len < 8!\n");
wifi_ap_cfg.security_type = RTW_SECURITY_OPEN;
}
}
else {
wifi_ap_cfg.password[0] = 0;
wifi_ap_cfg.security_type = RTW_SECURITY_OPEN;
}
if(argc > 3) {
if(argv[3][0]=='0') wifi_st_cfg.security_type = RTW_SECURITY_OPEN;
else wifi_st_cfg.security_type = RTW_SECURITY_WEP_PSK;
}
if(argc > 4) {
wifi_ap_cfg.channel = atoi(argv[4]);
}
else wifi_ap_cfg.channel = 1;
if(argc > 5) {
wifi_ap_cfg.ssid_hidden = atoi(argv[5]);
}
else wifi_ap_cfg.ssid_hidden = 0;
if(argc > 6) {
wifi_ap_cfg.max_sta = atoi(argv[6]);
}
else wifi_ap_cfg.max_sta = 3;
show_wifi_ap_cfg();
wifi_run(wifi_run_mode | RTW_MODE_AP);
}
}
}
// WIFI Connect, Disconnect
LOCAL void fATWR(int argc, char *argv[]){
rtw_mode_t mode = RTW_MODE_NONE;
if(argc > 1) mode = atoi(argv[1]);
wifi_run(mode);
}
// Close connections
LOCAL void fATOF(int argc, char *argv[]){
connect_close();
}
// Open connections
LOCAL void fATON(int argc, char *argv[]){
connect_start();
}
LOCAL void fATWI(int argc, char *argv[]) {
rtw_wifi_setting_t Setting;
if((wifi_run_mode & RTW_MODE_AP)
&& wifi_get_setting(wlan_ap_name, &Setting) == 0) {
wifi_show_setting(wlan_ap_name, &Setting);
// show_wifi_ap_ip();
printf("\tIP: " IPSTR "\n", IP2STR(&xnetif[WLAN_AP_NETIF_NUM].ip_addr));
}
if((wifi_run_mode & RTW_MODE_STA)
&& wifi_get_setting(wlan_st_name, &Setting) == 0) {
wifi_show_setting(wlan_st_name, &Setting);
// show_wifi_st_ip();
printf("\tIP: " IPSTR "\n", IP2STR(&xnetif[WLAN_ST_NETIF_NUM].ip_addr));
}
printf("\nWIFI config:\n");
printf(&str_rom_57ch3Dch0A[25]); // "================================\n"
show_wifi_cfg();
printf("\nWIFI AP config:\n");
printf(&str_rom_57ch3Dch0A[25]); // "================================\n"
show_wifi_ap_cfg();
printf("\nWIFI ST config:\n");
printf(&str_rom_57ch3Dch0A[25]); // "================================\n"
show_wifi_st_cfg();
printf("\n");
#if 1
if(argc > 2) {
uint8_t c = argv[1][0] | 0x20;
if(c == 's') {
int i = atoi(argv[2]);
printf("Save configs(%d)..\n", i);
write_wifi_cfg(atoi(argv[2]));
}
else if(c == 'l') {
wifi_cfg.load_flg = atoi(argv[2]);
}
else if(c == 'm') {
wifi_cfg.mode = atoi(argv[2]);
}
}
#endif
}
extern uint8_t rtw_power_percentage_idx;
LOCAL void fATWT(int argc, char *argv[]) {
if(argc > 1) {
int txpwr = atoi(argv[1]);
debug_printf("set tx power (%d)...\n", txpwr);
if(rltk_set_tx_power_percentage(txpwr) != RTW_SUCCESS) {
error_printf("Error set tx power (%d)!", wifi_cfg.tx_pwr);
}
}
printf("TX power = %d\n", rtw_power_percentage_idx);
}
//-- Test tsf (64-bits counts, 1 us step) ---
#include "hal_com_reg.h"
#define ReadTSF_Lo32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR)))
#define ReadTSF_Hi32() (*((volatile unsigned int *)(WIFI_REG_BASE + REG_TSFTR1)))
LOCAL uint64_t get_tsf(void)
{
return *((uint64_t *)(WIFI_REG_BASE + REG_TSFTR));
}
LOCAL void fATSF(int argc, char *argv[])
{
uint64_t tsf = get_tsf();
printf("\nTSF: %08x%08x\n", (uint32_t)(tsf>>32), (uint32_t)(tsf));
}
/* -------- WiFi Scan ------------------------------- */
unsigned char *tab_txt_rtw_secyrity[] = {
"OPEN ",
"WEP ",
"WPA TKIP",
"WPA AES",
"WPA2 AES",
"WPA2 TKIP",
"WPA2 Mixed",
"WPA/WPA2 AES",
"Unknown"
};
unsigned int *tab_code_rtw_secyrity[] = {
RTW_SECURITY_OPEN,
RTW_SECURITY_WEP_PSK,
RTW_SECURITY_WPA_TKIP_PSK,
RTW_SECURITY_WPA_AES_PSK,
RTW_SECURITY_WPA2_AES_PSK,
RTW_SECURITY_WPA2_TKIP_PSK,
RTW_SECURITY_WPA2_MIXED_PSK,
RTW_SECURITY_WPA_WPA2_MIXED,
RTW_SECURITY_UNKNOWN
};
volatile uint8_t scan_end;
/* -------- WiFi Scan ------------------------------- */
LOCAL rtw_result_t _scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
{
if (malloced_scan_result->scan_complete != RTW_TRUE) {
rtw_scan_result_t* record = &malloced_scan_result->ap_details;
record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
if(scan_end == 1) {
printf("\nScan networks:\n\n");
printf("N\tType\tMAC\t\t\tSignal\tCh\tWPS\tSecyrity\tSSID\n\n");
};
printf("%d\t", scan_end++);
printf("%s\t", (record->bss_type == RTW_BSS_TYPE_ADHOC)? "Adhoc": "Infra");
printf(MAC_FMT, MAC_ARG(record->BSSID.octet));
printf("\t%d\t", record->signal_strength);
printf("%d\t", record->channel);
printf("%d\t", record->wps_type);
int i = 0;
for(; record->security != tab_code_rtw_secyrity[i] && tab_code_rtw_secyrity[i] != RTW_SECURITY_UNKNOWN; i++);
printf("%s \t", tab_txt_rtw_secyrity[i]);
printf("%s\n", record->SSID.val);
} else {
scan_end = 0;
printf("\n");
}
return RTW_SUCCESS;
}
/* -------- WiFi Scan ------------------------------- */
#define scan_channels 14
LOCAL void fATSN(int argc, char *argv[])
{
int i;
u8 *channel_list = (u8*)pvPortMalloc(scan_channels*2);
if(channel_list) {
scan_end = 1;
u8 * pscan_config = &channel_list[scan_channels];
//parse command channel list
for(i = 1; i <= scan_channels; i++){
*(channel_list + i - 1) = i;
*(pscan_config + i - 1) = PSCAN_ENABLE;
};
if(wifi_set_pscan_chan(channel_list, pscan_config, scan_channels) < 0){
printf("ERROR: wifi set partial scan channel fail\n");
} else if(wifi_scan_networks(_scan_result_handler, NULL ) != RTW_SUCCESS){
printf("ERROR: wifi scan failed\n");
} else {
i = 300;
while(i-- && scan_end) {
vTaskDelay(10);
};
};
vPortFree(channel_list);
} else {
printf("ERROR: Can't malloc memory for channel list\n");
};
}
#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
extern void cmd_ap_wps(int argc, char **argv);
extern void cmd_wps(int argc, char **argv);
//extern void cmd_wifi_on(int argc, char **argv);
#endif
#if CONFIG_ENABLE_P2P
extern void cmd_wifi_p2p_start(int argc, char **argv);
extern void cmd_wifi_p2p_stop(int argc, char **argv);
extern void cmd_p2p_listen(int argc, char **argv);
extern void cmd_p2p_find(int argc, char **argv);
extern void cmd_p2p_peers(int argc, char **argv);
extern void cmd_p2p_info(int argc, char **argv);
extern void cmd_p2p_disconnect(int argc, char **argv);
extern void cmd_p2p_connect(int argc, char **argv);
extern void cmd_wifi_p2p_auto_go_start(int argc, char **argv);
extern void cmd_p2p_peers(int argc, char **argv);
#endif //CONFIG_ENABLE_P2P
MON_RAM_TAB_SECTION COMMAND_TABLE console_cmd_wifi_api[] = {
{"ATPN", 1, fATPN, "=<SSID>[,password[,encryption[,auto-reconnect[,reconnect pause]]]: WIFI Connect to AP"},
{"ATPA", 1, fATPA, "=<SSID>[,password[,encryption[,channel[,hidden[,max connections]]]]]: Start WIFI AP"},
#if defined(CONFIG_ENABLE_WPS_AP) && CONFIG_ENABLE_WPS_AP
{"WPS_AP", 1, cmd_ap_wps, "=<pbc/pin>[,pin]: WiFi AP WPS"},
{"WPS_ST", 1, cmd_wps, "=<pbc/pin>[,pin]: WiFi Station WPS"},
#endif
#if CONFIG_ENABLE_P2P
{"P2P_START", 0, cmd_wifi_p2p_start, ": p2p start" },
{"P2P_ASTART", 0, cmd_wifi_p2p_auto_go_start, ": p2p auto go start" },
{"P2P_STOP", 0, cmd_wifi_p2p_stop, ": p2p stop"},
{"P2P_PEERS", 0, cmd_p2p_peers, ": p2p peers" },
{"P2P_FIND", 0, cmd_p2p_find, ": p2p find"},
{"P2P_INFO", 0, cmd_p2p_info, ": p2p info"},
{"P2P_DISCCONNECT", 0, cmd_p2p_disconnect, ": p2p disconnect"},
{"P2P_CONNECT", 0, cmd_p2p_connect, ": p2p connect"},
#endif
{"ATWR", 0, fATWR, ": WIFI Connect, Disconnect"},
// {"ATON", 0, fATON, ": Open connections"},
// {"ATOF", 0, fATOF, ": Close connections"},
{"ATWI", 0, fATWI, ": WiFi Info"},
#if CONFIG_DEBUG_LOG > 3
{"ATWT", 1, fATWT, "=<tx_power>: WiFi tx power: 0 - 100%, 1 - 75%, 2 - 50%, 3 - 25%, 4 - 12.5%"},
{"ATSF", 0, fATSF, ": Test TSF value"},
#endif
{"ATSN", 0, fATSN, ": Scan networks"}
};

View file

@ -0,0 +1,50 @@
/*
* wlan_tst.c
*
* Created on: 10 апр. 2017 г.
* Author: PVV
*/
#include <platform_opts.h>
#include "rtl8195a.h"
#include "drv_types.h"
//#include "section_config.h"
//#include "hal_diag.h"
#include "rtl8195a/rtl_libc.h"
extern void dump_bytes(uint32 addr, int size);
extern Rltk_wlan_t rltk_wlan_info[2]; // in wrapper.h
LOCAL void tst_wlan_struct(int argc, char *argv[])
{
printf("Test: sizeof(struct _ADAPTER) = %d\n", sizeof(struct _ADAPTER)); //6088
printf("mlmeextpriv\t+%d\n", offsetof(struct _ADAPTER, mlmeextpriv)); //+1256
printf("TSFValue\t+%d\n", offsetof(struct _ADAPTER, mlmeextpriv.TSFValue)); //+1992
printf("stapriv\t\t+%d\n", offsetof(struct _ADAPTER, stapriv)); //+3024 [164]
printf("pwrctrlpriv.bInternalAutoSuspend +%d\n", offsetof(struct _ADAPTER, pwrctrlpriv.bInternalAutoSuspend)); //+5061
printf("eeprompriv\t+%d\n", offsetof(struct _ADAPTER, eeprompriv)); // +5128
printf("HalData\t\t+%d\n", offsetof(struct _ADAPTER, HalData)); //+5656
printf("HalFunc\t\t+%d\n", offsetof(struct _ADAPTER, HalFunc)); //+5664
printf("bDriverStopped\t+%d\n", offsetof(struct _ADAPTER, bDriverStopped)); //+5880
printf("hw_init_completed +%d\n", offsetof(struct _ADAPTER, hw_init_completed)); //+5905
printf("stats\t\t+%d\n", offsetof(struct _ADAPTER, stats)); //+6024
printf("hw_init_mutex\t+%d\n", offsetof(struct _ADAPTER, hw_init_mutex)); //+6060
printf("fix_rate\t+%d\n", offsetof(struct _ADAPTER, fix_rate)); //+6084
printf("rltk_wlan_info = %p\n", &rltk_wlan_info);
dump_bytes((u32)&rltk_wlan_info, sizeof(rltk_wlan_info));
_adapter * ad = *(_adapter **)((rltk_wlan_info[0].dev)->priv);
printf("adapter0 = %p, %p\n", ad, ad->pbuddy_adapter);
ad = *(_adapter **)((rltk_wlan_info[1].dev)->priv);
printf("adapter1 = %p, %p\n", ad, ad->pbuddy_adapter);
vTaskDelay(5);
dump_bytes((u32)ad,sizeof(struct _ADAPTER));
vTaskDelay(5);
if (sizeof(struct _ADAPTER) != 6088) {
printf("Error: Check WiFi adapter struct!\n");
};
}
MON_RAM_TAB_SECTION COMMAND_TABLE console_wlan_tst[] = {
{"CHKWL", 0, tst_wlan_struct, ": Chk wlan struct"}
};

File diff suppressed because it is too large Load diff

97
project/src/user/main.c Normal file
View file

@ -0,0 +1,97 @@
/*
*
*/
#include "platform_autoconf.h"
#include "autoconf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include "hal_crypto.h"
#include "hal_log_uart.h"
#include "hal_misc.h"
#include "diag.h"
//#include "wdt_api.h"
//#include <osdep_service.h>
#include "hal_platform.h"
#include "rtl8195a_sys_on.h"
#ifdef CONFIG_WDG_ON_IDLE
#include "hal_peri_on.h"
#include "rtl8195a_peri_on.h"
#endif
/* ---------------------------------------------------
* Customized Signature (Image Name)
* ---------------------------------------------------*/
#include "section_config.h"
SECTION(".custom.validate.rodata")
const unsigned char cus_sig[32] = "WEB Sample";
#ifdef CONFIG_DEBUG_LOG
#define DEBUG_MAIN_LEVEL CONFIG_DEBUG_LOG
#else
#define DEBUG_MAIN_LEVEL 0
#endif
#ifndef CONFIG_INIT_NET
#define CONFIG_INIT_NET 1
#endif
#ifndef CONFIG_INTERACTIVE_MODE
#define CONFIG_INTERACTIVE_MODE 1
#endif
extern void user_init_thrd(void);
/* RAM/TCM/Heaps info */
void ShowMemInfo(void)
{
DiagPrintf("\nCLK CPU\t\t%d Hz\nRAM heap\t%d bytes\nTCM heap\t%d bytes\n",
HalGetCpuClk(), xPortGetFreeHeapSize(), tcm_heap_freeSpace());
}
/* main */
void main(void)
{
#if DEBUG_MAIN_LEVEL > 3
ConfigDebugErr = -1;
ConfigDebugInfo = ~(_DBG_SPI_FLASH_);//|_DBG_TCM_HEAP_);
ConfigDebugWarn = -1;
CfgSysDebugErr = -1;
CfgSysDebugInfo = -1;
CfgSysDebugWarn = -1;
#endif
#ifdef CONFIG_WDG_ON_IDLE
HAL_PERI_ON_WRITE32(REG_SOC_FUNC_EN, HAL_PERI_ON_READ32(REG_SOC_FUNC_EN) & 0x1FFFFF);
#if CONFIG_DEBUG_LOG > 3
WDGInitial(CONFIG_WDG_ON_IDLE * 3000); // 30 s
#else
WDGInitial(CONFIG_WDG_ON_IDLE * 1000); // 10 s
#endif
WDGStart();
#endif
#if (defined(CONFIG_CRYPTO_STARTUP) && (CONFIG_CRYPTO_STARTUP))
if(rtl_cryptoEngine_init() != 0 ) {
DBG_8195A("Crypto engine init failed!\n");
}
#endif
#if DEBUG_MAIN_LEVEL > 1
vPortFree(pvPortMalloc(4)); // Init RAM heap
ShowMemInfo(); // RAM/TCM/Heaps info
#endif
/* wlan & user_start intialization */
xTaskCreate(user_init_thrd, "user_init", 1024, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, NULL);
/*Enable Schedule, Start Kernel*/
#if defined(CONFIG_KERNEL) && !TASK_SCHEDULER_DISABLED
#ifdef PLATFORM_FREERTOS
vTaskStartScheduler();
#endif
#else
RtlConsolTaskRom(NULL);
#endif
}

View file

@ -0,0 +1,77 @@
/*
* user_start.c
*
* Created on: 26/03/2017
* Author: pvvx
*/
#include "user_config.h"
#include "platform_autoconf.h"
#include "autoconf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include "netbios/netbios.h"
#include "user/sys_cfg.h"
#include "web/web_srv.h"
#include "webfs/webfs.h"
struct SystemCfg syscfg = {
.cfg.w = SYS_CFG_DEBUG_ENA | SYS_CFG_NETBIOS_ENA,
#if defined(USE_WEB)
.web_port = USE_WEB,
#else
.web_port = 0,
#endif
.web_twrec = 5,
.web_twcls = 5
};
void connect_start(void)
{
info_printf("\%s: Time at start %d ms.\n", __func__, xTaskGetTickCount());
}
void connect_close(void)
{
info_printf("\%s: Time at start %d ms.\n", __func__, xTaskGetTickCount());
}
void user_start(void)
{
info_printf("\%s: Time at start %d ms.\n", __func__, xTaskGetTickCount());
}
void sys_write_cfg(void)
{
flash_write_cfg(&syscfg, FEEP_ID_SYS_CFG, sizeof(syscfg));
}
void user_init_thrd(void) {
flash_read_cfg(&syscfg, FEEP_ID_SYS_CFG, sizeof(syscfg));
if(!syscfg.cfg.b.debug_print_enable) print_off = 1;
/* Initilaize the console stack */
console_init();
/* Web Disk Init */
WEBFSInit();
/* Load cfg, init WiFi + LwIP init, WiFi start if wifi_cfg.mode != RTW_MODE_NONE */
wifi_init();
if(syscfg.cfg.b.netbios_ena) netbios_init();
// webstuff_init(); // httpd_init();
webserver_init(syscfg.web_port);
// xTaskCreate(x_init_thrd, "wifi_init", 1024, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, NULL);
/* Kill init thread after all init tasks done */
vTaskDelete(NULL);
}

View file

@ -0,0 +1,688 @@
/******************************************************************************
* FileName: web_int_callbacks.c
* Description: The web server inernal callbacks.
*******************************************************************************/
#include "user_config.h"
#ifdef USE_WEB
#include "autoconf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include "lwip/tcp.h"
#include "flash_eep.h"
#include "device_lock.h"
#include "ethernetif.h"
#include "tcpsrv/tcp_srv_conn.h"
#include "web_srv_int.h"
#include "web_utils.h"
#include "webfs/webfs.h"
#include "rtl8195a/rtl_libc.h"
#include "user/sys_cfg.h"
#include "wifi_api.h"
#include "sys_api.h"
#include "esp_comp.h"
#ifdef USE_NETBIOS
#include "netbios.h"
#endif
#ifdef USE_SNTP
#include "sntp.h"
#endif
#ifdef USE_CAPTDNS
#include "captdns.h"
#endif
#ifdef USE_MODBUS
#include "modbustcp.h"
#include "mdbtab.h"
#endif
#ifdef USE_RS485DRV
#include "driver/rs485drv.h"
#endif
#ifdef USE_OVERLAY
#include "overlay.h"
#endif
#define atoi rom_atoi
#define mMIN(a, b) ((a<b)?a:b)
#define ifcmp(a) if(rom_xstrcmp(cstr, a))
extern struct netif xnetif[NET_IF_NUM]; /* network interface structure */
//#define TEST_SEND_WAVE
#ifdef TEST_SEND_WAVE
//-------------------------------------------------------------------------------
// Test adc
// Читает adc в одиночный буфер (~2килобайта) на ~20ksps и сохраняет в виде WAV
// Правильное чтение организуется по прерыванию таймера(!).
// Тут только демо!
//-------------------------------------------------------------------------------
typedef struct
{ // https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
unsigned long int RIFF ;/* +00 'RIFF' */
unsigned long int size8;/* +04 file size - 8 */
unsigned long int WAVE ;/* +08 'WAVE' */
unsigned long int fmt ;/* +12 'fmt ' */
unsigned long int fsize;/* +16 указатель до 'fact' или 'data' */
unsigned short int ccod;/* +20 01 00 Compression code: 1 - PCM/uncompressed */
unsigned short int mono;/* +22 00 01 или 00 02 */
unsigned long int freq ;/* +24 частота */
unsigned long int bps ;/* +28 */
unsigned short int blka;/* +32 1/2/4 BlockAlign*/
unsigned short int bits;/* +34 разрядность 8/16 */
unsigned long int data ;/* +36 'data' */
unsigned long int dsize;/* +40 размер данных */
} WAV_HEADER;
const WAV_HEADER ICACHE_RODATA_ATTR wav_header =
{0x46464952L,
0x00000008L,
0x45564157L,
0x20746d66L,
0x00000010L,
0x0001 ,
0x0001 ,
0x000055f0L,
0x000055f0L,
0x0002 ,
0x0010 ,
0x61746164L,
0x00000000L};
#define WAV_HEADER_SIZE sizeof(wav_header)
//===============================================================================
// web_test_adc()
//-------------------------------------------------------------------------------
void ICACHE_FLASH_ATTR web_test_adc(TCP_SERV_CONN *ts_conn)
{
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
unsigned int len = web_conn->msgbufsize - web_conn->msgbuflen;
if(len > WAV_HEADER_SIZE + 10) {
len -= WAV_HEADER_SIZE;
WAV_HEADER * ptr = (WAV_HEADER *) &web_conn->msgbuf[web_conn->msgbuflen];
os_memcpy(ptr, &wav_header, WAV_HEADER_SIZE);
ptr->dsize = len;
web_conn->msgbuflen += WAV_HEADER_SIZE;
len >>= 1;
read_adcs((uint16 *)(web_conn->msgbuf + web_conn->msgbuflen), len, 0x0808);
web_conn->msgbuflen += len << 1;
}
SetSCB(SCB_FCLOSE | SCB_DISCONNECT); // connection close
}
#endif // TEST_SEND_WAVE
#if 0
//===============================================================================
// WiFi Saved Aps XML
//-------------------------------------------------------------------------------
void ICACHE_FLASH_ATTR wifi_aps_xml(TCP_SERV_CONN *ts_conn)
{
struct buf_html_string {
uint8 ssid[32*6 + 1];
uint8 psw[64*6 + 1];
};
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
struct station_config config[5];
struct buf_html_string * buf = (struct buf_html_string *)os_malloc(sizeof(struct buf_html_string));
if(buf == NULL) return;
int total_aps = wifi_station_get_ap_info(config);
// Check if this is a first round call
if(CheckSCB(SCB_RETRYCB)==0) {
tcp_puts_fd("<total>%u</total><cur>%u</cur>", total_aps, wifi_station_get_current_ap_id());
if(total_aps == 0) return;
web_conn->udata_start = 0;
}
while(web_conn->msgbuflen + 74 + 32 <= web_conn->msgbufsize) {
if(web_conn->udata_start < total_aps) {
struct station_config *p = (struct station_config *)&config[web_conn->udata_start];
if(web_conn->msgbuflen + 74 + htmlcode(buf->ssid, p->ssid, 32*6, 32) + htmlcode(buf->psw, p->password, 64*6, 64) > web_conn->msgbufsize) break;
tcp_puts_fd("<aps id=\"%u\"><ss>%s</ss><ps>%s</ps><bs>" MACSTR "</bs><bt>%d</bt></aps>",
web_conn->udata_start, buf->ssid, buf->psw, MAC2STR(p->bssid), p->bssid_set);
web_conn->udata_start++;
if(web_conn->udata_start >= total_aps) {
ClrSCB(SCB_RETRYCB);
os_free(buf);
return;
}
}
else {
ClrSCB(SCB_RETRYCB);
os_free(buf);
return;
}
}
// repeat in the next call ...
SetSCB(SCB_RETRYCB);
SetNextFunSCB(wifi_aps_xml);
os_free(buf);
return;
}
//===============================================================================
// WiFi Scan XML
//-------------------------------------------------------------------------------
void ICACHE_FLASH_ATTR web_wscan_xml(TCP_SERV_CONN *ts_conn)
{
struct bss_scan_info si;
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
// Check if this is a first round call
if(CheckSCB(SCB_RETRYCB)==0) {
tcp_puts_fd("<total>%d</total>", total_scan_infos);
if(total_scan_infos == 0) return;
web_conn->udata_start = 0;
}
while(web_conn->msgbuflen + 96 + 32 <= web_conn->msgbufsize) {
if(web_conn->udata_start < total_scan_infos) {
struct bss_scan_info *p = (struct bss_scan_info *)buf_scan_infos;
p += web_conn->udata_start;
ets_memcpy(&si, p, sizeof(si));
/*
uint8 ssid[33];
ssid[32] = '\0';
ets_memcpy(ssid, si.ssid, 32); */
uint8 ssid[32*6 + 1];
if(web_conn->msgbuflen + 96 + htmlcode(ssid, si.ssid, 32*6, 32) > web_conn->msgbufsize) break;
tcp_puts_fd("<ap id=\"%d\"><ch>%d</ch><au>%d</au><bs>" MACSTR "</bs><ss>%s</ss><rs>%d</rs><hd>%d</hd></ap>", web_conn->udata_start, si.channel, si.authmode, MAC2STR(si.bssid), ssid, si.rssi, si.is_hidden);
web_conn->udata_start++;
if(web_conn->udata_start >= total_scan_infos) {
ClrSCB(SCB_RETRYCB);
return;
}
}
else {
ClrSCB(SCB_RETRYCB);
return;
}
}
// repeat in the next call ...
SetSCB(SCB_RETRYCB);
SetNextFunSCB(web_wscan_xml);
return;
}
//===============================================================================
// WiFi Probe Request XML
//-------------------------------------------------------------------------------
void ICACHE_FLASH_ATTR web_ProbeRequest_xml(TCP_SERV_CONN *ts_conn)
{
struct s_probe_requests pr;
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
// Check if this is a first round call
uint32 cnt = (probe_requests_count < MAX_COUNT_BUF_PROBEREQS)? probe_requests_count : MAX_COUNT_BUF_PROBEREQS;
if(CheckSCB(SCB_RETRYCB)==0) {
if(cnt == 0) {
tcp_strcpy_fd("<total>0</total>");
return;
}
web_conn->udata_start = 0;
}
while(web_conn->msgbuflen + 92 <= web_conn->msgbufsize) {
if(web_conn->udata_start < cnt) {
struct s_probe_requests *p = (struct s_probe_requests *)&buf_probe_requests;
p += web_conn->udata_start;
ets_memcpy(&pr, p, sizeof(struct s_probe_requests));
tcp_puts_fd("<pr id=\"%u\"><mac>" MACSTR "</mac><min>%d</min><max>%d</max></pr>", web_conn->udata_start, MAC2STR(pr.mac), pr.rssi_min, pr.rssi_max);
web_conn->udata_start++;
if(web_conn->udata_start >= cnt) {
tcp_puts_fd("<total>%d</total>", cnt);
ClrSCB(SCB_RETRYCB);
return;
}
}
else {
ClrSCB(SCB_RETRYCB);
return;
}
}
// repeat in the next call ...
SetSCB(SCB_RETRYCB);
SetNextFunSCB(web_ProbeRequest_xml);
return;
}
#endif
#ifdef USE_MODBUS
//===============================================================================
// Mdb XML
//-------------------------------------------------------------------------------
void ICACHE_FLASH_ATTR web_modbus_xml(TCP_SERV_CONN *ts_conn)
{
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
while(web_conn->msgbuflen + 24 <= web_conn->msgbufsize) {
if(web_conn->udata_start < web_conn->udata_stop) {
uint16 val16;
if(RdMdbData((uint8 *)&val16, web_conn->udata_start, 1) != 0) tcp_puts_fd("<m%u>?</m%u>", web_conn->udata_start, web_conn->udata_start);
else {
if(ts_conn->flag.user_option2) {
if(ts_conn->flag.user_option1) {
tcp_puts_fd("<m%u>0x%04x</m%u>", web_conn->udata_start, val16, web_conn->udata_start);
}
else {
tcp_puts_fd("<m%u>%04x</m%u>", web_conn->udata_start, val16, web_conn->udata_start);
};
}
else {
if(ts_conn->flag.user_option1) {
tcp_puts_fd("<m%u>%d</m%u>", web_conn->udata_start, (sint32)((sint16)val16), web_conn->udata_start);
}
else {
tcp_puts_fd("<m%u>%u</m%u>", web_conn->udata_start, val16, web_conn->udata_start);
};
};
};
web_conn->udata_start++;
}
else {
ClrSCB(SCB_RETRYCB);
return;
}
}
// repeat in the next call ...
SetSCB(SCB_RETRYCB);
SetNextFunSCB(web_modbus_xml);
return;
}
#endif
//===============================================================================
// RAM hexdump
//-------------------------------------------------------------------------------
void ICACHE_FLASH_ATTR web_hexdump(TCP_SERV_CONN *ts_conn)
{
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *) ts_conn->linkd;
union {
uint32 dw[4];
uint8 b[16];
}data;
web_conn->udata_start &= 0xfffffff0;
uint32 *addr = (uint32 *)web_conn->udata_start;
int i;
web_conn->udata_stop &= 0xfffffff0;
while(web_conn->msgbuflen + (9+3*16+17+2) <= web_conn->msgbufsize) {
if((uint32)addr < 0x9A000000) {
tcp_puts("%08x", addr);
for(i=0 ; i < 4 ; i++) data.dw[i] = *addr++;
web_conn->udata_start = (uint32)addr;
if(ts_conn->flag.user_option1) {
for(i=0 ; i < 4 ; i++) tcp_puts(" %08x", data.dw[i]);
}
else {
for(i=0 ; i < 16 ; i++) tcp_puts(" %02x", data.b[i]);
}
tcp_put(' '); tcp_put(' ');
for(i=0 ; i < 16 ; i++) tcp_put((data.b[i] >=' ' && data.b[i] != 0x7F)? data.b[i] : '.');
tcp_puts("\r\n");
if((uint32)addr >= web_conn->udata_stop) {
ClrSCB(SCB_RETRYCB);
SetSCB(SCB_FCLOSE | SCB_DISCONNECT); // connection close
return;
}
}
else {
tcp_puts("%p = Bad address!\r\n", addr);
ClrSCB(SCB_RETRYCB);
SetSCB(SCB_FCLOSE | SCB_DISCONNECT); // connection close
return;
};
}
// repeat in the next call ...
SetSCB(SCB_RETRYCB);
SetNextFunSCB(web_hexdump);
return;
}
/******************************************************************************
* FunctionName : web saved flash
* Description : Processing the flash data send
* Parameters : none (Calback)
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR web_get_flash(TCP_SERV_CONN *ts_conn)
{
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
// Check if this is a first round call
if(CheckSCB(SCB_RETRYCB)==0) {
if(web_conn->udata_start == web_conn->udata_stop) return;
#if DEBUGSOO > 2
os_printf("file_size:%08x ", web_conn->udata_stop - web_conn->udata_start );
#endif
}
// Get/put as many bytes as possible
unsigned int len = mMIN(web_conn->msgbufsize - web_conn->msgbuflen, web_conn->udata_stop - web_conn->udata_start);
// Read Flash addr = web_conn->webfinc_offsets, len = x, buf = sendbuf
#if DEBUGSOO > 2
os_printf("%08x..%08x ",web_conn->udata_start, web_conn->udata_start + len );
#endif
// device_mutex_lock(RT_DEV_LOCK_FLASH);
if(spi_flash_read(web_conn->udata_start, web_conn->msgbuf, len)) {
web_conn->udata_start += len;
web_conn->msgbuflen += len;
if(web_conn->udata_start < web_conn->udata_stop) {
SetNextFunSCB(web_get_flash);
// device_mutex_unlock(RT_DEV_LOCK_FLASH);
SetSCB(SCB_RETRYCB);
return;
};
};
// device_mutex_unlock(RT_DEV_LOCK_FLASH);
ClrSCB(SCB_RETRYCB);
// SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
return;
}
/******************************************************************************
* FunctionName : web saved flash
* Description : Processing the flash data send
* Parameters : none (Calback)
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR web_get_ram(TCP_SERV_CONN *ts_conn)
{
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
// Check if this is a first round call
if(CheckSCB(SCB_RETRYCB)==0) { // On initial call, проверка параметров
if(web_conn->udata_start == web_conn->udata_stop) {
// SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
return;
}
#if DEBUGSOO > 2
os_printf("file_size:%08x ", web_conn->udata_stop - web_conn->udata_start );
#endif
}
// Get/put as many bytes as possible
uint32 len = mMIN(web_conn->msgbufsize - web_conn->msgbuflen, web_conn->udata_stop - web_conn->udata_start);
copy_align4(web_conn->msgbuf, (void *)(web_conn->udata_start), len);
web_conn->msgbuflen += len;
web_conn->udata_start += len;
#if DEBUGSOO > 2
os_printf("%08x-%08x ",web_conn->udata_start, web_conn->udata_start + len );
#endif
if(web_conn->udata_start != web_conn->udata_stop) {
SetSCB(SCB_RETRYCB);
SetNextFunSCB(web_get_ram);
return;
};
ClrSCB(SCB_RETRYCB);
// SetSCB(SCB_FCLOSE | SCB_DISCONNECT);
return;
}
/******************************************************************************
* FunctionName : web_callback
* Description : callback
* Parameters : struct TCP_SERV_CONN
* Returns : none
******************************************************************************/
void ICACHE_FLASH_ATTR web_int_callback(TCP_SERV_CONN *ts_conn, uint8 *cstr)
{
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
// uint8 *cstr = &web_conn->msgbuf[web_conn->msgbuflen];
{
uint8 *vstr = os_strchr(cstr, '=');
if(vstr != NULL) {
*vstr++ = '\0';
web_int_vars(ts_conn, cstr, vstr);
return;
}
}
#if DEBUGSOO > 3
os_printf("[%s]\n", cstr);
#endif
ifcmp("start") tcp_puts("0x%08x", web_conn->udata_start);
else ifcmp("stop") tcp_puts("0x%08x", web_conn->udata_stop);
else ifcmp("xml_") {
cstr+=4;
web_conn->udata_start&=~3;
ifcmp("ram") tcp_puts("0x%08x", *((uint32*)web_conn->udata_start));
else tcp_put('?');
web_conn->udata_start += 4;
}
else ifcmp("sys_") {
cstr+=4;
ifcmp("cid") tcp_puts("%08x", HalGetChipId());
else ifcmp("fid") tcp_puts("%08x", spi_flash_get_id());
else ifcmp("fsize") tcp_puts("%u", spi_flash_real_size()); // flashchip->chip_size
else ifcmp("sdkver") tcp_strcpy_fd(SDK_VERSION);
else ifcmp("sysver") tcp_strcpy_fd(SYS_VERSION);
else ifcmp("webver") tcp_strcpy_fd(WEB_SVERSION);
else ifcmp("heap") tcp_puts("%u", xPortGetFreeHeapSize());
else ifcmp("heapm") tcp_puts("%u", xPortGetMinimumEverFreeHeapSize());
else ifcmp("tcmh") tcp_puts("%u", tcm_heap_freeSpace());
else ifcmp("time") tcp_puts("%u", xTaskGetTickCount());
else ifcmp("mactime") {
if(wifi_mode) {
union {
uint32 dw[2];
uint64 dd;
}ux;
ux.dd = *((uint64_t *)(WIFI_REG_BASE + 0x0560)); // REG_TSFTR -> #include "hal_com_reg.h"
tcp_puts("0x%08x%08x", ux.dw[1], ux.dw[0]);
}
}
else ifcmp("clkcpu") tcp_puts("%u", HalGetCpuClk());
else ifcmp("debug") tcp_put('1' - (print_off & 1)); // rtl_print on/off
else ifcmp("restart") web_conn->web_disc_cb = (web_func_disc_cb)sys_reset;
else ifcmp("ram") tcp_puts("0x%08x", *((uint32 *)(ahextoul(cstr+3)&(~3))));
else ifcmp("rdec") tcp_puts("%d", *((uint32 *)(ahextoul(cstr+4)&(~3))));
else ifcmp("ip") {
uint32 cur_ip;
if(netif_default != NULL) cur_ip = netif_default->ip_addr.addr;
tcp_puts(IPSTR, IP2STR(&cur_ip));
}
#ifdef USE_NETBIOS
else ifcmp("netbios") {
if(syscfg.cfg.b.netbios_ena) tcp_strcpy(netbios_name);
}
#endif
else tcp_put('?');
}
else ifcmp("cfg_") {
cstr += 4;
ifcmp("web_") {
cstr += 4;
ifcmp("port") tcp_puts("%u", syscfg.web_port);
else ifcmp("twrec") tcp_puts("%u", syscfg.web_twrec);
else ifcmp("twcls") tcp_puts("%u", syscfg.web_twcls);
else ifcmp("twd") tcp_put((syscfg.cfg.b.web_time_wait_delete)? '1' : '0');
else tcp_put('?');
}
else ifcmp("pinclr") tcp_put((syscfg.cfg.b.pin_clear_cfg_enable)? '1' : '0');
else ifcmp("debug") tcp_put((syscfg.cfg.b.debug_print_enable)? '1' : '0');
#ifdef USE_NETBIOS
else ifcmp("netbios") tcp_put((syscfg.cfg.b.netbios_ena)? '1' : '0');
#endif
#ifdef USE_SNTP
else ifcmp("sntp") tcp_put((syscfg.cfg.b.sntp_ena)? '1' : '0');
#endif
#ifdef USE_CAPTDNS
else ifcmp("cdns") tcp_put((syscfg.cfg.b.cdns_ena)? '1' : '0');
#endif
else tcp_put('?');
}
else ifcmp("wifi_") {
cstr+=5;
ifcmp("rdcfg") read_wifi_cfg(-1);
else ifcmp("newcfg") {
web_conn->web_disc_cb = (web_func_disc_cb)wifi_run;
web_conn->web_disc_par = wifi_cfg.mode;
}
else ifcmp("cmode") tcp_puts("%d", wifi_mode);
else ifcmp("mode") tcp_puts("%d", wifi_cfg.mode);
else ifcmp("bgn") tcp_puts("%d", wifi_cfg.bgn);
else ifcmp("sleep") tcp_puts("%d", wifi_cfg.sleep);
else ifcmp("txpow") tcp_puts("%u", wifi_cfg.tx_pwr);
else ifcmp("lflg") tcp_puts("%u", wifi_cfg.load_flg);
else ifcmp("sflg") tcp_puts("%u", wifi_cfg.save_flg);
else ifcmp("country") tcp_puts("%u", wifi_cfg.country_code);
else ifcmp("ap_") {
cstr+=3;
ifcmp("ssid") {
int len = os_strlen(wifi_ap_cfg.ssid);
if(len > sizeof(wifi_ap_cfg.ssid)) {
len = sizeof(wifi_ap_cfg.ssid);
}
os_memcpy((char *)&web_conn->msgbuf[web_conn->msgbuflen], wifi_ap_cfg.ssid, len);
web_conn->msgbuflen += len;
}
else ifcmp("psw") {
int len = os_strlen(wifi_ap_cfg.password);
if(len > sizeof(wifi_ap_cfg.password)) {
len = sizeof(wifi_ap_cfg.password);
}
os_memcpy((char *)&web_conn->msgbuf[web_conn->msgbuflen], wifi_ap_cfg.password, len);
web_conn->msgbuflen += len;
}
else ifcmp("chl") tcp_puts("%u", wifi_ap_cfg.channel);
else ifcmp("mcns") tcp_puts("%u", wifi_ap_cfg.max_sta);
else ifcmp("auth") tcp_put((wifi_ap_cfg.security_type == RTW_SECURITY_OPEN) ? '0' : '1');
else ifcmp("hssid") tcp_put((wifi_ap_cfg.ssid_hidden & 1) + '0');
else ifcmp("bint") tcp_puts("%u", wifi_ap_cfg.beacon_interval);
else ifcmp("mac") tcp_puts(MACSTR, MAC2STR(xnetif[wlan_ap_netifn].hwaddr));
else ifcmp("hostname") tcp_strcpy(lwip_host_name[wlan_ap_netifn]);
else ifcmp("dhcp") tcp_puts("%u", wifi_ap_dhcp.mode);
else ifcmp("ip") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.ip));
else ifcmp("gw") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.gw));
else ifcmp("msk") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.mask));
else ifcmp("cip") tcp_puts(IPSTR, IP2STR(&xnetif[wlan_st_netifn].ip_addr.addr));
// else ifcmp("mac") strtomac(pvar, wifi_ap_cfg.macaddr);
// else ifcmp("sip") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.start_ip));
// else ifcmp("eip") tcp_puts(IPSTR, IP2STR(&wifi_ap_dhcp.end_ip));
#if DEBUGSOO > 2
else os_printf(" - none! ");
#endif
}
else ifcmp("st_") {
cstr+=3;
ifcmp("rssi") {
int rssi;
wifi_get_rssi(&rssi);
tcp_puts("%d", rssi);
}
else ifcmp("arec") tcp_puts("%u", wifi_st_cfg.autoreconnect);
else ifcmp("rect") tcp_puts("%u", wifi_st_cfg.reconnect_pause);
else ifcmp("ssid") {
int len = os_strlen(wifi_st_cfg.ssid);
if(len > sizeof(wifi_st_cfg.ssid)) {
len = sizeof(wifi_st_cfg.ssid);
}
os_memcpy((char *)&web_conn->msgbuf[web_conn->msgbuflen], wifi_st_cfg.ssid, len);
web_conn->msgbuflen += len;
}
else ifcmp("psw") {
int len = os_strlen(wifi_st_cfg.password);
if(len > sizeof(wifi_st_cfg.password)) {
len = sizeof(wifi_st_cfg.password);
}
os_memcpy((char *)&web_conn->msgbuf[web_conn->msgbuflen], wifi_st_cfg.password, len);
web_conn->msgbuflen += len;
}
else ifcmp("mac") tcp_puts(MACSTR, MAC2STR(xnetif[wlan_st_netifn].hwaddr));
else ifcmp("bssid") tcp_puts(MACSTR, MAC2STR(wifi_st_cfg.bssid));
else ifcmp("sbss") tcp_puts("%u", wifi_st_cfg.flg);
#if LWIP_NETIF_HOSTNAME
else ifcmp("hostname") tcp_strcpy(lwip_host_name[wlan_st_netifn]);
#endif
else ifcmp("auth") tcp_puts("%u", wifi_st_cfg.security_type);
else ifcmp("dhcp") tcp_puts("%u", wifi_st_dhcp.mode);
else ifcmp("ip") tcp_puts(IPSTR, IP2STR(&wifi_st_dhcp.ip));
else ifcmp("gw") tcp_puts(IPSTR, IP2STR(&wifi_st_dhcp.gw));
else ifcmp("msk") tcp_puts(IPSTR, IP2STR(&wifi_st_dhcp.mask));
#if DEBUGSOO > 5
else os_printf(" - none!\n");
#endif
}
#if DEBUGSOO > 5
else os_printf(" - none!\n");
#endif
}
else ifcmp("bin_") {
cstr+=4;
ifcmp("flash") {
cstr+=5;
if(*cstr == '_') {
cstr++;
ifcmp("all") {
web_conn->udata_start = 0;
web_conn->udata_stop = spi_flash_real_size();
web_get_flash(ts_conn);
}
else ifcmp("sec_") {
web_conn->udata_start = ahextoul(cstr+4) << 12;
web_conn->udata_stop = web_conn->udata_start + FLASH_SECTOR_SIZE;
web_get_flash(ts_conn);
}
else ifcmp("disk") {
web_conn->udata_start = WEBFS_base_addr();
web_conn->udata_stop = web_conn->udata_start + WEBFS_curent_size();
web_get_flash(ts_conn);
}
else tcp_put('?');
}
else web_get_flash(ts_conn);
}
else ifcmp("ram") web_get_ram(ts_conn);
else tcp_put('?');
}
else ifcmp("hexdmp") {
if(cstr[6]=='d') ts_conn->flag.user_option1 = 1;
else ts_conn->flag.user_option1 = 0;
web_hexdump(ts_conn);
}
else ifcmp("web_") {
cstr+=4;
ifcmp("port") tcp_puts("%u", ts_conn->pcfg->port);
else ifcmp("host") tcp_puts(IPSTR ":%d", IP2STR(&(ts_conn->pcb->local_ip.addr)), ts_conn->pcb->local_port);
else ifcmp("remote") tcp_puts(IPSTR ":%d", IP2STR(&(ts_conn->remote_ip.dw)), ts_conn->remote_port);
else ifcmp("twrec") tcp_puts("%u", ts_conn->pcfg->time_wait_rec);
else ifcmp("twcls") tcp_puts("%u", ts_conn->pcfg->time_wait_cls);
else tcp_put('?');
}
else ifcmp("wfs_") {
cstr+=4;
ifcmp("files") tcp_puts("%u", numFiles);
else ifcmp("addr") tcp_puts("0x%08x", WEBFS_base_addr());
else ifcmp("size") tcp_puts("%u", WEBFS_curent_size());
else ifcmp("max_size") tcp_puts("%u", WEBFS_max_size());
else tcp_put('?');
}
#ifdef USE_OVERLAY
else ifcmp("ovl") {
cstr += 3;
if(*cstr == ':') {
int i = ovl_loader(cstr + 1);
if (i == 0) {
if(CheckSCB(SCB_WEBSOC)) {
tcp_puts("%d", ovl_call(1));
}
else {
web_conn->web_disc_cb = (web_func_disc_cb)ovl_call; // адрес старта оверлея
web_conn->web_disc_par = 1; // параметр функции - инициализация
}
}
tcp_puts("%d", i);
}
else if(*cstr == '$') {
if(ovl_call != NULL) tcp_puts("%d", ovl_call(ahextoul(cstr + 1)));
else tcp_put('?');
}
else if(*cstr == '@') {
if(ovl_call != NULL) tcp_puts("%d", ovl_call((int) cstr + 1));
else tcp_put('?');
}
else tcp_put('?');
}
#endif
#ifdef USE_SNTP
else ifcmp("sntp_") {
cstr += 5;
ifcmp("time") tcp_puts("%u", get_sntp_time());
else tcp_put('?');
}
#endif
#ifdef TEST_SEND_WAVE
else ifcmp("test_adc") web_test_adc(ts_conn);
#endif
else ifcmp("hellomsg") tcp_puts_fd("Web on RTL871x!");
else tcp_put('?');
}
#endif // USE_WEB

View file

@ -0,0 +1,356 @@
/******************************************************************************
* FileName: webserver.c
* Description: The web server mode configuration.
*******************************************************************************/
#include "user_config.h"
#ifdef USE_WEB
#include "autoconf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include "lwip/ip.h"
#include "lwip/ip_addr.h"
#include "lwip/tcp.h"
#include "tcpsrv/tcp_srv_conn.h"
#include "ethernetif.h"
#include "web_srv_int.h"
#include "web_utils.h"
#include "flash_eep.h"
#include "device_lock.h"
#include "rtl8195a/rtl_libc.h"
#include "user/sys_cfg.h"
#include "wifi_api.h"
#include "sys_api.h"
#include "esp_comp.h"
#ifdef USE_NETBIOS
#include "netbios.h"
#endif
#ifdef USE_SNTP
#include "sntp.h"
#endif
#ifdef USE_LWIP_PING
#include "lwip/app/ping.h"
struct ping_option pingopt; // for test
#endif
#ifdef USE_CAPTDNS
#include "captdns.h"
#endif
#ifdef USE_MODBUS
#include "modbustcp.h"
#include "mdbtab.h"
#endif
#ifdef USE_RS485DRV
#include "driver/rs485drv.h"
#include "mdbrs485.h"
#endif
#ifdef USE_OVERLAY
#include "overlay.h"
#endif
extern void web_get_ram(TCP_SERV_CONN *ts_conn);
extern void web_get_flash(TCP_SERV_CONN *ts_conn);
extern void web_hexdump(TCP_SERV_CONN *ts_conn);
#define ifcmp(a) if(rom_xstrcmp(cstr, a))
extern int rom_atoi(const char *);
#define atoi rom_atoi
typedef uint32 (* call_func)(uint32 a, uint32 b, uint32 c);
/******************************************************************************
* FunctionName : parse_url
* Description : parse the received data from the server
* Parameters : CurHTTP -- the result of parsing the url
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR web_int_vars(TCP_SERV_CONN *ts_conn, uint8 *pcmd, uint8 *pvar)
{
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
uint32 val = ahextoul(pvar);
char *cstr = pcmd;
#if DEBUGSOO > 1
os_printf("[%s=%s]\n", pcmd, pvar);
#endif
ifcmp("start") web_conn->udata_start = val;
else ifcmp("stop") web_conn->udata_stop = val;
else ifcmp("sys_") {
cstr+=4;
ifcmp("restart") {
if(val == 12345) web_conn->web_disc_cb = (web_func_disc_cb)sys_reset;
}
else ifcmp("ram") { uint32 *ptr = (uint32 *)(ahextoul(cstr+3)&(~3)); str_array(pvar, ptr, 32); }
else ifcmp("debug") print_off = (!val) & 1; // rtl_print on/off
#ifdef USE_LWIP_PING
else ifcmp("ping") {
// struct ping_option *pingopt = (struct ping_option *)UartDev.rcv_buff.pRcvMsgBuff;
pingopt.ip = ipaddr_addr(pvar);
pingopt.count = 3;
pingopt.recv_function=NULL;
pingopt.sent_function=NULL;
ping_start(&pingopt);
}
#endif
}
else ifcmp("cfg_") {
cstr += 4;
ifcmp("web_") {
cstr += 4;
ifcmp("port") {
if(syscfg.web_port != val) {
web_conn->web_disc_par = syscfg.web_port; // ts_conn->pcfg->port
syscfg.web_port = val;
web_conn->web_disc_cb = (web_func_disc_cb)webserver_reinit;
}
}
else ifcmp("twd") {
if(val) {
syscfg.cfg.b.web_time_wait_delete = 1;
ts_conn->pcfg->flag.pcb_time_wait_free = 1;
}
else {
syscfg.cfg.b.web_time_wait_delete = 0;
ts_conn->pcfg->flag.pcb_time_wait_free = 0;
}
}
else ifcmp("twrec") {
syscfg.web_twrec = val;
ts_conn->pcfg->time_wait_rec = val;
}
else ifcmp("twcls") {
syscfg.web_twcls = val;
ts_conn->pcfg->time_wait_cls = val;
}
#if DEBUGSOO > 5
else os_printf(" - none!\n");
#endif
}
else ifcmp("pinclr") syscfg.cfg.b.pin_clear_cfg_enable = (val)? 1 : 0;
else ifcmp("debug") {
syscfg.cfg.b.debug_print_enable = val;
print_off = (!val) & 1; // rtl_print on/off
}
else ifcmp("save") {
if(val == 2) SetSCB(SCB_SYSSAVE); // по закрытию соединения вызвать sys_write_cfg()
else if(val == 1) sys_write_cfg();
}
#ifdef USE_NETBIOS
else ifcmp("netbios") {
syscfg.cfg.b.netbios_ena = (val)? 1 : 0;
if(syscfg.cfg.b.netbios_ena) netbios_init();
else netbios_off();
}
#endif
#ifdef USE_SNTP
else ifcmp("sntp") {
syscfg.cfg.b.sntp_ena = (val)? 1 : 0;
if(syscfg.cfg.b.sntp_ena) sntp_inits();
else sntp_close();
}
#endif
#ifdef USE_CAPTDNS
else ifcmp("cdns") {
syscfg.cfg.b.cdns_ena = (val)? 1 : 0;
if(syscfg.cfg.b.cdns_ena && wifi_softap_get_station_num()) captdns_init();
else captdns_close();
}
#endif
#if DEBUGSOO > 5
else os_printf(" - none!\n");
#endif
// sys_write_cfg();
}
else ifcmp("wifi_") {
cstr+=5;
ifcmp("rdcfg") web_conn->udata_stop = read_wifi_cfg(val);
else ifcmp("newcfg") {
web_conn->web_disc_cb = (web_func_disc_cb)wifi_run;
web_conn->web_disc_par = wifi_cfg.mode;
}
else ifcmp("mode") wifi_cfg.mode = val;
else ifcmp("bgn") wifi_cfg.bgn = val;
else ifcmp("lflg") wifi_cfg.load_flg = val;
else ifcmp("sflg") wifi_cfg.save_flg = val;
else ifcmp("sleep") wifi_cfg.sleep = val;
else ifcmp("txpow") wifi_cfg.tx_pwr = val;
else ifcmp("country") wifi_cfg.country_code = val;
// else ifcmp("scan") {
// web_conn->web_disc_par = val;
// web_conn->web_disc_cb = (web_func_disc_cb)wifi_start_scan;
// }
else ifcmp("save") { write_wifi_cfg(val); }
else ifcmp("ap_") {
cstr+=3;
ifcmp("ssid") {
if(pvar[0]!='\0') {
int len = os_strlen(pvar);
if(len > sizeof(wifi_ap_cfg.ssid)) {
len = sizeof(wifi_ap_cfg.ssid);
}
else os_memset(wifi_ap_cfg.ssid, 0, sizeof(wifi_ap_cfg.ssid));
os_memcpy(wifi_ap_cfg.ssid, pvar, len);
#ifdef USE_NETBIOS
netbios_set_name(wifi_ap_cfg.ssid);
#endif
}
}
else ifcmp("psw") {
int len = os_strlen(pvar);
if(len > sizeof(wifi_ap_cfg.password)) {
len = sizeof(wifi_ap_cfg.password);
}
else os_memset(wifi_ap_cfg.password, 0, sizeof(wifi_ap_cfg.password));
os_memcpy(wifi_ap_cfg.password, pvar, len);
}
else ifcmp("chl") wifi_ap_cfg.channel = val;
else ifcmp("mcns") wifi_ap_cfg.max_sta = val;
else ifcmp("auth") wifi_ap_cfg.security_type = (val)? RTW_SECURITY_WEP_PSK : RTW_SECURITY_OPEN;
else ifcmp("hssid") wifi_ap_cfg.ssid_hidden = val;
else ifcmp("bint") wifi_ap_cfg.beacon_interval = val;
#if LWIP_NETIF_HOSTNAME
else ifcmp("hostname") {
int len = os_strlen(pvar);
if(len >= LWIP_NETIF_HOSTNAME_SIZE) {
len = LWIP_NETIF_HOSTNAME_SIZE-1;
}
os_memcpy(lwip_host_name[wlan_ap_netifn], pvar, len);
lwip_host_name[wlan_ap_netifn][len] = 0;
netbios_set_name(wlan_ap_netifn, pvar);
}
#endif
else ifcmp("dhcp") wifi_ap_dhcp.mode = val;
else ifcmp("ip") wifi_ap_dhcp.ip = ipaddr_addr(pvar);
else ifcmp("gw") wifi_ap_dhcp.gw = ipaddr_addr(pvar);
else ifcmp("msk") wifi_ap_dhcp.mask = ipaddr_addr(pvar);
// else ifcmp("mac") strtomac(pvar, wifi_ap_cfg.macaddr);
// else ifcmp("sip") wifi_ap_dhcp.start_ip = ipaddr_addr(pvar);
// else ifcmp("eip") wifi_ap_dhcp.end_ip = ipaddr_addr(pvar);
#if DEBUGSOO > 2
else os_printf(" - none! ");
#endif
}
else ifcmp("st_") {
cstr+=3;
ifcmp("arec") wifi_st_cfg.autoreconnect = val;
else ifcmp("rect") wifi_st_cfg.reconnect_pause = val;
else ifcmp("ssid") {
if(pvar[0]!='\0') {
int len = os_strlen(pvar);
if(len > sizeof(wifi_st_cfg.ssid)) {
len = sizeof(wifi_st_cfg.ssid);
}
else os_memset(wifi_st_cfg.ssid, 0, sizeof(wifi_st_cfg.ssid));
os_memcpy(wifi_st_cfg.ssid, pvar, len);
}
}
else ifcmp("psw") {
int len = os_strlen(pvar);
if(len > sizeof(wifi_st_cfg.password)) {
len = sizeof(wifi_st_cfg.password);
}
else os_memset(wifi_st_cfg.password, 0, sizeof(wifi_st_cfg.password));
os_memcpy(wifi_st_cfg.password, pvar, len);
}
else ifcmp("auth") wifi_st_cfg.security_type = val;
else ifcmp("bssid") strtomac(pvar, wifi_st_cfg.bssid);
else ifcmp("sbss") wifi_st_cfg.flg = val;
#if LWIP_NETIF_HOSTNAME
else ifcmp("hostname") {
int len = os_strlen(pvar);
if(len >= LWIP_NETIF_HOSTNAME_SIZE) {
len = LWIP_NETIF_HOSTNAME_SIZE-1;
}
os_memcpy(lwip_host_name[wlan_st_netifn], pvar, len);
lwip_host_name[wlan_st_netifn][len] = 0;
netbios_set_name(wlan_st_netifn, pvar);
}
#endif
else ifcmp("dhcp") wifi_st_dhcp.mode = val;
else ifcmp("ip") wifi_st_dhcp.ip = ipaddr_addr(pvar);
else ifcmp("gw") wifi_st_dhcp.gw = ipaddr_addr(pvar);
else ifcmp("msk") wifi_st_dhcp.mask = ipaddr_addr(pvar);
// else ifcmp("mac") strtomac(pvar, wifi_st_cfg.mac);
// else ifcmp("sbss") wifi_st_cfg.bssidx = val;
#if DEBUGSOO > 5
else os_printf(" - none!\n");
#endif
}
#if DEBUGSOO > 5
else os_printf(" - none!\n");
#endif
}
else if(web_conn->bffiles[0]==WEBFS_WEBCGI_HANDLE && CheckSCB(SCB_GET)) {
ifcmp("hexdmp") {
#if DEBUGSOO > 5
os_printf("hexdmp(%p)\n", val);
#endif
if(val > 0) {
if(cstr[6]=='d') ts_conn->flag.user_option1 = 1;
else ts_conn->flag.user_option1 = 0;
uint32 x = ahextoul(cstr+7);
web_conn->udata_start = x;
web_conn->udata_stop = val + web_conn->udata_start;
#if DEBUGSOO > 5
os_printf("start=%p, stop=%p\n", web_conn->udata_start, web_conn->udata_stop);
#endif
web_conn->fileType = HTTP_TXT;
SetSCB(SCB_RETRYCB | SCB_FCALBACK);
SetNextFunSCB(web_hexdump);
};
}
else ifcmp("flash") {
cstr+=5;
if(*cstr == '_') {
cstr++;
ifcmp("all") {
web_conn->udata_start = 0;
web_conn->udata_stop = spi_flash_real_size();
web_conn->fileType = HTTP_BIN;
SetSCB(SCB_RETRYCB | SCB_FCALBACK);
SetNextFunSCB(web_get_flash);
}
else ifcmp("sec_") {
web_conn->udata_start = ahextoul(cstr+4) << 12;
web_conn->udata_stop = web_conn->udata_start + FLASH_SECTOR_SIZE*val;
web_conn->fileType = HTTP_BIN;
SetSCB(SCB_RETRYCB | SCB_FCALBACK);
SetNextFunSCB(web_get_flash);
}
else ifcmp("disk") {
web_conn->udata_start = WEBFS_base_addr();
web_conn->udata_stop = web_conn->udata_start + WEBFS_curent_size();
web_conn->fileType = HTTP_BIN;
SetSCB(SCB_RETRYCB | SCB_FCALBACK);
SetNextFunSCB(web_get_flash);
}
else tcp_put('?');
}
else {
web_conn->fileType = HTTP_BIN;
SetSCB(SCB_RETRYCB | SCB_FCALBACK);
SetNextFunSCB(web_get_flash);
}
}
else ifcmp("bin_ram") {
web_conn->fileType = HTTP_BIN;
SetSCB(SCB_RETRYCB | SCB_FCALBACK);
SetNextFunSCB(web_get_ram);
}
#if DEBUGSOO > 5
else os_printf(" - none! ");
#endif
}
#if DEBUGSOO > 5
else os_printf(" - none! ");
#endif
}
#endif // USE_WEB

2073
project/src/web/web_srv.c Normal file

File diff suppressed because it is too large Load diff

640
project/src/web/web_utils.c Normal file
View file

@ -0,0 +1,640 @@
/*
* web_utils.c
*
* Created on: 25 дек. 2014 г.
* Author: PV`
*/
#include "user_config.h"
#include "autoconf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
//#include "bios.h"
//#include "sdk/add_func.h"
//#include "ets_sys.h"
//#include "os_type.h"
//#include "osapi.h"
//#include "user_interface.h"
#include "web_utils.h"
#include "esp_comp.h"
#define mMIN(a, b) ((a<b)?a:b)
/******************************************************************************
* xstrcpy() из сегментов flash и IRAM с возвратом размера строки:
* на выходе размер строки, без учета терминатора '\0'
*******************************************************************************/
int ICACHE_RAM_ATTR rom_xstrcpy(char * pd, const char * ps)
{
#if 0
union {
unsigned char uc[4];
unsigned int ud;
}tmp;
if(ps == 0 || pd == 0) return (0);
*pd = 0;
unsigned int len = 0;
unsigned int *p = (unsigned int *)((unsigned int)ps & (~3));
unsigned int xlen = (unsigned int)ps & 3;
while(1) {
tmp.ud = *p++;
do {
if((*pd++ = tmp.uc[xlen++]) == 0) return len;
len++;
xlen &= 3;
} while(xlen);
}
#else
int len = 0;
while(*ps) {
*pd++ = *ps++;
len++;
}
return len;
#endif
}
/******************************************************************************
* сравнение строки в ram со строкой в сегменте flash и IRAM
* = 1 если шаблон совпадает
*******************************************************************************/
int ICACHE_RAM_ATTR rom_xstrcmp(char * pd, const char * ps)
{
#if 0
union {
unsigned char uc[4];
unsigned int ud;
}tmp;
if(ps == 0 || pd == 0) return 0;
unsigned int *p = (unsigned int *)((unsigned int)ps & (~3));
unsigned int xlen = (unsigned int)ps & 3;
while(1) {
tmp.ud = *p++;
do {
if(tmp.uc[xlen] == 0) return 1;
if(tmp.uc[xlen++] != *pd || *pd++ == 0) return 0;
xlen &= 3;
} while(xlen);
}
#else
while(*ps) {
if(*pd++ != *ps++) return 0;
}
return 1;
#endif
}
/******************************************************************************
* rom_atoi
*******************************************************************************/
int ICACHE_FLASH_ATTR rom_atoi(const char *s)
{
int n=0, neg=0;
while (*s == ' ') s++;
switch (*s) {
case '-': neg=1;
case '+': s++;
}
/* Compute n as a negative number to avoid overflow on INT_MIN */
while (*s >= '0' && *s <= '9')
n = 10*n - (*s++ - '0');
return neg ? n : -n;
}
/******************************************************************************
* copy_align4
* копирует данные из области кеширования flash и т.д.
*******************************************************************************/
void ICACHE_FLASH_ATTR copy_align4(void *ptrd, void *ptrs, uint32 len)
{
union {
uint8 uc[4];
uint32 ud;
}tmp;
uint8 *pd = ptrd;
uint32 *p = (uint32 *)((uint32)ptrs & (~3));
uint32 xlen = ((uint32)ptrs) & 3;
if(xlen) {
if(((uint32)p >= 0x10000000)&&((uint32)p < 0x9A002000)) tmp.ud = *p++;
else {
tmp.ud = 0;
p++;
}
while (len) {
*pd++ = tmp.uc[xlen++];
len--;
if(xlen >= 4) break;
}
}
xlen = len >> 2;
while(xlen) {
if(((uint32)p >= 0x10000000)&&((uint32)p < 0x9A002000)) tmp.ud = *p++;
else {
tmp.ud = 0;
p++;
}
*pd++ = tmp.uc[0];
*pd++ = tmp.uc[1];
*pd++ = tmp.uc[2];
*pd++ = tmp.uc[3];
xlen--;
}
len &= 3;
if(len) {
if(((uint32)p >= 0x10000000)&&((uint32)p < 0x9A002000)) tmp.ud = *p;
else tmp.ud = 0;
uint8 * ptmp = tmp.uc;
while (len--) *pd++ = *ptmp++;
}
}
/******************************************************************************
* FunctionName : hextoul
*******************************************************************************/
// bool conv_str_hex(uint32 * dest, uint8 *s);
uint32 ICACHE_FLASH_ATTR hextoul(uint8 *s)
{
/*
uint32 val;
if(!conv_str_hex(&val, s)) return 0;
return val;
*/
uint32 val = 0;
while (*s)
{
if (*s >= '0' && *s <= '9')
{
val <<= 4;
val |= *s - '0';
}
else if (*s >= 'A' && *s <= 'F')
{
val <<= 4;
val |= *s - 'A' + 10;
}
else if (*s >= 'a' && *s <= 'f')
{
val <<= 4;
val |= *s - 'a' + 10;
}
else break;
s++;
};
return val;
}
/******************************************************************************
* FunctionName : ahextoul
*******************************************************************************/
// bool convert_para_str(uint32 * dest, uint8 *s);
uint32 ICACHE_FLASH_ATTR ahextoul(uint8 *s)
{
/*
uint32 ret;
if(!convert_para_str(&ret, s)) return 0;
return ret;
*/
if((s[0]=='0') && ((s[1] | 0x20) =='x')) return hextoul(s+2);
return rom_atoi(s);
}
/******************************************************************************
* FunctionName : cmpcpystr
* Description : выбирает слово из строки текста с заданными начальным символом
* и конечным терминатором. Терминатор и стартовый символ не копирует, если заданы.
* Parameters : При задании начального символа = '\0' берется любой символ (>' ').
Копирует до символа <' ' или терминатора.
Задается ограничение размера буфера для копируемого слова (с дописыванием в буфер '\0'!).
* Returns : Зависит от значения терминатора, указывает на терминатор в строке,
если терминатор найден.
Если NULL, то начальный или конечный терминатор не найден.
*******************************************************************************/
uint8 * ICACHE_FLASH_ATTR cmpcpystr(uint8 *pbuf, uint8 *pstr, uint8 a, uint8 b, uint16 len)
{
if(len == 0) pbuf = NULL;
if(pstr == NULL) {
if(pbuf != NULL) *pbuf='\0';
return NULL;
};
uint8 c;
do {
c = *pstr;
if(c < ' ') { // строка кончилась
if(pbuf != NULL) *pbuf='\0';
return NULL; // id не найден
};
if((a == '\0')&&(c > ' ')) break; // не задан -> любой символ
pstr++;
if(c == a) break; // нашли стартовый символ (некопируемый в буфер)
}while(1);
if(pbuf != NULL) {
while(len--) {
c = *pstr;
if(c == b) { // нашли терминирующий символ (некопируемый в буфер)
*pbuf='\0';
return pstr; // конечный терминатор найден
};
// if(c <= ' ') { // строка кончилась или пробел
if(c < ' ') { // строка кончилась или пробел
*pbuf='\0';
return NULL; // конечный терминатор не найден
};
pstr++;
*pbuf++ = c;
};
*--pbuf='\0'; // закрыть буфер
};
do {
c = *pstr;
if(c == b) return pstr; // нашли терминирующий символ
// if(c <= ' ') return NULL; // строка кончилась
if(c < ' ') return NULL; // строка кончилась
pstr++;
}while(1);
}
/******************************************************************************
* FunctionName : str_array
* Набирает из строки s массив слов в buf в кол-ве до max_buf
* возврат - кол-во переменных в строке
* Разделитель переменных в строке ','
* Если нет переменной, то пропускает изменение в buf
* Примеры:
* Строка "1,2,3,4" -> buf = 0x01 0x02 0x03 0x04
* Строка "1,,3," -> buf = 0x01 (не изменено) 0x03 (не изменено)
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR str_array(uint8 *s, uint32 *buf, uint32 max_buf)
{
uint32 ret = 0;
uint8 *sval = NULL;
while(max_buf > ret) {
if(sval == NULL) {
if (*s == '-' && s[1] >= '0' && s[1] <= '9') {
sval = s;
s++;
}
else if (*s >= '0' && *s <= '9') sval = s;
}
if(*s == ',' || *s <= ')') {
if(sval != NULL) {
*buf = ahextoul(sval);
sval = NULL;
}
buf++;
ret++;
if(*s < ')') return ret;
}
s++;
}
return ret;
}
uint32 ICACHE_FLASH_ATTR str_array_w(uint8 *s, uint16 *buf, uint32 max_buf)
{
uint32 ret = 0;
uint8 *sval = NULL;
while(max_buf > ret) {
if(sval == NULL) {
if (*s == '-' && s[1] >= '0' && s[1] <= '9') {
sval = s;
s++;
}
else if (*s >= '0' && *s <= '9') sval = s;
}
if(*s == ',' || *s <= ')') {
if(sval != NULL) {
*buf = ahextoul(sval);
sval = NULL;
}
buf++;
ret++;
if(*s < ')') return ret;
}
s++;
}
return ret;
}
uint32 ICACHE_FLASH_ATTR str_array_b(uint8 *s, uint8 *buf, uint32 max_buf)
{
uint32 ret = 0;
uint8 *sval = NULL;
while(max_buf > ret) {
if(sval == NULL) {
if (*s == '-' && s[1] >= '0' && s[1] <= '9') {
sval = s;
s++;
}
else if (*s >= '0' && *s <= '9') sval = s;
}
if(*s == ',' || *s == '.' || *s <= ')') {
if(sval != NULL) {
*buf = ahextoul(sval);
sval = NULL;
}
buf++;
ret++;
if(*s < ')') return ret;
}
s++;
}
return ret;
}
/******************************************************************************
* FunctionName : strtmac
*******************************************************************************/
void ICACHE_FLASH_ATTR strtomac(uint8 *s, uint8 *macaddr)
{
uint8 pbuf[4];
s = cmpcpystr(pbuf, s, 0, ':', 3);
*macaddr++ = hextoul(pbuf);
int i = 4;
while(i--) {
s = cmpcpystr(pbuf, s, ':', ':', 3);
*macaddr++ = hextoul(pbuf);
}
s = cmpcpystr(pbuf, s, ':', ' ', 3);
*macaddr++ = hextoul(pbuf);
}
/******************************************************************************
* FunctionName : urldecode
*******************************************************************************/
int ICACHE_FLASH_ATTR urldecode(uint8 *d, uint8 *s, uint16 lend, uint16 lens)
{
uint16 ret = 0;
if(s != NULL) while ((lens--) && (lend--) && (*s > ' ')) {
if ((*s == '%')&&(lens > 1)) {
s++;
int i = 2;
uint8 val = 0;
while(i--) {
if (*s >= '0' && *s <= '9') {
val <<= 4;
val |= *s - '0';
} else if (*s >= 'A' && *s <= 'F') {
val <<= 4;
val |= *s - 'A' + 10;
} else if (*s >= 'a' && *s <= 'f') {
val <<= 4;
val |= *s - 'a' + 10;
} else
break;
s++;
lens--;
};
s--;
*d++ = val;
} else if (*s == '+')
*d++ = ' ';
else
*d++ = *s;
ret++;
s++;
}
*d = '\0';
return ret;
}
/******************************************************************************
* FunctionName : urlencode
*******************************************************************************/
/*int ICACHE_FLASH_ATTR urlencode(uint8 *d, uint8 *s, uint16 lend, uint16 lens)
{
uint16 ret = 0;
if(s != NULL) while ((lens--) && (lend--) && (*s != '\0')) {
if ( (48 <= *s && *s <= 57) //0-9
|| (65 <= *s && *s <= 90) //abc...xyz
|| (97 <= *s && *s <= 122) //ABC...XYZ
|| (*s == '~' || *s == '!' || *s == '*' || *s == '(' || *s == ')' || *s == '\'')) {
*d++ = *s++;
ret++;
} else {
if(lend >= 3) {
ret += 3;
lend -= 3;
*d++ = '%';
uint8 val = *s >> 4;
if(val <= 9) val += '0';
else val += 0x41 - 10;
*d++ = val;
val = *s++ & 0x0F;
if(val <= 9) val += '0';
else val += 0x41 - 10;
*d++ = val;
}
else break;
}
}
*d = '\0';
return ret;
}*/
/******************************************************************************
* FunctionName : htmlcode
*******************************************************************************/
int ICACHE_FLASH_ATTR htmlcode(uint8 *d, uint8 *s, uint16 lend, uint16 lens)
{
uint16 ret = 0;
if(s != NULL) while ((lens--) && (lend--) && (*s != '\0')) {
if ( *s == 0x27 ) { // "'" &apos;
if(lend >= 6) {
ret += 6;
lend -= 6;
s++;
*d++ = '&';
*d++ = 'a';
*d++ = 'p';
*d++ = 'o';
*d++ = 's';
*d++ = ';';
}
else break;
} else if ( *s == '"' ) { // &quot;
if(lend >= 6) {
ret += 6;
lend -= 6;
s++;
*d++ = '&';
*d++ = 'q';
*d++ = 'u';
*d++ = 'o';
*d++ = 't';
*d++ = ';';
}
else break;
} else if ( *s == '&' ) { // &amp;
if(lend >= 5) {
ret += 5;
lend -= 5;
s++;
*d++ = '&';
*d++ = 'a';
*d++ = 'm';
*d++ = 'p';
*d++ = ';';
}
else break;
} else if ( *s == '<' ) { // &lt;
if(lend >= 4) {
ret += 4;
lend -= 4;
s++;
*d++ = '&';
*d++ = 'l';
*d++ = 't';
*d++ = ';';
}
else break;
} else if ( *s == '>' ) { // &gt;
if(lend >= 4) {
ret += 4;
lend -= 4;
s++;
*d++ = '&';
*d++ = 'g';
*d++ = 't';
*d++ = ';';
}
else break;
} else {
*d++ = *s++;
ret++;
}
}
*d = '\0';
return ret;
}
//=============================================================================
uint8* ICACHE_FLASH_ATTR
web_strnstr(const uint8* buffer, const uint8* token, int len)
{
const uint8* p;
int tokenlen = rtl_strlen(token);
if (tokenlen == 0) {
return (uint8 *)buffer;
};
for (p = buffer; *p && (p + tokenlen <= buffer + len); p++) {
if ((*p == *token) && (rtl_strncmp(p, token, tokenlen) == 0)) {
return (uint8 *)p;
};
};
return NULL;
}
//=============================================================================
static const uint8_t base64map[128] ICACHE_RODATA_ATTR =
{
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255
};
//=============================================================================
bool ICACHE_FLASH_ATTR base64decode(const uint8 *in, int len, uint8_t *out, int *outlen)
{
// uint8 *map = (uint8 *)UartDev.rcv_buff.pRcvMsgBuff;
// ets_memcpy(map, base64map, 128);
uint8 *map = base64map;
int g, t, x, y, z;
uint8_t c;
g = 3;
for (x = y = z = t = 0; x < len; x++) {
if ((c = map[in[x]&0x7F]) == 0xff) continue;
if (c == 254) { /* this is the end... */
c = 0;
if (--g < 0) return false;
}
else if (g != 3) return false; /* only allow = at end */
t = (t<<6) | c;
if (++y == 4) {
out[z++] = (uint8_t)((t>>16)&255);
if (g > 1) out[z++] = (uint8_t)((t>>8)&255);
if (g > 2) out[z++] = (uint8_t)(t&255);
y = t = 0;
}
/* check that we don't go past the output buffer */
if (z > *outlen) return false;
}
if (y != 0) return false;
*outlen = z;
return true;
}
//=============================================================================
/* Table 6-bit-index-to-ASCII used for base64-encoding */
const uint8_t base64_table[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'+', '/'
};
// ld: PROVIDE ( base64_table = 0x3FFFD600 );
//extern const uint8_t base64_table[];
//=============================================================================
/** Base64 encoding */
size_t ICACHE_FLASH_ATTR base64encode(char* target, size_t target_len, const char* source, size_t source_len)
{
size_t i;
sint8 j;
size_t target_idx = 0;
size_t longer = 3 - (source_len % 3);
size_t source_len_b64 = source_len + longer;
size_t len = (((source_len_b64) * 4) / 3);
uint8 x = 5;
uint8 current = 0;
if(target == NULL || target_len < len) return 0;
for (i = 0; i < source_len_b64; i++) {
uint8 b = (i < source_len ? source[i] : 0);
for (j = 7; j >= 0; j--, x--) {
uint8 shift = ((b & (1 << j)) != 0) ? 1 : 0;
current |= shift << x;
if (x == 0) {
target[target_idx++] = base64_table[current];
x = 6;
current = 0;
}
}
}
for (i = len - longer; i < len; i++) {
target[i] = '=';
}
return len;
}
/*
//=============================================================================
void ICACHE_FLASH_ATTR print_hex_dump(uint8 *buf, uint32 len, uint8 k)
{
if(!system_get_os_print()) return; // if(*((uint8 *)(0x3FFE8000)) == 0) return;
uint32 ss[2];
ss[0] = 0x78323025; // "%02x"
ss[1] = k; // ","...'\0'
uint8* ptr = buf;
while(len--) {
if(len == 0) ss[1] = 0;
ets_printf((uint8 *)&ss[0], *ptr++);
}
}
*/
//=============================================================================
#define LowerCase(a) ((('A' <= a) && (a <= 'Z')) ? a + 32 : a)
char* ICACHE_FLASH_ATTR word_to_lower_case(char* text) {
for(; *text ==' '; text++);
char* p = text;
for (; *p >= ' '; p++) {
*p = LowerCase(*p);
}
return text;
}
#if 0
//=============================================================================
/* char UpperCase(char ch) {
return (('a' <= ch) && (ch <= 'z')) ? ch - 32 : ch; }*/
#define UpperCase(a) ((('a' <= a) && (a <= 'z')) ? a - 32 : a)
char* ICACHE_FLASH_ATTR str_to_upper_case(char* text) {
char* p = text;
for (; *p; ++p) {
*p = UpperCase(*p);
}
return text;
}
#endif

View file

@ -0,0 +1,347 @@
/******************************************************************************
* FileName: web_websocket.c
* Description: websocket for web
* Author: pvvx
* 2016
*******************************************************************************/
#include "user_config.h"
#ifdef WEBSOCKET_ENA
#include "autoconf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
//#include "bios.h"
//#include "osapi.h"
//#include "sdk/rom2ram.h"
#include "lwip/tcp.h"
#include "tcpsrv/tcp_srv_conn.h"
#include "web_srv_int.h"
#include "web_utils.h"
#include "web_websocket.h"
#include "rtl8195a/rtl_libc.h"
#include "esp_comp.h"
#if 0
#undef DEBUGSOO
#define DEBUGSOO 4
#endif
#define copy_s4d1 rtl_memcpy
#define mMIN(a, b) ((a<b)?a:b)
#define MAX_RX_BUF_SIZE 8192
const char txt_wsping[] ICACHE_RODATA_ATTR = "ws:ping";
const char txt_wspong[] ICACHE_RODATA_ATTR = "ws:pong";
//=============================================================================
// websock_tx_frame() - передача фрейма
//=============================================================================
err_t ICACHE_FLASH_ATTR
websock_tx_frame(TCP_SERV_CONN *ts_conn, uint32 opcode, uint8 *raw_data, uint32 raw_len)
{
err_t err = WebsocketTxFrame(ts_conn, opcode, raw_data, raw_len);
if(err != ERR_OK) {
#if DEBUGSOO > 3
os_printf("ws%utx[%u] error %d!\n", opcode, raw_len, err);
#endif
((WEB_SRV_CONN *)ts_conn->linkd)->webflag |= SCB_DISCONNECT;
}
else {
if((opcode & WS_OPCODE_BITS) == WS_OPCODE_CLOSE) {
((WEB_SRV_CONN *)ts_conn->linkd)->ws.flg |= WS_FLG_CLOSE;
}
}
return err;
}
//=============================================================================
// websock_tx_close_err() - вывод сообщения закрытия или ошибки
//=============================================================================
err_t ICACHE_FLASH_ATTR
websock_tx_close_err(TCP_SERV_CONN *ts_conn, uint32 err)
{
uint8 uc[2];
uc[1] = err;
uc[0] = err>>8;
return websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, uc, 2);
}
//=============================================================================
// websock_rx_data() прием данных
//=============================================================================
#define MAX_WS_DATA_BLK_SIZE (tcp_sndbuf(ts_conn->pcb)-8) // (TCP_MSS - 8)
//=============================================================================
bool ICACHE_FLASH_ATTR
websock_rx_data(TCP_SERV_CONN *ts_conn)
{
// HTTP_CONN *CurHTTP;
WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
if(web_conn == NULL) return false;
WS_FRSTAT *ws = &web_conn->ws;
uint16 len;
uint8 *pstr;
#if DEBUGSOO > 3
os_printf("ws_rx[%u]%u ", ts_conn->sizei, ts_conn->cntri);
#endif
if(ts_conn->sizei == 0) return true; // докачивать
tcpsrv_unrecved_win(ts_conn);
if((ws->flg & WS_FLG_CLOSE) != 0) {
// убить буфер ts_conn->pbufi, конец давно :)
web_feee_bufi(ts_conn);
SetSCB(SCB_DISCONNECT);
return false;
}
if(ts_conn->sizei > MAX_RX_BUF_SIZE) {
#if DEBUGSOO > 0
os_printf("ws:rxbuf_full! ");
#endif
// убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR
web_feee_bufi(ts_conn);
websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG); // WS_CLOSE_UNEXPECTED_ERROR);
SetSCB(SCB_DISCONNECT);
return false;
}
pstr = ts_conn->pbufi;// + ts_conn->cntri;
len = ts_conn->sizei;// - ts_conn->cntri;
while(ts_conn->cntri < ts_conn->sizei || (ws->flg & WS_FLG_FIN) != 0) {
pstr = ts_conn->pbufi;// + ts_conn->cntri;
len = ts_conn->sizei;// - ts_conn->cntri;
if((ws->flg & WS_FLG_FIN) != 0 // обработка
|| ws->frame_len > ws->cur_len) {
ws->flg &= ~WS_FLG_FIN;
len = mMIN(ws->frame_len - ws->cur_len, mMIN(MAX_WS_DATA_BLK_SIZE, len));
// размаскировать
if((ws->flg & WS_FLG_MASK) != 0) WebsocketMask(ws, pstr, len);
#if DEBUGSOO > 3
os_printf("wsfr[%u]blk[%u]at:%u ", ws->frame_len, len, ws->cur_len);
#endif
switch(ws->status) {
case sw_frs_binary:
#if DEBUGSOO > 1
os_printf("ws:bin ");
#endif
if(ws->frame_len != 0) {
// пока просто эхо
uint32 opcode = WS_OPCODE_BINARY;
if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
return false; // не докачивать, ошибка или закрытие
}
}
ws->cur_len += len;
ts_conn->cntri += len;
break;
case sw_frs_text:
#if DEBUGSOO > 1
os_printf("ws:txt ");
#if DEBUGSOO > 2
if(ws->frame_len != 0) {
uint8 tt = pstr[len];
pstr[len] = 0;
os_printf("'%s' ", pstr);
pstr[len] = tt;
}
#endif
#endif
if(ws->frame_len == ws->cur_len + len && ws->frame_len != 0) { // полное соо
web_conn->msgbufsize = tcp_sndbuf(ts_conn->pcb); // сколько можем выввести сейчас?
if (web_conn->msgbufsize < MIN_SEND_SIZE) {
#if DEBUGSOO > 0
os_printf("ws:sndbuf=%u! ", web_conn->msgbufsize);
#endif
websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
return false;
}
if(ws->frame_len == (sizeof(txt_wsping)-1) && rom_xstrcmp(pstr, txt_wsping) != 0){
copy_s4d1(pstr, (void *)txt_wspong, sizeof(txt_wspong) - 1);
if(websock_tx_frame(ts_conn, WS_OPCODE_TEXT | WS_FRAGMENT_FIN, pstr, sizeof(txt_wspong) - 1) != ERR_OK) {
return false; // не докачивать, ошибка или закрытие
}
}
else {
web_conn->msgbuf = (uint8 *) os_malloc(web_conn->msgbufsize);
if (web_conn->msgbuf == NULL) {
#if DEBUGSOO > 0
os_printf("ws:mem!\n");
#endif
websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
return false;
};
web_conn->msgbuflen = 0;
uint32 opcode;
if(CheckSCB(SCB_RETRYCB)) { // повторный callback? да
if(web_conn->func_web_cb != NULL) web_conn->func_web_cb(ts_conn);
if(!CheckSCB(SCB_RETRYCB)) {
ClrSCB(SCB_FCLOSE | SCB_DISCONNECT);
opcode = WS_OPCODE_CONTINUE | WS_FRAGMENT_FIN;
}
else opcode = WS_OPCODE_CONTINUE;
}
else {
pstr[len] = '\0';
uint8 *vstr = os_strchr(pstr, '=');
if(vstr != NULL) {
*vstr++ = '\0';
web_int_vars(ts_conn, pstr, vstr);
}
else {
web_conn->msgbuf[0] = 0;
web_int_callback(ts_conn, pstr);
}
if(CheckSCB(SCB_RETRYCB)) opcode = WS_OPCODE_TEXT;
else {
ClrSCB(SCB_FCLOSE | SCB_DISCONNECT);
opcode = WS_OPCODE_TEXT | WS_FRAGMENT_FIN;
}
}
if(web_conn->msgbuflen != 0) {
if(websock_tx_frame(ts_conn, opcode, web_conn->msgbuf, web_conn->msgbuflen) != ERR_OK) {
os_free(web_conn->msgbuf);
web_conn->msgbuf = NULL;
return false; // не докачивать, ошибка или закрытие
}
}
os_free(web_conn->msgbuf);
web_conn->msgbuf = NULL;
if(CheckSCB(SCB_RETRYCB)) return false;
}
}
/*
if(0) {
uint32 opcode = WS_OPCODE_TEXT;
if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
return false; // не докачивать, ошибка или закрытие
}
}
*/
ws->cur_len += len;
ts_conn->cntri += len;
return true; // докачивать
// break;
// break;
case sw_frs_ping:
#if DEBUGSOO > 1
os_printf("ws:ping ");
#endif
{
uint32 opcode = WS_OPCODE_PONG;
if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
return false; // не докачивать, ошибка или закрытие
}
}
ws->cur_len += len;
ts_conn->cntri += len;
return true; // докачивать
// break;
case sw_frs_pong:
#if DEBUGSOO > 1
os_printf("ws:pong ");
#endif
ws->cur_len += len;
ts_conn->cntri += len;
break;
// return true;
case sw_frs_close:
#if DEBUGSOO > 1
os_printf("ws:close ");
#endif
// if((ws->flg & WS_FLG_CLOSE) == 0) {
{
if(len >= 2) {
uint32 close_code = (pstr[0]<<8) | pstr[1];
#if DEBUGSOO > 1
os_printf("code:%d ", close_code);
#endif
if(close_code == WS_CLOSE_NORMAL) websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL);
// else websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0);
}
else
{
websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL);
// websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0);
}
}
ts_conn->flag.pcb_time_wait_free = 1;
SetSCB(SCB_DISCONNECT);
// ts_conn->cntri = ts_conn->sizei;
/* ws->cur_len += len;
ts_conn->cntri += len; */
return false;
default:
#if DEBUGSOO > 0
os_printf("ws:f?! ");
#endif
websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
SetSCB(SCB_DISCONNECT);
// ts_conn->cntri = ts_conn->sizei;
return false;
}
}
else
if(ws->cur_len >= ws->frame_len) { // прием и разбор нового фрейма
if((ws->flg & WS_FLG_FIN) != 0) { // обработка
#if DEBUGSOO > 3
os_printf("ws_rx:fin=%u ", ws->cur_len);
#endif
}
else {
uint32 ret = WebsocketHead(ws, pstr, len);
if(ret >= WS_CLOSE_NORMAL) { // error или close
#if DEBUGSOO > 0
os_printf("ws:txerr=%u ", ret);
#endif
websock_tx_close_err(ts_conn, ret);
// ts_conn->cntri = ts_conn->sizei; // убить буфер ts_conn->pbufi
return false; // error
}
else if(ret == 0) {
#if DEBUGSOO > 3
os_printf("ws_rx... ");
#endif
return true; // докачивать
}
ts_conn->cntri += ws->head_len; // вычесть заголовок
/*
switch(ws->status) {
case sw_frs_binary:
break;
case sw_frs_text:
if(ws->frame_len > MAX_RX_BUF_SIZE) {
websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG);
return false;
}
break;
}
*/
}
}
#if DEBUGSOO > 3
os_printf("trim%u-%u ", ts_conn->sizei, ts_conn->sizei - ts_conn->cntri );
#endif
if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[ts_conn->cntri], ts_conn->sizei - ts_conn->cntri)) {
#if DEBUGSOO > 0
os_printf("ws:trim_err! ");
#endif
// убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR
websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
SetSCB(SCB_DISCONNECT);
// ts_conn->cntri = ts_conn->sizei;
return false;
};
}
return false; // не докачивать, ошибка или закрытие
}
//=============================================================================
//=============================================================================
#endif // WEBSOCKET_ENA

245
project/src/web/websock.c Normal file
View file

@ -0,0 +1,245 @@
/******************************************************************************
* FileName: websock.c
* Description: websocket for web ESP8266
* Author: PV`
* (c) PV` 2016
*******************************************************************************/
#include "user_config.h"
#ifdef WEBSOCKET_ENA
#include "autoconf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include "tcpsrv/tcp_srv_conn.h"
#include "web_utils.h" // base64encode()
#include "web_srv.h"
//#include "phy/phy.h"
#include "device_lock.h"
#include "lwip/tcp.h"
#include "websock.h"
#include "rtl8195a/rtl_libc.h"
#include "esp_comp.h"
#include "hal_crypto.h"
// HTTP/1.1 101 Web Socket Protocol Handshake\r\n
const uint8 WebSocketHTTPOkKey[] ICACHE_RODATA_ATTR = "HTTP/1.1 101 Switching Protocols\r\nAccess-Control-Allow-Origin: *\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\n\r\n";
const uint8 WebSocketAddKey[] ICACHE_RODATA_ATTR = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
const uint8 *HTTPUpgrade = "Upgrade:";
const uint8 *HTTPwebsocket = "websocket";
const uint8 *HTTPSecWebSocketKey = "Sec-WebSocket-Key:";
//=============================================================================
// WebSocketAcceptKey()
// 1) взять строковое значение из заголовка Sec-WebSocket-Key и объединить со
// строкой 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
// 2) вычислить бинарный хеш SHA-1 (бинарная строка из 20 символов) от полученной
// в первом пункте строки
// 3) закодировать хеш в Base64
// skey[24+36]:'dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
// cha:'b37a4f2cc0624f1690f64606cf385945b2bec4ea'
// key[28]:'s3pPLMBiTxaQ9kYGzzhZRbK+xOo='
//=============================================================================
uint8 buff[maxsizeWebSocketKey + sizeWebSocketAddKey]; // [68]
bool ICACHE_FLASH_ATTR WebSocketAcceptKey(uint8* dkey, uint8* skey)
{
int len = 0;
bool ret = false;
uint8 keybuf[CRYPTO_SHA1_DIGEST_LENGTH];
uint8 * buff = os_malloc(maxsizeWebSocketKey + sizeWebSocketAddKey);
if(buff) {
while(skey[len] >= '+' && len < maxsizeWebSocketKey) {
buff[len] = skey[len];
len++;
};
if(len > minsizeWebSocketKey) {
rtl_memcpy(&buff[len], WebSocketAddKey, sizeWebSocketAddKey+1);
device_mutex_lock(RT_DEV_LOCK_CRYPTO);
rtl_crypto_sha1(buff, len + sizeWebSocketAddKey, keybuf);
device_mutex_unlock(RT_DEV_LOCK_CRYPTO);
// rtl_cryptoEngine_info();
len = base64encode(dkey, FileNameSize, keybuf, CRYPTO_SHA1_DIGEST_LENGTH);
#if DEBUGSOO > 2
os_printf("\ncha:'");
print_hex_dump(keybuf, CRYPTO_SHA1_DIGEST_LENGTH, '\0');
os_printf("'\n");
os_printf("key[%u]:'%s'\n", len, dkey);
#endif
ret = true;
}
os_free(buff);
}
return ret;
}
//=============================================================================
// websock_mask() размаскирование блока
//=============================================================================
void ICACHE_FLASH_ATTR
WebsocketMask(WS_FRSTAT *ws, uint8 *raw_data, uint32 raw_len)
{
uint32 i, x = ws->cur_len;
#if DEBUGSOO > 3
os_printf("mask[%u]%u ", raw_len, x);
#endif
for (i = 0; i < raw_len; i++) {
raw_data[i] ^= ws->mask.uc[x++ & 3];
}
}
//=============================================================================
// websock_head() разбор заголовка
//=============================================================================
uint32 ICACHE_FLASH_ATTR
WebsocketHead(WS_FRSTAT *ws, uint8 *raw_data, uint32 raw_len)
{
// определить размер заголовка фрейма
uint32 head_len = 2;
if(raw_len < head_len) return 0; // докачивать
uint32 data_len = raw_data[1] & WS_SIZE1_BITS;
if(data_len == 127) head_len = 10;
else if(data_len == 126) head_len = 4;
if(raw_data[1] & WS_MASK_FLG) head_len += 4;
if(raw_len < head_len) return 0; // докачивать
ws->head_len = head_len;
ws->cur_len = 0;
ws->flg = 0;
data_len = raw_data[1] & WS_SIZE1_BITS;
if(data_len >= 126) {
if(data_len == 127) {
uint32 i;
for(i = 3; i < 6; i++) {
if(raw_data[i] != 0) {
ws->status = sw_frs_close;
ws->frame_len = 0;
return WS_CLOSE_MESSAGE_TOO_BIG;
}
}
data_len = (raw_data[6] << 24) | (raw_data[7] << 16) | (raw_data[8] << 8) | raw_data[9];
}
else {
data_len = (raw_data[2] << 8) | raw_data[3];
}
}
if(raw_data[1] & WS_MASK_FLG) {
ws->flg |= WS_FLG_MASK;
ws->mask.uc[0] = raw_data[head_len-4];
ws->mask.uc[1] = raw_data[head_len-3];
ws->mask.uc[2] = raw_data[head_len-2];
ws->mask.uc[3] = raw_data[head_len-1];
}
// else ws->mask = 0;
uint8 opcode = raw_data[0] & WS_OPCODE_BITS;
switch(opcode) {
case WS_OPCODE_PING: // эхо - дублировать прием
raw_data[0] &= ~WS_FRAGMENT_FIN;
raw_data[0] |= WS_OPCODE_PONG;
ws->status = sw_frs_pong;
ws->frame_len = data_len;
break;
case WS_OPCODE_PONG: // эхо - дублировать прием
ws->status = sw_frs_ping;
ws->frame_len = data_len;
break;
case WS_OPCODE_CONTINUE: // продолжить
if(ws->status == sw_frs_pong) {
ws->frame_len = data_len;
break;
}
else ws->frame_len += data_len;
break;
case WS_OPCODE_CLOSE: //
ws->status = sw_frs_close;
ws->frame_len = data_len;
break;
case WS_OPCODE_TEXT:
ws->status = sw_frs_text;
ws->frame_len = data_len;
break;
case WS_OPCODE_BINARY:
ws->status = sw_frs_binary;
ws->frame_len = data_len;
break;
default:
ws->status = sw_frs_close;
ws->frame_len = 0;
return WS_CLOSE_WRONG_TYPE;
}
// uint32 len = mMIN(raw_len - head_len, data_len);
// if((ws->flg & WS_FLG_MASK) != 0) websock_mask(ws, &raw_data[head_len], mMIN(raw_len - head_len, len));
// ws->cur_len += len;
if((raw_data[0] & WS_FRAGMENT_FIN) != 0) { // конец - данные на обработку
ws->flg |= WS_FLG_FIN;
}
#if DEBUGSOO > 1
os_printf("ws#%02xrx[%u] ", raw_data[0], data_len);
#endif
return 1;
/*
if(data_len + head_len <= raw_len) { // весь пакет уже в буфере?
return 1;
}
return 0; // докачивать */
}
//=============================================================================
// websock_tx_frame() - передача фрейма
//=============================================================================
err_t ICACHE_FLASH_ATTR
WebsocketTxFrame(TCP_SERV_CONN *ts_conn, uint32 opcode, uint8 *raw_data, uint32 raw_len)
{
union {
uint8 uc[8];
uint16 uw[4];
uint32 ud[2];
}head;
union {
uint8 uc[4];
uint16 uw[2];
uint32 ud;
}mask;
if(raw_data == NULL) raw_len = 0;
head.ud[0] = opcode;
uint32 head_len;
if(raw_len > 126) {
head.uc[1] = 126;
head.uc[2] = raw_len>>8;
head.uc[3] = raw_len;
head_len = 4;
}
else {
head.uc[1] = raw_len;
head_len = 2;
};
if(opcode & (WS_MASK_FLG << 8)) {
mask.ud ^= rand();
head.uc[1] |= WS_MASK_FLG;
head.uc[head_len] = mask.uc[0];
head.uc[head_len+1] = mask.uc[1];
head.uc[head_len+2] = mask.uc[2];
head.uc[head_len+3] = mask.uc[3];
head_len += 4;
}
uint32 len = tcp_sndbuf(ts_conn->pcb);
err_t err = 1; // ERR_BUF;
if(len >= raw_len + head_len) {
#if DEBUGSOO > 1
os_printf("ws#%02xtx[%u] ", head.uc[0], raw_len);
#endif
ts_conn->flag.nagle_disabled = 0;
tcp_nagle_disable(ts_conn->pcb);
err = tcpsrv_int_sent_data(ts_conn, head.uc, head_len);
ts_conn->flag.nagle_disabled = 1;
if(err == ERR_OK && raw_len != 0) {
if(opcode & (WS_MASK_FLG << 8)) {
uint32 i;
for (i = 0; i < raw_len; i++) {
raw_data[i] ^= mask.uc[i & 3];
}
}
err = tcpsrv_int_sent_data(ts_conn, raw_data, raw_len);
}
}
return err;
}
#endif // WEBSOCKET_ENA

483
project/src/webfs/webfs.c Normal file
View file

@ -0,0 +1,483 @@
/*********************************************************************
* WEBFS.c
* RTL871x Flash WEB File System v1.0
********************************************************************/
#include "autoconf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include <osdep_api.h>
#include <osdep_service.h>
#include "device_lock.h"
#include "flash_api.h"
//#include "flash_eep.h"
#include "webfs/webfs.h"
#include "rtl8195a/rtl_libc.h"
#include "esp_comp.h"
#define WEBFS_CODE_ATTR
#define WEBFS_DATA_ATTR
#define web_mutex_lock() device_mutex_lock(RT_DEV_LOCK_FLASH)
#define web_mutex_unlock() device_mutex_unlock(RT_DEV_LOCK_FLASH)
// Supports long file names to 64 characters
#define MAX_FILE_NAME_LEN 64 // VarNameSize
uint32 disk_base_addr WEBFS_DATA_ATTR;
#define WEBFS_HEAD_ADDR disk_base_addr
/*
*
* Structure:
*
* [F][W][E][B][uint8 Ver Hi][uint8 Ver Lo] // заголовок диска
* [uint16 Number of Files] // кол-во файлов на диске
* [Name Hash 0]...[Name Hash N] // uint16 типа хеш на каждое имя файла
* [File Record 0]...[File Record N] // uint32 указатели на адреса структур файлов, относительно начала диска
*
* File Record Structure:
* [uint32 Len] размер файла с заголовком
* [uint16 HeadLen] длина заголовка, включая размер, флаг, имя (адрес данных - адрес позиции len)
* [uint16 Flags] бит 0 =1 - файл сжат GZIP, бит 1 = 1 - парсится - имеет динамические переменные
* [File Name, 0] Имя файла с "СИ" терминатором
* [File Data] данные файла
*
* Name hash (2 uint8s) is calculated as follows:
* hash = 0
* for each(uint8 in name)
* hash += uint8
* hash <<= 1
*
* Technically this means the hash only includes the
* final 15 characters of a name.
*
* String FileNmae Structure (1 to 64 uint8s):
* ["path/to/file.ext"][0x00]
*
*
* Current version is 1.0
*/
// Lock WEBFS access during the upgrade
volatile bool isWEBFSLocked WEBFS_DATA_ATTR;
// Track the WEBFS File Handles
// WEBFSStubs[0] is reserved for internal use (FAT access)
WEBFS_STUB WEBFSStubs[MAX_WEBFS_OPENFILES+1] WEBFS_DATA_ATTR; // + HANDLE = 0
// FAT record cache
WEBFS_FAT_RECORD fatCache WEBFS_DATA_ATTR;
// ID of currently loaded fatCache
static uint32 fatCacheID WEBFS_DATA_ATTR;
// Number of files in this WEBFS image
uint16 numFiles WEBFS_DATA_ATTR;
LOCAL void GetFATRecord(uint16 fatID);
LOCAL void WEBFS_Update(void);
/*****************************************************************************
Function:
void WEBFSInit(void)
Description:
Web Disk Init
*****************************************************************************/
void WEBFS_CODE_ATTR WEBFSInit(void)
{
disk_base_addr = WEBFS_base_addr();
os_memset((char *) &WEBFSStubs, 0xff, sizeof(WEBFSStubs));
// Validate the image and load numFiles
WEBFS_Update();
#if DEBUGSOO > 0
os_printf("\nDisk init: %d files, addr = %p\n", numFiles, disk_base_addr);
#endif
// тут надо расчет контрольки тела диска или другой контроль...
if(numFiles == 0) isWEBFSLocked = true;
else isWEBFSLocked = false;
}
/*****************************************************************************
Function:
WEBFS_HANDLE WEBFSOpen(uint8* cFile)
Description:
Opens a file in the WEBFS2 file system.
Precondition:
None
Parameters:
cFile - a null terminated file name to open
Returns:
An WEBFS_HANDLE to the opened file if found, or WEBFS_INVALID_HANDLE
if the file could not be found or no free handles exist.
***************************************************************************/
WEBFS_HANDLE WEBFS_CODE_ATTR WEBFSOpen(uint8* cFile)
{
WEBFS_HANDLE hWEBFS;
uint16 nameHash;
int i, len = 0;
uint16 hashCache[16];
uint8 bufname[MAX_FILE_NAME_LEN];
uint8 *ptr;
// Make sure WEBFS is unlocked and we got a filename
if(*cFile == '\0' || isWEBFSLocked == true)
return WEBFS_INVALID_HANDLE;
// Calculate the name hash to speed up searching
for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++)
{
nameHash += *ptr;
nameHash <<= 1;
len++;
}
// Find a free file handle to use
for(hWEBFS = 1; hWEBFS <= MAX_WEBFS_OPENFILES; hWEBFS++)
if(WEBFSStubs[hWEBFS].addr == WEBFS_INVALID) break;
if(hWEBFS == MAX_WEBFS_OPENFILES)
return WEBFS_INVALID_HANDLE;
// Read in hashes, and check remainder on a match. Store 8 in cache for performance
for(i = 0; i < numFiles; i++) {
// For new block of 8, read in data
if((i & 0x0F) == 0) {
WEBFSStubs[0].addr = 12 + i*2;
WEBFSStubs[0].bytesRem = 32;
WEBFSGetArray(0, (uint8*)hashCache, 32);
}
// If the hash matches, compare the full filename
if(hashCache[i&0x0F] == nameHash)
{
GetFATRecord(i);
// filename comparison
WEBFSStubs[0].addr = fatCache.string;
WEBFSStubs[0].bytesRem = MAX_FILE_NAME_LEN;
WEBFSGetArray(0, bufname, MAX_FILE_NAME_LEN);
if(os_strncmp(cFile, bufname, len) == 0) { // Filename matches, so return true
WEBFSStubs[hWEBFS].addr = fatCache.data;
WEBFSStubs[hWEBFS].bytesRem = fatCache.len;
WEBFSStubs[hWEBFS].fatID = i;
return hWEBFS;
}
}
}
// No file name matched, so return nothing
return WEBFS_INVALID_HANDLE;
}
/*****************************************************************************
Function: void WEBFSClose(WEBFS_HANDLE hWEBFS)
Summary: Closes a file.
Returns: None
***************************************************************************/
void WEBFS_CODE_ATTR WEBFSClose(WEBFS_HANDLE hWEBFS)
{
if(hWEBFS != 0 && hWEBFS <= MAX_WEBFS_OPENFILES)
WEBFSStubs[hWEBFS].addr = WEBFS_INVALID;
}
/*****************************************************************************
Function: uint16 WEBFSGetArray(WEBFS_HANDLE hWEBFS, uint8* cData, uint16 wLen)
Description: Reads a series of uint8s from a file.
Precondition: The file handle referenced by hWEBFS is already open.
Parameters:
hWEBFS - the file handle from which to read
cData - where to store the uint8s that were read
wLen - how many uint8s to read
Returns:
The number of uint8s successfully read. If this is less than wLen,
an EOF occurred while attempting to read.
***************************************************************************/
uint16 WEBFS_CODE_ATTR WEBFSGetArray(WEBFS_HANDLE hWEBFS, uint8* cData, uint16 wLen)
{
// Make sure we're reading a valid address
if(hWEBFS > MAX_WEBFS_OPENFILES) return 0;
// Determine how many we can actually read
if(wLen > WEBFSStubs[hWEBFS].bytesRem) wLen = WEBFSStubs[hWEBFS].bytesRem;
// Make sure we're reading a valid address
if(WEBFSStubs[hWEBFS].addr == WEBFS_INVALID || wLen == 0) return 0;
if(cData != NULL) {
// Read the data
web_mutex_lock();
// if(wLen < 16)
flash_stream_read(&flashobj, WEBFSStubs[hWEBFS].addr + WEBFS_HEAD_ADDR, wLen, cData);
// else flash_burst_read(&flashobj, WEBFSStubs[hWEBFS].addr + WEBFS_HEAD_ADDR, wLen, cData);
web_mutex_unlock();
// if(spi_flash_read(WEBFSStubs[hWEBFS].addr+WEBFS_HEAD_ADDR, cData, wLen) != SPI_FLASH_RESULT_OK)
// return 0;
};
WEBFSStubs[hWEBFS].addr += wLen;
WEBFSStubs[hWEBFS].bytesRem -= wLen;
return wLen;
}
/*****************************************************************************
Function:
bool WEBFSSeek(WEBFS_HANDLE hWEBFS, uint32 dwOffset, WEBFS_SEEK_MODE tMode)
Description: Moves the current read pointer to a new location.
Precondition: The file handle referenced by hWEBFS is already open.
Parameters:
hWEBFS - the file handle to seek with
dwOffset - offset from the specified position in the specified direction
tMode - one of the WEBFS_SEEK_MODE constants
Returns:
true - the seek was successful
false - either the new location or the handle itself was invalid
***************************************************************************/
bool WEBFS_CODE_ATTR WEBFSSeek(WEBFS_HANDLE hWEBFS, uint32 dwOffset, WEBFS_SEEK_MODE tMode)
{
uint32 temp;
// Make sure a valid file is open
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
return false;
switch(tMode)
{
// Seek offset uint8s from start
case WEBFS_SEEK_START:
temp = WEBFSGetSize(hWEBFS);
if(dwOffset > temp)
return false;
WEBFSStubs[hWEBFS].addr = WEBFSGetStartAddr(hWEBFS) + dwOffset;
WEBFSStubs[hWEBFS].bytesRem = temp - dwOffset;
return true;
// Seek forwards offset uint8s
case WEBFS_SEEK_FORWARD:
if(dwOffset > WEBFSStubs[hWEBFS].bytesRem)
return false;
WEBFSStubs[hWEBFS].addr += dwOffset;
WEBFSStubs[hWEBFS].bytesRem -= dwOffset;
return true;
// Seek backwards offset uint8s
case WEBFS_SEEK_REWIND:
temp = WEBFSGetStartAddr(hWEBFS);
if(WEBFSStubs[hWEBFS].addr < temp + dwOffset)
return false;
WEBFSStubs[hWEBFS].addr -= dwOffset;
WEBFSStubs[hWEBFS].bytesRem += dwOffset;
return true;
// Seek so that offset uint8s remain in file
case WEBFS_SEEK_END:
temp = WEBFSGetSize(hWEBFS);
if(dwOffset > temp)
return false;
WEBFSStubs[hWEBFS].addr = WEBFSGetEndAddr(hWEBFS) - dwOffset;
WEBFSStubs[hWEBFS].bytesRem = dwOffset;
return true;
default:
return false;
}
}
/*****************************************************************************
Function: static void GetFATRecord(uint16 fatID)
Description: Loads the FAT record for a specified handle.
Precondition: None
Parameters: fatID - the ID of the file whose FAT is to be loaded
Returns: None
Remarks: The FAT record will be stored in fatCache.
***************************************************************************/
LOCAL void WEBFS_CODE_ATTR GetFATRecord(uint16 fatID)
{
WEBFS_FHEADER fhead;
if(fatID == fatCacheID || fatID >= numFiles) return;
// Read the FAT record to the cache
WEBFSStubs[0].bytesRem = sizeof(fhead) + 4;
WEBFSStubs[0].addr = 12 + numFiles*2 + fatID *4;
WEBFSGetArray(0, (uint8 *)&fatCache.data, 4);
WEBFSStubs[0].addr = fatCache.data;
WEBFSGetArray(0, (uint8 *)&fhead, sizeof(fhead));
fatCache.len = fhead.blksize - fhead.headlen;
fatCache.string = fatCache.data + 8;
fatCache.flags = fhead.flags;
fatCache.data = fatCache.data + fhead.headlen;
fatCacheID = fatID;
}
/*****************************************************************************
Function: uint16 WEBFSGetFlags(WEBFS_HANDLE hWEBFS)
Description: Reads a file's flags.
Precondition: The file handle referenced by hWEBFS is already open.
Parameters: hWEBFS - the file handle from which to read the metadata
Returns: The flags that were associated with the file
***************************************************************************/
uint16 WEBFS_CODE_ATTR WEBFSGetFlags(WEBFS_HANDLE hWEBFS)
{
// Make sure a valid file is open
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
return 0;
//move to the point for reading
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
return fatCache.flags;
}
/*****************************************************************************
Function: uint32 WEBFSGetSize(WEBFS_HANDLE hWEBFS)
Description: Reads the size of a file.
Precondition: The file handle referenced by hWEBFS is already open.
Parameters: hWEBFS - the file handle from which to read the metadata
Returns: The size that was read as a uint32
***************************************************************************/
uint32 WEBFS_CODE_ATTR WEBFSGetSize(WEBFS_HANDLE hWEBFS)
{
// Make sure a valid file is open
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
return 0;
// Move to the point for reading
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
return fatCache.len;
}
/*****************************************************************************
Function: uint32 WEBFSGetBytesRem(WEBFS_HANDLE hWEBFS)
Description: Determines how many uint8s remain to be read.
Precondition: The file handle referenced by hWEBFS is already open.
Parameters: hWEBFS - the file handle from which to read the metadata
Returns: The number of uint8s remaining in the file as a uint32
***************************************************************************/
uint32 WEBFS_CODE_ATTR WEBFSGetBytesRem(WEBFS_HANDLE hWEBFS)
{
// Make sure a valid file is open
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
return 0;
return WEBFSStubs[hWEBFS].bytesRem;
}
/*****************************************************************************
Function: WEBFS_PTR WEBFSGetStartAddr(WEBFS_HANDLE hWEBFS)
Description: Reads the starting address of a file.
Precondition: The file handle referenced by hWEBFS is already open.
Parameters: hWEBFS - the file handle from which to read the metadata
Returns: The starting address of the file in the WEBFS image
***************************************************************************/
WEBFS_PTR WEBFS_CODE_ATTR WEBFSGetStartAddr(WEBFS_HANDLE hWEBFS)
{
// Make sure a valid file is open
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
return 0;
// Move to the point for reading
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
return fatCache.data;
}
/*****************************************************************************
Function: WEBFS_PTR WEBFSGetEndAddr(WEBFS_HANDLE hWEBFS)
Description: Determines the ending address of a file.
Precondition: The file handle referenced by hWEBFS is already open.
Parameters: hWEBFS - the file handle from which to read the metadata
Returns: The address just after the file ends (start address of next file)
***************************************************************************/
WEBFS_PTR WEBFS_CODE_ATTR WEBFSGetEndAddr(WEBFS_HANDLE hWEBFS)
{
// Make sure a valid file is open
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
return WEBFS_INVALID;
// Move to the point for reading
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
return fatCache.data + fatCache.len;
}
/*****************************************************************************
Function: bool WEBFSGetFilename(WEBFS_HANDLE hWEBFS, uint8* cName, uint16 wLen)
Description: Reads the file name of a file that is already open.
Precondition: The file handle referenced by hWEBFS is already open.
Parameters:
hWEBFS - the file handle from which to determine the file name
cName - where to store the name of the file
wLen - the maximum length of data to store in cName
Returns:
true - the file name was successfully located
false - the file handle provided is not currently open
***************************************************************************/
bool WEBFS_CODE_ATTR WEBFSGetFilename(WEBFS_HANDLE hWEBFS, uint8* cName, uint16 wLen)
{
uint32 addr;
// Make sure a valid file is open
if(hWEBFS > MAX_WEBFS_OPENFILES || WEBFSStubs[hWEBFS].addr == WEBFS_INVALID)
return false;
// Move to the point for reading
GetFATRecord(WEBFSStubs[hWEBFS].fatID);
addr = fatCache.string;
WEBFSStubs[0].addr = addr;
WEBFSStubs[0].bytesRem = 255;
// Read the value and return
WEBFSGetArray(0, cName, wLen);
return true;
}
/*****************************************************************************
Function: uint32 WEBFSGetPosition(WEBFS_HANDLE hWEBFS)
Description: Determines the current position in the file
Precondition: The file handle referenced by hWEBFS is already open.
Parameters: hWEBFS - the file handle for which to determine position
Returns: The position in the file as a uint32 (or WEBFS_PTR)
***************************************************************************/
uint32 WEBFS_CODE_ATTR WEBFSGetPosition(WEBFS_HANDLE hWEBFS)
{
return WEBFSStubs[hWEBFS].addr - WEBFSGetStartAddr(hWEBFS);
}
/*****************************************************************************
Function: void WEBFS_Update(void)
Summary: Validates the WEBFS Image
Description: Verifies that the WEBFS image is valid, and reads the number of
available files from the image header. This function is called on
boot, and again after any image is written.
Parameters: None
Returns: None
***************************************************************************/
LOCAL void WEBFS_CODE_ATTR WEBFS_Update(void)
{
// Update numFiles
WEBFS_DISK_HEADER dhead;
WEBFSStubs[0].addr = 0;
WEBFSStubs[0].bytesRem = sizeof(dhead);
WEBFSGetArray(0, (uint8*)&dhead, sizeof(dhead));
if(dhead.id == WEBFS_DISK_ID && dhead.ver == WEBFS_DISK_VER) { //"FWEB"1,0 ?
numFiles = dhead.numFiles;
}
else numFiles = 0;
fatCacheID = WEBFS_INVALID_FAT;
}
/****************************************************************************
* WEBFS_max_size()
***************************************************************************/
uint32 WEBFS_CODE_ATTR WEBFS_max_size(void)
{
/*
uint32 size = spi_flash_real_size();
if(size > WEBFS_DISK_ADDR_BIGFLASH) size -= WEBFS_DISK_ADDR_BIGFLASH;
else {
size = WEBFS_DISK_ADDR_MINFLASH_END - WEBFS_DISK_ADDR_MINFLASH_START;
}
return size;
*/
return spi_flash_real_size() - WEBFS_DISK_FADDR;
}
/****************************************************************************
* WEBFS_size()
***************************************************************************/
uint32 WEBFS_CODE_ATTR WEBFS_curent_size(void)
{
uint32 size = 0;
web_mutex_lock();
if(numFiles) flash_read_word(&flashobj, disk_base_addr + 8, &size);
web_mutex_unlock();
return size;
}
/****************************************************************************
* WEBFS_size()
***************************************************************************/
uint32 WEBFS_CODE_ATTR WEBFS_base_addr(void)
{
/*
uint32 webfs_faddr;
if(flash_get_size(&flashobj) <= WEBFS_DISK_ADDR_BIGFLASH) webfs_faddr = WEBFS_DISK_ADDR_MINFLASH_START;
else webfs_faddr = WEBFS_DISK_ADDR_BIGFLASH;
return webfs_faddr;
*/
return WEBFS_DISK_FADDR;
}