source: mainline/uspace/lib/usb/src/recognise.c@ 7ed5b576

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

USB child device registration

Wrapper for adding child device (i.e. registration with devman) is ready. It takes care
of correct match id creation.

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2010 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 libusb usb
30 * @{
31 */
32/** @file
33 * @brief Functions for recognising kind of attached devices.
34 */
35#include <usb/usbdrv.h>
36#include <usb/classes/classes.h>
37#include <stdio.h>
38#include <errno.h>
39
40
41#define BCD_INT(a) (((unsigned int)(a)) / 256)
42#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
43
44#define BCD_FMT "%x.%x"
45#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
46
47/* FIXME: make this dynamic */
48#define MATCH_STRING_MAX 256
49
50/** Add formatted match id.
51 *
52 * @param matches List of match ids where to add to.
53 * @param score Score of the match.
54 * @param format Printf-like format
55 * @return Error code.
56 */
57static int usb_add_match_id(match_id_list_t *matches, int score,
58 const char *format, ...)
59{
60 char *match_str = NULL;
61 match_id_t *match_id = NULL;
62 int rc;
63
64 match_str = malloc(MATCH_STRING_MAX + 1);
65 if (match_str == NULL) {
66 rc = ENOMEM;
67 goto failure;
68 }
69
70 /*
71 * FIXME: replace with dynamic allocation of exact size
72 */
73 va_list args;
74 va_start(args, format );
75 vsnprintf(match_str, MATCH_STRING_MAX, format, args);
76 match_str[MATCH_STRING_MAX] = 0;
77 va_end(args);
78
79 match_id = create_match_id();
80 if (match_id == NULL) {
81 rc = ENOMEM;
82 goto failure;
83 }
84
85 match_id->id = match_str;
86 match_id->score = score;
87 add_match_id(matches, match_id);
88
89 return EOK;
90
91failure:
92 if (match_str != NULL) {
93 free(match_str);
94 }
95 if (match_id != NULL) {
96 match_id->id = NULL;
97 delete_match_id(match_id);
98 }
99
100 return rc;
101}
102
103/** Create match ids describing attached device.
104 *
105 * @warning The list of match ids @p matches may change even when
106 * function exits with error.
107 *
108 * @param hc Open phone to host controller.
109 * @param matches Initialized list of match ids.
110 * @param address USB address of the attached device.
111 * @return Error code.
112 */
113int usb_drv_create_device_match_ids(int hc, match_id_list_t *matches,
114 usb_address_t address)
115{
116 int rc;
117 usb_standard_device_descriptor_t device_descriptor;
118
119 rc = usb_drv_req_get_device_descriptor(hc, address,
120 &device_descriptor);
121 if (rc != EOK) {
122 return rc;
123 }
124
125 /*
126 * Unless the vendor id is 0, the pair idVendor-idProduct
127 * quite uniquely describes the device.
128 */
129 if (device_descriptor.vendor_id != 0) {
130 /* First, with release number. */
131 rc = usb_add_match_id(matches, 100,
132 "usb&vendor=%d&product=%d&release=" BCD_FMT,
133 (int) device_descriptor.vendor_id,
134 (int) device_descriptor.product_id,
135 BCD_ARGS(device_descriptor.device_version));
136 if (rc != EOK) {
137 return rc;
138 }
139
140 /* Next, without release number. */
141 rc = usb_add_match_id(matches, 90, "usb&vendor=%d&product=%d",
142 (int) device_descriptor.vendor_id,
143 (int) device_descriptor.product_id);
144 if (rc != EOK) {
145 return rc;
146 }
147
148 }
149
150 /*
151 * If the device class does not point to interface,
152 * it is added immediatelly, otherwise full configuration
153 * descriptor must be obtained and parsed.
154 */
155 if (device_descriptor.device_class != USB_CLASS_USE_INTERFACE) {
156 rc = usb_add_match_id(matches, 50, "usb&class=%s",
157 usb_str_class(device_descriptor.device_class));
158 if (rc != EOK) {
159 return rc;
160 }
161 } else {
162 /* TODO */
163 }
164
165 /*
166 * As a fallback, provide the simplest match id possible.
167 */
168 rc = usb_add_match_id(matches, 1, "usb&fallback");
169 if (rc != EOK) {
170 return rc;
171 }
172
173 return EOK;
174}
175
176
177/** Probe for device kind and register it in devman.
178 *
179 * @param hc Open phone to the host controller.
180 * @param parent Parent device.
181 * @param address Address of the (unknown) attached device.
182 * @return Error code.
183 */
184int usb_drv_register_child_in_devman(int hc, device_t *parent,
185 usb_address_t address, devman_handle_t *child_handle)
186{
187 device_t *child = NULL;
188 char *child_name = NULL;
189 int rc;
190
191 child = create_device();
192 if (child == NULL) {
193 rc = ENOMEM;
194 goto failure;
195 }
196
197 /*
198 * TODO: some better child naming
199 */
200 rc = asprintf(&child_name, "usb%p", child);
201 if (rc < 0) {
202 goto failure;
203 }
204 child->name = child_name;
205
206 rc = usb_drv_create_device_match_ids(hc, &child->match_ids, address);
207 if (rc != EOK) {
208 goto failure;
209 }
210
211 rc = child_device_register(child, parent);
212 if (rc != EOK) {
213 goto failure;
214 }
215
216 if (child_handle != NULL) {
217 *child_handle = child->handle;
218 }
219
220 return EOK;
221
222failure:
223 if (child != NULL) {
224 child->name = NULL;
225 /* This takes care of match_id deallocation as well. */
226 delete_device(child);
227 }
228 if (child_name != NULL) {
229 free(child_name);
230 }
231
232 return rc;
233
234}
235
236
237/**
238 * @}
239 */
Note: See TracBrowser for help on using the repository browser.