Em 28-07-2010 12:14, Maxim Levitsky escreveu: > Also reuse LIRC_SET_MEASURE_CARRIER_MODE as LIRC_SET_LEARN_MODE > (LIRC_SET_LEARN_MODE will start carrier reports if possible, and > tune receiver to wide band mode) > > This IOCTL isn't yet used by lirc, so this won't break userspace. > > Signed-off-by: Maxim Levitsky <maximlevitsky@xxxxxxxxx> > --- > drivers/media/IR/ir-core-priv.h | 2 + > drivers/media/IR/ir-lirc-codec.c | 100 ++++++++++++++++++++++++++++++++++---- > include/media/ir-core.h | 11 ++++ > include/media/lirc.h | 4 +- > 4 files changed, 105 insertions(+), 12 deletions(-) > > diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h > index 3eafdb7..4ed170d 100644 > --- a/drivers/media/IR/ir-core-priv.h > +++ b/drivers/media/IR/ir-core-priv.h > @@ -77,6 +77,8 @@ struct ir_raw_event_ctrl { > struct lirc_codec { > struct ir_input_dev *ir_dev; > struct lirc_driver *drv; > + int timeout_report; > + int carrier_low; > } lirc; > }; > > diff --git a/drivers/media/IR/ir-lirc-codec.c b/drivers/media/IR/ir-lirc-codec.c > index 8ca01fd..0f3969c 100644 > --- a/drivers/media/IR/ir-lirc-codec.c > +++ b/drivers/media/IR/ir-lirc-codec.c > @@ -96,13 +96,13 @@ out: > return ret; > } > > -static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) > +static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long __user arg) > { > struct lirc_codec *lirc; > struct ir_input_dev *ir_dev; > int ret = 0; > void *drv_data; > - unsigned long val; > + unsigned long val = 0; > > lirc = lirc_get_pdata(filep); > if (!lirc) > @@ -116,10 +116,21 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar > > switch (cmd) { > case LIRC_SET_TRANSMITTER_MASK: > + case LIRC_SET_SEND_CARRIER: > + case LIRC_SET_SEND_MODE: > + case LIRC_SET_REC_TIMEOUT: > + case LIRC_SET_REC_TIMEOUT_REPORTS: > + case LIRC_SET_LEARN_MODE: > + case LIRC_SET_REC_CARRIER: > + case LIRC_SET_REC_CARRIER_RANGE: > + case LIRC_SET_SEND_DUTY_CYCLE: > ret = get_user(val, (unsigned long *)arg); > if (ret) > return ret; > + } As, in all cases, the argument is an __u32, you can just use this, to get the arguments for all LIRC_SET_* cases: if (_IOC_DIR(cmd) & _IOC_WRITE) { ret = get_user(val, (unsigned long *)arg); if (ret) return ret; } > + switch (cmd) { > + case LIRC_SET_TRANSMITTER_MASK: > if (ir_dev->props && ir_dev->props->s_tx_mask) > ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); > else > @@ -127,10 +138,6 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar > break; > > case LIRC_SET_SEND_CARRIER: > - ret = get_user(val, (unsigned long *)arg); > - if (ret) > - return ret; > - > if (ir_dev->props && ir_dev->props->s_tx_carrier) > ir_dev->props->s_tx_carrier(drv_data, (u32)val); > else > @@ -143,14 +150,75 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar > break; > > case LIRC_SET_SEND_MODE: > - ret = get_user(val, (unsigned long *)arg); > - if (ret) > - return ret; > - > if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) > return -EINVAL; > break; > > + case LIRC_GET_REC_RESOLUTION: > + val = ir_dev->props->rx_resolution; > + ret = put_user(val, (unsigned long *)arg); > + break; You can use something like this, to handle the LIRC_GET* cases: switch (cmd) { ... case LIRC_GET_REC_RESOLUTION: val = ir_dev->props->rx_resolution; break; ... } if (_IOC_DIR(cmd) & _IOC_READ) { ret = put_user(val, (unsigned long *)arg); if (ret) return ret; } > + > + case LIRC_SET_REC_TIMEOUT: > + if (val < ir_dev->props->min_timeout || > + val > ir_dev->props->max_timeout) > + return -EINVAL; > + > + ir_dev->props->timeout = val; > + break; > + > + case LIRC_SET_REC_TIMEOUT_REPORTS: > + ir_dev->raw->lirc.timeout_report = !!val; > + return 0; > + > + case LIRC_GET_MIN_TIMEOUT: > + > + if (!ir_dev->props->max_timeout) > + return -ENOSYS; > + > + ret = put_user(ir_dev->props->min_timeout, (unsigned long *)arg); > + break; > + case LIRC_GET_MAX_TIMEOUT: > + if (!ir_dev->props->max_timeout) > + return -ENOSYS; > + > + ret = put_user(ir_dev->props->max_timeout, (unsigned long *)arg); > + break; > + > + case LIRC_SET_LEARN_MODE: > + if (ir_dev->props->s_learning_mode) > + return ir_dev->props->s_learning_mode( > + ir_dev->props->priv, !!val); > + else > + return -ENOSYS; > + > + case LIRC_SET_REC_CARRIER: > + if (ir_dev->props->s_rx_carrier_range) > + ret = ir_dev->props->s_rx_carrier_range( > + ir_dev->props->priv, > + ir_dev->raw->lirc.carrier_low, val); > + else > + return -ENOSYS; > + > + if (!ret) > + ir_dev->raw->lirc.carrier_low = 0; > + break; > + > + case LIRC_SET_REC_CARRIER_RANGE: > + if (val >= 0) > + ir_dev->raw->lirc.carrier_low = val; > + break; > + case LIRC_SET_SEND_DUTY_CYCLE: > + > + if (!ir_dev->props->s_tx_duty_cycle) > + return -ENOSYS; > + > + if (val <= 0 || val >= 100) > + return -EINVAL; > + > + ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val); > + break; > + > default: > return lirc_dev_fop_ioctl(filep, cmd, arg); > } > @@ -200,13 +268,25 @@ static int ir_lirc_register(struct input_dev *input_dev) > > features = LIRC_CAN_REC_MODE2; > if (ir_dev->props->tx_ir) { > + > features |= LIRC_CAN_SEND_PULSE; > if (ir_dev->props->s_tx_mask) > features |= LIRC_CAN_SET_TRANSMITTER_MASK; > if (ir_dev->props->s_tx_carrier) > features |= LIRC_CAN_SET_SEND_CARRIER; > + > + if (ir_dev->props->s_tx_duty_cycle) > + features |= LIRC_CAN_SET_REC_DUTY_CYCLE; > } > > + if (ir_dev->props->s_rx_carrier_range) > + features |= LIRC_CAN_SET_REC_CARRIER | > + LIRC_CAN_SET_REC_CARRIER_RANGE; > + > + if (ir_dev->props->s_learning_mode) > + features |= LIRC_CAN_LEARN_MODE; > + > + > snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", > ir_dev->driver_name); > drv->minor = -1; > diff --git a/include/media/ir-core.h b/include/media/ir-core.h > index 53ce966..46cc6c5 100644 > --- a/include/media/ir-core.h > +++ b/include/media/ir-core.h > @@ -44,6 +44,8 @@ enum rc_driver_type { > * @timeout: optional time after which device stops sending data > * @min_timeout: minimum timeout supported by device > * @max_timeout: maximum timeout supported by device > + * @rx_resolution : resolution (in ns) of input sampler > + * @tx_resolution: resolution (in ns) of output sampler > * @priv: driver-specific data, to be used on the callbacks > * @change_protocol: allow changing the protocol used on hardware decoders > * @open: callback to allow drivers to enable polling/irq when IR input device > @@ -52,9 +54,12 @@ enum rc_driver_type { > * is opened. > * @s_tx_mask: set transmitter mask (for devices with multiple tx outputs) > * @s_tx_carrier: set transmit carrier frequency > + * @s_tx_duty_cycle: set transmit duty cycle (0% - 100%) > + * @s_rx_carrier: inform driver about carrier it is expected to handle > * @tx_ir: transmit IR > * @s_idle: optional: enable/disable hardware idle mode, upon which, > device doesn't interrupt host untill it sees IR data > + * @s_learning_mode: enable learning mode > */ > struct ir_dev_props { > enum rc_driver_type driver_type; > @@ -65,6 +70,8 @@ struct ir_dev_props { > u64 min_timeout; > u64 max_timeout; > > + u32 rx_resolution; > + u32 tx_resolution; > > void *priv; > int (*change_protocol)(void *priv, u64 ir_type); > @@ -72,8 +79,12 @@ struct ir_dev_props { > void (*close)(void *priv); > int (*s_tx_mask)(void *priv, u32 mask); > int (*s_tx_carrier)(void *priv, u32 carrier); > + int (*s_tx_duty_cycle) (void *priv, u32 duty_cycle); > + int (*s_rx_carrier_range) (void *priv, u32 min, u32 max); > int (*tx_ir)(void *priv, int *txbuf, u32 n); > void (*s_idle) (void *priv, int enable); > + int (*s_learning_mode) (void *priv, int enable); > + > }; > > struct ir_input_dev { > diff --git a/include/media/lirc.h b/include/media/lirc.h > index 42c467c..09a9753 100644 > --- a/include/media/lirc.h > +++ b/include/media/lirc.h > @@ -76,7 +76,7 @@ > #define LIRC_CAN_SET_REC_TIMEOUT 0x10000000 > #define LIRC_CAN_SET_REC_FILTER 0x08000000 > > -#define LIRC_CAN_MEASURE_CARRIER 0x02000000 > +#define LIRC_CAN_LEARN_MODE 0x02000000 > > #define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) > #define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) > @@ -145,7 +145,7 @@ > * if enabled from the next key press on the driver will send > * LIRC_MODE2_FREQUENCY packets > */ > -#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32) > +#define LIRC_SET_LEARN_MODE _IOW('i', 0x0000001d, __u32) > > /* > * to set a range use -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html