diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2011-08-26 12:49:34 +0300 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2012-12-04 22:22:02 +0100 |
commit | 7e7a99b03943513622f6dde5d775a14e902744fe (patch) | |
tree | a838bc00512428fa3e8a0cdcc4125942b72c233c /tools/obex-client-tool.c | |
parent | b9794defb8dcc7643fa3cb8d2856e79a76c8d6b7 (diff) | |
download | bluez-7e7a99b03943513622f6dde5d775a14e902744fe.tar.gz |
gobex: Add Bluetooth support for test-client
Diffstat (limited to 'tools/obex-client-tool.c')
-rw-r--r-- | tools/obex-client-tool.c | 216 |
1 files changed, 155 insertions, 61 deletions
diff --git a/tools/obex-client-tool.c b/tools/obex-client-tool.c index ec6d1c264..d967f0274 100644 --- a/tools/obex-client-tool.c +++ b/tools/obex-client-tool.c @@ -33,12 +33,16 @@ #include <readline/history.h> #include <gobex/gobex.h> +#include <btio/btio.h> static GMainLoop *main_loop = NULL; static GObex *obex = NULL; static gboolean option_packet = FALSE; static gboolean option_bluetooth = FALSE; +static char *option_source = NULL; +static char *option_dest = NULL; +static int option_channel = -1; static void sig_term(int sig) { @@ -51,6 +55,14 @@ static GOptionEntry options[] = { &option_bluetooth, "Use a UNIX socket" }, { "bluetooth", 'b', 0, G_OPTION_ARG_NONE, &option_bluetooth, "Use Bluetooth" }, + { "source", 's', 0, G_OPTION_ARG_STRING, + &option_source, "Bluetooth adapter address", + "00:..." }, + { "destination", 'd', 0, G_OPTION_ARG_STRING, + &option_dest, "Remote bluetooth address", + "00:..." }, + { "channel", 'c', 0, G_OPTION_ARG_INT, + &option_channel, "Transport channel", "CHANNEL" }, { "packet", 'p', 0, G_OPTION_ARG_NONE, &option_packet, "Packet based transport" }, { "stream", 's', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, @@ -58,48 +70,6 @@ static GOptionEntry options[] = { { NULL }, }; -static void disconn_func(GObex *obex, GError *err, gpointer user_data) -{ - g_printerr("Disconnected: %s\n", err ? err->message : "(no error)"); - g_main_loop_quit(main_loop); -} - -static GIOChannel *unix_connect(void) -{ - GIOChannel *io; - struct sockaddr_un addr = { - AF_UNIX, "\0/gobex/server" - }; - int sk, err, sock_type; - - if (option_packet) - sock_type = SOCK_SEQPACKET; - else - sock_type = SOCK_STREAM; - - sk = socket(PF_LOCAL, sock_type, 0); - if (sk < 0) { - err = errno; - g_printerr("Can't create unix socket: %s (%d)\n", - strerror(err), err); - return NULL; - } - - if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - err = errno; - g_printerr("connect: %s (%d)\n", strerror(err), err); - return NULL; - } - - io = g_io_channel_unix_new(sk); - g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL); - g_io_channel_set_close_on_unref(io, TRUE); - - g_print("Unix socket created: %d\n", sk); - - return io; -} - static void conn_complete(GObex *obex, GError *err, GObexPacket *rsp, gpointer user_data) { @@ -293,13 +263,145 @@ static gboolean prompt_read(GIOChannel *chan, GIOCondition cond, return TRUE; } +static void disconn_func(GObex *obex, GError *err, gpointer user_data) +{ + g_printerr("Disconnected: %s\n", err ? err->message : "(no error)"); + g_main_loop_quit(main_loop); +} + +static void transport_connect(GIOChannel *io, GObexTransportType transport, + gssize rx_mtu, gssize tx_mtu) +{ + GIOChannel *input; + GIOCondition events; + + g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL); + g_io_channel_set_close_on_unref(io, TRUE); + + obex = g_obex_new(io, transport, rx_mtu, tx_mtu); + g_obex_set_disconnect_function(obex, disconn_func, NULL); + + input = g_io_channel_unix_new(STDIN_FILENO); + g_io_channel_set_close_on_unref(input, TRUE); + events = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL; + g_io_add_watch(input, events, prompt_read, NULL); + g_io_channel_unref(input); + rl_callback_handler_install("client> ", parse_line); +} + +static GIOChannel *unix_connect(GObexTransportType transport) +{ + GIOChannel *io; + struct sockaddr_un addr = { + AF_UNIX, "\0/gobex/server" + }; + int sk, err, sock_type; + + if (option_packet) + sock_type = SOCK_SEQPACKET; + else + sock_type = SOCK_STREAM; + + sk = socket(PF_LOCAL, sock_type, 0); + if (sk < 0) { + err = errno; + g_printerr("Can't create unix socket: %s (%d)\n", + strerror(err), err); + return NULL; + } + + if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + err = errno; + g_printerr("connect: %s (%d)\n", strerror(err), err); + return NULL; + } + + io = g_io_channel_unix_new(sk); + + g_print("Unix socket created: %d\n", sk); + + transport_connect(io, transport, -1, -1); + + return io; +} + +static void conn_callback(GIOChannel *io, GError *err, gpointer user_data) +{ + GObexTransportType transport = GPOINTER_TO_UINT(user_data); + guint16 imtu = 4096, omtu = 32767; + + if (err != NULL) { + g_printerr("%s\n", err->message); + return; + } + + if (transport == G_OBEX_TRANSPORT_PACKET) { + GError *err = NULL; + + if (!bt_io_get(io, BT_IO_L2CAP, &err, + BT_IO_OPT_OMTU, &omtu, + BT_IO_OPT_IMTU, &imtu, + BT_IO_OPT_INVALID)) { + g_printerr("%s\n", err->message); + g_clear_error(&err); + exit(EXIT_FAILURE); + } else + g_print("imtu=%u, omtu=%u\n", imtu, omtu); + } + + g_print("Bluetooth socket connected\n"); + + transport_connect(io, transport, imtu, omtu); +} + +static GIOChannel *bluetooth_connect(GObexTransportType transport) +{ + GIOChannel *io; + GError *err = NULL; + BtIOType type; + BtIOOption option; + + if (option_dest == NULL || option_channel < 0) + return NULL; + + if (transport == G_OBEX_TRANSPORT_PACKET || option_channel > 31) { + type = BT_IO_L2CAP; + option = BT_IO_OPT_PSM; + } else { + type = BT_IO_RFCOMM; + option = BT_IO_OPT_CHANNEL; + } + + if (option_source) + io = bt_io_connect(type, conn_callback, GUINT_TO_POINTER(transport), + NULL, &err, + BT_IO_OPT_SOURCE, option_source, + BT_IO_OPT_DEST, option_dest, + option, option_channel, + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, + BT_IO_OPT_INVALID); + else + io = bt_io_connect(type, conn_callback, GUINT_TO_POINTER(transport), + NULL, &err, + BT_IO_OPT_DEST, option_dest, + option, option_channel, + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, + BT_IO_OPT_INVALID); + + if (io != NULL) + return io; + + g_printerr("%s\n", err->message); + g_error_free(err); + return NULL; +} + int main(int argc, char *argv[]) { GOptionContext *context; GError *err = NULL; struct sigaction sa; GIOChannel *io; - GIOCondition events; GObexTransportType transport; context = g_option_context_new(NULL); @@ -312,7 +414,16 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - io = unix_connect(); + if (option_packet) + transport = G_OBEX_TRANSPORT_PACKET; + else + transport = G_OBEX_TRANSPORT_STREAM; + + if (option_bluetooth) + io = bluetooth_connect(transport); + else + io = unix_connect(transport); + if (io == NULL) exit(EXIT_FAILURE); @@ -323,23 +434,6 @@ int main(int argc, char *argv[]) main_loop = g_main_loop_new(NULL, FALSE); - if (option_packet) - transport = G_OBEX_TRANSPORT_PACKET; - else - transport = G_OBEX_TRANSPORT_STREAM; - - obex = g_obex_new(io, transport, -1, -1); - g_io_channel_unref(io); - - g_obex_set_disconnect_function(obex, disconn_func, NULL); - - io = g_io_channel_unix_new(STDIN_FILENO); - g_io_channel_set_close_on_unref(io, TRUE); - events = G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL; - g_io_add_watch(io, events, prompt_read, NULL); - g_io_channel_unref(io); - rl_callback_handler_install("client> ", parse_line); - g_main_loop_run(main_loop); rl_callback_handler_remove(); |