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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c280d7e was c280d7e, checked in by Ondřej Hlavatý <aearsis@…>, 7 years ago

libdrv: usb iface callbacks joined

In addition to handle and current interface, it is good for the device
to know its address and speed. Also, it is expected to add some other
fields (stats, info tied to devices of specific speed and so on) in the
future. Instead of adding yet another call, join those two and let HC
fill a description structure.

  • 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 return EOK;
74}
75
76/** DDF interface of the child - USB functions. */
77static usb_iface_t child_usb_iface = {
78 .get_my_description = usb_iface_description,
79};
80
81/** Operations for children - interface functions. */
82static ddf_dev_ops_t child_device_ops = {
83 .interfaces[USB_DEV_IFACE] = &child_usb_iface
84};
85
86int usbmid_interface_destroy(usbmid_interface_t *mid_iface)
87{
88 assert(mid_iface);
89 assert_link_not_used(&mid_iface->link);
90 const int ret = ddf_fun_unbind(mid_iface->fun);
91 if (ret != EOK) {
92 return ret;
93 }
94 ddf_fun_destroy(mid_iface->fun);
95 return EOK;
96}
97
98/** Spawn new child device from one interface.
99 *
100 * @param parent Parent MID device.
101 * @param iface Interface information.
102 * @param device_descriptor Device descriptor.
103 * @param interface_descriptor Interface descriptor.
104 * @return Error code.
105 */
106int usbmid_spawn_interface_child(usb_device_t *parent,
107 usbmid_interface_t **iface_ret,
108 const usb_standard_device_descriptor_t *device_descriptor,
109 const usb_standard_interface_descriptor_t *interface_descriptor)
110{
111 ddf_fun_t *child = NULL;
112 char *child_name = NULL;
113 int rc;
114
115 /*
116 * Name is class name followed by interface number.
117 * The interface number shall provide uniqueness while the
118 * class name something humanly understandable.
119 */
120 rc = asprintf(&child_name, "%s%hhu",
121 usb_str_class(interface_descriptor->interface_class),
122 interface_descriptor->interface_number);
123 if (rc < 0) {
124 return ENOMEM;
125 }
126
127 /* Create the device. */
128 child = usb_device_ddf_fun_create(parent, fun_inner, child_name);
129 free(child_name);
130 if (child == NULL) {
131 return ENOMEM;
132 }
133
134 match_id_list_t match_ids;
135 init_match_ids(&match_ids);
136
137 rc = usb_device_create_match_ids_from_interface(device_descriptor,
138 interface_descriptor, &match_ids);
139 if (rc != EOK) {
140 ddf_fun_destroy(child);
141 return rc;
142 }
143
144 list_foreach(match_ids.ids, link, match_id_t, match_id) {
145 rc = ddf_fun_add_match_id(child, match_id->id, match_id->score);
146 if (rc != EOK) {
147 clean_match_ids(&match_ids);
148 ddf_fun_destroy(child);
149 return rc;
150 }
151 }
152 clean_match_ids(&match_ids);
153 ddf_fun_set_ops(child, &child_device_ops);
154
155 usbmid_interface_t *iface = ddf_fun_data_alloc(child, sizeof(*iface));
156
157 iface->fun = child;
158 iface->interface_no = interface_descriptor->interface_number;
159 link_initialize(&iface->link);
160
161 rc = ddf_fun_bind(child);
162 if (rc != EOK) {
163 /* This takes care of match_id deallocation as well. */
164 ddf_fun_destroy(child);
165 return rc;
166 }
167 *iface_ret = iface;
168
169 return EOK;
170}
171
172/**
173 * @}
174 */
Note: See TracBrowser for help on using the repository browser.