Put up BT device browser while user is picking connection method

rather than when trying to send for first time, then pass address
through from conns dialog to bt code.
This commit is contained in:
ehouse 2006-08-26 21:12:10 +00:00
parent 406d746fbf
commit 74c6b241d7
12 changed files with 457 additions and 187 deletions

View file

@ -132,6 +132,9 @@ static XP_Bool send_via_relay( CommsCtxt* comms, XWRELAY_Cmd cmd,
XWHostID destID, void* data, int dlen );
static XWHostID getDestID( CommsCtxt* comms, XP_PlayerAddr channelNo );
static void setHeartbeatTimer( CommsCtxt* comms );
# ifdef XWFEATURE_BLUETOOTH
static void btConnect( CommsCtxt* comms );
# endif
#endif
/****************************************************************************
@ -354,6 +357,10 @@ comms_start( CommsCtxt* comms )
if ( comms->addr.conType == COMMS_CONN_RELAY ) {
comms->relayState = COMMS_RELAYSTATE_UNCONNECTED;
relayConnect( comms );
#ifdef XWFEATURE_BLUETOOTH
} else if ( comms->addr.conType == COMMS_CONN_BT ) {
btConnect( comms );
#endif
}
#endif
}
@ -476,14 +483,17 @@ void
comms_getInitialAddr( CommsAddrRec* addr )
{
/* default values; default is still IR where there's a choice */
addr->conType = COMMS_CONN_RELAY;
addr->u.ip_relay.ipAddr = 0L; /* force 'em to set it */
addr->u.ip_relay.port = 10999;
{
char* name = "eehouse.org";
XP_MEMCPY( addr->u.ip_relay.hostName, name, XP_STRLEN(name)+1 );
}
addr->u.ip_relay.cookie[0] = '\0';
#ifdef XWFEATURE_BLUETOOTH
addr->conType = COMMS_CONN_BT; /* for temporary ease in debugging */
#else
addr->u.ip_relay.ipAddr = 0L; /* force 'em to set it */
addr->u.ip_relay.port = 10999;
{
char* name = "eehouse.org";
XP_MEMCPY( addr->u.ip_relay.hostName, name, XP_STRLEN(name)+1 );
}
addr->u.ip_relay.cookie[0] = '\0';
#endif
} /* comms_getInitialAddr */
#endif
@ -812,10 +822,12 @@ comms_checkIncomingStream( CommsCtxt* comms, XWStreamCtxt* stream,
XP_ASSERT( addr == NULL || comms->addr.conType == addr->conType );
#ifdef BEYOND_IR
/* relayPreProcess returns true if consumes the message. May just eat the
header and leave a regular message to be processed below. */
if ( relayPreProcess( comms, stream, &senderID ) ) {
return XP_FALSE;
}
usingRelay = XP_TRUE;
usingRelay = comms->addr.conType == COMMS_CONN_RELAY;
#endif
connID = stream_getU32( stream );
@ -977,6 +989,7 @@ rememberChannelAddress( CommsCtxt* comms, XP_PlayerAddr channelNo,
XP_ASSERT( recs->hostID == hostID );
} else {
XP_MEMSET( &recs->addr, 0, sizeof(recs->addr) );
recs->addr.conType = comms->addr.conType;
}
}
return recs;
@ -1145,6 +1158,17 @@ relayConnect( CommsCtxt* comms )
}
} /* relayConnect */
#ifdef XWFEATURE_BLUETOOTH
static void
btConnect( CommsCtxt* comms )
{
/* Ping the bt layer so it'll get sockets set up. PENDING: if I'm server
need to do this once per guest record with non-null address. */
(void)(*comms->sendproc)( (const void*)comms, /* any valid ptr will do */
0, NULL, comms->sendClosure );
} /* btConnect */
#endif
static void
relayDisconnect( CommsCtxt* comms )
{
@ -1153,7 +1177,8 @@ relayDisconnect( CommsCtxt* comms )
if ( comms->addr.conType == COMMS_CONN_RELAY ) {
if ( comms->relayState != COMMS_RELAYSTATE_UNCONNECTED ) {
comms->relayState = COMMS_RELAYSTATE_UNCONNECTED;
send_via_relay( comms, XWRELAY_GAME_DISCONNECT, HOST_ID_NONE, NULL, 0 );
send_via_relay( comms, XWRELAY_GAME_DISCONNECT, HOST_ID_NONE,
NULL, 0 );
}
}
#endif

View file

@ -42,6 +42,10 @@ typedef enum {
LAST_____FOO
} CommsConnType;
/* on Palm BtLibDeviceAddressType is a 48-bit quantity. Linux's typeis the
same size. Goal is something all platforms support */
typedef XP_U8 XP_BtAddr[6];
#define MAX_HOSTNAME_LEN 63
typedef struct CommsAddrRec {
CommsConnType conType;
@ -63,8 +67,9 @@ typedef struct CommsAddrRec {
XP_UCHAR foo; /* wince doesn't like nothing here */
} ir;
struct {
/* nothing? */
XP_UCHAR foo; /* wince doesn't like nothing here */
/* guests can browse for the host to connect to */
XP_UCHAR hostName[MAX_HOSTNAME_LEN + 1];
XP_BtAddr btAddr;
} bt;
} u;
} CommsAddrRec;

View file

@ -100,6 +100,11 @@ typedef struct CommonPrefs {
XP_Bool reserved2;
} CommonPrefs;
#ifdef XWFEATURE_BLUETOOTH
/* temporary debugging hack */
# define XW_PSM 0x3131
#endif
/* used for all vtables */
#define SET_VTABLE_ENTRY( vt, name, prefix ) \
(vt)->m_##name = prefix##_##name

View file

@ -171,7 +171,8 @@ mem_stream_getBits( XWStreamCtxt* p_sctx, XP_U16 nBits )
} /* stream_getBits */
static void
mem_stream_putBytes( XWStreamCtxt* p_sctx, void* whence, XP_U16 count )
mem_stream_putBytes( XWStreamCtxt* p_sctx, const void* whence,
XP_U16 count )
{
MemStreamCtxt* stream = (MemStreamCtxt*)p_sctx;
XP_U32 newSize;

View file

@ -115,8 +115,11 @@ MYDEFS_COMMON += -DXWFEATURE_SEARCHLIMIT
# experimental at this point!
# MYDEFS_COMMON += -DBEYOND_IR
# turn on bluetooth comms option -- off by default until ready
# MYDEFS_COMMON += -DXWFEATURE_PALM_BLUETOOTH
# turn on bluetooth comms option for 68K and ARM -- which won't work yet
# MYDEFS_COMMON += -DXWFEATURE_BLUETOOTH
# Add menu allowing to choose to run 68K or ARM
# MYDEFS_COMMON += -DFEATURE_DUALCHOOSE
# For Danish and perhaps other languages, custom-measure glyph height
# so that overtall letters have a chance of fitting.
@ -138,7 +141,10 @@ MYDEFS_COMMON += -DIR_SUPPORT -DIR_EXCHMGR
endif
MYDEFS_ARM = -D__LITTLE_ENDIAN -DXW_TARGET_PNO $(MYDEFS_COMMON)
MYDEFS_68K = -DPLATFORM_PALM -D__BIG_ENDIAN $(MYDEFS_COMMON) -DAPPNAME=\"$(APPNAME)\"
MYDEFS_68K = -DPLATFORM_PALM -D__BIG_ENDIAN $(MYDEFS_COMMON) \
-DAPPNAME=\"$(APPNAME)\" \
# -DXWFEATURE_BLUETOOTH
BITMAP_RSRCS = \
$(BITMAPS)/rightarrow.pbitm \

View file

@ -24,9 +24,11 @@
#include "callback.h"
#include "connsdlg.h"
#include "strutils.h"
#include "palmmain.h"
#include "palmutil.h"
#include "palmir.h"
#include "palmbt.h"
/* When user pops up via Host gadget, we want to get the port to listen on.
* When pops up via the Guest gadget, we want to get the port and IP address
@ -40,6 +42,7 @@ typedef struct ConnsDlgState {
XP_U16 serverRole;
XP_Bool isNewGame;
CommsAddrRec* addr;
XP_BtAddr btAddr; /* since there's no field, save it here */
} ConnsDlgState;
static void
@ -56,38 +59,58 @@ strFromField( XP_U16 id, XP_UCHAR* buf, XP_U16 max )
} /* strFromField */
static void
ctlsFromState( PalmAppGlobals* globals, FormPtr form, ConnsDlgState* state )
ctlsFromState( ConnsDlgState* state )
{
XP_Bool isNewGame = state->isNewGame;
XP_UCHAR buf[16];
CommsAddrRec* addr = state->addr;
setFieldStr( XW_CONNS_RELAY_FIELD_ID, addr->u.ip_relay.hostName );
setFieldEditable( XW_CONNS_RELAY_FIELD_ID, isNewGame );
if ( addr->conType == COMMS_CONN_RELAY ) {
setFieldStr( XW_CONNS_RELAY_FIELD_ID, addr->u.ip_relay.hostName );
setFieldEditable( XW_CONNS_RELAY_FIELD_ID, isNewGame );
StrPrintF( buf, "%d", addr->u.ip_relay.port );
setFieldStr( XW_CONNS_PORT_FIELD_ID, buf );
setFieldEditable( XW_CONNS_PORT_FIELD_ID, isNewGame );
StrPrintF( buf, "%d", addr->u.ip_relay.port );
setFieldStr( XW_CONNS_PORT_FIELD_ID, buf );
setFieldEditable( XW_CONNS_PORT_FIELD_ID, isNewGame );
setFieldStr( XW_CONNS_COOKIE_FIELD_ID, addr->u.ip_relay.cookie );
setFieldEditable( XW_CONNS_COOKIE_FIELD_ID, isNewGame );
setFieldStr( XW_CONNS_COOKIE_FIELD_ID, addr->u.ip_relay.cookie );
setFieldEditable( XW_CONNS_COOKIE_FIELD_ID, isNewGame );
#ifdef XWFEATURE_BLUETOOTH
} else if ( addr->conType == COMMS_CONN_BT
&& state->serverRole == SERVER_ISCLIENT ) {
setFieldStr( XW_CONNS_BT_HOSTFIELD_ID, addr->u.bt.hostName );
#endif
}
} /* ctlsFromState */
static XP_Bool
stateFromCtls( PalmAppGlobals* globals, ConnsDlgState* state )
stateFromCtls( ConnsDlgState* state )
{
XP_Bool ok = XP_TRUE;
XP_UCHAR buf[16];
CommsAddrRec* addr = state->addr;
strFromField( XW_CONNS_RELAY_FIELD_ID, addr->u.ip_relay.hostName,
sizeof(addr->u.ip_relay.hostName) );
if ( addr->conType == COMMS_CONN_RELAY ) {
strFromField( XW_CONNS_RELAY_FIELD_ID, addr->u.ip_relay.hostName,
sizeof(addr->u.ip_relay.hostName) );
strFromField( XW_CONNS_PORT_FIELD_ID, buf, sizeof(buf) );
addr->u.ip_relay.port = StrAToI( buf );
strFromField( XW_CONNS_PORT_FIELD_ID, buf, sizeof(buf) );
addr->u.ip_relay.port = StrAToI( buf );
strFromField( XW_CONNS_COOKIE_FIELD_ID, addr->u.ip_relay.cookie,
sizeof(addr->u.ip_relay.cookie) );
#ifdef XWFEATURE_BLUETOOTH
} else if ( addr->conType == COMMS_CONN_BT
&& state->serverRole == SERVER_ISCLIENT ) {
strFromField( XW_CONNS_BT_HOSTFIELD_ID, addr->u.bt.hostName,
sizeof(addr->u.bt.hostName) );
/* Not exactly from a control... */
XP_MEMCPY( &addr->u.bt.btAddr, state->btAddr,
sizeof(addr->u.bt.btAddr) );
LOG_HEX( addr->u.bt.btAddr, sizeof(addr->u.bt.btAddr), __FUNCTION__ );
#endif
}
strFromField( XW_CONNS_COOKIE_FIELD_ID, addr->u.ip_relay.cookie,
sizeof(addr->u.ip_relay.cookie) );
return ok;
} /* stateFromCtls */
@ -103,9 +126,41 @@ updateFormCtls( FormPtr form, ConnsDlgState* state )
XW_CONNS_COOKIE_FIELD_ID,
0
};
disOrEnableSet( form, relayCtls,
state->addr->conType == COMMS_CONN_RELAY );
const XP_U16 btGuestCtls[] = {
#ifdef XWFEATURE_BLUETOOTH
XW_CONNS_BT_HOSTNAME_LABEL_ID,
XW_CONNS_BT_HOSTFIELD_ID,
XW_CONNS_BT_BROWSEBUTTON_ID,
#endif
0
};
const XP_U16* allCtls[] = {
relayCtls, btGuestCtls
};
const XP_U16* on;
XP_U16 i;
if ( state->addr->conType == COMMS_CONN_RELAY ) {
on = relayCtls;
#ifdef XWFEATURE_BLUETOOTH
} else if ( state->addr->conType == COMMS_CONN_BT
&& state->serverRole == SERVER_ISCLIENT ) {
on = btGuestCtls;
#endif
} else {
on = NULL;
}
for ( i = 0; i < sizeof(allCtls)/sizeof(allCtls[0]); ++i ) {
const XP_U16* cur = allCtls[i];
if ( cur != on ) {
disOrEnableSet( form, cur, XP_FALSE );
}
}
if ( on != NULL ) {
disOrEnableSet( form, on, XP_TRUE );
}
} /* updateFormCtls */
static void
@ -119,14 +174,14 @@ cleanupExit( PalmAppGlobals* globals )
static XP_U16
conTypeToSel( CommsConnType conType )
{
XP_U16 result;
XP_U16 result = 0;
switch ( conType ) {
#ifdef XWFEATURE_PALM_BLUETOOTH
case COMMS_CONN_BT: result = 0; break;
#ifdef XWFEATURE_BLUETOOTH
case COMMS_CONN_BT: /* result = 0; */break;
case COMMS_CONN_IR: result = 1; break;
case COMMS_CONN_RELAY: result = 2; break;
#else
case COMMS_CONN_IR: result = 0; break;
case COMMS_CONN_IR: /* result = 0; */break;
case COMMS_CONN_RELAY: result = 1; break;
#endif
default:
@ -140,7 +195,7 @@ selToConType( XP_U16 sel )
{
CommsConnType conType;
switch( sel ) {
#ifdef XWFEATURE_PALM_BLUETOOTH
#ifdef XWFEATURE_BLUETOOTH
case 0: conType = COMMS_CONN_BT; break;
case 1: conType = COMMS_CONN_IR; break;
case 2: conType = COMMS_CONN_RELAY; break;
@ -153,6 +208,20 @@ selToConType( XP_U16 sel )
return conType;
}
#ifdef XWFEATURE_BLUETOOTH
static void
browseForDeviceName( PalmAppGlobals* globals, ConnsDlgState* state )
{
char buf[32];
XP_BtAddr btAddr;
if ( palm_bt_browse_device( globals, &btAddr, buf, sizeof( buf ) ) ) {
setFieldStr( XW_CONNS_BT_HOSTFIELD_ID, buf );
XP_MEMCPY( state->btAddr, &btAddr, sizeof(state->btAddr) );
LOG_HEX( state->btAddr, sizeof(state->btAddr), __FUNCTION__ );
}
} /* browseForDeviceName */
#endif
Boolean
ConnsFormHandleEvent( EventPtr event )
{
@ -176,12 +245,13 @@ ConnsFormHandleEvent( EventPtr event )
switch ( event->eType ) {
case frmOpenEvent:
state->serverRole =
(Connectedness)globals->dlgParams[CONNS_PARAM_ROLE_INDEX];
state->addr =
(CommsAddrRec*)globals->dlgParams[CONNS_PARAM_ADDR_INDEX];
state->isNewGame = globals->isNewGame;
XP_MEMCPY( state->btAddr, &state->addr->u.bt.btAddr,
sizeof(state->btAddr) );
/* setup connection popup */
state->connTypesList = getActiveObjectPtr( XW_CONNS_TYPE_LIST_ID );
@ -191,7 +261,7 @@ ConnsFormHandleEvent( EventPtr event )
setSelectorFromList( XW_CONNS_TYPE_TRIGGER_ID, state->connTypesList,
conTypeToSel(state->addr->conType) );
ctlsFromState( globals, form, state );
ctlsFromState( state );
updateFormCtls( form, state );
@ -204,6 +274,12 @@ ConnsFormHandleEvent( EventPtr event )
result = true;
switch ( event->data.ctlSelect.controlID ) {
#ifdef XWFEATURE_BLUETOOTH
case XW_CONNS_BT_BROWSEBUTTON_ID:
browseForDeviceName( globals, state );
break;
#endif
case XW_CONNS_TYPE_TRIGGER_ID:
if ( state->isNewGame ) {
chosen = LstPopupList( state->connTypesList );
@ -219,7 +295,7 @@ ConnsFormHandleEvent( EventPtr event )
case XW_CONNS_OK_BUTTON_ID:
if ( !state->isNewGame ) {
/* do nothing; same as cancel */
} else if ( !stateFromCtls( globals, state ) ) {
} else if ( !stateFromCtls( state ) ) {
beep();
break;
} else {

View file

@ -240,18 +240,27 @@ BEGIN
POPUPTRIGGER "" ID XW_CONNS_TYPE_TRIGGER_ID
AT (PREVRIGHT+5 PREVTOP 72 12) LEFTANCHOR
LIST
#ifdef XWFEATURE_PALM_BLUETOOTH
#ifdef XWFEATURE_BLUETOOTH
"Bluetooth"
#endif
"IR" "Internet/IP" ID XW_CONNS_TYPE_LIST_ID
PREVLEFT PREVTOP 72 12 VISIBLEITEMS
#ifdef XWFEATURE_PALM_BLUETOOTH
#ifdef XWFEATURE_BLUETOOTH
3
#else
2
#endif
NONUSABLE POPUPLIST XW_CONNS_TYPE_TRIGGER_ID XW_CONNS_TYPE_LIST_ID
#ifdef XWFEATURE_BLUETOOTH
LABEL "host name:" XW_CONNS_BT_HOSTNAME_LABEL_ID
AT ( LEFTCOL+10 LOCALIP_TOP )
FIELD XW_CONNS_BT_HOSTFIELD_ID CONNS_FIELD_LEFT PREVTOP 70 AUTO \
SINGLELINE EDITABLE UNDERLINED MAXCHARS 32
BUTTON "Browse" XW_CONNS_BT_BROWSEBUTTON_ID LEFTCOL+10 PREVBOTTOM+5
AUTO AUTO
#endif
LABEL "Relay name:" XW_CONNS_RELAY_LABEL_ID
AT ( LEFTCOL+10 LOCALIP_TOP )
FIELD XW_CONNS_RELAY_FIELD_ID CONNS_FIELD_LEFT PREVTOP 70 AUTO \

View file

@ -17,10 +17,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef XWFEATURE_PALM_BLUETOOTH
#ifdef XWFEATURE_BLUETOOTH
#include "xptypes.h"
#include "palmbt.h"
#include "strutils.h"
# include <BtLib.h>
# include <BtLibTypes.h>
@ -44,6 +45,7 @@ typedef struct PalmBTStuff {
struct {
BtLibDeviceAddressType masterAddr;
BtLibSocketRef spdSocket;
XP_Bool addrSet;
} slave;
struct {
BtLibSocketRef listenSocket;
@ -55,6 +57,9 @@ typedef struct PalmBTStuff {
} PalmBTStuff;
#define LOG_ERR(f,e) palm_bt_log( #f, __FUNCTION__, e )
#define CALL_ERR(e,f,...) \
e = f(__VA_ARGS__); \
LOG_ERR(f,e)
/* WHAT SHOULD THIS BE? Copied from Whiteboard.... PENDING */
static const BtLibSdpUuidType XWORDS_UUID = {
@ -62,9 +67,11 @@ static const BtLibSdpUuidType XWORDS_UUID = {
{ 0x83, 0xe0, 0x87, 0xae, 0x4e, 0x18, 0x46, 0xbe,
0x83, 0xe0, 0x7b, 0x3d, 0xe6, 0xa1, 0xc3, 0x3b } };
static void initBTStuff( PalmAppGlobals* globals, DataCb cb, XP_Bool amMaster );
static Err initBTStuff( PalmAppGlobals* globals, DataCb cb, XP_Bool amMaster );
static void palm_bt_log( const char* btfunc, const char* func, Err err );
static void pbt_connect_slave( PalmBTStuff* btStuff, BtLibL2CapPsmType psm );
static Err bpd_discover( PalmBTStuff* btStuff, BtLibDeviceAddressType* addr );
static void pbt_setup_slave( PalmBTStuff* btStuff, const CommsAddrRec* addr );
#ifdef DEBUG
static const char* btErrToStr( Err err );
@ -81,38 +88,45 @@ static void libMgmtCallback( BtLibManagementEventType* mEvent, UInt32 refCon );
static void spdSocketCallback( BtLibSocketEventType* sEvent, UInt32 refCon );
static void l2SocketCallback( BtLibSocketEventType* sEvent, UInt32 refCon );
void
Err
palm_bt_init( PalmAppGlobals* globals, DataCb cb, XP_Bool amMaster )
{
XP_LOGF( "%s(amMaster=%d)", __FUNCTION__, (XP_U16)amMaster );
initBTStuff( globals, cb, amMaster );
return initBTStuff( globals, cb, amMaster );
}
void
palm_bt_close( PalmAppGlobals* globals )
{
PalmBTStuff* btStuff = globals->btStuff;
if ( !!btStuff ) {
/* Need to unregister callbacks */
(void)BtLibUnregisterManagementNotification( btStuff->btLibRefNum,
libMgmtCallback );
if ( btStuff->amMaster
&& btStuff->u.master.listenSocket != SOCK_INVAL ) {
(void)BtLibSocketClose( btStuff->btLibRefNum,
btStuff->u.master.listenSocket );
btStuff->u.master.listenSocket = SOCK_INVAL;
}
if ( btStuff->dataSocket != SOCK_INVAL ) {
(void)BtLibSocketClose( btStuff->btLibRefNum,
btStuff->u.master.listenSocket );
btStuff->dataSocket = SOCK_INVAL;
}
if ( btStuff->btLibRefNum != 0 ) {
Err err = BtLibClose( btStuff->btLibRefNum );
LOG_ERR( BtLibClose, err );
if ( !!btStuff ) {
XP_U16 btLibRefNum = btStuff->btLibRefNum;
if ( btLibRefNum != 0 ) {
Err err;
/* Need to unregister callbacks */
(void)BtLibUnregisterManagementNotification( btLibRefNum,
libMgmtCallback );
if ( btStuff->amMaster
&& btStuff->u.master.listenSocket != SOCK_INVAL ) {
CALL_ERR( err, BtLibSocketClose, btLibRefNum,
btStuff->u.master.listenSocket );
/* btStuff->u.master.listenSocket = SOCK_INVAL; */
}
if ( btStuff->dataSocket != SOCK_INVAL ) {
CALL_ERR( err, BtLibSocketClose, btLibRefNum,
btStuff->u.master.listenSocket );
/* btStuff->dataSocket = SOCK_INVAL; */
}
if ( !!btStuff->sdpRecordH ) {
CALL_ERR( err, BtLibSdpServiceRecordDestroy, btLibRefNum,
btStuff->sdpRecordH );
}
CALL_ERR( err, BtLibClose, btLibRefNum );
XP_ASSERT( errNone == err );
}
XP_FREE( globals->mpool, btStuff );
@ -120,6 +134,42 @@ palm_bt_close( PalmAppGlobals* globals )
}
} /* palm_bt_close */
XP_Bool
palm_bt_browse_device( PalmAppGlobals* globals, XP_BtAddr* btAddr,
XP_UCHAR* out, XP_U16 len )
{
Err err;
PalmBTStuff* btStuff;
err = initBTStuff( globals, NULL, XP_FALSE );
if ( errNone == err ) {
UInt16 index;
BtLibDeviceAddressType addr;
btStuff = globals->btStuff;
err = bpd_discover( btStuff, &addr );
CALL_ERR( err, BtLibSecurityFindTrustedDeviceRecord,
btStuff->btLibRefNum, &addr, &index );
CALL_ERR( err, BtLibSecurityGetTrustedDeviceRecordInfo,
btStuff->btLibRefNum, index, NULL, out, len,
NULL, NULL, NULL );
XP_ASSERT( sizeof(*btAddr) >= sizeof(addr) );
XP_MEMCPY( btAddr, &addr, sizeof(addr) );
LOG_HEX( &addr, sizeof(addr), __FUNCTION__ );
/* err = BtLibGetRemoteDeviceName( btStuff->btLibRefNum, */
/* BtLibDeviceAddressTypePtr remoteDeviceP, */
/* BtLibFriendlyNameType* nameP, */
/* BtLibGetNameEnum retrievalMethod ); */
/* err = BtLibAddrBtdToA( btStuff->btLibRefNum, &btStuff->u.slave.masterAddr, */
/* out, len ); */
} else {
XP_WARNF( "%s: err = %s", __FUNCTION__, btErrToStr(err) );
}
return errNone == err;
} /* palm_bt_browse_device */
XP_Bool
btSocketIsOpen( PalmAppGlobals* globals )
{
@ -128,74 +178,118 @@ btSocketIsOpen( PalmAppGlobals* globals )
}
static void
pbt_send_pending( PalmBTStuff* btStuff )
pbt_send_pending( PalmBTStuff* btStuff, const CommsAddrRec* addr )
{
Err err;
LOG_FUNC();
if ( btStuff->sendPending && !btStuff->sendInProgress ) {
if ( !!btStuff->dataSocket ) {
Err err = BtLibSocketSend( btStuff->btLibRefNum, btStuff->dataSocket,
btStuff->bufOut, btStuff->lenOut );
LOG_ERR( BtLibSocketSend, err );
if ( err == errNone ) {
// clear on receipt of btLibSocketEventSendComplete
btStuff->sendInProgress = XP_TRUE;
if ( btStuff->dataSocket != SOCK_INVAL ) {
if ( btStuff->lenOut > 0 ) { /* hack: zero-len send to cause connect */
CALL_ERR( err, BtLibSocketSend, btStuff->btLibRefNum,
btStuff->dataSocket,
btStuff->bufOut, btStuff->lenOut );
if ( err == errNone ) {
// clear on receipt of btLibSocketEventSendComplete
btStuff->sendInProgress = XP_TRUE;
}
} else {
btStuff->sendPending = XP_FALSE;
}
} else {
/* No data socket? */
if ( !btStuff->amMaster ) {
pbt_setup_slave( btStuff, addr );
}
}
}
} /* pbt_send_pending */
static void
pbt_check_socket( PalmBTStuff* btStuff, const CommsAddrRec* addr )
{
LOG_FUNC();
if ( btStuff->dataSocket == SOCK_INVAL ) {
if ( btStuff->amMaster ) {
XP_ASSERT(0);
/* pbt_setup_master( btStuff ); */
} else {
pbt_setup_slave( btStuff, addr );
}
}
}
XP_S16
palm_bt_send( const XP_U8* buf, XP_U16 len, PalmAppGlobals* globals )
palm_bt_send( const XP_U8* buf, XP_U16 len, const CommsAddrRec* addr,
PalmAppGlobals* globals )
{
XP_S16 nSent = -1;
PalmBTStuff* btStuff;
CommsAddrRec remoteAddr;
XP_LOGF( "%s(len=%d)", __FUNCTION__, len );
btStuff = globals->btStuff;
XP_ASSERT( !!btStuff );
if ( !!btStuff ) {
if ( !btStuff->sendInProgress ) {
if ( len > sizeof( btStuff->bufOut ) ) {
len = sizeof( btStuff->bufOut );
}
XP_MEMCPY( btStuff->bufOut, buf, len );
btStuff->lenOut = len;
btStuff->sendPending = XP_TRUE;
pbt_send_pending( btStuff );
}
if ( !addr ) {
comms_getAddr( globals->game.comms, &remoteAddr );
addr = &remoteAddr;
}
return -1;
XP_ASSERT( !!addr );
btStuff = globals->btStuff;
if ( !!btStuff ) {
pbt_check_socket( btStuff, addr );
if ( !!btStuff ) {
if ( !btStuff->sendInProgress ) {
if ( len > sizeof( btStuff->bufOut ) ) {
len = sizeof( btStuff->bufOut );
}
XP_MEMCPY( btStuff->bufOut, buf, len );
btStuff->lenOut = len;
btStuff->sendPending = XP_TRUE;
pbt_send_pending( btStuff, addr );
nSent = len;
} else {
XP_LOGF( "%s: send ALREADY in progress", __FUNCTION__ );
}
}
} else {
XP_LOGF( "%s: btStuff null", __FUNCTION__ );
}
LOG_RETURNF( "%d", nSent );
return nSent;
} /* palm_bt_send */
static void
pbt_find_psm( PalmBTStuff* btStuff )
{
Err err;
XP_ASSERT( !btStuff->amMaster );
err = BtLibSocketCreate( btStuff->btLibRefNum, &btStuff->u.slave.spdSocket,
spdSocketCallback,
(UInt32)btStuff, btLibSdpProtocol );
LOG_ERR( BtLibSocketCreate, err );
LOG_FUNC();
err = BtLibSdpGetPsmByUuid( btStuff->btLibRefNum,
btStuff->u.slave.spdSocket,
&btStuff->u.slave.masterAddr,
(BtLibSdpUuidType*)&XWORDS_UUID, 1 );
LOG_ERR( BtLibSdpGetPSMByUuid, err );
XP_ASSERT( !btStuff->amMaster );
CALL_ERR( err, BtLibSocketCreate, btStuff->btLibRefNum,
&btStuff->u.slave.spdSocket,
spdSocketCallback, (UInt32)btStuff, btLibSdpProtocol );
/* sends btLibSocketEventSdpGetPsmByUuid */
CALL_ERR( err, BtLibSdpGetPsmByUuid, btStuff->btLibRefNum,
btStuff->u.slave.spdSocket,
&btStuff->u.slave.masterAddr,
(BtLibSdpUuidType*)&XWORDS_UUID, 1 );
}
static void
pbt_connect_slave( PalmBTStuff* btStuff, BtLibL2CapPsmType psm )
{
Err err;
LOG_FUNC();
XP_ASSERT( !btStuff->amMaster );
err = BtLibSocketCreate( btStuff->btLibRefNum, &btStuff->dataSocket,
l2SocketCallback, (UInt32)btStuff,
btLibL2CapProtocol );
LOG_ERR( BtLibSocketCreate, err );
XP_LOGF( "%s(psm=%x)", __FUNCTION__, psm );
CALL_ERR( err, BtLibSocketCreate, btStuff->btLibRefNum,
&btStuff->dataSocket,
l2SocketCallback, (UInt32)btStuff,
btLibL2CapProtocol );
if ( btLibErrNoError == err ) {
BtLibSocketConnectInfoType connInfo;
@ -204,9 +298,9 @@ pbt_connect_slave( PalmBTStuff* btStuff, BtLibL2CapPsmType psm )
connInfo.data.L2Cap.minRemoteMtu = L2CAPSOCKETMTU;
connInfo.remoteDeviceP = &btStuff->u.slave.masterAddr;
err = BtLibSocketConnect( btStuff->btLibRefNum,
btStuff->dataSocket, &connInfo );
LOG_ERR( BtLibSocketConnect, err );
/* sends btLibManagementEventACLConnectOutbound */
CALL_ERR( err, BtLibSocketConnect, btStuff->btLibRefNum,
btStuff->dataSocket, &connInfo );
}
}
@ -218,48 +312,43 @@ pbt_setup_master( PalmBTStuff* btStuff )
Err err;
BtLibSocketListenInfoType listenInfo;
btStuff->u.master.listenSocket = SOCK_INVAL;
/* 1. BtLibSocketCreate: create an L2CAP socket. */
err = BtLibSocketCreate( btStuff->btLibRefNum,
&btStuff->u.master.listenSocket, l2SocketCallback,
(UInt32)btStuff, btLibL2CapProtocol );
LOG_ERR( BtLibSocketCreate, err );
CALL_ERR( err, BtLibSocketCreate, btStuff->btLibRefNum,
&btStuff->u.master.listenSocket, l2SocketCallback,
(UInt32)btStuff, btLibL2CapProtocol );
/* 2. BtLibSocketListen: set up an L2CAP socket as a listener. */
XP_MEMSET( &listenInfo, 0, sizeof(listenInfo) );
listenInfo.data.L2Cap.localPsm = BT_L2CAP_RANDOM_PSM;
listenInfo.data.L2Cap.localPsm = XW_PSM; // BT_L2CAP_RANDOM_PSM;
listenInfo.data.L2Cap.localMtu = L2CAPSOCKETMTU;
listenInfo.data.L2Cap.minRemoteMtu = L2CAPSOCKETMTU;
err = BtLibSocketListen( btStuff->btLibRefNum,
btStuff->u.master.listenSocket, &listenInfo );
LOG_ERR( BtLibSocketListen, err );
CALL_ERR( err, BtLibSocketListen, btStuff->btLibRefNum,
btStuff->u.master.listenSocket, &listenInfo );
/* 3. BtLibSdpServiceRecordCreate: allocate a memory chunk that
represents an SDP service record. */
err = BtLibSdpServiceRecordCreate(btStuff->btLibRefNum, &btStuff->sdpRecordH );
LOG_ERR( BtLibSdpServiceRecordCreate, err );
CALL_ERR( err, BtLibSdpServiceRecordCreate,
btStuff->btLibRefNum, &btStuff->sdpRecordH );
/* 4. BtLibSdpServiceRecordSetAttributesForSocket: initialize an SDP
memory record so it can represent the newly-created L2CAP listener
socket as a service */
err = BtLibSdpServiceRecordSetAttributesForSocket(
btStuff->btLibRefNum, btStuff->u.master.listenSocket,
(BtLibSdpUuidType*)&XWORDS_UUID, 1, APPNAME,
StrLen(APPNAME), btStuff->sdpRecordH );
LOG_ERR( BtLibSdpServiceRecordSetAttributesForSocket, err );
CALL_ERR( err, BtLibSdpServiceRecordSetAttributesForSocket,
btStuff->btLibRefNum, btStuff->u.master.listenSocket,
(BtLibSdpUuidType*)&XWORDS_UUID, 1, APPNAME,
StrLen(APPNAME), btStuff->sdpRecordH );
/* 5. BtLibSdpServiceRecordStartAdvertising: make an SDP memory record
representing a local SDP service record visible to remote
devices. */
err = BtLibSdpServiceRecordStartAdvertising( btStuff->btLibRefNum,
btStuff->sdpRecordH );
LOG_ERR( BtLibSdpServiceRecordStartAdvertising, err );
CALL_ERR( err, BtLibSdpServiceRecordStartAdvertising, btStuff->btLibRefNum,
btStuff->sdpRecordH );
} /* pbt_setup_master */
static void
pbt_setup_slave( PalmBTStuff* btStuff )
static Err
bpd_discover( PalmBTStuff* btStuff, BtLibDeviceAddressType* addr )
{
Err err;
static const BtLibClassOfDeviceType deviceFilter
@ -267,68 +356,103 @@ pbt_setup_slave( PalmBTStuff* btStuff )
| btLibCOD_Major_Any // btLibCOD_Major_Computer
| btLibCOD_Minor_Comp_Any; //btLibCOD_Minor_Comp_Palm;
CALL_ERR( err, BtLibDiscoverSingleDevice, btStuff->btLibRefNum, "Crosswords host",
(BtLibClassOfDeviceType*)&deviceFilter, 1,
addr, false, false );
LOG_RETURNF( "%s", btErrToStr(err) );
return err;
} /* bpd_discover */
static void
pbt_setup_slave( PalmBTStuff* btStuff, const CommsAddrRec* addr )
{
LOG_FUNC();
XP_ASSERT( !btStuff->amMaster );
err = BtLibDiscoverSingleDevice( btStuff->btLibRefNum, "Crosswords host",
(BtLibClassOfDeviceType*)&deviceFilter, 1,
&btStuff->u.slave.masterAddr,
false, false );
LOG_ERR( BtLibDiscoverSingleDevice, err );
if ( !!addr ) {
char buf[64];
if ( errNone == BtLibAddrBtdToA( btStuff->btLibRefNum,
(BtLibDeviceAddressType*)&addr->u.bt.btAddr,
buf, sizeof(buf) ) ) {
XP_LOGF( "%s(%s)", __FUNCTION__, buf );
}
} else {
XP_LOGF( "null addr" );
}
if ( errNone == err ) {
err = BtLibLinkConnect( btStuff->btLibRefNum,
&btStuff->u.slave.masterAddr );
LOG_ERR( BtLibLinkConnect, err );
if ( !btStuff->u.slave.addrSet && !!addr ) {
Err err;
/* Our xp type better be big enough */
XP_ASSERT( sizeof(addr->u.bt.btAddr)
>= sizeof(btStuff->u.slave.masterAddr) );
XP_MEMCPY( &btStuff->u.slave.masterAddr, addr->u.bt.btAddr,
sizeof(btStuff->u.slave.masterAddr) );
btStuff->u.slave.addrSet = XP_TRUE;
CALL_ERR( err, BtLibLinkConnect, btStuff->btLibRefNum,
&btStuff->u.slave.masterAddr );
XP_ASSERT( err == btLibErrPending );
} else {
XP_LOGF( "%s: doing nothing", __FUNCTION__ );
}
} /* pbt_setup_slave */
static void
static Err
initBTStuff( PalmAppGlobals* globals, DataCb cb, XP_Bool amMaster )
{
PalmBTStuff* btStuff;
Err err;
XP_U16 btLibRefNum;
LOG_FUNC();
btStuff = globals->btStuff;
if ( btStuff != NULL ) {
if ( NULL != cb ) {
btStuff->cb = cb;
}
if ( btStuff->amMaster == amMaster ) {
/* nothing to do */
} else {
/* role change. Adapt... */
XP_ASSERT( 0 );
}
err = errNone;
} else {
XP_U16 btLibRefNum;
btStuff = XP_MALLOC( globals->mpool, sizeof(*btStuff) );
XP_ASSERT( !!btStuff );
XP_MEMSET( btStuff, 0, sizeof(*btStuff) );
globals->btStuff = btStuff;
CALL_ERR( err, SysLibFind, btLibName, &btLibRefNum );
if ( errNone == err ) {
btStuff->globals = globals;
btStuff->cb = cb;
btStuff->amMaster = amMaster;
btStuff->dataSocket = SOCK_INVAL;
btStuff = XP_MALLOC( globals->mpool, sizeof(*btStuff) );
XP_ASSERT( !!btStuff );
XP_MEMSET( btStuff, 0, sizeof(*btStuff) );
globals->btStuff = btStuff;
err = SysLibFind( btLibName, &btLibRefNum );
XP_LOGF( "%s: SysLibFind(%s) => %d\n", __FUNCTION__, btLibName, err );
XP_ASSERT( errNone == err );
btStuff->btLibRefNum = btLibRefNum;
btStuff->globals = globals;
btStuff->cb = cb;
btStuff->amMaster = amMaster;
btStuff->dataSocket = SOCK_INVAL;
err = BtLibOpen( btLibRefNum, false );
LOG_ERR( BtLibOpen, err );
XP_ASSERT( errNone == err );
btStuff->btLibRefNum = btLibRefNum;
err = BtLibRegisterManagementNotification( btLibRefNum, libMgmtCallback,
(UInt32)btStuff );
LOG_ERR( BtLibRegisterManagementNotification, err );
CALL_ERR( err, BtLibOpen, btLibRefNum, false );
XP_ASSERT( errNone == err );
if ( btStuff->amMaster ) {
pbt_setup_master( btStuff );
} else {
pbt_setup_slave( btStuff );
CALL_ERR( err, BtLibRegisterManagementNotification, btLibRefNum,
libMgmtCallback, (UInt32)btStuff );
if ( btStuff->amMaster ) {
pbt_setup_master( btStuff );
} else {
/* Can't set up b/c don't have address yet. */
/* pbt_setup_slave( btStuff, addr ); */
}
}
}
LOG_RETURNF( "%s", btErrToStr(err) );
return err;
} /* initBTStuff */
static void
@ -342,24 +466,24 @@ l2SocketCallback( BtLibSocketEventType* sEvent, UInt32 refCon )
switch( event ) {
case btLibSocketEventConnectRequest:
err = BtLibSocketRespondToConnection( btStuff->btLibRefNum,
sEvent->socket, true );
LOG_ERR( BtLibSocketRespondToConnection, err );
CALL_ERR( err, BtLibSocketRespondToConnection, btStuff->btLibRefNum,
sEvent->socket, true );
break;
case btLibSocketEventConnectedInbound:
if ( sEvent->status == errNone ) {
btStuff->dataSocket = sEvent->eventData.newSocket;
XP_LOGF( "we have a data socket!!!" );
pbt_send_pending( btStuff );
pbt_send_pending( btStuff, NULL );
} else {
XP_LOGF( "%s: status = %d(%s)", __FUNCTION__,
sEvent->status, btErrToStr(sEvent->status) );
}
break;
case btLibSocketEventConnectedOutbound:
pbt_send_pending( btStuff );
pbt_send_pending( btStuff, NULL );
break;
case btLibSocketEventData:
XP_ASSERT( !!btStuff->cb );
(*btStuff->cb)( btStuff->globals, sEvent->eventData.data.data,
sEvent->eventData.data.dataLen );
break;
@ -385,11 +509,11 @@ spdSocketCallback( BtLibSocketEventType* sEvent, UInt32 refCon )
switch( event ) {
case btLibSocketEventSdpGetPsmByUuid:
if ( btLibErrNoError == sEvent->status ) {
err = BtLibSocketClose( btStuff->btLibRefNum,
sEvent->socket );
LOG_ERR( BtLibSocketClose, err );
CALL_ERR( err, BtLibSocketClose, btStuff->btLibRefNum,
sEvent->socket );
btStuff->u.slave.spdSocket = SOCK_INVAL;
pbt_connect_slave( btStuff, sEvent->eventData.sdpByUuid.param.psm );
pbt_connect_slave( btStuff,
sEvent->eventData.sdpByUuid.param.psm );
}
break;
default: /* happy now, compiler? */
@ -616,4 +740,4 @@ NOTE: I've read conflicting reports on whether a listening socket is good for
accepting more than one inbound connection. Confirm. Or just do a piconet.
*/
#endif /* #ifdef XWFEATURE_PALM_BLUETOOTH */
#endif /* #ifdef XWFEATURE_BLUETOOTH */

View file

@ -20,7 +20,7 @@
#ifndef _PALMBT_H_
#define _PALMBT_H_
#ifdef XWFEATURE_PALM_BLUETOOTH
#ifdef XWFEATURE_BLUETOOTH
#include "comms.h"
#include "palmmain.h"
@ -28,10 +28,15 @@
typedef void (*DataCb)( PalmAppGlobals* globals,
const XP_U8* data, XP_U16 len );
void palm_bt_init( PalmAppGlobals* globals, DataCb cb, XP_Bool amMaster );
Err palm_bt_init( PalmAppGlobals* globals, DataCb cb, XP_Bool amMaster );
void palm_bt_close( PalmAppGlobals* globals );
XP_S16 palm_bt_send( const XP_U8* buf, XP_U16 len, PalmAppGlobals* globals );
XP_S16 palm_bt_send( const XP_U8* buf, XP_U16 len, const CommsAddrRec* addr,
PalmAppGlobals* globals );
XP_Bool btSocketIsOpen( PalmAppGlobals* globals );
#endif
XP_Bool palm_bt_browse_device( PalmAppGlobals* globals, XP_BtAddr* btAddr,
XP_UCHAR* out,XP_U16 len );
#endif /* XWFEATURE_BLUETOOTH */
#endif

View file

@ -1303,7 +1303,7 @@ stopApplication( PalmAppGlobals* globals )
palm_ip_close( globals );
#endif
#endif
#ifdef XWFEATURE_PALM_BLUETOOTH
#ifdef XWFEATURE_BLUETOOTH
palm_bt_close( globals );
#endif
@ -1356,7 +1356,7 @@ figureWaitTicks( PalmAppGlobals* globals )
} else if ( ipSocketIsOpen(globals) ) {
/* we'll do our sleeping in NetLibSelect */
result = 0;
# ifdef XWFEATURE_PALM_BLUETOOTH
# ifdef XWFEATURE_BLUETOOTH
} else if ( btSocketIsOpen(globals) ) {
/* From Whiteboard. But: what to use here? BTLib needs nil events
AFAIK. */
@ -1888,6 +1888,8 @@ initAndStartBoard( PalmAppGlobals* globals, XP_Bool newGame )
if ( !!globals->game.comms ) {
comms_setAddr( globals->game.comms,
&globals->newGameState.addr );
} else {
XP_ASSERT(0);
}
#endif
}
@ -3450,8 +3452,7 @@ palm_send_on_close( XWStreamCtxt* stream, void* closure )
static XP_S16
palm_send( const XP_U8* buf, XP_U16 len,
const CommsAddrRec* XP_UNUSED_IR(addr), /* !!!? */
void* closure )
const CommsAddrRec* addr, void* closure )
{
PalmAppGlobals* globals = (PalmAppGlobals*)closure;
@ -3464,9 +3465,9 @@ palm_send( const XP_U8* buf, XP_U16 len,
case COMMS_CONN_RELAY:
result = palm_ip_send( buf, len, addr, globals );
break;
#ifdef XWFEATURE_PALM_BLUETOOTH
#ifdef XWFEATURE_BLUETOOTH
case COMMS_CONN_BT:
result = palm_bt_send( buf, len, globals );
result = palm_bt_send( buf, len, addr, globals );
break;
#endif
default:
@ -3536,7 +3537,7 @@ palm_util_warnIllegalWord( XW_UtilCtxt* uc, BadWordInfo* bwi,
} /* palm_util_warnIllegalWord */
#ifdef BEYOND_IR
#ifdef XWFEATURE_PALM_BLUETOOTH
#ifdef XWFEATURE_BLUETOOTH
static void
btDataHandler( PalmAppGlobals* globals, const XP_U8* data, XP_U16 len )
{
@ -3554,10 +3555,18 @@ palm_util_addrChange( XW_UtilCtxt* uc, const CommsAddrRec* oldAddr,
const CommsAddrRec* newAddr, XP_Bool isServer )
{
PalmAppGlobals* globals = (PalmAppGlobals*)uc->closure;
#ifdef XWFEATURE_BLUETOOTH
XP_Bool isBT = COMMS_CONN_BT == newAddr->conType;
if ( !isBT ) {
palm_bt_close( globals );
}
#endif
if ( COMMS_CONN_RELAY == newAddr->conType ) {
ip_addr_change( globals, oldAddr, newAddr );
#ifdef XWFEATURE_PALM_BLUETOOTH
} else if ( COMMS_CONN_BT == newAddr->conType ) {
#ifdef XWFEATURE_BLUETOOTH
} else if ( isBT ) {
palm_bt_init( globals, btDataHandler, isServer );
#endif
}

View file

@ -304,7 +304,7 @@ struct PalmAppGlobals {
#ifdef BEYOND_IR
NetLibStuff nlStuff;
XP_U32 heartTimerFireAt;
# ifdef XWFEATURE_PALM_BLUETOOTH
# ifdef XWFEATURE_BLUETOOTH
struct PalmBTStuff* btStuff;
# endif
#endif

View file

@ -334,6 +334,11 @@
#define XW_CONNS_PORT_FIELD_ID 2907
#define XW_CONNS_RELAY_LABEL_ID 2908
#define XW_CONNS_RELAY_FIELD_ID 2909
#ifdef XWFEATURE_BLUETOOTH
# define XW_CONNS_BT_HOSTNAME_LABEL_ID 2910
# define XW_CONNS_BT_HOSTFIELD_ID 2911
# define XW_CONNS_BT_BROWSEBUTTON_ID 2912
#endif
/*
* selector for number of tiles during hint