sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
libpad.c
Go to the documentation of this file.
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright 2001-2004, 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
12
12 * @file
13 * Pad library functions
14 * Quite easy rev engineered from util demos..
15 * Find any bugs? Mail me: pukko@home.se
16 */
17
18#include <tamtypes.h>
19#include <kernel.h>
20#include <stdio.h>
21#include <string.h>
22#include <sifrpc.h>
23#include <sifcmd.h>
24#include <iopcontrol.h>
25#include "libpad.h"
26
27/*
28 * Defines
29 */
30
31#define PAD_BIND_RPC_ID1_NEW 0x80000100
32#define PAD_BIND_RPC_ID2_NEW 0x80000101
33
34#define PAD_BIND_RPC_ID1_OLD 0x8000010f
35#define PAD_BIND_RPC_ID2_OLD 0x8000011f
36
37#define PAD_RPCCMD_OPEN_NEW 0x01
38#define PAD_RPCCMD_SET_MMODE_NEW 0x06
39#define PAD_RPCCMD_SET_ACTDIR_NEW 0x07
40#define PAD_RPCCMD_SET_ACTALIGN_NEW 0x08
41#define PAD_RPCCMD_GET_BTNMASK_NEW 0x09
42#define PAD_RPCCMD_SET_BTNINFO_NEW 0x0A
43#define PAD_RPCCMD_SET_VREF_NEW 0x0B
44#define PAD_RPCCMD_GET_PORTMAX_NEW 0x0C
45#define PAD_RPCCMD_GET_SLOTMAX_NEW 0x0D
46#define PAD_RPCCMD_CLOSE_NEW 0x0E
47#define PAD_RPCCMD_END_NEW 0x0F
48#define PAD_RPCCMD_INIT 0x10
49#define PAD_RPCCMD_GET_MODVER 0x12
50
51#define PAD_RPCCMD_OPEN_OLD 0x80000100
52#define PAD_RPCCMD_INFO_ACT 0x80000102
53#define PAD_RPCCMD_INFO_COMB_OLD 0x80000103
54#define PAD_RPCCMD_INFO_MODE 0x80000104
55#define PAD_RPCCMD_SET_MMODE_OLD 0x80000105
56#define PAD_RPCCMD_SET_ACTDIR_OLD 0x80000106
57#define PAD_RPCCMD_SET_ACTALIGN_OLD 0x80000107
58#define PAD_RPCCMD_GET_BTNMASK_OLD 0x80000108
59#define PAD_RPCCMD_SET_BTNINFO_OLD 0x80000109
60#define PAD_RPCCMD_SET_VREF_OLD 0x8000010a
61#define PAD_RPCCMD_GET_PORTMAX_OLD 0x8000010b
62#define PAD_RPCCMD_GET_SLOTMAX_OLD 0x8000010c
63#define PAD_RPCCMD_CLOSE_OLD 0x8000010d
64#define PAD_RPCCMD_END_OLD 0x8000010e
65
66/*
67 * Types
68 */
69
71{
72 u8 data[32];
73 u32 actDirData[2];
74 u32 actAlignData[2];
75 u8 actData[8][4];
76 u16 modeTable[4];
77 u32 frame;
78 u32 findPadRetries;
79 u32 length;
80 u8 modeConfig;
81 u8 modeCurId;
82 u8 model;
83 u8 buttonDataReady;
84 u8 nrOfModes;
85 u8 modeCurOffs;
86 u8 nrOfActuators;
87 u8 numActComb;
88 u8 val_c6;
89 u8 mode;
90 u8 lock;
91 u8 actDirSize;
92 u8 state;
93 u8 reqState;
94 u8 currentTask;
95 u8 runTask;
96 u8 stat70bit;
97 u8 padding[11];
98};
99
100// rom0:padman has only 64 byte of pad data
102{
103 u32 frame;
104 u8 state;
105 u8 reqState;
106 u8 ok;
107 u8 unkn7;
108 u8 data[32];
109 u32 length;
110 u8 request;
112 u8 CTP;
117 u8 errorCount;
118 u8 unk49[15];
119};
120
122{
123 struct pad_data_old oldPadData[2];
124 struct pad_data_new newPadData[2];
125};
126
128{
129 int open;
130 unsigned int port;
131 unsigned int slot;
132 union pad_data_u *padData;
133 unsigned char *padBuf;
134};
135
137{
138 u32 frame;
139 u32 openSlots[2];
140 u8 padding[116];
141};
142
143/*
144 * Pad variables etc.
145 */
146
147static const char *padStateString[] = {
148 "DISCONNECT",
149 "FINDPAD",
150 "FINDCTP1",
151 "",
152 "",
153 "EXECCMD",
154 "STABLE",
155 "ERROR",
156};
157static const char *padReqStateString[] = {
158 "COMPLETE",
159 "FAILED",
160 "BUSY",
161};
162
163static int padInitialised = 0;
164
165// pad rpc call
166static SifRpcClientData_t padsif[2] __attribute__((aligned(64)));
167static union {
168 s32 command;
169 struct {
170 s32 command;
171 s32 unused[3];
172 void *statBuf;
173 } padInitArgs;
174 struct {
175 s32 unknown[3];
176 s32 result;
177 s32 unknown2;
178 void *padBuf;
179 } padOpenResult;
180 struct {
181 s32 unknown[3];
182 s32 result;
183 } padResult;
184 struct {
185 s32 command;
186 s32 port, slot;
187 s32 unknown;
188 void *padArea;
189 } padOpenArgs;
190 struct {
191 s32 command;
192 s32 port, slot;
193 s32 unknown;
194 s32 mode;
195 } padCloseArgs;
196 struct {
197 s32 command;
198 s32 port;
199 } padSlotMaxArgs;
200 struct {
201 s32 command;
202 s32 port, slot;
203 s32 infoMode;
204 s32 index;
205 } padInfoModeArgs;
206 struct {
207 s32 command;
208 s32 port, slot;
209 s32 mode;
210 s32 lock;
211 } padSetMainModeArgs;
212 struct {
213 s32 unknown[5];
214 s32 result;
215 } padModeResult;
216 struct {
217 s32 command;
218 s32 port, slot;
219 } padGetButtonMaskArgs;
220 struct {
221 s32 command;
222 s32 port, slot;
223 s32 buttonInfo;
224 } padSetButtonInfoArgs;
225 struct {
226 s32 unknown[4];
227 s32 result;
228 } padSetButtonInfoResult;
229 struct {
230 s32 command;
231 s32 port, slot;
232 s32 actuator;
233 s32 act_cmd;
234 } padInfoActArgs;
235 struct {
236 s32 command;
237 s32 port, slot;
238 s8 align[6];
239 } padActDirAlignArgs;
240 char buffer[128];
241}
242buffer __attribute__((aligned(64)));
243
245static struct open_slot openSlot[2] __attribute__((aligned(64)));
246static struct pad_state PadState[2][8];
247
248
249/*
250 * Local functions
251 */
252
253static void padCleanup(void)
254{
255 memset(&padsif[0], 0, sizeof(padsif[0]));
256 memset(&padsif[1], 0, sizeof(padsif[1]));
257 padInitialised = 0;
258}
259
261static struct pad_data_new*
262padGetDmaStrNew(int port, int slot)
263{
264 struct pad_data_new *pdata;
265
266 pdata = PadState[port][slot].padData->newPadData;
267 SyncDCache(pdata, (u8 *)pdata + 256);
268
269 return (pdata[0].frame < pdata[1].frame) ? &pdata[1] : &pdata[0];
270}
271
272static struct pad_data_old*
273padGetDmaStrOld(int port, int slot)
274{
275 struct pad_data_old *pdata;
276
277 pdata = PadState[port][slot].padData->oldPadData;
278 SyncDCache(pdata, (u8 *)pdata + 256);
279
280 return (pdata[0].frame < pdata[1].frame) ? &pdata[1] : &pdata[0];
281}
282
287static struct open_slot*
288padGetConnDmaStr(void)
289{
290 SyncDCache(openSlot, (u8*)openSlot + sizeof(openSlot));
291
292 return (openSlot[0].frame < openSlot[1].frame) ? &openSlot[1] : &openSlot[0];
293}
294
295/*
296 * Global functions
297 */
298
299/*
300 * Functions not implemented here
301 * padGetFrameCount() <- dunno if it's useful for someone..
302 * padInfoComb() <- see above
303 * padSetVrefParam() <- dunno
304 */
305
306int
307padInit(int mode)
308{
309 // Version check isn't used by default
310 // int ver;
311 int rpc_init_next;
312
313 if (HasIopRebootedSinceLastCall())
314 padCleanup();
315
316 if (padsif[0].server && padsif[1].server)
317 return 0;
318
319 padInitialised = 0xFFFFFFFF;
320 rpc_init_next = 0;
321
322 padsif[0].server = NULL;
323 padsif[1].server = NULL;
324
325 {
326 unsigned int i;
327 SifRpcClientData_t rpciftmp[2] __attribute__((aligned(64)));
328 static const int rpc_ids[] = {
329 PAD_BIND_RPC_ID1_NEW,
330 PAD_BIND_RPC_ID1_OLD,
331 };
332
333 padsif[0].server = NULL;
334 for (i = 0; i < (sizeof(rpc_ids)/sizeof(rpc_ids[0])); i += 1)
335 rpciftmp[i].server = NULL;
336
337 for (;;)
338 {
339 for (i = 0; i < (sizeof(rpc_ids)/sizeof(rpc_ids[0])); i += 1)
340 {
341 if ((sceSifBindRpc(&rpciftmp[i], rpc_ids[i], 0) < 0))
342 return -1;
343 if (rpciftmp[i].server != NULL)
344 {
345 switch (rpc_ids[i])
346 {
347 case PAD_BIND_RPC_ID1_NEW:
348 {
349 padInitialised = 2;
350 rpc_init_next = PAD_BIND_RPC_ID2_NEW;
351 break;
352 }
353 case PAD_BIND_RPC_ID1_OLD:
354 {
355 padInitialised = 1;
356 rpc_init_next = PAD_BIND_RPC_ID2_OLD;
357 break;
358 }
359 default:
360 break;
361 }
362 memcpy(&padsif[0], &rpciftmp[i], sizeof(padsif[0]));
363 break;
364 }
365 }
366 if (padsif[0].server != NULL)
367 break;
368 nopdelay();
369 }
370 }
371
372 if (!rpc_init_next)
373 return -1;
374
375 while (!padsif[1].server)
376 {
377 if (sceSifBindRpc(&padsif[1], rpc_init_next, 0) < 0)
378 return -3;
379 nopdelay();
380 }
381
382 // If you require a special version of the padman, check for that here (uncomment)
383 // ver = padGetModVersion();
384
385 //At v1.3.4, this used to return 1 (and padPortInit is not used). But we are interested in the better design from release 1.4.
386 return padPortInit(mode);
387}
388
389int padPortInit(int mode)
390{
391 unsigned int i;
392 unsigned int j;
393
394 (void)mode;
395
396 for (i = 0; i < (sizeof(PadState)/sizeof(PadState[0])); i += 1)
397 {
398 for (j = 0; j < (sizeof(PadState[0])/sizeof(PadState[0][0])); j += 1)
399 {
400 PadState[i][j].open = 0;
401 PadState[i][j].port = 0;
402 PadState[i][j].slot = 0;
403 }
404 }
405
406 switch (padInitialised)
407 {
408 case 1:
409 {
410#if 0
411 int ret;
412 //Unofficial: libpad EE client from v1.3.4 has this RPC function implemented, but is not implemented within its PADMAN module.
413 buffer.command = PAD_RPCCMD_OPEN_OLD;
414 ret = sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL);
415#endif
416 return 1;
417 }
418 case 2:
419 {
420 int ret;
421
422 buffer.command = PAD_RPCCMD_INIT;
423 buffer.padInitArgs.statBuf = openSlot;
424 ret = sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL);
425
426 return ret >= 0 ? buffer.padResult.result : 0;
427 }
428 default:
429 return 1;
430 }
431}
432
433int
435{
436 int ret;
437
438 switch (padInitialised)
439 {
440 case 1:
441 {
442 buffer.command = PAD_RPCCMD_END_OLD;
443 break;
444 }
445 case 2:
446 {
447 buffer.command = PAD_RPCCMD_END_NEW;
448 break;
449 }
450 default:
451 return -1;
452 }
453
454 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
455 return -1;
456
457 ret = buffer.padResult.result;
458 if (ret == 1)
459 padCleanup();
460
461 return ret;
462}
463
464int
465padPortOpen(int port, int slot, void *padArea)
466{
467 union pad_data_u *dma_buf = (union pad_data_u *)padArea;
468
469 if ((unsigned int)port >= (sizeof(PadState)/sizeof(PadState[0])))
470 return 0;
471 if ((unsigned int)slot >= (sizeof(PadState[0])/sizeof(PadState[0][0])))
472 return 0;
473
474 switch (padInitialised)
475 {
476 case 1:
477 {
478 // Check 16 byte alignment
479 if ((u32)padArea & 0xf)
480 {
481 printf("Address is not 16-byte aligned.\n");
482 return 0;
483 }
484 break;
485 }
486 case 2:
487 {
488 // Check 64 byte alignment
489 if ((u32)padArea & 0x3f)
490 {
491 printf("Address is not 64-byte aligned.\n");
492 return 0;
493 }
494 break;
495 }
496 default:
497 return 0;
498 }
499
500
501 // Pad data is double buffered
502 switch (padInitialised)
503 {
504 case 1:
505 {
506 unsigned int i;
507
508 for (i = 0; i < (sizeof(dma_buf->oldPadData)/sizeof(dma_buf->oldPadData[0])); i += 1)
509 {
510 struct pad_data_old *pdata;
511
512 pdata = &dma_buf->oldPadData[i];
513 memset(pdata->data, 0xff, sizeof(pdata->data)); // 'Clear' data area
514 pdata->frame = 0;
515 pdata->length = 0;
516 pdata->state = PAD_STATE_EXECCMD;
517 pdata->reqState = PAD_RSTAT_BUSY;
518 pdata->length = 0;
519 pdata->ok = 0;
520 }
521 break;
522 }
523 case 2:
524 {
525 unsigned int i;
526
527 for (i = 0; i < (sizeof(dma_buf->newPadData)/sizeof(dma_buf->newPadData[0])); i += 1)
528 {
529 struct pad_data_new *pdata;
530
531 pdata = &dma_buf->newPadData[i];
532 memset(pdata->data, 0xff, sizeof(pdata->data)); // 'Clear' data area
533 pdata->frame = 0;
534 pdata->length = 0;
535 pdata->state = PAD_STATE_EXECCMD;
536 pdata->reqState = PAD_RSTAT_BUSY;
537 pdata->length = 0;
538 pdata->currentTask = 0;
539 pdata->buttonDataReady = 0; // Should be cleared in newer padman
540 }
541 break;
542 }
543 default:
544 return 0;
545 }
546
547 switch (padInitialised)
548 {
549 case 1:
550 {
551 buffer.command = PAD_RPCCMD_OPEN_OLD;
552 break;
553 }
554 case 2:
555 {
556 buffer.command = PAD_RPCCMD_OPEN_NEW;
557 break;
558 }
559 default:
560 return 0;
561 }
562 buffer.padOpenArgs.port = port;
563 buffer.padOpenArgs.slot = slot;
564 buffer.padOpenArgs.padArea = padArea;
565
566 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
567 return 0;
568
569 PadState[port][slot].open = padInitialised;
570 PadState[port][slot].padData = padArea;
571 PadState[port][slot].padBuf = buffer.padOpenResult.padBuf;
572
573 return buffer.padOpenResult.result;
574}
575
576int
577padPortClose(int port, int slot)
578{
579 int ret;
580
581 if ((unsigned int)port >= (sizeof(PadState)/sizeof(PadState[0])))
582 return -1;
583 if ((unsigned int)slot >= (sizeof(PadState[0])/sizeof(PadState[0][0])))
584 return -1;
585
586 switch (padInitialised)
587 {
588 case 1:
589 {
590 buffer.command = PAD_RPCCMD_CLOSE_OLD;
591 break;
592 }
593 case 2:
594 {
595 buffer.command = PAD_RPCCMD_CLOSE_NEW;
596 break;
597 }
598 default:
599 return -1;
600 }
601
602 buffer.padCloseArgs.port = port;
603 buffer.padCloseArgs.slot = slot;
604 buffer.padCloseArgs.mode = 1;
605
606 ret = sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL);
607
608 if (ret < 0)
609 return ret;
610 PadState[port][slot].open = 0;
611 return buffer.padResult.result;
612}
613
614unsigned char
615padRead(int port, int slot, struct padButtonStatus *data)
616{
617 if ((unsigned int)port >= (sizeof(PadState)/sizeof(PadState[0])))
618 return 0;
619 if ((unsigned int)slot >= (sizeof(PadState[0])/sizeof(PadState[0][0])))
620 return 0;
621
622 switch (PadState[port][slot].open)
623 {
624 case 1:
625 {
626 struct pad_data_old *pdata;
627
628 pdata = padGetDmaStrOld(port, slot);
629
630 memcpy(data, pdata->data, pdata->length);
631 return pdata->length;
632 }
633 case 2:
634 {
635 struct pad_data_new *pdata;
636
637 pdata = padGetDmaStrNew(port, slot);
638
639 memcpy(data, pdata->data, pdata->length);
640 return pdata->length;
641 }
642 default:
643 return 0;
644 }
645}
646
647int
648padGetState(int port, int slot)
649{
650 if ((unsigned int)port >= (sizeof(PadState)/sizeof(PadState[0])))
651 return 0;
652 if ((unsigned int)slot >= (sizeof(PadState[0])/sizeof(PadState[0][0])))
653 return 0;
654
655 switch (PadState[port][slot].open)
656 {
657 case 1:
658 {
659 const struct pad_data_old *pdata;
660 unsigned char state;
661
662 pdata = padGetDmaStrOld(port, slot);
663 state = pdata->state;
664
665 if (state == PAD_STATE_STABLE && padGetReqState(port, slot) == PAD_RSTAT_BUSY) // Ok
666 return PAD_STATE_EXECCMD;
667 return state;
668 }
669 case 2:
670 {
671 const struct pad_data_new *pdata;
672 unsigned char state;
673
674 pdata = padGetDmaStrNew(port, slot);
675 state = pdata->state;
676
677 if (state == PAD_STATE_ERROR && pdata->findPadRetries)
678 return PAD_STATE_FINDPAD;
679
680 if (state == PAD_STATE_STABLE && padGetReqState(port, slot) == PAD_RSTAT_BUSY) // Ok
681 return PAD_STATE_EXECCMD;
682 return state;
683 }
684 default:
685 return 0;
686 }
687}
688
689unsigned char
690padGetReqState(int port, int slot)
691{
692 if ((unsigned int)port >= (sizeof(PadState)/sizeof(PadState[0])))
693 return 0;
694 if ((unsigned int)slot >= (sizeof(PadState[0])/sizeof(PadState[0][0])))
695 return 0;
696
697 switch (PadState[port][slot].open)
698 {
699 case 1:
700 return padGetDmaStrOld(port, slot)->reqState;
701 case 2:
702 return padGetDmaStrNew(port, slot)->reqState;
703 default:
704 return 0;
705 }
706}
707
708int
709padSetReqState(int port, int slot, int state)
710{
711 if ((unsigned int)port >= (sizeof(PadState)/sizeof(PadState[0])))
712 return 0;
713 if ((unsigned int)slot >= (sizeof(PadState[0])/sizeof(PadState[0][0])))
714 return 0;
715
716 switch (PadState[port][slot].open)
717 {
718 case 1:
719 padGetDmaStrOld(port, slot)->reqState = state;
720 return 1;
721 case 2:
722 padGetDmaStrNew(port, slot)->reqState = state;
723 return 1;
724 default:
725 return 0;
726 }
727}
728
729void
730padStateInt2String(int state, char buf[16])
731{
732 if ((unsigned int)state < (sizeof(padStateString)/sizeof(padStateString[0])))
733 strcpy(buf, padStateString[state]);
734}
735
736void
737padReqStateInt2String(int state, char buf[16])
738{
739 if ((unsigned int)state < (sizeof(padReqStateString)/sizeof(padReqStateString[0])))
740 strcpy(buf, padReqStateString[state]);
741}
742
743int
745{
746 switch (padInitialised)
747 {
748 case 1:
749 {
750 buffer.command = PAD_RPCCMD_GET_PORTMAX_OLD;
751 break;
752 }
753 case 2:
754 {
755 buffer.command = PAD_RPCCMD_GET_PORTMAX_NEW;
756 break;
757 }
758 default:
759 return -1;
760 }
761
762 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
763 return -1;
764
765 return buffer.padResult.result;
766}
767
768int
770{
771 switch (padInitialised)
772 {
773 case 1:
774 {
775 buffer.command = PAD_RPCCMD_GET_SLOTMAX_OLD;
776 break;
777 }
778 case 2:
779 {
780 buffer.command = PAD_RPCCMD_GET_SLOTMAX_NEW;
781 break;
782 }
783 default:
784 return -1;
785 }
786 buffer.padSlotMaxArgs.port = port;
787
788 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
789 return -1;
790
791 return buffer.padResult.result;
792}
793
794int
796{
797 if (padInitialised != 2)
798 return 1; // Well.. return a low version #
799 buffer.command = PAD_RPCCMD_GET_MODVER;
800
801 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
802 return -1;
803
804 return buffer.padResult.result;
805}
806
807int
808padInfoMode(int port, int slot, int infoMode, int index)
809{
810 if ((unsigned int)port >= (sizeof(PadState)/sizeof(PadState[0])))
811 return 0;
812 if ((unsigned int)slot >= (sizeof(PadState[0])/sizeof(PadState[0][0])))
813 return 0;
814
815 switch (PadState[port][slot].open)
816 {
817 case 1:
818 {
819 buffer.command = PAD_RPCCMD_INFO_MODE;
820 buffer.padInfoModeArgs.port = port;
821 buffer.padInfoModeArgs.slot = slot;
822 buffer.padInfoModeArgs.infoMode = infoMode;
823 buffer.padInfoModeArgs.index = index;
824
825 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
826 return 0;
827
828 if (buffer.padModeResult.result == 1)
829 padSetReqState(port, slot, PAD_RSTAT_BUSY);
830 return buffer.padModeResult.result;
831 }
832 case 2:
833 {
834 struct pad_data_new *pdata;
835
836 pdata = padGetDmaStrNew(port, slot);
837
838 if (pdata->currentTask != 1)
839 return 0;
840 if (pdata->reqState == PAD_RSTAT_BUSY)
841 return 0;
842
843 switch (infoMode)
844 {
845 case PAD_MODECURID:
846 return (pdata->modeCurId == 0xF3) ? 0 : (pdata->modeCurId >> 4);
847 case PAD_MODECUREXID:
848 return (pdata->modeConfig == pdata->currentTask || ((unsigned int)(pdata->modeCurOffs) >= (sizeof(pdata->modeTable)/sizeof(pdata->modeTable[0])))) ? 0 : pdata->modeTable[pdata->modeCurOffs];
849 case PAD_MODECUROFFS:
850 return (pdata->modeConfig == 0) ? 0 : pdata->modeCurOffs;
851 case PAD_MODETABLE:
852 if (pdata->modeConfig != 0) {
853 if (index == -1)
854 return pdata->nrOfModes;
855 else if (index < pdata->nrOfModes && ((unsigned int)index <= (sizeof(pdata->modeTable)/sizeof(pdata->modeTable[0]))))
856 return pdata->modeTable[index];
857 }
858 return 0;
859 default:
860 return 0;
861 }
862 }
863 default:
864 return 0;
865 }
866}
867
868int
869padSetMainMode(int port, int slot, int mode, int lock)
870{
871 switch (padInitialised)
872 {
873 case 1:
874 {
875 buffer.command = PAD_RPCCMD_SET_MMODE_OLD;
876 break;
877 }
878 case 2:
879 {
880 buffer.command = PAD_RPCCMD_SET_MMODE_NEW;
881 break;
882 }
883 default:
884 return -1;
885 }
886 buffer.padSetMainModeArgs.port = port;
887 buffer.padSetMainModeArgs.slot = slot;
888 buffer.padSetMainModeArgs.mode = mode;
889 buffer.padSetMainModeArgs.lock = lock;
890
891 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
892 return 0;
893
894 if (buffer.padModeResult.result == 1)
895 padSetReqState(port, slot, PAD_RSTAT_BUSY);
896 return buffer.padModeResult.result;
897}
898
899int
900padInfoPressMode(int port, int slot)
901{
902 return (padGetButtonMask(port, slot) ^ 0x3ffff) ? 0 : 1;
903}
904
905int
906padEnterPressMode(int port, int slot)
907{
908 return padSetButtonInfo(port, slot, 0xFFF);
909}
910
911int
912padExitPressMode(int port, int slot)
913{
914 return padSetButtonInfo(port, slot, 0);
915}
916
917int
918padGetButtonMask(int port, int slot)
919{
920 switch (padInitialised)
921 {
922 case 1:
923 {
924 buffer.command = PAD_RPCCMD_GET_BTNMASK_OLD;
925 break;
926 }
927 case 2:
928 {
929 buffer.command = PAD_RPCCMD_GET_BTNMASK_NEW;
930 break;
931 }
932 default:
933 return -1;
934 }
935 buffer.padGetButtonMaskArgs.port = port;
936 buffer.padGetButtonMaskArgs.slot = slot;
937
938 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
939 return 0;
940
941 return buffer.padResult.result;
942}
943
944int
945padSetButtonInfo(int port, int slot, int buttonInfo)
946{
947 switch (padInitialised)
948 {
949 case 1:
950 {
951 buffer.command = PAD_RPCCMD_SET_BTNINFO_OLD;
952 break;
953 }
954 case 2:
955 {
956 buffer.command = PAD_RPCCMD_SET_BTNINFO_NEW;
957 break;
958 }
959 default:
960 return -1;
961 }
962 buffer.padSetButtonInfoArgs.port = port;
963 buffer.padSetButtonInfoArgs.slot = slot;
964 buffer.padSetButtonInfoArgs.buttonInfo = buttonInfo;
965
966 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
967 return 0;
968
969 if (buffer.padSetButtonInfoResult.result == 1)
970 padSetReqState(port, slot, PAD_RSTAT_BUSY);
971 return buffer.padSetButtonInfoResult.result;
972}
973
974unsigned char
975padInfoAct(int port, int slot, int actuator, int cmd)
976{
977 if ((unsigned int)port >= (sizeof(PadState)/sizeof(PadState[0])))
978 return 0;
979 if ((unsigned int)slot >= (sizeof(PadState[0])/sizeof(PadState[0][0])))
980 return 0;
981
982 switch (PadState[port][slot].open)
983 {
984 case 1:
985 {
986 buffer.command = PAD_RPCCMD_INFO_ACT;
987 buffer.padInfoActArgs.port = port;
988 buffer.padInfoActArgs.slot = slot;
989 buffer.padInfoActArgs.actuator = actuator;
990 buffer.padInfoActArgs.act_cmd = cmd;
991
992 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
993 return 0;
994
995 if (buffer.padModeResult.result == 1)
996 padSetReqState(port, slot, PAD_RSTAT_BUSY);
997 return buffer.padModeResult.result;
998 }
999 case 2:
1000 {
1001 struct pad_data_new *pdata;
1002
1003 pdata = padGetDmaStrNew(port, slot);
1004
1005 if (pdata->currentTask != 1)
1006 return 0;
1007 if (pdata->modeConfig < 2)
1008 return 0;
1009 if (actuator >= pdata->nrOfActuators)
1010 return 0;
1011
1012 if (actuator == -1)
1013 return pdata->nrOfActuators; // # of acutators?
1014
1015 if ((unsigned int)actuator >= (sizeof(pdata->actData)/sizeof(pdata->actData[0])))
1016 return 0;
1017 if ((unsigned int)cmd >= (sizeof(pdata->actData[0])/sizeof(pdata->actData[0][0])))
1018 return 0;
1019
1020 return pdata->actData[actuator][cmd];
1021 }
1022 default:
1023 return 0;
1024 }
1025}
1026
1027int
1028padSetActAlign(int port, int slot, const char actAlign[6])
1029{
1030 switch (padInitialised)
1031 {
1032 case 1:
1033 {
1034 buffer.command = PAD_RPCCMD_SET_ACTALIGN_OLD;
1035 break;
1036 }
1037 case 2:
1038 {
1039 buffer.command = PAD_RPCCMD_SET_ACTALIGN_NEW;
1040 break;
1041 }
1042 default:
1043 return -1;
1044 }
1045 buffer.padActDirAlignArgs.port = port;
1046 buffer.padActDirAlignArgs.slot = slot;
1047
1048 memcpy(buffer.padActDirAlignArgs.align, actAlign, sizeof(buffer.padActDirAlignArgs.align));
1049
1050 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
1051 return 0;
1052
1053 if (buffer.padModeResult.result == 1)
1054 padSetReqState(port, slot, PAD_RSTAT_BUSY);
1055 return buffer.padModeResult.result;
1056}
1057
1058int
1059padSetActDirect(int port, int slot, const char actAlign[6])
1060{
1061 switch (padInitialised)
1062 {
1063 case 1:
1064 {
1065 buffer.command = PAD_RPCCMD_SET_ACTDIR_OLD;
1066 break;
1067 }
1068 case 2:
1069 {
1070 buffer.command = PAD_RPCCMD_SET_ACTDIR_NEW;
1071 break;
1072 }
1073 default:
1074 return -1;
1075 }
1076 buffer.padActDirAlignArgs.port = port;
1077 buffer.padActDirAlignArgs.slot = slot;
1078
1079 memcpy(buffer.padActDirAlignArgs.align, actAlign, sizeof(buffer.padActDirAlignArgs.align));
1080
1081 if (sceSifCallRpc(&padsif[0], 1, 0, &buffer, sizeof(buffer), &buffer, sizeof(buffer), NULL, NULL) < 0)
1082 return 0;
1083
1084 return buffer.padModeResult.result;
1085}
1086
1087/*
1088 * This seems to have been removed from the official SDKs, very early during the PS2's lifetime.
1089 */
1090int
1091padGetConnection(int port, int slot)
1092{
1093 struct open_slot* oslt;
1094
1095 if (padInitialised != 2)
1096 return 1;
1097 oslt = padGetConnDmaStr();
1098 if ((unsigned int)slot >= (sizeof(oslt->openSlots)/sizeof(oslt->openSlots[0])))
1099 return 1;
1100 return ((oslt->openSlots[port] >> slot) & 0x1);
1101}
int padGetPortMax(void)
Definition libpad.c:744
int padPortOpen(int port, int slot, void *padArea)
Definition libpad.c:465
int padPortInit(int mode)
Definition libpad.c:389
unsigned char padRead(int port, int slot, struct padButtonStatus *data)
Definition libpad.c:615
int padInfoMode(int port, int slot, int infoMode, int index)
Definition libpad.c:808
unsigned char padInfoAct(int port, int slot, int actuator, int cmd)
Definition libpad.c:975
int padExitPressMode(int port, int slot)
Definition libpad.c:912
int padGetModVersion()
Definition libpad.c:795
int padInit(int mode)
Definition libpad.c:307
int padGetConnection(int port, int slot)
Definition libpad.c:1091
int padSetActDirect(int port, int slot, const char actAlign[6])
Definition libpad.c:1059
int padSetReqState(int port, int slot, int state)
Definition libpad.c:709
int padPortClose(int port, int slot)
Definition libpad.c:577
int padEnd(void)
Definition libpad.c:434
int padGetState(int port, int slot)
Definition libpad.c:648
unsigned char padGetReqState(int port, int slot)
Definition libpad.c:690
int padInfoPressMode(int port, int slot)
Definition libpad.c:900
int padSetMainMode(int port, int slot, int mode, int lock)
Definition libpad.c:869
int padEnterPressMode(int port, int slot)
Definition libpad.c:906
int padGetSlotMax(int port)
Definition libpad.c:769
int padSetActAlign(int port, int slot, const char actAlign[6])
Definition libpad.c:1028
u8 correction
Definition libpad.c:116