PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
dvrdv.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2021-2021, 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
11#include <stdbool.h>
12#include "iomanX.h"
13#include "loadcore.h"
14#include "pvrdrv.h"
15#include "stdio.h"
16#include "thbase.h"
17#include "thsemap.h"
18#include "speedregs.h"
19#include "errno.h"
20
21#define MODNAME "DVRDV"
22#ifdef DEBUG
23#define DPRINTF(x...) printf(MODNAME ": " x)
24#else
25#define DPRINTF(x...)
26#endif
27
28extern int module_start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi);
29extern int module_stop(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi);
30extern int dvrdv_df_init(iomanX_iop_device_t *dev);
31extern int dvrdv_df_exit(iomanX_iop_device_t *dev);
32extern int dvrdv_df_ioctl(iomanX_iop_file_t *f, int cmd, void *param);
33extern int dvrdv_df_devctl(iomanX_iop_file_t *a1, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
34extern int dvrdv_df_ioctl2(iomanX_iop_file_t *f, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
35extern int dvrioctl2_dv_dubb_start(iomanX_iop_file_t *a1, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
36extern int dvrioctl2_dv_dubb_stop(iomanX_iop_file_t *a1, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
37extern int dvrioctl2_dv_dubb_rec_start(iomanX_iop_file_t *a1, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
38extern int dvrioctl2_dv_dubb_rec_stop(iomanX_iop_file_t *a1, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
39extern int dvrioctl2_get_dvcam_info(iomanX_iop_file_t *a1, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
40extern int dvrioctl2_get_dvcam_name(iomanX_iop_file_t *a1, const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen);
41
42struct DevctlCmdTbl_t
43{
44 u16 cmd;
45 int (*fn)(iomanX_iop_file_t *, const char *, int, void *, unsigned int, void *, unsigned int);
46} DevctlCmdTbl[6] =
47 {
48 {0x5601, &dvrioctl2_dv_dubb_start},
49 {0x5602, &dvrioctl2_dv_dubb_stop},
50 {0x5603, &dvrioctl2_dv_dubb_rec_start},
51 {0x5604, &dvrioctl2_dv_dubb_rec_stop},
52 {0x5607, &dvrioctl2_get_dvcam_info},
53 {0x5608, &dvrioctl2_get_dvcam_name},
54};
55
56IOMANX_RETURN_VALUE_IMPL(EUNSUP);
57
58static iomanX_iop_device_ops_t DvrFuncTbl =
59 {
60 &dvrdv_df_init, // init
61 &dvrdv_df_exit, // deinit
62 IOMANX_RETURN_VALUE(EUNSUP), // format
63 IOMANX_RETURN_VALUE(EUNSUP), // open
64 IOMANX_RETURN_VALUE(EUNSUP), // close
65 IOMANX_RETURN_VALUE(EUNSUP), // read
66 IOMANX_RETURN_VALUE(EUNSUP), // write
67 IOMANX_RETURN_VALUE(EUNSUP), // lseek
68 &dvrdv_df_ioctl, // ioctl
69 IOMANX_RETURN_VALUE(EUNSUP), // remove
70 IOMANX_RETURN_VALUE(EUNSUP), // mkdir
71 IOMANX_RETURN_VALUE(EUNSUP), // rmdir
72 IOMANX_RETURN_VALUE(EUNSUP), // dopen
73 IOMANX_RETURN_VALUE(EUNSUP), // dclose
74 IOMANX_RETURN_VALUE(EUNSUP), // dread
75 IOMANX_RETURN_VALUE(EUNSUP), // getstat
76 IOMANX_RETURN_VALUE(EUNSUP), // chstat
77 IOMANX_RETURN_VALUE(EUNSUP), // rename
78 IOMANX_RETURN_VALUE(EUNSUP), // chdir
79 IOMANX_RETURN_VALUE(EUNSUP), // sync
80 IOMANX_RETURN_VALUE(EUNSUP), // mount
81 IOMANX_RETURN_VALUE(EUNSUP), // umount
82 IOMANX_RETURN_VALUE_S64(EUNSUP), // lseek64
83 &dvrdv_df_devctl, // devctl
84 IOMANX_RETURN_VALUE(EUNSUP), // symlink
85 IOMANX_RETURN_VALUE(EUNSUP), // readlink
86 &dvrdv_df_ioctl2, // ioctl2
87 };
88static iomanX_iop_device_t DVR = {
89 .name = "dvr_dv",
90 .desc = "Digital Video Recorder DVR task",
91 .type = (IOP_DT_FS | IOP_DT_FSEXT),
92 .ops = &DvrFuncTbl,
93};
94s32 sema_id;
95
96// Based off of DESR / PSX DVR system software version 2.11.
97IRX_ID(MODNAME, 1, 0);
98
99int _start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
100{
101 if (argc >= 0)
102 return module_start(argc, argv, startaddr, mi);
103 else
104 return module_stop(argc, argv, startaddr, mi);
105}
106
107int module_start(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
108{
109 int i;
110
111 (void)argc;
112 (void)argv;
113 (void)startaddr;
114
115 for (i = 0; i < 30000; ++i) {
116 if (((*((vu32 *)0xB0004230)) & 4) != 0)
117 break;
118 DelayThread(1000);
119 }
120 if (i == 30000) {
121 DPRINTF("DVR task of DVRP is not running...\n");
122 return MODULE_NO_RESIDENT_END;
123 } else {
124 if (iomanX_AddDrv(&DVR) != 0)
125 return MODULE_NO_RESIDENT_END;
126 }
127#if 0
128 return MODULE_REMOVABLE_END;
129#else
130 if (mi && ((mi->newflags & 2) != 0))
131 mi->newflags |= 0x10;
132 return MODULE_RESIDENT_END;
133#endif
134}
135
136int module_stop(int argc, char *argv[], void *startaddr, ModuleInfo_t *mi)
137{
138 (void)argc;
139 (void)argv;
140 (void)startaddr;
141 (void)mi;
142
143 if (iomanX_DelDrv(DVR.name) != 0)
144 return MODULE_REMOVABLE_END;
145 return MODULE_NO_RESIDENT_END;
146}
147
148int dvrdv_df_init(iomanX_iop_device_t *dev)
149{
150 int v1;
151 iop_sema_t v3;
152
153 (void)dev;
154
155 v3.attr = 0;
156 v3.initial = 1;
157 v3.max = 1;
158 v3.option = 0;
159 v1 = CreateSema(&v3);
160 if (v1 < 0)
161 return -1;
162 sema_id = v1;
163 return 0;
164}
165
166int dvrdv_df_exit(iomanX_iop_device_t *dev)
167{
168 (void)dev;
169
170 if (DeleteSema(sema_id) != 0)
171 return -1;
172 return 0;
173}
174
175int dvrdv_df_ioctl(iomanX_iop_file_t *f, int cmd, void *param)
176{
177 (void)f;
178 (void)cmd;
179 (void)param;
180
181 WaitSema(sema_id);
182 SignalSema(sema_id);
183 return -EINVAL;
184}
185
186int dvrdv_df_devctl(
188 const char *name,
189 int cmd,
190 void *arg,
191 unsigned int arglen,
192 void *buf,
193 unsigned int buflen)
194{
195 int v10;
196 unsigned int v11;
197 unsigned int v12;
198
199 v10 = 0;
200 v11 = 0;
201 WaitSema(sema_id);
202 v12 = 0;
203 while (DevctlCmdTbl[v12].cmd != cmd) {
204 v12 = ++v11;
205 if (v11 >= sizeof(DevctlCmdTbl) / sizeof(DevctlCmdTbl[0]))
206 goto LABEL_5;
207 }
208 v10 = DevctlCmdTbl[v12].fn(a1, name, cmd, arg, arglen, buf, buflen);
209LABEL_5:
210 if (v11 == sizeof(DevctlCmdTbl) / sizeof(DevctlCmdTbl[0]))
211 v10 = -EINVAL;
212 SignalSema(sema_id);
213 return v10;
214}
215
216int dvrdv_df_ioctl2(
218 int cmd,
219 void *arg,
220 unsigned int arglen,
221 void *buf,
222 unsigned int buflen)
223{
224
225 (void)f;
226 (void)cmd;
227 (void)arg;
228 (void)arglen;
229 (void)buf;
230 (void)buflen;
231
232 WaitSema(sema_id);
233 SignalSema(sema_id);
234 return -EINVAL;
235}
236
237int dvrioctl2_dv_dubb_start(
239 const char *name,
240 int cmd,
241 void *arg,
242 unsigned int arglen,
243 void *buf,
244 unsigned int buflen)
245{
246 int cmdack_err;
247 drvdrv_exec_cmd_ack cmdack;
248
249 (void)a1;
250 (void)name;
251 (void)cmd;
252 (void)arg;
253 (void)arglen;
254 (void)buf;
255 (void)buflen;
256
257 DPRINTF("------------------------------ dv dubb start!!!\n");
258 cmdack.command = 0x4101;
259 cmdack.input_word_count = 0;
260 cmdack_err = DvrdrvExecCmdAck(&cmdack);
261 if (cmdack_err) {
262 DPRINTF("dvrioctl2_dv_dubb_start -> Handshake error!,%d\n", cmdack_err);
263 return -EIO;
264 } else {
265 if (cmdack.ack_status_ack) {
266 DPRINTF("dvrioctl2_dv_dubb_start -> Status error!,%04X\n", cmdack.ack_status_ack);
267 return -EADV;
268 }
269 }
270 return 0;
271}
272
273int dvrioctl2_dv_dubb_stop(
275 const char *name,
276 int cmd,
277 void *arg,
278 unsigned int arglen,
279 void *buf,
280 unsigned int buflen)
281{
282 int cmdack_err;
283 drvdrv_exec_cmd_ack cmdack;
284
285 (void)a1;
286 (void)name;
287 (void)cmd;
288 (void)arg;
289 (void)arglen;
290 (void)buf;
291 (void)buflen;
292
293 DPRINTF("------------------------------ dv dubb stop!!!\n");
294 cmdack.command = 0x4102;
295 cmdack.input_word_count = 0;
296 cmdack_err = DvrdrvExecCmdAck(&cmdack);
297 if (cmdack_err) {
298 DPRINTF("dvrioctl2_dv_dubb_stop -> Handshake error!,%d\n", cmdack_err);
299 return -EIO;
300 } else {
301 if (cmdack.ack_status_ack) {
302 DPRINTF("dvrioctl2_dv_dubb_stop -> Status error!,%04X\n", cmdack.ack_status_ack);
303 return -EADV;
304 }
305 }
306 return 0;
307}
308
309int dvrioctl2_dv_dubb_rec_start(
311 const char *name,
312 int cmd,
313 void *arg,
314 unsigned int arglen,
315 void *buf,
316 unsigned int buflen)
317{
318 int v8;
319 u16 *v9;
320 u16 *v10;
321 int cmdack_err;
322 drvdrv_exec_cmd_ack cmdack;
323
324 (void)a1;
325 (void)name;
326 (void)cmd;
327 (void)arglen;
328 (void)buf;
329 (void)buflen;
330
331 cmdack.command = 0x4103;
332 DPRINTF("------------------------------ dv dubb rec start!!!\n");
333 v8 = 4;
334 v9 = (u16 *)((u8 *)arg + 8);
335 v10 = &cmdack.input_word[4];
336 do {
337 *v10 = *v9;
338 v9 += 1;
339 v8 += 1;
340 v10 += 1;
341 } while (v8 < 7);
342 cmdack.input_word[0] = *((u16 *)arg + 1);
343 cmdack.input_word[1] = *(u16 *)arg;
344 cmdack.input_word[2] = *((u16 *)arg + 3);
345 cmdack.input_word[3] = *((u16 *)arg + 2);
346 cmdack.input_word_count = 7;
347 cmdack_err = DvrdrvExecCmdAck(&cmdack);
348 if (cmdack_err) {
349 DPRINTF("dvrioctl2_dv_dubb_rec_start -> Handshake error!,%d\n", cmdack_err);
350 return -EIO;
351 } else {
352 if (cmdack.ack_status_ack) {
353 DPRINTF("dvrioctl2_dv_dubb_rec_start -> Status error!,%04X\n", cmdack.ack_status_ack);
354 return -EADV;
355 }
356 }
357 return 0;
358}
359
360int dvrioctl2_dv_dubb_rec_stop(
362 const char *name,
363 int cmd,
364 void *arg,
365 unsigned int arglen,
366 void *buf,
367 unsigned int buflen)
368{
369 int cmdack_err;
370 drvdrv_exec_cmd_ack cmdack;
371
372 (void)a1;
373 (void)name;
374 (void)cmd;
375 (void)arg;
376 (void)arglen;
377 (void)buf;
378 (void)buflen;
379
380 DPRINTF("------------------------------ dv dubb rec stop!!!\n");
381 cmdack.command = 0x4104;
382 cmdack.input_word_count = 0;
383 cmdack.timeout = 5000000;
384 cmdack_err = DvrdrvExecCmdAckComp(&cmdack);
385 if (cmdack_err) {
386 DPRINTF("phase %d\n", cmdack.phase);
387 DPRINTF("dvrioctl2_dv_dubb_rec_stop -> Handshake error!,%d\n", cmdack_err);
388 return -EIO;
389 } else {
390 if (cmdack.ack_status_ack) {
391 DPRINTF("phase %d\n", cmdack.phase);
392 DPRINTF("dvrioctl2_dv_dubb_rec_stop -> Status error!,%04X\n", cmdack.ack_status_ack);
393 return -EADV;
394 }
395 }
396 return 0;
397}
398
399int dvrioctl2_get_dvcam_info(
401 const char *name,
402 int cmd,
403 void *arg,
404 unsigned int arglen,
405 void *buf,
406 unsigned int buflen)
407{
408 int cmdack_err;
409 drvdrv_exec_cmd_ack cmdack;
410
411 (void)a1;
412 (void)name;
413 (void)cmd;
414 (void)arg;
415 (void)arglen;
416 (void)buflen;
417
418 cmdack.command = 0x4107;
419 cmdack.input_word_count = 0;
420 cmdack_err = DvrdrvExecCmdAck(&cmdack);
421 if (cmdack_err) {
422 DPRINTF("phase %d\n", cmdack.phase);
423 DPRINTF("dvrioctl2_get_dvcam_info -> Handshake error!,%d\n", cmdack_err);
424 return -EIO;
425 } else {
426 if (cmdack.ack_status_ack) {
427 DPRINTF("dvrioctl2_get_dvcam_info -> Status error!,%04X\n", cmdack.ack_status_ack);
428 return -EADV;
429 } else {
430 u16 *v11;
431 int cpy_cnt;
432 v11 = &cmdack.output_word[0];
433 cpy_cnt = 0;
434 do {
435 cpy_cnt += 1;
436 *(u16 *)buf = *v11;
437 buf = (char *)buf + 2;
438 v11 += 1;
439 } while (cpy_cnt < 4);
440 return 0;
441 }
442 }
443}
444
445int dvrioctl2_get_dvcam_name(
447 const char *name,
448 int cmd,
449 void *arg,
450 unsigned int arglen,
451 void *buf,
452 unsigned int buflen)
453{
454 drvdrv_exec_cmd_ack cmdack;
455
456 (void)name;
457 (void)arg;
458 (void)arglen;
459
460 DPRINTF("dvrioctl2_get_dvcam_name(io=%p, cmd=%d buf=%p, nbyte=%u)\n", a1, cmd, buf, buflen);
461 cmdack.command = 0x4108;
462 cmdack.input_word[0] = 0;
463 cmdack.input_word[1] = 0;
464 cmdack.input_word[2] = (buflen & 0xFFFF0000) >> 16;
465 cmdack.input_word[3] = buflen;
466 cmdack.input_word_count = 4;
467 cmdack.output_buffer = buf;
468 cmdack.timeout = 5000000;
469 if (DvrdrvExecCmdAckDmaRecvComp(&cmdack)) {
470 DPRINTF("dvrioctl2_get_dvcam_name : IO error (phase %d)\n", cmdack.phase);
471 return -EIO;
472 } else {
473 if (cmdack.comp_status) {
474 DPRINTF("dvrioctl2_get_dvcam_name : Complete parameter error (phase %d), %04X\n", cmdack.phase, cmdack.comp_status);
475 return -EIO;
476 }
477 }
478 return 0;
479}
#define EINVAL
Definition errno.h:63
#define EUNSUP
Definition errno.h:117
#define EIO
Definition errno.h:29
#define EADV
Definition errno.h:151
#define IOP_DT_FSEXT
Definition iomanX.h:66
u16 newflags
Definition loadcore.h:36