Tuesday, November 3, 2009

Bluetooth Device Discovery in c language HOW TO

Today i wanna show a simple how to about bluetooth programming.
I will start witha brief theory follow by a full commented c source compile under linux.

This two functions convert a string address in a bdaddr_t (a defined structure which is a bluetooth device address) and viceversa
str2ba (const char * str , bdaddr_t * ba)
ba2str (const bdaddr_t * ba , char * str)
We also need to know about local bluetooth adapter, this functions will be useful:
int hci_get_route (bdaddr_t * addr)
Return the device id of the given bdaddr_t, you can pass NULL so it returns the first available device.
If you know the device's address you want to use you can pass it to this function
int hci_devid (const char * addr)
finally you can open resources to use the device you choose with
int hci_open_dev (int adapter_id)
Now you need to send an inquiry signal to receive information about the devices to respond.
You can do this by calling
int hci_inquiry (int adapter_id, int len, int max_rsp,
 const uint8_t * lap , inquiry_info ** devs , long flags
)
  • adapter_id = the adapter you choose before
  • len = inquiry time, the standard is about 8 * 1.24 (so len = 8)
  • max_rsp = maximum devices response (usually 255)
  • flags = usually IREQ CACHE FLUSH, if you pass 0 then previous inquiry info may be returned
  • lap = determine the type of inquiry, if you don't care give it NULL.
Be careful: devs parameter should be sized enough to store a max of max_rsp inquiry_info struct...
Sounds like:
(inquiry_info *)malloc (max_rsp * sizeof (inquiry_info));
And finally you can get devices friendly name, follow this how-to
  1. cycle hci_inquiry return step to check for the devices found
  2. look for bdaddr_t field in the devices list stored by hci_inquiry, converted by ba2str
  3. store enough memory to convert string address to string name
  4. get the name with:
    int hci_read_remote_name (int hci_sock, const bdaddr_t * addr,
     int len, char * name, int timeout)

And here the code:
/**
 * bdd_main.c
 *
 * This is a sample about how to discovery bluetooth device
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

int main (int argc, char ** argv)
{
 inquiry_info * devices = NULL; // This struct will store the found devices
 int max_rsp, num_rsp; // max devices to find, devices found
 int adapter_id, sock, len, flags; // use to hci_inquiry and hci_open_dev, returned by hci_open_dev, 1.24 * len sec inquiry time, flags chache or flush
 int i;
 char addr[19] = { 0 }; // this is a middle to find out friendly name
 char name[248] = { 0 }; // this is to store friendly name

 /* OPEN A LOCAL BLUETOOTH ADAPTER */
 adapter_id = hci_get_route(NULL);
 sock = hci_open_dev(adapter_id);
 if(adapter_id < 0 || sock < 0)
 {
  fprintf(stderr, "Error code %d: %s\n", errno, strerror(errno));
  exit(1);
 }

 /* INQURY PROCESS */
 len = 8; // 10.24 sec lasts
 max_rsp = 255; // max of 255 devices to discover
 flags = IREQ_CACHE_FLUSH; // no use previous inquiry data
 devices = (inquiry_info *)malloc(max_rsp * sizeof(inquiry_info)); // malloc for devices

 num_rsp = hci_inquiry(adapter_id, len, max_rsp, NULL, &devices, flags); // inquiry
 if(num_rsp < 0)
 {
  fprintf(stderr, "Error code %d: %s\n", errno, strerror(errno));
  exit(1);
 }

 /* FRIENDLY NAME */
 for(i = 0; i < num_rsp; i++)
 {
  ba2str(&(devices+i)->bdaddr, addr); // convert bdaddr to a string
  memset(name, 0, sizeof(name)); // memset to store friendly name
  if(0 != hci_read_remote_name(sock, &(devices+i)->bdaddr, sizeof(name), name, 0)) // store in name the first sizeof(name) byte of the friendly name of the given addr.
  {
   // this mean the friendly name was not found
   strcpy(name, "[unknow]");
  }

  printf("%s %s\n", addr, name);
 }

 /* ENDING ROUTINES */
 free(devices);
 close(sock);

 return 0;
}

Do not forget to compile linking bluetooth lib XP...