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 >
C/C++ Source or Header  |  2000-06-05  |  9KB  |  320 lines

  1. //
  2. // $Id: IrIAS.cc,v 1.2 2000/06/04 23:23:39 sergey Exp $
  3. //
  4.  
  5. #include <Pilot.h>
  6. #include <irlib.h>
  7. #include "IrIAS.h"
  8. #include "IrError.h"
  9. #include "Util/Assert.h"
  10. #include "IrIasParameters.h"
  11. #include "Util/System.h"
  12.  
  13.  
  14. namespace IrDA
  15. {
  16.     //==============================================================================
  17.     // IAS constants
  18.     //==============================================================================
  19.  
  20.     static const char* IRDA_NAME                    = "IrDA";
  21.     static const char* IR_DEVICE_CLASS              = "Device";
  22.     static const char* IR_DEVICE_NAME_ATTRIBUTE     = "DeviceName";
  23.     static const char* IR_LSAP_SEL_ATTRIBUTE        = "LsapSel";
  24.     static const char* IR_PARAMETERS_ATTRIBUTE      = "Parameters";
  25.     static const char* IR_INSTANCE_NAME_ATTRIBUTE   = "InstanceName";
  26.  
  27.     static const int QUERY_TIME_OUT             = 5;        // sec
  28.     static const int QUERY_POLLING_PERIOD       = 10;       // ticks (~0.1 sec?)
  29.  
  30.  
  31.     //==============================================================================
  32.     // IasQueryBuffer class
  33.     //==============================================================================
  34.  
  35.     IasQueryBuffer::IasQueryBuffer():
  36.         _size(0)
  37.     {}
  38.  
  39.     IasQueryBuffer::IasQueryBuffer(const IasQueryBuffer& other)
  40.     {
  41.         MemMove(_buffer, other._buffer, other._size);
  42.         _size = other._size;
  43.     }
  44.  
  45.     IasQueryBuffer& IasQueryBuffer::operator =(const IasQueryBuffer& other)
  46.     {
  47.         MemMove(_buffer, other._buffer, other._size);
  48.         _size = other._size;
  49.         return *this;
  50.     }
  51.  
  52.     // operation
  53.  
  54.     void IasQueryBuffer::init(const char* className, const char* attributeName)
  55.     {
  56.         reset();
  57.         append(className);
  58.         append(attributeName);
  59.     }
  60.  
  61.     IasQueryBuffer& IasQueryBuffer::append(const char* piece)
  62.     {
  63.         assert(piece != NULL);
  64.         assert(_size+StrLen(piece)+1 <= IR_MAX_QUERY_LEN);
  65.  
  66.         _buffer[_size++] = StrLen(piece);
  67.         MemMove(_buffer+_size, piece, StrLen(piece));
  68.         _size += StrLen(piece);
  69.  
  70.         return *this;
  71.     }
  72.  
  73.     // attributes
  74.  
  75.     char* IasQueryBuffer::toString(char* dest) const
  76.     {
  77.         assert(_buffer != NULL);
  78.  
  79.         char* str = dest;
  80.  
  81.         for (int pos = 0, len = 0; pos < _size; pos += _buffer[pos]+1)
  82.         {
  83.             if (pos > 0)
  84.                 *str++ = ',';
  85.  
  86.             MemMove(str, _buffer+pos+1, _buffer[pos]);
  87.             str += _buffer[pos];
  88.         }
  89.         *str = 0;
  90.  
  91.         return dest;
  92.     }
  93.  
  94.  
  95.     //==============================================================================
  96.     // IasAttributeName class
  97.     //==============================================================================
  98.  
  99.     IasAttributeName::IasAttributeName()
  100.     {
  101.         _name[0] = 0;
  102.     }
  103.  
  104.     IasAttributeName::IasAttributeName(const char* protocol, const char* attribute)
  105.     {
  106.         _name[0] = 0;
  107.  
  108.         append(IRDA_NAME);
  109.         append(protocol);
  110.         append(attribute);
  111.     }
  112.  
  113.     IasAttributeName::IasAttributeName(const IasAttributeName& other)
  114.     {
  115.         StrCopy(_name, other._name);
  116.     }
  117.  
  118.     IasAttributeName& IasAttributeName::operator =(const IasAttributeName& other)
  119.     {
  120.         StrCopy(_name, other._name);
  121.         return *this;
  122.     }
  123.  
  124.     // operation
  125.  
  126.     IasAttributeName& IasAttributeName::append(const char* piece)
  127.     {
  128.         assert(piece != NULL);
  129.         assert(StrLen(_name)+StrLen(piece) <= IR_MAX_IAS_NAME);
  130.  
  131.         int len = StrLen(_name);
  132.         if (len > 0 && _name[len-1] != ':')
  133.             StrCat(_name, ":");
  134.         StrCat(_name, piece);
  135.  
  136.         return *this;
  137.     }
  138.  
  139.  
  140.     //==============================================================================
  141.     //  IasQuery class
  142.     //==============================================================================
  143.  
  144.     const IasQuery* IasQuery::_this = NULL;
  145.  
  146.     IasQuery::IasQuery(Word refNum):
  147.         _refNum(refNum),
  148.         _resultState(ResultNotReady)
  149.     {}
  150.  
  151.     IasQuery::~IasQuery()
  152.     {}
  153.  
  154.     // operations
  155.  
  156.     bool IasQuery::getRemoteLsap(IrClassType classType, IrProtocolType protocolType, Byte& remoteLsap) const
  157.     {
  158.         if (execute(classTypeName(classType), IasAttributeName(protocolTypeName(protocolType), IR_LSAP_SEL_ATTRIBUTE)))
  159.         {
  160.             if (waitForResult(IAS_ATTRIB_INTEGER))
  161.             {
  162.                 remoteLsap = IrIAS_GetIntLsap(&_query);
  163.                 return true;
  164.             }
  165.         }
  166.  
  167.         return false;
  168.     }
  169.  
  170.     bool IasQuery::getRemoteDeviceName(char* buffer) const
  171.     {
  172.         assert(buffer != NULL);
  173.  
  174.         if (execute(IR_DEVICE_CLASS, IR_DEVICE_NAME_ATTRIBUTE))
  175.         {
  176.             if (waitForResult(IAS_ATTRIB_USER_STRING))
  177.                 return getResultUserString(buffer);
  178.         }
  179.  
  180.         return false;
  181.     }
  182.  
  183.     bool IasQuery::getRemoteInstanceName(char* buffer) const
  184.     {
  185.         assert(buffer != NULL);
  186.  
  187.         // defined only for IrCOMM class and IrLMP protocol
  188.         if (execute(classTypeName(IrCommClass), IasAttributeName(protocolTypeName(IrLmpProtocol), IR_INSTANCE_NAME_ATTRIBUTE)))
  189.         {
  190.             if (waitForResult(IAS_ATTRIB_USER_STRING))
  191.                 return getResultUserString(buffer);
  192.         }
  193.  
  194.         return false;
  195.     }
  196.  
  197.     bool IasQuery::getRemoteParameter(IasParameter& remoteParameter) const
  198.     {
  199.         // Attribute defined only for IrCOMM class.
  200.         if (execute(classTypeName(IrCommClass), IR_PARAMETERS_ATTRIBUTE))
  201.         {
  202.             if (waitForResult(IAS_ATTRIB_OCTET_STRING))
  203.             {
  204.                 IasParameterList parameters(IrIAS_GetOctetString(&_query), IrIAS_GetOctetStringLen(&_query));
  205.                 return parameters.getParameter(remoteParameter);
  206.             }
  207.         }
  208.  
  209.         return false;
  210.     }
  211.  
  212.     // utilities
  213.  
  214.     const char* IasQuery::classTypeName(IrClassType classType)
  215.     {
  216.         static const char* classes[] = { "Unknown", "IrDA:IrCOMM", "IrLPT" };
  217.  
  218.         return classes[classType];
  219.     }
  220.  
  221.     const char* IasQuery::protocolTypeName(IrProtocolType protocolType)
  222.     {
  223.         static const char* protocols[] = { "Unknown", "IrLMP", "TinyTP" };
  224.  
  225.         return protocols[protocolType];
  226.     }
  227.  
  228.     // implementation
  229.  
  230.     bool IasQuery::execute(const char* className, const char* attributeName) const
  231.     {
  232.         _queryBuffer.init(className, attributeName);
  233.  
  234.         _query.queryBuf = const_cast<Byte*>(_queryBuffer.data());
  235.         _query.queryLen = _queryBuffer.size();
  236.         _query.resultBufSize = sizeof(_resultBuffer);
  237.         _query.result = _resultBuffer;
  238.         _query.callBack = queryCallback;
  239.  
  240.         _this = this;
  241.         _resultState = ResultNotReady;
  242.  
  243.         IrStatus rc = IrIAS_Query(_refNum, &_query);
  244.         if (rc != IR_STATUS_PENDING)
  245.         {
  246.             char text[IR_MAX_QUERY_LEN];
  247.             IrError::iasQueryError(_queryBuffer.toString(text), rc);
  248.  
  249.             _resultState = ErrorResult;
  250.             return false;
  251.         }
  252.  
  253.         return true;
  254.     }
  255.  
  256.     bool IasQuery::waitForResult(int expectedResultType) const
  257.     {
  258.         int count = QUERY_TIME_OUT*SysTicksPerSecond()/QUERY_POLLING_PERIOD;
  259.         for (int i = 0; i < count && _resultState == ResultNotReady; ++i)
  260.             Util::YieldControlToSystem(QUERY_POLLING_PERIOD, false);
  261.  
  262.         if (_resultState == ResultReady)
  263.             return checkResultType(expectedResultType);
  264.  
  265.         return false;
  266.     }
  267.  
  268.     bool IasQuery::checkResultType(int resultType) const
  269.     {
  270.         IrIAS_StartResult(&_query);     // must be called before reading the result, IrLIB "forgot" to initialize offset
  271.  
  272.         if (IrIAS_GetType(&_query) != resultType)
  273.         {
  274.             char text[IR_MAX_QUERY_LEN];
  275.             IrError::unexpectedIasQueryError(_queryBuffer.toString(text), IrIAS_GetType(&_query));
  276.             return false;
  277.         }
  278.  
  279.         return true;
  280.     }
  281.  
  282.     bool IasQuery::getResultUserString(char* buffer) const
  283.     {
  284.         int len = IrIAS_GetUserStringLen(&_query);
  285.         void* data = IrIAS_GetUserString(&_query);
  286.  
  287.         if (data != NULL)
  288.         {
  289.             MemMove(buffer, data, len);
  290.             buffer[len] = 0;
  291.  
  292.             return true;
  293.         }
  294.  
  295.         return false;
  296.     }
  297.  
  298.     // callback
  299.  
  300.     void IasQuery::queryCallback(IrStatus status)
  301.     {
  302.         if (status != IR_STATUS_SUCCESS)
  303.         {
  304.             IrError::iasCallbackError(status);
  305.  
  306.             _this->_resultState = ErrorResult;
  307.             return;
  308.         }
  309.  
  310.         if (_this->_query.retCode != IAS_RET_SUCCESS)
  311.         {
  312.             _this->_resultState = ErrorResult;
  313.             return;
  314.         }
  315.  
  316.         _this->_resultState = ResultReady;
  317.     }
  318. }
  319. // namespace IrDA
  320.