]> rtime.felk.cvut.cz Git - linux-lin.git/blobdiff - lin_config/src/pcl_config.c
linconf: Modular architecture.
[linux-lin.git] / lin_config / src / pcl_config.c
diff --git a/lin_config/src/pcl_config.c b/lin_config/src/pcl_config.c
new file mode 100644 (file)
index 0000000..61e07e2
--- /dev/null
@@ -0,0 +1,454 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <termios.h>
+#include <stdint.h>
+#include <assert.h>
+#include "pcl_config.h"
+#include "lin_config.h"
+
+struct termios term_attr;
+
+static void pcl_reset_input_mode(int tty)
+{
+       tcsetattr(tty, TCSANOW, &term_attr);
+}
+
+static void pcl_set_input_mode(int tty)
+{
+       int status;
+       struct termios tattr;
+
+       /* Flush input and output queues. */
+       if (tcflush(tty, TCIOFLUSH) != 0) {
+               perror("tcflush");
+               exit(EXIT_FAILURE);
+       }
+
+       /* Fetch the current terminal parameters. */
+       if (!isatty(tty)) {
+               fprintf(stderr, "Not a terminal.\n");
+               exit(EXIT_FAILURE);
+       }
+
+       /* Save settings for later restoring */
+       tcgetattr(tty, &term_attr);
+
+       /* RAW mode */
+       tcgetattr(tty, &tattr);
+       tattr.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+                               | INLCR | IGNCR | ICRNL | IXON);
+       tattr.c_oflag &= ~OPOST;
+       tattr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+       tattr.c_cflag &= ~(CSIZE | PARENB);
+       tattr.c_cflag |= CS8;
+
+       tattr.c_cc[VMIN] = 1;
+       tattr.c_cc[VTIME] = 0;
+
+       /* Set TX, RX speed */
+       cfsetispeed(&tattr, B38400);
+       cfsetospeed(&tattr, B38400);
+
+       status = tcsetattr(tty, TCSANOW, &tattr);
+       if (status == -1)
+               perror("tcsetattr()");
+}
+
+/* Transform 'logic' representation of a frame to exact byte sequence */
+int pcl_serialize(pcl_packet_t *pkt, uint8_t *pkt_raw)
+{
+       int i;
+       uint8_t checksum = 0;
+
+       pkt_raw[0] = pkt->stx;
+       pkt_raw[1] = (pkt->seq_no << PCL_SEQ_NO_ofs) |
+                       (pkt->seq_frlen << PCL_SEQ_FRLEN_ofs);
+       pkt_raw[2] = (pkt->ctrl_tiface << PCL_CTRL_TIFACE_ofs) |
+                       (pkt->ctrl_comc << PCL_CTRL_COMC_ofs);
+
+       for (i = 0; i < pkt->seq_frlen; i++) {
+               pkt_raw[3+i] = pkt->parms[i];
+       }
+
+       /* Calculate XOR checksum; Skip STX */
+       for (i = 1; i <= pkt->seq_frlen + PCL_HEADERS_SIZE; i++) {
+               checksum ^= pkt_raw[i];
+       }
+       pkt_raw[i] = checksum;
+
+       printf("Snd: [STX] [SEQ] [PRM] [...] \n      ");
+       for (i = 0; i < pkt->seq_frlen + PCL_PACKET_OVERHEAD + 1; i++)
+               printf("0x%02X  ", pkt_raw[i]);
+       printf("\n");
+
+       return pkt->seq_frlen + 4; /* real packet size */
+}
+
+int pcl_send_frame(int tty, pcl_packet_t *pkt)
+{
+       int pkt_size;
+       int to_send;
+       int sent;
+       uint8_t pkt_buff[PCL_PKT_MAX_SIZE];
+
+       pkt_size = pcl_serialize(pkt, (uint8_t *) &pkt_buff);
+       to_send = pkt_size;
+       sent = 0;
+
+       while (to_send > 0) {
+               sent = write(tty, pkt_buff+sent, to_send);
+               to_send -= sent;
+       }
+
+       memset(pkt, '\0', sizeof(pcl_packet_t));
+       return 0;
+}
+
+int pcl_read_reset_response(int tty)
+{
+       char c;
+       int ret;
+       int i = 0;
+       char str_match[] = {'G', 'm', 'b', 'H'};
+
+       do {
+               ret = read(tty, &c, 1);
+               if (ret == -1)
+                       perror("read()");
+
+               printf("%c", c);
+
+               if ((c == str_match[i]) && (i == 3))
+                       i = -1; /* We are done -- Stop the loop*/
+               else if (c == str_match[i])
+                       i++; /* Match found -- Go to the next letter */
+               else
+                       i = 0; /* Start from beginning */
+
+       } while (i != -1);
+
+       printf("\n\n");
+
+       return 0;
+}
+
+int pcl_read_response(int tty)
+{
+       int i;
+       int received = 0;
+       int to_read = 0;
+       int data_length = 0;
+       uint8_t buff[PCL_PKT_MAX_SIZE];
+       //memset(buff, '\0', sizeof(buff));
+
+       /* Read 2 bytes of header */
+       received = read(tty, &buff[0], 1); /* Read STX */
+       if (received == -1)
+               perror("read()");
+
+       if (buff[0] == 0x2) { /* STX ok */
+               received = read(tty, &buff[1], 1); /* Read SEQ */
+               if (received == -1)
+                       perror("read()");
+       } else {
+               return 1;
+       }
+
+       data_length = (buff[1] & PCL_SEQ_FRLEN_msk);
+       to_read = data_length + 1; /* +chksm */
+       while (to_read > 0) {
+               received = read(tty, &buff[2], to_read);
+               to_read -= received;
+       }
+
+       printf("Rcv: [STX] [SEQ] [PRM] [CHK]\n"); // FIXME add spaces before "CHKS" when
+                                                       //more than 1 byte received in params
+       printf("      0x%02X  0x%02X", buff[0], buff[1]);
+       for (i = 0; i < data_length; i++) {
+               printf("  0x%02X", buff[i + 2]);
+       }
+       printf("  0x%02X\n\n", buff[i]);
+
+       return 0;
+}
+
+void pcl_insert_scheduler_entries(int tty, struct linc_lin_state *linc_lin_state)
+{
+       pcl_packet_t pkt;
+       int i;
+
+       /* Insert scheduler entry */
+       for (i = 0; i < (sizeof(linc_lin_state->scheduler_entry)/sizeof(struct linc_scheduler_entry)); i++) {
+               pkt.stx = PCL_STX;
+               pkt.seq_no = 0x0;
+               pkt.seq_frlen = 0x3;
+               pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+               pkt.ctrl_comc = 0x28;
+               pkt.parms[0] = (linc_lin_state->scheduler_entry[i].interval_ms) & 0xFF;
+               pkt.parms[1] = (linc_lin_state->scheduler_entry[i].interval_ms >> 8) & 0xFF;
+               pkt.parms[2] = linc_lin_state->scheduler_entry[i].lin_id; /* LIN ID */
+
+               pcl_send_frame(tty, &pkt);
+               pcl_read_response(tty);
+       }
+
+}
+
+void pcl_set_slave_id_and_data_configuration(int tty, struct linc_lin_state *linc_lin_state)
+{
+       pcl_packet_t pkt;
+       int i;
+
+       /* Set Slave ID + Data Configuration */
+       for (i = 0; i < 0x3F; i++) {
+               int len;
+
+               if (linc_lin_state->frame_entry[i].status == PCL_ACTIVE) {
+                       pkt.stx = PCL_STX;
+                       pkt.seq_no = 0x0;
+                       pkt.seq_frlen = linc_lin_state->frame_entry[i].data_len + 2;
+                       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+                       pkt.ctrl_comc = 0x29;
+                       pkt.parms[0] = linc_lin_state->frame_entry[i].status; /* Field Status */
+                       pkt.parms[1] = i; /* LIN ID */
+                       pkt.parms[2] = linc_lin_state->frame_entry[i].data[0]; /* Data */
+                       pkt.parms[3] = linc_lin_state->frame_entry[i].data[1]; /* Data */
+                       pkt.parms[4] = linc_lin_state->frame_entry[i].data[2]; /* Data */
+                       pkt.parms[5] = linc_lin_state->frame_entry[i].data[3]; /* Data */
+                       pkt.parms[6] = linc_lin_state->frame_entry[i].data[4]; /* Data */
+                       pkt.parms[7] = linc_lin_state->frame_entry[i].data[5]; /* Data */
+                       pkt.parms[8] = linc_lin_state->frame_entry[i].data[6]; /* Data */
+                       pkt.parms[9] = linc_lin_state->frame_entry[i].data[7]; /* Data */
+
+               } else {
+                       if (i < 0x20)
+                               len = 4;
+                       else if (i < 0x30)
+                               len = 6;
+                       else
+                               len = 8;
+
+                       pkt.stx = PCL_STX;
+                       pkt.seq_no = 0x0;
+                       pkt.seq_frlen = len;
+                       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+                       pkt.ctrl_comc = 0x29;
+                       pkt.parms[0] = 0x00; /* Field Status -- unactive */
+                       pkt.parms[1] = i; /* LIN ID */
+               }
+
+               pcl_send_frame(tty, &pkt);
+               pcl_read_response(tty);
+       }
+}
+
+void pcl_flash_config(int tty)
+{
+       pcl_packet_t pkt;
+
+       /* Flash Current Configuration */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x0;
+       pkt.ctrl_tiface = PCL_PACKET_MODULE_IFACE;
+       pkt.ctrl_comc = 0x3;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+}
+
+void pcl_reset_device(int tty)
+{
+       pcl_packet_t pkt;
+
+       /* Reset module */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x0;
+       pkt.ctrl_tiface = PCL_PACKET_MODULE_IFACE;
+       pkt.ctrl_comc = 0x4;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_reset_response(tty);
+}
+
+int pcl_lin_init(int tty, struct linc_lin_state *linc_lin_state)
+{
+       pcl_packet_t pkt;
+#if 0
+       /* Initialization according to current parameters */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x0;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x0;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+#endif
+
+       /* Reset module */
+       pcl_reset_device(tty);
+
+       /* Erase Master Scheduler List */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x0;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x33;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set Activation Status */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x1;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x1E;
+       pkt.parms[0] = linc_lin_state->is_active;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set bitrate */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x2;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x1F;
+       pkt.parms[0] = 0x00;
+       pkt.parms[1] = 0x4B; /* 19200 kBit/s */
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set Forward Mask */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x1;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x20;
+       pkt.parms[0] = 0x00;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set Filter Mask */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x1;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x21;
+       pkt.parms[0] = 0xFF;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set Filter Code */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x1;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x21;
+       pkt.parms[0] = 0x00;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set Message Transmission Timeouts */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x8;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x26;
+       pkt.parms[0] = 0xA0;
+       pkt.parms[1] = 0x0F;
+       pkt.parms[2] = 0x09;
+       pkt.parms[3] = 0x00;
+       pkt.parms[4] = 0x06;
+       pkt.parms[5] = 0x00;
+       pkt.parms[6] = 0x05;
+       pkt.parms[7] = 0x00;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set Message Retries */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x1;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x27;
+       pkt.parms[0] = 0x0;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set Slave ID + Data configuration */
+       pcl_set_slave_id_and_data_configuration(tty, linc_lin_state);
+
+       /* Insert scheduler entry */
+       pcl_insert_scheduler_entries(tty, linc_lin_state);
+
+       /* Set master status: Active */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x1;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x24;
+       pkt.parms[0] = linc_lin_state->master_status;
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       /* Set LIN bus termination */
+       pkt.stx = PCL_STX;
+       pkt.seq_no = 0x0;
+       pkt.seq_frlen = 0x1;
+       pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
+       pkt.ctrl_comc = 0x25;
+       pkt.parms[0] = linc_lin_state->bus_termination;
+       /* Should have the same value as "Set master status" */
+
+       pcl_send_frame(tty, &pkt);
+       pcl_read_response(tty);
+
+       return 0;
+}
+
+int pcl_config(struct linc_lin_state *linc_lin_state, unsigned int flags)
+{
+       int tty;
+
+       tty = open(linc_lin_state->dev, O_RDWR);
+       if (tty < 0) {
+               perror("open()");
+               return -4;
+       }
+       /* Configure UART */
+       pcl_set_input_mode(tty);
+
+
+       if (flags & RESET_DEVICE_fl) {
+               pcl_reset_device(tty);
+                       return 0;
+       }
+
+       pcl_lin_init(tty, linc_lin_state);
+
+       if (flags & FLASH_CONF_fl) {
+               pcl_flash_config(tty);
+               pcl_reset_device(tty);
+       }
+
+       pcl_reset_input_mode(tty);
+       close(tty);
+
+       return 0;
+}
+
+