source: mainline/uspace/drv/bus/usb/usbmid/usbmid.c@ 132ab5d1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 132ab5d1 was 132ab5d1, checked in by Jenda <jenda.jzqk73@…>, 8 years ago

Merge commit '6a5d05bd2551e64111bea4f9332dd7448c26ce84' into forwardport

Separate return value from error code in gen_irq_code*().

  • 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/**
34 * @file
35 * Helper functions.
36 */
37
38#include <errno.h>
39#include <str_error.h>
40#include <stdlib.h>
41#include <usb_iface.h>
42#include <usb/dev/pipes.h>
43#include <usb/classes/classes.h>
44#include <usb/dev/recognise.h>
45#include "usbmid.h"
46
47/**
48 * Get USB device description by calling HC and altering the interface field.
49 *
50 * @param[in] fun Device function the operation is running on.
51 * @param[out] desc Device descriptor.
52 * @return Error code.
53 */
54static int usb_iface_description(ddf_fun_t *fun, usb_device_desc_t *desc)
55{
56 usbmid_interface_t *iface = ddf_fun_data_get(fun);
57 assert(iface);
58 usb_device_t *usb_dev = ddf_dev_data_get(ddf_fun_get_dev(fun));
59 assert(usb_dev);
60
61 async_exch_t *exch = usb_device_bus_exchange_begin(usb_dev);
62 if (!exch)
63 return EPARTY;
64
65 usb_device_desc_t tmp_desc;
66 const int ret = usb_get_my_description(exch, &tmp_desc);
67
68 if (ret == EOK && desc) {
69 *desc = tmp_desc;
70 desc->iface = iface->interface_no;
71 }
72
73 usb_device_bus_exchange_end(exch);
74
75 return EOK;
76}
77
78/** DDF interface of the child - USB functions. */
79static usb_iface_t child_usb_iface = {
80 .get_my_description = usb_iface_description,
81};
82
83/** Operations for children - interface functions. */
84static ddf_dev_ops_t child_device_ops = {
85 .interfaces[USB_DEV_IFACE] = &child_usb_iface
86};
87
88int usbmid_interface_destroy(usbmid_interface_t *mid_iface)
89{
90 assert(mid_iface);
91 assert_link_not_used(&mid_iface->link);
92 const int ret = ddf_fun_unbind(mid_iface->fun);
93 if (ret != EOK) {
94 return ret;
95 }
96 ddf_fun_destroy(mid_iface->fun);
97 return EOK;
98}
99
100/** Spawn new child device from one interface.
101 *
102 * @param parent Parent MID device.
103 * @param iface Interface information.
104 * @param device_descriptor Device descriptor.
105 * @param interface_descriptor Interface descriptor.
106 * @return Error code.
107 */
108int usbmid_spawn_interface_child(usb_device_t *parent,
109 usbmid_interface_t **iface_ret,
110 const usb_standard_device_descriptor_t *device_descriptor,
111 const usb_standard_interface_descriptor_t *interface_descriptor)
112{
113 ddf_fun_t *child = NULL;
114 char *child_name = NULL;
115 int rc;
116
117 /*
118 * Name is class name followed by interface number.
119 * The interface number shall provide uniqueness while the
120 * class name something humanly understandable.
121 */
122 int ret = asprintf(&child_name, "%s%hhu",
123 usb_str_class(interface_descriptor->interface_class),
124 interface_descriptor->interface_number);
125 if (ret < 0) {
126 return ENOMEM;
127 }
128
129 /* Create the device. */
130 child = usb_device_ddf_fun_create(parent, fun_inner, child_name);
131 free(child_name);
132 if (child == NULL) {
133 return ENOMEM;
134 }
135
136 match_id_list_t match_ids;
137 init_match_ids(&match_ids);
138
139 rc = usb_device_create_match_ids_from_interface(device_descriptor,
140 interface_descriptor, &match_ids);
141 if (rc != EOK) {
142 ddf_fun_destroy(child);
143 return rc;
144 }
145
146 list_foreach(match_ids.ids, link, match_id_t, match_id) {
147 rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
148 if (rc != EOK) {
149 clean_match_ids(&match_ids);
150 ddf_fun_destroy(child);
151 return rc;
152 }
153 }
154 clean_match_ids(&match_ids);
155 ddf_fun_set_ops(child, &child_device_ops);
156
157 usbmid_interface_t *iface = ddf_fun_data_alloc(child, sizeof(*iface));
158
159 iface->fun = child;
160 iface->interface_no = interface_descriptor->interface_number;
161 link_initialize(&iface->link);
162
163 rc = ddf_fun_bind(child);
164 if (rc != EOK) {
165 /* This takes care of match_id deallocation as well. */
166 ddf_fun_destroy(child);
167 return rc;
168 }
169 *iface_ret = iface;
170
171 return EOK;
172}
173
174/**
175 * @}
176 */
Note: See TracBrowser for help on using the repository browser.