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
XBOXUSB.cpp@0:84353c479782, 2020-07-12 (annotated)
- Committer:
- hudakz
- Date:
- Sun Jul 12 20:39:26 2020 +0000
- Revision:
- 0:84353c479782
- Child:
- 1:2263e77400e9
MAX3421E-based USB Host Shield Library
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hudakz | 0:84353c479782 | 1 | /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. |
hudakz | 0:84353c479782 | 2 | |
hudakz | 0:84353c479782 | 3 | This software may be distributed and modified under the terms of the GNU |
hudakz | 0:84353c479782 | 4 | General Public License version 2 (GPL2) as published by the Free Software |
hudakz | 0:84353c479782 | 5 | Foundation and appearing in the file GPL2.TXT included in the packaging of |
hudakz | 0:84353c479782 | 6 | this file. Please note that GPL2 Section 2[b] requires that all works based |
hudakz | 0:84353c479782 | 7 | on this software must also be made publicly available under the terms of |
hudakz | 0:84353c479782 | 8 | the GPL2 ("Copyleft"). |
hudakz | 0:84353c479782 | 9 | |
hudakz | 0:84353c479782 | 10 | Contact information |
hudakz | 0:84353c479782 | 11 | ------------------- |
hudakz | 0:84353c479782 | 12 | |
hudakz | 0:84353c479782 | 13 | Kristian Lauszus, TKJ Electronics |
hudakz | 0:84353c479782 | 14 | Web : http://www.tkjelectronics.com |
hudakz | 0:84353c479782 | 15 | e-mail : kristianl@tkjelectronics.com |
hudakz | 0:84353c479782 | 16 | */ |
hudakz | 0:84353c479782 | 17 | |
hudakz | 0:84353c479782 | 18 | #include "XBOXUSB.h" |
hudakz | 0:84353c479782 | 19 | // To enable serial debugging see "settings.h" |
hudakz | 0:84353c479782 | 20 | //#define EXTRADEBUG // Uncomment to get even more debugging data |
hudakz | 0:84353c479782 | 21 | //#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller |
hudakz | 0:84353c479782 | 22 | |
hudakz | 0:84353c479782 | 23 | XBOXUSB::XBOXUSB(USB *p) : |
hudakz | 0:84353c479782 | 24 | pUsb(p), // pointer to USB class instance - mandatory |
hudakz | 0:84353c479782 | 25 | bAddress(0), // device address - mandatory |
hudakz | 0:84353c479782 | 26 | bPollEnable(false) { // don't start polling before dongle is connected |
hudakz | 0:84353c479782 | 27 | for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) { |
hudakz | 0:84353c479782 | 28 | epInfo[i].epAddr = 0; |
hudakz | 0:84353c479782 | 29 | epInfo[i].maxPktSize = (i) ? 0 : 8; |
hudakz | 0:84353c479782 | 30 | epInfo[i].bmSndToggle = 0; |
hudakz | 0:84353c479782 | 31 | epInfo[i].bmRcvToggle = 0; |
hudakz | 0:84353c479782 | 32 | epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; |
hudakz | 0:84353c479782 | 33 | } |
hudakz | 0:84353c479782 | 34 | |
hudakz | 0:84353c479782 | 35 | if(pUsb) // register in USB subsystem |
hudakz | 0:84353c479782 | 36 | pUsb->RegisterDeviceClass(this); //set devConfig[] entry |
hudakz | 0:84353c479782 | 37 | } |
hudakz | 0:84353c479782 | 38 | |
hudakz | 0:84353c479782 | 39 | uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { |
hudakz | 0:84353c479782 | 40 | uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; |
hudakz | 0:84353c479782 | 41 | USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf); |
hudakz | 0:84353c479782 | 42 | uint8_t rcode; |
hudakz | 0:84353c479782 | 43 | UsbDevice *p = NULL; |
hudakz | 0:84353c479782 | 44 | EpInfo *oldep_ptr = NULL; |
hudakz | 0:84353c479782 | 45 | uint16_t PID; |
hudakz | 0:84353c479782 | 46 | uint16_t VID; |
hudakz | 0:84353c479782 | 47 | |
hudakz | 0:84353c479782 | 48 | // get memory address of USB device address pool |
hudakz | 0:84353c479782 | 49 | AddressPool &addrPool = pUsb->GetAddressPool(); |
hudakz | 0:84353c479782 | 50 | #ifdef EXTRADEBUG |
hudakz | 0:84353c479782 | 51 | Notify(PSTR("\r\nXBOXUSB Init"), 0x80); |
hudakz | 0:84353c479782 | 52 | #endif |
hudakz | 0:84353c479782 | 53 | // check if address has already been assigned to an instance |
hudakz | 0:84353c479782 | 54 | if(bAddress) { |
hudakz | 0:84353c479782 | 55 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 56 | Notify(PSTR("\r\nAddress in use"), 0x80); |
hudakz | 0:84353c479782 | 57 | #endif |
hudakz | 0:84353c479782 | 58 | return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; |
hudakz | 0:84353c479782 | 59 | } |
hudakz | 0:84353c479782 | 60 | |
hudakz | 0:84353c479782 | 61 | // Get pointer to pseudo device with address 0 assigned |
hudakz | 0:84353c479782 | 62 | p = addrPool.GetUsbDevicePtr(0); |
hudakz | 0:84353c479782 | 63 | |
hudakz | 0:84353c479782 | 64 | if(!p) { |
hudakz | 0:84353c479782 | 65 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 66 | Notify(PSTR("\r\nAddress not found"), 0x80); |
hudakz | 0:84353c479782 | 67 | #endif |
hudakz | 0:84353c479782 | 68 | return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; |
hudakz | 0:84353c479782 | 69 | } |
hudakz | 0:84353c479782 | 70 | |
hudakz | 0:84353c479782 | 71 | if(!p->epinfo) { |
hudakz | 0:84353c479782 | 72 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 73 | Notify(PSTR("\r\nepinfo is null"), 0x80); |
hudakz | 0:84353c479782 | 74 | #endif |
hudakz | 0:84353c479782 | 75 | return USB_ERROR_EPINFO_IS_NULL; |
hudakz | 0:84353c479782 | 76 | } |
hudakz | 0:84353c479782 | 77 | |
hudakz | 0:84353c479782 | 78 | // Save old pointer to EP_RECORD of address 0 |
hudakz | 0:84353c479782 | 79 | oldep_ptr = p->epinfo; |
hudakz | 0:84353c479782 | 80 | |
hudakz | 0:84353c479782 | 81 | // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence |
hudakz | 0:84353c479782 | 82 | p->epinfo = epInfo; |
hudakz | 0:84353c479782 | 83 | |
hudakz | 0:84353c479782 | 84 | p->lowspeed = lowspeed; |
hudakz | 0:84353c479782 | 85 | |
hudakz | 0:84353c479782 | 86 | // Get device descriptor |
hudakz | 0:84353c479782 | 87 | rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data |
hudakz | 0:84353c479782 | 88 | // Restore p->epinfo |
hudakz | 0:84353c479782 | 89 | p->epinfo = oldep_ptr; |
hudakz | 0:84353c479782 | 90 | |
hudakz | 0:84353c479782 | 91 | if(rcode) |
hudakz | 0:84353c479782 | 92 | goto FailGetDevDescr; |
hudakz | 0:84353c479782 | 93 | |
hudakz | 0:84353c479782 | 94 | VID = udd->idVendor; |
hudakz | 0:84353c479782 | 95 | PID = udd->idProduct; |
hudakz | 0:84353c479782 | 96 | |
hudakz | 0:84353c479782 | 97 | if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID && VID != GAMESTOP_VID) // Check VID |
hudakz | 0:84353c479782 | 98 | goto FailUnknownDevice; |
hudakz | 0:84353c479782 | 99 | if(PID == XBOX_WIRELESS_PID) { |
hudakz | 0:84353c479782 | 100 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 101 | Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80); |
hudakz | 0:84353c479782 | 102 | #endif |
hudakz | 0:84353c479782 | 103 | goto FailUnknownDevice; |
hudakz | 0:84353c479782 | 104 | } else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { |
hudakz | 0:84353c479782 | 105 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 106 | Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80); |
hudakz | 0:84353c479782 | 107 | #endif |
hudakz | 0:84353c479782 | 108 | goto FailUnknownDevice; |
hudakz | 0:84353c479782 | 109 | } else if(PID != XBOX_WIRED_PID && PID != MADCATZ_WIRED_PID && PID != GAMESTOP_WIRED_PID && PID != AFTERGLOW_WIRED_PID && PID != JOYTECH_WIRED_PID) // Check PID |
hudakz | 0:84353c479782 | 110 | goto FailUnknownDevice; |
hudakz | 0:84353c479782 | 111 | |
hudakz | 0:84353c479782 | 112 | // Allocate new address according to device class |
hudakz | 0:84353c479782 | 113 | bAddress = addrPool.AllocAddress(parent, false, port); |
hudakz | 0:84353c479782 | 114 | |
hudakz | 0:84353c479782 | 115 | if(!bAddress) |
hudakz | 0:84353c479782 | 116 | return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; |
hudakz | 0:84353c479782 | 117 | |
hudakz | 0:84353c479782 | 118 | // Extract Max Packet Size from device descriptor |
hudakz | 0:84353c479782 | 119 | epInfo[0].maxPktSize = udd->bMaxPacketSize0; |
hudakz | 0:84353c479782 | 120 | |
hudakz | 0:84353c479782 | 121 | // Assign new address to the device |
hudakz | 0:84353c479782 | 122 | rcode = pUsb->setAddr(0, 0, bAddress); |
hudakz | 0:84353c479782 | 123 | if(rcode) { |
hudakz | 0:84353c479782 | 124 | p->lowspeed = false; |
hudakz | 0:84353c479782 | 125 | addrPool.FreeAddress(bAddress); |
hudakz | 0:84353c479782 | 126 | bAddress = 0; |
hudakz | 0:84353c479782 | 127 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 128 | Notify(PSTR("\r\nsetAddr: "), 0x80); |
hudakz | 0:84353c479782 | 129 | D_PrintHex<uint8_t > (rcode, 0x80); |
hudakz | 0:84353c479782 | 130 | #endif |
hudakz | 0:84353c479782 | 131 | return rcode; |
hudakz | 0:84353c479782 | 132 | } |
hudakz | 0:84353c479782 | 133 | #ifdef EXTRADEBUG |
hudakz | 0:84353c479782 | 134 | Notify(PSTR("\r\nAddr: "), 0x80); |
hudakz | 0:84353c479782 | 135 | D_PrintHex<uint8_t > (bAddress, 0x80); |
hudakz | 0:84353c479782 | 136 | #endif |
hudakz | 0:84353c479782 | 137 | //wait_ms(300); // Spec says you should wait at least 200ms |
hudakz | 0:84353c479782 | 138 | |
hudakz | 0:84353c479782 | 139 | p->lowspeed = false; |
hudakz | 0:84353c479782 | 140 | |
hudakz | 0:84353c479782 | 141 | //get pointer to assigned address record |
hudakz | 0:84353c479782 | 142 | p = addrPool.GetUsbDevicePtr(bAddress); |
hudakz | 0:84353c479782 | 143 | if(!p) |
hudakz | 0:84353c479782 | 144 | return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; |
hudakz | 0:84353c479782 | 145 | |
hudakz | 0:84353c479782 | 146 | p->lowspeed = lowspeed; |
hudakz | 0:84353c479782 | 147 | |
hudakz | 0:84353c479782 | 148 | // Assign epInfo to epinfo pointer - only EP0 is known |
hudakz | 0:84353c479782 | 149 | rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); |
hudakz | 0:84353c479782 | 150 | if(rcode) |
hudakz | 0:84353c479782 | 151 | goto FailSetDevTblEntry; |
hudakz | 0:84353c479782 | 152 | |
hudakz | 0:84353c479782 | 153 | /* The application will work in reduced host mode, so we can save program and data |
hudakz | 0:84353c479782 | 154 | memory space. After verifying the VID we will use known values for the |
hudakz | 0:84353c479782 | 155 | configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ |
hudakz | 0:84353c479782 | 156 | |
hudakz | 0:84353c479782 | 157 | /* Initialize data structures for endpoints of device */ |
hudakz | 0:84353c479782 | 158 | epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint |
hudakz | 0:84353c479782 | 159 | epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; |
hudakz | 0:84353c479782 | 160 | epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints |
hudakz | 0:84353c479782 | 161 | epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; |
hudakz | 0:84353c479782 | 162 | epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0; |
hudakz | 0:84353c479782 | 163 | epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0; |
hudakz | 0:84353c479782 | 164 | epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint |
hudakz | 0:84353c479782 | 165 | epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; |
hudakz | 0:84353c479782 | 166 | epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints |
hudakz | 0:84353c479782 | 167 | epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; |
hudakz | 0:84353c479782 | 168 | epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0; |
hudakz | 0:84353c479782 | 169 | epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0; |
hudakz | 0:84353c479782 | 170 | |
hudakz | 0:84353c479782 | 171 | rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); |
hudakz | 0:84353c479782 | 172 | if(rcode) |
hudakz | 0:84353c479782 | 173 | goto FailSetDevTblEntry; |
hudakz | 0:84353c479782 | 174 | |
hudakz | 0:84353c479782 | 175 | wait_ms(200); // Give time for address change |
hudakz | 0:84353c479782 | 176 | |
hudakz | 0:84353c479782 | 177 | rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); |
hudakz | 0:84353c479782 | 178 | if(rcode) |
hudakz | 0:84353c479782 | 179 | goto FailSetConfDescr; |
hudakz | 0:84353c479782 | 180 | |
hudakz | 0:84353c479782 | 181 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 182 | Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80); |
hudakz | 0:84353c479782 | 183 | #endif |
hudakz | 0:84353c479782 | 184 | onInit(); |
hudakz | 0:84353c479782 | 185 | Xbox360Connected = true; |
hudakz | 0:84353c479782 | 186 | bPollEnable = true; |
hudakz | 0:84353c479782 | 187 | return 0; // Successful configuration |
hudakz | 0:84353c479782 | 188 | |
hudakz | 0:84353c479782 | 189 | /* Diagnostic messages */ |
hudakz | 0:84353c479782 | 190 | FailGetDevDescr: |
hudakz | 0:84353c479782 | 191 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 192 | NotifyFailGetDevDescr(); |
hudakz | 0:84353c479782 | 193 | goto Fail; |
hudakz | 0:84353c479782 | 194 | #endif |
hudakz | 0:84353c479782 | 195 | |
hudakz | 0:84353c479782 | 196 | FailSetDevTblEntry: |
hudakz | 0:84353c479782 | 197 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 198 | NotifyFailSetDevTblEntry(); |
hudakz | 0:84353c479782 | 199 | goto Fail; |
hudakz | 0:84353c479782 | 200 | #endif |
hudakz | 0:84353c479782 | 201 | |
hudakz | 0:84353c479782 | 202 | FailSetConfDescr: |
hudakz | 0:84353c479782 | 203 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 204 | NotifyFailSetConfDescr(); |
hudakz | 0:84353c479782 | 205 | #endif |
hudakz | 0:84353c479782 | 206 | goto Fail; |
hudakz | 0:84353c479782 | 207 | |
hudakz | 0:84353c479782 | 208 | FailUnknownDevice: |
hudakz | 0:84353c479782 | 209 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 210 | NotifyFailUnknownDevice(VID, PID); |
hudakz | 0:84353c479782 | 211 | #endif |
hudakz | 0:84353c479782 | 212 | rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; |
hudakz | 0:84353c479782 | 213 | |
hudakz | 0:84353c479782 | 214 | Fail: |
hudakz | 0:84353c479782 | 215 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 216 | Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); |
hudakz | 0:84353c479782 | 217 | NotifyFail(rcode); |
hudakz | 0:84353c479782 | 218 | #endif |
hudakz | 0:84353c479782 | 219 | Release(); |
hudakz | 0:84353c479782 | 220 | return rcode; |
hudakz | 0:84353c479782 | 221 | } |
hudakz | 0:84353c479782 | 222 | |
hudakz | 0:84353c479782 | 223 | /* Performs a cleanup after failed Init() attempt */ |
hudakz | 0:84353c479782 | 224 | uint8_t XBOXUSB::Release() { |
hudakz | 0:84353c479782 | 225 | Xbox360Connected = false; |
hudakz | 0:84353c479782 | 226 | pUsb->GetAddressPool().FreeAddress(bAddress); |
hudakz | 0:84353c479782 | 227 | bAddress = 0; |
hudakz | 0:84353c479782 | 228 | bPollEnable = false; |
hudakz | 0:84353c479782 | 229 | return 0; |
hudakz | 0:84353c479782 | 230 | } |
hudakz | 0:84353c479782 | 231 | |
hudakz | 0:84353c479782 | 232 | uint8_t XBOXUSB::Poll() { |
hudakz | 0:84353c479782 | 233 | if(!bPollEnable) |
hudakz | 0:84353c479782 | 234 | return 0; |
hudakz | 0:84353c479782 | 235 | uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; |
hudakz | 0:84353c479782 | 236 | pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 |
hudakz | 0:84353c479782 | 237 | readReport(); |
hudakz | 0:84353c479782 | 238 | #ifdef PRINTREPORT |
hudakz | 0:84353c479782 | 239 | printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller |
hudakz | 0:84353c479782 | 240 | #endif |
hudakz | 0:84353c479782 | 241 | return 0; |
hudakz | 0:84353c479782 | 242 | } |
hudakz | 0:84353c479782 | 243 | |
hudakz | 0:84353c479782 | 244 | void XBOXUSB::readReport() { |
hudakz | 0:84353c479782 | 245 | if(readBuf == NULL) |
hudakz | 0:84353c479782 | 246 | return; |
hudakz | 0:84353c479782 | 247 | if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports |
hudakz | 0:84353c479782 | 248 | return; |
hudakz | 0:84353c479782 | 249 | } |
hudakz | 0:84353c479782 | 250 | |
hudakz | 0:84353c479782 | 251 | ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24)); |
hudakz | 0:84353c479782 | 252 | |
hudakz | 0:84353c479782 | 253 | hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); |
hudakz | 0:84353c479782 | 254 | hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); |
hudakz | 0:84353c479782 | 255 | hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); |
hudakz | 0:84353c479782 | 256 | hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); |
hudakz | 0:84353c479782 | 257 | |
hudakz | 0:84353c479782 | 258 | //Notify(PSTR("\r\nButtonState"), 0x80); |
hudakz | 0:84353c479782 | 259 | //PrintHex<uint32_t>(ButtonState, 0x80); |
hudakz | 0:84353c479782 | 260 | |
hudakz | 0:84353c479782 | 261 | if(ButtonState != OldButtonState) { |
hudakz | 0:84353c479782 | 262 | ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 |
hudakz | 0:84353c479782 | 263 | if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons |
hudakz | 0:84353c479782 | 264 | R2Clicked = true; |
hudakz | 0:84353c479782 | 265 | if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0) |
hudakz | 0:84353c479782 | 266 | L2Clicked = true; |
hudakz | 0:84353c479782 | 267 | OldButtonState = ButtonState; |
hudakz | 0:84353c479782 | 268 | } |
hudakz | 0:84353c479782 | 269 | } |
hudakz | 0:84353c479782 | 270 | |
hudakz | 0:84353c479782 | 271 | void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller |
hudakz | 0:84353c479782 | 272 | #ifdef PRINTREPORT |
hudakz | 0:84353c479782 | 273 | if(readBuf == NULL) |
hudakz | 0:84353c479782 | 274 | return; |
hudakz | 0:84353c479782 | 275 | for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) { |
hudakz | 0:84353c479782 | 276 | D_PrintHex<uint8_t > (readBuf[i], 0x80); |
hudakz | 0:84353c479782 | 277 | Notify(PSTR(" "), 0x80); |
hudakz | 0:84353c479782 | 278 | } |
hudakz | 0:84353c479782 | 279 | Notify(PSTR("\r\n"), 0x80); |
hudakz | 0:84353c479782 | 280 | #endif |
hudakz | 0:84353c479782 | 281 | } |
hudakz | 0:84353c479782 | 282 | |
hudakz | 0:84353c479782 | 283 | uint8_t XBOXUSB::getButtonPress(ButtonEnum b) { |
hudakz | 0:84353c479782 | 284 | if(b == L2) // These are analog buttons |
hudakz | 0:84353c479782 | 285 | return (uint8_t)(ButtonState >> 8); |
hudakz | 0:84353c479782 | 286 | else if(b == R2) |
hudakz | 0:84353c479782 | 287 | return (uint8_t)ButtonState; |
hudakz | 0:84353c479782 | 288 | return (bool)(ButtonState & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16)); |
hudakz | 0:84353c479782 | 289 | } |
hudakz | 0:84353c479782 | 290 | |
hudakz | 0:84353c479782 | 291 | bool XBOXUSB::getButtonClick(ButtonEnum b) { |
hudakz | 0:84353c479782 | 292 | if(b == L2) { |
hudakz | 0:84353c479782 | 293 | if(L2Clicked) { |
hudakz | 0:84353c479782 | 294 | L2Clicked = false; |
hudakz | 0:84353c479782 | 295 | return true; |
hudakz | 0:84353c479782 | 296 | } |
hudakz | 0:84353c479782 | 297 | return false; |
hudakz | 0:84353c479782 | 298 | } else if(b == R2) { |
hudakz | 0:84353c479782 | 299 | if(R2Clicked) { |
hudakz | 0:84353c479782 | 300 | R2Clicked = false; |
hudakz | 0:84353c479782 | 301 | return true; |
hudakz | 0:84353c479782 | 302 | } |
hudakz | 0:84353c479782 | 303 | return false; |
hudakz | 0:84353c479782 | 304 | } |
hudakz | 0:84353c479782 | 305 | uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]); |
hudakz | 0:84353c479782 | 306 | bool click = (ButtonClickState & button); |
hudakz | 0:84353c479782 | 307 | ButtonClickState &= ~button; // clear "click" event |
hudakz | 0:84353c479782 | 308 | return click; |
hudakz | 0:84353c479782 | 309 | } |
hudakz | 0:84353c479782 | 310 | |
hudakz | 0:84353c479782 | 311 | int16_t XBOXUSB::getAnalogHat(AnalogHatEnum a) { |
hudakz | 0:84353c479782 | 312 | return hatValue[a]; |
hudakz | 0:84353c479782 | 313 | } |
hudakz | 0:84353c479782 | 314 | |
hudakz | 0:84353c479782 | 315 | /* Xbox Controller commands */ |
hudakz | 0:84353c479782 | 316 | void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) { |
hudakz | 0:84353c479782 | 317 | //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) |
hudakz | 0:84353c479782 | 318 | pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); |
hudakz | 0:84353c479782 | 319 | } |
hudakz | 0:84353c479782 | 320 | |
hudakz | 0:84353c479782 | 321 | void XBOXUSB::setLedRaw(uint8_t value) { |
hudakz | 0:84353c479782 | 322 | writeBuf[0] = 0x01; |
hudakz | 0:84353c479782 | 323 | writeBuf[1] = 0x03; |
hudakz | 0:84353c479782 | 324 | writeBuf[2] = value; |
hudakz | 0:84353c479782 | 325 | |
hudakz | 0:84353c479782 | 326 | XboxCommand(writeBuf, 3); |
hudakz | 0:84353c479782 | 327 | } |
hudakz | 0:84353c479782 | 328 | |
hudakz | 0:84353c479782 | 329 | void XBOXUSB::setLedOn(LEDEnum led) { |
hudakz | 0:84353c479782 | 330 | if(led == OFF) |
hudakz | 0:84353c479782 | 331 | setLedRaw(0); |
hudakz | 0:84353c479782 | 332 | else if(led != ALL) // All LEDs can't be on a the same time |
hudakz | 0:84353c479782 | 333 | setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4); |
hudakz | 0:84353c479782 | 334 | } |
hudakz | 0:84353c479782 | 335 | |
hudakz | 0:84353c479782 | 336 | void XBOXUSB::setLedBlink(LEDEnum led) { |
hudakz | 0:84353c479782 | 337 | setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led])); |
hudakz | 0:84353c479782 | 338 | } |
hudakz | 0:84353c479782 | 339 | |
hudakz | 0:84353c479782 | 340 | void XBOXUSB::setLedMode(LEDModeEnum ledMode) { // This function is used to do some special LED stuff the controller supports |
hudakz | 0:84353c479782 | 341 | setLedRaw((uint8_t)ledMode); |
hudakz | 0:84353c479782 | 342 | } |
hudakz | 0:84353c479782 | 343 | |
hudakz | 0:84353c479782 | 344 | void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) { |
hudakz | 0:84353c479782 | 345 | writeBuf[0] = 0x00; |
hudakz | 0:84353c479782 | 346 | writeBuf[1] = 0x08; |
hudakz | 0:84353c479782 | 347 | writeBuf[2] = 0x00; |
hudakz | 0:84353c479782 | 348 | writeBuf[3] = lValue; // big weight |
hudakz | 0:84353c479782 | 349 | writeBuf[4] = rValue; // small weight |
hudakz | 0:84353c479782 | 350 | writeBuf[5] = 0x00; |
hudakz | 0:84353c479782 | 351 | writeBuf[6] = 0x00; |
hudakz | 0:84353c479782 | 352 | writeBuf[7] = 0x00; |
hudakz | 0:84353c479782 | 353 | |
hudakz | 0:84353c479782 | 354 | XboxCommand(writeBuf, 8); |
hudakz | 0:84353c479782 | 355 | } |
hudakz | 0:84353c479782 | 356 | |
hudakz | 0:84353c479782 | 357 | void XBOXUSB::onInit() { |
hudakz | 0:84353c479782 | 358 | if(pFuncOnInit) |
hudakz | 0:84353c479782 | 359 | pFuncOnInit(); // Call the user function |
hudakz | 0:84353c479782 | 360 | else |
hudakz | 0:84353c479782 | 361 | setLedOn(static_cast<LEDEnum>(LED1)); |
hudakz | 0:84353c479782 | 362 | } |