today i spent ages hacking hccontrol to do something similar it does when
invoked as below
hccontrol remote_name_request <BD_ADDR>
somehow i couldn't succeed ;-(
what really i want is to search for devices and request their names
i have a ruby script which does the same by using hccontrol and manipulating
it console output
but am interested in C version.
pasted below is full source.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <bluetooth.h>
/*
* removes duplicate entries from result and returns the new size
* free()'s the original array, result is calloc()ed
* TODO: implement in a better way
*/
int do_uniq( const int size, struct bt_devinquiry** result)
{
struct bt_devinquiry* newResult = (struct bt_devinquiry*)calloc( size,
sizeof(struct bt_devinquiry));
struct bt_devinquiry* srcCurr = *result;
struct bt_devinquiry* dstCurr = newResult;
int count = 0;
int index = 0;
for ( ; index < size; ++index)
{
int j = 0;
int found = 0;
while ( j < count)
{
if ( bdaddr_same( &( newResult[j++].bdaddr), &(
srcCurr->bdaddr)))
{
found = 1;
break;
}
}
if ( !found)
{
*dstCurr = *srcCurr;
++dstCurr;
++count;
}
++srcCurr;
}
free(*result);
*result = newResult;
return count;
}
int main( int argc, char* argv[])
{
/* search devices */
struct bt_devinquiry* result = 0;
int num = bt_devinquiry( 0, 0, 0, &result);
if ( num <= 0)
{
if ( h_errno)
herror( "no devices found");
else
printf( "no devices found\n");
return num;
}
/* remove duplicate entries */
num = do_uniq( num, &result);
printf( "%d device(s) found\n", num);
/* try to query device's name */
int s = bt_devopen( "ubt0hci");
if ( s == -1)
{
if ( h_errno)
herror( "bt_devopen error\n");
else
printf( "bt_devopen error\n");
return -1;
}
int i = 0;
for ( ; i < num; ++i)
{
struct bt_devreq request;
memset( &request, 0, sizeof(request));
request.opcode = NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
NG_HCI_OCF_REMOTE_NAME_REQ);
request.event = NG_HCI_EVENT_REMOTE_NAME_REQ_COMPL;
ng_hci_remote_name_req_cp cp;
memset(&cp, 0, sizeof(cp));
bdaddr_copy( &cp.bdaddr, &result->bdaddr);
cp.page_scan_rep_mode = NG_HCI_SCAN_REP_MODE0;
cp.page_scan_mode = NG_HCI_MANDATORY_PAGE_SCAN_MODE;
request.cparam = (void*)&cp;
request.clen = sizeof(cp);
char buffer[512];
memset( buffer, 0, 512);
request.rparam = (void*)buffer;
request.rlen = 512;
int status = bt_devreq( s, &request, 0);
if ( status == 0)
{
ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t*)buffer;
ng_hci_remote_name_req_compl_ep *ep =
(ng_hci_remote_name_req_compl_ep*)(e + 1);
printf( "status: %d\n", ep->status);
printf( "name: %s\n", ep->name);
}
else if (status == -1)
{
if ( h_errno)
herror( "bt_devreq error\n");
else
printf( "bt_devreq error\n");
}
else
{
printf("bt_devreq unknown return value\n");
}
}
bt_devclose(s);
return 0;
}
> On Sat, 3 Oct 2009, Masoom Shaikh wrote:
>
> > Hi,
> >
> > today i spent ages hacking hccontrol to do something similar it does when
> > invoked as below
> >
> > hccontrol remote_name_request <BD_ADDR>
> >
> > somehow i couldn't succeed ;-(
>
> you didn't say exactly the failure you have reached, did you use hcidump
> to check the actions?
> what is h_errno? I think these checks are uninvolved with the code at
> hand..
>
> > herror( "no devices found");
> > else
> > printf( "no devices found\n");
> > return num;
> > }
> > /* remove duplicate entries */
> > num = do_uniq( num, &result);
> > printf( "%d device(s) found\n", num);
>
> also, I don't think the do_uniq() step should be necessary -- we did
> discuss it at least and in the version i wrote for NetBSD it doesn't
> return duplicate results
> I think your problem might be here. The event header is not returned, only
> the remote_name_req_compl_ep event packet.. (I would have used that
> directly in the rparam field rather than a separate buffer -- bt_devreq
> will not overflow the given space)
>
> > else if (status == -1)
> > {
> > if ( h_errno)
> > herror( "bt_devreq error\n");
> > else
> > printf( "bt_devreq error\n");
> > }
> > else
> > {
> > printf("bt_devreq unknown return value\n");
> > }
> > }
> > bt_devclose(s);
> > return 0;
> > }
>
> iain
>
>
> thanks for replying
yes, i did forgot to say where it failed, devices are inquired properly no
issues there
but bt_devreq() fails with status == -1
comment taken
i will remove the separate buffer, thank you again
here is the hcidump output
HCIDump - HCI packet analyzer ver 1.5
device: any snap_len: 65535 filter: 0xffffffffffffffff
< HCI Command: Inquiry(0x01|0x0001) plen 5
> HCI Event: Command Status(0x0f) plen 4
> HCI Event: Inquiry Result(0x02) plen 15
> HCI Event: Inquiry Result(0x02) plen 15
> HCI Event: Inquiry Complete(0x01) plen 1
< HCI Command: Remote Name Request(0x01|0x0019) plen 10
> HCI Event: Command Status(0x0f) plen 4
> HCI Event: Remote Name Req Complete(0x07) plen 255
i guess the last line indicates that we does receive device name but some
how bt_devreq() returns fails
i will poke around bt_devreq() for clues
> On Sun, 4 Oct 2009, Masoom Shaikh wrote:
>
> > > On Sat, 3 Oct 2009, Masoom Shaikh wrote:
> > >
> > > > int status = bt_devreq( s, &request, 0);
> >
> > yes, i did forgot to say where it failed, devices are inquired properly
> no
> > issues there
> > but bt_devreq() fails with status == -1
>
> ah, I see.. you should put a non-zero timeout value there (waiting for 0
> seconds will not leave enough time for the response :)
>
> if you use eg
>
> if (status == -1)
> err(1, "bt_devreq (RemoteNameRequest)")
>
> then you would see an "Operation timed out" message.. I should think 5
> seconds would be reasonable..
>
> regards,
> iain
>
>
> u got the bug by neck, and i would have slit its neck by the time this mail
is in your inbox ;-)
that was the exact error, timeout value of 5 didn't work for me, thus am
using 60, and it works
thanks Iain