/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.HLE.modules;
import static jpcsp.HLE.modules.sceNetAdhocctl.IBSS_NAME_LENGTH;
import static jpcsp.HLE.modules.sceNetAdhocctl.fillNextPointersInLinkedList;
import jpcsp.HLE.BufferInfo;
import jpcsp.HLE.CanBeNull;
import jpcsp.HLE.HLEFunction;
import jpcsp.HLE.HLEModule;
import jpcsp.HLE.HLEUnimplemented;
import jpcsp.HLE.TPointer;
import jpcsp.HLE.TPointer32;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.HashMap;
import org.apache.log4j.Logger;
import jpcsp.HLE.Modules;
import jpcsp.HLE.BufferInfo.Usage;
import jpcsp.HLE.kernel.managers.SceUidManager;
import jpcsp.HLE.kernel.types.SceKernelThreadInfo;
import jpcsp.HLE.kernel.types.pspNetMacAddress;
import jpcsp.hardware.Wlan;
import jpcsp.settings.Settings;
import jpcsp.Emulator;
import jpcsp.Processor;
public class sceNetApctl extends HLEModule {
public static Logger log = Modules.getLogger("sceNetApctl");
public static final int PSP_NET_APCTL_STATE_DISCONNECTED = 0;
public static final int PSP_NET_APCTL_STATE_SCANNING = 1;
public static final int PSP_NET_APCTL_STATE_JOINING = 2;
public static final int PSP_NET_APCTL_STATE_GETTING_IP = 3;
public static final int PSP_NET_APCTL_STATE_GOT_IP = 4;
public static final int PSP_NET_APCTL_STATE_EAP_AUTH = 5;
public static final int PSP_NET_APCTL_STATE_KEY_EXCHANGE = 6;
public static final int PSP_NET_APCTL_EVENT_CONNECT_REQUEST = 0;
public static final int PSP_NET_APCTL_EVENT_SCAN_REQUEST = 1;
public static final int PSP_NET_APCTL_EVENT_SCAN_COMPLETE = 2;
public static final int PSP_NET_APCTL_EVENT_ESTABLISHED = 3;
public static final int PSP_NET_APCTL_EVENT_GET_IP = 4;
public static final int PSP_NET_APCTL_EVENT_DISCONNECT_REQUEST = 5;
public static final int PSP_NET_APCTL_EVENT_ERROR = 6;
public static final int PSP_NET_APCTL_EVENT_INFO = 7;
public static final int PSP_NET_APCTL_EVENT_EAP_AUTH = 8;
public static final int PSP_NET_APCTL_EVENT_KEY_EXCHANGE = 9;
public static final int PSP_NET_APCTL_EVENT_RECONNECT = 10;
public static final int PSP_NET_APCTL_INFO_PROFILE_NAME = 0;
public static final int PSP_NET_APCTL_INFO_BSSID = 1;
public static final int PSP_NET_APCTL_INFO_SSID = 2;
public static final int PSP_NET_APCTL_INFO_SSID_LENGTH = 3;
public static final int PSP_NET_APCTL_INFO_SECURITY_TYPE = 4;
public static final int PSP_NET_APCTL_INFO_STRENGTH = 5;
public static final int PSP_NET_APCTL_INFO_CHANNEL = 6;
public static final int PSP_NET_APCTL_INFO_POWER_SAVE = 7;
public static final int PSP_NET_APCTL_INFO_IP = 8;
public static final int PSP_NET_APCTL_INFO_SUBNETMASK = 9;
public static final int PSP_NET_APCTL_INFO_GATEWAY = 10;
public static final int PSP_NET_APCTL_INFO_PRIMDNS = 11;
public static final int PSP_NET_APCTL_INFO_SECDNS = 12;
public static final int PSP_NET_APCTL_INFO_USE_PROXY = 13;
public static final int PSP_NET_APCTL_INFO_PROXY_URL = 14;
public static final int PSP_NET_APCTL_INFO_PROXY_PORT = 15;
public static final int PSP_NET_APCTL_INFO_8021_EAP_TYPE = 16;
public static final int PSP_NET_APCTL_INFO_START_BROWSER = 17;
public static final int PSP_NET_APCTL_INFO_WIFISP = 18;
public static final int PSP_NET_APCTL_INFO_UNKNOWN19 = 19;
private static final String[] apctlInfoNames = new String[] {
"PROFILE_NAME",
"BSSID",
"SSID",
"SSID_LENGTH",
"SECURITY_TYPE",
"STRENGTH",
"CHANNEL",
"POWER_SAVE",
"IP",
"SUBNETMASK",
"GATEWAY",
"PRIMDNS",
"SECDNS",
"USE_PROXY",
"PROXY_URL",
"PROXY_PORT",
"8021_EAP_TYPE",
"START_BROWSER",
"WIFISP"
};
public static final int PSP_NET_APCTL_INFO_SECURITY_TYPE_NONE = 0;
public static final int PSP_NET_APCTL_INFO_SECURITY_TYPE_WEP = 1;
public static final int PSP_NET_APCTL_INFO_SECURITY_TYPE_WPA_TKIP = 2;
public static final int PSP_NET_APCTL_INFO_SECURITY_TYPE_UNSUPPORTED = 3;
public static final int PSP_NET_APCTL_INFO_SECURITY_TYPE_WPA_AES = 4;
public static final int PSP_NET_APCTL_DESC_IBSS = 0;
public static final int PSP_NET_APCTL_DESC_SSID_NAME = 1;
public static final int PSP_NET_APCTL_DESC_SSID_NAME_LENGTH = 2;
public static final int PSP_NET_APCTL_DESC_SIGNAL_STRENGTH = 4;
public static final int PSP_NET_APCTL_DESC_SECURITY = 5;
public static final int SSID_NAME_LENGTH = 32;
private static final String dummyPrimaryDNS = "1.2.3.4";
private static final String dummySecondaryDNS = "1.2.3.5";
private static final String dummySubnetMask = "255.255.255.0";
private static final int dummySubnetMaskInt = 0xFFFFFF00;
protected static final String uidPurpose = "sceNetApctl";
protected static final String uidHandlerPurpose = "sceNetApctlHandler";
protected int state = PSP_NET_APCTL_STATE_DISCONNECTED;
protected int connectionIndex = 0;
private static String localHostIP;
private HashMap<Integer, ApctlHandler> apctlHandlers = new HashMap<Integer, ApctlHandler>();
protected static final int stateTransitionDelay = 100000; // 100ms
protected SceKernelThreadInfo sceNetApctlThread;
protected boolean sceNetApctlThreadTerminate;
private boolean doScan;
private volatile long scanStartMillis;
private static final int SCAN_DURATION_MILLIS = 700;
@Override
public void stop() {
sceNetApctlThread = null;
sceNetApctlThreadTerminate = false;
doScan = false;
apctlHandlers.clear();
super.stop();
}
protected class ApctlHandler {
private int id;
private int addr;
private int pArg;
private ApctlHandler(int id, int addr, int pArg) {
this.id = id;
this.addr = addr;
this.pArg = pArg;
}
protected void triggerHandler(int oldState, int newState, int event, int error) {
SceKernelThreadInfo thread = Modules.ThreadManForUserModule.getCurrentThread();
if (thread != null) {
if (log.isDebugEnabled()) {
log.debug(String.format("Triggering hanlder 0x%08X, oldState=%d, newState=%d, event=%d, error=0x%08X", addr, oldState, newState, event, error));
}
Modules.ThreadManForUserModule.executeCallback(thread, addr, null, true, oldState, newState, event, error, pArg);
}
}
@Override
public String toString() {
return String.format("ApctlHandler[id=%d, addr=0x%08X, pArg=0x%08X]", id, addr, pArg);
}
}
protected void notifyHandler(int oldState, int newState, int event, int error) {
for (ApctlHandler handler : apctlHandlers.values()) {
handler.triggerHandler(oldState, newState, event, error);
}
}
protected void changeState(int newState) {
int oldState = state;
int error = 0;
int event;
if (newState == oldState) {
// State not changed, no notification
return;
}
// The event is set to match tests done on a real PSP
switch (newState) {
case PSP_NET_APCTL_STATE_JOINING:
event = PSP_NET_APCTL_EVENT_CONNECT_REQUEST;
break;
case PSP_NET_APCTL_STATE_GETTING_IP:
event = PSP_NET_APCTL_EVENT_ESTABLISHED;
break;
case PSP_NET_APCTL_STATE_GOT_IP:
event = PSP_NET_APCTL_EVENT_GET_IP;
break;
case PSP_NET_APCTL_STATE_DISCONNECTED:
if (oldState == PSP_NET_APCTL_STATE_SCANNING) {
event = PSP_NET_APCTL_EVENT_SCAN_COMPLETE;
} else {
event = PSP_NET_APCTL_EVENT_DISCONNECT_REQUEST;
}
break;
case PSP_NET_APCTL_STATE_SCANNING:
event = PSP_NET_APCTL_EVENT_SCAN_REQUEST;
break;
default:
event = PSP_NET_APCTL_EVENT_CONNECT_REQUEST;
break;
}
// Set the new state before calling the handler, in case
// the handler is calling back sceNetApctl (e.g. sceNetApctlDisconnect()).
state = newState;
notifyHandler(oldState, newState, event, error);
if (newState == PSP_NET_APCTL_STATE_JOINING) {
triggerNetApctlThread();
}
}
protected static String getApctlInfoName(int code) {
if (code < 0 || code >= apctlInfoNames.length) {
return String.format("Unknown Info %d", code);
}
return apctlInfoNames[code];
}
public static String getSSID() {
String ssid = null;
try {
ssid = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()).getDisplayName();
} catch (SocketException e) {
log.error(e);
} catch (UnknownHostException e) {
log.error(e);
}
return ssid;
}
public static String getPrimaryDNS() {
String ip = getLocalHostIP();
if (ip != null) {
// Try to guess the primary DNS by replacing the last part of our
// IP address with 1.
// e.g.: ip=A.B.C.D -> primaryDNS=A.B.C.1
int lastDot = ip.lastIndexOf(".");
if (lastDot >= 0) {
String primaryDNS = ip.substring(0, lastDot) + ".1";
return primaryDNS;
}
}
return dummyPrimaryDNS;
}
public static String getSecondaryDNS() {
return dummySecondaryDNS;
}
public static String getGateway() {
String gateway = getLocalHostIP();
// Replace last component of the local IP with "1".
// E.g. "192.168.1.10" -> "192.168.1.1"
int lastDot = gateway.lastIndexOf('.');
if (lastDot >= 0) {
gateway = gateway.substring(0, lastDot + 1) + "1";
}
return gateway;
}
public static String getSubnetMask() {
return dummySubnetMask;
}
public static int getSubnetMaskInt() {
return dummySubnetMaskInt;
}
/**
* Returns the best IP address for the local host.
* The best IP address is defined as follows:
* - in all the IPv4 address of the local host, one IP address not being
* a gateway address (not X.X.X.1).
* E.g. such gateway addresses are defined for VMware bridges.
* - if no such address is found, take the IP address returned by
* InetAddress.getLocalHost().getHostAddress()
* - if everything fails, take a dummy address "192.168.1.1"
*
* @return the best IP address for the local host
*/
public static String getLocalHostIP() {
if (localHostIP == null) {
localHostIP = "192.168.1.1";
try {
localHostIP = InetAddress.getLocalHost().getHostAddress();
InetAddress localHostAddress = InetAddress.getLocalHost();
InetAddress[] allLocalIPs = InetAddress.getAllByName(localHostAddress.getHostName());
for (int i = 0; allLocalIPs != null && i < allLocalIPs.length; i++) {
if (log.isDebugEnabled()) {
log.debug(String.format("IP address of local host: %s", allLocalIPs[i].getHostAddress()));
}
byte[] bytes = allLocalIPs[i].getAddress();
if (bytes != null && bytes.length == 4 && bytes[3] != 1) {
localHostIP = allLocalIPs[i].getHostAddress();
}
}
if (log.isDebugEnabled()) {
log.debug(String.format("Using IP address of local host: %s, Subnet Mask %s", localHostIP, getSubnetMask()));
}
} catch (UnknownHostException e) {
log.error(e);
}
}
return localHostIP;
}
public void hleNetApctlConnect(int index) {
if (log.isDebugEnabled()) {
log.debug(String.format("hleNetApctlConnect index=%d", index));
}
connectionIndex = index;
changeState(PSP_NET_APCTL_STATE_JOINING);
}
public int hleNetApctlGetState() {
return state;
}
protected void triggerNetApctlThread() {
if (sceNetApctlThread != null) {
Modules.ThreadManForUserModule.hleKernelWakeupThread(sceNetApctlThread);
}
}
public void hleNetApctlThread(Processor processor) {
if (log.isDebugEnabled()) {
log.debug(String.format("hleNetApctlThread state=%d", state));
}
if (sceNetApctlThreadTerminate) {
processor.cpu._v0 = 0; // Exit status
Modules.ThreadManForUserModule.hleKernelExitDeleteThread();
sceNetApctlThread = null;
} else {
boolean stateTransitionCompleted = true;
// Make a transition to the next state
switch (state) {
case PSP_NET_APCTL_STATE_JOINING:
changeState(PSP_NET_APCTL_STATE_GETTING_IP);
stateTransitionCompleted = false;
break;
case PSP_NET_APCTL_STATE_GETTING_IP:
changeState(PSP_NET_APCTL_STATE_GOT_IP);
break;
case PSP_NET_APCTL_STATE_DISCONNECTED:
if (doScan) {
scanStartMillis = Emulator.getClock().milliTime();
changeState(PSP_NET_APCTL_STATE_SCANNING);
doScan = false;
stateTransitionCompleted = false;
}
break;
case PSP_NET_APCTL_STATE_SCANNING:
// End of SCAN?
long now = Emulator.getClock().milliTime();
if (now - scanStartMillis > SCAN_DURATION_MILLIS) {
// Return to DISCONNECTED state and trigger SCAN event
changeState(PSP_NET_APCTL_STATE_DISCONNECTED);
} else {
stateTransitionCompleted = false;
}
}
if (stateTransitionCompleted) {
if (log.isDebugEnabled()) {
log.debug(String.format("hleNetApctlThread sleeping with state=%d", state));
}
// Wait for a new state reset... wakeup is done by triggerNetApctlThread()
Modules.ThreadManForUserModule.hleKernelSleepThread(false);
} else {
if (log.isDebugEnabled()) {
log.debug(String.format("hleNetApctlThread waiting for %d us with state=%d", stateTransitionDelay, state));
}
// Wait a little bit before moving to the next state...
Modules.ThreadManForUserModule.hleKernelDelayThread(stateTransitionDelay, false);
}
}
}
/**
* Init the apctl.
*
* @param stackSize - The stack size of the internal thread.
*
* @param initPriority - The priority of the internal thread.
*
* @return < 0 on error.
*/
@HLEFunction(nid = 0xE2F91F9B, version = 150)
public int sceNetApctlInit(int stackSize, int initPriority) {
if (sceNetApctlThread == null) {
ThreadManForUser threadMan = Modules.ThreadManForUserModule;
sceNetApctlThread = threadMan.hleKernelCreateThread("SceNetApctl",
ThreadManForUser.NET_APCTL_LOOP_ADDRESS, initPriority, stackSize,
threadMan.getCurrentThread().attr, 0, SysMemUserForUser.USER_PARTITION_ID);
sceNetApctlThreadTerminate = false;
threadMan.hleKernelStartThread(sceNetApctlThread, 0, 0, sceNetApctlThread.gpReg_addr);
}
return 0;
}
/**
* Terminate the apctl.
*
* @return < 0 on error.
*/
@HLEFunction(nid = 0xB3EDD0EC, version = 150)
public int sceNetApctlTerm() {
changeState(PSP_NET_APCTL_STATE_DISCONNECTED);
sceNetApctlThreadTerminate = true;
triggerNetApctlThread();
return 0;
}
/**
* Get the apctl information.
*
* @param code - One of the PSP_NET_APCTL_INFO_* defines.
*
* @param pInfo - Pointer to a ::SceNetApctlInfo.
*
* @return < 0 on error.
*/
// union SceNetApctlInfo
// {
// char name[64]; /* Name of the config used */
// unsigned char bssid[6]; /* MAC address of the access point */
// unsigned char ssid[32]; /* ssid */
// unsigned int ssidLength; /* ssid string length*/
// unsigned int securityType; /* 0 for none, 1 for WEP, 2 for WPA) */
// unsigned char strength; /* Signal strength in % */
// unsigned char channel; /* Channel */
// unsigned char powerSave; /* 1 on, 0 off */
// char ip[16]; /* PSP's ip */
// char subNetMask[16]; /* Subnet mask */
// char gateway[16]; /* Gateway */
// char primaryDns[16]; /* Primary DNS */
// char secondaryDns[16]; /* Secondary DNS */
// unsigned int useProxy; /* 1 for proxy, 0 for no proxy */
// char proxyUrl[128]; /* Proxy url */
// unsigned short proxyPort; /* Proxy port */
// unsigned int eapType; /* 0 is none, 1 is EAP-MD5 */
// unsigned int startBrowser; /* Should browser be started */
// unsigned int wifisp; /* 1 if connection is for Wifi service providers (WISP) */
//
// };
@HLEFunction(nid = 0x2BEFDF23, version = 150)
public int sceNetApctlGetInfo(int code, TPointer pInfo) {
if (log.isDebugEnabled()) {
log.debug(String.format("sceNetApctlGetInfo code=0x%X(%s)", code, getApctlInfoName(code)));
}
switch (code) {
case PSP_NET_APCTL_INFO_PROFILE_NAME: {
String name = sceUtility.getNetParamName(connectionIndex);
pInfo.setStringNZ(128, name);
if (log.isDebugEnabled()) {
log.debug(String.format("sceNetApctlGetInfo returning Profile name '%s'", name));
}
break;
}
case PSP_NET_APCTL_INFO_IP: {
String ip = getLocalHostIP();
pInfo.setStringNZ(16, ip);
if (log.isDebugEnabled()) {
log.debug(String.format("sceNetApctlGetInfo returning IP address '%s'", ip));
}
break;
}
case PSP_NET_APCTL_INFO_SSID: {
String ssid = getSSID();
if (ssid == null) {
return -1;
}
pInfo.setStringNZ(SSID_NAME_LENGTH, ssid);
if (log.isDebugEnabled()) {
log.debug(String.format("sceNetApctlGetInfo returning SSID '%s'", ssid));
}
break;
}
case PSP_NET_APCTL_INFO_SSID_LENGTH: {
String ssid = getSSID();
if (ssid == null) {
return -1;
}
pInfo.setValue32(Math.min(ssid.length(), SSID_NAME_LENGTH));
break;
}
case PSP_NET_APCTL_INFO_PRIMDNS: {
pInfo.setStringNZ(16, getPrimaryDNS());
break;
}
case PSP_NET_APCTL_INFO_SECDNS: {
pInfo.setStringNZ(16, getSecondaryDNS());
break;
}
case PSP_NET_APCTL_INFO_GATEWAY: {
pInfo.setStringNZ(16, getGateway());
break;
}
case PSP_NET_APCTL_INFO_SUBNETMASK: {
pInfo.setStringNZ(16, getSubnetMask());
break;
}
case PSP_NET_APCTL_INFO_CHANNEL: {
int channel = Settings.getInstance().readInt("emu.sysparam.adhocchannel", 0);
pInfo.setValue8((byte) channel);
break;
}
case PSP_NET_APCTL_INFO_STRENGTH: {
pInfo.setValue8((byte) Wlan.getSignalStrenth());
break;
}
case PSP_NET_APCTL_INFO_USE_PROXY: {
pInfo.setValue32(false); // Don't use proxy
break;
}
case PSP_NET_APCTL_INFO_START_BROWSER: {
// Is it needed to start the browser to login/authenticate
// this connection?
pInfo.setValue32(false); // Do not start the browser
break;
}
case PSP_NET_APCTL_INFO_UNKNOWN19: {
// The PSP is returning value 1 (tested with JpcspTrace)
pInfo.setValue32(1);
break;
}
default: {
log.warn(String.format("sceNetApctlGetInfo unimplemented code=0x%X(%s)", code, getApctlInfoName(code)));
return -1;
}
}
return 0;
}
/**
* Add an apctl event handler.
*
* @param handler - Pointer to the event handler function.
* typedef void (*sceNetApctlHandler)(int oldState, int newState, int event, int error, void *pArg)
*
* @param pArg - Value to be passed to the pArg parameter of the handler function.
*
* @return A handler id or < 0 on error.
*/
@HLEFunction(nid = 0x8ABADD51, version = 150)
public int sceNetApctlAddHandler(TPointer handler, int handlerArg) {
int uid = SceUidManager.getNewUid(uidPurpose);
ApctlHandler apctlHandler = new ApctlHandler(uid, handler.getAddress(), handlerArg);
apctlHandlers.put(uid, apctlHandler);
return uid;
}
/**
* Delete an apctl event handler.
*
* @param handlerid - A handler as created returned from sceNetApctlAddHandler.
*
* @return < 0 on error.
*/
@HLEFunction(nid = 0x5963991B, version = 150)
public int sceNetApctlDelHandler(int handlerId) {
if (!apctlHandlers.containsKey(handlerId)) {
log.warn(String.format("sceNetApctlDelHandler unknown handlerId=0x%X", handlerId));
return -1;
}
SceUidManager.releaseUid(handlerId, uidPurpose);
apctlHandlers.remove(handlerId);
return 0;
}
/**
* Connect to an access point.
*
* @param connIndex - The index of the connection.
*
* @return < 0 on error.
*/
@HLEFunction(nid = 0xCFB957C6, version = 150)
public int sceNetApctlConnect(int connIndex) {
hleNetApctlConnect(connIndex);
return 0;
}
/**
* Disconnect from an access point.
*
* @return < 0 on error.
*/
@HLEFunction(nid = 0x24FE91A1, version = 150)
public int sceNetApctlDisconnect() {
changeState(PSP_NET_APCTL_STATE_DISCONNECTED);
return 0;
}
/**
* Get the state of the access point connection.
*
* @param pState - Pointer to receive the current state (one of the PSP_NET_APCTL_STATE_* defines).
*
* @return < 0 on error.
*/
@HLEFunction(nid = 0x5DEAC81B, version = 150)
public int sceNetApctlGetState(@BufferInfo(usage=Usage.out) TPointer32 stateAddr) {
stateAddr.setValue(state);
return 0;
}
@HLEUnimplemented
@HLEFunction(nid = 0x2935C45B, version = 150)
public int sceNetApctlGetBSSDescEntry2() {
return 0;
}
@HLEUnimplemented
@HLEFunction(nid = 0xA3E77E13, version = 150)
public int sceNetApctlScanSSID2() {
return 0;
}
@HLEUnimplemented
@HLEFunction(nid = 0xF25A5006, version = 150)
public int sceNetApctlGetBSSDescIDList2() {
return 0;
}
@HLEFunction(nid = 0xE9B2E5E6, version = 150)
public int sceNetApctlScanUser() {
doScan = true;
triggerNetApctlThread();
return 0;
}
@HLEFunction(nid = 0x6BDDCB8C, version = 150)
public int sceNetApctlGetBSSDescIDListUser(TPointer32 sizeAddr, @CanBeNull TPointer buf) {
final int userInfoSize = 8;
int entries = 1;
int size = sizeAddr.getValue();
// Return size required
sizeAddr.setValue(entries * userInfoSize);
if (buf.isNotNull()) {
int offset = 0;
for (int i = 0; i < entries; i++) {
// Check if enough space available to write the next structure
if (offset + userInfoSize > size) {
break;
}
if (log.isDebugEnabled()) {
log.debug(String.format("sceNetApctlGetBSSDescIDListUser returning %d at 0x%08X", i, buf.getAddress() + offset));
}
/** Pointer to next Network structure in list: will be written later */
offset += 4;
/** Entry ID */
buf.setValue32(offset, i);
offset += 4;
}
fillNextPointersInLinkedList(buf, offset, userInfoSize);
}
return 0;
}
@HLEFunction(nid = 0x04776994, version = 150)
public int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, TPointer result) {
switch (infoId) {
case PSP_NET_APCTL_DESC_IBSS: // IBSS, 6 bytes
String ibss = Modules.sceNetAdhocctlModule.hleNetAdhocctlGetIBSS();
result.setStringNZ(IBSS_NAME_LENGTH, ibss);
break;
case PSP_NET_APCTL_DESC_SSID_NAME:
// Return 32 bytes
String ssid = getSSID();
result.setStringNZ(SSID_NAME_LENGTH, ssid);
break;
case PSP_NET_APCTL_DESC_SSID_NAME_LENGTH:
// Return one 32-bit value
int length = Math.min(getSSID().length(), SSID_NAME_LENGTH);
result.setValue32(length);
break;
case PSP_NET_APCTL_DESC_SIGNAL_STRENGTH:
// Return 1 byte
result.setValue8((byte) Wlan.getSignalStrenth());
break;
case PSP_NET_APCTL_DESC_SECURITY:
// Return one 32-bit value
result.setValue32(PSP_NET_APCTL_INFO_SECURITY_TYPE_WPA_AES);
break;
default:
log.warn(String.format("sceNetApctlGetBSSDescEntryUser unknown id %d", infoId));
return -1;
}
return 0;
}
@HLEFunction(nid = 0x7CFAB990, version = 150)
public int sceNetApctlAddInternalHandler(TPointer handler, int handlerArg) {
// This seems to be a 2nd kind of handler
return sceNetApctlAddHandler(handler, handlerArg);
}
@HLEFunction(nid = 0xE11BAFAB, version = 150)
public int sceNetApctlDelInternalHandler(int handlerId) {
// This seems to be a 2nd kind of handler
return sceNetApctlDelHandler(handlerId);
}
@HLEUnimplemented
@HLEFunction(nid = 0xA7BB73DF, version = 150)
public int sceNetApctl_A7BB73DF(TPointer handler, int handlerArg) {
// This seems to be a 3rd kind of handler
return sceNetApctlAddHandler(handler, handlerArg);
}
@HLEUnimplemented
@HLEFunction(nid = 0x6F5D2981, version = 150)
public int sceNetApctl_6F5D2981(int handlerId) {
// This seems to be a 3rd kind of handler
return sceNetApctlDelHandler(handlerId);
}
@HLEUnimplemented
@HLEFunction(nid = 0x69745F0A, version = 150)
public int sceNetApctl_lib2_69745F0A(int handlerId) {
return 0;
}
@HLEUnimplemented
@HLEFunction(nid = 0x4C19731F, version = 150)
public int sceNetApctl_lib2_4C19731F(int code, TPointer pInfo) {
return sceNetApctlGetInfo(code, pInfo);
}
@HLEFunction(nid = 0xB3CF6849, version = 150)
public int sceNetApctlScan() {
return sceNetApctlScanUser();
}
@HLEFunction(nid = 0x0C7FFA5C, version = 150)
public int sceNetApctlGetBSSDescIDList(TPointer32 sizeAddr, @CanBeNull TPointer buf) {
return sceNetApctlGetBSSDescIDListUser(sizeAddr, buf);
}
@HLEFunction(nid = 0x96BEB231, version = 150)
public int sceNetApctlGetBSSDescEntry(int entryId, int infoId, TPointer result) {
return sceNetApctlGetBSSDescEntryUser(entryId, infoId, result);
}
@HLEUnimplemented
@HLEFunction(nid = 0xC20A144C, version = 150)
public int sceNetApctl_lib2_C20A144C(int connIndex, pspNetMacAddress ps3MacAddress) {
return sceNetApctlConnect(connIndex);
}
}