source: mainline/uspace/drv/usbmid/usbmid.c@ 3ae93a8

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

Add USB multi interface device driver

Incomplete implementation of a pseudo-bus driver that spawns children
devices for each interface in multi interface device.

WARNING: does not work as the child device does not learn its USB address.

  • Property mode set to 100644
File size: 4.5 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/pipes.h>
41#include <usb/classes/classes.h>
42#include <usb/recognise.h>
43#include "usbmid.h"
44
45/** Callback for DDF USB interface. */
46static int iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
47{
48 device_t *parent = dev->parent;
49
50 usb_log_debug("iface_get_hc_handle(dev=%zu)\n", (size_t) dev->handle);
51
52 if (parent && parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
53 usb_iface_t *usb_iface
54 = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
55 assert(usb_iface != NULL);
56 if (usb_iface->get_hc_handle) {
57 int rc = usb_iface->get_hc_handle(parent, handle);
58 return rc;
59 }
60 return ENOTSUP;
61 } else {
62 return usb_hc_find(dev->handle, handle);
63 }
64}
65
66static usb_iface_t usb_iface = {
67 .get_hc_handle = iface_get_hc_handle
68};
69
70static device_ops_t device_ops = {
71 .interfaces[USB_DEV_IFACE] = &usb_iface
72};
73
74/** Create new USB multi interface device.
75 *
76 * @param dev Backing generic DDF device.
77 * @return New USB MID device.
78 * @retval NULL Error occured.
79 */
80usbmid_device_t *usbmid_device_create(device_t *dev)
81{
82 usbmid_device_t *mid = malloc(sizeof(usbmid_device_t));
83 if (mid == NULL) {
84 return NULL;
85 }
86
87 int rc;
88 rc = usb_device_connection_initialize_from_device(&mid->wire, dev);
89 if (rc != EOK) {
90 free(mid);
91 return NULL;
92 }
93
94 rc = usb_endpoint_pipe_initialize_default_control(&mid->ctrl_pipe,
95 &mid->wire);
96 if (rc != EOK) {
97 free(mid);
98 return NULL;
99 }
100
101 mid->dev = dev;
102 dev->ops = &device_ops;
103
104 return mid;
105}
106
107
108/** Spawn new child device from one interface.
109 *
110 * @param parent Parent MID device.
111 * @param device_descriptor Device descriptor.
112 * @param interface_descriptor Interface descriptor.
113 * @return Error code.
114 */
115int usbmid_spawn_interface_child(usbmid_device_t *parent,
116 const usb_standard_device_descriptor_t *device_descriptor,
117 const usb_standard_interface_descriptor_t *interface_descriptor)
118{
119 device_t *child = NULL;
120 char *child_name = NULL;
121 int rc;
122
123 /* Create the device. */
124 child = create_device();
125 if (child == NULL) {
126 rc = ENOMEM;
127 goto error_leave;
128 }
129
130 /*
131 * Name is class name followed by interface number.
132 * The interface number shall provide uniqueness while the
133 * class name something humanly understandable.
134 */
135 rc = asprintf(&child_name, "%s%d",
136 usb_str_class(interface_descriptor->interface_class),
137 (int) interface_descriptor->interface_number);
138 if (rc < 0) {
139 goto error_leave;
140 }
141 child->parent = parent->dev;
142 child->name = child_name;
143 child->ops = &device_ops;
144
145 rc = usb_device_create_match_ids_from_interface(interface_descriptor,
146 &child->match_ids);
147 if (rc != EOK) {
148 goto error_leave;
149 }
150
151 rc = child_device_register(child, parent->dev);
152 if (rc != EOK) {
153 goto error_leave;
154 }
155
156 return EOK;
157
158error_leave:
159 if (child != NULL) {
160 child->name = NULL;
161 /* This takes care of match_id deallocation as well. */
162 delete_device(child);
163 }
164 if (child_name != NULL) {
165 free(child_name);
166 }
167
168 return rc;
169}
170
171/**
172 * @}
173 */
Note: See TracBrowser for help on using the repository browser.