static void initPs2(void) { if(interfaceReady == false){ interfaceReady = true; initAfterInterfaceMount(); startKeyMappingOnBoot(); } }
/** * 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 }