Library to use Arduino USB host shield on mbed
ArduinoのUSB Host Shield 2.0をmbedで使えるようにしたライブラリです。
大体のコードがArduinoからそのまま移植可能です。
Arduino UNOやMega用のホストシールド以外にもミニサイズのホストシールドでも使用可能です
シールドについて
3.3VのI/O用にシールドの改造が必要になりますがネット上に記事がたくさんあるのでそちらを参考にしてください
接続例
使い方
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"); } } }
USB_Host/confdescparser.h
- Committer:
- robo_ichinoseki_a
- Date:
- 2020-05-02
- Revision:
- 1:da31140f2a1c
- Parent:
- 0:b1ce54272580
File content as of revision 1:da31140f2a1c:
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact information ------------------- Circuits At Home, LTD Web : http://www.circuitsathome.com e-mail : support@circuitsathome.com */ #if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__) #error "Never include confdescparser.h directly; include Usb.h instead" #else #define __CONFDESCPARSER_H__ class UsbConfigXtracter { public: //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0; //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0; virtual void EndpointXtract(uint8_t conf __attribute__((unused)), uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *ep __attribute__((unused))) { }; }; #define CP_MASK_COMPARE_CLASS 1 #define CP_MASK_COMPARE_SUBCLASS 2 #define CP_MASK_COMPARE_PROTOCOL 4 #define CP_MASK_COMPARE_ALL 7 // Configuration Descriptor Parser Class Template template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> class ConfigDescParser : public USBReadParser { UsbConfigXtracter *theXtractor; MultiValueBuffer theBuffer; MultiByteValueParser valParser; ByteSkipper theSkipper; uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/]; uint8_t stateParseDescr; // ParseDescriptor state uint8_t dscrLen; // Descriptor length uint8_t dscrType; // Descriptor type bool isGoodInterface; // Apropriate interface flag uint8_t confValue; // Configuration value uint8_t protoValue; // Protocol value uint8_t ifaceNumber; // Interface number uint8_t ifaceAltSet; // Interface alternate settings bool UseOr; bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn); void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc); public: void SetOR(void) { UseOr = true; } ConfigDescParser(UsbConfigXtracter *xtractor); void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset); }; template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) : theXtractor(xtractor), stateParseDescr(0), dscrLen(0), dscrType(0), UseOr(false) { theBuffer.pValue = varBuffer; valParser.Initialize(&theBuffer); theSkipper.Initialize(&theBuffer); }; template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset __attribute__((unused))) { uint16_t cntdn = (uint16_t)len; uint8_t *p = (uint8_t*)pbuf; while(cntdn) if(!ParseDescriptor(&p, &cntdn)) return; } /* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer); USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer); switch(stateParseDescr) { case 0: theBuffer.valueSize = 2; valParser.Initialize(&theBuffer); stateParseDescr = 1; case 1: if(!valParser.Parse(pp, pcntdn)) return false; dscrLen = *((uint8_t*)theBuffer.pValue); dscrType = *((uint8_t*)theBuffer.pValue + 1); stateParseDescr = 2; case 2: // This is a sort of hack. Assuming that two bytes are all ready in the buffer // the pointer is positioned two bytes ahead in order for the rest of descriptor // to be read right after the size and the type fields. // This should be used carefully. varBuffer should be used directly to handle data // in the buffer. theBuffer.pValue = varBuffer + 2; stateParseDescr = 3; case 3: switch(dscrType) { case USB_DESCRIPTOR_INTERFACE: isGoodInterface = false; break; case USB_DESCRIPTOR_CONFIGURATION: case USB_DESCRIPTOR_ENDPOINT: case HID_DESCRIPTOR_HID: break; } theBuffer.valueSize = dscrLen - 2; valParser.Initialize(&theBuffer); stateParseDescr = 4; case 4: switch(dscrType) { case USB_DESCRIPTOR_CONFIGURATION: if(!valParser.Parse(pp, pcntdn)) return false; confValue = ucd->bConfigurationValue; break; case USB_DESCRIPTOR_INTERFACE: if(!valParser.Parse(pp, pcntdn)) return false; if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID) break; if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID) break; if(UseOr) { if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol))) break; } else { if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID) break; } isGoodInterface = true; ifaceNumber = uid->bInterfaceNumber; ifaceAltSet = uid->bAlternateSetting; protoValue = uid->bInterfaceProtocol; break; case USB_DESCRIPTOR_ENDPOINT: if(!valParser.Parse(pp, pcntdn)) return false; if(isGoodInterface) if(theXtractor) theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer); break; //case HID_DESCRIPTOR_HID: // if (!valParser.Parse(pp, pcntdn)) // return false; // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); // break; default: if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) return false; } theBuffer.pValue = varBuffer; stateParseDescr = 0; } return true; } template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); Notify(PSTR("bDescLength:\t\t"), 0x80); PrintHex<uint8_t > (pDesc->bLength, 0x80); Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80); Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); PrintHex<uint16_t > (pDesc->bcdHID, 0x80); Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); PrintHex<uint8_t > (pDesc->bCountryCode, 0x80); Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80); for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) { HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); PrintHex<uint8_t > (pLT[i].bDescrType, 0x80); Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80); } Notify(PSTR("\r\n"), 0x80); } #endif // __CONFDESCPARSER_H__