* [Bluez-devel] [PATCH] Palm Hotsync over Bluetooth
@ 2005-09-22 18:05 Bastien Nocera
2005-09-22 18:23 ` Marcel Holtmann
0 siblings, 1 reply; 3+ messages in thread
From: Bastien Nocera @ 2005-09-22 18:05 UTC (permalink / raw)
To: BlueZ Hackers; +Cc: leonerd, hacker, fpillet
[-- Attachment #1: Type: text/plain, Size: 1255 bytes --]
Heya,
David, Florent, Paul, I've copied you on this mail as the
pilot-sync-devel list seems to be down ATM. Bluez-devel people, I know a
few have been interested in Hotsync'ing over Bluetooth for Palm devices.
This patch should apply to the current CVS HEAD of pilot-link.
It adds configure checks for BlueZ (with the default being to turn on
the Bluetooth support), and use the "bt:" port.
How-to use it:
1) Make sure your Palm and computer are paired
2) Select your computer as the Hotsync (Bluetooth->Setup
devices->Hotsync, ignore the instructions on screen, and go through the
wizard)
3) launch your favourite Palm conduit with the "bt:" port, such as:
pilot-xfer -p bt: -l
4) Enjoy
There are a few kludges though:
- Multiple HOTSYNC SDP records could get created, you can remove them by
hand using sdptool.
- We need to wait for the rfcomm device to be created, and then handled
by the hotplug scripts before we can use it. Marcel probably knows how
to do this better than I do.
You can use bt:<Palm bdaddr> to only allow a specific Palm to connect to
your conduit.
Comments welcome. Palm hackers, is "bluetooth:" being used, and if not,
could we hijack it, and is the current code mergeable?
Cheers
---
Bastien Nocera <hadess@hadess.net>
[-- Attachment #2: pilot-link-bluetooth.patch --]
[-- Type: text/x-patch, Size: 31485 bytes --]
Index: configure.ac
===================================================================
RCS file: /cvs/pilot-link/pilot-link_src/configure.ac,v
retrieving revision 1.36
diff -u -p -r1.36 configure.ac
--- configure.ac 17 Aug 2005 15:12:26 -0000 1.36
+++ configure.ac 22 Sep 2005 17:49:41 -0000
@@ -335,6 +335,34 @@ AM_CONDITIONAL(WITH_FREEBSDUSB, test x$u
AM_CONDITIONAL(WITH_DARWINUSB, test x$usb_type = xdarwin)
AC_SUBST(usb_libs)
+dnl *******************************************
+dnl Test if building Bluetooth Support on Linux
+dnl *******************************************
+have_bluez=no
+use_bluez=no
+msg_bluez="no"
+
+PKG_CHECK_MODULES(BLUEZ, bluez, have_bluez=yes, have_bluez=no)
+
+AC_MSG_CHECKING([for BlueZ])
+AC_ARG_WITH(bluez,
+ AC_HELP_STRING([--with-bluez],
+ [Enable usage of BlueZ]),,
+ use_bluez=auto)
+if test "x$use_bluez" != "xno"; then
+ if test "x$have_bluez" = xno && test "x$use_bluez" = xyes; then
+ AC_MSG_ERROR([BlueZ explicitly requested but no support found])
+ fi
+ if test "x$have_bluez" = xyes; then
+ AC_DEFINE(HAVE_BLUEZ, 1, [Define if we have BlueZ support])
+ AC_MSG_RESULT([enabled])
+ msg_bluez="yes"
+ else
+ AC_MSG_RESULT([not found])
+ fi
+fi
+
+AM_CONDITIONAL(WITH_BLUEZ, test x$have_bluez = "xyes")
dnl *********************************
dnl Check for popt (use internal if needed)
@@ -810,6 +838,7 @@ AC_MSG_RESULT([
Build for host.......... : $host
Extra Warnings.......... : $set_compile_warnings
Direct USB support...... : $msg_usb
+ BlueZ support........... : $msg_bluez
Thread-safe libpisock... : $msg_threads
ElectricFence checks.... : $msg_efence
CPPFLAGS................ : $CPPFLAGS
Index: include/Makefile.am
===================================================================
RCS file: /cvs/pilot-link/pilot-link_src/include/Makefile.am,v
retrieving revision 1.24
diff -u -p -r1.24 Makefile.am
--- include/Makefile.am 9 Jun 2005 13:42:47 -0000 1.24
+++ include/Makefile.am 22 Sep 2005 17:49:42 -0000
@@ -2,6 +2,7 @@ c_headers = \
pi-address.h \
pi-appinfo.h \
pi-args.h \
+ pi-bluetooth.h \
pi-buffer.h \
pi-cmp.h \
pi-contact.h \
Index: libpisock/Makefile.am
===================================================================
RCS file: /cvs/pilot-link/pilot-link_src/libpisock/Makefile.am,v
retrieving revision 1.25
diff -u -p -r1.25 Makefile.am
--- libpisock/Makefile.am 26 Apr 2005 17:44:31 -0000 1.25
+++ libpisock/Makefile.am 22 Sep 2005 17:49:42 -0000
@@ -13,6 +13,8 @@ usb_FILES = \
freebsdusb.c \
darwinusb.c
+bluez_FILES = bluetooth.c
+
if WITH_LIBUSB
usb_SOURCE = usb.c libusb.c
endif
@@ -28,11 +30,16 @@ if WITH_DARWINUSB
usb_SOURCE = usb.c darwinusb.c
endif
+if WITH_BLUEZ
+bluez_SOURCE = bluetooth.c
+endif
+
lib_LTLIBRARIES = libpisock.la
libpisock_la_SOURCES = \
$(serial_SOURCE)\
$(usb_SOURCE) \
+ $(bluez_SOURCE) \
address.c \
appinfo.c \
connect.c \
@@ -68,10 +75,10 @@ libpisock_la_SOURCES = \
# Including PTHREAD_CFLAGS here is a dirty ugly kluge. It works.
libpisock_la_LIBADD = \
- @usb_libs@ @PTHREAD_LIBS@ @PTHREAD_CFLAGS@
+ @usb_libs@ @PTHREAD_LIBS@ @PTHREAD_CFLAGS@ $(BLUEZ_LIBS)
libpisock_la_LDFLAGS = \
-export-dynamic -version-info $(PISOCK_CURRENT):$(PISOCK_REVISION):$(PISOCK_AGE)
-libpisock_la_CFLAGS = $(PIC_LIBS) @PTHREAD_CFLAGS@
+libpisock_la_CFLAGS = $(PIC_LIBS) $(BLUEZ_CFLAGS) @PTHREAD_CFLAGS@
-EXTRA_DIST = $(serial_FILES) $(usb_FILES)
+EXTRA_DIST = $(serial_FILES) $(usb_FILES) $(bluez_FILES)
Index: libpisock/socket.c
===================================================================
RCS file: /cvs/pilot-link/pilot-link_src/libpisock/socket.c,v
retrieving revision 1.104
diff -u -p -r1.104 socket.c
--- libpisock/socket.c 20 Jul 2005 10:13:40 -0000 1.104
+++ libpisock/socket.c 22 Sep 2005 17:49:44 -0000
@@ -44,6 +44,9 @@
#ifdef HAVE_USB
#include "pi-usb.h"
#endif
+#ifdef HAVE_BLUEZ
+#include "pi-bluetooth.h"
+#endif
#include "pi-inet.h"
#include "pi-slp.h"
#include "pi-sys.h"
@@ -1014,6 +1017,9 @@ pi_devsocket(int pi_sd, const char *port
} else if (!strncmp (port, "net:", 4)) {
strncpy(addr->pi_device, port + 4, sizeof(addr->pi_device));
ps->device = pi_inet_device (PI_NET_DEV);
+ } else if (!strncmp (port, "bt:", 3)) {
+ strncpy(addr->pi_device, port + 3, sizeof(addr->pi_device));
+ ps->device = pi_bluetooth_device (PI_BLUETOOTH_DEV);
} else if (!strncmp (port, "bluetooth:", 10)) {
/* warning: this code is not well tested */
strncpy(addr->pi_device, port + 10, sizeof(addr->pi_device));
--- /dev/null 2005-07-22 22:09:04.821703896 +0100
+++ include/pi-bluetooth.h 2005-09-22 18:10:06.000000000 +0100
@@ -0,0 +1,69 @@
+/*
+ * pi-bluetooth.h
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ */
+#ifndef _PILOT_BLUETOOTH_H_
+#define _PILOT_BLUETOOTH_H_
+
+#include "pi-args.h"
+#include "pi-buffer.h"
+
+#include <bluetooth/bluetooth.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PI_BLUETOOTH_DEV 1
+
+ struct pi_bluetooth_impl {
+ int (*open) PI_ARGS((pi_socket_t *ps,
+ struct pi_sockaddr *addr, size_t addrlen));
+ int (*close) PI_ARGS((pi_socket_t *ps));
+ int (*changebaud) PI_ARGS((pi_socket_t *ps));
+ ssize_t (*write) PI_ARGS((pi_socket_t *ps,
+ PI_CONST unsigned char *buf, size_t len, int flags));
+ ssize_t (*read) PI_ARGS((pi_socket_t *ps,
+ pi_buffer_t *buf, size_t expect, int flags));
+ int (*flush) PI_ARGS((pi_socket_t *ps, int flags));
+ int (*poll) PI_ARGS((pi_socket_t *ps, int timeout));
+ };
+
+ struct pi_bluetooth_data {
+ struct pi_bluetooth_impl impl;
+
+ /* Device name passed from the front-ends */
+ char *device;
+
+ /* Which channel we're listening on, and the handle
+ * for the SDP record*/
+ int channel;
+ uint32_t handle;
+
+ /* Time out */
+ int timeout;
+ };
+
+ extern pi_device_t *pi_bluetooth_device
+ PI_ARGS((int type));
+
+ extern void pi_bluetooth_impl_init
+ PI_ARGS((struct pi_bluetooth_impl *impl));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null 2005-07-22 22:09:04.821703896 +0100
+++ libpisock/bluetooth.c 2005-09-22 18:48:46.000000000 +0100
@@ -0,0 +1,919 @@
+/*
+ * bluetooth.c: Interface layer to serial HotSync connections
+ *
+ * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski
+ * Copyright (c) 1999, Tilo Christ
+ * Copyright (c) 2005, Florent Pillet
+ * Copyright (c) 2004, Paul Evans <leonerd@leonerd.org.uk>
+ * Copyright (c) 2005, Bastien Nocera <hadess@hadess.net>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h> /* Needed for Redhat 6.x machines */
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-socket.h"
+#include "pi-bluetooth.h"
+#include "pi-cmp.h"
+#include "pi-net.h"
+#include "pi-error.h"
+#include "pi-serial.h"
+#include "pi-util.h"
+
+#ifdef OS2
+#include <sys/select.h>
+#endif
+
+/* Declare prototypes */
+static int pi_bluetooth_open(struct pi_socket *ps, struct pi_sockaddr *addr,
+ int addrlen);
+static int pi_bluetooth_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_bluetooth_bind(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_bluetooth_listen(pi_socket_t *ps, int backlog);
+static int pi_bluetooth_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen);
+static int pi_bluetooth_getsockopt(pi_socket_t *ps, int level,
+ int option_name, void *option_value,
+ size_t *option_len);
+static int pi_bluetooth_setsockopt(pi_socket_t *ps, int level,
+ int option_name, const void *option_value,
+ size_t *option_len);
+static int pi_bluetooth_close(pi_socket_t *ps);
+static int pi_bluetooth_flush(pi_socket_t *ps, int flags);
+static ssize_t pi_bluetooth_write(struct pi_socket *ps,
+ const unsigned char *buf, size_t len, int flags);
+static ssize_t pi_bluetooth_read(struct pi_socket *ps,
+ pi_buffer_t *buf, size_t len, int flags);
+
+extern int pi_socket_init(pi_socket_t *ps);
+
+/* SDP Helper functions */
+/*
+ * Copyright (C) 2004 Edd Dumbill <edd@usefulinc.com>
+ * Copyright (C) 2005 Bastien Nocera <hadess@hadess.net>
+ * Mostly borrowed from BlueZ
+ *
+ * Copyright (C) 2001-2002 Nokia Corporation
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2002-2005 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
+ * Copyright (C) 2002-2003 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ */
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+typedef struct {
+ char *name;
+ char *provider;
+ char *desc;
+
+ unsigned int class;
+ unsigned int profile;
+ unsigned int channel;
+} svc_info_t;
+
+static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
+ 0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
+
+static int
+add_hotsync(sdp_session_t *session,
+ sdp_record_t *rec,
+ bdaddr_t *interface,
+ svc_info_t *si,
+ uint32_t *handle,
+ int *channel_ret)
+{
+ sdp_record_t record;
+ sdp_list_t *root, *svclass, *proto;
+ uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
+ uint8_t channel = si->channel? si->channel: 22;
+
+ memset(&record, 0, sizeof(record));
+ record.handle = 0xffffffff;
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(&record, root);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto = sdp_list_append(proto, sdp_list_append(
+ sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
+
+ sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
+
+ sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
+ svclass = sdp_list_append(NULL, &svclass_uuid);
+ sdp_set_service_classes(&record, svclass);
+
+ sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
+
+ if (sdp_device_record_register(session, interface, &record, SDP_RECORD_PERSIST) < 0) {
+ fprintf(stderr, "Service Record registration failed\n");
+ return -1;
+ }
+
+ *handle = record.handle;
+ *channel_ret = channel;
+ return 0;
+}
+
+static int
+register_sdp (uint32_t *handle, int *channel)
+{
+ svc_info_t si;
+ int ret;
+ bdaddr_t interface;
+ sdp_session_t *sess;
+
+ bacpy (&interface, BDADDR_ANY);
+ sess = sdp_connect (&interface, BDADDR_LOCAL, 0);
+
+ if (!sess)
+ return -1;
+ memset (&si, 0, sizeof(si));
+ si.name = "HOTSYNC";
+ ret = add_hotsync (sess, 0, &interface, &si, handle, channel);
+ sdp_close (sess);
+ return ret;
+}
+
+static int
+deregister_sdp(uint32_t handle)
+{
+ uint32_t range = 0x0000ffff;
+ sdp_list_t *attr;
+ sdp_session_t *sess;
+ sdp_record_t *rec;
+ bdaddr_t interface;
+
+ bacpy(&interface, BDADDR_ANY);
+
+ sess = sdp_connect(&interface, BDADDR_LOCAL, 0);
+ if (!sess) {
+ fprintf (stderr, "No local SDP server!\n");
+ return -1;
+ }
+
+ attr = sdp_list_append(0, &range);
+ rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr);
+ sdp_list_free(attr, 0);
+ if (!rec) {
+ /* printf("Service Record not found.\n"); */
+ sdp_close(sess);
+ return -1;
+ }
+ if (sdp_record_unregister(sess, rec)) {
+ fprintf (stderr, "Failed to unregister service record: %s\n", strerror(errno));
+ sdp_close(sess);
+ return -1;
+ }
+ /* printf("Service Record deleted.\n"); */
+ sdp_close(sess);
+ return 0;
+}
+
+/* Protocol Functions */
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+pi_bluetooth_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot;
+
+ ASSERT (prot != NULL);
+
+ new_prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
+
+ if (new_prot != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+ new_prot->data = NULL;
+ }
+
+ return new_prot;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_bluetooth_protocol_free (pi_protocol_t *prot)
+{
+ ASSERT (prot != NULL);
+
+ if (prot != NULL)
+ free(prot);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol
+ *
+ * Summary: creates and inits pi_protocol struct instance
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+pi_bluetooth_protocol (pi_device_t *dev)
+{
+ pi_protocol_t *prot;
+ struct pi_bluetooth_data *data;
+
+ ASSERT (dev != NULL);
+
+ prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
+
+ data = (struct pi_bluetooth_data *)(dev->data);
+
+ if (prot != NULL) {
+ prot->level = PI_LEVEL_DEV;
+ prot->dup = pi_bluetooth_protocol_dup;
+ prot->free = pi_bluetooth_protocol_free;
+ prot->read = pi_bluetooth_read;
+ prot->write = pi_bluetooth_write;
+ prot->flush = pi_bluetooth_flush;
+ prot->getsockopt = pi_bluetooth_getsockopt;
+ prot->setsockopt = pi_bluetooth_setsockopt;
+ prot->data = NULL;
+ }
+
+ return prot;
+}
+
+/* Device Functions */
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_register_hotsync_sdp
+ *
+ * Summary: Gets on which channel the HOTSYNC service is, and
+ * registers it if necessary
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ **********************************************************************/
+static void
+pi_bluetooth_register_hotsync_sdp (struct pi_bluetooth_data *data)
+{
+ if (register_sdp (&data->handle, &data->channel) < 0) {
+ data->channel = -1;
+ data->handle = 0;
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_unregister_hotsync_sdp
+ *
+ * Summary: Removes the HOTSYNC service
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ **********************************************************************/
+static void
+pi_bluetooth_unregister_hotsync_sdp (struct pi_bluetooth_data *data)
+{
+ if (data->handle != 0)
+ deregister_sdp (data->handle);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_device_free
+ *
+ * Summary: frees an existing pi_device struct
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_bluetooth_device_free (pi_device_t *dev)
+{
+ struct pi_bluetooth_data *data;
+
+ ASSERT (dev != NULL);
+
+ if (dev->data) {
+ data = dev->data;
+ pi_bluetooth_unregister_hotsync_sdp (data);
+ if (data->device)
+ free (data->device);
+ free(dev->data);
+ }
+ free(dev);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_open
+ *
+ * Summary: Open a new BlueTooth RFCOMM socket
+ *
+ * Parameters: None
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ **********************************************************************/
+static int
+pi_bluetooth_open(struct pi_socket *ps, struct pi_sockaddr *addr, int addrlen)
+{
+ int fd, flags;
+ struct pi_bluetooth_data *data = ps->device->data;
+
+ pi_bluetooth_register_hotsync_sdp (data);
+ /* If we didn't manage to create an SDP record, force channel 22 and try
+ * again */
+ if (data->channel < 0) {
+ data->channel = 22;
+ }
+
+ if ((fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0)
+ return -1;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) != -1) {
+ flags &= ~O_NONBLOCK;
+ fcntl(fd, F_SETFL, flags);
+ }
+
+ if (pi_socket_setsd(ps, fd) < 0)
+ return -1;
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_device
+ *
+ * Summary: creates and inits pi_device struct instance
+ *
+ * Parameters: device type
+ *
+ * Returns: pi_device_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_device_t*
+pi_bluetooth_device (int type)
+{
+ pi_device_t *dev;
+ struct pi_bluetooth_data *data;
+
+ dev = (pi_device_t *) malloc(sizeof (pi_device_t));
+ if (dev == NULL)
+ return NULL;
+
+ data = (struct pi_bluetooth_data *) malloc(sizeof (struct pi_bluetooth_data));
+ if (data == NULL) {
+ free(dev);
+ return NULL;
+ }
+
+ dev->free = pi_bluetooth_device_free;
+ dev->protocol = pi_bluetooth_protocol;
+ dev->bind = pi_bluetooth_bind;
+ dev->listen = pi_bluetooth_listen;
+ dev->accept = pi_bluetooth_accept;
+ dev->connect = pi_bluetooth_connect;
+ dev->close = pi_bluetooth_close;
+
+ data->timeout = 0;
+ dev->data = data;
+
+ return dev;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_connect
+ *
+ * Summary: Connect socket to a given address
+ *
+ * Parameters: pi_socket*, sockaddr*, size_t
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen)
+{
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ if (ps->type == PI_SOCK_STREAM) {
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if (cmp_tx_handshake(ps) < 0)
+ goto fail;
+
+ break;
+
+ case PI_CMD_NET:
+ break;
+
+ case PI_CMD_SYS:
+ break;
+ }
+ }
+ ps->state = PI_SOCK_CONN_INIT;
+ ps->command = 0;
+
+ return 0;
+
+fail:
+ pi_close (ps->sd);
+ return -1;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_bind
+ *
+ * Summary: Bind address to a local socket
+ *
+ * Parameters: pi_socket*, sockaddr*, size_t
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_bind(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
+{
+ struct pi_sockaddr *pa = (struct pi_sockaddr *) addr;
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+ char *device = pa->pi_device;
+ struct sockaddr_rc bindaddr;
+
+ if (pi_bluetooth_open(ps, pa, addrlen) == -1)
+ return -1; /* errno already set */
+
+ data->device = strdup (device);
+
+ bindaddr.rc_family = AF_BLUETOOTH;
+ bacpy(&bindaddr.rc_bdaddr, BDADDR_ANY);
+ bindaddr.rc_channel = data->channel;
+
+ if (bind(ps->sd, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ return -1;
+ }
+
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_listen
+ *
+ * Summary: Prepare for incoming connections
+ *
+ * Parameters: pi_socket*, backlog
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int pi_bluetooth_listen(pi_socket_t *ps, int backlog)
+{
+ int result;
+
+ listen(ps->sd, 10);
+ ps->state = PI_SOCK_LISTEN;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_accept_rfcomm
+ *
+ * Summary: Accept an incoming connection and associate it with an
+ * RFCOMM serial device
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_accept_rfcomm(struct pi_socket *ps, const char *device, struct sockaddr_rc *peeraddr, unsigned int *peeraddrlen)
+{
+ int newfd;
+ struct sockaddr_rc localaddr;
+ unsigned int localaddrlen = sizeof(localaddr);
+ struct rfcomm_dev_req req;
+ int devid = -1;
+ char devicepath[100];
+ int rfcommfd, i;
+
+ newfd = accept(ps->sd, (struct sockaddr *)peeraddr, peeraddrlen);
+ if (newfd < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ return -1;
+ }
+
+ /* Check whether we need to really accept this connection */
+ if (device[0] != '\0' && strcmp (device, "any") != 0) {
+ bdaddr_t tmp;
+ if (str2ba (device, &tmp) < 0) {
+ close (newfd);
+ return -1;
+ }
+ if (bacmp (&tmp, &(peeraddr->rc_bdaddr)) != 0) {
+ close (newfd);
+ return -1;
+ }
+ }
+
+ if (getsockname(newfd, (struct sockaddr *)&localaddr, &localaddrlen) < 0) {
+ close (newfd);
+ return -1;
+ }
+
+ /* Find out on which device we need to connect, but only in the 10
+ * first Bluetooth adapters, should be more than enough */
+ for (i = 0; i < 10; i++) {
+ bdaddr_t tmp;
+ if (hci_devba (i, &tmp) < 0) {
+ break;
+ }
+ if (bacmp (&(localaddr.rc_bdaddr), &tmp) == 0) {
+ devid = i;
+ break;
+ }
+ }
+
+ if (devid < 0) {
+ close (newfd);
+ return -1;
+ }
+
+ /* Now request kernel to bind this to an rfcomm device */
+ memset(&req, 0, sizeof(req));
+ req.dev_id = devid;
+ req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
+ bacpy(&req.src, &localaddr.rc_bdaddr);
+ bacpy(&req.dst, &peeraddr->rc_bdaddr);
+ req.channel = peeraddr->rc_channel;
+
+ if ((devid = ioctl(newfd, RFCOMMCREATEDEV, &req)) < 0) {
+ close(newfd);
+ return -1;
+ }
+
+ snprintf(devicepath, sizeof(devicepath) - 1, "/dev/rfcomm%d", devid);
+
+ /* Sleep up to a second waiting for /dev/rfcomm%d to appear,
+ * and be set as writable by the hotplug scripts */
+ i = 0;
+ rfcommfd = open(devicepath, O_RDWR | O_NOCTTY);
+ while (rfcommfd < 0 && (errno == ENOENT || errno == EACCES)) {
+ usleep (10000);
+ rfcommfd = open(devicepath, O_RDWR | O_NOCTTY);
+ if (i >= 100) break;
+ i++;
+ }
+
+ if (rfcommfd < 0) {
+ close(newfd);
+ return -1;
+ }
+
+ /* Close it anyway; the rfcomm device will keep it up */
+ close(newfd);
+
+ return rfcommfd;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_accept
+ *
+ * Summary: Accept an incoming connection
+ *
+ * Parameters: pi_socket*, sockaddr*
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+ struct sockaddr_rc peeraddr;
+ unsigned int peeraddrlen = sizeof(peeraddr);
+ int sd;
+
+ /* Wait for data */
+ sd = pi_bluetooth_accept_rfcomm(ps, data->device, &peeraddr, &peeraddrlen);
+ if (sd < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ goto fail;
+ }
+
+ if (pi_socket_setsd(ps, sd) < 0)
+ return -1;
+ pi_socket_init(ps);
+
+ if (ps->type == PI_SOCK_STREAM) {
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if (cmp_rx_handshake(ps, 0, 0) < 0)
+ return -1;
+
+ break;
+ case PI_CMD_NET:
+ if (net_rx_handshake(ps) < 0)
+ return -1;
+ break;
+ }
+
+ ps->dlprecord = 0;
+ }
+
+ data->timeout = 0;
+ ps->command = 0;
+ ps->state = PI_SOCK_CONN_ACCEPT;
+
+ return ps->sd;
+
+fail:
+ return -1;
+}
+
+static int
+pi_bluetooth_flush(pi_socket_t *ps, int flags)
+{
+ char buf[256];
+ int fl;
+
+ if (flags & PI_FLUSH_INPUT) {
+ if ((fl = fcntl(ps->sd, F_GETFL, 0)) != -1) {
+ fcntl(ps->sd, F_SETFL, fl | O_NONBLOCK);
+ while (read(ps->sd, buf, sizeof(buf)) > 0)
+ ;
+ fcntl(ps->sd, F_SETFL, fl);
+ }
+ }
+ return 0;
+}
+
+static ssize_t
+pi_bluetooth_read(struct pi_socket *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ int rbuf;
+ struct pi_bluetooth_data *data = (struct pi_bluetooth_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ if (pi_buffer_expect (buf, len) == NULL) {
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ if (data->timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ select(ps->sd + 1, &ready, 0, 0, &t);
+ }
+ /* If data is available in time, read it */
+ if (FD_ISSET(ps->sd, &ready)) {
+ if (flags == PI_MSG_PEEK && len > 256)
+ len = 256;
+ rbuf = read(ps->sd, buf->data + buf->used, len);
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN, "DEV RX BlueTooth timeout\n"));
+ pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ return -1;
+ }
+ buf->used += rbuf;
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV RX BlueTooth Bytes: %d\n", rbuf));
+
+ return rbuf;
+}
+
+static ssize_t
+pi_bluetooth_write(struct pi_socket *ps, const unsigned char *buf, size_t len, int flags)
+{
+ int total,
+ nwrote;
+ struct pi_bluetooth_data *data = (struct pi_bluetooth_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ total = len;
+ while (total > 0) {
+ if (data->timeout == 0)
+ select(ps->sd + 1, 0, &ready, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ select(ps->sd + 1, 0, &ready, 0, &t);
+ }
+ if (!FD_ISSET(ps->sd, &ready)) {
+ pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ return -1;
+ }
+ nwrote = write(ps->sd, buf, len);
+ if (nwrote < 0) {
+ pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ return -1;
+ }
+ total -= nwrote;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV TX BlueTooth Bytes: %d\n", len));
+ return len;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_TIMEOUT:
+ if (*option_len < sizeof (data->timeout))
+ goto error;
+ memcpy (option_value, &data->timeout,
+ sizeof (data->timeout));
+ *option_len = sizeof (data->timeout);
+ break;
+ }
+
+ return 0;
+error:
+ pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ return -1;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_setsockopt
+ *
+ * Summary: set options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_TIMEOUT:
+ if (*option_len != sizeof (data->timeout))
+ goto error;
+ memcpy (&data->timeout, option_value,
+ sizeof (data->timeout));
+ break;
+ }
+
+ return 0;
+
+error:
+ pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ return -1;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_close
+ *
+ * Summary: Close a connection, destroy the socket
+ *
+ * Parameters: pi_socket*
+ *
+ * Returns: always 0 for success
+ *
+ ***********************************************************************/
+static int pi_bluetooth_close(pi_socket_t *ps)
+{
+ if (ps->laddr) {
+ free(ps->laddr);
+ ps->laddr = NULL;
+ }
+
+ if (ps->raddr) {
+ free(ps->raddr);
+ ps->raddr = NULL;
+ }
+
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [Bluez-devel] [PATCH] Palm Hotsync over Bluetooth
2005-09-22 18:05 [Bluez-devel] [PATCH] Palm Hotsync over Bluetooth Bastien Nocera
@ 2005-09-22 18:23 ` Marcel Holtmann
2005-09-22 21:51 ` Bastien Nocera
0 siblings, 1 reply; 3+ messages in thread
From: Marcel Holtmann @ 2005-09-22 18:23 UTC (permalink / raw)
To: bluez-devel; +Cc: leonerd, hacker, fpillet
Hi Bastien,
> David, Florent, Paul, I've copied you on this mail as the
> pilot-sync-devel list seems to be down ATM. Bluez-devel people, I know a
> few have been interested in Hotsync'ing over Bluetooth for Palm devices.
>
> This patch should apply to the current CVS HEAD of pilot-link.
> It adds configure checks for BlueZ (with the default being to turn on
> the Bluetooth support), and use the "bt:" port.
>
> How-to use it:
> 1) Make sure your Palm and computer are paired
> 2) Select your computer as the Hotsync (Bluetooth->Setup
> devices->Hotsync, ignore the instructions on screen, and go through the
> wizard)
> 3) launch your favourite Palm conduit with the "bt:" port, such as:
> pilot-xfer -p bt: -l
> 4) Enjoy
>
> There are a few kludges though:
> - Multiple HOTSYNC SDP records could get created, you can remove them by
> hand using sdptool.
look at the pand daemon and see how they handle the SDP records. There
is no need to make them persistent. If the application dies, the records
are automatically removed by sdpd.
> - We need to wait for the rfcomm device to be created, and then handled
> by the hotplug scripts before we can use it. Marcel probably knows how
> to do this better than I do.
Don't create a TTY device. You can use the RFCOMM socket directly.
> You can use bt:<Palm bdaddr> to only allow a specific Palm to connect to
> your conduit.
>
> Comments welcome. Palm hackers, is "bluetooth:" being used, and if not,
> could we hijack it, and is the current code mergeable?
Someone has to send me a Palm device with Bluetooth, so I can do more
testing.
Regards
Marcel
-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server.
Download it for free - -and be entered to win a 42" plasma tv or your very
own Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [Bluez-devel] [PATCH] Palm Hotsync over Bluetooth
2005-09-22 18:23 ` Marcel Holtmann
@ 2005-09-22 21:51 ` Bastien Nocera
0 siblings, 0 replies; 3+ messages in thread
From: Bastien Nocera @ 2005-09-22 21:51 UTC (permalink / raw)
To: bluez-devel; +Cc: leonerd, hacker, fpillet
[-- Attachment #1: Type: text/plain, Size: 2098 bytes --]
Hi Marcel,
On Thu, 2005-09-22 at 20:23 +0200, Marcel Holtmann wrote:
> Hi Bastien,
>
> > David, Florent, Paul, I've copied you on this mail as the
> > pilot-sync-devel list seems to be down ATM. Bluez-devel people, I know a
> > few have been interested in Hotsync'ing over Bluetooth for Palm devices.
> >
> > This patch should apply to the current CVS HEAD of pilot-link.
> > It adds configure checks for BlueZ (with the default being to turn on
> > the Bluetooth support), and use the "bt:" port.
> >
> > How-to use it:
> > 1) Make sure your Palm and computer are paired
> > 2) Select your computer as the Hotsync (Bluetooth->Setup
> > devices->Hotsync, ignore the instructions on screen, and go through the
> > wizard)
> > 3) launch your favourite Palm conduit with the "bt:" port, such as:
> > pilot-xfer -p bt: -l
> > 4) Enjoy
> >
> > There are a few kludges though:
> > - Multiple HOTSYNC SDP records could get created, you can remove them by
> > hand using sdptool.
>
> look at the pand daemon and see how they handle the SDP records. There
> is no need to make them persistent. If the application dies, the records
> are automatically removed by sdpd.
Ha! I fixed the gnome-bluetooth OBEX code to keep the session opened as
well.
> > - We need to wait for the rfcomm device to be created, and then handled
> > by the hotplug scripts before we can use it. Marcel probably knows how
> > to do this better than I do.
>
> Don't create a TTY device. You can use the RFCOMM socket directly.
And that removes wads of code as well, much cleaner. Thanks.
> > You can use bt:<Palm bdaddr> to only allow a specific Palm to connect to
> > your conduit.
> >
> > Comments welcome. Palm hackers, is "bluetooth:" being used, and if not,
> > could we hijack it, and is the current code mergeable?
>
> Someone has to send me a Palm device with Bluetooth, so I can do more
> testing.
Do you have a Palm? A Bluetooth SDIO card for a Palm is considerably
cheaper than a brand new Palm...
Thanks for the advices, I've attached the new patch below.
Cheers
---
Bastien Nocera <hadess@hadess.net>
[-- Attachment #2: pilot-link-bluetooth2.patch --]
[-- Type: text/x-patch, Size: 29792 bytes --]
Index: configure.ac
===================================================================
RCS file: /cvs/pilot-link/pilot-link_src/configure.ac,v
retrieving revision 1.36
diff -u -p -r1.36 configure.ac
--- configure.ac 17 Aug 2005 15:12:26 -0000 1.36
+++ configure.ac 22 Sep 2005 21:46:03 -0000
@@ -335,6 +335,34 @@ AM_CONDITIONAL(WITH_FREEBSDUSB, test x$u
AM_CONDITIONAL(WITH_DARWINUSB, test x$usb_type = xdarwin)
AC_SUBST(usb_libs)
+dnl *******************************************
+dnl Test if building Bluetooth Support on Linux
+dnl *******************************************
+have_bluez=no
+use_bluez=no
+msg_bluez="no"
+
+PKG_CHECK_MODULES(BLUEZ, bluez, have_bluez=yes, have_bluez=no)
+
+AC_MSG_CHECKING([for BlueZ])
+AC_ARG_WITH(bluez,
+ AC_HELP_STRING([--with-bluez],
+ [Enable usage of BlueZ]),,
+ use_bluez=auto)
+if test "x$use_bluez" != "xno"; then
+ if test "x$have_bluez" = xno && test "x$use_bluez" = xyes; then
+ AC_MSG_ERROR([BlueZ explicitly requested but no support found])
+ fi
+ if test "x$have_bluez" = xyes; then
+ AC_DEFINE(HAVE_BLUEZ, 1, [Define if we have BlueZ support])
+ AC_MSG_RESULT([enabled])
+ msg_bluez="yes"
+ else
+ AC_MSG_RESULT([not found])
+ fi
+fi
+
+AM_CONDITIONAL(WITH_BLUEZ, test x$have_bluez = "xyes")
dnl *********************************
dnl Check for popt (use internal if needed)
@@ -810,6 +838,7 @@ AC_MSG_RESULT([
Build for host.......... : $host
Extra Warnings.......... : $set_compile_warnings
Direct USB support...... : $msg_usb
+ BlueZ support........... : $msg_bluez
Thread-safe libpisock... : $msg_threads
ElectricFence checks.... : $msg_efence
CPPFLAGS................ : $CPPFLAGS
Index: include/Makefile.am
===================================================================
RCS file: /cvs/pilot-link/pilot-link_src/include/Makefile.am,v
retrieving revision 1.24
diff -u -p -r1.24 Makefile.am
--- include/Makefile.am 9 Jun 2005 13:42:47 -0000 1.24
+++ include/Makefile.am 22 Sep 2005 21:46:03 -0000
@@ -2,6 +2,7 @@ c_headers = \
pi-address.h \
pi-appinfo.h \
pi-args.h \
+ pi-bluetooth.h \
pi-buffer.h \
pi-cmp.h \
pi-contact.h \
Index: libpisock/Makefile.am
===================================================================
RCS file: /cvs/pilot-link/pilot-link_src/libpisock/Makefile.am,v
retrieving revision 1.25
diff -u -p -r1.25 Makefile.am
--- libpisock/Makefile.am 26 Apr 2005 17:44:31 -0000 1.25
+++ libpisock/Makefile.am 22 Sep 2005 21:46:04 -0000
@@ -13,6 +13,8 @@ usb_FILES = \
freebsdusb.c \
darwinusb.c
+bluez_FILES = bluetooth.c
+
if WITH_LIBUSB
usb_SOURCE = usb.c libusb.c
endif
@@ -28,11 +30,16 @@ if WITH_DARWINUSB
usb_SOURCE = usb.c darwinusb.c
endif
+if WITH_BLUEZ
+bluez_SOURCE = bluetooth.c
+endif
+
lib_LTLIBRARIES = libpisock.la
libpisock_la_SOURCES = \
$(serial_SOURCE)\
$(usb_SOURCE) \
+ $(bluez_SOURCE) \
address.c \
appinfo.c \
connect.c \
@@ -68,10 +75,10 @@ libpisock_la_SOURCES = \
# Including PTHREAD_CFLAGS here is a dirty ugly kluge. It works.
libpisock_la_LIBADD = \
- @usb_libs@ @PTHREAD_LIBS@ @PTHREAD_CFLAGS@
+ @usb_libs@ @PTHREAD_LIBS@ @PTHREAD_CFLAGS@ $(BLUEZ_LIBS)
libpisock_la_LDFLAGS = \
-export-dynamic -version-info $(PISOCK_CURRENT):$(PISOCK_REVISION):$(PISOCK_AGE)
-libpisock_la_CFLAGS = $(PIC_LIBS) @PTHREAD_CFLAGS@
+libpisock_la_CFLAGS = $(PIC_LIBS) $(BLUEZ_CFLAGS) @PTHREAD_CFLAGS@
-EXTRA_DIST = $(serial_FILES) $(usb_FILES)
+EXTRA_DIST = $(serial_FILES) $(usb_FILES) $(bluez_FILES)
Index: libpisock/socket.c
===================================================================
RCS file: /cvs/pilot-link/pilot-link_src/libpisock/socket.c,v
retrieving revision 1.104
diff -u -p -r1.104 socket.c
--- libpisock/socket.c 20 Jul 2005 10:13:40 -0000 1.104
+++ libpisock/socket.c 22 Sep 2005 21:46:05 -0000
@@ -44,6 +44,9 @@
#ifdef HAVE_USB
#include "pi-usb.h"
#endif
+#ifdef HAVE_BLUEZ
+#include "pi-bluetooth.h"
+#endif
#include "pi-inet.h"
#include "pi-slp.h"
#include "pi-sys.h"
@@ -1014,6 +1017,9 @@ pi_devsocket(int pi_sd, const char *port
} else if (!strncmp (port, "net:", 4)) {
strncpy(addr->pi_device, port + 4, sizeof(addr->pi_device));
ps->device = pi_inet_device (PI_NET_DEV);
+ } else if (!strncmp (port, "bt:", 3)) {
+ strncpy(addr->pi_device, port + 3, sizeof(addr->pi_device));
+ ps->device = pi_bluetooth_device (PI_BLUETOOTH_DEV);
} else if (!strncmp (port, "bluetooth:", 10)) {
/* warning: this code is not well tested */
strncpy(addr->pi_device, port + 10, sizeof(addr->pi_device));
--- /dev/null 2005-07-22 22:09:04.821703896 +0100
+++ include/pi-bluetooth.h 2005-09-22 22:32:43.000000000 +0100
@@ -0,0 +1,70 @@
+/*
+ * pi-bluetooth.h
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ */
+#ifndef _PILOT_BLUETOOTH_H_
+#define _PILOT_BLUETOOTH_H_
+
+#include "pi-args.h"
+#include "pi-buffer.h"
+
+#include <bluetooth/sdp.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PI_BLUETOOTH_DEV 1
+
+ struct pi_bluetooth_impl {
+ int (*open) PI_ARGS((pi_socket_t *ps,
+ struct pi_sockaddr *addr, size_t addrlen));
+ int (*close) PI_ARGS((pi_socket_t *ps));
+ int (*changebaud) PI_ARGS((pi_socket_t *ps));
+ ssize_t (*write) PI_ARGS((pi_socket_t *ps,
+ PI_CONST unsigned char *buf, size_t len, int flags));
+ ssize_t (*read) PI_ARGS((pi_socket_t *ps,
+ pi_buffer_t *buf, size_t expect, int flags));
+ int (*flush) PI_ARGS((pi_socket_t *ps, int flags));
+ int (*poll) PI_ARGS((pi_socket_t *ps, int timeout));
+ };
+
+ struct pi_bluetooth_data {
+ struct pi_bluetooth_impl impl;
+
+ /* Device name passed from the front-ends */
+ char *device;
+
+ /* Which channel we're listening on, the handle
+ * for the SDP record as well as the SDP session */
+ int channel;
+ uint32_t handle;
+ sdp_session_t *sess;
+
+ /* Time out */
+ int timeout;
+ };
+
+ extern pi_device_t *pi_bluetooth_device
+ PI_ARGS((int type));
+
+ extern void pi_bluetooth_impl_init
+ PI_ARGS((struct pi_bluetooth_impl *impl));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null 2005-07-22 22:09:04.821703896 +0100
+++ libpisock/bluetooth.c 2005-09-22 22:45:00.000000000 +0100
@@ -0,0 +1,856 @@
+/*
+ * bluetooth.c: Interface layer to serial HotSync connections
+ *
+ * Copyright (c) 1996, 1997, D. Jeff Dionne & Kenneth Albanowski
+ * Copyright (c) 1999, Tilo Christ
+ * Copyright (c) 2005, Florent Pillet
+ * Copyright (c) 2004, Paul Evans <leonerd@leonerd.org.uk>
+ * Copyright (c) 2005, Bastien Nocera <hadess@hadess.net>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This library 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 Library
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h> /* Needed for Redhat 6.x machines */
+
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include "pi-debug.h"
+#include "pi-source.h"
+#include "pi-socket.h"
+#include "pi-bluetooth.h"
+#include "pi-cmp.h"
+#include "pi-net.h"
+#include "pi-error.h"
+#include "pi-serial.h"
+#include "pi-util.h"
+
+#ifdef OS2
+#include <sys/select.h>
+#endif
+
+/* Declare prototypes */
+static int pi_bluetooth_open(struct pi_socket *ps, struct pi_sockaddr *addr,
+ int addrlen);
+static int pi_bluetooth_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_bluetooth_bind(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen);
+static int pi_bluetooth_listen(pi_socket_t *ps, int backlog);
+static int pi_bluetooth_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen);
+static int pi_bluetooth_getsockopt(pi_socket_t *ps, int level,
+ int option_name, void *option_value,
+ size_t *option_len);
+static int pi_bluetooth_setsockopt(pi_socket_t *ps, int level,
+ int option_name, const void *option_value,
+ size_t *option_len);
+static int pi_bluetooth_close(pi_socket_t *ps);
+static int pi_bluetooth_flush(pi_socket_t *ps, int flags);
+static ssize_t pi_bluetooth_write(struct pi_socket *ps,
+ const unsigned char *buf, size_t len, int flags);
+static ssize_t pi_bluetooth_read(struct pi_socket *ps,
+ pi_buffer_t *buf, size_t len, int flags);
+
+extern int pi_socket_init(pi_socket_t *ps);
+
+/* SDP Helper functions */
+/*
+ * Copyright (C) 2004 Edd Dumbill <edd@usefulinc.com>
+ * Copyright (C) 2005 Bastien Nocera <hadess@hadess.net>
+ * Mostly borrowed from BlueZ
+ *
+ * Copyright (C) 2001-2002 Nokia Corporation
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2002-2005 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
+ * Copyright (C) 2002-2003 Jean Tourrilhes <jt@hpl.hp.com>
+ *
+ */
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+typedef struct {
+ char *name;
+ char *provider;
+ char *desc;
+
+ unsigned int class;
+ unsigned int profile;
+ unsigned int channel;
+} svc_info_t;
+
+#define HOTSYNC_CHANNEL 22
+
+static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5,
+ 0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C };
+
+static int
+add_hotsync(sdp_session_t *session,
+ sdp_record_t *rec,
+ bdaddr_t *interface,
+ svc_info_t *si,
+ uint32_t *handle,
+ int *channel_ret)
+{
+ sdp_record_t record;
+ sdp_list_t *root, *svclass, *proto;
+ uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid;
+ uint8_t channel = HOTSYNC_CHANNEL;
+
+ memset(&record, 0, sizeof(record));
+ record.handle = 0xffffffff;
+
+ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
+ root = sdp_list_append(NULL, &root_uuid);
+ sdp_set_browse_groups(&record, root);
+
+ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
+ proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid));
+
+ sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
+ proto = sdp_list_append(proto, sdp_list_append(
+ sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel)));
+
+ sdp_set_access_protos(&record, sdp_list_append(NULL, proto));
+
+ sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid);
+ svclass = sdp_list_append(NULL, &svclass_uuid);
+ sdp_set_service_classes(&record, svclass);
+
+ sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL);
+
+ if (sdp_device_record_register(session, interface, &record, 0) < 0) {
+ fprintf(stderr, "Service Record registration failed\n");
+ return -1;
+ }
+
+ *handle = record.handle;
+ *channel_ret = HOTSYNC_CHANNEL;
+ return 0;
+}
+
+static int
+register_sdp (uint32_t *handle, int *channel, sdp_session_t *sess)
+{
+ svc_info_t si;
+ int ret;
+ bdaddr_t interface;
+
+ bacpy (&interface, BDADDR_ANY);
+ sess = sdp_connect (&interface, BDADDR_LOCAL, 0);
+
+ if (!sess)
+ return -1;
+ memset (&si, 0, sizeof(si));
+ si.name = "HOTSYNC";
+ ret = add_hotsync (sess, 0, &interface, &si, handle, channel);
+
+ return ret;
+}
+
+static int
+deregister_sdp(uint32_t handle, sdp_session_t *sess)
+{
+ uint32_t range = 0x0000ffff;
+ sdp_list_t *attr;
+ sdp_record_t *rec;
+ bdaddr_t interface;
+
+ if (!sess) {
+ return 0;
+ }
+
+ bacpy(&interface, BDADDR_ANY);
+
+ attr = sdp_list_append(0, &range);
+ rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr);
+ sdp_list_free(attr, 0);
+ if (!rec) {
+ /* printf("Service Record not found.\n"); */
+ sdp_close(sess);
+ return -1;
+ }
+ if (sdp_record_unregister(sess, rec)) {
+ fprintf (stderr, "Failed to unregister service record: %s\n", strerror(errno));
+ sdp_close(sess);
+ return -1;
+ }
+ /* printf("Service Record deleted.\n"); */
+ sdp_close(sess);
+ return 0;
+}
+
+/* Protocol Functions */
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol_dup
+ *
+ * Summary: clones an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+pi_bluetooth_protocol_dup (pi_protocol_t *prot)
+{
+ pi_protocol_t *new_prot;
+
+ ASSERT (prot != NULL);
+
+ new_prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
+
+ if (new_prot != NULL) {
+ new_prot->level = prot->level;
+ new_prot->dup = prot->dup;
+ new_prot->free = prot->free;
+ new_prot->read = prot->read;
+ new_prot->write = prot->write;
+ new_prot->flush = prot->flush;
+ new_prot->getsockopt = prot->getsockopt;
+ new_prot->setsockopt = prot->setsockopt;
+ new_prot->data = NULL;
+ }
+
+ return new_prot;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol_free
+ *
+ * Summary: frees an existing pi_protocol struct
+ *
+ * Parameters: pi_protocol*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_bluetooth_protocol_free (pi_protocol_t *prot)
+{
+ ASSERT (prot != NULL);
+
+ if (prot != NULL)
+ free(prot);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_protocol
+ *
+ * Summary: creates and inits pi_protocol struct instance
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: pi_protocol_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+static pi_protocol_t*
+pi_bluetooth_protocol (pi_device_t *dev)
+{
+ pi_protocol_t *prot;
+ struct pi_bluetooth_data *data;
+
+ ASSERT (dev != NULL);
+
+ prot = (pi_protocol_t *) malloc(sizeof (pi_protocol_t));
+
+ data = (struct pi_bluetooth_data *)(dev->data);
+
+ if (prot != NULL) {
+ prot->level = PI_LEVEL_DEV;
+ prot->dup = pi_bluetooth_protocol_dup;
+ prot->free = pi_bluetooth_protocol_free;
+ prot->read = pi_bluetooth_read;
+ prot->write = pi_bluetooth_write;
+ prot->flush = pi_bluetooth_flush;
+ prot->getsockopt = pi_bluetooth_getsockopt;
+ prot->setsockopt = pi_bluetooth_setsockopt;
+ prot->data = NULL;
+ }
+
+ return prot;
+}
+
+/* Device Functions */
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_register_hotsync_sdp
+ *
+ * Summary: Gets on which channel the HOTSYNC service is, and
+ * registers it if necessary
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ **********************************************************************/
+static void
+pi_bluetooth_register_hotsync_sdp (struct pi_bluetooth_data *data)
+{
+ if (register_sdp (&data->handle, &data->channel, data->sess) < 0) {
+ data->channel = -1;
+ data->handle = 0;
+ data->sess = NULL;
+ }
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_unregister_hotsync_sdp
+ *
+ * Summary: Removes the HOTSYNC service
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ **********************************************************************/
+static void
+pi_bluetooth_unregister_hotsync_sdp (struct pi_bluetooth_data *data)
+{
+ if (data->handle != 0)
+ deregister_sdp (data->handle, data->sess);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_device_free
+ *
+ * Summary: frees an existing pi_device struct
+ *
+ * Parameters: pi_device_t*
+ *
+ * Returns: void
+ *
+ ***********************************************************************/
+static void
+pi_bluetooth_device_free (pi_device_t *dev)
+{
+ struct pi_bluetooth_data *data;
+
+ ASSERT (dev != NULL);
+
+ if (dev->data) {
+ data = dev->data;
+ pi_bluetooth_unregister_hotsync_sdp (data);
+ if (data->device)
+ free (data->device);
+ free(dev->data);
+ }
+ free(dev);
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_open
+ *
+ * Summary: Open a new BlueTooth RFCOMM socket
+ *
+ * Parameters: None
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ **********************************************************************/
+static int
+pi_bluetooth_open(struct pi_socket *ps, struct pi_sockaddr *addr, int addrlen)
+{
+ int fd, flags;
+ struct pi_bluetooth_data *data = ps->device->data;
+
+ pi_bluetooth_register_hotsync_sdp (data);
+ /* If we didn't manage to create an SDP record, force channel 22 and try
+ * again */
+ if (data->channel < 0) {
+ fprintf (stderr, "didn't manage to get a channel\n");
+ data->channel = 22;
+ }
+
+ if ((fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0)
+ return -1;
+
+ if ((flags = fcntl(fd, F_GETFL, 0)) != -1) {
+ flags &= ~O_NONBLOCK;
+ fcntl(fd, F_SETFL, flags);
+ }
+
+ if (pi_socket_setsd(ps, fd) < 0)
+ return -1;
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_device
+ *
+ * Summary: creates and inits pi_device struct instance
+ *
+ * Parameters: device type
+ *
+ * Returns: pi_device_t* or NULL if operation failed
+ *
+ ***********************************************************************/
+pi_device_t*
+pi_bluetooth_device (int type)
+{
+ pi_device_t *dev;
+ struct pi_bluetooth_data *data;
+
+ dev = (pi_device_t *) malloc(sizeof (pi_device_t));
+ if (dev == NULL)
+ return NULL;
+
+ data = (struct pi_bluetooth_data *) malloc(sizeof (struct pi_bluetooth_data));
+ if (data == NULL) {
+ free(dev);
+ return NULL;
+ }
+
+ dev->free = pi_bluetooth_device_free;
+ dev->protocol = pi_bluetooth_protocol;
+ dev->bind = pi_bluetooth_bind;
+ dev->listen = pi_bluetooth_listen;
+ dev->accept = pi_bluetooth_accept;
+ dev->connect = pi_bluetooth_connect;
+ dev->close = pi_bluetooth_close;
+
+ data->timeout = 0;
+ dev->data = data;
+
+ return dev;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_connect
+ *
+ * Summary: Connect socket to a given address
+ *
+ * Parameters: pi_socket*, sockaddr*, size_t
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_connect(pi_socket_t *ps, struct sockaddr *addr,
+ size_t addrlen)
+{
+ ps->raddr = malloc(addrlen);
+ memcpy(ps->raddr, addr, addrlen);
+ ps->raddrlen = addrlen;
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ if (ps->type == PI_SOCK_STREAM) {
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if (cmp_tx_handshake(ps) < 0)
+ goto fail;
+
+ break;
+
+ case PI_CMD_NET:
+ break;
+
+ case PI_CMD_SYS:
+ break;
+ }
+ }
+ ps->state = PI_SOCK_CONN_INIT;
+ ps->command = 0;
+
+ return 0;
+
+fail:
+ pi_close (ps->sd);
+ return -1;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_bind
+ *
+ * Summary: Bind address to a local socket
+ *
+ * Parameters: pi_socket*, sockaddr*, size_t
+ *
+ * Returns: A negative number on error, 0 otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_bind(pi_socket_t *ps, struct sockaddr *addr, size_t addrlen)
+{
+ struct pi_sockaddr *pa = (struct pi_sockaddr *) addr;
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+ char *device = pa->pi_device;
+ struct sockaddr_rc bindaddr;
+
+ if (pi_bluetooth_open(ps, pa, addrlen) == -1)
+ return -1; /* errno already set */
+
+ data->device = strdup (device);
+
+ bindaddr.rc_family = AF_BLUETOOTH;
+ bacpy(&bindaddr.rc_bdaddr, BDADDR_ANY);
+ bindaddr.rc_channel = data->channel;
+
+ if (bind(ps->sd, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ return -1;
+ }
+
+ ps->laddr = malloc(addrlen);
+ memcpy(ps->laddr, addr, addrlen);
+ ps->laddrlen = addrlen;
+
+ return 0;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_listen
+ *
+ * Summary: Prepare for incoming connections
+ *
+ * Parameters: pi_socket*, backlog
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int pi_bluetooth_listen(pi_socket_t *ps, int backlog)
+{
+ int result;
+
+ listen(ps->sd, 10);
+ ps->state = PI_SOCK_LISTEN;
+
+ return result;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_accept_rfcomm
+ *
+ * Summary: Accept an incoming connection and associate it with an
+ * RFCOMM serial device
+ *
+ * Parameters: None
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_accept_rfcomm(struct pi_socket *ps, const char *device, struct sockaddr_rc *peeraddr, unsigned int *peeraddrlen)
+{
+ int rfcommfd;
+
+ rfcommfd = accept(ps->sd, (struct sockaddr *)peeraddr, peeraddrlen);
+ if (rfcommfd < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ return -1;
+ }
+
+ /* Check whether we need to really accept this connection */
+ if (device[0] != '\0' && strcmp (device, "any") != 0) {
+ bdaddr_t tmp;
+ if (str2ba (device, &tmp) < 0) {
+ close (rfcommfd);
+ return -1;
+ }
+ if (bacmp (&tmp, &(peeraddr->rc_bdaddr)) != 0) {
+ close (rfcommfd);
+ return -1;
+ }
+ }
+
+ return rfcommfd;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_accept
+ *
+ * Summary: Accept an incoming connection
+ *
+ * Parameters: pi_socket*, sockaddr*
+ *
+ * Returns: Nothing
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_accept(pi_socket_t *ps, struct sockaddr *addr,
+ size_t *addrlen)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+ struct sockaddr_rc peeraddr;
+ unsigned int peeraddrlen = sizeof(peeraddr);
+ int sd;
+
+ /* Wait for data */
+ sd = pi_bluetooth_accept_rfcomm(ps, data->device, &peeraddr, &peeraddrlen);
+ if (sd < 0) {
+ pi_set_error(ps->sd, PI_ERR_GENERIC_SYSTEM);
+ goto fail;
+ }
+
+ if (pi_socket_setsd(ps, sd) < 0)
+ return -1;
+ pi_socket_init(ps);
+
+ if (ps->type == PI_SOCK_STREAM) {
+ switch (ps->cmd) {
+ case PI_CMD_CMP:
+ if (cmp_rx_handshake(ps, 0, 0) < 0)
+ return -1;
+
+ break;
+ case PI_CMD_NET:
+ if (net_rx_handshake(ps) < 0)
+ return -1;
+ break;
+ }
+
+ ps->dlprecord = 0;
+ }
+
+ data->timeout = 0;
+ ps->command = 0;
+ ps->state = PI_SOCK_CONN_ACCEPT;
+
+ return ps->sd;
+
+fail:
+ return -1;
+}
+
+static int
+pi_bluetooth_flush(pi_socket_t *ps, int flags)
+{
+ char buf[256];
+ int fl;
+
+ if (flags & PI_FLUSH_INPUT) {
+ if ((fl = fcntl(ps->sd, F_GETFL, 0)) != -1) {
+ fcntl(ps->sd, F_SETFL, fl | O_NONBLOCK);
+ while (read(ps->sd, buf, sizeof(buf)) > 0)
+ ;
+ fcntl(ps->sd, F_SETFL, fl);
+ }
+ }
+ return 0;
+}
+
+static ssize_t
+pi_bluetooth_read(struct pi_socket *ps, pi_buffer_t *buf, size_t len, int flags)
+{
+ int rbuf;
+ struct pi_bluetooth_data *data = (struct pi_bluetooth_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ if (pi_buffer_expect (buf, len) == NULL) {
+ return pi_set_error(ps->sd, PI_ERR_GENERIC_MEMORY);
+ }
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ /* If timeout == 0, wait forever for packet, otherwise wait till
+ timeout milliseconds */
+ if (data->timeout == 0)
+ select(ps->sd + 1, &ready, 0, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ select(ps->sd + 1, &ready, 0, 0, &t);
+ }
+ /* If data is available in time, read it */
+ if (FD_ISSET(ps->sd, &ready)) {
+ if (flags == PI_MSG_PEEK && len > 256)
+ len = 256;
+ rbuf = read(ps->sd, buf->data + buf->used, len);
+ } else {
+ LOG((PI_DBG_DEV, PI_DBG_LVL_WARN, "DEV RX BlueTooth timeout\n"));
+ pi_set_error(ps->sd, PI_ERR_SOCK_TIMEOUT);
+ return -1;
+ }
+ buf->used += rbuf;
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV RX BlueTooth Bytes: %d\n", rbuf));
+
+ return rbuf;
+}
+
+static ssize_t
+pi_bluetooth_write(struct pi_socket *ps, const unsigned char *buf, size_t len, int flags)
+{
+ int total,
+ nwrote;
+ struct pi_bluetooth_data *data = (struct pi_bluetooth_data *)ps->device->data;
+ struct timeval t;
+ fd_set ready;
+
+ FD_ZERO(&ready);
+ FD_SET(ps->sd, &ready);
+
+ total = len;
+ while (total > 0) {
+ if (data->timeout == 0)
+ select(ps->sd + 1, 0, &ready, 0, 0);
+ else {
+ t.tv_sec = data->timeout / 1000;
+ t.tv_usec = (data->timeout % 1000) * 1000;
+ select(ps->sd + 1, 0, &ready, 0, &t);
+ }
+ if (!FD_ISSET(ps->sd, &ready)) {
+ pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ return -1;
+ }
+ nwrote = write(ps->sd, buf, len);
+ if (nwrote < 0) {
+ pi_set_error(ps->sd, PI_ERR_SOCK_IO);
+ return -1;
+ }
+ total -= nwrote;
+ }
+
+ LOG((PI_DBG_DEV, PI_DBG_LVL_INFO, "DEV TX BlueTooth Bytes: %d\n", len));
+ return len;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_getsockopt
+ *
+ * Summary: get options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_getsockopt(pi_socket_t *ps, int level, int option_name,
+ void *option_value, size_t *option_len)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_TIMEOUT:
+ if (*option_len < sizeof (data->timeout))
+ goto error;
+ memcpy (option_value, &data->timeout,
+ sizeof (data->timeout));
+ *option_len = sizeof (data->timeout);
+ break;
+ }
+
+ return 0;
+error:
+ pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ return -1;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_setsockopt
+ *
+ * Summary: set options on socket
+ *
+ * Parameters: pi_socket*, level, option name, option value, option length
+ *
+ * Returns: 0 for success, negative otherwise
+ *
+ ***********************************************************************/
+static int
+pi_bluetooth_setsockopt(pi_socket_t *ps, int level, int option_name,
+ const void *option_value, size_t *option_len)
+{
+ struct pi_bluetooth_data *data =
+ (struct pi_bluetooth_data *)ps->device->data;
+
+ switch (option_name) {
+ case PI_DEV_TIMEOUT:
+ if (*option_len != sizeof (data->timeout))
+ goto error;
+ memcpy (&data->timeout, option_value,
+ sizeof (data->timeout));
+ break;
+ }
+
+ return 0;
+
+error:
+ pi_set_error(ps->sd, PI_ERR_GENERIC_ARGUMENT);
+ return -1;
+}
+
+/***********************************************************************
+ *
+ * Function: pi_bluetooth_close
+ *
+ * Summary: Close a connection, destroy the socket
+ *
+ * Parameters: pi_socket*
+ *
+ * Returns: always 0 for success
+ *
+ ***********************************************************************/
+static int pi_bluetooth_close(pi_socket_t *ps)
+{
+ if (ps->laddr) {
+ free(ps->laddr);
+ ps->laddr = NULL;
+ }
+
+ if (ps->raddr) {
+ free(ps->raddr);
+ ps->raddr = NULL;
+ }
+
+ return 0;
+}
+
+/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
+/* Local Variables: */
+/* indent-tabs-mode: t */
+/* c-basic-offset: 8 */
+/* End: */
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2005-09-22 21:51 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-22 18:05 [Bluez-devel] [PATCH] Palm Hotsync over Bluetooth Bastien Nocera
2005-09-22 18:23 ` Marcel Holtmann
2005-09-22 21:51 ` Bastien Nocera
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.