RE: [Uclinux-dist-devel] [PATCH 2/2] add ad714x input driver forbutton/scrollwhell/slider/touchpad

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 

>-----Original Message-----
>From: uclinux-dist-devel-bounces@xxxxxxxxxxxxxxxxxxxx 
>[mailto:uclinux-dist-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On 
>Behalf Of Mike Frysinger
>Sent: Wednesday, September 02, 2009 3:31 AM
>To: Barry Song
>Cc: dbrownell@xxxxxxxxxxxxxxxxxxxxx; dtor@xxxxxxx; 
>dmitry.torokhov@xxxxxxxxx; 
>spi-devel-general@xxxxxxxxxxxxxxxxxxxxx; 
>linux-input@xxxxxxxxxxxxxxx; uclinux-dist-devel@xxxxxxxxxxxxxxxxxxxx
>Subject: Re: [Uclinux-dist-devel] [PATCH 2/2] add ad714x input 
>driver forbutton/scrollwhell/slider/touchpad
>
>On Mon, Aug 31, 2009 at 23:55, Barry Song wrote:
>> ad7142/ad7147 are Programmable Controllers for Capacitance 
>Touch Sensors.
>> The chips don't restrict the specific usage, and it can be 
>used as button/
>> slider/scrollwheel/touchpad etc. depending on the hardware 
>connection.
>> One special target board can include one or several these components.
>>
>> The driver is independent of special boards. It gets the components
>> layout information from the platform_data, registers related devices,
>> fullfills the algorithms and state machines for these components and
>> report related input events to up level.
>
>seems you didnt address all the comments i posted after your 
>first commit ...
>
>please add this line before the #include's:
>#define pr_fmt(fmt) "ad714x: " fmt
>this will fix all of your dev_*() output so that it is 
>properly prefixed

Fixed.

>
>> +#define AD714x_SPI_ADDR        0x1C
>> +#define AD714x_SPI_ADDR_SHFT   11
>> +#define AD714x_SPI_READ        1
>> +#define AD714x_SPI_READ_SHFT   10
>> +
>> +#define AD714X_PWR_CTRL           0x0
>> +#define AD714x_STG_CAL_EN_REG     0x1
>> +#define AD714X_AMB_COMP_CTRL0_REG 0x2
>> +#define AD714x_PARTID_REG         0x17
>> +#define AD7147_PARTID             0x1470
>> +#define AD7142_PARTID             0xE620
>> +#define AD714x_STAGECFG_REG       0x80
>> +#define AD714x_SYSCFG_REG         0x0
>
>your AD714X and AD714x needs to be consistent
Fixed.
>
>> +struct ad714x_button_drv {
>> +       ad714x_device_state state;
>> +       /* Unlike slider/wheel/touchpad, all buttons point to
>> +        * same input_dev instance */
>
>either put the comment on one line and do:
>/* fooo */
>or use proper comment style where the last */ is on a line by itself
>/*
> * foo
> */
>this applies to many comments in this file

Fixed.

>
>> +struct ad714x_chip {
>> +       unsigned short h_state;
>> +       unsigned short l_state;
>> +       unsigned short c_state;
>> +       unsigned short adc_reg[STAGE_NUM];
>> +       unsigned short amb_reg[STAGE_NUM];
>> +       unsigned short sensor_val[STAGE_NUM];
>> +
>> +       struct ad714x_platform_data *hw;
>> +       struct ad714x_driver_data *sw;
>> +
>> +       bus_device *bus;
>> +       int (*read) (bus_device *, unsigned short, unsigned short *);
>> +       int (*write) (bus_device *, unsigned short, unsigned short);
>
>using function pointers is pure overhead in your current
>implementation.  create a ad714x_read macro that expands to either the
>spi or the i2c version depending on which is enabled.
Using macro can be a choice. But I don't think it can save much overhead here. 
Function pointers encapsulates the object better.
>
>> +static void stage_use_com_int(struct ad714x_chip *ad714x, 
>int start_stage,
>> +               int end_stage)
>> +{
>
>all funcs in here really should have ad714x_ symbol prefixes.  if i
>saw a crash and it just said "stage_xxx", it isnt immediately obvious
>where this symbol is coming from.

Fixed.

>
>> +static int stage_cal_highest_stage(struct ad714x_chip 
>*ad714x, int start_stage,
>> +               int end_stage)
>> +{
>> +       int max_res = 0;
>> +       int max_idx = 0;
>> +       int i;
>> +
>> +       for (i = start_stage; i <= end_stage; i++) {
>> +               if (ad714x->sensor_val[i] > max_res) {
>> +                       max_res = ad714x->sensor_val[i];
>> +                       max_idx = i;
>> +               }
>> +       }
>
>should the loop limit really be "<=" and not "<" ?  seems to be this
>way throughout, so maybe the logic is correct ...

It's <=.

>
>> +static int stage_cal_abs_pos(struct ad714x_chip *ad714x, 
>int start_stage,
>> +               int end_stage, int highest_stage, int max_coord)
>> +{
>> +       int a_param, b_param;
>> +
>> +       if (highest_stage == start_stage) {
>> +               a_param = ad714x->sensor_val[start_stage + 1];
>> +               b_param = ad714x->sensor_val[start_stage] +
>> +                       ad714x->sensor_val[start_stage + 1];
>> +       } else if (highest_stage == end_stage) {
>> +               a_param = ad714x->sensor_val[end_stage] *
>> +                       (end_stage - start_stage) +
>> +                       ad714x->sensor_val[end_stage - 1] *
>> +                       (end_stage - start_stage - 1);
>> +               b_param = ad714x->sensor_val[end_stage] +
>> +                       ad714x->sensor_val[end_stage - 1];
>> +       } else {
>> +               a_param = ad714x->sensor_val[highest_stage] *
>> +                       (highest_stage - start_stage) +
>> +                       ad714x->sensor_val[highest_stage - 1] *
>> +                       (highest_stage - start_stage - 1) +
>> +                       ad714x->sensor_val[highest_stage + 1] *
>> +                       (highest_stage - start_stage + 1);
>> +               b_param = ad714x->sensor_val[highest_stage] +
>> +                       ad714x->sensor_val[highest_stage - 1] +
>> +                       ad714x->sensor_val[highest_stage + 1];
>> +       }
>> +
>> +       return (max_coord / (end_stage - start_stage)) * 
>a_param / b_param;
>> +}
>
>do the local vars really need "_stage" suffix ?  if you trimmed that,
>i imagine it'd make the code a bit easier to digest.
Yes. It need the _stage suffix. Otherwise, nobody know what's started, what's ended.
>
>> +/* One button can connect to multi postive and negative of CDCs
>> + * Multi-buttons can connect to same postive/negative of one CDC
>
>please run a spell checker on your comments ...
>postive -> positive
>

Fixed

>> +static int ad714x_hw_detect(struct ad714x_chip *ad714x)
>
>should be __devinit
>
>> +       default:
>> +               dev_err(&ad714x->bus->dev, "Fail to detect 
>AD714x captouch,\
>> +                               read ID is %04x\n", data);
>
>line continuation in strings produces awful output
>

Fixed

>> +static int ad714x_hw_init(struct ad714x_chip *ad714x)
>> ...
>> +       return 0;
>> ...
>> +       ad714x_hw_init(ad714x);
>
>considering you always return 0 and you never check the return, this
>should be a void function
>
>and ad714x_hw_init should be __devinit

Fixed.

>
>> +       drv_data = kzalloc(sizeof(struct 
>ad714x_driver_data), GFP_KERNEL);
>
>sizeof(*drv_data) ... applies to every alloc in this driver
>
>> + input[alloc_idx-1]->id.bustype = BUS_I2C;
>
>you set bustype to I2C in common code even though this will be
>executed for both SPI and I2C interfaces

There is a BUS_I2C, but no BUS_SPI. So people may use other serial type to imply. 
Do you think we should add a macro in input.h? I am really suprised why the macro hasn't been added until now. 

>
>> +       if (ad714x->bus->irq > 0) {
>> +               ret = request_threaded_irq(ad714x->bus->irq, 
>ad714x_interrupt,
>> +                               ad714x_interrupt_thread, 
>IRQF_TRIGGER_FALLING,
>> +                               "ad714x_captouch", ad714x);
>> +               if (ret) {
>> +                       dev_err(&ad714x->bus->dev, "Can't 
>allocate irq %d\n",
>> +                                       ad714x->bus->irq);
>> +                       goto fail_irq;
>> +               }
>> +       } else
>> +               dev_warn(&ad714x->bus->dev, "IRQ not configured!\n");
>> +
>> +       return 0;
>
>since the driver requires an IRQ in order to work, this should error
>out rather than warn and return success
>
>also, wouldnt it make more sense to request the IRQ first and then
>fail rather than doing all the memory/input allocation only to find
>out the IRQ is already taken ?
>

Ok

>> +int ad714x_spi_read(struct spi_device *spi, unsigned short reg,
>> +               unsigned short *data)
>
>you're missing "static" here and in a few other functions

Fixed

>
>> +{
>> +       int ret;
>> +       unsigned short tx[2];
>> +       unsigned short rx[2];
>> +       struct spi_transfer t = {
>> +               .tx_buf = tx,
>> +               .rx_buf = rx,
>> +               .len = 4,
>> +       };
>> +       struct spi_message m;
>> +
>> +       tx[0] = (AD714x_SPI_ADDR << AD714x_SPI_ADDR_SHFT) |
>> +               (AD714x_SPI_READ << AD714x_SPI_READ_SHFT) | reg;
>> +
>> +       spi_message_init(&m);
>> +       spi_message_add_tail(&t, &m);
>> +       ret = spi_sync(spi, &m);
>
>cant you use spi_write_then_read() ?  dont let the u8* prototype scare
>you, it should work with writing 16bits and then reading 16bits.

I have never been scared by any u8* or something else. I only prefer to use raw spi API, which can show the bottom level timing and SPI bus feature better. 
In fact, I prefer to use raw i2c API too. 

>
>> +int ad714x_spi_write(struct spi_device *spi, unsigned short reg,
>> +               unsigned short data)
>> +{
>> +       int ret = 0;
>> +       unsigned short tx[2];
>> +       struct spi_transfer t = {
>> +               .tx_buf = tx,
>> +               .len = 4,
>> +       };
>> +       struct spi_message m;
>> +
>> +       tx[0] = (AD714x_SPI_ADDR << AD714x_SPI_ADDR_SHFT) | reg;
>> +       tx[1] = data;
>> +
>> +       spi_message_init(&m);
>> +       spi_message_add_tail(&t, &m);
>> +
>> +       ret = spi_sync(spi, &m);
>> +       if (ret < 0)
>> +               dev_err(&spi->dev, "SPI write error\n");
>> +
>> +       return ret;
>> +}
>
>seems like spi_write() would be better
>
>> +static int __devexit ad714x_i2c_remove(struct i2c_client *client)
>> +{
>> +       struct ad714x_chip *chip = i2c_get_clientdata(client);
>> +       ad714x_remove(chip);
>> +
>> +       return 0;
>> +}
>
>return ad714x_remove(chip);

Fixed.

>
>of course, if you simply created a macro "ad714x_get_chipdata" and had
>it evaluate to either the spi or i2c version depending on the
>interface enabled, this function could be in common code rather than
>duplicating it for the two interfaces
>

In fact, dev_set_drvdata and dev_get_drvdata can be used in spi/i2c probe and remove. Then the probe/remove can be unified.
But at the beginning, I prefer to keep this little redundancy, which maybe make the code more readable. 
Maybe I will use a unified probe/remove for SPI/I2C too, Let me think...

>same goes for the module init/exit functions
>
>> +static struct spi_driver ad714x_spi_driver = {
>> +       .driver = {
>> +               .name   = "ad714x_captouch",
>> +               .bus    = &spi_bus_type,
>> +               .owner  = THIS_MODULE,
>> +       },
>
>i'm pretty sure you dont need to set .bus yourself

Fixed.

>
>> +       .probe          = ad714x_spi_probe,
>> +       .remove         = __devexit_p(ad714x_spi_remove),
>> +       .suspend        = ad714x_suspend,
>> +       .resume         = ad714x_resume,
>
>there is a new power management opts struct in 2.6.31 that 
>should be used

Ok

>
>> +static int __init ad714x_init(void)
>> +{
>> +       int ret;
>> +
>> +       ret = spi_register_driver(&ad714x_spi_driver);
>> +       if (ret != 0) {
>> +               printk(KERN_ERR "Failed to register ad714x 
>SPI driver: %d\n",
>> +                               ret);
>> +       }
>> +
>> +       return ret;
>

Ok

>pr_err(), no need for the braces, and no need to output the ret value.
> this is the module init function which means that error will be
>passed back up to userspace and it can handle displaying it.  in that
>case, it might as well read:
>{
>    return spi_register_driver(&ad714x_spi_driver);
>}

Fixed

>
>> +       u8 tx[4];
>> +
>> +       /* Do raw I2C, not smbus compatible */
>> +       tx[0] = (reg & 0xFF00) >> 8;
>> +       tx[1] = (reg & 0x00FF);
>> +       tx[2] = (data & 0xFF00) >> 8;
>> +       tx[3] = data & 0x00FF;
>
>the masks are pretty useless (and i wouldnt be surprised if gcc doesnt
>optimize all of them away) since you're already loading into a u8
>tx[4] = {
>    reg >> 8,
>    reg,
>    data >> 8,
>    data,
>};
>
>> +       u8 tx[2];
>> +
>> +       /* Do raw I2C, not smbus compatible */
>> +       tx[0] = (reg & 0xFF00) >> 8;
>> +       tx[1] = (reg & 0x00FF);
>
>same here
>
>> +       *data = rx[0];
>> +       *data = (*data << 8) | rx[1];
>
>erm, this is funky.  why cant you do it with one assignment ?
>
>> +MODULE_DESCRIPTION("ad714x captouch driver");
>
>please use a description like you did in the Kconfig

Fixed

>-mike
>_______________________________________________
>Uclinux-dist-devel mailing list
>Uclinux-dist-devel@xxxxxxxxxxxxxxxxxxxx
>https://blackfin.uclinux.org/mailman/listinfo/uclinux-dist-devel
>
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux