Develop .NET CF Bluetooth Communication Module with C # Development .NET CF Bluetooth Communication Module
In Windows Mobile software development .NET is playing an increasingly important role, we can see many software developed with .NET CF, these software involves all aspects of everyday applications. In the software development of smart devices, wireless interconnections are a fairly important piece. We can see that infrared is almost all smart devices, and Bluetooth is also increasingly appearing on more and more smart devices. With hardware It is clear that there must be corresponding software related applications.
We also know that it is relaxed when developing infrared communication with .NET CF, because there is a naming space in .NET CF System.Net.IRDA is a communication module for infrared communication. However, there is no module for Bluetooth communication in .NET CF, it is difficult to do this in this regard. Below, talk about how to develop .NET CF Bluetooth communication module with C #.
One. Basic point
First of all, it is clear that it is obviously unable to complete the development of C # development because of the problem of driving hardware, so we must understand C development. But for the sake of simplicity, we don't want to write half of the code with C , all the coding works all C #, which means that the development environment that uses Visual Studio. Net, does not require other editors.
As a result of developing such drive hardware, you need to understand the basic knowledge of C , know how the header file is, know how the managed code interacts with the non-hosting code. Because the core of this article explains how to develop .NET CF Bluetooth communication modules, these preparation knowledge is not described above.
two. About Bluetooth
Making a Bluetooth communication module development, naturally know how Bluetooth communication is. In my opinion, Bluetooth communication should be similar to the infrared communication module. Of course, I am from the developer's perspective. It should be like this. Of course, Bluetooth and infrared communications have a lot of different places, which is in object-oriented design. How do I say, I think there must be a lot of people to understand than I am thorough. Ok, this is our basic idea. I have checked the article on Bluetooth development online. Many people are handled by Bluetooth communication as a serial communication in .NET CF development, this is not bad, but I don't like it very much, because I do it, not For Bluetooth, in other words, in the process of use, you need to manually turn on Bluetooth, pair, connect, create a serial channel, then turn on the application, you have to set the serial port in the application, and to end users Speaking, this is very troublesome. I think this solution is that the name of the Bluetooth communication is simply ... not much, the book is passed.
In infrared communication, we know that the device's DeviceID is an array, then what is the DeviceID of the Bluetooth device? I think this everyone is very clear, it is a string of 16-based numbers separated by ":".
In infrared communication, there is generally not open, close, and the Bluetooth is turned on, off, and three states can be found.
There is no security setting in infrared, and Bluetooth has security settings, so we need to pair Bluetooth devices, and this need for infrared communication.
We look at the .NET's Socket address family with Irda, but there is no Bluetooth-related address family, this is what we need to solve.
three. Get device ID
1. Get the ID of the local device
We look at the SDK documentation of Window CE 4.2, know that the function that gets the local device ID is Bthreadlocaladdr, in BTDRT.DLL. The original article in the SDK document is this: "This function retrieves the Bluetooth address of the current device." Ok, I know this. I said: First, the local managed function is first encapsulated:
[DLLIMPORT ("BTDRT.DLL", setLastError = true)]
Public Static Extern Int Bthreadlocaladdr (Byte [] PBA);
The local DeviceID obtained by this function is also a group of Byte arrays. In order to display people, we have to turn it into 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, talking about how to get a remote device is involved in how to discover remote devices, so here will also explain the method of discovering equipment here.
Discovering equipment requires three Winsock APIs, which are WSALookupServiceBegin, WSALookupServiceExT, and WSAlookupServiceEnd. What role begins to view Windows CE 4.2's SDK, here is not explained in detail, just talk about a few more local.
WSALOOKUPSERVICEBEGIN's function is like this:
Int WsalookupServiceBegin
LPWSAQUERYSET LPQSRESTRICTIONS,
DWORD DWCONTROLFLAGS,
LPHANDLE LPHLOOKUP
);
We pack with managed code:
[DLLIMPORT ("ws2.dll", entrypoint = "wsalookupservicebegin", setlasterror = true)]
Public static extern int CelookupServiceBegin (Byte [] PQuerySet, LookupFlags DWFLAGS, REF INT LPHLOOKUP;
It can be seen that the original lpqsrestriotions is a structure. After packaging, it has become BYTE in the hosted code [], how many Byte, how to occupy this Struct, how is the location in the Byte array in the struct, It is good to assemble it.
Since it is a development of Bluetooth, we have to check what these parameters should be. In the SDK of Windows CE 4.2, the following members in the Struct LPWSAQUERYSET should be these values when Bluetooth development: The DWSIZE MEMBER MUSTBEOF (WSAQueryset).
The LPBLOB MEMBER (Itself A Pointer to a blob structure is optional, but if used, the device inquire parameters valid for lup_flushcache is Following:
The CBSIZE Member of The Blob Structure Must Be sizeof (bth_query_device).
The Pblobdata Member Is A Pointer TO A Bth_query_device structure
The dwnamespace member must be ns_bth.
All Other WSAQuerySet Members Are Ignored.
What do you mean to understand yourself, I think it is better than I translated, after all, my English is very poor. According to the above requirements, we are equipped with PQuerySet:
Byte [] buffer1 = new byte [0x400];
BitConverter.getbytes (60) .couthto (buffer1, 0);
Gchandle Handle1 = gchaldle.alloc (blob1.tobyteaRray (), gchandletype.pinned;
INTPTR PTR1 = Handle1.AddrofpinnedObject ();
BitConverter.getbytes ((int) (Ptr1.Toint32 () 4)))). CopyTo (buffer1, 0x38);
The other two APIs are also called by similar methods.
After calling WSALOKUPSERVICENEXT, the Bytes array PQuerySet contains address information of the remote device. Here we need to find it. After reading the description of the WSAQueryset structure in the SDK and calculates the location of each member, we have written 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 .NET frame, we use AddressFamily.unSpecified.
Then work is to get the id of the remote device:
As we have calculated, the top six bytes inside this address are the device ID in the form of the BYTE array, and the seventh to twenty-two bytes are Bluetooth service guid, and the four bytes behind are port numbers, so We only need to extract them separately.
four. Monitor service
The listening service call is the non-hosting API WsasetService, its prototype is
Int WsasetService (LPWSAQUERYSET LPQSREGINFO,
WSAESETSERVICEOP ESSOPERATION,
DWORD DWCONTROLFLAGS
);
It can be seen that the key is the first parameter, LPQSREGINFO, this is also a structure, our packaging method is similar to the method used in the previous discovery equipment, pay attention to its members as follows:
lpqsRegInfodwSizesizeof (WSAQUERYSET) lpszServiceInstanceNameNot supported on Windows CE. Set to 0. lpServiceClassIdNot supported on Windows CE. Set to 0. dwNameSpaceNS_BTH. dwNumberOfCsAddrsNot supported on Windows CE. Set to 0. IpcsaBufferNot supported on Windows CE. Set to 0. lpBlobPoints to a BTHNS_SETBLOB Structure, Containing Information About The Service To Be Added. * All Other WSAQuerySet Fields Are Ignored.
Fives. Connection
We know that connecting remote services in IRDA is the use of the Connect method in the System.Net.Sockets.Irdaclient class. This method is also a Connect method in the called socket class. The Socket class is a comparative abstract class that does not bind a specific address family, sockettype, and protocoltype, so you need to specify these three parameters when instantiation. We also know that in Irda, these three parameters are AddressFamily.irda, Sockettype.Stream, and protocoltype.ip, then what is the three parameters in Bluetooth? We can't find it.
And slow, really like this?
We know that in .NET, these three parameters are enumerated values, and enumerations are default, you can think that it is an alternative to INT values.
How do we know what these three parameters are?
Still first look at the CONNECT method of the Socket class.
We check the information, you can know that this method is actually called an unmanaged function:
[DLLIMPORT ("Mscoree", entrypoint = "@ 339")]
Public Static Extern Int Connect (Int S, Byte [] Name, INT Namelen
That is, non-hosted Socket API.
We look at the SDK of Windows CE 4.2, you can see that Winsock extensions are required when connecting to Bluetooth. We can also see that when you connect to Bluetooth, the three parameters should be AF_BTH, SOCK_STREAM and BTPROTO_RFCCMM, respectively, as for what these three parameters are representative, and we must see the relevant header files.
We found the ws2bth.h header file, you can see that AF_BTH represents the decimal number 32, and BthProto_RFComm represents the number of hexadecimal number 0x0003, which is consistent with the value of protocoltype.ggp represents. So, we wrote this when instantix SOCKET:
New Socket (AddressFamily) 0x20, sockettype.stream, protocoltype.ggp); socket instantiation, other of course, it is said, and will not be described here.
six. Bluetooth security settings
Bluetooth is more security settings than infrared, so there is a need for more code to process these. Specifically, there is not much to say, in fact, the packaging call of some non-hosting code, these APIs are in BTDRT.DLL:
Get a code request:
[DLLIMPORT ("BTDRT.DLL", setLastError = true)]
Public Static Extern Int BthgetpinRequest (byte [] PBA);
Set the pairing code:
[DLLIMPORT ("BTDRT.DLL", setLastError = true)]
Public static extern int bthsetpin (Byte [] PBA, INT CPINLENGTH, BYTE [] PPIN);
What is more troublesome is pairing, with a total of three steps:
The first is to create an ACL connection:
[DLLIMPORT ("BTDRT.DLL", setLastError = true)]
Public static extern int bthcreateaClConnection (Byte [] PBT, Ref ushort phandle;
Then a pairing code verification:
[DLLIMPORT ("BTDRT.DLL", setLastError = true)]
Public static extern int bthauthenticate (Byte [] PBT);
Then you must turn it off:
[DLLIMPORT ("BTDRT.DLL", setLastError = true)]
Public static extern int bthcloseConnection (Ushort Handle);
Seven. Set Bluetooth radio status
We know that Bluetooth radio is open, close, can find three states, then how do we implement programming?
I think this must everyone know, because there are many articles on this online:
Write a enumeration first:
Public Enum Radiomode
{
CONNECTABLE = 1,
Discoverable = 2,
Poweroff = 0
}
Then write a function to call the unmanaged code:
[DLLIMPORT ("Bthutil.dll", setLastError = true)]
Public Static Extern Int BthSetMode (Radiomode dwmode);
Use the following functions when getting radio state:
[DLLIMPORT ("Bthutil.dll", setLastError = true)]
Public Static Extern Int BthgetMode (Ref Radiomode DWMode);
Eight. Known problem