]> rtime.felk.cvut.cz Git - linux-lin.git/blob - lin_config/src/pcl_config.c
lin_config: Basic sllin frame cache configuration
[linux-lin.git] / lin_config / src / pcl_config.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <string.h>
6 #include <termios.h>
7 #include <stdint.h>
8 #include <assert.h>
9 #include "pcl_config.h"
10 #include "lin_config.h"
11
12 struct termios term_attr;
13
14 static void pcl_reset_input_mode(int tty)
15 {
16         tcsetattr(tty, TCSANOW, &term_attr);
17 }
18
19 static void pcl_set_input_mode(int tty)
20 {
21         int status;
22         struct termios tattr;
23
24         /* Flush input and output queues. */
25         if (tcflush(tty, TCIOFLUSH) != 0) {
26                 perror("tcflush");
27                 exit(EXIT_FAILURE);
28         }
29
30         /* Fetch the current terminal parameters. */
31         if (!isatty(tty)) {
32                 fprintf(stderr, "Not a terminal.\n");
33                 exit(EXIT_FAILURE);
34         }
35
36         /* Save settings for later restoring */
37         tcgetattr(tty, &term_attr);
38
39         /* RAW mode */
40         tcgetattr(tty, &tattr);
41         tattr.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
42                                 | INLCR | IGNCR | ICRNL | IXON);
43         tattr.c_oflag &= ~OPOST;
44         tattr.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
45         tattr.c_cflag &= ~(CSIZE | PARENB);
46         tattr.c_cflag |= CS8;
47
48         tattr.c_cc[VMIN] = 1;
49         tattr.c_cc[VTIME] = 0;
50
51         /* Set TX, RX speed */
52         cfsetispeed(&tattr, B38400);
53         cfsetospeed(&tattr, B38400);
54
55         status = tcsetattr(tty, TCSANOW, &tattr);
56         if (status == -1)
57                 perror("tcsetattr()");
58 }
59
60 /* Transform 'logic' representation of a frame to exact byte sequence */
61 int pcl_serialize(pcl_packet_t *pkt, uint8_t *pkt_raw)
62 {
63         int i;
64         uint8_t checksum = 0;
65
66         pkt_raw[0] = pkt->stx;
67         pkt_raw[1] = (pkt->seq_no << PCL_SEQ_NO_ofs) |
68                         (pkt->seq_frlen << PCL_SEQ_FRLEN_ofs);
69         pkt_raw[2] = (pkt->ctrl_tiface << PCL_CTRL_TIFACE_ofs) |
70                         (pkt->ctrl_comc << PCL_CTRL_COMC_ofs);
71
72         for (i = 0; i < pkt->seq_frlen; i++) {
73                 pkt_raw[3+i] = pkt->parms[i];
74         }
75
76         /* Calculate XOR checksum; Skip STX */
77         for (i = 1; i <= pkt->seq_frlen + PCL_HEADERS_SIZE; i++) {
78                 checksum ^= pkt_raw[i];
79         }
80         pkt_raw[i] = checksum;
81
82         printf("Snd: [STX] [SEQ] [PRM] [...] \n      ");
83         for (i = 0; i < pkt->seq_frlen + PCL_PACKET_OVERHEAD + 1; i++)
84                 printf("0x%02X  ", pkt_raw[i]);
85         printf("\n");
86
87         return pkt->seq_frlen + 4; /* real packet size */
88 }
89
90 int pcl_send_frame(int tty, pcl_packet_t *pkt)
91 {
92         int pkt_size;
93         int to_send;
94         int sent;
95         uint8_t pkt_buff[PCL_PKT_MAX_SIZE];
96
97         pkt_size = pcl_serialize(pkt, (uint8_t *) &pkt_buff);
98         to_send = pkt_size;
99         sent = 0;
100
101         while (to_send > 0) {
102                 sent = write(tty, pkt_buff+sent, to_send);
103                 to_send -= sent;
104         }
105
106         memset(pkt, '\0', sizeof(pcl_packet_t));
107         return 0;
108 }
109
110 int pcl_read_reset_response(int tty)
111 {
112         char c;
113         int ret;
114         int i = 0;
115         char str_match[] = {'G', 'm', 'b', 'H'};
116
117         do {
118                 ret = read(tty, &c, 1);
119                 if (ret == -1)
120                         perror("read()");
121
122                 printf("%c", c);
123
124                 if ((c == str_match[i]) && (i == 3))
125                         i = -1; /* We are done -- Stop the loop*/
126                 else if (c == str_match[i])
127                         i++; /* Match found -- Go to the next letter */
128                 else
129                         i = 0; /* Start from beginning */
130
131         } while (i != -1);
132
133         printf("\n\n");
134
135         return 0;
136 }
137
138 int pcl_read_response(int tty)
139 {
140         int i;
141         int received = 0;
142         int to_read = 0;
143         int data_length = 0;
144         uint8_t buff[PCL_PKT_MAX_SIZE];
145         //memset(buff, '\0', sizeof(buff));
146
147         /* Read 2 bytes of header */
148         received = read(tty, &buff[0], 1); /* Read STX */
149         if (received == -1)
150                 perror("read()");
151
152         if (buff[0] == 0x2) { /* STX ok */
153                 received = read(tty, &buff[1], 1); /* Read SEQ */
154                 if (received == -1)
155                         perror("read()");
156         } else {
157                 return 1;
158         }
159
160         data_length = (buff[1] & PCL_SEQ_FRLEN_msk);
161         to_read = data_length + 1; /* +chksm */
162         while (to_read > 0) {
163                 received = read(tty, &buff[2], to_read);
164                 to_read -= received;
165         }
166
167         printf("Rcv: [STX] [SEQ] [PRM] [CHK]\n"); // FIXME add spaces before "CHKS" when
168                                                         //more than 1 byte received in params
169         printf("      0x%02X  0x%02X", buff[0], buff[1]);
170         for (i = 0; i < data_length; i++) {
171                 printf("  0x%02X", buff[i + 2]);
172         }
173         printf("  0x%02X\n\n", buff[i]);
174
175         return 0;
176 }
177
178 void pcl_insert_scheduler_entries(int tty, struct linc_lin_state *linc_lin_state)
179 {
180         pcl_packet_t pkt;
181         int i;
182
183         /* Insert scheduler entry */
184         for (i = 0; i < (sizeof(linc_lin_state->scheduler_entry)/sizeof(struct linc_scheduler_entry)); i++) {
185                 pkt.stx = PCL_STX;
186                 pkt.seq_no = 0x0;
187                 pkt.seq_frlen = 0x3;
188                 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
189                 pkt.ctrl_comc = 0x28;
190                 pkt.parms[0] = (linc_lin_state->scheduler_entry[i].interval_ms) & 0xFF;
191                 pkt.parms[1] = (linc_lin_state->scheduler_entry[i].interval_ms >> 8) & 0xFF;
192                 pkt.parms[2] = linc_lin_state->scheduler_entry[i].lin_id; /* LIN ID */
193
194                 pcl_send_frame(tty, &pkt);
195                 pcl_read_response(tty);
196         }
197
198 }
199
200 void pcl_set_slave_id_and_data_configuration(int tty, struct linc_lin_state *linc_lin_state)
201 {
202         pcl_packet_t pkt;
203         int i;
204
205         /* Set Slave ID + Data Configuration */
206         for (i = 0; i < 0x3F; i++) {
207                 int len;
208
209                 if (linc_lin_state->frame_entry[i].status == 1) { /* Is Active */
210                         pkt.stx = PCL_STX;
211                         pkt.seq_no = 0x0;
212                         pkt.seq_frlen = linc_lin_state->frame_entry[i].data_len + 2;
213                         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
214                         pkt.ctrl_comc = 0x29;
215                         pkt.parms[0] = linc_lin_state->frame_entry[i].status; /* Field Status */
216                         pkt.parms[1] = i; /* LIN ID */
217                         pkt.parms[2] = linc_lin_state->frame_entry[i].data[0]; /* Data */
218                         pkt.parms[3] = linc_lin_state->frame_entry[i].data[1]; /* Data */
219                         pkt.parms[4] = linc_lin_state->frame_entry[i].data[2]; /* Data */
220                         pkt.parms[5] = linc_lin_state->frame_entry[i].data[3]; /* Data */
221                         pkt.parms[6] = linc_lin_state->frame_entry[i].data[4]; /* Data */
222                         pkt.parms[7] = linc_lin_state->frame_entry[i].data[5]; /* Data */
223                         pkt.parms[8] = linc_lin_state->frame_entry[i].data[6]; /* Data */
224                         pkt.parms[9] = linc_lin_state->frame_entry[i].data[7]; /* Data */
225
226                 } else {
227                         if (i < 0x20)
228                                 len = 4;
229                         else if (i < 0x30)
230                                 len = 6;
231                         else
232                                 len = 8;
233
234                         pkt.stx = PCL_STX;
235                         pkt.seq_no = 0x0;
236                         pkt.seq_frlen = len;
237                         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
238                         pkt.ctrl_comc = 0x29;
239                         pkt.parms[0] = 0x00; /* Field Status -- unactive */
240                         pkt.parms[1] = i; /* LIN ID */
241                 }
242
243                 pcl_send_frame(tty, &pkt);
244                 pcl_read_response(tty);
245         }
246 }
247
248 void pcl_flash_config(int tty)
249 {
250         pcl_packet_t pkt;
251
252         /* Flash Current Configuration */
253         pkt.stx = PCL_STX;
254         pkt.seq_no = 0x0;
255         pkt.seq_frlen = 0x0;
256         pkt.ctrl_tiface = PCL_PACKET_MODULE_IFACE;
257         pkt.ctrl_comc = 0x3;
258
259         pcl_send_frame(tty, &pkt);
260         pcl_read_response(tty);
261 }
262
263 void pcl_reset_device(int tty)
264 {
265         pcl_packet_t pkt;
266
267         /* Reset module */
268         pkt.stx = PCL_STX;
269         pkt.seq_no = 0x0;
270         pkt.seq_frlen = 0x0;
271         pkt.ctrl_tiface = PCL_PACKET_MODULE_IFACE;
272         pkt.ctrl_comc = 0x4;
273
274         pcl_send_frame(tty, &pkt);
275         pcl_read_reset_response(tty);
276 }
277
278 int pcl_lin_init(int tty, struct linc_lin_state *linc_lin_state)
279 {
280         pcl_packet_t pkt;
281 #if 0
282         /* Initialization according to current parameters */
283         pkt.stx = PCL_STX;
284         pkt.seq_no = 0x0;
285         pkt.seq_frlen = 0x0;
286         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
287         pkt.ctrl_comc = 0x0;
288
289         pcl_send_frame(tty, &pkt);
290         pcl_read_response(tty);
291 #endif
292
293         /* Reset module */
294         pcl_reset_device(tty);
295
296         /* Erase Master Scheduler List */
297         pkt.stx = PCL_STX;
298         pkt.seq_no = 0x0;
299         pkt.seq_frlen = 0x0;
300         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
301         pkt.ctrl_comc = 0x33;
302
303         pcl_send_frame(tty, &pkt);
304         pcl_read_response(tty);
305
306         /* Set Activation Status */
307         pkt.stx = PCL_STX;
308         pkt.seq_no = 0x0;
309         pkt.seq_frlen = 0x1;
310         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
311         pkt.ctrl_comc = 0x1E;
312         pkt.parms[0] = linc_lin_state->is_active;
313
314         pcl_send_frame(tty, &pkt);
315         pcl_read_response(tty);
316
317         /* Set bitrate */
318         pkt.stx = PCL_STX;
319         pkt.seq_no = 0x0;
320         pkt.seq_frlen = 0x2;
321         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
322         pkt.ctrl_comc = 0x1F;
323         pkt.parms[0] = linc_lin_state->baudrate & 0xFF;
324         pkt.parms[1] = (linc_lin_state->baudrate >> 8) & 0xFF;
325
326         pcl_send_frame(tty, &pkt);
327         pcl_read_response(tty);
328
329         /* Set Forward Mask */
330         pkt.stx = PCL_STX;
331         pkt.seq_no = 0x0;
332         pkt.seq_frlen = 0x1;
333         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
334         pkt.ctrl_comc = 0x20;
335         pkt.parms[0] = 0x00;
336
337         pcl_send_frame(tty, &pkt);
338         pcl_read_response(tty);
339
340         /* Set Filter Mask */
341         pkt.stx = PCL_STX;
342         pkt.seq_no = 0x0;
343         pkt.seq_frlen = 0x1;
344         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
345         pkt.ctrl_comc = 0x21;
346         pkt.parms[0] = 0xFF;
347
348         pcl_send_frame(tty, &pkt);
349         pcl_read_response(tty);
350
351         /* Set Filter Code */
352         pkt.stx = PCL_STX;
353         pkt.seq_no = 0x0;
354         pkt.seq_frlen = 0x1;
355         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
356         pkt.ctrl_comc = 0x21;
357         pkt.parms[0] = 0x00;
358
359         pcl_send_frame(tty, &pkt);
360         pcl_read_response(tty);
361
362         /* Set Message Transmission Timeouts */
363         pkt.stx = PCL_STX;
364         pkt.seq_no = 0x0;
365         pkt.seq_frlen = 0x8;
366         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
367         pkt.ctrl_comc = 0x26;
368         pkt.parms[0] = 0xA0;
369         pkt.parms[1] = 0x0F;
370         pkt.parms[2] = 0x09;
371         pkt.parms[3] = 0x00;
372         pkt.parms[4] = 0x06;
373         pkt.parms[5] = 0x00;
374         pkt.parms[6] = 0x05;
375         pkt.parms[7] = 0x00;
376
377         pcl_send_frame(tty, &pkt);
378         pcl_read_response(tty);
379
380         /* Set Message Retries */
381         pkt.stx = PCL_STX;
382         pkt.seq_no = 0x0;
383         pkt.seq_frlen = 0x1;
384         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
385         pkt.ctrl_comc = 0x27;
386         pkt.parms[0] = 0x0;
387
388         pcl_send_frame(tty, &pkt);
389         pcl_read_response(tty);
390
391         /* Set Slave ID + Data configuration */
392         pcl_set_slave_id_and_data_configuration(tty, linc_lin_state);
393
394         /* Insert scheduler entry */
395         pcl_insert_scheduler_entries(tty, linc_lin_state);
396
397         /* Set master status: Active */
398         pkt.stx = PCL_STX;
399         pkt.seq_no = 0x0;
400         pkt.seq_frlen = 0x1;
401         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
402         pkt.ctrl_comc = 0x24;
403         pkt.parms[0] = linc_lin_state->master_status;
404
405         pcl_send_frame(tty, &pkt);
406         pcl_read_response(tty);
407
408         /* Set LIN bus termination */
409         pkt.stx = PCL_STX;
410         pkt.seq_no = 0x0;
411         pkt.seq_frlen = 0x1;
412         pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
413         pkt.ctrl_comc = 0x25;
414         pkt.parms[0] = linc_lin_state->bus_termination;
415         /* Should have the same value as "Set master status" */
416
417         pcl_send_frame(tty, &pkt);
418         pcl_read_response(tty);
419
420         return 0;
421 }
422
423 int pcl_config(struct linc_lin_state *linc_lin_state)
424 {
425         int tty;
426
427         tty = open(linc_lin_state->dev, O_RDWR);
428         if (tty < 0) {
429                 perror("open()");
430                 return -4;
431         }
432         /* Configure UART */
433         pcl_set_input_mode(tty);
434
435
436         if (linc_lin_state->flags & RESET_DEVICE_fl) {
437                 pcl_reset_device(tty);
438                         return 0;
439         }
440
441         pcl_lin_init(tty, linc_lin_state);
442
443         if (linc_lin_state->flags & FLASH_CONF_fl) {
444                 pcl_flash_config(tty);
445                 pcl_reset_device(tty);
446         }
447
448         // FIXME add warning on unrecognized flags
449         //if (flags & (RESET_DEVICE_fl | FLASH_CONF_fl))
450
451         pcl_reset_input_mode(tty);
452         close(tty);
453
454         return LIN_EXIT_OK;
455 }
456