Library for Bert van Dam's book "ARM MICROCONTROLLERS" For all chapters with internet.

Dependencies:   mbed

Committer:
ICTFBI
Date:
Fri Oct 16 14:28:26 2015 +0000
Revision:
0:4edb816d21e1
Pre-update 16-10-15

Who changed what in which revision?

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