diff options
author | Denys Drozdov <denys.drozdov@toradex.com> | 2022-01-12 14:02:54 +0200 |
---|---|---|
committer | Denys Drozdov <denys.drozdov@toradex.com> | 2022-01-12 14:02:54 +0200 |
commit | 0021a0c8a58ff37f62f4d2424dca7c6a6d9f233d (patch) | |
tree | 2dd57ed085b1fdf17f9e79e963f1d02051bc76d3 /drivers/media | |
parent | 5b3083e6d7a98e4afec861060537004772dc4acf (diff) | |
parent | 712fcc850e5a6d0867b0d97a0b79f1addd01998f (diff) |
Merge remote-tracking branch 'fscl/5.4-2.3.x-imx' into toradex_5.4-2.3.x-imx-v5.4.161
Conflicts:
drivers/net/phy/micrel.c
drivers/usb/chipidea/core.c
Diffstat (limited to 'drivers/media')
27 files changed, 171 insertions, 68 deletions
diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c index e4528784f847..fff212c0bf3b 100644 --- a/drivers/media/dvb-frontends/mn88443x.c +++ b/drivers/media/dvb-frontends/mn88443x.c @@ -204,11 +204,18 @@ struct mn88443x_priv { struct regmap *regmap_t; }; -static void mn88443x_cmn_power_on(struct mn88443x_priv *chip) +static int mn88443x_cmn_power_on(struct mn88443x_priv *chip) { + struct device *dev = &chip->client_s->dev; struct regmap *r_t = chip->regmap_t; + int ret; - clk_prepare_enable(chip->mclk); + ret = clk_prepare_enable(chip->mclk); + if (ret) { + dev_err(dev, "Failed to prepare and enable mclk: %d\n", + ret); + return ret; + } gpiod_set_value_cansleep(chip->reset_gpio, 1); usleep_range(100, 1000); @@ -222,6 +229,8 @@ static void mn88443x_cmn_power_on(struct mn88443x_priv *chip) } else { regmap_write(r_t, HIZSET3, 0x8f); } + + return 0; } static void mn88443x_cmn_power_off(struct mn88443x_priv *chip) @@ -738,7 +747,10 @@ static int mn88443x_probe(struct i2c_client *client, chip->fe.demodulator_priv = chip; i2c_set_clientdata(client, chip); - mn88443x_cmn_power_on(chip); + ret = mn88443x_cmn_power_on(chip); + if (ret) + goto err_i2c_t; + mn88443x_s_sleep(chip); mn88443x_t_sleep(chip); diff --git a/drivers/media/firewire/firedtv-avc.c b/drivers/media/firewire/firedtv-avc.c index 2bf9467b917d..71991f8638e6 100644 --- a/drivers/media/firewire/firedtv-avc.c +++ b/drivers/media/firewire/firedtv-avc.c @@ -1165,7 +1165,11 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) read_pos += program_info_length; write_pos += program_info_length; } - while (read_pos < length) { + while (read_pos + 4 < length) { + if (write_pos + 4 >= sizeof(c->operand) - 4) { + ret = -EINVAL; + goto out; + } c->operand[write_pos++] = msg[read_pos++]; c->operand[write_pos++] = msg[read_pos++]; c->operand[write_pos++] = msg[read_pos++]; @@ -1177,13 +1181,17 @@ int avc_ca_pmt(struct firedtv *fdtv, char *msg, int length) c->operand[write_pos++] = es_info_length >> 8; c->operand[write_pos++] = es_info_length & 0xff; if (es_info_length > 0) { + if (read_pos >= length) { + ret = -EINVAL; + goto out; + } pmt_cmd_id = msg[read_pos++]; if (pmt_cmd_id != 1 && pmt_cmd_id != 4) dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n", pmt_cmd_id); - if (es_info_length > sizeof(c->operand) - 4 - - write_pos) { + if (es_info_length > sizeof(c->operand) - 4 - write_pos || + es_info_length > length - read_pos) { ret = -EINVAL; goto out; } diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c index 9363d005e2b6..e0d57e09dab0 100644 --- a/drivers/media/firewire/firedtv-ci.c +++ b/drivers/media/firewire/firedtv-ci.c @@ -134,6 +134,8 @@ static int fdtv_ca_pmt(struct firedtv *fdtv, void *arg) } else { data_length = msg->msg[3]; } + if (data_length > sizeof(msg->msg) - data_pos) + return -EINVAL; return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length); } diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index 92376592455e..56674173524f 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -791,6 +791,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE | RC_PROTO_BIT_RC6_6A_32; ir_codes = RC_MAP_HAUPPAUGE; + ir->polling_interval = 125; probe_tx = true; break; } diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c index dc23b9ed510a..18440c5104ad 100644 --- a/drivers/media/i2c/mt9p031.c +++ b/drivers/media/i2c/mt9p031.c @@ -78,7 +78,9 @@ #define MT9P031_PIXEL_CLOCK_INVERT (1 << 15) #define MT9P031_PIXEL_CLOCK_SHIFT(n) ((n) << 8) #define MT9P031_PIXEL_CLOCK_DIVIDE(n) ((n) << 0) -#define MT9P031_FRAME_RESTART 0x0b +#define MT9P031_RESTART 0x0b +#define MT9P031_FRAME_PAUSE_RESTART (1 << 1) +#define MT9P031_FRAME_RESTART (1 << 0) #define MT9P031_SHUTTER_DELAY 0x0c #define MT9P031_RST 0x0d #define MT9P031_RST_ENABLE 1 @@ -445,9 +447,23 @@ static int mt9p031_set_params(struct mt9p031 *mt9p031) static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable) { struct mt9p031 *mt9p031 = to_mt9p031(subdev); + struct i2c_client *client = v4l2_get_subdevdata(subdev); + int val; int ret; if (!enable) { + /* enable pause restart */ + val = MT9P031_FRAME_PAUSE_RESTART; + ret = mt9p031_write(client, MT9P031_RESTART, val); + if (ret < 0) + return ret; + + /* enable restart + keep pause restart set */ + val |= MT9P031_FRAME_RESTART; + ret = mt9p031_write(client, MT9P031_RESTART, val); + if (ret < 0) + return ret; + /* Stop sensor readout */ ret = mt9p031_set_output_control(mt9p031, MT9P031_OUTPUT_CONTROL_CEN, 0); @@ -467,6 +483,16 @@ static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable) if (ret < 0) return ret; + /* + * - clear pause restart + * - don't clear restart as clearing restart manually can cause + * undefined behavior + */ + val = MT9P031_FRAME_RESTART; + ret = mt9p031_write(client, MT9P031_RESTART, val); + if (ret < 0) + return ret; + return mt9p031_pll_enable(mt9p031); } diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index 18a2027ba145..5faffedb0feb 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -1247,13 +1247,13 @@ tda1997x_parse_infoframe(struct tda1997x_state *state, u16 addr) { struct v4l2_subdev *sd = &state->sd; union hdmi_infoframe frame; - u8 buffer[40]; + u8 buffer[40] = { 0 }; u8 reg; int len, err; /* read data */ len = io_readn(sd, addr, sizeof(buffer), buffer); - err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); + err = hdmi_infoframe_unpack(&frame, buffer, len); if (err) { v4l_err(state->client, "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", @@ -1927,13 +1927,13 @@ static int tda1997x_log_infoframe(struct v4l2_subdev *sd, int addr) { struct tda1997x_state *state = to_state(sd); union hdmi_infoframe frame; - u8 buffer[40]; + u8 buffer[40] = { 0 }; int len, err; /* read data */ len = io_readn(sd, addr, sizeof(buffer), buffer); v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len); - err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)); + err = hdmi_infoframe_unpack(&frame, buffer, len); if (err) { v4l_err(state->client, "failed parsing %d byte infoframe: 0x%04x/0x%02x\n", diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c index a8e980c6dacb..50772c2611ca 100644 --- a/drivers/media/pci/cx23885/cx23885-alsa.c +++ b/drivers/media/pci/cx23885/cx23885-alsa.c @@ -550,7 +550,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, THIS_MODULE, sizeof(struct cx23885_audio_dev), &card); if (err < 0) - goto error; + goto error_msg; chip = (struct cx23885_audio_dev *) card->private_data; chip->dev = dev; @@ -576,6 +576,7 @@ struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) error: snd_card_free(card); +error_msg: pr_err("%s(): Failed to register analog audio adapter\n", __func__); diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c index 80a7c41baa90..eb5621c9ebf8 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c @@ -258,19 +258,24 @@ static irqreturn_t netup_unidvb_isr(int irq, void *dev_id) if ((reg40 & AVL_IRQ_ASSERTED) != 0) { /* IRQ is being signaled */ reg_isr = readw(ndev->bmmio0 + REG_ISR); - if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) { - iret = netup_i2c_interrupt(&ndev->i2c[0]); - } else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) { - iret = netup_i2c_interrupt(&ndev->i2c[1]); - } else if (reg_isr & NETUP_UNIDVB_IRQ_SPI) { + if (reg_isr & NETUP_UNIDVB_IRQ_SPI) iret = netup_spi_interrupt(ndev->spi); - } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) { - iret = netup_dma_interrupt(&ndev->dma[0]); - } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) { - iret = netup_dma_interrupt(&ndev->dma[1]); - } else if (reg_isr & NETUP_UNIDVB_IRQ_CI) { - iret = netup_ci_interrupt(ndev); + else if (!ndev->old_fw) { + if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) { + iret = netup_i2c_interrupt(&ndev->i2c[0]); + } else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) { + iret = netup_i2c_interrupt(&ndev->i2c[1]); + } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) { + iret = netup_dma_interrupt(&ndev->dma[0]); + } else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) { + iret = netup_dma_interrupt(&ndev->dma[1]); + } else if (reg_isr & NETUP_UNIDVB_IRQ_CI) { + iret = netup_ci_interrupt(ndev); + } else { + goto err; + } } else { +err: dev_err(&pci_dev->dev, "%s(): unknown interrupt 0x%x\n", __func__, reg_isr); diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c index cc2ff40d060d..acf64723f938 100644 --- a/drivers/media/platform/mtk-vpu/mtk_vpu.c +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c @@ -809,7 +809,8 @@ static int mtk_vpu_probe(struct platform_device *pdev) vpu->wdt.wq = create_singlethread_workqueue("vpu_wdt"); if (!vpu->wdt.wq) { dev_err(dev, "initialize wdt workqueue failed\n"); - return -ENOMEM; + ret = -ENOMEM; + goto clk_unprepare; } INIT_WORK(&vpu->wdt.ws, vpu_wdt_reset_func); mutex_init(&vpu->vpu_mutex); @@ -908,6 +909,8 @@ disable_vpu_clk: vpu_clock_disable(vpu); workqueue_destroy: destroy_workqueue(vpu->wdt.wq); +clk_unprepare: + clk_unprepare(vpu->clk); return ret; } diff --git a/drivers/media/platform/rcar-vin/rcar-csi2.c b/drivers/media/platform/rcar-vin/rcar-csi2.c index d27eccfa57ca..e01f22bf826d 100644 --- a/drivers/media/platform/rcar-vin/rcar-csi2.c +++ b/drivers/media/platform/rcar-vin/rcar-csi2.c @@ -488,6 +488,8 @@ static int rcsi2_start_receiver(struct rcar_csi2 *priv) /* Code is validated in set_fmt. */ format = rcsi2_code_to_fmt(priv->mf.code); + if (!format) + return -EINVAL; /* * Enable all supported CSI-2 channels with virtual channel and diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index b776f83e395e..9faecd049002 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c @@ -1279,11 +1279,15 @@ static int s5p_mfc_probe(struct platform_device *pdev) spin_lock_init(&dev->condlock); dev->plat_dev = pdev; if (!dev->plat_dev) { - dev_err(&pdev->dev, "No platform data specified\n"); + mfc_err("No platform data specified\n"); return -ENODEV; } dev->variant = of_device_get_match_data(&pdev->dev); + if (!dev->variant) { + dev_err(&pdev->dev, "Failed to get device MFC hardware variant information\n"); + return -ENOENT; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->regs_base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index d41475f56ab5..72798aae7a62 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -135,6 +135,7 @@ struct stm32_dcmi { int sequence; struct list_head buffers; struct dcmi_buf *active; + int irq; struct v4l2_device v4l2_dev; struct video_device *vdev; @@ -1720,6 +1721,14 @@ static int dcmi_graph_notify_complete(struct v4l2_async_notifier *notifier) return ret; } + ret = devm_request_threaded_irq(dcmi->dev, dcmi->irq, dcmi_irq_callback, + dcmi_irq_thread, IRQF_ONESHOT, + dev_name(dcmi->dev), dcmi); + if (ret) { + dev_err(dcmi->dev, "Unable to request irq %d\n", dcmi->irq); + return ret; + } + return 0; } @@ -1881,6 +1890,8 @@ static int dcmi_probe(struct platform_device *pdev) if (irq <= 0) return irq ? irq : -ENXIO; + dcmi->irq = irq; + dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!dcmi->res) { dev_err(&pdev->dev, "Could not get resource\n"); @@ -1893,14 +1904,6 @@ static int dcmi_probe(struct platform_device *pdev) return PTR_ERR(dcmi->regs); } - ret = devm_request_threaded_irq(&pdev->dev, irq, dcmi_irq_callback, - dcmi_irq_thread, IRQF_ONESHOT, - dev_name(&pdev->dev), dcmi); - if (ret) { - dev_err(&pdev->dev, "Unable to request irq %d\n", irq); - return ret; - } - mclk = devm_clk_get(&pdev->dev, "mclk"); if (IS_ERR(mclk)) { if (PTR_ERR(mclk) != -EPROBE_DEFER) diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index 112376873167..484046471c03 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -1279,7 +1279,7 @@ static int wl1273_fm_vidioc_querycap(struct file *file, void *priv, strscpy(capability->driver, WL1273_FM_DRIVER_NAME, sizeof(capability->driver)); - strscpy(capability->card, "Texas Instruments Wl1273 FM Radio", + strscpy(capability->card, "TI Wl1273 FM Radio", sizeof(capability->card)); strscpy(capability->bus_info, radio->bus_type, sizeof(capability->bus_info)); diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index f491420d7b53..a972c0705ac7 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -11,7 +11,7 @@ /* driver definitions */ #define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>"; -#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" +#define DRIVER_CARD "Silicon Labs Si470x FM Radio" #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers" #define DRIVER_VERSION "1.0.2" diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c index fedff68d8c49..3f8634a46573 100644 --- a/drivers/media/radio/si470x/radio-si470x-usb.c +++ b/drivers/media/radio/si470x/radio-si470x-usb.c @@ -16,7 +16,7 @@ /* driver definitions */ #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>" -#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver" +#define DRIVER_CARD "Silicon Labs Si470x FM Radio" #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers" #define DRIVER_VERSION "1.0.10" diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 4b8aee390518..742b7f41b75f 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -283,7 +283,7 @@ static irqreturn_t ite_cir_isr(int irq, void *data) } /* check for the receive interrupt */ - if (iflags & ITE_IRQ_RX_FIFO) { + if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) { /* read the FIFO bytes */ rx_bytes = dev->params.get_rx_bytes(dev, rx_buf, diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index c68e52c17ae1..31e56f4f3479 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -1386,6 +1386,7 @@ static void mceusb_dev_recv(struct urb *urb) case -ECONNRESET: case -ENOENT: case -EILSEQ: + case -EPROTO: case -ESHUTDOWN: usb_unlink_urb(urb); return; diff --git a/drivers/media/spi/cxd2880-spi.c b/drivers/media/spi/cxd2880-spi.c index 93194f03764d..11273be702b6 100644 --- a/drivers/media/spi/cxd2880-spi.c +++ b/drivers/media/spi/cxd2880-spi.c @@ -618,7 +618,7 @@ fail_frontend: fail_attach: dvb_unregister_adapter(&dvb_spi->adapter); fail_adapter: - if (!dvb_spi->vcc_supply) + if (dvb_spi->vcc_supply) regulator_disable(dvb_spi->vcc_supply); fail_regulator: kfree(dvb_spi); diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c index 8de18da0c4bd..5aa9c501ed9c 100644 --- a/drivers/media/usb/dvb-usb/az6027.c +++ b/drivers/media/usb/dvb-usb/az6027.c @@ -391,6 +391,7 @@ static struct rc_map_table rc_map_az6027_table[] = { /* remote control stuff (does not work with my box) */ static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state) { + *state = REMOTE_NO_KEY_PRESSED; return 0; } diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index 59ce2dec11e9..9c1ebea68b54 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c @@ -223,7 +223,7 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) u8 *buf; int rc; - buf = kmalloc(2, GFP_KERNEL); + buf = kzalloc(2, GFP_KERNEL); if (!buf) return -ENOMEM; diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 5983e72a0622..3e96b4b711d7 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -4029,8 +4029,11 @@ static void em28xx_usb_disconnect(struct usb_interface *intf) em28xx_close_extension(dev); - if (dev->dev_next) + if (dev->dev_next) { + em28xx_close_extension(dev->dev_next); em28xx_release_resources(dev->dev_next); + } + em28xx_release_resources(dev); if (dev->dev_next) { diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 3daa64bb1e1d..af9216278024 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -1152,8 +1152,9 @@ int em28xx_suspend_extension(struct em28xx *dev) dev_info(&dev->intf->dev, "Suspending extensions\n"); mutex_lock(&em28xx_devlist_mutex); list_for_each_entry(ops, &em28xx_extension_devlist, next) { - if (ops->suspend) - ops->suspend(dev); + if (!ops->suspend) + continue; + ops->suspend(dev); if (dev->dev_next) ops->suspend(dev->dev_next); } diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index c46cbcfafab3..8874b0b922ee 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -854,8 +854,7 @@ static int vidioc_querycap(struct file *file, void *priv, struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev; strscpy(cap->driver, "tm6000", sizeof(cap->driver)); - strscpy(cap->card, "Trident TVMaster TM5600/6000/6010", - sizeof(cap->card)); + strscpy(cap->card, "Trident TM5600/6000/6010", sizeof(cap->card)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 40ca1d4e0348..378cfc46fc19 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1972,6 +1972,7 @@ int uvc_register_video_device(struct uvc_device *dev, const struct v4l2_file_operations *fops, const struct v4l2_ioctl_ops *ioctl_ops) { + const char *name; int ret; /* Initialize the video buffers queue. */ @@ -2000,16 +2001,20 @@ int uvc_register_video_device(struct uvc_device *dev, case V4L2_BUF_TYPE_VIDEO_CAPTURE: default: vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; + name = "Video Capture"; break; case V4L2_BUF_TYPE_VIDEO_OUTPUT: vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + name = "Video Output"; break; case V4L2_BUF_TYPE_META_CAPTURE: vdev->device_caps = V4L2_CAP_META_CAPTURE | V4L2_CAP_STREAMING; + name = "Metadata"; break; } - strscpy(vdev->name, dev->name, sizeof(vdev->name)); + snprintf(vdev->name, sizeof(vdev->name), "%s %u", name, + stream->header.bTerminalLink); /* * Set the driver data before calling video_register_device, otherwise diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index db7f8f8ee2f9..3126ee9e965c 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -467,10 +467,13 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, uvc_simplify_fraction(&timeperframe.numerator, &timeperframe.denominator, 8, 333); - if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { parm->parm.capture.timeperframe = timeperframe; - else + parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; + } else { parm->parm.output.timeperframe = timeperframe; + parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; + } return 0; } diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 5d095b2a0346..96b85d66e7a8 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -112,6 +112,11 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, case 5: /* Invalid unit */ case 6: /* Invalid control */ case 7: /* Invalid Request */ + /* + * The firmware has not properly implemented + * the control or there has been a HW error. + */ + return -EIO; case 8: /* Invalid value within range */ return -EINVAL; default: /* reserved or unknown */ diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 8d23be83432d..833fcffb6149 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -918,7 +918,7 @@ static void v4l_print_default(const void *arg, bool write_only) pr_cont("driver-specific ioctl\n"); } -static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) +static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl) { __u32 i; @@ -927,23 +927,41 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) for (i = 0; i < c->count; i++) c->controls[i].reserved2[0] = 0; - /* V4L2_CID_PRIVATE_BASE cannot be used as control class - when using extended controls. - Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL - is it allowed for backwards compatibility. - */ - if (!allow_priv && c->which == V4L2_CID_PRIVATE_BASE) - return 0; - if (!c->which) - return 1; + switch (c->which) { + case V4L2_CID_PRIVATE_BASE: + /* + * V4L2_CID_PRIVATE_BASE cannot be used as control class + * when using extended controls. + * Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL + * is it allowed for backwards compatibility. + */ + if (ioctl == VIDIOC_G_CTRL || ioctl == VIDIOC_S_CTRL) + return false; + break; + case V4L2_CTRL_WHICH_DEF_VAL: + /* Default value cannot be changed */ + if (ioctl == VIDIOC_S_EXT_CTRLS || + ioctl == VIDIOC_TRY_EXT_CTRLS) { + c->error_idx = c->count; + return false; + } + return true; + case V4L2_CTRL_WHICH_CUR_VAL: + return true; + case V4L2_CTRL_WHICH_REQUEST_VAL: + c->error_idx = c->count; + return false; + } + /* Check that all controls are from the same control class. */ for (i = 0; i < c->count; i++) { if (V4L2_CTRL_ID2WHICH(c->controls[i].id) != c->which) { - c->error_idx = i; - return 0; + c->error_idx = ioctl == VIDIOC_TRY_EXT_CTRLS ? i : + c->count; + return false; } } - return 1; + return true; } static int check_fmt(struct file *file, enum v4l2_buf_type type) @@ -2147,7 +2165,7 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, ctrls.controls = &ctrl; ctrl.id = p->id; ctrl.value = p->value; - if (check_ext_ctrls(&ctrls, 1)) { + if (check_ext_ctrls(&ctrls, VIDIOC_G_CTRL)) { int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); if (ret == 0) @@ -2181,7 +2199,7 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, ctrls.controls = &ctrl; ctrl.id = p->id; ctrl.value = p->value; - if (check_ext_ctrls(&ctrls, 1)) + if (check_ext_ctrls(&ctrls, VIDIOC_S_CTRL)) return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); return -EINVAL; } @@ -2203,8 +2221,8 @@ static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, vfd, vfd->v4l2_dev->mdev, p); if (ops->vidioc_g_ext_ctrls == NULL) return -ENOTTY; - return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : - -EINVAL; + return check_ext_ctrls(p, VIDIOC_G_EXT_CTRLS) ? + ops->vidioc_g_ext_ctrls(file, fh, p) : -EINVAL; } static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, @@ -2224,8 +2242,8 @@ static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, vfd, vfd->v4l2_dev->mdev, p); if (ops->vidioc_s_ext_ctrls == NULL) return -ENOTTY; - return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : - -EINVAL; + return check_ext_ctrls(p, VIDIOC_S_EXT_CTRLS) ? + ops->vidioc_s_ext_ctrls(file, fh, p) : -EINVAL; } static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, @@ -2245,8 +2263,8 @@ static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, vfd, vfd->v4l2_dev->mdev, p); if (ops->vidioc_try_ext_ctrls == NULL) return -ENOTTY; - return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : - -EINVAL; + return check_ext_ctrls(p, VIDIOC_TRY_EXT_CTRLS) ? + ops->vidioc_try_ext_ctrls(file, fh, p) : -EINVAL; } /* |