0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/types.h>
0010 #include <linux/kdev_t.h>
0011 #include <linux/console.h>
0012 #include <linux/vt_kern.h>
0013 #include <linux/screen_info.h>
0014 #include <linux/init.h>
0015 #include <linux/module.h>
0016
0017
0018
0019
0020
0021 #if defined(__arm__)
0022 #define DUMMY_COLUMNS screen_info.orig_video_cols
0023 #define DUMMY_ROWS screen_info.orig_video_lines
0024 #else
0025
0026 #define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS
0027 #define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS
0028 #endif
0029
0030 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
0031
0032 static RAW_NOTIFIER_HEAD(dummycon_output_nh);
0033 static bool dummycon_putc_called;
0034
0035 void dummycon_register_output_notifier(struct notifier_block *nb)
0036 {
0037 WARN_CONSOLE_UNLOCKED();
0038
0039 raw_notifier_chain_register(&dummycon_output_nh, nb);
0040
0041 if (dummycon_putc_called)
0042 nb->notifier_call(nb, 0, NULL);
0043 }
0044
0045 void dummycon_unregister_output_notifier(struct notifier_block *nb)
0046 {
0047 WARN_CONSOLE_UNLOCKED();
0048
0049 raw_notifier_chain_unregister(&dummycon_output_nh, nb);
0050 }
0051
0052 static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos)
0053 {
0054 WARN_CONSOLE_UNLOCKED();
0055
0056 dummycon_putc_called = true;
0057 raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
0058 }
0059
0060 static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
0061 int count, int ypos, int xpos)
0062 {
0063 int i;
0064
0065 if (!dummycon_putc_called) {
0066
0067 for (i = 0 ; i < count; i++) {
0068 if (s[i] != vc->vc_video_erase_char)
0069 break;
0070 }
0071 if (i == count)
0072 return;
0073
0074 dummycon_putc_called = true;
0075 }
0076
0077 raw_notifier_call_chain(&dummycon_output_nh, 0, NULL);
0078 }
0079
0080 static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch)
0081 {
0082
0083 return 1;
0084 }
0085 #else
0086 static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { }
0087 static void dummycon_putcs(struct vc_data *vc, const unsigned short *s,
0088 int count, int ypos, int xpos) { }
0089 static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch)
0090 {
0091 return 0;
0092 }
0093 #endif
0094
0095 static const char *dummycon_startup(void)
0096 {
0097 return "dummy device";
0098 }
0099
0100 static void dummycon_init(struct vc_data *vc, int init)
0101 {
0102 vc->vc_can_do_color = 1;
0103 if (init) {
0104 vc->vc_cols = DUMMY_COLUMNS;
0105 vc->vc_rows = DUMMY_ROWS;
0106 } else
0107 vc_resize(vc, DUMMY_COLUMNS, DUMMY_ROWS);
0108 }
0109
0110 static void dummycon_deinit(struct vc_data *vc) { }
0111 static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height,
0112 int width) { }
0113 static void dummycon_cursor(struct vc_data *vc, int mode) { }
0114
0115 static bool dummycon_scroll(struct vc_data *vc, unsigned int top,
0116 unsigned int bottom, enum con_scroll dir,
0117 unsigned int lines)
0118 {
0119 return false;
0120 }
0121
0122 static int dummycon_switch(struct vc_data *vc)
0123 {
0124 return 0;
0125 }
0126
0127
0128
0129
0130
0131
0132
0133 const struct consw dummy_con = {
0134 .owner = THIS_MODULE,
0135 .con_startup = dummycon_startup,
0136 .con_init = dummycon_init,
0137 .con_deinit = dummycon_deinit,
0138 .con_clear = dummycon_clear,
0139 .con_putc = dummycon_putc,
0140 .con_putcs = dummycon_putcs,
0141 .con_cursor = dummycon_cursor,
0142 .con_scroll = dummycon_scroll,
0143 .con_switch = dummycon_switch,
0144 .con_blank = dummycon_blank,
0145 };
0146 EXPORT_SYMBOL_GPL(dummy_con);