Index: include/wupc/wupc.h =================================================================== --- include/wupc/wupc.h (revision 3) +++ include/wupc/wupc.h (working copy) @@ -1,5 +1,6 @@ /**************************************************************************** * Copyright (C) 2014 FIX94 + * Changes, based on revision 3, by JoostinOnline * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +22,7 @@ extern "C" { #endif -struct WUPCData { +typedef struct WUPCData_s { s16 xAxisL; s16 xAxisR; s16 yAxisL; @@ -29,20 +30,68 @@ u32 button; u8 battery; u8 extra; +} WUPCData; + +enum { + WUPC_CHAN_0, + WUPC_CHAN_1, + WUPC_CHAN_2, + WUPC_CHAN_3, + WUPC_MAX_REMOTES }; +enum { + WUPC_BATTERY_CRITICAL, + WUPC_BATTERY_LOW, + WUPC_BATTERY_MEDIUM, + WUPC_BATTERY_HIGH, + WUPC_BATTERY_FULL +}; + +enum { + WUPC_STATE_DISABLED, + WUPC_STATE_ENABLED +}; + +#define WUPC_ERR_NONE 0 +#define WUPC_ERR_NOT_READY -1 +#define WUPC_ERR_BAD_CHANNEL -2 +#define WUPC_ERR_BADCONF -3 +#define WUPC_ERR_UNKNOWN -4 + #define WUPC_EXTRA_BUTTON_RSTICK 0x01 #define WUPC_EXTRA_BUTTON_LSTICK 0x02 - #define WUPC_EXTRA_CHARGING 0x04 #define WUPC_EXTRA_USBCONNECTED 0x08 -void WUPC_Init(); -void WUPC_Disconnect(u8 chan); -void WUPC_Shutdown(); -struct WUPCData *WUPC_Data(u8 chan); +// Identical to WPAD_CLASSIC_BUTTON_ values in wpad.h +#define WUPC_BUTTON_UP (0x0001<<16) +#define WUPC_BUTTON_LEFT (0x0002<<16) +#define WUPC_BUTTON_ZR (0x0004<<16) +#define WUPC_BUTTON_X (0x0008<<16) +#define WUPC_BUTTON_A (0x0010<<16) +#define WUPC_BUTTON_Y (0x0020<<16) +#define WUPC_BUTTON_B (0x0040<<16) +#define WUPC_BUTTON_ZL (0x0080<<16) +#define WUPC_BUTTON_FULL_R (0x0200<<16) +#define WUPC_BUTTON_PLUS (0x0400<<16) +#define WUPC_BUTTON_HOME (0x0800<<16) +#define WUPC_BUTTON_MINUS (0x1000<<16) +#define WUPC_BUTTON_FULL_L (0x2000<<16) +#define WUPC_BUTTON_DOWN (0x4000<<16) +#define WUPC_BUTTON_RIGHT (0x8000<<16) + +typedef void (*WUPCShutdownCallback)(s32 chan); + +s32 WUPC_Init(void); // Call before WPAD_Init() +s32 WUPC_Disconnect(u8 chan); +void WUPC_Shutdown(void); // Call before WPAD_Shutdown() +void WUPC_SetIdleTimeout(u32 seconds); +void WUPC_SetPowerButtonCallback(WUPCShutdownCallback cb); +void WUPC_SetBatteryDeadCallback(WUPCShutdownCallback cb); +WUPCData *WUPC_Data(u8 chan); void WUPC_Rumble(u8 chan, bool rumble); -u32 WUPC_UpdateButtonStats(); +u32 WUPC_ScanPads(void); u32 WUPC_ButtonsUp(u8 chan); u32 WUPC_ButtonsDown(u8 chan); u32 WUPC_ButtonsHeld(u8 chan); @@ -50,6 +99,7 @@ s16 WUPC_lStickY(u8 chan); s16 WUPC_rStickX(u8 chan); s16 WUPC_rStickY(u8 chan); +u8 WUPC_BatteryLevel(u8 chan); #ifdef __cplusplus } Index: lib/libwupc.a =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: Makefile =================================================================== --- Makefile (revision 3) +++ Makefile (working copy) @@ -20,13 +20,21 @@ SOURCES := source DATA := data INCLUDES := include - +INCDIR := $(LIBOGC_INC)/wupc/ +INCFILE := include/wupc/wupc +LIBFILE := lib/$(TARGET) #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -CFLAGS = -g -O2 -Wall -Wextra $(MACHDEP) $(INCLUDE) +CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) #--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(DEVKITPRO)/libogc + +#--------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional # rules for different file extensions #--------------------------------------------------------------------------------- @@ -64,16 +72,27 @@ #--------------------------------------------------------------------------------- $(BUILD): + @echo Building ... @[ -d $@ ] || mkdir -p $@ @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile #--------------------------------------------------------------------------------- clean: - @echo clean ... + @echo Cleaning ... @rm -fr $(BUILD) $(OUTPUT).a +#--------------------------------------------------------------------------------- +install: + @echo Installing ... + @mkdir -p $(INCDIR) + @install -v -m 644 $(LIBFILE).a $(LIBOGC_LIB) + @install -v -m 644 $(INCFILE).h $(INCDIR) #--------------------------------------------------------------------------------- + +all: clean $(BUILD) install +#--------------------------------------------------------------------------------- + else DEPENDS := $(OFILES:.o=.d) Index: source/wupc.c =================================================================== --- source/wupc.c (revision 3) +++ source/wupc.c (working copy) @@ -1,5 +1,6 @@ /**************************************************************************** * Copyright (C) 2014 FIX94 + * Changes, based on revision 3, by JoostinOnline * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,8 +21,12 @@ #include #include #include +#include #include #include +#include +#include + #include "wupc_structs.h" #include "wupc/wupc.h" @@ -29,21 +34,41 @@ static vu32 __WUPC_ChannelsUsed = 0; +static syswd_t __wupc_timer; static conf_pads __WUPC_Devices; -static struct WUPCStat *__WUPC_Connected[4]; +static struct WUPCStat *__WUPC_Connected[WUPC_MAX_REMOTES]; static struct WUPCStat __WUPC_Status[CONF_PAD_MAX_REGISTERED]; -static struct WUPCData __WUPC_PadData[4]; -static struct WUPCButtons __WUPC_PadButtons[4]; +static WUPCData __WUPC_PadData[WUPC_MAX_REMOTES]; +static struct WUPCButtons __WUPC_PadButtons[WUPC_MAX_REMOTES]; +static struct _wpad_cb __wupccb[WUPC_MAX_REMOTES]; +static s32 __wupc_idletimeout = 300; -static u32 __WUPC_Inited = 0; +static vu32 __WUPC_Inited = WUPC_STATE_DISABLED; static const u8 __WUPC_LEDState[] = { 0x10, 0x20, 0x40, 0x80 }; -#define CHAN_MAX 4 +#define TRANSFER_CALIBRATE 0 +#define TRANSFER_DONE 1 -#define TRANSFER_CALIBRATE 0 -#define TRANSFER_DONE 1 +static void __wupc_timeouthandler(syswd_t alarm,void *cbarg) +{ + s32 i; + struct _wpad_cb *wupccb = (struct _wpad_cb*)cbarg; + ++_thread_dispatch_disable_level; + for(i=WUPC_MAX_REMOTES; i--;) { + wupccb = &__wupccb[i]; + if(__WUPC_Connected[i] != NULL) { + wupccb->idle_time++; + if(wupccb->idle_time>=__wupc_idletimeout) { + wupccb->idle_time = 0; + WUPC_Disconnect(i); + } + } + } + --_thread_dispatch_disable_level; +} + static void __WUPC_SetLED(struct bte_pcb *sock, u32 state) { u8 buf[2]; @@ -75,7 +100,7 @@ __WUPC_PadData[chan].battery = (extradata >> 4) & 0x7; __WUPC_PadData[chan].extra = extradata & 0xF; } - return ERR_OK; + return WUPC_ERR_NONE; } static s32 __WUPC_HandleConnect(void *arg,struct bte_pcb *pcb,u8 err) @@ -82,7 +107,7 @@ { struct WUPCStat *stat = (struct WUPCStat*)arg; - if(__WUPC_ChannelsUsed >= CHAN_MAX) + if(__WUPC_ChannelsUsed >= WUPC_MAX_REMOTES) { bte_disconnect(pcb); return err; @@ -111,25 +136,25 @@ if(__WUPC_ChannelsUsed) __WUPC_ChannelsUsed--; u32 i; - for(i = stat->channel; i < 3; ++i) + for(i = stat->channel; i < WUPC_MAX_REMOTES-1; ++i) __WUPC_Connected[i] = __WUPC_Connected[i+1]; - __WUPC_Connected[3] = NULL; + __WUPC_Connected[WUPC_MAX_REMOTES-1] = NULL; for(i = 0; i < CONF_PAD_MAX_REGISTERED; ++i) { - if(__WUPC_Status[i].channel > stat->channel && __WUPC_Status[i].channel != CHAN_MAX) + if(__WUPC_Status[i].channel > stat->channel && __WUPC_Status[i].channel != WUPC_MAX_REMOTES) { __WUPC_Status[i].channel--; __WUPC_SetLED(__WUPC_Status[i].sock, __WUPC_Status[i].channel); } } - stat->channel = CHAN_MAX; + stat->channel = WUPC_MAX_REMOTES; return err; } int __WUPC_RegisterPad(struct WUPCStat *stat, struct bd_addr *_bdaddr) { - stat->channel = CHAN_MAX; + stat->channel = WUPC_MAX_REMOTES; stat->bdaddr = *_bdaddr; if(stat->sock == NULL) @@ -136,7 +161,7 @@ { stat->sock = bte_new(); if(stat->sock == NULL) - return ERR_OK; + return WUPC_ERR_NONE; } bte_arg(stat->sock, stat); @@ -145,14 +170,16 @@ bte_registerdeviceasync(stat->sock, _bdaddr, __WUPC_HandleConnect); - return ERR_OK; + return WUPC_ERR_NONE; } int __wrap_wiiuse_register(struct wiimote_listen_t *wml, struct bd_addr *bdaddr, struct wiimote_t *(*assign_cb)(struct bd_addr *bdaddr)) { - if(__WUPC_Inited) + u32 level; + _CPU_ISR_Disable(level); + if(__WUPC_Inited == WUPC_STATE_ENABLED) { - u8 got_addr[] = { bdaddr->addr[5], bdaddr->addr[4], bdaddr->addr[3], bdaddr->addr[2], bdaddr->addr[1], bdaddr->addr[0] }; + const u8 got_addr[] = { bdaddr->addr[5], bdaddr->addr[4], bdaddr->addr[3], bdaddr->addr[2], bdaddr->addr[1], bdaddr->addr[0] }; u32 i; for(i = 0; i < __WUPC_Devices.num_registered; ++i) { @@ -159,62 +186,98 @@ if(strstr(__WUPC_Devices.registered[i].name, "-UC") != NULL) { u8 *cur_bdaddr = __WUPC_Devices.registered[i].bdaddr; - if(memcmp(cur_bdaddr, got_addr, 6) == 0) + if(memcmp(cur_bdaddr, got_addr, 6) == 0) { + _CPU_ISR_Restore(level); return __WUPC_RegisterPad(&__WUPC_Status[i], bdaddr); + } } } } + _CPU_ISR_Restore(level); return __real_wiiuse_register(wml,bdaddr,assign_cb); } -void WUPC_Init() +s32 WUPC_Init(void) { - if(__WUPC_Inited == 1) - return; - if(CONF_GetPadDevices(&__WUPC_Devices) < 0) - return; - + u32 level; + struct timespec tb; + memset(__wupccb,0,sizeof(struct _wpad_cb)*WUPC_MAX_REMOTES); + _CPU_ISR_Disable(level); + if(__WUPC_Inited == WUPC_STATE_ENABLED) { + _CPU_ISR_Restore(level); + return WUPC_ERR_NOT_READY; + } + if(CONF_GetPadDevices(&__WUPC_Devices) < 0) { + _CPU_ISR_Restore(level); + return WUPC_ERR_BADCONF; + } u32 i; - for(i = 0; i < CHAN_MAX; ++i) + for(i = WUPC_MAX_REMOTES; i--;) __WUPC_Connected[i] = NULL; - for(i = 0; i < CONF_PAD_MAX_REGISTERED; ++i) - __WUPC_Status[i].channel = CHAN_MAX; + for(i = CONF_PAD_MAX_REGISTERED; i--;) + __WUPC_Status[i].channel = WUPC_MAX_REMOTES; __WUPC_ChannelsUsed = 0; - __WUPC_Inited = 1; + + if (SYS_CreateAlarm(&__wupc_timer) < 0) + { + WUPC_Shutdown(); + _CPU_ISR_Restore(level); + return WUPC_ERR_UNKNOWN; + } + tb.tv_sec = 1; + tb.tv_nsec = 0; + SYS_SetPeriodicAlarm(__wupc_timer,&tb,&tb,__wupc_timeouthandler,NULL); + + __WUPC_Inited = WUPC_STATE_ENABLED; + _CPU_ISR_Restore(level); + return WUPC_ERR_NONE; } -void WUPC_Disconnect(u8 chan) +s32 WUPC_Disconnect(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return; + u32 level; + _CPU_ISR_Disable(level); + if(__WUPC_Inited == WUPC_STATE_DISABLED) { + _CPU_ISR_Restore(level); + return WUPC_ERR_NOT_READY; + } + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return WUPC_ERR_BAD_CHANNEL; bte_disconnect(__WUPC_Connected[chan]->sock); + _CPU_ISR_Restore(level); + return WUPC_ERR_NONE; } -void WUPC_Shutdown() +void WUPC_Shutdown(void) { - if(__WUPC_Inited == 0) + u32 level; + _CPU_ISR_Disable(level); + if(__WUPC_Inited == WUPC_STATE_DISABLED) { + _CPU_ISR_Restore(level); return; + } - __WUPC_Inited = 0; + __WUPC_Inited = WUPC_STATE_DISABLED; u32 i; - for(i = 0; i < CONF_PAD_MAX_REGISTERED; ++i) + for(i = CONF_PAD_MAX_REGISTERED; i--;) { - if(__WUPC_Status[i].channel != CHAN_MAX) + if(__WUPC_Status[i].channel != WUPC_MAX_REMOTES) bte_disconnect(__WUPC_Status[i].sock); } + _CPU_ISR_Restore(level); } -struct WUPCData *WUPC_Data(u8 chan) +WUPCData *WUPC_Data(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return NULL; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return NULL; return &__WUPC_PadData[chan]; } void WUPC_Rumble(u8 chan, bool rumble) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return; u8 buf[2]; buf[0] = 0x11; @@ -222,11 +285,11 @@ bte_senddata(__WUPC_Connected[chan]->sock,buf,2); } -u32 WUPC_UpdateButtonStats() +u32 WUPC_ScanPads(void) { u32 newstate, oldstate; u32 i, ret = 0; - for(i = 0; i < CHAN_MAX; ++i) + for(i = 0; i < WUPC_MAX_REMOTES; ++i) { if(__WUPC_Connected[i] == NULL) return ret; @@ -242,36 +305,67 @@ u32 WUPC_ButtonsUp(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return 0; return __WUPC_PadButtons[chan].up; } u32 WUPC_ButtonsDown(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return 0; return __WUPC_PadButtons[chan].down; } u32 WUPC_ButtonsHeld(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return 0; return __WUPC_PadButtons[chan].state; } s16 WUPC_lStickX(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return 0; return __WUPC_PadData[chan].xAxisL; } s16 WUPC_lStickY(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return 0; return __WUPC_PadData[chan].yAxisL; } s16 WUPC_rStickX(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return 0; return __WUPC_PadData[chan].xAxisR; } s16 WUPC_rStickY(u8 chan) { - if(chan >= CHAN_MAX || __WUPC_Connected[chan] == NULL) return 0; + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return 0; return __WUPC_PadData[chan].yAxisR; } +u8 WUPC_BatteryLevel(u8 chan) +{ + if(chan >= WUPC_MAX_REMOTES || __WUPC_Connected[chan] == NULL) return 0; + return __WUPC_PadData[chan].battery; +} +s32 WUPC_GetStatus(void) +{ + s32 ret; + u32 level; + + _CPU_ISR_Disable(level); + ret = __WUPC_Inited; + _CPU_ISR_Restore(level); + + return ret; +} +void WUPC_SetIdleTimeout(u32 seconds) +{ + u32 level; + + _CPU_ISR_Disable(level); + __wupc_idletimeout = seconds; + _CPU_ISR_Restore(level); +} +inline void WUPC_SetPowerButtonCallback(WUPCShutdownCallback cb) { + WPAD_SetPowerButtonCallback(cb); +} +inline void WUPC_SetBatteryDeadCallback(WUPCShutdownCallback cb) +{ + WPAD_SetBatteryDeadCallback(cb); +} \ No newline at end of file Index: source/wupc_structs.h =================================================================== --- source/wupc_structs.h (revision 3) +++ source/wupc_structs.h (working copy) @@ -1,7 +1,39 @@ - #ifndef _WUPC_STRUCTS_H_ #define _WUPC_STRUCTS_H_ +#define EVENTQUEUE_LENGTH 16 + +struct _wpad_thresh{ + s32 btns; + s32 ir; + s32 js; + s32 acc; + s32 wb; + s32 mp; +}; + +struct _wpad_cb { + wiimote *wm; + s32 data_fmt; + s32 queue_head; + s32 queue_tail; + s32 queue_full; + u32 queue_length; + u32 dropped_events; + s32 idle_time; + s32 speaker_enabled; + struct _wpad_thresh thresh; + + void *sound_data; + u32 sound_len; + u32 sound_off; + syswd_t sound_alarm; + + WPADData lstate; + WPADData *queue_ext; + WPADData queue_int[EVENTQUEUE_LENGTH]; +}; + struct WUPCStat { u32 connected; u32 transferstate; Index: usage.txt =================================================================== --- usage.txt (revision 3) +++ usage.txt (working copy) @@ -1,23 +1,24 @@ -libwupc - A WiiU Pro Controller Library for Wii Homebrew Applications by FIX94 -WiiU Pro Controller Documentation from TeHaxor69 - -1. Copy the "lib" and "include" folder into your "portlibs" folder - -2. Make these modifications to your Makefile: --add "-lwupc" right behind "-lwiiuse" to your LIBS --add ",-wrap,wiiuse_register" to your LDFLAGS - -3. Modify your code like this: --make sure to include in all files you use WUPC calls --call "WUPC_Init" before "WPAD_Init" --call "WUPC_Shutdown" before "WPAD_Shutdown" --either use the separate calls or use WUPC_Data at the same place you would normally use the WPAD calls for your data handling --if you use ButtonsUp, ButtonsUp and/or ButtonsHeld, make sure to call "WUPC_UpdateButtonStats" before "WPAD_ScanPads", -if you dont use any of these you can ignore "WUPC_UpdateButtonStats" - -Notes: --The X and Y-Axis are going from about -1024 to +1024, make sure you adjust your calculations to that --The Buttons are using the same layout as the classic controller buttons, use the "WPAD_CLASSIC_BUTTON_" definitions in --The Battery Status goes from 0 (critical) to 4 (full) - +libwupc - A WiiU Pro Controller Library for Wii Homebrew Applications by FIX94 +Modifications by JoostinOnline +WiiU Pro Controller Documentation from TeHaxor69 + +1. Copy the "lib" and "include" folder into your "libogc" folder. Alternatively, run "make install" from command line + +2. Make these modifications to your Makefile: +-Add "-lwupc" right after "-lwiiuse" to your LIBS +-Add ",-wrap,wiiuse_register" to your LDFLAGS + +3. Modify your code like this: +-Make sure to include in all files you use WUPC calls +-Call "WUPC_Init" before "WPAD_Init" +-Call "WUPC_Shutdown" before "WPAD_Shutdown" +-Either use the separate calls or use WUPC_Data at the same place you would normally use the WPAD calls for your data handling +-If you use ButtonsUp, ButtonsUp and/or ButtonsHeld, make sure to call "WUPC_ScanPads" before "WPAD_ScanPads". If you dont use any of these you can ignore "WUPC_ScanPads" + +Notes: +-The X and Y-Axis are going from about -1024 to +1024, make sure you adjust your calculations to that +-The Buttons are using the same layout as the classic controller buttons, so you can use the "WPAD_CLASSIC_BUTTON_" definitions in instead of the ones included in wupc.h +-The Battery Status goes from 0 (critical) to 4 (full) +-The "WUPC_SetPowerButtonCallback" and "WUPC_SetBatteryDeadCallback" functions will have the same effect as "WPAD_SetPowerButtonCallback" and "WPAD_SetBatteryDeadCallback" (respectively), so there is no need to use both the WPAD and WUPC versions. + Have Fun! \ No newline at end of file