module USB_Types {

/* USB Standard Descriptors as per the "Universal Serial Bus Specification Revision 2.0 */

import from General_Types all;

type hexstring HEX4LE length(4) with { variant "BYTEORDER(last)" variant "HEXORDER(high)" };
type integer u8_t (0..255) with { variant "unsigned 8 bit" };
type integer u16le_t (0..65535) with { variant "unsigned 16 bit" variant "BYTEORDER(first)" };
type integer u32le_t (0..4294967295) with { variant "unsigned 32 bit" variant "BYTEORDER(first)" };

/* Chapter 9.3 */
type enumerated USB_RequestType_Direction {
	Host_to_Device		(0),
	Device_to_Host		(1)
} with { variant "FIELDLENGTH(1)" };
type enumerated USB_RequestType_Type {
	RequestType_Standard	(0),
	RequestType_Class	(1),
	RequestType_Vendor	(2),
	RequestType_Reserve	(3)
} with { variant "FIELDLENGTH(2)" };
type enumerated USB_RequestType_Recipient {
	RequestRecipient_Device		(0),
	RequestRecipient_Interface	(1),
	RequestRecipient_Endpoint	(2),
	RequestRecipient_Other		(3)
} with { variant "FIELDLENGTH(5)" };
type record USB_DeviceRequestType {
	USB_RequestType_Direction	direction,
	USB_RequestType_Type		req_type,
	USB_RequestType_Recipient	recipient
};
type record USB_DeviceRequest {
	USB_DeviceRequestType		req_type,
	OCT1				bRequest,
	u16le_t				wValue,
	u16le_t				wIndex,
	u16le_t				wLength
};

external function enc_USB_DeviceRequest(in USB_DeviceRequest desc) return octetstring
	with { extension "prototype(convert) encode(RAW)" };
external function dec_USB_DeviceRequest(in octetstring stream) return USB_DeviceRequest
	with { extension "prototype(convert) decode(RAW)" };

/* Chapter 9.4, Table 9-4: Standard Request Codes */
type enumerated USB_DeviceRequestCode {
	USB_DevReq_GET_STATUS			(0),
	USB_DevReq_CLEAR_FEATURE		(1),
	USB_DevReq_SET_FEATURE			(3),
	USB_DevReq_SET_ADDRESS			(5),
	USB_DevReq_GET_DESCRIPTOR		(6),
	USB_DevReq_SET_DESCRIPTOR		(7),
	USB_DevReq_GET_CONFIGURATION		(8),
	USB_DevReq_SET_CONFIGURATION		(9),
	USB_DevReq_GET_INTERFACE		(10),
	USB_DevReq_SET_INTERFACE		(11),
	USB_DevReq_SYNCH_FRAME			(12)
} with { variant "FIELDLENGTH(8)" };

/* Chapter 9.4, Table 9-5: Descriptor Type */
type enumerated USB_DescriptorType {
	USB_DescriptorType_DEVICE		(1),
	USB_DescriptorType_CONFIGURATION	(2),
	USB_DescriptorType_STRING		(3),
	USB_DescriptorType_INTERFACE		(4),
	USB_DescriptorType_ENDPOINT		(5),
	USB_DescriptorType_DEVICE_QUALIFIER	(6),
	USB_DescriptorType_OTHER_SPEED_CONFIG	(7),
	USB_DescriptorType_INTERFACE_POWER	(8)
} with { variant "FIELDLENGTH(8)" };

/* Chapter 9.4, Table 9-6: Standard Feature Selectors */
type enumerated USB_Feature_Selector {
	USB_Feature_DEVICE_REMOTE_WAKEUP	(1),
	USB_Feature_ENDPOINT_HALT		(0),
	USB_Feature_TEST_MODE			(2)
} with { variant "FIELDLENGTH(8)" };

type record USB_DescriptorHeader {
	u8_t		bLength,
	OCT1		bDescriptorType
};

/* Chapter 9.6.1: Device Descriptor */
type record USB_DeviceDescriptor {
	u8_t		bLength,
	OCT1		bDescriptorType,
	HEX4LE		bcdUSB,
	OCT1		bDeviceClass,
	OCT1		bDeviceSubClass,
	OCT1		bDeviceProtocol,
	u8_t		bMaxPacketSize0,
	HEX4LE		idVendor,
	HEX4LE		idProduct,
	HEX4LE		bcdDevice,
	u8_t		iManufacturer,
	u8_t		iProduct,
	u8_t		iSerialNumber,
	u8_t		bNumConfigurations
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,bcdUSB,bDeviceClass,bDeviceSubClass,
				     bDeviceProtocol,bMaxPacketSize0,idVendor,idProduct,
				     bcdDevice,iManufacturer,iProduct,iSerialNumber,bNumConfigurations)" };

external function enc_USB_DeviceDescriptor(in USB_DeviceDescriptor desc) return octetstring
	with { extension "prototype(convert) encode(RAW)" };
external function dec_USB_DeviceDescriptor(in octetstring stream) return USB_DeviceDescriptor
	with { extension "prototype(convert) decode(RAW)" };

/* Chapter 9.6.2: Device_Qualifier */
type record USB_DeviceQualifierDescriptor {
	u8_t		bLength,
	OCT1		bDescriptorType,
	HEX4n		bcdUSB,
	OCT1		bDeviceClass,
	OCT1		bDeviceSubClass,
	OCT1		bDeviceProtocol,
	u8_t		bMaxPacketSize0,
	u8_t		bNumConfigurations,
	OCT1		bReserved
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,bcdUSB,bDeviceClass,bcdUSB,bDeviceClass,
				     bDeviceSubClass,bDeviceProtocol,bMaxPacketSize0,
				     bNumConfigurations,bReserved)" };

/* Chapter 9.6.3: Configuration Descriptor */
type record USB_CfgAttrib {
	BIT1		reserved1,
	boolean		self_powered,
	boolean		remote_wakeup,
	BIT5		reserved0
};
type record USB_ConfigurationDescriptor {
	u8_t		bLength,
	OCT1		bDescriptorType,
	u16le_t		wTotalLength,
	u8_t		bNumInterfaces,
	u8_t		bConfigurationValue,
	u8_t		iConfiguration,
	USB_CfgAttrib	bmAttributes,
	u8_t		bMaxPower
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,wTotalLength,bNumInterfaces,
				     bConfigurationValue,iConfiguration,bmAttributes,bMaxPower)" };

/* Chapter 9.6.4 Other_Speed_Configuration Descripotor */
type record USB_OtherSpeedConfigurationDescriptor {
	u8_t		bLength,
	OCT1		bDescriptorType,
	u16le_t		wTotalLength,
	u8_t		bNumInterfaces,
	u8_t		bConfigurationValue,
	u8_t		iConfiguration,
	USB_CfgAttrib	bmAttributes,
	u8_t		bMaxPower
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,wTotalLength,bNumInterfaces,
				     bConfigurationValue,iConfiguration,bmAttributes,bMaxPower)" };

/* Chapter 9.6.5: Interface Descriptor */
type record USB_InterfaceDescriptor {
	u8_t		bLength,
	OCT1		bDescriptorType,
	u8_t		bInterfaceNumber,
	u8_t		bAlternateSetting,
	u8_t		bNumEndpoints,
	OCT1		bInterfaceClass,
	OCT1		bInterfaceSubClass,
	OCT1		bInterfaceProtocol,
	u8_t		iInterface
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,bInterfaceNumber,bAlternateSetting,
				     bNumEndpoints,bInterfaceClass,bInterfaceSubClass,bInterfaceProtocol,
				     iInterface)" };

/* Chapter 9.6.6: Endpoint Descriptor */
type enumerated USB_EpUsage {
	USB_EpUsage_DATA		(0),
	USB_EpUsage_FEEDBACK		(1),
	USB_EpUsage_IMPLICIT_FEEDBACK	(2),
	USB_EpUsage_RESERVED		(3)
} with { variant "FIELDLENGTH(2)" }
type enumerated USB_EpSync {
	USB_EpSync_NO			(0),
	USB_EpSync_ASYNC		(1),
	USB_EpSync_ADAPTIVE		(2),
	USB_EpSync_SYNCHRONOUS		(3)
} with { variant "FIELDLENGTH(2)" }
type enumerated USB_EpTransfer {
	USB_EpTransfer_CONTROL		(0),
	USB_EpTransfer_ISOCHRONOUS	(1),
	USB_EpTransfer_BULK		(2),
	USB_EpTransfer_INTERRUPT	(3)
} with { variant "FIELDLENGTH(2)" }
type record USB_EpAttribs {
	BIT2		RFU,
	USB_EpUsage	UsageType,
	USB_EpSync	SyncType,
	USB_EpTransfer	TranferType
};
type record USB_EndpointDescriptor {
	u8_t		bLength,
	OCT1		bDescriptorType,
	OCT1		bEndpointAddress,
	USB_EpAttribs	bmAttributes,
	u16le_t		wMaxPacketSize,
	u8_t		bInterval
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,bEndpointAddress,bmAttributes,
				     wMaxPacketSize,bInterval)" };

/* Chapter 9.6.7: String Descriptor */
type record USB_StringDescriptor {
	u8_t		bLength,
	OCT1		bDescriptorType,
	octetstring	string
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,string)" };
type record of u16le_t LangIds;
type record USB_StringDescriptorLang {
	u8_t		bLength,
	OCT1		bDescriptorType,
	LangIds		wLANGID
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,wLANGID)" };

/* any other descriptor that's not a standard descriptor */
type record USB_OtherDescriptor {
	u8_t		bLength,
	OCT1		bDescriptorType,
	octetstring	data
} with { variant (bLength) "LENGTHTO(bLength,bDescriptorType,data)" };

type union USB_StandardDescriptor {
	USB_DeviceDescriptor			device,
	USB_DeviceQualifierDescriptor		device_qualifier,
	USB_ConfigurationDescriptor		configuration,
	USB_OtherSpeedConfigurationDescriptor	other_speed_config,
	USB_InterfaceDescriptor			interface,
	USB_EndpointDescriptor			endpoint,
	USB_StringDescriptor			string,
	USB_OtherDescriptor			other
} with { variant "TAG(	device, 		bDescriptorType = '01'O;
			device_qualifier,	bDescriptorType = '06'O;
			configuration,		bDescriptorType = '02'O;
			other_speed_config,	bDescriptorType = '07'O;
			interface,		bDescriptorType = '04'O;
			endpoint,		bDescriptorType = '05'O;
			string,			bDescriptorType = '03'O;
			other,			OTHERWISE
		)" };

external function enc_USB_StandardDescriptor(in USB_StandardDescriptor desc) return octetstring
	with { extension "prototype(convert) encode(RAW)" };
external function dec_USB_StandardDescriptor(in octetstring stream) return USB_StandardDescriptor
	with { extension "prototype(convert) decode(RAW)" };

type record of USB_StandardDescriptor USB_StandardDescriptors;
external function enc_USB_StandardDescriptors(in USB_StandardDescriptors desc) return octetstring
	with { extension "prototype(convert) encode(RAW)" };
external function dec_USB_StandardDescriptors(in octetstring stream) return USB_StandardDescriptors
	with { extension "prototype(convert) decode(RAW)" };



} with { encode "RAW"; variant "FIELDORDER(msb)" };
