Linux bluetooth development
 help / color / mirror / Atom feed
From: "Elvis Pfützenreuter" <epx@signove.com>
To: linux-bluetooth@vger.kernel.org
Cc: epx@signove.com
Subject: [PATCH 2/9] Adds Python module for HDP record parsing/generation
Date: Tue, 11 May 2010 12:38:16 -0300	[thread overview]
Message-ID: <1273592303-18234-2-git-send-email-epx@signove.com> (raw)
In-Reply-To: <1273592303-18234-1-git-send-email-epx@signove.com>

This patch adds the HDP record generation part, from a
easy-to-use dictionary to record in XML format.
---
 test/hdp/hdp_record.py |  193 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 193 insertions(+), 0 deletions(-)
 create mode 100644 test/hdp/hdp_record.py

diff --git a/test/hdp/hdp_record.py b/test/hdp/hdp_record.py
new file mode 100644
index 0000000..d4d72d6
--- /dev/null
+++ b/test/hdp/hdp_record.py
@@ -0,0 +1,193 @@
+#!/usr/bin/env python
+
+# This module is a prototype implementation of HDP profile
+# conversion from a simple dictionary to/from the XML format
+# that BlueZ understands.
+
+import xml.dom.minidom
+import string
+
+
+class HDPRecordException(Exception):
+	pass
+
+
+def myuint(value):
+	if type(value) is not int:
+		try:
+			value = string.atoi(value, 0)
+		except (TypeError, ValueError):
+			raise HDPRecordException("Invalid uint: %s", value)
+	if value < 0:
+		raise HDPRecordException("Value must be non-negative: %d" \
+						% value)
+	return value
+
+
+def add_attr(doc, parent, attr, data):
+	if attr is not None:
+		child = doc.createElement("attribute")
+		child.setAttribute("id", "0x%04x" % myuint(attr))
+		parent.appendChild(child)
+		parent = child
+
+	if type(data) is list:
+		child = doc.createElement("sequence")
+		for item in data:
+			add_attr(doc, child, None, item)
+	else:
+		element_type, value = data
+		if element_type == 'uint8':
+			value = "0x%02x" % myuint(value)
+		elif element_type == 'uint16':
+			value = "0x%04x" % myuint(value)
+		elif element_type == 'uint32':
+			value = "0x%08x" % myuint(value)
+		elif element_type == 'uuid' and type(value) is int:
+			value = "0x%04x" % value
+		child = doc.createElement(element_type)
+		child.setAttribute("value", value)
+
+	parent.appendChild(child)
+
+
+def gen_xml(service):
+	if not service['features']:
+		raise HDPRecordException("No HDP features")
+
+	cpsm = service['mcap_control_psm']
+	dpsm = service['mcap_data_psm']
+
+	if cpsm < 0x1001 or cpsm > 0xffff:
+		raise HDPRecordException("Control PSM invalid")
+	if dpsm < 0x1001 or dpsm > 0xffff or dpsm == cpsm:
+		raise HDPRecordException("Data PSM invalid")
+
+	doc = xml.dom.minidom.Document()
+	record = doc.createElement("record")
+	doc.appendChild(record)
+
+	roles = {}
+	mcap_supported_procedures = 0x00
+
+	for mcap_procedures in service.get('mcap_procedures', []):
+		if mcap_procedures == 'csp':
+			mcap_supported_procedures |= 0x08
+		elif mcap_procedures == 'csp_master':
+			mcap_supported_procedures |= 0x10
+		elif mcap_procedures == 'reconnect_init':
+			mcap_supported_procedures |= 0x02
+		elif mcap_procedures == 'reconnect_accept':
+			mcap_supported_procedures |= 0x04
+		else:
+			raise HDPRecordException("Unknown MCAP procedure: %s" \
+					% mcap_procedures)
+
+	data_spec = service.get('data_spec', 0x01) # 0x01 == IEEE 10267
+
+	hdp_features = []
+	mdeps = {}
+	data_types = {}
+
+	for feature in service['features']:
+		mdep_id = feature['mdep_id']
+		data_type = feature['data_type']
+		description = feature.get('description', None)
+		s_role = feature['role']
+
+		if s_role == 'source':
+			roles[0x1401] = True
+			role = 0x00
+		elif s_role == 'sink':
+			roles[0x1402] = True
+			role = 0x01
+		else:
+			raise HDPRecordException("Unknown role: %s" \
+				% feature['role'])
+
+		if role != mdeps.get(mdep_id, role):
+			raise HDPRecordException("Reusing MDEP ID %d " \
+				"for different role" % mdep_id)
+		mdeps[mdep_id] = role
+
+		if data_type in data_types:
+			if role in data_types[data_type]:
+				raise HDPRecordException("Redundant role/type" \
+					" tuple: (%s, %d)" % \
+					(s_role, data_type))
+			data_types[data_type].append(role)
+		else:
+			data_types[data_type] = [ role ]
+
+		feature_record = [ \
+			('uint8', mdep_id),
+			('uint16', data_type),
+			('uint8', role),
+			]
+		if description:
+			feature_record.append(('text', description))
+
+		hdp_features.append(feature_record)
+
+	if "handle" in service:
+		add_attr(doc, record, 0x0000, ('uint32', service['handle']))
+
+	roles_sequence = [('uuid', k) for k in roles.keys()]
+	add_attr(doc, record, 0x0001, roles_sequence)
+
+	add_attr(doc, record, 0x0004,	# protocol descriptor list
+		[
+			[
+				('uuid', 0x0100), # L2CAP
+				('uint16', cpsm), # control channel
+			], [
+				('uuid', 0x001e),   # MCAP control channel
+				('uint16', 0x0100), # version
+			],
+		])
+
+	add_attr(doc, record, 0x0006, # language/encoding
+		[
+			('uint16', 0x656e),  # 'en' (ISO 639 lang. code)
+			('uint16', 0x006a),  # UTF-8 (IANA MIBE code)
+			('uint16', 0x0100),  # Natural language ID
+		])
+
+	add_attr(doc, record, 0x0009,
+		[
+			[
+				('uuid', 0x1400),   # HDP
+				('uint16', 0x0100), # HDP version
+			],
+		])
+
+	add_attr(doc, record, 0x000d,  # additional protocols
+		[
+			[
+				[
+					('uuid', 0x0100), # L2CAP
+					('uint16', dpsm), # data channel
+				], [
+					('uuid', 0x001f), # MCAP data channel
+				],
+			],
+		])
+
+	name = service.get('name', "")
+	if name:
+		add_attr(doc, record, 0x0100, ('text', name))
+
+	description = service.get('description', "")
+	if description:
+		add_attr(doc, record, 0x0101, ('text', description))
+
+	provider = service.get('provider', "")
+	if provider:
+		add_attr(doc, record, 0x0102, ('text', provider))
+
+	add_attr(doc, record, 0x0200, hdp_features) # HDP supported features
+
+	add_attr(doc, record, 0x0301, ('uint8', data_spec))
+	add_attr(doc, record, 0x0302, ('uint8', mcap_supported_procedures))
+
+	return doc.toprettyxml(encoding="UTF-8")
-- 
1.7.0.4


  reply	other threads:[~2010-05-11 15:38 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-11 15:38 [PATCH 1/9] Adds XML record samples from Nonin Oximeter Elvis Pfützenreuter
2010-05-11 15:38 ` Elvis Pfützenreuter [this message]
2010-05-11 15:38 ` [PATCH 3/9] Adds HDP record parsing capability to hdp_record Elvis Pfützenreuter
2010-05-11 15:38 ` [PATCH 4/9] Adds sample HDP record generation script Elvis Pfützenreuter
2010-05-11 15:38 ` [PATCH 5/9] Adds a HDP XML record parsing script Elvis Pfützenreuter
2010-05-11 15:38 ` [PATCH 6/9] Adds HDP record adder script Elvis Pfützenreuter
2010-05-11 15:38 ` [PATCH 7/9] Adds an HDP record browser Elvis Pfützenreuter
2010-05-11 15:38 ` [PATCH 8/9] Adds HDP record auto-testing script Elvis Pfützenreuter
2010-05-11 15:38 ` [PATCH 9/9] Changes HDP record example from source to sink Elvis Pfützenreuter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1273592303-18234-2-git-send-email-epx@signove.com \
    --to=epx@signove.com \
    --cc=linux-bluetooth@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox