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, 0x016f, 0x0107, 0x00e7,
60 0x0142, 0x00eb, 0x0150, 0x0151,
61 0x00ee, 0x0179, 0x00c4, 0x0106,
62
63 0x00c9, 0x0139, 0x013a, 0x00f4,
64 0x00f6, 0x013d, 0x013e, 0x015a,
65 0x015b, 0x00d6, 0x00dc, 0x0164,
66 0x0165, 0x0141, 0x00d7, 0x010d,
67
68 0x00e1, 0x00ed, 0x00f3, 0x00fa,
69 0x0104, 0x0105, 0x017d, 0x017e,
70 0x0118, 0x0119, 0x00ac, 0x017a,
71 0x010c, 0x015f, 0x00ab, 0x00bb,
72
73 0x2591, 0x2592, 0x2593, 0x2502,
74 0x2524, 0x00c1, 0x00c2, 0x011a,
75 0x015e, 0x2563, 0x2551, 0x2557,
76 0x255d, 0x017b, 0x017c, 0x2510,
77
78 0x2514, 0x2534, 0x252c, 0x251c,
79 0x2500, 0x253c, 0x0102, 0x0103,
80 0x255a, 0x2554, 0x2569, 0x2566,
81 0x2560, 0x2550, 0x256c, 0x00a4,
82
83 0x0111, 0x0110, 0x010e, 0x00cb,
84 0x010f, 0x0147, 0x00cd, 0x00ce,
85 0x011b, 0x2518, 0x250c, 0x2588,
86 0x2584, 0x0162, 0x016e, 0x2580,
87
88 0x00d3, 0x00df, 0x00d4, 0x0143,
89 0x0144, 0x0148, 0x0160, 0x0161,
90 0x0154, 0x00da, 0x0155, 0x0170,
91 0x00fd, 0x00dd, 0x0163, 0x00b4,
92
93 0x00ad, 0x02dd, 0x02db, 0x02c7,
94 0x02d8, 0x00a7, 0x00f7, 0x00b8,
95 0x00b0, 0x00a8, 0x02d9, 0x0171,
96 0x0158, 0x0159, 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, 0x00, 0x00, 0x00, 0xcf, 0x00, 0x00, 0xf5,
122 0xf9, 0x00, 0x00, 0xae, 0xaa, 0xf0, 0x00, 0x00,
123 0xf8, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00,
124 0xf7, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0xb5, 0xb6, 0x00, 0x8e, 0x00, 0x00, 0x80,
126 0x00, 0x90, 0x00, 0xd3, 0x00, 0xd6, 0xd7, 0x00,
127 0x00, 0x00, 0x00, 0xe0, 0xe2, 0x00, 0x99, 0x9e,
128 0x00, 0x00, 0xe9, 0x00, 0x9a, 0xed, 0x00, 0xe1,
129 0x00, 0xa0, 0x83, 0x00, 0x84, 0x00, 0x00, 0x87,
130 0x00, 0x82, 0x00, 0x89, 0x00, 0xa1, 0x8c, 0x00,
131 0x00, 0x00, 0x00, 0xa2, 0x93, 0x00, 0x94, 0xf6,
132 0x00, 0x00, 0xa3, 0x00, 0x81, 0xec, 0x00, 0x00,
133};
134
135static const unsigned char page01[256] = {
136 0x00, 0x00, 0xc6, 0xc7, 0xa4, 0xa5, 0x8f, 0x86,
137 0x00, 0x00, 0x00, 0x00, 0xac, 0x9f, 0xd2, 0xd4,
138 0xd1, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0xa8, 0xa9, 0xb7, 0xd8, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x91, 0x92, 0x00, 0x00, 0x95, 0x96, 0x00,
144 0x00, 0x9d, 0x88, 0xe3, 0xe4, 0x00, 0x00, 0xd5,
145 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x8a, 0x8b, 0x00, 0x00, 0xe8, 0xea, 0x00, 0x00,
147 0xfc, 0xfd, 0x97, 0x98, 0x00, 0x00, 0xb8, 0xad,
148 0xe6, 0xe7, 0xdd, 0xee, 0x9b, 0x9c, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x85,
150 0xeb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x8d, 0xab, 0xbd, 0xbe, 0xa6, 0xa7, 0x00,
152};
153
154static const unsigned char page02[256] = {
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171
172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3,
181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0xf4, 0xfa, 0x00, 0xf2, 0x00, 0xf1, 0x00, 0x00,
184};
185
186static const unsigned char page25[256] = {
187 0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00,
189 0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
190 0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0xcd, 0xba, 0x00, 0x00, 0xc9, 0x00, 0x00, 0xbb,
198 0x00, 0x00, 0xc8, 0x00, 0x00, 0xbc, 0x00, 0x00,
199 0xcc, 0x00, 0x00, 0xb9, 0x00, 0x00, 0xcb, 0x00,
200 0x00, 0xca, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203
204 0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
205 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209};
210
211static const unsigned char *const page_uni2charset[256] = {
212 page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
213 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
214 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
215 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
216 NULL, NULL, NULL, NULL, NULL, page25, NULL, NULL,
217};
218
219static const unsigned char charset2lower[256] = {
220 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
221 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
222 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
223 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
224 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
225 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
226 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
227 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
228 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
229 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
230 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
231 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
232 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
233 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
234 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
235 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
236
237 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
238 0x88, 0x89, 0x8b, 0x8b, 0x8c, 0xab, 0x84, 0x86,
239 0x82, 0x92, 0x92, 0x93, 0x94, 0x96, 0x96, 0x98,
240 0x98, 0x94, 0x81, 0x9c, 0x9c, 0x88, 0x9e, 0x9f,
241 0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa7, 0xa7,
242 0xa9, 0xa9, 0xaa, 0xab, 0x9f, 0xad, 0xae, 0xaf,
243 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xa0, 0x83, 0xd8,
244 0xad, 0xb9, 0xba, 0xbb, 0xbc, 0xbe, 0xbe, 0xbf,
245 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc7,
246 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
247 0xd0, 0xd0, 0xd4, 0x89, 0xd4, 0xe5, 0xa1, 0x8c,
248 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xee, 0x85, 0xdf,
249 0xa2, 0xe1, 0x93, 0xe4, 0xe4, 0xe5, 0xe7, 0xe7,
250 0xea, 0xa3, 0xea, 0xfb, 0xec, 0xec, 0xee, 0xef,
251 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
252 0xf8, 0xf9, 0xfa, 0xfb, 0xfd, 0xfd, 0xfe, 0xff,
253};
254
255static const unsigned char charset2upper[256] = {
256 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
257 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
258 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
259 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
260 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
261 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
262 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
263 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
264 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
265 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
266 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
267 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
268 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
269 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
270 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
271 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
272
273 0x80, 0x9a, 0x90, 0xb6, 0x8e, 0xde, 0x8f, 0x80,
274 0x9d, 0xd3, 0x8a, 0x8a, 0xd7, 0x8d, 0x8e, 0x8f,
275 0x90, 0x91, 0x91, 0xe2, 0x99, 0x95, 0x95, 0x97,
276 0x97, 0x99, 0x9a, 0x9b, 0x9b, 0x9d, 0x9e, 0xac,
277 0xb5, 0xd6, 0xe0, 0xe9, 0xa4, 0xa4, 0xa6, 0xa6,
278 0xa8, 0xa8, 0xaa, 0x8d, 0xac, 0xb8, 0xae, 0xaf,
279 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
280 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbd, 0xbf,
281 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6,
282 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
283 0xd1, 0xd1, 0xd2, 0xd3, 0xd2, 0xd5, 0xd6, 0xd7,
284 0xb7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
285 0xe0, 0xe1, 0xe2, 0xe3, 0xe3, 0xd5, 0xe6, 0xe6,
286 0xe8, 0xe9, 0xe8, 0xeb, 0xed, 0xed, 0xdd, 0xef,
287 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
288 0xf8, 0xf9, 0xfa, 0xeb, 0xfc, 0xfc, 0xfe, 0xff,
289};
290
291static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
292{
293 const unsigned char *uni2charset;
294 unsigned char cl = uni & 0x00ff;
295 unsigned char ch = (uni & 0xff00) >> 8;
296
297 if (boundlen <= 0)
298 return -ENAMETOOLONG;
299
300 uni2charset = page_uni2charset[ch];
301 if (uni2charset && uni2charset[cl])
302 out[0] = uni2charset[cl];
303 else
304 return -EINVAL;
305 return 1;
306}
307
308static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
309{
310 *uni = charset2uni[*rawstring];
311 if (*uni == 0x0000)
312 return -EINVAL;
313 return 1;
314}
315
316static struct nls_table table = {
317 .charset = "cp852",
318 .uni2char = uni2char,
319 .char2uni = char2uni,
320 .charset2lower = charset2lower,
321 .charset2upper = charset2upper,
322 .owner = THIS_MODULE,
323};
324
325static int __init init_nls_cp852(void)
326{
327 return register_nls(&table);
328}
329
330static void __exit exit_nls_cp852(void)
331{
332 unregister_nls(&table);
333}
334
335module_init(init_nls_cp852)
336module_exit(exit_nls_cp852)
337
338MODULE_LICENSE("Dual BSD/GPL");
339