I am faced with the task of implementing communication between a Tiva 4C129 microcontroller and TI's DLPC900 over USB (1.1).
I know close to nothing about the USB standard, and will probably have to learn a lot. However, at the moment I am stuck at a point where I think I may be helped without complete RTFMing. I know the Tiva should be host, and that the DLP is an HID (interface subclass 0, interface protocol 0, id vendor 0x451, id product 0xc900)
As a starting point, I am using TivaWare_C_Series-2.1.0.12573\examples\boards\ek-tm4c1294xl\usb_host_mouse\usb_host_mouse.c
I was hoping that if I changed
g_psMouse = USBHMouseOpen(MouseCallback, 0, 0);
into something like
g_psDLP = USBHHIDOpen(eUSBHHIDClassVendor, DLPCallback, (void *)g_psDLP);
Then the DLPCallback will at least fire. However, it does not. The only thing firing upon connecting/disconnecting the USB cable is USBHCDEvents, (with instance 0).
Any suggestions?
I am attaching my complete source for reference.
//*****************************************************************************
//
// usb_host_mouse.c - An example using that supports a mouse.
//
// 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 EK-TM4C1294XL Firmware Package.
//
//*****************************************************************************
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.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 "drivers/pinout.h"
#include "utils/uartstdio.h"
//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>USB Host mouse example(usb_host_mouse)</h1>
//!
//! This example application demonstrates how to support a USB mouse using
//! the EK-TM4C129X evaluation kit. This application supports only a
//! standard mouse HID device.
//!
//! UART0, connected to the Virtual Serial Port and running at 115,200, 8-N-1,
//! is used to display messages from this application.
//!
//!
//
//*****************************************************************************
//*****************************************************************************
//
// The size of the host controller's memory pool in bytes.
//
//*****************************************************************************
#define HCD_MEMORY_SIZE 128
//*****************************************************************************
//
// Structure to hold the status of the attached mouse.
//
//*****************************************************************************
typedef struct
{
//
// Holds if there is a device connected to this port.
//
bool bConnected;
//
// Holds if the mouse state has been updated.
//
bool bUpdate;
//
// The instance data for the device if bConnected is true.
//
uint32_t ui32Instance;
//
// The mouse button state.
//
uint32_t ui32Buttons;
//
// The mouse X position.
//
int32_t i32XPos;
//
// The mouse Y position.
//
int32_t i32YPos;
}
tMouseStatus;
//*****************************************************************************
//
// The global application status structure.
//
//*****************************************************************************
tMouseStatus g_sStatus;
//*****************************************************************************
//
// The memory pool to provide to the Host controller driver.
//
//*****************************************************************************
uint8_t g_pui8HCDPool[HCD_MEMORY_SIZE * MAX_USB_DEVICES];
//*****************************************************************************
//
// 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 HID 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_psMouse;
static tHIDInstance *g_psDLP;
// some buf
#define DLPBUFSIZE 100
uint8_t DLPbuf[DLPBUFSIZE];
//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif
//*****************************************************************************
//
// 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,
}
g_iMouseState;
//*****************************************************************************
//
// This is the callback from the USB HID mouse handler.
//
// pvCBData is ignored by this function.
// ui32Event is one of the valid events for a mouse device.
// ui32MsgParam is defined by the event that occurs.
// 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 a mouse movement or button pressed
// has occurred.
//
// This function will return 0.
//
//*****************************************************************************
void
MouseCallback(tUSBHMouse *psMouse, uint32_t ui32Event, uint32_t ui32MsgParam,
void *pvMsgData)
{
//
// Start with the assumption that the data on the serial port will need
// updating.
//
g_sStatus.bUpdate = true;
switch(ui32Event)
{
//
// New mouse detected.
//
case USB_EVENT_CONNECTED:
{
//
// Proceed to the eStateMouseInit state so that the main loop
// can finish initializing the mouse since USBHMouseInit() cannot
// be called from within a callback.
//
g_iMouseState = eStateMouseInit;
//
// Indicate that the mouse has been detected.
//
UARTprintf("\nMouse Connected\n");
break;
}
//
// Mouse has been unplugged.
//
case USB_EVENT_DISCONNECTED:
{
//
// Change the state so that the main loop knows that a device is no
// longer present.
//
g_iMouseState = eStateNoDevice;
//
// Need to clear out any held buttons.
//
g_sStatus.ui32Buttons = 0;
//
// Indicate that the device was disconnected.
//
UARTprintf("\nMouse disconnected\n");
//
// There shouldn't be any updates from a disconnected mouse.
//
g_sStatus.bUpdate = false;
break;
}
//
// New button press detected.
//
case USBH_EVENT_HID_MS_PRESS:
{
//
// Save the new button that was pressed.
//
g_sStatus.ui32Buttons |= ui32MsgParam;
break;
}
//
// A button was released on a HID mouse.
//
case USBH_EVENT_HID_MS_REL:
{
//
// Remove the button from the pressed state.
//
g_sStatus.ui32Buttons &= ~ui32MsgParam;
break;
}
//
// The HID mouse detected movement in the X direction.
//
case USBH_EVENT_HID_MS_X:
{
//
// Update the cursor X position.
//
g_sStatus.i32XPos += (int8_t) ui32MsgParam;
break;
}
//
// The HID mouse detected movement in the Y direction.
//
case USBH_EVENT_HID_MS_Y:
{
//
// Update the cursor Y position.
//
g_sStatus.i32YPos += (int8_t) ui32MsgParam;
break;
}
default:
{
//
// This was an event that we don't recognize, so there is no reason
// to update the UART output.
//
g_sStatus.bUpdate = false;
break;
}
}
//
// If we have an update for the UART, send it now.
//
if(g_sStatus.bUpdate == true)
{
//
// Print an update to the UART showing the current mouse position and
// the state of all three buttons.
//
UARTprintf("\rPos: %d, %d Buttons: %d%d%d ",
g_sStatus.i32XPos, g_sStatus.i32YPos,
g_sStatus.ui32Buttons & 1,
(g_sStatus.ui32Buttons & 2) >> 1,
(g_sStatus.ui32Buttons & 4) >> 2);
}
}
// this is analogous to USBHMouseInit()
// atm we are using a generic HID instance struct/pointer - TODO implement a DLPInstance struct akin to Mouse struct
uint32_t
USBHDLPInit(tHIDInstance *psDLPInstance)
{
UARTprintf("USBHDLPInit()\n");
//
// Set the initial rate to only update on mouse state changes.
//
USBHHIDSetIdle(psDLPInstance, 0, 0);
//
// Read out the Report Descriptor from the mouse and parse it for
// the format of the reports coming back from the mouse.
//
USBHHIDGetReportDescriptor(psDLPInstance,
DLPbuf,
DLPBUFSIZE);
//
// Set the DLP to boot protocol.
//
USBHHIDSetProtocol(psDLPInstance, 0);
return(0);
}
uint32_t
DLPCallback(void *vp, uint32_t ui32Event, uint32_t ui32MsgParam,
void *pvMsgData)
{
UARTprintf("DLPCallback()\n");
if (ui32Event == USB_EVENT_CONNECTED)
{
UARTprintf("Connected\n");
USBHDLPInit(g_psDLP);
}
else if (ui32Event == USB_EVENT_DISCONNECTED)
{
UARTprintf("Disconnected\n");
}
return 0;
}
//*****************************************************************************
//
// The main routine for handling the USB mouse.
//
//*****************************************************************************
void
MouseMain(void)
{
switch(g_iMouseState)
{
//
// This state is entered when they mouse is first detected.
//
case eStateMouseInit:
{
//
// Initialized the newly connected mouse.
//
USBHMouseInit(g_psMouse);
//
// Proceed to the mouse connected state.
//
g_iMouseState = eStateMouseConnected;
break;
}
case eStateMouseConnected:
{
//
// Nothing is currently done on mouse connect.
//
break;
}
default:
{
break;
}
}
}
//*****************************************************************************
//
// This is the generic callback from host stack.
//
// 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.
//
//*****************************************************************************
void
USBHCDEvents(void *pvData)
{
tEventInfo *pEventInfo;
//
// Cast this pointer to its actual type.
//
pEventInfo = (tEventInfo *)pvData;
UARTprintf("event: %d, inst: %d\n", pEventInfo->ui32Event, pEventInfo->ui32Instance);
switch(pEventInfo->ui32Event)
{
case USB_EVENT_UNKNOWN_CONNECTED:
case USB_EVENT_CONNECTED:
{
//
// Save the device instance data.
//
g_sStatus.ui32Instance = pEventInfo->ui32Instance;
g_sStatus.bConnected = true;
UARTprintf("connected\n");
break;
}
//
// A device has been unplugged.
//
case USB_EVENT_DISCONNECTED:
{
//
// Device is no longer connected.
//
g_sStatus.bConnected = false;
UARTprintf("disconnected\n");
break;
}
default:
{
break;
}
}
}
//*****************************************************************************
//
// The main application loop.
//
//*****************************************************************************
int
main(void)
{
uint32_t ui32SysClock, ui32PLLRate;
//
// Set the application to run at 120 MHz with a PLL frequency of 480 MHz.
//
ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);
//
// Set the part pin out appropriately for this device.
//
PinoutSet(false, true);
//
// Configure UART0 for 115,200 baud serial data output.
//
UARTStdioConfig(0, 115200, ui32SysClock);
//
// Print a welcome message
//
UARTprintf("\033[2J\033[H");
UARTprintf("USB Host Mouse Example\n");
UARTprintf("Waiting for device....\n");
//
// Save the PLL rate used by this application.
//
ui32PLLRate = 480000000;
//
// Initialize the connection status.
//
g_sStatus.bConnected = false;
g_sStatus.ui32Buttons = 0;
//
// Enable Clocking to the USB controller.
//
ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
//
// Enable Interrupts
//
ROM_IntMasterEnable();
//
// Initialize the USB stack mode and pass in a mode callback.
//
USBStackModeSet(0, eUSBModeHost, 0);
//
// Register the host class drivers.
//
USBHCDRegisterDrivers(0, g_ppHostClassDrivers, g_ui32NumHostClassDrivers);
//
// Open an instance of the mouse driver. The mouse does not need
// to be present at this time, this just save a place for it and allows
// the applications to be notified when a mouse is present.
//
//g_psMouse = USBHMouseOpen(MouseCallback, 0, 0);
g_psDLP = USBHHIDOpen(eUSBHHIDClassVendor, DLPCallback, (void *)g_psDLP);
if (g_psDLP == 0)
{
UARTprintf("USBHHIDOpen error!\n");
}
//
// 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);
//
// Tell the USB library the CPU clock and the PLL frequency. This is a
// new requirement for TM4C129 devices.
//
USBHCDFeatureSet(0, USBLIB_FEATURE_CPUCLK, &ui32SysClock);
USBHCDFeatureSet(0, USBLIB_FEATURE_USBPLL, &ui32PLLRate);
//
// Initialize the USB controller for Host mode.
//
USBHCDInit(0, g_pui8HCDPool, sizeof(g_pui8HCDPool));
//
// The main loop for the application.
//
while(1)
{
//
// Call the USB library to let non-interrupt code run.
//
USBHCDMain();
//
// Call the mouse and mass storage main routines.
//
//MouseMain();
}
}