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

📄 iic.c

📁 嵌入式linux的IIC驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
			if (((adap_id == address_data->force[i]) || 
			     (address_data->force[i] == ANY_I2C_BUS)) &&
			     (addr == address_data->force[i+1])) {
				DEB2(printk("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("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("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("i2c-core.o: found normal i2c entry for adapter %d, "
				            "addr %02x", 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("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("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("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 */

extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
{
	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
 	                      value,0,I2C_SMBUS_QUICK,NULL);
}

extern s32 i2c_smbus_read_byte(struct i2c_client * client)
{
	union i2c_smbus_data data;
	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                   I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
		return -1;
	else
		return 0x0FF & data.byte;
}

extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value)
{
	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                      I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL);
}

extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
{
	union i2c_smbus_data data;
	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                   I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
		return -1;
	else
		return 0x0FF & data.byte;
}

extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, u8 command,
                                     u8 value)
{
	union i2c_smbus_data data;
	data.byte = value;
	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                      I2C_SMBUS_WRITE,command,
	                      I2C_SMBUS_BYTE_DATA,&data);
}

extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command)
{
	union i2c_smbus_data data;
	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                   I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
		return -1;
	else
		return 0x0FFFF & data.word;
}

extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
                                     u8 command, u16 value)
{
	union i2c_smbus_data data;
	data.word = value;
	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                      I2C_SMBUS_WRITE,command,
	                      I2C_SMBUS_WORD_DATA,&data);
}

extern s32 i2c_smbus_process_call(struct i2c_client * client,
                                  u8 command, u16 value)
{
	union i2c_smbus_data data;
	data.word = value;
	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                   I2C_SMBUS_WRITE,command,
	                   I2C_SMBUS_PROC_CALL, &data))
		return -1;
	else
		return 0x0FFFF & data.word;
}

/* Returns the number of read bytes */
extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
                                     u8 command, u8 *values)
{
	union i2c_smbus_data data;
	int i;
	if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                   I2C_SMBUS_READ,command,
	                   I2C_SMBUS_BLOCK_DATA,&data))
		return -1;
	else {
		for (i = 1; i <= data.block[0]; i++)
			values[i-1] = data.block[i];
		return data.block[0];
	}
}

extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
                                      u8 command, u8 length, u8 *values)
{
	union i2c_smbus_data data;
	int i;
	if (length > 32)
		length = 32;
	for (i = 1; i <= length; i++)
		data.block[i] = values[i-1];
	data.block[0] = length;
	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                      I2C_SMBUS_WRITE,command,
	                      I2C_SMBUS_BLOCK_DATA,&data);
}

extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
                                          u8 command, u8 length, u8 *values)
{
	union i2c_smbus_data data;
	int i;
	if (length > 32)
		length = 32;
	for (i = 1; i <= length; i++)
		data.block[i] = values[i-1];
	data.block[0] = length;
	return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
	                      I2C_SMBUS_WRITE,command,
	                      I2C_SMBUS_I2C_BLOCK_DATA,&data);
}

/* Simulate a SMBus command using the i2c protocol 
   No checking of parameters is done!  */
static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, 
                                   unsigned short flags,
                                   char read_write, u8 command, int size, 
                                   union i2c_smbus_data * data)
{
	/* So we need to generate a series of msgs. In the case of writing, we
	  need to use only one message; when reading, we need two. We initialize
	  most things with sane defaults, to keep the code below somewhat
	  simpler. */
	unsigned char msgbuf0[34];
	unsigned char msgbuf1[34];
	int num = read_write == I2C_SMBUS_READ?2:1;
	struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, 
	                          { addr, flags | I2C_M_RD, 0, msgbuf1 }
	                        };
	int i;

	msgbuf0[0] = command;
	switch(size) {
	case I2C_SMBUS_QUICK:
		msg[0].len = 0;
		/* Special case: The read/write field is used as data */
		msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;
		num = 1;
		break;
	case I2C_SMBUS_BYTE:
		if (read_write == I2C_SMBUS_READ) {
			/* Special case: only a read! */
			msg[0].flags = I2C_M_RD | flags;
			num = 1;
		}
		break;
	case I2C_SMBUS_BYTE_DATA:
		if (read_write == I2C_SMBUS_READ)
			msg[1].len = 1;
		else {
			msg[0].len = 2;
			msgbuf0[1] = data->byte;
		}
		break;
	case I2C_SMBUS_WORD_DATA:
		if (read_write == I2C_SMBUS_READ)
			msg[1].len = 2;
		else {
			msg[0].len=3;
			msgbuf0[1] = data->word & 0xff;
			msgbuf0[2] = (data->word >> 8) & 0xff;
		}
		break;
	case I2C_SMBUS_PROC_CALL:
		num = 2; /* Special case */
		msg[0].len = 3;
		msg[1].len = 2;
		msgbuf0[1] = data->word & 0xff;
		msgbuf0[2] = (data->word >> 8) & 0xff;
		break;
	case I2C_SMBUS_BLOCK_DATA:
		if (read_write == I2C_SMBUS_READ) {
			printk("i2c-core.o: Block read not supported under "
			       "I2C emulation!\n");
		return -1;
		} else {
			msg[0].len = data->block[0] + 2;
			if (msg[0].len > 34) {
				printk("i2c-core.o: smbus_access called with "
				       "invalid block write size (%d)\n",
				       msg[0].len);
				return -1;
			}
			for (i = 1; i <= msg[0].len; i++)
				msgbuf0[i] = data->block[i-1];
		}
		break;
	default:
		printk("i2c-core.o: smbus_access called with invalid size (%d)\n",
		       size);
		return -1;
	}

	if (i2c_transfer(adapter, msg, num) < 0)
		return -1;

	if (read_write == I2C_SMBUS_READ)
		switch(size) {
			case I2C_SMBUS_BYTE:
				data->byte = msgbuf0[0];
				break;
			case I2C_SMBUS_BYTE_DATA:
				data->byte = msgbuf1[0];
				break;
			case I2C_SMBUS_WORD_DATA: 
			case I2C_SMBUS_PROC_CALL:
				data->word = msgbuf1[0] | (msgbuf1[1] << 8);
				break;
		}
	return 0;
}


s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
                   char read_write, u8 command, int size, 
                   union i2c_smbus_data * data)
{
	s32 res;
	flags = flags & I2C_M_TEN;
	if (adapter->algo->smbus_xfer) {
		I2C_LOCK(adapter);
		res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
		                                command,size,data);
		I2C_UNLOCK(adapter);
	} else
		res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
	                                      command,size,data);
	return res;
}


/* You should always define `functionality'; the 'else' is just for
   backward compatibility. */ 
u32 i2c_get_functionality (struct i2c_adapter *adap)
{
	if (adap->algo->functionality)
		return adap->algo->functionality(adap);
	else
		return 0xffffffff;
}

int i2c_check_functionality (struct i2c_adapter *adap, u32 func)
{
	u32 adap_func = i2c_get_functionality (adap);
	return (func & adap_func) == func;
}


static int __init i2c_init(void)
{
	printk(KERN_DEBUG "i2c-core.o: i2c core module\n");
	memset(adapters,0,sizeof(adapters));
	memset(drivers,0,sizeof(drivers));
	adap_count=0;
	driver_count=0;

	init_MUTEX(&adap_lock);
	init_MUTEX(&driver_lock);
	
	i2cproc_init();
	
	return 0;
}

EXPORT_SYMBOL(i2c_add_adapter);
EXPORT_SYMBOL(i2c_del_adapter);
EXPORT_SYMBOL(i2c_add_driver);
EXPORT_SYMBOL(i2c_del_driver);
EXPORT_SYMBOL(i2c_attach_client);
EXPORT_SYMBOL(i2c_detach_client);
EXPORT_SYMBOL(i2c_inc_use_client);
EXPORT_SYMBOL(i2c_dec_use_client);
EXPORT_SYMBOL(i2c_get_client);
EXPORT_SYMBOL(i2c_use_client);
EXPORT_SYMBOL(i2c_release_client);
EXPORT_SYMBOL(i2c_check_addr);


EXPORT_SYMBOL(i2c_master_send);
EXPORT_SYMBOL(i2c_master_recv);
EXPORT_SYMBOL(i2c_control);
EXPORT_SYMBOL(i2c_transfer);
EXPORT_SYMBOL(i2c_adapter_id);
EXPORT_SYMBOL(i2c_probe);

EXPORT_SYMBOL(i2c_smbus_xfer);
EXPORT_SYMBOL(i2c_smbus_write_quick);
EXPORT_SYMBOL(i2c_smbus_read_byte);
EXPORT_SYMBOL(i2c_smbus_write_byte);
EXPORT_SYMBOL(i2c_smbus_read_byte_data);
EXPORT_SYMBOL(i2c_smbus_write_byte_data);
EXPORT_SYMBOL(i2c_smbus_read_word_data);
EXPORT_SYMBOL(i2c_smbus_write_word_data);
EXPORT_SYMBOL(i2c_smbus_process_call);
EXPORT_SYMBOL(i2c_smbus_read_block_data);
EXPORT_SYMBOL(i2c_smbus_write_block_data);

EXPORT_SYMBOL(i2c_get_functionality);
EXPORT_SYMBOL(i2c_check_functionality);

MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus main module");
MODULE_PARM(i2c_debug, "i");
MODULE_PARM_DESC(i2c_debug,"debug level");
MODULE_LICENSE("GPL");

module_init(i2c_init);
module_exit(i2cproc_cleanup);

⌨️ 快捷键说明

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