1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3 * Copyright (C) 2011-2017 - Daniel De Matteis
4 * Copyright (C) 2012-2015 - Michael Lelli
5 * Copyright (C) 2013-2014 - Steven Crowe
6 *
7 * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found-
8 * ation, either version 3 of the License, or (at your option) any later version.
9 *
10 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 * PURPOSE. See the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along with RetroArch.
15 * If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "../../config.def.h"
19
20 #include "../input_driver.h"
21 #include "../drivers_keyboard/keyboard_event_android.h"
22
android_joypad_name(unsigned pad)23 static const char *android_joypad_name(unsigned pad)
24 {
25 return input_config_get_device_name(pad);
26 }
27
android_joypad_init(void * data)28 static void *android_joypad_init(void *data) { return (void*)-1; }
29
android_joypad_button_state(struct android_app * android_app,uint8_t * buf,unsigned port,uint16_t joykey)30 static int16_t android_joypad_button_state(
31 struct android_app *android_app,
32 uint8_t *buf,
33 unsigned port, uint16_t joykey)
34 {
35 unsigned hat_dir = GET_HAT_DIR(joykey);
36
37 if (hat_dir)
38 {
39 unsigned h = GET_HAT(joykey);
40 if (h > 0)
41 return 0;
42
43 switch (hat_dir)
44 {
45 case HAT_LEFT_MASK:
46 return (android_app->hat_state[port][0] == -1);
47 case HAT_RIGHT_MASK:
48 return (android_app->hat_state[port][0] == 1);
49 case HAT_UP_MASK:
50 return (android_app->hat_state[port][1] == -1);
51 case HAT_DOWN_MASK:
52 return (android_app->hat_state[port][1] == 1);
53 default:
54 break;
55 }
56 /* hat requested and no hat button down */
57 }
58 else if (joykey < LAST_KEYCODE)
59 return BIT_GET(buf, joykey);
60 return 0;
61 }
62
android_joypad_button(unsigned port,uint16_t joykey)63 static int16_t android_joypad_button(unsigned port, uint16_t joykey)
64 {
65 struct android_app *android_app = (struct android_app*)g_android;
66 uint8_t *buf = android_keyboard_state_get(port);
67
68 if (port >= DEFAULT_MAX_PADS)
69 return 0;
70
71 return android_joypad_button_state(android_app, buf, port, joykey);
72 }
73
android_joypad_axis_state(struct android_app * android_app,unsigned port,uint32_t joyaxis)74 static int16_t android_joypad_axis_state(
75 struct android_app *android_app,
76 unsigned port, uint32_t joyaxis)
77 {
78 if (AXIS_NEG_GET(joyaxis) < MAX_AXIS)
79 {
80 int val = android_app->analog_state[port][AXIS_NEG_GET(joyaxis)];
81 if (val < 0)
82 return val;
83 }
84 else if (AXIS_POS_GET(joyaxis) < MAX_AXIS)
85 {
86 int val = android_app->analog_state[port][AXIS_POS_GET(joyaxis)];
87 if (val > 0)
88 return val;
89 }
90
91 return 0;
92 }
93
android_joypad_axis(unsigned port,uint32_t joyaxis)94 static int16_t android_joypad_axis(unsigned port, uint32_t joyaxis)
95 {
96 struct android_app *android_app = (struct android_app*)g_android;
97 return android_joypad_axis_state(android_app, port, joyaxis);
98 }
99
android_joypad_state(rarch_joypad_info_t * joypad_info,const struct retro_keybind * binds,unsigned port)100 static int16_t android_joypad_state(
101 rarch_joypad_info_t *joypad_info,
102 const struct retro_keybind *binds,
103 unsigned port)
104 {
105 unsigned i;
106 int16_t ret = 0;
107 struct android_app *android_app = (struct android_app*)g_android;
108 uint8_t *buf = android_keyboard_state_get(port);
109 uint16_t port_idx = joypad_info->joy_idx;
110
111 if (port_idx >= DEFAULT_MAX_PADS)
112 return 0;
113
114 for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
115 {
116 /* Auto-binds are per joypad, not per user. */
117 const uint64_t joykey = (binds[i].joykey != NO_BTN)
118 ? binds[i].joykey : joypad_info->auto_binds[i].joykey;
119 const uint32_t joyaxis = (binds[i].joyaxis != AXIS_NONE)
120 ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
121 if ((uint16_t)joykey != NO_BTN
122 && android_joypad_button_state(
123 android_app,
124 buf,
125 port_idx, (uint16_t)joykey))
126 ret |= ( 1 << i);
127 else if (joyaxis != AXIS_NONE &&
128 ((float)abs(android_joypad_axis_state(
129 android_app, port_idx, joyaxis))
130 / 0x8000) > joypad_info->axis_threshold)
131 ret |= (1 << i);
132 }
133
134 return ret;
135 }
136
android_joypad_poll(void)137 static void android_joypad_poll(void) { }
138
android_joypad_query_pad(unsigned pad)139 static bool android_joypad_query_pad(unsigned pad)
140 {
141 return (pad < MAX_USERS);
142 }
143
android_joypad_destroy(void)144 static void android_joypad_destroy(void)
145 {
146 unsigned i, j;
147 struct android_app *android_app = (struct android_app*)g_android;
148
149 for (i = 0; i < DEFAULT_MAX_PADS; i++)
150 {
151 for (j = 0; j < 2; j++)
152 android_app->hat_state[i][j] = 0;
153 for (j = 0; j < MAX_AXIS; j++)
154 android_app->analog_state[i][j] = 0;
155 }
156
157 for (i = 0; i < MAX_USERS; i++)
158 {
159 android_app->rumble_last_strength_strong[i] = 0;
160 android_app->rumble_last_strength_weak [i] = 0;
161 android_app->rumble_last_strength [i] = 0;
162 android_app->id [i] = 0;
163 }
164 }
165
android_input_set_rumble_internal(uint16_t strength,uint16_t * last_strength_strong,uint16_t * last_strength_weak,uint16_t * last_strength,int8_t id,enum retro_rumble_effect effect)166 static void android_input_set_rumble_internal(
167 uint16_t strength,
168 uint16_t *last_strength_strong,
169 uint16_t *last_strength_weak,
170 uint16_t *last_strength,
171 int8_t id,
172 enum retro_rumble_effect effect
173 )
174 {
175 JNIEnv *env = (JNIEnv*)jni_thread_getenv();
176 uint16_t new_strength = 0;
177
178 if (!env)
179 return;
180
181 if (effect == RETRO_RUMBLE_STRONG)
182 {
183 new_strength = strength | *last_strength_weak;
184 *last_strength_strong = strength;
185 }
186 else if (effect == RETRO_RUMBLE_WEAK)
187 {
188 new_strength = strength | *last_strength_strong;
189 *last_strength_weak = strength;
190 }
191
192 if (new_strength != *last_strength)
193 {
194 /* trying to send this value as a JNI param without
195 * storing it first was causing 0 to be seen on the other side ?? */
196 int strength_final = (255.0f / 65535.0f) * (float)new_strength;
197
198 CALL_VOID_METHOD_PARAM(env, g_android->activity->clazz,
199 g_android->doVibrate, (jint)id, (jint)RETRO_RUMBLE_STRONG, (jint)strength_final, (jint)0);
200
201 *last_strength = new_strength;
202 }
203 }
204
android_joypad_rumble(unsigned port,enum retro_rumble_effect type,uint16_t strength)205 static bool android_joypad_rumble(unsigned port,
206 enum retro_rumble_effect type, uint16_t strength)
207 {
208 settings_t *settings = config_get_ptr();
209 struct android_app *android_app = (struct android_app*)g_android;
210 bool enable_device_vibration = settings->bools.enable_device_vibration;
211
212 if (!android_app || !android_app->doVibrate)
213 return false;
214
215 if (enable_device_vibration)
216 {
217 static uint16_t last_strength_strong = 0;
218 static uint16_t last_strength_weak = 0;
219 static uint16_t last_strength = 0;
220
221 if (port != 0)
222 return false;
223
224 android_input_set_rumble_internal(
225 strength,
226 &last_strength_strong,
227 &last_strength_weak,
228 &last_strength,
229 -1,
230 type);
231 }
232 else
233 {
234 android_input_set_rumble_internal(
235 strength,
236 &android_app->rumble_last_strength_strong[port],
237 &android_app->rumble_last_strength_weak[port],
238 &android_app->rumble_last_strength[port],
239 android_app->id[port],
240 type);
241 }
242
243 return true;
244 }
245
246 input_device_driver_t android_joypad = {
247 android_joypad_init,
248 android_joypad_query_pad,
249 android_joypad_destroy,
250 android_joypad_button,
251 android_joypad_state,
252 NULL,
253 android_joypad_axis,
254 android_joypad_poll,
255 android_joypad_rumble,
256 android_joypad_name,
257 "android",
258 };
259