sdk-core
v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Toggle main menu visibility
Loading...
Searching...
No Matches
tty.c
Go to the documentation of this file.
1
/*
2
# _____ ___ ____ ___ ____
3
# ____| | ____| | | |____|
4
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5
#-----------------------------------------------------------------------
6
# Licenced under Academic Free License version 2.0
7
# Review ps2sdk README & LICENSE files for further details.
8
*/
9
14
15
#include "
kernel.h
"
16
#include "
deci2.h
"
17
18
#define READ_ONCE(x) (*(const volatile typeof(x) *)(&x))
19
#define WRITE_ONCE(x, val) (*(volatile typeof(x) *)(&x) = (val))
20
21
int
ttyinit = 0;
22
23
struct
tty_packet
24
{
25
/* standard deci2 header */
26
u16 length;
27
u16 reserved;
28
u16 protocol;
29
u8 source;
30
u8 destination;
31
32
/* TTYP */
33
u32 ttyp_reserved;
34
char
buf[256];
35
};
36
37
static
struct
tty_packet
wbuf
__attribute__
((aligned(16)));
38
static
struct
tty_packet
rbuf
__attribute__
((aligned(16)));
39
40
struct
tty_queue
41
{
42
u32 read;
43
u32 write;
44
char
buf[256];
45
};
46
47
struct
tinfo
48
{
49
int
socket;
50
int
wlen;
51
int
rlen;
52
int
writing;
53
char
*wptr;
54
char
*rptr;
55
struct
tty_queue
*read_queue;
56
}
tinfo
;
57
58
static
struct
tty_queue
*QueueInit()
59
{
60
static
struct
tty_queue
q;
61
62
q.read = 0;
63
q.write = 0;
64
65
return
&q;
66
}
67
68
/* Attempt at safe spsc fifo without disabling interrupts
69
* User thread spins on QueueEmpty waiting for Handler to push data */
70
71
static
int
QueueEmpty(
struct
tty_queue
*q)
72
{
73
return
READ_ONCE(q->read) == READ_ONCE(q->write);
74
}
75
76
static
void
QueuePush(
struct
tty_queue
*q,
char
c)
77
{
78
int
w = READ_ONCE(q->write);
79
80
q->buf[w & 0xff] = c;
81
WRITE_ONCE(q->write, w + 1);
82
}
83
84
static
char
QueuePop(
struct
tty_queue
*q)
85
{
86
int
r = READ_ONCE(q->read);
87
char
ret;
88
89
ret = q->buf[r & 0xff];
90
WRITE_ONCE(q->read, r + 1);
91
92
return
ret;
93
}
94
95
void
sceTtyHandler(
int
event
,
int
param,
void
*opt)
96
{
97
struct
tinfo
*
tinfo
= opt;
98
struct
tty_packet
*pkt;
99
int
ret;
100
101
switch
(
event
) {
102
case
DECI2_READ:
103
case
DECI2_READ_DONE:
104
if
(param) {
105
ret = sceDeci2ExRecv(
tinfo
->socket,
tinfo
->rptr +
tinfo
->rlen, param);
106
tinfo
->rlen += ret;
107
break
;
108
}
109
110
pkt = (
struct
tty_packet
*)
tinfo
->rptr;
111
if
(pkt->length > offsetof(
struct
tty_packet
, buf)) {
112
for
(
int
i = 0; i < pkt->length - offsetof(
struct
tty_packet
, buf); i++) {
113
QueuePush(
tinfo
->read_queue, pkt->buf[i]);
114
}
115
}
116
117
tinfo
->rlen = 0;
118
break
;
119
case
DECI2_WRITE:
120
ret = sceDeci2ExSend(
tinfo
->socket,
tinfo
->wptr,
tinfo
->wlen);
121
if
(ret < 0) {
122
tinfo
->writing = 0;
123
break
;
124
}
125
126
tinfo
->wptr += ret;
127
tinfo
->wlen -= ret;
128
break
;
129
case
DECI2_WRITE_DONE:
130
tinfo
->writing = 0;
131
break
;
132
}
133
}
134
135
int
sceTtyWrite(
char
*buf,
int
len)
136
{
137
struct
tty_packet
*pkt;
138
int
oldintr, ret, ssize;
139
char
*wp;
140
141
if
(
tinfo
.writing) {
142
return
-1;
143
}
144
145
oldintr = DIntr();
146
147
tinfo
.writing = 1;
148
tinfo
.wptr = UNCACHED_SEG(&wbuf);
149
pkt = UNCACHED_SEG(&wbuf);
150
151
ssize = 0;
152
wp = pkt->buf;
153
for
(ret = 0; ret < len; ret++) {
154
if
(*buf ==
'\n'
) {
155
*wp++ =
'\r'
;
156
ssize++;
157
if
(ssize >= 256)
158
break
;
159
}
160
161
*wp++ = *buf++;
162
ssize++;
163
if
(ssize >= 256)
164
break
;
165
}
166
167
tinfo
.wlen = ssize + offsetof(
struct
tty_packet
, buf);
168
pkt->length =
tinfo
.wlen;
169
if
(sceDeci2ReqSend(
tinfo
.socket, pkt->destination) < 0) {
170
tinfo
.writing = 0;
171
if
(oldintr) {
172
EIntr();
173
}
174
175
return
-1;
176
}
177
178
while
(READ_ONCE(
tinfo
.writing)) {
179
sceDeci2Poll(
tinfo
.socket);
180
}
181
182
if
(oldintr) {
183
EIntr();
184
}
185
186
return
ret;
187
}
188
189
190
int
sceTtyRead(
char
*buf,
int
len)
191
{
192
int
i;
193
194
for
(i = 0; i < len; i++) {
195
while
(QueueEmpty(
tinfo
.read_queue))
196
;
197
198
buf[i] = QueuePop(
tinfo
.read_queue);
199
if
(buf[i] ==
'\n'
|| buf[i] ==
'\r'
) {
200
break
;
201
}
202
}
203
204
return
i;
205
}
206
207
int
sceTtyInit()
208
{
209
struct
tty_packet
*pkt;
210
211
FlushCache(0);
212
tinfo
.socket = sceDeci2Open(0x210, &
tinfo
, sceTtyHandler);
213
if
(
tinfo
.socket < 0) {
214
return
0;
215
}
216
217
tinfo
.writing = 0;
218
tinfo
.wlen = 0;
219
tinfo
.rptr = UNCACHED_SEG(&rbuf);
220
tinfo
.wptr = UNCACHED_SEG(&wbuf);
221
222
pkt = UNCACHED_SEG(&wbuf);
223
pkt->protocol = 0x210;
224
pkt->source =
'E'
;
225
pkt->destination =
'H'
;
226
227
pkt->reserved = 0;
228
pkt->ttyp_reserved = 0;
229
230
tinfo
.read_queue = QueueInit();
231
232
return
1;
233
}
deci2.h
kernel.h
__attribute__
Definition
gif_registers.h:40
event
Definition
thcommon.h:76
tinfo
Definition
tty.c:48
tty_packet
Definition
tty.c:24
tty_queue
Definition
tty.c:41
core
kernel
src
tty.c
Generated by
1.18.0