Zoltan Hudak / UsbHostMAX3421E

Dependents:   UsbHostMAX3421E_Hello

Committer:
hudakz
Date:
Sun Jul 12 20:39:26 2020 +0000
Revision:
0:84353c479782
Child:
1:2263e77400e9
MAX3421E-based USB Host Shield Library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:84353c479782 1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
hudakz 0:84353c479782 2
hudakz 0:84353c479782 3 This software may be distributed and modified under the terms of the GNU
hudakz 0:84353c479782 4 General Public License version 2 (GPL2) as published by the Free Software
hudakz 0:84353c479782 5 Foundation and appearing in the file GPL2.TXT included in the packaging of
hudakz 0:84353c479782 6 this file. Please note that GPL2 Section 2[b] requires that all works based
hudakz 0:84353c479782 7 on this software must also be made publicly available under the terms of
hudakz 0:84353c479782 8 the GPL2 ("Copyleft").
hudakz 0:84353c479782 9
hudakz 0:84353c479782 10 Contact information
hudakz 0:84353c479782 11 -------------------
hudakz 0:84353c479782 12
hudakz 0:84353c479782 13 Circuits At Home, LTD
hudakz 0:84353c479782 14 Web : http://www.circuitsathome.com
hudakz 0:84353c479782 15 e-mail : support@circuitsathome.com
hudakz 0:84353c479782 16 */
hudakz 0:84353c479782 17 #include "cdcacm.h"
hudakz 0:84353c479782 18
hudakz 0:84353c479782 19 const uint8_t ACM::epDataInIndex = 1;
hudakz 0:84353c479782 20 const uint8_t ACM::epDataOutIndex = 2;
hudakz 0:84353c479782 21 const uint8_t ACM::epInterruptInIndex = 3;
hudakz 0:84353c479782 22
hudakz 0:84353c479782 23 ACM::ACM(USB *p, CDCAsyncOper *pasync) :
hudakz 0:84353c479782 24 pUsb(p),
hudakz 0:84353c479782 25 pAsync(pasync),
hudakz 0:84353c479782 26 bAddress(0),
hudakz 0:84353c479782 27 bControlIface(0),
hudakz 0:84353c479782 28 bDataIface(0),
hudakz 0:84353c479782 29 bNumEP(1),
hudakz 0:84353c479782 30 qNextPollTime(0),
hudakz 0:84353c479782 31 bPollEnable(false),
hudakz 0:84353c479782 32 ready(false) {
hudakz 0:84353c479782 33 _enhanced_status = enhanced_features(); // Set up features
hudakz 0:84353c479782 34 for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {
hudakz 0:84353c479782 35 epInfo[i].epAddr = 0;
hudakz 0:84353c479782 36 epInfo[i].maxPktSize = (i) ? 0 : 8;
hudakz 0:84353c479782 37 epInfo[i].bmSndToggle = 0;
hudakz 0:84353c479782 38 epInfo[i].bmRcvToggle = 0;
hudakz 0:84353c479782 39 epInfo[i].bmNakPower = (i == epDataInIndex) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
hudakz 0:84353c479782 40
hudakz 0:84353c479782 41 }
hudakz 0:84353c479782 42 if(pUsb)
hudakz 0:84353c479782 43 pUsb->RegisterDeviceClass(this);
hudakz 0:84353c479782 44 }
hudakz 0:84353c479782 45
hudakz 0:84353c479782 46 uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
hudakz 0:84353c479782 47
hudakz 0:84353c479782 48 const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
hudakz 0:84353c479782 49
hudakz 0:84353c479782 50 uint8_t buf[constBufSize];
hudakz 0:84353c479782 51 USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
hudakz 0:84353c479782 52
hudakz 0:84353c479782 53 uint8_t rcode;
hudakz 0:84353c479782 54 UsbDevice *p = NULL;
hudakz 0:84353c479782 55 EpInfo *oldep_ptr = NULL;
hudakz 0:84353c479782 56 uint8_t num_of_conf; // number of configurations
hudakz 0:84353c479782 57
hudakz 0:84353c479782 58 AddressPool &addrPool = pUsb->GetAddressPool();
hudakz 0:84353c479782 59
hudakz 0:84353c479782 60 USBTRACE("ACM Init\r\n");
hudakz 0:84353c479782 61
hudakz 0:84353c479782 62 if(bAddress)
hudakz 0:84353c479782 63 return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
hudakz 0:84353c479782 64
hudakz 0:84353c479782 65 // Get pointer to pseudo device with address 0 assigned
hudakz 0:84353c479782 66 p = addrPool.GetUsbDevicePtr(0);
hudakz 0:84353c479782 67
hudakz 0:84353c479782 68 if(!p)
hudakz 0:84353c479782 69 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
hudakz 0:84353c479782 70
hudakz 0:84353c479782 71 if(!p->epinfo) {
hudakz 0:84353c479782 72 USBTRACE("epinfo\r\n");
hudakz 0:84353c479782 73 return USB_ERROR_EPINFO_IS_NULL;
hudakz 0:84353c479782 74 }
hudakz 0:84353c479782 75
hudakz 0:84353c479782 76 // Save old pointer to EP_RECORD of address 0
hudakz 0:84353c479782 77 oldep_ptr = p->epinfo;
hudakz 0:84353c479782 78
hudakz 0:84353c479782 79 // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
hudakz 0:84353c479782 80 p->epinfo = epInfo;
hudakz 0:84353c479782 81
hudakz 0:84353c479782 82 p->lowspeed = lowspeed;
hudakz 0:84353c479782 83
hudakz 0:84353c479782 84 // Get device descriptor
hudakz 0:84353c479782 85 rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
hudakz 0:84353c479782 86
hudakz 0:84353c479782 87 // Restore p->epinfo
hudakz 0:84353c479782 88 p->epinfo = oldep_ptr;
hudakz 0:84353c479782 89
hudakz 0:84353c479782 90 if(rcode)
hudakz 0:84353c479782 91 goto FailGetDevDescr;
hudakz 0:84353c479782 92
hudakz 0:84353c479782 93 // Allocate new address according to device class
hudakz 0:84353c479782 94 bAddress = addrPool.AllocAddress(parent, false, port);
hudakz 0:84353c479782 95
hudakz 0:84353c479782 96 if(!bAddress)
hudakz 0:84353c479782 97 return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
hudakz 0:84353c479782 98
hudakz 0:84353c479782 99 // Extract Max Packet Size from the device descriptor
hudakz 0:84353c479782 100 epInfo[0].maxPktSize = udd->bMaxPacketSize0;
hudakz 0:84353c479782 101
hudakz 0:84353c479782 102 // Assign new address to the device
hudakz 0:84353c479782 103 rcode = pUsb->setAddr(0, 0, bAddress);
hudakz 0:84353c479782 104
hudakz 0:84353c479782 105 if(rcode) {
hudakz 0:84353c479782 106 p->lowspeed = false;
hudakz 0:84353c479782 107 addrPool.FreeAddress(bAddress);
hudakz 0:84353c479782 108 bAddress = 0;
hudakz 0:84353c479782 109 USBTRACE2("setAddr:", rcode);
hudakz 0:84353c479782 110 return rcode;
hudakz 0:84353c479782 111 }
hudakz 0:84353c479782 112
hudakz 0:84353c479782 113 USBTRACE2("Addr:", bAddress);
hudakz 0:84353c479782 114
hudakz 0:84353c479782 115 p->lowspeed = false;
hudakz 0:84353c479782 116
hudakz 0:84353c479782 117 p = addrPool.GetUsbDevicePtr(bAddress);
hudakz 0:84353c479782 118
hudakz 0:84353c479782 119 if(!p)
hudakz 0:84353c479782 120 return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
hudakz 0:84353c479782 121
hudakz 0:84353c479782 122 p->lowspeed = lowspeed;
hudakz 0:84353c479782 123
hudakz 0:84353c479782 124 num_of_conf = udd->bNumConfigurations;
hudakz 0:84353c479782 125
hudakz 0:84353c479782 126 // Assign epInfo to epinfo pointer
hudakz 0:84353c479782 127 rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
hudakz 0:84353c479782 128
hudakz 0:84353c479782 129 if(rcode)
hudakz 0:84353c479782 130 goto FailSetDevTblEntry;
hudakz 0:84353c479782 131
hudakz 0:84353c479782 132 USBTRACE2("NC:", num_of_conf);
hudakz 0:84353c479782 133
hudakz 0:84353c479782 134 for(uint8_t i = 0; i < num_of_conf; i++) {
hudakz 0:84353c479782 135 ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,
hudakz 0:84353c479782 136 CDC_SUBCLASS_ACM,
hudakz 0:84353c479782 137 CDC_PROTOCOL_ITU_T_V_250,
hudakz 0:84353c479782 138 CP_MASK_COMPARE_CLASS |
hudakz 0:84353c479782 139 CP_MASK_COMPARE_SUBCLASS |
hudakz 0:84353c479782 140 CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this);
hudakz 0:84353c479782 141
hudakz 0:84353c479782 142 ConfigDescParser<USB_CLASS_CDC_DATA, 0, 0,
hudakz 0:84353c479782 143 CP_MASK_COMPARE_CLASS> CdcDataParser(this);
hudakz 0:84353c479782 144
hudakz 0:84353c479782 145 rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
hudakz 0:84353c479782 146
hudakz 0:84353c479782 147 if(rcode)
hudakz 0:84353c479782 148 goto FailGetConfDescr;
hudakz 0:84353c479782 149
hudakz 0:84353c479782 150 rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
hudakz 0:84353c479782 151
hudakz 0:84353c479782 152 if(rcode)
hudakz 0:84353c479782 153 goto FailGetConfDescr;
hudakz 0:84353c479782 154
hudakz 0:84353c479782 155 if(bNumEP > 1)
hudakz 0:84353c479782 156 break;
hudakz 0:84353c479782 157 } // for
hudakz 0:84353c479782 158
hudakz 0:84353c479782 159 if(bNumEP < 4)
hudakz 0:84353c479782 160 return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
hudakz 0:84353c479782 161
hudakz 0:84353c479782 162 // Assign epInfo to epinfo pointer
hudakz 0:84353c479782 163 rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
hudakz 0:84353c479782 164
hudakz 0:84353c479782 165 USBTRACE2("Conf:", bConfNum);
hudakz 0:84353c479782 166
hudakz 0:84353c479782 167 // Set Configuration Value
hudakz 0:84353c479782 168 rcode = pUsb->setConf(bAddress, 0, bConfNum);
hudakz 0:84353c479782 169
hudakz 0:84353c479782 170 if(rcode)
hudakz 0:84353c479782 171 goto FailSetConfDescr;
hudakz 0:84353c479782 172
hudakz 0:84353c479782 173 // Set up features status
hudakz 0:84353c479782 174 _enhanced_status = enhanced_features();
hudakz 0:84353c479782 175 half_duplex(false);
hudakz 0:84353c479782 176 autoflowRTS(false);
hudakz 0:84353c479782 177 autoflowDSR(false);
hudakz 0:84353c479782 178 autoflowXON(false);
hudakz 0:84353c479782 179 wide(false); // Always false, because this is only available in custom mode.
hudakz 0:84353c479782 180 rcode = pAsync->OnInit(this);
hudakz 0:84353c479782 181
hudakz 0:84353c479782 182 if(rcode)
hudakz 0:84353c479782 183 goto FailOnInit;
hudakz 0:84353c479782 184
hudakz 0:84353c479782 185 USBTRACE("ACM configured\r\n");
hudakz 0:84353c479782 186
hudakz 0:84353c479782 187 ready = true;
hudakz 0:84353c479782 188
hudakz 0:84353c479782 189 //bPollEnable = true;
hudakz 0:84353c479782 190
hudakz 0:84353c479782 191 //USBTRACE("Poll enabled\r\n");
hudakz 0:84353c479782 192 return 0;
hudakz 0:84353c479782 193
hudakz 0:84353c479782 194 FailGetDevDescr:
hudakz 0:84353c479782 195 #ifdef DEBUG_USB_HOST
hudakz 0:84353c479782 196 NotifyFailGetDevDescr();
hudakz 0:84353c479782 197 goto Fail;
hudakz 0:84353c479782 198 #endif
hudakz 0:84353c479782 199
hudakz 0:84353c479782 200 FailSetDevTblEntry:
hudakz 0:84353c479782 201 #ifdef DEBUG_USB_HOST
hudakz 0:84353c479782 202 NotifyFailSetDevTblEntry();
hudakz 0:84353c479782 203 goto Fail;
hudakz 0:84353c479782 204 #endif
hudakz 0:84353c479782 205
hudakz 0:84353c479782 206 FailGetConfDescr:
hudakz 0:84353c479782 207 #ifdef DEBUG_USB_HOST
hudakz 0:84353c479782 208 NotifyFailGetConfDescr();
hudakz 0:84353c479782 209 goto Fail;
hudakz 0:84353c479782 210 #endif
hudakz 0:84353c479782 211
hudakz 0:84353c479782 212 FailSetConfDescr:
hudakz 0:84353c479782 213 #ifdef DEBUG_USB_HOST
hudakz 0:84353c479782 214 NotifyFailSetConfDescr();
hudakz 0:84353c479782 215 goto Fail;
hudakz 0:84353c479782 216 #endif
hudakz 0:84353c479782 217
hudakz 0:84353c479782 218 FailOnInit:
hudakz 0:84353c479782 219 #ifdef DEBUG_USB_HOST
hudakz 0:84353c479782 220 USBTRACE("OnInit:");
hudakz 0:84353c479782 221 #endif
hudakz 0:84353c479782 222
hudakz 0:84353c479782 223 #ifdef DEBUG_USB_HOST
hudakz 0:84353c479782 224 Fail:
hudakz 0:84353c479782 225 NotifyFail(rcode);
hudakz 0:84353c479782 226 #endif
hudakz 0:84353c479782 227 Release();
hudakz 0:84353c479782 228 return rcode;
hudakz 0:84353c479782 229 }
hudakz 0:84353c479782 230
hudakz 0:84353c479782 231 void ACM::EndpointXtract(uint8_t conf, uint8_t iface __attribute__((unused)), uint8_t alt __attribute__((unused)), uint8_t proto __attribute__((unused)), const USB_ENDPOINT_DESCRIPTOR *pep) {
hudakz 0:84353c479782 232 //ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
hudakz 0:84353c479782 233 //ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
hudakz 0:84353c479782 234 //ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
hudakz 0:84353c479782 235
hudakz 0:84353c479782 236 bConfNum = conf;
hudakz 0:84353c479782 237
hudakz 0:84353c479782 238 uint8_t index;
hudakz 0:84353c479782 239
hudakz 0:84353c479782 240 if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_INTERRUPT && (pep->bEndpointAddress & 0x80) == 0x80)
hudakz 0:84353c479782 241 index = epInterruptInIndex;
hudakz 0:84353c479782 242 else if((pep->bmAttributes & bmUSB_TRANSFER_TYPE) == USB_TRANSFER_TYPE_BULK)
hudakz 0:84353c479782 243 index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
hudakz 0:84353c479782 244 else
hudakz 0:84353c479782 245 return;
hudakz 0:84353c479782 246
hudakz 0:84353c479782 247 // Fill in the endpoint info structure
hudakz 0:84353c479782 248 epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
hudakz 0:84353c479782 249 epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
hudakz 0:84353c479782 250 epInfo[index].bmSndToggle = 0;
hudakz 0:84353c479782 251 epInfo[index].bmRcvToggle = 0;
hudakz 0:84353c479782 252
hudakz 0:84353c479782 253 bNumEP++;
hudakz 0:84353c479782 254
hudakz 0:84353c479782 255 PrintEndpointDescriptor(pep);
hudakz 0:84353c479782 256 }
hudakz 0:84353c479782 257
hudakz 0:84353c479782 258 uint8_t ACM::Release() {
hudakz 0:84353c479782 259 ready = false;
hudakz 0:84353c479782 260 pUsb->GetAddressPool().FreeAddress(bAddress);
hudakz 0:84353c479782 261
hudakz 0:84353c479782 262 bControlIface = 0;
hudakz 0:84353c479782 263 bDataIface = 0;
hudakz 0:84353c479782 264 bNumEP = 1;
hudakz 0:84353c479782 265
hudakz 0:84353c479782 266 bAddress = 0;
hudakz 0:84353c479782 267 qNextPollTime = 0;
hudakz 0:84353c479782 268 bPollEnable = false;
hudakz 0:84353c479782 269 return 0;
hudakz 0:84353c479782 270 }
hudakz 0:84353c479782 271
hudakz 0:84353c479782 272 uint8_t ACM::Poll() {
hudakz 0:84353c479782 273 //uint8_t rcode = 0;
hudakz 0:84353c479782 274 //if(!bPollEnable)
hudakz 0:84353c479782 275 // return 0;
hudakz 0:84353c479782 276 //return rcode;
hudakz 0:84353c479782 277 return 0;
hudakz 0:84353c479782 278 }
hudakz 0:84353c479782 279
hudakz 0:84353c479782 280 uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
hudakz 0:84353c479782 281 uint8_t rv = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
hudakz 0:84353c479782 282 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 283 Release();
hudakz 0:84353c479782 284 }
hudakz 0:84353c479782 285 return rv;
hudakz 0:84353c479782 286 }
hudakz 0:84353c479782 287
hudakz 0:84353c479782 288 uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) {
hudakz 0:84353c479782 289 uint8_t rv = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
hudakz 0:84353c479782 290 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 291 Release();
hudakz 0:84353c479782 292 }
hudakz 0:84353c479782 293 return rv;
hudakz 0:84353c479782 294 }
hudakz 0:84353c479782 295
hudakz 0:84353c479782 296 uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
hudakz 0:84353c479782 297 uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
hudakz 0:84353c479782 298 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 299 Release();
hudakz 0:84353c479782 300 }
hudakz 0:84353c479782 301 return rv;
hudakz 0:84353c479782 302 }
hudakz 0:84353c479782 303
hudakz 0:84353c479782 304 uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
hudakz 0:84353c479782 305 uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
hudakz 0:84353c479782 306 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 307 Release();
hudakz 0:84353c479782 308 }
hudakz 0:84353c479782 309 return rv;
hudakz 0:84353c479782 310 }
hudakz 0:84353c479782 311
hudakz 0:84353c479782 312 uint8_t ACM::ClearCommFeature(uint16_t fid) {
hudakz 0:84353c479782 313 uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL));
hudakz 0:84353c479782 314 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 315 Release();
hudakz 0:84353c479782 316 }
hudakz 0:84353c479782 317 return rv;
hudakz 0:84353c479782 318 }
hudakz 0:84353c479782 319
hudakz 0:84353c479782 320 uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) {
hudakz 0:84353c479782 321 uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
hudakz 0:84353c479782 322 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 323 Release();
hudakz 0:84353c479782 324 }
hudakz 0:84353c479782 325 return rv;
hudakz 0:84353c479782 326 }
hudakz 0:84353c479782 327
hudakz 0:84353c479782 328 uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) {
hudakz 0:84353c479782 329 uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
hudakz 0:84353c479782 330 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 331 Release();
hudakz 0:84353c479782 332 }
hudakz 0:84353c479782 333 return rv;
hudakz 0:84353c479782 334 }
hudakz 0:84353c479782 335
hudakz 0:84353c479782 336 uint8_t ACM::SetControlLineState(uint8_t state) {
hudakz 0:84353c479782 337 uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL));
hudakz 0:84353c479782 338 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 339 Release();
hudakz 0:84353c479782 340 }
hudakz 0:84353c479782 341 return rv;
hudakz 0:84353c479782 342 }
hudakz 0:84353c479782 343
hudakz 0:84353c479782 344 uint8_t ACM::SendBreak(uint16_t duration) {
hudakz 0:84353c479782 345 uint8_t rv = ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL));
hudakz 0:84353c479782 346 if(rv && rv != hrNAK) {
hudakz 0:84353c479782 347 Release();
hudakz 0:84353c479782 348 }
hudakz 0:84353c479782 349 return rv;
hudakz 0:84353c479782 350 }
hudakz 0:84353c479782 351
hudakz 0:84353c479782 352 void ACM::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
hudakz 0:84353c479782 353 Notify(PSTR("Endpoint descriptor:"), 0x80);
hudakz 0:84353c479782 354 Notify(PSTR("\r\nLength:\t\t"), 0x80);
hudakz 0:84353c479782 355 D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
hudakz 0:84353c479782 356 Notify(PSTR("\r\nType:\t\t"), 0x80);
hudakz 0:84353c479782 357 D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
hudakz 0:84353c479782 358 Notify(PSTR("\r\nAddress:\t"), 0x80);
hudakz 0:84353c479782 359 D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
hudakz 0:84353c479782 360 Notify(PSTR("\r\nAttributes:\t"), 0x80);
hudakz 0:84353c479782 361 D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
hudakz 0:84353c479782 362 Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
hudakz 0:84353c479782 363 D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
hudakz 0:84353c479782 364 Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
hudakz 0:84353c479782 365 D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
hudakz 0:84353c479782 366 Notify(PSTR("\r\n"), 0x80);
hudakz 0:84353c479782 367 }