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

📄 i2c-core.c

📁 I2C总线LINUX驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
{	if (client->flags & I2C_CLIENT_ALLOW_USE) {		if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)			client->usage_count++;		else if (client->usage_count > 0) 			return -EBUSY;		else 			client->usage_count++;	}	i2c_inc_use_client(client);	return 0;}int i2c_release_client(struct i2c_client *client){	if(client->flags & I2C_CLIENT_ALLOW_USE) {		if(client->usage_count>0)			client->usage_count--;		else		{			printk(KERN_WARNING " i2c-core.o: dec_use_client used one too many times\n");			return -EPERM;		}	}		i2c_dec_use_client(client);		return 0;}/* ---------------------------------------------------- * The /proc functions * ---------------------------------------------------- */#ifdef CONFIG_PROC_FS/* This function generates the output for /proc/bus/i2c */static int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,                  void *private){	int i;	int nr = 0;	/* Note that it is safe to write a `little' beyond len. Yes, really. */	down(&core_lists);	for (i = 0; (i < I2C_ADAP_MAX) && (nr < len); i++)		if (adapters[i]) {			nr += sprintf(buf+nr, "i2c-%d\t", i);			if (adapters[i]->algo->smbus_xfer) {				if (adapters[i]->algo->master_xfer)					nr += sprintf(buf+nr,"smbus/i2c");				else					nr += sprintf(buf+nr,"smbus    ");			} else if (adapters[i]->algo->master_xfer)				nr += sprintf(buf+nr,"i2c       ");			else				nr += sprintf(buf+nr,"dummy     ");			nr += sprintf(buf+nr,"\t%-32s\t%-32s\n",			              adapters[i]->name,			              adapters[i]->algo->name);		}	up(&core_lists);	return nr;}/* This function generates the output for /proc/bus/i2c-? */ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,                          loff_t *ppos){	struct inode * inode = file->f_dentry->d_inode;	char *kbuf;	struct i2c_client *client;	struct i2c_adapter *adap;	int i,j,k,order_nr,len=0;	size_t len_total;	int order[I2C_CLIENT_MAX];#define OUTPUT_LENGTH_PER_LINE 70	len_total = file->f_pos + count;	if (len_total > (I2C_CLIENT_MAX * OUTPUT_LENGTH_PER_LINE) )		/* adjust to maximum file size */		len_total = (I2C_CLIENT_MAX * OUTPUT_LENGTH_PER_LINE);	down(&core_lists);	/* adap = file->private_data; ?? --km */	for (i = 0; i < I2C_ADAP_MAX; i++) {	    adap = adapters[i];	    if (adap && (adap->inode == inode->i_ino))		break;	}	if ( I2C_ADAP_MAX == i ) {	    up(&core_lists);	    return -ENOENT;	}	/* We need a bit of slack in the kernel buffer; this makes the	   sprintf safe. */	if (! (kbuf = kmalloc(len_total +			      OUTPUT_LENGTH_PER_LINE,			      GFP_KERNEL)))	    return -ENOMEM;	/* Order will hold the indexes of the clients	   sorted by address */	order_nr=0;	I2C_LOCK_LIST(adap);	for (j = 0; j < I2C_CLIENT_MAX; j++) {	    if ((client = adap->clients[j]) && 		(client->driver->id != I2C_DRIVERID_I2CDEV))  {		for(k = order_nr; 		    (k > 0) && 			adap->clients[order[k-1]]->			addr > client->addr; 		    k--)		    order[k] = order[k-1];		order[k] = j;		order_nr++;	    }	}	for (j = 0; (j < order_nr) && (len < len_total); j++) {	    client = adap->clients[order[j]];	    len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",			   client->addr,			   client->name,			   client->driver->name);	}	I2C_UNLOCK_LIST(adap);	up(&core_lists);		len = len - file->f_pos;	if (len > count)	    len = count;	if (len < 0) 	    len = 0;	if (copy_to_user (buf,kbuf+file->f_pos, len)) {	    kfree(kbuf);	    return -EFAULT;	}	file->f_pos += len;	kfree(kbuf);	return len;}static int i2cproc_register(struct i2c_adapter *adap, int bus){	char name[8];	struct proc_dir_entry *proc_entry;	sprintf(name,"i2c-%d", bus);	proc_entry = create_proc_entry(name,0,proc_bus);	if (! proc_entry) {		printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n",		       name);		return -ENOENT;	}	    	proc_entry->proc_fops = &i2cproc_operations;	proc_entry->owner = THIS_MODULE;	adap->inode = proc_entry->low_ino;	return 0;}static void i2cproc_remove(int bus){	char name[8];	sprintf(name,"i2c-%d", bus);	remove_proc_entry(name, proc_bus);}static int __init i2cproc_init(void){	struct proc_dir_entry *proc_bus_i2c;	proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);	if (!proc_bus_i2c) {		printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");		return -ENOENT; 	}	proc_bus_i2c->read_proc = &read_bus_i2c;	proc_bus_i2c->owner = THIS_MODULE;	return 0;}static void __exit i2cproc_cleanup(void){	remove_proc_entry("i2c",proc_bus);}#endif /* def CONFIG_PROC_FS *//* ---------------------------------------------------- * the functional interface to the i2c busses. * ---------------------------------------------------- */int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num){	int ret;	if (adap->algo->master_xfer) {		if (i2c_debug >= 2) { 	 		printk(KERN_DEBUG "i2c-core.o: master_xfer: %s with "			       "%d msgs\n", adap->name, num);			for (ret = 0; ret < num; ret++) {				printk(KERN_DEBUG "i2c-core.o: "				       "master_xfer[%d]: %c, "				       "addr=0x%02x, len=%d\n", ret,				       msgs[ret].flags & I2C_M_RD ? 'R' : 'W',				       msgs[ret].addr, msgs[ret].len);			}		}		down(&adap->bus);		ret = adap->algo->master_xfer(adap,msgs,num);		up(&adap->bus);		return ret;	} else {		printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",		       adap->id);		return -ENOSYS;	}}int i2c_master_send(struct i2c_client *client,const char *buf ,int count){	int ret;	struct i2c_adapter *adap=client->adapter;	struct i2c_msg msg;	if (client->adapter->algo->master_xfer) {		msg.addr   = client->addr;		msg.flags = client->flags & I2C_M_TEN;		msg.len = count;		msg.buf = (char *)buf;			DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",			count,client->adapter->name));			down(&adap->bus);		ret = adap->algo->master_xfer(adap,&msg,1);		up(&adap->bus);		/* if everything went ok (i.e. 1 msg transmitted), return #bytes		 * transmitted, else error code.		 */		return (ret == 1 )? count : ret;	} else {		printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",		       client->adapter->id);		return -ENOSYS;	}}int i2c_master_recv(struct i2c_client *client, char *buf ,int count){	struct i2c_adapter *adap=client->adapter;	struct i2c_msg msg;	int ret;	if (client->adapter->algo->master_xfer) {		msg.addr   = client->addr;		msg.flags = client->flags & I2C_M_TEN;		msg.flags |= I2C_M_RD;		msg.len = count;		msg.buf = buf;		DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",			count,client->adapter->name));			down(&adap->bus);		ret = adap->algo->master_xfer(adap,&msg,1);		up(&adap->bus);			DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n",			ret, count, client->addr));			/* if everything went ok (i.e. 1 msg transmitted), return #bytes	 	* transmitted, else error code.	 	*/		return (ret == 1 )? count : ret;	} else {		printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",		       client->adapter->id);		return -ENOSYS;	}}int i2c_control(struct i2c_client *client,	unsigned int cmd, unsigned long arg){	int ret = 0;	struct i2c_adapter *adap = client->adapter;	DEB2(printk(KERN_DEBUG "i2c-core.o: i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg));	switch ( cmd ) {		case I2C_RETRIES:			adap->retries = arg;			break;		case I2C_TIMEOUT:			adap->timeout = arg;			break;		default:			if (adap->algo->algo_control!=NULL)				ret = adap->algo->algo_control(adap,cmd,arg);	}	return ret;}/* ---------------------------------------------------- * the i2c address scanning function * Will not work for 10-bit addresses! * ---------------------------------------------------- */int i2c_probe(struct i2c_adapter *adapter,                   struct i2c_client_address_data *address_data,                   i2c_client_found_addr_proc *found_proc){	int addr,i,found,err;	int adap_id = i2c_adapter_id(adapter);	/* Forget it if we can't probe using SMBUS_QUICK */	if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))		return -1;	for (addr = 0x00; addr <= 0x7f; addr++) {		/* Skip if already in use */		if (i2c_check_addr(adapter,addr))			continue;		/* If it is in one of the force entries, we don't do any detection		   at all */		found = 0;		for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {			if (((adap_id == address_data->force[i]) || 			     (address_data->force[i] == ANY_I2C_BUS)) &&			     (addr == address_data->force[i+1])) {				DEB2(printk(KERN_DEBUG "i2c-core.o: found force parameter for adapter %d, addr %04x\n",				            adap_id,addr));				if ((err = found_proc(adapter,addr,0,0)))					return err;				found = 1;			}		}		if (found) 			continue;		/* If this address is in one of the ignores, we can forget about		   it right now */		for (i = 0;		     !found && (address_data->ignore[i] != I2C_CLIENT_END);		     i += 2) {			if (((adap_id == address_data->ignore[i]) || 			    ((address_data->ignore[i] == ANY_I2C_BUS))) &&			    (addr == address_data->ignore[i+1])) {				DEB2(printk(KERN_DEBUG "i2c-core.o: found ignore parameter for adapter %d, "				     "addr %04x\n", adap_id ,addr));				found = 1;			}		}		for (i = 0;		     !found && (address_data->ignore_range[i] != I2C_CLIENT_END);		     i += 3) {			if (((adap_id == address_data->ignore_range[i]) ||			    ((address_data->ignore_range[i]==ANY_I2C_BUS))) &&			    (addr >= address_data->ignore_range[i+1]) &&			    (addr <= address_data->ignore_range[i+2])) {				DEB2(printk(KERN_DEBUG "i2c-core.o: found ignore_range parameter for adapter %d, "				            "addr %04x\n", adap_id,addr));				found = 1;			}		}		if (found) 			continue;		/* Now, we will do a detection, but only if it is in the normal or 		   probe entries */  		for (i = 0;		     !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);		     i += 1) {			if (addr == address_data->normal_i2c[i]) {				found = 1;				DEB2(printk(KERN_DEBUG "i2c-core.o: found normal i2c entry for adapter %d, "				            "addr %02x\n", adap_id, addr));			}		}		for (i = 0;		     !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END);		     i += 2) {			if ((addr >= address_data->normal_i2c_range[i]) &&			    (addr <= address_data->normal_i2c_range[i+1])) {				found = 1;				DEB2(printk(KERN_DEBUG "i2c-core.o: found normal i2c_range entry for adapter %d, "				            "addr %04x\n", adap_id,addr));			}		}		for (i = 0;		     !found && (address_data->probe[i] != I2C_CLIENT_END);		     i += 2) {			if (((adap_id == address_data->probe[i]) ||			    ((address_data->probe[i] == ANY_I2C_BUS))) &&			    (addr == address_data->probe[i+1])) {				found = 1;				DEB2(printk(KERN_DEBUG "i2c-core.o: found probe parameter for adapter %d, "				            "addr %04x\n", adap_id,addr));			}		}		for (i = 0;		     !found && (address_data->probe_range[i] != I2C_CLIENT_END);		     i += 3) {			if (((adap_id == address_data->probe_range[i]) ||			   (address_data->probe_range[i] == ANY_I2C_BUS)) &&			   (addr >= address_data->probe_range[i+1]) &&			   (addr <= address_data->probe_range[i+2])) {				found = 1;				DEB2(printk(KERN_DEBUG "i2c-core.o: found probe_range parameter for adapter %d, "				            "addr %04x\n", adap_id,addr));			}		}		if (!found) 			continue;		/* OK, so we really should examine this address. First check		   whether there is some client here at all! */		if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)			if ((err = found_proc(adapter,addr,0,-1)))				return err;	}	return 0;}/* * return id number for a specific adapter */int i2c_adapter_id(struct i2c_adapter *adap){	int i;	for (i = 0; i < I2C_ADAP_MAX; i++)		if (adap == adapters[i])			return i;	return -1;}/* The SMBus parts */#define POLY    (0x1070U << 3) static u8crc8(u16 data){	int i;  	for(i = 0; i < 8; i++) {		if (data & 0x8000) 			data = data ^ POLY;		data = data << 1;	}	return (u8)(data >> 8);}/* Incremental CRC8 over count bytes in the array pointed to by p */static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count){	int i;	for(i = 0; i < count; i++)		crc = crc8((crc ^ p[i]) << 8);	return crc;}/* Assume a 7-bit address, which is reasonable for SMBus */static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg){	/* The address will be sent first */	u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);	pec = i2c_smbus_pec(pec, &addr, 1);	/* The data buffer follows */

⌨️ 快捷键说明

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