2 #include <sys/socket.h>
7 #include <netinet/in.h>
15 #include <netlink/netlink.h>
16 #include <netlink/cache.h>
17 #include <netlink/route/link.h>
18 #include <netlink/socket.h>
20 #include <linux/can.h>
21 #include <linux/can/bcm.h>
23 #include "lin_config.h"
24 #include "linux/lin_bus.h"
26 #define SLLIN_LDISC 25
28 struct bcm_msg_head msg_head;
29 struct can_frame frame;
32 struct sllin_connection {
33 int bcm_sock; // FIXME is necessary??
35 char iface[IFNAMSIZ+1];
38 void sllin_ms_to_timeval(int ms, struct timeval *tv)
40 tv->tv_sec = (int) ms/1000;
41 tv->tv_usec = (ms % 1000) * 1000;
44 int sllin_interface_up(struct linc_lin_state *linc_lin_state,
45 struct sllin_connection *sllin_connection)
48 struct rtnl_link *request;
49 struct nl_cache *cache;
50 struct rtnl_link *link;
53 // Allocate and initialize a new netlink socket
54 s = nl_socket_alloc();
56 // Bind and connect the socket to a protocol, NETLINK_ROUTE in this example.
57 nl_connect(s, NETLINK_ROUTE);
59 // The first step is to retrieve a list of all available interfaces within
60 // the kernel and put them into a cache.
61 ret = rtnl_link_alloc_cache(s, AF_UNSPEC, &cache);
62 // FIXME errorhandling
64 // In a second step, a specific link may be looked up by either interface
65 // index or interface name.
66 link = rtnl_link_get_by_name(cache, sllin_connection->iface);
68 // In order to change any attributes of an existing link, we must allocate
69 // a new link to hold the change requests:
70 request = rtnl_link_alloc();
72 // We can also shut an interface down administratively
73 //rtnl_link_unset_flags(request, rtnl_link_str2flags("up"));
74 rtnl_link_set_flags(request, rtnl_link_str2flags("up"));
76 // Two ways exist to commit this change request, the first one is to
77 // build the required netlink message and send it out in one single
79 rtnl_link_change(s, link, request, 0);
81 // An alternative way is to build the netlink message and send it
82 // out yourself using nl_send_auto_complete()
83 // struct nl_msg *msg = rtnl_link_build_change_request(old, request);
84 // nl_send_auto_complete(nl_handle, nlmsg_hdr(msg));
87 // After successful usage, the object must be given back to the cache
94 int sllin_cache_config(struct linc_lin_state *linc_lin_state,
95 struct sllin_connection *sllin_connection)
99 struct sockaddr_can addr;
100 struct can_frame frame;
104 /* Create the socket */
105 s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
111 /* Locate the interface you wish to use */
112 strcpy(ifr.ifr_name, sllin_connection->iface);
113 ioctl(s, SIOCGIFINDEX, &ifr); /* ifr.ifr_ifindex gets filled
114 * with that device's index */
116 /* Select that CAN interface, and bind the socket to it. */
117 addr.can_family = AF_CAN;
118 addr.can_ifindex = ifr.ifr_ifindex;
119 ret = bind(s, (struct sockaddr*)&addr, sizeof(addr));
125 for (i = 0; i < 0x3F; i++) {
126 if (linc_lin_state->frame_entry[i].status == 1) { /* Is active */
127 frame.can_dlc = linc_lin_state->frame_entry[i].data_len;
128 frame.can_id = i; /* LIN ID */
129 frame.data[0] = linc_lin_state->frame_entry[i].data[0]; /* Data */
130 frame.data[1] = linc_lin_state->frame_entry[i].data[1]; /* Data */
131 frame.data[2] = linc_lin_state->frame_entry[i].data[2]; /* Data */
132 frame.data[3] = linc_lin_state->frame_entry[i].data[3]; /* Data */
133 frame.data[4] = linc_lin_state->frame_entry[i].data[4]; /* Data */
134 frame.data[5] = linc_lin_state->frame_entry[i].data[5]; /* Data */
135 frame.data[6] = linc_lin_state->frame_entry[i].data[6]; /* Data */
136 frame.data[7] = linc_lin_state->frame_entry[i].data[7]; /* Data */
138 frame.can_id |= LIN_CTRL_FRAME | LIN_CACHE_RESPONSE;
139 ret = write(s, &frame, sizeof(frame));
140 printf("configuring frame cache; ret = %d\n", ret);
142 //read_response(tty);
150 int sllin_bcm_config(struct linc_lin_state *linc_lin_state,
151 struct sllin_connection *sllin_connection)
153 struct sockaddr_can caddr;
160 s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
162 perror("socket(): bcmsocket");
166 strcpy(ifr.ifr_name, sllin_connection->iface);
167 ioctl(s, SIOCGIFINDEX, &ifr);
169 memset(&caddr, 0, sizeof(caddr));
170 caddr.can_family = AF_CAN;
171 caddr.can_ifindex = ifr.ifr_ifindex;
173 // ret = bind(s, (struct sockaddr*)&caddr, sizeof(caddr));
179 // sllin_connection->bcm_sock = s;
181 ret = connect(s, (struct sockaddr *)&caddr, sizeof(caddr));
187 for (i = 0; i < linc_lin_state->scheduler_entries_cnt; i++) {
189 memset(&msg, 0, sizeof(msg));
191 msg.msg_head.nframes = 1;
192 msg.msg_head.opcode = TX_SETUP;
193 msg.msg_head.flags |= SETTIMER | STARTTIMER;
195 linc_lin_state->scheduler_entry[i].interval_ms, &time);
196 msg.msg_head.ival2.tv_sec = time.tv_sec;
197 msg.msg_head.ival2.tv_usec = time.tv_usec;
198 msg.msg_head.can_id = (
199 linc_lin_state->scheduler_entry[i].lin_id | CAN_RTR_FLAG);
200 msg.frame.can_dlc = 0;
201 msg.frame.can_id = msg.msg_head.can_id;
203 //printf("tv_sec = %i, tv_usec = %i\n", time.tv_sec, time.tv_usec);
205 sendto(s, &msg, sizeof(msg), 0,
206 (struct sockaddr*)&caddr, sizeof(caddr));
207 //read_response(s); // FIXME
210 /* Do not close "s" to make BCM configuration running */
212 printf("Configuration finished\n");
216 int sllin_config(struct linc_lin_state *linc_lin_state)
219 int ldisc = SLLIN_LDISC;
221 struct sllin_connection sllin_connection;
223 tty = open(linc_lin_state->dev, O_WRONLY | O_NOCTTY);
229 /* Set sllin line discipline on given tty */
230 if (linc_lin_state->flags & SLLIN_ATTACH_fl) {
231 ret = ioctl(tty, TIOCSETD, &ldisc);
233 perror("ioctl TIOCSETD");
237 /* Retrieve the name of the created CAN netdevice */
238 ret = ioctl(tty, SIOCGIFNAME, sllin_connection.iface);
240 perror("ioctl SIOCGIFNAME");
244 printf("Attached tty %s to netdevice %s\n",
245 linc_lin_state->dev, sllin_connection.iface);
248 if (linc_lin_state->flags & SLLIN_DETACH_fl) {
250 ret = ioctl(tty, TIOCSETD, &ldisc);
256 printf("Detached sllin line discipline from %s\n",
257 linc_lin_state->dev);
263 ret = sllin_bcm_config(linc_lin_state, &sllin_connection);
267 ret = sllin_interface_up(linc_lin_state, &sllin_connection);
271 ret = sllin_cache_config(linc_lin_state, &sllin_connection);
273 /* !!! Do not close "tty" to enable newly
274 configured tty line discipline */