5 * Copyright (C) 2011 Intel Corporation. All rights reserved.
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.
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.
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
33 #include <sys/ioctl.h>
39 #define CONNMAN_API_SUBJECT_TO_CHANGE
40 #include <connman/plugin.h>
41 #include <connman/log.h>
43 #define TIST_SYSFS_INSTALL "/sys/devices/platform/kim/install"
44 #define TIST_SYSFS_UART "/sys/devices/platform/kim/dev_name"
45 #define TIST_SYSFS_BAUD "/sys/devices/platform/kim/baud_rate"
47 /* Shared transport line discipline */
50 static GIOChannel *install_channel = NULL;
51 static GIOChannel *uart_channel = NULL;
52 static char uart_dev_name[32];
53 static unsigned long baud_rate = 0;
55 static guint install_watch = 0;
56 static guint uart_watch = 0;
58 static gint install_count = 0;
62 tcflag_t c_iflag; /* input mode flags */
63 tcflag_t c_oflag; /* output mode flags */
64 tcflag_t c_cflag; /* control mode flags */
65 tcflag_t c_lflag; /* local mode flags */
66 cc_t c_line; /* line discipline */
67 cc_t c_cc[NCCS2]; /* control characters */
68 speed_t c_ispeed; /* input speed */
69 speed_t c_ospeed; /* output speed */
72 #define BOTHER 0x00001000
75 #define HCI_HDR_OPCODE 0xff36
76 #define HCI_COMMAND_PKT 0x01
77 #define HCI_EVENT_PKT 0x04
78 #define EVT_CMD_COMPLETE 0x0E
80 /* HCI Command structure to set the target baud rate */
81 struct speed_change_cmd {
86 } __attribute__ ((packed));
88 /* HCI Event structure to set the cusrom baud rate*/
97 } __attribute__ ((packed));
99 static int read_baud_rate(unsigned long *baud)
106 f = fopen(TIST_SYSFS_BAUD, "r");
110 err = fscanf(f, "%lu", baud);
113 DBG("baud rate %lu", *baud);
118 static int read_uart_name(char uart_name[], size_t uart_name_len)
125 memset(uart_name, 0, uart_name_len);
127 f = fopen(TIST_SYSFS_UART, "r");
131 err = fscanf(f, "%s", uart_name);
134 DBG("UART name %s", uart_name);
139 static int read_hci_event(int fd, unsigned char *buf, int size)
141 int prefix_len, param_len;
146 /* First 3 bytes are prefix, event and param length */
147 prefix_len = read(fd, buf, 3);
151 if (prefix_len < 3) {
152 connman_error("Truncated HCI prefix %d bytes 0x%x",
157 DBG("type 0x%x event 0x%x param len %d", buf[0], buf[1], buf[2]);
160 if (param_len > size - 3) {
161 connman_error("Buffer is too small %d", size);
165 return read(fd, buf + 3, param_len);
168 static int read_command_complete(int fd, unsigned short opcode)
170 struct cmd_complete resp;
175 err = read_hci_event(fd, (unsigned char *)&resp, sizeof(resp));
179 DBG("HCI event %d bytes", err);
181 if (resp.uart_prefix != HCI_EVENT_PKT) {
182 connman_error("Not an event packet");
186 if (resp.evt != EVT_CMD_COMPLETE) {
187 connman_error("Not a cmd complete event");
192 connman_error("HCI header length %d", resp.plen);
196 if (resp.opcode != (unsigned short) opcode) {
197 connman_error("opcode 0x%04x 0x%04x", resp.opcode, opcode);
204 /* The default baud rate is 115200 */
205 static int set_default_baud_rate(int fd)
212 err = tcflush(fd, TCIOFLUSH);
216 err = tcgetattr(fd, &ti);
223 ti.c_cflag |= CRTSCTS;
225 err = tcsetattr(fd, TCSANOW, &ti);
229 cfsetospeed(&ti, B115200);
230 cfsetispeed(&ti, B115200);
232 err = tcsetattr(fd, TCSANOW, &ti);
236 err = tcflush(fd, TCIOFLUSH);
243 connman_error("%s", strerror(errno));
248 static int set_custom_baud_rate(int fd, unsigned long cus_baud_rate, int flow_ctrl)
254 DBG("baud rate %lu flow_ctrl %d", cus_baud_rate, flow_ctrl);
256 err = tcflush(fd, TCIOFLUSH);
260 err = tcgetattr(fd, &ti);
265 ti.c_cflag |= CRTSCTS;
267 ti.c_cflag &= ~CRTSCTS;
270 * Set the parameters associated with the UART
271 * The change will occur immediately by using TCSANOW.
273 err = tcsetattr(fd, TCSANOW, &ti);
277 err = tcflush(fd, TCIOFLUSH);
281 /* Set the actual baud rate */
282 err = ioctl(fd, TCGETS2, &ti2);
286 ti2.c_cflag &= ~CBAUD;
287 ti2.c_cflag |= BOTHER;
288 ti2.c_ospeed = cus_baud_rate;
290 err = ioctl(fd, TCSETS2, &ti2);
297 DBG("%s", strerror(errno));
302 static gboolean uart_event(GIOChannel *channel,
303 GIOCondition cond, gpointer data)
309 uart_fd = g_io_channel_unix_get_fd(channel);
311 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
312 connman_error("UART event 0x%x", cond);
314 g_source_remove(uart_watch);
319 if (read_command_complete(uart_fd, HCI_HDR_OPCODE) < 0)
322 if (set_custom_baud_rate(uart_fd, baud_rate, 1) < 0)
326 if (ioctl(uart_fd, TIOCSETD, &ldisc) < 0)
329 g_atomic_int_set(&install_count, 0);
334 g_atomic_int_set(&install_count, 0);
335 g_io_channel_shutdown(channel, TRUE, NULL);
336 g_io_channel_unref(channel);
341 static int install_ldisc(GIOChannel *channel, gboolean install)
344 struct speed_change_cmd cmd;
347 DBG("%d %p", install, uart_channel);
349 if (install == FALSE) {
350 g_atomic_int_set(&install_count, 0);
352 if (uart_channel == NULL) {
353 DBG("UART channel is NULL");
357 g_io_channel_shutdown(uart_channel, TRUE, NULL);
358 g_io_channel_unref(uart_channel);
365 if (uart_channel != NULL) {
366 g_io_channel_shutdown(uart_channel, TRUE, NULL);
367 g_io_channel_unref(uart_channel);
371 DBG("opening %s custom baud %lu", uart_dev_name, baud_rate);
373 uart_fd = open(uart_dev_name, O_RDWR | O_CLOEXEC);
377 uart_channel = g_io_channel_unix_new(uart_fd);
378 g_io_channel_set_close_on_unref(uart_channel, TRUE);
380 g_io_channel_set_encoding(uart_channel, NULL, NULL);
381 g_io_channel_set_buffered(uart_channel, FALSE);
383 flags = g_io_channel_get_flags(uart_channel);
384 flags |= G_IO_FLAG_NONBLOCK;
385 g_io_channel_set_flags(uart_channel, flags, NULL);
387 err = set_default_baud_rate(uart_fd);
389 g_io_channel_shutdown(uart_channel, TRUE, NULL);
390 g_io_channel_unref(uart_channel);
396 if (baud_rate == 115200) {
400 if (ioctl(uart_fd, TIOCSETD, &ldisc) < 0) {
401 g_io_channel_shutdown(uart_channel, TRUE, NULL);
402 g_io_channel_unref(uart_channel);
406 g_atomic_int_set(&install_count, 0);
411 cmd.uart_prefix = HCI_COMMAND_PKT;
412 cmd.opcode = HCI_HDR_OPCODE;
413 cmd.plen = sizeof(unsigned long);
414 cmd.speed = baud_rate;
416 uart_watch = g_io_add_watch(uart_channel,
417 G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
420 err = write(uart_fd, &cmd, sizeof(cmd));
422 connman_error("Write failed %d", err);
424 g_io_channel_shutdown(uart_channel, TRUE, NULL);
425 g_io_channel_unref(uart_channel);
433 static gboolean install_event(GIOChannel *channel,
434 GIOCondition cond, gpointer data)
436 GIOStatus status = G_IO_STATUS_NORMAL;
437 unsigned int install_state;
444 if (cond & (G_IO_HUP | G_IO_NVAL)) {
445 connman_error("install event 0x%x", cond);
449 if (g_atomic_int_get(&install_count) != 0) {
450 status = g_io_channel_seek_position(channel, 0, G_SEEK_SET, NULL);
451 if (status != G_IO_STATUS_NORMAL) {
452 g_io_channel_shutdown(channel, TRUE, NULL);
453 g_io_channel_unref(channel);
457 /* Read the install value */
458 status = g_io_channel_read_chars(channel, (gchar *) buf, 8, &len, NULL);
459 if (status != G_IO_STATUS_NORMAL) {
460 g_io_channel_shutdown(channel, TRUE, NULL);
461 g_io_channel_unref(channel);
465 install_state = atoi(buf);
466 DBG("install event while installing %d %c", install_state, buf[0]);
470 g_atomic_int_set(&install_count, 1);
473 status = g_io_channel_seek_position(channel, 0, G_SEEK_SET, NULL);
474 if (status != G_IO_STATUS_NORMAL) {
475 g_io_channel_shutdown(channel, TRUE, NULL);
476 g_io_channel_unref(channel);
480 /* Read the install value */
481 status = g_io_channel_read_chars(channel, (gchar *) buf, 8, &len, NULL);
482 if (status != G_IO_STATUS_NORMAL) {
483 g_io_channel_shutdown(channel, TRUE, NULL);
484 g_io_channel_unref(channel);
488 install_state = atoi(buf);
490 DBG("install state %d", install_state);
492 install = !!install_state;
494 if (install_ldisc(channel, install) < 0) {
495 connman_error("ldisc installation failed");
496 g_atomic_int_set(&install_count, 0);
504 static int tist_init(void)
506 GIOStatus status = G_IO_STATUS_NORMAL;
508 unsigned int install_state;
513 err = read_uart_name(uart_dev_name, sizeof(uart_dev_name));
515 connman_error("Could not read the UART name");
519 err = read_baud_rate(&baud_rate);
521 connman_error("Could not read the baud rate");
525 fd = open(TIST_SYSFS_INSTALL, O_RDONLY | O_CLOEXEC);
527 connman_error("Failed to open TI ST sysfs install file");
531 install_channel = g_io_channel_unix_new(fd);
532 g_io_channel_set_close_on_unref(install_channel, TRUE);
534 g_io_channel_set_encoding(install_channel, NULL, NULL);
535 g_io_channel_set_buffered(install_channel, FALSE);
537 flags = g_io_channel_get_flags(install_channel);
538 flags |= G_IO_FLAG_NONBLOCK;
539 g_io_channel_set_flags(install_channel, flags, NULL);
541 status = g_io_channel_read_chars(install_channel, (gchar *) buf, 8,
543 if (status != G_IO_STATUS_NORMAL) {
544 g_io_channel_shutdown(install_channel, TRUE, NULL);
545 g_io_channel_unref(install_channel);
549 status = g_io_channel_seek_position(install_channel, 0, G_SEEK_SET, NULL);
550 if (status != G_IO_STATUS_NORMAL) {
551 connman_error("Initial seek failed");
552 g_io_channel_shutdown(install_channel, TRUE, NULL);
553 g_io_channel_unref(install_channel);
557 install_state = atoi(buf);
559 DBG("Initial state %d", install_state);
561 install_watch = g_io_add_watch_full(install_channel, G_PRIORITY_HIGH,
563 install_event, NULL, NULL);
566 g_atomic_int_set(&install_count, 1);
567 err = install_ldisc(install_channel, TRUE);
569 connman_error("ldisc installtion failed");
578 static void tist_exit(void)
581 if (install_watch > 0)
582 g_source_remove(install_watch);
584 DBG("uart_channel %p", uart_channel);
586 g_io_channel_shutdown(install_channel, TRUE, NULL);
587 g_io_channel_unref(install_channel);
589 if (uart_channel != NULL) {
590 g_io_channel_shutdown(uart_channel, TRUE, NULL);
591 g_io_channel_unref(uart_channel);
597 CONNMAN_PLUGIN_DEFINE(tist, "TI shared transport support", VERSION,
598 CONNMAN_PLUGIN_PRIORITY_DEFAULT, tist_init, tist_exit)