home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2001 Mobile
/
Chip_Mobile_2001.iso
/
palm
/
business
/
printcar
/
printcar.exe
/
src
/
IrDA
/
IrIAS.cc
< prev
next >
Wrap
C/C++ Source or Header
|
2000-06-05
|
9KB
|
320 lines
//
// $Id: IrIAS.cc,v 1.2 2000/06/04 23:23:39 sergey Exp $
//
#include <Pilot.h>
#include <irlib.h>
#include "IrIAS.h"
#include "IrError.h"
#include "Util/Assert.h"
#include "IrIasParameters.h"
#include "Util/System.h"
namespace IrDA
{
//==============================================================================
// IAS constants
//==============================================================================
static const char* IRDA_NAME = "IrDA";
static const char* IR_DEVICE_CLASS = "Device";
static const char* IR_DEVICE_NAME_ATTRIBUTE = "DeviceName";
static const char* IR_LSAP_SEL_ATTRIBUTE = "LsapSel";
static const char* IR_PARAMETERS_ATTRIBUTE = "Parameters";
static const char* IR_INSTANCE_NAME_ATTRIBUTE = "InstanceName";
static const int QUERY_TIME_OUT = 5; // sec
static const int QUERY_POLLING_PERIOD = 10; // ticks (~0.1 sec?)
//==============================================================================
// IasQueryBuffer class
//==============================================================================
IasQueryBuffer::IasQueryBuffer():
_size(0)
{}
IasQueryBuffer::IasQueryBuffer(const IasQueryBuffer& other)
{
MemMove(_buffer, other._buffer, other._size);
_size = other._size;
}
IasQueryBuffer& IasQueryBuffer::operator =(const IasQueryBuffer& other)
{
MemMove(_buffer, other._buffer, other._size);
_size = other._size;
return *this;
}
// operation
void IasQueryBuffer::init(const char* className, const char* attributeName)
{
reset();
append(className);
append(attributeName);
}
IasQueryBuffer& IasQueryBuffer::append(const char* piece)
{
assert(piece != NULL);
assert(_size+StrLen(piece)+1 <= IR_MAX_QUERY_LEN);
_buffer[_size++] = StrLen(piece);
MemMove(_buffer+_size, piece, StrLen(piece));
_size += StrLen(piece);
return *this;
}
// attributes
char* IasQueryBuffer::toString(char* dest) const
{
assert(_buffer != NULL);
char* str = dest;
for (int pos = 0, len = 0; pos < _size; pos += _buffer[pos]+1)
{
if (pos > 0)
*str++ = ',';
MemMove(str, _buffer+pos+1, _buffer[pos]);
str += _buffer[pos];
}
*str = 0;
return dest;
}
//==============================================================================
// IasAttributeName class
//==============================================================================
IasAttributeName::IasAttributeName()
{
_name[0] = 0;
}
IasAttributeName::IasAttributeName(const char* protocol, const char* attribute)
{
_name[0] = 0;
append(IRDA_NAME);
append(protocol);
append(attribute);
}
IasAttributeName::IasAttributeName(const IasAttributeName& other)
{
StrCopy(_name, other._name);
}
IasAttributeName& IasAttributeName::operator =(const IasAttributeName& other)
{
StrCopy(_name, other._name);
return *this;
}
// operation
IasAttributeName& IasAttributeName::append(const char* piece)
{
assert(piece != NULL);
assert(StrLen(_name)+StrLen(piece) <= IR_MAX_IAS_NAME);
int len = StrLen(_name);
if (len > 0 && _name[len-1] != ':')
StrCat(_name, ":");
StrCat(_name, piece);
return *this;
}
//==============================================================================
// IasQuery class
//==============================================================================
const IasQuery* IasQuery::_this = NULL;
IasQuery::IasQuery(Word refNum):
_refNum(refNum),
_resultState(ResultNotReady)
{}
IasQuery::~IasQuery()
{}
// operations
bool IasQuery::getRemoteLsap(IrClassType classType, IrProtocolType protocolType, Byte& remoteLsap) const
{
if (execute(classTypeName(classType), IasAttributeName(protocolTypeName(protocolType), IR_LSAP_SEL_ATTRIBUTE)))
{
if (waitForResult(IAS_ATTRIB_INTEGER))
{
remoteLsap = IrIAS_GetIntLsap(&_query);
return true;
}
}
return false;
}
bool IasQuery::getRemoteDeviceName(char* buffer) const
{
assert(buffer != NULL);
if (execute(IR_DEVICE_CLASS, IR_DEVICE_NAME_ATTRIBUTE))
{
if (waitForResult(IAS_ATTRIB_USER_STRING))
return getResultUserString(buffer);
}
return false;
}
bool IasQuery::getRemoteInstanceName(char* buffer) const
{
assert(buffer != NULL);
// defined only for IrCOMM class and IrLMP protocol
if (execute(classTypeName(IrCommClass), IasAttributeName(protocolTypeName(IrLmpProtocol), IR_INSTANCE_NAME_ATTRIBUTE)))
{
if (waitForResult(IAS_ATTRIB_USER_STRING))
return getResultUserString(buffer);
}
return false;
}
bool IasQuery::getRemoteParameter(IasParameter& remoteParameter) const
{
// Attribute defined only for IrCOMM class.
if (execute(classTypeName(IrCommClass), IR_PARAMETERS_ATTRIBUTE))
{
if (waitForResult(IAS_ATTRIB_OCTET_STRING))
{
IasParameterList parameters(IrIAS_GetOctetString(&_query), IrIAS_GetOctetStringLen(&_query));
return parameters.getParameter(remoteParameter);
}
}
return false;
}
// utilities
const char* IasQuery::classTypeName(IrClassType classType)
{
static const char* classes[] = { "Unknown", "IrDA:IrCOMM", "IrLPT" };
return classes[classType];
}
const char* IasQuery::protocolTypeName(IrProtocolType protocolType)
{
static const char* protocols[] = { "Unknown", "IrLMP", "TinyTP" };
return protocols[protocolType];
}
// implementation
bool IasQuery::execute(const char* className, const char* attributeName) const
{
_queryBuffer.init(className, attributeName);
_query.queryBuf = const_cast<Byte*>(_queryBuffer.data());
_query.queryLen = _queryBuffer.size();
_query.resultBufSize = sizeof(_resultBuffer);
_query.result = _resultBuffer;
_query.callBack = queryCallback;
_this = this;
_resultState = ResultNotReady;
IrStatus rc = IrIAS_Query(_refNum, &_query);
if (rc != IR_STATUS_PENDING)
{
char text[IR_MAX_QUERY_LEN];
IrError::iasQueryError(_queryBuffer.toString(text), rc);
_resultState = ErrorResult;
return false;
}
return true;
}
bool IasQuery::waitForResult(int expectedResultType) const
{
int count = QUERY_TIME_OUT*SysTicksPerSecond()/QUERY_POLLING_PERIOD;
for (int i = 0; i < count && _resultState == ResultNotReady; ++i)
Util::YieldControlToSystem(QUERY_POLLING_PERIOD, false);
if (_resultState == ResultReady)
return checkResultType(expectedResultType);
return false;
}
bool IasQuery::checkResultType(int resultType) const
{
IrIAS_StartResult(&_query); // must be called before reading the result, IrLIB "forgot" to initialize offset
if (IrIAS_GetType(&_query) != resultType)
{
char text[IR_MAX_QUERY_LEN];
IrError::unexpectedIasQueryError(_queryBuffer.toString(text), IrIAS_GetType(&_query));
return false;
}
return true;
}
bool IasQuery::getResultUserString(char* buffer) const
{
int len = IrIAS_GetUserStringLen(&_query);
void* data = IrIAS_GetUserString(&_query);
if (data != NULL)
{
MemMove(buffer, data, len);
buffer[len] = 0;
return true;
}
return false;
}
// callback
void IasQuery::queryCallback(IrStatus status)
{
if (status != IR_STATUS_SUCCESS)
{
IrError::iasCallbackError(status);
_this->_resultState = ErrorResult;
return;
}
if (_this->_query.retCode != IAS_RET_SUCCESS)
{
_this->_resultState = ErrorResult;
return;
}
_this->_resultState = ResultReady;
}
}
// namespace IrDA