]> git.gir.st - tmk_keyboard.git/blob - tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp
ps2_usb: Fix for VUSB configuration
[tmk_keyboard.git] / tmk_core / protocol / usb_hid / USB_Host_Shield_2.0 / XBOXRECV.cpp
1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9
10 Contact information
11 -------------------
12
13 Kristian Lauszus, TKJ Electronics
14 Web : http://www.tkjelectronics.com
15 e-mail : kristianl@tkjelectronics.com
16
17 getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net
18 */
19
20 #include "XBOXRECV.h"
21 // To enable serial debugging see "settings.h"
22 //#define EXTRADEBUG // Uncomment to get even more debugging data
23 //#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller
24
25 XBOXRECV::XBOXRECV(USB *p) :
26 pUsb(p), // pointer to USB class instance - mandatory
27 bAddress(0), // device address - mandatory
28 bPollEnable(false) { // don't start polling before dongle is connected
29 for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
30 epInfo[i].epAddr = 0;
31 epInfo[i].maxPktSize = (i) ? 0 : 8;
32 epInfo[i].epAttribs = 0;
33 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
34 }
35
36 if(pUsb) // register in USB subsystem
37 pUsb->RegisterDeviceClass(this); //set devConfig[] entry
38 }
39
40 uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
41 const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
42 uint8_t buf[constBufSize];
43 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
44 uint8_t rcode;
45 UsbDevice *p = NULL;
46 EpInfo *oldep_ptr = NULL;
47 uint16_t PID, VID;
48
49 AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool
50 #ifdef EXTRADEBUG
51 Notify(PSTR("\r\nXBOXRECV Init"), 0x80);
52 #endif
53
54 if(bAddress) { // Check if address has already been assigned to an instance
55 #ifdef DEBUG_USB_HOST
56 Notify(PSTR("\r\nAddress in use"), 0x80);
57 #endif
58 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
59 }
60
61 p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned
62
63 if(!p) {
64 #ifdef DEBUG_USB_HOST
65 Notify(PSTR("\r\nAddress not found"), 0x80);
66 #endif
67 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
68 }
69
70 if(!p->epinfo) {
71 #ifdef DEBUG_USB_HOST
72 Notify(PSTR("\r\nepinfo is null"), 0x80);
73 #endif
74 return USB_ERROR_EPINFO_IS_NULL;
75 }
76
77 oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0
78 p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
79 p->lowspeed = lowspeed;
80
81 rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
82
83 p->epinfo = oldep_ptr; // Restore p->epinfo
84
85 if(rcode)
86 goto FailGetDevDescr;
87
88 VID = udd->idVendor;
89 PID = udd->idProduct;
90
91 if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)) { // Check if it's a Xbox receiver using the Vendor ID and Product ID
92 #ifdef DEBUG_USB_HOST
93 Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80);
94 #endif
95 goto FailUnknownDevice;
96 }
97
98 bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class
99
100 if(!bAddress) {
101 #ifdef DEBUG_USB_HOST
102 Notify(PSTR("\r\nOut of address space"), 0x80);
103 #endif
104 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
105 }
106
107 epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor
108
109 delay(20); // Wait a little before resetting device
110
111 return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
112
113 /* Diagnostic messages */
114 FailGetDevDescr:
115 #ifdef DEBUG_USB_HOST
116 NotifyFailGetDevDescr(rcode);
117 #endif
118 if(rcode != hrJERR)
119 rcode = USB_ERROR_FailGetDevDescr;
120 goto Fail;
121
122 FailUnknownDevice:
123 #ifdef DEBUG_USB_HOST
124 NotifyFailUnknownDevice(VID, PID);
125 #endif
126 rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
127
128 Fail:
129 #ifdef DEBUG_USB_HOST
130 Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80);
131 NotifyFail(rcode);
132 #endif
133 Release();
134 return rcode;
135 };
136
137 uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) {
138 uint8_t rcode;
139
140 AddressPool &addrPool = pUsb->GetAddressPool();
141 #ifdef EXTRADEBUG
142 Notify(PSTR("\r\nBTD Init"), 0x80);
143 #endif
144 UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
145
146 if(!p) {
147 #ifdef DEBUG_USB_HOST
148 Notify(PSTR("\r\nAddress not found"), 0x80);
149 #endif
150 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
151 }
152
153 delay(300); // Assign new address to the device
154
155 rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device
156 if(rcode) {
157 #ifdef DEBUG_USB_HOST
158 Notify(PSTR("\r\nsetAddr: "), 0x80);
159 D_PrintHex<uint8_t > (rcode, 0x80);
160 #endif
161 p->lowspeed = false;
162 goto Fail;
163 }
164 #ifdef EXTRADEBUG
165 Notify(PSTR("\r\nAddr: "), 0x80);
166 D_PrintHex<uint8_t > (bAddress, 0x80);
167 #endif
168
169 p->lowspeed = false;
170
171 p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
172 if(!p) {
173 #ifdef DEBUG_USB_HOST
174 Notify(PSTR("\r\nAddress not found"), 0x80);
175 #endif
176 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
177 }
178
179 p->lowspeed = lowspeed;
180
181 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known
182 if(rcode)
183 goto FailSetDevTblEntry;
184
185 /* The application will work in reduced host mode, so we can save program and data
186 memory space. After verifying the VID we will use known values for the
187 configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */
188
189 /* Initialize data structures for endpoints of device */
190 epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms
191 epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
192 epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
193 epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE;
194 epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = 0;
195 epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = 0;
196 epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms
197 epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
198 epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
199 epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE;
200 epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = 0;
201 epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = 0;
202
203 epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms
204 epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
205 epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
206 epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE;
207 epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = 0;
208 epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = 0;
209 epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms
210 epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
211 epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
212 epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE;
213 epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = 0;
214 epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = 0;
215
216 epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms
217 epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
218 epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
219 epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE;
220 epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = 0;
221 epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = 0;
222 epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms
223 epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
224 epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
225 epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE;
226 epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = 0;
227 epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = 0;
228
229 epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms
230 epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
231 epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
232 epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE;
233 epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = 0;
234 epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = 0;
235 epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms
236 epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
237 epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
238 epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE;
239 epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = 0;
240 epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = 0;
241
242 rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo);
243 if(rcode)
244 goto FailSetDevTblEntry;
245
246 delay(200); //Give time for address change
247
248 rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
249 if(rcode)
250 goto FailSetConfDescr;
251
252 #ifdef DEBUG_USB_HOST
253 Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80);
254 #endif
255 XboxReceiverConnected = true;
256 bPollEnable = true;
257 checkStatusTimer = 0; // Reset timer
258 return 0; // Successful configuration
259
260 /* Diagnostic messages */
261 FailSetDevTblEntry:
262 #ifdef DEBUG_USB_HOST
263 NotifyFailSetDevTblEntry();
264 goto Fail;
265 #endif
266
267 FailSetConfDescr:
268 #ifdef DEBUG_USB_HOST
269 NotifyFailSetConfDescr();
270 #endif
271
272 Fail:
273 #ifdef DEBUG_USB_HOST
274 Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80);
275 NotifyFail(rcode);
276 #endif
277 Release();
278 return rcode;
279 }
280
281 /* Performs a cleanup after failed Init() attempt */
282 uint8_t XBOXRECV::Release() {
283 XboxReceiverConnected = false;
284 for(uint8_t i = 0; i < 4; i++)
285 Xbox360Connected[i] = 0x00;
286 pUsb->GetAddressPool().FreeAddress(bAddress);
287 bAddress = 0;
288 bPollEnable = false;
289 return 0;
290 }
291
292 uint8_t XBOXRECV::Poll() {
293 if(!bPollEnable)
294 return 0;
295 if(!checkStatusTimer || ((millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds
296 checkStatusTimer = millis();
297 checkStatus();
298 }
299
300 uint8_t inputPipe;
301 uint16_t bufferSize;
302 for(uint8_t i = 0; i < 4; i++) {
303 if(i == 0)
304 inputPipe = XBOX_INPUT_PIPE_1;
305 else if(i == 1)
306 inputPipe = XBOX_INPUT_PIPE_2;
307 else if(i == 2)
308 inputPipe = XBOX_INPUT_PIPE_3;
309 else
310 inputPipe = XBOX_INPUT_PIPE_4;
311
312 bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive
313 pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf);
314 if(bufferSize > 0) { // The number of received bytes
315 #ifdef EXTRADEBUG
316 Notify(PSTR("Bytes Received: "), 0x80);
317 D_PrintHex<uint16_t > (bufferSize, 0x80);
318 Notify(PSTR("\r\n"), 0x80);
319 #endif
320 readReport(i);
321 #ifdef PRINTREPORT
322 printReport(i, bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
323 #endif
324 }
325 }
326 return 0;
327 }
328
329 void XBOXRECV::readReport(uint8_t controller) {
330 if(readBuf == NULL)
331 return;
332 // This report is send when a controller is connected and disconnected
333 if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) {
334 Xbox360Connected[controller] = readBuf[1];
335 #ifdef DEBUG_USB_HOST
336 Notify(PSTR("Controller "), 0x80);
337 Notify(controller, 0x80);
338 #endif
339 if(Xbox360Connected[controller]) {
340 #ifdef DEBUG_USB_HOST
341 const char* str = 0;
342 switch(readBuf[1]) {
343 case 0x80: str = PSTR(" as controller\r\n");
344 break;
345 case 0x40: str = PSTR(" as headset\r\n");
346 break;
347 case 0xC0: str = PSTR(" as controller+headset\r\n");
348 break;
349 }
350 Notify(PSTR(": connected"), 0x80);
351 Notify(str, 0x80);
352 #endif
353 onInit(controller);
354 }
355 #ifdef DEBUG_USB_HOST
356 else
357 Notify(PSTR(": disconnected\r\n"), 0x80);
358 #endif
359 return;
360 }
361 // Controller status report
362 if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) {
363 controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4];
364 return;
365 }
366 if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports
367 return;
368
369 // A controller must be connected if it's sending data
370 if(!Xbox360Connected[controller])
371 Xbox360Connected[controller] |= 0x80;
372
373 ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24));
374
375 hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
376 hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
377 hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);
378 hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);
379
380 //Notify(PSTR("\r\nButtonState: "), 0x80);
381 //PrintHex<uint32_t>(ButtonState[controller], 0x80);
382
383 if(ButtonState[controller] != OldButtonState[controller]) {
384 buttonStateChanged[controller] = true;
385 ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2
386 if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons
387 R2Clicked[controller] = true;
388 if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0)
389 L2Clicked[controller] = true;
390 OldButtonState[controller] = ButtonState[controller];
391 }
392 }
393
394 void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
395 #ifdef PRINTREPORT
396 if(readBuf == NULL)
397 return;
398 Notify(PSTR("Controller "), 0x80);
399 Notify(controller, 0x80);
400 Notify(PSTR(": "), 0x80);
401 for(uint8_t i = 0; i < nBytes; i++) {
402 D_PrintHex<uint8_t > (readBuf[i], 0x80);
403 Notify(PSTR(" "), 0x80);
404 }
405 Notify(PSTR("\r\n"), 0x80);
406 #endif
407 }
408
409 uint8_t XBOXRECV::getButtonPress(ButtonEnum b, uint8_t controller) {
410 if(b == L2) // These are analog buttons
411 return (uint8_t)(ButtonState[controller] >> 8);
412 else if(b == R2)
413 return (uint8_t)ButtonState[controller];
414 return (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16));
415 }
416
417 bool XBOXRECV::getButtonClick(ButtonEnum b, uint8_t controller) {
418 if(b == L2) {
419 if(L2Clicked[controller]) {
420 L2Clicked[controller] = false;
421 return true;
422 }
423 return false;
424 } else if(b == R2) {
425 if(R2Clicked[controller]) {
426 R2Clicked[controller] = false;
427 return true;
428 }
429 return false;
430 }
431 uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);
432 bool click = (ButtonClickState[controller] & button);
433 ButtonClickState[controller] &= ~button; // clear "click" event
434 return click;
435 }
436
437 int16_t XBOXRECV::getAnalogHat(AnalogHatEnum a, uint8_t controller) {
438 return hatValue[controller][a];
439 }
440
441 bool XBOXRECV::buttonChanged(uint8_t controller) {
442 bool state = buttonStateChanged[controller];
443 buttonStateChanged[controller] = false;
444 return state;
445 }
446
447 /*
448 ControllerStatus Breakdown
449 ControllerStatus[controller] & 0x0001 // 0
450 ControllerStatus[controller] & 0x0002 // normal batteries, no rechargeable battery pack
451 ControllerStatus[controller] & 0x0004 // controller starting up / settling
452 ControllerStatus[controller] & 0x0008 // headset adapter plugged in, but no headphones connected (mute?)
453 ControllerStatus[controller] & 0x0010 // 0
454 ControllerStatus[controller] & 0x0020 // 1
455 ControllerStatus[controller] & 0x0040 // battery level (high bit)
456 ControllerStatus[controller] & 0x0080 // battery level (low bit)
457 ControllerStatus[controller] & 0x0100 // 1
458 ControllerStatus[controller] & 0x0200 // 1
459 ControllerStatus[controller] & 0x0400 // headset adapter plugged in
460 ControllerStatus[controller] & 0x0800 // 0
461 ControllerStatus[controller] & 0x1000 // 1
462 ControllerStatus[controller] & 0x2000 // 0
463 ControllerStatus[controller] & 0x4000 // 0
464 ControllerStatus[controller] & 0x8000 // 0
465 */
466 uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) {
467 return ((controllerStatus[controller] & 0x00C0) >> 6);
468 }
469
470 void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) {
471 #ifdef EXTRADEBUG
472 uint8_t rcode;
473 #endif
474 uint8_t outputPipe;
475 switch(controller) {
476 case 0: outputPipe = XBOX_OUTPUT_PIPE_1;
477 break;
478 case 1: outputPipe = XBOX_OUTPUT_PIPE_2;
479 break;
480 case 2: outputPipe = XBOX_OUTPUT_PIPE_3;
481 break;
482 case 3: outputPipe = XBOX_OUTPUT_PIPE_4;
483 break;
484 default:
485 return;
486 }
487 #ifdef EXTRADEBUG
488 rcode =
489 #endif
490 pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data);
491 #ifdef EXTRADEBUG
492 if(rcode)
493 Notify(PSTR("Error sending Xbox message\r\n"), 0x80);
494 #endif
495 }
496
497 void XBOXRECV::disconnect(uint8_t controller) {
498 writeBuf[0] = 0x00;
499 writeBuf[1] = 0x00;
500 writeBuf[2] = 0x08;
501 writeBuf[3] = 0xC0;
502
503 XboxCommand(controller, writeBuf, 4);
504 }
505
506 void XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) {
507 writeBuf[0] = 0x00;
508 writeBuf[1] = 0x00;
509 writeBuf[2] = 0x08;
510 writeBuf[3] = value | 0x40;
511
512 XboxCommand(controller, writeBuf, 4);
513 }
514
515 void XBOXRECV::setLedOn(LEDEnum led, uint8_t controller) {
516 if(led == OFF)
517 setLedRaw(0, controller);
518 else if(led != ALL) // All LEDs can't be on a the same time
519 setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4, controller);
520 }
521
522 void XBOXRECV::setLedBlink(LEDEnum led, uint8_t controller) {
523 setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]), controller);
524 }
525
526 void XBOXRECV::setLedMode(LEDModeEnum ledMode, uint8_t controller) { // This function is used to do some speciel LED stuff the controller supports
527 setLedRaw((uint8_t)ledMode, controller);
528 }
529
530 /* PC runs this at interval of approx 2 seconds
531 Thanks to BusHound from Perisoft.net for the Windows USB Analysis output
532 Found by timstamp.co.uk
533 */
534 void XBOXRECV::checkStatus() {
535 if(!bPollEnable)
536 return;
537 // Get controller info
538 writeBuf[0] = 0x08;
539 writeBuf[1] = 0x00;
540 writeBuf[2] = 0x0f;
541 writeBuf[3] = 0xc0;
542 for(uint8_t i = 0; i < 4; i++) {
543 XboxCommand(i, writeBuf, 4);
544 }
545 // Get battery status
546 writeBuf[0] = 0x00;
547 writeBuf[1] = 0x00;
548 writeBuf[2] = 0x00;
549 writeBuf[3] = 0x40;
550 for(uint8_t i = 0; i < 4; i++) {
551 if(Xbox360Connected[i])
552 XboxCommand(i, writeBuf, 4);
553 }
554 }
555
556 void XBOXRECV::setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller) {
557 writeBuf[0] = 0x00;
558 writeBuf[1] = 0x01;
559 writeBuf[2] = 0x0f;
560 writeBuf[3] = 0xc0;
561 writeBuf[4] = 0x00;
562 writeBuf[5] = lValue; // big weight
563 writeBuf[6] = rValue; // small weight
564
565 XboxCommand(controller, writeBuf, 7);
566 }
567
568 void XBOXRECV::onInit(uint8_t controller) {
569 if(pFuncOnInit)
570 pFuncOnInit(); // Call the user function
571 else {
572 LEDEnum led;
573 if(controller == 0)
574 led = LED1;
575 else if(controller == 1)
576 led = LED2;
577 else if(controller == 2)
578 led = LED3;
579 else
580 led = LED4;
581 setLedOn(led, controller);
582 }
583 }
Imprint / Impressum