Mercurial > sdl-ios-xcode
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 } |