Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UsbHostMAX3421E_Hello
XBOXRECV.cpp
00001 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. 00002 00003 This software may be distributed and modified under the terms of the GNU 00004 General Public License version 2 (GPL2) as published by the Free Software 00005 Foundation and appearing in the file GPL2.TXT included in the packaging of 00006 this file. Please note that GPL2 Section 2[b] requires that all works based 00007 on this software must also be made publicly available under the terms of 00008 the GPL2 ("Copyleft"). 00009 00010 Contact information 00011 ------------------- 00012 00013 Kristian Lauszus, TKJ Electronics 00014 Web : http://www.tkjelectronics.com 00015 e-mail : kristianl@tkjelectronics.com 00016 00017 getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net 00018 */ 00019 00020 #include "XBOXRECV.h" 00021 // To enable serial debugging see "settings.h" 00022 //#define EXTRADEBUG // Uncomment to get even more debugging data 00023 //#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller 00024 00025 XBOXRECV::XBOXRECV(Usb *p) : 00026 pUsb(p), // pointer to USB class instance - mandatory 00027 bAddress(0), // device address - mandatory 00028 bPollEnable(false) { // don't start polling before dongle is connected 00029 for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { 00030 epInfo[i].epAddr = 0; 00031 epInfo[i].maxPktSize = (i) ? 0 : 8; 00032 epInfo[i].bmSndToggle = 0; 00033 epInfo[i].bmRcvToggle = 0; 00034 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; 00035 } 00036 00037 if(pUsb) // register in USB subsystem 00038 pUsb->RegisterDeviceClass(this); //set devConfig[] entry 00039 } 00040 00041 uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) { 00042 const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); 00043 uint8_t buf[constBufSize]; 00044 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf); 00045 uint8_t rcode; 00046 UsbDevice *p = NULL; 00047 EpInfo *oldep_ptr = NULL; 00048 uint16_t PID, VID; 00049 00050 AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool 00051 #ifdef EXTRADEBUG 00052 Notify(PSTR("\r\nXBOXRECV Init"), 0x80); 00053 #endif 00054 00055 if(bAddress) { // Check if address has already been assigned to an instance 00056 #ifdef DEBUG_USB_HOST 00057 Notify(PSTR("\r\nAddress in use"), 0x80); 00058 #endif 00059 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; 00060 } 00061 00062 p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned 00063 00064 if(!p) { 00065 #ifdef DEBUG_USB_HOST 00066 Notify(PSTR("\r\nAddress not found"), 0x80); 00067 #endif 00068 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00069 } 00070 00071 if(!p->epinfo) { 00072 #ifdef DEBUG_USB_HOST 00073 Notify(PSTR("\r\nepinfo is null"), 0x80); 00074 #endif 00075 return USB_ERROR_EPINFO_IS_NULL; 00076 } 00077 00078 oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0 00079 p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence 00080 p->lowspeed = lowspeed; 00081 00082 rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data 00083 00084 p->epinfo = oldep_ptr; // Restore p->epinfo 00085 00086 if(rcode) 00087 goto FailGetDevDescr; 00088 00089 VID = udd->idVendor; 00090 PID = udd->idProduct; 00091 00092 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 00093 #ifdef DEBUG_USB_HOST 00094 Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80); 00095 #endif 00096 goto FailUnknownDevice; 00097 } 00098 00099 bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class 00100 00101 if(!bAddress) { 00102 #ifdef DEBUG_USB_HOST 00103 Notify(PSTR("\r\nOut of address space"), 0x80); 00104 #endif 00105 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; 00106 } 00107 00108 epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor 00109 00110 wait_ms(20); // Wait a little before resetting device 00111 00112 return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET; 00113 00114 /* Diagnostic messages */ 00115 FailGetDevDescr: 00116 #ifdef DEBUG_USB_HOST 00117 NotifyFailGetDevDescr(rcode); 00118 #endif 00119 if(rcode != hrJERR) 00120 rcode = USB_ERROR_FailGetDevDescr; 00121 goto Fail; 00122 00123 FailUnknownDevice: 00124 #ifdef DEBUG_USB_HOST 00125 NotifyFailUnknownDevice(VID, PID); 00126 #endif 00127 rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; 00128 00129 Fail: 00130 #ifdef DEBUG_USB_HOST 00131 Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); 00132 NotifyFail(rcode); 00133 #endif 00134 Release(); 00135 return rcode; 00136 }; 00137 00138 uint8_t XBOXRECV::Init(uint8_t parent __attribute__((unused)), uint8_t port __attribute__((unused)), bool lowspeed) { 00139 uint8_t rcode; 00140 00141 AddressPool &addrPool = pUsb->GetAddressPool(); 00142 #ifdef EXTRADEBUG 00143 Notify(PSTR("\r\nBTD Init"), 0x80); 00144 #endif 00145 UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record 00146 00147 if(!p) { 00148 #ifdef DEBUG_USB_HOST 00149 Notify(PSTR("\r\nAddress not found"), 0x80); 00150 #endif 00151 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00152 } 00153 00154 wait_ms(300); // Assign new address to the device 00155 00156 rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device 00157 if(rcode) { 00158 #ifdef DEBUG_USB_HOST 00159 Notify(PSTR("\r\nsetAddr: "), 0x80); 00160 D_PrintHex<uint8_t > (rcode, 0x80); 00161 #endif 00162 p->lowspeed = false; 00163 goto Fail; 00164 } 00165 #ifdef EXTRADEBUG 00166 Notify(PSTR("\r\nAddr: "), 0x80); 00167 D_PrintHex<uint8_t > (bAddress, 0x80); 00168 #endif 00169 00170 p->lowspeed = false; 00171 00172 p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record 00173 if(!p) { 00174 #ifdef DEBUG_USB_HOST 00175 Notify(PSTR("\r\nAddress not found"), 0x80); 00176 #endif 00177 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00178 } 00179 00180 p->lowspeed = lowspeed; 00181 00182 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known 00183 if(rcode) 00184 goto FailSetDevTblEntry; 00185 00186 /* The application will work in reduced host mode, so we can save program and data 00187 memory space. After verifying the VID we will use known values for the 00188 configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */ 00189 00190 /* Initialize data structures for endpoints of device */ 00191 epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms 00192 epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00193 epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00194 epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; 00195 epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = 0; 00196 epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = 0; 00197 epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms 00198 epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00199 epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00200 epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; 00201 epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = 0; 00202 epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = 0; 00203 00204 epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms 00205 epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00206 epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00207 epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; 00208 epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = 0; 00209 epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = 0; 00210 epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms 00211 epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00212 epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00213 epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; 00214 epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = 0; 00215 epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = 0; 00216 00217 epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms 00218 epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00219 epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00220 epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; 00221 epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = 0; 00222 epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = 0; 00223 epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms 00224 epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00225 epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00226 epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; 00227 epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = 0; 00228 epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = 0; 00229 00230 epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms 00231 epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00232 epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00233 epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; 00234 epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = 0; 00235 epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = 0; 00236 epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms 00237 epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00238 epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00239 epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; 00240 epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = 0; 00241 epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = 0; 00242 00243 rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo); 00244 if(rcode) 00245 goto FailSetDevTblEntry; 00246 00247 wait_ms(200); //Give time for address change 00248 00249 rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); 00250 if(rcode) 00251 goto FailSetConfDescr; 00252 00253 #ifdef DEBUG_USB_HOST 00254 Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80); 00255 #endif 00256 XboxReceiverConnected = true; 00257 bPollEnable = true; 00258 checkStatusTimer = 0; // Reset timer 00259 return 0; // Successful configuration 00260 00261 /* Diagnostic messages */ 00262 FailSetDevTblEntry: 00263 #ifdef DEBUG_USB_HOST 00264 NotifyFailSetDevTblEntry(); 00265 goto Fail; 00266 #endif 00267 00268 FailSetConfDescr: 00269 #ifdef DEBUG_USB_HOST 00270 NotifyFailSetConfDescr(); 00271 #endif 00272 00273 Fail: 00274 #ifdef DEBUG_USB_HOST 00275 Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); 00276 NotifyFail(rcode); 00277 #endif 00278 Release(); 00279 return rcode; 00280 } 00281 00282 /* Performs a cleanup after failed Init() attempt */ 00283 uint8_t XBOXRECV::Release() { 00284 XboxReceiverConnected = false; 00285 for(uint8_t i = 0; i < 4; i++) 00286 Xbox360Connected[i] = 0x00; 00287 pUsb->GetAddressPool().FreeAddress(bAddress); 00288 bAddress = 0; 00289 bPollEnable = false; 00290 return 0; 00291 } 00292 00293 uint8_t XBOXRECV::Poll() { 00294 if(!bPollEnable) 00295 return 0; 00296 if(!checkStatusTimer || ((int32_t)((uint32_t)millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds 00297 checkStatusTimer = (uint32_t)millis(); 00298 checkStatus(); 00299 } 00300 00301 uint8_t inputPipe; 00302 uint16_t bufferSize; 00303 for(uint8_t i = 0; i < 4; i++) { 00304 if(i == 0) 00305 inputPipe = XBOX_INPUT_PIPE_1; 00306 else if(i == 1) 00307 inputPipe = XBOX_INPUT_PIPE_2; 00308 else if(i == 2) 00309 inputPipe = XBOX_INPUT_PIPE_3; 00310 else 00311 inputPipe = XBOX_INPUT_PIPE_4; 00312 00313 bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive 00314 pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf); 00315 if(bufferSize > 0) { // The number of received bytes 00316 #ifdef EXTRADEBUG 00317 Notify(PSTR("Bytes Received: "), 0x80); 00318 D_PrintHex<uint16_t > (bufferSize, 0x80); 00319 Notify(PSTR("\r\n"), 0x80); 00320 #endif 00321 readReport(i); 00322 #ifdef PRINTREPORT 00323 printReport(i, bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller 00324 #endif 00325 } 00326 } 00327 return 0; 00328 } 00329 00330 void XBOXRECV::readReport(uint8_t controller) { 00331 if(readBuf == NULL) 00332 return; 00333 // This report is send when a controller is connected and disconnected 00334 if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) { 00335 Xbox360Connected[controller] = readBuf[1]; 00336 #ifdef DEBUG_USB_HOST 00337 Notify(PSTR("Controller "), 0x80); 00338 Notify(controller, 0x80); 00339 #endif 00340 if(Xbox360Connected[controller]) { 00341 #ifdef DEBUG_USB_HOST 00342 const char* str = 0; 00343 switch(readBuf[1]) { 00344 case 0x80: str = PSTR(" as controller\r\n"); 00345 break; 00346 case 0x40: str = PSTR(" as headset\r\n"); 00347 break; 00348 case 0xC0: str = PSTR(" as controller+headset\r\n"); 00349 break; 00350 } 00351 Notify(PSTR(": connected"), 0x80); 00352 Notify(str, 0x80); 00353 #endif 00354 onInit(controller); 00355 } 00356 #ifdef DEBUG_USB_HOST 00357 else 00358 Notify(PSTR(": disconnected\r\n"), 0x80); 00359 #endif 00360 return; 00361 } 00362 // Controller status report 00363 if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) { 00364 controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4]; 00365 return; 00366 } 00367 if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports 00368 return; 00369 00370 // A controller must be connected if it's sending data 00371 if(!Xbox360Connected[controller]) 00372 Xbox360Connected[controller] |= 0x80; 00373 00374 ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24)); 00375 00376 hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); 00377 hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); 00378 hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); 00379 hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); 00380 00381 //Notify(PSTR("\r\nButtonState: "), 0x80); 00382 //PrintHex<uint32_t>(ButtonState[controller], 0x80); 00383 00384 if(ButtonState[controller] != OldButtonState[controller]) { 00385 buttonStateChanged[controller] = true; 00386 ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 00387 if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons 00388 R2Clicked[controller] = true; 00389 if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0) 00390 L2Clicked[controller] = true; 00391 OldButtonState[controller] = ButtonState[controller]; 00392 } 00393 } 00394 00395 void XBOXRECV::printReport(uint8_t controller __attribute__((unused)), uint8_t nBytes __attribute__((unused))) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller 00396 #ifdef PRINTREPORT 00397 if(readBuf == NULL) 00398 return; 00399 Notify(PSTR("Controller "), 0x80); 00400 Notify(controller, 0x80); 00401 Notify(PSTR(": "), 0x80); 00402 for(uint8_t i = 0; i < nBytes; i++) { 00403 D_PrintHex<uint8_t > (readBuf[i], 0x80); 00404 Notify(PSTR(" "), 0x80); 00405 } 00406 Notify(PSTR("\r\n"), 0x80); 00407 #endif 00408 } 00409 00410 uint8_t XBOXRECV::getButtonPress(ButtonEnum b, uint8_t controller) { 00411 if(b == L2) // These are analog buttons 00412 return (uint8_t)(ButtonState[controller] >> 8); 00413 else if(b == R2) 00414 return (uint8_t)ButtonState[controller]; 00415 return (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16)); 00416 } 00417 00418 bool XBOXRECV::getButtonClick(ButtonEnum b, uint8_t controller) { 00419 if(b == L2) { 00420 if(L2Clicked[controller]) { 00421 L2Clicked[controller] = false; 00422 return true; 00423 } 00424 return false; 00425 } else if(b == R2) { 00426 if(R2Clicked[controller]) { 00427 R2Clicked[controller] = false; 00428 return true; 00429 } 00430 return false; 00431 } 00432 uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]); 00433 bool click = (ButtonClickState[controller] & button); 00434 ButtonClickState[controller] &= ~button; // clear "click" event 00435 return click; 00436 } 00437 00438 int16_t XBOXRECV::getAnalogHat(AnalogHatEnum a, uint8_t controller) { 00439 return hatValue[controller][a]; 00440 } 00441 00442 bool XBOXRECV::buttonChanged(uint8_t controller) { 00443 bool state = buttonStateChanged[controller]; 00444 buttonStateChanged[controller] = false; 00445 return state; 00446 } 00447 00448 /* 00449 ControllerStatus Breakdown 00450 ControllerStatus[controller] & 0x0001 // 0 00451 ControllerStatus[controller] & 0x0002 // normal batteries, no rechargeable battery pack 00452 ControllerStatus[controller] & 0x0004 // controller starting up / settling 00453 ControllerStatus[controller] & 0x0008 // headset adapter plugged in, but no headphones connected (mute?) 00454 ControllerStatus[controller] & 0x0010 // 0 00455 ControllerStatus[controller] & 0x0020 // 1 00456 ControllerStatus[controller] & 0x0040 // battery level (high bit) 00457 ControllerStatus[controller] & 0x0080 // battery level (low bit) 00458 ControllerStatus[controller] & 0x0100 // 1 00459 ControllerStatus[controller] & 0x0200 // 1 00460 ControllerStatus[controller] & 0x0400 // headset adapter plugged in 00461 ControllerStatus[controller] & 0x0800 // 0 00462 ControllerStatus[controller] & 0x1000 // 1 00463 ControllerStatus[controller] & 0x2000 // 0 00464 ControllerStatus[controller] & 0x4000 // 0 00465 ControllerStatus[controller] & 0x8000 // 0 00466 */ 00467 uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) { 00468 return ((controllerStatus[controller] & 0x00C0) >> 6); 00469 } 00470 00471 void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) { 00472 #ifdef EXTRADEBUG 00473 uint8_t rcode; 00474 #endif 00475 uint8_t outputPipe; 00476 switch(controller) { 00477 case 0: outputPipe = XBOX_OUTPUT_PIPE_1; 00478 break; 00479 case 1: outputPipe = XBOX_OUTPUT_PIPE_2; 00480 break; 00481 case 2: outputPipe = XBOX_OUTPUT_PIPE_3; 00482 break; 00483 case 3: outputPipe = XBOX_OUTPUT_PIPE_4; 00484 break; 00485 default: 00486 return; 00487 } 00488 #ifdef EXTRADEBUG 00489 rcode = 00490 #endif 00491 pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data); 00492 #ifdef EXTRADEBUG 00493 if(rcode) 00494 Notify(PSTR("Error sending Xbox message\r\n"), 0x80); 00495 #endif 00496 } 00497 00498 void XBOXRECV::disconnect(uint8_t controller) { 00499 writeBuf[0] = 0x00; 00500 writeBuf[1] = 0x00; 00501 writeBuf[2] = 0x08; 00502 writeBuf[3] = 0xC0; 00503 00504 XboxCommand(controller, writeBuf, 4); 00505 } 00506 00507 void XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) { 00508 writeBuf[0] = 0x00; 00509 writeBuf[1] = 0x00; 00510 writeBuf[2] = 0x08; 00511 writeBuf[3] = value | 0x40; 00512 00513 XboxCommand(controller, writeBuf, 4); 00514 } 00515 00516 void XBOXRECV::setLedOn(LEDEnum led, uint8_t controller) { 00517 if(led == OFF) 00518 setLedRaw(0, controller); 00519 else if(led != ALL) // All LEDs can't be on a the same time 00520 setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4, controller); 00521 } 00522 00523 void XBOXRECV::setLedBlink(LEDEnum led, uint8_t controller) { 00524 setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]), controller); 00525 } 00526 00527 void XBOXRECV::setLedMode(LEDModeEnum ledMode, uint8_t controller) { // This function is used to do some speciel LED stuff the controller supports 00528 setLedRaw((uint8_t)ledMode, controller); 00529 } 00530 00531 /* PC runs this at interval of approx 2 seconds 00532 Thanks to BusHound from Perisoft.net for the Windows USB Analysis output 00533 Found by timstamp.co.uk 00534 */ 00535 void XBOXRECV::checkStatus() { 00536 if(!bPollEnable) 00537 return; 00538 // Get controller info 00539 writeBuf[0] = 0x08; 00540 writeBuf[1] = 0x00; 00541 writeBuf[2] = 0x0f; 00542 writeBuf[3] = 0xc0; 00543 for(uint8_t i = 0; i < 4; i++) { 00544 XboxCommand(i, writeBuf, 4); 00545 } 00546 // Get battery status 00547 writeBuf[0] = 0x00; 00548 writeBuf[1] = 0x00; 00549 writeBuf[2] = 0x00; 00550 writeBuf[3] = 0x40; 00551 for(uint8_t i = 0; i < 4; i++) { 00552 if(Xbox360Connected[i]) 00553 XboxCommand(i, writeBuf, 4); 00554 } 00555 } 00556 00557 void XBOXRECV::setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller) { 00558 writeBuf[0] = 0x00; 00559 writeBuf[1] = 0x01; 00560 writeBuf[2] = 0x0f; 00561 writeBuf[3] = 0xc0; 00562 writeBuf[4] = 0x00; 00563 writeBuf[5] = lValue; // big weight 00564 writeBuf[6] = rValue; // small weight 00565 00566 XboxCommand(controller, writeBuf, 7); 00567 } 00568 00569 void XBOXRECV::onInit(uint8_t controller) { 00570 if(pFuncOnInit) 00571 pFuncOnInit(); // Call the user function 00572 else { 00573 LEDEnum led; 00574 if(controller == 0) 00575 led = static_cast<LEDEnum>(LED1); 00576 else if(controller == 1) 00577 led = static_cast<LEDEnum>(LED2); 00578 else if(controller == 2) 00579 led = static_cast<LEDEnum>(LED3); 00580 else 00581 led = static_cast<LEDEnum>(LED4); 00582 setLedOn(led, controller); 00583 } 00584 }
Generated on Tue Jul 12 2022 18:12:05 by
1.7.2