* Re: How to config bluetooth headset ?
From: Daniel O'Connor @ 2011-02-22 10:02 UTC (permalink / raw)
To: Daniel O'Connor; +Cc: Bob Liu, linux-bluetooth
In-Reply-To: <6FA7AA79-9141-4C2A-BF2F-7B9C0F575F03@gsoft.com.au>
On 22/02/2011, at 20:27, Daniel O'Connor wrote:
>> Is there any doc about it in detail ?
>
> I haven't seen any :(
>
> There's the source of course, but.. :-/
Actually there is the D-Bus API documentation.
http://git.kernel.org/?p=bluetooth/bluez.git;a=tree;f=doc;h=c933b3d917a930387a2422589f1caccd7db3bc9a;hb=HEAD
--
Daniel O'Connor software and network engineer
for Genesis Software - http://www.gsoft.com.au
"The nice thing about standards is that there
are so many of them to choose from."
-- Andrew Tanenbaum
GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C
^ permalink raw reply
* Re: How to config bluetooth headset ?
From: Daniel O'Connor @ 2011-02-22 9:57 UTC (permalink / raw)
To: Bob Liu; +Cc: linux-bluetooth
In-Reply-To: <AANLkTinRZ2xCxcBQhWGzRvpNLe8hU5kk+0YJ8OP_hCp5@mail.gmail.com>
On 22/02/2011, at 20:03, Bob Liu wrote:
>> Does bluetooth-wizard help you?
>>
>
> Thanks,
> But I am using beagleboard, I need to cross compile all those tools.
Ahh right..
> Is there any doc about it in detail ?
I haven't seen any :(
There's the source of course, but.. :-/
>
>> I don't know if there is a command line equivalent though, or what happens afterward - eg if bluetoothd stores the connection info for later use or something else must be run..
>>
>
> --
> Regards,
> --Bob
>
--
Daniel O'Connor software and network engineer
for Genesis Software - http://www.gsoft.com.au
"The nice thing about standards is that there
are so many of them to choose from."
-- Andrew Tanenbaum
GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C
^ permalink raw reply
* [PATCH 5/5] Fix --enable-usb build
From: Luiz Augusto von Dentz @ 2011-02-22 9:43 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1298367822-27766-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
---
configure.ac | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/configure.ac b/configure.ac
index 602c948..fc63b8c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -156,7 +156,7 @@ AC_ARG_ENABLE(usb, AC_HELP_STRING([--enable-usb],
enable_usb=${enableval}
])
AM_CONDITIONAL(USB, test "${enable_usb}" = "yes" &&
- test "${enable_server}" != "no")
+ test "${enable_usb}" != "no")
AC_ARG_ENABLE(pcsuite, AC_HELP_STRING([--enable-pcsuite],
[enable Nokia PcSuite plugin]), [
--
1.7.1
^ permalink raw reply related
* [PATCH 4/5] Move pcsuite drivers to its own plugin
From: Luiz Augusto von Dentz @ 2011-02-22 9:43 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1298367822-27766-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
This make it easier to enable/disable this funcionality as a whole.
---
Makefile.am | 6 +-
configure.ac | 10 +-
plugins/ftp.c | 165 ++------------------------
plugins/nokia-backup.c | 309 ------------------------------------------------
4 files changed, 17 insertions(+), 473 deletions(-)
delete mode 100644 plugins/nokia-backup.c
diff --git a/Makefile.am b/Makefile.am
index fc996ec..d32d613 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,9 +43,9 @@ endif
builtin_modules += filesystem
builtin_sources += plugins/filesystem.c plugins/filesystem.h
-if NOKIA_BACKUP
-builtin_modules += backup
-builtin_sources += plugins/nokia-backup.c
+if NOKIA_PCSUITE
+builtin_modules += pcsuite
+builtin_sources += plugins/pcsuite.c
endif
builtin_modules += opp
diff --git a/configure.ac b/configure.ac
index da8fb64..602c948 100644
--- a/configure.ac
+++ b/configure.ac
@@ -158,12 +158,12 @@ AC_ARG_ENABLE(usb, AC_HELP_STRING([--enable-usb],
AM_CONDITIONAL(USB, test "${enable_usb}" = "yes" &&
test "${enable_server}" != "no")
-AC_ARG_ENABLE(nokia_backup, AC_HELP_STRING([--enable-nokia-backup],
- [enable nokia-backup plugin]), [
- enable_nokia_backup=${enableval}
+AC_ARG_ENABLE(pcsuite, AC_HELP_STRING([--enable-pcsuite],
+ [enable Nokia PcSuite plugin]), [
+ enable_pcsuite=${enableval}
])
-AM_CONDITIONAL(NOKIA_BACKUP, test "${enable_nokia_backup}" = "yes" &&
- test "${enable_server}" != "no")
+AM_CONDITIONAL(NOKIA_PCSUITE, test "${enable_pcsuite}" = "yes" &&
+ test "${enable_pcsuite}" != "no")
AC_ARG_ENABLE(client, AC_HELP_STRING([--disable-client],
[disable compilation of OBEX client]), [
diff --git a/plugins/ftp.c b/plugins/ftp.c
index 38d058c..b6ee75b 100644
--- a/plugins/ftp.c
+++ b/plugins/ftp.c
@@ -50,6 +50,7 @@
#include "dbus.h"
#include "mimetype.h"
#include "service.h"
+#include "ftp.h"
#define LST_TYPE "x-obex/folder-listing"
#define CAP_TYPE "x-obex/capability"
@@ -189,7 +190,7 @@ static int get_by_type(struct ftp_session *ftp, const char *type)
return err;
}
-static void *ftp_connect(struct obex_session *os, int *err)
+void *ftp_connect(struct obex_session *os, int *err)
{
struct ftp_session *ftp;
const char *root_folder;
@@ -212,8 +213,8 @@ static void *ftp_connect(struct obex_session *os, int *err)
return ftp;
}
-static int ftp_get(struct obex_session *os, obex_object_t *obj,
- gboolean *stream, void *user_data)
+int ftp_get(struct obex_session *os, obex_object_t *obj, gboolean *stream,
+ void *user_data)
{
struct ftp_session *ftp = user_data;
const char *type = obex_get_type(os);
@@ -254,7 +255,7 @@ static int ftp_delete(struct ftp_session *ftp, const char *name)
return ret;
}
-static int ftp_chkput(struct obex_session *os, void *user_data)
+int ftp_chkput(struct obex_session *os, void *user_data)
{
struct ftp_session *ftp = user_data;
const char *name = obex_get_name(os);
@@ -278,8 +279,7 @@ static int ftp_chkput(struct obex_session *os, void *user_data)
return ret;
}
-static int ftp_put(struct obex_session *os, obex_object_t *obj,
- void *user_data)
+int ftp_put(struct obex_session *os, obex_object_t *obj, void *user_data)
{
struct ftp_session *ftp = user_data;
const char *name = obex_get_name(os);
@@ -299,8 +299,7 @@ static int ftp_put(struct obex_session *os, obex_object_t *obj,
return 0;
}
-static int ftp_setpath(struct obex_session *os, obex_object_t *obj,
- void *user_data)
+int ftp_setpath(struct obex_session *os, obex_object_t *obj, void *user_data)
{
struct ftp_session *ftp = user_data;
const char *root_folder, *name;
@@ -404,7 +403,7 @@ done:
return err;
}
-static void ftp_disconnect(struct obex_session *os, void *user_data)
+void ftp_disconnect(struct obex_session *os, void *user_data)
{
struct ftp_session *ftp = user_data;
@@ -416,145 +415,6 @@ static void ftp_disconnect(struct obex_session *os, void *user_data)
g_free(ftp);
}
-static void *pcsuite_connect(struct obex_session *os, int *err)
-{
- struct pcsuite_session *pcsuite;
- struct ftp_session *ftp;
- int fd;
- char *filename;
-
- DBG("");
-
- ftp = ftp_connect(os, err);
- if (ftp == NULL)
- return NULL;
-
- filename = g_build_filename(g_get_home_dir(), ".pcsuite", NULL);
-
- fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644);
- if (fd < 0 && errno != EEXIST) {
- error("open(%s): %s(%d)", filename, strerror(errno), errno);
- goto fail;
- }
-
- /* Try to remove the file before retrying since it could be
- that some process left/crash without removing it */
- if (fd < 0) {
- if (remove(filename) < 0) {
- error("remove(%s): %s(%d)", filename, strerror(errno),
- errno);
- goto fail;
- }
-
- fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644);
- if (fd < 0) {
- error("open(%s): %s(%d)", filename, strerror(errno),
- errno);
- goto fail;
- }
- }
-
- DBG("%s created", filename);
-
- pcsuite = g_new0(struct pcsuite_session, 1);
- pcsuite->ftp = ftp;
- pcsuite->lock_file = filename;
- pcsuite->fd = fd;
-
- DBG("session %p created", pcsuite);
-
- if (err)
- *err = 0;
-
- return pcsuite;
-
-fail:
- if (ftp)
- ftp_disconnect(os, ftp);
- if (err)
- *err = -errno;
-
- g_free(filename);
-
- return NULL;
-}
-
-static int pcsuite_get(struct obex_session *os, obex_object_t *obj,
- gboolean *stream, void *user_data)
-{
- struct pcsuite_session *pcsuite = user_data;
-
- DBG("%p", pcsuite);
-
- return ftp_get(os, obj, stream, pcsuite->ftp);
-}
-
-static int pcsuite_chkput(struct obex_session *os, void *user_data)
-{
- struct pcsuite_session *pcsuite = user_data;
-
- DBG("%p", pcsuite);
-
- return ftp_chkput(os, pcsuite->ftp);
-}
-
-static int pcsuite_put(struct obex_session *os, obex_object_t *obj,
- void *user_data)
-{
- struct pcsuite_session *pcsuite = user_data;
-
- DBG("%p", pcsuite);
-
- return ftp_put(os, obj, pcsuite->ftp);
-}
-
-static int pcsuite_setpath(struct obex_session *os, obex_object_t *obj,
- void *user_data)
-{
- struct pcsuite_session *pcsuite = user_data;
-
- DBG("%p", pcsuite);
-
- return ftp_setpath(os, obj, pcsuite->ftp);
-}
-
-static void pcsuite_disconnect(struct obex_session *os, void *user_data)
-{
- struct pcsuite_session *pcsuite = user_data;
-
- DBG("%p", pcsuite);
-
- if (pcsuite->fd >= 0)
- close(pcsuite->fd);
-
- if (pcsuite->lock_file) {
- remove(pcsuite->lock_file);
- g_free(pcsuite->lock_file);
- }
-
- if (pcsuite->ftp)
- ftp_disconnect(os, pcsuite->ftp);
-
- g_free(pcsuite);
-}
-
-static struct obex_service_driver pcsuite = {
- .name = "Nokia OBEX PC Suite Services",
- .service = OBEX_PCSUITE,
- .channel = PCSUITE_CHANNEL,
- .record = PCSUITE_RECORD,
- .target = FTP_TARGET,
- .target_size = TARGET_SIZE,
- .who = PCSUITE_WHO,
- .who_size = PCSUITE_WHO_SIZE,
- .connect = pcsuite_connect,
- .get = pcsuite_get,
- .put = pcsuite_put,
- .chkput = pcsuite_chkput,
- .setpath = pcsuite_setpath,
- .disconnect = pcsuite_disconnect
-};
-
static struct obex_service_driver ftp = {
.name = "File Transfer server",
.service = OBEX_FTP,
@@ -572,19 +432,12 @@ static struct obex_service_driver ftp = {
static int ftp_init(void)
{
- int err;
-
- err = obex_service_driver_register(&ftp);
- if (err < 0)
- return err;
-
- return obex_service_driver_register(&pcsuite);
+ return obex_service_driver_register(&ftp);
}
static void ftp_exit(void)
{
obex_service_driver_unregister(&ftp);
- obex_service_driver_unregister(&pcsuite);
}
OBEX_PLUGIN_DEFINE(ftp, ftp_init, ftp_exit)
diff --git a/plugins/nokia-backup.c b/plugins/nokia-backup.c
deleted file mode 100644
index cf17e16..0000000
--- a/plugins/nokia-backup.c
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
- *
- * OBEX Server
- *
- * Copyright (C) 2010 Nokia Corporation
- * Copyright (C) 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 <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <fcntl.h>
-#include <wait.h>
-
-#include <glib.h>
-#include "gdbus.h"
-
-
-#include <openobex/obex.h>
-#include <openobex/obex_const.h>
-
-#include "plugin.h"
-#include "log.h"
-#include "obex.h"
-#include "mimetype.h"
-#include "service.h"
-
-#define BACKUP_BUS_NAME "com.nokia.backup.plugin"
-#define BACKUP_PATH "/com/nokia/backup"
-#define BACKUP_PLUGIN_INTERFACE "com.nokia.backup.plugin"
-#define BACKUP_DBUS_TIMEOUT (1000 * 60 * 15)
-
-static const uint8_t FTP_TARGET[TARGET_SIZE] = {
- 0xF9, 0xEC, 0x7B, 0xC4, 0x95, 0x3C, 0x11, 0xD2,
- 0x98, 0x4E, 0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 };
-
-struct backup_object{
- gchar *cmd;
- int fd;
- int oflag;
- int error_code;
- mode_t mode;
- DBusPendingCall *pending_call;
- DBusConnection *conn;
-};
-
-static void on_backup_dbus_notify(DBusPendingCall *pending_call,
- void *user_data)
-{
- struct backup_object *obj = user_data;
- DBusMessage *reply;
- const char *filename;
- int error_code;
-
- DBG("Notification received for pending call - %s", obj->cmd);
-
- reply = dbus_pending_call_steal_reply(pending_call);
-
- if (reply && dbus_message_get_args(reply, NULL, DBUS_TYPE_INT32,
- &error_code, DBUS_TYPE_STRING,
- &filename, DBUS_TYPE_INVALID)) {
-
- obj->error_code = error_code;
-
- if (filename) {
- DBG("Notification - file path = %s, error_code = %d",
- filename, error_code);
- if (error_code == 0)
- obj->fd = open(filename,obj->oflag,obj->mode);
- }
-
- } else
- DBG("Notification timed out or connection got closed");
-
- if (reply)
- dbus_message_unref(reply);
-
- dbus_pending_call_unref(pending_call);
- obj->pending_call = NULL;
- dbus_connection_unref(obj->conn);
- obj->conn = NULL;
-
- if (obj->fd >= 0) {
- DBG("File opened, setting io flags, cmd = %s",
- obj->cmd);
- if (obj->oflag == O_RDONLY)
- obex_object_set_io_flags(user_data, G_IO_IN, 0);
- else
- obex_object_set_io_flags(user_data, G_IO_OUT, 0);
- } else {
- DBG("File open error, setting io error, cmd = %s",
- obj->cmd);
- obex_object_set_io_flags(user_data, G_IO_ERR, -EPERM);
- }
-}
-
-static gboolean send_backup_dbus_message(const char *oper,
- struct backup_object *obj,
- size_t *size)
-{
- DBusConnection *conn;
- DBusMessage *msg;
- DBusPendingCall *pending_call;
- gboolean ret = FALSE;
- dbus_uint32_t file_size;
-
- file_size = size ? *size : 0;
-
- conn = g_dbus_setup_bus(DBUS_BUS_SESSION, NULL, NULL);
-
- if (conn == NULL)
- return FALSE;
-
- msg = dbus_message_new_method_call(BACKUP_BUS_NAME, BACKUP_PATH,
- BACKUP_PLUGIN_INTERFACE,
- "request");
- if (msg == NULL) {
- dbus_connection_unref(conn);
- return FALSE;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &oper,
- DBUS_TYPE_STRING, &obj->cmd,
- DBUS_TYPE_INT32, &file_size,
- DBUS_TYPE_INVALID);
-
- if (strcmp(oper, "open") == 0) {
- ret = dbus_connection_send_with_reply(conn, msg, &pending_call,
- BACKUP_DBUS_TIMEOUT);
- dbus_message_unref(msg);
- if (ret) {
- obj->conn = conn;
- obj->pending_call = pending_call;
- ret = dbus_pending_call_set_notify(pending_call,
- on_backup_dbus_notify,
- obj, NULL);
- } else
- dbus_connection_unref(conn);
- } else {
- ret = dbus_connection_send(conn, msg, NULL);
- dbus_message_unref(msg);
- dbus_connection_unref(conn);
- }
-
- return ret;
-}
-
-static void *backup_open(const char *name, int oflag, mode_t mode,
- void *context, size_t *size, int *err)
-{
- struct backup_object *obj = g_new0(struct backup_object, 1);
-
- DBG("cmd = %s", name);
-
- obj->cmd = g_path_get_basename(name);
- obj->oflag = oflag;
- obj->mode = mode;
- obj->fd = -1;
- obj->pending_call = NULL;
- obj->conn = NULL;
- obj->error_code = 0;
-
- if (send_backup_dbus_message("open", obj, size) == FALSE) {
- g_free(obj);
- obj = NULL;
- }
-
- if (err)
- *err = 0;
-
- return obj;
-}
-
-static int backup_close(void *object)
-{
- struct backup_object *obj = object;
- size_t size = 0;
-
- DBG("cmd = %s", obj->cmd);
-
- if (obj->fd != -1)
- close(obj->fd);
-
- if (obj->pending_call) {
- dbus_pending_call_cancel(obj->pending_call);
- dbus_pending_call_unref(obj->pending_call);
- dbus_connection_unref(obj->conn);
- }
-
- send_backup_dbus_message("close", obj, &size);
-
- g_free(obj->cmd);
- g_free(obj);
-
- return 0;
-}
-
-static ssize_t backup_read(void *object, void *buf, size_t count,
- uint8_t *hi, unsigned int *flags)
-{
- struct backup_object *obj = object;
- ssize_t ret = 0;
-
- *hi = OBEX_HDR_BODY;
-
- if (flags)
- *flags = 0;
-
- if (obj->pending_call) {
- DBG("cmd = %s, IN WAITING STAGE", obj->cmd);
- return -EAGAIN;
- }
-
- if (obj->fd != -1) {
- DBG("cmd = %s, READING DATA", obj->cmd);
- ret = read(obj->fd, buf, count);
- if (ret < 0)
- ret = -errno;
- } else {
- DBG("cmd = %s, PERMANENT FAILURE", obj->cmd);
- ret = obj->error_code ? -obj->error_code : -ENOENT;
- }
-
- return ret;
-}
-
-static ssize_t backup_write(void *object, const void *buf, size_t count)
-{
- struct backup_object *obj = object;
- ssize_t ret = 0;
-
- if (obj->pending_call) {
- DBG("cmd = %s, IN WAITING STAGE", obj->cmd);
- return -EAGAIN;
- }
-
- if (obj->fd != -1) {
- ret = write(obj->fd, buf, count);
-
- DBG("cmd = %s, WRITTING", obj->cmd);
-
- if (ret < 0) {
- error("backup: cmd = %s", obj->cmd);
- ret = -errno;
- }
- } else {
- error("backup: cmd = %s", obj->cmd);
- ret = obj->error_code ? -obj->error_code : -ENOENT;
- }
-
- return ret;
-}
-
-static int backup_flush(void *object)
-{
- DBG("%p", object);
-
- return 0;
-}
-
-static struct obex_mime_type_driver backup = {
- .target = FTP_TARGET,
- .target_size = TARGET_SIZE,
- .mimetype = "application/vnd.nokia-backup",
- .open = backup_open,
- .close = backup_close,
- .read = backup_read,
- .write = backup_write,
- .flush = backup_flush,
-};
-
-static int backup_init(void)
-{
- return obex_mime_type_driver_register(&backup);
-}
-
-static void backup_exit(void)
-{
- obex_mime_type_driver_unregister(&backup);
-}
-
-OBEX_PLUGIN_DEFINE(backup, backup_init, backup_exit)
--
1.7.1
^ permalink raw reply related
* [PATCH 3/5] Add .flush callback to backup plugin
From: Luiz Augusto von Dentz @ 2011-02-22 9:43 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1298367822-27766-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
---
plugins/nokia-backup.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/plugins/nokia-backup.c b/plugins/nokia-backup.c
index 4a69d8f..cf17e16 100644
--- a/plugins/nokia-backup.c
+++ b/plugins/nokia-backup.c
@@ -278,6 +278,13 @@ static ssize_t backup_write(void *object, const void *buf, size_t count)
return ret;
}
+static int backup_flush(void *object)
+{
+ DBG("%p", object);
+
+ return 0;
+}
+
static struct obex_mime_type_driver backup = {
.target = FTP_TARGET,
.target_size = TARGET_SIZE,
@@ -286,6 +293,7 @@ static struct obex_mime_type_driver backup = {
.close = backup_close,
.read = backup_read,
.write = backup_write,
+ .flush = backup_flush,
};
static int backup_init(void)
--
1.7.1
^ permalink raw reply related
* [PATCH 2/5] Add flush callback to mimetype driver
From: Luiz Augusto von Dentz @ 2011-02-22 9:43 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1298367822-27766-1-git-send-email-luiz.dentz@gmail.com>
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
This add the possibility to a driver to flush its data when final packet
is received which is specially usefull for PUT to prevent auto response
for objects with no body/body empty/size 0.
Note that it should not block like fsync, instead it is assumed to always
be asyncronous so request is suspended when .flush returns > 0, the
driver should then use obex_object_set_io_flags to indicate that it has
completed the operation.
---
src/mimetype.h | 1 +
src/obex.c | 26 ++++++++++++++++++++++++--
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/src/mimetype.h b/src/mimetype.h
index ff16a8c..5bf741c 100644
--- a/src/mimetype.h
+++ b/src/mimetype.h
@@ -36,6 +36,7 @@ struct obex_mime_type_driver {
ssize_t (*read) (void *object, void *buf, size_t count, uint8_t *hi,
unsigned int *flags);
ssize_t (*write) (void *object, const void *buf, size_t count);
+ int (*flush) (void *object);
int (*remove) (const char *name);
int (*set_io_watch) (void *object, obex_object_io_func func,
void *user_data);
diff --git a/src/obex.c b/src/obex.c
index f2a21b7..caba2fb 100644
--- a/src/obex.c
+++ b/src/obex.c
@@ -613,6 +613,11 @@ write:
os->pending -= w;
}
+ /* Flush on EOS */
+ if (os->size != OBJECT_SIZE_UNKNOWN && os->size == os->offset &&
+ os->driver->flush)
+ return os->driver->flush(os->object) > 0 ? -EAGAIN : 0;
+
return 0;
}
@@ -702,7 +707,7 @@ static gboolean handle_async_io(void *object, int flags, int err,
if (flags & (G_IO_IN | G_IO_PRI))
ret = obex_write_stream(os, os->obex, os->obj);
- else if (flags & G_IO_OUT)
+ else if ((flags & G_IO_OUT) && os->pending > 0)
ret = obex_read_stream(os, os->obex, os->obj);
proceed:
@@ -1089,8 +1094,25 @@ static void cmd_put(struct obex_session *os, obex_t *obex, obex_object_t *obj)
}
err = os->service->put(os, obj, os->service_data);
- if (err < 0)
+ if (err < 0) {
os_set_response(obj, err);
+ return;
+ }
+
+ /* Check if there is a body and it is not empty (size > 0), otherwise
+ openobex won't notify us with OBEX_EV_STREAMAVAIL and it gonna reply
+ right away */
+ if (os->size != 0)
+ return;
+
+ /* Flush immediatly since there is nothing to write so the driver
+ has a chance to do something before we reply */
+ if (os->object && os->driver && os->driver->flush &&
+ os->driver->flush(os->object) > 0) {
+ OBEX_SuspendRequest(obex, obj);
+ os->obj = obj;
+ os->driver->set_io_watch(os->object, handle_async_io, os);
+ }
}
static void obex_event_cb(obex_t *obex, obex_object_t *obj, int mode,
--
1.7.1
^ permalink raw reply related
* [PATCH 1/5] Add support for pcsuite lock file
From: Luiz Augusto von Dentz @ 2011-02-22 9:43 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
This should make others applications able to detect when pcsuite is
connected.
---
plugins/ftp.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 154 insertions(+), 6 deletions(-)
diff --git a/plugins/ftp.c b/plugins/ftp.c
index a952f64..38d058c 100644
--- a/plugins/ftp.c
+++ b/plugins/ftp.c
@@ -150,8 +150,16 @@ struct ftp_session {
char *folder;
};
+struct pcsuite_session {
+ struct ftp_session *ftp;
+ char *lock_file;
+ int fd;
+};
+
static void set_folder(struct ftp_session *ftp, const char *new_folder)
{
+ DBG("%p folder %s", ftp, new_folder);
+
g_free(ftp->folder);
ftp->folder = new_folder ? g_strdup(new_folder) : NULL;
@@ -165,6 +173,8 @@ static int get_by_type(struct ftp_session *ftp, const char *type)
char *path;
int err;
+ DBG("%p name %s type %s", ftp, name, type);
+
if (type == NULL && name == NULL)
return -EBADR;
@@ -184,6 +194,8 @@ static void *ftp_connect(struct obex_session *os, int *err)
struct ftp_session *ftp;
const char *root_folder;
+ DBG("");
+
root_folder = obex_get_root_folder(os);
manager_register_session(os);
@@ -195,6 +207,8 @@ static void *ftp_connect(struct obex_session *os, int *err)
if (err)
*err = 0;
+ DBG("session %p created", ftp);
+
return ftp;
}
@@ -205,6 +219,8 @@ static int ftp_get(struct obex_session *os, obex_object_t *obj,
const char *type = obex_get_type(os);
int ret;
+ DBG("%p", ftp);
+
if (ftp->folder == NULL)
return -ENOENT;
@@ -223,6 +239,8 @@ static int ftp_delete(struct ftp_session *ftp, const char *name)
char *path;
int ret = 0;
+ DBG("%p name %s", ftp, name);
+
if (!(ftp->folder && name))
return -EINVAL;
@@ -243,6 +261,8 @@ static int ftp_chkput(struct obex_session *os, void *user_data)
char *path;
int ret;
+ DBG("%p name %s", ftp, name);
+
if (name == NULL)
return -EBADR;
@@ -265,6 +285,8 @@ static int ftp_put(struct obex_session *os, obex_object_t *obj,
const char *name = obex_get_name(os);
ssize_t size = obex_get_size(os);
+ DBG("%p name %s size %d", ftp, name, size);
+
if (ftp->folder == NULL)
return -EPERM;
@@ -297,6 +319,8 @@ static int ftp_setpath(struct obex_session *os, obex_object_t *obj,
root_folder = obex_get_root_folder(os);
root = g_str_equal(root_folder, ftp->folder);
+ DBG("%p name %s", ftp, name);
+
/* Check flag "Backup" */
if ((nonhdr[0] & 0x01) == 0x01) {
DBG("Set to parent path");
@@ -384,12 +408,136 @@ static void ftp_disconnect(struct obex_session *os, void *user_data)
{
struct ftp_session *ftp = user_data;
+ DBG("%p", ftp);
+
manager_unregister_session(os);
g_free(ftp->folder);
g_free(ftp);
}
+static void *pcsuite_connect(struct obex_session *os, int *err)
+{
+ struct pcsuite_session *pcsuite;
+ struct ftp_session *ftp;
+ int fd;
+ char *filename;
+
+ DBG("");
+
+ ftp = ftp_connect(os, err);
+ if (ftp == NULL)
+ return NULL;
+
+ filename = g_build_filename(g_get_home_dir(), ".pcsuite", NULL);
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644);
+ if (fd < 0 && errno != EEXIST) {
+ error("open(%s): %s(%d)", filename, strerror(errno), errno);
+ goto fail;
+ }
+
+ /* Try to remove the file before retrying since it could be
+ that some process left/crash without removing it */
+ if (fd < 0) {
+ if (remove(filename) < 0) {
+ error("remove(%s): %s(%d)", filename, strerror(errno),
+ errno);
+ goto fail;
+ }
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644);
+ if (fd < 0) {
+ error("open(%s): %s(%d)", filename, strerror(errno),
+ errno);
+ goto fail;
+ }
+ }
+
+ DBG("%s created", filename);
+
+ pcsuite = g_new0(struct pcsuite_session, 1);
+ pcsuite->ftp = ftp;
+ pcsuite->lock_file = filename;
+ pcsuite->fd = fd;
+
+ DBG("session %p created", pcsuite);
+
+ if (err)
+ *err = 0;
+
+ return pcsuite;
+
+fail:
+ if (ftp)
+ ftp_disconnect(os, ftp);
+ if (err)
+ *err = -errno;
+
+ g_free(filename);
+
+ return NULL;
+}
+
+static int pcsuite_get(struct obex_session *os, obex_object_t *obj,
+ gboolean *stream, void *user_data)
+{
+ struct pcsuite_session *pcsuite = user_data;
+
+ DBG("%p", pcsuite);
+
+ return ftp_get(os, obj, stream, pcsuite->ftp);
+}
+
+static int pcsuite_chkput(struct obex_session *os, void *user_data)
+{
+ struct pcsuite_session *pcsuite = user_data;
+
+ DBG("%p", pcsuite);
+
+ return ftp_chkput(os, pcsuite->ftp);
+}
+
+static int pcsuite_put(struct obex_session *os, obex_object_t *obj,
+ void *user_data)
+{
+ struct pcsuite_session *pcsuite = user_data;
+
+ DBG("%p", pcsuite);
+
+ return ftp_put(os, obj, pcsuite->ftp);
+}
+
+static int pcsuite_setpath(struct obex_session *os, obex_object_t *obj,
+ void *user_data)
+{
+ struct pcsuite_session *pcsuite = user_data;
+
+ DBG("%p", pcsuite);
+
+ return ftp_setpath(os, obj, pcsuite->ftp);
+}
+
+static void pcsuite_disconnect(struct obex_session *os, void *user_data)
+{
+ struct pcsuite_session *pcsuite = user_data;
+
+ DBG("%p", pcsuite);
+
+ if (pcsuite->fd >= 0)
+ close(pcsuite->fd);
+
+ if (pcsuite->lock_file) {
+ remove(pcsuite->lock_file);
+ g_free(pcsuite->lock_file);
+ }
+
+ if (pcsuite->ftp)
+ ftp_disconnect(os, pcsuite->ftp);
+
+ g_free(pcsuite);
+}
+
static struct obex_service_driver pcsuite = {
.name = "Nokia OBEX PC Suite Services",
.service = OBEX_PCSUITE,
@@ -399,12 +547,12 @@ static struct obex_service_driver pcsuite = {
.target_size = TARGET_SIZE,
.who = PCSUITE_WHO,
.who_size = PCSUITE_WHO_SIZE,
- .connect = ftp_connect,
- .get = ftp_get,
- .put = ftp_put,
- .chkput = ftp_chkput,
- .setpath = ftp_setpath,
- .disconnect = ftp_disconnect
+ .connect = pcsuite_connect,
+ .get = pcsuite_get,
+ .put = pcsuite_put,
+ .chkput = pcsuite_chkput,
+ .setpath = pcsuite_setpath,
+ .disconnect = pcsuite_disconnect
};
static struct obex_service_driver ftp = {
--
1.7.1
^ permalink raw reply related
* Re: How to config bluetooth headset ?
From: Bob Liu @ 2011-02-22 9:33 UTC (permalink / raw)
To: Daniel O'Connor; +Cc: linux-bluetooth
In-Reply-To: <5BC4F68C-A168-4C70-8FB2-A4D2BFBB347D@gsoft.com.au>
On Tue, Feb 22, 2011 at 5:21 PM, Daniel O'Connor <doconnor@gsoft.com.au> wrote:
>
> On 22/02/2011, at 18:09, Bob Liu wrote:
>> Cureently I can scan the device:
>> # hcitool scan
>> Scanning ...
>> 00:1A:45:4A:EA:39 Jabra BT125
>> #
>>
>> How to make aplay can use that device?
>
> Does bluetooth-wizard help you?
>
Thanks,
But I am using beagleboard, I need to cross compile all those tools.
Is there any doc about it in detail ?
> I don't know if there is a command line equivalent though, or what happens afterward - eg if bluetoothd stores the connection info for later use or something else must be run..
>
--
Regards,
--Bob
^ permalink raw reply
* [PATCH] Fix not setting global mode when SetProperty is used
From: Luiz Augusto von Dentz @ 2011-02-22 9:26 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.dentz-von@nokia.com>
Global mode should be overwrite if user application change the adapter
mode by using SetProperty while there are sessions active, otherwise when
this sessions are released the mode restored will be the global mode from
before the sessions were created and not the mode set with SetProperty.
---
src/adapter.c | 14 +++++++++++---
1 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index dbae219..2e11832 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -516,8 +516,10 @@ static DBusMessage *set_discoverable(DBusConnection *conn, DBusMessage *msg,
mode = discoverable ? MODE_DISCOVERABLE : MODE_CONNECTABLE;
- if (mode == adapter->mode)
+ if (mode == adapter->mode) {
+ adapter->global_mode = mode;
return dbus_message_new_method_return(msg);
+ }
err = set_mode(adapter, mode, msg);
if (err < 0)
@@ -541,8 +543,10 @@ static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg,
mode = MODE_OFF;
- if (mode == adapter->mode)
+ if (mode == adapter->mode) {
+ adapter->global_mode = mode;
return dbus_message_new_method_return(msg);
+ }
err = set_mode(adapter, mode, msg);
if (err < 0)
@@ -2477,8 +2481,12 @@ static void set_mode_complete(struct btd_adapter *adapter)
if (err < 0)
reply = btd_error_failed(msg, strerror(-err));
- else
+ else {
+ if (strcmp(dbus_message_get_member(msg),
+ "SetProperty") == 0)
+ adapter->global_mode = adapter->mode;
reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
g_dbus_send_message(connection, reply);
}
--
1.7.1
^ permalink raw reply related
* Re: How to config bluetooth headset ?
From: Daniel O'Connor @ 2011-02-22 9:21 UTC (permalink / raw)
To: Bob Liu; +Cc: linux-bluetooth
In-Reply-To: <AANLkTinC4JqX627rv7PUWrhOZwmerCEQJ_jeZ0w29LW9@mail.gmail.com>
On 22/02/2011, at 18:09, Bob Liu wrote:
> Cureently I can scan the device:
> # hcitool scan
> Scanning ...
> 00:1A:45:4A:EA:39 Jabra BT125
> #
>
> How to make aplay can use that device?
Does bluetooth-wizard help you?
I don't know if there is a command line equivalent though, or what happens afterward - eg if bluetoothd stores the connection info for later use or something else must be run..
--
Daniel O'Connor software and network engineer
for Genesis Software - http://www.gsoft.com.au
"The nice thing about standards is that there
are so many of them to choose from."
-- Andrew Tanenbaum
GPG Fingerprint - 5596 B766 97C0 0E94 4347 295E E593 DC20 7B3F CE8C
^ permalink raw reply
* [PATCH] Bluetooth: l2cap: fix a NULL pointer oops in l2cap_conn_start
From: Feng Tang @ 2011-02-22 8:03 UTC (permalink / raw)
To: marcel, linux-bluetooth; +Cc: Feng Tang
When I try to setup a PAND connection between the sever and client,
the server side always get a NULL pointer oops in l2cap_conn_start()
right after the client run "pand -r PANU -c sever_addr". Don't have
the boot log as it's an immediate hang.
Simply adding this "if (parent)" check will fix it, don't know whether
it fix the real problem. Anyway, send it as a hint.
Signed-off-by: Feng Tang <feng.tang@intel.com>
---
net/bluetooth/l2cap.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 675614e..150366f 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -583,8 +583,9 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
struct sock *parent = bt_sk(sk)->parent;
rsp.result = cpu_to_le16(L2CAP_CR_PEND);
rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
- parent->sk_data_ready(parent, 0);
+ if (parent)
+ parent->sk_data_ready(parent, 0);
} else {
sk->sk_state = BT_CONFIG;
rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
--
1.7.0.4
^ permalink raw reply related
* How to config bluetooth headset ?
From: Bob Liu @ 2011-02-22 7:39 UTC (permalink / raw)
To: linux-bluetooth
Hi, folks
Since I can't open the wiki: http://wiki.bluez.org/wiki/HOWTO/AudioDevices.
Is there any guide how to config bluetooth headset ?
I used to use
root:/> hcid -n &
root:/> sdpd &
root:/> headsetd -n &
But it seems that things have changed a lot now, there is only bluetoothd ?
Cureently I can scan the device:
# hcitool scan
Scanning ...
00:1A:45:4A:EA:39 Jabra BT125
#
How to make aplay can use that device?
Thanks a lot.
--
Regards,
--Bob
^ permalink raw reply
* [PATCH] bluetooth: remove unnecessary call to hci_sock_cleanup
From: Anand Gadiyar @ 2011-02-22 7:13 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anand Gadiyar, Gustavo F. Padovan
hci_sock_cleanup is already called after the sock_err label.
It appears that we can drop this call.
Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
Cc: Gustavo F. Padovan <padovan@profusion.mobi>
---
net/bluetooth/af_bluetooth.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
Index: linux-omap-usb/net/bluetooth/af_bluetooth.c
===================================================================
--- linux-omap-usb.orig/net/bluetooth/af_bluetooth.c
+++ linux-omap-usb/net/bluetooth/af_bluetooth.c
@@ -550,10 +550,8 @@ static int __init bt_init(void)
goto error;
err = l2cap_init();
- if (err < 0) {
- hci_sock_cleanup();
+ if (err < 0)
goto sock_err;
- }
err = sco_init();
if (err < 0) {
^ permalink raw reply
* [PATCH -next] bluetooth: fix build break
From: Anand Gadiyar @ 2011-02-22 7:13 UTC (permalink / raw)
To: linux-bluetooth, linux-next; +Cc: Anand Gadiyar, Gustavo F. Padovan
Linux-next as of 20110217 complains when building for OMAP1.
LD vmlinux
`hci_sock_cleanup' referenced in section `.init.text' of net/built-in.o: defined in discarded section `.exit.text' of net/built-in.o
`hci_sock_cleanup' referenced in section `.init.text' of net/built-in.o: defined in discarded section `.exit.text' of net/built-in.o
make: *** [vmlinux] Error 1
A recent patch by Gustavo (Bluetooth: Merge L2CAP and SCO modules
into bluetooth.ko) introduced this by calling the hci_sock_cleanup
function in the error path of bt_init.
Fix this by dropping the __exit marking for hci_sock_cleanup.
Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
Cc: Gustavo F. Padovan <padovan@profusion.mobi>
---
net/bluetooth/hci_sock.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: linux-omap-usb/net/bluetooth/hci_sock.c
===================================================================
--- linux-omap-usb.orig/net/bluetooth/hci_sock.c
+++ linux-omap-usb/net/bluetooth/hci_sock.c
@@ -861,7 +861,7 @@ error:
return err;
}
-void __exit hci_sock_cleanup(void)
+void hci_sock_cleanup(void)
{
if (bt_sock_unregister(BTPROTO_HCI) < 0)
BT_ERR("HCI socket unregistration failed");
^ permalink raw reply
* [PATCH 7/7] Add Write Request in interactive gatttool
From: Sheldon Demario @ 2011-02-21 22:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1298328606-7993-1-git-send-email-sheldon.demario@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
---
attrib/interactive.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index e9d74b9..30e9f60 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -482,6 +482,51 @@ static void cmd_read_uuid(int argcp, char **argvp)
return;
}
+static void char_write_req_cb(guint8 status, const guint8 *pdu, guint16 plen,
+ gpointer user_data)
+{
+ if (status != 0) {
+ printf("Characteristic Write Request failed: "
+ "%s\n", att_ecode2str(status));
+ return;
+ }
+
+ if (!dec_write_resp(pdu, plen)) {
+ printf("Protocol error\n");
+ return;
+ }
+
+ printf("Characteristic value was written successfully\n");
+}
+
+static void cmd_char_write_req(int argcp, char **argvp)
+{
+ uint8_t *value;
+ size_t plen;
+ int handle;
+
+ if (argcp < 3) {
+ printf("Usage: char-write-req <handle> <new value>\n");
+ return;
+ }
+
+ handle = strtoll(argvp[1], NULL, 16);
+ if (errno != 0 || handle <= 0) {
+ printf("A valid handle is required\n");
+ return;
+ }
+
+ plen = gatt_attr_data_from_string(argvp[2], &value);
+ if (plen == 0) {
+ g_printerr("Invalid value\n");
+ return;
+ }
+
+ gatt_write_char(attrib, handle, value, plen, char_write_req_cb, NULL);
+
+ g_free(value);
+}
+
static struct {
const char *cmd;
void (*func)(int argcp, char **argvp);
@@ -506,6 +551,8 @@ static struct {
"Characteristics Value/Descriptor Read by handle" },
{ "char-read-uuid", cmd_read_uuid, "<UUID> [start hnd] [end hnd]",
"Characteristics Value/Descriptor Read by UUID" },
+ { "char-write-req", cmd_char_write_req, "<handle> <new value>",
+ "Characteristic Value Write (Write Request)"},
{ NULL, NULL, NULL}
};
--
1.7.1
^ permalink raw reply related
* [PATCH 6/7] Move attr_data_from_string() to utils.c
From: Sheldon Demario @ 2011-02-21 22:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Bruna Moreira
In-Reply-To: <1298328606-7993-1-git-send-email-sheldon.demario@openbossa.org>
From: Bruna Moreira <bruna.moreira@openbossa.org>
The attr_data_from_string() function will be used in interactive and
usual gatttool so this function was moved to common file utils.c.
---
attrib/gatttool.c | 23 ++---------------------
attrib/gatttool.h | 1 +
attrib/utils.c | 19 +++++++++++++++++++
3 files changed, 22 insertions(+), 21 deletions(-)
diff --git a/attrib/gatttool.c b/attrib/gatttool.c
index 7478043..d7887c6 100644
--- a/attrib/gatttool.c
+++ b/attrib/gatttool.c
@@ -313,25 +313,6 @@ static gboolean characteristics_read(gpointer user_data)
return FALSE;
}
-static size_t attr_data_from_string(const char *str, uint8_t **data)
-{
- char tmp[3];
- size_t size, i;
-
- size = strlen(str) / 2;
- *data = g_try_malloc0(size);
- if (*data == NULL)
- return 0;
-
- tmp[2] = '\0';
- for (i = 0; i < size; i++) {
- memcpy(tmp, str + (i * 2), 2);
- (*data)[i] = (uint8_t) strtol(tmp, NULL, 16);
- }
-
- return size;
-}
-
static void mainloop_quit(gpointer user_data)
{
uint8_t *value = user_data;
@@ -356,7 +337,7 @@ static gboolean characteristics_write(gpointer user_data)
goto error;
}
- len = attr_data_from_string(opt_value, &value);
+ len = gatt_attr_data_from_string(opt_value, &value);
if (len == 0) {
g_printerr("Invalid value\n");
goto error;
@@ -408,7 +389,7 @@ static gboolean characteristics_write_req(gpointer user_data)
goto error;
}
- len = attr_data_from_string(opt_value, &value);
+ len = gatt_attr_data_from_string(opt_value, &value);
if (len == 0) {
g_printerr("Invalid value\n");
goto error;
diff --git a/attrib/gatttool.h b/attrib/gatttool.h
index 7eae18d..2fd4a46 100644
--- a/attrib/gatttool.h
+++ b/attrib/gatttool.h
@@ -25,3 +25,4 @@ int interactive(gchar *dst, gboolean le);
GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
const gchar *sec_level, int psm, int mtu,
BtIOConnect connect_cb);
+size_t gatt_attr_data_from_string(const char *str, uint8_t **data);
diff --git a/attrib/utils.c b/attrib/utils.c
index 4d0000d..8d1ca74 100644
--- a/attrib/utils.c
+++ b/attrib/utils.c
@@ -104,3 +104,22 @@ GIOChannel *gatt_connect(const gchar *src, const gchar *dst,
return chan;
}
+
+size_t gatt_attr_data_from_string(const char *str, uint8_t **data)
+{
+ char tmp[3];
+ size_t size, i;
+
+ size = strlen(str) / 2;
+ *data = g_try_malloc0(size);
+ if (*data == NULL)
+ return 0;
+
+ tmp[2] = '\0';
+ for (i = 0; i < size; i++) {
+ memcpy(tmp, str + (i * 2), 2);
+ (*data)[i] = (uint8_t) strtol(tmp, NULL, 16);
+ }
+
+ return size;
+}
--
1.7.1
^ permalink raw reply related
* [PATCH 5/7] Add characteristics read options in interactive gatttool
From: Sheldon Demario @ 2011-02-21 22:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <1298328606-7993-1-git-send-email-sheldon.demario@openbossa.org>
---
attrib/interactive.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 141 insertions(+), 1 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 9389686..e9d74b9 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -50,6 +50,13 @@ static gchar *opt_sec_level = NULL;
static int opt_psm = 0;
static int opt_mtu = 0;
+struct characteristic_data {
+ uint16_t orig_start;
+ uint16_t start;
+ uint16_t end;
+ uuid_t uuid;
+};
+
static void cmd_help(int argcp, char **argvp);
enum state {
@@ -210,6 +217,79 @@ static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
rl_forced_update_display();
}
+static void char_read_cb(guint8 status, const guint8 *pdu, guint16 plen,
+ gpointer user_data)
+{
+ uint8_t value[ATT_MAX_MTU];
+ int i, vlen;
+
+ if (status != 0) {
+ printf("Characteristic value/descriptor read failed: %s\n",
+ att_ecode2str(status));
+ return;
+ }
+
+ if (!dec_read_resp(pdu, plen, value, &vlen)) {
+ printf("Protocol error\n");
+ return;
+ }
+
+ printf("\nCharacteristic value/descriptor: ");
+ for (i = 0; i < vlen; i++)
+ printf("%02x ", value[i]);
+ printf("\n");
+
+ rl_forced_update_display();
+}
+
+static void char_read_by_uuid_cb(guint8 status, const guint8 *pdu,
+ guint16 plen, gpointer user_data)
+{
+ struct characteristic_data *char_data = user_data;
+ struct att_data_list *list;
+ int i;
+
+ if (status == ATT_ECODE_ATTR_NOT_FOUND &&
+ char_data->start != char_data->orig_start)
+ goto done;
+
+ if (status != 0) {
+ printf("Read characteristics by UUID failed: %s\n",
+ att_ecode2str(status));
+ goto done;
+ }
+
+ list = dec_read_by_type_resp(pdu, plen);
+ if (list == NULL)
+ goto done;
+
+ for (i = 0; i < list->num; i++) {
+ uint8_t *value = list->data[i];
+ int j;
+
+ char_data->start = att_get_u16(value) + 1;
+
+ printf("\nhandle: 0x%04x \t value: ", att_get_u16(value));
+ value += 2;
+ for (j = 0; j < list->len - 2; j++, value++)
+ printf("%02x ", *value);
+ printf("\n");
+ }
+
+ att_data_list_free(list);
+
+ gatt_read_char_by_uuid(attrib, char_data->start, char_data->end,
+ &char_data->uuid, char_read_by_uuid_cb,
+ char_data);
+
+ rl_forced_update_display();
+
+ return;
+
+done:
+ g_free(char_data);
+}
+
static void cmd_exit(int argcp, char **argvp)
{
rl_callback_handler_remove();
@@ -346,6 +426,62 @@ static void cmd_char_desc(int argcp, char **argvp)
return;
}
+static void cmd_read_hnd(int argcp, char **argvp)
+{
+ int handle;
+
+ if (argcp < 2) {
+ printf("Missing argument: handle\n");
+ return;
+ }
+
+ if (strtohandle(&handle, argvp[1])) {
+ printf("Invalid handle: %s\n", argvp[1]);
+ return;
+ }
+
+ gatt_read_char(attrib, handle, char_read_cb, attrib);
+
+ return;
+}
+
+static void cmd_read_uuid(int argcp, char **argvp)
+{
+ struct characteristic_data *char_data;
+ int start = 0x0001;
+ int end = 0xffff;
+ uuid_t uuid;
+
+ if (conn_state != STATE_CONNECTED) {
+ printf("Command failed: disconnected\n");
+ return;
+ }
+
+ if (argcp < 2) {
+ printf("Missing argument: UUID\n");
+ return;
+ }
+
+ if (bt_string2uuid(&uuid, argvp[1]) < 0) {
+ printf("Invalid UUID\n");
+ return;
+ }
+
+ if (set_handles(&start, &end, argcp - 1, argvp + 1))
+ return;
+
+ char_data = g_new(struct characteristic_data, 1);
+ char_data->orig_start = start;
+ char_data->start = start;
+ char_data->end = end;
+ char_data->uuid = uuid;
+
+ gatt_read_char_by_uuid(attrib, start, end, &char_data->uuid,
+ char_read_by_uuid_cb, char_data);
+
+ return;
+}
+
static struct {
const char *cmd;
void (*func)(int argcp, char **argvp);
@@ -366,6 +502,10 @@ static struct {
"Characteristics Discovery" },
{ "char-desc", cmd_char_desc, "[start hnd] [end hnd]",
"Characteristics Descriptor Discovery" },
+ { "char-read-hnd", cmd_read_hnd, "<handle>",
+ "Characteristics Value/Descriptor Read by handle" },
+ { "char-read-uuid", cmd_read_uuid, "<UUID> [start hnd] [end hnd]",
+ "Characteristics Value/Descriptor Read by UUID" },
{ NULL, NULL, NULL}
};
@@ -374,7 +514,7 @@ static void cmd_help(int argcp, char **argvp)
int i;
for (i = 0; commands[i].cmd; i++)
- printf("%-15s %-25s %s\n", commands[i].cmd,
+ printf("%-15s %-30s %s\n", commands[i].cmd,
commands[i].params, commands[i].desc);
}
--
1.7.1
^ permalink raw reply related
* [PATCH 4/7] Add Characteristics Descriptor Discovery option in interactive gatttool
From: Sheldon Demario @ 2011-02-21 22:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <1298328606-7993-1-git-send-email-sheldon.demario@openbossa.org>
---
attrib/interactive.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index e9f6019..9389686 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -169,6 +169,47 @@ static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
rl_forced_update_display();
}
+static void char_desc_cb(guint8 status, const guint8 *pdu, guint16 plen,
+ gpointer user_data)
+{
+ struct att_data_list *list;
+ guint8 format;
+ int i;
+
+ if (status != 0) {
+ printf("Discover all characteristic descriptors failed: "
+ "%s\n", att_ecode2str(status));
+ return;
+ }
+
+ list = dec_find_info_resp(pdu, plen, &format);
+ if (list == NULL)
+ return;
+
+ printf("\n");
+ for (i = 0; i < list->num; i++) {
+ char uuidstr[MAX_LEN_UUID_STR];
+ uint16_t handle;
+ uint8_t *value;
+ uuid_t uuid;
+
+ value = list->data[i];
+ handle = att_get_u16(value);
+
+ if (format == 0x01)
+ sdp_uuid16_create(&uuid, att_get_u16(&value[2]));
+ else
+ sdp_uuid128_create(&uuid, &value[2]);
+
+ sdp_uuid2strn(&uuid, uuidstr, MAX_LEN_UUID_STR);
+ printf("handle: 0x%04x, uuid: %s\n", handle, uuidstr);
+ }
+
+ att_data_list_free(list);
+
+ rl_forced_update_display();
+}
+
static void cmd_exit(int argcp, char **argvp)
{
rl_callback_handler_remove();
@@ -287,6 +328,24 @@ static void cmd_char(int argcp, char **argvp)
return;
}
+static void cmd_char_desc(int argcp, char **argvp)
+{
+ int start = 0x0001;
+ int end = 0xffff;
+
+ if (conn_state != STATE_CONNECTED) {
+ printf("Command failed: disconnected\n");
+ return;
+ }
+
+ if (set_handles(&start, &end, argcp, argvp))
+ return;
+
+ gatt_find_info(attrib, start, end, char_desc_cb, NULL);
+
+ return;
+}
+
static struct {
const char *cmd;
void (*func)(int argcp, char **argvp);
@@ -305,6 +364,8 @@ static struct {
"Primary Service Discovery" },
{ "characteristics", cmd_char, "[start hnd] [end hnd]",
"Characteristics Discovery" },
+ { "char-desc", cmd_char_desc, "[start hnd] [end hnd]",
+ "Characteristics Descriptor Discovery" },
{ NULL, NULL, NULL}
};
--
1.7.1
^ permalink raw reply related
* [PATCH 3/7] Create helper functions to deal with handles on interactive gatttool
From: Sheldon Demario @ 2011-02-21 22:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <1298328606-7993-1-git-send-email-sheldon.demario@openbossa.org>
---
attrib/interactive.c | 46 ++++++++++++++++++++++++++++++----------------
1 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 7cc03bc..e9f6019 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -238,36 +238,50 @@ static void cmd_primary(int argcp, char **argvp)
gatt_discover_primary(attrib, &uuid, primary_by_uuid_cb, NULL);
}
-static void cmd_char(int argcp, char **argvp)
+static int strtohandle(int *dst, const char *src)
{
- int start = 0x0001;
- int end = 0xffff;
+ char *e;
- if (conn_state != STATE_CONNECTED) {
- printf("Command failed: disconnected\n");
- return;
+ *dst = strtoll(src, &e, 16);
+ if (errno != 0 || *e != '\0') {
+ return -1;
}
- if (argcp > 1) {
- char *e;
+ return 0;
+}
- start = strtoll(argvp[1], &e, 16);
- if (errno != 0 || *e != '\0') {
+static int set_handles(int *start, int *end, int argcp, char **argvp)
+{
+ if (argcp > 1) {
+ if (strtohandle(start, argvp[1])) {
printf("Invalid start handle: %s\n", argvp[1]);
- return;
+ return -1;
}
}
if (argcp > 2) {
- char *e;
-
- end = strtoll(argvp[2], &e, 16);
- if (errno != 0 || *e != '\0') {
+ if (strtohandle(end, argvp[2])) {
printf("Invalid end handle: %s\n", argvp[2]);
- return;
+ return -1;
}
}
+ return 0;
+}
+
+static void cmd_char(int argcp, char **argvp)
+{
+ int start = 0x0001;
+ int end = 0xffff;
+
+ if (conn_state != STATE_CONNECTED) {
+ printf("Command failed: disconnected\n");
+ return;
+ }
+
+ if (set_handles(&start, &end, argcp, argvp))
+ return;
+
gatt_discover_char(attrib, start, end, char_cb, NULL);
return;
--
1.7.1
^ permalink raw reply related
* [PATCH 2/7] Add Characteristics Discovery option to interactive gatttool
From: Sheldon Demario @ 2011-02-21 22:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <1298328606-7993-1-git-send-email-sheldon.demario@openbossa.org>
---
attrib/interactive.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index b491314..7cc03bc 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -22,6 +22,7 @@
*/
#include <string.h>
#include <stdlib.h>
+#include <errno.h>
#include <stdio.h>
#include <glib.h>
@@ -145,6 +146,29 @@ static void primary_by_uuid_cb(GSList *ranges, guint8 status,
rl_forced_update_display();
}
+static void char_cb(GSList *characteristics, guint8 status, gpointer user_data)
+{
+ GSList *l;
+
+ if (status) {
+ printf("Discover all characteristics failed: %s\n",
+ att_ecode2str(status));
+ return;
+ }
+
+ printf("\n");
+ for (l = characteristics; l; l = l->next) {
+ struct att_char *chars = l->data;
+
+ printf("handle: 0x%04x, char properties: 0x%02x, char value "
+ "handle: 0x%04x, uuid: %s\n", chars->handle,
+ chars->properties, chars->value_handle,
+ chars->uuid);
+ }
+
+ rl_forced_update_display();
+}
+
static void cmd_exit(int argcp, char **argvp)
{
rl_callback_handler_remove();
@@ -214,6 +238,41 @@ static void cmd_primary(int argcp, char **argvp)
gatt_discover_primary(attrib, &uuid, primary_by_uuid_cb, NULL);
}
+static void cmd_char(int argcp, char **argvp)
+{
+ int start = 0x0001;
+ int end = 0xffff;
+
+ if (conn_state != STATE_CONNECTED) {
+ printf("Command failed: disconnected\n");
+ return;
+ }
+
+ if (argcp > 1) {
+ char *e;
+
+ start = strtoll(argvp[1], &e, 16);
+ if (errno != 0 || *e != '\0') {
+ printf("Invalid start handle: %s\n", argvp[1]);
+ return;
+ }
+ }
+
+ if (argcp > 2) {
+ char *e;
+
+ end = strtoll(argvp[2], &e, 16);
+ if (errno != 0 || *e != '\0') {
+ printf("Invalid end handle: %s\n", argvp[2]);
+ return;
+ }
+ }
+
+ gatt_discover_char(attrib, start, end, char_cb, NULL);
+
+ return;
+}
+
static struct {
const char *cmd;
void (*func)(int argcp, char **argvp);
@@ -230,6 +289,8 @@ static struct {
"Disconnect from a remote device" },
{ "primary", cmd_primary, "[UUID]",
"Primary Service Discovery" },
+ { "characteristics", cmd_char, "[start hnd] [end hnd]",
+ "Characteristics Discovery" },
{ NULL, NULL, NULL}
};
--
1.7.1
^ permalink raw reply related
* [PATCH 1/7] Improve help messages in interactive gatttool
From: Sheldon Demario @ 2011-02-21 22:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
Includes the parameters info on help.
---
attrib/interactive.c | 19 +++++++++++++------
1 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index edc465a..b491314 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -217,13 +217,19 @@ static void cmd_primary(int argcp, char **argvp)
static struct {
const char *cmd;
void (*func)(int argcp, char **argvp);
+ const char *params;
const char *desc;
} commands[] = {
- { "help", cmd_help, "Show this help"},
- { "exit", cmd_exit, "Exit interactive mode"},
- { "connect", cmd_connect, "Connect to a remote device"},
- { "disconnect", cmd_disconnect, "Disconnect from a remote device"},
- { "primary", cmd_primary, "Primary Service Discovery"},
+ { "help", cmd_help, "",
+ "Show this help"},
+ { "exit", cmd_exit, "",
+ "Exit interactive mode" },
+ { "connect", cmd_connect, "[address]",
+ "Connect to a remote device" },
+ { "disconnect", cmd_disconnect, "",
+ "Disconnect from a remote device" },
+ { "primary", cmd_primary, "[UUID]",
+ "Primary Service Discovery" },
{ NULL, NULL, NULL}
};
@@ -232,7 +238,8 @@ static void cmd_help(int argcp, char **argvp)
int i;
for (i = 0; commands[i].cmd; i++)
- printf("%-12s\t%s\n", commands[i].cmd, commands[i].desc);
+ printf("%-15s %-25s %s\n", commands[i].cmd,
+ commands[i].params, commands[i].desc);
}
static void parse_line(char *line_read)
--
1.7.1
^ permalink raw reply related
* Re: [RESEND] ID_SERIAL for udev bluetooth joystick events
From: Antonio Ospite @ 2011-02-21 22:45 UTC (permalink / raw)
To: linux-hotplug; +Cc: linux-input, linux-bluetooth
In-Reply-To: <20110210114204.9639661d.ospite@studenti.unina.it>
[-- Attachment #1: Type: text/plain, Size: 7507 bytes --]
On Thu, 10 Feb 2011 11:42:04 +0100
Antonio Ospite <ospite@studenti.unina.it> wrote:
> Hi,
>
> I have a question about udev events generated by a bluetooth joystick:
> when udev generates the joystick event for a bt joystick, the ID_SERIAL
> property matches the one of the bt adapter not the one of the joystick.
>
Ok, now I have a clearer picture of what udev does when I connect the
joystick and I can pose better questions.
> For example (using "udevadm monitor --property"), when connecting the
> Sony Sixaxis via usb I get:
> ID_SERIAL=Sony_PLAYSTATION_R_3_Controller
> in the input and joystick events, but when I connect it via bt, I get:
> ID_SERIAL=Broadcom_Corp_ANYCOM_Blue_USB-200_250
> which matches my bluetooth adapter.
>
This happens because /lib/udev/usb_id goes up to the usb device when
creating the event for bt input devices connected to a btusb dongle.
> Some insight of what I am trying to achieve with udev:
> 1. Monitor new joystick devices.
> 2. If ID_SERIAL != Sony_PLAYSTATION_R_3_Controller, then STOP.
> 3. Get the associated hidraw device node navigating the event tree.
> 4. Set leds using the value from the ID_INPUT_JOYSTICK property.
This is wrong, /lib/udev/input_id hardcodes a '1' as value there, I
thought it was the index of the joystick like in:
1 -> js0
2 -> js1
but it is not, ID_INPUT_JOYSTICK=1 means just "this is a joystick", so
I think I have to parse the DEVNAME (dev/jsX) to get the actual index,
right?
> 5. If ID_USB_DRIVER=usbhid do the needed pairing.
>
> And with the current behaviour for ID_SERIAL I cannot enforce 2.
> I could listen for the (hid) event and use HID_NAME which seems to be a
> little more consistent:
> usb -> HID_NAME=Sony PLAYSTATION(R)3 Controller
> bt -> HID_NAME=PLAYSTATION(R)3 Controller
> and navigate the event hierarchy to get ID_INPUT_JOYSTICK, but that is
> slightly more complicated, and I am curious about the ID_SERIAL
> behavior anyways :)
>
Maybe I'd still better monitor the 'input' event and move up and down
from here to collect the joystick index and the hidraw device node, but
I wonder if a patch along these lines (this is just for the sake of
discussion) could have sense to prevent exposing the dongle properties
also for the input devices:
diff --git a/extras/usb_id/usb_id.c b/extras/usb_id/usb_id.c
index fabd092..8e6e20f 100644
--- a/extras/usb_id/usb_id.c
+++ b/extras/usb_id/usb_id.c
@@ -56,6 +56,7 @@ static char serial_str[UTIL_NAME_SIZE];
static char packed_if_str[UTIL_NAME_SIZE];
static char revision_str[64];
static char type_str[64];
+static char bustype_str[64];
static char instance_str[64];
static const char *ifnum;
static const char *driver;
@@ -147,6 +148,29 @@ static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len
return type_num;
}
+static int set_usb_input_bustype(char *to, const char *from, size_t len)
+{
+ int bustype_num = 0;
+ char *eptr;
+ char *type = "unknown";
+
+ bustype_num = strtoul(from, &eptr, 0);
+ if (eptr != from) {
+ switch (bustype_num) {
+ case 3:
+ type = "usb";
+ break;
+ case 5:
+ type = "bluetooth";
+ break;
+ default:
+ break;
+ }
+ }
+ util_strscpy(to, len, type);
+ return bustype_num;
+}
+
static void set_scsi_type(char *to, const char *from, size_t len)
{
int type_num;
@@ -312,8 +336,8 @@ static int usb_id(struct udev_device *dev)
set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1);
}
- info(udev, "%s: if_class %d protocol %d\n",
- udev_device_get_syspath(dev_interface), if_class_num, protocol);
+ info(udev, "%s: if_class %d protocol %d type_str: %s\n",
+ udev_device_get_syspath(dev_interface), if_class_num, protocol, type_str);
/* usb device directory */
dev_usb = udev_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device");
@@ -326,6 +350,57 @@ static int usb_id(struct udev_device *dev)
/* all interfaces of the device in a single string */
dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str));
+ /* input device XXX this check is not right, we might use a dev_input
+ * as below */
+ if ((protocol == 0) && !use_usb_info) {
+ struct udev_device *dev_input;
+ const char *input_vendor, *input_model, *input_rev, *input_bustype;
+
+ /* get input device */
+ dev_input = udev_device_get_parent_with_subsystem_devtype(dev, "input", NULL);
+ if (dev_input == NULL) {
+ info(udev, "unable to find parent 'input' device of '%s'\n",
+ udev_device_get_syspath(dev));
+ goto fallback;
+ }
+
+ input_vendor = udev_device_get_sysattr_value(dev_input, "id/vendor");
+ if (!input_vendor) {
+ info(udev, "%s: cannot get input vendor attribute\n",
+ udev_device_get_sysname(dev_input));
+ goto fallback;
+ }
+ udev_util_encode_string(input_vendor, vendor_str_enc, sizeof(vendor_str_enc));
+ udev_util_replace_whitespace(input_vendor, vendor_str, sizeof(vendor_str)-1);
+ udev_util_replace_chars(vendor_str, NULL);
+
+ vendor_id = input_vendor;
+ product_id = udev_device_get_sysattr_value(dev_input, "id/product");
+
+ input_model = udev_device_get_sysattr_value(dev_input, "name");
+ if (!input_model) {
+ info(udev, "%s: cannot get input model attribute\n",
+ udev_device_get_sysname(dev_input));
+ goto fallback;
+ }
+ udev_util_encode_string(input_model, model_str_enc, sizeof(model_str_enc));
+ udev_util_replace_whitespace(input_model, model_str, sizeof(model_str)-1);
+ udev_util_replace_chars(model_str, NULL);
+
+ input_rev = udev_device_get_sysattr_value(dev_input, "id/version");
+ if (!input_rev) {
+ info(udev, "%s: cannot get input revision attribute\n",
+ udev_device_get_sysname(dev_input));
+ goto fallback;
+ }
+ udev_util_replace_whitespace(input_rev, revision_str, sizeof(revision_str)-1);
+ udev_util_replace_chars(revision_str, NULL);
+
+ /* get Bus type, see BUS_* in linux/input.h */
+ input_bustype = udev_device_get_sysattr_value(dev_input, "id/bustype");
+ set_usb_input_bustype(bustype_str, input_bustype, sizeof(bustype_str) - 1 );
+ }
+
/* mass storage : SCSI or ATAPI */
if ((protocol == 6 || protocol == 2) && !use_usb_info) {
struct udev_device *dev_scsi;
@@ -390,8 +465,12 @@ static int usb_id(struct udev_device *dev)
}
fallback:
- vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor");
- product_id = udev_device_get_sysattr_value(dev_usb, "idProduct");
+ if (vendor_id[0] == '\0') {
+ vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor");
+ }
+ if (product_id[0] == '\0') {
+ product_id = udev_device_get_sysattr_value(dev_usb, "idProduct");
+ }
/* fallback to USB vendor & device */
if (vendor_str[0] == '\0') {
@@ -559,7 +638,7 @@ int main(int argc, char **argv)
printf("ID_TYPE=%s\n", type_str);
if (instance_str[0] != '\0')
printf("ID_INSTANCE=%s\n", instance_str);
- printf("ID_BUS=usb\n");
+ printf("ID_BUS=%s\n", (bustype_str[0] == '\0') ? "usb" : bustype_str);
if (packed_if_str[0] != '\0')
printf("ID_USB_INTERFACES=:%s\n", packed_if_str);
if (ifnum != NULL)
Thanks,
Antonio
--
Antonio Ospite
http://ao2.it
PGP public key ID: 0x4553B001
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
[-- Attachment #2: Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply related
* [PATCH] Bluetooth: Add support for LE Start Encryption
From: Vinicius Costa Gomes @ 2011-02-21 21:52 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Vinicius Costa Gomes
In-Reply-To: <d1a61c8a902cd0380e097701332c0a4975a972be.1298307667.git.vinicius.gomes@openbossa.org>
This adds support for starting SMP Phase 2 Encryption, when the initial
SMP negotiation is successful. This adds the LE Start Encryption and LE
Long Term Key Request commands and related events.
Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org>
---
Now this should apply cleanly after Johan's patches now in bluetooth-next.
include/net/bluetooth/hci.h | 34 +++++++++++++++++++
include/net/bluetooth/hci_core.h | 5 +++
net/bluetooth/hci_conn.c | 46 ++++++++++++++++++++++++++
net/bluetooth/hci_event.c | 67 ++++++++++++++++++++++++++++++++++++++
net/bluetooth/smp.c | 9 ++++-
5 files changed, 160 insertions(+), 1 deletions(-)
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index ec6acf2..d851f8b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -699,6 +699,33 @@ struct hci_cp_le_conn_update {
__le16 max_ce_len;
} __packed;
+#define HCI_OP_LE_START_ENC 0x2019
+struct hci_cp_le_start_enc {
+ __le16 handle;
+ __u8 rand[8];
+ __le16 ediv;
+ __u8 ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY 0x201a
+struct hci_cp_le_ltk_reply {
+ __le16 handle;
+ __u8 ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY 0x201b
+struct hci_cp_le_ltk_neg_reply {
+ __le16 handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+ __u8 status;
+ __le16 handle;
+} __packed;
+
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
@@ -984,6 +1011,13 @@ struct hci_ev_le_conn_complete {
__u8 clk_accurancy;
} __packed;
+#define HCI_EV_LE_LTK_REQ 0x05
+struct hci_ev_le_ltk_req {
+ __le16 handle;
+ __u8 random[8];
+ __le16 ediv;
+} __packed;
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index cf33856..e049d0e 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -226,6 +226,7 @@ struct hci_conn {
__u8 power_save;
__u16 disc_timeout;
unsigned long pend;
+ __u8 ltk[16];
__u8 remote_cap;
__u8 remote_oob;
@@ -802,4 +803,8 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
u16 latency, u16 to_multiplier);
+void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
#endif /* __HCI_CORE_H */
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 4504cb6..5f0844d 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -203,6 +203,52 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
}
EXPORT_SYMBOL(hci_le_conn_update);
+void hci_le_start_enc(struct hci_conn *conn, u8 ltk[16])
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_start_enc cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, ltk, sizeof(cp.ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_start_enc);
+
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_ltk_reply cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, ltk, sizeof(ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_reply);
+
+void hci_le_ltk_neg_reply(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+ struct hci_cp_le_ltk_neg_reply cp;
+
+ BT_DBG("%p", conn);
+
+ memset(&cp, 0, sizeof(cp));
+
+ cp.handle = cpu_to_le16(conn->handle);
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
+}
+
/* Device _must_ be locked */
void hci_sco_setup(struct hci_conn *conn, __u8 status)
{
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 3fbfa50..8c6cafa 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -819,6 +819,30 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
rp->status);
}
+static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
+}
+
+static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
+}
+
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1186,6 +1210,11 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
+static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
+{
+ BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -1761,6 +1790,14 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_cc_user_confirm_neg_reply(hdev, skb);
break;
+ case HCI_OP_LE_LTK_REPLY:
+ hci_cc_le_ltk_reply(hdev, skb);
+ break;
+
+ case HCI_OP_LE_LTK_NEG_REPLY:
+ hci_cc_le_ltk_neg_reply(hdev, skb);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -1839,6 +1876,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_cs_le_create_conn(hdev, ev->status);
break;
+ case HCI_OP_LE_START_ENC:
+ hci_cs_le_start_enc(hdev, ev->status);
+ break;
+
default:
BT_DBG("%s opcode 0x%x", hdev->name, opcode);
break;
@@ -2491,6 +2532,28 @@ unlock:
hci_dev_unlock(hdev);
}
+static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+ struct hci_cp_le_ltk_reply cp;
+ struct hci_conn *conn;
+
+ BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+
+ memset(&cp, 0, sizeof(cp));
+ cp.handle = cpu_to_le16(conn->handle);
+ memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk));
+
+ hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+
+ hci_dev_unlock(hdev);
+}
+
static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2502,6 +2565,10 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_conn_complete_evt(hdev, skb);
break;
+ case HCI_EV_LE_LTK_REQ:
+ hci_le_ltk_request_evt(hdev, skb);
+ break;
+
default:
break;
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 52241fd..6d32bcc 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -280,13 +280,16 @@ static void smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb
static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
{
- struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+ struct hci_conn *hcon = conn->hcon;
+ struct crypto_blkcipher *tfm = hcon->hdev->tfm;
int ret;
u8 key[16], res[16], random[16], confirm[16], buf[128];
swap128(skb->data, random);
skb_pull(skb, sizeof(random));
+ memset(hcon->ltk, 0, sizeof(hcon->ltk));
+
if (conn->hcon->out)
ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
conn->src, 0, conn->dst, res);
@@ -311,6 +314,9 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (conn->hcon->out) {
smp_s1(tfm, conn->tk, random, conn->prnd, key);
+ swap128(key, hcon->ltk);
+
+ hci_le_start_enc(hcon, hcon->ltk);
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
BT_DBG("key %s", buf);
@@ -321,6 +327,7 @@ static void smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
smp_s1(tfm, conn->tk, conn->prnd, random, key);
+ swap128(key, hcon->ltk);
hex_dump_to_buffer(key, sizeof(key), 16, 1, buf, sizeof(buf), 0);
BT_DBG("key %s", buf);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 5/5] Implement ATT handle indication
From: Anderson Lizardo @ 2011-02-21 21:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Elvis Pfützenreuter
In-Reply-To: <1298323843-31106-1-git-send-email-anderson.lizardo@openbossa.org>
From: Elvis Pfützenreuter <epx@signove.com>
---
src/attrib-server.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 585e1f3..ccb4228 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -59,6 +59,8 @@ struct gatt_channel {
guint mtu;
guint id;
gboolean encrypted;
+ guint outstanding_indications;
+ time_t oldest_indication;
};
struct group_elem {
@@ -885,6 +887,10 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
length = find_by_type(start, end, &uuid, value, vlen,
opdu, channel->mtu);
break;
+ case ATT_OP_HANDLE_CNF:
+ if (channel->outstanding_indications)
+ channel->outstanding_indications -= 1;
+ return;
case ATT_OP_READ_MULTI_REQ:
case ATT_OP_PREP_WRITE_REQ:
case ATT_OP_EXEC_WRITE_REQ:
@@ -964,10 +970,14 @@ static void confirm_event(GIOChannel *io, void *user_data)
static void attrib_notify_clients(struct attribute *attr)
{
uint8_t pdu[ATT_MAX_MTU];
+ uint8_t pdu_ind[ATT_MAX_MTU];
guint mtu, handle = attr->handle;
- uint16_t len;
+ uint16_t len, len_ind;
+ time_t now;
GSList *l;
+ time(&now);
+
for (l = clients, mtu = 0, len = 0; l; l = l->next) {
struct gatt_channel *channel = l->data;
@@ -985,6 +995,34 @@ static void attrib_notify_clients(struct attribute *attr)
g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
NULL, NULL, NULL);
}
+
+ /* The outstanding_indications variable counts how many
+ * unconfirmed indications have been sent. The oldest_indication
+ * variable gives a small time frame to accomodate
+ * almost-concomitant indications, sending both without forcing
+ * a serialization.
+ *
+ * Indications are withheld once oldest_indication is older than
+ * at least 1 second and there are pending confirmations. */
+
+ if (channel->outstanding_indications &&
+ (now - channel->oldest_indication) > 1)
+ continue;
+
+ /* Indication */
+ if (g_slist_find_custom(channel->indicate,
+ GUINT_TO_POINTER(handle), handle_cmp) != NULL) {
+ len_ind = enc_indication(attr, pdu_ind, mtu);
+ if (len_ind == 0)
+ return;
+
+ g_attrib_send(channel->attrib, 0, pdu_ind[0], pdu_ind,
+ len_ind, NULL, NULL, NULL);
+
+ channel->outstanding_indications += 1;
+ if (channel->outstanding_indications == 1)
+ channel->oldest_indication = now;
+ }
}
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH 4/5] Implement server-side ATT handle notification
From: Anderson Lizardo @ 2011-02-21 21:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andre Dieb Martins
In-Reply-To: <1298323843-31106-1-git-send-email-anderson.lizardo@openbossa.org>
From: Andre Dieb Martins <andre.dieb@signove.com>
Adds an initial version of ATT handle notification. Notifications are sent to
interested clients (based on the Client Characteristic Configuration) always
when the attribute is updated.
This enables services to call db_attrib_update() and send notifications on their
own terms.
---
src/attrib-server.c | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 5675a1b..585e1f3 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -961,6 +961,33 @@ static void confirm_event(GIOChannel *io, void *user_data)
return;
}
+static void attrib_notify_clients(struct attribute *attr)
+{
+ uint8_t pdu[ATT_MAX_MTU];
+ guint mtu, handle = attr->handle;
+ uint16_t len;
+ GSList *l;
+
+ for (l = clients, mtu = 0, len = 0; l; l = l->next) {
+ struct gatt_channel *channel = l->data;
+
+ mtu = channel->mtu;
+ if (mtu == 0)
+ continue;
+
+ /* Notification */
+ if (g_slist_find_custom(channel->notify,
+ GUINT_TO_POINTER(handle), handle_cmp)) {
+ len = enc_notification(attr, pdu, mtu);
+ if (len == 0)
+ return;
+
+ g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
+ NULL, NULL, NULL);
+ }
+ }
+}
+
static gboolean register_core_services(void)
{
uint8_t atval[256];
@@ -1205,6 +1232,8 @@ int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
a->len = len;
memcpy(a->data, value, len);
+ attrib_notify_clients(a);
+
return 0;
}
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox