Homebrew Infra Red Resource Thread

Would you like to see development for IR homebrew (CPP or not) on the 3ds?

  • Yes, and I have the CPP!

    Votes: 40 19.1%
  • Yes, why not!

    Votes: 164 78.5%
  • No.

    Votes: 5 2.4%

  • Total voters
    209

the assaf

Well-Known Member
Member
Joined
Jun 2, 2013
Messages
489
Trophies
0
Age
29
XP
360
Country
Hi, I hope it's not too late to revive this thread. I have been working on porting circle pad pro support to ctrulib for the past few days, basically decompiling the extra pad examples from CTR-SDK, and using dumps and the NTR debugger to check the runtime values of some variables, and I came up with a demo homebrew (cia) which tries to connect to the CPP using obviously the service ir:USER.

Here is the code (yes, I modified an example of ctrulib):
Code:
#include <3ds.h>
#include <stdio.h>

#define NN_ATTRIBUTE_ALIGN(n) __attribute__ ((aligned(n)))

u8 extraPadWorkingMemory[4096] NN_ATTRIBUTE_ALIGN(4096);
int irWorkingMemory = 0;
char peripheralId = 0x01;

Handle iruserHandle;
Handle iruserSharedMemHandle;
Handle connectionStatusEvent;

bool connected = false;
Result initializeIrnopSharedResult;
Result getConnectionStatusEventResult;
Result requireConnectionResult;

Result InitializeIrnopShared()
{
    Result ret = 0;
    u32 *cmdbuf = getThreadCommandBuffer();

    cmdbuf[0] = 0x00180182;
    cmdbuf[1] = 4096u;
    cmdbuf[2] = 3280u;
    cmdbuf[3] = (unsigned int)(0x00000500u >> 3);
    cmdbuf[4] = (unsigned int)(512 + 256);
    cmdbuf[5] = (unsigned int)(256u >> 3);
    cmdbuf[6] = (char)0x04; //byte 0x04
    cmdbuf[7] = 0;
    cmdbuf[8] = iruserSharedMemHandle; // mem handle

    if (R_FAILED(ret = svcSendSyncRequest(iruserHandle))) return ret;
    ret = (Result)cmdbuf[1];

    return ret;
}

Result GetConnectionStatusEvent(Handle *event_)
{
    Result ret = 0;
    u32 *cmdbuf = getThreadCommandBuffer();

    cmdbuf[0] = 0x000C0000;

    if (R_FAILED(ret = svcSendSyncRequest(iruserHandle))) return ret;
    ret = (Result)cmdbuf[1];

    *event_ = cmdbuf[3];

    return ret;
}

Result RequireConnection()
{
    Result ret = 0;
    u32 *cmdbuf = getThreadCommandBuffer();

    cmdbuf[0] = 0x00060040;
    cmdbuf[1] = peripheralId;

    if (R_FAILED(ret = svcSendSyncRequest(iruserHandle))) return ret;
    ret = (Result)cmdbuf[1];

    return ret;
}

Result Disconnect()
{
    Result ret = 0;
    u32 *cmdbuf = getThreadCommandBuffer();

    cmdbuf[0] = 0x00090000;

    if (R_FAILED(ret = svcSendSyncRequest(iruserHandle))) return ret;
    ret = (Result)cmdbuf[1];

    return ret;
}

int out, out_;
int StartSampling(int samplingThreadPriority, int period) // Button A
{
    int result = -1;
    // cepdSetPeriod(...);

    // Get IR:USER Handle
    Result ret = 0;
    ret = srvGetServiceHandle(&iruserHandle, "ir:USER");
    if (R_FAILED(ret)) iruserHandle = 0xFFFFFFFF;

    ret = svcCreateMemoryBlock(&iruserSharedMemHandle, irWorkingMemory, 0x1000, 1u, 3u);
    if (R_FAILED(ret)) iruserSharedMemHandle = 0xFFFFFFFF;

    initializeIrnopSharedResult = InitializeIrnopShared();

    svcCreateEvent(&connectionStatusEvent, 0);
    getConnectionStatusEventResult = GetConnectionStatusEvent(&connectionStatusEvent);

    svcWaitSynchronizationN(&out_, &connectionStatusEvent, 1, 0, 0);
    requireConnectionResult = RequireConnection();
    svcWaitSynchronizationN(&out_, &connectionStatusEvent, 1, 0, 4000000);

    /*while (true)
    {
        svcWaitSynchronizationN(&out_, &connectionStatusEvent, 1, 0, 0);
        requireConnectionResult = RequireConnection();
        int i = svcWaitSynchronizationN(&out_, &connectionStatusEvent, 1, 0, 4000000);
        s16 s = i;
        int i_ = s & 0x3FF;
        if (i_ != 1022) break;
        u8 connectionStatus = *((u8 *)(irWorkingMemory + 8));
        if (connectionStatus == 2) break;
        Disconnect();
        svcSleepThread(10416);
    }*/

    u8 connectionStatus = *((u8 *)(irWorkingMemory + 8));

    if (connectionStatus == 2) connected = true;

    out = connectionStatus;

    return result;
}

void TryToConnect() // Button B
{
    svcWaitSynchronizationN(&out_, &connectionStatusEvent, 1, 0, 0);
    RequireConnection();
    svcWaitSynchronizationN(&out_, &connectionStatusEvent, 1, 0, 4000000);

    u8 connectionStatus = *((u8 *)(irWorkingMemory + 8));

    if (connectionStatus == 2) connected = true;

    out = connectionStatus;

    Disconnect();
}

int main(int argc, char **argv)
{
    //Matrix containing the name of each key. Useful for printing when a key is pressed
    char keysNames[32][32] = {
        "KEY_A", "KEY_B", "KEY_SELECT", "KEY_START",
        "KEY_DRIGHT", "KEY_DLEFT", "KEY_DUP", "KEY_DDOWN",
        "KEY_R", "KEY_L", "KEY_X", "KEY_Y",
        "", "", "KEY_ZL", "KEY_ZR",
        "", "", "", "",
        "KEY_TOUCH", "", "", "",
        "KEY_CSTICK_RIGHT", "KEY_CSTICK_LEFT", "KEY_CSTICK_UP", "KEY_CSTICK_DOWN",
        "KEY_CPAD_RIGHT", "KEY_CPAD_LEFT", "KEY_CPAD_UP", "KEY_CPAD_DOWN"
    };

    // Initialize services
    gfxInitDefault();

    //Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
    consoleInit(GFX_TOP, NULL);

    u32 kDownOld = 0, kHeldOld = 0, kUpOld = 0; //In these variables there will be information about keys detected in the previous frame

    printf("\x1b[0;0HPress Start to exit.");
    printf("\x1b[1;0HCirclePad position:");
    printf("\x1b[20;0Hir:USER service handle: %x", iruserHandle);
    printf("\x1b[21;0HShared memory handle: %x", iruserSharedMemHandle);
    printf("\x1b[22;0HIIS result: %x", initializeIrnopSharedResult);
    printf("\x1b[23;0HGCSE result: %x", getConnectionStatusEventResult);
    printf("\x1b[24;0HConnectionStatus event handle: %x", connectionStatusEvent);
    printf("\x1b[25;0HRC result: %x", requireConnectionResult);
    if (connected)
        printf("\x1b[27;0HCONNECTED!!! %x", out);
    else
        printf("\x1b[27;0HNot connected. %x", out);

    // ---------------------------------------------------------------------------------------------------------------------------------------------------------------
    // ---------------------------------------------------------------------------------------------------------------------------------------------------------------

    irWorkingMemory = (int)extraPadWorkingMemory;
    out = *((u8 *)(irWorkingMemory + 8));

    // ---------------------------------------------------------------------------------------------------------------------------------------------------------------
    // ---------------------------------------------------------------------------------------------------------------------------------------------------------------

    // Main loop
    while (aptMainLoop())
    {
        //Scan all the inputs. This should be done once for each frame
        hidScanInput();

        //hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame)
        u32 kDown = hidKeysDown();
        //hidKeysHeld returns information about which buttons have are held down in this frame
        u32 kHeld = hidKeysHeld();
        //hidKeysUp returns information about which buttons have been just released
        u32 kUp = hidKeysUp();

        if (kDown & KEY_START) break; // break in order to return to hbmenu

        //Do the keys printing only if keys have changed
        if (kDown != kDownOld || kHeld != kHeldOld || kUp != kUpOld)
        {
            //Clear console
            consoleClear();

            //These two lines must be rewritten because we cleared the whole console
            printf("\x1b[0;0HPress Start to exit.");
            printf("\x1b[1;0HCirclePad position:");
            printf("\x1b[20;0Hir:USER service handle: %x", iruserHandle);
            printf("\x1b[21;0HShared memory handle: %x", iruserSharedMemHandle);
            printf("\x1b[22;0HIIS result: %x", initializeIrnopSharedResult);
            printf("\x1b[23;0HGCSE result: %x", getConnectionStatusEventResult);
            printf("\x1b[24;0HConnectionStatus event handle: %x", connectionStatusEvent);
            printf("\x1b[25;0HRC result: %x", requireConnectionResult);
            if (connected)
                printf("\x1b[27;0HCONNECTED!!! %x", out);
            else
                printf("\x1b[27;0HNot connected. %x", out);

            printf("\x1b[3;0H"); //Move the cursor to the fourth row because on the third one we'll write the circle pad position

            //Check if some of the keys are down, held or up
            int i;
            for (i = 0; i < 32; i++)
            {
                if (kDown & BIT(i)) printf("%s down\n", keysNames[i]);
                if (kHeld & BIT(i)) printf("%s held\n", keysNames[i]);
                if (kUp & BIT(i)) printf("%s up\n", keysNames[i]);
            }

            if (kDown & KEY_A)
            {
                StartSampling(0, 8);
            }
            if (kDown & KEY_B)
            {
                TryToConnect();
            }
        }

        //Set keys old values for the next frame
        kDownOld = kDown;
        kHeldOld = kHeld;
        kUpOld = kUp;

        circlePosition pos;

        //Read the CirclePad position
        hidCircleRead(&pos);

        //Print the CirclePad position
        printf("\x1b[2;0H%04d; %04d", pos.dx, pos.dy);

        // Flush and swap framebuffers
        gfxFlushBuffers();
        gfxSwapBuffers();

        //Wait for VBlank
        gspWaitForVBlank();
    }

    // Exit services
    gfxExit();
    return 0;
}

(And for you lazy, check the attachments)

BUT, it does not work. I mean it does initialize correctly and everything, it even turns on the ir of the 3ds on RequireConnection(), but it won't actually connect with the thing.

I suppose the problem is somewhere in the RequireConnection() function, specifically the peripheralId byte, which should be passed as a char, has most of my concern. I say this because I tried manually changing the value in the CTR-SDK example mentioned before with NTR debugger and it will fail to connect, apparently only 0x01 works, but not on my code.

Anyway, I thought about posting here because maybe some of you have succeded in this hard work, or maybe could help me out with this little project.

Oh and by the way, it *should* connect without pressing B, just by calling StartSampling, hence button A, and the commented out part in the StartSampling() function in what the CTR-SDK sample does to connect (more or less), but the while will just never end, because svcWaitSynchronizationN doesn't return before the maximum time has passed.
You tried luanching it with proper permission? Like to launch homebrew under oot/cn/DOA:dimension
 

DI2edd

New Member
Newbie
Joined
Feb 11, 2016
Messages
4
Trophies
0
Age
30
XP
56
Country
Italy
Cias also need permissions, which specified in rsf file
Well, this is not the case, since I can access the handle of ir:USER, but whatever, tried and didn't work.
With cubic ninja it doesn't even get the handle of the service, and with kingdom hearts: ddp, which supports the CPP, the result was the same as for the CIA
 

the assaf

Well-Known Member
Member
Joined
Jun 2, 2013
Messages
489
Trophies
0
Age
29
XP
360
Country
Well, this is not the case, since I can access the handle of ir:USER, but whatever, tried and didn't work.
With cubic ninja it doesn't even get the handle of the service, and with kingdom hearts: ddp, which supports the CPP, the result was the same as for the CIA
Try to run 3dsx on one of the titles that mentioned here like oot3d, cn,DOA:dimensions
 

DI2edd

New Member
Newbie
Joined
Feb 11, 2016
Messages
4
Trophies
0
Age
30
XP
56
Country
Italy
Try to run 3dsx on one of the titles that mentioned here like oot3d, cn,DOA:dimensions

when will a cia version be made so you don't need one of those games

I second this.
For now, since you want to use a .cia, you can just install one of the games and use it to access homebrew.

thing is cfw shoud allow ir access with out the need of a game

I think you don't get the point. I already have a cia of my homebrew, which can also be downloaded from the attachments in my previous post, and I don't know what you, the assaf, mean by the game cn, cause I've already said that I tried to run it under Cubic Ninja (is that what cn mean?) and it couldn't even provide access to the required service (please remember that this hb is different from the ones from RedHat, which use ir:u instead of the needed ir:USER). The problem here is in the code.

I'm starting to think that it needs to push RequireConnection() once every n seconds (well, milliseconds) to establish the connection in the first place, but I don't understand what the function nn::ir::CTR::CepdCalcSecondWait does, so...
 

RedHat

Well-Known Member
OP
Member
Joined
Oct 10, 2015
Messages
235
Trophies
0
Location
Mii Plaza
Website
github.com
XP
376
Country
United States
If people still seem interested, I guess I could have a reason to reboot this thread (A few others have PMd me, and this thread is still very relevant to current 3ds homebrew). I finally finished school finals, and with easy access to CFW because basically everyone has A9LH now, I suppose a lot of others could pitch in. We'll see!

I'm most interested in the CPP, but if IR for TVs end up working (different protocols, so it might be impossible), that would be a bonus.

No promises.

Nobody is going to shoot me for "bumping" this old thread, right?
 

Duo8

Well-Known Member
Member
Joined
Jul 16, 2013
Messages
3,613
Trophies
2
XP
3,045
Country
Vietnam
Oh yeah just found this

Code:
Dec 02 15:44:55 <sm>    your TV operates at ~36kHz weird ones might be 56kHz, I can't find my notes as to what exactly the 3ds operates at it but's MHz
Dec 02 15:44:55 <sm>    so while it's technically possible to do it wouldn't be easy to do, you'd have to manually turn on/off the LED and do some software clocking and hope
...
Dec 02 15:48:59 <sm>   the operational frequency of the IR modules I mean
Dec 02 15:48:59 <eussNL>   and some use 38, 40 etc. <sm> your TV operates at ~36kHz, some listings are in the old LIRC resources though....
Dec 02 15:48:59 <sm>   yeah well somewhere along that order 30-60KHz is a safe number to give
I'll dig around a bit more.
 
  • Like
Reactions: RedHat

Fishy4341

Member
Newcomer
Joined
Aug 20, 2016
Messages
6
Trophies
0
Age
23
XP
52
Country
United States
Maybe we could use the Ir as a file transfer(Like the old Palm Pilots)? Like homebrew to homebrew. Transfer Themes, .3dsx, .cia, and tons of other files!
Also I don't see a reason why you would want to use your 3ds as a tv remote. The ir is not strong enough so you would have to be super close. Since they operate at different frequencies it would be hard to speed one up(Or slow one down).
 

Giodude

GBAtemp's official rock
Member
Joined
May 17, 2015
Messages
5,094
Trophies
1
Age
23
Location
New York
XP
2,761
Country
United States
Maybe we could use the Ir as a file transfer(Like the old Palm Pilots)? Like homebrew to homebrew. Transfer Themes, .3dsx, .cia, and tons of other files!
Also I don't see a reason why you would want to use your 3ds as a tv remote. The ir is not strong enough so you would have to be super close. Since they operate at different frequencies it would be hard to speed one up(Or slow one down).
.eJwFwUsOgyAQANC7sIeB4TPg1oM0RAmaqBAYV03v3ve-4h2XWMTB3OcCsJ9za2NXk9vItajaWr1K7udUW7shM-ftuMvDE1Cjj4ZsSj5Zb61zgCaESM4nTSaaRBRgzZ3fUT6oTZA6StTSRGlJOlT9qeL3B9gCJsQ.-fF5eaauUjL17uix7eY1mG46Sms.png
just jokin though would love this to be revived
 

Fishy4341

Member
Newcomer
Joined
Aug 20, 2016
Messages
6
Trophies
0
Age
23
XP
52
Country
United States
I'm sorry, Though I really do think it would be cool to have an irDA file transfer system, so we could transfer stuff... If only I knew how to do this kind of stuff, I would do it in a heartbeat! It could be super useful to transfer files locally, and maybe someone here could make an all connections file transfer. Like via local Download and Play, irDA, and wifi, maybe Nintendo network!
 
  • Like
Reactions: Giodude

Giodude

GBAtemp's official rock
Member
Joined
May 17, 2015
Messages
5,094
Trophies
1
Age
23
Location
New York
XP
2,761
Country
United States
I'm sorry, Though I really do think it would be cool to have an irDA file transfer system, so we could transfer stuff... If only I knew how to do this kind of stuff, I would do it in a heartbeat! It could be super useful to transfer files locally, and maybe someone here could make an all connections file transfer. Like via local Download and Play, irDA, and wifi, maybe Nintendo network!
I just wanna control the tv with my 3ds
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    The Real Jdbye @ The Real Jdbye: @BakerMan needs more expand dong