dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_sys.c
Go to the documentation of this file.
1 
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26  * for more details.
27  *
28  * You should have received a copy of the GNU General Public License along
29  * with this program; if not, see <http://www.gnu.org/licenses/>
30  *
31  * Additional note on redistribution: The copyright and license notices above
32  * must be maintained in each individual source file that is a derivative work
33  * of this source file; otherwise redistribution is prohibited.
34  */
35 
36 /* Project Includes */
37 #if !defined(_GNU_SOURCE)
38 #define _GNU_SOURCE
39 #endif /* !defined(_GNU_SOURCE) */
40 
41 #include <unistd.h>
42 #include <ctype.h>
43 
44 #if !(defined(_WIN32) || defined(WIN32) || defined(__MINGW32__))
45 #ifndef __APPLE__
46 #include <sys/mman.h>
47 #include <sched.h>
48 #endif
49 #endif
50 
51 #include "pios.h"
52 
53 #include "pios_fileout_priv.h"
54 #include "pios_com_priv.h"
55 #include "pios_serial_priv.h"
56 #include "pios_tcp_priv.h"
57 #include "pios_flash_posix_priv.h"
58 #include "pios_flightgear.h"
59 #include "pios_thread.h"
60 
61 #include "pios_hal.h"
62 #include "pios_adc_priv.h"
63 #include "pios_rcvr_priv.h"
64 #ifdef PIOS_INCLUDE_RTC
65 #include "pios_rtc_priv.h"
66 #endif
67 
68 #include "hwshared.h"
69 #include "manualcontrolsettings.h"
70 
71 #include "sha1.h"
72 
73 #if defined(PIOS_INCLUDE_SYS)
74 static bool debug_fpe=false;
75 
76 #define MAX_SPI_BUSES 16
77 
78 bool are_realtime = false;
79 
80 #ifdef PIOS_INCLUDE_SPI
81 static int num_spi = 0;
82 static pios_spi_t spi_devs[16];
83 
84 #include "pios_spi_posix_priv.h"
85 #include "pios_ms5611_priv.h"
86 #include "pios_bmm150_priv.h"
87 #include "pios_bmx055_priv.h"
88 #include "pios_flyingpio.h"
89 
90 static HwSharedPortTypesOptions rcvr_proto = HWSHARED_PORTTYPES_SBUS;
91 #endif
92 
93 #ifdef PIOS_INCLUDE_I2C
94 static char mag_orientation = 255;
95 
96 static int num_i2c = 0;
97 static pios_i2c_t i2c_devs[16];
98 
100 
101 #include "pios_px4flow_priv.h"
102 #include "pios_hmc5883_priv.h"
103 #endif
104 
105 int orig_stdout;
106 
107 static void Usage(char *cmdName) {
108  printf( "usage: %s [-f] [-r] [-m orientation] [-p proto] [-s spibase]\n"
109  "\t\t[-d drvname:bus:id] [-l logfile] [-I i2cdev] [-i drvname:bus]\n"
110  "\t\t[-g port] [-c confflash] [-x time] -!\n"
111  "\n"
112 #if !(defined(_WIN32) || defined(WIN32) || defined(__MINGW32__))
113  "\t-f\t\t\tEnables floating point exception trapping mode\n"
114 #endif
115 #ifdef __linux__
116  "\t-r\t\t\tGoes realtime and pins all memory (requires root)\n"
117 #endif
118  "\t-!\t\t\tUse a fake clock timebase gated by gcs/simsensors\n"
119  "\t-l log\t\t\tWrites simulation data to a log\n"
120  "\t-g port\t\t\tStarts FlightGear driver on port\n"
122  "\t-y\t\t\tUse an external simulator (drhil yasim)\n"
123 #endif
124 #if !(defined(_WIN32) || defined(WIN32) || defined(__MINGW32__))
125  "\t-x time\t\t\tExit after time seconds\n"
126 #endif
127  "\t-S drvname:serialpath\tStarts a serial driver on serialpath\n"
128  "\t\t\tAvailable drivers: gps msp lighttelemetry telemetry omnip\n\n"
129 #ifdef PIOS_INCLUDE_SPI
130  "\t-p proto\t\tSpecify a flyingpio rcvr protocol\n"
131  "\t\t\tAvailable protocols: dsm hottsumd hottsumh sbus ppm\n"
132  "\t\t\t\t\tsrxl ibus\n\n"
133  "\t-s spibase\t\tConfigures a SPI interface on the base path\n"
134  "\t-d drvname:bus:id\tStarts driver drvname on bus/id\n"
135  "\t\t\tAvailable drivers: bmm150 bmx055 flyingpio ms5611\n\n"
136 #endif
137 #ifdef PIOS_INCLUDE_I2C
138  "\t-m orientation\t\tSets the orientation of an external mag\n"
139  "\t-I i2cdev\t\tConfigures an I2C interface on i2cdev\n"
140  "\t-i drvname:bus\t\tStarts a driver instance on bus\n"
141  "\t\t\tAvailable drivers: px4flow hmc5883 hmc5983 bmp280 ms5611\n\n"
142 #endif
143  "\t-c confflash\t\tspecify a filename to store config flash\n"
144  "",
145  cmdName);
146 
147  exit(1);
148 }
149 
150 #ifdef PIOS_INCLUDE_OMNIP
151 #include <pios_omnip.h>
152 #endif
153 
154 #define SERIAL_BUF_LEN 384
155 static int handle_serial_device(const char *optarg) {
156  char arg_copy[128];
157 
158  strncpy(arg_copy, optarg, sizeof(arg_copy));
159  arg_copy[sizeof(arg_copy)-1] = 0;
160 
161  char *saveptr;
162 
163  char *drv_name = strtok_r(arg_copy, ":", &saveptr);
164  if (drv_name == NULL) goto fail;
165 
166  char *ser_path = strtok_r(NULL, ":", &saveptr);
167  if (ser_path == NULL) goto fail;
168 
169  // If ser_path is entirely a number.. let's treat this as TCP
170  // instead!
171 
172  long port;
173  char *endptr;
174 
175  port = strtol(ser_path, &endptr, 10);
176 
177  uintptr_t com_id;
178  uintptr_t lower_id;
179 
180  const struct pios_com_driver *com_driver;
181 
182  if ((port > 0) && (port < 65536) && !(*endptr)) {
183  struct pios_tcp_cfg *virtserial_cfg;
184 
185  virtserial_cfg = PIOS_malloc(sizeof(*virtserial_cfg));
186 
187  virtserial_cfg->ip = "0.0.0.0";
188  virtserial_cfg->port = port;
189 
190  if (PIOS_TCP_Init(&lower_id, virtserial_cfg)) {
191  printf("Can't init PIOS_TCP\n");
192  goto fail;
193  }
194 
195  com_driver = &pios_tcp_com_driver;
196 
197  } else if (!strcmp(ser_path, "stdio")) {
198  if (PIOS_SERIAL_InitFromFd(&lower_id, STDIN_FILENO,
199  orig_stdout, true)) {
200  printf("Can't init stdio-serial\n");
201  goto fail;
202  }
203 
204  com_driver = &pios_serial_com_driver;
205  } else {
206  if (PIOS_SERIAL_Init(&lower_id, ser_path)) {
207  printf("Can't init serial\n");
208  goto fail;
209  }
210 
211  com_driver = &pios_serial_com_driver;
212  }
213 
214  if (PIOS_COM_Init(&com_id, com_driver, lower_id,
215  SERIAL_BUF_LEN, SERIAL_BUF_LEN)) {
216  printf("Can't init PIOS_COM\n");
217  goto fail;
218  }
219 
220  if (!strcmp(drv_name, "gps")) {
222  PIOS_COM_GPS = com_id;
223  } else if (!strcmp(drv_name, "msp")) {
225  PIOS_COM_MSP = com_id;
226  } else if (!strcmp(drv_name, "lighttelemetry")) {
228  PIOS_COM_LIGHTTELEMETRY = com_id;
229  } else if (!strcmp(drv_name, "telemetry")) {
230  PIOS_COM_TELEM_USB = com_id;
231 #ifdef PIOS_INCLUDE_OMNIP
232  } else if (!strcmp(drv_name, "omnip")) {
233  omnip_dev_t dontcare;
234 
235  if (PIOS_OMNIP_Init(&dontcare, com_driver, lower_id)) {
236  printf("Can't init OmniP radar\n");
237  goto fail;
238  }
239 #endif
240  } else {
241  printf("Unknown serial driver %s\n", drv_name);
242  goto fail;
243  }
244 
245  return 0;
246 fail:
247  return -1;
248 }
249 
250 #ifdef PIOS_INCLUDE_I2C
251 static int handle_i2c_device(const char *optarg) {
252  char arg_copy[128];
253 
254  strncpy(arg_copy, optarg, sizeof(arg_copy));
255  arg_copy[sizeof(arg_copy) - 1] = 0;
256 
257  char *saveptr;
258 
259  char *drv_name = strtok_r(arg_copy, ":", &saveptr);
260  if (drv_name == NULL) {
261  goto fail;
262  }
263 
264  char *bus_num_str = strtok_r(NULL, ":", &saveptr);
265  if (bus_num_str == NULL) {
266  goto fail;
267  }
268 
269  int bus_num = atoi(bus_num_str);
270  if ((bus_num < 0) || (bus_num >= num_i2c)) {
271  goto fail;
272  }
273 
274  if (!strcmp(drv_name, "px4flow")) {
275  struct pios_px4flow_cfg *px4_cfg;
276 
277  px4_cfg = PIOS_malloc(sizeof(*px4_cfg));
278 
279  external_i2c_adapter_id = i2c_devs[bus_num];
280  } else if (!strcmp(drv_name, "hmc5883")) {
281  if (PIOS_HAL_ConfigureExternalMag(HWSHARED_MAG_EXTERNALHMC5883,
282  mag_orientation,
283  i2c_devs + bus_num,
284  NULL)) {
285  goto fail;
286  }
287  } else if (!strcmp(drv_name, "hmc5983")) {
288  if (PIOS_HAL_ConfigureExternalMag(HWSHARED_MAG_EXTERNALHMC5983,
289  mag_orientation, i2c_devs + bus_num,
290  NULL)) {
291  goto fail;
292  }
293  } else if (!strcmp(drv_name, "bmp280")) {
294  if (PIOS_HAL_ConfigureExternalBaro(HWSHARED_EXTBARO_BMP280,
295  i2c_devs + bus_num, NULL)) {
296  goto fail;
297  }
298  } else if (!strcmp(drv_name, "ms5611")) {
299  if (PIOS_HAL_ConfigureExternalBaro(HWSHARED_EXTBARO_MS5611,
300  i2c_devs + bus_num, NULL)) {
301  goto fail;
302  }
303  } else {
304  goto fail;
305  }
306 
307  return 0;
308 fail:
309  return -1;
310 }
311 #endif
312 
313 #ifdef PIOS_INCLUDE_SPI
314 static int handle_rcvr_protocol(const char *optarg) {
315  if (!strcmp(optarg, "dsm")) {
316  rcvr_proto = HWSHARED_PORTTYPES_DSM;
317  } else if (!strcmp(optarg, "hottsumd")) {
318  rcvr_proto = HWSHARED_PORTTYPES_HOTTSUMD;
319  } else if (!strcmp(optarg, "hottsumh")) {
320  rcvr_proto = HWSHARED_PORTTYPES_HOTTSUMH;
321  } else if (!strcmp(optarg, "sbus")) {
322  rcvr_proto = HWSHARED_PORTTYPES_SBUS;
323  } else if (!strcmp(optarg, "ppm")) {
324  rcvr_proto = HWSHARED_PORTTYPES_PPM;
325  } else if (!strcmp(optarg, "srxl")) {
326  rcvr_proto = HWSHARED_PORTTYPES_SRXL;
327  } else if (!strcmp(optarg, "ibus")) {
328  rcvr_proto = HWSHARED_PORTTYPES_IBUS;
329  } else {
330  return -1;
331  }
332 
333  return 0;
334 }
335 
336 static int handle_device(const char *optarg) {
337  char arg_copy[128];
338 
339  strncpy(arg_copy, optarg, sizeof(arg_copy));
340  arg_copy[sizeof(arg_copy)-1] = 0;
341 
342  char *saveptr;
343 
344  char *drv_name = strtok_r(arg_copy, ":", &saveptr);
345  if (drv_name == NULL) goto fail;
346 
347  char *bus_num_str = strtok_r(NULL, ":", &saveptr);
348  if (bus_num_str == NULL) goto fail;
349 
350  char *dev_num_str = strtok_r(NULL, ":", &saveptr);
351  if (dev_num_str == NULL) goto fail;
352 
353  int bus_num = atoi(bus_num_str);
354  if ((bus_num < 0) || (bus_num >= num_spi)) {
355  goto fail;
356  }
357 
358  int dev_num = atoi(dev_num_str);
359  if (dev_num < 0) {
360  goto fail;
361  }
362 
363  if (!strcmp(drv_name, "ms5611")) {
364  struct pios_ms5611_cfg *ms5611_cfg;
365 
366  ms5611_cfg = PIOS_malloc(sizeof(*ms5611_cfg));
367 
368  ms5611_cfg->oversampling = MS5611_OSR_512;
369  ms5611_cfg->temperature_interleaving = 1;
370 
371  int ret = PIOS_MS5611_SPI_Init(spi_devs[bus_num], dev_num, ms5611_cfg);
372 
373  if (ret) goto fail;
374  } else if (!strcmp(drv_name, "bmx055")) {
375  struct pios_bmx055_cfg *bmx055_cfg;
376  pios_bmx055_dev_t dev;
377 
378  bmx055_cfg = PIOS_malloc(sizeof(*bmx055_cfg));
379  bzero(bmx055_cfg, sizeof(*bmx055_cfg));
380 
381  int ret = PIOS_BMX055_SPI_Init(&dev, spi_devs[bus_num], dev_num, dev_num+1, bmx055_cfg);
382 
383  if (ret) goto fail;
384  } else if (!strcmp(drv_name, "bmm150")) {
385  struct pios_bmm150_cfg *bmm150_cfg;
386  pios_bmm150_dev_t dev;
387 
388  bmm150_cfg = PIOS_malloc(sizeof(*bmm150_cfg));
389  bzero(bmm150_cfg, sizeof(*bmm150_cfg));
390 
391  if (mag_orientation == 255) {
392  bmm150_cfg->orientation = PIOS_BMM_TOP_90DEG;
393  } else {
394  /* XXX figure out orientation properly */
395  goto fail;
396  }
397 
398  int ret = PIOS_BMM150_SPI_Init(&dev, spi_devs[bus_num], dev_num, bmm150_cfg);
399 
400  if (ret) goto fail;
401  } else if (!strcmp(drv_name, "flyingpio")) {
403 
404  int ret = PIOS_FLYINGPIO_SPI_Init(&dev, spi_devs[bus_num], dev_num,
405  rcvr_proto);
406 
407  if (ret) goto fail;
408 
409  uintptr_t rcvr_id;
410 
412  (uintptr_t) dev)) {
413  PIOS_Assert(0);
414  }
415 
416  /* Pretend what we get is PWM */
417  PIOS_HAL_SetReceiver(MANUALCONTROLSETTINGS_CHANNELGROUPS_PWM,
418  rcvr_id);
419 
420  uintptr_t adc_id;
421 
423  (uintptr_t) dev)) {
424  PIOS_Assert(0);
425  }
426  } else {
427  goto fail;
428  }
429 
430  return 0;
431 fail:
432  return -1;
433 }
434 #endif
435 
436 static void go_realtime() {
437 #ifdef __linux__
438  /* First, pin all our memory. We don't want stuff we need
439  * to get faulted out. */
440  int rc = mlockall(MCL_CURRENT | MCL_FUTURE);
441 
442  if (rc) {
443  perror("mlockall");
444  exit(1);
445  }
446 
447  /* We always run on the same processor-- why migrate when
448  * you never yield?
449  */
450 
451  cpu_set_t allowable_cpus;
452 
453  CPU_ZERO(&allowable_cpus);
454 
455  CPU_SET(0, &allowable_cpus);
456 
457  rc = sched_setaffinity(0, sizeof(allowable_cpus), &allowable_cpus);
458 
459  if (rc) {
460  perror("sched_setaffinity");
461  exit(1);
462  }
463 
464  /* Next, let's go hard realtime. */
465 
466  struct sched_param sch_p = {
467  .sched_priority = 10
468  };
469 
470  rc = sched_setscheduler(0, SCHED_RR, &sch_p);
471 
472  if (rc) {
473  perror("sched_setscheduler");
474  exit(1);
475  }
476 
477  are_realtime = true;
478 #else
479  printf("Only can do realtime stuff on Linux\n");
480  exit(1);
481 #endif
482 }
483 
484 static int saved_argc;
485 static char **saved_argv;
486 
487 #ifdef PIOS_INCLUDE_SIMSENSORS_YASIM
488 bool use_yasim;
489 #endif
490 
491 void PIOS_SYS_Args(int argc, char *argv[]) {
492  saved_argc = argc;
493  saved_argv = argv;
494 
495  int opt;
496 
497  bool hw_argseen = true;
498 
499  while ((opt = getopt(argc, argv, "!yfrx:g:l:s:d:S:I:i:m:c:p:")) != -1) {
500  switch (opt) {
501 #ifdef PIOS_INCLUDE_SIMSENSORS_YASIM
502  case 'y':
503  use_yasim = true;
504  break;
505 #endif
506  case '!':
507  PIOS_Thread_FakeClock_Tick();
508  break;
509  case 'c':
511  break;
512  case 'f':
513  debug_fpe = true;
514  break;
515  case 'r':
516  if (!hw_argseen) {
517  printf("Realtime must be before hw\n");
518  exit(1);
519  }
520 
521  go_realtime();
522  break;
523  case 'l':
524  {
525  uintptr_t tmp;
526  if (PIOS_FILEOUT_Init(&tmp,
527  optarg, "w")) {
528  printf("Couldn't open logfile %s\n",
529  optarg);
530  exit(1);
531  }
532 
535  tmp,
536  0,
538  printf("Couldn't init fileout com layer\n");
539  exit(1);
540  }
541  hw_argseen = false;
542  break;
543  }
544  case 'S':
545  if (handle_serial_device(optarg)) {
546  printf("Couldn't init device\n");
547  exit(1);
548  }
549  hw_argseen = false;
550  break;
551 #ifdef PIOS_INCLUDE_I2C
552  case 'm':
553  {
554  char *endptr;
555 
556  if (!hw_argseen) {
557  printf("Mag orientation must be before hw\n");
558  exit(1);
559  }
560 
561  mag_orientation = strtol(optarg, &endptr, 10);
562 
563  if (!endptr || (*endptr != '\0')) {
564  printf("Invalid mag orientation\n");
565  exit(1);
566  }
567  break;
568  }
569  case 'I':
570  {
571  int ret = PIOS_I2C_Init(i2c_devs + num_i2c,
572  optarg);
573 
574  if (ret < 0) {
575  printf("Couldn't init I2C\n");
576  exit(1);
577  }
578 
579  num_i2c++;
580  break;
581  }
582  case 'i':
583  if (handle_i2c_device(optarg)) {
584  printf("Couldn't init i2c device\n");
585  exit(1);
586  }
587  hw_argseen = false;
588  break;
589 #endif
590 #ifdef PIOS_INCLUDE_SPI
591  case 'd':
592  if (handle_device(optarg)) {
593  printf("Couldn't init device\n");
594  exit(1);
595  }
596  break;
597  case 's':
598  {
599  struct pios_spi_cfg *spi_cfg;
600 
601  spi_cfg = PIOS_malloc(sizeof(*spi_cfg));
602 
603  strncpy(spi_cfg->base_path, optarg,
604  sizeof(spi_cfg->base_path));
605 
606  spi_cfg->base_path[sizeof(spi_cfg->base_path)-1] = 0;
607 
608  int ret = PIOS_SPI_Init(spi_devs + num_spi,
609  spi_cfg);
610 
611  if (ret < 0) {
612  printf("Couldn't init SPI\n");
613  exit(1);
614  }
615 
616  num_spi++;
617 
618  hw_argseen = false;
619  break;
620  }
621  case 'p':
622  if (!hw_argseen) {
623  printf("Proto must be before hw\n");
624  exit(1);
625  }
626 
627  if (handle_rcvr_protocol(optarg)) {
628  printf("Invalid receiver proto\n");
629  exit(1);
630  }
631 
632  break;
633 #endif
634  case 'g':
635  {
636  uint16_t port = atoi(optarg);
637 
638  flightgear_dev_t dontcare;
639 
640  if (PIOS_FLIGHTGEAR_Init(&dontcare, port)) {
641  printf("Couldn't init FGear\n");
642  exit(1);
643  }
644 
645  hw_argseen = false;
646  break;
647  }
648 #if !(defined(_WIN32) || defined(WIN32) || defined(__MINGW32__))
649  case 'x':
650  {
651  int timeout = atoi(optarg);
652 
653  alarm(timeout);
654  break;
655  }
656 #endif
657 
658  default:
659  Usage(argv[0]);
660  break;
661  }
662  }
663 
664  if (optind < argc) {
665  Usage(argv[0]);
666  }
667 }
668 
672 #include <assert.h> /* assert */
673 #include <stdlib.h> /* printf */
674 #include <signal.h> /* sigaction */
675 #include <fenv.h> /* PE_* */
676 
677 #if !(defined(_WIN32) || defined(WIN32) || defined(__MINGW32__))
678 static void sigint_handler(int signum, siginfo_t *siginfo, void *ucontext)
679 {
680  printf("\nSIGINT received. Shutting down\n");
681  exit(0);
682 }
683 
684 static void sigfpe_handler(int signum, siginfo_t *siginfo, void *ucontext)
685 {
686  printf("\nSIGFPE received. OMG!\n");
687  exit(0);
688 }
689 #endif
690 
691 void PIOS_SYS_Init(void)
692 {
693  /* Save the old stdout in case we want to do something with it in
694  * the future, but ensure that all output goes to stderr. */
695  orig_stdout = dup(STDOUT_FILENO);
696 
697  if (orig_stdout < 0) {
698  perror("dup");
699  exit(1);
700  }
701 
702  if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
703  perror("dup2");
704  exit(1);
705  }
706 
707  setbuf(stderr, NULL);
708 
709  char ser_text[PIOS_SYS_SERIAL_NUM_ASCII_LEN + 1];
710 
711  int ret = PIOS_SYS_SerialNumberGet(ser_text);
712 
713  if (ret == 0) {
714  printf("HW serial number-- hex: %s\n", ser_text);
715  }
716 
717  /* TODO: initialize random number generator */
718 
719 #ifdef PIOS_INCLUDE_RTC
720  PIOS_RTC_Init();
721  printf("Pseudo-RTC started\n");
722 #endif
723 
724 #if !(defined(_WIN32) || defined(WIN32) || defined(__MINGW32__))
725  struct sigaction sa_int = {
726  .sa_sigaction = sigint_handler,
727  .sa_flags = SA_SIGINFO,
728  };
729 
730  int rc = sigaction(SIGINT, &sa_int, NULL);
731  assert(rc == 0);
732 
733  if (debug_fpe) {
734  struct sigaction sa_fpe = {
735  .sa_sigaction = sigfpe_handler,
736  .sa_flags = SA_SIGINFO,
737  };
738 
739  rc = sigaction(SIGFPE, &sa_fpe, NULL);
740  assert(rc == 0);
741 
742  // Underflow is fairly harmless, do we even care in debug
743  // mode?
744 #ifndef __APPLE__
745  feenableexcept(FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW |
746  FE_INVALID);
747 #else
748  // XXX need the right magic
749  printf("UNABLE TO DBEUG FPE ON OSX!\n");
750  exit(1);
751 #endif
752  }
753 #endif
754 }
755 
766 int32_t PIOS_SYS_Reset(void)
767 {
768  char *argv[128];
769 
770  /* Sigh, ensure NULL termination of array like execvpe(3) expects*/
771  int num = saved_argc;
772  int i = 0;
773 
774  if (num > 128) {
775  num = 127;
776  }
777 
778  for (i = 0; i < num; i++) {
779  argv[i] = saved_argv[i];
780  }
781 
782  argv[i] = 0;
783 
784  // Close out all fds-- open or not.
785  // We don't want our existing listening socket leaking, etc.
786  // Note that we should really be using FD_CLOEXEC, but it's really
787  // tricky.. and even if we do, we should leave this to be safe.
788  for (i = STDERR_FILENO+1; i < 1024; i++) {
789  close(i);
790  }
791 
792  execvp(argv[0], argv);
793 
794  abort();
795 
796  return -1;
797 }
798 
799 static inline uint64_t find_ser_in_buf(const char *buf)
800 {
801  char *serial = strstr(buf, "Serial");
802 
803  if (!serial) {
804  return 0;
805  }
806 
807  serial += 6;
808 
809  while ((*serial) && (isblank(*serial))) {
810  serial++;
811  }
812 
813  if (*serial != ':') {
814  return 0;
815  }
816 
817  serial++;
818 
819  while (isblank(*serial)) {
820  serial++;
821  }
822 
823  char *endptr;
824 
825  uint64_t ret = strtoull(serial, &endptr, 16);
826 
827  if (ret == 0) {
828  return 0;
829  }
830 
831  if (*endptr != '\n' && (!*endptr)) {
832  return 0;
833  }
834 
835  return ret;
836 }
837 
839 
846 int32_t PIOS_SYS_SerialNumberGetBinary(uint8_t *array)
847 {
848  uint8_t buf[8192];
849 
850  int fd;
851  int len;
852 
853  uint64_t ret = 0;
854 
855  fd = open("/proc/cpuinfo", O_RDONLY);
856 
857  if (fd >= 0) {
858  len = read(fd, buf, sizeof(buf) - 1);
859 
860  if (len >= 0) {
861  buf[len] = 0;
862 
863  ret = find_ser_in_buf((const char *) buf);
864  }
865 
866  close(fd);
867 
868  if (ret) {
869  array[0] = 'C';
870  array[1] = 'P';
871  array[2] = 'U';
872  array[3] = ':';
873 
874  for (int i = 4; i < PIOS_SYS_SERIAL_NUM_BINARY_LEN; i++) {
875  array[i] = ret >> 56;
876 
877  ret <<= 8;
878  }
879 
880  return 0;
881  }
882  }
883 
884  fd = open("/sys/class/dmi/id/board_serial", O_RDONLY);
885 
886  if (fd >= 0) {
887  len = read(fd, buf, sizeof(buf) - 1);
888 
889  if (len > 0) {
890  /* Chomp newline */
891  if (buf[len-1] == '\n') {
892  len--;
893  }
894 
895  if (len < PIOS_SYS_SERIAL_NUM_BINARY_LEN) {
896  memcpy(array, buf, len);
897 
898  for (int i = len; i < PIOS_SYS_SERIAL_NUM_BINARY_LEN;
899  i++) {
900  array[i] = 0;
901  }
902  } else {
903  /* Too long to all fit in. So put the prefix of the
904  * serial number, and then hash the rest.
905  */
906  memcpy(array, buf, PIOS_SYS_SERIAL_NUM_BINARY_LEN - 4);
907 
908  SHA1_CTX ctx;
909  sha1_init(&ctx);
910 
911  sha1_update(&ctx,
914 
915  uint8_t hash[SHA1_BLOCK_SIZE];
916  sha1_final(&ctx, hash);
917 
918  array[PIOS_SYS_SERIAL_NUM_BINARY_LEN - 4] = hash[0];
919  array[PIOS_SYS_SERIAL_NUM_BINARY_LEN - 3] = hash[1];
920  array[PIOS_SYS_SERIAL_NUM_BINARY_LEN - 2] = hash[2];
921  array[PIOS_SYS_SERIAL_NUM_BINARY_LEN - 1] = hash[3];
922  }
923 
924  return 0;
925  }
926  }
927 
928  /* Last resort: all zeroes */
929  for (int i = 0; i < PIOS_SYS_SERIAL_NUM_BINARY_LEN; i++) {
930  array[i] = 0;
931  }
932 
933  return 0;
934 }
935 
936 static inline char nibble_to_hex(uint8_t c)
937 {
938  if (c < 10) {
939  return c + '0';
940  }
941 
942  return c + 'A' - 10;
943 }
944 
946  serLenMismatch);
947 
954 int32_t PIOS_SYS_SerialNumberGet(char *str)
955 {
956  uint8_t array[PIOS_SYS_SERIAL_NUM_BINARY_LEN];
957 
958  int ret = PIOS_SYS_SerialNumberGetBinary(array);
959 
960  if (ret) {
961  return ret;
962  }
963 
964  for (int i = 0; i < PIOS_SYS_SERIAL_NUM_BINARY_LEN; i++) {
965  str[i * 2] = nibble_to_hex(array[i] >> 4);
966  str[i * 2 + 1] = nibble_to_hex(array[i] & 0xf);
967  }
968 
970 
971  /* No error */
972  return 0;
973 }
974 
975 size_t PIOS_SYS_IrqStackUnused(void)
976 {
977  return 0;
978 }
979 
980 size_t PIOS_SYS_OsStackUnused(void)
981 {
982  return 0;
983 }
984 
985 #endif
986 
char base_path[PATH_MAX]
MS5611 functions header.
const struct pios_com_driver pios_serial_com_driver
Definition: pios_serial.c:80
Main PiOS header to include all the compiled in PiOS options.
int32_t PIOS_BMX055_SPI_Init(pios_bmx055_dev_t *dev, pios_spi_t spi_id, uint32_t slave_gyro, uint32_t slave_accel, const struct pios_bmx055_cfg *cfg)
Initialize the BMX-xxxx 6/9-axis sensor on SPI.
uintptr_t adc_id
Definition: main.c:51
TCP private definitions.
uint32_t temperature_interleaving
How many samples of pressure for each temperature measurement.
int PIOS_HAL_ConfigureExternalBaro(HwSharedExtBaroOptions baro, pios_i2c_t *i2c_id, const struct pios_i2c_adapter_cfg *i2c_cfg)
Definition: pios_hal.c:1242
int32_t PIOS_BMM150_SPI_Init(pios_bmm150_dev_t *dev, pios_spi_t spi_id, uint32_t slave_mag, const struct pios_bmm150_cfg *cfg)
Initialize the BMM-xxxx 6/9-axis sensor on SPI.
#define PIOS_FILEOUT_TX_BUFFER_SIZE
int32_t PIOS_FLIGHTGEAR_Init(flightgear_dev_t *dev, uint16_t port)
int32_t PIOS_MS5611_SPI_Init(pios_spi_t spi_id, uint32_t slave_num, const struct pios_ms5611_cfg *cfg)
COM private definitions.
FlightGear driver header.
void PIOS_Modules_Enable(enum pios_modules module)
Definition: pios_modules.c:34
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
int PIOS_HAL_ConfigureExternalMag(HwSharedMagOptions mag, HwSharedMagOrientationOptions orientation, pios_i2c_t *i2c_id, const struct pios_i2c_adapter_cfg *i2c_cfg)
Definition: pios_hal.c:1298
ADC private definitions.
#define PIOS_SYS_SERIAL_NUM_BINARY_LEN
Definition: pios_sys.h:36
void PIOS_SYS_Init(void)
void PIOS_Flash_Posix_SetFName(const char *name)
uint16_t port
Definition: pios_tcp_priv.h:53
#define PIOS_COM_TELEM_USB
Definition: pios_board.h:114
Configuration structure for the MS5611 driver.
int32_t PIOS_I2C_Init(pios_i2c_t *i2c_id, const char *path)
enum pios_ms5611_osr oversampling
#define PIOS_COM_MSP
Definition: pios_board.h:66
#define PIOS_SYS_SERIAL_NUM_ASCII_LEN
Definition: pios_sys.h:37
#define PIOS_COM_LIGHTTELEMETRY
Definition: pios_board.h:120
#define PIOS_COM_OPENLOG
Definition: pios_board.h:122
pios_i2c_t external_i2c_adapter_id
Definition: pios_board.c:53
#define PIOS_INCLUDE_I2C
Definition: pios_config.h:39
const struct pios_adc_driver pios_flyingpio_adc_driver
void sha1_init(SHA1_CTX *ctx)
Definition: sha1.c:78
int32_t PIOS_RCVR_Init(uintptr_t *rcvr_id, const struct pios_rcvr_driver *driver, const uintptr_t lower_id)
struct pios_i2c_adapter * pios_i2c_t
Definition: pios_i2c.h:48
int32_t PIOS_SPI_Init(pios_spi_t *spi_dev, const struct pios_spi_cfg *cfg)
int32_t PIOS_FLYINGPIO_SPI_Init(pios_flyingpio_dev_t *dev, pios_spi_t spi_id, uint32_t slave_idx, uint8_t protocol)
Initialize the FlyingPIO programmed-IO expander.
struct pios_flyingpio_dev * pios_flyingpio_dev_t
int32_t PIOS_OMNIP_Init(omnip_dev_t *dev, const struct pios_com_driver *driver, uintptr_t lower_id)
Allocate and initialise OMNIP device.
uint8_t i
Definition: msp_messages.h:97
SERIAL private definitions.
void PIOS_RTC_Init(const struct pios_rtc_cfg *cfg)
int32_t PIOS_SYS_Reset(void)
size_t PIOS_SYS_OsStackUnused(void)
int32_t PIOS_SERIAL_InitFromFd(uintptr_t *serial_id, int readfd, int writefd, bool dont_touch_line)
Definition: pios_serial.c:151
struct pios_bmx055_dev * pios_bmx055_dev_t
Definition: pios_bmx055.h:51
void sha1_update(SHA1_CTX *ctx, const uint8_t data[], size_t len)
Definition: sha1.c:93
Definition: sha1.h:20
int32_t PIOS_FILEOUT_Init(uintptr_t *fileout_id, const char *filename, const char *mode)
Definition: pios_fileout.c:64
int32_t PIOS_SYS_SerialNumberGet(char str[PIOS_SYS_SERIAL_NUM_ASCII_LEN+1])
int32_t PIOS_TCP_Init(uintptr_t *tcp_id, const struct pios_tcp_cfg *cfg)
#define SHA1_BLOCK_SIZE
Definition: sha1.h:17
const struct pios_com_driver pios_fileout_com_driver
Definition: pios_fileout.c:50
int32_t PIOS_COM_Init(uintptr_t *com_id, const struct pios_com_driver *driver, uintptr_t lower_id, uint16_t rx_buffer_len, uint16_t tx_buffer_len)
struct pios_bmm150_dev * pios_bmm150_dev_t
Definition: pios_bmm150.h:48
struct omnip_dev_s * omnip_dev_t
Definition: pios_omnip.h:33
#define DONT_BUILD_IF(COND, MSG)
Definition: morsel.c:206
size_t PIOS_SYS_IrqStackUnused(void)
void sha1_final(SHA1_CTX *ctx, uint8_t hash[])
Definition: sha1.c:108
const char * ip
Definition: pios_tcp_priv.h:52
int32_t PIOS_ADC_Init(uintptr_t *adc_id, const struct pios_adc_driver *driver, uintptr_t lower_id)
#define PIOS_INCLUDE_SPI
Definition: pios_config.h:36
int printf(const char *format,...)
const struct pios_com_driver pios_tcp_com_driver
void PIOS_SYS_Args(int argc, char *argv[])
void PIOS_HAL_SetReceiver(int receiver_type, uintptr_t value)
FILEOUT private definitions.
const struct pios_rcvr_driver pios_flyingpio_rcvr_driver
#define PIOS_Assert(test)
Definition: pios_debug.h:52
int32_t PIOS_SERIAL_Init(uintptr_t *serial_id, const char *path)
Definition: pios_serial.c:182
#define PIOS_INCLUDE_SIMSENSORS_YASIM
Definition: pios_config.h:116
#define PIOS_COM_GPS
Definition: pios_board.h:113
enum pios_bmm150_orientation orientation
Definition: pios_bmm150.h:45
USART private definitions.
int32_t PIOS_SYS_SerialNumberGetBinary(uint8_t array[PIOS_SYS_SERIAL_NUM_BINARY_LEN])