nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
keyboard.c
Go to the documentation of this file.
1 #include <slibc.h>
2 #include <sys/types.h>
3 #include <sys/io.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <errno.h>
7 #include <stddef.h>
8 #include <stdarg.h>
9 #include <stropts.h>
10 #include <fcntl.h>
11 #include <stdint.h>
12 #include <unistd.h>
13 #include <string.h>
14 
15 #include <object.h>
16 #include <list.h>
17 #include <vfs.h>
18 #include <device.h>
19 #include <keyboard.h>
20 #include <interrupt.h>
21 #include <isr.h>
22 
23 #include <debug.h>
24 
25 #define SIZE_OF_QUEUE 64
26 
27 static struct {
28  unsigned short buffer[SIZE_OF_QUEUE];
31 } s_info = {
32  .buffer = { 0, },
33  .write_offset = 0,
34  .read_offset = 0,
35 };
36 
37 struct info {
38 };
39 
40 off_t keyboard_lseek(struct ninfo *ninfo, struct nctx *ctx, off_t off, int whence)
41 {
42  switch (whence) {
43  case SEEK_SET:
44  break;
45  case SEEK_CUR:
46  off += ctx->offset;
47  break;
48  case SEEK_END:
49  off += ninfo->size;
50  break;
51  default:
52  return -EINVAL;
53  }
54 
55  if (off < 0 || off >= ninfo->size) {
56  return -EINVAL;
57  }
58 
59  ctx->offset = off;
60  return off;
61 }
62 
63 int keyboard_read(struct ninfo *ninfo, struct nctx *ctx, void *buf, size_t size)
64 {
65  int i;
66  char *out = (char *)buf;
67 
68  for (i = 0; s_info.read_offset != s_info.write_offset && i < size; i++) {
69  *out = (char)(s_info.buffer[s_info.read_offset] & 0x00FF);
70  s_info.read_offset = (s_info.read_offset + 1) % SIZE_OF_QUEUE;
71  }
72 
73  return i;
74 }
75 
76 int keyboard_write(struct ninfo *ninfo, struct nctx *ctx,
77  const void *buf, size_t size)
78 {
79  return -EPERM;
80 }
81 
82 int keyboard_ioctl(struct ninfo *ninfo, struct nctx *ctx, int request, va_list ap)
83 {
84  return -ENOSYS;
85 }
86 
87 int keyboard_open(struct ninfo *ninfo, struct nctx *ctx)
88 {
89  struct info *info;
90 
91  info = malloc(sizeof(*info));
92  if (!info) {
93  return -ENOMEM;
94  }
95 
96  memset(info, 0, sizeof(*info));
97 
98  ctx->offset = 0;
99  ctx->priv = info;
100 
101  return 0;
102 }
103 
104 int keyboard_close(struct ninfo *ninfo, struct nctx *ctx)
105 {
106  free(ctx->priv);
107  ctx->priv = NULL;
108  return 0;
109 }
110 
111 static struct ninfo_ops keyboard_ops = {
113  .read = keyboard_read,
114  .write = keyboard_write,
115  .ioctl = keyboard_ioctl,
116  .open = keyboard_open,
117  .close = keyboard_close,
118 };
119 
120 static int keyboard_handler(int sub_irq, void *info, void *data)
121 {
122  static int idx = 0;
123  unsigned short ch; /* status | scancode */
124 
125  ch = inb(0x64);
126  ch = (ch << 8) | inb(0x60);
127 
128  dbg_printf("[%d] keyboard: %d, %p, %d, %d\n", idx++, sub_irq, info, ch);
129 
130  s_info.buffer[s_info.write_offset] = ch;
131  s_info.write_offset = (s_info.write_offset + 1) % SIZE_OF_QUEUE;
132  if (s_info.write_offset == s_info.read_offset) {
133  /* Discard old input */
134  s_info.read_offset = (s_info.read_offset + 1) % SIZE_OF_QUEUE;
135  }
136 
137  return 0;
138 }
139 
140 int keyboard_init(void)
141 {
142  struct ninfo *parent;
143  struct ninfo *ninfo;
144  int ret;
145 
146  ret = register_irq(IRQ_NR_KEYBOARD, NORMAL_PRIORITY, keyboard_handler, NULL);
147  if (ret < 0) {
148  return ret;
149  }
150 
151  parent = vfs_get_ninfo(NULL, NULL, "/dev");
152  if (!parent) {
153  unregister_irq(IRQ_NR_KEYBOARD, keyboard_handler, NULL);
154  return -EFAULT;
155  }
156 
157  ninfo = vfs_new_dev_ninfo(NULL, parent,
158  "input", DEVICE_VIDEO80x25, &keyboard_ops);
159  if (!ninfo) {
160  unregister_irq(IRQ_NR_KEYBOARD, keyboard_handler, NULL);
161  return -EFAULT;
162  }
163 
164  ninfo->size = 0;
165 
166  return 0;
167 }
168 
169 /* End of a file */