Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PS3USB.cpp Source File

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 }