#include "typedef.h" #include "usb_stack.h" #include "hid.h" #include "generic/jiffies.h" #define KB_LED_NUM_LOCK 0x01 #define KB_LED_CAPS_LOCK 0x02 #define KB_LED_SCROLL_LOCK 0x04 #define KB_LED_COMPOSE 0x08 #define KB_LED_KANA 0x10 struct usb_hid_keyboard { usb_dev usb_id; u8 kb_leds_sta; }; static struct usb_hid_keyboard hid_kb; static struct usb_hid_keyboard *const __this = &hid_kb; const u8 report_keyboard[] = { 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, #if 1 //OUTPUT 0x95, 0x05, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91, 0x03, #endif 0xc0, }; u8 *hid_keyboard_get_report_desc() { return (u8 *)report_keyboard; } u32 hid_keyboard_get_report_desc_size() { return sizeof(report_keyboard); } int inter2string(int value, char *s, int len) { char tmp; int count = 0; char symbol = 0; if (s == NULL) { return -1; } if (value < 0) { value = -value; symbol = 1; } do { s[count++] = value % 10 + '0'; value = value / 10; } while (value != 0 && count < len); if (count > len - 1 - symbol) { return -2; } if (symbol) { s[count] = '-'; s[count + 1] = 0; count++; } else { s[count] = 0; } len = count; for (count = 0; count < len / 2; count++) { tmp = s[count]; s[count] = s[len - 1 - count]; s[len - 1 - count] = tmp; } return len; } int string2inter(const char *s, int len, int *val) { char *p = (char *)s; char symbol = 0; char radix = 10; //进制,取值为16,10,8 int err = 0; if (!p) { return -1; } if (*p == '-') { symbol = 1; p++; radix = 10; } else if (*p == '+') { symbol = 0; p++; radix = 10; } else if (*p == '0' && len >= 2 && (*(p + 1) == 'x' || *(p + 1) == 'X')) { radix = 16; while (*p != 0) { //upper to lower if (*p >= 'A' && *p <= 'Z') { *p += 'a' - 'A'; } p++; } p = (char *)s + 2; } else if (*p == '0' && len >= 2 && *(p + 1) != 'x' && *(p + 1) != 'X') { radix = 8; p++; } *val = 0; while (*p && len--) { if (radix == 16) { if (*p >= '0' && *p <= '9') { *val *= 16; *val += *p - '0'; } else if (*p >= 'a' && *p <= 'f') { *val *= 16; *val += *p - 'a' + 10; } else { return -2; } } else if (radix == 10) { if (*p < '0' || *p > '9') { return -2; } *val *= 10; *val += *p - '0'; } else if (radix == 8) { if (*p < '0' || *p > '7') { return -2; } *val *= 8; *val += *p - '0'; } p++; } *val = symbol ? -(*val) : *val; return err; } static const u16 ascii2kb_remap[128] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x002a, 0x002b, 0x0028, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0 ~ 15 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 16 ~ 31 0x002c, 0x011e, 0x0134, 0x0120, 0x0121, 0x0122, 0x0124, 0x0034, 0x0126, 0x0127, 0x0125, 0x012e, 0x0036, 0x002d, 0x0037, 0x0038, // 32 ~ 47 0x0027, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0133, 0x0033, 0x0136, 0x002e, 0x0137, 0x0138, // 48 ~ 63 0x011f, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f, 0x0110, 0x0111, 0x0112, // 64 ~ 79 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x002f, 0x0031, 0x0030, 0x0123, 0x012d, // 80 ~ 95 0x0035, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, // 96 ~ 111 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x012f, 0x0131, 0x0130, 0x0135, 0x0000, // 112 ~ 127 }; /* --------------------------------------------------------------------------*/ /** * @brief hid keyboard send one key * @param key - ascii code * @return NULL * * @additional infomation * modifier key bitmap * - bit0 left control * - bit1 left shift * - bit2 left alt * - bit3 left gui * - bit4 right control * - bit5 right shift * - bit6 right alt * - bit7 right gui */ /* --------------------------------------------------------------------------*/ static void hid_keyboard_send_onekey(u8 key) { static u8 last_key = 0; u8 buf[8] = {0}; u8 err = 0; if (key > sizeof(ascii2kb_remap) / sizeof(ascii2kb_remap[0])) { printf("ERR KEY %x", key); return; } #if 1 if ((ascii2kb_remap[key] & 0xff) == (ascii2kb_remap[last_key] & 0xff)) { buf[0] = (ascii2kb_remap[last_key] & 0x0100) ? 0x02 : 0; if (__this->kb_leds_sta & KB_LED_CAPS_LOCK) { if ((last_key >= 'a' && last_key <= 'z') || (last_key >= 'A' && last_key <= 'Z')) { buf[0] ^= 0x02; } } if ((buf[0] & 0x02) == 0) { buf[0] = 0x00; //shift key buf[2] = 0x00; hid_send_buf_async(__this->usb_id, buf, 8); //hid_tx_data(__this->usb_id, buf, 8); } } last_key = key; buf[0] = ascii2kb_remap[key] & 0x0100 ? 0x02 : 0x00; //shift key if (__this->kb_leds_sta & KB_LED_CAPS_LOCK) { if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')) { buf[0] ^= 0x02; } } buf[2] = (u8)(ascii2kb_remap[key] & 0xff); hid_send_buf_async(__this->usb_id, buf, 8); //hid_tx_data(__this->usb_id, buf, 8); if (buf[2] & 0x02) { buf[0] = 0; buf[2] = 0; hid_send_buf_async(__this->usb_id, buf, 8); //hid_tx_data(__this->usb_id, buf, 8); } #else buf[0] = ascii2kb_remap[key] & 0x0100 ? 0x02 : 0x00; //shift key if (__this->kb_leds_sta & KB_LED_CAPS_LOCK) { if ((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z')) { buf[0] ^= 0x02; } } buf[2] = (u8)(ascii2kb_remap[key] & 0xff); if ((buf[0] & 0x02) && buf[2] != 0) { u8 tmpbuf[8] = {0x02}; //hid_send_buf_async(__this->usb_id, buf, 8); hid_tx_data(__this->usb_id, tmpbuf, 8); } //hid_send_buf_async(__this->usb_id, buf, 8); hid_tx_data(__this->usb_id, buf, 8); if ((buf[0] & 0x02) && buf[2] != 0) { u8 tmpbuf[8] = {0x02}; //hid_send_buf_async(__this->usb_id, buf, 8); hid_tx_data(__this->usb_id, tmpbuf, 8); } buf[0] = 0x00; //shift key buf[2] = 0x00; //hid_send_buf_async(__this->usb_id, buf, 8); hid_tx_data(__this->usb_id, buf, 8); #endif } static const u16 ascii2kp_remap[128] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0058, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 0 ~ 15 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 16 ~ 31 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0055, 0x0057, 0x0000, 0x0056, 0x0063, 0x0054, // 32 ~ 47 0x0062, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x0060, 0x0061, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 48 ~ 63 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 64 ~ 79 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 80 ~ 95 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 96 ~ 111 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 112 ~ 127 }; static void hid_keyboard_send_wc_gbk(u16 wchar) { char numeric_str[6] = {0}; u8 buf[8] = {0}; int err; char *p; buf[0] = BIT(2); //left alt hid_send_buf_async(__this->usb_id, buf, 8); //hid_tx_data(__this->usb_id, buf, 8); inter2string(wchar, numeric_str, sizeof(numeric_str)); //printf("%c%c, %d, %s\n", ((u8 *)&wchar)[1], ((u8 *)&wchar)[0], wchar, numeric_str); p = numeric_str; while (*p != 0) { buf[0] = BIT(2); //left alt buf[2] = ascii2kp_remap[*p] & 0xff; hid_send_buf_async(__this->usb_id, buf, 8); //hid_tx_data(__this->usb_id, buf, 8); buf[0] = BIT(2); //left alt buf[2] = 0; hid_send_buf_async(__this->usb_id, buf, 8); //hid_tx_data(__this->usb_id, buf, 8); p++; } buf[0] = 0; buf[2] = 0; hid_send_buf_async(__this->usb_id, buf, 8); //hid_tx_data(__this->usb_id, buf, 8); } int hid_keyboard_send(const u8 *data, u32 len) { int i; u32 start_time = jiffies; u16 wchar_gbk; u8 is_tax_code = 0; u32 len2; u8 lf = 0; u8 *ptr = (u8 *)data; //国税总局发票助手二维码格式 if (len > 11 && ptr[0] == '$' && ptr[1] == '0' && ptr[2] == '1') { len2 = len; while (len2 > 11) { if (ptr[len2 - 1] == '$') { is_tax_code = 1; len = len2 - 3; //begin: $01 len -= 1; //end: $ ptr += 3; u8 *tmpbuf = zalloc(len); if (!tmpbuf) { printf("malloc tmpbuf fail\n"); return -1; } // << need function prototype>> //base64_decode(tmpbuf, ptr, len); len -= 4; //CRC16 if (!memcmp(&tmpbuf[len - 3], "", 3)) { len -= 3; // } ptr = tmpbuf; break; } else if (ptr[len2 - 1] == '\n') { lf = 1; } len2--; } } if (is_tax_code != 0) { printf("================ is tax qrcode ================\n"); i = 0; while (i < len) { if (ptr[i] >= 0x81 && ptr[i] <= 0xfe) { if ((i + 1 < len) && ptr[i + 1] >= 0x40 && ptr[i + 1] <= 0xfe) { wchar_gbk = (ptr[i] << 8) + ptr[i + 1]; hid_keyboard_send_wc_gbk(wchar_gbk); i++; } i++; } else if ((i + 2 < len) && !memcmp(&ptr[i], "", 3)) { hid_keyboard_send_onekey('\t'); i += 3; } else { hid_keyboard_send_onekey(ptr[i]); i++; } } if (lf != 0) { hid_keyboard_send_onekey('\n'); } } else { i = 0; while (i < len) { if (ptr[i] < 0x80) { hid_keyboard_send_onekey(ptr[i]); i++; } else { //utf-8 code i += 2; } } } hid_keyboard_send_onekey(0); printf("usb send ptr %3d[in %d ms]: %s\n", len, jiffies_to_msecs(jiffies - start_time), ptr); if (ptr != data) { free(ptr); } return 0; } int hid_keyboard_output(u8 *buf, u32 len) { puts("hid output report\n"); put_buf(buf, len); __this->kb_leds_sta = buf[0]; return len; } void hid_keyboard_set_usb_dev(usb_dev usb_id) { __this->usb_id = usb_id; }