nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
video.c
Go to the documentation of this file.
1 #include <slibc.h>
2 #include <sys/types.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <stddef.h>
7 #include <stdarg.h>
8 #include <stropts.h>
9 #include <fcntl.h>
10 #include <stdint.h>
11 #include <unistd.h>
12 
13 #include <object.h>
14 #include <list.h>
15 #include <vfs.h>
16 #include <device.h>
17 #include <video.h>
18 
19 #include <debug.h>
20 
21 #define TAB_SIZE 7
22 #define MAX_SIZE 2000
23 #define MAX_COLUMN 80
24 #define VIDEO_BUFFER ((char *)0xb8000)
25 
26 struct info {
27  char *video;
28  unsigned char auto_scroll;
29  char attribute;
30 };
31 
32 off_t video_lseek(struct ninfo *ninfo, struct nctx *ctx, off_t off, int whence)
33 {
34  switch (whence) {
35  case SEEK_SET:
36  break;
37  case SEEK_CUR:
38  off += ctx->offset;
39  break;
40  case SEEK_END:
41  off += ninfo->size;
42  break;
43  default:
44  return -EINVAL;
45  }
46 
47  if (off < 0 || off >= ninfo->size) {
48  return -EINVAL;
49  }
50 
51  ctx->offset = off;
52  return off;
53 }
54 
55 int video_read(struct ninfo *ninfo, struct nctx *ctx, void *buf, size_t size)
56 {
57  register int i;
58  register int offset;
59  struct info *info;
60  char *buffer = buf;
61 
62  info = ctx->priv;
63 
64  for (i = 0; i < size && ctx->offset < ninfo->size; i ++) {
65  offset = ctx->offset << 1;
66  buffer[i] = info->video[offset];
67  ctx->offset++;
68  }
69 
70  return i;
71 }
72 
73 int video_write(struct ninfo *ninfo, struct nctx *ctx,
74  const void *buf, size_t size)
75 {
76  register int i;
77  int offset;
78  int tmp;
79  struct info *info;
80  const char *buffer = buf;
81 
82  info = ctx->priv;
83 
84  do {
85  if (ctx->offset >= ninfo->size) {
86  /* Scroll up A line */
87  tmp = MAX_SIZE - MAX_COLUMN;
88  for (i = 0; i < tmp; i++) {
89  offset = i << 1;
90  info->video[offset] =
91  info->video[offset + (MAX_COLUMN << 1)];
92 
93  /* Copy attribute */
94  offset++;
95  info->video[offset] =
96  info->video[offset + (MAX_COLUMN << 1)];
97  }
98 
99  ctx->offset -= MAX_COLUMN;
100 
101  /* Clear last line */
102  for (i = ctx->offset; i < ninfo->size; i++) {
103  offset = i << 1;
104  info->video[offset] = 0x20;
105  info->video[offset + 1] = info->attribute;
106  }
107 
108  /* Update the offset */
109  }
110 
111  /* Write */
112  for (i = 0; i < size && ctx->offset < ninfo->size; i++) {
113  if (buffer[i] == '\n') {
114  offset = ctx->offset % MAX_COLUMN;
115  ctx->offset += (MAX_COLUMN - offset);
116  continue;
117  } else if (buffer[i] == '\r') {
118  offset = ctx->offset % MAX_COLUMN;
119  ctx->offset -= offset;
120  continue;
121  } else if (buffer[i] == '\t') {
122  ctx->offset += (7 << 1);
123  continue;
124  }
125 
126  offset = ctx->offset << 1;
127  info->video[offset] = buffer[i];
128  info->video[offset + 1] = info->attribute;
129  ctx->offset++;
130  }
131 
132  size -= i;
133  } while (size > 0 && info->auto_scroll);
134 
135  return i;
136 }
137 
138 int video_ioctl(struct ninfo *ninfo, struct nctx *ctx, int request, va_list ap)
139 {
140  return -ENOSYS;
141 }
142 
143 int video_open(struct ninfo *ninfo, struct nctx *ctx)
144 {
145  struct info *info;
146 
147  info = malloc(sizeof(*info));
148  if (!info) {
149  return -ENOMEM;
150  }
151 
152  info->video = VIDEO_BUFFER;
153  info->auto_scroll = 1;
154  info->attribute = 0x07;
155  ctx->offset = 0;
156  ctx->priv = info;
157 
158  return 0;
159 }
160 
161 int video_close(struct ninfo *ninfo, struct nctx *ctx)
162 {
163  free(ctx->priv);
164  ctx->priv = NULL;
165  return 0;
166 }
167 
168 static struct ninfo_ops video_ops = {
169  .lseek = video_lseek,
170  .read = video_read,
171  .write = video_write,
172  .ioctl = video_ioctl,
173  .open = video_open,
174  .close = video_close,
175 };
176 
177 int video_init(void)
178 {
179  struct ninfo *parent;
180  struct ninfo *ninfo;
181 
182  parent = vfs_get_ninfo(NULL, NULL, "/dev");
183  if (!parent) {
184  return -EFAULT;
185  }
186 
187  ninfo = vfs_new_dev_ninfo(NULL, parent,
188  "video", DEVICE_VIDEO80x25, &video_ops);
189  if (!ninfo) {
190  return -EFAULT;
191  }
192 
193  ninfo->size = MAX_SIZE;
194  return 0;
195 }
196 
197 /* End of a file */