diff --git a/xwords4/palm/Makefile.PNO b/xwords4/palm/Makefile.PNO index 81f6aa473..15734a5a8 100644 --- a/xwords4/palm/Makefile.PNO +++ b/xwords4/palm/Makefile.PNO @@ -117,6 +117,7 @@ pace_gen.c pace_gen.h: ./gen_pace.pl funcfile.txt -file $(PALMDIR)/Core/UI \ -file $(PALMDIR)/Core/System \ -file $(PALMDIR)/Extensions/ExpansionMgr \ + -file $(PALMDIR)/Extensions/Bluetooth \ -file /usr/local/share/palmdev/Handspring5/68K/System \ -oc pace_gen.c -oh pace_gen.h rm -f _dirList diff --git a/xwords4/palm/funcfile.txt b/xwords4/palm/funcfile.txt index 14589eb3f..d4dfe4dca 100644 --- a/xwords4/palm/funcfile.txt +++ b/xwords4/palm/funcfile.txt @@ -66,7 +66,6 @@ FntCharsWidth FntGetFont FntLineHeight FntSetFont -FntsWidth FrmCloseAllForms FrmCustomAlert FrmDeleteForm @@ -184,7 +183,6 @@ WinSetDrawWindow WinSetForeColor WinSetPattern WinSetTextColor -memcpy WinEraseLine SclDrawScrollBar DmNumRecordsInCategory @@ -231,3 +229,20 @@ WinGetPixel # UIColorGetTableEntryIndex #HsNavDrawFocusRing +# Bluetooth +BtLibOpen +BtLibAddrBtdToA +BtLibSecurityFindTrustedDeviceRecord +BtLibSocketSend +BtLibSocketClose +BtLibLinkConnect +BtLibDiscoverSingleDevice +BtLibLinkDisconnect +BtLibSocketRespondToConnection +BtLibClose +BtLibSecurityGetTrustedDeviceRecordInfo +BtLibSocketConnect +BtLibSocketListen +#BtLibRegisterManagementNotification +#BtLibUnregisterManagementNotification +#BtLibSocketCreate diff --git a/xwords4/palm/pace_man.c b/xwords4/palm/pace_man.c index 9bd8d0b21..bad28918e 100644 --- a/xwords4/palm/pace_man.c +++ b/xwords4/palm/pace_man.c @@ -1,6 +1,7 @@ -/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */ +/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make ARCH=ARM_ONLY MEMDEBUG=TRUE"; -*- */ /* - * Copyright 2004 by Eric House (xwords@eehouse.org). All rights reserved. + * Copyright 2004-2007 by Eric House (xwords@eehouse.org). All rights + * reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,6 +23,11 @@ #include #include +#ifdef XWFEATURE_BLUETOOTH +#include +#include +#endif + #include "pace_man.h" #include "palmmain.h" /* for custom event types */ @@ -541,10 +547,10 @@ FrmSetEventHandler( FormType* formP, FormEventHandlerType* handler ) FUNC_HEADER(FrmSetEventHandler); { PNOState* sp = GET_CALLBACK_STATE(); - unsigned char* handlerStub = makeHandlerStub( handler ); + unsigned char* stub = makeHandlerStub( handler ); STACK_START(unsigned char, stack, 8); ADD_TO_STACK4(stack, formP, 0); - ADD_TO_STACK4(stack, handlerStub, 4); + ADD_TO_STACK4(stack, stub, 4); STACK_END(stack); (*sp->call68KFuncP)( sp->emulStateP, PceNativeTrapNo(sysTrapFrmSetEventHandler), @@ -692,7 +698,7 @@ paramsArmtoParams68K( unsigned char* params68K, write_unaligned8( ¶ms68K[16], armParams->handled ); } /* paramsArmtoParams68K */ -unsigned long +static unsigned long notifyEntryPoint( const void* XP_UNUSED_DBG(emulStateP), void* userData68KP, Call68KFuncType* XP_UNUSED_DBG(call68KFuncP) ) @@ -777,13 +783,13 @@ SysNotifyRegister( UInt16 cardNo, LocalID dbID, UInt32 notifyType, /* swapIns */ { PNOState* sp = GET_CALLBACK_STATE(); - unsigned char* handlerStub = makeNotifyStub( callbackP ); + unsigned char* stub = makeNotifyStub( callbackP ); STACK_START(unsigned char, stack, 20); /* pushes */ ADD_TO_STACK2(stack, cardNo, 0); ADD_TO_STACK4(stack, dbID, 2); ADD_TO_STACK4(stack, notifyType, 6); - ADD_TO_STACK4(stack, handlerStub, 10); + ADD_TO_STACK4(stack, stub, 10); ADD_TO_STACK1(stack, priority, 14); ADD_TO_STACK4(stack, userDataP, 16); STACK_END(stack); @@ -934,7 +940,6 @@ NetLibGetHostByName( UInt16 libRefNum, const Char* nameP, stack, kPceNativeWantA0 | 18 ); /* swapOuts */ - XP_LOGF( "result = 0x%lx", result ); if ( result != NULL ) { result->nameP = Byte_Swap32( result->nameP ); result->nameAliasesP = Byte_Swap32( result->nameAliasesP ); @@ -944,9 +949,8 @@ NetLibGetHostByName( UInt16 libRefNum, const Char* nameP, /* we'll use only the first */ result->addrListP[0] = Byte_Swap32( result->addrListP[0] ); - XP_LOGF( "turning 0x%lx", result->addrListP[0] ); - *(XP_U32*)result->addrListP[0] = Byte_Swap32( *(XP_U32*)result->addrListP[0] ); - XP_LOGF( "into 0x%lx", result->addrListP[0] ); + *(XP_U32*)result->addrListP[0] = + Byte_Swap32( *(XP_U32*)result->addrListP[0] ); } } FUNC_TAIL(NetLibGetHostByName); @@ -1060,3 +1064,325 @@ ExgDBWrite( ExgDBWriteProcPtr writeProcP, void* userDataP, EMIT_NAME("ExgDBWrite","'E','x','g','D','B','W','r','i','t','e'"); return result; } /* ExgDBWrite */ + +static void* +lookupStubFor( XP_U16 key ) +{ + void* val; + Err err = FtrGet( APPID, key, (UInt32*)&val ); + if ( err != errNone ) { + val = NULL; + } + LOG_RETURNF( "%lx", val ); + return val; +} + +static void +registerStubFor( XP_U16 key, void* stub ) +{ + Err err; + XP_ASSERT( NULL == lookupStubFor( key ) ); + XP_LOGF( "%s: registering %lx", __func__, stub ); + err = FtrSet( APPID, key, stub ); + XP_ASSERT( err == errNone ); +} + +static void +unregisterStubFor( XP_U16 key ) +{ + Err err = FtrUnregister( APPID, key ); + XP_ASSERT( err == errNone ); +} + +#ifdef XWFEATURE_BLUETOOTH +static void +btLibManagementEventType68K_TO_ARM( BtLibManagementEventType* out, const unsigned char* in ) +{ + BtLibManagementEventEnum event + = (BtLibManagementEventEnum)read_unaligned8( &in[0] ); + out->event = event; + out->status = read_unaligned16( &in[2] ); + switch( event ) { + case btLibManagementEventACLConnectInbound: + case btLibManagementEventACLDisconnect: + memcpy( &out->eventData.bdAddr, &in[4], sizeof(out->eventData.bdAddr) ); + break; + case btLibManagementEventAccessibilityChange: + out->eventData.accessible + = (BtLibAccessibleModeEnum)read_unaligned8( &in[4] ); + break; + } +} + +static unsigned long +btLibManagementProcArmEntry( const void* XP_UNUSED_DBG(emulStateP), + void* userData68KP, + Call68KFuncType* XP_UNUSED_DBG(call68KFuncP) ) +{ + unsigned long* data; + BtLibManagementProcPtr procPtr; + PNOState* state; + unsigned long oldR10; + BtLibManagementEventType mEvent; + const BtLibManagementEventType* mEventP; + UInt32 refCon; + + data = (unsigned long*)userData68KP; + state = getStorageLoc(); + + /* set up stack here too? */ + asm( "mov %0, r10" : "=r" (oldR10) ); + asm( "mov r10, %0" : : "r" (state->gotTable) ); + + XP_ASSERT( emulStateP == state->emulStateP ); + XP_ASSERT( call68KFuncP == state->call68KFuncP ); + + procPtr = (BtLibManagementProcPtr)read_unaligned32( &data[0] ); + mEventP = read_unaligned32( &data[1] ); + btLibManagementEventType68K_TO_ARM( &mEvent, (unsigned char*)mEventP ); + refCon = read_unaligned32( (unsigned char*)&data[2] ); + (*procPtr)( &mEvent, refCon ); + + asm( "mov r10, %0" : : "r" (oldR10) ); + + return 0L; /* no result to return */ +} /* btLibManagementProcArmEntry */ + +/* BtLibSocketProcPtr and BtLibManagementProc have the same signatures as far + as 68K code goes: */ +/* static void BtLibManagementProc( BtLibManagementEventType *mEvent, UInt32 refCon ) */ +/* { */ +/* unsigned long data[] = { callbackP, mEvent, refCon }; */ +/* (void)PceNativeCall( btLibManagementProcArmEntry, (void*)data ); */ +/* } */ + +static unsigned char* +findOrMakeBTProcStub( void* callbackP, XP_U16 key, NativeFuncType armFunc ) +{ + unsigned char* stub = lookupStubFor( key ); + if ( !stub ) { + unsigned char code_68k[] = { + /* 0 */ 0x4e, 0x56, 0xff, 0xf4, // linkw %fp,#-12 + /* 4 */ 0x20, 0x2e, 0x00, 0x08, // movel %fp@(8),%d0 + /* 8 */ 0x22, 0x2e, 0x00, 0x0c, // movel %fp@(12),%d1 + /* C */ 0x2d, 0x7c, 0x11, 0x22, 0x33, 0x44, // movel #287454020,%fp@(-12) + /* 12 */ 0xff, 0xf4, + /* 14 */ 0x2d, 0x40, 0xff, 0xf8, // movel %d0,%fp@(-8) + /* 18 */ 0x2d, 0x41, 0xff, 0xfc, // movel %d1,%fp@(-4) + /* 1C */ 0x48, 0x6e, 0xff, 0xf4, // pea %fp@(-12) + /* 20 */ 0x2f, 0x3c, 0x55, 0x66, 0x77, 0x88, // movel #1432778632,%sp@- + /* 26 */ 0x4e, 0x4f, // trap #15 + /* 28 */ 0xa4, 0x5a, // 0122132 + /* 2A */ 0x50, 0x8f, // addql #8,%sp + /* 2C */ 0x4e, 0x5e, // unlk %fp + /* 2E */ 0x4e, 0x75 // rts + }; + stub = MemPtrNew( sizeof(code_68k) ); + memcpy( stub, code_68k, sizeof(code_68k) ); + + write_unaligned32( &stub[0x0E], + /* replace 0x11223344 */ + (unsigned long)callbackP ); + write_unaligned32( &stub[0x22], + /* replace 0x55667788 */ + (unsigned long)armFunc ); + + registerStubFor( key, stub ); + } + return stub; +} /* findOrMakeBTProcStub */ + +static void +btLibSocketEventType68K_TO_ARM( BtLibSocketEventType* out, const unsigned char* in ) +{ + BtLibSocketEventEnum event = read_unaligned8( &in[0] ); /* enum? */ + out->event = event; + out->socket = read_unaligned16( &in[2] ); + out->status = read_unaligned16( &in[4] ); + + switch( event ) { + case btLibSocketEventConnectedInbound: + out->eventData.newSocket = read_unaligned16( &in[6] ); + break; + case btLibSocketEventData: + out->eventData.data.dataLen = read_unaligned16( &in[6] ); + out->eventData.data.data = read_unaligned32( &in[8] ); + break; + default: /* shut up, compiler */ + break; + } +} + +static unsigned long +btSocketProcArmEntry( const void* XP_UNUSED_DBG(emulStateP), + void* userData68KP, + Call68KFuncType* XP_UNUSED_DBG(call68KFuncP) ) +{ + BtLibSocketEventType sEvent; + BtLibSocketEventType* sEventP; + UInt32 refCon; + + unsigned long* data = (unsigned long*)userData68KP; + unsigned long oldR10; + BtLibSocketProcPtr procPtr + = (BtLibSocketProcPtr)read_unaligned32( (unsigned char*)&data[0] ); + PNOState* state = getStorageLoc(); + + /* set up stack here too? */ + asm( "mov %0, r10" : "=r" (oldR10) ); + asm( "mov r10, %0" : : "r" (state->gotTable) ); + + LOG_FUNC(); + + XP_ASSERT( emulStateP == state->emulStateP ); + XP_ASSERT( call68KFuncP == state->call68KFuncP ); + + sEventP = (BtLibSocketEventType*) + read_unaligned32( (unsigned char*)&data[1] ); + btLibSocketEventType68K_TO_ARM( &sEvent, (unsigned char*)sEventP ); + refCon = read_unaligned32( (unsigned char*)&data[2] ); + (*procPtr)( &sEvent, refCon ); + + asm( "mov r10, %0" : : "r" (oldR10) ); + + return 0L; /* no result to return */ +} /* btSocketProcArmEntry */ + +/* from file BtLib.h */ +Err +BtLibRegisterManagementNotification( UInt16 btLibRefNum, + BtLibManagementProcPtr callbackP, + UInt32 refCon ) +{ + Err result; + FUNC_HEADER(BtLibRegisterManagementNotification); + /* var decls */ + /* swapIns */ + { + PNOState* sp = GET_CALLBACK_STATE(); + + unsigned char* stub; + stub = findOrMakeBTProcStub( callbackP, PACE_SCREEN_LIBMNGMT_FEATURE, + btLibManagementProcArmEntry ); + XP_LOGF( "%s: stub=%lx", __func__, stub ); + STACK_START(unsigned char, stack, 10); + /* pushes */ + ADD_TO_STACK2(stack, btLibRefNum, 0); + ADD_TO_STACK4(stack, stub, 2); + ADD_TO_STACK4(stack, refCon, 6); + STACK_END(stack); + result = (Err)(*sp->call68KFuncP)( + sp->emulStateP, + PceNativeTrapNo(btLibTrapRegisterManagementNotification), + stack, 10 ); + /* swapOuts */ + } + FUNC_TAIL(BtLibRegisterManagementNotification); + EMIT_NAME("BtLibRegisterManagementNotification","'B','t','L','i','b','R','e','g','i','s','t','e','r','M','a','n','a','g','e','m','e','n','t','N','o','t','i','f','i','c','a','t','i','o','n'"); + return result; +} /* BtLibRegisterManagementNotification */ + +/* from file BtLib.h */ +Err +BtLibUnregisterManagementNotification( + UInt16 btLibRefNum, + BtLibManagementProcPtr XP_UNUSED_DBG(callbackP) ) +{ + Err result; + unsigned char* stub; + FUNC_HEADER(BtLibUnregisterManagementNotification); + + stub = lookupStubFor( PACE_SCREEN_LIBMNGMT_FEATURE ); + XP_ASSERT( stub ); + XP_LOGF( "%s: stub=%lx", __func__, stub ); + + XP_ASSERT( 0 == XP_MEMCMP( &callbackP, &stub[0x0E], sizeof(callbackP) ) ); + unregisterStubFor( PACE_SCREEN_LIBMNGMT_FEATURE ); + + /* var decls */ + /* swapIns */ + { + PNOState* sp = GET_CALLBACK_STATE(); + STACK_START(unsigned char, stack, 6); + /* pushes */ + ADD_TO_STACK2(stack, btLibRefNum, 0); + ADD_TO_STACK4(stack, stub, 2); + STACK_END(stack); + result = (Err)(*sp->call68KFuncP)( sp->emulStateP, + PceNativeTrapNo(btLibTrapUnregisterManagementNotification), + stack, 6 ); + /* swapOuts */ + } + MemPtrFree( stub ); + XP_LOGF( "%s: stub freed", __func__ ); + + FUNC_TAIL(BtLibUnregisterManagementNotification); + EMIT_NAME("BtLibUnregisterManagementNotification","'B','t','L','i','b','U','n','r','e','g','i','s','t','e','r','M','a','n','a','g','e','m','e','n','t','N','o','t','i','f','i','c','a','t','i','o','n'"); + return result; +} /* BtLibUnregisterManagementNotification */ + +/* from file BtLib.h */ +Err +BtLibSocketCreate( UInt16 btLibRefNum, BtLibSocketRef* socketRefP, + BtLibSocketProcPtr callbackP, UInt32 refCon, + BtLibProtocolEnum socketProtocol ) +{ + Err result; + FUNC_HEADER(BtLibSocketCreate); + /* var decls */ + /* swapIns */ + /* SWAP2_NON_NULL_IN(socketRefP); */ + { + PNOState* sp = GET_CALLBACK_STATE(); + unsigned char* stub; + stub = findOrMakeBTProcStub( callbackP, + PACE_SCREEN_SOCKETPROC_FEATURE, + btSocketProcArmEntry ); + STACK_START(unsigned char, stack, 16); + /* pushes */ + ADD_TO_STACK2(stack, btLibRefNum, 0); + ADD_TO_STACK4(stack, socketRefP, 2); + ADD_TO_STACK4(stack, stub, 6); + ADD_TO_STACK4(stack, refCon, 10); + ADD_TO_STACK1(stack, socketProtocol, 14); + STACK_END(stack); + result = (Err) + (*sp->call68KFuncP)( sp->emulStateP, + PceNativeTrapNo(btLibTrapSocketCreate), + stack, 16 ); + /* swapOuts */ + SWAP2_NON_NULL_OUT(socketRefP); + } + FUNC_TAIL(BtLibSocketCreate); + EMIT_NAME("BtLibSocketCreate","'B','t','L','i','b','S','o','c','k','e','t','C','r','e','a','t','e'"); + return result; +} /* BtLibSocketCreate */ + +void +flipBtConnInfoArm268K( unsigned char* out, const BtLibSocketConnectInfoType* in ) +{ + write_unaligned32( out + 0, in->remoteDeviceP ); + write_unaligned16( out + 4, in->data.L2Cap.remotePsm ); + write_unaligned16( out + 6, in->data.L2Cap.minRemoteMtu ); + write_unaligned16( out + 8, in->data.L2Cap.localMtu ); +} + +/* from file BtLib.h */ + +void +flipBtSocketListenInfoArm268K( unsigned char* out, + const BtLibSocketListenInfoType* in) +{ + /* Some moron didn't put a type field in BtLibSocketListenInfoType. The + interpretation of the data depends on the protocol with which the + socket (param to BtLibSocketListen) was created. We *could* pass the + socket into this function and pull the protocol out, using that to + decide which overlapping union field to swap, but let's just hard-code + btLibL2CapProtocol (field data.L2Cap) since that's what I'm using.*/ + + write_unaligned16( out + 0, in->data.L2Cap.localPsm ); + write_unaligned16( out + 2, in->data.L2Cap.localMtu ); + write_unaligned16( out + 4, in->data.L2Cap.minRemoteMtu ); +} + +#endif /* XWFEATURE_BLUETOOTH */ diff --git a/xwords4/palm/pace_man.h b/xwords4/palm/pace_man.h index ef73830ce..1e99d695a 100644 --- a/xwords4/palm/pace_man.h +++ b/xwords4/palm/pace_man.h @@ -28,10 +28,15 @@ #include #include #include +#ifdef XWFEATURE_BLUETOOTH +# include +# include +#endif #include "pnostate.h" #include "xptypes.h" +void* memcpy( void* dest, const void* src, unsigned long n ); extern Int16 StrPrintF( Char* s, const Char* formatStr, ... ); extern Int16 StrVPrintF( Char* s, const Char* formatStr, _Palm_va_list arg ); extern Boolean SysHandleEvent( EventPtr eventP ); @@ -105,6 +110,19 @@ NetHostInfoPtr NetLibGetHostByName( UInt16 libRefNum, const Char* nameP, NetHostInfoBufPtr bufP, Int32 timeout, Err* errP ); +#ifdef XWFEATURE_BLUETOOTH +void flipBtConnInfoArm268K( unsigned char* out, const BtLibSocketConnectInfoType* in ); +void flipBtSocketListenInfoArm268K( unsigned char* out, + const BtLibSocketListenInfoType* in); + +# define SWAP_BTLIBSOCKETCONNECTINFOTYPE_ARM_TO_68K( out, in ) \ + flipBtConnInfoArm268K( out, in ) +# define SWAP_BTLIBSOCKETCONNECTINFOTYPE_68K_TO_ARM( out, in ) /* nothing for now */ +# define SWAP_BTLIBSOCKETLISTENINFOTYPE_ARM_TO_68K( out, in ) \ + flipBtSocketListenInfoArm268K( out, in ) +# define SWAP_BTLIBSOCKETLISTENINFOTYPE_68K_TO_ARM( out, in ) /* nothing for now */ +#endif /* XWFEATURE_BLUETOOTH */ + PNOState* getStorageLoc(); #define GET_CALLBACK_STATE() getStorageLoc() diff --git a/xwords4/palm/palmmain.h b/xwords4/palm/palmmain.h index 8c0d19d13..f8eb71810 100644 --- a/xwords4/palm/palmmain.h +++ b/xwords4/palm/palmmain.h @@ -375,6 +375,8 @@ enum { #ifdef XWFEATURE_COMBINEDAWG , DAWG_STORE_FEATURE #endif + , PACE_SCREEN_LIBMNGMT_FEATURE + , PACE_SCREEN_SOCKETPROC_FEATURE }; enum { WANTS_68K, WANTS_ARM };