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

📄 writing-clients

📁 优龙Intel Xscale PXA270 开发平台 LINUX源码, 包括 平台用户手册, PDF原理图, kernel, driver代码. 非常有参考价值.
💻
📖 第 1 页 / 共 3 页
字号:
  static unsigned short normal_i2c_range[] = {0x20,0x2f,0x40,0x4f,                                              SENSORS_I2C_END};  /* Scan ISA address 0x290 */  static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};  static unsigned int normal_isa_range[] = {SENSORS_ISA_END};  /* Define chips foo and bar, as well as all module parameters and things */  SENSORS_INSMOD_2(foo,bar);If you have one chip, you use macro SENSORS_INSMOD_1(chip), if you have 2you use macro SENSORS_INSMOD_2(chip1,chip2), etc. If you do not want tobother with chip types, you can use SENSORS_INSMOD_0.A enum is automatically defined as follows:  enum chips { any_chip, chip1, chip2, ... }Attaching to an adapter-----------------------Whenever a new adapter is inserted, or for all adapters if the driver isbeing registered, the callback attach_adapter() is called. Now is thetime to determine what devices are present on the adapter, and to registera client for each of them.The attach_adapter callback is really easy: we just call the genericdetection function. This function will scan the bus for us, using theinformation as defined in the lists explained above. If a device isdetected at a specific address, another callback is called.  int foo_attach_adapter(struct i2c_adapter *adapter)  {    return i2c_probe(adapter,&addr_data,&foo_detect_client);  }For `sensors' drivers, use the i2c_detect function instead:    int foo_attach_adapter(struct i2c_adapter *adapter)  {     return i2c_detect(adapter,&addr_data,&foo_detect_client);  }Remember, structure `addr_data' is defined by the macros explained above,so you do not have to define it yourself.The i2c_probe or i2c_detect 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--------------------------The detect client function is called by i2c_probe or i2c_detect.The `kind' parameter contains 0 if this call is due to a `force'parameter, and -1 otherwise (for i2c_detect, it contains 0 ifthis call is due to the generic `force' parameter, and the chip typenumber if it is due to a specific `force' parameter).Below, some things are only needed if this is a `sensors' driver. Thoseparts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */markers. This function should only return an error (any value != 0) if there issome reason why no more detection should be done anymore. If thedetection just fails for this address, return 0.For now, you can ignore the `flags' parameter. It is there for future use.  /* Unique ID allocation */  static int foo_id = 0;  int foo_detect_client(struct i2c_adapter *adapter, int address,                         unsigned short flags, int kind)  {    int err = 0;    int i;    struct i2c_client *new_client;    struct foo_data *data;    const char *client_name = ""; /* For non-`sensors' drivers, put the real                                     name here! */       /* Let's see whether this adapter can support what we need.       Please substitute the things you need here!        For `sensors' drivers, add `! is_isa &&' to the if statement */    if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |                                        I2C_FUNC_SMBUS_WRITE_BYTE))       goto ERROR0;    /* SENSORS ONLY START */    const char *type_name = "";    int is_isa = i2c_is_isa_adapter(adapter);    if (is_isa) {      /* If this client can't be on the ISA bus at all, we can stop now         (call `goto ERROR0'). But for kicks, we will assume it is all         right. */      /* Discard immediately if this ISA range is already used */      if (check_region(address,FOO_EXTENT))        goto ERROR0;      /* Probe whether there is anything on this address.         Some example code is below, but you will have to adapt this         for your own driver */      if (kind < 0) /* Only if no force parameter was used */ {        /* We may need long timeouts at least for some chips. */        #define REALLY_SLOW_IO        i = inb_p(address + 1);        if (inb_p(address + 2) != i)          goto ERROR0;        if (inb_p(address + 3) != i)          goto ERROR0;        if (inb_p(address + 7) != i)          goto ERROR0;        #undef REALLY_SLOW_IO        /* Let's just hope nothing breaks here */        i = inb_p(address + 5) & 0x7f;        outb_p(~i & 0x7f,address+5);        if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {          outb_p(i,address+5);          return 0;        }      }    }    /* SENSORS ONLY END */    /* 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 */        /* Note that we reserve some space for foo_data too. If you don't       need it, remove it. We do it here to help to lessen memory       fragmentation. */    if (! (new_client = kmalloc(sizeof(struct i2c_client) +                                 sizeof(struct foo_data),                                GFP_KERNEL))) {      err = -ENOMEM;      goto ERROR0;    }    /* This is tricky, but it will set the data to the right value. */    client->data = new_client + 1;    data = (struct foo_data *) (client->data);    new_client->addr = address;    new_client->data = data;    new_client->adapter = adapter;    new_client->driver = &foo_driver;    new_client->flags = 0;    /* 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(new_client,FOO_REG_GENERIC) != FOO_GENERIC_VALUE)         goto ERROR1;    }    /* SENSORS ONLY START */    /* 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(new_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) {      type_name = "chip1"; /* For /proc entry */      client_name = "CHIP 1";    } else if (kind == chip2) {      type_name = "chip2"; /* For /proc entry */      client_name = "CHIP 2";    }       /* Reserve the ISA region */    if (is_isa)      request_region(address,FOO_EXTENT,type_name);    /* SENSORS ONLY END */    /* Fill in the remaining client fields. */    strcpy(new_client->name,client_name);    /* SENSORS ONLY BEGIN */    data->type = kind;    /* SENSORS ONLY END */    new_client->id = foo_id++; /* Automatically unique */    data->valid = 0; /* Only if you use this field */    init_MUTEX(&data->update_lock); /* Only if you use this field */    /* Any other initializations in data must be done here too. */    /* Tell the i2c layer a new client has arrived */    if ((err = i2c_attach_client(new_client)))      goto ERROR3;    /* SENSORS ONLY BEGIN */    /* Register a new directory entry with module sensors. See below for       the `template' structure. */    if ((i = i2c_register_entry(new_client, type_name,                                    foo_dir_table_template,THIS_MODULE)) < 0) {      err = i;      goto ERROR4;    }    data->sysctl_id = i;    /* SENSORS ONLY END */    /* This function can write default values to the client registers, if       needed. */    foo_init_client(new_client);    return 0;    /* OK, this is not exactly good programming practice, usually. But it is       very code-efficient in this case. */    ERROR4:      i2c_detach_client(new_client);    ERROR3:    ERROR2:    /* SENSORS ONLY START */      if (is_isa)        release_region(address,FOO_EXTENT);    /* SENSORS ONLY END */    ERROR1:      kfree(new_client);    ERROR0:      return err;  }Removing the client===================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,i;    /* SENSORS ONLY START */    /* Deregister with the `i2c-proc' module. */    i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);    /* SENSORS ONLY END */    /* Try to detach the client from i2c space */    if ((err = i2c_detach_client(client))) {      printk("foo.o: Client deregistration failed, client not detached.\n");      return err;    }

⌨️ 快捷键说明

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