source: mainline/uspace/drv/usbmid/usbmid.c@ 95120c3

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

MID driver handles get_address requests correctly

Also, splitted some error messages to get more details.

  • Property mode set to 100644
File size: 4.9 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 * Helper functions.
35 */
36#include <errno.h>
37#include <str_error.h>
38#include <stdlib.h>
39#include <usb_iface.h>
40#include <usb/ddfiface.h>
41#include <usb/pipes.h>
42#include <usb/classes/classes.h>
43#include <usb/recognise.h>
44#include "usbmid.h"
45
46/** Callback for DDF USB interface. */
47static int usb_iface_get_address_impl(device_t *device, devman_handle_t handle,
48 usb_address_t *address)
49{
50 assert(device);
51 device_t *parent = device->parent;
52
53 /* Default error, device does not support this operation. */
54 int rc = ENOTSUP;
55
56 if (parent && parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
57 usb_iface_t *usb_iface
58 = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
59 assert(usb_iface != NULL);
60
61 if (usb_iface->get_address) {
62 rc = usb_iface->get_address(parent, parent->handle,
63 address);
64 }
65 }
66
67 return rc;
68}
69
70static usb_iface_t child_usb_iface = {
71 .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
72 .get_address = usb_iface_get_address_impl
73};
74
75
76static device_ops_t child_device_ops = {
77 .interfaces[USB_DEV_IFACE] = &child_usb_iface
78};
79
80static device_ops_t mid_device_ops = {
81 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
82};
83
84/** Create new USB multi interface device.
85 *
86 * @param dev Backing generic DDF device.
87 * @return New USB MID device.
88 * @retval NULL Error occured.
89 */
90usbmid_device_t *usbmid_device_create(device_t *dev)
91{
92 usbmid_device_t *mid = malloc(sizeof(usbmid_device_t));
93 if (mid == NULL) {
94 usb_log_error("Out of memory (wanted %zu bytes).\n",
95 sizeof(usbmid_device_t));
96 return NULL;
97 }
98
99 int rc;
100 rc = usb_device_connection_initialize_from_device(&mid->wire, dev);
101 if (rc != EOK) {
102 usb_log_error("Failed to initialize `USB wire': %s.\n",
103 str_error(rc));
104 free(mid);
105 return NULL;
106 }
107
108 rc = usb_endpoint_pipe_initialize_default_control(&mid->ctrl_pipe,
109 &mid->wire);
110 if (rc != EOK) {
111 usb_log_error("Failed to initialize control pipe: %s.\n",
112 str_error(rc));
113 free(mid);
114 return NULL;
115 }
116
117 mid->dev = dev;
118 dev->ops = &mid_device_ops;
119
120 return mid;
121}
122
123
124/** Spawn new child device from one interface.
125 *
126 * @param parent Parent MID device.
127 * @param device_descriptor Device descriptor.
128 * @param interface_descriptor Interface descriptor.
129 * @return Error code.
130 */
131int usbmid_spawn_interface_child(usbmid_device_t *parent,
132 const usb_standard_device_descriptor_t *device_descriptor,
133 const usb_standard_interface_descriptor_t *interface_descriptor)
134{
135 device_t *child = NULL;
136 char *child_name = NULL;
137 int rc;
138
139 /* Create the device. */
140 child = create_device();
141 if (child == NULL) {
142 rc = ENOMEM;
143 goto error_leave;
144 }
145
146 /*
147 * Name is class name followed by interface number.
148 * The interface number shall provide uniqueness while the
149 * class name something humanly understandable.
150 */
151 rc = asprintf(&child_name, "%s%d",
152 usb_str_class(interface_descriptor->interface_class),
153 (int) interface_descriptor->interface_number);
154 if (rc < 0) {
155 goto error_leave;
156 }
157 child->parent = parent->dev;
158 child->name = child_name;
159 child->ops = &child_device_ops;
160
161 rc = usb_device_create_match_ids_from_interface(interface_descriptor,
162 &child->match_ids);
163 if (rc != EOK) {
164 goto error_leave;
165 }
166
167 rc = child_device_register(child, parent->dev);
168 if (rc != EOK) {
169 goto error_leave;
170 }
171
172 return EOK;
173
174error_leave:
175 if (child != NULL) {
176 child->name = NULL;
177 /* This takes care of match_id deallocation as well. */
178 delete_device(child);
179 }
180 if (child_name != NULL) {
181 free(child_name);
182 }
183
184 return rc;
185}
186
187/**
188 * @}
189 */
Note: See TracBrowser for help on using the repository browser.