diff --git a/libctru/include/3ds/services/ac.h b/libctru/include/3ds/services/ac.h index a60af10..bc1ad79 100644 --- a/libctru/include/3ds/services/ac.h +++ b/libctru/include/3ds/services/ac.h @@ -6,16 +6,21 @@ /// Wifi security modes. typedef enum { - AC_OPEN = 0, ///< Open authentication. - AC_WEP_40BIT = 1, ///< WEP 40-bit authentication. - AC_WEP_104BIT = 2, ///< WEP 104-bit authentication. - AC_WEP_128BIT = 3, ///< WEP 128-bit authentication. - AC_WPA_TKIP = 4, ///< WPA TKIP authentication. - AC_WPA2_TKIP = 5, ///< WPA2 TKIP authentication. - AC_WPA_AES = 6, ///< WPA AES authentication. - AC_WPA2_AES = 7, ///< WPA2 AES authentication. + AC_OPEN = 0, ///< Open authentication. + AC_WEP_40BIT = 1, ///< WEP 40-bit authentication. + AC_WEP_104BIT = 2, ///< WEP 104-bit authentication. + AC_WEP_128BIT = 3, ///< WEP 128-bit authentication. + AC_WPA_TKIP = 4, ///< WPA TKIP authentication. + AC_WPA2_TKIP = 5, ///< WPA2 TKIP authentication. + AC_WPA_AES = 6, ///< WPA AES authentication. + AC_WPA2_AES = 7, ///< WPA2 AES authentication. } acSecurityMode; +/// Struct to contain the data for connecting to a Wifi network from a stored slot. +typedef struct { + u8 reserved[0x200]; +} acuConfig; + /// Initializes AC. Result acInit(void); @@ -90,3 +95,36 @@ Result ACU_GetLastErrorCode(u32* errorCode); * @param errorCode Pointer to output the error code to. */ Result ACU_GetLastDetailErrorCode(u32* errorCode); + +/** + * @brief Prepares a buffer to hold the configuration data to start a connection. + * @param config Pointer to an acuConfig struct to contain the data. + */ +Result ACU_CreateDefaultConfig(acuConfig* config); + +/** + * @brief Sets something that makes the connection reliable. + * @param config Pointer to an acuConfig struct used with ACU_CreateDefaultConfig previously. + * @param area Always 2 ? + */ +Result ACU_SetNetworkArea(acuConfig* config, u8 area); + +/** + * @brief Sets the slot to use when connecting. + * @param config Pointer to an acuConfig struct used with ACU_CreateDefaultConfig previously. + * @param type Allowed slots flag. BIT(0) for slot 1, BIT(1) for slot 2, BIT(2) for slot 3. + */ +Result ACU_SetAllowApType(acuConfig* config, u8 type); + +/** + * @brief Sets something that makes the connection reliable. + * @param config Pointer to an acuConfig struct used with ACU_CreateDefaultConfig previously. + */ +Result ACU_SetRequestEulaVersion(acuConfig* config); + +/** + * @brief Starts the connection procedure. + * @param config Pointer to an acuConfig struct used with ACU_CreateDefaultConfig previously. + * @param connectionHandle Handle created with svcCreateEvent to wait on until the connection succeeds or fails. + */ +Result ACU_ConnectAsync(const acuConfig* config, Handle connectionHandle); diff --git a/libctru/source/services/ac.c b/libctru/source/services/ac.c index 9267ad1..007a70c 100644 --- a/libctru/source/services/ac.c +++ b/libctru/source/services/ac.c @@ -16,8 +16,9 @@ Result acInit(void) if (AtomicPostIncrement(&acRefCount)) return 0; - ret = srvGetServiceHandle(&acHandle, "ac:u"); - if(R_FAILED(ret)) ret = srvGetServiceHandle(&acHandle, "ac:i"); + // ac:i has the most commands, then ac:u + ret = srvGetServiceHandle(&acHandle, "ac:i"); + if(R_FAILED(ret)) ret = srvGetServiceHandle(&acHandle, "ac:u"); if(R_FAILED(ret)) AtomicDecrement(&acRefCount); return ret; @@ -37,16 +38,62 @@ Result acWaitInternetConnection(void) return ret; } -Result ACU_GetWifiStatus(u32 *out) +Result ACU_CreateDefaultConfig(acuConfig* config) +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 *staticbufs = getThreadStaticBuffers(); + + cmdbuf[0] = IPC_MakeHeader(0x1,0,0); // 0x10000 + staticbufs[0] = IPC_Desc_StaticBuffer(0x200, 0); + staticbufs[1] = (u32)config; + + if(R_FAILED(ret = svcSendSyncRequest(acHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result ACU_ConnectAsync(const acuConfig* config, Handle connectionHandle) { Result ret=0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0xD,0,0); // 0xD0000 + cmdbuf[0] = IPC_MakeHeader(0x4,0,6); // 0x40006 + cmdbuf[1] = 0x20; + cmdbuf[3] = 0; + cmdbuf[4] = connectionHandle; + cmdbuf[5] = IPC_Desc_StaticBuffer(0x200, 1); + cmdbuf[6] = (u32)config; + + if(R_FAILED(ret = svcSendSyncRequest(acHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result ACU_GetLastErrorCode(u32* errorCode) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xA,0,0); // 0xA0000 if(R_FAILED(ret = svcSendSyncRequest(acHandle)))return ret; - *out = cmdbuf[2]; + if(errorCode) *errorCode = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result ACU_GetLastDetailErrorCode(u32* errorCode) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000 + + if(R_FAILED(ret = svcSendSyncRequest(acHandle)))return ret; + + if(errorCode) *errorCode = cmdbuf[2]; return (Result)cmdbuf[1]; } @@ -65,6 +112,91 @@ Result ACU_GetStatus(u32 *out) return (Result)cmdbuf[1]; } +Result ACU_GetWifiStatus(u32 *out) +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xD,0,0); // 0xD0000 + + if(R_FAILED(ret = svcSendSyncRequest(acHandle)))return ret; + + *out = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result ACU_SetAllowApType(acuConfig* config, u8 type) +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 *staticbufs = getThreadStaticBuffers(); + + cmdbuf[0] = IPC_MakeHeader(0x22,1,2); // 0x220042 + cmdbuf[1] = type; + cmdbuf[2] = IPC_Desc_StaticBuffer(0x200, 0); + cmdbuf[3] = (u32)config; + staticbufs[0] = IPC_Desc_StaticBuffer(0x200, 0); + staticbufs[1] = (u32)config; + + if(R_FAILED(ret = svcSendSyncRequest(acHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result ACU_SetNetworkArea(acuConfig* config, u8 area) +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 *staticbufs = getThreadStaticBuffers(); + + cmdbuf[0] = IPC_MakeHeader(0x25,1,2); // 0x250042 + cmdbuf[1] = area; + cmdbuf[2] = IPC_Desc_StaticBuffer(0x200, 0); + cmdbuf[3] = (u32)config; + staticbufs[0] = IPC_Desc_StaticBuffer(0x200, 0); + staticbufs[1] = (u32)config; + + if(R_FAILED(ret = svcSendSyncRequest(acHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result ACU_SetRequestEulaVersion(acuConfig* config) +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 *staticbufs = getThreadStaticBuffers(); + + cmdbuf[0] = IPC_MakeHeader(0x2D,2,2); // 0x2D0082 + cmdbuf[1] = 0; + cmdbuf[2] = 0; + cmdbuf[3] = IPC_Desc_StaticBuffer(0x200, 0); + cmdbuf[4] = (u32)config; + staticbufs[0] = IPC_Desc_StaticBuffer(0x200, 0); + staticbufs[1] = (u32)config; + + if(R_FAILED(ret = svcSendSyncRequest(acHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result ACU_GetProxyPassword(char *password) +{ + Result ret=0; + u32 *cmdbuf = getThreadCommandBuffer(); + u32 *staticbufs = getThreadStaticBuffers(); + + cmdbuf[0] = IPC_MakeHeader(0x3B,0,0); // 0x3B0000 + + staticbufs[0] = IPC_Desc_StaticBuffer(0x20, 0); + staticbufs[1] = (u32)password; + + if(R_FAILED(ret = svcSendSyncRequest(acHandle)))return ret; + + return (Result)cmdbuf[1]; +} + Result ACU_GetSecurityMode(acSecurityMode *mode) { Result ret=0; @@ -86,7 +218,7 @@ Result ACU_GetSSID(char *SSID) u32 *staticbufs = getThreadStaticBuffers(); cmdbuf[0] = IPC_MakeHeader(0x34,0,0); // 0x340000 - + staticbufs[0] = IPC_Desc_StaticBuffer(0x20, 0); staticbufs[1] = (u32)SSID; @@ -144,7 +276,7 @@ Result ACU_GetProxyUserName(char *username) u32 *staticbufs = getThreadStaticBuffers(); cmdbuf[0] = IPC_MakeHeader(0x3A,0,0); // 0x3A0000 - + staticbufs[0] = IPC_Desc_StaticBuffer(0x20, 0); staticbufs[1] = (u32)username; @@ -152,47 +284,3 @@ Result ACU_GetProxyUserName(char *username) return (Result)cmdbuf[1]; } - -Result ACU_GetProxyPassword(char *password) -{ - Result ret=0; - u32 *cmdbuf = getThreadCommandBuffer(); - u32 *staticbufs = getThreadStaticBuffers(); - - cmdbuf[0] = IPC_MakeHeader(0x3B,0,0); // 0x3B0000 - - staticbufs[0] = IPC_Desc_StaticBuffer(0x20, 0); - staticbufs[1] = (u32)password; - - if(R_FAILED(ret = svcSendSyncRequest(acHandle)))return ret; - - return (Result)cmdbuf[1]; -} - -Result ACU_GetLastErrorCode(u32* errorCode) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0xA,0,0); // 0xA0000 - - if(R_FAILED(ret = svcSendSyncRequest(acHandle)))return ret; - - if(errorCode) *errorCode = cmdbuf[2]; - - return (Result)cmdbuf[1]; -} - -Result ACU_GetLastDetailErrorCode(u32* errorCode) -{ - Result ret = 0; - u32 *cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0xB,0,0); // 0xB0000 - - if(R_FAILED(ret = svcSendSyncRequest(acHandle)))return ret; - - if(errorCode) *errorCode = cmdbuf[2]; - - return (Result)cmdbuf[1]; -}