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

📄 writing-clients

📁 linux 内核源代码
💻
📖 第 1 页 / 共 2 页
字号:
so you do not have to define it yourself.The i2c_probe function will call the foo_detect_clientfunction only for those i2c addresses that actually have a device onthem (unless a `force' parameter was used). In addition, addresses thatare already in use (by some other registered client) are skipped.The detect client function (Legacy model)-----------------------------------------The detect client function is called by i2c_probe. The `kind' parametercontains -1 for a probed detection, 0 for a forced detection, or a positivenumber for a forced detection with a chip type forced.Returning an error different from -ENODEV in a detect function will causethe detection to stop: other addresses and adapters won't be scanned.This should only be done on fatal or internal errors, such as a memoryshortage or i2c_attach_client failing.For now, you can ignore the `flags' parameter. It is there for future use.  int foo_detect_client(struct i2c_adapter *adapter, int address,                         int kind)  {    int err = 0;    int i;    struct i2c_client *client;    struct foo_data *data;    const char *name = "";       /* Let's see whether this adapter can support what we need.       Please substitute the things you need here! */    if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |                                        I2C_FUNC_SMBUS_WRITE_BYTE))       goto ERROR0;    /* OK. For now, we presume we have a valid client. We now create the       client structure, even though we cannot fill it completely yet.       But it allows us to access several i2c functions safely */        if (!(data = kzalloc(sizeof(struct foo_data), GFP_KERNEL))) {      err = -ENOMEM;      goto ERROR0;    }    client = &data->client;    i2c_set_clientdata(client, data);    client->addr = address;    client->adapter = adapter;    client->driver = &foo_driver;    /* Now, we do the remaining detection. If no `force' parameter is used. */    /* First, the generic detection (if any), that is skipped if any force       parameter was used. */    if (kind < 0) {      /* The below is of course bogus */      if (foo_read(client, FOO_REG_GENERIC) != FOO_GENERIC_VALUE)         goto ERROR1;    }    /* Next, specific detection. This is especially important for `sensors'       devices. */    /* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter       was used. */    if (kind <= 0) {      i = foo_read(client, FOO_REG_CHIPTYPE);      if (i == FOO_TYPE_1)         kind = chip1; /* As defined in the enum */      else if (i == FOO_TYPE_2)        kind = chip2;      else {        printk("foo: Ignoring 'force' parameter for unknown chip at "               "adapter %d, address 0x%02x\n",i2c_adapter_id(adapter),address);        goto ERROR1;      }    }    /* Now set the type and chip names */    if (kind == chip1) {      name = "chip1";    } else if (kind == chip2) {      name = "chip2";    }       /* Fill in the remaining client fields. */    strlcpy(client->name, name, I2C_NAME_SIZE);    data->type = kind;    mutex_init(&data->update_lock); /* Only if you use this field */    /* Any other initializations in data must be done here too. */    /* This function can write default values to the client registers, if       needed. */    foo_init_client(client);    /* Tell the i2c layer a new client has arrived */    if ((err = i2c_attach_client(client)))      goto ERROR1;    return 0;    /* OK, this is not exactly good programming practice, usually. But it is       very code-efficient in this case. */    ERROR1:      kfree(data);    ERROR0:      return err;  }Removing the client (Legacy model)==================================The detach_client call back function is called when a client should beremoved. It may actually fail, but only when panicking. This code ismuch simpler than the attachment code, fortunately!  int foo_detach_client(struct i2c_client *client)  {    int err;    /* Try to detach the client from i2c space */    if ((err = i2c_detach_client(client)))      return err;    kfree(i2c_get_clientdata(client));    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.  static int __init foo_init(void)  {    int res;        if ((res = i2c_add_driver(&foo_driver))) {      printk("foo: Driver registration failed, module not inserted.\n");      return res;    }    return 0;  }  static void __exit foo_cleanup(void)  {    i2c_del_driver(&foo_driver);  }  /* Substitute your own name and email address */  MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"  MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");  /* a few non-GPL license types are also allowed */  MODULE_LICENSE("GPL");  module_init(foo_init);  module_exit(foo_cleanup);Note that some functions are marked by `__init', and some data structuresby `__initdata'.  These functions and structures can be removed afterkernel booting (or module loading) is completed.Power Management================If your I2C device needs special handling when entering a system lowpower state -- like putting a transceiver into a low power mode, oractivating a system wakeup mechanism -- do that in the suspend() method.The resume() method should reverse what the suspend() method does.These are standard driver model calls, and they work just like theywould for any other driver stack.  The calls can sleep, and can useI2C messaging to the device being suspended or resumed (since theirparent I2C adapter is active when these calls are issued, and IRQsare still enabled).System Shutdown===============If your I2C device needs special handling when the system shuts downor reboots (including kexec) -- like turning something off -- use ashutdown() method.Again, this is a standard driver model call, working just like itwould for any other driver stack:  the calls can sleep, and can useI2C messaging.Command function================A generic ioctl-like function call back is supported. You will seldomneed this, and its use is deprecated anyway, so newer design should notuse it. Set it to NULL.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_write_block_data(struct i2c_client * client,                                        u8 command, u8 length,                                        u8 *values);  extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,                                           u8 command, u8 length, u8 *values);These ones were removed in Linux 2.6.10 because they had no users, but couldbe added back later if needed:  extern s32 i2c_smbus_read_block_data(struct i2c_client * client,                                       u8 command, u8 *values);  extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,                                            u8 command, u8 length,                                            u8 *values);  extern s32 i2c_smbus_process_call(struct i2c_client * client,                                    u8 command, u16 value);  extern s32 i2c_smbus_block_process_call(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.   */  extern int i2c_adapter_id(struct i2c_adapter *adap);

⌨️ 快捷键说明

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