aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/ps2/rpckbd.c
blob: 0bb45208f50e94a50aab463c99c448a5dcfaeac0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*
# _____     ___ ____     ___ ____
#  ____|   |    ____|   |        | |____|
# |     ___|   |____ ___|    ____| |    \    PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright 2005, ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
#
# $Id$
# USB Keyboard Driver for PS2 using RPC instead of FIO
*/

#include <tamtypes.h>
#include <kernel.h>
#include <sifrpc.h>
#include <string.h>
#include "backends/platform/ps2/rpckbd.h"

static int curr_readmode = PS2KBD_READMODE_NORMAL;
static int kbdRpcSema = -1;
static int kbdInitialized = 0;

static SifRpcClientData_t cd0;
static unsigned char rpcBuf[3 * PS2KBD_KEYMAP_SIZE] __attribute__((aligned (16)));
static unsigned int  rpcKey __attribute__((aligned (16)));

int PS2KbdInit(void)
/* Initialise the keyboard library */
{
	int res;
	ee_sema_t kbdSema;

	while ((res = SifBindRpc(&cd0, PS2KBD_RPC_ID, 0)) < 0)
		nopdelay();

	memset(rpcBuf, 0, 3 * PS2KBD_KEYMAP_SIZE);
	rpcKey = 0;

	kbdSema.init_count = 1;
	kbdSema.max_count = 1;

	kbdRpcSema = CreateSema(&kbdSema);
	if (kbdRpcSema >= 0) {
		kbdInitialized = 1;
		return 0;
	} else
		return -1;
}

static void rpcCompleteIntr(void *param) {
    iSignalSema(kbdRpcSema);
}

int PS2KbdRead(char *key)
/* Reads 1 character from the keyboard */
{
	int res;
	if ((!kbdInitialized) || (curr_readmode != PS2KBD_READMODE_NORMAL))
		return -1;

	if (PollSema(kbdRpcSema) >= 0) {
		// last rpc call completed
		res = (rpcKey != 0);
		*key = *(char *)UNCACHED_SEG(&rpcKey);
		SifCallRpc(&cd0, KBD_RPC_READKEY, SIF_RPC_M_NOWAIT, rpcBuf, 0, &rpcKey, 4, rpcCompleteIntr, NULL);
		return res;
	} else // rpc still running
		return 0;
}

int PS2KbdReadRaw(PS2KbdRawKey *key)
/* Reads 1 raw character from the keyboard */
{
	int res;
	if ((!kbdInitialized) || (curr_readmode != PS2KBD_READMODE_RAW))
		return -1;

	if (PollSema(kbdRpcSema) >= 0) {
		// last rpc call completed
		res = (rpcKey != 0);
		*key = *(PS2KbdRawKey *)UNCACHED_SEG(&rpcKey);
		SifCallRpc(&cd0, KBD_RPC_READRAW, SIF_RPC_M_NOWAIT, rpcBuf, 0, &rpcKey, 4, rpcCompleteIntr, NULL);
		return res;
	} else // rpc still running
		return 0;
}

int PS2KbdSetReadmode(u32 readmode)
/* Sets the read mode to normal or raw */
{
	if (kbdInitialized) {
		if (curr_readmode == readmode)
			return 0;
		WaitSema(kbdRpcSema);
		*(unsigned int *)rpcBuf = curr_readmode = readmode;
		return SifCallRpc(&cd0, KBD_RPC_SETREADMODE, SIF_RPC_M_NOWAIT, rpcBuf, 4, rpcBuf, 0, rpcCompleteIntr, NULL);
	} else
		return -1;
}

int PS2KbdSetLeds(u8 leds)
/* Sets all connected keyboards leds */
{
	if (kbdInitialized) {
		WaitSema(kbdRpcSema);
		*(unsigned char *)rpcBuf = leds;
		return SifCallRpc(&cd0, KBD_RPC_SETLEDS, SIF_RPC_M_NOWAIT, rpcBuf, 4, rpcBuf, 0, rpcCompleteIntr, NULL);
	} else
		return -1;
}

int PS2KbdSetKeymap(PS2KbdKeyMap *keymaps)
/* Sets the current keymap */
{
	if (kbdInitialized) {
		WaitSema(kbdRpcSema);
		memcpy(rpcBuf + 0 * PS2KBD_KEYMAP_SIZE, keymaps->keymap,      PS2KBD_KEYMAP_SIZE);
		memcpy(rpcBuf + 1 * PS2KBD_KEYMAP_SIZE, keymaps->shiftkeymap, PS2KBD_KEYMAP_SIZE);
		memcpy(rpcBuf + 2 * PS2KBD_KEYMAP_SIZE, keymaps->keycap,      PS2KBD_KEYMAP_SIZE);
		return SifCallRpc(&cd0, KBD_RPC_SETKEYMAP, SIF_RPC_M_NOWAIT, rpcBuf, 3 * PS2KBD_KEYMAP_SIZE, rpcBuf, 0, rpcCompleteIntr, NULL);
	} else
		return -1;
}

int PS2KbdSetCtrlmap(u8 *ctrlmap)
/* Sets the control key mappings */
{
	if (kbdInitialized) {
		WaitSema(kbdRpcSema);
		memcpy(rpcBuf, ctrlmap, PS2KBD_KEYMAP_SIZE);
		return SifCallRpc(&cd0, KBD_RPC_SETCTRLMAP, SIF_RPC_M_NOWAIT, rpcBuf, PS2KBD_KEYMAP_SIZE, rpcBuf, 0, rpcCompleteIntr, NULL);
	} else
		return -1;
}

int PS2KbdSetAltmap(u8 *altmap)
/* Sets the alt key mappings */
{
	if (kbdInitialized) {
		WaitSema(kbdRpcSema);
		memcpy(rpcBuf, altmap, PS2KBD_KEYMAP_SIZE);
		return SifCallRpc(&cd0, KBD_RPC_SETALTMAP, SIF_RPC_M_NOWAIT, rpcBuf, PS2KBD_KEYMAP_SIZE, rpcBuf, 0, rpcCompleteIntr, NULL);
	} else
		return -1;
}

int PS2KbdSetSpecialmap(u8 *special)
/* Sets the special key mappings */
{
	if (kbdInitialized) {
		WaitSema(kbdRpcSema);
		memcpy(rpcBuf, special, PS2KBD_KEYMAP_SIZE);
		return SifCallRpc(&cd0, KBD_RPC_SETSPECIALMAP, SIF_RPC_M_NOWAIT, rpcBuf, PS2KBD_KEYMAP_SIZE, rpcBuf, 0, rpcCompleteIntr, NULL);
	} else
		return -1;
}

int PS2KbdFlushBuffer(void)
/* Flushes the keyboard buffer */
{
	if (kbdInitialized) {
		WaitSema(kbdRpcSema);
		return SifCallRpc(&cd0, KBD_RPC_FLUSHBUFFER, SIF_RPC_M_NOWAIT, rpcBuf, 0, rpcBuf, 0, rpcCompleteIntr, NULL);
	} else
		return -1;
}

int PS2KbdResetKeymap(void)
/* Resets the keymap to the default US mapping */
{
	if (kbdInitialized) {
		WaitSema(kbdRpcSema);
		return SifCallRpc(&cd0, KBD_RPC_RESETKEYMAP, SIF_RPC_M_NOWAIT, rpcBuf, 0, rpcBuf, 0, rpcCompleteIntr, NULL);
	} else
		return -1;
}