Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

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?

UserRevisionLine numberNew 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 }