Added to LPC4088-USBHost the USBHostMidi class. Plugin an usb midi interface to the usb host of lpc4088 allows to send midi event to the midi interface. For the moment I can not be able to get event from the interface by using the attacheNoteOn or other triggers...

Dependencies:   FATFileSystem mbed-rtos

Fork of LPC4088-USBHost by Norimasa Okamoto

Committer:
Grag38
Date:
Mon Apr 06 12:46:58 2015 +0000
Revision:
1:d652de69bd1a
Parent:
0:148fca6fd246
Added USBHostMidi to drive midi interface.; ; Tested to send Midi messages from LPC4088. This works.; ; Need to test with incomming events.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:148fca6fd246 1 /* mbed USBHost Library
va009039 0:148fca6fd246 2 * Copyright (c) 2006-2013 ARM Limited
va009039 0:148fca6fd246 3 *
va009039 0:148fca6fd246 4 * Licensed under the Apache License, Version 2.0 (the "License");
va009039 0:148fca6fd246 5 * you may not use this file except in compliance with the License.
va009039 0:148fca6fd246 6 * You may obtain a copy of the License at
va009039 0:148fca6fd246 7 *
va009039 0:148fca6fd246 8 * http://www.apache.org/licenses/LICENSE-2.0
va009039 0:148fca6fd246 9 *
va009039 0:148fca6fd246 10 * Unless required by applicable law or agreed to in writing, software
va009039 0:148fca6fd246 11 * distributed under the License is distributed on an "AS IS" BASIS,
va009039 0:148fca6fd246 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
va009039 0:148fca6fd246 13 * See the License for the specific language governing permissions and
va009039 0:148fca6fd246 14 * limitations under the License.
va009039 0:148fca6fd246 15 */
va009039 0:148fca6fd246 16
va009039 0:148fca6fd246 17 #include "USBHALHost.h"
va009039 0:148fca6fd246 18 //#define _USB_DBG
va009039 0:148fca6fd246 19 #include "BaseUsbHostDebug.h"
va009039 0:148fca6fd246 20 #include "BaseUsbHostTest.h"
va009039 0:148fca6fd246 21
va009039 0:148fca6fd246 22 #ifndef CTASSERT
va009039 0:148fca6fd246 23 template <bool>struct CtAssert;
va009039 0:148fca6fd246 24 template <>struct CtAssert<true> {};
va009039 0:148fca6fd246 25 #define CTASSERT(A) CtAssert<A>();
va009039 0:148fca6fd246 26 #endif
va009039 0:148fca6fd246 27
va009039 0:148fca6fd246 28 #ifdef _USB_DBG
va009039 0:148fca6fd246 29 #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
va009039 0:148fca6fd246 30 #define USB_DBG_HEX(A,B) debug_hex(A,B)
va009039 0:148fca6fd246 31 void debug_hex(uint8_t* buf, int size);
va009039 0:148fca6fd246 32 #else
va009039 0:148fca6fd246 33 #define USB_DBG(...) while(0)
va009039 0:148fca6fd246 34 #define USB_DBG_HEX(A,B) while(0)
va009039 0:148fca6fd246 35 #endif
va009039 0:148fca6fd246 36
va009039 0:148fca6fd246 37 #ifdef _USB_TEST
va009039 0:148fca6fd246 38 #define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
va009039 0:148fca6fd246 39 #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
va009039 0:148fca6fd246 40 #else
va009039 0:148fca6fd246 41 #define USB_TEST_ASSERT(A) while(0)
va009039 0:148fca6fd246 42 #define USB_TEST_ASSERT_FALSE(A) while(0)
va009039 0:148fca6fd246 43 #endif
va009039 0:148fca6fd246 44
va009039 0:148fca6fd246 45 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
va009039 0:148fca6fd246 46
va009039 0:148fca6fd246 47 // bits of the USB/OTG clock control register
va009039 0:148fca6fd246 48 #define HOST_CLK_EN (1<<0)
va009039 0:148fca6fd246 49 #define DEV_CLK_EN (1<<1)
va009039 0:148fca6fd246 50 #define PORTSEL_CLK_EN (1<<3)
va009039 0:148fca6fd246 51 #define AHB_CLK_EN (1<<4)
va009039 0:148fca6fd246 52
va009039 0:148fca6fd246 53 // bits of the USB/OTG clock status register
va009039 0:148fca6fd246 54 #define HOST_CLK_ON (1<<0)
va009039 0:148fca6fd246 55 #define DEV_CLK_ON (1<<1)
va009039 0:148fca6fd246 56 #define PORTSEL_CLK_ON (1<<3)
va009039 0:148fca6fd246 57 #define AHB_CLK_ON (1<<4)
va009039 0:148fca6fd246 58
va009039 0:148fca6fd246 59 // we need host clock, OTG/portsel clock and AHB clock
va009039 0:148fca6fd246 60 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
va009039 0:148fca6fd246 61 #define FI 0x2EDF /* 12000 bits per frame (-1) */
va009039 0:148fca6fd246 62 #define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI)
va009039 0:148fca6fd246 63
va009039 0:148fca6fd246 64 USBHALHost* USBHALHost::instHost;
va009039 0:148fca6fd246 65
va009039 0:148fca6fd246 66 USBHALHost::USBHALHost() {
va009039 0:148fca6fd246 67 instHost = this;
va009039 0:148fca6fd246 68 }
va009039 0:148fca6fd246 69
va009039 0:148fca6fd246 70 void USBHALHost::init() {
va009039 0:148fca6fd246 71 NVIC_DisableIRQ(USB_IRQn);
va009039 0:148fca6fd246 72 m_pHcca = new HCCA();
va009039 0:148fca6fd246 73 init_hw_ohci(m_pHcca);
va009039 0:148fca6fd246 74 ResetRootHub();
va009039 0:148fca6fd246 75 NVIC_SetVector(USB_IRQn, (uint32_t)_usbisr);
va009039 0:148fca6fd246 76 NVIC_SetPriority(USB_IRQn, 0);
va009039 0:148fca6fd246 77 NVIC_EnableIRQ(USB_IRQn);
va009039 0:148fca6fd246 78
va009039 0:148fca6fd246 79 #ifndef BASE_USBHOST
va009039 0:148fca6fd246 80 USB_INFO("Simple USBHost Library for EA LPC4088 QSB");
va009039 0:148fca6fd246 81 bool lowSpeed = wait_attach();
va009039 0:148fca6fd246 82 addDevice(NULL, 0, lowSpeed);
va009039 0:148fca6fd246 83 #endif // BASE_USBHOST
va009039 0:148fca6fd246 84 }
va009039 0:148fca6fd246 85
va009039 0:148fca6fd246 86 void USBHALHost::init_hw_ohci(HCCA* pHcca) {
va009039 0:148fca6fd246 87 LPC_SC->PCONP &= ~(1UL<<31); //Cut power
va009039 0:148fca6fd246 88 wait_ms(1000);
va009039 0:148fca6fd246 89 LPC_SC->PCONP |= (1UL<<31); // turn on power for USB
va009039 0:148fca6fd246 90 LPC_USB->USBClkCtrl |= CLOCK_MASK; // Enable USB host clock, port selection and AHB clock
va009039 0:148fca6fd246 91 // Wait for clocks to become available
va009039 0:148fca6fd246 92 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
va009039 0:148fca6fd246 93 ;
va009039 0:148fca6fd246 94 LPC_USB->OTGStCtrl |= 1;
va009039 0:148fca6fd246 95 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
va009039 0:148fca6fd246 96
va009039 0:148fca6fd246 97 #if defined(TARGET_LPC1768)
va009039 0:148fca6fd246 98 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
va009039 0:148fca6fd246 99 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000
va009039 0:148fca6fd246 100 #elif defined(TARGET_LPC4088)
va009039 0:148fca6fd246 101 LPC_IOCON->P0_29 = 0x01; // USB_D+1
va009039 0:148fca6fd246 102 LPC_IOCON->P0_30 = 0x01; // USB_D-1
va009039 0:148fca6fd246 103 // DO NOT CHANGE P1_19.
va009039 0:148fca6fd246 104 #else
va009039 0:148fca6fd246 105 #error "target error"
va009039 0:148fca6fd246 106 #endif
va009039 0:148fca6fd246 107 USB_DBG("initialize OHCI\n");
va009039 0:148fca6fd246 108 wait_ms(100); /* Wait 50 ms before apply reset */
va009039 0:148fca6fd246 109 TEST_ASSERT((LPC_USB->HcRevision&0xff) == 0x10); // check revision
va009039 0:148fca6fd246 110 LPC_USB->HcControl = 0; /* HARDWARE RESET */
va009039 0:148fca6fd246 111 LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */
va009039 0:148fca6fd246 112 LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */
va009039 0:148fca6fd246 113 /* SOFTWARE RESET */
va009039 0:148fca6fd246 114 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
va009039 0:148fca6fd246 115 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */
va009039 0:148fca6fd246 116 LPC_USB->HcPeriodicStart = FI*90/100;
va009039 0:148fca6fd246 117 /* Put HC in operational state */
va009039 0:148fca6fd246 118 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
va009039 0:148fca6fd246 119 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */
va009039 0:148fca6fd246 120 TEST_ASSERT(pHcca);
va009039 0:148fca6fd246 121 for (int i = 0; i < 32; i++) {
va009039 0:148fca6fd246 122 pHcca->InterruptTable[i] = NULL;
va009039 0:148fca6fd246 123 }
va009039 0:148fca6fd246 124 LPC_USB->HcHCCA = reinterpret_cast<uint32_t>(pHcca);
va009039 0:148fca6fd246 125 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
va009039 0:148fca6fd246 126 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO;
va009039 0:148fca6fd246 127
va009039 0:148fca6fd246 128 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
va009039 0:148fca6fd246 129 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
va009039 0:148fca6fd246 130 }
va009039 0:148fca6fd246 131
va009039 0:148fca6fd246 132 void USBHALHost::ResetRootHub() {
va009039 0:148fca6fd246 133 wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */
va009039 0:148fca6fd246 134 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
va009039 0:148fca6fd246 135 USB_DBG("Before loop\n");
va009039 0:148fca6fd246 136 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
va009039 0:148fca6fd246 137 ;
va009039 0:148fca6fd246 138 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
va009039 0:148fca6fd246 139 USB_DBG("After loop\n");
va009039 0:148fca6fd246 140 wait_ms(200); /* Wait for 100 MS after port reset */
va009039 0:148fca6fd246 141 }
va009039 0:148fca6fd246 142
va009039 0:148fca6fd246 143 bool USBHALHost::wait_attach() {
va009039 0:148fca6fd246 144 bool lowSpeed = false;
va009039 0:148fca6fd246 145 uint32_t status = LPC_USB->HcRhPortStatus1;
va009039 0:148fca6fd246 146 if (status & OR_RH_PORT_LSDA) { // lowSpeedDeviceAttached
va009039 0:148fca6fd246 147 lowSpeed = true;
va009039 0:148fca6fd246 148 }
va009039 0:148fca6fd246 149 return lowSpeed;
va009039 0:148fca6fd246 150 }
va009039 0:148fca6fd246 151
va009039 0:148fca6fd246 152 void USBHALHost::enable(ENDPOINT_TYPE type) {
va009039 0:148fca6fd246 153 switch(type) {
va009039 0:148fca6fd246 154 case CONTROL_ENDPOINT:
va009039 0:148fca6fd246 155 LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
va009039 0:148fca6fd246 156 LPC_USB->HcControl |= OR_CONTROL_CLE;
va009039 0:148fca6fd246 157 break;
va009039 0:148fca6fd246 158 case ISOCHRONOUS_ENDPOINT:
va009039 0:148fca6fd246 159 LPC_USB->HcControl |= OR_CONTROL_PLE;
va009039 0:148fca6fd246 160 break;
va009039 0:148fca6fd246 161 case BULK_ENDPOINT:
va009039 0:148fca6fd246 162 LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF;
va009039 0:148fca6fd246 163 LPC_USB->HcControl |= OR_CONTROL_BLE;
va009039 0:148fca6fd246 164 break;
va009039 0:148fca6fd246 165 case INTERRUPT_ENDPOINT:
va009039 0:148fca6fd246 166 LPC_USB->HcControl |= OR_CONTROL_PLE;
va009039 0:148fca6fd246 167 break;
va009039 0:148fca6fd246 168 }
va009039 0:148fca6fd246 169 }
va009039 0:148fca6fd246 170
va009039 0:148fca6fd246 171 void USBHALHost::token_init(USBEndpoint* ep) {
va009039 0:148fca6fd246 172 if (ep->m_pED == NULL) {
va009039 0:148fca6fd246 173 ep->m_pED = new HCED(ep);
va009039 0:148fca6fd246 174 USB_DBG_ED(ep->m_pED);
va009039 0:148fca6fd246 175 }
va009039 0:148fca6fd246 176 HCED* ed = ep->m_pED;
va009039 0:148fca6fd246 177 USBDeviceConnected* dev = ep->getDevice();
va009039 0:148fca6fd246 178 USB_TEST_ASSERT(dev);
va009039 0:148fca6fd246 179 if (dev) {
va009039 0:148fca6fd246 180 uint8_t devAddr = dev->getAddress();
va009039 0:148fca6fd246 181 USB_DBG("devAddr=%02x", devAddr);
va009039 0:148fca6fd246 182 ed->setFunctionAddress(devAddr);
va009039 0:148fca6fd246 183 }
va009039 0:148fca6fd246 184 uint16_t size = ep->getSize();
va009039 0:148fca6fd246 185 USB_DBG("MaxPacketSize=%d", size);
va009039 0:148fca6fd246 186 ed->setMaxPacketSize(size);
va009039 0:148fca6fd246 187 if (ed->HeadTd == NULL) {
va009039 0:148fca6fd246 188 HCTD* td = new HCTD(ep);
va009039 0:148fca6fd246 189 ed->TailTd = td;
va009039 0:148fca6fd246 190 ed->HeadTd = td;
va009039 0:148fca6fd246 191 switch(ep->getType()) {
va009039 0:148fca6fd246 192 case CONTROL_ENDPOINT:
va009039 0:148fca6fd246 193 ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED);
va009039 0:148fca6fd246 194 LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(ed);
va009039 0:148fca6fd246 195 break;
va009039 0:148fca6fd246 196 case BULK_ENDPOINT:
va009039 0:148fca6fd246 197 ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcBulkHeadED);
va009039 0:148fca6fd246 198 LPC_USB->HcBulkHeadED = reinterpret_cast<uint32_t>(ed);
va009039 0:148fca6fd246 199 break;
va009039 0:148fca6fd246 200 case INTERRUPT_ENDPOINT:
va009039 0:148fca6fd246 201 HCCA* pHcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
va009039 0:148fca6fd246 202 ed->Next = pHcca->InterruptTable[0];
va009039 0:148fca6fd246 203 pHcca->InterruptTable[0] = ed;
va009039 0:148fca6fd246 204 break;
va009039 0:148fca6fd246 205 }
va009039 0:148fca6fd246 206 USB_DBG_ED(ed);
va009039 0:148fca6fd246 207 }
va009039 0:148fca6fd246 208 }
va009039 0:148fca6fd246 209
va009039 0:148fca6fd246 210 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
va009039 0:148fca6fd246 211 token_init(ep);
va009039 0:148fca6fd246 212 HCED* ed = ep->m_pED;
va009039 0:148fca6fd246 213 HCTD* td = ed->TailTd;
va009039 0:148fca6fd246 214 setup->wLength = wLength;
va009039 0:148fca6fd246 215 TBUF* tbuf = new(sizeof(SETUP_PACKET))TBUF(setup, sizeof(SETUP_PACKET));
va009039 0:148fca6fd246 216 td->transfer(tbuf, sizeof(SETUP_PACKET));
va009039 0:148fca6fd246 217 td->Control |= TD_TOGGLE_0|TD_SETUP;
va009039 0:148fca6fd246 218 HCTD* blank = new HCTD(ep);
va009039 0:148fca6fd246 219 ed->enqueue(blank);
va009039 0:148fca6fd246 220 //DBG_ED(ed);
va009039 0:148fca6fd246 221 enable(ep->getType());
va009039 0:148fca6fd246 222
va009039 0:148fca6fd246 223 td = ep->get_queue_HCTD();
va009039 0:148fca6fd246 224 TEST_ASSERT(td);
va009039 0:148fca6fd246 225 int result = td->getLengthTransferred();
va009039 0:148fca6fd246 226 DBG_TD(td);
va009039 0:148fca6fd246 227 delete tbuf;
va009039 0:148fca6fd246 228 delete td;
va009039 0:148fca6fd246 229 return result;
va009039 0:148fca6fd246 230 }
va009039 0:148fca6fd246 231
va009039 0:148fca6fd246 232 int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
va009039 0:148fca6fd246 233 token_init(ep);
va009039 0:148fca6fd246 234 HCED* ed = ep->m_pED;
va009039 0:148fca6fd246 235 HCTD* td = ed->TailTd;
va009039 0:148fca6fd246 236 TBUF* tbuf = NULL;
va009039 0:148fca6fd246 237 if (data != NULL) {
va009039 0:148fca6fd246 238 tbuf = new(size)TBUF();
va009039 0:148fca6fd246 239 td->transfer(tbuf, size);
va009039 0:148fca6fd246 240 }
va009039 0:148fca6fd246 241 td->Control |= TD_IN;
va009039 0:148fca6fd246 242 HCTD* blank = new HCTD(ep);
va009039 0:148fca6fd246 243 ed->enqueue(blank);
va009039 0:148fca6fd246 244 USB_DBG_ED_IF(ed->EndpointNumber()==0, ed); // control transfer
va009039 0:148fca6fd246 245 enable(ep->getType());
va009039 0:148fca6fd246 246
va009039 0:148fca6fd246 247 td = ep->get_queue_HCTD();
va009039 0:148fca6fd246 248 TEST_ASSERT(td);
va009039 0:148fca6fd246 249 if (data != NULL) {
va009039 0:148fca6fd246 250 memcpy(data, tbuf->buf, size);
va009039 0:148fca6fd246 251 delete tbuf;
va009039 0:148fca6fd246 252 }
va009039 0:148fca6fd246 253 int result = td->getLengthTransferred();
va009039 0:148fca6fd246 254 delete td;
va009039 0:148fca6fd246 255 return result;
va009039 0:148fca6fd246 256 }
va009039 0:148fca6fd246 257
va009039 0:148fca6fd246 258 int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
va009039 0:148fca6fd246 259 token_init(ep);
va009039 0:148fca6fd246 260 HCED* ed = ep->m_pED;
va009039 0:148fca6fd246 261 HCTD* td = ed->TailTd;
va009039 0:148fca6fd246 262 TBUF* tbuf = NULL;
va009039 0:148fca6fd246 263 if (data != NULL) {
va009039 0:148fca6fd246 264 tbuf = new(size)TBUF(data, size);
va009039 0:148fca6fd246 265 td->transfer(tbuf, size);
va009039 0:148fca6fd246 266 }
va009039 0:148fca6fd246 267 td->Control |= TD_OUT;
va009039 0:148fca6fd246 268 HCTD* blank = new HCTD(ep);
va009039 0:148fca6fd246 269 ed->enqueue(blank);
va009039 0:148fca6fd246 270 DBG_ED(ed);
va009039 0:148fca6fd246 271 enable(ep->getType());
va009039 0:148fca6fd246 272
va009039 0:148fca6fd246 273 td = ep->get_queue_HCTD();
va009039 0:148fca6fd246 274 TEST_ASSERT(td);
va009039 0:148fca6fd246 275 if (data != NULL) {
va009039 0:148fca6fd246 276 delete tbuf;
va009039 0:148fca6fd246 277 }
va009039 0:148fca6fd246 278 int result = td->getLengthTransferred();
va009039 0:148fca6fd246 279 delete td;
va009039 0:148fca6fd246 280 return result;
va009039 0:148fca6fd246 281 }
va009039 0:148fca6fd246 282
va009039 0:148fca6fd246 283 void USBHALHost::token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
va009039 0:148fca6fd246 284 token_init(ep);
va009039 0:148fca6fd246 285 HCED* ed = ep->m_pED;
va009039 0:148fca6fd246 286 HCTD* td = ed->TailTd;
va009039 0:148fca6fd246 287 TBUF* tbuf = new(size)TBUF();
va009039 0:148fca6fd246 288 td->transfer(tbuf, size);
va009039 0:148fca6fd246 289 td->Control |= TD_IN;
va009039 0:148fca6fd246 290 HCTD* blank = new HCTD(ep);
va009039 0:148fca6fd246 291 ed->enqueue(blank);
va009039 0:148fca6fd246 292 enable(ep->getType());
va009039 0:148fca6fd246 293 }
va009039 0:148fca6fd246 294
va009039 0:148fca6fd246 295 USB_TYPE USBHALHost::token_inNB_result(USBEndpoint* ep) {
va009039 0:148fca6fd246 296 HCTD* td = ep->get_queue_HCTD(0);
va009039 0:148fca6fd246 297 if (td) {
va009039 0:148fca6fd246 298 int len = td->getLengthTransferred();
va009039 0:148fca6fd246 299 TBUF* tbuf = (TBUF*)td->buf_top;
va009039 0:148fca6fd246 300 memcpy(ep->getBufStart(), tbuf->buf, len);
va009039 0:148fca6fd246 301 ep->setLengthTransferred(len);
va009039 0:148fca6fd246 302 ep->setState((USB_TYPE)td->ConditionCode());
va009039 0:148fca6fd246 303 delete td;
va009039 0:148fca6fd246 304 delete tbuf;
va009039 0:148fca6fd246 305 return USB_TYPE_OK;
va009039 0:148fca6fd246 306 }
va009039 0:148fca6fd246 307 return USB_TYPE_PROCESSING;
va009039 0:148fca6fd246 308 }
va009039 0:148fca6fd246 309
va009039 0:148fca6fd246 310 void USBHALHost::_usbisr(void) {
va009039 0:148fca6fd246 311 if (instHost) {
va009039 0:148fca6fd246 312 instHost->UsbIrqhandler();
va009039 0:148fca6fd246 313 }
va009039 0:148fca6fd246 314 }
va009039 0:148fca6fd246 315
va009039 0:148fca6fd246 316 HCTD* td_reverse(HCTD* td)
va009039 0:148fca6fd246 317 {
va009039 0:148fca6fd246 318 HCTD* result = NULL;
va009039 0:148fca6fd246 319 HCTD* next;
va009039 0:148fca6fd246 320 while(td) {
va009039 0:148fca6fd246 321 next = const_cast<HCTD*>(td->Next);
va009039 0:148fca6fd246 322 td->Next = result;
va009039 0:148fca6fd246 323 result = td;
va009039 0:148fca6fd246 324 td = next;
va009039 0:148fca6fd246 325 }
va009039 0:148fca6fd246 326 return result;
va009039 0:148fca6fd246 327 }
va009039 0:148fca6fd246 328
va009039 0:148fca6fd246 329 void USBHALHost::UsbIrqhandler() {
va009039 0:148fca6fd246 330 if (!(LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable)) {
va009039 0:148fca6fd246 331 return;
va009039 0:148fca6fd246 332 }
va009039 0:148fca6fd246 333 m_report_irq++;
va009039 0:148fca6fd246 334 uint32_t status = LPC_USB->HcInterruptStatus;
va009039 0:148fca6fd246 335 if (status & OR_INTR_STATUS_FNO) {
va009039 0:148fca6fd246 336 m_report_FNO++;
va009039 0:148fca6fd246 337 }
va009039 0:148fca6fd246 338 if (status & OR_INTR_STATUS_WDH) {
va009039 0:148fca6fd246 339 union {
va009039 0:148fca6fd246 340 HCTD* done_td;
va009039 0:148fca6fd246 341 uint32_t lsb;
va009039 0:148fca6fd246 342 };
va009039 0:148fca6fd246 343 done_td = const_cast<HCTD*>(m_pHcca->DoneHead);
va009039 0:148fca6fd246 344 TEST_ASSERT(done_td);
va009039 0:148fca6fd246 345 m_pHcca->DoneHead = NULL; // reset
va009039 0:148fca6fd246 346 if (lsb & 1) { // error ?
va009039 0:148fca6fd246 347 lsb &= ~1;
va009039 0:148fca6fd246 348 }
va009039 0:148fca6fd246 349 HCTD* td = td_reverse(done_td);
va009039 0:148fca6fd246 350 while(td) {
va009039 0:148fca6fd246 351 USBEndpoint* ep = td->ep;
va009039 0:148fca6fd246 352 TEST_ASSERT(ep);
va009039 0:148fca6fd246 353 if (ep) {
va009039 0:148fca6fd246 354 ep->irqWdhHandler(td);
va009039 0:148fca6fd246 355 }
va009039 0:148fca6fd246 356 td = td->Next;
va009039 0:148fca6fd246 357 }
va009039 0:148fca6fd246 358 m_report_WDH++;
va009039 0:148fca6fd246 359 }
va009039 0:148fca6fd246 360 LPC_USB->HcInterruptStatus = status; // Clear Interrrupt Status
va009039 0:148fca6fd246 361 }
va009039 0:148fca6fd246 362
va009039 0:148fca6fd246 363 TBUF::TBUF(const void* data, int size) {
va009039 0:148fca6fd246 364 if (size > 0) {
va009039 0:148fca6fd246 365 memcpy(buf, data, size);
va009039 0:148fca6fd246 366 }
va009039 0:148fca6fd246 367 }
va009039 0:148fca6fd246 368
va009039 0:148fca6fd246 369 HCTD::HCTD(USBEndpoint* obj) {
va009039 0:148fca6fd246 370 CTASSERT(sizeof(HCTD) == 36);
va009039 0:148fca6fd246 371 TEST_ASSERT(obj);
va009039 0:148fca6fd246 372 Control = TD_CC|TD_ROUNDING;
va009039 0:148fca6fd246 373 CurrBufPtr = NULL;
va009039 0:148fca6fd246 374 Next = NULL;
va009039 0:148fca6fd246 375 BufEnd = NULL;
va009039 0:148fca6fd246 376 buf_top = NULL;
va009039 0:148fca6fd246 377 buf_size = 0;
va009039 0:148fca6fd246 378 ep = obj;
va009039 0:148fca6fd246 379 }
va009039 0:148fca6fd246 380
va009039 0:148fca6fd246 381 HCITD::HCITD(USBEndpoint* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
va009039 0:148fca6fd246 382 Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED
va009039 0:148fca6fd246 383 ((FrameCount-1) << 24)| // FC FrameCount
va009039 0:148fca6fd246 384 TD_DELAY_INT(0) | // DI DelayInterrupt
va009039 0:148fca6fd246 385 FrameNumber; // SF StartingFrame
va009039 0:148fca6fd246 386 BufferPage0 = const_cast<uint8_t*>(buf);
va009039 0:148fca6fd246 387 BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
va009039 0:148fca6fd246 388 Next = NULL;
va009039 0:148fca6fd246 389 ep = obj;
va009039 0:148fca6fd246 390 uint32_t addr = reinterpret_cast<uint32_t>(buf);
va009039 0:148fca6fd246 391 for(int i = 0; i < FrameCount; i++) {
va009039 0:148fca6fd246 392 uint16_t offset = addr & 0x0fff;
va009039 0:148fca6fd246 393 if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
va009039 0:148fca6fd246 394 offset |= 0x1000;
va009039 0:148fca6fd246 395 }
va009039 0:148fca6fd246 396 OffsetPSW[i] = 0xe000|offset;
va009039 0:148fca6fd246 397 addr += PacketSize;
va009039 0:148fca6fd246 398 }
va009039 0:148fca6fd246 399 }
va009039 0:148fca6fd246 400
va009039 0:148fca6fd246 401 HCED::HCED(USBEndpoint* ep) {
va009039 0:148fca6fd246 402 USBDeviceConnected* dev = ep->getDevice();
va009039 0:148fca6fd246 403 int devAddr = 0;
va009039 0:148fca6fd246 404 bool lowSpeed = false;
va009039 0:148fca6fd246 405 if (dev) {
va009039 0:148fca6fd246 406 devAddr = dev->getAddress();
va009039 0:148fca6fd246 407 lowSpeed = dev->getSpeed();
va009039 0:148fca6fd246 408 }
va009039 0:148fca6fd246 409 int ep_number = ep->getAddress();
va009039 0:148fca6fd246 410 int MaxPacketSize = ep->getSize();
va009039 0:148fca6fd246 411 Control = devAddr | /* USB address */
va009039 0:148fca6fd246 412 ((ep_number & 0x7F) << 7) | /* Endpoint address */
va009039 0:148fca6fd246 413 (ep_number!=0?(((ep_number&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
va009039 0:148fca6fd246 414 ((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */
va009039 0:148fca6fd246 415 (MaxPacketSize << 16); /* MaxPkt Size */
va009039 0:148fca6fd246 416 TailTd = NULL;
va009039 0:148fca6fd246 417 HeadTd = NULL;
va009039 0:148fca6fd246 418 Next = NULL;
va009039 0:148fca6fd246 419 }
va009039 0:148fca6fd246 420
va009039 0:148fca6fd246 421 bool HCED::enqueue(HCTD* td) {
va009039 0:148fca6fd246 422 if (td) {
va009039 0:148fca6fd246 423 HCTD* tail = reinterpret_cast<HCTD*>(TailTd);
va009039 0:148fca6fd246 424 if (tail) {
va009039 0:148fca6fd246 425 tail->Next = td;
va009039 0:148fca6fd246 426 TailTd = reinterpret_cast<HCTD*>(td);
va009039 0:148fca6fd246 427 return true;
va009039 0:148fca6fd246 428 }
va009039 0:148fca6fd246 429 }
va009039 0:148fca6fd246 430 return false;
va009039 0:148fca6fd246 431 }
va009039 0:148fca6fd246 432
va009039 0:148fca6fd246 433 void HCED::init_queue(HCTD* td) {
va009039 0:148fca6fd246 434 TailTd = reinterpret_cast<HCTD*>(td);
va009039 0:148fca6fd246 435 HeadTd = reinterpret_cast<HCTD*>(td);
va009039 0:148fca6fd246 436 }
va009039 0:148fca6fd246 437
va009039 0:148fca6fd246 438 void HCCA::enqueue(HCED* ed) {
va009039 0:148fca6fd246 439 for(int i = 0; i < 32; i++) {
va009039 0:148fca6fd246 440 if (InterruptTable[i] == NULL) {
va009039 0:148fca6fd246 441 InterruptTable[i] = ed;
va009039 0:148fca6fd246 442 } else {
va009039 0:148fca6fd246 443 HCED* nextEd = InterruptTable[i];
va009039 0:148fca6fd246 444 while(nextEd->Next && nextEd->Next != ed) {
va009039 0:148fca6fd246 445 nextEd = nextEd->Next;
va009039 0:148fca6fd246 446 }
va009039 0:148fca6fd246 447 nextEd->Next = ed;
va009039 0:148fca6fd246 448 }
va009039 0:148fca6fd246 449 }
va009039 0:148fca6fd246 450 }
va009039 0:148fca6fd246 451
va009039 0:148fca6fd246 452