I'm developing an application (Pocket PC 2003 / Windows Mobile 2003) which should establish a RFCOMM Bluetooth connection to a bluetooth-server-device. ( A serial interface for an older non-bluetooth version of this device already exists. PPC is the T-Mobile MDA )
So i checked the scanty microsoft documentation and found out, that it is possible to create a virtual com port with
RegisterDevice(L"COM", index, L"btd.dll", (DWORD)&pp).
With WSALookupServiceBegin(...) and WSALookupServiceNext(...) it was possible to detect the BT_ADDR needed for the PORTEMUPortParams (see above -> pp ) device parameter.
But RegisterDevice always fails with SystemError:ERROR_DEVICE_IN_USE (The device is in use by an active process and cannot be disconnected.) - Then i checked the "HKLM\drivers\Active" Key in my PPC registry and found out, that there is no service using COM 4, 5 or 6. But this Ports also generate this error message.
Interestingly enough the "btd.dll" is not yet loaded. So i guess my PORTEMUPortParams structure isn't the error source.
The sample source code supplied with Windows CE Evaluation Edition seems to do exactly the same.
Maybe I could have forgotten to implement several important gimmicks. Or maybe there is another way to connect with a RFCOMM bluetooth device.
Thanks in advance.
Here is the source (without catching any errors :)
/*+++++++++++Startup WSA+++++++++++++++++*/
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 2 );
WSAStartup( wVersionRequested, &wsaData );
/*+++++++++++++Search for my device++++++++++++++++*/
INT iResult = 0;
LPWSAQUERYSET pwsaResults;
DWORD dwSize = 0;
WSAQUERYSET wsaq;
HANDLE hLookup = 0;
memset (&wsaq, 0, sizeof(wsaq));
wsaq.dwSize = sizeof(wsaq);
wsaq.dwNameSpace = NS_BTH;
wsaq.lpcsaBuffer = NULL;
WSALookupServiceBegin(&wsaq, LUP_CONTAINERS, &hLookup);
union {
CHAR buf[5000];
SOCKADDR_BTH __unused;
};
pwsaResults = (LPWSAQUERYSET) buf;
dwSize = sizeof(buf);
memset(pwsaResults,0,sizeof(WSAQUERYSET));
pwsaResults->dwSize = sizeof(WSAQUERYSET);
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->lpBlob = NULL;
WSALookupServiceNext (hLookup, LUP_RETURN_NAME | LUP_RETURN_ADDR, &dwSize, pwsaResults);
// Real device name is found ... pwsaResults->lpszServiceInstanceName;
/*+++++++++Now trying to register the virtual COM Port+++++++++++++++*/
PORTEMUPortParams pp;
memset (&pp, 0, sizeof(pp));
pp.channel = 0;
pp.flocal = false;
pp.device = reinterpret_cast<_SOCKADDR_BTH*>(pwsaResults->lpcsaBuffer->LocalAddr.lpSockaddr)->btAddr;
//the detected BT_ADDR
memcpy(&pp.uuidService, &CLSID_NULL, sizeof(GUID));
pp.uiportflags = RFCOMM_PORT_FLAGS_REMOTE_DCB;
int port = 4; //or anything else like 1..4,5 or 6..9 | Limit is 9 i think
HANDLE bth = RegisterDevice (L"COM", port, L"btd.dll", (DWORD)&pp));
/*++++++++the result+++++++++++++++++++*/
//bth == 0
//GetLastError () == ERROR_DEVICE_IN_USE :(
by: cindy_kPosted on 2003-11-04 at 10:57:10ID: 9680833
Here is some code I use to Register a com port to use with Bluetooth.
_hDlg,TXT_ CHANNEL),s Channel,3) ; hannel);
********** ********** ********** ********** ********* ********** ********** ********** ********** ********* ********** ********** ********** ********** *********
NULL)); // Clear the wait cursor
********** ********** ********** ********** ********** *** ********** ********** ********** ********** ********** **/
I noticed you Channel is 0, try setting it to 1.
You can discover the Channel by Querying for information on the RFCOMM Serial Service but doing full SDP is a pain.
You are correct the limit is 9 for com ports on a CE device.
The GetBA function I call is from a Sample from Microsoft Platform builder.
I included it so you can look at it.
If this function succeeds you should be able to open the Com Port and communicate over it.
This function will not check to see if the device you are connecting to exists, it just sets up the comm port.
When you go to open the Comm Port if the device is out of range, suspended, whatever the CreateFile call will fail.
Hope this helps,
Cynthia
BOOL RegisterPort(void)
{
PORTEMUPortParams pp;
int nIndex;
WCHAR sBA[13];
int nChannel;
WCHAR sChannel[4];
GetWindowText(GetDlgItem(g
swscanf(sChannel,L"%d",&nC
WCHAR sIdx[2];
int idx;
//************************
//************************
//************************
// This section demonstrates how to create a BT virtual COM port
// Begin
memset (&pp, 0, sizeof(pp)); // Clear the PORTEMUPortParams structure.
// pp.channel = 6; //Printer // Set to either an explicit server
pp.channel = nChannel; // channel, or, for a server
// application that wants the
// server channel to be autobound,
// to RFCOMM_CHANNEL_MULTIPLE.
// pp.channel = RFCOMM_CHANNEL_MULTIPLE;
pp.flocal = FALSE; // Set to FALSE for a client port that
// is used to creating outgoing connections.
GetBA(_T("0002C710F63E"), &pp.device); // Using Static BTADDR
nIndex = 7; // This must be the same as the COM port number.
// For devices that expose the stream interface, the drivers are
// DLL files. Each driver is initialized by a call to the RegisterDevice
// function. The Device Manager calls this function on behalf of the
// driver. However, applications can load their own special-purpose stream
// interface, in which case they also call this function to register the driver.
h = RegisterDevice(_T("COM"), nIndex, _T("btd.dll"), (DWORD)&pp);
if (h != NULL)
{
bRegister = TRUE;
}
else
bRegister = FALSE;
SetCursor(LoadCursor(NULL,
return bRegister;
}
/*************************
FUNCTION: GetBA
PROTOTYPE: int GetBA (WCHAR *pp, BT_ADDR *pba)
PURPOSE: Form the BDADDR in a way the PORTEMUPortParams structure
understands.
**************************
int GetBA (WCHAR *pp, BT_ADDR *pba)
{
// Bump pointer through any leading spaces
while (*pp == ' ')
++pp;
for (int i = 0 ; i < 4 ; ++i, ++pp)
{
if (!iswxdigit (*pp))
return(FALSE);
int c = *pp;
if (c >= 'a')
c = c - 'a' + 0xa;
else if (c >= 'A')
c = c - 'A' + 0xa;
else c = c - '0';
if ((c < 0) || (c > 16))
return(FALSE);
*pba = *pba * 16 + c;
}
for (i = 0; i < 8 ; ++i, ++pp)
{
if (!iswxdigit (*pp))
return(FALSE);
int c = *pp;
if (c >= 'a')
c = c - 'a' + 0xa;
else if (c >= 'A')
c = c - 'A' + 0xa;
else c = c - '0';
if ((c < 0) || (c > 16))
return(FALSE);
*pba = *pba * 16 + c;
}
if ((*pp != ' ') && (*pp != '\0'))
return(FALSE);
else
return(TRUE);
}