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