5 static struct devman_device
*devman_dev_add_child(struct devman_device
6 *parent
, struct devman_device_info
*devinf
);
7 static struct devman_device
*_find_dev(struct devman_device
*dev
, int
9 static int devman_dev_add_info(struct devman_device
*dev
, struct
10 devman_device_info_entry
*entry
, char *buf
);
11 static ssize_t
devman_event_read(char *ptr
, size_t len
, off_t offset
, void
14 static int devman_del_device(struct devman_device
*dev
);
16 static int next_device_id
= 1;
18 static struct inode_stat default_dir_stat
= {
19 /* .mode = */ S_IFDIR
| S_IRUSR
| S_IRGRP
| S_IROTH
,
26 static struct inode_stat default_file_stat
= {
27 /* .mode = */ S_IFREG
| S_IRUSR
| S_IRGRP
| S_IROTH
,
35 static struct devman_device root_dev
;
36 static struct devman_event_inode event_inode_data
= {
37 TAILQ_HEAD_INITIALIZER(event_inode_data
.event_queue
),
39 static struct devman_inode event_inode
;
41 /*===========================================================================*
42 * devman_generate_path *
43 *===========================================================================*/
45 devman_generate_path(char* buf
, int len
, struct devman_device
*dev
)
48 const char * name
= ".";
49 const char * sep
= "/";
52 res
= devman_generate_path(buf
, len
, dev
->parent
);
56 name
= get_inode_name(dev
->inode
.inode
);
61 if (strlen(buf
) + strlen(name
) + strlen(sep
) + 1 > len
) {
71 /*===========================================================================*
72 * devman_device_add_event *
73 *===========================================================================*/
75 devman_device_add_event(struct devman_device
* dev
)
77 struct devman_event
* event
;
78 char buf
[12]; /* this fits the device ID " 0xXXXXXXXX" */
81 event
= malloc(sizeof(struct devman_event
));
84 panic("devman_device_remove_event: out of memory\n");
87 memset(event
, 0, sizeof(*event
));
89 strncpy(event
->data
, ADD_STRING
, DEVMAN_STRING_LEN
- 1);
91 res
= devman_generate_path(event
->data
, DEVMAN_STRING_LEN
- 11 , dev
);
94 panic("devman_device_add_event: "
95 "devman_generate_path failed: (%d)\n", res
);
98 snprintf(buf
, 12, " 0x%08x", dev
->dev_id
);
99 strcat(event
->data
,buf
);
101 TAILQ_INSERT_HEAD(&event_inode_data
.event_queue
, event
, events
);
104 /*===========================================================================*
105 * devman_device_remove_event *
106 *===========================================================================*/
108 devman_device_remove_event(struct devman_device
* dev
)
110 struct devman_event
* event
;
111 char buf
[12]; /* this fits the device ID " 0xXXXXXXXX" */
114 event
= malloc(sizeof(struct devman_event
));
117 panic("devman_device_remove_event: out of memory\n");
120 memset(event
, 0, sizeof(*event
));
122 strncpy(event
->data
, REMOVE_STRING
, DEVMAN_STRING_LEN
- 1);
124 res
= devman_generate_path(event
->data
, DEVMAN_STRING_LEN
-11, dev
);
127 panic("devman_device_remove_event: "
128 "devman_generate_path failed: (%d)\n", res
);
131 snprintf(buf
, 12, " 0x%08x", dev
->dev_id
);
132 strcat(event
->data
,buf
);
135 TAILQ_INSERT_HEAD(&event_inode_data
.event_queue
, event
, events
);
138 /*===========================================================================*
139 * devman_event_read *
140 *===========================================================================*/
142 devman_event_read(char *ptr
, size_t len
, off_t offset
, void *data
)
144 struct devman_event
*ev
= NULL
;
145 struct devman_event_inode
*n
;
148 n
= (struct devman_event_inode
*) data
;
150 if (!TAILQ_EMPTY(&n
->event_queue
)) {
151 ev
= TAILQ_LAST(&n
->event_queue
, event_head
);
154 buf_init(ptr
, len
, offset
);
156 buf_printf("%s", ev
->data
);
160 /* read all (EOF)? */
161 if (ev
!= NULL
&& r
== 0) {
162 TAILQ_REMOVE(&n
->event_queue
, ev
, events
);
169 /*===========================================================================*
170 * devman_static_info_read *
171 *===========================================================================*/
173 devman_static_info_read(char *ptr
, size_t len
, off_t offset
, void *data
)
175 struct devman_static_info_inode
*n
;
177 n
= (struct devman_static_info_inode
*) data
;
179 buf_init(ptr
, len
, offset
);
180 buf_printf("%s\n", n
->data
);
184 /*===========================================================================*
185 * devman_init_devices *
186 *===========================================================================*/
187 void devman_init_devices()
189 event_inode
.data
= &event_inode_data
;
190 event_inode
.read_fn
= devman_event_read
;
195 root_dev
.parent
= NULL
;
197 root_dev
.inode
.inode
=
198 add_inode(get_root_inode(), "devices",
199 NO_INDEX
, &default_dir_stat
, 0, &root_dev
.inode
);
202 add_inode(get_root_inode(), "events",
203 NO_INDEX
, &default_file_stat
, 0, &event_inode
);
205 TAILQ_INIT(&root_dev
.children
);
206 TAILQ_INIT(&root_dev
.infos
);
210 /*===========================================================================*
212 *===========================================================================*/
213 static void do_reply(message
*msg
, int res
)
215 msg
->m_type
= DEVMAN_REPLY
;
216 msg
->DEVMAN_RESULT
= res
;
217 ipc_send(msg
->m_source
, msg
);
220 /*===========================================================================*
222 *===========================================================================*/
223 int do_add_device(message
*msg
)
225 endpoint_t ep
= msg
->m_source
;
227 struct devman_device
*dev
;
228 struct devman_device
*parent
;
229 struct devman_device_info
*devinf
= NULL
;
231 devinf
= malloc(msg
->DEVMAN_GRANT_SIZE
);
233 if (devinf
== NULL
) {
239 res
= sys_safecopyfrom(ep
, msg
->DEVMAN_GRANT_ID
,
240 0, (vir_bytes
) devinf
, msg
->DEVMAN_GRANT_SIZE
);
249 if ((parent
= _find_dev(&root_dev
, devinf
->parent_dev_id
))
257 dev
= devman_dev_add_child(parent
, devinf
);
266 dev
->state
= DEVMAN_DEVICE_UNBOUND
;
268 dev
->owner
= msg
->m_source
;
270 msg
->DEVMAN_DEVICE_ID
= dev
->dev_id
;
272 devman_device_add_event(dev
);
279 /*===========================================================================*
281 *===========================================================================*/
282 static struct devman_device
*
283 _find_dev(struct devman_device
*dev
, int dev_id
)
285 struct devman_device
*_dev
;
287 if(dev
->dev_id
== dev_id
)
290 TAILQ_FOREACH(_dev
, &dev
->children
, siblings
) {
292 struct devman_device
*t
= _find_dev(_dev
, dev_id
);
302 /*===========================================================================*
304 *===========================================================================*/
305 struct devman_device
*devman_find_device(int dev_id
)
307 return _find_dev(&root_dev
, dev_id
);
310 /*===========================================================================*
311 * devman_dev_add_static_info *
312 *===========================================================================*/
314 devman_dev_add_static_info
315 (struct devman_device
*dev
, char * name
, char *data
)
317 struct devman_inode
*inode
;
318 struct devman_static_info_inode
*st_inode
;
321 st_inode
= malloc(sizeof(struct devman_static_info_inode
));
324 strncpy(st_inode
->data
, data
, DEVMAN_STRING_LEN
);
325 /* if string is longer it's truncated */
326 st_inode
->data
[DEVMAN_STRING_LEN
-1] = 0;
328 inode
= malloc (sizeof(struct devman_inode
));
329 inode
->data
= st_inode
;
330 inode
->read_fn
= devman_static_info_read
;
332 inode
->inode
= add_inode(dev
->inode
.inode
, name
,
333 NO_INDEX
, &default_file_stat
, 0, inode
);
335 /* add info to info_list */
336 TAILQ_INSERT_HEAD(&dev
->infos
, inode
, inode_list
);
341 /*===========================================================================*
342 * devman_dev_add_child *
343 *===========================================================================*/
344 static struct devman_device
*
346 (struct devman_device
*parent
, struct devman_device_info
*devinf
)
349 char * buffer
= (char *) (devinf
);
351 struct devman_device_info_entry
*entries
;
354 struct devman_device
* dev
= malloc(sizeof(struct devman_device
));
356 panic("devman_dev_add_child: out of memory\n");
360 if (parent
== NULL
) {
368 dev
->parent
= parent
;
371 dev
->dev_id
= next_device_id
++;
374 add_inode(parent
->inode
.inode
, buffer
+ devinf
->name_offset
,
375 NO_INDEX
, &default_dir_stat
, 0, &dev
->inode
);
377 TAILQ_INIT(&dev
->children
);
378 TAILQ_INIT(&dev
->infos
);
380 /* create information inodes */
381 entries
= (struct devman_device_info_entry
*)
382 (buffer
+ sizeof(struct devman_device_info
));
384 for (i
= 0; i
< devinf
->count
; i
++) {
385 devman_dev_add_info(dev
, &entries
[i
], buffer
);
388 /* make device ID accessible to user land */
389 snprintf(tmp_buf
, DEVMAN_STRING_LEN
, "%d",dev
->dev_id
);
390 devman_dev_add_static_info(dev
, "devman_id", tmp_buf
);
392 TAILQ_INSERT_HEAD(&parent
->children
, dev
, siblings
);
394 devman_get_device(parent
);
396 /* FUTURE TODO: create links(BUS, etc) */
400 /*===========================================================================*
401 * devman_dev_add_info *
402 *===========================================================================*/
405 (struct devman_device
*dev
, struct devman_device_info_entry
*entry
, char *buf
)
407 switch(entry
->type
) {
409 case DEVMAN_DEVINFO_STATIC
:
410 return devman_dev_add_static_info(dev
,
411 buf
+ entry
->name_offset
, buf
+ entry
->data_offset
);
413 case DEVMAN_DEVINFO_DYNAMIC
:
421 /*===========================================================================*
423 *===========================================================================*/
424 int do_del_device(message
*msg
)
426 int dev_id
= msg
->DEVMAN_DEVICE_ID
;
430 /* only parrent is allowed to add devices */
431 struct devman_device
*dev
= _find_dev(&root_dev
, dev_id
);
434 printf("devman: no dev with id %d\n",dev_id
);
439 if (dev
->parent
->owner
!= ep
) {
445 devman_device_remove_event(dev
);
446 if (dev
->state
== DEVMAN_DEVICE_BOUND
) {
447 dev
->state
= DEVMAN_DEVICE_ZOMBIE
;
449 devman_put_device(dev
);
457 /*===========================================================================*
458 * devman_get_device *
459 *===========================================================================*/
460 void devman_get_device(struct devman_device
*dev
)
462 if (dev
== NULL
|| dev
== &root_dev
) {
468 /*===========================================================================*
469 * devman_put_device *
470 *===========================================================================*/
471 void devman_put_device(struct devman_device
*dev
)
473 if (dev
== NULL
|| dev
== &root_dev
) {
477 if (dev
->ref_count
== 0) {
478 devman_del_device(dev
);
482 /*===========================================================================*
483 * devman_del_device *
484 *===========================================================================*/
485 static int devman_del_device(struct devman_device
*dev
)
487 /* does device have children -> error */
488 /* evtl. remove links */
490 /* free devinfo inodes */
491 struct devman_inode
*inode
, *_inode
;
493 TAILQ_FOREACH_SAFE(inode
, &dev
->infos
, inode_list
, _inode
) {
495 delete_inode(inode
->inode
);
497 TAILQ_REMOVE(&dev
->infos
, inode
, inode_list
);
506 /* free device inode */
507 delete_inode(dev
->inode
.inode
);
509 /* remove from parent */
510 TAILQ_REMOVE(&dev
->parent
->children
, dev
, siblings
);
512 devman_put_device(dev
->parent
);