1
2
3
4
5
6
7
8
9
10#include <linux/module.h>
11#include <linux/kernel.h>
12#include <linux/string.h>
13#include <linux/nls.h>
14#include <linux/errno.h>
15
16static const wchar_t charset2uni[256] = {
17
18 0x0000, 0x0001, 0x0002, 0x0003,
19 0x0004, 0x0005, 0x0006, 0x0007,
20 0x0008, 0x0009, 0x000a, 0x000b,
21 0x000c, 0x000d, 0x000e, 0x000f,
22
23 0x0010, 0x0011, 0x0012, 0x0013,
24 0x0014, 0x0015, 0x0016, 0x0017,
25 0x0018, 0x0019, 0x001a, 0x001b,
26 0x001c, 0x001d, 0x001e, 0x001f,
27
28 0x0020, 0x0021, 0x0022, 0x0023,
29 0x0024, 0x0025, 0x0026, 0x0027,
30 0x0028, 0x0029, 0x002a, 0x002b,
31 0x002c, 0x002d, 0x002e, 0x002f,
32
33 0x0030, 0x0031, 0x0032, 0x0033,
34 0x0034, 0x0035, 0x0036, 0x0037,
35 0x0038, 0x0039, 0x003a, 0x003b,
36 0x003c, 0x003d, 0x003e, 0x003f,
37
38 0x0040, 0x0041, 0x0042, 0x0043,
39 0x0044, 0x0045, 0x0046, 0x0047,
40 0x0048, 0x0049, 0x004a, 0x004b,
41 0x004c, 0x004d, 0x004e, 0x004f,
42
43 0x0050, 0x0051, 0x0052, 0x0053,
44 0x0054, 0x0055, 0x0056, 0x0057,
45 0x0058, 0x0059, 0x005a, 0x005b,
46 0x005c, 0x005d, 0x005e, 0x005f,
47
48 0x0060, 0x0061, 0x0062, 0x0063,
49 0x0064, 0x0065, 0x0066, 0x0067,
50 0x0068, 0x0069, 0x006a, 0x006b,
51 0x006c, 0x006d, 0x006e, 0x006f,
52
53 0x0070, 0x0071, 0x0072, 0x0073,
54 0x0074, 0x0075, 0x0076, 0x0077,
55 0x0078, 0x0079, 0x007a, 0x007b,
56 0x007c, 0x007d, 0x007e, 0x007f,
57
58 0x00c7, 0x00fc, 0x00e9, 0x00e2,
59 0x00e4, 0x00e0, 0x00e5, 0x00e7,
60 0x00ea, 0x00eb, 0x00e8, 0x00ef,
61 0x00ee, 0x00ec, 0x00c4, 0x00c5,
62
63 0x00c9, 0x00e6, 0x00c6, 0x00f4,
64 0x00f6, 0x00f2, 0x00fb, 0x00f9,
65 0x00ff, 0x00d6, 0x00dc, 0x00f8,
66 0x00a3, 0x00d8, 0x00d7, 0x0192,
67
68 0x00e1, 0x00ed, 0x00f3, 0x00fa,
69 0x00f1, 0x00d1, 0x00aa, 0x00ba,
70 0x00bf, 0x00ae, 0x00ac, 0x00bd,
71 0x00bc, 0x00a1, 0x00ab, 0x00bb,
72
73 0x2591, 0x2592, 0x2593, 0x2502,
74 0x2524, 0x00c1, 0x00c2, 0x00c0,
75 0x00a9, 0x2563, 0x2551, 0x2557,
76 0x255d, 0x00a2, 0x00a5, 0x2510,
77
78 0x2514, 0x2534, 0x252c, 0x251c,
79 0x2500, 0x253c, 0x00e3, 0x00c3,
80 0x255a, 0x2554, 0x2569, 0x2566,
81 0x2560, 0x2550, 0x256c, 0x00a4,
82
83 0x00f0, 0x00d0, 0x00ca, 0x00cb,
84 0x00c8, 0x0131, 0x00cd, 0x00ce,
85 0x00cf, 0x2518, 0x250c, 0x2588,
86 0x2584, 0x00a6, 0x00cc, 0x2580,
87
88 0x00d3, 0x00df, 0x00d4, 0x00d2,
89 0x00f5, 0x00d5, 0x00b5, 0x00fe,
90 0x00de, 0x00da, 0x00db, 0x00d9,
91 0x00fd, 0x00dd, 0x00af, 0x00b4,
92
93 0x00ad, 0x00b1, 0x2017, 0x00be,
94 0x00b6, 0x00a7, 0x00f7, 0x00b8,
95 0x00b0, 0x00a8, 0x00b7, 0x00b9,
96 0x00b3, 0x00b2, 0x25a0, 0x00a0,
97};
98
99static const unsigned char page00[256] = {
100 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
101 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
102 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
103 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
104 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
105 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
106 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
107 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
108 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
109 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
110 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
111 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
112 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
113 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
114 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
115 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
116
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0xff, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5,
122 0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee,
123 0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa,
124 0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8,
125 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80,
126 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8,
127 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e,
128 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1,
129 0x85, 0xa0, 0x83, 0xc6, 0x84, 0x86, 0x91, 0x87,
130 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b,
131 0xd0, 0xa4, 0x95, 0xa2, 0x93, 0xe4, 0x94, 0xf6,
132 0x9b, 0x97, 0xa3, 0x96, 0x81, 0xec, 0xe7, 0x98,
133};
134
135static const unsigned char page01[256] = {
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0xd5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00,
156};
157
158static const unsigned char page20[256] = {
159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2,
162};
163
164static const unsigned char page25[256] = {
165 0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00,
167 0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
168 0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
172 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0xcd, 0xba, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xbb,
176 0x00, 0x00, 0xc8, 0x00, 0x00, 0xbc, 0x00, 0x00,
177 0xcc, 0x00, 0x00, 0xb9, 0x00, 0x00, 0xcb, 0x00,
178 0x00, 0xca, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181
182 0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
183 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 0x00, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00,
185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187};
188
189static const unsigned char *const page_uni2charset[256] = {
190 page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
191 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
192 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
193 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
194 page20, NULL, NULL, NULL, NULL, page25, NULL, NULL,
195};
196
197static const unsigned char charset2lower[256] = {
198 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
199 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
200 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
201 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
202 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
203 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
204 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
205 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
206 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
207 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
208 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
209 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
210 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
211 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
212 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
213 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
214
215 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
216 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x84, 0x86,
217 0x82, 0x91, 0x91, 0x93, 0x94, 0x95, 0x96, 0x97,
218 0x98, 0x94, 0x81, 0x9b, 0x9c, 0x9b, 0x9e, 0x9f,
219 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa6, 0xa7,
220 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
221 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xa0, 0x83, 0x85,
222 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
223 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6,
224 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
225 0xd0, 0xd0, 0x88, 0x89, 0x8a, 0xd5, 0xa1, 0x8c,
226 0x8b, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x8d, 0xdf,
227 0xa2, 0xe1, 0x93, 0x95, 0xe4, 0xe4, 0xe6, 0xe7,
228 0xe7, 0xa3, 0x96, 0x97, 0xec, 0xec, 0xee, 0xef,
229 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
230 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
231};
232
233static const unsigned char charset2upper[256] = {
234 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
235 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
236 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
237 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
238 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
239 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
240 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
241 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
242 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
243 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
244 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
245 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
246 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
247 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
248 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
249 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
250
251 0x80, 0x9a, 0x90, 0xb6, 0x8e, 0xb7, 0x8f, 0x80,
252 0xd2, 0xd3, 0xd4, 0xd8, 0xd7, 0xde, 0x8e, 0x8f,
253 0x90, 0x92, 0x92, 0xe2, 0x99, 0xe3, 0xea, 0xeb,
254 0x00, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x00,
255 0xb5, 0xd6, 0xe0, 0xe9, 0xa5, 0xa5, 0xa6, 0xa7,
256 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
257 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
258 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
259 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc7,
260 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
261 0xd1, 0xd1, 0xd2, 0xd3, 0xd4, 0x49, 0xd6, 0xd7,
262 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
263 0xe0, 0xe1, 0xe2, 0xe3, 0xe5, 0xe5, 0x00, 0xe8,
264 0xe8, 0xe9, 0xea, 0xeb, 0xed, 0xed, 0xee, 0xef,
265 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
266 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
267};
268
269static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
270{
271 const unsigned char *uni2charset;
272 unsigned char cl = uni & 0x00ff;
273 unsigned char ch = (uni & 0xff00) >> 8;
274
275 if (boundlen <= 0)
276 return -ENAMETOOLONG;
277
278 uni2charset = page_uni2charset[ch];
279 if (uni2charset && uni2charset[cl])
280 out[0] = uni2charset[cl];
281 else
282 return -EINVAL;
283 return 1;
284}
285
286static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
287{
288 *uni = charset2uni[*rawstring];
289 if (*uni == 0x0000)
290 return -EINVAL;
291 return 1;
292}
293
294static struct nls_table table = {
295 .charset = "cp850",
296 .uni2char = uni2char,
297 .char2uni = char2uni,
298 .charset2lower = charset2lower,
299 .charset2upper = charset2upper,
300};
301
302static int __init init_nls_cp850(void)
303{
304 return register_nls(&table);
305}
306
307static void __exit exit_nls_cp850(void)
308{
309 unregister_nls(&table);
310}
311
312module_init(init_nls_cp850)
313module_exit(exit_nls_cp850)
314
315MODULE_LICENSE("Dual BSD/GPL");
316