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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include "video.h"
#include "string.h"
#include "kernel.h"
#undef DEBUG
static video_vtable_t const video_vtable = {
{
video_activate,
video_deactivate,
video_deinit,
video_print_info
}
};
void video_init( video_t *video, interrupt_t *interrupt, void *context )
{
memset( video, 0, sizeof( video_t ) );
driver_init( (driver_t *)video, DRIVER_TYPE_VIDEO, interrupt, context );
video->nof_modes = 0;
((driver_t *)video)->vtable = (driver_vtable_t *)&video_vtable;
}
void video_activate( void *obj )
{
kernel_panic( "Activating generic video driver should not be called directly." );
}
void video_deactivate( void *obj )
{
kernel_panic( "Deactivating generic video driver should not be called directly." );
}
void video_deinit( void *obj )
{
// nothing to be done
}
void video_print_info( void *obj )
{
kernel_panic( "Printing info of generic video driver should not be called directly." );
}
video_mode_t video_make_mode( const video_mode_type_t mode_type, const int x, const int y, const int color_depth )
{
video_mode_t mode;
mode.mode_type = mode_type;
mode.x = x;
mode.y = y;
mode.color_depth = color_depth;
return mode;
}
void video_register_mode( void *obj, const video_mode_t *mode )
{
video_t *video = (video_t *)obj;
if( video->nof_modes >= MAX_NOF_VIDEO_MODES ) {
kernel_panic( "Trying to register too many video modes, see MAX_NOF_VIDEO_MODES: %d", MAX_NOF_VIDEO_MODES );
}
video->modes[video->nof_modes++] = mode;
}
static int get_matching_mode_idx( video_t *video, const video_mode_t mode )
{
for( int i = 0; video->modes[i]->x != 0; i++ ) {
if( mode.mode_type == video->modes[i]->mode_type &&
mode.x == video->modes[i]->x &&
mode.y == video->modes[i]->y &&
mode.color_depth == video->modes[i]->color_depth ) {
return i;
}
}
return -1;
}
bool video_supports_mode( void *obj, const video_mode_t mode )
{
video_t *video = (video_t *)obj;
for( int i = 0; video->modes[i]->x != 0; i++ ) {
if( mode.mode_type == video->modes[i]->mode_type &&
mode.x == video->modes[i]->x &&
mode.y == video->modes[i]->y &&
mode.color_depth == video->modes[i]->color_depth ) {
return true;
}
}
return false;
}
bool video_set_mode( void *obj, const video_mode_t mode )
{
video_t *video = (video_t *)obj;
// do not allow unknown timings!
if( !((video_vtable_t *)(video->base.vtable))->supports_mode( obj, mode ) ) {
return false;
}
const video_mode_t *matching_mode = video->modes[get_matching_mode_idx( video, mode )];
return ((video_vtable_t *)(video->base.vtable))->switch_mode( obj, matching_mode );
}
bool video_switch_mode( void *obj, const video_mode_t *mode )
{
kernel_panic( "Switching mode function of abstract video driver should not be called directly." );
return false;
}
|