예제 #1
0
static void applyQuickSwap(void) {
	static uint8_t prevModifier = 0;

	if(getDownBufferAt(0) > 0){
		enabledQuickSwapCount = 0;
		return;
	}
	
	uint8_t gModi = getModifierDownBuffer();

	if(gModi != prevModifier) {

        if(gModi == (MODI_RSHIFT|MODI_LALT|MODI_LGUI) || gModi == (MODI_RSHIFT|MODI_RALT|MODI_RGUI) || gModi == (MODI_RSHIFT|MODI_LALT|MODI_RGUI) || gModi == (MODI_RSHIFT|MODI_LALT|MODI_LGUI)){	// ALT + GUI + R SHIFT
            _quickSwapCount = 0;
            enabledQuickSwapCount = COUNT_TYPE_QUICKSWAP_ALT_GUI;
        }else{
            enabledQuickSwapCount = 0;
        }

        prevModifier = gModi;

    }

//}
//static void countQuickSwapEnabled(void){
	if(enabledQuickSwapCount && ++_quickSwapCount > quickSwapCountMax){
		if(enabledQuickSwapCount == COUNT_TYPE_QUICKSWAP_ALT_GUI){
			blinkOnce(50);
			if((quickSwapMode & QUICKSWAP_ALT_GUI) == QUICKSWAP_ALT_GUI){			
				quickSwapMode &= ~QUICKSWAP_ALT_GUI;
			}else{
				quickSwapMode |= QUICKSWAP_ALT_GUI;		
				_delay_ms(50);
				blinkOnce(100);
			}
		}		
		eeprom_update_byte((uint8_t *)EEPROM_QUICK_SWAP, quickSwapMode);
		enabledQuickSwapCount = 0;
	}

}
예제 #2
0
/*static uint8_t pushKeyCodeDummy(uint8_t keyidx, bool isDown){
    return 0;
}*/
static uint8_t pushKeyCode(uint8_t keyidx, bool isDown)
{
    if(keyidx == KEY_NONE) return 0;

//    keyidx = getDualActionKeyWhenCompound(keyidx);
    keyidx = getDualActionDownKeyIndexWhenIsCancel(keyidx);

    if(keyidx >= KEY_MAX) return 0;

    DBG1(0x20, (uchar *)&keyidx, 2);

    // if prev and current state are different,
    uint8_t keyVal = pgm_read_byte(&keycode_set2[keyidx]);

    if(isDown) {        // make code
        lastMAKE_keyidx = keyidx;
        loopCnt=0;
        m_state = STA_NORMAL;

        if(KFLA[keyidx]&KFLA_SPECIAL) {
            switch(keyidx) {
                case KEY_PRNSCR:
                    push(START_MAKE);
                    push(0xE0);
                    push(0x12);
                    push(0xE0);
                    push(0x7C);
                    push(END_MAKE);
                    push(SPLIT); // SPLIT is for make sure all key codes are transmitted before disturbed by RX
                    break;
                case KEY_PAUSE:
                    push(NO_REPEAT);
                    push(0xE1);
                    push(0x14);
                    push(0x77);
                    push(0xE1);
                    push(0xF0);
                    push(0x14);
                    push(0xF0);
                    push(0x77);
                    push(SPLIT);
                    break;
            }
        }else if(KFLA[keyidx]&KFLA_MAKEONLY) {
            push(keyVal);
            push(SPLIT);
        }else{
            push(START_MAKE);
            if(KFLA[keyidx]&KFLA_EXTEND) 
                push(0xE0);
            push(keyVal);

            push(END_MAKE);
            push(SPLIT);

        }


        // 2 연속으로 waiting rx 키가 입력 되면 오류로 키보드가 멈춘다. 이를 방지 하기 위해서 isAlreadyPushedWaitingRx를 설정;
        if((KFLA[keyidx] & KFLA_WAIT_UNTIL_RX) && isAlreadyPushedWaitingRx == false){
        	isAlreadyPushedWaitingRx = true;
            if(keyidx == KEY_SCRLCK){
            	// ctrl + scroll lock 키는 LED 반응을 하지 않으니 설정안함
            	// ctrl + alt + s/l 등 다른 조합키와 섞이면 반응함
            	uint8_t gModi = getModifierDownBuffer();
				if(!(gModi == 0x01) || !(gModi == 0x10) || !(gModi == 0x11)){
	            	push(WAIT_RX);
				}
            }else{
            	push(WAIT_RX);
            }
        }
    }
    else            // break code - key realeased
    {
        if(lastMAKE_keyidx == keyidx)       // repeat is resetted only if last make key is released
            lastMAKE_SIZE=0;

        if(KFLA[keyidx]&KFLA_SPECIAL) {
            switch(keyidx) {
                case KEY_PRNSCR:
                    push(0xE0);
                    push(0xF0);
                    push(0x7C);
                    push(0xE0);
                    push(0xF0);
                    push(0x12);
                    push(SPLIT);
                    break;
            }
        }else if(KFLA[keyidx]&KFLA_MAKEONLY) {
        }else{
            if(KFLA[keyidx]&KFLA_EXTEND)
                push(0xE0);

            push(0xF0);
            push(keyVal);
            push(SPLIT);

            // DBG1(0x21, (uchar *)&keyidx, 1); 
        }
    }
    return 1;
}
예제 #3
0
void enterFrameForQuickSwap(void){
	applyQuickSwap(getModifierDownBuffer());

	countQuickSwapEnabled();
}
예제 #4
0
// 키를 누르거나 땔때 FN 및 LED등 을 컨트롤한다.
bool applyFN(uint8_t xKeyidx, uint8_t xCol, uint8_t xRow, bool xIsDown) {

    // DEBUG_PRINT(("applyFN  : %d xIsDown : %d\n", xKeyidx, xIsDown));
    applyKeyDownForFullLED(xKeyidx, xCol, xRow, xIsDown);

    if(isFnKey(xKeyidx)) return false; 

    setDualAction(xKeyidx, xIsDown);    

    // 듀얼액션 키의 기본 키를 가져온다.
    xKeyidx = getDualActionDefaultKey(xKeyidx);
    if(isFnKey(xKeyidx)) return false; 

    if(xIsDown) {

        if((xKeyidx ==  KEY_BEYOND_FN || xKeyidx == KEY_BEYOND_FN3)
        		|| (_isExtraFNDown && xKeyidx == BEYOND_FN_CANCEL_KEY)){ // beyond_fn을 활성화;
             if( xKeyidx == BEYOND_FN_CANCEL_KEY ) {    // 취소만 가능한 키 
                _beyondFnIndex = false;
             }else{
            	if(_beyondFnIndex == 0){
            		if(xKeyidx ==  KEY_BEYOND_FN){
            			_beyondFnIndex = LAYER_FN2;
            		}else{
            			_beyondFnIndex = LAYER_FN3;
            		}
            	}else{
            		if(xKeyidx ==  KEY_BEYOND_FN){
            			if(_beyondFnIndex ==  LAYER_FN2){
            				_beyondFnIndex = LAYER_NORMAL;
            			}else{
            				_beyondFnIndex = LAYER_FN2;
            			}
					}else if(xKeyidx ==  KEY_BEYOND_FN3){
            			if(_beyondFnIndex ==  LAYER_FN3){
            				_beyondFnIndex = LAYER_NORMAL;
            			}else{
            				_beyondFnIndex = LAYER_FN3;
            			}
					}
            	}
             }

#ifndef DISABLE_FN2_TOGGLE_LED_BLINK 
             if(isBeyondFnLedEnabled() == false){
                 if(_beyondFnIndex == 0){
                    blinkOnce(100);
                 }else{
                    blinkOnce(100);
                    _delay_ms(80);
                    blinkOnce(70);
                 }
             }
#endif

             if(isBeyondFnLedEnabled()){    
                setLed(LED_STATE_NUM, isBeyondFN());
             }

             return 0;
        }else if(_isQuickMacroDown && isEepromMacroKey(xKeyidx)){
            _quickMacroIndex = xKeyidx - KEY_MAC1; 
            _isReadyQuickMacro = true;
            return 0;
        }else if(xKeyidx == EXTRA_FN){
            _isExtraFNDown = true;
        }else if((_isExtraFNDown && xKeyidx == LED_KEY)){
        	uint8_t gModi = getModifierDownBuffer();
			if(gModi == 0x02 || gModi == 0x20){
				changeFullLedState(FULL_LED_MODE2);
			}else{
				changeFullLedState(FULL_LED_MODE1);
			}
            return 0;
        }else if(xKeyidx == KEY_LED){
			changeFullLedState(FULL_LED_MODE1);
			return 0;
        }else if(xKeyidx == KEY_LED2){
			changeFullLedState(FULL_LED_MODE2);
			return 0;
        }else if(xKeyidx == KEY_LED_UP){
        	uint8_t gModi = getModifierDownBuffer();
        	if(gModi == 0x02 || gModi == 0x20){
        		increaseLedBrightness(FULL_LED_MODE2);
        	}else{
        		increaseLedBrightness(FULL_LED_MODE1);
        	}
        	return 0;
        }else if(xKeyidx == KEY_LED_DOWN){
        	uint8_t gModi = getModifierDownBuffer();
        	if(gModi == 0x02 || gModi == 0x20){
        		reduceLedBrightness(FULL_LED_MODE2);
        	}else{
        		reduceLedBrightness(FULL_LED_MODE1);
        	}
            return 0;
        }else if(xKeyidx == KEY_LED_ON_OFF){
        	_ledOff ^= true;
        	if(_ledOff == false){
        		turnOnLedAll();
        	}else{
        		turnOffLedAll();
        	}
        }else if(xKeyidx == KEY_QUICK_MACRO){
            if(isQuickMacro()){
                stopQuickMacro();
            }else{
                _isQuickMacroDown = true;                
            }
            return 0;
        }

    }else{  // up 

        if(xKeyidx ==  KEY_BEYOND_FN){  // beyond_fn             
             return 0;
        }else if(xKeyidx == EXTRA_FN){
            _isExtraFNDown = false;
        }else if(xKeyidx == KEY_QUICK_MACRO){
            _isQuickMacroDown = false;
            return 0;
        }
    }

    return 1;
}
예제 #5
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
    
    // 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

}