From 6830733d53a4517588e56227b9c8538633f0c496 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Thu, 2 Feb 2017 12:53:04 -0200 Subject: [media] pvrusb2: reduce stack usage pvr2_eeprom_analyze() The driver uses a relatively large data structure on the stack, which showed up on my radar as we get a warning with the "latent entropy" GCC plugin: drivers/media/usb/pvrusb2/pvrusb2-eeprom.c:153:1: error: the frame size of 1376 bytes is larger than 1152 bytes [-Werror=frame-larger-than=] The warning is usually hidden as we raise the warning limit to 2048 when the plugin is enabled, but I'd like to lower that again in the future, and making this function smaller helps to do that without build regressions. Further analysis shows that putting an 'i2c_client' structure on the stack is not really supported, as the embedded 'struct device' is not initialized here, and we are only saved by the fact that the function that is called here does not use the pointer at all. Fixes: d855497edbfb ("V4L/DVB (4228a): pvrusb2 to kernel 2.6.18") Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/pvrusb2/pvrusb2-eeprom.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c index 4af2fb5c85d5..7252f113df2f 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c @@ -118,15 +118,10 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) memset(&tvdata,0,sizeof(tvdata)); eeprom = pvr2_eeprom_fetch(hdw); - if (!eeprom) return -EINVAL; - - { - struct i2c_client fake_client; - /* Newer version expects a useless client interface */ - fake_client.addr = hdw->eeprom_addr; - fake_client.adapter = &hdw->i2c_adap; - tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom); - } + if (!eeprom) + return -EINVAL; + + tveeprom_hauppauge_analog(NULL, &tvdata, eeprom); trace_eeprom("eeprom assumed v4l tveeprom module"); trace_eeprom("eeprom direct call results:"); -- cgit v1.2.3 From 4063987c9bb419bb14d83b9ad812ad3d6a3c65e4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Thu, 2 Feb 2017 12:53:06 -0200 Subject: [media] cx231xx-i2c: reduce stack size in bus scan The cx231xx_do_i2c_scan function needs a lot of stack because it puts an i2c_client structure on it: drivers/media/usb/cx231xx/cx231xx-i2c.c: In function 'cx231xx_do_i2c_scan': drivers/media/usb/cx231xx/cx231xx-i2c.c:518:1: error: the frame size of 1248 bytes is larger than 1152 bytes [-Werror=frame-larger-than=] This changes it to call i2c_transfer() directly instead, avoiding the need for the structure. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/cx231xx/cx231xx-i2c.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c index 35e9acfe63d3..24e23a06d8c6 100644 --- a/drivers/media/usb/cx231xx/cx231xx-i2c.c +++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c @@ -491,20 +491,24 @@ void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port) { unsigned char buf; int i, rc; - struct i2c_client client; + struct i2c_adapter *adap; + struct i2c_msg msg = { + .flags = I2C_M_RD, + .len = 1, + .buf = &buf, + }; if (!i2c_scan) return; /* Don't generate I2C errors during scan */ dev->i2c_scan_running = true; - - memset(&client, 0, sizeof(client)); - client.adapter = cx231xx_get_i2c_adap(dev, i2c_port); + adap = cx231xx_get_i2c_adap(dev, i2c_port); for (i = 0; i < 128; i++) { - client.addr = i; - rc = i2c_master_recv(&client, &buf, 0); + msg.addr = i; + rc = i2c_transfer(adap, &msg, 1); + if (rc < 0) continue; dev_info(dev->dev, -- cgit v1.2.3 From 371d1143a5581718f7c687e4da259f80ab0c4634 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann <arnd@arndb.de> Date: Thu, 2 Feb 2017 12:53:07 -0200 Subject: [media] mxl111sf: reduce stack usage in init function mxl111sf uses a lot of kernel stack memory as it puts an i2c_client structure on the stack: drivers/media/usb/dvb-usb-v2/mxl111sf.c: In function 'mxl111sf_init': drivers/media/usb/dvb-usb-v2/mxl111sf.c:953:1: error: the frame size of 1248 bytes is larger than 1152 bytes [-Werror=frame-larger-than=] We can avoid doing this by open-coding the call to i2c_transfer() instead of calling tveeprom_read(), and not passing an i2c_client pointer to tveeprom_hauppauge_analog(), which would ignore that anyway. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index 80c635980526..60bc5cc9a483 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -919,7 +919,12 @@ static int mxl111sf_init(struct dvb_usb_device *d) struct mxl111sf_state *state = d_to_priv(d); int ret; static u8 eeprom[256]; - struct i2c_client c; + u8 reg = 0; + struct i2c_msg msg[2] = { + { .addr = 0xa0 >> 1, .len = 1, .buf = ® }, + { .addr = 0xa0 >> 1, .flags = I2C_M_RD, + .len = sizeof(eeprom), .buf = eeprom }, + }; ret = get_chip_info(state); if (mxl_fail(ret)) @@ -930,13 +935,10 @@ static int mxl111sf_init(struct dvb_usb_device *d) if (state->chip_rev > MXL111SF_V6) mxl111sf_config_pin_mux_modes(state, PIN_MUX_TS_SPI_IN_MODE_1); - c.adapter = &d->i2c_adap; - c.addr = 0xa0 >> 1; - - ret = tveeprom_read(&c, eeprom, sizeof(eeprom)); + ret = i2c_transfer(&d->i2c_adap, msg, 2); if (mxl_fail(ret)) return 0; - tveeprom_hauppauge_analog(&c, &state->tv, (0x84 == eeprom[0xa0]) ? + tveeprom_hauppauge_analog(NULL, &state->tv, (0x84 == eeprom[0xa0]) ? eeprom + 0xa0 : eeprom + 0x80); #if 0 switch (state->tv.model) { -- cgit v1.2.3 From 446aba663b8240b24202cb8902b0d5c8f91aa3da Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab <mchehab@s-opensource.com> Date: Fri, 3 Mar 2017 07:28:29 -0300 Subject: [media] tveeprom: get rid of unused arg on tveeprom_hauppauge_analog() tveeprom_hauppauge_analog() used to need the I2C adapter in order to print debug messages. As it now uses pr_foo() facilities since commit 6037b3ca28f4 ("[media] tveeprom: print log messages using pr_foo()"), the first argument of the function is not needed anymore. So, get rid of it. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/common/tveeprom.c | 4 ++-- drivers/media/pci/bt8xx/bttv-cards.c | 2 +- drivers/media/pci/cx18/cx18-driver.c | 2 +- drivers/media/pci/cx23885/cx23885-cards.c | 3 +-- drivers/media/pci/cx88/cx88-cards.c | 2 +- drivers/media/pci/ivtv/ivtv-driver.c | 2 +- drivers/media/pci/saa7134/saa7134-cards.c | 2 +- drivers/media/pci/saa7164/saa7164-cards.c | 4 +--- drivers/media/usb/au0828/au0828-cards.c | 2 +- drivers/media/usb/cx231xx/cx231xx-cards.c | 3 +-- drivers/media/usb/dvb-usb-v2/mxl111sf.c | 4 ++-- drivers/media/usb/em28xx/em28xx-cards.c | 3 +-- drivers/media/usb/pvrusb2/pvrusb2-eeprom.c | 2 +- include/media/tveeprom.h | 2 +- 14 files changed, 16 insertions(+), 21 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/common/tveeprom.c b/drivers/media/common/tveeprom.c index 6e1020227f9f..ccf2d3b12aec 100644 --- a/drivers/media/common/tveeprom.c +++ b/drivers/media/common/tveeprom.c @@ -420,8 +420,8 @@ static int hasRadioTuner(int tunerType) return 0; } -void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, - unsigned char *eeprom_data) +void tveeprom_hauppauge_analog(struct tveeprom *tvee, + unsigned char *eeprom_data) { /* ---------------------------------------------- ** The hauppauge eeprom format is tagged diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c index a1b0f3193bc0..5cc42b426715 100644 --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c @@ -3717,7 +3717,7 @@ static void hauppauge_eeprom(struct bttv *btv) { struct tveeprom tv; - tveeprom_hauppauge_analog(&btv->i2c_client, &tv, eeprom_data); + tveeprom_hauppauge_analog(&tv, eeprom_data); btv->tuner_type = tv.tuner_type; btv->has_radio = tv.has_radio; diff --git a/drivers/media/pci/cx18/cx18-driver.c b/drivers/media/pci/cx18/cx18-driver.c index 206db81ef78e..8bce49cdad46 100644 --- a/drivers/media/pci/cx18/cx18-driver.c +++ b/drivers/media/pci/cx18/cx18-driver.c @@ -339,7 +339,7 @@ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv) case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: case CX18_CARD_HVR_1600_S5H1411: - tveeprom_hauppauge_analog(c, tv, eedata); + tveeprom_hauppauge_analog(tv, eedata); break; case CX18_CARD_YUAN_MPC718: case CX18_CARD_GOTVIEW_PCI_DVD3: diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 0350f13c5a9f..9e39aea85df6 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -1143,8 +1143,7 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) { struct tveeprom tv; - tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv, - eeprom_data); + tveeprom_hauppauge_analog(&tv, eeprom_data); /* Make sure we support the board model */ switch (tv.model) { diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c index cdfbde277b8b..61e1803882d9 100644 --- a/drivers/media/pci/cx88/cx88-cards.c +++ b/drivers/media/pci/cx88/cx88-cards.c @@ -2854,7 +2854,7 @@ static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data) { struct tveeprom tv; - tveeprom_hauppauge_analog(&core->i2c_client, &tv, eeprom_data); + tveeprom_hauppauge_analog(&tv, eeprom_data); core->board.tuner_type = tv.tuner_type; core->tuner_formats = tv.tuner_formats; core->board.radio.type = tv.has_radio ? CX88_RADIO : 0; diff --git a/drivers/media/pci/ivtv/ivtv-driver.c b/drivers/media/pci/ivtv/ivtv-driver.c index ab2ae53618e8..aaccc1187791 100644 --- a/drivers/media/pci/ivtv/ivtv-driver.c +++ b/drivers/media/pci/ivtv/ivtv-driver.c @@ -408,7 +408,7 @@ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv) itv->i2c_client.addr = 0xA0 >> 1; tveeprom_read(&itv->i2c_client, eedata, sizeof(eedata)); - tveeprom_hauppauge_analog(&itv->i2c_client, tv, eedata); + tveeprom_hauppauge_analog(tv, eedata); } static void ivtv_process_eeprom(struct ivtv *itv) diff --git a/drivers/media/pci/saa7134/saa7134-cards.c b/drivers/media/pci/saa7134/saa7134-cards.c index 321253827997..f79380faf499 100644 --- a/drivers/media/pci/saa7134/saa7134-cards.c +++ b/drivers/media/pci/saa7134/saa7134-cards.c @@ -7319,7 +7319,7 @@ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) { struct tveeprom tv; - tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); + tveeprom_hauppauge_analog(&tv, eeprom_data); /* Make sure we support the board model */ switch (tv.model) { diff --git a/drivers/media/pci/saa7164/saa7164-cards.c b/drivers/media/pci/saa7164/saa7164-cards.c index 0e1cd7e153ca..3af16062e79d 100644 --- a/drivers/media/pci/saa7164/saa7164-cards.c +++ b/drivers/media/pci/saa7164/saa7164-cards.c @@ -780,9 +780,7 @@ static void hauppauge_eeprom(struct saa7164_dev *dev, u8 *eeprom_data) { struct tveeprom tv; - /* TODO: Assumption: eeprom on bus 0 */ - tveeprom_hauppauge_analog(&dev->i2c_bus[0].i2c_client, &tv, - eeprom_data); + tveeprom_hauppauge_analog(&tv, eeprom_data); /* Make sure we support the board model */ switch (tv.model) { diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c index 313f659f0bfb..43bfa778b070 100644 --- a/drivers/media/usb/au0828/au0828-cards.c +++ b/drivers/media/usb/au0828/au0828-cards.c @@ -153,7 +153,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) { struct tveeprom tv; - tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data); + tveeprom_hauppauge_analog(&tv, eeprom_data); dev->board.tuner_type = tv.tuner_type; /* Make sure we support the board model */ diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index f730fdbc9156..9b28d57006af 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1165,8 +1165,7 @@ void cx231xx_card_setup(struct cx231xx *dev) e->client.addr = 0xa0 >> 1; read_eeprom(dev, &e->client, e->eeprom, sizeof(e->eeprom)); - tveeprom_hauppauge_analog(&e->client, - &e->tvee, e->eeprom + 0xc0); + tveeprom_hauppauge_analog(&e->tvee, e->eeprom + 0xc0); kfree(e); break; } diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c index 60bc5cc9a483..abf69d8fa469 100644 --- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c +++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c @@ -938,8 +938,8 @@ static int mxl111sf_init(struct dvb_usb_device *d) ret = i2c_transfer(&d->i2c_adap, msg, 2); if (mxl_fail(ret)) return 0; - tveeprom_hauppauge_analog(NULL, &state->tv, (0x84 == eeprom[0xa0]) ? - eeprom + 0xa0 : eeprom + 0x80); + tveeprom_hauppauge_analog(&state->tv, (0x84 == eeprom[0xa0]) ? + eeprom + 0xa0 : eeprom + 0x80); #if 0 switch (state->tv.model) { case 117001: diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 5f90d0899a45..5f80a1b2fb8c 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2974,8 +2974,7 @@ static void em28xx_card_setup(struct em28xx *dev) #endif /* Call first TVeeprom */ - dev->i2c_client[dev->def_i2c_bus].addr = 0xa0 >> 1; - tveeprom_hauppauge_analog(&dev->i2c_client[dev->def_i2c_bus], &tv, dev->eedata); + tveeprom_hauppauge_analog(&tv, dev->eedata); dev->tuner_type = tv.tuner_type; diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c index 7252f113df2f..8b643d511a0b 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c @@ -121,7 +121,7 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) if (!eeprom) return -EINVAL; - tveeprom_hauppauge_analog(NULL, &tvdata, eeprom); + tveeprom_hauppauge_analog(&tvdata, eeprom); trace_eeprom("eeprom assumed v4l tveeprom module"); trace_eeprom("eeprom direct call results:"); diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h index c56501ee0484..5324c82fc810 100644 --- a/include/media/tveeprom.h +++ b/include/media/tveeprom.h @@ -100,7 +100,7 @@ struct tveeprom { * contain 256 bytes filled with the contents of the * eeprom read from the Hauppauge device. */ -void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, +void tveeprom_hauppauge_analog(struct tveeprom *tvee, unsigned char *eeprom_data); /** -- cgit v1.2.3 From f8585ce655e9cdeabc38e8e2580b05735110e4a5 Mon Sep 17 00:00:00 2001 From: Evgeny Plehov <EvgenyPlehov@ukr.net> Date: Tue, 7 Feb 2017 19:37:01 -0200 Subject: [media] dvb-usb-cxusb: Geniatech T230C support Updated Geniatech DVB-T/T2 stick support. Signed-off-by: Evgeny Plehov <EvgenyPlehov@ukr.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/dvb-usb/cxusb.c | 139 +++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 51620e02292f..9a7665fddc29 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -1239,6 +1239,82 @@ static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap) return 0; } +static int cxusb_mygica_t230c_frontend_attach(struct dvb_usb_adapter *adap) +{ + struct dvb_usb_device *d = adap->dev; + struct cxusb_state *st = d->priv; + struct i2c_adapter *adapter; + struct i2c_client *client_demod; + struct i2c_client *client_tuner; + struct i2c_board_info info; + struct si2168_config si2168_config; + struct si2157_config si2157_config; + + /* Select required USB configuration */ + if (usb_set_interface(d->udev, 0, 0) < 0) + err("set interface failed"); + + /* Unblock all USB pipes */ + usb_clear_halt(d->udev, + usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); + usb_clear_halt(d->udev, + usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint)); + usb_clear_halt(d->udev, + usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint)); + + /* attach frontend */ + memset(&si2168_config, 0, sizeof(si2168_config)); + si2168_config.i2c_adapter = &adapter; + si2168_config.fe = &adap->fe_adap[0].fe; + si2168_config.ts_mode = SI2168_TS_PARALLEL; + si2168_config.ts_clock_inv = 1; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2168", I2C_NAME_SIZE); + info.addr = 0x64; + info.platform_data = &si2168_config; + request_module(info.type); + client_demod = i2c_new_device(&d->i2c_adap, &info); + if (client_demod == NULL || client_demod->dev.driver == NULL) + return -ENODEV; + + if (!try_module_get(client_demod->dev.driver->owner)) { + i2c_unregister_device(client_demod); + return -ENODEV; + } + + /* attach tuner */ + memset(&si2157_config, 0, sizeof(si2157_config)); + si2157_config.fe = adap->fe_adap[0].fe; + memset(&info, 0, sizeof(struct i2c_board_info)); + strlcpy(info.type, "si2141", I2C_NAME_SIZE); + info.addr = 0x60; + info.platform_data = &si2157_config; + request_module("si2157"); + client_tuner = i2c_new_device(adapter, &info); + if (client_tuner == NULL || client_tuner->dev.driver == NULL) { + module_put(client_demod->dev.driver->owner); + i2c_unregister_device(client_demod); + return -ENODEV; + } + if (!try_module_get(client_tuner->dev.driver->owner)) { + i2c_unregister_device(client_tuner); + module_put(client_demod->dev.driver->owner); + i2c_unregister_device(client_demod); + return -ENODEV; + } + + st->i2c_client_demod = client_demod; + st->i2c_client_tuner = client_tuner; + + /* hook fe: need to resync the slave fifo when signal locks. */ + mutex_init(&st->stream_mutex); + st->last_lock = 0; + st->fe_read_status = adap->fe_adap[0].fe->ops.read_status; + adap->fe_adap[0].fe->ops.read_status = cxusb_read_status; + + return 0; +} + /* * DViCO has shipped two devices with the same USB ID, but only one of them * needs a firmware download. Check the device class details to see if they @@ -1321,6 +1397,7 @@ static struct dvb_usb_device_properties cxusb_aver_a868r_properties; static struct dvb_usb_device_properties cxusb_d680_dmb_properties; static struct dvb_usb_device_properties cxusb_mygica_d689_properties; static struct dvb_usb_device_properties cxusb_mygica_t230_properties; +static struct dvb_usb_device_properties cxusb_mygica_t230c_properties; static int cxusb_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -1353,6 +1430,8 @@ static int cxusb_probe(struct usb_interface *intf, THIS_MODULE, NULL, adapter_nr) || 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties, THIS_MODULE, NULL, adapter_nr) || + 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230c_properties, + THIS_MODULE, NULL, adapter_nr) || 0) return 0; @@ -1404,6 +1483,7 @@ enum cxusb_table_index { CONEXANT_D680_DMB, MYGICA_D689, MYGICA_T230, + MYGICA_T230C, NR__cxusb_table_index }; @@ -1471,6 +1551,9 @@ static struct usb_device_id cxusb_table[NR__cxusb_table_index + 1] = { [MYGICA_T230] = { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230) }, + [MYGICA_T230C] = { + USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230+1) + }, {} /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, cxusb_table); @@ -2165,7 +2248,7 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties = { .rc.core = { .rc_interval = 100, - .rc_codes = RC_MAP_D680_DMB, + .rc_codes = RC_MAP_TOTAL_MEDIA_IN_HAND_02, .module_name = KBUILD_MODNAME, .rc_query = cxusb_d680_dmb_rc_query, .allowed_protos = RC_BIT_UNKNOWN, @@ -2181,6 +2264,60 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties = { } }; +static struct dvb_usb_device_properties cxusb_mygica_t230c_properties = { + .caps = DVB_USB_IS_AN_I2C_ADAPTER, + + .usb_ctrl = CYPRESS_FX2, + + .size_of_priv = sizeof(struct cxusb_state), + + .num_adapters = 1, + .adapter = { + { + .num_frontends = 1, + .fe = {{ + .streaming_ctrl = cxusb_streaming_ctrl, + .frontend_attach = cxusb_mygica_t230c_frontend_attach, + + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_BULK, + .count = 5, + .endpoint = 0x02, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, + } }, + }, + }, + + .power_ctrl = cxusb_d680_dmb_power_ctrl, + + .i2c_algo = &cxusb_i2c_algo, + + .generic_bulk_ctrl_endpoint = 0x01, + + .rc.core = { + .rc_interval = 100, + .rc_codes = RC_MAP_TOTAL_MEDIA_IN_HAND_02, + .module_name = KBUILD_MODNAME, + .rc_query = cxusb_d680_dmb_rc_query, + .allowed_protos = RC_BIT_UNKNOWN, + }, + + .num_device_descs = 1, + .devices = { + { + "Mygica T230C DVB-T/T2/C", + { NULL }, + { &cxusb_table[MYGICA_T230C], NULL }, + }, + } +}; + static struct usb_driver cxusb_driver = { .name = "dvb_usb_cxusb", .probe = cxusb_probe, -- cgit v1.2.3 From f9fa0f2bebaa629aff839b7b992298b1fce453d2 Mon Sep 17 00:00:00 2001 From: Stefan Brüns <stefan.bruens@rwth-aachen.de> Date: Sun, 12 Feb 2017 13:02:13 -0200 Subject: [media] dvb-usb-firmware: don't do DMA on stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The buffer allocation for the firmware data was changed in commit 43fab9793c1f ("[media] dvb-usb: don't use stack for firmware load") but the same applies for the reset value. Fixes: 43fab9793c1f ("[media] dvb-usb: don't use stack for firmware load") Cc: stable@vger.kernel.org Signed-off-by: Stefan Brüns <stefan.bruens@rwth-aachen.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/dvb-usb/dvb-usb-firmware.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c index ab9866024ec7..04033efe7ad5 100644 --- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c +++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c @@ -36,16 +36,18 @@ static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 le int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type) { struct hexline *hx; - u8 reset; - int ret,pos=0; + u8 *buf; + int ret, pos = 0; + u16 cpu_cs_register = cypress[type].cpu_cs_register; - hx = kmalloc(sizeof(*hx), GFP_KERNEL); - if (!hx) + buf = kmalloc(sizeof(*hx), GFP_KERNEL); + if (!buf) return -ENOMEM; + hx = (struct hexline *)buf; /* stop the CPU */ - reset = 1; - if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) + buf[0] = 1; + if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) err("could not stop the USB controller CPU."); while ((ret = dvb_usb_get_hexline(fw, hx, &pos)) > 0) { @@ -61,21 +63,21 @@ int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw } if (ret < 0) { err("firmware download failed at %d with %d",pos,ret); - kfree(hx); + kfree(buf); return ret; } if (ret == 0) { /* restart the CPU */ - reset = 0; - if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) { + buf[0] = 0; + if (usb_cypress_writemem(udev, cpu_cs_register, buf, 1) != 1) { err("could not restart the USB controller CPU."); ret = -EINVAL; } } else ret = -EIO; - kfree(hx); + kfree(buf); return ret; } -- cgit v1.2.3 From c3d173a396c2700cb1ba02744fdc112f461f8177 Mon Sep 17 00:00:00 2001 From: Gustavo Padovan <gustavo.padovan@collabora.com> Date: Wed, 15 Feb 2017 15:55:33 -0200 Subject: [media] go7007: improve subscribe event handling We already check for the V4L2_EVENT_CTRL inside v4l2_ctrl_subscribe_event() so just move this function to the default: branch of the switch and let it does the job for us. Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/go7007/go7007-v4l2.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c index 4eaba0c24629..ed5ec9773969 100644 --- a/drivers/media/usb/go7007/go7007-v4l2.c +++ b/drivers/media/usb/go7007/go7007-v4l2.c @@ -792,14 +792,13 @@ static int vidioc_subscribe_event(struct v4l2_fh *fh, { switch (sub->type) { - case V4L2_EVENT_CTRL: - return v4l2_ctrl_subscribe_event(fh, sub); case V4L2_EVENT_MOTION_DET: /* Allow for up to 30 events (1 second for NTSC) to be * stored. */ return v4l2_event_subscribe(fh, sub, 30, NULL); + default: + return v4l2_ctrl_subscribe_event(fh, sub); } - return -EINVAL; } -- cgit v1.2.3 From 9e00695364fb74f3aa9912a6a686db8446dcd695 Mon Sep 17 00:00:00 2001 From: Frank Schaefer <fschaefer.oss@googlemail.com> Date: Sun, 19 Feb 2017 15:29:17 -0300 Subject: [media] em28xx: reduce stack usage in sensor probing functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's no longer necessary to keep the i2c_client in the device struct unmodified until a sensor is found, so reduce stack usage in em28xx_probe_sensor_micron() and em28xx_probe_sensor_omnivision() by using a pointer to the client instead of a local copy. Reported-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/em28xx-camera.c | 42 +++++++++++++++----------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 89c890ba7dd6..7b4129ab1cf9 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -110,44 +110,44 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) __be16 id_be; u16 id; - struct i2c_client client = dev->i2c_client[dev->def_i2c_bus]; + struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; dev->em28xx_sensor = EM28XX_NOSENSOR; for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { - client.addr = micron_sensor_addrs[i]; + client->addr = micron_sensor_addrs[i]; /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ /* Read chip ID from register 0x00 */ reg = 0x00; - ret = i2c_master_send(&client, ®, 1); + ret = i2c_master_send(client, ®, 1); if (ret < 0) { if (ret != -ENXIO) dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + client->addr << 1, ret); continue; } - ret = i2c_master_recv(&client, (u8 *)&id_be, 2); + ret = i2c_master_recv(client, (u8 *)&id_be, 2); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + client->addr << 1, ret); continue; } id = be16_to_cpu(id_be); /* Read chip ID from register 0xff */ reg = 0xff; - ret = i2c_master_send(&client, ®, 1); + ret = i2c_master_send(client, ®, 1); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + client->addr << 1, ret); continue; } - ret = i2c_master_recv(&client, (u8 *)&id_be, 2); + ret = i2c_master_recv(client, (u8 *)&id_be, 2); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + client->addr << 1, ret); continue; } /* Validate chip ID to be sure we have a Micron device */ @@ -197,7 +197,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) dev_info(&dev->intf->dev, "sensor %s detected\n", name); - dev->i2c_client[dev->def_i2c_bus].addr = client.addr; return 0; } @@ -213,30 +212,30 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev) char *name; u8 reg; u16 id; - struct i2c_client client = dev->i2c_client[dev->def_i2c_bus]; + struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; dev->em28xx_sensor = EM28XX_NOSENSOR; /* NOTE: these devices have the register auto incrementation disabled * by default, so we have to use single byte reads ! */ for (i = 0; omnivision_sensor_addrs[i] != I2C_CLIENT_END; i++) { - client.addr = omnivision_sensor_addrs[i]; + client->addr = omnivision_sensor_addrs[i]; /* Read manufacturer ID from registers 0x1c-0x1d (BE) */ reg = 0x1c; - ret = i2c_smbus_read_byte_data(&client, reg); + ret = i2c_smbus_read_byte_data(client, reg); if (ret < 0) { if (ret != -ENXIO) dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + client->addr << 1, ret); continue; } id = ret << 8; reg = 0x1d; - ret = i2c_smbus_read_byte_data(&client, reg); + ret = i2c_smbus_read_byte_data(client, reg); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + client->addr << 1, ret); continue; } id += ret; @@ -245,20 +244,20 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev) continue; /* Read product ID from registers 0x0a-0x0b (BE) */ reg = 0x0a; - ret = i2c_smbus_read_byte_data(&client, reg); + ret = i2c_smbus_read_byte_data(client, reg); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + client->addr << 1, ret); continue; } id = ret << 8; reg = 0x0b; - ret = i2c_smbus_read_byte_data(&client, reg); + ret = i2c_smbus_read_byte_data(client, reg); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", - client.addr << 1, ret); + client->addr << 1, ret); continue; } id += ret; @@ -309,7 +308,6 @@ static int em28xx_probe_sensor_omnivision(struct em28xx *dev) dev_info(&dev->intf->dev, "sensor %s detected\n", name); - dev->i2c_client[dev->def_i2c_bus].addr = client.addr; return 0; } -- cgit v1.2.3 From 207c957d9e70d1eb8f98c028524dff3befc07f42 Mon Sep 17 00:00:00 2001 From: Sean Young <sean@mess.org> Date: Sat, 4 Feb 2017 17:00:36 -0200 Subject: [media] cxusb: dvico remotes are nec Adjust the keymap to use the correct nec scancodes, and adjust the rc driver to output the correct nec scancodes. Now the keymap can be used with any nec receiver, and the rc device should work with any nec keymap. Tested-by: Vincent McIntyre <vincent.mcintyre@gmail.com> Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/rc/keymaps/rc-dvico-mce.c | 92 ++++++++++++++-------------- drivers/media/rc/keymaps/rc-dvico-portable.c | 74 +++++++++++----------- drivers/media/usb/dvb-usb/cxusb.c | 24 ++++---- 3 files changed, 95 insertions(+), 95 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/rc/keymaps/rc-dvico-mce.c b/drivers/media/rc/keymaps/rc-dvico-mce.c index e5f098c50235..d1e861f4d095 100644 --- a/drivers/media/rc/keymaps/rc-dvico-mce.c +++ b/drivers/media/rc/keymaps/rc-dvico-mce.c @@ -12,58 +12,58 @@ #include <linux/module.h> static struct rc_map_table rc_map_dvico_mce_table[] = { - { 0xfe02, KEY_TV }, - { 0xfe0e, KEY_MP3 }, - { 0xfe1a, KEY_DVD }, - { 0xfe1e, KEY_FAVORITES }, - { 0xfe16, KEY_SETUP }, - { 0xfe46, KEY_POWER2 }, - { 0xfe0a, KEY_EPG }, - { 0xfe49, KEY_BACK }, - { 0xfe4d, KEY_MENU }, - { 0xfe51, KEY_UP }, - { 0xfe5b, KEY_LEFT }, - { 0xfe5f, KEY_RIGHT }, - { 0xfe53, KEY_DOWN }, - { 0xfe5e, KEY_OK }, - { 0xfe59, KEY_INFO }, - { 0xfe55, KEY_TAB }, - { 0xfe0f, KEY_PREVIOUSSONG },/* Replay */ - { 0xfe12, KEY_NEXTSONG }, /* Skip */ - { 0xfe42, KEY_ENTER }, /* Windows/Start */ - { 0xfe15, KEY_VOLUMEUP }, - { 0xfe05, KEY_VOLUMEDOWN }, - { 0xfe11, KEY_CHANNELUP }, - { 0xfe09, KEY_CHANNELDOWN }, - { 0xfe52, KEY_CAMERA }, - { 0xfe5a, KEY_TUNER }, /* Live */ - { 0xfe19, KEY_OPEN }, - { 0xfe0b, KEY_1 }, - { 0xfe17, KEY_2 }, - { 0xfe1b, KEY_3 }, - { 0xfe07, KEY_4 }, - { 0xfe50, KEY_5 }, - { 0xfe54, KEY_6 }, - { 0xfe48, KEY_7 }, - { 0xfe4c, KEY_8 }, - { 0xfe58, KEY_9 }, - { 0xfe13, KEY_ANGLE }, /* Aspect */ - { 0xfe03, KEY_0 }, - { 0xfe1f, KEY_ZOOM }, - { 0xfe43, KEY_REWIND }, - { 0xfe47, KEY_PLAYPAUSE }, - { 0xfe4f, KEY_FASTFORWARD }, - { 0xfe57, KEY_MUTE }, - { 0xfe0d, KEY_STOP }, - { 0xfe01, KEY_RECORD }, - { 0xfe4e, KEY_POWER }, + { 0x0102, KEY_TV }, + { 0x010e, KEY_MP3 }, + { 0x011a, KEY_DVD }, + { 0x011e, KEY_FAVORITES }, + { 0x0116, KEY_SETUP }, + { 0x0146, KEY_POWER2 }, + { 0x010a, KEY_EPG }, + { 0x0149, KEY_BACK }, + { 0x014d, KEY_MENU }, + { 0x0151, KEY_UP }, + { 0x015b, KEY_LEFT }, + { 0x015f, KEY_RIGHT }, + { 0x0153, KEY_DOWN }, + { 0x015e, KEY_OK }, + { 0x0159, KEY_INFO }, + { 0x0155, KEY_TAB }, + { 0x010f, KEY_PREVIOUSSONG },/* Replay */ + { 0x0112, KEY_NEXTSONG }, /* Skip */ + { 0x0142, KEY_ENTER }, /* Windows/Start */ + { 0x0115, KEY_VOLUMEUP }, + { 0x0105, KEY_VOLUMEDOWN }, + { 0x0111, KEY_CHANNELUP }, + { 0x0109, KEY_CHANNELDOWN }, + { 0x0152, KEY_CAMERA }, + { 0x015a, KEY_TUNER }, /* Live */ + { 0x0119, KEY_OPEN }, + { 0x010b, KEY_1 }, + { 0x0117, KEY_2 }, + { 0x011b, KEY_3 }, + { 0x0107, KEY_4 }, + { 0x0150, KEY_5 }, + { 0x0154, KEY_6 }, + { 0x0148, KEY_7 }, + { 0x014c, KEY_8 }, + { 0x0158, KEY_9 }, + { 0x0113, KEY_ANGLE }, /* Aspect */ + { 0x0103, KEY_0 }, + { 0x011f, KEY_ZOOM }, + { 0x0143, KEY_REWIND }, + { 0x0147, KEY_PLAYPAUSE }, + { 0x014f, KEY_FASTFORWARD }, + { 0x0157, KEY_MUTE }, + { 0x010d, KEY_STOP }, + { 0x0101, KEY_RECORD }, + { 0x014e, KEY_POWER }, }; static struct rc_map_list dvico_mce_map = { .map = { .scan = rc_map_dvico_mce_table, .size = ARRAY_SIZE(rc_map_dvico_mce_table), - .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_NEC, .name = RC_MAP_DVICO_MCE, } }; diff --git a/drivers/media/rc/keymaps/rc-dvico-portable.c b/drivers/media/rc/keymaps/rc-dvico-portable.c index 94ceeee94b3f..ac4cb515cbf1 100644 --- a/drivers/media/rc/keymaps/rc-dvico-portable.c +++ b/drivers/media/rc/keymaps/rc-dvico-portable.c @@ -12,49 +12,49 @@ #include <linux/module.h> static struct rc_map_table rc_map_dvico_portable_table[] = { - { 0xfc02, KEY_SETUP }, /* Profile */ - { 0xfc43, KEY_POWER2 }, - { 0xfc06, KEY_EPG }, - { 0xfc5a, KEY_BACK }, - { 0xfc05, KEY_MENU }, - { 0xfc47, KEY_INFO }, - { 0xfc01, KEY_TAB }, - { 0xfc42, KEY_PREVIOUSSONG },/* Replay */ - { 0xfc49, KEY_VOLUMEUP }, - { 0xfc09, KEY_VOLUMEDOWN }, - { 0xfc54, KEY_CHANNELUP }, - { 0xfc0b, KEY_CHANNELDOWN }, - { 0xfc16, KEY_CAMERA }, - { 0xfc40, KEY_TUNER }, /* ATV/DTV */ - { 0xfc45, KEY_OPEN }, - { 0xfc19, KEY_1 }, - { 0xfc18, KEY_2 }, - { 0xfc1b, KEY_3 }, - { 0xfc1a, KEY_4 }, - { 0xfc58, KEY_5 }, - { 0xfc59, KEY_6 }, - { 0xfc15, KEY_7 }, - { 0xfc14, KEY_8 }, - { 0xfc17, KEY_9 }, - { 0xfc44, KEY_ANGLE }, /* Aspect */ - { 0xfc55, KEY_0 }, - { 0xfc07, KEY_ZOOM }, - { 0xfc0a, KEY_REWIND }, - { 0xfc08, KEY_PLAYPAUSE }, - { 0xfc4b, KEY_FASTFORWARD }, - { 0xfc5b, KEY_MUTE }, - { 0xfc04, KEY_STOP }, - { 0xfc56, KEY_RECORD }, - { 0xfc57, KEY_POWER }, - { 0xfc41, KEY_UNKNOWN }, /* INPUT */ - { 0xfc00, KEY_UNKNOWN }, /* HD */ + { 0x0302, KEY_SETUP }, /* Profile */ + { 0x0343, KEY_POWER2 }, + { 0x0306, KEY_EPG }, + { 0x035a, KEY_BACK }, + { 0x0305, KEY_MENU }, + { 0x0347, KEY_INFO }, + { 0x0301, KEY_TAB }, + { 0x0342, KEY_PREVIOUSSONG },/* Replay */ + { 0x0349, KEY_VOLUMEUP }, + { 0x0309, KEY_VOLUMEDOWN }, + { 0x0354, KEY_CHANNELUP }, + { 0x030b, KEY_CHANNELDOWN }, + { 0x0316, KEY_CAMERA }, + { 0x0340, KEY_TUNER }, /* ATV/DTV */ + { 0x0345, KEY_OPEN }, + { 0x0319, KEY_1 }, + { 0x0318, KEY_2 }, + { 0x031b, KEY_3 }, + { 0x031a, KEY_4 }, + { 0x0358, KEY_5 }, + { 0x0359, KEY_6 }, + { 0x0315, KEY_7 }, + { 0x0314, KEY_8 }, + { 0x0317, KEY_9 }, + { 0x0344, KEY_ANGLE }, /* Aspect */ + { 0x0355, KEY_0 }, + { 0x0307, KEY_ZOOM }, + { 0x030a, KEY_REWIND }, + { 0x0308, KEY_PLAYPAUSE }, + { 0x034b, KEY_FASTFORWARD }, + { 0x035b, KEY_MUTE }, + { 0x0304, KEY_STOP }, + { 0x0356, KEY_RECORD }, + { 0x0357, KEY_POWER }, + { 0x0341, KEY_UNKNOWN }, /* INPUT */ + { 0x0300, KEY_UNKNOWN }, /* HD */ }; static struct rc_map_list dvico_portable_map = { .map = { .scan = rc_map_dvico_portable_table, .size = ARRAY_SIZE(rc_map_dvico_portable_table), - .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */ + .rc_type = RC_TYPE_NEC, .name = RC_MAP_DVICO_PORTABLE, } }; diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 9a7665fddc29..99a3f3625944 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -458,8 +458,8 @@ static int cxusb_rc_query(struct dvb_usb_device *d) cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4); if (ircode[2] || ircode[3]) - rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, - RC_SCANCODE_RC5(ircode[2], ircode[3]), 0); + rc_keydown(d->rc_dev, RC_TYPE_NEC, + RC_SCANCODE_NEC(~ircode[2] & 0xff, ircode[3]), 0); return 0; } @@ -473,8 +473,8 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d) return 0; if (ircode[1] || ircode[2]) - rc_keydown(d->rc_dev, RC_TYPE_UNKNOWN, - RC_SCANCODE_RC5(ircode[1], ircode[2]), 0); + rc_keydown(d->rc_dev, RC_TYPE_NEC, + RC_SCANCODE_NEC(~ircode[1] & 0xff, ircode[2]), 0); return 0; } @@ -1646,7 +1646,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = { .rc_codes = RC_MAP_DVICO_PORTABLE, .module_name = KBUILD_MODNAME, .rc_query = cxusb_rc_query, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_BIT_NEC, }, .generic_bulk_ctrl_endpoint = 0x01, @@ -1703,7 +1703,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = { .rc_codes = RC_MAP_DVICO_MCE, .module_name = KBUILD_MODNAME, .rc_query = cxusb_rc_query, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_BIT_NEC, }, .generic_bulk_ctrl_endpoint = 0x01, @@ -1768,7 +1768,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { .rc_codes = RC_MAP_DVICO_PORTABLE, .module_name = KBUILD_MODNAME, .rc_query = cxusb_rc_query, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_BIT_NEC, }, .generic_bulk_ctrl_endpoint = 0x01, @@ -1824,7 +1824,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = { .rc_codes = RC_MAP_DVICO_PORTABLE, .module_name = KBUILD_MODNAME, .rc_query = cxusb_rc_query, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_BIT_NEC, }, .generic_bulk_ctrl_endpoint = 0x01, @@ -1879,7 +1879,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = { .rc_codes = RC_MAP_DVICO_MCE, .module_name = KBUILD_MODNAME, .rc_query = cxusb_bluebird2_rc_query, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_BIT_NEC, }, .num_device_descs = 1, @@ -1933,7 +1933,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = { .rc_codes = RC_MAP_DVICO_PORTABLE, .module_name = KBUILD_MODNAME, .rc_query = cxusb_bluebird2_rc_query, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_BIT_NEC, }, .num_device_descs = 1, @@ -1989,7 +1989,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope .rc_codes = RC_MAP_DVICO_PORTABLE, .module_name = KBUILD_MODNAME, .rc_query = cxusb_rc_query, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_BIT_NEC, }, .num_device_descs = 1, @@ -2088,7 +2088,7 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = { .rc_codes = RC_MAP_DVICO_MCE, .module_name = KBUILD_MODNAME, .rc_query = cxusb_rc_query, - .allowed_protos = RC_BIT_UNKNOWN, + .allowed_protos = RC_BIT_NEC, }, .num_device_descs = 1, -- cgit v1.2.3 From aa58fedb8c7b6cf2f05941d238495f9e2f29655c Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@kernel.org> Date: Mon, 13 Mar 2017 09:53:59 -0300 Subject: [media] gspca: konica: add missing endpoint sanity check Make sure to check the number of endpoints to avoid accessing memory beyond the endpoint array should a device lack the expected endpoints. Note that, as far as I can tell, the gspca framework has already made sure there is at least one endpoint in the current alternate setting so there should be no risk for a NULL-pointer dereference here. Fixes: b517af722860 ("V4L/DVB: gspca_konica: New gspca subdriver for konica chipset using cams") Cc: stable <stable@vger.kernel.org> # 2.6.37 Cc: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Hans Verkuil <hansverk@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/gspca/konica.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c index 71f273377f83..31b2117e8f1d 100644 --- a/drivers/media/usb/gspca/konica.c +++ b/drivers/media/usb/gspca/konica.c @@ -184,6 +184,9 @@ static int sd_start(struct gspca_dev *gspca_dev) return -EIO; } + if (alt->desc.bNumEndpoints < 2) + return -ENODEV; + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv; -- cgit v1.2.3 From 49375e68fec71d067ea02e74386cf6171bab85f5 Mon Sep 17 00:00:00 2001 From: Colin Ian King <colin.king@canonical.com> Date: Wed, 22 Mar 2017 13:32:01 -0300 Subject: [media] usb: au0828: remove redundant code The check for ret being non-zero is false as ret is always zero, hence we have redundant dead code that can be removed. Detected with CoverityScan, CID#112968 ("Constant' variable guards dead code (DEADCODE)'") Signed-off-by: Colin Ian King <colin.king@canonical.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/au0828/au0828-video.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 16f9125a985a..2a255bd32bb3 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -809,16 +809,9 @@ static void au0828_analog_stream_reset(struct au0828_dev *dev) */ static int au0828_stream_interrupt(struct au0828_dev *dev) { - int ret = 0; - dev->stream_state = STREAM_INTERRUPT; if (test_bit(DEV_DISCONNECTED, &dev->dev_state)) return -ENODEV; - else if (ret) { - set_bit(DEV_MISCONFIGURED, &dev->dev_state); - dprintk(1, "%s device is misconfigured!\n", __func__); - return ret; - } return 0; } -- cgit v1.2.3 From bb25db504771d3d9b176ee9a5e3eb579cf4e3002 Mon Sep 17 00:00:00 2001 From: Jose Abreu <Jose.Abreu@synopsys.com> Date: Fri, 24 Mar 2017 13:47:58 -0300 Subject: [media] usb: pulse8-cec: Use cec_get_drvdata() Use helper function to get driver private data from CEC adapter. Signed-off-by: Jose Abreu <joabreu@synopsys.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/pulse8-cec/pulse8-cec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c index 7c18daeb0ade..1dfc2de1fe77 100644 --- a/drivers/media/usb/pulse8-cec/pulse8-cec.c +++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c @@ -461,7 +461,7 @@ static int pulse8_apply_persistent_config(struct pulse8 *pulse8, static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable) { - struct pulse8 *pulse8 = adap->priv; + struct pulse8 *pulse8 = cec_get_drvdata(adap); u8 cmd[16]; int err; @@ -474,7 +474,7 @@ static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable) static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) { - struct pulse8 *pulse8 = adap->priv; + struct pulse8 *pulse8 = cec_get_drvdata(adap); u16 mask = 0; u16 pa = adap->phys_addr; u8 cmd[16]; @@ -594,7 +594,7 @@ unlock: static int pulse8_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg) { - struct pulse8 *pulse8 = adap->priv; + struct pulse8 *pulse8 = cec_get_drvdata(adap); u8 cmd[2]; unsigned int i; int err; -- cgit v1.2.3 From d5823511c0f8719a39e72ede1bce65411ac653b7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@kernel.org> Date: Mon, 13 Mar 2017 09:53:54 -0300 Subject: [media] dib0700: fix NULL-deref at probe Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer should a malicious device lack endpoints. Fixes: c4018fa2e4c0 ("[media] dib0700: fix RC support on Hauppauge Nova-TD") Cc: stable <stable@vger.kernel.org> # 3.16 Cc: Mauro Carvalho Chehab <mchehab@kernel.org> Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/dvb-usb/dib0700_core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index dd5edd3a17ee..08acdd32e412 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -809,6 +809,9 @@ int dib0700_rc_setup(struct dvb_usb_device *d, struct usb_interface *intf) /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */ + if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1) + return -ENODEV; + purb = usb_alloc_urb(0, GFP_KERNEL); if (purb == NULL) return -ENOMEM; -- cgit v1.2.3 From eacb975b48272f54532b62f515a3cf7eefa35123 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@kernel.org> Date: Mon, 13 Mar 2017 09:53:55 -0300 Subject: [media] usbvision: fix NULL-deref at probe Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer or accessing memory beyond the endpoint array should a malicious device lack the expected endpoints. Fixes: 2a9f8b5d25be ("V4L/DVB (5206): Usbvision: set alternate interface modification") Cc: stable <stable@vger.kernel.org> # 2.6.21 Cc: Thierry MERLE <thierry.merle@free.fr> Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/usbvision/usbvision-video.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c index f5c635a67d74..f9c3325aa4d4 100644 --- a/drivers/media/usb/usbvision/usbvision-video.c +++ b/drivers/media/usb/usbvision/usbvision-video.c @@ -1501,7 +1501,14 @@ static int usbvision_probe(struct usb_interface *intf, } for (i = 0; i < usbvision->num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < 2) { + ret = -ENODEV; + goto err_pkt; + } + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc. wMaxPacketSize); usbvision->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); -- cgit v1.2.3 From 0cd273bb5e4d1828efaaa8dfd11b7928131ed149 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@kernel.org> Date: Mon, 13 Mar 2017 09:53:56 -0300 Subject: [media] cx231xx-cards: fix NULL-deref at probe Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer or accessing memory beyond the endpoint array should a malicious device lack the expected endpoints. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Cc: stable <stable@vger.kernel.org> # 2.6.30 Cc: Sri Deevi <Srinivasa.Deevi@conexant.com> Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/cx231xx/cx231xx-cards.c | 45 +++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index 9b28d57006af..a1007d005290 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1425,6 +1425,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, uif = udev->actconfig->interface[idx]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress; dev->video_mode.num_alt = uif->num_altsetting; @@ -1438,7 +1441,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, return -ENOMEM; for (i = 0; i < dev->video_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); dev_dbg(dev->dev, "Alternate setting %i, max size= %i\n", i, @@ -1455,6 +1463,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, } uif = udev->actconfig->interface[idx]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + dev->vbi_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc. bEndpointAddress; @@ -1471,8 +1482,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, return -ENOMEM; for (i = 0; i < dev->vbi_mode.num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. desc.wMaxPacketSize); dev->vbi_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); @@ -1492,6 +1507,9 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, } uif = udev->actconfig->interface[idx]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + dev->sliced_cc_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc. bEndpointAddress; @@ -1506,7 +1524,12 @@ static int cx231xx_init_v4l2(struct cx231xx *dev, return -ENOMEM; for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) + return -ENODEV; + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe]. desc.wMaxPacketSize); dev->sliced_cc_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); @@ -1675,6 +1698,11 @@ static int cx231xx_usb_probe(struct usb_interface *interface, } uif = udev->actconfig->interface[idx]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) { + retval = -ENODEV; + goto err_video_alt; + } + dev->ts1_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe]. desc.bEndpointAddress; @@ -1692,7 +1720,14 @@ static int cx231xx_usb_probe(struct usb_interface *interface, } for (i = 0; i < dev->ts1_mode.num_alt; i++) { - u16 tmp = le16_to_cpu(uif->altsetting[i]. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) { + retval = -ENODEV; + goto err_video_alt; + } + + tmp = le16_to_cpu(uif->altsetting[i]. endpoint[isoc_pipe].desc. wMaxPacketSize); dev->ts1_mode.alt_max_pkt_size[i] = -- cgit v1.2.3 From fff1abc4d54e469140a699612b4db8d6397bfcba Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@kernel.org> Date: Mon, 13 Mar 2017 09:53:57 -0300 Subject: [media] cx231xx-audio: fix init error path Make sure to release the snd_card also on a late allocation error. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Cc: stable <stable@vger.kernel.org> # 2.6.30 Cc: Sri Deevi <Srinivasa.Deevi@conexant.com> Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/cx231xx/cx231xx-audio.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index cf80842dfa08..f3729d6eb46a 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -670,10 +670,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm); - if (err < 0) { - snd_card_free(card); - return err; - } + if (err < 0) + goto err_free_card; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx231xx_pcm_capture); @@ -687,10 +685,9 @@ static int cx231xx_audio_init(struct cx231xx *dev) INIT_WORK(&dev->wq_trigger, audio_trigger); err = snd_card_register(card); - if (err < 0) { - snd_card_free(card); - return err; - } + if (err < 0) + goto err_free_card; + adev->sndcard = card; adev->udev = dev->udev; @@ -709,9 +706,10 @@ static int cx231xx_audio_init(struct cx231xx *dev) "audio EndPoint Addr 0x%x, Alternate settings: %i\n", adev->end_point_addr, adev->num_alt); adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL); - - if (adev->alt_max_pkt_size == NULL) - return -ENOMEM; + if (!adev->alt_max_pkt_size) { + err = -ENOMEM; + goto err_free_card; + } for (i = 0; i < adev->num_alt; i++) { u16 tmp = @@ -725,6 +723,11 @@ static int cx231xx_audio_init(struct cx231xx *dev) } return 0; + +err_free_card: + snd_card_free(card); + + return err; } static int cx231xx_audio_fini(struct cx231xx *dev) -- cgit v1.2.3 From 65f921647f4c89a2068478c89691f39b309b58f7 Mon Sep 17 00:00:00 2001 From: Johan Hovold <johan@kernel.org> Date: Mon, 13 Mar 2017 09:53:58 -0300 Subject: [media] cx231xx-audio: fix NULL-deref at probe Make sure to check the number of endpoints to avoid dereferencing a NULL-pointer or accessing memory beyond the endpoint array should a malicious device lack the expected endpoints. Fixes: e0d3bafd0258 ("V4L/DVB (10954): Add cx231xx USB driver") Cc: stable <stable@vger.kernel.org> # 2.6.30 Cc: Sri Deevi <Srinivasa.Deevi@conexant.com> Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/cx231xx/cx231xx-audio.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c index f3729d6eb46a..a050d125934c 100644 --- a/drivers/media/usb/cx231xx/cx231xx-audio.c +++ b/drivers/media/usb/cx231xx/cx231xx-audio.c @@ -697,6 +697,11 @@ static int cx231xx_audio_init(struct cx231xx *dev) hs_config_info[0].interface_info. audio_index + 1]; + if (uif->altsetting[0].desc.bNumEndpoints < isoc_pipe + 1) { + err = -ENODEV; + goto err_free_card; + } + adev->end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc. bEndpointAddress; @@ -712,8 +717,14 @@ static int cx231xx_audio_init(struct cx231xx *dev) } for (i = 0; i < adev->num_alt; i++) { - u16 tmp = - le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. + u16 tmp; + + if (uif->altsetting[i].desc.bNumEndpoints < isoc_pipe + 1) { + err = -ENODEV; + goto err_free_pkt_size; + } + + tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc. wMaxPacketSize); adev->alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1); @@ -724,6 +735,8 @@ static int cx231xx_audio_init(struct cx231xx *dev) return 0; +err_free_pkt_size: + kfree(adev->alt_max_pkt_size); err_free_card: snd_card_free(card); -- cgit v1.2.3 From 360a3a90c6261fe24a959ff38f8f6c3a8468f23c Mon Sep 17 00:00:00 2001 From: Kieran Bingham <kieran.bingham@ideasonboard.com> Date: Mon, 3 Apr 2017 08:25:32 -0300 Subject: [media] uvcvideo: Fix empty packet statistic The frame counters are inadvertently counting packets with content as empty. Fix it by correcting the logic expression Fixes: 7bc5edb00bbd [media] uvcvideo: Extract video stream statistics Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/uvc/uvc_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 07a6c833ef7b..128c0a7826ce 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -818,7 +818,7 @@ static void uvc_video_stats_decode(struct uvc_streaming *stream, /* Update the packets counters. */ stream->stats.frame.nb_packets++; - if (len > header_size) + if (len <= header_size) stream->stats.frame.nb_empty++; if (data[1] & UVC_STREAM_ERR) -- cgit v1.2.3 From 52276df0b1ce3a833293f4b57fc3b62d6f540901 Mon Sep 17 00:00:00 2001 From: Kieran Bingham <kieran.bingham@ideasonboard.com> Date: Mon, 3 Apr 2017 08:25:31 -0300 Subject: [media] uvcvideo: Don't record timespec_sub The statistics function subtracts two timespecs manually. A helper is provided by the kernel to do this. Replace the implementation, using the helper. Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/uvc/uvc_video.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 128c0a7826ce..47d93a938dde 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -868,14 +868,8 @@ size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf, struct timespec ts; size_t count = 0; - ts.tv_sec = stream->stats.stream.stop_ts.tv_sec - - stream->stats.stream.start_ts.tv_sec; - ts.tv_nsec = stream->stats.stream.stop_ts.tv_nsec - - stream->stats.stream.start_ts.tv_nsec; - if (ts.tv_nsec < 0) { - ts.tv_sec--; - ts.tv_nsec += 1000000000; - } + ts = timespec_sub(stream->stats.stream.stop_ts, + stream->stats.stream.start_ts); /* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF * frequency this will not overflow before more than 1h. -- cgit v1.2.3 From c4a0968aea0d887b15d8df15399f8e0dc614aecf Mon Sep 17 00:00:00 2001 From: Daniel Patrick Johnson <teknotus@teknot.us> Date: Thu, 2 Mar 2017 20:43:20 -0300 Subject: [media] uvcvideo: Add support for Intel SR300 depth camera Add support for Intel SR300 depth camera in uvc driver. This includes adding three uvc GUIDs for the required pixel formats and updating the uvc driver GUID-to-4cc tables with the new formats. Signed-off-by: Daniel Patrick Johnson <teknotus@teknot.us> Signed-off-by: Aviv Greenberg <avivgr@gmail.com> Signed-off-by: Evgeni Raikhel <evgeni.raikhel@intel.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/uvc/uvc_driver.c | 15 +++++++++++++++ drivers/media/usb/uvc/uvcvideo.h | 9 +++++++++ 2 files changed, 24 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 04bf35063c4c..46d6be0bb316 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -188,6 +188,21 @@ static struct uvc_format_desc uvc_fmts[] = { .guid = UVC_GUID_FORMAT_GR16, .fcc = V4L2_PIX_FMT_SGRBG16, }, + { + .name = "Depth data 16-bit (Z16)", + .guid = UVC_GUID_FORMAT_INVZ, + .fcc = V4L2_PIX_FMT_Z16, + }, + { + .name = "Greyscale 10-bit (Y10 )", + .guid = UVC_GUID_FORMAT_INVI, + .fcc = V4L2_PIX_FMT_Y10, + }, + { + .name = "IR:Depth 26-bit (INZI)", + .guid = UVC_GUID_FORMAT_INZI, + .fcc = V4L2_PIX_FMT_INZI, + }, }; /* ------------------------------------------------------------------------ diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 4205e7a423f0..15e415e32c7f 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -143,6 +143,15 @@ #define UVC_GUID_FORMAT_RW10 \ { 'R', 'W', '1', '0', 0x00, 0x00, 0x10, 0x00, \ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} +#define UVC_GUID_FORMAT_INVZ \ + { 'I', 'N', 'V', 'Z', 0x90, 0x2d, 0x58, 0x4a, \ + 0x92, 0x0b, 0x77, 0x3f, 0x1f, 0x2c, 0x55, 0x6b} +#define UVC_GUID_FORMAT_INZI \ + { 'I', 'N', 'Z', 'I', 0x66, 0x1a, 0x42, 0xa2, \ + 0x90, 0x65, 0xd0, 0x18, 0x14, 0xa8, 0xef, 0x8a} +#define UVC_GUID_FORMAT_INVI \ + { 'I', 'N', 'V', 'I', 0xdb, 0x57, 0x49, 0x5e, \ + 0x8e, 0x3f, 0xf4, 0x79, 0x53, 0x2b, 0x94, 0x6f} /* ------------------------------------------------------------------------ * Driver specific constants. -- cgit v1.2.3 From 0f314f6c2e77beb1a232be21dd6be4e1849ba5ac Mon Sep 17 00:00:00 2001 From: Hans Verkuil <hans.verkuil@cisco.com> Date: Sat, 5 Nov 2016 08:39:58 -0200 Subject: [media] rainshadow-cec: new RainShadow Tech HDMI CEC driver This driver supports the RainShadow Tech USB HDMI CEC adapter. See: http://rainshadowtech.com/HdmiCecUsb.html Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- MAINTAINERS | 7 + drivers/media/usb/Kconfig | 1 + drivers/media/usb/Makefile | 1 + drivers/media/usb/rainshadow-cec/Kconfig | 10 + drivers/media/usb/rainshadow-cec/Makefile | 1 + drivers/media/usb/rainshadow-cec/rainshadow-cec.c | 388 ++++++++++++++++++++++ 6 files changed, 408 insertions(+) create mode 100644 drivers/media/usb/rainshadow-cec/Kconfig create mode 100644 drivers/media/usb/rainshadow-cec/Makefile create mode 100644 drivers/media/usb/rainshadow-cec/rainshadow-cec.c (limited to 'drivers/media/usb') diff --git a/MAINTAINERS b/MAINTAINERS index baed28a5969a..eb572ccd2d69 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10456,6 +10456,13 @@ L: linux-fbdev@vger.kernel.org S: Maintained F: drivers/video/fbdev/aty/aty128fb.c +RAINSHADOW-CEC DRIVER +M: Hans Verkuil <hverkuil@xs4all.nl> +L: linux-media@vger.kernel.org +T: git git://linuxtv.org/media_tree.git +S: Maintained +F: drivers/media/usb/rainshadow-cec/* + RALINK MIPS ARCHITECTURE M: John Crispin <john@phrozen.org> L: linux-mips@linux-mips.org diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig index c9644b62f91a..b24e753c4766 100644 --- a/drivers/media/usb/Kconfig +++ b/drivers/media/usb/Kconfig @@ -63,6 +63,7 @@ endif if MEDIA_CEC_SUPPORT comment "USB HDMI CEC adapters" source "drivers/media/usb/pulse8-cec/Kconfig" +source "drivers/media/usb/rainshadow-cec/Kconfig" endif endif #MEDIA_USB_SUPPORT diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile index 0f15e3351ddc..738b993ec8b0 100644 --- a/drivers/media/usb/Makefile +++ b/drivers/media/usb/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_VIDEO_USBTV) += usbtv/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_DVB_AS102) += as102/ obj-$(CONFIG_USB_PULSE8_CEC) += pulse8-cec/ +obj-$(CONFIG_USB_RAINSHADOW_CEC) += rainshadow-cec/ diff --git a/drivers/media/usb/rainshadow-cec/Kconfig b/drivers/media/usb/rainshadow-cec/Kconfig new file mode 100644 index 000000000000..447291b3cca3 --- /dev/null +++ b/drivers/media/usb/rainshadow-cec/Kconfig @@ -0,0 +1,10 @@ +config USB_RAINSHADOW_CEC + tristate "RainShadow Tech HDMI CEC" + depends on USB_ACM && MEDIA_CEC_SUPPORT + select SERIO + select SERIO_SERPORT + ---help--- + This is a cec driver for the RainShadow Tech HDMI CEC device. + + To compile this driver as a module, choose M here: the + module will be called rainshadow-cec. diff --git a/drivers/media/usb/rainshadow-cec/Makefile b/drivers/media/usb/rainshadow-cec/Makefile new file mode 100644 index 000000000000..a79fbc77e1f7 --- /dev/null +++ b/drivers/media/usb/rainshadow-cec/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_USB_RAINSHADOW_CEC) += rainshadow-cec.o diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c new file mode 100644 index 000000000000..541ca543f71f --- /dev/null +++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c @@ -0,0 +1,388 @@ +/* + * RainShadow Tech HDMI CEC driver + * + * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version of 2 of the License, or (at your + * option) any later version. See the file COPYING in the main directory of + * this archive for more details. + */ + +/* + * Notes: + * + * The higher level protocols are currently disabled. This can be added + * later, similar to how this is done for the Pulse Eight CEC driver. + * + * Documentation of the protocol is available here: + * + * http://rainshadowtech.com/doc/HDMICECtoUSBandRS232v2.0.pdf + */ + +#include <linux/completion.h> +#include <linux/ctype.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/serio.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/time.h> +#include <linux/workqueue.h> + +#include <media/cec.h> + +MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>"); +MODULE_DESCRIPTION("RainShadow Tech HDMI CEC driver"); +MODULE_LICENSE("GPL"); + +#define DATA_SIZE 256 + +struct rain { + struct device *dev; + struct serio *serio; + struct cec_adapter *adap; + struct completion cmd_done; + struct work_struct work; + + /* Low-level ringbuffer, collecting incoming characters */ + char buf[DATA_SIZE]; + unsigned int buf_rd_idx; + unsigned int buf_wr_idx; + unsigned int buf_len; + spinlock_t buf_lock; + + /* command buffer */ + char cmd[DATA_SIZE]; + unsigned int cmd_idx; + bool cmd_started; + + /* reply to a command, only used to store the firmware version */ + char cmd_reply[DATA_SIZE]; + + struct mutex write_lock; +}; + +static void rain_process_msg(struct rain *rain) +{ + struct cec_msg msg = {}; + const char *cmd = rain->cmd + 3; + int stat = -1; + + for (; *cmd; cmd++) { + if (!isxdigit(*cmd)) + continue; + if (isxdigit(cmd[0]) && isxdigit(cmd[1])) { + if (msg.len == CEC_MAX_MSG_SIZE) + break; + if (hex2bin(msg.msg + msg.len, cmd, 1)) + continue; + msg.len++; + cmd++; + continue; + } + if (!cmd[1]) + stat = hex_to_bin(cmd[0]); + break; + } + + if (rain->cmd[0] == 'R') { + if (stat == 1 || stat == 2) + cec_received_msg(rain->adap, &msg); + return; + } + + switch (stat) { + case 1: + cec_transmit_done(rain->adap, CEC_TX_STATUS_OK, + 0, 0, 0, 0); + break; + case 2: + cec_transmit_done(rain->adap, CEC_TX_STATUS_NACK, + 0, 1, 0, 0); + break; + default: + cec_transmit_done(rain->adap, CEC_TX_STATUS_LOW_DRIVE, + 0, 0, 0, 1); + break; + } +} + +static void rain_irq_work_handler(struct work_struct *work) +{ + struct rain *rain = + container_of(work, struct rain, work); + + while (true) { + unsigned long flags; + bool exit_loop; + char data; + + spin_lock_irqsave(&rain->buf_lock, flags); + exit_loop = rain->buf_len == 0; + if (rain->buf_len) { + data = rain->buf[rain->buf_rd_idx]; + rain->buf_len--; + rain->buf_rd_idx = (rain->buf_rd_idx + 1) & 0xff; + } + spin_unlock_irqrestore(&rain->buf_lock, flags); + + if (exit_loop) + break; + + if (!rain->cmd_started && data != '?') + continue; + + switch (data) { + case '\r': + rain->cmd[rain->cmd_idx] = '\0'; + dev_dbg(rain->dev, "received: %s\n", rain->cmd); + if (!memcmp(rain->cmd, "REC", 3) || + !memcmp(rain->cmd, "STA", 3)) { + rain_process_msg(rain); + } else { + strcpy(rain->cmd_reply, rain->cmd); + complete(&rain->cmd_done); + } + rain->cmd_idx = 0; + rain->cmd_started = false; + break; + + case '\n': + rain->cmd_idx = 0; + rain->cmd_started = false; + break; + + case '?': + rain->cmd_idx = 0; + rain->cmd_started = true; + break; + + default: + if (rain->cmd_idx >= DATA_SIZE - 1) { + dev_dbg(rain->dev, + "throwing away %d bytes of garbage\n", rain->cmd_idx); + rain->cmd_idx = 0; + } + rain->cmd[rain->cmd_idx++] = data; + break; + } + } +} + +static irqreturn_t rain_interrupt(struct serio *serio, unsigned char data, + unsigned int flags) +{ + struct rain *rain = serio_get_drvdata(serio); + + if (rain->buf_len == DATA_SIZE) { + dev_warn_once(rain->dev, "buffer overflow\n"); + return IRQ_HANDLED; + } + spin_lock(&rain->buf_lock); + rain->buf_len++; + rain->buf[rain->buf_wr_idx] = data; + rain->buf_wr_idx = (rain->buf_wr_idx + 1) & 0xff; + spin_unlock(&rain->buf_lock); + schedule_work(&rain->work); + return IRQ_HANDLED; +} + +static void rain_disconnect(struct serio *serio) +{ + struct rain *rain = serio_get_drvdata(serio); + + cancel_work_sync(&rain->work); + cec_unregister_adapter(rain->adap); + dev_info(&serio->dev, "disconnected\n"); + serio_close(serio); + serio_set_drvdata(serio, NULL); + kfree(rain); +} + +static int rain_send(struct rain *rain, const char *command) +{ + int err = serio_write(rain->serio, '!'); + + dev_dbg(rain->dev, "send: %s\n", command); + while (!err && *command) + err = serio_write(rain->serio, *command++); + if (!err) + err = serio_write(rain->serio, '~'); + + return err; +} + +static int rain_send_and_wait(struct rain *rain, + const char *cmd, const char *reply) +{ + int err; + + init_completion(&rain->cmd_done); + + mutex_lock(&rain->write_lock); + err = rain_send(rain, cmd); + if (err) + goto err; + + if (!wait_for_completion_timeout(&rain->cmd_done, HZ)) { + err = -ETIMEDOUT; + goto err; + } + if (reply && strncmp(rain->cmd_reply, reply, strlen(reply))) { + dev_dbg(rain->dev, + "transmit of '%s': received '%s' instead of '%s'\n", + cmd, rain->cmd_reply, reply); + err = -EIO; + } +err: + mutex_unlock(&rain->write_lock); + return err; +} + +static int rain_setup(struct rain *rain, struct serio *serio, + struct cec_log_addrs *log_addrs, u16 *pa) +{ + int err; + + err = rain_send_and_wait(rain, "R", "REV"); + if (err) + return err; + dev_info(rain->dev, "Firmware version %s\n", rain->cmd_reply + 4); + + err = rain_send_and_wait(rain, "Q 1", "QTY"); + if (err) + return err; + err = rain_send_and_wait(rain, "c0000", "CFG"); + if (err) + return err; + return rain_send_and_wait(rain, "A F 0000", "ADR"); +} + +static int rain_cec_adap_enable(struct cec_adapter *adap, bool enable) +{ + return 0; +} + +static int rain_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) +{ + struct rain *rain = cec_get_drvdata(adap); + u8 cmd[16]; + + if (log_addr == CEC_LOG_ADDR_INVALID) + log_addr = CEC_LOG_ADDR_UNREGISTERED; + snprintf(cmd, sizeof(cmd), "A %x", log_addr); + return rain_send_and_wait(rain, cmd, "ADR"); +} + +static int rain_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg) +{ + struct rain *rain = cec_get_drvdata(adap); + char cmd[2 * CEC_MAX_MSG_SIZE + 16]; + unsigned int i; + int err; + + if (msg->len == 1) { + snprintf(cmd, sizeof(cmd), "x%x", cec_msg_destination(msg)); + } else { + char hex[3]; + + snprintf(cmd, sizeof(cmd), "x%x %02x ", + cec_msg_destination(msg), msg->msg[1]); + for (i = 2; i < msg->len; i++) { + snprintf(hex, sizeof(hex), "%02x", msg->msg[i]); + strncat(cmd, hex, sizeof(cmd)); + } + } + mutex_lock(&rain->write_lock); + err = rain_send(rain, cmd); + mutex_unlock(&rain->write_lock); + return err; +} + +static const struct cec_adap_ops rain_cec_adap_ops = { + .adap_enable = rain_cec_adap_enable, + .adap_log_addr = rain_cec_adap_log_addr, + .adap_transmit = rain_cec_adap_transmit, +}; + +static int rain_connect(struct serio *serio, struct serio_driver *drv) +{ + u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | CEC_CAP_PHYS_ADDR | + CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL; + struct rain *rain; + int err = -ENOMEM; + struct cec_log_addrs log_addrs = {}; + u16 pa = CEC_PHYS_ADDR_INVALID; + + rain = kzalloc(sizeof(*rain), GFP_KERNEL); + + if (!rain) + return -ENOMEM; + + rain->serio = serio; + rain->adap = cec_allocate_adapter(&rain_cec_adap_ops, rain, + "HDMI CEC", caps, 1); + err = PTR_ERR_OR_ZERO(rain->adap); + if (err < 0) + goto free_device; + + rain->dev = &serio->dev; + serio_set_drvdata(serio, rain); + INIT_WORK(&rain->work, rain_irq_work_handler); + mutex_init(&rain->write_lock); + + err = serio_open(serio, drv); + if (err) + goto delete_adap; + + err = rain_setup(rain, serio, &log_addrs, &pa); + if (err) + goto close_serio; + + err = cec_register_adapter(rain->adap, &serio->dev); + if (err < 0) + goto close_serio; + + rain->dev = &rain->adap->devnode.dev; + return 0; + +close_serio: + serio_close(serio); +delete_adap: + cec_delete_adapter(rain->adap); + serio_set_drvdata(serio, NULL); +free_device: + kfree(rain); + return err; +} + +static struct serio_device_id rain_serio_ids[] = { + { + .type = SERIO_RS232, + .proto = SERIO_RAINSHADOW_CEC, + .id = SERIO_ANY, + .extra = SERIO_ANY, + }, + { 0 } +}; + +MODULE_DEVICE_TABLE(serio, rain_serio_ids); + +static struct serio_driver rain_drv = { + .driver = { + .name = "rainshadow-cec", + }, + .description = "RainShadow Tech HDMI CEC driver", + .id_table = rain_serio_ids, + .interrupt = rain_interrupt, + .connect = rain_connect, + .disconnect = rain_disconnect, +}; + +module_serio_driver(rain_drv); -- cgit v1.2.3 From a9b99bbedae6f861de3be635bdc9382e1e29a4f9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil <hans.verkuil@cisco.com> Date: Thu, 24 Nov 2016 05:49:35 -0200 Subject: [media] em28xx: drop last soc_camera link The em28xx driver still used the soc_camera.h header for the ov2640 driver. Since this driver no longer uses soc_camera, that include can be removed. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/em28xx-camera.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 7b4129ab1cf9..2f59237ee399 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -23,7 +23,6 @@ #include <linux/i2c.h> #include <linux/usb.h> -#include <media/soc_camera.h> #include <media/i2c/mt9v011.h> #include <media/v4l2-clk.h> #include <media/v4l2-common.h> @@ -43,13 +42,6 @@ static unsigned short omnivision_sensor_addrs[] = { I2C_CLIENT_END }; -static struct soc_camera_link camlink = { - .bus_id = 0, - .flags = 0, - .module_name = "em28xx", - .unbalanced_power = true, -}; - /* FIXME: Should be replaced by a proper mt9m111 driver */ static int em28xx_initialize_mt9m111(struct em28xx *dev) { @@ -419,7 +411,6 @@ int em28xx_init_camera(struct em28xx *dev) .type = "ov2640", .flags = I2C_CLIENT_SCCB, .addr = client->addr, - .platform_data = &camlink, }; struct v4l2_subdev_format format = { .which = V4L2_SUBDEV_FORMAT_ACTIVE, -- cgit v1.2.3 From bf05b65a9fe5f6a6dd3e72cab2aacd8b5b96e41d Mon Sep 17 00:00:00 2001 From: Ben Hutchings <ben@decadent.org.uk> Date: Fri, 17 Feb 2017 22:30:51 -0200 Subject: [media] dvb-usb-dibusb-mc-common: Add MODULE_LICENSE dvb-usb-dibusb-mc-common is licensed under GPLv2, and if we don't say so then it won't even load since it needs a GPL-only symbol. Fixes: e91455a1495a ("[media] dvb-usb: split out common parts of dibusb") Reported-by: Dominique Dumont <dod@debian.org> Cc: stable@vger.kernel.org # 4.9+ Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/dvb-usb/dibusb-mc-common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/dvb-usb/dibusb-mc-common.c b/drivers/media/usb/dvb-usb/dibusb-mc-common.c index c989cac9343d..0c2bc97436d5 100644 --- a/drivers/media/usb/dvb-usb/dibusb-mc-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-mc-common.c @@ -11,6 +11,8 @@ #include "dibusb.h" +MODULE_LICENSE("GPL"); + /* 3000MC/P stuff */ // Config Adjacent channels Perf -cal22 static struct dibx000_agc_config dib3000p_mt2060_agc_config = { -- cgit v1.2.3 From f81a18d860a22b0c56d4dac51752f475cf840144 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Date: Wed, 22 Feb 2017 19:32:19 -0300 Subject: [media] tm6000: Fix resource freeing in 'tm6000_prepare_isoc()' 'usb_free_urb(urb)' is a no-op, because urb is known to be NULL. It is likelly that releasing resources allocated by 'tm6000_alloc_urb_buffers()' just a few lines above is expected here. This has been spotted by the following coccinelle script: @@ expression ret, x, e; identifier f; @@ * if (x == NULL) { ... when != x = e; ( * f(<+...x...+>); | * ret = f(<+...x...+>); ) ... } Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/tm6000/tm6000-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index c4fdc1fa32ef..7e960d0a5b92 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -631,7 +631,7 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev) urb = usb_alloc_urb(max_packets, GFP_KERNEL); if (!urb) { tm6000_uninit_isoc(dev); - usb_free_urb(urb); + tm6000_free_urb_buffers(dev); return -ENOMEM; } dev->isoc_ctl.urb[i] = urb; -- cgit v1.2.3 From 1c13f7aaaab12a01d7bf530539780e40a0ff24d4 Mon Sep 17 00:00:00 2001 From: Alexandre-Xavier Labonté-Lamoureux <alexandrexavier@live.ca> Date: Sat, 25 Feb 2017 05:03:38 -0300 Subject: [media] em28xx: Add new USB ID eb1a:5051 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new usbid eb1a:5051 for the Ion Video 2 PC MKII, Startech svid2usb23 and Raygo R12-41373. Signed-off-by: Alexandre-Xavier Labonté-Lamoureux <alexandrexavier@live.ca> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/em28xx-cards.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 5f80a1b2fb8c..6fb604900a33 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2600,6 +2600,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM28178_BOARD_TERRATEC_T2_STICK_HD }, { USB_DEVICE(0x3275, 0x0085), .driver_info = EM28178_BOARD_PLEX_PX_BCUD }, + { USB_DEVICE(0xeb1a, 0x5051), /* Ion Video 2 PC MKII / Startech svid2usb23 / Raygo R12-41373 */ + .driver_info = EM2860_BOARD_TVP5150_REFERENCE_DESIGN }, { }, }; MODULE_DEVICE_TABLE(usb, em28xx_id_table); -- cgit v1.2.3 From 4d58443696a8e2a4bcae3fc6d32b0bee71ad9fa1 Mon Sep 17 00:00:00 2001 From: Frank Schaefer <fschaefer.oss@googlemail.com> Date: Sun, 16 Apr 2017 14:41:52 -0300 Subject: [media] em28xx: simplify ID-reading from Micron sensors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use i2c_smbus_read_word_data() instead of i2c_master_send() and i2c_master_recv() for reading the ID of Micorn sensors. i2c_smbus_read_word_data() assumes that byes are in little-endian, so, it uses: data->word = msgbuf1[0] | (msgbuf1[1] << 8); However, Micron datasheet describes the ID as if they were read in big-endian. So, we need to change the byte order in order to match the ID number as described on their datasheets. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/em28xx-camera.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index 2f59237ee399..f401e5aa1373 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -98,8 +98,6 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) { int ret, i; char *name; - u8 reg; - __be16 id_be; u16 id; struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; @@ -107,10 +105,8 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) dev->em28xx_sensor = EM28XX_NOSENSOR; for (i = 0; micron_sensor_addrs[i] != I2C_CLIENT_END; i++) { client->addr = micron_sensor_addrs[i]; - /* NOTE: i2c_smbus_read_word_data() doesn't work with BE data */ /* Read chip ID from register 0x00 */ - reg = 0x00; - ret = i2c_master_send(client, ®, 1); + ret = i2c_smbus_read_word_data(client, 0x00); /* assumes LE */ if (ret < 0) { if (ret != -ENXIO) dev_err(&dev->intf->dev, @@ -118,24 +114,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) client->addr << 1, ret); continue; } - ret = i2c_master_recv(client, (u8 *)&id_be, 2); - if (ret < 0) { - dev_err(&dev->intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client->addr << 1, ret); - continue; - } - id = be16_to_cpu(id_be); + id = swab16(ret); /* LE -> BE */ /* Read chip ID from register 0xff */ - reg = 0xff; - ret = i2c_master_send(client, ®, 1); - if (ret < 0) { - dev_err(&dev->intf->dev, - "couldn't read from i2c device 0x%02x: error %i\n", - client->addr << 1, ret); - continue; - } - ret = i2c_master_recv(client, (u8 *)&id_be, 2); + ret = i2c_smbus_read_word_data(client, 0xff); if (ret < 0) { dev_err(&dev->intf->dev, "couldn't read from i2c device 0x%02x: error %i\n", @@ -143,10 +124,9 @@ static int em28xx_probe_sensor_micron(struct em28xx *dev) continue; } /* Validate chip ID to be sure we have a Micron device */ - if (id != be16_to_cpu(id_be)) + if (id != swab16(ret)) continue; /* Check chip ID */ - id = be16_to_cpu(id_be); switch (id) { case 0x1222: name = "MT9V012"; /* MI370 */ /* 640x480 */ -- cgit v1.2.3 From 2437aeb497ef43bff7f887aba4c45dd0ced61a4c Mon Sep 17 00:00:00 2001 From: Frank Schaefer <fschaefer.oss@googlemail.com> Date: Sat, 15 Apr 2017 07:05:00 -0300 Subject: [media] em28xx: get rid of the dummy clock source MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v4l2 dummy clock has been added with commit fc5d0f8a8878 ("V4L2: em28xx: register a V4L2 clock source") to be able to use the ov2640 soc_camera driver. Since commit 46796cfcd346 ("ov2640: use standard clk and enable it") it is no longer required. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/em28xx-camera.c | 30 ++++++------------------------ drivers/media/usb/em28xx/em28xx-video.c | 6 ------ drivers/media/usb/em28xx/em28xx.h | 1 - 3 files changed, 6 insertions(+), 31 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index f401e5aa1373..ee0fe1f13070 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -24,7 +24,6 @@ #include <linux/i2c.h> #include <linux/usb.h> #include <media/i2c/mt9v011.h> -#include <media/v4l2-clk.h> #include <media/v4l2-common.h> /* Possible i2c addresses of Micron sensors */ @@ -311,17 +310,9 @@ int em28xx_detect_sensor(struct em28xx *dev) int em28xx_init_camera(struct em28xx *dev) { - char clk_name[V4L2_CLK_NAME_SIZE]; struct i2c_client *client = &dev->i2c_client[dev->def_i2c_bus]; struct i2c_adapter *adap = &dev->i2c_adap[dev->def_i2c_bus]; struct em28xx_v4l2 *v4l2 = dev->v4l2; - int ret = 0; - - v4l2_clk_name_i2c(clk_name, sizeof(clk_name), - i2c_adapter_id(adap), client->addr); - v4l2->clk = v4l2_clk_register_fixed(clk_name, -EINVAL); - if (IS_ERR(v4l2->clk)) - return PTR_ERR(v4l2->clk); switch (dev->em28xx_sensor) { case EM28XX_MT9V011: @@ -351,10 +342,8 @@ int em28xx_init_camera(struct em28xx *dev) pdata.xtal = v4l2->sensor_xtal; if (NULL == v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap, - &mt9v011_info, NULL)) { - ret = -ENODEV; - break; - } + &mt9v011_info, NULL)) + return -ENODEV; /* probably means GRGB 16 bit bayer */ v4l2->vinmode = 0x0d; v4l2->vinctl = 0x00; @@ -410,10 +399,8 @@ int em28xx_init_camera(struct em28xx *dev) subdev = v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap, &ov2640_info, NULL); - if (NULL == subdev) { - ret = -ENODEV; - break; - } + if (subdev == NULL) + return -ENODEV; format.format.code = MEDIA_BUS_FMT_YUYV8_2X8; format.format.width = 640; @@ -430,14 +417,9 @@ int em28xx_init_camera(struct em28xx *dev) } case EM28XX_NOSENSOR: default: - ret = -EINVAL; - } - - if (ret < 0) { - v4l2_clk_unregister_fixed(v4l2->clk); - v4l2->clk = NULL; + return -EINVAL; } - return ret; + return 0; } EXPORT_SYMBOL_GPL(em28xx_init_camera); diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 8d93100334ea..3cbc3d4270a3 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -43,7 +43,6 @@ #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> #include <media/v4l2-event.h> -#include <media/v4l2-clk.h> #include <media/drv-intf/msp3400.h> #include <media/tuner.h> @@ -2140,11 +2139,6 @@ static int em28xx_v4l2_fini(struct em28xx *dev) v4l2_ctrl_handler_free(&v4l2->ctrl_handler); v4l2_device_unregister(&v4l2->v4l2_dev); - if (v4l2->clk) { - v4l2_clk_unregister_fixed(v4l2->clk); - v4l2->clk = NULL; - } - kref_put(&v4l2->ref, em28xx_free_v4l2); mutex_unlock(&dev->lock); diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index e9f379959fa5..e8d97d5ec161 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -510,7 +510,6 @@ struct em28xx_v4l2 { struct v4l2_device v4l2_dev; struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_clk *clk; struct video_device vdev; struct video_device vbi_dev; -- cgit v1.2.3 From bb42fc4ad442d4de78b4a16233db98a5396988ff Mon Sep 17 00:00:00 2001 From: Frank Schaefer <fschaefer.oss@googlemail.com> Date: Sat, 15 Apr 2017 07:05:01 -0300 Subject: [media] em28xx: add missing auto-selections for build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With MEDIA_SUBDRV_AUTOSELECT enabled in the kernel config, the em28xx driver currently does't select some used subdrivers. Fix this by adding the missing auto-selections to the Kconfig file. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/Kconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig index aa131cf9989b..4cc029f18aa8 100644 --- a/drivers/media/usb/em28xx/Kconfig +++ b/drivers/media/usb/em28xx/Kconfig @@ -12,7 +12,7 @@ config VIDEO_EM28XX_V4L2 select VIDEO_TVP5150 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT - + select VIDEO_OV2640 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT ---help--- This is a video4linux driver for Empia 28xx based TV cards. @@ -39,6 +39,7 @@ config VIDEO_EM28XX_DVB depends on VIDEO_EM28XX && DVB_CORE select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT + select DVB_LGDT3306A if MEDIA_SUBDRV_AUTOSELECT select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT select DVB_S921 if MEDIA_SUBDRV_AUTOSELECT @@ -61,6 +62,10 @@ config VIDEO_EM28XX_DVB select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_QM1D1C0042 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT ---help--- This adds support for DVB cards based on the Empiatech em28xx chips. -- cgit v1.2.3 From 85316cf8da9e808f28c81343a050f489ac03e20e Mon Sep 17 00:00:00 2001 From: Frank Schaefer <fschaefer.oss@googlemail.com> Date: Sat, 15 Apr 2017 07:05:02 -0300 Subject: [media] em28xx: don't treat device as webcam if an unknown sensor is detected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With an unknown sensor, norm_maxw() and norm_maxh() return 0 as max. height and width values, which causes a devide by zero in size_to_scale(). Of course we could use speculative default values for unknown sensors, but the chance that the device works at this resolution without any driver/setup is very low and therefore not worth the efforts. Instead, just don't treat the device as camera. A message will then be printed to the log that the device isn't supported. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/em28xx-cards.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 6fb604900a33..a12b599a1fa2 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -2919,7 +2919,9 @@ static void em28xx_card_setup(struct em28xx *dev) * If sensor is not found, then it isn't a webcam. */ if (dev->board.is_webcam) { - if (em28xx_detect_sensor(dev) < 0) + em28xx_detect_sensor(dev); + if (dev->em28xx_sensor == EM28XX_NOSENSOR) + /* NOTE: error/unknown sensor/no sensor */ dev->board.is_webcam = 0; } @@ -3667,9 +3669,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, try_bulk = usb_xfer_mode > 0; } - /* Disable V4L2 if the device doesn't have a decoder */ + /* Disable V4L2 if the device doesn't have a decoder or image sensor */ if (has_video && - dev->board.decoder == EM28XX_NODECODER && !dev->board.is_webcam) { + dev->board.decoder == EM28XX_NODECODER && + dev->em28xx_sensor == EM28XX_NOSENSOR) { + dev_err(&interface->dev, "Currently, V4L2 is not supported on this model\n"); has_video = false; -- cgit v1.2.3 From a7b8e9a5b3224883c2ab996717d6b808c46c81b3 Mon Sep 17 00:00:00 2001 From: Frank Schaefer <fschaefer.oss@googlemail.com> Date: Sat, 15 Apr 2017 07:05:03 -0300 Subject: [media] em28xx: shed some light on video input formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CbYCrY has been identified by looking into the tvp5150 driver and the saa7115 datasheet. YUV formats have been verified with em2765 + ov2640 (VAD Laplace webcam). RGB8 formats have been verified with em2710/em2820 + mt9v011 (Silvercrest webcam 1.3mpix). I also did some cross-checking with these two camera devices and 0x08-0x0b are at least 16 bits per pixel formats on em2710/em2820, too, and 0x0c-0x0f are at least 8 bits per pixel formats on em2765, too. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/em28xx-camera.c | 10 ++++------ drivers/media/usb/em28xx/em28xx-reg.h | 18 ++++++++++++++++++ drivers/media/usb/em28xx/em28xx-video.c | 2 +- 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c index ee0fe1f13070..ae87dd3e671f 100644 --- a/drivers/media/usb/em28xx/em28xx-camera.c +++ b/drivers/media/usb/em28xx/em28xx-camera.c @@ -344,8 +344,7 @@ int em28xx_init_camera(struct em28xx *dev) v4l2_i2c_new_subdev_board(&v4l2->v4l2_dev, adap, &mt9v011_info, NULL)) return -ENODEV; - /* probably means GRGB 16 bit bayer */ - v4l2->vinmode = 0x0d; + v4l2->vinmode = EM28XX_VINMODE_RGB8_GRBG; v4l2->vinctl = 0x00; break; @@ -356,8 +355,7 @@ int em28xx_init_camera(struct em28xx *dev) em28xx_initialize_mt9m001(dev); - /* probably means BGGR 16 bit bayer */ - v4l2->vinmode = 0x0c; + v4l2->vinmode = EM28XX_VINMODE_RGB8_BGGR; v4l2->vinctl = 0x00; break; @@ -369,7 +367,7 @@ int em28xx_init_camera(struct em28xx *dev) em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk); em28xx_initialize_mt9m111(dev); - v4l2->vinmode = 0x0a; + v4l2->vinmode = EM28XX_VINMODE_YUV422_UYVY; v4l2->vinctl = 0x00; break; @@ -410,7 +408,7 @@ int em28xx_init_camera(struct em28xx *dev) /* NOTE: for UXGA=1600x1200 switch to 12MHz */ dev->board.xclk = EM28XX_XCLK_FREQUENCY_24MHZ; em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk); - v4l2->vinmode = 0x08; + v4l2->vinmode = EM28XX_VINMODE_YUV422_YUYV; v4l2->vinctl = 0x00; break; diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h index afe7a66d7dc8..747525ca7ed5 100644 --- a/drivers/media/usb/em28xx/em28xx-reg.h +++ b/drivers/media/usb/em28xx/em28xx-reg.h @@ -93,6 +93,24 @@ #define EM28XX_XCLK_FREQUENCY_24MHZ 0x0b #define EM28XX_R10_VINMODE 0x10 + /* used by all non-camera devices: */ +#define EM28XX_VINMODE_YUV422_CbYCrY 0x10 + /* used by camera devices: */ +#define EM28XX_VINMODE_YUV422_YUYV 0x08 +#define EM28XX_VINMODE_YUV422_YVYU 0x09 +#define EM28XX_VINMODE_YUV422_UYVY 0x0a +#define EM28XX_VINMODE_YUV422_VYUY 0x0b +#define EM28XX_VINMODE_RGB8_BGGR 0x0c +#define EM28XX_VINMODE_RGB8_GRBG 0x0d +#define EM28XX_VINMODE_RGB8_GBRG 0x0e +#define EM28XX_VINMODE_RGB8_RGGB 0x0f + /* + * apparently: + * bit 0: swap component 1+2 with 3+4 + * => e.g.: YUYV => YVYU, BGGR => GRBG + * bit 1: swap component 1 with 2 and 3 with 4 + * => e.g.: YUYV => UYVY, BGGR => GBRG + */ #define EM28XX_R11_VINCTRL 0x11 diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index 3cbc3d4270a3..aaa83f9e5c1a 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -2459,7 +2459,7 @@ static int em28xx_v4l2_init(struct em28xx *dev) /* * Default format, used for tvp5150 or saa711x output formats */ - v4l2->vinmode = 0x10; + v4l2->vinmode = EM28XX_VINMODE_YUV422_CbYCrY; v4l2->vinctl = EM28XX_VINCTRL_INTERLACED | EM28XX_VINCTRL_CCIR656_ENABLE; -- cgit v1.2.3 From 495ab569d0845065016617edcf07a75db96c3ef0 Mon Sep 17 00:00:00 2001 From: Frank Schaefer <fschaefer.oss@googlemail.com> Date: Sat, 15 Apr 2017 07:05:04 -0300 Subject: [media] em28xx: add support for V4L2_PIX_FMT_SRGGB8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adding support for SRGGB8 is as simple as adding a new entry at struct em28xx_fmt. Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/em28xx/em28xx-video.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c index aaa83f9e5c1a..8d253a5df0a9 100644 --- a/drivers/media/usb/em28xx/em28xx-video.c +++ b/drivers/media/usb/em28xx/em28xx-video.c @@ -115,6 +115,11 @@ static struct em28xx_fmt format[] = { .fourcc = V4L2_PIX_FMT_RGB565, .depth = 16, .reg = EM28XX_OUTFMT_RGB_16_656, + }, { + .name = "8 bpp Bayer RGRG..GBGB", + .fourcc = V4L2_PIX_FMT_SRGGB8, + .depth = 8, + .reg = EM28XX_OUTFMT_RGB_8_RGRG, }, { .name = "8 bpp Bayer BGBG..GRGR", .fourcc = V4L2_PIX_FMT_SBGGR8, -- cgit v1.2.3 From e8357cdec3d1b6b42566ce3bc960e5e10c2b3787 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> Date: Sat, 25 Mar 2017 16:14:15 -0300 Subject: [media] media: stk1160: Add Kconfig help on snd-usb-audio requirement The Kconfig currently makes no reference to the snd-usb-audio driver, which supports audio capture for this type of devices. Just in case, let's make sure the requirement is mentioned in the description. Signed-off-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/stk1160/Kconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig index 22dff4f3b921..425ed00e2599 100644 --- a/drivers/media/usb/stk1160/Kconfig +++ b/drivers/media/usb/stk1160/Kconfig @@ -6,7 +6,11 @@ config VIDEO_STK1160_COMMON This is a video4linux driver for STK1160 based video capture devices. To compile this driver as a module, choose M here: the - module will be called stk1160 + module will be called stk1160. + + This driver only provides support for video capture. For audio + capture, you need to select the snd-usb-audio driver (i.e. + CONFIG_SND_USB_AUDIO). config VIDEO_STK1160 tristate -- cgit v1.2.3 From 821117dc21083a99dd99174c10848d70ff43de29 Mon Sep 17 00:00:00 2001 From: Alyssa Milburn <amilburn@zall.org> Date: Sat, 1 Apr 2017 14:33:42 -0300 Subject: [media] digitv: limit messages to buffer size Return an error rather than memcpy()ing beyond the end of the buffer. Internal callers use appropriate sizes, but digitv_i2c_xfer may not. Signed-off-by: Alyssa Milburn <amilburn@zall.org> Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/dvb-usb/digitv.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 4284f6984dc1..475a3c0cdee7 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c @@ -33,6 +33,9 @@ static int digitv_ctrl_msg(struct dvb_usb_device *d, wo = (rbuf == NULL || rlen == 0); /* write-only */ + if (wlen > 4 || rlen > 4) + return -EIO; + memset(st->sndbuf, 0, 7); memset(st->rcvbuf, 0, 7); -- cgit v1.2.3 From ee0fe833d96793853335844b6d99fb76bd12cbeb Mon Sep 17 00:00:00 2001 From: Alyssa Milburn <amilburn@zall.org> Date: Sat, 1 Apr 2017 14:34:08 -0300 Subject: [media] zr364xx: enforce minimum size when reading header This code copies actual_length-128 bytes from the header, which will underflow if the received buffer is too small. Signed-off-by: Alyssa Milburn <amilburn@zall.org> Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/zr364xx/zr364xx.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index f2d6fc03dda0..efdcd5bd6a4c 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -600,6 +600,14 @@ static int zr364xx_read_video_callback(struct zr364xx_camera *cam, ptr = pdest = frm->lpvbits; if (frm->ulState == ZR364XX_READ_IDLE) { + if (purb->actual_length < 128) { + /* header incomplete */ + dev_info(&cam->udev->dev, + "%s: buffer (%d bytes) too small to hold jpeg header. Discarding.\n", + __func__, purb->actual_length); + return -EINVAL; + } + frm->ulState = ZR364XX_READ_FRAME; frm->cur_size = 0; -- cgit v1.2.3 From 56a263aaa0a5f58d70517fae2bdd63fc1e17efec Mon Sep 17 00:00:00 2001 From: Hans Verkuil <hans.verkuil@cisco.com> Date: Mon, 17 Apr 2017 07:44:35 -0300 Subject: [media] cec: Kconfig cleanup The Kconfig options for the CEC subsystem were a bit messy. In addition there were two cec sources (cec-edid.c and cec-notifier.c) that were outside of the media/cec directory, which was weird. Move those sources to media/cec as well. The cec-edid and cec-notifier functionality is now part of the cec module and these are no longer separate modules. Also remove the MEDIA_CEC_EDID config option and include it with the main CEC config option (which defined CEC_EDID anyway). Added static inlines to cec-edid.h for dummy functions when CEC_CORE isn't defined. CEC drivers should now depend on CEC_CORE. CEC drivers that need the cec-notifier functionality must explicitly select CEC_NOTIFIER. The s5p-cec and stih-cec drivers depended on VIDEO_DEV instead of CEC_CORE, fix that as well. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- MAINTAINERS | 2 - drivers/media/Kconfig | 26 ++--- drivers/media/Makefile | 14 +-- drivers/media/cec-edid.c | 171 ------------------------------- drivers/media/cec-notifier.c | 129 ----------------------- drivers/media/cec/Kconfig | 13 +++ drivers/media/cec/Makefile | 8 +- drivers/media/cec/cec-edid.c | 167 ++++++++++++++++++++++++++++++ drivers/media/cec/cec-notifier.c | 129 +++++++++++++++++++++++ drivers/media/i2c/Kconfig | 9 +- drivers/media/platform/Kconfig | 56 +++++----- drivers/media/platform/vivid/Kconfig | 3 +- drivers/media/usb/pulse8-cec/Kconfig | 2 +- drivers/media/usb/rainshadow-cec/Kconfig | 2 +- include/media/cec-edid.h | 29 ++++++ include/media/cec.h | 2 +- 16 files changed, 387 insertions(+), 375 deletions(-) delete mode 100644 drivers/media/cec-edid.c delete mode 100644 drivers/media/cec-notifier.c create mode 100644 drivers/media/cec/Kconfig create mode 100644 drivers/media/cec/cec-edid.c create mode 100644 drivers/media/cec/cec-notifier.c (limited to 'drivers/media/usb') diff --git a/MAINTAINERS b/MAINTAINERS index 6919a495bdad..cf0101544a08 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3075,8 +3075,6 @@ S: Supported F: Documentation/media/kapi/cec-core.rst F: Documentation/media/uapi/cec F: drivers/media/cec/ -F: drivers/media/cec-edid.c -F: drivers/media/cec-notifier.c F: drivers/media/rc/keymaps/rc-cec.c F: include/media/cec.h F: include/media/cec-edid.h diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index 9e9ded44e8a8..b72edd27f880 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -81,27 +81,15 @@ config MEDIA_RC_SUPPORT Say Y when you have a TV or an IR device. config MEDIA_CEC_SUPPORT - bool "HDMI CEC support" - select MEDIA_CEC_EDID - ---help--- - Enable support for HDMI CEC (Consumer Electronics Control), - which is an optional HDMI feature. - - Say Y when you have an HDMI receiver, transmitter or a USB CEC - adapter that supports HDMI CEC. - -config MEDIA_CEC_DEBUG - bool "HDMI CEC debugfs interface" - depends on MEDIA_CEC_SUPPORT && DEBUG_FS - ---help--- - Turns on the DebugFS interface for CEC devices. + bool "HDMI CEC support" + ---help--- + Enable support for HDMI CEC (Consumer Electronics Control), + which is an optional HDMI feature. -config MEDIA_CEC_EDID - bool + Say Y when you have an HDMI receiver, transmitter or a USB CEC + adapter that supports HDMI CEC. -config MEDIA_CEC_NOTIFIER - bool - select MEDIA_CEC_EDID +source "drivers/media/cec/Kconfig" # # Media controller diff --git a/drivers/media/Makefile b/drivers/media/Makefile index 8b36a571d443..523fea3648ad 100644 --- a/drivers/media/Makefile +++ b/drivers/media/Makefile @@ -2,20 +2,10 @@ # Makefile for the kernel multimedia device drivers. # -ifeq ($(CONFIG_MEDIA_CEC_EDID),y) - obj-$(CONFIG_MEDIA_SUPPORT) += cec-edid.o -endif - -ifeq ($(CONFIG_MEDIA_CEC_NOTIFIER),y) - obj-$(CONFIG_MEDIA_SUPPORT) += cec-notifier.o -endif - -ifeq ($(CONFIG_MEDIA_CEC_SUPPORT),y) - obj-$(CONFIG_MEDIA_SUPPORT) += cec/ -endif - media-objs := media-device.o media-devnode.o media-entity.o +obj-$(CONFIG_CEC_CORE) += cec/ + # # I2C drivers should come before other drivers, otherwise they'll fail # when compiled as builtin drivers diff --git a/drivers/media/cec-edid.c b/drivers/media/cec-edid.c deleted file mode 100644 index 5719b991e340..000000000000 --- a/drivers/media/cec-edid.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * cec-edid - HDMI Consumer Electronics Control EDID & CEC helper functions - * - * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * This program is free software; you may redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <media/cec-edid.h> - -/* - * This EDID is expected to be a CEA-861 compliant, which means that there are - * at least two blocks and one or more of the extensions blocks are CEA-861 - * blocks. - * - * The returned location is guaranteed to be < size - 1. - */ -static unsigned int cec_get_edid_spa_location(const u8 *edid, unsigned int size) -{ - unsigned int blocks = size / 128; - unsigned int block; - u8 d; - - /* Sanity check: at least 2 blocks and a multiple of the block size */ - if (blocks < 2 || size % 128) - return 0; - - /* - * If there are fewer extension blocks than the size, then update - * 'blocks'. It is allowed to have more extension blocks than the size, - * since some hardware can only read e.g. 256 bytes of the EDID, even - * though more blocks are present. The first CEA-861 extension block - * should normally be in block 1 anyway. - */ - if (edid[0x7e] + 1 < blocks) - blocks = edid[0x7e] + 1; - - for (block = 1; block < blocks; block++) { - unsigned int offset = block * 128; - - /* Skip any non-CEA-861 extension blocks */ - if (edid[offset] != 0x02 || edid[offset + 1] != 0x03) - continue; - - /* search Vendor Specific Data Block (tag 3) */ - d = edid[offset + 2] & 0x7f; - /* Check if there are Data Blocks */ - if (d <= 4) - continue; - if (d > 4) { - unsigned int i = offset + 4; - unsigned int end = offset + d; - - /* Note: 'end' is always < 'size' */ - do { - u8 tag = edid[i] >> 5; - u8 len = edid[i] & 0x1f; - - if (tag == 3 && len >= 5 && i + len <= end && - edid[i + 1] == 0x03 && - edid[i + 2] == 0x0c && - edid[i + 3] == 0x00) - return i + 4; - i += len + 1; - } while (i < end); - } - } - return 0; -} - -u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, - unsigned int *offset) -{ - unsigned int loc = cec_get_edid_spa_location(edid, size); - - if (offset) - *offset = loc; - if (loc == 0) - return CEC_PHYS_ADDR_INVALID; - return (edid[loc] << 8) | edid[loc + 1]; -} -EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr); - -void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr) -{ - unsigned int loc = cec_get_edid_spa_location(edid, size); - u8 sum = 0; - unsigned int i; - - if (loc == 0) - return; - edid[loc] = phys_addr >> 8; - edid[loc + 1] = phys_addr & 0xff; - loc &= ~0x7f; - - /* update the checksum */ - for (i = loc; i < loc + 127; i++) - sum += edid[i]; - edid[i] = 256 - sum; -} -EXPORT_SYMBOL_GPL(cec_set_edid_phys_addr); - -u16 cec_phys_addr_for_input(u16 phys_addr, u8 input) -{ - /* Check if input is sane */ - if (WARN_ON(input == 0 || input > 0xf)) - return CEC_PHYS_ADDR_INVALID; - - if (phys_addr == 0) - return input << 12; - - if ((phys_addr & 0x0fff) == 0) - return phys_addr | (input << 8); - - if ((phys_addr & 0x00ff) == 0) - return phys_addr | (input << 4); - - if ((phys_addr & 0x000f) == 0) - return phys_addr | input; - - /* - * All nibbles are used so no valid physical addresses can be assigned - * to the input. - */ - return CEC_PHYS_ADDR_INVALID; -} -EXPORT_SYMBOL_GPL(cec_phys_addr_for_input); - -int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) -{ - int i; - - if (parent) - *parent = phys_addr; - if (port) - *port = 0; - if (phys_addr == CEC_PHYS_ADDR_INVALID) - return 0; - for (i = 0; i < 16; i += 4) - if (phys_addr & (0xf << i)) - break; - if (i == 16) - return 0; - if (parent) - *parent = phys_addr & (0xfff0 << i); - if (port) - *port = (phys_addr >> i) & 0xf; - for (i += 4; i < 16; i += 4) - if ((phys_addr & (0xf << i)) == 0) - return -EINVAL; - return 0; -} -EXPORT_SYMBOL_GPL(cec_phys_addr_validate); - -MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>"); -MODULE_DESCRIPTION("CEC EDID helper functions"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/cec-notifier.c b/drivers/media/cec-notifier.c deleted file mode 100644 index 5f5209a73665..000000000000 --- a/drivers/media/cec-notifier.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * cec-notifier.c - notify CEC drivers of physical address changes - * - * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk> - * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * This program is free software; you may redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include <linux/export.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/kref.h> - -#include <media/cec-notifier.h> -#include <drm/drm_edid.h> - -struct cec_notifier { - struct mutex lock; - struct list_head head; - struct kref kref; - struct device *dev; - struct cec_adapter *cec_adap; - void (*callback)(struct cec_adapter *adap, u16 pa); - - u16 phys_addr; -}; - -static LIST_HEAD(cec_notifiers); -static DEFINE_MUTEX(cec_notifiers_lock); - -struct cec_notifier *cec_notifier_get(struct device *dev) -{ - struct cec_notifier *n; - - mutex_lock(&cec_notifiers_lock); - list_for_each_entry(n, &cec_notifiers, head) { - if (n->dev == dev) { - kref_get(&n->kref); - mutex_unlock(&cec_notifiers_lock); - return n; - } - } - n = kzalloc(sizeof(*n), GFP_KERNEL); - if (!n) - goto unlock; - n->dev = dev; - n->phys_addr = CEC_PHYS_ADDR_INVALID; - mutex_init(&n->lock); - kref_init(&n->kref); - list_add_tail(&n->head, &cec_notifiers); -unlock: - mutex_unlock(&cec_notifiers_lock); - return n; -} -EXPORT_SYMBOL_GPL(cec_notifier_get); - -static void cec_notifier_release(struct kref *kref) -{ - struct cec_notifier *n = - container_of(kref, struct cec_notifier, kref); - - list_del(&n->head); - kfree(n); -} - -void cec_notifier_put(struct cec_notifier *n) -{ - mutex_lock(&cec_notifiers_lock); - kref_put(&n->kref, cec_notifier_release); - mutex_unlock(&cec_notifiers_lock); -} -EXPORT_SYMBOL_GPL(cec_notifier_put); - -void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) -{ - mutex_lock(&n->lock); - n->phys_addr = pa; - if (n->callback) - n->callback(n->cec_adap, n->phys_addr); - mutex_unlock(&n->lock); -} -EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr); - -void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n, - const struct edid *edid) -{ - u16 pa = CEC_PHYS_ADDR_INVALID; - - if (edid && edid->extensions) - pa = cec_get_edid_phys_addr((const u8 *)edid, - EDID_LENGTH * (edid->extensions + 1), NULL); - cec_notifier_set_phys_addr(n, pa); -} -EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr_from_edid); - -void cec_notifier_register(struct cec_notifier *n, - struct cec_adapter *adap, - void (*callback)(struct cec_adapter *adap, u16 pa)) -{ - kref_get(&n->kref); - mutex_lock(&n->lock); - n->cec_adap = adap; - n->callback = callback; - n->callback(adap, n->phys_addr); - mutex_unlock(&n->lock); -} -EXPORT_SYMBOL_GPL(cec_notifier_register); - -void cec_notifier_unregister(struct cec_notifier *n) -{ - mutex_lock(&n->lock); - n->callback = NULL; - mutex_unlock(&n->lock); - cec_notifier_put(n); -} -EXPORT_SYMBOL_GPL(cec_notifier_unregister); diff --git a/drivers/media/cec/Kconfig b/drivers/media/cec/Kconfig new file mode 100644 index 000000000000..24b53187ee52 --- /dev/null +++ b/drivers/media/cec/Kconfig @@ -0,0 +1,13 @@ +config CEC_CORE + tristate + depends on MEDIA_CEC_SUPPORT + default y + +config MEDIA_CEC_NOTIFIER + bool + +config MEDIA_CEC_DEBUG + bool "HDMI CEC debugfs interface" + depends on MEDIA_CEC_SUPPORT && DEBUG_FS + ---help--- + Turns on the DebugFS interface for CEC devices. diff --git a/drivers/media/cec/Makefile b/drivers/media/cec/Makefile index d6686337275f..402a6c62a3e8 100644 --- a/drivers/media/cec/Makefile +++ b/drivers/media/cec/Makefile @@ -1,5 +1,7 @@ -cec-objs := cec-core.o cec-adap.o cec-api.o +cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o -ifeq ($(CONFIG_MEDIA_CEC_SUPPORT),y) - obj-$(CONFIG_MEDIA_SUPPORT) += cec.o +ifeq ($(CONFIG_MEDIA_CEC_NOTIFIER),y) + cec-objs += cec-notifier.o endif + +obj-$(CONFIG_CEC_CORE) += cec.o diff --git a/drivers/media/cec/cec-edid.c b/drivers/media/cec/cec-edid.c new file mode 100644 index 000000000000..c63dc81d2a29 --- /dev/null +++ b/drivers/media/cec/cec-edid.c @@ -0,0 +1,167 @@ +/* + * cec-edid - HDMI Consumer Electronics Control EDID & CEC helper functions + * + * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <media/cec-edid.h> + +/* + * This EDID is expected to be a CEA-861 compliant, which means that there are + * at least two blocks and one or more of the extensions blocks are CEA-861 + * blocks. + * + * The returned location is guaranteed to be < size - 1. + */ +static unsigned int cec_get_edid_spa_location(const u8 *edid, unsigned int size) +{ + unsigned int blocks = size / 128; + unsigned int block; + u8 d; + + /* Sanity check: at least 2 blocks and a multiple of the block size */ + if (blocks < 2 || size % 128) + return 0; + + /* + * If there are fewer extension blocks than the size, then update + * 'blocks'. It is allowed to have more extension blocks than the size, + * since some hardware can only read e.g. 256 bytes of the EDID, even + * though more blocks are present. The first CEA-861 extension block + * should normally be in block 1 anyway. + */ + if (edid[0x7e] + 1 < blocks) + blocks = edid[0x7e] + 1; + + for (block = 1; block < blocks; block++) { + unsigned int offset = block * 128; + + /* Skip any non-CEA-861 extension blocks */ + if (edid[offset] != 0x02 || edid[offset + 1] != 0x03) + continue; + + /* search Vendor Specific Data Block (tag 3) */ + d = edid[offset + 2] & 0x7f; + /* Check if there are Data Blocks */ + if (d <= 4) + continue; + if (d > 4) { + unsigned int i = offset + 4; + unsigned int end = offset + d; + + /* Note: 'end' is always < 'size' */ + do { + u8 tag = edid[i] >> 5; + u8 len = edid[i] & 0x1f; + + if (tag == 3 && len >= 5 && i + len <= end && + edid[i + 1] == 0x03 && + edid[i + 2] == 0x0c && + edid[i + 3] == 0x00) + return i + 4; + i += len + 1; + } while (i < end); + } + } + return 0; +} + +u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, + unsigned int *offset) +{ + unsigned int loc = cec_get_edid_spa_location(edid, size); + + if (offset) + *offset = loc; + if (loc == 0) + return CEC_PHYS_ADDR_INVALID; + return (edid[loc] << 8) | edid[loc + 1]; +} +EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr); + +void cec_set_edid_phys_addr(u8 *edid, unsigned int size, u16 phys_addr) +{ + unsigned int loc = cec_get_edid_spa_location(edid, size); + u8 sum = 0; + unsigned int i; + + if (loc == 0) + return; + edid[loc] = phys_addr >> 8; + edid[loc + 1] = phys_addr & 0xff; + loc &= ~0x7f; + + /* update the checksum */ + for (i = loc; i < loc + 127; i++) + sum += edid[i]; + edid[i] = 256 - sum; +} +EXPORT_SYMBOL_GPL(cec_set_edid_phys_addr); + +u16 cec_phys_addr_for_input(u16 phys_addr, u8 input) +{ + /* Check if input is sane */ + if (WARN_ON(input == 0 || input > 0xf)) + return CEC_PHYS_ADDR_INVALID; + + if (phys_addr == 0) + return input << 12; + + if ((phys_addr & 0x0fff) == 0) + return phys_addr | (input << 8); + + if ((phys_addr & 0x00ff) == 0) + return phys_addr | (input << 4); + + if ((phys_addr & 0x000f) == 0) + return phys_addr | input; + + /* + * All nibbles are used so no valid physical addresses can be assigned + * to the input. + */ + return CEC_PHYS_ADDR_INVALID; +} +EXPORT_SYMBOL_GPL(cec_phys_addr_for_input); + +int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) +{ + int i; + + if (parent) + *parent = phys_addr; + if (port) + *port = 0; + if (phys_addr == CEC_PHYS_ADDR_INVALID) + return 0; + for (i = 0; i < 16; i += 4) + if (phys_addr & (0xf << i)) + break; + if (i == 16) + return 0; + if (parent) + *parent = phys_addr & (0xfff0 << i); + if (port) + *port = (phys_addr >> i) & 0xf; + for (i += 4; i < 16; i += 4) + if ((phys_addr & (0xf << i)) == 0) + return -EINVAL; + return 0; +} +EXPORT_SYMBOL_GPL(cec_phys_addr_validate); diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c new file mode 100644 index 000000000000..5f5209a73665 --- /dev/null +++ b/drivers/media/cec/cec-notifier.c @@ -0,0 +1,129 @@ +/* + * cec-notifier.c - notify CEC drivers of physical address changes + * + * Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk> + * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <linux/export.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/kref.h> + +#include <media/cec-notifier.h> +#include <drm/drm_edid.h> + +struct cec_notifier { + struct mutex lock; + struct list_head head; + struct kref kref; + struct device *dev; + struct cec_adapter *cec_adap; + void (*callback)(struct cec_adapter *adap, u16 pa); + + u16 phys_addr; +}; + +static LIST_HEAD(cec_notifiers); +static DEFINE_MUTEX(cec_notifiers_lock); + +struct cec_notifier *cec_notifier_get(struct device *dev) +{ + struct cec_notifier *n; + + mutex_lock(&cec_notifiers_lock); + list_for_each_entry(n, &cec_notifiers, head) { + if (n->dev == dev) { + kref_get(&n->kref); + mutex_unlock(&cec_notifiers_lock); + return n; + } + } + n = kzalloc(sizeof(*n), GFP_KERNEL); + if (!n) + goto unlock; + n->dev = dev; + n->phys_addr = CEC_PHYS_ADDR_INVALID; + mutex_init(&n->lock); + kref_init(&n->kref); + list_add_tail(&n->head, &cec_notifiers); +unlock: + mutex_unlock(&cec_notifiers_lock); + return n; +} +EXPORT_SYMBOL_GPL(cec_notifier_get); + +static void cec_notifier_release(struct kref *kref) +{ + struct cec_notifier *n = + container_of(kref, struct cec_notifier, kref); + + list_del(&n->head); + kfree(n); +} + +void cec_notifier_put(struct cec_notifier *n) +{ + mutex_lock(&cec_notifiers_lock); + kref_put(&n->kref, cec_notifier_release); + mutex_unlock(&cec_notifiers_lock); +} +EXPORT_SYMBOL_GPL(cec_notifier_put); + +void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) +{ + mutex_lock(&n->lock); + n->phys_addr = pa; + if (n->callback) + n->callback(n->cec_adap, n->phys_addr); + mutex_unlock(&n->lock); +} +EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr); + +void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n, + const struct edid *edid) +{ + u16 pa = CEC_PHYS_ADDR_INVALID; + + if (edid && edid->extensions) + pa = cec_get_edid_phys_addr((const u8 *)edid, + EDID_LENGTH * (edid->extensions + 1), NULL); + cec_notifier_set_phys_addr(n, pa); +} +EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr_from_edid); + +void cec_notifier_register(struct cec_notifier *n, + struct cec_adapter *adap, + void (*callback)(struct cec_adapter *adap, u16 pa)) +{ + kref_get(&n->kref); + mutex_lock(&n->lock); + n->cec_adap = adap; + n->callback = callback; + n->callback(adap, n->phys_addr); + mutex_unlock(&n->lock); +} +EXPORT_SYMBOL_GPL(cec_notifier_register); + +void cec_notifier_unregister(struct cec_notifier *n) +{ + mutex_lock(&n->lock); + n->callback = NULL; + mutex_unlock(&n->lock); + cec_notifier_put(n); +} +EXPORT_SYMBOL_GPL(cec_notifier_unregister); diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index b358d1a40688..40bb4bdc51da 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -209,7 +209,6 @@ config VIDEO_ADV7604 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on GPIOLIB || COMPILE_TEST select HDMI - select MEDIA_CEC_EDID ---help--- Support for the Analog Devices ADV7604 video decoder. @@ -221,7 +220,7 @@ config VIDEO_ADV7604 config VIDEO_ADV7604_CEC bool "Enable Analog Devices ADV7604 CEC support" - depends on VIDEO_ADV7604 && MEDIA_CEC_SUPPORT + depends on VIDEO_ADV7604 && CEC_CORE ---help--- When selected the adv7604 will support the optional HDMI CEC feature. @@ -230,7 +229,6 @@ config VIDEO_ADV7842 tristate "Analog Devices ADV7842 decoder" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API select HDMI - select MEDIA_CEC_EDID ---help--- Support for the Analog Devices ADV7842 video decoder. @@ -242,7 +240,7 @@ config VIDEO_ADV7842 config VIDEO_ADV7842_CEC bool "Enable Analog Devices ADV7842 CEC support" - depends on VIDEO_ADV7842 && MEDIA_CEC_SUPPORT + depends on VIDEO_ADV7842 && CEC_CORE ---help--- When selected the adv7842 will support the optional HDMI CEC feature. @@ -470,7 +468,6 @@ config VIDEO_ADV7511 tristate "Analog Devices ADV7511 encoder" depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API select HDMI - select MEDIA_CEC_EDID ---help--- Support for the Analog Devices ADV7511 video encoder. @@ -481,7 +478,7 @@ config VIDEO_ADV7511 config VIDEO_ADV7511_CEC bool "Enable Analog Devices ADV7511 CEC support" - depends on VIDEO_ADV7511 && MEDIA_CEC_SUPPORT + depends on VIDEO_ADV7511 && CEC_CORE ---help--- When selected the adv7511 will support the optional HDMI CEC feature. diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 73c3bc5deadf..ac026ee1ca07 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -461,34 +461,6 @@ config VIDEO_TI_SC config VIDEO_TI_CSC tristate -menuconfig V4L_CEC_DRIVERS - bool "Platform HDMI CEC drivers" - depends on MEDIA_CEC_SUPPORT - -if V4L_CEC_DRIVERS - -config VIDEO_SAMSUNG_S5P_CEC - tristate "Samsung S5P CEC driver" - depends on VIDEO_DEV && MEDIA_CEC_SUPPORT && (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST) - select MEDIA_CEC_NOTIFIER - ---help--- - This is a driver for Samsung S5P HDMI CEC interface. It uses the - generic CEC framework interface. - CEC bus is present in the HDMI connector and enables communication - between compatible devices. - -config VIDEO_STI_HDMI_CEC - tristate "STMicroelectronics STiH4xx HDMI CEC driver" - depends on VIDEO_DEV && MEDIA_CEC_SUPPORT && (ARCH_STI || COMPILE_TEST) - select MEDIA_CEC_NOTIFIER - ---help--- - This is a driver for STIH4xx HDMI CEC interface. It uses the - generic CEC framework interface. - CEC bus is present in the HDMI connector and enables communication - between compatible devices. - -endif #V4L_CEC_DRIVERS - menuconfig V4L_TEST_DRIVERS bool "Media test drivers" depends on MEDIA_CAMERA_SUPPORT @@ -520,3 +492,31 @@ menuconfig DVB_PLATFORM_DRIVERS if DVB_PLATFORM_DRIVERS source "drivers/media/platform/sti/c8sectpfe/Kconfig" endif #DVB_PLATFORM_DRIVERS + +menuconfig CEC_PLATFORM_DRIVERS + bool "CEC platform devices" + depends on MEDIA_CEC_SUPPORT + +if CEC_PLATFORM_DRIVERS + +config VIDEO_SAMSUNG_S5P_CEC + tristate "Samsung S5P CEC driver" + depends on CEC_CORE && (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST) + select MEDIA_CEC_NOTIFIER + ---help--- + This is a driver for Samsung S5P HDMI CEC interface. It uses the + generic CEC framework interface. + CEC bus is present in the HDMI connector and enables communication + between compatible devices. + +config VIDEO_STI_HDMI_CEC + tristate "STMicroelectronics STiH4xx HDMI CEC driver" + depends on CEC_CORE && (ARCH_STI || COMPILE_TEST) + select MEDIA_CEC_NOTIFIER + ---help--- + This is a driver for STIH4xx HDMI CEC interface. It uses the + generic CEC framework interface. + CEC bus is present in the HDMI connector and enables communication + between compatible devices. + +endif #CEC_PLATFORM_DRIVERS diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig index 94ab1364a792..b36ac19dc6e4 100644 --- a/drivers/media/platform/vivid/Kconfig +++ b/drivers/media/platform/vivid/Kconfig @@ -7,7 +7,6 @@ config VIDEO_VIVID select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select MEDIA_CEC_EDID select VIDEOBUF2_VMALLOC select VIDEOBUF2_DMA_CONTIG select VIDEO_V4L2_TPG @@ -27,7 +26,7 @@ config VIDEO_VIVID config VIDEO_VIVID_CEC bool "Enable CEC emulation support" - depends on VIDEO_VIVID && MEDIA_CEC_SUPPORT + depends on VIDEO_VIVID && CEC_CORE ---help--- When selected the vivid module will emulate the optional HDMI CEC feature. diff --git a/drivers/media/usb/pulse8-cec/Kconfig b/drivers/media/usb/pulse8-cec/Kconfig index 6ffc407de62f..8937f3986a01 100644 --- a/drivers/media/usb/pulse8-cec/Kconfig +++ b/drivers/media/usb/pulse8-cec/Kconfig @@ -1,6 +1,6 @@ config USB_PULSE8_CEC tristate "Pulse Eight HDMI CEC" - depends on USB_ACM && MEDIA_CEC_SUPPORT + depends on USB_ACM && CEC_CORE select SERIO select SERIO_SERPORT ---help--- diff --git a/drivers/media/usb/rainshadow-cec/Kconfig b/drivers/media/usb/rainshadow-cec/Kconfig index 447291b3cca3..3eb86607efb8 100644 --- a/drivers/media/usb/rainshadow-cec/Kconfig +++ b/drivers/media/usb/rainshadow-cec/Kconfig @@ -1,6 +1,6 @@ config USB_RAINSHADOW_CEC tristate "RainShadow Tech HDMI CEC" - depends on USB_ACM && MEDIA_CEC_SUPPORT + depends on USB_ACM && CEC_CORE select SERIO select SERIO_SERPORT ---help--- diff --git a/include/media/cec-edid.h b/include/media/cec-edid.h index bdf731ecba1a..242781fd377f 100644 --- a/include/media/cec-edid.h +++ b/include/media/cec-edid.h @@ -26,6 +26,8 @@ #define cec_phys_addr_exp(pa) \ ((pa) >> 12), ((pa) >> 8) & 0xf, ((pa) >> 4) & 0xf, (pa) & 0xf +#if IS_ENABLED(CONFIG_CEC_CORE) + /** * cec_get_edid_phys_addr() - find and return the physical address * @@ -101,4 +103,31 @@ u16 cec_phys_addr_for_input(u16 phys_addr, u8 input); */ int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port); +#else + +static inline u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size, + unsigned int *offset) +{ + if (offset) + *offset = 0; + return CEC_PHYS_ADDR_INVALID; +} + +static inline void cec_set_edid_phys_addr(u8 *edid, unsigned int size, + u16 phys_addr) +{ +} + +static inline u16 cec_phys_addr_for_input(u16 phys_addr, u8 input) +{ + return CEC_PHYS_ADDR_INVALID; +} + +static inline int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port) +{ + return 0; +} + +#endif + #endif /* _MEDIA_CEC_EDID_H */ diff --git a/include/media/cec.h b/include/media/cec.h index b313e3ecab70..bae8d0153de7 100644 --- a/include/media/cec.h +++ b/include/media/cec.h @@ -204,7 +204,7 @@ static inline bool cec_is_sink(const struct cec_adapter *adap) return adap->phys_addr == 0; } -#if IS_ENABLED(CONFIG_MEDIA_CEC_SUPPORT) +#if IS_ENABLED(CONFIG_CEC_CORE) struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, void *priv, const char *name, u32 caps, u8 available_las); int cec_register_adapter(struct cec_adapter *adap, struct device *parent); -- cgit v1.2.3 From a12b8ab8c5ff7ccd7b107a564743507c850a441d Mon Sep 17 00:00:00 2001 From: Alyssa Milburn <amilburn@zall.org> Date: Sat, 1 Apr 2017 14:34:32 -0300 Subject: [media] ttusb2: limit messages to buffer size Otherwise ttusb2_i2c_xfer can read or write beyond the end of static and heap buffers. Signed-off-by: Alyssa Milburn <amilburn@zall.org> Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/dvb-usb/ttusb2.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c index ecc207fbaf3c..9e0d6a4166d2 100644 --- a/drivers/media/usb/dvb-usb/ttusb2.c +++ b/drivers/media/usb/dvb-usb/ttusb2.c @@ -78,6 +78,9 @@ static int ttusb2_msg(struct dvb_usb_device *d, u8 cmd, u8 *s, *r = NULL; int ret = 0; + if (4 + rlen > 64) + return -EIO; + s = kzalloc(wlen+4, GFP_KERNEL); if (!s) return -ENOMEM; @@ -381,6 +384,22 @@ static int ttusb2_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num write_read = i+1 < num && (msg[i+1].flags & I2C_M_RD); read = msg[i].flags & I2C_M_RD; + if (3 + msg[i].len > sizeof(obuf)) { + err("i2c wr len=%d too high", msg[i].len); + break; + } + if (write_read) { + if (3 + msg[i+1].len > sizeof(ibuf)) { + err("i2c rd len=%d too high", msg[i+1].len); + break; + } + } else if (read) { + if (3 + msg[i].len > sizeof(ibuf)) { + err("i2c rd len=%d too high", msg[i].len); + break; + } + } + obuf[0] = (msg[i].addr << 1) | (write_read | read); if (read) obuf[1] = 0; -- cgit v1.2.3 From 950e252cb469f323740d78e4907843acef89eedb Mon Sep 17 00:00:00 2001 From: Alyssa Milburn <amilburn@zall.org> Date: Sat, 1 Apr 2017 14:34:49 -0300 Subject: [media] dw2102: limit messages to buffer size Otherwise the i2c transfer functions can read or write beyond the end of stack or heap buffers. Signed-off-by: Alyssa Milburn <amilburn@zall.org> Cc: stable@vger.kernel.org Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> --- drivers/media/usb/dvb-usb/dw2102.c | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers/media/usb') diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 4f42d57f81d9..6e654e5026dd 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -204,6 +204,20 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, switch (num) { case 2: + if (msg[0].len != 1) { + warn("i2c rd: len=%d is not 1!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + + if (2 + msg[1].len > sizeof(buf6)) { + warn("i2c rd: len=%d is too big!\n", + msg[1].len); + num = -EOPNOTSUPP; + break; + } + /* read si2109 register by number */ buf6[0] = msg[0].addr << 1; buf6[1] = msg[0].len; @@ -219,6 +233,13 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap, case 1: switch (msg[0].addr) { case 0x68: + if (2 + msg[0].len > sizeof(buf6)) { + warn("i2c wr: len=%d is too big!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + /* write to si2109 register */ buf6[0] = msg[0].addr << 1; buf6[1] = msg[0].len; @@ -262,6 +283,13 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms /* first write first register number */ u8 ibuf[MAX_XFER_SIZE], obuf[3]; + if (2 + msg[0].len != sizeof(obuf)) { + warn("i2c rd: len=%d is not 1!\n", + msg[0].len); + ret = -EOPNOTSUPP; + goto unlock; + } + if (2 + msg[1].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[1].len); @@ -462,6 +490,12 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], /* first write first register number */ u8 ibuf[MAX_XFER_SIZE], obuf[3]; + if (2 + msg[0].len != sizeof(obuf)) { + warn("i2c rd: len=%d is not 1!\n", + msg[0].len); + ret = -EOPNOTSUPP; + goto unlock; + } if (2 + msg[1].len > sizeof(ibuf)) { warn("i2c rd: len=%d is too big!\n", msg[1].len); @@ -696,6 +730,13 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], msg[0].buf[0] = state->data[1]; break; default: + if (3 + msg[0].len > sizeof(state->data)) { + warn("i2c wr: len=%d is too big!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + /* always i2c write*/ state->data[0] = 0x08; state->data[1] = msg[0].addr; @@ -711,6 +752,19 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], break; case 2: /* always i2c read */ + if (4 + msg[0].len > sizeof(state->data)) { + warn("i2c rd: len=%d is too big!\n", + msg[0].len); + num = -EOPNOTSUPP; + break; + } + if (1 + msg[1].len > sizeof(state->data)) { + warn("i2c rd: len=%d is too big!\n", + msg[1].len); + num = -EOPNOTSUPP; + break; + } + state->data[0] = 0x09; state->data[1] = msg[0].len; state->data[2] = msg[1].len; -- cgit v1.2.3