void ps2_main(void){ m_state = STA_WAIT_RESET; kbd_init(); keymap_init(); clear(); //set key repeat speed; uint8_t gSpeed = eeprom_read_byte((uint8_t *)EEPROM_PS2_REPEAT_SPEED); if(gSpeed == 0xFF) gSpeed = 1; if(ps2_repeat_speed == PS2_REPEAT_SPEED_NONE){ ps2_repeat_speed = gSpeed; }else if(ps2_repeat_speed != gSpeed){ eeprom_write_byte((uint8_t *)EEPROM_PS2_REPEAT_SPEED, ps2_repeat_speed); } // init setKeyScanDriver(&driverKeyScanPs2); setUpdateDriver(&updatePs2); clearMatrix(); // DEBUG_PRINT(("STARTING PS/2 KEYBOARD\n")); sei(); // DBG1(0x90, 0, 0); for(;;){ // 카운트 이내에 신호가 잡히지 않으면 이동; // 특별한 경우에만 발생하는 현상이다. if(INTERFACE == INTERFACE_PS2 && interfaceReady == false && interfaceCount++ > 1000){ // move to usb INTERFACE = INTERFACE_USB; DBG1(0x99, 0, 0); break; } processRxPs2(); processTxPs2(); } // DBG1(0x9F, 0, 0); }
/** * Main function, containing the main loop that manages timer- and * USB-functionality. * /return the obligatory integer that nobody cares about... */ void usb_main(void) { // USB Reset by device only required on Watchdog Reset P2U_PS2_PORT &= ~((1 << P2U_PS2_CLOCK_PIN)|(1 << P2U_PS2_DATA_PIN)); // input:tri-state output:low P2U_USB_CFG_DDR &= ~((1 << P2U_USB_CFG_DPLUS_BIT)|(1 << P2U_USB_CFG_DMINUS_BIT));// input, remove USB reset condition usbInit(); int interfaceCount = 0; if( eeprom_read_byte((uint8_t *)EEPROM_USB_COMPATIBILITY) == 0x00 ) { usbDeviceDisconnect(); /* do this while interrupts are disabled */ uchar i = 0; do{ /* fake USB disconnect for > 250 ms */ wdt_reset(); _delay_ms(1); }while(--i); } usbDeviceConnect(); // init setKeyScanDriver(&driverKeyScanUsb); setUpdateDriver(&updateUsb); clearReportBuffer(); sei(); #if USB_COUNT_SOF bool _isSuspended = false; int suspendCount = 0; #endif for(;;){ /* * USB3.0 + win10의 경우 usbDeviceConnect() 딜레이가 있으면 일부 장치에서 인식이 되지않아 이를 제거 * 하지만, 구식 부트로더 (ps2avrGB_bootloader_140623)의 경우 빠져나올 때 usbDeviceDisconnect()를 처리하지 않아서 * 이를 여기서 처리해줌. */ if(interfaceReady == false && interfaceCount++ > 1000) { cli(); usbDeviceDisconnect(); wdt_enable(WDTO_15MS); for(;;); } #if USB_COUNT_SOF if (usbSofCount != 0) { _isSuspended = false; usbSofCount = 0; suspendCount = 0; _usbReset = false; wakeUp(); } else if(_usbReset == true){ _isSuspended = false; usbSofCount = 1; wakeUp(); }else{ // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1) if (_isSuspended == false && suspendCount++ > 1000 && isReleaseAll()) { _isSuspended = true; sleep(); } } #endif // main event loop usbPoll(); // if an update is needed, send the report if (usbInterruptIsReady()) { scanKeyUsbWithMacro(); // changes? if(updateNeeded){ if(interfaceReady==false) continue; #if USB_COUNT_SOF if(_isSuspended == true) { wake_up_signal(); updateNeeded = 0; continue; } #endif memset(reportKeyboard, 0, REPORT_SIZE_KEYBOARD); reportKeyboard[0] = _modifiers; reportKeyboard[1] = 0; memcpy ( reportKeyboard+2, reportBuffer, _countOfBuffer ); //strlen((char *)reportBuffer) ); // DBG1(0x06, (uchar *)&reportKeyboard, 8); usbSetInterrupt((void *)&reportKeyboard, sizeof(reportKeyboard)); updateNeeded = 0; #if !USB_COUNT_SOF wakeUpUsb(); #endif }else if(_initState == INIT_INDEX_SET_IDLE){ // DBG1(0x99, (uchar *)&_initState, 1); _initState = INIT_INDEX_INITED; // 재부팅시 첫키 입력 오류를 방지하기 위해서 HID init 후 all release 전송; memset(reportKeyboard, 0, REPORT_SIZE_KEYBOARD); usbSetInterrupt((void *)&reportKeyboard, sizeof(reportKeyboard)); clearMatrix(); #if !USB_COUNT_SOF wakeUpUsb(); #endif // 플러깅 후 출력되는 메세지는 넘락등 LED가 반응한 후에 보여진다. // usbInterruptIsReady() 일지라도 LED 반응 전에는 출력이 되지 않는다. // LED 반응 후에 처리하려고 하면 MAC OS에서 실행되지 않는다. // (MAC OS에서는 플러깅 시 LED가 반응하지 않는다. 대신 바로 출력이 된다.) // for os x // DBG1(0xAA, (uchar *)&idleRate, 1); }else if(_ledInitState == INIT_LED_INDEX_INITED){ _ledInitState = INIT_LED_INDEX_COMPLETE; // for windows } // ps2avrU loop, must be after scan matrix; enterFrame(); } #if !defined( USING_SIMPLE_MODE ) if(usbInterruptIsReady3()){ if(_extraHasChanged){ report_extra_t gReportExtra = { .report_id = REPORT_ID_CONSUMER, .usage = extraData }; usbSetInterrupt3((void *)&gReportExtra, sizeof(gReportExtra)); _extraHasChanged = false; #if !USB_COUNT_SOF wakeUpUsb(); #endif } if(_systemHasChanged){ report_extra_t gReportExtra = { .report_id = REPORT_ID_SYSTEM, .usage = systemData }; usbSetInterrupt3((void *)&gReportExtra, sizeof(gReportExtra)); _systemHasChanged = false; #if !USB_COUNT_SOF wakeUpUsb(); #endif } } #endif if(_initState == INIT_INDEX_INITED){ if(initCount++ == 200){ // delay for OS X USB multi device // all platform init led initAfterInterfaceMount(); // DBG1(0xAB, (uchar *)&initCount, 2); }else if(initCount > 200){ initCount = 201; _initState = INIT_INDEX_COMPLETE; } } #if !USB_COUNT_SOF // 입력이 한동안 없으면 슬립모드로; countSleepUsb(); #endif } /* #if !defined(INTERFACE_ONLY_USB) // data line reset; USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); #endif */ }
/** * Main function, containing the main loop that manages timer- and * USB-functionality. * /return the obligatory integer that nobody cares about... */ void usb_main(void) { // USB Reset by device only required on Watchdog Reset P2U_PS2_PORT &= ~((1 << P2U_PS2_CLOCK_PIN)|(1 << P2U_PS2_DATA_PIN)); // input:tri-state output:low P2U_USB_CFG_DDR &= ~((1 << P2U_USB_CFG_DPLUS_BIT)|(1 << P2U_USB_CFG_DMINUS_BIT));// input, remove USB reset condition // configure timer 0 for a rate of 12M/(1024 * 256) = 45.78Hz (~22ms) //TCCR0 |= (1<<CS02)|(1<<CS00); // timer 0 prescaler: 1024 // TCCR0 &= ~((1<<CS02)|(1<<CS01)|(1<<CS00)); // timer stop usbInit(); uint8_t idleCounter = 0; uchar i = 0; usbDeviceDisconnect(); /* do this while interrupts are disabled */ do{ /* fake USB disconnect for > 250 ms */ // wdt_reset(); _delay_ms(1); }while(--i); usbDeviceConnect(); // init setKeyScanDriver(&driverKeyScanUsb); setUpdateDriver(&updateUsb); clearReportBuffer(); sei(); #if USB_COUNT_SOF bool _isSuspended = false; int suspendCount = 0; #endif for(;;){ #ifndef INTERFACE_ONLY_USB // 카운트 이내에 신호가 잡히지 않으면 이동; // 특별한 경우에만 발생하는 현상이다. if(INTERFACE == INTERFACE_USB && interfaceReady == false && interfaceCount++ > 3000){ // move to ps/2 INTERFACE = INTERFACE_PS2; DBG1(0x88, 0, 0); break; } #endif #if USB_COUNT_SOF if (usbSofCount != 0) { // DBG1(0x55, (uchar *)&usbSofCount, 1); _isSuspended = false; usbSofCount = 0; suspendCount = 0; _usbReset = false; wakeUp(); } else if(_usbReset == true){ // DBG1(0x56, (uchar *)&usbSofCount, 1); _isSuspended = false; usbSofCount = 1; wakeUp(); }else{ // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1) if (_isSuspended == false && suspendCount++ > 10000 && getModifierDownBuffer() == 0 && getDownBufferAt(0) == 0) { // DBG1(0x5a, (uchar *)&usbSofCount, 2); _isSuspended = true; sleep(); } } #endif // main event loop usbPoll(); #if USB_COUNT_SOF /*if(_isSuspended == true) { continue; }*/ #endif // check timer if we need periodic reports if (TIFR & (1 << TOV0)) { TIFR = (1 << TOV0); // reset flag if (idleRate != 0) { // do we need periodic reports? if(idleCounter > 4){ // yes, but not yet idleCounter -= 5; // 22ms in units of 4ms } else { // yes, it is time now updateNeeded = 1; idleCounter = idleRate; } } } // if an update is needed, send the report if (usbInterruptIsReady()) { scanKeyUsbWithMacro(); // changes? // ps2avrU loop, must be after scan matrix; enterFrame(); if(updateNeeded){ if(interfaceReady==false) continue; memset(reportKeyboard, 0, REPORT_SIZE_KEYBOARD); reportKeyboard[0] = _modifiers; reportKeyboard[1] = 0; memcpy ( reportKeyboard+2, reportBuffer, strlen((char *)reportBuffer) ); // DBG1(0x06, (uchar *)&reportKeyboard[0], 1); usbSetInterrupt((void *)&reportKeyboard, sizeof(reportKeyboard)); updateNeeded = 0; #if !USB_COUNT_SOF wakeUpUsb(); #endif }else if(_initState == INIT_INDEX_SET_IDLE){ DBG1(0x99, (uchar *)&_initState, 1); _initState = INIT_INDEX_INITED; // 재부팅시 첫키 입력 오류를 방지하기 위해서 HID init 후 all release 전송; memset(reportKeyboard, 0, REPORT_SIZE_KEYBOARD); usbSetInterrupt((void *)&reportKeyboard, sizeof(reportKeyboard)); clearMatrix(); #if !USB_COUNT_SOF wakeUpUsb(); #endif // 플러깅 후 출력되는 메세지는 넘락등 LED가 반응한 후에 보여진다. // usbInterruptIsReady() 일지라도 LED 반응 전에는 출력이 되지 않는다. // LED 반응 후에 처리하려고 하면 MAC OS에서 실행되지 않는다. // (MAC OS에서는 플러깅 시 LED가 반응하지 않는다. 대신 바로 출력이 된다.) // for os x if(idleRate > 0) { startKeyMappingOnBoot(); } // DBG1(0xAA, (uchar *)&idleRate, 1); }else if(_ledInitState == INIT_INDEX_INITED){ _ledInitState = INIT_INDEX_COMPLETE; // for windows if(idleRate == 0) { startKeyMappingOnBoot(); } } } if(usbInterruptIsReady3()){ if(_extraHasChanged){ report_extra_t gReportExtra = { .report_id = REPORT_ID_CONSUMER, .usage = extraData }; usbSetInterrupt3((void *)&gReportExtra, sizeof(gReportExtra)); _extraHasChanged = false; #if !USB_COUNT_SOF wakeUpUsb(); #endif } if(_systemHasChanged){ report_extra_t gReportExtra = { .report_id = REPORT_ID_SYSTEM, .usage = systemData }; usbSetInterrupt3((void *)&gReportExtra, sizeof(gReportExtra)); _systemHasChanged = false; #if !USB_COUNT_SOF wakeUpUsb(); #endif } } if(_initState == INIT_INDEX_INITED){ if(initCount++ == 200){ // delay for OS X USB multi device // all platform init led initAfterInterfaceMount(); }else if(initCount > 200){ initCount = 201; _initState = INIT_INDEX_COMPLETE; } } #if !USB_COUNT_SOF // 입력이 한동안 없으면 슬립모드로; countSleepUsb(); #endif } #ifndef INTERFACE_ONLY_USB // data line reset; USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); #endif }