0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/kernel.h>
0012 #include <linux/string.h>
0013 #include <linux/nls.h>
0014 #include <linux/errno.h>
0015
0016 static const wchar_t charset2uni[256] = {
0017
0018 0x0000, 0x0001, 0x0002, 0x0003,
0019 0x0004, 0x0005, 0x0006, 0x0007,
0020 0x0008, 0x0009, 0x000a, 0x000b,
0021 0x000c, 0x000d, 0x000e, 0x000f,
0022
0023 0x0010, 0x0011, 0x0012, 0x0013,
0024 0x0014, 0x0015, 0x0016, 0x0017,
0025 0x0018, 0x0019, 0x001a, 0x001b,
0026 0x001c, 0x001d, 0x001e, 0x001f,
0027
0028 0x0020, 0x0021, 0x0022, 0x0023,
0029 0x0024, 0x0025, 0x0026, 0x0027,
0030 0x0028, 0x0029, 0x002a, 0x002b,
0031 0x002c, 0x002d, 0x002e, 0x002f,
0032
0033 0x0030, 0x0031, 0x0032, 0x0033,
0034 0x0034, 0x0035, 0x0036, 0x0037,
0035 0x0038, 0x0039, 0x003a, 0x003b,
0036 0x003c, 0x003d, 0x003e, 0x003f,
0037
0038 0x0040, 0x0041, 0x0042, 0x0043,
0039 0x0044, 0x0045, 0x0046, 0x0047,
0040 0x0048, 0x0049, 0x004a, 0x004b,
0041 0x004c, 0x004d, 0x004e, 0x004f,
0042
0043 0x0050, 0x0051, 0x0052, 0x0053,
0044 0x0054, 0x0055, 0x0056, 0x0057,
0045 0x0058, 0x0059, 0x005a, 0x005b,
0046 0x005c, 0x005d, 0x005e, 0x005f,
0047
0048 0x0060, 0x0061, 0x0062, 0x0063,
0049 0x0064, 0x0065, 0x0066, 0x0067,
0050 0x0068, 0x0069, 0x006a, 0x006b,
0051 0x006c, 0x006d, 0x006e, 0x006f,
0052
0053 0x0070, 0x0071, 0x0072, 0x0073,
0054 0x0074, 0x0075, 0x0076, 0x0077,
0055 0x0078, 0x0079, 0x007a, 0x007b,
0056 0x007c, 0x007d, 0x007e, 0x007f,
0057
0058 0x0410, 0x0411, 0x0412, 0x0413,
0059 0x0414, 0x0415, 0x0416, 0x0417,
0060 0x0418, 0x0419, 0x041a, 0x041b,
0061 0x041c, 0x041d, 0x041e, 0x041f,
0062
0063 0x0420, 0x0421, 0x0422, 0x0423,
0064 0x0424, 0x0425, 0x0426, 0x0427,
0065 0x0428, 0x0429, 0x042a, 0x042b,
0066 0x042c, 0x042d, 0x042e, 0x042f,
0067
0068 0x0430, 0x0431, 0x0432, 0x0433,
0069 0x0434, 0x0435, 0x0436, 0x0437,
0070 0x0438, 0x0439, 0x043a, 0x043b,
0071 0x043c, 0x043d, 0x043e, 0x043f,
0072
0073 0x2591, 0x2592, 0x2593, 0x2502,
0074 0x2524, 0x2561, 0x2562, 0x2556,
0075 0x2555, 0x2563, 0x2551, 0x2557,
0076 0x255d, 0x255c, 0x255b, 0x2510,
0077
0078 0x2514, 0x2534, 0x252c, 0x251c,
0079 0x2500, 0x253c, 0x255e, 0x255f,
0080 0x255a, 0x2554, 0x2569, 0x2566,
0081 0x2560, 0x2550, 0x256c, 0x2567,
0082
0083 0x2568, 0x2564, 0x2565, 0x2559,
0084 0x2558, 0x2552, 0x2553, 0x256b,
0085 0x256a, 0x2518, 0x250c, 0x2588,
0086 0x2584, 0x258c, 0x2590, 0x2580,
0087
0088 0x0440, 0x0441, 0x0442, 0x0443,
0089 0x0444, 0x0445, 0x0446, 0x0447,
0090 0x0448, 0x0449, 0x044a, 0x044b,
0091 0x044c, 0x044d, 0x044e, 0x044f,
0092
0093 0x0401, 0x0451, 0x0404, 0x0454,
0094 0x0407, 0x0457, 0x040e, 0x045e,
0095 0x00b0, 0x2219, 0x00b7, 0x221a,
0096 0x2116, 0x00a4, 0x25a0, 0x00a0,
0097 };
0098
0099 static const unsigned char page00[256] = {
0100 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0101 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0102 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0103 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0104 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0105 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0106 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0107 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0108 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0109 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0110 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0111 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0112 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0113 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0114 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0115 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0116
0117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0121 0xff, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00,
0122 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0123 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa,
0124 };
0125
0126 static const unsigned char page04[256] = {
0127 0x00, 0xf0, 0x00, 0x00, 0xf2, 0x00, 0x00, 0xf4,
0128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x00,
0129 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0130 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0131 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0132 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0133 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0134 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0135 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0136 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0137 0x00, 0xf1, 0x00, 0x00, 0xf3, 0x00, 0x00, 0xf5,
0138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00,
0139 };
0140
0141 static const unsigned char page21[256] = {
0142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00,
0145 };
0146
0147 static const unsigned char page22[256] = {
0148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0151 0x00, 0xf9, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00,
0152 };
0153
0154 static const unsigned char page25[256] = {
0155 0xc4, 0x00, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00,
0156 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00,
0157 0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
0158 0xd9, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x00,
0159 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
0160 0x00, 0x00, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x00,
0161 0x00, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00,
0162 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00,
0163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0165 0xcd, 0xba, 0xd5, 0xd6, 0xc9, 0xb8, 0xb7, 0xbb,
0166 0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, 0xc7,
0167 0xcc, 0xb5, 0xb6, 0xb9, 0xd1, 0xd2, 0xcb, 0xcf,
0168 0xd0, 0xca, 0xd8, 0xd7, 0xce, 0x00, 0x00, 0x00,
0169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0171
0172 0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00,
0173 0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00,
0174 0xde, 0xb0, 0xb1, 0xb2, 0x00, 0x00, 0x00, 0x00,
0175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0176 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0177 };
0178
0179 static const unsigned char *const page_uni2charset[256] = {
0180 page00, NULL, NULL, NULL, page04, NULL, NULL, NULL,
0181 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0182 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0183 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0184 NULL, page21, page22, NULL, NULL, page25, NULL, NULL,
0185 };
0186
0187 static const unsigned char charset2lower[256] = {
0188 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0189 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0190 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0191 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0192 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0193 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0194 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0195 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0196 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0197 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0198 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0199 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0200 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0201 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0202 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0203 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0204
0205 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0206 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0207 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0208 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0209 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0210 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0211 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0212 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0213 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0214 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0215 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0216 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0217 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0218 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0219 0xf1, 0xf1, 0xf3, 0xf3, 0xf5, 0xf5, 0xf7, 0xf7,
0220 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0221 };
0222
0223 static const unsigned char charset2upper[256] = {
0224 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0225 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0226 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0227 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0228 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0229 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0230 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0231 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0232 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0233 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0234 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0235 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0236 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0237 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0238 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0239 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0240
0241 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0242 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0243 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0244 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0245 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0246 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0247 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0248 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0249 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0250 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0251 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0252 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0253 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0254 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0255 0xf0, 0xf0, 0xf2, 0xf2, 0xf4, 0xf4, 0xf6, 0xf6,
0256 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0257 };
0258
0259 static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
0260 {
0261 const unsigned char *uni2charset;
0262 unsigned char cl = uni & 0x00ff;
0263 unsigned char ch = (uni & 0xff00) >> 8;
0264
0265 if (boundlen <= 0)
0266 return -ENAMETOOLONG;
0267
0268 uni2charset = page_uni2charset[ch];
0269 if (uni2charset && uni2charset[cl])
0270 out[0] = uni2charset[cl];
0271 else
0272 return -EINVAL;
0273 return 1;
0274 }
0275
0276 static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
0277 {
0278 *uni = charset2uni[*rawstring];
0279 if (*uni == 0x0000)
0280 return -EINVAL;
0281 return 1;
0282 }
0283
0284 static struct nls_table table = {
0285 .charset = "cp866",
0286 .uni2char = uni2char,
0287 .char2uni = char2uni,
0288 .charset2lower = charset2lower,
0289 .charset2upper = charset2upper,
0290 };
0291
0292 static int __init init_nls_cp866(void)
0293 {
0294 return register_nls(&table);
0295 }
0296
0297 static void __exit exit_nls_cp866(void)
0298 {
0299 unregister_nls(&table);
0300 }
0301
0302 module_init(init_nls_cp866)
0303 module_exit(exit_nls_cp866)
0304
0305 MODULE_LICENSE("Dual BSD/GPL");