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
34 #include <sys/ioctl.h>
40 #define CONNMAN_API_SUBJECT_TO_CHANGE
41 #include <connman/plugin.h>
42 #include <connman/log.h>
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"
48 /* Shared transport line discipline */
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;
56 static guint install_watch = 0;
57 static guint uart_watch = 0;
59 static gint install_count = 0;
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 */
73 #define BOTHER 0x00001000
76 #define HCI_HDR_OPCODE 0xff36
77 #define HCI_COMMAND_PKT 0x01
78 #define HCI_EVENT_PKT 0x04
79 #define EVT_CMD_COMPLETE 0x0E
81 /* HCI Command structure to set the target baud rate */
82 struct speed_change_cmd {
87 } __attribute__ ((packed));
89 /* HCI Event structure to set the cusrom baud rate*/
98 } __attribute__ ((packed));
100 static int read_baud_rate(unsigned long *baud)
107 f = fopen(TIST_SYSFS_BAUD, "r");
111 err = fscanf(f, "%lu", baud);
114 DBG("baud rate %lu", *baud);
119 static int read_uart_name(char uart_name[], size_t uart_name_len)
126 memset(uart_name, 0, uart_name_len);
128 f = fopen(TIST_SYSFS_UART, "r");
132 err = fscanf(f, "%s", uart_name);
135 DBG("UART name %s", uart_name);
140 static int read_hci_event(int fd, unsigned char *buf, int size)
142 int prefix_len, param_len;
147 /* First 3 bytes are prefix, event and param length */
148 prefix_len = read(fd, buf, 3);
152 if (prefix_len < 3) {
153 connman_error("Truncated HCI prefix %d bytes 0x%x",
158 DBG("type 0x%x event 0x%x param len %d", buf[0], buf[1], buf[2]);
161 if (param_len > size - 3) {
162 connman_error("Buffer is too small %d", size);
166 return read(fd, buf + 3, param_len);
169 static int read_command_complete(int fd, unsigned short opcode)
171 struct cmd_complete resp;
176 err = read_hci_event(fd, (unsigned char *)&resp, sizeof(resp));
180 DBG("HCI event %d bytes", err);
182 if (resp.uart_prefix != HCI_EVENT_PKT) {
183 connman_error("Not an event packet");
187 if (resp.evt != EVT_CMD_COMPLETE) {
188 connman_error("Not a cmd complete event");
193 connman_error("HCI header length %d", resp.plen);
197 if (resp.opcode != (unsigned short) opcode) {
198 connman_error("opcode 0x%04x 0x%04x", resp.opcode, opcode);
205 /* The default baud rate is 115200 */
206 static int set_default_baud_rate(int fd)
213 err = tcflush(fd, TCIOFLUSH);
217 err = tcgetattr(fd, &ti);
224 ti.c_cflag |= CRTSCTS;
226 err = tcsetattr(fd, TCSANOW, &ti);
230 cfsetospeed(&ti, B115200);
231 cfsetispeed(&ti, B115200);
233 err = tcsetattr(fd, TCSANOW, &ti);
237 err = tcflush(fd, TCIOFLUSH);
244 connman_error("%s", strerror(errno));
249 static int set_custom_baud_rate(int fd, unsigned long cus_baud_rate, int flow_ctrl)
255 DBG("baud rate %lu flow_ctrl %d", cus_baud_rate, flow_ctrl);
257 err = tcflush(fd, TCIOFLUSH);
261 err = tcgetattr(fd, &ti);
266 ti.c_cflag |= CRTSCTS;
268 ti.c_cflag &= ~CRTSCTS;
271 * Set the parameters associated with the UART
272 * The change will occur immediately by using TCSANOW.
274 err = tcsetattr(fd, TCSANOW, &ti);
278 err = tcflush(fd, TCIOFLUSH);
282 /* Set the actual baud rate */
283 err = ioctl(fd, TCGETS2, &ti2);
287 ti2.c_cflag &= ~CBAUD;
288 ti2.c_cflag |= BOTHER;
289 ti2.c_ospeed = cus_baud_rate;
291 err = ioctl(fd, TCSETS2, &ti2);
298 DBG("%s", strerror(errno));
303 static gboolean uart_event(GIOChannel *channel,
304 GIOCondition cond, gpointer data)
310 uart_fd = g_io_channel_unix_get_fd(channel);
312 if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
313 connman_error("UART event 0x%x", cond);
315 g_source_remove(uart_watch);
320 if (read_command_complete(uart_fd, HCI_HDR_OPCODE) < 0)
323 if (set_custom_baud_rate(uart_fd, baud_rate, 1) < 0)
327 if (ioctl(uart_fd, TIOCSETD, &ldisc) < 0)
330 g_atomic_int_set(&install_count, 0);
335 g_atomic_int_set(&install_count, 0);
336 g_io_channel_shutdown(channel, TRUE, NULL);
337 g_io_channel_unref(channel);
342 static int install_ldisc(GIOChannel *channel, gboolean install)
345 struct speed_change_cmd cmd;
348 DBG("%d %p", install, uart_channel);
350 if (install == FALSE) {
351 g_atomic_int_set(&install_count, 0);
353 if (uart_channel == NULL) {
354 DBG("UART channel is NULL");
358 g_io_channel_shutdown(uart_channel, TRUE, NULL);
359 g_io_channel_unref(uart_channel);
366 if (uart_channel != NULL) {
367 g_io_channel_shutdown(uart_channel, TRUE, NULL);
368 g_io_channel_unref(uart_channel);
372 DBG("opening %s custom baud %lu", uart_dev_name, baud_rate);
374 uart_fd = open(uart_dev_name, O_RDWR | O_CLOEXEC);
378 uart_channel = g_io_channel_unix_new(uart_fd);
379 g_io_channel_set_close_on_unref(uart_channel, TRUE);
381 g_io_channel_set_encoding(uart_channel, NULL, NULL);
382 g_io_channel_set_buffered(uart_channel, FALSE);
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);
388 err = set_default_baud_rate(uart_fd);
390 g_io_channel_shutdown(uart_channel, TRUE, NULL);
391 g_io_channel_unref(uart_channel);
397 if (baud_rate == 115200) {
401 if (ioctl(uart_fd, TIOCSETD, &ldisc) < 0) {
402 g_io_channel_shutdown(uart_channel, TRUE, NULL);
403 g_io_channel_unref(uart_channel);
407 g_atomic_int_set(&install_count, 0);
412 cmd.uart_prefix = HCI_COMMAND_PKT;
413 cmd.opcode = HCI_HDR_OPCODE;
414 cmd.plen = sizeof(unsigned long);
415 cmd.speed = baud_rate;
417 uart_watch = g_io_add_watch(uart_channel,
418 G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
421 err = write(uart_fd, &cmd, sizeof(cmd));
423 connman_error("Write failed %d", err);
425 g_io_channel_shutdown(uart_channel, TRUE, NULL);
426 g_io_channel_unref(uart_channel);
434 static gboolean install_event(GIOChannel *channel,
435 GIOCondition cond, gpointer data)
437 GIOStatus status = G_IO_STATUS_NORMAL;
438 unsigned int install_state;
445 if (cond & (G_IO_HUP | G_IO_NVAL)) {
446 connman_error("install event 0x%x", cond);
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);
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);
466 install_state = atoi(buf);
467 DBG("install event while installing %d %c", install_state, buf[0]);
471 g_atomic_int_set(&install_count, 1);
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);
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);
489 install_state = atoi(buf);
491 DBG("install state %d", install_state);
493 install = !!install_state;
495 if (install_ldisc(channel, install) < 0) {
496 connman_error("ldisc installation failed");
497 g_atomic_int_set(&install_count, 0);
505 static int tist_init(void)
507 GIOStatus status = G_IO_STATUS_NORMAL;
509 unsigned int install_state;
514 err = read_uart_name(uart_dev_name, sizeof(uart_dev_name));
516 connman_error("Could not read the UART name");
520 err = read_baud_rate(&baud_rate);
522 connman_error("Could not read the baud rate");
526 fd = open(TIST_SYSFS_INSTALL, O_RDONLY | O_CLOEXEC);
528 connman_error("Failed to open TI ST sysfs install file");
532 install_channel = g_io_channel_unix_new(fd);
533 g_io_channel_set_close_on_unref(install_channel, TRUE);
535 g_io_channel_set_encoding(install_channel, NULL, NULL);
536 g_io_channel_set_buffered(install_channel, FALSE);
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);
542 status = g_io_channel_read_chars(install_channel, (gchar *) buf, 8,
544 if (status != G_IO_STATUS_NORMAL) {
545 g_io_channel_shutdown(install_channel, TRUE, NULL);
546 g_io_channel_unref(install_channel);
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);
558 install_state = atoi(buf);
560 DBG("Initial state %d", install_state);
562 install_watch = g_io_add_watch_full(install_channel, G_PRIORITY_HIGH,
564 install_event, NULL, NULL);
567 g_atomic_int_set(&install_count, 1);
568 err = install_ldisc(install_channel, TRUE);
570 connman_error("ldisc installtion failed");
579 static void tist_exit(void)
582 if (install_watch > 0)
583 g_source_remove(install_watch);
585 DBG("uart_channel %p", uart_channel);
587 g_io_channel_shutdown(install_channel, TRUE, NULL);
588 g_io_channel_unref(install_channel);
590 if (uart_channel != NULL) {
591 g_io_channel_shutdown(uart_channel, TRUE, NULL);
592 g_io_channel_unref(uart_channel);
598 CONNMAN_PLUGIN_DEFINE(tist, "TI shared transport support", VERSION,
599 CONNMAN_PLUGIN_PRIORITY_DEFAULT, tist_init, tist_exit)