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
PS3USB.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 "PS3USB.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 PS3 Controllers |
hudakz | 0:84353c479782 | 22 | |
hudakz | 0:84353c479782 | 23 | PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : |
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 | { |
hudakz | 0:84353c479782 | 28 | for(uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) { |
hudakz | 0:84353c479782 | 29 | epInfo[i].epAddr = 0; |
hudakz | 0:84353c479782 | 30 | epInfo[i].maxPktSize = (i) ? 0 : 8; |
hudakz | 0:84353c479782 | 31 | epInfo[i].bmSndToggle = 0; |
hudakz | 0:84353c479782 | 32 | epInfo[i].bmRcvToggle = 0; |
hudakz | 0:84353c479782 | 33 | epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; |
hudakz | 0:84353c479782 | 34 | } |
hudakz | 0:84353c479782 | 35 | |
hudakz | 0:84353c479782 | 36 | if(pUsb) // register in USB subsystem |
hudakz | 0:84353c479782 | 37 | pUsb->RegisterDeviceClass(this); //set devConfig[] entry |
hudakz | 0:84353c479782 | 38 | |
hudakz | 0:84353c479782 | 39 | my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead |
hudakz | 0:84353c479782 | 40 | my_bdaddr[4] = btadr4; |
hudakz | 0:84353c479782 | 41 | my_bdaddr[3] = btadr3; |
hudakz | 0:84353c479782 | 42 | my_bdaddr[2] = btadr2; |
hudakz | 0:84353c479782 | 43 | my_bdaddr[1] = btadr1; |
hudakz | 0:84353c479782 | 44 | my_bdaddr[0] = btadr0; |
hudakz | 0:84353c479782 | 45 | } |
hudakz | 0:84353c479782 | 46 | |
hudakz | 0:84353c479782 | 47 | uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { |
hudakz | 0:84353c479782 | 48 | uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; |
hudakz | 0:84353c479782 | 49 | USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf); |
hudakz | 0:84353c479782 | 50 | uint8_t rcode; |
hudakz | 0:84353c479782 | 51 | UsbDevice *p = NULL; |
hudakz | 0:84353c479782 | 52 | EpInfo *oldep_ptr = NULL; |
hudakz | 0:84353c479782 | 53 | uint16_t PID; |
hudakz | 0:84353c479782 | 54 | uint16_t VID; |
hudakz | 0:84353c479782 | 55 | |
hudakz | 0:84353c479782 | 56 | // get memory address of USB device address pool |
hudakz | 0:84353c479782 | 57 | AddressPool &addrPool = pUsb->GetAddressPool(); |
hudakz | 0:84353c479782 | 58 | #ifdef EXTRADEBUG |
hudakz | 0:84353c479782 | 59 | Notify(PSTR("\r\nPS3USB Init"), 0x80); |
hudakz | 0:84353c479782 | 60 | #endif |
hudakz | 0:84353c479782 | 61 | // check if address has already been assigned to an instance |
hudakz | 0:84353c479782 | 62 | if(bAddress) { |
hudakz | 0:84353c479782 | 63 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 64 | Notify(PSTR("\r\nAddress in use"), 0x80); |
hudakz | 0:84353c479782 | 65 | #endif |
hudakz | 0:84353c479782 | 66 | return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; |
hudakz | 0:84353c479782 | 67 | } |
hudakz | 0:84353c479782 | 68 | |
hudakz | 0:84353c479782 | 69 | // Get pointer to pseudo device with address 0 assigned |
hudakz | 0:84353c479782 | 70 | p = addrPool.GetUsbDevicePtr(0); |
hudakz | 0:84353c479782 | 71 | |
hudakz | 0:84353c479782 | 72 | if(!p) { |
hudakz | 0:84353c479782 | 73 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 74 | Notify(PSTR("\r\nAddress not found"), 0x80); |
hudakz | 0:84353c479782 | 75 | #endif |
hudakz | 0:84353c479782 | 76 | return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; |
hudakz | 0:84353c479782 | 77 | } |
hudakz | 0:84353c479782 | 78 | |
hudakz | 0:84353c479782 | 79 | if(!p->epinfo) { |
hudakz | 0:84353c479782 | 80 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 81 | Notify(PSTR("\r\nepinfo is null"), 0x80); |
hudakz | 0:84353c479782 | 82 | #endif |
hudakz | 0:84353c479782 | 83 | return USB_ERROR_EPINFO_IS_NULL; |
hudakz | 0:84353c479782 | 84 | } |
hudakz | 0:84353c479782 | 85 | |
hudakz | 0:84353c479782 | 86 | // Save old pointer to EP_RECORD of address 0 |
hudakz | 0:84353c479782 | 87 | oldep_ptr = p->epinfo; |
hudakz | 0:84353c479782 | 88 | |
hudakz | 0:84353c479782 | 89 | // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence |
hudakz | 0:84353c479782 | 90 | p->epinfo = epInfo; |
hudakz | 0:84353c479782 | 91 | |
hudakz | 0:84353c479782 | 92 | p->lowspeed = lowspeed; |
hudakz | 0:84353c479782 | 93 | |
hudakz | 0:84353c479782 | 94 | // Get device descriptor |
hudakz | 0:84353c479782 | 95 | rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data |
hudakz | 0:84353c479782 | 96 | // Restore p->epinfo |
hudakz | 0:84353c479782 | 97 | p->epinfo = oldep_ptr; |
hudakz | 0:84353c479782 | 98 | |
hudakz | 0:84353c479782 | 99 | if(rcode) |
hudakz | 0:84353c479782 | 100 | goto FailGetDevDescr; |
hudakz | 0:84353c479782 | 101 | |
hudakz | 0:84353c479782 | 102 | VID = udd->idVendor; |
hudakz | 0:84353c479782 | 103 | PID = udd->idProduct; |
hudakz | 0:84353c479782 | 104 | |
hudakz | 0:84353c479782 | 105 | if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID)) |
hudakz | 0:84353c479782 | 106 | goto FailUnknownDevice; |
hudakz | 0:84353c479782 | 107 | |
hudakz | 0:84353c479782 | 108 | // Allocate new address according to device class |
hudakz | 0:84353c479782 | 109 | bAddress = addrPool.AllocAddress(parent, false, port); |
hudakz | 0:84353c479782 | 110 | |
hudakz | 0:84353c479782 | 111 | if(!bAddress) |
hudakz | 0:84353c479782 | 112 | return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; |
hudakz | 0:84353c479782 | 113 | |
hudakz | 0:84353c479782 | 114 | // Extract Max Packet Size from device descriptor |
hudakz | 0:84353c479782 | 115 | epInfo[0].maxPktSize = udd->bMaxPacketSize0; |
hudakz | 0:84353c479782 | 116 | |
hudakz | 0:84353c479782 | 117 | // Assign new address to the device |
hudakz | 0:84353c479782 | 118 | rcode = pUsb->setAddr(0, 0, bAddress); |
hudakz | 0:84353c479782 | 119 | if(rcode) { |
hudakz | 0:84353c479782 | 120 | p->lowspeed = false; |
hudakz | 0:84353c479782 | 121 | addrPool.FreeAddress(bAddress); |
hudakz | 0:84353c479782 | 122 | bAddress = 0; |
hudakz | 0:84353c479782 | 123 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 124 | Notify(PSTR("\r\nsetAddr: "), 0x80); |
hudakz | 0:84353c479782 | 125 | D_PrintHex<uint8_t > (rcode, 0x80); |
hudakz | 0:84353c479782 | 126 | #endif |
hudakz | 0:84353c479782 | 127 | return rcode; |
hudakz | 0:84353c479782 | 128 | } |
hudakz | 0:84353c479782 | 129 | #ifdef EXTRADEBUG |
hudakz | 0:84353c479782 | 130 | Notify(PSTR("\r\nAddr: "), 0x80); |
hudakz | 0:84353c479782 | 131 | D_PrintHex<uint8_t > (bAddress, 0x80); |
hudakz | 0:84353c479782 | 132 | #endif |
hudakz | 0:84353c479782 | 133 | //wait_ms(300); // Spec says you should wait at least 200ms |
hudakz | 0:84353c479782 | 134 | |
hudakz | 0:84353c479782 | 135 | p->lowspeed = false; |
hudakz | 0:84353c479782 | 136 | |
hudakz | 0:84353c479782 | 137 | //get pointer to assigned address record |
hudakz | 0:84353c479782 | 138 | p = addrPool.GetUsbDevicePtr(bAddress); |
hudakz | 0:84353c479782 | 139 | if(!p) |
hudakz | 0:84353c479782 | 140 | return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; |
hudakz | 0:84353c479782 | 141 | |
hudakz | 0:84353c479782 | 142 | p->lowspeed = lowspeed; |
hudakz | 0:84353c479782 | 143 | |
hudakz | 0:84353c479782 | 144 | // Assign epInfo to epinfo pointer - only EP0 is known |
hudakz | 0:84353c479782 | 145 | rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); |
hudakz | 0:84353c479782 | 146 | if(rcode) |
hudakz | 0:84353c479782 | 147 | goto FailSetDevTblEntry; |
hudakz | 0:84353c479782 | 148 | |
hudakz | 0:84353c479782 | 149 | |
hudakz | 0:84353c479782 | 150 | /* The application will work in reduced host mode, so we can save program and data |
hudakz | 0:84353c479782 | 151 | memory space. After verifying the PID and VID we will use known values for the |
hudakz | 0:84353c479782 | 152 | configuration values for device, interface, endpoints and HID for the PS3 Controllers */ |
hudakz | 0:84353c479782 | 153 | |
hudakz | 0:84353c479782 | 154 | /* Initialize data structures for endpoints of device */ |
hudakz | 0:84353c479782 | 155 | epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint |
hudakz | 0:84353c479782 | 156 | epInfo[ PS3_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; |
hudakz | 0:84353c479782 | 157 | epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints |
hudakz | 0:84353c479782 | 158 | epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; |
hudakz | 0:84353c479782 | 159 | epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = 0; |
hudakz | 0:84353c479782 | 160 | epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = 0; |
hudakz | 0:84353c479782 | 161 | epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint |
hudakz | 0:84353c479782 | 162 | epInfo[ PS3_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; |
hudakz | 0:84353c479782 | 163 | epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints |
hudakz | 0:84353c479782 | 164 | epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; |
hudakz | 0:84353c479782 | 165 | epInfo[ PS3_INPUT_PIPE ].bmSndToggle = 0; |
hudakz | 0:84353c479782 | 166 | epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = 0; |
hudakz | 0:84353c479782 | 167 | |
hudakz | 0:84353c479782 | 168 | rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); |
hudakz | 0:84353c479782 | 169 | if(rcode) |
hudakz | 0:84353c479782 | 170 | goto FailSetDevTblEntry; |
hudakz | 0:84353c479782 | 171 | |
hudakz | 0:84353c479782 | 172 | wait_ms(200); //Give time for address change |
hudakz | 0:84353c479782 | 173 | |
hudakz | 0:84353c479782 | 174 | rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); |
hudakz | 0:84353c479782 | 175 | if(rcode) |
hudakz | 0:84353c479782 | 176 | goto FailSetConfDescr; |
hudakz | 0:84353c479782 | 177 | |
hudakz | 0:84353c479782 | 178 | if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { |
hudakz | 0:84353c479782 | 179 | if(PID == PS3_PID) { |
hudakz | 0:84353c479782 | 180 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 181 | Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); |
hudakz | 0:84353c479782 | 182 | #endif |
hudakz | 0:84353c479782 | 183 | PS3Connected = true; |
hudakz | 0:84353c479782 | 184 | } else { // must be a navigation controller |
hudakz | 0:84353c479782 | 185 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 186 | Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); |
hudakz | 0:84353c479782 | 187 | #endif |
hudakz | 0:84353c479782 | 188 | PS3NavigationConnected = true; |
hudakz | 0:84353c479782 | 189 | } |
hudakz | 0:84353c479782 | 190 | enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data |
hudakz | 0:84353c479782 | 191 | |
hudakz | 0:84353c479782 | 192 | // Needed for PS3 Dualshock and Navigation commands to work |
hudakz | 0:84353c479782 | 193 | for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) |
hudakz | 0:84353c479782 | 194 | writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); |
hudakz | 0:84353c479782 | 195 | |
hudakz | 0:84353c479782 | 196 | for(uint8_t i = 6; i < 10; i++) |
hudakz | 0:84353c479782 | 197 | readBuf[i] = 0x7F; // Set the analog joystick values to center position |
hudakz | 0:84353c479782 | 198 | } else { // must be a Motion controller |
hudakz | 0:84353c479782 | 199 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 200 | Notify(PSTR("\r\nMotion Controller Connected"), 0x80); |
hudakz | 0:84353c479782 | 201 | #endif |
hudakz | 0:84353c479782 | 202 | PS3MoveConnected = true; |
hudakz | 0:84353c479782 | 203 | writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work |
hudakz | 0:84353c479782 | 204 | } |
hudakz | 0:84353c479782 | 205 | if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { |
hudakz | 0:84353c479782 | 206 | if(PS3MoveConnected) |
hudakz | 0:84353c479782 | 207 | setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address |
hudakz | 0:84353c479782 | 208 | else |
hudakz | 0:84353c479782 | 209 | setBdaddr(my_bdaddr); // Set internal Bluetooth address |
hudakz | 0:84353c479782 | 210 | |
hudakz | 0:84353c479782 | 211 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 212 | Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); |
hudakz | 0:84353c479782 | 213 | for(int8_t i = 5; i > 0; i--) { |
hudakz | 0:84353c479782 | 214 | D_PrintHex<uint8_t > (my_bdaddr[i], 0x80); |
hudakz | 0:84353c479782 | 215 | Notify(PSTR(":"), 0x80); |
hudakz | 0:84353c479782 | 216 | } |
hudakz | 0:84353c479782 | 217 | D_PrintHex<uint8_t > (my_bdaddr[0], 0x80); |
hudakz | 0:84353c479782 | 218 | #endif |
hudakz | 0:84353c479782 | 219 | } |
hudakz | 0:84353c479782 | 220 | onInit(); |
hudakz | 0:84353c479782 | 221 | |
hudakz | 0:84353c479782 | 222 | bPollEnable = true; |
hudakz | 0:84353c479782 | 223 | Notify(PSTR("\r\n"), 0x80); |
hudakz | 0:84353c479782 | 224 | timer = (uint32_t)millis(); |
hudakz | 0:84353c479782 | 225 | return 0; // Successful configuration |
hudakz | 0:84353c479782 | 226 | |
hudakz | 0:84353c479782 | 227 | /* Diagnostic messages */ |
hudakz | 0:84353c479782 | 228 | FailGetDevDescr: |
hudakz | 0:84353c479782 | 229 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 230 | NotifyFailGetDevDescr(); |
hudakz | 0:84353c479782 | 231 | goto Fail; |
hudakz | 0:84353c479782 | 232 | #endif |
hudakz | 0:84353c479782 | 233 | |
hudakz | 0:84353c479782 | 234 | FailSetDevTblEntry: |
hudakz | 0:84353c479782 | 235 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 236 | NotifyFailSetDevTblEntry(); |
hudakz | 0:84353c479782 | 237 | goto Fail; |
hudakz | 0:84353c479782 | 238 | #endif |
hudakz | 0:84353c479782 | 239 | |
hudakz | 0:84353c479782 | 240 | FailSetConfDescr: |
hudakz | 0:84353c479782 | 241 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 242 | NotifyFailSetConfDescr(); |
hudakz | 0:84353c479782 | 243 | #endif |
hudakz | 0:84353c479782 | 244 | goto Fail; |
hudakz | 0:84353c479782 | 245 | |
hudakz | 0:84353c479782 | 246 | FailUnknownDevice: |
hudakz | 0:84353c479782 | 247 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 248 | NotifyFailUnknownDevice(VID, PID); |
hudakz | 0:84353c479782 | 249 | #endif |
hudakz | 0:84353c479782 | 250 | rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; |
hudakz | 0:84353c479782 | 251 | |
hudakz | 0:84353c479782 | 252 | Fail: |
hudakz | 0:84353c479782 | 253 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 254 | Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80); |
hudakz | 0:84353c479782 | 255 | NotifyFail(rcode); |
hudakz | 0:84353c479782 | 256 | #endif |
hudakz | 0:84353c479782 | 257 | Release(); |
hudakz | 0:84353c479782 | 258 | return rcode; |
hudakz | 0:84353c479782 | 259 | } |
hudakz | 0:84353c479782 | 260 | |
hudakz | 0:84353c479782 | 261 | /* Performs a cleanup after failed Init() attempt */ |
hudakz | 0:84353c479782 | 262 | uint8_t PS3USB::Release() { |
hudakz | 0:84353c479782 | 263 | PS3Connected = false; |
hudakz | 0:84353c479782 | 264 | PS3MoveConnected = false; |
hudakz | 0:84353c479782 | 265 | PS3NavigationConnected = false; |
hudakz | 0:84353c479782 | 266 | pUsb->GetAddressPool().FreeAddress(bAddress); |
hudakz | 0:84353c479782 | 267 | bAddress = 0; |
hudakz | 0:84353c479782 | 268 | bPollEnable = false; |
hudakz | 0:84353c479782 | 269 | return 0; |
hudakz | 0:84353c479782 | 270 | } |
hudakz | 0:84353c479782 | 271 | |
hudakz | 0:84353c479782 | 272 | uint8_t PS3USB::Poll() { |
hudakz | 0:84353c479782 | 273 | if(!bPollEnable) |
hudakz | 0:84353c479782 | 274 | return 0; |
hudakz | 0:84353c479782 | 275 | |
hudakz | 0:84353c479782 | 276 | if(PS3Connected || PS3NavigationConnected) { |
hudakz | 0:84353c479782 | 277 | uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; |
hudakz | 0:84353c479782 | 278 | pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 |
hudakz | 0:84353c479782 | 279 | if((int32_t)((uint32_t)millis() - timer) > 100) { // Loop 100ms before processing data |
hudakz | 0:84353c479782 | 280 | readReport(); |
hudakz | 0:84353c479782 | 281 | #ifdef PRINTREPORT |
hudakz | 0:84353c479782 | 282 | printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers |
hudakz | 0:84353c479782 | 283 | #endif |
hudakz | 0:84353c479782 | 284 | } |
hudakz | 0:84353c479782 | 285 | } else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB |
hudakz | 0:84353c479782 | 286 | if((int32_t)((uint32_t)millis() - timer) > 4000) { // Send at least every 4th second |
hudakz | 0:84353c479782 | 287 | Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on |
hudakz | 0:84353c479782 | 288 | timer = (uint32_t)millis(); |
hudakz | 0:84353c479782 | 289 | } |
hudakz | 0:84353c479782 | 290 | } |
hudakz | 0:84353c479782 | 291 | return 0; |
hudakz | 0:84353c479782 | 292 | } |
hudakz | 0:84353c479782 | 293 | |
hudakz | 0:84353c479782 | 294 | void PS3USB::readReport() { |
hudakz | 0:84353c479782 | 295 | ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); |
hudakz | 0:84353c479782 | 296 | |
hudakz | 0:84353c479782 | 297 | //Notify(PSTR("\r\nButtonState", 0x80); |
hudakz | 0:84353c479782 | 298 | //PrintHex<uint32_t>(ButtonState, 0x80); |
hudakz | 0:84353c479782 | 299 | |
hudakz | 0:84353c479782 | 300 | if(ButtonState != OldButtonState) { |
hudakz | 0:84353c479782 | 301 | ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable |
hudakz | 0:84353c479782 | 302 | OldButtonState = ButtonState; |
hudakz | 0:84353c479782 | 303 | } |
hudakz | 0:84353c479782 | 304 | } |
hudakz | 0:84353c479782 | 305 | |
hudakz | 0:84353c479782 | 306 | void PS3USB::printReport() { // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers |
hudakz | 0:84353c479782 | 307 | #ifdef PRINTREPORT |
hudakz | 0:84353c479782 | 308 | for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) { |
hudakz | 0:84353c479782 | 309 | D_PrintHex<uint8_t > (readBuf[i], 0x80); |
hudakz | 0:84353c479782 | 310 | Notify(PSTR(" "), 0x80); |
hudakz | 0:84353c479782 | 311 | } |
hudakz | 0:84353c479782 | 312 | Notify(PSTR("\r\n"), 0x80); |
hudakz | 0:84353c479782 | 313 | #endif |
hudakz | 0:84353c479782 | 314 | } |
hudakz | 0:84353c479782 | 315 | |
hudakz | 0:84353c479782 | 316 | bool PS3USB::getButtonPress(ButtonEnum b) { |
hudakz | 0:84353c479782 | 317 | return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b])); |
hudakz | 0:84353c479782 | 318 | } |
hudakz | 0:84353c479782 | 319 | |
hudakz | 0:84353c479782 | 320 | bool PS3USB::getButtonClick(ButtonEnum b) { |
hudakz | 0:84353c479782 | 321 | uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]); |
hudakz | 0:84353c479782 | 322 | bool click = (ButtonClickState & button); |
hudakz | 0:84353c479782 | 323 | ButtonClickState &= ~button; // Clear "click" event |
hudakz | 0:84353c479782 | 324 | return click; |
hudakz | 0:84353c479782 | 325 | } |
hudakz | 0:84353c479782 | 326 | |
hudakz | 0:84353c479782 | 327 | uint8_t PS3USB::getAnalogButton(ButtonEnum a) { |
hudakz | 0:84353c479782 | 328 | return (uint8_t)(readBuf[(pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])) - 9]); |
hudakz | 0:84353c479782 | 329 | } |
hudakz | 0:84353c479782 | 330 | |
hudakz | 0:84353c479782 | 331 | uint8_t PS3USB::getAnalogHat(AnalogHatEnum a) { |
hudakz | 0:84353c479782 | 332 | return (uint8_t)(readBuf[((uint8_t)a + 6)]); |
hudakz | 0:84353c479782 | 333 | } |
hudakz | 0:84353c479782 | 334 | |
hudakz | 0:84353c479782 | 335 | uint16_t PS3USB::getSensor(SensorEnum a) { |
hudakz | 0:84353c479782 | 336 | return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]); |
hudakz | 0:84353c479782 | 337 | } |
hudakz | 0:84353c479782 | 338 | |
hudakz | 0:84353c479782 | 339 | float PS3USB::getAngle(AngleEnum a) { |
hudakz | 0:84353c479782 | 340 | if(PS3Connected) { |
hudakz | 0:84353c479782 | 341 | float accXval, accYval, accZval; |
hudakz | 0:84353c479782 | 342 | |
hudakz | 0:84353c479782 | 343 | // Data for the Kionix KXPC4 used in the DualShock 3 |
hudakz | 0:84353c479782 | 344 | const float zeroG = 511.5f; // 1.65/3.3*1023 (1,65V) |
hudakz | 0:84353c479782 | 345 | accXval = -((float)getSensor(aX) - zeroG); |
hudakz | 0:84353c479782 | 346 | accYval = -((float)getSensor(aY) - zeroG); |
hudakz | 0:84353c479782 | 347 | accZval = -((float)getSensor(aZ) - zeroG); |
hudakz | 0:84353c479782 | 348 | |
hudakz | 0:84353c479782 | 349 | // Convert to 360 degrees resolution |
hudakz | 0:84353c479782 | 350 | // atan2 outputs the value of -π to π (radians) |
hudakz | 0:84353c479782 | 351 | // We are then converting it to 0 to 2π and then to degrees |
hudakz | 0:84353c479782 | 352 | if(a == Pitch) |
hudakz | 0:84353c479782 | 353 | return (atan2f(accYval, accZval) + M_PI) * RAD_TO_DEG; |
hudakz | 0:84353c479782 | 354 | else |
hudakz | 0:84353c479782 | 355 | return (atan2f(accXval, accZval) + M_PI) * RAD_TO_DEG; |
hudakz | 0:84353c479782 | 356 | } else |
hudakz | 0:84353c479782 | 357 | return 0; |
hudakz | 0:84353c479782 | 358 | } |
hudakz | 0:84353c479782 | 359 | |
hudakz | 0:84353c479782 | 360 | bool PS3USB::getStatus(StatusEnum c) { |
hudakz | 0:84353c479782 | 361 | return (readBuf[((uint16_t)c >> 8) - 9] == ((uint8_t)c & 0xff)); |
hudakz | 0:84353c479782 | 362 | } |
hudakz | 0:84353c479782 | 363 | |
hudakz | 0:84353c479782 | 364 | void PS3USB::printStatusString() { |
hudakz | 0:84353c479782 | 365 | char statusOutput[102]; // Max string length plus null character |
hudakz | 0:84353c479782 | 366 | if(PS3Connected || PS3NavigationConnected) { |
hudakz | 0:84353c479782 | 367 | strcpy_P(statusOutput, PSTR("\r\nConnectionStatus: ")); |
hudakz | 0:84353c479782 | 368 | |
hudakz | 0:84353c479782 | 369 | if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged")); |
hudakz | 0:84353c479782 | 370 | else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged")); |
hudakz | 0:84353c479782 | 371 | else strcat_P(statusOutput, PSTR("Error")); |
hudakz | 0:84353c479782 | 372 | |
hudakz | 0:84353c479782 | 373 | strcat_P(statusOutput, PSTR(" - PowerRating: ")); |
hudakz | 0:84353c479782 | 374 | |
hudakz | 0:84353c479782 | 375 | if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging")); |
hudakz | 0:84353c479782 | 376 | else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); |
hudakz | 0:84353c479782 | 377 | else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown")); |
hudakz | 0:84353c479782 | 378 | else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying")); |
hudakz | 0:84353c479782 | 379 | else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low")); |
hudakz | 0:84353c479782 | 380 | else if(getStatus(High)) strcat_P(statusOutput, PSTR("High")); |
hudakz | 0:84353c479782 | 381 | else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full")); |
hudakz | 0:84353c479782 | 382 | else strcat_P(statusOutput, PSTR("Error")); |
hudakz | 0:84353c479782 | 383 | |
hudakz | 0:84353c479782 | 384 | strcat_P(statusOutput, PSTR(" - WirelessStatus: ")); |
hudakz | 0:84353c479782 | 385 | |
hudakz | 0:84353c479782 | 386 | if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on")); |
hudakz | 0:84353c479782 | 387 | else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off")); |
hudakz | 0:84353c479782 | 388 | else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on")); |
hudakz | 0:84353c479782 | 389 | else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off")); |
hudakz | 0:84353c479782 | 390 | else strcat_P(statusOutput, PSTR("Error")); |
hudakz | 0:84353c479782 | 391 | } else |
hudakz | 0:84353c479782 | 392 | strcpy_P(statusOutput, PSTR("\r\nError")); |
hudakz | 0:84353c479782 | 393 | #ifndef __MBED__ |
hudakz | 0:84353c479782 | 394 | USB_HOST_SERIAL.write(statusOutput); |
hudakz | 0:84353c479782 | 395 | #endif |
hudakz | 0:84353c479782 | 396 | } |
hudakz | 0:84353c479782 | 397 | |
hudakz | 0:84353c479782 | 398 | /* Playstation Sixaxis Dualshock and Navigation Controller commands */ |
hudakz | 0:84353c479782 | 399 | void PS3USB::PS3_Command(uint8_t *data, uint16_t nbytes) { |
hudakz | 0:84353c479782 | 400 | // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) |
hudakz | 0:84353c479782 | 401 | pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); |
hudakz | 0:84353c479782 | 402 | } |
hudakz | 0:84353c479782 | 403 | |
hudakz | 0:84353c479782 | 404 | void PS3USB::setAllOff() { |
hudakz | 0:84353c479782 | 405 | for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) |
hudakz | 0:84353c479782 | 406 | writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer |
hudakz | 0:84353c479782 | 407 | |
hudakz | 0:84353c479782 | 408 | PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 409 | } |
hudakz | 0:84353c479782 | 410 | |
hudakz | 0:84353c479782 | 411 | void PS3USB::setRumbleOff() { |
hudakz | 0:84353c479782 | 412 | uint8_t rumbleBuf[EP_MAXPKTSIZE]; |
hudakz | 0:84353c479782 | 413 | memcpy(rumbleBuf, writeBuf, EP_MAXPKTSIZE); |
hudakz | 0:84353c479782 | 414 | rumbleBuf[1] = 0x00; |
hudakz | 0:84353c479782 | 415 | rumbleBuf[2] = 0x00; // Low mode off |
hudakz | 0:84353c479782 | 416 | rumbleBuf[3] = 0x00; |
hudakz | 0:84353c479782 | 417 | rumbleBuf[4] = 0x00; // High mode off |
hudakz | 0:84353c479782 | 418 | PS3_Command(rumbleBuf, PS3_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 419 | } |
hudakz | 0:84353c479782 | 420 | |
hudakz | 0:84353c479782 | 421 | void PS3USB::setRumbleOn(RumbleEnum mode) { |
hudakz | 0:84353c479782 | 422 | if((mode & 0x30) > 0x00) { |
hudakz | 0:84353c479782 | 423 | uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow |
hudakz | 0:84353c479782 | 424 | if(mode == RumbleHigh) { |
hudakz | 0:84353c479782 | 425 | power[0] = 0x00; |
hudakz | 0:84353c479782 | 426 | power[1] = 0xff; |
hudakz | 0:84353c479782 | 427 | } |
hudakz | 0:84353c479782 | 428 | setRumbleOn(0xfe, power[0], 0xfe, power[1]); |
hudakz | 0:84353c479782 | 429 | } |
hudakz | 0:84353c479782 | 430 | } |
hudakz | 0:84353c479782 | 431 | |
hudakz | 0:84353c479782 | 432 | void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { |
hudakz | 0:84353c479782 | 433 | uint8_t rumbleBuf[EP_MAXPKTSIZE]; |
hudakz | 0:84353c479782 | 434 | memcpy(rumbleBuf, writeBuf, EP_MAXPKTSIZE); |
hudakz | 0:84353c479782 | 435 | rumbleBuf[1] = rightDuration; |
hudakz | 0:84353c479782 | 436 | rumbleBuf[2] = rightPower; |
hudakz | 0:84353c479782 | 437 | rumbleBuf[3] = leftDuration; |
hudakz | 0:84353c479782 | 438 | rumbleBuf[4] = leftPower; |
hudakz | 0:84353c479782 | 439 | PS3_Command(rumbleBuf, PS3_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 440 | } |
hudakz | 0:84353c479782 | 441 | |
hudakz | 0:84353c479782 | 442 | void PS3USB::setLedRaw(uint8_t value) { |
hudakz | 0:84353c479782 | 443 | writeBuf[9] = value << 1; |
hudakz | 0:84353c479782 | 444 | PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 445 | } |
hudakz | 0:84353c479782 | 446 | |
hudakz | 0:84353c479782 | 447 | void PS3USB::setLedOff(LEDEnum a) { |
hudakz | 0:84353c479782 | 448 | writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1)); |
hudakz | 0:84353c479782 | 449 | PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 450 | } |
hudakz | 0:84353c479782 | 451 | |
hudakz | 0:84353c479782 | 452 | void PS3USB::setLedOn(LEDEnum a) { |
hudakz | 0:84353c479782 | 453 | if(a == OFF) |
hudakz | 0:84353c479782 | 454 | setLedRaw(0); |
hudakz | 0:84353c479782 | 455 | else { |
hudakz | 0:84353c479782 | 456 | writeBuf[9] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); |
hudakz | 0:84353c479782 | 457 | PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 458 | } |
hudakz | 0:84353c479782 | 459 | } |
hudakz | 0:84353c479782 | 460 | |
hudakz | 0:84353c479782 | 461 | void PS3USB::setLedToggle(LEDEnum a) { |
hudakz | 0:84353c479782 | 462 | writeBuf[9] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); |
hudakz | 0:84353c479782 | 463 | PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 464 | } |
hudakz | 0:84353c479782 | 465 | |
hudakz | 0:84353c479782 | 466 | void PS3USB::setBdaddr(uint8_t *bdaddr) { |
hudakz | 0:84353c479782 | 467 | /* Set the internal Bluetooth address */ |
hudakz | 0:84353c479782 | 468 | uint8_t buf[8]; |
hudakz | 0:84353c479782 | 469 | buf[0] = 0x01; |
hudakz | 0:84353c479782 | 470 | buf[1] = 0x00; |
hudakz | 0:84353c479782 | 471 | |
hudakz | 0:84353c479782 | 472 | for(uint8_t i = 0; i < 6; i++) |
hudakz | 0:84353c479782 | 473 | buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first |
hudakz | 0:84353c479782 | 474 | |
hudakz | 0:84353c479782 | 475 | // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data |
hudakz | 0:84353c479782 | 476 | pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); |
hudakz | 0:84353c479782 | 477 | } |
hudakz | 0:84353c479782 | 478 | |
hudakz | 0:84353c479782 | 479 | void PS3USB::getBdaddr(uint8_t *bdaddr) { |
hudakz | 0:84353c479782 | 480 | uint8_t buf[8]; |
hudakz | 0:84353c479782 | 481 | |
hudakz | 0:84353c479782 | 482 | // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data |
hudakz | 0:84353c479782 | 483 | pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); |
hudakz | 0:84353c479782 | 484 | |
hudakz | 0:84353c479782 | 485 | for(uint8_t i = 0; i < 6; i++) |
hudakz | 0:84353c479782 | 486 | bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first |
hudakz | 0:84353c479782 | 487 | } |
hudakz | 0:84353c479782 | 488 | |
hudakz | 0:84353c479782 | 489 | void PS3USB::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via USB |
hudakz | 0:84353c479782 | 490 | uint8_t cmd_buf[4]; |
hudakz | 0:84353c479782 | 491 | cmd_buf[0] = 0x42; // Special PS3 Controller enable commands |
hudakz | 0:84353c479782 | 492 | cmd_buf[1] = 0x0c; |
hudakz | 0:84353c479782 | 493 | cmd_buf[2] = 0x00; |
hudakz | 0:84353c479782 | 494 | cmd_buf[3] = 0x00; |
hudakz | 0:84353c479782 | 495 | |
hudakz | 0:84353c479782 | 496 | // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) |
hudakz | 0:84353c479782 | 497 | pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); |
hudakz | 0:84353c479782 | 498 | } |
hudakz | 0:84353c479782 | 499 | |
hudakz | 0:84353c479782 | 500 | /* Playstation Move Controller commands */ |
hudakz | 0:84353c479782 | 501 | void PS3USB::Move_Command(uint8_t *data, uint16_t nbytes) { |
hudakz | 0:84353c479782 | 502 | pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); |
hudakz | 0:84353c479782 | 503 | } |
hudakz | 0:84353c479782 | 504 | |
hudakz | 0:84353c479782 | 505 | void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values |
hudakz | 0:84353c479782 | 506 | // Set the Bulb's values into the write buffer |
hudakz | 0:84353c479782 | 507 | writeBuf[2] = r; |
hudakz | 0:84353c479782 | 508 | writeBuf[3] = g; |
hudakz | 0:84353c479782 | 509 | writeBuf[4] = b; |
hudakz | 0:84353c479782 | 510 | |
hudakz | 0:84353c479782 | 511 | Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 512 | } |
hudakz | 0:84353c479782 | 513 | |
hudakz | 0:84353c479782 | 514 | void PS3USB::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in "enums.h" |
hudakz | 0:84353c479782 | 515 | moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); |
hudakz | 0:84353c479782 | 516 | } |
hudakz | 0:84353c479782 | 517 | |
hudakz | 0:84353c479782 | 518 | void PS3USB::moveSetRumble(uint8_t rumble) { |
hudakz | 0:84353c479782 | 519 | #ifdef DEBUG_USB_HOST |
hudakz | 0:84353c479782 | 520 | if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) |
hudakz | 0:84353c479782 | 521 | Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); |
hudakz | 0:84353c479782 | 522 | #endif |
hudakz | 0:84353c479782 | 523 | writeBuf[6] = rumble; // Set the rumble value into the write buffer |
hudakz | 0:84353c479782 | 524 | |
hudakz | 0:84353c479782 | 525 | Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); |
hudakz | 0:84353c479782 | 526 | } |
hudakz | 0:84353c479782 | 527 | |
hudakz | 0:84353c479782 | 528 | void PS3USB::setMoveBdaddr(uint8_t *bdaddr) { |
hudakz | 0:84353c479782 | 529 | /* Set the internal Bluetooth address */ |
hudakz | 0:84353c479782 | 530 | uint8_t buf[11]; |
hudakz | 0:84353c479782 | 531 | buf[0] = 0x05; |
hudakz | 0:84353c479782 | 532 | buf[7] = 0x10; |
hudakz | 0:84353c479782 | 533 | buf[8] = 0x01; |
hudakz | 0:84353c479782 | 534 | buf[9] = 0x02; |
hudakz | 0:84353c479782 | 535 | buf[10] = 0x12; |
hudakz | 0:84353c479782 | 536 | |
hudakz | 0:84353c479782 | 537 | for(uint8_t i = 0; i < 6; i++) |
hudakz | 0:84353c479782 | 538 | buf[i + 1] = bdaddr[i]; |
hudakz | 0:84353c479782 | 539 | |
hudakz | 0:84353c479782 | 540 | // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data |
hudakz | 0:84353c479782 | 541 | pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); |
hudakz | 0:84353c479782 | 542 | } |
hudakz | 0:84353c479782 | 543 | |
hudakz | 0:84353c479782 | 544 | void PS3USB::getMoveBdaddr(uint8_t *bdaddr) { |
hudakz | 0:84353c479782 | 545 | uint8_t buf[16]; |
hudakz | 0:84353c479782 | 546 | |
hudakz | 0:84353c479782 | 547 | // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x04), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data |
hudakz | 0:84353c479782 | 548 | pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL); |
hudakz | 0:84353c479782 | 549 | |
hudakz | 0:84353c479782 | 550 | for(uint8_t i = 0; i < 6; i++) |
hudakz | 0:84353c479782 | 551 | bdaddr[i] = buf[10 + i]; |
hudakz | 0:84353c479782 | 552 | } |
hudakz | 0:84353c479782 | 553 | |
hudakz | 0:84353c479782 | 554 | void PS3USB::getMoveCalibration(uint8_t *data) { |
hudakz | 0:84353c479782 | 555 | uint8_t buf[49]; |
hudakz | 0:84353c479782 | 556 | |
hudakz | 0:84353c479782 | 557 | for(uint8_t i = 0; i < 3; i++) { |
hudakz | 0:84353c479782 | 558 | // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data |
hudakz | 0:84353c479782 | 559 | pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL); |
hudakz | 0:84353c479782 | 560 | |
hudakz | 0:84353c479782 | 561 | for(uint8_t j = 0; j < 49; j++) |
hudakz | 0:84353c479782 | 562 | data[49 * i + j] = buf[j]; |
hudakz | 0:84353c479782 | 563 | } |
hudakz | 0:84353c479782 | 564 | } |
hudakz | 0:84353c479782 | 565 | |
hudakz | 0:84353c479782 | 566 | void PS3USB::onInit() { |
hudakz | 0:84353c479782 | 567 | if(pFuncOnInit) |
hudakz | 0:84353c479782 | 568 | pFuncOnInit(); // Call the user function |
hudakz | 0:84353c479782 | 569 | else { |
hudakz | 0:84353c479782 | 570 | if(PS3MoveConnected) |
hudakz | 0:84353c479782 | 571 | moveSetBulb(Red); |
hudakz | 0:84353c479782 | 572 | else // Dualshock 3 or Navigation controller |
hudakz | 0:84353c479782 | 573 | setLedOn(static_cast<LEDEnum>(LED1)); |
hudakz | 0:84353c479782 | 574 | } |
hudakz | 0:84353c479782 | 575 | } |