source: mainline/uspace/drv/bus/usb/usbmid/usbmid.c@ 8e4219ab

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8e4219ab was 8e4219ab, checked in by Jan Vesely <jano.vesely@…>, 12 years ago

Implement and use usb_get_device_handle.

Enables object instantiation on usb interface functions.
avoids forwarding in usbmid driver.

  • 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/**
34 * @file
35 * Helper functions.
36 */
37#include <errno.h>
38#include <str_error.h>
39#include <stdlib.h>
40#include <usb_iface.h>
41#include <usb/dev/pipes.h>
42#include <usb/classes/classes.h>
43#include <usb/dev/recognise.h>
44#include "usbmid.h"
45/** Get host controller handle by calling the parent usb_device_t.
46 *
47 * @param[in] fun Device function the operation is running on.
48 * @param[out] handle Storage for the host controller handle.
49 * @return Error code.
50 */
51static int usb_iface_device_hc_handle(ddf_fun_t *fun, devman_handle_t *handle)
52{
53 assert(handle);
54 assert(fun);
55 usb_device_t *usb_dev = usb_device_get(ddf_fun_get_dev(fun));
56 assert(usb_dev);
57 *handle = usb_device_hc_handle(usb_dev);
58 return EOK;
59}
60
61static int usb_iface_device_handle(ddf_fun_t *fun, devman_handle_t *handle)
62{
63 assert(fun);
64 assert(handle);
65 usb_device_t *usb_dev = usb_device_get(ddf_fun_get_dev(fun));
66 assert(usb_dev);
67 *handle = usb_device_get_devman_handle(usb_dev);
68 return EOK;
69}
70
71/** Get USB device address by calling the parent usb_device_t.
72 *
73 * @param[in] fun Device function the operation is running on.
74 * @param[in] handle Devman handle of USB device we want address of.
75 * @param[out] address Storage for USB address of device with handle @p handle.
76 * @return Error code.
77 */
78static int usb_iface_device_address(ddf_fun_t *fun, usb_address_t *address)
79{
80 assert(address);
81 assert(fun);
82 usb_device_t *usb_dev = usb_device_get(ddf_fun_get_dev(fun));
83 assert(usb_dev);
84 *address = usb_device_address(usb_dev);
85 return EOK;
86}
87
88/** Callback for DDF USB interface. */
89static int usb_iface_iface(ddf_fun_t *fun, int *iface_no)
90{
91 usbmid_interface_t *iface = ddf_fun_data_get(fun);
92 assert(iface);
93
94 if (iface_no != NULL) {
95 *iface_no = iface->interface_no;
96 }
97
98 return EOK;
99}
100
101static int usb_iface_register_endpoint(ddf_fun_t *fun, usb_endpoint_t ep,
102 usb_transfer_type_t type, usb_direction_t dir, size_t mps, unsigned inter)
103{
104 usb_device_t *usb_dev = usb_device_get(ddf_fun_get_dev(fun));
105 assert(usb_dev);
106 async_exch_t *exch = usb_device_bus_exchange_begin(usb_dev);
107 if (!exch)
108 return ENOMEM;
109 const int ret = usb_register_endpoint(exch, ep, type, dir, mps, inter);
110 usb_device_bus_exchange_end(exch);
111 return ret;
112}
113
114static int usb_iface_unregister_endpoint(ddf_fun_t *fun, usb_endpoint_t ep,
115 usb_direction_t dir)
116{
117 usb_device_t *usb_dev = usb_device_get(ddf_fun_get_dev(fun));
118 assert(usb_dev);
119 async_exch_t *exch = usb_device_bus_exchange_begin(usb_dev);
120 if (!exch)
121 return ENOMEM;
122 const int ret = usb_unregister_endpoint(exch, ep, dir);
123 usb_device_bus_exchange_end(exch);
124 return ret;
125}
126
127/** DDF interface of the child - interface function. */
128static usb_iface_t child_usb_iface = {
129 .get_hc_handle = usb_iface_device_hc_handle,
130 .get_my_address = usb_iface_device_address,
131 .get_device_handle = usb_iface_device_handle,
132 .get_my_interface = usb_iface_iface,
133 .register_endpoint = usb_iface_register_endpoint,
134 .unregister_endpoint = usb_iface_unregister_endpoint,
135};
136
137/** Operations for children - interface functions. */
138static ddf_dev_ops_t child_device_ops = {
139 .interfaces[USB_DEV_IFACE] = &child_usb_iface
140};
141
142int usbmid_interface_destroy(usbmid_interface_t *mid_iface)
143{
144 assert(mid_iface);
145 assert_link_not_used(&mid_iface->link);
146 const int ret = ddf_fun_unbind(mid_iface->fun);
147 if (ret != EOK) {
148 return ret;
149 }
150 ddf_fun_destroy(mid_iface->fun);
151 return EOK;
152}
153
154/** Spawn new child device from one interface.
155 *
156 * @param parent Parent MID device.
157 * @param iface Interface information.
158 * @param device_descriptor Device descriptor.
159 * @param interface_descriptor Interface descriptor.
160 * @return Error code.
161 */
162int usbmid_spawn_interface_child(usb_device_t *parent,
163 usbmid_interface_t **iface_ret,
164 const usb_standard_device_descriptor_t *device_descriptor,
165 const usb_standard_interface_descriptor_t *interface_descriptor)
166{
167 ddf_fun_t *child = NULL;
168 char *child_name = NULL;
169 int rc;
170
171 /*
172 * Name is class name followed by interface number.
173 * The interface number shall provide uniqueness while the
174 * class name something humanly understandable.
175 */
176 rc = asprintf(&child_name, "%s%hhu",
177 usb_str_class(interface_descriptor->interface_class),
178 interface_descriptor->interface_number);
179 if (rc < 0) {
180 return ENOMEM;
181 }
182
183 /* Create the device. */
184 child = usb_device_ddf_fun_create(parent, fun_inner, child_name);
185 free(child_name);
186 if (child == NULL) {
187 return ENOMEM;
188 }
189
190 match_id_list_t match_ids;
191 init_match_ids(&match_ids);
192
193 rc = usb_device_create_match_ids_from_interface(device_descriptor,
194 interface_descriptor, &match_ids);
195 if (rc != EOK) {
196 ddf_fun_destroy(child);
197 return rc;
198 }
199
200 list_foreach(match_ids.ids, link) {
201 match_id_t *match_id = list_get_instance(link, match_id_t, link);
202 rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
203 if (rc != EOK) {
204 clean_match_ids(&match_ids);
205 ddf_fun_destroy(child);
206 return rc;
207 }
208 }
209 clean_match_ids(&match_ids);
210 ddf_fun_set_ops(child, &child_device_ops);
211
212 usbmid_interface_t *iface = ddf_fun_data_alloc(child, sizeof(*iface));
213
214 iface->fun = child;
215 iface->interface_no = interface_descriptor->interface_number;
216 link_initialize(&iface->link);
217
218 rc = ddf_fun_bind(child);
219 if (rc != EOK) {
220 /* This takes care of match_id deallocation as well. */
221 ddf_fun_destroy(child);
222 return rc;
223 }
224 *iface_ret = iface;
225
226 return EOK;
227}
228
229/**
230 * @}
231 */
Note: See TracBrowser for help on using the repository browser.