#include #include #include #include #include #include #include #include #include #include "../gfaspi.h" ///////////////////////////////////////////////////////////////////////////// #define TRACE(...) fprintf(stdout, __VA_ARGS__), fflush(stdout) #define ETRACE(...) fprintf(stderr, __VA_ARGS__), fflush(stderr) #define _countof(a) (sizeof(a) / sizeof(*a)) #define UNUSED(arg) (void)arg ///////////////////////////////////////////////////////////////////////////// #define _GFA_SYSFS_PATH_ROOT "/sys/gfa/tiva/" #define _GFA_SYSFS_PATH_RTC_TIMESTAMP _GFA_SYSFS_PATH_ROOT "rtc/uxts64bin" #define _GFA_SYSFS_PATH_RTC_CTRL _GFA_SYSFS_PATH_ROOT "rtc/ctrl" #define _GFA_SYSFS_PATH_RTC_TYPE _GFA_SYSFS_PATH_ROOT "rtc/type" #define _GFA_SYSFS_PATH_MEM_RW _GFA_SYSFS_PATH_ROOT "mem/mem" #define _GFA_SYSFS_PATH_FIRMWARE_VERSION _GFA_SYSFS_PATH_ROOT "firmware/version" #define _GFA_SYSFS_PATH_ADC_BIN _GFA_SYSFS_PATH_ROOT "adc/AdcBin" #define _GFA_SYSFS_PATH_UPTIME _GFA_SYSFS_PATH_ROOT "uptime" #define _GFA_SYSFS_PATH_BACKLIGHT_DUTYCYCLE _GFA_SYSFS_PATH_ROOT "backlight/dutycycle" ///////////////////////////////////////////////////////////////////////////// typedef enum { Cmd_Inval, Cmd_Sys2Rtc, Cmd_Rtc2Sys, Cmd_GetRtc, Cmd_TestI2C, Cmd_ReadAddr, Cmd_WriteAddr, Cmd_GetFwVer, Cmd_GetADC, Cmd_GetUptime, Cmd_SetBacklight }Commands; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// static int _FileGetContent(const char *pszFilepath, void *pBuffer, size_t nCbBuffer) { int fd, ret = 0; if((fd = open(pszFilepath, O_RDONLY)) >= 0) { ret = read(fd, pBuffer, nCbBuffer); close(fd); } else ret = fd; return ret; } static int _FileSetContent(const char *pszFilepath, const void *pBuffer, size_t nCbBuffer) { int fd, ret = 0; if((fd = open(pszFilepath, O_WRONLY)) >= 0) { ret = write(fd, pBuffer, nCbBuffer); close(fd); } else ret = fd; return ret; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// static unsigned int _LegacyGetTivaTemp(void) { TIVA_ADC tadc; int ret = _FileGetContent(_GFA_SYSFS_PATH_ADC_BIN, &tadc, sizeof(tadc)); if(ret == sizeof(tadc)) return (unsigned int)tadc.TempTIVA; return 0xFFFFFFFF; } static int _LegacySetBacklightBrightness(unsigned int val) { int nLen, nRet = -1; char szBuf[256]; if((nLen = sprintf(szBuf, "%u", val)) > 0) { if((nRet = _FileSetContent(_GFA_SYSFS_PATH_BACKLIGHT_DUTYCYCLE, szBuf, nLen)) == nLen) nRet = 0; } return nRet; } ///////////////////////////////////////////////////////////////////////////// typedef unsigned int (*PFN_READ_ADDR_HANDLER)(void); typedef int (*PFN_WRITE_ADDR_HANDLER)(unsigned int); typedef struct _TIVA_LEGACY_ADDRESS { unsigned int addr; // Tiva address PFN_READ_ADDR_HANDLER pfnRead; PFN_WRITE_ADDR_HANDLER pfnWrite; }TIVA_LEGACY_ADDRESS, *LPTIVA_LEGACY_ADDRESS; typedef const TIVA_LEGACY_ADDRESS *LPCTIVA_LEGACY_ADDRESS; static const TIVA_LEGACY_ADDRESS g_tLegAddrMap[] = { { 0x200003A0, _LegacyGetTivaTemp, NULL }, { 0x200004E4, NULL, _LegacySetBacklightBrightness } }; ///////////////////////////////////////////////////////////////////////////// static LPCTIVA_LEGACY_ADDRESS _LookupLegacyAddressMap(unsigned int addr) { for(size_t i = 0; i < _countof(g_tLegAddrMap); ++i) { LPCTIVA_LEGACY_ADDRESS pla = &g_tLegAddrMap[i]; if(pla->addr == addr) return pla; } return NULL; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// static bool _StrToULong(const char *pszNum, unsigned long &l) { char *pszEndPtr = NULL; unsigned long v = strtoul(pszNum, &pszEndPtr, 16); if(((v == ULONG_MAX) && (errno == ERANGE)) || *pszEndPtr) return false; l = v; return true; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// static void _ShowUsage(void) { TRACE("\ngfaspistub V 1.0\n" " Stub to replace gfa_spi.\n Implements gfa_spi command interface using GfA SysFs.\n" " Usage: gfaspistub [opt]\n" " -w System Time to RTC\n" " -s RTC to System Time\n" " -r Read RTC\n" " -t Test I2C\n" " -i , Read from addr\n" " -o , Write to addr\n" " -v Get Firmware Version\n" " -a Get Analog Values\n" " -u Tiva Uptime\n" " -b Backlight in %% (0 .. 100)\n"); } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// static int _GetRtcType(void) { char szBuf[256]; int ret = _FileGetContent(_GFA_SYSFS_PATH_RTC_TYPE, szBuf, sizeof(szBuf)); if(ret > 0) { szBuf[ret] = '\0'; if(!strncmp(szBuf, "MCP7940", 7)) return 0; else if(!strncmp(szBuf, "DS3231", 6)) return 1; } return -1; } ///////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { int fd, nRet = 0, nLen, cmd, access = O_RDONLY, rtcType = -1; unsigned int cmdCnt = 0; unsigned long opt1 = 0xFFFFFFFF, opt2 = 0xFFFFFFFF; bool bHasOpt1 = false, bHasOpt2 = false; const char *pszSysFsPath = NULL; unsigned char ctrl = 0; char szBuf[256]; long long ts; TIVA_ADC tadc; Commands command = Cmd_Inval; LPCTIVA_LEGACY_ADDRESS ptla; ///////////////////////////////////////////////////////////////////////// // parse command line options if(argc < 2) { ETRACE("Error: No command provided!\n"); _ShowUsage(); return -1; } while((cmd = getopt(argc, argv, "-:wsrti:o:vaub:")) != -1) { switch(cmd) { case 1: if(!_StrToULong(optarg, opt2)) { ETRACE("Invalid argument: %s\n", optarg); return -1; } bHasOpt2 = true; break; case 'w': // SystemTime to RTC command = Cmd_Sys2Rtc; pszSysFsPath = _GFA_SYSFS_PATH_RTC_CTRL; access = O_RDWR; ctrl = 1; ++cmdCnt; break; case 's': // RTC to SystemTime command = Cmd_Rtc2Sys; pszSysFsPath = _GFA_SYSFS_PATH_RTC_CTRL; access = O_RDWR; ctrl = 2; ++cmdCnt; break; case 'r': // Read RTC command = Cmd_GetRtc; pszSysFsPath = _GFA_SYSFS_PATH_RTC_TIMESTAMP; ++cmdCnt; break; case 't': // testI2C command = Cmd_TestI2C; pszSysFsPath = _GFA_SYSFS_PATH_RTC_CTRL; access = O_RDWR; ctrl = 3; ++cmdCnt; break; case 'i': // read from addr if(!_StrToULong(optarg, opt1)) { ETRACE("Invalid argument: %s\n", optarg); _ShowUsage(); return -1; } command = Cmd_ReadAddr; bHasOpt1 = true; pszSysFsPath = _GFA_SYSFS_PATH_MEM_RW; ++cmdCnt; break; case 'o': // write to addr if(!_StrToULong(optarg, opt1)) { ETRACE("Invalid argument: %s\n", optarg); _ShowUsage(); return -1; } command = Cmd_WriteAddr; bHasOpt1 = true; pszSysFsPath = _GFA_SYSFS_PATH_MEM_RW; access = O_RDWR; ++cmdCnt; break; case 'v': // Get firmware version command = Cmd_GetFwVer; pszSysFsPath = _GFA_SYSFS_PATH_FIRMWARE_VERSION; ++cmdCnt; break; case 'a': // Get Analog Values command = Cmd_GetADC; pszSysFsPath = _GFA_SYSFS_PATH_ADC_BIN; ++cmdCnt; break; case 'u': // Tiva uptime command = Cmd_GetUptime; pszSysFsPath = _GFA_SYSFS_PATH_UPTIME; ++cmdCnt; break; case 'b': // Backlight in %, <0-100> if(!_StrToULong(optarg, opt1)) { ETRACE("Invalid argument: %s\n", optarg); _ShowUsage(); return -1; } command = Cmd_SetBacklight; bHasOpt1 = true; pszSysFsPath = _GFA_SYSFS_PATH_BACKLIGHT_DUTYCYCLE; access = O_WRONLY; ++cmdCnt; break; case ':': break; case '?': _ShowUsage(); return 1; default: _ShowUsage(); return 1; } if(cmdCnt > 1) { ETRACE("Error: Only one command may be provided!\n"); _ShowUsage(); return -1; } } ///////////////////////////////////////////////////////////////////////// // validate command line options switch(command) { case Cmd_Inval: ETRACE("Error: Invalid command or missing arguments!\n"); _ShowUsage(); return -1; case Cmd_ReadAddr: if(bHasOpt2) { ETRACE("Error: Invalid argument(s)!\n"); _ShowUsage(); return -1; } if(bHasOpt1) break; case Cmd_WriteAddr: if(!bHasOpt1) { ETRACE("Error: No address provided!\n"); _ShowUsage(); return -1; } if(!bHasOpt2) { ETRACE("Error: Missing value!\n"); _ShowUsage(); return -1; } break; case Cmd_SetBacklight: if(!bHasOpt1) { ETRACE("Error: No value provided!\n"); _ShowUsage(); return -1; } break; case Cmd_Sys2Rtc: case Cmd_Rtc2Sys: case Cmd_GetRtc: if((rtcType = _GetRtcType()) < 0) { ETRACE("Error: RTC-Type unknown!\n"); return -1; } break; default: if(bHasOpt1 || bHasOpt2) { ETRACE("Error: Invalid argument(s)!\n"); _ShowUsage(); return -1; } break; } ///////////////////////////////////////////////////////////////////////// // execute command if((fd = open(pszSysFsPath, access)) < 0) { ETRACE("Error opening SysFs: %s!\n", strerror(errno)); return -1; } switch(command) { case Cmd_Sys2Rtc: if((nRet = write(fd, &ctrl, 1)) == 1) { char szTime[256]; time_t t = time(NULL); struct tm *ptm = gmtime(&t); strftime(szTime, sizeof(szTime), "%y/%m/%d,%H:%M:%S", ptm); TRACE("SYSTIME(%d) \"%s\"\n", rtcType, szTime); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_Rtc2Sys: if((nRet = write(fd, &ctrl, 1)) == 1) { char szTime[256]; time_t t = time(NULL); struct tm *ptm = gmtime(&t); strftime(szTime, sizeof(szTime), "%y/%m/%d,%H:%M:%S", ptm); TRACE("RTCTIME(ok/%d) \"%s\"\n", rtcType, szTime); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_GetRtc: if((nRet = read(fd, &ts, sizeof(ts))) == sizeof(ts)) { char szTime[256]; time_t t = (time_t)ts; struct tm *ptm = gmtime(&t); strftime(szTime, sizeof(szTime), "%y/%m/%d,%H:%M:%S", ptm); TRACE("RTCTIME(ok/%d) \"%s\"\n", rtcType, szTime); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_TestI2C: if((nRet = write(fd, &ctrl, 1)) == 1) { TRACE("I2C-Test Success!\n"); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_ReadAddr: opt1 &= 0xFFFFFFFCUL; if((ptla = _LookupLegacyAddressMap((unsigned int)opt1)) && ptla->pfnRead) { unsigned int val = (*ptla->pfnRead)(); TRACE("Addr:%08lX Data:%08X\n", opt1, val); nRet = 0; } else if((nRet = lseek(fd, (off_t)opt1, SEEK_SET)) == (off_t)opt1) { unsigned int val; if((nRet = read(fd, &val, sizeof(val))) == sizeof(val)) { TRACE("Addr:%08lX Data:%08X\n", opt1, val); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_WriteAddr: opt1 &= 0xFFFFFFFCUL; if((ptla = _LookupLegacyAddressMap((unsigned int)opt1)) && ptla->pfnWrite) { if(!(nRet = (*ptla->pfnWrite)((unsigned int)opt2))) TRACE("Addr:%08lX ret:%d\n", opt1, nRet); else ETRACE("Error: %s!\n", strerror(errno)); } else if((nRet = lseek(fd, (off_t)opt1, SEEK_SET)) == (off_t)opt1) { unsigned int val = (unsigned int)opt2; if((nRet = write(fd, &val, sizeof(val))) == sizeof(val)) { TRACE("Addr:%08lX ret:0\n", opt1); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_GetFwVer: if((nRet = read(fd, szBuf, sizeof(szBuf))) > 0) { if(sscanf(szBuf, "%lu %lu", &opt1, &opt2) == 2) { TRACE("Tivia Firmware Version HW : 0x%.8lX SW: 0x%.8lX\n", opt1, opt2); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_GetADC: if((nRet = read(fd, &tadc, sizeof(tadc))) == sizeof(tadc)) { TRACE("UVers : %5.2f\n", (double)tadc.UVers / 100.0 + 0.4); TRACE("UBATV3 : %5.2f\n", (double)tadc.UBatV3 / 100.0); TRACE("TEMP : %5.2f\n", (double)tadc.Temp / 10.0); TRACE("UV5VSYS : %5.2f\n", (double)tadc.UV5Vsys / 100.0); TRACE("UV3V6BAT : %5.2f\n", (double)tadc.UV3V6Bat / 100.0); TRACE("TEMPTIVA : %5.2f\n", 147.5 - 187.5 * (double)tadc.TempTIVA / 4096.0); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_GetUptime: if((nRet = read(fd, szBuf, sizeof(szBuf))) > 0) { if(sscanf(szBuf, "%lu", &opt1) == 1) { opt1 /= 60000; int day = opt1 / 1440; int hour = (opt1 % 1440) / 60; int min = (opt1 % 1440) % 60; TRACE("%d d %02d:%02d\n", day, hour, min); nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); } else ETRACE("Error: %s!\n", strerror(errno)); break; case Cmd_SetBacklight: if((nLen = sprintf(szBuf, "%lu", opt1)) > 0) { if((nRet = write(fd, szBuf, nLen)) != nLen) ETRACE("Error: %s!\n", strerror(errno)); else nRet = 0; } else ETRACE("Error: %s!\n", strerror(errno)); break; default: break; } close(fd); return nRet; }