Webcam Server.

Dependencies:   uvchost FatFileSystem mbed HTTPServer NetServicesMin

Committer:
va009039
Date:
Wed Jun 06 11:47:06 2012 +0000
Revision:
0:2b4ea8a138e5

        

Who changed what in which revision?

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