1 // license:BSD-3-Clause
2 // copyright-holders:Samuele Zannoli
3 #ifndef MAME_INCLUDES_XBOX_USB_H
4 #define MAME_INCLUDES_XBOX_USB_H
5 
6 #pragma once
7 
8 #include <forward_list>
9 #include <functional>
10 #include <memory>
11 
12 
13 struct OHCIEndpointDescriptor {
14 	int mps; // MaximumPacketSize
15 	int f; // Format
16 	int k; // sKip
17 	int s; // Speed
18 	int d; // Direction
19 	int en; // EndpointNumber
20 	int fa; // FunctionAddress
21 	uint32_t tailp; // TDQueueTailPointer
22 	uint32_t headp; // TDQueueHeadPointer
23 	uint32_t nexted; // NextED
24 	int c; // toggleCarry
25 	int h; // Halted
26 	uint32_t word0;
27 };
28 
29 struct OHCITransferDescriptor {
30 	int cc; // ConditionCode
31 	int ec; // ErrorCount
32 	int t; // DataToggle
33 	int di; // DelayInterrupt
34 	int dp; // Direction/PID
35 	int r; // bufferRounding
36 	uint32_t cbp; // CurrentBufferPointer
37 	uint32_t nexttd; // NextTD
38 	uint32_t be; // BufferEnd
39 	uint32_t word0;
40 };
41 
42 struct OHCIIsochronousTransferDescriptor {
43 	int cc; // ConditionCode
44 	int fc; // FrameCount
45 	int di; // DelayInterrupt
46 	int sf; // StartingFrame
47 	uint32_t bp0; // BufferPage0
48 	uint32_t nexttd; // NextTD
49 	uint32_t be; // BufferEnd
50 	uint32_t offset[8]; // Offset/PacketStatusWord
51 	uint32_t word0;
52 	uint32_t word1;
53 };
54 
55 enum OHCIRegisters {
56 	HcRevision=0,
57 	HcControl,
58 	HcCommandStatus,
59 	HcInterruptStatus,
60 	HcInterruptEnable,
61 	HcInterruptDisable,
62 	HcHCCA,
63 	HcPeriodCurrentED,
64 	HcControlHeadED,
65 	HcControlCurrentED,
66 	HcBulkHeadED,
67 	HcBulkCurrentED,
68 	HcDoneHead,
69 	HcFmInterval,
70 	HcFmRemaining,
71 	HcFmNumber,
72 	HcPeriodicStart,
73 	HcLSThreshold,
74 	HcRhDescriptorA,
75 	HcRhDescriptorB,
76 	HcRhStatus,
77 	HcRhPortStatus1
78 };
79 
80 enum HcControlBits
81 {
82 	CBSR = 3 << 0, // ControlBulkServiceRatio
83 	PLE = 1 << 2, // PeriodicListEnable
84 	IE = 1 << 3, // IsochronousEnable
85 	CLE = 1 << 4, // ControlListEnable
86 	BLE = 1 << 5, // BulkListEnable
87 	HCFS = 3 << 6, // HostControllerFunctionalState
88 	IR = 1 << 8, // InterruptRouting
89 	RWC = 1 << 9, // RemoteWakeupConnected
90 	RWE = 1 << 10 // RemoteWakeupEnable
91 };
92 
93 enum HcCommandStatusBits
94 {
95 	HCR = 1 << 0, // HostControllerReset
96 	CLF = 1 << 1, // ControlListFilled
97 	BLF = 1 << 2, // BulkListFilled
98 	OCR = 1 << 3, // OwnershipChangeRequest
99 	SOC = 3 << 16 // SchedulingOverrunCount
100 };
101 
102 enum HcInterruptEnableBits
103 {
104 	SO = 1 << 0, // SchedulingOverrun
105 	WDH = 1 << 1, // WritebackDoneHead
106 	SF = 1 << 2, // StartofFrame
107 	RD = 1 << 3, // ResumeDetected
108 	UE = 1 << 4, // UnrecoverableError
109 	FNO = 1 << 5, // FrameNumberOverflow
110 	RHSC = 1 << 6, // RootHubStatusChange
111 	OC = 1 << 30, // OwnershipChange
112 	MIE = 1 << 31, // MasterInterruptEnable
113 };
114 
115 
116 enum HcRhDescriptorABits
117 {
118 	NDP = 0xff << 0, // NumberDownstreamPorts
119 	PSM = 1 << 8, // PowerSwitchingMode
120 	NPS = 1 << 9, // NoPowerSwitching
121 	DT = 1 << 10, // DeviceType
122 	OCPM = 1 << 11, // OverCurrentProtectionMode
123 	NOCPM = 1 << 12, // NoOverCurrentProtection
124 	POTPGT = 0xff << 24 // PowerOnToPowerGoodTime
125 };
126 
127 enum HcRhDescriptorBBits
128 {
129 	DR = 0xffff << 0, // DeviceRemovable
130 	PPCM = 0xffff << 16 // PortPowerControlMask
131 };
132 
133 enum HcRhStatusBits
134 {
135 	LPS = 1 << 0, // LocalPowerStatus
136 	OCI = 1 << 1, // OverCurrentIndicator
137 	DRWE = 1 << 15, // DeviceRemoteWakeupEnable
138 	LPSC = 1 << 16, // LocalPowerStatusChange
139 	OCIC = 1 << 17, // OverCurrentIndicatorChange
140 	CRWE = 1 << 31, // ClearRemoteWakeupEnable
141 };
142 
143 enum HcRhPortStatusBits
144 {
145 	CCS = 1 << 0, // CurrentConnectStatus
146 	PES = 1 << 1, // PortEnableStatus
147 	PSS = 1 << 2, // PortSuspendStatus
148 	POCI = 1 << 3, // PortOverCurrentIndicator
149 	PRS = 1 << 4, // PortResetStatus
150 	PPS = 1 << 8, // PortPowerStatus
151 	LSDA = 1 << 9, // LowSpeedDeviceAttached
152 	CSC = 1 << 16, // ConnectStatusChange
153 	PESC = 1 << 17, // PortEnableStatusChange
154 	PSSC = 1 << 18, // PortSuspendStatusChange
155 	POCIC = 1 << 19, // PortOverCurrentIndicatorChange
156 	PRSC = 1 << 20 // PortResetStatusChange
157 };
158 
159 enum OHCIHostControllerFunctionalState {
160 	UsbReset=0,
161 	UsbResume,
162 	UsbOperational,
163 	UsbSuspend
164 };
165 
166 enum OHCIInterrupt {
167 	SchedulingOverrun=1,
168 	WritebackDoneHead=2,
169 	StartofFrame=4,
170 	ResumeDetected=8,
171 	UnrecoverableError=16,
172 	FrameNumberOverflow=32,
173 	RootHubStatusChange=64,
174 	OwnershipChange=0x40000000,
175 	MasterInterruptEnable=0x80000000
176 };
177 
178 enum OHCICompletionCode {
179 	NoError=0,
180 	CRC,
181 	BitStuffing,
182 	DataToggleMismatch,
183 	Stall,
184 	DeviceNotResponding,
185 	PIDCheckFailure,
186 	UnexpectedPID,
187 	DataOverrun,
188 	DataUnderrun,
189 	BufferOverrun=12,
190 	BufferUnderrun,
191 	NotAccessed=14
192 };
193 
194 struct USBSetupPacket {
195 	uint8_t bmRequestType;
196 	uint8_t bRequest;
197 	uint16_t wValue;
198 	uint16_t wIndex;
199 	uint16_t wLength;
200 };
201 
202 struct USBStandardDeviceDescriptor {
203 	uint8_t bLength;
204 	uint8_t bDescriptorType;
205 	uint16_t bcdUSB;
206 	uint8_t bDeviceClass;
207 	uint8_t bDeviceSubClass;
208 	uint8_t bDeviceProtocol;
209 	uint8_t bMaxPacketSize0;
210 	uint16_t idVendor;
211 	uint16_t idProduct;
212 	uint16_t bcdDevice;
213 	uint8_t iManufacturer;
214 	uint8_t iProduct;
215 	uint8_t iSerialNumber;
216 	uint8_t bNumConfigurations;
217 };
218 
219 struct USBStandardConfigurationDescriptor {
220 	uint8_t bLength;
221 	uint8_t bDescriptorType;
222 	uint16_t wTotalLength;
223 	uint8_t bNumInterfaces;
224 	uint8_t bConfigurationValue;
225 	uint8_t iConfiguration;
226 	uint8_t bmAttributes;
227 	uint8_t MaxPower;
228 };
229 
230 struct USBStandardInterfaceDescriptor {
231 	uint8_t bLength;
232 	uint8_t bDescriptorType;
233 	uint8_t bInterfaceNumber;
234 	uint8_t bAlternateSetting;
235 	uint8_t bNumEndpoints;
236 	uint8_t bInterfaceClass;
237 	uint8_t bInterfaceSubClass;
238 	uint8_t bInterfaceProtocol;
239 	uint8_t iInterface;
240 };
241 
242 struct USBStandardEndpointDescriptor {
243 	uint8_t bLength;
244 	uint8_t bDescriptorType;
245 	uint8_t bEndpointAddress;
246 	uint8_t bmAttributes;
247 	uint16_t wMaxPacketSize;
248 	uint8_t bInterval;
249 };
250 
251 enum USBPid {
252 	SetupPid=0,
253 	OutPid,
254 	InPid
255 };
256 
257 enum USBRequestCode {
258 	GET_STATUS=0,
259 	CLEAR_FEATURE=1,
260 	SET_FEATURE=3,
261 	SET_ADDRESS=5,
262 	GET_DESCRIPTOR=6,
263 	SET_DESCRIPTOR=7,
264 	GET_CONFIGURATION=8,
265 	SET_CONFIGURATION=9,
266 	GET_INTERFACE=10,
267 	SET_INTERFACE=11,
268 	SYNCH_FRAME=12
269 };
270 
271 enum USBDescriptorType {
272 	DEVICE=1,
273 	CONFIGURATION=2,
274 	STRING=3,
275 	INTERFACE=4,
276 	ENDPOINT=5
277 };
278 
279 enum USBRequestType
280 {
281 	StandardType=0,
282 	ClassType,
283 	VendorType,
284 	ReservedType
285 };
286 
287 enum USBRequestRecipient
288 {
289 	DeviceRecipient=0,
290 	InterfaceRecipient,
291 	EndpointRecipient,
292 	OtherRecipient
293 };
294 
295 enum USBDeviceState
296 {
297 	DefaultState,
298 	AddressState,
299 	ConfiguredState
300 };
301 
302 enum USBControlDirection
303 {
304 	HostToDevice=0,
305 	DeviceToHost=1
306 };
307 
308 enum USBEndpointType
309 {
310 	ControlEndpoint=0,
311 	IsochronousEndpoint,
312 	BulkEndpoint,
313 	InterruptEndpoint
314 };
315 
316 struct usb_device_string
317 {
318 	uint8_t *position;
319 	int size;
320 };
321 
322 struct usb_device_interfac_alternate
323 {
324 	uint8_t *position;
325 	int size;
326 	USBStandardInterfaceDescriptor interface_descriptor;
327 	std::forward_list<USBStandardEndpointDescriptor> endpoint_descriptors;
328 };
329 
330 struct usb_device_interfac
331 {
332 	uint8_t *position;
333 	int size;
334 	std::forward_list<usb_device_interfac_alternate> alternate_settings;
335 	int selected_alternate;
336 };
337 
338 struct usb_device_configuration
339 {
340 	USBStandardConfigurationDescriptor configuration_descriptor;
341 	uint8_t *position;
342 	int size;
343 	std::forward_list<usb_device_interfac> interfaces;
344 };
345 
346 /*
347  * OHCI Usb Controller
348  */
349 
350 class device_usb_ohci_function_interface; // forward declaration
351 
352 class ohci_usb_controller
353 {
354 public:
355 	ohci_usb_controller();
~ohci_usb_controller()356 	~ohci_usb_controller() {}
357 	void usb_ohci_plug(int port, device_usb_ohci_function_interface *function);
358 	void usb_ohci_device_address_changed(int old_address, int new_address);
set_cpu(cpu_device * cpu)359 	void set_cpu(cpu_device *cpu) { m_maincpu = cpu; }
set_timer(emu_timer * timer)360 	void set_timer(emu_timer *timer) { ohcist.timer = timer; }
set_irq_callback(std::function<void (int state)> callback)361 	void set_irq_callback(std::function<void(int state)> callback) { irq_callback = callback; }
362 
363 	void start();
364 	void reset();
365 	void timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
366 
367 	uint32_t read(offs_t offset);
368 	void write(offs_t offset, uint32_t data);
369 
370 private:
371 	void usb_ohci_interrupts();
372 	void usb_ohci_read_endpoint_descriptor(uint32_t address);
373 	void usb_ohci_writeback_endpoint_descriptor(uint32_t address);
374 	void usb_ohci_read_transfer_descriptor(uint32_t address);
375 	void usb_ohci_writeback_transfer_descriptor(uint32_t address);
376 	void usb_ohci_read_isochronous_transfer_descriptor(uint32_t address);
377 	void usb_ohci_writeback_isochronous_transfer_descriptor(uint32_t address);
378 	std::function<void (int state)> irq_callback;
379 	cpu_device *m_maincpu;
380 	struct {
381 		uint32_t hc_regs[256];
382 		struct {
383 			device_usb_ohci_function_interface *function;
384 			int address;
385 			int delay;
386 		} ports[4 + 1];
387 		struct
388 		{
389 			device_usb_ohci_function_interface *function;
390 			int port;
391 		} address[256];
392 		emu_timer *timer;
393 		int state;
394 		uint32_t framenumber;
395 		uint32_t nextinterupted;
396 		uint32_t nextbulked;
397 		int interruptbulkratio;
398 		int writebackdonehadcounter;
399 		address_space *space;
400 		uint8_t buffer[1024];
401 		OHCIEndpointDescriptor endpoint_descriptor;
402 		OHCITransferDescriptor transfer_descriptor;
403 		OHCIIsochronousTransferDescriptor isochronous_transfer_descriptor;
404 	} ohcist;
405 };
406 
407 /*
408  * Base class for usb devices
409  */
410 
411 class device_usb_ohci_function_interface : public device_interface {
412 public:
413 	virtual void initialize();
414 	virtual void execute_reset();
execute_connect()415 	virtual void execute_connect() {}
execute_disconnect()416 	virtual void execute_disconnect() {}
417 	void set_bus_manager(ohci_usb_controller *usb_bus_manager);
418 	int execute_transfer(int endpoint, int pid, uint8_t *buffer, int size);
419 protected:
420 	device_usb_ohci_function_interface(const machine_config &config, device_t &device);
handle_nonstandard_request(int endpoint,USBSetupPacket * setup)421 	virtual int handle_nonstandard_request(int endpoint, USBSetupPacket *setup) { return -1; }
handle_get_status_request(int endpoint,USBSetupPacket * setup)422 	virtual int handle_get_status_request(int endpoint, USBSetupPacket *setup) { return 0; }
handle_clear_feature_request(int endpoint,USBSetupPacket * setup)423 	virtual int handle_clear_feature_request(int endpoint, USBSetupPacket *setup) { return 0; }
handle_set_feature_request(int endpoint,USBSetupPacket * setup)424 	virtual int handle_set_feature_request(int endpoint, USBSetupPacket *setup) { return 0; }
handle_set_descriptor_request(int endpoint,USBSetupPacket * setup)425 	virtual int handle_set_descriptor_request(int endpoint, USBSetupPacket *setup) { return 0; }
handle_synch_frame_request(int endpoint,USBSetupPacket * setup)426 	virtual int handle_synch_frame_request(int endpoint, USBSetupPacket *setup) { return 0; }
handle_status_stage(int endpoint)427 	virtual void handle_status_stage(int endpoint) { return; }
handle_bulk_pid(int endpoint,int pid,uint8_t * buffer,int size)428 	virtual int handle_bulk_pid(int endpoint, int pid, uint8_t *buffer, int size) { return 0; }
handle_interrupt_pid(int endpoint,int pid,uint8_t * buffer,int size)429 	virtual int handle_interrupt_pid(int endpoint, int pid, uint8_t *buffer, int size) { return 0; }
handle_isochronous_pid(int endpoint,int pid,uint8_t * buffer,int size)430 	virtual int handle_isochronous_pid(int endpoint, int pid, uint8_t *buffer, int size) { return 0; }
431 
432 	void add_device_descriptor(const USBStandardDeviceDescriptor &descriptor);
433 	void add_configuration_descriptor(const USBStandardConfigurationDescriptor &descriptor);
434 	void add_interface_descriptor(const USBStandardInterfaceDescriptor &descriptor);
435 	void add_endpoint_descriptor(const USBStandardEndpointDescriptor &descriptor);
436 	void add_string_descriptor(const uint8_t *descriptor);
437 	void select_configuration(int index);
438 	void select_alternate(int interfacei, int index);
439 	int find_alternate(int interfacei);
440 	uint8_t *position_device_descriptor(int &size);
441 	uint8_t *position_configuration_descriptor(int index, int &size);
442 	uint8_t *position_string_descriptor(int index, int &size);
443 	ohci_usb_controller *busmanager;
444 	struct {
445 		int type;
446 		int controldirection;
447 		int controltype;
448 		int controlrecipient;
449 		int remain;
450 		uint8_t *position;
451 		uint8_t buffer[128];
452 	} endpoints[256];
453 	int state;
454 	bool settingaddress;
455 	int newaddress;
456 	int address;
457 	int configurationvalue;
458 	std::unique_ptr<uint8_t []> descriptors;
459 	int descriptors_pos;
460 	bool wantstatuscallback;
461 	USBStandardDeviceDescriptor device_descriptor;
462 	std::forward_list<usb_device_configuration> configurations;
463 	std::forward_list<usb_device_string> device_strings;
464 	usb_device_configuration *latest_configuration;
465 	usb_device_interfac_alternate *latest_alternate;
466 	usb_device_configuration *selected_configuration;
467 };
468 
469 /*
470  * Usb port connector
471  */
472 
473 class ohci_usb_connector : public device_t, public device_single_card_slot_interface<device_usb_ohci_function_interface>
474 {
475 public:
476 	template <typename T>
ohci_usb_connector(const machine_config & mconfig,const char * tag,device_t * owner,T && opts,const char * dflt,bool fixed)477 	ohci_usb_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, bool fixed)
478 		: ohci_usb_connector(mconfig, tag, owner, 0)
479 	{
480 		option_reset();
481 		opts(*this);
482 		set_default_option(dflt);
483 		set_fixed(fixed);
484 	}
485 
486 	ohci_usb_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
487 	virtual ~ohci_usb_connector();
488 
489 protected:
490 	virtual void device_start() override;
491 };
492 
DECLARE_DEVICE_TYPE(OHCI_USB_CONNECTOR,ohci_usb_connector)493 DECLARE_DEVICE_TYPE(OHCI_USB_CONNECTOR, ohci_usb_connector)
494 
495 /*
496  * Game controller usb device
497  */
498 
499 DECLARE_DEVICE_TYPE(OHCI_GAME_CONTROLLER, ohci_game_controller_device)
500 
501 class ohci_game_controller_device : public device_t, public device_usb_ohci_function_interface
502 {
503 public:
504 	ohci_game_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
505 	void initialize() override;
506 	int handle_nonstandard_request(int endpoint, USBSetupPacket *setup) override;
507 	int handle_interrupt_pid(int endpoint, int pid, uint8_t *buffer, int size) override;
508 
509 protected:
510 	virtual void device_start() override;
511 	virtual ioport_constructor device_input_ports() const override;
512 private:
513 	static const USBStandardDeviceDescriptor devdesc;
514 	static const USBStandardConfigurationDescriptor condesc;
515 	static const USBStandardInterfaceDescriptor intdesc;
516 	static const USBStandardEndpointDescriptor enddesc82;
517 	static const USBStandardEndpointDescriptor enddesc02;
518 	required_ioport m_ThumbstickLh; // left analog thumbstick horizontal movement
519 	required_ioport m_ThumbstickLv; // left analog thumbstick vertical movement
520 	required_ioport m_ThumbstickRh; // right analog thumbstick horizontal movement
521 	required_ioport m_ThumbstickRv; // right analog thumbstick vertical movement
522 	required_ioport m_DPad; // pressure sensitive directional pad
523 	required_ioport m_TriggerL; // analog trigger
524 	required_ioport m_TriggerR; // analog trigger
525 	required_ioport m_Buttons; // digital buttons
526 	required_ioport m_AGreen; // analog button
527 	required_ioport m_BRed; // analog button
528 	required_ioport m_XBlue; // analog button
529 	required_ioport m_YYellow; // analog button
530 	required_ioport m_Black; // analog button
531 	required_ioport m_White; // analog button
532 };
533 
534 #endif // MAME_INCLUDES_XBOX_USB_H
535