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