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