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
next prev parent 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