00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
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                 
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                 
00119 
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         
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         
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         
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         
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