SAMV71 Xplained Ultra Software Package 1.5

uhi_hid_mouse.c

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