Conflicts:
	src/sdl/iwadpicker_cocoa.mm
This commit is contained in:
Christoph Oelckers 2014-11-25 16:39:56 +01:00
commit a7a2d55695
61 changed files with 11883 additions and 482 deletions

View file

@ -28,6 +28,8 @@ endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
option( DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON )
option( OSX_COCOA_BACKEND "Use native Cocoa backend instead of SDL" ON )
if( CMAKE_SIZEOF_VOID_P MATCHES "8" )
set( X64 64 )
endif( CMAKE_SIZEOF_VOID_P MATCHES "8" )
@ -213,7 +215,9 @@ else( WIN32 )
if( NOT SDL_FOUND )
message( SEND_ERROR "SDL is required for building." )
endif( NOT SDL_FOUND )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SDL_LIBRARY}" )
if( NOT APPLE OR NOT OSX_COCOA_BACKEND )
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${SDL_LIBRARY}" )
endif( NOT APPLE OR NOT OSX_COCOA_BACKEND )
include_directories( "${SDL_INCLUDE_DIR}" )
find_path( FPU_CONTROL_DIR fpu_control.h )
@ -375,19 +379,19 @@ if( NOT NO_ASM )
set( ASM_FLAGS -f win32 -DWIN32 -i${CMAKE_CURRENT_SOURCE_DIR}/ )
endif( X64 )
endif( UNIX )
if( WIN32 )
if( WIN32 AND NOT X64 )
set( FIXRTEXT fixrtext )
else( WIN32 )
else( WIN32 AND NOT X64 )
set( FIXRTEXT "" )
endif( WIN32 )
endif( WIN32 AND NOT X64 )
message( STATUS "Selected assembler: ${ASSEMBLER}" )
MACRO( ADD_ASM_FILE indir infile )
set( ASM_OUTPUT_${infile} "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/zdoom.dir/${indir}/${infile}${ASM_OUTPUT_EXTENSION}" )
if( WIN32 )
if( WIN32 AND NOT X64 )
set( FIXRTEXT_${infile} COMMAND ${FIXRTEXT} "${ASM_OUTPUT_${infile}}" )
else( WIN32 )
else( WIN32 AND NOT X64 )
set( FIXRTEXT_${infile} COMMAND "" )
endif( WIN32 )
endif( WIN32 AND NOT X64 )
add_custom_command( OUTPUT ${ASM_OUTPUT_${infile}}
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/zdoom.dir/${indir}
COMMAND ${ASSEMBLER} ${ASM_FLAGS} -o"${ASM_OUTPUT_${infile}}" "${CMAKE_CURRENT_SOURCE_DIR}/${indir}/${infile}${ASM_SOURCE_EXTENSION}"
@ -446,9 +450,10 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
endif( PROFILE )
set( REL_CXX_FLAGS "-fno-rtti" )
if( NOT PROFILE )
if( NOT PROFILE AND NOT APPLE )
# On OS X frame pointers are required for exception handling, at least with Clang
set( REL_CXX_FLAGS "${REL_CXX_FLAGS} -fomit-frame-pointer" )
endif( NOT PROFILE )
endif( NOT PROFILE AND NOT APPLE )
set( CMAKE_CXX_FLAGS_RELEASE "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}" )
set( CMAKE_CXX_FLAGS_MINSIZEREL "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_MINSIZEREL}" )
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${REL_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" )
@ -579,22 +584,53 @@ set( PLAT_WIN32_SOURCES
win32/st_start.cpp
win32/win32gliface.cpp
win32/win32video.cpp )
set( PLAT_SDL_SOURCES
set( PLAT_SDL_SYSTEM_SOURCES
sdl/crashcatcher.c
sdl/hardware.cpp
sdl/i_cd.cpp
sdl/i_input.cpp
sdl/i_joystick.cpp
sdl/i_main.cpp
sdl/i_movie.cpp
sdl/i_system.cpp
sdl/sdlvideo.cpp
sdl/sdlglvideo.cpp
sdl/st_start.cpp )
set( PLAT_SDL_SPECIAL_SOURCES
sdl/i_gui.cpp
sdl/i_input.cpp
sdl/i_joystick.cpp
sdl/i_timer.cpp )
set( PLAT_MAC_SOURCES
sdl/SDLMain.m
sdl/iwadpicker_cocoa.mm
sdl/i_system_cocoa.mm )
set( PLAT_COCOA_SOURCES
cocoa/HID_Config_Utilities.c
cocoa/HID_Error_Handler.c
cocoa/HID_Name_Lookup.c
cocoa/HID_Queue_Utilities.c
cocoa/HID_Utilities.c
cocoa/IOHIDDevice_.c
cocoa/IOHIDElement_.c
cocoa/ImmrHIDUtilAddOn.c
cocoa/i_backend_cocoa.mm
cocoa/i_joystick.cpp
cocoa/i_timer.cpp
cocoa/zdoom.icns )
if( APPLE )
set( PLAT_SDL_SOURCES ${PLAT_SDL_SYSTEM_SOURCES} "${FMOD_LIBRARY}" )
if( OSX_COCOA_BACKEND )
set( PLAT_MAC_SOURCES ${PLAT_MAC_SOURCES} ${PLAT_COCOA_SOURCES} )
else( OSX_COCOA_BACKEND )
set( PLAT_MAC_SOURCES ${PLAT_MAC_SOURCES} ${PLAT_SDL_SPECIAL_SOURCES} sdl/SDLMain.m )
endif( OSX_COCOA_BACKEND )
set_source_files_properties( cocoa/zdoom.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources )
set_source_files_properties( "${FMOD_LIBRARY}" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks )
else( APPLE )
set( PLAT_SDL_SOURCES ${PLAT_SDL_SYSTEM_SOURCES} ${PLAT_SDL_SPECIAL_SOURCES} )
endif( APPLE )
if( WIN32 )
set( SYSTEM_SOURCES_DIR win32 )
set( SYSTEM_SOURCES ${PLAT_WIN32_SOURCES} )
@ -810,7 +846,7 @@ set( NOT_COMPILED_SOURCE_FILES
asm_x86_64/tmap3.s
)
add_executable( zdoom WIN32
add_executable( zdoom WIN32 MACOSX_BUNDLE
${HEADER_FILES}
${NOT_COMPILED_SOURCE_FILES}
__autostart.cpp
@ -1087,6 +1123,7 @@ add_executable( zdoom WIN32
oplsynth/opl_mus_player.cpp
oplsynth/dosbox/opl.cpp
oplsynth/OPL3.cpp
oplsynth/nukedopl3.cpp
resourcefiles/ancientzip.cpp
resourcefiles/file_7z.cpp
resourcefiles/file_grp.cpp
@ -1259,6 +1296,25 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
endif( SSE_MATTERS )
endif( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )
if( APPLE )
set_target_properties(zdoom PROPERTIES
LINK_FLAGS "-framework Carbon -framework Cocoa -framework IOKit -framework OpenGL"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/cocoa/zdoom-info.plist" )
# Fix fmod link so that it can be found in the app bundle.
find_program( OTOOL otool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" )
find_program( INSTALL_NAME_TOOL install_name_tool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin" )
execute_process( COMMAND "${OTOOL}" -L "${FMOD_LIBRARY}"
COMMAND grep "libfmodex.dylib (compat"
COMMAND head -n1
COMMAND awk "{print $1}"
OUTPUT_VARIABLE FMOD_LINK
OUTPUT_STRIP_TRAILING_WHITESPACE )
add_custom_command( TARGET zdoom POST_BUILD
COMMAND "${INSTALL_NAME_TOOL}" -change "${FMOD_LINK}" @executable_path/../Frameworks/libfmodex.dylib "$<TARGET_FILE:zdoom>"
COMMENT "Relinking FMOD Ex" )
endif( APPLE )
source_group("Assembly Files\\ia32" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_ia32/.+")
source_group("Assembly Files\\x86_64" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/asm_x86_64/.+")
source_group("Audio Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/sound/.+")
@ -1266,6 +1322,7 @@ source_group("Audio Files\\OPL Synth" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURC
source_group("Audio Files\\OPL Synth\\DOSBox" FILES oplsynth/dosbox/opl.cpp oplsynth/dosbox/opl.h)
source_group("Audio Files\\Timidity\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.h$")
source_group("Audio Files\\Timidity\\Source" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/timidity/.+\\.cpp$")
source_group("Cocoa Files" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/cocoa/.+")
source_group("Decorate++" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/thingdef/.+")
source_group("FraggleScript" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/fragglescript/.+")
source_group("Games\\Doom Game" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/g_doom/.+")

View file

@ -971,6 +971,7 @@ public:
FNameNoInit DamageType;
FNameNoInit DamageTypeReceived;
fixed_t DamageFactor;
fixed_t DamageMultiply;
FNameNoInit PainType;
FNameNoInit DeathType;

View file

@ -24,12 +24,14 @@ IMPLEMENT_POINTY_CLASS(DBot)
END_POINTERS
DBot::DBot ()
: DThinker(STAT_BOT)
{
Clear ();
}
void DBot::Clear ()
{
player = NULL;
angle = 0;
dest = NULL;
prev = NULL;
@ -64,6 +66,10 @@ void DBot::Serialize (FArchive &arc)
arc << savedyaw
<< savedpitch;
}
else if (SaveVersion >= 4516)
{
arc << player;
}
arc << angle
<< dest
@ -88,6 +94,22 @@ void DBot::Serialize (FArchive &arc)
<< oldy;
}
void DBot::Tick ()
{
Super::Tick ();
if (player->mo == NULL || bglobal.freeze)
{
return;
}
BotThinkCycles.Clock();
bglobal.m_Thinking = true;
bglobal.Think (player->mo, &netcmds[player - players][((gametic + 1)/ticdup)%BACKUPTICS]);
bglobal.m_Thinking = false;
BotThinkCycles.Unclock();
}
CVAR (Int, bot_next_color, 11, 0)
CVAR (Bool, bot_observer, false, 0)

View file

@ -14,6 +14,7 @@
#include "d_ticcmd.h"
#include "r_defs.h"
#include "a_pickups.h"
#include "stats.h"
#define FORWARDWALK 0x1900
#define FORWARDRUN 0x3200
@ -89,20 +90,22 @@ public:
void ClearPlayer (int playernum, bool keepTeam);
//(B_Game.c)
void Main (int buf);
void Main ();
void Init ();
void End();
bool SpawnBot (const char *name, int color = NOCOLOR);
bool LoadBots ();
void ForgetBots ();
void TryAddBot (BYTE **stream, int player);
void RemoveAllBots (bool fromlist);
void DestroyAllBots ();
bool LoadBots ();
void ForgetBots ();
//(B_Func.c)
bool Check_LOS (AActor *mobj1, AActor *mobj2, angle_t vangle);
void StartTravel ();
void FinishTravel ();
//(B_Think.c)
void Think (AActor *actor, ticcmd_t *cmd);
void WhatToGet (AActor *actor, AActor *item);
//(B_move.c)
@ -144,7 +147,6 @@ private:
bool SafeCheckPosition (AActor *actor, fixed_t x, fixed_t y, FCheckPosition &tm);
//(B_Think.c)
void Think (AActor *actor, ticcmd_t *cmd);
void ThinkForMove (AActor *actor, ticcmd_t *cmd);
void Set_enemy (AActor *actor);
@ -155,16 +157,18 @@ protected:
bool observer; //Consoleplayer is observer.
};
class DBot : public DObject
class DBot : public DThinker
{
DECLARE_CLASS(DBot,DObject)
DECLARE_CLASS(DBot,DThinker)
HAS_OBJECT_POINTERS
public:
DBot ();
void Clear ();
void Serialize (FArchive &arc);
void Tick ();
player_t *player;
angle_t angle; // The wanted angle that the bot try to get every tic.
// (used to get a smooth view movement)
TObjPtr<AActor> dest; // Move Destination.
@ -205,6 +209,7 @@ public:
//Externs
extern FCajunMaster bglobal;
extern cycle_t BotThinkCycles, BotSupportCycles;
EXTERN_CVAR (Float, bot_flag_return_time)
EXTERN_CVAR (Int, bot_next_color)

View file

@ -402,7 +402,7 @@ AActor *FCajunMaster::Find_enemy (AActor *bot)
&& bot != client->mo)
{
if (Check_LOS (bot, client->mo, vangle)) //Here's a strange one, when bot is standing still, the P_CheckSight within Check_LOS almost always returns false. tought it should be the same checksight as below but.. (below works) something must be fuckin wierd screded up.
//if(P_CheckSight( bot, players[count].mo))
//if(P_CheckSight(bot, players[count].mo))
{
temp = P_AproxDistance (client->mo->x - bot->x,
client->mo->y - bot->y);
@ -552,3 +552,25 @@ bool FCajunMaster::SafeCheckPosition (AActor *actor, fixed_t x, fixed_t y, FChec
actor->flags = savedFlags;
return res;
}
void FCajunMaster::StartTravel ()
{
for (int i = 0; i < MAXPLAYERS; ++i)
{
if (players[i].Bot != NULL)
{
players[i].Bot->ChangeStatNum (STAT_TRAVELLING);
}
}
}
void FCajunMaster::FinishTravel ()
{
for (int i = 0; i < MAXPLAYERS; ++i)
{
if (players[i].Bot != NULL)
{
players[i].Bot->ChangeStatNum (STAT_BOT);
}
}
}

View file

@ -94,71 +94,46 @@ FCajunMaster::~FCajunMaster()
ForgetBots();
}
//This function is called every tick (from g_game.c),
//send bots into thinking (+more).
void FCajunMaster::Main (int buf)
//This function is called every tick (from g_game.c).
void FCajunMaster::Main ()
{
int i;
BotThinkCycles.Reset();
if (demoplayback)
if (demoplayback || gamestate != GS_LEVEL || consoleplayer != Net_Arbitrator)
return;
if (gamestate != GS_LEVEL)
return;
m_Thinking = true;
//Think for bots.
if (botnum)
//Add new bots?
if (wanted_botnum > botnum && !freeze)
{
BotThinkCycles.Clock();
for (i = 0; i < MAXPLAYERS; i++)
if (t_join == ((wanted_botnum - botnum) * SPAWN_DELAY))
{
if (playeringame[i] && players[i].mo && !freeze && players[i].Bot != NULL)
Think (players[i].mo, &netcmds[i][buf]);
if (!SpawnBot (getspawned[spawn_tries]))
wanted_botnum--;
spawn_tries++;
}
BotThinkCycles.Unclock();
t_join--;
}
if (consoleplayer == Net_Arbitrator)
//Check if player should go observer. Or un observe
if (bot_observer && !observer && !netgame)
{
//Add new bots?
if (wanted_botnum > botnum && !freeze)
{
if (t_join == ((wanted_botnum - botnum) * SPAWN_DELAY))
{
if (!SpawnBot (getspawned[spawn_tries]))
wanted_botnum--;
spawn_tries++;
}
t_join--;
}
//Check if player should go observer. Or un observe
if (bot_observer && !observer && !netgame)
{
Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName());
observer = true;
players[consoleplayer].mo->UnlinkFromWorld ();
players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY;
players[consoleplayer].mo->flags2 |= MF2_FLY;
players[consoleplayer].mo->LinkToWorld ();
}
else if (!bot_observer && observer && !netgame) //Go back
{
Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName());
observer = false;
players[consoleplayer].mo->UnlinkFromWorld ();
players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY;
players[consoleplayer].mo->flags2 &= ~MF2_FLY;
players[consoleplayer].mo->LinkToWorld ();
}
Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName());
observer = true;
players[consoleplayer].mo->UnlinkFromWorld ();
players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY;
players[consoleplayer].mo->flags2 |= MF2_FLY;
players[consoleplayer].mo->LinkToWorld ();
}
else if (!bot_observer && observer && !netgame) //Go back
{
Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName());
observer = false;
players[consoleplayer].mo->UnlinkFromWorld ();
players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY;
players[consoleplayer].mo->flags2 &= ~MF2_FLY;
players[consoleplayer].mo->LinkToWorld ();
}
m_Thinking = false;
}
void FCajunMaster::Init ()
@ -199,18 +174,13 @@ void FCajunMaster::End ()
//Arrange wanted botnum and their names, so they can be spawned next level.
getspawned.Clear();
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].Bot != NULL)
{
if (deathmatch)
{
getspawned.Push(players[i].userinfo.GetName());
}
}
}
if (deathmatch)
{
for (i = 0; i < MAXPLAYERS; i++)
{
getspawned.Push(players[i].userinfo.GetName());
}
wanted_botnum = botnum;
}
}
@ -400,7 +370,7 @@ bool FCajunMaster::DoAddBot (BYTE *info, botskill_t skill)
multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost).
players[bnum].Bot = new DBot;
GC::WriteBarrier (players[bnum].Bot);
players[bnum].Bot->player = &players[bnum];
players[bnum].Bot->skill = skill;
playeringame[bnum] = true;
players[bnum].mo = NULL;
@ -426,7 +396,7 @@ void FCajunMaster::RemoveAllBots (bool fromlist)
for (i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i] && players[i].Bot != NULL)
if (players[i].Bot != NULL)
{
// If a player is looking through this bot's eyes, make him
// look through his own eyes instead.
@ -456,18 +426,6 @@ void FCajunMaster::RemoveAllBots (bool fromlist)
botnum = 0;
}
void FCajunMaster::DestroyAllBots ()
{
for (int i = 0; i < MAXPLAYERS; ++i)
{
if (players[i].Bot != NULL)
{
players[i].Bot->Destroy ();
players[i].Bot = NULL;
}
}
}
//------------------
//Reads data for bot from

View file

@ -230,7 +230,11 @@ const char *KeyNames[NUM_KEYS] =
NULL, NULL, NULL, NULL, NULL, "pause", NULL, "home", //C0
"uparrow", "pgup", NULL, "leftarrow",NULL, "rightarrow",NULL, "end", //C8
"downarrow","pgdn", "ins", "del", NULL, NULL, NULL, NULL, //D0
#ifdef __APPLE__
NULL, NULL, NULL, "command", NULL, "apps", "power", "sleep", //D8
#else // !__APPLE__
NULL, NULL, NULL, "lwin", "rwin", "apps", "power", "sleep", //D8
#endif // __APPLE__
NULL, NULL, NULL, "wake", NULL, "search", "favorites","refresh", //E0
"webstop", "webforward","webback", "mycomputer","mail", "mediaselect",NULL, NULL, //E8
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //F0

View file

@ -1426,7 +1426,11 @@ static bool C_HandleKey (event_t *ev, BYTE *buffer, int len)
case 'V':
TabbedLast = false;
TabbedList = false;
#ifdef __APPLE__
if (ev->data3 & GKM_META)
#else // !__APPLE__
if (ev->data3 & GKM_CTRL)
#endif // __APPLE__
{
if (data1 == 'C')
{ // copy to clipboard

View file

@ -0,0 +1,926 @@
// File: HID_Config_Utilities.c
// Abstract: Implementation of the HID configuration utilities
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#define LOG_SCORING 0
#include <stdlib.h> // malloc
#include <time.h> // clock
#include <AssertMacros.h>
#include "HID_Utilities_External.h"
// ---------------------------------
// polls single device's elements for a change greater than kPercentMove. Times out after given time
// returns 1 and pointer to element if found
// returns 0 and NULL for both parameters if not found
unsigned char HIDConfigureSingleDeviceAction(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef *outIOHIDElementRef, float timeout) {
if ( !inIOHIDDeviceRef ) {
return (0);
}
if ( 0 == HIDHaveDeviceList() ) { // if we do not have a device list
return (0); // return 0
}
Boolean found = FALSE;
// build list of device and elements to save current values
int maxElements = HIDCountDeviceElements(inIOHIDDeviceRef, kHIDElementTypeInput);
int *saveValueArray = (int *) calloc( maxElements, sizeof(int) ); // 2D array to save values
// store initial values on first pass / compare to initial value on subsequent passes
Boolean first = TRUE;
// get all the elements from this device
CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(inIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone);
// if that worked...
if ( elementCFArrayRef ) {
clock_t start = clock(), end;
// poll all devices and elements
while ( !found ) {
int currElementIndex = 0;
CFIndex idx, cnt = CFArrayGetCount(elementCFArrayRef);
for ( idx = 0; idx < cnt; idx++ ) {
*outIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(elementCFArrayRef, idx);
if ( !*outIOHIDElementRef ) {
continue;
}
// is this an input element?
IOHIDElementType type = IOHIDElementGetType(*outIOHIDElementRef);
switch ( type ) {
// these types are inputs
case kIOHIDElementTypeInput_Misc:
case kIOHIDElementTypeInput_Button:
case kIOHIDElementTypeInput_Axis:
case kIOHIDElementTypeInput_ScanCodes:
default:
{
break;
}
case kIOHIDElementTypeOutput:
case kIOHIDElementTypeFeature:
case kIOHIDElementTypeCollection:
{
*outIOHIDElementRef = NULL; // these types are not ( Skip them )
break;
}
} /* switch */
if ( !*outIOHIDElementRef ) {
continue; // skip this element
}
// get this elements current value
int value = 0; // default value is zero
IOHIDValueRef tIOHIDValueRef;
IOReturn ioReturn = IOHIDDeviceGetValue(inIOHIDDeviceRef, *outIOHIDElementRef, &tIOHIDValueRef);
if ( kIOReturnSuccess == ioReturn ) {
value = IOHIDValueGetScaledValue(tIOHIDValueRef, kIOHIDValueScaleTypePhysical);
}
if ( first ) {
saveValueArray[currElementIndex] = value;
} else {
CFIndex min = IOHIDElementGetLogicalMin(*outIOHIDElementRef);
CFIndex max = IOHIDElementGetLogicalMax(*outIOHIDElementRef);
int initialValue = saveValueArray[currElementIndex];
int delta = (float)(max - min) * kPercentMove * 0.01;
// is the new value within +/- delta of the initial value?
if ( ( (initialValue + delta) < value ) || ( (initialValue - delta) > value ) ) {
found = 1; // ( yes! ) mark as found
break;
}
} // if ( first )
currElementIndex++; // bump element index
} // next idx
first = FALSE; // no longer the first pass
// are we done?
end = clock();
double secs = (double)(end - start) / CLOCKS_PER_SEC;
if ( secs > timeout ) {
break; // ( yes ) timeout
}
} // while ( !found )
CFRelease(elementCFArrayRef);
} // if ( elementCFArrayRef )
// return device and element moved
if ( found ) {
return (1);
} else {
*outIOHIDElementRef = NULL;
return (0);
}
} // HIDConfigureSingleDeviceAction
//*************************************************************************
//
// HIDConfigureAction( outIOHIDDeviceRef, outIOHIDElementRef, inTimeout )
//
// Purpose: polls all devices and elements for a change greater than kPercentMove.
// Times out after given time returns 1 and pointer to device and element
// if found; returns 0 and NULL for both parameters if not found
//
// Inputs: outIOHIDDeviceRef - address where to store the device
// outIOHIDElementRef - address where to store the element
// inTimeout - the timeout
// Returns: Boolean - if successful
// outIOHIDDeviceRef - the device
// outIOHIDElementRef - the element
//
Boolean HIDConfigureAction(IOHIDDeviceRef *outIOHIDDeviceRef, IOHIDElementRef *outIOHIDElementRef, float inTimeout) {
// param error?
if ( !outIOHIDDeviceRef || !outIOHIDElementRef ) {
return (0);
}
if ( !gDeviceCFArrayRef ) { // if we do not have a device list
// and we can't build another list
if ( !HIDBuildDeviceList(0, 0) || !gDeviceCFArrayRef ) {
return (FALSE); // bail
}
}
IOHIDDeviceRef tIOHIDDeviceRef;
IOHIDElementRef tIOHIDElementRef;
// remember when we start; used to calculate timeout
clock_t start = clock(), end;
// determine the maximum number of elements
CFIndex maxElements = 0;
CFIndex devIndex, devCount = CFArrayGetCount(gDeviceCFArrayRef);
for ( devIndex = 0; devIndex < devCount; devIndex++ ) {
tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef, devIndex);
if ( !tIOHIDDeviceRef ) {
continue; // skip this one
}
CFIndex count = HIDCountDeviceElements(tIOHIDDeviceRef, kHIDElementTypeInput);
if ( count > maxElements ) {
maxElements = count;
}
}
// allocate an array of int's in which to store devCount * maxElements values
double *saveValueArray = (double *) calloc( devCount * maxElements, sizeof(double) ); // clear 2D array to save values
// on first pass store initial values / compare current values to initial values on subsequent passes
Boolean found = FALSE, first = TRUE;
while ( !found ) {
double maxDeltaPercent = 0; // we want to find the one that moves the most ( percentage wise )
for ( devIndex = 0; devIndex < devCount; devIndex++ ) {
tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef, devIndex);
if ( !tIOHIDDeviceRef ) {
continue; // skip this one
}
#ifdef DEBUG
long vendorID = IOHIDDevice_GetVendorID(tIOHIDDeviceRef);
long productID = IOHIDDevice_GetProductID(tIOHIDDeviceRef);
#endif
gElementCFArrayRef = IOHIDDeviceCopyMatchingElements(tIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone);
if ( gElementCFArrayRef ) {
CFIndex eleIndex, eleCount = CFArrayGetCount(gElementCFArrayRef);
for ( eleIndex = 0; eleIndex < eleCount; eleIndex++ ) {
tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gElementCFArrayRef, eleIndex);
if ( !tIOHIDElementRef ) {
continue;
}
IOHIDElementType tIOHIDElementType = IOHIDElementGetType(tIOHIDElementRef);
// only care about inputs (no outputs or features)
if ( tIOHIDElementType <= kIOHIDElementTypeInput_ScanCodes ) {
if ( IOHIDElementIsArray(tIOHIDElementRef) ) {
//printf( "ARRAY!\n" );
continue; // skip array elements
}
uint32_t usagePage = IOHIDElementGetUsagePage(tIOHIDElementRef);
uint32_t usage = IOHIDElementGetUsage(tIOHIDElementRef);
uint32_t reportCount = IOHIDElementGetReportCount(tIOHIDElementRef);
#ifdef DEBUG
if ( first ) {
IOHIDElementCookie cookie = IOHIDElementGetCookie(tIOHIDElementRef);
printf("%s, dev: {ref:%p, ven: 0x%08lX, pro: 0x%08lX}, ele: {ref:%p, cookie: %p, usage:%04lX:%08lX}\n",
__PRETTY_FUNCTION__,
tIOHIDDeviceRef,
vendorID,
productID,
tIOHIDElementRef,
cookie,
(long unsigned int) usagePage,
(long unsigned int) usage);
fflush(stdout);
if ( (0x054C == vendorID) && (0x0268 == productID) && (0x001E == (UInt32) cookie) ) {
//printf( "DING!\n" );
}
}
#endif
#if 1 // work-around for IOHIDValueGetScaledValue crash (when element report count > 1)
if ( reportCount > 1 ) {
//printf( "REPORT!\n" );
continue; // skip reports
}
#endif
// ignore PID elements and arrays
if ( (kHIDPage_PID != usagePage) && (((uint32_t)-1) != usage) ) {
// get this elements current value
double value = 0.0; // default value is zero
IOHIDValueRef tIOHIDValueRef;
IOReturn ioReturn = IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &tIOHIDValueRef);
if ( kIOReturnSuccess == ioReturn ) {
value = IOHIDValueGetScaledValue(tIOHIDValueRef, kIOHIDValueScaleTypePhysical);
}
if ( first ) {
saveValueArray[(devIndex * maxElements) + eleIndex] = value;
} else {
double initialValue = saveValueArray[(devIndex * maxElements) + eleIndex];
CFIndex valueMin = IOHIDElementGetPhysicalMin(tIOHIDElementRef);
CFIndex valueMax = IOHIDElementGetPhysicalMax(tIOHIDElementRef);
double deltaPercent = fabs( (initialValue - value) * 100.0 / (valueMax - valueMin) );
#if 0 // debug code useful to dump out value info for specific (vendorID, productID, usagePage and usage) device
if ( !first ) {
// Device: 0x13b6a0 = { Logitech Inc. - WingMan Force 3D, vendorID: 0x046D, productID: 0xC283,
// usage: 0x0001:0x0004, "Generic Desktop Joystick"
if ( (vendorID == 0x046D) && (productID == 0xC283) ) {
if ( (kHIDPage_GenericDesktop == usagePage) && (kHIDUsage_GD_Rz == usage) ) {
printf("initial: %6.2f, value: %6.2f, diff: %6.2f, delta percent: %6.2f!\n",
initialValue,
value,
fabs(initialValue - value),
deltaPercent);
}
}
}
deltaPercent = 0.0;
#endif
if ( deltaPercent >= kPercentMove ) {
found = TRUE;
if ( deltaPercent > maxDeltaPercent ) {
maxDeltaPercent = deltaPercent;
*outIOHIDDeviceRef = tIOHIDDeviceRef;
*outIOHIDElementRef = tIOHIDElementRef;
}
break;
}
} // if first
} // if usage
} // if type
} // for elements...
CFRelease(gElementCFArrayRef);
gElementCFArrayRef = NULL;
} // if ( gElementCFArrayRef )
if ( found ) {
// HIDDumpElementInfo( tIOHIDElementRef );
break; // DONE!
}
} // for devices
first = FALSE; // no longer the first pass
// are we done?
end = clock();
double secs = (double)(end - start) / CLOCKS_PER_SEC;
if ( secs > inTimeout ) {
break; // ( yes ) timeout
}
} // while ( !found )
// return device and element moved
if ( !found ) {
*outIOHIDDeviceRef = NULL;
*outIOHIDElementRef = NULL;
}
return (found);
} // HIDConfigureAction
//*************************************************************************
//
// HIDSaveElementPref( inKeyCFStringRef, inAppCFStringRef, inIOHIDDeviceRef, inIOHIDElementRef )
//
// Purpose: Save the device & element values into the specified key in the specified applications preferences
//
// Inputs: inKeyCFStringRef - the preference key
// inAppCFStringRef - the application identifier
// inIOHIDDeviceRef - the device
// inIOHIDElementRef - the element
// Returns: Boolean - if successful
//
Boolean HIDSaveElementPref(const CFStringRef inKeyCFStringRef,
CFStringRef inAppCFStringRef,
IOHIDDeviceRef inIOHIDDeviceRef,
IOHIDElementRef inIOHIDElementRef) {
Boolean success = FALSE;
if ( inKeyCFStringRef && inAppCFStringRef && inIOHIDDeviceRef && inIOHIDElementRef ) {
long vendorID = IOHIDDevice_GetVendorID(inIOHIDDeviceRef);
require(vendorID, Oops);
long productID = IOHIDDevice_GetProductID(inIOHIDDeviceRef);
require(productID, Oops);
long locID = IOHIDDevice_GetLocationID(inIOHIDDeviceRef);
require(locID, Oops);
uint32_t usagePage = IOHIDDevice_GetUsagePage(inIOHIDDeviceRef);
uint32_t usage = IOHIDDevice_GetUsage(inIOHIDDeviceRef);
if ( !usagePage || !usage ) {
usagePage = IOHIDDevice_GetPrimaryUsagePage(inIOHIDDeviceRef);
usage = IOHIDDevice_GetPrimaryUsage(inIOHIDDeviceRef);
}
require(usagePage && usage, Oops);
uint32_t usagePageE = IOHIDElementGetUsagePage(inIOHIDElementRef);
uint32_t usageE = IOHIDElementGetUsage(inIOHIDElementRef);
IOHIDElementCookie eleCookie = IOHIDElementGetCookie(inIOHIDElementRef);
CFStringRef prefCFStringRef = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
CFSTR("d:{v:%ld, p:%ld, l:%ld, p:%ld, u:%ld}, e:{p:%ld, u:%ld, c:%ld}"),
vendorID, productID, locID, usagePage, usage,
usagePageE, usageE, eleCookie);
if ( prefCFStringRef ) {
CFPreferencesSetAppValue(inKeyCFStringRef, prefCFStringRef, inAppCFStringRef);
CFRelease(prefCFStringRef);
success = TRUE;
}
}
Oops: ;
return (success);
} // HIDSaveElementPref
//*************************************************************************
//
// HIDRestoreElementPref( inKeyCFStringRef, inAppCFStringRef, outIOHIDDeviceRef, outIOHIDElementRef )
//
// Purpose: Find the specified preference in the specified application
//
// Inputs: inKeyCFStringRef - the preference key
// inAppCFStringRef - the application identifier
// outIOHIDDeviceRef - address where to restore the device
// outIOHIDElementRef - address where to restore the element
// Returns: Boolean - if successful
// outIOHIDDeviceRef - the device
// outIOHIDElementRef - the element
//
Boolean HIDRestoreElementPref(CFStringRef inKeyCFStringRef,
CFStringRef inAppCFStringRef,
IOHIDDeviceRef * outIOHIDDeviceRef,
IOHIDElementRef *outIOHIDElementRef) {
Boolean found = FALSE;
if ( inKeyCFStringRef && inAppCFStringRef && outIOHIDDeviceRef && outIOHIDElementRef ) {
CFPropertyListRef prefCFPropertyListRef = CFPreferencesCopyAppValue(inKeyCFStringRef, inAppCFStringRef);
if ( prefCFPropertyListRef ) {
if ( CFStringGetTypeID() == CFGetTypeID(prefCFPropertyListRef) ) {
char buffer[256];
if ( CFStringGetCString( (CFStringRef) prefCFPropertyListRef, buffer, sizeof(buffer),
kCFStringEncodingUTF8 ) )
{
HID_info_rec searchHIDInfo;
int count = sscanf(buffer,
"d:{v:%d, p:%d, l:%d, p:%d, u:%d}, e:{p:%d, u:%d, c:%ld}",
&searchHIDInfo.device.vendorID,
&searchHIDInfo.device.productID,
&searchHIDInfo.device.locID,
&searchHIDInfo.device.usagePage,
&searchHIDInfo.device.usage,
&searchHIDInfo.element.usagePage,
&searchHIDInfo.element.usage,
(long *) &searchHIDInfo.element.cookie);
if ( 8 == count ) { // if we found all eight parameters…
// and can find a device & element that matches these…
if ( HIDFindDeviceAndElement(&searchHIDInfo, outIOHIDDeviceRef, outIOHIDElementRef) ) {
found = TRUE;
}
}
}
} else {
// We found the entry with this key but it's the wrong type; delete it.
CFPreferencesSetAppValue(inKeyCFStringRef, NULL, inAppCFStringRef);
(void) CFPreferencesAppSynchronize(inAppCFStringRef);
}
CFRelease(prefCFPropertyListRef);
}
}
return (found);
} // HIDRestoreElementPref
//*************************************************************************
//
// HIDFindDeviceAndElement( inSearchInfo, outFoundDevice, outFoundElement )
//
// Purpose: find the closest matching device and element for this action
//
// Notes: matches device: serial, vendorID, productID, location, inUsagePage, usage
// matches element: cookie, inUsagePage, usage,
//
// Inputs: inSearchInfo - the device & element info we searching for
// outFoundDevice - the address of the best matching device
// outFoundElement - the address of the best matching element
//
// Returns: Boolean - TRUE if we find a match
// outFoundDevice - the best matching device
// outFoundElement - the best matching element
//
Boolean HIDFindDeviceAndElement(const HID_info_rec *inSearchInfo, IOHIDDeviceRef *outFoundDevice, IOHIDElementRef *outFoundElement) {
Boolean result = FALSE;
IOHIDDeviceRef bestIOHIDDeviceRef = NULL;
IOHIDElementRef bestIOHIDElementRef = NULL;
long bestScore = 0;
CFIndex devIndex, devCount = CFArrayGetCount(gDeviceCFArrayRef);
for ( devIndex = 0; devIndex < devCount; devIndex++ ) {
long deviceScore = 1;
IOHIDDeviceRef tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef, devIndex);
if ( !tIOHIDDeviceRef ) {
continue;
}
// match vendorID, productID (+10, +8)
if ( inSearchInfo->device.vendorID ) {
long vendorID = IOHIDDevice_GetVendorID(tIOHIDDeviceRef);
if ( vendorID ) {
if ( inSearchInfo->device.vendorID == vendorID ) {
deviceScore += 10;
if ( inSearchInfo->device.productID ) {
long productID = IOHIDDevice_GetProductID(tIOHIDDeviceRef);
if ( productID ) {
if ( inSearchInfo->device.productID == productID ) {
deviceScore += 8;
} // if ( inSearchInfo->device.productID == productID )
} // if ( productID )
} // if ( inSearchInfo->device.productID )
} // if (inSearchInfo->device.vendorID == vendorID)
} // if vendorID
} // if search->device.vendorID
// match usagePage & usage (+9)
if ( inSearchInfo->device.usagePage && inSearchInfo->device.usage ) {
uint32_t usagePage = IOHIDDevice_GetUsagePage(tIOHIDDeviceRef) ;
uint32_t usage = IOHIDDevice_GetUsage(tIOHIDDeviceRef);
if ( !usagePage || !usage ) {
usagePage = IOHIDDevice_GetPrimaryUsagePage(tIOHIDDeviceRef);
usage = IOHIDDevice_GetPrimaryUsage(tIOHIDDeviceRef);
}
if ( usagePage ) {
if ( inSearchInfo->device.usagePage == usagePage ) {
if ( usage ) {
if ( inSearchInfo->device.usage == usage ) {
deviceScore += 9;
} // if ( inSearchInfo->usage == usage )
} // if ( usage )
} // if ( inSearchInfo->usagePage == usagePage )
} // if ( usagePage )
} // if ( inSearchInfo->usagePage && inSearchInfo->usage )
// match location ID (+5)
if ( inSearchInfo->device.locID ) {
long locID = IOHIDDevice_GetLocationID(tIOHIDDeviceRef);
if ( locID ) {
if ( inSearchInfo->device.locID == locID ) {
deviceScore += 5;
}
}
}
// iterate over all elements of this device
gElementCFArrayRef = IOHIDDeviceCopyMatchingElements(tIOHIDDeviceRef, NULL, 0);
if ( gElementCFArrayRef ) {
CFIndex eleIndex, eleCount = CFArrayGetCount(gElementCFArrayRef);
for ( eleIndex = 0; eleIndex < eleCount; eleIndex++ ) {
IOHIDElementRef tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gElementCFArrayRef, eleIndex);
if ( !tIOHIDElementRef ) {
continue;
}
long score = deviceScore;
// match usage page, usage & cookie
if ( inSearchInfo->element.usagePage && inSearchInfo->element.usage ) {
uint32_t usagePage = IOHIDElementGetUsagePage(tIOHIDElementRef);
if ( inSearchInfo->element.usagePage == usagePage ) {
uint32_t usage = IOHIDElementGetUsage(tIOHIDElementRef);
if ( inSearchInfo->element.usage == usage ) {
score += 5;
IOHIDElementCookie cookie = IOHIDElementGetCookie(tIOHIDElementRef);
if ( inSearchInfo->element.cookie == cookie ) {
score += 4;
} // cookies match
} else {
score = 0;
} // usages match
} else {
score = 0;
} // usage pages match
} // if ( search usage page & usage )
#if LOG_SCORING
if ( kHIDPage_KeyboardOrKeypad != tElementRef->usagePage ) { // skip keyboards here
printf("%s: ( %ld:%ld )-I-Debug, score: %ld\t",
__PRETTY_FUNCTION__,
inSearchInfo->element.usagePage,
inSearchInfo->element.usage,
score);
HIDPrintElement(tIOHIDElementRef);
}
#endif // LOG_SCORING
if ( score > bestScore ) {
bestIOHIDDeviceRef = tIOHIDDeviceRef;
bestIOHIDElementRef = tIOHIDElementRef;
bestScore = score;
#if LOG_SCORING
printf("%s: ( %ld:%ld )-I-Debug, better score: %ld\t",
__PRETTY_FUNCTION__,
inSearchInfo->element.usagePage,
inSearchInfo->element.usage,
score);
HIDPrintElement(bestIOHIDElementRef);
#endif // LOG_SCORING
}
} // for elements...
CFRelease(gElementCFArrayRef);
gElementCFArrayRef = NULL;
} // if ( gElementCFArrayRef )
} // for ( devIndex = 0; devIndex < devCount; devIndex++ )
if ( bestIOHIDDeviceRef || bestIOHIDElementRef ) {
*outFoundDevice = bestIOHIDDeviceRef;
*outFoundElement = bestIOHIDElementRef;
#if LOG_SCORING
printf("%s: ( %ld:%ld )-I-Debug, best score: %ld\t",
__PRETTY_FUNCTION__,
inSearchInfo->element.usagePage,
inSearchInfo->element.usage,
bestScore);
HIDPrintElement(bestIOHIDElementRef);
#endif // LOG_SCORING
result = TRUE;
}
return (result);
} // HIDFindDeviceAndElement
// ---------------------------------
// takes input records, save required info
// assume file is open and at correct position.
// will always write to file (if file exists) size of HID_info_rec, even if device and or element is bad
void HIDSaveElementConfig(FILE *fileRef, IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef, int actionCookie) {
// must save:
// actionCookie
// Device: serial,vendorID, productID, location, usagePage, usage
// Element: cookie, usagePage, usage,
HID_info_rec hidInfoRec;
HIDSetElementConfig(&hidInfoRec, inIOHIDDeviceRef, inIOHIDElementRef, actionCookie);
// write to file
if ( fileRef ) {
fwrite( (void *)&hidInfoRec, sizeof(HID_info_rec), 1, fileRef );
}
} // HIDSaveElementConfig
// ---------------------------------
// take file, read one record (assume file position is correct and file is open)
// search for matching device
// return pDevice, pElement and cookie for action
int HIDRestoreElementConfig(FILE *fileRef, IOHIDDeviceRef *outIOHIDDeviceRef, IOHIDElementRef *outIOHIDElementRef) {
// Device: serial,vendorID, productID, location, usagePage, usage
// Element: cookie, usagePage, usage,
HID_info_rec hidInfoRec;
fread( (void *) &hidInfoRec, 1, sizeof(HID_info_rec), fileRef );
return ( HIDGetElementConfig(&hidInfoRec, outIOHIDDeviceRef, outIOHIDElementRef) );
} // HIDRestoreElementConfig
// ---------------------------------
// Set up a config record for saving
// takes an input records, returns record user can save as they want
// Note: the save rec must be pre-allocated by the calling app and will be filled out
void HIDSetElementConfig(HID_info_ptr inHIDInfoPtr,
IOHIDDeviceRef inIOHIDDeviceRef,
IOHIDElementRef inIOHIDElementRef,
int actionCookie) {
// must save:
// actionCookie
// Device: serial,vendorID, productID, location, usagePage, usage
// Element: cookie, usagePage, usage,
inHIDInfoPtr->actionCookie = actionCookie;
// device
// need to add serial number when I have a test case
if ( inIOHIDDeviceRef && inIOHIDElementRef ) {
inHIDInfoPtr->device.vendorID = IOHIDDevice_GetVendorID(inIOHIDDeviceRef);
inHIDInfoPtr->device.productID = IOHIDDevice_GetProductID(inIOHIDDeviceRef);
inHIDInfoPtr->device.locID = IOHIDDevice_GetLocationID(inIOHIDDeviceRef);
inHIDInfoPtr->device.usage = IOHIDDevice_GetUsage(inIOHIDDeviceRef);
inHIDInfoPtr->device.usagePage = IOHIDDevice_GetUsagePage(inIOHIDDeviceRef);
inHIDInfoPtr->element.usagePage = IOHIDElementGetUsagePage(inIOHIDElementRef);
inHIDInfoPtr->element.usage = IOHIDElementGetUsage(inIOHIDElementRef);
inHIDInfoPtr->element.minReport = IOHIDElement_GetCalibrationSaturationMin(inIOHIDElementRef);
inHIDInfoPtr->element.maxReport = IOHIDElement_GetCalibrationSaturationMax(inIOHIDElementRef);
inHIDInfoPtr->element.cookie = IOHIDElementGetCookie(inIOHIDElementRef);
} else {
inHIDInfoPtr->device.vendorID = 0;
inHIDInfoPtr->device.productID = 0;
inHIDInfoPtr->device.locID = 0;
inHIDInfoPtr->device.usage = 0;
inHIDInfoPtr->device.usagePage = 0;
inHIDInfoPtr->element.usagePage = 0;
inHIDInfoPtr->element.usage = 0;
inHIDInfoPtr->element.minReport = 0;
inHIDInfoPtr->element.maxReport = 0;
inHIDInfoPtr->element.cookie = 0;
}
} // HIDSetElementConfig
// ---------------------------------
#if 0 // debug utility function to dump config record
void HIDDumpConfig(HID_info_ptr inHIDInfoPtr) {
printf(
"Config Record for action: %d\n\t vendor: %d product: %d location: %d\n\t usage: %d usagePage: %d\n\t element.usagePage: %d element.usage: %d\n\t minReport: %d maxReport: %d\n\t cookie: %d\n",
inHIDInfoPtr->actionCookie,
inHIDInfoPtr->device.vendorID,
inHIDInfoPtr->device.productID,
inHIDInfoPtr->locID,
inHIDInfoPtr->usage,
inHIDInfoPtr->usagePage,
inHIDInfoPtr->element.usagePage,
inHIDInfoPtr->element.usage,
inHIDInfoPtr->minReport,
inHIDInfoPtr->maxReport,
inHIDInfoPtr->cookie);
} // HIDDumpConfig
#endif // 0
// ---------------------------------
// Get matching element from config record
// takes a pre-allocated and filled out config record
// search for matching device
// return pDevice, pElement and cookie for action
int HIDGetElementConfig(HID_info_ptr inHIDInfoPtr, IOHIDDeviceRef *outIOHIDDeviceRef, IOHIDElementRef *outIOHIDElementRef) {
if ( !inHIDInfoPtr->device.locID && !inHIDInfoPtr->device.vendorID && !inHIDInfoPtr->device.productID && !inHIDInfoPtr->device.usage
&& !inHIDInfoPtr->device.usagePage ) //
{ //
// early out
*outIOHIDDeviceRef = NULL;
*outIOHIDElementRef = NULL;
return (inHIDInfoPtr->actionCookie);
}
IOHIDDeviceRef tIOHIDDeviceRef, foundIOHIDDeviceRef = NULL;
IOHIDElementRef tIOHIDElementRef, foundIOHIDElementRef = NULL;
CFIndex devIdx, devCnt, idx, cnt;
// compare to current device list for matches
// look for device
if ( inHIDInfoPtr->device.locID && inHIDInfoPtr->device.vendorID && inHIDInfoPtr->device.productID ) { // look for specific device
// type plug in to same port
devCnt = CFArrayGetCount(gDeviceCFArrayRef);
for ( devIdx = 0; devIdx < devCnt; devIdx++ ) {
tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef, devIdx);
if ( !tIOHIDDeviceRef ) {
continue; // skip this device
}
long locID = IOHIDDevice_GetLocationID(tIOHIDDeviceRef);
long vendorID = IOHIDDevice_GetVendorID(tIOHIDDeviceRef);
long productID = IOHIDDevice_GetProductID(tIOHIDDeviceRef);
if ( (inHIDInfoPtr->device.locID == locID)
&& (inHIDInfoPtr->device.vendorID == vendorID)
&& (inHIDInfoPtr->device.productID == productID) )
{
foundIOHIDDeviceRef = tIOHIDDeviceRef;
}
if ( foundIOHIDDeviceRef ) {
break;
}
} // next devIdx
if ( foundIOHIDDeviceRef ) {
CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(foundIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone);
if ( elementCFArrayRef ) {
cnt = CFArrayGetCount(elementCFArrayRef);
for ( idx = 0; idx < cnt; idx++ ) {
tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(elementCFArrayRef, idx);
if ( !tIOHIDElementRef ) {
continue; // skip this element
}
IOHIDElementCookie cookie = IOHIDElementGetCookie(tIOHIDElementRef);
if ( inHIDInfoPtr->element.cookie == cookie ) {
foundIOHIDElementRef = tIOHIDElementRef;
}
if ( foundIOHIDElementRef ) {
break;
}
}
if ( !foundIOHIDElementRef ) {
cnt = CFArrayGetCount(elementCFArrayRef);
for ( idx = 0; idx < cnt; idx++ ) {
tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(elementCFArrayRef, idx);
if ( !tIOHIDElementRef ) {
continue; // skip this element
}
uint32_t usagePage = IOHIDElementGetUsagePage(tIOHIDElementRef);
uint32_t usage = IOHIDElementGetUsage(tIOHIDElementRef);
if ( (inHIDInfoPtr->element.usage == usage) && (inHIDInfoPtr->element.usagePage == usagePage) ) {
foundIOHIDElementRef = tIOHIDElementRef;
}
if ( foundIOHIDElementRef ) {
break;
}
} // next idx
} // if ( !foundIOHIDElementRef )
if ( foundIOHIDElementRef ) { // if same device
// setup the calibration
IOHIDElement_SetupCalibration(tIOHIDElementRef);
IOHIDElement_SetCalibrationSaturationMin(tIOHIDElementRef, inHIDInfoPtr->element.minReport);
IOHIDElement_SetCalibrationSaturationMax(tIOHIDElementRef, inHIDInfoPtr->element.maxReport);
}
CFRelease(elementCFArrayRef);
} // if ( elementCFArrayRef )
} // if ( foundIOHIDDeviceRef )
// if we have not found a match, look at just vendor and product
if ( (!foundIOHIDDeviceRef) && (inHIDInfoPtr->device.vendorID && inHIDInfoPtr->device.productID) ) {
devCnt = CFArrayGetCount(gDeviceCFArrayRef);
for ( devIdx = 0; devIdx < devCnt; devIdx++ ) {
tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef, devIdx);
if ( !tIOHIDDeviceRef ) {
continue; // skip this device
}
long vendorID = IOHIDDevice_GetVendorID(tIOHIDDeviceRef);
long productID = IOHIDDevice_GetProductID(tIOHIDDeviceRef);
if ( (inHIDInfoPtr->device.vendorID == vendorID)
&& (inHIDInfoPtr->device.productID == productID) )
{
foundIOHIDDeviceRef = tIOHIDDeviceRef;
}
if ( foundIOHIDDeviceRef ) {
break;
}
}
// match elements by cookie since same device type
if ( foundIOHIDDeviceRef ) {
CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(foundIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone);
if ( elementCFArrayRef ) {
cnt = CFArrayGetCount(elementCFArrayRef);
for ( idx = 0; idx < cnt; idx++ ) {
tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(elementCFArrayRef, idx);
if ( !tIOHIDElementRef ) {
continue; // skip this element
}
IOHIDElementCookie cookie = IOHIDElementGetCookie(tIOHIDElementRef);
if ( inHIDInfoPtr->element.cookie == cookie ) {
foundIOHIDElementRef = tIOHIDElementRef;
}
if ( foundIOHIDElementRef ) {
break;
}
}
// if no cookie match (should NOT occur) match on usage
if ( !foundIOHIDElementRef ) {
cnt = CFArrayGetCount(elementCFArrayRef);
for ( idx = 0; idx < cnt; idx++ ) {
tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(elementCFArrayRef, idx);
if ( !tIOHIDElementRef ) {
continue; // skip this element
}
uint32_t usagePage = IOHIDElementGetUsagePage(tIOHIDElementRef);
uint32_t usage = IOHIDElementGetUsage(tIOHIDElementRef);
if ( (inHIDInfoPtr->element.usage == usage)
&& (inHIDInfoPtr->element.usagePage == usagePage) )
{
foundIOHIDElementRef = tIOHIDElementRef;
}
if ( foundIOHIDElementRef ) {
break;
}
} // next idx
} // if ( !foundIOHIDElementRef )
if ( foundIOHIDElementRef ) { // if same device
// setup the calibration
IOHIDElement_SetupCalibration(tIOHIDElementRef);
IOHIDElement_SetCalibrationSaturationMin(tIOHIDElementRef, inHIDInfoPtr->element.minReport);
IOHIDElement_SetCalibrationSaturationMax(tIOHIDElementRef, inHIDInfoPtr->element.maxReport);
}
CFRelease(elementCFArrayRef);
} // if ( elementCFArrayRef )
} // if ( foundIOHIDDeviceRef )
} // if ( device not found & vendorID & productID )
} // if ( inHIDInfoPtr->locID && inHIDInfoPtr->device.vendorID && inHIDInfoPtr->device.productID )
// can't find matching device return NULL, do not return first device
if ( (!foundIOHIDDeviceRef) || (!foundIOHIDElementRef) ) {
// no HID device
*outIOHIDDeviceRef = NULL;
*outIOHIDElementRef = NULL;
return (inHIDInfoPtr->actionCookie);
} else {
// HID device
*outIOHIDDeviceRef = foundIOHIDDeviceRef;
*outIOHIDElementRef = foundIOHIDElementRef;
return (inHIDInfoPtr->actionCookie);
}
} // HIDGetElementConfig
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050

View file

@ -0,0 +1,108 @@
// File: HID_Error_Handler.c
// Abstract: Implementation of the HID utilities error handlers
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#ifdef DEBUG // not used in release
#if !defined (kBuildingLibrary)
#define kVerboseErrors
// system includes ----------------------------------------------------------
#ifdef kVerboseErrors
//#include <Carbon/Carbon.h>
#endif
#endif // not kBuildingLibrary
#endif // DEBUG
#include <stdio.h>
// project includes ---------------------------------------------------------
#include "HID_Utilities_External.h"
// globals (internal/private) -----------------------------------------------
// prototypes (internal/private) --------------------------------------------
// functions (internal/private) ---------------------------------------------
#pragma mark -
// -------------------------------------
// central error reporting
void HIDReportErrorNum(const char *strError, int numError) {
char errMsgCStr[256];
sprintf(errMsgCStr, "%s #%d (0x%x)", strError, numError, numError);
// out as debug string
#ifdef kVerboseErrors
{
fputs(errMsgCStr, stderr);
}
#endif // kVerboseErrors
} // HIDReportErrorNum
// -------------------------------------
void HIDReportError(const char *strError) {
char errMsgCStr[256];
sprintf(errMsgCStr, "%s", strError);
// out as debug string
#ifdef kVerboseErrors
{
fputs(errMsgCStr, stderr);
}
#endif // kVerboseErrors
} // HIDReportError
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050

1210
src/cocoa/HID_Name_Lookup.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,361 @@
// File: HID_Queue_Utilities.c
// Abstract: HID Queue Utilities.
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#include "HID_Utilities_External.h"
// ==================================
// private functions
// creates a queue for a device, creates and opens device interface if required
static IOReturn HIDCreateQueue(IOHIDDeviceRef inIOHIDDeviceRef) {
IOReturn result = kIOReturnSuccess;
if ( inIOHIDDeviceRef ) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
// do we already have a queue?
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
if ( tIOHIDQueueRef ) { // (yes)
assert( IOHIDQueueGetTypeID() == CFGetTypeID(tIOHIDQueueRef) );
} else {
tIOHIDQueueRef = IOHIDQueueCreate(kCFAllocatorDefault, inIOHIDDeviceRef, kDeviceQueueSize, kIOHIDOptionsTypeNone);
if ( tIOHIDQueueRef ) { // did that work
IOHIDDevice_SetQueue(inIOHIDDeviceRef, tIOHIDQueueRef);
result = kIOReturnSuccess;
} else {
HIDReportErrorNum("Failed to create queue via create", result);
}
}
} else {
HIDReportErrorNum("HID device ref does not exist for queue creation", result);
}
return (result);
} /* HIDCreateQueue */
// ---------------------------------
// returns true if queue is empty false otherwise
// error if no device, empty if no queue
static unsigned char HIDIsDeviceQueueEmpty(IOHIDDeviceRef inIOHIDDeviceRef) {
if ( inIOHIDDeviceRef ) { // need device and queue
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
if ( tIOHIDQueueRef ) {
IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement(inIOHIDDeviceRef, kHIDElementTypeIO);
while ( tIOHIDElementRef ) {
if ( IOHIDQueueContainsElement(tIOHIDQueueRef, tIOHIDElementRef) ) {
return (false);
}
tIOHIDElementRef = HIDGetNextDeviceElement(tIOHIDElementRef, kHIDElementTypeIO);
}
} else {
HIDReportError("NULL device passed to HIDIsDeviceQueueEmpty.");
}
} else {
HIDReportError("NULL device passed to HIDIsDeviceQueueEmpty.");
}
return (true);
} /* HIDIsDeviceQueueEmpty */
// ---------------------------------
// disposes and releases queue, sets queue to NULL,.
// Note: will have no effect if device or queue do not exist
static IOReturn HIDDisposeReleaseQueue(IOHIDDeviceRef inIOHIDDeviceRef) {
IOReturn result = kIOReturnSuccess;
if ( inIOHIDDeviceRef ) {
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
if ( tIOHIDQueueRef ) {
// stop queue
IOHIDQueueStop(tIOHIDQueueRef);
// release the queue
CFRelease(tIOHIDQueueRef);
}
} else {
HIDReportError("NULL device passed to HIDDisposeReleaseQueue.");
}
return (result);
} /* HIDDisposeReleaseQueue */
// ==================================
// public functions
// ----------------------------------
// queues specific element, performing any device queue set up required
// queue is started and ready to return events on exit from this function
int HIDQueueElement(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef) {
IOReturn result = kIOReturnSuccess;
if ( inIOHIDDeviceRef ) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
if ( inIOHIDElementRef ) {
assert( IOHIDElementGetTypeID() == CFGetTypeID(inIOHIDElementRef) );
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
if ( !tIOHIDQueueRef ) { // if no queue create queue
result = HIDCreateQueue(inIOHIDDeviceRef);
if ( kIOReturnSuccess == result ) {
tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
}
}
if ( tIOHIDQueueRef ) {
// stop queue
IOHIDQueueStop(tIOHIDQueueRef);
// queue element
if ( !IOHIDQueueContainsElement(tIOHIDQueueRef, inIOHIDElementRef) ) {
IOHIDQueueAddElement(tIOHIDQueueRef, inIOHIDElementRef);
}
// restart queue
IOHIDQueueStart(tIOHIDQueueRef);
} else {
HIDReportError("No queue for device passed to HIDQueueElement.");
if ( kIOReturnSuccess == result ) {
result = kIOReturnError;
}
}
} else {
HIDReportError("NULL element passed to HIDQueueElement.");
result = kIOReturnBadArgument;
}
} else {
HIDReportError("NULL device passed to HIDQueueElement.");
result = kIOReturnBadArgument;
}
return (result);
} /* HIDQueueElement */
// ---------------------------------
// adds all elements to queue, performing any device queue set up required
// queue is started and ready to return events on exit from this function
int HIDQueueDevice(IOHIDDeviceRef inIOHIDDeviceRef) {
IOReturn result = kIOReturnSuccess;
// error checking
if ( !inIOHIDDeviceRef ) {
HIDReportError("Device does not exist, cannot queue device.");
return (kIOReturnBadArgument);
}
if ( !inIOHIDDeviceRef ) { // must have interface
HIDReportError("Device does not have hid device ref, cannot queue device.");
return (kIOReturnError);
}
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
if ( !tIOHIDQueueRef ) { // if no queue create queue
result = HIDCreateQueue(inIOHIDDeviceRef);
if ( kIOReturnSuccess == result ) {
tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
}
}
if ( (kIOReturnSuccess != result) || (!tIOHIDQueueRef) ) {
HIDReportErrorNum("Could not queue device due to problem creating queue.", result);
if ( kIOReturnSuccess != result ) {
return (result);
} else {
return (kIOReturnError);
}
}
// stop queue
IOHIDQueueStop(tIOHIDQueueRef);
// queue element
IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement(inIOHIDDeviceRef, kHIDElementTypeIO);
while ( tIOHIDElementRef ) {
if ( !IOHIDQueueContainsElement(tIOHIDQueueRef, tIOHIDElementRef) ) {
IOHIDQueueAddElement(tIOHIDQueueRef, tIOHIDElementRef);
}
tIOHIDElementRef = HIDGetNextDeviceElement(tIOHIDElementRef, kHIDElementTypeIO);
}
// restart queue
IOHIDQueueStart(tIOHIDQueueRef);
return (result);
} /* HIDQueueDevice */
// ---------------------------------
// removes element for queue, if last element in queue will release queue and closes device interface
int HIDDequeueElement(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef) {
IOReturn result = kIOReturnSuccess;
if ( inIOHIDDeviceRef ) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
if ( inIOHIDElementRef ) {
assert( IOHIDElementGetTypeID() == CFGetTypeID(inIOHIDElementRef) );
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
if ( tIOHIDQueueRef ) {
// stop queue
IOHIDQueueStop(tIOHIDQueueRef);
// de-queue element
if ( IOHIDQueueContainsElement(tIOHIDQueueRef, inIOHIDElementRef) ) {
IOHIDQueueRemoveElement(tIOHIDQueueRef, inIOHIDElementRef);
}
// release device queue and close interface if queue empty
if ( HIDIsDeviceQueueEmpty(inIOHIDDeviceRef) ) {
result = HIDDisposeReleaseQueue(inIOHIDDeviceRef);
if ( kIOReturnSuccess != result ) {
HIDReportErrorNum("Failed to dispose and release queue.", result);
}
} else { // not empty so restart queue
IOHIDQueueStart(tIOHIDQueueRef);
}
} else {
HIDReportError("No queue for device passed to HIDDequeueElement.");
if ( kIOReturnSuccess == result ) {
result = kIOReturnError;
}
}
} else {
HIDReportError("NULL element passed to HIDDequeueElement.");
result = kIOReturnBadArgument;
}
} else {
HIDReportError("NULL device passed to HIDDequeueElement.");
result = kIOReturnBadArgument;
}
return (result);
} /* HIDDequeueElement */
// ---------------------------------
// completely removes all elements from queue and releases queue and closes device interface
// does not release device interfaces, application must call ReleaseHIDDeviceList on exit
int HIDDequeueDevice(IOHIDDeviceRef inIOHIDDeviceRef) {
IOReturn result = kIOReturnSuccess;
// error checking
if ( !inIOHIDDeviceRef ) {
HIDReportError("Device does not exist, cannot queue device.");
return (kIOReturnBadArgument);
}
if ( !inIOHIDDeviceRef ) { // must have interface
HIDReportError("Device does not have hid device ref, cannot queue device.");
return (kIOReturnError);
}
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
if ( tIOHIDQueueRef ) {
// iterate through elements and if queued, remove
IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement(inIOHIDDeviceRef, kHIDElementTypeIO);
while ( tIOHIDElementRef ) {
// de-queue element
if ( IOHIDQueueContainsElement(tIOHIDQueueRef, tIOHIDElementRef) ) {
IOHIDQueueRemoveElement(tIOHIDQueueRef, tIOHIDElementRef);
}
tIOHIDElementRef = HIDGetNextDeviceElement(tIOHIDElementRef, kHIDElementTypeIO);
}
// ensure queue is disposed and released
result = HIDDisposeReleaseQueue(inIOHIDDeviceRef);
if ( kIOReturnSuccess != result ) {
HIDReportErrorNum("Failed to dispose and release queue.", result);
}
} else {
HIDReportError("No queue for device passed to HIDDequeueElement.");
if ( kIOReturnSuccess == result ) {
result = kIOReturnError;
}
}
return (result);
} /* HIDDequeueDevice */
// ---------------------------------
// releases all device queues for quit or rebuild (must be called)
// does not release device interfaces, application must call ReleaseHIDDeviceList on exit
IOReturn HIDReleaseAllDeviceQueues(void) {
IOReturn result = kIOReturnSuccess;
IOHIDDeviceRef tIOHIDDeviceRef = HIDGetFirstDevice();
while ( tIOHIDDeviceRef ) {
result = HIDDequeueDevice(tIOHIDDeviceRef);
if ( kIOReturnSuccess != result ) {
HIDReportErrorNum("Could not dequeue device.", result);
}
tIOHIDDeviceRef = HIDGetNextDevice(tIOHIDDeviceRef);
}
return (result);
} /* HIDReleaseAllDeviceQueues */
// ---------------------------------
// Get the next event in the queue for a device
// elements or entire device should be queued prior to calling this with HIDQueueElement or HIDQueueDevice
// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise
// Note: kIOReturnUnderrun returned from getNextEvent indicates an empty queue not an error condition
// Note: application should pass in a pointer to a IOHIDEventStruct cast to a void (for CFM compatibility)
unsigned char HIDGetEvent(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDValueRef *pIOHIDValueRef) {
if ( inIOHIDDeviceRef ) {
IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue(inIOHIDDeviceRef);
if ( tIOHIDQueueRef ) {
if ( pIOHIDValueRef ) {
*pIOHIDValueRef = IOHIDQueueCopyNextValueWithTimeout(tIOHIDQueueRef, 0.0);
if ( *pIOHIDValueRef ) {
return (true);
}
}
} else {
HIDReportError("Could not get HID event, hid queue reference does not exist.");
}
} else {
HIDReportError("Could not get HID event, device does not exist.");
}
return (false); // did not get event
} /* HIDGetEvent */
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050

1068
src/cocoa/HID_Utilities.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,417 @@
// File: HID_Utilities_External.h
// Abstract: External interface for HID Utilities, can be used with either library or source.
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#ifndef _HID_Utilities_External_h_
#define _HID_Utilities_External_h_
// ==================================
#ifdef __cplusplus
extern "C" {
#endif
// ==================================
//includes
#include <stdio.h>
#include "IOHIDLib_.h"
// ==================================
#ifndef _IOKIT_HID_IOHIDKEYS_H_
/*!
@typedef IOHIDElementCookie
@abstract Abstract data type used as a unique identifier for an element.
*/
#ifdef __LP64__
typedef uint32_t IOHIDElementCookie;
#else
typedef void *IOHIDElementCookie;
#endif
#endif
// Device and Element Interfaces
enum HIDElementTypeMask {
kHIDElementTypeInput = 1 << 1,
kHIDElementTypeOutput = 1 << 2,
kHIDElementTypeFeature = 1 << 3,
kHIDElementTypeCollection = 1 << 4,
kHIDElementTypeIO = kHIDElementTypeInput | kHIDElementTypeOutput | kHIDElementTypeFeature,
kHIDElementTypeAll = kHIDElementTypeIO | kHIDElementTypeCollection
};
typedef enum HIDElementTypeMask HIDElementTypeMask;
// ==================================
//*****************************************************
#pragma mark - exported globals
//-----------------------------------------------------
extern IOHIDManagerRef gIOHIDManagerRef;
extern CFMutableArrayRef gDeviceCFArrayRef;
extern CFArrayRef gElementCFArrayRef;
//*************************************************************************
//
// HIDBuildMultiDeviceList( inUsagePages, inUsages, inNumDeviceTypes )
//
// Purpose: builds list of devices with elements (allocates memory and captures devices) in which
// the devices could be of different types/usages list is allocated internally within HID
// Utilites and can be accessed via accessor functions structures within list are considered
// flat and user accessable, but not user modifiable can be called again to rebuild list to
// account for new devices (will do the right thing in case of disposing existing list)
// usagePage, usage are each a numDeviceTypes sized array of matching usage and usage pages
// returns true if succesful
//
// Inputs: inUsagePages - inNumDeviceTypes sized array of matching usage pages
// inUsages - inNumDeviceTypes sized array of matching usages
// inNumDeviceTypes - number of usage pages & usages
//
// Returns: Boolean - if successful
//
extern Boolean HIDBuildMultiDeviceList(const UInt32 *inUsagePages, const UInt32 *inUsages, int inNumDeviceTypes);
// same as above but this uses a single usagePage and usage
extern Boolean HIDBuildDeviceList(UInt32 usagePage, UInt32 usage);
// updates the current device list for any new/removed devices
// if this is called before HIDBuildDeviceList the it functions like HIDBuildMultiDeviceList
// usagePage, usage are each a numDeviceTypes sized array of matching usage and usage pages
// returns true if successful which means if any device were added or removed (the device config changed)
extern Boolean HIDUpdateDeviceList(const UInt32 *inUsagePages, const UInt32 *inUsages, int inNumDeviceTypes);
// release list built by above function
// MUST be called prior to application exit to properly release devices
// if not called (or app crashes) devices can be recovered by pluging into different location in USB chain
extern void HIDReleaseDeviceList(void);
//*************************************************************************
//
// HIDRebuildDevices( )
//
// Purpose: rebuilds the (internal) list of devices
//
// Inputs: none
//
// Returns: none
//
extern void HIDRebuildDevices(void);
// does a device list exist
extern unsigned char HIDHaveDeviceList(void);
// how many HID devices have been found
// returns 0 if no device list exist
extern UInt32 HIDCountDevices(void);
// how many elements does a specific device have
// returns 0 if device is invalid or NULL
// uses mask of HIDElementTypeMask to restrict element found
// use kHIDElementTypeIO to get non-collection elements
extern UInt32 HIDCountDeviceElements(IOHIDDeviceRef inIOHIDDeviceRef, HIDElementTypeMask typeMask);
// get the first device in the device list
// returns NULL if no list exists
extern IOHIDDeviceRef HIDGetFirstDevice(void);
// get next device in list given current device as parameter
// returns NULL if end of list
extern IOHIDDeviceRef HIDGetNextDevice(IOHIDDeviceRef inIOHIDDeviceRef);
// get the first element of device passed in as parameter
// returns NULL if no list exists or device does not exists or is NULL
// uses mask of HIDElementTypeMask to restrict element found
// use kHIDElementTypeIO to get previous HIDGetFirstDeviceElement functionality
extern IOHIDElementRef HIDGetFirstDeviceElement(IOHIDDeviceRef inIOHIDDeviceRef, HIDElementTypeMask typeMask);
// get next element of given device in list given current element as parameter
// will walk down each collection then to next element or collection (depthwise traverse)
// returns NULL if end of list
// uses mask of HIDElementTypeMask to restrict element found
// use kHIDElementTypeIO to get previous HIDGetNextDeviceElement functionality
extern IOHIDElementRef HIDGetNextDeviceElement(IOHIDElementRef inIOHidElementRef, HIDElementTypeMask typeMask);
// get previous element of given device in list given current element as parameter
// this walks directly up the tree to the top element and does not search at each level
// returns NULL if beginning of list
// uses mask of HIDElementTypeMask to restrict element found
// use kHIDElementTypeIO to get non-collection elements
extern IOHIDElementRef HIDGetPreviousDeviceElement(IOHIDElementRef inIOHidElementRef, HIDElementTypeMask typeMask);
// returns C string type name given a type enumeration passed in as parameter( see IOHIDKeys.h )
// returns empty string for invalid types
extern void HIDGetTypeName(IOHIDElementType inIOHIDElementType, char *outCStrName);
//*************************************************************************
//
// HIDCopyUsageName( inUsagePage, inUsage )
//
// Purpose: return a CFStringRef string for a given usage page & usage( see IOUSBHIDParser.h )
//
// Notes: returns usage page and usage values in CFString form for unknown values
//
// Inputs: inUsagePage - the usage page
// inUsage - the usage
//
// Returns: CFStringRef - the resultant string
//
extern CFStringRef HIDCopyUsageName(long inUsagePage, long inUsage);
// ==================================
// Element Event Queue and Value Interfaces
enum {
kDefaultUserMin = 0, // default user min and max used for scaling
kDefaultUserMax = 255
};
enum {
kDeviceQueueSize = 50 // this is wired kernel memory so should be set to as small as possible
// but should account for the maximum possible events in the queue
// USB updates will likely occur at 100 Hz so one must account for this rate of
// if states change quickly (updates are only posted on state changes)
};
// ==================================
// queues specific element, performing any device queue set up required
extern int HIDQueueElement(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHidElementRef);
// adds all elements to queue, performing any device queue set up required
extern int HIDQueueDevice(IOHIDDeviceRef inIOHIDDeviceRef);
// removes element for queue, if last element in queue will release queue and device
extern int HIDDequeueElement(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHidElementRef);
// completely removes all elements from queue and releases queue and device
extern int HIDDequeueDevice(IOHIDDeviceRef inIOHIDDeviceRef);
// releases all device queues for quit or rebuild (must be called)
extern int HIDReleaseAllDeviceQueues(void);
// returns true if an event is avialable for the element and fills out *pHIDEvent structure, returns false otherwise
// pHIDEvent is a poiner to a IOHIDEventStruct, using void here for compatibility, users can cast a required
extern unsigned char HIDGetEvent(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDValueRef *pIOHIDValueRef);
// ==================================
// Conguration and Save Interfaces
enum {
kPercentMove = 10 // precent of overall range a element must move to register
};
typedef struct HID_info_struct {
int actionCookie;
// device
// need to add serial number when I have a test case
struct {
int vendorID, productID;
int locID;
uint32_t usagePage, usage;
} device;
// elements
struct {
uint32_t usagePage, usage;
int minReport, maxReport;
IOHIDElementCookie cookie; // always 32 bits
} element;
}HID_info_rec, *HID_info_ptr;
// get vendor name from vendor ID
extern Boolean HIDGetVendorNameFromVendorID(long inVendorID, char *outCStrName);
// get product name from vendor/product ID
extern Boolean HIDGetProductNameFromVendorProductID(long inVendorID, long inProductID, char *outCStrName);
// get element name from vendor id/product id look up ( using element cookie )
extern Boolean HIDGetElementNameFromVendorProductCookie(int inVendorID,
int inProductID,
IOHIDElementCookie inCookie,
char * outCStrName);
// get element name from vendor id/product id look up ( using element usage page & usage )
extern Boolean HIDGetElementNameFromVendorProductUsage(long inVendorID,
long inProductID,
long inUsagePage,
long inUsage,
char *inCStrName);
// utility routines to dump device or element info
extern void HIDDumpDeviceInfo(IOHIDDeviceRef inIOHIDDeviceRef);
extern void HIDDumpElementInfo(IOHIDElementRef inIOHIDElementRef);
extern void HIDDumpElementCalibrationInfo(IOHIDElementRef inIOHIDElementRef);
// polls single device's elements for a change greater than kPercentMove. Times out after given time
// returns 1 and pointer to element if found
// returns 0 and NULL for both parameters if not found
extern unsigned char HIDConfigureSingleDeviceAction(IOHIDDeviceRef inIOHIDDeviceRef,
IOHIDElementRef *outIOHIDElementRef,
float timeout);
//*************************************************************************
//
// HIDConfigureAction( outDeviceRef, outElementRef, inTimeout )
//
// Purpose: polls all devices and elements for a change greater than kPercentMove.
// Times out after given time returns 1 and pointer to device and element
// if found; returns 0 and NULL for both parameters if not found
//
// Inputs: outDeviceRef - address where to store the device
// outElementRef - address where to store the element
// inTimeout - the timeout
// Returns: Boolean - TRUE if successful
// outDeviceRef - the device
// outElementRef - the element
//
extern Boolean HIDConfigureAction(IOHIDDeviceRef *outDeviceRef, IOHIDElementRef *outElementRef, float inTimeout);
//*************************************************************************
//
// HIDSaveElementPref( inKeyCFStringRef, inAppCFStringRef, inDeviceRef, inElementRef )
//
// Purpose: Save the device & element values into the specified key in the specified applications preferences
//
// Inputs: inKeyCFStringRef - the preference key
// inAppCFStringRef - the application identifier
// inDeviceRef - the device
// inElementRef - the element
// Returns: Boolean - if successful
//
extern Boolean HIDSaveElementPref(const CFStringRef inKeyCFStringRef,
CFStringRef inAppCFStringRef,
IOHIDDeviceRef inDeviceRef,
IOHIDElementRef inElementRef);
//*************************************************************************
//
// HIDRestoreElementPref( inKeyCFStringRef, inAppCFStringRef, outDeviceRef, outElementRef )
//
// Purpose: Find the specified preference in the specified application
//
// Inputs: inKeyCFStringRef - the preference key
// inAppCFStringRef - the application identifier
// outDeviceRef - address where to restore the device
// outElementRef - address where to restore the element
// Returns: Boolean - if successful
// outDeviceRef - the device
// outElementRef - the element
//
extern Boolean HIDRestoreElementPref(CFStringRef inKeyCFStringRef,
CFStringRef inAppCFStringRef,
IOHIDDeviceRef * outDeviceRef,
IOHIDElementRef *outElementRef);
//*************************************************************************
//
// HIDFindDeviceAndElement( inSearchInfo, outFoundDevice, outFoundElement )
//
// Purpose: find the closest matching device and element for this action
//
// Notes: matches device: serial, vendorID, productID, location, inUsagePage, usage
// matches element: cookie, inUsagePage, usage,
//
// Inputs: inSearchInfo - the device & element info we searching for
// outFoundDevice - the address of the best matching device
// outFoundElement - the address of the best matching element
//
// Returns: Boolean - TRUE if we find a match
// outFoundDevice - the best matching device
// outFoundElement - the best matching element
//
extern Boolean HIDFindDeviceAndElement(const HID_info_rec *inSearchInfo,
IOHIDDeviceRef * outFoundDevice,
IOHIDElementRef * outFoundElement);
// -- These are routines to use if the applcationwants HID Utilities to do the file handling --
// Note: the FILE * is a MachO posix FILE and will not likely work directly with MW MSL FILE * type.
// take input records, save required info
// assume file is open and at correct position.
void HIDSaveElementConfig(FILE *fileRef, IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHidElementRef, int actionCookie);
// takes a file, reads one record (assume file position is correct and file is open)
// search for matching device
// return tIOHIDDeviceRef, tIOHIDElementRef and cookie for action
int HIDRestoreElementConfig(FILE *fileRef, IOHIDDeviceRef *outIOHIDDeviceRef, IOHIDElementRef *outIOHIDElementRef);
// -- These are routines to use if the client wants to use their own file handling --
// Set up a config record for saving
// takes an input records, returns record user can save as they want
// Note: the save rec must be pre-allocated by the calling app and will be filled out
void HIDSetElementConfig(HID_info_ptr inHIDInfoPtr,
IOHIDDeviceRef inIOHIDDeviceRef,
IOHIDElementRef inIOHidElementRef,
int actionCookie);
// Get matching element from config record
// takes a pre-allocated and filled out config record
// search for matching device
// return tIOHIDDeviceRef, tIOHIDElementRef and cookie for action
int HIDGetElementConfig(HID_info_ptr inHIDInfoPtr, IOHIDDeviceRef *outIOHIDDeviceRef, IOHIDElementRef *outIOHIDElementRef);
// ==================================
// Error reporter, can be set to report however the application desires
extern void HIDReportError(const char *strError);
// Error with numeric code reporter, can be set to report however the application desires
extern void HIDReportErrorNum(const char *strError, int numError);
#ifdef __cplusplus
}
#endif
#endif // _HID_Utilities_External_h_

619
src/cocoa/IOHIDDevice_.c Normal file
View file

@ -0,0 +1,619 @@
// File: IOHIDDevice_.c
// Abstract: convieance functions for IOHIDDeviceGetProperty
// Version: 2.0 + 5.3
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#pragma mark - includes & imports
//-----------------------------------------------------
#include "IOHIDDevice_.h"
//*****************************************************
#pragma mark - typedef's, struct's, enums, defines, etc.
//-----------------------------------------------------
#define kIOHIDDevice_TransactionKey "DeviceTransactionRef"
#define kIOHIDDevice_QueueKey "DeviceQueueRef"
//*****************************************************
#pragma mark - local (static) function prototypes
//-----------------------------------------------------
static Boolean IOHIDDevice_GetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef,
CFStringRef inKey,
uint32_t * outValue);
// static void IOHIDDevice_SetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey, uint32_t inValue);
static Boolean IOHIDDevice_GetPtrProperty(IOHIDDeviceRef inIOHIDDeviceRef,
CFStringRef inKey,
void ** outValue);
static void IOHIDDevice_SetPtrProperty(IOHIDDeviceRef inIOHIDDeviceRef,
CFStringRef inKey,
void * inValue);
//*****************************************************
#pragma mark - exported globals
//-----------------------------------------------------
//*****************************************************
#pragma mark - local (static) globals
//-----------------------------------------------------
//*****************************************************
#pragma mark - exported function implementations
//-----------------------------------------------------
//*************************************************************************
//
// HIDIsValidDevice( inIOHIDDeviceRef )
//
// Purpose: validate this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: Boolean - TRUE if we find the device in our( internal ) device list
//
Boolean HIDIsValidDevice(IOHIDDeviceRef inIOHIDDeviceRef) {
Boolean result = FALSE; // assume failure (pessimist!)
if ( inIOHIDDeviceRef ) {
if ( CFGetTypeID(inIOHIDDeviceRef) ==IOHIDDeviceGetTypeID() ) {
result = TRUE;
}
}
return (result);
} // HIDIsValidDevice
//*************************************************************************
//
// IOHIDDevice_GetTransport( inIOHIDDeviceRef )
//
// Purpose: get the Transport CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the Transport for this device
//
CFStringRef IOHIDDevice_GetTransport(IOHIDDeviceRef inIOHIDDeviceRef) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
return ( IOHIDDeviceGetProperty( inIOHIDDeviceRef, CFSTR(kIOHIDTransportKey) ) );
}
//*************************************************************************
//
// IOHIDDevice_GetVendorID( inIOHIDDeviceRef )
//
// Purpose: get the vendor ID for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the vendor ID for this device
//
uint32_t IOHIDDevice_GetVendorID(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey), &result);
return (result);
} // IOHIDDevice_GetVendorID
//*************************************************************************
//
// IOHIDDevice_GetVendorIDSource( inIOHIDDeviceRef )
//
// Purpose: get the VendorIDSource for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the VendorIDSource for this device
//
uint32_t IOHIDDevice_GetVendorIDSource(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDSourceKey), &result);
return (result);
} // IOHIDDevice_GetVendorIDSource
//*************************************************************************
//
// IOHIDDevice_GetProductID( inIOHIDDeviceRef )
//
// Purpose: get the product ID for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the product ID for this device
//
uint32_t IOHIDDevice_GetProductID(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey), &result);
return (result);
} // IOHIDDevice_GetProductID
//*************************************************************************
//
// IOHIDDevice_GetVersionNumber( inIOHIDDeviceRef )
//
// Purpose: get the VersionNumber CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the VersionNumber for this device
//
uint32_t IOHIDDevice_GetVersionNumber(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDVersionNumberKey), &result);
return (result);
} // IOHIDDevice_GetVersionNumber
//*************************************************************************
//
// IOHIDDevice_GetManufacturer( inIOHIDDeviceRef )
//
// Purpose: get the Manufacturer CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the Manufacturer for this device
//
CFStringRef IOHIDDevice_GetManufacturer(IOHIDDeviceRef inIOHIDDeviceRef) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
return ( IOHIDDeviceGetProperty( inIOHIDDeviceRef, CFSTR(kIOHIDManufacturerKey) ) );
} // IOHIDDevice_GetManufacturer
//*************************************************************************
//
// IOHIDDevice_GetProduct( inIOHIDDeviceRef )
//
// Purpose: get the Product CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the Product for this device
//
CFStringRef IOHIDDevice_GetProduct(IOHIDDeviceRef inIOHIDDeviceRef) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
return ( IOHIDDeviceGetProperty( inIOHIDDeviceRef, CFSTR(kIOHIDProductKey) ) );
} // IOHIDDevice_GetProduct
//*************************************************************************
//
// IOHIDDevice_GetSerialNumber( inIOHIDDeviceRef )
//
// Purpose: get the SerialNumber CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the SerialNumber for this device
//
CFStringRef IOHIDDevice_GetSerialNumber(IOHIDDeviceRef inIOHIDDeviceRef) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
return ( IOHIDDeviceGetProperty( inIOHIDDeviceRef, CFSTR(kIOHIDSerialNumberKey) ) );
}
//*************************************************************************
//
// IOHIDDevice_GetCountryCode( inIOHIDDeviceRef )
//
// Purpose: get the CountryCode CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the CountryCode for this device
//
uint32_t IOHIDDevice_GetCountryCode(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDCountryCodeKey), &result);
return (result);
} // IOHIDDevice_GetCountryCode
//*************************************************************************
//
// IOHIDDevice_GetLocationID( inIOHIDDeviceRef )
//
// Purpose: get the location ID for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the location ID for this device
//
uint32_t IOHIDDevice_GetLocationID(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDLocationIDKey), &result);
return (result);
} // IOHIDDevice_GetLocationID
//*************************************************************************
//
// IOHIDDevice_GetUsage( inIOHIDDeviceRef )
//
// Purpose: get the usage for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the usage for this device
//
uint32_t IOHIDDevice_GetUsage(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDDeviceUsageKey), &result);
return (result);
} // IOHIDDevice_GetUsage
//*************************************************************************
//
// IOHIDDevice_GetUsagePage( inIOHIDDeviceRef )
//
// Purpose: get the usage page for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the usage page for this device
//
uint32_t IOHIDDevice_GetUsagePage(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDDeviceUsagePageKey), &result);
return (result);
} // IOHIDDevice_GetUsagePage
//*************************************************************************
//
// IOHIDDevice_GetUsagePairs( inIOHIDDeviceRef )
//
// Purpose: get the UsagePairs CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFArrayRef - the UsagePairs for this device
//
CFArrayRef IOHIDDevice_GetUsagePairs(IOHIDDeviceRef inIOHIDDeviceRef) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
return ( IOHIDDeviceGetProperty( inIOHIDDeviceRef, CFSTR(kIOHIDDeviceUsagePairsKey) ) );
}
//*************************************************************************
//
// IOHIDDevice_GetPrimaryUsage( inIOHIDDeviceRef )
//
// Purpose: get the PrimaryUsage CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the PrimaryUsage for this device
//
uint32_t IOHIDDevice_GetPrimaryUsage(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsageKey), &result);
return (result);
} // IOHIDDevice_GetPrimaryUsage
//*************************************************************************
//
// IOHIDDevice_GetPrimaryUsagePage( inIOHIDDeviceRef )
//
// Purpose: get the PrimaryUsagePage CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the PrimaryUsagePage for this device
//
uint32_t IOHIDDevice_GetPrimaryUsagePage(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDPrimaryUsagePageKey), &result);
return (result);
} // IOHIDDevice_GetPrimaryUsagePage
//*************************************************************************
//
// IOHIDDevice_GetMaxInputReportSize( inIOHIDDeviceRef )
//
// Purpose: get the MaxInputReportSize CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the MaxInputReportSize for this device
//
uint32_t IOHIDDevice_GetMaxInputReportSize(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDMaxInputReportSizeKey), &result);
return (result);
} // IOHIDDevice_GetMaxInputReportSize
//*************************************************************************
//
// IOHIDDevice_GetMaxOutputReportSize( inIOHIDDeviceRef )
//
// Purpose: get the MaxOutputReportSize for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the MaxOutput for this device
//
uint32_t IOHIDDevice_GetMaxOutputReportSize(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDMaxOutputReportSizeKey), &result);
return (result);
} // IOHIDDevice_GetMaxOutputReportSize
//*************************************************************************
//
// IOHIDDevice_GetMaxFeatureReportSize( inIOHIDDeviceRef )
//
// Purpose: get the MaxFeatureReportSize for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the MaxFeatureReportSize for this device
//
uint32_t IOHIDDevice_GetMaxFeatureReportSize(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDMaxFeatureReportSizeKey), &result);
return (result);
} // IOHIDDevice_GetMaxFeatureReportSize
//*************************************************************************
//
// IOHIDDevice_GetReportInterval( inIOHIDDeviceRef )
//
// Purpose: get the ReportInterval for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the ReportInterval for this device
//
#ifndef kIOHIDReportIntervalKey
#define kIOHIDReportIntervalKey "ReportInterval"
#endif
uint32_t IOHIDDevice_GetReportInterval(IOHIDDeviceRef inIOHIDDeviceRef) {
uint32_t result = 0;
(void) IOHIDDevice_GetUInt32Property(inIOHIDDeviceRef, CFSTR(kIOHIDReportIntervalKey), &result);
return (result);
} // IOHIDDevice_GetReportInterval
//*************************************************************************
//
// IOHIDDevice_GetQueue( inIOHIDDeviceRef )
//
// Purpose: get the Queue for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: IOHIDQueueRef - the Queue for this device
//
IOHIDQueueRef IOHIDDevice_GetQueue(IOHIDDeviceRef inIOHIDDeviceRef) {
IOHIDQueueRef result = 0;
(void) IOHIDDevice_GetPtrProperty(inIOHIDDeviceRef, CFSTR(kIOHIDDevice_QueueKey), (void *) &result);
if ( result ) {
assert( IOHIDQueueGetTypeID() == CFGetTypeID(result) );
}
return (result);
} // IOHIDDevice_GetQueue
//*************************************************************************
//
// IOHIDDevice_SetQueue( inIOHIDDeviceRef, inQueueRef )
//
// Purpose: Set the Queue for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
// inQueueRef - the Queue reference
//
// Returns: nothing
//
void IOHIDDevice_SetQueue(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDQueueRef inQueueRef) {
IOHIDDevice_SetPtrProperty(inIOHIDDeviceRef, CFSTR(kIOHIDDevice_QueueKey), inQueueRef);
}
//*************************************************************************
//
// IOHIDDevice_GetTransaction( inIOHIDDeviceRef )
//
// Purpose: get the Transaction for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: IOHIDTransactionRef - the Transaction for this device
//
IOHIDTransactionRef IOHIDDevice_GetTransaction(IOHIDDeviceRef inIOHIDDeviceRef) {
IOHIDTransactionRef result = 0;
(void) IOHIDDevice_GetPtrProperty(inIOHIDDeviceRef, CFSTR(kIOHIDDevice_TransactionKey), (void *) &result);
return (result);
} // IOHIDDevice_GetTransaction
//*************************************************************************
//
// IOHIDDevice_SetTransaction( inIOHIDDeviceRef, inTransactionRef )
//
// Purpose: Set the Transaction for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
// inTransactionRef - the Transaction reference
//
// Returns: nothing
//
void IOHIDDevice_SetTransaction(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDTransactionRef inTransactionRef) {
IOHIDDevice_SetPtrProperty(inIOHIDDeviceRef, CFSTR(kIOHIDDevice_TransactionKey), inTransactionRef);
}
//*****************************************************
#pragma mark - local (static) function implementations
//-----------------------------------------------------
//*************************************************************************
//
// IOHIDDevice_GetUInt32Property( inIOHIDDeviceRef, inKey, outValue )
//
// Purpose: convieance function to return a uint32_t property of a device
//
// Inputs: inIOHIDDeviceRef - the device
// inKey - CFString for the
// outValue - address where to restore the element
// Returns: the action cookie
// outValue - the device
//
static Boolean IOHIDDevice_GetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey, uint32_t *outValue) {
Boolean result = FALSE;
if ( inIOHIDDeviceRef ) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey);
if ( tCFTypeRef ) {
// if this is a number
if ( CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef) ) {
// get it's value
result = CFNumberGetValue( (CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, outValue );
}
}
}
return (result);
} // IOHIDDevice_GetUInt32Property
//*************************************************************************
//
// IOHIDDevice_SetUInt32Property( inIOHIDDeviceRef, inKey, inValue )
//
// Purpose: convieance function to set a long property of an Device
//
// Inputs: inIOHIDDeviceRef - the Device
// inKey - CFString for the key
// inValue - the value to set it to
// Returns: nothing
//
#if 0 // unused
static void IOHIDDevice_SetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey, uint32_t inValue) {
CFNumberRef tCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &inValue);
if ( tCFNumberRef ) {
IOHIDDeviceSetProperty(inIOHIDDeviceRef, inKey, tCFNumberRef);
CFRelease(tCFNumberRef);
}
} // IOHIDDevice_SetUInt32Property
#endif
//*************************************************************************
//
// IOHIDDevice_GetPtrProperty( inIOHIDDeviceRef, inKey, outValue )
//
// Purpose: convieance function to return a pointer property of a device
//
// Inputs: inIOHIDDeviceRef - the device
// inKey - CFString for the
// outValue - address where to restore the element
// Returns: the action cookie
// outValue - the device
//
static Boolean IOHIDDevice_GetPtrProperty(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey, void **outValue) {
Boolean result = FALSE;
if ( inIOHIDDeviceRef ) {
assert( IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef) );
CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey);
if ( tCFTypeRef ) {
// if this is a number
if ( CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef) ) {
// get it's value
#ifdef __LP64__
result = CFNumberGetValue( (CFNumberRef) tCFTypeRef, kCFNumberSInt64Type, outValue );
#else
result = CFNumberGetValue( (CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, outValue );
#endif // ifdef __LP64__
}
}
}
return (result);
} // IOHIDDevice_GetPtrProperty
//*************************************************************************
//
// IOHIDDevice_SetPtrProperty( inIOHIDDeviceRef, inKey, inValue )
//
// Purpose: convieance function to set a long property of an Device
//
// Inputs: inIOHIDDeviceRef - the Device
// inKey - CFString for the key
// inValue - the value to set it to
// Returns: nothing
//
static void IOHIDDevice_SetPtrProperty(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey, void *inValue) {
#ifdef __LP64__
CFNumberRef tCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &inValue);
#else
CFNumberRef tCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &inValue);
#endif // ifdef __LP64__
if ( tCFNumberRef ) {
IOHIDDeviceSetProperty(inIOHIDDeviceRef, inKey, tCFNumberRef);
CFRelease(tCFNumberRef);
}
} // IOHIDDevice_SetPtrProperty
//*****************************************************
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050

422
src/cocoa/IOHIDDevice_.h Normal file
View file

@ -0,0 +1,422 @@
// File: IOHIDDevice_.h
// Abstract: convieance functions for IOHIDDeviceGetProperty
// Version: 2.0 + 5.3
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2014 Apple Inc. All Rights Reserved.
//
//*****************************************************
#ifndef __IOHIDDevice__
#define __IOHIDDevice__
//*****************************************************
#pragma mark - includes & imports
#include <AvailabilityMacros.h>
#include "IOHIDLib_.h"
//*****************************************************
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
//*****************************************************
#pragma mark - typedef's, struct's, enums, defines, etc.
//-----------------------------------------------------
//*****************************************************
#pragma mark - exported globals
//-----------------------------------------------------
//*****************************************************
#pragma mark - exported function prototypes
//-----------------------------------------------------
//*************************************************************************
//
// HIDIsValidDevice( inIOHIDDeviceRef )
//
// Purpose: validate this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: Boolean - TRUE if we find the device in our( internal ) device list
//
extern Boolean HIDIsValidDevice(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetTransport( inIOHIDDeviceRef )
//
// Purpose: get the Transport CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the Transport CFString for this device
//
extern CFStringRef IOHIDDevice_GetTransport(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetVendorID( inIOHIDDeviceRef )
//
// Purpose: get the vendor ID for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the vendor ID for this device
//
extern uint32_t IOHIDDevice_GetVendorID(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetVendorIDSource( inIOHIDDeviceRef )
//
// Purpose: get the VendorIDSource for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the VendorIDSource for this device
//
extern uint32_t IOHIDDevice_GetVendorIDSource(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetProductID( inIOHIDDeviceRef )
//
// Purpose: get the product ID for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the product ID for this device
//
extern uint32_t IOHIDDevice_GetProductID(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetVersionNumber( inIOHIDDeviceRef )
//
// Purpose: get the VersionNumber CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the VersionNumber for this device
//
extern uint32_t IOHIDDevice_GetVersionNumber(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetManufacturer( inIOHIDDeviceRef )
//
// Purpose: get the Manufacturer CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the Manufacturer CFString for this device
//
extern CFStringRef IOHIDDevice_GetManufacturer(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetProduct( inIOHIDDeviceRef )
//
// Purpose: get the Product CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the Product CFString for this device
//
extern CFStringRef IOHIDDevice_GetProduct(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetSerialNumber( inIOHIDDeviceRef )
//
// Purpose: get the SerialNumber CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the SerialNumber CFString for this device
//
extern CFStringRef IOHIDDevice_GetSerialNumber(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetCountryCode( inIOHIDDeviceRef )
//
// Purpose: get the CountryCode CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the CountryCode for this device
//
extern uint32_t IOHIDDevice_GetCountryCode(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetLocationID( inIOHIDDeviceRef )
//
// Purpose: get the location ID for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the location ID for this device
//
extern uint32_t IOHIDDevice_GetLocationID(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetUsage( inIOHIDDeviceRef )
//
// Purpose: get the usage for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the usage for this device
//
extern uint32_t IOHIDDevice_GetUsage(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetUsagePage( inIOHIDDeviceRef )
//
// Purpose: get the usage page for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the usage page for this device
//
extern uint32_t IOHIDDevice_GetUsagePage(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetUsagePairs( inIOHIDDeviceRef )
//
// Purpose: get the UsagePairs CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFArrayRef - the UsagePairs for this device
//
extern CFArrayRef IOHIDDevice_GetUsagePairs(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetPrimaryUsage( inIOHIDDeviceRef )
//
// Purpose: get the PrimaryUsage CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the PrimaryUsage CFString for this device
//
extern uint32_t IOHIDDevice_GetPrimaryUsage(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetPrimaryUsagePage( inIOHIDDeviceRef )
//
// Purpose: get the PrimaryUsagePage CFString for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: CFStringRef - the PrimaryUsagePage CFString for this device
//
extern uint32_t IOHIDDevice_GetPrimaryUsagePage(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetMaxInputReportSize( inIOHIDDeviceRef )
//
// Purpose: get the MaxInputReportSize for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the MaxInputReportSize for this device
//
extern uint32_t IOHIDDevice_GetMaxInputReportSize(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetMaxOutputReportSize( inIOHIDDeviceRef )
//
// Purpose: get the MaxOutputReportSize for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the MaxOutputReportSize for this device
//
extern uint32_t IOHIDDevice_GetMaxOutputReportSize(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetMaxFeatureReportSize( inIOHIDDeviceRef )
//
// Purpose: get the MaxFeatureReportSize for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the MaxFeatureReportSize for this device
//
extern uint32_t IOHIDDevice_GetMaxFeatureReportSize(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetReportInterval( inIOHIDDeviceRef )
//
// Purpose: get the ReportInterval for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: uint32_t - the ReportInterval for this device
//
extern uint32_t IOHIDDevice_GetReportInterval(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_GetQueue( inIOHIDDeviceRef )
//
// Purpose: get the Queue for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: IOHIDQueueRef - the Queue for this device
//
extern IOHIDQueueRef IOHIDDevice_GetQueue(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_SetQueue( inIOHIDDeviceRef, inQueueRef )
//
// Purpose: Set the Queue for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
// inQueueRef - the Queue
//
// Returns: nothing
//
extern void IOHIDDevice_SetQueue(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDQueueRef inQueueRef);
//*************************************************************************
//
// IOHIDDevice_GetTransaction( inIOHIDDeviceRef )
//
// Purpose: get the Transaction for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
//
// Returns: IOHIDTransactionRef - the Transaction for this device
//
extern IOHIDTransactionRef IOHIDDevice_GetTransaction(IOHIDDeviceRef inIOHIDDeviceRef);
//*************************************************************************
//
// IOHIDDevice_SetTransaction( inIOHIDDeviceRef, inTransactionRef )
//
// Purpose: Set the Transaction for this device
//
// Inputs: inIOHIDDeviceRef - the IDHIDDeviceRef for this device
// inTransactionRef - the Transaction
//
// Returns: nothing
//
extern void IOHIDDevice_SetTransaction(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDTransactionRef inTransactionRef);
//*****************************************************
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif // __IOHIDDevice__ //

509
src/cocoa/IOHIDElement_.c Normal file
View file

@ -0,0 +1,509 @@
// File: IOHIDElement_.c
// Abstract: convieance functions for IOHIDElementGetProperty
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#pragma mark - includes & imports
//-----------------------------------------------------
#include "IOHIDElement_.h"
//*****************************************************
#pragma mark - typedef's, struct's, enums, defines, etc.
//-----------------------------------------------------
//*****************************************************
#pragma mark - local (static) function prototypes
//-----------------------------------------------------
// static Boolean IOHIDElement_GetLongProperty( IOHIDElementRef inElementRef, CFStringRef inKey, long * outValue );
// static void IOHIDElement_SetLongProperty( IOHIDElementRef inElementRef, CFStringRef inKey, long inValue );
//*****************************************************
#pragma mark - exported globals
//-----------------------------------------------------
//*****************************************************
#pragma mark - local (static) globals
//-----------------------------------------------------
//*****************************************************
#pragma mark - exported function implementations
//-----------------------------------------------------
//*************************************************************************
//
// HIDIsValidElement( inIOHIDElementRef )
//
// Purpose: validate this element
//
// Inputs: inIOHIDElementRef - the element
//
// Returns: Boolean - TRUE if this is a valid element ref
//
Boolean HIDIsValidElement(IOHIDElementRef inIOHIDElementRef) {
Boolean result = FALSE; // assume failure (pessimist!)
if ( inIOHIDElementRef ) {
if ( CFGetTypeID(inIOHIDElementRef) ==IOHIDElementGetTypeID() ) {
result = TRUE;
}
}
return (result);
} // HIDIsValidElement
//*************************************************************************
//
// IOHIDElement_GetValue( inElementRef, inIOHIDValueScaleType )
//
// Purpose: returns the current value for an element( polling )
//
// Notes: will return 0 on error conditions which should be accounted for by application
//
// Inputs: inElementRef - the element
// inIOHIDValueScaleType - scale type ( calibrated or physical )
//
// Returns: double - current value for element
//
double IOHIDElement_GetValue(IOHIDElementRef inElementRef, IOHIDValueScaleType inIOHIDValueScaleType) {
long result = 0;
IOHIDValueRef tIOHIDValueRef;
if ( kIOReturnSuccess == IOHIDDeviceGetValue(IOHIDElementGetDevice(inElementRef), inElementRef, &tIOHIDValueRef) ) {
result = IOHIDValueGetScaledValue(tIOHIDValueRef, inIOHIDValueScaleType);
}
return (result);
} // IOHIDElement_GetValue
//*************************************************************************
//
// IOHIDElement_GetCalibrationMin( inElementRef )
//
// Purpose: get the minimum bounds for a calibrated value for this element
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the minimum Calibration value for this element
//
CFIndex IOHIDElement_GetCalibrationMin(IOHIDElementRef inElementRef) {
CFIndex result;
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationMinKey), &result) ) {
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementMaxKey), &result) ) {
result = 0x7FFFFFFF;
}
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationMinKey), result);
}
return (result);
} // IOHIDElement_GetCalibrationMin
//*************************************************************************
//
// IOHIDElement_SetCalibrationMin( inElementRef, inValue )
//
// Purpose: set the minimum bounds for a calibrated value for this element
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the minimum bounds for a calibrated value for this element
//
// Returns: nothing
//
void IOHIDElement_SetCalibrationMin(IOHIDElementRef inElementRef, CFIndex inValue) {
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationMinKey), inValue);
} // IOHIDElement_SetCalibrationMin
//*************************************************************************
//
// IOHIDElement_GetCalibrationMax( inElementRef )
//
// Purpose: get the maximum bounds for a calibrated value for this element
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
CFIndex IOHIDElement_GetCalibrationMax(IOHIDElementRef inElementRef) {
CFIndex result;
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationMaxKey), &result) ) {
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementMinKey), &result) ) {
result = -0x7FFFFFFF;
}
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationMaxKey), result);
}
return (result);
} // IOHIDElement_GetCalibrationMax
//*************************************************************************
//
// IOHIDElement_SetCalibrationMax( inElementRef, inValue )
//
// Purpose: set the maximum bounds for a calibrated value for this element
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
void IOHIDElement_SetCalibrationMax(IOHIDElementRef inElementRef, CFIndex inValue) {
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationMaxKey), inValue);
} // IOHIDElement_SetCalibrationMax
//*************************************************************************
//
// IOHIDElement_GetCalibrationSaturationMin( inElementRef )
//
// Purpose: get the mininum tolerance to be used when calibrating a logical element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
CFIndex IOHIDElement_GetCalibrationSaturationMin(IOHIDElementRef inElementRef) {
CFIndex result;
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationSaturationMinKey), &result) ) {
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementMinKey), &result) ) {
result = -0x7FFFFFFF;
}
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationSaturationMinKey), result);
}
return (result);
} // IOHIDElement_GetCalibrationSaturationMin
//*************************************************************************
//
// IOHIDElement_SetCalibrationSaturationMin( inElementRef, inValue )
//
// Purpose: set the mininum tolerance to be used when calibrating a logical element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
void IOHIDElement_SetCalibrationSaturationMin(IOHIDElementRef inElementRef, CFIndex inValue) {
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationSaturationMinKey), inValue);
} // IOHIDElement_SetCalibrationSaturationMin
//*************************************************************************
//
// IOHIDElement_GetCalibrationSaturationMax( inElementRef )
//
// Purpose: get the maximum tolerance to be used when calibrating a logical element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
CFIndex IOHIDElement_GetCalibrationSaturationMax(IOHIDElementRef inElementRef) {
CFIndex result;
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationSaturationMaxKey), &result) ) {
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementMinKey), &result) ) {
result = -0x7FFFFFFF;
}
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationSaturationMaxKey), result);
}
return (result);
} // IOHIDElement_GetCalibrationSaturationMax
//*************************************************************************
//
// IOHIDElement_SetCalibrationSaturationMax( inElementRef, inValue )
//
// Purpose: set the maximum tolerance to be used when calibrating a logical element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
void IOHIDElement_SetCalibrationSaturationMax(IOHIDElementRef inElementRef, CFIndex inValue) {
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationSaturationMaxKey), inValue);
} // IOHIDElement_SetCalibrationSaturationMax
//*************************************************************************
//
// IOHIDElement_GetCalibrationDeadZoneMin( inElementRef )
//
// Purpose: get the minimum bounds near the midpoint of a logical value in which the value is ignored
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
CFIndex IOHIDElement_GetCalibrationDeadZoneMin(IOHIDElementRef inElementRef) {
CFIndex result;
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationDeadZoneMinKey), &result) ) {
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementMinKey), &result) ) {
result = -0x7FFFFFFF;
}
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationDeadZoneMinKey), result);
}
return (result);
} // IOHIDElement_GetCalibrationDeadZoneMin
//*************************************************************************
//
// IOHIDElement_SetCalibrationDeadZoneMin( inElementRef, inValue )
//
// Purpose: set the minimum bounds near the midpoint of a logical value in which the value is ignored
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
void IOHIDElement_SetCalibrationDeadZoneMin(IOHIDElementRef inElementRef, CFIndex inValue) {
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationDeadZoneMinKey), inValue);
} // IOHIDElement_SetCalibrationDeadZoneMin
//*************************************************************************
//
// IOHIDElement_GetCalibrationDeadZoneMax( inElementRef )
//
// Purpose: get the maximum bounds near the midpoint of a logical value in which the value is ignored
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
CFIndex IOHIDElement_GetCalibrationDeadZoneMax(IOHIDElementRef inElementRef) {
CFIndex result;
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationDeadZoneMaxKey), &result) ) {
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementMinKey), &result) ) {
result = -0x7FFFFFFF;
}
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationDeadZoneMaxKey), result);
}
return (result);
} // IOHIDElement_GetCalibrationDeadZoneMax
//*************************************************************************
//
// IOHIDElement_SetCalibrationDeadZoneMax( inElementRef, inValue )
//
// Purpose: set the maximum bounds near the midpoint of a logical value in which the value is ignored
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
void IOHIDElement_SetCalibrationDeadZoneMax(IOHIDElementRef inElementRef, CFIndex inValue) {
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationDeadZoneMaxKey), inValue);
} // IOHIDElement_SetCalibrationDeadZoneMax
//*************************************************************************
//
// IOHIDElement_GetCalibrationGranularity( inElementRef )
//
// Purpose: get the level of detail returned for a calibrated element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: double_t - the maximum Calibration value for this element
//
double_t IOHIDElement_GetCalibrationGranularity(IOHIDElementRef inElementRef) {
CFIndex result;
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationGranularityKey), &result) ) {
if ( !IOHIDElement_GetLongProperty(inElementRef, CFSTR(kIOHIDElementMinKey), &result) ) {
result = -0x7FFFFFFF;
}
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationGranularityKey), result);
}
return (result);
} // IOHIDElement_GetCalibrationGranularity
//*************************************************************************
//
// IOHIDElement_SetCalibrationGranularity( inElementRef, inValue )
//
// Purpose: set the level of detail returned for a calibrated element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the the level of detail for this element
//
// Returns: nothing
//
void IOHIDElement_SetCalibrationGranularity(IOHIDElementRef inElementRef, double_t inValue) {
IOHIDElement_SetLongProperty(inElementRef, CFSTR(kIOHIDElementCalibrationGranularityKey), inValue);
} // IOHIDElement_SetCalibrationGranularity
//*************************************************************************
//
// IOHIDElement_SetupCalibration( inElementRef )
//
// Purpose: set default values for the element calibration parameters
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: nothing
//
void IOHIDElement_SetupCalibration(IOHIDElementRef inIOHIDElementRef) {
// these are the min/max values returned by IOHIDValueGetScaledValue( v, kIOHIDValueScaleTypeCalibrated );
IOHIDElement_SetCalibrationMin( inIOHIDElementRef, IOHIDElementGetLogicalMin(inIOHIDElementRef) );
IOHIDElement_SetCalibrationMax( inIOHIDElementRef, IOHIDElementGetLogicalMax(inIOHIDElementRef) );
// this is the granularity of the values returned by IOHIDValueGetScaledValue( v, kIOHIDValueScaleTypeCalibrated );
// for example if set to 0.1 the values returned will be multiples of 0.1 ( 0.1, 0.2, 0.3, etc. )
IOHIDElement_SetCalibrationGranularity(inIOHIDElementRef, 0.);
// these define the dead zone (like in the middel of joystick axis)
IOHIDElement_SetCalibrationDeadZoneMin(inIOHIDElementRef, 0);
IOHIDElement_SetCalibrationDeadZoneMax(inIOHIDElementRef, 0);
#if 1
// get the current value of this element
double value = IOHIDElement_GetValue(inIOHIDElementRef, kIOHIDValueScaleTypePhysical);
// use it as our min/mas saturation
IOHIDElement_SetCalibrationSaturationMin(inIOHIDElementRef, value);
IOHIDElement_SetCalibrationSaturationMax(inIOHIDElementRef, value);
#else
// calculate the middle physical value we would expect from this element
CFIndex valueMin = IOHIDElementGetPhysicalMin(inIOHIDElementRef);
CFIndex valueMax = IOHIDElementGetPhysicalMax(inIOHIDElementRef);
CFIndex valueMid = (valueMin + valueMax) / 2;
// use it as our min/mas saturation
// this value determines the min/max values that have been recieved from the device element
IOHIDElement_SetCalibrationSaturationMin(inIOHIDElementRef, valueMid);
IOHIDElement_SetCalibrationSaturationMax(inIOHIDElementRef, valueMid);
// get the current value of this element
double value = IOHIDElement_GetValue(inIOHIDElementRef, kIOHIDValueScaleTypePhysical);
// and use it to adjust the current saturation values if it's outside their range
if ( value < IOHIDElement_GetCalibrationSaturationMin(inIOHIDElementRef) ) {
IOHIDElement_SetCalibrationSaturationMin(inIOHIDElementRef, value);
}
if ( value > IOHIDElement_GetCalibrationSaturationMax(inIOHIDElementRef) ) {
IOHIDElement_SetCalibrationSaturationMax(inIOHIDElementRef, value);
}
#endif
} // IOHIDElement_SetupCalibration
//*****************************************************
#pragma mark - local (static) function implementations
//-----------------------------------------------------
//*************************************************************************
//
// IOHIDElement_GetLongProperty( inElementRef, inKey, outValue )
//
// Purpose: convieance function to return a long property of an element
//
// Inputs: inElementRef - the element
// inKey - CFString for the key
// outValue - address where to store the value
// Returns: Boolean - TRUE if successful
// outValue - the long property's value
//
Boolean IOHIDElement_GetLongProperty(IOHIDElementRef inElementRef, CFStringRef inKey, long *outValue) {
Boolean result = FALSE;
CFTypeRef tCFTypeRef = IOHIDElementGetProperty(inElementRef, inKey);
if ( tCFTypeRef ) {
// if this is a number
if ( CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef) ) {
// get it's value
result = CFNumberGetValue( (CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, outValue );
}
}
return (result);
} /* IOHIDElement_GetLongProperty */
//*************************************************************************
//
// IOHIDElement_SetLongProperty( inElementRef, inKey, inValue )
//
// Purpose: convieance function to set a long property of an element
//
// Inputs: inElementRef - the element
// inKey - CFString for the key
// inValue - the value to set it to
//
// Returns: nothing
//
void IOHIDElement_SetLongProperty(IOHIDElementRef inElementRef, CFStringRef inKey, long inValue) {
CFNumberRef tCFNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &inValue);
if ( tCFNumberRef ) {
IOHIDElementSetProperty(inElementRef, inKey, tCFNumberRef);
CFRelease(tCFNumberRef);
}
} // IOHIDElement_SetLongProperty
//*****************************************************
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050

339
src/cocoa/IOHIDElement_.h Normal file
View file

@ -0,0 +1,339 @@
// File: IOHIDElement_.h
// Abstract: convieance functions for IOHIDElementGetProperty
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#ifndef __IOHIDElement___
#define __IOHIDElement___
//*****************************************************
#pragma mark - includes & imports
#include <AvailabilityMacros.h>
#include "IOHIDLib_.h"
//*****************************************************
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
//*****************************************************
#pragma mark - typedef's, struct's, enums, defines, etc.
//-----------------------------------------------------
//*****************************************************
#pragma mark - exported globals
//-----------------------------------------------------
//*****************************************************
#pragma mark - exported function prototypes
//-----------------------------------------------------
//*************************************************************************
//
// HIDIsValidElement( inIOHIDElementRef )
//
// Purpose: validate this element
//
// Inputs: inIOHIDElementRef - the element
//
// Returns: Boolean - TRUE if this is a valid element ref
//
extern Boolean HIDIsValidElement(IOHIDElementRef inIOHIDElementRef);
//*************************************************************************
//
// IOHIDElement_GetValue( inElementRef, inIOHIDValueScaleType )
//
// Purpose: returns the current value for an element( polling )
//
// Notes: will return 0 on error conditions which should be accounted for by application
//
// Inputs: inElementRef - the element
// inIOHIDValueScaleType - scale type ( calibrated or physical )
//
// Returns: double - current value for element
//
extern double IOHIDElement_GetValue(IOHIDElementRef inElementRef, IOHIDValueScaleType inIOHIDValueScaleType);
//*************************************************************************
//
// IOHIDElement_GetCalibrationMin( inElementRef )
//
// Purpose: get the minimum bounds for a calibrated value for this element
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the minimum Calibration value for this element
//
extern CFIndex IOHIDElement_GetCalibrationMin(IOHIDElementRef inElementRef);
//*************************************************************************
//
// IOHIDElement_SetCalibrationMin( inElementRef, inValue )
//
// Purpose: set the minimum bounds for a calibrated value for this element
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the minimum bounds for a calibrated value for this element
//
// Returns: nothing
//
extern void IOHIDElement_SetCalibrationMin(IOHIDElementRef inElementRef, CFIndex inValue);
//*************************************************************************
//
// IOHIDElement_GetCalibrationMax( inElementRef )
//
// Purpose: get the maximum bounds for a calibrated value for this element
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
extern CFIndex IOHIDElement_GetCalibrationMax(IOHIDElementRef inElementRef);
//*************************************************************************
//
// IOHIDElement_SetCalibrationMax( inElementRef, inValue )
//
// Purpose: set the maximum bounds for a calibrated value for this element
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
extern void IOHIDElement_SetCalibrationMax(IOHIDElementRef inElementRef, CFIndex inValue);
//*************************************************************************
//
// IOHIDElement_GetCalibrationSaturationMin( inElementRef )
//
// Purpose: get the mininum tolerance to be used when calibrating a logical element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
extern CFIndex IOHIDElement_GetCalibrationSaturationMin(IOHIDElementRef inElementRef);
//*************************************************************************
//
// IOHIDElement_SetCalibrationSaturationMin( inElementRef, inValue )
//
// Purpose: set the mininum tolerance to be used when calibrating a logical element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
extern void IOHIDElement_SetCalibrationSaturationMin(IOHIDElementRef inElementRef, CFIndex inValue);
//*************************************************************************
//
// IOHIDElement_GetCalibrationSaturationMax( inElementRef )
//
// Purpose: get the maximum tolerance to be used when calibrating a logical element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
extern CFIndex IOHIDElement_GetCalibrationSaturationMax(IOHIDElementRef inElementRef);
//*************************************************************************
//
// IOHIDElement_SetCalibrationSaturationMax( inElementRef, inValue )
//
// Purpose: set the maximum tolerance to be used when calibrating a logical element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
extern void IOHIDElement_SetCalibrationSaturationMax(IOHIDElementRef inElementRef, CFIndex inValue);
//*************************************************************************
//
// IOHIDElement_GetCalibrationDeadZoneMin( inElementRef )
//
// Purpose: get the minimum bounds near the midpoint of a logical value in which the value is ignored
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
extern CFIndex IOHIDElement_GetCalibrationDeadZoneMin(IOHIDElementRef inElementRef);
//*************************************************************************
//
// IOHIDElement_SetCalibrationDeadZoneMin( inElementRef, inValue )
//
// Purpose: set the minimum bounds near the midpoint of a logical value in which the value is ignored
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
extern void IOHIDElement_SetCalibrationDeadZoneMin(IOHIDElementRef inElementRef, CFIndex inValue);
//*************************************************************************
//
// IOHIDElement_GetCalibrationDeadZoneMax( inElementRef )
//
// Purpose: get the maximum bounds near the midpoint of a logical value in which the value is ignored
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: CFIndex - the maximum Calibration value for this element
//
extern CFIndex IOHIDElement_GetCalibrationDeadZoneMax(IOHIDElementRef inElementRef);
//*************************************************************************
//
// IOHIDElement_SetCalibrationDeadZoneMax( inElementRef, inValue )
//
// Purpose: set the maximum bounds near the midpoint of a logical value in which the value is ignored
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the maximum Calibration value for this element
//
// Returns: nothing
//
extern void IOHIDElement_SetCalibrationDeadZoneMax(IOHIDElementRef inElementRef, CFIndex inValue);
//*************************************************************************
//
// IOHIDElement_GetCalibrationGranularity( inElementRef )
//
// Purpose: get the level of detail returned for a calibrated element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: double_t - the maximum Calibration value for this element
//
extern double_t IOHIDElement_GetCalibrationGranularity(IOHIDElementRef inElementRef);
//*************************************************************************
//
// IOHIDElement_SetCalibrationGranularity( inElementRef, inValue )
//
// Purpose: set the level of detail returned for a calibrated element value
//
// Inputs: inElementRef - the IOHIDElementRef for this element
// inValue - the the level of detail for this element
//
// Returns: nothing
//
extern void IOHIDElement_SetCalibrationGranularity(IOHIDElementRef inElementRef, double_t inValue);
//*************************************************************************
//
// IOHIDElement_SetupCalibration( inElementRef )
//
// Purpose: set default values for the element calibration parameters
//
// Inputs: inElementRef - the IOHIDElementRef for this element
//
// Returns: nothing
//
extern void IOHIDElement_SetupCalibration(IOHIDElementRef inIOHIDElementRef);
extern Boolean IOHIDElement_GetLongProperty(IOHIDElementRef inElementRef, CFStringRef inKey, long *outValue);
extern void IOHIDElement_SetLongProperty(IOHIDElementRef inElementRef, CFStringRef inKey, long inValue);
//*****************************************************
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif // __IOHIDElement___ //

111
src/cocoa/IOHIDLib_.h Normal file
View file

@ -0,0 +1,111 @@
// File: IOHIDLib_.h
// Abstract: Single include file for all header files of IOHIDLib
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#ifndef __IOHIDLib___
#define __IOHIDLib___
//*****************************************************
#pragma mark - includes & imports
//-----------------------------------------------------
#include <IOKit/hid/IOHIDLib.h>
#include "IOHIDDevice_.h"
#include "IOHIDElement_.h"
#include "ImmrHIDUtilAddOn.h"
//*****************************************************
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_IMPORT
#pragma import on
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
//*****************************************************
#pragma mark - typedef's, struct's, enums, defines, etc.
//-----------------------------------------------------
//*****************************************************
#pragma mark - exported globals
//-----------------------------------------------------
//*****************************************************
#pragma mark - exported function prototypes
//-----------------------------------------------------
//*****************************************************
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef PRAGMA_IMPORT_OFF
#pragma import off
#elif PRAGMA_IMPORT
#pragma import reset
#endif
#ifdef __cplusplus
}
#endif
#endif // __IOHIDLib___

View file

@ -0,0 +1,108 @@
// File: ImmrHIDUtilAddOn.c
// Abstract: Glue code to convert IOHIDDeviceRef's to (FFB) io_object_t's
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#include <mach/mach.h>
#include <mach/mach_error.h>
#include "ImmrHIDUtilAddOn.h"
//---------------------------------------------------------------------------------
//
// AllocateHIDObjectFromIOHIDDeviceRef( )
//
// returns:
// NULL, or acceptable io_object_t
//
//---------------------------------------------------------------------------------
io_service_t AllocateHIDObjectFromIOHIDDeviceRef(IOHIDDeviceRef inIOHIDDeviceRef) {
io_service_t result = 0L;
if ( inIOHIDDeviceRef ) {
// Set up the matching criteria for the devices we're interested in.
// We are interested in instances of class IOHIDDevice.
// matchingDict is consumed below( in IOServiceGetMatchingService )
// so we have no leak here.
CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOHIDDeviceKey);
if ( matchingDict ) {
// Add a key for locationID to our matching dictionary. This works for matching to
// IOHIDDevices, so we will only look for a device attached to that particular port
// on the machine.
CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty( inIOHIDDeviceRef, CFSTR(kIOHIDLocationIDKey) );
if ( tCFTypeRef ) {
CFDictionaryAddValue(matchingDict, CFSTR(kIOHIDLocationIDKey), tCFTypeRef);
// CFRelease( tCFTypeRef ); // don't release objects that we "Get".
// IOServiceGetMatchingService assumes that we already know that there is only one device
// that matches. This way we don't have to do the whole iteration dance to look at each
// device that matches. This is a new API in 10.2
result = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
}
// Note: We're not leaking the matchingDict.
// One reference is consumed by IOServiceGetMatchingServices
}
}
return (result);
} // AllocateHIDObjectFromIOHIDDeviceRef
//---------------------------------------------------------------------------------
//
// FreeHIDObject( )
//
//---------------------------------------------------------------------------------
bool FreeHIDObject(io_service_t inHIDObject) {
kern_return_t kr;
kr = IOObjectRelease(inHIDObject);
return (kIOReturnSuccess == kr);
} // FreeHIDObject
#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= 1050

View file

@ -0,0 +1,50 @@
// File: ImmrHIDUtilAddOn.h
// Abstract: Glue code to convert IOHIDDeviceRef's to (FFB) io_object_t's
// Version: 2.0
//
// Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
// Inc. ("Apple") in consideration of your agreement to the following
// terms, and your use, installation, modification or redistribution of
// this Apple software constitutes acceptance of these terms. If you do
// not agree with these terms, please do not use, install, modify or
// redistribute this Apple software.
//
// In consideration of your agreement to abide by the following terms, and
// subject to these terms, Apple grants you a personal, non-exclusive
// license, under Apple's copyrights in this original Apple software (the
// "Apple Software"), to use, reproduce, modify and redistribute the Apple
// Software, with or without modifications, in source and/or binary forms;
// provided that if you redistribute the Apple Software in its entirety and
// without modifications, you must retain this notice and the following
// text and disclaimers in all such redistributions of the Apple Software.
// Neither the name, trademarks, service marks or logos of Apple Inc. may
// be used to endorse or promote products derived from the Apple Software
// without specific prior written permission from Apple. Except as
// expressly stated in this notice, no other rights or licenses, express or
// implied, are granted by Apple herein, including but not limited to any
// patent rights that may be infringed by your derivative works or by other
// works in which the Apple Software may be incorporated.
//
// The Apple Software is provided by Apple on an "AS IS" basis. APPLE
// MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
// THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
// OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
//
// IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
// MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
// AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
// STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (C) 2009 Apple Inc. All Rights Reserved.
//
//*****************************************************
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDLib.h>
extern io_service_t AllocateHIDObjectFromIOHIDDeviceRef(IOHIDDeviceRef inIOHIDDeviceRef);
extern bool FreeHIDObject(io_object_t inHIDObject);

2171
src/cocoa/i_backend_cocoa.mm Normal file

File diff suppressed because it is too large Load diff

820
src/cocoa/i_joystick.cpp Normal file
View file

@ -0,0 +1,820 @@
/*
** i_joystick.cpp
**
**---------------------------------------------------------------------------
** Copyright 2012-2014 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "m_joy.h"
#include <AvailabilityMacros.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
#include "HID_Utilities_External.h"
#include "d_event.h"
#include "doomdef.h"
#include "templates.h"
#include "i_osversion.h"
namespace
{
FString ToFString( const CFStringRef string )
{
if ( NULL == string )
{
return FString();
}
const CFIndex stringLength = CFStringGetLength( string );
if ( 0 == stringLength )
{
return FString();
}
const size_t bufferSize = CFStringGetMaximumSizeForEncoding( stringLength, kCFStringEncodingUTF8 ) + 1;
char buffer[ bufferSize ];
memset( buffer, 0, bufferSize );
CFStringGetCString( string, buffer, bufferSize, kCFStringEncodingUTF8 );
return FString( buffer );
}
class IOKitJoystick : public IJoystickConfig
{
public:
explicit IOKitJoystick( IOHIDDeviceRef device );
virtual ~IOKitJoystick();
virtual FString GetName();
virtual float GetSensitivity();
virtual void SetSensitivity( float scale );
virtual int GetNumAxes();
virtual float GetAxisDeadZone( int axis );
virtual EJoyAxis GetAxisMap( int axis );
virtual const char* GetAxisName( int axis );
virtual float GetAxisScale( int axis );
virtual void SetAxisDeadZone( int axis, float deadZone );
virtual void SetAxisMap( int axis, EJoyAxis gameAxis );
virtual void SetAxisScale( int axis, float scale );
virtual bool IsSensitivityDefault();
virtual bool IsAxisDeadZoneDefault( int axis );
virtual bool IsAxisMapDefault( int axis );
virtual bool IsAxisScaleDefault( int axis );
virtual void SetDefaultConfig();
virtual FString GetIdentifier();
void AddAxes( float axes[ NUM_JOYAXIS ] ) const;
void Update();
private:
IOHIDDeviceRef m_device;
float m_sensitivity;
struct AxisInfo
{
char name[ 64 ];
float value;
float deadZone;
float defaultDeadZone;
float sensitivity;
float defaultSensitivity;
EJoyAxis gameAxis;
EJoyAxis defaultGameAxis;
IOHIDElementRef element;
};
TArray< AxisInfo > m_axes;
TArray< IOHIDElementRef > m_buttons;
TArray< IOHIDElementRef > m_POVs;
static const float DEFAULT_DEADZONE;
static const float DEFAULT_SENSITIVITY;
bool ProcessAxis ( const IOHIDValueRef value );
bool ProcessButton( const IOHIDValueRef value );
bool ProcessPOV ( const IOHIDValueRef value );
};
const float IOKitJoystick::DEFAULT_DEADZONE = 0.25f;
const float IOKitJoystick::DEFAULT_SENSITIVITY = 1.0f;
IOKitJoystick::IOKitJoystick( IOHIDDeviceRef device )
: m_device( device )
, m_sensitivity( DEFAULT_SENSITIVITY )
{
IOHIDElementRef element = HIDGetFirstDeviceElement( device, kHIDElementTypeInput );
while ( NULL != element )
{
const uint32_t usagePage = IOHIDElementGetUsagePage( element );
if ( kHIDPage_GenericDesktop == usagePage )
{
const uint32_t usage = IOHIDElementGetUsage( element );
if ( kHIDUsage_GD_Slider == usage
|| kHIDUsage_GD_X == usage || kHIDUsage_GD_Y == usage || kHIDUsage_GD_Z == usage
|| kHIDUsage_GD_Rx == usage || kHIDUsage_GD_Ry == usage || kHIDUsage_GD_Rz == usage )
{
AxisInfo axis;
memset( &axis, 0, sizeof( axis ) );
if ( const CFStringRef name = IOHIDElementGetName( element ) )
{
CFStringGetCString( name, axis.name, sizeof( axis.name ) - 1, kCFStringEncodingUTF8 );
}
else
{
snprintf( axis.name, sizeof( axis.name ), "Axis %i", m_axes.Size() + 1 );
}
axis.element = element;
m_axes.Push( axis );
IOHIDElement_SetCalibrationMin( element, -1 );
IOHIDElement_SetCalibrationMax( element, 1 );
HIDQueueElement( m_device, element );
}
else if ( kHIDUsage_GD_Hatswitch == usage && m_POVs.Size() < 4 )
{
m_POVs.Push( element );
HIDQueueElement( m_device, element );
}
}
else if ( kHIDPage_Button == usagePage )
{
m_buttons.Push( element );
HIDQueueElement( m_device, element );
}
element = HIDGetNextDeviceElement( element, kHIDElementTypeInput );
}
SetDefaultConfig();
}
IOKitJoystick::~IOKitJoystick()
{
M_SaveJoystickConfig( this );
}
FString IOKitJoystick::GetName()
{
FString result;
result += ToFString( IOHIDDevice_GetManufacturer( m_device ) );
result += " ";
result += ToFString( IOHIDDevice_GetProduct( m_device ) );
return result;
}
float IOKitJoystick::GetSensitivity()
{
return m_sensitivity;
}
void IOKitJoystick::SetSensitivity( float scale )
{
m_sensitivity = scale;
}
int IOKitJoystick::GetNumAxes()
{
return static_cast< int >( m_axes.Size() );
}
#define IS_AXIS_VALID ( static_cast< unsigned int >( axis ) < m_axes.Size() )
float IOKitJoystick::GetAxisDeadZone( int axis )
{
return IS_AXIS_VALID ? m_axes[ axis ].deadZone : 0.0f;
}
EJoyAxis IOKitJoystick::GetAxisMap( int axis )
{
return IS_AXIS_VALID ? m_axes[ axis ].gameAxis : JOYAXIS_None;
}
const char* IOKitJoystick::GetAxisName( int axis )
{
return IS_AXIS_VALID ? m_axes[ axis ].name : "Invalid";
}
float IOKitJoystick::GetAxisScale( int axis )
{
return IS_AXIS_VALID ? m_axes[ axis ].sensitivity : 0.0f;
}
void IOKitJoystick::SetAxisDeadZone( int axis, float deadZone )
{
if ( IS_AXIS_VALID )
{
m_axes[ axis ].deadZone = clamp( deadZone, 0.0f, 1.0f );
}
}
void IOKitJoystick::SetAxisMap( int axis, EJoyAxis gameAxis )
{
if ( IS_AXIS_VALID )
{
m_axes[ axis ].gameAxis = ( gameAxis > JOYAXIS_None && gameAxis < NUM_JOYAXIS )
? gameAxis
: JOYAXIS_None;
}
}
void IOKitJoystick::SetAxisScale( int axis, float scale )
{
if ( IS_AXIS_VALID )
{
m_axes[ axis ].sensitivity = scale;
}
}
bool IOKitJoystick::IsSensitivityDefault()
{
return DEFAULT_SENSITIVITY == m_sensitivity;
}
bool IOKitJoystick::IsAxisDeadZoneDefault( int axis )
{
return IS_AXIS_VALID
? ( m_axes[ axis ].deadZone == m_axes[ axis ].defaultDeadZone )
: true;
}
bool IOKitJoystick::IsAxisMapDefault( int axis )
{
return IS_AXIS_VALID
? ( m_axes[ axis ].gameAxis == m_axes[ axis ].defaultGameAxis )
: true;
}
bool IOKitJoystick::IsAxisScaleDefault( int axis )
{
return IS_AXIS_VALID
? ( m_axes[ axis ].sensitivity == m_axes[ axis ].defaultSensitivity )
: true;
}
#undef IS_AXIS_VALID
void IOKitJoystick::SetDefaultConfig()
{
m_sensitivity = DEFAULT_SENSITIVITY;
const size_t axisCount = m_axes.Size();
for ( size_t i = 0; i < axisCount; ++i )
{
m_axes[i].deadZone = DEFAULT_DEADZONE;
m_axes[i].sensitivity = DEFAULT_SENSITIVITY;
m_axes[i].gameAxis = JOYAXIS_None;
}
// Two axes? Horizontal is yaw and vertical is forward.
if ( 2 == axisCount)
{
m_axes[0].gameAxis = JOYAXIS_Yaw;
m_axes[1].gameAxis = JOYAXIS_Forward;
}
// Three axes? First two are movement, third is yaw.
else if ( axisCount >= 3 )
{
m_axes[0].gameAxis = JOYAXIS_Side;
m_axes[1].gameAxis = JOYAXIS_Forward;
m_axes[2].gameAxis = JOYAXIS_Yaw;
// Four axes? First two are movement, last two are looking around.
if ( axisCount >= 4 )
{
m_axes[3].gameAxis = JOYAXIS_Pitch;
// ??? m_axes[3].sensitivity = 0.75f;
// Five axes? Use the fifth one for moving up and down.
if ( axisCount >= 5 )
{
m_axes[4].gameAxis = JOYAXIS_Up;
}
}
}
// If there is only one axis, then we make no assumptions about how
// the user might want to use it.
// Preserve defaults for config saving.
for ( size_t i = 0; i < axisCount; ++i )
{
m_axes[i].defaultDeadZone = m_axes[i].deadZone;
m_axes[i].defaultSensitivity = m_axes[i].sensitivity;
m_axes[i].defaultGameAxis = m_axes[i].gameAxis;
}
}
FString IOKitJoystick::GetIdentifier()
{
char identifier[ 32 ] = {0};
snprintf( identifier, sizeof( identifier ), "VID_%04x_PID_%04x",
IOHIDDevice_GetVendorID( m_device ), IOHIDDevice_GetProductID( m_device ) );
return FString( identifier );
}
void IOKitJoystick::AddAxes( float axes[ NUM_JOYAXIS ] ) const
{
for ( size_t i = 0, count = m_axes.Size(); i < count; ++i )
{
const EJoyAxis axis = m_axes[i].gameAxis;
if ( JOYAXIS_None == axis )
{
continue;
}
axes[ axis ] -= m_axes[i].value;
}
}
void IOKitJoystick::Update()
{
IOHIDValueRef value = NULL;
while ( HIDGetEvent( m_device, &value ) && NULL != value )
{
ProcessAxis( value ) || ProcessButton( value ) || ProcessPOV( value );
CFRelease( value );
}
}
bool IOKitJoystick::ProcessAxis( const IOHIDValueRef value )
{
const IOHIDElementRef element = IOHIDValueGetElement( value );
if ( NULL == element )
{
return false;
}
for ( size_t i = 0, count = m_axes.Size(); i < count; ++i )
{
if ( element != m_axes[i].element )
{
continue;
}
AxisInfo& axis = m_axes[i];
const double scaledValue = IOHIDValueGetScaledValue( value, kIOHIDValueScaleTypeCalibrated );
const double filteredValue = Joy_RemoveDeadZone( scaledValue, axis.deadZone, NULL );
axis.value = static_cast< float >( filteredValue * m_sensitivity * axis.sensitivity );
return true;
}
return false;
}
bool IOKitJoystick::ProcessButton( const IOHIDValueRef value )
{
const IOHIDElementRef element = IOHIDValueGetElement( value );
if ( NULL == element )
{
return false;
}
for ( size_t i = 0, count = m_buttons.Size(); i < count; ++i )
{
if ( element != m_buttons[i] )
{
continue;
}
const int newButton = IOHIDValueGetIntegerValue( value ) & 1;
const int oldButton = ~newButton;
Joy_GenerateButtonEvents( oldButton, newButton, 1,
static_cast< int >( KEY_FIRSTJOYBUTTON + i ) );
return true;
}
return false;
}
bool IOKitJoystick::ProcessPOV( const IOHIDValueRef value )
{
const IOHIDElementRef element = IOHIDValueGetElement( value );
if ( NULL == element )
{
return false;
}
for ( size_t i = 0, count = m_POVs.Size(); i < count; ++i )
{
if ( element != m_POVs[i] )
{
continue;
}
const CFIndex direction = IOHIDValueGetIntegerValue( value );
// Default values is for Up/North
int oldButtons = 0;
int newButtons = 1;
int numButtons = 1;
int baseButton = KEY_JOYPOV1_UP;
switch ( direction )
{
case 0: // N
break;
case 1: // NE
newButtons = 3;
numButtons = 2;
break;
case 2: // E
baseButton = KEY_JOYPOV1_RIGHT;
break;
case 3: // SE
newButtons = 3;
numButtons = 2;
baseButton = KEY_JOYPOV1_RIGHT;
break;
case 4: // S
baseButton = KEY_JOYPOV1_DOWN;
break;
case 5: // SW
newButtons = 3;
numButtons = 2;
baseButton = KEY_JOYPOV1_DOWN;
break;
case 6: // W
baseButton = KEY_JOYPOV1_LEFT;
break;
case 7: // NW
newButtons = 9; // UP and LEFT
numButtons = 4;
break;
default:
// release all four directions
oldButtons = 15;
newButtons = 0;
numButtons = 4;
break;
}
Joy_GenerateButtonEvents( oldButtons, newButtons, numButtons,
static_cast< int >( baseButton + i * 4 ) );
}
return false;
}
// ---------------------------------------------------------------------------
class IOKitJoystickManager
{
public:
IOKitJoystickManager();
~IOKitJoystickManager();
void GetJoysticks( TArray< IJoystickConfig* >& joysticks ) const;
void AddAxes( float axes[ NUM_JOYAXIS ] ) const;
// Updates axes/buttons states
void Update();
// Rebuilds device list
void Rescan();
private:
TArray< IOKitJoystick* > m_joysticks;
static void OnDeviceChanged( void* context, IOReturn result, void* sender, IOHIDDeviceRef device );
void ReleaseJoysticks();
void EnableCallbacks();
void DisableCallbacks();
};
IOKitJoystickManager::IOKitJoystickManager()
{
Rescan();
}
IOKitJoystickManager::~IOKitJoystickManager()
{
ReleaseJoysticks();
DisableCallbacks();
HIDReleaseDeviceList();
}
void IOKitJoystickManager::GetJoysticks( TArray< IJoystickConfig* >& joysticks ) const
{
const size_t joystickCount = m_joysticks.Size();
joysticks.Resize( joystickCount );
for ( size_t i = 0; i < joystickCount; ++i )
{
M_LoadJoystickConfig( m_joysticks[i] );
joysticks[i] = m_joysticks[i];
}
}
void IOKitJoystickManager::AddAxes( float axes[ NUM_JOYAXIS ] ) const
{
for ( size_t i = 0, count = m_joysticks.Size(); i < count; ++i )
{
m_joysticks[i]->AddAxes( axes );
}
}
void IOKitJoystickManager::Update()
{
for ( size_t i = 0, count = m_joysticks.Size(); i < count; ++i )
{
m_joysticks[i]->Update();
}
}
void IOKitJoystickManager::Rescan()
{
ReleaseJoysticks();
DisableCallbacks();
const int usageCount = 2;
const UInt32 usagePages[ usageCount ] =
{
kHIDPage_GenericDesktop,
kHIDPage_GenericDesktop
};
const UInt32 usages[ usageCount ] =
{
kHIDUsage_GD_Joystick,
kHIDUsage_GD_GamePad
};
if ( HIDUpdateDeviceList( usagePages, usages, usageCount ) )
{
IOHIDDeviceRef device = HIDGetFirstDevice();
while ( NULL != device )
{
IOKitJoystick* joystick = new IOKitJoystick( device );
m_joysticks.Push( joystick );
device = HIDGetNextDevice( device );
}
}
else
{
Printf( "IOKitJoystickManager: Failed to build gamepad/joystick device list.\n" );
}
EnableCallbacks();
}
void IOKitJoystickManager::OnDeviceChanged( void* context, IOReturn result, void* sender, IOHIDDeviceRef device )
{
event_t event;
memset( &event, 0, sizeof( event ) );
event.type = EV_DeviceChange;
D_PostEvent( &event );
}
void IOKitJoystickManager::ReleaseJoysticks()
{
for ( size_t i = 0, count = m_joysticks.Size(); i < count; ++i )
{
delete m_joysticks[i];
}
m_joysticks.Clear();
}
void IOKitJoystickManager::EnableCallbacks()
{
if ( NULL == gIOHIDManagerRef )
{
return;
}
IOHIDManagerRegisterDeviceMatchingCallback( gIOHIDManagerRef, OnDeviceChanged, this );
IOHIDManagerRegisterDeviceRemovalCallback ( gIOHIDManagerRef, OnDeviceChanged, this );
IOHIDManagerScheduleWithRunLoop( gIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
}
void IOKitJoystickManager::DisableCallbacks()
{
if ( NULL == gIOHIDManagerRef )
{
return;
}
IOHIDManagerUnscheduleFromRunLoop( gIOHIDManagerRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
IOHIDManagerRegisterDeviceMatchingCallback( gIOHIDManagerRef, NULL, NULL );
IOHIDManagerRegisterDeviceRemovalCallback ( gIOHIDManagerRef, NULL, NULL );
}
IOKitJoystickManager* s_joystickManager;
} // unnamed namespace
// ---------------------------------------------------------------------------
void I_StartupJoysticks()
{
// HID Manager API is available on 10.5 (Darwin 9.x) or newer
if (darwinVersion.major >= 9)
{
s_joystickManager = new IOKitJoystickManager;
}
}
void I_ShutdownJoysticks()
{
delete s_joystickManager;
}
void I_GetJoysticks( TArray< IJoystickConfig* >& sticks )
{
if ( NULL != s_joystickManager )
{
s_joystickManager->GetJoysticks( sticks );
}
}
void I_GetAxes( float axes[ NUM_JOYAXIS ] )
{
for ( size_t i = 0; i < NUM_JOYAXIS; ++i )
{
axes[i] = 0.0f;
}
if ( use_joystick && NULL != s_joystickManager )
{
s_joystickManager->AddAxes( axes );
}
}
IJoystickConfig* I_UpdateDeviceList()
{
if ( use_joystick && NULL != s_joystickManager )
{
s_joystickManager->Rescan();
}
return NULL;
}
// ---------------------------------------------------------------------------
void I_ProcessJoysticks()
{
if ( use_joystick && NULL != s_joystickManager )
{
s_joystickManager->Update();
}
}
#else // prior to 10.5
void I_StartupJoysticks()
{
}
void I_ShutdownJoysticks()
{
}
void I_GetJoysticks(TArray<IJoystickConfig*>& sticks)
{
sticks.Clear();
}
void I_GetAxes(float axes[NUM_JOYAXIS])
{
for (size_t i = 0; i < NUM_JOYAXIS; ++i)
{
axes[i] = 0.0f;
}
}
IJoystickConfig *I_UpdateDeviceList()
{
return NULL;
}
void I_ProcessJoysticks()
{
}
#endif // 10.5 or higher

43
src/cocoa/i_osversion.h Executable file
View file

@ -0,0 +1,43 @@
/*
** i_osversion.h
**
**---------------------------------------------------------------------------
** Copyright 2012-2014 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <stdint.h>
struct DarwinVersion
{
uint16_t major;
uint16_t minor;
uint16_t bugfix;
};
extern const DarwinVersion darwinVersion;

52
src/cocoa/i_rbopts.h Normal file
View file

@ -0,0 +1,52 @@
/*
** i_rbopts.h
**
**---------------------------------------------------------------------------
** Copyright 2014 Alexey Lysiuk
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef SRC_COCOA_I_RBOPTS_H_INCLUDED
#define SRC_COCOA_I_RBOPTS_H_INCLUDED
struct RenderBufferOptions
{
float pixelScale;
float shiftX;
float shiftY;
float width;
float height;
bool dirty;
};
extern RenderBufferOptions rbOpts;
#endif // SRC_COCOA_I_RBOPTS_H_INCLUDED

190
src/cocoa/i_timer.cpp Normal file
View file

@ -0,0 +1,190 @@
#include <assert.h>
#include <sys/time.h>
#include <pthread.h>
#include <libkern/OSAtomic.h>
#include <SDL.h>
#include "basictypes.h"
#include "basicinlines.h"
#include "doomdef.h"
#include "i_system.h"
#include "templates.h"
unsigned int I_MSTime()
{
return SDL_GetTicks();
}
unsigned int I_FPSTime()
{
return SDL_GetTicks();
}
bool g_isTicFrozen;
namespace
{
timespec GetNextTickTime()
{
static const long MILLISECONDS_IN_SECOND = 1000;
static const long MICROSECONDS_IN_SECOND = 1000 * MILLISECONDS_IN_SECOND;
static const long NANOSECONDS_IN_SECOND = 1000 * MICROSECONDS_IN_SECOND;
static timespec ts = {};
if (__builtin_expect((0 == ts.tv_sec), 0))
{
timeval tv;
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = (tv.tv_usec + MICROSECONDS_IN_SECOND / TICRATE) * MILLISECONDS_IN_SECOND;
}
else
{
ts.tv_nsec += (MICROSECONDS_IN_SECOND / TICRATE) * MILLISECONDS_IN_SECOND;
}
if (ts.tv_nsec >= NANOSECONDS_IN_SECOND)
{
ts.tv_sec++;
ts.tv_nsec -= NANOSECONDS_IN_SECOND;
}
return ts;
}
pthread_cond_t s_timerEvent;
pthread_mutex_t s_timerMutex;
pthread_t s_timerThread;
bool s_timerInitialized;
bool s_timerExitRequested;
uint32_t s_ticStart;
uint32_t s_timerStart;
int s_tics;
void* TimerThreadFunc(void*)
{
assert(s_timerInitialized);
assert(!s_timerExitRequested);
while (true)
{
if (s_timerExitRequested)
{
break;
}
const timespec timeToNextTick = GetNextTickTime();
pthread_mutex_lock(&s_timerMutex);
pthread_cond_timedwait(&s_timerEvent, &s_timerMutex, &timeToNextTick);
if (!g_isTicFrozen)
{
// The following GCC/Clang intrinsic can be used instead of OS X specific function:
// __sync_add_and_fetch(&s_tics, 1);
// Although it's not supported on all platform/compiler combination,
// e.g. GCC 4.0.1 with PowerPC target architecture
OSAtomicIncrement32(&s_tics);
}
s_timerStart = SDL_GetTicks();
pthread_cond_broadcast(&s_timerEvent);
pthread_mutex_unlock(&s_timerMutex);
}
return NULL;
}
int GetTimeThreaded(bool saveMS)
{
if (saveMS)
{
s_ticStart = s_timerStart;
}
return s_tics;
}
int WaitForTicThreaded(int prevTic)
{
assert(!g_isTicFrozen);
while (s_tics <= prevTic)
{
pthread_mutex_lock(&s_timerMutex);
pthread_cond_wait(&s_timerEvent, &s_timerMutex);
pthread_mutex_unlock(&s_timerMutex);
}
return s_tics;
}
void FreezeTimeThreaded(bool frozen)
{
g_isTicFrozen = frozen;
}
} // unnamed namespace
fixed_t I_GetTimeFrac(uint32* ms)
{
const uint32_t now = SDL_GetTicks();
if (NULL != ms)
{
*ms = s_ticStart + 1000 / TICRATE;
}
return 0 == s_ticStart
? FRACUNIT
: clamp<fixed_t>( (now - s_ticStart) * FRACUNIT * TICRATE / 1000, 0, FRACUNIT);
}
void I_InitTimer ()
{
assert(!s_timerInitialized);
s_timerInitialized = true;
pthread_cond_init (&s_timerEvent, NULL);
pthread_mutex_init(&s_timerMutex, NULL);
pthread_create(&s_timerThread, NULL, TimerThreadFunc, NULL);
I_GetTime = GetTimeThreaded;
I_WaitForTic = WaitForTicThreaded;
I_FreezeTime = FreezeTimeThreaded;
}
void I_ShutdownTimer ()
{
if (!s_timerInitialized)
{
// This might happen if Cancel button was pressed
// in the IWAD selector window
return;
}
s_timerExitRequested = true;
pthread_join(s_timerThread, NULL);
pthread_mutex_destroy(&s_timerMutex);
pthread_cond_destroy (&s_timerEvent);
}

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string>zdoom.icns</string>
<key>CFBundleIdentifier</key>
<string>org.zdoom.zdoom</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>ZDoom</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>Version 2.8.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.action-games</string>
<key>LSMinimumSystemVersion</key>
<string>10.4</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>Doom Resource File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>wad</string>
<string>pk3</string>
<string>zip</string>
<string>pk7</string>
<string>7z</string>
</array>
</dict>
</array>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

BIN
src/cocoa/zdoom.icns Normal file

Binary file not shown.

View file

@ -145,12 +145,20 @@ bool CT_Responder (event_t *ev)
CT_BackSpace ();
return true;
}
#ifdef __APPLE__
else if (ev->data1 == 'C' && (ev->data3 & GKM_META))
#else // !__APPLE__
else if (ev->data1 == 'C' && (ev->data3 & GKM_CTRL))
#endif // __APPLE__
{
I_PutInClipboard ((char *)ChatQueue);
return true;
}
#ifdef __APPLE__
else if (ev->data1 == 'V' && (ev->data3 & GKM_META))
#else // !__APPLE__
else if (ev->data1 == 'V' && (ev->data3 & GKM_CTRL))
#endif // __APPLE__
{
CT_PasteChat(I_GetFromClipboard(false));
}

View file

@ -70,7 +70,8 @@ enum GUIKeyModifiers
GKM_SHIFT = 1,
GKM_CTRL = 2,
GKM_ALT = 4,
GKM_LBUTTON = 8
GKM_META = 8,
GKM_LBUTTON = 16
};
// Special codes for some GUI keys, including a few real ASCII codes.

View file

@ -1128,11 +1128,8 @@ void G_Ticker ()
// check, not just the player's x position like BOOM.
DWORD rngsum = FRandom::StaticSumSeeds ();
if ((gametic % ticdup) == 0)
{
//Added by MC: For some of that bot stuff. The main bot function.
bglobal.Main (buf);
}
//Added by MC: For some of that bot stuff. The main bot function.
bglobal.Main ();
for (i = 0; i < MAXPLAYERS; i++)
{
@ -1395,7 +1392,6 @@ void G_PlayerReborn (int player)
if (gamestate != GS_TITLELEVEL)
{
// [GRB] Give inventory specified in DECORATE
actor->GiveDefaultInventory ();
p->ReadyWeapon = p->PendingWeapon;
@ -1406,6 +1402,7 @@ void G_PlayerReborn (int player)
{
botskill_t skill = p->Bot->skill;
p->Bot->Clear ();
p->Bot->player = p;
p->Bot->skill = skill;
}
}

View file

@ -1164,6 +1164,8 @@ void G_StartTravel ()
}
}
}
bglobal.StartTravel ();
}
//==========================================================================
@ -1261,6 +1263,8 @@ void G_FinishTravel ()
}
}
}
bglobal.FinishTravel ();
}
//==========================================================================

View file

@ -52,7 +52,7 @@ class FScanner;
#define GCC_YSEG
#else
#define MSVC_YSEG
#define GCC_YSEG __attribute__((section(SECTION_YREG)))
#define GCC_YSEG __attribute__((section(SECTION_YREG))) __attribute__((used))
#endif
struct FIntermissionDescriptor;

View file

@ -516,7 +516,14 @@ void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
// with the dragon skin bracers.
if (damage < 10000)
{
#if __APPLE__ && __GNUC__ == 4 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ == 1
// -O1 optimizer bug work around. Only needed for
// GCC 4.2.1 on OS X for 10.4/10.5 tools compatibility.
volatile fixed_t tmp = 300;
Slots[i] -= Scale (damage, SlotsIncrement[i], tmp);
#else
Slots[i] -= Scale (damage, SlotsIncrement[i], 300);
#endif
if (Slots[i] < 2*FRACUNIT)
{
Slots[i] = 0;

View file

@ -1024,7 +1024,7 @@ void AInventory::Touch (AActor *toucher)
//Added by MC: Check if item taken was the roam destination of any bot
for (int i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].Bot != NULL && this == players[i].Bot->dest)
if (players[i].Bot != NULL && this == players[i].Bot->dest)
players[i].Bot->dest = NULL;
}
}

View file

@ -41,7 +41,7 @@ static inline SDWORD Scale (SDWORD a, SDWORD b, SDWORD c)
: "a,a,a,a,a,a" (a),
"m,r,m,r,d,d" (b),
"r,r,m,m,r,m" (c)
: "%cc"
: "cc"
);
return result;
@ -59,7 +59,7 @@ static inline SDWORD MulScale (SDWORD a, SDWORD b, SDWORD c)
: "a,a,a,a" (a),
"m,r,m,r" (b),
"c,c,I,I" (c)
: "%cc"
: "cc"
);
return result;
}
@ -210,7 +210,7 @@ static inline SDWORD DivScale (SDWORD a, SDWORD b, SDWORD c)
: "a" (lo),
"d" (hi),
"r" (b)
: "%cc");
: "cc");
return result;
}
@ -226,7 +226,7 @@ static inline SDWORD DivScale1 (SDWORD a, SDWORD b)
"=&d,d" (dummy)
: "a,a" (a),
"r,m" (b)
: "%cc");
: "cc");
return result;
}
@ -241,7 +241,7 @@ static inline SDWORD DivScale1 (SDWORD a, SDWORD b)
: "a,a" (a<<s), \
"d,d" (a>>(32-s)), \
"r,m" (b) \
: "%cc"); \
: "cc"); \
return result; \
}
@ -287,7 +287,7 @@ static inline SDWORD DivScale32 (SDWORD a, SDWORD b)
"=d,d" (dummy)
: "d,d" (a),
"r,m" (b)
: "%cc");
: "cc");
return result;
}
@ -313,7 +313,7 @@ static inline void clearbufshort (void *buff, unsigned int count, WORD clear)
"rep stosw"
:"=D" (buff), "=c" (count)
:"D" (buff), "c" (count), "a" (clear|(clear<<16))
:"%cc");
:"cc");
}
static inline SDWORD ksgn (SDWORD a)
@ -327,6 +327,6 @@ static inline SDWORD ksgn (SDWORD a)
"adc $0,%1"
:"=r" (dummy), "=r" (result)
:"0" (a)
:"%cc");
:"cc");
return result;
}

View file

@ -69,7 +69,13 @@ static const int PO_LINE_EXPLICIT = 5;
angle_t FNodeBuilder::PointToAngle (fixed_t x, fixed_t y)
{
const double rad2bam = double(1<<30) / M_PI;
#if defined __APPLE__ && !defined __llvm__
// Work-around for vectorization issue in Apple's GCC 4.x
// See https://gcc.gnu.org/wiki/Math_Optimization_Flags for details
long double ang = atan2l (double(y), double(x));
#else // !__APPLE__ || __llvm__
double ang = atan2 (double(y), double(x));
#endif // __APPLE__ && !__llvm__
return angle_t(ang * rad2bam) << 1;
}

View file

@ -323,7 +323,7 @@ int OPLio::OPLinit(uint numchips, bool stereo, bool initopl3)
{
assert(numchips >= 1 && numchips <= countof(chips));
uint i;
IsOPL3 = (opl_core == 1 || opl_core == 2);
IsOPL3 = (opl_core == 1 || opl_core == 2 || opl_core == 3);
memset(chips, 0, sizeof(chips));
if (IsOPL3)
@ -332,7 +332,7 @@ int OPLio::OPLinit(uint numchips, bool stereo, bool initopl3)
}
for (i = 0; i < numchips; ++i)
{
OPLEmul *chip = IsOPL3 ? (opl_core == 1 ? DBOPLCreate(stereo) : JavaOPLCreate(stereo)) : YM3812Create(stereo);
OPLEmul *chip = IsOPL3 ? (opl_core == 1 ? DBOPLCreate(stereo) : (opl_core == 2 ? JavaOPLCreate(stereo) : NukedOPL3Create(stereo))) : YM3812Create(stereo);
if (chip == NULL)
{
break;

1147
src/oplsynth/nukedopl3.cpp Normal file

File diff suppressed because it is too large Load diff

120
src/oplsynth/nukedopl3.h Normal file
View file

@ -0,0 +1,120 @@
/*
* Copyright (C) 2013-2014 Nuke.YKT
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
Nuked Yamaha YMF262(aka OPL3) emulator.
Thanks:
MAME Development Team(Jarek Burczynski, Tatsuyuki Satoh):
Feedback and Rhythm part calculation information.
forums.submarine.org.uk(carbon14, opl3):
Tremolo and phase generator calculation information.
OPLx decapsulated(Matthew Gambrell and Olli Niemitalo):
OPL2 ROMs.
*/
//version 1.4.2
#include "opl.h"
#include "muslib.h"
typedef uintptr_t Bitu;
typedef intptr_t Bits;
typedef DWORD Bit32u;
typedef SDWORD Bit32s;
typedef WORD Bit16u;
typedef SWORD Bit16s;
typedef BYTE Bit8u;
typedef SBYTE Bit8s;
struct channel {
Bit8u con;
Bit8u chtype;
Bit8u alg;
Bit16u offset;
Bit8u feedback;
Bit16u cha, chb, chc, chd;
Bit16s out;
Bit16u f_number;
Bit8u block;
Bit8u ksv;
float panl;
float panr;
};
struct slot {
Bit32u PG_pos;
Bit32u PG_inc;
Bit16s EG_out;
Bit8u eg_inc;
Bit8u eg_gen;
Bit8u eg_gennext;
Bit16u EG_mout;
Bit8u EG_ksl;
Bit8u EG_ar;
Bit8u EG_dr;
Bit8u EG_sl;
Bit8u EG_rr;
Bit8u EG_state;
Bit8u EG_type;
Bit16s out;
Bit16s *mod;
Bit16s prevout[2];
Bit16s fbmod;
Bit16u offset;
Bit8u mult;
Bit8u vibrato;
Bit8u tremolo;
Bit8u ksr;
Bit8u EG_tl;
Bit8u ksl;
Bit8u key;
Bit8u waveform;
};
struct chip {
Bit8u opl_memory[0x200];
Bit8u newm;
Bit8u nts;
Bit8u rhythm;
Bit8u dvb;
Bit8u dam;
Bit32u noise;
Bit16u vib_pos;
Bit16u timer;
Bit8u trem_inc;
Bit8u trem_tval;
Bit8u trem_dir;
Bit8u trem_val;
channel Channels[18];
slot OPs[36];
Bit16s zm;
};
class NukedOPL3 : public OPLEmul {
private:
chip opl3;
bool FullPan;
public:
void Reset();
void Update(float* sndptr, int numsamples);
void WriteReg(int reg, int v);
void SetPanning(int c, float left, float right);
NukedOPL3(bool stereo);
};

View file

@ -20,6 +20,7 @@ public:
OPLEmul *YM3812Create(bool stereo);
OPLEmul *DBOPLCreate(bool stereo);
OPLEmul *JavaOPLCreate(bool stereo);
OPLEmul *NukedOPL3Create(bool stereo);
#define OPL_SAMPLE_RATE 49716.0
#define CENTER_PANNING_POWER 0.70710678118 /* [RH] volume at center for EQP */

View file

@ -1581,20 +1581,28 @@ void FBehavior::StaticSerializeModuleStates (FArchive &arc)
for (modnum = 0; modnum < StaticModules.Size(); ++modnum)
{
FBehavior *module = StaticModules[modnum];
int ModSize = module->GetDataSize();
if (arc.IsStoring())
{
arc.WriteString (module->ModuleName);
if (SaveVersion >= 4516) arc << ModSize;
}
else
{
char *modname = NULL;
arc << modname;
if (SaveVersion >= 4516) arc << ModSize;
if (stricmp (modname, module->ModuleName) != 0)
{
delete[] modname;
I_Error ("Level was saved with a different set of ACS modules.");
}
else if (ModSize != module->GetDataSize())
{
delete[] modname;
I_Error("ACS module %s has changed from what was saved. (Have %d bytes, save has %d bytes)", module->ModuleName, module->GetDataSize(), ModSize);
}
delete[] modname;
}
module->SerializeVars (arc);
@ -1873,7 +1881,7 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len)
funcm->HasReturnValue = funcf->HasReturnValue;
funcm->ImportNum = funcf->ImportNum;
funcm->LocalCount = funcf->LocalCount;
funcm->Address = funcf->Address;
funcm->Address = LittleLong(funcf->Address);
}
}
@ -2058,7 +2066,7 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len)
const char *const parse = (char *)&chunk[2];
DWORD i;
for (i = 0; i < chunk[1]; )
for (i = 0; i < LittleLong(chunk[1]); )
{
if (parse[i])
{
@ -2351,7 +2359,7 @@ void FBehavior::LoadScriptsDirectory ()
scripts.b = FindChunk (MAKE_ID('S','F','L','G'));
if (scripts.dw != NULL)
{
max = scripts.dw[1] / 4;
max = LittleLong(scripts.dw[1]) / 4;
scripts.dw += 2;
for (i = max; i > 0; --i, scripts.w += 2)
{
@ -2367,7 +2375,7 @@ void FBehavior::LoadScriptsDirectory ()
scripts.b = FindChunk (MAKE_ID('S','V','C','T'));
if (scripts.dw != NULL)
{
max = scripts.dw[1] / 4;
max = LittleLong(scripts.dw[1]) / 4;
scripts.dw += 2;
for (i = max; i > 0; --i, scripts.w += 2)
{
@ -2681,7 +2689,7 @@ BYTE *FBehavior::FindChunk (DWORD id) const
{
return chunk;
}
chunk += ((DWORD *)chunk)[1] + 8;
chunk += LittleLong(((DWORD *)chunk)[1]) + 8;
}
return NULL;
}
@ -2689,14 +2697,14 @@ BYTE *FBehavior::FindChunk (DWORD id) const
BYTE *FBehavior::NextChunk (BYTE *chunk) const
{
DWORD id = *(DWORD *)chunk;
chunk += ((DWORD *)chunk)[1] + 8;
chunk += LittleLong(((DWORD *)chunk)[1]) + 8;
while (chunk != NULL && chunk < Data + DataSize)
{
if (((DWORD *)chunk)[0] == id)
{
return chunk;
}
chunk += ((DWORD *)chunk)[1] + 8;
chunk += LittleLong(((DWORD *)chunk)[1]) + 8;
}
return NULL;
}
@ -3673,6 +3681,7 @@ enum
APROP_AttackZOffset = 40,
APROP_StencilColor = 41,
APROP_Friction = 42,
APROP_DamageMultiplier=43,
};
// These are needed for ACS's APROP_RenderStyle
@ -3862,6 +3871,10 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
actor->DamageFactor = value;
break;
case APROP_DamageMultiplier:
actor->DamageMultiply = value;
break;
case APROP_MasterTID:
AActor *other;
other = SingleActorFromTID (value, NULL);
@ -3933,6 +3946,7 @@ int DLevelScript::GetActorProperty (int tid, int property, const SDWORD *stack,
case APROP_Speed: return actor->Speed;
case APROP_Damage: return actor->Damage; // Should this call GetMissileDamage() instead?
case APROP_DamageFactor:return actor->DamageFactor;
case APROP_DamageMultiplier: return actor->DamageMultiply;
case APROP_Alpha: return actor->alpha;
case APROP_RenderStyle: for (int style = STYLE_None; style < STYLE_Count; ++style)
{ // Check for a legacy render style that matches.

View file

@ -308,6 +308,7 @@ public:
int GetScriptIndex (const ScriptPtr *ptr) const { ptrdiff_t index = ptr - Scripts; return index >= NumScripts ? -1 : (int)index; }
ScriptPtr *GetScriptPtr(int index) const { return index >= 0 && index < NumScripts ? &Scripts[index] : NULL; }
int GetLumpNum() const { return LumpNum; }
int GetDataSize() const { return DataSize; }
const char *GetModuleName() const { return ModuleName; }
ACSProfileInfo *GetFunctionProfileData(int index) { return index >= 0 && index < NumFunctions ? &FunctionProfileData[index] : NULL; }
ACSProfileInfo *GetFunctionProfileData(ScriptFunction *func) { return GetFunctionProfileData((int)(func - (ScriptFunction *)Functions)); }

View file

@ -925,6 +925,11 @@ static inline bool MustForcePain(AActor *target, AActor *inflictor)
(inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS));
}
static inline bool isFakePain(AActor *target, AActor *inflictor)
{
return ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)));
}
// Returns the amount of damage actually inflicted upon the target, or -1 if
// the damage was cancelled.
@ -940,6 +945,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
bool justhit = false;
bool plrDontThrust = false;
bool invulpain = false;
bool fakedPain = false;
bool forcedPain = false;
int fakeDamage = 0;
int holdDamage = 0;
@ -948,6 +955,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
return -1;
}
//Rather than unnecessarily call the function over and over again, let's be a little more efficient.
fakedPain = (isFakePain(target, inflictor));
forcedPain = (MustForcePain(target, inflictor));
// Spectral targets only take damage from spectral projectiles.
if (target->flags4 & MF4_SPECTRAL && damage < TELEFRAG_DAMAGE)
{
@ -976,7 +987,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
if (inflictor == NULL || (!(inflictor->flags3 & MF3_FOILINVUL) && !(flags & DMG_FOILINVUL)))
{
if ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)))
if (fakedPain)
{
invulpain = true; //This returns -1 later.
fakeDamage = damage;
@ -991,7 +1002,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// Players are optionally excluded from getting thrust by damage.
if (static_cast<APlayerPawn *>(target)->PlayerFlags & PPF_NOTHRUSTWHENINVUL)
{
if ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)))
if (fakedPain)
plrDontThrust = 1;
else
return -1;
@ -999,7 +1010,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
}
}
if (((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN))) && (damage < TELEFRAG_DAMAGE))
if ((fakedPain) && (damage < TELEFRAG_DAMAGE))
{
//Intentionally do not jump to fakepain because the damage hasn't been dished out yet.
//Once it's dished out, THEN we can disregard damage factors affecting pain chances.
@ -1057,24 +1068,31 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if (damage > 0)
damage = inflictor->DoSpecialDamage (target, damage, mod);
if (damage == -1)
if ((damage == -1) && (target->player == NULL)) //This isn't meant for the player.
{
if ((target->flags7 & MF7_ALLOWPAIN) || (inflictor->flags7 & MF7_CAUSEPAIN)) //Hold off ending the function before we can deal the pain chances.
if (fakedPain) //Hold off ending the function before we can deal the pain chances.
goto fakepain;
return -1;
}
}
// Handle active damage modifiers (e.g. PowerDamage)
if (source != NULL && source->Inventory != NULL)
if (source != NULL)
{
int olddam = damage;
source->Inventory->ModifyDamage(olddam, mod, damage, false);
if (olddam != damage && damage <= 0)
if (source->Inventory != NULL)
{
source->Inventory->ModifyDamage(olddam, mod, damage, false);
}
damage = FixedMul(damage, source->DamageMultiply);
if (((source->flags7 & MF7_CAUSEPAIN) && (fakeDamage <= 0)) || (olddam != damage && damage <= 0))
{ // Still allow FORCEPAIN
if (MustForcePain(target, inflictor))
{
if (forcedPain)
goto dopain;
}
else if (fakedPain)
goto fakepain;
return -1;
}
}
@ -1083,13 +1101,11 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
int olddam = damage;
target->Inventory->ModifyDamage(olddam, mod, damage, true);
if (((target->flags7 & MF7_ALLOWPAIN) && (fakeDamage <= 0)) || (olddam != damage && damage <= 0))
if ((olddam != damage && damage <= 0) && target->player == NULL)
{ // Still allow FORCEPAIN and make sure we're still passing along fake damage to hit enemies for their pain states.
if (MustForcePain(target, inflictor))
{
if (forcedPain)
goto dopain;
}
else if ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)))
else if (fakedPain)
goto fakepain;
return -1;
@ -1103,13 +1119,11 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, mod, target->GetClass()->ActorInfo->DamageFactors);
}
if (damage <= 0)
if (damage <= 0 && target->player == NULL)
{ // Still allow FORCEPAIN
if (MustForcePain(target, inflictor))
{
if (forcedPain)
goto dopain;
}
else if ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)))
else if (fakedPain)
goto fakepain;
return -1;
@ -1118,9 +1132,9 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if (damage > 0)
damage = target->TakeSpecialDamage (inflictor, source, damage, mod);
}
if (damage == -1)
if (damage == -1 && target->player == NULL) //Make sure it's not a player, the pain has yet to be processed with cheats.
{
if ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)))
if (fakedPain)
goto fakepain;
return -1;
@ -1247,17 +1261,18 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
(player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE))
//Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2.
{ // player is invulnerable, so don't hurt him
if (((!(player->cheats & CF_GODMODE)) && (!(player->cheats & CF_GODMODE2)) && (!(player->mo->flags5 & MF5_NOPAIN))) &&
(((player->mo->flags7 & MF7_ALLOWPAIN) || (player->mo->flags5 & MF5_NODAMAGE)) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN))))
//Make sure no godmodes and NOPAIN flags are found first.
//Then, check to see if the player has NODAMAGE or ALLOWPAIN, or inflictor has CAUSEPAIN.
{
if ((player->cheats & CF_GODMODE) || (player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NOPAIN))
return -1;
else if ((((player->mo->flags7 & MF7_ALLOWPAIN) || (player->mo->flags5 & MF5_NODAMAGE)) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN))))
{
invulpain = true;
fakeDamage = damage;
goto fakepain;
}
return -1;
else
return -1;
}
if (!(flags & DMG_NO_ARMOR) && player->mo->Inventory != NULL)
@ -1306,6 +1321,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// telefrag him right? ;) (Unfortunately the damage is "absorbed" by armor,
// but telefragging should still do enough damage to kill the player)
// Ignore players that are already dead.
// [MC]Buddha2 absorbs telefrag damage, and anything else thrown their way.
if ((player->cheats & CF_BUDDHA2) || (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && (damage < TELEFRAG_DAMAGE)) && (player->playerstate != PST_DEAD))
{
// If this is a voodoo doll we need to handle the real player as well.
@ -1339,7 +1355,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
damage = newdam;
if (damage <= 0)
{
if ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)))
if (fakedPain)
goto fakepain;
else
return damage;
@ -1370,6 +1386,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if (target->health <= 0)
{
//[MC]Buddha flag for monsters.
if ((target->flags7 & MF7_BUDDHA) && (damage < TELEFRAG_DAMAGE) && ((inflictor == NULL || !(inflictor->flags3 & MF7_FOILBUDDHA)) && !(flags & DMG_FOILBUDDHA)))
{ //FOILBUDDHA or Telefrag damage must kill it.
target->health = 1;
@ -1434,7 +1451,7 @@ fakepain: //Needed so we can skip the rest of the above, but still obey the orig
//CAUSEPAIN can always attempt to trigger the chances of pain.
//ALLOWPAIN can do the same, only if the (unfiltered aka fake) damage is greater than 0.
if ((((target->flags7 & MF7_ALLOWPAIN) && (fakeDamage > 0))
|| ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN))) && (fakeDamage != damage))
|| ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN))))
{
holdDamage = damage; //Store the modified damage away after factors are taken into account.
damage = fakeDamage; //Retrieve the original damage.
@ -1535,7 +1552,7 @@ dopain:
{
return -1; //NOW we return -1!
}
else if ((target->flags7 & MF7_ALLOWPAIN) || ((inflictor != NULL) && (inflictor->flags7 & MF7_CAUSEPAIN)))
else if (fakedPain)
{
return holdDamage; //This is the calculated damage after all is said and done.
}

View file

@ -736,8 +736,18 @@ bool PIT_CheckLine(line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
else
{ // Find the point on the line closest to the actor's center, and use
// that to calculate openings
SQWORD r_den = (SQWORD(ld->dx)*ld->dx + SQWORD(ld->dy)*ld->dy) / (1 << 24);
// [EP] Use 64 bit integers in order to keep the exact result of the
// multiplication, because in the worst case, which is by the map limit
// (32767 units, which is 2147418112 in fixed_t notation), the result
// would occupy 62 bits (if I consider also the addition with another
// and possible 62 bit value, it's 63 bits).
// This privilege could not be available if the starting data would be
// 64 bit long.
// With this, the division is exact as the 32 bit float counterpart,
// though I don't know why I had to discard the first 24 bits from the
// divisor.
SQWORD r_num = ((SQWORD(tm.x - ld->v1->x)*ld->dx) + (SQWORD(tm.y - ld->v1->y)*ld->dy));
SQWORD r_den = (SQWORD(ld->dx)*ld->dx + SQWORD(ld->dy)*ld->dy) / (1 << 24);
fixed_t r = (fixed_t)(r_num / r_den);
/* Printf ("%d:%d: %d (%d %d %d %d) (%d %d %d %d)\n", level.time, ld-lines, r,
ld->frontsector->floorplane.a,

View file

@ -84,7 +84,6 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern cycle_t BotSupportCycles;
extern int BotWTG;
EXTERN_CVAR (Int, cl_rockettrails)
@ -313,8 +312,16 @@ void AActor::Serialize (FArchive &arc)
}
arc << lastpush << lastbump
<< PainThreshold
<< DamageFactor
<< WeaveIndexXY << WeaveIndexZ
<< DamageFactor;
if (SaveVersion >= 4516)
{
arc << DamageMultiply;
}
else
{
DamageMultiply = FRACUNIT;
}
arc << WeaveIndexXY << WeaveIndexZ
<< PoisonDamageReceived << PoisonDurationReceived << PoisonPeriodReceived << Poisoner
<< PoisonDamage << PoisonDuration << PoisonPeriod;
if (SaveVersion >= 3235)
@ -3868,6 +3875,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t
actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98
if (G_SkillProperty(SKILLP_FastMonsters))
actor->Speed = actor->GetClass()->Meta.GetMetaFixed(AMETA_FastSpeed, actor->Speed);
actor->DamageMultiply = FRACUNIT;
// set subsector and/or block links

View file

@ -4175,7 +4175,6 @@ static void P_Shutdown ()
P_FreeLevelData ();
P_FreeExtraLevelData ();
ST_Clear();
bglobal.DestroyAllBots ();
}
#if 0

View file

@ -3066,7 +3066,6 @@ void player_t::Serialize (FArchive &arc)
if (SaveVersion < 4514 && IsBot)
{
Bot = new DBot;
GC::WriteBarrier (Bot);
arc << Bot->angle
<< Bot->dest
@ -3089,6 +3088,12 @@ void player_t::Serialize (FArchive &arc)
<< Bot->oldx
<< Bot->oldy;
}
if (SaveVersion < 4516 && Bot != NULL)
{
Bot->player = this;
}
if (arc.IsLoading ())
{
// If the player reloaded because they pressed +use after dying, we

131
src/sdl/i_gui.cpp Normal file
View file

@ -0,0 +1,131 @@
// Moved from sdl/i_system.cpp
#include <string.h>
#include <SDL.h>
#include "bitmap.h"
#include "v_palette.h"
#include "textures.h"
extern SDL_Surface *cursorSurface;
extern SDL_Rect cursorBlit;
#ifdef USE_XCURSOR
// Xlib has its own GC, so don't let it interfere.
#define GC XGC
#include <X11/Xcursor/Xcursor.h>
#undef GC
bool UseXCursor;
SDL_Cursor *X11Cursor;
SDL_Cursor *FirstCursor;
// Hack! Hack! SDL does not provide a clean way to get the XDisplay.
// On the other hand, there are no more planned updates for SDL 1.2,
// so we should be fine making assumptions.
struct SDL_PrivateVideoData
{
int local_X11;
Display *X11_Display;
};
struct SDL_VideoDevice
{
const char *name;
int (*functions[9])();
SDL_VideoInfo info;
SDL_PixelFormat *displayformatalphapixel;
int (*morefuncs[9])();
Uint16 *gamma;
int (*somefuncs[9])();
unsigned int texture; // Only here if SDL was compiled with OpenGL support. Ack!
int is_32bit;
int (*itsafuncs[13])();
SDL_Surface *surfaces[3];
SDL_Palette *physpal;
SDL_Color *gammacols;
char *wm_strings[2];
int offsets[2];
SDL_GrabMode input_grab;
int handles_any_size;
SDL_PrivateVideoData *hidden; // Why did they have to bury this so far in?
};
extern SDL_VideoDevice *current_video;
#define SDL_Display (current_video->hidden->X11_Display)
SDL_Cursor *CreateColorCursor(FTexture *cursorpic)
{
return NULL;
}
#endif
bool I_SetCursor(FTexture *cursorpic)
{
if (cursorpic != NULL && cursorpic->UseType != FTexture::TEX_Null)
{
// Must be no larger than 32x32.
if (cursorpic->GetWidth() > 32 || cursorpic->GetHeight() > 32)
{
return false;
}
#ifdef USE_XCURSOR
if (UseXCursor)
{
if (FirstCursor == NULL)
{
FirstCursor = SDL_GetCursor();
}
X11Cursor = CreateColorCursor(cursorpic);
if (X11Cursor != NULL)
{
SDL_SetCursor(X11Cursor);
return true;
}
}
#endif
if (cursorSurface == NULL)
cursorSurface = SDL_CreateRGBSurface (0, 32, 32, 32, MAKEARGB(0,255,0,0), MAKEARGB(0,0,255,0), MAKEARGB(0,0,0,255), MAKEARGB(255,0,0,0));
SDL_ShowCursor(0);
SDL_LockSurface(cursorSurface);
BYTE buffer[32*32*4];
memset(buffer, 0, 32*32*4);
FBitmap bmp(buffer, 32*4, 32, 32);
cursorpic->CopyTrueColorPixels(&bmp, 0, 0);
memcpy(cursorSurface->pixels, bmp.GetPixels(), 32*32*4);
SDL_UnlockSurface(cursorSurface);
}
else
{
SDL_ShowCursor(1);
if (cursorSurface != NULL)
{
SDL_FreeSurface(cursorSurface);
cursorSurface = NULL;
}
#ifdef USE_XCURSOR
if (X11Cursor != NULL)
{
SDL_SetCursor(FirstCursor);
SDL_FreeCursor(X11Cursor);
X11Cursor = NULL;
}
#endif
}
return true;
}
void I_SetMainWindowVisible(bool visible)
{
}
const char* I_GetBackEndName()
{
return "SDL";
}

View file

@ -75,6 +75,10 @@
extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*));
#ifdef __APPLE__
void Mac_I_FatalError(const char* errortext);
#endif
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
@ -235,6 +239,8 @@ static void unprotect_rtext()
void I_StartupJoysticks();
void I_ShutdownJoysticks();
const char* I_GetBackEndName();
int main (int argc, char **argv)
{
#if !defined (__APPLE__)
@ -244,8 +250,8 @@ int main (int argc, char **argv)
}
#endif // !__APPLE__
printf(GAMENAME" %s - %s - SDL version\nCompiled on %s\n",
GetVersionString(), GetGitTime(), __DATE__);
printf(GAMENAME" %s - %s - %s version\nCompiled on %s\n",
GetVersionString(), GetGitTime(), I_GetBackEndName(), __DATE__);
seteuid (getuid ());
std::set_new_handler (NewFailure);
@ -356,6 +362,11 @@ int main (int argc, char **argv)
I_ShutdownJoysticks();
if (error.GetMessage ())
fprintf (stderr, "%s\n", error.GetMessage ());
#ifdef __APPLE__
Mac_I_FatalError(error.GetMessage());
#endif // __APPLE__
exit (-1);
}
catch (...)

View file

@ -71,12 +71,9 @@
#include "m_fixed.h"
#include "g_level.h"
#ifdef USE_XCURSOR
// Xlib has its own GC, so don't let it interfere.
#define GC XGC
#include <X11/Xcursor/Xcursor.h>
#undef GC
#endif
#ifdef __APPLE__
#include <ApplicationServices/ApplicationServices.h>
#endif // __APPLE__
EXTERN_CVAR (String, language)
@ -91,11 +88,6 @@ extern bool GtkAvailable;
#elif defined(__APPLE__)
int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad);
#endif
#ifdef USE_XCURSOR
bool UseXCursor;
SDL_Cursor *X11Cursor;
SDL_Cursor *FirstCursor;
#endif
DWORD LanguageIDs[4];
@ -122,185 +114,6 @@ void I_EndRead(void)
}
static DWORD TicStart;
static DWORD BaseTime;
static int TicFrozen;
// Signal based timer.
static Semaphore timerWait;
static int tics;
static DWORD sig_start;
void I_SelectTimer();
// [RH] Returns time in milliseconds
unsigned int I_MSTime (void)
{
unsigned int time = SDL_GetTicks ();
return time - BaseTime;
}
// Exactly the same thing, but based does no modification to the time.
unsigned int I_FPSTime()
{
return SDL_GetTicks();
}
//
// I_GetTime
// returns time in 1/35th second tics
//
int I_GetTimeSelect (bool saveMS)
{
I_SelectTimer();
return I_GetTime (saveMS);
}
int I_GetTimePolled (bool saveMS)
{
if (TicFrozen != 0)
{
return TicFrozen;
}
DWORD tm = SDL_GetTicks();
if (saveMS)
{
TicStart = tm;
}
return Scale(tm - BaseTime, TICRATE, 1000);
}
int I_GetTimeSignaled (bool saveMS)
{
if (saveMS)
{
TicStart = sig_start;
}
return tics;
}
int I_WaitForTicPolled (int prevtic)
{
int time;
assert (TicFrozen == 0);
while ((time = I_GetTimePolled(false)) <= prevtic)
;
return time;
}
int I_WaitForTicSignaled (int prevtic)
{
assert (TicFrozen == 0);
while(tics <= prevtic)
{
SEMAPHORE_WAIT(timerWait)
}
return tics;
}
void I_FreezeTimeSelect (bool frozen)
{
I_SelectTimer();
return I_FreezeTime (frozen);
}
void I_FreezeTimePolled (bool frozen)
{
if (frozen)
{
assert(TicFrozen == 0);
TicFrozen = I_GetTimePolled(false);
}
else
{
assert(TicFrozen != 0);
int froze = TicFrozen;
TicFrozen = 0;
int now = I_GetTimePolled(false);
BaseTime += (now - froze) * 1000 / TICRATE;
}
}
void I_FreezeTimeSignaled (bool frozen)
{
TicFrozen = frozen;
}
int I_WaitForTicSelect (int prevtic)
{
I_SelectTimer();
return I_WaitForTic (prevtic);
}
//
// I_HandleAlarm
// Should be called every time there is an alarm.
//
void I_HandleAlarm (int sig)
{
if(!TicFrozen)
tics++;
sig_start = SDL_GetTicks();
SEMAPHORE_SIGNAL(timerWait)
}
//
// I_SelectTimer
// Sets up the timer function based on if we can use signals for efficent CPU
// usage.
//
void I_SelectTimer()
{
SEMAPHORE_INIT(timerWait, 0, 0)
#ifndef __sun
signal(SIGALRM, I_HandleAlarm);
#else
struct sigaction alrmaction;
sigaction(SIGALRM, NULL, &alrmaction);
alrmaction.sa_handler = I_HandleAlarm;
sigaction(SIGALRM, &alrmaction, NULL);
#endif
struct itimerval itv;
itv.it_interval.tv_sec = itv.it_value.tv_sec = 0;
itv.it_interval.tv_usec = itv.it_value.tv_usec = 1000000/TICRATE;
if (setitimer(ITIMER_REAL, &itv, NULL) != 0)
{
I_GetTime = I_GetTimePolled;
I_FreezeTime = I_FreezeTimePolled;
I_WaitForTic = I_WaitForTicPolled;
}
else
{
I_GetTime = I_GetTimeSignaled;
I_FreezeTime = I_FreezeTimeSignaled;
I_WaitForTic = I_WaitForTicSignaled;
}
}
// Returns the fractional amount of a tic passed since the most recent tic
fixed_t I_GetTimeFrac (uint32 *ms)
{
DWORD now = SDL_GetTicks ();
if (ms) *ms = TicStart + (1000 / TICRATE);
if (TicStart == 0)
{
return FRACUNIT;
}
else
{
fixed_t frac = clamp<fixed_t> ((now - TicStart)*FRACUNIT*TICRATE/1000, 0, FRACUNIT);
return frac;
}
}
void I_WaitVBL (int count)
{
// I_WaitVBL is never used to actually synchronize to the
@ -322,6 +135,9 @@ void SetLanguageIDs ()
LanguageIDs[3] = LanguageIDs[2] = LanguageIDs[1] = LanguageIDs[0] = lang;
}
void I_InitTimer ();
void I_ShutdownTimer ();
//
// I_Init
//
@ -330,11 +146,9 @@ void I_Init (void)
CheckCPUID (&CPU);
DumpCPUInfo (&CPU);
I_GetTime = I_GetTimeSelect;
I_WaitForTic = I_WaitForTicSelect;
I_FreezeTime = I_FreezeTimeSelect;
atterm (I_ShutdownSound);
I_InitSound ();
I_InitTimer ();
}
//
@ -350,6 +164,8 @@ void I_Quit (void)
G_CheckDemoStatus();
C_DeinitConsole();
I_ShutdownTimer();
}
@ -785,6 +601,10 @@ int I_FindAttr (findstate_t *fileinfo)
return 0;
}
#ifdef __APPLE__
static PasteboardRef s_clipboard;
#endif // __APPLE__
// Clipboard support requires GTK+
// TODO: GTK+ uses UTF-8. We don't, so some conversions would be appropriate.
void I_PutInClipboard (const char *str)
@ -805,6 +625,23 @@ void I_PutInClipboard (const char *str)
}
*/
}
#elif defined __APPLE__
if (NULL == s_clipboard)
{
PasteboardCreate(kPasteboardClipboard, &s_clipboard);
}
PasteboardClear(s_clipboard);
PasteboardSynchronize(s_clipboard);
const CFDataRef textData = CFDataCreate(kCFAllocatorDefault,
reinterpret_cast<const UInt8*>(str), strlen(str));
if (NULL != textData)
{
PasteboardPutItemFlavor(s_clipboard, PasteboardItemID(1),
CFSTR("public.utf8-plain-text"), textData, 0);
}
#endif
}
@ -826,6 +663,61 @@ FString I_GetFromClipboard (bool use_primary_selection)
}
}
}
#elif defined __APPLE__
FString result;
if (NULL == s_clipboard)
{
PasteboardCreate(kPasteboardClipboard, &s_clipboard);
}
PasteboardSynchronize(s_clipboard);
ItemCount itemCount = 0;
PasteboardGetItemCount(s_clipboard, &itemCount);
if (0 == itemCount)
{
return FString();
}
PasteboardItemID itemID;
if (0 != PasteboardGetItemIdentifier(s_clipboard, 1, &itemID))
{
return FString();
}
CFArrayRef flavorTypeArray;
if (0 != PasteboardCopyItemFlavors(s_clipboard, itemID, &flavorTypeArray))
{
return FString();
}
const CFIndex flavorCount = CFArrayGetCount(flavorTypeArray);
for (CFIndex flavorIndex = 0; flavorIndex < flavorCount; ++flavorIndex)
{
const CFStringRef flavorType = static_cast<const CFStringRef>(
CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex));
if (UTTypeConformsTo(flavorType, CFSTR("public.utf8-plain-text")))
{
CFDataRef flavorData;
if (0 == PasteboardCopyItemFlavorData(s_clipboard, itemID, flavorType, &flavorData))
{
result += reinterpret_cast<const char*>(CFDataGetBytePtr(flavorData));
}
CFRelease(flavorData);
}
}
CFRelease(flavorTypeArray);
return result;
#endif
return "";
}
@ -851,104 +743,3 @@ unsigned int I_MakeRNGSeed()
}
return seed;
}
#ifdef USE_XCURSOR
// Hack! Hack! SDL does not provide a clean way to get the XDisplay.
// On the other hand, there are no more planned updates for SDL 1.2,
// so we should be fine making assumptions.
struct SDL_PrivateVideoData
{
int local_X11;
Display *X11_Display;
};
struct SDL_VideoDevice
{
const char *name;
int (*functions[9])();
SDL_VideoInfo info;
SDL_PixelFormat *displayformatalphapixel;
int (*morefuncs[9])();
Uint16 *gamma;
int (*somefuncs[9])();
unsigned int texture; // Only here if SDL was compiled with OpenGL support. Ack!
int is_32bit;
int (*itsafuncs[13])();
SDL_Surface *surfaces[3];
SDL_Palette *physpal;
SDL_Color *gammacols;
char *wm_strings[2];
int offsets[2];
SDL_GrabMode input_grab;
int handles_any_size;
SDL_PrivateVideoData *hidden; // Why did they have to bury this so far in?
};
extern SDL_VideoDevice *current_video;
#define SDL_Display (current_video->hidden->X11_Display)
SDL_Cursor *CreateColorCursor(FTexture *cursorpic)
{
return NULL;
}
#endif
SDL_Surface *cursorSurface = NULL;
SDL_Rect cursorBlit = {0, 0, 32, 32};
bool I_SetCursor(FTexture *cursorpic)
{
if (cursorpic != NULL && cursorpic->UseType != FTexture::TEX_Null)
{
// Must be no larger than 32x32.
if (cursorpic->GetWidth() > 32 || cursorpic->GetHeight() > 32)
{
return false;
}
#ifdef USE_XCURSOR
if (UseXCursor)
{
if (FirstCursor == NULL)
{
FirstCursor = SDL_GetCursor();
}
X11Cursor = CreateColorCursor(cursorpic);
if (X11Cursor != NULL)
{
SDL_SetCursor(X11Cursor);
return true;
}
}
#endif
if (cursorSurface == NULL)
cursorSurface = SDL_CreateRGBSurface (0, 32, 32, 32, MAKEARGB(0,255,0,0), MAKEARGB(0,0,255,0), MAKEARGB(0,0,0,255), MAKEARGB(255,0,0,0));
SDL_ShowCursor(0);
SDL_LockSurface(cursorSurface);
BYTE buffer[32*32*4];
memset(buffer, 0, 32*32*4);
FBitmap bmp(buffer, 32*4, 32, 32);
cursorpic->CopyTrueColorPixels(&bmp, 0, 0);
memcpy(cursorSurface->pixels, bmp.GetPixels(), 32*32*4);
SDL_UnlockSurface(cursorSurface);
}
else
{
SDL_ShowCursor(1);
if (cursorSurface != NULL)
{
SDL_FreeSurface(cursorSurface);
cursorSurface = NULL;
}
#ifdef USE_XCURSOR
if (X11Cursor != NULL)
{
SDL_SetCursor(FirstCursor);
SDL_FreeCursor(X11Cursor);
X11Cursor = NULL;
}
#endif
}
return true;
}

206
src/sdl/i_timer.cpp Normal file
View file

@ -0,0 +1,206 @@
// Moved from sdl/i_system.cpp
#include <assert.h>
#include <signal.h>
#include <sys/time.h>
#include <SDL.h>
#include "basictypes.h"
#include "basicinlines.h"
#include "hardware.h"
#include "i_system.h"
#include "templates.h"
static DWORD TicStart;
static DWORD BaseTime;
static int TicFrozen;
// Signal based timer.
static Semaphore timerWait;
static int tics;
static DWORD sig_start;
void I_SelectTimer();
// [RH] Returns time in milliseconds
unsigned int I_MSTime (void)
{
unsigned int time = SDL_GetTicks ();
return time - BaseTime;
}
// Exactly the same thing, but based does no modification to the time.
unsigned int I_FPSTime()
{
return SDL_GetTicks();
}
//
// I_GetTime
// returns time in 1/35th second tics
//
int I_GetTimeSelect (bool saveMS)
{
I_SelectTimer();
return I_GetTime (saveMS);
}
int I_GetTimePolled (bool saveMS)
{
if (TicFrozen != 0)
{
return TicFrozen;
}
DWORD tm = SDL_GetTicks();
if (saveMS)
{
TicStart = tm;
}
return Scale(tm - BaseTime, TICRATE, 1000);
}
int I_GetTimeSignaled (bool saveMS)
{
if (saveMS)
{
TicStart = sig_start;
}
return tics;
}
int I_WaitForTicPolled (int prevtic)
{
int time;
assert (TicFrozen == 0);
while ((time = I_GetTimePolled(false)) <= prevtic)
;
return time;
}
int I_WaitForTicSignaled (int prevtic)
{
assert (TicFrozen == 0);
while(tics <= prevtic)
{
SEMAPHORE_WAIT(timerWait)
}
return tics;
}
void I_FreezeTimeSelect (bool frozen)
{
I_SelectTimer();
return I_FreezeTime (frozen);
}
void I_FreezeTimePolled (bool frozen)
{
if (frozen)
{
assert(TicFrozen == 0);
TicFrozen = I_GetTimePolled(false);
}
else
{
assert(TicFrozen != 0);
int froze = TicFrozen;
TicFrozen = 0;
int now = I_GetTimePolled(false);
BaseTime += (now - froze) * 1000 / TICRATE;
}
}
void I_FreezeTimeSignaled (bool frozen)
{
TicFrozen = frozen;
}
int I_WaitForTicSelect (int prevtic)
{
I_SelectTimer();
return I_WaitForTic (prevtic);
}
//
// I_HandleAlarm
// Should be called every time there is an alarm.
//
void I_HandleAlarm (int sig)
{
if(!TicFrozen)
tics++;
sig_start = SDL_GetTicks();
SEMAPHORE_SIGNAL(timerWait)
}
//
// I_SelectTimer
// Sets up the timer function based on if we can use signals for efficent CPU
// usage.
//
void I_SelectTimer()
{
SEMAPHORE_INIT(timerWait, 0, 0)
#ifndef __sun
signal(SIGALRM, I_HandleAlarm);
#else
struct sigaction alrmaction;
sigaction(SIGALRM, NULL, &alrmaction);
alrmaction.sa_handler = I_HandleAlarm;
sigaction(SIGALRM, &alrmaction, NULL);
#endif
struct itimerval itv;
itv.it_interval.tv_sec = itv.it_value.tv_sec = 0;
itv.it_interval.tv_usec = itv.it_value.tv_usec = 1000000/TICRATE;
if (setitimer(ITIMER_REAL, &itv, NULL) != 0)
{
I_GetTime = I_GetTimePolled;
I_FreezeTime = I_FreezeTimePolled;
I_WaitForTic = I_WaitForTicPolled;
}
else
{
I_GetTime = I_GetTimeSignaled;
I_FreezeTime = I_FreezeTimeSignaled;
I_WaitForTic = I_WaitForTicSignaled;
}
}
// Returns the fractional amount of a tic passed since the most recent tic
fixed_t I_GetTimeFrac (uint32 *ms)
{
DWORD now = SDL_GetTicks ();
if (ms) *ms = TicStart + (1000 / TICRATE);
if (TicStart == 0)
{
return FRACUNIT;
}
else
{
fixed_t frac = clamp<fixed_t> ((now - TicStart)*FRACUNIT*TICRATE/1000, 0, FRACUNIT);
return frac;
}
}
void I_InitTimer ()
{
I_GetTime = I_GetTimeSelect;
I_WaitForTic = I_WaitForTicSelect;
I_FreezeTime = I_FreezeTimeSelect;
}
void I_ShutdownTimer ()
{
}

View file

@ -33,9 +33,29 @@
**
*/
// Avoid collision between DObject class and Objective-C
#define Class ObjectClass
#include "cmdlib.h"
#include "d_main.h"
#include "version.h"
#include "c_cvars.h"
#include "m_argv.h"
#include "m_misc.h"
#include "gameconfigfile.h"
#undef Class
#include <Cocoa/Cocoa.h>
#include <wordexp.h>
#include <unistd.h>
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
// Missing type definition for 10.4 and earlier
typedef unsigned int NSUInteger;
#endif // prior to 10.5
CVAR(String, osx_additional_parameters, "", CVAR_ARCHIVE | CVAR_NOSET | CVAR_GLOBALCONFIG);
enum
{
@ -107,6 +127,45 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" };
@end
static NSDictionary* GetKnownFileTypes()
{
return [NSDictionary dictionaryWithObjectsAndKeys:
@"-file" , @"wad",
@"-file" , @"pk3",
@"-file" , @"zip",
@"-file" , @"pk7",
@"-file" , @"7z",
@"-deh" , @"deh",
@"-bex" , @"bex",
@"-exec" , @"cfg",
@"-playdemo", @"lmp",
nil];
}
static NSArray* GetKnownExtensions()
{
return [GetKnownFileTypes() allKeys];
}
@interface NSMutableString(AppendKnownFileType)
- (void)appendKnownFileType:(NSString *)filePath;
@end
@implementation NSMutableString(AppendKnownFileType)
- (void)appendKnownFileType:(NSString *)filePath
{
NSString* extension = [[filePath pathExtension] lowercaseString];
NSString* parameter = [GetKnownFileTypes() objectForKey:extension];
if (nil == parameter)
{
return;
}
[self appendFormat:@"%@ \"%@\" ", parameter, filePath];
}
@end
// So we can listen for button actions and such we need to have an Obj-C class.
@interface IWADPicker : NSObject
{
@ -114,13 +173,18 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" };
NSWindow *window;
NSButton *okButton;
NSButton *cancelButton;
NSButton *browseButton;
NSTextField *parametersTextField;
bool cancelled;
}
- (void)buttonPressed:(id) sender;
- (void)browseButtonPressed:(id) sender;
- (void)doubleClicked:(id) sender;
- (void)makeLabel:(NSTextField *)label withString:(const char*) str;
- (int)pickIWad:(WadStuff *)wads num:(int) numwads showWindow:(bool) showwin defaultWad:(int) defaultiwad;
- (NSString*)commandLineParameters;
- (void)menuActionSent:(NSNotification*)notification;
@end
@implementation IWADPicker
@ -134,6 +198,52 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" };
[app stopModal];
}
- (void)browseButtonPressed:(id) sender
{
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
[openPanel setAllowsMultipleSelection:YES];
[openPanel setCanChooseFiles:YES];
[openPanel setCanChooseDirectories:YES];
[openPanel setResolvesAliases:YES];
[openPanel setAllowedFileTypes:GetKnownExtensions()];
if (NSOKButton == [openPanel runModal])
{
NSArray* files = [openPanel URLs];
NSMutableString* parameters = [NSMutableString string];
for (NSUInteger i = 0, ei = [files count]; i < ei; ++i)
{
NSString* filePath = [[files objectAtIndex:i] path];
BOOL isDirectory = false;
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory] && isDirectory)
{
[parameters appendFormat:@"-file \"%@\" ", filePath];
}
else
{
[parameters appendKnownFileType:filePath];
}
}
if ([parameters length] > 0)
{
NSString* newParameters = [parametersTextField stringValue];
if ([newParameters length] > 0
&& NO == [newParameters hasSuffix:@" "])
{
newParameters = [newParameters stringByAppendingString:@" "];
}
newParameters = [newParameters stringByAppendingString:parameters];
[parametersTextField setStringValue: newParameters];
}
}
}
- (void)doubleClicked:(id) sender
{
if ([sender clickedRow] >= 0)
@ -159,20 +269,18 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" };
cancelled = false;
app = [NSApplication sharedApplication];
id windowTitle = [NSString stringWithFormat:@"%s %s", GAMESIG, GetVersionString()];
id windowTitle = [NSString stringWithFormat:@"%s %s", GAMENAME, GetVersionString()];
NSRect frame = NSMakeRect(0, 0, 440, 450);
window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO];
[window setTitle:windowTitle];
NSTextField *description = [[NSTextField alloc] initWithFrame:NSMakeRect(22, 379, 412, 50)];
[self makeLabel:description withString:"GZDoom found more than one IWAD\nSelect from the list below to determine which one to use:"];
NSTextField *description = [[NSTextField alloc] initWithFrame:NSMakeRect(18, 384, 402, 50)];
[self makeLabel:description withString:GAMENAME " found more than one IWAD\nSelect from the list below to determine which one to use:"];
[[window contentView] addSubview:description];
[description release];
// Commented out version would account for an additional parameters box.
//NSScrollView *iwadScroller = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 103, 412, 288)];
NSScrollView *iwadScroller = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 50, 412, 341)];
NSScrollView *iwadScroller = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 135, 402, 256)];
NSTableView *iwadTable = [[NSTableView alloc] initWithFrame:[iwadScroller bounds]];
IWADTableData *tableData = [[IWADTableData alloc] init:wads num:numwads];
for(int i = 0;i < NUM_COLUMNS;i++)
@ -200,11 +308,12 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" };
[iwadTable release];
[iwadScroller release];
/*NSTextField *additionalParametersLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(17, 78, 144, 17)];
[self makeLabel:additionalParametersLabel:"Additional Parameters"];
NSTextField *additionalParametersLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(18, 108, 144, 17)];
[self makeLabel:additionalParametersLabel withString:"Additional Parameters:"];
[[window contentView] addSubview:additionalParametersLabel];
NSTextField *additionalParameters = [[NSTextField alloc] initWithFrame:NSMakeRect(20, 48, 360, 22)];
[[window contentView] addSubview:additionalParameters];*/
parametersTextField = [[NSTextField alloc] initWithFrame:NSMakeRect(20, 48, 402, 54)];
[parametersTextField setStringValue:[NSString stringWithUTF8String:osx_additional_parameters]];
[[window contentView] addSubview:parametersTextField];
// Doesn't look like the SDL version implements this so lets not show it.
/*NSButton *dontAsk = [[NSButton alloc] initWithFrame:NSMakeRect(18, 18, 178, 18)];
@ -213,39 +322,164 @@ static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" };
[dontAsk setState:(showwin ? NSOffState : NSOnState)];
[[window contentView] addSubview:dontAsk];*/
okButton = [[NSButton alloc] initWithFrame:NSMakeRect(236, 12, 96, 32)];
[okButton setTitle:[NSString stringWithUTF8String:"OK"]];
okButton = [[NSButton alloc] initWithFrame:NSMakeRect(236, 8, 96, 32)];
[okButton setTitle:@"OK"];
[okButton setBezelStyle:NSRoundedBezelStyle];
[okButton setAction:@selector(buttonPressed:)];
[okButton setTarget:self];
[okButton setKeyEquivalent:@"\r"];
[[window contentView] addSubview:okButton];
cancelButton = [[NSButton alloc] initWithFrame:NSMakeRect(332, 12, 96, 32)];
[cancelButton setTitle:[NSString stringWithUTF8String:"Cancel"]];
cancelButton = [[NSButton alloc] initWithFrame:NSMakeRect(332, 8, 96, 32)];
[cancelButton setTitle:@"Cancel"];
[cancelButton setBezelStyle:NSRoundedBezelStyle];
[cancelButton setAction:@selector(buttonPressed:)];
[cancelButton setTarget:self];
[cancelButton setKeyEquivalent:@"\033"];
[[window contentView] addSubview:cancelButton];
browseButton = [[NSButton alloc] initWithFrame:NSMakeRect(14, 8, 96, 32)];
[browseButton setTitle:@"Browse..."];
[browseButton setBezelStyle:NSRoundedBezelStyle];
[browseButton setAction:@selector(browseButtonPressed:)];
[browseButton setTarget:self];
[[window contentView] addSubview:browseButton];
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(menuActionSent:) name:NSMenuDidSendActionNotification object:nil];
[window center];
[app runModalForWindow:window];
[center removeObserver:self name:NSMenuDidSendActionNotification object:nil];
[window release];
[okButton release];
[cancelButton release];
[browseButton release];
return cancelled ? -1 : [iwadTable selectedRow];
}
- (NSString*)commandLineParameters
{
return [parametersTextField stringValue];
}
- (void)menuActionSent:(NSNotification*)notification
{
NSDictionary* userInfo = [notification userInfo];
NSMenuItem* menuItem = [userInfo valueForKey:@"MenuItem"];
if ( @selector(terminate:) == [menuItem action] )
{
exit(0);
}
}
@end
EXTERN_CVAR(String, defaultiwad)
static NSString* GetArchitectureString()
{
#ifdef __i386__
return @"i386";
#elif defined __x86_64__
return @"x86_64";
#elif defined __ppc__
return @"ppc";
#elif defined __ppc64__
return @"ppc64";
#endif
}
static void RestartWithParameters(const char* iwadPath, NSString* parameters)
{
assert(nil != parameters);
defaultiwad = ExtractFileBase(iwadPath);
GameConfig->DoGameSetup("Doom");
M_SaveDefaults(NULL);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@try
{
const int commandLineParametersCount = Args->NumArgs();
assert(commandLineParametersCount > 0);
NSString* executablePath = [NSString stringWithUTF8String:Args->GetArg(0)];
NSString* architecture = GetArchitectureString();
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:commandLineParametersCount + 6];
[arguments addObject:@"-arch"];
[arguments addObject:architecture];
[arguments addObject:executablePath];
[arguments addObject:@"-wad_picker_restart"];
[arguments addObject:@"-iwad"];
[arguments addObject:[NSString stringWithUTF8String:iwadPath]];
for (int i = 1; i < commandLineParametersCount; ++i)
{
NSString* currentParameter = [NSString stringWithUTF8String:Args->GetArg(i)];
[arguments addObject:currentParameter];
}
wordexp_t expansion = {};
if (0 == wordexp([parameters UTF8String], &expansion, 0))
{
for (size_t i = 0; i < expansion.we_wordc; ++i)
{
NSString* argumentString = [NSString stringWithCString:expansion.we_wordv[i]
encoding:NSUTF8StringEncoding];
[arguments addObject:argumentString];
}
wordfree(&expansion);
}
[NSTask launchedTaskWithLaunchPath:@"/usr/bin/arch" arguments:arguments];
_exit(0); // to avoid atexit()'s functions
}
@catch (NSException* e)
{
NSLog(@"Cannot restart: %@", [e reason]);
}
[pool release];
}
void I_SetMainWindowVisible(bool visible);
// Simple wrapper so we can call this from outside.
int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
I_SetMainWindowVisible(false);
IWADPicker *picker = [IWADPicker alloc];
int ret = [picker pickIWad:wads num:numwads showWindow:showwin defaultWad:defaultiwad];
[picker release];
I_SetMainWindowVisible(true);
NSString* parametersToAppend = [picker commandLineParameters];
osx_additional_parameters = [parametersToAppend UTF8String];
if (ret >= 0)
{
if (0 != [parametersToAppend length])
{
RestartWithParameters(wads[ret].Path, parametersToAppend);
}
}
[pool release];
return ret;
}

View file

@ -15,6 +15,10 @@
#include <SDL.h>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#endif // __APPLE__
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
@ -43,6 +47,8 @@ public:
friend class SDLVideo;
virtual void SetVSync (bool vsync);
private:
PalEntry SourcePalette[256];
BYTE GammaTable[3][256];
@ -75,13 +81,15 @@ struct MiniModeInfo
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern IVideo *Video;
extern SDL_Surface *cursorSurface;
extern SDL_Rect cursorBlit;
extern bool GUICapture;
SDL_Surface *cursorSurface = NULL;
SDL_Rect cursorBlit = {0, 0, 32, 32};
EXTERN_CVAR (Float, Gamma)
EXTERN_CVAR (Int, vid_maxfps)
EXTERN_CVAR (Bool, cl_capfps)
EXTERN_CVAR (Bool, vid_vsync)
// PUBLIC DATA DEFINITIONS -------------------------------------------------
@ -326,6 +334,7 @@ SDLFB::SDLFB (int width, int height, bool fullscreen)
}
memcpy (SourcePalette, GPalette.BaseColors, sizeof(PalEntry)*256);
UpdateColors ();
SetVSync (vid_vsync);
}
SDLFB::~SDLFB ()
@ -535,6 +544,26 @@ bool SDLFB::IsFullscreen ()
return (Screen->flags & SDL_FULLSCREEN) != 0;
}
void SDLFB::SetVSync (bool vsync)
{
#ifdef __APPLE__
if (CGLContextObj context = CGLGetCurrentContext())
{
// Apply vsync for native backend only (where OpenGL context is set)
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
// Inconsistency between 10.4 and 10.5 SDKs:
// third argument of CGLSetParameter() is const long* on 10.4 and const GLint* on 10.5
// So, GLint typedef'ed to long instead of int to workaround this issue
typedef long GLint;
#endif // prior to 10.5
const GLint value = vsync ? 1 : 0;
CGLSetParameter(context, kCGLCPSwapInterval, &value);
}
#endif // __APPLE__
}
ADD_STAT (blit)
{
FString out;

View file

@ -433,7 +433,7 @@ bool TimidityPPMIDIDevice::LaunchTimidity ()
}
int forkres;
wordexp_t words;
wordexp_t words = {};
switch (wordexp (CommandLine.GetChars(), &words, 0))
{

View file

@ -63,6 +63,7 @@ enum
STAT_SECTOREFFECT, // All sector effects that cause floor and ceiling movement
STAT_ACTORMOVER, // actor movers
STAT_SCRIPTS, // The ACS thinker. This is to ensure that it can't tick before all actors called PostBeginPlay
STAT_BOT, // Bot thinker
};
#endif

View file

@ -266,11 +266,11 @@ enum EDefinitionType
#define GCC_MSEG
#else
#define MSVC_ASEG
#define GCC_ASEG __attribute__((section(SECTION_AREG)))
#define GCC_ASEG __attribute__((section(SECTION_AREG))) __attribute__((used))
#define MSVC_PSEG
#define GCC_PSEG __attribute__((section(SECTION_GREG)))
#define GCC_PSEG __attribute__((section(SECTION_GREG))) __attribute__((used))
#define MSVC_MSEG
#define GCC_MSEG __attribute__((section(SECTION_MREG)))
#define GCC_MSEG __attribute__((section(SECTION_MREG))) __attribute__((used))
#endif

View file

@ -76,7 +76,7 @@ const char *GetVersionString();
// Use 4500 as the base git save version, since it's higher than the
// SVN revision ever got.
#define SAVEVER 4515
#define SAVEVER 4516
#define SAVEVERSTRINGIFY2(x) #x
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)

View file

@ -2,9 +2,9 @@ cmake_minimum_required( VERSION 2.4 )
add_subdirectory( lemon )
add_subdirectory( re2c )
if( WIN32 )
if( WIN32 AND NOT CMAKE_SIZEOF_VOID_P MATCHES "8" )
add_subdirectory( fixrtext )
endif( WIN32 )
endif( WIN32 AND NOT CMAKE_SIZEOF_VOID_P MATCHES "8" )
add_subdirectory( updaterevision )
add_subdirectory( zipdir )

View file

@ -1478,6 +1478,7 @@ OptionValue OplCores
0, "MAME OPL2"
1, "DOSBox OPL3"
2, "Java OPL3"
3, "Nuked OPL3"
}
OptionMenu AdvSoundOptions

View file

@ -2632,6 +2632,14 @@
RelativePath=".\src\oplsynth\opl_mus_player.h"
>
</File>
<File
RelativePath=".\src\oplsynth\nukedopl3.cpp"
>
</File>
<File
RelativePath=".\src\oplsynth\nukedopl3.h"
>
</File>
<Filter
Name="DOSBox"
>