summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author yz70s <yz70s@users.noreply.github.com>2016-02-27 09:59:40 +0100
committer yz70s <yz70s@users.noreply.github.com>2016-03-07 22:17:58 +0100
commitd9a00119f4df57e7845524dfcbd3408ab58d9173 (patch)
tree827a5a5f847be3e99dafa576e07469e63adbfb25
parentb61b025eab66d07488f10ba3b932d92d1476ba37 (diff)
xbox.cpp: more usb (nw)
-rw-r--r--src/mame/includes/xbox.h68
-rw-r--r--src/mame/machine/xbox.cpp313
2 files changed, 310 insertions, 71 deletions
diff --git a/src/mame/includes/xbox.h b/src/mame/includes/xbox.h
index 8094ac33100..045d7504700 100644
--- a/src/mame/includes/xbox.h
+++ b/src/mame/includes/xbox.h
@@ -1,6 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:Samuele Zannoli
+#include <forward_list>
+
struct OHCIEndpointDescriptor {
int mps; // MaximumPacketSize
int f; // Format
@@ -211,29 +213,79 @@ enum USBDeviceState
ConfiguredState
};
+enum USBControlDirection
+{
+ HostToDevice=0,
+ DeviceToHost=1
+};
+
+enum USBEndpointType
+{
+ ControlEndpoint=0,
+ IsochronousEndpoint,
+ BulkEndpoint,
+ InterruptEndpoint
+};
+
+struct usb_device_interface_alternate
+{
+ USBStandardInterfaceDescriptor interface_descriptor;
+ std::forward_list<USBStandardEndpointDescriptor> endpoint_descriptors;
+};
+
+struct usb_device_interface
+{
+ std::forward_list<usb_device_interface_alternate> alternate_settings;
+ int selected_alternate;
+};
+
+struct usb_device_configuration
+{
+ USBStandardConfigurationDescriptor configuration_descriptor;
+ std::forward_list<usb_device_interface> interfaces;
+};
+
class ohci_function_device {
public:
ohci_function_device(running_machine &machine);
void execute_reset();
int execute_transfer(int address, int endpoint, int pid, UINT8 *buffer, int size);
+protected:
+ int handle_nonstandard_request(int endpoint, USBSetupPacket *setup);
+ virtual int handle_get_status_request(int endpoint, USBSetupPacket *setup) = 0;
+ virtual int handle_clear_feature_request(int endpoint, USBSetupPacket *setup) = 0;
+ virtual int handle_set_feature_request(int endpoint, USBSetupPacket *setup) = 0;
+ virtual int handle_set_descriptor_request(int endpoint, USBSetupPacket *setup) = 0;
+ virtual int handle_synch_frame_request(int endpoint, USBSetupPacket *setup) = 0;
private:
void add_device_descriptor(USBStandardDeviceDescriptor &descriptor);
void add_configuration_descriptor(USBStandardConfigurationDescriptor &descriptor);
void add_interface_descriptor(USBStandardInterfaceDescriptor &descriptor);
void add_endpoint_descriptor(USBStandardEndpointDescriptor &descriptor);
- int handle_nonstandard_request(USBSetupPacket *setup);
+ void select_configuration(int index);
+ void select_alternate(int interfacei, int index);
+ int find_alternate(int interfacei);
+ struct {
+ int type;
+ int controldirection;
+ int controltype;
+ int controlrecipient;
+ int remain;
+ UINT8 *position;
+ UINT8 buffer[4];
+ } endpoints[256];
int state;
- int address;
+ bool settingaddress;
int newaddress;
- int controldirection;
- int controltype;
- int controlrecipient;
+ int address;
int configurationvalue;
- bool settingaddress;
- int remain;
- UINT8 *position;
UINT8 *descriptors;
int descriptors_pos;
+ USBStandardDeviceDescriptor device_descriptor;
+ std::forward_list<usb_device_configuration> configurations;
+ usb_device_configuration *latest_configuration;
+ usb_device_interface_alternate *latest_alternate;
+ usb_device_configuration *selected_configuration;
};
class xbox_base_state : public driver_device
diff --git a/src/mame/machine/xbox.cpp b/src/mame/machine/xbox.cpp
index 5748e09d469..2f8de78b4b4 100644
--- a/src/mame/machine/xbox.cpp
+++ b/src/mame/machine/xbox.cpp
@@ -846,13 +846,19 @@ ohci_function_device::ohci_function_device(running_machine &machine)
descriptors_pos = 0;
address = 0;
newaddress = 0;
- controldirection = 0;
- controltype = 0;
- controlrecipient = 0;
- configurationvalue = 0;
- remain = 0;
- position = nullptr;
+ for (int e = 0; e < 256;e++) {
+ endpoints[e].type = -1;
+ endpoints[e].controldirection = 0;
+ endpoints[e].controltype = 0;
+ endpoints[e].controlrecipient = 0;
+ endpoints[e].remain = 0;
+ endpoints[e].position = nullptr;
+ }
+ endpoints[0].type = ControlEndpoint;
settingaddress = false;
+ configurationvalue = 0;
+ latest_configuration = nullptr;
+ latest_alternate = nullptr;
add_device_descriptor(devdesc);
add_configuration_descriptor(condesc);
add_interface_descriptor(intdesc);
@@ -862,26 +868,175 @@ ohci_function_device::ohci_function_device(running_machine &machine)
void ohci_function_device::add_device_descriptor(USBStandardDeviceDescriptor &descriptor)
{
- memcpy(descriptors + descriptors_pos, &descriptor, sizeof(descriptor));
+ UINT8 *p = descriptors + descriptors_pos;
+
+ p[0] = descriptor.bLength;
+ p[1] = descriptor.bDescriptorType;
+ p[2] = descriptor.bcdUSB & 255;
+ p[3] = descriptor.bcdUSB >> 8;
+ p[4] = descriptor.bDeviceClass;
+ p[5] = descriptor.bDeviceSubClass;
+ p[6] = descriptor.bDeviceProtocol;
+ p[7] = descriptor.bMaxPacketSize0;
+ p[8] = descriptor.idVendor & 255;
+ p[9] = descriptor.idVendor >> 8;
+ p[10] = descriptor.idProduct & 255;
+ p[11] = descriptor.idProduct >> 8;
+ p[12] = descriptor.bcdDevice & 255;
+ p[13] = descriptor.bcdDevice >> 8;
+ p[14] = descriptor.iManufacturer;
+ p[15] = descriptor.iProduct;
+ p[16] = descriptor.iSerialNumber;
+ p[17] = descriptor.bNumConfigurations;
descriptors_pos += descriptor.bLength;
+ memcpy(&device_descriptor, &descriptor, sizeof(USBStandardDeviceDescriptor));
}
void ohci_function_device::add_configuration_descriptor(USBStandardConfigurationDescriptor &descriptor)
{
- memcpy(descriptors + descriptors_pos, &descriptor, sizeof(descriptor));
+ usb_device_configuration *c = new usb_device_configuration;
+ UINT8 *p = descriptors + descriptors_pos;
+
+ p[0] = descriptor.bLength;
+ p[1] = descriptor.bDescriptorType;
+ p[2] = descriptor.wTotalLength & 255;
+ p[3] = descriptor.wTotalLength >> 8;
+ p[4] = descriptor.bNumInterfaces;
+ p[5] = descriptor.bConfigurationValue;
+ p[6] = descriptor.iConfiguration;
+ p[7] = descriptor.bmAttributes;
+ p[8] = descriptor.MaxPower;
descriptors_pos += descriptor.bLength;
+ memcpy(&c->configuration_descriptor, &descriptor, sizeof(USBStandardConfigurationDescriptor));
+ configurations.push_front(*c);
+ latest_configuration = c;
+ latest_alternate = nullptr;
}
void ohci_function_device::add_interface_descriptor(USBStandardInterfaceDescriptor &descriptor)
{
- memcpy(descriptors + descriptors_pos, &descriptor, sizeof(descriptor));
+ usb_device_interface *ii;
+ usb_device_interface_alternate *aa;
+ UINT8 *p = descriptors + descriptors_pos;
+
+ if (latest_configuration == nullptr)
+ return;
+ p[0] = descriptor.bLength;
+ p[1] = descriptor.bDescriptorType;
+ p[2] = descriptor.bInterfaceNumber;
+ p[3] = descriptor.bAlternateSetting;
+ p[4] = descriptor.bNumEndpoints;
+ p[5] = descriptor.bInterfaceClass;
+ p[6] = descriptor.bInterfaceSubClass;
+ p[7] = descriptor.bInterfaceProtocol;
+ p[8] = descriptor.iInterface;
descriptors_pos += descriptor.bLength;
+ for (auto i = latest_configuration->interfaces.begin(); i != latest_configuration->interfaces.end(); ++i)
+ {
+ if (i->alternate_settings.front().interface_descriptor.bInterfaceNumber == descriptor.bInterfaceNumber)
+ {
+ aa = new usb_device_interface_alternate;
+ memcpy(&aa->interface_descriptor, &descriptor, sizeof(USBStandardInterfaceDescriptor));
+ i->alternate_settings.push_front(*aa);
+ latest_alternate = aa;
+ return;
+ }
+ }
+ ii = new usb_device_interface;
+ aa = new usb_device_interface_alternate;
+ memcpy(&aa->interface_descriptor, &descriptor, sizeof(USBStandardInterfaceDescriptor));
+ ii->selected_alternate = -1;
+ ii->alternate_settings.push_front(*aa);
+ latest_alternate = aa;
+ latest_configuration->interfaces.push_front(*ii);
}
void ohci_function_device::add_endpoint_descriptor(USBStandardEndpointDescriptor &descriptor)
{
- memcpy(descriptors + descriptors_pos, &descriptor, sizeof(descriptor));
+ UINT8 *p = descriptors + descriptors_pos;
+
+ if (latest_alternate == nullptr)
+ return;
+ p[0] = descriptor.bLength;
+ p[1] = descriptor.bDescriptorType;
+ p[2] = descriptor.bEndpointAddress;
+ p[3] = descriptor.bmAttributes;
+ p[4] = descriptor.wMaxPacketSize & 255;
+ p[5] = descriptor.wMaxPacketSize >> 8;
+ p[6] = descriptor.bInterval;
descriptors_pos += descriptor.bLength;
+ latest_alternate->endpoint_descriptors.push_front(descriptor);
+}
+
+void ohci_function_device::select_configuration(int index)
+{
+ configurationvalue = index;
+ for (auto c = configurations.begin(); c != configurations.end(); ++c)
+ {
+ if (c->configuration_descriptor.bConfigurationValue == index)
+ {
+ selected_configuration = &(*c);
+ for (auto i = c->interfaces.begin(); i != c->interfaces.end(); ++i)
+ {
+ i->selected_alternate = 0;
+ for (auto a = i->alternate_settings.begin(); a != i->alternate_settings.end(); ++a)
+ {
+ if (a->interface_descriptor.bAlternateSetting == 0)
+ {
+ for (auto e = a->endpoint_descriptors.begin(); e != a->endpoint_descriptors.end(); ++e)
+ {
+ endpoints[e->bEndpointAddress].type = e->bmAttributes & 3;
+ endpoints[e->bEndpointAddress].remain = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void ohci_function_device::select_alternate(int interfacei, int index)
+{
+ for (auto i = selected_configuration->interfaces.begin(); i != selected_configuration->interfaces.end(); ++i)
+ {
+ for (auto a = i->alternate_settings.begin(); a != i->alternate_settings.end(); ++a)
+ {
+ if ((a->interface_descriptor.bInterfaceNumber == interfacei) && (a->interface_descriptor.bAlternateSetting == i->selected_alternate))
+ {
+ for (auto e = a->endpoint_descriptors.begin(); e != a->endpoint_descriptors.end(); ++e)
+ {
+ endpoints[e->bEndpointAddress].type = -1;
+ }
+ }
+ }
+ for (auto a = i->alternate_settings.begin(); a != i->alternate_settings.end(); ++a)
+ {
+ if ((a->interface_descriptor.bInterfaceNumber == interfacei) && (a->interface_descriptor.bAlternateSetting == index))
+ {
+ i->selected_alternate = index;
+ for (auto e = a->endpoint_descriptors.begin(); e != a->endpoint_descriptors.end(); ++e)
+ {
+ endpoints[e->bEndpointAddress].type = e->bmAttributes & 3;
+ endpoints[e->bEndpointAddress].remain = 0;
+ }
+ }
+ }
+ }
+}
+
+int ohci_function_device::find_alternate(int interfacei)
+{
+ for (auto i = selected_configuration->interfaces.begin(); i != selected_configuration->interfaces.end(); ++i)
+ {
+ for (auto a = i->alternate_settings.begin(); a != i->alternate_settings.end(); ++a)
+ {
+ if (a->interface_descriptor.bInterfaceNumber == interfacei)
+ {
+ return i->selected_alternate;
+ }
+ }
+ }
+ return 0;
}
void ohci_function_device::execute_reset()
@@ -894,25 +1049,30 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
{
int descriptortype;// descriptorindex;
- if (endpoint == 0) {
- if (pid == SetupPid) {
- USBSetupPacket *p=(USBSetupPacket *)buffer;
- // define direction 0:host->device 1:device->host
- controldirection = (p->bmRequestType & 128) >> 7;
- // case ==1, IN data stage and OUT status stage
- // case ==0, OUT data stage and IN status stage
- // data stage is optional, IN status stage
- controltype = (p->bmRequestType & 0x60) >> 5;
- controlrecipient = p->bmRequestType & 0x1f;
- position = nullptr;
+ if (pid == SetupPid) {
+ USBSetupPacket *p=(USBSetupPacket *)buffer;
+ // define direction 0:host->device 1:device->host
+ // case == 1, IN data stage and OUT status stage
+ // case == 0, OUT data stage and IN status stage
+ // data stage is optional, IN status stage
+ endpoints[endpoint].controldirection = (p->bmRequestType & 128) >> 7;
+ endpoints[endpoint].controltype = (p->bmRequestType & 0x60) >> 5;
+ endpoints[endpoint].controlrecipient = p->bmRequestType & 0x1f;
+ if (endpoint == 0) {
+ endpoints[endpoint].position = nullptr;
// number of byte to transfer in data stage (0 no data stage)
- remain = p->wLength;
+ endpoints[endpoint].remain = p->wLength;
// if standard device request
- if ((controltype == StandardType) && (controlrecipient == DeviceRecipient)) {
+ if ((endpoints[endpoint].controltype == StandardType) && (endpoints[endpoint].controlrecipient == DeviceRecipient)) {
switch (p->bRequest) {
case GET_STATUS:
+ return handle_get_status_request(endpoint, p);
+ break;
case CLEAR_FEATURE:
+ return handle_clear_feature_request(endpoint, p);
+ break;
case SET_FEATURE:
+ return handle_set_feature_request(endpoint, p);
break;
case SET_ADDRESS:
newaddress = p->wValue;
@@ -922,52 +1082,74 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
descriptortype = p->wValue >> 8;
//descriptorindex = p->wValue & 255;
if (descriptortype == DEVICE) { // device descriptor
- position = descriptors;
- remain = descriptors[0];
+ endpoints[endpoint].position = descriptors;
+ endpoints[endpoint].remain = descriptors[0];
}
else if (descriptortype == CONFIGURATION) { // configuration descriptor
- position = descriptors + 18;
- remain = descriptors[18+2];
+ endpoints[endpoint].position = descriptors + 18;
+ endpoints[endpoint].remain = descriptors[18 + 2];
}
else if (descriptortype == INTERFACE) { // interface descriptor
- position = descriptors + 18 + 9;
- remain = descriptors[18 + 9];
+ endpoints[endpoint].position = descriptors + 18 + 9;
+ endpoints[endpoint].remain = descriptors[18 + 9];
}
else if (descriptortype == ENDPOINT) { // endpoint descriptor
- position = descriptors + 18 + 9 + 9;
- remain = descriptors[18 + 9 + 9];
+ endpoints[endpoint].position = descriptors + 18 + 9 + 9;
+ endpoints[endpoint].remain = descriptors[18 + 9 + 9];
}
else
- remain = 0;
- if (remain > p->wLength)
- remain = p->wLength;
+ endpoints[endpoint].remain = 0;
+ if (endpoints[endpoint].remain > p->wLength)
+ endpoints[endpoint].remain = p->wLength;
break;
case SET_CONFIGURATION:
if (p->wValue == 0)
state = AddressState;
else {
- configurationvalue = p->wValue;
+ select_configuration(p->wValue);
state = ConfiguredState;
}
break;
+ case SET_INTERFACE:
+ select_alternate(p->wIndex, p->wValue);
+ break;
case SET_DESCRIPTOR:
+ return handle_set_descriptor_request(endpoint, p);
+ break;
case GET_CONFIGURATION:
+ endpoints[endpoint].buffer[0] = (UINT8)configurationvalue;
+ endpoints[endpoint].position = endpoints[endpoint].buffer;
+ endpoints[endpoint].remain = 1;
+ if (p->wLength == 0)
+ endpoints[endpoint].remain = 0;
+ break;
case GET_INTERFACE:
- case SET_INTERFACE:
+ endpoints[endpoint].buffer[0] = (UINT8)find_alternate(p->wIndex);
+ endpoints[endpoint].position = endpoints[endpoint].buffer;
+ endpoints[endpoint].remain = 1;
+ if (p->wLength == 0)
+ endpoints[endpoint].remain = 0;
+ break;
case SYNCH_FRAME:
+ return handle_synch_frame_request(endpoint, p);
default:
+ return handle_nonstandard_request(endpoint, p);
break;
}
}
else
- return handle_nonstandard_request(p);
+ return handle_nonstandard_request(endpoint, p);
size = 0;
}
- else if (pid == InPid) {
+ else
+ return handle_nonstandard_request(endpoint, p);
+ }
+ else if (pid == InPid) {
+ if (endpoint == 0) {
// if no data has been transferred (except for the setup stage)
// and the lenght of this IN transaction is 0
// assume this is the status stage
- if ((size == 0) && (remain == 0)) {
+ if ((size == 0) && (endpoints[endpoint].remain == 0)) {
if (settingaddress == true)
{
// set of address is active at end of status stage
@@ -980,53 +1162,58 @@ int ohci_function_device::execute_transfer(int address, int endpoint, int pid, U
// case ==1, give data
// case ==0, nothing
// if device->host
- if (controldirection == 1) {
+ if (endpoints[endpoint].controldirection == DeviceToHost) {
// data stage
- if (size > remain)
- size = remain;
- if (position != nullptr)
- memcpy(buffer, position, size);
- position = position + size;
- remain = remain - size;
+ if (size > endpoints[endpoint].remain)
+ size = endpoints[endpoint].remain;
+ if (endpoints[endpoint].position != nullptr)
+ memcpy(buffer, endpoints[endpoint].position, size);
+ endpoints[endpoint].position = endpoints[endpoint].position + size;
+ endpoints[endpoint].remain = endpoints[endpoint].remain - size;
}
}
- else if (pid == OutPid) {
+ else
+ return -1;
+ }
+ else if (pid == OutPid) {
+ if (endpoint == 0) {
// case ==1, nothing
// case ==0, give data
// if host->device
- if (controldirection == 0) {
+ if (endpoints[endpoint].controldirection == HostToDevice) {
// data stage
- if (size > remain)
- size = remain;
- if (position != nullptr)
- memcpy(position, buffer, size);
- position = position + size;
- remain = remain - size;
+ if (size > endpoints[endpoint].remain)
+ size = endpoints[endpoint].remain;
+ if (endpoints[endpoint].position != nullptr)
+ memcpy(endpoints[endpoint].position, buffer, size);
+ endpoints[endpoint].position = endpoints[endpoint].position + size;
+ endpoints[endpoint].remain = endpoints[endpoint].remain - size;
}
}
+ else
+ return -1;
}
- else
- return -1;
return size;
}
-int ohci_function_device::handle_nonstandard_request(USBSetupPacket *setup)
+int ohci_function_device::handle_nonstandard_request(int endpoint, USBSetupPacket *setup)
{
// >=8 ==42 !=0 !=0 1,3 2<20 <=20
static UINT8 mytestdata[16] = { 0x10,0x42 ,0x32,0x43,1 ,0x65,0x18,0x20,0x98,0xa9,0xba,0xcb,0xdc,0xed,0xfe };
- if ((controltype == VendorType) && (controlrecipient == InterfaceRecipient))
+ if ((endpoints[endpoint].controltype == VendorType) && (endpoints[endpoint].controlrecipient == InterfaceRecipient))
{
if (setup->bRequest == GET_DESCRIPTOR)
{
if (setup->wValue == 0x4200)
{
- position = mytestdata;
- remain = 16;
+ endpoints[endpoint].position = mytestdata;
+ endpoints[endpoint].remain = 16;
+ return 0;
}
}
}
- return 0;
+ return -1;
}
void xbox_base_state::usb_ohci_interrupts()
@@ -1232,8 +1419,8 @@ WRITE32_MEMBER(xbox_base_state::audio_apu_w)
return;
}
if (offset == 0x2037c / 4) { // value related to sample rate
- INT16 v = (INT16)(data >> 16); // upper 16 bits as a signed 16 bit value
- float vv = ((float)v) / 4096.0f; // divide by 4096
+ INT16 v0 = (INT16)(data >> 16); // upper 16 bits as a signed 16 bit value
+ float vv = ((float)v0) / 4096.0f; // divide by 4096
float vvv = powf(2, vv); // two to the vv
int f = vvv*48000.0f; // sample rate
apust.voices_frequency[apust.voice_number] = f;