2011-06-15 03:51:29

by Nami

[permalink] [raw]
Subject: [PATCH 1/2] Bluetooth: FTP and OPP over L2CAP

From: nami <[email protected]>


Signed-off-by: Nami <[email protected]>
---
client/main.c | 26 +++++++----
client/session.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++----
client/session.h | 6 +++
gwobex/gw-obex.c | 6 +-
gwobex/gw-obex.h | 3 +-
gwobex/obex-priv.c | 4 +-
gwobex/obex-priv.h | 2 +-
plugins/bluetooth.c | 112 +++++++++++++++++++++++++++++++++++++++++++++---
plugins/ftp.c | 8 +++-
plugins/opp.c | 8 +++-
src/obex.c | 10 +++-
src/service.h | 7 +++
test/main.c | 2 +-
13 files changed, 275 insertions(+), 38 deletions(-)

diff --git a/client/main.c b/client/main.c
index 478181c..5752831 100644
--- a/client/main.c
+++ b/client/main.c
@@ -125,7 +125,7 @@ done:

static int parse_device_dict(DBusMessageIter *iter,
const char **source, const char **dest, const char **target,
- uint8_t *channel)
+ uint8_t *channel, uint16_t *psm)
{
while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) {
DBusMessageIter entry, value;
@@ -150,6 +150,10 @@ static int parse_device_dict(DBusMessageIter *iter,
if (g_str_equal(key, "Channel") == TRUE)
dbus_message_iter_get_basic(&value, channel);
break;
+ case DBUS_TYPE_UINT16:
+ if (g_str_equal(key, "Psm") == TRUE)
+ dbus_message_iter_get_basic(&value, psm);
+ break;
}

dbus_message_iter_next(iter);
@@ -168,11 +172,12 @@ static DBusMessage *send_files(DBusConnection *connection,
const char *agent, *source = NULL, *dest = NULL, *target = NULL;
const char *sender;
uint8_t channel = 0;
+ uint16_t psm = 0;

dbus_message_iter_init(message, &iter);
dbus_message_iter_recurse(&iter, &array);

- parse_device_dict(&array, &source, &dest, &target, &channel);
+ parse_device_dict(&array, &source, &dest, &target, &channel, &psm);
if (dest == NULL)
return g_dbus_create_error(message,
"org.openobex.Error.InvalidArguments", NULL);
@@ -218,7 +223,7 @@ static DBusMessage *send_files(DBusConnection *connection,
data->agent = g_strdup(agent);
data->files = files;

- session = session_create(source, dest, "OPP", channel, sender,
+ session = session_create(source, dest, "OPP", channel, psm, sender,
create_callback, data);
if (session != NULL) {
sessions = g_slist_append(sessions, session);
@@ -295,11 +300,12 @@ static DBusMessage *pull_business_card(DBusConnection *connection,
const char *source = NULL, *dest = NULL, *target = NULL;
const char *name = NULL;
uint8_t channel = 0;
+ uint16_t psm = 0;

dbus_message_iter_init(message, &iter);
dbus_message_iter_recurse(&iter, &dict);

- parse_device_dict(&dict, &source, &dest, &target, &channel);
+ parse_device_dict(&dict, &source, &dest, &target, &channel, &psm);
if (dest == NULL)
return g_dbus_create_error(message,
"org.openobex.Error.InvalidArguments", NULL);
@@ -322,7 +328,7 @@ static DBusMessage *pull_business_card(DBusConnection *connection,
data->sender = g_strdup(dbus_message_get_sender(message));
data->filename = g_strdup(name);

- session = session_create(source, dest, "OPP", channel, data->sender,
+ session = session_create(source, dest, "OPP", channel, psm, data->sender,
pull_session_callback, data);
if (session != NULL) {
sessions = g_slist_append(sessions, session);
@@ -366,11 +372,12 @@ static DBusMessage *create_session(DBusConnection *connection,
struct send_data *data;
const char *source = NULL, *dest = NULL, *target = NULL;
uint8_t channel = 0;
+ uint16_t psm = 0;

dbus_message_iter_init(message, &iter);
dbus_message_iter_recurse(&iter, &dict);

- parse_device_dict(&dict, &source, &dest, &target, &channel);
+ parse_device_dict(&dict, &source, &dest, &target, &channel, &psm);
if (dest == NULL || target == NULL)
return g_dbus_create_error(message,
"org.openobex.Error.InvalidArguments", NULL);
@@ -384,7 +391,7 @@ static DBusMessage *create_session(DBusConnection *connection,
data->message = dbus_message_ref(message);
data->sender = g_strdup(dbus_message_get_sender(message));

- session = session_create(source, dest, target, channel, data->sender,
+ session = session_create(source, dest, target, channel, psm, data->sender,
create_callback, data);
if (session != NULL) {
sessions = g_slist_append(sessions, session);
@@ -493,11 +500,12 @@ static DBusMessage *get_capabilities(DBusConnection *connection,
struct send_data *data;
const char *source = NULL, *dest = NULL, *target = NULL;
uint8_t channel = 0;
+ uint16_t psm = 0;

dbus_message_iter_init(message, &iter);
dbus_message_iter_recurse(&iter, &dict);

- parse_device_dict(&dict, &source, &dest, &target, &channel);
+ parse_device_dict(&dict, &source, &dest, &target, &channel, &psm);
if (dest == NULL)
return g_dbus_create_error(message,
"org.openobex.Error.InvalidArguments", NULL);
@@ -514,7 +522,7 @@ static DBusMessage *get_capabilities(DBusConnection *connection,
if (!target)
target = "OPP";

- session = session_create(source, dest, target, channel, data->sender,
+ session = session_create(source, dest, target, channel, psm, data->sender,
capability_session_callback, data);
if (session != NULL) {
sessions = g_slist_append(sessions, session);
diff --git a/client/session.c b/client/session.c
index 266d00c..7529e84 100644
--- a/client/session.c
+++ b/client/session.c
@@ -39,6 +39,7 @@
#include <bluetooth/rfcomm.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
+#include <bluetooth/l2cap.h>

#include "log.h"
#include "pbap.h"
@@ -246,7 +247,7 @@ static void rfcomm_callback(GIOChannel *io, GError *err, gpointer user_data)
fd = g_io_channel_unix_get_fd(io);

obex = gw_obex_setup_fd(fd, session->target,
- session->target_len, NULL, NULL);
+ session->target_len, NULL, NULL, OBEX_MT_STREAM);

session->obex = obex;

@@ -283,6 +284,70 @@ static GIOChannel *rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst,
return NULL;
}

+static void l2cap_callback(GIOChannel *io, GError *err, gpointer user_data)
+{
+ struct callback_data *callback = user_data;
+ struct session_data *session = callback->session;
+ GwObex *obex;
+ int fd;
+
+ DBG("");
+
+ if (err != NULL) {
+ error("%s", err->message);
+ goto done;
+ }
+
+ /* do not close when gw_obex is using the fd */
+ g_io_channel_set_close_on_unref(session->io, FALSE);
+ g_io_channel_unref(session->io);
+ session->io = NULL;
+
+ fd = g_io_channel_unix_get_fd(io);
+
+
+ obex = gw_obex_setup_fd(fd, session->target,
+ session->target_len, NULL, NULL,OBEX_MT_SEQPACKET);
+
+ session->obex = obex;
+
+ sessions = g_slist_prepend(sessions, session);
+
+done:
+ callback->func(callback->session, err, callback->data);
+
+ session_unref(callback->session);
+
+ g_free(callback);
+}
+
+
+
+
+static GIOChannel *l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst,
+ uint16_t psm, BtIOConnect function,
+ gpointer user_data)
+{
+ GIOChannel *io;
+ GError *err = NULL;
+ DBG("");
+
+ io = bt_io_connect(BT_IO_L2CAP, function, user_data, NULL, &err,
+ BT_IO_OPT_SOURCE_BDADDR, src,
+ BT_IO_OPT_DEST_BDADDR, dst,
+ BT_IO_OPT_PSM, psm,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_MTU, 32767,
+ BT_IO_OPT_MODE, L2CAP_MODE_ERTM,
+ BT_IO_OPT_INVALID);
+ if (io != NULL)
+ return io;
+
+ error("%s", err->message);
+ g_error_free(err);
+ return NULL;
+}
+
static void search_callback(uint8_t type, uint16_t status,
uint8_t *rsp, size_t size, void *user_data)
{
@@ -291,6 +356,7 @@ static void search_callback(uint8_t type, uint16_t status,
unsigned int scanned, bytesleft = size;
int seqlen = 0;
uint8_t dataType, channel = 0;
+ uint16_t l2capPsm = 0;
GError *gerr = NULL;

if (status || type != SDP_SVC_SEARCH_ATTR_RSP)
@@ -305,7 +371,9 @@ static void search_callback(uint8_t type, uint16_t status,
do {
sdp_record_t *rec;
sdp_list_t *protos;
+ sdp_data_t *data;
int recsize, ch = -1;
+ int l2psm = -1;

recsize = 0;
rec = sdp_extract_pdu(rsp, bytesleft, &recsize);
@@ -316,7 +384,11 @@ static void search_callback(uint8_t type, uint16_t status,
sdp_record_free(rec);
break;
}
-
+ data = sdp_data_get(rec, SDP_ATTR_GOEP_L2CAP_PSM);
+ if(data != NULL){
+ l2psm = data->val.uint16;
+ DBG("sdp l2psm is %d,",l2psm);
+ }
if (!sdp_get_access_protos(rec, &protos)) {
ch = sdp_get_proto_port(protos, RFCOMM_UUID);
sdp_list_foreach(protos,
@@ -326,6 +398,11 @@ static void search_callback(uint8_t type, uint16_t status,
}

sdp_record_free(rec);
+
+ if (l2psm > 0) {
+ l2capPsm = l2psm;
+ break;
+ }

if (ch > 0) {
channel = ch;
@@ -337,16 +414,28 @@ static void search_callback(uint8_t type, uint16_t status,
bytesleft -= recsize;
} while (scanned < size && bytesleft > 0);

- if (channel == 0)
+ if ((l2capPsm == 0)&&(channel == 0))
goto failed;

- session->channel = channel;
+ if(l2capPsm > 0){
+ session->psm = l2capPsm;

- g_io_channel_set_close_on_unref(session->io, FALSE);
- g_io_channel_unref(session->io);
+ g_io_channel_set_close_on_unref(session->io, FALSE);
+ g_io_channel_unref(session->io);
+
+ session->io = l2cap_connect(&session->src, &session->dst, l2capPsm,
+ l2cap_callback, callback);
+ }else{
+
+ session->channel = channel;
+
+ g_io_channel_set_close_on_unref(session->io, FALSE);
+ g_io_channel_unref(session->io);
+
+ session->io = rfcomm_connect(&session->src, &session->dst, channel,
+ rfcomm_callback, callback);
+ }

- session->io = rfcomm_connect(&session->src, &session->dst, channel,
- rfcomm_callback, callback);
if (session->io != NULL) {
sdp_close(callback->sdp);
return;
@@ -498,6 +587,7 @@ static struct session_data *session_find(const char *source,
const char *destination,
const char *service,
uint8_t channel,
+ uint16_t psm,
const char *owner)
{
GSList *l;
@@ -519,7 +609,8 @@ static struct session_data *session_find(const char *source,
if (g_strcmp0(service, session->service))
continue;

- if (channel && session->channel != channel)
+ if ((channel && session->channel != channel)
+ &&(psm && session->psm != psm))
continue;

if (g_strcmp0(owner, session->owner))
@@ -535,6 +626,7 @@ struct session_data *session_create(const char *source,
const char *destination,
const char *service,
uint8_t channel,
+ uint16_t psm,
const char *owner,
session_callback_t function,
void *user_data)
@@ -546,7 +638,7 @@ struct session_data *session_create(const char *source,
if (destination == NULL)
return NULL;

- session = session_find(source, destination, service, channel, owner);
+ session = session_find(source, destination, service, channel, psm, owner);
if (session) {
session_ref(session);
goto proceed;
@@ -558,6 +650,7 @@ struct session_data *session_create(const char *source,

session->refcount = 1;
session->channel = channel;
+ session->psm = psm;

session->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
if (session->conn == NULL) {
@@ -607,6 +700,12 @@ proceed:
if (session->obex) {
g_idle_add(connection_complete, callback);
err = 0;
+ } else if (session->psm > 0) {
+ session->io = l2cap_connect(&session->src, &session->dst,
+ session->psm,
+ l2cap_callback,
+ callback);
+ err = (session->io == NULL) ? -EINVAL : 0;
} else if (session->channel > 0) {
session->io = rfcomm_connect(&session->src, &session->dst,
session->channel,
diff --git a/client/session.h b/client/session.h
index 6f8a434..24b1ec5 100644
--- a/client/session.h
+++ b/client/session.h
@@ -36,6 +36,7 @@ struct session_data {
bdaddr_t src;
bdaddr_t dst;
uint8_t channel;
+ uint16_t psm; /* GOEP v2.0 and later supprot OBEX over L2CAP */
char *service; /* Service friendly name */
const char *target; /* OBEX Target UUID */
int target_len;
@@ -53,6 +54,10 @@ struct session_data {
void *priv;
};

+#ifndef SDP_ATTR_GOEP_L2CAP_PSM
+#define SDP_ATTR_GOEP_L2CAP_PSM 0x0200
+#endif
+
typedef void (*session_callback_t) (struct session_data *session,
GError *err, void *user_data);

@@ -60,6 +65,7 @@ struct session_data *session_create(const char *source,
const char *destination,
const char *service,
uint8_t channel,
+ uint16_t psm,
const char *owner,
session_callback_t function,
void *user_data);
diff --git a/gwobex/gw-obex.c b/gwobex/gw-obex.c
index 4481212..a566e30 100644
--- a/gwobex/gw-obex.c
+++ b/gwobex/gw-obex.c
@@ -322,11 +322,11 @@ void gw_obex_close(GwObex *ctx) {
}

GwObex *gw_obex_setup_fd(int fd, const gchar *uuid, gint uuid_len,
- GMainContext *context, gint *error) {
+ GMainContext *context, gint *error, gint fmt) {
obex_t *handle;
GwObex *ctx;

- if (!gw_obex_transport_setup(fd, &handle)) {
+ if (!gw_obex_transport_setup(fd, &handle, fmt)) {
debug("gw_obex_open() failed\n");
if (error)
*error = GW_OBEX_ERROR_CONNECT_FAILED;
@@ -394,7 +394,7 @@ GwObex *gw_obex_setup_dev(const char *dev, const gchar *uuid, gint uuid_len,
return NULL;
}

- ctx = gw_obex_setup_fd(fd, uuid, uuid_len, context, error);
+ ctx = gw_obex_setup_fd(fd, uuid, uuid_len, context, error, OBEX_MT_STREAM);
if (ctx == NULL) {
close(fd);
}
diff --git a/gwobex/gw-obex.h b/gwobex/gw-obex.h
index c858341..985c85b 100644
--- a/gwobex/gw-obex.h
+++ b/gwobex/gw-obex.h
@@ -183,7 +183,8 @@ GwObex *gw_obex_setup_fd(int fd,
const gchar *uuid,
gint uuid_len,
GMainContext *context,
- gint *error);
+ gint *error,
+ gint fmt);


/** Close GW OBEX connection and free all memory associated with it.
diff --git a/gwobex/obex-priv.c b/gwobex/obex-priv.c
index aba7dd7..ba24f8c 100644
--- a/gwobex/obex-priv.c
+++ b/gwobex/obex-priv.c
@@ -612,7 +612,7 @@ void obex_link_error(GwObex *ctx) {
}
}

-gboolean gw_obex_transport_setup(int fd, obex_t **handle) {
+gboolean gw_obex_transport_setup(int fd, obex_t **handle, int fmt) {
*handle = OBEX_Init(OBEX_TRANS_FD, obex_event_handler, 0);
if (*handle == NULL) {
debug("OBEX_Init() failed\n");
@@ -621,7 +621,7 @@ gboolean gw_obex_transport_setup(int fd, obex_t **handle) {

(void) OBEX_SetTransportMTU(*handle, GW_OBEX_RX_MTU, GW_OBEX_TX_MTU);

- if (FdOBEX_TransportSetup(*handle, fd, fd, 0) < 0) {
+ if (FdOBEX_TransportSetup(*handle, fd, fd, 0, fmt) < 0) {
debug("FdOBEX_TransportSetup() failed\n");
OBEX_Cleanup(*handle);
return FALSE;
diff --git a/gwobex/obex-priv.h b/gwobex/obex-priv.h
index f4e3e5b..66738a4 100644
--- a/gwobex/obex-priv.h
+++ b/gwobex/obex-priv.h
@@ -181,7 +181,7 @@ gboolean gw_obex_connect(GwObex *ctx, const char *target, size_t target_len);

gboolean gw_obex_disconnect(GwObex *ctx);

-gboolean gw_obex_transport_setup(int fd, obex_t **handle);
+gboolean gw_obex_transport_setup(int fd, obex_t **handle, int fmt);

gboolean gw_obex_action_op(GwObex *ctx, const gchar *src, const gchar *dst,
uint8_t action);
diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c
index 851daa2..d5e1824 100644
--- a/plugins/bluetooth.c
+++ b/plugins/bluetooth.c
@@ -31,6 +31,8 @@

#include <openobex/obex.h>
#include <openobex/obex_const.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/l2cap.h>

#include <glib.h>
#include <gdbus.h>
@@ -146,6 +148,26 @@ static struct bluetooth_service *find_service(
return NULL;
}

+static struct bluetooth_service *find_service_psm(
+ struct obex_service_driver *driver,
+ uint16_t psm)
+{
+ GSList *l;
+ DBG("");
+ for (l = any->services; l; l = l->next) {
+ struct bluetooth_service *service = l->data;
+
+ if (driver != NULL && service->driver != driver)
+ continue;
+
+ if (psm != 0 && service->driver->psm != psm)
+ continue;
+
+ return service;
+ }
+
+ return NULL;
+}
static void register_record(struct obex_server *server)
{
const GSList *l;
@@ -175,7 +197,7 @@ static void register_record(struct obex_server *server)
continue;

xml = g_markup_printf_escaped(driver->record, driver->channel,
- driver->name);
+ driver->name, driver->psm);
add_record(any->path, xml, service);
g_free(xml);
}
@@ -207,7 +229,8 @@ static void find_adapter_any_reply(DBusPendingCall *call, void *user_data)

xml = g_markup_printf_escaped(service->driver->record,
service->driver->channel,
- service->driver->name);
+ service->driver->name,
+ service->driver->psm);
add_record(any->path, xml, service);
g_free(xml);
}
@@ -433,10 +456,14 @@ static int request_service_authorization(struct bluetooth_service *service,

if (connection == NULL || any->path == NULL)
return -1;
-
- bt_io_get(io, BT_IO_RFCOMM, &err,
- BT_IO_OPT_SOURCE, source,
- BT_IO_OPT_INVALID);
+ if(service->driver->protocol == RFCOMM_OBEX)
+ bt_io_get(io, BT_IO_RFCOMM, &err,
+ BT_IO_OPT_SOURCE, source,
+ BT_IO_OPT_INVALID);
+ else
+ bt_io_get(io, BT_IO_L2CAP, &err,
+ BT_IO_OPT_SOURCE, source,
+ BT_IO_OPT_INVALID);
if (err) {
error("%s", err->message);
g_error_free(err);
@@ -482,6 +509,7 @@ static void confirm_event(GIOChannel *io, void *user_data)
error("bluetooth: Unable to find service");
goto drop;
}
+ service->driver->protocol = RFCOMM_OBEX;

if (service->driver->service != OBEX_OPP) {
if (request_service_authorization(service, io, address) < 0)
@@ -502,6 +530,50 @@ drop:
g_io_channel_shutdown(io, TRUE, NULL);
}

+static void l2cap_confirm_event(GIOChannel *io, void *user_data)
+{
+ struct bluetooth_service *service;
+ GError *err = NULL;
+ char address[18];
+ uint16_t psm;
+
+ bt_io_get(io, BT_IO_L2CAP, &err,
+ BT_IO_OPT_DEST, address,
+ BT_IO_OPT_PSM, &psm,
+ BT_IO_OPT_INVALID);
+ if (err) {
+ error("%s", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+
+ info("bluetooth: New connection from: %s, psm 0x%x", address,
+ psm);
+
+ service = find_service_psm(NULL, psm);
+ if (service == NULL) {
+ error("bluetooth: Unable to find service");
+ goto drop;
+ }
+ service->driver->protocol = L2CAP_OBEX;
+ if (service->driver->service != OBEX_OPP) {
+ if (request_service_authorization(service, io, address) < 0)
+ goto drop;
+
+ return;
+ }
+
+ if (!bt_io_accept(io, connect_event, service, NULL, &err)) {
+ error("%s", err->message);
+ g_error_free(err);
+ goto drop;
+ }
+
+ return;
+
+drop:
+ g_io_channel_shutdown(io, TRUE, NULL);
+}
static GIOChannel *start(struct obex_server *server,
struct obex_service_driver *service,
BtIOSecLevel sec_level)
@@ -524,6 +596,28 @@ static GIOChannel *start(struct obex_server *server,
return io;
}

+static GIOChannel *start_l2cap(struct obex_server *server,
+ struct obex_service_driver *service,
+ BtIOSecLevel sec_level)
+{
+ GIOChannel *io;
+ GError *err = NULL;
+ io = bt_io_listen(BT_IO_L2CAP, NULL, l2cap_confirm_event,
+ server, NULL, &err,
+ BT_IO_OPT_PSM, service->psm,
+ BT_IO_OPT_SEC_LEVEL, sec_level,
+ BT_IO_OPT_MTU, 32767,
+ BT_IO_OPT_MODE, L2CAP_MODE_ERTM,
+ BT_IO_OPT_INVALID);
+ if (io == NULL) {
+ error("bluetooth: unable to listen in psm 0x%x: %s",
+ service->psm, err->message);
+ g_error_free(err);
+ } else
+ DBG("listening on psm 0x%x", service->psm);
+
+ return io;
+}
static void *bluetooth_start(struct obex_server *server, int *err)
{
BtIOSecLevel sec_level;
@@ -544,6 +638,12 @@ static void *bluetooth_start(struct obex_server *server, int *err)
continue;

ios = g_slist_prepend(ios, io);
+
+ io = start_l2cap(server, service, sec_level);
+ if (io == NULL)
+ continue;
+
+ ios = g_slist_prepend(ios, io);
}

register_record(server);
diff --git a/plugins/ftp.c b/plugins/ftp.c
index 79223bf..c057fae 100644
--- a/plugins/ftp.c
+++ b/plugins/ftp.c
@@ -56,6 +56,7 @@
#define CAP_TYPE "x-obex/capability"

#define FTP_CHANNEL 10
+#define FTP_PSM 0x1015
#define FTP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
<record> \
<attribute id=\"0x0001\"> \
@@ -83,7 +84,7 @@
<sequence> \
<sequence> \
<uuid value=\"0x1106\"/> \
- <uint16 value=\"0x0100\" name=\"version\"/> \
+ <uint16 value=\"0x0102\" name=\"version\"/> \
</sequence> \
</sequence> \
</attribute> \
@@ -91,6 +92,10 @@
<attribute id=\"0x0100\"> \
<text value=\"%s\" name=\"name\"/> \
</attribute> \
+ \
+ <attribute id=\"0x0200\"> \
+ <uint16 value=\"%u\" name=\"psm\"/> \
+ </attribute> \
</record>"

#define PCSUITE_CHANNEL 24
@@ -419,6 +424,7 @@ static struct obex_service_driver ftp = {
.name = "File Transfer server",
.service = OBEX_FTP,
.channel = FTP_CHANNEL,
+ .psm = FTP_PSM,
.record = FTP_RECORD,
.target = FTP_TARGET,
.target_size = TARGET_SIZE,
diff --git a/plugins/opp.c b/plugins/opp.c
index 17c4356..6fa71c3 100644
--- a/plugins/opp.c
+++ b/plugins/opp.c
@@ -44,6 +44,7 @@
#define VCARD_FILE CONFIGDIR "/vcard.vcf"

#define OPP_CHANNEL 9
+#define OPP_PSM 0x1009
#define OPP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
<record> \
<attribute id=\"0x0001\"> \
@@ -71,7 +72,7 @@
<sequence> \
<sequence> \
<uuid value=\"0x1105\"/> \
- <uint16 value=\"0x0100\" name=\"version\"/> \
+ <uint16 value=\"0x0102\" name=\"version\"/> \
</sequence> \
</sequence> \
</attribute> \
@@ -91,6 +92,10 @@
<uint8 value=\"0xff\"/> \
</sequence> \
</attribute> \
+ \
+ <attribute id=\"0x0200\"> \
+ <uint16 value=\"%u\" name=\"psm\"/> \
+ </attribute> \
</record>"

static void *opp_connect(struct obex_session *os, int *err)
@@ -210,6 +215,7 @@ static struct obex_service_driver driver = {
.name = "Object Push server",
.service = OBEX_OPP,
.channel = OPP_CHANNEL,
+ .psm = OPP_PSM,
.record = OPP_RECORD,
.connect = opp_connect,
.progress = opp_progress,
diff --git a/src/obex.c b/src/obex.c
index caba2fb..5f6cf60 100644
--- a/src/obex.c
+++ b/src/obex.c
@@ -1283,11 +1283,13 @@ int obex_session_start(GIOChannel *io, uint16_t tx_mtu, uint16_t rx_mtu,
struct obex_session *os;
obex_t *obex;
int ret, fd;
+ int fmt = OBEX_MT_STREAM;

os = g_new0(struct obex_session, 1);

- os->service = obex_service_driver_find(server->drivers, NULL,
- 0, NULL, 0);
+ //os->service = obex_service_driver_find(server->drivers, NULL,
+ // 0, NULL, 0);
+ os->service = server->drivers->data;
os->server = server;
os->rx_mtu = rx_mtu != 0 ? rx_mtu : DEFAULT_RX_MTU;
os->tx_mtu = tx_mtu != 0 ? tx_mtu : DEFAULT_TX_MTU;
@@ -1306,7 +1308,9 @@ int obex_session_start(GIOChannel *io, uint16_t tx_mtu, uint16_t rx_mtu,

fd = g_io_channel_unix_get_fd(io);

- ret = FdOBEX_TransportSetup(obex, fd, fd, 0);
+ if(os->service->protocol == L2CAP_OBEX)
+ fmt = OBEX_MT_SEQPACKET;
+ ret = FdOBEX_TransportSetup(obex, fd, fd, 0, fmt);
if (ret < 0) {
obex_session_free(os);
OBEX_Cleanup(obex);
diff --git a/src/service.h b/src/service.h
index a844885..f45b573 100644
--- a/src/service.h
+++ b/src/service.h
@@ -20,11 +20,18 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+typedef enum Obex_Protocol {
+ RFCOMM_OBEX,
+ L2CAP_OBEX
+};
+

struct obex_service_driver {
const char *name;
uint16_t service;
uint8_t channel;
+ uint16_t psm;
+ enum Obex_Protocol protocol;
const uint8_t *target;
unsigned int target_size;
const uint8_t *who;
diff --git a/test/main.c b/test/main.c
index 37b307c..b29ebf0 100644
--- a/test/main.c
+++ b/test/main.c
@@ -256,7 +256,7 @@ int main(int argc, char *argv[])
exit(1);
}

- obex = gw_obex_setup_fd(sk, target, target_len, NULL, &error);
+ obex = gw_obex_setup_fd(sk, target, target_len, NULL, &error, OBEX_MT_STREAM);
if (obex == NULL) {
fprintf(stderr, "Failed to create OBEX session\n");
close(sk);
--
1.7.1



2011-06-16 03:22:45

by Li, Nami

[permalink] [raw]
Subject: RE: [PATCH 1/2] Bluetooth: FTP and OPP over L2CAP

SGkgTWFyY2VsLA0KICBPSywgSSB3aWxsIHNwbGl0IG15IHBhdGNoZXMgaW50byBzbWFsbCBsb2dp
Y2FsIHBpZWNlcyBhbmQgdXBsb2FkIGxhdGVyLg0KDQpUaGFua3MuDQpOYW1pDQoNCi0tLS0tT3Jp
Z2luYWwgTWVzc2FnZS0tLS0tDQpGcm9tOiBNYXJjZWwgSG9sdG1hbm4gW21haWx0bzptYXJjZWxA
aG9sdG1hbm4ub3JnXSANClNlbnQ6IDIwMTHlubQ25pyIMTXml6UgMTk6MTUNClRvOiBMaSwgTmFt
aQ0KQ2M6IGxpbnV4LWJsdWV0b290aEB2Z2VyLmtlcm5lbC5vcmcNClN1YmplY3Q6IFJlOiBbUEFU
Q0ggMS8yXSBCbHVldG9vdGg6IEZUUCBhbmQgT1BQIG92ZXIgTDJDQVANCg0KSGkgTmFtaSwNCg0K
PiBGcm9tOiBuYW1pIDxuYW1pLmxpQGF0aGVyb3MuY29tPg0KPiANCj4gDQo+IFNpZ25lZC1vZmYt
Ynk6IE5hbWkgPG5hbWkubGlAYXRoZXJvcy5jb20+DQoNCnRoZSBudW1iZXIgb25lIHRoaW5nIGhl
cmUgaXMgdG8gZ2V0IHlvdXIgR0lUIHNldHVwIGRvbmUgcmlnaHQgYW5kIGZvbGxvdyBvdXIgcG9s
aWNlcyBsaWtlIG5vIHNpZ25lZC1vZmYtYnkgbGluZSBmb3IgYmx1ZXogYW5kIG9iZXhkIHN1Ym1p
c3Npb25zLg0KDQo+IC0tLQ0KPiAgY2xpZW50L21haW4uYyAgICAgICB8ICAgMjYgKysrKysrKy0t
LS0NCj4gIGNsaWVudC9zZXNzaW9uLmMgICAgfCAgMTE5ICsrKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKystLS0tDQo+ICBjbGllbnQvc2Vzc2lvbi5oICAgIHwgICAg
NiArKysNCj4gIGd3b2JleC9ndy1vYmV4LmMgICAgfCAgICA2ICstDQo+ICBnd29iZXgvZ3ctb2Jl
eC5oICAgIHwgICAgMyArLQ0KPiAgZ3dvYmV4L29iZXgtcHJpdi5jICB8ICAgIDQgKy0NCj4gIGd3
b2JleC9vYmV4LXByaXYuaCAgfCAgICAyICstDQo+ICBwbHVnaW5zL2JsdWV0b290aC5jIHwgIDEx
MiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKystLS0NCj4gIHBs
dWdpbnMvZnRwLmMgICAgICAgfCAgICA4ICsrKy0NCj4gIHBsdWdpbnMvb3BwLmMgICAgICAgfCAg
ICA4ICsrKy0NCj4gIHNyYy9vYmV4LmMgICAgICAgICAgfCAgIDEwICsrKy0NCj4gIHNyYy9zZXJ2
aWNlLmggICAgICAgfCAgICA3ICsrKw0KPiAgdGVzdC9tYWluLmMgICAgICAgICB8ICAgIDIgKy0N
Cj4gIDEzIGZpbGVzIGNoYW5nZWQsIDI3NSBpbnNlcnRpb25zKCspLCAzOCBkZWxldGlvbnMoLSkN
Cg0KQW5kIHdpdGhvdXQgZXZlbiBsb29raW5nIGF0IHRoZSBhY3R1YWwgcGF0Y2gsIEkgY2FuIHRl
bGwgeW91IHJpZ2h0IG5vdyBoZXJlIHRoYXQgeW91IHNob3VsZCBoYXZlIHNwbGl0IHRoaXMgdXAg
aW50byBsb2dpY2FsIHBpZWNlcy4gRm9yIGV4YW1wbGUgZ3dvYmV4IHNob3VsZCBiZSBpdCBzZXBh
cmF0ZSBwYXRjaCBpbiB0aGUgZmlyc3QgcGxhY2UuIEFuZCBJIGFzc3VtZSBvdGhlcnMgY2FuIGFs
c28gYmUgbmljZWx5IHNwbGl0IHVwLg0KDQpUaGVzZSAibW9uc3RlciIgcGF0Y2hlcyBhcmUgbm90
IGFjY2VwdGFibGUuDQoNClJlZ2FyZHMNCg0KTWFyY2VsDQoNCg0K

2011-06-15 11:14:38

by Marcel Holtmann

[permalink] [raw]
Subject: Re: [PATCH 1/2] Bluetooth: FTP and OPP over L2CAP

Hi Nami,

> From: nami <[email protected]>
>
>
> Signed-off-by: Nami <[email protected]>

the number one thing here is to get your GIT setup done right and follow
our polices like no signed-off-by line for bluez and obexd submissions.

> ---
> client/main.c | 26 +++++++----
> client/session.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++----
> client/session.h | 6 +++
> gwobex/gw-obex.c | 6 +-
> gwobex/gw-obex.h | 3 +-
> gwobex/obex-priv.c | 4 +-
> gwobex/obex-priv.h | 2 +-
> plugins/bluetooth.c | 112 +++++++++++++++++++++++++++++++++++++++++++++---
> plugins/ftp.c | 8 +++-
> plugins/opp.c | 8 +++-
> src/obex.c | 10 +++-
> src/service.h | 7 +++
> test/main.c | 2 +-
> 13 files changed, 275 insertions(+), 38 deletions(-)

And without even looking at the actual patch, I can tell you right now
here that you should have split this up into logical pieces. For example
gwobex should be it separate patch in the first place. And I assume
others can also be nicely split up.

These "monster" patches are not acceptable.

Regards

Marcel