⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kdriver.c

📁 嵌入式linux下的4*5键盘驱动功能
💻 C
📖 第 1 页 / 共 2 页
字号:
			at91_set_gpio_value(AT91_PIN_PB15,0);			break;		case 3:			at91_set_gpio_value(AT91_PIN_PB16,0);			break;		case 4:			at91_set_gpio_value(AT91_PIN_PB17,0);			break;	}	}//#define GET_ROWS_STATUS(c)	(((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT))/* * The scan keyboard only generates interrupts when a key is pressed. * When a key is pressed, we enable a timer which then scans the * keyboard to detect when the key is released. *///scan/* Scan the hardware keyboard and push any changes up through the input layer */static void scankbd_scankeyboard(struct scankbd *scankbd_data, struct pt_regs *regs){	unsigned int row, col, rowd, scancode;	unsigned long flags;	unsigned int num_pressed;	spin_lock_irqsave(&scankbd_data->lock, flags);	if (regs)		input_regs(&scankbd_data->scan_kbd_dev, regs);	scan_kbd_discharge_all();	udelay(10);	num_pressed = 0;	udelay(10);	readr = GET_ROWS_STATUS(col);//获取键盘按下瞬间的行状态		for (col = 0; col < KB_COLS; col++) {	//	udelay(10);		//scan_kbd_activate_all();		scan_kbd_activate_col(col);//设置一列为1		udelay(10);		rowd = GET_ROWS_STATUS(col);//行端口状态		if(rowd!=readr)		{//与键按下时的行状态比较		for (row = 0; row < KB_ROWS; row++) {			scancode = SCANCODE(row, col);//			//handle_scancode((readr & KB_ROWMASK(row)), scancode, scankbd_data);//get the key status						if ( readr & KB_ROWMASK(row))			{				num_pressed++;				//printk(KERN_ALERT "col %i\n", col);				//printk(KERN_ALERT "readr %i\n", readr);				//printk(KERN_ALERT "KB_ROWMASK %i\n", KB_ROWMASK(row));				//printk(KERN_ALERT "row %i\n", row);				//printk(KERN_ALERT "rowd %i\n", rowd);				input_report_key(&(scankbd_data->scan_kbd_dev), scankbd_data->keycode[scancode], 1);				//input_sync(&(scankbd_data->scan_kbd_dev));				printk(KERN_ALERT "keycode %i\n", scankbd_data->keycode[scancode]);			}			else				input_report_key(&(scankbd_data->scan_kbd_dev), scankbd_data->keycode[scancode], 0);				//input_sync(&(scankbd_data->scan_kbd_dev));			//printk(KERN_ALERT "scan_kbd %d\n", row);		}		}		scan_kbd_reset_col(col);	}	//scan_kbd_activate_all();	input_sync(&scankbd_data->scan_kbd_dev);	/* if any keys are pressed, enable the timer */	if (num_pressed)	{//注册定时器		mod_timer(&scankbd_data->scan_timer, jiffies + SCAN_INTERVAL);	}		spin_unlock_irqrestore(&scankbd_data->lock, flags);}/* * timer checking for released keys */static void scan_timer_callback(unsigned long data){	printk(KERN_ALERT "Timer callback.\n");	struct scankbd *scankbd_data = (struct scankbd *) data;	scankbd_scankeyboard(scankbd_data, NULL);}/* * The 4� keyboard only generates interrupts when a key is pressed. * When a key is pressed, we enable a timer which then scans the * keyboard to detect when the key is released. *//* Scan the hardware keyboard and push any changes up through the input layer */static irqreturn_t scan_kbd_interrupt(int irq, void *dummy, struct pt_regs *regs){	struct scankbd *scankbd_data = dummy;	//printk(KERN_ALERT "scan_kbd_interrupt\n");	if (!timer_pending(&scankbd_data->scan_timer)) 	{		/** wait chattering delay **/		udelay(20);		scankbd_scankeyboard(scankbd_data, regs);	}	return IRQ_HANDLED;}static int khello_init_module(void){	int i;	unsigned int status;	struct scankbd *scankbd;	/** * kcalloc - allocate memory for an array. The memory is set to zero. * @n: number of elements. * @size: element size. * @flags: the type of memory to allocate. */	scankbd = kcalloc(1, sizeof(struct scankbd), GFP_KERNEL);//	//scankbd = input_allocate_device();	if (!scankbd)		return -ENOMEM;			//init 9200 gpio register 	//AT91_SYS->PIOB_PER  |= ( AT91C_PIO_PB1 | AT91C_PIO_PB2 | AT91C_PIO_PB6  );//PIO Enable Register	//AT91_SYS->PIOB_ODR  |= ( AT91C_PIO_PB1 | AT91C_PIO_PB2 | AT91C_PIO_PB6  );//Output Disable Register	//AT91_SYS->PIOB_PPUDR &=  ~( AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11 | AT91C_PIO_PB12 );//Pull-up Disable Register	//AT91_SYS->PIOB_PPUER |= ( AT91C_PIO_PB9 | AT91C_PIO_PB10 | AT91C_PIO_PB11 | AT91C_PIO_PB12 );//Pull-up Enable Register	//init 9200 gpio attribute :input /output		at91_set_gpio_input(AT91_PIN_PB1,1);	at91_set_deglitch(AT91_PIN_PB1,1);	at91_set_gpio_input(AT91_PIN_PB2,1);	at91_set_deglitch(AT91_PIN_PB2,1);	at91_set_gpio_input(AT91_PIN_PB6,1);	at91_set_deglitch(AT91_PIN_PB6,1);	at91_set_gpio_input(AT91_PIN_PA24,1);	at91_set_deglitch(AT91_PIN_PA24,1);	at91_set_gpio_output(AT91_PIN_PB7,1);	at91_set_gpio_output(AT91_PIN_PB8,1);	at91_set_gpio_output(AT91_PIN_PB15,1);	at91_set_gpio_output(AT91_PIN_PB16,1);	at91_set_gpio_output(AT91_PIN_PB17,1);		//printk(KERN_ALERT "init output.\n");	scan_kbd_discharge_all();	AT91_SYS->PIOB_IER  |=  ( AT91C_PIO_PB1 | AT91C_PIO_PB2 | AT91C_PIO_PB6  );//Interrupt Enable Register	AT91_SYS->PIOB_IDR  &=   ~( AT91C_PIO_PB1 | AT91C_PIO_PB2 | AT91C_PIO_PB6  );//Interrupt Disable Register	AT91_SYS->PIOA_IER  |=  AT91C_PIO_PA24;//Interrupt Enable Register	AT91_SYS->PIOA_IDR  &=   ~AT91C_PIO_PA24;//Interrupt Disable Register	    status = AT91_SYS->PIOB_ISR & AT91_SYS->PIOB_IMR;//Interrupt Status Register & Interrupt Mask Register	AT91_SYS->PMC_PCER |= (1 << AT91C_ID_PIOB);// Peripheral Clock Enable Register	AT91_SYS->PMC_PCER |= (1 << AT91C_ID_PIOA);// Peripheral Clock Enable Register	/* Store the Source Mode Register as defined in table above */	AT91_SYS->AIC_SMR[2] = (AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED);//Parallel IO Controller A(AIC) Internal Sources Code Label Edge triggered	AT91_SYS->AIC_SMR[3] = (AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED);//Parallel IO Controller B(AIC) Internal Sources Code Label Edge triggered	init_input_dev(&scankbd->scan_kbd_dev);//init listhaed /listnode 	scankbd->scan_kbd_dev.evbit[0] = BIT(EV_KEY) ;	scankbd->scan_kbd_dev.keycode = scan_kbd_keycode;	scankbd->scan_kbd_dev.keycodesize = sizeof(unsigned char);	scankbd->scan_kbd_dev.keycodemax = ARRAY_SIZE(scan_kbd_keycode);	scankbd->scan_kbd_dev.private = scankbd;	memcpy(scankbd->keycode, scan_kbd_keycode, sizeof(scankbd->keycode));	//printk(KERN_ALERT "keycode %i\n",scankbd->keycode[2]);		for (i = 0; i < 20; i++)			set_bit(scankbd->keycode[i], scankbd->scan_kbd_dev.keybit);//if (scan_kbd_keycode[i])	clear_bit(0, scankbd->scan_kbd_dev.keybit);	scankbd->scan_kbd_dev.name = scan_kbd_name;	scankbd->scan_kbd_dev.phys = scan_kbd_phys;	scankbd->scan_kbd_dev.id.bustype = BUS_HOST;	scankbd->scan_kbd_dev.id.vendor = 0x0001;	scankbd->scan_kbd_dev.id.product = 0x0001;	scankbd->scan_kbd_dev.id.version = 0x0100;	/* Init Keyboard rescan timer */	init_timer(&scankbd->scan_timer);	scankbd->scan_timer.function = scan_timer_callback;	//printk(KERN_ALERT "timerdata: %ul\n", (unsigned long) scankbd);	scankbd->scan_timer.data = (unsigned long) scankbd;//(unsigned long) scankbd	//add_timer(&scankbd->scan_timer);	//for (i = 0; i < 20; i++)		//	scankbd->state[i] = 0;	scankbd_dev = scankbd;	//Enable interrupt 内存泄露,中断源泄露	if(-EINVAL == request_irq(AT91_PIN_PA24,scan_kbd_interrupt,SA_INTERRUPT,scan_kbd_name,scankbd) )	{		printk(KERN_ALERT"AT91C_PIO_PA24 is busy.");		return -EBUSY;	}	if( request_irq(AT91_PIN_PB1,scan_kbd_interrupt,SA_INTERRUPT,scan_kbd_name,scankbd) )	{		printk(KERN_ALERT"AT91C_PIO_PB1 is busy.");		return -EBUSY;	}	if( request_irq(AT91_PIN_PB2 ,scan_kbd_interrupt,SA_INTERRUPT,scan_kbd_name,scankbd) )	{		printk(KERN_ALERT"AT91C_PIO_PB2 is busy.");		return -EBUSY;	}	if( request_irq(AT91_PIN_PB6,scan_kbd_interrupt,SA_INTERRUPT,scan_kbd_name,scankbd) )	{		printk(KERN_ALERT"AT91C_PIO_PB6 is busy.");		return -EBUSY;	}		input_register_device(&scankbd->scan_kbd_dev);		printk(KERN_ALERT "input: %s init\n", scan_kbd_name);	return 0;}static void khello_exit_module(void){	//struct scankbd *scankbd;	free_irq(AT91C_PIO_PA24, scankbd_dev);	free_irq(AT91C_PIO_PB6, scankbd_dev);	free_irq(AT91C_PIO_PB2, scankbd_dev);	free_irq(AT91C_PIO_PB1, scankbd_dev);	del_timer_sync(&scankbd_dev->scan_timer);	input_unregister_device(&scankbd_dev->scan_kbd_dev);/** * kfree - free previously allocated memory * @objp: pointer returned by kmalloc. * * Don't free memory not originally allocated by kmalloc() * or you will run into trouble. */	kfree(scankbd_dev);	printk(KERN_ALERT "Module khello exit\n" );}module_init(khello_init_module);module_exit(khello_exit_module);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -