diff options
author | Luiz Augusto von Dentz <luiz.dentz-von@nokia.com> | 2010-06-03 18:27:54 +0300 |
---|---|---|
committer | Luiz Augusto von Dentz <luiz.dentz-von@nokia.com> | 2010-06-03 18:27:54 +0300 |
commit | c905dd81bb7b0cae9bba385d0e22ecd6ed8b82bc (patch) | |
tree | 3bd0e6be95223cfa0be2ddd251903bcfdb8507d3 | |
parent | dbfff05632d87d4ebf2d8dad8ddcb92e7d9e7d07 (diff) | |
download | obexd-c905dd81bb7b0cae9bba385d0e22ecd6ed8b82bc.tar.gz |
Add usb transport driver
-rw-r--r-- | Makefile.am | 5 | ||||
-rwxr-xr-x | bootstrap-configure | 1 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | plugins/usb.c | 256 |
4 files changed, 269 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 7ff8a3c..57fbd24 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,11 @@ builtin_nodist = builtin_modules += bluetooth builtin_sources += plugins/bluetooth.c +if USB +builtin_modules += usb +builtin_sources += plugins/usb.c +endif + builtin_modules += filesystem builtin_sources += plugins/filesystem.c plugins/filesystem.h diff --git a/bootstrap-configure b/bootstrap-configure index 73e993a..111c79a 100755 --- a/bootstrap-configure +++ b/bootstrap-configure @@ -7,6 +7,7 @@ fi ./bootstrap && \ ./configure --enable-maintainer-mode \ --enable-debug \ + --enable-usb \ --prefix=/usr \ --libexec=/usr/lib/obex \ --mandir=/usr/share/man \ diff --git a/configure.ac b/configure.ac index 9b023be..13a771c 100644 --- a/configure.ac +++ b/configure.ac @@ -144,6 +144,13 @@ AC_ARG_ENABLE(server, AC_HELP_STRING([--disable-server], ]) AM_CONDITIONAL(SERVER, test "${enable_server}" != "no") +AC_ARG_ENABLE(usb, AC_HELP_STRING([--enable-usb], + [enable usb plugin]), [ + enable_usb=${enableval} +]) +AM_CONDITIONAL(USB, test "${enable_usb}" = "yes" && + test "${enable_server}" != "no") + AC_ARG_ENABLE(client, AC_HELP_STRING([--disable-client], [disable compilation of OBEX client]), [ enable_client=${enableval} diff --git a/plugins/usb.c b/plugins/usb.c new file mode 100644 index 0000000..1032bbc --- /dev/null +++ b/plugins/usb.c @@ -0,0 +1,256 @@ +/* + * + * OBEX Server + * + * Copyright (C) 2007-2010 Nokia Corporation + * Copyright (C) 2007-2010 Marcel Holtmann <marcel@holtmann.org> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <fcntl.h> +#include <termios.h> + +#include <openobex/obex.h> +#include <openobex/obex_const.h> + +#include <glib.h> +#include <gdbus.h> + +#include "plugin.h" +#include "server.h" +#include "obex.h" +#include "transport.h" +#include "service.h" +#include "logging.h" + +static GIOChannel *usb_io = NULL; +static guint usb_reconnecting = 0; +static guint usb_watch = 0; +static int signal_pipe[2]; + +#define USB_RX_MTU 65535 +#define USB_TX_MTU 65535 +#define USB_DEVNODE "/dev/ttyGS0" + +static int usb_connect(struct obex_server *server); + +static void usb_disconnect(struct obex_server *server) +{ + if (usb_reconnecting > 0) { + g_source_remove(usb_reconnecting); + usb_reconnecting = 0; + } + + if (usb_watch > 0) { + g_source_remove(usb_watch); + usb_watch = 0; + } + + /* already disconnected */ + if (usb_io == NULL) + return; + + g_io_channel_shutdown(usb_io, TRUE, NULL); + g_io_channel_unref(usb_io); + usb_io = NULL; + debug("usb: disconnected"); +} + +static gboolean usb_reconnect(void *data) +{ + struct obex_server *server = data; + + usb_reconnecting = 0; + usb_connect(server); + + return FALSE; +} + +static gboolean usb_watchdog(GIOChannel *io, GIOCondition cond, + void *user_data) +{ + struct obex_server *server = user_data; + + usb_watch = 0; + usb_disconnect(server); + + if ((cond & G_IO_NVAL) == FALSE) + usb_reconnecting = g_idle_add(usb_reconnect, server); + + return FALSE; +} + +static int usb_connect(struct obex_server *server) +{ + struct termios options; + int fd, err, arg; + glong flags; + + if (usb_reconnecting > 0) { + g_source_remove(usb_reconnecting); + usb_reconnecting = 0; + } + + /* already connected */ + if (usb_io != NULL) + return 0; + + fd = open(USB_DEVNODE, O_RDWR | O_NOCTTY); + if (fd < 0) + return fd; + + flags = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + + tcgetattr(fd, &options); + cfmakeraw(&options); + options.c_oflag &= ~ONLCR; + tcsetattr(fd, TCSANOW, &options); + + arg = fcntl(fd, F_GETFL); + if (arg < 0) { + err = -errno; + goto failed; + } + + arg |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, arg) < 0) { + err = -errno; + goto failed; + } + + usb_io = g_io_channel_unix_new(fd); + g_io_channel_set_close_on_unref(usb_io, TRUE); + + err = obex_server_new_connection(server, usb_io, + USB_TX_MTU, USB_RX_MTU); + if (err < 0) + goto failed; + + usb_watch = g_io_add_watch(usb_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL, + usb_watchdog, server); + + debug("usb: Successfully opened %s", USB_DEVNODE); + + return 0; + +failed: + error("usb: %s (%d)", strerror(-err), -err); + if (usb_io == NULL) + close(fd); + else + usb_disconnect(server); + return err; +} + +static void sig_usb(int sig) +{ + if (write(signal_pipe[1], &sig, sizeof(sig)) != sizeof(sig)) + error("unable to write to signal pipe"); +} + +static gboolean handle_signal(GIOChannel *io, GIOCondition cond, + void *user_data) +{ + struct obex_server *server = user_data; + int sig, fd = g_io_channel_unix_get_fd(io); + + if (read(fd, &sig, sizeof(sig)) != sizeof(sig)) { + error("handle_signal: unable to read signal from pipe"); + return TRUE; + } + + switch (sig) { + case SIGUSR1: + debug("SIGUSR1"); + usb_connect(server); + break; + case SIGHUP: + debug("SIGHUP"); + usb_disconnect(server); + break; + default: + error("handle_signal: got unexpected signal %d", sig); + break; + } + + return TRUE; +} + +static void usb_stop(void *data) +{ + guint id = GPOINTER_TO_UINT(data); + g_source_remove(id); +} + +static void *usb_start(struct obex_server *server, int *err) +{ + GIOChannel *io; + guint id; + + io = g_io_channel_unix_new(signal_pipe[0]); + id = g_io_add_watch(io, G_IO_IN, handle_signal, server); + g_io_channel_unref(io); + + if (err != NULL) + *err = 0; + + return GUINT_TO_POINTER(id); +} + +static struct obex_transport_driver driver = { + .name = "usb", + .service = OBEX_PCSUITE, + .start = usb_start, + .stop = usb_stop +}; + +static int usb_init(void) +{ + struct sigaction sa; + + if (pipe(signal_pipe) < 0) + return -errno; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = sig_usb; + sigaction(SIGUSR1, &sa, NULL); + sigaction(SIGHUP, &sa, NULL); + + return obex_transport_driver_register(&driver); +} + +static void usb_exit(void) +{ + close(signal_pipe[0]); + close(signal_pipe[1]); + + obex_transport_driver_unregister(&driver); +} + +OBEX_PLUGIN_DEFINE(usb, usb_init, usb_exit) |