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