Base Code merged to SPIN 2.4
[platform/upstream/connman.git] / plugins / tist.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2012  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #define _GNU_SOURCE
27 #include <stdio.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <stdint.h>
35 #include <sys/ioctl.h>
36 #include <termios.h>
37 #include <unistd.h>
38
39 #include <gdbus.h>
40
41 #define CONNMAN_API_SUBJECT_TO_CHANGE
42 #include <connman/plugin.h>
43 #include <connman/log.h>
44
45 #define TIST_SYSFS_INSTALL "/sys/devices/platform/kim/install"
46 #define TIST_SYSFS_UART "/sys/devices/platform/kim/dev_name"
47 #define TIST_SYSFS_BAUD "/sys/devices/platform/kim/baud_rate"
48
49 /* Shared transport line discipline */
50 #define N_TI_WL 22
51
52 static GIOChannel *install_channel = NULL;
53 static GIOChannel *uart_channel = NULL;
54 static char uart_dev_name[32];
55 static unsigned long baud_rate = 0;
56
57 static guint install_watch = 0;
58 static guint uart_watch = 0;
59
60 static int install_count = 0;
61
62 #define NCCS2 19
63 struct termios2 {
64         tcflag_t c_iflag;               /* input mode flags */
65         tcflag_t c_oflag;               /* output mode flags */
66         tcflag_t c_cflag;               /* control mode flags */
67         tcflag_t c_lflag;               /* local mode flags */
68         cc_t c_line;                    /* line discipline */
69         cc_t c_cc[NCCS2];               /* control characters */
70         speed_t c_ispeed;               /* input speed */
71         speed_t c_ospeed;               /* output speed */
72 };
73
74 #define  BOTHER         0x00001000
75
76 /* HCI definitions */
77 #define HCI_HDR_OPCODE          0xff36
78 #define HCI_COMMAND_PKT         0x01
79 #define HCI_EVENT_PKT           0x04
80 #define EVT_CMD_COMPLETE        0x0E
81
82 /* HCI Command structure to set the target baud rate */
83 struct speed_change_cmd {
84         uint8_t uart_prefix;
85         uint16_t opcode;
86         uint8_t plen;
87         uint32_t speed;
88 } __attribute__ ((packed));
89
90 /* HCI Event structure to set the cusrom baud rate*/
91 struct cmd_complete {
92         uint8_t uart_prefix;
93         uint8_t evt;
94         uint8_t plen;
95         uint8_t ncmd;
96         uint16_t opcode;
97         uint8_t status;
98         uint8_t data[16];
99 } __attribute__ ((packed));
100
101 static int read_baud_rate(unsigned long *baud)
102 {
103         int err;
104         FILE *f;
105
106         DBG("");
107
108         f = fopen(TIST_SYSFS_BAUD, "r");
109         if (!f)
110                 return -EIO;
111
112         err = fscanf(f, "%lu", baud);
113         fclose(f);
114
115         DBG("baud rate %lu", *baud);
116
117         return err;
118 }
119
120 static int read_uart_name(char uart_name[], size_t uart_name_len)
121 {
122         int err;
123         FILE *f;
124
125         DBG("");
126
127         memset(uart_name, 0, uart_name_len);
128
129         f = fopen(TIST_SYSFS_UART, "r");
130         if (!f)
131                 return -EIO;
132
133         err = fscanf(f, "%s", uart_name);
134         fclose(f);
135
136         DBG("UART name %s", uart_name);
137
138         return err;
139 }
140
141 static int read_hci_event(int fd, unsigned char *buf, int size)
142 {
143         int prefix_len, param_len;
144
145         if (size <= 0)
146                 return -EINVAL;
147
148         /* First 3 bytes are prefix, event and param length */
149         prefix_len = read(fd, buf, 3);
150         if (prefix_len < 0)
151                 return prefix_len;
152
153         if (prefix_len < 3) {
154                 connman_error("Truncated HCI prefix %d bytes 0x%x",
155                                                 prefix_len, buf[0]);
156                 return -EIO;
157         }
158
159         DBG("type 0x%x event 0x%x param len %d", buf[0], buf[1], buf[2]);
160
161         param_len = buf[2];
162         if (param_len > size - 3) {
163                 connman_error("Buffer is too small %d", size);
164                 return -EINVAL;
165         }
166
167         return read(fd, buf + 3, param_len);
168 }
169
170 static int read_command_complete(int fd, unsigned short opcode)
171 {
172         struct cmd_complete resp;
173         int err;
174
175         DBG("");
176
177         err = read_hci_event(fd, (unsigned char *)&resp, sizeof(resp));
178         if (err < 0)
179                 return err;
180
181         DBG("HCI event %d bytes", err);
182
183         if (resp.uart_prefix != HCI_EVENT_PKT) {
184                 connman_error("Not an event packet");
185                 return -EIO;
186         }
187
188         if (resp.evt != EVT_CMD_COMPLETE) {
189                 connman_error("Not a cmd complete event");
190                 return -EIO;
191         }
192
193         if (resp.plen < 4) {
194                 connman_error("HCI header length %d", resp.plen);
195                 return -EIO;
196         }
197
198         if (resp.opcode != (unsigned short) opcode) {
199                 connman_error("opcode 0x%04x 0x%04x", resp.opcode, opcode);
200                 return -EIO;
201         }
202
203         return 0;
204 }
205
206 /* The default baud rate is 115200 */
207 static int set_default_baud_rate(int fd)
208 {
209         struct termios ti;
210         int err;
211
212         DBG("");
213
214         err = tcflush(fd, TCIOFLUSH);
215         if (err < 0)
216                 goto err;
217
218         err = tcgetattr(fd, &ti);
219         if (err < 0)
220                 goto err;
221
222         cfmakeraw(&ti);
223
224         ti.c_cflag |= 1;
225         ti.c_cflag |= CRTSCTS;
226
227         err = tcsetattr(fd, TCSANOW, &ti);
228         if (err < 0)
229                 goto err;
230
231         cfsetospeed(&ti, B115200);
232         cfsetispeed(&ti, B115200);
233
234         err = tcsetattr(fd, TCSANOW, &ti);
235         if (err < 0)
236                 goto err;
237
238         err = tcflush(fd, TCIOFLUSH);
239         if (err < 0)
240                 goto err;
241
242         return 0;
243
244 err:
245         connman_error("%s", strerror(errno));
246
247         return err;
248 }
249
250 static int set_custom_baud_rate(int fd, unsigned long cus_baud_rate, int flow_ctrl)
251 {
252         struct termios ti;
253         struct termios2 ti2;
254         int err;
255
256         DBG("baud rate %lu flow_ctrl %d", cus_baud_rate, flow_ctrl);
257
258         err = tcflush(fd, TCIOFLUSH);
259         if (err < 0)
260                 goto err;
261
262         err = tcgetattr(fd, &ti);
263         if (err < 0)
264                 goto err;
265
266         if (flow_ctrl)
267                 ti.c_cflag |= CRTSCTS;
268         else
269                 ti.c_cflag &= ~CRTSCTS;
270
271         /*
272          * Set the parameters associated with the UART
273          * The change will occur immediately by using TCSANOW.
274          */
275         err = tcsetattr(fd, TCSANOW, &ti);
276         if (err < 0)
277                 goto err;
278
279         err = tcflush(fd, TCIOFLUSH);
280         if (err < 0)
281                 goto err;
282
283         /* Set the actual baud rate */
284         err = ioctl(fd, TCGETS2, &ti2);
285         if (err < 0)
286                 goto err;
287
288         ti2.c_cflag &= ~CBAUD;
289         ti2.c_cflag |= BOTHER;
290         ti2.c_ospeed = cus_baud_rate;
291
292         err = ioctl(fd, TCSETS2, &ti2);
293         if (err < 0)
294                 goto err;
295
296         return 0;
297
298 err:
299         DBG("%s", strerror(errno));
300
301         return err;
302 }
303
304 static gboolean uart_event(GIOChannel *channel,
305                                 GIOCondition cond, gpointer data)
306 {
307         int uart_fd, ldisc;
308
309         DBG("");
310
311         uart_fd = g_io_channel_unix_get_fd(channel);
312
313         if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
314                 connman_error("UART event 0x%x", cond);
315                 if (uart_watch > 0)
316                         g_source_remove(uart_watch);
317
318                 goto err;
319         }
320
321         if (read_command_complete(uart_fd, HCI_HDR_OPCODE) < 0)
322                 goto err;
323
324         if (set_custom_baud_rate(uart_fd, baud_rate, 1) < 0)
325                 goto err;
326
327         ldisc = N_TI_WL;
328         if (ioctl(uart_fd, TIOCSETD, &ldisc) < 0)
329                 goto err;
330
331         install_count = 1;
332         __sync_synchronize();
333
334         return FALSE;
335
336 err:
337         install_count = 0;
338         __sync_synchronize();
339
340         g_io_channel_shutdown(channel, TRUE, NULL);
341         g_io_channel_unref(channel);
342
343         return FALSE;
344 }
345
346 static int install_ldisc(GIOChannel *channel, bool install)
347 {
348         int uart_fd, err;
349         struct speed_change_cmd cmd;
350         GIOFlags flags;
351
352         DBG("%d %p", install, uart_channel);
353
354         if (!install) {
355                 install_count = 0;
356                 __sync_synchronize();
357
358                 if (!uart_channel) {
359                         DBG("UART channel is NULL");
360                         return 0;
361                 }
362
363                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
364                 g_io_channel_unref(uart_channel);
365
366                 uart_channel = NULL;
367
368                 return 0;
369         }
370
371         if (uart_channel) {
372                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
373                 g_io_channel_unref(uart_channel);
374                 uart_channel = NULL;
375         }
376
377         DBG("opening %s custom baud %lu", uart_dev_name, baud_rate);
378
379         uart_fd = open(uart_dev_name, O_RDWR | O_CLOEXEC);
380         if (uart_fd < 0)
381                 return -EIO;
382
383         uart_channel = g_io_channel_unix_new(uart_fd);
384         g_io_channel_set_close_on_unref(uart_channel, TRUE);
385
386         g_io_channel_set_encoding(uart_channel, NULL, NULL);
387         g_io_channel_set_buffered(uart_channel, FALSE);
388
389         flags = g_io_channel_get_flags(uart_channel);
390         flags |= G_IO_FLAG_NONBLOCK;
391         g_io_channel_set_flags(uart_channel, flags, NULL);
392
393         err = set_default_baud_rate(uart_fd);
394         if (err < 0) {
395                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
396                 g_io_channel_unref(uart_channel);
397                 uart_channel = NULL;
398
399                 return err;
400         }
401
402         if (baud_rate == 115200) {
403                 int ldisc;
404
405                 ldisc = N_TI_WL;
406                 if (ioctl(uart_fd, TIOCSETD, &ldisc) < 0) {
407                         g_io_channel_shutdown(uart_channel, TRUE, NULL);
408                         g_io_channel_unref(uart_channel);
409                         uart_channel = NULL;
410                 }
411
412                 install_count = 0;
413                 __sync_synchronize();
414
415                 return 0;
416         }
417
418         cmd.uart_prefix = HCI_COMMAND_PKT;
419         cmd.opcode = HCI_HDR_OPCODE;
420         cmd.plen = sizeof(unsigned long);
421         cmd.speed = baud_rate;
422
423         uart_watch = g_io_add_watch(uart_channel,
424                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
425                                 uart_event, NULL);
426
427         err = write(uart_fd, &cmd, sizeof(cmd));
428         if (err < 0) {
429                 connman_error("Write failed %d", err);
430
431                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
432                 g_io_channel_unref(uart_channel);
433                 uart_channel = NULL;
434         }
435
436         return err;
437 }
438
439
440 static gboolean install_event(GIOChannel *channel,
441                                 GIOCondition cond, gpointer data)
442 {
443         GIOStatus status = G_IO_STATUS_NORMAL;
444         unsigned int install_state;
445         bool install;
446         char buf[8];
447         gsize len;
448
449         DBG("");
450
451         if (cond & (G_IO_HUP | G_IO_NVAL)) {
452                 connman_error("install event 0x%x", cond);
453                 return FALSE;
454         }
455
456         __sync_synchronize();
457         if (install_count != 0) {
458                 status = g_io_channel_seek_position(channel, 0, G_SEEK_SET, NULL);
459                 if (status != G_IO_STATUS_NORMAL) {
460                         g_io_channel_shutdown(channel, TRUE, NULL);
461                         g_io_channel_unref(channel);
462                         return FALSE;
463                 }
464
465                 /* Read the install value */
466                 status = g_io_channel_read_chars(channel, (gchar *) buf,
467                                                 8, &len, NULL);
468                 if (status != G_IO_STATUS_NORMAL) {
469                         g_io_channel_shutdown(channel, TRUE, NULL);
470                         g_io_channel_unref(channel);
471                         return FALSE;
472                 }
473
474                 install_state = atoi(buf);
475                 DBG("install event while installing %d %c", install_state, buf[0]);
476
477                 return TRUE;
478         } else {
479                 install_count = 1;
480                 __sync_synchronize();
481         }
482
483         status = g_io_channel_seek_position(channel, 0, G_SEEK_SET, NULL);
484         if (status != G_IO_STATUS_NORMAL) {
485                 g_io_channel_shutdown(channel, TRUE, NULL);
486                 g_io_channel_unref(channel);
487                 return FALSE;
488         }
489
490         /* Read the install value */
491         status = g_io_channel_read_chars(channel, (gchar *) buf, 8, &len, NULL);
492         if (status != G_IO_STATUS_NORMAL) {
493                 g_io_channel_shutdown(channel, TRUE, NULL);
494                 g_io_channel_unref(channel);
495                 return FALSE;
496         }
497
498         install_state = atoi(buf);
499
500         DBG("install state %d", install_state);
501
502         install = !!install_state;
503
504         if (install_ldisc(channel, install) < 0) {
505                 connman_error("ldisc installation failed");
506                 install_count = 0;
507                 __sync_synchronize();
508                 return TRUE;
509         }
510
511         return TRUE;
512 }
513
514
515 static int tist_init(void)
516 {
517         GIOStatus status = G_IO_STATUS_NORMAL;
518         GIOFlags flags;
519         unsigned int install_state;
520         char buf[8];
521         int fd, err;
522         gsize len;
523
524         err = read_uart_name(uart_dev_name, sizeof(uart_dev_name));
525         if (err < 0) {
526                 connman_error("Could not read the UART name");
527                 return err;
528         }
529
530         err = read_baud_rate(&baud_rate);
531         if (err < 0) {
532                 connman_error("Could not read the baud rate");
533                 return err;
534         }
535
536         fd = open(TIST_SYSFS_INSTALL, O_RDONLY | O_CLOEXEC);
537         if (fd < 0) {
538                 connman_error("Failed to open TI ST sysfs install file");
539                 return -EIO;
540         }
541
542         install_channel = g_io_channel_unix_new(fd);
543         g_io_channel_set_close_on_unref(install_channel, TRUE);
544
545         g_io_channel_set_encoding(install_channel, NULL, NULL);
546         g_io_channel_set_buffered(install_channel, FALSE);
547
548         flags = g_io_channel_get_flags(install_channel);
549         flags |= G_IO_FLAG_NONBLOCK;
550         g_io_channel_set_flags(install_channel, flags, NULL);
551
552         status = g_io_channel_read_chars(install_channel, (gchar *) buf, 8,
553                                                                 &len, NULL);
554         if (status != G_IO_STATUS_NORMAL) {
555                 g_io_channel_shutdown(install_channel, TRUE, NULL);
556                 g_io_channel_unref(install_channel);
557                 return status;
558         }
559
560         status = g_io_channel_seek_position(install_channel, 0, G_SEEK_SET, NULL);
561         if (status != G_IO_STATUS_NORMAL) {
562                 connman_error("Initial seek failed");
563                 g_io_channel_shutdown(install_channel, TRUE, NULL);
564                 g_io_channel_unref(install_channel);
565                 return -EIO;
566         }
567
568         install_state = atoi(buf);
569
570         DBG("Initial state %d", install_state);
571
572         install_watch = g_io_add_watch_full(install_channel, G_PRIORITY_HIGH,
573                                 G_IO_PRI | G_IO_ERR,
574                                             install_event, NULL, NULL);
575
576         if (install_state) {
577                 install_count = 1;
578                 __sync_synchronize();
579
580                 err = install_ldisc(install_channel, true);
581                 if (err < 0) {
582                         connman_error("ldisc installtion failed");
583                         return err;
584                 }
585         }
586
587         return 0;
588 }
589
590
591 static void tist_exit(void)
592 {
593
594         if (install_watch > 0)
595                 g_source_remove(install_watch);
596
597         DBG("uart_channel %p", uart_channel);
598
599         g_io_channel_shutdown(install_channel, TRUE, NULL);
600         g_io_channel_unref(install_channel);
601
602         if (uart_channel) {
603                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
604                 g_io_channel_unref(uart_channel);
605                 uart_channel = NULL;
606         }
607
608 }
609
610 CONNMAN_PLUGIN_DEFINE(tist, "TI shared transport support", VERSION,
611                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, tist_init, tist_exit)