comparison src/video/qnxgf/SDL_gf_input.c @ 3109:7b3a09fb9c8b

Support for HID devices (mice and keyboards only for now) has been added
author Mike Gorchak <lestat@i.com.ua>
date Tue, 28 Apr 2009 04:33:30 +0000
parents
children d7174e9f65ce
comparison
equal deleted inserted replaced
3108:aa1897bee1e9 3109:7b3a09fb9c8b
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21
22 QNX Graphics Framework SDL driver
23 Copyright (C) 2009 Mike Gorchak
24 (mike@malva.ua, lestat@i.com.ua)
25 */
26
27 #include "SDL_gf_input.h"
28
29 #include "SDL_config.h"
30 #include "SDL_events.h"
31 #include "../../events/SDL_mouse_c.h"
32 #include "../../events/SDL_keyboard_c.h"
33
34 /* Include QNX HIDDI definitions */
35 #include "SDL_hiddi_keyboard.h"
36 #include "SDL_hiddi_mouse.h"
37 #include "SDL_hiddi_joystick.h"
38
39 /* Mouse related functions */
40 SDL_Cursor* gf_createcursor(SDL_Surface* surface, int hot_x, int hot_y);
41 int gf_showcursor(SDL_Cursor* cursor);
42 void gf_movecursor(SDL_Cursor* cursor);
43 void gf_freecursor(SDL_Cursor* cursor);
44 void gf_warpmouse(SDL_Mouse* mouse, SDL_WindowID windowID, int x, int y);
45 void gf_freemouse(SDL_Mouse* mouse);
46
47 /* HIDDI interacting functions */
48 static int32_t hiddi_connect_devices();
49 static int32_t hiddi_disconnect_devices();
50
51 int32_t gf_addinputdevices(_THIS)
52 {
53 SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata;
54 SDL_DisplayData* didata;
55 struct SDL_Mouse gf_mouse;
56 SDL_Keyboard gf_keyboard;
57 SDLKey keymap[SDL_NUM_SCANCODES];
58 SDL_MouseData* mdata;
59 uint32_t it;
60
61 for (it=0; it<_this->num_displays; it++)
62 {
63 /* Clear SDL mouse structure */
64 SDL_memset(&gf_mouse, 0x00, sizeof(struct SDL_Mouse));
65
66 /* Allocate SDL_MouseData structure */
67 mdata=(SDL_MouseData*)SDL_calloc(1, sizeof(SDL_MouseData));
68 if (mdata==NULL)
69 {
70 SDL_OutOfMemory();
71 return -1;
72 }
73
74 /* Mark this mouse with ID 0 */
75 gf_mouse.id=it;
76 gf_mouse.driverdata=(void*)mdata;
77 gf_mouse.CreateCursor=gf_createcursor;
78 gf_mouse.ShowCursor=gf_showcursor;
79 gf_mouse.MoveCursor=gf_movecursor;
80 gf_mouse.FreeCursor=gf_freecursor;
81 gf_mouse.WarpMouse=gf_warpmouse;
82 gf_mouse.FreeMouse=gf_freemouse;
83
84 /* Get display data */
85 didata=(SDL_DisplayData*)_this->displays[it].driverdata;
86
87 /* Store SDL_DisplayData pointer in the mouse driver internals */
88 mdata->didata=didata;
89
90 /* Set cursor pos to 0,0 to avoid cursor disappearing in some drivers */
91 gf_cursor_set_pos(didata->display, 0, 0, 0);
92
93 /* Register mouse cursor in SDL */
94 SDL_AddMouse(&gf_mouse, "GF mouse cursor", 0, 0, 1);
95 }
96
97 /* Keyboard could be one only */
98 SDL_zero(gf_keyboard);
99 SDL_AddKeyboard(&gf_keyboard, -1);
100
101 /* Add scancode to key mapping, HIDDI uses USB HID codes, so */
102 /* map will be exact one-to-one */
103 SDL_GetDefaultKeymap(keymap);
104 SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES);
105
106 /* Connect to HID server and enumerate all input devices */
107 hiddi_connect_devices();
108
109 return 0;
110 }
111
112 int32_t gf_delinputdevices(_THIS)
113 {
114 /* Disconnect from HID server and release input devices */
115 hiddi_disconnect_devices();
116
117 /* Delete keyboard */
118 SDL_KeyboardQuit();
119
120 /* Destroy all of the mice */
121 SDL_MouseQuit();
122 }
123
124 /*****************************************************************************/
125 /* GF Mouse related functions */
126 /*****************************************************************************/
127 SDL_Cursor* gf_createcursor(SDL_Surface* surface, int hot_x, int hot_y)
128 {
129 gf_cursor_t* internal_cursor;
130 SDL_Cursor* sdl_cursor;
131 uint8_t* image0=NULL;
132 uint8_t* image1=NULL;
133 uint32_t it;
134 uint32_t jt;
135 uint32_t shape_color;
136
137 /* SDL converts monochrome cursor shape to 32bpp cursor shape */
138 /* and we must convert it back to monochrome, this routine handles */
139 /* 24/32bpp surfaces only */
140 if ((surface->format->BitsPerPixel!=32) && (surface->format->BitsPerPixel!=24))
141 {
142 SDL_SetError("GF: Cursor shape is not 24/32bpp.");
143 return NULL;
144 }
145
146 /* Since GF is not checking data, we must check */
147 if ((surface->w==0) || (surface->h==0))
148 {
149 SDL_SetError("GF: Cursor shape dimensions are zero");
150 return NULL;
151 }
152
153 /* Allocate memory for the internal cursor format */
154 internal_cursor=(gf_cursor_t*)SDL_calloc(1, sizeof(gf_cursor_t));
155 if (internal_cursor==NULL)
156 {
157 SDL_OutOfMemory();
158 return NULL;
159 }
160
161 /* Allocate memory for the SDL cursor */
162 sdl_cursor=(SDL_Cursor*)SDL_calloc(1, sizeof(SDL_Cursor));
163 if (sdl_cursor==NULL)
164 {
165 SDL_free(internal_cursor);
166 SDL_OutOfMemory();
167 return NULL;
168 }
169
170 /* Allocate two monochrome images */
171 image0=(uint8_t*)SDL_calloc(1, ((surface->w+7)/8)*surface->h);
172 if (image0==NULL)
173 {
174 SDL_free(sdl_cursor);
175 SDL_free(internal_cursor);
176 SDL_OutOfMemory();
177 return NULL;
178 }
179 image1=(uint8_t*)SDL_calloc(1, ((surface->w+7)>>3)*surface->h);
180 if (image1==NULL)
181 {
182 SDL_free(image0);
183 SDL_free(sdl_cursor);
184 SDL_free(internal_cursor);
185 SDL_OutOfMemory();
186 return NULL;
187 }
188
189 /* Set driverdata as GF cursor format */
190 sdl_cursor->driverdata=(void*)internal_cursor;
191 internal_cursor->type=GF_CURSOR_BITMAP;
192 internal_cursor->hotspot.x=hot_x;
193 internal_cursor->hotspot.y=hot_y;
194 internal_cursor->cursor.bitmap.w=surface->w;
195 internal_cursor->cursor.bitmap.h=surface->h;
196 internal_cursor->cursor.bitmap.color0=SDL_GF_MOUSE_COLOR_BLACK;
197 internal_cursor->cursor.bitmap.color1=SDL_GF_MOUSE_COLOR_WHITE;
198
199 /* Setup cursor shape images */
200 internal_cursor->cursor.bitmap.stride=((surface->w+7)>>3);
201 internal_cursor->cursor.bitmap.image0=image0;
202 internal_cursor->cursor.bitmap.image1=image1;
203
204 /* Convert cursor from 32 bpp */
205 for (jt=0; jt<surface->h; jt++)
206 {
207 for (it=0; it<surface->w; it++)
208 {
209 shape_color=*((uint32_t*)((uint8_t*)surface->pixels+jt*surface->pitch+it*surface->format->BytesPerPixel));
210 switch(shape_color)
211 {
212 case SDL_GF_MOUSE_COLOR_BLACK:
213 {
214 *(image0+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))|=0x80>>(it%8);
215 *(image1+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8));
216 }
217 break;
218 case SDL_GF_MOUSE_COLOR_WHITE:
219 {
220 *(image0+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8));
221 *(image1+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))|=0x80>>(it%8);
222 }
223 break;
224 case SDL_GF_MOUSE_COLOR_TRANS:
225 {
226 *(image0+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8));
227 *(image1+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8));
228 }
229 break;
230 default:
231 {
232 /* The same as transparent color, must not happen */
233 *(image0+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8));
234 *(image1+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8));
235 }
236 break;
237 }
238 }
239 }
240
241 return sdl_cursor;
242 }
243
244 int gf_showcursor(SDL_Cursor* cursor)
245 {
246 SDL_VideoDisplay* display;
247 SDL_DisplayData* didata;
248 SDL_Window* window;
249 SDL_WindowID window_id;
250 gf_cursor_t* internal_cursor;
251 int32_t status;
252
253 /* Get current window id */
254 window_id=SDL_GetFocusWindow();
255 if (window_id<=0)
256 {
257 SDL_MouseData* mdata=NULL;
258
259 /* If there is no current window, then someone calls this function */
260 /* to set global mouse settings during SDL initialization */
261 if (cursor!=NULL)
262 {
263 mdata=(SDL_MouseData*)cursor->mouse->driverdata;
264 didata=(SDL_DisplayData*)mdata->didata;
265 }
266 else
267 {
268 /* We can't get SDL_DisplayData at this point, return fake success */
269 return 0;
270 }
271 }
272 else
273 {
274 /* Sanity checks */
275 window=SDL_GetWindowFromID(window_id);
276 if (window!=NULL)
277 {
278 display=SDL_GetDisplayFromWindow(window);
279 if (display!=NULL)
280 {
281 didata=(SDL_DisplayData*)display->driverdata;
282 if (didata==NULL)
283 {
284 return -1;
285 }
286 }
287 else
288 {
289 return -1;
290 }
291 }
292 else
293 {
294 return -1;
295 }
296 }
297
298 /* Check if we need to set new shape or disable cursor shape */
299 if (cursor!=NULL)
300 {
301 /* Retrieve GF cursor shape */
302 internal_cursor=(gf_cursor_t*)cursor->driverdata;
303 if (internal_cursor==NULL)
304 {
305 SDL_SetError("GF: Internal cursor data is absent");
306 return -1;
307 }
308 if ((internal_cursor->cursor.bitmap.image0==NULL) ||
309 (internal_cursor->cursor.bitmap.image1==NULL))
310 {
311 SDL_SetError("GF: Cursor shape is absent");
312 return -1;
313 }
314
315 /* Store last shown cursor to display data */
316 didata->cursor.type=internal_cursor->type;
317 didata->cursor.hotspot.x=internal_cursor->hotspot.x;
318 didata->cursor.hotspot.y=internal_cursor->hotspot.y;
319 if (internal_cursor->cursor.bitmap.w>SDL_VIDEO_GF_MAX_CURSOR_SIZE)
320 {
321 didata->cursor.cursor.bitmap.w=SDL_VIDEO_GF_MAX_CURSOR_SIZE;
322 }
323 else
324 {
325 didata->cursor.cursor.bitmap.w=internal_cursor->cursor.bitmap.w;
326 }
327
328 if (didata->cursor.cursor.bitmap.h>SDL_VIDEO_GF_MAX_CURSOR_SIZE)
329 {
330 didata->cursor.cursor.bitmap.h=SDL_VIDEO_GF_MAX_CURSOR_SIZE;
331 }
332 else
333 {
334 didata->cursor.cursor.bitmap.h=internal_cursor->cursor.bitmap.h;
335 }
336
337 didata->cursor.cursor.bitmap.color0=internal_cursor->cursor.bitmap.color0;
338 didata->cursor.cursor.bitmap.color1=internal_cursor->cursor.bitmap.color1;
339 didata->cursor.cursor.bitmap.stride=internal_cursor->cursor.bitmap.stride;
340 SDL_memcpy(didata->cursor.cursor.bitmap.image0,
341 internal_cursor->cursor.bitmap.image0,
342 ((internal_cursor->cursor.bitmap.w+7)/(sizeof(uint8_t)*8))*internal_cursor->cursor.bitmap.h);
343 SDL_memcpy(didata->cursor.cursor.bitmap.image1,
344 internal_cursor->cursor.bitmap.image1,
345 ((internal_cursor->cursor.bitmap.w+7)/(sizeof(uint8_t)*8))*internal_cursor->cursor.bitmap.h);
346
347 /* Setup cursor shape */
348 status=gf_cursor_set(didata->display, 0, internal_cursor);
349 if (status!=GF_ERR_OK)
350 {
351 if (status!=GF_ERR_NOSUPPORT)
352 {
353 SDL_SetError("GF: Can't set hardware cursor shape");
354 return -1;
355 }
356 }
357
358 /* Enable just set cursor */
359 status=gf_cursor_enable(didata->display, 0);
360 if (status!=GF_ERR_OK)
361 {
362 if (status!=GF_ERR_NOSUPPORT)
363 {
364 SDL_SetError("GF: Can't enable hardware cursor");
365 return -1;
366 }
367 }
368
369 /* Set cursor visible */
370 didata->cursor_visible=SDL_TRUE;
371 }
372 else
373 {
374 /* SDL requests to disable cursor */
375 status=gf_cursor_disable(didata->display, 0);
376 if (status!=GF_ERR_OK)
377 {
378 if (status!=GF_ERR_NOSUPPORT)
379 {
380 SDL_SetError("GF: Can't disable hardware cursor");
381 return -1;
382 }
383 }
384
385 /* Set cursor invisible */
386 didata->cursor_visible=SDL_FALSE;
387 }
388
389 /* New cursor shape is set */
390 return 0;
391 }
392
393 void gf_movecursor(SDL_Cursor* cursor)
394 {
395 SDL_VideoDisplay* display;
396 SDL_DisplayData* didata;
397 SDL_Window* window;
398 SDL_WindowID window_id;
399 int32_t status;
400 uint32_t xmax;
401 uint32_t ymax;
402
403 /* Get current window id */
404 window_id=SDL_GetFocusWindow();
405 if (window_id<=0)
406 {
407 didata=(SDL_DisplayData*)cursor->mouse->driverdata;
408 }
409 else
410 {
411 /* Sanity checks */
412 window=SDL_GetWindowFromID(window_id);
413 if (window!=NULL)
414 {
415 display=SDL_GetDisplayFromWindow(window);
416 if (display!=NULL)
417 {
418 didata=(SDL_DisplayData*)display->driverdata;
419 if (didata==NULL)
420 {
421 return;
422 }
423 }
424 else
425 {
426 return;
427 }
428 }
429 else
430 {
431 return;
432 }
433 }
434
435 /* Add checks for out of screen bounds position */
436 if (cursor->mouse->x<0)
437 {
438 cursor->mouse->x=0;
439 }
440 if (cursor->mouse->y<0)
441 {
442 cursor->mouse->y=0;
443 }
444
445 /* Get window size to clamp maximum coordinates */
446 SDL_GetWindowSize(window_id, &xmax, &ymax);
447 if (cursor->mouse->x>=xmax)
448 {
449 cursor->mouse->x=xmax-1;
450 }
451 if (cursor->mouse->y>=ymax)
452 {
453 cursor->mouse->y=ymax-1;
454 }
455
456 status=gf_cursor_set_pos(didata->display, 0, cursor->mouse->x, cursor->mouse->y);
457 if (status!=GF_ERR_OK)
458 {
459 if (status!=GF_ERR_NOSUPPORT)
460 {
461 SDL_SetError("GF: Can't set hardware cursor position");
462 return;
463 }
464 }
465 }
466
467 void gf_freecursor(SDL_Cursor* cursor)
468 {
469 gf_cursor_t* internal_cursor;
470
471 if (cursor!=NULL)
472 {
473 internal_cursor=(gf_cursor_t*)cursor->driverdata;
474 if (internal_cursor!=NULL)
475 {
476 if (internal_cursor->cursor.bitmap.image0!=NULL)
477 {
478 SDL_free((uint8_t*)internal_cursor->cursor.bitmap.image0);
479 }
480 if (internal_cursor->cursor.bitmap.image1!=NULL)
481 {
482 SDL_free((uint8_t*)internal_cursor->cursor.bitmap.image1);
483 }
484 SDL_free(internal_cursor);
485 }
486 }
487 }
488
489 void gf_warpmouse(SDL_Mouse* mouse, SDL_WindowID windowID, int x, int y)
490 {
491 SDL_VideoDisplay* display;
492 SDL_DisplayData* didata;
493 SDL_Window* window;
494 uint32_t xmax;
495 uint32_t ymax;
496 int32_t status;
497
498 /* Sanity checks */
499 window=SDL_GetWindowFromID(windowID);
500 if (window!=NULL)
501 {
502 display=SDL_GetDisplayFromWindow(window);
503 if (display!=NULL)
504 {
505 didata=(SDL_DisplayData*)display->driverdata;
506 if (didata==NULL)
507 {
508 return;
509 }
510 }
511 else
512 {
513 return;
514 }
515 }
516 else
517 {
518 return;
519 }
520
521 /* Add checks for out of screen bounds position */
522 if (x<0)
523 {
524 x=0;
525 }
526 if (y<0)
527 {
528 y=0;
529 }
530
531 /* Get window size to clamp maximum coordinates */
532 SDL_GetWindowSize(windowID, &xmax, &ymax);
533 if (x>=xmax)
534 {
535 x=xmax-1;
536 }
537 if (y>=ymax)
538 {
539 y=ymax-1;
540 }
541
542 status=gf_cursor_set_pos(didata->display, 0, x, y);
543 if (status!=GF_ERR_OK)
544 {
545 if (status!=GF_ERR_NOSUPPORT)
546 {
547 SDL_SetError("GF: Can't set hardware cursor position");
548 return;
549 }
550 }
551 }
552
553 void gf_freemouse(SDL_Mouse* mouse)
554 {
555 if (mouse->driverdata==NULL)
556 {
557 return;
558 }
559
560 /* Mouse framework doesn't deletes automatically our driverdata */
561 SDL_free(mouse->driverdata);
562 mouse->driverdata=NULL;
563
564 return;
565 }
566
567 /*****************************************************************************/
568 /* HIDDI handlers code */
569 /*****************************************************************************/
570 static key_packet key_last_state[SDL_HIDDI_MAX_DEVICES];
571
572 static void hiddi_keyboard_handler(uint32_t devno, uint8_t* report_data, uint32_t report_len)
573 {
574 key_packet* packet;
575 uint32_t it;
576 uint32_t jt;
577
578 packet=(key_packet*)report_data;
579
580 /* Check for special states */
581 switch (report_len)
582 {
583 case 8: /* 8 bytes of report length */
584 {
585 for (it=0; it<6; it++)
586 {
587 /* Check for keyboard overflow, when it can't handle */
588 /* many simultaneous pressed keys */
589 if (packet->codes[it]==HIDDI_KEY_OVERFLOW)
590 {
591 return;
592 }
593 }
594 }
595 break;
596 default:
597 {
598 /* Do not process unknown reports */
599 return;
600 }
601 break;
602 }
603
604 /* Check if modifier key was pressed */
605 if (packet->modifiers!=key_last_state[devno].modifiers)
606 {
607 if (((packet->modifiers & HIDDI_MKEY_LEFT_CTRL)==HIDDI_MKEY_LEFT_CTRL) &&
608 (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_CTRL)==0)
609 {
610 /* Left Ctrl key was pressed */
611 SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LCTRL);
612 }
613 if (((packet->modifiers & HIDDI_MKEY_LEFT_CTRL)==0) &&
614 (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_CTRL)==HIDDI_MKEY_LEFT_CTRL)
615 {
616 /* Left Ctrl key was released */
617 SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LCTRL);
618 }
619 if (((packet->modifiers & HIDDI_MKEY_LEFT_SHIFT)==HIDDI_MKEY_LEFT_SHIFT) &&
620 (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_SHIFT)==0)
621 {
622 /* Left Shift key was pressed */
623 SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LSHIFT);
624 }
625 if (((packet->modifiers & HIDDI_MKEY_LEFT_SHIFT)==0) &&
626 (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_SHIFT)==HIDDI_MKEY_LEFT_SHIFT)
627 {
628 /* Left Shift key was released */
629 SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LSHIFT);
630 }
631 if (((packet->modifiers & HIDDI_MKEY_LEFT_ALT)==HIDDI_MKEY_LEFT_ALT) &&
632 (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_ALT)==0)
633 {
634 /* Left Alt key was pressed */
635 SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LALT);
636 }
637 if (((packet->modifiers & HIDDI_MKEY_LEFT_ALT)==0) &&
638 (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_ALT)==HIDDI_MKEY_LEFT_ALT)
639 {
640 /* Left Alt key was released */
641 SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LALT);
642 }
643 if (((packet->modifiers & HIDDI_MKEY_LEFT_WFLAG)==HIDDI_MKEY_LEFT_WFLAG) &&
644 (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_WFLAG)==0)
645 {
646 /* Left Windows flag key was pressed */
647 SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LGUI);
648 }
649 if (((packet->modifiers & HIDDI_MKEY_LEFT_WFLAG)==0) &&
650 (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_WFLAG)==HIDDI_MKEY_LEFT_WFLAG)
651 {
652 /* Left Windows flag key was released */
653 SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LGUI);
654 }
655 if (((packet->modifiers & HIDDI_MKEY_RIGHT_CTRL)==HIDDI_MKEY_RIGHT_CTRL) &&
656 (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_CTRL)==0)
657 {
658 /* Right Ctrl key was pressed */
659 SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_RCTRL);
660 }
661 if (((packet->modifiers & HIDDI_MKEY_RIGHT_CTRL)==0) &&
662 (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_CTRL)==HIDDI_MKEY_RIGHT_CTRL)
663 {
664 /* Right Ctrl key was released */
665 SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_RCTRL);
666 }
667 if (((packet->modifiers & HIDDI_MKEY_RIGHT_SHIFT)==HIDDI_MKEY_RIGHT_SHIFT) &&
668 (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_SHIFT)==0)
669 {
670 /* Right Shift key was pressed */
671 SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_RSHIFT);
672 }
673 if (((packet->modifiers & HIDDI_MKEY_RIGHT_SHIFT)==0) &&
674 (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_SHIFT)==HIDDI_MKEY_RIGHT_SHIFT)
675 {
676 /* Right Shift key was released */
677 SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_RSHIFT);
678 }
679 if (((packet->modifiers & HIDDI_MKEY_RIGHT_ALT)==HIDDI_MKEY_RIGHT_ALT) &&
680 (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_ALT)==0)
681 {
682 /* Right Alt key was pressed */
683 SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_RALT);
684 }
685 if (((packet->modifiers & HIDDI_MKEY_RIGHT_ALT)==0) &&
686 (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_ALT)==HIDDI_MKEY_RIGHT_ALT)
687 {
688 /* Right Alt key was released */
689 SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_RALT);
690 }
691 if (((packet->modifiers & HIDDI_MKEY_RIGHT_WFLAG)==HIDDI_MKEY_RIGHT_WFLAG) &&
692 (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_WFLAG)==0)
693 {
694 /* Right Windows flag key was pressed */
695 SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_RGUI);
696 }
697 if (((packet->modifiers & HIDDI_MKEY_RIGHT_WFLAG)==0) &&
698 (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_WFLAG)==HIDDI_MKEY_RIGHT_WFLAG)
699 {
700 /* Right Windows flag key was released */
701 SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_RGUI);
702 }
703 }
704
705 /* Check each key in the press/release buffer */
706 switch (report_len)
707 {
708 case 8: /* 8 bytes of report length */
709 {
710 /* Check if at least one key was unpressed */
711 for (it=0; it<6; it++)
712 {
713 if (key_last_state[devno].codes[it]==HIDDI_KEY_UNPRESSED)
714 {
715 /* if stored keycode is zero, find another */
716 continue;
717 }
718 for (jt=0; jt<6; jt++)
719 {
720 /* Find stored keycode in the current pressed codes */
721 if (packet->codes[jt]==key_last_state[devno].codes[it])
722 {
723 /* If found then particular key state is not changed */
724 break;
725 }
726 }
727
728 /* Check if pressed key can't longer be found */
729 if (jt==6)
730 {
731 SDL_SendKeyboardKey(0, SDL_RELEASED, key_last_state[devno].codes[it]);
732 }
733 }
734
735 /* Check if at least one new key was pressed */
736 for (it=0; it<6; it++)
737 {
738 if (packet->codes[it]==HIDDI_KEY_UNPRESSED)
739 {
740 continue;
741 }
742 for (jt=0; jt<6; jt++)
743 {
744 /* Find new keycode it the array of old pressed keys */
745 if (packet->codes[it]==key_last_state[devno].codes[jt])
746 {
747 break;
748 }
749 }
750
751 /* Check if new key was pressed */
752 if (jt==6)
753 {
754 SDL_SendKeyboardKey(0, SDL_PRESSED, packet->codes[it]);
755 }
756 }
757 }
758 default: /* unknown keyboard report type */
759 {
760 /* Ignore all unknown reports */
761 }
762 break;
763 }
764
765 /* Store last state */
766 key_last_state[devno]=*packet;
767 }
768
769 static uint32_t mouse_last_state_button[SDL_HIDDI_MAX_DEVICES];
770 static uint32_t collect_reports=0;
771
772 static void hiddi_mouse_handler(uint32_t devno, uint8_t* report_data, uint32_t report_len)
773 {
774 uint32_t it;
775 uint32_t sdlbutton;
776
777 /* We do not want to collect stored events */
778 if (collect_reports==0)
779 {
780 return;
781 }
782
783 /* Check for special states */
784 switch (report_len)
785 {
786 case 8: /* 8 bytes of report length, usually multi-button USB mice */
787 {
788 mouse_packet8* packet;
789 packet=(mouse_packet8*)report_data;
790
791 /* Send motion event if motion really was */
792 if ((packet->horizontal_precision!=0) || (packet->vertical_precision!=0))
793 {
794 SDL_SendMouseMotion(0, 1, packet->horizontal_precision, packet->vertical_precision, 0);
795 }
796
797 /* Send mouse button press/release events */
798 if (mouse_last_state_button[devno]!=packet->buttons)
799 {
800 /* Cycle all buttons status */
801 for (it=0; it<8; it++)
802 {
803 /* convert hiddi button id to sdl button id */
804 switch(it)
805 {
806 case 0:
807 {
808 sdlbutton=SDL_BUTTON_LEFT;
809 }
810 break;
811 case 1:
812 {
813 sdlbutton=SDL_BUTTON_RIGHT;
814 }
815 break;
816 case 2:
817 {
818 sdlbutton=SDL_BUTTON_MIDDLE;
819 }
820 break;
821 default:
822 {
823 sdlbutton=it+1;
824 }
825 break;
826 }
827
828 /* Button pressed */
829 if (((packet->buttons & (0x01<<it))==(0x01<<it)) &&
830 ((mouse_last_state_button[devno] & (0x01<<it))==0x00))
831 {
832 SDL_SendMouseButton(0, SDL_PRESSED, sdlbutton);
833 }
834 /* Button released */
835 if (((packet->buttons & (0x01<<it))==0x00) &&
836 ((mouse_last_state_button[devno] & (0x01<<it))==(0x01<<it)))
837 {
838 SDL_SendMouseButton(0, SDL_RELEASED, sdlbutton);
839 }
840 }
841 mouse_last_state_button[devno]=packet->buttons;
842 }
843
844 /* Send mouse wheel events */
845 if (packet->wheel!=0)
846 {
847 /* Send vertical wheel event only */
848 SDL_SendMouseWheel(0, 0, packet->wheel);
849 }
850 }
851 break;
852 case 4: /* 4 bytes of report length, usually PS/2 mice */
853 {
854 mouse_packet4* packet;
855 packet=(mouse_packet4*)report_data;
856
857 /* Send motion event if motion really was */
858 if ((packet->horizontal!=0) || (packet->vertical!=0))
859 {
860 SDL_SendMouseMotion(0, 1, packet->horizontal, packet->vertical, 0);
861 }
862
863 /* Send mouse button press/release events */
864 if (mouse_last_state_button[devno]!=packet->buttons)
865 {
866 /* Cycle all buttons status */
867 for (it=0; it<8; it++)
868 {
869 /* convert hiddi button id to sdl button id */
870 switch(it)
871 {
872 case 0:
873 {
874 sdlbutton=SDL_BUTTON_LEFT;
875 }
876 break;
877 case 1:
878 {
879 sdlbutton=SDL_BUTTON_RIGHT;
880 }
881 break;
882 case 2:
883 {
884 sdlbutton=SDL_BUTTON_MIDDLE;
885 }
886 break;
887 default:
888 {
889 sdlbutton=it+1;
890 }
891 break;
892 }
893
894 /* Button pressed */
895 if (((packet->buttons & (0x01<<it))==(0x01<<it)) &&
896 ((mouse_last_state_button[devno] & (0x01<<it))==0x00))
897 {
898 SDL_SendMouseButton(0, SDL_PRESSED, sdlbutton);
899 }
900 /* Button released */
901 if (((packet->buttons & (0x01<<it))==0x00) &&
902 ((mouse_last_state_button[devno] & (0x01<<it))==(0x01<<it)))
903 {
904 SDL_SendMouseButton(0, SDL_RELEASED, sdlbutton);
905 }
906 }
907 mouse_last_state_button[devno]=packet->buttons;
908 }
909
910 /* Send mouse wheel events */
911 if (packet->wheel!=0)
912 {
913 /* Send vertical wheel event only */
914 SDL_SendMouseWheel(0, 0, packet->wheel);
915 }
916 }
917 break;
918 }
919 }
920
921 /*****************************************************************************/
922 /* HIDDI interacting code */
923 /*****************************************************************************/
924 static hidd_device_ident_t hiddevice=
925 {
926 HIDD_CONNECT_WILDCARD, /* vendor id: any */
927 HIDD_CONNECT_WILDCARD, /* product id: any */
928 HIDD_CONNECT_WILDCARD, /* version: any */
929 };
930
931 static hidd_connect_parm_t hidparams={NULL, HID_VERSION, HIDD_VERSION, 0, 0, &hiddevice, NULL, 0};
932
933 static void hiddi_insertion(struct hidd_connection* connection, hidd_device_instance_t* device_instance);
934 static void hiddi_removal(struct hidd_connection* connection, hidd_device_instance_t* instance);
935 static void hiddi_report(struct hidd_connection* connection, struct hidd_report* report, void* report_data, uint32_t report_len, uint32_t flags, void* user);
936
937 static hidd_funcs_t hidfuncs={_HIDDI_NFUNCS, hiddi_insertion, hiddi_removal, hiddi_report, NULL};
938
939 /* HID handle, singletone */
940 struct hidd_connection* connection=NULL;
941
942 /* SDL detected input device types, singletone */
943 static uint32_t sdl_input_devices[SDL_HIDDI_MAX_DEVICES];
944
945 static int hiddi_register_for_reports(struct hidd_collection* col, hidd_device_instance_t* device_instance)
946 {
947 int it;
948 uint16_t num_col;
949 struct hidd_collection** hidd_collections;
950 struct hidd_report_instance* report_instance;
951 struct hidd_report* report;
952 int status=0;
953 hidview_device_t* device;
954
955 for (it=0 ; it<10 && !status; it++)
956 {
957 status=hidd_get_report_instance(col, it, HID_INPUT_REPORT, &report_instance);
958 if (status==EOK)
959 {
960 status=hidd_report_attach(connection, device_instance, report_instance, 0, sizeof(hidview_device_t), &report);
961 if (status==EOK)
962 {
963 device=hidd_report_extra(report);
964 device->report=report;
965 device->instance=report_instance;
966 }
967 }
968 }
969 hidd_get_collections(NULL, col, &hidd_collections, &num_col);
970
971 for (it=0; it<num_col; it++)
972 {
973 hiddi_register_for_reports(hidd_collections[it], device_instance);
974 }
975
976 return EOK;
977 }
978
979 static void hiddi_insertion(struct hidd_connection* connection, hidd_device_instance_t* device_instance)
980 {
981 uint32_t it;
982 struct hidd_collection** hidd_collections;
983 uint16_t num_col;
984
985 /* get root level collections */
986 hidd_get_collections(device_instance, NULL, &hidd_collections, &num_col);
987 for (it=0; it<num_col; it++)
988 {
989 hiddi_register_for_reports(hidd_collections[it], device_instance);
990 }
991 }
992
993 static void hiddi_removal(struct hidd_connection* connection, hidd_device_instance_t* instance)
994 {
995 hidd_reports_detach(connection, instance);
996 }
997
998 static void hiddi_report(struct hidd_connection* connection, hidd_report_t* report, void* report_data, uint32_t report_len, uint32_t flags, void* user)
999 {
1000 if (report->dev_inst->devno>=SDL_HIDDI_MAX_DEVICES)
1001 {
1002 /* Unknown HID device, with devno number out of supported range */
1003 return;
1004 }
1005
1006 /* Check device type which generates event */
1007 switch (sdl_input_devices[report->dev_inst->devno])
1008 {
1009 case SDL_GF_HIDDI_NONE:
1010 {
1011 /* We do not handle other devices type*/
1012 return;
1013 }
1014 break;
1015 case SDL_GF_HIDDI_MOUSE:
1016 {
1017 /* Call mouse handler */
1018 hiddi_mouse_handler(report->dev_inst->devno, report_data, report_len);
1019 }
1020 break;
1021 case SDL_GF_HIDDI_KEYBOARD:
1022 {
1023 /* Call keyboard handler */
1024 hiddi_keyboard_handler(report->dev_inst->devno, report_data, report_len);
1025 }
1026 break;
1027 case SDL_GF_HIDDI_JOYSTICK:
1028 {
1029 /* Call joystick handler */
1030 }
1031 break;
1032 }
1033 }
1034
1035 static hiddi_get_device_type(uint8_t* report_data, uint16_t report_length)
1036 {
1037 hid_byte_t byte;
1038 uint16_t usage_page=0;
1039 uint16_t usage=0;
1040 uint16_t data=0;
1041
1042 while (report_length && !(usage_page && usage))
1043 {
1044 if (hidp_analyse_byte(*report_data, &byte))
1045 {
1046 /* Error in parser, do nothing */
1047 }
1048 data=hidp_get_data((report_data+1), &byte);
1049 switch (byte.HIDB_Type)
1050 {
1051 case HID_TYPE_GLOBAL:
1052 if (!usage_page && byte.HIDB_Tag==HID_GLOBAL_USAGE_PAGE)
1053 {
1054 usage_page=data;
1055 }
1056 break;
1057 case HID_TYPE_LOCAL:
1058 if (!usage && byte.HIDB_Tag==HID_LOCAL_USAGE)
1059 {
1060 usage=data;
1061 }
1062 break;
1063 }
1064 report_data+=byte.HIDB_Length+1;
1065 report_length-=byte.HIDB_Length+1;
1066 }
1067
1068 switch (usage_page)
1069 {
1070 case HIDD_PAGE_DESKTOP:
1071 {
1072 switch (usage)
1073 {
1074 case HIDD_USAGE_MOUSE:
1075 {
1076 return SDL_GF_HIDDI_MOUSE;
1077 }
1078 break;
1079 case HIDD_USAGE_JOYSTICK:
1080 {
1081 return SDL_GF_HIDDI_JOYSTICK;
1082 }
1083 break;
1084 case HIDD_USAGE_KEYBOARD:
1085 {
1086 return SDL_GF_HIDDI_KEYBOARD;
1087 }
1088 break;
1089 }
1090 }
1091 break;
1092 case HIDD_PAGE_DIGITIZER:
1093 {
1094 /* Do not handle digitizers */
1095 }
1096 break;
1097 case HIDD_PAGE_CONSUMER:
1098 {
1099 /* Do not handle consumer input devices */
1100 }
1101 break;
1102 }
1103
1104 return SDL_GF_HIDDI_NONE;
1105 }
1106
1107 static int32_t hiddi_connect_devices()
1108 {
1109 int32_t status;
1110 uint32_t it;
1111 uint8_t* report_data;
1112 uint16_t report_length;
1113 hidd_device_instance_t instance;
1114
1115 /* Cleanup initial keys and mice state */
1116 SDL_memset(key_last_state, 0x00, sizeof(key_packet)*SDL_HIDDI_MAX_DEVICES);
1117 SDL_memset(mouse_last_state_button, 0x00, sizeof(uint32_t)*SDL_HIDDI_MAX_DEVICES);
1118
1119 status=hidd_connect(&hidparams, &connection);
1120 if (status!=EOK)
1121 {
1122 return -1;
1123 }
1124
1125 for (it=0; it<SDL_HIDDI_MAX_DEVICES; it++)
1126 {
1127 /* Get device instance */
1128 status=hidd_get_device_instance(connection, it, &instance);
1129 if (status!=EOK)
1130 {
1131 continue;
1132 }
1133
1134 status=hidd_get_report_desc(connection, &instance, &report_data, &report_length);
1135 if (status!=EOK)
1136 {
1137 continue;
1138 }
1139
1140 status=hiddi_get_device_type(report_data, report_length);
1141 sdl_input_devices[it]=status;
1142
1143 free(report_data);
1144 }
1145
1146 /* Disconnect from HID server */
1147 status=hidd_disconnect(connection);
1148 if (status!=EOK)
1149 {
1150 return -1;
1151 }
1152
1153 /* Add handlers for HID devices */
1154 hidparams.funcs=&hidfuncs;
1155
1156 status=hidd_connect(&hidparams, &connection);
1157 if (status!=EOK)
1158 {
1159 return -1;
1160 }
1161
1162 return 0;
1163 }
1164
1165 static int32_t hiddi_disconnect_devices()
1166 {
1167 int32_t status;
1168
1169 hiddi_disable_mouse();
1170
1171 /* Disconnect from HID server */
1172 status=hidd_disconnect(connection);
1173 if (status!=EOK)
1174 {
1175 return -1;
1176 }
1177 }
1178
1179 void hiddi_enable_mouse()
1180 {
1181 collect_reports=1;
1182 }
1183
1184 void hiddi_disable_mouse()
1185 {
1186 collect_reports=0;
1187 }