⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bluetoothservice.cs

📁 老外的一个开源项目
💻 CS
字号:
// Copyright (c) David Vescovi.  All rights reserved.
// Part of Project DrumStix
// Windows Embedded Developers Interest Group (WE-DIG) community project.
// http://www.we-dig.org
// Copyright (c)  Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/?linkid=2933443.
//

#region Using directives

using System;
using System.Net.Sockets;
using System.Runtime.InteropServices;

#endregion

namespace Gumstix.Bluetooth 
{
	/// <summary>
	/// Represents a Bluetooth Service identified by a GUID.
	/// 
	/// Use this class to publish a new service and accept client connections.
	/// </summary>
	public class BluetoothService
	{
		/// <summary>
		/// Constructs a new Bluetooth Service identified by a GUID
		/// </summary>
		/// <param name="serviceGuid">GUID identifying this service</param>
		public BluetoothService(Guid serviceGuid)
		{
			this.serviceGuid = serviceGuid;
			serverSocket = null;
			started = false;
		}

		/// <summary>
		/// Registers this service with the system and enables clients to connect
		/// </summary>
		public void Start()
		{
			PublishService();

			serverSocket.Listen(100);
			started = true;
		}

		/// <summary>
		/// Stops this service
		/// </summary>
		public void Stop()
		{
			if (serverSocket != null)
			{
				serverSocket.Close();
				started = false;
			}
		}

		/// <summary>
		/// Indicates whether the service has been started or not
		/// </summary>
		public bool Started
		{
			get
			{
				return started;
			}
		}

		/// <summary>
		/// Indicates whether there are clients waiting to connect on this service
		/// </summary>
		public bool ConnectionPending
		{
			get
			{
				return serverSocket.Poll(0, SelectMode.SelectRead);
			}
		}

		/// <summary>
		/// Accepts a connection on this service
		/// </summary>
		/// <returns>A NetworkStream object used to communicate between the two devices</returns>
		public NetworkStream AcceptConnection()
		{
			Socket clientSocket = serverSocket.Accept();

			return new NetworkStream(clientSocket, true);
		}

        /// <summary>
        /// Begins an asynchronous accept connection on this service
        /// </summary>
        /// <returns>Represents the status of an asynchronous operation.</returns>
        public IAsyncResult BeginAcceptConnection(AsyncCallback callback)
        {
            return serverSocket.BeginAccept(callback,null);
        }

        /// <summary>
        /// Ends an asynchronous accept connection on this service
        /// </summary>
        /// <returns>A NetworkStream object used to communicate between the two devices</returns>
        public NetworkStream EndAcceptConnection(IAsyncResult asyncResult)
        {
            return new NetworkStream(serverSocket.EndAccept(asyncResult), true);
        }

        /// <summary>
		/// GUID identifying this service
		/// </summary>
		public Guid ServiceGuid
		{
			get
			{
				return serviceGuid;
			}
		}

		private void PublishService()
		{
			serverSocket = new Socket((AddressFamily)32, SocketType.Stream, (ProtocolType)3);

			BluetoothEndPoint btep = new BluetoothEndPoint();

			serverSocket.Bind(btep);

			// extract port number
			int port = ((BluetoothEndPoint)serverSocket.LocalEndPoint).Port;

			byte[] sdpRecord = GenerateSDPRecord(ServiceGuid, port);

			// set up BTHNS_BLOB

			byte[] bthnsBlob = new byte[36 + sdpRecord.Length];

			int sdpVersion = 1;
			int serviceHandle = 0;

			GCHandle sdpVersionHandle = GCHandle.Alloc(sdpVersion, GCHandleType.Pinned);
			GCHandle recordHandle = GCHandle.Alloc(serviceHandle, GCHandleType.Pinned);

			BitConverter.GetBytes(sdpVersionHandle.AddrOfPinnedObject().ToInt32()).CopyTo(bthnsBlob, 0);
			BitConverter.GetBytes(recordHandle.AddrOfPinnedObject().ToInt32()).CopyTo(bthnsBlob, 4);

			BitConverter.GetBytes(sdpRecord.Length).CopyTo(bthnsBlob, 32);

			Buffer.BlockCopy(sdpRecord, 0, bthnsBlob, 36, sdpRecord.Length);

			// end BTHNS_BLOB

			// create a BLOB to hold the BTHNS_BLOB

			byte[] querySetBlob = new byte[8];

			GCHandle bthnsBlobHandle = GCHandle.Alloc(bthnsBlob, GCHandleType.Pinned);

			BitConverter.GetBytes(80).CopyTo(querySetBlob, 0);
			BitConverter.GetBytes(bthnsBlobHandle.AddrOfPinnedObject().ToInt32()).CopyTo(querySetBlob, 4);

			// end BLOB

			// query set setup
			const int querySetLengthOffset = 0;
			const int querySetNamespaceOffset = 20;
			const int querySetLength = 60;
			const int NS_BTH = 16;

			byte[] querySet = new byte[querySetLength];

			BitConverter.GetBytes(querySetLength).CopyTo(querySet, querySetLengthOffset);
			BitConverter.GetBytes(NS_BTH).CopyTo(querySet, querySetNamespaceOffset);

			GCHandle querySetBlobHandle = GCHandle.Alloc(querySetBlob, GCHandleType.Pinned);

			BitConverter.GetBytes(querySetBlobHandle.AddrOfPinnedObject().ToInt32()).CopyTo(querySet, 56);

			// end query set setup

			// register the service

			int result = SafeNativeMethods.WSASetService(querySet, 0, 0);

			querySetBlobHandle.Free();
			bthnsBlobHandle.Free();
			sdpVersionHandle.Free();
			recordHandle.Free();

			// end register service
		}

		private static byte[] GetLocalAddress()
		{
			byte[] localAddr = new byte[8];

			SafeNativeMethods.BthReadLocalAddr(localAddr);

			return localAddr;
		}


		private static byte[] GenerateSDPRecord(Guid serviceGuid, int channel)
		{
			// build the most basic SDP record specifying the service GUID and channel

			byte[] sdpRecord = new byte[] { 0x35, 0x00, 0x09, 0x00, 0x01, 0x35, 0x11, 0x1c,
				/* guid goes here */		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
											0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
				/* L2CAP + RFCOMM */		0x09, 0x00, 0x04, 0x35, 0x0c, 0x35, 0x03, 0x19,
											0x01, 0x00, 0x35, 0x05, 0x19, 0x00, 0x03, 0x08,
				/* channel number here */	0x00 };

			// set sdp record length
			sdpRecord[1] = Convert.ToByte(sdpRecord.Length - 2);

			// copy in the service guid in network byte order
			byte[] guidArray = serviceGuid.ToByteArray();

			sdpRecord[8] = guidArray[3];
			sdpRecord[9] = guidArray[2];
			sdpRecord[10] = guidArray[1];
			sdpRecord[11] = guidArray[0];

			sdpRecord[12] = guidArray[5];
			sdpRecord[13] = guidArray[4];

			sdpRecord[14] = guidArray[7];
			sdpRecord[15] = guidArray[6];

			Array.Copy(guidArray, 8, sdpRecord, 16, 8);

			// last byte is the RFCOMM channel
			sdpRecord[sdpRecord.Length - 1] = Convert.ToByte(channel);

			return sdpRecord;
		}

		private bool started = false;
		private Guid serviceGuid;
		private Socket serverSocket;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -