예제 #1
0
/* Scan the hardware keyboard and push any changes up through the input layer */
static void tosakbd_scankeyboard(struct platform_device *dev)
{
	struct tosakbd *tosakbd = platform_get_drvdata(dev);
	unsigned int row, col, rowd;
	unsigned long flags;
	unsigned int num_pressed = 0;

	spin_lock_irqsave(&tosakbd->lock, flags);

	if (tosakbd->suspended)
		goto out;

	for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) {
		/*
		 * Discharge the output driver capacitatance
		 * in the keyboard matrix. (Yes it is significant..)
		 */
		tosakbd_discharge_all();
		udelay(KB_DISCHARGE_DELAY);

		tosakbd_activate_col(col);
		udelay(KB_ACTIVATE_DELAY);

		rowd = GET_ROWS_STATUS(col);

		for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) {
			unsigned int scancode, pressed;
			scancode = SCANCODE(row, col);
			pressed = rowd & KB_ROWMASK(row);

			if (pressed && !tosakbd->keycode[scancode])
				dev_warn(&dev->dev,
						"unhandled scancode: 0x%02x\n",
						scancode);

			input_report_key(tosakbd->input,
					tosakbd->keycode[scancode],
					pressed);
			if (pressed)
				num_pressed++;
		}

		tosakbd_reset_col(col);
	}

	tosakbd_activate_all();

	input_sync(tosakbd->input);

	/* if any keys are pressed, enable the timer */
	if (num_pressed)
		mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL);

 out:
	spin_unlock_irqrestore(&tosakbd->lock, flags);
}
예제 #2
0
/* Scan the hardware keyboard and push any changes up through the input layer */
static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data)
{
	unsigned int row, col, rowd;
	unsigned long flags;
	unsigned int num_pressed;

	if (corgikbd_data->suspended)
		return;

	spin_lock_irqsave(&corgikbd_data->lock, flags);

	num_pressed = 0;
	for (col = 0; col < KB_COLS; col++) {
		/*
		 * Discharge the output driver capacitatance
		 * in the keyboard matrix. (Yes it is significant..)
		 */

		corgikbd_discharge_all();
		udelay(KB_DISCHARGE_DELAY);

		corgikbd_activate_col(col);
		udelay(KB_ACTIVATE_DELAY);

		rowd = GET_ROWS_STATUS(col);
		for (row = 0; row < KB_ROWS; row++) {
			unsigned int scancode, pressed;

			scancode = SCANCODE(row, col);
			pressed = rowd & KB_ROWMASK(row);

			input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed);

			if (pressed)
				num_pressed++;

			if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
					&& time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) {
				input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
				corgikbd_data->suspend_jiffies=jiffies;
			}
		}
		corgikbd_reset_col(col);
	}

	corgikbd_activate_all();

	input_sync(corgikbd_data->input);

	/* if any keys are pressed, enable the timer */
	if (num_pressed)
		mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL));

	spin_unlock_irqrestore(&corgikbd_data->lock, flags);
}
예제 #3
0
/****************************************************************************
*
*   This function creates the Keymap Array with scan code RC pointing to KeyCode
*
***************************************************************************/
static int CreateKeyMap( struct CBLK *bcm_kp, struct BCM_GPIO_KEYMAP *keymap_p ) 
{
    int r,k, c=0;

    for(k=0;k<bcm_kp->key_count; k++)
    {
        r =  elementExistInArray( keymap_p->gpio_row, bcm_kp->row_count, bcm_kp->keyRowArray );
        c =  elementExistInArray( keymap_p->gpio_col, bcm_kp->col_count, bcm_kp->keyColArray );

        bcm_kp->keycode[SCANCODE(r,c)] = keymap_p->key_code;
        BCMKP_DBG(KERN_NOTICE "setting keymap r= %d, c=%d, code=%d\n", r,c,keymap_p->key_code);
        set_bit(keymap_p->key_code ,bcm_kp->input_dev->keybit);
        keymap_p++;
    }
    return(1);
}
예제 #4
0
/****************************************************************************f
*
*   Scan the matrix, and generate event for changes.
*
***************************************************************************/
static void keypad_scan( int gpio_pin, struct CBLK *bcm_kp )
{
	unsigned int stat;
	int r, gpio_c, value;
    int c = 0;

    r = elementExistInArray( gpio_pin, bcm_kp->row_count , bcm_kp->keyRowArray );
    stat = gpio_get_value(gpio_pin);
    if(stat)
    {
        /* At this point we know that the some key was released. So no point in scanning the 
        Matrix. Just report the last pressed key on same GPIO as released. */  
        
        /* Handle if its a Direct key release*/
        if(( bcm_kp->direct_key_col_index != -1 ) && ( bcm_kp->keycode[SCANCODE(r,bcm_kp->direct_key_col_index)] )) 
        {
            input_report_key(bcm_kp->input_dev, bcm_kp->keycode[SCANCODE(r,bcm_kp->direct_key_col_index)], !stat);         
            input_sync( bcm_kp->input_dev );
        }

        /* Handle Matrix Key Release */
        else
        {
            for(c=0;c< bcm_kp->col_count;c++)
            {
                if( test_bit( SCANCODE(r,c), bcm_kp->prevDown ) )
                {
                    input_report_key(bcm_kp->input_dev, bcm_kp->keycode[SCANCODE(r,c)], !stat);
                    input_sync( bcm_kp->input_dev );                    
                    change_bit( SCANCODE(r,c), bcm_kp->prevDown );
                    BCMKP_DBG(KERN_DEBUG "Key released r=%d c=%d..\n", r, c);
                } 
            }            
        }            
    }
    
    else {
        /* The Key is presses, so scan the Matrix */
        //Now we have the GPIO row that cause the interrupt 
        if(( bcm_kp->direct_key_col_index != -1 ) && ( bcm_kp->keycode[SCANCODE(r,bcm_kp->direct_key_col_index)] ))
        {
            /* The Key is a Direct Key */
            input_report_key(bcm_kp->input_dev, bcm_kp->keycode[SCANCODE(r,bcm_kp->direct_key_col_index)], !stat);            
            BCMKP_DBG(KERN_DEBUG "GPIO %d row press found Direct Key..\n", gpio_pin);
        }
        
        else{
            //Now set all Col as High
            for(c=0;c< bcm_kp->col_count;c++)
            {
                gpio_c = bcm_kp->keyColArray[c];
                if( gpio_c != BCM_NO_COLUMN )
                    gpio_set_value( gpio_c, 1 );
            }
            
            for(c=0;c< bcm_kp->col_count;c++)
            {
                gpio_c = bcm_kp->keyColArray[c];
                if( gpio_c == BCM_NO_COLUMN )
                    continue;
                gpio_set_value( gpio_c, 0 ); 
                value = gpio_get_value(gpio_pin); 
                gpio_set_value( gpio_c, 1 );
                
                if( !value )  //Found the Key
                {
                    if( bcm_kp->keycode[SCANCODE(r,c)] && !test_bit( SCANCODE(r,c), bcm_kp->prevDown ) )
                    {
                        /* report status to input-subsystem */
                        input_report_key(bcm_kp->input_dev, bcm_kp->keycode[SCANCODE(r,c)], !value);
                        input_sync( bcm_kp->input_dev );
                        change_bit( SCANCODE(r,c), bcm_kp->prevDown );
                        BCMKP_DBG(KERN_DEBUG "Key Pressed r=%d c=%d..\n", r, c);
                        break;
                    }
                }
                
            }
            
             //Now restore all the Col as Low for next interrupt
            for(c=0;c< bcm_kp->col_count;c++)
            {
                gpio_c = bcm_kp->keyColArray[c];
                if( gpio_c != BCM_NO_COLUMN )
                    gpio_set_value( gpio_c, 0 );
            }           
            
        }
	}
	return;
}
예제 #5
0
파일: locomokbd.c 프로젝트: 020gzh/linux
/* Scan the hardware keyboard and push any changes up through the input layer */
static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
{
	unsigned int row, col, rowd;
	unsigned long flags;
	unsigned int num_pressed;
	unsigned long membase = locomokbd->base;

	spin_lock_irqsave(&locomokbd->lock, flags);

	locomokbd_charge_all(membase);

	num_pressed = 0;
	for (col = 0; col < KB_COLS; col++) {

		locomokbd_activate_col(membase, col);
		udelay(KB_DELAY);

		rowd = ~locomo_readl(membase + LOCOMO_KIB);
		for (row = 0; row < KB_ROWS; row++) {
			unsigned int scancode, pressed, key;

			scancode = SCANCODE(col, row);
			pressed = rowd & KB_ROWMASK(row);
			key = locomokbd->keycode[scancode];

			input_report_key(locomokbd->input, key, pressed);
			if (likely(!pressed))
				continue;

			num_pressed++;

			/* The "Cancel/ESC" key is labeled "On/Off" on
			 * Collie and Poodle and should suspend the device
			 * if it was pressed for more than a second. */
			if (unlikely(key == KEY_ESC)) {
				if (!time_after(jiffies,
					locomokbd->suspend_jiffies + HZ))
					continue;
				if (locomokbd->count_cancel++
					!= (HZ/SCAN_INTERVAL + 1))
					continue;
				input_event(locomokbd->input, EV_PWR,
					KEY_SUSPEND, 1);
				locomokbd->suspend_jiffies = jiffies;
			} else
				locomokbd->count_cancel = 0;
		}
		locomokbd_reset_col(membase, col);
	}
	locomokbd_activate_all(membase);

	input_sync(locomokbd->input);

	/* if any keys are pressed, enable the timer */
	if (num_pressed)
		mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
	else
		locomokbd->count_cancel = 0;

	spin_unlock_irqrestore(&locomokbd->lock, flags);
}
예제 #6
0
namespace KKeyServer
{
struct TransKey {
    int qt_code;
    int mac_code;
};

static TransKey qtKeyToChar[] = {
    {Qt::Key_Escape,     kEscapeCharCode},
    {Qt::Key_Tab,        kTabCharCode},
    {Qt::Key_Backtab,    kTabCharCode},  // Backtab == tab with different modifiers
    {Qt::Key_Backspace,  kBackspaceCharCode},
    {Qt::Key_Return,     kReturnCharCode},
    {Qt::Key_Enter,      kEnterCharCode},
    // Insert
    {Qt::Key_Delete,     kDeleteCharCode},
    // Pause, Print, SysReq
    {Qt::Key_Clear,      kClearCharCode},
    {Qt::Key_Home,       kHomeCharCode},
    {Qt::Key_End,        kEndCharCode},
    {Qt::Key_Left,       kLeftArrowCharCode},
    {Qt::Key_Up,         kUpArrowCharCode},
    {Qt::Key_Right,      kRightArrowCharCode},
    {Qt::Key_Down,       kDownArrowCharCode},
    {Qt::Key_PageUp,     kPageUpCharCode},
    {Qt::Key_PageDown,   kPageDownCharCode},
    // Shift, Control, Meta, Alt, CapsLock, NumLock, ScrollLock
    // Super_L, Super_R, Menu, Hyper_L, Hyper_R
    {Qt::Key_Help,       kHelpCharCode},
    // Direction_L, Direction_R
    {Qt::Key_nobreakspace, kNonBreakingSpaceCharCode},
    {0, 0}
};

static QMultiMap<int, uint> scancodes;
static long lastLayoutID = -1;
#ifdef QT_MAC_USE_COCOA
static TISInputSourceRef lastLayout = 0;
#else
static KeyboardLayoutRef lastLayout = NULL;
#endif

void updateScancodes()
{
#ifdef QT_MAC_USE_COCOA
    TISInputSourceRef layout = TISCopyCurrentKeyboardLayoutInputSource();
    if (!layout) {
        qWarning() << "Error retrieving current layout";
        return;
    }
    if (layout == lastLayout) {
        CFRelease(layout);
    } else {
        // keyboard layout changed
#ifndef NDEBUG
        const void *name = TISGetInputSourceProperty(layout, kTISPropertyLocalizedName);
        qDebug() << "Layout changed to: " << CFStringGetCStringPtr((CFStringRef)name, 0);
#endif
        lastLayout = layout;
        scancodes.clear();

        CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(layout,
                                                kTISPropertyUnicodeKeyLayoutData));
        const UCKeyboardLayout *ucData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0;

        if (!ucData) {
            qWarning() << "Error retrieving current layout character data";
            return;
        }

        for (int i = 0; i < 128; ++i) {
            UInt32 tmpState = 0;
            UniChar str[4];
            UniCharCount actualLength = 0;
            OSStatus err = UCKeyTranslate(ucData, i, kUCKeyActionDown, 0, LMGetKbdType(),
                                          kUCKeyTranslateNoDeadKeysMask, &tmpState, 4, &actualLength, str);
            if (err != noErr) {
                qWarning() << "Error translating unicode key" << err;
            } else {
                if (str[0] && str[0] != kFunctionKeyCharCode) {
                    scancodes.insert(str[0], i);
                }
            }
        }
    }
#else
    KeyboardLayoutRef layout;
    if (KLGetCurrentKeyboardLayout(&layout) != noErr) {
        qWarning() << "Error retrieving current layout";
    }
    if (layout != lastLayout) {
#ifndef NDEBUG
        void *name;
        KLGetKeyboardLayoutProperty(layout, kKLName, const_cast<const void **>(&name));
        qDebug() << "Layout changed to: " << CFStringGetCStringPtr((CFStringRef) name, 0);
#endif
        lastLayout = layout;
        scancodes.clear();
        void *kchr;
        if (KLGetKeyboardLayoutProperty(layout, kKLKCHRData, const_cast<const void **>(&kchr)) != noErr) {
            qWarning() << "Couldn't load active keyboard layout";
        } else {
            for (int i = 0; i < 128; i++) {
                UInt32 tmpState = 0;
                UInt32 chr = KeyTranslate(kchr, i, &tmpState);
                if (chr && chr != kFunctionKeyCharCode) {
                    scancodes.insert(chr, i);
                }
            }
        }
    }
#endif
}

#define SCANCODE(name, value) { Qt::Key_ ## name, value }
static TransKey functionKeys[] = {
    SCANCODE(F1, 122),
    SCANCODE(F2, 120),
    SCANCODE(F3, 99),
    SCANCODE(F4, 118),
    SCANCODE(F5, 96),
    SCANCODE(F6, 97),
    SCANCODE(F7, 98),
    SCANCODE(F8, 100),
    SCANCODE(F9, 101),
    SCANCODE(F10, 109),
    //TODO: figure out scancodes of other F* keys
    { 0, 0 }
};
#undef SCANCODE

bool keyQtToSymMac(int keyQt, int &sym)
{
    // Printable ascii values, before A
    if (keyQt >= 0x20 && keyQt < Qt::Key_A) {
        sym = keyQt;
        return true;
    }
    // Letters, return lower-case equivalent
    if (keyQt >= Qt::Key_A && keyQt <= Qt::Key_Z) {
        sym = keyQt - Qt::Key_A + 'a';
        return true;
    }
    // Printable ascii values up to lower-case a
    if (keyQt > Qt::Key_Z && keyQt <= 0x60) {
        sym = keyQt;
        return true;
    }
    // Remainder of printable ascii values
    if (keyQt >= 0x7B && keyQt < 0x7F) {
        sym = keyQt;
        return true;
    }
    // Function keys
    if (keyQt >= Qt::Key_F1 && keyQt <= Qt::Key_F35) {
        sym = kFunctionKeyCharCode;
        return true;
    }
    // Try to find in lookup table
    for (int i = 0; qtKeyToChar[i].qt_code; i++) {
        if (qtKeyToChar[i].qt_code == keyQt) {
            sym = qtKeyToChar[i].mac_code;
            return true;
        }
    }

    // Not found
    return false;
}

bool keyQtToCodeMac(int keyQt, QList<uint> &keyCodes)
{
    updateScancodes();
    keyCodes.clear();
    keyQt &= ~Qt::KeyboardModifierMask;
    int chr;
    if (!keyQtToSymMac(keyQt, chr)) {
        return false;
    }

    if (chr == kFunctionKeyCharCode) {
        for (int i = 0; functionKeys[i].qt_code; i++) {
            if (functionKeys[i].qt_code == keyQt) {
                keyCodes.append(functionKeys[i].mac_code);
            }
        }
    } else {
        keyCodes += scancodes.values(chr);
    }

    return keyCodes.count() > 0;
}

bool keyQtToModMac(int keyQt, uint &mod)
{
    mod = 0;
    if (keyQt & Qt::ShiftModifier) {
        mod |= shiftKey;
    }
    if (keyQt & Qt::ControlModifier) {
        mod |= cmdKey;
    }
    if (keyQt & Qt::AltModifier) {
        mod |= optionKey;
    }
    if (keyQt & Qt::MetaModifier) {
        mod |= controlKey;
    }
    if (keyQt & Qt::KeypadModifier) {
        mod |= kEventKeyModifierNumLockMask;
    }
    // Special case for Qt::Key_Backtab
    if ((keyQt & ~Qt::KeyboardModifierMask) == Qt::Key_Backtab) {
        mod |= shiftKey;
    }

    return true;
}
} // end of namespace KKeyServer