9 #include "pcl_config.h"
10 #include "lin_config.h"
12 struct termios term_attr;
14 static void pcl_reset_input_mode(int tty)
16 tcsetattr(tty, TCSANOW, &term_attr);
19 static void pcl_set_input_mode(int tty)
24 /* Flush input and output queues. */
25 if (tcflush(tty, TCIOFLUSH) != 0) {
30 /* Fetch the current terminal parameters. */
32 fprintf(stderr, "Not a terminal.\n");
36 /* Save settings for later restoring */
37 tcgetattr(tty, &term_attr);
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);
49 tattr.c_cc[VTIME] = 0;
51 /* Set TX, RX speed */
52 cfsetispeed(&tattr, B38400);
53 cfsetospeed(&tattr, B38400);
55 status = tcsetattr(tty, TCSANOW, &tattr);
57 perror("tcsetattr()");
60 /* Transform 'logic' representation of a frame to exact byte sequence */
61 int pcl_serialize(pcl_packet_t *pkt, uint8_t *pkt_raw)
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);
72 for (i = 0; i < pkt->seq_frlen; i++) {
73 pkt_raw[3+i] = pkt->parms[i];
76 /* Calculate XOR checksum; Skip STX */
77 for (i = 1; i <= pkt->seq_frlen + PCL_HEADERS_SIZE; i++) {
78 checksum ^= pkt_raw[i];
80 pkt_raw[i] = checksum;
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]);
87 return pkt->seq_frlen + 4; /* real packet size */
90 int pcl_send_frame(int tty, pcl_packet_t *pkt)
95 uint8_t pkt_buff[PCL_PKT_MAX_SIZE];
97 pkt_size = pcl_serialize(pkt, (uint8_t *) &pkt_buff);
101 while (to_send > 0) {
102 sent = write(tty, pkt_buff+sent, to_send);
106 memset(pkt, '\0', sizeof(pcl_packet_t));
110 int pcl_read_reset_response(int tty)
115 char str_match[] = {'G', 'm', 'b', 'H'};
118 ret = read(tty, &c, 1);
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 */
129 i = 0; /* Start from beginning */
138 int pcl_read_response(int tty)
144 uint8_t buff[PCL_PKT_MAX_SIZE];
145 //memset(buff, '\0', sizeof(buff));
147 /* Read 2 bytes of header */
148 received = read(tty, &buff[0], 1); /* Read STX */
152 if (buff[0] == 0x2) { /* STX ok */
153 received = read(tty, &buff[1], 1); /* Read SEQ */
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);
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]);
173 printf(" 0x%02X\n\n", buff[i]);
178 void pcl_insert_scheduler_entries(int tty, struct linc_lin_state *linc_lin_state)
183 /* Insert scheduler entry */
184 for (i = 0; i < (sizeof(linc_lin_state->scheduler_entry)/sizeof(struct linc_scheduler_entry)); i++) {
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 */
194 pcl_send_frame(tty, &pkt);
195 pcl_read_response(tty);
200 void pcl_set_slave_id_and_data_configuration(int tty, struct linc_lin_state *linc_lin_state)
205 /* Set Slave ID + Data Configuration */
206 for (i = 0; i < 0x3F; i++) {
209 if (linc_lin_state->frame_entry[i].status == 1) { /* Is Active */
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 */
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 */
243 pcl_send_frame(tty, &pkt);
244 pcl_read_response(tty);
248 void pcl_flash_config(int tty)
252 /* Flash Current Configuration */
256 pkt.ctrl_tiface = PCL_PACKET_MODULE_IFACE;
259 pcl_send_frame(tty, &pkt);
260 pcl_read_response(tty);
263 void pcl_reset_device(int tty)
271 pkt.ctrl_tiface = PCL_PACKET_MODULE_IFACE;
274 pcl_send_frame(tty, &pkt);
275 pcl_read_reset_response(tty);
278 int pcl_lin_init(int tty, struct linc_lin_state *linc_lin_state)
282 /* Initialization according to current parameters */
286 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
289 pcl_send_frame(tty, &pkt);
290 pcl_read_response(tty);
294 pcl_reset_device(tty);
296 /* Erase Master Scheduler List */
300 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
301 pkt.ctrl_comc = 0x33;
303 pcl_send_frame(tty, &pkt);
304 pcl_read_response(tty);
306 /* Set Activation Status */
310 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
311 pkt.ctrl_comc = 0x1E;
312 pkt.parms[0] = linc_lin_state->is_active;
314 pcl_send_frame(tty, &pkt);
315 pcl_read_response(tty);
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;
326 pcl_send_frame(tty, &pkt);
327 pcl_read_response(tty);
329 /* Set Forward Mask */
333 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
334 pkt.ctrl_comc = 0x20;
337 pcl_send_frame(tty, &pkt);
338 pcl_read_response(tty);
340 /* Set Filter Mask */
344 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
345 pkt.ctrl_comc = 0x21;
348 pcl_send_frame(tty, &pkt);
349 pcl_read_response(tty);
351 /* Set Filter Code */
355 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
356 pkt.ctrl_comc = 0x21;
359 pcl_send_frame(tty, &pkt);
360 pcl_read_response(tty);
362 /* Set Message Transmission Timeouts */
366 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
367 pkt.ctrl_comc = 0x26;
377 pcl_send_frame(tty, &pkt);
378 pcl_read_response(tty);
380 /* Set Message Retries */
384 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
385 pkt.ctrl_comc = 0x27;
388 pcl_send_frame(tty, &pkt);
389 pcl_read_response(tty);
391 /* Set Slave ID + Data configuration */
392 pcl_set_slave_id_and_data_configuration(tty, linc_lin_state);
394 /* Insert scheduler entry */
395 pcl_insert_scheduler_entries(tty, linc_lin_state);
397 /* Set master status: Active */
401 pkt.ctrl_tiface = PCL_PACKET_LIN_IFACE;
402 pkt.ctrl_comc = 0x24;
403 pkt.parms[0] = linc_lin_state->master_status;
405 pcl_send_frame(tty, &pkt);
406 pcl_read_response(tty);
408 /* Set LIN bus termination */
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" */
417 pcl_send_frame(tty, &pkt);
418 pcl_read_response(tty);
423 int pcl_config(struct linc_lin_state *linc_lin_state)
427 tty = open(linc_lin_state->dev, O_RDWR);
433 pcl_set_input_mode(tty);
436 if (linc_lin_state->flags & RESET_DEVICE_fl) {
437 pcl_reset_device(tty);
441 pcl_lin_init(tty, linc_lin_state);
443 if (linc_lin_state->flags & FLASH_CONF_fl) {
444 pcl_flash_config(tty);
445 pcl_reset_device(tty);
448 // FIXME add warning on unrecognized flags
449 //if (flags & (RESET_DEVICE_fl | FLASH_CONF_fl))
451 pcl_reset_input_mode(tty);