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 int 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
;
153 n
= (struct devman_event_inode
*) data
;
155 if (!TAILQ_EMPTY(&n
->event_queue
)) {
156 ev
= TAILQ_LAST(&n
->event_queue
, event_head
);
159 buf_init(offset
, *len
);
161 buf_printf("%s", ev
->data
);
163 if (*len
+ offset
>= strlen(ev
->data
)) {
164 TAILQ_REMOVE(&n
->event_queue
, ev
, events
);
175 /*===========================================================================*
176 * devman_static_info_read *
177 *===========================================================================*/
179 devman_static_info_read(char **ptr
, size_t *len
, off_t offset
, void *data
)
181 struct devman_static_info_inode
*n
;
183 n
= (struct devman_static_info_inode
*) data
;
185 buf_init(offset
, *len
);
186 buf_printf("%s\n", n
->data
);
191 /*===========================================================================*
192 * devman_init_devices *
193 *===========================================================================*/
194 void devman_init_devices()
196 event_inode
.data
= &event_inode_data
;
197 event_inode
.read_fn
= devman_event_read
;
202 root_dev
.parent
= NULL
;
204 root_dev
.inode
.inode
=
205 add_inode(get_root_inode(), "devices",
206 NO_INDEX
, &default_dir_stat
, 0, &root_dev
.inode
);
209 add_inode(get_root_inode(), "events",
210 NO_INDEX
, &default_file_stat
, 0, &event_inode
);
212 TAILQ_INIT(&root_dev
.children
);
213 TAILQ_INIT(&root_dev
.infos
);
217 /*===========================================================================*
219 *===========================================================================*/
220 static void do_reply(message
*msg
, int res
)
222 msg
->m_type
= DEVMAN_REPLY
;
223 msg
->DEVMAN_RESULT
= res
;
224 send(msg
->m_source
, msg
);
227 /*===========================================================================*
229 *===========================================================================*/
230 int do_add_device(message
*msg
)
232 endpoint_t ep
= msg
->m_source
;
234 struct devman_device
*dev
;
235 struct devman_device
*parent
;
236 struct devman_device_info
*devinf
= NULL
;
238 devinf
= malloc(msg
->DEVMAN_GRANT_SIZE
);
240 if (devinf
== NULL
) {
246 res
= sys_safecopyfrom(ep
, msg
->DEVMAN_GRANT_ID
,
247 0, (vir_bytes
) devinf
, msg
->DEVMAN_GRANT_SIZE
);
256 if ((parent
= _find_dev(&root_dev
, devinf
->parent_dev_id
))
264 dev
= devman_dev_add_child(parent
, devinf
);
273 dev
->state
= DEVMAN_DEVICE_UNBOUND
;
275 dev
->owner
= msg
->m_source
;
277 msg
->DEVMAN_DEVICE_ID
= dev
->dev_id
;
279 devman_device_add_event(dev
);
286 /*===========================================================================*
288 *===========================================================================*/
289 static struct devman_device
*
290 _find_dev(struct devman_device
*dev
, int dev_id
)
292 struct devman_device
*_dev
;
294 if(dev
->dev_id
== dev_id
)
297 TAILQ_FOREACH(_dev
, &dev
->children
, siblings
) {
299 struct devman_device
*t
= _find_dev(_dev
, dev_id
);
309 /*===========================================================================*
311 *===========================================================================*/
312 struct devman_device
*devman_find_device(int dev_id
)
314 return _find_dev(&root_dev
, dev_id
);
317 /*===========================================================================*
318 * devman_dev_add_static_info *
319 *===========================================================================*/
321 devman_dev_add_static_info
322 (struct devman_device
*dev
, char * name
, char *data
)
324 struct devman_inode
*inode
;
325 struct devman_static_info_inode
*st_inode
;
328 st_inode
= malloc(sizeof(struct devman_static_info_inode
));
331 strncpy(st_inode
->data
, data
, DEVMAN_STRING_LEN
);
332 /* if string is longer it's truncated */
333 st_inode
->data
[DEVMAN_STRING_LEN
-1] = 0;
335 inode
= malloc (sizeof(struct devman_inode
));
336 inode
->data
= st_inode
;
337 inode
->read_fn
= devman_static_info_read
;
339 inode
->inode
= add_inode(dev
->inode
.inode
, name
,
340 NO_INDEX
, &default_file_stat
, 0, inode
);
342 /* add info to info_list */
343 TAILQ_INSERT_HEAD(&dev
->infos
, inode
, inode_list
);
348 /*===========================================================================*
349 * devman_dev_add_child *
350 *===========================================================================*/
351 static struct devman_device
*
353 (struct devman_device
*parent
, struct devman_device_info
*devinf
)
356 char * buffer
= (char *) (devinf
);
358 struct devman_device_info_entry
*entries
;
361 struct devman_device
* dev
= malloc(sizeof(struct devman_device
));
363 panic("devman_dev_add_child: out of memory\n");
367 if (parent
== NULL
) {
375 dev
->parent
= parent
;
378 dev
->dev_id
= next_device_id
++;
381 add_inode(parent
->inode
.inode
, buffer
+ devinf
->name_offset
,
382 NO_INDEX
, &default_dir_stat
, 0, &dev
->inode
);
384 TAILQ_INIT(&dev
->children
);
385 TAILQ_INIT(&dev
->infos
);
387 /* create information inodes */
388 entries
= (struct devman_device_info_entry
*)
389 (buffer
+ sizeof(struct devman_device_info
));
391 for (i
= 0; i
< devinf
->count
; i
++) {
392 devman_dev_add_info(dev
, &entries
[i
], buffer
);
395 /* make device ID accessible to user land */
396 snprintf(tmp_buf
, DEVMAN_STRING_LEN
, "%d",dev
->dev_id
);
397 devman_dev_add_static_info(dev
, "devman_id", tmp_buf
);
399 TAILQ_INSERT_HEAD(&parent
->children
, dev
, siblings
);
401 devman_get_device(parent
);
403 /* FUTURE TODO: create links(BUS, etc) */
407 /*===========================================================================*
408 * devman_dev_add_info *
409 *===========================================================================*/
412 (struct devman_device
*dev
, struct devman_device_info_entry
*entry
, char *buf
)
414 switch(entry
->type
) {
416 case DEVMAN_DEVINFO_STATIC
:
417 return devman_dev_add_static_info(dev
,
418 buf
+ entry
->name_offset
, buf
+ entry
->data_offset
);
420 case DEVMAN_DEVINFO_DYNAMIC
:
428 /*===========================================================================*
430 *===========================================================================*/
431 int do_del_device(message
*msg
)
433 int dev_id
= msg
->DEVMAN_DEVICE_ID
;
437 /* only parrent is allowed to add devices */
438 struct devman_device
*dev
= _find_dev(&root_dev
, dev_id
);
441 printf("devman: no dev with id %d\n",dev_id
);
446 if (dev
->parent
->owner
!= ep
) {
452 devman_device_remove_event(dev
);
453 if (dev
->state
== DEVMAN_DEVICE_BOUND
) {
454 dev
->state
= DEVMAN_DEVICE_ZOMBIE
;
456 devman_put_device(dev
);
464 /*===========================================================================*
465 * devman_get_device *
466 *===========================================================================*/
467 void devman_get_device(struct devman_device
*dev
)
469 if (dev
== NULL
|| dev
== &root_dev
) {
475 /*===========================================================================*
476 * devman_put_device *
477 *===========================================================================*/
478 void devman_put_device(struct devman_device
*dev
)
480 if (dev
== NULL
|| dev
== &root_dev
) {
484 if (dev
->ref_count
== 0) {
485 devman_del_device(dev
);
489 /*===========================================================================*
490 * devman_del_device *
491 *===========================================================================*/
492 static int devman_del_device(struct devman_device
*dev
)
494 /* does device have children -> error */
495 /* evtl. remove links */
497 /* free devinfo inodes */
498 struct devman_inode
*inode
, *_inode
;
500 TAILQ_FOREACH_SAFE(inode
, &dev
->infos
, inode_list
, _inode
) {
502 delete_inode(inode
->inode
);
504 TAILQ_REMOVE(&dev
->infos
, inode
, inode_list
);
513 /* free device inode */
514 delete_inode(dev
->inode
.inode
);
516 /* remove from parent */
517 TAILQ_REMOVE(&dev
->parent
->children
, dev
, siblings
);
519 devman_put_device(dev
->parent
);