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