]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/vdevice.cc
e52494cbcabff802700173d4f47c7df9eaab6e3a
[l4.git] / l4 / pkg / io / server / src / vdevice.cc
1 /*
2  * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *          Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #include "vdevice.h"
11
12 #include <cstring>
13 #include <cstdio>
14
15 #include "device.h"
16 #include <l4/vbus/vdevice-ops.h>
17 #include <l4/vbus/vbus_types.h>
18
19 namespace Vi {
20
21 Device::Dev_set Device::__devs;
22
23 bool
24 Device::resource_allocated(Resource const *r) const
25 {
26   if (!parent())
27     return false;
28
29   return parent()->resource_allocated(r);
30 }
31
32
33 Device *
34 Device::get_dev_by_id(l4vbus_device_handle_t id)
35 {
36   if (id == 0)
37     return this;
38   else if (__devs.find(id) != __devs.end())
39     return (Device*)id;
40   else
41     return 0;
42 }
43
44 struct Match_hid
45 {
46   char const *hid;
47   Device mutable *dev;
48
49   int operator () (Device *d) const
50   {
51     char const *h = d->hid();
52     if (h && strcmp(h, hid) == 0)
53       {
54         dev = d;
55         return 1;
56       }
57     return 0;
58   }
59 };
60
61 int
62 Device::get_by_hid(L4::Ipc_iostream &ios)
63 {
64   l4vbus_device_handle_t child;
65   unsigned long sz;
66   char const *hid = 0;
67
68   int depth;
69
70   ios >> child >> depth >> L4::ipc_buf_in(hid, sz);
71
72   //printf("look for '%s' in %p(%x) from %x\n", hid, this, _id, start);
73   if (!hid || !sz)
74     return -L4_ENOENT;
75
76   iterator c;
77   if (!child)
78     c = begin(depth);
79   else if ((c = iterator(this, get_dev_by_id(child), depth)) != end())
80     ++c;
81
82   if (c == end())
83     return -L4_ENODEV;
84
85
86   Match_hid mh;
87   mh.hid = hid;
88   mh.dev = 0;
89
90   for (; c != end(); ++c)
91     if (mh(*c) == 1)
92       {
93         ios << l4vbus_device_handle_t(mh.dev);
94         return L4_EOK;
95       }
96
97   return -L4_ENOENT;
98 }
99
100
101 int
102 Device::vbus_get_device(L4::Ipc_iostream &ios)
103 {
104   l4vbus_device_t inf;
105   inf.num_resources = resources()->size();
106   if (hid())
107     {
108       strncpy(inf.name, hid(), sizeof(inf.name));
109       inf.name[sizeof(inf.name) - 1] = 0;
110     }
111   else
112     *inf.name = 0;
113   inf.type = ~0;
114   inf.flags = 0;
115   if (children())
116     inf.flags |= L4VBUS_DEVICE_F_CHILDREN;
117
118   ios << l4vbus_device_handle_t(this);
119   ios.put(inf);
120   return L4_EOK;
121 }
122
123 int
124 Device::vdevice_dispatch(l4_umword_t obj, l4_uint32_t func, L4::Ipc_iostream &ios)
125 {
126   if (func & L4vbus_vdevice_generic)
127     {
128       switch (func)
129         {
130         case L4vbus_vdevice_hid:
131             {
132               char const *h = hid();
133               if (!h)
134                 return -L4_ENOSYS;
135
136               ios << h;
137               return L4_EOK;
138             }
139         case L4vbus_vdevice_adr:
140             {
141               l4_uint32_t a = adr();
142               if (a == l4_uint32_t(~0))
143                 return -L4_ENOSYS;
144
145               ios << a;
146               return L4_EOK;
147             }
148         case L4vbus_vdevice_get_by_hid:
149           return get_by_hid(ios);
150
151         case L4vbus_vdevice_get_next:
152             {
153               l4vbus_device_handle_t child;
154               int depth;
155               ios >> child >> depth;
156
157               iterator c;
158               if (!child)
159                 c = begin(depth);
160               else
161                 c = ++iterator(this, get_dev_by_id(child), depth);
162
163               if (c == end())
164                 return -L4_ENODEV;
165
166               return dynamic_cast<Device*>(*c)->vbus_get_device(ios);
167             }
168
169         case L4vbus_vdevice_get_resource:
170             {
171               int res_idx;
172               ios >> res_idx;
173               Adr_resource *r = dynamic_cast<Adr_resource*>(resources()->elem(res_idx));
174
175               if (!r)
176                 return -L4_ENOENT;
177
178               l4vbus_resource_t res;
179               Adr_resource::Data d = r->data();
180               res.start = d.start();
181               res.end = d.end();
182               res.type = r->type();
183               res.flags = 0;
184               ios.put(res);
185               return L4_EOK;
186             }
187
188         default: return -L4_ENOSYS;
189         }
190     }
191
192   for (Feature_list::const_iterator i = _features.begin();
193        i != _features.end(); ++i)
194     {
195       int e = (*i)->dispatch(obj, func, ios);
196       if (e != -L4_ENOSYS)
197         return e;
198     }
199
200   return -L4_ENOSYS;
201 }
202
203 }