Bladeren bron

Merge pull request #23 from KurtE/Gigabyte-Logitech-fix

Now only optionally force keyboard into boot protocol mode
main
Paul Stoffregen 6 jaren geleden
bovenliggende
commit
1dabff1534
No account linked to committer's email address
4 gewijzigde bestanden met toevoegingen van 146 en 32 verwijderingen
  1. +11
    -2
      USBHost_t36.h
  2. +44
    -26
      examples/Mouse/Mouse.ino
  3. +90
    -4
      keyboard.cpp
  4. +1
    -0
      keywords.txt

+ 11
- 2
USBHost_t36.h Bestand weergeven

KeyboardController(USBHost &host) { init(); } KeyboardController(USBHost &host) { init(); }
KeyboardController(USBHost *host) { init(); } KeyboardController(USBHost *host) { init(); }


// need their own versions as both USBDriver and USBHIDInput provide
uint16_t idVendor();
uint16_t idProduct();
const uint8_t *manufacturer();
const uint8_t *product();
const uint8_t *serialNumber();

// Some methods are in both public classes so we need to figure out which one to use // Some methods are in both public classes so we need to figure out which one to use
operator bool() { return (device != nullptr); } operator bool() { return (device != nullptr); }
// Main boot keyboard functions. // Main boot keyboard functions.
// Added for extras information. // Added for extras information.
void attachExtrasPress(void (*f)(uint32_t top, uint16_t code)) { extrasKeyPressedFunction = f; } void attachExtrasPress(void (*f)(uint32_t top, uint16_t code)) { extrasKeyPressedFunction = f; }
void attachExtrasRelease(void (*f)(uint32_t top, uint16_t code)) { extrasKeyReleasedFunction = f; } void attachExtrasRelease(void (*f)(uint32_t top, uint16_t code)) { extrasKeyReleasedFunction = f; }
void forceBootProtocol();
enum {MAX_KEYS_DOWN=4}; enum {MAX_KEYS_DOWN=4};




volatile bool hid_input_data_ = false; // did we receive any valid data with report? volatile bool hid_input_data_ = false; // did we receive any valid data with report?
uint8_t count_keys_down_ = 0; uint8_t count_keys_down_ = 0;
uint16_t keys_down[MAX_KEYS_DOWN]; uint16_t keys_down[MAX_KEYS_DOWN];

bool force_boot_protocol; // User or VID/PID said force boot protocol?
bool control_queued;
}; };




uint8_t pl2303_v1; // Which version do we have uint8_t pl2303_v1; // Which version do we have
uint8_t pl2303_v2; uint8_t pl2303_v2;
uint8_t interface; uint8_t interface;
bool control_queued;
bool control_queued; // Is there already a queued control messaged
typedef enum { UNKNOWN=0, CDCACM, FTDI, PL2303, CH341, CP210X } sertype_t; typedef enum { UNKNOWN=0, CDCACM, FTDI, PL2303, CH341, CP210X } sertype_t;
sertype_t sertype; sertype_t sertype;



+ 44
- 26
examples/Mouse/Mouse.ino Bestand weergeven

RawHIDController rawhid1(myusb); RawHIDController rawhid1(myusb);
RawHIDController rawhid2(myusb, 0xffc90004); RawHIDController rawhid2(myusb, 0xffc90004);


USBDriver *drivers[] = {&hub1, &hub2,&keyboard1, &keyboard2, &joystick1, &hid1, &hid2, &hid3, &hid4, &hid5};
USBDriver *drivers[] = {&hub1, &hub2, &keyboard1, &keyboard2, &joystick1, &hid1, &hid2, &hid3, &hid4, &hid5};
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) #define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "KB2", "JOY1D", "HID1", "HID2", "HID3", "HID4", "HID5"};
const char * driver_names[CNT_DEVICES] = {"Hub1", "Hub2", "KB1", "KB2", "JOY1D", "HID1", "HID2", "HID3", "HID4", "HID5"};
bool driver_active[CNT_DEVICES] = {false, false, false, false}; bool driver_active[CNT_DEVICES] = {false, false, false, false};


// Lets also look at HID Input devices // Lets also look at HID Input devices
USBHIDInput *hiddrivers[] = {&mouse1, &joystick1, &rawhid1, &rawhid2}; USBHIDInput *hiddrivers[] = {&mouse1, &joystick1, &rawhid1, &rawhid2};
#define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) #define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0]))
const char * hid_driver_names[CNT_DEVICES] = {"Mouse1","Joystick1", "RawHid1", "RawHid2"};
const char * hid_driver_names[CNT_DEVICES] = {"Mouse1", "Joystick1", "RawHid1", "RawHid2"};
bool hid_driver_active[CNT_DEVICES] = {false, false}; bool hid_driver_active[CNT_DEVICES] = {false, false};
bool show_changed_only = false;
bool show_changed_only = false;


uint8_t joystick_left_trigger_value = 0; uint8_t joystick_left_trigger_value = 0;
uint8_t joystick_right_trigger_value = 0; uint8_t joystick_right_trigger_value = 0;
uint64_t joystick_full_notify_mask = (uint64_t)-1;
uint64_t joystick_full_notify_mask = (uint64_t) - 1;


void setup() void setup()
{ {
keyboard2.attachExtrasPress(OnHIDExtrasPress); keyboard2.attachExtrasPress(OnHIDExtrasPress);
keyboard2.attachExtrasRelease(OnHIDExtrasRelease); keyboard2.attachExtrasRelease(OnHIDExtrasRelease);


// The below forceBootProtocol will force which ever
// next keyboard that attaches to this device to be in boot protocol
// Only try this if you run into keyboard with issues. If this is a combined
// device like wireless mouse and keyboard this can cause mouse problems.
//keyboard1.forceBootProtocol();
rawhid1.attachReceive(OnReceiveHidData); rawhid1.attachReceive(OnReceiveHidData);
rawhid2.attachReceive(OnReceiveHidData); rawhid2.attachReceive(OnReceiveHidData);
} }
myusb.Task(); myusb.Task();


if (Serial.available()) { if (Serial.available()) {
int ch = Serial.read(); // get the first char.
while (Serial.read() != -1) ;
int ch = Serial.read(); // get the first char.
while (Serial.read() != -1) ;
if ((ch == 'b') || (ch == 'B')) { if ((ch == 'b') || (ch == 'B')) {
Serial.println("Only notify on Basic Axis changes"); Serial.println("Only notify on Basic Axis changes");
joystick1.axisChangeNotifyMask(0x3ff); joystick1.axisChangeNotifyMask(0x3ff);
Serial.println("\n*** Show only changed fields mode ***"); Serial.println("\n*** Show only changed fields mode ***");
} }
} }
}
}


for (uint8_t i = 0; i < CNT_DEVICES; i++) { for (uint8_t i = 0; i < CNT_DEVICES; i++) {
if (*drivers[i] != driver_active[i]) { if (*drivers[i] != driver_active[i]) {
if (psz && *psz) Serial.printf(" product: %s\n", psz); if (psz && *psz) Serial.printf(" product: %s\n", psz);
psz = drivers[i]->serialNumber(); psz = drivers[i]->serialNumber();
if (psz && *psz) Serial.printf(" Serial: %s\n", psz); if (psz && *psz) Serial.printf(" Serial: %s\n", psz);

// Note: with some keyboards there is an issue that they don't output in boot protocol mode
// and may not work. The above code can try to force the keyboard into boot mode, but there
// are issues with doing this blindly with combo devices like wireless keyboard/mouse, which
// may cause the mouse to not work. Note: the above id is in the builtin list of
// vendor IDs that are already forced
if (drivers[i] == &keyboard1) {
if (keyboard1.idVendor() == 0x04D9) {
Serial.println("Gigabyte vendor: force boot protocol");
// Gigabyte keyboard
keyboard1.forceBootProtocol();
}
}
} }
} }
} }






if(mouse1.available()) {
if (mouse1.available()) {
Serial.print("Mouse: buttons = "); Serial.print("Mouse: buttons = ");
Serial.print(mouse1.getButtons()); Serial.print(mouse1.getButtons());
Serial.print(", mouseX = "); Serial.print(", mouseX = ");
joystick_left_trigger_value = ltv; joystick_left_trigger_value = ltv;
joystick_right_trigger_value = rtv; joystick_right_trigger_value = rtv;
joystick1.setRumble(ltv, rtv); joystick1.setRumble(ltv, rtv);
}
}
break; break;


case JoystickController::PS3: case JoystickController::PS3:
joystick_left_trigger_value = ltv; joystick_left_trigger_value = ltv;
joystick_right_trigger_value = rtv; joystick_right_trigger_value = rtv;
joystick1.setRumble(ltv, rtv, 50); joystick1.setRumble(ltv, rtv, 50);
}
}
break; break;


case JoystickController::XBOXONE:
case JoystickController::XBOX360:
case JoystickController::XBOXONE:
case JoystickController::XBOX360:
ltv = joystick1.getAxis(4); ltv = joystick1.getAxis(4);
rtv = joystick1.getAxis(5); rtv = joystick1.getAxis(5);
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
joystick_right_trigger_value = rtv; joystick_right_trigger_value = rtv;
joystick1.setRumble(ltv, rtv); joystick1.setRumble(ltv, rtv);
Serial.printf(" Set Rumble %d %d", ltv, rtv); Serial.printf(" Set Rumble %d %d", ltv, rtv);
}
}
break; break;
} }
if (buttons != buttons_prev) { if (buttons != buttons_prev) {
if (joystick1.joystickType == JoystickController::PS3) { if (joystick1.joystickType == JoystickController::PS3) {
joystick1.setLEDs((buttons>>12) & 0xf); // try to get to TRI/CIR/X/SQuare
joystick1.setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare
} else { } else {
uint8_t lr = (buttons & 1)? 0xff : 0;
uint8_t lg = (buttons & 2)? 0xff : 0;
uint8_t lb = (buttons & 4)? 0xff : 0;
uint8_t lr = (buttons & 1) ? 0xff : 0;
uint8_t lg = (buttons & 2) ? 0xff : 0;
uint8_t lb = (buttons & 4) ? 0xff : 0;
joystick1.setLEDs(lr, lg, lb); joystick1.setLEDs(lr, lg, lb);
} }
buttons_prev = buttons; buttons_prev = buttons;
if (rawhid1) { if (rawhid1) {
int ch; int ch;
uint8_t buffer[64]; uint8_t buffer[64];
uint8_t count_chars = 0;
uint8_t count_chars = 0;
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
if (Serial.available()) { if (Serial.available()) {
while (((ch = Serial.read()) != -1) && (count_chars < sizeof(buffer))) { while (((ch = Serial.read()) != -1) && (count_chars < sizeof(buffer))) {
//Serial.print((char)keyboard2.getKey()); //Serial.print((char)keyboard2.getKey());
//Serial.println(); //Serial.println();
} }
void OnHIDExtrasPress(uint32_t top, uint16_t key)
void OnHIDExtrasPress(uint32_t top, uint16_t key)
{ {
Serial.print("HID ("); Serial.print("HID (");
Serial.print(top, HEX); Serial.print(top, HEX);
Serial.println(); Serial.println();
} }


void OnHIDExtrasRelease(uint32_t top, uint16_t key)
void OnHIDExtrasRelease(uint32_t top, uint16_t key)
{ {
Serial.print("HID ("); Serial.print("HID (");
Serial.print(top, HEX); Serial.print(top, HEX);


bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) {
// Called for maybe both HIDS for rawhid basic test. One is for the Teensy // Called for maybe both HIDS for rawhid basic test. One is for the Teensy
// to output to Serial. while still having Raw Hid...
// to output to Serial. while still having Raw Hid...
if (usage == 0xffc90004) { if (usage == 0xffc90004) {
// Lets trim off trailing null characters. // Lets trim off trailing null characters.
while ((len > 0) && (data[len-1] == 0)) {
while ((len > 0) && (data[len - 1] == 0)) {
len--; len--;
} }
if (len) { if (len) {
Serial.print("RawHID data: "); Serial.print("RawHID data: ");
Serial.println(usage, HEX); Serial.println(usage, HEX);
while (len) { while (len) {
uint8_t cb = (len > 16)? 16 : len;
uint8_t cb = (len > 16) ? 16 : len;
const uint8_t *p = data; const uint8_t *p = data;
uint8_t i; uint8_t i;
for (i = 0; i < cb; i++) { for (i = 0; i < cb; i++) {
} }
Serial.print(": "); Serial.print(": ");
for (i = 0; i < cb; i++) { for (i = 0; i < cb; i++) {
Serial.write(((*data >= ' ')&&(*data <= '~'))? *data : '.');
Serial.write(((*data >= ' ') && (*data <= '~')) ? *data : '.');
data++; data++;
} }
len -= cb; len -= cb;
} }


return true; return true;
}
}

+ 90
- 4
keyboard.cpp Bestand weergeven

uint8_t charNumlockOn; // We will assume when num lock is on we have all characters... uint8_t charNumlockOn; // We will assume when num lock is on we have all characters...
} keycode_numlock_t; } keycode_numlock_t;


typedef struct {
uint16_t idVendor; // vendor id of keyboard
uint16_t idProduct; // product id - 0 implies all of the ones from vendor;
} keyboard_force_boot_protocol_t; // list of products to force into boot protocol

#ifdef M #ifdef M
#undef M #undef M
#endif #endif
#define M(n) ((n) & KEYCODE_MASK) #define M(n) ((n) & KEYCODE_MASK)


keycode_extra_t keycode_extras[] = {
static const keycode_extra_t keycode_extras[] = {
{M(KEY_ENTER), '\n'}, {M(KEY_ENTER), '\n'},
{M(KEY_ESC), 0x1b}, {M(KEY_ESC), 0x1b},
{M(KEY_TAB), 0x9 }, {M(KEY_TAB), 0x9 },
}; };


// Some of these mapped to key + shift. // Some of these mapped to key + shift.
keycode_numlock_t keycode_numlock[] = {
static const keycode_numlock_t keycode_numlock[] = {
{M(KEYPAD_SLASH), '/', '/'}, {M(KEYPAD_SLASH), '/', '/'},
{M(KEYPAD_ASTERIX), '*', '*'}, {M(KEYPAD_ASTERIX), '*', '*'},
{M(KEYPAD_MINUS), '-', '-'}, {M(KEYPAD_MINUS), '-', '-'},
{M(KEYPAD_PERIOD), 0x80 | M(KEY_DELETE), '.'} {M(KEYPAD_PERIOD), 0x80 | M(KEY_DELETE), '.'}
}; };


static const keyboard_force_boot_protocol_t keyboard_forceBootMode[] = {
{0x04D9, 0}
};


#define print USBHost::print_ #define print USBHost::print_
#define println USBHost::println_ #define println USBHost::println_


contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t));
driver_ready_for_device(this); driver_ready_for_device(this);
USBHIDParser::driver_ready_for_hid_collection(this); USBHIDParser::driver_ready_for_hid_collection(this);
force_boot_protocol = false; // start off assuming not
} }


bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len) bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
// only claim at interface level // only claim at interface level
if (type != 1) return false; if (type != 1) return false;
if (len < 9+9+7) return false; if (len < 9+9+7) return false;
print_hexbytes(descriptors, len);


uint32_t numendpoint = descriptors[4]; uint32_t numendpoint = descriptors[4];
if (numendpoint < 1) return false; if (numendpoint < 1) return false;
datapipe->callback_function = callback; datapipe->callback_function = callback;
queue_Data_Transfer(datapipe, report, 8, this); queue_Data_Transfer(datapipe, report, 8, this);


mk_setup(setup, 0x21, 11, 0, 0, 0); // 11=SET_PROTOCOL BOOT
// see if this device in list of devices that need to be set in
// boot protocol mode
bool in_forceBoot_mode_list = false;
for (uint8_t i = 0; i < sizeof(keyboard_forceBootMode)/sizeof(keyboard_forceBootMode[0]); i++) {
if (dev->idVendor == keyboard_forceBootMode[i].idVendor) {
if ((dev->idProduct == keyboard_forceBootMode[i].idProduct) ||
(keyboard_forceBootMode[i].idProduct == 0)) {
in_forceBoot_mode_list = true;
break;
}
}
}
if (in_forceBoot_mode_list) {
println("SET_PROTOCOL Boot");
mk_setup(setup, 0x21, 11, 0, 0, 0); // 11=SET_PROTOCOL BOOT
} else {
mk_setup(setup, 0x21, 10, 0, 0, 0); // 10=SET_IDLE
}
queue_Control_Transfer(dev, &setup, NULL, this); queue_Control_Transfer(dev, &setup, NULL, this);
control_queued = true;
return true; return true;
} }


void KeyboardController::control(const Transfer_t *transfer) void KeyboardController::control(const Transfer_t *transfer)
{ {
println("control callback (keyboard)"); println("control callback (keyboard)");
control_queued = false;
print_hexbytes(transfer->buffer, transfer->length); print_hexbytes(transfer->buffer, transfer->length);
// To decode hex dump to human readable HID report summary: // To decode hex dump to human readable HID report summary:
// http://eleccelerator.com/usbdescreqparser/ // http://eleccelerator.com/usbdescreqparser/
uint32_t mesg = transfer->setup.word1; uint32_t mesg = transfer->setup.word1;
println(" mesg = ", mesg, HEX); println(" mesg = ", mesg, HEX);
if (mesg == 0x001021 && transfer->length == 0) { // SET_PROTOCOL
if (mesg == 0x00B21 && transfer->length == 0) { // SET_PROTOCOL
mk_setup(setup, 0x21, 10, 0, 0, 0); // 10=SET_IDLE mk_setup(setup, 0x21, 10, 0, 0, 0); // 10=SET_IDLE
control_queued = true;
queue_Control_Transfer(device, &setup, NULL, this); queue_Control_Transfer(device, &setup, NULL, this);
} else if (force_boot_protocol) {
forceBootProtocol(); // lets setup to do the boot protocol
force_boot_protocol = false; // turn back off
} }
} }


} }
} }


void KeyboardController::forceBootProtocol()
{
if (device && !control_queued) {
mk_setup(setup, 0x21, 11, 0, 0, 0); // 11=SET_PROTOCOL BOOT
control_queued = true;
queue_Control_Transfer(device, &setup, NULL, this);
} else {
force_boot_protocol = true; // let system know we want to force this.
}
}

void KeyboardController::disconnect() void KeyboardController::disconnect()
{ {
// TODO: free resources // TODO: free resources
hid_input_begin_ = false; hid_input_begin_ = false;
} }
} }

//*****************************************************************************
// Some simple query functions depend on which interface we are using...
//*****************************************************************************

uint16_t KeyboardController::idVendor()
{
if (device != nullptr) return device->idVendor;
if (mydevice != nullptr) return mydevice->idVendor;
return 0;
}

uint16_t KeyboardController::idProduct()
{
if (device != nullptr) return device->idProduct;
if (mydevice != nullptr) return mydevice->idProduct;
return 0;
}

const uint8_t *KeyboardController::manufacturer()
{
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]];
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]];
return nullptr;
}

const uint8_t *KeyboardController::product()
{
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]];
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]];
return nullptr;
}

const uint8_t *KeyboardController::serialNumber()
{
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]];
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]];
return nullptr;
}


+ 1
- 0
keywords.txt Bestand weergeven

numLock KEYWORD2 numLock KEYWORD2
capsLock KEYWORD2 capsLock KEYWORD2
scrollLock KEYWORD2 scrollLock KEYWORD2
forceBootProtocol KEYWORD2


# MIDIDevice # MIDIDevice
getType KEYWORD2 getType KEYWORD2

Laden…
Annuleren
Opslaan