source: mainline/uspace/drv/test/test2/test2.c@ 09187c6e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 09187c6e 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
RevLine 
[c245f16e]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>
[af6b5157]33#include <async.h>
[c245f16e]34#include <stdio.h>
35#include <errno.h>
36#include <str_error.h>
[af6b5157]37#include <ddf/driver.h>
[fc51296]38#include <ddf/log.h>
[c245f16e]39
40#define NAME "test2"
41
[0c0f823b]42static int test2_dev_add(ddf_dev_t *dev);
[7fff38c1]43static int test2_dev_remove(ddf_dev_t *dev);
[80a96d2]44static int test2_dev_gone(ddf_dev_t *dev);
[7fff38c1]45static int test2_fun_online(ddf_fun_t *fun);
46static int test2_fun_offline(ddf_fun_t *fun);
[c245f16e]47
48static driver_ops_t driver_ops = {
[0c0f823b]49 .dev_add = &test2_dev_add,
[7fff38c1]50 .dev_remove = &test2_dev_remove,
[80a96d2]51 .dev_gone = &test2_dev_gone,
[7fff38c1]52 .fun_online = &test2_fun_online,
53 .fun_offline = &test2_fun_offline
[c245f16e]54};
55
[bab6388]56static driver_t test2_driver = {
[c245f16e]57 .name = NAME,
58 .driver_ops = &driver_ops
59};
60
[7fff38c1]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
[c245f16e]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 */
[83a2f43]79static int register_fun_verbose(ddf_dev_t *parent, const char *message,
[7fff38c1]80 const char *name, const char *match_id, int match_score, ddf_fun_t **pfun)
[c245f16e]81{
[83a2f43]82 ddf_fun_t *fun;
[cd0684d]83 int rc;
[c245f16e]84
[ebcb05a]85 ddf_msg(LVL_DEBUG, "Registering function `%s': %s.", name, message);
[c245f16e]86
[cd0684d]87 fun = ddf_fun_create(parent, fun_inner, name);
88 if (fun == NULL) {
[ebcb05a]89 ddf_msg(LVL_ERROR, "Failed creating function %s", name);
[cd0684d]90 return ENOMEM;
91 }
92
93 rc = ddf_fun_add_match_id(fun, match_id, match_score);
94 if (rc != EOK) {
[ebcb05a]95 ddf_msg(LVL_ERROR, "Failed adding match IDs to function %s",
[fc51296]96 name);
[cd0684d]97 ddf_fun_destroy(fun);
98 return rc;
[c245f16e]99 }
[cd0684d]100
101 rc = ddf_fun_bind(fun);
102 if (rc != EOK) {
[ebcb05a]103 ddf_msg(LVL_ERROR, "Failed binding function %s: %s", name,
[cd0684d]104 str_error(rc));
105 ddf_fun_destroy(fun);
106 return rc;
107 }
108
[7fff38c1]109 *pfun = fun;
110
[ebcb05a]111 ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
[cd0684d]112 return EOK;
[c245f16e]113}
114
[80a96d2]115/** Simulate plugging and surprise unplugging.
[c245f16e]116 *
[83a2f43]117 * @param arg Parent device structure (ddf_dev_t *).
[c245f16e]118 * @return Always EOK.
119 */
[80a96d2]120static int plug_unplug(void *arg)
[c245f16e]121{
[7fff38c1]122 test2_t *test2 = (test2_t *) arg;
[83a2f43]123 ddf_fun_t *fun_a;
[97a62fe]124 int rc;
[c245f16e]125
126 async_usleep(1000);
127
[7fff38c1]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);
[c245f16e]132
[7fff38c1]133 fun_a = ddf_fun_create(test2->dev, fun_exposed, "a");
[97a62fe]134 if (fun_a == NULL) {
[ebcb05a]135 ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
[97a62fe]136 return ENOMEM;
137 }
[8b1e15ac]138
[97a62fe]139 rc = ddf_fun_bind(fun_a);
140 if (rc != EOK) {
[ebcb05a]141 ddf_msg(LVL_ERROR, "Failed binding function 'a'.");
[97a62fe]142 return rc;
143 }
[8b1e15ac]144
[1dc4a5e]145 ddf_fun_add_to_category(fun_a, "virtual");
[7fff38c1]146 test2->fun_a = fun_a;
[c245f16e]147
[80a96d2]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
[c245f16e]156 return EOK;
157}
158
[7fff38c1]159static int fun_remove(ddf_fun_t *fun, const char *name)
160{
161 int rc;
162
[deac215e]163 ddf_msg(LVL_DEBUG, "fun_remove(%p, '%s')", fun, name);
[7fff38c1]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
[80a96d2]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
[0c0f823b]195static int test2_dev_add(ddf_dev_t *dev)
[c245f16e]196{
[7fff38c1]197 test2_t *test2;
[56fd7cf]198 const char *dev_name = ddf_dev_get_name(dev);
[7fff38c1]199
[0c0f823b]200 ddf_msg(LVL_DEBUG, "test2_dev_add(name=\"%s\", handle=%d)",
[56fd7cf]201 dev_name, (int) ddf_dev_get_handle(dev));
[c245f16e]202
[7fff38c1]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
[56fd7cf]211 if (str_cmp(dev_name, "child") != 0) {
[80a96d2]212 fid_t postpone = fibril_create(plug_unplug, test2);
[86d7bfa]213 if (postpone == 0) {
[ebcb05a]214 ddf_msg(LVL_ERROR, "fibril_create() failed.");
[86d7bfa]215 return ENOMEM;
216 }
[c245f16e]217 fibril_add_ready(postpone);
218 } else {
[cd0684d]219 (void) register_fun_verbose(dev, "child without available driver",
[7fff38c1]220 "ERROR", "non-existent.match.id", 10, &test2->fun_err);
[c245f16e]221 }
222
223 return EOK;
224}
225
[7fff38c1]226static int test2_dev_remove(ddf_dev_t *dev)
227{
[56fd7cf]228 test2_t *test2 = (test2_t *)ddf_dev_data_get(dev);
[7fff38c1]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
[80a96d2]260static int test2_dev_gone(ddf_dev_t *dev)
261{
[56fd7cf]262 test2_t *test2 = (test2_t *)ddf_dev_data_get(dev);
[80a96d2]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
[7fff38c1]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
[c245f16e]307int main(int argc, char *argv[])
308{
309 printf(NAME ": HelenOS test2 virtual device driver\n");
[267f235]310 ddf_log_init(NAME);
[83a2f43]311 return ddf_driver_main(&test2_driver);
[c245f16e]312}
313
314
Note: See TracBrowser for help on using the repository browser.