📄 i2c-proc.c
字号:
/* nrels contains initially the maximum number of elements which can be put in results, and finally the number of elements actually put there. A magnitude of 1 will multiply everything with 10; etc. buffer, bufsize is the character buffer we read from and its length. results will finally contain the parsed integers. Buffer should contain several reals, separated by whitespace. A real has the following syntax: [ Minus ] Digit* [ Dot Digit* ] (everything between [] is optional; * means zero or more). When the next character is unparsable, everything is skipped until the next whitespace. WARNING! This is tricky code. I have tested it, but there may still be hidden bugs in it, even leading to crashes and things!*/int i2c_parse_reals(int *nrels, void *buffer, int bufsize, long *results, int magnitude){ int maxels, min, mag; long res,ret=0; char nextchar = 0; maxels = *nrels; *nrels = 0; while (bufsize && (*nrels < maxels)) { /* Skip spaces at the start */ while (bufsize && !((ret=get_user(nextchar, (char *) buffer))) && isspace((int) nextchar)) { bufsize--; ((char *) buffer)++; } if (ret) return -EFAULT; /* Well, we may be done now */ if (!bufsize) return 0; /* New defaults for our result */ min = 0; res = 0; mag = magnitude; /* Check for a minus */ if (!((ret=get_user(nextchar, (char *) buffer))) && (nextchar == '-')) { min = 1; bufsize--; ((char *) buffer)++; } if (ret) return -EFAULT; /* Digits before a decimal dot */ while (bufsize && !((ret=get_user(nextchar, (char *) buffer))) && isdigit((int) nextchar)) { res = res * 10 + nextchar - '0'; bufsize--; ((char *) buffer)++; } if (ret) return -EFAULT; /* If mag < 0, we must actually divide here! */ while (mag < 0) { res = res / 10; mag++; } if (bufsize && (nextchar == '.')) { /* Skip the dot */ bufsize--; ((char *) buffer)++; /* Read digits while they are significant */ while (bufsize && (mag > 0) && !((ret=get_user(nextchar, (char *) buffer))) && isdigit((int) nextchar)) { res = res * 10 + nextchar - '0'; mag--; bufsize--; ((char *) buffer)++; } if (ret) return -EFAULT; } /* If we are out of data, but mag > 0, we need to scale here */ while (mag > 0) { res = res * 10; mag--; } /* Skip everything until we hit whitespace */ while (bufsize && !((ret=get_user(nextchar, (char *) buffer))) && isspace((int) nextchar)) { bufsize--; ((char *) buffer)++; } if (ret) return -EFAULT; /* Put res in results */ results[*nrels] = (min ? -1 : 1) * res; (*nrels)++; } /* Well, there may be more in the buffer, but we need no more data. Ignore anything that is left. */ return 0;}int i2c_write_reals(int nrels, void *buffer, int *bufsize, long *results, int magnitude){#define BUFLEN 20 char BUF[BUFLEN + 1]; /* An individual representation should fit! */ char printfstr[10]; int nr = 0; int buflen, mag, times; int curbufsize = 0; while ((nr < nrels) && (curbufsize < *bufsize)) { mag = magnitude; if (nr != 0) { if(put_user(' ', (char *) buffer)) return -EFAULT; curbufsize++; ((char *) buffer)++; } /* Fill BUF with the representation of the next string */ if (mag <= 0) { buflen = sprintf(BUF, "%ld", results[nr]); if (buflen < 0) { /* Oops, a sprintf error! */ *bufsize = 0; return -EINVAL; } while ((mag < 0) && (buflen < BUFLEN)) { BUF[buflen++] = '0'; mag++; } BUF[buflen] = 0; } else { times = 1; for (times = 1; mag-- > 0; times *= 10); if (results[nr] < 0) { BUF[0] = '-'; buflen = 1; } else buflen = 0; strcpy(printfstr, "%ld.%0Xld"); printfstr[6] = magnitude + '0'; buflen += sprintf(BUF + buflen, printfstr, abs(results[nr]) / times, abs(results[nr]) % times); if (buflen < 0) { /* Oops, a sprintf error! */ *bufsize = 0; return -EINVAL; } } /* Now copy it to the user-space buffer */ if (buflen + curbufsize > *bufsize) buflen = *bufsize - curbufsize; if(copy_to_user(buffer, BUF, buflen)) return -EFAULT; curbufsize += buflen; (char *) buffer += buflen; nr++; } if (curbufsize < *bufsize) { if(put_user('\n', (char *) buffer)) return -EFAULT; curbufsize++; } *bufsize = curbufsize; return 0;}/* Very inefficient for ISA detects, and won't work for 10-bit addresses! */int i2c_detect(struct i2c_adapter *adapter, struct i2c_address_data *address_data, i2c_found_addr_proc * found_proc){ int addr, i, found, j, err; struct i2c_force_data *this_force; int is_isa = i2c_is_isa_adapter(adapter); int adapter_id = is_isa ? SENSORS_ISA_BUS : i2c_adapter_id(adapter); /* Forget it if we can't probe using SMBUS_QUICK */ if ((!is_isa) && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) return -1; for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) { if ((is_isa && check_region(addr, 1)) || (!is_isa && 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 && (this_force = address_data->forces + i, this_force->force); i++) { for (j = 0; !found && (this_force->force[j] != SENSORS_I2C_END); j += 2) { if ( ((adapter_id == this_force->force[j]) || ((this_force-> force[j] == SENSORS_ANY_I2C_BUS) && !is_isa)) && (addr == this_force->force[j + 1])) {#ifdef DEBUG printk ("i2c-proc.o: found force parameter for adapter %d, addr %04x\n", adapter_id, addr);#endif if ( (err = found_proc(adapter, addr, 0, this_force-> kind))) 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] != SENSORS_I2C_END); i += 2) { if ( ((adapter_id == address_data->ignore[i]) || ((address_data-> ignore[i] == SENSORS_ANY_I2C_BUS) && !is_isa)) && (addr == address_data->ignore[i + 1])) {#ifdef DEBUG printk ("i2c-proc.o: found ignore parameter for adapter %d, " "addr %04x\n", adapter_id, addr);#endif found = 1; } } for (i = 0; !found && (address_data->ignore_range[i] != SENSORS_I2C_END); i += 3) { if ( ((adapter_id == address_data->ignore_range[i]) || ((address_data-> ignore_range[i] == SENSORS_ANY_I2C_BUS) & !is_isa)) && (addr >= address_data->ignore_range[i + 1]) && (addr <= address_data->ignore_range[i + 2])) {#ifdef DEBUG printk ("i2c-proc.o: found ignore_range parameter for adapter %d, " "addr %04x\n", adapter_id, addr);#endif found = 1; } } if (found) continue; /* Now, we will do a detection, but only if it is in the normal or probe entries */ if (is_isa) { for (i = 0; !found && (address_data->normal_isa[i] != SENSORS_ISA_END); i += 1) { if (addr == address_data->normal_isa[i]) {#ifdef DEBUG printk ("i2c-proc.o: found normal isa entry for adapter %d, " "addr %04x\n", adapter_id, addr);#endif found = 1; } } for (i = 0; !found && (address_data->normal_isa_range[i] != SENSORS_ISA_END); i += 3) { if ((addr >= address_data->normal_isa_range[i]) && (addr <= address_data->normal_isa_range[i + 1]) && ((addr - address_data->normal_isa_range[i]) % address_data->normal_isa_range[i + 2] == 0)) {#ifdef DEBUG printk ("i2c-proc.o: found normal isa_range entry for adapter %d, " "addr %04x", adapter_id, addr);#endif found = 1; } } } else { for (i = 0; !found && (address_data->normal_i2c[i] != SENSORS_I2C_END); i += 1) { if (addr == address_data->normal_i2c[i]) { found = 1;#ifdef DEBUG printk ("i2c-proc.o: found normal i2c entry for adapter %d, " "addr %02x", adapter_id, addr);#endif } } for (i = 0; !found && (address_data->normal_i2c_range[i] != SENSORS_I2C_END); i += 2) { if ((addr >= address_data->normal_i2c_range[i]) && (addr <= address_data->normal_i2c_range[i + 1])) {#ifdef DEBUG printk ("i2c-proc.o: found normal i2c_range entry for adapter %d, " "addr %04x\n", adapter_id, addr);#endif found = 1; } } } for (i = 0; !found && (address_data->probe[i] != SENSORS_I2C_END); i += 2) { if (((adapter_id == address_data->probe[i]) || ((address_data-> probe[i] == SENSORS_ANY_I2C_BUS) & !is_isa)) && (addr == address_data->probe[i + 1])) {#ifdef DEBUG printk ("i2c-proc.o: found probe parameter for adapter %d, " "addr %04x\n", adapter_id, addr);#endif found = 1; } } for (i = 0; !found && (address_data->probe_range[i] != SENSORS_I2C_END); i += 3) { if ( ((adapter_id == address_data->probe_range[i]) || ((address_data->probe_range[i] == SENSORS_ANY_I2C_BUS) & !is_isa)) && (addr >= address_data->probe_range[i + 1]) && (addr <= address_data->probe_range[i + 2])) { found = 1;#ifdef DEBUG printk ("i2c-proc.o: found probe_range parameter for adapter %d, " "addr %04x\n", adapter_id, addr);#endif } } if (!found) continue; /* OK, so we really should examine this address. First check whether there is some client here at all! */ if (is_isa || (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;}int __init sensors_init(void){ printk("i2c-proc.o version %s (%s)\n", LM_VERSION, LM_DATE); i2c_initialized = 0; if (! (i2c_proc_header = register_sysctl_table(i2c_proc, 0))) return -ENOMEM;#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)) i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE;#else i2c_proc_header->ctl_table->child->de->fill_inode = &i2c_fill_inode;#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,1)) */ i2c_initialized++; return 0;}EXPORT_SYMBOL(i2c_deregister_entry);EXPORT_SYMBOL(i2c_detect);EXPORT_SYMBOL(i2c_proc_real);EXPORT_SYMBOL(i2c_register_entry);EXPORT_SYMBOL(i2c_sysctl_real);#ifdef MODULEMODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");MODULE_DESCRIPTION("i2c-proc driver");MODULE_LICENSE("GPL");int i2c_cleanup(void){ if (i2c_initialized >= 1) { unregister_sysctl_table(i2c_proc_header); i2c_initialized--; } return 0;}int init_module(void){ return sensors_init();}int cleanup_module(void){ return i2c_cleanup();}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -