This library is stripped down version of NetServices library. HTTP server and client function is NOT supported.

Dependents:   imu-daq-eth

Committer:
idinor
Date:
Wed Jul 20 11:45:39 2011 +0000
Revision:
0:dcf3c92487ca

        

Who changed what in which revision?

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