1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3 * Copyright (C) 2011-2017 - Daniel De Matteis
4 *
5 * RetroArch is free software: you can redistribute it and/or modify it under the terms
6 * of the GNU General Public License as published by the Free Software Found-
7 * ation, either version 3 of the License, or (at your option) any later version.
8 *
9 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with RetroArch.
14 * If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <stdint.h>
18 #include <stdlib.h>
19
20 #ifdef HAVE_CONFIG_H
21 #include "../../config.h"
22 #endif
23
24 #if defined(SN_TARGET_PSP2)
25 #include <sceerror.h>
26 #include <kernel.h>
27 #include <ctrl.h>
28 #elif defined(VITA)
29 #include <psp2/ctrl.h>
30 #include <psp2/kernel/processmgr.h>
31 #include <psp2/hid.h>
32 #include <psp2/motion.h>
33 #define VITA_NUM_SCANCODES 115 /* size of rarch_key_map_vita */
34 #define VITA_MAX_SCANCODE 0xE7
35 #define VITA_NUM_MODIFIERS 11 /* number of modifiers reported */
36 #define MOUSE_MAX_X 960
37 #define MOUSE_MAX_Y 544
38 #elif defined(PSP)
39 #include <pspctrl.h>
40 #endif
41
42 #include <boolean.h>
43 #include <libretro.h>
44 #include <retro_miscellaneous.h>
45
46 #ifdef HAVE_KERNEL_PRX
47 #include "../../bootstrap/psp1/kernel_functions.h"
48 #endif
49
50 #include <defines/psp_defines.h>
51
52 #include "../input_driver.h"
53
54 /* TODO/FIXME -
55 * fix game focus toggle */
56
57 #if defined(SN_TARGET_PSP2) || defined(VITA)
58 #include "../input_keymaps.h"
59
60 uint8_t modifier_lut[VITA_NUM_MODIFIERS][2] =
61 {
62 { 0xE0, 0x01 }, /* LCTRL */
63 { 0xE4, 0x10 }, /* RCTRL */
64 { 0xE1, 0x02 }, /* LSHIFT */
65 { 0xE5, 0x20 }, /* RSHIFT */
66 { 0xE2, 0x04 }, /* LALT */
67 { 0xE6, 0x40 }, /* RALT */
68 { 0xE3, 0x08 }, /* LGUI */
69 { 0xE7, 0x80 }, /* RGUI */
70 { 0x53, 0x01 }, /* NUMLOCK */
71 { 0x39, 0x02 }, /* CAPSLOCK */
72 { 0x47, 0x04 } /* SCROLLOCK */
73 };
74
75 typedef struct psp_input
76 {
77 int keyboard_hid_handle;
78 int mouse_hid_handle;
79 int32_t mouse_x;
80 int32_t mouse_y;
81 int32_t mouse_x_delta;
82 int32_t mouse_y_delta;
83 uint8_t prev_keys[6];
84 bool keyboard_state[VITA_MAX_SCANCODE + 1];
85 bool mouse_button_left;
86 bool mouse_button_right;
87 bool mouse_button_middle;
88 bool sensors_enabled;
89 } psp_input_t;
90
vita_input_poll(void * data)91 static void vita_input_poll(void *data)
92 {
93 psp_input_t *psp = (psp_input_t*)data;
94 unsigned int i = 0;
95 int key_sym = 0;
96 unsigned key_code = 0;
97 uint8_t mod_code = 0;
98 uint16_t mod = 0;
99 uint8_t modifiers[2] = { 0, 0 };
100 bool key_held = false;
101 int mouse_velocity_x = 0;
102 int mouse_velocity_y = 0;
103 SceHidKeyboardReport k_reports[SCE_HID_MAX_REPORT];
104 SceHidMouseReport m_reports[SCE_HID_MAX_REPORT];
105
106 if (psp->keyboard_hid_handle > 0)
107 {
108 int numReports = sceHidKeyboardRead(
109 psp->keyboard_hid_handle,
110 (SceHidKeyboardReport**)&k_reports, SCE_HID_MAX_REPORT);
111
112 if (numReports < 0)
113 psp->keyboard_hid_handle = 0;
114 else if (numReports)
115 {
116 modifiers[0] = k_reports[numReports - 1].modifiers[0];
117 modifiers[1] = k_reports[numReports - 1].modifiers[1];
118 mod = 0;
119 if (modifiers[0] & 0x11)
120 mod |= RETROKMOD_CTRL;
121 if (modifiers[0] & 0x22)
122 mod |= RETROKMOD_SHIFT;
123 if (modifiers[0] & 0x44)
124 mod |= RETROKMOD_ALT;
125 if (modifiers[0] & 0x88)
126 mod |= RETROKMOD_META;
127 if (modifiers[1] & 0x01)
128 mod |= RETROKMOD_NUMLOCK;
129 if (modifiers[1] & 0x02)
130 mod |= RETROKMOD_CAPSLOCK;
131 if (modifiers[1] & 0x04)
132 mod |= RETROKMOD_SCROLLOCK;
133
134 for (i = 0; i < VITA_NUM_MODIFIERS; i++)
135 {
136 key_sym = (int)modifier_lut[i][0];
137 mod_code = modifier_lut[i][1];
138 key_code = input_keymaps_translate_keysym_to_rk(key_sym);
139 if (i < 8)
140 key_held = (modifiers[0] & mod_code);
141 else
142 key_held = (modifiers[1] & mod_code);
143
144 if (key_held && !(psp->keyboard_state[key_sym]))
145 {
146 psp->keyboard_state[key_sym] = true;
147 input_keyboard_event(true, key_code, 0, mod,
148 RETRO_DEVICE_KEYBOARD);
149 }
150 else if (!key_held && (psp->keyboard_state[key_sym]))
151 {
152 psp->keyboard_state[key_sym] = false;
153 input_keyboard_event(false, key_code, 0, mod,
154 RETRO_DEVICE_KEYBOARD);
155 }
156 }
157
158 for (i = 0; i < 6; i++)
159 {
160 key_sym = k_reports[numReports - 1].keycodes[i];
161
162 if (key_sym != psp->prev_keys[i])
163 {
164 if (psp->prev_keys[i])
165 {
166 psp->keyboard_state[psp->prev_keys[i]] = false;
167 key_code =
168 input_keymaps_translate_keysym_to_rk(
169 psp->prev_keys[i]);
170 input_keyboard_event(false, key_code, 0, mod,
171 RETRO_DEVICE_KEYBOARD);
172 }
173 if (key_sym)
174 {
175 psp->keyboard_state[key_sym] = true;
176 key_code =
177 input_keymaps_translate_keysym_to_rk(
178 key_sym);
179 input_keyboard_event(true, key_code, 0, mod,
180 RETRO_DEVICE_KEYBOARD);
181 }
182 psp->prev_keys[i] = key_sym;
183 }
184 }
185 }
186 }
187
188 if (psp->mouse_hid_handle > 0)
189 {
190 int numReports = sceHidMouseRead(psp->mouse_hid_handle,
191 (SceHidMouseReport**)&m_reports, SCE_HID_MAX_REPORT);
192
193 if (numReports > 0)
194 {
195 for (i = 0; i <= numReports - 1; i++)
196 {
197 uint8_t buttons = m_reports[i].buttons;
198
199 if (buttons & 0x1)
200 psp->mouse_button_left = true;
201 else
202 psp->mouse_button_left = false;
203
204 if (buttons & 0x2)
205 psp->mouse_button_right = true;
206 else
207 psp->mouse_button_right = false;
208
209 if (buttons & 0x4)
210 psp->mouse_button_middle = true;
211 else
212 psp->mouse_button_middle = false;
213
214 mouse_velocity_x += m_reports[i].rel_x;
215 mouse_velocity_y += m_reports[i].rel_y;
216 }
217 }
218 }
219
220 psp->mouse_x_delta = mouse_velocity_x;
221 psp->mouse_y_delta = mouse_velocity_y;
222 psp->mouse_x += mouse_velocity_x;
223 psp->mouse_y += mouse_velocity_y;
224 if (psp->mouse_x < 0)
225 psp->mouse_x = 0;
226 else if (psp->mouse_x > MOUSE_MAX_X)
227 psp->mouse_x = MOUSE_MAX_X;
228
229 if (psp->mouse_y < 0)
230 psp->mouse_y = 0;
231 else if (psp->mouse_y > MOUSE_MAX_Y)
232 psp->mouse_y = MOUSE_MAX_Y;
233 }
234
vita_input_state(void * data,const input_device_driver_t * joypad,const input_device_driver_t * sec_joypad,rarch_joypad_info_t * joypad_info,const struct retro_keybind ** binds,bool keyboard_mapping_blocked,unsigned port,unsigned device,unsigned idx,unsigned id)235 static int16_t vita_input_state(
236 void *data,
237 const input_device_driver_t *joypad,
238 const input_device_driver_t *sec_joypad,
239 rarch_joypad_info_t *joypad_info,
240 const struct retro_keybind **binds,
241 bool keyboard_mapping_blocked,
242 unsigned port,
243 unsigned device,
244 unsigned idx,
245 unsigned id)
246 {
247 psp_input_t *psp = (psp_input_t*)data;
248
249 switch (device)
250 {
251 case RETRO_DEVICE_JOYPAD:
252 case RETRO_DEVICE_ANALOG:
253 break;
254 #ifdef VITA
255 case RETRO_DEVICE_KEYBOARD:
256 return ((id < RETROK_LAST) &&
257 psp->keyboard_state[rarch_keysym_lut[(enum retro_key)id]]);
258 case RETRO_DEVICE_MOUSE:
259 case RARCH_DEVICE_MOUSE_SCREEN:
260 {
261 bool screen = device == RARCH_DEVICE_MOUSE_SCREEN;
262 int val = 0;
263 switch (id)
264 {
265 case RETRO_DEVICE_ID_MOUSE_LEFT:
266 return psp->mouse_button_left;
267 case RETRO_DEVICE_ID_MOUSE_RIGHT:
268 return psp->mouse_button_right;
269 case RETRO_DEVICE_ID_MOUSE_MIDDLE:
270 return psp->mouse_button_middle;
271 case RETRO_DEVICE_ID_MOUSE_X:
272 if (screen)
273 return psp->mouse_x;
274
275 val = psp->mouse_x_delta;
276 psp->mouse_x_delta = 0;
277 /* flush delta after it has been read */
278 break;
279 case RETRO_DEVICE_ID_MOUSE_Y:
280 if (screen)
281 return psp->mouse_y;
282 val = psp->mouse_y_delta;
283 psp->mouse_y_delta = 0;
284 /* flush delta after it has been read */
285 break;
286 }
287 return val;
288 }
289 break;
290 #endif
291 }
292
293 return 0;
294 }
295 #else
296 typedef struct psp_input
297 {
298 void *empty;
299 } psp_input_t;
300 #endif
301
psp_input_free_input(void * data)302 static void psp_input_free_input(void *data)
303 {
304 free(data);
305 }
306
307
psp_input_get_capabilities(void * data)308 static uint64_t psp_input_get_capabilities(void *data)
309 {
310 uint64_t caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG);
311
312 #ifdef VITA
313 caps |= (1 << RETRO_DEVICE_KEYBOARD) | (1 << RETRO_DEVICE_MOUSE);
314 #endif
315
316 return caps;
317 }
318
319 #ifdef VITA
psp_input_set_sensor_state(void * data,unsigned port,enum retro_sensor_action action,unsigned event_rate)320 static bool psp_input_set_sensor_state(void *data, unsigned port,
321 enum retro_sensor_action action, unsigned event_rate)
322 {
323 psp_input_t *psp = (psp_input_t*)data;
324
325 if (!psp)
326 return false;
327
328 switch (action)
329 {
330 case RETRO_SENSOR_ILLUMINANCE_DISABLE:
331 return true;
332 case RETRO_SENSOR_ACCELEROMETER_DISABLE:
333 case RETRO_SENSOR_GYROSCOPE_DISABLE:
334 if(psp->sensors_enabled)
335 {
336 psp->sensors_enabled = false;
337 sceMotionMagnetometerOff();
338 sceMotionStopSampling();
339 }
340 return true;
341 case RETRO_SENSOR_ACCELEROMETER_ENABLE:
342 case RETRO_SENSOR_GYROSCOPE_ENABLE:
343 if(!psp->sensors_enabled)
344 {
345 psp->sensors_enabled = true;
346 sceMotionStartSampling();
347 sceMotionMagnetometerOn();
348 }
349 return true;
350 case RETRO_SENSOR_DUMMY:
351 case RETRO_SENSOR_ILLUMINANCE_ENABLE:
352 break;
353 }
354
355 return false;
356 }
357
psp_input_get_sensor_input(void * data,unsigned port,unsigned id)358 static float psp_input_get_sensor_input(void *data,
359 unsigned port, unsigned id)
360 {
361 SceMotionSensorState sixaxis;
362
363 psp_input_t *psp = (psp_input_t*)data;
364
365 if(!psp || !psp->sensors_enabled)
366 return false;
367
368 if(id >= RETRO_SENSOR_ACCELEROMETER_X && id <= RETRO_SENSOR_GYROSCOPE_Z)
369 {
370 sceMotionGetSensorState(&sixaxis, port);
371
372 switch(id)
373 {
374 case RETRO_SENSOR_ACCELEROMETER_X:
375 return sixaxis.accelerometer.x;
376 case RETRO_SENSOR_ACCELEROMETER_Y:
377 return sixaxis.accelerometer.y;
378 case RETRO_SENSOR_ACCELEROMETER_Z:
379 return sixaxis.accelerometer.z;
380 case RETRO_SENSOR_GYROSCOPE_X:
381 return sixaxis.gyro.x;
382 case RETRO_SENSOR_GYROSCOPE_Y:
383 return sixaxis.gyro.y;
384 case RETRO_SENSOR_GYROSCOPE_Z:
385 return sixaxis.gyro.z;
386 }
387
388 }
389
390 return 0.0f;
391 }
392
vita_input_initialize(const char * joypad_driver)393 static void *vita_input_initialize(const char *joypad_driver)
394 {
395 unsigned i;
396 psp_input_t *psp = (psp_input_t*)calloc(1, sizeof(*psp));
397 if (!psp)
398 return NULL;
399
400 sceHidKeyboardEnumerate(&(psp->keyboard_hid_handle), 1);
401 sceHidMouseEnumerate(&(psp->mouse_hid_handle), 1);
402
403 input_keymaps_init_keyboard_lut(rarch_key_map_vita);
404 for (i = 0; i <= VITA_MAX_SCANCODE; i++)
405 psp->keyboard_state[i] = false;
406 for (i = 0; i < 6; i++)
407 psp->prev_keys[i] = 0;
408 psp->mouse_x = 0;
409 psp->mouse_y = 0;
410
411 return psp;
412 }
413 #else
psp_input_initialize(const char * joypad_driver)414 static void* psp_input_initialize(const char *joypad_driver)
415 {
416 psp_input_t *psp = (psp_input_t*)calloc(1, sizeof(*psp));
417 if (!psp)
418 return NULL;
419 return psp;
420 }
421 #endif
422
423 input_driver_t input_psp = {
424 #ifdef VITA
425 vita_input_initialize,
426 vita_input_poll,
427 vita_input_state,
428 #else
429 psp_input_initialize,
430 NULL, /* poll */
431 NULL, /* input_state */
432 #endif
433 psp_input_free_input,
434 #ifdef VITA
435 psp_input_set_sensor_state,
436 psp_input_get_sensor_input,
437 #else
438 NULL,
439 NULL,
440 #endif
441 psp_input_get_capabilities,
442 #ifdef VITA
443 "vita",
444 #else
445 "psp",
446 #endif
447
448 NULL, /* grab_mouse */
449 NULL
450 };
451