?? i2c-core.c
字號:
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; }}//for iic slave receive//by threewaterint i2c_slave_recv(struct i2c_client *client, unsigned short *buf ,int maxcount){ struct i2c_adapter *adap=client->adapter; int ret; if (client->adapter->algo->slave_recv) { DEB2(printk("i2c-core.o: slave_recv: reading %d maxbytes on %s.\n", maxcount,client->adapter->name)); I2C_LOCK(adap); ret = adap->algo->slave_recv(adap,buf,maxcount); I2C_UNLOCK(adap); DEB2(printk("i2c-core.o: slave_recv: return:%d (count:%d)\n", ret, maxcount)); /* if everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code. */ return 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; //add by threewater case I2C_SET_OWNADDR: if(!adap->algo->set_ownaddress) return -EINVAL; adap->algo->set_ownaddress(adap, arg); break; case I2C_GET_OWNADDR: { unsigned long ownaddress=adap->algo->get_ownaddress(adap); if(!adap->algo->get_ownaddress) return -EINVAL; if (copy_to_user( (unsigned long*)arg, &(ownaddress), sizeof(ownaddress)) ) return -EFAULT; return 0; } 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!
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -