]> rtime.felk.cvut.cz Git - linux-lin.git/blob - lin_config/src/sllin_config.c
Merge /home/pi/repo/lin/pcan_lin_config/submodule/linux-lin
[linux-lin.git] / lin_config / src / sllin_config.c
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/ioctl.h>
4 #include <sys/uio.h>
5 #include <net/if.h>
6 #include <netinet/in.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13
14 #include <linux/can.h>
15 #include <linux/can/bcm.h>
16
17 #include "lin_config.h"
18 #include "linux/lin_bus.h"
19
20 #define SLLIN_LDISC                                     25
21 struct bcm_msg {
22         struct bcm_msg_head msg_head;
23         struct can_frame frame;
24 };
25
26 struct sllin_connection {
27         int bcm_sock; // FIXME is necessary??
28         int can_sock;
29         char iface[IFNAMSIZ+1];
30 };
31
32 void sllin_ms_to_timeval(int ms, struct timeval *tv)
33 {
34         tv->tv_sec = (int) ms/1000;
35         tv->tv_usec = (ms % 1000) * 1000;
36 }
37
38 int sllin_cache_config(struct linc_lin_state *linc_lin_state,
39                         struct sllin_connection *sllin_connection)
40 {
41         int i;
42         struct ifreq ifr;
43         struct sockaddr_can addr;
44         struct can_frame frame;
45         int s;
46         int ret;
47
48         /* Create the socket */
49         s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
50         if (s < 0) {
51                 perror("socket()");
52                 return -1;
53         }
54
55         /* Locate the interface you wish to use */
56         strcpy(ifr.ifr_name, sllin_connection->iface);
57         ioctl(s, SIOCGIFINDEX, &ifr); /* ifr.ifr_ifindex gets filled
58                                        * with that device's index */
59
60         /* Select that CAN interface, and bind the socket to it. */
61         addr.can_family = AF_CAN;
62         addr.can_ifindex = ifr.ifr_ifindex;
63         ret = bind(s, (struct sockaddr*)&addr, sizeof(addr));
64         if (ret < 0) {
65                 perror("bind()");
66                 return -1;
67         }
68
69         for (i = 0; i < 0x3F; i++) {
70                 if (linc_lin_state->frame_entry[i].status == 1) { /* Is active */
71                         frame.can_dlc = linc_lin_state->frame_entry[i].data_len;
72                         frame.can_id = i; /* LIN ID */
73                         frame.data[0] = linc_lin_state->frame_entry[i].data[0]; /* Data */
74                         frame.data[1] = linc_lin_state->frame_entry[i].data[1]; /* Data */
75                         frame.data[2] = linc_lin_state->frame_entry[i].data[2]; /* Data */
76                         frame.data[3] = linc_lin_state->frame_entry[i].data[3]; /* Data */
77                         frame.data[4] = linc_lin_state->frame_entry[i].data[4]; /* Data */
78                         frame.data[5] = linc_lin_state->frame_entry[i].data[5]; /* Data */
79                         frame.data[6] = linc_lin_state->frame_entry[i].data[6]; /* Data */
80                         frame.data[7] = linc_lin_state->frame_entry[i].data[7]; /* Data */
81
82                         frame.can_id |= LIN_CTRL_FRAME | LIN_CACHE_RESPONSE;
83                         ret = write(s, &frame, sizeof(frame));
84                         printf("configuring frame cache; ret = %d\n", ret);
85                         //if (ret ...)
86                         //read_response(tty);
87                 }
88         }
89
90         close(s);
91         return 0;
92 }
93
94 int sllin_bcm_config(struct linc_lin_state *linc_lin_state,
95                         struct sllin_connection *sllin_connection)
96 {
97         struct sockaddr_can caddr;
98         struct ifreq ifr;
99         struct bcm_msg msg;
100         int s;
101         int ret;
102         int i;
103
104         s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
105         if (s < 0) {
106                 perror("socket(): bcmsocket");
107                 return -1;
108         }
109
110         strcpy(ifr.ifr_name, sllin_connection->iface);
111         ioctl(s, SIOCGIFINDEX, &ifr);
112
113         memset(&caddr, 0, sizeof(caddr));
114         caddr.can_family = AF_CAN;
115         caddr.can_ifindex = ifr.ifr_ifindex;
116
117 //      ret = bind(s, (struct sockaddr*)&caddr, sizeof(caddr));
118 //      if (ret < 0) {
119 //              perror("bind()");
120 //              return -1;
121 //      }
122 //
123 //      sllin_connection->bcm_sock = s;
124
125         ret = connect(s, (struct sockaddr *)&caddr, sizeof(caddr));
126         if (ret < 0) {
127                 perror("connect()");
128                 return -1;
129         }
130
131         for (i = 0; i < linc_lin_state->scheduler_entries_cnt; i++) {
132                 struct timeval time;
133                 memset(&msg, 0, sizeof(msg));
134
135                 msg.msg_head.nframes = 1;
136                 msg.msg_head.opcode = TX_SETUP;
137                 msg.msg_head.flags |= SETTIMER | STARTTIMER;
138                 sllin_ms_to_timeval(
139                         linc_lin_state->scheduler_entry[i].interval_ms, &time);
140                 msg.msg_head.ival2.tv_sec = time.tv_sec;
141                 msg.msg_head.ival2.tv_usec = time.tv_usec;
142                 msg.msg_head.can_id = (
143                         linc_lin_state->scheduler_entry[i].lin_id | CAN_RTR_FLAG);
144                 msg.frame.can_dlc = 0;
145                 msg.frame.can_id = msg.msg_head.can_id;
146
147                 //printf("tv_sec = %i, tv_usec = %i\n", time.tv_sec, time.tv_usec);
148
149                 sendto(s, &msg, sizeof(msg), 0,
150                         (struct sockaddr*)&caddr, sizeof(caddr));
151                 //read_response(s); // FIXME
152         }
153
154         /* Do not close "s" to make BCM configuration running */
155
156         printf("Configuration finished\n");
157         return 0;
158 }
159
160 int sllin_config(struct linc_lin_state *linc_lin_state)
161 {
162         int tty;
163         int ldisc = SLLIN_LDISC;
164         int ret;
165         struct sllin_connection sllin_connection;
166
167         tty = open(linc_lin_state->dev, O_WRONLY | O_NOCTTY);
168         if (tty < 0) {
169                 perror("open()");
170                 return -1;
171         }
172
173         /* Set sllin line discipline on given tty */
174         if (linc_lin_state->flags & SLLIN_ATTACH_fl) {
175                 ret = ioctl(tty, TIOCSETD, &ldisc);
176                 if (ret < 0) {
177                         perror("ioctl TIOCSETD");
178                         return -1;
179                 }
180
181                 /* Retrieve the name of the created CAN netdevice */
182                 ret = ioctl(tty, SIOCGIFNAME, sllin_connection.iface);
183                 if (ret < 0) {
184                         perror("ioctl SIOCGIFNAME");
185                         return -1;
186                 }
187
188                 printf("Attached tty %s to netdevice %s\n",
189                         linc_lin_state->dev, sllin_connection.iface);
190         }
191
192         if (linc_lin_state->flags & SLLIN_DETACH_fl) {
193                 ldisc = N_TTY;
194                 ret = ioctl(tty, TIOCSETD, &ldisc);
195                 if (ret < 0) {
196                         perror("ioctl");
197                         return -1;
198                 }
199
200                 printf("Detached sllin line discipline from %s\n",
201                         linc_lin_state->dev);
202
203                 close(tty);
204                 return LIN_EXIT_OK;
205         }
206
207         ret = sllin_bcm_config(linc_lin_state, &sllin_connection);
208         if (ret < 0)
209                 return ret;
210
211         ret = sllin_cache_config(linc_lin_state, &sllin_connection);
212
213         /* !!! Do not close "tty" to enable newly
214            configured tty line discipline */
215
216         return ret;
217 }
218