Files

358 lines
11 KiB
Odin

package usbd
import "core:c"
SCE_USBD_CLASS_PER_INTERFACE :: 0x00
SCE_USBD_CLASS_AUDIO :: 0x01
SCE_USBD_CLASS_COMMUNICATIONS :: 0x02
SCE_USBD_CLASS_HID :: 0x03
SCE_USBD_CLASS_MONITOR :: 0x04
SCE_USBD_CLASS_PHYSICAL :: 0x05
SCE_USBD_CLASS_POWER :: 0x06
SCE_USBD_CLASS_PRINTER :: 0x07
SCE_USBD_CLASS_STORAGE :: 0x08
SCE_USBD_CLASS_HUB :: 0x09
SCE_USBD_CLASS_DATA :: 0x0a
SCE_USBD_CLASS_VENDOR_SPECIFIC :: 0xff
SCE_USBD_CONFIGURATION_RESERVED_ZERO :: 0x1f
SCE_USBD_CONFIGURATION_REMOTE_WAKEUP :: 0x20
SCE_USBD_CONFIGURATION_SELF_POWERED :: 0x40
SCE_USBD_CONFIGURATION_RESERVED_ONE :: 0x80
/* bmAttributes */
SCE_USBD_ENDPOINT_TRANSFER_TYPE_BITS :: 0x03
SCE_USBD_ENDPOINT_TRANSFER_TYPE_SHIFT :: 0
SCE_USBD_ENDPOINT_TRANSFER_TYPE_CONTROL :: 0x00
SCE_USBD_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS :: 0x01
SCE_USBD_ENDPOINT_TRANSFER_TYPE_BULK :: 0x02
SCE_USBD_ENDPOINT_TRANSFER_TYPE_INTERRUPT :: 0x03
/* bEndpointAddress */
SCE_USBD_ENDPOINT_NUMBER_BITS :: 0x1f
SCE_USBD_ENDPOINT_NUMBER_SHIFT :: 0
SCE_USBD_ENDPOINT_DIRECTION_BITS :: 0x80
SCE_USBD_ENDPOINT_DIRECTION_SHIFT :: 7
SCE_USBD_ENDPOINT_DIRECTION_OUT :: 0x00
SCE_USBD_ENDPOINT_DIRECTION_IN :: 0x80
USB_DESCRIPTOR_DEVICE :: 0x01 // bDescriptorType for a Device Descriptor.
USB_DESCRIPTOR_CONFIGURATION :: 0x02 // bDescriptorType for a Configuration Descriptor.
USB_DESCRIPTOR_STRING :: 0x03 // bDescriptorType for a String Descriptor.
USB_DESCRIPTOR_INTERFACE :: 0x04 // bDescriptorType for an Interface Descriptor.
USB_DESCRIPTOR_ENDPOINT :: 0x05 // bDescriptorType for an Endpoint Descriptor.
USB_DESCRIPTOR_DEVICE_QUALIFIER :: 0x06 // bDescriptorType for a Device Qualifier.
USB_DESCRIPTOR_OTHER_SPEED :: 0x07 // bDescriptorType for a Other Speed Configuration.
USB_DESCRIPTOR_INTERFACE_POWER :: 0x08 // bDescriptorType for Interface Power.
USB_DESCRIPTOR_OTG :: 0x09 // bDescriptorType for an OTG Descriptor.
SCE_USBD_DEVICE_SPEED_LS :: 0
SCE_USBD_DEVICE_SPEED_FS :: 1
SCE_USBD_DEVICE_SPEED_HS :: 2
SceUsbdErrorCode :: enum c.uint {
ERROR_NOT_INITIALIZED = 0x80240001,
ERROR_ALREADY_INITIALIZED = 0x80240002,
ERROR_INVALID_PARAM = 0x80240003,
ERROR_PIPE_NOT_FOUND = 0x80240004,
ERROR_NO_MEMORY = 0x80240005,
ERROR_DEVICE_NOT_FOUND = 0x80240006,
ERROR_80240007 = 0x80240007,
ERROR_80240009 = 0x80240009,
ERROR_8024000A = 0x8024000A,
ERROR_FATAL = 0x802400FF
}
SceUsbdDescriptorType :: enum c.int {
DEVICE = 0x01, // bDescriptorType for a Device Descriptor.
CONFIGURATION = 0x02, // bDescriptorType for a Configuration Descriptor.
STRING = 0x03, // bDescriptorType for a String Descriptor.
INTERFACE = 0x04, // bDescriptorType for an Interface Descriptor.
ENDPOINT = 0x05, // bDescriptorType for an Endpoint Descriptor.
DEVICE_QUALIFIER = 0x06, // bDescriptorType for a Device Qualifier.
OTHER_SPEED = 0x07, // bDescriptorType for a Other Speed Configuration.
INTERFACE_POWER = 0x08, // bDescriptorType for Interface Power.
OTG = 0x09, // bDescriptorType for an OTG Descriptor.
HID = 0x21, // bDescriptorType for an HID descriptor.
REPORT = 0x22 // bDescriptorType for an HID report descriptor.
}
SceUsbdDeviceDescriptor :: struct {
bLength: c.uint8_t,
bDescriptorType: c.uint8_t,
bcdUSB: c.uint16_t,
bDeviceClass: c.uint8_t,
bDeviceSubclass: c.uint8_t,
bDeviceProtocol: c.uint8_t,
bMaxPacketSize0: c.uint8_t,
idVendor: c.uint16_t,
idProduct: c.uint16_t,
bcdDevice: c.uint16_t,
iManufacturer: c.uint8_t,
iProduct: c.uint8_t,
iSerialNumber: c.uint8_t,
bNumConfigurations: c.uint8_t,
}
#assert(size_of(SceUsbdDeviceDescriptor) == 0x12)
SceUsbdConfigurationDescriptor :: struct {
bLength: c.uint8_t,
bDescriptorType: c.uint8_t,
wTotalLength: c.uint16_t,
bNumInterfaces: c.uint8_t,
bConfigurationValue: c.uint8_t,
iConfiguration: c.uint8_t,
bmAttributes: c.uint8_t,
MaxPower: c.uint8_t,
}
#assert(size_of(SceUsbdConfigurationDescriptor) == 0xA)
SceUsbdInterfaceDescriptor :: struct {
bLength: c.uint8_t,
bDescriptorType: c.uint8_t,
bInterfaceNumber: c.uint8_t,
bAlternateSetting: c.uint8_t,
bNumEndpoints: c.uint8_t,
bInterfaceClass: c.uint8_t,
bInterfaceSubclass: c.uint8_t,
bInterfaceProtocol: c.uint8_t,
iInterface: c.uint8_t,
}
#assert(size_of(SceUsbdInterfaceDescriptor) == 9)
SceUsbdEndpointDescriptor :: struct {
bLength: c.uint8_t,
bDescriptorType: c.uint8_t,
bEndpointAddress: c.uint8_t,
bmAttributes: c.uint8_t,
wMaxPacketSize: c.uint16_t,
bInterval: c.uint8_t,
}
#assert(size_of(SceUsbdEndpointDescriptor) == 8)
SceUsbdStringDescriptor :: struct {
bLength: c.uint8_t,
bDescriptorType: c.uint8_t,
bString: [0]c.uint8_t,
}
#assert(size_of(SceUsbdStringDescriptor) == 2)
SceUsbdHidSubDescriptorInfo :: struct {
bDescriptorType: c.uint8_t,
wDescriptorLength0: c.uint8_t,
wDescriptorLength1: c.uint8_t,
}
#assert(size_of(SceUsbdHidSubDescriptorInfo) == 3)
SceUsbdHidDescriptor :: struct {
bLength: c.uint8_t,
bDescriptorType: c.uint8_t,
bcdHID0: c.uint8_t,
bcdHID1: c.uint8_t,
bCountryCode: c.uint8_t,
bNumDescriptors: c.uint8_t, /* SubDescriptor count */
SubDescriptorInfo: [0]SceUsbdHidSubDescriptorInfo,
}
#assert(size_of(SceUsbdHidDescriptor) == 6)
SceUsbdDeviceAddress :: struct #packed {
unk0: c.uint,
unk1: c.ushort,
}
#assert(size_of(SceUsbdDeviceAddress) == 6)
SceUsbdDeviceInfo :: struct {
port: c.uint,
device_num: c.uint,
unk3: c.uint, // handled? 0, 1, 2
}
#assert(size_of(SceUsbdDeviceInfo) == 0xC)
SceUsbdTransferData :: struct {
pipe: c.uint, // 0x00
data: rawptr, // 0x04
data_size: c.uint, // 0x08
transferred: rawptr, // // 0x0C // ptr to 8 bytes?
timeout: c.uint, // 0x10 // size of above ptr? only 8 allowed?
}
SceUsbdReceiveEvent :: struct {
unk0: c.uint, // 0
unk1: c.uint, // next ptr?
unk2: c.uint, // != 8, set to 1, 2, 4? // transfer flags? type?
unk3: c.uint,
unk4: c.uint,
unk5: c.uint,
transfer_id: c.uint,
}
#assert(size_of(SceUsbdReceiveEvent) == 0x1C)
SceUsbdAttachCompositeParam :: struct {
driver_id: c.uint32_t,
bus: c.uint32_t,
device: c.uint32_t,
unk3: c.uint32_t, // num devices?
unk4: c.uint32_t,
}
#assert(size_of(SceUsbdAttachCompositeParam) == 0x14)
SceUsbdIsochTransfer :: struct {
unk0: c.uint, // array of num_packets? ptrs to 4
unk1: c.uint, // num packets?
unk2: c.uint,
unk3: c.uint,
unk4: c.uint,
unk5: c.uint,
unk6: c.uint,
unk7: c.uint,
unk8: c.uint,
unk9: c.uint,
}
#assert(size_of(SceUsbdIsochTransfer) == 0x28)
SceUsbdDevicePipe :: struct {
device_id: c.uint,
unk1: c.uint,
unk2: c.uint,
unk3: c.uint,
unk4: c.uint,
unk5: c.uint,
}
#assert(size_of(SceUsbdDevicePipe) == 0x18)
SceUsbdTransferStatus :: struct {
unk0: c.uint32_t, // < 0x40 - transfer id (result of sceUsbdTransferData)
unk1: c.uint32_t, // unused
unk2: c.uint32_t, // ret 4. ptr? // status?
unk3: c.uint32_t, // ret 4. ptr? // transferred?
}
#assert(size_of(SceUsbdTransferStatus) == 0x10)
SceUsbdIsochTransferStatus :: struct {
unk0: c.uint32_t, // < 0x40 - size? pipe? transfer id?
unk1: c.uint32_t, // unused
unk2: ^c.uintptr_t, // ret up to 0x28 buff. 10 * 4 bytes. or 8*5 bytes
unk3: c.uint32_t, // ret 4. ptr?
}
SCE_USBD_PROBE_SUCCEEDED :: (0)
SCE_USBD_PROBE_FAILED :: (-1)
SCE_USBD_ATTACH_SUCCEEDED :: (0)
SCE_USBD_ATTACH_FAILED :: (-1)
SCE_USBD_DETACH_SUCCEEDED :: (0)
SCE_USBD_DETACH_FAILED :: (-1)
SCE_USBD_MAX_LS_CONTROL_PACKET_SIZE :: 8
SCE_USBD_MAX_FS_CONTROL_PACKET_SIZE :: 64
SCE_USBD_MAX_ISOCHRONOUS_PACKET_SIZE :: 1023
SCE_USBD_MAX_LS_INTERRUPT_PACKET_SIZE :: 8
SCE_USBD_MAX_FS_INTERRUPT_PACKET_SIZE :: 64
SCE_USBD_MAX_BULK_PACKET_SIZE :: 64
SCE_USBD_FEATURE_ENDPOINT_HALT :: 0x00
SCE_USBD_FEATURE_DEVICE_REMOTE_WAKEUP :: 0x01
SceUsbdDriver :: struct {
name: cstring,
probe: #type ^proc "c" (device_id: c.int) -> c.int,
attach: #type ^proc "c" (device_id: c.int) -> c.int,
detach: #type ^proc "c" (device_id: c.int) -> c.int,
}
SceUsbdCompositeDriver :: struct {
name: cstring,
probe: #type ^proc "c" (device_id: c.int, desc: ^SceUsbdEndpointDescriptor) -> c.int, // endpoint descriptor should be interface one
attach: #type ^proc "c" (device_id: c.int) -> c.int,
detach: #type ^proc "c" (device_id: c.int) -> c.int,
}
SceUsbdDeviceRequest :: struct {
bmRequestType: c.uint8_t,
bRequest: c.uint8_t,
wValue: c.uint16_t,
wIndex: c.uint16_t,
wLength: c.uint16_t,
}
#assert(size_of(SceUsbdDeviceRequest) == 8)
SceUsbdReqtype :: enum c.int {
DIR_BITS = 0x80,
DIR_TO_DEVICE = 0x00,
DIR_TO_HOST = 0x80,
TYPE_BITS = 0x60,
TYPE_STANDARD = 0x00,
TYPE_CLASS = 0x20,
TYPE_VENDOR = 0x40,
TYPE_RESERVED = 0x60,
RECIP_BITS = 0x1f,
RECIP_DEVICE = 0x00,
RECIP_INTERFACE = 0x01,
RECIP_ENDPOINT = 0x02,
RECIP_OTHER = 0x03,
}
SceUsbdRequest :: enum c.int {
GET_STATUS = 0x00,
CLEAR_FEATURE = 0x01,
SET_FEATURE = 0x03,
SET_ADDRESS = 0x05,
GET_DESCRIPTOR = 0x06,
SET_DESCRIPTOR = 0x07,
GET_CONFIGURATION = 0x08,
SET_CONFIGURATION = 0x09,
GET_INTERFACE = 0x0a,
SET_INTERFACE = 0x0b,
SYNCH_FRAME = 0x0c
}
ksceUsbdIsochPswLen :: bit_field c.uint16_t {
len: c.uint16_t | 12,
PSW: c.uint16_t | 4,
}
#assert(size_of(ksceUsbdIsochPswLen) == 2)
ksceUsbdIsochTransfer :: struct {
buffer_base: rawptr,
relative_start_frame: c.int32_t,
num_packets: c.int32_t,
packets: [8]ksceUsbdIsochPswLen,
}
ksceUsbdDoneCallback :: #type ^proc "c" (result: c.int32_t, count: c.int32_t, arg: rawptr)
ksceUsbdIsochDoneCallback :: #type ^proc "c" (result: c.int32_t, req: ^ksceUsbdIsochTransfer, arg: rawptr)
// OHCI/EHCI completion codes
OHCI_CC_NO_ERROR :: 0x0
OHCI_CC_CRC :: 0x1
OHCI_CC_BIT_STUFFING :: 0x2
OHCI_CC_DATA_TOGGLE_MISMATCH :: 0x3
OHCI_CC_STALL :: 0x4
OHCI_CC_DEVICE_NOT_RESPONDING :: 0x5
OHCI_CC_PID_CHECK_FAILURE :: 0x6
OHCI_CC_UNEXPECTED_PID :: 0x7
OHCI_CC_DATA_OVERRUN :: 0x8
OHCI_CC_DATA_UNDERRUN :: 0x9
OHCI_CC_BUFFER_OVERRUN :: 0xc
OHCI_CC_BUFFER_UNDERRUN :: 0xd
OHCI_CC_NOT_ACCESSED1 :: 0xe
OHCI_CC_NOT_ACCESSED2 :: 0xf
EHCI_CC_MISSED_MICRO_FRAME :: 0x10
EHCI_CC_XACT :: 0x20
EHCI_CC_BABBLE :: 0x30
EHCI_CC_DATABUF :: 0x40
EHCI_CC_HALTED :: 0x50
// Isochronous transfer(PSW) completion codes
USBD_CC_NOERR :: 0x0
USBD_CC_MISSED_MICRO_FRAME :: 0x1
USBD_CC_XACTERR :: 0x2
USBD_CC_BABBLE :: 0x4
USBD_CC_DATABUF :: 0x8