178f83902SAndreas Klinger /* 278f83902SAndreas Klinger * srf08.c - Support for Devantech SRF08 ultrasonic ranger 378f83902SAndreas Klinger * 478f83902SAndreas Klinger * Copyright (c) 2016 Andreas Klinger <ak@it-klinger.de> 578f83902SAndreas Klinger * 678f83902SAndreas Klinger * This file is subject to the terms and conditions of version 2 of 778f83902SAndreas Klinger * the GNU General Public License. See the file COPYING in the main 878f83902SAndreas Klinger * directory of this archive for more details. 978f83902SAndreas Klinger * 1078f83902SAndreas Klinger * For details about the device see: 1178f83902SAndreas Klinger * http://www.robot-electronics.co.uk/htm/srf08tech.html 1278f83902SAndreas Klinger */ 1378f83902SAndreas Klinger 1478f83902SAndreas Klinger #include <linux/err.h> 1578f83902SAndreas Klinger #include <linux/i2c.h> 1678f83902SAndreas Klinger #include <linux/delay.h> 1778f83902SAndreas Klinger #include <linux/module.h> 1878f83902SAndreas Klinger #include <linux/bitops.h> 1978f83902SAndreas Klinger #include <linux/iio/iio.h> 2078f83902SAndreas Klinger #include <linux/iio/sysfs.h> 2178f83902SAndreas Klinger 2278f83902SAndreas Klinger /* registers of SRF08 device */ 2378f83902SAndreas Klinger #define SRF08_WRITE_COMMAND 0x00 /* Command Register */ 2478f83902SAndreas Klinger #define SRF08_WRITE_MAX_GAIN 0x01 /* Max Gain Register: 0 .. 31 */ 2578f83902SAndreas Klinger #define SRF08_WRITE_RANGE 0x02 /* Range Register: 0 .. 255 */ 2678f83902SAndreas Klinger #define SRF08_READ_SW_REVISION 0x00 /* Software Revision */ 2778f83902SAndreas Klinger #define SRF08_READ_LIGHT 0x01 /* Light Sensor during last echo */ 2878f83902SAndreas Klinger #define SRF08_READ_ECHO_1_HIGH 0x02 /* Range of first echo received */ 2978f83902SAndreas Klinger #define SRF08_READ_ECHO_1_LOW 0x03 /* Range of first echo received */ 3078f83902SAndreas Klinger 3178f83902SAndreas Klinger #define SRF08_CMD_RANGING_CM 0x51 /* Ranging Mode - Result in cm */ 3278f83902SAndreas Klinger 3378f83902SAndreas Klinger #define SRF08_DEFAULT_GAIN 1025 /* default analogue value of Gain */ 3478f83902SAndreas Klinger #define SRF08_DEFAULT_RANGE 6020 /* default value of Range in mm */ 3578f83902SAndreas Klinger 3678f83902SAndreas Klinger struct srf08_data { 3778f83902SAndreas Klinger struct i2c_client *client; 3878f83902SAndreas Klinger int sensitivity; /* Gain */ 3978f83902SAndreas Klinger int range_mm; /* max. Range in mm */ 4078f83902SAndreas Klinger struct mutex lock; 4178f83902SAndreas Klinger }; 4278f83902SAndreas Klinger 4378f83902SAndreas Klinger /* 4478f83902SAndreas Klinger * in the documentation one can read about the "Gain" of the device 4578f83902SAndreas Klinger * which is used here for amplifying the signal and filtering out unwanted 4678f83902SAndreas Klinger * ones. 4778f83902SAndreas Klinger * But with ADC's this term is already used differently and that's why it 4878f83902SAndreas Klinger * is called "Sensitivity" here. 4978f83902SAndreas Klinger */ 5078f83902SAndreas Klinger static const int srf08_sensitivity[] = { 5178f83902SAndreas Klinger 94, 97, 100, 103, 107, 110, 114, 118, 5278f83902SAndreas Klinger 123, 128, 133, 139, 145, 152, 159, 168, 5378f83902SAndreas Klinger 177, 187, 199, 212, 227, 245, 265, 288, 5478f83902SAndreas Klinger 317, 352, 395, 450, 524, 626, 777, 1025 }; 5578f83902SAndreas Klinger 5678f83902SAndreas Klinger static int srf08_read_ranging(struct srf08_data *data) 5778f83902SAndreas Klinger { 5878f83902SAndreas Klinger struct i2c_client *client = data->client; 5978f83902SAndreas Klinger int ret, i; 6078f83902SAndreas Klinger int waittime; 6178f83902SAndreas Klinger 6278f83902SAndreas Klinger mutex_lock(&data->lock); 6378f83902SAndreas Klinger 6478f83902SAndreas Klinger ret = i2c_smbus_write_byte_data(data->client, 6578f83902SAndreas Klinger SRF08_WRITE_COMMAND, SRF08_CMD_RANGING_CM); 6678f83902SAndreas Klinger if (ret < 0) { 6778f83902SAndreas Klinger dev_err(&client->dev, "write command - err: %d\n", ret); 6878f83902SAndreas Klinger mutex_unlock(&data->lock); 6978f83902SAndreas Klinger return ret; 7078f83902SAndreas Klinger } 7178f83902SAndreas Klinger 7278f83902SAndreas Klinger /* 7378f83902SAndreas Klinger * we read here until a correct version number shows up as 7478f83902SAndreas Klinger * suggested by the documentation 7578f83902SAndreas Klinger * 7678f83902SAndreas Klinger * with an ultrasonic speed of 343 m/s and a roundtrip of it 7778f83902SAndreas Klinger * sleep the expected duration and try to read from the device 7878f83902SAndreas Klinger * if nothing useful is read try it in a shorter grid 7978f83902SAndreas Klinger * 8078f83902SAndreas Klinger * polling for not more than 20 ms should be enough 8178f83902SAndreas Klinger */ 8278f83902SAndreas Klinger waittime = 1 + data->range_mm / 172; 8378f83902SAndreas Klinger msleep(waittime); 8478f83902SAndreas Klinger for (i = 0; i < 4; i++) { 8578f83902SAndreas Klinger ret = i2c_smbus_read_byte_data(data->client, 8678f83902SAndreas Klinger SRF08_READ_SW_REVISION); 8778f83902SAndreas Klinger 8878f83902SAndreas Klinger /* check if a valid version number is read */ 8978f83902SAndreas Klinger if (ret < 255 && ret > 0) 9078f83902SAndreas Klinger break; 9178f83902SAndreas Klinger msleep(5); 9278f83902SAndreas Klinger } 9378f83902SAndreas Klinger 9478f83902SAndreas Klinger if (ret >= 255 || ret <= 0) { 9578f83902SAndreas Klinger dev_err(&client->dev, "device not ready\n"); 9678f83902SAndreas Klinger mutex_unlock(&data->lock); 9778f83902SAndreas Klinger return -EIO; 9878f83902SAndreas Klinger } 9978f83902SAndreas Klinger 10078f83902SAndreas Klinger ret = i2c_smbus_read_word_swapped(data->client, 10178f83902SAndreas Klinger SRF08_READ_ECHO_1_HIGH); 10278f83902SAndreas Klinger if (ret < 0) { 10378f83902SAndreas Klinger dev_err(&client->dev, "cannot read distance: ret=%d\n", ret); 10478f83902SAndreas Klinger mutex_unlock(&data->lock); 10578f83902SAndreas Klinger return ret; 10678f83902SAndreas Klinger } 10778f83902SAndreas Klinger 10878f83902SAndreas Klinger mutex_unlock(&data->lock); 10978f83902SAndreas Klinger 11078f83902SAndreas Klinger return ret; 11178f83902SAndreas Klinger } 11278f83902SAndreas Klinger 11378f83902SAndreas Klinger static int srf08_read_raw(struct iio_dev *indio_dev, 11478f83902SAndreas Klinger struct iio_chan_spec const *channel, int *val, 11578f83902SAndreas Klinger int *val2, long mask) 11678f83902SAndreas Klinger { 11778f83902SAndreas Klinger struct srf08_data *data = iio_priv(indio_dev); 11878f83902SAndreas Klinger int ret; 11978f83902SAndreas Klinger 12078f83902SAndreas Klinger if (channel->type != IIO_DISTANCE) 12178f83902SAndreas Klinger return -EINVAL; 12278f83902SAndreas Klinger 12378f83902SAndreas Klinger switch (mask) { 12478f83902SAndreas Klinger case IIO_CHAN_INFO_RAW: 12578f83902SAndreas Klinger ret = srf08_read_ranging(data); 12678f83902SAndreas Klinger if (ret < 0) 12778f83902SAndreas Klinger return ret; 12878f83902SAndreas Klinger *val = ret; 12978f83902SAndreas Klinger return IIO_VAL_INT; 13078f83902SAndreas Klinger case IIO_CHAN_INFO_SCALE: 13178f83902SAndreas Klinger /* 1 LSB is 1 cm */ 13278f83902SAndreas Klinger *val = 0; 13378f83902SAndreas Klinger *val2 = 10000; 13478f83902SAndreas Klinger return IIO_VAL_INT_PLUS_MICRO; 13578f83902SAndreas Klinger default: 13678f83902SAndreas Klinger return -EINVAL; 13778f83902SAndreas Klinger } 13878f83902SAndreas Klinger } 13978f83902SAndreas Klinger 14078f83902SAndreas Klinger static ssize_t srf08_show_range_mm_available(struct device *dev, 14178f83902SAndreas Klinger struct device_attribute *attr, char *buf) 14278f83902SAndreas Klinger { 14378f83902SAndreas Klinger return sprintf(buf, "[0.043 0.043 11.008]\n"); 14478f83902SAndreas Klinger } 14578f83902SAndreas Klinger 14678f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_max_range_available, S_IRUGO, 14778f83902SAndreas Klinger srf08_show_range_mm_available, NULL, 0); 14878f83902SAndreas Klinger 14978f83902SAndreas Klinger static ssize_t srf08_show_range_mm(struct device *dev, 15078f83902SAndreas Klinger struct device_attribute *attr, char *buf) 15178f83902SAndreas Klinger { 15278f83902SAndreas Klinger struct iio_dev *indio_dev = dev_to_iio_dev(dev); 15378f83902SAndreas Klinger struct srf08_data *data = iio_priv(indio_dev); 15478f83902SAndreas Klinger 15578f83902SAndreas Klinger return sprintf(buf, "%d.%03d\n", data->range_mm / 1000, 15678f83902SAndreas Klinger data->range_mm % 1000); 15778f83902SAndreas Klinger } 15878f83902SAndreas Klinger 15978f83902SAndreas Klinger /* 16078f83902SAndreas Klinger * set the range of the sensor to an even multiple of 43 mm 16178f83902SAndreas Klinger * which corresponds to 1 LSB in the register 16278f83902SAndreas Klinger * 16378f83902SAndreas Klinger * register value corresponding range 16478f83902SAndreas Klinger * 0x00 43 mm 16578f83902SAndreas Klinger * 0x01 86 mm 16678f83902SAndreas Klinger * 0x02 129 mm 16778f83902SAndreas Klinger * ... 16878f83902SAndreas Klinger * 0xFF 11008 mm 16978f83902SAndreas Klinger */ 17078f83902SAndreas Klinger static ssize_t srf08_write_range_mm(struct srf08_data *data, unsigned int val) 17178f83902SAndreas Klinger { 17278f83902SAndreas Klinger int ret; 17378f83902SAndreas Klinger struct i2c_client *client = data->client; 17478f83902SAndreas Klinger unsigned int mod; 17578f83902SAndreas Klinger u8 regval; 17678f83902SAndreas Klinger 17778f83902SAndreas Klinger ret = val / 43 - 1; 17878f83902SAndreas Klinger mod = val % 43; 17978f83902SAndreas Klinger 18078f83902SAndreas Klinger if (mod || (ret < 0) || (ret > 255)) 18178f83902SAndreas Klinger return -EINVAL; 18278f83902SAndreas Klinger 18378f83902SAndreas Klinger regval = ret; 18478f83902SAndreas Klinger 18578f83902SAndreas Klinger mutex_lock(&data->lock); 18678f83902SAndreas Klinger 18778f83902SAndreas Klinger ret = i2c_smbus_write_byte_data(client, SRF08_WRITE_RANGE, regval); 18878f83902SAndreas Klinger if (ret < 0) { 18978f83902SAndreas Klinger dev_err(&client->dev, "write_range - err: %d\n", ret); 19078f83902SAndreas Klinger mutex_unlock(&data->lock); 19178f83902SAndreas Klinger return ret; 19278f83902SAndreas Klinger } 19378f83902SAndreas Klinger 19478f83902SAndreas Klinger data->range_mm = val; 19578f83902SAndreas Klinger 19678f83902SAndreas Klinger mutex_unlock(&data->lock); 19778f83902SAndreas Klinger 19878f83902SAndreas Klinger return 0; 19978f83902SAndreas Klinger } 20078f83902SAndreas Klinger 20178f83902SAndreas Klinger static ssize_t srf08_store_range_mm(struct device *dev, 20278f83902SAndreas Klinger struct device_attribute *attr, 20378f83902SAndreas Klinger const char *buf, size_t len) 20478f83902SAndreas Klinger { 20578f83902SAndreas Klinger struct iio_dev *indio_dev = dev_to_iio_dev(dev); 20678f83902SAndreas Klinger struct srf08_data *data = iio_priv(indio_dev); 20778f83902SAndreas Klinger int ret; 20878f83902SAndreas Klinger int integer, fract; 20978f83902SAndreas Klinger 21078f83902SAndreas Klinger ret = iio_str_to_fixpoint(buf, 100, &integer, &fract); 21178f83902SAndreas Klinger if (ret) 21278f83902SAndreas Klinger return ret; 21378f83902SAndreas Klinger 21478f83902SAndreas Klinger ret = srf08_write_range_mm(data, integer * 1000 + fract); 21578f83902SAndreas Klinger if (ret < 0) 21678f83902SAndreas Klinger return ret; 21778f83902SAndreas Klinger 21878f83902SAndreas Klinger return len; 21978f83902SAndreas Klinger } 22078f83902SAndreas Klinger 22178f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_max_range, S_IRUGO | S_IWUSR, 22278f83902SAndreas Klinger srf08_show_range_mm, srf08_store_range_mm, 0); 22378f83902SAndreas Klinger 22478f83902SAndreas Klinger static ssize_t srf08_show_sensitivity_available(struct device *dev, 22578f83902SAndreas Klinger struct device_attribute *attr, char *buf) 22678f83902SAndreas Klinger { 22778f83902SAndreas Klinger int i, len = 0; 22878f83902SAndreas Klinger 22978f83902SAndreas Klinger for (i = 0; i < ARRAY_SIZE(srf08_sensitivity); i++) 23078f83902SAndreas Klinger len += sprintf(buf + len, "%d ", srf08_sensitivity[i]); 23178f83902SAndreas Klinger 23278f83902SAndreas Klinger len += sprintf(buf + len, "\n"); 23378f83902SAndreas Klinger 23478f83902SAndreas Klinger return len; 23578f83902SAndreas Klinger } 23678f83902SAndreas Klinger 23778f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_sensitivity_available, S_IRUGO, 23878f83902SAndreas Klinger srf08_show_sensitivity_available, NULL, 0); 23978f83902SAndreas Klinger 24078f83902SAndreas Klinger static ssize_t srf08_show_sensitivity(struct device *dev, 24178f83902SAndreas Klinger struct device_attribute *attr, char *buf) 24278f83902SAndreas Klinger { 24378f83902SAndreas Klinger struct iio_dev *indio_dev = dev_to_iio_dev(dev); 24478f83902SAndreas Klinger struct srf08_data *data = iio_priv(indio_dev); 24578f83902SAndreas Klinger int len; 24678f83902SAndreas Klinger 24778f83902SAndreas Klinger len = sprintf(buf, "%d\n", data->sensitivity); 24878f83902SAndreas Klinger 24978f83902SAndreas Klinger return len; 25078f83902SAndreas Klinger } 25178f83902SAndreas Klinger 25278f83902SAndreas Klinger static ssize_t srf08_write_sensitivity(struct srf08_data *data, 25378f83902SAndreas Klinger unsigned int val) 25478f83902SAndreas Klinger { 25578f83902SAndreas Klinger struct i2c_client *client = data->client; 25678f83902SAndreas Klinger int ret, i; 25778f83902SAndreas Klinger u8 regval; 25878f83902SAndreas Klinger 25978f83902SAndreas Klinger for (i = 0; i < ARRAY_SIZE(srf08_sensitivity); i++) 26078f83902SAndreas Klinger if (val == srf08_sensitivity[i]) { 26178f83902SAndreas Klinger regval = i; 26278f83902SAndreas Klinger break; 26378f83902SAndreas Klinger } 26478f83902SAndreas Klinger 26578f83902SAndreas Klinger if (i >= ARRAY_SIZE(srf08_sensitivity)) 26678f83902SAndreas Klinger return -EINVAL; 26778f83902SAndreas Klinger 26878f83902SAndreas Klinger mutex_lock(&data->lock); 26978f83902SAndreas Klinger 27078f83902SAndreas Klinger ret = i2c_smbus_write_byte_data(client, 27178f83902SAndreas Klinger SRF08_WRITE_MAX_GAIN, regval); 27278f83902SAndreas Klinger if (ret < 0) { 27378f83902SAndreas Klinger dev_err(&client->dev, "write_sensitivity - err: %d\n", ret); 27478f83902SAndreas Klinger mutex_unlock(&data->lock); 27578f83902SAndreas Klinger return ret; 27678f83902SAndreas Klinger } 27778f83902SAndreas Klinger 27878f83902SAndreas Klinger data->sensitivity = val; 27978f83902SAndreas Klinger 28078f83902SAndreas Klinger mutex_unlock(&data->lock); 28178f83902SAndreas Klinger 28278f83902SAndreas Klinger return 0; 28378f83902SAndreas Klinger } 28478f83902SAndreas Klinger 28578f83902SAndreas Klinger static ssize_t srf08_store_sensitivity(struct device *dev, 28678f83902SAndreas Klinger struct device_attribute *attr, 28778f83902SAndreas Klinger const char *buf, size_t len) 28878f83902SAndreas Klinger { 28978f83902SAndreas Klinger struct iio_dev *indio_dev = dev_to_iio_dev(dev); 29078f83902SAndreas Klinger struct srf08_data *data = iio_priv(indio_dev); 29178f83902SAndreas Klinger int ret; 29278f83902SAndreas Klinger unsigned int val; 29378f83902SAndreas Klinger 29478f83902SAndreas Klinger ret = kstrtouint(buf, 10, &val); 29578f83902SAndreas Klinger if (ret) 29678f83902SAndreas Klinger return ret; 29778f83902SAndreas Klinger 29878f83902SAndreas Klinger ret = srf08_write_sensitivity(data, val); 29978f83902SAndreas Klinger if (ret < 0) 30078f83902SAndreas Klinger return ret; 30178f83902SAndreas Klinger 30278f83902SAndreas Klinger return len; 30378f83902SAndreas Klinger } 30478f83902SAndreas Klinger 30578f83902SAndreas Klinger static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR, 30678f83902SAndreas Klinger srf08_show_sensitivity, srf08_store_sensitivity, 0); 30778f83902SAndreas Klinger 30878f83902SAndreas Klinger static struct attribute *srf08_attributes[] = { 30978f83902SAndreas Klinger &iio_dev_attr_sensor_max_range.dev_attr.attr, 31078f83902SAndreas Klinger &iio_dev_attr_sensor_max_range_available.dev_attr.attr, 31178f83902SAndreas Klinger &iio_dev_attr_sensor_sensitivity.dev_attr.attr, 31278f83902SAndreas Klinger &iio_dev_attr_sensor_sensitivity_available.dev_attr.attr, 31378f83902SAndreas Klinger NULL, 31478f83902SAndreas Klinger }; 31578f83902SAndreas Klinger 31678f83902SAndreas Klinger static const struct attribute_group srf08_attribute_group = { 31778f83902SAndreas Klinger .attrs = srf08_attributes, 31878f83902SAndreas Klinger }; 31978f83902SAndreas Klinger 32078f83902SAndreas Klinger static const struct iio_chan_spec srf08_channels[] = { 32178f83902SAndreas Klinger { 32278f83902SAndreas Klinger .type = IIO_DISTANCE, 32378f83902SAndreas Klinger .info_mask_separate = 32478f83902SAndreas Klinger BIT(IIO_CHAN_INFO_RAW) | 32578f83902SAndreas Klinger BIT(IIO_CHAN_INFO_SCALE), 32678f83902SAndreas Klinger }, 32778f83902SAndreas Klinger }; 32878f83902SAndreas Klinger 32978f83902SAndreas Klinger static const struct iio_info srf08_info = { 33078f83902SAndreas Klinger .read_raw = srf08_read_raw, 33178f83902SAndreas Klinger .attrs = &srf08_attribute_group, 33278f83902SAndreas Klinger .driver_module = THIS_MODULE, 33378f83902SAndreas Klinger }; 33478f83902SAndreas Klinger 33578f83902SAndreas Klinger static int srf08_probe(struct i2c_client *client, 33678f83902SAndreas Klinger const struct i2c_device_id *id) 33778f83902SAndreas Klinger { 33878f83902SAndreas Klinger struct iio_dev *indio_dev; 33978f83902SAndreas Klinger struct srf08_data *data; 34078f83902SAndreas Klinger int ret; 34178f83902SAndreas Klinger 34278f83902SAndreas Klinger if (!i2c_check_functionality(client->adapter, 34378f83902SAndreas Klinger I2C_FUNC_SMBUS_READ_BYTE_DATA | 34478f83902SAndreas Klinger I2C_FUNC_SMBUS_WRITE_BYTE_DATA | 34578f83902SAndreas Klinger I2C_FUNC_SMBUS_READ_WORD_DATA)) 34678f83902SAndreas Klinger return -ENODEV; 34778f83902SAndreas Klinger 34878f83902SAndreas Klinger indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 34978f83902SAndreas Klinger if (!indio_dev) 35078f83902SAndreas Klinger return -ENOMEM; 35178f83902SAndreas Klinger 35278f83902SAndreas Klinger data = iio_priv(indio_dev); 35378f83902SAndreas Klinger i2c_set_clientdata(client, indio_dev); 35478f83902SAndreas Klinger data->client = client; 35578f83902SAndreas Klinger 35678f83902SAndreas Klinger indio_dev->name = "srf08"; 35778f83902SAndreas Klinger indio_dev->dev.parent = &client->dev; 35878f83902SAndreas Klinger indio_dev->modes = INDIO_DIRECT_MODE; 35978f83902SAndreas Klinger indio_dev->info = &srf08_info; 36078f83902SAndreas Klinger indio_dev->channels = srf08_channels; 36178f83902SAndreas Klinger indio_dev->num_channels = ARRAY_SIZE(srf08_channels); 36278f83902SAndreas Klinger 36378f83902SAndreas Klinger mutex_init(&data->lock); 36478f83902SAndreas Klinger 36578f83902SAndreas Klinger /* 36678f83902SAndreas Klinger * set default values of device here 36778f83902SAndreas Klinger * these register values cannot be read from the hardware 36878f83902SAndreas Klinger * therefore set driver specific default values 36978f83902SAndreas Klinger */ 37078f83902SAndreas Klinger ret = srf08_write_range_mm(data, SRF08_DEFAULT_RANGE); 37178f83902SAndreas Klinger if (ret < 0) 37278f83902SAndreas Klinger return ret; 37378f83902SAndreas Klinger 37478f83902SAndreas Klinger ret = srf08_write_sensitivity(data, SRF08_DEFAULT_GAIN); 37578f83902SAndreas Klinger if (ret < 0) 37678f83902SAndreas Klinger return ret; 37778f83902SAndreas Klinger 37878f83902SAndreas Klinger return devm_iio_device_register(&client->dev, indio_dev); 37978f83902SAndreas Klinger } 38078f83902SAndreas Klinger 38178f83902SAndreas Klinger static const struct i2c_device_id srf08_id[] = { 38278f83902SAndreas Klinger { "srf08", 0 }, 38378f83902SAndreas Klinger { } 38478f83902SAndreas Klinger }; 38578f83902SAndreas Klinger MODULE_DEVICE_TABLE(i2c, srf08_id); 38678f83902SAndreas Klinger 38778f83902SAndreas Klinger static struct i2c_driver srf08_driver = { 38878f83902SAndreas Klinger .driver = { 38978f83902SAndreas Klinger .name = "srf08", 39078f83902SAndreas Klinger }, 39178f83902SAndreas Klinger .probe = srf08_probe, 39278f83902SAndreas Klinger .id_table = srf08_id, 39378f83902SAndreas Klinger }; 39478f83902SAndreas Klinger module_i2c_driver(srf08_driver); 39578f83902SAndreas Klinger 39678f83902SAndreas Klinger MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>"); 39778f83902SAndreas Klinger MODULE_DESCRIPTION("Devantech SRF08 ultrasonic ranger driver"); 39878f83902SAndreas Klinger MODULE_LICENSE("GPL"); 399