UVC host library

Dependents:   LifeCam WebcamServer

Committer:
va009039
Date:
Wed Aug 15 13:52:53 2012 +0000
Revision:
3:3eb41d749f9a
Parent:
0:b0f04c137829
add USB_USE_MALLOC

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:b0f04c137829 1
va009039 0:b0f04c137829 2 /*
va009039 0:b0f04c137829 3 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
va009039 0:b0f04c137829 4
va009039 0:b0f04c137829 5 Permission is hereby granted, free of charge, to any person obtaining a copy
va009039 0:b0f04c137829 6 of this software and associated documentation files (the "Software"), to deal
va009039 0:b0f04c137829 7 in the Software without restriction, including without limitation the rights
va009039 0:b0f04c137829 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
va009039 0:b0f04c137829 9 copies of the Software, and to permit persons to whom the Software is
va009039 0:b0f04c137829 10 furnished to do so, subject to the following conditions:
va009039 0:b0f04c137829 11
va009039 0:b0f04c137829 12 The above copyright notice and this permission notice shall be included in
va009039 0:b0f04c137829 13 all copies or substantial portions of the Software.
va009039 0:b0f04c137829 14
va009039 0:b0f04c137829 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
va009039 0:b0f04c137829 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
va009039 0:b0f04c137829 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
va009039 0:b0f04c137829 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
va009039 0:b0f04c137829 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
va009039 0:b0f04c137829 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
va009039 0:b0f04c137829 21 THE SOFTWARE.
va009039 0:b0f04c137829 22 */
va009039 0:b0f04c137829 23 #include "UsbHostMgr.h"
va009039 0:b0f04c137829 24 #include "usb_mem.h"
va009039 0:b0f04c137829 25 #include "string.h" //For memcpy, memmove, memset
va009039 0:b0f04c137829 26 //#define __DEBUG
va009039 0:b0f04c137829 27 //#define __DEBUG3
va009039 0:b0f04c137829 28 //#include "dbg/dbg.h"
va009039 0:b0f04c137829 29 #include "mydbg.h"
va009039 0:b0f04c137829 30
va009039 0:b0f04c137829 31 // bits of the USB/OTG clock control register
va009039 0:b0f04c137829 32 #define HOST_CLK_EN (1<<0)
va009039 0:b0f04c137829 33 #define DEV_CLK_EN (1<<1)
va009039 0:b0f04c137829 34 #define PORTSEL_CLK_EN (1<<3)
va009039 0:b0f04c137829 35 #define AHB_CLK_EN (1<<4)
va009039 0:b0f04c137829 36
va009039 0:b0f04c137829 37 // bits of the USB/OTG clock status register
va009039 0:b0f04c137829 38 #define HOST_CLK_ON (1<<0)
va009039 0:b0f04c137829 39 #define DEV_CLK_ON (1<<1)
va009039 0:b0f04c137829 40 #define PORTSEL_CLK_ON (1<<3)
va009039 0:b0f04c137829 41 #define AHB_CLK_ON (1<<4)
va009039 0:b0f04c137829 42
va009039 0:b0f04c137829 43 // we need host clock, OTG/portsel clock and AHB clock
va009039 0:b0f04c137829 44 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
va009039 0:b0f04c137829 45
va009039 0:b0f04c137829 46 static UsbHostMgr* pMgr = NULL;
va009039 0:b0f04c137829 47
va009039 0:b0f04c137829 48 extern "C" void sUsbIrqhandler(void) __irq
va009039 0:b0f04c137829 49 {
va009039 0:b0f04c137829 50 DBG("\n+Int\n");
va009039 0:b0f04c137829 51 if(pMgr)
va009039 0:b0f04c137829 52 pMgr->UsbIrqhandler();
va009039 0:b0f04c137829 53 DBG("\n-Int\n");
va009039 0:b0f04c137829 54 return;
va009039 0:b0f04c137829 55 }
va009039 0:b0f04c137829 56
va009039 0:b0f04c137829 57 UsbHostMgr::UsbHostMgr() : m_lpDevices()
va009039 0:b0f04c137829 58 {
va009039 0:b0f04c137829 59 /*if(!pMgr)*/ //Assume singleton
va009039 0:b0f04c137829 60 pMgr = this;
va009039 0:b0f04c137829 61 usb_mem_init();
va009039 0:b0f04c137829 62 for(int i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) {
va009039 0:b0f04c137829 63 m_lpDevices[i] = NULL;
va009039 0:b0f04c137829 64 }
va009039 0:b0f04c137829 65 m_pHcca = (HCCA*) usb_get_hcca();
va009039 0:b0f04c137829 66 memset((void*)m_pHcca, 0, 0x100);
va009039 0:b0f04c137829 67 m_hardware_init = false;
va009039 0:b0f04c137829 68 DBG("Host manager at %p\n", this);
va009039 0:b0f04c137829 69 }
va009039 0:b0f04c137829 70
va009039 0:b0f04c137829 71 UsbHostMgr::~UsbHostMgr()
va009039 0:b0f04c137829 72 {
va009039 0:b0f04c137829 73 if(pMgr == this)
va009039 0:b0f04c137829 74 pMgr = NULL;
va009039 0:b0f04c137829 75 }
va009039 0:b0f04c137829 76
va009039 0:b0f04c137829 77 UsbErr UsbHostMgr::init() //Initialize host
va009039 0:b0f04c137829 78 {
va009039 0:b0f04c137829 79 DBG("m_hardware_init=%d\n", m_hardware_init);
va009039 0:b0f04c137829 80 if(m_hardware_init) {
va009039 0:b0f04c137829 81 return USBERR_OK;
va009039 0:b0f04c137829 82 }
va009039 0:b0f04c137829 83
va009039 0:b0f04c137829 84 NVIC_DisableIRQ(USB_IRQn); /* Disable the USB interrupt source */
va009039 0:b0f04c137829 85
va009039 0:b0f04c137829 86 LPC_SC->PCONP &= ~(1UL<<31); //Cut power
va009039 0:b0f04c137829 87 wait(1);
va009039 0:b0f04c137829 88
va009039 0:b0f04c137829 89
va009039 0:b0f04c137829 90 // turn on power for USB
va009039 0:b0f04c137829 91 LPC_SC->PCONP |= (1UL<<31);
va009039 0:b0f04c137829 92 // Enable USB host clock, port selection and AHB clock
va009039 0:b0f04c137829 93 LPC_USB->USBClkCtrl |= CLOCK_MASK;
va009039 0:b0f04c137829 94 // Wait for clocks to become available
va009039 0:b0f04c137829 95 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
va009039 0:b0f04c137829 96 ;
va009039 0:b0f04c137829 97
va009039 0:b0f04c137829 98 // it seems the bits[0:1] mean the following
va009039 0:b0f04c137829 99 // 0: U1=device, U2=host
va009039 0:b0f04c137829 100 // 1: U1=host, U2=host
va009039 0:b0f04c137829 101 // 2: reserved
va009039 0:b0f04c137829 102 // 3: U1=host, U2=device
va009039 0:b0f04c137829 103 // NB: this register is only available if OTG clock (aka "port select") is enabled!!
va009039 0:b0f04c137829 104 // since we don't care about port 2, set just bit 0 to 1 (U1=host)
va009039 0:b0f04c137829 105 LPC_USB->OTGStCtrl |= 1;
va009039 0:b0f04c137829 106
va009039 0:b0f04c137829 107 // now that we've configured the ports, we can turn off the portsel clock
va009039 0:b0f04c137829 108 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
va009039 0:b0f04c137829 109
va009039 0:b0f04c137829 110 // power pins are not connected on mbed, so we can skip them
va009039 0:b0f04c137829 111 /* P1[18] = USB_UP_LED, 01 */
va009039 0:b0f04c137829 112 /* P1[19] = /USB_PPWR, 10 */
va009039 0:b0f04c137829 113 /* P1[22] = USB_PWRD, 10 */
va009039 0:b0f04c137829 114 /* P1[27] = /USB_OVRCR, 10 */
va009039 0:b0f04c137829 115 /*LPC_PINCON->PINSEL3 &= ~((3<<4) | (3<<6) | (3<<12) | (3<<22));
va009039 0:b0f04c137829 116 LPC_PINCON->PINSEL3 |= ((1<<4)|(2<<6) | (2<<12) | (2<<22)); // 0x00802080
va009039 0:b0f04c137829 117 */
va009039 0:b0f04c137829 118
va009039 0:b0f04c137829 119 // configure USB D+/D- pins
va009039 0:b0f04c137829 120 /* P0[29] = USB_D+, 01 */
va009039 0:b0f04c137829 121 /* P0[30] = USB_D-, 01 */
va009039 0:b0f04c137829 122 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
va009039 0:b0f04c137829 123 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000
va009039 0:b0f04c137829 124
va009039 0:b0f04c137829 125 DBG("Initializing Host Stack\n");
va009039 0:b0f04c137829 126
va009039 0:b0f04c137829 127 wait_ms(100); /* Wait 50 ms before apply reset */
va009039 0:b0f04c137829 128 LPC_USB->HcControl = 0; /* HARDWARE RESET */
va009039 0:b0f04c137829 129 LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */
va009039 0:b0f04c137829 130 LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */
va009039 0:b0f04c137829 131
va009039 0:b0f04c137829 132 /* SOFTWARE RESET */
va009039 0:b0f04c137829 133 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
va009039 0:b0f04c137829 134 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */
va009039 0:b0f04c137829 135 LPC_USB->HcPeriodicStart = FI*90/100;
va009039 0:b0f04c137829 136
va009039 0:b0f04c137829 137 /* Put HC in operational state */
va009039 0:b0f04c137829 138 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
va009039 0:b0f04c137829 139 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */
va009039 0:b0f04c137829 140
va009039 0:b0f04c137829 141 LPC_USB->HcHCCA = (uint32_t)(m_pHcca);
va009039 0:b0f04c137829 142 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
va009039 0:b0f04c137829 143
va009039 0:b0f04c137829 144
va009039 0:b0f04c137829 145 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE |
va009039 0:b0f04c137829 146 OR_INTR_ENABLE_WDH |
va009039 0:b0f04c137829 147 OR_INTR_ENABLE_RHSC;
va009039 0:b0f04c137829 148
va009039 0:b0f04c137829 149 NVIC_SetPriority(USB_IRQn, 0); /* highest priority */
va009039 0:b0f04c137829 150 /* Enable the USB Interrupt */
va009039 0:b0f04c137829 151 NVIC_SetVector(USB_IRQn, (uint32_t)(sUsbIrqhandler));
va009039 0:b0f04c137829 152 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
va009039 0:b0f04c137829 153 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
va009039 0:b0f04c137829 154
va009039 0:b0f04c137829 155
va009039 0:b0f04c137829 156 /* Check for any connected devices */
va009039 0:b0f04c137829 157 //if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) //Root device connected
va009039 0:b0f04c137829 158 //{
va009039 0:b0f04c137829 159 // //Device connected
va009039 0:b0f04c137829 160 // wait(1);
va009039 0:b0f04c137829 161 // DBG("Device connected (%08x)\n", LPC_USB->HcRhPortStatus1);
va009039 0:b0f04c137829 162 // onUsbDeviceConnected(0, 1); //Hub 0 (root hub), Port 1 (count starts at 1)
va009039 0:b0f04c137829 163 //}
va009039 0:b0f04c137829 164
va009039 0:b0f04c137829 165 DBG("Enabling IRQ\n");
va009039 0:b0f04c137829 166 NVIC_EnableIRQ(USB_IRQn);
va009039 0:b0f04c137829 167 DBG("End of host stack initialization\n");
va009039 0:b0f04c137829 168 m_hardware_init = true;
va009039 0:b0f04c137829 169 return USBERR_OK;
va009039 0:b0f04c137829 170 }
va009039 0:b0f04c137829 171
va009039 0:b0f04c137829 172 UsbErr UsbHostMgr::poll() //Enumerate connected devices, etc
va009039 0:b0f04c137829 173 {
va009039 0:b0f04c137829 174 /* Check for any connected devices */
va009039 0:b0f04c137829 175 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) //Root device connected
va009039 0:b0f04c137829 176 {
va009039 0:b0f04c137829 177 //Device connected
va009039 0:b0f04c137829 178 wait(1);
va009039 0:b0f04c137829 179 DBG("Device connected (%08x)\n", LPC_USB->HcRhPortStatus1);
va009039 0:b0f04c137829 180 bool lowspeed = false;
va009039 0:b0f04c137829 181 if (LPC_USB->HcRhPortStatus1 & 0x0200) { // lowspeed?
va009039 0:b0f04c137829 182 lowspeed = true;
va009039 0:b0f04c137829 183 }
va009039 0:b0f04c137829 184 onUsbDeviceConnected(0, 1, lowspeed); //Hub 0 (root hub), Port 1 (count starts at 1)
va009039 0:b0f04c137829 185 }
va009039 0:b0f04c137829 186
va009039 0:b0f04c137829 187 for(int i = 0; i < USB_HOSTMGR_MAX_DEVS; i++)
va009039 0:b0f04c137829 188 {
va009039 0:b0f04c137829 189 UsbDevice* dev = m_lpDevices[i];
va009039 0:b0f04c137829 190 if (dev == NULL) {
va009039 0:b0f04c137829 191 continue;
va009039 0:b0f04c137829 192 }
va009039 0:b0f04c137829 193 DBG3("%d dev=%p %d %d addr=%d\n", i, dev, dev->m_connected, dev->m_enumerated, dev->m_addr);
va009039 0:b0f04c137829 194 if(dev->m_connected) {
va009039 0:b0f04c137829 195 if (!dev->m_enumerated) {
va009039 0:b0f04c137829 196 dev->enumerate();
va009039 0:b0f04c137829 197 return USBERR_PROCESSING;
va009039 0:b0f04c137829 198 }
va009039 0:b0f04c137829 199 }
va009039 0:b0f04c137829 200 }
va009039 0:b0f04c137829 201 for(int i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) {
va009039 0:b0f04c137829 202 UsbDevice* dev = m_lpDevices[i];
va009039 0:b0f04c137829 203 if (dev == NULL) {
va009039 0:b0f04c137829 204 continue;
va009039 0:b0f04c137829 205 }
va009039 0:b0f04c137829 206 if (dev->m_connected && dev->m_enumerated) {
va009039 0:b0f04c137829 207 if (dev->m_DeviceClass == 0x09) { // HUB
va009039 0:b0f04c137829 208 UsbErr rc = dev->hub_poll();
va009039 0:b0f04c137829 209 if (rc == USBERR_PROCESSING) {
va009039 0:b0f04c137829 210 return USBERR_PROCESSING;
va009039 0:b0f04c137829 211 }
va009039 0:b0f04c137829 212 }
va009039 0:b0f04c137829 213 }
va009039 0:b0f04c137829 214 }
va009039 0:b0f04c137829 215 return USBERR_OK;
va009039 0:b0f04c137829 216 }
va009039 0:b0f04c137829 217
va009039 0:b0f04c137829 218 int UsbHostMgr::devicesCount()
va009039 0:b0f04c137829 219 {
va009039 0:b0f04c137829 220 int i;
va009039 0:b0f04c137829 221 for(i = 0; i < USB_HOSTMGR_MAX_DEVS; i++)
va009039 0:b0f04c137829 222 {
va009039 0:b0f04c137829 223 if (m_lpDevices[i] == NULL) {
va009039 0:b0f04c137829 224 return i;
va009039 0:b0f04c137829 225 }
va009039 0:b0f04c137829 226 }
va009039 0:b0f04c137829 227 return i;
va009039 0:b0f04c137829 228 }
va009039 0:b0f04c137829 229
va009039 0:b0f04c137829 230 UsbDevice* UsbHostMgr::getDevice(int item)
va009039 0:b0f04c137829 231 {
va009039 0:b0f04c137829 232 UsbDevice* pDev = m_lpDevices[item];
va009039 0:b0f04c137829 233 if(!pDev)
va009039 0:b0f04c137829 234 return NULL;
va009039 0:b0f04c137829 235
va009039 0:b0f04c137829 236 pDev->m_refs++;
va009039 0:b0f04c137829 237 return pDev;
va009039 0:b0f04c137829 238 }
va009039 0:b0f04c137829 239
va009039 0:b0f04c137829 240 void UsbHostMgr::releaseDevice(UsbDevice* pDev)
va009039 0:b0f04c137829 241 {
va009039 0:b0f04c137829 242 pDev->m_refs--;
va009039 0:b0f04c137829 243 if(pDev->m_refs > 0)
va009039 0:b0f04c137829 244 return;
va009039 0:b0f04c137829 245 //If refs count = 0, delete
va009039 0:b0f04c137829 246 //Find & remove from list
va009039 0:b0f04c137829 247 int i;
va009039 0:b0f04c137829 248 for(i = 0; i < USB_HOSTMGR_MAX_DEVS; i++)
va009039 0:b0f04c137829 249 {
va009039 0:b0f04c137829 250 if (m_lpDevices[i] == pDev)
va009039 0:b0f04c137829 251 break;
va009039 0:b0f04c137829 252 }
va009039 0:b0f04c137829 253 if(i!=USB_HOSTMGR_MAX_DEVS)
va009039 0:b0f04c137829 254 memmove(&m_lpDevices[i], &m_lpDevices[i+1], sizeof(UsbDevice*) * (USB_HOSTMGR_MAX_DEVS - (i + 1))); //Safer than memcpy because of overlapping mem
va009039 0:b0f04c137829 255 m_lpDevices[USB_HOSTMGR_MAX_DEVS - 1] = NULL;
va009039 0:b0f04c137829 256 delete pDev;
va009039 0:b0f04c137829 257 }
va009039 0:b0f04c137829 258
va009039 0:b0f04c137829 259 void UsbHostMgr::UsbIrqhandler()
va009039 0:b0f04c137829 260 {
va009039 0:b0f04c137829 261 uint32_t int_status;
va009039 0:b0f04c137829 262 uint32_t ie_status;
va009039 0:b0f04c137829 263
va009039 0:b0f04c137829 264 int_status = LPC_USB->HcInterruptStatus; /* Read Interrupt Status */
va009039 0:b0f04c137829 265 ie_status = LPC_USB->HcInterruptEnable; /* Read Interrupt enable status */
va009039 0:b0f04c137829 266
va009039 0:b0f04c137829 267 if (!(int_status & ie_status))
va009039 0:b0f04c137829 268 {
va009039 0:b0f04c137829 269 return;
va009039 0:b0f04c137829 270 }
va009039 0:b0f04c137829 271 else
va009039 0:b0f04c137829 272 {
va009039 0:b0f04c137829 273 int_status = int_status & ie_status;
va009039 0:b0f04c137829 274 if (int_status & OR_INTR_STATUS_RHSC) /* Root hub status change interrupt */
va009039 0:b0f04c137829 275 {
va009039 0:b0f04c137829 276 DBG("LPC_USB->HcRhPortStatus1 = %08x\n", LPC_USB->HcRhPortStatus1);
va009039 0:b0f04c137829 277 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC)
va009039 0:b0f04c137829 278 {
va009039 0:b0f04c137829 279 if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE)
va009039 0:b0f04c137829 280 {
va009039 0:b0f04c137829 281 /*
va009039 0:b0f04c137829 282 * When DRWE is on, Connect Status Change
va009039 0:b0f04c137829 283 * means a remote wakeup event.
va009039 0:b0f04c137829 284 */
va009039 0:b0f04c137829 285 //HOST_RhscIntr = 1;// JUST SOMETHING FOR A BREAKPOINT
va009039 0:b0f04c137829 286 }
va009039 0:b0f04c137829 287 else
va009039 0:b0f04c137829 288 {
va009039 0:b0f04c137829 289 /*
va009039 0:b0f04c137829 290 * When DRWE is off, Connect Status Change
va009039 0:b0f04c137829 291 * is NOT a remote wakeup event
va009039 0:b0f04c137829 292 */
va009039 0:b0f04c137829 293 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) //Root device connected
va009039 0:b0f04c137829 294 {
va009039 0:b0f04c137829 295 //Device connected
va009039 0:b0f04c137829 296 DBG("Device connected (%08x)\n", LPC_USB->HcRhPortStatus1);
va009039 0:b0f04c137829 297 onUsbDeviceConnected(0, 1); //Hub 0 (root hub), Port 1 (count starts at 1)
va009039 0:b0f04c137829 298 }
va009039 0:b0f04c137829 299 else //Root device disconnected
va009039 0:b0f04c137829 300 {
va009039 0:b0f04c137829 301 //Device disconnected
va009039 0:b0f04c137829 302 DBG("Device disconnected\n");
va009039 0:b0f04c137829 303 onUsbDeviceDisconnected(0, 1);
va009039 0:b0f04c137829 304 }
va009039 0:b0f04c137829 305 //TODO: HUBS
va009039 0:b0f04c137829 306 }
va009039 0:b0f04c137829 307 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
va009039 0:b0f04c137829 308 }
va009039 0:b0f04c137829 309 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC)
va009039 0:b0f04c137829 310 {
va009039 0:b0f04c137829 311 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
va009039 0:b0f04c137829 312 }
va009039 0:b0f04c137829 313 }
va009039 0:b0f04c137829 314 if (int_status & OR_INTR_STATUS_WDH) /* Writeback Done Head interrupt */
va009039 0:b0f04c137829 315 {
va009039 0:b0f04c137829 316 //UsbEndpoint::sOnCompletion((LPC_USB->HccaDoneHead) & 0xFE);
va009039 0:b0f04c137829 317 if(m_pHcca->DoneHead)
va009039 0:b0f04c137829 318 {
va009039 0:b0f04c137829 319 UsbEndpoint::sOnCompletion(m_pHcca->DoneHead);
va009039 0:b0f04c137829 320 m_pHcca->DoneHead = 0;
va009039 0:b0f04c137829 321 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
va009039 0:b0f04c137829 322 if(m_pHcca->DoneHead)
va009039 0:b0f04c137829 323 DBG("??????????????????????????????\n\n\n");
va009039 0:b0f04c137829 324 }
va009039 0:b0f04c137829 325 else
va009039 0:b0f04c137829 326 {
va009039 0:b0f04c137829 327 //Probably an error
va009039 0:b0f04c137829 328 int_status = LPC_USB->HcInterruptStatus;
va009039 0:b0f04c137829 329 DBG("HcInterruptStatus = %08x\n", int_status);
va009039 0:b0f04c137829 330 if (int_status & OR_INTR_STATUS_UE) //Unrecoverable error, disconnect devices and resume
va009039 0:b0f04c137829 331 {
va009039 0:b0f04c137829 332 onUsbDeviceDisconnected(0, 1);
va009039 0:b0f04c137829 333 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_UE;
va009039 0:b0f04c137829 334 LPC_USB->HcCommandStatus = 0x01; //Host Controller Reset
va009039 0:b0f04c137829 335 }
va009039 0:b0f04c137829 336 }
va009039 0:b0f04c137829 337 }
va009039 0:b0f04c137829 338 LPC_USB->HcInterruptStatus = int_status; /* Clear interrupt status register */
va009039 0:b0f04c137829 339 }
va009039 0:b0f04c137829 340 return;
va009039 0:b0f04c137829 341 }
va009039 0:b0f04c137829 342
va009039 0:b0f04c137829 343 void UsbHostMgr::onUsbDeviceDisconnected(int hub, int port)
va009039 0:b0f04c137829 344 {
va009039 0:b0f04c137829 345 for(int i = 0; i < devicesCount(); i++)
va009039 0:b0f04c137829 346 {
va009039 0:b0f04c137829 347 if( (m_lpDevices[i]->m_hub == hub)
va009039 0:b0f04c137829 348 && (m_lpDevices[i]->m_port == port) )
va009039 0:b0f04c137829 349 {
va009039 0:b0f04c137829 350 m_lpDevices[i]->m_connected = false;
va009039 0:b0f04c137829 351 if(!m_lpDevices[i]->m_enumerated)
va009039 0:b0f04c137829 352 {
va009039 0:b0f04c137829 353 delete m_lpDevices[i];
va009039 0:b0f04c137829 354 m_lpDevices[i] = NULL;
va009039 0:b0f04c137829 355 }
va009039 0:b0f04c137829 356 return;
va009039 0:b0f04c137829 357 }
va009039 0:b0f04c137829 358 }
va009039 0:b0f04c137829 359 }
va009039 0:b0f04c137829 360
va009039 0:b0f04c137829 361 void UsbHostMgr::resetPort(int hub, int port)
va009039 0:b0f04c137829 362 {
va009039 0:b0f04c137829 363 DBG3("hub=%d port=%d\n", hub, port);
va009039 0:b0f04c137829 364 if(hub == 0) //Root hub
va009039 0:b0f04c137829 365 {
va009039 0:b0f04c137829 366 wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */
va009039 0:b0f04c137829 367 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
va009039 0:b0f04c137829 368 DBG("Before loop\n");
va009039 0:b0f04c137829 369 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
va009039 0:b0f04c137829 370 ;
va009039 0:b0f04c137829 371 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
va009039 0:b0f04c137829 372 DBG("After loop\n");
va009039 0:b0f04c137829 373 wait_ms(200); /* Wait for 100 MS after port reset */
va009039 0:b0f04c137829 374 }
va009039 0:b0f04c137829 375 else
va009039 0:b0f04c137829 376 {
va009039 0:b0f04c137829 377 for(int i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) {
va009039 0:b0f04c137829 378 UsbDevice* dev = m_lpDevices[i];
va009039 0:b0f04c137829 379 if (dev == NULL) {
va009039 0:b0f04c137829 380 continue;
va009039 0:b0f04c137829 381 }
va009039 0:b0f04c137829 382 if (dev->m_addr == hub) {
va009039 0:b0f04c137829 383 DBG("%d dev=%p\n", i, dev);
va009039 0:b0f04c137829 384 dev->hub_PortReset(port);
va009039 0:b0f04c137829 385 return;
va009039 0:b0f04c137829 386 }
va009039 0:b0f04c137829 387 }
va009039 0:b0f04c137829 388 DBG_ASSERT(0);
va009039 0:b0f04c137829 389 }
va009039 0:b0f04c137829 390 }