ST/USBHOST forked to add another HID handler for raw keyboard data to get more detail not available with current handlers (all pressed keys, all releases, and periodic updates)

Dependents:   C64-stm429_discovery

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHALHost_RZ_A1.cpp Source File

USBHALHost_RZ_A1.cpp

00001 /* mbed USBHost Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #if defined(TARGET_RZ_A1H) || defined(TARGET_VK_RZ_A1H)
00018 
00019 #include "mbed.h"
00020 #include "USBHALHost.h"
00021 #include "dbg.h"
00022 
00023 #include "ohci_wrapp_RZ_A1.h"
00024 
00025 
00026 #define HCCA_SIZE sizeof(HCCA)
00027 #define ED_SIZE sizeof(HCED)
00028 #define TD_SIZE sizeof(HCTD)
00029 
00030 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
00031 #define ALIGNE_MSK (0x0000000F)
00032 
00033 static volatile uint8_t usb_buf[TOTAL_SIZE + ALIGNE_MSK];  //16 bytes aligned!
00034 
00035 USBHALHost * USBHALHost::instHost;
00036 
00037 USBHALHost::USBHALHost() {
00038     instHost = this;
00039     memInit();
00040     memset((void*)usb_hcca, 0, HCCA_SIZE);
00041     for (int i = 0; i < MAX_ENDPOINT; i++) {
00042         edBufAlloc[i] = false;
00043     }
00044     for (int i = 0; i < MAX_TD; i++) {
00045         tdBufAlloc[i] = false;
00046     }
00047 }
00048 
00049 void USBHALHost::init() {
00050     ohciwrapp_init(&_usbisr);
00051 
00052     ohciwrapp_reg_w(OHCI_REG_CONTROL, 1);       // HARDWARE RESET
00053     ohciwrapp_reg_w(OHCI_REG_CONTROLHEADED, 0); // Initialize Control list head to Zero
00054     ohciwrapp_reg_w(OHCI_REG_BULKHEADED, 0);    // Initialize Bulk list head to Zero
00055 
00056     // Wait 100 ms before apply reset
00057     wait_ms(100);
00058 
00059     // software reset
00060     ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS, OR_CMD_STATUS_HCR);
00061 
00062     // Write Fm Interval and Largest Data Packet Counter
00063     ohciwrapp_reg_w(OHCI_REG_FMINTERVAL, DEFAULT_FMINTERVAL);
00064     ohciwrapp_reg_w(OHCI_REG_PERIODICSTART,  FI * 90 / 100);
00065 
00066     // Put HC in operational state
00067     ohciwrapp_reg_w(OHCI_REG_CONTROL, (ohciwrapp_reg_r(OHCI_REG_CONTROL) & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER);
00068     // Set Global Power
00069     ohciwrapp_reg_w(OHCI_REG_RHSTATUS, OR_RH_STATUS_LPSC);
00070 
00071     ohciwrapp_reg_w(OHCI_REG_HCCA, (uint32_t)(usb_hcca));
00072 
00073     // Clear Interrrupt Status
00074     ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS, ohciwrapp_reg_r(OHCI_REG_INTERRUPTSTATUS));
00075 
00076     ohciwrapp_reg_w(OHCI_REG_INTERRUPTENABLE, OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC);
00077 
00078     // Enable the USB Interrupt
00079     ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_CSC);
00080     ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_PRSC);
00081 
00082     // Check for any connected devices
00083     if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_CCS) {
00084         //Device connected
00085         wait_ms(150);
00086         USB_DBG("Device connected (%08x)\n\r", ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1));
00087         deviceConnected(0, 1, ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_LSDA);
00088     }
00089 }
00090 
00091 uint32_t USBHALHost::controlHeadED() {
00092     return ohciwrapp_reg_r(OHCI_REG_CONTROLHEADED);
00093 }
00094 
00095 uint32_t USBHALHost::bulkHeadED() {
00096     return ohciwrapp_reg_r(OHCI_REG_BULKHEADED);
00097 }
00098 
00099 uint32_t USBHALHost::interruptHeadED() {
00100     return usb_hcca->IntTable[0];
00101 }
00102 
00103 void USBHALHost::updateBulkHeadED(uint32_t addr) {
00104     ohciwrapp_reg_w(OHCI_REG_BULKHEADED, addr);
00105 }
00106 
00107 
00108 void USBHALHost::updateControlHeadED(uint32_t addr) {
00109     ohciwrapp_reg_w(OHCI_REG_CONTROLHEADED, addr);
00110 }
00111 
00112 void USBHALHost::updateInterruptHeadED(uint32_t addr) {
00113     usb_hcca->IntTable[0] = addr;
00114 }
00115 
00116 
00117 void USBHALHost::enableList(ENDPOINT_TYPE type) {
00118     uint32_t wk_data;
00119 
00120     switch(type) {
00121         case CONTROL_ENDPOINT:
00122             ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS, OR_CMD_STATUS_CLF);
00123             wk_data = (ohciwrapp_reg_r(OHCI_REG_CONTROL) | OR_CONTROL_CLE);
00124             ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data);
00125             break;
00126         case ISOCHRONOUS_ENDPOINT:
00127             break;
00128         case BULK_ENDPOINT:
00129             ohciwrapp_reg_w(OHCI_REG_COMMANDSTATUS, OR_CMD_STATUS_BLF);
00130             wk_data = (ohciwrapp_reg_r(OHCI_REG_CONTROL) | OR_CONTROL_BLE);
00131             ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data);
00132             break;
00133         case INTERRUPT_ENDPOINT:
00134             wk_data = (ohciwrapp_reg_r(OHCI_REG_CONTROL) | OR_CONTROL_PLE);
00135             ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data);
00136             break;
00137     }
00138 }
00139 
00140 
00141 bool USBHALHost::disableList(ENDPOINT_TYPE type) {
00142     uint32_t wk_data;
00143 
00144     switch(type) {
00145         case CONTROL_ENDPOINT:
00146             wk_data = ohciwrapp_reg_r(OHCI_REG_CONTROL);
00147             if(wk_data & OR_CONTROL_CLE) {
00148                 wk_data &= ~OR_CONTROL_CLE;
00149                 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data);
00150                 return true;
00151             }
00152             return false;
00153         case ISOCHRONOUS_ENDPOINT:
00154             return false;
00155         case BULK_ENDPOINT:
00156             wk_data = ohciwrapp_reg_r(OHCI_REG_CONTROL);
00157             if(wk_data & OR_CONTROL_BLE) {
00158                 wk_data &= ~OR_CONTROL_BLE;
00159                 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data);
00160                 return true;
00161             }
00162             return false;
00163         case INTERRUPT_ENDPOINT:
00164             wk_data = ohciwrapp_reg_r(OHCI_REG_CONTROL);
00165             if(wk_data & OR_CONTROL_PLE) {
00166                 wk_data &= ~OR_CONTROL_PLE;
00167                 ohciwrapp_reg_w(OHCI_REG_CONTROL, wk_data);
00168                 return true;
00169             }
00170             return false;
00171     }
00172     return false;
00173 }
00174 
00175 
00176 void USBHALHost::memInit() {
00177     volatile uint8_t *p_wk_buf = (uint8_t *)(((uint32_t)usb_buf + ALIGNE_MSK) & ~ALIGNE_MSK);
00178 
00179     usb_hcca = (volatile HCCA *)p_wk_buf;
00180     usb_edBuf = (volatile uint8_t *)(p_wk_buf + HCCA_SIZE);
00181     usb_tdBuf = (volatile uint8_t *)(p_wk_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE));
00182 }
00183 
00184 volatile uint8_t * USBHALHost::getED() {
00185     for (int i = 0; i < MAX_ENDPOINT; i++) {
00186         if ( !edBufAlloc[i] ) {
00187             edBufAlloc[i] = true;
00188             return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE);
00189         }
00190     }
00191     perror("Could not allocate ED\r\n");
00192     return NULL; //Could not alloc ED
00193 }
00194 
00195 volatile uint8_t * USBHALHost::getTD() {
00196     int i;
00197     for (i = 0; i < MAX_TD; i++) {
00198         if ( !tdBufAlloc[i] ) {
00199             tdBufAlloc[i] = true;
00200             return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE);
00201         }
00202     }
00203     perror("Could not allocate TD\r\n");
00204     return NULL; //Could not alloc TD
00205 }
00206 
00207 
00208 void USBHALHost::freeED(volatile uint8_t * ed) {
00209     int i;
00210     i = (ed - usb_edBuf) / ED_SIZE;
00211     edBufAlloc[i] = false;
00212 }
00213 
00214 void USBHALHost::freeTD(volatile uint8_t * td) {
00215     int i;
00216     i = (td - usb_tdBuf) / TD_SIZE;
00217     tdBufAlloc[i] = false;
00218 }
00219 
00220 
00221 void USBHALHost::resetRootHub() {
00222     // Initiate port reset
00223     ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_PRS);
00224 
00225     while (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_PRS);
00226 
00227     // ...and clear port reset signal
00228     ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_PRSC);
00229 }
00230 
00231 
00232 void USBHALHost::_usbisr(void) {
00233     if (instHost) {
00234         instHost->UsbIrqhandler();
00235     }
00236 }
00237 
00238 void USBHALHost::UsbIrqhandler() {
00239     uint32_t int_status = ohciwrapp_reg_r(OHCI_REG_INTERRUPTSTATUS) & ohciwrapp_reg_r(OHCI_REG_INTERRUPTENABLE);
00240     uint32_t data;
00241 
00242     if (int_status != 0) { //Is there something to actually process?
00243         // Root hub status change interrupt
00244         if (int_status & OR_INTR_STATUS_RHSC) {
00245             if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_CSC) {
00246                 if (ohciwrapp_reg_r(OHCI_REG_RHSTATUS) & OR_RH_STATUS_DRWE) {
00247                     // When DRWE is on, Connect Status Change
00248                     // means a remote wakeup event.
00249                 } else {
00250 
00251                     //Root device connected
00252                     if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_CCS) {
00253 
00254                         // wait 150ms to avoid bounce
00255                         wait_ms(150);
00256 
00257                         //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
00258                         data = ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_LSDA;
00259                         deviceConnected(0, 1, data);
00260                     }
00261 
00262                     //Root device disconnected
00263                     else {
00264                         deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE);
00265                     }
00266                 }
00267                 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_CSC);
00268             }
00269             if (ohciwrapp_reg_r(OHCI_REG_RHPORTSTATUS1) & OR_RH_PORT_PRSC) {
00270                 ohciwrapp_reg_w(OHCI_REG_RHPORTSTATUS1, OR_RH_PORT_PRSC);
00271             }
00272             ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS, OR_INTR_STATUS_RHSC);
00273         }
00274 
00275         // Writeback Done Head interrupt
00276         if (int_status & OR_INTR_STATUS_WDH) {
00277             transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE);
00278             ohciwrapp_reg_w(OHCI_REG_INTERRUPTSTATUS, OR_INTR_STATUS_WDH);
00279         }
00280     }
00281 }
00282 #endif