Exemple #1
0
uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
        uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
        uint8_t rcode;
        UsbDevice *p = NULL;
        EpInfo *oldep_ptr = NULL;
        uint16_t PID;
        uint16_t VID;

        // get memory address of USB device address pool
        AddressPool &addrPool = pUsb->GetAddressPool();
#ifdef EXTRADEBUG
        Notify(PSTR("\r\nPS3USB Init"), 0x80);
#endif
        // check if address has already been assigned to an instance
        if (bAddress) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nAddress in use"), 0x80);
#endif
                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
        }

        // Get pointer to pseudo device with address 0 assigned
        p = addrPool.GetUsbDevicePtr(0);

        if (!p) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nAddress not found"), 0x80);
#endif
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
        }

        if (!p->epinfo) {
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif
                return USB_ERROR_EPINFO_IS_NULL;
        }

        // Save old pointer to EP_RECORD of address 0
        oldep_ptr = p->epinfo;

        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
        p->epinfo = epInfo;

        p->lowspeed = lowspeed;

        // Get device descriptor
        rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
        // Restore p->epinfo
        p->epinfo = oldep_ptr;

        if (rcode)
                goto FailGetDevDescr;

        VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
        PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;

        if (VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID))
                goto FailUnknownDevice;

        // Allocate new address according to device class
        bAddress = addrPool.AllocAddress(parent, false, port);

        if (!bAddress)
                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;

        // Extract Max Packet Size from device descriptor
        epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;

        // Assign new address to the device
        rcode = pUsb->setAddr(0, 0, bAddress);
        if (rcode) {
                p->lowspeed = false;
                addrPool.FreeAddress(bAddress);
                bAddress = 0;
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nsetAddr: "), 0x80);
                D_PrintHex<uint8_t > (rcode, 0x80);
#endif
                return rcode;
        }
#ifdef EXTRADEBUG
        Notify(PSTR("\r\nAddr: "), 0x80);
        D_PrintHex<uint8_t > (bAddress, 0x80);
#endif
        delay(300); // Spec says you should wait at least 200ms
        
        p->lowspeed = false;

        //get pointer to assigned address record
        p = addrPool.GetUsbDevicePtr(bAddress);
        if (!p)
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;

        p->lowspeed = lowspeed;

        // Assign epInfo to epinfo pointer - only EP0 is known
        rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
        if (rcode)
                goto FailSetDevTblEntry;


        /* The application will work in reduced host mode, so we can save program and data
           memory space. After verifying the PID and VID we will use known values for the
           configuration values for device, interface, endpoints and HID for the PS3 Controllers */

        /* Initialize data structures for endpoints of device */
        epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint
        epInfo[ PS3_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT;
        epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
        epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
        epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0;
        epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0;
        epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint
        epInfo[ PS3_INPUT_PIPE ].epAttribs = EP_INTERRUPT;
        epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
        epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
        epInfo[ PS3_INPUT_PIPE ].bmSndToggle = bmSNDTOG0;
        epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0;

        rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
        if (rcode)
                goto FailSetDevTblEntry;

        delay(200); //Give time for address change

        rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1);
        if (rcode)
                goto FailSetConfDescr;

        if (PID == PS3_PID || PID == PS3NAVIGATION_PID) {
                if (PID == PS3_PID) {
#ifdef DEBUG_USB_HOST
                        Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
#endif
                        PS3Connected = true;
                } else { // must be a navigation controller
#ifdef DEBUG_USB_HOST
                        Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
#endif
                        PS3NavigationConnected = true;
                }
                enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data

                // Needed for PS3 Dualshock and Navigation commands to work
                for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
                        writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]);

                for (uint8_t i = 6; i < 10; i++)
                        readBuf[i] = 0x7F; // Set the analog joystick values to center position
        } else { // must be a Motion controller
#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
#endif
                PS3MoveConnected = true;
                writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work
        }
        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) {
                if (PS3MoveConnected)
                        setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
                else
                        setBdaddr(my_bdaddr); // Set internal Bluetooth address

#ifdef DEBUG_USB_HOST
                Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
                for (int8_t i = 5; i > 0; i--) {
                        D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
                        Notify(PSTR(":"), 0x80);
                }
                D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif
        }
        onInit();

        bPollEnable = true;
        Notify(PSTR("\r\n"), 0x80);
        timer = millis();
        return 0; // successful configuration

        /* diagnostic messages */
FailGetDevDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailGetDevDescr();
        goto Fail;
#endif
FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST
        NotifyFailSetDevTblEntry();
        goto Fail;
#endif

FailSetConfDescr:
#ifdef DEBUG_USB_HOST
        NotifyFailSetConfDescr();
#endif
        goto Fail;
FailUnknownDevice:
#ifdef DEBUG_USB_HOST
        NotifyFailUnknownDevice(VID, PID);
#endif
        rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
Fail:

#ifdef DEBUG_USB_HOST
        Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80);
        NotifyFail(rcode);
#endif
        Release();
        return rcode;
}
Exemple #2
0
uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
    uint8_t rcode;
    uint8_t num_of_conf = epInfo[1].epAddr; // Number of configurations
    epInfo[1].epAddr = 0;

    AddressPool &addrPool = pUsb->GetAddressPool();
#ifdef EXTRADEBUG
    Notify(PSTR("\r\nBTD Init"), 0x80);
#endif
    UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record

    if(!p) {
#ifdef DEBUG_USB_HOST
        Notify(PSTR("\r\nAddress not found"), 0x80);
#endif
        return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
    }

    delay(300); // Assign new address to the device

    rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device
    if(rcode) {
#ifdef DEBUG_USB_HOST
        Notify(PSTR("\r\nsetAddr: "), 0x80);
        D_PrintHex<uint8_t > (rcode, 0x80);
#endif
        p->lowspeed = false;
        goto Fail;
    }
#ifdef EXTRADEBUG
    Notify(PSTR("\r\nAddr: "), 0x80);
    D_PrintHex<uint8_t > (bAddress, 0x80);
#endif

    p->lowspeed = false;

    p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
    if(!p) {
#ifdef DEBUG_USB_HOST
        Notify(PSTR("\r\nAddress not found"), 0x80);
#endif
        return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
    }

    p->lowspeed = lowspeed;

    rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known
    if(rcode)
        goto FailSetDevTblEntry;

    if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) {
        delay(100);
        rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); // We only need the Control endpoint, so we don't have to initialize the other endpoints of device
        if(rcode)
            goto FailSetConfDescr;

#ifdef DEBUG_USB_HOST
        if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {
            if(PID == PS3_PID)
                Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
            else // It must be a navigation controller
                Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
        } else // It must be a Motion controller
            Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
#endif

        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) {
#ifdef DEBUG_USB_HOST
            Notify(PSTR("\r\nPlease plug in the dongle before trying to pair with the PS3 Controller\r\nor set the Bluetooth address in the constructor of the PS3BT class"), 0x80);
#endif
        } else {
            if(PID == PS3_PID || PID == PS3NAVIGATION_PID)
                setBdaddr(my_bdaddr); // Set internal Bluetooth address
            else
                setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
#ifdef DEBUG_USB_HOST
            Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
            for(int8_t i = 5; i > 0; i--) {
                D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
                Notify(PSTR(":"), 0x80);
            }
            D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif
        }

        pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value
        pUsb->setAddr(bAddress, 0, 0); // Reset address
        Release(); // Release device
        return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Return
    } else {
        // Check if attached device is a Bluetooth dongle and fill endpoint data structure
        // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
        // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order
        for(uint8_t i = 0; i < num_of_conf; i++) {
            if(VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) {
                ConfigDescParser<USB_CLASS_VENDOR_SPECIFIC, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Needed for the IOGEAR GBU521
                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
            } else {
                ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this);
                rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
            }
            if(rcode) // Check error code
                goto FailGetConfDescr;
            if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted
                break;
        }

        if(bNumEP < BTD_MAX_ENDPOINTS)
            goto FailUnknownDevice;

        // Assign epInfo to epinfo pointer - this time all 3 endpoins
        rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
        if(rcode)
            goto FailSetDevTblEntry;

        // Set Configuration Value
        rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum);
        if(rcode)
            goto FailSetConfDescr;

        hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command
        hci_counter = 0;
        hci_state = HCI_INIT_STATE;
        watingForConnection = false;
        bPollEnable = true;

#ifdef DEBUG_USB_HOST
        Notify(PSTR("\r\nBluetooth Dongle Initialized"), 0x80);
#endif
    }
    return 0; // Successful configuration

    /* Diagnostic messages */
FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST
    NotifyFailSetDevTblEntry();
    goto Fail;
#endif

FailGetConfDescr:
#ifdef DEBUG_USB_HOST
    NotifyFailGetConfDescr();
    goto Fail;
#endif

FailSetConfDescr:
#ifdef DEBUG_USB_HOST
    NotifyFailSetConfDescr();
#endif
    goto Fail;

FailUnknownDevice:
#ifdef DEBUG_USB_HOST
    NotifyFailUnknownDevice(VID, PID);
#endif
    pUsb->setAddr(bAddress, 0, 0); // Reset address
    rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
Fail:
#ifdef DEBUG_USB_HOST
    Notify(PSTR("\r\nBTD Init Failed, error code: "), 0x80);
    NotifyFail(rcode);
#endif
    Release();
    return rcode;
}