// TITLE: USB HID Mouse device class driver
#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_types.h"
extern "C"{
#include "debug.h"
}
#include "usb.h"
#include "usblib.h"
#include "usblibpriv.h"
#include "usbdevice.h"
//#include "usbdhid.h"
#include "usbdhidmouse.h"
// report descriptor
static const uint8_t ReportDesc[] = {
0x05,1, // UsagePage(GENERIC_DESKTOP)
0x09,2, // Usage(MOUSE),
0xA1,1, // Collection(APPLICATION)
0x09,1, // Usage(POINTER)
0xA1,0, // Collection(Physical)
// buttons
0x05,9, // UsagePage(BUTTONS)
0x19,1, // UsageMinimum(1)
0x29,3, // UsageMaximum(3)
0x15,0, // LogicalMinimum(0)
0x25,1, // LogicalMaximum(1)
0x75,1, // ReportSize(1)
0x95,3, // ReportCount(3)
0x81,2, // Input(VAR,ABS)
0x75,5, // ReportSize(5)
0x95,1, // ReportCount(1)
0x81,3, // Input(CONST|ARY|ABS)
// X and Y axis
0x05,1, // UsagePage(GENERIC_DESKTOP)
0x09,0x30, // Usage(X),
0x09,0x31, // Usage(Y),
0x15,(uint8_t)-127, // LogicalMinimum(-127)
0x25,127, // LogicalMaximum(127)
0x75,8, // ReportSize(8)
0x95,2, // ReportCount(2)
0x81,6, // Input(DATA|VAR|REL)
0xC0, // EndCollection
0xC0, // EndCollection
};
// Device Descriptor
static const uint8_t DeviceDesc[] = {
18, // Size of this structure.
1, // Type of this structure = DTYPE_DEVICE
USB2(0x110), // USB version 1.1
0, // USB Device Class
0, // USB Device Sub-class
0, // USB Device protocol
64, // Maximum packet size for default pipe.
USB2(0x1CBE), // Vendor ID = Texas Instruments
USB2(0), // Product ID = TI Mouse
USB2(0x100), // Device Version BCD.
1, // Manufacturer string identifier.
2, // Product string identifier.
0, // Product serial number.
1, // Number of configurations.
};
// configuration descriptor.
static const uint8_t ConfigDesc[] = {
9, // bLength
2, // USB_DTYPE_CONFIGURATION
USB2(9+9+9+7), // The total size of this full structure.
1, // bNumInterfaces
1, // bConfigurationValue
0, // iConfiguration
0xC0, // Bus Powered, Self Powered, remote wake up.
50, // The maximum power in 2mA increments.
// Interface Descriptor.
9, // Size of the interface descriptor.
4, //USB_DTYPE_INTERFACE, // Type of this descriptor.
0, // The index for this interface.
0, // The alternate setting for this interface.
1, // The number of endpoints used by this interface.
3, // USB_CLASS_HID, // interface class
0, // interface sub-class.
0, // interface protocol for the sub-class specified above.
0, // The string index for this interface.
// HID descriptor
9, // bLength
0x21, // bDescriptorType = DTYPE_HID
USB2(0x111), // bcdHID (version 1.11 compliant)
0, // bCountryCode (not localized)
1, // bNumDescriptors
0x22, // Report descriptor = DTYPE_REPORT
USB2(sizeof ReportDesc), // Size of report descriptor
// Interrupt IN endpoint descriptor
7, // The size of the endpoint descriptor.
5, //USB_DTYPE_ENDPOINT, // Descriptor type is an endpoint.
0x81, // EP1IN
0x03, // Endpoint is an interrupt endpoint.
USB2(64), // The maximum packet size.
16, // The polling interval for this endpoint.
};
//*****************************************************************************
// Main HID device class event handler function.
//
// \param pvMouseDevice is the event callback pointer provided during
// USBDHIDInit(). This is a pointer to our HID device structure
// (&g_sHIDMouseDevice).
// \param ui32Event identifies the event we are being called back for.
// \param ui32MsgData is an event-specific value.
// \param pvMsgData is an event-specific pointer.
//
// This function is called by the HID device class driver to inform the
// application of particular asynchronous events related to operation of the
// mouse HID device.
//
// \return Returns a value which is event-specific.
//
//*****************************************************************************
uint32_t tUSBDHIDMouseDevice::RxCallback(uint32_t ev, uint32_t data, void *ptr) {
// Which event were we sent?
switch(ev) {
// The host has connected to us and configured the device.
case USB_EVENT_CONNECTED: {
Configured = true;
// Pass the information on to the client.
// psMouseDevice->pfnCallback(psMouseDevice->pvCBData,USB_EVENT_CONNECTED, 0, 0);
}break;
// The host has disconnected from us.
case USB_EVENT_DISCONNECTED: {
Configured = false;
// Pass the information on to the client.
// psMouseDevice->pfnCallback(psMouseDevice->pvCBData,USB_EVENT_DISCONNECTED, 0, 0);
}break;
// The host is polling us for a particular report and the HID driver
// is asking for the latest version to transmit.
case USBD_HID_EVENT_IDLE_TIMEOUT:
case USBD_HID_EVENT_GET_REPORT: {
// We only support a single input report so we don't need to check
// the ui32MsgValue parameter in this case. Set the report pointer
// in *pvMsgData and return the length of the report in bytes.
*(uint8_t **)ptr = pui8Report;
}return 8;
// This event is sent in response to a host Set_Report request. The
// mouse device has no output reports so we return a NULL pointer and
// zero length to cause this request to be stalled.
case USBD_HID_EVENT_GET_REPORT_BUFFER: {
// We are being asked for a report that does not exist for
// this device. Return 0 to indicate that we are not providing
// a buffer.
}return 0;
case USB_EVENT_TX_COMPLETE: { // Our last transmission is complete.
iMouseState = eHIDMouseStateIdle;
}break;
}
return tUSBDHIDDevice::RxCallback(ev,data,ptr); // chain handlers
}
//*****************************************************************************
//
//! Initializes HID mouse device operation for a given USB controller.
//!
//! \param ui32Index is the index of the USB controller which is to be
//! initialized for HID mouse device operation.
//! \param psMouseDevice points to a structure containing parameters
//! customizing the operation of the HID mouse device.
//!
//! An application wishing to offer a USB HID mouse interface to a USB host
//! must call this function to initialize the USB controller and attach the
//! mouse device to the USB bus. This function performs all required USB
//! initialization.
//!
//! On successful completion, this function returns the \e psMouseDevice
//! pointer passed to it. This must be passed on all future calls to the HID
//! mouse device driver.
//!
//! When a host connects and configures the device, the application callback
//! receives \b USB_EVENT_CONNECTED after which calls can be made to
//! USBDHIDMouseStateChange() to report pointer movement and button presses
//! to the host.
//!
//! \note The application must not make any calls to the lower level USB device
//! interfaces if interacting with USB via the USB HID mouse device API.
//! Doing so causes unpredictable (though almost certainly unpleasant)
//! behavior.
//!
//! \return Returns NULL on failure or the psMouseDevice pointer on success.
//
//*****************************************************************************
void * tUSBDHIDMouseDevice::Init() {
// Check parameter validity.
ASSERT(ppui8StringDescriptors);
Configured = false;
// sReportIdle.ui8Duration4mS = 0;
// sReportIdle.ui8ReportID = 0;
// sReportIdle.ui32TimeSinceReportmS = 0;
// sReportIdle.ui16TimeTillNextmS = 0;
iMouseState = eHIDMouseStateUnconfigured;
// Initialize the HID device class instance structure based on input from the caller.
// psReportIdle = &sReportIdle;
desc.device = DeviceDesc;
desc.config = ConfigDesc;
desc.hid = ConfigDesc + 9+9;
desc.hidrep = ReportDesc;
// Initialize the lower layer HID driver and pass it the various structures
// and descriptors necessary to declare that we are a keyboard.
// tConfigDescriptor *pConfigDesc = (tConfigDescriptor *)ConfigDesc;
// pConfigDesc->bmAttributes = psMouseDevice->ui8PwrAttributes;
// pConfigDesc->bMaxPower = (uint8_t)(psMouseDevice->ui16MaxPowermA / 2);
// If we initialized the HID layer successfully, pass our device pointer
// back as the return code, otherwise return NULL to indicate an error.
return tUSBDHIDDevice::Init();
}
//*****************************************************************************
//
//! Shuts down the HID mouse device.
//!
//! \param pvMouseDevice is the pointer to the device instance structure.
//!
//! This function terminates HID mouse operation for the instance supplied
//! and removes the device from the USB bus. Following this call, the
//! \e pvMouseDevice instance may not me used in any other call to the HID
//! mouse device other than USBDHIDMouseInit().
//!
//! \return None.
//
//*****************************************************************************
void tUSBDHIDMouseDevice::Term() {
// Terminate the low level HID driver.
tUSBDHIDDevice::Term();
Configured = false;
}
//*****************************************************************************
//
//! Reports a mouse state change, pointer movement or button press, to the USB
//! host.
//!
//! \param pvMouseDevice is the pointer to the mouse device instance structure.
//! \param i8DeltaX is the relative horizontal pointer movement that the
//! application wishes to report. Valid values are in the range [-127, 127]
//! with positive values indicating movement to the right.
//! \param i8DeltaY is the relative vertical pointer movement that the
//! application wishes to report. Valid values are in the range [-127, 127]
//! with positive values indicating downward movement.
//! \param ui8Buttons is a bit mask indicating which (if any) of the three
//! mouse buttons is pressed. Valid values are logical OR combinations of
//! \b MOUSE_REPORT_BUTTON_1, \b MOUSE_REPORT_BUTTON_2 and
//! \b MOUSE_REPORT_BUTTON_3.
//!
//! This function is called to report changes in the mouse state to the USB
//! host. These changes can be movement of the pointer, reported relative to
//! its previous position, or changes in the states of up to 3 buttons that
//! the mouse may support. The return code indicates whether or not the
//! mouse report could be sent to the host. In cases where a previous
//! report is still being transmitted, \b MOUSE_ERR_TX_ERROR is returned
//! and the state change is ignored.
//!
//! \return Returns \b MOUSE_SUCCESS on success, \b MOUSE_ERR_TX_ERROR if an
//! error occurred while attempting to schedule transmission of the mouse
//! report to the host (typically due to a previous report which has not yet
//! completed transmission or due to disconnection of the host) or \b
//! MOUSE_ERR_NOT_CONFIGURED if called before a host has connected to and
//! configured the device.
//
//*****************************************************************************
uint32_t tUSBDHIDMouseDevice::StateChange(int8_t i8DeltaX, int8_t i8DeltaY, uint8_t ui8Buttons) {
// Get a pointer to the HID device data.
pui8Report[0] = ui8Buttons;
pui8Report[1] = (uint8_t)i8DeltaX;
pui8Report[2] = (uint8_t)i8DeltaY;
// If we are not configured, return an error here before trying to send anything.
if (!Configured) return MOUSE_ERR_NOT_CONFIGURED;
// Only send a report if the transmitter is currently free.
if (TxPacketAvailable()) {
// Send the report to the host.
iMouseState = eHIDMouseStateSend;
uint32_t ui32Count = ReportWrite(pui8Report, 3,true);
// Did we schedule a packet for transmission correctly?
if (!ui32Count) return MOUSE_ERR_TX_ERROR; // No - report the error to the caller.
return MOUSE_SUCCESS;
}
return MOUSE_ERR_TX_ERROR;
}
Vorgefundene Kodierung: ASCII (7 bit) | 2
|