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;
}