mirror of https://github.com/PCSX2/pcsx2.git
parent
f416fd7a9e
commit
4ace75151f
|
@ -4,6 +4,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "USB/qemu-usb/qusb.h"
|
#include "USB/qemu-usb/qusb.h"
|
||||||
|
#include "common/Pcsx2Types.h"
|
||||||
|
|
||||||
/* Dump packet contents. */
|
/* Dump packet contents. */
|
||||||
//#define DEBUG_PACKET
|
//#define DEBUG_PACKET
|
||||||
|
@ -15,59 +16,59 @@
|
||||||
#define OHCI_MAX_PORTS 15 // status regs from 0x0c54 but usb snooping
|
#define OHCI_MAX_PORTS 15 // status regs from 0x0c54 but usb snooping
|
||||||
// reg is at 0x0c80, so only 11 ports?
|
// reg is at 0x0c80, so only 11 ports?
|
||||||
|
|
||||||
extern int64_t g_usb_frame_time;
|
extern s64 g_usb_frame_time;
|
||||||
extern int64_t g_usb_bit_time;
|
extern s64 g_usb_bit_time;
|
||||||
|
|
||||||
typedef struct OHCIPort
|
typedef struct OHCIPort
|
||||||
{
|
{
|
||||||
USBPort port;
|
USBPort port;
|
||||||
uint32_t ctrl;
|
u32 ctrl;
|
||||||
} OHCIPort;
|
} OHCIPort;
|
||||||
|
|
||||||
typedef uint32_t target_phys_addr_t;
|
typedef u32 target_phys_addr_t;
|
||||||
|
|
||||||
typedef struct OHCIState
|
typedef struct OHCIState
|
||||||
{
|
{
|
||||||
target_phys_addr_t mem_base;
|
target_phys_addr_t mem_base;
|
||||||
uint32_t num_ports;
|
u32 num_ports;
|
||||||
|
|
||||||
uint64_t eof_timer;
|
u64 eof_timer;
|
||||||
int64_t sof_time;
|
s64 sof_time;
|
||||||
|
|
||||||
/* OHCI state */
|
/* OHCI state */
|
||||||
/* Control partition */
|
/* Control partition */
|
||||||
uint32_t ctl, status;
|
u32 ctl, status;
|
||||||
uint32_t intr_status;
|
u32 intr_status;
|
||||||
uint32_t intr;
|
u32 intr;
|
||||||
|
|
||||||
/* memory pointer partition */
|
/* memory pointer partition */
|
||||||
uint32_t hcca;
|
u32 hcca;
|
||||||
uint32_t ctrl_head, ctrl_cur;
|
u32 ctrl_head, ctrl_cur;
|
||||||
uint32_t bulk_head, bulk_cur;
|
u32 bulk_head, bulk_cur;
|
||||||
uint32_t per_cur;
|
u32 per_cur;
|
||||||
uint32_t done;
|
u32 done;
|
||||||
int32_t done_count;
|
s32 done_count;
|
||||||
|
|
||||||
/* Frame counter partition */
|
/* Frame counter partition */
|
||||||
uint32_t fsmps : 15;
|
u32 fsmps : 15;
|
||||||
uint32_t fit : 1;
|
u32 fit : 1;
|
||||||
uint32_t fi : 14;
|
u32 fi : 14;
|
||||||
uint32_t frt : 1;
|
u32 frt : 1;
|
||||||
uint16_t frame_number;
|
uint16_t frame_number;
|
||||||
uint16_t padding;
|
uint16_t padding;
|
||||||
uint32_t pstart;
|
u32 pstart;
|
||||||
uint32_t lst;
|
u32 lst;
|
||||||
|
|
||||||
/* Root Hub partition */
|
/* Root Hub partition */
|
||||||
uint32_t rhdesc_a, rhdesc_b;
|
u32 rhdesc_a, rhdesc_b;
|
||||||
uint32_t rhstatus;
|
u32 rhstatus;
|
||||||
OHCIPort rhport[OHCI_MAX_PORTS];
|
OHCIPort rhport[OHCI_MAX_PORTS];
|
||||||
|
|
||||||
/* Active packets. */
|
/* Active packets. */
|
||||||
uint32_t old_ctl;
|
u32 old_ctl;
|
||||||
USBPacket usb_packet;
|
USBPacket usb_packet;
|
||||||
uint8_t usb_buf[8192];
|
uint8_t usb_buf[8192];
|
||||||
uint32_t async_td;
|
u32 async_td;
|
||||||
bool async_complete;
|
bool async_complete;
|
||||||
|
|
||||||
} OHCIState;
|
} OHCIState;
|
||||||
|
@ -75,9 +76,9 @@ typedef struct OHCIState
|
||||||
/* Host Controller Communications Area */
|
/* Host Controller Communications Area */
|
||||||
struct ohci_hcca
|
struct ohci_hcca
|
||||||
{
|
{
|
||||||
uint32_t intr[32];
|
u32 intr[32];
|
||||||
uint16_t frame, pad;
|
u16 frame, pad;
|
||||||
uint32_t done;
|
u32 done;
|
||||||
};
|
};
|
||||||
|
|
||||||
//ISO C++ forbids declaration of ‘typeof’ with no type
|
//ISO C++ forbids declaration of ‘typeof’ with no type
|
||||||
|
@ -158,29 +159,29 @@ struct ohci_hcca
|
||||||
/* endpoint descriptor */
|
/* endpoint descriptor */
|
||||||
struct ohci_ed
|
struct ohci_ed
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
u32 flags;
|
||||||
uint32_t tail;
|
u32 tail;
|
||||||
uint32_t head;
|
u32 head;
|
||||||
uint32_t next;
|
u32 next;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* General transfer descriptor */
|
/* General transfer descriptor */
|
||||||
struct ohci_td
|
struct ohci_td
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
u32 flags;
|
||||||
uint32_t cbp;
|
u32 cbp;
|
||||||
uint32_t next;
|
u32 next;
|
||||||
uint32_t be;
|
u32 be;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Isochronous transfer descriptor */
|
/* Isochronous transfer descriptor */
|
||||||
struct ohci_iso_td
|
struct ohci_iso_td
|
||||||
{
|
{
|
||||||
uint32_t flags;
|
u32 flags;
|
||||||
uint32_t bp;
|
u32 bp;
|
||||||
uint32_t next;
|
u32 next;
|
||||||
uint32_t be;
|
u32 be;
|
||||||
uint16_t offset[8];
|
u16 offset[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define USB_HZ 12000000
|
#define USB_HZ 12000000
|
||||||
|
@ -276,10 +277,10 @@ struct ohci_iso_td
|
||||||
#define OHCI_CC_BUFFEROVERRUN 0xc
|
#define OHCI_CC_BUFFEROVERRUN 0xc
|
||||||
#define OHCI_CC_BUFFERUNDERRUN 0xd
|
#define OHCI_CC_BUFFERUNDERRUN 0xd
|
||||||
|
|
||||||
OHCIState* ohci_create(uint32_t base, int ports);
|
OHCIState* ohci_create(u32 base, int ports);
|
||||||
|
|
||||||
uint32_t ohci_mem_read(OHCIState* ohci, uint32_t addr);
|
u32 ohci_mem_read(OHCIState* ohci, u32 addr);
|
||||||
void ohci_mem_write(OHCIState* ohci, uint32_t addr, uint32_t value);
|
void ohci_mem_write(OHCIState* ohci, u32 addr, u32 value);
|
||||||
void ohci_frame_boundary(void* opaque);
|
void ohci_frame_boundary(void* opaque);
|
||||||
|
|
||||||
void ohci_hard_reset(OHCIState* ohci);
|
void ohci_hard_reset(OHCIState* ohci);
|
||||||
|
|
|
@ -6,19 +6,6 @@
|
||||||
|
|
||||||
#define USB_DEVICE_GET_CLASS(p) (&p->klass)
|
#define USB_DEVICE_GET_CLASS(p) (&p->klass)
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Unused
|
|
||||||
static void usb_device_realize(USBDevice* dev /*, Error **errp*/)
|
|
||||||
{
|
|
||||||
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
|
|
||||||
|
|
||||||
if (klass->realize)
|
|
||||||
{
|
|
||||||
klass->realize(dev /*, errp*/);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
USBDevice* usb_device_find_device(USBDevice* dev, uint8_t addr)
|
USBDevice* usb_device_find_device(USBDevice* dev, uint8_t addr)
|
||||||
{
|
{
|
||||||
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
|
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
|
||||||
|
@ -26,22 +13,9 @@ USBDevice* usb_device_find_device(USBDevice* dev, uint8_t addr)
|
||||||
{
|
{
|
||||||
return klass->find_device(dev, addr);
|
return klass->find_device(dev, addr);
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Unused
|
|
||||||
static void usb_device_unrealize(USBDevice* dev /*, Error **errp*/)
|
|
||||||
{
|
|
||||||
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
|
|
||||||
|
|
||||||
if (klass->unrealize)
|
|
||||||
{
|
|
||||||
klass->unrealize(dev /*, errp*/);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void usb_device_cancel_packet(USBDevice* dev, USBPacket* p)
|
void usb_device_cancel_packet(USBDevice* dev, USBPacket* p)
|
||||||
{
|
{
|
||||||
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
|
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
|
||||||
|
@ -88,12 +62,6 @@ void usb_device_handle_data(USBDevice* dev, USBPacket* p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*const char *usb_device_get_product_desc(USBDevice *dev)
|
|
||||||
{
|
|
||||||
USBDeviceClass *klass = USB_DEVICE_GET_CLASS(dev);
|
|
||||||
return klass->product_desc;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
const USBDesc* usb_device_get_usb_desc(USBDevice* dev)
|
const USBDesc* usb_device_get_usb_desc(USBDevice* dev)
|
||||||
{
|
{
|
||||||
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
|
USBDeviceClass* klass = USB_DEVICE_GET_CLASS(dev);
|
||||||
|
|
|
@ -61,7 +61,7 @@ void usb_attach(USBPort* port)
|
||||||
{
|
{
|
||||||
USBDevice* dev = port->dev;
|
USBDevice* dev = port->dev;
|
||||||
|
|
||||||
assert(dev != NULL);
|
assert(dev != nullptr);
|
||||||
assert(dev->attached);
|
assert(dev->attached);
|
||||||
assert(dev->state == USB_STATE_NOTATTACHED);
|
assert(dev->state == USB_STATE_NOTATTACHED);
|
||||||
usb_pick_speed(port);
|
usb_pick_speed(port);
|
||||||
|
@ -74,7 +74,7 @@ void usb_detach(USBPort* port)
|
||||||
{
|
{
|
||||||
USBDevice* dev = port->dev;
|
USBDevice* dev = port->dev;
|
||||||
|
|
||||||
assert(dev != NULL);
|
assert(dev != nullptr);
|
||||||
assert(dev->state != USB_STATE_NOTATTACHED);
|
assert(dev->state != USB_STATE_NOTATTACHED);
|
||||||
port->ops->detach(port);
|
port->ops->detach(port);
|
||||||
dev->state = USB_STATE_NOTATTACHED;
|
dev->state = USB_STATE_NOTATTACHED;
|
||||||
|
@ -90,7 +90,7 @@ void usb_port_reset(USBPort* port)
|
||||||
{
|
{
|
||||||
USBDevice* dev = port->dev;
|
USBDevice* dev = port->dev;
|
||||||
|
|
||||||
assert(dev != NULL);
|
assert(dev != nullptr);
|
||||||
usb_detach(port);
|
usb_detach(port);
|
||||||
usb_attach(port);
|
usb_attach(port);
|
||||||
usb_device_reset(dev);
|
usb_device_reset(dev);
|
||||||
|
@ -98,7 +98,7 @@ void usb_port_reset(USBPort* port)
|
||||||
|
|
||||||
void usb_device_reset(USBDevice* dev)
|
void usb_device_reset(USBDevice* dev)
|
||||||
{
|
{
|
||||||
if (dev == NULL || !dev->attached)
|
if (dev == nullptr || !dev->attached)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -381,13 +381,13 @@ void usb_generic_async_ctrl_complete(USBDevice* s, USBPacket* p)
|
||||||
usb_packet_complete(s, p);
|
usb_packet_complete(s, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
USBDevice* usb_find_device(USBPort* port, uint8_t addr)
|
USBDevice* usb_find_device(USBPort* port, u8 addr)
|
||||||
{
|
{
|
||||||
USBDevice* dev = port->dev;
|
USBDevice* dev = port->dev;
|
||||||
|
|
||||||
if (dev == NULL || !dev->attached || dev->state != USB_STATE_DEFAULT)
|
if (dev == nullptr || !dev->attached || dev->state != USB_STATE_DEFAULT)
|
||||||
{
|
{
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (dev->addr == addr)
|
if (dev->addr == addr)
|
||||||
{
|
{
|
||||||
|
@ -449,7 +449,7 @@ static void usb_queue_one(USBPacket* p)
|
||||||
driver will call usb_packet_complete() when done processing it. */
|
driver will call usb_packet_complete() when done processing it. */
|
||||||
void usb_handle_packet(USBDevice* dev, USBPacket* p)
|
void usb_handle_packet(USBDevice* dev, USBPacket* p)
|
||||||
{
|
{
|
||||||
if (dev == NULL)
|
if (dev == nullptr)
|
||||||
{
|
{
|
||||||
p->status = USB_RET_NODEV;
|
p->status = USB_RET_NODEV;
|
||||||
return;
|
return;
|
||||||
|
@ -457,7 +457,7 @@ void usb_handle_packet(USBDevice* dev, USBPacket* p)
|
||||||
assert(dev == p->ep->dev);
|
assert(dev == p->ep->dev);
|
||||||
assert(dev->state == USB_STATE_DEFAULT);
|
assert(dev->state == USB_STATE_DEFAULT);
|
||||||
usb_packet_check_state(p, USB_PACKET_SETUP);
|
usb_packet_check_state(p, USB_PACKET_SETUP);
|
||||||
assert(p->ep != NULL);
|
assert(p->ep != nullptr);
|
||||||
|
|
||||||
/* Submitting a new packet clears halt */
|
/* Submitting a new packet clears halt */
|
||||||
if (p->ep->halted)
|
if (p->ep->halted)
|
||||||
|
@ -632,7 +632,7 @@ void usb_packet_setup(USBPacket* p, int pid,
|
||||||
p->parameter = 0;
|
p->parameter = 0;
|
||||||
p->short_not_ok = short_not_ok;
|
p->short_not_ok = short_not_ok;
|
||||||
p->int_req = int_req;
|
p->int_req = int_req;
|
||||||
p->buffer_ptr = NULL;
|
p->buffer_ptr = nullptr;
|
||||||
p->buffer_size = 0;
|
p->buffer_size = 0;
|
||||||
usb_packet_set_state(p, USB_PACKET_SETUP);
|
usb_packet_set_state(p, USB_PACKET_SETUP);
|
||||||
}
|
}
|
||||||
|
@ -640,7 +640,7 @@ void usb_packet_setup(USBPacket* p, int pid,
|
||||||
void usb_packet_addbuf(USBPacket* p, void* ptr, size_t len)
|
void usb_packet_addbuf(USBPacket* p, void* ptr, size_t len)
|
||||||
{
|
{
|
||||||
assert(!p->buffer_ptr);
|
assert(!p->buffer_ptr);
|
||||||
p->buffer_ptr = static_cast<uint8_t*>(ptr);
|
p->buffer_ptr = static_cast<u8*>(ptr);
|
||||||
p->buffer_size = static_cast<unsigned int>(len);
|
p->buffer_size = static_cast<unsigned int>(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,9 +785,9 @@ struct USBEndpoint* usb_ep_get(USBDevice* dev, int pid, int ep)
|
||||||
{
|
{
|
||||||
struct USBEndpoint* eps;
|
struct USBEndpoint* eps;
|
||||||
|
|
||||||
if (dev == NULL)
|
if (dev == nullptr)
|
||||||
{
|
{
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
|
eps = (pid == USB_TOKEN_IN) ? dev->ep_in : dev->ep_out;
|
||||||
if (ep == 0)
|
if (ep == 0)
|
||||||
|
@ -799,19 +799,19 @@ struct USBEndpoint* usb_ep_get(USBDevice* dev, int pid, int ep)
|
||||||
return eps + ep - 1;
|
return eps + ep - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t usb_ep_get_type(USBDevice* dev, int pid, int ep)
|
u8 usb_ep_get_type(USBDevice* dev, int pid, int ep)
|
||||||
{
|
{
|
||||||
struct USBEndpoint* uep = usb_ep_get(dev, pid, ep);
|
struct USBEndpoint* uep = usb_ep_get(dev, pid, ep);
|
||||||
return uep->type;
|
return uep->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_ep_set_type(USBDevice* dev, int pid, int ep, uint8_t type)
|
void usb_ep_set_type(USBDevice* dev, int pid, int ep, u8 type)
|
||||||
{
|
{
|
||||||
struct USBEndpoint* uep = usb_ep_get(dev, pid, ep);
|
struct USBEndpoint* uep = usb_ep_get(dev, pid, ep);
|
||||||
uep->type = type;
|
uep->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_ep_set_ifnum(USBDevice* dev, int pid, int ep, uint8_t ifnum)
|
void usb_ep_set_ifnum(USBDevice* dev, int pid, int ep, u8 ifnum)
|
||||||
{
|
{
|
||||||
struct USBEndpoint* uep = usb_ep_get(dev, pid, ep);
|
struct USBEndpoint* uep = usb_ep_get(dev, pid, ep);
|
||||||
uep->ifnum = ifnum;
|
uep->ifnum = ifnum;
|
||||||
|
@ -839,7 +839,7 @@ void usb_ep_set_max_packet_size(USBDevice* dev, int pid, int ep,
|
||||||
uep->max_packet_size = size * microframes;
|
uep->max_packet_size = size * microframes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_ep_set_max_streams(USBDevice* dev, int pid, int ep, uint8_t raw)
|
void usb_ep_set_max_streams(USBDevice* dev, int pid, int ep, u8 raw)
|
||||||
{
|
{
|
||||||
struct USBEndpoint* uep = usb_ep_get(dev, pid, ep);
|
struct USBEndpoint* uep = usb_ep_get(dev, pid, ep);
|
||||||
int MaxStreams;
|
int MaxStreams;
|
||||||
|
@ -875,7 +875,7 @@ USBPacket* usb_ep_find_packet_by_id(USBDevice* dev, int pid, int ep,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_wakeup(USBDevice* dev)
|
void usb_wakeup(USBDevice* dev)
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
int usb_desc_device(const USBDescID* id, const USBDescDevice* dev,
|
int usb_desc_device(const USBDescID* id, const USBDescDevice* dev,
|
||||||
bool msos, uint8_t* dest, size_t len)
|
bool msos, u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength = 0x12;
|
constexpr u8 bLength = 0x12;
|
||||||
USBDescriptor* d = (USBDescriptor*)dest;
|
USBDescriptor* d = (USBDescriptor*)dest;
|
||||||
|
|
||||||
if (len < bLength)
|
if (len < bLength)
|
||||||
|
@ -59,9 +59,9 @@ int usb_desc_device(const USBDescID* id, const USBDescDevice* dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_device_qualifier(const USBDescDevice* dev,
|
int usb_desc_device_qualifier(const USBDescDevice* dev,
|
||||||
uint8_t* dest, size_t len)
|
u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength = 0x0a;
|
constexpr u8 bLength = 0x0a;
|
||||||
USBDescriptor* d = (USBDescriptor*)dest;
|
USBDescriptor* d = (USBDescriptor*)dest;
|
||||||
|
|
||||||
if (len < bLength)
|
if (len < bLength)
|
||||||
|
@ -85,10 +85,10 @@ int usb_desc_device_qualifier(const USBDescDevice* dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_config(const USBDescConfig& conf, int flags,
|
int usb_desc_config(const USBDescConfig& conf, int flags,
|
||||||
uint8_t* dest, size_t len)
|
u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength = 0x09;
|
constexpr u8 bLength = 0x09;
|
||||||
uint16_t wTotalLength = 0;
|
u16 wTotalLength = 0;
|
||||||
USBDescriptor* d = (USBDescriptor*)dest;
|
USBDescriptor* d = (USBDescriptor*)dest;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -138,12 +138,12 @@ int usb_desc_config(const USBDescConfig& conf, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_iface_group(const USBDescIfaceAssoc& iad, int flags,
|
int usb_desc_iface_group(const USBDescIfaceAssoc& iad, int flags,
|
||||||
uint8_t* dest, size_t len)
|
u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
/* handle interface association descriptor */
|
/* handle interface association descriptor */
|
||||||
uint8_t bLength = 0x08;
|
constexpr u8 bLength = 0x08;
|
||||||
|
|
||||||
if (len < bLength)
|
if (len < bLength)
|
||||||
{
|
{
|
||||||
|
@ -175,9 +175,9 @@ int usb_desc_iface_group(const USBDescIfaceAssoc& iad, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_iface(const USBDescIface& iface, int flags,
|
int usb_desc_iface(const USBDescIface& iface, int flags,
|
||||||
uint8_t* dest, size_t len)
|
u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength = 0x09;
|
constexpr u8 bLength = 0x09;
|
||||||
int rc, pos = 0;
|
int rc, pos = 0;
|
||||||
USBDescriptor* d = (USBDescriptor*)dest;
|
USBDescriptor* d = (USBDescriptor*)dest;
|
||||||
|
|
||||||
|
@ -222,14 +222,14 @@ int usb_desc_iface(const USBDescIface& iface, int flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_endpoint(const USBDescEndpoint& ep, int flags,
|
int usb_desc_endpoint(const USBDescEndpoint& ep, int flags,
|
||||||
uint8_t* dest, size_t len)
|
u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength = ep.is_audio ? 0x09 : 0x07;
|
u8 bLength = ep.is_audio ? 0x09 : 0x07;
|
||||||
uint8_t extralen = ep.extra ? ep.extra[0] : 0;
|
const u8 extralen = ep.extra ? ep.extra[0] : 0;
|
||||||
uint8_t superlen = (flags & USB_DESC_FLAG_SUPER) ? 0x06 : 0;
|
u8 superlen = (flags & USB_DESC_FLAG_SUPER) ? 0x06 : 0;
|
||||||
USBDescriptor* d = (USBDescriptor*)dest;
|
USBDescriptor* d = (USBDescriptor*)dest;
|
||||||
|
|
||||||
if (len < (size_t)(bLength + extralen + superlen))
|
if (len < static_cast<size_t>(bLength + extralen + superlen))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -271,11 +271,11 @@ int usb_desc_endpoint(const USBDescEndpoint& ep, int flags,
|
||||||
return bLength + extralen + superlen;
|
return bLength + extralen + superlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_other(const USBDescOther& desc, uint8_t* dest, size_t len)
|
int usb_desc_other(const USBDescOther& desc, u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
int bLength = desc.length ? desc.length : desc.data[0];
|
const int bLength = desc.length ? desc.length : desc.data[0];
|
||||||
|
|
||||||
if (len < (size_t)bLength)
|
if (len < static_cast<size_t>(bLength))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -284,9 +284,9 @@ int usb_desc_other(const USBDescOther& desc, uint8_t* dest, size_t len)
|
||||||
return bLength;
|
return bLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_desc_cap_usb2_ext(const USBDesc* desc, uint8_t* dest, size_t len)
|
static int usb_desc_cap_usb2_ext(const USBDesc* desc, u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength = 0x07;
|
constexpr u8 bLength = 0x07;
|
||||||
USBDescriptor* d = (USBDescriptor*)dest;
|
USBDescriptor* d = (USBDescriptor*)dest;
|
||||||
|
|
||||||
if (len < bLength)
|
if (len < bLength)
|
||||||
|
@ -306,9 +306,9 @@ static int usb_desc_cap_usb2_ext(const USBDesc* desc, uint8_t* dest, size_t len)
|
||||||
return bLength;
|
return bLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_desc_cap_super(const USBDesc* desc, uint8_t* dest, size_t len)
|
static int usb_desc_cap_super(const USBDesc* desc, u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength = 0x0a;
|
constexpr u8 bLength = 0x0a;
|
||||||
USBDescriptor* d = (USBDescriptor*)dest;
|
USBDescriptor* d = (USBDescriptor*)dest;
|
||||||
|
|
||||||
if (len < bLength)
|
if (len < bLength)
|
||||||
|
@ -353,11 +353,11 @@ static int usb_desc_cap_super(const USBDesc* desc, uint8_t* dest, size_t len)
|
||||||
return bLength;
|
return bLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_desc_bos(const USBDesc* desc, uint8_t* dest, size_t len)
|
static int usb_desc_bos(const USBDesc* desc, u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength = 0x05;
|
constexpr u8 bLength = 0x05;
|
||||||
uint16_t wTotalLength = 0;
|
u16 wTotalLength = 0;
|
||||||
uint8_t bNumDeviceCaps = 0;
|
u8 bNumDeviceCaps = 0;
|
||||||
USBDescriptor* d = (USBDescriptor*)dest;
|
USBDescriptor* d = (USBDescriptor*)dest;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -371,7 +371,7 @@ static int usb_desc_bos(const USBDesc* desc, uint8_t* dest, size_t len)
|
||||||
|
|
||||||
wTotalLength += bLength;
|
wTotalLength += bLength;
|
||||||
|
|
||||||
if (desc->high != NULL)
|
if (desc->high != nullptr)
|
||||||
{
|
{
|
||||||
rc = usb_desc_cap_usb2_ext(desc, dest + wTotalLength,
|
rc = usb_desc_cap_usb2_ext(desc, dest + wTotalLength,
|
||||||
len - wTotalLength);
|
len - wTotalLength);
|
||||||
|
@ -383,7 +383,7 @@ static int usb_desc_bos(const USBDesc* desc, uint8_t* dest, size_t len)
|
||||||
bNumDeviceCaps++;
|
bNumDeviceCaps++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (desc->super != NULL)
|
if (desc->super != nullptr)
|
||||||
{
|
{
|
||||||
rc = usb_desc_cap_super(desc, dest + wTotalLength,
|
rc = usb_desc_cap_super(desc, dest + wTotalLength,
|
||||||
len - wTotalLength);
|
len - wTotalLength);
|
||||||
|
@ -401,7 +401,7 @@ static int usb_desc_bos(const USBDesc* desc, uint8_t* dest, size_t len)
|
||||||
return wTotalLength;
|
return wTotalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_parse_dev(const uint8_t* data, int len, USBDesc& desc, USBDescDevice& dev)
|
int usb_desc_parse_dev(const u8* data, int len, USBDesc& desc, USBDescDevice& dev)
|
||||||
{
|
{
|
||||||
USBDescriptor* d = (USBDescriptor*)data;
|
USBDescriptor* d = (USBDescriptor*)data;
|
||||||
if (d->bLength != len || d->bDescriptorType != USB_DT_DEVICE)
|
if (d->bLength != len || d->bDescriptorType != USB_DT_DEVICE)
|
||||||
|
@ -422,7 +422,7 @@ int usb_desc_parse_dev(const uint8_t* data, int len, USBDesc& desc, USBDescDevic
|
||||||
return d->bLength;
|
return d->bLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_parse_config(const uint8_t* data, int len, USBDescDevice& dev)
|
int usb_desc_parse_config(const u8* data, int len, USBDescDevice& dev)
|
||||||
{
|
{
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
USBDescIface* iface = nullptr;
|
USBDescIface* iface = nullptr;
|
||||||
|
@ -511,27 +511,6 @@ int usb_desc_parse_config(const uint8_t* data, int len, USBDescDevice& dev)
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// simple `dev = {};` seems to be enough
|
|
||||||
/*void usb_desc_clear_device (USBDescDevice& dev)
|
|
||||||
{
|
|
||||||
for (auto& conf : dev.confs)
|
|
||||||
{
|
|
||||||
for (auto& ifassoc : conf.if_groups)
|
|
||||||
{
|
|
||||||
ifassoc.ifs.clear();
|
|
||||||
ifassoc = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& iface : conf.ifs)
|
|
||||||
{
|
|
||||||
iface.descs.clear();
|
|
||||||
iface.eps.clear();
|
|
||||||
iface = {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dev = {};
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
static void usb_desc_ep_init(USBDevice* dev)
|
static void usb_desc_ep_init(USBDevice* dev)
|
||||||
|
@ -543,7 +522,7 @@ static void usb_desc_ep_init(USBDevice* dev)
|
||||||
for (i = 0; i < dev->ninterfaces; i++)
|
for (i = 0; i < dev->ninterfaces; i++)
|
||||||
{
|
{
|
||||||
iface = dev->ifaces[i];
|
iface = dev->ifaces[i];
|
||||||
if (iface == NULL)
|
if (iface == nullptr)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -568,7 +547,7 @@ static const USBDescIface* usb_desc_find_interface(USBDevice* dev,
|
||||||
{
|
{
|
||||||
if (!dev->config)
|
if (!dev->config)
|
||||||
{
|
{
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
for (auto& g : dev->config->if_groups)
|
for (auto& g : dev->config->if_groups)
|
||||||
{
|
{
|
||||||
|
@ -589,7 +568,7 @@ static const USBDescIface* usb_desc_find_interface(USBDevice* dev,
|
||||||
return &iface;
|
return &iface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
|
@ -599,7 +578,7 @@ int usb_desc_set_interface(USBDevice* dev, int index, int value)
|
||||||
int old;
|
int old;
|
||||||
|
|
||||||
iface = usb_desc_find_interface(dev, index, value);
|
iface = usb_desc_find_interface(dev, index, value);
|
||||||
if (iface == NULL)
|
if (iface == nullptr)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -625,7 +604,7 @@ int usb_desc_set_config(USBDevice* dev, int value)
|
||||||
{
|
{
|
||||||
dev->configuration = 0;
|
dev->configuration = 0;
|
||||||
dev->ninterfaces = 0;
|
dev->ninterfaces = 0;
|
||||||
dev->config = NULL;
|
dev->config = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -651,7 +630,7 @@ int usb_desc_set_config(USBDevice* dev, int value)
|
||||||
for (; i < USB_MAX_INTERFACES; i++)
|
for (; i < USB_MAX_INTERFACES; i++)
|
||||||
{
|
{
|
||||||
dev->altsetting[i] = 0;
|
dev->altsetting[i] = 0;
|
||||||
dev->ifaces[i] = NULL;
|
dev->ifaces[i] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -661,7 +640,7 @@ static void usb_desc_setdefaults(USBDevice* dev)
|
||||||
{
|
{
|
||||||
const USBDesc* desc = usb_device_get_usb_desc(dev);
|
const USBDesc* desc = usb_device_get_usb_desc(dev);
|
||||||
|
|
||||||
assert(desc != NULL);
|
assert(desc != nullptr);
|
||||||
switch (dev->speed)
|
switch (dev->speed)
|
||||||
{
|
{
|
||||||
case USB_SPEED_LOW:
|
case USB_SPEED_LOW:
|
||||||
|
@ -684,7 +663,7 @@ void usb_desc_init(USBDevice* dev)
|
||||||
{
|
{
|
||||||
const USBDesc* desc = usb_device_get_usb_desc(dev);
|
const USBDesc* desc = usb_device_get_usb_desc(dev);
|
||||||
|
|
||||||
assert(desc != NULL);
|
assert(desc != nullptr);
|
||||||
dev->speed = USB_SPEED_FULL;
|
dev->speed = USB_SPEED_FULL;
|
||||||
dev->speedmask = 0;
|
dev->speedmask = 0;
|
||||||
if (desc->full)
|
if (desc->full)
|
||||||
|
@ -699,9 +678,9 @@ void usb_desc_attach(USBDevice* dev)
|
||||||
usb_desc_setdefaults(dev);
|
usb_desc_setdefaults(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_string(USBDevice* dev, int index, uint8_t* dest, size_t len)
|
int usb_desc_string(USBDevice* dev, int index, u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t bLength, pos, i;
|
u8 bLength, pos, i;
|
||||||
const char* str;
|
const char* str;
|
||||||
|
|
||||||
if (len < 4)
|
if (len < 4)
|
||||||
|
@ -720,7 +699,7 @@ int usb_desc_string(USBDevice* dev, int index, uint8_t* dest, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
str = usb_device_get_usb_desc(dev)->str[index];
|
str = usb_device_get_usb_desc(dev)->str[index];
|
||||||
if (str == NULL)
|
if (str == nullptr)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -739,14 +718,14 @@ int usb_desc_string(USBDevice* dev, int index, uint8_t* dest, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_get_descriptor(USBDevice* dev, USBPacket* p,
|
int usb_desc_get_descriptor(USBDevice* dev, USBPacket* p,
|
||||||
int value, uint8_t* dest, size_t len)
|
int value, u8* dest, size_t len)
|
||||||
{
|
{
|
||||||
bool msos = (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE));
|
const bool msos = (dev->flags & (1 << USB_DEV_FLAG_MSOS_DESC_IN_USE));
|
||||||
const USBDesc* desc = usb_device_get_usb_desc(dev);
|
const USBDesc* desc = usb_device_get_usb_desc(dev);
|
||||||
const USBDescDevice* other_dev;
|
const USBDescDevice* other_dev;
|
||||||
uint8_t buf[1024];
|
u8 buf[1024];
|
||||||
uint8_t type = value >> 8;
|
const u8 type = value >> 8;
|
||||||
uint8_t index = value & 0xff;
|
const u8 index = value & 0xff;
|
||||||
int flags, ret = -1;
|
int flags, ret = -1;
|
||||||
|
|
||||||
if (dev->speed == USB_SPEED_HIGH)
|
if (dev->speed == USB_SPEED_HIGH)
|
||||||
|
@ -784,14 +763,14 @@ int usb_desc_get_descriptor(USBDevice* dev, USBPacket* p,
|
||||||
//trace_usb_desc_string(dev->addr, index, len, ret);
|
//trace_usb_desc_string(dev->addr, index, len, ret);
|
||||||
break;
|
break;
|
||||||
case USB_DT_DEVICE_QUALIFIER:
|
case USB_DT_DEVICE_QUALIFIER:
|
||||||
if (other_dev != NULL)
|
if (other_dev != nullptr)
|
||||||
{
|
{
|
||||||
ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
|
ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
|
||||||
}
|
}
|
||||||
//trace_usb_desc_device_qualifier(dev->addr, len, ret);
|
//trace_usb_desc_device_qualifier(dev->addr, len, ret);
|
||||||
break;
|
break;
|
||||||
case USB_DT_OTHER_SPEED_CONFIG:
|
case USB_DT_OTHER_SPEED_CONFIG:
|
||||||
if (other_dev != NULL && index < other_dev->bNumConfigurations)
|
if (other_dev != nullptr && index < other_dev->bNumConfigurations)
|
||||||
{
|
{
|
||||||
ret = usb_desc_config(other_dev->confs[index], flags,
|
ret = usb_desc_config(other_dev->confs[index], flags,
|
||||||
buf, sizeof(buf));
|
buf, sizeof(buf));
|
||||||
|
@ -814,7 +793,7 @@ int usb_desc_get_descriptor(USBDevice* dev, USBPacket* p,
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
if ((size_t)ret > len)
|
if (static_cast<size_t>(ret) > len)
|
||||||
{
|
{
|
||||||
ret = len;
|
ret = len;
|
||||||
}
|
}
|
||||||
|
@ -826,9 +805,9 @@ int usb_desc_get_descriptor(USBDevice* dev, USBPacket* p,
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_desc_handle_control(USBDevice* dev, USBPacket* p,
|
int usb_desc_handle_control(USBDevice* dev, USBPacket* p,
|
||||||
int request, int value, int index, int length, uint8_t* data)
|
int request, int value, int index, int length, u8* data)
|
||||||
{
|
{
|
||||||
assert(usb_device_get_usb_desc(dev) != NULL);
|
assert(usb_device_get_usb_desc(dev) != nullptr);
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
switch (request)
|
switch (request)
|
||||||
|
|
|
@ -3,207 +3,210 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/Pcsx2Types.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/* binary representation */
|
/* binary representation */
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
typedef struct USBDescriptor {
|
typedef struct USBDescriptor
|
||||||
uint8_t bLength;
|
{
|
||||||
uint8_t bDescriptorType;
|
u8 bLength;
|
||||||
union
|
u8 bDescriptorType;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
{
|
{
|
||||||
struct
|
u8 bcdUSB_lo;
|
||||||
|
u8 bcdUSB_hi;
|
||||||
|
u8 bDeviceClass;
|
||||||
|
u8 bDeviceSubClass;
|
||||||
|
u8 bDeviceProtocol;
|
||||||
|
u8 bMaxPacketSize0;
|
||||||
|
u8 idVendor_lo;
|
||||||
|
u8 idVendor_hi;
|
||||||
|
u8 idProduct_lo;
|
||||||
|
u8 idProduct_hi;
|
||||||
|
u8 bcdDevice_lo;
|
||||||
|
u8 bcdDevice_hi;
|
||||||
|
u8 iManufacturer;
|
||||||
|
u8 iProduct;
|
||||||
|
u8 iSerialNumber;
|
||||||
|
u8 bNumConfigurations;
|
||||||
|
} device;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u8 bcdUSB_lo;
|
||||||
|
u8 bcdUSB_hi;
|
||||||
|
u8 bDeviceClass;
|
||||||
|
u8 bDeviceSubClass;
|
||||||
|
u8 bDeviceProtocol;
|
||||||
|
u8 bMaxPacketSize0;
|
||||||
|
u8 bNumConfigurations;
|
||||||
|
u8 bReserved;
|
||||||
|
} device_qualifier;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u8 wTotalLength_lo;
|
||||||
|
u8 wTotalLength_hi;
|
||||||
|
u8 bNumInterfaces;
|
||||||
|
u8 bConfigurationValue;
|
||||||
|
u8 iConfiguration;
|
||||||
|
u8 bmAttributes;
|
||||||
|
u8 bMaxPower;
|
||||||
|
} config;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u8 bInterfaceNumber;
|
||||||
|
u8 bAlternateSetting;
|
||||||
|
u8 bNumEndpoints;
|
||||||
|
u8 bInterfaceClass;
|
||||||
|
u8 bInterfaceSubClass;
|
||||||
|
u8 bInterfaceProtocol;
|
||||||
|
u8 iInterface;
|
||||||
|
} intf;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u8 bEndpointAddress;
|
||||||
|
u8 bmAttributes;
|
||||||
|
u8 wMaxPacketSize_lo;
|
||||||
|
u8 wMaxPacketSize_hi;
|
||||||
|
u8 bInterval;
|
||||||
|
u8 bRefresh; /* only audio ep */
|
||||||
|
u8 bSynchAddress; /* only audio ep */
|
||||||
|
} endpoint;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u8 bMaxBurst;
|
||||||
|
u8 bmAttributes;
|
||||||
|
u8 wBytesPerInterval_lo;
|
||||||
|
u8 wBytesPerInterval_hi;
|
||||||
|
} super_endpoint;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u8 wTotalLength_lo;
|
||||||
|
u8 wTotalLength_hi;
|
||||||
|
u8 bNumDeviceCaps;
|
||||||
|
} bos;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u8 bDevCapabilityType;
|
||||||
|
union
|
||||||
{
|
{
|
||||||
uint8_t bcdUSB_lo;
|
struct
|
||||||
uint8_t bcdUSB_hi;
|
|
||||||
uint8_t bDeviceClass;
|
|
||||||
uint8_t bDeviceSubClass;
|
|
||||||
uint8_t bDeviceProtocol;
|
|
||||||
uint8_t bMaxPacketSize0;
|
|
||||||
uint8_t idVendor_lo;
|
|
||||||
uint8_t idVendor_hi;
|
|
||||||
uint8_t idProduct_lo;
|
|
||||||
uint8_t idProduct_hi;
|
|
||||||
uint8_t bcdDevice_lo;
|
|
||||||
uint8_t bcdDevice_hi;
|
|
||||||
uint8_t iManufacturer;
|
|
||||||
uint8_t iProduct;
|
|
||||||
uint8_t iSerialNumber;
|
|
||||||
uint8_t bNumConfigurations;
|
|
||||||
} device;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t bcdUSB_lo;
|
|
||||||
uint8_t bcdUSB_hi;
|
|
||||||
uint8_t bDeviceClass;
|
|
||||||
uint8_t bDeviceSubClass;
|
|
||||||
uint8_t bDeviceProtocol;
|
|
||||||
uint8_t bMaxPacketSize0;
|
|
||||||
uint8_t bNumConfigurations;
|
|
||||||
uint8_t bReserved;
|
|
||||||
} device_qualifier;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t wTotalLength_lo;
|
|
||||||
uint8_t wTotalLength_hi;
|
|
||||||
uint8_t bNumInterfaces;
|
|
||||||
uint8_t bConfigurationValue;
|
|
||||||
uint8_t iConfiguration;
|
|
||||||
uint8_t bmAttributes;
|
|
||||||
uint8_t bMaxPower;
|
|
||||||
} config;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t bInterfaceNumber;
|
|
||||||
uint8_t bAlternateSetting;
|
|
||||||
uint8_t bNumEndpoints;
|
|
||||||
uint8_t bInterfaceClass;
|
|
||||||
uint8_t bInterfaceSubClass;
|
|
||||||
uint8_t bInterfaceProtocol;
|
|
||||||
uint8_t iInterface;
|
|
||||||
} intf;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t bEndpointAddress;
|
|
||||||
uint8_t bmAttributes;
|
|
||||||
uint8_t wMaxPacketSize_lo;
|
|
||||||
uint8_t wMaxPacketSize_hi;
|
|
||||||
uint8_t bInterval;
|
|
||||||
uint8_t bRefresh; /* only audio ep */
|
|
||||||
uint8_t bSynchAddress; /* only audio ep */
|
|
||||||
} endpoint;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t bMaxBurst;
|
|
||||||
uint8_t bmAttributes;
|
|
||||||
uint8_t wBytesPerInterval_lo;
|
|
||||||
uint8_t wBytesPerInterval_hi;
|
|
||||||
} super_endpoint;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t wTotalLength_lo;
|
|
||||||
uint8_t wTotalLength_hi;
|
|
||||||
uint8_t bNumDeviceCaps;
|
|
||||||
} bos;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t bDevCapabilityType;
|
|
||||||
union
|
|
||||||
{
|
{
|
||||||
struct
|
u8 bmAttributes_1;
|
||||||
{
|
u8 bmAttributes_2;
|
||||||
uint8_t bmAttributes_1;
|
u8 bmAttributes_3;
|
||||||
uint8_t bmAttributes_2;
|
u8 bmAttributes_4;
|
||||||
uint8_t bmAttributes_3;
|
} usb2_ext;
|
||||||
uint8_t bmAttributes_4;
|
struct
|
||||||
} usb2_ext;
|
{
|
||||||
struct
|
u8 bmAttributes;
|
||||||
{
|
u8 wSpeedsSupported_lo;
|
||||||
uint8_t bmAttributes;
|
u8 wSpeedsSupported_hi;
|
||||||
uint8_t wSpeedsSupported_lo;
|
u8 bFunctionalitySupport;
|
||||||
uint8_t wSpeedsSupported_hi;
|
u8 bU1DevExitLat;
|
||||||
uint8_t bFunctionalitySupport;
|
u8 wU2DevExitLat_lo;
|
||||||
uint8_t bU1DevExitLat;
|
u8 wU2DevExitLat_hi;
|
||||||
uint8_t wU2DevExitLat_lo;
|
} super;
|
||||||
uint8_t wU2DevExitLat_hi;
|
} u;
|
||||||
} super;
|
} cap;
|
||||||
} u;
|
} u;
|
||||||
} cap;
|
} USBDescriptor;
|
||||||
} u;
|
|
||||||
} USBDescriptor;
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct USBDescID
|
struct USBDescID
|
||||||
{
|
{
|
||||||
uint16_t idVendor;
|
u16 idVendor;
|
||||||
uint16_t idProduct;
|
u16 idProduct;
|
||||||
uint16_t bcdDevice;
|
u16 bcdDevice;
|
||||||
uint8_t iManufacturer;
|
u8 iManufacturer;
|
||||||
uint8_t iProduct;
|
u8 iProduct;
|
||||||
uint8_t iSerialNumber;
|
u8 iSerialNumber;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct USBDescDevice
|
struct USBDescDevice
|
||||||
{
|
{
|
||||||
uint16_t bcdUSB;
|
u16 bcdUSB;
|
||||||
uint8_t bDeviceClass;
|
u8 bDeviceClass;
|
||||||
uint8_t bDeviceSubClass;
|
u8 bDeviceSubClass;
|
||||||
uint8_t bDeviceProtocol;
|
u8 bDeviceProtocol;
|
||||||
uint8_t bMaxPacketSize0;
|
u8 bMaxPacketSize0;
|
||||||
uint8_t bNumConfigurations;
|
u8 bNumConfigurations;
|
||||||
|
|
||||||
std::vector<USBDescConfig> confs;
|
std::vector<USBDescConfig> confs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct USBDescConfig
|
struct USBDescConfig
|
||||||
{
|
{
|
||||||
uint8_t bNumInterfaces;
|
u8 bNumInterfaces;
|
||||||
uint8_t bConfigurationValue;
|
u8 bConfigurationValue;
|
||||||
uint8_t iConfiguration;
|
u8 iConfiguration;
|
||||||
uint8_t bmAttributes;
|
u8 bmAttributes;
|
||||||
uint8_t bMaxPower;
|
u8 bMaxPower;
|
||||||
|
|
||||||
/* grouped interfaces */
|
/* grouped interfaces */
|
||||||
//uint8_t nif_groups;
|
//u8 nif_groups;
|
||||||
std::vector<USBDescIfaceAssoc> if_groups;
|
std::vector<USBDescIfaceAssoc> if_groups;
|
||||||
|
|
||||||
/* "normal" interfaces */
|
/* "normal" interfaces */
|
||||||
//uint8_t nif;
|
//u8 nif;
|
||||||
std::vector<USBDescIface> ifs;
|
std::vector<USBDescIface> ifs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* conceptually an Interface Association Descriptor, and releated interfaces */
|
/* conceptually an Interface Association Descriptor, and releated interfaces */
|
||||||
struct USBDescIfaceAssoc
|
struct USBDescIfaceAssoc
|
||||||
{
|
{
|
||||||
uint8_t bFirstInterface;
|
u8 bFirstInterface;
|
||||||
uint8_t bInterfaceCount;
|
u8 bInterfaceCount;
|
||||||
uint8_t bFunctionClass;
|
u8 bFunctionClass;
|
||||||
uint8_t bFunctionSubClass;
|
u8 bFunctionSubClass;
|
||||||
uint8_t bFunctionProtocol;
|
u8 bFunctionProtocol;
|
||||||
uint8_t iFunction;
|
u8 iFunction;
|
||||||
|
|
||||||
//uint8_t nif;
|
//u8 nif;
|
||||||
std::vector<USBDescIface> ifs;
|
std::vector<USBDescIface> ifs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct USBDescIface
|
struct USBDescIface
|
||||||
{
|
{
|
||||||
uint8_t bInterfaceNumber;
|
u8 bInterfaceNumber;
|
||||||
uint8_t bAlternateSetting;
|
u8 bAlternateSetting;
|
||||||
uint8_t bNumEndpoints;
|
u8 bNumEndpoints;
|
||||||
uint8_t bInterfaceClass;
|
u8 bInterfaceClass;
|
||||||
uint8_t bInterfaceSubClass;
|
u8 bInterfaceSubClass;
|
||||||
uint8_t bInterfaceProtocol;
|
u8 bInterfaceProtocol;
|
||||||
uint8_t iInterface;
|
u8 iInterface;
|
||||||
|
|
||||||
//uint8_t ndesc;
|
//u8 ndesc;
|
||||||
std::vector<USBDescOther> descs;
|
std::vector<USBDescOther> descs;
|
||||||
std::vector<USBDescEndpoint> eps;
|
std::vector<USBDescEndpoint> eps;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct USBDescEndpoint
|
struct USBDescEndpoint
|
||||||
{
|
{
|
||||||
uint8_t bEndpointAddress;
|
u8 bEndpointAddress;
|
||||||
uint8_t bmAttributes;
|
u8 bmAttributes;
|
||||||
uint16_t wMaxPacketSize;
|
u16 wMaxPacketSize;
|
||||||
uint8_t bInterval;
|
u8 bInterval;
|
||||||
uint8_t bRefresh;
|
u8 bRefresh;
|
||||||
uint8_t bSynchAddress;
|
u8 bSynchAddress;
|
||||||
|
|
||||||
uint8_t is_audio; /* has bRefresh + bSynchAddress */
|
u8 is_audio; /* has bRefresh + bSynchAddress */
|
||||||
const uint8_t* extra;
|
const u8* extra;
|
||||||
|
|
||||||
/* superspeed endpoint companion */
|
/* superspeed endpoint companion */
|
||||||
uint8_t bMaxBurst;
|
u8 bMaxBurst;
|
||||||
uint8_t bmAttributes_super;
|
u8 bmAttributes_super;
|
||||||
uint16_t wBytesPerInterval;
|
u16 wBytesPerInterval;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct USBDescOther
|
struct USBDescOther
|
||||||
{
|
{
|
||||||
uint8_t length;
|
u8 length;
|
||||||
const uint8_t* data;
|
const u8* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct USBDescMSOS
|
struct USBDescMSOS
|
||||||
|
@ -228,43 +231,43 @@ struct USBDesc
|
||||||
#define USB_DESC_FLAG_SUPER (1 << 1)
|
#define USB_DESC_FLAG_SUPER (1 << 1)
|
||||||
|
|
||||||
/* little helpers */
|
/* little helpers */
|
||||||
static inline uint8_t usb_lo(uint16_t val)
|
static inline u8 usb_lo(u16 val)
|
||||||
{
|
{
|
||||||
return val & 0xff;
|
return val & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t usb_hi(uint16_t val)
|
static inline u8 usb_hi(u16 val)
|
||||||
{
|
{
|
||||||
return (val >> 8) & 0xff;
|
return (val >> 8) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate usb packages from structs */
|
/* generate usb packages from structs */
|
||||||
int usb_desc_device(const USBDescID* id, const USBDescDevice* dev,
|
int usb_desc_device(const USBDescID* id, const USBDescDevice* dev,
|
||||||
bool msos, uint8_t* dest, size_t len);
|
bool msos, u8* dest, size_t len);
|
||||||
int usb_desc_device_qualifier(const USBDescDevice* dev,
|
int usb_desc_device_qualifier(const USBDescDevice* dev,
|
||||||
uint8_t* dest, size_t len);
|
u8* dest, size_t len);
|
||||||
int usb_desc_config(const USBDescConfig& conf, int flags,
|
int usb_desc_config(const USBDescConfig& conf, int flags,
|
||||||
uint8_t* dest, size_t len);
|
u8* dest, size_t len);
|
||||||
int usb_desc_iface_group(const USBDescIfaceAssoc& iad, int flags,
|
int usb_desc_iface_group(const USBDescIfaceAssoc& iad, int flags,
|
||||||
uint8_t* dest, size_t len);
|
u8* dest, size_t len);
|
||||||
int usb_desc_iface(const USBDescIface& iface, int flags,
|
int usb_desc_iface(const USBDescIface& iface, int flags,
|
||||||
uint8_t* dest, size_t len);
|
u8* dest, size_t len);
|
||||||
int usb_desc_endpoint(const USBDescEndpoint& ep, int flags,
|
int usb_desc_endpoint(const USBDescEndpoint& ep, int flags,
|
||||||
uint8_t* dest, size_t len);
|
u8* dest, size_t len);
|
||||||
int usb_desc_other(const USBDescOther& desc, uint8_t* dest, size_t len);
|
int usb_desc_other(const USBDescOther& desc, u8* dest, size_t len);
|
||||||
//int usb_desc_msos(const USBDesc *desc, USBPacket *p,
|
//int usb_desc_msos(const USBDesc *desc, USBPacket *p,
|
||||||
// int index, uint8_t *dest, size_t len);
|
// int index, u8 *dest, size_t len);
|
||||||
int usb_desc_parse_dev(const uint8_t* data, int len, USBDesc& desc, USBDescDevice& dev);
|
int usb_desc_parse_dev(const u8* data, int len, USBDesc& desc, USBDescDevice& dev);
|
||||||
int usb_desc_parse_config(const uint8_t* data, int len, USBDescDevice& dev);
|
int usb_desc_parse_config(const u8* data, int len, USBDescDevice& dev);
|
||||||
|
|
||||||
/* control message emulation helpers */
|
/* control message emulation helpers */
|
||||||
void usb_desc_init(USBDevice* dev);
|
void usb_desc_init(USBDevice* dev);
|
||||||
void usb_desc_attach(USBDevice* dev);
|
void usb_desc_attach(USBDevice* dev);
|
||||||
int usb_desc_string(USBDevice* dev, int index, uint8_t* dest, size_t len);
|
int usb_desc_string(USBDevice* dev, int index, u8* dest, size_t len);
|
||||||
int usb_desc_get_descriptor(USBDevice* dev, USBPacket* p,
|
int usb_desc_get_descriptor(USBDevice* dev, USBPacket* p,
|
||||||
int value, uint8_t* dest, size_t len);
|
int value, u8* dest, size_t len);
|
||||||
int usb_desc_handle_control(USBDevice* dev, USBPacket* p,
|
int usb_desc_handle_control(USBDevice* dev, USBPacket* p,
|
||||||
int request, int value, int index, int length, uint8_t* data);
|
int request, int value, int index, int length, u8* data);
|
||||||
|
|
||||||
int usb_desc_set_config(USBDevice* dev, int value);
|
int usb_desc_set_config(USBDevice* dev, int value);
|
||||||
int usb_desc_set_interface(USBDevice* dev, int index, int value);
|
int usb_desc_set_interface(USBDevice* dev, int index, int value);
|
||||||
|
|
|
@ -188,7 +188,7 @@ int qemu_input_key_value_to_scancode(const KeyValue* value, bool down,
|
||||||
value->u.qcode == Q_KEY_CODE_PAUSE)
|
value->u.qcode == Q_KEY_CODE_PAUSE)
|
||||||
{
|
{
|
||||||
/* specific case */
|
/* specific case */
|
||||||
int v = down ? 0 : 0x80;
|
const int v = down ? 0 : 0x80;
|
||||||
codes[count++] = 0xe1;
|
codes[count++] = 0xe1;
|
||||||
codes[count++] = 0x1d | v;
|
codes[count++] = 0x1d | v;
|
||||||
codes[count++] = 0x45 | v;
|
codes[count++] = 0x45 | v;
|
||||||
|
|
|
@ -482,8 +482,6 @@ void usb_packet_setup(USBPacket* p, int pid,
|
||||||
USBEndpoint* ep, unsigned int stream,
|
USBEndpoint* ep, unsigned int stream,
|
||||||
uint64_t id, bool short_not_ok, bool int_req);
|
uint64_t id, bool short_not_ok, bool int_req);
|
||||||
void usb_packet_addbuf(USBPacket* p, void* ptr, size_t len);
|
void usb_packet_addbuf(USBPacket* p, void* ptr, size_t len);
|
||||||
//int usb_packet_map(USBPacket *p, QEMUSGList *sgl);
|
|
||||||
//void usb_packet_unmap(USBPacket *p, QEMUSGList *sgl);
|
|
||||||
void usb_packet_copy(USBPacket* p, void* ptr, size_t bytes);
|
void usb_packet_copy(USBPacket* p, void* ptr, size_t bytes);
|
||||||
void usb_packet_skip(USBPacket* p, size_t bytes);
|
void usb_packet_skip(USBPacket* p, size_t bytes);
|
||||||
size_t usb_packet_size(USBPacket* p);
|
size_t usb_packet_size(USBPacket* p);
|
||||||
|
@ -540,10 +538,6 @@ void usb_ep_set_halted(USBDevice* dev, int pid, int ep, bool halted);
|
||||||
USBPacket* usb_ep_find_packet_by_id(USBDevice* dev, int pid, int ep,
|
USBPacket* usb_ep_find_packet_by_id(USBDevice* dev, int pid, int ep,
|
||||||
uint64_t id);
|
uint64_t id);
|
||||||
|
|
||||||
void usb_ep_combine_input_packets(USBEndpoint* ep);
|
|
||||||
void usb_combined_input_packet_complete(USBDevice* dev, USBPacket* p);
|
|
||||||
void usb_combined_packet_cancel(USBDevice* dev, USBPacket* p);
|
|
||||||
|
|
||||||
void usb_pick_speed(USBPort* port);
|
void usb_pick_speed(USBPort* port);
|
||||||
void usb_attach(USBPort* port);
|
void usb_attach(USBPort* port);
|
||||||
void usb_detach(USBPort* port);
|
void usb_detach(USBPort* port);
|
||||||
|
@ -552,17 +546,9 @@ void usb_device_reset(USBDevice* dev);
|
||||||
void usb_wakeup(USBEndpoint* ep, unsigned int stream);
|
void usb_wakeup(USBEndpoint* ep, unsigned int stream);
|
||||||
void usb_generic_async_ctrl_complete(USBDevice* s, USBPacket* p);
|
void usb_generic_async_ctrl_complete(USBDevice* s, USBPacket* p);
|
||||||
|
|
||||||
|
|
||||||
int usb_generic_handle_packet(USBDevice* s, int pid,
|
|
||||||
uint8_t devaddr, uint8_t devep,
|
|
||||||
uint8_t* data, int len);
|
|
||||||
void usb_reattach(USBPort* port);
|
void usb_reattach(USBPort* port);
|
||||||
void usb_send_msg(USBDevice* dev, int msg);
|
|
||||||
|
|
||||||
|
|
||||||
/* usb hub */
|
/* usb hub */
|
||||||
USBDevice* usb_hub_init(int nb_ports);
|
|
||||||
|
|
||||||
USBDevice* usb_device_find_device(USBDevice* dev, uint8_t addr);
|
USBDevice* usb_device_find_device(USBDevice* dev, uint8_t addr);
|
||||||
|
|
||||||
void usb_device_cancel_packet(USBDevice* dev, USBPacket* p);
|
void usb_device_cancel_packet(USBDevice* dev, USBPacket* p);
|
||||||
|
@ -587,6 +573,4 @@ int usb_device_alloc_streams(USBDevice* dev, USBEndpoint** eps, int nr_eps,
|
||||||
int streams);
|
int streams);
|
||||||
void usb_device_free_streams(USBDevice* dev, USBEndpoint** eps, int nr_eps);
|
void usb_device_free_streams(USBDevice* dev, USBEndpoint** eps, int nr_eps);
|
||||||
|
|
||||||
const char* usb_device_get_product_desc(USBDevice* dev);
|
|
||||||
|
|
||||||
const USBDesc* usb_device_get_usb_desc(USBDevice* dev);
|
const USBDesc* usb_device_get_usb_desc(USBDevice* dev);
|
|
@ -14,10 +14,10 @@
|
||||||
#define DMA_DIRECTION_FROM_DEVICE 1
|
#define DMA_DIRECTION_FROM_DEVICE 1
|
||||||
#define ED_LINK_LIMIT 32
|
#define ED_LINK_LIMIT 32
|
||||||
|
|
||||||
extern int64_t g_usb_last_cycle;
|
extern s64 g_usb_last_cycle;
|
||||||
#define MIN_IRQ_INTERVAL 64 /* hack */
|
#define MIN_IRQ_INTERVAL 64 /* hack */
|
||||||
|
|
||||||
extern int64_t usb_get_clock();
|
extern s64 usb_get_clock();
|
||||||
extern int usb_get_ticks_per_second();
|
extern int usb_get_ticks_per_second();
|
||||||
extern void usbIrq(int);
|
extern void usbIrq(int);
|
||||||
|
|
||||||
|
@ -26,21 +26,21 @@ extern void usbIrq(int);
|
||||||
|
|
||||||
static void ohci_async_cancel_device(OHCIState* ohci, USBDevice* dev);
|
static void ohci_async_cancel_device(OHCIState* ohci, USBDevice* dev);
|
||||||
|
|
||||||
static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
static u64 muldiv64(u64 a, u32 b, u32 c)
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
uint64_t ll;
|
u64 ll;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint32_t low, high;
|
u32 low, high;
|
||||||
} l;
|
} l;
|
||||||
} u, res;
|
} u, res;
|
||||||
uint64_t rl, rh;
|
u64 rl, rh;
|
||||||
|
|
||||||
u.ll = a;
|
u.ll = a;
|
||||||
rl = (uint64_t)u.l.low * (uint64_t)b;
|
rl = static_cast<u64>(u.l.low) * static_cast<u64>(b);
|
||||||
rh = (uint64_t)u.l.high * (uint64_t)b;
|
rh = static_cast<u64>(u.l.high) * static_cast<u64>(b);
|
||||||
rh += (rl >> 32);
|
rh += (rl >> 32);
|
||||||
res.l.high = rh / c;
|
res.l.high = rh / c;
|
||||||
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
|
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
|
||||||
|
@ -68,7 +68,7 @@ static inline void ohci_intr_update(OHCIState* ohci)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set an interrupt */
|
/* Set an interrupt */
|
||||||
static inline void ohci_set_interrupt(OHCIState* ohci, uint32_t intr)
|
static inline void ohci_set_interrupt(OHCIState* ohci, u32 intr)
|
||||||
{
|
{
|
||||||
ohci->intr_status |= intr;
|
ohci->intr_status |= intr;
|
||||||
ohci_intr_update(ohci);
|
ohci_intr_update(ohci);
|
||||||
|
@ -86,68 +86,12 @@ static void ohci_die(OHCIState* ohci)
|
||||||
// PCI_STATUS_DETECTED_PARITY);
|
// PCI_STATUS_DETECTED_PARITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Attach or detach a device on a root hub port. */
|
|
||||||
// Unused
|
|
||||||
static void ohci_attach2(USBPort* port1, USBDevice* dev)
|
|
||||||
{
|
|
||||||
OHCIState* s = (OHCIState*)port1->opaque;
|
|
||||||
OHCIPort* port = (OHCIPort*)&s->rhport[port1->index];
|
|
||||||
uint32_t old_state = port->ctrl;
|
|
||||||
|
|
||||||
if (dev)
|
|
||||||
{
|
|
||||||
if (port1->dev)
|
|
||||||
{
|
|
||||||
ohci_attach2(port1, NULL);
|
|
||||||
}
|
|
||||||
/* set connect status */
|
|
||||||
port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
|
|
||||||
|
|
||||||
/* update speed */
|
|
||||||
if (dev->speed == USB_SPEED_LOW)
|
|
||||||
port->ctrl |= OHCI_PORT_LSDA;
|
|
||||||
else
|
|
||||||
port->ctrl &= ~OHCI_PORT_LSDA;
|
|
||||||
dev->port = port1;
|
|
||||||
port1->dev = dev;
|
|
||||||
dev->state = USB_STATE_ATTACHED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* set connect status */
|
|
||||||
if (port->ctrl & OHCI_PORT_CCS)
|
|
||||||
{
|
|
||||||
port->ctrl &= ~OHCI_PORT_CCS;
|
|
||||||
port->ctrl |= OHCI_PORT_CSC;
|
|
||||||
}
|
|
||||||
/* disable port */
|
|
||||||
if (port->ctrl & OHCI_PORT_PES)
|
|
||||||
{
|
|
||||||
port->ctrl &= ~OHCI_PORT_PES;
|
|
||||||
port->ctrl |= OHCI_PORT_PESC;
|
|
||||||
}
|
|
||||||
dev = port1->dev;
|
|
||||||
if (dev)
|
|
||||||
{
|
|
||||||
dev->port = NULL;
|
|
||||||
/* send the detach message */
|
|
||||||
dev->state = USB_STATE_NOTATTACHED;
|
|
||||||
}
|
|
||||||
port1->dev = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old_state != port->ctrl)
|
|
||||||
ohci_set_interrupt(s, OHCI_INTR_RHSC);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Attach or detach a device on a root hub port. */
|
/* Attach or detach a device on a root hub port. */
|
||||||
static void ohci_attach(USBPort* port1)
|
static void ohci_attach(USBPort* port1)
|
||||||
{
|
{
|
||||||
OHCIState* s = (OHCIState*)port1->opaque;
|
OHCIState* s = (OHCIState*)port1->opaque;
|
||||||
OHCIPort* port = &s->rhport[port1->index];
|
OHCIPort* port = &s->rhport[port1->index];
|
||||||
uint32_t old_state = port->ctrl;
|
const u32 old_state = port->ctrl;
|
||||||
|
|
||||||
port1->dev->port = port1;
|
port1->dev->port = port1;
|
||||||
|
|
||||||
|
@ -182,7 +126,7 @@ static void ohci_detach(USBPort* port1)
|
||||||
{
|
{
|
||||||
OHCIState* s = (OHCIState*)port1->opaque;
|
OHCIState* s = (OHCIState*)port1->opaque;
|
||||||
OHCIPort* port = &s->rhport[port1->index];
|
OHCIPort* port = &s->rhport[port1->index];
|
||||||
uint32_t old_state = port->ctrl;
|
const u32 old_state = port->ctrl;
|
||||||
|
|
||||||
if (port1->dev)
|
if (port1->dev)
|
||||||
ohci_async_cancel_device(s, port1->dev);
|
ohci_async_cancel_device(s, port1->dev);
|
||||||
|
@ -211,7 +155,7 @@ static void ohci_wakeup(USBPort* port1)
|
||||||
{
|
{
|
||||||
OHCIState* s = (OHCIState*)port1->opaque;
|
OHCIState* s = (OHCIState*)port1->opaque;
|
||||||
OHCIPort* port = (OHCIPort*)&s->rhport[port1->index];
|
OHCIPort* port = (OHCIPort*)&s->rhport[port1->index];
|
||||||
uint32_t intr = 0;
|
u32 intr = 0;
|
||||||
if (port->ctrl & OHCI_PORT_PSS)
|
if (port->ctrl & OHCI_PORT_PSS)
|
||||||
{
|
{
|
||||||
//trace_usb_ohci_port_wakeup(port1->index);
|
//trace_usb_ohci_port_wakeup(port1->index);
|
||||||
|
@ -282,7 +226,7 @@ static void ohci_roothub_reset(OHCIState* ohci)
|
||||||
ohci->rhdesc_b = 0x0; /* Impl. specific */
|
ohci->rhdesc_b = 0x0; /* Impl. specific */
|
||||||
ohci->rhstatus = 0;
|
ohci->rhstatus = 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < ohci->num_ports; i++)
|
for (u32 i = 0; i < ohci->num_ports; i++)
|
||||||
{
|
{
|
||||||
port = &ohci->rhport[i];
|
port = &ohci->rhport[i];
|
||||||
port->ctrl = 0;
|
port->ctrl = 0;
|
||||||
|
@ -336,89 +280,88 @@ void ohci_hard_reset(OHCIState* ohci)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get an array of dwords from main memory */
|
/* Get an array of dwords from main memory */
|
||||||
__fi static int get_dwords(uint32_t addr, uint32_t* buf, uint32_t num)
|
__fi static int get_dwords(u32 addr, u32* buf, u32 num)
|
||||||
{
|
{
|
||||||
if ((addr + (num * sizeof(uint32_t))) > sizeof(iopMem->Main))
|
if ((addr + (num * sizeof(u32))) > sizeof(iopMem->Main))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
std::memcpy(buf, iopMem->Main + addr, num * sizeof(uint32_t));
|
std::memcpy(buf, iopMem->Main + addr, num * sizeof(u32));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get an array of words from main memory */
|
/* Get an array of words from main memory */
|
||||||
__fi static int get_words(uint32_t addr, uint16_t* buf, uint32_t num)
|
__fi static int get_words(u32 addr, u16* buf, u32 num)
|
||||||
{
|
{
|
||||||
if ((addr + (num * sizeof(uint16_t))) > sizeof(iopMem->Main))
|
if ((addr + (num * sizeof(u16))) > sizeof(iopMem->Main))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
std::memcpy(buf, iopMem->Main + addr, num * sizeof(uint16_t));
|
std::memcpy(buf, iopMem->Main + addr, num * sizeof(u16));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put an array of dwords in to main memory */
|
/* Put an array of dwords in to main memory */
|
||||||
__fi static int put_dwords(uint32_t addr, uint32_t* buf, uint32_t num)
|
__fi static int put_dwords(u32 addr, u32* buf, u32 num)
|
||||||
{
|
{
|
||||||
if ((addr + (num * sizeof(uint32_t))) > sizeof(iopMem->Main))
|
if ((addr + (num * sizeof(u32))) > sizeof(iopMem->Main))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
std::memcpy(iopMem->Main + addr, buf, num * sizeof(uint32_t));
|
std::memcpy(iopMem->Main + addr, buf, num * sizeof(u32));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put an array of dwords in to main memory */
|
/* Put an array of dwords in to main memory */
|
||||||
__fi static int put_words(uint32_t addr, uint16_t* buf, uint32_t num)
|
__fi static int put_words(u32 addr, u16* buf, u32 num)
|
||||||
{
|
{
|
||||||
if ((addr + (num * sizeof(uint16_t))) > sizeof(iopMem->Main))
|
if ((addr + (num * sizeof(u16))) > sizeof(iopMem->Main))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
std::memcpy(iopMem->Main + addr, buf, num * sizeof(uint16_t));
|
std::memcpy(iopMem->Main + addr, buf, num * sizeof(u16));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ohci_read_ed(OHCIState* ohci, uint32_t addr, struct ohci_ed* ed)
|
static inline int ohci_read_ed(OHCIState* ohci, u32 addr, struct ohci_ed* ed)
|
||||||
{
|
{
|
||||||
return get_dwords(addr, (uint32_t*)ed, sizeof(*ed) >> 2);
|
return get_dwords(addr, (u32*)ed, sizeof(*ed) >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ohci_read_td(OHCIState* ohci, uint32_t addr, struct ohci_td* td)
|
static inline int ohci_read_td(OHCIState* ohci, u32 addr, struct ohci_td* td)
|
||||||
{
|
{
|
||||||
return get_dwords(addr, (uint32_t*)td, sizeof(*td) >> 2);
|
return get_dwords(addr, (u32*)td, sizeof(*td) >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ohci_read_iso_td(OHCIState* ohci, uint32_t addr, struct ohci_iso_td* td)
|
static inline int ohci_read_iso_td(OHCIState* ohci, u32 addr, struct ohci_iso_td* td)
|
||||||
{
|
{
|
||||||
return get_dwords(addr, (uint32_t*)td, 4) &&
|
return get_dwords(addr, (u32*)td, 4) &&
|
||||||
get_words(addr + 16, td->offset, 8);
|
get_words(addr + 16, td->offset, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ohci_put_ed(OHCIState* ohci, uint32_t addr, struct ohci_ed* ed)
|
static inline int ohci_put_ed(OHCIState* ohci, u32 addr, struct ohci_ed* ed)
|
||||||
{
|
{
|
||||||
/* ed->tail is under control of the HCD.
|
/* ed->tail is under control of the HCD.
|
||||||
* Since just ed->head is changed by HC, just write back this
|
* Since just ed->head is changed by HC, just write back this
|
||||||
*/
|
*/
|
||||||
return put_dwords(addr + ED_WBACK_OFFSET,
|
return put_dwords(addr + ED_WBACK_OFFSET,
|
||||||
(uint32_t*)((char*)ed + ED_WBACK_OFFSET),
|
(u32*)((char*)ed + ED_WBACK_OFFSET),
|
||||||
ED_WBACK_SIZE >> 2);
|
ED_WBACK_SIZE >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ohci_put_td(OHCIState* ohci, uint32_t addr, struct ohci_td* td)
|
static inline int ohci_put_td(OHCIState* ohci, u32 addr, struct ohci_td* td)
|
||||||
{
|
{
|
||||||
return put_dwords(addr, (uint32_t*)td, sizeof(*td) >> 2);
|
return put_dwords(addr, (u32*)td, sizeof(*td) >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int ohci_put_iso_td(OHCIState* ohci, uint32_t addr, struct ohci_iso_td* td)
|
static inline int ohci_put_iso_td(OHCIState* ohci, u32 addr, struct ohci_iso_td* td)
|
||||||
{
|
{
|
||||||
return put_dwords(addr, (uint32_t*)td, 4) &&
|
return put_dwords(addr, (u32*)td, 4) &&
|
||||||
put_words(addr + 16, td->offset, 8);
|
put_words(addr + 16, td->offset, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read/Write the contents of a TD from/to main memory. */
|
/* Read/Write the contents of a TD from/to main memory. */
|
||||||
static int ohci_copy_td(OHCIState* ohci, struct ohci_td* td, uint8_t* buf, uint32_t len, int write)
|
static int ohci_copy_td(OHCIState* ohci, struct ohci_td* td, uint8_t* buf, u32 len, int write)
|
||||||
{
|
{
|
||||||
uint32_t ptr, n;
|
u32 ptr = td->cbp;
|
||||||
|
const u32 n = std::min<u32>(0x1000 - (ptr & 0xfff), len);
|
||||||
|
|
||||||
ptr = td->cbp;
|
|
||||||
n = std::min<uint32_t>(0x1000 - (ptr & 0xfff), len);
|
|
||||||
if ((ptr + n) > sizeof(iopMem->Main))
|
if ((ptr + n) > sizeof(iopMem->Main))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -445,13 +388,11 @@ static int ohci_copy_td(OHCIState* ohci, struct ohci_td* td, uint8_t* buf, uint3
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read/Write the contents of an ISO TD from/to main memory. */
|
/* Read/Write the contents of an ISO TD from/to main memory. */
|
||||||
static int ohci_copy_iso_td(OHCIState* ohci, uint32_t start_addr, uint32_t end_addr,
|
static int ohci_copy_iso_td(OHCIState* ohci, u32 start_addr, u32 end_addr,
|
||||||
uint8_t* buf, uint32_t len, int write)
|
uint8_t* buf, u32 len, int write)
|
||||||
{
|
{
|
||||||
uint32_t ptr, n;
|
u32 ptr = start_addr;
|
||||||
|
const u32 n = std::min<u32>(0x1000 - (ptr & 0xfff), len);
|
||||||
ptr = start_addr;
|
|
||||||
n = std::min<uint32_t>(0x1000 - (ptr & 0xfff), len);
|
|
||||||
|
|
||||||
if ((ptr + n) > sizeof(iopMem->Main))
|
if ((ptr + n) > sizeof(iopMem->Main))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -489,24 +430,21 @@ static void ohci_async_complete_packet(USBPort* port, USBPacket* packet)
|
||||||
ohci_process_lists(ohci, 1);
|
ohci_process_lists(ohci, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b)))
|
#define USUB(a, b) ((int16_t)((u16)(a) - (u16)(b)))
|
||||||
|
|
||||||
static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
||||||
int completion)
|
int completion)
|
||||||
{
|
{
|
||||||
int dir;
|
u32 len = 0;
|
||||||
uint32_t len = 0;
|
[[maybe_unused]] const char* str = nullptr;
|
||||||
[[maybe_unused]] const char* str = NULL;
|
|
||||||
int pid;
|
int pid;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
struct ohci_iso_td iso_td;
|
struct ohci_iso_td iso_td;
|
||||||
uint32_t addr;
|
u32 next_offset;
|
||||||
int16_t relative_frame_number;
|
u32 start_addr, end_addr;
|
||||||
uint32_t next_offset;
|
|
||||||
uint32_t start_addr, end_addr;
|
|
||||||
|
|
||||||
addr = ed->head & OHCI_DPTR_MASK;
|
const u32 addr = ed->head & OHCI_DPTR_MASK;
|
||||||
|
|
||||||
if (!ohci_read_iso_td(ohci, addr, &iso_td))
|
if (!ohci_read_iso_td(ohci, addr, &iso_td))
|
||||||
{
|
{
|
||||||
|
@ -515,9 +453,9 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint16_t starting_frame = OHCI_BM(iso_td.flags, TD_SF);
|
const u16 starting_frame = OHCI_BM(iso_td.flags, TD_SF);
|
||||||
const int frame_count = OHCI_BM(iso_td.flags, TD_FC);
|
const int frame_count = OHCI_BM(iso_td.flags, TD_FC);
|
||||||
relative_frame_number = USUB(ohci->frame_number, starting_frame);
|
const s16 relative_frame_number = USUB(ohci->frame_number, starting_frame);
|
||||||
|
|
||||||
/*trace_usb_ohci_iso_td_head(
|
/*trace_usb_ohci_iso_td_head(
|
||||||
ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
|
ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK,
|
||||||
|
@ -562,7 +500,7 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = OHCI_BM(ed->flags, ED_D);
|
const int dir = OHCI_BM(ed->flags, ED_D);
|
||||||
switch (dir)
|
switch (dir)
|
||||||
{
|
{
|
||||||
case OHCI_TD_DIR_IN:
|
case OHCI_TD_DIR_IN:
|
||||||
|
@ -588,7 +526,7 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t start_offset = iso_td.offset[relative_frame_number];
|
const u32 start_offset = iso_td.offset[relative_frame_number];
|
||||||
if (relative_frame_number < frame_count)
|
if (relative_frame_number < frame_count)
|
||||||
{
|
{
|
||||||
next_offset = iso_td.offset[relative_frame_number + 1];
|
next_offset = iso_td.offset[relative_frame_number + 1];
|
||||||
|
@ -625,7 +563,7 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
||||||
|
|
||||||
if (relative_frame_number < frame_count)
|
if (relative_frame_number < frame_count)
|
||||||
{
|
{
|
||||||
const uint32_t end_offset = next_offset - 1;
|
const u32 end_offset = next_offset - 1;
|
||||||
if ((end_offset & 0x1000) == 0)
|
if ((end_offset & 0x1000) == 0)
|
||||||
{
|
{
|
||||||
end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
|
end_addr = (iso_td.bp & OHCI_PAGE_MASK) |
|
||||||
|
@ -677,7 +615,7 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
||||||
const bool int_req = relative_frame_number == frame_count &&
|
const bool int_req = relative_frame_number == frame_count &&
|
||||||
OHCI_BM(iso_td.flags, TD_DI) == 0;
|
OHCI_BM(iso_td.flags, TD_DI) == 0;
|
||||||
USBDevice* dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
|
USBDevice* dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
|
||||||
if (dev == NULL)
|
if (dev == nullptr)
|
||||||
{
|
{
|
||||||
//trace_usb_ohci_td_dev_error();
|
//trace_usb_ohci_td_dev_error();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -793,22 +731,18 @@ static int ohci_service_iso_td(OHCIState* ohci, struct ohci_ed* ed,
|
||||||
|
|
||||||
static int ohci_service_td(OHCIState* ohci, struct ohci_ed* ed)
|
static int ohci_service_td(OHCIState* ohci, struct ohci_ed* ed)
|
||||||
{
|
{
|
||||||
int dir;
|
u32 len = 0, pktlen = 0;
|
||||||
uint32_t len = 0, pktlen = 0;
|
[[maybe_unused]]const char* str = nullptr;
|
||||||
[[maybe_unused]]const char* str = NULL;
|
|
||||||
int pid;
|
int pid;
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
USBDevice* dev;
|
USBDevice* dev;
|
||||||
USBEndpoint* ep;
|
USBEndpoint* ep;
|
||||||
struct ohci_td td;
|
struct ohci_td td;
|
||||||
uint32_t addr;
|
|
||||||
int flag_r;
|
|
||||||
int completion;
|
|
||||||
|
|
||||||
addr = ed->head & OHCI_DPTR_MASK;
|
const u32 addr = ed->head & OHCI_DPTR_MASK;
|
||||||
/* See if this TD has already been submitted to the device. */
|
/* See if this TD has already been submitted to the device. */
|
||||||
completion = (addr == ohci->async_td);
|
const int completion = (addr == ohci->async_td);
|
||||||
if (completion && !ohci->async_complete)
|
if (completion && !ohci->async_complete)
|
||||||
{
|
{
|
||||||
//trace_usb_ohci_td_skip_async();
|
//trace_usb_ohci_td_skip_async();
|
||||||
|
@ -821,7 +755,7 @@ static int ohci_service_td(OHCIState* ohci, struct ohci_ed* ed)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = OHCI_BM(ed->flags, ED_D);
|
int dir = OHCI_BM(ed->flags, ED_D);
|
||||||
switch (dir)
|
switch (dir)
|
||||||
{
|
{
|
||||||
case OHCI_TD_DIR_OUT:
|
case OHCI_TD_DIR_OUT:
|
||||||
|
@ -892,8 +826,8 @@ static int ohci_service_td(OHCIState* ohci, struct ohci_ed* ed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flag_r = (td.flags & OHCI_TD_R) != 0;
|
const int flag_r = (td.flags & OHCI_TD_R) != 0;
|
||||||
//trace_usb_ohci_td_pkt_hdr(addr, (int64_t)pktlen, (int64_t)len, str,
|
//trace_usb_ohci_td_pkt_hdr(addr, (s64)pktlen, (s64)len, str,
|
||||||
// flag_r, td.cbp, td.be);
|
// flag_r, td.cbp, td.be);
|
||||||
//ohci_td_pkt("OUT", ohci->usb_buf, pktlen);
|
//ohci_td_pkt("OUT", ohci->usb_buf, pktlen);
|
||||||
|
|
||||||
|
@ -915,7 +849,7 @@ static int ohci_service_td(OHCIState* ohci, struct ohci_ed* ed)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
|
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
|
||||||
if (dev == NULL)
|
if (dev == nullptr)
|
||||||
{
|
{
|
||||||
//trace_usb_ohci_td_dev_error();
|
//trace_usb_ohci_td_dev_error();
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1053,13 +987,13 @@ exit_no_retire:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Service an endpoint list. Returns nonzero if active TD were found. */
|
/* Service an endpoint list. Returns nonzero if active TD were found. */
|
||||||
static int ohci_service_ed_list(OHCIState* ohci, uint32_t head, int completion)
|
static int ohci_service_ed_list(OHCIState* ohci, u32 head, int completion)
|
||||||
{
|
{
|
||||||
struct ohci_ed ed;
|
struct ohci_ed ed;
|
||||||
uint32_t next_ed;
|
u32 next_ed = 0;
|
||||||
uint32_t cur;
|
u32 cur;
|
||||||
int active;
|
int active;
|
||||||
uint32_t link_cnt = 0;
|
u32 link_cnt = 0;
|
||||||
active = 0;
|
active = 0;
|
||||||
|
|
||||||
if (head == 0)
|
if (head == 0)
|
||||||
|
@ -1078,7 +1012,7 @@ static int ohci_service_ed_list(OHCIState* ohci, uint32_t head, int completion)
|
||||||
|
|
||||||
if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K))
|
if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K))
|
||||||
{
|
{
|
||||||
uint32_t addr;
|
u32 addr;
|
||||||
/* Cancel pending packets for ED that have been paused. */
|
/* Cancel pending packets for ED that have been paused. */
|
||||||
addr = ed.head & OHCI_DPTR_MASK;
|
addr = ed.head & OHCI_DPTR_MASK;
|
||||||
if (ohci->async_td && addr == ohci->async_td)
|
if (ohci->async_td && addr == ohci->async_td)
|
||||||
|
@ -1254,7 +1188,7 @@ void ohci_bus_stop(OHCIState* ohci)
|
||||||
* connected, if not set ConnectStatusChange flag. If flag is enabled
|
* connected, if not set ConnectStatusChange flag. If flag is enabled
|
||||||
* return 1.
|
* return 1.
|
||||||
*/
|
*/
|
||||||
static int ohci_port_set_if_connected(OHCIState* ohci, int i, uint32_t val)
|
static int ohci_port_set_if_connected(OHCIState* ohci, int i, u32 val)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
|
|
||||||
|
@ -1285,7 +1219,7 @@ static int ohci_port_set_if_connected(OHCIState* ohci, int i, uint32_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the frame interval - frame interval toggle is manipulated by the hcd only */
|
/* Set the frame interval - frame interval toggle is manipulated by the hcd only */
|
||||||
static void ohci_set_frame_interval(OHCIState* ohci, uint16_t val)
|
static void ohci_set_frame_interval(OHCIState* ohci, u16 val)
|
||||||
{
|
{
|
||||||
val &= OHCI_FMI_FI;
|
val &= OHCI_FMI_FI;
|
||||||
|
|
||||||
|
@ -1312,14 +1246,11 @@ static void ohci_port_power(OHCIState* ohci, int i, int p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set HcControlRegister */
|
/* Set HcControlRegister */
|
||||||
static void ohci_set_ctl(OHCIState* ohci, uint32_t val)
|
static void ohci_set_ctl(OHCIState* ohci, u32 val)
|
||||||
{
|
{
|
||||||
uint32_t old_state;
|
const u32 old_state = ohci->ctl & OHCI_CTL_HCFS;
|
||||||
uint32_t new_state;
|
|
||||||
|
|
||||||
old_state = ohci->ctl & OHCI_CTL_HCFS;
|
|
||||||
ohci->ctl = val;
|
ohci->ctl = val;
|
||||||
new_state = ohci->ctl & OHCI_CTL_HCFS;
|
const u32 new_state = ohci->ctl & OHCI_CTL_HCFS;
|
||||||
|
|
||||||
/* no state change */
|
/* no state change */
|
||||||
if (old_state == new_state)
|
if (old_state == new_state)
|
||||||
|
@ -1346,10 +1277,10 @@ static void ohci_set_ctl(OHCIState* ohci, uint32_t val)
|
||||||
//ohci_intr_update(ohci);
|
//ohci_intr_update(ohci);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t ohci_get_frame_remaining(OHCIState* ohci)
|
static u32 ohci_get_frame_remaining(OHCIState* ohci)
|
||||||
{
|
{
|
||||||
uint16_t fr;
|
u16 fr;
|
||||||
int64_t tks;
|
s64 tks;
|
||||||
|
|
||||||
if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
|
if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL)
|
||||||
return (ohci->frt << 31);
|
return (ohci->frt << 31);
|
||||||
|
@ -1364,18 +1295,16 @@ static uint32_t ohci_get_frame_remaining(OHCIState* ohci)
|
||||||
return (ohci->frt << 31);
|
return (ohci->frt << 31);
|
||||||
|
|
||||||
tks = muldiv64(1, tks, g_usb_bit_time);
|
tks = muldiv64(1, tks, g_usb_bit_time);
|
||||||
fr = (uint16_t)(ohci->fi - tks);
|
fr = (u16)(ohci->fi - tks);
|
||||||
|
|
||||||
return (ohci->frt << 31) | fr;
|
return (ohci->frt << 31) | fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Set root hub status */
|
/* Set root hub status */
|
||||||
static void ohci_set_hub_status(OHCIState* ohci, uint32_t val)
|
static void ohci_set_hub_status(OHCIState* ohci, u32 val)
|
||||||
{
|
{
|
||||||
uint32_t old_state;
|
const u32 old_state = ohci->rhstatus;
|
||||||
|
|
||||||
old_state = ohci->rhstatus;
|
|
||||||
|
|
||||||
/* write 1 to clear OCIC */
|
/* write 1 to clear OCIC */
|
||||||
if (val & OHCI_RHS_OCIC)
|
if (val & OHCI_RHS_OCIC)
|
||||||
|
@ -1404,13 +1333,10 @@ static void ohci_set_hub_status(OHCIState* ohci, uint32_t val)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set root hub port status */
|
/* Set root hub port status */
|
||||||
static void ohci_port_set_status(OHCIState* ohci, int portnum, uint32_t val)
|
static void ohci_port_set_status(OHCIState* ohci, int portnum, u32 val)
|
||||||
{
|
{
|
||||||
uint32_t old_state;
|
OHCIPort* port = &ohci->rhport[portnum];
|
||||||
OHCIPort* port;
|
const u32 old_state = port->ctrl;
|
||||||
|
|
||||||
port = &ohci->rhport[portnum];
|
|
||||||
old_state = port->ctrl;
|
|
||||||
|
|
||||||
/* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
|
/* Write to clear CSC, PESC, PSSC, OCIC, PRSC */
|
||||||
if (val & OHCI_PORT_WTC)
|
if (val & OHCI_PORT_WTC)
|
||||||
|
@ -1470,8 +1396,8 @@ static const char* reg_names[] = {
|
||||||
"HcRhStatus",
|
"HcRhStatus",
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t ohci_mem_read_impl(OHCIState* ptr, uint32_t addr);
|
u32 ohci_mem_read_impl(OHCIState* ptr, u32 addr);
|
||||||
uint32_t ohci_mem_read(OHCIState* ptr, uint32_t addr)
|
u32 ohci_mem_read(OHCIState* ptr, u32 addr)
|
||||||
{
|
{
|
||||||
auto val = ohci_mem_read_impl(ptr, addr);
|
auto val = ohci_mem_read_impl(ptr, addr);
|
||||||
int idx = (addr - ptr->mem_base) >> 2;
|
int idx = (addr - ptr->mem_base) >> 2;
|
||||||
|
@ -1482,9 +1408,9 @@ uint32_t ohci_mem_read(OHCIState* ptr, uint32_t addr)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ohci_mem_read_impl(OHCIState* ptr, uint32_t addr)
|
u32 ohci_mem_read_impl(OHCIState* ptr, u32 addr)
|
||||||
#else
|
#else
|
||||||
uint32_t ohci_mem_read(OHCIState* ptr, uint32_t addr)
|
u32 ohci_mem_read(OHCIState* ptr, u32 addr)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
OHCIState* ohci = ptr;
|
OHCIState* ohci = ptr;
|
||||||
|
@ -1571,8 +1497,8 @@ uint32_t ohci_mem_read(OHCIState* ptr, uint32_t addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_OHCI
|
#ifdef DEBUG_OHCI
|
||||||
void ohci_mem_write_impl(OHCIState* ptr, uint32_t addr, uint32_t val);
|
void ohci_mem_write_impl(OHCIState* ptr, u32 addr, u32 val);
|
||||||
void ohci_mem_write(OHCIState* ptr, uint32_t addr, uint32_t val)
|
void ohci_mem_write(OHCIState* ptr, u32 addr, u32 val)
|
||||||
{
|
{
|
||||||
int idx = (addr - ptr->mem_base) >> 2;
|
int idx = (addr - ptr->mem_base) >> 2;
|
||||||
if (idx < countof(reg_names))
|
if (idx < countof(reg_names))
|
||||||
|
@ -1582,9 +1508,9 @@ void ohci_mem_write(OHCIState* ptr, uint32_t addr, uint32_t val)
|
||||||
ohci_mem_write_impl(ptr, addr, val);
|
ohci_mem_write_impl(ptr, addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ohci_mem_write_impl(OHCIState* ptr, uint32_t addr, uint32_t val)
|
void ohci_mem_write_impl(OHCIState* ptr, u32 addr, u32 val)
|
||||||
#else
|
#else
|
||||||
void ohci_mem_write(OHCIState* ptr, uint32_t addr, uint32_t val)
|
void ohci_mem_write(OHCIState* ptr, u32 addr, u32 val)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
OHCIState* ohci = ptr;
|
OHCIState* ohci = ptr;
|
||||||
|
@ -1706,7 +1632,7 @@ static USBPortOps ohci_port_ops = {
|
||||||
/*.complete =*/ohci_async_complete_packet,
|
/*.complete =*/ohci_async_complete_packet,
|
||||||
};
|
};
|
||||||
|
|
||||||
OHCIState* ohci_create(uint32_t base, int ports)
|
OHCIState* ohci_create(u32 base, int ports)
|
||||||
{
|
{
|
||||||
OHCIState* ohci = (OHCIState*)malloc(sizeof(OHCIState));
|
OHCIState* ohci = (OHCIState*)malloc(sizeof(OHCIState));
|
||||||
if (!ohci)
|
if (!ohci)
|
||||||
|
|
Loading…
Reference in New Issue