![](/media/cache/profiles/f0fcf351df4eb6786e9bb6fc4e2dee02.jpg.50x50_q85.jpg)
Test program for FlashAir with iSDIO
Dependencies: FlashAir_iSDIO SDFileSystem
Diff: FlashAir_monitor/mon.cpp
- Revision:
- 3:fc1908567f3b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FlashAir_monitor/mon.cpp Wed Aug 28 22:48:37 2019 +0000 @@ -0,0 +1,1382 @@ +/* + * mbed Application program for the mbed + * FlashAir Check program + * + * Copyright (c) 2015,'19 Kenji Arai / JH1PJL + * http://www.page.sannet.ne.jp/kenjia/index.html + * https://os.mbed.com/users/kenjiArai/ + * Created: May 5th, 2015 + * Revised: August 27th, 2019 + */ + +// Include -------------------------------------------------------------------- +#include "mbed.h" +#include "FlashAir_iSDIO.h" +#include "mon.h" + +// Definition ----------------------------------------------------------------- +#define DO_DEBUG 0 + +#if DO_DEBUG +#define DEBUG_LINE pc.printf("line:%d\r\n", __LINE__); +#else +#define DEBUG_LINE {;} +#endif + +// from ffconf.h +#define _VOLUMES 1 + +// RAM ------------------------------------------------------------------------ +BYTE Buff[4096]; +char linebuf[64]; // Console input buffer +FATFS Fatfs[_VOLUMES]; // File system object for each logical drive +FIL File1, File2; // File objects +FATFS_DIR* Dirx; +FILINFO Finfo; +char Lfname[512]; +DWORD AccSize; // Work register for fs command +WORD AccFiles, AccDirs; + +uint8_t buffer[512]; +uint32_t nextSequenceId = 0; + +// ROM / Constant data -------------------------------------------------------- +const char *const monmsg0 = + "Start monitor program for FlashAir & FatFs/SD File System\r\n"; +const char *const monmsg1 = + " <Please press any key to start the monitor>"; +const char *const hisdmsg0 = + "Entered FlashAir/TOSHIBA iSDIO control commands\r\n"; +const char *const hisdmsg1 = + " retrun=q Help=?\r\n"; +const char *const rtnmsg = + "Return to Root Mode\r\n"; +const char *const msg_ok = + "\r\nSuccess\r\n"; +const char *const msg_ng = + "\r\nFailed\r\n"; + +static const char HelpMsg0[] = + "i FlashAir, iSDIO\r\n" + "dir <full_pass>\r\n" + "type <file_name>\r\n" + "vol\r\n" + "ren <org_file_name> <new_file_name>\r\n" + "copy <file_name> <file_name>\r\n" + "mkdir <dir_name>\r\n" + "cd <dir_name>\r\n" + "q Return to main\r\n" + "t Show current time or Adjust time\r\n" + " e.g. t 19 8 24 14 15 16 -> August 24,'19, 14:15:16\r\n" + "? Help/You know the command\r\n" + "\r\n"; + +static const char HelpMsg1[] = + "a Set as AP(Access Point) mode / Act as Host\r\n" + "s Set as STA(Station) mode / Connect to Host\r\n" + "q Return to File control monitor\r\n" + "\r\n"; + +static const char HelpMsg2[] = + "Connect to Host: step d->s->c->g\r\n" + "s Scan sounded host\r\n" + "c Connect specific host\r\n" + "d Disconnect line\r\n" + "g Get status\r\n" + "t Current time(JST)\r\n" + "q Return to previous monitor\r\n" + "\r\n"; + +static const char HelpMsg3[] = + "Estblish as Host: step d->e->g\r\n" + "e Establish connection\r\n" + "d Disconnect line\r\n" + "g Get status\r\n" + "q Return to previous monitor\r\n" + "\r\n"; + +// Host information @ STA mode +const char *const ssid = "pr500m-c86a71-1"; +const char *const networkKey = "7daaa01146644"; + +// FlashAir Host name & password @ AP mode +const char *const name_as_host = "flashair"; +const char *const password_ap = "12345678"; + +// Function prototypes -------------------------------------------------------- + +// Object --------------------------------------------------------------------- +extern Serial pc; +extern FlashAir_iSDIO sd; +Timer t; + +//------------------------------------------------------------------------------ +// Control Program +//------------------------------------------------------------------------------ +// Monitor program for File control +void mon () +{ + char *ptr; + + Dirx = new FATFS_DIR; + /* Open Uart to communicate with Host PC */ + pc.puts(monmsg0); + pc.puts(monmsg1); + crlf(); + /* monitor is running all time when systen is running */ + char c = pc.getc(); + Finfo.lfname = Lfname; + Finfo.lfsize = sizeof Lfname; + //pc.printf("0x%x, 0x%x\r\n", mon, HelpMsg0); + for (;;) { + DEBUG_LINE + pc.putc('>'); + ptr = linebuf; + get_line( ptr, sizeof(linebuf) ); + switch ( *ptr++ ) { + // iSDIO, goto sub functions + case 'i' : + isdio_mon(ptr); + break; + // vol + case 'v' : + v_next(ptr); + break; + // dir + case 'd' : + d_next(ptr); + break; + // cd, copy + case 'c' : + c_next(ptr); + break; + // mkdir + case 'm' : + m_next(ptr); + break; + // ren + case 'r' : + r_next(ptr); + break; + // type, set time + case 't' : + t_next(ptr); + break; + // Help + case '?' : + pc.puts(HelpMsg0); + break; + // Exit monitor (return to main()) + case 'q' : + pc.puts("Return to main\r\n"); + return; + // Not a command + default: + DEBUG_LINE + pc.puts("? [HELP]=?"); + crlf(); + break; + } + } +} + +uint32_t get_disk_freespace(void) +{ + long p1; + UINT s1, s2; + FATFS *fs; + BYTE res; + + if (Dirx == NULL) { + Dirx = new FATFS_DIR; + } + char p = NULL; + res = f_opendir(Dirx, &p); + if (res) { + return 0; + } + p1 = s1 = s2 = 0; + for(;;) { + res = f_readdir(Dirx, &Finfo); + if ((res != FR_OK) || !Finfo.fname[0]) break; + if (Finfo.fattrib & AM_DIR) { + s2++; + } else { + s1++; + p1 += Finfo.fsize; + } + } + res = f_getfree(&p, (DWORD*)&p1, &fs); + uint32_t size = p1 * fs->csize * 512; + if (res == FR_OK) { + return size; + } else { + return 0; + } +} + +static void isdio_mon(char *ptr) +{ + pc.puts(hisdmsg0); + pc.puts(hisdmsg1); + for (uint32_t i=0; i==0; ) { + pc.puts("iSDIO>"); + ptr = linebuf; + get_line(ptr, sizeof(linebuf)); + switch(*ptr++) { + case 'a' : + ap_mon(ptr); + break; + case 's' : + sta_mon(ptr); + break; + case 'q' : + i = 1; // return + break; + case '?' : + pc.puts(HelpMsg1); + break; + default: + pc.putc('?'); + crlf(); + } + } + pc.puts(rtnmsg); +} + +// Station Mode (connect to Host) +static void sta_mon(char *ptr) +{ + static char str[512]; + time_t seconds_jst; + + pc.puts("Enterd FlashAir STA(Station) Mode -> connect to Host Device\r\n"); + pc.puts(hisdmsg1); + //Initialise card + FILE *fp = fopen("/sd/mbed.txt", "a"); + sprintf((char *)buffer, ".."); + fprintf(fp,(char *)buffer); + fclose(fp); + DEBUG_LINE + // Read the previous sequence ID. + if (sd.readExtMemory(1, 1, 0x420, 0x34, buffer)) { + DEBUG_LINE + if (buffer[0x20] == 0x01) { + DEBUG_LINE + nextSequenceId = get_u32(buffer + 0x24); + sd.waitResponse(nextSequenceId); + nextSequenceId++; + } else { + DEBUG_LINE + nextSequenceId = 0; + } + } else { + DEBUG_LINE + pc.puts("Failed to read status\r\n"); + nextSequenceId = 0; + } + for (uint32_t i=0; i==0; ) { + DEBUG_LINE + pc.puts("STA>"); + ptr = linebuf; + get_line(ptr, sizeof(linebuf)); + switch(*ptr++) { + case 's' : + DEBUG_LINE + if (iSDIO_scan(nextSequenceId) && + iSDIO_waitResponse(nextSequenceId) && + iSDIO_showScanResult()) { + pc.puts(msg_ok); + } else { + pc.puts(msg_ng); + } + nextSequenceId++; + break; + case 'c' : + DEBUG_LINE + if (iSDIO_connect(nextSequenceId, ssid, networkKey) && + iSDIO_waitResponse(nextSequenceId)) { + pc.puts(msg_ok); + } else { + pc.puts(msg_ng); + } + nextSequenceId++; + break; + case 'e' : + DEBUG_LINE + if (iSDIO_establish(nextSequenceId)) { + pc.puts(msg_ok); + } else { + pc.puts(msg_ng); + } + break; + case 'd' : + DEBUG_LINE + if (iSDIO_disconnect(nextSequenceId)) { + pc.puts(msg_ok); + } else { + pc.puts(msg_ng); + } + break; + case 't' : + DEBUG_LINE + seconds_jst = time(NULL); // Read Int. RTC time + strftime( + str, 40, + "%B %d,'%y, %H:%M:%S", + localtime(&seconds_jst)); + pc.printf("Time(JST): %s\r\n", str); + break; + case 'g' : + DEBUG_LINE + if (iSDIO_status() == false) { + pc.puts(msg_ng); + } + break; + case 'q' : + i = 1; // return + break; + case '?' : + pc.puts(HelpMsg2); + break; + default: + DEBUG_LINE + pc.putc('?'); + crlf(); + } + } + pc.puts(rtnmsg); +} + +// Access Point Mode (Act as Host) +static void ap_mon(char *ptr) +{ + pc.puts("Enterd FlashAir AP(Access Point) Mode -> Act as Host\r\n"); + pc.puts(hisdmsg1); + for (uint32_t i=0; i==0; ) { + pc.puts("AP>"); + ptr = linebuf; + get_line(ptr, sizeof(linebuf)); + switch(*ptr++) { + case 'e' : + if (iSDIO_establish(nextSequenceId)) { + pc.puts(msg_ok); + } else { + pc.puts(msg_ng); + } + break; + case 'd' : + if (iSDIO_disconnect(nextSequenceId)) { + pc.puts(msg_ok); + } else { + pc.puts(msg_ng); + } + break; + case 'g' : + if (iSDIO_status() == false) { + pc.puts(msg_ng); + } + break; + case 'q' : + i = 1; // return + break; + case '?' : + pc.puts(HelpMsg3); + break; + default: + pc.putc('?'); + crlf(); + } + } + pc.puts(rtnmsg); +} + +//------------------------------------------------------------------------------ +// iSDIO +void printByte(uint8_t value) +{ + pc.printf("%x", value >> 4); + pc.printf("%x", value & 0xF); +} + +void printBytes(uint8_t* p, uint32_t len) +{ + for (uint32_t i = 0; i < len; ++i) { + printByte(p[i]); + } +} +void printIPAddress(uint8_t* p) +{ + pc.printf("%d", p[0]); + pc.putc('.'); + pc.printf("%d", p[1]); + pc.putc('.'); + pc.printf("%d", p[2]); + pc.putc('.'); + pc.printf("%d", p[3]); +} + +void printHex(uint8_t* p, uint32_t len) +{ + uint32_t i = 0; + while (i < len) { + if ((i & 0xf) == 0) { + pc.puts("\r\n"); + printByte(i >> 4); + pc.puts(": "); + } + printByte(*p++); + i++; + } + pc.puts("\r\n"); +} + +uint8_t iSDIO_establish(uint32_t sequenceId) +{ + pc.puts("Establish command: \r\n"); + memset(buffer, 0, 512); + uint8_t* p = buffer; + p = put_command_header(p, 1, 0); + p = put_command_info_header(p, 0x03, sequenceId, 3); + p = put_str_arg(p, (const uint8_t*)name_as_host); + p = put_str_arg(p, (const uint8_t*)password_ap); + p = put_u8_arg(p, 0x06); + put_command_header(buffer, 1, (p - buffer)); + printHex(buffer, (p - buffer)); + return sd.writeExtDataPort(1, 1, 0x000, buffer) ? true : false; +} + +uint8_t iSDIO_connect( + uint32_t sequenceId, + const char* ssid, + const char* networkKey +) +{ + pc.puts("Connect command: \r\n"); + memset(buffer, 0, 512); + uint8_t* p = buffer; + p = put_command_header(p, 1, 0); + p = put_command_info_header(p, 0x02, sequenceId, 2); + p = put_str_arg(p, (const uint8_t*)ssid); + p = put_str_arg(p, (const uint8_t*)networkKey); + put_command_header(buffer, 1, (p - buffer)); + printHex(buffer, (p - buffer)); + return sd.writeExtDataPort(1, 1, 0x000, buffer) ? true : false; +} + +uint8_t iSDIO_disconnect(uint32_t sequenceId) +{ + pc.puts("Disconnect command: \r\n"); + memset(buffer, 0, 512); + uint8_t* p = buffer; + p = put_command_header(p, 1, 0); + p = put_command_info_header(p, 0x07, sequenceId, 0); + put_command_header(buffer, 1, (p - buffer)); + printHex(buffer, (p - buffer)); + return sd.writeExtDataPort(1, 1, 0x000, buffer) ? true : false; +} + +uint8_t iSDIO_waitResponse(uint32_t sequenceId) +{ + pc.puts("Waiting response "); + uint8_t prev = 0xFF; + for (int i = 0; i < 20; ++i) { + memset(buffer, 0, 0x14); + + // Read command response status. + if (!sd.readExtMemory(1, 1, 0x440, 0x14, buffer)) { + return false; + } + uint8_t resp = get_u8(buffer + 8); + if (sequenceId == get_u32(buffer + 4)) { + if (prev != resp) { + switch (resp) { + case 0x00: + pc.puts(" Initial"); + break; + case 0x01: + pc.puts(" Command Processing"); + break; + case 0x02: + pc.puts(" Command Rejected"); + return false; + case 0x03: + pc.puts(" Process Succeeded"); + return true; + case 0x04: + pc.puts(" Process Terminated"); + return false; + default: + pc.puts(" Process Failed "); + return false; + } + prev = resp; + } + } + pc.putc('.'); + wait(1.0); + } + return false; +} + +uint8_t iSDIO_scan(uint32_t sequenceId) +{ + pc.puts("Scan: \r\n"); + memset(buffer, 0, 512); + uint8_t* p = buffer; + p = put_command_header(p, 1, 0); + p = put_command_info_header(p, 0x01, sequenceId, 0); + put_command_header(buffer, 1, (p - buffer)); + printHex(buffer, (p - buffer)); + return sd.writeExtDataPort(1, 1, 0x000, buffer) ? true : false; +} + +uint8_t iSDIO_showScanResult(void) +{ + // Try to output some wifi info. + if (!sd.readExtDataPort(1, 1, 0x200, buffer)) { + pc.puts("Scan result: False\r\n"); + return false; + } + uint8_t num = get_u8(buffer + 24); + pc.puts("\r\nScan result:Number of APs: "); + pc.printf("%u\r\n",num); + uint8_t* p = buffer + 28; + for (int i = 0; i < num; i++) { + pc.putc(' '); + pc.printf("%s",(const char*)p); + pc.puts(", "); + printBytes(p + 32, 6); + pc.puts(", "); + pc.printf("%u",get_u8(p + 38)); + pc.puts(", "); + switch (get_u8(p + 39)) { + case 0 : + pc.puts("NoSec"); + break; + case 1 : + pc.puts("WEP"); + break; + case 2 : + pc.puts("WPA"); + break; + case 3 : + pc.puts("WPA2"); + break; + default : + pc.puts("error"); + break; + } + pc.puts("\r\n"); + p += 44; + } + return true; +} + +uint8_t iSDIO_status(void) +{ + pc.puts("Read iSDIO Status Register\r\n"); + // Read iSDIO Status Register (E7 1.10 2.2.2.1) + memset(buffer, 0, 0x200); + if (!sd.readExtMemory(1, 1, 0x400, 0x200, buffer)) { + pc.puts("Cannot read Ext Memory\r\n"); + return false; + } +#if 1 + uint16_t j = 0; + pc.puts("HEX 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n 0 "); + for (int i = 0; i < 0x200; i++) { + pc.printf("%2x ", buffer[i]); + if ((i & 0xf) == 0xf) { + if (i == 0x1ff) { + pc.puts("\r\n"); + } else { + pc.printf("\r\n%2x ", ++j); + } + } + } +#endif + // Show values in the common status area. + pc.puts("\r\n == iSDIO Status Registers == "); + pc.puts("\r\n [0400h] Command Write Status: "); + if (buffer[0x000] & 0x01) pc.puts("CWU "); + if (buffer[0x000] & 0x02) pc.puts("CWA "); + pc.puts("\r\n [0420h] iSDIO Status: "); + if (buffer[0x020] & 0x01) pc.puts("CRU "); + if (buffer[0x020] & 0x02) pc.puts("ESU "); + if (buffer[0x020] & 0x04) pc.puts("MCU "); + if (buffer[0x020] & 0x08) pc.puts("ASU "); + pc.puts("\r\n [0422h] iSDIO Int Enable: "); + if (buffer[0x022] & 0x01) pc.puts("CRU_ENA "); + if (buffer[0x022] & 0x02) pc.puts("ESU_ENA "); + if (buffer[0x022] & 0x04) pc.puts("MCU_ENA "); + if (buffer[0x022] & 0x08) pc.puts("ASU_ENA "); + pc.puts("\r\n [0424h] Error Status: "); + if (buffer[0x024] & 0x01) pc.puts("CRE "); + if (buffer[0x024] & 0x02) pc.puts("CWE "); + if (buffer[0x024] & 0x04) pc.puts("RRE "); + if (buffer[0x024] & 0x08) pc.puts("APE "); + pc.puts("\r\n [0426h] Memory Status: "); + if (buffer[0x026] & 0x01) pc.puts("MEX "); + if (buffer[0x026] & 0x02) pc.puts("FAT "); + for (int i = 0; i < 8; ++i) { + uint8_t addr = 0x40 + i * 0x14; + pc.puts("\r\n [04"); + printByte(addr); + pc.puts("h] Command Response Status #"); + pc.printf("%d", i + 1); + pc.puts(": "); + if (buffer[addr] & 0x01) { + pc.puts("id = "); + pc.printf("%d", get_u16(buffer + addr + 2)); + pc.puts(", sequence id = "); + pc.printf("%d", get_u32(buffer + addr + 4)); + pc.puts(", status = "); + switch (buffer[addr + 8]) { + case 0x00: + pc.puts("Initial"); + break; + case 0x01: + pc.puts("Command Processing"); + break; + case 0x02: + pc.puts("Command Rejected"); + break; + case 0x03: + pc.puts("Process Succeeded"); + break; + case 0x04: + pc.puts("Process Terminated"); + break; + default: + pc.puts("Process Failed "); + pc.printf("0x%x", buffer[addr + 8]); + break; + } + } else { + pc.puts("Not registered"); + } + } + // Show values in the application status area. + pc.puts("\r\n == Wireless LAN Status Registers =="); + pc.puts("\r\n [0500h] DLNA Status: "); + if (buffer[0x100] & 0x01) pc.puts("ULR "); + if (buffer[0x100] & 0x02) pc.puts("DLU "); + if (buffer[0x100] & 0x04) pc.puts("CBR "); + if (buffer[0x100] & 0x08) pc.puts("CDR "); + pc.puts("\r\n [0501h] P2P Status: "); + if (buffer[0x101] & 0x01) pc.puts("ILU "); + if (buffer[0x101] & 0x02) pc.puts("FLU "); + pc.puts("\r\n [0502h] PTP Status: "); + if (buffer[0x102] & 0x01) pc.puts("RPO "); + if (buffer[0x102] & 0x02) pc.puts("RPD "); + if (buffer[0x102] & 0x04) pc.puts("RPC "); + if (buffer[0x102] & 0x08) pc.puts("CPI "); + if (buffer[0x102] & 0x10) pc.puts("DPI "); + if (buffer[0x102] & 0x20) pc.puts("CIL "); + pc.puts("\r\n [0504h] Application: "); + pc.printf("0x%x", buffer[0x104]); + pc.puts("\r\n [0506h] WLAN: "); + if ((buffer[0x106] & 0x01) == 0x00) pc.puts("No Scan, "); + if ((buffer[0x106] & 0x01) == 0x01) pc.puts("Scanning, "); + if ((buffer[0x106] & 0x06) == 0x00) pc.puts("No WPS, "); + if ((buffer[0x106] & 0x06) == 0x02) pc.puts("WPS with PIN, "); + if ((buffer[0x106] & 0x06) == 0x04) pc.puts("WPS with PBC, "); + if ((buffer[0x106] & 0x08) == 0x00) pc.puts("Group Client, "); + if ((buffer[0x106] & 0x08) == 0x08) pc.puts("Group Owner "); + if ((buffer[0x106] & 0x10) == 0x00) pc.puts("STA, "); + if ((buffer[0x106] & 0x10) == 0x10) pc.puts("AP, "); + if ((buffer[0x106] & 0x60) == 0x00) pc.puts("Initial, "); + if ((buffer[0x106] & 0x60) == 0x20) pc.puts("Infrastructure, "); + if ((buffer[0x106] & 0x60) == 0x40) pc.puts("Wi-Fi Direct, "); + if ((buffer[0x106] & 0x80) == 0x00) pc.puts("No Connection, "); + if ((buffer[0x106] & 0x80) == 0x80) pc.puts("Connected, "); + pc.puts("\r\n [0508h] SSID: "); + for (int i = 0; i < 32 && buffer[0x108 + i] != 0; ++i) { + pc.printf("%c", (char)buffer[0x108 + i]); + } + pc.puts("\r\n [0528h] Encryption Mode: "); + switch (buffer[0x128]) { + case 0 : + pc.puts("Open System and no encryption"); + break; + case 1 : + pc.puts("Open System and WEP"); + break; + case 2 : + pc.puts("Shared Key and WEP"); + break; + case 3 : + pc.puts("WPA-PSK and TKIP"); + break; + case 4 : + pc.puts("WPA-PSK and AES"); + break; + case 5 : + pc.puts("WPA2-PSK and TKIP"); + break; + case 6 : + pc.puts("WPA2-PSK and AES"); + break; + default: + pc.puts("Unknown"); + } + pc.puts("\r\n [0529h] Signal Strength: "); + pc.printf("%d", buffer[0x129]); + pc.puts("\r\n [052Ah] Channel: "); + if (buffer[0x12A] == 0) pc.puts("No connection"); + else pc.printf("%d", buffer[0x12A]); + pc.puts("\r\n [0530h] MAC Address: "); + printBytes(buffer + 0x130, 6); + pc.puts("\r\n [0540h] ID: "); + for (int i = 0; i < 16 && buffer[0x140 + i] != 0; ++i) { + pc.printf("%c", (char)buffer[0x140 + i]); + } + pc.puts("\r\n [0550h] IP Address: "); + printIPAddress(buffer + 0x150); + pc.puts("\r\n [0554h] Subnet Mask: "); + printIPAddress(buffer + 0x154); + pc.puts("\r\n [0558h] Default Gateway: "); + printIPAddress(buffer + 0x158); + pc.puts("\r\n [055Ch] Preferred DNS Server: "); + printIPAddress(buffer + 0x15C); + pc.puts("\r\n [0560h] Alternate DNS Server: "); + printIPAddress(buffer + 0x160); + pc.puts("\r\n [0564h] Proxy Server: "); + if ((buffer[0x164] & 0x01) == 0x00) pc.puts("Disabled"); + if ((buffer[0x164] & 0x01) == 0x01) pc.puts("Enabled"); + pc.puts("\r\n [0570h] Date: "); + pc.printf("%d", buffer[0x171] + 1980); + pc.putc('-'); + pc.printf("%d", buffer[0x170] >> 4); + pc.putc('-'); + pc.printf("%d", buffer[0x170] & 0xF); + pc.puts("\r\n [0572h] Time: "); + pc.printf("%d", buffer[0x173] >> 3); + pc.putc(':'); + pc.printf("%d", buffer[0x172] << 3 | buffer[0x170] >> 3); + pc.putc(':'); + pc.printf("%d", (buffer[0x172] & 0x1F) * 2); + pc.puts("\r\n [0574h] HTTP Status: "); + pc.printf("%d", buffer[0x174] & 0xEF); + if ((buffer[0x174] & 0x80) == 0x00) pc.puts(" (No Processing)"); + if ((buffer[0x174] & 0x80) == 0x80) pc.puts(" (Processing)"); + pc.puts("\r\n [0575h] Power Save Management: "); + if ((buffer[0x175] & 0x01) == 0x00) pc.puts("Power Save Mode Off"); + if ((buffer[0x175] & 0x01) == 0x01) pc.puts("Power Save Mode On"); + pc.puts("\r\n [0576h] File System Management: "); + if ((buffer[0x176] & 0x01) == 0x00) { + pc.puts("FS Information may be modified"); + } + if ((buffer[0x176] & 0x01) == 0x01) { + pc.puts("FS Information shall not be modified"); + } + pc.puts("\r\n"); + return true; +} + +//------------------------------------------------------------------------------ +// General monitor functions +static void v_next(char *ptr) +{ + switch (*ptr++) { + case 'o' : + if (*ptr == 'l') { + *ptr = 's'; + file_inf(ptr); // fs [<path>] - Show volume status + } + break; + default: + pc.puts( "?\r\n" ); + } +} + +static void d_next(char *ptr) +{ + switch (*ptr++) { + case 'i' : + if (*ptr == 'r') { + *ptr = 'l'; + file_inf(ptr); // fl [<path>] - Directory listing + } + break; + default: + pc.puts( "?\r\n" ); + } +} + +static void c_next(char *ptr) +{ + switch (*ptr++) { + case 'o' : + if ((*ptr == 'p') && (*(ptr + 1) == 'y')) { + ptr++; + *ptr = 'x'; + file_inf(ptr); // fx <src_name> <dst_name> - Copy file + } + break; + case 'd' : + *ptr = 'g'; + file_inf(ptr); // fg Change directory + break; + default: + pc.puts( "?\r\n" ); + } +} + +static void m_next(char *ptr) +{ + switch (*ptr++) { + case 'k' : + if ((*ptr == 'd') && (*(ptr + 1) == 'i') && (*(ptr + 2) == 'r')) { + ptr += 2; + *ptr = 'k'; + file_inf(ptr); // fk <name> - Create a directory + } + break; + default: + pc.puts("?\r\n"); + } +} + +static void r_next(char *ptr) +{ + switch (*ptr++) { + case 'e' : + // fn <old_name> <new_name> - Change file/dir name + if (*ptr == 'n') { + file_inf(ptr); + } + break; + default: + pc.puts("?\r\n"); + } +} + +static void t_next(char *ptr) +{ + switch (*ptr++) { + case ' ' : + case 0x0d: + chk_and_set_time(ptr); + case 'y' : + if ((*ptr == 'p') && (*(ptr + 1) == 'e')) { + ptr++; + *ptr = '&'; + file_inf(ptr); + } + break; + default: + pc.puts("?\r\n"); + } +} + +static FRESULT scan_files( + char* path /* Pointer to the path name working buffer */ +) +{ + FATFS_DIR dirs; + FRESULT res; + BYTE i; + char *fn; + + if ((res = f_opendir(&dirs, path)) == FR_OK) { + i = strlen(path); + pc.printf("path: %s, n=%u\r\n", path, i); + while (((res = f_readdir(&dirs, &Finfo)) == FR_OK) && Finfo.fname[0]) { + if (_FS_RPATH && Finfo.fname[0] == '.') { + continue; + } + fn = *Finfo.lfname ? Finfo.lfname : Finfo.fname; + if (Finfo.fattrib & AM_DIR) { + AccDirs++; + *(path+i) = '/'; + strcpy(path+i+1, fn); + res = scan_files(path); + *(path+i) = '\0'; + if (res != FR_OK) break; + } else { + pc.printf("%s/%s\r\n", path, fn); + AccFiles++; + AccSize += Finfo.fsize; + } + } + } + return res; +} + +static void put_rc(FRESULT rc) +{ + const char *str = + "OK\0" "DISK_ERR\0" "INT_ERR\0" "NOT_READY\0" "NO_FILE\0" "NO_PATH\0" + "INVALID_NAME\0" "DENIED\0" "EXIST\0" "INVALID_OBJECT\0" + "WRITE_PROTECTED\0" "INVALID_DRIVE\0" "NOT_ENABLED\0" + "NO_FILE_SYSTEM\0" "MKFS_ABORTED\0" "TIMEOUT\0" + "LOCKED\0" "NOT_ENOUGH_CORE\0" "TOO_MANY_OPEN_FILES\0"; + for (uint32_t i = 0; i != rc && *str; i++ ) { + while ( *str++ ) { ;} + } + pc.printf( "rc=%u FR_%s\r\n", (UINT)rc, str ); +} + +static void file_inf(char *ptr) +{ + DDWORD pf; + long p1, p2, p3; + CHAR *ptr2; + BYTE f_res; + UINT s1, s2, cnt, blen = sizeof Buff; + FATFS *fs; + static const BYTE ft[] = {0, 12, 16, 32}; + BYTE res; + DWORD ofs = 0; + uint32_t tim; + + switch (*ptr++) { + case '&' : + DEBUG_LINE; + while (*ptr == ' ') ptr++; + /* Open a file */ + f_res = f_open(&File1, ptr, FA_READ); + if ( f_res ) { + put_rc((FRESULT)f_res); + break; + } + DEBUG_LINE; + /* Read all lines and display it */ + while(true) { + f_res = f_read(&File1, (TCHAR*)Buff, blen, &cnt); + if ( f_res ) { + put_rc((FRESULT)f_res); + break; + } + for (s1 = 0; s1 < cnt; s1++) { + pc.putc(Buff[s1]); + } + if (cnt != blen) { + break; + } + } + DEBUG_LINE; + /* Close the file */ + f_close(&File1); + break; + case 'i' : /* fi [<opt>]- Initialize logical drive */ + if ( !xatoi(&ptr, &p1) ) { + break; + } + if (!xatoi(&ptr, &p2)) p2 = 0; + put_rc(f_mount(&Fatfs[p1], (const TCHAR*)p1, 0)); + break; + case 's' : /* fs [<path>] - Show volume status */ + f_res = f_getfree( ptr, (DWORD*)&p2, &fs ); + if ( f_res ) { + put_rc((FRESULT)f_res); + break; + } + pc.printf + ( + "\rFAT type = FAT%u\r\nBytes/Cluster" + " = %lu\r\nNumber of FATs = %u\r\n" + "Root DIR entries = %u\r\n" + "Sectors/FAT = %lu\r\n" + "Number of clusters = %lu\r\n" + "FAT start (lba) = %lu\r\n" + "DIR start (lba,clustor) = %lu\r\n" + "Data start (lba) = %lu\r\n", + ft[fs->fs_type & 3], (DWORD)fs->csize * 512, fs->n_fats, + fs->n_rootdir, fs->fsize, (DWORD)fs->n_fatent - 2, + fs->fatbase, fs->dirbase, fs->database + ); + AccSize = AccFiles = AccDirs = 0; + break; + case 'l' : /* fl [<path>] - Directory listing */ + while ( *ptr == ' ' ) { + ptr++; + } + f_res = f_opendir( Dirx, ptr ); + if ( f_res ) { + put_rc( (FRESULT)f_res ); + break; + } + pf = 0; + p1 = s1 = s2 = 0; + for(;;) { + f_res = f_readdir( Dirx, &Finfo ); + if ( (f_res != FR_OK) || !Finfo.fname[0] ) { + break; + } + if ( Finfo.fattrib & AM_DIR ) { + s2++; + } else { + s1++; + pf += Finfo.fsize; + } + pc.printf( + "%c%c%c%c%c %u/%02u/%02u %02u:%02u %9lu %-12s %s\r\n", + (Finfo.fattrib & AM_DIR) ? 'D' : '-', + (Finfo.fattrib & AM_RDO) ? 'R' : '-', + (Finfo.fattrib & AM_HID) ? 'H' : '-', + (Finfo.fattrib & AM_SYS) ? 'S' : '-', + (Finfo.fattrib & AM_ARC) ? 'A' : '-', + (Finfo.fdate >> 9) + 1980, (Finfo.fdate >> 5) & 15, + Finfo.fdate & 31, + (Finfo.ftime >> 11), (Finfo.ftime >> 5) & 63, + Finfo.fsize, Finfo.fname, + Lfname ); + } + p1 = pf%100; + pc.printf( + "%4u file(s),%10lu%02lu bytes total\r\n%4u Dir(s)", + s1, (DWORD)(pf/100), p1, s2 + ); + if ( f_getfree(ptr, (DWORD *)&p1, &fs) == FR_OK ) { + pc.printf( ", %10lu bytes free\r\n", p1 * fs->csize * 512 ); + } else { + put_rc( (FRESULT)f_res ); + } + break; + case 'o' : /* fo <mode> <file> - Open a file */ + if (!xatoi(&ptr, &p1)) break; + while (*ptr == ' ') ptr++; + put_rc(f_open(&File1, ptr, (BYTE)p1)); + break; + case 'c' : /* fc - Close a file */ + put_rc(f_close(&File1)); + break; + case 'e' : /* fe - Seek file pointer */ + if (!xatoi(&ptr, &p1)) break; + res = f_lseek(&File1, p1); + put_rc((FRESULT)res); + if (res == FR_OK) + pc.printf("fptr=%lu(0x%lX)\r\n", File1.fptr, File1.fptr); + break; + case 'd' : /* fd <len> - read and dump file from current fp */ + if (!xatoi(&ptr, &p1)) break; + ofs = File1.fptr; + while (p1) { + if ((UINT)p1 >= 16) { + cnt = 16; + p1 -= 16; + } else { + cnt = p1; + p1 = 0; + } + res = f_read(&File1, Buff, cnt, &cnt); + if (res != FR_OK) { + put_rc((FRESULT)res); + break; + } + if (!cnt) break; + put_dump(Buff, ofs, cnt, DW_CHAR); + ofs += 16; + } + break; + case 'r' : /* fr <len> - read file */ + if (!xatoi(&ptr, &p1)) break; + p2 = 0; + t.reset(); + t.start(); + while (p1) { + if ((UINT)p1 >= blen) { + cnt = blen; + p1 -= blen; + } else { + cnt = p1; + p1 = 0; + } + res = f_read(&File1, Buff, cnt, &s2); + if (res != FR_OK) { + put_rc((FRESULT)res); + break; + } + p2 += s2; + if (cnt != s2) break; + } + tim = t.read_ms(); + pc.printf("%lu bytes read with %lu kB/sec.\r\n", + p2, tim ? (p2 / tim) : 0); + break; + case 'w' : /* fw <len> <val> - write file */ + if (!xatoi(&ptr, &p1) || !xatoi(&ptr, &p2)) break; + memset(Buff, (BYTE)p2, blen); + p2 = 0; + t.reset(); + t.start(); + while (p1) { + if ((UINT)p1 >= blen) { + cnt = blen; + p1 -= blen; + } else { + cnt = p1; + p1 = 0; + } + res = f_write(&File1, Buff, cnt, &s2); + if (res != FR_OK) { + put_rc((FRESULT)res); + break; + } + p2 += s2; + if (cnt != s2) break; + } + tim = t.read_ms(); + pc.printf("%lu bytes written with %lu kB/sec.\r\n", + p2, tim ? (p2 / tim) : 0); + break; + case 'n' : /* fn <org.name> <new.name> - Change name of an object */ + while (*ptr == ' ') ptr++; + ptr2 = strchr(ptr, ' '); + if (!ptr2) break; + *ptr2++ = 0; + while (*ptr2 == ' ') ptr2++; + put_rc(f_rename(ptr, ptr2)); + break; + case 'u' : /* fu <name> - Unlink an object */ + while (*ptr == ' ') ptr++; + put_rc(f_unlink(ptr)); + break; + case 'v' : /* fv - Truncate file */ + put_rc(f_truncate(&File1)); + break; + case 'k' : /* fk <name> - Create a directory */ + while (*ptr == ' ') ptr++; + put_rc(f_mkdir(ptr)); + break; +#if FILCPY_NOTUSE == 0 + case 'x' : /* fx <src_name> <dst_name> - Copy file */ + while ( *ptr == ' ' ) { + ptr++; + } + ptr2 = strchr( ptr, ' ' ); + if ( !ptr2 ) { + break; + } + *ptr2++ = 0; + while ( *ptr2 == ' ' ) { + ptr2++; + } + f_res = f_open( &File1, ptr, FA_OPEN_EXISTING | FA_READ ); + pc.printf("Opening %s \r\n", ptr); + if ( f_res ) { + put_rc( (FRESULT)f_res ); + break; + } + f_res = f_open( &File2, ptr2, FA_CREATE_ALWAYS | FA_WRITE ); + pc.printf(" Creating %s \r\n", ptr2); + if ( f_res ) { + put_rc( (FRESULT)f_res ); + f_close( &File1 ); + break; + } + pc.printf("Copying file..."); + p1 = 0; + for ( ;; ) { + f_res = f_read( &File1, Buff, blen, &s1 ); + if ( f_res || s1 == 0 ) { + break; /* error or eof */ + } + f_res = f_write( &File2, Buff, s1, &s2 ); + p1 += s2; + if ( f_res || s2 < s1 ) { + break; /* error or disk full */ + } + } + f_close( &File1 ); + f_close( &File2 ); + crlf(); + break; +#endif +#if _FS_RPATH + case 'g' : /* fg <path> - Change current directory */ + while (*ptr == ' ') ptr++; + put_rc(f_chdir(ptr)); + break; +#endif + } +} + +void put_dump ( + void* buff, /* Pointer to the array to be dumped */ + unsigned long addr, /* Heading address value */ + int len, /* Number of items to be dumped */ + int width /* Size of the items (DW_CHAR, DW_SHORT, DW_LONG) */ +) +{ + int i; + unsigned char *bp; + unsigned short *sp; + unsigned long *lp; + + pc.printf( "%08lx ", addr ); /* address */ + switch ( width ) { + case DW_CHAR: + bp = (unsigned char *)buff; + for ( i = 0; i < len; i++ ) { /* Hexdecimal dump */ + pc.printf( " %02x", bp[i] ); + } + pc.putc(' '); + for ( i = 0; i < len; i++ ) { /* ASCII dump */ + pc.putc( (bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.' ); + } + break; + case DW_SHORT: + sp = (unsigned short *)buff; + do { /* Hexdecimal dump */ + pc.printf( " %04x", *sp++ ); + } while ( --len ); + break; + case DW_LONG: + lp = (unsigned long *)buff; + do { /* Hexdecimal dump */ + pc.printf( " %08lx", *lp++ ); + } while ( --len ); + break; + } + pc.puts( "\r\n" ); +} + +// RTC related subroutines +void chk_and_set_time(char *ptr) +{ + char buf[64]; + + long p1; + struct tm t; + time_t seconds; + + if (xatoi(&ptr, &p1)) { + t.tm_year = (uint8_t)p1 + 100; + pc.printf("Year:%ld ",p1); + xatoi( &ptr, &p1 ); + t.tm_mon = (uint8_t)p1 - 1; + pc.printf("Month:%ld ",p1); + xatoi( &ptr, &p1 ); + t.tm_mday = (uint8_t)p1; + pc.printf("Day:%ld ",p1); + xatoi( &ptr, &p1 ); + t.tm_hour = (uint8_t)p1; + pc.printf("Hour:%ld ",p1); + xatoi( &ptr, &p1 ); + t.tm_min = (uint8_t)p1; + pc.printf("Min:%ld ",p1); + xatoi( &ptr, &p1 ); + t.tm_sec = (uint8_t)p1; + pc.printf("Sec: %ld \r\n",p1); + seconds = mktime(&t); + set_time(seconds); + } else { + seconds = time(NULL); + } + strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds)); + pc.printf("[Time] %s", buf); +} + +// Get key input data +void get_line (char *buff, int len) +{ + char c; + int idx = 0; + + for (;;) { + c = pc.getc(); + // Added by Kenji Arai / JH1PJL May 9th, 2010 + if (c == '\r') { + buff[idx++] = c; + break; + } + if ((c == '\b') && idx) { + idx--; + pc.putc(c); + pc.putc(' '); + pc.putc(c); + } + if (((uint8_t)c >= ' ') && (idx < len - 1)) { + buff[idx++] = c; + pc.putc(c); + } + } + buff[idx] = 0; + pc.puts("\r\n"); +} + +/* Outpur LF & CR */ +void crlf( void ) +{ + pc.printf( "\r\n" ); +} + +/* Check key input */ +unsigned int check_hit_key (void) +{ + return ( pc.readable() ); +} + +//------------------------------------------------------------------------------ +// Get a value of the string +//------------------------------------------------------------------------------ +/* "123 -5 0x3ff 0b1111 0377 w " + ^ 1st call returns 123 and next ptr + ^ 2nd call returns -5 and next ptr + ^ 3rd call returns 1023 and next ptr + ^ 4th call returns 15 and next ptr + ^ 5th call returns 255 and next ptr + ^ 6th call fails and returns 0 +*/ +int xatoi ( /* 0:Failed, 1:Successful */ + char **str, /* Pointer to pointer to the string */ + long *res /* Pointer to the valiable to store the value */ +) +{ + unsigned long val; + unsigned char c, r, s = 0; + + *res = 0; + while ( (c = **str) == ' ' ) { + (*str)++; /* Skip leading spaces */ + } + if ( c == '-' ) { /* negative? */ + s = 1; + c = *(++(*str)); + } + if ( c == '0' ) { + c = *(++(*str)); + switch (c) { + case 'x': /* hexdecimal */ + r = 16; + c = *(++(*str)); + break; + case 'b': /* binary */ + r = 2; + c = *(++(*str)); + break; + default: + if ( c <= ' ' ) return 1; /* single zero */ + if ( c < '0' || c > '9' ) return 0; /* invalid char */ + r = 8; /* octal */ + } + } else { + if ( c < '0' || c > '9' ) return 0; /* EOL or invalid char */ + r = 10; /* decimal */ + } + val = 0; + while ( c > ' ' ) { + if ( c >= 'a' ) { + c -= 0x20; + } + c -= '0'; + if ( c >= 17 ) { + c -= 7; + if ( c <= 9 ) { + return 0; /* invalid char */ + } + } + if ( c >= r ) { + return 0; /* invalid char for current radix */ + } + val = val * r + c; + c = *(++(*str)); + } + if (s) val = 0 - val; /* apply sign if needed */ + *res = val; + return 1; +}