Takumi Odashima / ArduinoUsbHostShield

Dependents:   USBHOST_PS5

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