From c3e4c9a25c2910d2d66d52215b3406b13d5b23d5 Mon Sep 17 00:00:00 2001 From: Yuval Adam Date: Sun, 29 Jun 2014 12:34:32 +0300 Subject: Add more board models --- boards/dk-tm4c129x/usb_otg_mouse/usb_host_mouse.c | 740 ++++++++++++++++++++++ 1 file changed, 740 insertions(+) create mode 100644 boards/dk-tm4c129x/usb_otg_mouse/usb_host_mouse.c (limited to 'boards/dk-tm4c129x/usb_otg_mouse/usb_host_mouse.c') diff --git a/boards/dk-tm4c129x/usb_otg_mouse/usb_host_mouse.c b/boards/dk-tm4c129x/usb_otg_mouse/usb_host_mouse.c new file mode 100644 index 0000000..c2b0de6 --- /dev/null +++ b/boards/dk-tm4c129x/usb_otg_mouse/usb_host_mouse.c @@ -0,0 +1,740 @@ +//***************************************************************************** +// +// usb_host_mouse.c - main application code for the host mouse example. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the DK-TM4C129X Firmware Package. +// +//***************************************************************************** + +#include +#include +#include "grlib/grlib.h" +#include "usblib/usblib.h" +#include "usblib/usbhid.h" +#include "usblib/host/usbhost.h" +#include "usblib/host/usbhhid.h" +#include "usblib/host/usbhhidmouse.h" +#include "utils/uartstdio.h" +#include "usb_otg_mouse.h" + +//***************************************************************************** +// +// The size of the mouse device interface's memory pool in bytes. +// +//***************************************************************************** +#define MOUSE_MEMORY_SIZE 128 + +//***************************************************************************** +// +// The memory pool to provide to the mouse device. +// +//***************************************************************************** +uint8_t g_pui8Buffer[MOUSE_MEMORY_SIZE]; + +//***************************************************************************** +// +// Declare the USB Events driver interface. +// +//***************************************************************************** +DECLARE_EVENT_DRIVER(g_sUSBEventDriver, 0, 0, USBHCDEvents); + +//***************************************************************************** +// +// The global that holds all of the host drivers in use in the application. +// In this case, only the Mouse class is loaded. +// +//***************************************************************************** +static tUSBHostClassDriver const * const g_ppHostClassDrivers[] = +{ + &g_sUSBHIDClassDriver, + &g_sUSBEventDriver +}; + +//***************************************************************************** +// +// This global holds the number of class drivers in the g_ppHostClassDrivers +// list. +// +//***************************************************************************** +static const uint32_t g_ui32NumHostClassDrivers = + sizeof(g_ppHostClassDrivers) / sizeof(tUSBHostClassDriver *); + +//***************************************************************************** +// +// The global value used to store the mouse instance value. +// +//***************************************************************************** +static tUSBHMouse *g_psMouseInstance; + +//***************************************************************************** +// +// The global values used to store the mouse state. +// +//***************************************************************************** +static uint32_t g_ui32Buttons; +static tRectangle g_sCursor; + +//***************************************************************************** +// +// This enumerated type is used to hold the states of the mouse. +// +//***************************************************************************** +enum +{ + // + // No device is present. + // + eStateNoDevice, + + // + // Mouse has been detected and needs to be initialized in the main + // loop. + // + eStateMouseInit, + + // + // Mouse is connected and waiting for events. + // + eStateMouseConnected, + + // + // An unsupported device has been attached. + // + eStateUnknownDevice, + + // + // A power fault has occurred. + // + eStatePowerFault +} +iUSBState; + +//***************************************************************************** +// +// These defines are used to define the screen constraints to the application. +// +//***************************************************************************** +#define DISPLAY_BANNER_HEIGHT 20 +#define DISPLAY_BANNER_BG ClrDarkBlue +#define DISPLAY_BANNER_FG ClrWhite +#define DISPLAY_MOUSE_BG ClrBlack +#define DISPLAY_MOUSE_FG ClrWhite +#define DISPLAY_MOUSE_SIZE 2 + +//***************************************************************************** +// +// This function clears the main application screen area. +// +//***************************************************************************** +void +ClearMainWindow(void) +{ + tRectangle sRect; + + // + // Initialize the button indicator. + // + sRect.i16XMin = 0; + sRect.i16YMin = DISPLAY_BANNER_HEIGHT + 1; + sRect.i16XMax = GrContextDpyWidthGet(&g_sContext) - 1; + sRect.i16YMax = GrContextDpyHeightGet(&g_sContext) - DISPLAY_BANNER_HEIGHT; + + GrContextForegroundSet(&g_sContext, DISPLAY_MOUSE_BG); + GrRectFill(&g_sContext, &sRect); + GrContextForegroundSet(&g_sContext, DISPLAY_MOUSE_FG); +} + +//***************************************************************************** +// +// This function updates the cursor position based on deltas received from +// the mouse device. +// +// \param i32XDelta is the signed movement in the X direction. +// \param i32YDelta is the signed movement in the Y direction. +// +// This function is called by the mouse handler code when it detects a change +// in the position of the mouse. It will take the inputs and force them +// to be constrained to the display area of the screen. If the left mouse +// button is pressed then the mouse will draw on the screen and if it is not +// it will move around normally. A side effect of not being able to read the +// current state of the screen is that the cursor will erase anything it moves +// over while the left mouse button is not pressed. +// +// \return None. +// +//***************************************************************************** +void +UpdateCursor(int32_t i32XDelta, int32_t i32YDelta) +{ + int32_t i32Temp; + + // + // If the left button is not pressed then erase the previous cursor + // position. + // + if((g_ui32Buttons & 1) == 0) + { + // + // Erase the previous cursor. + // + GrContextForegroundSet(&g_sContext, DISPLAY_MOUSE_BG); + GrRectFill(&g_sContext, &g_sCursor); + } + + // + // Need to do signed math so use the temporary signed value. + // + i32Temp = g_sCursor.i16XMin; + + // + // Update the X position without going off the screen. + // + if(((int)g_sCursor.i16XMin + i32XDelta + DISPLAY_MOUSE_SIZE) < + GrContextDpyWidthGet(&g_sContext)) + { + // + // Update the X cursor position. + // + i32Temp += i32XDelta; + + // + // Don't let the cursor go off the left of the screen either. + // + if(i32Temp < 0) + { + i32Temp = 0; + } + } + + // + // Update the X position. + // + g_sCursor.i16XMin = i32Temp; + g_sCursor.i16XMax = i32Temp + DISPLAY_MOUSE_SIZE; + + // + // Need to do signed math so use the temporary signed value. + // + i32Temp = g_sCursor.i16YMin; + + // + // Update the Y position without going off the screen. + // + if(((int)g_sCursor.i16YMin + i32YDelta) < + (GrContextDpyHeightGet(&g_sContext) - + DISPLAY_BANNER_HEIGHT - DISPLAY_MOUSE_SIZE - 1)) + { + // + // Update the Y cursor position. + // + i32Temp += i32YDelta; + + // + // Don't let the cursor overwrite the status area of the screen. + // + if(i32Temp < DISPLAY_BANNER_HEIGHT + 1) + { + i32Temp = DISPLAY_BANNER_HEIGHT + 1; + } + } + + // + // Update the Y position. + // + g_sCursor.i16YMin = i32Temp; + g_sCursor.i16YMax = i32Temp + DISPLAY_MOUSE_SIZE; + + // + // Draw the new cursor. + // + GrContextForegroundSet(&g_sContext, DISPLAY_MOUSE_FG); + GrRectFill(&g_sContext, &g_sCursor); +} + +//***************************************************************************** +// +// This function will update the small mouse button indicators in the status +// bar area of the screen. This can be called on its own or it will be called +// whenever UpdateStatus() is called as well. +// +//***************************************************************************** +void +UpdateButtons(void) +{ + tRectangle sRect, sRectInner; + int iButton; + + // + // Initialize the button indicator position. + // + sRect.i16XMin = GrContextDpyWidthGet(&g_sContext) - 36; + sRect.i16YMin = GrContextDpyHeightGet(&g_sContext) - 18; + sRect.i16XMax = sRect.i16XMin + 6; + sRect.i16YMax = sRect.i16YMin + 8; + sRectInner.i16XMin = sRect.i16XMin + 1; + sRectInner.i16YMin = sRect.i16YMin + 1; + sRectInner.i16XMax = sRect.i16XMax - 1; + sRectInner.i16YMax = sRect.i16YMax - 1; + + // + // Check all three buttons. + // + for(iButton = 0; iButton < 3; iButton++) + { + // + // Draw the button indicator red if pressed and black if not pressed. + // + if(g_ui32Buttons & (1 << iButton)) + { + GrContextForegroundSet(&g_sContext, ClrRed); + } + else + { + GrContextForegroundSet(&g_sContext, ClrBlack); + } + + // + // Draw the back of the button indicator. + // + GrRectFill(&g_sContext, &sRectInner); + + // + // Draw the border on the button indicator. + // + GrContextForegroundSet(&g_sContext, ClrWhite); + GrRectDraw(&g_sContext, &sRect); + + // + // Move to the next button indicator position. + // + sRect.i16XMin += 8; + sRect.i16XMax += 8; + sRectInner.i16XMin += 8; + sRectInner.i16XMax += 8; + } +} + +//***************************************************************************** +// +// This function updates the status area of the screen. It uses the current +// state of the application to print the status bar. +// +//***************************************************************************** +void +UpdateStatus(char *pcString, uint32_t ui32Buttons, bool bClrBackground) +{ + tRectangle sRect; + + // + // Fill the bottom rows of the screen with blue to create the status area. + // + sRect.i16XMin = 0; + sRect.i16YMin = GrContextDpyHeightGet(&g_sContext) - + DISPLAY_BANNER_HEIGHT - 1; + sRect.i16XMax = GrContextDpyWidthGet(&g_sContext) - 1; + sRect.i16YMax = sRect.i16YMin + DISPLAY_BANNER_HEIGHT; + + // + // Were we asked to clear the background of the status area? + // + GrContextBackgroundSet(&g_sContext, DISPLAY_BANNER_BG); + + if(bClrBackground) + { + // + // Draw the background of the banner. + // + GrContextForegroundSet(&g_sContext, DISPLAY_BANNER_BG); + GrRectFill(&g_sContext, &sRect); + + // + // Put a white box around the banner. + // + GrContextForegroundSet(&g_sContext, DISPLAY_BANNER_FG); + GrRectDraw(&g_sContext, &sRect); + } + + // + // Write the current state to the left of the status area. + // + GrContextFontSet(&g_sContext, g_psFontFixed6x8); + + // + // Update the status on the screen. + // + if(pcString != 0) + { + UARTprintf(pcString); + UARTprintf("\n"); + GrStringDraw(&g_sContext, pcString, -1, 10, sRect.i16YMin + 4, 1); + + g_ui32Buttons = ui32Buttons; + } + else if(iUSBState == eStateNoDevice) + { + // + // Mouse is currently disconnected. + // + UARTprintf("no device\n"); + GrStringDraw(&g_sContext, "no device ", -1, 10, sRect.i16YMin + 4, + 1); + } + else if(iUSBState == eStateMouseConnected) + { + // + // Mouse is connected. + // + UARTprintf("connected\n"); + GrStringDraw(&g_sContext, "connected ", -1, 10, sRect.i16YMin + 4, + 1); + } + else if(iUSBState == eStateUnknownDevice) + { + // + // Some other (unknown) device is connected. + // + UARTprintf("unknown device\n"); + GrStringDraw(&g_sContext, "unknown device", -1, 10, sRect.i16YMin + 4, + 1); + } + else if(iUSBState == eStatePowerFault) + { + // + // Power fault. + // + UARTprintf("power fault\n"); + GrStringDraw(&g_sContext, "power fault ", -1, 10, sRect.i16YMin + 4, + 1); + } + + UpdateButtons(); +} + +//***************************************************************************** +// +// This is the generic callback from host stack. +// +// \param pvData is actually a pointer to a tEventInfo structure. +// +// This function will be called to inform the application when a USB event has +// occurred that is outside those related to the mouse device. At this +// point this is used to detect unsupported devices being inserted and removed. +// It is also used to inform the application when a power fault has occurred. +// This function is required when the g_USBGenericEventDriver is included in +// the host controller driver array that is passed in to the +// USBHCDRegisterDrivers() function. +// +// \return None. +// +//***************************************************************************** +void +USBHCDEvents(void *pvData) +{ + tEventInfo *psEventInfo; + + // + // Cast this pointer to its actual type. + // + psEventInfo = (tEventInfo *)pvData; + + switch(psEventInfo->ui32Event) + { + // + // New mouse detected. + // + case USB_EVENT_CONNECTED: + { + // + // See if this is a HID Keyboard. + // + if((USBHCDDevClass(psEventInfo->ui32Instance, 0) == + USB_CLASS_HID) && + (USBHCDDevProtocol(psEventInfo->ui32Instance, 0) == + USB_HID_PROTOCOL_MOUSE)) + { + // + // Indicate that the mouse has been detected. + // + UARTprintf("Mouse Connected\n"); + + // + // Proceed to the eStateMouseInit state so that the main loop + // can finish initialized the mouse since USBHMouseInit() + // cannot be called from within a callback. + // + iUSBState = eStateMouseInit; + } + + break; + } + // + // Unsupported device detected. + // + case USB_EVENT_UNKNOWN_CONNECTED: + { + UARTprintf("Unsupported Device Connected\n"); + + // + // An unknown device was detected. + // + iUSBState = eStateUnknownDevice; + + break; + } + // + // Device has been unplugged. + // + case USB_EVENT_DISCONNECTED: + { + // + // Indicate that the mouse has been disconnected. + // + UARTprintf("Device Disconnected\n"); + + // + // Change the state so that the main loop knows that the mouse is + // no longer present. + // + iUSBState = eStateNoDevice; + + // + // Reset the button state. + // + g_ui32Buttons = 0; + + break; + } + // + // Power Fault. + // + case USB_EVENT_POWER_FAULT: + { + UARTprintf("Power Fault\n"); + + // + // No power means no device is present. + // + iUSBState = eStatePowerFault; + + break; + } + default: + { + break; + } + } +} + +//***************************************************************************** +// +// This is the callback from the USB HID mouse handler. +// +// \param pvCBData is ignored by this function. +// \param ui32Event is one of the valid events for a mouse device. +// \param ui32MsgParam is defined by the event that occurs. +// \param pvMsgData is a pointer to data that is defined by the event that +// occurs. +// +// This function will be called to inform the application when a mouse has +// been plugged in or removed and any time mouse movement or button pressed +// is detected. +// +// \return None. +// +//***************************************************************************** +void +MouseCallback(tUSBHMouse *psMsInstance, uint32_t ui32Event, + uint32_t ui32MsgParam, void *pvMsgData) +{ + switch(ui32Event) + { + // + // Mouse button press detected. + // + case USBH_EVENT_HID_MS_PRESS: + { + UARTprintf("Button Pressed %02x\n", ui32MsgParam); + + // + // Save the new button that was pressed. + // + g_ui32Buttons |= ui32MsgParam; + + break; + } + + // + // Mouse button release detected. + // + case USBH_EVENT_HID_MS_REL: + { + UARTprintf("Button Released %02x\n", ui32MsgParam); + + // + // Remove the button from the pressed state. + // + g_ui32Buttons &= ~ui32MsgParam; + + break; + } + + // + // Mouse X movement detected. + // + case USBH_EVENT_HID_MS_X: + { + UARTprintf("X:%02d.\n", (signed char)ui32MsgParam); + + // + // Update the cursor on the screen. + // + UpdateCursor((signed char)ui32MsgParam, 0); + + break; + } + + // + // Mouse Y movement detected. + // + case USBH_EVENT_HID_MS_Y: + { + UARTprintf("Y:%02d.\n", (signed char)ui32MsgParam); + + // + // Update the cursor on the screen. + // + UpdateCursor(0, (signed char)ui32MsgParam); + + break; + } + } + + // + // Update the status area of the screen. + // + UpdateStatus(0, 0, false); +} + +//***************************************************************************** +// +// Initialize the host mode stack. +// +//***************************************************************************** +void +HostInit(void) +{ + // + // Register the host class drivers. + // + USBHCDRegisterDrivers(0, g_ppHostClassDrivers, g_ui32NumHostClassDrivers); + + // + // Initialize the button states. + // + g_ui32Buttons = 0; + + // + // Update the status on the screen. + // + UpdateStatus(0, 0, true); + + // + // Open an instance of the mouse driver. The mouse does not need + // to be present at this time, this just saves a place for it and allows + // the applications to be notified when a mouse is present. + // + g_psMouseInstance = + USBHMouseOpen(MouseCallback, g_pui8Buffer, MOUSE_MEMORY_SIZE); + + // + // Initialize the power configuration. This sets the power enable signal + // to be active high and does not enable the power fault. + // + USBHCDPowerConfigInit(0, USBHCD_VBUS_AUTO_HIGH | USBHCD_VBUS_FILTER); + + // + // Call the main loop for the Host controller driver. + // + iUSBState = eStateNoDevice; +} + +//***************************************************************************** +// +// This is the main loop that runs the application. +// +//***************************************************************************** +void +HostMain(void) +{ + switch(iUSBState) + { + // + // This state is entered when the mouse is first detected. + // + case eStateMouseInit: + { + // + // Initialize the newly connected mouse. + // + USBHMouseInit(g_psMouseInstance); + + // + // Proceed to the mouse connected state. + // + iUSBState = eStateMouseConnected; + + // + // Update the status on the screen. + // + UpdateStatus(0, 0, true); + + // + // Update the cursor on the screen. + // + UpdateCursor(GrContextDpyWidthGet(&g_sContext) / 2, + GrContextDpyHeightGet(&g_sContext)/ 2); + + break; + } + case eStateMouseConnected: + { + // + // Nothing is currently done in the main loop when the mouse + // is connected. + // + break; + } + case eStateNoDevice: + { + // + // The mouse is not connected so nothing needs to be done here. + // + break; + } + default: + { + break; + } + } + + // + // Periodically call the main loop for the Host controller driver. + // + USBHCDMain(); +} -- cgit v1.3.1