int main()

in canutils/slcan/slcan.c [179:537]


int main(int argc, char *argv[])
{
  /* UART */

  char buf[31];
  int mode = 0;
  size_t n;
  int canspeed = 1000000; /* default to 1MBps */
  int fd;                 /* UART slcan channel */

  /* CAN */

  int s;
  int nbytes;
  int i;
  int ret;
  int reccount = 0;
  struct sockaddr_can addr;
  struct canfd_frame frame;
  struct msghdr msg;
  struct iovec iov;
  fd_set rdfs;
  char ctrlmsg[CMSG_SPACE(sizeof(struct timeval) +
                          3 * sizeof(struct timespec) + sizeof(int))];
  char sbuf[40];
  char *sbp;

  if (argc != 3)
    {
      fprintf(stderr, "Usage: slcan <can device> <uart device>\n");
      fflush(stderr);
      return -1;
    }

  char *chrdev = argv[2];
  char *candev = argv[1];

  debug_print("Starting slcan on NuttX\n");
  fd = open(chrdev, O_RDWR);
  if (fd < 0)
    {
      syslog(LOG_ERR, "Failed to open serial channel %s\n", chrdev);
      return -1;
    }
  else
    {
      /* Create CAN socket */

      if (caninit(candev, &s, &addr, &ctrlmsg[0], &frame, &msg, &iov) < 0)
        {
          syslog(LOG_ERR, "Failed to open CAN socket %s\n", candev);
          close(fd);
          return -1;
        }

      /* serial interface active */

      debug_print("Serial interface open %s\n", chrdev);
      write(fd, opening, (sizeof(opening) - 1));

      while (mode < 100)
        {
          /* Setup ooll */

          FD_ZERO(&rdfs);
          FD_SET(s, &rdfs);  /* CAN Socket */
          FD_SET(fd, &rdfs); /* UART */

          if ((ret = select(s + 1, &rdfs, NULL, NULL, NULL)) <= 0)
            {
              continue;
            }

          if (FD_ISSET(s, &rdfs))
            {
              /* CAN received new message in socketCAN input */

              iov.iov_len        = sizeof(frame);
              msg.msg_namelen    = sizeof(addr);
              msg.msg_controllen = sizeof(ctrlmsg);
              msg.msg_flags      = 0;
              nbytes             = recvmsg(s, &msg, 0);

              if (nbytes == CAN_MTU)
                {
                  reccount++;
                  debug_print("R%d, Id:0x%" PRIx32 "\n",
                              reccount, frame.can_id);
                  if (frame.can_id & CAN_EFF_FLAG)
                    {
                      /* 29 bit address */

                      frame.can_id = frame.can_id & ~CAN_EFF_FLAG;
                      snprintf(sbuf, sizeof(sbuf), "T%08" PRIx32 "%d",
                               frame.can_id, frame.len);
                      sbp = &sbuf[10];
                    }
                  else
                    {
                      /* 11 bit address */

                      snprintf(sbuf, sizeof(sbuf), "t%03" PRIx32 "%d",
                               frame.can_id, frame.len);
                      sbp = &sbuf[5];
                    }

                  for (i = 0; i < frame.len; i++)
                    {
                      snprintf(sbp, sizeof(sbuf) - (sbp - sbuf),
                               "%02X", frame.data[i]);
                      sbp += 2;
                    }

                  *sbp++ = '\r';
                  *sbp   = '\0';
                  write(fd, sbuf, strlen(sbuf));
                }
            }

          if (FD_ISSET(fd, &rdfs))
            {
              /* UART receive */

              n = readlinebuffer(fd, buf, 30);

              switch (mode)
                {
                case 0: /* CAN channel not open */
                  if (n > 0)
                    {
                      if (buf[0] == 'F')
                        {
                          /* return clear flags */

                          write(fd, "F00\r", 4);
                        }
                      else if (buf[0] == 'O')
                        {
                          /* open CAN interface */

                          struct ifreq ifr;

                          strlcpy(ifr.ifr_name, argv[1], IFNAMSIZ);

                          ifr.ifr_flags = IFF_UP;
                          if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
                            {
                              syslog(LOG_ERR, "Open interface failed\n");
                              fail_return(fd);
                            }
                          else
                            {
                              mode = 1;
                              debug_print("Open interface\n");
                              ok_return(fd);
                            }
                        }
                      else if (buf[0] == 'S')
                        {
                          /* set CAN interface speed */

                          switch (buf[1])
                            {
                            case '0':
                              canspeed = 10000;
                              break;
                            case '1':
                              canspeed = 20000;
                              break;
                            case '2':
                              canspeed = 50000;
                              break;
                            case '3':
                              canspeed = 100000;
                              break;
                            case '4':
                              canspeed = 125000;
                              break;
                            case '5':
                              canspeed = 250000;
                              break;
                            case '6':
                              canspeed = 500000;
                              break;
                            case '7':
                              canspeed = 800000;
                              break;
                            case '8': /* set speed to 1Mbps */
                              canspeed = 1000000;
                              break;
                            default:
                              break;
                            }

                          struct ifreq ifr;

                          /* set the device name */

                          strlcpy(ifr.ifr_name, argv[1], IFNAMSIZ);
                          ifr.ifr_ifru.ifru_can_data.arbi_bitrate = canspeed;
                          ifr.ifr_ifru.ifru_can_data.arbi_samplep = 80;

                          if (ioctl(s, SIOCSCANBITRATE, &ifr) < 0)
                            {
                              syslog(LOG_ERR, "set speed %d failed\n",
                                     canspeed);
                              fail_return(fd);
                            }
                          else
                            {
                              debug_print("set speed %d\n", canspeed);
                              ok_return(fd);
                            }
                        }
                      else
                        {
                          /* whatever */

                          ok_return(fd);
                        }
                    }
                  break;
                case 1: /* CAN task running open interface */
                  if (n > 0)
                    {
                      if (buf[0] == 'C')
                        {
                          /* close interface */

                          struct ifreq ifr;

                          strlcpy(ifr.ifr_name, argv[1], IFNAMSIZ);

                          ifr.ifr_flags = 0;
                          if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
                            {
                              syslog(LOG_ERR, "Close interface failed\n");
                              fail_return(fd);
                            }
                          else
                            {
                              mode = 0;
                              debug_print("Close interface\n");
                              ok_return(fd);
                            }
                        }
                      else if (buf[0] == 'T')
                        {
                          /* Transmit an extended 29 bit CAN frame */

                          char tbuf[9];
                          int idval;
                          int val;

                          /* get 29bit CAN ID */

                          strncpy(tbuf, &buf[1], 8);
                          tbuf[8] = '\0';
                          sscanf(tbuf, "%x", &idval);

                          frame.len = buf[9] - '0'; /* get byte count */

                          /* get canmessage */

                          for (i = 0; i < frame.len; i++)
                            {
                              tbuf[0] = buf[10 + (2 * i)];
                              tbuf[1] = buf[11 + (2 * i)];
                              tbuf[2] = '\0';
                              sscanf(tbuf, "%x", &val);
                              frame.data[i] = val & 0xff;
                            }

                          debug_print("Transmitt: 0x%X ", idval);
                          for (i = 0; i < frame.len; i++)
                            {
                              debug_print("0x%02X ", frame.data[i]);
                            }

                          debug_print("\n");

                          frame.can_id = idval | CAN_EFF_FLAG; /* 29 bit */

                          if (write(s, &frame, CAN_MTU) != CAN_MTU)
                            {
                              syslog(LOG_ERR, "transmitt error\n");

                              /* TODO update error flags */
                            }

                          ok_return(fd);
                        }
                      else if (buf[0] == 't')
                        {
                          /* Transmit an 11 bit CAN frame */

                          char tbuf[9];
                          int idval;
                          int val;

                          /* get 11bit CAN ID */

                          strncpy(tbuf, &buf[1], 3);
                          tbuf[3] = '\0';
                          sscanf(tbuf, "%x", &idval);

                          frame.len = buf[4] - '0'; /* get byte count */

                          /* get canmessage */

                          for (i = 0; i < frame.len; i++)
                            {
                              tbuf[0] = buf[5 + (2 * i)];
                              tbuf[1] = buf[6 + (2 * i)];
                              tbuf[2] = '\0';
                              sscanf(tbuf, "%x", &val);
                              frame.data[i] = val & 0xff;
                            }

                          debug_print("Transmitt: 0x%X ", idval);
                          for (i = 0; i < frame.len; i++)
                            {
                              debug_print("0x%02X ", frame.data[i]);
                            }

                          debug_print("\n");

                          frame.can_id = idval; /* 11 bit address command */

                          if (write(s, &frame, CAN_MTU) != CAN_MTU)
                            {
                              syslog(LOG_ERR, "transmitt error\n");

                              /* TODO update error flags */
                            }

                          ok_return(fd);
                        }
                      else
                        {
                          /* whatever */

                          ok_return(fd);
                        }
                    }
                  break;
                default: /* should not happen */
                  mode = 100;
                  break;
                }
            }
        }

      close(fd);
      close(s);
    }

  return 0;
}