| @@ -26,9 +26,10 @@ | |||
| #include <stdint.h> | |||
| #if !defined(__MK66FX1M0__) | |||
| #if !defined(__MK66FX1M0__) && !defined(__IMXRT1052__) && !defined(__IMXRT1062__) | |||
| #error "USBHost_t36 only works with Teensy 3.6. Please select it in Tools > Boards" | |||
| #endif | |||
| #include "utility/imxrt_usbhs.h" | |||
| // Dear inquisitive reader, USB is a complex protocol defined with | |||
| // very specific terminology. To have any chance of understand this | |||
| @@ -712,6 +713,13 @@ public: | |||
| 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 | |||
| uint16_t idVendor(); | |||
| uint16_t idProduct(); | |||
| @@ -739,6 +747,7 @@ public: | |||
| // Added for extras information. | |||
| 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 forceBootProtocol(); | |||
| enum {MAX_KEYS_DOWN=4}; | |||
| @@ -791,7 +800,8 @@ private: | |||
| volatile bool hid_input_data_ = false; // did we receive any valid data with report? | |||
| uint8_t count_keys_down_ = 0; | |||
| uint16_t keys_down[MAX_KEYS_DOWN]; | |||
| bool force_boot_protocol; // User or VID/PID said force boot protocol? | |||
| bool control_queued; | |||
| }; | |||
| @@ -1330,7 +1340,7 @@ private: | |||
| uint8_t pl2303_v1; // Which version do we have | |||
| uint8_t pl2303_v2; | |||
| 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; | |||
| sertype_t sertype; | |||
| @@ -106,6 +106,7 @@ static void remove_from_periodic_followup_list(Transfer_t *transfer); | |||
| void USBHost::begin() | |||
| { | |||
| #if defined(__MK66FX1M0__) | |||
| // Teensy 3.6 has USB host power controlled by PTE6 | |||
| PORTE_PCR6 = PORT_PCR_MUX(1); | |||
| GPIOE_PDDR |= (1<<6); | |||
| @@ -142,15 +143,14 @@ void USBHost::begin() | |||
| USBPHY_PLL_SIC = USBPHY_PLL_SIC_PLL_POWER | USBPHY_PLL_SIC_PLL_ENABLE | | |||
| USBPHY_PLL_SIC_PLL_DIV_SEL(1) | USBPHY_PLL_SIC_PLL_EN_USB_CLKS; | |||
| // wait for the PLL to lock | |||
| int count=0; | |||
| int pll_count=0; | |||
| while ((USBPHY_PLL_SIC & USBPHY_PLL_SIC_PLL_LOCK) == 0) { | |||
| count++; | |||
| pll_count++; | |||
| } | |||
| //println("PLL locked, waited ", count); | |||
| //println("PLL locked, waited ", pll_count); | |||
| // turn on power to PHY | |||
| USBPHY_PWD = 0; | |||
| delay(10); | |||
| // sanity check, connect 470K pullup & 100K pulldown and watch D+ voltage change | |||
| //USBPHY_ANACTRL_CLR = (1<<10); // turn off both 15K pulldowns... works! :) | |||
| @@ -163,14 +163,60 @@ void USBHost::begin() | |||
| //SIM_SOPT2 = SIM_SOPT2 & (~SIM_SOPT2_CLKOUTSEL(7)) | SIM_SOPT2_CLKOUTSEL(4); // MCGIRCLK | |||
| //CORE_PIN9_CONFIG = PORT_PCR_MUX(5); // CLKOUT on PTC3 Alt5 (Arduino pin 9) | |||
| #elif defined(__IMXRT1052__) || defined(__IMXRT1062__) | |||
| // Teensy 4.0 PLL & USB PHY powerup | |||
| while (1) { | |||
| uint32_t n = CCM_ANALOG_PLL_USB2; | |||
| if (n & CCM_ANALOG_PLL_USB2_DIV_SELECT) { | |||
| CCM_ANALOG_PLL_USB2_CLR = 0xC000; // get out of 528 MHz mode | |||
| CCM_ANALOG_PLL_USB2_SET = CCM_ANALOG_PLL_USB2_BYPASS; | |||
| CCM_ANALOG_PLL_USB2_CLR = CCM_ANALOG_PLL_USB2_POWER | | |||
| CCM_ANALOG_PLL_USB2_DIV_SELECT | | |||
| CCM_ANALOG_PLL_USB2_ENABLE | | |||
| CCM_ANALOG_PLL_USB2_EN_USB_CLKS; | |||
| continue; | |||
| } | |||
| if (!(n & CCM_ANALOG_PLL_USB2_ENABLE)) { | |||
| CCM_ANALOG_PLL_USB2_SET = CCM_ANALOG_PLL_USB2_ENABLE; // enable | |||
| continue; | |||
| } | |||
| if (!(n & CCM_ANALOG_PLL_USB2_POWER)) { | |||
| CCM_ANALOG_PLL_USB2_SET = CCM_ANALOG_PLL_USB2_POWER; // power up | |||
| continue; | |||
| } | |||
| if (!(n & CCM_ANALOG_PLL_USB2_LOCK)) { | |||
| continue; // wait for lock | |||
| } | |||
| if (n & CCM_ANALOG_PLL_USB2_BYPASS) { | |||
| CCM_ANALOG_PLL_USB2_CLR = CCM_ANALOG_PLL_USB2_BYPASS; // turn off bypass | |||
| continue; | |||
| } | |||
| if (!(n & CCM_ANALOG_PLL_USB2_EN_USB_CLKS)) { | |||
| CCM_ANALOG_PLL_USB2_SET = CCM_ANALOG_PLL_USB2_EN_USB_CLKS; // enable | |||
| continue; | |||
| } | |||
| println("USB2 PLL running"); | |||
| break; // USB2 PLL up and running | |||
| } | |||
| // turn on USB clocks (should already be on) | |||
| CCM_CCGR6 |= CCM_CCGR6_USBOH3(CCM_CCGR_ON); | |||
| // turn on USB2 PHY | |||
| USBPHY2_CTRL_CLR = USBPHY_CTRL_SFTRST | USBPHY_CTRL_CLKGATE; | |||
| USBPHY2_CTRL_SET = USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3; | |||
| USBPHY2_PWD = 0; | |||
| #endif | |||
| delay(10); | |||
| // now with the PHY up and running, start up USBHS | |||
| //print("begin ehci reset"); | |||
| USBHS_USBCMD |= USBHS_USBCMD_RST; | |||
| //count = 0; | |||
| int reset_count = 0; | |||
| while (USBHS_USBCMD & USBHS_USBCMD_RST) { | |||
| //count++; | |||
| reset_count++; | |||
| } | |||
| //println(" reset waited ", count); | |||
| println(" reset waited ", reset_count); | |||
| init_Device_Pipe_Transfer_memory(); | |||
| for (int i=0; i < PERIODIC_LIST_SIZE; i++) { | |||
| @@ -216,9 +262,9 @@ void USBHost::begin() | |||
| //USBHS_PORTSC1 |= USBHS_PORTSC_PFSC; // force 12 Mbit/sec | |||
| //USBHS_PORTSC1 |= USBHS_PORTSC_PHCD; // phy off | |||
| //println("USBHS_ASYNCLISTADDR = ", USBHS_ASYNCLISTADDR, HEX); | |||
| //println("USBHS_PERIODICLISTBASE = ", USBHS_PERIODICLISTBASE, HEX); | |||
| //println("periodictable = ", (uint32_t)periodictable, HEX); | |||
| println("USBHS_ASYNCLISTADDR = ", USBHS_ASYNCLISTADDR, HEX); | |||
| println("USBHS_PERIODICLISTBASE = ", USBHS_PERIODICLISTBASE, HEX); | |||
| println("periodictable = ", (uint32_t)periodictable, HEX); | |||
| // enable interrupts, after this point interruts to all the work | |||
| attachInterruptVector(IRQ_USBHS, isr); | |||
| @@ -31,13 +31,13 @@ bool driver_active[CNT_DEVICES] = {false, false, false, false}; | |||
| // Lets also look at HID Input devices | |||
| USBHIDInput *hiddrivers[] = {&mouse1, &joystick1, &rawhid1, &rawhid2}; | |||
| #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 show_changed_only = false; | |||
| bool show_changed_only = false; | |||
| uint8_t joystick_left_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() | |||
| { | |||
| @@ -52,6 +52,11 @@ void setup() | |||
| keyboard2.attachExtrasPress(OnHIDExtrasPress); | |||
| 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); | |||
| rawhid2.attachReceive(OnReceiveHidData); | |||
| } | |||
| @@ -62,8 +67,8 @@ void loop() | |||
| myusb.Task(); | |||
| 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')) { | |||
| Serial.println("Only notify on Basic Axis changes"); | |||
| joystick1.axisChangeNotifyMask(0x3ff); | |||
| @@ -80,7 +85,7 @@ void loop() | |||
| Serial.println("\n*** Show only changed fields mode ***"); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| for (uint8_t i = 0; i < CNT_DEVICES; i++) { | |||
| if (*drivers[i] != driver_active[i]) { | |||
| @@ -97,6 +102,19 @@ void loop() | |||
| if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||
| psz = drivers[i]->serialNumber(); | |||
| 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(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -122,7 +140,7 @@ void loop() | |||
| if(mouse1.available()) { | |||
| if (mouse1.available()) { | |||
| Serial.print("Mouse: buttons = "); | |||
| Serial.print(mouse1.getButtons()); | |||
| Serial.print(", mouseX = "); | |||
| @@ -170,7 +188,7 @@ void loop() | |||
| joystick_left_trigger_value = ltv; | |||
| joystick_right_trigger_value = rtv; | |||
| joystick1.setRumble(ltv, rtv); | |||
| } | |||
| } | |||
| break; | |||
| case JoystickController::PS3: | |||
| @@ -180,11 +198,11 @@ void loop() | |||
| joystick_left_trigger_value = ltv; | |||
| joystick_right_trigger_value = rtv; | |||
| joystick1.setRumble(ltv, rtv, 50); | |||
| } | |||
| } | |||
| break; | |||
| case JoystickController::XBOXONE: | |||
| case JoystickController::XBOX360: | |||
| case JoystickController::XBOXONE: | |||
| case JoystickController::XBOX360: | |||
| ltv = joystick1.getAxis(4); | |||
| rtv = joystick1.getAxis(5); | |||
| if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | |||
| @@ -192,16 +210,16 @@ void loop() | |||
| joystick_right_trigger_value = rtv; | |||
| joystick1.setRumble(ltv, rtv); | |||
| Serial.printf(" Set Rumble %d %d", ltv, rtv); | |||
| } | |||
| } | |||
| break; | |||
| } | |||
| if (buttons != buttons_prev) { | |||
| 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 { | |||
| 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); | |||
| } | |||
| buttons_prev = buttons; | |||
| @@ -215,7 +233,7 @@ void loop() | |||
| if (rawhid1) { | |||
| int ch; | |||
| uint8_t buffer[64]; | |||
| uint8_t count_chars = 0; | |||
| uint8_t count_chars = 0; | |||
| memset(buffer, 0, sizeof(buffer)); | |||
| if (Serial.available()) { | |||
| while (((ch = Serial.read()) != -1) && (count_chars < sizeof(buffer))) { | |||
| @@ -279,7 +297,7 @@ void OnPress(int key) | |||
| //Serial.print((char)keyboard2.getKey()); | |||
| //Serial.println(); | |||
| } | |||
| void OnHIDExtrasPress(uint32_t top, uint16_t key) | |||
| void OnHIDExtrasPress(uint32_t top, uint16_t key) | |||
| { | |||
| Serial.print("HID ("); | |||
| Serial.print(top, HEX); | |||
| @@ -515,7 +533,7 @@ void OnHIDExtrasPress(uint32_t top, uint16_t key) | |||
| Serial.println(); | |||
| } | |||
| void OnHIDExtrasRelease(uint32_t top, uint16_t key) | |||
| void OnHIDExtrasRelease(uint32_t top, uint16_t key) | |||
| { | |||
| Serial.print("HID ("); | |||
| Serial.print(top, HEX); | |||
| @@ -525,10 +543,10 @@ void OnHIDExtrasRelease(uint32_t top, uint16_t key) | |||
| 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 | |||
| // to output to Serial. while still having Raw Hid... | |||
| // to output to Serial. while still having Raw Hid... | |||
| if (usage == 0xffc90004) { | |||
| // Lets trim off trailing null characters. | |||
| while ((len > 0) && (data[len-1] == 0)) { | |||
| while ((len > 0) && (data[len - 1] == 0)) { | |||
| len--; | |||
| } | |||
| if (len) { | |||
| @@ -539,7 +557,7 @@ bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||
| Serial.print("RawHID data: "); | |||
| Serial.println(usage, HEX); | |||
| while (len) { | |||
| uint8_t cb = (len > 16)? 16 : len; | |||
| uint8_t cb = (len > 16) ? 16 : len; | |||
| const uint8_t *p = data; | |||
| uint8_t i; | |||
| for (i = 0; i < cb; i++) { | |||
| @@ -547,7 +565,7 @@ bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||
| } | |||
| Serial.print(": "); | |||
| for (i = 0; i < cb; i++) { | |||
| Serial.write(((*data >= ' ')&&(*data <= '~'))? *data : '.'); | |||
| Serial.write(((*data >= ' ') && (*data <= '~')) ? *data : '.'); | |||
| data++; | |||
| } | |||
| len -= cb; | |||
| @@ -556,4 +574,4 @@ bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @@ -36,12 +36,17 @@ typedef struct { | |||
| uint8_t charNumlockOn; // We will assume when num lock is on we have all characters... | |||
| } 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 | |||
| #undef M | |||
| #endif | |||
| #define M(n) ((n) & KEYCODE_MASK) | |||
| keycode_extra_t keycode_extras[] = { | |||
| static const keycode_extra_t keycode_extras[] = { | |||
| {M(KEY_ENTER), '\n'}, | |||
| {M(KEY_ESC), 0x1b}, | |||
| {M(KEY_TAB), 0x9 }, | |||
| @@ -70,7 +75,7 @@ keycode_extra_t keycode_extras[] = { | |||
| }; | |||
| // Some of these mapped to key + shift. | |||
| keycode_numlock_t keycode_numlock[] = { | |||
| static const keycode_numlock_t keycode_numlock[] = { | |||
| {M(KEYPAD_SLASH), '/', '/'}, | |||
| {M(KEYPAD_ASTERIX), '*', '*'}, | |||
| {M(KEYPAD_MINUS), '-', '-'}, | |||
| @@ -89,6 +94,11 @@ keycode_numlock_t keycode_numlock[] = { | |||
| {M(KEYPAD_PERIOD), 0x80 | M(KEY_DELETE), '.'} | |||
| }; | |||
| static const keyboard_force_boot_protocol_t keyboard_forceBootMode[] = { | |||
| {0x04D9, 0} | |||
| }; | |||
| #define print USBHost::print_ | |||
| #define println USBHost::println_ | |||
| @@ -138,6 +148,7 @@ void KeyboardController::init() | |||
| driver_ready_for_device(this); | |||
| USBHIDParser::driver_ready_for_hid_collection(this); | |||
| BluetoothController::driver_ready_for_bluetooth(this); | |||
| force_boot_protocol = false; // start off assuming not | |||
| } | |||
| bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len) | |||
| @@ -147,6 +158,7 @@ bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descripto | |||
| // only claim at interface level | |||
| if (type != 1) return false; | |||
| if (len < 9+9+7) return false; | |||
| print_hexbytes(descriptors, len); | |||
| uint32_t numendpoint = descriptors[4]; | |||
| if (numendpoint < 1) return false; | |||
| @@ -178,22 +190,45 @@ bool KeyboardController::claim(Device_t *dev, int type, const uint8_t *descripto | |||
| datapipe->callback_function = callback; | |||
| 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); | |||
| control_queued = true; | |||
| return true; | |||
| } | |||
| void KeyboardController::control(const Transfer_t *transfer) | |||
| { | |||
| println("control callback (keyboard)"); | |||
| control_queued = false; | |||
| print_hexbytes(transfer->buffer, transfer->length); | |||
| // To decode hex dump to human readable HID report summary: | |||
| // http://eleccelerator.com/usbdescreqparser/ | |||
| uint32_t mesg = transfer->setup.word1; | |||
| 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 | |||
| control_queued = true; | |||
| 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 | |||
| } | |||
| } | |||
| @@ -205,6 +240,17 @@ void KeyboardController::callback(const Transfer_t *transfer) | |||
| } | |||
| } | |||
| 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() | |||
| { | |||
| // TODO: free resources | |||
| @@ -527,5 +573,42 @@ void KeyboardController::release_bluetooth() | |||
| { | |||
| //btdevice = nullptr; | |||
| //***************************************************************************** | |||
| // 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; | |||
| } | |||
| @@ -31,6 +31,7 @@ updateLEDS KEYWORD2 | |||
| numLock KEYWORD2 | |||
| capsLock KEYWORD2 | |||
| scrollLock KEYWORD2 | |||
| forceBootProtocol KEYWORD2 | |||
| # MIDIDevice | |||
| getType KEYWORD2 | |||
| @@ -0,0 +1,81 @@ | |||
| #ifndef IMXRT_USBHS_H_ | |||
| #define IMXRT_USBHS_H_ | |||
| #if defined(__IMXRT1052__) || defined(__IMXRT1062__) | |||
| // Allow USB host code written for "USBHS" on Teensy 3.6 to compile for "USB2" on Teensy 4.0 | |||
| #define IRQ_USBHS IRQ_USB2 | |||
| #define USBPHY_CTRL USBPHY2_CTRL | |||
| #define USBPHY_CTRL_CLR USBPHY2_CTRL_CLR | |||
| #define USBPHY_CTRL_SET USBPHY2_CTRL_SET | |||
| #define USBHS_USBCMD USB2_USBCMD | |||
| #define USBHS_USBSTS USB2_USBSTS | |||
| #define USBHS_USBINTR USB2_USBINTR | |||
| #define USBHS_FRINDEX USB2_FRINDEX | |||
| #define USBHS_PERIODICLISTBASE USB2_PERIODICLISTBASE | |||
| #define USBHS_ASYNCLISTADDR USB2_ASYNCLISTADDR | |||
| #define USBHS_PORTSC1 USB2_PORTSC1 | |||
| #define USBHS_USBMODE USB2_USBMODE | |||
| #define USBHS_GPTIMER0CTL USB2_GPTIMER0CTRL | |||
| #define USBHS_GPTIMER0LD USB2_GPTIMER0LD | |||
| #define USBHS_GPTIMER1CTL USB2_GPTIMER1CTRL | |||
| #define USBHS_GPTIMER1LD USB2_GPTIMER1LD | |||
| #define USBHS_USBCMD_ASE USB_USBCMD_ASE | |||
| #define USBHS_USBCMD_IAA USB_USBCMD_IAA | |||
| #define USBHS_USBCMD_RST USB_USBCMD_RST | |||
| #define USBHS_USBCMD_ITC(n) USB_USBCMD_ITC(n) | |||
| #define USBHS_USBCMD_RS USB_USBCMD_RS | |||
| #define USBHS_USBCMD_ASP(n) USB_USBCMD_ASP(n) | |||
| #define USBHS_USBCMD_ASPE USB_USBCMD_ASPE | |||
| #define USBHS_USBCMD_PSE USB_USBCMD_PSE | |||
| #define USBHS_USBCMD_FS2 USB_USBCMD_FS_2 | |||
| #define USBHS_USBCMD_FS(n) USB_USBCMD_FS_1(n) | |||
| #define USBHS_USBSTS_AAI USB_USBSTS_AAI | |||
| #define USBHS_USBSTS_AS USB_USBSTS_AS | |||
| // UAI & UPI bits are undocumented in IMXRT, K66 pg 1602, RT1050 pg 2374 | |||
| #define USBHS_USBSTS_UAI ((uint32_t)(1<<18)) | |||
| #define USBHS_USBSTS_UPI ((uint32_t)(1<<19)) | |||
| #define USBHS_USBSTS_UEI USB_USBSTS_UEI | |||
| #define USBHS_USBSTS_PCI USB_USBSTS_PCI | |||
| #define USBHS_USBSTS_TI0 USB_USBSTS_TI0 | |||
| #define USBHS_USBSTS_TI1 USB_USBSTS_TI1 | |||
| #define USBHS_USBSTS_SEI USB_USBSTS_SEI | |||
| #define USBHS_USBSTS_URI USB_USBSTS_URI | |||
| #define USBHS_USBSTS_SLI USB_USBSTS_SLI | |||
| #define USBHS_USBSTS_HCH USB_USBSTS_HCH | |||
| #define USBHS_USBSTS_NAKI USB_USBSTS_NAKI | |||
| #define USBHS_USBINTR_PCE USB_USBINTR_PCE | |||
| #define USBHS_USBINTR_TIE0 USB_USBINTR_TIE0 | |||
| #define USBHS_USBINTR_TIE1 USB_USBINTR_TIE1 | |||
| #define USBHS_USBINTR_UEE USB_USBINTR_UEE | |||
| #define USBHS_USBINTR_SEE USB_USBINTR_SEE | |||
| #define USBHS_USBINTR_UPIE USB_USBINTR_UPIE | |||
| #define USBHS_USBINTR_UAIE USB_USBINTR_UAIE | |||
| #define USBHS_PORTSC_PP USB_PORTSC1_PP | |||
| #define USBHS_PORTSC_OCC USB_PORTSC1_OCC | |||
| #define USBHS_PORTSC_PEC USB_PORTSC1_PEC | |||
| #define USBHS_PORTSC_CSC USB_PORTSC1_CSC | |||
| #define USBHS_PORTSC_CCS USB_PORTSC1_CCS | |||
| #define USBHS_PORTSC_PE USB_PORTSC1_PE | |||
| #define USBHS_PORTSC_HSP USB_PORTSC1_HSP | |||
| #define USBHS_PORTSC_FPR USB_PORTSC1_FPR | |||
| #define USBHS_PORTSC_PR USB_PORTSC1_PR | |||
| #define USBHS_GPTIMERCTL_RST USB_GPTIMERCTRL_GPTRST | |||
| #define USBHS_GPTIMERCTL_RUN USB_GPTIMERCTRL_GPTRUN | |||
| #define USBHS_USBMODE_CM(n) USB_USBMODE_CM(n) | |||
| // TODO: what is the best setting for this register on IMXRT ??? | |||
| #define USBHS_USB_SBUSCFG USB2_SBUSCFG | |||
| #endif // __IMXRT1052__ or __IMXRT1062__ | |||
| #endif // IMXRT_USBHS_H_ | |||