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

📄 common.c

📁 arm 平台下 linux gpio 的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Soekris Netxxxx GPIO driver Common functions shared between the net4501 and net4801 driver  (c) Copyright 2003-2004   Martin Hejl <martin@hejl.de>                            G&H Softwareentwicklung GmbH ********************************************************************** * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ********************************************************************** * */#define GPIO_PROC_FILE 1#define LED_PROC_FILE 2#define SETTINGS_PROC_FILE 4#define TEMP_PROC_FILE 8#define VOLT_PROC_FILE 16#include "common.h"struct gpio_operations *driver_ops;static int gpio_major =  GPIO_MAJOR;int __number_of_pins;static unsigned long init_map;struct semaphore gpio_sema;extern int net4501_init(struct gpio_operations **driver_ops);extern int net4801_init(struct gpio_operations **driver_ops);void __exit common_cleanup(void);int toString(unsigned long value, char* buffer, int number_of_bits) {	static int i;	/* convert it into a string */	for(i=number_of_bits;i>0;i--){		buffer[number_of_bits-i]=test_bit(i-1,&value)?'1':'0';	}	buffer[number_of_bits] = '\n';	buffer[number_of_bits+1] = 0;	return number_of_bits+1;}unsigned long  fromString(char* buffer, int number_of_bits) {	static int i;	static unsigned long ret_val=0;	ret_val = 0;	/* Create WORD to write from the string */	for(i=0;i<number_of_bits;i++){		if (buffer[i] == 0) break;		if (buffer[i] == '0' || buffer[i] == '1') {			ret_val=ret_val<<1;		}		if (buffer[i] == '1') {			ret_val |= 1;		}	}	return(ret_val);}//------------------------------------------------static ssize_t net4xxx_gpio_write(struct file *file, const char *data,                                 size_t count, loff_t *ppos){	unsigned m;	size_t        i;	char          port_status=0;	ssize_t       ret = 0;	unsigned int  value=0;	unsigned int  temp_value;	m = MINOR(file->f_dentry->d_inode->i_rdev);	if (ppos != &file->f_pos)		return -ESPIPE;	if (down_interruptible(&gpio_sema))		return -ERESTARTSYS;	value = 0;	for (i = 0; i < count; ++i) {		port_status = 0;		ret = __get_user(port_status, (char *)data);		if (ret != 0) {			//ret = -EFAULT;			goto out;		}		switch(m) {			case MINOR_BYTE:				driver_ops->write8Bit(port_status);				break;			case MINOR_FULL:				if ((i&1) == 0) {					value = ((unsigned char)port_status);				} else {					temp_value = ((unsigned char)port_status);					value |= ((temp_value<<8)&0xF00);					driver_ops->write16Bit(value);				}				break;			case MINOR_LED:				driver_ops->writeErrorLed(port_status);				break;			default:				ret=-EINVAL;				goto out;		}		data++;		*ppos = *ppos+1;	}	ret = count;out:	up(&gpio_sema);	return ret;}static ssize_t net4xxx_gpio_read(struct file *file, char *buf,                                size_t count, loff_t *ppos){	unsigned m = MINOR(file->f_dentry->d_inode->i_rdev);	unsigned long value=0;	size_t bytes_read=0;	ssize_t ret = 0;	char port_status;	if (count == 0)		return bytes_read;	if (ppos != &file->f_pos)		return -ESPIPE;	if (down_interruptible(&gpio_sema))		return -ERESTARTSYS;	switch(m) {		case MINOR_BYTE:			value = driver_ops->read8Bit();			port_status = (char)(value & 0xFF);			if (copy_to_user(buf, &port_status, sizeof(char))) {				ret = -EFAULT;				goto out;			}			bytes_read++;			buf++;			*ppos = *ppos+1;			ret = bytes_read;			break;		case MINOR_FULL:			value = driver_ops->read16Bit();			port_status = (char)(value & 0xFF);			if (copy_to_user(buf, &port_status, sizeof(char))) {				ret = -EFAULT;				goto out;			}			bytes_read++;			buf++;			*ppos = *ppos+1;			if (count>1) {				port_status = (char)((value>>8) & 0xF);				if (copy_to_user(buf, &port_status, sizeof(char))) {					ret = -EFAULT;					goto out;				}				bytes_read++;				buf++;				*ppos = *ppos+1;			}			ret = bytes_read;			break;		case MINOR_LED:			port_status = driver_ops->readErrorLed();			if (copy_to_user(buf, &port_status, sizeof(char))) {				ret = -EFAULT;				goto out;			}			bytes_read++;			buf++;			*ppos = *ppos+1;			ret = bytes_read;			break;		default:			ret = -EFAULT;			goto out;	}out:	up(&gpio_sema);	return ret;}static int net4xxx_gpio_open(struct inode *inode, struct file *file){	unsigned m = MINOR(inode->i_rdev);	if (m!=MINOR_BYTE && m!=MINOR_FULL && m!=MINOR_LED )		return -EINVAL;	return 0;}static int net4xxx_gpio_release(struct inode *inode, struct file *file){	return 0;}//------------------------------------------------// PROC filestatic int procfile_gpio_read( char *buffer,                               __attribute__ ((unused)) char **start,                               off_t offset,                               int buffer_length,                               int *eof,                               __attribute__ ((unused)) void *data){	int len; /* The number of bytes actually used */	unsigned int port_status=0;	/* We give all of our information in one go, so if the	 * user asks us if we have more information the	 * answer should always be no.	 *	 * This is important because the standard read	 * function from the library would continue to issue	 * the read system call until the kernel replies	 * that it has no more information, or until its	 * buffer is filled.	 */	if (offset > 0 || buffer_length<__number_of_pins+2) {		return 0;	}	len = buffer_length;	if (len > __number_of_pins+1) {		len = __number_of_pins+1;	}	if (down_interruptible(&gpio_sema))		return -ERESTARTSYS;	/* Get the status of the gpio ports */	if (driver_ops->read16Bit == NULL) {		port_status = driver_ops->read8Bit();	} else {		port_status = driver_ops->read16Bit();	}	len = toString(port_status,buffer,__number_of_pins);	//*start = buffer;	*eof = 1;	/* Return the length */	up(&gpio_sema);	return len;}static int procfile_gpio_write(		__attribute__ ((unused)) struct file *file,		const char *buf,		unsigned long count,		__attribute__ ((unused)) void *data){	int len;	char new_gpio_state[MAX_NUMBER_OF_PINS+1];	unsigned int  gpio_state;	if (count==0) return 0;	if(count > __number_of_pins) {		len = __number_of_pins;	} else {		len = count;	}	if (down_interruptible(&gpio_sema))		return -ERESTARTSYS;	if(copy_from_user(new_gpio_state, buf, len)) {		up(&gpio_sema);		return -EFAULT;	}	gpio_state = fromString(new_gpio_state,__number_of_pins);	if (driver_ops->write16Bit==NULL) {		driver_ops->write8Bit(gpio_state);	} else {		driver_ops->write16Bit(gpio_state);	}	up(&gpio_sema);	return len;}static int procfile_settings_read(                               char *buffer,                               char **start,                               off_t offset,                               int buffer_length,                               int *eof,                               __attribute__ ((unused)) void *data){	int len; /* The number of bytes actually used */	unsigned int port_status=0;	if (offset > 0 || buffer_length<__number_of_pins+2)		return 0;	if (down_interruptible(&gpio_sema))		return -ERESTARTSYS;	if (driver_ops->set16BitDirection == NULL) {		port_status = driver_ops->get8BitDirection();	} else {		port_status = driver_ops->get16BitDirection();	}	len = toString(port_status,buffer,__number_of_pins);	// *start = buffer;	*eof=1;	up(&gpio_sema);	return len;}static int procfile_settings_write(                               __attribute__ ((unused)) struct file *file,                               const char *buf,                               unsigned long count,                               __attribute__ ((unused)) void *data){	int len;	int p1,p2;	char ch;	char new_gpio_state[MAX_NUMBER_OF_PINS+1];	unsigned int  gpio_state;	if (count==0) return 0;	if (down_interruptible(&gpio_sema))		return -ERESTARTSYS;	if(count > __number_of_pins) {		len = __number_of_pins;	} else {	len = count;	}	if(copy_from_user(new_gpio_state, buf, len)) {		up(&gpio_sema);		return -EFAULT;	}	/* make sure our string only contains 1 and 0 */	p1=0;	p2=0;	while (p2<=len) {		ch=new_gpio_state[p2];		if (ch == '0' || ch == '1' || ch == '\0') {			new_gpio_state[p1] = ch;			p1++;		}		if (ch==0) break;			p2++;	}	new_gpio_state[p1] = 0;	if (strlen(new_gpio_state)>0) {		gpio_state = fromString(new_gpio_state,__number_of_pins);		if (driver_ops->set16BitDirection==NULL) {			driver_ops->set8BitDirection(gpio_state);		} else {			driver_ops->set16BitDirection(gpio_state);		}	}	up(&gpio_sema);	return len;}static int procfile_led_read(					char *buffer,					__attribute__ ((unused)) char **start,					off_t offset,					int len,					int *eof,					__attribute__ ((unused)) void *data){	unsigned int error_led_status;	if (offset > 0 || len<3) {		return 0;	}	if (down_interruptible(&gpio_sema))

⌨️ 快捷键说明

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