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
#include <assert.h>
#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] <SERIAL_INTERFACE>\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 <FILE> 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 <FILE> 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[])
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;
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;
}
}
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;
}
#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"
};
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;
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;
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;
}
-
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_ */
--- /dev/null
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <linux/can.h>
+#include <linux/can/bcm.h>
+
+#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;
+}
+