1 /*
2 # _____     ___ ____     ___ ____
3 #  ____|   |    ____|   |        | |____|
4 # |     ___|   |____ ___|    ____| |    \    PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2005, 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 # $Id$
11 # USB Keyboard Driver for PS2 using RPC instead of FIO
12 */
13 
14 #include <tamtypes.h>
15 #include <kernel.h>
16 #include <sifrpc.h>
17 #include <string.h>
18 #include "backends/platform/ps2/rpckbd.h"
19 
20 static unsigned int curr_readmode = PS2KBD_READMODE_NORMAL;
21 static int kbdRpcSema = -1;
22 static int kbdInitialized = 0;
23 
24 static SifRpcClientData_t cd0;
25 static unsigned char rpcBuf[3 * PS2KBD_KEYMAP_SIZE] __attribute__((aligned (16)));
26 static unsigned int  rpcKey __attribute__((aligned (16)));
27 
PS2KbdInit(void)28 int PS2KbdInit(void)
29 /* Initialise the keyboard library */
30 {
31 	int res;
32 	ee_sema_t kbdSema;
33 
34 	while ((res = SifBindRpc(&cd0, PS2KBD_RPC_ID, 0)) < 0)
35 		nopdelay();
36 
37 	memset(rpcBuf, 0, 3 * PS2KBD_KEYMAP_SIZE);
38 	rpcKey = 0;
39 
40 	kbdSema.init_count = 1;
41 	kbdSema.max_count = 1;
42 
43 	kbdRpcSema = CreateSema(&kbdSema);
44 	if (kbdRpcSema >= 0) {
45 		kbdInitialized = 1;
46 		return 0;
47 	} else
48 		return -1;
49 }
50 
rpcCompleteIntr(void * param)51 static void rpcCompleteIntr(void *param) {
52     iSignalSema(kbdRpcSema);
53 }
54 
PS2KbdRead(char * key)55 int PS2KbdRead(char *key)
56 /* Reads 1 character from the keyboard */
57 {
58 	int res;
59 	if ((!kbdInitialized) || (curr_readmode != PS2KBD_READMODE_NORMAL))
60 		return -1;
61 
62 	if (PollSema(kbdRpcSema) >= 0) {
63 		// last rpc call completed
64 		res = (rpcKey != 0);
65 		*key = *(char *)UNCACHED_SEG(&rpcKey);
66 		SifCallRpc(&cd0, KBD_RPC_READKEY, SIF_RPC_M_NOWAIT, rpcBuf, 0, &rpcKey, 4, rpcCompleteIntr, NULL);
67 		return res;
68 	} else // rpc still running
69 		return 0;
70 }
71 
PS2KbdReadRaw(PS2KbdRawKey * key)72 int PS2KbdReadRaw(PS2KbdRawKey *key)
73 /* Reads 1 raw character from the keyboard */
74 {
75 	int res;
76 	if ((!kbdInitialized) || (curr_readmode != PS2KBD_READMODE_RAW))
77 		return -1;
78 
79 	if (PollSema(kbdRpcSema) >= 0) {
80 		// last rpc call completed
81 		res = (rpcKey != 0);
82 		*key = *(PS2KbdRawKey *)UNCACHED_SEG(&rpcKey);
83 		SifCallRpc(&cd0, KBD_RPC_READRAW, SIF_RPC_M_NOWAIT, rpcBuf, 0, &rpcKey, 4, rpcCompleteIntr, NULL);
84 		return res;
85 	} else // rpc still running
86 		return 0;
87 }
88 
PS2KbdSetReadmode(u32 readmode)89 int PS2KbdSetReadmode(u32 readmode)
90 /* Sets the read mode to normal or raw */
91 {
92 	if (kbdInitialized) {
93 		if (curr_readmode == readmode)
94 			return 0;
95 		WaitSema(kbdRpcSema);
96 		*(unsigned int *)rpcBuf = curr_readmode = readmode;
97 		return SifCallRpc(&cd0, KBD_RPC_SETREADMODE, SIF_RPC_M_NOWAIT, rpcBuf, 4, rpcBuf, 0, rpcCompleteIntr, NULL);
98 	} else
99 		return -1;
100 }
101 
PS2KbdSetLeds(u8 leds)102 int PS2KbdSetLeds(u8 leds)
103 /* Sets all connected keyboards leds */
104 {
105 	if (kbdInitialized) {
106 		WaitSema(kbdRpcSema);
107 		*(unsigned char *)rpcBuf = leds;
108 		return SifCallRpc(&cd0, KBD_RPC_SETLEDS, SIF_RPC_M_NOWAIT, rpcBuf, 4, rpcBuf, 0, rpcCompleteIntr, NULL);
109 	} else
110 		return -1;
111 }
112 
PS2KbdSetKeymap(PS2KbdKeyMap * keymaps)113 int PS2KbdSetKeymap(PS2KbdKeyMap *keymaps)
114 /* Sets the current keymap */
115 {
116 	if (kbdInitialized) {
117 		WaitSema(kbdRpcSema);
118 		memcpy(rpcBuf + 0 * PS2KBD_KEYMAP_SIZE, keymaps->keymap,      PS2KBD_KEYMAP_SIZE);
119 		memcpy(rpcBuf + 1 * PS2KBD_KEYMAP_SIZE, keymaps->shiftkeymap, PS2KBD_KEYMAP_SIZE);
120 		memcpy(rpcBuf + 2 * PS2KBD_KEYMAP_SIZE, keymaps->keycap,      PS2KBD_KEYMAP_SIZE);
121 		return SifCallRpc(&cd0, KBD_RPC_SETKEYMAP, SIF_RPC_M_NOWAIT, rpcBuf, 3 * PS2KBD_KEYMAP_SIZE, rpcBuf, 0, rpcCompleteIntr, NULL);
122 	} else
123 		return -1;
124 }
125 
PS2KbdSetCtrlmap(u8 * ctrlmap)126 int PS2KbdSetCtrlmap(u8 *ctrlmap)
127 /* Sets the control key mappings */
128 {
129 	if (kbdInitialized) {
130 		WaitSema(kbdRpcSema);
131 		memcpy(rpcBuf, ctrlmap, PS2KBD_KEYMAP_SIZE);
132 		return SifCallRpc(&cd0, KBD_RPC_SETCTRLMAP, SIF_RPC_M_NOWAIT, rpcBuf, PS2KBD_KEYMAP_SIZE, rpcBuf, 0, rpcCompleteIntr, NULL);
133 	} else
134 		return -1;
135 }
136 
PS2KbdSetAltmap(u8 * altmap)137 int PS2KbdSetAltmap(u8 *altmap)
138 /* Sets the alt key mappings */
139 {
140 	if (kbdInitialized) {
141 		WaitSema(kbdRpcSema);
142 		memcpy(rpcBuf, altmap, PS2KBD_KEYMAP_SIZE);
143 		return SifCallRpc(&cd0, KBD_RPC_SETALTMAP, SIF_RPC_M_NOWAIT, rpcBuf, PS2KBD_KEYMAP_SIZE, rpcBuf, 0, rpcCompleteIntr, NULL);
144 	} else
145 		return -1;
146 }
147 
PS2KbdSetSpecialmap(u8 * special)148 int PS2KbdSetSpecialmap(u8 *special)
149 /* Sets the special key mappings */
150 {
151 	if (kbdInitialized) {
152 		WaitSema(kbdRpcSema);
153 		memcpy(rpcBuf, special, PS2KBD_KEYMAP_SIZE);
154 		return SifCallRpc(&cd0, KBD_RPC_SETSPECIALMAP, SIF_RPC_M_NOWAIT, rpcBuf, PS2KBD_KEYMAP_SIZE, rpcBuf, 0, rpcCompleteIntr, NULL);
155 	} else
156 		return -1;
157 }
158 
PS2KbdFlushBuffer(void)159 int PS2KbdFlushBuffer(void)
160 /* Flushes the keyboard buffer */
161 {
162 	if (kbdInitialized) {
163 		WaitSema(kbdRpcSema);
164 		return SifCallRpc(&cd0, KBD_RPC_FLUSHBUFFER, SIF_RPC_M_NOWAIT, rpcBuf, 0, rpcBuf, 0, rpcCompleteIntr, NULL);
165 	} else
166 		return -1;
167 }
168 
PS2KbdResetKeymap(void)169 int PS2KbdResetKeymap(void)
170 /* Resets the keymap to the default US mapping */
171 {
172 	if (kbdInitialized) {
173 		WaitSema(kbdRpcSema);
174 		return SifCallRpc(&cd0, KBD_RPC_RESETKEYMAP, SIF_RPC_M_NOWAIT, rpcBuf, 0, rpcBuf, 0, rpcCompleteIntr, NULL);
175 	} else
176 		return -1;
177 }
178