0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/string.h>
0013 #include <linux/nls.h>
0014 #include <linux/kernel.h>
0015 #include <linux/errno.h>
0016 #include <linux/kmod.h>
0017 #include <linux/spinlock.h>
0018 #include <asm/byteorder.h>
0019
0020 static struct nls_table default_table;
0021 static struct nls_table *tables = &default_table;
0022 static DEFINE_SPINLOCK(nls_lock);
0023
0024
0025
0026
0027
0028 struct utf8_table {
0029 int cmask;
0030 int cval;
0031 int shift;
0032 long lmask;
0033 long lval;
0034 };
0035
0036 static const struct utf8_table utf8_table[] =
0037 {
0038 {0x80, 0x00, 0*6, 0x7F, 0, },
0039 {0xE0, 0xC0, 1*6, 0x7FF, 0x80, },
0040 {0xF0, 0xE0, 2*6, 0xFFFF, 0x800, },
0041 {0xF8, 0xF0, 3*6, 0x1FFFFF, 0x10000, },
0042 {0xFC, 0xF8, 4*6, 0x3FFFFFF, 0x200000, },
0043 {0xFE, 0xFC, 5*6, 0x7FFFFFFF, 0x4000000, },
0044 {0, }
0045 };
0046
0047 #define UNICODE_MAX 0x0010ffff
0048 #define PLANE_SIZE 0x00010000
0049
0050 #define SURROGATE_MASK 0xfffff800
0051 #define SURROGATE_PAIR 0x0000d800
0052 #define SURROGATE_LOW 0x00000400
0053 #define SURROGATE_BITS 0x000003ff
0054
0055 int utf8_to_utf32(const u8 *s, int inlen, unicode_t *pu)
0056 {
0057 unsigned long l;
0058 int c0, c, nc;
0059 const struct utf8_table *t;
0060
0061 nc = 0;
0062 c0 = *s;
0063 l = c0;
0064 for (t = utf8_table; t->cmask; t++) {
0065 nc++;
0066 if ((c0 & t->cmask) == t->cval) {
0067 l &= t->lmask;
0068 if (l < t->lval || l > UNICODE_MAX ||
0069 (l & SURROGATE_MASK) == SURROGATE_PAIR)
0070 return -1;
0071 *pu = (unicode_t) l;
0072 return nc;
0073 }
0074 if (inlen <= nc)
0075 return -1;
0076 s++;
0077 c = (*s ^ 0x80) & 0xFF;
0078 if (c & 0xC0)
0079 return -1;
0080 l = (l << 6) | c;
0081 }
0082 return -1;
0083 }
0084 EXPORT_SYMBOL(utf8_to_utf32);
0085
0086 int utf32_to_utf8(unicode_t u, u8 *s, int maxout)
0087 {
0088 unsigned long l;
0089 int c, nc;
0090 const struct utf8_table *t;
0091
0092 if (!s)
0093 return 0;
0094
0095 l = u;
0096 if (l > UNICODE_MAX || (l & SURROGATE_MASK) == SURROGATE_PAIR)
0097 return -1;
0098
0099 nc = 0;
0100 for (t = utf8_table; t->cmask && maxout; t++, maxout--) {
0101 nc++;
0102 if (l <= t->lmask) {
0103 c = t->shift;
0104 *s = (u8) (t->cval | (l >> c));
0105 while (c > 0) {
0106 c -= 6;
0107 s++;
0108 *s = (u8) (0x80 | ((l >> c) & 0x3F));
0109 }
0110 return nc;
0111 }
0112 }
0113 return -1;
0114 }
0115 EXPORT_SYMBOL(utf32_to_utf8);
0116
0117 static inline void put_utf16(wchar_t *s, unsigned c, enum utf16_endian endian)
0118 {
0119 switch (endian) {
0120 default:
0121 *s = (wchar_t) c;
0122 break;
0123 case UTF16_LITTLE_ENDIAN:
0124 *s = __cpu_to_le16(c);
0125 break;
0126 case UTF16_BIG_ENDIAN:
0127 *s = __cpu_to_be16(c);
0128 break;
0129 }
0130 }
0131
0132 int utf8s_to_utf16s(const u8 *s, int inlen, enum utf16_endian endian,
0133 wchar_t *pwcs, int maxout)
0134 {
0135 u16 *op;
0136 int size;
0137 unicode_t u;
0138
0139 op = pwcs;
0140 while (inlen > 0 && maxout > 0 && *s) {
0141 if (*s & 0x80) {
0142 size = utf8_to_utf32(s, inlen, &u);
0143 if (size < 0)
0144 return -EINVAL;
0145 s += size;
0146 inlen -= size;
0147
0148 if (u >= PLANE_SIZE) {
0149 if (maxout < 2)
0150 break;
0151 u -= PLANE_SIZE;
0152 put_utf16(op++, SURROGATE_PAIR |
0153 ((u >> 10) & SURROGATE_BITS),
0154 endian);
0155 put_utf16(op++, SURROGATE_PAIR |
0156 SURROGATE_LOW |
0157 (u & SURROGATE_BITS),
0158 endian);
0159 maxout -= 2;
0160 } else {
0161 put_utf16(op++, u, endian);
0162 maxout--;
0163 }
0164 } else {
0165 put_utf16(op++, *s++, endian);
0166 inlen--;
0167 maxout--;
0168 }
0169 }
0170 return op - pwcs;
0171 }
0172 EXPORT_SYMBOL(utf8s_to_utf16s);
0173
0174 static inline unsigned long get_utf16(unsigned c, enum utf16_endian endian)
0175 {
0176 switch (endian) {
0177 default:
0178 return c;
0179 case UTF16_LITTLE_ENDIAN:
0180 return __le16_to_cpu(c);
0181 case UTF16_BIG_ENDIAN:
0182 return __be16_to_cpu(c);
0183 }
0184 }
0185
0186 int utf16s_to_utf8s(const wchar_t *pwcs, int inlen, enum utf16_endian endian,
0187 u8 *s, int maxout)
0188 {
0189 u8 *op;
0190 int size;
0191 unsigned long u, v;
0192
0193 op = s;
0194 while (inlen > 0 && maxout > 0) {
0195 u = get_utf16(*pwcs, endian);
0196 if (!u)
0197 break;
0198 pwcs++;
0199 inlen--;
0200 if (u > 0x7f) {
0201 if ((u & SURROGATE_MASK) == SURROGATE_PAIR) {
0202 if (u & SURROGATE_LOW) {
0203
0204 continue;
0205 }
0206 if (inlen <= 0)
0207 break;
0208 v = get_utf16(*pwcs, endian);
0209 if ((v & SURROGATE_MASK) != SURROGATE_PAIR ||
0210 !(v & SURROGATE_LOW)) {
0211
0212 continue;
0213 }
0214 u = PLANE_SIZE + ((u & SURROGATE_BITS) << 10)
0215 + (v & SURROGATE_BITS);
0216 pwcs++;
0217 inlen--;
0218 }
0219 size = utf32_to_utf8(u, op, maxout);
0220 if (size == -1) {
0221
0222 } else {
0223 op += size;
0224 maxout -= size;
0225 }
0226 } else {
0227 *op++ = (u8) u;
0228 maxout--;
0229 }
0230 }
0231 return op - s;
0232 }
0233 EXPORT_SYMBOL(utf16s_to_utf8s);
0234
0235 int __register_nls(struct nls_table *nls, struct module *owner)
0236 {
0237 struct nls_table ** tmp = &tables;
0238
0239 if (nls->next)
0240 return -EBUSY;
0241
0242 nls->owner = owner;
0243 spin_lock(&nls_lock);
0244 while (*tmp) {
0245 if (nls == *tmp) {
0246 spin_unlock(&nls_lock);
0247 return -EBUSY;
0248 }
0249 tmp = &(*tmp)->next;
0250 }
0251 nls->next = tables;
0252 tables = nls;
0253 spin_unlock(&nls_lock);
0254 return 0;
0255 }
0256 EXPORT_SYMBOL(__register_nls);
0257
0258 int unregister_nls(struct nls_table * nls)
0259 {
0260 struct nls_table ** tmp = &tables;
0261
0262 spin_lock(&nls_lock);
0263 while (*tmp) {
0264 if (nls == *tmp) {
0265 *tmp = nls->next;
0266 spin_unlock(&nls_lock);
0267 return 0;
0268 }
0269 tmp = &(*tmp)->next;
0270 }
0271 spin_unlock(&nls_lock);
0272 return -EINVAL;
0273 }
0274
0275 static struct nls_table *find_nls(char *charset)
0276 {
0277 struct nls_table *nls;
0278 spin_lock(&nls_lock);
0279 for (nls = tables; nls; nls = nls->next) {
0280 if (!strcmp(nls->charset, charset))
0281 break;
0282 if (nls->alias && !strcmp(nls->alias, charset))
0283 break;
0284 }
0285 if (nls && !try_module_get(nls->owner))
0286 nls = NULL;
0287 spin_unlock(&nls_lock);
0288 return nls;
0289 }
0290
0291 struct nls_table *load_nls(char *charset)
0292 {
0293 return try_then_request_module(find_nls(charset), "nls_%s", charset);
0294 }
0295
0296 void unload_nls(struct nls_table *nls)
0297 {
0298 if (nls)
0299 module_put(nls->owner);
0300 }
0301
0302 static const wchar_t charset2uni[256] = {
0303
0304 0x0000, 0x0001, 0x0002, 0x0003,
0305 0x0004, 0x0005, 0x0006, 0x0007,
0306 0x0008, 0x0009, 0x000a, 0x000b,
0307 0x000c, 0x000d, 0x000e, 0x000f,
0308
0309 0x0010, 0x0011, 0x0012, 0x0013,
0310 0x0014, 0x0015, 0x0016, 0x0017,
0311 0x0018, 0x0019, 0x001a, 0x001b,
0312 0x001c, 0x001d, 0x001e, 0x001f,
0313
0314 0x0020, 0x0021, 0x0022, 0x0023,
0315 0x0024, 0x0025, 0x0026, 0x0027,
0316 0x0028, 0x0029, 0x002a, 0x002b,
0317 0x002c, 0x002d, 0x002e, 0x002f,
0318
0319 0x0030, 0x0031, 0x0032, 0x0033,
0320 0x0034, 0x0035, 0x0036, 0x0037,
0321 0x0038, 0x0039, 0x003a, 0x003b,
0322 0x003c, 0x003d, 0x003e, 0x003f,
0323
0324 0x0040, 0x0041, 0x0042, 0x0043,
0325 0x0044, 0x0045, 0x0046, 0x0047,
0326 0x0048, 0x0049, 0x004a, 0x004b,
0327 0x004c, 0x004d, 0x004e, 0x004f,
0328
0329 0x0050, 0x0051, 0x0052, 0x0053,
0330 0x0054, 0x0055, 0x0056, 0x0057,
0331 0x0058, 0x0059, 0x005a, 0x005b,
0332 0x005c, 0x005d, 0x005e, 0x005f,
0333
0334 0x0060, 0x0061, 0x0062, 0x0063,
0335 0x0064, 0x0065, 0x0066, 0x0067,
0336 0x0068, 0x0069, 0x006a, 0x006b,
0337 0x006c, 0x006d, 0x006e, 0x006f,
0338
0339 0x0070, 0x0071, 0x0072, 0x0073,
0340 0x0074, 0x0075, 0x0076, 0x0077,
0341 0x0078, 0x0079, 0x007a, 0x007b,
0342 0x007c, 0x007d, 0x007e, 0x007f,
0343
0344 0x0080, 0x0081, 0x0082, 0x0083,
0345 0x0084, 0x0085, 0x0086, 0x0087,
0346 0x0088, 0x0089, 0x008a, 0x008b,
0347 0x008c, 0x008d, 0x008e, 0x008f,
0348
0349 0x0090, 0x0091, 0x0092, 0x0093,
0350 0x0094, 0x0095, 0x0096, 0x0097,
0351 0x0098, 0x0099, 0x009a, 0x009b,
0352 0x009c, 0x009d, 0x009e, 0x009f,
0353
0354 0x00a0, 0x00a1, 0x00a2, 0x00a3,
0355 0x00a4, 0x00a5, 0x00a6, 0x00a7,
0356 0x00a8, 0x00a9, 0x00aa, 0x00ab,
0357 0x00ac, 0x00ad, 0x00ae, 0x00af,
0358
0359 0x00b0, 0x00b1, 0x00b2, 0x00b3,
0360 0x00b4, 0x00b5, 0x00b6, 0x00b7,
0361 0x00b8, 0x00b9, 0x00ba, 0x00bb,
0362 0x00bc, 0x00bd, 0x00be, 0x00bf,
0363
0364 0x00c0, 0x00c1, 0x00c2, 0x00c3,
0365 0x00c4, 0x00c5, 0x00c6, 0x00c7,
0366 0x00c8, 0x00c9, 0x00ca, 0x00cb,
0367 0x00cc, 0x00cd, 0x00ce, 0x00cf,
0368
0369 0x00d0, 0x00d1, 0x00d2, 0x00d3,
0370 0x00d4, 0x00d5, 0x00d6, 0x00d7,
0371 0x00d8, 0x00d9, 0x00da, 0x00db,
0372 0x00dc, 0x00dd, 0x00de, 0x00df,
0373
0374 0x00e0, 0x00e1, 0x00e2, 0x00e3,
0375 0x00e4, 0x00e5, 0x00e6, 0x00e7,
0376 0x00e8, 0x00e9, 0x00ea, 0x00eb,
0377 0x00ec, 0x00ed, 0x00ee, 0x00ef,
0378
0379 0x00f0, 0x00f1, 0x00f2, 0x00f3,
0380 0x00f4, 0x00f5, 0x00f6, 0x00f7,
0381 0x00f8, 0x00f9, 0x00fa, 0x00fb,
0382 0x00fc, 0x00fd, 0x00fe, 0x00ff,
0383 };
0384
0385 static const unsigned char page00[256] = {
0386 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0387 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0388 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0389 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0390 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0391 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0392 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0393 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0394 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0395 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0396 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0397 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0398 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0399 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0400 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0401 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0402
0403 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0404 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0405 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0406 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0407 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0408 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0409 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0410 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0411 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0412 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0413 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0414 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0415 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0416 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0417 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0418 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0419 };
0420
0421 static const unsigned char *const page_uni2charset[256] = {
0422 page00
0423 };
0424
0425 static const unsigned char charset2lower[256] = {
0426 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0427 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0428 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0429 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0430 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0431 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0432 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0433 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0434 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0435 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0436 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0437 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0438 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0439 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0440 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0441 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0442
0443 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0444 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0445 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0446 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0447 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0448 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0449 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0450 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0451 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0452 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0453 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0454 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0455 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0456 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0457 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0458 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0459 };
0460
0461 static const unsigned char charset2upper[256] = {
0462 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0463 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0464 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0465 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0466 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0467 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0468 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0469 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0470 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0471 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0472 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0473 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0474 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0475 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0476 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0477 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0478
0479 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0480 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0481 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0482 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0483 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0484 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0485 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0486 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0487 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0488 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0489 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0490 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0491 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0492 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0493 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0494 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0495 };
0496
0497
0498 static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
0499 {
0500 const unsigned char *uni2charset;
0501 unsigned char cl = uni & 0x00ff;
0502 unsigned char ch = (uni & 0xff00) >> 8;
0503
0504 if (boundlen <= 0)
0505 return -ENAMETOOLONG;
0506
0507 uni2charset = page_uni2charset[ch];
0508 if (uni2charset && uni2charset[cl])
0509 out[0] = uni2charset[cl];
0510 else
0511 return -EINVAL;
0512 return 1;
0513 }
0514
0515 static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
0516 {
0517 *uni = charset2uni[*rawstring];
0518 if (*uni == 0x0000)
0519 return -EINVAL;
0520 return 1;
0521 }
0522
0523 static struct nls_table default_table = {
0524 .charset = "default",
0525 .uni2char = uni2char,
0526 .char2uni = char2uni,
0527 .charset2lower = charset2lower,
0528 .charset2upper = charset2upper,
0529 };
0530
0531
0532 struct nls_table *load_nls_default(void)
0533 {
0534 struct nls_table *default_nls;
0535
0536 default_nls = load_nls(CONFIG_NLS_DEFAULT);
0537 if (default_nls != NULL)
0538 return default_nls;
0539 else
0540 return &default_table;
0541 }
0542
0543 EXPORT_SYMBOL(unregister_nls);
0544 EXPORT_SYMBOL(unload_nls);
0545 EXPORT_SYMBOL(load_nls);
0546 EXPORT_SYMBOL(load_nls_default);
0547
0548 MODULE_LICENSE("Dual BSD/GPL");