altiface.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011 Vojtech Horky
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 
00035 #include <usb/dev/driver.h>
00036 #include <usb/dev/request.h>
00037 #include <usb/debug.h>
00038 #include <usb/dev/dp.h>
00039 #include <errno.h>
00040 #include <str_error.h>
00041 #include <assert.h>
00042 
00050 size_t usb_interface_count_alternates(uint8_t *config_descr,
00051     size_t config_descr_size, uint8_t interface_no)
00052 {
00053         assert(config_descr != NULL);
00054         assert(config_descr_size > 0);
00055 
00056         usb_dp_parser_t dp_parser = {
00057                 .nesting = usb_dp_standard_descriptor_nesting
00058         };
00059         usb_dp_parser_data_t dp_data = {
00060                 .data = config_descr,
00061                 .size = config_descr_size,
00062                 .arg = NULL
00063         };
00064 
00065         size_t alternate_count = 0;
00066 
00067         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
00068             &dp_data, config_descr);
00069         while (iface_ptr != NULL) {
00070                 usb_standard_interface_descriptor_t *iface
00071                     = (usb_standard_interface_descriptor_t *) iface_ptr;
00072                 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
00073                         if (iface->interface_number == interface_no) {
00074                                 alternate_count++;
00075                         }
00076                 }
00077                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
00078                     config_descr, iface_ptr);
00079         }
00080 
00081         return alternate_count;
00082 }
00083 
00092 int usb_alternate_interfaces_create(uint8_t *config_descr,
00093     size_t config_descr_size, int interface_number,
00094     usb_alternate_interfaces_t **alternates_ptr)
00095 {
00096         assert(alternates_ptr != NULL);
00097         assert(config_descr != NULL);
00098         assert(config_descr_size > 0);
00099 
00100         if (interface_number < 0) {
00101                 alternates_ptr = NULL;
00102                 return EOK;
00103         }
00104 
00105         usb_alternate_interfaces_t *alternates
00106             = malloc(sizeof(usb_alternate_interfaces_t));
00107 
00108         if (alternates == NULL) {
00109                 return ENOMEM;
00110         }
00111 
00112         alternates->alternative_count
00113             = usb_interface_count_alternates(config_descr, config_descr_size,
00114             interface_number);
00115 
00116         if (alternates->alternative_count == 0) {
00117                 free(alternates);
00118                 return ENOENT;
00119         }
00120 
00121         alternates->alternatives = malloc(alternates->alternative_count
00122             * sizeof(usb_alternate_interface_descriptors_t));
00123         if (alternates->alternatives == NULL) {
00124                 free(alternates);
00125                 return ENOMEM;
00126         }
00127 
00128         alternates->current = 0;
00129 
00130         usb_dp_parser_t dp_parser = {
00131                 .nesting = usb_dp_standard_descriptor_nesting
00132         };
00133         usb_dp_parser_data_t dp_data = {
00134                 .data = config_descr,
00135                 .size = config_descr_size,
00136                 .arg = NULL
00137         };
00138 
00139         usb_alternate_interface_descriptors_t *cur_alt_iface
00140             = &alternates->alternatives[0];
00141 
00142         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
00143             &dp_data, dp_data.data);
00144         while (iface_ptr != NULL) {
00145                 usb_standard_interface_descriptor_t *iface
00146                     = (usb_standard_interface_descriptor_t *) iface_ptr;
00147                 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
00148                     || (iface->interface_number != interface_number)) {
00149                         iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
00150                             &dp_data,
00151                             dp_data.data, iface_ptr);
00152                         continue;
00153                 }
00154 
00155                 cur_alt_iface->interface = iface;
00156                 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
00157 
00158                 /* Find next interface to count size of nested descriptors. */
00159                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
00160                     dp_data.data, iface_ptr);
00161                 if (iface_ptr == NULL) {
00162                         uint8_t *next = dp_data.data + dp_data.size;
00163                         cur_alt_iface->nested_descriptors_size
00164                             = next - cur_alt_iface->nested_descriptors;
00165                 } else {
00166                         cur_alt_iface->nested_descriptors_size
00167                             = iface_ptr - cur_alt_iface->nested_descriptors;
00168                 }
00169 
00170                 cur_alt_iface++;
00171         }
00172 
00173         *alternates_ptr = alternates;
00174 
00175         return EOK;
00176 }
00177 
00178 

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