BLE demo for mbed Ported RunningElectronics's SBDBT firmware for BLE. It can communicate with iOS
Dependencies: FatFileSystem mbed
Fork of BTstack by
UsbHostMgr.cpp
00001 00002 /* 00003 Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com) 00004 00005 Permission is hereby granted, free of charge, to any person obtaining a copy 00006 of this software and associated documentation files (the "Software"), to deal 00007 in the Software without restriction, including without limitation the rights 00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00009 copies of the Software, and to permit persons to whom the Software is 00010 furnished to do so, subject to the following conditions: 00011 00012 The above copyright notice and this permission notice shall be included in 00013 all copies or substantial portions of the Software. 00014 00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00021 THE SOFTWARE. 00022 */ 00023 #include "UsbHostMgr.h" 00024 #include "usb_mem.h" 00025 #include "Usb_td.h" 00026 #include "string.h" //For memcpy, memmove, memset 00027 #include "netCfg.h" 00028 #if NET_USB 00029 //#define __DEBUG 00030 //#define __DEBUG3 00031 //#include "dbg/dbg.h" 00032 #include "mydbg.h" 00033 00034 // bits of the USB/OTG clock control register 00035 #define HOST_CLK_EN (1<<0) 00036 #define DEV_CLK_EN (1<<1) 00037 #define PORTSEL_CLK_EN (1<<3) 00038 #define AHB_CLK_EN (1<<4) 00039 00040 // bits of the USB/OTG clock status register 00041 #define HOST_CLK_ON (1<<0) 00042 #define DEV_CLK_ON (1<<1) 00043 #define PORTSEL_CLK_ON (1<<3) 00044 #define AHB_CLK_ON (1<<4) 00045 00046 // we need host clock, OTG/portsel clock and AHB clock 00047 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN) 00048 00049 static UsbHostMgr* pMgr = NULL; 00050 00051 extern "C" void sUsbIrqhandler(void) __irq 00052 { 00053 DBG("\n+Int\n"); 00054 if(pMgr) 00055 pMgr->UsbIrqhandler(); 00056 DBG("\n-Int\n"); 00057 return; 00058 } 00059 00060 UsbHostMgr::UsbHostMgr() : m_lpDevices() 00061 { 00062 /*if(!pMgr)*/ //Assume singleton 00063 pMgr = this; 00064 usb_mem_init(); 00065 for(int i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) { 00066 m_lpDevices[i] = NULL; 00067 } 00068 m_pHcca = (HCCA*) usb_get_hcca(); 00069 memset((void*)m_pHcca, 0, 0x100); 00070 m_hardware_init = false; 00071 DBG("Host manager at %p\n", this); 00072 00073 test_td(); // TD test program 00074 } 00075 00076 UsbHostMgr::~UsbHostMgr() 00077 { 00078 if(pMgr == this) 00079 pMgr = NULL; 00080 } 00081 00082 UsbErr UsbHostMgr::init() //Initialize host 00083 { 00084 DBG("m_hardware_init=%d\n", m_hardware_init); 00085 if(m_hardware_init) { 00086 return USBERR_OK; 00087 } 00088 00089 NVIC_DisableIRQ(USB_IRQn); /* Disable the USB interrupt source */ 00090 00091 LPC_SC->PCONP &= ~(1UL<<31); //Cut power 00092 wait(1); 00093 00094 00095 // turn on power for USB 00096 LPC_SC->PCONP |= (1UL<<31); 00097 // Enable USB host clock, port selection and AHB clock 00098 LPC_USB->USBClkCtrl |= CLOCK_MASK; 00099 // Wait for clocks to become available 00100 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK) 00101 ; 00102 00103 // it seems the bits[0:1] mean the following 00104 // 0: U1=device, U2=host 00105 // 1: U1=host, U2=host 00106 // 2: reserved 00107 // 3: U1=host, U2=device 00108 // NB: this register is only available if OTG clock (aka "port select") is enabled!! 00109 // since we don't care about port 2, set just bit 0 to 1 (U1=host) 00110 LPC_USB->OTGStCtrl |= 1; 00111 00112 // now that we've configured the ports, we can turn off the portsel clock 00113 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; 00114 00115 // power pins are not connected on mbed, so we can skip them 00116 /* P1[18] = USB_UP_LED, 01 */ 00117 /* P1[19] = /USB_PPWR, 10 */ 00118 /* P1[22] = USB_PWRD, 10 */ 00119 /* P1[27] = /USB_OVRCR, 10 */ 00120 /*LPC_PINCON->PINSEL3 &= ~((3<<4) | (3<<6) | (3<<12) | (3<<22)); 00121 LPC_PINCON->PINSEL3 |= ((1<<4)|(2<<6) | (2<<12) | (2<<22)); // 0x00802080 00122 */ 00123 00124 // configure USB D+/D- pins 00125 /* P0[29] = USB_D+, 01 */ 00126 /* P0[30] = USB_D-, 01 */ 00127 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28)); 00128 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000 00129 00130 DBG("Initializing Host Stack\n"); 00131 00132 wait_ms(100); /* Wait 50 ms before apply reset */ 00133 LPC_USB->HcControl = 0; /* HARDWARE RESET */ 00134 LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */ 00135 LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */ 00136 00137 /* SOFTWARE RESET */ 00138 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR; 00139 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */ 00140 LPC_USB->HcPeriodicStart = FI*90/100; 00141 00142 /* Put HC in operational state */ 00143 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER; 00144 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */ 00145 00146 LPC_USB->HcHCCA = (uint32_t)(m_pHcca); 00147 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */ 00148 00149 00150 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | 00151 OR_INTR_ENABLE_WDH | 00152 OR_INTR_ENABLE_RHSC; 00153 00154 NVIC_SetPriority(USB_IRQn, 0); /* highest priority */ 00155 /* Enable the USB Interrupt */ 00156 NVIC_SetVector(USB_IRQn, (uint32_t)(sUsbIrqhandler)); 00157 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC; 00158 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; 00159 00160 00161 /* Check for any connected devices */ 00162 //if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) //Root device connected 00163 //{ 00164 // //Device connected 00165 // wait(1); 00166 // DBG("Device connected (%08x)\n", LPC_USB->HcRhPortStatus1); 00167 // onUsbDeviceConnected(0, 1); //Hub 0 (root hub), Port 1 (count starts at 1) 00168 //} 00169 00170 DBG("Enabling IRQ\n"); 00171 NVIC_EnableIRQ(USB_IRQn); 00172 DBG("End of host stack initialization\n"); 00173 m_hardware_init = true; 00174 return USBERR_OK; 00175 } 00176 00177 UsbErr UsbHostMgr::poll() //Enumerate connected devices, etc 00178 { 00179 /* Check for any connected devices */ 00180 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) //Root device connected 00181 { 00182 //Device connected 00183 wait(1); 00184 DBG("Device connected (%08x)\n", LPC_USB->HcRhPortStatus1); 00185 onUsbDeviceConnected(0, 1); //Hub 0 (root hub), Port 1 (count starts at 1) 00186 } 00187 00188 for(int i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) 00189 { 00190 UsbDevice* dev = m_lpDevices[i]; 00191 if (dev == NULL) { 00192 continue; 00193 } 00194 DBG3("%d dev=%p %d %d addr=%d\n", i, dev, dev->m_connected, dev->m_enumerated, dev->m_addr); 00195 if(dev->m_connected) { 00196 if (!dev->m_enumerated) { 00197 dev->enumerate(); 00198 return USBERR_PROCESSING; 00199 } 00200 } 00201 } 00202 for(int i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) { 00203 UsbDevice* dev = m_lpDevices[i]; 00204 if (dev == NULL) { 00205 continue; 00206 } 00207 if (dev->m_connected && dev->m_enumerated) { 00208 if (dev->m_DeviceClass == 0x09) { // HUB 00209 UsbErr rc = dev->hub_poll(); 00210 if (rc == USBERR_PROCESSING) { 00211 return USBERR_PROCESSING; 00212 } 00213 } 00214 } 00215 } 00216 return USBERR_OK; 00217 } 00218 00219 int UsbHostMgr::devicesCount() 00220 { 00221 int i; 00222 for(i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) 00223 { 00224 if (m_lpDevices[i] == NULL) { 00225 return i; 00226 } 00227 } 00228 return i; 00229 } 00230 00231 UsbDevice* UsbHostMgr::getDevice(int item) 00232 { 00233 UsbDevice* pDev = m_lpDevices[item]; 00234 if(!pDev) 00235 return NULL; 00236 00237 pDev->m_refs++; 00238 return pDev; 00239 } 00240 00241 void UsbHostMgr::releaseDevice(UsbDevice* pDev) 00242 { 00243 DBG_ASSERT(0); 00244 00245 pDev->m_refs--; 00246 if(pDev->m_refs > 0) 00247 return; 00248 //If refs count = 0, delete 00249 //Find & remove from list 00250 int i; 00251 for(i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) 00252 { 00253 if (m_lpDevices[i] == pDev) 00254 break; 00255 } 00256 if(i!=USB_HOSTMGR_MAX_DEVS) 00257 memmove(&m_lpDevices[i], &m_lpDevices[i+1], sizeof(UsbDevice*) * (USB_HOSTMGR_MAX_DEVS - (i + 1))); //Safer than memcpy because of overlapping mem 00258 m_lpDevices[USB_HOSTMGR_MAX_DEVS - 1] = NULL; 00259 delete pDev; 00260 } 00261 00262 void UsbHostMgr::UsbIrqhandler() 00263 { 00264 uint32_t int_status; 00265 uint32_t ie_status; 00266 00267 int_status = LPC_USB->HcInterruptStatus; /* Read Interrupt Status */ 00268 ie_status = LPC_USB->HcInterruptEnable; /* Read Interrupt enable status */ 00269 00270 if (!(int_status & ie_status)) 00271 { 00272 return; 00273 } 00274 else 00275 { 00276 int_status = int_status & ie_status; 00277 if (int_status & OR_INTR_STATUS_RHSC) /* Root hub status change interrupt */ 00278 { 00279 DBG("LPC_USB->HcRhPortStatus1 = %08x\n", LPC_USB->HcRhPortStatus1); 00280 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC) 00281 { 00282 if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) 00283 { 00284 /* 00285 * When DRWE is on, Connect Status Change 00286 * means a remote wakeup event. 00287 */ 00288 //HOST_RhscIntr = 1;// JUST SOMETHING FOR A BREAKPOINT 00289 } 00290 else 00291 { 00292 /* 00293 * When DRWE is off, Connect Status Change 00294 * is NOT a remote wakeup event 00295 */ 00296 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) //Root device connected 00297 { 00298 //Device connected 00299 DBG("Device connected (%08x)\n", LPC_USB->HcRhPortStatus1); 00300 onUsbDeviceConnected(0, 1); //Hub 0 (root hub), Port 1 (count starts at 1) 00301 } 00302 else //Root device disconnected 00303 { 00304 //Device disconnected 00305 DBG("Device disconnected\n"); 00306 onUsbDeviceDisconnected(0, 1); 00307 } 00308 //TODO: HUBS 00309 } 00310 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC; 00311 } 00312 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC) 00313 { 00314 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; 00315 } 00316 } 00317 if (int_status & OR_INTR_STATUS_WDH) /* Writeback Done Head interrupt */ 00318 { 00319 //UsbEndpoint::sOnCompletion((LPC_USB->HccaDoneHead) & 0xFE); 00320 if(m_pHcca->DoneHead) 00321 { 00322 UsbEndpoint::sOnCompletion(m_pHcca->DoneHead); 00323 m_pHcca->DoneHead = 0; 00324 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH; 00325 if(m_pHcca->DoneHead) 00326 DBG("??????????????????????????????\n\n\n"); 00327 } 00328 else 00329 { 00330 //Probably an error 00331 int_status = LPC_USB->HcInterruptStatus; 00332 DBG("HcInterruptStatus = %08x\n", int_status); 00333 if (int_status & OR_INTR_STATUS_UE) //Unrecoverable error, disconnect devices and resume 00334 { 00335 onUsbDeviceDisconnected(0, 1); 00336 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_UE; 00337 LPC_USB->HcCommandStatus = 0x01; //Host Controller Reset 00338 } 00339 } 00340 } 00341 LPC_USB->HcInterruptStatus = int_status; /* Clear interrupt status register */ 00342 } 00343 return; 00344 } 00345 00346 void UsbHostMgr::onUsbDeviceDisconnected(int hub, int port) 00347 { 00348 for(int i = 0; i < devicesCount(); i++) 00349 { 00350 if( (m_lpDevices[i]->m_hub == hub) 00351 && (m_lpDevices[i]->m_port == port) ) 00352 { 00353 m_lpDevices[i]->m_connected = false; 00354 if(!m_lpDevices[i]->m_enumerated) 00355 { 00356 delete m_lpDevices[i]; 00357 m_lpDevices[i] = NULL; 00358 } 00359 return; 00360 } 00361 } 00362 } 00363 00364 void UsbHostMgr::resetPort(int hub, int port) 00365 { 00366 DBG3("hub=%d port=%d\n", hub, port); 00367 if(hub == 0) //Root hub 00368 { 00369 wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */ 00370 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset 00371 DBG("Before loop\n"); 00372 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS) 00373 ; 00374 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal 00375 DBG("After loop\n"); 00376 wait_ms(200); /* Wait for 100 MS after port reset */ 00377 } 00378 else 00379 { 00380 for(int i = 0; i < USB_HOSTMGR_MAX_DEVS; i++) { 00381 UsbDevice* dev = m_lpDevices[i]; 00382 if (dev == NULL) { 00383 continue; 00384 } 00385 if (dev->m_addr == hub) { 00386 DBG("%d dev=%p\n", i, dev); 00387 dev->hub_PortReset(port); 00388 return; 00389 } 00390 } 00391 DBG_ASSERT(0); 00392 } 00393 } 00394 00395 #endif
Generated on Thu Jul 14 2022 15:03:49 by 1.7.2