source: mainline/uspace/drv/test/test2/test2.c@ c631734

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

log_init() needs only one parameter

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 * Copyright (c) 2010 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/** @file
30 */
31
32#include <assert.h>
33#include <async.h>
34#include <stdio.h>
35#include <errno.h>
36#include <str_error.h>
37#include <ddf/driver.h>
38#include <ddf/log.h>
39
40#define NAME "test2"
41
42static int test2_dev_add(ddf_dev_t *dev);
43static int test2_dev_remove(ddf_dev_t *dev);
44static int test2_dev_gone(ddf_dev_t *dev);
45static int test2_fun_online(ddf_fun_t *fun);
46static int test2_fun_offline(ddf_fun_t *fun);
47
48static driver_ops_t driver_ops = {
49 .dev_add = &test2_dev_add,
50 .dev_remove = &test2_dev_remove,
51 .dev_gone = &test2_dev_gone,
52 .fun_online = &test2_fun_online,
53 .fun_offline = &test2_fun_offline
54};
55
56static driver_t test2_driver = {
57 .name = NAME,
58 .driver_ops = &driver_ops
59};
60
61/* Device soft state */
62typedef struct {
63 ddf_dev_t *dev;
64
65 ddf_fun_t *fun_a;
66 ddf_fun_t *fun_err;
67 ddf_fun_t *child;
68 ddf_fun_t *test1;
69} test2_t;
70
71/** Register child and inform user about it.
72 *
73 * @param parent Parent device.
74 * @param message Message for the user.
75 * @param name Device name.
76 * @param match_id Device match id.
77 * @param score Device match score.
78 */
79static int register_fun_verbose(ddf_dev_t *parent, const char *message,
80 const char *name, const char *match_id, int match_score, ddf_fun_t **pfun)
81{
82 ddf_fun_t *fun;
83 int rc;
84
85 ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);
86
87 fun = ddf_fun_create(parent, fun_inner, name);
88 if (fun == NULL) {
89 ddf_msg(LVL_ERROR, "Failed creating function %s", name);
90 return ENOMEM;
91 }
92
93 rc = ddf_fun_add_match_id(fun, match_id, match_score);
94 if (rc != EOK) {
95 ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
96 name);
97 ddf_fun_destroy(fun);
98 return rc;
99 }
100
101 rc = ddf_fun_bind(fun);
102 if (rc != EOK) {
103 ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
104 str_error(rc));
105 ddf_fun_destroy(fun);
106 return rc;
107 }
108
109 *pfun = fun;
110
111 ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
112 return EOK;
113}
114
115/** Simulate plugging and surprise unplugging.
116 *
117 * @param arg Parent device structure (ddf_dev_t *).
118 * @return Always EOK.
119 */
120static int plug_unplug(void *arg)
121{
122 test2_t *test2 = (test2_t *) arg;
123 ddf_fun_t *fun_a;
124 int rc;
125
126 async_usleep(1000);
127
128 (void) register_fun_verbose(test2->dev, "child driven by the same task",
129 "child", "virtual&test2", 10, &test2->child);
130 (void) register_fun_verbose(test2->dev, "child driven by test1",
131 "test1", "virtual&test1", 10, &test2->test1);
132
133 fun_a = ddf_fun_create(test2->dev, fun_exposed, "a");
134 if (fun_a == NULL) {
135 ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
136 return ENOMEM;
137 }
138
139 rc = ddf_fun_bind(fun_a);
140 if (rc != EOK) {
141 ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
142 return rc;
143 }
144
145 ddf_fun_add_to_category(fun_a, "virtual");
146 test2->fun_a = fun_a;
147
148 async_usleep(10000000);
149
150 ddf_msg(LVL_NOTE, "Unbinding function test1.");
151 ddf_fun_unbind(test2->test1);
152 async_usleep(1000000);
153 ddf_msg(LVL_NOTE, "Unbinding function child.");
154 ddf_fun_unbind(test2->child);
155
156 return EOK;
157}
158
159static int fun_remove(ddf_fun_t *fun, const char *name)
160{
161 int rc;
162
163 ddf_msg(LVL_DEBUG, "fun_remove(%p, '%s')", fun, name);
164 rc = ddf_fun_offline(fun);
165 if (rc != EOK) {
166 ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name);
167 return rc;
168 }
169
170 rc = ddf_fun_unbind(fun);
171 if (rc != EOK) {
172 ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
173 return rc;
174 }
175
176 ddf_fun_destroy(fun);
177 return EOK;
178}
179
180static int fun_unbind(ddf_fun_t *fun, const char *name)
181{
182 int rc;
183
184 ddf_msg(LVL_DEBUG, "fun_unbind(%p, '%s')", fun, name);
185 rc = ddf_fun_unbind(fun);
186 if (rc != EOK) {
187 ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
188 return rc;
189 }
190
191 ddf_fun_destroy(fun);
192 return EOK;
193}
194
195static int test2_dev_add(ddf_dev_t *dev)
196{
197 test2_t *test2;
198 const char *dev_name = ddf_dev_get_name(dev);
199
200 ddf_msg(LVL_DEBUG, "test2_dev_add(name=\"%s\", handle=%d)",
201 dev_name, (int) ddf_dev_get_handle(dev));
202
203 test2 = ddf_dev_data_alloc(dev, sizeof(test2_t));
204 if (test2 == NULL) {
205 ddf_msg(LVL_ERROR, "Failed allocating soft state.");
206 return ENOMEM;
207 }
208
209 test2->dev = dev;
210
211 if (str_cmp(dev_name, "child") != 0) {
212 fid_t postpone = fibril_create(plug_unplug, test2);
213 if (postpone == 0) {
214 ddf_msg(LVL_ERROR, "fibril_create() failed.");
215 return ENOMEM;
216 }
217 fibril_add_ready(postpone);
218 } else {
219 (void) register_fun_verbose(dev, "child without available driver",
220 "ERROR", "non-existent.match.id", 10, &test2->fun_err);
221 }
222
223 return EOK;
224}
225
226static int test2_dev_remove(ddf_dev_t *dev)
227{
228 test2_t *test2 = (test2_t *)ddf_dev_data_get(dev);
229 int rc;
230
231 ddf_msg(LVL_DEBUG, "test2_dev_remove(%p)", dev);
232
233 if (test2->fun_a != NULL) {
234 rc = fun_remove(test2->fun_a, "a");
235 if (rc != EOK)
236 return rc;
237 }
238
239 if (test2->fun_err != NULL) {
240 rc = fun_remove(test2->fun_err, "ERROR");
241 if (rc != EOK)
242 return rc;
243 }
244
245 if (test2->child != NULL) {
246 rc = fun_remove(test2->child, "child");
247 if (rc != EOK)
248 return rc;
249 }
250
251 if (test2->test1 != NULL) {
252 rc = fun_remove(test2->test1, "test1");
253 if (rc != EOK)
254 return rc;
255 }
256
257 return EOK;
258}
259
260static int test2_dev_gone(ddf_dev_t *dev)
261{
262 test2_t *test2 = (test2_t *)ddf_dev_data_get(dev);
263 int rc;
264
265 ddf_msg(LVL_DEBUG, "test2_dev_gone(%p)", dev);
266
267 if (test2->fun_a != NULL) {
268 rc = fun_unbind(test2->fun_a, "a");
269 if (rc != EOK)
270 return rc;
271 }
272
273 if (test2->fun_err != NULL) {
274 rc = fun_unbind(test2->fun_err, "ERROR");
275 if (rc != EOK)
276 return rc;
277 }
278
279 if (test2->child != NULL) {
280 rc = fun_unbind(test2->child, "child");
281 if (rc != EOK)
282 return rc;
283 }
284
285 if (test2->test1 != NULL) {
286 rc = fun_unbind(test2->test1, "test1");
287 if (rc != EOK)
288 return rc;
289 }
290
291 return EOK;
292}
293
294
295static int test2_fun_online(ddf_fun_t *fun)
296{
297 ddf_msg(LVL_DEBUG, "test2_fun_online()");
298 return ddf_fun_online(fun);
299}
300
301static int test2_fun_offline(ddf_fun_t *fun)
302{
303 ddf_msg(LVL_DEBUG, "test2_fun_offline()");
304 return ddf_fun_offline(fun);
305}
306
307int main(int argc, char *argv[])
308{
309 printf(NAME ": HelenOS test2 virtual device driver\n");
310 ddf_log_init(NAME);
311 return ddf_driver_main(&test2_driver);
312}
313
314
Note: See TracBrowser for help on using the repository browser.