SAMV71 Xplained Ultra Software Package 1.3

uhi_hid_mouse.c

Go to the documentation of this file.
00001 /**
00002  * \file
00003  *
00004  * \brief USB host Human Interface Device (HID) mouse driver.
00005  *
00006  * Copyright (C) 2011-2015 Atmel Corporation. All rights reserved.
00007  *
00008  * \asf_license_start
00009  *
00010  * \page License
00011  *
00012  * Redistribution and use in source and binary forms, with or without
00013  * modification, are permitted provided that the following conditions are met:
00014  *
00015  * 1. Redistributions of source code must retain the above copyright notice,
00016  *    this list of conditions and the following disclaimer.
00017  *
00018  * 2. Redistributions in binary form must reproduce the above copyright notice,
00019  *    this list of conditions and the following disclaimer in the documentation
00020  *    and/or other materials provided with the distribution.
00021  *
00022  * 3. The name of Atmel may not be used to endorse or promote products derived
00023  *    from this software without specific prior written permission.
00024  *
00025  * 4. This software may only be redistributed and used in connection with an
00026  *    Atmel microcontroller product.
00027  *
00028  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
00029  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00030  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00031  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
00032  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00033  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00034  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00035  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00036  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00037  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00038  * POSSIBILITY OF SUCH DAMAGE.
00039  *
00040  * \asf_license_stop
00041  *
00042  */
00043 /*
00044  * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
00045  */
00046 
00047 #include "conf_usb_host.h"
00048 #include "USBHDriver.h"
00049 #include "USBH.h"
00050 #include "uhi_hid_mouse.h"
00051 #include <string.h>
00052 
00053 #ifdef USB_HOST_HUB_SUPPORT
00054 # error USB HUB support is not implemented on UHI mouse
00055 #endif
00056 
00057 /**
00058  * \ingroup uhi_hid_mouse_group
00059  * \defgroup uhi_hid_mouse_group_internal Implementation of UHI HID Mouse
00060  *
00061  * Class internal implementation
00062  * @{
00063  */
00064 
00065 /**
00066  * \name Index in HID report for usual HID mouse events
00067  * @{
00068  */
00069 #define UHI_HID_MOUSE_BTN        0
00070 #define UHI_HID_MOUSE_MOV_X      1
00071 #define UHI_HID_MOUSE_MOV_Y      2
00072 #define UHI_HID_MOUSE_MOV_SCROLL 3
00073 //@}
00074 
00075 /**
00076  * \name Structure to store information about USB Device HID mouse
00077  */
00078 //@{
00079 typedef struct {
00080     USBH_device_t *dev;
00081     uint8_t ep_in;
00082     uint8_t report_size;
00083     uint8_t *report;
00084     uint8_t report_btn_prev;
00085 }uhi_hid_mouse_dev_t;
00086 
00087 static uhi_hid_mouse_dev_t uhi_hid_mouse_dev = {
00088     .dev = NULL,
00089     .report = NULL,
00090     };
00091 
00092 //@}
00093 
00094 
00095 /**
00096  * \name Internal routines
00097  */
00098 //@{
00099 static void uhi_hid_mouse_start_trans_report(USBHS_Add_t add);
00100 static void uhi_hid_mouse_report_reception(
00101         USBHS_Add_t add,
00102         USBHS_Ep_t ep,
00103         USBH_XfrStatus_t status,
00104         uint32_t nb_transfered);
00105 //@}
00106 
00107 
00108 /**
00109  * \name Functions required by UHC
00110  * @{
00111  */
00112 
00113 USBH_enum_status_t uhi_hid_mouse_install(USBH_device_t* dev)
00114 {
00115     bool b_iface_supported;
00116     uint16_t conf_desc_lgt;
00117     USBInterfaceDescriptor *ptr_iface;
00118 
00119     if (uhi_hid_mouse_dev.dev != NULL) {
00120         return UHC_ENUM_SOFTWARE_LIMIT; // Device already allocated
00121     }
00122     conf_desc_lgt = (dev->conf_desc->wTotalLength);
00123     ptr_iface = (USBInterfaceDescriptor*)dev->conf_desc;
00124     b_iface_supported = false;
00125     while(conf_desc_lgt) {
00126         switch (ptr_iface->bDescriptorType) {
00127 
00128         case USBGenericDescriptor_INTERFACE:
00129             if ((ptr_iface->bInterfaceClass   == HIDInterfaceDescriptor_CLASS)
00130             && (ptr_iface->bInterfaceProtocol == HIDInterfaceDescriptor_PROTOCOL_MOUSE) ) {
00131                 // USB HID Mouse interface found
00132                 // Start allocation endpoint(s)
00133                 b_iface_supported = true;
00134             } else {
00135                 // Stop allocation endpoint(s)
00136                 b_iface_supported = false;
00137             }
00138             break;
00139 
00140         case USBGenericDescriptor_ENDPOINT:
00141             //  Allocation of the endpoint
00142             if (!b_iface_supported) {
00143                 break;
00144             }
00145             if (!USBH_HAL_ConfigurePipe(dev->address, (USBEndpointDescriptor*)ptr_iface)) {
00146                 return UHC_ENUM_HARDWARE_LIMIT; // Endpoint allocation fail
00147             }
00148             assert(((USBEndpointDescriptor*)ptr_iface)->bEndpointAddress & USB_EP_DIR_IN);
00149             uhi_hid_mouse_dev.ep_in = ((USBEndpointDescriptor*)ptr_iface)->bEndpointAddress;
00150             uhi_hid_mouse_dev.report_size =
00151                     (((USBEndpointDescriptor*)ptr_iface)->wMaxPacketSize);
00152             uhi_hid_mouse_dev.report = malloc(uhi_hid_mouse_dev.report_size);
00153             if (uhi_hid_mouse_dev.report == NULL) {
00154                 assert(false);
00155                 return UHC_ENUM_MEMORY_LIMIT; // Internal RAM allocation fail
00156             }
00157             uhi_hid_mouse_dev.dev = dev;
00158             // All endpoints of all interfaces supported allocated
00159             return UHC_ENUM_SUCCESS;
00160 
00161         default:
00162             // Ignore descriptor
00163             break;
00164         }
00165         assert(conf_desc_lgt>=ptr_iface->bLength);
00166         conf_desc_lgt -= ptr_iface->bLength;
00167         ptr_iface = (USBInterfaceDescriptor*)((uint8_t*)ptr_iface + ptr_iface->bLength);
00168     }
00169     return UHC_ENUM_UNSUPPORTED; // No interface supported
00170 }
00171 
00172 void uhi_hid_mouse_enable(USBH_device_t* dev)
00173 {
00174     if (uhi_hid_mouse_dev.dev != dev) {
00175         return;  // No interface to enable
00176     }
00177 
00178     // Init value
00179     uhi_hid_mouse_dev.report_btn_prev = 0;
00180     uhi_hid_mouse_start_trans_report(dev->address);
00181     UHI_HID_MOUSE_CHANGE(dev, true);
00182 }
00183 
00184 void uhi_hid_mouse_uninstall(USBH_device_t* dev)
00185 {
00186     if (uhi_hid_mouse_dev.dev != dev) {
00187         return; // Device not enabled in this interface
00188     }
00189     uhi_hid_mouse_dev.dev = NULL;
00190     assert(uhi_hid_mouse_dev.report!=NULL);
00191     free(uhi_hid_mouse_dev.report);
00192     UHI_HID_MOUSE_CHANGE(dev, false);
00193 }
00194 //@}
00195 
00196 /**
00197  * \name Internal routines
00198  */
00199 //@{
00200 
00201 /**
00202  * \brief Starts the reception of the HID mouse report
00203  *
00204  * \param add   USB address to use
00205  */
00206 static void uhi_hid_mouse_start_trans_report(USBHS_Add_t add)
00207 {
00208     // Start transfer on interrupt endpoint IN
00209     USBH_HAL_RunEndpoint(add, uhi_hid_mouse_dev.ep_in, true, uhi_hid_mouse_dev.report,
00210             uhi_hid_mouse_dev.report_size, 0, uhi_hid_mouse_report_reception);
00211 }
00212 
00213 /**
00214  * \brief Decodes the HID mouse report received
00215  *
00216  * \param add           USB address used by the transfer
00217  * \param status        Transfer status
00218  * \param nb_transfered Number of data transfered
00219  */
00220 static void uhi_hid_mouse_report_reception(
00221         USBHS_Add_t add,
00222         USBHS_Ep_t ep,
00223         USBH_XfrStatus_t status,
00224         uint32_t nb_transfered)
00225 {
00226     uint8_t state_prev;
00227     uint8_t state_new;
00228     UNUSED(ep);
00229 
00230     if ((status == UHD_TRANS_NOTRESPONDING) || (status == UHD_TRANS_TIMEOUT)) {
00231         uhi_hid_mouse_start_trans_report(add);
00232         return; // HID mouse transfer restart
00233     }
00234 
00235     if ((status != UHD_TRANS_NOERROR) || (nb_transfered < 4)) {
00236         return; // HID mouse transfer aborted
00237     }
00238 
00239     // Decode buttons
00240     state_prev = uhi_hid_mouse_dev.report_btn_prev;
00241     state_new = uhi_hid_mouse_dev.report[UHI_HID_MOUSE_BTN];
00242     if ((state_prev & 0x01) != (state_new & 0x01)) {
00243         UHI_HID_MOUSE_EVENT_BTN_LEFT((state_new & 0x01) ? true : false);
00244     }
00245     if ((state_prev & 0x02) != (state_new & 0x02)) {
00246         UHI_HID_MOUSE_EVENT_BTN_RIGHT((state_new & 0x02) ? true : false);
00247     }
00248     if ((state_prev & 0x04) != (state_new & 0x04)) {
00249         UHI_HID_MOUSE_EVENT_BTN_MIDDLE((state_new & 0x04) ? true : false);
00250     }
00251     uhi_hid_mouse_dev.report_btn_prev = state_new;
00252 
00253     // Decode moves
00254     if ((uhi_hid_mouse_dev.report[UHI_HID_MOUSE_MOV_X] != 0)
00255             || (uhi_hid_mouse_dev.report[UHI_HID_MOUSE_MOV_Y] != 0)
00256             || (uhi_hid_mouse_dev.report[UHI_HID_MOUSE_MOV_SCROLL] != 0)) {
00257         UHI_HID_MOUSE_EVENT_MOUVE(
00258                 (int8_t)uhi_hid_mouse_dev.report[UHI_HID_MOUSE_MOV_X],
00259                 (int8_t)uhi_hid_mouse_dev.report[UHI_HID_MOUSE_MOV_Y],
00260                 (int8_t)uhi_hid_mouse_dev.report[UHI_HID_MOUSE_MOV_SCROLL]);
00261     }
00262 
00263     uhi_hid_mouse_start_trans_report(add);
00264 }
00265 //@}
00266 
00267 //@}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines