source: mainline/uspace/drv/usbmid/explore.c@ 1585c7e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1585c7e was 8f74140c, checked in by Vojtech Horky <vojtechhorky@…>, 14 years ago

USB MID sets device configuration

A forgotten piece of code. Sorry.

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * Copyright (c) 2011 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup drvusbmid
30 * @{
31 */
32/**
33 * @file
34 * Exploration of available interfaces in the USB device.
35 */
36#include <errno.h>
37#include <str_error.h>
38#include <stdlib.h>
39#include <usb/classes/classes.h>
40#include <usb/request.h>
41#include <usb/dp.h>
42#include "usbmid.h"
43
44/** Find starting indexes of all interface descriptors in a configuration.
45 *
46 * @param config_descriptor Full configuration descriptor.
47 * @param config_descriptor_size Size of @p config_descriptor in bytes.
48 * @param interface_positions Array where to store indexes of interfaces.
49 * @param interface_count Size of @p interface_positions array.
50 * @return Number of found interfaces.
51 * @retval (size_t)-1 Error occured.
52 */
53static size_t find_interface_descriptors(uint8_t *config_descriptor,
54 size_t config_descriptor_size,
55 size_t *interface_positions, size_t interface_count)
56{
57 if (interface_count == 0) {
58 return (size_t) -1;
59 }
60
61 usb_dp_parser_data_t data = {
62 .data = config_descriptor,
63 .size = config_descriptor_size,
64 .arg = NULL
65 };
66
67 usb_dp_parser_t parser = {
68 .nesting = usb_dp_standard_descriptor_nesting
69 };
70
71 uint8_t *interface = usb_dp_get_nested_descriptor(&parser, &data,
72 data.data);
73 if (interface == NULL) {
74 return (size_t) -1;
75 }
76 if (interface[1] != USB_DESCTYPE_INTERFACE) {
77 return (size_t) -1;
78 }
79
80 size_t found_interfaces = 0;
81 interface_positions[found_interfaces] = interface - config_descriptor;
82 found_interfaces++;
83
84 while (interface != NULL) {
85 interface = usb_dp_get_sibling_descriptor(&parser, &data,
86 data.data, interface);
87 if ((interface != NULL)
88 && (found_interfaces < interface_count)
89 && (interface[1] == USB_DESCTYPE_INTERFACE)) {
90 interface_positions[found_interfaces]
91 = interface - config_descriptor;
92 found_interfaces++;
93 }
94 }
95
96 return found_interfaces;
97}
98
99/** Explore MID device.
100 *
101 * We expect that @p dev is initialized and session on control pipe is
102 * started.
103 *
104 * @param dev Device to be explored.
105 * @return Whether to accept this device from devman.
106 */
107bool usbmid_explore_device(usbmid_device_t *dev)
108{
109 usb_standard_device_descriptor_t device_descriptor;
110 int rc = usb_request_get_device_descriptor(&dev->ctrl_pipe,
111 &device_descriptor);
112 if (rc != EOK) {
113 usb_log_error("Getting device descriptor failed: %s.\n",
114 str_error(rc));
115 return false;
116 }
117
118 if (device_descriptor.device_class != USB_CLASS_USE_INTERFACE) {
119 usb_log_warning(
120 "Device class: %d (%s), but expected class 0.\n",
121 device_descriptor.device_class,
122 usb_str_class(device_descriptor.device_class));
123 usb_log_error("Not multi interface device, refusing.\n");
124 return false;
125 }
126
127 size_t config_descriptor_size;
128 uint8_t *config_descriptor_raw = NULL;
129 rc = usb_request_get_full_configuration_descriptor_alloc(
130 &dev->ctrl_pipe, 0,
131 (void **) &config_descriptor_raw, &config_descriptor_size);
132 if (rc != EOK) {
133 usb_log_error("Failed getting full config descriptor: %s.\n",
134 str_error(rc));
135 return false;
136 }
137
138 usb_standard_configuration_descriptor_t *config_descriptor
139 = (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
140
141 size_t *interface_descriptors
142 = malloc(sizeof(size_t) * config_descriptor->interface_count);
143 if (interface_descriptors == NULL) {
144 usb_log_error("Out of memory (wanted %zuB).\n",
145 sizeof(size_t) * config_descriptor->interface_count);
146 free(config_descriptor_raw);
147 return false;
148 }
149 size_t interface_descriptors_count
150 = find_interface_descriptors(
151 config_descriptor_raw, config_descriptor_size,
152 interface_descriptors, config_descriptor->interface_count);
153
154 if (interface_descriptors_count == (size_t) -1) {
155 usb_log_error("Problem parsing configuration descriptor.\n");
156 free(config_descriptor_raw);
157 free(interface_descriptors);
158 return false;
159 }
160
161 /* Select the first configuration */
162 rc = usb_request_set_configuration(&dev->ctrl_pipe,
163 config_descriptor->configuration_number);
164 if (rc != EOK) {
165 usb_log_error("Failed to set device configuration: %s.\n",
166 str_error(rc));
167 free(config_descriptor_raw);
168 free(interface_descriptors);
169 return false;
170 }
171
172
173 /* Create control function */
174 ddf_fun_t *ctl_fun = ddf_fun_create(dev->dev, fun_exposed, "ctl");
175 if (ctl_fun == NULL) {
176 usb_log_error("Failed to create control function.\n");
177 free(config_descriptor_raw);
178 free(interface_descriptors);
179 return false;
180 }
181 rc = ddf_fun_bind(ctl_fun);
182 if (rc != EOK) {
183 usb_log_error("Failed to bind control function: %s.\n",
184 str_error(rc));
185 free(config_descriptor_raw);
186 free(interface_descriptors);
187 return false;
188 }
189
190 /* Spawn interface children */
191 size_t i;
192 for (i = 0; i < interface_descriptors_count; i++) {
193 usb_standard_interface_descriptor_t *interface
194 = (usb_standard_interface_descriptor_t *)
195 (config_descriptor_raw + interface_descriptors[i]);
196 usb_log_debug2("Interface descriptor at index %zu (type %d).\n",
197 interface_descriptors[i], (int) interface->descriptor_type);
198 usb_log_info("Creating child for interface %d (%s).\n",
199 (int) interface->interface_number,
200 usb_str_class(interface->interface_class));
201 rc = usbmid_spawn_interface_child(dev, &device_descriptor,
202 interface);
203 if (rc != EOK) {
204 usb_log_error("Failed to create interface child: %s.\n",
205 str_error(rc));
206 }
207 }
208
209 free(config_descriptor_raw);
210
211 return true;
212}
213
214/**
215 * @}
216 */
Note: See TracBrowser for help on using the repository browser.