forked from ish-app/ish
-
Notifications
You must be signed in to change notification settings - Fork 12
/
dyndev.c
83 lines (67 loc) · 1.99 KB
/
dyndev.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "kernel/errno.h"
#include "fs/dev.h"
#include "fs/dyndev.h"
#include "fs/devices.h"
#define MAX_MINOR 255
typedef struct fd rtc_fd;
// Handles DYNDEV_MAJOR device number
// XXX(stek29): unregister might be added later
struct dyn_dev_info {
// devs & next_dev lock
lock_t devs_lock;
// table of dev_ops registered by minor number
struct dev_ops *devs[MAX_MINOR+1];
};
struct dyn_dev_info dyn_info_char = {
.devs_lock = LOCK_INITIALIZER,
.devs = {},
};
int dyn_dev_register(struct dev_ops *ops, int type, int major, int minor) {
// Validate arguments
if (minor < 0 || minor > MAX_MINOR) {
return _EINVAL;
}
if ((major != DYN_DEV_MAJOR) && (major != DEV_RTC_MAJOR)) {
return _EINVAL;
}
if (ops == NULL) {
return _EINVAL;
}
if (type != DEV_CHAR) {
return _EINVAL;
}
lock(&dyn_info_char.devs_lock, 0);
// Make sure minor number isn't taken yet
if (dyn_info_char.devs[minor] != NULL) {
unlock(&dyn_info_char.devs_lock);
return _EEXIST;
}
dyn_info_char.devs[minor] = ops;
unlock(&dyn_info_char.devs_lock);
return 0;
}
static int dyn_open(int type, int major, int minor, struct fd *fd) {
assert((type == DEV_CHAR) || (type == DEV_BLOCK));
assert(major == DYN_DEV_MAJOR || major == DEV_RTC_MAJOR); // mkemkemke
// it's safe to access devs without locking (read-only)
if(major == DEV_RTC_MAJOR) {
//return rtc_dev_char(major, minor, fd);
} else {
struct dev_ops *ops = dyn_info_char.devs[minor];
if (ops == NULL) {
return _ENXIO;
}
fd->ops = &ops->fd;
// Succeed if there's no open provided by ops
if (!ops->open)
return 0;
return ops->open(major, minor, fd);
}
return 0;
}
static int dyn_open_char(int major, int minor, struct fd *fd) {
return dyn_open(DEV_CHAR, major, minor, fd);
}
struct dev_ops dyn_dev_char = {
.open = dyn_open_char,
};