]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/virt/vdevice.cc
update
[l4.git] / l4 / pkg / io / server / src / virt / 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_pm-ops.h>
18 #include <l4/vbus/vbus_types.h>
19
20 namespace Vi {
21
22 Device::Dev_set Device::__devs;
23
24 void
25 Device::dump(int indent) const
26 {
27   printf("%*.s%s: [%s]\n", indent, " ", name(), typeid(*this).name());
28 }
29
30 bool
31 Device::resource_allocated(Resource const *r) const
32 {
33   if (!parent())
34     return false;
35
36   return parent()->resource_allocated(r);
37 }
38
39
40 Device *
41 Device::get_dev_by_id(l4vbus_device_handle_t id)
42 {
43   if (id == 0)
44     return this;
45   else if (__devs.find(id) != __devs.end())
46     return (Device*)id;
47   else
48     return 0;
49 }
50
51 struct Match_hid
52 {
53   char const *hid;
54   Device mutable *dev;
55
56   int operator () (Device *d) const
57   {
58     char const *h = d->hid();
59     if (h && strcmp(h, hid) == 0)
60       {
61         dev = d;
62         return 1;
63       }
64     return 0;
65   }
66 };
67
68 int
69 Device::get_by_hid(L4::Ipc::Iostream &ios)
70 {
71   l4vbus_device_handle_t child;
72   unsigned long sz;
73   char const *hid = 0;
74
75   int depth;
76
77   ios >> child >> depth >> L4::Ipc::buf_in(hid, sz);
78
79   //printf("look for '%s' in %p(%x) from %x\n", hid, this, _id, start);
80   if (!hid || !sz)
81     return -L4_ENOENT;
82
83   iterator c;
84   if (!child)
85     c = begin(depth);
86   else if ((c = iterator(this, get_dev_by_id(child), depth)) != end())
87     ++c;
88
89   if (c == end())
90     return -L4_ENODEV;
91
92
93   Match_hid mh;
94   mh.hid = hid;
95   mh.dev = 0;
96
97   for (; c != end(); ++c)
98     if (mh(*c) == 1)
99       return dynamic_cast<Device*>(*c)->vbus_get_device(ios);
100
101   return -L4_ENOENT;
102 }
103
104
105 int
106 Device::vbus_get_device(L4::Ipc::Iostream &ios)
107 {
108   l4vbus_device_t inf;
109   inf.num_resources = resources()->size();
110   if (hid())
111     {
112       strncpy(inf.name, name(), sizeof(inf.name));
113       inf.name[sizeof(inf.name) - 1] = 0;
114     }
115   else
116     *inf.name = 0;
117   inf.type = ~0;
118   inf.flags = 0;
119   if (children())
120     inf.flags |= L4VBUS_DEVICE_F_CHILDREN;
121
122   ios << l4vbus_device_handle_t(this);
123   ios.put(inf);
124   return L4_EOK;
125 }
126
127 int
128 Device::vdevice_dispatch(l4_umword_t obj, l4_uint32_t func, L4::Ipc::Iostream &ios)
129 {
130   if (func & L4vbus_vdevice_generic)
131     {
132       switch (func)
133         {
134         case L4vbus_vdevice_hid:
135             {
136               char const *h = hid();
137               if (!h)
138                 return -L4_ENOSYS;
139
140               ios << h;
141               return L4_EOK;
142             }
143         case L4vbus_vdevice_adr:
144             {
145               l4_uint32_t a = adr();
146               if (a == l4_uint32_t(~0))
147                 return -L4_ENOSYS;
148
149               ios << a;
150               return L4_EOK;
151             }
152         case L4vbus_vdevice_get_by_hid:
153           return get_by_hid(ios);
154
155         case L4vbus_vdevice_get_next:
156             {
157               l4vbus_device_handle_t child;
158               int depth;
159               ios >> child >> depth;
160
161               iterator c;
162               if (!child)
163                 c = begin(depth);
164               else
165                 c = ++iterator(this, get_dev_by_id(child), depth);
166
167               if (c == end())
168                 return -L4_ENODEV;
169
170               return dynamic_cast<Device*>(*c)->vbus_get_device(ios);
171             }
172
173         case L4vbus_vdevice_get_resource:
174             {
175               int res_idx;
176               ios >> res_idx;
177               if (res_idx < 0 || (unsigned)res_idx >= resources()->size())
178                 return -L4_ENOENT;
179
180               Resource *r = resources()->at(res_idx);
181               l4vbus_resource_t res;
182               res.start = r->start();
183               res.end = r->end();
184               res.type = r->type();
185               res.flags = 0;
186               res.provider = r->provider_device_handle();
187               res.id = r->id();
188               ios.put(res);
189               return L4_EOK;
190             }
191
192         case L4vbus_vdevice_is_compatible:
193             {
194               unsigned long sz;
195               char const *cid = 0;
196               ios >> L4::Ipc::buf_in(cid, sz);
197               return match_cid(cxx::String(cid, strnlen(cid, sz))) ? 1 : 0;
198             }
199
200         case L4vbus_vdevice_get_hid:
201           if (char const *_hid = hid())
202             ios << _hid;
203           else
204             ios << "";
205
206           return L4_EOK;
207
208         case L4VBUS_PM_OP_SUSPEND:
209           return pm_suspend();
210
211         case L4VBUS_PM_OP_RESUME:
212           return pm_resume();
213
214         default: return -L4_ENOSYS;
215         }
216     }
217
218   for (Feature_list::const_iterator i = _features.begin();
219        i != _features.end(); ++i)
220     {
221       int e = (*i)->dispatch(obj, func, ios);
222       if (e != -L4_ENOSYS)
223         return e;
224     }
225
226   return -L4_ENOSYS;
227 }
228
229 }