diff --git a/config.def.h b/config.def.h index 88a931c393..3c1b02c72b 100644 --- a/config.def.h +++ b/config.def.h @@ -93,6 +93,10 @@ #define DEFAULT_MAX_PADS 16 #endif +#if defined(GEKKO) +#define DEFAULT_MOUSE_SCALE 1 +#endif + #if defined(RARCH_MOBILE) || defined(HAVE_LIBNX) #define DEFAULT_POINTER_ENABLE true #else diff --git a/configuration.c b/configuration.c index 749da361d6..910112c8ac 100644 --- a/configuration.c +++ b/configuration.c @@ -1726,6 +1726,9 @@ static struct config_uint_setting *populate_settings_uint(settings_t *settings, SETTING_UINT("input_max_users", input_driver_get_uint(INPUT_ACTION_MAX_USERS), true, input_max_users, false); SETTING_UINT("fps_update_interval", &settings->uints.fps_update_interval, true, DEFAULT_FPS_UPDATE_INTERVAL, false); SETTING_UINT("input_menu_toggle_gamepad_combo", &settings->uints.input_menu_toggle_gamepad_combo, true, menu_toggle_gamepad_combo, false); +#ifdef GEKKO + SETTING_UINT("input_mouse_scale", &settings->uints.input_mouse_scale, true, DEFAULT_MOUSE_SCALE, false); +#endif SETTING_UINT("audio_latency", &settings->uints.audio_latency, false, 0 /* TODO */, false); SETTING_UINT("audio_resampler_quality", &settings->uints.audio_resampler_quality, true, audio_resampler_quality_level, false); SETTING_UINT("audio_block_frames", &settings->uints.audio_block_frames, true, 0, false); diff --git a/configuration.h b/configuration.h index 7c1dda92cd..7107eb790d 100644 --- a/configuration.h +++ b/configuration.h @@ -454,7 +454,9 @@ typedef struct settings unsigned input_bind_timeout; unsigned input_bind_hold; - +#ifdef GEKKO + unsigned input_mouse_scale; +#endif unsigned input_menu_toggle_gamepad_combo; unsigned input_keyboard_gamepad_mapping_type; unsigned input_poll_type_behavior; diff --git a/input/drivers/gx_input.c b/input/drivers/gx_input.c index d93413a0bf..ddf178eb2e 100644 --- a/input/drivers/gx_input.c +++ b/input/drivers/gx_input.c @@ -32,11 +32,103 @@ /* TODO/FIXME - * fix game focus toggle */ +/* gx joypad functions */ +bool gxpad_mousevalid(unsigned port); +void gx_joypad_read_mouse(unsigned port, int *irx, int *iry, uint32_t *button); + +typedef struct +{ + int x_abs, y_abs; + int x_last, y_last; + uint32_t button; +} gx_input_mouse_t; + typedef struct gx_input { const input_device_driver_t *joypad; + int mouse_max; + gx_input_mouse_t *mouse; } gx_input_t; +static int16_t gx_lightgun_state(gx_input_t *gx, unsigned id, uint16_t joy_idx) +{ + struct video_viewport vp = {0}; + video_driver_get_viewport_info(&vp); + int16_t res_x = 0; + int16_t res_y = 0; + int16_t res_screen_x = 0; + int16_t res_screen_y = 0; + int16_t x = 0; + int16_t y = 0; + + vp.x = 0; + vp.y = 0; + vp.width = 0; + vp.height = 0; + vp.full_width = 0; + vp.full_height = 0; + + x = gx->mouse[joy_idx].x_abs; + y = gx->mouse[joy_idx].y_abs; + + if (!(video_driver_translate_coord_viewport_wrap(&vp, x, y, + &res_x, &res_y, &res_screen_x, &res_screen_y))) + return 0; + + switch (id) + { + case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_X: + return res_screen_x; + case RETRO_DEVICE_ID_LIGHTGUN_SCREEN_Y: + return res_screen_y; + case RETRO_DEVICE_ID_LIGHTGUN_TRIGGER: + return gx->mouse[joy_idx].button & (1 << RETRO_DEVICE_ID_LIGHTGUN_TRIGGER); + case RETRO_DEVICE_ID_LIGHTGUN_AUX_A: + return gx->mouse[joy_idx].button & (1 << RETRO_DEVICE_ID_LIGHTGUN_AUX_A); + case RETRO_DEVICE_ID_LIGHTGUN_AUX_B: + return gx->mouse[joy_idx].button & (1 << RETRO_DEVICE_ID_LIGHTGUN_AUX_B); + case RETRO_DEVICE_ID_LIGHTGUN_AUX_C: + return gx->mouse[joy_idx].button & (1 << RETRO_DEVICE_ID_LIGHTGUN_AUX_C); + case RETRO_DEVICE_ID_LIGHTGUN_START: + return gx->mouse[joy_idx].button & (1 << RETRO_DEVICE_ID_LIGHTGUN_START); + case RETRO_DEVICE_ID_LIGHTGUN_SELECT: + return gx->mouse[joy_idx].button & (1 << RETRO_DEVICE_ID_LIGHTGUN_SELECT); + case RETRO_DEVICE_ID_LIGHTGUN_IS_OFFSCREEN: + return !gxpad_mousevalid(joy_idx); + default: + return 0; + } + + return 0; +} + +static int16_t gx_mouse_state(gx_input_t *gx, unsigned id, uint16_t joy_idx) +{ + int x = 0; + int y = 0; + + settings_t *settings = config_get_ptr(); + int x_scale = settings->uints.input_mouse_scale; + int y_scale = settings->uints.input_mouse_scale; + + x = (gx->mouse[joy_idx].x_abs - gx->mouse[joy_idx].x_last) * x_scale; + y = (gx->mouse[joy_idx].y_abs - gx->mouse[joy_idx].y_last) * y_scale; + + switch (id) + { + case RETRO_DEVICE_ID_MOUSE_X: + return x; + case RETRO_DEVICE_ID_MOUSE_Y: + return y; + case RETRO_DEVICE_ID_MOUSE_LEFT: + return gx->mouse[joy_idx].button & (1 << RETRO_DEVICE_ID_MOUSE_LEFT); + case RETRO_DEVICE_ID_MOUSE_RIGHT: + return gx->mouse[joy_idx].button & (1 << RETRO_DEVICE_ID_MOUSE_RIGHT); + default: + return 0; + } +} + static int16_t gx_input_state(void *data, rarch_joypad_info_t joypad_info, const struct retro_keybind **binds, @@ -96,6 +188,12 @@ static int16_t gx_input_state(void *data, return input_joypad_analog(gx->joypad, joypad_info, port, idx, id, binds[port]); break; + + case RETRO_DEVICE_MOUSE: + return gx_mouse_state(gx, id, joypad_info.joy_idx); + + case RETRO_DEVICE_LIGHTGUN: + return gx_lightgun_state(gx, id, joypad_info.joy_idx); } return 0; @@ -111,9 +209,33 @@ static void gx_input_free_input(void *data) if (gx->joypad) gx->joypad->destroy(); + if(gx->mouse) + free(gx->mouse); + free(gx); } +static inline int gx_count_mouse(gx_input_t *gx) +{ + int count = 0; + + if(gx) + { + for(int i=0; ijoypad->name(i)) + { + if(!strcmp(gx->joypad->name(i), "Wiimote Controller")) + { + count++; + } + } + } + } + + return count; +} + static void *gx_input_init(const char *joypad_driver) { gx_input_t *gx = (gx_input_t*)calloc(1, sizeof(*gx)); @@ -122,22 +244,72 @@ static void *gx_input_init(const char *joypad_driver) gx->joypad = input_joypad_init_driver(joypad_driver, gx); + /* Allocate at least 1 mouse at startup */ + gx->mouse_max = 1; + gx->mouse = (gx_input_mouse_t*) calloc(gx->mouse_max, sizeof(gx_input_mouse_t)); + return gx; } +static void gx_input_poll_mouse(gx_input_t *gx) +{ + int count = 0; + count = gx_count_mouse(gx); + + if(gx && count > 0) + { + if(count != gx->mouse_max) + { + gx_input_mouse_t* tmp = NULL; + + tmp = (gx_input_mouse_t*)realloc(gx->mouse, count * sizeof(gx_input_mouse_t)); + if(!tmp) + { + free(gx->mouse); + } + else + { + gx->mouse = tmp; + gx->mouse_max = count; + + for(int i=0; imouse_max; i++) + { + gx->mouse[i].x_last = 0; + gx->mouse[i].y_last = 0; + } + } + } + + for(unsigned i=0; imouse_max; i++) + { + gx->mouse[i].x_last = gx->mouse[i].x_abs; + gx->mouse[i].y_last = gx->mouse[i].y_abs; + gx_joypad_read_mouse(i, &gx->mouse[i].x_abs, &gx->mouse[i].y_abs, &gx->mouse[i].button); + } + } +} + static void gx_input_poll(void *data) { gx_input_t *gx = (gx_input_t*)data; if (gx && gx->joypad) + { gx->joypad->poll(); + + if(gx->mouse) + gx_input_poll_mouse(gx); + } } static uint64_t gx_input_get_capabilities(void *data) { (void)data; - return (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG); + return (1 << RETRO_DEVICE_JOYPAD) | + (1 << RETRO_DEVICE_ANALOG) | + (1 << RETRO_DEVICE_MOUSE) | + (1 << RETRO_DEVICE_LIGHTGUN); } static const input_device_driver_t *gx_input_get_joypad_driver(void *data) diff --git a/input/drivers_joypad/gx_joypad.c b/input/drivers_joypad/gx_joypad.c index 5af82e6113..d560b31a32 100644 --- a/input/drivers_joypad/gx_joypad.c +++ b/input/drivers_joypad/gx_joypad.c @@ -29,6 +29,7 @@ #define WPADInit WPAD_Init #define WPADDisconnect WPAD_Disconnect #define WPADProbe WPAD_Probe +#define WPADSetDataFormat WPAD_SetDataFormat #endif #define WPAD_EXP_SICKSAXIS 252 @@ -41,6 +42,12 @@ #define NUM_DEVICES 1 #endif +#ifdef HW_RVL +#define MAX_MOUSEBUTTONS 6 +static const uint32_t gx_mousemask[MAX_MOUSEBUTTONS] = {WPAD_BUTTON_B, WPAD_BUTTON_A, WPAD_BUTTON_1, WPAD_BUTTON_2, + WPAD_BUTTON_PLUS, WPAD_BUTTON_MINUS}; +#endif + enum { GX_GC_A = 0, @@ -102,6 +109,17 @@ static uint32_t pad_type[DEFAULT_MAX_PADS] = { WPAD_EXP_NOCONTROLLER, WPAD_EXP_N static int16_t analog_state[DEFAULT_MAX_PADS][2][2]; static bool g_menu = false; +struct gx_mousedata +{ + int32_t x, y; + uint32_t mouse_button; + bool valid; +}; + +static struct gx_mousedata gx_mouse[2]; + +static bool gx_joypad_query_pad(unsigned pad); + #ifdef HW_RVL static bool g_quit = false; @@ -116,6 +134,45 @@ static void reset_cb(void) g_menu = true; } +static inline void gx_mouse_info(uint32_t joybutton, unsigned port) { + uint8_t i; + ir_t ir; + + /* Get the IR data from the wiimote */ + WPAD_IR(port, &ir); + if (ir.valid) + { + gx_mouse[port].valid = true; + gx_mouse[port].x = ir.x; + gx_mouse[port].y = ir.y; + } + else + { + gx_mouse[port].valid = false; + } + + /* reset button state */ + gx_mouse[port].mouse_button = 0; + for (i = 0; i < MAX_MOUSEBUTTONS; i++) { + gx_mouse[port].mouse_button |= (joybutton & gx_mousemask[i]) ? (1 << i) : 0; + } + + /* Small adjustment to match the RA buttons */ + gx_mouse[port].mouse_button = gx_mouse[port].mouse_button << 2; +} + +bool gxpad_mousevalid(unsigned port) +{ + return gx_mouse[port].valid; +} + +void gx_joypad_read_mouse(unsigned port, int *irx, int *iry, uint32_t *button) +{ + *irx = gx_mouse[port].x; + *iry = gx_mouse[port].y; + *button = gx_mouse[port].mouse_button; +} + static const char *gx_joypad_name(unsigned pad) { switch (pad_type[pad]) @@ -150,6 +207,33 @@ static void handle_hotplug(unsigned port, uint32_t ptype) ); } +static void check_port0_active(uint8_t pad_count) +{ + settings_t *settings = config_get_ptr(); + int idx = settings->uints.input_joypad_map[0]; + + if(pad_count < 2 && idx != 0) + { +#ifdef HW_RVL + pad_type[0] = WPAD_EXP_NONE; +#else + pad_type[0] = WPAD_EXP_GAMECUBE; +#endif + settings->uints.input_joypad_map[0] = 0; + + input_autoconfigure_connect( + gx_joypad_name(0), + NULL, + gx_joypad.ident, + 0, // port + 0, + 0 + ); + + input_config_set_device_name(0, gx_joypad_name(0)); + } +} + static bool gx_joypad_button(unsigned port, uint16_t key) { if (port >= DEFAULT_MAX_PADS) @@ -309,6 +393,7 @@ static int16_t WPAD_StickY(WPADData *data, u8 right) static void gx_joypad_poll(void) { unsigned i, j, port; + uint8_t pad_count = 0; uint8_t gcpad = 0; uint64_t state_p1; uint64_t check_menu_toggle; @@ -381,6 +466,13 @@ static void gx_joypad_poll(void) down = wpaddata->btns_h; + /* Mouse & Lightgun: Retrieve IR data */ + if (ptype == WPAD_EXP_NONE) + { + if (port == WPAD_CHAN_0 || port == WPAD_CHAN_1) + gx_mouse_info(wpaddata->btns_h, port); + } + *state_cur |= (down & WPAD_BUTTON_A) ? (UINT64_C(1) << GX_WIIMOTE_A) : 0; *state_cur |= (down & WPAD_BUTTON_B) ? (UINT64_C(1) << GX_WIIMOTE_B) : 0; *state_cur |= (down & WPAD_BUTTON_1) ? (UINT64_C(1) << GX_WIIMOTE_1) : 0; @@ -389,6 +481,8 @@ static void gx_joypad_poll(void) *state_cur |= (down & WPAD_BUTTON_MINUS) ? (UINT64_C(1) << GX_WIIMOTE_MINUS) : 0; *state_cur |= (down & WPAD_BUTTON_HOME) ? (UINT64_C(1) << GX_WIIMOTE_HOME) : 0; + + if (ptype != WPAD_EXP_NUNCHUK) { /* Rotated d-pad on Wiimote. */ @@ -439,6 +533,14 @@ static void gx_joypad_poll(void) } #endif + /* Count active controllers */ + if(gx_joypad_query_pad(port)) + pad_count++; + + /* Always enable 1 pad in port 0 if there's only 1 controller connected. + * This avoids being stuck in rgui input settings. */ + check_port0_active(pad_count); + if (ptype != pad_type[port]) handle_hotplug(port, ptype); @@ -482,6 +584,9 @@ static bool gx_joypad_init(void *data) PAD_Init(); #ifdef HW_RVL WPADInit(); + /* Set IR for all wiimotes */ + WPAD_SetVRes(WPAD_CHAN_ALL,640,480); + WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR); #endif gx_joypad_poll(); diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 6d13938271..4fcf775066 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -567,6 +567,10 @@ MSG_HASH(MENU_ENUM_LABEL_INPUT_ANALOG_DEADZONE, "input_analog_deadzone") MSG_HASH(MENU_ENUM_LABEL_INPUT_ANALOG_SENSITIVITY, "input_analog_sensitivity") +#ifdef GEKKO +MSG_HASH(MENU_ENUM_LABEL_INPUT_MOUSE_SCALE, + "input_mouse_scale") +#endif MSG_HASH(MENU_ENUM_LABEL_INPUT_BIND_MODE, "input_bind_mode") MSG_HASH(MENU_ENUM_LABEL_INPUT_BIND_TIMEOUT, diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 481537193a..616e31150e 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -1085,6 +1085,16 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_SENSITIVITY, "Analog Sensitivity" ) +#ifdef GEKKO +MSG_HASH( + MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_SCALE, + "Mouse Scale" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_INPUT_MOUSE_SCALE, + "Adjust x/y scale for Wiimote lightgun speed." + ) +#endif MSG_HASH( MENU_ENUM_LABEL_VALUE_MENU_INPUT_SWAP_OK_CANCEL, "Menu Swap OK & Cancel Buttons" diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index f04573e8ee..daa910b278 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -230,6 +230,9 @@ default_sublabel_macro(action_bind_sublabel_audio_volume, MENU_ default_sublabel_macro(action_bind_sublabel_audio_mixer_volume, MENU_ENUM_SUBLABEL_AUDIO_MIXER_VOLUME) #endif default_sublabel_macro(action_bind_sublabel_audio_sync, MENU_ENUM_SUBLABEL_AUDIO_SYNC) +#if defined(GEKKO) +default_sublabel_macro(action_bind_sublabel_input_mouse_scale, MENU_ENUM_SUBLABEL_INPUT_MOUSE_SCALE) +#endif default_sublabel_macro(action_bind_sublabel_axis_threshold, MENU_ENUM_SUBLABEL_INPUT_BUTTON_AXIS_THRESHOLD) default_sublabel_macro(action_bind_sublabel_input_turbo_period, MENU_ENUM_SUBLABEL_INPUT_TURBO_PERIOD) default_sublabel_macro(action_bind_sublabel_input_duty_cycle, MENU_ENUM_SUBLABEL_INPUT_DUTY_CYCLE) @@ -2402,6 +2405,11 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_INPUT_BUTTON_AXIS_THRESHOLD: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_axis_threshold); break; +#if defined(GEKKO) + case MENU_ENUM_LABEL_INPUT_MOUSE_SCALE: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_mouse_scale); + break; +#endif case MENU_ENUM_LABEL_AUDIO_SYNC: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_audio_sync); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 79ddeb8921..f47f7cbd4a 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -3768,6 +3768,12 @@ unsigned menu_displaylist_build_list(file_list_t *list, enum menu_displaylist_ct MENU_ENUM_LABEL_INPUT_BUTTON_AXIS_THRESHOLD, PARSE_ONLY_FLOAT, false) == 0) count++; +#if defined(GEKKO) + if (menu_displaylist_parse_settings_enum(list, + MENU_ENUM_LABEL_INPUT_MOUSE_SCALE, + PARSE_ONLY_UINT, false) == 0) + count++; +#endif if (menu_displaylist_parse_settings_enum(list, MENU_ENUM_LABEL_INPUT_ANALOG_DEADZONE, PARSE_ONLY_FLOAT, false) == 0) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index f5364dc2b0..72ea5aa40b 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -10349,6 +10349,21 @@ static bool setting_append_list( menu_settings_list_current_add_range(list, list_info, 0, 2, 1, true, true); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED); +#ifdef GEKKO + CONFIG_UINT( + list, list_info, + &settings->uints.input_mouse_scale, + MENU_ENUM_LABEL_INPUT_MOUSE_SCALE, + MENU_ENUM_LABEL_VALUE_INPUT_MOUSE_SCALE, + DEFAULT_MOUSE_SCALE, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler); + menu_settings_list_current_add_range(list, list_info, 1, 4, 1, true, true); +#endif + #ifdef VITA CONFIG_BOOL( list, list_info, diff --git a/msg_hash.h b/msg_hash.h index 4c11a0da26..9c614e0f6f 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -772,6 +772,9 @@ enum msg_hash_enums MENU_LABEL(INPUT_DESCRIPTOR_LABEL_SHOW), MENU_LABEL(INPUT_DESCRIPTOR_HIDE_UNBOUND), MENU_LABEL(INPUT_BUTTON_AXIS_THRESHOLD), +#if defined(GEKKO) + MENU_LABEL(INPUT_MOUSE_SCALE), +#endif MENU_LABEL(INPUT_ANALOG_DEADZONE), MENU_LABEL(INPUT_ANALOG_SENSITIVITY), MENU_LABEL(INPUT_BIND_TIMEOUT), diff --git a/wii/libogc/libs/wii/libbte.a b/wii/libogc/libs/wii/libbte.a index 191c62e51b..9cc37e149b 100644 Binary files a/wii/libogc/libs/wii/libbte.a and b/wii/libogc/libs/wii/libbte.a differ diff --git a/wii/libogc/libs/wii/libdb.a b/wii/libogc/libs/wii/libdb.a index 876deee6b8..9981b20ee8 100644 Binary files a/wii/libogc/libs/wii/libdb.a and b/wii/libogc/libs/wii/libdb.a differ diff --git a/wii/libogc/libs/wii/libogc.a b/wii/libogc/libs/wii/libogc.a index 8d1fd55a9f..ec000bbe7f 100644 Binary files a/wii/libogc/libs/wii/libogc.a and b/wii/libogc/libs/wii/libogc.a differ diff --git a/wii/libogc/libs/wii/libwiikeyboard.a b/wii/libogc/libs/wii/libwiikeyboard.a index 4a24f7cee4..6ef17286b2 100644 Binary files a/wii/libogc/libs/wii/libwiikeyboard.a and b/wii/libogc/libs/wii/libwiikeyboard.a differ diff --git a/wii/libogc/libs/wii/libwiiuse.a b/wii/libogc/libs/wii/libwiiuse.a index 60f39ba83a..fc934065bb 100644 Binary files a/wii/libogc/libs/wii/libwiiuse.a and b/wii/libogc/libs/wii/libwiiuse.a differ diff --git a/wii/libogc/wiiuse/wpad.c b/wii/libogc/wiiuse/wpad.c index 639ed79222..1d97f9f520 100644 --- a/wii/libogc/wiiuse/wpad.c +++ b/wii/libogc/wiiuse/wpad.c @@ -1104,3 +1104,41 @@ void WPAD_Accel(int chan, struct vec3w_t *accel) //if(chan<0 || chan>=WPAD_MAX_WIIMOTES || accel==NULL ) return; *accel = wpaddata[chan].accel; } + +s32 WPAD_SetDataFormat(s32 chan, s32 fmt) +{ + u32 level; + s32 ret; + int i; + + if(chan == WPAD_CHAN_ALL) { + for(i=WPAD_CHAN_0; i=WPAD_MAX_WIIMOTES) return WPAD_ERR_BAD_CHANNEL; + + _CPU_ISR_Disable(level); + if(__wpads_inited==WPAD_STATE_DISABLED) { + _CPU_ISR_Restore(level); + return WPAD_ERR_NOT_READY; + } + + if(__wpads[chan]!=NULL) { + switch(fmt) { + case WPAD_FMT_BTNS: + case WPAD_FMT_BTNS_ACC: + case WPAD_FMT_BTNS_ACC_IR: + __wpdcb[chan].data_fmt = fmt; + __wpad_setfmt(chan); + break; + default: + _CPU_ISR_Restore(level); + return WPAD_ERR_BADVALUE; + } + } + _CPU_ISR_Restore(level); + return WPAD_ERR_NONE; +}