Library to use Arduino USB host shield on mbed

Dependents:   USBHOST_PS5

ArduinoのUSB Host Shield 2.0をmbedで使えるようにしたライブラリです。
大体のコードがArduinoからそのまま移植可能です。

Arduino UNOやMega用のホストシールド以外にもミニサイズのホストシールドでも使用可能です https://os.mbed.com/media/uploads/kotakku/dffgfddswa.png

シールドについて

3.3VのI/O用にシールドの改造が必要になりますがネット上に記事がたくさんあるのでそちらを参考にしてください

接続例

https://os.mbed.com/media/uploads/kotakku/esgsvfvhjrekldkcjxvb.png

使い方

Arduinoのコードと違うのはUSBのインスタンスの宣言部分のみです。
ピンを自分で指定できるようにしたので使いやすくなりました。

仕様

  • Arduinoのmillis関数、micros関数の移植のために内部でTimerクラスを使用しています。

main.cpp

#include "mbed.h"
#include <PS3BT.h>
#include <usbhub.h>

Serial pc(USBTX, USBRX, 115200);

//Nucleo f303k8用
USB Usb(A6, A5, A4, A3, A2); // mosi, miso, sclk, ssel, intr
BTD Btd(&Usb);
PS3BT PS3(&Btd);

int main()
{
    bool printAngle = false;

    if (Usb.Init() == -1)
    {
        pc.printf("\r\nOSC did not start");
        while (1); // Halt
    }
    pc.printf("\r\nPS3 USB Library Started");

    while (1)
    {
        Usb.Task();
        
        if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
            if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117)
            {
                pc.printf("\r\nLeftHatX: %d", PS3.getAnalogHat(LeftHatX));
                pc.printf("\tLeftHatY: %d", PS3.getAnalogHat(LeftHatY));
                if (PS3.PS3Connected)
                { // The Navigation controller only have one joystick
                    pc.printf("\tRightHatX: %d", PS3.getAnalogHat(RightHatX));
                    pc.printf("\tRightHatY: %d", PS3.getAnalogHat(RightHatY));
                }
            }
            // Analog button values can be read from almost all buttons
            if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2))
            {
                pc.printf("\r\nL2: %d", PS3.getAnalogButton(L2));
                if (!PS3.PS3NavigationConnected)
                {
                    pc.printf("\tR2: %d", PS3.getAnalogButton(R2));
                }
            }
            if (PS3.getButtonClick(PS))
            {
                PS3.disconnect();
                pc.printf("\r\nPS");
            }
    
            if (PS3.getButtonClick(TRIANGLE))
                pc.printf("\r\nTriangle");
            if (PS3.getButtonClick(CIRCLE))
                pc.printf("\r\nCircle");
            if (PS3.getButtonClick(CROSS))
                pc.printf("\r\nCross");
            if (PS3.getButtonClick(SQUARE))
                pc.printf("\r\nSquare");
    
            if (PS3.getButtonClick(UP))
            {
                pc.printf("\r\nUp");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED4);
            }
            if (PS3.getButtonClick(RIGHT))
            {
                pc.printf("\r\nRight");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED1);
            }
            if (PS3.getButtonClick(DOWN))
            {
                pc.printf("\r\nDown");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED2);
            }
            if (PS3.getButtonClick(LEFT))
            {
                pc.printf("\r\nLeft");
                PS3.setLedOff();
                PS3.setLedOn(CONTROLLER_LED3);
            }
    
            if (PS3.getButtonClick(L1))
                pc.printf("\r\nL1");
            if (PS3.getButtonClick(L3))
                pc.printf("\r\nL3");
            if (PS3.getButtonClick(R1))
                pc.printf("\r\nR1");
            if (PS3.getButtonClick(R3))
                pc.printf("\r\nR3");
    
            if (PS3.getButtonClick(SELECT))
            {
                pc.printf("\r\nSelect - ");
                PS3.printStatusString();
            }
            if (PS3.getButtonClick(START))
            {
                pc.printf("\r\nStart");
                printAngle = !printAngle;
            }
            if (printAngle)
            {
                pc.printf("\r\nPitch: %.3lf", PS3.getAngle(Pitch));
                pc.printf("\tRoll: %.3lf", PS3.getAngle(Roll));
            }
        }
        else
        {
            pc.printf("not connect\n");
        }
    }
}
Committer:
robo_ichinoseki_a
Date:
Sat May 02 05:56:48 2020 +0000
Revision:
1:da31140f2a1c
Parent:
0:b1ce54272580
update

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kotakku 0:b1ce54272580 1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
kotakku 0:b1ce54272580 2
kotakku 0:b1ce54272580 3 This software may be distributed and modified under the terms of the GNU
kotakku 0:b1ce54272580 4 General Public License version 2 (GPL2) as published by the Free Software
kotakku 0:b1ce54272580 5 Foundation and appearing in the file GPL2.TXT included in the packaging of
kotakku 0:b1ce54272580 6 this file. Please note that GPL2 Section 2[b] requires that all works based
kotakku 0:b1ce54272580 7 on this software must also be made publicly available under the terms of
kotakku 0:b1ce54272580 8 the GPL2 ("Copyleft").
kotakku 0:b1ce54272580 9
kotakku 0:b1ce54272580 10 Contact information
kotakku 0:b1ce54272580 11 -------------------
kotakku 0:b1ce54272580 12
kotakku 0:b1ce54272580 13 Circuits At Home, LTD
kotakku 0:b1ce54272580 14 Web : http://www.circuitsathome.com
kotakku 0:b1ce54272580 15 e-mail : support@circuitsathome.com
kotakku 0:b1ce54272580 16 */
kotakku 0:b1ce54272580 17 /* USB functions */
kotakku 0:b1ce54272580 18
kotakku 0:b1ce54272580 19 // warning
kotakku 0:b1ce54272580 20 // #define _usb_h_
kotakku 0:b1ce54272580 21 // #define MBED_H
kotakku 0:b1ce54272580 22
kotakku 0:b1ce54272580 23 #include "Usb.h"
kotakku 0:b1ce54272580 24
robo_ichinoseki_a 1:da31140f2a1c 25 Timer USB::arduinoTimer;
robo_ichinoseki_a 1:da31140f2a1c 26
kotakku 0:b1ce54272580 27 static uint8_t usb_error = 0;
kotakku 0:b1ce54272580 28 static uint8_t usb_task_state;
kotakku 0:b1ce54272580 29
kotakku 0:b1ce54272580 30 /* constructor */
kotakku 0:b1ce54272580 31 USB::USB(PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName intr) :
kotakku 0:b1ce54272580 32 MAX3421E(mosi, miso, sclk, ssel, intr),
kotakku 0:b1ce54272580 33 bmHubPre(0)
kotakku 0:b1ce54272580 34 {
kotakku 0:b1ce54272580 35 arduinoTimer.start();
kotakku 0:b1ce54272580 36 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
kotakku 0:b1ce54272580 37 init();
kotakku 0:b1ce54272580 38 }
kotakku 0:b1ce54272580 39
kotakku 0:b1ce54272580 40
kotakku 0:b1ce54272580 41 /* Initialize data structures */
kotakku 0:b1ce54272580 42 void USB::init()
kotakku 0:b1ce54272580 43 {
kotakku 0:b1ce54272580 44 //devConfigIndex = 0;
kotakku 0:b1ce54272580 45 bmHubPre = 0;
kotakku 0:b1ce54272580 46 }
kotakku 0:b1ce54272580 47
kotakku 0:b1ce54272580 48 uint8_t USB::getUsbTaskState(void)
kotakku 0:b1ce54272580 49 {
kotakku 0:b1ce54272580 50 return (usb_task_state);
kotakku 0:b1ce54272580 51 }
kotakku 0:b1ce54272580 52
kotakku 0:b1ce54272580 53 void USB::setUsbTaskState(uint8_t state)
kotakku 0:b1ce54272580 54 {
kotakku 0:b1ce54272580 55 usb_task_state = state;
kotakku 0:b1ce54272580 56 }
kotakku 0:b1ce54272580 57
kotakku 0:b1ce54272580 58 EpInfo *USB::getEpInfoEntry(uint8_t addr, uint8_t ep)
kotakku 0:b1ce54272580 59 {
kotakku 0:b1ce54272580 60 UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
kotakku 0:b1ce54272580 61
kotakku 0:b1ce54272580 62 if (!p || !p->epinfo)
kotakku 0:b1ce54272580 63 return NULL;
kotakku 0:b1ce54272580 64
kotakku 0:b1ce54272580 65 EpInfo *pep = p->epinfo;
kotakku 0:b1ce54272580 66
kotakku 0:b1ce54272580 67 for (uint8_t i = 0; i < p->epcount; i++)
kotakku 0:b1ce54272580 68 {
kotakku 0:b1ce54272580 69 if ((pep)->epAddr == ep)
kotakku 0:b1ce54272580 70 return pep;
kotakku 0:b1ce54272580 71
kotakku 0:b1ce54272580 72 pep++;
kotakku 0:b1ce54272580 73 }
kotakku 0:b1ce54272580 74 return NULL;
kotakku 0:b1ce54272580 75 }
kotakku 0:b1ce54272580 76
kotakku 0:b1ce54272580 77 /* set device table entry */
kotakku 0:b1ce54272580 78
kotakku 0:b1ce54272580 79 /* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
kotakku 0:b1ce54272580 80 uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
kotakku 0:b1ce54272580 81 {
kotakku 0:b1ce54272580 82 if (!eprecord_ptr)
kotakku 0:b1ce54272580 83 return USB_ERROR_INVALID_ARGUMENT;
kotakku 0:b1ce54272580 84
kotakku 0:b1ce54272580 85 UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
kotakku 0:b1ce54272580 86
kotakku 0:b1ce54272580 87 if (!p)
kotakku 0:b1ce54272580 88 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 89
kotakku 0:b1ce54272580 90 p->address.devAddress = addr;
kotakku 0:b1ce54272580 91 p->epinfo = eprecord_ptr;
kotakku 0:b1ce54272580 92 p->epcount = epcount;
kotakku 0:b1ce54272580 93
kotakku 0:b1ce54272580 94 return 0;
kotakku 0:b1ce54272580 95 }
kotakku 0:b1ce54272580 96
kotakku 0:b1ce54272580 97 uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit)
kotakku 0:b1ce54272580 98 {
kotakku 0:b1ce54272580 99 UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
kotakku 0:b1ce54272580 100
kotakku 0:b1ce54272580 101 if (!p)
kotakku 0:b1ce54272580 102 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 103
kotakku 0:b1ce54272580 104 if (!p->epinfo)
kotakku 0:b1ce54272580 105 return USB_ERROR_EPINFO_IS_NULL;
kotakku 0:b1ce54272580 106
kotakku 0:b1ce54272580 107 *ppep = getEpInfoEntry(addr, ep);
kotakku 0:b1ce54272580 108
kotakku 0:b1ce54272580 109 if (!*ppep)
kotakku 0:b1ce54272580 110 return USB_ERROR_EP_NOT_FOUND_IN_TBL;
kotakku 0:b1ce54272580 111
kotakku 0:b1ce54272580 112 *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
kotakku 0:b1ce54272580 113 (*nak_limit)--;
kotakku 0:b1ce54272580 114 /*
kotakku 0:b1ce54272580 115 USBTRACE2("\r\nAddress: ", addr);
kotakku 0:b1ce54272580 116 USBTRACE2(" EP: ", ep);
kotakku 0:b1ce54272580 117 USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower);
kotakku 0:b1ce54272580 118 USBTRACE2(" NAK Limit: ", nak_limit);
kotakku 0:b1ce54272580 119 USBTRACE("\r\n");
kotakku 0:b1ce54272580 120 */
kotakku 0:b1ce54272580 121 regWr(rPERADDR, addr); //set peripheral address
kotakku 0:b1ce54272580 122
kotakku 0:b1ce54272580 123 uint8_t mode = regRd(rMODE);
kotakku 0:b1ce54272580 124
kotakku 0:b1ce54272580 125 //Serial.print("\r\nMode: ");
kotakku 0:b1ce54272580 126 //Serial.println( mode, HEX);
kotakku 0:b1ce54272580 127 //Serial.print("\r\nLS: ");
kotakku 0:b1ce54272580 128 //Serial.println(p->lowspeed, HEX);
kotakku 0:b1ce54272580 129
kotakku 0:b1ce54272580 130 // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise
kotakku 0:b1ce54272580 131 regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED));
kotakku 0:b1ce54272580 132
kotakku 0:b1ce54272580 133 return 0;
kotakku 0:b1ce54272580 134 }
kotakku 0:b1ce54272580 135
kotakku 0:b1ce54272580 136 /* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
kotakku 0:b1ce54272580 137 /* depending on request. Actual requests are defined as inlines */
kotakku 0:b1ce54272580 138 /* return codes: */
kotakku 0:b1ce54272580 139 /* 00 = success */
kotakku 0:b1ce54272580 140
kotakku 0:b1ce54272580 141 /* 01-0f = non-zero HRSLT */
kotakku 0:b1ce54272580 142 uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
kotakku 0:b1ce54272580 143 uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t *dataptr, USBReadParser *p)
kotakku 0:b1ce54272580 144 {
kotakku 0:b1ce54272580 145 bool direction = false; //request direction, IN or OUT
kotakku 0:b1ce54272580 146 uint8_t rcode;
kotakku 0:b1ce54272580 147 SETUP_PKT setup_pkt;
kotakku 0:b1ce54272580 148
kotakku 0:b1ce54272580 149 EpInfo *pep = NULL;
kotakku 0:b1ce54272580 150 uint16_t nak_limit = 0;
kotakku 0:b1ce54272580 151
kotakku 0:b1ce54272580 152 rcode = SetAddress(addr, ep, &pep, &nak_limit);
kotakku 0:b1ce54272580 153
kotakku 0:b1ce54272580 154 if (rcode)
kotakku 0:b1ce54272580 155 return rcode;
kotakku 0:b1ce54272580 156
kotakku 0:b1ce54272580 157 direction = ((bmReqType & 0x80) > 0);
kotakku 0:b1ce54272580 158
kotakku 0:b1ce54272580 159 /* fill in setup packet */
kotakku 0:b1ce54272580 160 setup_pkt.ReqType_u.bmRequestType = bmReqType;
kotakku 0:b1ce54272580 161 setup_pkt.bRequest = bRequest;
kotakku 0:b1ce54272580 162 setup_pkt.wVal_u.wValueLo = wValLo;
kotakku 0:b1ce54272580 163 setup_pkt.wVal_u.wValueHi = wValHi;
kotakku 0:b1ce54272580 164 setup_pkt.wIndex = wInd;
kotakku 0:b1ce54272580 165 setup_pkt.wLength = total;
kotakku 0:b1ce54272580 166
kotakku 0:b1ce54272580 167 bytesWr(rSUDFIFO, 8, (uint8_t *)&setup_pkt); //transfer to setup packet FIFO
kotakku 0:b1ce54272580 168
kotakku 0:b1ce54272580 169 rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
kotakku 0:b1ce54272580 170
kotakku 0:b1ce54272580 171 if (rcode) //return HRSLT if not zero
kotakku 0:b1ce54272580 172 return (rcode);
kotakku 0:b1ce54272580 173
kotakku 0:b1ce54272580 174 if (dataptr != NULL) //data stage, if present
kotakku 0:b1ce54272580 175 {
kotakku 0:b1ce54272580 176 if (direction) //IN transfer
kotakku 0:b1ce54272580 177 {
kotakku 0:b1ce54272580 178 uint16_t left = total;
kotakku 0:b1ce54272580 179
kotakku 0:b1ce54272580 180 pep->bmRcvToggle = 1; //bmRCVTOG1;
kotakku 0:b1ce54272580 181
kotakku 0:b1ce54272580 182 while (left)
kotakku 0:b1ce54272580 183 {
kotakku 0:b1ce54272580 184 // Bytes read into buffer
kotakku 0:b1ce54272580 185 #if defined(ESP8266) || defined(ESP32)
kotakku 0:b1ce54272580 186 yield(); // needed in order to reset the watchdog timer on the ESP8266
kotakku 0:b1ce54272580 187 #endif
kotakku 0:b1ce54272580 188 uint16_t read = nbytes;
kotakku 0:b1ce54272580 189 //uint16_t read = (left<nbytes) ? left : nbytes;
kotakku 0:b1ce54272580 190
kotakku 0:b1ce54272580 191 rcode = InTransfer(pep, nak_limit, &read, dataptr);
kotakku 0:b1ce54272580 192 if (rcode == hrTOGERR)
kotakku 0:b1ce54272580 193 {
kotakku 0:b1ce54272580 194 // yes, we flip it wrong here so that next time it is actually correct!
kotakku 0:b1ce54272580 195 pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
kotakku 0:b1ce54272580 196 continue;
kotakku 0:b1ce54272580 197 }
kotakku 0:b1ce54272580 198
kotakku 0:b1ce54272580 199 if (rcode)
kotakku 0:b1ce54272580 200 return rcode;
kotakku 0:b1ce54272580 201
kotakku 0:b1ce54272580 202 // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
kotakku 0:b1ce54272580 203 if (!rcode && p)
kotakku 0:b1ce54272580 204 ((USBReadParser *)p)->Parse(read, dataptr, total - left);
kotakku 0:b1ce54272580 205
kotakku 0:b1ce54272580 206 left -= read;
kotakku 0:b1ce54272580 207
kotakku 0:b1ce54272580 208 if (read < nbytes)
kotakku 0:b1ce54272580 209 break;
kotakku 0:b1ce54272580 210 }
kotakku 0:b1ce54272580 211 }
kotakku 0:b1ce54272580 212 else //OUT transfer
kotakku 0:b1ce54272580 213 {
kotakku 0:b1ce54272580 214 pep->bmSndToggle = 1; //bmSNDTOG1;
kotakku 0:b1ce54272580 215 rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
kotakku 0:b1ce54272580 216 }
kotakku 0:b1ce54272580 217 if (rcode) //return error
kotakku 0:b1ce54272580 218 return (rcode);
kotakku 0:b1ce54272580 219 }
kotakku 0:b1ce54272580 220 // Status stage
kotakku 0:b1ce54272580 221 return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
kotakku 0:b1ce54272580 222 }
kotakku 0:b1ce54272580 223
kotakku 0:b1ce54272580 224 /* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
kotakku 0:b1ce54272580 225 /* Keep sending INs and writes data to memory area pointed by 'data' */
kotakku 0:b1ce54272580 226
kotakku 0:b1ce54272580 227 /* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
kotakku 0:b1ce54272580 228 fe USB xfer timeout */
kotakku 0:b1ce54272580 229 uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval /*= 0*/)
kotakku 0:b1ce54272580 230 {
kotakku 0:b1ce54272580 231 EpInfo *pep = NULL;
kotakku 0:b1ce54272580 232 uint16_t nak_limit = 0;
kotakku 0:b1ce54272580 233
kotakku 0:b1ce54272580 234 uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
kotakku 0:b1ce54272580 235
kotakku 0:b1ce54272580 236 if (rcode)
kotakku 0:b1ce54272580 237 {
kotakku 0:b1ce54272580 238 USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
kotakku 0:b1ce54272580 239 USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
kotakku 0:b1ce54272580 240 USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
kotakku 0:b1ce54272580 241 return rcode;
kotakku 0:b1ce54272580 242 }
kotakku 0:b1ce54272580 243 return InTransfer(pep, nak_limit, nbytesptr, data, bInterval);
kotakku 0:b1ce54272580 244 }
kotakku 0:b1ce54272580 245
kotakku 0:b1ce54272580 246 uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval /*= 0*/)
kotakku 0:b1ce54272580 247 {
kotakku 0:b1ce54272580 248 uint8_t rcode = 0;
kotakku 0:b1ce54272580 249 uint8_t pktsize;
kotakku 0:b1ce54272580 250
kotakku 0:b1ce54272580 251 uint16_t nbytes = *nbytesptr;
kotakku 0:b1ce54272580 252 //DEBUG("Requesting %i bytes ", nbytes);
kotakku 0:b1ce54272580 253 uint8_t maxpktsize = pep->maxPktSize;
kotakku 0:b1ce54272580 254
kotakku 0:b1ce54272580 255 *nbytesptr = 0;
kotakku 0:b1ce54272580 256 regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
kotakku 0:b1ce54272580 257
kotakku 0:b1ce54272580 258 // use a 'break' to exit this loop
kotakku 0:b1ce54272580 259 while (1)
kotakku 0:b1ce54272580 260 {
kotakku 0:b1ce54272580 261 #if defined(ESP8266) || defined(ESP32)
kotakku 0:b1ce54272580 262 yield(); // needed in order to reset the watchdog timer on the ESP8266
kotakku 0:b1ce54272580 263 #endif
kotakku 0:b1ce54272580 264 rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
kotakku 0:b1ce54272580 265 if (rcode == hrTOGERR)
kotakku 0:b1ce54272580 266 {
kotakku 0:b1ce54272580 267 // yes, we flip it wrong here so that next time it is actually correct!
kotakku 0:b1ce54272580 268 pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1;
kotakku 0:b1ce54272580 269 regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
kotakku 0:b1ce54272580 270 continue;
kotakku 0:b1ce54272580 271 }
kotakku 0:b1ce54272580 272 if (rcode)
kotakku 0:b1ce54272580 273 {
kotakku 0:b1ce54272580 274 //DEBUG(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
kotakku 0:b1ce54272580 275 break; //should be 0, indicating ACK. Else return error code.
kotakku 0:b1ce54272580 276 }
kotakku 0:b1ce54272580 277 /* check for RCVDAVIRQ and generate error if not present
kotakku 0:b1ce54272580 278 * the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred.
kotakku 0:b1ce54272580 279 * Need to add handling for that
kotakku 0:b1ce54272580 280 *
kotakku 0:b1ce54272580 281 * NOTE: I've seen this happen with SPI corruption -- xxxajk
kotakku 0:b1ce54272580 282 */
kotakku 0:b1ce54272580 283 if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0)
kotakku 0:b1ce54272580 284 {
kotakku 0:b1ce54272580 285 //DEBUG(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
kotakku 0:b1ce54272580 286 rcode = 0xf0; //receive error
kotakku 0:b1ce54272580 287 break;
kotakku 0:b1ce54272580 288 }
kotakku 0:b1ce54272580 289 pktsize = regRd(rRCVBC); //number of received bytes
kotakku 0:b1ce54272580 290 //DEBUG("Got %i bytes \r\n", pktsize);
kotakku 0:b1ce54272580 291 // This would be OK, but...
kotakku 0:b1ce54272580 292 //assert(pktsize <= nbytes);
kotakku 0:b1ce54272580 293 if (pktsize > nbytes)
kotakku 0:b1ce54272580 294 {
kotakku 0:b1ce54272580 295 // This can happen. Use of assert on Arduino locks up the Arduino.
kotakku 0:b1ce54272580 296 // So I will trim the value, and hope for the best.
kotakku 0:b1ce54272580 297 //DEBUG(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
kotakku 0:b1ce54272580 298 pktsize = nbytes;
kotakku 0:b1ce54272580 299 }
kotakku 0:b1ce54272580 300
kotakku 0:b1ce54272580 301 int16_t mem_left = (int16_t)nbytes - *((int16_t *)nbytesptr);
kotakku 0:b1ce54272580 302
kotakku 0:b1ce54272580 303 if (mem_left < 0)
kotakku 0:b1ce54272580 304 mem_left = 0;
kotakku 0:b1ce54272580 305
kotakku 0:b1ce54272580 306 data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
kotakku 0:b1ce54272580 307
kotakku 0:b1ce54272580 308 regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
kotakku 0:b1ce54272580 309 *nbytesptr += pktsize; // add this packet's byte count to total transfer length
kotakku 0:b1ce54272580 310
kotakku 0:b1ce54272580 311 /* The transfer is complete under two conditions: */
kotakku 0:b1ce54272580 312 /* 1. The device sent a short packet (L.T. maxPacketSize) */
kotakku 0:b1ce54272580 313 /* 2. 'nbytes' have been transferred. */
kotakku 0:b1ce54272580 314 if ((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
kotakku 0:b1ce54272580 315 {
kotakku 0:b1ce54272580 316 // Save toggle value
kotakku 0:b1ce54272580 317 pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
kotakku 0:b1ce54272580 318 //DEBUG("\r\n");
kotakku 0:b1ce54272580 319 rcode = 0;
kotakku 0:b1ce54272580 320 break;
kotakku 0:b1ce54272580 321 }
kotakku 0:b1ce54272580 322 else if (bInterval > 0)
kotakku 0:b1ce54272580 323 delay(bInterval); // Delay according to polling interval
kotakku 0:b1ce54272580 324 } //while( 1 )
kotakku 0:b1ce54272580 325 return (rcode);
kotakku 0:b1ce54272580 326 }
kotakku 0:b1ce54272580 327
kotakku 0:b1ce54272580 328 /* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
kotakku 0:b1ce54272580 329 /* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
kotakku 0:b1ce54272580 330
kotakku 0:b1ce54272580 331 /* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
kotakku 0:b1ce54272580 332 uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
kotakku 0:b1ce54272580 333 {
kotakku 0:b1ce54272580 334 EpInfo *pep = NULL;
kotakku 0:b1ce54272580 335 uint16_t nak_limit = 0;
kotakku 0:b1ce54272580 336
kotakku 0:b1ce54272580 337 uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
kotakku 0:b1ce54272580 338
kotakku 0:b1ce54272580 339 if (rcode)
kotakku 0:b1ce54272580 340 return rcode;
kotakku 0:b1ce54272580 341
kotakku 0:b1ce54272580 342 return OutTransfer(pep, nak_limit, nbytes, data);
kotakku 0:b1ce54272580 343 }
kotakku 0:b1ce54272580 344
kotakku 0:b1ce54272580 345 uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data)
kotakku 0:b1ce54272580 346 {
kotakku 0:b1ce54272580 347 uint8_t rcode = hrSUCCESS, retry_count;
kotakku 0:b1ce54272580 348 uint8_t *data_p = data; //local copy of the data pointer
kotakku 0:b1ce54272580 349 uint16_t bytes_tosend, nak_count;
kotakku 0:b1ce54272580 350 uint16_t bytes_left = nbytes;
kotakku 0:b1ce54272580 351
kotakku 0:b1ce54272580 352 uint8_t maxpktsize = pep->maxPktSize;
kotakku 0:b1ce54272580 353
kotakku 0:b1ce54272580 354 if (maxpktsize < 1 || maxpktsize > 64)
kotakku 0:b1ce54272580 355 return USB_ERROR_INVALID_MAX_PKT_SIZE;
kotakku 0:b1ce54272580 356
kotakku 0:b1ce54272580 357 uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
kotakku 0:b1ce54272580 358
kotakku 0:b1ce54272580 359 regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
kotakku 0:b1ce54272580 360
kotakku 0:b1ce54272580 361 while (bytes_left)
kotakku 0:b1ce54272580 362 {
kotakku 0:b1ce54272580 363 #if defined(ESP8266) || defined(ESP32)
kotakku 0:b1ce54272580 364 yield(); // needed in order to reset the watchdog timer on the ESP8266
kotakku 0:b1ce54272580 365 #endif
kotakku 0:b1ce54272580 366 retry_count = 0;
kotakku 0:b1ce54272580 367 nak_count = 0;
kotakku 0:b1ce54272580 368 bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
kotakku 0:b1ce54272580 369 bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
kotakku 0:b1ce54272580 370 regWr(rSNDBC, bytes_tosend); //set number of bytes
kotakku 0:b1ce54272580 371 regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
kotakku 0:b1ce54272580 372 while (!(regRd(rHIRQ) & bmHXFRDNIRQ))
kotakku 0:b1ce54272580 373 {
kotakku 0:b1ce54272580 374 #if defined(ESP8266) || defined(ESP32)
kotakku 0:b1ce54272580 375 yield(); // needed in order to reset the watchdog timer on the ESP8266
kotakku 0:b1ce54272580 376 #endif
kotakku 0:b1ce54272580 377 } //wait for the completion IRQ
kotakku 0:b1ce54272580 378 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
kotakku 0:b1ce54272580 379 rcode = (regRd(rHRSL) & 0x0f);
kotakku 0:b1ce54272580 380
kotakku 0:b1ce54272580 381 while (rcode && ((int32_t)((uint32_t)millis() - timeout) < 0L))
kotakku 0:b1ce54272580 382 {
kotakku 0:b1ce54272580 383 #if defined(ESP8266) || defined(ESP32)
kotakku 0:b1ce54272580 384 yield(); // needed in order to reset the watchdog timer on the ESP8266
kotakku 0:b1ce54272580 385 #endif
kotakku 0:b1ce54272580 386 switch (rcode)
kotakku 0:b1ce54272580 387 {
kotakku 0:b1ce54272580 388 case hrNAK:
kotakku 0:b1ce54272580 389 nak_count++;
kotakku 0:b1ce54272580 390 if (nak_limit && (nak_count == nak_limit))
kotakku 0:b1ce54272580 391 goto breakout;
kotakku 0:b1ce54272580 392 //return ( rcode);
kotakku 0:b1ce54272580 393 break;
kotakku 0:b1ce54272580 394 case hrTIMEOUT:
kotakku 0:b1ce54272580 395 retry_count++;
kotakku 0:b1ce54272580 396 if (retry_count == USB_RETRY_LIMIT)
kotakku 0:b1ce54272580 397 goto breakout;
kotakku 0:b1ce54272580 398 //return ( rcode);
kotakku 0:b1ce54272580 399 break;
kotakku 0:b1ce54272580 400 case hrTOGERR:
kotakku 0:b1ce54272580 401 // yes, we flip it wrong here so that next time it is actually correct!
kotakku 0:b1ce54272580 402 pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
kotakku 0:b1ce54272580 403 regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
kotakku 0:b1ce54272580 404 break;
kotakku 0:b1ce54272580 405 default:
kotakku 0:b1ce54272580 406 goto breakout;
kotakku 0:b1ce54272580 407 } //switch( rcode
kotakku 0:b1ce54272580 408
kotakku 0:b1ce54272580 409 /* process NAK according to Host out NAK bug */
kotakku 0:b1ce54272580 410 regWr(rSNDBC, 0);
kotakku 0:b1ce54272580 411 regWr(rSNDFIFO, *data_p);
kotakku 0:b1ce54272580 412 regWr(rSNDBC, bytes_tosend);
kotakku 0:b1ce54272580 413 regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
kotakku 0:b1ce54272580 414 while (!(regRd(rHIRQ) & bmHXFRDNIRQ))
kotakku 0:b1ce54272580 415 {
kotakku 0:b1ce54272580 416 #if defined(ESP8266) || defined(ESP32)
kotakku 0:b1ce54272580 417 yield(); // needed in order to reset the watchdog timer on the ESP8266
kotakku 0:b1ce54272580 418 #endif
kotakku 0:b1ce54272580 419 } //wait for the completion IRQ
kotakku 0:b1ce54272580 420 regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
kotakku 0:b1ce54272580 421 rcode = (regRd(rHRSL) & 0x0f);
kotakku 0:b1ce54272580 422 } //while( rcode && ....
kotakku 0:b1ce54272580 423 bytes_left -= bytes_tosend;
kotakku 0:b1ce54272580 424 data_p += bytes_tosend;
kotakku 0:b1ce54272580 425 } //while( bytes_left...
kotakku 0:b1ce54272580 426 breakout:
kotakku 0:b1ce54272580 427
kotakku 0:b1ce54272580 428 pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
kotakku 0:b1ce54272580 429 return (rcode); //should be 0 in all cases
kotakku 0:b1ce54272580 430 }
kotakku 0:b1ce54272580 431 /* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
kotakku 0:b1ce54272580 432 /* If NAK, tries to re-send up to nak_limit times */
kotakku 0:b1ce54272580 433 /* If nak_limit == 0, do not count NAKs, exit after timeout */
kotakku 0:b1ce54272580 434 /* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
kotakku 0:b1ce54272580 435
kotakku 0:b1ce54272580 436 /* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
kotakku 0:b1ce54272580 437 uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit)
kotakku 0:b1ce54272580 438 {
kotakku 0:b1ce54272580 439 uint32_t timeout = (uint32_t)millis() + USB_XFER_TIMEOUT;
kotakku 0:b1ce54272580 440 uint8_t tmpdata;
kotakku 0:b1ce54272580 441 uint8_t rcode = hrSUCCESS;
kotakku 0:b1ce54272580 442 uint8_t retry_count = 0;
kotakku 0:b1ce54272580 443 uint16_t nak_count = 0;
kotakku 0:b1ce54272580 444
kotakku 0:b1ce54272580 445 while ((int32_t)((uint32_t)millis() - timeout) < 0L)
kotakku 0:b1ce54272580 446 {
kotakku 0:b1ce54272580 447 #if defined(ESP8266) || defined(ESP32)
kotakku 0:b1ce54272580 448 yield(); // needed in order to reset the watchdog timer on the ESP8266
kotakku 0:b1ce54272580 449 #endif
kotakku 0:b1ce54272580 450 regWr(rHXFR, (token | ep)); //launch the transfer
kotakku 0:b1ce54272580 451 rcode = USB_ERROR_TRANSFER_TIMEOUT;
kotakku 0:b1ce54272580 452
kotakku 0:b1ce54272580 453 while ((int32_t)((uint32_t)millis() - timeout) < 0L) //wait for transfer completion
kotakku 0:b1ce54272580 454 {
kotakku 0:b1ce54272580 455 #if defined(ESP8266) || defined(ESP32)
kotakku 0:b1ce54272580 456 yield(); // needed in order to reset the watchdog timer on the ESP8266
kotakku 0:b1ce54272580 457 #endif
kotakku 0:b1ce54272580 458 tmpdata = regRd(rHIRQ);
kotakku 0:b1ce54272580 459
kotakku 0:b1ce54272580 460 if (tmpdata & bmHXFRDNIRQ)
kotakku 0:b1ce54272580 461 {
kotakku 0:b1ce54272580 462 regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
kotakku 0:b1ce54272580 463 rcode = 0x00;
kotakku 0:b1ce54272580 464 break;
kotakku 0:b1ce54272580 465 } //if( tmpdata & bmHXFRDNIRQ
kotakku 0:b1ce54272580 466
kotakku 0:b1ce54272580 467 } //while ( millis() < timeout
kotakku 0:b1ce54272580 468
kotakku 0:b1ce54272580 469 //if (rcode != 0x00) //exit if timeout
kotakku 0:b1ce54272580 470 // return ( rcode);
kotakku 0:b1ce54272580 471
kotakku 0:b1ce54272580 472 rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
kotakku 0:b1ce54272580 473
kotakku 0:b1ce54272580 474 switch (rcode)
kotakku 0:b1ce54272580 475 {
kotakku 0:b1ce54272580 476 case hrNAK:
kotakku 0:b1ce54272580 477 nak_count++;
kotakku 0:b1ce54272580 478 if (nak_limit && (nak_count == nak_limit))
kotakku 0:b1ce54272580 479 return (rcode);
kotakku 0:b1ce54272580 480 break;
kotakku 0:b1ce54272580 481 case hrTIMEOUT:
kotakku 0:b1ce54272580 482 retry_count++;
kotakku 0:b1ce54272580 483 if (retry_count == USB_RETRY_LIMIT)
kotakku 0:b1ce54272580 484 return (rcode);
kotakku 0:b1ce54272580 485 break;
kotakku 0:b1ce54272580 486 default:
kotakku 0:b1ce54272580 487 return (rcode);
kotakku 0:b1ce54272580 488 } //switch( rcode
kotakku 0:b1ce54272580 489
kotakku 0:b1ce54272580 490 } //while( timeout > millis()
kotakku 0:b1ce54272580 491 return (rcode);
kotakku 0:b1ce54272580 492 }
kotakku 0:b1ce54272580 493
kotakku 0:b1ce54272580 494 /* USB main task. Performs enumeration/cleanup */
kotakku 0:b1ce54272580 495 void USB::Task(void) //USB state machine
kotakku 0:b1ce54272580 496 {
kotakku 0:b1ce54272580 497 uint8_t rcode;
kotakku 0:b1ce54272580 498 uint8_t tmpdata;
kotakku 0:b1ce54272580 499 static uint32_t delay = 0;
kotakku 0:b1ce54272580 500 //USB_DEVICE_DESCRIPTOR buf;
kotakku 0:b1ce54272580 501 bool lowspeed = false;
kotakku 0:b1ce54272580 502
kotakku 0:b1ce54272580 503 MAX3421E::Task(); // 割り込みがあったらコマンドで対応する
kotakku 0:b1ce54272580 504
kotakku 0:b1ce54272580 505 tmpdata = getVbusState();
kotakku 0:b1ce54272580 506
kotakku 0:b1ce54272580 507 /* modify USB task state if Vbus changed */
kotakku 0:b1ce54272580 508 switch (tmpdata)
kotakku 0:b1ce54272580 509 {
kotakku 0:b1ce54272580 510 case SE1: //illegal state
kotakku 0:b1ce54272580 511 usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
kotakku 0:b1ce54272580 512 lowspeed = false;
kotakku 0:b1ce54272580 513 break;
kotakku 0:b1ce54272580 514 case SE0: //disconnected
kotakku 0:b1ce54272580 515 if ((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
kotakku 0:b1ce54272580 516 usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
kotakku 0:b1ce54272580 517 lowspeed = false;
kotakku 0:b1ce54272580 518 break;
kotakku 0:b1ce54272580 519 case LSHOST:
kotakku 0:b1ce54272580 520
kotakku 0:b1ce54272580 521 lowspeed = true;
kotakku 0:b1ce54272580 522 //intentional fallthrough
kotakku 0:b1ce54272580 523 case FSHOST: //attached
kotakku 0:b1ce54272580 524 if ((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED)
kotakku 0:b1ce54272580 525 {
kotakku 0:b1ce54272580 526 delay = (uint32_t)millis() + USB_SETTLE_DELAY;
kotakku 0:b1ce54272580 527 usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
kotakku 0:b1ce54272580 528 }
kotakku 0:b1ce54272580 529 break;
kotakku 0:b1ce54272580 530 } // switch( tmpdata
kotakku 0:b1ce54272580 531
kotakku 0:b1ce54272580 532 for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
kotakku 0:b1ce54272580 533 if (devConfig[i])
kotakku 0:b1ce54272580 534 {
kotakku 0:b1ce54272580 535 DEBUG("dev %d, poll\n", i);
kotakku 0:b1ce54272580 536 rcode = devConfig[i]->Poll();
kotakku 0:b1ce54272580 537 }
kotakku 0:b1ce54272580 538
kotakku 0:b1ce54272580 539 switch (usb_task_state)
kotakku 0:b1ce54272580 540 {
kotakku 0:b1ce54272580 541 case USB_DETACHED_SUBSTATE_INITIALIZE:
kotakku 0:b1ce54272580 542 init();
kotakku 0:b1ce54272580 543
kotakku 0:b1ce54272580 544 for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
kotakku 0:b1ce54272580 545 if (devConfig[i])
kotakku 0:b1ce54272580 546 rcode = devConfig[i]->Release();
kotakku 0:b1ce54272580 547
kotakku 0:b1ce54272580 548 usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
kotakku 0:b1ce54272580 549 break;
kotakku 0:b1ce54272580 550 case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
kotakku 0:b1ce54272580 551 break;
kotakku 0:b1ce54272580 552 case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
kotakku 0:b1ce54272580 553 break;
kotakku 0:b1ce54272580 554 case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
kotakku 0:b1ce54272580 555 if ((int32_t)((uint32_t)millis() - delay) >= 0L)
kotakku 0:b1ce54272580 556 usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
kotakku 0:b1ce54272580 557 else
kotakku 0:b1ce54272580 558 break; // don't fall through
kotakku 0:b1ce54272580 559 case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
kotakku 0:b1ce54272580 560 regWr(rHCTL, bmBUSRST); //issue bus reset
kotakku 0:b1ce54272580 561 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
kotakku 0:b1ce54272580 562 break;
kotakku 0:b1ce54272580 563 case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
kotakku 0:b1ce54272580 564 if ((regRd(rHCTL) & bmBUSRST) == 0)
kotakku 0:b1ce54272580 565 {
kotakku 0:b1ce54272580 566 tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
kotakku 0:b1ce54272580 567 regWr(rMODE, tmpdata);
kotakku 0:b1ce54272580 568 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
kotakku 0:b1ce54272580 569 //delay = (uint32_t)millis() + 20; //20ms wait after reset per USB spec
kotakku 0:b1ce54272580 570 }
kotakku 0:b1ce54272580 571 break;
kotakku 0:b1ce54272580 572 case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
kotakku 0:b1ce54272580 573 if (regRd(rHIRQ) & bmFRAMEIRQ)
kotakku 0:b1ce54272580 574 {
kotakku 0:b1ce54272580 575 //when first SOF received _and_ 20ms has passed we can continue
kotakku 0:b1ce54272580 576 /*
kotakku 0:b1ce54272580 577 if (delay < (uint32_t)millis()) //20ms passed
kotakku 0:b1ce54272580 578 usb_task_state = USB_STATE_CONFIGURING;
kotakku 0:b1ce54272580 579 */
kotakku 0:b1ce54272580 580 usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
kotakku 0:b1ce54272580 581 delay = (uint32_t)millis() + 20;
kotakku 0:b1ce54272580 582 }
kotakku 0:b1ce54272580 583 break;
kotakku 0:b1ce54272580 584 case USB_ATTACHED_SUBSTATE_WAIT_RESET:
kotakku 0:b1ce54272580 585 if ((int32_t)((uint32_t)millis() - delay) >= 0L)
kotakku 0:b1ce54272580 586 usb_task_state = USB_STATE_CONFIGURING;
kotakku 0:b1ce54272580 587 else
kotakku 0:b1ce54272580 588 break; // don't fall through
kotakku 0:b1ce54272580 589 case USB_STATE_CONFIGURING:
kotakku 0:b1ce54272580 590
kotakku 0:b1ce54272580 591 //Serial.print("\r\nConf.LS: ");
kotakku 0:b1ce54272580 592 //Serial.println(lowspeed, HEX);
kotakku 0:b1ce54272580 593
kotakku 0:b1ce54272580 594 rcode = Configuring(0, 0, lowspeed);
kotakku 0:b1ce54272580 595
kotakku 0:b1ce54272580 596 if (rcode)
kotakku 0:b1ce54272580 597 {
kotakku 0:b1ce54272580 598 if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
kotakku 0:b1ce54272580 599 {
kotakku 0:b1ce54272580 600 usb_error = rcode;
kotakku 0:b1ce54272580 601 usb_task_state = USB_STATE_ERROR;
kotakku 0:b1ce54272580 602 }
kotakku 0:b1ce54272580 603 }
kotakku 0:b1ce54272580 604 else
kotakku 0:b1ce54272580 605 usb_task_state = USB_STATE_RUNNING;
kotakku 0:b1ce54272580 606 break;
kotakku 0:b1ce54272580 607 case USB_STATE_RUNNING:
kotakku 0:b1ce54272580 608 break;
kotakku 0:b1ce54272580 609 case USB_STATE_ERROR:
kotakku 0:b1ce54272580 610 //MAX3421E::Init();
kotakku 0:b1ce54272580 611 break;
kotakku 0:b1ce54272580 612 } // switch( usb_task_state )
kotakku 0:b1ce54272580 613 }
kotakku 0:b1ce54272580 614
kotakku 0:b1ce54272580 615 uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed)
kotakku 0:b1ce54272580 616 {
kotakku 0:b1ce54272580 617 //uint8_t buf[12];
kotakku 0:b1ce54272580 618 uint8_t rcode;
kotakku 0:b1ce54272580 619 UsbDevice *p0 = NULL, *p = NULL;
kotakku 0:b1ce54272580 620
kotakku 0:b1ce54272580 621 // Get pointer to pseudo device with address 0 assigned
kotakku 0:b1ce54272580 622 p0 = addrPool.GetUsbDevicePtr(0);
kotakku 0:b1ce54272580 623
kotakku 0:b1ce54272580 624 if (!p0)
kotakku 0:b1ce54272580 625 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 626
kotakku 0:b1ce54272580 627 if (!p0->epinfo)
kotakku 0:b1ce54272580 628 return USB_ERROR_EPINFO_IS_NULL;
kotakku 0:b1ce54272580 629
kotakku 0:b1ce54272580 630 p0->lowspeed = (lowspeed) ? true : false;
kotakku 0:b1ce54272580 631
kotakku 0:b1ce54272580 632 // Allocate new address according to device class
kotakku 0:b1ce54272580 633 uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
kotakku 0:b1ce54272580 634
kotakku 0:b1ce54272580 635 if (!bAddress)
kotakku 0:b1ce54272580 636 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
kotakku 0:b1ce54272580 637
kotakku 0:b1ce54272580 638 p = addrPool.GetUsbDevicePtr(bAddress);
kotakku 0:b1ce54272580 639
kotakku 0:b1ce54272580 640 if (!p)
kotakku 0:b1ce54272580 641 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 642
kotakku 0:b1ce54272580 643 p->lowspeed = lowspeed;
kotakku 0:b1ce54272580 644
kotakku 0:b1ce54272580 645 // Assign new address to the device
kotakku 0:b1ce54272580 646 rcode = setAddr(0, 0, bAddress);
kotakku 0:b1ce54272580 647
kotakku 0:b1ce54272580 648 if (rcode)
kotakku 0:b1ce54272580 649 {
kotakku 0:b1ce54272580 650 addrPool.FreeAddress(bAddress);
kotakku 0:b1ce54272580 651 bAddress = 0;
kotakku 0:b1ce54272580 652 return rcode;
kotakku 0:b1ce54272580 653 }
kotakku 0:b1ce54272580 654 return 0;
kotakku 0:b1ce54272580 655 };
kotakku 0:b1ce54272580 656
kotakku 0:b1ce54272580 657 uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed)
kotakku 0:b1ce54272580 658 {
kotakku 0:b1ce54272580 659 //DEBUG("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
kotakku 0:b1ce54272580 660 uint8_t retries = 0;
kotakku 0:b1ce54272580 661
kotakku 0:b1ce54272580 662 again:
kotakku 0:b1ce54272580 663 uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
kotakku 0:b1ce54272580 664 if (rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET)
kotakku 0:b1ce54272580 665 {
kotakku 0:b1ce54272580 666 if (parent == 0)
kotakku 0:b1ce54272580 667 {
kotakku 0:b1ce54272580 668 // Send a bus reset on the root interface.
kotakku 0:b1ce54272580 669 regWr(rHCTL, bmBUSRST); //issue bus reset
kotakku 0:b1ce54272580 670 delay(102); // delay 102ms, compensate for clock inaccuracy.
kotakku 0:b1ce54272580 671 }
kotakku 0:b1ce54272580 672 else
kotakku 0:b1ce54272580 673 {
kotakku 0:b1ce54272580 674 // reset parent port
kotakku 0:b1ce54272580 675 devConfig[parent]->ResetHubPort(port);
kotakku 0:b1ce54272580 676 }
kotakku 0:b1ce54272580 677 }
kotakku 0:b1ce54272580 678 else if (rcode == hrJERR && retries < 3)
kotakku 0:b1ce54272580 679 { // Some devices returns this when plugged in - trying to initialize the device again usually works
kotakku 0:b1ce54272580 680 delay(100);
kotakku 0:b1ce54272580 681 retries++;
kotakku 0:b1ce54272580 682 goto again;
kotakku 0:b1ce54272580 683 }
kotakku 0:b1ce54272580 684 else if (rcode)
kotakku 0:b1ce54272580 685 return rcode;
kotakku 0:b1ce54272580 686
kotakku 0:b1ce54272580 687 rcode = devConfig[driver]->Init(parent, port, lowspeed);
kotakku 0:b1ce54272580 688 if (rcode == hrJERR && retries < 3)
kotakku 0:b1ce54272580 689 { // Some devices returns this when plugged in - trying to initialize the device again usually works
kotakku 0:b1ce54272580 690 delay(100);
kotakku 0:b1ce54272580 691 retries++;
kotakku 0:b1ce54272580 692 goto again;
kotakku 0:b1ce54272580 693 }
kotakku 0:b1ce54272580 694 if (rcode)
kotakku 0:b1ce54272580 695 {
kotakku 0:b1ce54272580 696 // Issue a bus reset, because the device may be in a limbo state
kotakku 0:b1ce54272580 697 if (parent == 0)
kotakku 0:b1ce54272580 698 {
kotakku 0:b1ce54272580 699 // Send a bus reset on the root interface.
kotakku 0:b1ce54272580 700 regWr(rHCTL, bmBUSRST); //issue bus reset
kotakku 0:b1ce54272580 701 delay(102); // delay 102ms, compensate for clock inaccuracy.
kotakku 0:b1ce54272580 702 }
kotakku 0:b1ce54272580 703 else
kotakku 0:b1ce54272580 704 {
kotakku 0:b1ce54272580 705 // reset parent port
kotakku 0:b1ce54272580 706 devConfig[parent]->ResetHubPort(port);
kotakku 0:b1ce54272580 707 }
kotakku 0:b1ce54272580 708 }
kotakku 0:b1ce54272580 709 return rcode;
kotakku 0:b1ce54272580 710 }
kotakku 0:b1ce54272580 711
kotakku 0:b1ce54272580 712 /*
kotakku 0:b1ce54272580 713 * This is broken. We need to enumerate differently.
kotakku 0:b1ce54272580 714 * It causes major problems with several devices if detected in an unexpected order.
kotakku 0:b1ce54272580 715 *
kotakku 0:b1ce54272580 716 *
kotakku 0:b1ce54272580 717 * Oleg - I wouldn't do anything before the newly connected device is considered sane.
kotakku 0:b1ce54272580 718 * i.e.(delays are not indicated for brevity):
kotakku 0:b1ce54272580 719 * 1. reset
kotakku 0:b1ce54272580 720 * 2. GetDevDescr();
kotakku 0:b1ce54272580 721 * 3a. If ACK, continue with allocating address, addressing, etc.
kotakku 0:b1ce54272580 722 * 3b. Else reset again, count resets, stop at some number (5?).
kotakku 0:b1ce54272580 723 * 4. When max.number of resets is reached, toggle power/fail
kotakku 0:b1ce54272580 724 * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
kotakku 0:b1ce54272580 725 * it doesn't need to be reset again
kotakku 0:b1ce54272580 726 * New steps proposal:
kotakku 0:b1ce54272580 727 * 1: get address pool instance. exit on fail
kotakku 0:b1ce54272580 728 * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
kotakku 0:b1ce54272580 729 * 3: bus reset, 100ms delay
kotakku 0:b1ce54272580 730 * 4: set address
kotakku 0:b1ce54272580 731 * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
kotakku 0:b1ce54272580 732 * 6: while (configurations) {
kotakku 0:b1ce54272580 733 * for(each configuration) {
kotakku 0:b1ce54272580 734 * for (each driver) {
kotakku 0:b1ce54272580 735 * 6a: Ask device if it likes configuration. Returns 0 on OK.
kotakku 0:b1ce54272580 736 * If successful, the driver configured device.
kotakku 0:b1ce54272580 737 * The driver now owns the endpoints, and takes over managing them.
kotakku 0:b1ce54272580 738 * The following will need codes:
kotakku 0:b1ce54272580 739 * Everything went well, instance consumed, exit with success.
kotakku 0:b1ce54272580 740 * Instance already in use, ignore it, try next driver.
kotakku 0:b1ce54272580 741 * Not a supported device, ignore it, try next driver.
kotakku 0:b1ce54272580 742 * Not a supported configuration for this device, ignore it, try next driver.
kotakku 0:b1ce54272580 743 * Could not configure device, fatal, exit with fail.
kotakku 0:b1ce54272580 744 * }
kotakku 0:b1ce54272580 745 * }
kotakku 0:b1ce54272580 746 * }
kotakku 0:b1ce54272580 747 * 7: for(each driver) {
kotakku 0:b1ce54272580 748 * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
kotakku 0:b1ce54272580 749 * 8: if we get here, no driver likes the device plugged in, so exit failure.
kotakku 0:b1ce54272580 750 *
kotakku 0:b1ce54272580 751 */
kotakku 0:b1ce54272580 752 uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed)
kotakku 0:b1ce54272580 753 {
kotakku 0:b1ce54272580 754 //uint8_t bAddress = 0;
kotakku 0:b1ce54272580 755 //DEBUG("Configuring: parent = %i, port = %i\r\n", parent, port);
kotakku 0:b1ce54272580 756 uint8_t devConfigIndex;
kotakku 0:b1ce54272580 757 uint8_t rcode = 0;
kotakku 0:b1ce54272580 758 uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)];
kotakku 0:b1ce54272580 759 USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
kotakku 0:b1ce54272580 760 UsbDevice *p = NULL;
kotakku 0:b1ce54272580 761 EpInfo *oldep_ptr = NULL;
kotakku 0:b1ce54272580 762 EpInfo epInfo;
kotakku 0:b1ce54272580 763
kotakku 0:b1ce54272580 764 epInfo.epAddr = 0;
kotakku 0:b1ce54272580 765 epInfo.maxPktSize = 8;
kotakku 0:b1ce54272580 766 epInfo.bmSndToggle = 0;
kotakku 0:b1ce54272580 767 epInfo.bmRcvToggle = 0;
kotakku 0:b1ce54272580 768 epInfo.bmNakPower = USB_NAK_MAX_POWER;
kotakku 0:b1ce54272580 769
kotakku 0:b1ce54272580 770 //delay(2000);
kotakku 0:b1ce54272580 771 AddressPool &addrPool = GetAddressPool();
kotakku 0:b1ce54272580 772 // Get pointer to pseudo device with address 0 assigned
kotakku 0:b1ce54272580 773 p = addrPool.GetUsbDevicePtr(0);
kotakku 0:b1ce54272580 774 if (!p)
kotakku 0:b1ce54272580 775 {
kotakku 0:b1ce54272580 776 //DEBUG("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
kotakku 0:b1ce54272580 777 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
kotakku 0:b1ce54272580 778 }
kotakku 0:b1ce54272580 779
kotakku 0:b1ce54272580 780 // Save old pointer to EP_RECORD of address 0
kotakku 0:b1ce54272580 781 oldep_ptr = p->epinfo;
kotakku 0:b1ce54272580 782
kotakku 0:b1ce54272580 783 // Temporary assign new pointer to epInfo to p->epinfo in order to
kotakku 0:b1ce54272580 784 // avoid toggle inconsistence
kotakku 0:b1ce54272580 785
kotakku 0:b1ce54272580 786 p->epinfo = &epInfo;
kotakku 0:b1ce54272580 787
kotakku 0:b1ce54272580 788 p->lowspeed = lowspeed;
kotakku 0:b1ce54272580 789 // Get device descriptor
kotakku 0:b1ce54272580 790 rcode = getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t *)buf);
kotakku 0:b1ce54272580 791
kotakku 0:b1ce54272580 792 // Restore p->epinfo
kotakku 0:b1ce54272580 793 p->epinfo = oldep_ptr;
kotakku 0:b1ce54272580 794
kotakku 0:b1ce54272580 795 if (rcode)
kotakku 0:b1ce54272580 796 {
kotakku 0:b1ce54272580 797 //DEBUG("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
kotakku 0:b1ce54272580 798 return rcode;
kotakku 0:b1ce54272580 799 }
kotakku 0:b1ce54272580 800
kotakku 0:b1ce54272580 801 // to-do?
kotakku 0:b1ce54272580 802 // Allocate new address according to device class
kotakku 0:b1ce54272580 803 //bAddress = addrPool.AllocAddress(parent, false, port);
kotakku 0:b1ce54272580 804
kotakku 0:b1ce54272580 805 uint16_t vid = udd->idVendor;
kotakku 0:b1ce54272580 806 uint16_t pid = udd->idProduct;
kotakku 0:b1ce54272580 807 uint8_t klass = udd->bDeviceClass;
kotakku 0:b1ce54272580 808 uint8_t subklass = udd->bDeviceSubClass;
kotakku 0:b1ce54272580 809 // Attempt to configure if VID/PID or device class matches with a driver
kotakku 0:b1ce54272580 810 // Qualify with subclass too.
kotakku 0:b1ce54272580 811 //
kotakku 0:b1ce54272580 812 // VID/PID & class tests default to false for drivers not yet ported
kotakku 0:b1ce54272580 813 // subclass defaults to true, so you don't have to define it if you don't have to.
kotakku 0:b1ce54272580 814 //
kotakku 0:b1ce54272580 815 for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++)
kotakku 0:b1ce54272580 816 {
kotakku 0:b1ce54272580 817 if (!devConfig[devConfigIndex])
kotakku 0:b1ce54272580 818 continue; // no driver
kotakku 0:b1ce54272580 819 if (devConfig[devConfigIndex]->GetAddress())
kotakku 0:b1ce54272580 820 continue; // consumed
kotakku 0:b1ce54272580 821 if (devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)))
kotakku 0:b1ce54272580 822 {
kotakku 0:b1ce54272580 823 rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
kotakku 0:b1ce54272580 824 if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
kotakku 0:b1ce54272580 825 break;
kotakku 0:b1ce54272580 826 }
kotakku 0:b1ce54272580 827 }
kotakku 0:b1ce54272580 828
kotakku 0:b1ce54272580 829 if (devConfigIndex < USB_NUMDEVICES)
kotakku 0:b1ce54272580 830 {
kotakku 0:b1ce54272580 831 return rcode;
kotakku 0:b1ce54272580 832 }
kotakku 0:b1ce54272580 833
kotakku 0:b1ce54272580 834 // blindly attempt to configure
kotakku 0:b1ce54272580 835 for (devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++)
kotakku 0:b1ce54272580 836 {
kotakku 0:b1ce54272580 837 if (!devConfig[devConfigIndex])
kotakku 0:b1ce54272580 838 continue;
kotakku 0:b1ce54272580 839 if (devConfig[devConfigIndex]->GetAddress())
kotakku 0:b1ce54272580 840 continue; // consumed
kotakku 0:b1ce54272580 841 if (devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass)))
kotakku 0:b1ce54272580 842 continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
kotakku 0:b1ce54272580 843 rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
kotakku 0:b1ce54272580 844
kotakku 0:b1ce54272580 845 //DEBUG("ERROR ENUMERATING %2.2x\r\n", rcode);
kotakku 0:b1ce54272580 846 if (!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE))
kotakku 0:b1ce54272580 847 {
kotakku 0:b1ce54272580 848 // in case of an error dev_index should be reset to 0
kotakku 0:b1ce54272580 849 // in order to start from the very beginning the
kotakku 0:b1ce54272580 850 // next time the program gets here
kotakku 0:b1ce54272580 851 //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
kotakku 0:b1ce54272580 852 // devConfigIndex = 0;
kotakku 0:b1ce54272580 853 return rcode;
kotakku 0:b1ce54272580 854 }
kotakku 0:b1ce54272580 855 }
kotakku 0:b1ce54272580 856 // if we get here that means that the device class is not supported by any of registered classes
kotakku 0:b1ce54272580 857 rcode = DefaultAddressing(parent, port, lowspeed);
kotakku 0:b1ce54272580 858
kotakku 0:b1ce54272580 859 return rcode;
kotakku 0:b1ce54272580 860 }
kotakku 0:b1ce54272580 861
kotakku 0:b1ce54272580 862 uint8_t USB::ReleaseDevice(uint8_t addr)
kotakku 0:b1ce54272580 863 {
kotakku 0:b1ce54272580 864 if (!addr)
kotakku 0:b1ce54272580 865 return 0;
kotakku 0:b1ce54272580 866
kotakku 0:b1ce54272580 867 for (uint8_t i = 0; i < USB_NUMDEVICES; i++)
kotakku 0:b1ce54272580 868 {
kotakku 0:b1ce54272580 869 if (!devConfig[i])
kotakku 0:b1ce54272580 870 continue;
kotakku 0:b1ce54272580 871 if (devConfig[i]->GetAddress() == addr)
kotakku 0:b1ce54272580 872 return devConfig[i]->Release();
kotakku 0:b1ce54272580 873 }
kotakku 0:b1ce54272580 874 return 0;
kotakku 0:b1ce54272580 875 }
kotakku 0:b1ce54272580 876
kotakku 0:b1ce54272580 877 #if 1 //!defined(USB_METHODS_INLINE)
kotakku 0:b1ce54272580 878 //get device descriptor
kotakku 0:b1ce54272580 879
kotakku 0:b1ce54272580 880 uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
kotakku 0:b1ce54272580 881 {
kotakku 0:b1ce54272580 882 return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
kotakku 0:b1ce54272580 883 }
kotakku 0:b1ce54272580 884 //get configuration descriptor
kotakku 0:b1ce54272580 885
kotakku 0:b1ce54272580 886 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
kotakku 0:b1ce54272580 887 {
kotakku 0:b1ce54272580 888 return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
kotakku 0:b1ce54272580 889 }
kotakku 0:b1ce54272580 890
kotakku 0:b1ce54272580 891 /* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this
kotakku 0:b1ce54272580 892 total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */
kotakku 0:b1ce54272580 893 uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p)
kotakku 0:b1ce54272580 894 {
kotakku 0:b1ce54272580 895 const uint8_t bufSize = 64;
kotakku 0:b1ce54272580 896 uint8_t buf[bufSize];
kotakku 0:b1ce54272580 897 USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
kotakku 0:b1ce54272580 898
kotakku 0:b1ce54272580 899 uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
kotakku 0:b1ce54272580 900
kotakku 0:b1ce54272580 901 if (ret)
kotakku 0:b1ce54272580 902 return ret;
kotakku 0:b1ce54272580 903
kotakku 0:b1ce54272580 904 uint16_t total = ucd->wTotalLength;
kotakku 0:b1ce54272580 905
kotakku 0:b1ce54272580 906 //USBTRACE2("\r\ntotal conf.size:", total);
kotakku 0:b1ce54272580 907
kotakku 0:b1ce54272580 908 return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
kotakku 0:b1ce54272580 909 }
kotakku 0:b1ce54272580 910
kotakku 0:b1ce54272580 911 //get string descriptor
kotakku 0:b1ce54272580 912
kotakku 0:b1ce54272580 913 uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t *dataptr)
kotakku 0:b1ce54272580 914 {
kotakku 0:b1ce54272580 915 return (ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
kotakku 0:b1ce54272580 916 }
kotakku 0:b1ce54272580 917 //set address
kotakku 0:b1ce54272580 918
kotakku 0:b1ce54272580 919 uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
kotakku 0:b1ce54272580 920 {
kotakku 0:b1ce54272580 921 uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
kotakku 0:b1ce54272580 922 //delay(2); //per USB 2.0 sect.9.2.6.3
kotakku 0:b1ce54272580 923 delay(300); // Older spec says you should wait at least 200ms
kotakku 0:b1ce54272580 924 return rcode;
kotakku 0:b1ce54272580 925 //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
kotakku 0:b1ce54272580 926 }
kotakku 0:b1ce54272580 927 //set configuration
kotakku 0:b1ce54272580 928
kotakku 0:b1ce54272580 929 uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
kotakku 0:b1ce54272580 930 {
kotakku 0:b1ce54272580 931 return (ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
kotakku 0:b1ce54272580 932 }
kotakku 0:b1ce54272580 933
kotakku 0:b1ce54272580 934 #endif // defined(USB_METHODS_INLINE)