plugins: Fix compilation in MeeGo
[framework/connectivity/connman.git] / plugins / tist.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2011  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 <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 gint 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 == NULL)
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 == NULL)
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         g_atomic_int_set(&install_count, 0);
331
332         return FALSE;
333
334 err:
335         g_atomic_int_set(&install_count, 0);
336         g_io_channel_shutdown(channel, TRUE, NULL);
337         g_io_channel_unref(channel);
338
339         return FALSE;
340 }
341
342 static int install_ldisc(GIOChannel *channel, gboolean install)
343 {
344         int uart_fd, err;
345         struct speed_change_cmd cmd;
346         GIOFlags flags;
347
348         DBG("%d %p", install, uart_channel);
349
350         if (install == FALSE) {
351                 g_atomic_int_set(&install_count, 0);
352
353                 if (uart_channel == NULL) {
354                         DBG("UART channel is NULL");
355                         return 0;
356                 }
357
358                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
359                 g_io_channel_unref(uart_channel);
360
361                 uart_channel = NULL;
362
363                 return 0;
364         }
365
366         if (uart_channel != NULL) {
367                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
368                 g_io_channel_unref(uart_channel);
369                 uart_channel = NULL;
370         }
371
372         DBG("opening %s custom baud %lu", uart_dev_name, baud_rate);
373         
374         uart_fd = open(uart_dev_name, O_RDWR | O_CLOEXEC);
375         if (uart_fd < 0)
376                 return -EIO;
377
378         uart_channel = g_io_channel_unix_new(uart_fd);  
379         g_io_channel_set_close_on_unref(uart_channel, TRUE);
380
381         g_io_channel_set_encoding(uart_channel, NULL, NULL);
382         g_io_channel_set_buffered(uart_channel, FALSE);
383
384         flags = g_io_channel_get_flags(uart_channel);
385         flags |= G_IO_FLAG_NONBLOCK;
386         g_io_channel_set_flags(uart_channel, flags, NULL);
387
388         err = set_default_baud_rate(uart_fd);
389         if (err < 0) {
390                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
391                 g_io_channel_unref(uart_channel);
392                 uart_channel = NULL;
393
394                 return err;
395         }
396
397         if (baud_rate == 115200) {
398                 int ldisc;
399
400                 ldisc = N_TI_WL;
401                 if (ioctl(uart_fd, TIOCSETD, &ldisc) < 0) {
402                         g_io_channel_shutdown(uart_channel, TRUE, NULL);
403                         g_io_channel_unref(uart_channel);
404                         uart_channel = NULL;
405                 }
406
407                 g_atomic_int_set(&install_count, 0);
408
409                 return 0;
410         }
411
412         cmd.uart_prefix = HCI_COMMAND_PKT;
413         cmd.opcode = HCI_HDR_OPCODE;
414         cmd.plen = sizeof(unsigned long);
415         cmd.speed = baud_rate;
416
417         uart_watch = g_io_add_watch(uart_channel,
418                         G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
419                                 uart_event, NULL);
420
421         err = write(uart_fd, &cmd, sizeof(cmd));
422         if (err < 0) {
423                 connman_error("Write failed %d", err);
424
425                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
426                 g_io_channel_unref(uart_channel);
427                 uart_channel = NULL;
428         }
429
430         return err;
431 }
432
433
434 static gboolean install_event(GIOChannel *channel,
435                                 GIOCondition cond, gpointer data)
436 {
437         GIOStatus status = G_IO_STATUS_NORMAL;
438         unsigned int install_state;
439         gboolean install;
440         char buf[8];
441         gsize len;
442
443         DBG("");
444
445         if (cond & (G_IO_HUP | G_IO_NVAL)) {
446                 connman_error("install event 0x%x", cond);
447                 return FALSE;
448         }
449
450         if (g_atomic_int_get(&install_count) != 0) {
451                 status = g_io_channel_seek_position(channel, 0, G_SEEK_SET, NULL);
452                 if (status != G_IO_STATUS_NORMAL) {
453                         g_io_channel_shutdown(channel, TRUE, NULL);
454                         g_io_channel_unref(channel);
455                         return FALSE;
456                 }
457
458                 /* Read the install value */
459                 status = g_io_channel_read_chars(channel, (gchar *) buf, 8, &len, NULL);
460                 if (status != G_IO_STATUS_NORMAL) {
461                         g_io_channel_shutdown(channel, TRUE, NULL);
462                         g_io_channel_unref(channel);
463                         return FALSE;
464                 }
465
466                 install_state = atoi(buf);
467                 DBG("install event while installing %d %c", install_state, buf[0]);
468
469                 return TRUE;
470         } else {
471                 g_atomic_int_set(&install_count, 1);
472         }
473
474         status = g_io_channel_seek_position(channel, 0, G_SEEK_SET, NULL);
475         if (status != G_IO_STATUS_NORMAL) {
476                 g_io_channel_shutdown(channel, TRUE, NULL);
477                 g_io_channel_unref(channel);
478                 return FALSE;
479         }
480
481         /* Read the install value */
482         status = g_io_channel_read_chars(channel, (gchar *) buf, 8, &len, 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         install_state = atoi(buf);
490
491         DBG("install state %d", install_state);
492
493         install = !!install_state;
494
495         if (install_ldisc(channel, install) < 0) {
496                 connman_error("ldisc installation failed");
497                 g_atomic_int_set(&install_count, 0);
498                 return TRUE;
499         }
500
501         return TRUE;
502 }
503
504
505 static int tist_init(void)
506 {
507         GIOStatus status = G_IO_STATUS_NORMAL;
508         GIOFlags flags;
509         unsigned int install_state;
510         char buf[8];
511         int fd, err;
512         gsize len;
513
514         err = read_uart_name(uart_dev_name, sizeof(uart_dev_name));
515         if (err < 0) {
516                 connman_error("Could not read the UART name");
517                 return err;
518         }
519
520         err = read_baud_rate(&baud_rate);
521         if (err < 0) {
522                 connman_error("Could not read the baud rate");
523                 return err;
524         }
525
526         fd = open(TIST_SYSFS_INSTALL, O_RDONLY | O_CLOEXEC);
527         if (fd < 0) {
528                 connman_error("Failed to open TI ST sysfs install file");
529                 return -EIO;
530         }
531
532         install_channel = g_io_channel_unix_new(fd);
533         g_io_channel_set_close_on_unref(install_channel, TRUE);
534
535         g_io_channel_set_encoding(install_channel, NULL, NULL);
536         g_io_channel_set_buffered(install_channel, FALSE);
537
538         flags = g_io_channel_get_flags(install_channel);
539         flags |= G_IO_FLAG_NONBLOCK;
540         g_io_channel_set_flags(install_channel, flags, NULL);
541
542         status = g_io_channel_read_chars(install_channel, (gchar *) buf, 8,
543                                                                 &len, NULL);
544         if (status != G_IO_STATUS_NORMAL) {
545                 g_io_channel_shutdown(install_channel, TRUE, NULL);
546                 g_io_channel_unref(install_channel);
547                 return status;
548         }
549
550         status = g_io_channel_seek_position(install_channel, 0, G_SEEK_SET, NULL);
551         if (status != G_IO_STATUS_NORMAL) {
552                 connman_error("Initial seek failed");
553                 g_io_channel_shutdown(install_channel, TRUE, NULL);
554                 g_io_channel_unref(install_channel);
555                 return -EIO;
556         }
557
558         install_state = atoi(buf);
559
560         DBG("Initial state %d", install_state);
561
562         install_watch = g_io_add_watch_full(install_channel, G_PRIORITY_HIGH,
563                                 G_IO_PRI | G_IO_ERR,
564                                             install_event, NULL, NULL);
565
566         if (install_state) {
567                 g_atomic_int_set(&install_count, 1);
568                 err = install_ldisc(install_channel, TRUE);
569                 if (err < 0) {
570                         connman_error("ldisc installtion failed");
571                         return err;
572                 }
573         }
574
575         return 0;
576 }
577
578
579 static void tist_exit(void)
580 {
581
582         if (install_watch > 0)
583                 g_source_remove(install_watch);
584
585         DBG("uart_channel %p", uart_channel);
586
587         g_io_channel_shutdown(install_channel, TRUE, NULL);
588         g_io_channel_unref(install_channel);
589
590         if (uart_channel != NULL) {
591                 g_io_channel_shutdown(uart_channel, TRUE, NULL);
592                 g_io_channel_unref(uart_channel);
593                 uart_channel = NULL;
594         }
595
596 }
597
598 CONNMAN_PLUGIN_DEFINE(tist, "TI shared transport support", VERSION,
599                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, tist_init, tist_exit)