Modified version of NetServices. Fixes an issue where connections failed should the HTTP response status line be received in a packet on its own prior to any further headers. Changes are made to the HTTPClient.cpp file's readHeaders method.

Committer:
andrewbonney
Date:
Fri Apr 08 14:39:41 2011 +0000
Revision:
0:ec559500a63f

        

Who changed what in which revision?

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