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
00001 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved. 00002 00003 This software may be distributed and modified under the terms of the GNU 00004 General Public License version 2 (GPL2) as published by the Free Software 00005 Foundation and appearing in the file GPL2.TXT included in the packaging of 00006 this file. Please note that GPL2 Section 2[b] requires that all works based 00007 on this software must also be made publicly available under the terms of 00008 the GPL2 ("Copyleft"). 00009 00010 Contact information 00011 ------------------- 00012 00013 Kristian Lauszus, TKJ Electronics 00014 Web : http://www.tkjelectronics.com 00015 e-mail : kristianl@tkjelectronics.com 00016 */ 00017 00018 #include "PS3USB.h" 00019 // To enable serial debugging see "settings.h" 00020 //#define EXTRADEBUG // Uncomment to get even more debugging data 00021 //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers 00022 00023 PS3USB::PS3USB(Usb *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) : 00024 pUsb(p), // pointer to USB class instance - mandatory 00025 bAddress(0), // device address - mandatory 00026 bPollEnable(false) // don't start polling before dongle is connected 00027 { 00028 for(uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) { 00029 epInfo[i].epAddr = 0; 00030 epInfo[i].maxPktSize = (i) ? 0 : 8; 00031 epInfo[i].bmSndToggle = 0; 00032 epInfo[i].bmRcvToggle = 0; 00033 epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; 00034 } 00035 00036 if(pUsb) // register in USB subsystem 00037 pUsb->RegisterDeviceClass(this); //set devConfig[] entry 00038 00039 my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead 00040 my_bdaddr[4] = btadr4; 00041 my_bdaddr[3] = btadr3; 00042 my_bdaddr[2] = btadr2; 00043 my_bdaddr[1] = btadr1; 00044 my_bdaddr[0] = btadr0; 00045 } 00046 00047 uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { 00048 uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)]; 00049 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf); 00050 uint8_t rcode; 00051 UsbDevice *p = NULL; 00052 EpInfo *oldep_ptr = NULL; 00053 uint16_t PID; 00054 uint16_t VID; 00055 00056 // get memory address of USB device address pool 00057 AddressPool &addrPool = pUsb->GetAddressPool(); 00058 #ifdef EXTRADEBUG 00059 Notify(PSTR("\r\nPS3USB Init"), 0x80); 00060 #endif 00061 // check if address has already been assigned to an instance 00062 if(bAddress) { 00063 #ifdef DEBUG_USB_HOST 00064 Notify(PSTR("\r\nAddress in use"), 0x80); 00065 #endif 00066 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; 00067 } 00068 00069 // Get pointer to pseudo device with address 0 assigned 00070 p = addrPool.GetUsbDevicePtr(0); 00071 00072 if(!p) { 00073 #ifdef DEBUG_USB_HOST 00074 Notify(PSTR("\r\nAddress not found"), 0x80); 00075 #endif 00076 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00077 } 00078 00079 if(!p->epinfo) { 00080 #ifdef DEBUG_USB_HOST 00081 Notify(PSTR("\r\nepinfo is null"), 0x80); 00082 #endif 00083 return USB_ERROR_EPINFO_IS_NULL; 00084 } 00085 00086 // Save old pointer to EP_RECORD of address 0 00087 oldep_ptr = p->epinfo; 00088 00089 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence 00090 p->epinfo = epInfo; 00091 00092 p->lowspeed = lowspeed; 00093 00094 // Get device descriptor 00095 rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data 00096 // Restore p->epinfo 00097 p->epinfo = oldep_ptr; 00098 00099 if(rcode) 00100 goto FailGetDevDescr; 00101 00102 VID = udd->idVendor; 00103 PID = udd->idProduct; 00104 00105 if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID)) 00106 goto FailUnknownDevice; 00107 00108 // Allocate new address according to device class 00109 bAddress = addrPool.AllocAddress(parent, false, port); 00110 00111 if(!bAddress) 00112 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; 00113 00114 // Extract Max Packet Size from device descriptor 00115 epInfo[0].maxPktSize = udd->bMaxPacketSize0; 00116 00117 // Assign new address to the device 00118 rcode = pUsb->setAddr(0, 0, bAddress); 00119 if(rcode) { 00120 p->lowspeed = false; 00121 addrPool.FreeAddress(bAddress); 00122 bAddress = 0; 00123 #ifdef DEBUG_USB_HOST 00124 Notify(PSTR("\r\nsetAddr: "), 0x80); 00125 D_PrintHex<uint8_t > (rcode, 0x80); 00126 #endif 00127 return rcode; 00128 } 00129 #ifdef EXTRADEBUG 00130 Notify(PSTR("\r\nAddr: "), 0x80); 00131 D_PrintHex<uint8_t > (bAddress, 0x80); 00132 #endif 00133 //wait_ms(300); // Spec says you should wait at least 200ms 00134 00135 p->lowspeed = false; 00136 00137 //get pointer to assigned address record 00138 p = addrPool.GetUsbDevicePtr(bAddress); 00139 if(!p) 00140 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; 00141 00142 p->lowspeed = lowspeed; 00143 00144 // Assign epInfo to epinfo pointer - only EP0 is known 00145 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); 00146 if(rcode) 00147 goto FailSetDevTblEntry; 00148 00149 00150 /* The application will work in reduced host mode, so we can save program and data 00151 memory space. After verifying the PID and VID we will use known values for the 00152 configuration values for device, interface, endpoints and HID for the PS3 Controllers */ 00153 00154 /* Initialize data structures for endpoints of device */ 00155 epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint 00156 epInfo[ PS3_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00157 epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00158 epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; 00159 epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = 0; 00160 epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = 0; 00161 epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint 00162 epInfo[ PS3_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT; 00163 epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints 00164 epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; 00165 epInfo[ PS3_INPUT_PIPE ].bmSndToggle = 0; 00166 epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = 0; 00167 00168 rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); 00169 if(rcode) 00170 goto FailSetDevTblEntry; 00171 00172 wait_ms(200); //Give time for address change 00173 00174 rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1); 00175 if(rcode) 00176 goto FailSetConfDescr; 00177 00178 if(PID == PS3_PID || PID == PS3NAVIGATION_PID) { 00179 if(PID == PS3_PID) { 00180 #ifdef DEBUG_USB_HOST 00181 Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); 00182 #endif 00183 PS3Connected = true; 00184 } else { // must be a navigation controller 00185 #ifdef DEBUG_USB_HOST 00186 Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); 00187 #endif 00188 PS3NavigationConnected = true; 00189 } 00190 enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data 00191 00192 // Needed for PS3 Dualshock and Navigation commands to work 00193 for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) 00194 writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); 00195 00196 for(uint8_t i = 6; i < 10; i++) 00197 readBuf[i] = 0x7F; // Set the analog joystick values to center position 00198 } else { // must be a Motion controller 00199 #ifdef DEBUG_USB_HOST 00200 Notify(PSTR("\r\nMotion Controller Connected"), 0x80); 00201 #endif 00202 PS3MoveConnected = true; 00203 writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work 00204 } 00205 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) { 00206 if(PS3MoveConnected) 00207 setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address 00208 else 00209 setBdaddr(my_bdaddr); // Set internal Bluetooth address 00210 00211 #ifdef DEBUG_USB_HOST 00212 Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); 00213 for(int8_t i = 5; i > 0; i--) { 00214 D_PrintHex<uint8_t > (my_bdaddr[i], 0x80); 00215 Notify(PSTR(":"), 0x80); 00216 } 00217 D_PrintHex<uint8_t > (my_bdaddr[0], 0x80); 00218 #endif 00219 } 00220 onInit(); 00221 00222 bPollEnable = true; 00223 Notify(PSTR("\r\n"), 0x80); 00224 timer = (uint32_t)millis(); 00225 return 0; // Successful configuration 00226 00227 /* Diagnostic messages */ 00228 FailGetDevDescr: 00229 #ifdef DEBUG_USB_HOST 00230 NotifyFailGetDevDescr(); 00231 goto Fail; 00232 #endif 00233 00234 FailSetDevTblEntry: 00235 #ifdef DEBUG_USB_HOST 00236 NotifyFailSetDevTblEntry(); 00237 goto Fail; 00238 #endif 00239 00240 FailSetConfDescr: 00241 #ifdef DEBUG_USB_HOST 00242 NotifyFailSetConfDescr(); 00243 #endif 00244 goto Fail; 00245 00246 FailUnknownDevice: 00247 #ifdef DEBUG_USB_HOST 00248 NotifyFailUnknownDevice(VID, PID); 00249 #endif 00250 rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; 00251 00252 Fail: 00253 #ifdef DEBUG_USB_HOST 00254 Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80); 00255 NotifyFail(rcode); 00256 #endif 00257 Release(); 00258 return rcode; 00259 } 00260 00261 /* Performs a cleanup after failed Init() attempt */ 00262 uint8_t PS3USB::Release() { 00263 PS3Connected = false; 00264 PS3MoveConnected = false; 00265 PS3NavigationConnected = false; 00266 pUsb->GetAddressPool().FreeAddress(bAddress); 00267 bAddress = 0; 00268 bPollEnable = false; 00269 return 0; 00270 } 00271 00272 uint8_t PS3USB::Poll() { 00273 if(!bPollEnable) 00274 return 0; 00275 00276 if(PS3Connected || PS3NavigationConnected) { 00277 uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; 00278 pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 00279 if((int32_t)((uint32_t)millis() - timer) > 100) { // Loop 100ms before processing data 00280 readReport(); 00281 #ifdef PRINTREPORT 00282 printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers 00283 #endif 00284 } 00285 } 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 00286 if((int32_t)((uint32_t)millis() - timer) > 4000) { // Send at least every 4th second 00287 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 00288 timer = (uint32_t)millis(); 00289 } 00290 } 00291 return 0; 00292 } 00293 00294 void PS3USB::readReport() { 00295 ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); 00296 00297 //Notify(PSTR("\r\nButtonState", 0x80); 00298 //PrintHex<uint32_t>(ButtonState, 0x80); 00299 00300 if(ButtonState != OldButtonState) { 00301 ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable 00302 OldButtonState = ButtonState; 00303 } 00304 } 00305 00306 void PS3USB::printReport() { // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers 00307 #ifdef PRINTREPORT 00308 for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) { 00309 D_PrintHex<uint8_t > (readBuf[i], 0x80); 00310 Notify(PSTR(" "), 0x80); 00311 } 00312 Notify(PSTR("\r\n"), 0x80); 00313 #endif 00314 } 00315 00316 bool PS3USB::getButtonPress(ButtonEnum b) { 00317 return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b])); 00318 } 00319 00320 bool PS3USB::getButtonClick(ButtonEnum b) { 00321 uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]); 00322 bool click = (ButtonClickState & button); 00323 ButtonClickState &= ~button; // Clear "click" event 00324 return click; 00325 } 00326 00327 uint8_t PS3USB::getAnalogButton(ButtonEnum a) { 00328 return (uint8_t)(readBuf[(pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])) - 9]); 00329 } 00330 00331 uint8_t PS3USB::getAnalogHat(AnalogHatEnum a) { 00332 return (uint8_t)(readBuf[((uint8_t)a + 6)]); 00333 } 00334 00335 uint16_t PS3USB::getSensor(SensorEnum a) { 00336 return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]); 00337 } 00338 00339 float PS3USB::getAngle(AngleEnum a) { 00340 if(PS3Connected) { 00341 float accXval, accYval, accZval; 00342 00343 // Data for the Kionix KXPC4 used in the DualShock 3 00344 const float zeroG = 511.5f; // 1.65/3.3*1023 (1,65V) 00345 accXval = -((float)getSensor(aX) - zeroG); 00346 accYval = -((float)getSensor(aY) - zeroG); 00347 accZval = -((float)getSensor(aZ) - zeroG); 00348 00349 // Convert to 360 degrees resolution 00350 // atan2 outputs the value of -π to π (radians) 00351 // We are then converting it to 0 to 2π and then to degrees 00352 if(a == Pitch) 00353 return (atan2f(accYval, accZval) + M_PI) * RAD_TO_DEG; 00354 else 00355 return (atan2f(accXval, accZval) + M_PI) * RAD_TO_DEG; 00356 } else 00357 return 0; 00358 } 00359 00360 bool PS3USB::getStatus(StatusEnum c) { 00361 return (readBuf[((uint16_t)c >> 8) - 9] == ((uint8_t)c & 0xff)); 00362 } 00363 00364 void PS3USB::printStatusString() { 00365 char statusOutput[102]; // Max string length plus null character 00366 if(PS3Connected || PS3NavigationConnected) { 00367 strcpy_P(statusOutput, PSTR("\r\nConnectionStatus: ")); 00368 00369 if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged")); 00370 else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged")); 00371 else strcat_P(statusOutput, PSTR("Error")); 00372 00373 strcat_P(statusOutput, PSTR(" - PowerRating: ")); 00374 00375 if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging")); 00376 else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging")); 00377 else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown")); 00378 else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying")); 00379 else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low")); 00380 else if(getStatus(High)) strcat_P(statusOutput, PSTR("High")); 00381 else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full")); 00382 else strcat_P(statusOutput, PSTR("Error")); 00383 00384 strcat_P(statusOutput, PSTR(" - WirelessStatus: ")); 00385 00386 if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on")); 00387 else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off")); 00388 else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on")); 00389 else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off")); 00390 else strcat_P(statusOutput, PSTR("Error")); 00391 } else 00392 strcpy_P(statusOutput, PSTR("\r\nError")); 00393 #ifndef __MBED__ 00394 USB_HOST_SERIAL.write(statusOutput); 00395 #endif 00396 } 00397 00398 /* Playstation Sixaxis Dualshock and Navigation Controller commands */ 00399 void PS3USB::PS3_Command(uint8_t *data, uint16_t nbytes) { 00400 // 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) 00401 pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); 00402 } 00403 00404 void PS3USB::setAllOff() { 00405 for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) 00406 writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer 00407 00408 PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); 00409 } 00410 00411 void PS3USB::setRumbleOff() { 00412 uint8_t rumbleBuf[EP_MAXPKTSIZE]; 00413 memcpy(rumbleBuf, writeBuf, EP_MAXPKTSIZE); 00414 rumbleBuf[1] = 0x00; 00415 rumbleBuf[2] = 0x00; // Low mode off 00416 rumbleBuf[3] = 0x00; 00417 rumbleBuf[4] = 0x00; // High mode off 00418 PS3_Command(rumbleBuf, PS3_REPORT_BUFFER_SIZE); 00419 } 00420 00421 void PS3USB::setRumbleOn(RumbleEnum mode) { 00422 if((mode & 0x30) > 0x00) { 00423 uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow 00424 if(mode == RumbleHigh) { 00425 power[0] = 0x00; 00426 power[1] = 0xff; 00427 } 00428 setRumbleOn(0xfe, power[0], 0xfe, power[1]); 00429 } 00430 } 00431 00432 void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) { 00433 uint8_t rumbleBuf[EP_MAXPKTSIZE]; 00434 memcpy(rumbleBuf, writeBuf, EP_MAXPKTSIZE); 00435 rumbleBuf[1] = rightDuration; 00436 rumbleBuf[2] = rightPower; 00437 rumbleBuf[3] = leftDuration; 00438 rumbleBuf[4] = leftPower; 00439 PS3_Command(rumbleBuf, PS3_REPORT_BUFFER_SIZE); 00440 } 00441 00442 void PS3USB::setLedRaw(uint8_t value) { 00443 writeBuf[9] = value << 1; 00444 PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); 00445 } 00446 00447 void PS3USB::setLedOff(LEDEnum a) { 00448 writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1)); 00449 PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); 00450 } 00451 00452 void PS3USB::setLedOn(LEDEnum a) { 00453 if(a == OFF) 00454 setLedRaw(0); 00455 else { 00456 writeBuf[9] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); 00457 PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); 00458 } 00459 } 00460 00461 void PS3USB::setLedToggle(LEDEnum a) { 00462 writeBuf[9] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1); 00463 PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); 00464 } 00465 00466 void PS3USB::setBdaddr(uint8_t *bdaddr) { 00467 /* Set the internal Bluetooth address */ 00468 uint8_t buf[8]; 00469 buf[0] = 0x01; 00470 buf[1] = 0x00; 00471 00472 for(uint8_t i = 0; i < 6; i++) 00473 buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first 00474 00475 // 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 00476 pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); 00477 } 00478 00479 void PS3USB::getBdaddr(uint8_t *bdaddr) { 00480 uint8_t buf[8]; 00481 00482 // 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 00483 pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); 00484 00485 for(uint8_t i = 0; i < 6; i++) 00486 bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first 00487 } 00488 00489 void PS3USB::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via USB 00490 uint8_t cmd_buf[4]; 00491 cmd_buf[0] = 0x42; // Special PS3 Controller enable commands 00492 cmd_buf[1] = 0x0c; 00493 cmd_buf[2] = 0x00; 00494 cmd_buf[3] = 0x00; 00495 00496 // 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) 00497 pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); 00498 } 00499 00500 /* Playstation Move Controller commands */ 00501 void PS3USB::Move_Command(uint8_t *data, uint16_t nbytes) { 00502 pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); 00503 } 00504 00505 void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values 00506 // Set the Bulb's values into the write buffer 00507 writeBuf[2] = r; 00508 writeBuf[3] = g; 00509 writeBuf[4] = b; 00510 00511 Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); 00512 } 00513 00514 void PS3USB::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in "enums.h" 00515 moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color)); 00516 } 00517 00518 void PS3USB::moveSetRumble(uint8_t rumble) { 00519 #ifdef DEBUG_USB_HOST 00520 if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) 00521 Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); 00522 #endif 00523 writeBuf[6] = rumble; // Set the rumble value into the write buffer 00524 00525 Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); 00526 } 00527 00528 void PS3USB::setMoveBdaddr(uint8_t *bdaddr) { 00529 /* Set the internal Bluetooth address */ 00530 uint8_t buf[11]; 00531 buf[0] = 0x05; 00532 buf[7] = 0x10; 00533 buf[8] = 0x01; 00534 buf[9] = 0x02; 00535 buf[10] = 0x12; 00536 00537 for(uint8_t i = 0; i < 6; i++) 00538 buf[i + 1] = bdaddr[i]; 00539 00540 // 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 00541 pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL); 00542 } 00543 00544 void PS3USB::getMoveBdaddr(uint8_t *bdaddr) { 00545 uint8_t buf[16]; 00546 00547 // 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 00548 pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL); 00549 00550 for(uint8_t i = 0; i < 6; i++) 00551 bdaddr[i] = buf[10 + i]; 00552 } 00553 00554 void PS3USB::getMoveCalibration(uint8_t *data) { 00555 uint8_t buf[49]; 00556 00557 for(uint8_t i = 0; i < 3; i++) { 00558 // 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 00559 pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL); 00560 00561 for(uint8_t j = 0; j < 49; j++) 00562 data[49 * i + j] = buf[j]; 00563 } 00564 } 00565 00566 void PS3USB::onInit() { 00567 if(pFuncOnInit) 00568 pFuncOnInit(); // Call the user function 00569 else { 00570 if(PS3MoveConnected) 00571 moveSetBulb(Red); 00572 else // Dualshock 3 or Navigation controller 00573 setLedOn(static_cast<LEDEnum>(LED1)); 00574 } 00575 }
Generated on Tue Jul 12 2022 18:12:04 by
1.7.2