explore.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 
00036 #include <errno.h>
00037 #include <str_error.h>
00038 #include <stdlib.h>
00039 #include <usb/classes/classes.h>
00040 #include <usb/dev/request.h>
00041 #include <usb/dev/dp.h>
00042 #include <usb/ddfiface.h>
00043 #include "usbmid.h"
00044 
00046 static ddf_dev_ops_t mid_device_ops = {
00047         .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
00048 };
00049 
00056 static bool interface_in_list(link_t *list, int interface_no)
00057 {
00058         link_t *l;
00059         for (l = list->next; l != list; l = l->next) {
00060                 usbmid_interface_t *iface
00061                     = list_get_instance(l, usbmid_interface_t, link);
00062                 if (iface->interface_no == interface_no) {
00063                         return true;
00064                 }
00065         }
00066 
00067         return false;
00068 }
00069 
00076 static void create_interfaces(uint8_t *config_descriptor,
00077     size_t config_descriptor_size, link_t *list)
00078 {
00079         usb_dp_parser_data_t data = {
00080                 .data = config_descriptor,
00081                 .size = config_descriptor_size,
00082                 .arg = NULL
00083         };
00084 
00085         usb_dp_parser_t parser = {
00086                 .nesting = usb_dp_standard_descriptor_nesting
00087         };
00088 
00089         uint8_t *interface_ptr = usb_dp_get_nested_descriptor(&parser, &data,
00090             data.data);
00091         if (interface_ptr == NULL) {
00092                 return;
00093         }
00094 
00095         do {
00096                 if (interface_ptr[1] != USB_DESCTYPE_INTERFACE) {
00097                         goto next_descriptor;
00098                 }
00099 
00100                 usb_standard_interface_descriptor_t *interface
00101                     = (usb_standard_interface_descriptor_t *) interface_ptr;
00102 
00103                 /* Skip alternate interfaces. */
00104                 if (!interface_in_list(list, interface->interface_number)) {
00105                         usbmid_interface_t *iface
00106                             = malloc(sizeof(usbmid_interface_t));
00107                         if (iface == NULL) {
00108                                 break;
00109                         }
00110                         link_initialize(&iface->link);
00111                         iface->fun = NULL;
00112                         iface->interface_no = interface->interface_number;
00113                         iface->interface = interface;
00114 
00115                         list_append(&iface->link, list);
00116                 }
00117 
00118                 /* TODO: add the alternatives and create match ids from them
00119                  * as well.
00120                  */
00121 
00122 next_descriptor:
00123                 interface_ptr = usb_dp_get_sibling_descriptor(&parser, &data,
00124                     data.data, interface_ptr);
00125 
00126         } while (interface_ptr != NULL);
00127 
00128 }
00129 
00138 bool usbmid_explore_device(usb_device_t *dev)
00139 {
00140         int rc;
00141 
00142         int dev_class = dev->descriptors.device.device_class;
00143         if (dev_class != USB_CLASS_USE_INTERFACE) {
00144                 usb_log_warning(
00145                     "Device class: %d (%s), but expected class 0.\n",
00146                     dev_class, usb_str_class(dev_class));
00147                 usb_log_error("Not multi interface device, refusing.\n");
00148                 return false;
00149         }
00150 
00151         /* Short cuts to save on typing ;-). */
00152         uint8_t *config_descriptor_raw = dev->descriptors.configuration;
00153         size_t config_descriptor_size = dev->descriptors.configuration_size;
00154         usb_standard_configuration_descriptor_t *config_descriptor =
00155             (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
00156 
00157         /* Select the first configuration */
00158         rc = usb_request_set_configuration(&dev->ctrl_pipe,
00159             config_descriptor->configuration_number);
00160         if (rc != EOK) {
00161                 usb_log_error("Failed to set device configuration: %s.\n",
00162                     str_error(rc));
00163                 return false;
00164         }
00165 
00166         /* Create control function */
00167         ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
00168         if (ctl_fun == NULL) {
00169                 usb_log_error("Failed to create control function.\n");
00170                 return false;
00171         }
00172 
00173         ctl_fun->ops = &mid_device_ops;
00174 
00175         rc = ddf_fun_bind(ctl_fun);
00176         if (rc != EOK) {
00177                 usb_log_error("Failed to bind control function: %s.\n",
00178                     str_error(rc));
00179                 return false;
00180         }
00181 
00182         /* Create interface children. */
00183         link_t interface_list;
00184         list_initialize(&interface_list);
00185         create_interfaces(config_descriptor_raw, config_descriptor_size,
00186             &interface_list);
00187 
00188         link_t *link;
00189         for (link = interface_list.next; link != &interface_list;
00190             link = link->next) {
00191                 usbmid_interface_t *iface = list_get_instance(link,
00192                     usbmid_interface_t, link);
00193 
00194                 usb_log_info("Creating child for interface %d (%s).\n",
00195                     (int) iface->interface_no,
00196                     usb_str_class(iface->interface->interface_class));
00197 
00198                 rc = usbmid_spawn_interface_child(dev, iface,
00199                     &dev->descriptors.device, iface->interface);
00200                 if (rc != EOK) {
00201                         usb_log_error("Failed to create interface child: %s.\n",
00202                             str_error(rc));
00203                 }
00204         }
00205 
00206         return true;
00207 }
00208 

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