⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mouse_driver.c

📁 最新版IAR FOR ARM(EWARM)5.11中的代码例子
💻 C
字号:
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support  -  ROUSSET  -
 * ----------------------------------------------------------------------------
 * Copyright (c) 2006, Atmel Corporation

 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the disclaiimer below.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the disclaimer below in the documentation and/or
 * other materials provided with the distribution.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * ----------------------------------------------------------------------------
 */

/*
$Id: mouse_driver.c,v 1.1.2.1 2006/12/05 08:33:25 danielru Exp $
*/

//------------------------------------------------------------------------------
//      Includes
//------------------------------------------------------------------------------

#include "core/common.h"
#include "core/device.h"
#include "core/board.h"
#include "core/trace.h"
#include "core/usb.h"
#include "core/standard.h"
#include "hid.h"
#include "mouse_driver.h"

//------------------------------------------------------------------------------
//      Global variables
//------------------------------------------------------------------------------

// Descriptors
//------------------------------------------------------------------------------
//! \brief  Report descriptor for a 3-buttons mouse
#pragma data_alignment=4
static const unsigned char pReport[] = {

    HID_GLOBAL_USAGE_PAGE + 1, HID_USAGE_PAGE_GENERIC_DESKTOP,
    HID_LOCAL_USAGE + 1, HID_USAGE_MOUSE,
    HID_MAIN_COLLECTION + 1, HID_COLLECTION_APPLICATION,
        HID_LOCAL_USAGE + 1, HID_USAGE_POINTER,
        HID_MAIN_COLLECTION + 1, HID_COLLECTION_PHYSICAL,
              HID_GLOBAL_USAGE_PAGE + 1, HID_USAGE_PAGE_BUTTON,
              HID_LOCAL_USAGE_MINIMUM + 1, 1,
              HID_LOCAL_USAGE_MAXIMUM + 1, 3,
              HID_GLOBAL_LOGICAL_MINIMUM + 1, 0,
              HID_GLOBAL_LOGICAL_MAXIMUM + 1, 1,
              HID_GLOBAL_REPORT_COUNT + 1, 3,
              HID_GLOBAL_REPORT_SIZE + 1, 1,
              HID_MAIN_INPUT + 1, HID_VARIABLE,  // 3 button bits
              HID_GLOBAL_REPORT_COUNT + 1, 1,
              HID_GLOBAL_REPORT_SIZE + 1, 5,
              HID_MAIN_INPUT + 1, HID_CONSTANT,  // 5 bit padding
              HID_GLOBAL_USAGE_PAGE + 1, HID_USAGE_PAGE_GENERIC_DESKTOP,
              HID_LOCAL_USAGE + 1, HID_USAGE_X,
              HID_LOCAL_USAGE + 1, HID_USAGE_Y,
              HID_GLOBAL_LOGICAL_MINIMUM + 1, (unsigned char) -127,
              HID_GLOBAL_LOGICAL_MAXIMUM + 1, 127,
              HID_GLOBAL_REPORT_SIZE + 1, 8,
              HID_GLOBAL_REPORT_COUNT + 1, 2,
              HID_MAIN_INPUT + 1, HID_VARIABLE | HID_RELATIVE,
        HID_MAIN_ENDCOLLECTION,
    HID_MAIN_ENDCOLLECTION
};

//! \brief  Standard USB device descriptor
//! \see    S_usb_device_descriptor
static const S_usb_device_descriptor sDevice = {

    sizeof(S_usb_device_descriptor), // Size of this descriptor in bytes (18)
    USB_DEVICE_DESCRIPTOR,           // DEVICE Descriptor Type
    USB2_00,                         // USB 2.0 specification
    USB_CLASS_DEVICE,                // Class is specified in the interface descriptor.
    0x00,                            // No device subclass code
    0x00,                            // No device protocol code
    USB_ENDPOINT0_MAXPACKETSIZE,     // Maximum packet size for endpoint zero
    USB_VENDOR_ATMEL,                // ATMEL Vendor ID
    MSE_PRODUCT_ID,                  // Product ID (6200h)
    0x0001,                          // Device release number 0.01
    0x01,                            // Index of manufacturer description
    0x02,                            // Index of product description
    0x03,                            // Index of serial number description
    0x01                             // One possible configuration
};

//! \brief  Device configuration descriptor
//! \see    S_mse_configuration_descriptor
static const S_mse_configuration_descriptor sConfiguration = {

    // Standard configuration descriptor
    {
        sizeof(S_usb_configuration_descriptor), // Size of this descriptor in bytes (9)
        USB_CONFIGURATION_DESCRIPTOR,           // CONFIGURATION descriptor type
        sizeof(S_mse_configuration_descriptor), // Total length of data returned for this configuration
        0x01,                                   // One interface is used by this configuration
        0x01,                                   // Value 0x01 is used to select this configuration
        0x00,                                   // No string is used to describe this configuration
        USB_CONFIG_SELF_NOWAKEUP,               // Device is self-powered and does not support remote wakeup
        USB_POWER_MA(100)                       // maximum power consumption in mA
    },
    // First Interface Descriptor
    {
        sizeof(S_usb_interface_descriptor), // Size of this descriptor in bytes (9)
        USB_INTERFACE_DESCRIPTOR,           // INTERFACE Descriptor Type
        0x00,                               // Interface 0
        0x00,                               // No alternate settings
        1,                                  // One endpoint used
        USB_CLASS_HID,                      // Class HID (Human Interface Device)
        HID_BOOT_INTERFACE_SUBCLASS,        // Boot Interface subclass
        HID_PROTOCOL_CODE_MOUSE,            // Interface Protocol Mouse
        0x00                                // No associated string descriptor
    },
    // HID-Specific Descriptor
    {
        sizeof(S_hid_descriptor), // Size of this descriptor in bytes (9)
        HID_DESCRIPTOR,           // HID descriptor type
        HID_1_11,                 // HID Class Specification 0x101
        0x00,                     // CountryCode
        0x01,                     // 1 HID class descriptor
        HID_REPORT_DESCRIPTOR,    // Report descriptor type
        sizeof(pReport)           // Total length of Report descriptor
    },
    // Endpoint Descriptor
    {
        sizeof(S_usb_endpoint_descriptor),  // Size of this descriptor in bytes
        USB_ENDPOINT_DESCRIPTOR,            // ENDPOINT descriptor type
        MSE_INTERRUPT_IN | USB_ENDPOINT_IN, // Endpoint number 01h, direction IN
        ENDPOINT_TYPE_INTERRUPT,            // Interrupt endpoint
        MSE_REPORT_SIZE,                    // Maximum packet size is 3 bytes
        10                                  // Interval for polling: 10ms
    }
};

//! \brief  Language ID string descriptor
static const S_usb_language_id sLanguageID = {

    USB_STRING_DESCRIPTOR_SIZE(1),
    USB_STRING_DESCRIPTOR,
    USB_LANGUAGE_ENGLISH_US
};

//! \brief  Manufacturer string descriptor
static const char pManufacturer[] = {

    USB_STRING_DESCRIPTOR_SIZE(5),
    USB_STRING_DESCRIPTOR,
    USB_UNICODE('A'),
    USB_UNICODE('T'),
    USB_UNICODE('M'),
    USB_UNICODE('E'),
    USB_UNICODE('L')
};

//! \brief  Product string descriptor
static const char pProduct[] = {

    USB_STRING_DESCRIPTOR_SIZE(20),
    USB_STRING_DESCRIPTOR,
    USB_UNICODE('A'),
    USB_UNICODE('T'),
    USB_UNICODE('M'),
    USB_UNICODE('E'),
    USB_UNICODE('L'),
    USB_UNICODE(' '),
    USB_UNICODE('A'),
    USB_UNICODE('T'),
    USB_UNICODE('9'),
    USB_UNICODE('1'),
    USB_UNICODE(' '),
    USB_UNICODE('H'),
    USB_UNICODE('I'),
    USB_UNICODE('D'),
    USB_UNICODE(' '),
    USB_UNICODE('M'),
    USB_UNICODE('O'),
    USB_UNICODE('U'),
    USB_UNICODE('S'),
    USB_UNICODE('E'),
};

//! \brief  Serial number string descriptor
static const char pSerialNumber[] = {

    USB_STRING_DESCRIPTOR_SIZE(12),
    USB_STRING_DESCRIPTOR,
    USB_UNICODE('0'),
    USB_UNICODE('1'),
    USB_UNICODE('2'),
    USB_UNICODE('3'),
    USB_UNICODE('4'),
    USB_UNICODE('5'),
    USB_UNICODE('6'),
    USB_UNICODE('7'),
    USB_UNICODE('8'),
    USB_UNICODE('9'),
    USB_UNICODE('A'),
    USB_UNICODE('F')
};

//! \brief  List of string descriptors
static const char *pStrings[] = {

    (char *) &sLanguageID,
    pManufacturer,
    pProduct,
    pSerialNumber
};

//! \brief  List of endpoint descriptors
static const S_usb_endpoint_descriptor *pEndpoints[] = {

    &(sConfiguration.sInterruptIn)
};

//! \brief  Standard descriptors list
static const S_std_descriptors sDescriptors = {

    &sDevice,
    (S_usb_configuration_descriptor *) &sConfiguration,
    pStrings,
    pEndpoints
};

//------------------------------------------------------------------------------
//      Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//! \brief  Handles standard and class-specific SETUP requests.
//!
//! \param  pMse Pointer to a S_mse instance
//! \see    S_mse
//------------------------------------------------------------------------------
void MSE_RequestHandler(S_mse *pMse)
{
    const S_usb   *pUsb = pMse->sClass.pUsb;
    S_usb_request *pSetup = USB_GetSetup(pUsb);

    TRACE_DEBUG_M("NewReq ");

    // Handle request
    switch (pSetup->bRequest) {
    //----------------------
    case USB_GET_DESCRIPTOR:
    //----------------------
        // Identify requested descriptor
        switch (HBYTE(pSetup->wValue)) {
        //-------------------------
        case HID_REPORT_DESCRIPTOR:
        //-------------------------
            // Send report descriptor
            TRACE_DEBUG_M("Report ");
            USB_Write(pUsb,
                      0,
                      pReport,
                      min(sizeof(pReport), pSetup->wLength),
                      0,
                      0);
            break;

        //------------------
        case HID_DESCRIPTOR:
        //------------------
            // Send HID descriptor
            TRACE_DEBUG_M("HID ");

            USB_Write(pUsb,
                      0,
                      (void *) &sConfiguration.sHID,
                      min(sizeof(S_hid_descriptor), pSetup->wLength),
                      0,
                      0);
            break;

        //------
        default:
        //------
            // Forward request to standard handler
            STD_RequestHandler(&(pMse->sClass));
            break;
        }
        break;

    //--------------------
    case HID_GET_PROTOCOL:
    //--------------------
        // Return the protocol currently in use
        TRACE_DEBUG_M("gProtocol ");
        USB_Write(pUsb,
                  0,
                  &(pMse->bProtocol),
                  1,
                  0,
                  0);
        break;

    //--------------------
    case HID_SET_PROTOCOL:
    //--------------------
        // Set new protocol value
        TRACE_DEBUG_M("SetProtocol ");

        pMse->bProtocol = (unsigned char) pSetup->wValue;
        USB_SendZLP0(pUsb, 0, 0);
    break;

    //----------------
    case HID_GET_IDLE:
    //----------------
        // Return current Idle rate
        TRACE_DEBUG_M("gIdle ");

        USB_Write(pUsb, 0, &(pMse->bIdleRate), 1, 0, 0);
        break;

    //----------------
    case HID_SET_IDLE:
    //----------------
        // Get new Idle rate
        pMse->bIdleRate = HBYTE(pSetup->wValue);
        TRACE_DEBUG_M("sIdle(%d) ", pMse->bIdleRate);

        USB_SendZLP0(pUsb, 0, 0);
        break;

    //------------------
    case HID_GET_REPORT:
    //------------------
        // Send the current report to the host
        TRACE_DEBUG_M("gReport ");

        // Check report type
        if (HBYTE(pSetup->wValue) == HID_INPUT_REPORT) {

            // Send report
            TRACE_DEBUG_M("Input ");
            USB_Write(pUsb, 0, &(pMse->sReport), MSE_REPORT_SIZE, 0, 0);
        }
        else {

            // STALL endpoint
            USB_Stall(pUsb, 0);
        }
        break;

    //------
    default:
    //------
        // Forward request to standard handler
        STD_RequestHandler(&(pMse->sClass));
    }
}

//------------------------------------------------------------------------------
//! \brief  Initializes a HID mouse driver
//!
//!         This method sets the standard descriptors of the device and the
//!         default HID mouse configuration.
//! \param  pMse Pointer to a S_mse instance
//! \param  pUsb Pointer to the S_usb driver instance to use
//! \see    S_mse
//! \see    S_usb
//------------------------------------------------------------------------------
void MSE_Init(S_mse *pMse, const S_usb *pUsb)
{
    // Initialize mouse driver
    pMse->bIdleRate = 0;
    pMse->bProtocol = HID_REPORT_PROTOCOL;
    pMse->sReport.bButtons = 0;
    pMse->sReport.bX = 0;
    pMse->sReport.bY = 0;

    // Initialize standard class attributes
    pMse->sClass.pUsb = pUsb;
    pMse->sClass.pDescriptors = &sDescriptors;

    // Initialize the USB driver
    USB_Init(pUsb);
}

//------------------------------------------------------------------------------
//! \brief  Sends the current mouse report to the host, through the interrupt IN
//!         endpoint
//! \param  pMSe      Pointer to a S_mse instance
//! \param  fCallback Optional callback function to invoke when the report is
//!                   sent
//! \param  pArgument Optional argument to pass to the callback function
//------------------------------------------------------------------------------
unsigned char MSE_SendReport(const S_mse *pMse,
                             Callback_f  fCallback,
                             void        *pArgument)
{
    return USB_Write(pMse->sClass.pUsb, MSE_INTERRUPT_IN, &(pMse->sReport),
                     MSE_REPORT_SIZE, fCallback, pArgument);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -