📄 iic.c
字号:
if (client == adapter->clients[i])
break;
if (I2C_CLIENT_MAX == i) {
printk(KERN_WARNING " i2c-core.o: unregister_client "
"[%s] not found\n",
client->name);
return -ENODEV;
}
if( (client->flags & I2C_CLIENT_ALLOW_USE) &&
(client->usage_count>0))
return -EBUSY;
if (adapter->client_unregister != NULL)
if ((res = adapter->client_unregister(client))) {
printk("i2c-core.o: client_unregister [%s] failed, "
"client not detached",client->name);
return res;
}
adapter->clients[i] = NULL;
adapter->client_count--;
DEB(printk("i2c-core.o: client [%s] unregistered.\n",client->name));
return 0;
}
void i2c_inc_use_client(struct i2c_client *client)
{
if (client->driver->inc_use != NULL)
client->driver->inc_use(client);
if (client->adapter->inc_use != NULL)
client->adapter->inc_use(client->adapter);
}
void i2c_dec_use_client(struct i2c_client *client)
{
if (client->driver->dec_use != NULL)
client->driver->dec_use(client);
if (client->adapter->dec_use != NULL)
client->adapter->dec_use(client->adapter);
}
struct i2c_client *i2c_get_client(int driver_id, int adapter_id,
struct i2c_client *prev)
{
int i,j;
/* Will iterate through the list of clients in each adapter of adapters-list
in search for a client that matches the search criteria. driver_id or
adapter_id are ignored if set to 0. If both are ignored this returns
first client found. */
i = j = 0;
/* set starting point */
if(prev)
{
if(!(prev->adapter))
return (struct i2c_client *) -EINVAL;
for(j=0; j < I2C_ADAP_MAX; j++)
if(prev->adapter == adapters[j])
break;
/* invalid starting point? */
if (I2C_ADAP_MAX == j) {
printk(KERN_WARNING " i2c-core.o: get_client adapter for client:[%s] not found\n",
prev->name);
return (struct i2c_client *) -ENODEV;
}
for(i=0; i < I2C_CLIENT_MAX; i++)
if(prev == adapters[j]->clients[i])
break;
/* invalid starting point? */
if (I2C_CLIENT_MAX == i) {
printk(KERN_WARNING " i2c-core.o: get_client client:[%s] not found\n",
prev->name);
return (struct i2c_client *) -ENODEV;
}
i++; /* start from one after prev */
}
for(; j < I2C_ADAP_MAX; j++)
{
if(!adapters[j])
continue;
if(adapter_id && (adapters[j]->id != adapter_id))
continue;
for(; i < I2C_CLIENT_MAX; i++)
{
if(!adapters[j]->clients[i])
continue;
if(driver_id && (adapters[j]->clients[i]->driver->id != driver_id))
continue;
if(adapters[j]->clients[i]->flags & I2C_CLIENT_ALLOW_USE)
return adapters[j]->clients[i];
}
i = 0;
}
return 0;
}
int i2c_use_client(struct i2c_client *client)
{
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
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,27))
/* Monitor access to /proc/bus/i2c*; make unloading i2c-proc impossible
if some process still uses it or some file in it */
void monitor_bus_i2c(struct inode *inode, int fill)
{
if (fill)
MOD_INC_USE_COUNT;
else
MOD_DEC_USE_COUNT;
}
#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,37)) */
/* This function generates the output for /proc/bus/i2c */
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. */
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);
}
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;
int i,j,k,order_nr,len=0,len_total;
int order[I2C_CLIENT_MAX];
if (count > 4000)
return -EINVAL;
len_total = file->f_pos + count;
/* Too bad if this gets longer (unlikely) */
if (len_total > 4000)
len_total = 4000;
for (i = 0; i < I2C_ADAP_MAX; i++)
if (adapters[i]->inode == inode->i_ino) {
/* We need a bit of slack in the kernel buffer; this makes the
sprintf safe. */
if (! (kbuf = kmalloc(count + 80,GFP_KERNEL)))
return -ENOMEM;
/* Order will hold the indexes of the clients
sorted by address */
order_nr=0;
for (j = 0; j < I2C_CLIENT_MAX; j++) {
if ((client = adapters[i]->clients[j]) &&
(client->driver->id != I2C_DRIVERID_I2CDEV)) {
for(k = order_nr;
(k > 0) &&
adapters[i]->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 = adapters[i]->clients[order[j]];
len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
client->addr,
client->name,
client->driver->name);
}
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;
}
return -ENOENT;
}
int i2cproc_init(void)
{
struct proc_dir_entry *proc_bus_i2c;
i2cproc_initialized = 0;
if (! proc_bus) {
printk("i2c-core.o: /proc/bus/ does not exist");
i2cproc_cleanup();
return -ENOENT;
}
proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);
if (!proc_bus_i2c) {
printk("i2c-core.o: Could not create /proc/bus/i2c");
i2cproc_cleanup();
return -ENOENT;
}
proc_bus_i2c->read_proc = &read_bus_i2c;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27))
proc_bus_i2c->owner = THIS_MODULE;
#else
proc_bus_i2c->fill_inode = &monitor_bus_i2c;
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27)) */
i2cproc_initialized += 2;
return 0;
}
static void i2cproc_cleanup(void)
{
if (i2cproc_initialized >= 1) {
remove_proc_entry("i2c",proc_bus);
i2cproc_initialized -= 2;
}
}
#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) {
DEB2(printk("i2c-core.o: master_xfer: %s with %d msgs.\n",
adap->name,num));
I2C_LOCK(adap);
ret = adap->algo->master_xfer(adap,msgs,num);
I2C_UNLOCK(adap);
return ret;
} else {
printk("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;
(const char *)msg.buf = buf;
DEB2(printk("i2c-core.o: master_send: writing %d bytes on %s.\n",
count,client->adapter->name));
I2C_LOCK(adap);
ret = adap->algo->master_xfer(adap,&msg,1);
I2C_UNLOCK(adap);
/* if everything went ok (i.e. 1 msg transmitted), return #bytes
* transmitted, else error code.
*/
return (ret == 1 )? count : ret;
} else {
printk("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("i2c-core.o: master_recv: reading %d bytes on %s.\n",
count,client->adapter->name));
I2C_LOCK(adap);
ret = adap->algo->master_xfer(adap,&msg,1);
I2C_UNLOCK(adap);
DEB2(printk("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("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("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 += 3) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -