PS2SDK
PS2 Homebrew Libraries
ps2kbd.c
Go to the documentation of this file.
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
16 #include "types.h"
17 #include "ioman.h"
18 #include "loadcore.h"
19 #include "stdio.h"
20 #include "sifcmd.h"
21 #include "sifrpc.h"
22 #include "sysclib.h"
23 #include <errno.h>
24 #include "sysmem.h"
25 #include "usbd.h"
26 #include "usbd_macro.h"
27 #include "thbase.h"
28 #include "thevent.h"
29 #include "thsemap.h"
30 
31 #include "ps2kbd.h"
32 #include "us_keymap.h"
33 
34 #define MODNAME "PS2 USB keyboard driver"
35 
36 IRX_ID(MODNAME, 1, 1);
37 
38 #define PS2KBD_VERSION 0x100
39 
40 #define USB_SUBCLASS_BOOT 1
41 #define USB_HIDPROTO_KEYBOARD 1
42 
43 #define PS2KBD_MAXDEV 2
44 #define PS2KBD_MAXKEYS 6
45 
46 #define PS2KBD_DEFLINELEN 4096
47 #define PS2KBD_DEFREPEATRATE 100
48 
49 #define PS2KBD_REPEATWAIT 1000
50 
51 #define USB_KEYB_NUMLOCK 0x53
52 #define USB_KEYB_CAPSLOCK 0x39
53 #define USB_KEYB_SCRLOCK 0x47
54 
55 #define USB_KEYB_NUMPAD_START 0x54
56 #define USB_KEYB_NUMPAD_END 0x63
57 
58 #define SEMA_ZERO -419
59 #define SEMA_DELETED -425
60 
61 int ps2kbd_init();
62 void ps2kbd_config_set(int resultCode, int bytes, void *arg);
63 void ps2kbd_idlemode_set(int resultCode, int bytes, void *arg);
64 void ps2kbd_data_recv(int resultCode, int bytes, void *arg);
65 int ps2kbd_probe(int devId);
66 int ps2kbd_connect(int devId);
67 int ps2kbd_disconnect(int devId);
68 void usb_getstring(int endp, int index, char *desc);
69 
70 typedef struct _kbd_data_recv
71 
72 {
73  u8 mod_keys;
74  u8 reserved;
75  u8 keycodes[PS2KBD_MAXKEYS];
77 
78 typedef struct _keyb_dev
79 
80 {
81  int configEndp;
82  int dataEndp;
83  int packetSize;
84  int devId;
87  char repeatkeys[2];
88  u32 eventmask;
90  u8 ledStatus;
91  kbd_data_recv oldData;
94 } kbd_dev;
95 
96 /* Global Variables */
97 
98 int kbd_readmode;
99 int kbd_blocking;
100 u32 kbd_repeatrate;
102 kbd_dev *devices[PS2KBD_MAXDEV];
103 int dev_count;
104 sceUsbdLddOps kbd_driver = { NULL, NULL, "PS2Kbd", ps2kbd_probe, ps2kbd_connect, ps2kbd_disconnect, 0, 0, 0, 0, 0, NULL };
105 u8 *lineBuffer;
106 u32 lineStartP, lineEndP;
107 int lineSema;
108 int bufferSema;
109 u32 lineSize;
111 u8 keymap[PS2KBD_KEYMAP_SIZE];
113 u8 shiftkeymap[PS2KBD_KEYMAP_SIZE];
115 u8 keycap[PS2KBD_KEYMAP_SIZE];
116 u8 special_keys[PS2KBD_KEYMAP_SIZE];
117 u8 control_map[PS2KBD_KEYMAP_SIZE];
118 u8 alt_map[PS2KBD_KEYMAP_SIZE];
119 //static struct fileio_driver kbd_fdriver;
120 u8 keyModValue[8] = { 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7 };
121 int repeat_tid;
122 int eventid; /* Id of the repeat event */
123 
124 int _start (int argc, char *argv[])
125 {
126  (void)argc;
127  (void)argv;
128 
129  ps2kbd_init();
130 
131  printf("PS2KBD - USB Keyboard Library\n");
132 
133  return MODULE_RESIDENT_END;
134 }
135 
136 int ps2kbd_probe(int devId)
137 
138 {
139  UsbDeviceDescriptor *dev;
140  UsbConfigDescriptor *conf;
142  UsbEndpointDescriptor *endp;
143  //UsbStringDescriptor *str;
144 
145  if(dev_count >= PS2KBD_MAXDEV)
146  {
147  printf("ERROR: Maximum keyboard devices reached\n");
148  return 0;
149  }
150 
151  //printf("PS2Kbd_probe devId %d\n", devId);
152 
153  dev = sceUsbdScanStaticDescriptor(devId, NULL, USB_DT_DEVICE); /* Get device descriptor */
154  if(!dev)
155  {
156  printf("ERROR: Couldn't get device descriptor\n");
157  return 0;
158  }
159 
160  //printf("Device class %d, Size %d, Man %d, Product %d Cpnfigurations %d\n", dev->bDeviceClass, dev->bMaxPacketSize0, dev->iManufacturer, dev->iProduct, dev->bNumConfigurations);
161  /* Check that the device class is specified in the interfaces and it has at least one configuration */
162  if((dev->bDeviceClass != USB_CLASS_PER_INTERFACE) || (dev->bNumConfigurations < 1))
163  {
164  //printf("This is not the droid you're looking for\n");
165  return 0;
166  }
167 
168  conf = sceUsbdScanStaticDescriptor(devId, dev, USB_DT_CONFIG);
169  if(!conf)
170  {
171  printf("ERROR: Couldn't get configuration descriptor\n");
172  return 0;
173  }
174  //printf("Config Length %d Total %d Interfaces %d\n", conf->bLength, conf->wTotalLength, conf->bNumInterfaces);
175 
176  if((conf->bNumInterfaces < 1) || (conf->wTotalLength < (sizeof(UsbConfigDescriptor) + sizeof(UsbInterfaceDescriptor))))
177  {
178  printf("ERROR: No interfaces available\n");
179  return 0;
180  }
181 
182  intf = (UsbInterfaceDescriptor *) ((char *) conf + conf->bLength); /* Get first interface */
183 /* printf("Interface Length %d Endpoints %d Class %d Sub %d Proto %d\n", intf->bLength, */
184 /* intf->bNumEndpoints, intf->bInterfaceClass, intf->bInterfaceSubClass, */
185 /* intf->bInterfaceProtocol); */
186 
187  if((intf->bInterfaceClass != USB_CLASS_HID) || (intf->bInterfaceSubClass != USB_SUBCLASS_BOOT) ||
188  (intf->bInterfaceProtocol != USB_HIDPROTO_KEYBOARD) || (intf->bNumEndpoints < 1))
189 
190  {
191  //printf("We came, we saw, we told it to fuck off\n");
192  return 0;
193  }
194 
195  endp = (UsbEndpointDescriptor *) ((char *) intf + intf->bLength);
196  endp = (UsbEndpointDescriptor *) ((char *) endp + endp->bLength); /* Go to the data endpoint */
197 
198  //printf("Endpoint 1 Addr %d, Attr %d, MaxPacket %d\n", endp->bEndpointAddress, endp->bmAttributes, endp->wMaxPacketSizeLB);
199 
200  if(((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) ||
201  ((endp->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN))
202  {
203  printf("ERROR: Endpoint not interrupt type and/or an input\n");
204  return 0;
205  }
206 
207  printf("PS2KBD: Found a keyboard device\n");
208 
209  return 1;
210 }
211 
212 int ps2kbd_connect(int devId)
213 
214 {
215  /* Assume we can only get here if we have already checked the device is kosher */
216 
217  UsbDeviceDescriptor *dev;
218  UsbConfigDescriptor *conf;
220  UsbEndpointDescriptor *endp;
221  kbd_dev *currDev;
222  int devLoop;
223 
224  //printf("PS2Kbd_connect devId %d\n", devId);
225 
226  dev = sceUsbdScanStaticDescriptor(devId, NULL, USB_DT_DEVICE); /* Get device descriptor */
227  if(!dev)
228  {
229  printf("ERROR: Couldn't get device descriptor\n");
230  return 1;
231  }
232 
233  conf = sceUsbdScanStaticDescriptor(devId, dev, USB_DT_CONFIG);
234  if(!conf)
235  {
236  printf("ERROR: Couldn't get configuration descriptor\n");
237  return 1;
238  }
239 
240  intf = (UsbInterfaceDescriptor *) ((char *) conf + conf->bLength); /* Get first interface */
241  endp = (UsbEndpointDescriptor *) ((char *) intf + intf->bLength);
242  endp = (UsbEndpointDescriptor *) ((char *) endp + endp->bLength); /* Go to the data endpoint */
243 
244  for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
245  {
246  if(devices[devLoop] == NULL)
247  {
248  break;
249  }
250  }
251 
252  if(devLoop == PS2KBD_MAXDEV)
253  {
254  /* How the f*** did we end up here ??? */
255  printf("ERROR: Device Weirdness!!\n");
256  return 1;
257  }
258 
259  currDev = (kbd_dev *) AllocSysMemory(0, sizeof(kbd_dev), NULL);
260  if(!currDev)
261  {
262  printf("ERROR: Couldn't allocate a device point for the kbd\n");
263  return 1;
264  }
265 
266  devices[devLoop] = currDev;
267  memset(currDev, 0, sizeof(kbd_dev));
268  currDev->configEndp = sceUsbdOpenPipe(devId, NULL);
269  currDev->dataEndp = sceUsbdOpenPipe(devId, endp);
270  currDev->packetSize = endp->wMaxPacketSizeLB | ((int) endp->wMaxPacketSizeHB << 8);
271  currDev->eventmask = (1 << devLoop);
272  if((unsigned int)(currDev->packetSize) > sizeof(kbd_data_recv))
273  {
274  currDev->packetSize = sizeof(kbd_data_recv);
275  }
276 
277  if(dev->iManufacturer != 0)
278  {
279  usb_getstring(currDev->configEndp, dev->iManufacturer, "Keyboard Manufacturer");
280  }
281 
282  if(dev->iProduct != 0)
283  {
284  usb_getstring(currDev->configEndp, dev->iProduct, "Keyboard Product");
285  }
286 
287  currDev->devId = devId;
288  currDev->interfaceNo = intf->bInterfaceNumber;
289  currDev->ledStatus = 0;
290 
291  sceUsbdSetPrivateData(devId, currDev); /* Set the index for the device data */
292 
293  //printf("Configuration value %d\n", conf->bConfigurationValue);
294  sceUsbdSetConfiguration(currDev->configEndp, conf->bConfigurationValue, ps2kbd_config_set, currDev);
295 
296  dev_count++; /* Increment device count */
297  printf("PS2KBD: Connected device\n");
298 
299  return 0;
300 }
301 
302 int ps2kbd_disconnect(int devId)
303 
304 {
305  int devLoop;
306  //printf("PS2Kbd_disconnect devId %d\n", devId);
307 
308  for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
309  {
310  if((devices[devLoop]) && (devices[devLoop]->devId == devId))
311  {
312  dev_count--;
313  FreeSysMemory(devices[devLoop]);
314  devices[devLoop] = NULL;
315  printf("PS2KBD: Disconnected device\n");
316  break;
317  }
318  }
319 
320  return 0;
321 }
322 
323 typedef struct _string_descriptor
324 
325 {
326  u8 buf[200];
327  char *desc;
329 
330 void ps2kbd_getstring_set(int resultCode, int bytes, void *arg)
331 
332 {
334  string_descriptor *strBuf = (string_descriptor *) arg;
335 
336 /* printf("=========getstring=========\n"); */
337 
338 /* printf("PS2KEYBOARD: GET_DESCRIPTOR res %d, bytes %d, arg %p\n", resultCode, bytes, arg); */
339 
340  if(resultCode == USB_RC_OK)
341  {
342  char string[50];
343  int strLoop;
344 
345  memset(string, 0, 50);
346  for(strLoop = 0; strLoop < ((bytes - 2) / 2); strLoop++)
347  {
348  string[strLoop] = str->wData[strLoop] & 0xFF;
349  }
350  printf("PS2KBD %s: %s\n", strBuf->desc, string);
351  }
352 
353  FreeSysMemory(arg);
354 }
355 
356 void usb_getstring(int endp, int index, char *desc)
357 
358 {
359  u8 *data;
360  string_descriptor *str;
361 
362  data = (u8 *) AllocSysMemory(0, sizeof(string_descriptor), NULL);
363  str = (string_descriptor *) data;
364 
365  if(data != NULL)
366  {
367  int ret;
368 
369  str->desc = desc;
370  ret = sceUsbdControlTransfer(endp, 0x80, USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | index,
371  0x0409, sizeof(string_descriptor) - 4, data, ps2kbd_getstring_set, data);
372  if(ret != USB_RC_OK)
373  {
374  printf("PS2KBD: Error sending string descriptor request\n");
375  FreeSysMemory(data);
376  }
377  }
378 }
379 
380 void ps2kbd_config_set(int resultCode, int bytes, void *arg)
381  /* Called when we have finished choosing our configuration */
382 
383 {
384  kbd_dev *dev;
385 
386  if(resultCode != USB_RC_OK)
387  {
388  printf("PS2KEYBOARD: Configuration set error res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
389  return;
390  }
391 
392  //printf("PS2KEYBOARD: Configuration set res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
393  /* Do a interrupt data transfer */
394 
395  dev = (kbd_dev *) arg;
396  if(dev != NULL)
397  {
398  sceUsbdControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_IDLE, 0, dev->interfaceNo, 0, NULL, ps2kbd_idlemode_set, arg);
399  }
400 }
401 
402 void ps2kbd_idlemode_set(int resultCode, int bytes, void *arg)
403 
404 {
405  kbd_dev *dev;
406 
407 
408 
409  if(resultCode != USB_RC_OK)
410  {
411  printf("PS2KBD: Idlemode set error res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
412  return;
413  }
414 
415  dev = (kbd_dev *) arg;
416  if(dev != NULL)
417  {
418  sceUsbdInterruptTransfer(dev->dataEndp, &dev->data, dev->packetSize, ps2kbd_data_recv, arg);
419  }
420 }
421 
422 void ps2kbd_led_set(int resultCode, int bytes, void *arg)
423 
424 {
425  (void)resultCode;
426  (void)bytes;
427  (void)arg;
428 
429  //printf("LED Set\n");
430 }
431 
432 void ps2kbd_build_uniquekeys(u8 *res, const u8 *new_, const u8 *old)
433 
434  /* Builds a list of unique keys */
435 
436 {
437  int loopNew, loopOld;
438  int loopRes = 0;
439  int foundKey;
440 
441  for(loopNew = 0; loopNew < PS2KBD_MAXKEYS; loopNew++)
442  {
443  if(new_[loopNew] != 0)
444  {
445  foundKey = 0;
446  for(loopOld = 0; loopOld < PS2KBD_MAXKEYS; loopOld++)
447  {
448  if(new_[loopNew] == old[loopOld])
449  {
450  foundKey = 1;
451  break;
452  }
453  }
454  if(!foundKey)
455  {
456  res[loopRes++] = new_[loopNew];
457  }
458  }
459  }
460 }
461 
462 u32 ps2kbd_repeathandler(void *arg)
463 
464 {
465  kbd_dev *dev = arg;
466  iop_sys_clock_t t;
467  //printf("Repeat handler\n");
468 
469  iSetEventFlag(eventid, dev->eventmask);
470 
471  USec2SysClock(kbd_repeatrate * 1000, &t);
472  iSetAlarm(&t, (void *)ps2kbd_repeathandler, arg);
473 
474  return t.hi;
475 }
476 
477 void ps2kbd_getkeys(u8 keyMods, u8 ledStatus, const u8 *keys, kbd_dev *dev)
478 
479 {
480  int loopKey;
481  int tempPos = 0;
482  int byteCount = 0;
483  u8 currChars[2];
484 
485  if(lineStartP < lineEndP)
486  {
487  tempPos = lineStartP + lineSize;
488  }
489  else
490  {
491  tempPos = lineStartP;
492  }
493 
494  for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++)
495  {
496  u8 currKey = keys[loopKey];
497 
498  currChars[0] = 0;
499  currChars[1] = 0;
500 
501  if(lineEndP == (u32)(tempPos - 1))
502  {
503  break;
504  }
505 
506  if(currKey) /* If this is a valid key */
507  {
508  if((currKey >= USB_KEYB_NUMPAD_START) && (currKey <= USB_KEYB_NUMPAD_END))
509  /* Handle numpad specially */
510  {
511  if(ledStatus & PS2KBD_LED_NUMLOCK)
512  {
513  if(keymap[currKey])
514  {
515  currChars[0] = keymap[currKey];
516  }
517  }
518  else
519  {
520  if(special_keys[currKey])
521  {
522  currChars[0] = PS2KBD_ESCAPE_KEY;
523  currChars[1] = special_keys[currKey];
524  }
525  else if(keymap[currKey] != '5') /* Make sure this isnt a 5 key :) */
526  {
527  currChars[0] = keymap[currKey];
528  }
529  }
530  }
531  else if(special_keys[currKey]) /* This is a special key */
532  {
533  currChars[0] = PS2KBD_ESCAPE_KEY;
534  currChars[1] = special_keys[currKey];
535  }
536  else if(keyMods & PS2KBD_CTRL) /* CTRL */
537  {
538  if(control_map[currKey])
539  {
540  currChars[0] = control_map[currKey];
541  }
542  }
543  else if(keyMods & PS2KBD_ALT) /* ALT */
544  {
545  if(alt_map[currKey])
546  {
547  currChars[0] = alt_map[currKey];
548  }
549  }
550  else if(keyMods & PS2KBD_SHIFT) /* SHIFT */
551  {
552  if((ledStatus & PS2KBD_LED_CAPSLOCK) && (keycap[currKey]))
553  {
554  currChars[0] = keymap[currKey];
555  }
556  else
557  {
558  currChars[0] = shiftkeymap[currKey];
559  }
560  }
561  else /* Normal key */
562  {
563  if(keymap[keys[loopKey]])
564  {
565  if((ledStatus & PS2KBD_LED_CAPSLOCK) && (keycap[currKey]))
566  {
567  currChars[0] = shiftkeymap[currKey];
568  }
569  else
570  {
571  currChars[0] = keymap[currKey];
572  }
573  }
574  }
575  }
576 
577  if((currChars[0] == PS2KBD_ESCAPE_KEY) && (currChars[1] != 0))
578  {
579  if(lineEndP != (u32)(tempPos - 2))
580  {
581  lineBuffer[lineEndP++] = currChars[0];
582  lineEndP %= lineSize;
583  lineBuffer[lineEndP++] = currChars[1];
584  lineEndP %= lineSize;
585  byteCount += 2;
586  }
587  dev->repeatkeys[0] = currChars[0];
588  dev->repeatkeys[1] = currChars[1];
589  }
590  else if(currChars[0] != 0)
591  {
592  lineBuffer[lineEndP++] = currChars[0];
593  lineEndP %= lineSize;
594  byteCount++;
595  dev->repeatkeys[0] = currChars[0];
596  dev->repeatkeys[1] = 0;
597  }
598  }
599 
600  if(byteCount > 0)
601  {
602  iop_sys_clock_t t;
603  /* Set alarm to do repeat rate */
604  //printf("repeatkeys %d %d\n", kbd_repeatkeys[0], kbd_repeatkeys[1]);
605  USec2SysClock(PS2KBD_REPEATWAIT * 1000, &t);
606  SetAlarm(&t, (void *)ps2kbd_repeathandler, dev);
607  }
608 
609  for(loopKey = 0; loopKey < byteCount; loopKey++) /* Signal the sema to indicate data */
610  {
611  SignalSema(bufferSema);
612  }
613 
614 /* lineBuffer[PS2KBD_DEFLINELEN - 1] = 0; */
615 /* printf(lineBuffer); */
616  //printf("lineStart %d, lineEnd %d\n", lineStartP, lineEndP);
617 }
618 
619 
620 void ps2kbd_getkeys_raw(u8 newKeyMods, u8 oldKeyMods, const u8 *new_, const u8 *old)
621 
622 {
623  int loopKey;
624  u8 currKey;
625  u8 keyMods = newKeyMods ^ oldKeyMods;
626  u8 keyModsMap = newKeyMods & keyMods;
627  int tempPos = 0;
628  int byteCount = 0;
629 
630  if(lineStartP < lineEndP)
631  {
632  tempPos = lineStartP + lineSize;
633  }
634  else
635  {
636  tempPos = lineStartP;
637  }
638 
639  for(loopKey = 0; loopKey < 8; loopKey++)
640  {
641  int currMod = (1 << loopKey);
642  if(keyMods & currMod)
643  {
644  if(lineEndP == (u32)(tempPos - 2))
645  {
646  return;
647  }
648 
649  currKey = keyModValue[loopKey];
650 
651  if(keyModsMap & currMod) /* If key pressed */
652  {
653  lineBuffer[lineEndP++] = PS2KBD_RAWKEY_DOWN;
654  //printf("Key down\n");
655  }
656  else
657  {
658  lineBuffer[lineEndP++] = PS2KBD_RAWKEY_UP;
659  //printf("Key up\n");
660  }
661 
662  lineEndP %= lineSize;
663  lineBuffer[lineEndP++] = currKey;
664  lineEndP %= lineSize;
665  byteCount += 2;
666  //printf("Key %d\n", currKey);
667  }
668  }
669 
670  for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++)
671  {
672  if(lineEndP == (u32)(tempPos - 2))
673  {
674  return;
675  }
676 
677  if(new_[loopKey] != 0)
678  {
679  lineBuffer[lineEndP++] = PS2KBD_RAWKEY_DOWN;
680  lineEndP %= lineSize;
681  lineBuffer[lineEndP++] = new_[loopKey];
682  lineEndP %= lineSize;
683  byteCount += 2;
684  //printf("Key down\nKey %d\n", new_[loopKey]);
685  }
686 
687  }
688 
689  for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++)
690  {
691  if(lineEndP == (u32)(tempPos - 2))
692  {
693  return;
694  }
695 
696  if(old[loopKey] != 0)
697  {
698  lineBuffer[lineEndP++] = PS2KBD_RAWKEY_UP;
699  lineEndP %= lineSize;
700  lineBuffer[lineEndP++] = old[loopKey];
701  lineEndP %= lineSize;
702  byteCount += 2;
703  //printf("Key up\nKey %d\n", old[loopKey]);
704  }
705 
706  }
707 
708  for(loopKey = 0; loopKey < byteCount; loopKey++) /* Signal the sema for the number of bytes read */
709  {
710  SignalSema(bufferSema);
711  }
712 }
713 
714 void ps2kbd_data_recv(int resultCode, int bytes, void *arg)
715 
716 {
717  kbd_dev *dev;
718  int phantom;
719  int loop;
720 
721  if(resultCode != USB_RC_OK)
722  {
723  printf("PS2KEYBOARD: Data Recv set res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
724  return;
725  }
726 
727  //printf("PS2KBD: Data Recv set res %d, bytes %d, arg %p\n", resultCode, bytes, arg);
728 
729  dev = (kbd_dev *) arg;
730  if(dev == NULL)
731  {
732  printf("PS2KBD: dev == NULL\n");
733  return;
734  }
735 
736 /* printf("PS2KBD Modifiers %02X, Keys ", dev->data.mod_keys); */
737 /* for(loop = 0; loop < PS2KBD_MAXKEYS; loop++) */
738 /* { */
739 /* printf("%02X ", dev->data.keycodes[loop]); */
740 /* } */
741 /* printf("\n"); */
742 
743  CancelAlarm((void *)ps2kbd_repeathandler, dev); /* Make sure repeat alarm is cancelled */
744 
745  /* Check for phantom states */
746  phantom = 1;
747  for(loop = 0; loop < PS2KBD_MAXKEYS; loop++)
748  {
749  if(dev->data.keycodes[loop] != 1)
750  {
751  phantom = 0;
752  break;
753  }
754  }
755 
756  if(!phantom) /* If not in a phantom state */
757  {
758  u8 uniqueKeys[PS2KBD_MAXKEYS];
759  u8 missingKeys[PS2KBD_MAXKEYS];
760 
761  memset(uniqueKeys, 0, PS2KBD_MAXKEYS);
762  memset(missingKeys, 0, PS2KBD_MAXKEYS);
763  ps2kbd_build_uniquekeys(uniqueKeys, dev->data.keycodes, dev->oldData.keycodes);
764  ps2kbd_build_uniquekeys(missingKeys, dev->oldData.keycodes, dev->data.keycodes);
765  /* Build new and missing key lists */
766 
767 /* printf("Unique keys : "); */
768 /* for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) */
769 /* { */
770 /* printf("%02X ", uniqueKeys[loopKey]); */
771 /* } */
772 /* printf("\n"); */
773 
774 /* printf("Missing keys : "); */
775 /* for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) */
776 /* { */
777 /* printf("%02X ", missingKeys[loopKey]); */
778 /* } */
779 /* printf("\n"); */
780 
781  if(kbd_readmode == PS2KBD_READMODE_NORMAL)
782  {
783  int loopKey;
784  u8 ledStatus;
785 
786  ledStatus = dev->ledStatus;
787  //printf("ledStatus %02X\n", ledStatus);
788 
789  for(loopKey = 0; loopKey < PS2KBD_MAXKEYS; loopKey++) /* Process key codes */
790  {
791  switch(uniqueKeys[loopKey])
792  {
793  case USB_KEYB_NUMLOCK :
794  ledStatus ^= PS2KBD_LED_NUMLOCK;
795  uniqueKeys[loopKey] = 0;
796  break;
797  case USB_KEYB_CAPSLOCK :
798  ledStatus ^= PS2KBD_LED_CAPSLOCK;
799  uniqueKeys[loopKey] = 0;
800  break;
801  case USB_KEYB_SCRLOCK :
802  ledStatus ^= PS2KBD_LED_SCRLOCK;
803  uniqueKeys[loopKey] = 0;
804  break;
805  }
806  }
807 
808  if(ledStatus != dev->ledStatus)
809  {
810  dev->ledStatus = ledStatus & PS2KBD_LED_MASK;
811  //printf("LEDS %02X\n", dev->ledStatus);
812  /* Call Set LEDS */
813  sceUsbdControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_REPORT, 0x200,
814  dev->interfaceNo, 1, &dev->ledStatus, ps2kbd_led_set, arg);
815  }
816 
817  WaitSema(lineSema); /* Make sure no other thread is going to manipulate the buffer */
818  ps2kbd_getkeys(dev->data.mod_keys, dev->ledStatus, uniqueKeys, dev); /* read in remaining keys */
819  SignalSema(lineSema);
820  }
821  else /* RAW Mode */
822  {
823  WaitSema(lineSema);
824  ps2kbd_getkeys_raw(dev->data.mod_keys, dev->oldData.mod_keys, uniqueKeys, missingKeys);
825  SignalSema(lineSema);
826  }
827 
828  memcpy(&dev->oldData, &dev->data, sizeof(kbd_data_recv));
829  }
830 
831  sceUsbdInterruptTransfer(dev->dataEndp, &dev->data, dev->packetSize, ps2kbd_data_recv, arg);
832 }
833 
834 void flushbuffer()
835 
836 {
837  iop_sema_t s;
838 
839  lineStartP = 0;
840  lineEndP = 0;
841  memset(lineBuffer, 0, lineSize);
842 
843  DeleteSema(bufferSema);
844  s.initial = 0;
845  s.max = lineSize;
846  s.option = 0;
847  s.attr = 0;
848  bufferSema = CreateSema(&s); /* Create a sema to maintain status of readable data */
849 
850  if(bufferSema <= 0)
851  {
852  printf("PS2KBD: Error creating buffer sema\n");
853  }
854 }
855 
856 void ps2kbd_ioctl_setreadmode(u32 readmode)
857 
858 {
859 
860  if(readmode == (u32)kbd_readmode) return;
861 
862  if((readmode == PS2KBD_READMODE_NORMAL) || (readmode == PS2KBD_READMODE_RAW))
863  {
864  int devLoop;
865 
866  /* Reset line buffer */
867  //printf("ioctl_setreadmode %d\n", readmode);
868  for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
869  {
870  CancelAlarm((void *)ps2kbd_repeathandler, devices[devLoop]);
871  }
872 
873  WaitSema(lineSema);
874  kbd_readmode = readmode;
875  flushbuffer();
876  SignalSema(lineSema);
877  }
878 }
879 
880 void ps2kbd_ioctl_setkeymap(kbd_keymap *keymaps)
881 
882 {
883  //printf("ioctl_setkeymap %p\n", keymaps);
884  WaitSema(lineSema); /* Lock the input so you dont end up with weird results */
885  memcpy(keymap, keymaps->keymap, PS2KBD_KEYMAP_SIZE);
886  memcpy(shiftkeymap, keymaps->shiftkeymap, PS2KBD_KEYMAP_SIZE);
887  memcpy(keycap, keymaps->keycap, PS2KBD_KEYMAP_SIZE);
888  SignalSema(lineSema);
889 }
890 
891 void ps2kbd_ioctl_setctrlmap(u8 *ctrlmap)
892 
893 {
894  //printf("ioctl_setctrlmap %p\n", ctrlmap);
895  WaitSema(lineSema);
896  memcpy(control_map, ctrlmap, PS2KBD_KEYMAP_SIZE);
897  SignalSema(lineSema);
898 }
899 
900 void ps2kbd_ioctl_setaltmap(u8 *altmap)
901 
902 {
903  //printf("ioctl_setaltmap %p\n", altmap);
904  WaitSema(lineSema);
905  memcpy(alt_map, altmap, PS2KBD_KEYMAP_SIZE);
906  SignalSema(lineSema);
907 }
908 
909 void ps2kbd_ioctl_setspecialmap(u8 *special)
910 
911 {
912  //printf("ioctl_setspecialmap %p\n", special);
913  WaitSema(lineSema);
914  memcpy(special_keys, special, PS2KBD_KEYMAP_SIZE);
915  SignalSema(lineSema);
916 }
917 
918 void ps2kbd_ioctl_resetkeymap()
919  /* Reset keymap to default US variety */
920 
921 {
922  //printf("ioctl_resetkeymap()\n");
923  WaitSema(lineSema);
924  memcpy(keymap, us_keymap, PS2KBD_KEYMAP_SIZE);
925  memcpy(shiftkeymap, us_shiftkeymap, PS2KBD_KEYMAP_SIZE);
926  memcpy(keycap, us_keycap, PS2KBD_KEYMAP_SIZE);
927  memcpy(special_keys, us_special_keys, PS2KBD_KEYMAP_SIZE);
928  memcpy(control_map, us_control_map, PS2KBD_KEYMAP_SIZE);
929  memcpy(alt_map, us_alt_map, PS2KBD_KEYMAP_SIZE);
930  SignalSema(lineSema);
931 }
932 
933 void ps2kbd_ioctl_flushbuffer()
934  /* Flush the internal buffer */
935 
936 {
937  //printf("ioctl_flushbuffer()\n");
938  WaitSema(lineSema);
939  flushbuffer();
940  SignalSema(lineSema);
941 }
942 
943 void ps2kbd_ioctl_setleds(u8 ledStatus)
944 
945 {
946  int devLoop;
947  kbd_dev *dev;
948 
949  //printf("ioctl_setleds %d\n", ledStatus);
950  ledStatus &= PS2KBD_LED_MASK;
951  for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
952  {
953  dev = devices[devLoop];
954  if(dev)
955  {
956  if(ledStatus != dev->ledStatus)
957  {
958  dev->ledStatus = ledStatus & PS2KBD_LED_MASK;
959  sceUsbdControlTransfer(dev->configEndp, 0x21, USB_REQ_SET_REPORT, 0x200,
960  dev->interfaceNo, 1, &dev->ledStatus, ps2kbd_led_set, dev);
961  }
962  }
963  }
964 }
965 
966 void ps2kbd_ioctl_setblockmode(u32 blockmode)
967 
968 {
969  if((blockmode == PS2KBD_BLOCKING) || (blockmode == PS2KBD_NONBLOCKING))
970  {
971  kbd_blocking = blockmode;
972  //printf("ioctl_setblockmode %d\n", blockmode);
973  }
974 }
975 
976 void ps2kbd_ioctl_setrepeatrate(u32 rate)
977 
978 {
979  kbd_repeatrate = rate;
980 }
981 
982 int fio_init(iop_device_t *driver)
983 {
984  (void)driver;
985 
986  //printf("fio_init()\n");
987  return 0;
988 }
989 
990 int fio_format(iop_file_t *f)
991 {
992  (void)f;
993 
994  //printf("fio_format()\n");
995  return 0;
996 }
997 
998 int fio_open(iop_file_t *f, const char *name, int mode)
999 {
1000  (void)f;
1001  (void)mode;
1002 
1003  //printf("fio_open() %s %d\n", name, mode);
1004  if(strcmp(name, PS2KBD_KBDFILE)) /* If not the keyboard file */
1005  {
1006  return -EPERM;
1007  }
1008 
1009  return 0;
1010 }
1011 
1012 int fio_read(iop_file_t *f, void *buf, int size)
1013 
1014 {
1015  int count = 0;
1016  char *data = (char *) buf;
1017  int ret;
1018 
1019  (void)f;
1020 
1021  //printf("fio_read() %p %d\n", buf, size);
1022 
1023  if(kbd_readmode == PS2KBD_READMODE_RAW)
1024  {
1025  size &= ~1; /* Ensure size of a multiple of 2 */
1026  }
1027 
1028  ret = PollSema(bufferSema);
1029  if(ret < 0)
1030  {
1031  if((ret == SEMA_ZERO) && (kbd_blocking == PS2KBD_BLOCKING))
1032  {
1033  //printf("Blocking\n");
1034  ret = WaitSema(bufferSema);
1035  if(ret < 0) /* Means either an error or the sema was deleted from under us */
1036  {
1037  return 0;
1038  }
1039  }
1040  else
1041  {
1042  return 0;
1043  }
1044  }
1045 
1046  SignalSema(bufferSema);
1047  ret = WaitSema(lineSema);
1048  if(ret < 0) return 0;
1049 
1050  while((count < size) && (lineStartP != lineEndP))
1051  {
1052  data[count] = lineBuffer[lineStartP++];
1053  lineStartP %= lineSize;
1054  count++;
1055  PollSema(bufferSema); /* Take off one count from the sema */
1056  }
1057 
1058  SignalSema(lineSema);
1059 /* //printf("read %d bytes\n", count); */
1060 /* { */
1061 /* struct t_sema_status s; */
1062 
1063 /* ReferSemaStatus(bufferSema, &s); */
1064 /* //printf("Sema count %d\n", s.curr_count); */
1065 /* } */
1066 
1067  return count;
1068 }
1069 
1070 int fio_ioctl(iop_file_t *f, int cmd, void *param)
1071 
1072 {
1073  (void)f;
1074 
1075  //printf("fio_ioctl() %ld %d\n", cmd, *((u32 *) param));
1076  switch(cmd)
1077  {
1078  case PS2KBD_IOCTL_SETREADMODE: ps2kbd_ioctl_setreadmode(*((u32 *) param));
1079  break;
1080  case PS2KBD_IOCTL_SETKEYMAP: ps2kbd_ioctl_setkeymap((kbd_keymap *) param);
1081  break;
1082  case PS2KBD_IOCTL_SETALTMAP: ps2kbd_ioctl_setaltmap((u8 *) param);
1083  break;
1084  case PS2KBD_IOCTL_SETCTRLMAP: ps2kbd_ioctl_setctrlmap((u8 *) param);
1085  break;
1086  case PS2KBD_IOCTL_SETSPECIALMAP: ps2kbd_ioctl_setspecialmap((u8 *) param);
1087  break;
1088  case PS2KBD_IOCTL_FLUSHBUFFER: ps2kbd_ioctl_flushbuffer();
1089  break;
1090  case PS2KBD_IOCTL_SETLEDS: ps2kbd_ioctl_setleds(*(u8*) param);
1091  break;
1092  case PS2KBD_IOCTL_SETBLOCKMODE: ps2kbd_ioctl_setblockmode(*(u32 *) param);
1093  break;
1094  case PS2KBD_IOCTL_RESETKEYMAP: ps2kbd_ioctl_resetkeymap();
1095  break;
1096  case PS2KBD_IOCTL_SETREPEATRATE: ps2kbd_ioctl_setrepeatrate(*(u32 *) param);
1097  break;
1098  default : return -EPERM;
1099  }
1100 
1101  return 0;
1102 }
1103 
1104 int fio_close(iop_file_t *f)
1105 
1106 {
1107  (void)f;
1108 
1109  //printf("fio_close()\n");
1110  return 0;
1111 }
1112 
1113 IOMAN_RETURN_VALUE_IMPL(0);
1114 IOMAN_RETURN_VALUE_IMPL(EIO);
1115 
1116 static iop_device_ops_t fio_ops =
1117 
1118  {
1119  &fio_init, // init
1120  IOMAN_RETURN_VALUE(0), // deinit
1121  &fio_format, // format
1122  &fio_open, // open
1123  &fio_close, // close
1124  &fio_read, // read
1125  IOMAN_RETURN_VALUE(EIO), // write
1126  IOMAN_RETURN_VALUE(EIO), // lseek
1127  &fio_ioctl, // ioctl
1128  IOMAN_RETURN_VALUE(EIO), // remove
1129  IOMAN_RETURN_VALUE(EIO), // mkdir
1130  IOMAN_RETURN_VALUE(EIO), // rmdir
1131  IOMAN_RETURN_VALUE(EIO), // dopen
1132  IOMAN_RETURN_VALUE(EIO), // dclose
1133  IOMAN_RETURN_VALUE(EIO), // dread
1134  IOMAN_RETURN_VALUE(EIO), // getstat
1135  IOMAN_RETURN_VALUE(EIO), // chstat
1136  };
1137 
1138 static iop_device_t kbd_filedrv = {
1139  PS2KBD_FSNAME,
1140  IOP_DT_CHAR,
1141  0,
1142  "USB Keyboard FIO driver",
1143  &fio_ops,
1144 };
1145 
1146 
1147 int init_fio()
1148 
1149 {
1150  return AddDrv(&kbd_filedrv);
1151 }
1152 
1153 void repeat_thread(void *arg)
1154 
1155 {
1156  u32 eventmask;
1157  int devLoop;
1158 
1159  (void)arg;
1160 
1161  for(;;)
1162  {
1163  WaitEventFlag(eventid, 0xFFFFFFFF, 0x01 | 0x10, &eventmask);
1164  //printf("Recieved event %08X\n", eventmask);
1165  for(devLoop = 0; devLoop < PS2KBD_MAXDEV; devLoop++)
1166  {
1167  if((eventmask & (1 << devLoop)) && (devices[devLoop]))
1168  {
1169  int tempPos = 0;
1170 
1171  WaitSema(lineSema);
1172  if(lineStartP < lineEndP)
1173  {
1174  tempPos = lineStartP + lineSize;
1175  }
1176  else
1177  {
1178  tempPos = lineStartP;
1179  }
1180 
1181  if((devices[devLoop]->repeatkeys[0]) && (devices[devLoop]->repeatkeys[1]))
1182  {
1183  if(lineEndP != (u32)(tempPos - 2))
1184  {
1185  lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[0];
1186  lineEndP %= lineSize;
1187  lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[1];
1188  lineEndP %= lineSize;
1189  SignalSema(bufferSema);
1190  SignalSema(bufferSema);
1191  }
1192  }
1193  else if(devices[devLoop]->repeatkeys[0])
1194  {
1195  if(lineEndP != (u32)(tempPos - 1))
1196  {
1197  lineBuffer[lineEndP++] = devices[devLoop]->repeatkeys[0];
1198  lineEndP %= lineSize;
1199  SignalSema(bufferSema);
1200  }
1201  }
1202 
1203  SignalSema(lineSema);
1204  }
1205  }
1206  }
1207 }
1208 
1209 int init_repeatthread()
1210  /* Creates a thread to handle key repeats */
1211 
1212 {
1213  iop_thread_t param;
1215 
1216  event.attr = 0;
1217  event.option = 0;
1218  event.bits = 0;
1219  eventid = CreateEventFlag(&event);
1220 
1221  param.attr = TH_C;
1222  param.thread = repeat_thread;
1223  param.priority = 40;
1224  param.stacksize = 0x800;
1225  param.option = 0;
1226 
1227  repeat_tid = CreateThread(&param);
1228  if (repeat_tid > 0) {
1229  StartThread(repeat_tid, 0);
1230  return 0;
1231  }
1232  else
1233  {
1234  return 1;
1235  }
1236 }
1237 
1238 int ps2kbd_init()
1239 
1240 {
1241  int ret;
1242  iop_sema_t s;
1243 
1244  s.initial = 1;
1245  s.max = 1;
1246  s.option = 0;
1247  s.attr = 0;
1248  lineSema = CreateSema(&s);
1249  if(lineSema <= 0)
1250  {
1251  printf("PS2KBD: Error creating sema\n");
1252  return 1;
1253  }
1254 
1255  s.initial = 0;
1256  s.max = PS2KBD_DEFLINELEN;
1257  s.option = 0;
1258  s.attr = 0;
1259  bufferSema = CreateSema(&s); /* Create a sema to maintain status of readable data */
1260  if(bufferSema <= 0)
1261  {
1262  printf("PS2KBD: Error creating buffer sema\n");
1263  return 1;
1264  }
1265 
1266  lineBuffer = (u8 *) AllocSysMemory(0, PS2KBD_DEFLINELEN, NULL);
1267  if(lineBuffer == NULL)
1268  {
1269  printf("PS2KBD: Error allocating line buffer\n");
1270  return 1;
1271  }
1272  lineStartP = 0;
1273  lineEndP = 0;
1274  lineSize = PS2KBD_DEFLINELEN;
1275  memset(lineBuffer, 0, PS2KBD_DEFLINELEN);
1276 
1277  memset(devices, 0, sizeof(kbd_dev *) * PS2KBD_MAXDEV);
1278  dev_count = 0;
1279  kbd_blocking = PS2KBD_NONBLOCKING;
1280  kbd_readmode = PS2KBD_READMODE_NORMAL;
1281  kbd_repeatrate = PS2KBD_DEFREPEATRATE;
1282  memcpy(keymap, us_keymap, PS2KBD_KEYMAP_SIZE);
1283  memcpy(shiftkeymap, us_shiftkeymap, PS2KBD_KEYMAP_SIZE);
1284  memcpy(keycap, us_keycap, PS2KBD_KEYMAP_SIZE);
1285  memcpy(special_keys, us_special_keys, PS2KBD_KEYMAP_SIZE);
1286  memcpy(control_map, us_control_map, PS2KBD_KEYMAP_SIZE);
1287  memcpy(alt_map, us_alt_map, PS2KBD_KEYMAP_SIZE);
1288 
1289  ret = init_fio();
1290  if(ret < 0)
1291  {
1292  printf("PS2KBD: Error adding ioman driver\n");
1293  return 1;
1294  }
1295  //printf("ps2kbd AddDrv [%d]\n", ret);
1296  init_repeatthread();
1297 
1298  ret = sceUsbdRegisterLdd(&kbd_driver);
1299  if(ret != USB_RC_OK)
1300  {
1301  printf("PS2KBD: Error registering USB devices\n");
1302  return 1;
1303  }
1304 
1305  //printf("sceUsbdRegisterLdd %d\n", ret);
1306 
1307  return 0;
1308 }
UsbDeviceDescriptor
Definition: usbd.h:63
PS2KBD_IOCTL_RESETKEYMAP
#define PS2KBD_IOCTL_RESETKEYMAP
Definition: ps2kbd.h:101
USB_RC_OK
#define USB_RC_OK
Definition: usbd.h:238
_keyb_dev::interfaceNo
int interfaceNo
Definition: ps2kbd.c:86
thbase.h
iop_sema_t
Definition: thsemap.h:38
sysclib.h
PS2KBD_IOCTL_SETCTRLMAP
#define PS2KBD_IOCTL_SETCTRLMAP
Definition: ps2kbd.h:91
EPERM
#define EPERM
Definition: errno.h:21
_UsbDriver
Definition: usbd.h:47
event
Definition: thcommon.h:71
EIO
#define EIO
Definition: errno.h:29
loadcore.h
shiftkeymap
u8 shiftkeymap[PS2KBD_KEYMAP_SIZE]
Definition: ps2kbd.c:113
UsbEndpointDescriptor
Definition: usbd.h:108
PS2KBD_IOCTL_SETALTMAP
#define PS2KBD_IOCTL_SETALTMAP
Definition: ps2kbd.h:93
usbd.h
_keyb_dev
Definition: ps2kbd.c:78
keymap
u8 keymap[PS2KBD_KEYMAP_SIZE]
Definition: ps2kbd.c:111
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
PS2KBD_IOCTL_SETLEDS
#define PS2KBD_IOCTL_SETLEDS
Definition: ps2kbd.h:85
PS2KBD_IOCTL_SETSPECIALMAP
#define PS2KBD_IOCTL_SETSPECIALMAP
Definition: ps2kbd.h:95
thsemap.h
PS2KBD_IOCTL_FLUSHBUFFER
#define PS2KBD_IOCTL_FLUSHBUFFER
Definition: ps2kbd.h:99
PS2KBD_IOCTL_SETKEYMAP
#define PS2KBD_IOCTL_SETKEYMAP
Definition: ps2kbd.h:89
USB_KEYB_NUMLOCK
#define USB_KEYB_NUMLOCK
Definition: ps2kbd.c:51
_keyb_dev::data
kbd_data_recv data
Definition: ps2kbd.c:93
_iop_file
Definition: ioman.h:53
usbd_macro.h
stdio.h
_kbd_keymap
Definition: ps2kbd.h:73
keycap
u8 keycap[PS2KBD_KEYMAP_SIZE]
Definition: ps2kbd.c:115
ioman.h
_iop_thread
Definition: thbase.h:39
devices
kbd_dev * devices[PS2KBD_MAXDEV]
Definition: ps2kbd.c:102
UsbConfigDescriptor
Definition: usbd.h:81
_string_descriptor
Definition: ps2kbd.c:323
PS2KBD_IOCTL_SETREADMODE
#define PS2KBD_IOCTL_SETREADMODE
Definition: ps2kbd.h:83
_iop_device_ops
Definition: ioman.h:79
sysmem.h
PS2KBD_REPEATWAIT
#define PS2KBD_REPEATWAIT
Definition: ps2kbd.c:49
PS2KBD_IOCTL_SETREPEATRATE
#define PS2KBD_IOCTL_SETREPEATRATE
Definition: ps2kbd.h:87
us_keymap.h
_kbd_data_recv
Definition: ps2kbd.c:70
_iop_device
Definition: ioman.h:64
_keyb_dev::ledStatus
u8 ledStatus
Definition: ps2kbd.c:90
UsbInterfaceDescriptor
Definition: usbd.h:95
iop_event_t
Definition: thevent.h:37
thevent.h
PS2KBD_IOCTL_SETBLOCKMODE
#define PS2KBD_IOCTL_SETBLOCKMODE
Definition: ps2kbd.h:97
_iop_sys_clock
Definition: thbase.h:87
errno.h
UsbStringDescriptor
Definition: usbd.h:119