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
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
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