]> rtime.felk.cvut.cz Git - linux-lin.git/blob - lin_config/src/sllin_config.c
lin_config: Run as daemon when configuring sllin tty line discipline
[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
19 #define SLLIN_LDISC                                     25
20 struct bcm_msg {
21         struct bcm_msg_head msg_head;
22         struct can_frame frame;
23 };
24
25 struct sllin_connection {
26         int bcm_sock; // FIXME is necessary??
27         int can_sock;
28         char iface[IFNAMSIZ+1];
29 };
30
31 void sllin_ms_to_timeval(int ms, struct timeval *tv)
32 {
33         tv->tv_sec = (int) ms/1000;
34         tv->tv_usec = (ms % 1000) * 1000;
35 }
36
37 int sllin_cache_config(struct linc_lin_state *linc_lin_state,
38                         struct sllin_connection *sllin_connection)
39 {
40
41         return 0;
42 }
43
44 int sllin_bcm_config(struct linc_lin_state *linc_lin_state,
45                         struct sllin_connection *sllin_connection)
46 {
47         struct sockaddr_can caddr;
48         struct ifreq ifr;
49         struct bcm_msg msg;
50         int s;
51         int ret;
52         int i;
53
54         s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
55         if (s < 0) {
56                 perror("socket(): bcmsocket");
57                 return -1;
58         }
59
60         strcpy(ifr.ifr_name, sllin_connection->iface);
61         ioctl(s, SIOCGIFINDEX, &ifr);
62
63         memset(&caddr, 0, sizeof(caddr));
64         caddr.can_family = AF_CAN;
65         caddr.can_ifindex = ifr.ifr_ifindex;
66
67 //      ret = bind(s, (struct sockaddr*)&caddr, sizeof(caddr));
68 //      if (ret < 0) {
69 //              perror("bind()");
70 //              return -1;
71 //      }
72 //
73 //      sllin_connection->bcm_sock = s;
74
75         ret = connect(s, (struct sockaddr *)&caddr, sizeof(caddr));
76         if (ret < 0) {
77                 perror("connect()");
78                 return -1;
79         }
80
81         for (i = 0; i < linc_lin_state->scheduler_entries_cnt; i++) {
82                 struct timeval time;
83                 memset(&msg, 0, sizeof(msg));
84
85                 msg.msg_head.nframes = 1;
86                 msg.msg_head.opcode = TX_SETUP;
87                 msg.msg_head.flags |= SETTIMER | STARTTIMER;
88                 sllin_ms_to_timeval(
89                         linc_lin_state->scheduler_entry[i].interval_ms, &time);
90                 msg.msg_head.ival2.tv_sec = time.tv_sec;
91                 msg.msg_head.ival2.tv_usec = time.tv_usec;
92                 msg.msg_head.can_id = (
93                         linc_lin_state->scheduler_entry[i].lin_id | CAN_RTR_FLAG);
94                 msg.frame.can_dlc = 0;
95                 msg.frame.can_id = msg.msg_head.can_id;
96
97                 //printf("tv_sec = %i, tv_usec = %i\n", time.tv_sec, time.tv_usec);
98
99                 sendto(s, &msg, sizeof(msg), 0,
100                         (struct sockaddr*)&caddr, sizeof(caddr));
101                 //read_response(s); // FIXME
102         }
103
104         /* Do not close "s" to make BCM configuration running */
105
106         printf("Configuration finished\n");
107         return 0;
108 }
109
110 int sllin_config(struct linc_lin_state *linc_lin_state)
111 {
112         int tty;
113         int ldisc = SLLIN_LDISC;
114         int ret;
115         struct sllin_connection sllin_connection;
116
117         tty = open(linc_lin_state->dev, O_WRONLY | O_NOCTTY);
118         if (tty < 0) {
119                 perror("open()");
120                 return -1;
121         }
122
123         /* Set sllin line discipline on given tty */
124         if (linc_lin_state->flags & SLLIN_ATTACH_fl) {
125                 ret = ioctl(tty, TIOCSETD, &ldisc);
126                 if (ret < 0) {
127                         perror("ioctl TIOCSETD");
128                         return -1;
129                 }
130
131                 /* Retrieve the name of the created CAN netdevice */
132                 ret = ioctl(tty, SIOCGIFNAME, sllin_connection.iface);
133                 if (ret < 0) {
134                         perror("ioctl SIOCGIFNAME");
135                         return -1;
136                 }
137
138                 printf("Attached tty %s to netdevice %s\n",
139                         linc_lin_state->dev, sllin_connection.iface);
140         }
141
142         if (linc_lin_state->flags & SLLIN_DETACH_fl) {
143                 ldisc = N_TTY;
144                 ret = ioctl(tty, TIOCSETD, &ldisc);
145                 if (ret < 0) {
146                         perror("ioctl");
147                         return -1;
148                 }
149
150                 printf("Detached sllin line discipline from %s\n",
151                         linc_lin_state->dev);
152
153                 close(tty);
154                 return LIN_EXIT_OK;
155         }
156
157         ret = sllin_bcm_config(linc_lin_state, &sllin_connection);
158         if (ret < 0)
159                 return ret;
160
161         ret = sllin_cache_config(linc_lin_state, &sllin_connection);
162
163         /* !!! Do not close "tty" to enable newly
164            configured tty line discipline */
165
166         return ret;
167 }
168