LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   searching for bluetooth services using bluez sdp (http://www.linuxquestions.org/questions/programming-9/searching-for-bluetooth-services-using-bluez-sdp-539873/)

Josephus Ross 03-23-2007 05:50 AM

searching for bluetooth services using bluez sdp
 
hi there

I am trying to search my mobile phone for bluetooth services. I have copied some code from

http://people.csail.mit.edu/albert/b...ntro/x601.html

and have changed the mac address to my phones mac address and the 0xABCD to 0x1105 which seems to be the obexpush code in bluez (I'm not sure if I need to change this number). The problem is that although the phone shows some bluetooth activity when I initiate the code I get no output showing me the obex push service so that I can get the 'channel/port' which is all I want.

I am using slackware 2.6.18 by the way

Here is the script I am using

#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

int main(int argc, char **argv)
{
uint32_t svc_uuid_int[] = { 0x0, 0x0, 0x0, 0x1105 };
uuid_t svc_uuid;
int err;
bdaddr_t target;
sdp_list_t *response_list = NULL, *search_list, *attrid_list;
sdp_session_t *session = 0;

str2ba( "xx:xx:xx:xx:xx:xx", &target );

// connect to the SDP server running on the remote machine
session = sdp_connect( BDADDR_ANY, &target, SDP_RETRY_IF_BUSY );

// specify the UUID of the application we're searching for
sdp_uuid128_create( &svc_uuid, &svc_uuid_int );
search_list = sdp_list_append( NULL, &svc_uuid );

// specify that we want a list of all the matching applications' attributes
uint32_t range = 0x0000ffff;
attrid_list = sdp_list_append( NULL, &range );

// get a list of service records that have UUID 0xabcd
err = sdp_service_search_attr_req( session, search_list, \
SDP_ATTR_REQ_RANGE, attrid_list, &response_list);


sdp_list_t *r = response_list;

// go through each of the service records
for (; r; r = r->next ) {
sdp_record_t *rec = (sdp_record_t*) r->data;
sdp_list_t *proto_list;

// get a list of the protocol sequences
if( sdp_get_access_protos( rec, &proto_list ) == 0 ) {
sdp_list_t *p = proto_list;

// go through each protocol sequence
for( ; p ; p = p->next ) {
sdp_list_t *pds = (sdp_list_t*)p->data;

// go through each protocol list of the protocol sequence
for( ; pds ; pds = pds->next ) {

// check the protocol attributes
sdp_data_t *d = (sdp_data_t*)pds->data;
int proto = 0;
for( ; d; d = d->next ) {
switch( d->dtd ) {
case SDP_UUID16:
case SDP_UUID32:
case SDP_UUID128:
proto = sdp_uuid_to_proto( &d->val.uuid );
break;
case SDP_UINT8:
if( proto == RFCOMM_UUID ) {
printf("rfcomm channel: %d\n",d->val.int8);
}
break;
}
}
}
sdp_list_free( (sdp_list_t*)p->data, 0 );
}
sdp_list_free( proto_list, 0 );

}

printf("found service record 0x%x\n", rec->handle);
sdp_record_free( rec );
}

sdp_close(session);
}

I am quite a novice at doing this in C as I am used to using bash/shell script and using sdptool. However I am trying to learn C and am using this as a project.

Thanks in advance

Joe

Mara 03-25-2007 09:09 AM

It's hard to debug that way. The easiest way would be to add printfs showing results of all the functions you run. Then you can check if you have an error somewhere.

slzckboy 03-28-2007 03:16 AM

what-a-nightmare !!!!!

Ok

I have got my bluetoth system running and I made sure that I can do sdp service queries to the target bluetooth device via the sdptool tool so I am happy that bluez is installed properly!?!!
i.e

Code:




Browsing 00:0E:07:A5:BC:C2 ...
Service Name: Dial-up Networking
Service RecHandle: 0x10000
Service Class ID List:
  "Dialup Networking" (0x1103)
  "Generic Networking" (0x1201)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Profile Descriptor List:
  "Dialup Networking" (0x1103)
    Version: 0x0100
....

I can connect with oebxftp and rfcomm ok.


I can write code using the bluez-libs that can connect to my bluetooth target device and return the bdaddr of that device long with its human friendly name(as per the tutorial on the link you sent)

But I am stuck on the below.
Code:


#include "blue.h"


int service_search(bdaddr_t *mac){


        int status;
        char addr[19];
        uint32_t svc_uuid_int[]={0x0,0x0,0x0,0x1103};
        sdp_record_t *record;
        sdp_session_t *session=0;
        uuid_t svc_uuid;
        uint8_t port=0;
        sdp_list_t *response_list,*search_list,*attrid_list,*r;
        sdp_list_t *proto_list;
        ba2str(mac,addr);
        printf("Target sdp server is : %s\n",addr);
        if(!(session=sdp_connect(BDADDR_ANY,mac,SDP_RETRY_IF_BUSY)))
                return -1;
        else
                puts("sdp session established\n");

        sdp_uuid128_create(&svc_uuid,&svc_uuid_int[0]);
        search_list=sdp_list_append(NULL,&svc_uuid);
        uint32_t range=0x0000ffff;
        attrid_list=sdp_list_append(NULL,&range);
        sleep(3);
/* SEARCH FOR A SPECIFIC BLUETOOTH SERVICE QUOTING THE UUID NUMBER */
        status=sdp_service_search_attr_req(session,search_list,SDP_ATTR_REQ_RANGE,attrid_list,&response_list);
        if(!(status)){
                puts("Status ok\n");
                if(response_list)
                        printf("Dialup Networking (0x1103) service found\n");
               
                else
              printf("No sdp service detils returned\n");
        }

        sdp_close(session);


}

the sdp_service_search_attr_req should return a data structure in the last parameter passed to it,in my case response_list.
But it is returning a NULL pointer.Without this structue you can interogate the records any futher.
Is this what is happening to you?
I used gdb to see what was happening...

Code:

9              status=sdp_service_search_attr_req(session,search_list,SDP_ATTR_REQ_RANGE,attrid_list,&response_list);
(gdb) p status
$1 = 0
(gdb) s
30              if(!(status)){
(gdb) s
31                      puts("Status ok\n");
(gdb) s
Status ok

32                      if(response_list)
(gdb) p response_list
$2 = (sdp_list_t *) 0x0

As you cn see the spd_list_t pointer is not being returned with any meaningful memory address.
The code above is basically the code that you found on that web page.
Question:
The UUID is that taken from the service class id list
or the service rec handle???
Code:

Service RecHandle: 0x10000
Service Class ID List:
  "Dialup Networking" (0x1103)
  "Generic Networking" (0x1201)

Anyway I have tried both and still can't get this sdp query to work
:0(
As you can see I am trying to connect to DUN(dial up networking) service.

There is sooo little documentation on this stuff...
Google dosn't return much......

slzckboy 03-28-2007 03:21 AM

i'm going to have to go through the source code of the sdptool application.
:study:

slzckboy 03-29-2007 06:01 AM

This works now.
everything is hard coded in this version (i.e the service of interest and the mac of the remote address).However I am posting this one because it is simpler.I will leave it to you to refine.
You will need to change the address of the target bluetooth device and if you want the details from another sdp service you will have to change the service class id that you wish the program to find aswell.

Code:

char serv_class_ID[]="0x1106"; /* obex push service identifier */
 char bdaddr[]="00:0E:07:A5:BC:C2";/* remote bdaddress(Pls change for yours)*/

Here is the entire source code.
Code:

#include <bluetooth/bluetooth.h>
 #include <bluetooth/sdp.h>
 #include <bluetooth/sdp_lib.h>

 int main(int argc, char **argv)
 {
 uuid_t svc_uuid;
 int err;
 bdaddr_t target;
 sdp_list_t *response_list = NULL, *search_list, *attrid_list;
 sdp_session_t *session = 0;
 uint32_t class = 0;
 int num;

/* hard code your remote bdaddr here  */
 char serv_class_ID[]="0x1106"; /* obex push service identifier */
 char bdaddr[]="00:0E:07:A5:BC:C2";/* remote bdaddress(Pls change for yours)*/

 str2ba( bdaddr, &target );

        if (!strncasecmp(serv_class_ID, "0x", 2)) {
                int num;
                /* This is a UUID16, just convert to int */
                sscanf(serv_class_ID + 2, "%X", &num);
                class = num;
                printf("Service Class 0x%X\n", class);
        }

        if (class) {
                if (class & 0xffff0000){
                        sdp_uuid32_create(&svc_uuid, class);
                        printf("Creating a 32 bit uuid\n");
                }
                else {
                        uint16_t class16 = class & 0xffff;
                        sdp_uuid16_create(&svc_uuid, class16);
                        printf("Creating a 16 bit uuid\n");
                }
        }
        else
        printf("You have no class :0)\n");



 // connect to the SDP server running on the remote machine
 session = sdp_connect( BDADDR_ANY, &target, SDP_RETRY_IF_BUSY );

 // specify the UUID of the application we're searching for


 search_list = sdp_list_append( NULL, &svc_uuid );

 // specify that we want a list of all the matching applications' attributes
 uint32_t range = 0x0000ffff;
 attrid_list = sdp_list_append( NULL, &range );

 // get a list of service records that have UUID 0xabcd
 err = sdp_service_search_attr_req( session, search_list, \
 SDP_ATTR_REQ_RANGE, attrid_list, &response_list);


 sdp_list_t *r = response_list;

 // go through each of the service records
 for (; r; r = r->next ) {
 sdp_record_t *rec = (sdp_record_t*) r->data;
 sdp_record_print(rec);
 printf("Service RecHandle: 0x%x\n", rec->handle);
 sdp_list_t *proto_list;

 // get a list of the protocol sequences
if( sdp_get_access_protos( rec, &proto_list ) == 0 ) {
 sdp_list_t *p = proto_list;

 // go through each protocol sequence
 for( ; p ; p = p->next ) {
 sdp_list_t *pds = (sdp_list_t*)p->data;

 // go through each protocol list of the protocol sequence
 for( ; pds ; pds = pds->next ) {

 // check the protocol attributes
 sdp_data_t *d = (sdp_data_t*)pds->data;
 int proto = 0;
 for( ; d; d = d->next ) {
 switch( d->dtd ) {
 case SDP_UUID16:
 case SDP_UUID32:
 case SDP_UUID128:
 proto = sdp_uuid_to_proto( &d->val.uuid );
 break;
 case SDP_UINT8:
 if( proto == RFCOMM_UUID ) {
 printf("rfcomm channel: %d\n",d->val.int8);
 }
 break;
 }
 }
 }
 sdp_list_free( (sdp_list_t*)p->data, 0 );
 }
 sdp_list_free( proto_list, 0 );

 }

 printf("found service record 0x%x\n", rec->handle);
 sdp_record_free( rec );
 }

 sdp_close(session);
 }

Output log

Code:

Service Class 0x1106
Creating a 16 bit uuid
Service Name: OBEX File Transfer
Service RecHandle: 0x1000d
rfcomm channel: 7
found service record 0x1000d


Josephus Ross 03-29-2007 11:49 AM

Thank you so much slzckboy your a total star!!!!

This works perfectly. Cheers for all your efforts :)

Aknom 05-06-2007 06:13 PM

Hello guy ... i was looking for a method to get all the services from bluetooth whit C ... and this can help me ... the question is ... there ar a way to get all the services ?? or a list of UUID of service to ask for each one ?

ivalladt 05-22-2007 04:56 AM

Nice piece of code, very useful to me, thanks!

Nonetheless this check is required:

session = sdp_connect( BDADDR_ANY, &target, SDP_RETRY_IF_BUSY );
if (session == (sdp_session_t *)NULL) {
printf("E: Device not found\n");
return -1;
}

As sdp_service_search_attr_req breaks with a segment violation if NULL is provided as session argument, i.e. when a bluetooth id of a device not in range is provided.

slzckboy 05-24-2007 01:05 PM

:)

It was just a "proof or concept" but your right of course.


aknom

between the code i modified and the code originallly linked to by the original poster
you should be able to achieve your aim,if you havn't already.

ta

Aknom 06-28-2007 04:17 PM

slzckboy.. sry but i dont tell u .. i use what u say ... thanks

Josephus Ross ... the new versions of obex have something like this to get the channel obexftp_browse_bt(mac, OBEX_PUSH_SERVICE)


All times are GMT -5. The time now is 12:31 AM.