summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/includes/xbox_usb.h
blob: 4adf16edaf19dc06cee88efaf037c892abb662a8 (plain) (tree)
1
2
3
4

                                    

                                












                                     


                                             

                             
                       








                                 



                                             






                                          





                                                      




























                           
                                                 



                                           
                                                       




                                              







































                                                     





























































                                                          




                              


                                    













                                   


                                           







                                    


                                       








                                   


                                      





                                 




































































                            
                          


                 
                                    
 
                          




                                                                              
                          
 
                          
                 
                                                                              





                                                                    
                          
                 
                                                            

  



                      
                                           
 
                         

       
                              
                                 
                                                              
                                                                               


                                                                                                    
 


                                                                               



                                      

                                   





                                                                                  
                                                     
                              
                
                                      
                        
                                                




                                    
                                                



                                 


                                        


                                            
                                     



                                                                                  

  



                             
                     
       
                        
                                                          


                                             
                                                                   
                                                                               







                                                                                                     


                                                                                                           




                                                                                                
                                                              


                                                         


                                                                         






                                        

                                    





                               
                             





                                                                     
                                                        


                                                         















                                                                                                            
                                                           








                                                                        
                                                                      
 
                                                                                                            

       
                                                                                                                     
                                                           
                                                                                     
                                                                                            
























                                                                                      

                                  
// license:BSD-3-Clause
// copyright-holders:Samuele Zannoli
#ifndef MAME_INCLUDES_XBOX_USB_H
#define MAME_INCLUDES_XBOX_USB_H

#pragma once

#include <forward_list>

struct OHCIEndpointDescriptor {
	int mps; // MaximumPacketSize
	int f; // Format
	int k; // sKip
	int s; // Speed
	int d; // Direction
	int en; // EndpointNumber
	int fa; // FunctionAddress
	uint32_t tailp; // TDQueueTailPointer
	uint32_t headp; // TDQueueHeadPointer
	uint32_t nexted; // NextED
	int c; // toggleCarry
	int h; // Halted
	uint32_t word0;
};

struct OHCITransferDescriptor {
	int cc; // ConditionCode
	int ec; // ErrorCount
	int t; // DataToggle
	int di; // DelayInterrupt
	int dp; // Direction/PID
	int r; // bufferRounding
	uint32_t cbp; // CurrentBufferPointer
	uint32_t nexttd; // NextTD
	uint32_t be; // BufferEnd
	uint32_t word0;
};

struct OHCIIsochronousTransferDescriptor {
	int cc; // ConditionCode
	int fc; // FrameCount
	int di; // DelayInterrupt
	int sf; // StartingFrame
	uint32_t bp0; // BufferPage0
	uint32_t nexttd; // NextTD
	uint32_t be; // BufferEnd
	uint32_t offset[8]; // Offset/PacketStatusWord
	uint32_t word0;
	uint32_t word1;
};

enum OHCIRegisters {
	HcRevision=0,
	HcControl,
	HcCommandStatus,
	HcInterruptStatus,
	HcInterruptEnable,
	HcInterruptDisable,
	HcHCCA,
	HcPeriodCurrentED,
	HcControlHeadED,
	HcControlCurrentED,
	HcBulkHeadED,
	HcBulkCurrentED,
	HcDoneHead,
	HcFmInterval,
	HcFmRemaining,
	HcFmNumber,
	HcPeriodicStart,
	HcLSThreshold,
	HcRhDescriptorA,
	HcRhDescriptorB,
	HcRhStatus,
	HcRhPortStatus1
};

enum HcControlBits
{
	CBSR = 3 << 0, // ControlBulkServiceRatio
	PLE = 1 << 2, // PeriodicListEnable
	IE = 1 << 3, // IsochronousEnable
	CLE = 1 << 4, // ControlListEnable
	BLE = 1 << 5, // BulkListEnable
	HCFS = 3 << 6, // HostControllerFunctionalState
	IR = 1 << 8, // InterruptRouting
	RWC = 1 << 9, // RemoteWakeupConnected
	RWE = 1 << 10 // RemoteWakeupEnable
};

enum HcCommandStatusBits
{
	HCR = 1 << 0, // HostControllerReset
	CLF = 1 << 1, // ControlListFilled
	BLF = 1 << 2, // BulkListFilled
	OCR = 1 << 3, // OwnershipChangeRequest
	SOC = 3 << 16 // SchedulingOverrunCount
};

enum HcInterruptEnableBits
{
	SO = 1 << 0, // SchedulingOverrun
	WDH = 1 << 1, // WritebackDoneHead
	SF = 1 << 2, // StartofFrame
	RD = 1 << 3, // ResumeDetected
	UE = 1 << 4, // UnrecoverableError
	FNO = 1 << 5, // FrameNumberOverflow
	RHSC = 1 << 6, // RootHubStatusChange
	OC = 1 << 30, // OwnershipChange
	MIE = 1 << 31, // MasterInterruptEnable
};


enum HcRhDescriptorABits
{
	NDP = 0xff << 0, // NumberDownstreamPorts
	PSM = 1 << 8, // PowerSwitchingMode
	NPS = 1 << 9, // NoPowerSwitching
	DT = 1 << 10, // DeviceType
	OCPM = 1 << 11, // OverCurrentProtectionMode
	NOCPM = 1 << 12, // NoOverCurrentProtection
	POTPGT = 0xff << 24 // PowerOnToPowerGoodTime
};

enum HcRhDescriptorBBits
{
	DR = 0xffff << 0, // DeviceRemovable
	PPCM = 0xffff << 16 // PortPowerControlMask
};

enum HcRhStatusBits
{
	LPS = 1 << 0, // LocalPowerStatus
	OCI = 1 << 1, // OverCurrentIndicator
	DRWE = 1 << 15, // DeviceRemoteWakeupEnable
	LPSC = 1 << 16, // LocalPowerStatusChange
	OCIC = 1 << 17, // OverCurrentIndicatorChange
	CRWE = 1 << 31, // ClearRemoteWakeupEnable
};

enum HcRhPortStatusBits
{
	CCS = 1 << 0, // CurrentConnectStatus
	PES = 1 << 1, // PortEnableStatus
	PSS = 1 << 2, // PortSuspendStatus
	POCI = 1 << 3, // PortOverCurrentIndicator
	PRS = 1 << 4, // PortResetStatus
	PPS = 1 << 8, // PortPowerStatus
	LSDA = 1 << 9, // LowSpeedDeviceAttached
	CSC = 1 << 16, // ConnectStatusChange
	PESC = 1 << 17, // PortEnableStatusChange
	PSSC = 1 << 18, // PortSuspendStatusChange
	POCIC = 1 << 19, // PortOverCurrentIndicatorChange
	PRSC = 1 << 20 // PortResetStatusChange
};

enum OHCIHostControllerFunctionalState {
	UsbReset=0,
	UsbResume,
	UsbOperational,
	UsbSuspend
};

enum OHCIInterrupt {
	SchedulingOverrun=1,
	WritebackDoneHead=2,
	StartofFrame=4,
	ResumeDetected=8,
	UnrecoverableError=16,
	FrameNumberOverflow=32,
	RootHubStatusChange=64,
	OwnershipChange=0x40000000,
	MasterInterruptEnable=0x80000000
};

enum OHCICompletionCode {
	NoError=0,
	CRC,
	BitStuffing,
	DataToggleMismatch,
	Stall,
	DeviceNotResponding,
	PIDCheckFailure,
	UnexpectedPID,
	DataOverrun,
	DataUnderrun,
	BufferOverrun=12,
	BufferUnderrun,
	NotAccessed=14
};

struct USBSetupPacket {
	uint8_t bmRequestType;
	uint8_t bRequest;
	uint16_t wValue;
	uint16_t wIndex;
	uint16_t wLength;
};

struct USBStandardDeviceDescriptor {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint16_t bcdUSB;
	uint8_t bDeviceClass;
	uint8_t bDeviceSubClass;
	uint8_t bDeviceProtocol;
	uint8_t bMaxPacketSize0;
	uint16_t idVendor;
	uint16_t idProduct;
	uint16_t bcdDevice;
	uint8_t iManufacturer;
	uint8_t iProduct;
	uint8_t iSerialNumber;
	uint8_t bNumConfigurations;
};

struct USBStandardConfigurationDescriptor {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint16_t wTotalLength;
	uint8_t bNumInterfaces;
	uint8_t bConfigurationValue;
	uint8_t iConfiguration;
	uint8_t bmAttributes;
	uint8_t MaxPower;
};

struct USBStandardInterfaceDescriptor {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint8_t bInterfaceNumber;
	uint8_t bAlternateSetting;
	uint8_t bNumEndpoints;
	uint8_t bInterfaceClass;
	uint8_t bInterfaceSubClass;
	uint8_t bInterfaceProtocol;
	uint8_t iInterface;
};

struct USBStandardEndpointDescriptor {
	uint8_t bLength;
	uint8_t bDescriptorType;
	uint8_t bEndpointAddress;
	uint8_t bmAttributes;
	uint16_t wMaxPacketSize;
	uint8_t bInterval;
};

enum USBPid {
	SetupPid=0,
	OutPid,
	InPid
};

enum USBRequestCode {
	GET_STATUS=0,
	CLEAR_FEATURE=1,
	SET_FEATURE=3,
	SET_ADDRESS=5,
	GET_DESCRIPTOR=6,
	SET_DESCRIPTOR=7,
	GET_CONFIGURATION=8,
	SET_CONFIGURATION=9,
	GET_INTERFACE=10,
	SET_INTERFACE=11,
	SYNCH_FRAME=12
};

enum USBDescriptorType {
	DEVICE=1,
	CONFIGURATION=2,
	STRING=3,
	INTERFACE=4,
	ENDPOINT=5
};

enum USBRequestType
{
	StandardType=0,
	ClassType,
	VendorType,
	ReservedType
};

enum USBRequestRecipient
{
	DeviceRecipient=0,
	InterfaceRecipient,
	EndpointRecipient,
	OtherRecipient
};

enum USBDeviceState
{
	DefaultState,
	AddressState,
	ConfiguredState
};

enum USBControlDirection
{
	HostToDevice=0,
	DeviceToHost=1
};

enum USBEndpointType
{
	ControlEndpoint=0,
	IsochronousEndpoint,
	BulkEndpoint,
	InterruptEndpoint
};

struct usb_device_string
{
	uint8_t *position;
	int size;
};

struct usb_device_interfac_alternate
{
	uint8_t *position;
	int size;
	USBStandardInterfaceDescriptor interface_descriptor;
	std::forward_list<USBStandardEndpointDescriptor> endpoint_descriptors;
};

struct usb_device_interfac
{
	uint8_t *position;
	int size;
	std::forward_list<usb_device_interfac_alternate *> alternate_settings;
	int selected_alternate;
};

struct usb_device_configuration
{
	USBStandardConfigurationDescriptor configuration_descriptor;
	uint8_t *position;
	int size;
	std::forward_list<usb_device_interfac *> interfaces;
};

/*
 * OHCI Usb Controller
 */

class ohci_function; // forward declaration

class ohci_usb_controller
{
public:
	ohci_usb_controller();
	~ohci_usb_controller() {}
	void usb_ohci_plug(int port, ohci_function *function);
	void usb_ohci_device_address_changed(int old_address, int new_address);
	void set_cpu(cpu_device *cpu) { m_maincpu = cpu; }
	void set_timer(emu_timer *timer) { ohcist.timer = timer; }
	void set_irq_callbaclk(std::function<void(int state)> callback) { irq_callback = callback; }

	void start();
	void reset();
	void timer(emu_timer &timer, device_timer_id id, int param, void *ptr);

	DECLARE_READ32_MEMBER(read);
	DECLARE_WRITE32_MEMBER(write);

private:
	void usb_ohci_interrupts();
	void usb_ohci_read_endpoint_descriptor(uint32_t address);
	void usb_ohci_writeback_endpoint_descriptor(uint32_t address);
	void usb_ohci_read_transfer_descriptor(uint32_t address);
	void usb_ohci_writeback_transfer_descriptor(uint32_t address);
	void usb_ohci_read_isochronous_transfer_descriptor(uint32_t address);
	void usb_ohci_writeback_isochronous_transfer_descriptor(uint32_t address);
	std::function<void (int state)> irq_callback;
	cpu_device *m_maincpu;
	struct {
		uint32_t hc_regs[256];
		struct {
			ohci_function *function;
			int address;
			int delay;
		} ports[4 + 1];
		struct
		{
			ohci_function *function;
			int port;
		} address[256];
		emu_timer *timer;
		int state;
		uint32_t framenumber;
		uint32_t nextinterupted;
		uint32_t nextbulked;
		int interruptbulkratio;
		int writebackdonehadcounter;
		address_space *space;
		uint8_t buffer[1024];
		OHCIEndpointDescriptor endpoint_descriptor;
		OHCITransferDescriptor transfer_descriptor;
		OHCIIsochronousTransferDescriptor isochronous_transfer_descriptor;
	} ohcist;
};

/*
 * Base class for usb devices
 */

class ohci_function {
public:
	ohci_function();
	virtual void initialize(running_machine &machine);
	virtual void execute_reset();
	virtual void execute_connect() {};
	virtual void execute_disconnect() {};
	void set_bus_manager(ohci_usb_controller *usb_bus_manager);
	int execute_transfer(int endpoint, int pid, uint8_t *buffer, int size);
protected:
	virtual int handle_nonstandard_request(int endpoint, USBSetupPacket *setup) { return -1; };
	virtual int handle_get_status_request(int endpoint, USBSetupPacket *setup) { return 0; };
	virtual int handle_clear_feature_request(int endpoint, USBSetupPacket *setup) { return 0; };
	virtual int handle_set_feature_request(int endpoint, USBSetupPacket *setup) { return 0; };
	virtual int handle_set_descriptor_request(int endpoint, USBSetupPacket *setup) { return 0; };
	virtual int handle_synch_frame_request(int endpoint, USBSetupPacket *setup) { return 0; };
	virtual void handle_status_stage(int endpoint) { return; };
	virtual int handle_bulk_pid(int endpoint, int pid, uint8_t *buffer, int size) { return 0; };
	virtual int handle_interrupt_pid(int endpoint, int pid, uint8_t *buffer, int size) { return 0; };
	virtual int handle_isochronous_pid(int endpoint, int pid, uint8_t *buffer, int size) { return 0; };

	void add_device_descriptor(const USBStandardDeviceDescriptor &descriptor);
	void add_configuration_descriptor(const USBStandardConfigurationDescriptor &descriptor);
	void add_interface_descriptor(const USBStandardInterfaceDescriptor &descriptor);
	void add_endpoint_descriptor(const USBStandardEndpointDescriptor &descriptor);
	void add_string_descriptor(const uint8_t *descriptor);
	void select_configuration(int index);
	void select_alternate(int interfacei, int index);
	int find_alternate(int interfacei);
	uint8_t *position_device_descriptor(int &size);
	uint8_t *position_configuration_descriptor(int index, int &size);
	uint8_t *position_string_descriptor(int index, int &size);
	ohci_usb_controller *busmanager;
	struct {
		int type;
		int controldirection;
		int controltype;
		int controlrecipient;
		int remain;
		uint8_t *position;
		uint8_t buffer[128];
	} endpoints[256];
	int state;
	bool settingaddress;
	int newaddress;
	int address;
	int configurationvalue;
	uint8_t *descriptors;
	int descriptors_pos;
	bool wantstatuscallback;
	USBStandardDeviceDescriptor device_descriptor;
	std::forward_list<usb_device_configuration *> configurations;
	std::forward_list<usb_device_string *> device_strings;
	usb_device_configuration *latest_configuration;
	usb_device_interfac_alternate *latest_alternate;
	usb_device_configuration *selected_configuration;
};

/*
 * Usb port connector
 */

class ohci_usb_connector : public device_t, public device_slot_interface
{
public:
	ohci_usb_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
	virtual ~ohci_usb_connector();

	ohci_function *get_device();

protected:
	virtual void device_start() override;
};

DECLARE_DEVICE_TYPE(OHCI_USB_CONNECTOR, ohci_usb_connector)

#define MCFG_USB_PORT_ADD(_tag, _slot_intf, _def_slot, _fixed) \
	MCFG_DEVICE_ADD(_tag, OHCI_USB_CONNECTOR, 0)                   \
	MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, _fixed)

/*
 * Game controller usb device
 */

DECLARE_DEVICE_TYPE(OHCI_GAME_CONTROLLER, ohci_game_controller_device)

class ohci_game_controller_device : public device_t, public ohci_function, public device_slot_card_interface
{
public:
	ohci_game_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
	void initialize(running_machine &machine) override;
	int handle_nonstandard_request(int endpoint, USBSetupPacket *setup) override;
	int handle_interrupt_pid(int endpoint, int pid, uint8_t *buffer, int size) override;

protected:
	virtual void device_start() override;
	virtual ioport_constructor device_input_ports() const override;
private:
	static const USBStandardDeviceDescriptor devdesc;
	static const USBStandardConfigurationDescriptor condesc;
	static const USBStandardInterfaceDescriptor intdesc;
	static const USBStandardEndpointDescriptor enddesc82;
	static const USBStandardEndpointDescriptor enddesc02;
	required_ioport m_ThumbstickLh; // left analog thumbstick horizontal movement
	required_ioport m_ThumbstickLv; // left analog thumbstick vertical movement
	required_ioport m_ThumbstickRh; // right analog thumbstick horizontal movement
	required_ioport m_ThumbstickRv; // right analog thumbstick vertical movement
	required_ioport m_DPad; // pressure sensitive directional pad
	required_ioport m_TriggerL; // analog trigger
	required_ioport m_TriggerR; // analog trigger
	required_ioport m_Buttons; // digital buttons
	required_ioport m_AGreen; // analog button
	required_ioport m_BRed; // analog button
	required_ioport m_XBlue; // analog button
	required_ioport m_YYellow; // analog button
	required_ioport m_Black; // analog button
	required_ioport m_White; // analog button
};

#endif // MAME_INCLUDES_XBOX_USB_H