Merge branch 'SPI' into Galileo

Conflicts:
	Usb.h
	avrpins.h
	usbhost.h
This commit is contained in:
Kristian Sloth Lauszus 2015-03-19 16:36:51 +01:00
commit 73ce976198
61 changed files with 15019 additions and 14416 deletions

23
.gitattributes vendored Normal file
View file

@ -0,0 +1,23 @@
# Auto detect text files and perform LF normalization
* text=auto
* text eol=lf
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain

View file

@ -1343,7 +1343,7 @@ void BTD::setBdaddr(uint8_t* bdaddr) {
buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first
// 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
pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
}
void BTD::setMoveBdaddr(uint8_t* bdaddr) {
@ -1359,5 +1359,5 @@ void BTD::setMoveBdaddr(uint8_t* bdaddr) {
buf[i + 1] = bdaddr[i];
// 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
pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);
pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);
}

2
BTD.h
View file

@ -19,7 +19,7 @@
#define _btd_h_
#include "Usb.h"
#include "Hid.h"
#include "hid.h"
//PID and VID of the Sony PS3 devices
#define PS3_VID 0x054C // Sony Corporation

View file

@ -398,7 +398,7 @@ void PS3USB::printStatusString() {
/* Playstation Sixaxis Dualshock and Navigation Controller commands */
void PS3USB::PS3_Command(uint8_t *data, uint16_t nbytes) {
// 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)
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL);
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL);
}
void PS3USB::setAllOff() {
@ -470,14 +470,14 @@ void PS3USB::setBdaddr(uint8_t *bdaddr) {
buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first
// 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
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
}
void PS3USB::getBdaddr(uint8_t *bdaddr) {
uint8_t buf[8];
// 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
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
for(uint8_t i = 0; i < 6; i++)
bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first
@ -491,7 +491,7 @@ void PS3USB::enable_sixaxis() { // Command used to enable the Dualshock 3 and Na
cmd_buf[3] = 0x00;
// 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)
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL);
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL);
}
/* Playstation Move Controller commands */
@ -535,14 +535,14 @@ void PS3USB::setMoveBdaddr(uint8_t *bdaddr) {
buf[i + 1] = bdaddr[i];
// 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
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);
}
void PS3USB::getMoveBdaddr(uint8_t *bdaddr) {
uint8_t buf[16];
// 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
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL);
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL);
for(uint8_t i = 0; i < 6; i++)
bdaddr[i] = buf[10 + i];
@ -553,7 +553,7 @@ void PS3USB::getMoveCalibration(uint8_t *data) {
for(uint8_t i = 0; i < 3; i++) {
// 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
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL);
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL);
for(byte j = 0; j < 49; j++)
data[49 * i + j] = buf[j];

View file

@ -19,7 +19,7 @@
#define _ps3usb_h_
#include "Usb.h"
#include "Hid.h"
#include "hid.h"
#include "PS3Enums.h"
/* PS3 data taken from descriptors */

View file

@ -78,5 +78,5 @@ void PSBuzz::setLedRaw(bool value, uint8_t controller) {
void PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) {
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
};

View file

@ -285,7 +285,7 @@ More information about the controller can be found at the following sites:
The shield is using SPI for communicating with the MAX3421E USB host controller. It uses the SCK, MISO and MOSI pins via the ICSP on your board.
Note this means that it uses pin 13, 12, 11 on an Arduino Uno, so these pins can not be used for anything else!
Note this means that it uses pin 13, 12, 11 on an Arduino Uno, so these pins can not be used for anything else than SPI communication!
Furthermore it uses one pin as SS and one INT pin. These are by default located on pin 10 and 9 respectively. They can easily be reconfigured in case you need to use them for something else by cutting the jumper on the shield and then solder a wire from the pad to the new pin.
@ -309,3 +309,17 @@ See the "Interface modifications" section in the [hardware manual](https://www.c
* Try to connect a external power supply to the Arduino - this solves the problem in most cases.
* You can also use a powered hub between the device and the USB Host Shield. You should then include the USB hub library: ```#include <usbhub.h>``` and create the instance like so: ```USBHub Hub1(&Usb);```.
> When I connecting my PS3 controller I get a output like this:
```
Dualshock 3 Controller Enabled
LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
```
* This means that your dongle does not support 2.0+EDR, so you will need another dongle. Please see the following [list](https://github.com/felis/USB_Host_Shield_2.0/wiki/Bluetooth-dongles) for tested working dongles.

12
Usb.cpp
View file

@ -77,7 +77,7 @@ uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr)
return 0;
}
uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit) {
uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {
UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
if(!p)
@ -91,8 +91,8 @@ uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_l
if(!*ppep)
return USB_ERROR_EP_NOT_FOUND_IN_TBL;
nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
nak_limit--;
*nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
*nak_limit--;
/*
USBTRACE2("\r\nAddress: ", addr);
USBTRACE2(" EP: ", ep);
@ -132,7 +132,7 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque
EpInfo *pep = NULL;
uint16_t nak_limit = 0;
rcode = SetAddress(addr, ep, &pep, nak_limit);
rcode = SetAddress(addr, ep, &pep, &nak_limit);
if(rcode)
return rcode;
@ -207,7 +207,7 @@ uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t*
EpInfo *pep = NULL;
uint16_t nak_limit = 0;
uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit);
uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
if(rcode) {
USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
@ -293,7 +293,7 @@ uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dat
EpInfo *pep = NULL;
uint16_t nak_limit = 0;
uint8_t rcode = SetAddress(addr, ep, &pep, nak_limit);
uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
if(rcode)
return rcode;

View file

@ -89,10 +89,10 @@ typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega
#define USB_ERROR_FailGetConfDescr 0xE3
#define USB_ERROR_TRANSFER_TIMEOUT 0xFF
#define USB_XFER_TIMEOUT 10000 //30000 // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
//#define USB_NAK_LIMIT 32000 //NAK limit for a transfer. 0 means NAKs are not counted
#define USB_XFER_TIMEOUT 5000 // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
//#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. 0 means NAKs are not counted
#define USB_RETRY_LIMIT 3 // 3 retry limit for a transfer
#define USB_SETTLE_DELAY 200 //settle delay in milliseconds
#define USB_SETTLE_DELAY 200 // settle delay in milliseconds
#define USB_NUMDEVICES 16 //number of USB devices
//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller
@ -258,7 +258,7 @@ public:
private:
void init();
uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t &nak_limit);
uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit);
uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data);
uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data);
uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed);

View file

@ -320,7 +320,7 @@ int16_t XBOXOLD::getAnalogHat(AnalogHatEnum a) {
/* Xbox Controller commands */
void XBOXOLD::XboxCommand(uint8_t* data, uint16_t nbytes) {
//bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
}
void XBOXOLD::setRumbleOn(uint8_t lValue, uint8_t rValue) {

View file

@ -19,7 +19,7 @@
#define _xboxold_h_
#include "Usb.h"
#include "Hid.h"
#include "hid.h"
#include "controllerEnums.h"
/* Data Xbox taken from descriptors */

View file

@ -314,7 +314,7 @@ int16_t XBOXUSB::getAnalogHat(AnalogHatEnum a) {
/* Xbox Controller commands */
void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) {
//bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
}
void XBOXUSB::setLedRaw(uint8_t value) {

View file

@ -19,7 +19,7 @@
#define _xboxusb_h_
#include "Usb.h"
#include "Hid.h"
#include "hid.h"
#include "xboxEnums.h"
/* Data Xbox 360 taken from descriptors */

12
adk.cpp
View file

@ -356,16 +356,16 @@ uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) {
void ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
Notify(PSTR("Endpoint descriptor:"), 0x80);
Notify(PSTR("\r\nLength:\t\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
Notify(PSTR("\r\nType:\t\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
Notify(PSTR("\r\nAddress:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
Notify(PSTR("\r\nAttributes:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
Notify(PSTR("\r\n"), 0x80);
}

211
cdc_XR21B1411.cpp Normal file
View file

@ -0,0 +1,211 @@
/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#include "cdc_XR21B1411.h"
XR21B1411::XR21B1411(USB *p, CDCAsyncOper *pasync) :
ACM(p, pasync) {
// Is this needed??
_enhanced_status = enhanced_features(); // Set up features
}
uint8_t XR21B1411::Init(uint8_t parent, uint8_t port, bool lowspeed) {
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
uint8_t buf[constBufSize];
USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
uint8_t rcode;
UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL;
uint8_t num_of_conf; // number of configurations
AddressPool &addrPool = pUsb->GetAddressPool();
USBTRACE("XR Init\r\n");
if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0);
if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if(!p->epinfo) {
USBTRACE("epinfo\r\n");
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, constBufSize, (uint8_t*)buf);
// Restore p->epinfo
p->epinfo = oldep_ptr;
if(rcode)
goto FailGetDevDescr;
// 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 the device descriptor
epInfo[0].maxPktSize = udd->bMaxPacketSize0;
// Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress);
if(rcode) {
p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
USBTRACE2("setAddr:", rcode);
return rcode;
}
USBTRACE2("Addr:", bAddress);
p->lowspeed = false;
p = addrPool.GetUsbDevicePtr(bAddress);
if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed;
num_of_conf = udd->bNumConfigurations;
if((((udd->idVendor != 0x2890U) || (udd->idProduct != 0x0201U)) && ((udd->idVendor != 0x04e2U) || (udd->idProduct != 0x1411U))))
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if(rcode)
goto FailSetDevTblEntry;
USBTRACE2("NC:", num_of_conf);
for(uint8_t i = 0; i < num_of_conf; i++) {
ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,
CDC_SUBCLASS_ACM,
CDC_PROTOCOL_ITU_T_V_250,
CP_MASK_COMPARE_CLASS |
CP_MASK_COMPARE_SUBCLASS |
CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this);
ConfigDescParser<USB_CLASS_CDC_DATA, 0, 0,
CP_MASK_COMPARE_CLASS> CdcDataParser(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
if(rcode)
goto FailGetConfDescr;
rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
if(rcode)
goto FailGetConfDescr;
if(bNumEP > 1)
break;
} // for
if(bNumEP < 4)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
USBTRACE2("Conf:", bConfNum);
// Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum);
if(rcode)
goto FailSetConfDescr;
// Set up features status
_enhanced_status = enhanced_features();
half_duplex(false);
autoflowRTS(false);
autoflowDSR(false);
autoflowXON(false);
wide(false); // Always false, because this is only available in custom mode.
rcode = pAsync->OnInit(this);
if(rcode)
goto FailOnInit;
USBTRACE("XR configured\r\n");
ready = true;
//bPollEnable = true;
//USBTRACE("Poll enabled\r\n");
return 0;
FailGetDevDescr:
#ifdef DEBUG_USB_HOST
NotifyFailGetDevDescr();
goto Fail;
#endif
FailSetDevTblEntry:
#ifdef DEBUG_USB_HOST
NotifyFailSetDevTblEntry();
goto Fail;
#endif
FailGetConfDescr:
#ifdef DEBUG_USB_HOST
NotifyFailGetConfDescr();
goto Fail;
#endif
FailSetConfDescr:
#ifdef DEBUG_USB_HOST
NotifyFailSetConfDescr();
goto Fail;
#endif
FailOnInit:
#ifdef DEBUG_USB_HOST
USBTRACE("OnInit:");
#endif
#ifdef DEBUG_USB_HOST
Fail:
NotifyFail(rcode);
#endif
Release();
return rcode;
}

272
cdc_XR21B1411.h Normal file
View file

@ -0,0 +1,272 @@
/* Copyright (C) 2015 Andrew J. Kroll
and
Circuits At Home, LTD. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Circuits At Home, LTD
Web : http://www.circuitsathome.com
e-mail : support@circuitsathome.com
*/
#if !defined(__CDC_XR21B1411_H__)
#define __CDC_XR21B1411_H__
#include "cdcacm.h"
#define XR_REG_CUSTOM_DRIVER (0x020DU) // DRIVER SELECT
#define XR_REG_CUSTOM_DRIVER_ACTIVE (0x0001U) // 0: CDC 1: CUSTOM
#define XR_REG_ACM_FLOW_CTL (0x0216U) // FLOW CONTROL REGISTER CDCACM MODE
#define XR_REG_FLOW_CTL (0x0C06U) // FLOW CONTROL REGISTER CUSTOM MODE
#define XR_REG_FLOW_CTL_HALF_DPLX (0x0008U) // 0:FULL DUPLEX 1:HALF DUPLEX
#define XR_REG_FLOW_CTL_MODE_MASK (0x0007U) // MODE BITMASK
#define XR_REG_FLOW_CTL_NONE (0x0000U) // NO FLOW CONTROL
#define XR_REG_FLOW_CTL_HW (0x0001U) // HARDWARE FLOW CONTROL
#define XR_REG_FLOW_CTL_SW (0x0002U) // SOFTWARE FLOW CONTROL
#define XR_REG_FLOW_CTL_MMMRX (0x0003U) // MULTIDROP RX UPON ADDRESS MATCH
#define XR_REG_FLOW_CTL_MMMRXTX (0x0004U) // MULTIDROP RX/TX UPON ADDRESS MATCH
#define XR_REG_ACM_GPIO_MODE (0x0217U) // GPIO MODE REGISTER IN CDCACM MODE
#define XR_REG_GPIO_MODE (0x0C0CU) // GPIO MODE REGISTER IN CUSTOM MODE
#define XR_REG_GPIO_MODE_GPIO (0x0000U) // ALL GPIO PINS ACM PROGRAMMABLE
#define XR_REG_GPIO_MODE_FC_RTSCTS (0x0001U) // AUTO RTSCTS HW FC (GPIO 4/5)
#define XR_REG_GPIO_MODE_FC_DTRDSR (0x0002U) // AUTO DTRDSR HW FC (GPIO 2/3)
#define XR_REG_GPIO_MODE_ATE (0x0003U) // AUTO TRANSCEIVER ENABLE DURING TX (GPIO 5)
#define XR_REG_GPIO_MODE_ATE_ADDRESS (0x0004U) // AUTO TRANSCEIVER ENABLE ON ADDRESS MATCH (GPIO 5)
#define XR_REG_ACM_GPIO_DIR (0x0218U) // GPIO DIRECTION REGISTER CDCACM MODE, 0:IN 1:OUT
#define XR_REG_GPIO_DIR (0x0C0DU) // GPIO DIRECTION REGISTER CUSTOM MODE, 0:IN 1:OUT
#define XR_REG_ACM_GPIO_INT (0x0219U) // GPIO PIN CHANGE INTERRUPT ENABLE CDCACM MODE, 0: ENABLED 1: DISABLED
#define XR_REG_GPIO_INT (0x0C11U) // GPIO PIN CHANGE INTERRUPT ENABLE CUSTOM MODE, 0: ENABLED 1: DISABLED
#define XR_REG_GPIO_MASK (0x001FU) // GPIO REGISTERS BITMASK
#define XR_REG_UART_ENABLE (0x0C00U) // UART I/O ENABLE REGISTER
#define XR_REG_UART_ENABLE_RX (0x0002U) // 0:DISABLED 1:ENABLED
#define XR_REG_UART_ENABLE_TX (0x0001U) // 0:DISABLED 1:ENABLED
#define XR_REG_ERROR_STATUS (0x0C09U) // ERROR STATUS REGISTER
#define XR_REG_ERROR_STATUS_MASK (0x00F8U) // ERROR STATUS BITMASK
#define XR_REG_ERROR_STATUS_ERROR (0x0070U) // ERROR STATUS ERROR BITMASK
#define XR_REG_ERROR_STATUS_BREAK (0x0008U) // BREAK HAS BEEN DETECTED
#define XR_REG_ERROR_STATUS_OVERRUN (0x0010U) // RX OVERRUN ERROR
#define XR_REG_ERROR_STATUS_PARITY (0x0020U) // PARITY ERROR
#define XR_REG_ERROR_STATUS_FRAME (0x0040U) // FRAMING ERROR
#define XR_REG_ERROR_STATUS_BREAK (0x0080U) // BREAK IS BEING DETECTED
#define XR_REG_TX_BREAK (0x0C0AU) // TRANSMIT BREAK. 0X0001-0XFFE TIME IN MS, 0X0000 STOP, 0X0FFF BREAK ON
#define XR_REG_XCVR_EN_DELAY (0x0C0BU) // TURN-ARROUND DELAY IN BIT-TIMES 0X0000-0X000F
#define XR_REG_GPIO_SET (0x0C0EU) // 1:SET GPIO PIN
#define XR_REG_GPIO_CLR (0x0C0FU) // 1:CLEAR GPIO PIN
#define XR_REG_GPIO_STATUS (0x0C10U) // READ GPIO PINS
#define XR_REG_CUSTOMISED_INT (0x0C12U) // 0:STANDARD 1:CUSTOM SEE DATA SHEET
#define XR_REG_PIN_PULLUP_ENABLE (0x0C14U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX
#define XR_REG_PIN_PULLDOWN_ENABLE (0x0C15U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX
#define XR_REG_LOOPBACK (0x0C16U) // 0:DISABLE 1:ENABLE, SEE DATA SHEET
#define XR_REG_RX_FIFO_LATENCY (0x0CC2U) // FIFO LATENCY REGISTER
#define XR_REG_RX_FIFO_LATENCY_ENABLE (0x0001U) //
#define XR_REG_WIDE_MODE (0x0D02U)
#define XR_REG_WIDE_MODE_ENABLE (0x0001U)
#define XR_REG_XON_CHAR (0x0C07U)
#define XR_REG_XOFF_CHAR (0x0C08U)
#define XR_REG_TX_FIFO_RESET (0x0C80U) // 1: RESET, SELF-CLEARING
#define XR_REG_TX_FIFO_COUNT (0x0C81U) // READ-ONLY
#define XR_REG_RX_FIFO_RESET (0x0CC0U) // 1: RESET, SELF-CLEARING
#define XR_REG_RX_FIFO_COUNT (0x0CC1U) // READ-ONLY
#define XR_WRITE_REQUEST_TYPE (0x40U)
#define XR_READ_REQUEST_TYPE (0xC0U)
#define XR_MAX_ENDPOINTS 4
class XR21B1411 : public ACM {
protected:
public:
XR21B1411(USB *pusb, CDCAsyncOper *pasync);
/**
* Used by the USB core to check what this driver support.
* @param vid The device's VID.
* @param pid The device's PID.
* @return Returns true if the device's VID and PID matches this driver.
*/
virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
return (((vid == 0x2890U) && (pid == 0x0201U)) || ((vid == 0x04e2U) && (pid == 0x1411U)));
};
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
virtual tty_features enhanced_features(void) {
tty_features rv;
rv.enhanced = true;
rv.autoflow_RTS = true;
rv.autoflow_DSR = true;
rv.autoflow_XON = true;
rv.half_duplex = true;
rv.wide = true;
return rv;
};
uint8_t read_register(uint16_t reg, uint16_t *val) {
return (pUsb->ctrlReq(bAddress, 0, XR_READ_REQUEST_TYPE, 1, 0, 0, reg, 2, 2, (uint8_t *)val, NULL));
}
uint8_t write_register(uint16_t reg, uint16_t val) {
return (pUsb->ctrlReq(bAddress, 0, XR_WRITE_REQUEST_TYPE, 0, BGRAB0(val), BGRAB1(val), reg, 0, 0, NULL, NULL));
}
////////////////////////////////////////////////////////////////////////
// The following methods set the CDC-ACM defaults.
////////////////////////////////////////////////////////////////////////
virtual void autoflowRTS(bool s) {
uint16_t val;
uint8_t rval;
rval = read_register(XR_REG_ACM_FLOW_CTL, &val);
if(!rval) {
if(s) {
val &= XR_REG_FLOW_CTL_HALF_DPLX;
val |= XR_REG_FLOW_CTL_HW;
} else {
val &= XR_REG_FLOW_CTL_HALF_DPLX;
}
rval = write_register(XR_REG_ACM_FLOW_CTL, val);
if(!rval) {
rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);
if(!rval) {
// ACM commands apply the new settings.
LINE_CODING LCT;
rval = GetLineCoding(&LCT);
if(!rval) {
rval = SetLineCoding(&LCT);
if(!rval) {
_enhanced_status.autoflow_XON = false;
_enhanced_status.autoflow_DSR = false;
_enhanced_status.autoflow_RTS = s;
}
}
}
}
}
};
virtual void autoflowDSR(bool s) {
uint16_t val;
uint8_t rval;
rval = read_register(XR_REG_ACM_FLOW_CTL, &val);
if(!rval) {
if(s) {
val &= XR_REG_FLOW_CTL_HALF_DPLX;
val |= XR_REG_FLOW_CTL_HW;
} else {
val &= XR_REG_FLOW_CTL_HALF_DPLX;
}
rval = write_register(XR_REG_ACM_FLOW_CTL, val);
if(!rval) {
if(s) {
rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_FC_DTRDSR);
} else {
rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);
}
if(!rval) {
// ACM commands apply the new settings.
LINE_CODING LCT;
rval = GetLineCoding(&LCT);
if(!rval) {
rval = SetLineCoding(&LCT);
if(!rval) {
_enhanced_status.autoflow_XON = false;
_enhanced_status.autoflow_RTS = false;
_enhanced_status.autoflow_DSR = s;
}
}
}
}
}
};
virtual void autoflowXON(bool s) {
// NOTE: hardware defaults to the normal XON/XOFF
uint16_t val;
uint8_t rval;
rval = read_register(XR_REG_ACM_FLOW_CTL, &val);
if(!rval) {
if(s) {
val &= XR_REG_FLOW_CTL_HALF_DPLX;
val |= XR_REG_FLOW_CTL_SW;
} else {
val &= XR_REG_FLOW_CTL_HALF_DPLX;
}
rval = write_register(XR_REG_ACM_FLOW_CTL, val);
if(!rval) {
rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);
if(!rval) {
// ACM commands apply the new settings.
LINE_CODING LCT;
rval = GetLineCoding(&LCT);
if(!rval) {
rval = SetLineCoding(&LCT);
if(!rval) {
_enhanced_status.autoflow_RTS = false;
_enhanced_status.autoflow_DSR = false;
_enhanced_status.autoflow_XON = s;
}
}
}
}
}
};
virtual void half_duplex(bool s) {
uint16_t val;
uint8_t rval;
rval = read_register(XR_REG_ACM_FLOW_CTL, &val);
if(!rval) {
if(s) {
val |= XR_REG_FLOW_CTL_HALF_DPLX;
} else {
val &= XR_REG_FLOW_CTL_MODE_MASK;
}
rval = write_register(XR_REG_ACM_FLOW_CTL, val);
if(!rval) {
// ACM commands apply the new settings.
LINE_CODING LCT;
rval = GetLineCoding(&LCT);
if(!rval) {
rval = SetLineCoding(&LCT);
if(!rval) {
_enhanced_status.half_duplex = s;
}
}
}
}
};
};
#endif // __CDCPROLIFIC_H__

View file

@ -30,21 +30,20 @@ bNumEP(1),
qNextPollTime(0),
bPollEnable(false),
ready(false) {
_enhanced_status = enhanced_features(); // Set up features
for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
//epInfo[i].bmNakPower = USB_NAK_NOWAIT;
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
epInfo[i].bmNakPower = (i == epDataInIndex) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
//if (!i)
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
}
if(pUsb)
pUsb->RegisterDeviceClass(this);
}
uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
uint8_t buf[constBufSize];
@ -170,6 +169,13 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
if(rcode)
goto FailSetConfDescr;
// Set up features status
_enhanced_status = enhanced_features();
half_duplex(false);
autoflowRTS(false);
autoflowDSR(false);
autoflowXON(false);
wide(false); // Always false, because this is only available in custom mode.
rcode = pAsync->OnInit(this);
if(rcode)
@ -222,9 +228,9 @@ Fail:
}
void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
//ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
//ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
//ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
bConfNum = conf;
@ -249,6 +255,7 @@ void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
}
uint8_t ACM::Release() {
ready = false;
pUsb->GetAddressPool().FreeAddress(bAddress);
bControlIface = 0;
@ -267,33 +274,6 @@ uint8_t ACM::Poll() {
if(!bPollEnable)
return 0;
//uint32_t time_now = millis();
//if (qNextPollTime <= time_now)
//{
// qNextPollTime = time_now + 100;
// uint8_t rcode;
// const uint8_t constBufSize = 16;
// uint8_t buf[constBufSize];
// for (uint8_t i=0; i<constBufSize; i++)
// buf[i] = 0;
// uint16_t read = (constBufSize > epInfo[epInterruptInIndex].maxPktSize)
// ? epInfo[epInterruptInIndex].maxPktSize : constBufSize;
// rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf);
// if (rcode)
// return rcode;
// for (uint8_t i=0; i<read; i++)
// {
// PrintHex<uint8_t>(buf[i]);
// USB_HOST_SERIAL.print(" ");
// }
// USBTRACE("\r\n");
//}
return rcode;
}
@ -336,16 +316,16 @@ uint8_t ACM::SendBreak(uint16_t duration) {
void ACM::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
Notify(PSTR("Endpoint descriptor:"), 0x80);
Notify(PSTR("\r\nLength:\t\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
Notify(PSTR("\r\nType:\t\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
Notify(PSTR("\r\nAddress:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
Notify(PSTR("\r\nAttributes:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
Notify(PSTR("\r\n"), 0x80);
}

View file

@ -129,11 +129,34 @@ class CDCAsyncOper {
public:
virtual uint8_t OnInit(ACM *pacm) {
return 0;
};
//virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0;
//virtual void OnDisconnected(ACM *pacm) = 0;
};
/**
* This structure is used to report the extended capabilities of the connected device.
* It is also used to report the current status.
* Regular CDC-ACM reports all as false.
*/
typedef struct {
union {
uint8_t tty;
struct {
bool enhanced : 1; // Do we have the ability to set/clear any features?
// Status and 8th bit in data stream.
// Presence only indicates feature is available, but this isn't used for CDC-ACM.
bool wide : 1;
bool autoflow_RTS : 1; // Has autoflow on RTS/CTS
bool autoflow_DSR : 1; // Has autoflow on DTR/DSR
bool autoflow_XON : 1; // Has autoflow XON/XOFF
bool half_duplex : 1; // Has half-duplex capability.
} __attribute__((packed));
};
} tty_features;
#define ACM_MAX_ENDPOINTS 4
@ -151,8 +174,9 @@ protected:
uint8_t bDataIface; // Data interface value
uint8_t bNumEP; // total number of EP in the configuration
uint32_t qNextPollTime; // next poll time
bool bPollEnable; // poll enable flag
bool ready; //device ready indicator
volatile bool bPollEnable; // poll enable flag
volatile bool ready; //device ready indicator
tty_features _enhanced_status; // current status
EpInfo epInfo[ACM_MAX_ENDPOINTS];
@ -170,7 +194,7 @@ public:
uint8_t SendBreak(uint16_t duration);
uint8_t GetNotif(uint16_t *bytes_rcvd, uint8_t *dataptr);
// Methods for recieving and sending data
// Methods for receiving and sending data
uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr);
uint8_t SndData(uint16_t nbytes, uint8_t *dataptr);
@ -179,6 +203,10 @@ public:
uint8_t Release();
uint8_t Poll();
bool available(void) {
};
virtual uint8_t GetAddress() {
return bAddress;
};
@ -187,6 +215,36 @@ public:
return ready;
};
virtual tty_features enhanced_status(void) {
return _enhanced_status;
};
virtual tty_features enhanced_features(void) {
tty_features rv;
rv.enhanced = false;
rv.autoflow_RTS = false;
rv.autoflow_DSR = false;
rv.autoflow_XON = false;
rv.half_duplex = false;
rv.wide = false;
return rv;
};
virtual void autoflowRTS(bool s) {
};
virtual void autoflowDSR(bool s) {
};
virtual void autoflowXON(bool s) {
};
virtual void half_duplex(bool s) {
};
virtual void wide(bool s) {
};
// UsbConfigXtracter implementation
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
};

View file

@ -30,9 +30,7 @@ wFTDIType(0) {
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
//if (!i)
epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
epInfo[i].bmNakPower = (i==epDataInIndex) ? USB_NAK_NOWAIT: USB_NAK_MAX_POWER;
}
if(pUsb)
pUsb->RegisterDeviceClass(this);
@ -46,11 +44,8 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
uint8_t rcode;
UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL;
//uint8_t len = 0;
//uint16_t cd_len = 0;
uint8_t num_of_conf; // number of configurations
//uint8_t num_of_intf; // number of interfaces
AddressPool &addrPool = pUsb->GetAddressPool();
@ -324,16 +319,16 @@ uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) {
void FTDI::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
Notify(PSTR("Endpoint descriptor:"), 0x80);
Notify(PSTR("\r\nLength:\t\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
Notify(PSTR("\r\nType:\t\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
Notify(PSTR("\r\nAddress:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
Notify(PSTR("\r\nAttributes:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
Notify(PSTR("\r\n"), 0x80);
}

View file

@ -197,12 +197,6 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescrip
Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
//Notify(PSTR("\r\nbDescrType:\t\t"));
//PrintHex<uint8_t>(pDesc->bDescrType);
//
//Notify(PSTR("\r\nwDescriptorLength:\t"));
//PrintHex<uint16_t>(pDesc->wDescriptorLength);
for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);

View file

@ -0,0 +1,83 @@
#include <cdc_XR21B1411.h>
// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
class ACMAsyncOper : public CDCAsyncOper
{
public:
uint8_t OnInit(ACM *pacm);
};
uint8_t ACMAsyncOper::OnInit(ACM *pacm)
{
uint8_t rcode;
// Set DTR = 1 RTS=1
rcode = pacm->SetControlLineState(3);
if (rcode)
{
ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
return rcode;
}
LINE_CODING lc;
lc.dwDTERate = 115200;
lc.bCharFormat = 0;
lc.bParityType = 0;
lc.bDataBits = 8;
rcode = pacm->SetLineCoding(&lc);
if (rcode)
ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
return rcode;
}
USB Usb;
ACMAsyncOper AsyncOper;
XR21B1411 Acm(&Usb, &AsyncOper);
void setup() {
Serial.begin( 115200 );
#if !defined(__MIPSEL__)
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
Serial.println("\r\n\r\nStart");
if (Usb.Init() == -1) Serial.println("OSCOKIRQ failed to assert");
}
void loop() {
Usb.Task();
if( Acm.isReady()) {
uint8_t rcode;
uint8_t buf[1];
uint16_t rcvd = 1;
/* read keyboard */
if(Serial.available()) {
uint8_t data = Serial.read();
/* send */
rcode = Acm.SndData(1, &data);
if (rcode)
ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
}
/* read XR serial */
rcode = Acm.RcvData(&rcvd, buf);
if (rcode && rcode != hrNAK)
ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
if( rcvd ) { //more than zero bytes received
for(uint16_t i=0; i < rcvd; i++ ) {
Serial.print((char)buf[i]);
}
}
}
}

16
hid.cpp
View file

@ -24,7 +24,7 @@ uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) {
const uint8_t constBufLen = 64;
uint8_t buf[constBufLen];
uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser);
//return ((rcode != hrSTALL) ? rcode : 0);
@ -35,7 +35,7 @@ uint8_t HID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) {
const uint8_t constBufLen = 64;
uint8_t buf[constBufLen];
uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
HID_DESCRIPTOR_REPORT, wIndex, 128, constBufLen, buf, (USBReadParser*)parser);
//return ((rcode != hrSTALL) ? rcode : 0);
@ -48,27 +48,27 @@ uint8_t HID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) {
//}
uint8_t HID::SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) {
return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HIDOUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
}
uint8_t HID::GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) {
return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HIDIN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
}
uint8_t HID::GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL));
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL));
}
uint8_t HID::SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL));
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL));
}
uint8_t HID::SetProtocol(uint8_t iface, uint8_t protocol) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL));
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDOUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL));
}
uint8_t HID::GetProtocol(uint8_t iface, uint8_t* dataptr) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL));
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HIDIN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL));
}
void HID::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {

6
hid.h
View file

@ -60,9 +60,9 @@ e-mail : support@circuitsathome.com
#define TAG_LOCAL_USAGEMAX 0x20
/* HID requests */
#define bmREQ_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
#define bmREQ_HID_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
#define bmREQ_HID_REPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
#define bmREQ_HIDOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
#define bmREQ_HIDIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
#define bmREQ_HIDREPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
/* HID constants. Not part of chapter 9 */
/* Class-Specific Requests */

View file

@ -168,8 +168,8 @@ uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) {
// [a-z]
if (VALUE_WITHIN(key, 0x04, 0x1d)) {
// Upper case letters
if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && shift) ||
(kbdLockingKeys.kbdLeds.bmCapsLock == 1 && shift == 0))
if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && (mod & 2)) ||
(kbdLockingKeys.kbdLeds.bmCapsLock == 1 && (mod & 2) == 0))
return (key - 4 + 'A');
// Lower case letters

View file

@ -232,10 +232,6 @@ public:
return bAddress;
};
virtual bool isReady() {
return bPollEnable;
};
// UsbConfigXtracter implementation
// Method should be defined here if virtual.
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);

View file

@ -1233,22 +1233,10 @@ ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /
void ReportDescParserBase::SetUsagePage(uint16_t page) {
pfUsage = NULL;
if(VALUE_BETWEEN(page, 0x00, 0x11))
if(VALUE_BETWEEN(page, 0x00, 0x11)) {
pfUsage = (usagePageFunctions[page - 1]);
// Dead code...
//
// pfUsage = (UsagePageFunc)pgm_read_pointer(usagePageFunctions[page - 1]);
//else if (page > 0x7f && page < 0x84)
// E_Notify(pstrUsagePageMonitor);
//else if (page > 0x83 && page < 0x8c)
// E_Notify(pstrUsagePagePower);
//else if (page > 0x8b && page < 0x92)
// E_Notify((char*)pgm_read_pointer(&usagePageTitles1[page - 0x8c]));
//else if (page > 0xfeff && page <= 0xffff)
// E_Notify(pstrUsagePageVendorDefined);
//
else
} else {
switch(page) {
case 0x14:
pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage;
@ -1257,6 +1245,7 @@ void ReportDescParserBase::SetUsagePage(uint16_t page) {
pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage;
break;
}
}
}
void ReportDescParserBase::PrintUsagePage(uint16_t page) {

View file

@ -418,9 +418,3 @@ uint8_t HIDUniversal::Poll() {
}
return rcode;
}
//Send a report to interrupt out endpoint. This is NOT SetReport() request!
uint8_t HIDUniversal::SndRpt(uint16_t nbytes, uint8_t *dataptr) {
return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr);
}

View file

@ -100,9 +100,6 @@ public:
// UsbConfigXtracter implementation
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
// Send report - do not mix with SetReport()!
uint8_t SndRpt(uint16_t nbytes, uint8_t *dataptr);
};
#endif // __HIDUNIVERSAL_H__

View file

@ -19,6 +19,8 @@ e-mail : support@circuitsathome.com
#include "hidusagestr.h"
// This is here why?
//const char *usagePageTitles0[] PROGMEM =
//{
// pstrUsagePageGenericDesktopControls ,

View file

@ -25,11 +25,6 @@ e-mail : support@circuitsathome.com
/* Arduino pin definitions */
/* pin numbers to port numbers */
//#define MAX_INT 9 // Duemielanove
//#define MAX_GPX 8
#define SE0 0
#define SE1 1
#define FSHOST 2

View file

@ -22,7 +22,7 @@ e-mail : support@circuitsathome.com
#define _Max_LCD_h_
#include "Usb.h"
#include <Print.h>
#include "Print.h"
// commands
#define LCD_CLEARDISPLAY 0x01