From b6f0bc6543d2078d13245d945a13e378e74d76af Mon Sep 17 00:00:00 2001 From: Rostislav Lisovy Date: Wed, 18 Jul 2012 17:33:05 +0200 Subject: [PATCH] linconf: Basic sllin configuration. --- lin_config/src/Makefile | 2 +- lin_config/src/lin_config.c | 62 ++++++++++++--- lin_config/src/lin_config.h | 23 ++++-- lin_config/src/pcl_config.c | 10 ++- lin_config/src/pcl_config.h | 2 +- lin_config/src/sllin_config.c | 144 ++++++++++++++++++++++++++++++++++ 6 files changed, 216 insertions(+), 27 deletions(-) create mode 100644 lin_config/src/sllin_config.c diff --git a/lin_config/src/Makefile b/lin_config/src/Makefile index bd91ff7..52b7c2d 100644 --- a/lin_config/src/Makefile +++ b/lin_config/src/Makefile @@ -3,7 +3,7 @@ CFLAGS=-std=gnu99 -Wall -pedantic $(DEBUG) `xml2-config --cflags` LIBS=`xml2-config --libs` DEBUG=-ggdb -objects = linc_parse_xml.o pcl_config.o lin_config.o +objects = linc_parse_xml.o pcl_config.o sllin_config.o lin_config.o lin_config: $(objects) $(CC) $(objects) $(LIBS) -o lin_config diff --git a/lin_config/src/lin_config.c b/lin_config/src/lin_config.c index 9dcad11..891494c 100644 --- a/lin_config/src/lin_config.c +++ b/lin_config/src/lin_config.c @@ -27,27 +27,48 @@ #include #include "linc_parse_xml.h" #include "pcl_config.h" +#include "sllin_config.h" #include "lin_config.h" void linc_explain(int argc, char *argv[]) { +// FIXME what is default behaviour +// Write a warning about not using a rs232--usb converter for sllin fprintf(stderr, "Usage: %s [OPTIONS] \n", argv[0]); fprintf(stderr, "\n"); - fprintf(stderr, "'pcan_lin_config' Is used for configuring PEAK PCAN-LIN device.\n"); - fprintf(stderr, " When invoked without any OPTIONS, it configures PCAN-LIN device\n"); - fprintf(stderr, " with configuration obtained from '"PCL_DEFAULT_CONFIG"' file (if it exists).\n"); - fprintf(stderr, " The PCAN-LIN module enables CAN, LIN and serial participants to communicate.\n"); + fprintf(stderr, "'lin_config' is used for configuring sllin -- " \ + "simple LIN device implemented\n" \ + " as a TTY line discipline for arbitrary UART interface.\n" \ + " This program is able to configure PCAN-LIN (RS232 configurable " \ + "LIN node) as well.\n" \ + " When invoked without any OPTIONS, it configures PCAN-LIN device\n" \ + " with configuration obtained from '"PCL_DEFAULT_CONFIG"' " \ + "file (if it exists).\n"); fprintf(stderr, "\n"); - fprintf(stderr, "Options:\n"); + fprintf(stderr, "SERIAL_INTERFACE is in format CLASS:PATH\n"); + fprintf(stderr, " CLASS defines the device class -- it is either " \ + "'sllin' or 'pcanlin'\n"); + fprintf(stderr, " PATH is path to the serial interface, e.g /dev/ttyS0\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "General options:\n"); + fprintf(stderr, " -c Path to XML configuration file in PCLIN format\n"); fprintf(stderr, " -r Execute only Reset of a device\n"); - fprintf(stderr, " -f Flash the active configuration\n"); - fprintf(stderr, " -c Path to XML configuration file\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "PCAN-LIN specific options:\n"); + fprintf(stderr, " -f Store the active configuration into internal " \ + "flash memory\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Sllin specific options:\n"); + fprintf(stderr, " -a Attach sllin TTY line discipline to " \ + "particular SERIAL_INTERFACE\n"); + fprintf(stderr, " -d Detach sllin TTY line discipline from " \ + "particular SERIAL_INTERFACE\n"); fprintf(stderr, "\n"); fprintf(stderr, "Examples:\n"); - fprintf(stderr, " %s /dev/ttyS0 (Configure the device with the configuration from '"PCL_DEFAULT_CONFIG"')\n", - argv[0]); - fprintf(stderr, " %s -r /dev/ttyS0 (Reset the device)\n", argv[0]); + fprintf(stderr, " %s sllin:/dev/ttyS0 (Configure the device with the " \ + "configuration from '"PCL_DEFAULT_CONFIG"')\n", argv[0]); + fprintf(stderr, " %s -r pcanlin:/dev/ttyS0 (Reset the device)\n", argv[0]); } int main(int argc, char *argv[]) @@ -57,7 +78,7 @@ int main(int argc, char *argv[]) int flags = 0; char *filename = NULL; - while ((opt = getopt(argc, argv, "rfc:")) != -1) { + while ((opt = getopt(argc, argv, "rfc:ad")) != -1) { switch (opt) { case 'r': flags |= RESET_DEVICE_fl; @@ -68,9 +89,15 @@ int main(int argc, char *argv[]) case 'c': filename = optarg; break; + case 'a': + flags |= SLLIN_ATTACH_fl; + break; + case 'd': + flags |= SLLIN_DETACH_fl; + break; default: linc_explain(argc, argv); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } } @@ -86,7 +113,16 @@ int main(int argc, char *argv[]) if (!ret) printf("Configuration file %s parsed correctly\n", filename); - pcl_config(&linc_lin_state, flags); + linc_lin_state.flags = flags; + //ret = pcl_config(&linc_lin_state); + ret = sllin_config(&linc_lin_state); + +// printf("Press any key to detach %s ...\n", linc_lin_state.dev); +// getchar(); + + + if (ret < 0) + return EXIT_FAILURE; return EXIT_SUCCESS; } diff --git a/lin_config/src/lin_config.h b/lin_config/src/lin_config.h index 9bf6d00..e46cf8a 100644 --- a/lin_config/src/lin_config.h +++ b/lin_config/src/lin_config.h @@ -3,6 +3,8 @@ #define FLASH_CONF_fl (1 << 0) #define RESET_DEVICE_fl (1 << 1) +#define SLLIN_ATTACH_fl (1 << 2) +#define SLLIN_DETACH_fl (1 << 3) #define MAX_LIN_ID 0x3F #define PCL_DEFAULT_CONFIG "config.pclin" @@ -20,16 +22,21 @@ struct linc_frame_entry { }; struct linc_lin_state { - int is_active; - int baudrate; - int master_status; - int bus_termination; + int is_active; /* Is LIN device active */ + int baudrate; /* LIN baudrate */ + int master_status; /* LIN node type -- Master or Slave */ + int bus_termination; /* LIN bus termination in device -- Master or Slave */ + /* Subscriber/publisher table entries */ struct linc_frame_entry frame_entry[MAX_LIN_ID]; - struct linc_scheduler_entry scheduler_entry[100]; // FIXME max value - int scheduler_entries_cnt; - - char *dev; + /* Scheduler table entries */ + // FIXME max value + struct linc_scheduler_entry scheduler_entry[100]; + int scheduler_entries_cnt; /* No. of configured scheduler entries */ + + char *dev; /* Path to LIN device to be configured */ + int flags; /* Flags passed to configuration function + of particular device */ }; struct linc_lin_state linc_lin_state; diff --git a/lin_config/src/pcl_config.c b/lin_config/src/pcl_config.c index 61e07e2..06c6004 100644 --- a/lin_config/src/pcl_config.c +++ b/lin_config/src/pcl_config.c @@ -420,7 +420,7 @@ int pcl_lin_init(int tty, struct linc_lin_state *linc_lin_state) return 0; } -int pcl_config(struct linc_lin_state *linc_lin_state, unsigned int flags) +int pcl_config(struct linc_lin_state *linc_lin_state) { int tty; @@ -433,22 +433,24 @@ int pcl_config(struct linc_lin_state *linc_lin_state, unsigned int flags) pcl_set_input_mode(tty); - if (flags & RESET_DEVICE_fl) { + if (linc_lin_state->flags & RESET_DEVICE_fl) { pcl_reset_device(tty); return 0; } pcl_lin_init(tty, linc_lin_state); - if (flags & FLASH_CONF_fl) { + if (linc_lin_state->flags & FLASH_CONF_fl) { pcl_flash_config(tty); pcl_reset_device(tty); } + // FIXME add warning on unrecognized flags + //if (flags & (RESET_DEVICE_fl | FLASH_CONF_fl)) + pcl_reset_input_mode(tty); close(tty); return 0; } - diff --git a/lin_config/src/pcl_config.h b/lin_config/src/pcl_config.h index 0b8deee..70b1b16 100644 --- a/lin_config/src/pcl_config.h +++ b/lin_config/src/pcl_config.h @@ -37,6 +37,6 @@ typedef struct { uint8_t chks; /* Checksum; Bitwise XOR of all bytes except STX */ } pcl_packet_t; -int pcl_config(struct linc_lin_state *linc_lin_state, unsigned int flags); +int pcl_config(struct linc_lin_state *linc_lin_state); #endif /* _PCL_CONFIG_H_ */ diff --git a/lin_config/src/sllin_config.c b/lin_config/src/sllin_config.c new file mode 100644 index 0000000..f2c24fa --- /dev/null +++ b/lin_config/src/sllin_config.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "lin_config.h" + +#define SLLIN_LDISC 25 +struct bcm_msg { + struct bcm_msg_head msg_head; + struct can_frame frame; +}; + +struct sllin_connection { + int bcm_sock; // FIXME is necessary?? + int can_sock; + char iface[IFNAMSIZ+1]; +}; + +int sllin_bcm_config(struct linc_lin_state *linc_lin_state, + struct sllin_connection *sllin_connection) +{ + struct sockaddr_can caddr; + struct ifreq ifr; + struct bcm_msg msg; + int s; + int ret; + int i; + + //printf("tty %s to netdevice %s\n", linc_lin_state->dev, sllin_connection->iface); + + s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM); + if (s < 0) { + perror("socket(): bcmsocket"); + return -1; + } + + strcpy(ifr.ifr_name, sllin_connection->iface); + ioctl(s, SIOCGIFINDEX, &ifr); + + memset(&caddr, 0, sizeof(caddr)); + caddr.can_family = AF_CAN; + caddr.can_ifindex = ifr.ifr_ifindex; + +// ret = bind(s, (struct sockaddr*)&caddr, sizeof(caddr)); +// if (ret < 0) { +// perror("bind()"); +// return -1; +// } +// +// sllin_connection->bcm_sock = s; + + ret = connect(s, (struct sockaddr *)&caddr, sizeof(caddr)); + if (ret < 0) { + perror("connect()"); + return -1; + } + + for (i = 0; i < linc_lin_state->scheduler_entries_cnt; i++) { + memset(&msg, 0, sizeof(msg)); + msg.msg_head.nframes = 1; + msg.msg_head.opcode = TX_SETUP; + msg.msg_head.flags |= SETTIMER | STARTTIMER; + //msg.msg_head.ival2.tv_sec = // FIXME + msg.msg_head.ival2.tv_usec = + linc_lin_state->scheduler_entry[i].interval_ms * 1000; + msg.msg_head.can_id = + linc_lin_state->scheduler_entry[i].lin_id | CAN_RTR_FLAG; + msg.frame.can_dlc = 0; + + sendto(s, &msg, sizeof(msg), 0, + (struct sockaddr*)&caddr, sizeof(caddr)); + printf(".\n"); + //read_response(s); // FIXME + } + + close(s); + + printf("Configuration finished\n"); + return 0; +} + +int sllin_config(struct linc_lin_state *linc_lin_state) +{ + int tty; + int ldisc = SLLIN_LDISC; + int ret; + struct sllin_connection sllin_connection; + + tty = open(linc_lin_state->dev, O_WRONLY | O_NOCTTY); + if (tty < 0) { + perror("open()"); + return -1; + } + + /* Set sllin line discipline on given tty */ + if (linc_lin_state->flags & SLLIN_ATTACH_fl) { + ret = ioctl(tty, TIOCSETD, &ldisc); + if (ret < 0) { + perror("ioctl TIOCSETD"); + return -1; + } + + /* Retrieve the name of the created CAN netdevice */ + ret = ioctl(tty, SIOCGIFNAME, sllin_connection.iface); + if (ret < 0) { + perror("ioctl SIOCGIFNAME"); + return -1; + } + + printf("Attached tty %s to netdevice %s\n", linc_lin_state->dev, sllin_connection.iface); + } + + if (linc_lin_state->flags & SLLIN_DETACH_fl) { + ldisc = N_TTY; + ret = ioctl(tty, TIOCSETD, &ldisc); + if (ret < 0) { + perror("ioctl"); + return -1; + } + + printf("Detached sllin line discipline from %s\n", linc_lin_state->dev); + return 0; + } + + ret = sllin_bcm_config(linc_lin_state, &sllin_connection); + + printf("Press any key to detach %s ...\n", linc_lin_state->dev); + getchar(); + close(tty); + return ret; +} + -- 2.39.2