programming MSI pc2pc bluetooth key in Windows XP
Posted: 06-03-2004, 07:33 AM
Here is a sample code, how to program MSI pc2pc bluetooth key in
Windows XP with C++. The main API constis of CommOpen, CommWrite and
CommClose. This sample is for specific bluetooth device, but here you
have idea what you need, for example using overlapping is a must in
our product, otherwise the software hangs when using WriteFile.
#include <windows.h>
#include <stdio.h>
#include "bl_port.h"
//TIMER_TIMEOUT in seconds
#define TIMER_TIMEOUT 3
#define RESPONSE_SIZE 1024
static BOOLEAN comm_runTimerThread = TRUE;
static BOOLEAN comm_timeOuted = FALSE;
static char comm_response[RESPONSE_SIZE];
static int comm_pos = 0;
FILE *comm_f;
void comm_debug(char*);
char comm_buf[256];
HANDLE handles[1];
BOOLEAN recRunning = TRUE;
OVERLAPPED overlapped2;
void notifySymbol(int group, int selection);
void attachThread();
void detachThread();
int NEAR ReadBlock( HANDLE hPort, LPSTR lpszBlock, int nMaxLength )
{
BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength;
DWORD dwError;
char szError[ 10 ] ;
// only try to read number of bytes in queue
ClearCommError( hPort, &dwErrorFlags, &ComStat ) ;
dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;
if (dwLength > 0)
{
fReadStat = ReadFile( hPort, lpszBlock,
dwLength, &dwLength, &overlapped2 ) ;
if (!fReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
comm_debug("\n\rIO Pending");
// We have to wait for read to complete.
// This function will timeout according to the
// CommTimeOuts.ReadTotalTimeoutConstant variable
// Every time it times out, check for port errors
while(!GetOverlappedResult( hPort,
&overlapped2, &dwLength, TRUE ))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
// normal result if not finished
continue;
else
{
// an error occurred, try to recover
wsprintf( szError, "<CE-%u>", dwError ) ;
comm_debug(szError);
ClearCommError( hPort, &dwErrorFlags, &ComStat ) ;
break;
}
}
}
else
{
// some other error occurred
dwLength = 0 ;
ClearCommError( hPort, &dwErrorFlags, &ComStat ) ;
wsprintf( szError, "<CE-%u>", dwErrorFlags ) ;
comm_debug(szError);
}
}
}
return ( dwLength ) ;
} // end of ReadCommBlock()
int CommOpen (LPTSTR lpszPortName, int rate, int data_bits, int
stop_bits, int parity)
{
DWORD dwError,
dwThreadID;
DCB PortDCB;
COMMTIMEOUTS CommTimeouts;
HANDLE comm_hReadThread;
HANDLE comm_hPort;
// Open the serial port.
comm_hPort = CreateFile (lpszPortName, // Pointer to the name of the
port
GENERIC_READ | GENERIC_WRITE,
// Access (read-write) mode
0, // Share mode
NULL, // Pointer to the security
attribute
OPEN_EXISTING,// How to open the serial port
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
// Port attributes
NULL); // Handle to port with attribute
// to copy
// If it fails to open the port, return FALSE.
if ( comm_hPort == INVALID_HANDLE_VALUE )
{
// Could not open the port.
// MessageBox (NULL, TEXT("Cannot open bluetooth port"),
// TEXT("Error"), MB_OK);
dwError = GetLastError ();
return 0;
}
PortDCB.DCBlength = sizeof (DCB);
// Get the default port setting information.
GetCommState (comm_hPort, &PortDCB);
// Change the DCB structure settings.
PortDCB.BaudRate = rate; // Current baud
PortDCB.fBinary = TRUE; // Binary mode; no EOF check
PortDCB.fParity = FALSE; // Enable parity checking
PortDCB.fOutxCtsFlow = FALSE; // No CTS output flow control
PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control
PortDCB.fDtrControl = DTR_CONTROL_DISABLE;
// DTR flow control type
PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity
PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx
PortDCB.fOutX = FALSE; // No XON/XOFF out flow
control
PortDCB.fInX = FALSE; // No XON/XOFF in flow control
PortDCB.fErrorChar = FALSE; // Disable error replacement
PortDCB.fNull = FALSE; // Disable null stripping
PortDCB.fRtsControl = RTS_CONTROL_DISABLE;//
// RTS flow control
PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes
on
// error
PortDCB.ByteSize = data_bits; // Number of
bits/byte, 4-8
PortDCB.Parity = parity; // 0-4=no,odd,even,mark,space
PortDCB.StopBits = stop_bits; // 0,1,2 = 1, 1.5, 2
// Configure the port according to the specifications of the DCB
// structure.
if (!SetCommState (comm_hPort, &PortDCB))
{
// Could not create the read thread.
MessageBox (NULL, TEXT("Unable to configure the bluetooth port"),
TEXT("Error"), MB_OK);
dwError = GetLastError ();
return 0;
}
// Retrieve the time-out parameters for all read and write
operations
// on the port.
GetCommTimeouts (comm_hPort, &CommTimeouts);
// Change the COMMTIMEOUTS structure settings.
CommTimeouts.ReadIntervalTimeout = 1;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 0;
CommTimeouts.WriteTotalTimeoutMultiplier = 0;
CommTimeouts.WriteTotalTimeoutConstant = 0;
// Set the time-out parameters for all read and write operations
// on the port.
if (!SetCommTimeouts (comm_hPort, &CommTimeouts))
{
// Could not create the read thread.
MessageBox (NULL, TEXT("Unable to set the time-out parameters"),
TEXT("Error"), MB_OK);
dwError = GetLastError ();
return 0;
}
// Direct the port to perform extended functions SETDTR and SETRTS
// SETDTR: Sends the DTR (data-terminal-ready) signal.
// SETRTS: Sends the RTS (request-to-send) signal.
//EscapeCommFunction (comm_hPort, SETDTR);
//EscapeCommFunction (comm_hPort, SETRTS);
handles[0] = comm_hPort;
recRunning = TRUE;
// Create a read thread for reading data from the communication
port.
if (comm_hReadThread = CreateThread (NULL, 0, CommReadThread,
(LPVOID)0, 0,
&dwThreadID))
{
CloseHandle (comm_hReadThread);
}
else
{
// Could not create the read thread.
MessageBox (NULL, TEXT("Unable to create the read thread"),
TEXT("Error"), MB_OK);
dwError = GetLastError ();
return 0;
}
Sleep(500);
return 1;
}
void WriterGeneric(HANDLE hp, char * lpBuf, DWORD dwToWrite)
{
OVERLAPPED osWrite = {0};
HANDLE hArray[1];
DWORD dwWritten;
DWORD dwRes;
//
// create this writes overlapped structure hEvent
//
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osWrite.hEvent == NULL)
;//ErrorInComm("CreateEvent (overlapped write hEvent)");
hArray[0] = osWrite.hEvent;
//
// issue write
//
if (!WriteFile(hp, lpBuf, dwToWrite, &dwWritten, &osWrite)) {
if (GetLastError() == ERROR_IO_PENDING) {
//
// write is delayed
//
dwRes = WaitForMultipleObjects(1, hArray, FALSE,
INFINITE);
switch(dwRes)
{
//
// write event set
//
case WAIT_OBJECT_0:
SetLastError(ERROR_SUCCESS);
if (!GetOverlappedResult(hp, &osWrite,
&dwWritten, FALSE)) {
if (GetLastError() ==
ERROR_OPERATION_ABORTED)
comm_debug("Write aborted\r\n");
else
comm_debug("GetOverlappedResult(in
Writer)");
}
if (dwWritten != dwToWrite) {
if (GetLastError() == ERROR_SUCCESS)
comm_debug("Write timed out.
(overlapped)\r\n");
else
comm_debug("Error writing data to
port (overlapped)");
}
break;
//
// wait timed out
//
case WAIT_TIMEOUT:
comm_debug("Wait Timeout in
WriterGeneric.\r\n");
break;
case WAIT_FAILED:
default: comm_debug("WaitForMultipleObjects
(WriterGeneric)");
break;
}
}
else
; //
// writefile failed, but it isn't delayed
//
comm_debug("WriteFile (in Writer)");
}
else {
//
// writefile returned immediately
//
if (dwWritten != dwToWrite)
;comm_debug("Write timed out. (immediate)\r\n");
}
CloseHandle(osWrite.hEvent);
return;
}
DWORD ComWriteBuf (HANDLE hp, int* buf ,int buf_len)
{
DWORD dwError = S_OK;
BYTE* byteBuf;
int i;
byteBuf = (BYTE*)malloc(buf_len * sizeof(BYTE));
for (i = 0; i < buf_len; i++) {
byteBuf[i] = (BYTE)buf[i];
}
WriterGeneric(hp, byteBuf, buf_len);
free(byteBuf);
return dwError;
}
void comm_putToResponse(BYTE byte) {
comm_response[comm_pos] = (char) byte;
comm_pos++;
if (comm_pos >= RESPONSE_SIZE) {
comm_pos = 0;
}
if ((comm_response[0] == (char)0x93) && (comm_pos == 13)) {
comm_pos = 0;
notifySymbol((int)comm_response[3], (int)comm_response[4]);
}
}
/************************************************** *********************
PortReadThread (LPVOID lpvoid)
************************************************** *********************/
DWORD WINAPI CommReadThread (LPVOID lpvoid)
{
int i = (int) lpvoid;
HANDLE hp = handles[i];
DWORD dwEvtMask ;
OVERLAPPED os ;
int nLength ;
BYTE abIn[ 1 + 1] ;
attachThread();
Sleep(3000);
memset( &os, 0, sizeof( OVERLAPPED ) ) ;
// create I/O event used for overlapped read
os.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (os.hEvent == NULL)
{
comm_debug("Failed to create event for thread!");
return ( FALSE ) ;
}
if (!SetCommMask( hp, EV_RXCHAR ))
return ( FALSE ) ;
while ( recRunning )
{
dwEvtMask = 0 ;
WaitCommEvent( hp, &dwEvtMask, NULL );
if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
{
do
{
if (nLength = ReadBlock( hp, (LPSTR) abIn, 1))
{
comm_putToResponse(abIn[0]);
}
}
while ( nLength > 0 ) ;
}
}
// get rid of event handle
CloseHandle( os.hEvent ) ;
// clear information in structure (kind of a "we're done flag")
// hCommWatchThread = NULL;
//dwThreadID = 0;
return( TRUE ) ;
}
void comm_StopTimerThread() {
comm_runTimerThread = FALSE;
}
/************************************************** *********************
PortClose (HANDLE hCommPort)
************************************************** *********************/
BOOL CommClose (int hCommPort)
{
DWORD dwError;
//comm_debug("comm close");
recRunning = FALSE;
comm_StopTimerThread();
// Close the communication port.
if (!CloseHandle (handles[hCommPort - 1]))
{
dwError = GetLastError ();
sprintf(comm_buf, "CommClose failed, error=%d", dwError);
comm_debug(comm_buf);
return FALSE;
}
else
{
Sleep(500);
return TRUE;
}
return FALSE;
}
DWORD WINAPI comm_TimerThread (LPVOID lpvoid) {
DWORD orig;
DWORD now;
orig = GetTickCount();
do {
now = GetTickCount();
Sleep(100);
if ((now - orig) > (TIMER_TIMEOUT * 1000)) {
comm_timeOuted = TRUE;
}
} while ((comm_runTimerThread == TRUE) && (comm_timeOuted == FALSE));
return 0;
}
void comm_StartTimerThread() {
HANDLE hTimerThread;
DWORD dwThreadID;
comm_runTimerThread = TRUE;
comm_timeOuted = FALSE;
if (hTimerThread = CreateThread (NULL, 0, comm_TimerThread, 0, 0,
&dwThreadID))
{
CloseHandle (hTimerThread);
}
else {
comm_debug("TimerThread creation failed!");
}
}
BOOLEAN comm_waitFor(char* reply, int len) {
comm_StartTimerThread();
do {
Sleep(100);
} while ((comm_timeOuted == FALSE) && (memcmp(reply, comm_response,
len) != 0));
comm_StopTimerThread();
return !comm_timeOuted;
}
DWORD CommWrite(int port, int* message, int msg_len, int* reply, int
reply_len) {
DWORD ret = S_FALSE;
int i = 0;
HANDLE hp;
char reply_buf[RESPONSE_SIZE];
hp = handles[port -1];
//Sleep (500);
comm_response[0] = 0;
comm_response[1] = 0;
comm_response[2] = 0;
comm_pos = 0;
ret = ComWriteBuf (hp, message, msg_len);
if( ret != S_OK) {
return ret;
}
if ((reply != NULL) && (reply_len > 0)) {
for (i = 0; i < reply_len; i++) {
reply_buf[i] = (char)reply[i];
}
if (comm_waitFor(reply_buf, reply_len) == FALSE) {
comm_debug("reply failed");
ret = ERROR_TIMEOUT;
goto Exit;
}
}
ret = S_OK;
//comm_debug("sending successful");
Exit:
free (message);
if (reply != NULL) {
free(reply);
}
comm_pos = 0;
return ret;
}
void comm_debug(char* message) {
comm_f = fopen("commdebug.txt","a");
fprintf(comm_f, "%s\n", message);
fclose(comm_f);
}



Linear Mode

