//------------------------------------------------------------------------------ // Main //------------------------------------------------------------------------------ int main() { unsigned int dPioStatus; S_mse_report *pReport = &(sMse.sReport); bool isChanged; TRACE_INIT(); TRACE_INFO("\n\rMain HID mouse\n\r"); // Initialize the HID mouse driver MSE_Init(&sMse, &sUsb); TRACE_INFO("Connecting ... "); // Wait for the device to be powered before connecting it while (!ISSET(USB_GetState(&sUsb), USB_STATE_POWERED)); USB_Connect(&sUsb); TRACE_INFO("OK\n\r"); // Main loop while (1) { // Retrieve PIO status change isChanged = false; dPioStatus = SWITCH_PIO->PIO_PDSR; // Check for clicks on any button // Left mouse button if (ISCLEARED(dPioStatus, SW_LEFTCLICK)) { SET(pReport->bButtons, MSE_LEFT_BUTTON); CLEAR(dPioStatus, SW_LEFTCLICK); isChanged = true; } else { // Check if button was previously pressed if (ISSET(pReport->bButtons, MSE_LEFT_BUTTON)) { CLEAR(pReport->bButtons, MSE_LEFT_BUTTON); isChanged = true; } } // Right mouse button if (ISCLEARED(dPioStatus, SW_RIGHTCLICK)) { SET(pReport->bButtons, MSE_RIGHT_BUTTON); CLEAR(dPioStatus, SW_RIGHTCLICK); isChanged = true; } else { // Check if button was previously pressed if (ISSET(pReport->bButtons, MSE_RIGHT_BUTTON)) { CLEAR(pReport->bButtons, MSE_RIGHT_BUTTON); isChanged = true; } } // Check pointer for movement // Left if (ISCLEARED(dPioStatus, SW_LEFT)) { pReport->bX = -SPEED_X; isChanged = true; } // Right else if (ISCLEARED(dPioStatus, SW_RIGHT)) { pReport->bX = SPEED_X; isChanged = true; } else { pReport->bX = 0; } // Up if (ISCLEARED(dPioStatus, SW_UP)) { pReport->bY = -SPEED_Y; isChanged = true; } // Down else if (ISCLEARED(dPioStatus, SW_DOWN)) { pReport->bY = SPEED_Y; isChanged = true; } else { pReport->bY = 0; } // Send report if a change has occured if (isChanged) { LED_TOGGLE(LED_MEM); MSE_SendReport(&sMse, 0, 0); } } }
//------------------------------------------------------------------------------ // \brief Endpoint interrupt handler. // // Handle IN/OUT transfers, received SETUP packets and STALLing // \param pUsb Pointer to a S_usb instance // \param bEndpoint Index of endpoint // \see S_usb //------------------------------------------------------------------------------ static void UDP_EndpointHandler(const S_usb *pUsb, unsigned char bEndpoint) { S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint); AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb); unsigned int dStatus = pInterface->UDP_CSR[bEndpoint]; TRACE_DEBUG_L("Ept%d ", bEndpoint); // Handle interrupts // IN packet sent if (ISSET(dStatus, AT91C_UDP_TXCOMP)) { TRACE_DEBUG_L("Wr "); // Check that endpoint was in Write state if (pEndpoint->dState == endpointStateWrite) { // End of transfer ? if ((pEndpoint->dBytesBuffered < pEndpoint->wMaxPacketSize) || (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE) && (pEndpoint->dBytesRemaining == 0) && (pEndpoint->dBytesBuffered == pEndpoint->wMaxPacketSize))) { TRACE_DEBUG_L("%d ", pEndpoint->dBytesBuffered); pEndpoint->dBytesTransferred += pEndpoint->dBytesBuffered; pEndpoint->dBytesBuffered = 0; // Disable interrupt if this is not a control endpoint if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) { SET(pInterface->UDP_IDR, 1 << bEndpoint); } UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS); } else { // Transfer remaining data TRACE_DEBUG_L("%d ", pEndpoint->wMaxPacketSize); pEndpoint->dBytesTransferred += pEndpoint->wMaxPacketSize; pEndpoint->dBytesBuffered -= pEndpoint->wMaxPacketSize; // Send next packet if (pEndpoint->dNumFIFO == 1) { // No double buffering UDP_WritePayload(pUsb, bEndpoint); UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY); } else { // Double buffering UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY); UDP_WritePayload(pUsb, bEndpoint); } } } // Acknowledge interrupt UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXCOMP); } // OUT packet received if (ISSET(dStatus, AT91C_UDP_RX_DATA_BK0) || ISSET(dStatus, AT91C_UDP_RX_DATA_BK1)) { TRACE_DEBUG_L("Rd "); // Check that the endpoint is in Read state if (pEndpoint->dState != endpointStateRead) { // Endpoint is NOT in Read state if (ISCLEARED(dStatus, AT91C_UDP_EPTYPE) && ISCLEARED(dStatus, 0xFFFF0000)) { // Control endpoint, 0 bytes received // Acknowledge the data and finish the current transfer TRACE_DEBUG_L("Ack "); UDP_ClearRXFlag(pUsb, bEndpoint); UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS); } else if (ISSET(dStatus, AT91C_UDP_FORCESTALL)) { // Non-control endpoint // Discard stalled data TRACE_DEBUG_L("Disc "); UDP_ClearRXFlag(pUsb, bEndpoint); } else { // Non-control endpoint // Nak data TRACE_DEBUG_L("Nak "); SET(pInterface->UDP_IDR, 1 << bEndpoint); } } else { // Endpoint is in Read state // Retrieve data and store it into the current transfer buffer unsigned short wPacketSize = (unsigned short) (dStatus >> 16); TRACE_DEBUG_L("%d ", wPacketSize); UDP_GetPayload(pUsb, bEndpoint, wPacketSize); UDP_ClearRXFlag(pUsb, bEndpoint); if ((pEndpoint->dBytesRemaining == 0) || (wPacketSize < pEndpoint->wMaxPacketSize)) { // Disable interrupt if this is not a control endpoint if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) { SET(pInterface->UDP_IDR, 1 << bEndpoint); } UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS); } } }
//void NAKEDFUNC usb_irq_service(void) void usb_irq_service(void) { //ISR_ENTRY(); // End interrupt if we are not attached to USB bus //*AT91C_PIOA_SODR = PIN_LED; //TRACE_ALL("@"); if (ISCLEARED(usb_device_state,USB_STATE_ATTACHED)) goto end_of_irq; unsigned char endpoint; unsigned int status = pUDP->UDP_ISR & pUDP->UDP_IMR & ISR_MASK; while( status != 0) { // Start Of Frame (SOF) if (ISSET(status, AT91C_UDP_SOFINT)) { TRACE_USB("SOF "); // Acknowledge interrupt SET(pUDP->UDP_ICR, AT91C_UDP_SOFINT); CLEAR(status, AT91C_UDP_SOFINT); } // Suspend if (ISSET(status,AT91C_UDP_RXSUSP)) { TRACE_USB("Susp "); if (ISCLEARED(usb_device_state,USB_STATE_SUSPENDED)) { // The device enters the Suspended state // MCK + UDPCK must be off // Pull-Up must be connected // Transceiver must be disabled // Enable wakeup SET(pUDP->UDP_IER, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM); // Acknowledge interrupt SET(pUDP->UDP_ICR, AT91C_UDP_RXSUSP); // Set suspended state SET(usb_device_state,USB_STATE_SUSPENDED); // Disable transceiver SET(pUDP->UDP_TXVC, AT91C_UDP_TXVDIS); // Disable master clock AT91C_BASE_PMC->PMC_PCDR |= (1 << AT91C_ID_UDP); // Disable peripheral clock for USB AT91C_BASE_PMC->PMC_SCDR |= AT91C_PMC_UDP; } } // Resume else if (ISSET(status, AT91C_UDP_WAKEUP) || ISSET(status, AT91C_UDP_RXRSM)) { TRACE_USB("Resm "); // The device enters Configured state // MCK + UDPCK must be on // Pull-Up must be connected // Transceiver must be enabled // Powered state // Enable master clock AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_UDP); // Enable peripheral clock for USB AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP; // Default state if (ISSET(usb_device_state,USB_STATE_DEFAULT)) { // Enable transceiver CLEAR(pUDP->UDP_TXVC, AT91C_UDP_TXVDIS); } CLEAR(usb_device_state, USB_STATE_SUSPENDED); SET(pUDP->UDP_ICR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP); SET(pUDP->UDP_IDR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM); } // End of bus reset else if (ISSET(status, AT91C_UDP_ENDBUSRES)) { TRACE_USB("\n\n\nEoBres "); // Initialize UDP peripheral device usb_bus_reset_handler(); // Flush and enable the Suspend interrupt SET(pUDP->UDP_ICR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP); // Acknowledge end of bus reset interrupt SET(pUDP->UDP_ICR, AT91C_UDP_ENDBUSRES); } // Endpoint interrupts else { while (status != 0) { // Get endpoint index endpoint = last_set_bit(status); usb_endpoint_handler(endpoint); CLEAR(pUDP->UDP_ICR, (1 << endpoint)); CLEAR(status, 1 << endpoint); } } status = pUDP->UDP_ISR & pUDP->UDP_IMR & ISR_MASK; // Mask unneeded interrupts if (ISCLEARED(usb_device_state,DEFAULT_STATE)) { status &= AT91C_UDP_ENDBUSRES | AT91C_UDP_SOFINT; } } // end while status != 0 end_of_irq: *AT91C_AIC_EOICR = 1; // ACK interrupt end *AT91C_AIC_ICCR = 1 << AT91C_ID_UDP; // clear interrupt on the interrupt controller //ISR_EXIT(); }