Печати на клавиатуре с крохой


Я пытаюсь написать кусок кода, который будет имитировать выход через клавиатуру ASCII. Он использует клавиатуру библиотеку из pjrc, но приложение, я работаю над требует вывода последовательности символов, а не отдельные ключи ( с++ интерфейс предоставляет клавиатуру.печать, которая делает именно то, что я хочу, за исключением того, что я пытаюсь придерживаться С в учебных целях).

Вот такой удар по нему;

[snip]
#include <string.h>
#include "usb_keyboard.h" // definitions for the /KEY_\w+/ symbols

int key_from_char(char c){
  if (c >= 'a' && c <= 'z') return c + KEY_A - 'a';
  if (c >= 'A' && c <= 'Z') return c + KEY_A - 'A';
  if (c >= '1' && c <= '9') return c + KEY_A - '1';
  if (c == '0') return 39; // 0 is low in ASCII, high in the USB key definition

  // there's no easy mapping between the other ASCII characters and 
  // USB keyboard keys, so these are all manually represented
  switch (c) {
  case ' ': return KEY_SPACE; break;
  case '!': return KEY_1; break;
  case '"': return KEY_QUOTE; break;
  case '#': return KEY_NUMBER; break;
  case '$': return KEY_4; break;
  case '%': return KEY_5; break;
  case '&': return KEY_7; break;
  case '\'': return KEY_QUOTE; break;
  case '(': return KEY_9; break;
  case ')': return KEY_0; break;
  case '*': return KEYPAD_ASTERIX; break;
  case '+': return KEYPAD_PLUS; break;
  case ',': return KEY_COMMA; break;
  case '-': return KEYPAD_MINUS; break;
  case '.': return KEY_PERIOD; break;
  case '/': return KEYPAD_SLASH; break;

  case ':': return KEY_SEMICOLON; break;
  case ';': return KEY_SEMICOLON; break;
  case '<': return KEY_COMMA; break;
  case '=': return KEY_EQUAL; break;
  case '>': return KEY_PERIOD; break;
  case '?': return KEY_SLASH; break;
  case '@': return KEY_2; break;

  case '[': return KEY_LEFT_BRACE; break;
  case '\\': return KEY_BACKSLASH; break;
  case ']': return KEY_RIGHT_BRACE; break;
  case '^': return KEY_6; break;
  case '_': return KEY_MINUS; break;
  case '`': return KEY_TILDE; break;

  case '{': return KEY_LEFT_BRACE; break;
  case '|': return KEY_BACKSLASH; break;
  case '}': return KEY_RIGHT_BRACE; break;
  case '~': return KEY_TILDE; break;

  default: return 0;
  }
}

int modifier_from_char(char c){
  if ((c >= 'A' && c <= 'Z') ||
      // not sure how useful it is to put chars instead of ints for the rest of these
      c == '!' || c == '"' ||
      (c >= '$' && c <= '&') ||
      c == '(' || c == ')' ||
      c == ':' || c == '<' ||
      (c >= '>' && c <= '@') ||
      c == '^' || c == '_' ||
      (c >= '{' && c <= '~')) return KEY_SHIFT;

  return 0;
}

int8_t usb_keyboard_print(char *s){
  int s_len = strlen(s);
  int i;

  for(i = 0; i < s_len; i++){
    usb_keyboard_press(key_from_char(s[i]), modifier_from_char(s[i]));
  }
}

Это, кажется, работает, когда я делаю

int main(void) {
   ...
   usb_keyboard_print("abcdABCD1234!@#$%^&*()_+|~{}:\">?<-=\\`[];',./");
   ...
}

последовательность символов

abcdABCD1234!@\$%^&*()_+|~{}:">?<-=\`[];',./

выводится как бы клавиатурой.

Все комментарии приветствуются, но у меня тоже есть определенные точки/вопросы

  • Кажется, что там должен быть более простой способ сделать это. Я упомянул выше, что c++ версии usb_keyboard библиотека предоставляет клавиатуру.печать , которая делает по сути то же самое, но я не нашел ничего похожего на обычный C.
  • Есть ли какие-то вопросы я пропускаю о ключевых кодов USB, что бы сделать этот код зубрила вне зависимости от настроек национальности? Как бы вы идете по поводу интернационализацией?
  • Это, по сути, первый код на языке C, которые я написал после выхода из школы, поэтому, пожалуйста, указать на стилистические ошибки и недостатки с крайним предубеждением.


205
2
задан 13 декабря 2011 в 05:12 Источник Поделиться
Комментарии
2 ответа

Не вычитать абсолютные значения:

    if (c >= 'a' && c <= 'z') return c - 93;

Это делает его трудно понять, что вы делаете, когда вы вычесть целые числа из кодов символов. Я бы обычно ожидать некоторые формы стоимости, которая передает какой-то смысл. Например, предположим, что в кодировке ASCII (вы, вероятно, хотите, чтобы ваш клавиатурой, но я не знаю соответствующий макрос).

 if (c >= 'a' && c <= 'z') return c + 3 - 'a';  // For some reason you want 'a' to map to 3
// If we assume ASCII 'a' => 96

if (c >= 'A' && c <= 'Z') return c + 4 - 'A'; // For some reason you want 'A' to map to 4
// If we assume ASCII 'A' => 65

Или вы имеете другое требование, то есть не ASCII (очень возможно), вы хотите 'а'/'а' на карте до некоторой ненулевой цифры или у вас есть ошибка. Но трудно сказать, как вы написали свой код как литеральные значения 93 и 61 не имеют никакого реального смысла.

1
ответ дан 13 декабря 2011 в 08:12 Источник Поделиться

Вы могли бы взять немного другой подход, если вы хотели избавиться от выключателя ( как они получают немного неэффективно, с большим количеством условий)

можно сделать массив из 256 целых чисел, и использовать текущую функцию для заполнения массива, то, чтобы получить int в тип char.

int key_from_char(char c){
return my_char_mapping_array[(unsigned int)c];
}

1
ответ дан 13 декабря 2011 в 10:12 Источник Поделиться