toward improving bt support in gtk client: add scan button that only

picks up devices currently open for discovery
This commit is contained in:
Eric House 2013-12-07 10:12:20 -08:00
parent d25e20221b
commit f0c5d1f865
4 changed files with 170 additions and 48 deletions

View file

@ -22,6 +22,7 @@
#include "gtkconnsdlg.h"
#include "gtkutils.h"
#include "linuxbt.h"
typedef struct _GtkConnsState {
GtkGameGlobals* globals;
@ -32,8 +33,12 @@ typedef struct _GtkConnsState {
GtkWidget* hostName;
GtkWidget* port;
GtkWidget* bthost;
GtkWidget* smsphone;
GtkWidget* smsport;
GtkWidget* bgScanButton;
GtkWidget* notebook;
CommsConnType pageTypes[COMMS_CONN_NTYPES];
gboolean cancelled;
@ -91,9 +96,13 @@ handle_ok( GtkWidget* XP_UNUSED(widget), gpointer closure )
#endif
#ifdef XWFEATURE_BLUETOOTH
case COMMS_CONN_BT:
txt = gtk_entry_get_text( GTK_ENTRY(state->bthost) );
XP_STRNCPY( state->addr->u.bt.hostName, txt,
sizeof(state->addr->u.bt.hostName) );
break;
#endif
case COMMS_CONN_SMS:
XP_ASSERT(0);
break;
default:
XP_ASSERT( 0 ); /* keep compiler happy */
@ -107,6 +116,25 @@ handle_ok( GtkWidget* XP_UNUSED(widget), gpointer closure )
gtk_main_quit();
} /* handle_ok */
static void
handle_scan( GtkWidget* XP_UNUSED(widget), gpointer closure )
{
GtkConnsState* state = (GtkConnsState*)closure;
XP_USE(state);
LOG_FUNC();
GSList* devNames = linux_bt_scan();
if ( !devNames ) {
XP_LOGF( "%s: got nothing", __func__ );
} else {
GSList* iter;
for ( iter = devNames; !!iter; iter = iter->next ) {
gchar* name = iter->data;
XP_LOGF( "%s: got %s", __func__, name );
}
}
}
static void
handle_cancel( GtkWidget* XP_UNUSED(widget), void* closure )
{
@ -140,21 +168,27 @@ makeRelayPage( GtkConnsState* state )
gtk_box_pack_start( GTK_BOX(vbox), gtk_label_new( hint ), FALSE, TRUE, 0 );
GtkWidget* hbox = makeLabeledField( "Room", &state->invite );
gtk_entry_set_text( GTK_ENTRY(state->invite),
state->addr->u.ip_relay.invite );
if ( COMMS_CONN_RELAY == state->addr->conType ) {
gtk_entry_set_text( GTK_ENTRY(state->invite),
state->addr->u.ip_relay.invite );
}
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->invite, !state->readOnly );
hbox = makeLabeledField( "Relay address", &state->hostName );
gtk_entry_set_text( GTK_ENTRY(state->hostName),
state->addr->u.ip_relay.hostName );
if ( COMMS_CONN_RELAY == state->addr->conType ) {
gtk_entry_set_text( GTK_ENTRY(state->hostName),
state->addr->u.ip_relay.hostName );
}
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->hostName, !state->readOnly );
hbox = makeLabeledField( "Relay port", &state->port );
char buf[16];
snprintf( buf, sizeof(buf), "%d", state->addr->u.ip_relay.port );
gtk_entry_set_text( GTK_ENTRY(state->port), buf );
if ( COMMS_CONN_RELAY == state->addr->conType ) {
char buf[16];
snprintf( buf, sizeof(buf), "%d", state->addr->u.ip_relay.port );
gtk_entry_set_text( GTK_ENTRY(state->port), buf );
}
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->port, !state->readOnly );
@ -169,10 +203,42 @@ makeBTPage( GtkConnsState* state )
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
GtkWidget* hbox = makeLabeledField( "Host device", &state->bthost );
gtk_entry_set_text( GTK_ENTRY(state->bthost), state->addr->u.bt.hostName );
if ( COMMS_CONN_BT == state->addr->conType ) {
gtk_entry_set_text( GTK_ENTRY(state->bthost), state->addr->u.bt.hostName );
}
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->bthost, !state->readOnly );
state->bgScanButton = makeButton( "Scan", GTK_SIGNAL_FUNC(handle_scan),
state );
gtk_box_pack_start( GTK_BOX(vbox), state->bgScanButton, FALSE, TRUE, 0 );
gtk_widget_show( vbox );
return vbox;
} /* makeBTPage */
static GtkWidget*
makeSMSPage( GtkConnsState* state )
{
GtkWidget* vbox = gtk_vbox_new( FALSE, 0 );
GtkWidget* hbox = makeLabeledField( "Host phone", &state->smsphone );
if ( COMMS_CONN_SMS == state->addr->conType ) {
gtk_entry_set_text( GTK_ENTRY(state->smsphone), state->addr->u.sms.phone );
}
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->smsphone, !state->readOnly );
hbox = makeLabeledField( "Host port", &state->smsport );
if ( COMMS_CONN_SMS == state->addr->conType ) {
gchar port[32];
snprintf( port, sizeof(port), "%d", state->addr->u.sms.port );
gtk_entry_set_text( GTK_ENTRY(state->smsphone), port );
}
gtk_box_pack_start( GTK_BOX(vbox), hbox, FALSE, TRUE, 0 );
gtk_widget_set_sensitive( state->smsport, !state->readOnly );
gtk_widget_show( vbox );
return vbox;
@ -209,6 +275,10 @@ gtkConnsDlg( GtkGameGlobals* globals, CommsAddrRec* addr, DeviceRole role,
makeBTPage(&state),
gtk_label_new( "Bluetooth" ) );
#endif
state.pageTypes[nTypes++] = COMMS_CONN_SMS;
(void)gtk_notebook_append_page( GTK_NOTEBOOK(state.notebook),
makeSMSPage(&state),
gtk_label_new( "SMS" ) );
vbox = gtk_vbox_new( FALSE, 0 );
gtk_box_pack_start( GTK_BOX(vbox), state.notebook, FALSE, TRUE, 0 );
@ -222,7 +292,7 @@ gtkConnsDlg( GtkGameGlobals* globals, CommsAddrRec* addr, DeviceRole role,
/* buttons at the bottom */
hbox = gtk_hbox_new( FALSE, 0 );
gtk_box_pack_start( GTK_BOX(hbox),
makeButton( "Ok", GTK_SIGNAL_FUNC(handle_ok) , &state ),
makeButton( "Ok", GTK_SIGNAL_FUNC(handle_ok), &state ),
FALSE, TRUE, 0 );
if ( !readOnly ) {
gtk_box_pack_start( GTK_BOX(hbox),

View file

@ -30,6 +30,8 @@
#include <errno.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#if defined BT_USE_L2CAP
# include <bluetooth/l2cap.h>
#elif defined BT_USE_RFCOMM
@ -516,4 +518,89 @@ linux_bt_socketclosed( CommonGlobals* globals, int XP_UNUSED_DBG(sock) )
btStuff->socket = -1;
}
#define RESPMAX 20
typedef gboolean (*bt_proc)( const bdaddr_t* bdaddr, int socket, void* closure );
static void
btDevsIterate( bt_proc proc, void* closure )
{
int id, socket;
LOG_FUNC();
id = hci_get_route( NULL );
socket = hci_open_dev( id );
if ( id >= 0 && socket >= 0 ) {
long flags = IREQ_CACHE_FLUSH;
inquiry_info inqInfo[RESPMAX];
inquiry_info* inqInfoP = inqInfo;
int count = hci_inquiry( id, 8/*wait seconds*/,
RESPMAX, NULL, &inqInfoP, flags );
int ii;
for ( ii = 0; ii < count; ++ii ) {
const bdaddr_t* bdaddr = &inqInfo[ii].bdaddr;
if ( !(*proc)( bdaddr, socket, closure ) ) {
break;
}
}
}
}
typedef struct _get_ba_data {
const char* name;
bdaddr_t* ba;
gboolean success;
} get_ba_data;
static gboolean
get_ba_proc( const bdaddr_t* bdaddr, int socket, void* closure )
{
get_ba_data* data = (get_ba_data*)closure;
char buf[64];
if ( 0 >= hci_read_remote_name( socket, bdaddr, sizeof(buf), buf, 0 ) ) {
if ( 0 == strcmp( buf, data->name ) ) {
XP_MEMCPY( data->ba, bdaddr, sizeof(*data->ba) );
data->success = XP_TRUE;
XP_LOGF( "%s: matched %s", __func__, data->name );
char addrStr[32];
ba2str( data->ba, addrStr );
XP_LOGF( "bt_addr is %s", addrStr );
}
}
return !data->success;
}
XP_Bool
nameToBtAddr( const char* name, bdaddr_t* ba )
{
LOG_FUNC();
get_ba_data data = { .name = name, .ba = ba, .success = FALSE };
btDevsIterate( get_ba_proc, &data );
return data.success;
} /* nameToBtAddr */
static gboolean
append_name_proc( const bdaddr_t* bdaddr, int socket, void* closure )
{
GSList** list = (GSList**)closure;
char buf[64];
char addr[19] = { 0 };
ba2str( bdaddr, addr );
XP_LOGF( "%s: adding %s", __func__, addr );
if ( 0 >= hci_read_remote_name( socket, bdaddr, sizeof(buf), buf, 0 ) ) {
gchar* name = g_strdup( buf );
*list = g_slist_append( *list, name );
}
return TRUE;
}
GSList*
linux_bt_scan()
{
GSList* list = NULL;
btDevsIterate( append_name_proc, &list );
return list;
}
#endif /* XWFEATURE_BLUETOOTH */

View file

@ -35,5 +35,9 @@ XP_S16 linux_bt_receive( int sock, XP_U8* buf, XP_U16 buflen );
void linux_bt_socketclosed( CommonGlobals* globals, int sock );
GSList* linux_bt_scan();
XP_Bool nameToBtAddr( const char* name, bdaddr_t* ba );
#endif /* XWFEATURE_BLUETOOTH */
#endif /* #ifndef _LINUXBT_H_ */

View file

@ -1446,45 +1446,6 @@ defaultRandomSeed()
return rs;
} /* defaultRandomSeed */
/* This belongs in linuxbt.c */
#ifdef XWFEATURE_BLUETOOTH
static XP_Bool
nameToBtAddr( const char* name, bdaddr_t* ba )
{
XP_Bool success = XP_FALSE;
int id, socket;
LOG_FUNC();
# define RESPMAX 5
id = hci_get_route( NULL );
socket = hci_open_dev( id );
if ( id >= 0 && socket >= 0 ) {
long flags = 0L;
inquiry_info inqInfo[RESPMAX];
inquiry_info* inqInfoP = inqInfo;
int count = hci_inquiry( id, 10, RESPMAX, NULL, &inqInfoP, flags );
int i;
for ( i = 0; i < count; ++i ) {
char buf[64];
if ( 0 >= hci_read_remote_name( socket, &inqInfo[i].bdaddr,
sizeof(buf), buf, 0)) {
if ( 0 == strcmp( buf, name ) ) {
XP_MEMCPY( ba, &inqInfo[i].bdaddr, sizeof(*ba) );
success = XP_TRUE;
XP_LOGF( "%s: matched %s", __func__, name );
char addrStr[32];
ba2str(ba, addrStr);
XP_LOGF( "bt_addr is %s", addrStr );
break;
}
}
}
}
return success;
} /* nameToBtAddr */
#endif
#ifdef XWFEATURE_SLOW_ROBOT
static bool
parsePair( const char* optarg, XP_U16* min, XP_U16* max )