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