/*
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 java.util.HashMap;
import jpcsp.HLE.CanBeNull;
import jpcsp.HLE.HLEFunction;
import jpcsp.HLE.HLEModule;
import jpcsp.HLE.HLEModuleManager;
import jpcsp.HLE.HLEUnimplemented;
import jpcsp.HLE.PspString;
import jpcsp.HLE.TPointer;
import jpcsp.HLE.TPointer32;
import org.apache.log4j.Logger;
import jpcsp.HLE.Modules;
import jpcsp.HLE.kernel.Managers;
import jpcsp.HLE.kernel.types.SceKernelThreadInfo;
import jpcsp.HLE.kernel.types.SceModule;
import jpcsp.hardware.Usb;
public class sceUsb extends HLEModule {
public static Logger log = Modules.getLogger("sceUsb");
public static final String PSP_USBBUS_DRIVERNAME = "USBBusDriver";
public static final int PSP_USB_CONNECTION_NOT_ESTABLISHED = 0x001;
public static final int PSP_USB_CONNECTION_ESTABLISHED = 0x002;
public static final int PSP_USB_CABLE_DISCONNECTED = 0x010;
public static final int PSP_USB_CABLE_CONNECTED = 0x020;
public static final int PSP_USB_DEACTIVATED = 0x100;
public static final int PSP_USB_ACTIVATED = 0x200;
protected static final int WAIT_MODE_ANDOR_MASK = 0x1;
protected static final int WAIT_MODE_AND = 0x0;
protected static final int WAIT_MODE_OR = 0x1;
protected boolean usbActivated = false;
protected boolean usbStarted = false;
protected HashMap<String, SceModule> loadedModules;
protected int callbackId = -1;
@Override
public void start() {
usbActivated = false;
usbStarted = false;
loadedModules = new HashMap<String, SceModule>();
super.start();
}
protected int getUsbState() {
int state = Usb.isCableConnected() ? PSP_USB_CABLE_CONNECTED : PSP_USB_CABLE_DISCONNECTED;
// USB has been activated?
state |= usbActivated ? PSP_USB_ACTIVATED : PSP_USB_DEACTIVATED;
// USB has been started?
state |= usbStarted ? PSP_USB_CONNECTION_ESTABLISHED : PSP_USB_CONNECTION_NOT_ESTABLISHED;
return state;
}
protected boolean matchState(int waitState, int waitMode) {
int state = getUsbState();
if ((waitMode & WAIT_MODE_ANDOR_MASK) == WAIT_MODE_AND) {
// WAIT_MODE_AND
return (state & waitState) == waitState;
}
// WAIT_MODE_OR
return (state & waitState) != 0;
}
protected void notifyCallback() {
if (callbackId >= 0) {
Modules.ThreadManForUserModule.hleKernelNotifyCallback(SceKernelThreadInfo.THREAD_CALLBACK_USB, getUsbState());
}
}
/**
* Start a USB driver.
*
* @param driverName - name of the USB driver to start
* @param size - Size of arguments to pass to USB driver start
* @param args - Arguments to pass to USB driver start
*
* @return 0 on success
*/
@HLEUnimplemented
@HLEFunction(nid = 0xAE5DE6AF, version = 150)
public int sceUsbStart(String driverName, int size, @CanBeNull TPointer args) {
usbStarted = true;
HLEModuleManager moduleManager = HLEModuleManager.getInstance();
if (moduleManager.hasFlash0Module(driverName)) {
log.info(String.format("Loading HLE module '%s'", driverName));
int sceModuleId = moduleManager.LoadFlash0Module(driverName);
SceModule module = Managers.modules.getModuleByUID(sceModuleId);
loadedModules.put(driverName, module);
}
notifyCallback();
return 0;
}
/**
* Stop a USB driver.
*
* @param driverName - name of the USB driver to stop
* @param size - Size of arguments to pass to USB driver start
* @param args - Arguments to pass to USB driver start
*
* @return 0 on success
*/
@HLEUnimplemented
@HLEFunction(nid = 0xC2464FA0, version = 150)
public int sceUsbStop(PspString driverName, int size, @CanBeNull TPointer args) {
usbStarted = false;
SceModule module = loadedModules.remove(driverName);
if (module != null) {
HLEModuleManager moduleManager = HLEModuleManager.getInstance();
moduleManager.UnloadFlash0Module(module);
}
notifyCallback();
return 0;
}
/**
* Get USB state
*
* @return OR'd PSP_USB_* constants
*/
@HLEFunction(nid = 0xC21645A4, version = 150)
public int sceUsbGetState() {
if (log.isDebugEnabled()) {
log.debug(String.format("sceUsbGetState returning 0x%X", getUsbState()));
}
return getUsbState();
}
@HLEFunction(nid = 0x4E537366, version = 150)
public int sceUsbGetDrvList(int unknown1, int unknown2, int unknown3) {
log.warn(String.format("Unimplemented sceUsbGetDrvList unknown1=0x%08X, unknown2=0x%08X, unknown3=0x%08X", unknown1, unknown2, unknown3));
return 0;
}
/**
* Get state of a specific USB driver
*
* @param driverName - name of USB driver to get status from
*
* @return 1 if the driver has been started, 2 if it is stopped
*/
@HLEUnimplemented
@HLEFunction(nid = 0x112CC951, version = 150)
public int sceUsbGetDrvState(PspString driverName) {
return 0;
}
/**
* Activate a USB driver.
*
* @param pid - Product ID for the default USB Driver
*
* @return 0 on success
*/
@HLEFunction(nid = 0x586DB82C, version = 150)
public int sceUsbActivate(int pid) {
return sceUsbActivateWithCharging(pid, false);
}
/**
* Deactivate USB driver.
*
* @param pid - Product ID for the default USB driver
*
* @return 0 on success
*/
@HLEFunction(nid = 0xC572A9C8, version = 150)
public int sceUsbDeactivate(int pid) {
usbActivated = false;
notifyCallback();
return 0;
}
@HLEFunction(nid = 0x5BE0E002, version = 150)
public int sceUsbWaitState(int state, int waitMode, @CanBeNull TPointer32 timeoutAddr) {
if (!matchState(state, waitMode)) {
log.warn(String.format("Unimplemented sceUsbWaitState state=0x%X, waitMode=0x%X, timeoutAddr=%s - non-matching state not implemented", state, waitMode, timeoutAddr));
Modules.ThreadManForUserModule.hleBlockCurrentThread(SceKernelThreadInfo.JPCSP_WAIT_USB);
return 0;
}
int usbState = getUsbState();
if (log.isDebugEnabled()) {
log.debug(String.format("sceUsbWaitState returning 0x%X", usbState));
}
return usbState;
}
@HLEFunction(nid = 0x616F2B61, version = 150)
public int sceUsbWaitStateCB(int state, int waitMode, @CanBeNull TPointer32 timeoutAddr) {
if (!matchState(state, waitMode)) {
log.warn(String.format("Unimplemented sceUsbWaitStateCB state=0x%X, waitMode=0x%X, timeoutAddr=%s - non-matching state not implemented", state, waitMode, timeoutAddr));
Modules.ThreadManForUserModule.hleBlockCurrentThread(SceKernelThreadInfo.JPCSP_WAIT_USB);
return 0;
}
int usbState = getUsbState();
if (log.isDebugEnabled()) {
log.debug(String.format("sceUsbWaitStateCB returning 0x%X", usbState));
}
return usbState;
}
@HLEUnimplemented
@HLEFunction(nid = 0x1C360735, version = 150)
public int sceUsbWaitCancel() {
return 0;
}
@HLEUnimplemented
@HLEFunction(nid = 0x8BFC3DE8, version = 150)
public int sceUsb_8BFC3DE8(int callbackId, int unknown1, int unknown2) {
// Registering a callback?
if (Modules.ThreadManForUserModule.hleKernelRegisterCallback(SceKernelThreadInfo.THREAD_CALLBACK_USB, callbackId)) {
this.callbackId = callbackId;
notifyCallback();
}
return 0;
}
@HLEUnimplemented
@HLEFunction(nid = 0x89DE0DC5, version = 150)
public int sceUsb_89DE0DC5(int callbackId) {
// Unregistering a callback?
if (this.callbackId == callbackId) {
this.callbackId = -1;
}
return 0;
}
/**
* Activate a USB driver.
*
* @param pid - Product ID for the default USB Driver
* @param charging - charging the PSP while the USB is connected?
*
* @return 0 on success
*/
@HLEFunction(nid = 0xE20B23A6, version = 150)
public int sceUsbActivateWithCharging(int pid, boolean charging) {
usbActivated = true;
notifyCallback();
return 0;
}
}