Implementing the AC:I service functions

Discussion in '3DS - Homebrew Development and Emulators' started by natinusala, May 8, 2017.

  1. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    Hello everyone,

    I've been trying to implement the AC:I service, using the documentation found on 3dbrew. I slowly test each function, adding a new page on the wiki as I go further. I have some Citra3DS logs of the System Settings and Network Settings dev app as a starting point for the call order and parameters.

    Here is what I got so far :
    • To read a network setting :
      • Call LoadNetworkSetting with the wanted network ID (0-1-2)
      • Read the values using the various getters
    • To update a network setting :
      • Call LoadNetworkSetting with the wanted network ID (0-1-2)
      • Call InitializeNetworkSetting with 1 as a parameter (I don't know what it represents but it's the value used by both System Settings and Network Settings)
      • Set all the values using the various setters
      • Call UpdateNetworkSetting to update the setting
    • To delete a network setting :
      • Just call RemoveNetworkSetting with the wanted network ID
    • At the end :
      • Always call FlushNetworkSetting to commit and save the changes
    I successfully implemented the basic functions such as LoadNetworkSetting, InitializeNetworkSetting or RemoveNetworkSetting. However, I can't get all the getters to work : the ones with a "string" as return value (such as the getter for the ssid, password or proxy host) make the system freeze when calling the svcSendSyncRequest function. It just crashes. The other getters, such as the proxy state or proxy port are working just fine.

    I know that these function doesn't require any additionnal parameters, and that they are not likely to use a shared memory buffer (as I would see it in Citra's logs). Here is the code of my implementation of the GetNetworkProxyHost function (I don't have any return value yet since the call freezes the console).

    What am I doing wrong ? I do the AC:I calls in the exact same order than the System Settings app, but I might be missing something. Here are the Citra logs that I use, you can see all the unimplemented AC:I functions starting at line 60 - it starts with LoadNetworkSetting and immediatly reads all the values, starting with function 0x04070000, then the CRC...

    Thanks for the help :)
     
    Last edited by natinusala, May 9, 2017
  2. NANASHI89

    NANASHI89 GBAtemp Maniac

    Member
    1,096
    121
    May 3, 2012
    United States
    What's an "AC:I service?"

    Sent from my SM-T280 using Tapatalk
     
  3. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    It's the service which is used to manipulate the WiFi networks.
     
  4. B_E_P_I_S_M_A_N

    B_E_P_I_S_M_A_N oh no

    Member
    688
    2,472
    Jun 7, 2016
    United States
    Sixth Circle of Hell
  5. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    I'm almost 100% positive on that for 3 reasons :
    1. As you stated, the command header contains the number of parameters (0-4-8...). However, of you look at the wiki you'll see that all the getters are like 0x04XX0000 : no standard parameters and no translate parameters.
    2. If they would need parameters I would see it on the Citra logs (cmd_buff[x] = ...)
    3. Some setters work : the ones with integral values work, the ones with string values doesn't
    I'm aware that the getters need some place to put the string to, like an output buffer... But since they doesn't need any additional parameters, there is only a few options left :
    • Either it gives a "read-only" string pointer to strcpy from
    • Either it uses shared memory, but I guess I would see the svcCreateMemoryBlock call in the Citra logs
    But I can't test any of that since the call freezes the console. Could it come from the non-existent shared buffer ?
     
    Last edited by natinusala, May 9, 2017
  6. B_E_P_I_S_M_A_N

    B_E_P_I_S_M_A_N oh no

    Member
    688
    2,472
    Jun 7, 2016
    United States
    Sixth Circle of Hell
    Maybe. Unfortunately, I don't have that much knowledge of 3DS Hacking to give you a definitive answer. Sorry.

    This may sound weird, but have you tried working with C++ strings? But you said the program crashes on svcSendSyncRequest(). Hrm.
     
  7. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    The 3DS totally freezes when calling svcSendSyncRequest, I have to manually power it down by pressing the power button for 10s or so. I tried giving a garbage IPC header to see, and I have the same result, which makes me think that every time the SVC isn't happy with something it just crashes the system. I don't know if calling a service which needs a shared buffer will either return a bad value or crash the system... There is no reason for the freeze apart a missing shared buffer. I'll try this evening, even tho I don't know its size.

    edit : Nope I just realized that even with a shared memory buffer it would be given as a parameter... they don't require any parameter and still they fail, why ? it's driving me crazy
     
    Last edited by natinusala, May 9, 2017
    B_E_P_I_S_M_A_N likes this.
  8. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    I just rebuild and ran Citra3DS, I can't find anything that I do wrong... those who are familiar with such function calls, how is the return value passed to the homebrew if there is no output buffer parameter ?
     
    Last edited by natinusala, May 10, 2017
  9. B_E_P_I_S_M_A_N

    B_E_P_I_S_M_A_N oh no

    Member
    688
    2,472
    Jun 7, 2016
    United States
    Sixth Circle of Hell
    Oh, you're testing on Citra?

    Have you done any testing on the actual 3DS?
     
  10. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    Testing on the actual 3DS freezes it at the GetProxyHost svc call. Testing in Citra blurts out red unknown/uninmplemented ac:i functions, which is normal, but I use it to log service calls done by the System Settings app. I do the exact same calls on the 3DS and it freezes. Ugh.

    edit : if anyone wants to read the OP Citra logs and point me to what i'm missing...
     
    Last edited by natinusala, May 10, 2017
    B_E_P_I_S_M_A_N likes this.
  11. Kartik

    Kartik Gbatemp advanced fan

    Member
    339
    236
    Jun 6, 2015
    India
    github
    This piece of code worked for me(ACI:GetConnectingSsid):-
    Code:
    Handle acHandle;
        Result ret;
        u8 *try = malloc(0x100);
        ret = srvGetServiceHandle(&acHandle,"ac:i");
        printf("%d\n",(int)ret);
        u32 *cmdbuf = getThreadCommandBuffer();
        cmdbuf[0] = 0x340000;
        u32 *staticbuf = getThreadStaticBuffers();
        staticbuf[0] = 0x80002;
        staticbuf[1] = try;
        ret = svcSendSyncRequest(acHandle);
        printf("ret,try: %d|%s\n",(int)ret,(char*)try);
     
  12. Ryuzaki_MrL

    Ryuzaki_MrL Furry Addict

    Member
    744
    719
    Jun 23, 2015
    Brazil
    Did you try:
    Code:
    Result ACI_GetNetworkProxyHost(u16* out)
    {
        Result ret;
        u32 *cmdbuf = getThreadCommandBuffer();
     
        cmdbuf[0] = IPC_MakeHeader(0x465,0,0); // 0x04650000
    
        if(R_FAILED(ret = svcSendSyncRequest(aciHandle)))return ret;
    
        if(out) memcpy(out, &cmdbuf[2], <whatever_is_the_max_length>);
        return (Result)cmdbuf[1];
    }
    
    May aswell be a char* if it's not using UTF-16.
     
    Last edited by Ryuzaki_MrL, May 15, 2017
  13. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    I didn't know that getThreadStaticBuffers was a thing... it still freezes tho, could it come from the size of the try buffer ? Also, what is 0x80002 ? Here is my code.

    The problem is not with reading the value, it's with the actual svc call which freezes the console. But if it uses the static buffer as @Kartik suggested, it might not work like you wrote it.
     
  14. Kartik

    Kartik Gbatemp advanced fan

    Member
    339
    236
    Jun 6, 2015
    India
    github
    Not sure why it is not work for you...As for in GetProxyHost()this should work:-
    Code:
    Result ACI_GetNetworkProxyHost(void)
    {
        Result ret=0;
        ret = srvGetServiceHandle(&acHandle,"ac:i");
        printf("%d\n",ret);
        u32 *cmdbuf = getThreadCommandBuffer();
          
        cmdbuf[0] = IPC_MakeHeader(0x465,0,0); // 0x04650000
      
        u32 *staticbuf = getThreadStaticBuffers();
        u8* try = malloc(0x200);
        if(try==NULL)return 1;
        staticbuf[0] = 0x190002;
        staticbuf[1] = try;
     
        if(R_FAILED(ret = svcSendSyncRequest(aciHandle)))return ret;
     
        return (Result)cmdbuf[1];
    }
     
  15. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    Holy sh*t that works. Thanks a lot ! But again, what is 0x190002 and how do you find it ?
     
  16. Drakia

    Drakia GBAtemp Advanced Maniac

    Member
    1,512
    1,762
    Mar 15, 2008
    Canada
  17. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    I couldn't find a way to get 0x190002 back using this function =/ I put 0x200 as a size and tried each buffer ID (0x0 - 0xF).
     
  18. Drakia

    Drakia GBAtemp Advanced Maniac

    Member
    1,512
    1,762
    Mar 15, 2008
    Canada
    Yeah, not sure how he got his specific numbers, just saying how libctru seems to get the number to use. If you look for all references to "getThreadStaticBuffers", you will see they all use "IPC_Desc_StaticBuffer" to get that specific value, passing in the buffer size. So I'd recommend just doing the same.
     
  19. natinusala
    OP

    natinusala GBAtemp Regular

    Member
    164
    104
    Dec 1, 2012
    France
    Yeah i'll do just that. Thanks for the help :)
     
    Drakia likes this.