Today look for other information, found here Bluetooth development, closed. To prepare for later use.
In Windows Mobile Software development. NET is playing an increasingly important role, we can already see a lot of software developed with. NET CF, which covers every aspect of everyday application. In the software development of intelligent devices, wireless interconnection is a very important piece, we can see that the infrared is almost all the standard of smart devices, and Bluetooth is increasingly in more and more intelligent devices appear, with hardware, it is obvious that the corresponding software related applications.
We also know that it is fairly easy to develop IR communications using. NET CF because there is a namespace in the. NET CF System.Net.IrDA is the communication module for infrared communication. However, there is no module on Bluetooth communication in. NET CF, so there are still some difficulties in the development of this aspect. Next, let's talk about how to develop the. NET CF Bluetooth communication module in C #.
A Basic points
First of all, because it involves the problem of driving the hardware, so the knowledge of C # development is obviously impossible to complete development, we must have knowledge of C + + development. But for the sake of simplicity, we do not want to write half a line of code in C + +, all coding work using C #, that is, the use of the development environment only need to use Visual Studio.NET, do not need to use a different editor.
As a preparation for developing this type of driver hardware, you need to understand the basics of C + +, know what header files are about, and how managed code interacts with unmanaged code. Because the core of this article is a description of how to develop the. NET CF Bluetooth communication module, these preparation knowledge is not described in the foregoing.
Two About Bluetooth
Do Bluetooth communication module development, natural first to know how Bluetooth communication is the same. In my opinion, Bluetooth communication should be similar to the infrared communication module, of course, I am from the perspective of developers, the abstraction should be so, of course, Bluetooth and infrared communication also have a lot of different places, which in the object-oriented design how to say, I think there must be a lot of people understand than I thoroughly. Well, that's our basic idea. I have been on the internet to look up the article about Bluetooth development, many people in. NET CF development to treat Bluetooth communication as a serial communication, which is also good, but I do not like, because this is not for Bluetooth to develop, in other words, in the use of the process, you need to manually open Bluetooth, pairing, connecting , set up a serial channel, then open the application, and you have to set the serial port in the application, which is very troublesome to the end user. I think that this solution to the crown of Bluetooth communication is simply ... Not much, the book is the story.
In infrared communication, we know that the device's DeviceID is a byte array, so what is the DeviceID of the Bluetooth device? I think this is clear to all, is a string of ":" separated by the 16 binary numbers.
Infrared communication, in general, infrared is not open, closed, such as the state, but Bluetooth has turned on, closed, can be found in three states.
IR does not have security settings, and Bluetooth has security settings, so we need to pair the Bluetooth device, and infrared communication is required.
We look at the. NET socket address family with IrDA, but no Bluetooth-related address family, this is the problem we need to solve.
Three Get Device ID
1. Get ID of local device
We looked at the Windows CE 4.2 SDK documentation and learned that the function to get the local device ID was bthreadlocaladdr, in Btdrt.dll. The English text in the SDK documentation is as follows: "This function retrieves the ' Bluetooth address ' of the current device." Well, that's all I know:
Encapsulate local managed functions first:
[DllImport ("Btdrt.dll", Setlasterror=true)]
public static extern int bthreadlocaladdr (byte[] PBA);
The local DeviceID that this function gets is also a set of byte arrays, and in order to show it to people, we want to turn it into a string:
String Text1 = "";
Text1 = Text1 + pba[5]. ToString ("X2") + ":";
Text1 = Text1 + PBA [4]. ToString ("X2") + ":";
Text1 = Text1 + PBA [3]. ToString ("X2") + ":";
Text1 = Text1 + PBA [2]. ToString ("X2") + ":";
Text1 = Text1 + PBA [1]. ToString ("X2") + ":";
Return (Text1 + PBA [0]. ToString ("X2"));
2. Get the ID of the remote device
In fact, when it comes to acquiring the ID of a remote device, it involves how to find a remote device, so the method of discovering the device is also explained here. The discovery device requires three Winsock APIs, namely, Wsalookupservicebegin, WSALookupServiceNext, and WSALookupServiceEnd, The three APIs in the end can go to see the Windows CE 4.2 SDK, here is not explained in detail, just a few points to note.
The prototype of the Wsalookupservicebegin function is this:
INT Wsalookupservicebegin (
Lpwsaqueryset Lpqsrestrictions,
DWORD dwControlFlags,
Lphandle Lphlookup
);
We use managed code to wrap:
[DllImport ("Ws2.dll", entrypoint= "Wsalookupservicebegin", Setlasterror=true)]
public static extern int Celookupservicebegin (byte[] pqueryset, lookupflags dwflags, ref int lphlookup);
As you can see, originally lpqsrestrictions was a struct, packaged in managed code as byte[], we calculated how many byte,struct the struct would take to occupy the position of each member in the byte array, Just assemble it.
Because it is a Bluetooth based development, we want to see what these parameters should be the values. The Windows CE 4.2 SDK says that when Bluetooth is developed, the following members of the struct lpwsaqueryset should be these values:
The dwsize member must is sizeof (Wsaqueryset).
The Lpblob member (itself a pointer to a BLOB structure) are optional, but if used, the device inquire parameters valid for Lup_flushcache are the following:
The cbsize member of the BLOB structure must is sizeof (Bth_query_device).
The Pblobdata member was a pointer to a BTH_QUERY_DEVICE structure, for which the LAP ' is the Bluetooth inquiry acces s code, and the length is the length of the inquiry, in seconds.
The Dwnamespace member must is ns_bth.
All other Wsaqueryset members are ignored.
You can understand what you want, I think it is better than my translation, after all, my English is very poor. According to the above requirements, we assemble pqueryset:
byte[] Buffer1 = new byte[0x400];
Bitconverter.getbytes (60). CopyTo (buffer1, 0);
GCHandle handle1 = GCHandle.Alloc (blob1. Tobytearray (), gchandletype.pinned);
IntPtr ptr1 = handle1. Addrofpinnedobject ();
Bitconverter.getbytes ((int) (PTR1. ToInt32 () + 4)). CopyTo (Buffer1, 0x38);
Another two APIs are called by similar methods.
After calling WSALookupServiceNext, the bytes array Pqueryset contains the address information for the remote device, which we need to find out below. After reading the description of the WSAQUERYSET structure in the SDK and calculating the location of each member, we write the following code:
int NUM5 = Bitconverter.toint32 (Buffer1, 0x30);
int num6 = Marshal.readint32 ((IntPtr) NUM5, 8);
int num7 = Marshal.readint32 ((IntPtr) NUM5, 12);
SocketAddress Address1 = new SocketAddress (addressfamily.unspecified, NUM7);
Because there is no Bluetooth in the address family of the. NET Framework, we use addressfamily.unspecified here.
Then the job is to get the ID of the remote device from:
We've already calculated that the first six bytes in this address are the device IDs in byte array, the seventh to 22nd byte is the Bluetooth service Guid, and the four bytes are the port number, so we just need to extract them separately.
Four Listening Service
The unmanaged API Wsasetservice that listens for service invocation, and its prototype is
INT Wsasetservice (
Lpwsaqueryset Lpqsreginfo,
Wsaesetserviceop Essoperation,
DWORD dwControlFlags
);
You can see that the key is also the first parameter, Lpqsreginfo, this is also a struct, our packaging method and the previous discovery device is similar to the method used to do Bluetooth communication should be aware of its members to be the following settings:
Lpqsreginfo dwsize sizeof (Wsaqueryset)
Lpszserviceinstancename not supported on Windows CE. Set to 0.
Lpserviceclassid not supported on Windows CE. Set to 0.
Dwnamespace ns_bth.
Dwnumberofcsaddrs not supported on Windows CE. Set to 0.
Ipcsabuffer not supported on Windows CE. Set to 0.
Lpblob Points to a BTHNS_SETBLOB structure and containing information about the service to be added.
*
All other wsaqueryset fields are ignored.
Five Connection
We know that connecting remote services in IrDA is the Connect method in the System.Net.Sockets.IrDAClient class using the method. This method is also called in the socket class of the Connect method. And the socket class is a more abstract class, it does not bind a specific address family, SocketType and ProtocolType, so when instantiated, you need to specify these three parameters. We also know that in Irda, these three parameters are Addressfamily.irda, SocketType.Stream, and Protocoltype.ip, so what are the three parameters in Bluetooth, respectively? We can't seem to find it.
Wait a minute, is that so?
We know that in. NET, these three parameters are enumerated values, and enumerations, by default, can be considered an alternative representation of the int value.
How do we know what these three parameters are?
Or first look at the socket type of connect method.
Let's check the data to see that this method is actually an unmanaged function called:
[DllImport ("Mscoree", entrypoint= "@339")]
public static extern int connect (int s, byte[] name, int namelen);
That is, the unmanaged socket API.
We look at the Windows CE 4.2 SDK to see that you need to use the Winsock extension when connecting using Bluetooth. We can also see that in the use of Bluetooth connection, three parameters should be af_bth, Sock_stream and Bthproto_rfcomm, as for these three parameters represent what each, we need to view the relevant header file.
We found the WS2BTH.H header file, and we can see that the af_bth represents the decimal number 32, and the Bthproto_rfcomm represents the hexadecimal number 0x0003, which is exactly the same as the value that the PROTOCOLTYPE.GGP represents. So, we write this when we instantiate the socket:
New Socket ((addressfamily) 0x20, SocketType.Stream, PROTOCOLTYPE.GGP);
Socket instantiation, the rest of course is all right, here no longer repeat.
Six Security settings for Bluetooth
Bluetooth has more security than infrared settings, so it requires a little more code to handle this. The specifics are not much said, in fact, some unmanaged code packaging calls, these APIs in the Btdrt.dll:
Get pairing code Request:
[DllImport ("Btdrt.dll", Setlasterror=true)]
public static extern int bthgetpinrequest (byte[] PBA);
Set pairing code:
[DllImport ("Btdrt.dll", Setlasterror=true)]
public static extern int Bthsetpin (byte[] PBA, int cpinlength, byte[] ppin);
The more troublesome point is pairing, there are three steps in total:
The first is to create an ACL connection:
[DllImport ("Btdrt.dll", Setlasterror=true)]
public static extern int bthcreateaclconnection (byte[] PBT, ref ushort Phandle);
Then the pairing code verification:
[DllImport ("Btdrt.dll", Setlasterror=true)]
public static extern int bthauthenticate (byte[] PBT);
Then be sure to close the connection:
[DllImport ("Btdrt.dll", Setlasterror=true)]
public static extern int bthcloseconnection (ushort handle);
Seven Set Bluetooth radio status
We know that Bluetooth radio is open, shut down, can find three kinds of states, then how do we achieve programming control?
I think this must be known to all, because there are many articles on the Web:
First, write an enumeration:
public enum Radiomode
{
connectable = 1,
Discoverable = 2,
Poweroff = 0
}
Then write a function that calls unmanaged code:
[DllImport ("BthUtil.dll", Setlasterror=true)]
public static extern int BthSetMode (Radiomode dwmode);
To get the radio status, use the following function:
[DllImport ("BthUtil.dll", Setlasterror=true)]
public static extern int BthGetMode (ref radiomode Dwmode);
Eight Known Issues
Perhaps because the Bluetooth control software has not yet been standardized or otherwise, we find that there is a problem with Bluetooth development made using the Winsock extension with the Windows CE 4.2 SDK, and whether the managed or other unmanaged code described in this article As long as the use of this kind of thinking with the development of Winsock 2 There is a problem, that is not on all Windows Mobile devices will work correctly. After my tests, I found that in many devices that use the Bluetooth control software developed separately, such as Lenovo ET560, Asus MyPal A730 can not run on the device, without the development of Bluetooth control software separately, I don't know why Preliminary speculation may be the company developed a separate Bluetooth control software to block the Microsoft API, in the end is not the case, but also to please expert advice.