Re: [PATCH v3] media: si2168: Refactor command setup code

2019-07-14 Thread Matthias Schwarzott
Am 13.07.19 um 12:02 schrieb Mauro Carvalho Chehab:
> Em Sat, 13 Jul 2019 00:11:12 +0200
> Marc Gonzalez  escreveu:
> 
>> On 12/07/2019 19:45, Mauro Carvalho Chehab wrote:
>>
>>> Brad Love  escreveu:
>>>   
>>> IMHO, using sizeof() here is a very bad idea.  
>>
>> You may have a point...
>> (Though I'm not proposing a kernel API function, merely code
>> refactoring for a single file that's unlikely to change going
>> forward.)
> 
> Yes, I know, but we had already some bugs due to the usage of
> sizeof() on similar macros at drivers in the past.
> 
>> It's also bad form to repeat the cmd size (twice) when the compiler
>> can figure it out automatically for string literals (which is 95%
>> of the use-cases).
>>
>> I can drop the macro, and just use the helper...
> 
> The helper function sounds fine.
> 
>>
>> Or maybe there's a GCC extension to test that an argument is a
>> string literal...
> 
> If this could be evaluated by some advanced macro logic that
> would work not only with gcc but also with clang, then a
> macro that does what you proposed could be useful.
> 
> There are some ways to check the type of a macro argument, but I'm
> not sure if are there any way for it to distinguish between a
> string constant from a char * array.
> 
Maybe something like this will prevent compilation if the argument is no
string literal:

#define CMD_SETUP(cmd, args, rlen) \
cmd_setup(cmd, args "", sizeof(args) - 1, rlen)

Another idea is a check like:

#define CMD_SETUP(cmd, args, rlen) \
do { \
BUILD_BUG_ON(#args[0] != "\""); \
cmd_setup(cmd, args "", sizeof(args) - 1, rlen) \
} while(0)

Regards
Matthias


Re: [PATCH v3] media: si2168: Refactor command setup code

2019-07-13 Thread Mauro Carvalho Chehab
Em Sat, 13 Jul 2019 00:11:12 +0200
Marc Gonzalez  escreveu:

> On 12/07/2019 19:45, Mauro Carvalho Chehab wrote:
> 
> > Brad Love  escreveu:
> >   
> >> On 04/07/2019 05.33, Marc Gonzalez wrote:
> >>  
> >>> +#define CMD_SETUP(cmd, args, rlen) \
> >>> + cmd_setup(cmd, args, sizeof(args) - 1, rlen)
> >>> +
> >>
> >> This is only a valid helper if args is a null terminated string. It just
> >> so happens that every instance in this driver is, but that could be a
> >> silent pitfall if someone used a u8 array with this macro.  
> > 
> > Actually, it is uglier than that. If one writes something like:
> > 
> > char buf[20];
> > 
> > buf[0] = 0x20;
> > buf[1] = 0x03;
> > 
> > CMD_SETUP(cmd, buf, 0);
> > 
> > // some other init, up to 5 values, then another CMD_SETUP()  
> 
> I'm not sure what you mean in the // comment.
> What kind of init? Why up to 5 values? Why another CMD_SETUP?

I mean that the same buffer could be re-used to do something like:

char buf[20];
 
buf[0] = 0x20;
buf[1] = 0x03;
 
CMD_SETUP(cmd, buf, 0);   // write size here should be 2

buf[2] = 0x04
buf[3] = 0x00
buf[4] = 0x05

CMD_SETUP(cmd, buf, 0); // write size here should be 5

This kind of pattern happens on other drivers and someone may
end needing something like that at this driver on some future.

> > sizeof() will evaluate to 20, and not to 2, with would be the
> > expected buffer size, and it will pass 18 random values.
> > 
> > IMHO, using sizeof() here is a very bad idea.  
> 
> You may have a point...
> (Though I'm not proposing a kernel API function, merely code
> refactoring for a single file that's unlikely to change going
> forward.)

Yes, I know, but we had already some bugs due to the usage of
sizeof() on similar macros at drivers in the past.

> It's also bad form to repeat the cmd size (twice) when the compiler
> can figure it out automatically for string literals (which is 95%
> of the use-cases).
> 
> I can drop the macro, and just use the helper...

The helper function sounds fine.

> 
> Or maybe there's a GCC extension to test that an argument is a
> string literal...

If this could be evaluated by some advanced macro logic that
would work not only with gcc but also with clang, then a
macro that does what you proposed could be useful.

There are some ways to check the type of a macro argument, but I'm
not sure if are there any way for it to distinguish between a
string constant from a char * array.

Thanks,
Mauro


Re: [PATCH v3] media: si2168: Refactor command setup code

2019-07-12 Thread Marc Gonzalez
On 12/07/2019 19:45, Mauro Carvalho Chehab wrote:

> Brad Love  escreveu:
> 
>> On 04/07/2019 05.33, Marc Gonzalez wrote:
>>
>>> +#define CMD_SETUP(cmd, args, rlen) \
>>> +   cmd_setup(cmd, args, sizeof(args) - 1, rlen)
>>> +  
>>
>> This is only a valid helper if args is a null terminated string. It just
>> so happens that every instance in this driver is, but that could be a
>> silent pitfall if someone used a u8 array with this macro.
> 
> Actually, it is uglier than that. If one writes something like:
> 
>   char buf[20];
> 
>   buf[0] = 0x20;
>   buf[1] = 0x03;
> 
>   CMD_SETUP(cmd, buf, 0);
> 
>   // some other init, up to 5 values, then another CMD_SETUP()

I'm not sure what you mean in the // comment.
What kind of init? Why up to 5 values? Why another CMD_SETUP?

> sizeof() will evaluate to 20, and not to 2, with would be the
> expected buffer size, and it will pass 18 random values.
> 
> IMHO, using sizeof() here is a very bad idea.

You may have a point...
(Though I'm not proposing a kernel API function, merely code
refactoring for a single file that's unlikely to change going
forward.)

It's also bad form to repeat the cmd size (twice) when the compiler
can figure it out automatically for string literals (which is 95%
of the use-cases).

I can drop the macro, and just use the helper...

Or maybe there's a GCC extension to test that an argument is a
string literal...

Regards.


Re: [PATCH v3] media: si2168: Refactor command setup code

2019-07-12 Thread Marc Gonzalez
On 12/07/2019 17:47, Brad Love wrote:

> On 04/07/2019 05.33, Marc Gonzalez wrote:
>
>> Refactor the command setup code, and let the compiler determine
>> the size of each command.
>>
>> Reviewed-by: Jonathan Neuschäfer 
>> Signed-off-by: Marc Gonzalez 
>> ---
>> Changes from v1:
>> - Use a real function to populate struct si2168_cmd *cmd, and a trivial
>> macro wrapping it (macro because sizeof).
>> Changes from v2:
>> - Fix header mess
>> - Add Jonathan's tag
>> ---
>>  drivers/media/dvb-frontends/si2168.c | 146 +--
>>  1 file changed, 45 insertions(+), 101 deletions(-)
>>
>> diff --git a/drivers/media/dvb-frontends/si2168.c 
>> b/drivers/media/dvb-frontends/si2168.c
>> index c64b360ce6b5..5e81e076369c 100644
>> --- a/drivers/media/dvb-frontends/si2168.c
>> +++ b/drivers/media/dvb-frontends/si2168.c
>> @@ -12,6 +12,16 @@
>>  
>>  static const struct dvb_frontend_ops si2168_ops;
>>  
>> +static void cmd_setup(struct si2168_cmd *cmd, char *args, int wlen, int 
>> rlen)
>> +{
>> +memcpy(cmd->args, args, wlen);
>> +cmd->wlen = wlen;
>> +cmd->rlen = rlen;
>> +}
> 
> struct si2168_cmd.args is u8, not char.

Yes, struct si2168_cmd.args is an u8 array.
However, string literals such as "\xa0\x01" are char arrays.
memcpy() ignores the types altogether.

> I also think const should apply to the pointer.

I can do that, even though it's obvious we're not writing
to args in the trivial cmd_setup() body.

>> +#define CMD_SETUP(cmd, args, rlen) \
>> +cmd_setup(cmd, args, sizeof(args) - 1, rlen)
>> +
> 
> This is only a valid helper if args is a null terminated string.

You say that because of the "-1" arithmetic, I assume?

> It just so happens that every instance in this driver is,

FWIW, there are 2 calls where it is not.
memcpy(cmd.args, >data[(fw->size - remaining) + 1], len);
memcpy(cmd.args, >data[fw->size - remaining], len);

> but that could be a silent pitfall if someone used a u8 array
> with this macro.

Actually, the compiler warns if we pass an u8 array instead of
a char array. IMO, the type is actually a good thing, since it
warns for cases where we don't use a string literal.

> Otherwise I'm ok with the refactoring.

I'll see what I can do...

Regards.


Re: [PATCH v3] media: si2168: Refactor command setup code

2019-07-12 Thread Mauro Carvalho Chehab
Em Fri, 12 Jul 2019 10:47:17 -0500
Brad Love  escreveu:

> Hi Marc,
> 
> Replying inline.
> 
> 
> On 04/07/2019 05.33, Marc Gonzalez wrote:
> > Refactor the command setup code, and let the compiler determine
> > the size of each command.
> >
> > Reviewed-by: Jonathan Neuschäfer 
> > Signed-off-by: Marc Gonzalez 
> > ---
> > Changes from v1:
> > - Use a real function to populate struct si2168_cmd *cmd, and a trivial
> > macro wrapping it (macro because sizeof).
> > Changes from v2:
> > - Fix header mess
> > - Add Jonathan's tag
> > ---
> >  drivers/media/dvb-frontends/si2168.c | 146 +--
> >  1 file changed, 45 insertions(+), 101 deletions(-)
> >
> > diff --git a/drivers/media/dvb-frontends/si2168.c 
> > b/drivers/media/dvb-frontends/si2168.c
> > index c64b360ce6b5..5e81e076369c 100644
> > --- a/drivers/media/dvb-frontends/si2168.c
> > +++ b/drivers/media/dvb-frontends/si2168.c
> > @@ -12,6 +12,16 @@
> >  
> >  static const struct dvb_frontend_ops si2168_ops;
> >  
> > +static void cmd_setup(struct si2168_cmd *cmd, char *args, int wlen, int 
> > rlen)
> > +{
> > +   memcpy(cmd->args, args, wlen);
> > +   cmd->wlen = wlen;
> > +   cmd->rlen = rlen;
> > +}
> > +  
> 
> 
> struct si2168_cmd.args is u8, not char. I also think const should apply
> to the pointer.
> 
> 
> > +#define CMD_SETUP(cmd, args, rlen) \
> > +   cmd_setup(cmd, args, sizeof(args) - 1, rlen)
> > +  
> 
> 
> This is only a valid helper if args is a null terminated string. It just
> so happens that every instance in this driver is, but that could be a
> silent pitfall if someone used a u8 array with this macro.

Actually, it is uglier than that. Of one writes something like:

char buf[20];

buf[0] = 0x20;
buf[1] = 0x03;

CMD_SETUP(cmd, buf, 0);

// some other init, up to 5 values, then another CMD_SETUP()


sizeof() will evaluate to 20, and not to 2, with would be the
expected buffer size, and it will pass 18 random values.

IMHO, using sizeof() here is a very bad idea.

Regards,
Mauro


Re: [PATCH v3] media: si2168: Refactor command setup code

2019-07-12 Thread Brad Love
Hi Marc,

Replying inline.


On 04/07/2019 05.33, Marc Gonzalez wrote:
> Refactor the command setup code, and let the compiler determine
> the size of each command.
>
> Reviewed-by: Jonathan Neuschäfer 
> Signed-off-by: Marc Gonzalez 
> ---
> Changes from v1:
> - Use a real function to populate struct si2168_cmd *cmd, and a trivial
> macro wrapping it (macro because sizeof).
> Changes from v2:
> - Fix header mess
> - Add Jonathan's tag
> ---
>  drivers/media/dvb-frontends/si2168.c | 146 +--
>  1 file changed, 45 insertions(+), 101 deletions(-)
>
> diff --git a/drivers/media/dvb-frontends/si2168.c 
> b/drivers/media/dvb-frontends/si2168.c
> index c64b360ce6b5..5e81e076369c 100644
> --- a/drivers/media/dvb-frontends/si2168.c
> +++ b/drivers/media/dvb-frontends/si2168.c
> @@ -12,6 +12,16 @@
>  
>  static const struct dvb_frontend_ops si2168_ops;
>  
> +static void cmd_setup(struct si2168_cmd *cmd, char *args, int wlen, int rlen)
> +{
> + memcpy(cmd->args, args, wlen);
> + cmd->wlen = wlen;
> + cmd->rlen = rlen;
> +}
> +


struct si2168_cmd.args is u8, not char. I also think const should apply
to the pointer.


> +#define CMD_SETUP(cmd, args, rlen) \
> + cmd_setup(cmd, args, sizeof(args) - 1, rlen)
> +


This is only a valid helper if args is a null terminated string. It just
so happens that every instance in this driver is, but that could be a
silent pitfall if someone used a u8 array with this macro.

Otherwise I'm ok with the refactoring.

Regards,

Brad




>  /* execute firmware command */
>  static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
> *cmd)
>  {
> @@ -84,15 +94,13 @@ static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, 
> int acquire)
>   dev_dbg(>dev, "%s acquire: %d\n", __func__, acquire);
>  
>   /* set TS_MODE property */
> - memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
> + CMD_SETUP(, "\x14\x00\x01\x10\x10\x00", 4);
>   if (acquire)
>   cmd.args[4] |= dev->ts_mode;
>   else
>   cmd.args[4] |= SI2168_TS_TRISTATE;
>   if (dev->ts_clock_gapped)
>   cmd.args[4] |= 0x40;
> - cmd.wlen = 6;
> - cmd.rlen = 4;
>   ret = si2168_cmd_execute(client, );
>  
>   return ret;
> @@ -116,19 +124,13 @@ static int si2168_read_status(struct dvb_frontend *fe, 
> enum fe_status *status)
>  
>   switch (c->delivery_system) {
>   case SYS_DVBT:
> - memcpy(cmd.args, "\xa0\x01", 2);
> - cmd.wlen = 2;
> - cmd.rlen = 13;
> + CMD_SETUP(, "\xa0\x01", 13);
>   break;
>   case SYS_DVBC_ANNEX_A:
> - memcpy(cmd.args, "\x90\x01", 2);
> - cmd.wlen = 2;
> - cmd.rlen = 9;
> + CMD_SETUP(, "\x90\x01", 9);
>   break;
>   case SYS_DVBT2:
> - memcpy(cmd.args, "\x50\x01", 2);
> - cmd.wlen = 2;
> - cmd.rlen = 14;
> + CMD_SETUP(, "\x50\x01", 14);
>   break;
>   default:
>   ret = -EINVAL;
> @@ -165,9 +167,7 @@ static int si2168_read_status(struct dvb_frontend *fe, 
> enum fe_status *status)
>  
>   /* BER */
>   if (*status & FE_HAS_VITERBI) {
> - memcpy(cmd.args, "\x82\x00", 2);
> - cmd.wlen = 2;
> - cmd.rlen = 3;
> + CMD_SETUP(, "\x82\x00", 3);
>   ret = si2168_cmd_execute(client, );
>   if (ret)
>   goto err;
> @@ -198,9 +198,7 @@ static int si2168_read_status(struct dvb_frontend *fe, 
> enum fe_status *status)
>  
>   /* UCB */
>   if (*status & FE_HAS_SYNC) {
> - memcpy(cmd.args, "\x84\x01", 2);
> - cmd.wlen = 2;
> - cmd.rlen = 3;
> + CMD_SETUP(, "\x84\x01", 3);
>   ret = si2168_cmd_execute(client, );
>   if (ret)
>   goto err;
> @@ -286,22 +284,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
>   goto err;
>   }
>  
> - memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5);
> - cmd.wlen = 5;
> - cmd.rlen = 5;
> + CMD_SETUP(, "\x88\x02\x02\x02\x02", 5);
>   ret = si2168_cmd_execute(client, );
>   if (ret)
>   goto err;
>  
>   /* that has no big effect */
>   if (c->delivery_system == SYS_DVBT)
> - memcpy(cmd.args, "\x89\x21\x06\x11\xff\x98", 6);
> + CMD_SETUP(, "\x89\x21\x06\x11\xff\x98", 3);
>   else if (c->delivery_system == SYS_DVBC_ANNEX_A)
> - memcpy(cmd.args, "\x89\x21\x06\x11\x89\xf0", 6);
> + CMD_SETUP(, "\x89\x21\x06\x11\x89\xf0", 3);
>   else if (c->delivery_system == SYS_DVBT2)
> - memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6);
> - cmd.wlen = 6;
> - cmd.rlen = 3;
> + CMD_SETUP(, "\x89\x21\x06\x11\x89\x20", 3);
>   ret = si2168_cmd_execute(client, );
>   if (ret)
>   goto err;
> @@ -318,103 

Re: [PATCH v3] media: si2168: Refactor command setup code

2019-07-12 Thread Marc Gonzalez
+ Sean

On 12/07/2019 10:43, Uwe Kleine-König wrote:

> On Thu, Jul 04, 2019 at 12:33:22PM +0200, Marc Gonzalez wrote:
>
>> Refactor the command setup code, and let the compiler determine
>> the size of each command.
>>
>> Reviewed-by: Jonathan Neuschäfer 
>> Signed-off-by: Marc Gonzalez 
>> ---
>> Changes from v1:
>> - Use a real function to populate struct si2168_cmd *cmd, and a trivial
>> macro wrapping it (macro because sizeof).
>> Changes from v2:
>> - Fix header mess
>> - Add Jonathan's tag
>> ---
>>  drivers/media/dvb-frontends/si2168.c | 146 +--
>>  1 file changed, 45 insertions(+), 101 deletions(-)
>>
>> diff --git a/drivers/media/dvb-frontends/si2168.c 
>> b/drivers/media/dvb-frontends/si2168.c
>> index c64b360ce6b5..5e81e076369c 100644
>> --- a/drivers/media/dvb-frontends/si2168.c
>> +++ b/drivers/media/dvb-frontends/si2168.c
>> @@ -12,6 +12,16 @@
>>  
>>  static const struct dvb_frontend_ops si2168_ops;
>>  
>> +static void cmd_setup(struct si2168_cmd *cmd, char *args, int wlen, int 
>> rlen)
> 
> I'd add an "inline" here. And you could add a const for *args.

I was under the (vague) impression that it's better to let the compiler
decide when to inline, except for trivial alternatives in headers.
David Miller wrote: "Please do not use the inline directive in foo.c
files, let the compiler decide."

Antti, Sean, what do you think?

For my notes: https://gcc.gnu.org/onlinedocs/gcc/Inline.html


>> +{
>> +memcpy(cmd->args, args, wlen);
>> +cmd->wlen = wlen;
>> +cmd->rlen = rlen;
>> +}
>> +
>> +#define CMD_SETUP(cmd, args, rlen) \
>> +cmd_setup(cmd, args, sizeof(args) - 1, rlen)
> 
> Here is the chance to add some static checking. Also it is a good habit
> to put parens around macro arguments.

Wrt parens around arguments, I figured they are not required here, since they
are used as function arguments. Though you may have a valid point.

Antti, Sean?


> Something like:
> 
> #define CMD_SETUP(cmd, args, rlen) ({ \
>   BUILD_BUG_ON(sizeof((args)) - 1 > SI2168_ARGLEN);
>   cmd_setup((cmd), (args), __must_be_array((args)) + sizeof((args)) - 1, 
> (rlen));
> 
> Maybe let this macro live in drivers/media/dvb-frontends/si2168_priv.h
> where struct si2168_cmd is defined?

Antti, Sean?


> I looked over the transformations in the rest of the patch and this
> looks good.

Thanks for taking a look!

Regards.


Re: [PATCH v3] media: si2168: Refactor command setup code

2019-07-12 Thread Uwe Kleine-König
Hello,

On Thu, Jul 04, 2019 at 12:33:22PM +0200, Marc Gonzalez wrote:
> Refactor the command setup code, and let the compiler determine
> the size of each command.
> 
> Reviewed-by: Jonathan Neuschäfer 
> Signed-off-by: Marc Gonzalez 
> ---
> Changes from v1:
> - Use a real function to populate struct si2168_cmd *cmd, and a trivial
> macro wrapping it (macro because sizeof).
> Changes from v2:
> - Fix header mess
> - Add Jonathan's tag
> ---
>  drivers/media/dvb-frontends/si2168.c | 146 +--
>  1 file changed, 45 insertions(+), 101 deletions(-)
> 
> diff --git a/drivers/media/dvb-frontends/si2168.c 
> b/drivers/media/dvb-frontends/si2168.c
> index c64b360ce6b5..5e81e076369c 100644
> --- a/drivers/media/dvb-frontends/si2168.c
> +++ b/drivers/media/dvb-frontends/si2168.c
> @@ -12,6 +12,16 @@
>  
>  static const struct dvb_frontend_ops si2168_ops;
>  
> +static void cmd_setup(struct si2168_cmd *cmd, char *args, int wlen, int rlen)

I'd add an "inline" here. And you could add a const for *args.

> +{
> + memcpy(cmd->args, args, wlen);
> + cmd->wlen = wlen;
> + cmd->rlen = rlen;
> +}
> +
> +#define CMD_SETUP(cmd, args, rlen) \
> + cmd_setup(cmd, args, sizeof(args) - 1, rlen)

Here is the chance to add some static checking. Also it is a good habit
to put parens around macro arguments.

Something like:

#define CMD_SETUP(cmd, args, rlen) ({ \
BUILD_BUG_ON(sizeof((args)) - 1 > SI2168_ARGLEN);
cmd_setup((cmd), (args), __must_be_array((args)) + sizeof((args)) - 1, 
(rlen));

Maybe let this macro live in drivers/media/dvb-frontends/si2168_priv.h
where struct si2168_cmd is defined?

I looked over the transformations in the rest of the patch and this
looks good.

Best regards
Uwe


signature.asc
Description: PGP signature


[PATCH v3] media: si2168: Refactor command setup code

2019-07-04 Thread Marc Gonzalez
Refactor the command setup code, and let the compiler determine
the size of each command.

Reviewed-by: Jonathan Neuschäfer 
Signed-off-by: Marc Gonzalez 
---
Changes from v1:
- Use a real function to populate struct si2168_cmd *cmd, and a trivial
macro wrapping it (macro because sizeof).
Changes from v2:
- Fix header mess
- Add Jonathan's tag
---
 drivers/media/dvb-frontends/si2168.c | 146 +--
 1 file changed, 45 insertions(+), 101 deletions(-)

diff --git a/drivers/media/dvb-frontends/si2168.c 
b/drivers/media/dvb-frontends/si2168.c
index c64b360ce6b5..5e81e076369c 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -12,6 +12,16 @@
 
 static const struct dvb_frontend_ops si2168_ops;
 
+static void cmd_setup(struct si2168_cmd *cmd, char *args, int wlen, int rlen)
+{
+   memcpy(cmd->args, args, wlen);
+   cmd->wlen = wlen;
+   cmd->rlen = rlen;
+}
+
+#define CMD_SETUP(cmd, args, rlen) \
+   cmd_setup(cmd, args, sizeof(args) - 1, rlen)
+
 /* execute firmware command */
 static int si2168_cmd_execute(struct i2c_client *client, struct si2168_cmd 
*cmd)
 {
@@ -84,15 +94,13 @@ static int si2168_ts_bus_ctrl(struct dvb_frontend *fe, int 
acquire)
dev_dbg(>dev, "%s acquire: %d\n", __func__, acquire);
 
/* set TS_MODE property */
-   memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
+   CMD_SETUP(, "\x14\x00\x01\x10\x10\x00", 4);
if (acquire)
cmd.args[4] |= dev->ts_mode;
else
cmd.args[4] |= SI2168_TS_TRISTATE;
if (dev->ts_clock_gapped)
cmd.args[4] |= 0x40;
-   cmd.wlen = 6;
-   cmd.rlen = 4;
ret = si2168_cmd_execute(client, );
 
return ret;
@@ -116,19 +124,13 @@ static int si2168_read_status(struct dvb_frontend *fe, 
enum fe_status *status)
 
switch (c->delivery_system) {
case SYS_DVBT:
-   memcpy(cmd.args, "\xa0\x01", 2);
-   cmd.wlen = 2;
-   cmd.rlen = 13;
+   CMD_SETUP(, "\xa0\x01", 13);
break;
case SYS_DVBC_ANNEX_A:
-   memcpy(cmd.args, "\x90\x01", 2);
-   cmd.wlen = 2;
-   cmd.rlen = 9;
+   CMD_SETUP(, "\x90\x01", 9);
break;
case SYS_DVBT2:
-   memcpy(cmd.args, "\x50\x01", 2);
-   cmd.wlen = 2;
-   cmd.rlen = 14;
+   CMD_SETUP(, "\x50\x01", 14);
break;
default:
ret = -EINVAL;
@@ -165,9 +167,7 @@ static int si2168_read_status(struct dvb_frontend *fe, enum 
fe_status *status)
 
/* BER */
if (*status & FE_HAS_VITERBI) {
-   memcpy(cmd.args, "\x82\x00", 2);
-   cmd.wlen = 2;
-   cmd.rlen = 3;
+   CMD_SETUP(, "\x82\x00", 3);
ret = si2168_cmd_execute(client, );
if (ret)
goto err;
@@ -198,9 +198,7 @@ static int si2168_read_status(struct dvb_frontend *fe, enum 
fe_status *status)
 
/* UCB */
if (*status & FE_HAS_SYNC) {
-   memcpy(cmd.args, "\x84\x01", 2);
-   cmd.wlen = 2;
-   cmd.rlen = 3;
+   CMD_SETUP(, "\x84\x01", 3);
ret = si2168_cmd_execute(client, );
if (ret)
goto err;
@@ -286,22 +284,18 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
goto err;
}
 
-   memcpy(cmd.args, "\x88\x02\x02\x02\x02", 5);
-   cmd.wlen = 5;
-   cmd.rlen = 5;
+   CMD_SETUP(, "\x88\x02\x02\x02\x02", 5);
ret = si2168_cmd_execute(client, );
if (ret)
goto err;
 
/* that has no big effect */
if (c->delivery_system == SYS_DVBT)
-   memcpy(cmd.args, "\x89\x21\x06\x11\xff\x98", 6);
+   CMD_SETUP(, "\x89\x21\x06\x11\xff\x98", 3);
else if (c->delivery_system == SYS_DVBC_ANNEX_A)
-   memcpy(cmd.args, "\x89\x21\x06\x11\x89\xf0", 6);
+   CMD_SETUP(, "\x89\x21\x06\x11\x89\xf0", 3);
else if (c->delivery_system == SYS_DVBT2)
-   memcpy(cmd.args, "\x89\x21\x06\x11\x89\x20", 6);
-   cmd.wlen = 6;
-   cmd.rlen = 3;
+   CMD_SETUP(, "\x89\x21\x06\x11\x89\x20", 3);
ret = si2168_cmd_execute(client, );
if (ret)
goto err;
@@ -318,103 +312,77 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
goto err;
}
 
-   memcpy(cmd.args, "\x51\x03", 2);
-   cmd.wlen = 2;
-   cmd.rlen = 12;
+   CMD_SETUP(, "\x51\x03", 12);
ret = si2168_cmd_execute(client, );
if (ret)
goto err;
 
-   memcpy(cmd.args, "\x12\x08\x04", 3);
-   cmd.wlen = 3;
-   cmd.rlen = 3;
+   CMD_SETUP(, "\x12\x08\x04", 3);
ret = si2168_cmd_execute(client, );
if (ret)