PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
udptty.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright (c) 2003 Marcus R. Brown <mrbrown@0xd6.org>
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9#
10# $Id: tty.c 629 2004-10-11 00:45:00Z mrbrown $
11# TTY filesystem for UDPTTY.
12
13 modified by jimmikaelkael <jimmikaelkael@wanadoo.fr>
14
15*/
16
17#include <tamtypes.h>
18#include <loadcore.h>
19#include <stdio.h>
20#include <thsemap.h>
21#include <ioman.h>
22#include <intrman.h>
23#include <sysclib.h>
24#include <sysmem.h>
25#include <thbase.h>
26#include <thevent.h>
27#include <ps2ip.h>
28#include <errno.h>
29
30#define MODNAME "udptty"
31IRX_ID(MODNAME, 2, 1);
32
33extern struct irx_export_table _exp_udptty;
34
35#define DEVNAME "tty"
36
37static int udp_socket;
38static int tty_sema = -1;
39
40static int tty_init(iop_device_t *device);
41static int tty_deinit(iop_device_t *device);
42static int tty_stdout_fd(void);
43static int tty_write(iop_file_t *file, void *buf, size_t size);
44
45IOMAN_RETURN_VALUE_IMPL(EIO);
46
47/* device ops */
48static iop_device_ops_t tty_ops = {
49 &tty_init, // init
50 &tty_deinit, // deinit
51 IOMAN_RETURN_VALUE(EIO), // format
52 (void *)&tty_stdout_fd, // open
53 (void *)&tty_stdout_fd, // close
54 IOMAN_RETURN_VALUE(EIO), // read
55 (void *)&tty_write, // write
56 IOMAN_RETURN_VALUE(EIO), // lseek
57 IOMAN_RETURN_VALUE(EIO), // ioctl
58 IOMAN_RETURN_VALUE(EIO), // remove
59 IOMAN_RETURN_VALUE(EIO), // mkdir
60 IOMAN_RETURN_VALUE(EIO), // rmdir
61 IOMAN_RETURN_VALUE(EIO), // dopen
62 IOMAN_RETURN_VALUE(EIO), // dclose
63 IOMAN_RETURN_VALUE(EIO), // dread
64 IOMAN_RETURN_VALUE(EIO), // getstat
65 IOMAN_RETURN_VALUE(EIO), // chstat
66};
67
68/* device descriptor */
69static iop_device_t tty_device = {
70 DEVNAME,
71 IOP_DT_CHAR | IOP_DT_CONS,
72 1,
73 "TTY via SMAP UDP",
74 &tty_ops,
75};
76
77
78/* KPRTTY */
79#ifdef KPRTTY
80#define PRNT_IO_BEGIN 0x200
81#define PRNT_IO_END 0x201
82
83typedef struct _KprArg
84{
85 int eflag;
86 int bsize;
87 char *kpbuf;
88 int prpos;
89 int calls;
90} KprArg;
91
92static KprArg g_kprarg;
93
94#define KPR_BUFFER_SIZE 0x1000
95static char kprbuffer[KPR_BUFFER_SIZE];
96
97static void PrntFunc(void *context, int chr)
98{
99 KprArg *kpa = (KprArg *)context;
100
101 switch (chr) {
102 case 0:
103 break;
104 case PRNT_IO_BEGIN:
105 kpa->calls++;
106 break;
107 case PRNT_IO_END:
108 break;
109 case '\n':
110 PrntFunc(context, '\r');
111 default:
112 if (kpa->prpos < kpa->bsize)
113 kpa->kpbuf[kpa->prpos++] = chr;
114 break;
115 }
116}
117
118static int Kprnt(void *context, const char *format, void *arg)
119{
120 if (format)
121 prnt(PrntFunc, context, format, arg);
122
123 return 0;
124}
125
126static int Kprintf_Handler(void *context, const char *format, va_list ap)
127{
128 KprArg *kpa = (KprArg *)context;
129 int res;
130
131 res = CpuInvokeInKmode(Kprnt, kpa, format, ap);
132
133 if (QueryIntrContext())
134 iSetEventFlag(kpa->eflag, 1);
135 else
136 SetEventFlag(kpa->eflag, 1);
137
138 return res;
139}
140
141static void KPRTTY_Thread(void *args)
142{
143 u32 flags;
144 KprArg *kpa = (KprArg *)args;
145
146 while (1) {
147 WaitEventFlag(kpa->eflag, 1, WEF_AND | WEF_CLEAR, &flags);
148
149 if (kpa->prpos) {
150 write(1, kpa->kpbuf, kpa->prpos);
151 kpa->prpos = 0;
152 }
153 }
154}
155
156static void kprtty_init(void)
157{
158 iop_event_t efp;
159 iop_thread_t thp;
160 KprArg *kpa;
161 int thid;
162
163 kpa = &g_kprarg;
164
165 efp.attr = EA_SINGLE;
166 efp.option = 0;
167 efp.bits = 0;
168
169 thp.attr = TH_C;
170 thp.option = 0;
171 thp.thread = &KPRTTY_Thread;
172 thp.stacksize = 0x800;
173 thp.priority = 8;
174
175 kpa->eflag = CreateEventFlag(&efp);
176 kpa->bsize = KPR_BUFFER_SIZE;
177 kpa->kpbuf = kprbuffer;
178 kpa->prpos = 0;
179 kpa->calls = 0;
180
181 thid = CreateThread(&thp);
182 StartThread(thid, (void *)kpa);
183
184 KprintfSet(&Kprintf_Handler, kpa);
185}
186#endif
187
188int _start(int argc, char *argv[])
189{
190 (void)argc;
191 (void)argv;
192
193 // register exports
194 RegisterLibraryEntries(&_exp_udptty);
195
196 // create the socket
197 udp_socket = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
198 if (udp_socket < 0)
199 return MODULE_NO_RESIDENT_END;
200
201 DelDrv(tty_device.name);
202
203 if (AddDrv(&tty_device) < 0)
204 return MODULE_NO_RESIDENT_END;
205
206 close(0);
207 open(DEVNAME "00:", 0x1000 | O_RDWR);
208
209 close(1);
210 open(DEVNAME "00:", O_WRONLY);
211
212 close(2);
213 open(DEVNAME "00:", O_WRONLY);
214
215 printf("UDPTTY loaded!\n");
216
217#ifdef KPRTTY
218 kprtty_init();
219 printf("KPRTTY enabled!\n");
220#endif
221
222 return MODULE_RESIDENT_END;
223}
224
225int _shutdown()
226{
227 lwip_close(udp_socket);
228
229 return 0;
230}
231
232/* Copy the data into place, calculate the various checksums, and send the
233 final packet. */
234static int udp_send(void *buf, size_t size)
235{
236 struct sockaddr_in peer;
237
238 peer.sin_family = AF_INET;
239 peer.sin_port = htons(18194);
240 peer.sin_addr.s_addr = inet_addr("255.255.255.255");
241
242 lwip_sendto(udp_socket, buf, size, 0, (struct sockaddr *)&peer, sizeof(peer));
243
244 return 0;
245}
246
247/* TTY driver. */
248
249static int tty_init(iop_device_t *device)
250{
251 (void)device;
252
253 if ((tty_sema = CreateMutex(IOP_MUTEX_UNLOCKED)) < 0)
254 return -1;
255
256 return 0;
257}
258
259static int tty_deinit(iop_device_t *device)
260{
261 (void)device;
262
263 DeleteSema(tty_sema);
264 return 0;
265}
266
267static int tty_stdout_fd(void)
268{
269 return 1;
270}
271
272static int tty_write(iop_file_t *file, void *buf, size_t size)
273{
274 int res = 0;
275
276 (void)file;
277
278 WaitSema(tty_sema);
279 res = udp_send(buf, size);
280 SignalSema(tty_sema);
281
282 return res;
283}
#define EIO
Definition errno.h:29
int CpuInvokeInKmode(void *function,...)
int QueryIntrContext(void)
#define EA_SINGLE
Definition thevent.h:33