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