SAMV71 Xplained Ultra Software Package 1.5

host_hid.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 Management of the generic host HID features.
00033  */
00034 
00035 //_____  I N C L U D E S _______________________________________________________
00036 
00037 #include <stddef.h>
00038 #include "compiler.h"
00039 #include "conf_usb.h"
00040 #include "usb_task.h"
00041 #include "usb_host_task.h"
00042 #include "usb_host_enum.h"
00043 #include "hid.h"
00044 #include "host_hid.h"
00045 
00046 
00047 //_____ M A C R O S ____________________________________________________________
00048 
00049 
00050 //_____ D E F I N I T I O N S __________________________________________________
00051 
00052 //! HID report descriptor parser control structure.
00053 static struct {
00054     size_t length;
00055     const hid_item_t *item;
00056 } host_hid_report_descriptor_parser = {
00057     0,
00058     NULL
00059 };
00060 
00061 
00062 //_____ D E C L A R A T I O N S ________________________________________________
00063 
00064 /*! \name Standard Requests Applied to HID
00065  */
00066 //! @{
00067 
00068 
00069 Status_t host_hid_get_descriptor(U8 descriptor_type, U8 descriptor_index,
00070                                  U8 s_interface)
00071 {
00072     Status_t status;
00073     const hid_descriptor_t *hid_descriptor = (hid_descriptor_t *)&data_stage;
00074     U8 i;
00075 
00076     usb_request.bmRequestType   = 0x81;
00077     usb_request.bRequest        = GET_DESCRIPTOR;
00078     usb_request.wValue          = descriptor_type << 8 | descriptor_index;
00079     usb_request.wIndex          = Get_interface_number(s_interface);
00080     usb_request.wLength         = SIZEOF_DATA_STAGE;
00081     usb_request.incomplete_read = FALSE;
00082 
00083     status = host_transfer_control(data_stage);
00084 
00085     switch (descriptor_type) {
00086     case HID_DESCRIPTOR:
00087         for (i = 0; i < hid_descriptor->bNumDescriptors; i++) {
00088             if (hid_descriptor->Descriptor[i].bType == HID_REPORT_DESCRIPTOR) {
00089                 host_hid_report_descriptor_parser.length =
00090                     usb_format_usb_to_mcu_data(16, hid_descriptor->Descriptor[i].wLength);
00091                 break;
00092             }
00093         }
00094 
00095         break;
00096 
00097     case HID_REPORT_DESCRIPTOR:
00098         host_hid_report_descriptor_parser.item = (hid_item_t *)&data_stage;
00099         break;
00100     }
00101 
00102     return status;
00103 }
00104 
00105 
00106 Status_t host_hid_set_descriptor(U8 descriptor_type, U8 descriptor_index,
00107                                  U8 s_interface, U16 length)
00108 {
00109     usb_request.bmRequestType   = 0x01;
00110     usb_request.bRequest        = SET_DESCRIPTOR;
00111     usb_request.wValue          = descriptor_type << 8 | descriptor_index;
00112     usb_request.wIndex          = Get_interface_number(s_interface);
00113     usb_request.wLength         = length;
00114     usb_request.incomplete_read = FALSE;
00115 
00116     return host_transfer_control(data_stage);
00117 }
00118 
00119 
00120 //! @}
00121 
00122 
00123 /*! \name HID-Specific Requests
00124  */
00125 //! @{
00126 
00127 
00128 Status_t host_hid_get_report(U8 report_type, U8 report_id, U8 s_interface)
00129 {
00130     usb_request.bmRequestType   = 0xA1;
00131     usb_request.bRequest        = HID_GET_REPORT;
00132     usb_request.wValue          = report_type << 8 | report_id;
00133     usb_request.wIndex          = Get_interface_number(s_interface);
00134     usb_request.wLength         = SIZEOF_DATA_STAGE;
00135     usb_request.incomplete_read = FALSE;
00136 
00137     return host_transfer_control(data_stage);
00138 }
00139 
00140 
00141 Status_t host_hid_set_report(U8 report_type, U8 report_id, U8 s_interface,
00142                              U16 length)
00143 {
00144     usb_request.bmRequestType   = 0x21;
00145     usb_request.bRequest        = HID_SET_REPORT;
00146     usb_request.wValue          = report_type << 8 | report_id;
00147     usb_request.wIndex          = Get_interface_number(s_interface);
00148     usb_request.wLength         = length;
00149     usb_request.incomplete_read = FALSE;
00150 
00151     return host_transfer_control(data_stage);
00152 }
00153 
00154 
00155 U8 host_hid_get_idle(U8 report_id, U8 s_interface)
00156 {
00157     usb_request.bmRequestType   = 0xA1;
00158     usb_request.bRequest        = HID_GET_IDLE;
00159     usb_request.wValue          = 0x00 << 8 | report_id;
00160     usb_request.wIndex          = Get_interface_number(s_interface);
00161     usb_request.wLength         = 0x0001;
00162     usb_request.incomplete_read = FALSE;
00163 
00164     host_transfer_control(data_stage);
00165 
00166     return data_stage[0x00];
00167 }
00168 
00169 
00170 Status_t host_hid_set_idle(U8 duration_4_ms, U8 report_id, U8 s_interface)
00171 {
00172     usb_request.bmRequestType   = 0x21;
00173     usb_request.bRequest        = HID_SET_IDLE;
00174     usb_request.wValue          = duration_4_ms << 8 | report_id;
00175     usb_request.wIndex          = Get_interface_number(s_interface);
00176     usb_request.wLength         = 0x0000;
00177     usb_request.incomplete_read = FALSE;
00178 
00179     return host_transfer_control(data_stage);
00180 }
00181 
00182 
00183 U8 host_hid_get_protocol(U8 s_interface)
00184 {
00185     usb_request.bmRequestType   = 0xA1;
00186     usb_request.bRequest        = HID_GET_PROTOCOL;
00187     usb_request.wValue          = 0x0000;
00188     usb_request.wIndex          = Get_interface_number(s_interface);
00189     usb_request.wLength         = 0x0001;
00190     usb_request.incomplete_read = FALSE;
00191 
00192     host_transfer_control(data_stage);
00193 
00194     return data_stage[0x00];
00195 }
00196 
00197 
00198 Status_t host_hid_set_protocol(U8 protocol, U8 s_interface)
00199 {
00200     usb_request.bmRequestType   = 0x21;
00201     usb_request.bRequest        = HID_SET_PROTOCOL;
00202     usb_request.wValue          = protocol;
00203     usb_request.wIndex          = Get_interface_number(s_interface);
00204     usb_request.wLength         = 0x0000;
00205     usb_request.incomplete_read = FALSE;
00206 
00207     return host_transfer_control(data_stage);
00208 }
00209 
00210 
00211 //! @}
00212 
00213 
00214 /*! \name HID Report Descriptor Parsing Functions
00215  */
00216 //! @{
00217 
00218 
00219 Status_bool_t host_hid_get_item(host_hid_item_t *item)
00220 {
00221     const hid_item_t *hid_item = host_hid_report_descriptor_parser.item;
00222     U8 size;
00223 
00224     if (host_hid_report_descriptor_parser.length <
00225         (U8 *)&hid_item->header - (U8 *)hid_item +
00226         sizeof(hid_item->header))
00227         return FALSE;
00228 
00229     item->type = hid_item->header.bType;
00230 
00231     if (hid_item->header.bTag == HID_ITEM_TAG_LONG_ITEM) {
00232         if (host_hid_report_descriptor_parser.length <
00233             (U8 *)&hid_item->long_format.bDataSize - (U8 *)hid_item +
00234             sizeof(hid_item->long_format.bDataSize))
00235             return FALSE;
00236 
00237         size = hid_item->long_format.bDataSize;
00238 
00239         if (host_hid_report_descriptor_parser.length <
00240             (U8 *)&hid_item->long_format.data - (U8 *)hid_item +
00241             size)
00242             return FALSE;
00243 
00244         item->tag = hid_item->long_format.bLongItemTag;
00245 
00246         item->long_format = TRUE;
00247 
00248         item->long_data.size = size;
00249         item->long_data.data = &hid_item->long_format.data;
00250 
00251         host_hid_report_descriptor_parser.length -=
00252             (U8 *)&hid_item->long_format.data - (U8 *)hid_item +
00253             size;
00254 
00255         host_hid_report_descriptor_parser.item =
00256             (hid_item_t *)&hid_item->long_format.data[size];
00257     } else {
00258         U8 i;
00259 
00260         size = (hid_item->short_format.bSize) ?
00261                1 << (hid_item->short_format.bSize - 1) :
00262                0;
00263 
00264         if (host_hid_report_descriptor_parser.length <
00265             (U8 *)&hid_item->short_format.data - (U8 *)hid_item +
00266             size)
00267             return FALSE;
00268 
00269         item->tag = hid_item->short_format.bTag;
00270 
00271         item->long_format = FALSE;
00272 
00273         item->short_data.value = 0x00000000;
00274 
00275         for (i = 0; i < size; i++) {
00276             item->short_data.value = item->short_data.value << 8 |
00277                                      hid_item->short_format.data[i];
00278         }
00279 
00280         item->short_data.value =
00281             usb_format_usb_to_mcu_data(32, item->short_data.value <<
00282                                        ((sizeof(U32) - size) << 3));
00283 
00284         host_hid_report_descriptor_parser.length -=
00285             (U8 *)&hid_item->short_format.data - (U8 *)hid_item +
00286             size;
00287 
00288         host_hid_report_descriptor_parser.item =
00289             (hid_item_t *)&hid_item->short_format.data[size];
00290     }
00291 
00292     return TRUE;
00293 }
00294 
00295 
00296 //! @}
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines