August 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Object Exchange (OBEX) Protocol Primer

  • December 27, 2005
  • By Alex Gusev
  • Send Email »
  • More Articles »

What OBEX Stands For

According to its name, OBEX stands for OBject EXchange. It allows the devices to exchange standard objects such as files, business cards, and calendar infos. This is a vendor-independent protocol implemented on different OSes, such as Palm OS and Windows CE. The actual OBEX support on a particular mobile device depends on system configuration; in other words, vendors can decide what to put there, but at least the OBEX Push protocol is usually presented because it is supported by an Inbox application.

If you turn to the Windows Mobile area, you now can choose between IrDA and Bluetooth as underlying transports. OBEX does all the transport-specific work for you, so there is no need to worry about such things like BT devices being discovered and so forth. In addition, there are a number of COM interfaces to control OBEX as well as to perform device enumeration:

  • IObex
  • IObex2
  • IObexDevice
  • IHeaderCollection
  • IObexSink
  • IObexService
  • IObexServiceConnection
  • IInboxSink
  • IHeaderEnum
  • IPropertyBagEnum
  • IDeviceEnum
  • IObexCaps

I won't disscuss all of them, but I will cover IObexService, IObexServiceConnection, and IInboxSink; they are used in the article's sample project. Moreover, in many cases you will need Object Push rather than Object Pull, so you will cover only sending data process, leaving it up to the OS to implement receiving operations (or GET in terms of OBEX). You also can implement GET operation at low level—for example, with WinSock—according to OBEX protocol description.

Initialization

Your entry point to OBEX is the IObex and IObex2 interfaces. A common workflow, therefore, will be as follows:

  • Initialize OBEX
  • Find a connection point and command OBEX to send notifications on the remote device's arrival or departure
  • Enumerate devices
  • Handle OBEX events
  • Perform all required transfers
  • Shut down OBEX

The very first step is to make an initialization. You will assume that IObex2 is supported in your system:

int CObex::InitObex(HWND hWnd)
{
   HRESULT hr;
   CString sInfo;
   CComPtr<IObex> pObex;
   m_hWnd = hWnd;
   hr = pObex.CoCreateInstance(__uuidof(Obex),NULL,
                               CLSCTX_INPROC_SERVER);
   if(FAILED(hr))
   {
      sInfo.Format(_T("Failed to initialize Obex interface:
                   hr = 0x%X, err =  0x%Xn"),
                   hr, GetLastError());
      ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
      return 0;
   }
   hr = pObex->QueryInterface(__uuidof(IObex2),(void**)&m_pObex);
   if(FAILED(hr))
   {
      sInfo.Format(_T("Failed to initialize Obex interface:
                   hr = 0x%X, err =  0x%Xn"),
                   hr, GetLastError());
      ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
      return 0;
   }
   pObex.Release();
   if (!m_pObex)
      return 0;
   m_pObex->Initialize();
   IObexCaps *pObexCaps = NULL;
   hr = m_pObex->QueryInterface(IID_IObexCaps,
                                (LPVOID *)&pObexCaps);
   if(SUCCEEDED(hr))
   {
      pObexCaps->SetCaps(SEND_DEVICE_UPDATES);
      pObexCaps->Release();
   }
   CCriticalSection csLock;
   csLock.Lock(INFINITE);
   IObexSinkImpl *pSink = new IObexSinkImpl(hWnd);
   if (!pSink)
   {
      csLock.Unlock();
      return 0;
   }
   hr = m_pObex->QueryInterface(IID_IConnectionPointContainer,
                                (LPVOID *)&m_pContainer);
   if (!SUCCEEDED(hr) || (m_pContainer == 0))
   {
      csLock.Unlock();
      return 0;
   }
   hr = m_pContainer->FindConnectionPoint(IID_IObexSink,
                                          &m_pConPoint);
   if (!SUCCEEDED(hr) || (m_pConPoint == 0))
   {
      m_pContainer.Release();
      csLock.Unlock();
      return 0;
   }
   hr = m_pConPoint->Advise((IUnknown *)pSink, &m_dwCookie);
   csLock.Unlock();
   if (ERROR_SUCCESS != m_pObex->StartDeviceEnum())
      return 0;
   if(!SUCCEEDED(hr) || (pDeviceEnum == 0))
      return 0;
   return 1;
}

This code snippet illustrates the entire process: Create all required interfaces, look for connection point, and advise for sink object. Please note that, to receive callback notifications, you have to implement a simple COM-like class. In this sample, it is IObexSinkImpl. All it actually does is to implement the Notify method to pass events to the main application. After all objects are ready, you can start a device lookup. You can collect all devices in range either with a Notify callback or directly by a

CComPtr<IDeviceEnum> pDeviceEnum;
hr = m_pObex->EnumDevices(&pDeviceEnum, GUID_NULL);

call. This function returns the IDeviceEnum interface, which allows you to surf through device enumeration. The last parameter defines a device type to request. You want all devices in range, so sending CLSID_NULL will do. If you want a specific device class, you can do it by sending the appropriate parameter here. The following table lists possible values:

Value Description
CLSID_BthTransport A device that uses Bluetooth to communicate with other devices
CLSID_HeaderCollection The header collection of a device
CLSID_IpTransport A device that uses TCP/IP to communicate with other devices
CLSID_IrdaTransport A device that uses IRdA to communicate with other devices
CLSID_Obex An OBEX-class device
CLSID_PropertyBag The property bag of a device




Page 1 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel