/// <overloads> /// Creates a Service Record byte array from the given /// <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> object. /// </overloads> /// - /// <summary> /// Creates a Service Record byte array from the given /// <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> object, /// into the specified byte array. /// </summary> /// - /// <remarks> /// See the other overload <see cref="M:InTheHand.Net.Bluetooth.ServiceRecordCreator.CreateServiceRecord(InTheHand.Net.Bluetooth.ServiceRecord)"/> /// </remarks> /// - /// <param name="record">An instance of <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> /// containing the record to be created. /// </param> /// <param name="buffer">An array of <see cref="T:System.Byte"/> for the record /// to be written to. /// </param> /// - /// <exception cref="T:System.ArgumentOutOfRangeException"> /// The record bytes are longer that the supplied byte array buffer. /// </exception> /// - /// <returns>The length of the record in the array of <see cref="T:System.Byte"/>. /// </returns> public int CreateServiceRecord(ServiceRecord record, byte[] buffer) { if (record == null) { throw new ArgumentNullException("record"); } if (buffer == null) { throw new ArgumentNullException("buffer"); } // int len; HeaderWriteState headerState; int offset = 0; len = MakeVariableLengthHeader(buffer, offset, ElementTypeDescriptor.ElementSequence, out headerState); offset += len; foreach (ServiceAttribute attr in record) { WriteAttribute(attr, buffer, ref offset); }//for int tmp; CompleteHeaderWrite(headerState, buffer, offset, out tmp); System.Diagnostics.Debug.Assert(offset != 0); return(offset); }
/// <summary> /// Produce a raw 'dump' of the given record, not including attribute names etc, to the given /// <see cref="T:System.IO.TextWriter"/>. /// </summary> /// <param name="writer">A <see cref="T:System.IO.TextWriter"/> where the 'dump' /// text is to be written.</param> /// <param name="record">A <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> to be dumped.</param> /// <seealso cref="M:InTheHand.Net.Bluetooth.ServiceRecordUtilities.DumpRaw(InTheHand.Net.Bluetooth.ServiceRecord)"/> public static void DumpRaw(TextWriter writer, ServiceRecord record) { if (writer == null) { throw new ArgumentNullException("writer"); } if (record == null) { throw new ArgumentNullException("record"); } // bool firstRecord = true; foreach (ServiceAttribute attr in record) { if (!firstRecord) { writer.WriteLine(); } // All this casting of enum values to int/underlying type is for the // benefit of NETCFv1, where Enum has no support for hex formatting. writer.WriteLine("AttrId: 0x{0:X4}", unchecked ((ushort)attr.Id)); DumpRawElement(writer, 0, attr.Value); firstRecord = false; }//for }
/// <summary> /// Reads the L2CAP Channel Number value from the service record, /// or returns -1 if the element is not present. /// </summary> /// - /// <param name="record">The <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> /// to search for the element. /// </param> /// - /// <returns>The PSM number as an uint16 cast to an Int32, /// or -1 if at the <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList"/> /// attribute is missing or contains invalid elements. /// </returns> public static int GetL2CapChannelNumber(ServiceRecord record) { ServiceElement channelElement = GetL2CapChannelElement(record); if (channelElement == null) { return(-1); } return(GetL2CapChannelNumber(channelElement)); }
static Guid _GetPrimaryServiceClassId(ServiceRecord sr) { var a = sr.GetAttributeById(UniversalAttributeId.ServiceClassIdList); var eL = a.Value; var eClassList = eL.GetValueAsElementList(); var e0 = eClassList[0]; var classId = e0.GetValueAsUuid(); return(classId); }
//-------------------------------------------------------------- /// <overloads> /// Produces a 'dump' of the given record, including attribute names etc. /// </overloads> /// -- /// <summary> /// Gets a <see cref="T:System.String"/> containing a 'dump' of the given record, including attribute names etc. /// </summary> /// - /// <param name="record">A <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> to be dumped.</param> /// <param name="attributeIdEnumDefiningTypes"> /// An optional array of <see cref="T:System.Type"/> specifing a set of Ids /// for the attributes contained in this record. See the /// <see cref="M:InTheHand.Net.Bluetooth.ServiceRecordUtilities.Dump(System.IO.TextWriter,InTheHand.Net.Bluetooth.ServiceRecord,System.Type[])"/> /// overload for more information. /// </param> /// - /// <returns>A <see cref="T:System.String"/> containing the 'dump' text.</returns> /// - /// <seealso cref="M:InTheHand.Net.Bluetooth.ServiceRecordUtilities.Dump(System.IO.TextWriter,InTheHand.Net.Bluetooth.ServiceRecord,System.Type[])"/> public static string Dump(ServiceRecord record, params Type[] attributeIdEnumDefiningTypes) { using (System.IO.StringWriter writer = new System.IO.StringWriter( System.Globalization.CultureInfo.InvariantCulture)) { Dump(writer, record, attributeIdEnumDefiningTypes); writer.Close(); // close here, and to be sure to be sure also with using() string result = writer.ToString(); return(result); } }
/* * AttrId: 0x0000 * UInt32: 0x0 * * AttrId: 0x0001 * ElementSequence * Uuid16: 0x1000 * * AttrId: 0x0004 * ElementSequence * ElementSequence * Uuid16: 0x100 * UInt16: 0x1 * ElementSequence * Uuid16: 0x1 * * AttrId: 0x0005 * ElementSequence * Uuid16: 0x1002 * * AttrId: 0x0006 * ElementSequence * UInt16: 0x656E * UInt16: 0x6A * UInt16: 0x100 * * AttrId: 0x0100 * _____ToBeDefined: 0x * * AttrId: 0x0101 * _____ToBeDefined: 0x * * AttrId: 0x0102 * _____ToBeDefined: 0x * * AttrId: 0x0200 * ElementSequence * UInt16: 0x100 * * AttrId: 0x0201 * UInt32: 0x1 */ /// <overloads> /// Produces a raw 'dump' of the given record, not including attribute names etc. /// </overloads> /// - /// <summary> /// Gets a string containing a raw 'dump' of the given record, not including attribute names etc. /// </summary> /// - /// <param name="record">A <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> to be dumped.</param> /// <returns>A <see cref="T:System.String"/> containing the 'dump' text.</returns> /// <seealso cref="M:InTheHand.Net.Bluetooth.ServiceRecordUtilities.DumpRaw(System.IO.TextWriter,InTheHand.Net.Bluetooth.ServiceRecord)"/> public static string DumpRaw(ServiceRecord record) { using (StringWriter writer = new StringWriter( System.Globalization.CultureInfo.InvariantCulture)) { DumpRaw(writer, record); writer.Close(); // close here, and to be sure to be sure also with using() string result = writer.ToString(); return(result); } }
/// <summary> /// Creates a Service Record byte array from the given /// <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> object. /// </summary> /// - /// <remarks> /// <para>The only oddity (as with parsing) is with the <c>TextString</c> /// type. The <see cref="T:InTheHand.Net.Bluetooth.ServiceElement"/> can /// either hold the string already encoded to its array of bytes or an /// <see cref="T:System.String"/>. In the latter case we will always simply /// encode the string to an array of bytes using encoding /// <see cref="P:System.Text.Encoding.UTF8"/>. /// </para> /// <para>Currently any UUIDs in the record are written out in the form supplied, /// we should probably write a ‘short-form’ equivalent if its /// a ‘Bluetooth-based’ UUID e.g. <c>Uuid128</c> as <c>Uuid16</c>. /// </para> /// </remarks> /// - /// <param name="record">An instance of <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> /// containing the record to be created. /// </param> /// - /// <returns>An array of <see cref="T:System.Byte"/> containing the resultant /// record bytes. The length of the array is the length of the record bytes. /// </returns> public byte[] CreateServiceRecord(ServiceRecord record) { const int MaxiOutputSize = 256; byte[] tmpResult = new byte[MaxiOutputSize]; int length = CreateServiceRecord(record, tmpResult); byte[] result = new byte[length]; Array.Copy(tmpResult, 0, result, 0, length); return(result); }
/// <summary> /// Sets the RFCOMM Channel Number value in the service record. /// </summary> /// - /// <param name="record">The <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> /// in which to set the RFCOMM Channel number. /// </param> /// <param name="channelNumber">The Channel number to set in the record. /// </param> /// - /// <exception cref="T:System.InvalidOperationException">The /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList"/> /// attribute is missing or contains invalid elements. /// </exception> public static void SetRfcommChannelNumber(ServiceRecord record, byte channelNumber) { ServiceElement channelElement = GetRfcommChannelElement(record); if (channelElement == null) { throw new InvalidOperationException("ProtocolDescriptorList element does not exist or is not in the RFCOMM format."); } System.Diagnostics.Debug.Assert(channelElement.ElementType == ElementType.UInt8); channelElement.SetValue(channelNumber); }
static ServiceElement GetChannelElement(ServiceRecord record, BluetoothProtocolDescriptorType proto) { if (!record.Contains(UniversalAttributeId.ProtocolDescriptorList)) { goto NotFound; } ServiceAttribute attr = record.GetAttributeById(UniversalAttributeId.ProtocolDescriptorList); bool?isSimpleRfcomm; return(GetChannelElement(attr, proto, out isSimpleRfcomm)); NotFound: return(null); }
/// <summary> /// Sets the RFCOMM Channel Number value in the service record. /// </summary> /// - /// <remarks> /// <para>Note: We use an <see cref="T:System.Int32"/> for the /// <paramref name="psm"/> parameter as its natural type <see cref="T:System.UInt16"/> /// in not usable in CLS Compliant interfaces. /// </para> /// </remarks> /// - /// <param name="record">The <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> /// in which to set the L2CAP PSM value. /// </param> /// <param name="psm">The PSM value to set in the record. /// Note that although the parameter is of type <see cref="T:System.Int32"/> /// the value must actually be in the range of a <see cref="T:System.UInt16"/>, /// see the remarks for more information. /// </param> /// - /// <exception cref="T:System.InvalidOperationException">The /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList"/> /// attribute is missing or contains invalid elements. /// </exception> /// <exception cref="T:System.ArgumentOutOfRangeException"> /// The PSM must fit in a 16-bit unsigned integer. /// </exception> public static void SetL2CapPsmNumber(ServiceRecord record, int psm) { if (psm < 0 || psm > UInt16.MaxValue) { throw new ArgumentOutOfRangeException("psm", "A PSM is a UInt16 value."); } var psm16 = checked ((UInt16)psm); ServiceElement rfcommElement = GetRfcommChannelElement(record); if (rfcommElement != null) { Debug.WriteLine("Setting L2CAP PSM for a PDL that includes RFCOMM."); } ServiceElement channelElement = GetChannelElement(record, BluetoothProtocolDescriptorType.L2Cap); if (channelElement == null || channelElement.ElementType != ElementType.UInt16) { throw new InvalidOperationException("ProtocolDescriptorList element does not exist, is not in the L2CAP format, or it the L2CAP layer has no PSM element."); } channelElement.SetValue(psm16); }
/// <summary> /// Creates an XML representation of a Service Record from the given /// <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> object. /// </summary> /// <param name="record">An instance of <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> /// containing the record to be created. /// </param> /// <returns> /// A <see cref="XDocument"/> which represents the XML representation of the Service /// Record. /// </returns> public XDocument CreateServiceRecord(ServiceRecord record) { if (record == null) { throw new ArgumentNullException(nameof(record)); } XDocument document = new XDocument(); var root = new XElement("record"); document.Add(root); foreach (var attribute in record) { var node = new XElement("attribute"); node.SetAttributeValue("id", GetIdString(attribute)); node.Add(GetAttributeValue(attribute.Value)); root.Add(node); } return(document); }
/// <summary> /// Get a list of enum-like classes containing Service Attribute Id definitions /// for the type of the Service Class contained in the given Service Record. /// </summary> /// - /// <param name="record">A <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> /// whose <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ServiceClassIdList"/> /// element will be retrieved, and its Service Class Id will used /// for the lookup. /// </param> /// - /// <returns> /// An array of <see cref="T:System.Type"/> each of which is a enum-like class /// which defines the set of Service Attribute IDs used by a particular /// Service Class e.g. ObjectPushProfile. /// An empty array will be returned if none of the Service Classes /// are known, or the record contains no /// <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ServiceClassIdList"/> /// attribute, or it is invalid. /// <note>Currently only the first Service Class Id is looked-up.</note> /// </returns> /// - /// <exception cref="T:System.ArgumentNullException"> /// <paramref name="record"/> is null. /// </exception> public Type[] GetAttributeIdEnumTypes(ServiceRecord record) { if (record == null) { throw new ArgumentNullException("record"); } // ServiceAttribute attr; try { attr = record.GetAttributeById(UniversalAttributeId.ServiceClassIdList); } catch (System.Collections.Generic.KeyNotFoundException ex) { System.Diagnostics.Debug.Assert(ex.Message == ServiceRecord.ErrorMsgNoAttributeWithId); goto InvalidRecord; } ServiceElement element = attr.Value; if (element.ElementType != ElementType.ElementSequence) { goto InvalidRecord; } ServiceElement[] idElements = element.GetValueAsElementArray(); //TODO ((GetServiceClassSpecificAttributeIdEnumDefiningType--foreach (ServiceElement curIdElem in idElements) {)) if (idElements.Length != 0) { ServiceElement curIdElem = idElements[0]; Type enumType = GetAttributeIdEnumType(curIdElem); if (enumType != null) { return(new Type[] { enumType }); } }//else fall through... // None-matched, or invalid attribute format etc. InvalidRecord: return(new Type[0]); }
public void Dispose() { m_record = null; }
internal ServiceRecordEnumerator(ServiceRecord record) { m_record = record; }
/// <summary> /// Produce a 'dump' of the given record, including attribute names etc to the given /// <see cref="T:System.IO.TextWriter"/>. /// </summary> /// - /// <remarks> /// <para>The system has built-in a set of mappings from Service Class to /// its Attribute IDs. This is supplied by the /// <see cref="T:InTheHand.Net.Bluetooth.MapServiceClassToAttributeIdList"/> class, /// and contains the Attribute IDs defined in the base SDP specification as /// well as in Bluetooth Profiles specification e.g. ObjectPushProfile, Headset, /// Panu, etc. /// If however the record being decoded is a custom one then a set of extra /// Attribute Id definitions can be supplied in the /// <paramref name="attributeIdEnumDefiningTypes"/> parameter. /// The Attribute IDs for a particular Service Class /// should be defined in a static class and the set of such classes should /// be passed as their <see cref="T:System.Type"/> object. e.g. /// <code lang="C#"> /// static class FooAttributeId /// { /// public const ServiceAttributeId BarName = (ServiceAttributeId)0x0300; /// } /// /// … /// ServiceRecordUtilities.Dump(writer, myRecord, typeof(FooAttributeId)); /// … /// </code> /// </para> /// </remarks> /// - /// <param name="writer">A <see cref="T:System.IO.TextWriter"/> where the 'dump' /// text is to be written.</param> /// <param name="record">A <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> to be dumped.</param> /// <param name="attributeIdEnumDefiningTypes"> /// An optional array of <see cref="T:System.Type"/> specifing a set of Ids /// for the attributes contained in this record. See the /// </param> /// <seealso cref="M:InTheHand.Net.Bluetooth.ServiceRecordUtilities.Dump(InTheHand.Net.Bluetooth.ServiceRecord,System.Type[])"/> public static void Dump(TextWriter writer, ServiceRecord record, params Type[] attributeIdEnumDefiningTypes) { if (writer == null) { throw new ArgumentNullException("writer"); } if (record == null) { throw new ArgumentNullException("record"); } // // .... // Get the AttributeIdEnumDefiningType for the services contained in the record. Type[] recordSpecificAttributeIdEnumDefiningTypes = GetServiceClassSpecificAttributeIdEnumDefiningType(record); // // Prepend the Universal Attribute Id definition class to the supplied list. Type[] allAttributeIdEnumDefiningTypes; allAttributeIdEnumDefiningTypes = CombineAttributeIdEnumDefiningTypes(attributeIdEnumDefiningTypes, recordSpecificAttributeIdEnumDefiningTypes); // LanguageBaseItem[] langBaseList = record.GetLanguageBaseList(); // bool firstAttr = true; foreach (ServiceAttribute attr in record) { if (!firstAttr) { writer.WriteLine(); } ServiceAttributeId id = attr.Id; LanguageBaseItem applicableLangBase; string name = AttributeIdLookup.GetName(id, allAttributeIdEnumDefiningTypes, langBaseList, out applicableLangBase); if (name == null) { writer.WriteLine("AttrId: 0x{0:X4}", unchecked ((ushort)attr.Id)); } else { writer.WriteLine("AttrId: 0x{0:X4} -- {1}", (ushort)attr.Id, name); } //---- if (attr.Value.ElementType == ElementType.TextString) { DumpString(writer, 0, attr.Value, applicableLangBase); } else { DumpElement(writer, 0, attr.Value); } // Now print descriptive information for some cases. // e.g. for PDL: "( ( L2Cap ), ( Rfcomm, ChannelNumber=1 ), ( Obex ) )" if (id == AttributeIds.UniversalAttributeId.ProtocolDescriptorList) { DumpProtocolDescriptorList(writer, 0, attr.Value); } if (id == AttributeIds.UniversalAttributeId.AdditionalProtocolDescriptorLists) { DumpAdditionalProtocolDescriptorLists(writer, 0, attr.Value); } //TODO (( DumpLanguageBaseAttributeIdList, use ParseListFromElementSequence )) firstAttr = false; }//for }
/// <summary> /// Reads the L2CAP Channel Number element from the service record. /// </summary> /// - /// <param name="record">The <see cref="T:InTheHand.Net.Bluetooth.ServiceRecord"/> /// to search for the element. /// </param> /// - /// <returns>The <see cref="T:InTheHand.Net.Bluetooth.ServiceElement"/> /// holding the Channel Number. /// or <see langword="null"/> if at the <see cref="F:InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList"/> /// attribute is missing or contains invalid elements. /// </returns> public static ServiceElement GetL2CapChannelElement(ServiceRecord record) { return(GetChannelElement(record, BluetoothProtocolDescriptorType.L2Cap)); }
//-------------------------------------------------------------- private static Type[] GetServiceClassSpecificAttributeIdEnumDefiningType(ServiceRecord record) { MapServiceClassToAttributeIdList instance = new MapServiceClassToAttributeIdList(); return(instance.GetAttributeIdEnumTypes(record)); }