Diff between 50df085bb61a812f2f7eeaa8c9d8e850c8508725 and 57724fbcd3afc76acd2c9bc295164b51f865daa8

Changed Files

File Additions Deletions Status
tools/parser/l2cap.c +4 -0 modified
tools/parser/parser.h +1 -0 modified
tools/parser/sdp.c +594 -0 added
tools/parser/sdp.h +158 -0 added

Full Patch

diff --git a/tools/parser/l2cap.c b/tools/parser/l2cap.c
index b13990d..5a971e8 100644
--- a/tools/parser/l2cap.c
+++ b/tools/parser/l2cap.c
@@ -345,6 +345,10 @@ static void l2cap_parse(int level, struct frame *frm)
 		printf("L2CAP(d): cid 0x%x len %d [psm %d]\n", cid, dlen, psm);
 
 		switch (psm) {
+		case 0x01:
+			sdp_dump(level+1, frm);
+			break;
+
 		case 0x03:
 			rfcomm_dump(level+1, frm);
 			break;
diff --git a/tools/parser/parser.h b/tools/parser/parser.h
index 4e10589..88b5f70 100644
--- a/tools/parser/parser.h
+++ b/tools/parser/parser.h
@@ -52,6 +52,7 @@ void raw_dump(int level, struct frame *frm);
 void hci_dump(int level, struct frame *frm);
 void l2cap_dump(int level, struct frame *frm);
 void rfcomm_dump(int level, struct frame *frm);
+void sdp_dump(int level, struct frame *frm);
 
 static inline void indent(int level)
 {
diff --git a/tools/parser/sdp.c b/tools/parser/sdp.c
new file mode 100644
index 0000000..2268159
--- /dev/null
+++ b/tools/parser/sdp.c
@@ -0,0 +1,594 @@
+/* 
+	HCIDump - HCI packet analyzer	
+	Copyright (C) 2000-2001 Maxim Krasnyansky <maxk@qualcomm.com>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License version 2 as
+	published by the Free Software Foundation;
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+	OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+	IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM,
+	OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+	RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+	NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
+	USE OR PERFORMANCE OF THIS SOFTWARE.
+
+	ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS,
+	TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED.
+*/
+
+/*
+	SDP parser.
+	Copyright (C) 2001 Ricky Yuen <ryuen@qualcomm.com>
+*/
+
+/*
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <asm/types.h> 
+#include <netinet/in.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/l2cap.h>
+
+#include "parser.h"
+#include "sdp.h"
+
+static inline void print_de(int, struct frame*);
+
+sdp_siz_idx_lookup_table_t sdp_siz_idx_lookup_table[] = {
+	{ 0, 1  }, /* Size index = 0 */
+	{ 0, 2  }, /*              1 */
+	{ 0, 4  }, /*              2 */
+	{ 0, 8  }, /*              3 */
+	{ 0, 16 }, /*              4 */
+	{ 1, 1  }, /*              5 */
+	{ 1, 2  }, /*              6 */
+	{ 1, 4  }, /*              7 */
+};
+
+sdp_uuid_nam_lookup_table_t sdp_uuid_nam_lookup_table[] = {
+	{ SDP_UUID_SDP,                      "SDP"          },
+	{ SDP_UUID_UDP,                      "UDP"          },
+	{ SDP_UUID_RFCOMM,                   "RFCOMM"       },
+	{ SDP_UUID_TCP,                      "TCP"          },
+	{ SDP_UUID_TCS_BIN,                  "TCS-BIN"      },
+	{ SDP_UUID_TCS_AT,                   "TCS-AT"       },
+	{ SDP_UUID_OBEX,                     "OBEX"         },
+	{ SDP_UUID_IP,                       "IP"           },
+	{ SDP_UUID_FTP,                      "FTP"          },
+	{ SDP_UUID_HTTP,                     "HTTP"         },
+	{ SDP_UUID_WSP,                      "WSP"          },
+	{ SDP_UUID_L2CAP,                    "L2CAP"        },
+	{ SDP_UUID_SERVICE_DISCOVERY_SERVER, "SDServer"     },
+	{ SDP_UUID_BROWSE_GROUP_DESCRIPTOR,  "BrwsGrpDesc"  },
+	{ SDP_UUID_PUBLIC_BROWSE_GROUP,      "PubBrwsGrp"   },
+	{ SDP_UUID_SERIAL_PORT,              "SP"           },
+	{ SDP_UUID_LAN_ACCESS_PPP,           "LAN"          },
+	{ SDP_UUID_DIALUP_NETWORKING,        "DUN"          },
+	{ SDP_UUID_IR_MC_SYNC,               "IRMCSync"     },
+	{ SDP_UUID_OBEX_OBJECT_PUSH,         "OBEXObjPush"  },
+	{ SDP_UUID_OBEX_FILE_TRANSFER,       "OBEXObjTrnsf" },
+	{ SDP_UUID_IR_MC_SYNC_COMMAND,       "IRMCSyncCmd"  },
+	{ SDP_UUID_HEADSET,                  "Headset"      },
+	{ SDP_UUID_CORDLESS_TELEPHONY,       "CordlessTel"  },
+	{ SDP_UUID_INTERCOM,                 "Intercom"     },
+	{ SDP_UUID_FAX,                      "Fax"          },
+	{ SDP_UUID_HEADSET_AUDIO_GATEWAY,    "AG"           },
+	{ SDP_UUID_PNP_INFORMATION,          "PNPInfo"      },
+	{ SDP_UUID_GENERIC_NETWORKING,       "Networking"   },
+	{ SDP_UUID_GENERIC_FILE_TRANSFER,    "FileTrnsf"    },
+	{ SDP_UUID_GENERIC_AUDIO,            "Audio"        },
+	{ SDP_UUID_GENERIC_TELEPHONY,        "Telephony"    }
+};
+
+sdp_attr_id_nam_lookup_table_t sdp_attr_id_nam_lookup_table[] = {
+	{ SDP_ATTR_ID_SERVICE_RECORD_HANDLE,             "SrvRecHndl"         },
+	{ SDP_ATTR_ID_SERVICE_CLASS_ID_LIST,             "SrvClassIDList"     },
+	{ SDP_ATTR_ID_SERVICE_RECORD_STATE,              "SrvRecState"        },
+	{ SDP_ATTR_ID_SERVICE_SERVICE_ID,                "SrvID"              },
+	{ SDP_ATTR_ID_PROTOCOL_DESCRIPTOR_LIST,          "ProtocolDescList"   },
+	{ SDP_ATTR_ID_BROWSE_GROUP_LIST,                 "BrwGrpList"         },
+	{ SDP_ATTR_ID_LANGUAGE_BASE_ATTRIBUTE_ID_LIST,   "LangBaseAttrIDList" },
+	{ SDP_ATTR_ID_SERVICE_INFO_TIME_TO_LIVE,         "SrvInfoTimeToLive"  },
+	{ SDP_ATTR_ID_SERVICE_AVAILABILITY,              "SrvAvail"           },
+	{ SDP_ATTR_ID_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, "BTProfileDescList"  },
+	{ SDP_ATTR_ID_DOCUMENTATION_URL,                 "DocURL"             },
+	{ SDP_ATTR_ID_CLIENT_EXECUTABLE_URL,             "ClientExeURL"       },
+	{ SDP_ATTR_ID_ICON_10,                           "Icon10"             },
+	{ SDP_ATTR_ID_ICON_URL,                          "IconURL"            },
+	{ SDP_ATTR_ID_SERVICE_NAME,                      "SrvName"            },
+	{ SDP_ATTR_ID_SERVICE_DESCRIPTION,               "SrvDesc"            },
+	{ SDP_ATTR_ID_PROVIDER_NAME,                     "ProviderName"       },
+	{ SDP_ATTR_ID_VERSION_NUMBER_LIST,               "VersionNumList"     },
+	{ SDP_ATTR_ID_GROUP_ID,                          "GrpID"              },
+	{ SDP_ATTR_ID_SERVICE_DATABASE_STATE,            "SrvDBState"         },
+	{ SDP_ATTR_ID_SERVICE_VERSION,                   "SrvVersion"         }
+};
+
+static inline __u8 get_u8(struct frame *frm)
+{
+	__u8 *u8_ptr = frm->ptr;
+	frm->ptr += 1;
+	frm->len -= 1;
+	return *u8_ptr;
+}
+
+static inline __u16 get_u16(struct frame *frm)
+{
+	__u16 *u16_ptr = frm->ptr;
+	frm->ptr += 2;
+	frm->len -= 2;
+	return ntohs(*u16_ptr);
+}
+
+static inline __u32 get_u32(struct frame *frm)
+{
+	__u32 *u32_ptr = frm->ptr;
+	frm->ptr += 4;
+	frm->len -= 4;
+	return ntohl(*u32_ptr);
+}
+
+
+static inline char* get_uuid_name(int uuid)
+{
+	int i;
+
+	for (i = 0; i < SDP_UUID_NAM_LOOKUP_TABLE_SIZE; i++)
+	{
+		if (sdp_uuid_nam_lookup_table[i].uuid == uuid)
+		{
+			return sdp_uuid_nam_lookup_table[i].name;
+		}
+	}
+
+	return 0;
+}
+
+static inline char* get_attr_id_name(int attr_id)
+{
+	int i;
+
+	for (i = 0; i < SDP_ATTR_ID_NAM_LOOKUP_TABLE_SIZE; i++)
+	{
+		if (sdp_attr_id_nam_lookup_table[i].attr_id == attr_id)
+		{
+			return sdp_attr_id_nam_lookup_table[i].name;
+		}
+	}
+
+	return 0;
+}
+
+static inline __u8 parse_de_hdr(struct frame *frm, int* n)
+{
+	__u8	de_hdr = get_u8(frm);
+	__u8	de_type = de_hdr >> 3;
+	__u8	siz_idx = de_hdr & 0x07;
+
+	/* Get the number of bytes */
+	if (sdp_siz_idx_lookup_table[siz_idx].addl_bits) {
+		switch(sdp_siz_idx_lookup_table[siz_idx].num_bytes) {
+		case 1:
+			*n = get_u8(frm); break;
+		case 2:
+			*n = get_u16(frm); break;
+		case 4:
+			*n = get_u32(frm); break;
+		}
+	} else {
+		*n = sdp_siz_idx_lookup_table[siz_idx].num_bytes;
+	}
+
+	return de_type;
+}
+
+static inline void print_des(__u8 de_type, int level, int n, struct frame *frm)
+{
+	int len = frm->len;
+
+	while (len - frm->len < n ) {
+		print_de(level, frm);
+	}
+}
+
+static inline void print_int(__u8 de_type, int level, int n, struct frame *frm)
+{
+	__u64 val;
+
+	switch(de_type) {
+	case SDP_DE_UINT:
+		printf(" uint");
+		break;
+	case SDP_DE_INT:
+		printf(" int");
+		break;
+	case SDP_DE_BOOL:
+		printf(" bool");
+		break;
+	}
+
+	switch(n) {
+	case 1: /* 8-bit */
+		val = get_u8(frm);
+		break;
+	case 2: /* 16-bit */
+		val = get_u16(frm);
+		break;
+	case 4: /* 32-bit */
+		val = get_u32(frm);
+		break;
+	case 8: /* 64-bit */
+		/* Not supported yet */
+		val = 0;
+		break;
+	default: /* syntax error */
+		printf(" err");
+		frm->ptr += n;
+		frm->len -= n;
+		return;
+	}
+
+	printf(" 0x%llx", val);
+}
+
+static inline void print_uuid(int n, struct frame *frm)
+{
+	__u32 uuid = 0;
+	char* s;
+
+	switch(n) {
+	case 2: /* 16-bit UUID */
+		uuid = get_u16(frm);
+		break;
+	case 4: /* 32_bit UUID */
+		uuid = get_u32(frm);
+		break;
+	case 16: /* 128-bit UUID */
+		uuid = get_u32(frm);
+		frm->ptr += 12;
+		frm->len -= 12;
+		break;
+	default: /* syntax error */
+		printf(" *err*");
+		frm->ptr += n;
+		frm->len -= n;
+		return;
+	}
+
+	printf(" 0x%x", uuid);
+	if ((s = get_uuid_name(uuid)) != 0)
+	{
+		printf(" (%s)", s);
+	}
+}
+
+static inline void print_string(int n, struct frame *frm)
+{
+	char	*s;
+
+	printf(" str");
+	if ((s = malloc(n + 1))) {
+		s = frm->ptr;
+		s[n] = '\0';
+		printf(" \"%s\"", s);
+	} else {
+		perror("Can't allocate string buffer");
+	}
+
+	frm->ptr += n;
+	frm->len -= n;
+}
+
+static inline void print_de(int level, struct frame *frm)
+{
+	int  n;
+	__u8 de_type = parse_de_hdr(frm, &n);
+
+	switch(de_type) {
+	case SDP_DE_NULL:
+		printf("null");
+		break;
+	case SDP_DE_UINT:
+	case SDP_DE_INT:
+	case SDP_DE_BOOL:
+		print_int(de_type, level, n, frm);
+		break;
+	case SDP_DE_UUID:
+		print_uuid(n, frm);
+		break;
+	case SDP_DE_STRING:
+		print_string(n, frm);
+		break;
+	case SDP_DE_SEQ:
+	case SDP_DE_ALT:
+		print_des(de_type, ++level, n, frm);
+		break;
+	case SDP_DE_URL:
+		break;
+	}
+}
+
+
+static inline void print_srv_srch_pat(int level, struct frame *frm)
+{
+	int len = frm->len;
+	int n1;
+	int n2;
+
+	indent(level);
+	printf("pat");
+
+	if (parse_de_hdr(frm, &n1) == SDP_DE_SEQ) {
+		while (len - frm->len < n1 ) {
+			if (parse_de_hdr(frm,&n2) == SDP_DE_UUID) {
+				print_uuid(n2, frm);
+			} else {
+				printf("\nERROR: Unexpected syntax\n");
+				raw_dump(level, frm);
+			}
+		}
+		printf("\n");
+	} else {
+		printf("\nERROR: Unexpected syntax\n");
+		raw_dump(level, frm);
+	}
+}
+
+
+static inline void print_attr_id_list(int level, struct frame *frm)
+{
+	__u16 attr_id;
+	__u32 attr_id_range;
+	int   n1;
+	int   n2;
+	int   len = frm->len;
+
+	indent(level);
+	printf("aid(s)");
+
+	if (parse_de_hdr(frm, &n1) == SDP_DE_SEQ) {
+		while (len - frm->len < n1 ) {
+			/* Print AttributeID */
+			if (parse_de_hdr(frm, &n2) == SDP_DE_UINT) {
+				switch(n2) {
+				case 2:
+					attr_id = get_u16(frm);
+					printf(" 0x%x (%s)", attr_id, get_attr_id_name(attr_id));
+					break;
+				case 4:
+					attr_id_range = get_u32(frm);
+					printf(" 0x%x--0x%x",
+							(attr_id_range >> 16),
+							(attr_id_range & 0x00FF));
+					break;
+				}
+			} else {
+				printf("\nERROR: Unexpected syntax\n");
+				raw_dump(level, frm);
+			}
+		}
+		printf("\n");
+	} else {
+		printf("\nERROR: Unexpected syntax\n");
+		raw_dump(level, frm);
+	}
+}
+
+
+static inline void print_attr_list(int level, struct frame *frm)
+{
+	__u16 attr_id;
+	int   n1;
+	int   n2;
+	int   len = frm->len;
+
+	if (parse_de_hdr(frm, &n1) == SDP_DE_SEQ) {
+		while (len - frm->len < n1 ) {
+			/* Print AttributeID */
+			if ((parse_de_hdr(frm, &n2) == SDP_DE_UINT) &&
+				 (n2 == sizeof(attr_id))) {
+				attr_id = get_u16(frm);
+				indent(level);
+				printf("aid 0x%x (%s)\n", attr_id, get_attr_id_name(attr_id));
+
+				/* Print AttributeValue */
+				indent(++level);
+				print_de(level, frm);
+			} else {
+				printf("\nERROR: Unexpected syntax\n");
+				raw_dump(level, frm);
+				break;
+			}
+		}
+		printf("\n");
+	} else {
+		printf("\nERROR: Unexpected syntax\n");
+		raw_dump(level, frm);
+	}
+}
+
+
+static inline void print_attr_lists(int level, struct frame *frm)
+{
+	int   n;
+	int   cnt = 0;
+	int   len = frm->len;
+
+	if (parse_de_hdr(frm, &n) == SDP_DE_SEQ) {
+		while (len - frm->len < n ) {
+			indent(level);
+			printf("srv rec #%d\n", cnt++);
+			print_attr_list(level+1, frm);
+		}
+	} else {
+		printf("\nERROR: Unexpected syntax\n");
+		raw_dump(level, frm);
+	}
+}
+
+
+static inline void err_rsp(int level, __u16 tid, __u16 len, struct frame *frm)
+{
+	printf("SDP Error Rsp: tid 0x%x len 0x%x\n", tid, len);
+
+	indent(++level);
+   printf("ec 0x%x info ", get_u16(frm));
+	if (frm->len > 0) {
+		raw_dump(0, frm);
+	} else {
+		printf("none\n");
+	}
+}
+
+
+static inline void ss_req(int level, __u16 tid, __u16 len, struct frame *frm)
+{
+	printf("SDP SS Req: tid 0x%x len 0x%x\n", tid, len);
+
+	/* Parse ServiceSearchPattern */
+	print_srv_srch_pat(++level, frm);
+
+	/* Parse MaximumServiceRecordCount */
+	indent(level);
+	printf("max 0x%x\n", get_u16(frm));
+}
+
+static inline void ss_rsp(int level, __u16 tid, __u16 len, struct frame *frm)
+{
+	register int i;
+	__u16 cur_srv_rec_cnt = get_u16(frm); /* Parse CurrentServiceRecordCount */
+	__u16 tot_srv_rec_cnt = get_u16(frm); /* Parse TotalServiceRecordCount */
+
+	printf("SDP SS Rsp: tid 0x%x len 0x%x\n", tid, len);
+
+	indent(++level);
+	printf("cur 0x%x tot 0x%x", cur_srv_rec_cnt, tot_srv_rec_cnt);
+
+	/* Parse service record handle(s) */
+	if (cur_srv_rec_cnt > 0) {
+		printf(" hndl");
+		for (i = 0; i < cur_srv_rec_cnt; i++) {
+			printf(" 0x%x", get_u32(frm));
+		}
+	}
+	printf("\n");
+}
+
+static inline void sa_req(int level, __u16 tid, __u16 len, struct frame *frm)
+{
+	printf("SDP SA Req: tid 0x%x len 0x%x\n", tid, len);
+
+	/* Parse ServiceRecordHandle */
+	indent(++level);
+	printf("hndl 0x%x\n", get_u32(frm));
+
+	/* Parse MaximumAttributeByteCount */
+	indent(level);
+	printf("max 0x%x\n", get_u16(frm));
+
+	/* Parse ServiceSearchPattern */
+	print_attr_id_list(level, frm);
+}
+
+static inline void sa_rsp(int level, __u16 tid, __u16 len, struct frame *frm)
+{
+	printf("SDP SA Rsp: tid 0x%x len 0x%x\n", tid, len);
+
+	/* Parse AttributeByteCount */
+	indent(++level);
+	printf("cnt 0x%x\n", get_u16(frm));
+
+	/* Parse AttributeList */
+	print_attr_list(level, frm);
+}
+
+static inline void ssa_req(int level, __u16 tid, __u16 len, struct frame *frm)
+{
+	printf("SDP SSA Req: tid 0x%x len 0x%x\n", tid, len);
+
+	/* Parse ServiceSearchPattern */
+	print_srv_srch_pat(++level, frm);
+
+	/* Parse MaximumAttributeByteCount */
+	indent(level);
+   printf("max 0x%x\n", get_u16(frm));
+
+	/* Parse AttributeList */
+	print_attr_id_list(level, frm);
+}
+
+static inline void ssa_rsp(int level, __u16 tid, __u16 len, struct frame *frm)
+{
+	printf("SDP SSA Rsp: tid 0x%x len 0x%x\n", tid, len);
+
+	/* Parse AttributeByteCount */
+	indent(++level);
+	printf("cnt 0x%x\n", get_u16(frm));
+
+	/* Parse AttributeLists */
+	print_attr_lists(level, frm);
+}
+
+void sdp_dump(int level, struct frame *frm)
+{
+	sdp_pdu_hdr *hdr = frm->ptr;
+ 	__u16 tid = ntohs(hdr->tid);
+	__u16 len = ntohs(hdr->len);
+
+	frm->ptr += SDP_PDU_HDR_SIZE;
+	frm->len -= SDP_PDU_HDR_SIZE;
+
+	indent(++level);
+
+	switch(hdr->pid) {
+	case SDP_ERROR_RSP:
+		err_rsp(level, tid, len, frm);
+		break;
+	case SDP_SERVICE_SEARCH_REQ:
+		ss_req(level, tid, len, frm);
+		break;
+	case SDP_SERVICE_SEARCH_RSP:
+		ss_rsp(level, tid, len, frm);
+		break;
+	case SDP_SERVICE_ATTR_REQ:
+		sa_req(level, tid, len, frm);
+		break;
+	case SDP_SERVICE_ATTR_RSP:
+		sa_rsp(level, tid, len, frm);
+		break;
+	case SDP_SERVICE_SEARCH_ATTR_REQ:
+		ssa_req(level, tid, len, frm);
+		break;
+	case SDP_SERVICE_SEARCH_ATTR_RSP:
+		ssa_rsp(level, tid, len, frm);
+		break;
+	default:
+		printf("ERROR: Unknown PDU ID: 0x%x\n", hdr->pid);
+		raw_dump(++level, frm);
+		return;
+	}
+
+	if (hdr->pid != SDP_ERROR_RSP)
+	{
+		/* Parse ContinuationState */
+		if (*(__u8*) frm->ptr)	{
+			indent(++level);
+			printf("cont ");
+			raw_dump(0, frm);
+		}
+	}
+}
diff --git a/tools/parser/sdp.h b/tools/parser/sdp.h
new file mode 100644
index 0000000..b240110
--- /dev/null
+++ b/tools/parser/sdp.h
@@ -0,0 +1,158 @@
+/* 
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2000-2001 Qualcomm Incorporated
+
+   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   SOFTWARE IS DISCLAIMED.
+*/
+
+/*
+	SDP parser.
+	Copyright (C) 2001 Ricky Yuen <ryuen@qualcomm.com>
+*/
+
+/*
+ *  $Id$
+ */
+
+#ifndef __SDP_H
+#define __SDP_H
+
+#define SDP_ERROR_RSP                                  0x01
+#define SDP_SERVICE_SEARCH_REQ                         0x02
+#define SDP_SERVICE_SEARCH_RSP                         0x03
+#define SDP_SERVICE_ATTR_REQ                           0x04
+#define SDP_SERVICE_ATTR_RSP                           0x05
+#define SDP_SERVICE_SEARCH_ATTR_REQ                    0x06
+#define SDP_SERVICE_SEARCH_ATTR_RSP                    0x07
+
+/* Bluetooth assigned UUIDs for protocols */
+#define SDP_UUID_SDP                                   0x0001
+#define SDP_UUID_UDP                                   0x0002
+#define SDP_UUID_RFCOMM                                0x0003
+#define SDP_UUID_TCP                                   0x0004
+#define SDP_UUID_TCS_BIN                               0x0005
+#define SDP_UUID_TCS_AT                                0x0006
+#define SDP_UUID_OBEX                                  0x0008
+#define SDP_UUID_IP                                    0x0009
+#define SDP_UUID_FTP                                   0x000A
+#define SDP_UUID_HTTP                                  0x000C
+#define SDP_UUID_WSP                                   0x000E
+#define SDP_UUID_L2CAP                                 0x0100
+
+/* Bluetooth assigned UUIDs for Service Classes */
+#define SDP_UUID_SERVICE_DISCOVERY_SERVER              0x1000
+#define SDP_UUID_BROWSE_GROUP_DESCRIPTOR               0x1001
+#define SDP_UUID_PUBLIC_BROWSE_GROUP                   0x1002
+#define SDP_UUID_SERIAL_PORT                           0x1101
+#define SDP_UUID_LAN_ACCESS_PPP                        0x1102
+#define SDP_UUID_DIALUP_NETWORKING                     0x1103
+#define SDP_UUID_IR_MC_SYNC                            0x1104
+#define SDP_UUID_OBEX_OBJECT_PUSH                      0x1105
+#define SDP_UUID_OBEX_FILE_TRANSFER                    0x1106
+#define SDP_UUID_IR_MC_SYNC_COMMAND                    0x1107
+#define SDP_UUID_HEADSET                               0x1108
+#define SDP_UUID_CORDLESS_TELEPHONY                    0x1109
+#define SDP_UUID_INTERCOM                              0x1110
+#define SDP_UUID_FAX                                   0x1111
+#define SDP_UUID_HEADSET_AUDIO_GATEWAY                 0x1112
+#define SDP_UUID_PNP_INFORMATION                       0x1200
+#define SDP_UUID_GENERIC_NETWORKING                    0x1201
+#define SDP_UUID_GENERIC_FILE_TRANSFER                 0x1202
+#define SDP_UUID_GENERIC_AUDIO                         0x1203
+#define SDP_UUID_GENERIC_TELEPHONY                     0x1204
+
+/* Bluetooth assigned numbers for Attribute IDs */
+#define SDP_ATTR_ID_SERVICE_RECORD_HANDLE              0x0000
+#define SDP_ATTR_ID_SERVICE_CLASS_ID_LIST              0x0001
+#define SDP_ATTR_ID_SERVICE_RECORD_STATE               0x0002
+#define SDP_ATTR_ID_SERVICE_SERVICE_ID                 0x0003
+#define SDP_ATTR_ID_PROTOCOL_DESCRIPTOR_LIST           0x0004
+#define SDP_ATTR_ID_BROWSE_GROUP_LIST                  0x0005
+#define SDP_ATTR_ID_LANGUAGE_BASE_ATTRIBUTE_ID_LIST    0x0006
+#define SDP_ATTR_ID_SERVICE_INFO_TIME_TO_LIVE          0x0007
+#define SDP_ATTR_ID_SERVICE_AVAILABILITY               0x0008
+#define SDP_ATTR_ID_BLUETOOTH_PROFILE_DESCRIPTOR_LIST  0x0009
+#define SDP_ATTR_ID_DOCUMENTATION_URL                  0x000A
+#define SDP_ATTR_ID_CLIENT_EXECUTABLE_URL              0x000B
+#define SDP_ATTR_ID_ICON_10                            0x000C
+#define SDP_ATTR_ID_ICON_URL                           0x000D
+#define SDP_ATTR_ID_SERVICE_NAME                       0x0100
+#define SDP_ATTR_ID_SERVICE_DESCRIPTION                0x0101
+#define SDP_ATTR_ID_PROVIDER_NAME                      0x0102
+#define SDP_ATTR_ID_VERSION_NUMBER_LIST                0x0200
+#define SDP_ATTR_ID_GROUP_ID                           0x0200
+#define SDP_ATTR_ID_SERVICE_DATABASE_STATE             0x0201
+#define SDP_ATTR_ID_SERVICE_VERSION                    0x0300
+
+#define SDP_ATTR_ID_EXTERNAL_NETWORK                   0x0301 /* Cordless Telephony */
+#define SDP_ATTR_ID_SUPPORTED_DATA_STORES_LIST         0x0301 /* Synchronization */
+#define SDP_ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL        0x0302 /* GAP */
+#define SDP_ATTR_ID_SUPPORTED_FORMATS_LIST             0x0303 /* OBEX Object Push */
+#define SDP_ATTR_ID_FAX_CLASS_1_SUPPORT                0x0302 /* Fax */
+#define SDP_ATTR_ID_FAX_CLASS_2_0_SUPPORT              0x0303
+#define SDP_ATTR_ID_FAX_CLASS_2_SUPPORT                0x0304
+#define SDP_ATTR_ID_AUDIO_FEEDBACK_SUPPORT             0x0305
+
+/* Data element type descriptor */
+#define SDP_DE_NULL   0
+#define SDP_DE_UINT   1
+#define SDP_DE_INT    2
+#define SDP_DE_UUID   3
+#define SDP_DE_STRING 4
+#define SDP_DE_BOOL   5
+#define SDP_DE_SEQ    6
+#define SDP_DE_ALT    7
+#define SDP_DE_URL    8
+
+/* SDP structures */
+
+typedef struct {
+	__u8  pid;
+	__u16 tid;
+	__u16 len;
+} __attribute__ ((packed)) sdp_pdu_hdr;
+#define SDP_PDU_HDR_SIZE	5
+
+/* Data element size index lookup table */
+typedef struct {
+	int addl_bits;
+	int num_bytes;
+} sdp_siz_idx_lookup_table_t;
+extern sdp_siz_idx_lookup_table_t sdp_siz_idx_lookup_table[];
+
+/* UUID name lookup table */
+typedef struct {
+	int   uuid;
+	char* name;
+} sdp_uuid_nam_lookup_table_t;
+extern sdp_uuid_nam_lookup_table_t sdp_uuid_nam_lookup_table[];
+#define SDP_UUID_NAM_LOOKUP_TABLE_SIZE \
+	(sizeof(sdp_uuid_nam_lookup_table)/sizeof(sdp_uuid_nam_lookup_table_t))
+
+/* AttrID name lookup table */
+typedef struct {
+	int   attr_id;
+	char* name;
+} sdp_attr_id_nam_lookup_table_t;
+extern sdp_attr_id_nam_lookup_table_t sdp_attr_id_nam_lookup_table[];
+#define SDP_ATTR_ID_NAM_LOOKUP_TABLE_SIZE \
+	(sizeof(sdp_attr_id_nam_lookup_table)/sizeof(sdp_attr_id_nam_lookup_table_t))
+
+#endif /* __SDP_H */