---
Makefile.am | 1 +
client/manager.c | 2 +
client/map.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++
client/map.h | 24 +++++++++
doc/client-api.txt | 9 ++++
5 files changed, 171 insertions(+), 0 deletions(-)
create mode 100644 client/map.c
create mode 100644 client/map.h
diff --git a/Makefile.am b/Makefile.am
index 2582651..90fdd63 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -120,6 +120,7 @@ client_obex_client_SOURCES = $(gdbus_sources) $(gobex_sources) \
client/pbap.h client/pbap.c \
client/ftp.h client/ftp.c \
client/opp.h client/opp.c \
+ client/map.h client/map.c \
client/transfer.h client/transfer.c \
client/agent.h client/agent.c \
client/driver.h client/driver.c
diff --git a/client/manager.c b/client/manager.c
index dfb282b..f6628d7 100644
--- a/client/manager.c
+++ b/client/manager.c
@@ -42,6 +42,7 @@
#include "ftp.h"
#include "pbap.h"
#include "sync.h"
+#include "map.h"
#define CLIENT_SERVICE "org.openobex.client"
@@ -567,6 +568,7 @@ static struct target_module {
{ "ftp", ftp_init, ftp_exit },
{ "pbap", pbap_init, pbap_exit },
{ "sync", sync_init, sync_exit },
+ { "map", map_init, map_exit },
{ }
};
diff --git a/client/map.c b/client/map.c
new file mode 100644
index 0000000..bee49c5
--- /dev/null
+++ b/client/map.c
@@ -0,0 +1,135 @@
+/*
+ *
+ * OBEX Client
+ *
+ * Copyright (C) 2011 Bartosz Szatkowski <[email protected]> for Comarch
+ *
+ * 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 <errno.h>
+#include <glib.h>
+#include <gdbus.h>
+
+#include "log.h"
+
+#include "map.h"
+#include "transfer.h"
+#include "session.h"
+#include "driver.h"
+
+#define OBEX_MAS_UUID \
+ "\xBB\x58\x2B\x40\x42\x0C\x11\xDB\xB0\xDE\x08\x00\x20\x0C\x9A\x66"
+#define OBEX_MAS_UUID_LEN 16
+
+#define MAP_INTERFACE "org.openobex.MessageAccess"
+#define MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"
+
+struct map_data {
+ struct obc_session *session;
+ DBusMessage *msg;
+};
+
+static DBusConnection *conn = NULL;
+
+static GDBusMethodTable map_methods[] = {
+ { }
+};
+
+static void map_free(void *data)
+{
+ struct map_data *map = data;
+
+ obc_session_unref(map->session);
+ g_free(map);
+}
+
+static int map_probe(struct obc_session *session)
+{
+ struct map_data *map;
+ const char *path;
+
+ path = obc_session_get_path(session);
+
+ DBG("%s", path);
+
+ map = g_try_new0(struct map_data, 1);
+ if (!map)
+ return -ENOMEM;
+
+ map->session = obc_session_ref(session);
+
+ if (!g_dbus_register_interface(conn, path, MAP_INTERFACE, map_methods,
+ NULL, NULL, map, map_free)) {
+ map_free(map);
+
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void map_remove(struct obc_session *session)
+{
+ const char *path = obc_session_get_path(session);
+
+ DBG("%s", path);
+
+ g_dbus_unregister_interface(conn, path, MAP_INTERFACE);
+}
+
+static struct obc_driver map = {
+ .service = "MAP",
+ .uuid = MAS_UUID,
+ .target = OBEX_MAS_UUID,
+ .target_len = OBEX_MAS_UUID_LEN,
+ .probe = map_probe,
+ .remove = map_remove
+};
+
+int map_init(void)
+{
+ int err;
+
+ DBG("");
+
+ conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
+ if (!conn)
+ return -EIO;
+
+ err = obc_driver_register(&map);
+ if (err < 0) {
+ dbus_connection_unref(conn);
+ conn = NULL;
+ return err;
+ }
+
+ return 0;
+}
+
+void map_exit(void)
+{
+ DBG("");
+
+ dbus_connection_unref(conn);
+ conn = NULL;
+
+ obc_driver_unregister(&map);
+}
diff --git a/client/map.h b/client/map.h
new file mode 100644
index 0000000..86f6b95
--- /dev/null
+++ b/client/map.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * OBEX Client
+ *
+ * Copyright (C) 2011 Bartosz Szatkowski <[email protected]> for Comarch
+ *
+ * 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
+ *
+ */
+
+int map_init(void);
+void map_exit(void);
diff --git a/doc/client-api.txt b/doc/client-api.txt
index 3e61cf7..ee8951f 100644
--- a/doc/client-api.txt
+++ b/doc/client-api.txt
@@ -251,6 +251,15 @@ Methods void SetLocation(string location)
Send an entire Phonebook Object store to remote device
+Message Access hierarchy
+=========================
+
+Service org.openobex.client
+Interface org.openobex.MessageAccess
+Object path [variable prefix]/{session0,session1,...}
+
+Methods
+
Transfer hierarchy
==================
--
1.7.4.1
On Fri, Dec 2, 2011 at 3:37 PM, Johan Hedberg <[email protected]> wrote:
> Hi Bartosz,
>
> On Fri, Dec 02, 2011, Bartosz Szatkowski wrote:
>> +static struct error_code {
>> + const char *name;
>> + guint8 code;
>> +} map_errors[] = {
>> + {"Success", G_OBEX_RSP_SUCCESS},
>> + {"Bad Request", G_OBEX_RSP_BAD_REQUEST},
>> + {"Not Implemented", G_OBEX_RSP_NOT_IMPLEMENTED},
>> + {"Service Unavailable", G_OBEX_RSP_SERVICE_UNAVAILABLE},
>> + {"Forbidden", G_OBEX_RSP_FORBIDDEN},
>> + {"Unauthorized", G_OBEX_RSP_UNAUTHORIZED},
>> + {"Precondition Failed", G_OBEX_RSP_PRECONDITION_FAILED},
>> + {"Not Acceptable", G_OBEX_RSP_NOT_ACCEPTABLE},
>> + {"Not Found", G_OBEX_RSP_NOT_FOUND},
>> + { }
>
> The table is missing spaces on each line after { and before }
>
>> +static const char *get_error_string(guint8 err_code)
>> +{
>> + struct error_code *error;
>> +
>> + for (error = map_errors; error != NULL; error++)
>> + if (error->code == err_code)
>> + return error->name;
>> +
>> + return NULL;
>> +}
>
> It'd probably make sense to make this kind of function more widely
> available, maybe through gobex. However instead of a NULL return I'd
> return "<unknown>" to avoid passing NULL pointers to %s format
> specifiers like you're doing below (I know this will typically just work
> and add a "(null)" to the string, but it's still not a very good
> practice and can cause misleading logs:
>
>> + reply = g_dbus_create_error(map->msg,
>> + "org.openobex.Error.Response",
>> + "%s(0x%X)", get_error_string(err_code),
>> + err_code);
>
> You're also missing a space between %s and ( and please use 0x%02x for
> single byte values.
>
> Johan
OK
--
Pozdrowienia - Cheers,
Bartosz Szatkowski
Hi Bartosz,
On Fri, Dec 02, 2011, Bartosz Szatkowski wrote:
> ---
> test/map-client | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 52 insertions(+), 0 deletions(-)
> create mode 100755 test/map-client
This patch is missing an addition to Makefile.am (test_files).
Johan
Hi Bartosz,
On Fri, Dec 02, 2011, Bartosz Szatkowski wrote:
> +static struct error_code {
> + const char *name;
> + guint8 code;
> +} map_errors[] = {
> + {"Success", G_OBEX_RSP_SUCCESS},
> + {"Bad Request", G_OBEX_RSP_BAD_REQUEST},
> + {"Not Implemented", G_OBEX_RSP_NOT_IMPLEMENTED},
> + {"Service Unavailable", G_OBEX_RSP_SERVICE_UNAVAILABLE},
> + {"Forbidden", G_OBEX_RSP_FORBIDDEN},
> + {"Unauthorized", G_OBEX_RSP_UNAUTHORIZED},
> + {"Precondition Failed", G_OBEX_RSP_PRECONDITION_FAILED},
> + {"Not Acceptable", G_OBEX_RSP_NOT_ACCEPTABLE},
> + {"Not Found", G_OBEX_RSP_NOT_FOUND},
> + { }
The table is missing spaces on each line after { and before }
> +static const char *get_error_string(guint8 err_code)
> +{
> + struct error_code *error;
> +
> + for (error = map_errors; error != NULL; error++)
> + if (error->code == err_code)
> + return error->name;
> +
> + return NULL;
> +}
It'd probably make sense to make this kind of function more widely
available, maybe through gobex. However instead of a NULL return I'd
return "<unknown>" to avoid passing NULL pointers to %s format
specifiers like you're doing below (I know this will typically just work
and add a "(null)" to the string, but it's still not a very good
practice and can cause misleading logs:
> + reply = g_dbus_create_error(map->msg,
> + "org.openobex.Error.Response",
> + "%s(0x%X)", get_error_string(err_code),
> + err_code);
You're also missing a space between %s and ( and please use 0x%02x for
single byte values.
Johan
---
test/map-client | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 52 insertions(+), 0 deletions(-)
create mode 100755 test/map-client
diff --git a/test/map-client b/test/map-client
new file mode 100755
index 0000000..5ee4331
--- /dev/null
+++ b/test/map-client
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+
+import gobject
+
+import dbus
+import dbus.mainloop.glib
+from optparse import OptionParser
+
+def parse_options():
+ parser.add_option("-d", "--device", dest="device",
+ help="Device to connect", metavar="DEVICE")
+ parser.add_option("-c", "--chdir", dest="new_dir",
+ help="Change current directory to DIR", metavar="DIR")
+ parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
+
+ return parser.parse_args()
+
+def set_folder(session, new_dir):
+ for node in new_dir.split("/"):
+ session.SetFolder(node)
+
+if __name__ == '__main__':
+
+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+ parser = OptionParser()
+
+ (options, args) = parse_options()
+
+ if not options.device:
+ parser.print_help()
+ exit(0)
+
+ bus = dbus.SessionBus()
+ mainloop = gobject.MainLoop()
+
+ client = dbus.Interface(bus.get_object("org.openobex.client", "/"),
+ "org.openobex.Client")
+
+ session_path = client.CreateSession({ "Destination": options.device,
+ "Target": "map"})
+
+ session = dbus.Interface(bus.get_object("org.openobex.client", session_path),
+ "org.openobex.Session")
+
+ map = dbus.Interface(bus.get_object("org.openobex.client", session_path),
+ "org.openobex.MessageAccess")
+
+ if options.new_dir:
+ set_folder(map, options.new_dir)
+
+ mainloop.run()
--
1.7.4.1
---
client/map.c | 33 +++++++++++++++++++++++++++++++++
1 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/client/map.c b/client/map.c
index e5ebecb..8bc1583 100644
--- a/client/map.c
+++ b/client/map.c
@@ -50,17 +50,50 @@ struct map_data {
DBusMessage *msg;
};
+static struct error_code {
+ const char *name;
+ guint8 code;
+} map_errors[] = {
+ {"Success", G_OBEX_RSP_SUCCESS},
+ {"Bad Request", G_OBEX_RSP_BAD_REQUEST},
+ {"Not Implemented", G_OBEX_RSP_NOT_IMPLEMENTED},
+ {"Service Unavailable", G_OBEX_RSP_SERVICE_UNAVAILABLE},
+ {"Forbidden", G_OBEX_RSP_FORBIDDEN},
+ {"Unauthorized", G_OBEX_RSP_UNAUTHORIZED},
+ {"Precondition Failed", G_OBEX_RSP_PRECONDITION_FAILED},
+ {"Not Acceptable", G_OBEX_RSP_NOT_ACCEPTABLE},
+ {"Not Found", G_OBEX_RSP_NOT_FOUND},
+ { }
+};
+
static DBusConnection *conn = NULL;
+static const char *get_error_string(guint8 err_code)
+{
+ struct error_code *error;
+
+ for (error = map_errors; error != NULL; error++)
+ if (error->code == err_code)
+ return error->name;
+
+ return NULL;
+}
+
static void simple_cb(GObex *obex, GError *err, GObexPacket *rsp,
gpointer user_data)
{
DBusMessage *reply;
struct map_data *map = user_data;
+ guint8 err_code = g_obex_packet_get_operation(rsp, NULL);
if (err != NULL)
reply = g_dbus_create_error(map->msg, ERROR_FAILED_PATH,
"%s", err->message);
+ else if (err_code != G_OBEX_RSP_SUCCESS)
+ reply = g_dbus_create_error(map->msg,
+ "org.openobex.Error.Response",
+ "%s(0x%X)", get_error_string(err_code),
+ err_code);
else
reply = dbus_message_new_method_return(map->msg);
--
1.7.4.1
---
client/map.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
doc/client-api.txt | 5 ++++-
2 files changed, 54 insertions(+), 1 deletions(-)
diff --git a/client/map.c b/client/map.c
index bee49c5..e5ebecb 100644
--- a/client/map.c
+++ b/client/map.c
@@ -40,6 +40,9 @@
#define OBEX_MAS_UUID_LEN 16
#define MAP_INTERFACE "org.openobex.MessageAccess"
+#define ERROR_INF MAP_INTERFACE ".Error"
+#define ERROR_FAILED_PATH "org.openobex.Error.Failed"
+
#define MAS_UUID "00001132-0000-1000-8000-00805f9b34fb"
struct map_data {
@@ -49,7 +52,54 @@ struct map_data {
static DBusConnection *conn = NULL;
+static void simple_cb(GObex *obex, GError *err, GObexPacket *rsp,
+ gpointer user_data)
+{
+ DBusMessage *reply;
+ struct map_data *map = user_data;
+
+ if (err != NULL)
+ reply = g_dbus_create_error(map->msg, ERROR_FAILED_PATH,
+ "%s", err->message);
+ else
+ reply = dbus_message_new_method_return(map->msg);
+
+ g_dbus_send_message(conn, reply);
+ dbus_message_unref(map->msg);
+}
+
+static DBusMessage *map_setpath(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct map_data *map = user_data;
+ const char *folder;
+ GObex *obex;
+ GError *err = NULL;
+
+ if (dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &folder,
+ DBUS_TYPE_INVALID) == FALSE)
+ return g_dbus_create_error(message,
+ ERROR_INF ".InvalidArguments", NULL);
+
+ obex = obc_session_get_obex(map->session);
+
+ g_obex_setpath(obex, folder, simple_cb, map, &err);
+ if (err != NULL) {
+ DBusMessage *reply;
+ reply = g_dbus_create_error(message,
+ ERROR_FAILED_PATH,
+ "%s", err->message);
+ g_error_free(err);
+ return reply;
+ }
+
+ map->msg = dbus_message_ref(message);
+
+ return NULL;
+}
+
static GDBusMethodTable map_methods[] = {
+ { "SetFolder", "s", "", map_setpath, G_DBUS_METHOD_FLAG_ASYNC },
{ }
};
diff --git a/doc/client-api.txt b/doc/client-api.txt
index ee8951f..fb5a8b2 100644
--- a/doc/client-api.txt
+++ b/doc/client-api.txt
@@ -258,7 +258,10 @@ Service org.openobex.client
Interface org.openobex.MessageAccess
Object path [variable prefix]/{session0,session1,...}
-Methods
+Methods void SetFolder(string name)
+
+ Set working directory for current session, *name* may
+ be the directory name or '..[/dir]'.
Transfer hierarchy
==================
--
1.7.4.1