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

📄 writing-clients

📁 优龙Intel Xscale PXA270 开发平台 LINUX源码, 包括 平台用户手册, PDF原理图, kernel, driver代码. 非常有参考价值.
💻
📖 第 1 页 / 共 3 页
字号:
    /* SENSORS ONLY START */    if i2c_is_isa_client(client)      release_region(client->addr,LM78_EXTENT);    /* SENSORS ONLY END */    kfree(client); /* Frees client data too, if allocated at the same time */    return 0;  }Initializing the module or kernel=================================When the kernel is booted, or when your foo driver module is inserted, you have to do some initializing. Fortunately, just attaching (registering)the driver module is usually enough.  /* Keep track of how far we got in the initialization process. If several     things have to initialized, and we fail halfway, only those things     have to be cleaned up! */  static int __initdata foo_initialized = 0;  int __init foo_init(void)  {    int res;    printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);        if ((res = i2c_add_driver(&foo_driver))) {      printk("foo: Driver registration failed, module not inserted.\n");      foo_cleanup();      return res;    }    foo_initialized ++;    return 0;  }  int __init foo_cleanup(void)  {    int res;    if (foo_initialized == 1) {      if ((res = i2c_del_driver(&foo_driver))) {        printk("foo: Driver registration failed, module not removed.\n");        return res;      }      foo_initialized --;    }    return 0;  }  #ifdef MODULE  /* Substitute your own name and email address */  MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"  MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");  int init_module(void)  {    return foo_init();  }  int cleanup_module(void)  {    return foo_cleanup();  }  #endif /* def MODULE */Note that some functions are marked by `__init', and some data structuresby `__init_data'. If this driver is compiled as part of the kernel (insteadof as a module), those functions and structures can be removed afterkernel booting is completed.Command function================A generic ioctl-like function call back is supported. You will seldomneed this. You may even set it to NULL.  /* No commands defined */  int foo_command(struct i2c_client *client, unsigned int cmd, void *arg)  {    return 0;  }Sending and receiving=====================If you want to communicate with your device, there are several functionsto do this. You can find all of them in i2c.h.If you can choose between plain i2c communication and SMBus levelcommunication, please use the last. All adapters understand SMBus levelcommands, but only some of them understand plain i2c!Plain i2c communication-----------------------  extern int i2c_master_send(struct i2c_client *,const char* ,int);  extern int i2c_master_recv(struct i2c_client *,char* ,int);These routines read and write some bytes from/to a client. The clientcontains the i2c address, so you do not have to include it. The secondparameter contains the bytes the read/write, the third the length of thebuffer. Returned is the actual number of bytes read/written.    extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],                          int num);This sends a series of messages. Each message can be a read or write,and they can be mixed in any way. The transactions are combined: nostop bit is sent between transaction. The i2c_msg structure containsfor each message the client address, the number of bytes of the messageand the message data itself.You can read the file `i2c-protocol' for more information about theactual i2c protocol.SMBus communication-------------------  extern 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);  This is the generic SMBus function. All functions below are implemented  in terms of it. Never use this function directly!  extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);  extern s32 i2c_smbus_read_byte(struct i2c_client * client);  extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);  extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);  extern s32 i2c_smbus_write_byte_data(struct i2c_client * client,                                       u8 command, u8 value);  extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);  extern s32 i2c_smbus_write_word_data(struct i2c_client * client,                                       u8 command, u16 value);  extern s32 i2c_smbus_process_call(struct i2c_client * client,                                    u8 command, u16 value);  extern s32 i2c_smbus_read_block_data(struct i2c_client * client,                                       u8 command, u8 *values);  extern s32 i2c_smbus_write_block_data(struct i2c_client * client,                                        u8 command, u8 length,                                        u8 *values);All these transactions return -1 on failure. The 'write' transactions return 0 on success; the 'read' transactions return the read value, except for read_block, which returns the number of values read. The block buffers need not be longer than 32 bytes.You can read the file `smbus-protocol' for more information about theactual SMBus protocol.General purpose routines========================Below all general purpose routines are listed, that were not mentionedbefore.  /* This call returns a unique low identifier for each registered adapter,   * or -1 if the adapter was not registered.   */  extern int i2c_adapter_id(struct i2c_adapter *adap);The sensors sysctl/proc interface=================================This section only applies if you write `sensors' drivers.Each sensors driver creates a directory in /proc/sys/dev/sensors for eachregistered client. The directory is called something like foo-i2c-4-65.The sensors module helps you to do this as easily as possible.The template------------You will need to define a ctl_table template. This template will automaticallybe copied to a newly allocated structure and filled in where necessary whenyou call sensors_register_entry.First, I will give an example definition.  static ctl_table foo_dir_table_template[] = {    { FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real,      &i2c_sysctl_real,NULL,&foo_func },    { FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &i2c_proc_real,      &i2c_sysctl_real,NULL,&foo_func },    { FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &i2c_proc_real,      &i2c_sysctl_real,NULL,&foo_data },    { 0 }  };In the above example, three entries are defined. They can either beaccessed through the /proc interface, in the /proc/sys/dev/sensors/*directories, as files named func1, func2 and data, or alternatively through the sysctl interface, in the appropriate table, with identifiersFOO_SYSCTL_FUNC1, FOO_SYSCTL_FUNC2 and FOO_SYSCTL_DATA.The third, sixth and ninth parameters should always be NULL, and thefourth should always be 0. The fifth is the mode of the /proc file;0644 is safe, as the file will be owned by root:root. The seventh and eighth parameters should be &i2c_proc_real and&i2c_sysctl_real if you want to export lists of reals (scaledintegers). You can also use your own function for them, as usual.Finally, the last parameter is the call-back to gather the data(see below) if you use the *_proc_real functions. Gathering the data------------------The call back functions (foo_func and foo_data in the above example)can be called in several ways; the operation parameter determineswhat should be done:  * If operation == SENSORS_PROC_REAL_INFO, you must return the    magnitude (scaling) in nrels_mag;  * If operation == SENSORS_PROC_REAL_READ, you must read information    from the chip and return it in results. The number of integers    to display should be put in nrels_mag;  * If operation == SENSORS_PROC_REAL_WRITE, you must write the    supplied information to the chip. nrels_mag will contain the number    of integers, results the integers themselves.The *_proc_real functions will display the elements as reals for the/proc interface. If you set the magnitude to 2, and supply 345 forSENSORS_PROC_REAL_READ, it would display 3.45; and if the user wouldwrite 45.6 to the /proc file, it would be returned as 4560 forSENSORS_PROC_REAL_WRITE. A magnitude may even be negative!An example function:  /* FOO_FROM_REG and FOO_TO_REG translate between scaled values and     register values. Note the use of the read cache. */  void foo_in(struct i2c_client *client, int operation, int ctl_name,               int *nrels_mag, long *results)  {    struct foo_data *data = client->data;    int nr = ctl_name - FOO_SYSCTL_FUNC1; /* reduce to 0 upwards */        if (operation == SENSORS_PROC_REAL_INFO)      *nrels_mag = 2;    else if (operation == SENSORS_PROC_REAL_READ) {      /* Update the readings cache (if necessary) */      foo_update_client(client);      /* Get the readings from the cache */      results[0] = FOO_FROM_REG(data->foo_func_base[nr]);      results[1] = FOO_FROM_REG(data->foo_func_more[nr]);      results[2] = FOO_FROM_REG(data->foo_func_readonly[nr]);      *nrels_mag = 2;    } else if (operation == SENSORS_PROC_REAL_WRITE) {      if (*nrels_mag >= 1) {        /* Update the cache */        data->foo_base[nr] = FOO_TO_REG(results[0]);        /* Update the chip */        foo_write_value(client,FOO_REG_FUNC_BASE(nr),data->foo_base[nr]);      }      if (*nrels_mag >= 2) {        /* Update the cache */        data->foo_more[nr] = FOO_TO_REG(results[1]);        /* Update the chip */        foo_write_value(client,FOO_REG_FUNC_MORE(nr),data->foo_more[nr]);      }    }  }

⌨️ 快捷键说明

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