示例#1
0
        /// <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);
        }
示例#2
0
        /// <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
        }
示例#3
0
        /// <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));
        }
示例#4
0
        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);
        }
示例#5
0
        //--------------------------------------------------------------

        /// <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);
            }
        }
示例#6
0
        /*
         *  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);
            }
        }
示例#7
0
        /// <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 &#x2018;short-form&#x2019; equivalent if its
        /// a &#x2018;Bluetooth-based&#x2019; 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);
        }
示例#8
0
        /// <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);
        }
示例#9
0
        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);
        }
示例#10
0
        /// <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]);
        }
示例#13
0
 public void Dispose()
 {
     m_record = null;
 }
示例#14
0
 internal ServiceRecordEnumerator(ServiceRecord record)
 {
     m_record = record;
 }
示例#15
0
        /// <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;
        /// }
        ///
        /// &#x2026;
        ///     ServiceRecordUtilities.Dump(writer, myRecord, typeof(FooAttributeId));
        /// &#x2026;
        /// </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
        }
示例#16
0
 /// <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));
 }
示例#17
0
        //--------------------------------------------------------------

        private static Type[] GetServiceClassSpecificAttributeIdEnumDefiningType(ServiceRecord record)
        {
            MapServiceClassToAttributeIdList instance = new MapServiceClassToAttributeIdList();

            return(instance.GetAttributeIdEnumTypes(record));
        }