diff options
author | Jean Delvare <khali@linux-fr.org> | 2007-05-01 17:26:35 -0400 |
---|---|---|
committer | Jean Delvare <khali@hyperion.delvare> | 2007-05-01 17:26:35 -0400 |
commit | eefcd75e72f382270f8f64e030550b10e3882b2b (patch) | |
tree | ccd55fa7068067ddd6299fe62dc15b22cc3ca46a /Documentation/i2c/writing-clients | |
parent | 35532d20035d04b0ec28508583a56c7a65c5fa47 (diff) |
i2c: Documentation update
Make the documentation on how to write and port i2c drivers more in
line with the current state of things:
* i2c-isa is deprecated and soon gone, so stop advertising it.
* Drop many sensors-specific references. Most of them were outdated
anyway.
* Update the example code to reflect the recent and not-so-recent
API and coding style preference changes.
* Simplify the example init and cleanup functions.
This should make things less complex to understand for newcomers.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'Documentation/i2c/writing-clients')
-rw-r--r-- | Documentation/i2c/writing-clients | 292 |
1 files changed, 31 insertions, 261 deletions
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index f7e04ec849b1..3d8d36b0ad12 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients | |||
@@ -74,16 +74,13 @@ An example structure is below. | |||
74 | 74 | ||
75 | struct foo_data { | 75 | struct foo_data { |
76 | struct i2c_client client; | 76 | struct i2c_client client; |
77 | struct semaphore lock; /* For ISA access in `sensors' drivers. */ | ||
78 | int sysctl_id; /* To keep the /proc directory entry for | ||
79 | `sensors' drivers. */ | ||
80 | enum chips type; /* To keep the chips type for `sensors' drivers. */ | 77 | enum chips type; /* To keep the chips type for `sensors' drivers. */ |
81 | 78 | ||
82 | /* Because the i2c bus is slow, it is often useful to cache the read | 79 | /* Because the i2c bus is slow, it is often useful to cache the read |
83 | information of a chip for some time (for example, 1 or 2 seconds). | 80 | information of a chip for some time (for example, 1 or 2 seconds). |
84 | It depends of course on the device whether this is really worthwhile | 81 | It depends of course on the device whether this is really worthwhile |
85 | or even sensible. */ | 82 | or even sensible. */ |
86 | struct semaphore update_lock; /* When we are reading lots of information, | 83 | struct mutex update_lock; /* When we are reading lots of information, |
87 | another process should not update the | 84 | another process should not update the |
88 | below information */ | 85 | below information */ |
89 | char valid; /* != 0 if the following fields are valid. */ | 86 | char valid; /* != 0 if the following fields are valid. */ |
@@ -104,8 +101,7 @@ some obscure clients). But we need generic reading and writing routines. | |||
104 | I have found it useful to define foo_read and foo_write function for this. | 101 | I have found it useful to define foo_read and foo_write function for this. |
105 | For some cases, it will be easier to call the i2c functions directly, | 102 | For some cases, it will be easier to call the i2c functions directly, |
106 | but many chips have some kind of register-value idea that can easily | 103 | but many chips have some kind of register-value idea that can easily |
107 | be encapsulated. Also, some chips have both ISA and I2C interfaces, and | 104 | be encapsulated. |
108 | it useful to abstract from this (only for `sensors' drivers). | ||
109 | 105 | ||
110 | The below functions are simple examples, and should not be copied | 106 | The below functions are simple examples, and should not be copied |
111 | literally. | 107 | literally. |
@@ -128,24 +124,6 @@ literally. | |||
128 | return i2c_smbus_write_word_data(client,reg,value); | 124 | return i2c_smbus_write_word_data(client,reg,value); |
129 | } | 125 | } |
130 | 126 | ||
131 | For sensors code, you may have to cope with ISA registers too. Something | ||
132 | like the below often works. Note the locking! | ||
133 | |||
134 | int foo_read_value(struct i2c_client *client, u8 reg) | ||
135 | { | ||
136 | int res; | ||
137 | if (i2c_is_isa_client(client)) { | ||
138 | down(&(((struct foo_data *) (client->data)) -> lock)); | ||
139 | outb_p(reg,client->addr + FOO_ADDR_REG_OFFSET); | ||
140 | res = inb_p(client->addr + FOO_DATA_REG_OFFSET); | ||
141 | up(&(((struct foo_data *) (client->data)) -> lock)); | ||
142 | return res; | ||
143 | } else | ||
144 | return i2c_smbus_read_byte_data(client,reg); | ||
145 | } | ||
146 | |||
147 | Writing is done the same way. | ||
148 | |||
149 | 127 | ||
150 | Probing and attaching | 128 | Probing and attaching |
151 | ===================== | 129 | ===================== |
@@ -257,10 +235,6 @@ detection algorithm. | |||
257 | You do not have to use this parameter interface; but don't try to use | 235 | You do not have to use this parameter interface; but don't try to use |
258 | function i2c_probe() if you don't. | 236 | function i2c_probe() if you don't. |
259 | 237 | ||
260 | NOTE: If you want to write a `sensors' driver, the interface is slightly | ||
261 | different! See below. | ||
262 | |||
263 | |||
264 | 238 | ||
265 | Probing classes (Legacy model) | 239 | Probing classes (Legacy model) |
266 | ------------------------------ | 240 | ------------------------------ |
@@ -344,10 +318,6 @@ The detect client function is called by i2c_probe. The `kind' parameter | |||
344 | contains -1 for a probed detection, 0 for a forced detection, or a positive | 318 | contains -1 for a probed detection, 0 for a forced detection, or a positive |
345 | number for a forced detection with a chip type forced. | 319 | number for a forced detection with a chip type forced. |
346 | 320 | ||
347 | Below, some things are only needed if this is a `sensors' driver. Those | ||
348 | parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */ | ||
349 | markers. | ||
350 | |||
351 | Returning an error different from -ENODEV in a detect function will cause | 321 | Returning an error different from -ENODEV in a detect function will cause |
352 | the detection to stop: other addresses and adapters won't be scanned. | 322 | the detection to stop: other addresses and adapters won't be scanned. |
353 | This should only be done on fatal or internal errors, such as a memory | 323 | This should only be done on fatal or internal errors, such as a memory |
@@ -356,64 +326,20 @@ shortage or i2c_attach_client failing. | |||
356 | For now, you can ignore the `flags' parameter. It is there for future use. | 326 | For now, you can ignore the `flags' parameter. It is there for future use. |
357 | 327 | ||
358 | int foo_detect_client(struct i2c_adapter *adapter, int address, | 328 | int foo_detect_client(struct i2c_adapter *adapter, int address, |
359 | unsigned short flags, int kind) | 329 | int kind) |
360 | { | 330 | { |
361 | int err = 0; | 331 | int err = 0; |
362 | int i; | 332 | int i; |
363 | struct i2c_client *new_client; | 333 | struct i2c_client *client; |
364 | struct foo_data *data; | 334 | struct foo_data *data; |
365 | const char *client_name = ""; /* For non-`sensors' drivers, put the real | 335 | const char *name = ""; |
366 | name here! */ | ||
367 | 336 | ||
368 | /* Let's see whether this adapter can support what we need. | 337 | /* Let's see whether this adapter can support what we need. |
369 | Please substitute the things you need here! | 338 | Please substitute the things you need here! */ |
370 | For `sensors' drivers, add `! is_isa &&' to the if statement */ | ||
371 | if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA | | 339 | if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA | |
372 | I2C_FUNC_SMBUS_WRITE_BYTE)) | 340 | I2C_FUNC_SMBUS_WRITE_BYTE)) |
373 | goto ERROR0; | 341 | goto ERROR0; |
374 | 342 | ||
375 | /* SENSORS ONLY START */ | ||
376 | const char *type_name = ""; | ||
377 | int is_isa = i2c_is_isa_adapter(adapter); | ||
378 | |||
379 | /* Do this only if the chip can additionally be found on the ISA bus | ||
380 | (hybrid chip). */ | ||
381 | |||
382 | if (is_isa) { | ||
383 | |||
384 | /* Discard immediately if this ISA range is already used */ | ||
385 | /* FIXME: never use check_region(), only request_region() */ | ||
386 | if (check_region(address,FOO_EXTENT)) | ||
387 | goto ERROR0; | ||
388 | |||
389 | /* Probe whether there is anything on this address. | ||
390 | Some example code is below, but you will have to adapt this | ||
391 | for your own driver */ | ||
392 | |||
393 | if (kind < 0) /* Only if no force parameter was used */ { | ||
394 | /* We may need long timeouts at least for some chips. */ | ||
395 | #define REALLY_SLOW_IO | ||
396 | i = inb_p(address + 1); | ||
397 | if (inb_p(address + 2) != i) | ||
398 | goto ERROR0; | ||
399 | if (inb_p(address + 3) != i) | ||
400 | goto ERROR0; | ||
401 | if (inb_p(address + 7) != i) | ||
402 | goto ERROR0; | ||
403 | #undef REALLY_SLOW_IO | ||
404 | |||
405 | /* Let's just hope nothing breaks here */ | ||
406 | i = inb_p(address + 5) & 0x7f; | ||
407 | outb_p(~i & 0x7f,address+5); | ||
408 | if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) { | ||
409 | outb_p(i,address+5); | ||
410 | return 0; | ||
411 | } | ||
412 | } | ||
413 | } | ||
414 | |||
415 | /* SENSORS ONLY END */ | ||
416 | |||
417 | /* OK. For now, we presume we have a valid client. We now create the | 343 | /* OK. For now, we presume we have a valid client. We now create the |
418 | client structure, even though we cannot fill it completely yet. | 344 | client structure, even though we cannot fill it completely yet. |
419 | But it allows us to access several i2c functions safely */ | 345 | But it allows us to access several i2c functions safely */ |
@@ -423,13 +349,12 @@ For now, you can ignore the `flags' parameter. It is there for future use. | |||
423 | goto ERROR0; | 349 | goto ERROR0; |
424 | } | 350 | } |
425 | 351 | ||
426 | new_client = &data->client; | 352 | client = &data->client; |
427 | i2c_set_clientdata(new_client, data); | 353 | i2c_set_clientdata(client, data); |
428 | 354 | ||
429 | new_client->addr = address; | 355 | client->addr = address; |
430 | new_client->adapter = adapter; | 356 | client->adapter = adapter; |
431 | new_client->driver = &foo_driver; | 357 | client->driver = &foo_driver; |
432 | new_client->flags = 0; | ||
433 | 358 | ||
434 | /* Now, we do the remaining detection. If no `force' parameter is used. */ | 359 | /* Now, we do the remaining detection. If no `force' parameter is used. */ |
435 | 360 | ||
@@ -437,19 +362,17 @@ For now, you can ignore the `flags' parameter. It is there for future use. | |||
437 | parameter was used. */ | 362 | parameter was used. */ |
438 | if (kind < 0) { | 363 | if (kind < 0) { |
439 | /* The below is of course bogus */ | 364 | /* The below is of course bogus */ |
440 | if (foo_read(new_client,FOO_REG_GENERIC) != FOO_GENERIC_VALUE) | 365 | if (foo_read(client, FOO_REG_GENERIC) != FOO_GENERIC_VALUE) |
441 | goto ERROR1; | 366 | goto ERROR1; |
442 | } | 367 | } |
443 | 368 | ||
444 | /* SENSORS ONLY START */ | ||
445 | |||
446 | /* Next, specific detection. This is especially important for `sensors' | 369 | /* Next, specific detection. This is especially important for `sensors' |
447 | devices. */ | 370 | devices. */ |
448 | 371 | ||
449 | /* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter | 372 | /* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter |
450 | was used. */ | 373 | was used. */ |
451 | if (kind <= 0) { | 374 | if (kind <= 0) { |
452 | i = foo_read(new_client,FOO_REG_CHIPTYPE); | 375 | i = foo_read(client, FOO_REG_CHIPTYPE); |
453 | if (i == FOO_TYPE_1) | 376 | if (i == FOO_TYPE_1) |
454 | kind = chip1; /* As defined in the enum */ | 377 | kind = chip1; /* As defined in the enum */ |
455 | else if (i == FOO_TYPE_2) | 378 | else if (i == FOO_TYPE_2) |
@@ -463,63 +386,31 @@ For now, you can ignore the `flags' parameter. It is there for future use. | |||
463 | 386 | ||
464 | /* Now set the type and chip names */ | 387 | /* Now set the type and chip names */ |
465 | if (kind == chip1) { | 388 | if (kind == chip1) { |
466 | type_name = "chip1"; /* For /proc entry */ | 389 | name = "chip1"; |
467 | client_name = "CHIP 1"; | ||
468 | } else if (kind == chip2) { | 390 | } else if (kind == chip2) { |
469 | type_name = "chip2"; /* For /proc entry */ | 391 | name = "chip2"; |
470 | client_name = "CHIP 2"; | ||
471 | } | 392 | } |
472 | 393 | ||
473 | /* Reserve the ISA region */ | ||
474 | if (is_isa) | ||
475 | request_region(address,FOO_EXTENT,type_name); | ||
476 | |||
477 | /* SENSORS ONLY END */ | ||
478 | |||
479 | /* Fill in the remaining client fields. */ | 394 | /* Fill in the remaining client fields. */ |
480 | strcpy(new_client->name,client_name); | 395 | strlcpy(client->name, name, I2C_NAME_SIZE); |
481 | |||
482 | /* SENSORS ONLY BEGIN */ | ||
483 | data->type = kind; | 396 | data->type = kind; |
484 | /* SENSORS ONLY END */ | 397 | mutex_init(&data->update_lock); /* Only if you use this field */ |
485 | |||
486 | data->valid = 0; /* Only if you use this field */ | ||
487 | init_MUTEX(&data->update_lock); /* Only if you use this field */ | ||
488 | 398 | ||
489 | /* Any other initializations in data must be done here too. */ | 399 | /* Any other initializations in data must be done here too. */ |
490 | 400 | ||
491 | /* Tell the i2c layer a new client has arrived */ | ||
492 | if ((err = i2c_attach_client(new_client))) | ||
493 | goto ERROR3; | ||
494 | |||
495 | /* SENSORS ONLY BEGIN */ | ||
496 | /* Register a new directory entry with module sensors. See below for | ||
497 | the `template' structure. */ | ||
498 | if ((i = i2c_register_entry(new_client, type_name, | ||
499 | foo_dir_table_template,THIS_MODULE)) < 0) { | ||
500 | err = i; | ||
501 | goto ERROR4; | ||
502 | } | ||
503 | data->sysctl_id = i; | ||
504 | |||
505 | /* SENSORS ONLY END */ | ||
506 | |||
507 | /* This function can write default values to the client registers, if | 401 | /* This function can write default values to the client registers, if |
508 | needed. */ | 402 | needed. */ |
509 | foo_init_client(new_client); | 403 | foo_init_client(client); |
404 | |||
405 | /* Tell the i2c layer a new client has arrived */ | ||
406 | if ((err = i2c_attach_client(client))) | ||
407 | goto ERROR1; | ||
408 | |||
510 | return 0; | 409 | return 0; |
511 | 410 | ||
512 | /* OK, this is not exactly good programming practice, usually. But it is | 411 | /* OK, this is not exactly good programming practice, usually. But it is |
513 | very code-efficient in this case. */ | 412 | very code-efficient in this case. */ |
514 | 413 | ||
515 | ERROR4: | ||
516 | i2c_detach_client(new_client); | ||
517 | ERROR3: | ||
518 | ERROR2: | ||
519 | /* SENSORS ONLY START */ | ||
520 | if (is_isa) | ||
521 | release_region(address,FOO_EXTENT); | ||
522 | /* SENSORS ONLY END */ | ||
523 | ERROR1: | 414 | ERROR1: |
524 | kfree(data); | 415 | kfree(data); |
525 | ERROR0: | 416 | ERROR0: |
@@ -536,22 +427,12 @@ much simpler than the attachment code, fortunately! | |||
536 | 427 | ||
537 | int foo_detach_client(struct i2c_client *client) | 428 | int foo_detach_client(struct i2c_client *client) |
538 | { | 429 | { |
539 | int err,i; | 430 | int err; |
540 | |||
541 | /* SENSORS ONLY START */ | ||
542 | /* Deregister with the `i2c-proc' module. */ | ||
543 | i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id); | ||
544 | /* SENSORS ONLY END */ | ||
545 | 431 | ||
546 | /* Try to detach the client from i2c space */ | 432 | /* Try to detach the client from i2c space */ |
547 | if ((err = i2c_detach_client(client))) | 433 | if ((err = i2c_detach_client(client))) |
548 | return err; | 434 | return err; |
549 | 435 | ||
550 | /* HYBRID SENSORS CHIP ONLY START */ | ||
551 | if i2c_is_isa_client(client) | ||
552 | release_region(client->addr,LM78_EXTENT); | ||
553 | /* HYBRID SENSORS CHIP ONLY END */ | ||
554 | |||
555 | kfree(i2c_get_clientdata(client)); | 436 | kfree(i2c_get_clientdata(client)); |
556 | return 0; | 437 | return 0; |
557 | } | 438 | } |
@@ -564,42 +445,34 @@ When the kernel is booted, or when your foo driver module is inserted, | |||
564 | you have to do some initializing. Fortunately, just attaching (registering) | 445 | you have to do some initializing. Fortunately, just attaching (registering) |
565 | the driver module is usually enough. | 446 | the driver module is usually enough. |
566 | 447 | ||
567 | /* Keep track of how far we got in the initialization process. If several | ||
568 | things have to initialized, and we fail halfway, only those things | ||
569 | have to be cleaned up! */ | ||
570 | static int __initdata foo_initialized = 0; | ||
571 | |||
572 | static int __init foo_init(void) | 448 | static int __init foo_init(void) |
573 | { | 449 | { |
574 | int res; | 450 | int res; |
575 | printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE); | ||
576 | 451 | ||
577 | if ((res = i2c_add_driver(&foo_driver))) { | 452 | if ((res = i2c_add_driver(&foo_driver))) { |
578 | printk("foo: Driver registration failed, module not inserted.\n"); | 453 | printk("foo: Driver registration failed, module not inserted.\n"); |
579 | foo_cleanup(); | ||
580 | return res; | 454 | return res; |
581 | } | 455 | } |
582 | foo_initialized ++; | ||
583 | return 0; | 456 | return 0; |
584 | } | 457 | } |
585 | 458 | ||
586 | void foo_cleanup(void) | 459 | static void __exit foo_cleanup(void) |
587 | { | 460 | { |
588 | if (foo_initialized == 1) { | 461 | i2c_del_driver(&foo_driver); |
589 | i2c_del_driver(&foo_driver); | ||
590 | foo_initialized --; | ||
591 | } | ||
592 | } | 462 | } |
593 | 463 | ||
594 | /* Substitute your own name and email address */ | 464 | /* Substitute your own name and email address */ |
595 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>" | 465 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>" |
596 | MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices"); | 466 | MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices"); |
597 | 467 | ||
468 | /* a few non-GPL license types are also allowed */ | ||
469 | MODULE_LICENSE("GPL"); | ||
470 | |||
598 | module_init(foo_init); | 471 | module_init(foo_init); |
599 | module_exit(foo_cleanup); | 472 | module_exit(foo_cleanup); |
600 | 473 | ||
601 | Note that some functions are marked by `__init', and some data structures | 474 | Note that some functions are marked by `__init', and some data structures |
602 | by `__init_data'. Hose functions and structures can be removed after | 475 | by `__initdata'. These functions and structures can be removed after |
603 | kernel booting (or module loading) is completed. | 476 | kernel booting (or module loading) is completed. |
604 | 477 | ||
605 | 478 | ||
@@ -729,110 +602,7 @@ General purpose routines | |||
729 | Below all general purpose routines are listed, that were not mentioned | 602 | Below all general purpose routines are listed, that were not mentioned |
730 | before. | 603 | before. |
731 | 604 | ||
732 | /* This call returns a unique low identifier for each registered adapter, | 605 | /* This call returns a unique low identifier for each registered adapter. |
733 | * or -1 if the adapter was not registered. | ||
734 | */ | 606 | */ |
735 | extern int i2c_adapter_id(struct i2c_adapter *adap); | 607 | extern int i2c_adapter_id(struct i2c_adapter *adap); |
736 | 608 | ||
737 | |||
738 | The sensors sysctl/proc interface | ||
739 | ================================= | ||
740 | |||
741 | This section only applies if you write `sensors' drivers. | ||
742 | |||
743 | Each sensors driver creates a directory in /proc/sys/dev/sensors for each | ||
744 | registered client. The directory is called something like foo-i2c-4-65. | ||
745 | The sensors module helps you to do this as easily as possible. | ||
746 | |||
747 | The template | ||
748 | ------------ | ||
749 | |||
750 | You will need to define a ctl_table template. This template will automatically | ||
751 | be copied to a newly allocated structure and filled in where necessary when | ||
752 | you call sensors_register_entry. | ||
753 | |||
754 | First, I will give an example definition. | ||
755 | static ctl_table foo_dir_table_template[] = { | ||
756 | { FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real, | ||
757 | &i2c_sysctl_real,NULL,&foo_func }, | ||
758 | { FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &i2c_proc_real, | ||
759 | &i2c_sysctl_real,NULL,&foo_func }, | ||
760 | { FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &i2c_proc_real, | ||
761 | &i2c_sysctl_real,NULL,&foo_data }, | ||
762 | { 0 } | ||
763 | }; | ||
764 | |||
765 | In the above example, three entries are defined. They can either be | ||
766 | accessed through the /proc interface, in the /proc/sys/dev/sensors/* | ||
767 | directories, as files named func1, func2 and data, or alternatively | ||
768 | through the sysctl interface, in the appropriate table, with identifiers | ||
769 | FOO_SYSCTL_FUNC1, FOO_SYSCTL_FUNC2 and FOO_SYSCTL_DATA. | ||
770 | |||
771 | The third, sixth and ninth parameters should always be NULL, and the | ||
772 | fourth should always be 0. The fifth is the mode of the /proc file; | ||
773 | 0644 is safe, as the file will be owned by root:root. | ||
774 | |||
775 | The seventh and eighth parameters should be &i2c_proc_real and | ||
776 | &i2c_sysctl_real if you want to export lists of reals (scaled | ||
777 | integers). You can also use your own function for them, as usual. | ||
778 | Finally, the last parameter is the call-back to gather the data | ||
779 | (see below) if you use the *_proc_real functions. | ||
780 | |||
781 | |||
782 | Gathering the data | ||
783 | ------------------ | ||
784 | |||
785 | The call back functions (foo_func and foo_data in the above example) | ||
786 | can be called in several ways; the operation parameter determines | ||
787 | what should be done: | ||
788 | |||
789 | * If operation == SENSORS_PROC_REAL_INFO, you must return the | ||
790 | magnitude (scaling) in nrels_mag; | ||
791 | * If operation == SENSORS_PROC_REAL_READ, you must read information | ||
792 | from the chip and return it in results. The number of integers | ||
793 | to display should be put in nrels_mag; | ||
794 | * If operation == SENSORS_PROC_REAL_WRITE, you must write the | ||
795 | supplied information to the chip. nrels_mag will contain the number | ||
796 | of integers, results the integers themselves. | ||
797 | |||
798 | The *_proc_real functions will display the elements as reals for the | ||
799 | /proc interface. If you set the magnitude to 2, and supply 345 for | ||
800 | SENSORS_PROC_REAL_READ, it would display 3.45; and if the user would | ||
801 | write 45.6 to the /proc file, it would be returned as 4560 for | ||
802 | SENSORS_PROC_REAL_WRITE. A magnitude may even be negative! | ||
803 | |||
804 | An example function: | ||
805 | |||
806 | /* FOO_FROM_REG and FOO_TO_REG translate between scaled values and | ||
807 | register values. Note the use of the read cache. */ | ||
808 | void foo_in(struct i2c_client *client, int operation, int ctl_name, | ||
809 | int *nrels_mag, long *results) | ||
810 | { | ||
811 | struct foo_data *data = client->data; | ||
812 | int nr = ctl_name - FOO_SYSCTL_FUNC1; /* reduce to 0 upwards */ | ||
813 | |||
814 | if (operation == SENSORS_PROC_REAL_INFO) | ||
815 | *nrels_mag = 2; | ||
816 | else if (operation == SENSORS_PROC_REAL_READ) { | ||
817 | /* Update the readings cache (if necessary) */ | ||
818 | foo_update_client(client); | ||
819 | /* Get the readings from the cache */ | ||
820 | results[0] = FOO_FROM_REG(data->foo_func_base[nr]); | ||
821 | results[1] = FOO_FROM_REG(data->foo_func_more[nr]); | ||
822 | results[2] = FOO_FROM_REG(data->foo_func_readonly[nr]); | ||
823 | *nrels_mag = 2; | ||
824 | } else if (operation == SENSORS_PROC_REAL_WRITE) { | ||
825 | if (*nrels_mag >= 1) { | ||
826 | /* Update the cache */ | ||
827 | data->foo_base[nr] = FOO_TO_REG(results[0]); | ||
828 | /* Update the chip */ | ||
829 | foo_write_value(client,FOO_REG_FUNC_BASE(nr),data->foo_base[nr]); | ||
830 | } | ||
831 | if (*nrels_mag >= 2) { | ||
832 | /* Update the cache */ | ||
833 | data->foo_more[nr] = FOO_TO_REG(results[1]); | ||
834 | /* Update the chip */ | ||
835 | foo_write_value(client,FOO_REG_FUNC_MORE(nr),data->foo_more[nr]); | ||
836 | } | ||
837 | } | ||
838 | } | ||