bool WEAK CDC_Setup(Setup& setup) { u8 r = setup.bRequest; u8 requestType = setup.bmRequestType; if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) { if (CDC_GET_LINE_CODING == r) { USB_SendControl(0,(void*)&_usbLineInfo,7); return true; } } if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (CDC_SET_LINE_CODING == r) { USB_RecvControl((void*)&_usbLineInfo,7); return true; } if (CDC_SET_CONTROL_LINE_STATE == r) { _usbLineInfo.lineState = setup.wValueL; if(1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) { // auto-reset is triggered when the port, already open at 1200 bps, is closed Reboot(); } return true; } } return false; }
bool CDC_Setup(USBSetup& setup) { u8 r = setup.bRequest; u8 requestType = setup.bmRequestType; if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) { if (CDC_GET_LINE_CODING == r) { USB_SendControl(0,(void*)&_usbLineInfo,7); return true; } } if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (CDC_SET_LINE_CODING == r) { USB_RecvControl((void*)&_usbLineInfo,7); } if (CDC_SET_CONTROL_LINE_STATE == r) { _usbLineInfo.lineState = setup.wValueL; } if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r) { // auto-reset into the bootloader is triggered when the port, already // open at 1200 bps, is closed. this is the signal to start the watchdog // with a relatively long period so it can finish housekeeping tasks // like servicing endpoints before the sketch ends // We check DTR state to determine if host port is open (bit 0 of lineState). if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) { *(uint16_t *)(RAMEND-1) = *(uint16_t *)0x0800; *(uint16_t *)0x0800 = 0x7777; wdt_enable(WDTO_120MS); } else { // Most OSs do some intermediate steps when configuring ports and DTR can // twiggle more than once before stabilizing. // To avoid spurious resets we set the watchdog to 250ms and eventually // cancel if DTR goes back high. wdt_disable(); wdt_reset(); *(uint16_t *)0x0800 = *(uint16_t *)(RAMEND-1); } } return true; } return false; }
bool WEAK HID_Setup(Setup& setup) { u8 r = setup.bRequest; u8 requestType = setup.bmRequestType; if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) { if (HID_GET_REPORT == r) { //HID_GetReport(); return true; } if (HID_GET_PROTOCOL == r) { //Send8(_hid_protocol); // TODO return true; } } if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (HID_SET_PROTOCOL == r) { _hid_protocol = setup.wValueL; return true; } if (HID_SET_IDLE == r) { _hid_idle = setup.wValueL; return true; } #if defined(HID_KEYBOARD_LEDS_ENABLED) if (HID_SET_REPORT == r) { //TODO check correct report ID (not needed for now, no other device has an out report) // maybe make this a general weak implementation to use it for RAW HID later? if (setup.wLength == 2) { // write led out report data uint8_t data[2]; if (2 == USB_RecvControl(data, 2)) hid_keyboard_leds = data[1]; } // else TODO check for other devices like RAW HID, not needed for now } #endif } return false; }
bool WEAK HID_Setup(Setup& setup) { u8 r = setup.bRequest; u8 requestType = setup.bmRequestType; if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) { if (HID_GET_REPORT == r) { //HID_GetReport(); return true; } if (HID_GET_PROTOCOL == r) { //Send8(_hid_protocol); // TODO return true; } } if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (HID_SET_PROTOCOL == r) { _hid_protocol = setup.wValueL; return true; } if (HID_SET_IDLE == r) { _hid_idle = setup.wValueL; return true; } if (HID_SET_REPORT == r) { if (setup.wLength == 2) { uint8_t data[2]; if (2 == USB_RecvControl(data, 2)) { Keyboard.setLedStatus(data[1]); return true; } } } } return false; }
bool CDC_Setup(USBSetup& setup) { u8 r = setup.bRequest; u8 requestType = setup.bmRequestType; if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) { if (CDC_GET_LINE_CODING == r) { USB_SendControl(0,(void*)&_usbLineInfo,7); return true; } } if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (CDC_SEND_BREAK == r) { breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; } if (CDC_SET_LINE_CODING == r) { USB_RecvControl((void*)&_usbLineInfo,7); } if (CDC_SET_CONTROL_LINE_STATE == r) { _usbLineInfo.lineState = setup.wValueL; } if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r) { // auto-reset into the bootloader is triggered when the port, already // open at 1200 bps, is closed. this is the signal to start the watchdog // with a relatively long period so it can finish housekeeping tasks // like servicing endpoints before the sketch ends #ifndef MAGIC_KEY #define MAGIC_KEY 0x7777 #endif #ifndef MAGIC_KEY_POS #define MAGIC_KEY_POS 0x0800 #endif // We check DTR state to determine if host port is open (bit 0 of lineState). if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) { #if MAGIC_KEY_POS != (RAMEND-1) *(uint16_t *)(RAMEND-1) = *(uint16_t *)MAGIC_KEY_POS; *(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY; #else // for future boards save the key in the inproblematic RAMEND // which is reserved for the main() return value (which will never return) *(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY; #endif wdt_enable(WDTO_120MS); } else { // Most OSs do some intermediate steps when configuring ports and DTR can // twiggle more than once before stabilizing. // To avoid spurious resets we set the watchdog to 250ms and eventually // cancel if DTR goes back high. wdt_disable(); wdt_reset(); #if MAGIC_KEY_POS != (RAMEND-1) *(uint16_t *)MAGIC_KEY_POS = *(uint16_t *)(RAMEND-1); #else *(uint16_t *)MAGIC_KEY_POS = 0x0000; #endif } } return true; } return false; }
bool CDC_Setup(USBSetup& setup) { u8 r = setup.bRequest; u8 requestType = setup.bmRequestType; if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) { if (CDC_GET_LINE_CODING == r) { USB_SendControl(0,(void*)&_usbLineInfo,7); return true; } } if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) { if (CDC_SEND_BREAK == r) { breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; } if (CDC_SET_LINE_CODING == r) { USB_RecvControl((void*)&_usbLineInfo,7); } if (CDC_SET_CONTROL_LINE_STATE == r) { _usbLineInfo.lineState = setup.wValueL; } if (CDC_SET_LINE_CODING == r || CDC_SET_CONTROL_LINE_STATE == r) { // auto-reset into the bootloader is triggered when the port, already // open at 1200 bps, is closed. this is the signal to start the watchdog // with a relatively long period so it can finish housekeeping tasks // like servicing endpoints before the sketch ends uint16_t magic_key_pos = MAGIC_KEY_POS; // If we don't use the new RAMEND directly, check manually if we have a newer bootloader. // This is used to keep compatible with the old leonardo bootloaders. // You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check. #if MAGIC_KEY_POS != (RAMEND-1) // For future boards save the key in the inproblematic RAMEND // Which is reserved for the main() return value (which will never return) if (_updatedLUFAbootloader) { // horray, we got a new bootloader! magic_key_pos = (RAMEND-1); } #endif // We check DTR state to determine if host port is open (bit 0 of lineState). if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) { #if MAGIC_KEY_POS != (RAMEND-1) // Backup ram value if its not a newer bootloader. // This should avoid memory corruption at least a bit, not fully if (magic_key_pos != (RAMEND-1)) { *(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos; } #endif // Store boot key *(uint16_t *)magic_key_pos = MAGIC_KEY; wdt_enable(WDTO_120MS); } else { // Most OSs do some intermediate steps when configuring ports and DTR can // twiggle more than once before stabilizing. // To avoid spurious resets we set the watchdog to 250ms and eventually // cancel if DTR goes back high. wdt_disable(); wdt_reset(); #if MAGIC_KEY_POS != (RAMEND-1) // Restore backed up (old bootloader) magic key data if (magic_key_pos != (RAMEND-1)) { *(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1); } else #endif { // Clean up RAMEND key *(uint16_t *)magic_key_pos = 0x0000; } } } return true; } return false; }