private static void SetRecordService(ServiceRecord m_record, Guid uuid128) { ServiceAttribute attr = m_record.GetAttributeById(UniversalAttributeId.ServiceClassIdList); ServiceElement element = (ServiceElement)attr.Value.GetValueAsElementList()[0]; element.SetValue(uuid128); }
/// <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> /// - /// <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. /// </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 ( #if V1 ArgumentException #else System.Collections.Generic.KeyNotFoundException #endif 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]; }
/// <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(System.IO.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 }
private Guid GetRecordService(ServiceRecord m_record) { ServiceAttribute attr = m_record.GetAttributeById(UniversalAttributeId.ServiceClassIdList); ServiceElement element = (ServiceElement)attr.Value.GetValueAsElementList()[0]; Guid uuid128 = (Guid)element.Value; return(uuid128); }
//-------------------------------------------------------------- /// <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 (System.IO.StringWriter writer = new System.IO.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); } }
public SdpRecordTemp() { m_data = new byte[] { 0x35, 0x27, 0x09, 0x00, 0x01, 0x35, 0x11, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x04, 0x35, 0x0c, 0x35, 0x03, 0x19, 0x01, 0x00, 0x35, 0x05, 0x19, 0x00, 0x03, 0x08, 0x00 }; m_record = CreateRecord(); m_expectedRecordLength = 41; }
/// <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); }
public SdpRecordTemp() { m_data = new byte[] {0x35,0x27,0x09,0x00,0x01,0x35,0x11,0x1c, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x09,0x00,0x04,0x35,0x0c,0x35,0x03,0x19, 0x01,0x00,0x35,0x05,0x19,0x00,0x03,0x08, 0x00}; m_record = CreateRecord(); m_expectedRecordLength = 41; }
//-------------------------------------------------------------- private static ServiceRecord CreateRecord() { List_ServiceAttribute attrs = new List_ServiceAttribute(); ServiceElement element; // element = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid128, Guid.Empty)); attrs.Add(new ServiceAttribute(UniversalAttributeId.ServiceClassIdList, element)); // element = ServiceRecordHelper.CreateRfcommProtocolDescriptorList(); attrs.Add(new ServiceAttribute(UniversalAttributeId.ProtocolDescriptorList, element)); // ServiceRecord record = new ServiceRecord(attrs); return(record); }
static ServiceElement GetChannelElement(ServiceRecord record, BluetoothProtocolDescriptorType proto) { if (!record.Contains(UniversalAttributeId.ProtocolDescriptorList)) { goto NotFound; } ServiceAttribute attr = record.GetAttributeById(UniversalAttributeId.ProtocolDescriptorList); #if !V1 bool?isSimpleRfcomm; #else object isSimpleRfcomm; #endif return(GetChannelElement(attr, proto, out isSimpleRfcomm)); NotFound: return(null); }
/// <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 ( #if V1 ArgumentException #else System.Collections.Generic.KeyNotFoundException #endif 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]); }
/// <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) { len = CreateAttrId(attr.Id, buffer, offset); offset += len; len = CreateElement(attr.Value, buffer, offset); offset += len; }//for int tmp; CompleteHeaderWrite(headerState, buffer, offset, out tmp); System.Diagnostics.Debug.Assert(offset != 0); return offset; }
//-------------------------------------------------------------- /// <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 (System.IO.StringWriter writer = new System.IO.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> /// Initializes a new instance of the <see cref="BluetoothListener"/> class /// to listen on the specified service identifier, /// publishing the specified SDP record. /// </summary> /// - /// <param name="service">The Bluetooth service to listen for.</param> /// <param name="sdpRecord">Prepared SDP Record to publish.</param> /// - /// <remarks> /// <note> /// The constructors taking the SDP record explicitly should /// only be used if /// a specialized SDP record is required. For instance when using one of the /// standard profiles. Otherwise use one of the other constructors /// e.g. <see /// cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(System.Guid)"/> /// which create a generic SDP Record from the specified service identifier. /// </note> /// <para>Any useful SDP record will include /// a <c>ProtocolDescriptor</c> element containing /// the RFCOMM Channel number that the server is listening on, /// and a <c>ServiceClassId</c> element containing the service UUIDs. /// The record supplied in the <paramref name="sdpRecord"/> parameter /// should contain those elements. On successful <see /// cref="M:InTheHand.Net.Sockets.BluetoothListener.Start"/>, /// the RFCOMM Channel number that the protocol stack has assigned to the /// server is retrieved, and copied into the service record before it is /// published. /// </para> /// <para> /// An example SDP record is as follows. This is actually the format of the /// generic record used in the other constructors. For another example see /// the code in the <c>ObexListener</c> class. /// <code lang="C#"> /// private static ServiceRecord CreateBasicRfcommRecord(Guid serviceClassUuid) /// { /// ServiceElement pdl = ServiceRecordHelper.CreateRfcommProtocolDescriptorList(); /// ServiceElement classList = new ServiceElement(ElementType.ElementSequence, /// new ServiceElement(ElementType.Uuid128, serviceClassUuid)); /// ServiceRecord record = new ServiceRecord( /// new ServiceAttribute( /// InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ServiceClassIdList, /// classList), /// new ServiceAttribute( /// InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList, /// pdl)); /// return record; /// } /// </code> /// </para> /// </remarks> public BluetoothListener(Guid service, ServiceRecord sdpRecord) : this(service) { InitServiceRecord(sdpRecord); }
private Guid GetRecordService(ServiceRecord m_record) { ServiceAttribute attr = m_record.GetAttributeById(UniversalAttributeId.ServiceClassIdList); ServiceElement element = (ServiceElement)attr.Value.GetValueAsElementList()[0]; Guid uuid128 = (Guid)element.Value; return uuid128; }
//-------------------------------------------------------------- private static ServiceRecord CreateRecord() { List_ServiceAttribute attrs = new List_ServiceAttribute(); ServiceElement element; // element = new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid128, Guid.Empty)); attrs.Add(new ServiceAttribute(UniversalAttributeId.ServiceClassIdList, element)); // element = ServiceRecordHelper.CreateRfcommProtocolDescriptorList(); attrs.Add(new ServiceAttribute(UniversalAttributeId.ProtocolDescriptorList, element)); // ServiceRecord record = new ServiceRecord(attrs); return record; }
/// <summary> /// Initialise a new instance of the <see cref="T:InTheHand.Net.Sockets.BluetoothListener"/> /// class, /// with the specified Service Class Id, local device address and Service Record /// using the respective stack and/or radio. /// </summary> /// - /// <param name="localAddress">See <see cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(InTheHand.Net.BluetoothAddress,System.Guid,InTheHand.Net.Bluetooth.ServiceRecord)"/>. /// </param> /// <param name="service">See <see cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(InTheHand.Net.BluetoothAddress,System.Guid,InTheHand.Net.Bluetooth.ServiceRecord)"/>. /// </param> /// <param name="sdpRecord">See <see cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(InTheHand.Net.BluetoothAddress,System.Guid,InTheHand.Net.Bluetooth.ServiceRecord)"/>. /// </param> /// - /// <returns>The new instance. /// </returns> public BluetoothListener CreateBluetoothListener(BluetoothAddress localAddress, Guid service, ServiceRecord sdpRecord) { return(new BluetoothListener(m_factory, localAddress, service, sdpRecord)); }
protected override void AddSimpleServiceRecord(out ServiceRecord fullServiceRecord, int livePort, Guid serviceClass, string serviceName) { fullServiceRecord = CreateSimpleServiceRecord(serviceClass, serviceName); AddCustomServiceRecord(ref fullServiceRecord, livePort); }
protected override void AddCustomServiceRecord(ref ServiceRecord fullServiceRecord, int livePort) { }
/// <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)); }
/// <summary> /// Initialise a new instance of the <see cref="T:InTheHand.Net.Sockets.BluetoothListener"/> /// class, /// with the specified Service Class Id and Service Record /// using the respective stack and/or radio. /// </summary> /// - /// <param name="service">See <see cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(System.Guid,InTheHand.Net.Bluetooth.ServiceRecord)"/>. /// </param> /// <param name="sdpRecord">See <see cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(System.Guid,InTheHand.Net.Bluetooth.ServiceRecord)"/>. /// </param> /// - /// <returns>The new instance. /// </returns> public BluetoothListener CreateBluetoothListener(Guid service, ServiceRecord sdpRecord) { return(new BluetoothListener(m_factory, service, sdpRecord)); }
private static ServiceRecord CreateServiceRecord() { ServiceElement englishUtf8PrimaryLanguage = CreateEnglishUtf8PrimaryLanguageServiceElement(); ServiceRecord record = new ServiceRecord( new ServiceAttribute(InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ServiceClassIdList, new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.Uuid16, (UInt16)0x1105))), new ServiceAttribute(InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList, ServiceRecordHelper.CreateGoepProtocolDescriptorList()), #if ADD_SERVICE_NAME_TO_SDP_RECORD // Could add ServiceName, ProviderName etc here. new ServiceAttribute(InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.LanguageBaseAttributeIdList, englishUtf8PrimaryLanguage), new ServiceAttribute(ServiceRecord.CreateLanguageBasedAttributeId( InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProviderName, LanguageBaseItem.PrimaryLanguageBaseAttributeId), new ServiceElement(ElementType.TextString, "32feet.NET")), #endif // new ServiceAttribute(InTheHand.Net.Bluetooth.AttributeIds.ObexAttributeId.SupportedFormatsList, new ServiceElement(ElementType.ElementSequence, new ServiceElement(ElementType.UInt8, (byte)0xFF))) ); return record; }
/// <summary> /// Initialise a new instance of the <see cref="T:InTheHand.Net.Sockets.BluetoothListener"/> /// class, /// with the specified Service Class Id and local device address as a /// <see cref="T:InTheHand.Net.BluetoothEndPoint"/> and Service Record /// using the respective stack and/or radio. /// </summary> /// - /// <param name="localEP">See <see cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(InTheHand.Net.BluetoothEndPoint,InTheHand.Net.Bluetooth.ServiceRecord)"/>. /// </param> /// <param name="sdpRecord">See <see cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(InTheHand.Net.BluetoothEndPoint,InTheHand.Net.Bluetooth.ServiceRecord)"/>. /// </param> /// - /// <returns>The new instance. /// </returns> public BluetoothListener CreateBluetoothListener(BluetoothEndPoint localEP, ServiceRecord sdpRecord) { return(new BluetoothListener(m_factory, localEP, sdpRecord)); }
internal ServiceRecordEnumerator(ServiceRecord record) { m_record = record; }
public void Dispose() { m_record = null; }
/// <summary> /// Initializes a new instance of the <see cref="BluetoothListener"/> class /// with the specified local endpoint, /// publishing the specified SDP record. /// </summary> /// <param name="localEP">A <see cref="BluetoothEndPoint"/> that represents the local endpoint to which to bind the listener <see cref="Socket"/>.</param> /// <param name="sdpRecord">Prepared SDP Record to publish</param> /// - /// <remarks> /// <note> /// The constructors taking the SDP record explicitly (as a byte array) should /// only be used if /// a specialized SDP record is required. For instance when using one of the /// standard profiles. Otherwise use one of the other constructors /// e.g. <see /// cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(InTheHand.Net.BluetoothEndPoint)"/> /// which create a generic SDP Record from the specified service identifier. /// </note> /// <para>Any useful SDP record will include /// a <c>ProtocolDescriptor</c> element containing /// the RFCOMM Channel number that the server is listening on, /// and a <c>ServiceClassId</c> element containing the service UUIDs. /// The record supplied in the <paramref name="sdpRecord"/> parameter /// should contain those elements. On successful <see /// cref="M:InTheHand.Net.Sockets.BluetoothListener.Start"/>, /// the RFCOMM Channel number that the protocol stack has assigned to the /// server is retrieved, and copied into the service record before it is /// published. /// </para> /// <para> /// An example SDP record is as follows. This is actually the format of the /// generic record used in the other constructors. For another example see /// the code in the <c>ObexListener</c> class. /// <code lang="C#"> /// private static ServiceRecord CreateBasicRfcommRecord(Guid serviceClassUuid) /// { /// ServiceElement pdl = ServiceRecordHelper.CreateRfcommProtocolDescriptorList(); /// ServiceElement classList = new ServiceElement(ElementType.ElementSequence, /// new ServiceElement(ElementType.Uuid128, serviceClassUuid)); /// ServiceRecord record = new ServiceRecord( /// new ServiceAttribute( /// InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ServiceClassIdList, /// classList), /// new ServiceAttribute( /// InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList, /// pdl)); /// return record; /// } /// </code> /// </para> /// </remarks> public BluetoothListener(BluetoothEndPoint localEP, ServiceRecord sdpRecord) : this(localEP) { InitServiceRecord(sdpRecord); }
private void InitServiceRecord(ServiceRecord sdpRecord) { if (sdpRecord == null) { throw new ArgumentNullException("sdpRecord"); } if (ServiceRecordHelper.GetRfcommChannelNumber(sdpRecord) == -1) { throw new ArgumentException("The ServiceRecord must contain a RFCOMM-style ProtocolDescriptorList."); } m_serviceRecord = sdpRecord; m_manualServiceRecord = true; }
/// <summary> /// Initializes a new instance of the <see cref="BluetoothListener"/> class /// that listens for incoming connection attempts on the specified local Bluetooth address and service identifier, /// publishing the specified SDP record. /// </summary> /// - /// <param name="localaddr">A <see cref="BluetoothAddress"/> that represents the local Bluetooth radio address.</param> /// <param name="service">The Bluetooth service to listen for.</param> /// <param name="sdpRecord">Prepared SDP Record to publish</param> /// - /// <remarks> /// <note> /// The constructors taking the SDP record explicitly should /// only be used if /// a specialized SDP record is required. For instance when using one of the /// standard profiles. Otherwise use one of the other constructors /// e.g. <see /// cref="M:InTheHand.Net.Sockets.BluetoothListener.#ctor(InTheHand.Net.BluetoothAddress,System.Guid)"/> /// which create a generic SDP Record from the specified service identifier. /// </note> /// <para>Any useful SDP record will include /// a <c>ProtocolDescriptor</c> element containing /// the RFCOMM Channel number that the server is listening on, /// and a <c>ServiceClassId</c> element containing the service UUIDs. /// The record supplied in the <paramref name="sdpRecord"/> parameter /// should contain those elements. On successful <see /// cref="M:InTheHand.Net.Sockets.BluetoothListener.Start"/>, /// the RFCOMM Channel number that the protocol stack has assigned to the /// server is retrieved, and copied into the service record before it is /// published. /// </para> /// <para> /// An example SDP record is as follows. This is actually the format of the /// generic record used in the other constructors. For another example see /// the code in the <c>ObexListener</c> class. /// <code lang="C#"> /// private static ServiceRecord CreateBasicRfcommRecord(Guid serviceClassUuid) /// { /// ServiceElement pdl = ServiceRecordHelper.CreateRfcommProtocolDescriptorList(); /// ServiceElement classList = new ServiceElement(ElementType.ElementSequence, /// new ServiceElement(ElementType.Uuid128, serviceClassUuid)); /// ServiceRecord record = new ServiceRecord( /// new ServiceAttribute( /// InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ServiceClassIdList, /// classList), /// new ServiceAttribute( /// InTheHand.Net.Bluetooth.AttributeIds.UniversalAttributeId.ProtocolDescriptorList, /// pdl)); /// return record; /// } /// </code> /// </para> /// </remarks> public BluetoothListener(BluetoothAddress localaddr, Guid service, ServiceRecord sdpRecord) : this(localaddr, service) { InitServiceRecord(sdpRecord); }
/// <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; }
private void InitServiceRecord(Guid serviceClassUuid) { ServiceRecord record = CreateBasicRfcommRecord(serviceClassUuid, m_serviceName); m_serviceRecord = record; }
//-------------------------------------------------------------- private static Type[] GetServiceClassSpecificAttributeIdEnumDefiningType(ServiceRecord record) { MapServiceClassToAttributeIdList instance = new MapServiceClassToAttributeIdList(); return instance.GetAttributeIdEnumTypes(record); }
private void InitServiceRecord(byte[] sdpRecord, int channelOffset) { if (sdpRecord.Length == 0) { throw new ArgumentException("sdpRecord must not be empty."); } if (channelOffset >= sdpRecord.Length) { throw new ArgumentOutOfRangeException("channelOffset"); } // // Parse into a ServiceRecord, and discard the array and offset! m_serviceRecord = ServiceRecord.CreateServiceRecordFromBytes(sdpRecord); m_manualServiceRecord = true; }
/// <summary> /// Sets the RFCOMM Channel Number value in the service record. /// </summary> /// - /// <exception cref="T:System.InvalidOperation">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); }
/// <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(System.IO.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}", (int)attr.Id); DumpRawElement(writer, 0, attr.Value); firstRecord = false; }//for }
/// <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(System.IO.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 = (ServiceAttributeId)attr.Id; LanguageBaseItem applicableLangBase; string name = AttributeIdLookup.GetName(id, allAttributeIdEnumDefiningTypes, langBaseList, out applicableLangBase); if (name == null) { writer.WriteLine("AttrId: 0x{0:X4}", (int)attr.Id); } else { writer.WriteLine("AttrId: 0x{0:X4} -- {1}", (int)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 }
//-------------------------------------------------------------- private static Type[] GetServiceClassSpecificAttributeIdEnumDefiningType(ServiceRecord record) { MapServiceClassToAttributeIdList instance = new MapServiceClassToAttributeIdList(); return(instance.GetAttributeIdEnumTypes(record)); }
/// <summary> /// Reads the RFCOMM Channel Number value from the service record, /// or returns -1 if the element is not present. /// </summary> /// <returns>The Channel Number as an unsigned byte 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 Int32 GetRfcommChannelNumber(ServiceRecord record) { ServiceElement channelElement = GetRfcommChannelElement(record); if (channelElement == null) { return -1; } System.Diagnostics.Debug.Assert(channelElement.ElementType == ElementType.UInt8); byte value = (byte)channelElement.Value; return value; }
/// <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(System.IO.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 = (ServiceAttributeId)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 RFCOMM Channel Number element from the service record. /// </summary> /// <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 GetRfcommChannelElement(ServiceRecord record) { if (!record.Contains(UniversalAttributeId.ProtocolDescriptorList)) { goto NotFound; } ServiceAttribute attr = record.GetAttributeById(UniversalAttributeId.ProtocolDescriptorList); ServiceElement e0 = attr.Value; if (e0.ElementType == ElementType.ElementAlternative) { #if ! WinCE Trace.WriteLine("Don't support ElementAlternative ProtocolDescriptorList values."); #endif goto NotFound; } else if (e0.ElementType != ElementType.ElementSequence) { #if ! WinCE Trace.WriteLine("Bad ProtocolDescriptorList base element."); #endif goto NotFound; } IList_ServiceElement protoStack = e0.GetValueAsElementList(); IEnumerator_ServiceElement etor = protoStack.GetEnumerator(); ServiceElement layer; IList_ServiceElement layerContent; if (!etor.MoveNext()) { #if ! WinCE Trace.WriteLine("Protocol stack truncated before {0}.", "L2CAP"); #endif goto NotFound; } layer = (ServiceElement)etor.Current; //cast here are for non-Generic version. layerContent = layer.GetValueAsElementList(); if (((ServiceElement)layerContent[0]).GetValueAsUuid() != BluetoothService.L2CapProtocol) { #if ! WinCE Trace.WriteLine(String.Format(System.Globalization.CultureInfo.InvariantCulture, "Bad protocol stack, layer {0} is not {1}.", 1, "L2CAP")); #endif goto NotFound; } // if (!etor.MoveNext()) { #if ! WinCE Trace.WriteLine("Protocol stack truncated before {0}.", "RFCOMM"); #endif goto NotFound; } layer = (ServiceElement)etor.Current; layerContent = layer.GetValueAsElementList(); if (((ServiceElement)layerContent[0]).GetValueAsUuid() != BluetoothService.RFCommProtocol) { #if ! WinCE Trace.WriteLine(String.Format(System.Globalization.CultureInfo.InvariantCulture, "Bad protocol stack, layer {0} is not {1}.", 2, "RFCOMM")); #endif goto NotFound; } // if (layerContent.Count < 2) { #if ! WinCE Trace.WriteLine(String.Format(System.Globalization.CultureInfo.InvariantCulture, "Bad protocol stack, layer {0} hasn't a second element.", 2)); #endif goto NotFound; } ServiceElement channelElement = (ServiceElement)layerContent[1]; if (channelElement.ElementType != ElementType.UInt8) { #if ! WinCE Trace.WriteLine(String.Format(System.Globalization.CultureInfo.InvariantCulture, "Bad protocol stack, layer {0} is not UInt8.", 2)); #endif goto NotFound; } // Success return channelElement; NotFound: return null; }