hidreport.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Lubos Slovak
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00037 #include <assert.h>
00038 #include <errno.h>
00039 #include <str_error.h>
00040 
00041 #include <usb/debug.h>
00042 #include <usb/hid/hidparser.h>
00043 #include <usb/dev/dp.h>
00044 #include <usb/dev/driver.h>
00045 #include <usb/dev/pipes.h>
00046 #include <usb/hid/hid.h>
00047 #include <usb/descriptor.h>
00048 #include <usb/dev/request.h>
00049 
00050 #include <usb/hid/hidreport.h>
00051 
00052 static int usb_hid_get_report_descriptor(usb_device_t *dev, 
00053     uint8_t **report_desc, size_t *size)
00054 {
00055         assert(report_desc != NULL);
00056         assert(size != NULL);
00057         
00058         usb_dp_parser_t parser =  {
00059                 .nesting = usb_dp_standard_descriptor_nesting
00060         };
00061         
00062         usb_dp_parser_data_t parser_data = {
00063                 .data = dev->descriptors.configuration,
00064                 .size = dev->descriptors.configuration_size,
00065                 .arg = NULL
00066         };
00067         
00068         /*
00069          * First nested descriptor of the configuration descriptor.
00070          */
00071         uint8_t *d = 
00072             usb_dp_get_nested_descriptor(&parser, &parser_data, 
00073             dev->descriptors.configuration);
00074         
00075         /*
00076          * Find the interface descriptor corresponding to our interface number.
00077          */
00078         int i = 0;
00079         while (d != NULL && i < dev->interface_no) {
00080                 d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
00081                     dev->descriptors.configuration, d);
00082                 ++i;
00083         }
00084         
00085         if (d == NULL) {
00086                 usb_log_error("The %d. interface descriptor not found!\n",
00087                     dev->interface_no);
00088                 return ENOENT;
00089         }
00090         
00091         /*
00092          * First nested descriptor of the interface descriptor.
00093          */
00094         uint8_t *iface_desc = d;
00095         d = usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc);
00096         
00097         /*
00098          * Search through siblings until the HID descriptor is found.
00099          */
00100         while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) {
00101                 d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
00102                     iface_desc, d);
00103         }
00104         
00105         if (d == NULL) {
00106                 usb_log_fatal("No HID descriptor found!\n");
00107                 return ENOENT;
00108         }
00109         
00110         if (*d != sizeof(usb_standard_hid_descriptor_t)) {
00111                 usb_log_error("HID descriptor has wrong size (%u, expected %zu"
00112                     ")\n", *d, sizeof(usb_standard_hid_descriptor_t));
00113                 return EINVAL;
00114         }
00115         
00116         usb_standard_hid_descriptor_t *hid_desc = 
00117             (usb_standard_hid_descriptor_t *)d;
00118         
00119         uint16_t length =  hid_desc->report_desc_info.length;
00120         size_t actual_size = 0;
00121 
00122         /*
00123          * Allocate space for the report descriptor.
00124          */
00125         *report_desc = (uint8_t *)malloc(length);
00126         if (*report_desc == NULL) {
00127                 usb_log_error("Failed to allocate space for Report descriptor."
00128                     "\n");
00129                 return ENOMEM;
00130         }
00131         
00132         usb_log_debug("Getting Report descriptor, expected size: %u\n", length);
00133         
00134         /*
00135          * Get the descriptor from the device.
00136          */
00137         int rc = usb_request_get_descriptor(&dev->ctrl_pipe,
00138             USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
00139             USB_DESCTYPE_HID_REPORT, 0, dev->interface_no,
00140             *report_desc, length, &actual_size);
00141 
00142         if (rc != EOK) {
00143                 free(*report_desc);
00144                 *report_desc = NULL;
00145                 return rc;
00146         }
00147 
00148         if (actual_size != length) {
00149                 free(*report_desc);
00150                 *report_desc = NULL;
00151                 usb_log_error("Report descriptor has wrong size (%zu, expected "
00152                     "%u)\n", actual_size, length);
00153                 return EINVAL;
00154         }
00155         
00156         *size = length;
00157         
00158         usb_log_debug("Done.\n");
00159         
00160         return EOK;
00161 }
00162 
00163 /*----------------------------------------------------------------------------*/
00164 
00165 int usb_hid_process_report_descriptor(usb_device_t *dev, 
00166     usb_hid_report_t *report, uint8_t **report_desc, size_t *report_size)
00167 {
00168         if (dev == NULL || report == NULL) {
00169                 usb_log_error("Failed to process Report descriptor: wrong "
00170                     "parameters given.\n");
00171                 return EINVAL;
00172         }
00173         
00174 //      uint8_t *report_desc = NULL;
00175 //      size_t report_size;
00176         
00177         int rc = usb_hid_get_report_descriptor(dev, report_desc, report_size);
00178         
00179         if (rc != EOK) {
00180                 usb_log_error("Problem with getting Report descriptor: %s.\n",
00181                     str_error(rc));
00182                 if (*report_desc != NULL) {
00183                         free(*report_desc);
00184                         *report_desc = NULL;
00185                 }
00186                 return rc;
00187         }
00188         
00189         assert(*report_desc != NULL);
00190         
00191         rc = usb_hid_parse_report_descriptor(report, *report_desc, *report_size);
00192         if (rc != EOK) {
00193                 usb_log_error("Problem parsing Report descriptor: %s.\n",
00194                     str_error(rc));
00195                 free(*report_desc);
00196                 *report_desc = NULL;
00197                 return rc;
00198         }
00199         
00200         usb_hid_descriptor_print(report);
00201         
00202         return EOK;
00203 }
00204 

Generated on Thu Jun 2 07:45:48 2011 for HelenOS/USB by  doxygen 1.4.7