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) 2013-2014 - CatalystG
5  *
6  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
7  *  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 <boolean.h>
19 #include <string/stdstring.h>
20 
21 #include <screen/screen.h>
22 #include <bps/event.h>
23 #include <bps/navigator.h>
24 #include <sys/keycodes.h>
25 
26 #ifdef HAVE_CONFIG_H
27 #include "../../config.h"
28 #endif
29 
30 #include "../../config.def.h"
31 
32 
33 #include "../../retroarch.h"
34 #include "../../tasks/tasks_internal.h"
35 
36 #include "../../command.h"
37 
38 #ifdef HAVE_BB10
39 #define MAX_TOUCH 16
40 #else
41 #define MAX_TOUCH 4
42 #endif
43 
44 typedef struct
45 {
46 #ifdef HAVE_BB10
47    screen_device_t handle;
48 #endif
49    int type;
50    int analogCount;
51    int buttonCount;
52    int device;
53    int port;
54    int index;
55    /* Current state. */
56    int buttons;
57    int analog0[3];
58    int analog1[3];
59    char id[64];
60    char vid[64];
61    char pid[64];
62 } qnx_input_device_t;
63 
64 struct input_pointer
65 {
66    int contact_id;
67    int map;
68    int16_t x, y;
69    int16_t full_x, full_y;
70 };
71 
72 #define QNX_MAX_KEYS (65535 + 7) / 8
73 #define TRACKPAD_CPI 500
74 #define TRACKPAD_THRESHOLD TRACKPAD_CPI / 2
75 
76 typedef struct qnx_input
77 {
78    uint64_t pad_state[DEFAULT_MAX_PADS];
79 
80    /*
81     * The first pointer_count indices of touch_map will be a valid,
82     * active index in pointer array.
83     * Saves us from searching through pointer array when polling state.
84     */
85    struct input_pointer pointer[MAX_TOUCH]; /* int alignment */
86    int touch_map[MAX_TOUCH];
87    int trackpad_acc[2];
88    unsigned pointer_count;
89    unsigned pads_connected;
90 
91    qnx_input_device_t devices[DEFAULT_MAX_PADS];
92 
93    uint8_t keyboard_state[QNX_MAX_KEYS];
94 } qnx_input_t;
95 
96 extern screen_context_t screen_ctx;
97 
qnx_init_controller(qnx_input_t * qnx,qnx_input_device_t * controller)98 static void qnx_init_controller(
99       qnx_input_t *qnx, qnx_input_device_t* controller)
100 {
101    if (!qnx)
102       return;
103 
104    /* Initialize controller values. */
105 #ifdef HAVE_BB10
106    controller->handle      = 0;
107 #endif
108    controller->type        = 0;
109    controller->analogCount = 0;
110    controller->buttonCount = 0;
111    controller->buttons     = 0;
112    controller->analog0[0]  = 0;
113    controller->analog0[1]  = 0;
114    controller->analog0[2]  = 0;
115    controller->analog1[0]  = 0;
116    controller->analog1[1]  = 0;
117    controller->analog1[2]  = 0;
118    controller->port        = -1;
119    controller->device      = -1;
120    controller->index       = -1;
121 
122    memset(controller->id, 0, sizeof(controller->id));
123 }
124 
125 #ifdef HAVE_BB10
126 bool prevMenu;
qnx_process_gamepad_event(qnx_input_t * qnx,screen_event_t screen_event,int type)127 static void qnx_process_gamepad_event(
128       qnx_input_t *qnx,
129       screen_event_t screen_event, int type)
130 {
131    int i;
132    screen_device_t device;
133    qnx_input_device_t* controller = NULL;
134 
135    (void)type;
136 
137    screen_get_event_property_pv(screen_event,
138          SCREEN_PROPERTY_DEVICE, (void**)&device);
139 
140    for (i = 0; i < DEFAULT_MAX_PADS; ++i)
141    {
142       if (device == qnx->devices[i].handle)
143       {
144          controller = (qnx_input_device_t*)&qnx->devices[i];
145          break;
146       }
147    }
148 
149    if (!controller)
150       return;
151 
152    /* Store the controller's new state. */
153    screen_get_event_property_iv(screen_event,
154          SCREEN_PROPERTY_BUTTONS, &controller->buttons);
155 
156    if (controller->analogCount > 0)
157    {
158       screen_get_event_property_iv(screen_event,
159             SCREEN_PROPERTY_ANALOG0, controller->analog0);
160 
161       controller->analog0[0] *= 256;
162       controller->analog0[1] *= 256;
163 
164        if (controller->analogCount == 2)
165        {
166           screen_get_event_property_iv(screen_event,
167                 SCREEN_PROPERTY_ANALOG1, controller->analog1);
168 
169           controller->analog1[0] *= 256;
170           controller->analog1[1] *= 256;
171        }
172    }
173 }
174 
qnx_process_joystick_event(qnx_input_t * qnx,screen_event_t screen_event,int type)175 static void qnx_process_joystick_event(qnx_input_t *qnx, screen_event_t screen_event, int type)
176 {
177     int displacement[2];
178     screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_DISPLACEMENT, displacement);
179 
180     if(displacement != 0)
181     {
182         qnx->trackpad_acc[0] += displacement[0];
183         if(abs(qnx->trackpad_acc[0]) > TRACKPAD_THRESHOLD)
184         {
185             if(qnx->trackpad_acc < 0)
186             {
187                 input_keyboard_event(true, RETROK_LEFT, 0, 0, RETRO_DEVICE_KEYBOARD);
188                 input_keyboard_event(false, RETROK_LEFT, 0, 0, RETRO_DEVICE_KEYBOARD);
189             }
190             else if(qnx->trackpad_acc > 0)
191             {
192                 input_keyboard_event(true, RETROK_RIGHT, 0, 0, RETRO_DEVICE_KEYBOARD);
193                 input_keyboard_event(false, RETROK_RIGHT, 0, 0, RETRO_DEVICE_KEYBOARD);
194             }
195 
196             qnx->trackpad_acc[0] = 0;
197         }
198 
199         qnx->trackpad_acc[1] += displacement[1];
200         if(abs(qnx->trackpad_acc[1]) > TRACKPAD_THRESHOLD)
201         {
202             if(qnx->trackpad_acc < 0)
203             {
204                 input_keyboard_event(true, RETROK_UP, 0, 0, RETRO_DEVICE_KEYBOARD);
205                 input_keyboard_event(false, RETROK_UP, 0, 0, RETRO_DEVICE_KEYBOARD);
206             }
207             else if(qnx->trackpad_acc > 0)
208             {
209                 input_keyboard_event(true, RETROK_DOWN, 0, 0, RETRO_DEVICE_KEYBOARD);
210                 input_keyboard_event(false, RETROK_DOWN, 0, 0, RETRO_DEVICE_KEYBOARD);
211             }
212 
213             qnx->trackpad_acc[1] = 0;
214         }
215     }
216 
217     int buttons = 0;
218     screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons);
219     input_keyboard_event(buttons != 0, RETROK_RETURN, 0, 0, RETRO_DEVICE_KEYBOARD);
220 }
221 
qnx_input_autodetect_gamepad(qnx_input_t * qnx,qnx_input_device_t * controller)222 static void qnx_input_autodetect_gamepad(qnx_input_t *qnx,
223       qnx_input_device_t* controller)
224 {
225    char name_buf[256];
226 
227    if (!qnx)
228       return;
229 
230    name_buf[0] = '\0';
231    if(controller && controller->type == SCREEN_EVENT_GAMEPAD)
232    {
233        if(strstr(controller->id, "0-054C-05C4-1.0"))
234            strlcpy(name_buf, "DS4 Controller", sizeof(name_buf));
235        else
236            strlcpy(name_buf, "QNX Gamepad", sizeof(name_buf));
237    }
238 
239    if (!string_is_empty(name_buf))
240    {
241       controller->port = qnx->pads_connected;
242 
243       input_autoconfigure_connect(
244             name_buf,
245             NULL,
246             "qnx",
247             controller->port,
248             *controller->vid,
249             *controller->pid);
250 
251       qnx->pads_connected++;
252    }
253 }
254 
qnx_handle_device(qnx_input_t * qnx,qnx_input_device_t * controller)255 static void qnx_handle_device(qnx_input_t *qnx,
256       qnx_input_device_t* controller)
257 {
258    if (!qnx)
259       return;
260 
261    /* Query libscreen for information about this device. */
262    screen_get_device_property_iv(controller->handle,
263          SCREEN_PROPERTY_TYPE, &controller->type);
264    screen_get_device_property_cv(controller->handle,
265          SCREEN_PROPERTY_ID_STRING, sizeof(controller->id), controller->id);
266    screen_get_device_property_cv(controller->handle,
267          SCREEN_PROPERTY_VENDOR, sizeof(controller->vid), controller->vid);
268    screen_get_device_property_cv(controller->handle,
269          SCREEN_PROPERTY_PRODUCT, sizeof(controller->pid), controller->pid);
270 
271    if (controller->type == SCREEN_EVENT_GAMEPAD)
272    {
273       screen_get_device_property_iv(controller->handle,
274             SCREEN_PROPERTY_BUTTON_COUNT, &controller->buttonCount);
275 
276       /* Check for the existence of analog sticks. */
277       if (!screen_get_device_property_iv(controller->handle,
278                SCREEN_PROPERTY_ANALOG0, controller->analog0))
279          ++controller->analogCount;
280 
281       if (!screen_get_device_property_iv(controller->handle,
282                SCREEN_PROPERTY_ANALOG1, controller->analog1))
283          ++controller->analogCount;
284    }
285 
286    /* Screen service will map supported controllers,
287     * we still might need to adjust. */
288    qnx_input_autodetect_gamepad(qnx, controller);
289 
290 #ifdef DEBUG
291    if (controller->type == SCREEN_EVENT_GAMEPAD)
292       RARCH_LOG("Gamepad Device Connected:\n");
293    else if (controller->type == SCREEN_EVENT_JOYSTICK)
294       RARCH_LOG("Joystick Device Connected:\n");
295    else if (controller->type == SCREEN_EVENT_KEYBOARD)
296       RARCH_LOG("Keyboard Device Connected:\n");
297 
298    RARCH_LOG("\tID: %s\n", controller->id);
299    RARCH_LOG("\tVendor  ID: %s\n", controller->vid);
300    RARCH_LOG("\tProduct ID: %s\n", controller->pid);
301    RARCH_LOG("\tButton Count: %d\n", controller->buttonCount);
302    RARCH_LOG("\tAnalog Count: %d\n", controller->analogCount);
303 #endif
304 }
305 
306 /* Find currently connected gamepads. */
qnx_discover_controllers(qnx_input_t * qnx)307 static int qnx_discover_controllers(qnx_input_t *qnx)
308 {
309    /* Get an array of all available devices. */
310    int deviceCount = 0;
311    int ret;
312    unsigned i;
313 
314    ret = screen_get_context_property_iv(screen_ctx,
315          SCREEN_PROPERTY_DEVICE_COUNT, &deviceCount);
316    if (ret < 0)
317    {
318      RARCH_ERR("Error querying SCREEN_PROPERTY_DEVICE_COUNT: [%d] %s\n",
319 	       errno, strerror(errno));
320      return false;
321    }
322    screen_device_t* devices_found = (screen_device_t*)
323       calloc(deviceCount, sizeof(screen_device_t));
324    if (!devices_found)
325    {
326      RARCH_ERR("Error allocating devices_found, deviceCount=%d\n",
327 	       deviceCount);
328      return false;
329    }
330 
331    ret = screen_get_context_property_pv(screen_ctx,
332          SCREEN_PROPERTY_DEVICES, (void**)devices_found);
333    if (ret < 0)
334    {
335      RARCH_ERR("Error querying SCREEN_PROPERTY_DEVICES: [%d] %s\n",
336 	       errno, strerror(errno));
337      return false;
338    }
339 
340    /* Scan the list for gamepad and joystick devices. */
341    for (i = 0; i < qnx->pads_connected; ++i)
342       qnx_init_controller(qnx, &qnx->devices[i]);
343 
344    qnx->pads_connected = 0;
345 
346    for (i = 0; i < deviceCount; i++)
347    {
348       int type;
349       screen_get_device_property_iv(
350             devices_found[i], SCREEN_PROPERTY_TYPE, &type);
351 
352       if (type == SCREEN_EVENT_GAMEPAD  ||
353           type == SCREEN_EVENT_JOYSTICK ||
354           type == SCREEN_EVENT_KEYBOARD)
355       {
356          qnx->devices[qnx->pads_connected].handle = devices_found[i];
357          qnx->devices[qnx->pads_connected].index = qnx->pads_connected;
358          qnx_handle_device(qnx, &qnx->devices[qnx->pads_connected]);
359 
360          if (qnx->pads_connected == DEFAULT_MAX_PADS)
361             break;
362       }
363    }
364 
365    free(devices_found);
366 
367    return true;
368 }
369 #endif
370 
qnx_process_keyboard_event(qnx_input_t * qnx,screen_event_t event,int type)371 static void qnx_process_keyboard_event(
372       qnx_input_t *qnx,
373       screen_event_t event, int type)
374 {
375     // Get key properties from screen event
376     int flags = 0;
377     screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_FLAGS, &flags);
378 
379     int cap = 0;
380     screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap);
381 
382     int mod = 0;
383     screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_MODIFIERS, &mod);
384 
385     // Calculate state
386     unsigned keycode = input_keymaps_translate_keysym_to_rk(cap);
387     bool keydown = flags & KEY_DOWN;
388     bool keyrepeat = flags & KEY_REPEAT;
389 
390     // Fire keyboard event
391     if(!keyrepeat)
392     {
393         input_keyboard_event(keydown, keycode, 0, mod, RETRO_DEVICE_KEYBOARD);
394     }
395 
396     // Apply keyboard state
397     if(keydown && !keyrepeat)
398     {
399        BIT_SET(qnx->keyboard_state, cap);
400     }
401     else if(!keydown && !keyrepeat)
402     {
403        BIT_CLEAR(qnx->keyboard_state, cap);
404     }
405 }
406 
qnx_process_touch_event(qnx_input_t * qnx,screen_event_t event,int type)407 static void qnx_process_touch_event(
408       qnx_input_t *qnx, screen_event_t event, int type)
409 {
410    int contact_id, pos[2];
411    unsigned i, j;
412 
413    screen_get_event_property_iv(event,
414          SCREEN_PROPERTY_TOUCH_ID, (int*)&contact_id);
415    screen_get_event_property_iv(event,
416          SCREEN_PROPERTY_SOURCE_POSITION, pos);
417 
418    switch(type)
419    {
420       case SCREEN_EVENT_MTOUCH_TOUCH:
421          /* Find a free touch struct. */
422          for (i = 0; i < MAX_TOUCH; ++i)
423          {
424             if(qnx->pointer[i].contact_id == -1)
425             {
426                struct video_viewport vp;
427 
428                vp.x                        = 0;
429                vp.y                        = 0;
430                vp.width                    = 0;
431                vp.height                   = 0;
432                vp.full_width               = 0;
433                vp.full_height              = 0;
434 
435                qnx->pointer[i].contact_id  = contact_id;
436 
437                video_driver_translate_coord_viewport_wrap(
438                      &vp,
439                      pos[0], pos[1],
440                      &qnx->pointer[i].x, &qnx->pointer[i].y,
441                      &qnx->pointer[i].full_x, &qnx->pointer[i].full_y);
442 
443                /* Add this pointer to the map to signal it's valid. */
444                qnx->pointer[i].map = qnx->pointer_count;
445                qnx->touch_map[qnx->pointer_count] = i;
446                qnx->pointer_count++;
447                break;
448             }
449          }
450 #if 0
451          RARCH_LOG("New Touch: x:%d, y:%d, id:%d\n", pos[0], pos[1], contact_id);
452          RARCH_LOG("Map: %d %d %d %d %d %d\n", qnx->touch_map[0], qnx->touch_map[1],
453                qnx->touch_map[2], qnx->touch_map[3], qnx->touch_map[4],
454                qnx->touch_map[5]);
455 #endif
456          break;
457 
458       case SCREEN_EVENT_MTOUCH_RELEASE:
459          for (i = 0; i < MAX_TOUCH; ++i)
460          {
461             if(qnx->pointer[i].contact_id == contact_id)
462             {
463                /* Invalidate the finger. */
464                qnx->pointer[i].contact_id = -1;
465 
466                /* Remove pointer from map and shift
467                 * remaining valid ones to the front. */
468                qnx->touch_map[qnx->pointer[i].map] = -1;
469                for (j = qnx->pointer[i].map; j < qnx->pointer_count; ++j)
470                {
471                   qnx->touch_map[j] = qnx->touch_map[j+1];
472                   qnx->pointer[qnx->touch_map[j+1]].map = j;
473                   qnx->touch_map[j+1] = -1;
474                }
475                qnx->pointer_count--;
476                break;
477             }
478          }
479 #if 0
480          RARCH_LOG("Release: x:%d, y:%d, id:%d\n", pos[0], pos[1], contact_id);
481          RARCH_LOG("Map: %d %d %d %d %d %d\n", qnx->touch_map[0], qnx->touch_map[1],
482                qnx->touch_map[2], qnx->touch_map[3], qnx->touch_map[4],
483                qnx->touch_map[5]);
484 #endif
485          break;
486 
487       case SCREEN_EVENT_MTOUCH_MOVE:
488          /* Find the finger we're tracking and update. */
489          for (i = 0; i < qnx->pointer_count; ++i)
490          {
491             if(qnx->pointer[i].contact_id == contact_id)
492             {
493                struct video_viewport vp;
494 
495                vp.x                        = 0;
496                vp.y                        = 0;
497                vp.width                    = 0;
498                vp.height                   = 0;
499                vp.full_width               = 0;
500                vp.full_height              = 0;
501 
502 #if 0
503                gl_t *gl = (gl_t*)video_driver_get_ptr();
504 
505                /*During a move, we can go ~30 pixel into the
506                 * bezel which gives negative numbers or
507                 * numbers larger than the screen resolution.
508                 *
509                 * Normalize. */
510                if(pos[0] < 0)
511                   pos[0] = 0;
512                if(pos[0] > gl->full_x)
513                   pos[0] = gl->full_x;
514 
515                if(pos[1] < 0)
516                   pos[1] = 0;
517                if(pos[1] > gl->full_y)
518                   pos[1] = gl->full_y;
519 #endif
520 
521                video_driver_translate_coord_viewport_wrap(&vp,
522                      pos[0], pos[1],
523                      &qnx->pointer[i].x, &qnx->pointer[i].y,
524                      &qnx->pointer[i].full_x, &qnx->pointer[i].full_y);
525 #if 0
526                RARCH_LOG("Move: x:%d, y:%d, id:%d\n", pos[0], pos[1],
527                      contact_id);
528 #endif
529                break;
530             }
531          }
532          break;
533    }
534 }
535 
qnx_handle_screen_event(qnx_input_t * qnx,bps_event_t * event)536 static void qnx_handle_screen_event(qnx_input_t *qnx, bps_event_t *event)
537 {
538    int type;
539    screen_event_t screen_event = screen_event_get_event(event);
540 
541    screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &type);
542 
543    switch(type)
544    {
545       case SCREEN_EVENT_MTOUCH_TOUCH:
546       case SCREEN_EVENT_MTOUCH_RELEASE:
547       case SCREEN_EVENT_MTOUCH_MOVE:
548          qnx_process_touch_event(qnx, screen_event, type);
549          break;
550       case SCREEN_EVENT_KEYBOARD:
551          qnx_process_keyboard_event(qnx, screen_event, type);
552          break;
553 #ifdef HAVE_BB10
554       case SCREEN_EVENT_GAMEPAD:
555          qnx_process_gamepad_event(qnx, screen_event, type);
556           break;
557       case SCREEN_EVENT_JOYSTICK:
558          qnx_process_joystick_event(qnx, screen_event, type);
559          break;
560       case SCREEN_EVENT_DEVICE:
561          {
562             /* A device was attached or removed. */
563             screen_device_t device;
564             int attached, type, i;
565 
566             screen_get_event_property_pv(screen_event,
567                   SCREEN_PROPERTY_DEVICE, (void**)&device);
568             screen_get_event_property_iv(screen_event,
569                   SCREEN_PROPERTY_ATTACHED, &attached);
570 
571             if (attached)
572                screen_get_device_property_iv(device,
573                      SCREEN_PROPERTY_TYPE, &type);
574 
575             if (attached &&
576                   (
577                    type == SCREEN_EVENT_GAMEPAD ||
578                    type == SCREEN_EVENT_JOYSTICK ||
579                    type == SCREEN_EVENT_KEYBOARD)
580                )
581             {
582                for (i = 0; i < DEFAULT_MAX_PADS; ++i)
583                {
584                   if (!qnx->devices[i].handle)
585                   {
586                      qnx->devices[i].handle = device;
587                      qnx_handle_device(qnx, &qnx->devices[i]);
588                      break;
589                   }
590                }
591             }
592             else
593             {
594                for (i = 0; i < DEFAULT_MAX_PADS; ++i)
595                {
596                   if (device == qnx->devices[i].handle)
597                   {
598                      RARCH_LOG("Device %s: Disconnected.\n",
599                            qnx->devices[i].id);
600                      qnx_init_controller(qnx, &qnx->devices[i]);
601                      break;
602                   }
603                }
604             }
605          }
606          break;
607 #endif
608       default:
609          break;
610    }
611 }
612 
qnx_handle_navigator_event(qnx_input_t * qnx,bps_event_t * event)613 static void qnx_handle_navigator_event(
614       qnx_input_t *qnx, bps_event_t *event)
615 {
616    bps_event_t *event_pause = NULL;
617 
618    switch (bps_event_get_code(event))
619    {
620       case NAVIGATOR_SYSKEY_PRESS:
621          switch(navigator_event_get_syskey_key(event))
622          {
623             case NAVIGATOR_SYSKEY_BACK:
624                input_keyboard_event(true, RETROK_BACKSPACE, 0, 0, RETRO_DEVICE_KEYBOARD);
625                input_keyboard_event(false, RETROK_BACKSPACE, 0, 0, RETRO_DEVICE_KEYBOARD);
626                break;
627             case NAVIGATOR_SYSKEY_SEND:
628             case NAVIGATOR_SYSKEY_END:
629                break;
630             default:
631                break;
632          }
633          break;
634       case NAVIGATOR_SWIPE_DOWN:
635          command_event(CMD_EVENT_MENU_TOGGLE, NULL);
636          break;
637       case NAVIGATOR_WINDOW_STATE:
638          switch(navigator_event_get_window_state(event))
639          {
640             case NAVIGATOR_WINDOW_THUMBNAIL:
641             case NAVIGATOR_WINDOW_INVISIBLE:
642                for (;;)
643                {
644                   unsigned event_code;
645 
646                   /* Block until we get a resume or exit event. */
647                   bps_get_event(&event_pause, -1);
648                   event_code = bps_event_get_code(event_pause);
649 
650                   if(event_code == NAVIGATOR_WINDOW_STATE)
651                   {
652                      if(navigator_event_get_window_state(event_pause) == NAVIGATOR_WINDOW_FULLSCREEN)
653                         break;
654                   }
655                   else if(event_code == NAVIGATOR_EXIT)
656                      goto shutdown;
657                }
658                break;
659             case NAVIGATOR_WINDOW_FULLSCREEN:
660                break;
661          }
662          break;
663      case NAVIGATOR_EXIT:
664         goto shutdown;
665       default:
666          break;
667    }
668 
669    return;
670 
671    shutdown:
672        rarch_ctl(RARCH_CTL_SET_SHUTDOWN, NULL);
673        return;
674 }
675 
qnx_input_init(const char * joypad_driver)676 static void *qnx_input_init(const char *joypad_driver)
677 {
678    int i;
679    qnx_input_t *qnx     = (qnx_input_t*)calloc(1, sizeof(*qnx));
680 
681    if (!qnx)
682       return NULL;
683 
684    input_keymaps_init_keyboard_lut(rarch_key_map_qnx);
685 
686    for (i = 0; i < MAX_TOUCH; ++i)
687    {
688       qnx->pointer[i].contact_id = -1;
689       qnx->touch_map[i] = -1;
690    }
691 
692    for (i = 0; i < DEFAULT_MAX_PADS; ++i)
693       qnx_init_controller(qnx, &qnx->devices[i]);
694 
695 #ifdef HAVE_BB10
696    qnx_discover_controllers(qnx);
697 #else
698    /* Initialize Playbook keyboard. */
699    strlcpy(qnx->devices[0].id, "0A5C-8502",
700          sizeof(qnx->devices[0].id));
701    qnx_input_autodetect_gamepad(qnx, &qnx->devices[0]);
702    qnx->pads_connected = 1;
703 #endif
704 
705    return qnx;
706 }
707 
qnx_input_poll(void * data)708 static void qnx_input_poll(void *data)
709 {
710    qnx_input_t *qnx = (qnx_input_t*)data;
711 
712    /* Request and process all available BPS events. */
713    for (;;)
714    {
715       bps_event_t *event = NULL;
716       int rc             = bps_get_event(&event, 0);
717 
718       if(rc == BPS_SUCCESS)
719       {
720          int domain;
721 
722          if (!event)
723             break;
724 
725          domain = bps_event_get_domain(event);
726          if (domain == navigator_get_domain())
727             qnx_handle_navigator_event(qnx, event);
728          else if (domain == screen_get_domain())
729             qnx_handle_screen_event(qnx, event);
730       }
731    }
732 }
733 
qnx_keyboard_pressed(qnx_input_t * qnx,unsigned id)734 static bool qnx_keyboard_pressed(qnx_input_t *qnx, unsigned id)
735 {
736     unsigned bit = rarch_keysym_lut[(enum retro_key)id];
737     return id < RETROK_LAST && BIT_GET(qnx->keyboard_state, bit);
738 }
739 
qnx_pointer_input_state(qnx_input_t * qnx,unsigned idx,unsigned id,bool screen)740 static int16_t qnx_pointer_input_state(qnx_input_t *qnx,
741       unsigned idx, unsigned id, bool screen)
742 {
743    int16_t x;
744    int16_t y;
745 
746    if(screen)
747    {
748        x = qnx->pointer[idx].full_x;
749        y = qnx->pointer[idx].full_y;
750    }
751    else
752    {
753        x = qnx->pointer[idx].x;
754        y = qnx->pointer[idx].y;
755    }
756 
757    switch (id)
758    {
759       case RETRO_DEVICE_ID_POINTER_X:
760          return x;
761       case RETRO_DEVICE_ID_POINTER_Y:
762          return y;
763       case RETRO_DEVICE_ID_POINTER_PRESSED:
764          return (idx < qnx->pointer_count)
765                  && (x != -0x8000)
766                  && (y != -0x8000);
767    }
768 
769    return 0;
770 }
771 
qnx_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)772 static int16_t qnx_input_state(
773       void *data,
774       const input_device_driver_t *joypad,
775       const input_device_driver_t *sec_joypad,
776       rarch_joypad_info_t *joypad_info,
777       const struct retro_keybind **binds,
778       bool keyboard_mapping_blocked,
779       unsigned port,
780       unsigned device,
781       unsigned idx,
782       unsigned id)
783 {
784    qnx_input_t *qnx           = (qnx_input_t*)data;
785 
786    switch (device)
787    {
788       case RETRO_DEVICE_JOYPAD:
789          if (id == RETRO_DEVICE_ID_JOYPAD_MASK)
790          {
791             unsigned i;
792             int16_t ret = 0;
793 
794             if (!keyboard_mapping_blocked)
795             {
796                for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
797                {
798                   if (binds[port][i].valid)
799                   {
800                      if (qnx_keyboard_pressed(qnx, key))
801                         ret |= (1 << i);
802                   }
803                }
804             }
805 
806             return ret;
807          }
808 
809          if (id < RARCH_BIND_LIST_END)
810          {
811             if (binds[port][id].valid)
812             {
813                if (
814                      ((id == RARCH_GAME_FOCUS_TOGGLE) ||
815                       !keyboard_mapping_blocked) &&
816                      qnx_keyboard_pressed(qnx, key)
817                   )
818                   return 1;
819             }
820          }
821          break;
822       case RETRO_DEVICE_ANALOG:
823          break;
824       case RETRO_DEVICE_KEYBOARD:
825          return qnx_keyboard_pressed(qnx, id);
826       case RETRO_DEVICE_POINTER:
827       case RARCH_DEVICE_POINTER_SCREEN:
828          return qnx_pointer_input_state(qnx, idx, id, device == RARCH_DEVICE_POINTER_SCREEN);
829       default:
830          break;
831    }
832 
833    return 0;
834 }
835 
qnx_input_free_input(void * data)836 static void qnx_input_free_input(void *data)
837 {
838    if (data)
839       free(data);
840 }
841 
qnx_input_get_capabilities(void * data)842 static uint64_t qnx_input_get_capabilities(void *data)
843 {
844     (void)data;
845 
846     return
847         (1 << RETRO_DEVICE_JOYPAD)   |
848         (1 << RETRO_DEVICE_POINTER)  |
849 #ifdef HAVE_BB10
850         (1 << RETRO_DEVICE_ANALOG)   |
851 #endif
852         (1 << RETRO_DEVICE_KEYBOARD);
853 }
854 
855 input_driver_t input_qnx = {
856    qnx_input_init,
857    qnx_input_poll,
858    qnx_input_state,
859    qnx_input_free_input,
860    NULL,
861    NULL,
862    qnx_input_get_capabilities,
863    "qnx_input",
864    NULL,
865    NULL
866 };
867