main.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. #include <errno.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <time.h>
  8. #include <limits.h>
  9. #include <getopt.h>
  10. #include "../gfaspi.h"
  11. /////////////////////////////////////////////////////////////////////////////
  12. #define TRACE(...) fprintf(stdout, __VA_ARGS__), fflush(stdout)
  13. #define ETRACE(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
  14. #define _countof(a) (sizeof(a) / sizeof(*a))
  15. #define UNUSED(arg) (void)arg
  16. /////////////////////////////////////////////////////////////////////////////
  17. #define _GFA_SYSFS_PATH_ROOT "/sys/gfa/tiva/"
  18. #define _GFA_SYSFS_PATH_RTC_TIMESTAMP _GFA_SYSFS_PATH_ROOT "rtc/uxts64bin"
  19. #define _GFA_SYSFS_PATH_RTC_CTRL _GFA_SYSFS_PATH_ROOT "rtc/ctrl"
  20. #define _GFA_SYSFS_PATH_RTC_TYPE _GFA_SYSFS_PATH_ROOT "rtc/type"
  21. #define _GFA_SYSFS_PATH_MEM_RW _GFA_SYSFS_PATH_ROOT "mem/mem"
  22. #define _GFA_SYSFS_PATH_FIRMWARE_VERSION _GFA_SYSFS_PATH_ROOT "firmware/version"
  23. #define _GFA_SYSFS_PATH_ADC_BIN _GFA_SYSFS_PATH_ROOT "adc/AdcBin"
  24. #define _GFA_SYSFS_PATH_UPTIME _GFA_SYSFS_PATH_ROOT "uptime"
  25. #define _GFA_SYSFS_PATH_BACKLIGHT_DUTYCYCLE _GFA_SYSFS_PATH_ROOT "backlight/dutycycle"
  26. /////////////////////////////////////////////////////////////////////////////
  27. typedef enum
  28. {
  29. Cmd_Inval,
  30. Cmd_Sys2Rtc,
  31. Cmd_Rtc2Sys,
  32. Cmd_GetRtc,
  33. Cmd_TestI2C,
  34. Cmd_ReadAddr,
  35. Cmd_WriteAddr,
  36. Cmd_GetFwVer,
  37. Cmd_GetADC,
  38. Cmd_GetUptime,
  39. Cmd_SetBacklight
  40. }Commands;
  41. /////////////////////////////////////////////////////////////////////////////
  42. /////////////////////////////////////////////////////////////////////////////
  43. static int _FileGetContent(const char *pszFilepath, void *pBuffer, size_t nCbBuffer)
  44. {
  45. int fd, ret = 0;
  46. if((fd = open(pszFilepath, O_RDONLY)) >= 0)
  47. {
  48. ret = read(fd, pBuffer, nCbBuffer);
  49. close(fd);
  50. }
  51. else
  52. ret = fd;
  53. return ret;
  54. }
  55. static int _FileSetContent(const char *pszFilepath, const void *pBuffer, size_t nCbBuffer)
  56. {
  57. int fd, ret = 0;
  58. if((fd = open(pszFilepath, O_WRONLY)) >= 0)
  59. {
  60. ret = write(fd, pBuffer, nCbBuffer);
  61. close(fd);
  62. }
  63. else
  64. ret = fd;
  65. return ret;
  66. }
  67. /////////////////////////////////////////////////////////////////////////////
  68. /////////////////////////////////////////////////////////////////////////////
  69. static unsigned int _LegacyGetTivaTemp(void)
  70. {
  71. TIVA_ADC tadc;
  72. int ret = _FileGetContent(_GFA_SYSFS_PATH_ADC_BIN, &tadc, sizeof(tadc));
  73. if(ret == sizeof(tadc))
  74. return (unsigned int)tadc.TempTIVA;
  75. return 0xFFFFFFFF;
  76. }
  77. static int _LegacySetBacklightBrightness(unsigned int val)
  78. {
  79. int nLen, nRet = -1;
  80. char szBuf[256];
  81. if((nLen = sprintf(szBuf, "%u", val)) > 0)
  82. {
  83. if((nRet = _FileSetContent(_GFA_SYSFS_PATH_BACKLIGHT_DUTYCYCLE, szBuf, nLen)) == nLen)
  84. nRet = 0;
  85. }
  86. return nRet;
  87. }
  88. /////////////////////////////////////////////////////////////////////////////
  89. typedef unsigned int (*PFN_READ_ADDR_HANDLER)(void);
  90. typedef int (*PFN_WRITE_ADDR_HANDLER)(unsigned int);
  91. typedef struct _TIVA_LEGACY_ADDRESS
  92. {
  93. unsigned int addr; // Tiva address
  94. PFN_READ_ADDR_HANDLER pfnRead;
  95. PFN_WRITE_ADDR_HANDLER pfnWrite;
  96. }TIVA_LEGACY_ADDRESS, *LPTIVA_LEGACY_ADDRESS;
  97. typedef const TIVA_LEGACY_ADDRESS *LPCTIVA_LEGACY_ADDRESS;
  98. static const TIVA_LEGACY_ADDRESS g_tLegAddrMap[] =
  99. {
  100. {
  101. 0x200003A0,
  102. _LegacyGetTivaTemp,
  103. NULL
  104. },
  105. {
  106. 0x200004E4,
  107. NULL,
  108. _LegacySetBacklightBrightness
  109. }
  110. };
  111. /////////////////////////////////////////////////////////////////////////////
  112. static LPCTIVA_LEGACY_ADDRESS _LookupLegacyAddressMap(unsigned int addr)
  113. {
  114. for(size_t i = 0; i < _countof(g_tLegAddrMap); ++i)
  115. {
  116. LPCTIVA_LEGACY_ADDRESS pla = &g_tLegAddrMap[i];
  117. if(pla->addr == addr)
  118. return pla;
  119. }
  120. return NULL;
  121. }
  122. /////////////////////////////////////////////////////////////////////////////
  123. /////////////////////////////////////////////////////////////////////////////
  124. static bool _StrToULong(const char *pszNum, unsigned long &l)
  125. {
  126. char *pszEndPtr = NULL;
  127. unsigned long v = strtoul(pszNum, &pszEndPtr, 16);
  128. if(((v == ULONG_MAX) && (errno == ERANGE)) || *pszEndPtr)
  129. return false;
  130. l = v;
  131. return true;
  132. }
  133. /////////////////////////////////////////////////////////////////////////////
  134. /////////////////////////////////////////////////////////////////////////////
  135. static void _ShowUsage(void)
  136. {
  137. TRACE("\ngfaspistub V 1.0\n"
  138. " Stub to replace gfa_spi.\n Implements gfa_spi command interface using GfA SysFs.\n"
  139. " Usage: gfaspistub [opt]\n"
  140. " -w System Time to RTC\n"
  141. " -s RTC to System Time\n"
  142. " -r Read RTC\n"
  143. " -t Test I2C\n"
  144. " -i <Addr HEX>, Read from addr\n"
  145. " -o <Addr HEX> <data HEX>, Write to addr\n"
  146. " -v Get Firmware Version\n"
  147. " -a Get Analog Values\n"
  148. " -u Tiva Uptime\n"
  149. " -b Backlight in %% (0 .. 100)\n");
  150. }
  151. /////////////////////////////////////////////////////////////////////////////
  152. /////////////////////////////////////////////////////////////////////////////
  153. static int _GetRtcType(void)
  154. {
  155. char szBuf[256];
  156. int ret = _FileGetContent(_GFA_SYSFS_PATH_RTC_TYPE, szBuf, sizeof(szBuf));
  157. if(ret > 0)
  158. {
  159. szBuf[ret] = '\0';
  160. if(!strncmp(szBuf, "MCP7940", 7))
  161. return 0;
  162. else if(!strncmp(szBuf, "DS3231", 6))
  163. return 1;
  164. }
  165. return -1;
  166. }
  167. /////////////////////////////////////////////////////////////////////////////
  168. int main(int argc, char *argv[])
  169. {
  170. int fd, nRet = 0, nLen, cmd, access = O_RDONLY, rtcType = -1;
  171. unsigned int cmdCnt = 0;
  172. unsigned long opt1 = 0xFFFFFFFF, opt2 = 0xFFFFFFFF;
  173. bool bHasOpt1 = false, bHasOpt2 = false;
  174. const char *pszSysFsPath = NULL;
  175. unsigned char ctrl = 0;
  176. char szBuf[256];
  177. long long ts;
  178. TIVA_ADC tadc;
  179. Commands command = Cmd_Inval;
  180. LPCTIVA_LEGACY_ADDRESS ptla;
  181. /////////////////////////////////////////////////////////////////////////
  182. // parse command line options
  183. if(argc < 2)
  184. {
  185. ETRACE("Error: No command provided!\n");
  186. _ShowUsage();
  187. return -1;
  188. }
  189. while((cmd = getopt(argc, argv, "-:wsrti:o:vaub:")) != -1)
  190. {
  191. switch(cmd)
  192. {
  193. case 1:
  194. if(!_StrToULong(optarg, opt2))
  195. {
  196. ETRACE("Invalid argument: %s\n", optarg);
  197. return -1;
  198. }
  199. bHasOpt2 = true;
  200. break;
  201. case 'w': // SystemTime to RTC
  202. command = Cmd_Sys2Rtc;
  203. pszSysFsPath = _GFA_SYSFS_PATH_RTC_CTRL;
  204. access = O_RDWR;
  205. ctrl = 1;
  206. ++cmdCnt;
  207. break;
  208. case 's': // RTC to SystemTime
  209. command = Cmd_Rtc2Sys;
  210. pszSysFsPath = _GFA_SYSFS_PATH_RTC_CTRL;
  211. access = O_RDWR;
  212. ctrl = 2;
  213. ++cmdCnt;
  214. break;
  215. case 'r': // Read RTC
  216. command = Cmd_GetRtc;
  217. pszSysFsPath = _GFA_SYSFS_PATH_RTC_TIMESTAMP;
  218. ++cmdCnt;
  219. break;
  220. case 't': // testI2C
  221. command = Cmd_TestI2C;
  222. pszSysFsPath = _GFA_SYSFS_PATH_RTC_CTRL;
  223. access = O_RDWR;
  224. ctrl = 3;
  225. ++cmdCnt;
  226. break;
  227. case 'i': // <Addr HEX> read from addr
  228. if(!_StrToULong(optarg, opt1))
  229. {
  230. ETRACE("Invalid argument: %s\n", optarg);
  231. _ShowUsage();
  232. return -1;
  233. }
  234. command = Cmd_ReadAddr;
  235. bHasOpt1 = true;
  236. pszSysFsPath = _GFA_SYSFS_PATH_MEM_RW;
  237. ++cmdCnt;
  238. break;
  239. case 'o': // <Addr HEX> <data HEX> write to addr
  240. if(!_StrToULong(optarg, opt1))
  241. {
  242. ETRACE("Invalid argument: %s\n", optarg);
  243. _ShowUsage();
  244. return -1;
  245. }
  246. command = Cmd_WriteAddr;
  247. bHasOpt1 = true;
  248. pszSysFsPath = _GFA_SYSFS_PATH_MEM_RW;
  249. access = O_RDWR;
  250. ++cmdCnt;
  251. break;
  252. case 'v': // Get firmware version
  253. command = Cmd_GetFwVer;
  254. pszSysFsPath = _GFA_SYSFS_PATH_FIRMWARE_VERSION;
  255. ++cmdCnt;
  256. break;
  257. case 'a': // Get Analog Values
  258. command = Cmd_GetADC;
  259. pszSysFsPath = _GFA_SYSFS_PATH_ADC_BIN;
  260. ++cmdCnt;
  261. break;
  262. case 'u': // Tiva uptime
  263. command = Cmd_GetUptime;
  264. pszSysFsPath = _GFA_SYSFS_PATH_UPTIME;
  265. ++cmdCnt;
  266. break;
  267. case 'b': // Backlight in %, <0-100>
  268. if(!_StrToULong(optarg, opt1))
  269. {
  270. ETRACE("Invalid argument: %s\n", optarg);
  271. _ShowUsage();
  272. return -1;
  273. }
  274. command = Cmd_SetBacklight;
  275. bHasOpt1 = true;
  276. pszSysFsPath = _GFA_SYSFS_PATH_BACKLIGHT_DUTYCYCLE;
  277. access = O_WRONLY;
  278. ++cmdCnt;
  279. break;
  280. case ':':
  281. break;
  282. case '?':
  283. _ShowUsage();
  284. return 1;
  285. default:
  286. _ShowUsage();
  287. return 1;
  288. }
  289. if(cmdCnt > 1)
  290. {
  291. ETRACE("Error: Only one command may be provided!\n");
  292. _ShowUsage();
  293. return -1;
  294. }
  295. }
  296. /////////////////////////////////////////////////////////////////////////
  297. // validate command line options
  298. switch(command)
  299. {
  300. case Cmd_Inval:
  301. ETRACE("Error: Invalid command or missing arguments!\n");
  302. _ShowUsage();
  303. return -1;
  304. case Cmd_ReadAddr:
  305. if(bHasOpt2)
  306. {
  307. ETRACE("Error: Invalid argument(s)!\n");
  308. _ShowUsage();
  309. return -1;
  310. }
  311. if(bHasOpt1)
  312. break;
  313. case Cmd_WriteAddr:
  314. if(!bHasOpt1)
  315. {
  316. ETRACE("Error: No address provided!\n");
  317. _ShowUsage();
  318. return -1;
  319. }
  320. if(!bHasOpt2)
  321. {
  322. ETRACE("Error: Missing value!\n");
  323. _ShowUsage();
  324. return -1;
  325. }
  326. break;
  327. case Cmd_SetBacklight:
  328. if(!bHasOpt1)
  329. {
  330. ETRACE("Error: No value provided!\n");
  331. _ShowUsage();
  332. return -1;
  333. }
  334. break;
  335. case Cmd_Sys2Rtc:
  336. case Cmd_Rtc2Sys:
  337. case Cmd_GetRtc:
  338. if((rtcType = _GetRtcType()) < 0)
  339. {
  340. ETRACE("Error: RTC-Type unknown!\n");
  341. return -1;
  342. }
  343. break;
  344. default:
  345. if(bHasOpt1 || bHasOpt2)
  346. {
  347. ETRACE("Error: Invalid argument(s)!\n");
  348. _ShowUsage();
  349. return -1;
  350. }
  351. break;
  352. }
  353. /////////////////////////////////////////////////////////////////////////
  354. // execute command
  355. if((fd = open(pszSysFsPath, access)) < 0)
  356. {
  357. ETRACE("Error opening SysFs: %s!\n", strerror(errno));
  358. return -1;
  359. }
  360. switch(command)
  361. {
  362. case Cmd_Sys2Rtc:
  363. if((nRet = write(fd, &ctrl, 1)) == 1)
  364. {
  365. char szTime[256];
  366. time_t t = time(NULL);
  367. struct tm *ptm = gmtime(&t);
  368. strftime(szTime, sizeof(szTime), "%y/%m/%d,%H:%M:%S", ptm);
  369. TRACE("SYSTIME(%d) \"%s\"\n", rtcType, szTime);
  370. nRet = 0;
  371. }
  372. else
  373. ETRACE("Error: %s!\n", strerror(errno));
  374. break;
  375. case Cmd_Rtc2Sys:
  376. if((nRet = write(fd, &ctrl, 1)) == 1)
  377. {
  378. char szTime[256];
  379. time_t t = time(NULL);
  380. struct tm *ptm = gmtime(&t);
  381. strftime(szTime, sizeof(szTime), "%y/%m/%d,%H:%M:%S", ptm);
  382. TRACE("RTCTIME(ok/%d) \"%s\"\n", rtcType, szTime);
  383. nRet = 0;
  384. }
  385. else
  386. ETRACE("Error: %s!\n", strerror(errno));
  387. break;
  388. case Cmd_GetRtc:
  389. if((nRet = read(fd, &ts, sizeof(ts))) == sizeof(ts))
  390. {
  391. char szTime[256];
  392. time_t t = (time_t)ts;
  393. struct tm *ptm = gmtime(&t);
  394. strftime(szTime, sizeof(szTime), "%y/%m/%d,%H:%M:%S", ptm);
  395. TRACE("RTCTIME(ok/%d) \"%s\"\n", rtcType, szTime);
  396. nRet = 0;
  397. }
  398. else
  399. ETRACE("Error: %s!\n", strerror(errno));
  400. break;
  401. case Cmd_TestI2C:
  402. if((nRet = write(fd, &ctrl, 1)) == 1)
  403. {
  404. TRACE("I2C-Test Success!\n");
  405. nRet = 0;
  406. }
  407. else
  408. ETRACE("Error: %s!\n", strerror(errno));
  409. break;
  410. case Cmd_ReadAddr:
  411. opt1 &= 0xFFFFFFFCUL;
  412. if((ptla = _LookupLegacyAddressMap((unsigned int)opt1)) && ptla->pfnRead)
  413. {
  414. unsigned int val = (*ptla->pfnRead)();
  415. TRACE("Addr:%08lX Data:%08X\n", opt1, val);
  416. nRet = 0;
  417. }
  418. else if((nRet = lseek(fd, (off_t)opt1, SEEK_SET)) == (off_t)opt1)
  419. {
  420. unsigned int val;
  421. if((nRet = read(fd, &val, sizeof(val))) == sizeof(val))
  422. {
  423. TRACE("Addr:%08lX Data:%08X\n", opt1, val);
  424. nRet = 0;
  425. }
  426. else
  427. ETRACE("Error: %s!\n", strerror(errno));
  428. }
  429. else
  430. ETRACE("Error: %s!\n", strerror(errno));
  431. break;
  432. case Cmd_WriteAddr:
  433. opt1 &= 0xFFFFFFFCUL;
  434. if((ptla = _LookupLegacyAddressMap((unsigned int)opt1)) && ptla->pfnWrite)
  435. {
  436. if(!(nRet = (*ptla->pfnWrite)((unsigned int)opt2)))
  437. TRACE("Addr:%08lX ret:%d\n", opt1, nRet);
  438. else
  439. ETRACE("Error: %s!\n", strerror(errno));
  440. }
  441. else if((nRet = lseek(fd, (off_t)opt1, SEEK_SET)) == (off_t)opt1)
  442. {
  443. unsigned int val = (unsigned int)opt2;
  444. if((nRet = write(fd, &val, sizeof(val))) == sizeof(val))
  445. {
  446. TRACE("Addr:%08lX ret:0\n", opt1);
  447. nRet = 0;
  448. }
  449. else
  450. ETRACE("Error: %s!\n", strerror(errno));
  451. }
  452. else
  453. ETRACE("Error: %s!\n", strerror(errno));
  454. break;
  455. case Cmd_GetFwVer:
  456. if((nRet = read(fd, szBuf, sizeof(szBuf))) > 0)
  457. {
  458. if(sscanf(szBuf, "%lu %lu", &opt1, &opt2) == 2)
  459. {
  460. TRACE("Tivia Firmware Version HW : 0x%.8lX SW: 0x%.8lX\n", opt1, opt2);
  461. nRet = 0;
  462. }
  463. else
  464. ETRACE("Error: %s!\n", strerror(errno));
  465. }
  466. else
  467. ETRACE("Error: %s!\n", strerror(errno));
  468. break;
  469. case Cmd_GetADC:
  470. if((nRet = read(fd, &tadc, sizeof(tadc))) == sizeof(tadc))
  471. {
  472. TRACE("UVers : %5.2f\n", (double)tadc.UVers / 100.0 + 0.4);
  473. TRACE("UBATV3 : %5.2f\n", (double)tadc.UBatV3 / 100.0);
  474. TRACE("TEMP : %5.2f\n", (double)tadc.Temp / 10.0);
  475. TRACE("UV5VSYS : %5.2f\n", (double)tadc.UV5Vsys / 100.0);
  476. TRACE("UV3V6BAT : %5.2f\n", (double)tadc.UV3V6Bat / 100.0);
  477. TRACE("TEMPTIVA : %5.2f\n", 147.5 - 187.5 * (double)tadc.TempTIVA / 4096.0);
  478. nRet = 0;
  479. }
  480. else
  481. ETRACE("Error: %s!\n", strerror(errno));
  482. break;
  483. case Cmd_GetUptime:
  484. if((nRet = read(fd, szBuf, sizeof(szBuf))) > 0)
  485. {
  486. if(sscanf(szBuf, "%lu", &opt1) == 1)
  487. {
  488. opt1 /= 60000;
  489. int day = opt1 / 1440;
  490. int hour = (opt1 % 1440) / 60;
  491. int min = (opt1 % 1440) % 60;
  492. TRACE("%d d %02d:%02d\n", day, hour, min);
  493. nRet = 0;
  494. }
  495. else
  496. ETRACE("Error: %s!\n", strerror(errno));
  497. }
  498. else
  499. ETRACE("Error: %s!\n", strerror(errno));
  500. break;
  501. case Cmd_SetBacklight:
  502. if((nLen = sprintf(szBuf, "%lu", opt1)) > 0)
  503. {
  504. if((nRet = write(fd, szBuf, nLen)) != nLen)
  505. ETRACE("Error: %s!\n", strerror(errno));
  506. else
  507. nRet = 0;
  508. }
  509. else
  510. ETRACE("Error: %s!\n", strerror(errno));
  511. break;
  512. default:
  513. break;
  514. }
  515. close(fd);
  516. return nRet;
  517. }