diff options
Diffstat (limited to 'drivers/media/usb')
36 files changed, 319 insertions, 281 deletions
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c index 87c12930416f..19cd64c95bb8 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -488,7 +488,7 @@ static void airspy_disconnect(struct usb_interface *intf) /* Videobuf2 operations */ static int airspy_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, - unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) + unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { struct airspy *s = vb2_get_drv_priv(vq); @@ -1072,7 +1072,7 @@ static int airspy_probe(struct usb_interface *intf, if (ret) { dev_err(s->dev, "Failed to register as video device (%d)\n", ret); - goto err_unregister_v4l2_dev; + goto err_free_controls; } dev_info(s->dev, "Registered as %s\n", video_device_node_name(&s->vdev)); diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c index b4efc103ae57..e0930ce59b8d 100644 --- a/drivers/media/usb/au0828/au0828-vbi.c +++ b/drivers/media/usb/au0828/au0828-vbi.c @@ -32,7 +32,7 @@ static int vbi_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { struct au0828_dev *dev = vb2_get_drv_priv(vq); unsigned long size = dev->vbi_width * dev->vbi_height * 2; diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 7d0ec4cb248c..82b026985868 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -698,7 +698,7 @@ int au0828_v4l2_device_register(struct usb_interface *interface, static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { struct au0828_dev *dev = vb2_get_drv_priv(vq); unsigned long size = dev->height * dev->bytesperline; diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c index 00da024b47a6..29d450c15f29 100644 --- a/drivers/media/usb/cx231xx/cx231xx-417.c +++ b/drivers/media/usb/cx231xx/cx231xx-417.c @@ -1570,10 +1570,12 @@ static int vidioc_s_ctrl(struct file *file, void *priv, { struct cx231xx_fh *fh = file->private_data; struct cx231xx *dev = fh->dev; + struct v4l2_subdev *sd; dprintk(3, "enter vidioc_s_ctrl()\n"); /* Update the A/V core */ - call_all(dev, core, s_ctrl, ctl); + v4l2_device_for_each_subdev(sd, &dev->v4l2_dev) + v4l2_s_ctrl(NULL, sd->ctrl_handler, ctl); dprintk(3, "exit vidioc_s_ctrl()\n"); return 0; } diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c index eabede44ad88..ca018cd3fcd4 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.c +++ b/drivers/media/usb/dvb-usb-v2/af9035.c @@ -496,7 +496,8 @@ static int af9035_identify_state(struct dvb_usb_device *d, const char **name) { struct state *state = d_to_priv(d); struct usb_interface *intf = d->intf; - int ret; + int ret, ts_mode_invalid; + u8 tmp; u8 wbuf[1] = { 1 }; u8 rbuf[4]; struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf, @@ -530,6 +531,36 @@ static int af9035_identify_state(struct dvb_usb_device *d, const char **name) state->eeprom_addr = EEPROM_BASE_AF9035; } + + /* check for dual tuner mode */ + ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); + if (ret < 0) + goto err; + + ts_mode_invalid = 0; + switch (tmp) { + case 0: + break; + case 1: + case 3: + state->dual_mode = true; + break; + case 5: + if (state->chip_type != 0x9135 && state->chip_type != 0x9306) + state->dual_mode = true; /* AF9035 */ + else + ts_mode_invalid = 1; + break; + default: + ts_mode_invalid = 1; + } + + dev_dbg(&intf->dev, "ts mode=%d dual mode=%d\n", tmp, state->dual_mode); + + if (ts_mode_invalid) + dev_info(&intf->dev, "ts mode=%d not supported, defaulting to single tuner mode!", tmp); + + ret = af9035_ctrl_msg(d, &req); if (ret < 0) goto err; @@ -698,11 +729,7 @@ static int af9035_download_firmware(struct dvb_usb_device *d, * which is done by master demod. * Master feeds also clock and controls power via GPIO. */ - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); - if (ret < 0) - goto err; - - if (tmp == 1 || tmp == 3 || tmp == 5) { + if (state->dual_mode) { /* configure gpioh1, reset & power slave demod */ ret = af9035_wr_reg_mask(d, 0x00d8b0, 0x01, 0x01); if (ret < 0) @@ -835,17 +862,6 @@ static int af9035_read_config(struct dvb_usb_device *d) } - - /* check if there is dual tuners */ - ret = af9035_rd_reg(d, state->eeprom_addr + EEPROM_TS_MODE, &tmp); - if (ret < 0) - goto err; - - if (tmp == 1 || tmp == 3 || tmp == 5) - state->dual_mode = true; - - dev_dbg(&intf->dev, "ts mode=%d dual mode=%d\n", tmp, state->dual_mode); - if (state->dual_mode) { /* read 2nd demodulator I2C address */ ret = af9035_rd_reg(d, diff --git a/drivers/media/usb/dvb-usb-v2/af9035.h b/drivers/media/usb/dvb-usb-v2/af9035.h index c91d1a3789e6..1f83c9218ad0 100644 --- a/drivers/media/usb/dvb-usb-v2/af9035.h +++ b/drivers/media/usb/dvb-usb-v2/af9035.h @@ -113,7 +113,7 @@ static const u32 clock_lut_it9135[] = { * 0 TS * 1 DCA + PIP * 3 PIP - * 5 DCA + PIP + * 5 DCA + PIP (AF9035 only) * n DCA * * Values 0, 3 and 5 are seen to this day. 0 for single TS and 3/5 for dual TS. diff --git a/drivers/media/usb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c index ca3b69aa9688..be633ece4194 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.c +++ b/drivers/media/usb/dvb-usb/dtt200u.c @@ -55,36 +55,36 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, return dvb_usb_generic_write(adap->dev, b_pid, 4); } -/* remote control */ -/* key list for the tiny remote control (Yakumo, don't know about the others) */ -static struct rc_map_table rc_map_dtt200u_table[] = { - { 0x8001, KEY_MUTE }, - { 0x8002, KEY_CHANNELDOWN }, - { 0x8003, KEY_VOLUMEDOWN }, - { 0x8004, KEY_1 }, - { 0x8005, KEY_2 }, - { 0x8006, KEY_3 }, - { 0x8007, KEY_4 }, - { 0x8008, KEY_5 }, - { 0x8009, KEY_6 }, - { 0x800a, KEY_7 }, - { 0x800c, KEY_ZOOM }, - { 0x800d, KEY_0 }, - { 0x800e, KEY_SELECT }, - { 0x8012, KEY_POWER }, - { 0x801a, KEY_CHANNELUP }, - { 0x801b, KEY_8 }, - { 0x801e, KEY_VOLUMEUP }, - { 0x801f, KEY_9 }, -}; - -static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) +static int dtt200u_rc_query(struct dvb_usb_device *d) { u8 key[5],cmd = GET_RC_CODE; + u32 scancode; + dvb_usb_generic_rw(d,&cmd,1,key,5,0); - dvb_usb_nec_rc_key_to_event(d,key,event,state); + if (key[0] == 1) { + scancode = key[1]; + if ((u8) ~key[1] != key[2]) { + /* Extended NEC */ + scancode = scancode << 8; + scancode |= key[2]; + } + scancode = scancode << 8; + scancode |= key[3]; + + /* Check command checksum is ok */ + if ((u8) ~key[3] == key[4]) + rc_keydown(d->rc_dev, RC_TYPE_NEC, scancode, 0); + else + rc_keyup(d->rc_dev); + } else if (key[0] == 2) { + rc_repeat(d->rc_dev); + } else { + rc_keyup(d->rc_dev); + } + if (key[0] != 0) deb_info("key: %*ph\n", 5, key); + return 0; } @@ -164,11 +164,11 @@ static struct dvb_usb_device_properties dtt200u_properties = { }, .power_ctrl = dtt200u_power_ctrl, - .rc.legacy = { + .rc.core = { .rc_interval = 300, - .rc_map_table = rc_map_dtt200u_table, - .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), + .rc_codes = RC_MAP_DTT200U, .rc_query = dtt200u_rc_query, + .allowed_protos = RC_BIT_NEC, }, .generic_bulk_ctrl_endpoint = 0x01, @@ -214,11 +214,11 @@ static struct dvb_usb_device_properties wt220u_properties = { }, .power_ctrl = dtt200u_power_ctrl, - .rc.legacy = { + .rc.core = { .rc_interval = 300, - .rc_map_table = rc_map_dtt200u_table, - .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), + .rc_codes = RC_MAP_DTT200U, .rc_query = dtt200u_rc_query, + .allowed_protos = RC_BIT_NEC, }, .generic_bulk_ctrl_endpoint = 0x01, @@ -264,11 +264,11 @@ static struct dvb_usb_device_properties wt220u_fc_properties = { }, .power_ctrl = dtt200u_power_ctrl, - .rc.legacy = { + .rc.core = { .rc_interval = 300, - .rc_map_table = rc_map_dtt200u_table, - .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), + .rc_codes = RC_MAP_DTT200U, .rc_query = dtt200u_rc_query, + .allowed_protos = RC_BIT_NEC, }, .generic_bulk_ctrl_endpoint = 0x01, @@ -314,11 +314,11 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = { }, .power_ctrl = dtt200u_power_ctrl, - .rc.legacy = { + .rc.core = { .rc_interval = 300, - .rc_map_table = rc_map_dtt200u_table, - .rc_map_size = ARRAY_SIZE(rc_map_dtt200u_table), + .rc_codes = RC_MAP_DTT200U, .rc_query = dtt200u_rc_query, + .allowed_protos = RC_BIT_NEC, }, .generic_bulk_ctrl_endpoint = 0x01, diff --git a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c index 6477b04e95c7..a04c0a250625 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-dvb.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-dvb.c @@ -320,8 +320,6 @@ int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap) adap->num_frontends_initialized++; } - if (ret) - return ret; ret = dvb_create_media_graph(&adap->dvb_adap, true); if (ret) diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 49b55d7069b1..5fb0c650926e 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -847,7 +847,7 @@ static int su3000_power_ctrl(struct dvb_usb_device *d, int i) struct dw2102_state *state = (struct dw2102_state *)d->priv; u8 obuf[] = {0xde, 0}; - info("%s: %d, initialized %d\n", __func__, i, state->initialized); + info("%s: %d, initialized %d", __func__, i, state->initialized); if (i && !state->initialized) { state->initialized = 1; @@ -894,7 +894,7 @@ static int su3000_identify_state(struct usb_device *udev, struct dvb_usb_device_description **desc, int *cold) { - info("%s\n", __func__); + info("%s", __func__); *cold = 0; return 0; @@ -1132,7 +1132,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d) tuner_ops->set_bandwidth = stb6100_set_bandw; tuner_ops->get_bandwidth = stb6100_get_bandw; d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; - info("Attached STV0900+STB6100!\n"); + info("Attached STV0900+STB6100!"); return 0; } } @@ -1146,7 +1146,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d) &dw2104_stv6110_config, &d->dev->i2c_adap)) { d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; - info("Attached STV0900+STV6110A!\n"); + info("Attached STV0900+STV6110A!"); return 0; } } @@ -1157,7 +1157,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d) &d->dev->i2c_adap); if (d->fe_adap[0].fe != NULL) { d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; - info("Attached cx24116!\n"); + info("Attached cx24116!"); return 0; } } @@ -1168,7 +1168,7 @@ static int dw2104_frontend_attach(struct dvb_usb_adapter *d) dvb_attach(ts2020_attach, d->fe_adap[0].fe, &dw2104_ts2020_config, &d->dev->i2c_adap); d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; - info("Attached DS3000!\n"); + info("Attached DS3000!"); return 0; } @@ -1187,7 +1187,7 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d) &d->dev->i2c_adap); if (d->fe_adap[0].fe != NULL) { d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; - info("Attached si21xx!\n"); + info("Attached si21xx!"); return 0; } } @@ -1199,7 +1199,7 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d) if (dvb_attach(stb6000_attach, d->fe_adap[0].fe, 0x61, &d->dev->i2c_adap)) { d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; - info("Attached stv0288!\n"); + info("Attached stv0288!"); return 0; } } @@ -1211,7 +1211,7 @@ static int dw2102_frontend_attach(struct dvb_usb_adapter *d) &d->dev->i2c_adap); if (d->fe_adap[0].fe != NULL) { d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; - info("Attached stv0299!\n"); + info("Attached stv0299!"); return 0; } } @@ -1223,7 +1223,7 @@ static int dw3101_frontend_attach(struct dvb_usb_adapter *d) d->fe_adap[0].fe = dvb_attach(tda10023_attach, &dw3101_tda10023_config, &d->dev->i2c_adap, 0x48); if (d->fe_adap[0].fe != NULL) { - info("Attached tda10023!\n"); + info("Attached tda10023!"); return 0; } return -EIO; @@ -1237,7 +1237,7 @@ static int zl100313_frontend_attach(struct dvb_usb_adapter *d) if (dvb_attach(zl10039_attach, d->fe_adap[0].fe, 0x60, &d->dev->i2c_adap)) { d->fe_adap[0].fe->ops.set_voltage = dw210x_set_voltage; - info("Attached zl100313+zl10039!\n"); + info("Attached zl100313+zl10039!"); return 0; } } @@ -1262,7 +1262,7 @@ static int stv0288_frontend_attach(struct dvb_usb_adapter *d) dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); - info("Attached stv0288+stb6000!\n"); + info("Attached stv0288+stb6000!"); return 0; @@ -1287,7 +1287,7 @@ static int ds3000_frontend_attach(struct dvb_usb_adapter *d) dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); - info("Attached ds3000+ts2020!\n"); + info("Attached ds3000+ts2020!"); return 0; } @@ -1305,7 +1305,7 @@ static int prof_7500_frontend_attach(struct dvb_usb_adapter *d) dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG); - info("Attached STV0900+STB6100A!\n"); + info("Attached STV0900+STB6100A!"); return 0; } @@ -1353,11 +1353,11 @@ static int su3000_frontend_attach(struct dvb_usb_adapter *d) if (dvb_attach(ts2020_attach, d->fe_adap[0].fe, &dw2104_ts2020_config, &d->dev->i2c_adap)) { - info("Attached DS3000/TS2020!\n"); + info("Attached DS3000/TS2020!"); return 0; } - info("Failed to attach DS3000/TS2020!\n"); + info("Failed to attach DS3000/TS2020!"); return -EIO; } @@ -1402,12 +1402,12 @@ static int t220_frontend_attach(struct dvb_usb_adapter *d) if (d->fe_adap[0].fe != NULL) { if (dvb_attach(tda18271_attach, d->fe_adap[0].fe, 0x60, &d->dev->i2c_adap, &tda18271_config)) { - info("Attached TDA18271HD/CXD2820R!\n"); + info("Attached TDA18271HD/CXD2820R!"); return 0; } } - info("Failed to attach TDA18271HD/CXD2820R!\n"); + info("Failed to attach TDA18271HD/CXD2820R!"); return -EIO; } @@ -1428,11 +1428,11 @@ static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d) if (dvb_attach(ts2020_attach, d->fe_adap[0].fe, &dw2104_ts2020_config, &d->dev->i2c_adap)) { - info("Attached RS2000/TS2020!\n"); + info("Attached RS2000/TS2020!"); return 0; } - info("Failed to attach RS2000/TS2020!\n"); + info("Failed to attach RS2000/TS2020!"); return -EIO; } @@ -1641,6 +1641,7 @@ enum dw2102_table_entry { TEVII_S421, TEVII_S632, TERRATEC_CINERGY_S2_R2, + TERRATEC_CINERGY_S2_R3, GOTVIEW_SAT_HD, GENIATECH_T220, TECHNOTREND_S2_4600, @@ -1669,6 +1670,7 @@ static struct usb_device_id dw2102_table[] = { [TEVII_S421] = {USB_DEVICE(0x9022, USB_PID_TEVII_S421)}, [TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)}, [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R2)}, + [TERRATEC_CINERGY_S2_R3] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R3)}, [GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)}, [GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)}, [TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND, @@ -2083,7 +2085,7 @@ static struct dvb_usb_device_properties su3000_properties = { }}, } }, - .num_device_descs = 5, + .num_device_descs = 6, .devices = { { "SU3000HD DVB-S USB2.0", { &dw2102_table[GENIATECH_SU3000], NULL }, @@ -2101,6 +2103,10 @@ static struct dvb_usb_device_properties su3000_properties = { { &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL }, { NULL }, }, + { "Terratec Cinergy S2 USB HD Rev.3", + { &dw2102_table[TERRATEC_CINERGY_S2_R3], NULL }, + { NULL }, + }, { "GOTVIEW Satellite HD", { &dw2102_table[GOTVIEW_SAT_HD], NULL }, { NULL }, diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c index fe94c9225dd7..836c6b53b16c 100644 --- a/drivers/media/usb/em28xx/em28xx-vbi.c +++ b/drivers/media/usb/em28xx/em28xx-vbi.c @@ -33,7 +33,7 @@ static int vbi_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { struct em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 44834b2eff55..7968695217f3 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -1013,7 +1013,7 @@ static void em28xx_v4l2_create_entities(struct em28xx *dev) static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { struct em28xx *dev = vb2_get_drv_priv(vq); struct em28xx_v4l2 *v4l2 = dev->v4l2; diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index ea01ee5df60a..af8458996d91 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -370,7 +370,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, static int go7007_queue_setup(struct vb2_queue *q, unsigned int *num_buffers, unsigned int *num_planes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { sizes[0] = GO7007_BUF_SIZE; *num_planes = 1; diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c index f23df4a9d8c5..52b88e9e656b 100644 --- a/drivers/media/usb/gspca/cpia1.c +++ b/drivers/media/usb/gspca/cpia1.c @@ -1624,7 +1624,7 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; + struct sd *sd __maybe_unused = (struct sd *) gspca_dev; command_pause(gspca_dev); diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index af5cd8213e8b..b17bd7ebcb47 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -522,7 +522,7 @@ static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file, frame = &gspca_dev->frame[i]; frame->v4l2_buf.index = i; frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - frame->v4l2_buf.flags = 0; + frame->v4l2_buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; frame->v4l2_buf.field = V4L2_FIELD_NONE; frame->v4l2_buf.length = frsz; frame->v4l2_buf.memory = memory; @@ -705,7 +705,7 @@ static int build_isoc_ep_tb(struct gspca_dev *gspca_dev, psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); bandwidth = psize * 1000; if (gspca_dev->dev->speed == USB_SPEED_HIGH - || gspca_dev->dev->speed == USB_SPEED_SUPER) + || gspca_dev->dev->speed >= USB_SPEED_SUPER) bandwidth *= 8; bandwidth /= 1 << (ep->desc.bInterval - 1); if (bandwidth <= last_bw) @@ -996,6 +996,19 @@ static int wxh_to_mode(struct gspca_dev *gspca_dev, { int i; + for (i = 0; i < gspca_dev->cam.nmodes; i++) { + if (width == gspca_dev->cam.cam_mode[i].width + && height == gspca_dev->cam.cam_mode[i].height) + return i; + } + return -EINVAL; +} + +static int wxh_to_nearest_mode(struct gspca_dev *gspca_dev, + int width, int height) +{ + int i; + for (i = gspca_dev->cam.nmodes; --i > 0; ) { if (width >= gspca_dev->cam.cam_mode[i].width && height >= gspca_dev->cam.cam_mode[i].height) @@ -1125,8 +1138,8 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev, PDEBUG_MODE(gspca_dev, D_CONF, "try fmt cap", fmt->fmt.pix.pixelformat, w, h); - /* search the closest mode for width and height */ - mode = wxh_to_mode(gspca_dev, w, h); + /* search the nearest mode for width and height */ + mode = wxh_to_nearest_mode(gspca_dev, w, h); /* OK if right palette */ if (gspca_dev->cam.cam_mode[mode].pixelformat @@ -1233,9 +1246,13 @@ static int vidioc_enum_frameintervals(struct file *filp, void *priv, struct v4l2_frmivalenum *fival) { struct gspca_dev *gspca_dev = video_drvdata(filp); - int mode = wxh_to_mode(gspca_dev, fival->width, fival->height); + int mode; __u32 i; + mode = wxh_to_mode(gspca_dev, fival->width, fival->height); + if (mode < 0) + return -EINVAL; + if (gspca_dev->cam.mode_framerates == NULL || gspca_dev->cam.mode_framerates[mode].nrates == 0) return -EINVAL; @@ -1246,7 +1263,7 @@ static int vidioc_enum_frameintervals(struct file *filp, void *priv, for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) { if (fival->index == i) { - fival->type = V4L2_FRMSIZE_TYPE_DISCRETE; + fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; fival->discrete.numerator = 1; fival->discrete.denominator = gspca_dev->cam.mode_framerates[mode].rates[i]; diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c index 39c96bb4c985..0712b1bc90b4 100644 --- a/drivers/media/usb/gspca/konica.c +++ b/drivers/media/usb/gspca/konica.c @@ -243,7 +243,7 @@ static int sd_start(struct gspca_dev *gspca_dev) static void sd_stopN(struct gspca_dev *gspca_dev) { - struct sd *sd = (struct sd *) gspca_dev; + struct sd *sd __maybe_unused = (struct sd *) gspca_dev; konica_stream_off(gspca_dev); #if IS_ENABLED(CONFIG_INPUT) diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c index bfff1d1c70ab..9266a5c9abc5 100644 --- a/drivers/media/usb/gspca/ov534.c +++ b/drivers/media/usb/gspca/ov534.c @@ -51,6 +51,7 @@ #define OV534_OP_READ_2 0xf9 #define CTRL_TIMEOUT 500 +#define DEFAULT_FRAME_RATE 30 MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver"); @@ -1061,7 +1062,7 @@ static int sd_config(struct gspca_dev *gspca_dev, cam->cam_mode = ov772x_mode; cam->nmodes = ARRAY_SIZE(ov772x_mode); - sd->frame_rate = 30; + sd->frame_rate = DEFAULT_FRAME_RATE; return 0; } @@ -1492,10 +1493,8 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev, struct sd *sd = (struct sd *) gspca_dev; if (tpf->numerator == 0 || tpf->denominator == 0) - /* Set default framerate */ - sd->frame_rate = 30; + sd->frame_rate = DEFAULT_FRAME_RATE; else - /* Set requested framerate */ sd->frame_rate = tpf->denominator / tpf->numerator; if (gspca_dev->streaming) diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c index d0ee899584a9..10269dad9d20 100644 --- a/drivers/media/usb/gspca/sn9c20x.c +++ b/drivers/media/usb/gspca/sn9c20x.c @@ -92,7 +92,6 @@ struct sd { struct v4l2_ctrl *jpegqual; struct work_struct work; - struct workqueue_struct *work_thread; u32 pktsz; /* (used by pkt_scan) */ u16 npkt; @@ -2051,8 +2050,6 @@ static int sd_start(struct gspca_dev *gspca_dev) if (mode & MODE_JPEG) { sd->pktsz = sd->npkt = 0; sd->nchg = 0; - sd->work_thread = - create_singlethread_workqueue(KBUILD_MODNAME); } return gspca_dev->usb_err; @@ -2070,12 +2067,9 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->work_thread != NULL) { - mutex_unlock(&gspca_dev->usb_lock); - destroy_workqueue(sd->work_thread); - mutex_lock(&gspca_dev->usb_lock); - sd->work_thread = NULL; - } + mutex_unlock(&gspca_dev->usb_lock); + flush_work(&sd->work); + mutex_lock(&gspca_dev->usb_lock); } static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) @@ -2228,7 +2222,7 @@ static void transfer_check(struct gspca_dev *gspca_dev, new_qual = sd->jpegqual->maximum; if (new_qual != curqual) { sd->jpegqual->cur.val = new_qual; - queue_work(sd->work_thread, &sd->work); + schedule_work(&sd->work); } } } else { diff --git a/drivers/media/usb/gspca/t613.c b/drivers/media/usb/gspca/t613.c index e2cc4e5a0ccb..bb52fc1fe598 100644 --- a/drivers/media/usb/gspca/t613.c +++ b/drivers/media/usb/gspca/t613.c @@ -837,7 +837,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, /* isoc packet */ int len) /* iso packet length */ { - struct sd *sd = (struct sd *) gspca_dev; + struct sd *sd __maybe_unused = (struct sd *) gspca_dev; int pkt_type; if (data[0] == 0x5a) { diff --git a/drivers/media/usb/gspca/topro.c b/drivers/media/usb/gspca/topro.c index c028a5c2438e..15eb069ab60b 100644 --- a/drivers/media/usb/gspca/topro.c +++ b/drivers/media/usb/gspca/topro.c @@ -175,6 +175,8 @@ static const u8 jpeg_q[17] = { #error "USB buffer too small" #endif +#define DEFAULT_FRAME_RATE 30 + static const u8 rates[] = {30, 20, 15, 10, 7, 5}; static const struct framerates framerates[] = { { @@ -4020,7 +4022,7 @@ static int sd_config(struct gspca_dev *gspca_dev, gspca_dev->cam.mode_framerates = sd->bridge == BRIDGE_TP6800 ? framerates : framerates_6810; - sd->framerate = 30; /* default: 30 fps */ + sd->framerate = DEFAULT_FRAME_RATE; return 0; } @@ -4803,7 +4805,7 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev, int fr, i; if (tpf->numerator == 0 || tpf->denominator == 0) - sd->framerate = 30; + sd->framerate = DEFAULT_FRAME_RATE; else sd->framerate = tpf->denominator / tpf->numerator; diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c index c5d8ee6fa3c7..5f7254d2bc9a 100644 --- a/drivers/media/usb/gspca/zc3xx.c +++ b/drivers/media/usb/gspca/zc3xx.c @@ -53,7 +53,6 @@ struct sd { struct v4l2_ctrl *jpegqual; struct work_struct work; - struct workqueue_struct *work_thread; u8 reg08; /* webcam compression quality */ @@ -6826,8 +6825,7 @@ static int sd_start(struct gspca_dev *gspca_dev) return gspca_dev->usb_err; /* Start the transfer parameters update thread */ - sd->work_thread = create_singlethread_workqueue(KBUILD_MODNAME); - queue_work(sd->work_thread, &sd->work); + schedule_work(&sd->work); return 0; } @@ -6838,12 +6836,9 @@ static void sd_stop0(struct gspca_dev *gspca_dev) { struct sd *sd = (struct sd *) gspca_dev; - if (sd->work_thread != NULL) { - mutex_unlock(&gspca_dev->usb_lock); - destroy_workqueue(sd->work_thread); - mutex_lock(&gspca_dev->usb_lock); - sd->work_thread = NULL; - } + mutex_unlock(&gspca_dev->usb_lock); + flush_work(&sd->work); + mutex_lock(&gspca_dev->usb_lock); if (!gspca_dev->present) return; send_unknown(gspca_dev, sd->sensor); diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c index 9e700caf0d66..b1e229a44192 100644 --- a/drivers/media/usb/hackrf/hackrf.c +++ b/drivers/media/usb/hackrf/hackrf.c @@ -760,7 +760,7 @@ static void hackrf_return_all_buffers(struct vb2_queue *vq, static int hackrf_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, - unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) + unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { struct hackrf_dev *dev = vb2_get_drv_priv(vq); diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c index 08f0ca7aa012..a61d8fd63c12 100644 --- a/drivers/media/usb/hdpvr/hdpvr-core.c +++ b/drivers/media/usb/hdpvr/hdpvr-core.c @@ -310,10 +310,6 @@ static int hdpvr_probe(struct usb_interface *interface, init_waitqueue_head(&dev->wait_buffer); init_waitqueue_head(&dev->wait_data); - dev->workqueue = create_singlethread_workqueue("hdpvr_buffer"); - if (!dev->workqueue) - goto error; - dev->options = hdpvr_default_options; if (default_video_input < HDPVR_VIDEO_INPUTS) @@ -404,9 +400,7 @@ reg_fail: #endif error: if (dev) { - /* Destroy single thread */ - if (dev->workqueue) - destroy_workqueue(dev->workqueue); + flush_work(&dev->worker); /* this frees allocated memory */ hdpvr_delete(dev); } @@ -427,7 +421,7 @@ static void hdpvr_disconnect(struct usb_interface *interface) mutex_unlock(&dev->io_mutex); v4l2_device_disconnect(&dev->v4l2_dev); msleep(100); - flush_workqueue(dev->workqueue); + flush_work(&dev->worker); mutex_lock(&dev->io_mutex); hdpvr_cancel_queue(dev); mutex_unlock(&dev->io_mutex); diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c index ba7f02270c83..2a3a8b470555 100644 --- a/drivers/media/usb/hdpvr/hdpvr-video.c +++ b/drivers/media/usb/hdpvr/hdpvr-video.c @@ -316,7 +316,7 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev) dev->status = STATUS_STREAMING; INIT_WORK(&dev->worker, hdpvr_transmit_buffers); - queue_work(dev->workqueue, &dev->worker); + schedule_work(&dev->worker); v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev, "streaming started\n"); @@ -350,7 +350,7 @@ static int hdpvr_stop_streaming(struct hdpvr_device *dev) wake_up_interruptible(&dev->wait_buffer); msleep(50); - flush_workqueue(dev->workqueue); + flush_work(&dev->worker); mutex_lock(&dev->io_mutex); /* kill the still outstanding urbs */ @@ -1123,7 +1123,7 @@ static void hdpvr_device_release(struct video_device *vdev) hdpvr_delete(dev); mutex_lock(&dev->io_mutex); - destroy_workqueue(dev->workqueue); + flush_work(&dev->worker); mutex_unlock(&dev->io_mutex); v4l2_device_unregister(&dev->v4l2_dev); diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h index 78e815441f95..a12e0af1d4e1 100644 --- a/drivers/media/usb/hdpvr/hdpvr.h +++ b/drivers/media/usb/hdpvr/hdpvr.h @@ -107,8 +107,6 @@ struct hdpvr_device { /* waitqueue for data */ wait_queue_head_t wait_data; /**/ - struct workqueue_struct *workqueue; - /**/ struct work_struct worker; /* current stream owner */ struct v4l2_fh *owner; diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index 2d33033682af..e7f167d44c61 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -618,7 +618,7 @@ static int msi2500_querycap(struct file *file, void *fh, static int msi2500_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], - void *alloc_ctxs[]) + struct device *alloc_devs[]) { struct msi2500_dev *dev = vb2_get_drv_priv(vq); diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 83e9a3eb3859..fe20fe4f2330 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -2856,11 +2856,15 @@ static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id, const char *name, int val) { struct v4l2_control ctrl; + struct v4l2_subdev *sd; + pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val); memset(&ctrl, 0, sizeof(ctrl)); ctrl.id = id; ctrl.value = val; - v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl); + + v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) + v4l2_s_ctrl(NULL, sd->ctrl_handler, &ctrl); } #define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \ diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c index 18aed5dd325e..b51b27a3fd61 100644 --- a/drivers/media/usb/pwc/pwc-if.c +++ b/drivers/media/usb/pwc/pwc-if.c @@ -573,7 +573,7 @@ static void pwc_video_release(struct v4l2_device *v) static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { struct pwc_device *pdev = vb2_get_drv_priv(vq); int size; @@ -1118,8 +1118,10 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id return 0; +#ifdef CONFIG_USB_PWC_INPUT_EVDEV err_video_unreg: video_unregister_device(&pdev->vdev); +#endif err_unregister_v4l2_dev: v4l2_device_unregister(&pdev->v4l2_dev); err_free_controls: diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index 9acdaa3716fb..43ba71a7d02b 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -662,7 +662,7 @@ static void s2255_fillbuff(struct s2255_vc *vc, static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { struct s2255_vc *vc = vb2_get_drv_priv(vq); if (*nbuffers < S2255_MIN_BUFS) diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c index 7ddbc0274f12..5fab3bee8c74 100644 --- a/drivers/media/usb/stk1160/stk1160-v4l.c +++ b/drivers/media/usb/stk1160/stk1160-v4l.c @@ -666,7 +666,7 @@ static const struct v4l2_ioctl_ops stk1160_ioctl_ops = { */ static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { struct stk1160 *dev = vb2_get_drv_priv(vq); unsigned long size; diff --git a/drivers/media/usb/usbtv/usbtv-audio.c b/drivers/media/usb/usbtv/usbtv-audio.c index 78c12d22dfbb..1965ff1b1f12 100644 --- a/drivers/media/usb/usbtv/usbtv-audio.c +++ b/drivers/media/usb/usbtv/usbtv-audio.c @@ -1,13 +1,6 @@ /* - * Fushicai USBTV007 Audio-Video Grabber Driver - * - * Product web site: - * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html - * * Copyright (c) 2013 Federico Simoncelli * All rights reserved. - * No physical hardware was harmed running Windows during the - * reverse-engineering activity * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,6 +13,27 @@ * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Fushicai USBTV007 Audio-Video Grabber Driver + * + * Product web site: + * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html + * + * No physical hardware was harmed running Windows during the + * reverse-engineering activity */ #include <sound/core.h> @@ -278,6 +292,9 @@ static void snd_usbtv_trigger(struct work_struct *work) { struct usbtv *chip = container_of(work, struct usbtv, snd_trigger); + if (!chip->snd) + return; + if (atomic_read(&chip->snd_stream)) usbtv_audio_start(chip); else @@ -378,6 +395,8 @@ err: void usbtv_audio_free(struct usbtv *usbtv) { + cancel_work_sync(&usbtv->snd_trigger); + if (usbtv->snd && usbtv->udev) { snd_card_free(usbtv->snd); usbtv->snd = NULL; diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c index 29428bef272c..dc76fd41e00f 100644 --- a/drivers/media/usb/usbtv/usbtv-core.c +++ b/drivers/media/usb/usbtv/usbtv-core.c @@ -1,19 +1,6 @@ /* - * Fushicai USBTV007 Audio-Video Grabber Driver - * - * Product web site: - * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html - * - * Following LWN articles were very useful in construction of this driver: - * Video4Linux2 API series: http://lwn.net/Articles/203924/ - * videobuf2 API explanation: http://lwn.net/Articles/447435/ - * Thanks go to Jonathan Corbet for providing this quality documentation. - * He is awesome. - * * Copyright (c) 2013 Lubomir Rintel * All rights reserved. - * No physical hardware was harmed running Windows during the - * reverse-engineering activity * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,6 +13,33 @@ * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Fushicai USBTV007 Audio-Video Grabber Driver + * + * Product web site: + * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html + * + * Following LWN articles were very useful in construction of this driver: + * Video4Linux2 API series: http://lwn.net/Articles/203924/ + * videobuf2 API explanation: http://lwn.net/Articles/447435/ + * Thanks go to Jonathan Corbet for providing this quality documentation. + * He is awesome. + * + * No physical hardware was harmed running Windows during the + * reverse-engineering activity */ #include "usbtv.h" diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c index f6cfad46547e..2a089756c988 100644 --- a/drivers/media/usb/usbtv/usbtv-video.c +++ b/drivers/media/usb/usbtv/usbtv-video.c @@ -1,19 +1,6 @@ /* - * Fushicai USBTV007 Audio-Video Grabber Driver - * - * Product web site: - * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html - * - * Following LWN articles were very useful in construction of this driver: - * Video4Linux2 API series: http://lwn.net/Articles/203924/ - * videobuf2 API explanation: http://lwn.net/Articles/447435/ - * Thanks go to Jonathan Corbet for providing this quality documentation. - * He is awesome. - * * Copyright (c) 2013 Lubomir Rintel * All rights reserved. - * No physical hardware was harmed running Windows during the - * reverse-engineering activity * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,6 +13,33 @@ * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Fushicai USBTV007 Audio-Video Grabber Driver + * + * Product web site: + * http://www.fushicai.com/products_detail/&productId=d05449ee-b690-42f9-a661-aa7353894bed.html + * + * Following LWN articles were very useful in construction of this driver: + * Video4Linux2 API series: http://lwn.net/Articles/203924/ + * videobuf2 API explanation: http://lwn.net/Articles/447435/ + * Thanks go to Jonathan Corbet for providing this quality documentation. + * He is awesome. + * + * No physical hardware was harmed running Windows during the + * reverse-engineering activity */ #include <media/v4l2-ioctl.h> @@ -251,8 +265,23 @@ static int usbtv_setup_capture(struct usbtv *usbtv) /* Copy data from chunk into a frame buffer, deinterlacing the data * into every second line. Unfortunately, they don't align nicely into * 720 pixel lines, as the chunk is 240 words long, which is 480 pixels. - * Therefore, we break down the chunk into two halves before copyting, - * so that we can interleave a line if needed. */ + * Therefore, we break down the chunk into two halves before copying, + * so that we can interleave a line if needed. + * + * Each "chunk" is 240 words; a word in this context equals 4 bytes. + * Image format is YUYV/YUV 4:2:2, consisting of Y Cr Y Cb, defining two + * pixels, the Cr and Cb shared between the two pixels, but each having + * separate Y values. Thus, the 240 words equal 480 pixels. It therefore, + * takes 1.5 chunks to make a 720 pixel-wide line for the frame. + * The image is interlaced, so there is a "scan" of odd lines, followed + * by "scan" of even numbered lines. + * + * Following code is writing the chunks in correct sequence, skipping + * the rows based on "odd" value. + * line 1: chunk[0][ 0..479] chunk[0][480..959] chunk[1][ 0..479] + * line 3: chunk[1][480..959] chunk[2][ 0..479] chunk[2][480..959] + * ...etc. + */ static void usbtv_chunk_to_vbuf(u32 *frame, __be32 *src, int chunk_no, int odd) { int half; @@ -608,7 +637,7 @@ static struct v4l2_file_operations usbtv_fops = { static int usbtv_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, - unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) + unsigned int *nplanes, unsigned int sizes[], struct device *alloc_devs[]) { struct usbtv *usbtv = vb2_get_drv_priv(vq); unsigned size = USBTV_CHUNK * usbtv->n_chunks * 2 * sizeof(u32); diff --git a/drivers/media/usb/usbtv/usbtv.h b/drivers/media/usb/usbtv/usbtv.h index 161b38d5cfa0..011f9fdc77a9 100644 --- a/drivers/media/usb/usbtv/usbtv.h +++ b/drivers/media/usb/usbtv/usbtv.h @@ -1,10 +1,6 @@ /* - * Fushicai USBTV007 Audio-Video Grabber Driver - * * Copyright (c) 2013 Lubomir Rintel * All rights reserved. - * No physical hardware was harmed running Windows during the - * reverse-engineering activity * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -17,6 +13,24 @@ * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Fushicai USBTV007 Audio-Video Grabber Driver + * + * No physical hardware was harmed running Windows during the + * reverse-engineering activity */ #include <linux/module.h> diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index ad2f3d27b266..c8b4eb2ee7a2 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -188,12 +188,10 @@ static ssize_t show_hue(struct device *cd, { struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_HUE; - ctrl.value = 0; - if (usbvision->user) - call_all(usbvision, core, g_ctrl, &ctrl); - return sprintf(buf, "%d\n", ctrl.value); + s32 val = v4l2_ctrl_g_ctrl(v4l2_ctrl_find(&usbvision->hdl, + V4L2_CID_HUE)); + + return sprintf(buf, "%d\n", val); } static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL); @@ -202,12 +200,10 @@ static ssize_t show_contrast(struct device *cd, { struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_CONTRAST; - ctrl.value = 0; - if (usbvision->user) - call_all(usbvision, core, g_ctrl, &ctrl); - return sprintf(buf, "%d\n", ctrl.value); + s32 val = v4l2_ctrl_g_ctrl(v4l2_ctrl_find(&usbvision->hdl, + V4L2_CID_CONTRAST)); + + return sprintf(buf, "%d\n", val); } static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL); @@ -216,12 +212,10 @@ static ssize_t show_brightness(struct device *cd, { struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_BRIGHTNESS; - ctrl.value = 0; - if (usbvision->user) - call_all(usbvision, core, g_ctrl, &ctrl); - return sprintf(buf, "%d\n", ctrl.value); + s32 val = v4l2_ctrl_g_ctrl(v4l2_ctrl_find(&usbvision->hdl, + V4L2_CID_BRIGHTNESS)); + + return sprintf(buf, "%d\n", val); } static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL); @@ -230,12 +224,10 @@ static ssize_t show_saturation(struct device *cd, { struct video_device *vdev = to_video_device(cd); struct usb_usbvision *usbvision = video_get_drvdata(vdev); - struct v4l2_control ctrl; - ctrl.id = V4L2_CID_SATURATION; - ctrl.value = 0; - if (usbvision->user) - call_all(usbvision, core, g_ctrl, &ctrl); - return sprintf(buf, "%d\n", ctrl.value); + s32 val = v4l2_ctrl_g_ctrl(v4l2_ctrl_find(&usbvision->hdl, + V4L2_CID_SATURATION)); + + return sprintf(buf, "%d\n", val); } static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL); diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index 54394722756f..773fefb52d7a 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -71,7 +71,7 @@ static void uvc_queue_return_buffers(struct uvc_video_queue *queue, static int uvc_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], void *alloc_ctxs[]) + unsigned int sizes[], struct device *alloc_devs[]) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index cded5ef52e24..05eed4be25df 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -1289,8 +1289,6 @@ struct uvc_xu_control_mapping32 { static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, const struct uvc_xu_control_mapping32 __user *up) { - struct uvc_menu_info __user *umenus; - struct uvc_menu_info __user *kmenus; compat_caddr_t p; if (!access_ok(VERIFY_READ, up, sizeof(*up)) || @@ -1307,17 +1305,7 @@ static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, if (__get_user(p, &up->menu_info)) return -EFAULT; - umenus = compat_ptr(p); - if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus))) - return -EFAULT; - - kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus)); - if (kmenus == NULL) - return -EFAULT; - kp->menu_info = kmenus; - - if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus))) - return -EFAULT; + kp->menu_info = compat_ptr(p); return 0; } @@ -1325,10 +1313,6 @@ static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, struct uvc_xu_control_mapping32 __user *up) { - struct uvc_menu_info __user *umenus; - struct uvc_menu_info __user *kmenus = kp->menu_info; - compat_caddr_t p; - if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) || __put_user(kp->menu_count, &up->menu_count)) @@ -1337,16 +1321,6 @@ static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, if (__clear_user(up->reserved, sizeof(up->reserved))) return -EFAULT; - if (kp->menu_count == 0) - return 0; - - if (get_user(p, &up->menu_info)) - return -EFAULT; - umenus = compat_ptr(p); - - if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus))) - return -EFAULT; - return 0; } @@ -1361,8 +1335,6 @@ struct uvc_xu_control_query32 { static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, const struct uvc_xu_control_query32 __user *up) { - u8 __user *udata; - u8 __user *kdata; compat_caddr_t p; if (!access_ok(VERIFY_READ, up, sizeof(*up)) || @@ -1376,17 +1348,7 @@ static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, if (__get_user(p, &up->data)) return -EFAULT; - udata = compat_ptr(p); - if (!access_ok(VERIFY_READ, udata, kp->size)) - return -EFAULT; - - kdata = compat_alloc_user_space(kp->size); - if (kdata == NULL) - return -EFAULT; - kp->data = kdata; - - if (copy_in_user(kdata, udata, kp->size)) - return -EFAULT; + kp->data = compat_ptr(p); return 0; } @@ -1394,26 +1356,10 @@ static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, struct uvc_xu_control_query32 __user *up) { - u8 __user *udata; - u8 __user *kdata = kp->data; - compat_caddr_t p; - if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || __copy_to_user(up, kp, offsetof(typeof(*up), data))) return -EFAULT; - if (kp->size == 0) - return 0; - - if (get_user(p, &up->data)) - return -EFAULT; - udata = compat_ptr(p); - if (!access_ok(VERIFY_READ, udata, kp->size)) - return -EFAULT; - - if (copy_in_user(udata, kdata, kp->size)) - return -EFAULT; - return 0; } @@ -1423,47 +1369,44 @@ static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, static long uvc_v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) { + struct uvc_fh *handle = file->private_data; union { struct uvc_xu_control_mapping xmap; struct uvc_xu_control_query xqry; } karg; void __user *up = compat_ptr(arg); - mm_segment_t old_fs; long ret; switch (cmd) { case UVCIOC_CTRL_MAP32: - cmd = UVCIOC_CTRL_MAP; ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up); + if (ret) + return ret; + ret = uvc_ioctl_ctrl_map(handle->chain, &karg.xmap); + if (ret) + return ret; + ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up); + if (ret) + return ret; + break; case UVCIOC_CTRL_QUERY32: - cmd = UVCIOC_CTRL_QUERY; ret = uvc_v4l2_get_xu_query(&karg.xqry, up); + if (ret) + return ret; + ret = uvc_xu_ctrl_query(handle->chain, &karg.xqry); + if (ret) + return ret; + ret = uvc_v4l2_put_xu_query(&karg.xqry, up); + if (ret) + return ret; break; default: return -ENOIOCTLCMD; } - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = video_ioctl2(file, cmd, (unsigned long)&karg); - set_fs(old_fs); - - if (ret < 0) - return ret; - - switch (cmd) { - case UVCIOC_CTRL_MAP: - ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up); - break; - - case UVCIOC_CTRL_QUERY: - ret = uvc_v4l2_put_xu_query(&karg.xqry, up); - break; - } - return ret; } #endif |