Bluetooth PAN support for FreeBSD

Rako rako29 at gmail.com
Mon Mar 10 23:40:40 UTC 2008


Hi, I write the code to teach sdpd and libsdp about pan profiles. Also 
write the registration of NAP service on btpand daemon.

Tested with sony ericsson w850i.

Thanks Maksim for the btpand work!
Rako

-------------- next part --------------
diff -Nua sdpd.orig/Makefile sdpd/Makefile
--- sdpd.orig/Makefile	2005-01-05 15:37:37.000000000 -0300
+++ sdpd/Makefile	2008-03-10 20:11:59.000000000 -0300
@@ -4,7 +4,7 @@
 PROG=		sdpd
 MAN=		sdpd.8
 SRCS=		bgd.c dun.c ftrn.c irmc.c irmc_command.c lan.c log.c main.c \
-		opush.c profile.c provider.c sar.c scr.c sd.c server.c sp.c \
+		opush.c profile.c provider.c sar.c scr.c sd.c server.c sp.c pan.c \
 		srr.c ssar.c ssr.c sur.c uuid.c
 
 CFLAGS+=	-I${.CURDIR}
diff -Nua sdpd.orig/pan.c sdpd/pan.c
--- sdpd.orig/pan.c	1969-12-31 21:00:00.000000000 -0300
+++ sdpd/pan.c	2008-03-10 20:11:59.000000000 -0300
@@ -0,0 +1,209 @@
+/*
+ * pan.c
+ *
+ */
+
+#include <arpa/inet.h>
+#include <sys/queue.h>
+#include <bluetooth.h>
+#include <sdp.h>
+#include <stdio.h>
+#include <string.h>
+#include "profile.h"
+#include "provider.h"
+
+static int32_t
+pan_profile_create_service_class_id_list(
+		uint8_t *buf, uint8_t const * const eob,
+		uint8_t const *data, uint32_t datalen)
+{
+	provider_p		provider = (provider_p) data;
+	sdp_pan_profile_p 	 pan = (sdp_pan_profile_p) provider->data;
+	
+	return (common_profile_create_service_class_id_list(
+			buf, eob,
+			(uint8_t const *)&pan->service,
+			sizeof(pan->security)));
+}
+
+/*
+ * seq8 len8			- 2 bytes
+ *	seq 8 len8		    - 2 bytes
+ *		uuid16 value16	- 3 bytes
+ *		uint16 value16	- 3 bytes
+ */
+static int32_t
+pan_profile_create_bluetooth_profile_descriptor_list(
+		uint8_t *buf, uint8_t const * const eob,
+		uint8_t const *data, uint32_t datalen)
+{
+	provider_p		provider = (provider_p) data;
+	sdp_pan_profile_p 	 pan = (sdp_pan_profile_p) provider->data;
+	
+	SDP_PUT8(SDP_DATA_SEQ8, buf);
+	SDP_PUT8(8, buf);
+
+	SDP_PUT8(SDP_DATA_SEQ8, buf);
+	SDP_PUT8(6, buf);
+	SDP_PUT8(SDP_DATA_UUID16, buf);
+	SDP_PUT16(pan->service, buf);
+	SDP_PUT8(SDP_DATA_UINT16, buf);
+	SDP_PUT16(0x100, buf);
+	
+	return 10;
+}
+
+static int32_t
+pan_profile_create_service_name(
+		uint8_t *buf, uint8_t const * const eob,
+		uint8_t const *data, uint32_t datalen)
+{
+	static char	service_name[] = "NAP";
+
+	return (common_profile_create_string8(
+			buf, eob,
+			(uint8_t const *) service_name, strlen(service_name)));
+}
+
+/*
+ * seq8 len8			- 2 bytes
+ *	seq8 len8		    - 2 bytes
+ *		uuid16 value16	- 3 bytes
+ *      uint16 value16  - 3 bytes
+ *	seq8 len8		    - 2 bytes
+ *		uuid16 value16	- 3 bytes
+ *      uint16 value16  - 3 bytes
+ *		seq16 len16   	- 3 bytes
+ *       uint16 value16 - 3 bytes
+ *       uint16 value16 - 3 bytes
+ */
+static int32_t
+pan_profile_create_protocol_descriptor_list(
+		uint8_t *buf, uint8_t const * const eob,
+		uint8_t const *data, uint32_t datalen)
+{
+	provider_p		provider = (provider_p) data;
+	sdp_pan_profile_p 	 nap = (sdp_pan_profile_p) provider->data;
+
+	SDP_PUT8(SDP_DATA_SEQ8, buf);
+#ifndef INET6	
+	SDP_PUT8(25, buf);
+#else
+	SDP_PUT8(28, buf);	
+#endif
+
+	SDP_PUT8(SDP_DATA_SEQ8, buf);
+	SDP_PUT8(6, buf);
+	SDP_PUT8(SDP_DATA_UUID16, buf);
+	SDP_PUT16(SDP_UUID_PROTOCOL_L2CAP, buf);
+	SDP_PUT8(SDP_DATA_UINT16, buf);
+	SDP_PUT16(nap->psm, buf);
+
+	SDP_PUT8(SDP_DATA_SEQ8, buf);
+	SDP_PUT8(15, buf);
+	SDP_PUT8(SDP_DATA_UUID16, buf);
+	SDP_PUT16(SDP_UUID_PROTOCOL_BNEP, buf);
+	SDP_PUT8(SDP_DATA_UINT16, buf);
+	SDP_PUT16(0x0100, buf);
+	SDP_PUT8(SDP_DATA_SEQ16, buf);
+#ifndef INET6
+	SDP_PUT16(6,buf);
+#else
+	SDP_PUT16(9,buf);	
+#endif
+	SDP_PUT8(SDP_DATA_UINT16, buf);
+	SDP_PUT16(0x0800, buf);
+	SDP_PUT8(SDP_DATA_UINT16, buf);
+	SDP_PUT16(0x0806, buf);
+#ifdef INET6
+	SDP_PUT8(SDP_DATA_UINT16, buf);
+	SDP_PUT16(0x86dd, buf);	
+#endif
+
+#ifndef INET6
+	return (27);
+#else
+	return (29);
+#endif
+}
+
+/* 
+ *   uint16 value16  - 3 bytes
+ */
+static int32_t
+pan_profile_create_security_description(
+	uint8_t *buf, uint8_t const * const eob,
+	uint8_t const *data, uint32_t datalen)
+{
+	provider_p		provider = (provider_p) data;
+	sdp_pan_profile_p 	 nap = (sdp_pan_profile_p) provider->data;
+	
+	SDP_PUT8(SDP_DATA_UINT16, buf);
+	SDP_PUT16(nap->security, buf);
+	return (3);
+}
+
+/* 
+ *   uint16 value16  - 3 bytes
+ */
+static int32_t
+pan_profile_create_net_access_type(
+	uint8_t *buf, uint8_t const * const eob,
+	uint8_t const *data, uint32_t datalen)
+{
+	provider_p		provider = (provider_p) data;
+	sdp_pan_profile_p 	 pan = (sdp_pan_profile_p) provider->data;
+	
+	SDP_PUT8(SDP_DATA_UINT16, buf);	
+	SDP_PUT16(pan->net, buf);
+	return (3);
+}
+
+/* 
+ *   uint32 value32  - 5 bytes
+ */
+static int32_t
+pan_profile_create_max_net_access_rate(
+	uint8_t *buf, uint8_t const * const eob,
+	uint8_t const *data, uint32_t datalen)
+{
+	provider_p		provider = (provider_p) data;
+	sdp_pan_profile_p 	 pan = (sdp_pan_profile_p) provider->data;
+	
+	SDP_PUT8(SDP_DATA_UINT32, buf);	
+	SDP_PUT32(pan->rate, buf);
+	return (5);
+}
+
+
+static attr_t	pan_profile_attrs[] = {
+	{ SDP_ATTR_SERVICE_RECORD_HANDLE,
+	  common_profile_create_service_record_handle },
+	{ SDP_ATTR_SERVICE_CLASS_ID_LIST,
+	  pan_profile_create_service_class_id_list },
+	{ SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
+	  pan_profile_create_protocol_descriptor_list },
+	{ SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST,
+	  common_profile_create_language_base_attribute_id_list },
+	{ SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET, 
+	  pan_profile_create_service_name },
+	{ SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET, 
+	  pan_profile_create_service_name },
+	{ SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST,
+	  pan_profile_create_bluetooth_profile_descriptor_list },
+	{ SDP_ATTR_SECURITY_DESCRIPTION,
+	  pan_profile_create_security_description },
+	{ SDP_ATTR_NET_ACCESS_TYPE,
+	  pan_profile_create_net_access_type },
+	{ SDP_ATTR_MAX_NET_ACCESS_RATE,
+	  pan_profile_create_max_net_access_rate },		
+	{ 0, NULL } /* end entry */
+};
+
+profile_t	pan_profile_descriptor = {
+	SDP_SERVICE_CLASS_NAP,
+	sizeof(sdp_pan_profile_t),
+	common_profile_server_channel_valid,
+	(attr_t const * const) &pan_profile_attrs
+};
+
diff -Nua sdpd.orig/profile.c sdpd/profile.c
--- sdpd.orig/profile.c	2004-07-28 04:15:44.000000000 -0300
+++ sdpd/profile.c	2008-03-10 20:11:59.000000000 -0300
@@ -50,6 +50,7 @@
 	extern	profile_t	lan_profile_descriptor;
 	extern	profile_t	opush_profile_descriptor;
 	extern	profile_t	sp_profile_descriptor;
+	extern	profile_t	pan_profile_descriptor;
 
 	static const profile_p	profiles[] = {
 		&dun_profile_descriptor,
@@ -58,7 +59,8 @@
 		&irmc_command_profile_descriptor,
 		&lan_profile_descriptor,
 		&opush_profile_descriptor,
-		&sp_profile_descriptor
+		&sp_profile_descriptor,
+		&pan_profile_descriptor
 	};
 
 	int32_t			i;
-------------- next part --------------
--- main.c.orig	2008-03-10 19:30:26.000000000 -0300
+++ main.c	2008-03-10 20:01:10.000000000 -0300
@@ -39,6 +39,8 @@
 #include <syslog.h>
 #include <sys/param.h>
 #include <unistd.h>
+#include <bluetooth.h>
+#include <sdp.h>
 #include "btpand.h"
 
 
@@ -64,14 +66,45 @@
       if( !serv->detached )
 	fprintf(stderr,"[%d] %s\n",level,msg);
       free(msg);
-    }
+    }	
   }
 }
 
+/* SDP registration */
+static void sdp_register( int psm ) {
+	void             *xss;
+	bdaddr_t          bt_addr_any;
+	sdp_pan_profile_t pan;
+
+	xss = sdp_open_local(NULL);
+	if (xss == NULL)
+		errx(1, "Unable to create local SDP session");
+
+	if (sdp_error(xss) != 0)
+		errx(1, "Unable to open local SDP session. %s (%d)",
+			 strerror(sdp_error(xss)), sdp_error(xss));
+
+	/* setup service */
+	memset(&pan, 0, sizeof(pan));
+	pan.service  = SDP_SERVICE_CLASS_NAP;
+	pan.psm      = psm;
+	pan.version  = 0x0100;
+	pan.security = 0;
+	pan.net      = 0x0005;
+	pan.rate     = 0xffffffff;
+
+	memcpy(&bt_addr_any, NG_HCI_BDADDR_ANY, sizeof(bt_addr_any));
+	if (sdp_register_service(xss, SDP_SERVICE_CLASS_NAP, &bt_addr_any,
+							 (void *)&pan, sizeof(pan), NULL) != 0) {
+		errx(1, "Unable to register PAN service with "
+			 "local SDP daemon. %s (%d)",
+			 strerror(sdp_error(xss)), sdp_error(xss));
+	}
+}
+
 
 /* Server initialization
    --------------------- */
-
 static int init_btpand(btpand_t* serv, const char* ifname, bdaddr_t* addr,
 		       uint16_t psm, int verbosity, int detached)
 {
@@ -222,6 +255,8 @@
     }
   }
 
+  sdp_register( psm );
+
   if( ( rv = init_btpand(&serv,ifname,&addr,psm,verbosity,detached) ) )
     return rv;
 
-------------- next part --------------
--- sdp.h.orig	2006-08-26 20:16:35.000000000 -0300
+++ sdp.h	2008-03-10 20:04:50.000000000 -0300
@@ -629,6 +629,18 @@
 typedef struct sdp_lan_profile		sdp_lan_profile_t;
 typedef struct sdp_lan_profile *	sdp_lan_profile_p;
 
+struct sdp_pan_profile
+{
+	uint16_t	psm;
+	uint16_t    version;
+	uint16_t    security;
+	uint16_t    service;
+	uint16_t    net;
+	uint32_t    rate;
+};
+typedef struct sdp_pan_profile		sdp_pan_profile_t;
+typedef struct sdp_pan_profile *	sdp_pan_profile_p;
+
 /* Keep this in sync with sdp_irmc_profile */
 struct sdp_opush_profile
 {


More information about the freebsd-bluetooth mailing list