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

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

usbmid: fix leaking exchange

  • Property mode set to 100644
File size: 4.9 KB
RevLine 
[3ae93a8]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 */
[56fd7cf]32
[3ae93a8]33/**
34 * @file
35 * Helper functions.
36 */
[58563585]37
[3ae93a8]38#include <errno.h>
39#include <str_error.h>
40#include <stdlib.h>
41#include <usb_iface.h>
[7d521e24]42#include <usb/dev/pipes.h>
[3ae93a8]43#include <usb/classes/classes.h>
[7d521e24]44#include <usb/dev/recognise.h>
[3ae93a8]45#include "usbmid.h"
[6fe7683]46
[c280d7e]47/**
48 * Get USB device description by calling HC and altering the interface field.
[4ca778b]49 *
50 * @param[in] fun Device function the operation is running on.
[c280d7e]51 * @param[out] desc Device descriptor.
[4ca778b]52 * @return Error code.
53 */
[c280d7e]54static int usb_iface_description(ddf_fun_t *fun, usb_device_desc_t *desc)
[8ba18c6]55{
[56fd7cf]56 usbmid_interface_t *iface = ddf_fun_data_get(fun);
[8ba18c6]57 assert(iface);
[c280d7e]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);
[8ba18c6]67
[c280d7e]68 if (ret == EOK && desc) {
69 *desc = tmp_desc;
70 desc->iface = iface->interface_no;
71 }
[8ba18c6]72
[4c3fef4]73 usb_device_bus_exchange_end(exch);
74
[8ba18c6]75 return EOK;
76}
77
[6fe7683]78/** DDF interface of the child - USB functions. */
[b68b279]79static usb_iface_t child_usb_iface = {
[c280d7e]80 .get_my_description = usb_iface_description,
[b68b279]81};
82
[a6add7a]83/** Operations for children - interface functions. */
[eb1a2f4]84static ddf_dev_ops_t child_device_ops = {
[b68b279]85 .interfaces[USB_DEV_IFACE] = &child_usb_iface
[3ae93a8]86};
87
[38e68ab]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}
[3ae93a8]99
100/** Spawn new child device from one interface.
101 *
102 * @param parent Parent MID device.
[ecb107b]103 * @param iface Interface information.
[3ae93a8]104 * @param device_descriptor Device descriptor.
105 * @param interface_descriptor Interface descriptor.
106 * @return Error code.
107 */
[fcafa04]108int usbmid_spawn_interface_child(usb_device_t *parent,
[9e2132a]109 usbmid_interface_t **iface_ret,
[3ae93a8]110 const usb_standard_device_descriptor_t *device_descriptor,
111 const usb_standard_interface_descriptor_t *interface_descriptor)
112{
[eb1a2f4]113 ddf_fun_t *child = NULL;
[3ae93a8]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 */
[8be7819]122 rc = asprintf(&child_name, "%s%hhu",
[3ae93a8]123 usb_str_class(interface_descriptor->interface_class),
[8be7819]124 interface_descriptor->interface_number);
[3ae93a8]125 if (rc < 0) {
[359d96f]126 return ENOMEM;
[3ae93a8]127 }
[8ba18c6]128
[eb1a2f4]129 /* Create the device. */
[6785b538]130 child = usb_device_ddf_fun_create(parent, fun_inner, child_name);
[359d96f]131 free(child_name);
[eb1a2f4]132 if (child == NULL) {
[359d96f]133 return ENOMEM;
[eb1a2f4]134 }
135
[56fd7cf]136 match_id_list_t match_ids;
137 init_match_ids(&match_ids);
138
[51f0e410]139 rc = usb_device_create_match_ids_from_interface(device_descriptor,
[56fd7cf]140 interface_descriptor, &match_ids);
[3ae93a8]141 if (rc != EOK) {
[359d96f]142 ddf_fun_destroy(child);
143 return rc;
[3ae93a8]144 }
145
[feeac0d]146 list_foreach(match_ids.ids, link, match_id_t, match_id) {
[56fd7cf]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);
[9e2132a]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);
[56fd7cf]162
[eb1a2f4]163 rc = ddf_fun_bind(child);
[3ae93a8]164 if (rc != EOK) {
165 /* This takes care of match_id deallocation as well. */
[eb1a2f4]166 ddf_fun_destroy(child);
[359d96f]167 return rc;
[3ae93a8]168 }
[9e2132a]169 *iface_ret = iface;
[5153b58]170
[359d96f]171 return EOK;
[3ae93a8]172}
173
174/**
175 * @}
176 */
Note: See TracBrowser for help on using the repository browser.