source: mainline/uspace/drv/usbmid/usbmid.c@ dde8ca4

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

Merge mainline changes (DDF refactoring)

This merge includes DDF refactoring that brought multifunctional devices
(i.e. ddf_dev_t and ddf_fun_t). Please, see ticket #295 at HelenOS
upstream Trac.

The conflicts themselves were easy to solve (merely several renamings).

Changes to USB subsystem:

  • drivers uses ddf_dev_t and ddf_fun_t
  • different signatures of many library functions
  • several hacks around communication with parent device (now the communication is clearer and somehow what we have now is hack about other hacks)
    • will repair and clean later
  • maybe added some extra debugging messages (the diff has about 240K, and I admit I have no energy to double check that)

WARNING:

  • the diff is VERY long, recommended is viewing partial diffs of the merge (i.e. merges in mainline branch that lead to the parent one)
  • merging with your branches might involve huge renamings, sorry, no other way is possible

BUGS:

  • hub driver will not work (no function created)

GOOD NEWS:

  • QEMU keyboard seems to work with QEMU 0.13 and 0.14
  • we are up-to-date with mainline again
  • Property mode set to 100644
File size: 5.8 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(ddf_fun_t *fun, devman_handle_t handle,
48 usb_address_t *address)
49{
50 return usb_iface_get_address_hub_impl(fun, handle, address);
51}
52
53/** Callback for DDF USB interface. */
54static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle,
55 int *iface_no)
56{
57 assert(fun);
58
59 usbmid_interface_t *iface = fun->driver_data;
60 assert(iface);
61
62 if (iface_no != NULL) {
63 *iface_no = iface->interface_no;
64 }
65
66 return EOK;
67}
68
69static usb_iface_t child_usb_iface = {
70 .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
71 .get_address = usb_iface_get_address_impl,
72 .get_interface = usb_iface_get_interface_impl
73};
74
75
76static ddf_dev_ops_t child_device_ops = {
77 .interfaces[USB_DEV_IFACE] = &child_usb_iface
78};
79
80static ddf_dev_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(ddf_dev_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 (void) &mid_device_ops;
119
120 return mid;
121}
122
123/** Create new interface for USB MID device.
124 *
125 * @param dev Backing generic DDF child device (representing interface).
126 * @param iface_no Interface number.
127 * @return New interface.
128 * @retval NULL Error occured.
129 */
130usbmid_interface_t *usbmid_interface_create(ddf_fun_t *fun, int iface_no)
131{
132 usbmid_interface_t *iface = malloc(sizeof(usbmid_interface_t));
133 if (iface == NULL) {
134 usb_log_error("Out of memory (wanted %zuB).\n",
135 sizeof(usbmid_interface_t));
136 return NULL;
137 }
138
139 iface->fun = fun;
140 iface->interface_no = iface_no;
141
142 return iface;
143}
144
145
146/** Spawn new child device from one interface.
147 *
148 * @param parent Parent MID device.
149 * @param device_descriptor Device descriptor.
150 * @param interface_descriptor Interface descriptor.
151 * @return Error code.
152 */
153int usbmid_spawn_interface_child(usbmid_device_t *parent,
154 const usb_standard_device_descriptor_t *device_descriptor,
155 const usb_standard_interface_descriptor_t *interface_descriptor)
156{
157 ddf_fun_t *child = NULL;
158 char *child_name = NULL;
159 usbmid_interface_t *child_as_interface = NULL;
160 int rc;
161
162 /*
163 * Name is class name followed by interface number.
164 * The interface number shall provide uniqueness while the
165 * class name something humanly understandable.
166 */
167 rc = asprintf(&child_name, "%s%d",
168 usb_str_class(interface_descriptor->interface_class),
169 (int) interface_descriptor->interface_number);
170 if (rc < 0) {
171 goto error_leave;
172 }
173
174 /* Create the device. */
175 child = ddf_fun_create(parent->dev, fun_inner, child_name);
176 if (child == NULL) {
177 rc = ENOMEM;
178 goto error_leave;
179 }
180
181
182
183 child_as_interface = usbmid_interface_create(child,
184 (int) interface_descriptor->interface_number);
185 if (child_as_interface == NULL) {
186 rc = ENOMEM;
187 goto error_leave;
188 }
189
190 child->driver_data = child_as_interface;
191 child->ops = &child_device_ops;
192
193 rc = usb_device_create_match_ids_from_interface(device_descriptor,
194 interface_descriptor,
195 &child->match_ids);
196 if (rc != EOK) {
197 goto error_leave;
198 }
199
200 rc = ddf_fun_bind(child);
201 if (rc != EOK) {
202 goto error_leave;
203 }
204
205 return EOK;
206
207error_leave:
208 if (child != NULL) {
209 child->name = NULL;
210 /* This takes care of match_id deallocation as well. */
211 ddf_fun_destroy(child);
212 }
213 if (child_name != NULL) {
214 free(child_name);
215 }
216 if (child_as_interface != NULL) {
217 free(child_as_interface);
218 }
219
220 return rc;
221}
222
223/**
224 * @}
225 */
Note: See TracBrowser for help on using the repository browser.