diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-07-07 02:01:26 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-07-07 02:01:26 -0400 |
| commit | 032f82786f9be4635acaa5f77feca175a4ac5fe1 (patch) | |
| tree | 11ce43c1086d3dec43c92b0a2cc740240b338fb7 /drivers/media | |
| parent | 46ac22bab42cc868b9c1d0e915ddbc8e8065a44d (diff) | |
| parent | b7279469d66b55119784b8b9529c99c1955fe747 (diff) | |
Merge commit 'v2.6.26-rc9' into sched/devel
Diffstat (limited to 'drivers/media')
50 files changed, 7476 insertions, 442 deletions
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index a3485817e46c..8fa91f846d59 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c | |||
| @@ -2201,3 +2201,41 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = { | |||
| 2201 | [0x25] = KEY_POWER, /* power */ | 2201 | [0x25] = KEY_POWER, /* power */ |
| 2202 | }; | 2202 | }; |
| 2203 | EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel); | 2203 | EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel); |
| 2204 | |||
| 2205 | IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = { | ||
| 2206 | [0x20] = KEY_LIST, | ||
| 2207 | [0x00] = KEY_POWER, | ||
| 2208 | [0x28] = KEY_1, | ||
| 2209 | [0x18] = KEY_2, | ||
| 2210 | [0x38] = KEY_3, | ||
| 2211 | [0x24] = KEY_4, | ||
| 2212 | [0x14] = KEY_5, | ||
| 2213 | [0x34] = KEY_6, | ||
| 2214 | [0x2c] = KEY_7, | ||
| 2215 | [0x1c] = KEY_8, | ||
| 2216 | [0x3c] = KEY_9, | ||
| 2217 | [0x12] = KEY_SUBTITLE, | ||
| 2218 | [0x22] = KEY_0, | ||
| 2219 | [0x32] = KEY_REWIND, | ||
| 2220 | [0x3a] = KEY_SHUFFLE, | ||
| 2221 | [0x02] = KEY_PRINT, | ||
| 2222 | [0x11] = KEY_CHANNELDOWN, | ||
| 2223 | [0x31] = KEY_CHANNELUP, | ||
| 2224 | [0x0c] = KEY_ZOOM, | ||
| 2225 | [0x1e] = KEY_VOLUMEDOWN, | ||
| 2226 | [0x3e] = KEY_VOLUMEUP, | ||
| 2227 | [0x0a] = KEY_MUTE, | ||
| 2228 | [0x04] = KEY_AUDIO, | ||
| 2229 | [0x26] = KEY_RECORD, | ||
| 2230 | [0x06] = KEY_PLAY, | ||
| 2231 | [0x36] = KEY_STOP, | ||
| 2232 | [0x16] = KEY_PAUSE, | ||
| 2233 | [0x2e] = KEY_REWIND, | ||
| 2234 | [0x0e] = KEY_FASTFORWARD, | ||
| 2235 | [0x30] = KEY_TEXT, | ||
| 2236 | [0x21] = KEY_GREEN, | ||
| 2237 | [0x01] = KEY_BLUE, | ||
| 2238 | [0x08] = KEY_EPG, | ||
| 2239 | [0x2a] = KEY_MENU, | ||
| 2240 | }; | ||
| 2241 | EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d); | ||
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c index f1894fec32b9..6fb5b4586569 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/common/tuners/tda18271-common.c | |||
| @@ -649,9 +649,17 @@ int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq) | |||
| 649 | u8 val; | 649 | u8 val; |
| 650 | 650 | ||
| 651 | int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val); | 651 | int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val); |
| 652 | /* The TDA18271HD/C1 rf_cal map lookup is expected to go out of range | ||
| 653 | * for frequencies above 61.1 MHz. In these cases, the internal RF | ||
| 654 | * tracking filters calibration mechanism is used. | ||
| 655 | * | ||
| 656 | * There is no need to warn the user about this. | ||
| 657 | */ | ||
| 658 | if (ret < 0) | ||
| 659 | goto fail; | ||
| 652 | 660 | ||
| 653 | regs[R_EB14] = val; | 661 | regs[R_EB14] = val; |
| 654 | 662 | fail: | |
| 655 | return ret; | 663 | return ret; |
| 656 | } | 664 | } |
| 657 | 665 | ||
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 89c01fb1f859..93063c6fbbf6 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c | |||
| @@ -45,6 +45,21 @@ static inline int charge_pump_source(struct dvb_frontend *fe, int force) | |||
| 45 | TDA18271_MAIN_PLL, force); | 45 | TDA18271_MAIN_PLL, force); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static inline void tda18271_set_if_notch(struct dvb_frontend *fe) | ||
| 49 | { | ||
| 50 | struct tda18271_priv *priv = fe->tuner_priv; | ||
| 51 | unsigned char *regs = priv->tda18271_regs; | ||
| 52 | |||
| 53 | switch (priv->mode) { | ||
| 54 | case TDA18271_ANALOG: | ||
| 55 | regs[R_MPD] &= ~0x80; /* IF notch = 0 */ | ||
| 56 | break; | ||
| 57 | case TDA18271_DIGITAL: | ||
| 58 | regs[R_MPD] |= 0x80; /* IF notch = 1 */ | ||
| 59 | break; | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 48 | static int tda18271_channel_configuration(struct dvb_frontend *fe, | 63 | static int tda18271_channel_configuration(struct dvb_frontend *fe, |
| 49 | struct tda18271_std_map_item *map, | 64 | struct tda18271_std_map_item *map, |
| 50 | u32 freq, u32 bw) | 65 | u32 freq, u32 bw) |
| @@ -60,25 +75,18 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, | |||
| 60 | regs[R_EP3] &= ~0x1f; /* clear std bits */ | 75 | regs[R_EP3] &= ~0x1f; /* clear std bits */ |
| 61 | regs[R_EP3] |= (map->agc_mode << 3) | map->std; | 76 | regs[R_EP3] |= (map->agc_mode << 3) | map->std; |
| 62 | 77 | ||
| 63 | /* set rfagc to high speed mode */ | 78 | if (priv->id == TDA18271HDC2) { |
| 64 | regs[R_EP3] &= ~0x04; | 79 | /* set rfagc to high speed mode */ |
| 80 | regs[R_EP3] &= ~0x04; | ||
| 81 | } | ||
| 65 | 82 | ||
| 66 | /* set cal mode to normal */ | 83 | /* set cal mode to normal */ |
| 67 | regs[R_EP4] &= ~0x03; | 84 | regs[R_EP4] &= ~0x03; |
| 68 | 85 | ||
| 69 | /* update IF output level & IF notch frequency */ | 86 | /* update IF output level */ |
| 70 | regs[R_EP4] &= ~0x1c; /* clear if level bits */ | 87 | regs[R_EP4] &= ~0x1c; /* clear if level bits */ |
| 71 | regs[R_EP4] |= (map->if_lvl << 2); | 88 | regs[R_EP4] |= (map->if_lvl << 2); |
| 72 | 89 | ||
| 73 | switch (priv->mode) { | ||
| 74 | case TDA18271_ANALOG: | ||
| 75 | regs[R_MPD] &= ~0x80; /* IF notch = 0 */ | ||
| 76 | break; | ||
| 77 | case TDA18271_DIGITAL: | ||
| 78 | regs[R_MPD] |= 0x80; /* IF notch = 1 */ | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | |||
| 82 | /* update FM_RFn */ | 90 | /* update FM_RFn */ |
| 83 | regs[R_EP4] &= ~0x80; | 91 | regs[R_EP4] &= ~0x80; |
| 84 | regs[R_EP4] |= map->fm_rfn << 7; | 92 | regs[R_EP4] |= map->fm_rfn << 7; |
| @@ -95,6 +103,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, | |||
| 95 | /* disable Power Level Indicator */ | 103 | /* disable Power Level Indicator */ |
| 96 | regs[R_EP1] |= 0x40; | 104 | regs[R_EP1] |= 0x40; |
| 97 | 105 | ||
| 106 | /* make sure thermometer is off */ | ||
| 107 | regs[R_TM] &= ~0x10; | ||
| 108 | |||
| 98 | /* frequency dependent parameters */ | 109 | /* frequency dependent parameters */ |
| 99 | 110 | ||
| 100 | tda18271_calc_ir_measure(fe, &freq); | 111 | tda18271_calc_ir_measure(fe, &freq); |
| @@ -135,6 +146,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, | |||
| 135 | switch (priv->role) { | 146 | switch (priv->role) { |
| 136 | case TDA18271_MASTER: | 147 | case TDA18271_MASTER: |
| 137 | tda18271_calc_main_pll(fe, N); | 148 | tda18271_calc_main_pll(fe, N); |
| 149 | tda18271_set_if_notch(fe); | ||
| 138 | tda18271_write_regs(fe, R_MPD, 4); | 150 | tda18271_write_regs(fe, R_MPD, 4); |
| 139 | break; | 151 | break; |
| 140 | case TDA18271_SLAVE: | 152 | case TDA18271_SLAVE: |
| @@ -142,6 +154,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, | |||
| 142 | tda18271_write_regs(fe, R_CPD, 4); | 154 | tda18271_write_regs(fe, R_CPD, 4); |
| 143 | 155 | ||
| 144 | regs[R_MPD] = regs[R_CPD] & 0x7f; | 156 | regs[R_MPD] = regs[R_CPD] & 0x7f; |
| 157 | tda18271_set_if_notch(fe); | ||
| 145 | tda18271_write_regs(fe, R_MPD, 1); | 158 | tda18271_write_regs(fe, R_MPD, 1); |
| 146 | break; | 159 | break; |
| 147 | } | 160 | } |
| @@ -160,12 +173,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, | |||
| 160 | 173 | ||
| 161 | msleep(20); | 174 | msleep(20); |
| 162 | 175 | ||
| 163 | /* set rfagc to normal speed mode */ | 176 | if (priv->id == TDA18271HDC2) { |
| 164 | if (map->fm_rfn) | 177 | /* set rfagc to normal speed mode */ |
| 165 | regs[R_EP3] &= ~0x04; | 178 | if (map->fm_rfn) |
| 166 | else | 179 | regs[R_EP3] &= ~0x04; |
| 167 | regs[R_EP3] |= 0x04; | 180 | else |
| 168 | ret = tda18271_write_regs(fe, R_EP3, 1); | 181 | regs[R_EP3] |= 0x04; |
| 182 | ret = tda18271_write_regs(fe, R_EP3, 1); | ||
| 183 | } | ||
| 169 | fail: | 184 | fail: |
| 170 | return ret; | 185 | return ret; |
| 171 | } | 186 | } |
| @@ -507,7 +522,7 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe) | |||
| 507 | /* set cal mode to normal */ | 522 | /* set cal mode to normal */ |
| 508 | regs[R_EP4] &= ~0x03; | 523 | regs[R_EP4] &= ~0x03; |
| 509 | 524 | ||
| 510 | /* update IF output level & IF notch frequency */ | 525 | /* update IF output level */ |
| 511 | regs[R_EP4] &= ~0x1c; /* clear if level bits */ | 526 | regs[R_EP4] &= ~0x1c; /* clear if level bits */ |
| 512 | 527 | ||
| 513 | ret = tda18271_write_regs(fe, R_EP3, 2); | 528 | ret = tda18271_write_regs(fe, R_EP3, 2); |
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index ceae6db901ec..7cf4f5bdb2ec 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c | |||
| @@ -177,6 +177,7 @@ static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = { | |||
| 177 | {"FM Radio-INPUT1", 0x0208, 0x9002} | 177 | {"FM Radio-INPUT1", 0x0208, 0x9002} |
| 178 | }; | 178 | }; |
| 179 | 179 | ||
| 180 | static int xc5000_is_firmware_loaded(struct dvb_frontend *fe); | ||
| 180 | static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); | 181 | static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len); |
| 181 | static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len); | 182 | static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len); |
| 182 | static void xc5000_TunerReset(struct dvb_frontend *fe); | 183 | static void xc5000_TunerReset(struct dvb_frontend *fe); |
| @@ -352,7 +353,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv, | |||
| 352 | 353 | ||
| 353 | static int xc_shutdown(struct xc5000_priv *priv) | 354 | static int xc_shutdown(struct xc5000_priv *priv) |
| 354 | { | 355 | { |
| 355 | return 0; | 356 | return XC_RESULT_SUCCESS; |
| 356 | /* Fixme: cannot bring tuner back alive once shutdown | 357 | /* Fixme: cannot bring tuner back alive once shutdown |
| 357 | * without reloading the driver modules. | 358 | * without reloading the driver modules. |
| 358 | * return xc_write_reg(priv, XREG_POWER_DOWN, 0); | 359 | * return xc_write_reg(priv, XREG_POWER_DOWN, 0); |
| @@ -685,6 +686,25 @@ static int xc5000_set_params(struct dvb_frontend *fe, | |||
| 685 | return 0; | 686 | return 0; |
| 686 | } | 687 | } |
| 687 | 688 | ||
| 689 | static int xc5000_is_firmware_loaded(struct dvb_frontend *fe) | ||
| 690 | { | ||
| 691 | struct xc5000_priv *priv = fe->tuner_priv; | ||
| 692 | int ret; | ||
| 693 | u16 id; | ||
| 694 | |||
| 695 | ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id); | ||
| 696 | if (ret == XC_RESULT_SUCCESS) { | ||
| 697 | if (id == XC_PRODUCT_ID_FW_NOT_LOADED) | ||
| 698 | ret = XC_RESULT_RESET_FAILURE; | ||
| 699 | else | ||
| 700 | ret = XC_RESULT_SUCCESS; | ||
| 701 | } | ||
| 702 | |||
| 703 | dprintk(1, "%s() returns %s id = 0x%x\n", __func__, | ||
| 704 | ret == XC_RESULT_SUCCESS ? "True" : "False", id); | ||
| 705 | return ret; | ||
| 706 | } | ||
| 707 | |||
| 688 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); | 708 | static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe); |
| 689 | 709 | ||
| 690 | static int xc5000_set_analog_params(struct dvb_frontend *fe, | 710 | static int xc5000_set_analog_params(struct dvb_frontend *fe, |
| @@ -693,7 +713,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe, | |||
| 693 | struct xc5000_priv *priv = fe->tuner_priv; | 713 | struct xc5000_priv *priv = fe->tuner_priv; |
| 694 | int ret; | 714 | int ret; |
| 695 | 715 | ||
| 696 | if(priv->fwloaded == 0) | 716 | if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) |
| 697 | xc_load_fw_and_init_tuner(fe); | 717 | xc_load_fw_and_init_tuner(fe); |
| 698 | 718 | ||
| 699 | dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", | 719 | dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", |
| @@ -808,11 +828,10 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe) | |||
| 808 | struct xc5000_priv *priv = fe->tuner_priv; | 828 | struct xc5000_priv *priv = fe->tuner_priv; |
| 809 | int ret = 0; | 829 | int ret = 0; |
| 810 | 830 | ||
| 811 | if (priv->fwloaded == 0) { | 831 | if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) { |
| 812 | ret = xc5000_fwupload(fe); | 832 | ret = xc5000_fwupload(fe); |
| 813 | if (ret != XC_RESULT_SUCCESS) | 833 | if (ret != XC_RESULT_SUCCESS) |
| 814 | return ret; | 834 | return ret; |
| 815 | priv->fwloaded = 1; | ||
| 816 | } | 835 | } |
| 817 | 836 | ||
| 818 | /* Start the tuner self-calibration process */ | 837 | /* Start the tuner self-calibration process */ |
| @@ -852,7 +871,6 @@ static int xc5000_sleep(struct dvb_frontend *fe) | |||
| 852 | return -EREMOTEIO; | 871 | return -EREMOTEIO; |
| 853 | } | 872 | } |
| 854 | else { | 873 | else { |
| 855 | /* priv->fwloaded = 0; */ | ||
| 856 | return XC_RESULT_SUCCESS; | 874 | return XC_RESULT_SUCCESS; |
| 857 | } | 875 | } |
| 858 | } | 876 | } |
| @@ -933,7 +951,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | |||
| 933 | cfg->i2c_address); | 951 | cfg->i2c_address); |
| 934 | printk(KERN_INFO | 952 | printk(KERN_INFO |
| 935 | "xc5000: Firmware has been loaded previously\n"); | 953 | "xc5000: Firmware has been loaded previously\n"); |
| 936 | priv->fwloaded = 1; | ||
| 937 | break; | 954 | break; |
| 938 | case XC_PRODUCT_ID_FW_NOT_LOADED: | 955 | case XC_PRODUCT_ID_FW_NOT_LOADED: |
| 939 | printk(KERN_INFO | 956 | printk(KERN_INFO |
| @@ -941,7 +958,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, | |||
| 941 | cfg->i2c_address); | 958 | cfg->i2c_address); |
| 942 | printk(KERN_INFO | 959 | printk(KERN_INFO |
| 943 | "xc5000: Firmware has not been loaded previously\n"); | 960 | "xc5000: Firmware has not been loaded previously\n"); |
| 944 | priv->fwloaded = 0; | ||
| 945 | break; | 961 | break; |
| 946 | default: | 962 | default: |
| 947 | printk(KERN_ERR | 963 | printk(KERN_ERR |
diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h index ecebfe4745ad..a72a9887fe7f 100644 --- a/drivers/media/common/tuners/xc5000_priv.h +++ b/drivers/media/common/tuners/xc5000_priv.h | |||
| @@ -30,7 +30,6 @@ struct xc5000_priv { | |||
| 30 | u32 bandwidth; | 30 | u32 bandwidth; |
| 31 | u8 video_standard; | 31 | u8 video_standard; |
| 32 | u8 rf_mode; | 32 | u8 rf_mode; |
| 33 | u8 fwloaded; | ||
| 34 | 33 | ||
| 35 | void *devptr; | 34 | void *devptr; |
| 36 | }; | 35 | }; |
diff --git a/drivers/media/dvb/dvb-usb/gl861.c b/drivers/media/dvb/dvb-usb/gl861.c index 0a8ac64a4e33..037f7ffb47b2 100644 --- a/drivers/media/dvb/dvb-usb/gl861.c +++ b/drivers/media/dvb/dvb-usb/gl861.c | |||
| @@ -47,6 +47,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, | |||
| 47 | return -EINVAL; | 47 | return -EINVAL; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | msleep(1); /* avoid I2C errors */ | ||
| 51 | |||
| 50 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, | 52 | return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, |
| 51 | value, index, rbuf, rlen, 2000); | 53 | value, index, rbuf, rlen, 2000); |
| 52 | } | 54 | } |
| @@ -92,16 +94,6 @@ static struct i2c_algorithm gl861_i2c_algo = { | |||
| 92 | }; | 94 | }; |
| 93 | 95 | ||
| 94 | /* Callbacks for DVB USB */ | 96 | /* Callbacks for DVB USB */ |
| 95 | static int gl861_identify_state(struct usb_device *udev, | ||
| 96 | struct dvb_usb_device_properties *props, | ||
| 97 | struct dvb_usb_device_description **desc, | ||
| 98 | int *cold) | ||
| 99 | { | ||
| 100 | *cold = 0; | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | } | ||
| 104 | |||
| 105 | static struct zl10353_config gl861_zl10353_config = { | 97 | static struct zl10353_config gl861_zl10353_config = { |
| 106 | .demod_address = 0x0f, | 98 | .demod_address = 0x0f, |
| 107 | .no_tuner = 1, | 99 | .no_tuner = 1, |
| @@ -172,7 +164,6 @@ static struct dvb_usb_device_properties gl861_properties = { | |||
| 172 | 164 | ||
| 173 | .size_of_priv = 0, | 165 | .size_of_priv = 0, |
| 174 | 166 | ||
| 175 | .identify_state = gl861_identify_state, | ||
| 176 | .num_adapters = 1, | 167 | .num_adapters = 1, |
| 177 | .adapter = {{ | 168 | .adapter = {{ |
| 178 | 169 | ||
| @@ -194,13 +185,15 @@ static struct dvb_usb_device_properties gl861_properties = { | |||
| 194 | 185 | ||
| 195 | .num_device_descs = 2, | 186 | .num_device_descs = 2, |
| 196 | .devices = { | 187 | .devices = { |
| 197 | { "MSI Mega Sky 55801 DVB-T USB2.0", | 188 | { |
| 198 | { &gl861_table[0], NULL }, | 189 | .name = "MSI Mega Sky 55801 DVB-T USB2.0", |
| 199 | { NULL }, | 190 | .cold_ids = { NULL }, |
| 191 | .warm_ids = { &gl861_table[0], NULL }, | ||
| 200 | }, | 192 | }, |
| 201 | { "A-LINK DTU DVB-T USB2.0", | 193 | { |
| 202 | { &gl861_table[1], NULL }, | 194 | .name = "A-LINK DTU DVB-T USB2.0", |
| 203 | { NULL }, | 195 | .cold_ids = { NULL }, |
| 196 | .warm_ids = { &gl861_table[1], NULL }, | ||
| 204 | }, | 197 | }, |
| 205 | } | 198 | } |
| 206 | }; | 199 | }; |
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c index 9e7653bb3b66..118aab1a3e54 100644 --- a/drivers/media/dvb/dvb-usb/umt-010.c +++ b/drivers/media/dvb/dvb-usb/umt-010.c | |||
| @@ -107,7 +107,7 @@ static struct dvb_usb_device_properties umt_properties = { | |||
| 107 | /* parameter for the MPEG2-data transfer */ | 107 | /* parameter for the MPEG2-data transfer */ |
| 108 | .stream = { | 108 | .stream = { |
| 109 | .type = USB_BULK, | 109 | .type = USB_BULK, |
| 110 | .count = 20, | 110 | .count = MAX_NO_URBS_FOR_DATA_STREAM, |
| 111 | .endpoint = 0x06, | 111 | .endpoint = 0x06, |
| 112 | .u = { | 112 | .u = { |
| 113 | .bulk = { | 113 | .bulk = { |
diff --git a/drivers/media/dvb/frontends/au8522.c b/drivers/media/dvb/frontends/au8522.c index 084a280c2d7f..03900d241a76 100644 --- a/drivers/media/dvb/frontends/au8522.c +++ b/drivers/media/dvb/frontends/au8522.c | |||
| @@ -463,10 +463,13 @@ static int au8522_set_frontend(struct dvb_frontend *fe, | |||
| 463 | struct dvb_frontend_parameters *p) | 463 | struct dvb_frontend_parameters *p) |
| 464 | { | 464 | { |
| 465 | struct au8522_state *state = fe->demodulator_priv; | 465 | struct au8522_state *state = fe->demodulator_priv; |
| 466 | int ret = -EINVAL; | ||
| 466 | 467 | ||
| 467 | dprintk("%s(frequency=%d)\n", __func__, p->frequency); | 468 | dprintk("%s(frequency=%d)\n", __func__, p->frequency); |
| 468 | 469 | ||
| 469 | state->current_frequency = p->frequency; | 470 | if ((state->current_frequency == p->frequency) && |
| 471 | (state->current_modulation == p->u.vsb.modulation)) | ||
| 472 | return 0; | ||
| 470 | 473 | ||
| 471 | au8522_enable_modulation(fe, p->u.vsb.modulation); | 474 | au8522_enable_modulation(fe, p->u.vsb.modulation); |
| 472 | 475 | ||
| @@ -476,11 +479,16 @@ static int au8522_set_frontend(struct dvb_frontend *fe, | |||
| 476 | if (fe->ops.tuner_ops.set_params) { | 479 | if (fe->ops.tuner_ops.set_params) { |
| 477 | if (fe->ops.i2c_gate_ctrl) | 480 | if (fe->ops.i2c_gate_ctrl) |
| 478 | fe->ops.i2c_gate_ctrl(fe, 1); | 481 | fe->ops.i2c_gate_ctrl(fe, 1); |
| 479 | fe->ops.tuner_ops.set_params(fe, p); | 482 | ret = fe->ops.tuner_ops.set_params(fe, p); |
| 480 | if (fe->ops.i2c_gate_ctrl) | 483 | if (fe->ops.i2c_gate_ctrl) |
| 481 | fe->ops.i2c_gate_ctrl(fe, 0); | 484 | fe->ops.i2c_gate_ctrl(fe, 0); |
| 482 | } | 485 | } |
| 483 | 486 | ||
| 487 | if (ret < 0) | ||
| 488 | return ret; | ||
| 489 | |||
| 490 | state->current_frequency = p->frequency; | ||
| 491 | |||
| 484 | return 0; | 492 | return 0; |
| 485 | } | 493 | } |
| 486 | 494 | ||
| @@ -498,6 +506,16 @@ static int au8522_init(struct dvb_frontend *fe) | |||
| 498 | return 0; | 506 | return 0; |
| 499 | } | 507 | } |
| 500 | 508 | ||
| 509 | static int au8522_sleep(struct dvb_frontend *fe) | ||
| 510 | { | ||
| 511 | struct au8522_state *state = fe->demodulator_priv; | ||
| 512 | dprintk("%s()\n", __func__); | ||
| 513 | |||
| 514 | state->current_frequency = 0; | ||
| 515 | |||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 501 | static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) | 519 | static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) |
| 502 | { | 520 | { |
| 503 | struct au8522_state *state = fe->demodulator_priv; | 521 | struct au8522_state *state = fe->demodulator_priv; |
| @@ -509,10 +527,8 @@ static int au8522_read_status(struct dvb_frontend *fe, fe_status_t *status) | |||
| 509 | if (state->current_modulation == VSB_8) { | 527 | if (state->current_modulation == VSB_8) { |
| 510 | dprintk("%s() Checking VSB_8\n", __func__); | 528 | dprintk("%s() Checking VSB_8\n", __func__); |
| 511 | reg = au8522_readreg(state, 0x4088); | 529 | reg = au8522_readreg(state, 0x4088); |
| 512 | if (reg & 0x01) | 530 | if ((reg & 0x03) == 0x03) |
| 513 | *status |= FE_HAS_VITERBI; | 531 | *status |= FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI; |
| 514 | if (reg & 0x02) | ||
| 515 | *status |= FE_HAS_LOCK | FE_HAS_SYNC; | ||
| 516 | } else { | 532 | } else { |
| 517 | dprintk("%s() Checking QAM\n", __func__); | 533 | dprintk("%s() Checking QAM\n", __func__); |
| 518 | reg = au8522_readreg(state, 0x4541); | 534 | reg = au8522_readreg(state, 0x4541); |
| @@ -672,6 +688,7 @@ static struct dvb_frontend_ops au8522_ops = { | |||
| 672 | }, | 688 | }, |
| 673 | 689 | ||
| 674 | .init = au8522_init, | 690 | .init = au8522_init, |
| 691 | .sleep = au8522_sleep, | ||
| 675 | .i2c_gate_ctrl = au8522_i2c_gate_ctrl, | 692 | .i2c_gate_ctrl = au8522_i2c_gate_ctrl, |
| 676 | .set_frontend = au8522_set_frontend, | 693 | .set_frontend = au8522_set_frontend, |
| 677 | .get_frontend = au8522_get_frontend, | 694 | .get_frontend = au8522_get_frontend, |
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c index 17556183e871..35435bef8e79 100644 --- a/drivers/media/dvb/frontends/stv0299.c +++ b/drivers/media/dvb/frontends/stv0299.c | |||
| @@ -63,6 +63,7 @@ struct stv0299_state { | |||
| 63 | u32 symbol_rate; | 63 | u32 symbol_rate; |
| 64 | fe_code_rate_t fec_inner; | 64 | fe_code_rate_t fec_inner; |
| 65 | int errmode; | 65 | int errmode; |
| 66 | u32 ucblocks; | ||
| 66 | }; | 67 | }; |
| 67 | 68 | ||
| 68 | #define STATUS_BER 0 | 69 | #define STATUS_BER 0 |
| @@ -501,8 +502,10 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber) | |||
| 501 | { | 502 | { |
| 502 | struct stv0299_state* state = fe->demodulator_priv; | 503 | struct stv0299_state* state = fe->demodulator_priv; |
| 503 | 504 | ||
| 504 | if (state->errmode != STATUS_BER) return 0; | 505 | if (state->errmode != STATUS_BER) |
| 505 | *ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); | 506 | return -ENOSYS; |
| 507 | |||
| 508 | *ber = stv0299_readreg(state, 0x1e) | (stv0299_readreg(state, 0x1d) << 8); | ||
| 506 | 509 | ||
| 507 | return 0; | 510 | return 0; |
| 508 | } | 511 | } |
| @@ -540,8 +543,12 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) | |||
| 540 | { | 543 | { |
| 541 | struct stv0299_state* state = fe->demodulator_priv; | 544 | struct stv0299_state* state = fe->demodulator_priv; |
| 542 | 545 | ||
| 543 | if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0; | 546 | if (state->errmode != STATUS_UCBLOCKS) |
| 544 | else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e); | 547 | return -ENOSYS; |
| 548 | |||
| 549 | state->ucblocks += stv0299_readreg(state, 0x1e); | ||
| 550 | state->ucblocks += (stv0299_readreg(state, 0x1d) << 8); | ||
| 551 | *ucblocks = state->ucblocks; | ||
| 545 | 552 | ||
| 546 | return 0; | 553 | return 0; |
| 547 | } | 554 | } |
diff --git a/drivers/media/dvb/frontends/tda10023.c b/drivers/media/dvb/frontends/tda10023.c index 0727b80bc4d2..c6ff5b82ff80 100644 --- a/drivers/media/dvb/frontends/tda10023.c +++ b/drivers/media/dvb/frontends/tda10023.c | |||
| @@ -116,9 +116,12 @@ static u8 tda10023_readreg (struct tda10023_state* state, u8 reg) | |||
| 116 | int ret; | 116 | int ret; |
| 117 | 117 | ||
| 118 | ret = i2c_transfer (state->i2c, msg, 2); | 118 | ret = i2c_transfer (state->i2c, msg, 2); |
| 119 | if (ret != 2) | 119 | if (ret != 2) { |
| 120 | printk("DVB: TDA10023: %s: readreg error (ret == %i)\n", | 120 | int num = state->frontend.dvb ? state->frontend.dvb->num : -1; |
| 121 | __func__, ret); | 121 | printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error " |
| 122 | "(reg == 0x%02x, ret == %i)\n", | ||
| 123 | num, __func__, reg, ret); | ||
| 124 | } | ||
| 122 | return b1[0]; | 125 | return b1[0]; |
| 123 | } | 126 | } |
| 124 | 127 | ||
| @@ -129,11 +132,12 @@ static int tda10023_writereg (struct tda10023_state* state, u8 reg, u8 data) | |||
| 129 | int ret; | 132 | int ret; |
| 130 | 133 | ||
| 131 | ret = i2c_transfer (state->i2c, &msg, 1); | 134 | ret = i2c_transfer (state->i2c, &msg, 1); |
| 132 | if (ret != 1) | 135 | if (ret != 1) { |
| 133 | printk("DVB: TDA10023(%d): %s, writereg error " | 136 | int num = state->frontend.dvb ? state->frontend.dvb->num : -1; |
| 137 | printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error " | ||
| 134 | "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", | 138 | "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", |
| 135 | state->frontend.dvb->num, __func__, reg, data, ret); | 139 | num, __func__, reg, data, ret); |
| 136 | 140 | } | |
| 137 | return (ret != 1) ? -EREMOTEIO : 0; | 141 | return (ret != 1) ? -EREMOTEIO : 0; |
| 138 | } | 142 | } |
| 139 | 143 | ||
| @@ -464,7 +468,7 @@ struct dvb_frontend* tda10023_attach(const struct tda1002x_config* config, | |||
| 464 | int i; | 468 | int i; |
| 465 | 469 | ||
| 466 | /* allocate memory for the internal state */ | 470 | /* allocate memory for the internal state */ |
| 467 | state = kmalloc(sizeof(struct tda10023_state), GFP_KERNEL); | 471 | state = kzalloc(sizeof(struct tda10023_state), GFP_KERNEL); |
| 468 | if (state == NULL) goto error; | 472 | if (state == NULL) goto error; |
| 469 | 473 | ||
| 470 | /* setup the state */ | 474 | /* setup the state */ |
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c index 49973846373e..a0d638653567 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c | |||
| @@ -1248,11 +1248,14 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, | |||
| 1248 | struct i2c_adapter* i2c) | 1248 | struct i2c_adapter* i2c) |
| 1249 | { | 1249 | { |
| 1250 | struct tda1004x_state *state; | 1250 | struct tda1004x_state *state; |
| 1251 | int id; | ||
| 1251 | 1252 | ||
| 1252 | /* allocate memory for the internal state */ | 1253 | /* allocate memory for the internal state */ |
| 1253 | state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); | 1254 | state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); |
| 1254 | if (!state) | 1255 | if (!state) { |
| 1256 | printk(KERN_ERR "Can't alocate memory for tda10045 state\n"); | ||
| 1255 | return NULL; | 1257 | return NULL; |
| 1258 | } | ||
| 1256 | 1259 | ||
| 1257 | /* setup the state */ | 1260 | /* setup the state */ |
| 1258 | state->config = config; | 1261 | state->config = config; |
| @@ -1260,7 +1263,15 @@ struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, | |||
| 1260 | state->demod_type = TDA1004X_DEMOD_TDA10045; | 1263 | state->demod_type = TDA1004X_DEMOD_TDA10045; |
| 1261 | 1264 | ||
| 1262 | /* check if the demod is there */ | 1265 | /* check if the demod is there */ |
| 1263 | if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) { | 1266 | id = tda1004x_read_byte(state, TDA1004X_CHIPID); |
| 1267 | if (id < 0) { | ||
| 1268 | printk(KERN_ERR "tda10045: chip is not answering. Giving up.\n"); | ||
| 1269 | kfree(state); | ||
| 1270 | return NULL; | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | if (id != 0x25) { | ||
| 1274 | printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id); | ||
| 1264 | kfree(state); | 1275 | kfree(state); |
| 1265 | return NULL; | 1276 | return NULL; |
| 1266 | } | 1277 | } |
| @@ -1307,11 +1318,14 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, | |||
| 1307 | struct i2c_adapter* i2c) | 1318 | struct i2c_adapter* i2c) |
| 1308 | { | 1319 | { |
| 1309 | struct tda1004x_state *state; | 1320 | struct tda1004x_state *state; |
| 1321 | int id; | ||
| 1310 | 1322 | ||
| 1311 | /* allocate memory for the internal state */ | 1323 | /* allocate memory for the internal state */ |
| 1312 | state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); | 1324 | state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL); |
| 1313 | if (!state) | 1325 | if (!state) { |
| 1326 | printk(KERN_ERR "Can't alocate memory for tda10046 state\n"); | ||
| 1314 | return NULL; | 1327 | return NULL; |
| 1328 | } | ||
| 1315 | 1329 | ||
| 1316 | /* setup the state */ | 1330 | /* setup the state */ |
| 1317 | state->config = config; | 1331 | state->config = config; |
| @@ -1319,7 +1333,14 @@ struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, | |||
| 1319 | state->demod_type = TDA1004X_DEMOD_TDA10046; | 1333 | state->demod_type = TDA1004X_DEMOD_TDA10046; |
| 1320 | 1334 | ||
| 1321 | /* check if the demod is there */ | 1335 | /* check if the demod is there */ |
| 1322 | if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) { | 1336 | id = tda1004x_read_byte(state, TDA1004X_CHIPID); |
| 1337 | if (id < 0) { | ||
| 1338 | printk(KERN_ERR "tda10046: chip is not answering. Giving up.\n"); | ||
| 1339 | kfree(state); | ||
| 1340 | return NULL; | ||
| 1341 | } | ||
| 1342 | if (id != 0x46) { | ||
| 1343 | printk(KERN_ERR "Invalid tda1004x ID = 0x%02x. Can't proceed\n", id); | ||
| 1323 | kfree(state); | 1344 | kfree(state); |
| 1324 | return NULL; | 1345 | return NULL; |
| 1325 | } | 1346 | } |
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index d4339b1b3b68..07643e010093 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
| @@ -101,6 +101,7 @@ config DVB_BUDGET | |||
| 101 | config DVB_BUDGET_CI | 101 | config DVB_BUDGET_CI |
| 102 | tristate "Budget cards with onboard CI connector" | 102 | tristate "Budget cards with onboard CI connector" |
| 103 | depends on DVB_BUDGET_CORE && I2C | 103 | depends on DVB_BUDGET_CORE && I2C |
| 104 | depends on INPUT # due to IR | ||
| 104 | select DVB_STV0297 if !DVB_FE_CUSTOMISE | 105 | select DVB_STV0297 if !DVB_FE_CUSTOMISE |
| 105 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | 106 | select DVB_STV0299 if !DVB_FE_CUSTOMISE |
| 106 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE | 107 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE |
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c index 9d81074b31df..3a3f5279e927 100644 --- a/drivers/media/dvb/ttpci/av7110_hw.c +++ b/drivers/media/dvb/ttpci/av7110_hw.c | |||
| @@ -427,6 +427,7 @@ static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length) | |||
| 427 | if (err) { | 427 | if (err) { |
| 428 | printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", | 428 | printk(KERN_ERR "%s: timeout waiting on busy %s QUEUE\n", |
| 429 | __func__, type); | 429 | __func__, type); |
| 430 | av7110->arm_errors++; | ||
| 430 | return -ETIMEDOUT; | 431 | return -ETIMEDOUT; |
| 431 | } | 432 | } |
| 432 | msleep(1); | 433 | msleep(1); |
| @@ -853,10 +854,8 @@ static osd_raw_window_t bpp2bit[8] = { | |||
| 853 | 854 | ||
| 854 | static inline int WaitUntilBmpLoaded(struct av7110 *av7110) | 855 | static inline int WaitUntilBmpLoaded(struct av7110 *av7110) |
| 855 | { | 856 | { |
| 856 | int ret = wait_event_interruptible_timeout(av7110->bmpq, | 857 | int ret = wait_event_timeout(av7110->bmpq, |
| 857 | av7110->bmp_state != BMP_LOADING, 10*HZ); | 858 | av7110->bmp_state != BMP_LOADING, 10*HZ); |
| 858 | if (ret == -ERESTARTSYS) | ||
| 859 | return ret; | ||
| 860 | if (ret == 0) { | 859 | if (ret == 0) { |
| 861 | printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n", | 860 | printk("dvb-ttpci: warning: timeout waiting in LoadBitmap: %d, %d\n", |
| 862 | ret, av7110->bmp_state); | 861 | ret, av7110->bmp_state); |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 3b26fbd3e558..5ccb0aeca8cc 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
| @@ -793,6 +793,14 @@ menuconfig V4L_USB_DRIVERS | |||
| 793 | 793 | ||
| 794 | if V4L_USB_DRIVERS && USB | 794 | if V4L_USB_DRIVERS && USB |
| 795 | 795 | ||
| 796 | config USB_VIDEO_CLASS | ||
| 797 | tristate "USB Video Class (UVC)" | ||
| 798 | ---help--- | ||
| 799 | Support for the USB Video Class (UVC). Currently only video | ||
| 800 | input devices, such as webcams, are supported. | ||
| 801 | |||
| 802 | For more information see: <http://linux-uvc.berlios.de/> | ||
| 803 | |||
| 796 | source "drivers/media/video/pvrusb2/Kconfig" | 804 | source "drivers/media/video/pvrusb2/Kconfig" |
| 797 | 805 | ||
| 798 | source "drivers/media/video/em28xx/Kconfig" | 806 | source "drivers/media/video/em28xx/Kconfig" |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index dff0d6abe917..ecbbfaab24d5 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
| @@ -136,6 +136,8 @@ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o | |||
| 136 | 136 | ||
| 137 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ | 137 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ |
| 138 | 138 | ||
| 139 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ | ||
| 140 | |||
| 139 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core | 141 | EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core |
| 140 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends | 142 | EXTRA_CFLAGS += -Idrivers/media/dvb/frontends |
| 141 | EXTRA_CFLAGS += -Idrivers/media/common/tuners | 143 | EXTRA_CFLAGS += -Idrivers/media/common/tuners |
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c index a2a6983444fa..898e12395e7c 100644 --- a/drivers/media/video/au0828/au0828-cards.c +++ b/drivers/media/video/au0828/au0828-cards.c | |||
| @@ -77,8 +77,14 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) | |||
| 77 | 77 | ||
| 78 | /* Make sure we support the board model */ | 78 | /* Make sure we support the board model */ |
| 79 | switch (tv.model) { | 79 | switch (tv.model) { |
| 80 | case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */ | ||
| 80 | case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ | 81 | case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ |
| 82 | case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ | ||
| 83 | case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ | ||
| 84 | case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ | ||
| 85 | case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */ | ||
| 81 | case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ | 86 | case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ |
| 87 | case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ | ||
| 82 | break; | 88 | break; |
| 83 | default: | 89 | default: |
| 84 | printk(KERN_WARNING "%s: warning: " | 90 | printk(KERN_WARNING "%s: warning: " |
| @@ -175,6 +181,18 @@ struct usb_device_id au0828_usb_id_table [] = { | |||
| 175 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 }, | 181 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 }, |
| 176 | { USB_DEVICE(0x0fe9, 0xd620), | 182 | { USB_DEVICE(0x0fe9, 0xd620), |
| 177 | .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 }, | 183 | .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 }, |
| 184 | { USB_DEVICE(0x2040, 0x7210), | ||
| 185 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
| 186 | { USB_DEVICE(0x2040, 0x7217), | ||
| 187 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
| 188 | { USB_DEVICE(0x2040, 0x721b), | ||
| 189 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
| 190 | { USB_DEVICE(0x2040, 0x721f), | ||
| 191 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
| 192 | { USB_DEVICE(0x2040, 0x7280), | ||
| 193 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
| 194 | { USB_DEVICE(0x0fd9, 0x0008), | ||
| 195 | .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, | ||
| 178 | { }, | 196 | { }, |
| 179 | }; | 197 | }; |
| 180 | 198 | ||
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index 5f942690570c..9aefdc5ea79a 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig | |||
| @@ -10,8 +10,8 @@ config VIDEO_CX18 | |||
| 10 | select VIDEO_TVEEPROM | 10 | select VIDEO_TVEEPROM |
| 11 | select VIDEO_CX2341X | 11 | select VIDEO_CX2341X |
| 12 | select VIDEO_CS5345 | 12 | select VIDEO_CS5345 |
| 13 | select DVB_S5H1409 | 13 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
| 14 | select MEDIA_TUNER_MXL5005S | 14 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE |
| 15 | ---help--- | 15 | ---help--- |
| 16 | This is a video4linux driver for Conexant cx23418 based | 16 | This is a video4linux driver for Conexant cx23418 based |
| 17 | PCI combo video recorder devices. | 17 | PCI combo video recorder devices. |
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c index 9a26751615c6..faca43eb940f 100644 --- a/drivers/media/video/cx18/cx18-av-core.c +++ b/drivers/media/video/cx18/cx18-av-core.c | |||
| @@ -69,6 +69,58 @@ int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 and_mask, | |||
| 69 | or_value); | 69 | or_value); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value, int no_acfg_mask) | ||
| 73 | { | ||
| 74 | int retval; | ||
| 75 | u32 saved_reg[8] = {0}; | ||
| 76 | |||
| 77 | if (no_acfg_mask & CXADEC_NO_ACFG_AFE) { | ||
| 78 | saved_reg[0] = cx18_av_read4(cx, CXADEC_CHIP_CTRL); | ||
| 79 | saved_reg[1] = cx18_av_read4(cx, CXADEC_AFE_CTRL); | ||
| 80 | } | ||
| 81 | |||
| 82 | if (no_acfg_mask & CXADEC_NO_ACFG_PLL) { | ||
| 83 | saved_reg[2] = cx18_av_read4(cx, CXADEC_PLL_CTRL1); | ||
| 84 | saved_reg[3] = cx18_av_read4(cx, CXADEC_VID_PLL_FRAC); | ||
| 85 | } | ||
| 86 | |||
| 87 | if (no_acfg_mask & CXADEC_NO_ACFG_VID) { | ||
| 88 | saved_reg[4] = cx18_av_read4(cx, CXADEC_HORIZ_TIM_CTRL); | ||
| 89 | saved_reg[5] = cx18_av_read4(cx, CXADEC_VERT_TIM_CTRL); | ||
| 90 | saved_reg[6] = cx18_av_read4(cx, CXADEC_SRC_COMB_CFG); | ||
| 91 | saved_reg[7] = cx18_av_read4(cx, CXADEC_CHROMA_VBIOFF_CFG); | ||
| 92 | } | ||
| 93 | |||
| 94 | retval = cx18_av_write(cx, addr, value); | ||
| 95 | |||
| 96 | if (no_acfg_mask & CXADEC_NO_ACFG_AFE) { | ||
| 97 | cx18_av_write4(cx, CXADEC_CHIP_CTRL, saved_reg[0]); | ||
| 98 | cx18_av_write4(cx, CXADEC_AFE_CTRL, saved_reg[1]); | ||
| 99 | } | ||
| 100 | |||
| 101 | if (no_acfg_mask & CXADEC_NO_ACFG_PLL) { | ||
| 102 | cx18_av_write4(cx, CXADEC_PLL_CTRL1, saved_reg[2]); | ||
| 103 | cx18_av_write4(cx, CXADEC_VID_PLL_FRAC, saved_reg[3]); | ||
| 104 | } | ||
| 105 | |||
| 106 | if (no_acfg_mask & CXADEC_NO_ACFG_VID) { | ||
| 107 | cx18_av_write4(cx, CXADEC_HORIZ_TIM_CTRL, saved_reg[4]); | ||
| 108 | cx18_av_write4(cx, CXADEC_VERT_TIM_CTRL, saved_reg[5]); | ||
| 109 | cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, saved_reg[6]); | ||
| 110 | cx18_av_write4(cx, CXADEC_CHROMA_VBIOFF_CFG, saved_reg[7]); | ||
| 111 | } | ||
| 112 | |||
| 113 | return retval; | ||
| 114 | } | ||
| 115 | |||
| 116 | int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned and_mask, | ||
| 117 | u8 or_value, int no_acfg_mask) | ||
| 118 | { | ||
| 119 | return cx18_av_write_no_acfg(cx, addr, | ||
| 120 | (cx18_av_read(cx, addr) & and_mask) | | ||
| 121 | or_value, no_acfg_mask); | ||
| 122 | } | ||
| 123 | |||
| 72 | /* ----------------------------------------------------------------------- */ | 124 | /* ----------------------------------------------------------------------- */ |
| 73 | 125 | ||
| 74 | static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | 126 | static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, |
| @@ -170,13 +222,15 @@ static void input_change(struct cx18 *cx) | |||
| 170 | 222 | ||
| 171 | /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */ | 223 | /* Follow step 8c and 8d of section 3.16 in the cx18_av datasheet */ |
| 172 | if (std & V4L2_STD_SECAM) | 224 | if (std & V4L2_STD_SECAM) |
| 173 | cx18_av_write(cx, 0x402, 0); | 225 | cx18_av_write_no_acfg(cx, 0x402, 0, CXADEC_NO_ACFG_ALL); |
| 174 | else { | 226 | else { |
| 175 | cx18_av_write(cx, 0x402, 0x04); | 227 | cx18_av_write_no_acfg(cx, 0x402, 0x04, CXADEC_NO_ACFG_ALL); |
| 176 | cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11); | 228 | cx18_av_write(cx, 0x49f, (std & V4L2_STD_NTSC) ? 0x14 : 0x11); |
| 177 | } | 229 | } |
| 178 | cx18_av_and_or(cx, 0x401, ~0x60, 0); | 230 | cx18_av_and_or_no_acfg(cx, 0x401, ~0x60, 0, |
| 179 | cx18_av_and_or(cx, 0x401, ~0x60, 0x60); | 231 | CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID); |
| 232 | cx18_av_and_or_no_acfg(cx, 0x401, ~0x60, 0x60, | ||
| 233 | CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID); | ||
| 180 | 234 | ||
| 181 | if (std & V4L2_STD_525_60) { | 235 | if (std & V4L2_STD_525_60) { |
| 182 | if (std == V4L2_STD_NTSC_M_JP) { | 236 | if (std == V4L2_STD_NTSC_M_JP) { |
| @@ -228,7 +282,7 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
| 228 | 282 | ||
| 229 | if ((vid_input & ~0xff0) || | 283 | if ((vid_input & ~0xff0) || |
| 230 | luma < CX18_AV_SVIDEO_LUMA1 || | 284 | luma < CX18_AV_SVIDEO_LUMA1 || |
| 231 | luma > CX18_AV_SVIDEO_LUMA4 || | 285 | luma > CX18_AV_SVIDEO_LUMA8 || |
| 232 | chroma < CX18_AV_SVIDEO_CHROMA4 || | 286 | chroma < CX18_AV_SVIDEO_CHROMA4 || |
| 233 | chroma > CX18_AV_SVIDEO_CHROMA8) { | 287 | chroma > CX18_AV_SVIDEO_CHROMA8) { |
| 234 | CX18_ERR("0x%04x is not a valid video input!\n", | 288 | CX18_ERR("0x%04x is not a valid video input!\n", |
| @@ -262,7 +316,8 @@ static int set_input(struct cx18 *cx, enum cx18_av_video_input vid_input, | |||
| 262 | 316 | ||
| 263 | cx18_av_write(cx, 0x103, reg); | 317 | cx18_av_write(cx, 0x103, reg); |
| 264 | /* Set INPUT_MODE to Composite (0) or S-Video (1) */ | 318 | /* Set INPUT_MODE to Composite (0) or S-Video (1) */ |
| 265 | cx18_av_and_or(cx, 0x401, ~0x6, is_composite ? 0 : 0x02); | 319 | cx18_av_and_or_no_acfg(cx, 0x401, ~0x6, is_composite ? 0 : 0x02, |
| 320 | CXADEC_NO_ACFG_PLL | CXADEC_NO_ACFG_VID); | ||
| 266 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ | 321 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ |
| 267 | cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); | 322 | cx18_av_and_or(cx, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); |
| 268 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ | 323 | /* Set DUAL_MODE_ADC2 to 1 if input comes from both CH2 and CH3 */ |
| @@ -318,12 +373,12 @@ static int set_v4lstd(struct cx18 *cx) | |||
| 318 | This happens for example with the Yuan MPC622. */ | 373 | This happens for example with the Yuan MPC622. */ |
| 319 | if (fmt >= 4 && fmt < 8) { | 374 | if (fmt >= 4 && fmt < 8) { |
| 320 | /* Set format to NTSC-M */ | 375 | /* Set format to NTSC-M */ |
| 321 | cx18_av_and_or(cx, 0x400, ~0xf, 1); | 376 | cx18_av_and_or_no_acfg(cx, 0x400, ~0xf, 1, CXADEC_NO_ACFG_AFE); |
| 322 | /* Turn off LCOMB */ | 377 | /* Turn off LCOMB */ |
| 323 | cx18_av_and_or(cx, 0x47b, ~6, 0); | 378 | cx18_av_and_or(cx, 0x47b, ~6, 0); |
| 324 | } | 379 | } |
| 325 | cx18_av_and_or(cx, 0x400, ~0xf, fmt); | 380 | cx18_av_and_or_no_acfg(cx, 0x400, ~0xf, fmt, CXADEC_NO_ACFG_AFE); |
| 326 | cx18_av_and_or(cx, 0x403, ~0x3, pal_m); | 381 | cx18_av_and_or_no_acfg(cx, 0x403, ~0x3, pal_m, CXADEC_NO_ACFG_ALL); |
| 327 | cx18_av_vbi_setup(cx); | 382 | cx18_av_vbi_setup(cx); |
| 328 | input_change(cx); | 383 | input_change(cx); |
| 329 | return 0; | 384 | return 0; |
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h index 786901d72e9a..c172823ce1d8 100644 --- a/drivers/media/video/cx18/cx18-av-core.h +++ b/drivers/media/video/cx18/cx18-av-core.h | |||
| @@ -37,12 +37,16 @@ enum cx18_av_video_input { | |||
| 37 | CX18_AV_COMPOSITE7, | 37 | CX18_AV_COMPOSITE7, |
| 38 | CX18_AV_COMPOSITE8, | 38 | CX18_AV_COMPOSITE8, |
| 39 | 39 | ||
| 40 | /* S-Video inputs consist of one luma input (In1-In4) ORed with one | 40 | /* S-Video inputs consist of one luma input (In1-In8) ORed with one |
| 41 | chroma input (In5-In8) */ | 41 | chroma input (In5-In8) */ |
| 42 | CX18_AV_SVIDEO_LUMA1 = 0x10, | 42 | CX18_AV_SVIDEO_LUMA1 = 0x10, |
| 43 | CX18_AV_SVIDEO_LUMA2 = 0x20, | 43 | CX18_AV_SVIDEO_LUMA2 = 0x20, |
| 44 | CX18_AV_SVIDEO_LUMA3 = 0x30, | 44 | CX18_AV_SVIDEO_LUMA3 = 0x30, |
| 45 | CX18_AV_SVIDEO_LUMA4 = 0x40, | 45 | CX18_AV_SVIDEO_LUMA4 = 0x40, |
| 46 | CX18_AV_SVIDEO_LUMA5 = 0x50, | ||
| 47 | CX18_AV_SVIDEO_LUMA6 = 0x60, | ||
| 48 | CX18_AV_SVIDEO_LUMA7 = 0x70, | ||
| 49 | CX18_AV_SVIDEO_LUMA8 = 0x80, | ||
| 46 | CX18_AV_SVIDEO_CHROMA4 = 0x400, | 50 | CX18_AV_SVIDEO_CHROMA4 = 0x400, |
| 47 | CX18_AV_SVIDEO_CHROMA5 = 0x500, | 51 | CX18_AV_SVIDEO_CHROMA5 = 0x500, |
| 48 | CX18_AV_SVIDEO_CHROMA6 = 0x600, | 52 | CX18_AV_SVIDEO_CHROMA6 = 0x600, |
| @@ -291,14 +295,24 @@ struct cx18_av_state { | |||
| 291 | #define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */ | 295 | #define CXADEC_SELECT_AUDIO_STANDARD_FM 0xF9 /* FM radio */ |
| 292 | #define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */ | 296 | #define CXADEC_SELECT_AUDIO_STANDARD_AUTO 0xFF /* Auto detect */ |
| 293 | 297 | ||
| 298 | /* Flags on what to preserve on write to 0x400-0x403 with cx18_av_.*_no_acfg()*/ | ||
| 299 | #define CXADEC_NO_ACFG_AFE 0x01 /* Preserve 0x100-0x107 */ | ||
| 300 | #define CXADEC_NO_ACFG_PLL 0x02 /* Preserve 0x108-0x10f */ | ||
| 301 | #define CXADEC_NO_ACFG_VID 0x04 /* Preserve 0x470-0x47f */ | ||
| 302 | #define CXADEC_NO_ACFG_ALL 0x07 | ||
| 303 | |||
| 294 | /* ----------------------------------------------------------------------- */ | 304 | /* ----------------------------------------------------------------------- */ |
| 295 | /* cx18_av-core.c */ | 305 | /* cx18_av-core.c */ |
| 296 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); | 306 | int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); |
| 297 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); | 307 | int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); |
| 308 | int cx18_av_write_no_acfg(struct cx18 *cx, u16 addr, u8 value, | ||
| 309 | int no_acfg_mask); | ||
| 298 | u8 cx18_av_read(struct cx18 *cx, u16 addr); | 310 | u8 cx18_av_read(struct cx18 *cx, u16 addr); |
| 299 | u32 cx18_av_read4(struct cx18 *cx, u16 addr); | 311 | u32 cx18_av_read4(struct cx18 *cx, u16 addr); |
| 300 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); | 312 | int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); |
| 301 | int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); | 313 | int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); |
| 314 | int cx18_av_and_or_no_acfg(struct cx18 *cx, u16 addr, unsigned mask, u8 value, | ||
| 315 | int no_acfg_mask); | ||
| 302 | int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); | 316 | int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); |
| 303 | 317 | ||
| 304 | /* ----------------------------------------------------------------------- */ | 318 | /* ----------------------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index baccd079243d..c26e0ef5b075 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #include "cx18-driver.h" | 24 | #include "cx18-driver.h" |
| 25 | #include "cx18-cards.h" | 25 | #include "cx18-cards.h" |
| 26 | #include "cx18-av-core.h" | ||
| 26 | #include "cx18-i2c.h" | 27 | #include "cx18-i2c.h" |
| 27 | #include <media/cs5345.h> | 28 | #include <media/cs5345.h> |
| 28 | 29 | ||
| @@ -54,22 +55,22 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { | |||
| 54 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | | 55 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | |
| 55 | CX18_HW_CS5345 | CX18_HW_DVB, | 56 | CX18_HW_CS5345 | CX18_HW_DVB, |
| 56 | .video_inputs = { | 57 | .video_inputs = { |
| 57 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 58 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, |
| 58 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 59 | { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, |
| 59 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, | 60 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 }, |
| 60 | { CX18_CARD_INPUT_SVIDEO2, 2, CX23418_SVIDEO2 }, | 61 | { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO2 }, |
| 61 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 }, | 62 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 }, |
| 62 | }, | 63 | }, |
| 63 | .audio_inputs = { | 64 | .audio_inputs = { |
| 64 | { CX18_CARD_INPUT_AUD_TUNER, | 65 | { CX18_CARD_INPUT_AUD_TUNER, |
| 65 | CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, | 66 | CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, |
| 66 | { CX18_CARD_INPUT_LINE_IN1, | 67 | { CX18_CARD_INPUT_LINE_IN1, |
| 67 | CX23418_AUDIO_SERIAL, CS5345_IN_2 }, | 68 | CX18_AV_AUDIO_SERIAL, CS5345_IN_2 }, |
| 68 | { CX18_CARD_INPUT_LINE_IN2, | 69 | { CX18_CARD_INPUT_LINE_IN2, |
| 69 | CX23418_AUDIO_SERIAL, CS5345_IN_2 }, | 70 | CX18_AV_AUDIO_SERIAL, CS5345_IN_3 }, |
| 70 | }, | 71 | }, |
| 71 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, | 72 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, |
| 72 | CX23418_AUDIO_SERIAL, 0 }, | 73 | CX18_AV_AUDIO_SERIAL, CS5345_IN_4 }, |
| 73 | .ddr = { | 74 | .ddr = { |
| 74 | /* ESMT M13S128324A-5B memory */ | 75 | /* ESMT M13S128324A-5B memory */ |
| 75 | .chip_config = 0x003, | 76 | .chip_config = 0x003, |
| @@ -81,6 +82,11 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { | |||
| 81 | }, | 82 | }, |
| 82 | .gpio_init.initial_value = 0x3001, | 83 | .gpio_init.initial_value = 0x3001, |
| 83 | .gpio_init.direction = 0x3001, | 84 | .gpio_init.direction = 0x3001, |
| 85 | .gpio_i2c_slave_reset = { | ||
| 86 | .active_lo_mask = 0x3001, | ||
| 87 | .msecs_asserted = 10, | ||
| 88 | .msecs_recovery = 40, | ||
| 89 | }, | ||
| 84 | .i2c = &cx18_i2c_std, | 90 | .i2c = &cx18_i2c_std, |
| 85 | }; | 91 | }; |
| 86 | 92 | ||
| @@ -94,22 +100,22 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { | |||
| 94 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | | 100 | .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | |
| 95 | CX18_HW_CS5345 | CX18_HW_DVB, | 101 | CX18_HW_CS5345 | CX18_HW_DVB, |
| 96 | .video_inputs = { | 102 | .video_inputs = { |
| 97 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 103 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE7 }, |
| 98 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 104 | { CX18_CARD_INPUT_SVIDEO1, 1, CX18_AV_SVIDEO1 }, |
| 99 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, | 105 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE3 }, |
| 100 | { CX18_CARD_INPUT_SVIDEO2, 2, CX23418_SVIDEO2 }, | 106 | { CX18_CARD_INPUT_SVIDEO2, 2, CX18_AV_SVIDEO2 }, |
| 101 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX23418_COMPOSITE4 }, | 107 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE4 }, |
| 102 | }, | 108 | }, |
| 103 | .audio_inputs = { | 109 | .audio_inputs = { |
| 104 | { CX18_CARD_INPUT_AUD_TUNER, | 110 | { CX18_CARD_INPUT_AUD_TUNER, |
| 105 | CX23418_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, | 111 | CX18_AV_AUDIO8, CS5345_IN_1 | CS5345_MCLK_1_5 }, |
| 106 | { CX18_CARD_INPUT_LINE_IN1, | 112 | { CX18_CARD_INPUT_LINE_IN1, |
| 107 | CX23418_AUDIO_SERIAL, CS5345_IN_2 }, | 113 | CX18_AV_AUDIO_SERIAL, CS5345_IN_2 }, |
| 108 | { CX18_CARD_INPUT_LINE_IN2, | 114 | { CX18_CARD_INPUT_LINE_IN2, |
| 109 | CX23418_AUDIO_SERIAL, CS5345_IN_2 }, | 115 | CX18_AV_AUDIO_SERIAL, CS5345_IN_3 }, |
| 110 | }, | 116 | }, |
| 111 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, | 117 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, |
| 112 | CX23418_AUDIO_SERIAL, 0 }, | 118 | CX18_AV_AUDIO_SERIAL, CS5345_IN_4 }, |
| 113 | .ddr = { | 119 | .ddr = { |
| 114 | /* Samsung K4D263238G-VC33 memory */ | 120 | /* Samsung K4D263238G-VC33 memory */ |
| 115 | .chip_config = 0x003, | 121 | .chip_config = 0x003, |
| @@ -121,6 +127,11 @@ static const struct cx18_card cx18_card_hvr1600_samsung = { | |||
| 121 | }, | 127 | }, |
| 122 | .gpio_init.initial_value = 0x3001, | 128 | .gpio_init.initial_value = 0x3001, |
| 123 | .gpio_init.direction = 0x3001, | 129 | .gpio_init.direction = 0x3001, |
| 130 | .gpio_i2c_slave_reset = { | ||
| 131 | .active_lo_mask = 0x3001, | ||
| 132 | .msecs_asserted = 10, | ||
| 133 | .msecs_recovery = 40, | ||
| 134 | }, | ||
| 124 | .i2c = &cx18_i2c_std, | 135 | .i2c = &cx18_i2c_std, |
| 125 | }; | 136 | }; |
| 126 | 137 | ||
| @@ -141,19 +152,19 @@ static const struct cx18_card cx18_card_h900 = { | |||
| 141 | .hw_audio_ctrl = CX18_HW_CX23418, | 152 | .hw_audio_ctrl = CX18_HW_CX23418, |
| 142 | .hw_all = CX18_HW_TUNER, | 153 | .hw_all = CX18_HW_TUNER, |
| 143 | .video_inputs = { | 154 | .video_inputs = { |
| 144 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE2 }, | 155 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, |
| 145 | { CX18_CARD_INPUT_SVIDEO1, 1, | 156 | { CX18_CARD_INPUT_SVIDEO1, 1, |
| 146 | CX23418_SVIDEO_LUMA3 | CX23418_SVIDEO_CHROMA4 }, | 157 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, |
| 147 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE1 }, | 158 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, |
| 148 | }, | 159 | }, |
| 149 | .audio_inputs = { | 160 | .audio_inputs = { |
| 150 | { CX18_CARD_INPUT_AUD_TUNER, | 161 | { CX18_CARD_INPUT_AUD_TUNER, |
| 151 | CX23418_AUDIO8, 0 }, | 162 | CX18_AV_AUDIO8, 0 }, |
| 152 | { CX18_CARD_INPUT_LINE_IN1, | 163 | { CX18_CARD_INPUT_LINE_IN1, |
| 153 | CX23418_AUDIO_SERIAL, 0 }, | 164 | CX18_AV_AUDIO_SERIAL, 0 }, |
| 154 | }, | 165 | }, |
| 155 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, | 166 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, |
| 156 | CX23418_AUDIO_SERIAL, 0 }, | 167 | CX18_AV_AUDIO_SERIAL, 0 }, |
| 157 | .tuners = { | 168 | .tuners = { |
| 158 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | 169 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, |
| 159 | }, | 170 | }, |
| @@ -183,23 +194,26 @@ static const struct cx18_card_pci_info cx18_pci_mpc718[] = { | |||
| 183 | static const struct cx18_card cx18_card_mpc718 = { | 194 | static const struct cx18_card cx18_card_mpc718 = { |
| 184 | .type = CX18_CARD_YUAN_MPC718, | 195 | .type = CX18_CARD_YUAN_MPC718, |
| 185 | .name = "Yuan MPC718", | 196 | .name = "Yuan MPC718", |
| 186 | .comment = "Not yet supported!\n", | 197 | .comment = "Some Composite and S-Video inputs are currently working.\n", |
| 187 | .v4l2_capabilities = 0, | 198 | .v4l2_capabilities = CX18_CAP_ENCODER, |
| 188 | .hw_audio_ctrl = CX18_HW_CX23418, | 199 | .hw_audio_ctrl = CX18_HW_CX23418, |
| 189 | .hw_all = CX18_HW_TUNER, | 200 | .hw_all = CX18_HW_TUNER, |
| 190 | .video_inputs = { | 201 | .video_inputs = { |
| 191 | { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, | 202 | { CX18_CARD_INPUT_VID_TUNER, 0, CX18_AV_COMPOSITE2 }, |
| 192 | { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, | 203 | { CX18_CARD_INPUT_SVIDEO1, 1, |
| 193 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, | 204 | CX18_AV_SVIDEO_LUMA3 | CX18_AV_SVIDEO_CHROMA4 }, |
| 205 | { CX18_CARD_INPUT_COMPOSITE1, 1, CX18_AV_COMPOSITE1 }, | ||
| 206 | { CX18_CARD_INPUT_SVIDEO2, 2, | ||
| 207 | CX18_AV_SVIDEO_LUMA7 | CX18_AV_SVIDEO_CHROMA8 }, | ||
| 208 | { CX18_CARD_INPUT_COMPOSITE2, 2, CX18_AV_COMPOSITE6 }, | ||
| 209 | { CX18_CARD_INPUT_COMPOSITE3, 2, CX18_AV_COMPOSITE3 }, | ||
| 194 | }, | 210 | }, |
| 195 | .audio_inputs = { | 211 | .audio_inputs = { |
| 196 | { CX18_CARD_INPUT_AUD_TUNER, | 212 | { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO5, 0 }, |
| 197 | CX23418_AUDIO8, 0 }, | 213 | { CX18_CARD_INPUT_LINE_IN1, CX18_AV_AUDIO_SERIAL, 0 }, |
| 198 | { CX18_CARD_INPUT_LINE_IN1, | 214 | { CX18_CARD_INPUT_LINE_IN2, CX18_AV_AUDIO_SERIAL, 0 }, |
| 199 | CX23418_AUDIO_SERIAL, 0 }, | ||
| 200 | }, | 215 | }, |
| 201 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, | 216 | .radio_input = { CX18_CARD_INPUT_AUD_TUNER, CX18_AV_AUDIO_SERIAL, 0 }, |
| 202 | CX23418_AUDIO_SERIAL, 0 }, | ||
| 203 | .tuners = { | 217 | .tuners = { |
| 204 | /* XC3028 tuner */ | 218 | /* XC3028 tuner */ |
| 205 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, | 219 | { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, |
diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index bccb67f0db16..dc2dd945d4c3 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h | |||
| @@ -36,36 +36,6 @@ | |||
| 36 | #define CX18_CARD_INPUT_COMPOSITE2 5 | 36 | #define CX18_CARD_INPUT_COMPOSITE2 5 |
| 37 | #define CX18_CARD_INPUT_COMPOSITE3 6 | 37 | #define CX18_CARD_INPUT_COMPOSITE3 6 |
| 38 | 38 | ||
| 39 | enum cx34180_video_input { | ||
| 40 | /* Composite video inputs In1-In8 */ | ||
| 41 | CX23418_COMPOSITE1 = 1, | ||
| 42 | CX23418_COMPOSITE2, | ||
| 43 | CX23418_COMPOSITE3, | ||
| 44 | CX23418_COMPOSITE4, | ||
| 45 | CX23418_COMPOSITE5, | ||
| 46 | CX23418_COMPOSITE6, | ||
| 47 | CX23418_COMPOSITE7, | ||
| 48 | CX23418_COMPOSITE8, | ||
| 49 | |||
| 50 | /* S-Video inputs consist of one luma input (In1-In4) ORed with one | ||
| 51 | chroma input (In5-In8) */ | ||
| 52 | CX23418_SVIDEO_LUMA1 = 0x10, | ||
| 53 | CX23418_SVIDEO_LUMA2 = 0x20, | ||
| 54 | CX23418_SVIDEO_LUMA3 = 0x30, | ||
| 55 | CX23418_SVIDEO_LUMA4 = 0x40, | ||
| 56 | CX23418_SVIDEO_CHROMA4 = 0x400, | ||
| 57 | CX23418_SVIDEO_CHROMA5 = 0x500, | ||
| 58 | CX23418_SVIDEO_CHROMA6 = 0x600, | ||
| 59 | CX23418_SVIDEO_CHROMA7 = 0x700, | ||
| 60 | CX23418_SVIDEO_CHROMA8 = 0x800, | ||
| 61 | |||
| 62 | /* S-Video aliases for common luma/chroma combinations */ | ||
| 63 | CX23418_SVIDEO1 = 0x510, | ||
| 64 | CX23418_SVIDEO2 = 0x620, | ||
| 65 | CX23418_SVIDEO3 = 0x730, | ||
| 66 | CX23418_SVIDEO4 = 0x840, | ||
| 67 | }; | ||
| 68 | |||
| 69 | /* audio inputs */ | 39 | /* audio inputs */ |
| 70 | #define CX18_CARD_INPUT_AUD_TUNER 1 | 40 | #define CX18_CARD_INPUT_AUD_TUNER 1 |
| 71 | #define CX18_CARD_INPUT_LINE_IN1 2 | 41 | #define CX18_CARD_INPUT_LINE_IN1 2 |
| @@ -75,16 +45,6 @@ enum cx34180_video_input { | |||
| 75 | #define CX18_CARD_MAX_AUDIO_INPUTS 3 | 45 | #define CX18_CARD_MAX_AUDIO_INPUTS 3 |
| 76 | #define CX18_CARD_MAX_TUNERS 2 | 46 | #define CX18_CARD_MAX_TUNERS 2 |
| 77 | 47 | ||
| 78 | enum cx23418_audio_input { | ||
| 79 | /* Audio inputs: serial or In4-In8 */ | ||
| 80 | CX23418_AUDIO_SERIAL, | ||
| 81 | CX23418_AUDIO4 = 4, | ||
| 82 | CX23418_AUDIO5, | ||
| 83 | CX23418_AUDIO6, | ||
| 84 | CX23418_AUDIO7, | ||
| 85 | CX23418_AUDIO8, | ||
| 86 | }; | ||
| 87 | |||
| 88 | /* V4L2 capability aliases */ | 48 | /* V4L2 capability aliases */ |
| 89 | #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ | 49 | #define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \ |
| 90 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE) | 50 | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE) |
| @@ -118,6 +78,13 @@ struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */ | |||
| 118 | u32 initial_value; | 78 | u32 initial_value; |
| 119 | }; | 79 | }; |
| 120 | 80 | ||
| 81 | struct cx18_gpio_i2c_slave_reset { | ||
| 82 | u32 active_lo_mask; /* GPIO outputs that reset i2c chips when low */ | ||
| 83 | u32 active_hi_mask; /* GPIO outputs that reset i2c chips when high */ | ||
| 84 | int msecs_asserted; /* time period reset must remain asserted */ | ||
| 85 | int msecs_recovery; /* time after deassert for chips to be ready */ | ||
| 86 | }; | ||
| 87 | |||
| 121 | struct cx18_card_tuner { | 88 | struct cx18_card_tuner { |
| 122 | v4l2_std_id std; /* standard for which the tuner is suitable */ | 89 | v4l2_std_id std; /* standard for which the tuner is suitable */ |
| 123 | int tuner; /* tuner ID (from tuner.h) */ | 90 | int tuner; /* tuner ID (from tuner.h) */ |
| @@ -154,7 +121,8 @@ struct cx18_card { | |||
| 154 | 121 | ||
| 155 | /* GPIO card-specific settings */ | 122 | /* GPIO card-specific settings */ |
| 156 | u8 xceive_pin; /* XCeive tuner GPIO reset pin */ | 123 | u8 xceive_pin; /* XCeive tuner GPIO reset pin */ |
| 157 | struct cx18_gpio_init gpio_init; | 124 | struct cx18_gpio_init gpio_init; |
| 125 | struct cx18_gpio_i2c_slave_reset gpio_i2c_slave_reset; | ||
| 158 | 126 | ||
| 159 | struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; | 127 | struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; |
| 160 | struct cx18_card_tuner_i2c *i2c; | 128 | struct cx18_card_tuner_i2c *i2c; |
diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index c9744173f969..cae38985b131 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c | |||
| @@ -69,11 +69,21 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
| 69 | struct dvb_demux *demux = feed->demux; | 69 | struct dvb_demux *demux = feed->demux; |
| 70 | struct cx18_stream *stream = (struct cx18_stream *) demux->priv; | 70 | struct cx18_stream *stream = (struct cx18_stream *) demux->priv; |
| 71 | struct cx18 *cx = stream->cx; | 71 | struct cx18 *cx = stream->cx; |
| 72 | int ret = -EINVAL; | 72 | int ret; |
| 73 | u32 v; | 73 | u32 v; |
| 74 | 74 | ||
| 75 | CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n", | 75 | CX18_DEBUG_INFO("Start feed: pid = 0x%x index = %d\n", |
| 76 | feed->pid, feed->index); | 76 | feed->pid, feed->index); |
| 77 | |||
| 78 | mutex_lock(&cx->serialize_lock); | ||
| 79 | ret = cx18_init_on_first_open(cx); | ||
| 80 | mutex_unlock(&cx->serialize_lock); | ||
| 81 | if (ret) { | ||
| 82 | CX18_ERR("Failed to initialize firmware starting DVB feed\n"); | ||
| 83 | return ret; | ||
| 84 | } | ||
| 85 | ret = -EINVAL; | ||
| 86 | |||
| 77 | switch (cx->card->type) { | 87 | switch (cx->card->type) { |
| 78 | case CX18_CARD_HVR_1600_ESMT: | 88 | case CX18_CARD_HVR_1600_ESMT: |
| 79 | case CX18_CARD_HVR_1600_SAMSUNG: | 89 | case CX18_CARD_HVR_1600_SAMSUNG: |
| @@ -101,6 +111,11 @@ static int cx18_dvb_start_feed(struct dvb_demux_feed *feed) | |||
| 101 | if (stream->dvb.feeding++ == 0) { | 111 | if (stream->dvb.feeding++ == 0) { |
| 102 | CX18_DEBUG_INFO("Starting Transport DMA\n"); | 112 | CX18_DEBUG_INFO("Starting Transport DMA\n"); |
| 103 | ret = cx18_start_v4l2_encode_stream(stream); | 113 | ret = cx18_start_v4l2_encode_stream(stream); |
| 114 | if (ret < 0) { | ||
| 115 | CX18_DEBUG_INFO( | ||
| 116 | "Failed to start Transport DMA\n"); | ||
| 117 | stream->dvb.feeding--; | ||
| 118 | } | ||
| 104 | } else | 119 | } else |
| 105 | ret = 0; | 120 | ret = 0; |
| 106 | mutex_unlock(&stream->dvb.feedlock); | 121 | mutex_unlock(&stream->dvb.feedlock); |
diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index ceb63653c926..b302833f6f9d 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c | |||
| @@ -53,10 +53,34 @@ static void gpio_write(struct cx18 *cx) | |||
| 53 | write_reg(((dir & 0xffff) << 16) | (val & 0xffff), | 53 | write_reg(((dir & 0xffff) << 16) | (val & 0xffff), |
| 54 | CX18_REG_GPIO_OUT1); | 54 | CX18_REG_GPIO_OUT1); |
| 55 | write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); | 55 | write_reg(dir & 0xffff0000, CX18_REG_GPIO_DIR2); |
| 56 | write_reg((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), | 56 | write_reg_sync((dir & 0xffff0000) | ((val & 0xffff0000) >> 16), |
| 57 | CX18_REG_GPIO_OUT2); | 57 | CX18_REG_GPIO_OUT2); |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | void cx18_reset_i2c_slaves_gpio(struct cx18 *cx) | ||
| 61 | { | ||
| 62 | const struct cx18_gpio_i2c_slave_reset *p; | ||
| 63 | |||
| 64 | p = &cx->card->gpio_i2c_slave_reset; | ||
| 65 | |||
| 66 | if ((p->active_lo_mask | p->active_hi_mask) == 0) | ||
| 67 | return; | ||
| 68 | |||
| 69 | /* Assuming that the masks are a subset of the bits in gpio_dir */ | ||
| 70 | |||
| 71 | /* Assert */ | ||
| 72 | cx->gpio_val = | ||
| 73 | (cx->gpio_val | p->active_hi_mask) & ~(p->active_lo_mask); | ||
| 74 | gpio_write(cx); | ||
| 75 | schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_asserted)); | ||
| 76 | |||
| 77 | /* Deassert */ | ||
| 78 | cx->gpio_val = | ||
| 79 | (cx->gpio_val | p->active_lo_mask) & ~(p->active_hi_mask); | ||
| 80 | gpio_write(cx); | ||
| 81 | schedule_timeout_uninterruptible(msecs_to_jiffies(p->msecs_recovery)); | ||
| 82 | } | ||
| 83 | |||
| 60 | void cx18_gpio_init(struct cx18 *cx) | 84 | void cx18_gpio_init(struct cx18 *cx) |
| 61 | { | 85 | { |
| 62 | cx->gpio_dir = cx->card->gpio_init.direction; | 86 | cx->gpio_dir = cx->card->gpio_init.direction; |
diff --git a/drivers/media/video/cx18/cx18-gpio.h b/drivers/media/video/cx18/cx18-gpio.h index 41bac8856b50..525c328f748a 100644 --- a/drivers/media/video/cx18/cx18-gpio.h +++ b/drivers/media/video/cx18/cx18-gpio.h | |||
| @@ -21,4 +21,5 @@ | |||
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | void cx18_gpio_init(struct cx18 *cx); | 23 | void cx18_gpio_init(struct cx18 *cx); |
| 24 | void cx18_reset_i2c_slaves_gpio(struct cx18 *cx); | ||
| 24 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value); | 25 | int cx18_reset_tuner_gpio(void *dev, int cmd, int value); |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 1d6c51a75313..680bc4e35b79 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
| @@ -405,6 +405,8 @@ int init_cx18_i2c(struct cx18 *cx) | |||
| 405 | cx18_setscl(&cx->i2c_algo_cb_data[1], 1); | 405 | cx18_setscl(&cx->i2c_algo_cb_data[1], 1); |
| 406 | cx18_setsda(&cx->i2c_algo_cb_data[1], 1); | 406 | cx18_setsda(&cx->i2c_algo_cb_data[1], 1); |
| 407 | 407 | ||
| 408 | cx18_reset_i2c_slaves_gpio(cx); | ||
| 409 | |||
| 408 | return i2c_bit_add_bus(&cx->i2c_adap[0]) || | 410 | return i2c_bit_add_bus(&cx->i2c_adap[0]) || |
| 409 | i2c_bit_add_bus(&cx->i2c_adap[1]); | 411 | i2c_bit_add_bus(&cx->i2c_adap[1]); |
| 410 | } | 412 | } |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index 607efdcd22f8..1da6f134888d 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
| @@ -433,7 +433,7 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
| 433 | int chroma = vid_input & 0xf00; | 433 | int chroma = vid_input & 0xf00; |
| 434 | 434 | ||
| 435 | if ((vid_input & ~0xff0) || | 435 | if ((vid_input & ~0xff0) || |
| 436 | luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA4 || | 436 | luma < CX25840_SVIDEO_LUMA1 || luma > CX25840_SVIDEO_LUMA8 || |
| 437 | chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { | 437 | chroma < CX25840_SVIDEO_CHROMA4 || chroma > CX25840_SVIDEO_CHROMA8) { |
| 438 | v4l_err(client, "0x%04x is not a valid video input!\n", | 438 | v4l_err(client, "0x%04x is not a valid video input!\n", |
| 439 | vid_input); | 439 | vid_input); |
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index e976fc6bef7c..80c8883e54b5 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c | |||
| @@ -332,6 +332,12 @@ static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) | |||
| 332 | struct snd_pcm_runtime *runtime = substream->runtime; | 332 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 333 | int err; | 333 | int err; |
| 334 | 334 | ||
| 335 | if (!chip) { | ||
| 336 | printk(KERN_ERR "BUG: cx88 can't find device struct." | ||
| 337 | " Can't proceed with open\n"); | ||
| 338 | return -ENODEV; | ||
| 339 | } | ||
| 340 | |||
| 335 | err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); | 341 | err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); |
| 336 | if (err < 0) | 342 | if (err < 0) |
| 337 | goto _error; | 343 | goto _error; |
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 92b2a6db4fdc..3c006103c1eb 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
| @@ -268,6 +268,12 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream) | |||
| 268 | 268 | ||
| 269 | dprintk("opening device and trying to acquire exclusive lock\n"); | 269 | dprintk("opening device and trying to acquire exclusive lock\n"); |
| 270 | 270 | ||
| 271 | if (!dev) { | ||
| 272 | printk(KERN_ERR "BUG: em28xx can't find device struct." | ||
| 273 | " Can't proceed with open\n"); | ||
| 274 | return -ENODEV; | ||
| 275 | } | ||
| 276 | |||
| 271 | /* Sets volume, mute, etc */ | 277 | /* Sets volume, mute, etc */ |
| 272 | 278 | ||
| 273 | dev->mute = 0; | 279 | dev->mute = 0; |
| @@ -415,6 +421,12 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
| 415 | static int devnr; | 421 | static int devnr; |
| 416 | int ret, err; | 422 | int ret, err; |
| 417 | 423 | ||
| 424 | if (dev->has_audio_class) { | ||
| 425 | /* This device does not support the extension (in this case | ||
| 426 | the device is expecting the snd-usb-audio module */ | ||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 418 | printk(KERN_INFO "em28xx-audio.c: probing for em28x1 " | 430 | printk(KERN_INFO "em28xx-audio.c: probing for em28x1 " |
| 419 | "non standard usbaudio\n"); | 431 | "non standard usbaudio\n"); |
| 420 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " | 432 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " |
| @@ -458,6 +470,12 @@ static int em28xx_audio_fini(struct em28xx *dev) | |||
| 458 | if (dev == NULL) | 470 | if (dev == NULL) |
| 459 | return 0; | 471 | return 0; |
| 460 | 472 | ||
| 473 | if (dev->has_audio_class) { | ||
| 474 | /* This device does not support the extension (in this case | ||
| 475 | the device is expecting the snd-usb-audio module */ | ||
| 476 | return 0; | ||
| 477 | } | ||
| 478 | |||
| 461 | if (dev->adev) { | 479 | if (dev->adev) { |
| 462 | snd_card_free(dev->adev->sndcard); | 480 | snd_card_free(dev->adev->sndcard); |
| 463 | kfree(dev->adev); | 481 | kfree(dev->adev); |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 3e4f3c7e92e7..8cbda43727c3 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
| @@ -157,6 +157,7 @@ struct em28xx_board em28xx_boards[] = { | |||
| 157 | .tda9887_conf = TDA9887_PRESENT, | 157 | .tda9887_conf = TDA9887_PRESENT, |
| 158 | .tuner_type = TUNER_XC2028, | 158 | .tuner_type = TUNER_XC2028, |
| 159 | .mts_firmware = 1, | 159 | .mts_firmware = 1, |
| 160 | .has_dvb = 1, | ||
| 160 | .decoder = EM28XX_TVP5150, | 161 | .decoder = EM28XX_TVP5150, |
| 161 | .input = { { | 162 | .input = { { |
| 162 | .type = EM28XX_VMUX_TELEVISION, | 163 | .type = EM28XX_VMUX_TELEVISION, |
| @@ -524,6 +525,9 @@ void em28xx_pre_card_setup(struct em28xx *dev) | |||
| 524 | rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); | 525 | rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID); |
| 525 | if (rc > 0) { | 526 | if (rc > 0) { |
| 526 | switch (rc) { | 527 | switch (rc) { |
| 528 | case CHIP_ID_EM2860: | ||
| 529 | em28xx_info("chip ID is em2860\n"); | ||
| 530 | break; | ||
| 527 | case CHIP_ID_EM2883: | 531 | case CHIP_ID_EM2883: |
| 528 | em28xx_info("chip ID is em2882/em2883\n"); | 532 | em28xx_info("chip ID is em2882/em2883\n"); |
| 529 | dev->wait_after_write = 0; | 533 | dev->wait_after_write = 0; |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 8cf4983f0039..0b2333ee07f8 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
| @@ -382,6 +382,11 @@ static int dvb_init(struct em28xx *dev) | |||
| 382 | int result = 0; | 382 | int result = 0; |
| 383 | struct em28xx_dvb *dvb; | 383 | struct em28xx_dvb *dvb; |
| 384 | 384 | ||
| 385 | if (!dev->has_dvb) { | ||
| 386 | /* This device does not support the extension */ | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 385 | dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); | 390 | dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL); |
| 386 | 391 | ||
| 387 | if (dvb == NULL) { | 392 | if (dvb == NULL) { |
| @@ -444,6 +449,11 @@ out_free: | |||
| 444 | 449 | ||
| 445 | static int dvb_fini(struct em28xx *dev) | 450 | static int dvb_fini(struct em28xx *dev) |
| 446 | { | 451 | { |
| 452 | if (!dev->has_dvb) { | ||
| 453 | /* This device does not support the extension */ | ||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | |||
| 447 | if (dev->dvb) { | 457 | if (dev->dvb) { |
| 448 | unregister_dvb(dev->dvb); | 458 | unregister_dvb(dev->dvb); |
| 449 | dev->dvb = NULL; | 459 | dev->dvb = NULL; |
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 9058bed07953..fac1ab23f621 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h | |||
| @@ -84,5 +84,6 @@ | |||
| 84 | 84 | ||
| 85 | /* FIXME: Need to be populated with the other chip ID's */ | 85 | /* FIXME: Need to be populated with the other chip ID's */ |
| 86 | enum em28xx_chip_id { | 86 | enum em28xx_chip_id { |
| 87 | CHIP_ID_EM2860 = 34, | ||
| 87 | CHIP_ID_EM2883 = 36, | 88 | CHIP_ID_EM2883 = 36, |
| 88 | }; | 89 | }; |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index fb163ecd9216..285bc62bbe46 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
| @@ -1848,32 +1848,28 @@ static DEFINE_MUTEX(em28xx_extension_devlist_lock); | |||
| 1848 | 1848 | ||
| 1849 | int em28xx_register_extension(struct em28xx_ops *ops) | 1849 | int em28xx_register_extension(struct em28xx_ops *ops) |
| 1850 | { | 1850 | { |
| 1851 | struct em28xx *h, *dev = NULL; | 1851 | struct em28xx *dev = NULL; |
| 1852 | |||
| 1853 | list_for_each_entry(h, &em28xx_devlist, devlist) | ||
| 1854 | dev = h; | ||
| 1855 | 1852 | ||
| 1856 | mutex_lock(&em28xx_extension_devlist_lock); | 1853 | mutex_lock(&em28xx_extension_devlist_lock); |
| 1857 | list_add_tail(&ops->next, &em28xx_extension_devlist); | 1854 | list_add_tail(&ops->next, &em28xx_extension_devlist); |
| 1858 | if (dev) | 1855 | list_for_each_entry(dev, &em28xx_devlist, devlist) { |
| 1859 | ops->init(dev); | 1856 | if (dev) |
| 1860 | 1857 | ops->init(dev); | |
| 1858 | } | ||
| 1861 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); | 1859 | printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name); |
| 1862 | mutex_unlock(&em28xx_extension_devlist_lock); | 1860 | mutex_unlock(&em28xx_extension_devlist_lock); |
| 1863 | |||
| 1864 | return 0; | 1861 | return 0; |
| 1865 | } | 1862 | } |
| 1866 | EXPORT_SYMBOL(em28xx_register_extension); | 1863 | EXPORT_SYMBOL(em28xx_register_extension); |
| 1867 | 1864 | ||
| 1868 | void em28xx_unregister_extension(struct em28xx_ops *ops) | 1865 | void em28xx_unregister_extension(struct em28xx_ops *ops) |
| 1869 | { | 1866 | { |
| 1870 | struct em28xx *h, *dev = NULL; | 1867 | struct em28xx *dev = NULL; |
| 1871 | |||
| 1872 | list_for_each_entry(h, &em28xx_devlist, devlist) | ||
| 1873 | dev = h; | ||
| 1874 | 1868 | ||
| 1875 | if (dev) | 1869 | list_for_each_entry(dev, &em28xx_devlist, devlist) { |
| 1876 | ops->fini(dev); | 1870 | if (dev) |
| 1871 | ops->fini(dev); | ||
| 1872 | } | ||
| 1877 | 1873 | ||
| 1878 | mutex_lock(&em28xx_extension_devlist_lock); | 1874 | mutex_lock(&em28xx_extension_devlist_lock); |
| 1879 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); | 1875 | printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name); |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 7cc8e9b19fb7..5ec5bb9a94d2 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
| @@ -1019,12 +1019,12 @@ static int pxa_camera_probe(struct platform_device *pdev) | |||
| 1019 | struct pxa_camera_dev *pcdev; | 1019 | struct pxa_camera_dev *pcdev; |
| 1020 | struct resource *res; | 1020 | struct resource *res; |
| 1021 | void __iomem *base; | 1021 | void __iomem *base; |
| 1022 | unsigned int irq; | 1022 | int irq; |
| 1023 | int err = 0; | 1023 | int err = 0; |
| 1024 | 1024 | ||
| 1025 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1025 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1026 | irq = platform_get_irq(pdev, 0); | 1026 | irq = platform_get_irq(pdev, 0); |
| 1027 | if (!res || !irq) { | 1027 | if (!res || irq < 0) { |
| 1028 | err = -ENODEV; | 1028 | err = -ENODEV; |
| 1029 | goto exit; | 1029 | goto exit; |
| 1030 | } | 1030 | } |
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index ba3082422a01..f118de6e3672 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
| @@ -613,9 +613,15 @@ static int snd_card_saa7134_capture_open(struct snd_pcm_substream * substream) | |||
| 613 | struct snd_pcm_runtime *runtime = substream->runtime; | 613 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 614 | snd_card_saa7134_pcm_t *pcm; | 614 | snd_card_saa7134_pcm_t *pcm; |
| 615 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | 615 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); |
| 616 | struct saa7134_dev *dev = saa7134->dev; | 616 | struct saa7134_dev *dev; |
| 617 | int amux, err; | 617 | int amux, err; |
| 618 | 618 | ||
| 619 | if (!saa7134) { | ||
| 620 | printk(KERN_ERR "BUG: saa7134 can't find device struct." | ||
| 621 | " Can't proceed with open\n"); | ||
| 622 | return -ENODEV; | ||
| 623 | } | ||
| 624 | dev = saa7134->dev; | ||
| 619 | mutex_lock(&dev->dmasound.lock); | 625 | mutex_lock(&dev->dmasound.lock); |
| 620 | 626 | ||
| 621 | dev->dmasound.read_count = 0; | 627 | dev->dmasound.read_count = 0; |
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index b111903aa322..2618cfa592e7 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
| @@ -4114,11 +4114,7 @@ struct saa7134_board saa7134_boards[] = { | |||
| 4114 | .radio_type = UNSET, | 4114 | .radio_type = UNSET, |
| 4115 | .tuner_addr = ADDR_UNSET, | 4115 | .tuner_addr = ADDR_UNSET, |
| 4116 | .radio_addr = ADDR_UNSET, | 4116 | .radio_addr = ADDR_UNSET, |
| 4117 | /* | ||
| 4118 | TODO: | ||
| 4119 | .mpeg = SAA7134_MPEG_DVB, | 4117 | .mpeg = SAA7134_MPEG_DVB, |
| 4120 | */ | ||
| 4121 | |||
| 4122 | .inputs = {{ | 4118 | .inputs = {{ |
| 4123 | .name = name_tv, | 4119 | .name = name_tv, |
| 4124 | .vmux = 1, | 4120 | .vmux = 1, |
| @@ -4157,7 +4153,7 @@ struct saa7134_board saa7134_boards[] = { | |||
| 4157 | } }, | 4153 | } }, |
| 4158 | .radio = { | 4154 | .radio = { |
| 4159 | .name = name_radio, | 4155 | .name = name_radio, |
| 4160 | .amux = LINE1, | 4156 | .amux = TV, |
| 4161 | }, | 4157 | }, |
| 4162 | }, | 4158 | }, |
| 4163 | [SAA7134_BOARD_AVERMEDIA_M115] = { | 4159 | [SAA7134_BOARD_AVERMEDIA_M115] = { |
| @@ -4167,6 +4163,7 @@ struct saa7134_board saa7134_boards[] = { | |||
| 4167 | .radio_type = UNSET, | 4163 | .radio_type = UNSET, |
| 4168 | .tuner_addr = ADDR_UNSET, | 4164 | .tuner_addr = ADDR_UNSET, |
| 4169 | .radio_addr = ADDR_UNSET, | 4165 | .radio_addr = ADDR_UNSET, |
| 4166 | .mpeg = SAA7134_MPEG_DVB, | ||
| 4170 | .inputs = {{ | 4167 | .inputs = {{ |
| 4171 | .name = name_tv, | 4168 | .name = name_tv, |
| 4172 | .vmux = 1, | 4169 | .vmux = 1, |
| @@ -5351,22 +5348,21 @@ static int saa7134_xc2028_callback(struct saa7134_dev *dev, | |||
| 5351 | { | 5348 | { |
| 5352 | switch (command) { | 5349 | switch (command) { |
| 5353 | case XC2028_TUNER_RESET: | 5350 | case XC2028_TUNER_RESET: |
| 5354 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); | 5351 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00000000); |
| 5355 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); | 5352 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00008000, 0x00008000); |
| 5356 | mdelay(250); | 5353 | switch (dev->board) { |
| 5357 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0); | 5354 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: |
| 5358 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0); | 5355 | saa7134_set_gpio(dev, 23, 0); |
| 5359 | mdelay(250); | 5356 | msleep(10); |
| 5360 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); | 5357 | saa7134_set_gpio(dev, 23, 1); |
| 5361 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); | 5358 | break; |
| 5362 | mdelay(250); | 5359 | case SAA7134_BOARD_AVERMEDIA_A16D: |
| 5363 | saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02); | 5360 | saa7134_set_gpio(dev, 21, 0); |
| 5364 | saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81); | 5361 | msleep(10); |
| 5365 | saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7); | 5362 | saa7134_set_gpio(dev, 21, 1); |
| 5366 | saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03); | 5363 | break; |
| 5367 | saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2, | 5364 | } |
| 5368 | 0x0001e000, 0x0001e000); | 5365 | return 0; |
| 5369 | return 0; | ||
| 5370 | } | 5366 | } |
| 5371 | return -EINVAL; | 5367 | return -EINVAL; |
| 5372 | } | 5368 | } |
| @@ -5553,9 +5549,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 5553 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000); | 5549 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000); |
| 5554 | break; | 5550 | break; |
| 5555 | case SAA7134_BOARD_AVERMEDIA_CARDBUS: | 5551 | case SAA7134_BOARD_AVERMEDIA_CARDBUS: |
| 5556 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | ||
| 5557 | case SAA7134_BOARD_AVERMEDIA_M115: | 5552 | case SAA7134_BOARD_AVERMEDIA_M115: |
| 5558 | case SAA7134_BOARD_AVERMEDIA_A16D: | ||
| 5559 | /* power-down tuner chip */ | 5553 | /* power-down tuner chip */ |
| 5560 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0); | 5554 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0); |
| 5561 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0); | 5555 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0); |
| @@ -5565,6 +5559,18 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 5565 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); | 5559 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); |
| 5566 | msleep(10); | 5560 | msleep(10); |
| 5567 | break; | 5561 | break; |
| 5562 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | ||
| 5563 | saa7134_set_gpio(dev, 23, 0); | ||
| 5564 | msleep(10); | ||
| 5565 | saa7134_set_gpio(dev, 23, 1); | ||
| 5566 | break; | ||
| 5567 | case SAA7134_BOARD_AVERMEDIA_A16D: | ||
| 5568 | saa7134_set_gpio(dev, 21, 0); | ||
| 5569 | msleep(10); | ||
| 5570 | saa7134_set_gpio(dev, 21, 1); | ||
| 5571 | msleep(1); | ||
| 5572 | dev->has_remote = SAA7134_REMOTE_GPIO; | ||
| 5573 | break; | ||
| 5568 | case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: | 5574 | case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: |
| 5569 | /* power-down tuner chip */ | 5575 | /* power-down tuner chip */ |
| 5570 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); | 5576 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); |
| @@ -5615,7 +5621,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
| 5615 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); | 5621 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); |
| 5616 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); | 5622 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); |
| 5617 | printk("%s: %s: hybrid analog/dvb card\n" | 5623 | printk("%s: %s: hybrid analog/dvb card\n" |
| 5618 | "%s: Sorry, only the analog inputs are supported for now.\n", | 5624 | "%s: Sorry, only analog s-video and composite input " |
| 5625 | "are supported for now.\n", | ||
| 5619 | dev->name, card(dev).name, dev->name); | 5626 | dev->name, card(dev).name, dev->name); |
| 5620 | break; | 5627 | break; |
| 5621 | } | 5628 | } |
| @@ -5675,6 +5682,7 @@ static void saa7134_tuner_setup(struct saa7134_dev *dev) | |||
| 5675 | 5682 | ||
| 5676 | switch (dev->board) { | 5683 | switch (dev->board) { |
| 5677 | case SAA7134_BOARD_AVERMEDIA_A16D: | 5684 | case SAA7134_BOARD_AVERMEDIA_A16D: |
| 5685 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | ||
| 5678 | ctl.demod = XC3028_FE_ZARLINK456; | 5686 | ctl.demod = XC3028_FE_ZARLINK456; |
| 5679 | break; | 5687 | break; |
| 5680 | default: | 5688 | default: |
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 469f93aac008..341b101b0357 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
| @@ -153,12 +153,12 @@ static int mt352_aver777_init(struct dvb_frontend* fe) | |||
| 153 | return 0; | 153 | return 0; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | static int mt352_aver_a16d_init(struct dvb_frontend *fe) | 156 | static int mt352_avermedia_xc3028_init(struct dvb_frontend *fe) |
| 157 | { | 157 | { |
| 158 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; | 158 | static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x2d }; |
| 159 | static u8 reset [] = { RESET, 0x80 }; | 159 | static u8 reset [] = { RESET, 0x80 }; |
| 160 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; | 160 | static u8 adc_ctl_1_cfg [] = { ADC_CTL_1, 0x40 }; |
| 161 | static u8 agc_cfg [] = { AGC_TARGET, 0x28, 0xa0 }; | 161 | static u8 agc_cfg [] = { AGC_TARGET, 0xe }; |
| 162 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 }; | 162 | static u8 capt_range_cfg[] = { CAPT_RANGE, 0x33 }; |
| 163 | 163 | ||
| 164 | mt352_write(fe, clock_config, sizeof(clock_config)); | 164 | mt352_write(fe, clock_config, sizeof(clock_config)); |
| @@ -167,12 +167,9 @@ static int mt352_aver_a16d_init(struct dvb_frontend *fe) | |||
| 167 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); | 167 | mt352_write(fe, adc_ctl_1_cfg, sizeof(adc_ctl_1_cfg)); |
| 168 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); | 168 | mt352_write(fe, agc_cfg, sizeof(agc_cfg)); |
| 169 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); | 169 | mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg)); |
| 170 | |||
| 171 | return 0; | 170 | return 0; |
| 172 | } | 171 | } |
| 173 | 172 | ||
| 174 | |||
| 175 | |||
| 176 | static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, | 173 | static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, |
| 177 | struct dvb_frontend_parameters* params) | 174 | struct dvb_frontend_parameters* params) |
| 178 | { | 175 | { |
| @@ -215,14 +212,10 @@ static struct mt352_config avermedia_777 = { | |||
| 215 | .demod_init = mt352_aver777_init, | 212 | .demod_init = mt352_aver777_init, |
| 216 | }; | 213 | }; |
| 217 | 214 | ||
| 218 | static struct mt352_config avermedia_16d = { | 215 | static struct mt352_config avermedia_xc3028_mt352_dev = { |
| 219 | .demod_address = 0xf, | ||
| 220 | .demod_init = mt352_aver_a16d_init, | ||
| 221 | }; | ||
| 222 | |||
| 223 | static struct mt352_config avermedia_e506r_mt352_dev = { | ||
| 224 | .demod_address = (0x1e >> 1), | 216 | .demod_address = (0x1e >> 1), |
| 225 | .no_tuner = 1, | 217 | .no_tuner = 1, |
| 218 | .demod_init = mt352_avermedia_xc3028_init, | ||
| 226 | }; | 219 | }; |
| 227 | 220 | ||
| 228 | /* ================================================================== | 221 | /* ================================================================== |
| @@ -975,9 +968,10 @@ static int dvb_init(struct saa7134_dev *dev) | |||
| 975 | } | 968 | } |
| 976 | break; | 969 | break; |
| 977 | case SAA7134_BOARD_AVERMEDIA_A16D: | 970 | case SAA7134_BOARD_AVERMEDIA_A16D: |
| 978 | dprintk("avertv A16D dvb setup\n"); | 971 | dprintk("AverMedia A16D dvb setup\n"); |
| 979 | dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_16d, | 972 | dev->dvb.frontend = dvb_attach(mt352_attach, |
| 980 | &dev->i2c_adap); | 973 | &avermedia_xc3028_mt352_dev, |
| 974 | &dev->i2c_adap); | ||
| 981 | attach_xc3028 = 1; | 975 | attach_xc3028 = 1; |
| 982 | break; | 976 | break; |
| 983 | case SAA7134_BOARD_MD7134: | 977 | case SAA7134_BOARD_MD7134: |
| @@ -1091,7 +1085,8 @@ static int dvb_init(struct saa7134_dev *dev) | |||
| 1091 | ads_tech_duo_config.tuner_address); | 1085 | ads_tech_duo_config.tuner_address); |
| 1092 | goto dettach_frontend; | 1086 | goto dettach_frontend; |
| 1093 | } | 1087 | } |
| 1094 | } | 1088 | } else |
| 1089 | wprintk("failed to attach tda10046\n"); | ||
| 1095 | break; | 1090 | break; |
| 1096 | case SAA7134_BOARD_TEVION_DVBT_220RF: | 1091 | case SAA7134_BOARD_TEVION_DVBT_220RF: |
| 1097 | if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config, | 1092 | if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config, |
| @@ -1260,11 +1255,14 @@ static int dvb_init(struct saa7134_dev *dev) | |||
| 1260 | goto dettach_frontend; | 1255 | goto dettach_frontend; |
| 1261 | break; | 1256 | break; |
| 1262 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | 1257 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: |
| 1258 | dprintk("AverMedia E506R dvb setup\n"); | ||
| 1259 | saa7134_set_gpio(dev, 25, 0); | ||
| 1260 | msleep(10); | ||
| 1261 | saa7134_set_gpio(dev, 25, 1); | ||
| 1263 | dev->dvb.frontend = dvb_attach(mt352_attach, | 1262 | dev->dvb.frontend = dvb_attach(mt352_attach, |
| 1264 | &avermedia_e506r_mt352_dev, | 1263 | &avermedia_xc3028_mt352_dev, |
| 1265 | &dev->i2c_adap); | 1264 | &dev->i2c_adap); |
| 1266 | attach_xc3028 = 1; | 1265 | attach_xc3028 = 1; |
| 1267 | break; | ||
| 1268 | case SAA7134_BOARD_MD7134_BRIDGE_2: | 1266 | case SAA7134_BOARD_MD7134_BRIDGE_2: |
| 1269 | dev->dvb.frontend = dvb_attach(tda10086_attach, | 1267 | dev->dvb.frontend = dvb_attach(tda10086_attach, |
| 1270 | &sd1878_4m, &dev->i2c_adap); | 1268 | &sd1878_4m, &dev->i2c_adap); |
| @@ -1338,7 +1336,8 @@ static int dvb_init(struct saa7134_dev *dev) | |||
| 1338 | return ret; | 1336 | return ret; |
| 1339 | 1337 | ||
| 1340 | dettach_frontend: | 1338 | dettach_frontend: |
| 1341 | dvb_frontend_detach(dev->dvb.frontend); | 1339 | if (dev->dvb.frontend) |
| 1340 | dvb_frontend_detach(dev->dvb.frontend); | ||
| 1342 | dev->dvb.frontend = NULL; | 1341 | dev->dvb.frontend = NULL; |
| 1343 | 1342 | ||
| 1344 | return -1; | 1343 | return -1; |
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 81431ee41842..3ae71a340822 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c | |||
| @@ -110,9 +110,10 @@ static int ts_release(struct inode *inode, struct file *file) | |||
| 110 | { | 110 | { |
| 111 | struct saa7134_dev *dev = file->private_data; | 111 | struct saa7134_dev *dev = file->private_data; |
| 112 | 112 | ||
| 113 | mutex_lock(&dev->empress_tsq.vb_lock); | ||
| 114 | |||
| 113 | videobuf_stop(&dev->empress_tsq); | 115 | videobuf_stop(&dev->empress_tsq); |
| 114 | videobuf_mmap_free(&dev->empress_tsq); | 116 | videobuf_mmap_free(&dev->empress_tsq); |
| 115 | dev->empress_users--; | ||
| 116 | 117 | ||
| 117 | /* stop the encoder */ | 118 | /* stop the encoder */ |
| 118 | ts_reset_encoder(dev); | 119 | ts_reset_encoder(dev); |
| @@ -121,6 +122,10 @@ static int ts_release(struct inode *inode, struct file *file) | |||
| 121 | saa_writeb(SAA7134_AUDIO_MUTE_CTRL, | 122 | saa_writeb(SAA7134_AUDIO_MUTE_CTRL, |
| 122 | saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); | 123 | saa_readb(SAA7134_AUDIO_MUTE_CTRL) | (1 << 6)); |
| 123 | 124 | ||
| 125 | dev->empress_users--; | ||
| 126 | |||
| 127 | mutex_unlock(&dev->empress_tsq.vb_lock); | ||
| 128 | |||
| 124 | return 0; | 129 | return 0; |
| 125 | } | 130 | } |
| 126 | 131 | ||
| @@ -218,8 +223,7 @@ static int empress_enum_fmt_cap(struct file *file, void *priv, | |||
| 218 | static int empress_g_fmt_cap(struct file *file, void *priv, | 223 | static int empress_g_fmt_cap(struct file *file, void *priv, |
| 219 | struct v4l2_format *f) | 224 | struct v4l2_format *f) |
| 220 | { | 225 | { |
| 221 | struct saa7134_fh *fh = priv; | 226 | struct saa7134_dev *dev = file->private_data; |
| 222 | struct saa7134_dev *dev = fh->dev; | ||
| 223 | 227 | ||
| 224 | saa7134_i2c_call_clients(dev, VIDIOC_G_FMT, f); | 228 | saa7134_i2c_call_clients(dev, VIDIOC_G_FMT, f); |
| 225 | 229 | ||
| @@ -232,8 +236,7 @@ static int empress_g_fmt_cap(struct file *file, void *priv, | |||
| 232 | static int empress_s_fmt_cap(struct file *file, void *priv, | 236 | static int empress_s_fmt_cap(struct file *file, void *priv, |
| 233 | struct v4l2_format *f) | 237 | struct v4l2_format *f) |
| 234 | { | 238 | { |
| 235 | struct saa7134_fh *fh = priv; | 239 | struct saa7134_dev *dev = file->private_data; |
| 236 | struct saa7134_dev *dev = fh->dev; | ||
| 237 | 240 | ||
| 238 | saa7134_i2c_call_clients(dev, VIDIOC_S_FMT, f); | 241 | saa7134_i2c_call_clients(dev, VIDIOC_S_FMT, f); |
| 239 | 242 | ||
| @@ -247,8 +250,7 @@ static int empress_s_fmt_cap(struct file *file, void *priv, | |||
| 247 | static int empress_reqbufs(struct file *file, void *priv, | 250 | static int empress_reqbufs(struct file *file, void *priv, |
| 248 | struct v4l2_requestbuffers *p) | 251 | struct v4l2_requestbuffers *p) |
| 249 | { | 252 | { |
| 250 | struct saa7134_fh *fh = priv; | 253 | struct saa7134_dev *dev = file->private_data; |
| 251 | struct saa7134_dev *dev = fh->dev; | ||
| 252 | 254 | ||
| 253 | return videobuf_reqbufs(&dev->empress_tsq, p); | 255 | return videobuf_reqbufs(&dev->empress_tsq, p); |
| 254 | } | 256 | } |
| @@ -256,24 +258,21 @@ static int empress_reqbufs(struct file *file, void *priv, | |||
| 256 | static int empress_querybuf(struct file *file, void *priv, | 258 | static int empress_querybuf(struct file *file, void *priv, |
| 257 | struct v4l2_buffer *b) | 259 | struct v4l2_buffer *b) |
| 258 | { | 260 | { |
| 259 | struct saa7134_fh *fh = priv; | 261 | struct saa7134_dev *dev = file->private_data; |
| 260 | struct saa7134_dev *dev = fh->dev; | ||
| 261 | 262 | ||
| 262 | return videobuf_querybuf(&dev->empress_tsq, b); | 263 | return videobuf_querybuf(&dev->empress_tsq, b); |
| 263 | } | 264 | } |
| 264 | 265 | ||
| 265 | static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) | 266 | static int empress_qbuf(struct file *file, void *priv, struct v4l2_buffer *b) |
| 266 | { | 267 | { |
| 267 | struct saa7134_fh *fh = priv; | 268 | struct saa7134_dev *dev = file->private_data; |
| 268 | struct saa7134_dev *dev = fh->dev; | ||
| 269 | 269 | ||
| 270 | return videobuf_qbuf(&dev->empress_tsq, b); | 270 | return videobuf_qbuf(&dev->empress_tsq, b); |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | 273 | static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) |
| 274 | { | 274 | { |
| 275 | struct saa7134_fh *fh = priv; | 275 | struct saa7134_dev *dev = file->private_data; |
| 276 | struct saa7134_dev *dev = fh->dev; | ||
| 277 | 276 | ||
| 278 | return videobuf_dqbuf(&dev->empress_tsq, b, | 277 | return videobuf_dqbuf(&dev->empress_tsq, b, |
| 279 | file->f_flags & O_NONBLOCK); | 278 | file->f_flags & O_NONBLOCK); |
| @@ -282,8 +281,7 @@ static int empress_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b) | |||
| 282 | static int empress_streamon(struct file *file, void *priv, | 281 | static int empress_streamon(struct file *file, void *priv, |
| 283 | enum v4l2_buf_type type) | 282 | enum v4l2_buf_type type) |
| 284 | { | 283 | { |
| 285 | struct saa7134_fh *fh = priv; | 284 | struct saa7134_dev *dev = file->private_data; |
| 286 | struct saa7134_dev *dev = fh->dev; | ||
| 287 | 285 | ||
| 288 | return videobuf_streamon(&dev->empress_tsq); | 286 | return videobuf_streamon(&dev->empress_tsq); |
| 289 | } | 287 | } |
| @@ -291,8 +289,7 @@ static int empress_streamon(struct file *file, void *priv, | |||
| 291 | static int empress_streamoff(struct file *file, void *priv, | 289 | static int empress_streamoff(struct file *file, void *priv, |
| 292 | enum v4l2_buf_type type) | 290 | enum v4l2_buf_type type) |
| 293 | { | 291 | { |
| 294 | struct saa7134_fh *fh = priv; | 292 | struct saa7134_dev *dev = file->private_data; |
| 295 | struct saa7134_dev *dev = fh->dev; | ||
| 296 | 293 | ||
| 297 | return videobuf_streamoff(&dev->empress_tsq); | 294 | return videobuf_streamoff(&dev->empress_tsq); |
| 298 | } | 295 | } |
| @@ -300,8 +297,7 @@ static int empress_streamoff(struct file *file, void *priv, | |||
| 300 | static int empress_s_ext_ctrls(struct file *file, void *priv, | 297 | static int empress_s_ext_ctrls(struct file *file, void *priv, |
| 301 | struct v4l2_ext_controls *ctrls) | 298 | struct v4l2_ext_controls *ctrls) |
| 302 | { | 299 | { |
| 303 | struct saa7134_fh *fh = priv; | 300 | struct saa7134_dev *dev = file->private_data; |
| 304 | struct saa7134_dev *dev = fh->dev; | ||
| 305 | 301 | ||
| 306 | /* count == 0 is abused in saa6752hs.c, so that special | 302 | /* count == 0 is abused in saa6752hs.c, so that special |
| 307 | case is handled here explicitly. */ | 303 | case is handled here explicitly. */ |
| @@ -320,8 +316,7 @@ static int empress_s_ext_ctrls(struct file *file, void *priv, | |||
| 320 | static int empress_g_ext_ctrls(struct file *file, void *priv, | 316 | static int empress_g_ext_ctrls(struct file *file, void *priv, |
| 321 | struct v4l2_ext_controls *ctrls) | 317 | struct v4l2_ext_controls *ctrls) |
| 322 | { | 318 | { |
| 323 | struct saa7134_fh *fh = priv; | 319 | struct saa7134_dev *dev = file->private_data; |
| 324 | struct saa7134_dev *dev = fh->dev; | ||
| 325 | 320 | ||
| 326 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) | 321 | if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG) |
| 327 | return -EINVAL; | 322 | return -EINVAL; |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 919632b10aae..76e6501d238d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
| @@ -323,6 +323,15 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
| 323 | saa_setb(SAA7134_GPIO_GPMODE1, 0x1); | 323 | saa_setb(SAA7134_GPIO_GPMODE1, 0x1); |
| 324 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); | 324 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); |
| 325 | break; | 325 | break; |
| 326 | case SAA7134_BOARD_AVERMEDIA_A16D: | ||
| 327 | ir_codes = ir_codes_avermedia_a16d; | ||
| 328 | mask_keycode = 0x02F200; | ||
| 329 | mask_keydown = 0x000400; | ||
| 330 | polling = 50; /* ms */ | ||
| 331 | /* Without this we won't receive key up events */ | ||
| 332 | saa_setb(SAA7134_GPIO_GPMODE1, 0x1); | ||
| 333 | saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); | ||
| 334 | break; | ||
| 326 | case SAA7134_BOARD_KWORLD_TERMINATOR: | 335 | case SAA7134_BOARD_KWORLD_TERMINATOR: |
| 327 | ir_codes = ir_codes_pixelview; | 336 | ir_codes = ir_codes_pixelview; |
| 328 | mask_keycode = 0x00001f; | 337 | mask_keycode = 0x00001f; |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index a1b92446c8b4..d015bfe00950 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
| @@ -763,15 +763,6 @@ static struct device_driver ic_drv = { | |||
| 763 | .owner = THIS_MODULE, | 763 | .owner = THIS_MODULE, |
| 764 | }; | 764 | }; |
| 765 | 765 | ||
| 766 | /* | ||
| 767 | * Image capture host - this is a host device, not a bus device, so, | ||
| 768 | * no bus reference, no probing. | ||
| 769 | */ | ||
| 770 | static struct class soc_camera_host_class = { | ||
| 771 | .owner = THIS_MODULE, | ||
| 772 | .name = "camera_host", | ||
| 773 | }; | ||
| 774 | |||
| 775 | static void dummy_release(struct device *dev) | 766 | static void dummy_release(struct device *dev) |
| 776 | { | 767 | { |
| 777 | } | 768 | } |
| @@ -801,7 +792,6 @@ int soc_camera_host_register(struct soc_camera_host *ici) | |||
| 801 | 792 | ||
| 802 | /* Number might be equal to the platform device ID */ | 793 | /* Number might be equal to the platform device ID */ |
| 803 | sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); | 794 | sprintf(ici->dev.bus_id, "camera_host%d", ici->nr); |
| 804 | ici->dev.class = &soc_camera_host_class; | ||
| 805 | 795 | ||
| 806 | mutex_lock(&list_lock); | 796 | mutex_lock(&list_lock); |
| 807 | list_for_each_entry(ix, &hosts, list) { | 797 | list_for_each_entry(ix, &hosts, list) { |
| @@ -1003,14 +993,9 @@ static int __init soc_camera_init(void) | |||
| 1003 | ret = driver_register(&ic_drv); | 993 | ret = driver_register(&ic_drv); |
| 1004 | if (ret) | 994 | if (ret) |
| 1005 | goto edrvr; | 995 | goto edrvr; |
| 1006 | ret = class_register(&soc_camera_host_class); | ||
| 1007 | if (ret) | ||
| 1008 | goto eclr; | ||
| 1009 | 996 | ||
| 1010 | return 0; | 997 | return 0; |
| 1011 | 998 | ||
| 1012 | eclr: | ||
| 1013 | driver_unregister(&ic_drv); | ||
| 1014 | edrvr: | 999 | edrvr: |
| 1015 | bus_unregister(&soc_camera_bus_type); | 1000 | bus_unregister(&soc_camera_bus_type); |
| 1016 | return ret; | 1001 | return ret; |
| @@ -1018,7 +1003,6 @@ edrvr: | |||
| 1018 | 1003 | ||
| 1019 | static void __exit soc_camera_exit(void) | 1004 | static void __exit soc_camera_exit(void) |
| 1020 | { | 1005 | { |
| 1021 | class_unregister(&soc_camera_host_class); | ||
| 1022 | driver_unregister(&ic_drv); | 1006 | driver_unregister(&ic_drv); |
| 1023 | bus_unregister(&soc_camera_bus_type); | 1007 | bus_unregister(&soc_camera_bus_type); |
| 1024 | } | 1008 | } |
diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile new file mode 100644 index 000000000000..968c1994eda0 --- /dev/null +++ b/drivers/media/video/uvc/Makefile | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ | ||
| 2 | uvc_status.o uvc_isight.o | ||
| 3 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o | ||
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c new file mode 100644 index 000000000000..f0ee46d15540 --- /dev/null +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
| @@ -0,0 +1,1256 @@ | |||
| 1 | /* | ||
| 2 | * uvc_ctrl.c -- USB Video Class driver - Controls | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2008 | ||
| 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/version.h> | ||
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/uaccess.h> | ||
| 19 | #include <linux/usb.h> | ||
| 20 | #include <linux/videodev2.h> | ||
| 21 | #include <linux/vmalloc.h> | ||
| 22 | #include <linux/wait.h> | ||
| 23 | #include <asm/atomic.h> | ||
| 24 | |||
| 25 | #include "uvcvideo.h" | ||
| 26 | |||
| 27 | #define UVC_CTRL_NDATA 2 | ||
| 28 | #define UVC_CTRL_DATA_CURRENT 0 | ||
| 29 | #define UVC_CTRL_DATA_BACKUP 1 | ||
| 30 | |||
| 31 | /* ------------------------------------------------------------------------ | ||
| 32 | * Control, formats, ... | ||
| 33 | */ | ||
| 34 | |||
| 35 | static struct uvc_control_info uvc_ctrls[] = { | ||
| 36 | { | ||
| 37 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 38 | .selector = PU_BRIGHTNESS_CONTROL, | ||
| 39 | .index = 0, | ||
| 40 | .size = 2, | ||
| 41 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 42 | | UVC_CONTROL_RESTORE, | ||
| 43 | }, | ||
| 44 | { | ||
| 45 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 46 | .selector = PU_CONTRAST_CONTROL, | ||
| 47 | .index = 1, | ||
| 48 | .size = 2, | ||
| 49 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 50 | | UVC_CONTROL_RESTORE, | ||
| 51 | }, | ||
| 52 | { | ||
| 53 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 54 | .selector = PU_HUE_CONTROL, | ||
| 55 | .index = 2, | ||
| 56 | .size = 2, | ||
| 57 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 58 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 59 | }, | ||
| 60 | { | ||
| 61 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 62 | .selector = PU_SATURATION_CONTROL, | ||
| 63 | .index = 3, | ||
| 64 | .size = 2, | ||
| 65 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 66 | | UVC_CONTROL_RESTORE, | ||
| 67 | }, | ||
| 68 | { | ||
| 69 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 70 | .selector = PU_SHARPNESS_CONTROL, | ||
| 71 | .index = 4, | ||
| 72 | .size = 2, | ||
| 73 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 74 | | UVC_CONTROL_RESTORE, | ||
| 75 | }, | ||
| 76 | { | ||
| 77 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 78 | .selector = PU_GAMMA_CONTROL, | ||
| 79 | .index = 5, | ||
| 80 | .size = 2, | ||
| 81 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 82 | | UVC_CONTROL_RESTORE, | ||
| 83 | }, | ||
| 84 | { | ||
| 85 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 86 | .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, | ||
| 87 | .index = 8, | ||
| 88 | .size = 2, | ||
| 89 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 90 | | UVC_CONTROL_RESTORE, | ||
| 91 | }, | ||
| 92 | { | ||
| 93 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 94 | .selector = PU_GAIN_CONTROL, | ||
| 95 | .index = 9, | ||
| 96 | .size = 2, | ||
| 97 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 98 | | UVC_CONTROL_RESTORE, | ||
| 99 | }, | ||
| 100 | { | ||
| 101 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 102 | .selector = PU_POWER_LINE_FREQUENCY_CONTROL, | ||
| 103 | .index = 10, | ||
| 104 | .size = 1, | ||
| 105 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 106 | | UVC_CONTROL_RESTORE, | ||
| 107 | }, | ||
| 108 | { | ||
| 109 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 110 | .selector = PU_HUE_AUTO_CONTROL, | ||
| 111 | .index = 11, | ||
| 112 | .size = 1, | ||
| 113 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 114 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
| 115 | }, | ||
| 116 | { | ||
| 117 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 118 | .selector = CT_AE_MODE_CONTROL, | ||
| 119 | .index = 1, | ||
| 120 | .size = 1, | ||
| 121 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 122 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_GET_RES | ||
| 123 | | UVC_CONTROL_RESTORE, | ||
| 124 | }, | ||
| 125 | { | ||
| 126 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 127 | .selector = CT_AE_PRIORITY_CONTROL, | ||
| 128 | .index = 2, | ||
| 129 | .size = 1, | ||
| 130 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 131 | | UVC_CONTROL_RESTORE, | ||
| 132 | }, | ||
| 133 | { | ||
| 134 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 135 | .selector = CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, | ||
| 136 | .index = 3, | ||
| 137 | .size = 4, | ||
| 138 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 139 | | UVC_CONTROL_RESTORE, | ||
| 140 | }, | ||
| 141 | { | ||
| 142 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 143 | .selector = CT_FOCUS_ABSOLUTE_CONTROL, | ||
| 144 | .index = 5, | ||
| 145 | .size = 2, | ||
| 146 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 147 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 148 | }, | ||
| 149 | { | ||
| 150 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 151 | .selector = CT_FOCUS_AUTO_CONTROL, | ||
| 152 | .index = 17, | ||
| 153 | .size = 1, | ||
| 154 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 155 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
| 156 | }, | ||
| 157 | { | ||
| 158 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 159 | .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | ||
| 160 | .index = 12, | ||
| 161 | .size = 1, | ||
| 162 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 163 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
| 164 | }, | ||
| 165 | { | ||
| 166 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 167 | .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | ||
| 168 | .index = 6, | ||
| 169 | .size = 2, | ||
| 170 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 171 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 172 | }, | ||
| 173 | { | ||
| 174 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 175 | .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | ||
| 176 | .index = 13, | ||
| 177 | .size = 1, | ||
| 178 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR | ||
| 179 | | UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, | ||
| 180 | }, | ||
| 181 | { | ||
| 182 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 183 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | ||
| 184 | .index = 7, | ||
| 185 | .size = 4, | ||
| 186 | .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE | ||
| 187 | | UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, | ||
| 188 | }, | ||
| 189 | }; | ||
| 190 | |||
| 191 | static struct uvc_menu_info power_line_frequency_controls[] = { | ||
| 192 | { 0, "Disabled" }, | ||
| 193 | { 1, "50 Hz" }, | ||
| 194 | { 2, "60 Hz" }, | ||
| 195 | }; | ||
| 196 | |||
| 197 | static struct uvc_menu_info exposure_auto_controls[] = { | ||
| 198 | { 1, "Manual Mode" }, | ||
| 199 | { 2, "Auto Mode" }, | ||
| 200 | { 4, "Shutter Priority Mode" }, | ||
| 201 | { 8, "Aperture Priority Mode" }, | ||
| 202 | }; | ||
| 203 | |||
| 204 | static struct uvc_control_mapping uvc_ctrl_mappings[] = { | ||
| 205 | { | ||
| 206 | .id = V4L2_CID_BRIGHTNESS, | ||
| 207 | .name = "Brightness", | ||
| 208 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 209 | .selector = PU_BRIGHTNESS_CONTROL, | ||
| 210 | .size = 16, | ||
| 211 | .offset = 0, | ||
| 212 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 213 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
| 214 | }, | ||
| 215 | { | ||
| 216 | .id = V4L2_CID_CONTRAST, | ||
| 217 | .name = "Contrast", | ||
| 218 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 219 | .selector = PU_CONTRAST_CONTROL, | ||
| 220 | .size = 16, | ||
| 221 | .offset = 0, | ||
| 222 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 223 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 224 | }, | ||
| 225 | { | ||
| 226 | .id = V4L2_CID_HUE, | ||
| 227 | .name = "Hue", | ||
| 228 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 229 | .selector = PU_HUE_CONTROL, | ||
| 230 | .size = 16, | ||
| 231 | .offset = 0, | ||
| 232 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 233 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
| 234 | }, | ||
| 235 | { | ||
| 236 | .id = V4L2_CID_SATURATION, | ||
| 237 | .name = "Saturation", | ||
| 238 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 239 | .selector = PU_SATURATION_CONTROL, | ||
| 240 | .size = 16, | ||
| 241 | .offset = 0, | ||
| 242 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 243 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 244 | }, | ||
| 245 | { | ||
| 246 | .id = V4L2_CID_SHARPNESS, | ||
| 247 | .name = "Sharpness", | ||
| 248 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 249 | .selector = PU_SHARPNESS_CONTROL, | ||
| 250 | .size = 16, | ||
| 251 | .offset = 0, | ||
| 252 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 253 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 254 | }, | ||
| 255 | { | ||
| 256 | .id = V4L2_CID_GAMMA, | ||
| 257 | .name = "Gamma", | ||
| 258 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 259 | .selector = PU_GAMMA_CONTROL, | ||
| 260 | .size = 16, | ||
| 261 | .offset = 0, | ||
| 262 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 263 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 264 | }, | ||
| 265 | { | ||
| 266 | .id = V4L2_CID_BACKLIGHT_COMPENSATION, | ||
| 267 | .name = "Backlight Compensation", | ||
| 268 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 269 | .selector = PU_BACKLIGHT_COMPENSATION_CONTROL, | ||
| 270 | .size = 16, | ||
| 271 | .offset = 0, | ||
| 272 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 273 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 274 | }, | ||
| 275 | { | ||
| 276 | .id = V4L2_CID_GAIN, | ||
| 277 | .name = "Gain", | ||
| 278 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 279 | .selector = PU_GAIN_CONTROL, | ||
| 280 | .size = 16, | ||
| 281 | .offset = 0, | ||
| 282 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 283 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 284 | }, | ||
| 285 | { | ||
| 286 | .id = V4L2_CID_POWER_LINE_FREQUENCY, | ||
| 287 | .name = "Power Line Frequency", | ||
| 288 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 289 | .selector = PU_POWER_LINE_FREQUENCY_CONTROL, | ||
| 290 | .size = 2, | ||
| 291 | .offset = 0, | ||
| 292 | .v4l2_type = V4L2_CTRL_TYPE_MENU, | ||
| 293 | .data_type = UVC_CTRL_DATA_TYPE_ENUM, | ||
| 294 | .menu_info = power_line_frequency_controls, | ||
| 295 | .menu_count = ARRAY_SIZE(power_line_frequency_controls), | ||
| 296 | }, | ||
| 297 | { | ||
| 298 | .id = V4L2_CID_HUE_AUTO, | ||
| 299 | .name = "Hue, Auto", | ||
| 300 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 301 | .selector = PU_HUE_AUTO_CONTROL, | ||
| 302 | .size = 1, | ||
| 303 | .offset = 0, | ||
| 304 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 305 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
| 306 | }, | ||
| 307 | { | ||
| 308 | .id = V4L2_CID_EXPOSURE_AUTO, | ||
| 309 | .name = "Exposure, Auto", | ||
| 310 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 311 | .selector = CT_AE_MODE_CONTROL, | ||
| 312 | .size = 4, | ||
| 313 | .offset = 0, | ||
| 314 | .v4l2_type = V4L2_CTRL_TYPE_MENU, | ||
| 315 | .data_type = UVC_CTRL_DATA_TYPE_BITMASK, | ||
| 316 | .menu_info = exposure_auto_controls, | ||
| 317 | .menu_count = ARRAY_SIZE(exposure_auto_controls), | ||
| 318 | }, | ||
| 319 | { | ||
| 320 | .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY, | ||
| 321 | .name = "Exposure, Auto Priority", | ||
| 322 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 323 | .selector = CT_AE_PRIORITY_CONTROL, | ||
| 324 | .size = 1, | ||
| 325 | .offset = 0, | ||
| 326 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 327 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
| 328 | }, | ||
| 329 | { | ||
| 330 | .id = V4L2_CID_EXPOSURE_ABSOLUTE, | ||
| 331 | .name = "Exposure (Absolute)", | ||
| 332 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 333 | .selector = CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, | ||
| 334 | .size = 32, | ||
| 335 | .offset = 0, | ||
| 336 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 337 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 338 | }, | ||
| 339 | { | ||
| 340 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
| 341 | .name = "White Balance Temperature, Auto", | ||
| 342 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 343 | .selector = PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, | ||
| 344 | .size = 1, | ||
| 345 | .offset = 0, | ||
| 346 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 347 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
| 348 | }, | ||
| 349 | { | ||
| 350 | .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, | ||
| 351 | .name = "White Balance Temperature", | ||
| 352 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 353 | .selector = PU_WHITE_BALANCE_TEMPERATURE_CONTROL, | ||
| 354 | .size = 16, | ||
| 355 | .offset = 0, | ||
| 356 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 357 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 358 | }, | ||
| 359 | { | ||
| 360 | .id = V4L2_CID_AUTO_WHITE_BALANCE, | ||
| 361 | .name = "White Balance Component, Auto", | ||
| 362 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 363 | .selector = PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, | ||
| 364 | .size = 1, | ||
| 365 | .offset = 0, | ||
| 366 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 367 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
| 368 | }, | ||
| 369 | { | ||
| 370 | .id = V4L2_CID_BLUE_BALANCE, | ||
| 371 | .name = "White Balance Blue Component", | ||
| 372 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 373 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | ||
| 374 | .size = 16, | ||
| 375 | .offset = 0, | ||
| 376 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 377 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
| 378 | }, | ||
| 379 | { | ||
| 380 | .id = V4L2_CID_RED_BALANCE, | ||
| 381 | .name = "White Balance Red Component", | ||
| 382 | .entity = UVC_GUID_UVC_PROCESSING, | ||
| 383 | .selector = PU_WHITE_BALANCE_COMPONENT_CONTROL, | ||
| 384 | .size = 16, | ||
| 385 | .offset = 16, | ||
| 386 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 387 | .data_type = UVC_CTRL_DATA_TYPE_SIGNED, | ||
| 388 | }, | ||
| 389 | { | ||
| 390 | .id = V4L2_CID_FOCUS_ABSOLUTE, | ||
| 391 | .name = "Focus (absolute)", | ||
| 392 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 393 | .selector = CT_FOCUS_ABSOLUTE_CONTROL, | ||
| 394 | .size = 16, | ||
| 395 | .offset = 0, | ||
| 396 | .v4l2_type = V4L2_CTRL_TYPE_INTEGER, | ||
| 397 | .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, | ||
| 398 | }, | ||
| 399 | { | ||
| 400 | .id = V4L2_CID_FOCUS_AUTO, | ||
| 401 | .name = "Focus, Auto", | ||
| 402 | .entity = UVC_GUID_UVC_CAMERA, | ||
| 403 | .selector = CT_FOCUS_AUTO_CONTROL, | ||
| 404 | .size = 1, | ||
| 405 | .offset = 0, | ||
| 406 | .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, | ||
| 407 | .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, | ||
| 408 | }, | ||
| 409 | }; | ||
| 410 | |||
| 411 | /* ------------------------------------------------------------------------ | ||
| 412 | * Utility functions | ||
| 413 | */ | ||
| 414 | |||
| 415 | static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id) | ||
| 416 | { | ||
| 417 | return ctrl->data + id * ctrl->info->size; | ||
| 418 | } | ||
| 419 | |||
| 420 | static inline int uvc_get_bit(const __u8 *data, int bit) | ||
| 421 | { | ||
| 422 | return (data[bit >> 3] >> (bit & 7)) & 1; | ||
| 423 | } | ||
| 424 | |||
| 425 | /* Extract the bit string specified by mapping->offset and mapping->size | ||
| 426 | * from the little-endian data stored at 'data' and return the result as | ||
| 427 | * a signed 32bit integer. Sign extension will be performed if the mapping | ||
| 428 | * references a signed data type. | ||
| 429 | */ | ||
| 430 | static __s32 uvc_get_le_value(const __u8 *data, | ||
| 431 | struct uvc_control_mapping *mapping) | ||
| 432 | { | ||
| 433 | int bits = mapping->size; | ||
| 434 | int offset = mapping->offset; | ||
| 435 | __s32 value = 0; | ||
| 436 | __u8 mask; | ||
| 437 | |||
| 438 | data += offset / 8; | ||
| 439 | offset &= 7; | ||
| 440 | mask = ((1LL << bits) - 1) << offset; | ||
| 441 | |||
| 442 | for (; bits > 0; data++) { | ||
| 443 | __u8 byte = *data & mask; | ||
| 444 | value |= offset > 0 ? (byte >> offset) : (byte << (-offset)); | ||
| 445 | bits -= 8 - (offset > 0 ? offset : 0); | ||
| 446 | offset -= 8; | ||
| 447 | mask = (1 << bits) - 1; | ||
| 448 | } | ||
| 449 | |||
| 450 | /* Sign-extend the value if needed */ | ||
| 451 | if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED) | ||
| 452 | value |= -(value & (1 << (mapping->size - 1))); | ||
| 453 | |||
| 454 | return value; | ||
| 455 | } | ||
| 456 | |||
| 457 | /* Set the bit string specified by mapping->offset and mapping->size | ||
| 458 | * in the little-endian data stored at 'data' to the value 'value'. | ||
| 459 | */ | ||
| 460 | static void uvc_set_le_value(__s32 value, __u8 *data, | ||
| 461 | struct uvc_control_mapping *mapping) | ||
| 462 | { | ||
| 463 | int bits = mapping->size; | ||
| 464 | int offset = mapping->offset; | ||
| 465 | __u8 mask; | ||
| 466 | |||
| 467 | data += offset / 8; | ||
| 468 | offset &= 7; | ||
| 469 | |||
| 470 | for (; bits > 0; data++) { | ||
| 471 | mask = ((1LL << bits) - 1) << offset; | ||
| 472 | *data = (*data & ~mask) | ((value << offset) & mask); | ||
| 473 | value >>= offset ? offset : 8; | ||
| 474 | bits -= 8 - offset; | ||
| 475 | offset = 0; | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | /* ------------------------------------------------------------------------ | ||
| 480 | * Terminal and unit management | ||
| 481 | */ | ||
| 482 | |||
| 483 | static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING; | ||
| 484 | static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA; | ||
| 485 | static const __u8 uvc_media_transport_input_guid[16] = | ||
| 486 | UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT; | ||
| 487 | |||
| 488 | static int uvc_entity_match_guid(struct uvc_entity *entity, __u8 guid[16]) | ||
| 489 | { | ||
| 490 | switch (UVC_ENTITY_TYPE(entity)) { | ||
| 491 | case ITT_CAMERA: | ||
| 492 | return memcmp(uvc_camera_guid, guid, 16) == 0; | ||
| 493 | |||
| 494 | case ITT_MEDIA_TRANSPORT_INPUT: | ||
| 495 | return memcmp(uvc_media_transport_input_guid, guid, 16) == 0; | ||
| 496 | |||
| 497 | case VC_PROCESSING_UNIT: | ||
| 498 | return memcmp(uvc_processing_guid, guid, 16) == 0; | ||
| 499 | |||
| 500 | case VC_EXTENSION_UNIT: | ||
| 501 | return memcmp(entity->extension.guidExtensionCode, | ||
| 502 | guid, 16) == 0; | ||
| 503 | |||
| 504 | default: | ||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | } | ||
| 508 | |||
| 509 | /* ------------------------------------------------------------------------ | ||
| 510 | * UVC Controls | ||
| 511 | */ | ||
| 512 | |||
| 513 | static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id, | ||
| 514 | struct uvc_control_mapping **mapping, struct uvc_control **control, | ||
| 515 | int next) | ||
| 516 | { | ||
| 517 | struct uvc_control *ctrl; | ||
| 518 | struct uvc_control_mapping *map; | ||
| 519 | unsigned int i; | ||
| 520 | |||
| 521 | if (entity == NULL) | ||
| 522 | return; | ||
| 523 | |||
| 524 | for (i = 0; i < entity->ncontrols; ++i) { | ||
| 525 | ctrl = &entity->controls[i]; | ||
| 526 | if (ctrl->info == NULL) | ||
| 527 | continue; | ||
| 528 | |||
| 529 | list_for_each_entry(map, &ctrl->info->mappings, list) { | ||
| 530 | if ((map->id == v4l2_id) && !next) { | ||
| 531 | *control = ctrl; | ||
| 532 | *mapping = map; | ||
| 533 | return; | ||
| 534 | } | ||
| 535 | |||
| 536 | if ((*mapping == NULL || (*mapping)->id > map->id) && | ||
| 537 | (map->id > v4l2_id) && next) { | ||
| 538 | *control = ctrl; | ||
| 539 | *mapping = map; | ||
| 540 | } | ||
| 541 | } | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 545 | struct uvc_control *uvc_find_control(struct uvc_video_device *video, | ||
| 546 | __u32 v4l2_id, struct uvc_control_mapping **mapping) | ||
| 547 | { | ||
| 548 | struct uvc_control *ctrl = NULL; | ||
| 549 | struct uvc_entity *entity; | ||
| 550 | int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL; | ||
| 551 | |||
| 552 | *mapping = NULL; | ||
| 553 | |||
| 554 | /* Mask the query flags. */ | ||
| 555 | v4l2_id &= V4L2_CTRL_ID_MASK; | ||
| 556 | |||
| 557 | /* Find the control. */ | ||
| 558 | __uvc_find_control(video->processing, v4l2_id, mapping, &ctrl, next); | ||
| 559 | if (ctrl && !next) | ||
| 560 | return ctrl; | ||
| 561 | |||
| 562 | list_for_each_entry(entity, &video->iterms, chain) { | ||
| 563 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); | ||
| 564 | if (ctrl && !next) | ||
| 565 | return ctrl; | ||
| 566 | } | ||
| 567 | |||
| 568 | list_for_each_entry(entity, &video->extensions, chain) { | ||
| 569 | __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next); | ||
| 570 | if (ctrl && !next) | ||
| 571 | return ctrl; | ||
| 572 | } | ||
| 573 | |||
| 574 | if (ctrl == NULL && !next) | ||
| 575 | uvc_trace(UVC_TRACE_CONTROL, "Control 0x%08x not found.\n", | ||
| 576 | v4l2_id); | ||
| 577 | |||
| 578 | return ctrl; | ||
| 579 | } | ||
| 580 | |||
| 581 | int uvc_query_v4l2_ctrl(struct uvc_video_device *video, | ||
| 582 | struct v4l2_queryctrl *v4l2_ctrl) | ||
| 583 | { | ||
| 584 | struct uvc_control *ctrl; | ||
| 585 | struct uvc_control_mapping *mapping; | ||
| 586 | struct uvc_menu_info *menu; | ||
| 587 | unsigned int i; | ||
| 588 | __u8 data[8]; | ||
| 589 | int ret; | ||
| 590 | |||
| 591 | ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping); | ||
| 592 | if (ctrl == NULL) | ||
| 593 | return -EINVAL; | ||
| 594 | |||
| 595 | v4l2_ctrl->id = mapping->id; | ||
| 596 | v4l2_ctrl->type = mapping->v4l2_type; | ||
| 597 | strncpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name); | ||
| 598 | v4l2_ctrl->flags = 0; | ||
| 599 | |||
| 600 | if (!(ctrl->info->flags & UVC_CONTROL_SET_CUR)) | ||
| 601 | v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | ||
| 602 | |||
| 603 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | ||
| 604 | if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id, | ||
| 605 | video->dev->intfnum, ctrl->info->selector, | ||
| 606 | &data, ctrl->info->size)) < 0) | ||
| 607 | return ret; | ||
| 608 | v4l2_ctrl->default_value = uvc_get_le_value(data, mapping); | ||
| 609 | } | ||
| 610 | |||
| 611 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { | ||
| 612 | v4l2_ctrl->minimum = 0; | ||
| 613 | v4l2_ctrl->maximum = mapping->menu_count - 1; | ||
| 614 | v4l2_ctrl->step = 1; | ||
| 615 | |||
| 616 | menu = mapping->menu_info; | ||
| 617 | for (i = 0; i < mapping->menu_count; ++i, ++menu) { | ||
| 618 | if (menu->value == v4l2_ctrl->default_value) { | ||
| 619 | v4l2_ctrl->default_value = i; | ||
| 620 | break; | ||
| 621 | } | ||
| 622 | } | ||
| 623 | |||
| 624 | return 0; | ||
| 625 | } | ||
| 626 | |||
| 627 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { | ||
| 628 | if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id, | ||
| 629 | video->dev->intfnum, ctrl->info->selector, | ||
| 630 | &data, ctrl->info->size)) < 0) | ||
| 631 | return ret; | ||
| 632 | v4l2_ctrl->minimum = uvc_get_le_value(data, mapping); | ||
| 633 | } | ||
| 634 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { | ||
| 635 | if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id, | ||
| 636 | video->dev->intfnum, ctrl->info->selector, | ||
| 637 | &data, ctrl->info->size)) < 0) | ||
| 638 | return ret; | ||
| 639 | v4l2_ctrl->maximum = uvc_get_le_value(data, mapping); | ||
| 640 | } | ||
| 641 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) { | ||
| 642 | if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id, | ||
| 643 | video->dev->intfnum, ctrl->info->selector, | ||
| 644 | &data, ctrl->info->size)) < 0) | ||
| 645 | return ret; | ||
| 646 | v4l2_ctrl->step = uvc_get_le_value(data, mapping); | ||
| 647 | } | ||
| 648 | |||
| 649 | return 0; | ||
| 650 | } | ||
| 651 | |||
| 652 | |||
| 653 | /* -------------------------------------------------------------------------- | ||
| 654 | * Control transactions | ||
| 655 | * | ||
| 656 | * To make extended set operations as atomic as the hardware allows, controls | ||
| 657 | * are handled using begin/commit/rollback operations. | ||
| 658 | * | ||
| 659 | * At the beginning of a set request, uvc_ctrl_begin should be called to | ||
| 660 | * initialize the request. This function acquires the control lock. | ||
| 661 | * | ||
| 662 | * When setting a control, the new value is stored in the control data field | ||
| 663 | * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for | ||
| 664 | * later processing. If the UVC and V4L2 control sizes differ, the current | ||
| 665 | * value is loaded from the hardware before storing the new value in the data | ||
| 666 | * field. | ||
| 667 | * | ||
| 668 | * After processing all controls in the transaction, uvc_ctrl_commit or | ||
| 669 | * uvc_ctrl_rollback must be called to apply the pending changes to the | ||
| 670 | * hardware or revert them. When applying changes, all controls marked as | ||
| 671 | * dirty will be modified in the UVC device, and the dirty flag will be | ||
| 672 | * cleared. When reverting controls, the control data field | ||
| 673 | * UVC_CTRL_DATA_CURRENT is reverted to its previous value | ||
| 674 | * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the | ||
| 675 | * control lock. | ||
| 676 | */ | ||
| 677 | int uvc_ctrl_begin(struct uvc_video_device *video) | ||
| 678 | { | ||
| 679 | return mutex_lock_interruptible(&video->ctrl_mutex) ? -ERESTARTSYS : 0; | ||
| 680 | } | ||
| 681 | |||
| 682 | static int uvc_ctrl_commit_entity(struct uvc_device *dev, | ||
| 683 | struct uvc_entity *entity, int rollback) | ||
| 684 | { | ||
| 685 | struct uvc_control *ctrl; | ||
| 686 | unsigned int i; | ||
| 687 | int ret; | ||
| 688 | |||
| 689 | if (entity == NULL) | ||
| 690 | return 0; | ||
| 691 | |||
| 692 | for (i = 0; i < entity->ncontrols; ++i) { | ||
| 693 | ctrl = &entity->controls[i]; | ||
| 694 | if (ctrl->info == NULL || !ctrl->dirty) | ||
| 695 | continue; | ||
| 696 | |||
| 697 | if (!rollback) | ||
| 698 | ret = uvc_query_ctrl(dev, SET_CUR, ctrl->entity->id, | ||
| 699 | dev->intfnum, ctrl->info->selector, | ||
| 700 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 701 | ctrl->info->size); | ||
| 702 | else | ||
| 703 | ret = 0; | ||
| 704 | |||
| 705 | if (rollback || ret < 0) | ||
| 706 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 707 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
| 708 | ctrl->info->size); | ||
| 709 | |||
| 710 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) | ||
| 711 | ctrl->loaded = 0; | ||
| 712 | |||
| 713 | ctrl->dirty = 0; | ||
| 714 | |||
| 715 | if (ret < 0) | ||
| 716 | return ret; | ||
| 717 | } | ||
| 718 | |||
| 719 | return 0; | ||
| 720 | } | ||
| 721 | |||
| 722 | int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback) | ||
| 723 | { | ||
| 724 | struct uvc_entity *entity; | ||
| 725 | int ret = 0; | ||
| 726 | |||
| 727 | /* Find the control. */ | ||
| 728 | ret = uvc_ctrl_commit_entity(video->dev, video->processing, rollback); | ||
| 729 | if (ret < 0) | ||
| 730 | goto done; | ||
| 731 | |||
| 732 | list_for_each_entry(entity, &video->iterms, chain) { | ||
| 733 | ret = uvc_ctrl_commit_entity(video->dev, entity, rollback); | ||
| 734 | if (ret < 0) | ||
| 735 | goto done; | ||
| 736 | } | ||
| 737 | |||
| 738 | list_for_each_entry(entity, &video->extensions, chain) { | ||
| 739 | ret = uvc_ctrl_commit_entity(video->dev, entity, rollback); | ||
| 740 | if (ret < 0) | ||
| 741 | goto done; | ||
| 742 | } | ||
| 743 | |||
| 744 | done: | ||
| 745 | mutex_unlock(&video->ctrl_mutex); | ||
| 746 | return ret; | ||
| 747 | } | ||
| 748 | |||
| 749 | int uvc_ctrl_get(struct uvc_video_device *video, | ||
| 750 | struct v4l2_ext_control *xctrl) | ||
| 751 | { | ||
| 752 | struct uvc_control *ctrl; | ||
| 753 | struct uvc_control_mapping *mapping; | ||
| 754 | struct uvc_menu_info *menu; | ||
| 755 | unsigned int i; | ||
| 756 | int ret; | ||
| 757 | |||
| 758 | ctrl = uvc_find_control(video, xctrl->id, &mapping); | ||
| 759 | if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) | ||
| 760 | return -EINVAL; | ||
| 761 | |||
| 762 | if (!ctrl->loaded) { | ||
| 763 | ret = uvc_query_ctrl(video->dev, GET_CUR, ctrl->entity->id, | ||
| 764 | video->dev->intfnum, ctrl->info->selector, | ||
| 765 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 766 | ctrl->info->size); | ||
| 767 | if (ret < 0) | ||
| 768 | return ret; | ||
| 769 | |||
| 770 | if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) | ||
| 771 | ctrl->loaded = 1; | ||
| 772 | } | ||
| 773 | |||
| 774 | xctrl->value = uvc_get_le_value( | ||
| 775 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping); | ||
| 776 | |||
| 777 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { | ||
| 778 | menu = mapping->menu_info; | ||
| 779 | for (i = 0; i < mapping->menu_count; ++i, ++menu) { | ||
| 780 | if (menu->value == xctrl->value) { | ||
| 781 | xctrl->value = i; | ||
| 782 | break; | ||
| 783 | } | ||
| 784 | } | ||
| 785 | } | ||
| 786 | |||
| 787 | return 0; | ||
| 788 | } | ||
| 789 | |||
| 790 | int uvc_ctrl_set(struct uvc_video_device *video, | ||
| 791 | struct v4l2_ext_control *xctrl) | ||
| 792 | { | ||
| 793 | struct uvc_control *ctrl; | ||
| 794 | struct uvc_control_mapping *mapping; | ||
| 795 | s32 value = xctrl->value; | ||
| 796 | int ret; | ||
| 797 | |||
| 798 | ctrl = uvc_find_control(video, xctrl->id, &mapping); | ||
| 799 | if (ctrl == NULL || (ctrl->info->flags & UVC_CONTROL_SET_CUR) == 0) | ||
| 800 | return -EINVAL; | ||
| 801 | |||
| 802 | if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) { | ||
| 803 | if (value < 0 || value >= mapping->menu_count) | ||
| 804 | return -EINVAL; | ||
| 805 | value = mapping->menu_info[value].value; | ||
| 806 | } | ||
| 807 | |||
| 808 | if (!ctrl->loaded && (ctrl->info->size * 8) != mapping->size) { | ||
| 809 | if ((ctrl->info->flags & UVC_CONTROL_GET_CUR) == 0) { | ||
| 810 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 811 | 0, ctrl->info->size); | ||
| 812 | } else { | ||
| 813 | ret = uvc_query_ctrl(video->dev, GET_CUR, | ||
| 814 | ctrl->entity->id, video->dev->intfnum, | ||
| 815 | ctrl->info->selector, | ||
| 816 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 817 | ctrl->info->size); | ||
| 818 | if (ret < 0) | ||
| 819 | return ret; | ||
| 820 | } | ||
| 821 | |||
| 822 | if ((ctrl->info->flags & UVC_CONTROL_AUTO_UPDATE) == 0) | ||
| 823 | ctrl->loaded = 1; | ||
| 824 | } | ||
| 825 | |||
| 826 | if (!ctrl->dirty) { | ||
| 827 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
| 828 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 829 | ctrl->info->size); | ||
| 830 | } | ||
| 831 | |||
| 832 | uvc_set_le_value(value, | ||
| 833 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), mapping); | ||
| 834 | |||
| 835 | ctrl->dirty = 1; | ||
| 836 | ctrl->modified = 1; | ||
| 837 | return 0; | ||
| 838 | } | ||
| 839 | |||
| 840 | /* -------------------------------------------------------------------------- | ||
| 841 | * Dynamic controls | ||
| 842 | */ | ||
| 843 | |||
| 844 | int uvc_xu_ctrl_query(struct uvc_video_device *video, | ||
| 845 | struct uvc_xu_control *xctrl, int set) | ||
| 846 | { | ||
| 847 | struct uvc_entity *entity; | ||
| 848 | struct uvc_control *ctrl = NULL; | ||
| 849 | unsigned int i, found = 0; | ||
| 850 | __u8 *data; | ||
| 851 | int ret; | ||
| 852 | |||
| 853 | /* Find the extension unit. */ | ||
| 854 | list_for_each_entry(entity, &video->extensions, chain) { | ||
| 855 | if (entity->id == xctrl->unit) | ||
| 856 | break; | ||
| 857 | } | ||
| 858 | |||
| 859 | if (entity->id != xctrl->unit) { | ||
| 860 | uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n", | ||
| 861 | xctrl->unit); | ||
| 862 | return -EINVAL; | ||
| 863 | } | ||
| 864 | |||
| 865 | /* Find the control. */ | ||
| 866 | for (i = 0; i < entity->ncontrols; ++i) { | ||
| 867 | ctrl = &entity->controls[i]; | ||
| 868 | if (ctrl->info == NULL) | ||
| 869 | continue; | ||
| 870 | |||
| 871 | if (ctrl->info->selector == xctrl->selector) { | ||
| 872 | found = 1; | ||
| 873 | break; | ||
| 874 | } | ||
| 875 | } | ||
| 876 | |||
| 877 | if (!found) { | ||
| 878 | uvc_trace(UVC_TRACE_CONTROL, | ||
| 879 | "Control " UVC_GUID_FORMAT "/%u not found.\n", | ||
| 880 | UVC_GUID_ARGS(entity->extension.guidExtensionCode), | ||
| 881 | xctrl->selector); | ||
| 882 | return -EINVAL; | ||
| 883 | } | ||
| 884 | |||
| 885 | /* Validate control data size. */ | ||
| 886 | if (ctrl->info->size != xctrl->size) | ||
| 887 | return -EINVAL; | ||
| 888 | |||
| 889 | if ((set && !(ctrl->info->flags & UVC_CONTROL_SET_CUR)) || | ||
| 890 | (!set && !(ctrl->info->flags & UVC_CONTROL_GET_CUR))) | ||
| 891 | return -EINVAL; | ||
| 892 | |||
| 893 | if (mutex_lock_interruptible(&video->ctrl_mutex)) | ||
| 894 | return -ERESTARTSYS; | ||
| 895 | |||
| 896 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
| 897 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 898 | xctrl->size); | ||
| 899 | data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT); | ||
| 900 | |||
| 901 | if (set && copy_from_user(data, xctrl->data, xctrl->size)) { | ||
| 902 | ret = -EFAULT; | ||
| 903 | goto out; | ||
| 904 | } | ||
| 905 | |||
| 906 | ret = uvc_query_ctrl(video->dev, set ? SET_CUR : GET_CUR, xctrl->unit, | ||
| 907 | video->dev->intfnum, xctrl->selector, data, | ||
| 908 | xctrl->size); | ||
| 909 | if (ret < 0) | ||
| 910 | goto out; | ||
| 911 | |||
| 912 | if (!set && copy_to_user(xctrl->data, data, xctrl->size)) { | ||
| 913 | ret = -EFAULT; | ||
| 914 | goto out; | ||
| 915 | } | ||
| 916 | |||
| 917 | out: | ||
| 918 | if (ret) | ||
| 919 | memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT), | ||
| 920 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP), | ||
| 921 | xctrl->size); | ||
| 922 | |||
| 923 | mutex_unlock(&video->ctrl_mutex); | ||
| 924 | return ret; | ||
| 925 | } | ||
| 926 | |||
| 927 | /* -------------------------------------------------------------------------- | ||
| 928 | * Suspend/resume | ||
| 929 | */ | ||
| 930 | |||
| 931 | /* | ||
| 932 | * Restore control values after resume, skipping controls that haven't been | ||
| 933 | * changed. | ||
| 934 | * | ||
| 935 | * TODO | ||
| 936 | * - Don't restore modified controls that are back to their default value. | ||
| 937 | * - Handle restore order (Auto-Exposure Mode should be restored before | ||
| 938 | * Exposure Time). | ||
| 939 | */ | ||
| 940 | int uvc_ctrl_resume_device(struct uvc_device *dev) | ||
| 941 | { | ||
| 942 | struct uvc_control *ctrl; | ||
| 943 | struct uvc_entity *entity; | ||
| 944 | unsigned int i; | ||
| 945 | int ret; | ||
| 946 | |||
| 947 | /* Walk the entities list and restore controls when possible. */ | ||
| 948 | list_for_each_entry(entity, &dev->entities, list) { | ||
| 949 | |||
| 950 | for (i = 0; i < entity->ncontrols; ++i) { | ||
| 951 | ctrl = &entity->controls[i]; | ||
| 952 | |||
| 953 | if (ctrl->info == NULL || !ctrl->modified || | ||
| 954 | (ctrl->info->flags & UVC_CONTROL_RESTORE) == 0) | ||
| 955 | continue; | ||
| 956 | |||
| 957 | printk(KERN_INFO "restoring control " UVC_GUID_FORMAT | ||
| 958 | "/%u/%u\n", UVC_GUID_ARGS(ctrl->info->entity), | ||
| 959 | ctrl->info->index, ctrl->info->selector); | ||
| 960 | ctrl->dirty = 1; | ||
| 961 | } | ||
| 962 | |||
| 963 | ret = uvc_ctrl_commit_entity(dev, entity, 0); | ||
| 964 | if (ret < 0) | ||
| 965 | return ret; | ||
| 966 | } | ||
| 967 | |||
| 968 | return 0; | ||
| 969 | } | ||
| 970 | |||
| 971 | /* -------------------------------------------------------------------------- | ||
| 972 | * Control and mapping handling | ||
| 973 | */ | ||
| 974 | |||
| 975 | static void uvc_ctrl_add_ctrl(struct uvc_device *dev, | ||
| 976 | struct uvc_control_info *info) | ||
| 977 | { | ||
| 978 | struct uvc_entity *entity; | ||
| 979 | struct uvc_control *ctrl = NULL; | ||
| 980 | int ret, found = 0; | ||
| 981 | unsigned int i; | ||
| 982 | |||
| 983 | list_for_each_entry(entity, &dev->entities, list) { | ||
| 984 | if (!uvc_entity_match_guid(entity, info->entity)) | ||
| 985 | continue; | ||
| 986 | |||
| 987 | for (i = 0; i < entity->ncontrols; ++i) { | ||
| 988 | ctrl = &entity->controls[i]; | ||
| 989 | if (ctrl->index == info->index) { | ||
| 990 | found = 1; | ||
| 991 | break; | ||
| 992 | } | ||
| 993 | } | ||
| 994 | |||
| 995 | if (found) | ||
| 996 | break; | ||
| 997 | } | ||
| 998 | |||
| 999 | if (!found) | ||
| 1000 | return; | ||
| 1001 | |||
| 1002 | if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) { | ||
| 1003 | /* Check if the device control information and length match | ||
| 1004 | * the user supplied information. | ||
| 1005 | */ | ||
| 1006 | __u32 flags; | ||
| 1007 | __le16 size; | ||
| 1008 | __u8 inf; | ||
| 1009 | |||
| 1010 | if ((ret = uvc_query_ctrl(dev, GET_LEN, ctrl->entity->id, | ||
| 1011 | dev->intfnum, info->selector, (__u8 *)&size, 2)) < 0) { | ||
| 1012 | uvc_trace(UVC_TRACE_CONTROL, "GET_LEN failed on " | ||
| 1013 | "control " UVC_GUID_FORMAT "/%u (%d).\n", | ||
| 1014 | UVC_GUID_ARGS(info->entity), info->selector, | ||
| 1015 | ret); | ||
| 1016 | return; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | if (info->size != le16_to_cpu(size)) { | ||
| 1020 | uvc_trace(UVC_TRACE_CONTROL, "Control " UVC_GUID_FORMAT | ||
| 1021 | "/%u size doesn't match user supplied " | ||
| 1022 | "value.\n", UVC_GUID_ARGS(info->entity), | ||
| 1023 | info->selector); | ||
| 1024 | return; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | if ((ret = uvc_query_ctrl(dev, GET_INFO, ctrl->entity->id, | ||
| 1028 | dev->intfnum, info->selector, &inf, 1)) < 0) { | ||
| 1029 | uvc_trace(UVC_TRACE_CONTROL, "GET_INFO failed on " | ||
| 1030 | "control " UVC_GUID_FORMAT "/%u (%d).\n", | ||
| 1031 | UVC_GUID_ARGS(info->entity), info->selector, | ||
| 1032 | ret); | ||
| 1033 | return; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | flags = info->flags; | ||
| 1037 | if (((flags & UVC_CONTROL_GET_CUR) && !(inf & (1 << 0))) || | ||
| 1038 | ((flags & UVC_CONTROL_SET_CUR) && !(inf & (1 << 1)))) { | ||
| 1039 | uvc_trace(UVC_TRACE_CONTROL, "Control " | ||
| 1040 | UVC_GUID_FORMAT "/%u flags don't match " | ||
| 1041 | "supported operations.\n", | ||
| 1042 | UVC_GUID_ARGS(info->entity), info->selector); | ||
| 1043 | return; | ||
| 1044 | } | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | ctrl->info = info; | ||
| 1048 | ctrl->data = kmalloc(ctrl->info->size * UVC_CTRL_NDATA, GFP_KERNEL); | ||
| 1049 | uvc_trace(UVC_TRACE_CONTROL, "Added control " UVC_GUID_FORMAT "/%u " | ||
| 1050 | "to device %s entity %u\n", UVC_GUID_ARGS(ctrl->info->entity), | ||
| 1051 | ctrl->info->selector, dev->udev->devpath, entity->id); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | /* | ||
| 1055 | * Add an item to the UVC control information list, and instantiate a control | ||
| 1056 | * structure for each device that supports the control. | ||
| 1057 | */ | ||
| 1058 | int uvc_ctrl_add_info(struct uvc_control_info *info) | ||
| 1059 | { | ||
| 1060 | struct uvc_control_info *ctrl; | ||
| 1061 | struct uvc_device *dev; | ||
| 1062 | int ret = 0; | ||
| 1063 | |||
| 1064 | /* Find matching controls by walking the devices, entities and | ||
| 1065 | * controls list. | ||
| 1066 | */ | ||
| 1067 | mutex_lock(&uvc_driver.ctrl_mutex); | ||
| 1068 | |||
| 1069 | /* First check if the list contains a control matching the new one. | ||
| 1070 | * Bail out if it does. | ||
| 1071 | */ | ||
| 1072 | list_for_each_entry(ctrl, &uvc_driver.controls, list) { | ||
| 1073 | if (memcmp(ctrl->entity, info->entity, 16)) | ||
| 1074 | continue; | ||
| 1075 | |||
| 1076 | if (ctrl->selector == info->selector) { | ||
| 1077 | uvc_trace(UVC_TRACE_CONTROL, "Control " | ||
| 1078 | UVC_GUID_FORMAT "/%u is already defined.\n", | ||
| 1079 | UVC_GUID_ARGS(info->entity), info->selector); | ||
| 1080 | ret = -EEXIST; | ||
| 1081 | goto end; | ||
| 1082 | } | ||
| 1083 | if (ctrl->index == info->index) { | ||
| 1084 | uvc_trace(UVC_TRACE_CONTROL, "Control " | ||
| 1085 | UVC_GUID_FORMAT "/%u would overwrite index " | ||
| 1086 | "%d.\n", UVC_GUID_ARGS(info->entity), | ||
| 1087 | info->selector, info->index); | ||
| 1088 | ret = -EEXIST; | ||
| 1089 | goto end; | ||
| 1090 | } | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | list_for_each_entry(dev, &uvc_driver.devices, list) | ||
| 1094 | uvc_ctrl_add_ctrl(dev, info); | ||
| 1095 | |||
| 1096 | INIT_LIST_HEAD(&info->mappings); | ||
| 1097 | list_add_tail(&info->list, &uvc_driver.controls); | ||
| 1098 | end: | ||
| 1099 | mutex_unlock(&uvc_driver.ctrl_mutex); | ||
| 1100 | return ret; | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping) | ||
| 1104 | { | ||
| 1105 | struct uvc_control_info *info; | ||
| 1106 | struct uvc_control_mapping *map; | ||
| 1107 | int ret = -EINVAL; | ||
| 1108 | |||
| 1109 | if (mapping->id & ~V4L2_CTRL_ID_MASK) { | ||
| 1110 | uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s' with " | ||
| 1111 | "invalid control id 0x%08x\n", mapping->name, | ||
| 1112 | mapping->id); | ||
| 1113 | return -EINVAL; | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | mutex_lock(&uvc_driver.ctrl_mutex); | ||
| 1117 | list_for_each_entry(info, &uvc_driver.controls, list) { | ||
| 1118 | if (memcmp(info->entity, mapping->entity, 16) || | ||
| 1119 | info->selector != mapping->selector) | ||
| 1120 | continue; | ||
| 1121 | |||
| 1122 | if (info->size * 8 < mapping->size + mapping->offset) { | ||
| 1123 | uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' would " | ||
| 1124 | "overflow control " UVC_GUID_FORMAT "/%u\n", | ||
| 1125 | mapping->name, UVC_GUID_ARGS(info->entity), | ||
| 1126 | info->selector); | ||
| 1127 | ret = -EOVERFLOW; | ||
| 1128 | goto end; | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | /* Check if the list contains a mapping matching the new one. | ||
| 1132 | * Bail out if it does. | ||
| 1133 | */ | ||
| 1134 | list_for_each_entry(map, &info->mappings, list) { | ||
| 1135 | if (map->id == mapping->id) { | ||
| 1136 | uvc_trace(UVC_TRACE_CONTROL, "Mapping '%s' is " | ||
| 1137 | "already defined.\n", mapping->name); | ||
| 1138 | ret = -EEXIST; | ||
| 1139 | goto end; | ||
| 1140 | } | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | mapping->ctrl = info; | ||
| 1144 | list_add_tail(&mapping->list, &info->mappings); | ||
| 1145 | uvc_trace(UVC_TRACE_CONTROL, "Adding mapping %s to control " | ||
| 1146 | UVC_GUID_FORMAT "/%u.\n", mapping->name, | ||
| 1147 | UVC_GUID_ARGS(info->entity), info->selector); | ||
| 1148 | |||
| 1149 | ret = 0; | ||
| 1150 | break; | ||
| 1151 | } | ||
| 1152 | end: | ||
| 1153 | mutex_unlock(&uvc_driver.ctrl_mutex); | ||
| 1154 | return ret; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | /* | ||
| 1158 | * Initialize device controls. | ||
| 1159 | */ | ||
| 1160 | int uvc_ctrl_init_device(struct uvc_device *dev) | ||
| 1161 | { | ||
| 1162 | struct uvc_control_info *info; | ||
| 1163 | struct uvc_control *ctrl; | ||
| 1164 | struct uvc_entity *entity; | ||
| 1165 | unsigned int i; | ||
| 1166 | |||
| 1167 | /* Walk the entities list and instantiate controls */ | ||
| 1168 | list_for_each_entry(entity, &dev->entities, list) { | ||
| 1169 | unsigned int bControlSize = 0, ncontrols = 0; | ||
| 1170 | __u8 *bmControls = NULL; | ||
| 1171 | |||
| 1172 | if (UVC_ENTITY_TYPE(entity) == VC_EXTENSION_UNIT) { | ||
| 1173 | bmControls = entity->extension.bmControls; | ||
| 1174 | bControlSize = entity->extension.bControlSize; | ||
| 1175 | } else if (UVC_ENTITY_TYPE(entity) == VC_PROCESSING_UNIT) { | ||
| 1176 | bmControls = entity->processing.bmControls; | ||
| 1177 | bControlSize = entity->processing.bControlSize; | ||
| 1178 | } else if (UVC_ENTITY_TYPE(entity) == ITT_CAMERA) { | ||
| 1179 | bmControls = entity->camera.bmControls; | ||
| 1180 | bControlSize = entity->camera.bControlSize; | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | for (i = 0; i < bControlSize; ++i) | ||
| 1184 | ncontrols += hweight8(bmControls[i]); | ||
| 1185 | |||
| 1186 | if (ncontrols == 0) | ||
| 1187 | continue; | ||
| 1188 | |||
| 1189 | entity->controls = kzalloc(ncontrols*sizeof *ctrl, GFP_KERNEL); | ||
| 1190 | if (entity->controls == NULL) | ||
| 1191 | return -ENOMEM; | ||
| 1192 | |||
| 1193 | entity->ncontrols = ncontrols; | ||
| 1194 | |||
| 1195 | ctrl = entity->controls; | ||
| 1196 | for (i = 0; i < bControlSize * 8; ++i) { | ||
| 1197 | if (uvc_get_bit(bmControls, i) == 0) | ||
| 1198 | continue; | ||
| 1199 | |||
| 1200 | ctrl->entity = entity; | ||
| 1201 | ctrl->index = i; | ||
| 1202 | ctrl++; | ||
| 1203 | } | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | /* Walk the controls info list and associate them with the device | ||
| 1207 | * controls, then add the device to the global device list. This has | ||
| 1208 | * to be done while holding the controls lock, to make sure | ||
| 1209 | * uvc_ctrl_add_info() will not get called in-between. | ||
| 1210 | */ | ||
| 1211 | mutex_lock(&uvc_driver.ctrl_mutex); | ||
| 1212 | list_for_each_entry(info, &uvc_driver.controls, list) | ||
| 1213 | uvc_ctrl_add_ctrl(dev, info); | ||
| 1214 | |||
| 1215 | list_add_tail(&dev->list, &uvc_driver.devices); | ||
| 1216 | mutex_unlock(&uvc_driver.ctrl_mutex); | ||
| 1217 | |||
| 1218 | return 0; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | /* | ||
| 1222 | * Cleanup device controls. | ||
| 1223 | */ | ||
| 1224 | void uvc_ctrl_cleanup_device(struct uvc_device *dev) | ||
| 1225 | { | ||
| 1226 | struct uvc_entity *entity; | ||
| 1227 | unsigned int i; | ||
| 1228 | |||
| 1229 | /* Remove the device from the global devices list */ | ||
| 1230 | mutex_lock(&uvc_driver.ctrl_mutex); | ||
| 1231 | if (dev->list.next != NULL) | ||
| 1232 | list_del(&dev->list); | ||
| 1233 | mutex_unlock(&uvc_driver.ctrl_mutex); | ||
| 1234 | |||
| 1235 | list_for_each_entry(entity, &dev->entities, list) { | ||
| 1236 | for (i = 0; i < entity->ncontrols; ++i) | ||
| 1237 | kfree(entity->controls[i].data); | ||
| 1238 | |||
| 1239 | kfree(entity->controls); | ||
| 1240 | } | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | void uvc_ctrl_init(void) | ||
| 1244 | { | ||
| 1245 | struct uvc_control_info *ctrl = uvc_ctrls; | ||
| 1246 | struct uvc_control_info *cend = ctrl + ARRAY_SIZE(uvc_ctrls); | ||
| 1247 | struct uvc_control_mapping *mapping = uvc_ctrl_mappings; | ||
| 1248 | struct uvc_control_mapping *mend = | ||
| 1249 | mapping + ARRAY_SIZE(uvc_ctrl_mappings); | ||
| 1250 | |||
| 1251 | for (; ctrl < cend; ++ctrl) | ||
| 1252 | uvc_ctrl_add_info(ctrl); | ||
| 1253 | |||
| 1254 | for (; mapping < mend; ++mapping) | ||
| 1255 | uvc_ctrl_add_mapping(mapping); | ||
| 1256 | } | ||
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c new file mode 100644 index 000000000000..60ced589f898 --- /dev/null +++ b/drivers/media/video/uvc/uvc_driver.c | |||
| @@ -0,0 +1,1955 @@ | |||
| 1 | /* | ||
| 2 | * uvc_driver.c -- USB Video Class driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2008 | ||
| 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * This driver aims to support video input devices compliant with the 'USB | ||
| 16 | * Video Class' specification. | ||
| 17 | * | ||
| 18 | * The driver doesn't support the deprecated v4l1 interface. It implements the | ||
| 19 | * mmap capture method only, and doesn't do any image format conversion in | ||
| 20 | * software. If your user-space application doesn't support YUYV or MJPEG, fix | ||
| 21 | * it :-). Please note that the MJPEG data have been stripped from their | ||
| 22 | * Huffman tables (DHT marker), you will need to add it back if your JPEG | ||
| 23 | * codec can't handle MJPEG data. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include <linux/version.h> | ||
| 28 | #include <linux/list.h> | ||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/usb.h> | ||
| 31 | #include <linux/videodev2.h> | ||
| 32 | #include <linux/vmalloc.h> | ||
| 33 | #include <linux/wait.h> | ||
| 34 | #include <asm/atomic.h> | ||
| 35 | |||
| 36 | #include <media/v4l2-common.h> | ||
| 37 | |||
| 38 | #include "uvcvideo.h" | ||
| 39 | |||
| 40 | #define DRIVER_AUTHOR "Laurent Pinchart <laurent.pinchart@skynet.be>" | ||
| 41 | #define DRIVER_DESC "USB Video Class driver" | ||
| 42 | #ifndef DRIVER_VERSION | ||
| 43 | #define DRIVER_VERSION "v0.1.0" | ||
| 44 | #endif | ||
| 45 | |||
| 46 | static unsigned int uvc_quirks_param; | ||
| 47 | unsigned int uvc_trace_param; | ||
| 48 | |||
| 49 | /* ------------------------------------------------------------------------ | ||
| 50 | * Control, formats, ... | ||
| 51 | */ | ||
| 52 | |||
| 53 | static struct uvc_format_desc uvc_fmts[] = { | ||
| 54 | { | ||
| 55 | .name = "YUV 4:2:2 (YUYV)", | ||
| 56 | .guid = UVC_GUID_FORMAT_YUY2, | ||
| 57 | .fcc = V4L2_PIX_FMT_YUYV, | ||
| 58 | }, | ||
| 59 | { | ||
| 60 | .name = "YUV 4:2:0 (NV12)", | ||
| 61 | .guid = UVC_GUID_FORMAT_NV12, | ||
| 62 | .fcc = V4L2_PIX_FMT_NV12, | ||
| 63 | }, | ||
| 64 | { | ||
| 65 | .name = "MJPEG", | ||
| 66 | .guid = UVC_GUID_FORMAT_MJPEG, | ||
| 67 | .fcc = V4L2_PIX_FMT_MJPEG, | ||
| 68 | }, | ||
| 69 | { | ||
| 70 | .name = "YVU 4:2:0 (YV12)", | ||
| 71 | .guid = UVC_GUID_FORMAT_YV12, | ||
| 72 | .fcc = V4L2_PIX_FMT_YVU420, | ||
| 73 | }, | ||
| 74 | { | ||
| 75 | .name = "YUV 4:2:0 (I420)", | ||
| 76 | .guid = UVC_GUID_FORMAT_I420, | ||
| 77 | .fcc = V4L2_PIX_FMT_YUV420, | ||
| 78 | }, | ||
| 79 | { | ||
| 80 | .name = "YUV 4:2:2 (UYVY)", | ||
| 81 | .guid = UVC_GUID_FORMAT_UYVY, | ||
| 82 | .fcc = V4L2_PIX_FMT_UYVY, | ||
| 83 | }, | ||
| 84 | { | ||
| 85 | .name = "Greyscale", | ||
| 86 | .guid = UVC_GUID_FORMAT_Y800, | ||
| 87 | .fcc = V4L2_PIX_FMT_GREY, | ||
| 88 | }, | ||
| 89 | { | ||
| 90 | .name = "RGB Bayer", | ||
| 91 | .guid = UVC_GUID_FORMAT_BY8, | ||
| 92 | .fcc = V4L2_PIX_FMT_SBGGR8, | ||
| 93 | }, | ||
| 94 | }; | ||
| 95 | |||
| 96 | /* ------------------------------------------------------------------------ | ||
| 97 | * Utility functions | ||
| 98 | */ | ||
| 99 | |||
| 100 | struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts, | ||
| 101 | __u8 epaddr) | ||
| 102 | { | ||
| 103 | struct usb_host_endpoint *ep; | ||
| 104 | unsigned int i; | ||
| 105 | |||
| 106 | for (i = 0; i < alts->desc.bNumEndpoints; ++i) { | ||
| 107 | ep = &alts->endpoint[i]; | ||
| 108 | if (ep->desc.bEndpointAddress == epaddr) | ||
| 109 | return ep; | ||
| 110 | } | ||
| 111 | |||
| 112 | return NULL; | ||
| 113 | } | ||
| 114 | |||
| 115 | static struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16]) | ||
| 116 | { | ||
| 117 | unsigned int len = ARRAY_SIZE(uvc_fmts); | ||
| 118 | unsigned int i; | ||
| 119 | |||
| 120 | for (i = 0; i < len; ++i) { | ||
| 121 | if (memcmp(guid, uvc_fmts[i].guid, 16) == 0) | ||
| 122 | return &uvc_fmts[i]; | ||
| 123 | } | ||
| 124 | |||
| 125 | return NULL; | ||
| 126 | } | ||
| 127 | |||
| 128 | static __u32 uvc_colorspace(const __u8 primaries) | ||
| 129 | { | ||
| 130 | static const __u8 colorprimaries[] = { | ||
| 131 | 0, | ||
| 132 | V4L2_COLORSPACE_SRGB, | ||
| 133 | V4L2_COLORSPACE_470_SYSTEM_M, | ||
| 134 | V4L2_COLORSPACE_470_SYSTEM_BG, | ||
| 135 | V4L2_COLORSPACE_SMPTE170M, | ||
| 136 | V4L2_COLORSPACE_SMPTE240M, | ||
| 137 | }; | ||
| 138 | |||
| 139 | if (primaries < ARRAY_SIZE(colorprimaries)) | ||
| 140 | return colorprimaries[primaries]; | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* Simplify a fraction using a simple continued fraction decomposition. The | ||
| 146 | * idea here is to convert fractions such as 333333/10000000 to 1/30 using | ||
| 147 | * 32 bit arithmetic only. The algorithm is not perfect and relies upon two | ||
| 148 | * arbitrary parameters to remove non-significative terms from the simple | ||
| 149 | * continued fraction decomposition. Using 8 and 333 for n_terms and threshold | ||
| 150 | * respectively seems to give nice results. | ||
| 151 | */ | ||
| 152 | void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, | ||
| 153 | unsigned int n_terms, unsigned int threshold) | ||
| 154 | { | ||
| 155 | uint32_t *an; | ||
| 156 | uint32_t x, y, r; | ||
| 157 | unsigned int i, n; | ||
| 158 | |||
| 159 | an = kmalloc(n_terms * sizeof *an, GFP_KERNEL); | ||
| 160 | if (an == NULL) | ||
| 161 | return; | ||
| 162 | |||
| 163 | /* Convert the fraction to a simple continued fraction. See | ||
| 164 | * http://mathforum.org/dr.math/faq/faq.fractions.html | ||
| 165 | * Stop if the current term is bigger than or equal to the given | ||
| 166 | * threshold. | ||
| 167 | */ | ||
| 168 | x = *numerator; | ||
| 169 | y = *denominator; | ||
| 170 | |||
| 171 | for (n = 0; n < n_terms && y != 0; ++n) { | ||
| 172 | an[n] = x / y; | ||
| 173 | if (an[n] >= threshold) { | ||
| 174 | if (n < 2) | ||
| 175 | n++; | ||
| 176 | break; | ||
| 177 | } | ||
| 178 | |||
| 179 | r = x - an[n] * y; | ||
| 180 | x = y; | ||
| 181 | y = r; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* Expand the simple continued fraction back to an integer fraction. */ | ||
| 185 | x = 0; | ||
| 186 | y = 1; | ||
| 187 | |||
| 188 | for (i = n; i > 0; --i) { | ||
| 189 | r = y; | ||
| 190 | y = an[i-1] * y + x; | ||
| 191 | x = r; | ||
| 192 | } | ||
| 193 | |||
| 194 | *numerator = y; | ||
| 195 | *denominator = x; | ||
| 196 | kfree(an); | ||
| 197 | } | ||
| 198 | |||
| 199 | /* Convert a fraction to a frame interval in 100ns multiples. The idea here is | ||
| 200 | * to compute numerator / denominator * 10000000 using 32 bit fixed point | ||
| 201 | * arithmetic only. | ||
| 202 | */ | ||
| 203 | uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator) | ||
| 204 | { | ||
| 205 | uint32_t multiplier; | ||
| 206 | |||
| 207 | /* Saturate the result if the operation would overflow. */ | ||
| 208 | if (denominator == 0 || | ||
| 209 | numerator/denominator >= ((uint32_t)-1)/10000000) | ||
| 210 | return (uint32_t)-1; | ||
| 211 | |||
| 212 | /* Divide both the denominator and the multiplier by two until | ||
| 213 | * numerator * multiplier doesn't overflow. If anyone knows a better | ||
| 214 | * algorithm please let me know. | ||
| 215 | */ | ||
| 216 | multiplier = 10000000; | ||
| 217 | while (numerator > ((uint32_t)-1)/multiplier) { | ||
| 218 | multiplier /= 2; | ||
| 219 | denominator /= 2; | ||
| 220 | } | ||
| 221 | |||
| 222 | return denominator ? numerator * multiplier / denominator : 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | /* ------------------------------------------------------------------------ | ||
| 226 | * Terminal and unit management | ||
| 227 | */ | ||
| 228 | |||
| 229 | static struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id) | ||
| 230 | { | ||
| 231 | struct uvc_entity *entity; | ||
| 232 | |||
| 233 | list_for_each_entry(entity, &dev->entities, list) { | ||
| 234 | if (entity->id == id) | ||
| 235 | return entity; | ||
| 236 | } | ||
| 237 | |||
| 238 | return NULL; | ||
| 239 | } | ||
| 240 | |||
| 241 | static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, | ||
| 242 | int id, struct uvc_entity *entity) | ||
| 243 | { | ||
| 244 | unsigned int i; | ||
| 245 | |||
| 246 | if (entity == NULL) | ||
| 247 | entity = list_entry(&dev->entities, struct uvc_entity, list); | ||
| 248 | |||
| 249 | list_for_each_entry_continue(entity, &dev->entities, list) { | ||
| 250 | switch (UVC_ENTITY_TYPE(entity)) { | ||
| 251 | case TT_STREAMING: | ||
| 252 | if (entity->output.bSourceID == id) | ||
| 253 | return entity; | ||
| 254 | break; | ||
| 255 | |||
| 256 | case VC_PROCESSING_UNIT: | ||
| 257 | if (entity->processing.bSourceID == id) | ||
| 258 | return entity; | ||
| 259 | break; | ||
| 260 | |||
| 261 | case VC_SELECTOR_UNIT: | ||
| 262 | for (i = 0; i < entity->selector.bNrInPins; ++i) | ||
| 263 | if (entity->selector.baSourceID[i] == id) | ||
| 264 | return entity; | ||
| 265 | break; | ||
| 266 | |||
| 267 | case VC_EXTENSION_UNIT: | ||
| 268 | for (i = 0; i < entity->extension.bNrInPins; ++i) | ||
| 269 | if (entity->extension.baSourceID[i] == id) | ||
| 270 | return entity; | ||
| 271 | break; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | return NULL; | ||
| 276 | } | ||
| 277 | |||
| 278 | /* ------------------------------------------------------------------------ | ||
| 279 | * Descriptors handling | ||
| 280 | */ | ||
| 281 | |||
| 282 | static int uvc_parse_format(struct uvc_device *dev, | ||
| 283 | struct uvc_streaming *streaming, struct uvc_format *format, | ||
| 284 | __u32 **intervals, unsigned char *buffer, int buflen) | ||
| 285 | { | ||
| 286 | struct usb_interface *intf = streaming->intf; | ||
| 287 | struct usb_host_interface *alts = intf->cur_altsetting; | ||
| 288 | struct uvc_format_desc *fmtdesc; | ||
| 289 | struct uvc_frame *frame; | ||
| 290 | const unsigned char *start = buffer; | ||
| 291 | unsigned int interval; | ||
| 292 | unsigned int i, n; | ||
| 293 | __u8 ftype; | ||
| 294 | |||
| 295 | format->type = buffer[2]; | ||
| 296 | format->index = buffer[3]; | ||
| 297 | |||
| 298 | switch (buffer[2]) { | ||
| 299 | case VS_FORMAT_UNCOMPRESSED: | ||
| 300 | case VS_FORMAT_FRAME_BASED: | ||
| 301 | if (buflen < 27) { | ||
| 302 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
| 303 | "interface %d FORMAT error\n", | ||
| 304 | dev->udev->devnum, | ||
| 305 | alts->desc.bInterfaceNumber); | ||
| 306 | return -EINVAL; | ||
| 307 | } | ||
| 308 | |||
| 309 | /* Find the format descriptor from its GUID. */ | ||
| 310 | fmtdesc = uvc_format_by_guid(&buffer[5]); | ||
| 311 | |||
| 312 | if (fmtdesc != NULL) { | ||
| 313 | strncpy(format->name, fmtdesc->name, | ||
| 314 | sizeof format->name); | ||
| 315 | format->fcc = fmtdesc->fcc; | ||
| 316 | } else { | ||
| 317 | uvc_printk(KERN_INFO, "Unknown video format " | ||
| 318 | UVC_GUID_FORMAT "\n", | ||
| 319 | UVC_GUID_ARGS(&buffer[5])); | ||
| 320 | snprintf(format->name, sizeof format->name, | ||
| 321 | UVC_GUID_FORMAT, UVC_GUID_ARGS(&buffer[5])); | ||
| 322 | format->fcc = 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | format->bpp = buffer[21]; | ||
| 326 | if (buffer[2] == VS_FORMAT_UNCOMPRESSED) { | ||
| 327 | ftype = VS_FRAME_UNCOMPRESSED; | ||
| 328 | } else { | ||
| 329 | ftype = VS_FRAME_FRAME_BASED; | ||
| 330 | if (buffer[27]) | ||
| 331 | format->flags = UVC_FMT_FLAG_COMPRESSED; | ||
| 332 | } | ||
| 333 | break; | ||
| 334 | |||
| 335 | case VS_FORMAT_MJPEG: | ||
| 336 | if (buflen < 11) { | ||
| 337 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
| 338 | "interface %d FORMAT error\n", | ||
| 339 | dev->udev->devnum, | ||
| 340 | alts->desc.bInterfaceNumber); | ||
| 341 | return -EINVAL; | ||
| 342 | } | ||
| 343 | |||
| 344 | strncpy(format->name, "MJPEG", sizeof format->name); | ||
| 345 | format->fcc = V4L2_PIX_FMT_MJPEG; | ||
| 346 | format->flags = UVC_FMT_FLAG_COMPRESSED; | ||
| 347 | format->bpp = 0; | ||
| 348 | ftype = VS_FRAME_MJPEG; | ||
| 349 | break; | ||
| 350 | |||
| 351 | case VS_FORMAT_DV: | ||
| 352 | if (buflen < 9) { | ||
| 353 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
| 354 | "interface %d FORMAT error\n", | ||
| 355 | dev->udev->devnum, | ||
| 356 | alts->desc.bInterfaceNumber); | ||
| 357 | return -EINVAL; | ||
| 358 | } | ||
| 359 | |||
| 360 | switch (buffer[8] & 0x7f) { | ||
| 361 | case 0: | ||
| 362 | strncpy(format->name, "SD-DV", sizeof format->name); | ||
| 363 | break; | ||
| 364 | case 1: | ||
| 365 | strncpy(format->name, "SDL-DV", sizeof format->name); | ||
| 366 | break; | ||
| 367 | case 2: | ||
| 368 | strncpy(format->name, "HD-DV", sizeof format->name); | ||
| 369 | break; | ||
| 370 | default: | ||
| 371 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
| 372 | "interface %d: unknown DV format %u\n", | ||
| 373 | dev->udev->devnum, | ||
| 374 | alts->desc.bInterfaceNumber, buffer[8]); | ||
| 375 | return -EINVAL; | ||
| 376 | } | ||
| 377 | |||
| 378 | strncat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz", | ||
| 379 | sizeof format->name); | ||
| 380 | |||
| 381 | format->fcc = V4L2_PIX_FMT_DV; | ||
| 382 | format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM; | ||
| 383 | format->bpp = 0; | ||
| 384 | ftype = 0; | ||
| 385 | |||
| 386 | /* Create a dummy frame descriptor. */ | ||
| 387 | frame = &format->frame[0]; | ||
| 388 | memset(&format->frame[0], 0, sizeof format->frame[0]); | ||
| 389 | frame->bFrameIntervalType = 1; | ||
| 390 | frame->dwDefaultFrameInterval = 1; | ||
| 391 | frame->dwFrameInterval = *intervals; | ||
| 392 | *(*intervals)++ = 1; | ||
| 393 | format->nframes = 1; | ||
| 394 | break; | ||
| 395 | |||
| 396 | case VS_FORMAT_MPEG2TS: | ||
| 397 | case VS_FORMAT_STREAM_BASED: | ||
| 398 | /* Not supported yet. */ | ||
| 399 | default: | ||
| 400 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
| 401 | "interface %d unsupported format %u\n", | ||
| 402 | dev->udev->devnum, alts->desc.bInterfaceNumber, | ||
| 403 | buffer[2]); | ||
| 404 | return -EINVAL; | ||
| 405 | } | ||
| 406 | |||
| 407 | uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name); | ||
| 408 | |||
| 409 | buflen -= buffer[0]; | ||
| 410 | buffer += buffer[0]; | ||
| 411 | |||
| 412 | /* Parse the frame descriptors. Only uncompressed, MJPEG and frame | ||
| 413 | * based formats have frame descriptors. | ||
| 414 | */ | ||
| 415 | while (buflen > 2 && buffer[2] == ftype) { | ||
| 416 | frame = &format->frame[format->nframes]; | ||
| 417 | |||
| 418 | if (ftype != VS_FRAME_FRAME_BASED) | ||
| 419 | n = buflen > 25 ? buffer[25] : 0; | ||
| 420 | else | ||
| 421 | n = buflen > 21 ? buffer[21] : 0; | ||
| 422 | |||
| 423 | n = n ? n : 3; | ||
| 424 | |||
| 425 | if (buflen < 26 + 4*n) { | ||
| 426 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
| 427 | "interface %d FRAME error\n", dev->udev->devnum, | ||
| 428 | alts->desc.bInterfaceNumber); | ||
| 429 | return -EINVAL; | ||
| 430 | } | ||
| 431 | |||
| 432 | frame->bFrameIndex = buffer[3]; | ||
| 433 | frame->bmCapabilities = buffer[4]; | ||
| 434 | frame->wWidth = le16_to_cpup((__le16 *)&buffer[5]); | ||
| 435 | frame->wHeight = le16_to_cpup((__le16 *)&buffer[7]); | ||
| 436 | frame->dwMinBitRate = le32_to_cpup((__le32 *)&buffer[9]); | ||
| 437 | frame->dwMaxBitRate = le32_to_cpup((__le32 *)&buffer[13]); | ||
| 438 | if (ftype != VS_FRAME_FRAME_BASED) { | ||
| 439 | frame->dwMaxVideoFrameBufferSize = | ||
| 440 | le32_to_cpup((__le32 *)&buffer[17]); | ||
| 441 | frame->dwDefaultFrameInterval = | ||
| 442 | le32_to_cpup((__le32 *)&buffer[21]); | ||
| 443 | frame->bFrameIntervalType = buffer[25]; | ||
| 444 | } else { | ||
| 445 | frame->dwMaxVideoFrameBufferSize = 0; | ||
| 446 | frame->dwDefaultFrameInterval = | ||
| 447 | le32_to_cpup((__le32 *)&buffer[17]); | ||
| 448 | frame->bFrameIntervalType = buffer[21]; | ||
| 449 | } | ||
| 450 | frame->dwFrameInterval = *intervals; | ||
| 451 | |||
| 452 | /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize | ||
| 453 | * completely. Observed behaviours range from setting the | ||
| 454 | * value to 1.1x the actual frame size of hardwiring the | ||
| 455 | * 16 low bits to 0. This results in a higher than necessary | ||
| 456 | * memory usage as well as a wrong image size information. For | ||
| 457 | * uncompressed formats this can be fixed by computing the | ||
| 458 | * value from the frame size. | ||
| 459 | */ | ||
| 460 | if (!(format->flags & UVC_FMT_FLAG_COMPRESSED)) | ||
| 461 | frame->dwMaxVideoFrameBufferSize = format->bpp | ||
| 462 | * frame->wWidth * frame->wHeight / 8; | ||
| 463 | |||
| 464 | /* Some bogus devices report dwMinFrameInterval equal to | ||
| 465 | * dwMaxFrameInterval and have dwFrameIntervalStep set to | ||
| 466 | * zero. Setting all null intervals to 1 fixes the problem and | ||
| 467 | * some other divisions by zero which could happen. | ||
| 468 | */ | ||
| 469 | for (i = 0; i < n; ++i) { | ||
| 470 | interval = le32_to_cpup((__le32 *)&buffer[26+4*i]); | ||
| 471 | *(*intervals)++ = interval ? interval : 1; | ||
| 472 | } | ||
| 473 | |||
| 474 | /* Make sure that the default frame interval stays between | ||
| 475 | * the boundaries. | ||
| 476 | */ | ||
| 477 | n -= frame->bFrameIntervalType ? 1 : 2; | ||
| 478 | frame->dwDefaultFrameInterval = | ||
| 479 | min(frame->dwFrameInterval[n], | ||
| 480 | max(frame->dwFrameInterval[0], | ||
| 481 | frame->dwDefaultFrameInterval)); | ||
| 482 | |||
| 483 | uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n", | ||
| 484 | frame->wWidth, frame->wHeight, | ||
| 485 | 10000000/frame->dwDefaultFrameInterval, | ||
| 486 | (100000000/frame->dwDefaultFrameInterval)%10); | ||
| 487 | |||
| 488 | format->nframes++; | ||
| 489 | buflen -= buffer[0]; | ||
| 490 | buffer += buffer[0]; | ||
| 491 | } | ||
| 492 | |||
| 493 | if (buflen > 2 && buffer[2] == VS_STILL_IMAGE_FRAME) { | ||
| 494 | buflen -= buffer[0]; | ||
| 495 | buffer += buffer[0]; | ||
| 496 | } | ||
| 497 | |||
| 498 | if (buflen > 2 && buffer[2] == VS_COLORFORMAT) { | ||
| 499 | if (buflen < 6) { | ||
| 500 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming" | ||
| 501 | "interface %d COLORFORMAT error\n", | ||
| 502 | dev->udev->devnum, | ||
| 503 | alts->desc.bInterfaceNumber); | ||
| 504 | return -EINVAL; | ||
| 505 | } | ||
| 506 | |||
| 507 | format->colorspace = uvc_colorspace(buffer[3]); | ||
| 508 | |||
| 509 | buflen -= buffer[0]; | ||
| 510 | buffer += buffer[0]; | ||
| 511 | } | ||
| 512 | |||
| 513 | return buffer - start; | ||
| 514 | } | ||
| 515 | |||
| 516 | static int uvc_parse_streaming(struct uvc_device *dev, | ||
| 517 | struct usb_interface *intf) | ||
| 518 | { | ||
| 519 | struct uvc_streaming *streaming = NULL; | ||
| 520 | struct uvc_format *format; | ||
| 521 | struct uvc_frame *frame; | ||
| 522 | struct usb_host_interface *alts = &intf->altsetting[0]; | ||
| 523 | unsigned char *_buffer, *buffer = alts->extra; | ||
| 524 | int _buflen, buflen = alts->extralen; | ||
| 525 | unsigned int nformats = 0, nframes = 0, nintervals = 0; | ||
| 526 | unsigned int size, i, n, p; | ||
| 527 | __u32 *interval; | ||
| 528 | __u16 psize; | ||
| 529 | int ret = -EINVAL; | ||
| 530 | |||
| 531 | if (intf->cur_altsetting->desc.bInterfaceSubClass | ||
| 532 | != SC_VIDEOSTREAMING) { | ||
| 533 | uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a " | ||
| 534 | "video streaming interface\n", dev->udev->devnum, | ||
| 535 | intf->altsetting[0].desc.bInterfaceNumber); | ||
| 536 | return -EINVAL; | ||
| 537 | } | ||
| 538 | |||
| 539 | if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) { | ||
| 540 | uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already " | ||
| 541 | "claimed\n", dev->udev->devnum, | ||
| 542 | intf->altsetting[0].desc.bInterfaceNumber); | ||
| 543 | return -EINVAL; | ||
| 544 | } | ||
| 545 | |||
| 546 | streaming = kzalloc(sizeof *streaming, GFP_KERNEL); | ||
| 547 | if (streaming == NULL) { | ||
| 548 | usb_driver_release_interface(&uvc_driver.driver, intf); | ||
| 549 | return -EINVAL; | ||
| 550 | } | ||
| 551 | |||
| 552 | mutex_init(&streaming->mutex); | ||
| 553 | streaming->intf = usb_get_intf(intf); | ||
| 554 | streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; | ||
| 555 | |||
| 556 | /* The Pico iMage webcam has its class-specific interface descriptors | ||
| 557 | * after the endpoint descriptors. | ||
| 558 | */ | ||
| 559 | if (buflen == 0) { | ||
| 560 | for (i = 0; i < alts->desc.bNumEndpoints; ++i) { | ||
| 561 | struct usb_host_endpoint *ep = &alts->endpoint[i]; | ||
| 562 | |||
| 563 | if (ep->extralen == 0) | ||
| 564 | continue; | ||
| 565 | |||
| 566 | if (ep->extralen > 2 && | ||
| 567 | ep->extra[1] == USB_DT_CS_INTERFACE) { | ||
| 568 | uvc_trace(UVC_TRACE_DESCR, "trying extra data " | ||
| 569 | "from endpoint %u.\n", i); | ||
| 570 | buffer = alts->endpoint[i].extra; | ||
| 571 | buflen = alts->endpoint[i].extralen; | ||
| 572 | break; | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } | ||
| 576 | |||
| 577 | /* Skip the standard interface descriptors. */ | ||
| 578 | while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) { | ||
| 579 | buflen -= buffer[0]; | ||
| 580 | buffer += buffer[0]; | ||
| 581 | } | ||
| 582 | |||
| 583 | if (buflen <= 2) { | ||
| 584 | uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming " | ||
| 585 | "interface descriptors found.\n"); | ||
| 586 | goto error; | ||
| 587 | } | ||
| 588 | |||
| 589 | /* Parse the header descriptor. */ | ||
| 590 | if (buffer[2] == VS_OUTPUT_HEADER) { | ||
| 591 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | ||
| 592 | "%d OUTPUT HEADER descriptor is not supported.\n", | ||
| 593 | dev->udev->devnum, alts->desc.bInterfaceNumber); | ||
| 594 | goto error; | ||
| 595 | } else if (buffer[2] == VS_INPUT_HEADER) { | ||
| 596 | p = buflen >= 5 ? buffer[3] : 0; | ||
| 597 | n = buflen >= 12 ? buffer[12] : 0; | ||
| 598 | |||
| 599 | if (buflen < 13 + p*n || buffer[2] != VS_INPUT_HEADER) { | ||
| 600 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " | ||
| 601 | "interface %d INPUT HEADER descriptor is " | ||
| 602 | "invalid.\n", dev->udev->devnum, | ||
| 603 | alts->desc.bInterfaceNumber); | ||
| 604 | goto error; | ||
| 605 | } | ||
| 606 | |||
| 607 | streaming->header.bNumFormats = p; | ||
| 608 | streaming->header.bEndpointAddress = buffer[6]; | ||
| 609 | streaming->header.bmInfo = buffer[7]; | ||
| 610 | streaming->header.bTerminalLink = buffer[8]; | ||
| 611 | streaming->header.bStillCaptureMethod = buffer[9]; | ||
| 612 | streaming->header.bTriggerSupport = buffer[10]; | ||
| 613 | streaming->header.bTriggerUsage = buffer[11]; | ||
| 614 | streaming->header.bControlSize = n; | ||
| 615 | |||
| 616 | streaming->header.bmaControls = kmalloc(p*n, GFP_KERNEL); | ||
| 617 | if (streaming->header.bmaControls == NULL) { | ||
| 618 | ret = -ENOMEM; | ||
| 619 | goto error; | ||
| 620 | } | ||
| 621 | |||
| 622 | memcpy(streaming->header.bmaControls, &buffer[13], p*n); | ||
| 623 | } else { | ||
| 624 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | ||
| 625 | "%d HEADER descriptor not found.\n", dev->udev->devnum, | ||
| 626 | alts->desc.bInterfaceNumber); | ||
| 627 | goto error; | ||
| 628 | } | ||
| 629 | |||
| 630 | buflen -= buffer[0]; | ||
| 631 | buffer += buffer[0]; | ||
| 632 | |||
| 633 | _buffer = buffer; | ||
| 634 | _buflen = buflen; | ||
| 635 | |||
| 636 | /* Count the format and frame descriptors. */ | ||
| 637 | while (_buflen > 2) { | ||
| 638 | switch (_buffer[2]) { | ||
| 639 | case VS_FORMAT_UNCOMPRESSED: | ||
| 640 | case VS_FORMAT_MJPEG: | ||
| 641 | case VS_FORMAT_FRAME_BASED: | ||
| 642 | nformats++; | ||
| 643 | break; | ||
| 644 | |||
| 645 | case VS_FORMAT_DV: | ||
| 646 | /* DV format has no frame descriptor. We will create a | ||
| 647 | * dummy frame descriptor with a dummy frame interval. | ||
| 648 | */ | ||
| 649 | nformats++; | ||
| 650 | nframes++; | ||
| 651 | nintervals++; | ||
| 652 | break; | ||
| 653 | |||
| 654 | case VS_FORMAT_MPEG2TS: | ||
| 655 | case VS_FORMAT_STREAM_BASED: | ||
| 656 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming " | ||
| 657 | "interface %d FORMAT %u is not supported.\n", | ||
| 658 | dev->udev->devnum, | ||
| 659 | alts->desc.bInterfaceNumber, _buffer[2]); | ||
| 660 | break; | ||
| 661 | |||
| 662 | case VS_FRAME_UNCOMPRESSED: | ||
| 663 | case VS_FRAME_MJPEG: | ||
| 664 | nframes++; | ||
| 665 | if (_buflen > 25) | ||
| 666 | nintervals += _buffer[25] ? _buffer[25] : 3; | ||
| 667 | break; | ||
| 668 | |||
| 669 | case VS_FRAME_FRAME_BASED: | ||
| 670 | nframes++; | ||
| 671 | if (_buflen > 21) | ||
| 672 | nintervals += _buffer[21] ? _buffer[21] : 3; | ||
| 673 | break; | ||
| 674 | } | ||
| 675 | |||
| 676 | _buflen -= _buffer[0]; | ||
| 677 | _buffer += _buffer[0]; | ||
| 678 | } | ||
| 679 | |||
| 680 | if (nformats == 0) { | ||
| 681 | uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface " | ||
| 682 | "%d has no supported formats defined.\n", | ||
| 683 | dev->udev->devnum, alts->desc.bInterfaceNumber); | ||
| 684 | goto error; | ||
| 685 | } | ||
| 686 | |||
| 687 | size = nformats * sizeof *format + nframes * sizeof *frame | ||
| 688 | + nintervals * sizeof *interval; | ||
| 689 | format = kzalloc(size, GFP_KERNEL); | ||
| 690 | if (format == NULL) { | ||
| 691 | ret = -ENOMEM; | ||
| 692 | goto error; | ||
| 693 | } | ||
| 694 | |||
| 695 | frame = (struct uvc_frame *)&format[nformats]; | ||
| 696 | interval = (__u32 *)&frame[nframes]; | ||
| 697 | |||
| 698 | streaming->format = format; | ||
| 699 | streaming->nformats = nformats; | ||
| 700 | |||
| 701 | /* Parse the format descriptors. */ | ||
| 702 | while (buflen > 2) { | ||
| 703 | switch (buffer[2]) { | ||
| 704 | case VS_FORMAT_UNCOMPRESSED: | ||
| 705 | case VS_FORMAT_MJPEG: | ||
| 706 | case VS_FORMAT_DV: | ||
| 707 | case VS_FORMAT_FRAME_BASED: | ||
| 708 | format->frame = frame; | ||
| 709 | ret = uvc_parse_format(dev, streaming, format, | ||
| 710 | &interval, buffer, buflen); | ||
| 711 | if (ret < 0) | ||
| 712 | goto error; | ||
| 713 | |||
| 714 | frame += format->nframes; | ||
| 715 | format++; | ||
| 716 | |||
| 717 | buflen -= ret; | ||
| 718 | buffer += ret; | ||
| 719 | continue; | ||
| 720 | |||
| 721 | default: | ||
| 722 | break; | ||
| 723 | } | ||
| 724 | |||
| 725 | buflen -= buffer[0]; | ||
| 726 | buffer += buffer[0]; | ||
| 727 | } | ||
| 728 | |||
| 729 | /* Parse the alternate settings to find the maximum bandwidth. */ | ||
| 730 | for (i = 0; i < intf->num_altsetting; ++i) { | ||
| 731 | struct usb_host_endpoint *ep; | ||
| 732 | alts = &intf->altsetting[i]; | ||
| 733 | ep = uvc_find_endpoint(alts, | ||
| 734 | streaming->header.bEndpointAddress); | ||
| 735 | if (ep == NULL) | ||
| 736 | continue; | ||
| 737 | |||
| 738 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | ||
| 739 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | ||
| 740 | if (psize > streaming->maxpsize) | ||
| 741 | streaming->maxpsize = psize; | ||
| 742 | } | ||
| 743 | |||
| 744 | list_add_tail(&streaming->list, &dev->streaming); | ||
| 745 | return 0; | ||
| 746 | |||
| 747 | error: | ||
| 748 | usb_driver_release_interface(&uvc_driver.driver, intf); | ||
| 749 | usb_put_intf(intf); | ||
| 750 | kfree(streaming->format); | ||
| 751 | kfree(streaming->header.bmaControls); | ||
| 752 | kfree(streaming); | ||
| 753 | return ret; | ||
| 754 | } | ||
| 755 | |||
| 756 | /* Parse vendor-specific extensions. */ | ||
| 757 | static int uvc_parse_vendor_control(struct uvc_device *dev, | ||
| 758 | const unsigned char *buffer, int buflen) | ||
| 759 | { | ||
| 760 | struct usb_device *udev = dev->udev; | ||
| 761 | struct usb_host_interface *alts = dev->intf->cur_altsetting; | ||
| 762 | struct uvc_entity *unit; | ||
| 763 | unsigned int n, p; | ||
| 764 | int handled = 0; | ||
| 765 | |||
| 766 | switch (le16_to_cpu(dev->udev->descriptor.idVendor)) { | ||
| 767 | case 0x046d: /* Logitech */ | ||
| 768 | if (buffer[1] != 0x41 || buffer[2] != 0x01) | ||
| 769 | break; | ||
| 770 | |||
| 771 | /* Logitech implements several vendor specific functions | ||
| 772 | * through vendor specific extension units (LXU). | ||
| 773 | * | ||
| 774 | * The LXU descriptors are similar to XU descriptors | ||
| 775 | * (see "USB Device Video Class for Video Devices", section | ||
| 776 | * 3.7.2.6 "Extension Unit Descriptor") with the following | ||
| 777 | * differences: | ||
| 778 | * | ||
| 779 | * ---------------------------------------------------------- | ||
| 780 | * 0 bLength 1 Number | ||
| 781 | * Size of this descriptor, in bytes: 24+p+n*2 | ||
| 782 | * ---------------------------------------------------------- | ||
| 783 | * 23+p+n bmControlsType N Bitmap | ||
| 784 | * Individual bits in the set are defined: | ||
| 785 | * 0: Absolute | ||
| 786 | * 1: Relative | ||
| 787 | * | ||
| 788 | * This bitset is mapped exactly the same as bmControls. | ||
| 789 | * ---------------------------------------------------------- | ||
| 790 | * 23+p+n*2 bReserved 1 Boolean | ||
| 791 | * ---------------------------------------------------------- | ||
| 792 | * 24+p+n*2 iExtension 1 Index | ||
| 793 | * Index of a string descriptor that describes this | ||
| 794 | * extension unit. | ||
| 795 | * ---------------------------------------------------------- | ||
| 796 | */ | ||
| 797 | p = buflen >= 22 ? buffer[21] : 0; | ||
| 798 | n = buflen >= 25 + p ? buffer[22+p] : 0; | ||
| 799 | |||
| 800 | if (buflen < 25 + p + 2*n) { | ||
| 801 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 802 | "interface %d EXTENSION_UNIT error\n", | ||
| 803 | udev->devnum, alts->desc.bInterfaceNumber); | ||
| 804 | break; | ||
| 805 | } | ||
| 806 | |||
| 807 | unit = kzalloc(sizeof *unit + p + 2*n, GFP_KERNEL); | ||
| 808 | if (unit == NULL) | ||
| 809 | return -ENOMEM; | ||
| 810 | |||
| 811 | unit->id = buffer[3]; | ||
| 812 | unit->type = VC_EXTENSION_UNIT; | ||
| 813 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); | ||
| 814 | unit->extension.bNumControls = buffer[20]; | ||
| 815 | unit->extension.bNrInPins = | ||
| 816 | le16_to_cpup((__le16 *)&buffer[21]); | ||
| 817 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; | ||
| 818 | memcpy(unit->extension.baSourceID, &buffer[22], p); | ||
| 819 | unit->extension.bControlSize = buffer[22+p]; | ||
| 820 | unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; | ||
| 821 | unit->extension.bmControlsType = (__u8 *)unit + sizeof *unit | ||
| 822 | + p + n; | ||
| 823 | memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); | ||
| 824 | |||
| 825 | if (buffer[24+p+2*n] != 0) | ||
| 826 | usb_string(udev, buffer[24+p+2*n], unit->name, | ||
| 827 | sizeof unit->name); | ||
| 828 | else | ||
| 829 | sprintf(unit->name, "Extension %u", buffer[3]); | ||
| 830 | |||
| 831 | list_add_tail(&unit->list, &dev->entities); | ||
| 832 | handled = 1; | ||
| 833 | break; | ||
| 834 | } | ||
| 835 | |||
| 836 | return handled; | ||
| 837 | } | ||
| 838 | |||
| 839 | static int uvc_parse_standard_control(struct uvc_device *dev, | ||
| 840 | const unsigned char *buffer, int buflen) | ||
| 841 | { | ||
| 842 | struct usb_device *udev = dev->udev; | ||
| 843 | struct uvc_entity *unit, *term; | ||
| 844 | struct usb_interface *intf; | ||
| 845 | struct usb_host_interface *alts = dev->intf->cur_altsetting; | ||
| 846 | unsigned int i, n, p, len; | ||
| 847 | __u16 type; | ||
| 848 | |||
| 849 | switch (buffer[2]) { | ||
| 850 | case VC_HEADER: | ||
| 851 | n = buflen >= 12 ? buffer[11] : 0; | ||
| 852 | |||
| 853 | if (buflen < 12 || buflen < 12 + n) { | ||
| 854 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 855 | "interface %d HEADER error\n", udev->devnum, | ||
| 856 | alts->desc.bInterfaceNumber); | ||
| 857 | return -EINVAL; | ||
| 858 | } | ||
| 859 | |||
| 860 | dev->uvc_version = le16_to_cpup((__le16 *)&buffer[3]); | ||
| 861 | dev->clock_frequency = le32_to_cpup((__le32 *)&buffer[7]); | ||
| 862 | |||
| 863 | /* Parse all USB Video Streaming interfaces. */ | ||
| 864 | for (i = 0; i < n; ++i) { | ||
| 865 | intf = usb_ifnum_to_if(udev, buffer[12+i]); | ||
| 866 | if (intf == NULL) { | ||
| 867 | uvc_trace(UVC_TRACE_DESCR, "device %d " | ||
| 868 | "interface %d doesn't exists\n", | ||
| 869 | udev->devnum, i); | ||
| 870 | continue; | ||
| 871 | } | ||
| 872 | |||
| 873 | uvc_parse_streaming(dev, intf); | ||
| 874 | } | ||
| 875 | break; | ||
| 876 | |||
| 877 | case VC_INPUT_TERMINAL: | ||
| 878 | if (buflen < 8) { | ||
| 879 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 880 | "interface %d INPUT_TERMINAL error\n", | ||
| 881 | udev->devnum, alts->desc.bInterfaceNumber); | ||
| 882 | return -EINVAL; | ||
| 883 | } | ||
| 884 | |||
| 885 | /* Make sure the terminal type MSB is not null, otherwise it | ||
| 886 | * could be confused with a unit. | ||
| 887 | */ | ||
| 888 | type = le16_to_cpup((__le16 *)&buffer[4]); | ||
| 889 | if ((type & 0xff00) == 0) { | ||
| 890 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 891 | "interface %d INPUT_TERMINAL %d has invalid " | ||
| 892 | "type 0x%04x, skipping\n", udev->devnum, | ||
| 893 | alts->desc.bInterfaceNumber, | ||
| 894 | buffer[3], type); | ||
| 895 | return 0; | ||
| 896 | } | ||
| 897 | |||
| 898 | n = 0; | ||
| 899 | p = 0; | ||
| 900 | len = 8; | ||
| 901 | |||
| 902 | if (type == ITT_CAMERA) { | ||
| 903 | n = buflen >= 15 ? buffer[14] : 0; | ||
| 904 | len = 15; | ||
| 905 | |||
| 906 | } else if (type == ITT_MEDIA_TRANSPORT_INPUT) { | ||
| 907 | n = buflen >= 9 ? buffer[8] : 0; | ||
| 908 | p = buflen >= 10 + n ? buffer[9+n] : 0; | ||
| 909 | len = 10; | ||
| 910 | } | ||
| 911 | |||
| 912 | if (buflen < len + n + p) { | ||
| 913 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 914 | "interface %d INPUT_TERMINAL error\n", | ||
| 915 | udev->devnum, alts->desc.bInterfaceNumber); | ||
| 916 | return -EINVAL; | ||
| 917 | } | ||
| 918 | |||
| 919 | term = kzalloc(sizeof *term + n + p, GFP_KERNEL); | ||
| 920 | if (term == NULL) | ||
| 921 | return -ENOMEM; | ||
| 922 | |||
| 923 | term->id = buffer[3]; | ||
| 924 | term->type = type | UVC_TERM_INPUT; | ||
| 925 | |||
| 926 | if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) { | ||
| 927 | term->camera.bControlSize = n; | ||
| 928 | term->camera.bmControls = (__u8 *)term + sizeof *term; | ||
| 929 | term->camera.wObjectiveFocalLengthMin = | ||
| 930 | le16_to_cpup((__le16 *)&buffer[8]); | ||
| 931 | term->camera.wObjectiveFocalLengthMax = | ||
| 932 | le16_to_cpup((__le16 *)&buffer[10]); | ||
| 933 | term->camera.wOcularFocalLength = | ||
| 934 | le16_to_cpup((__le16 *)&buffer[12]); | ||
| 935 | memcpy(term->camera.bmControls, &buffer[15], n); | ||
| 936 | } else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) { | ||
| 937 | term->media.bControlSize = n; | ||
| 938 | term->media.bmControls = (__u8 *)term + sizeof *term; | ||
| 939 | term->media.bTransportModeSize = p; | ||
| 940 | term->media.bmTransportModes = (__u8 *)term | ||
| 941 | + sizeof *term + n; | ||
| 942 | memcpy(term->media.bmControls, &buffer[9], n); | ||
| 943 | memcpy(term->media.bmTransportModes, &buffer[10+n], p); | ||
| 944 | } | ||
| 945 | |||
| 946 | if (buffer[7] != 0) | ||
| 947 | usb_string(udev, buffer[7], term->name, | ||
| 948 | sizeof term->name); | ||
| 949 | else if (UVC_ENTITY_TYPE(term) == ITT_CAMERA) | ||
| 950 | sprintf(term->name, "Camera %u", buffer[3]); | ||
| 951 | else if (UVC_ENTITY_TYPE(term) == ITT_MEDIA_TRANSPORT_INPUT) | ||
| 952 | sprintf(term->name, "Media %u", buffer[3]); | ||
| 953 | else | ||
| 954 | sprintf(term->name, "Input %u", buffer[3]); | ||
| 955 | |||
| 956 | list_add_tail(&term->list, &dev->entities); | ||
| 957 | break; | ||
| 958 | |||
| 959 | case VC_OUTPUT_TERMINAL: | ||
| 960 | if (buflen < 9) { | ||
| 961 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 962 | "interface %d OUTPUT_TERMINAL error\n", | ||
| 963 | udev->devnum, alts->desc.bInterfaceNumber); | ||
| 964 | return -EINVAL; | ||
| 965 | } | ||
| 966 | |||
| 967 | /* Make sure the terminal type MSB is not null, otherwise it | ||
| 968 | * could be confused with a unit. | ||
| 969 | */ | ||
| 970 | type = le16_to_cpup((__le16 *)&buffer[4]); | ||
| 971 | if ((type & 0xff00) == 0) { | ||
| 972 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 973 | "interface %d OUTPUT_TERMINAL %d has invalid " | ||
| 974 | "type 0x%04x, skipping\n", udev->devnum, | ||
| 975 | alts->desc.bInterfaceNumber, buffer[3], type); | ||
| 976 | return 0; | ||
| 977 | } | ||
| 978 | |||
| 979 | term = kzalloc(sizeof *term, GFP_KERNEL); | ||
| 980 | if (term == NULL) | ||
| 981 | return -ENOMEM; | ||
| 982 | |||
| 983 | term->id = buffer[3]; | ||
| 984 | term->type = type | UVC_TERM_OUTPUT; | ||
| 985 | term->output.bSourceID = buffer[7]; | ||
| 986 | |||
| 987 | if (buffer[8] != 0) | ||
| 988 | usb_string(udev, buffer[8], term->name, | ||
| 989 | sizeof term->name); | ||
| 990 | else | ||
| 991 | sprintf(term->name, "Output %u", buffer[3]); | ||
| 992 | |||
| 993 | list_add_tail(&term->list, &dev->entities); | ||
| 994 | break; | ||
| 995 | |||
| 996 | case VC_SELECTOR_UNIT: | ||
| 997 | p = buflen >= 5 ? buffer[4] : 0; | ||
| 998 | |||
| 999 | if (buflen < 5 || buflen < 6 + p) { | ||
| 1000 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 1001 | "interface %d SELECTOR_UNIT error\n", | ||
| 1002 | udev->devnum, alts->desc.bInterfaceNumber); | ||
| 1003 | return -EINVAL; | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | unit = kzalloc(sizeof *unit + p, GFP_KERNEL); | ||
| 1007 | if (unit == NULL) | ||
| 1008 | return -ENOMEM; | ||
| 1009 | |||
| 1010 | unit->id = buffer[3]; | ||
| 1011 | unit->type = buffer[2]; | ||
| 1012 | unit->selector.bNrInPins = buffer[4]; | ||
| 1013 | unit->selector.baSourceID = (__u8 *)unit + sizeof *unit; | ||
| 1014 | memcpy(unit->selector.baSourceID, &buffer[5], p); | ||
| 1015 | |||
| 1016 | if (buffer[5+p] != 0) | ||
| 1017 | usb_string(udev, buffer[5+p], unit->name, | ||
| 1018 | sizeof unit->name); | ||
| 1019 | else | ||
| 1020 | sprintf(unit->name, "Selector %u", buffer[3]); | ||
| 1021 | |||
| 1022 | list_add_tail(&unit->list, &dev->entities); | ||
| 1023 | break; | ||
| 1024 | |||
| 1025 | case VC_PROCESSING_UNIT: | ||
| 1026 | n = buflen >= 8 ? buffer[7] : 0; | ||
| 1027 | p = dev->uvc_version >= 0x0110 ? 10 : 9; | ||
| 1028 | |||
| 1029 | if (buflen < p + n) { | ||
| 1030 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 1031 | "interface %d PROCESSING_UNIT error\n", | ||
| 1032 | udev->devnum, alts->desc.bInterfaceNumber); | ||
| 1033 | return -EINVAL; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | unit = kzalloc(sizeof *unit + n, GFP_KERNEL); | ||
| 1037 | if (unit == NULL) | ||
| 1038 | return -ENOMEM; | ||
| 1039 | |||
| 1040 | unit->id = buffer[3]; | ||
| 1041 | unit->type = buffer[2]; | ||
| 1042 | unit->processing.bSourceID = buffer[4]; | ||
| 1043 | unit->processing.wMaxMultiplier = | ||
| 1044 | le16_to_cpup((__le16 *)&buffer[5]); | ||
| 1045 | unit->processing.bControlSize = buffer[7]; | ||
| 1046 | unit->processing.bmControls = (__u8 *)unit + sizeof *unit; | ||
| 1047 | memcpy(unit->processing.bmControls, &buffer[8], n); | ||
| 1048 | if (dev->uvc_version >= 0x0110) | ||
| 1049 | unit->processing.bmVideoStandards = buffer[9+n]; | ||
| 1050 | |||
| 1051 | if (buffer[8+n] != 0) | ||
| 1052 | usb_string(udev, buffer[8+n], unit->name, | ||
| 1053 | sizeof unit->name); | ||
| 1054 | else | ||
| 1055 | sprintf(unit->name, "Processing %u", buffer[3]); | ||
| 1056 | |||
| 1057 | list_add_tail(&unit->list, &dev->entities); | ||
| 1058 | break; | ||
| 1059 | |||
| 1060 | case VC_EXTENSION_UNIT: | ||
| 1061 | p = buflen >= 22 ? buffer[21] : 0; | ||
| 1062 | n = buflen >= 24 + p ? buffer[22+p] : 0; | ||
| 1063 | |||
| 1064 | if (buflen < 24 + p + n) { | ||
| 1065 | uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol " | ||
| 1066 | "interface %d EXTENSION_UNIT error\n", | ||
| 1067 | udev->devnum, alts->desc.bInterfaceNumber); | ||
| 1068 | return -EINVAL; | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL); | ||
| 1072 | if (unit == NULL) | ||
| 1073 | return -ENOMEM; | ||
| 1074 | |||
| 1075 | unit->id = buffer[3]; | ||
| 1076 | unit->type = buffer[2]; | ||
| 1077 | memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); | ||
| 1078 | unit->extension.bNumControls = buffer[20]; | ||
| 1079 | unit->extension.bNrInPins = | ||
| 1080 | le16_to_cpup((__le16 *)&buffer[21]); | ||
| 1081 | unit->extension.baSourceID = (__u8 *)unit + sizeof *unit; | ||
| 1082 | memcpy(unit->extension.baSourceID, &buffer[22], p); | ||
| 1083 | unit->extension.bControlSize = buffer[22+p]; | ||
| 1084 | unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; | ||
| 1085 | memcpy(unit->extension.bmControls, &buffer[23+p], n); | ||
| 1086 | |||
| 1087 | if (buffer[23+p+n] != 0) | ||
| 1088 | usb_string(udev, buffer[23+p+n], unit->name, | ||
| 1089 | sizeof unit->name); | ||
| 1090 | else | ||
| 1091 | sprintf(unit->name, "Extension %u", buffer[3]); | ||
| 1092 | |||
| 1093 | list_add_tail(&unit->list, &dev->entities); | ||
| 1094 | break; | ||
| 1095 | |||
| 1096 | default: | ||
| 1097 | uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE " | ||
| 1098 | "descriptor (%u)\n", buffer[2]); | ||
| 1099 | break; | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | return 0; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | static int uvc_parse_control(struct uvc_device *dev) | ||
| 1106 | { | ||
| 1107 | struct usb_host_interface *alts = dev->intf->cur_altsetting; | ||
| 1108 | unsigned char *buffer = alts->extra; | ||
| 1109 | int buflen = alts->extralen; | ||
| 1110 | int ret; | ||
| 1111 | |||
| 1112 | /* Parse the default alternate setting only, as the UVC specification | ||
| 1113 | * defines a single alternate setting, the default alternate setting | ||
| 1114 | * zero. | ||
| 1115 | */ | ||
| 1116 | |||
| 1117 | while (buflen > 2) { | ||
| 1118 | if (uvc_parse_vendor_control(dev, buffer, buflen) || | ||
| 1119 | buffer[1] != USB_DT_CS_INTERFACE) | ||
| 1120 | goto next_descriptor; | ||
| 1121 | |||
| 1122 | if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0) | ||
| 1123 | return ret; | ||
| 1124 | |||
| 1125 | next_descriptor: | ||
| 1126 | buflen -= buffer[0]; | ||
| 1127 | buffer += buffer[0]; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | /* Check if the optional status endpoint is present. */ | ||
| 1131 | if (alts->desc.bNumEndpoints == 1) { | ||
| 1132 | struct usb_host_endpoint *ep = &alts->endpoint[0]; | ||
| 1133 | struct usb_endpoint_descriptor *desc = &ep->desc; | ||
| 1134 | |||
| 1135 | if (usb_endpoint_is_int_in(desc) && | ||
| 1136 | le16_to_cpu(desc->wMaxPacketSize) >= 8 && | ||
| 1137 | desc->bInterval != 0) { | ||
| 1138 | uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint " | ||
| 1139 | "(addr %02x).\n", desc->bEndpointAddress); | ||
| 1140 | dev->int_ep = ep; | ||
| 1141 | } | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | return 0; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | /* ------------------------------------------------------------------------ | ||
| 1148 | * USB probe and disconnect | ||
| 1149 | */ | ||
| 1150 | |||
| 1151 | /* | ||
| 1152 | * Unregister the video devices. | ||
| 1153 | */ | ||
| 1154 | static void uvc_unregister_video(struct uvc_device *dev) | ||
| 1155 | { | ||
| 1156 | if (dev->video.vdev) { | ||
| 1157 | if (dev->video.vdev->minor == -1) | ||
| 1158 | video_device_release(dev->video.vdev); | ||
| 1159 | else | ||
| 1160 | video_unregister_device(dev->video.vdev); | ||
| 1161 | dev->video.vdev = NULL; | ||
| 1162 | } | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | /* | ||
| 1166 | * Scan the UVC descriptors to locate a chain starting at an Output Terminal | ||
| 1167 | * and containing the following units: | ||
| 1168 | * | ||
| 1169 | * - a USB Streaming Output Terminal | ||
| 1170 | * - zero or one Processing Unit | ||
| 1171 | * - zero, one or mode single-input Selector Units | ||
| 1172 | * - zero or one multiple-input Selector Units, provided all inputs are | ||
| 1173 | * connected to input terminals | ||
| 1174 | * - zero, one or mode single-input Extension Units | ||
| 1175 | * - one Camera Input Terminal, or one or more External terminals. | ||
| 1176 | * | ||
| 1177 | * A side forward scan is made on each detected entity to check for additional | ||
| 1178 | * extension units. | ||
| 1179 | */ | ||
| 1180 | static int uvc_scan_chain_entity(struct uvc_video_device *video, | ||
| 1181 | struct uvc_entity *entity) | ||
| 1182 | { | ||
| 1183 | switch (UVC_ENTITY_TYPE(entity)) { | ||
| 1184 | case VC_EXTENSION_UNIT: | ||
| 1185 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
| 1186 | printk(" <- XU %d", entity->id); | ||
| 1187 | |||
| 1188 | if (entity->extension.bNrInPins != 1) { | ||
| 1189 | uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more " | ||
| 1190 | "than 1 input pin.\n", entity->id); | ||
| 1191 | return -1; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | list_add_tail(&entity->chain, &video->extensions); | ||
| 1195 | break; | ||
| 1196 | |||
| 1197 | case VC_PROCESSING_UNIT: | ||
| 1198 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
| 1199 | printk(" <- PU %d", entity->id); | ||
| 1200 | |||
| 1201 | if (video->processing != NULL) { | ||
| 1202 | uvc_trace(UVC_TRACE_DESCR, "Found multiple " | ||
| 1203 | "Processing Units in chain.\n"); | ||
| 1204 | return -1; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | video->processing = entity; | ||
| 1208 | break; | ||
| 1209 | |||
| 1210 | case VC_SELECTOR_UNIT: | ||
| 1211 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
| 1212 | printk(" <- SU %d", entity->id); | ||
| 1213 | |||
| 1214 | /* Single-input selector units are ignored. */ | ||
| 1215 | if (entity->selector.bNrInPins == 1) | ||
| 1216 | break; | ||
| 1217 | |||
| 1218 | if (video->selector != NULL) { | ||
| 1219 | uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector " | ||
| 1220 | "Units in chain.\n"); | ||
| 1221 | return -1; | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | video->selector = entity; | ||
| 1225 | break; | ||
| 1226 | |||
| 1227 | case ITT_VENDOR_SPECIFIC: | ||
| 1228 | case ITT_CAMERA: | ||
| 1229 | case ITT_MEDIA_TRANSPORT_INPUT: | ||
| 1230 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
| 1231 | printk(" <- IT %d\n", entity->id); | ||
| 1232 | |||
| 1233 | list_add_tail(&entity->chain, &video->iterms); | ||
| 1234 | break; | ||
| 1235 | |||
| 1236 | default: | ||
| 1237 | uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type " | ||
| 1238 | "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity)); | ||
| 1239 | return -1; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | return 0; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | static int uvc_scan_chain_forward(struct uvc_video_device *video, | ||
| 1246 | struct uvc_entity *entity, struct uvc_entity *prev) | ||
| 1247 | { | ||
| 1248 | struct uvc_entity *forward; | ||
| 1249 | int found; | ||
| 1250 | |||
| 1251 | /* Forward scan */ | ||
| 1252 | forward = NULL; | ||
| 1253 | found = 0; | ||
| 1254 | |||
| 1255 | while (1) { | ||
| 1256 | forward = uvc_entity_by_reference(video->dev, entity->id, | ||
| 1257 | forward); | ||
| 1258 | if (forward == NULL) | ||
| 1259 | break; | ||
| 1260 | |||
| 1261 | if (UVC_ENTITY_TYPE(forward) != VC_EXTENSION_UNIT || | ||
| 1262 | forward == prev) | ||
| 1263 | continue; | ||
| 1264 | |||
| 1265 | if (forward->extension.bNrInPins != 1) { | ||
| 1266 | uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has" | ||
| 1267 | "more than 1 input pin.\n", entity->id); | ||
| 1268 | return -1; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | list_add_tail(&forward->chain, &video->extensions); | ||
| 1272 | if (uvc_trace_param & UVC_TRACE_PROBE) { | ||
| 1273 | if (!found) | ||
| 1274 | printk(" (-> XU"); | ||
| 1275 | |||
| 1276 | printk(" %d", forward->id); | ||
| 1277 | found = 1; | ||
| 1278 | } | ||
| 1279 | } | ||
| 1280 | if (found) | ||
| 1281 | printk(")"); | ||
| 1282 | |||
| 1283 | return 0; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | static int uvc_scan_chain_backward(struct uvc_video_device *video, | ||
| 1287 | struct uvc_entity *entity) | ||
| 1288 | { | ||
| 1289 | struct uvc_entity *term; | ||
| 1290 | int id = -1, i; | ||
| 1291 | |||
| 1292 | switch (UVC_ENTITY_TYPE(entity)) { | ||
| 1293 | case VC_EXTENSION_UNIT: | ||
| 1294 | id = entity->extension.baSourceID[0]; | ||
| 1295 | break; | ||
| 1296 | |||
| 1297 | case VC_PROCESSING_UNIT: | ||
| 1298 | id = entity->processing.bSourceID; | ||
| 1299 | break; | ||
| 1300 | |||
| 1301 | case VC_SELECTOR_UNIT: | ||
| 1302 | /* Single-input selector units are ignored. */ | ||
| 1303 | if (entity->selector.bNrInPins == 1) { | ||
| 1304 | id = entity->selector.baSourceID[0]; | ||
| 1305 | break; | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
| 1309 | printk(" <- IT"); | ||
| 1310 | |||
| 1311 | video->selector = entity; | ||
| 1312 | for (i = 0; i < entity->selector.bNrInPins; ++i) { | ||
| 1313 | id = entity->selector.baSourceID[i]; | ||
| 1314 | term = uvc_entity_by_id(video->dev, id); | ||
| 1315 | if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { | ||
| 1316 | uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " | ||
| 1317 | "input %d isn't connected to an " | ||
| 1318 | "input terminal\n", entity->id, i); | ||
| 1319 | return -1; | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
| 1323 | printk(" %d", term->id); | ||
| 1324 | |||
| 1325 | list_add_tail(&term->chain, &video->iterms); | ||
| 1326 | uvc_scan_chain_forward(video, term, entity); | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | if (uvc_trace_param & UVC_TRACE_PROBE) | ||
| 1330 | printk("\n"); | ||
| 1331 | |||
| 1332 | id = 0; | ||
| 1333 | break; | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | return id; | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | static int uvc_scan_chain(struct uvc_video_device *video) | ||
| 1340 | { | ||
| 1341 | struct uvc_entity *entity, *prev; | ||
| 1342 | int id; | ||
| 1343 | |||
| 1344 | entity = video->oterm; | ||
| 1345 | uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain: OT %d", entity->id); | ||
| 1346 | id = entity->output.bSourceID; | ||
| 1347 | while (id != 0) { | ||
| 1348 | prev = entity; | ||
| 1349 | entity = uvc_entity_by_id(video->dev, id); | ||
| 1350 | if (entity == NULL) { | ||
| 1351 | uvc_trace(UVC_TRACE_DESCR, "Found reference to " | ||
| 1352 | "unknown entity %d.\n", id); | ||
| 1353 | return -1; | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | /* Process entity */ | ||
| 1357 | if (uvc_scan_chain_entity(video, entity) < 0) | ||
| 1358 | return -1; | ||
| 1359 | |||
| 1360 | /* Forward scan */ | ||
| 1361 | if (uvc_scan_chain_forward(video, entity, prev) < 0) | ||
| 1362 | return -1; | ||
| 1363 | |||
| 1364 | /* Stop when a terminal is found. */ | ||
| 1365 | if (!UVC_ENTITY_IS_UNIT(entity)) | ||
| 1366 | break; | ||
| 1367 | |||
| 1368 | /* Backward scan */ | ||
| 1369 | id = uvc_scan_chain_backward(video, entity); | ||
| 1370 | if (id < 0) | ||
| 1371 | return id; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | /* Initialize the video buffers queue. */ | ||
| 1375 | uvc_queue_init(&video->queue); | ||
| 1376 | |||
| 1377 | return 0; | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | /* | ||
| 1381 | * Register the video devices. | ||
| 1382 | * | ||
| 1383 | * The driver currently supports a single video device per control interface | ||
| 1384 | * only. The terminal and units must match the following structure: | ||
| 1385 | * | ||
| 1386 | * ITT_CAMERA -> VC_PROCESSING_UNIT -> VC_EXTENSION_UNIT{0,n} -> TT_STREAMING | ||
| 1387 | * | ||
| 1388 | * The Extension Units, if present, must have a single input pin. The | ||
| 1389 | * Processing Unit and Extension Units can be in any order. Additional | ||
| 1390 | * Extension Units connected to the main chain as single-unit branches are | ||
| 1391 | * also supported. | ||
| 1392 | */ | ||
| 1393 | static int uvc_register_video(struct uvc_device *dev) | ||
| 1394 | { | ||
| 1395 | struct video_device *vdev; | ||
| 1396 | struct uvc_entity *term; | ||
| 1397 | int found = 0, ret; | ||
| 1398 | |||
| 1399 | /* Check if the control interface matches the structure we expect. */ | ||
| 1400 | list_for_each_entry(term, &dev->entities, list) { | ||
| 1401 | struct uvc_streaming *streaming; | ||
| 1402 | |||
| 1403 | if (UVC_ENTITY_TYPE(term) != TT_STREAMING) | ||
| 1404 | continue; | ||
| 1405 | |||
| 1406 | memset(&dev->video, 0, sizeof dev->video); | ||
| 1407 | mutex_init(&dev->video.ctrl_mutex); | ||
| 1408 | INIT_LIST_HEAD(&dev->video.iterms); | ||
| 1409 | INIT_LIST_HEAD(&dev->video.extensions); | ||
| 1410 | dev->video.oterm = term; | ||
| 1411 | dev->video.dev = dev; | ||
| 1412 | if (uvc_scan_chain(&dev->video) < 0) | ||
| 1413 | continue; | ||
| 1414 | |||
| 1415 | list_for_each_entry(streaming, &dev->streaming, list) { | ||
| 1416 | if (streaming->header.bTerminalLink == term->id) { | ||
| 1417 | dev->video.streaming = streaming; | ||
| 1418 | found = 1; | ||
| 1419 | break; | ||
| 1420 | } | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | if (found) | ||
| 1424 | break; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | if (!found) { | ||
| 1428 | uvc_printk(KERN_INFO, "No valid video chain found.\n"); | ||
| 1429 | return -1; | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | if (uvc_trace_param & UVC_TRACE_PROBE) { | ||
| 1433 | uvc_printk(KERN_INFO, "Found a valid video chain ("); | ||
| 1434 | list_for_each_entry(term, &dev->video.iterms, chain) { | ||
| 1435 | printk("%d", term->id); | ||
| 1436 | if (term->chain.next != &dev->video.iterms) | ||
| 1437 | printk(","); | ||
| 1438 | } | ||
| 1439 | printk(" -> %d).\n", dev->video.oterm->id); | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | /* Initialize the streaming interface with default streaming | ||
| 1443 | * parameters. | ||
| 1444 | */ | ||
| 1445 | if ((ret = uvc_video_init(&dev->video)) < 0) { | ||
| 1446 | uvc_printk(KERN_ERR, "Failed to initialize the device " | ||
| 1447 | "(%d).\n", ret); | ||
| 1448 | return ret; | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | /* Register the device with V4L. */ | ||
| 1452 | vdev = video_device_alloc(); | ||
| 1453 | if (vdev == NULL) | ||
| 1454 | return -1; | ||
| 1455 | |||
| 1456 | /* We already hold a reference to dev->udev. The video device will be | ||
| 1457 | * unregistered before the reference is released, so we don't need to | ||
| 1458 | * get another one. | ||
| 1459 | */ | ||
| 1460 | vdev->dev = &dev->intf->dev; | ||
| 1461 | vdev->type = 0; | ||
| 1462 | vdev->type2 = 0; | ||
| 1463 | vdev->minor = -1; | ||
| 1464 | vdev->fops = &uvc_fops; | ||
| 1465 | vdev->release = video_device_release; | ||
| 1466 | strncpy(vdev->name, dev->name, sizeof vdev->name); | ||
| 1467 | |||
| 1468 | /* Set the driver data before calling video_register_device, otherwise | ||
| 1469 | * uvc_v4l2_open might race us. | ||
| 1470 | * | ||
| 1471 | * FIXME: usb_set_intfdata hasn't been called so far. Is that a | ||
| 1472 | * problem ? Does any function which could be called here get | ||
| 1473 | * a pointer to the usb_interface ? | ||
| 1474 | */ | ||
| 1475 | dev->video.vdev = vdev; | ||
| 1476 | video_set_drvdata(vdev, &dev->video); | ||
| 1477 | |||
| 1478 | if (video_register_device(vdev, VFL_TYPE_GRABBER, -1) < 0) { | ||
| 1479 | dev->video.vdev = NULL; | ||
| 1480 | video_device_release(vdev); | ||
| 1481 | return -1; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | return 0; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | /* | ||
| 1488 | * Delete the UVC device. | ||
| 1489 | * | ||
| 1490 | * Called by the kernel when the last reference to the uvc_device structure | ||
| 1491 | * is released. | ||
| 1492 | * | ||
| 1493 | * Unregistering the video devices is done here because every opened instance | ||
| 1494 | * must be closed before the device can be unregistered. An alternative would | ||
| 1495 | * have been to use another reference count for uvc_v4l2_open/uvc_release, and | ||
| 1496 | * unregister the video devices on disconnect when that reference count drops | ||
| 1497 | * to zero. | ||
| 1498 | * | ||
| 1499 | * As this function is called after or during disconnect(), all URBs have | ||
| 1500 | * already been canceled by the USB core. There is no need to kill the | ||
| 1501 | * interrupt URB manually. | ||
| 1502 | */ | ||
| 1503 | void uvc_delete(struct kref *kref) | ||
| 1504 | { | ||
| 1505 | struct uvc_device *dev = container_of(kref, struct uvc_device, kref); | ||
| 1506 | struct list_head *p, *n; | ||
| 1507 | |||
| 1508 | /* Unregister the video device */ | ||
| 1509 | uvc_unregister_video(dev); | ||
| 1510 | usb_put_intf(dev->intf); | ||
| 1511 | usb_put_dev(dev->udev); | ||
| 1512 | |||
| 1513 | uvc_status_cleanup(dev); | ||
| 1514 | uvc_ctrl_cleanup_device(dev); | ||
| 1515 | |||
| 1516 | list_for_each_safe(p, n, &dev->entities) { | ||
| 1517 | struct uvc_entity *entity; | ||
| 1518 | entity = list_entry(p, struct uvc_entity, list); | ||
| 1519 | kfree(entity); | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | list_for_each_safe(p, n, &dev->streaming) { | ||
| 1523 | struct uvc_streaming *streaming; | ||
| 1524 | streaming = list_entry(p, struct uvc_streaming, list); | ||
| 1525 | usb_driver_release_interface(&uvc_driver.driver, | ||
| 1526 | streaming->intf); | ||
| 1527 | usb_put_intf(streaming->intf); | ||
| 1528 | kfree(streaming->format); | ||
| 1529 | kfree(streaming->header.bmaControls); | ||
| 1530 | kfree(streaming); | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | kfree(dev); | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | static int uvc_probe(struct usb_interface *intf, | ||
| 1537 | const struct usb_device_id *id) | ||
| 1538 | { | ||
| 1539 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 1540 | struct uvc_device *dev; | ||
| 1541 | int ret; | ||
| 1542 | |||
| 1543 | if (id->idVendor && id->idProduct) | ||
| 1544 | uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s " | ||
| 1545 | "(%04x:%04x)\n", udev->devpath, id->idVendor, | ||
| 1546 | id->idProduct); | ||
| 1547 | else | ||
| 1548 | uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n", | ||
| 1549 | udev->devpath); | ||
| 1550 | |||
| 1551 | /* Allocate memory for the device and initialize it */ | ||
| 1552 | if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL) | ||
| 1553 | return -ENOMEM; | ||
| 1554 | |||
| 1555 | INIT_LIST_HEAD(&dev->entities); | ||
| 1556 | INIT_LIST_HEAD(&dev->streaming); | ||
| 1557 | kref_init(&dev->kref); | ||
| 1558 | |||
| 1559 | dev->udev = usb_get_dev(udev); | ||
| 1560 | dev->intf = usb_get_intf(intf); | ||
| 1561 | dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber; | ||
| 1562 | dev->quirks = id->driver_info | uvc_quirks_param; | ||
| 1563 | |||
| 1564 | if (udev->product != NULL) | ||
| 1565 | strncpy(dev->name, udev->product, sizeof dev->name); | ||
| 1566 | else | ||
| 1567 | snprintf(dev->name, sizeof dev->name, | ||
| 1568 | "UVC Camera (%04x:%04x)", | ||
| 1569 | le16_to_cpu(udev->descriptor.idVendor), | ||
| 1570 | le16_to_cpu(udev->descriptor.idProduct)); | ||
| 1571 | |||
| 1572 | /* Parse the Video Class control descriptor */ | ||
| 1573 | if (uvc_parse_control(dev) < 0) { | ||
| 1574 | uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC " | ||
| 1575 | "descriptors.\n"); | ||
| 1576 | goto error; | ||
| 1577 | } | ||
| 1578 | |||
| 1579 | uvc_printk(KERN_INFO, "Found UVC %u.%02u device %s (%04x:%04x)\n", | ||
| 1580 | dev->uvc_version >> 8, dev->uvc_version & 0xff, | ||
| 1581 | udev->product ? udev->product : "<unnamed>", | ||
| 1582 | le16_to_cpu(udev->descriptor.idVendor), | ||
| 1583 | le16_to_cpu(udev->descriptor.idProduct)); | ||
| 1584 | |||
| 1585 | if (uvc_quirks_param != 0) { | ||
| 1586 | uvc_printk(KERN_INFO, "Forcing device quirks 0x%x by module " | ||
| 1587 | "parameter for testing purpose.\n", uvc_quirks_param); | ||
| 1588 | uvc_printk(KERN_INFO, "Please report required quirks to the " | ||
| 1589 | "linux-uvc-devel mailing list.\n"); | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | /* Initialize controls */ | ||
| 1593 | if (uvc_ctrl_init_device(dev) < 0) | ||
| 1594 | goto error; | ||
| 1595 | |||
| 1596 | /* Register the video devices */ | ||
| 1597 | if (uvc_register_video(dev) < 0) | ||
| 1598 | goto error; | ||
| 1599 | |||
| 1600 | /* Save our data pointer in the interface data */ | ||
| 1601 | usb_set_intfdata(intf, dev); | ||
| 1602 | |||
| 1603 | /* Initialize the interrupt URB */ | ||
| 1604 | if ((ret = uvc_status_init(dev)) < 0) { | ||
| 1605 | uvc_printk(KERN_INFO, "Unable to initialize the status " | ||
| 1606 | "endpoint (%d), status interrupt will not be " | ||
| 1607 | "supported.\n", ret); | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n"); | ||
| 1611 | return 0; | ||
| 1612 | |||
| 1613 | error: | ||
| 1614 | kref_put(&dev->kref, uvc_delete); | ||
| 1615 | return -ENODEV; | ||
| 1616 | } | ||
| 1617 | |||
| 1618 | static void uvc_disconnect(struct usb_interface *intf) | ||
| 1619 | { | ||
| 1620 | struct uvc_device *dev = usb_get_intfdata(intf); | ||
| 1621 | |||
| 1622 | /* Set the USB interface data to NULL. This can be done outside the | ||
| 1623 | * lock, as there's no other reader. | ||
| 1624 | */ | ||
| 1625 | usb_set_intfdata(intf, NULL); | ||
| 1626 | |||
| 1627 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOSTREAMING) | ||
| 1628 | return; | ||
| 1629 | |||
| 1630 | /* uvc_v4l2_open() might race uvc_disconnect(). A static driver-wide | ||
| 1631 | * lock is needed to prevent uvc_disconnect from releasing its | ||
| 1632 | * reference to the uvc_device instance after uvc_v4l2_open() received | ||
| 1633 | * the pointer to the device (video_devdata) but before it got the | ||
| 1634 | * chance to increase the reference count (kref_get). | ||
| 1635 | */ | ||
| 1636 | mutex_lock(&uvc_driver.open_mutex); | ||
| 1637 | |||
| 1638 | dev->state |= UVC_DEV_DISCONNECTED; | ||
| 1639 | kref_put(&dev->kref, uvc_delete); | ||
| 1640 | |||
| 1641 | mutex_unlock(&uvc_driver.open_mutex); | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | static int uvc_suspend(struct usb_interface *intf, pm_message_t message) | ||
| 1645 | { | ||
| 1646 | struct uvc_device *dev = usb_get_intfdata(intf); | ||
| 1647 | |||
| 1648 | uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n", | ||
| 1649 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 1650 | |||
| 1651 | /* Controls are cached on the fly so they don't need to be saved. */ | ||
| 1652 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) | ||
| 1653 | return uvc_status_suspend(dev); | ||
| 1654 | |||
| 1655 | if (dev->video.streaming->intf != intf) { | ||
| 1656 | uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB " | ||
| 1657 | "interface mismatch.\n"); | ||
| 1658 | return -EINVAL; | ||
| 1659 | } | ||
| 1660 | |||
| 1661 | return uvc_video_suspend(&dev->video); | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | static int uvc_resume(struct usb_interface *intf) | ||
| 1665 | { | ||
| 1666 | struct uvc_device *dev = usb_get_intfdata(intf); | ||
| 1667 | int ret; | ||
| 1668 | |||
| 1669 | uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n", | ||
| 1670 | intf->cur_altsetting->desc.bInterfaceNumber); | ||
| 1671 | |||
| 1672 | if (intf->cur_altsetting->desc.bInterfaceSubClass == SC_VIDEOCONTROL) { | ||
| 1673 | if ((ret = uvc_ctrl_resume_device(dev)) < 0) | ||
| 1674 | return ret; | ||
| 1675 | |||
| 1676 | return uvc_status_resume(dev); | ||
| 1677 | } | ||
| 1678 | |||
| 1679 | if (dev->video.streaming->intf != intf) { | ||
| 1680 | uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB " | ||
| 1681 | "interface mismatch.\n"); | ||
| 1682 | return -EINVAL; | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | return uvc_video_resume(&dev->video); | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | /* ------------------------------------------------------------------------ | ||
| 1689 | * Driver initialization and cleanup | ||
| 1690 | */ | ||
| 1691 | |||
| 1692 | /* | ||
| 1693 | * The Logitech cameras listed below have their interface class set to | ||
| 1694 | * VENDOR_SPEC because they don't announce themselves as UVC devices, even | ||
| 1695 | * though they are compliant. | ||
| 1696 | */ | ||
| 1697 | static struct usb_device_id uvc_ids[] = { | ||
| 1698 | /* ALi M5606 (Clevo M540SR) */ | ||
| 1699 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1700 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1701 | .idVendor = 0x0402, | ||
| 1702 | .idProduct = 0x5606, | ||
| 1703 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1704 | .bInterfaceSubClass = 1, | ||
| 1705 | .bInterfaceProtocol = 0, | ||
| 1706 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1707 | /* Creative Live! Optia */ | ||
| 1708 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1709 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1710 | .idVendor = 0x041e, | ||
| 1711 | .idProduct = 0x4057, | ||
| 1712 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1713 | .bInterfaceSubClass = 1, | ||
| 1714 | .bInterfaceProtocol = 0, | ||
| 1715 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1716 | /* Microsoft Lifecam NX-6000 */ | ||
| 1717 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1718 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1719 | .idVendor = 0x045e, | ||
| 1720 | .idProduct = 0x00f8, | ||
| 1721 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1722 | .bInterfaceSubClass = 1, | ||
| 1723 | .bInterfaceProtocol = 0, | ||
| 1724 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1725 | /* Microsoft Lifecam VX-7000 */ | ||
| 1726 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1727 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1728 | .idVendor = 0x045e, | ||
| 1729 | .idProduct = 0x0723, | ||
| 1730 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1731 | .bInterfaceSubClass = 1, | ||
| 1732 | .bInterfaceProtocol = 0, | ||
| 1733 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1734 | /* Logitech Quickcam Fusion */ | ||
| 1735 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1736 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1737 | .idVendor = 0x046d, | ||
| 1738 | .idProduct = 0x08c1, | ||
| 1739 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
| 1740 | .bInterfaceSubClass = 1, | ||
| 1741 | .bInterfaceProtocol = 0 }, | ||
| 1742 | /* Logitech Quickcam Orbit MP */ | ||
| 1743 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1744 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1745 | .idVendor = 0x046d, | ||
| 1746 | .idProduct = 0x08c2, | ||
| 1747 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
| 1748 | .bInterfaceSubClass = 1, | ||
| 1749 | .bInterfaceProtocol = 0 }, | ||
| 1750 | /* Logitech Quickcam Pro for Notebook */ | ||
| 1751 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1752 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1753 | .idVendor = 0x046d, | ||
| 1754 | .idProduct = 0x08c3, | ||
| 1755 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
| 1756 | .bInterfaceSubClass = 1, | ||
| 1757 | .bInterfaceProtocol = 0 }, | ||
| 1758 | /* Logitech Quickcam Pro 5000 */ | ||
| 1759 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1760 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1761 | .idVendor = 0x046d, | ||
| 1762 | .idProduct = 0x08c5, | ||
| 1763 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
| 1764 | .bInterfaceSubClass = 1, | ||
| 1765 | .bInterfaceProtocol = 0 }, | ||
| 1766 | /* Logitech Quickcam OEM Dell Notebook */ | ||
| 1767 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1768 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1769 | .idVendor = 0x046d, | ||
| 1770 | .idProduct = 0x08c6, | ||
| 1771 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
| 1772 | .bInterfaceSubClass = 1, | ||
| 1773 | .bInterfaceProtocol = 0 }, | ||
| 1774 | /* Logitech Quickcam OEM Cisco VT Camera II */ | ||
| 1775 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1776 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1777 | .idVendor = 0x046d, | ||
| 1778 | .idProduct = 0x08c7, | ||
| 1779 | .bInterfaceClass = USB_CLASS_VENDOR_SPEC, | ||
| 1780 | .bInterfaceSubClass = 1, | ||
| 1781 | .bInterfaceProtocol = 0 }, | ||
| 1782 | /* Apple Built-In iSight */ | ||
| 1783 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1784 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1785 | .idVendor = 0x05ac, | ||
| 1786 | .idProduct = 0x8501, | ||
| 1787 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1788 | .bInterfaceSubClass = 1, | ||
| 1789 | .bInterfaceProtocol = 0, | ||
| 1790 | .driver_info = UVC_QUIRK_PROBE_MINMAX | ||
| 1791 | | UVC_QUIRK_BUILTIN_ISIGHT }, | ||
| 1792 | /* Genesys Logic USB 2.0 PC Camera */ | ||
| 1793 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1794 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1795 | .idVendor = 0x05e3, | ||
| 1796 | .idProduct = 0x0505, | ||
| 1797 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1798 | .bInterfaceSubClass = 1, | ||
| 1799 | .bInterfaceProtocol = 0, | ||
| 1800 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
| 1801 | /* Silicon Motion SM371 */ | ||
| 1802 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1803 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1804 | .idVendor = 0x090c, | ||
| 1805 | .idProduct = 0xb371, | ||
| 1806 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1807 | .bInterfaceSubClass = 1, | ||
| 1808 | .bInterfaceProtocol = 0, | ||
| 1809 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1810 | /* MT6227 */ | ||
| 1811 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1812 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1813 | .idVendor = 0x0e8d, | ||
| 1814 | .idProduct = 0x0004, | ||
| 1815 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1816 | .bInterfaceSubClass = 1, | ||
| 1817 | .bInterfaceProtocol = 0, | ||
| 1818 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1819 | /* Syntek (HP Spartan) */ | ||
| 1820 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1821 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1822 | .idVendor = 0x174f, | ||
| 1823 | .idProduct = 0x5212, | ||
| 1824 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1825 | .bInterfaceSubClass = 1, | ||
| 1826 | .bInterfaceProtocol = 0, | ||
| 1827 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
| 1828 | /* Syntek (Asus U3S) */ | ||
| 1829 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1830 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1831 | .idVendor = 0x174f, | ||
| 1832 | .idProduct = 0x8a33, | ||
| 1833 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1834 | .bInterfaceSubClass = 1, | ||
| 1835 | .bInterfaceProtocol = 0, | ||
| 1836 | .driver_info = UVC_QUIRK_STREAM_NO_FID }, | ||
| 1837 | /* Ecamm Pico iMage */ | ||
| 1838 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1839 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1840 | .idVendor = 0x18cd, | ||
| 1841 | .idProduct = 0xcafe, | ||
| 1842 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1843 | .bInterfaceSubClass = 1, | ||
| 1844 | .bInterfaceProtocol = 0, | ||
| 1845 | .driver_info = UVC_QUIRK_PROBE_EXTRAFIELDS }, | ||
| 1846 | /* Bodelin ProScopeHR */ | ||
| 1847 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1848 | | USB_DEVICE_ID_MATCH_DEV_HI | ||
| 1849 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1850 | .idVendor = 0x19ab, | ||
| 1851 | .idProduct = 0x1000, | ||
| 1852 | .bcdDevice_hi = 0x0126, | ||
| 1853 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1854 | .bInterfaceSubClass = 1, | ||
| 1855 | .bInterfaceProtocol = 0, | ||
| 1856 | .driver_info = UVC_QUIRK_STATUS_INTERVAL }, | ||
| 1857 | /* SiGma Micro USB Web Camera */ | ||
| 1858 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1859 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1860 | .idVendor = 0x1c4f, | ||
| 1861 | .idProduct = 0x3000, | ||
| 1862 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1863 | .bInterfaceSubClass = 1, | ||
| 1864 | .bInterfaceProtocol = 0, | ||
| 1865 | .driver_info = UVC_QUIRK_PROBE_MINMAX | ||
| 1866 | | UVC_QUIRK_IGNORE_SELECTOR_UNIT}, | ||
| 1867 | /* Acer OEM Webcam - Unknown vendor */ | ||
| 1868 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1869 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1870 | .idVendor = 0x5986, | ||
| 1871 | .idProduct = 0x0100, | ||
| 1872 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1873 | .bInterfaceSubClass = 1, | ||
| 1874 | .bInterfaceProtocol = 0, | ||
| 1875 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1876 | /* Packard Bell OEM Webcam */ | ||
| 1877 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1878 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1879 | .idVendor = 0x5986, | ||
| 1880 | .idProduct = 0x0101, | ||
| 1881 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1882 | .bInterfaceSubClass = 1, | ||
| 1883 | .bInterfaceProtocol = 0, | ||
| 1884 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1885 | /* Acer Crystal Eye webcam */ | ||
| 1886 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1887 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1888 | .idVendor = 0x5986, | ||
| 1889 | .idProduct = 0x0102, | ||
| 1890 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1891 | .bInterfaceSubClass = 1, | ||
| 1892 | .bInterfaceProtocol = 0, | ||
| 1893 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1894 | /* Acer OrbiCam - Unknown vendor */ | ||
| 1895 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
| 1896 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
| 1897 | .idVendor = 0x5986, | ||
| 1898 | .idProduct = 0x0200, | ||
| 1899 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
| 1900 | .bInterfaceSubClass = 1, | ||
| 1901 | .bInterfaceProtocol = 0, | ||
| 1902 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
| 1903 | /* Generic USB Video Class */ | ||
| 1904 | { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) }, | ||
| 1905 | {} | ||
| 1906 | }; | ||
| 1907 | |||
| 1908 | MODULE_DEVICE_TABLE(usb, uvc_ids); | ||
| 1909 | |||
| 1910 | struct uvc_driver uvc_driver = { | ||
| 1911 | .driver = { | ||
| 1912 | .name = "uvcvideo", | ||
| 1913 | .probe = uvc_probe, | ||
| 1914 | .disconnect = uvc_disconnect, | ||
| 1915 | .suspend = uvc_suspend, | ||
| 1916 | .resume = uvc_resume, | ||
| 1917 | .id_table = uvc_ids, | ||
| 1918 | .supports_autosuspend = 1, | ||
| 1919 | }, | ||
| 1920 | }; | ||
| 1921 | |||
| 1922 | static int __init uvc_init(void) | ||
| 1923 | { | ||
| 1924 | int result; | ||
| 1925 | |||
| 1926 | INIT_LIST_HEAD(&uvc_driver.devices); | ||
| 1927 | INIT_LIST_HEAD(&uvc_driver.controls); | ||
| 1928 | mutex_init(&uvc_driver.open_mutex); | ||
| 1929 | mutex_init(&uvc_driver.ctrl_mutex); | ||
| 1930 | |||
| 1931 | uvc_ctrl_init(); | ||
| 1932 | |||
| 1933 | result = usb_register(&uvc_driver.driver); | ||
| 1934 | if (result == 0) | ||
| 1935 | printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n"); | ||
| 1936 | return result; | ||
| 1937 | } | ||
| 1938 | |||
| 1939 | static void __exit uvc_cleanup(void) | ||
| 1940 | { | ||
| 1941 | usb_deregister(&uvc_driver.driver); | ||
| 1942 | } | ||
| 1943 | |||
| 1944 | module_init(uvc_init); | ||
| 1945 | module_exit(uvc_cleanup); | ||
| 1946 | |||
| 1947 | module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR); | ||
| 1948 | MODULE_PARM_DESC(quirks, "Forced device quirks"); | ||
| 1949 | module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR); | ||
| 1950 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | ||
| 1951 | |||
| 1952 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
| 1953 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 1954 | MODULE_LICENSE("GPL"); | ||
| 1955 | MODULE_VERSION(DRIVER_VERSION); | ||
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c new file mode 100644 index 000000000000..37bdefdbead5 --- /dev/null +++ b/drivers/media/video/uvc/uvc_isight.c | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | /* | ||
| 2 | * uvc_isight.c -- USB Video Class driver - iSight support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006-2007 | ||
| 5 | * Ivan N. Zlatev <contact@i-nz.net> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/usb.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/mm.h> | ||
| 17 | |||
| 18 | #include "uvcvideo.h" | ||
| 19 | |||
| 20 | /* Built-in iSight webcams implements most of UVC 1.0 except a | ||
| 21 | * different packet format. Instead of sending a header at the | ||
| 22 | * beginning of each isochronous transfer payload, the webcam sends a | ||
| 23 | * single header per image (on its own in a packet), followed by | ||
| 24 | * packets containing data only. | ||
| 25 | * | ||
| 26 | * Offset Size (bytes) Description | ||
| 27 | * ------------------------------------------------------------------ | ||
| 28 | * 0x00 1 Header length | ||
| 29 | * 0x01 1 Flags (UVC-compliant) | ||
| 30 | * 0x02 4 Always equal to '11223344' | ||
| 31 | * 0x06 8 Always equal to 'deadbeefdeadface' | ||
| 32 | * 0x0e 16 Unknown | ||
| 33 | * | ||
| 34 | * The header can be prefixed by an optional, unknown-purpose byte. | ||
| 35 | */ | ||
| 36 | |||
| 37 | static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf, | ||
| 38 | const __u8 *data, unsigned int len) | ||
| 39 | { | ||
| 40 | static const __u8 hdr[] = { | ||
| 41 | 0x11, 0x22, 0x33, 0x44, | ||
| 42 | 0xde, 0xad, 0xbe, 0xef, | ||
| 43 | 0xde, 0xad, 0xfa, 0xce | ||
| 44 | }; | ||
| 45 | |||
| 46 | unsigned int maxlen, nbytes; | ||
| 47 | __u8 *mem; | ||
| 48 | int is_header = 0; | ||
| 49 | |||
| 50 | if (buf == NULL) | ||
| 51 | return 0; | ||
| 52 | |||
| 53 | if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) || | ||
| 54 | (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) { | ||
| 55 | uvc_trace(UVC_TRACE_FRAME, "iSight header found\n"); | ||
| 56 | is_header = 1; | ||
| 57 | } | ||
| 58 | |||
| 59 | /* Synchronize to the input stream by waiting for a header packet. */ | ||
| 60 | if (buf->state != UVC_BUF_STATE_ACTIVE) { | ||
| 61 | if (!is_header) { | ||
| 62 | uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of " | ||
| 63 | "sync).\n"); | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | buf->state = UVC_BUF_STATE_ACTIVE; | ||
| 68 | } | ||
| 69 | |||
| 70 | /* Mark the buffer as done if we're at the beginning of a new frame. | ||
| 71 | * | ||
| 72 | * Empty buffers (bytesused == 0) don't trigger end of frame detection | ||
| 73 | * as it doesn't make sense to return an empty buffer. | ||
| 74 | */ | ||
| 75 | if (is_header && buf->buf.bytesused != 0) { | ||
| 76 | buf->state = UVC_BUF_STATE_DONE; | ||
| 77 | return -EAGAIN; | ||
| 78 | } | ||
| 79 | |||
| 80 | /* Copy the video data to the buffer. Skip header packets, as they | ||
| 81 | * contain no data. | ||
| 82 | */ | ||
| 83 | if (!is_header) { | ||
| 84 | maxlen = buf->buf.length - buf->buf.bytesused; | ||
| 85 | mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; | ||
| 86 | nbytes = min(len, maxlen); | ||
| 87 | memcpy(mem, data, nbytes); | ||
| 88 | buf->buf.bytesused += nbytes; | ||
| 89 | |||
| 90 | if (len > maxlen || buf->buf.bytesused == buf->buf.length) { | ||
| 91 | uvc_trace(UVC_TRACE_FRAME, "Frame complete " | ||
| 92 | "(overflow).\n"); | ||
| 93 | buf->state = UVC_BUF_STATE_DONE; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, | ||
| 101 | struct uvc_buffer *buf) | ||
| 102 | { | ||
| 103 | int ret, i; | ||
| 104 | |||
| 105 | for (i = 0; i < urb->number_of_packets; ++i) { | ||
| 106 | if (urb->iso_frame_desc[i].status < 0) { | ||
| 107 | uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " | ||
| 108 | "lost (%d).\n", | ||
| 109 | urb->iso_frame_desc[i].status); | ||
| 110 | } | ||
| 111 | |||
| 112 | /* Decode the payload packet. | ||
| 113 | * uvc_video_decode is entered twice when a frame transition | ||
| 114 | * has been detected because the end of frame can only be | ||
| 115 | * reliably detected when the first packet of the new frame | ||
| 116 | * is processed. The first pass detects the transition and | ||
| 117 | * closes the previous frame's buffer, the second pass | ||
| 118 | * processes the data of the first payload of the new frame. | ||
| 119 | */ | ||
| 120 | do { | ||
| 121 | ret = isight_decode(&video->queue, buf, | ||
| 122 | urb->transfer_buffer + | ||
| 123 | urb->iso_frame_desc[i].offset, | ||
| 124 | urb->iso_frame_desc[i].actual_length); | ||
| 125 | |||
| 126 | if (buf == NULL) | ||
| 127 | break; | ||
| 128 | |||
| 129 | if (buf->state == UVC_BUF_STATE_DONE || | ||
| 130 | buf->state == UVC_BUF_STATE_ERROR) | ||
| 131 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
| 132 | } while (ret == -EAGAIN); | ||
| 133 | } | ||
| 134 | } | ||
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c new file mode 100644 index 000000000000..0923f0e3b3d4 --- /dev/null +++ b/drivers/media/video/uvc/uvc_queue.c | |||
| @@ -0,0 +1,477 @@ | |||
| 1 | /* | ||
| 2 | * uvc_queue.c -- USB Video Class driver - Buffers management | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2008 | ||
| 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/version.h> | ||
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/usb.h> | ||
| 19 | #include <linux/videodev2.h> | ||
| 20 | #include <linux/vmalloc.h> | ||
| 21 | #include <linux/wait.h> | ||
| 22 | #include <asm/atomic.h> | ||
| 23 | |||
| 24 | #include "uvcvideo.h" | ||
| 25 | |||
| 26 | /* ------------------------------------------------------------------------ | ||
| 27 | * Video buffers queue management. | ||
| 28 | * | ||
| 29 | * Video queues is initialized by uvc_queue_init(). The function performs | ||
| 30 | * basic initialization of the uvc_video_queue struct and never fails. | ||
| 31 | * | ||
| 32 | * Video buffer allocation and freeing are performed by uvc_alloc_buffers and | ||
| 33 | * uvc_free_buffers respectively. The former acquires the video queue lock, | ||
| 34 | * while the later must be called with the lock held (so that allocation can | ||
| 35 | * free previously allocated buffers). Trying to free buffers that are mapped | ||
| 36 | * to user space will return -EBUSY. | ||
| 37 | * | ||
| 38 | * Video buffers are managed using two queues. However, unlike most USB video | ||
| 39 | * drivers which use an in queue and an out queue, we use a main queue which | ||
| 40 | * holds all queued buffers (both 'empty' and 'done' buffers), and an irq | ||
| 41 | * queue which holds empty buffers. This design (copied from video-buf) | ||
| 42 | * minimizes locking in interrupt, as only one queue is shared between | ||
| 43 | * interrupt and user contexts. | ||
| 44 | * | ||
| 45 | * Use cases | ||
| 46 | * --------- | ||
| 47 | * | ||
| 48 | * Unless stated otherwise, all operations which modify the irq buffers queue | ||
| 49 | * are protected by the irq spinlock. | ||
| 50 | * | ||
| 51 | * 1. The user queues the buffers, starts streaming and dequeues a buffer. | ||
| 52 | * | ||
| 53 | * The buffers are added to the main and irq queues. Both operations are | ||
| 54 | * protected by the queue lock, and the latert is protected by the irq | ||
| 55 | * spinlock as well. | ||
| 56 | * | ||
| 57 | * The completion handler fetches a buffer from the irq queue and fills it | ||
| 58 | * with video data. If no buffer is available (irq queue empty), the handler | ||
| 59 | * returns immediately. | ||
| 60 | * | ||
| 61 | * When the buffer is full, the completion handler removes it from the irq | ||
| 62 | * queue, marks it as ready (UVC_BUF_STATE_DONE) and wake its wait queue. | ||
| 63 | * At that point, any process waiting on the buffer will be woken up. If a | ||
| 64 | * process tries to dequeue a buffer after it has been marked ready, the | ||
| 65 | * dequeing will succeed immediately. | ||
| 66 | * | ||
| 67 | * 2. Buffers are queued, user is waiting on a buffer and the device gets | ||
| 68 | * disconnected. | ||
| 69 | * | ||
| 70 | * When the device is disconnected, the kernel calls the completion handler | ||
| 71 | * with an appropriate status code. The handler marks all buffers in the | ||
| 72 | * irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so | ||
| 73 | * that any process waiting on a buffer gets woken up. | ||
| 74 | * | ||
| 75 | * Waking up up the first buffer on the irq list is not enough, as the | ||
| 76 | * process waiting on the buffer might restart the dequeue operation | ||
| 77 | * immediately. | ||
| 78 | * | ||
| 79 | */ | ||
| 80 | |||
| 81 | void uvc_queue_init(struct uvc_video_queue *queue) | ||
| 82 | { | ||
| 83 | mutex_init(&queue->mutex); | ||
| 84 | spin_lock_init(&queue->irqlock); | ||
| 85 | INIT_LIST_HEAD(&queue->mainqueue); | ||
| 86 | INIT_LIST_HEAD(&queue->irqqueue); | ||
| 87 | } | ||
| 88 | |||
| 89 | /* | ||
| 90 | * Allocate the video buffers. | ||
| 91 | * | ||
| 92 | * Pages are reserved to make sure they will not be swaped, as they will be | ||
| 93 | * filled in URB completion handler. | ||
| 94 | * | ||
| 95 | * Buffers will be individually mapped, so they must all be page aligned. | ||
| 96 | */ | ||
| 97 | int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, | ||
| 98 | unsigned int buflength) | ||
| 99 | { | ||
| 100 | unsigned int bufsize = PAGE_ALIGN(buflength); | ||
| 101 | unsigned int i; | ||
| 102 | void *mem = NULL; | ||
| 103 | int ret; | ||
| 104 | |||
| 105 | if (nbuffers > UVC_MAX_VIDEO_BUFFERS) | ||
| 106 | nbuffers = UVC_MAX_VIDEO_BUFFERS; | ||
| 107 | |||
| 108 | mutex_lock(&queue->mutex); | ||
| 109 | |||
| 110 | if ((ret = uvc_free_buffers(queue)) < 0) | ||
| 111 | goto done; | ||
| 112 | |||
| 113 | /* Bail out if no buffers should be allocated. */ | ||
| 114 | if (nbuffers == 0) | ||
| 115 | goto done; | ||
| 116 | |||
| 117 | /* Decrement the number of buffers until allocation succeeds. */ | ||
| 118 | for (; nbuffers > 0; --nbuffers) { | ||
| 119 | mem = vmalloc_32(nbuffers * bufsize); | ||
| 120 | if (mem != NULL) | ||
| 121 | break; | ||
| 122 | } | ||
| 123 | |||
| 124 | if (mem == NULL) { | ||
| 125 | ret = -ENOMEM; | ||
| 126 | goto done; | ||
| 127 | } | ||
| 128 | |||
| 129 | for (i = 0; i < nbuffers; ++i) { | ||
| 130 | memset(&queue->buffer[i], 0, sizeof queue->buffer[i]); | ||
| 131 | queue->buffer[i].buf.index = i; | ||
| 132 | queue->buffer[i].buf.m.offset = i * bufsize; | ||
| 133 | queue->buffer[i].buf.length = buflength; | ||
| 134 | queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 135 | queue->buffer[i].buf.sequence = 0; | ||
| 136 | queue->buffer[i].buf.field = V4L2_FIELD_NONE; | ||
| 137 | queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; | ||
| 138 | queue->buffer[i].buf.flags = 0; | ||
| 139 | init_waitqueue_head(&queue->buffer[i].wait); | ||
| 140 | } | ||
| 141 | |||
| 142 | queue->mem = mem; | ||
| 143 | queue->count = nbuffers; | ||
| 144 | queue->buf_size = bufsize; | ||
| 145 | ret = nbuffers; | ||
| 146 | |||
| 147 | done: | ||
| 148 | mutex_unlock(&queue->mutex); | ||
| 149 | return ret; | ||
| 150 | } | ||
| 151 | |||
| 152 | /* | ||
| 153 | * Free the video buffers. | ||
| 154 | * | ||
| 155 | * This function must be called with the queue lock held. | ||
| 156 | */ | ||
| 157 | int uvc_free_buffers(struct uvc_video_queue *queue) | ||
| 158 | { | ||
| 159 | unsigned int i; | ||
| 160 | |||
| 161 | for (i = 0; i < queue->count; ++i) { | ||
| 162 | if (queue->buffer[i].vma_use_count != 0) | ||
| 163 | return -EBUSY; | ||
| 164 | } | ||
| 165 | |||
| 166 | if (queue->count) { | ||
| 167 | vfree(queue->mem); | ||
| 168 | queue->count = 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static void __uvc_query_buffer(struct uvc_buffer *buf, | ||
| 175 | struct v4l2_buffer *v4l2_buf) | ||
| 176 | { | ||
| 177 | memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf); | ||
| 178 | |||
| 179 | if (buf->vma_use_count) | ||
| 180 | v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED; | ||
| 181 | |||
| 182 | switch (buf->state) { | ||
| 183 | case UVC_BUF_STATE_ERROR: | ||
| 184 | case UVC_BUF_STATE_DONE: | ||
| 185 | v4l2_buf->flags |= V4L2_BUF_FLAG_DONE; | ||
| 186 | break; | ||
| 187 | case UVC_BUF_STATE_QUEUED: | ||
| 188 | case UVC_BUF_STATE_ACTIVE: | ||
| 189 | v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; | ||
| 190 | break; | ||
| 191 | case UVC_BUF_STATE_IDLE: | ||
| 192 | default: | ||
| 193 | break; | ||
| 194 | } | ||
| 195 | } | ||
| 196 | |||
| 197 | int uvc_query_buffer(struct uvc_video_queue *queue, | ||
| 198 | struct v4l2_buffer *v4l2_buf) | ||
| 199 | { | ||
| 200 | int ret = 0; | ||
| 201 | |||
| 202 | mutex_lock(&queue->mutex); | ||
| 203 | if (v4l2_buf->index >= queue->count) { | ||
| 204 | ret = -EINVAL; | ||
| 205 | goto done; | ||
| 206 | } | ||
| 207 | |||
| 208 | __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); | ||
| 209 | |||
| 210 | done: | ||
| 211 | mutex_unlock(&queue->mutex); | ||
| 212 | return ret; | ||
| 213 | } | ||
| 214 | |||
| 215 | /* | ||
| 216 | * Queue a video buffer. Attempting to queue a buffer that has already been | ||
| 217 | * queued will return -EINVAL. | ||
| 218 | */ | ||
| 219 | int uvc_queue_buffer(struct uvc_video_queue *queue, | ||
| 220 | struct v4l2_buffer *v4l2_buf) | ||
| 221 | { | ||
| 222 | struct uvc_buffer *buf; | ||
| 223 | unsigned long flags; | ||
| 224 | int ret = 0; | ||
| 225 | |||
| 226 | uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index); | ||
| 227 | |||
| 228 | if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
| 229 | v4l2_buf->memory != V4L2_MEMORY_MMAP) { | ||
| 230 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " | ||
| 231 | "and/or memory (%u).\n", v4l2_buf->type, | ||
| 232 | v4l2_buf->memory); | ||
| 233 | return -EINVAL; | ||
| 234 | } | ||
| 235 | |||
| 236 | mutex_lock(&queue->mutex); | ||
| 237 | if (v4l2_buf->index >= queue->count) { | ||
| 238 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); | ||
| 239 | ret = -EINVAL; | ||
| 240 | goto done; | ||
| 241 | } | ||
| 242 | |||
| 243 | buf = &queue->buffer[v4l2_buf->index]; | ||
| 244 | if (buf->state != UVC_BUF_STATE_IDLE) { | ||
| 245 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state " | ||
| 246 | "(%u).\n", buf->state); | ||
| 247 | ret = -EINVAL; | ||
| 248 | goto done; | ||
| 249 | } | ||
| 250 | |||
| 251 | spin_lock_irqsave(&queue->irqlock, flags); | ||
| 252 | if (queue->flags & UVC_QUEUE_DISCONNECTED) { | ||
| 253 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
| 254 | ret = -ENODEV; | ||
| 255 | goto done; | ||
| 256 | } | ||
| 257 | buf->state = UVC_BUF_STATE_QUEUED; | ||
| 258 | buf->buf.bytesused = 0; | ||
| 259 | list_add_tail(&buf->stream, &queue->mainqueue); | ||
| 260 | list_add_tail(&buf->queue, &queue->irqqueue); | ||
| 261 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
| 262 | |||
| 263 | done: | ||
| 264 | mutex_unlock(&queue->mutex); | ||
| 265 | return ret; | ||
| 266 | } | ||
| 267 | |||
| 268 | static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) | ||
| 269 | { | ||
| 270 | if (nonblocking) { | ||
| 271 | return (buf->state != UVC_BUF_STATE_QUEUED && | ||
| 272 | buf->state != UVC_BUF_STATE_ACTIVE) | ||
| 273 | ? 0 : -EAGAIN; | ||
| 274 | } | ||
| 275 | |||
| 276 | return wait_event_interruptible(buf->wait, | ||
| 277 | buf->state != UVC_BUF_STATE_QUEUED && | ||
| 278 | buf->state != UVC_BUF_STATE_ACTIVE); | ||
| 279 | } | ||
| 280 | |||
| 281 | /* | ||
| 282 | * Dequeue a video buffer. If nonblocking is false, block until a buffer is | ||
| 283 | * available. | ||
| 284 | */ | ||
| 285 | int uvc_dequeue_buffer(struct uvc_video_queue *queue, | ||
| 286 | struct v4l2_buffer *v4l2_buf, int nonblocking) | ||
| 287 | { | ||
| 288 | struct uvc_buffer *buf; | ||
| 289 | int ret = 0; | ||
| 290 | |||
| 291 | if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
| 292 | v4l2_buf->memory != V4L2_MEMORY_MMAP) { | ||
| 293 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " | ||
| 294 | "and/or memory (%u).\n", v4l2_buf->type, | ||
| 295 | v4l2_buf->memory); | ||
| 296 | return -EINVAL; | ||
| 297 | } | ||
| 298 | |||
| 299 | mutex_lock(&queue->mutex); | ||
| 300 | if (list_empty(&queue->mainqueue)) { | ||
| 301 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n"); | ||
| 302 | ret = -EINVAL; | ||
| 303 | goto done; | ||
| 304 | } | ||
| 305 | |||
| 306 | buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); | ||
| 307 | if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) | ||
| 308 | goto done; | ||
| 309 | |||
| 310 | uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n", | ||
| 311 | buf->buf.index, buf->state, buf->buf.bytesused); | ||
| 312 | |||
| 313 | switch (buf->state) { | ||
| 314 | case UVC_BUF_STATE_ERROR: | ||
| 315 | uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data " | ||
| 316 | "(transmission error).\n"); | ||
| 317 | ret = -EIO; | ||
| 318 | case UVC_BUF_STATE_DONE: | ||
| 319 | buf->state = UVC_BUF_STATE_IDLE; | ||
| 320 | break; | ||
| 321 | |||
| 322 | case UVC_BUF_STATE_IDLE: | ||
| 323 | case UVC_BUF_STATE_QUEUED: | ||
| 324 | case UVC_BUF_STATE_ACTIVE: | ||
| 325 | default: | ||
| 326 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " | ||
| 327 | "(driver bug?).\n", buf->state); | ||
| 328 | ret = -EINVAL; | ||
| 329 | goto done; | ||
| 330 | } | ||
| 331 | |||
| 332 | list_del(&buf->stream); | ||
| 333 | __uvc_query_buffer(buf, v4l2_buf); | ||
| 334 | |||
| 335 | done: | ||
| 336 | mutex_unlock(&queue->mutex); | ||
| 337 | return ret; | ||
| 338 | } | ||
| 339 | |||
| 340 | /* | ||
| 341 | * Poll the video queue. | ||
| 342 | * | ||
| 343 | * This function implements video queue polling and is intended to be used by | ||
| 344 | * the device poll handler. | ||
| 345 | */ | ||
| 346 | unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, | ||
| 347 | poll_table *wait) | ||
| 348 | { | ||
| 349 | struct uvc_buffer *buf; | ||
| 350 | unsigned int mask = 0; | ||
| 351 | |||
| 352 | mutex_lock(&queue->mutex); | ||
| 353 | if (list_empty(&queue->mainqueue)) { | ||
| 354 | mask |= POLLERR; | ||
| 355 | goto done; | ||
| 356 | } | ||
| 357 | buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); | ||
| 358 | |||
| 359 | poll_wait(file, &buf->wait, wait); | ||
| 360 | if (buf->state == UVC_BUF_STATE_DONE || | ||
| 361 | buf->state == UVC_BUF_STATE_ERROR) | ||
| 362 | mask |= POLLIN | POLLRDNORM; | ||
| 363 | |||
| 364 | done: | ||
| 365 | mutex_unlock(&queue->mutex); | ||
| 366 | return mask; | ||
| 367 | } | ||
| 368 | |||
| 369 | /* | ||
| 370 | * Enable or disable the video buffers queue. | ||
| 371 | * | ||
| 372 | * The queue must be enabled before starting video acquisition and must be | ||
| 373 | * disabled after stopping it. This ensures that the video buffers queue | ||
| 374 | * state can be properly initialized before buffers are accessed from the | ||
| 375 | * interrupt handler. | ||
| 376 | * | ||
| 377 | * Enabling the video queue initializes parameters (such as sequence number, | ||
| 378 | * sync pattern, ...). If the queue is already enabled, return -EBUSY. | ||
| 379 | * | ||
| 380 | * Disabling the video queue cancels the queue and removes all buffers from | ||
| 381 | * the main queue. | ||
| 382 | * | ||
| 383 | * This function can't be called from interrupt context. Use | ||
| 384 | * uvc_queue_cancel() instead. | ||
| 385 | */ | ||
| 386 | int uvc_queue_enable(struct uvc_video_queue *queue, int enable) | ||
| 387 | { | ||
| 388 | unsigned int i; | ||
| 389 | int ret = 0; | ||
| 390 | |||
| 391 | mutex_lock(&queue->mutex); | ||
| 392 | if (enable) { | ||
| 393 | if (uvc_queue_streaming(queue)) { | ||
| 394 | ret = -EBUSY; | ||
| 395 | goto done; | ||
| 396 | } | ||
| 397 | queue->sequence = 0; | ||
| 398 | queue->flags |= UVC_QUEUE_STREAMING; | ||
| 399 | } else { | ||
| 400 | uvc_queue_cancel(queue, 0); | ||
| 401 | INIT_LIST_HEAD(&queue->mainqueue); | ||
| 402 | |||
| 403 | for (i = 0; i < queue->count; ++i) | ||
| 404 | queue->buffer[i].state = UVC_BUF_STATE_IDLE; | ||
| 405 | |||
| 406 | queue->flags &= ~UVC_QUEUE_STREAMING; | ||
| 407 | } | ||
| 408 | |||
| 409 | done: | ||
| 410 | mutex_unlock(&queue->mutex); | ||
| 411 | return ret; | ||
| 412 | } | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Cancel the video buffers queue. | ||
| 416 | * | ||
| 417 | * Cancelling the queue marks all buffers on the irq queue as erroneous, | ||
| 418 | * wakes them up and remove them from the queue. | ||
| 419 | * | ||
| 420 | * If the disconnect parameter is set, further calls to uvc_queue_buffer will | ||
| 421 | * fail with -ENODEV. | ||
| 422 | * | ||
| 423 | * This function acquires the irq spinlock and can be called from interrupt | ||
| 424 | * context. | ||
| 425 | */ | ||
| 426 | void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) | ||
| 427 | { | ||
| 428 | struct uvc_buffer *buf; | ||
| 429 | unsigned long flags; | ||
| 430 | |||
| 431 | spin_lock_irqsave(&queue->irqlock, flags); | ||
| 432 | while (!list_empty(&queue->irqqueue)) { | ||
| 433 | buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | ||
| 434 | queue); | ||
| 435 | list_del(&buf->queue); | ||
| 436 | buf->state = UVC_BUF_STATE_ERROR; | ||
| 437 | wake_up(&buf->wait); | ||
| 438 | } | ||
| 439 | /* This must be protected by the irqlock spinlock to avoid race | ||
| 440 | * conditions between uvc_queue_buffer and the disconnection event that | ||
| 441 | * could result in an interruptible wait in uvc_dequeue_buffer. Do not | ||
| 442 | * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED | ||
| 443 | * state outside the queue code. | ||
| 444 | */ | ||
| 445 | if (disconnect) | ||
| 446 | queue->flags |= UVC_QUEUE_DISCONNECTED; | ||
| 447 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
| 448 | } | ||
| 449 | |||
| 450 | struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | ||
| 451 | struct uvc_buffer *buf) | ||
| 452 | { | ||
| 453 | struct uvc_buffer *nextbuf; | ||
| 454 | unsigned long flags; | ||
| 455 | |||
| 456 | if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && | ||
| 457 | buf->buf.length != buf->buf.bytesused) { | ||
| 458 | buf->state = UVC_BUF_STATE_QUEUED; | ||
| 459 | buf->buf.bytesused = 0; | ||
| 460 | return buf; | ||
| 461 | } | ||
| 462 | |||
| 463 | spin_lock_irqsave(&queue->irqlock, flags); | ||
| 464 | list_del(&buf->queue); | ||
| 465 | if (!list_empty(&queue->irqqueue)) | ||
| 466 | nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | ||
| 467 | queue); | ||
| 468 | else | ||
| 469 | nextbuf = NULL; | ||
| 470 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
| 471 | |||
| 472 | buf->buf.sequence = queue->sequence++; | ||
| 473 | do_gettimeofday(&buf->buf.timestamp); | ||
| 474 | |||
| 475 | wake_up(&buf->wait); | ||
| 476 | return nextbuf; | ||
| 477 | } | ||
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c new file mode 100644 index 000000000000..be9084e5eace --- /dev/null +++ b/drivers/media/video/uvc/uvc_status.c | |||
| @@ -0,0 +1,207 @@ | |||
| 1 | /* | ||
| 2 | * uvc_status.c -- USB Video Class driver - Status endpoint | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007-2008 | ||
| 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/version.h> | ||
| 16 | #include <linux/input.h> | ||
| 17 | #include <linux/usb.h> | ||
| 18 | #include <linux/usb/input.h> | ||
| 19 | |||
| 20 | #include "uvcvideo.h" | ||
| 21 | |||
| 22 | /* -------------------------------------------------------------------------- | ||
| 23 | * Input device | ||
| 24 | */ | ||
| 25 | static int uvc_input_init(struct uvc_device *dev) | ||
| 26 | { | ||
| 27 | struct usb_device *udev = dev->udev; | ||
| 28 | struct input_dev *input; | ||
| 29 | char *phys = NULL; | ||
| 30 | int ret; | ||
| 31 | |||
| 32 | input = input_allocate_device(); | ||
| 33 | if (input == NULL) | ||
| 34 | return -ENOMEM; | ||
| 35 | |||
| 36 | phys = kmalloc(6 + strlen(udev->bus->bus_name) + strlen(udev->devpath), | ||
| 37 | GFP_KERNEL); | ||
| 38 | if (phys == NULL) { | ||
| 39 | ret = -ENOMEM; | ||
| 40 | goto error; | ||
| 41 | } | ||
| 42 | sprintf(phys, "usb-%s-%s", udev->bus->bus_name, udev->devpath); | ||
| 43 | |||
| 44 | input->name = dev->name; | ||
| 45 | input->phys = phys; | ||
| 46 | usb_to_input_id(udev, &input->id); | ||
| 47 | input->dev.parent = &dev->intf->dev; | ||
| 48 | |||
| 49 | set_bit(EV_KEY, input->evbit); | ||
| 50 | set_bit(BTN_0, input->keybit); | ||
| 51 | |||
| 52 | if ((ret = input_register_device(input)) < 0) | ||
| 53 | goto error; | ||
| 54 | |||
| 55 | dev->input = input; | ||
| 56 | return 0; | ||
| 57 | |||
| 58 | error: | ||
| 59 | input_free_device(input); | ||
| 60 | kfree(phys); | ||
| 61 | return ret; | ||
| 62 | } | ||
| 63 | |||
| 64 | static void uvc_input_cleanup(struct uvc_device *dev) | ||
| 65 | { | ||
| 66 | if (dev->input) | ||
| 67 | input_unregister_device(dev->input); | ||
| 68 | } | ||
| 69 | |||
| 70 | /* -------------------------------------------------------------------------- | ||
| 71 | * Status interrupt endpoint | ||
| 72 | */ | ||
| 73 | static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len) | ||
| 74 | { | ||
| 75 | if (len < 3) { | ||
| 76 | uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event " | ||
| 77 | "received.\n"); | ||
| 78 | return; | ||
| 79 | } | ||
| 80 | |||
| 81 | if (data[2] == 0) { | ||
| 82 | if (len < 4) | ||
| 83 | return; | ||
| 84 | uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n", | ||
| 85 | data[1], data[3] ? "pressed" : "released", len); | ||
| 86 | if (dev->input) | ||
| 87 | input_report_key(dev->input, BTN_0, data[3]); | ||
| 88 | } else { | ||
| 89 | uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x " | ||
| 90 | "len %d.\n", data[1], data[2], data[3], len); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | static void uvc_event_control(struct uvc_device *dev, __u8 *data, int len) | ||
| 95 | { | ||
| 96 | char *attrs[3] = { "value", "info", "failure" }; | ||
| 97 | |||
| 98 | if (len < 6 || data[2] != 0 || data[4] > 2) { | ||
| 99 | uvc_trace(UVC_TRACE_STATUS, "Invalid control status event " | ||
| 100 | "received.\n"); | ||
| 101 | return; | ||
| 102 | } | ||
| 103 | |||
| 104 | uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n", | ||
| 105 | data[1], data[3], attrs[data[4]], len); | ||
| 106 | } | ||
| 107 | |||
| 108 | static void uvc_status_complete(struct urb *urb) | ||
| 109 | { | ||
| 110 | struct uvc_device *dev = urb->context; | ||
| 111 | int len, ret; | ||
| 112 | |||
| 113 | switch (urb->status) { | ||
| 114 | case 0: | ||
| 115 | break; | ||
| 116 | |||
| 117 | case -ENOENT: /* usb_kill_urb() called. */ | ||
| 118 | case -ECONNRESET: /* usb_unlink_urb() called. */ | ||
| 119 | case -ESHUTDOWN: /* The endpoint is being disabled. */ | ||
| 120 | case -EPROTO: /* Device is disconnected (reported by some | ||
| 121 | * host controller). */ | ||
| 122 | return; | ||
| 123 | |||
| 124 | default: | ||
| 125 | uvc_printk(KERN_WARNING, "Non-zero status (%d) in status " | ||
| 126 | "completion handler.\n", urb->status); | ||
| 127 | return; | ||
| 128 | } | ||
| 129 | |||
| 130 | len = urb->actual_length; | ||
| 131 | if (len > 0) { | ||
| 132 | switch (dev->status[0] & 0x0f) { | ||
| 133 | case UVC_STATUS_TYPE_CONTROL: | ||
| 134 | uvc_event_control(dev, dev->status, len); | ||
| 135 | break; | ||
| 136 | |||
| 137 | case UVC_STATUS_TYPE_STREAMING: | ||
| 138 | uvc_event_streaming(dev, dev->status, len); | ||
| 139 | break; | ||
| 140 | |||
| 141 | default: | ||
| 142 | uvc_printk(KERN_INFO, "unknown event type %u.\n", | ||
| 143 | dev->status[0]); | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | /* Resubmit the URB. */ | ||
| 149 | urb->interval = dev->int_ep->desc.bInterval; | ||
| 150 | if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { | ||
| 151 | uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n", | ||
| 152 | ret); | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | int uvc_status_init(struct uvc_device *dev) | ||
| 157 | { | ||
| 158 | struct usb_host_endpoint *ep = dev->int_ep; | ||
| 159 | unsigned int pipe; | ||
| 160 | int interval; | ||
| 161 | |||
| 162 | if (ep == NULL) | ||
| 163 | return 0; | ||
| 164 | |||
| 165 | uvc_input_init(dev); | ||
| 166 | |||
| 167 | dev->int_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 168 | if (dev->int_urb == NULL) | ||
| 169 | return -ENOMEM; | ||
| 170 | |||
| 171 | pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); | ||
| 172 | |||
| 173 | /* For high-speed interrupt endpoints, the bInterval value is used as | ||
| 174 | * an exponent of two. Some developers forgot about it. | ||
| 175 | */ | ||
| 176 | interval = ep->desc.bInterval; | ||
| 177 | if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH && | ||
| 178 | (dev->quirks & UVC_QUIRK_STATUS_INTERVAL)) | ||
| 179 | interval = fls(interval) - 1; | ||
| 180 | |||
| 181 | usb_fill_int_urb(dev->int_urb, dev->udev, pipe, | ||
| 182 | dev->status, sizeof dev->status, uvc_status_complete, | ||
| 183 | dev, interval); | ||
| 184 | |||
| 185 | return usb_submit_urb(dev->int_urb, GFP_KERNEL); | ||
| 186 | } | ||
| 187 | |||
| 188 | void uvc_status_cleanup(struct uvc_device *dev) | ||
| 189 | { | ||
| 190 | usb_kill_urb(dev->int_urb); | ||
| 191 | usb_free_urb(dev->int_urb); | ||
| 192 | uvc_input_cleanup(dev); | ||
| 193 | } | ||
| 194 | |||
| 195 | int uvc_status_suspend(struct uvc_device *dev) | ||
| 196 | { | ||
| 197 | usb_kill_urb(dev->int_urb); | ||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | int uvc_status_resume(struct uvc_device *dev) | ||
| 202 | { | ||
| 203 | if (dev->int_urb == NULL) | ||
| 204 | return 0; | ||
| 205 | |||
| 206 | return usb_submit_urb(dev->int_urb, GFP_KERNEL); | ||
| 207 | } | ||
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c new file mode 100644 index 000000000000..2e0a66575bb4 --- /dev/null +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
| @@ -0,0 +1,1105 @@ | |||
| 1 | /* | ||
| 2 | * uvc_v4l2.c -- USB Video Class driver - V4L2 API | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2008 | ||
| 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/version.h> | ||
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/usb.h> | ||
| 19 | #include <linux/videodev2.h> | ||
| 20 | #include <linux/vmalloc.h> | ||
| 21 | #include <linux/mm.h> | ||
| 22 | #include <linux/wait.h> | ||
| 23 | #include <asm/atomic.h> | ||
| 24 | |||
| 25 | #include <media/v4l2-common.h> | ||
| 26 | |||
| 27 | #include "uvcvideo.h" | ||
| 28 | |||
| 29 | /* ------------------------------------------------------------------------ | ||
| 30 | * V4L2 interface | ||
| 31 | */ | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Mapping V4L2 controls to UVC controls can be straighforward if done well. | ||
| 35 | * Most of the UVC controls exist in V4L2, and can be mapped directly. Some | ||
| 36 | * must be grouped (for instance the Red Balance, Blue Balance and Do White | ||
| 37 | * Balance V4L2 controls use the White Balance Component UVC control) or | ||
| 38 | * otherwise translated. The approach we take here is to use a translation | ||
| 39 | * table for the controls which can be mapped directly, and handle the others | ||
| 40 | * manually. | ||
| 41 | */ | ||
| 42 | static int uvc_v4l2_query_menu(struct uvc_video_device *video, | ||
| 43 | struct v4l2_querymenu *query_menu) | ||
| 44 | { | ||
| 45 | struct uvc_menu_info *menu_info; | ||
| 46 | struct uvc_control_mapping *mapping; | ||
| 47 | struct uvc_control *ctrl; | ||
| 48 | |||
| 49 | ctrl = uvc_find_control(video, query_menu->id, &mapping); | ||
| 50 | if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) | ||
| 51 | return -EINVAL; | ||
| 52 | |||
| 53 | if (query_menu->index >= mapping->menu_count) | ||
| 54 | return -EINVAL; | ||
| 55 | |||
| 56 | menu_info = &mapping->menu_info[query_menu->index]; | ||
| 57 | strncpy(query_menu->name, menu_info->name, 32); | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | /* | ||
| 62 | * Find the frame interval closest to the requested frame interval for the | ||
| 63 | * given frame format and size. This should be done by the device as part of | ||
| 64 | * the Video Probe and Commit negotiation, but some hardware don't implement | ||
| 65 | * that feature. | ||
| 66 | */ | ||
| 67 | static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval) | ||
| 68 | { | ||
| 69 | unsigned int i; | ||
| 70 | |||
| 71 | if (frame->bFrameIntervalType) { | ||
| 72 | __u32 best = -1, dist; | ||
| 73 | |||
| 74 | for (i = 0; i < frame->bFrameIntervalType; ++i) { | ||
| 75 | dist = interval > frame->dwFrameInterval[i] | ||
| 76 | ? interval - frame->dwFrameInterval[i] | ||
| 77 | : frame->dwFrameInterval[i] - interval; | ||
| 78 | |||
| 79 | if (dist > best) | ||
| 80 | break; | ||
| 81 | |||
| 82 | best = dist; | ||
| 83 | } | ||
| 84 | |||
| 85 | interval = frame->dwFrameInterval[i-1]; | ||
| 86 | } else { | ||
| 87 | const __u32 min = frame->dwFrameInterval[0]; | ||
| 88 | const __u32 max = frame->dwFrameInterval[1]; | ||
| 89 | const __u32 step = frame->dwFrameInterval[2]; | ||
| 90 | |||
| 91 | interval = min + (interval - min + step/2) / step * step; | ||
| 92 | if (interval > max) | ||
| 93 | interval = max; | ||
| 94 | } | ||
| 95 | |||
| 96 | return interval; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int uvc_v4l2_try_format(struct uvc_video_device *video, | ||
| 100 | struct v4l2_format *fmt, struct uvc_streaming_control *probe, | ||
| 101 | struct uvc_format **uvc_format, struct uvc_frame **uvc_frame) | ||
| 102 | { | ||
| 103 | struct uvc_format *format = NULL; | ||
| 104 | struct uvc_frame *frame = NULL; | ||
| 105 | __u16 rw, rh; | ||
| 106 | unsigned int d, maxd; | ||
| 107 | unsigned int i; | ||
| 108 | __u32 interval; | ||
| 109 | int ret = 0; | ||
| 110 | __u8 *fcc; | ||
| 111 | |||
| 112 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 113 | return -EINVAL; | ||
| 114 | |||
| 115 | fcc = (__u8 *)&fmt->fmt.pix.pixelformat; | ||
| 116 | uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n", | ||
| 117 | fmt->fmt.pix.pixelformat, | ||
| 118 | fcc[0], fcc[1], fcc[2], fcc[3], | ||
| 119 | fmt->fmt.pix.width, fmt->fmt.pix.height); | ||
| 120 | |||
| 121 | /* Check if the hardware supports the requested format. */ | ||
| 122 | for (i = 0; i < video->streaming->nformats; ++i) { | ||
| 123 | format = &video->streaming->format[i]; | ||
| 124 | if (format->fcc == fmt->fmt.pix.pixelformat) | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | |||
| 128 | if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) { | ||
| 129 | uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n", | ||
| 130 | fmt->fmt.pix.pixelformat); | ||
| 131 | return -EINVAL; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* Find the closest image size. The distance between image sizes is | ||
| 135 | * the size in pixels of the non-overlapping regions between the | ||
| 136 | * requested size and the frame-specified size. | ||
| 137 | */ | ||
| 138 | rw = fmt->fmt.pix.width; | ||
| 139 | rh = fmt->fmt.pix.height; | ||
| 140 | maxd = (unsigned int)-1; | ||
| 141 | |||
| 142 | for (i = 0; i < format->nframes; ++i) { | ||
| 143 | __u16 w = format->frame[i].wWidth; | ||
| 144 | __u16 h = format->frame[i].wHeight; | ||
| 145 | |||
| 146 | d = min(w, rw) * min(h, rh); | ||
| 147 | d = w*h + rw*rh - 2*d; | ||
| 148 | if (d < maxd) { | ||
| 149 | maxd = d; | ||
| 150 | frame = &format->frame[i]; | ||
| 151 | } | ||
| 152 | |||
| 153 | if (maxd == 0) | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (frame == NULL) { | ||
| 158 | uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n", | ||
| 159 | fmt->fmt.pix.width, fmt->fmt.pix.height); | ||
| 160 | return -EINVAL; | ||
| 161 | } | ||
| 162 | |||
| 163 | /* Use the default frame interval. */ | ||
| 164 | interval = frame->dwDefaultFrameInterval; | ||
| 165 | uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us " | ||
| 166 | "(%u.%u fps).\n", interval/10, interval%10, 10000000/interval, | ||
| 167 | (100000000/interval)%10); | ||
| 168 | |||
| 169 | /* Set the format index, frame index and frame interval. */ | ||
| 170 | memset(probe, 0, sizeof *probe); | ||
| 171 | probe->bmHint = 1; /* dwFrameInterval */ | ||
| 172 | probe->bFormatIndex = format->index; | ||
| 173 | probe->bFrameIndex = frame->bFrameIndex; | ||
| 174 | probe->dwFrameInterval = uvc_try_frame_interval(frame, interval); | ||
| 175 | /* Some webcams stall the probe control set request when the | ||
| 176 | * dwMaxVideoFrameSize field is set to zero. The UVC specification | ||
| 177 | * clearly states that the field is read-only from the host, so this | ||
| 178 | * is a webcam bug. Set dwMaxVideoFrameSize to the value reported by | ||
| 179 | * the webcam to work around the problem. | ||
| 180 | * | ||
| 181 | * The workaround could probably be enabled for all webcams, so the | ||
| 182 | * quirk can be removed if needed. It's currently useful to detect | ||
| 183 | * webcam bugs and fix them before they hit the market (providing | ||
| 184 | * developers test their webcams with the Linux driver as well as with | ||
| 185 | * the Windows driver). | ||
| 186 | */ | ||
| 187 | if (video->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) | ||
| 188 | probe->dwMaxVideoFrameSize = | ||
| 189 | video->streaming->ctrl.dwMaxVideoFrameSize; | ||
| 190 | |||
| 191 | /* Probe the device */ | ||
| 192 | if ((ret = uvc_probe_video(video, probe)) < 0) | ||
| 193 | goto done; | ||
| 194 | |||
| 195 | fmt->fmt.pix.width = frame->wWidth; | ||
| 196 | fmt->fmt.pix.height = frame->wHeight; | ||
| 197 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
| 198 | fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8; | ||
| 199 | fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize; | ||
| 200 | fmt->fmt.pix.colorspace = format->colorspace; | ||
| 201 | fmt->fmt.pix.priv = 0; | ||
| 202 | |||
| 203 | if (uvc_format != NULL) | ||
| 204 | *uvc_format = format; | ||
| 205 | if (uvc_frame != NULL) | ||
| 206 | *uvc_frame = frame; | ||
| 207 | |||
| 208 | done: | ||
| 209 | return ret; | ||
| 210 | } | ||
| 211 | |||
| 212 | static int uvc_v4l2_get_format(struct uvc_video_device *video, | ||
| 213 | struct v4l2_format *fmt) | ||
| 214 | { | ||
| 215 | struct uvc_format *format = video->streaming->cur_format; | ||
| 216 | struct uvc_frame *frame = video->streaming->cur_frame; | ||
| 217 | |||
| 218 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 219 | return -EINVAL; | ||
| 220 | |||
| 221 | if (format == NULL || frame == NULL) | ||
| 222 | return -EINVAL; | ||
| 223 | |||
| 224 | fmt->fmt.pix.pixelformat = format->fcc; | ||
| 225 | fmt->fmt.pix.width = frame->wWidth; | ||
| 226 | fmt->fmt.pix.height = frame->wHeight; | ||
| 227 | fmt->fmt.pix.field = V4L2_FIELD_NONE; | ||
| 228 | fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8; | ||
| 229 | fmt->fmt.pix.sizeimage = video->streaming->ctrl.dwMaxVideoFrameSize; | ||
| 230 | fmt->fmt.pix.colorspace = format->colorspace; | ||
| 231 | fmt->fmt.pix.priv = 0; | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static int uvc_v4l2_set_format(struct uvc_video_device *video, | ||
| 237 | struct v4l2_format *fmt) | ||
| 238 | { | ||
| 239 | struct uvc_streaming_control probe; | ||
| 240 | struct uvc_format *format; | ||
| 241 | struct uvc_frame *frame; | ||
| 242 | int ret; | ||
| 243 | |||
| 244 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 245 | return -EINVAL; | ||
| 246 | |||
| 247 | if (uvc_queue_streaming(&video->queue)) | ||
| 248 | return -EBUSY; | ||
| 249 | |||
| 250 | ret = uvc_v4l2_try_format(video, fmt, &probe, &format, &frame); | ||
| 251 | if (ret < 0) | ||
| 252 | return ret; | ||
| 253 | |||
| 254 | if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) | ||
| 255 | return ret; | ||
| 256 | |||
| 257 | memcpy(&video->streaming->ctrl, &probe, sizeof probe); | ||
| 258 | video->streaming->cur_format = format; | ||
| 259 | video->streaming->cur_frame = frame; | ||
| 260 | |||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int uvc_v4l2_get_streamparm(struct uvc_video_device *video, | ||
| 265 | struct v4l2_streamparm *parm) | ||
| 266 | { | ||
| 267 | uint32_t numerator, denominator; | ||
| 268 | |||
| 269 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 270 | return -EINVAL; | ||
| 271 | |||
| 272 | numerator = video->streaming->ctrl.dwFrameInterval; | ||
| 273 | denominator = 10000000; | ||
| 274 | uvc_simplify_fraction(&numerator, &denominator, 8, 333); | ||
| 275 | |||
| 276 | memset(parm, 0, sizeof *parm); | ||
| 277 | parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
| 278 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; | ||
| 279 | parm->parm.capture.capturemode = 0; | ||
| 280 | parm->parm.capture.timeperframe.numerator = numerator; | ||
| 281 | parm->parm.capture.timeperframe.denominator = denominator; | ||
| 282 | parm->parm.capture.extendedmode = 0; | ||
| 283 | parm->parm.capture.readbuffers = 0; | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int uvc_v4l2_set_streamparm(struct uvc_video_device *video, | ||
| 289 | struct v4l2_streamparm *parm) | ||
| 290 | { | ||
| 291 | struct uvc_frame *frame = video->streaming->cur_frame; | ||
| 292 | struct uvc_streaming_control probe; | ||
| 293 | uint32_t interval; | ||
| 294 | int ret; | ||
| 295 | |||
| 296 | if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 297 | return -EINVAL; | ||
| 298 | |||
| 299 | if (uvc_queue_streaming(&video->queue)) | ||
| 300 | return -EBUSY; | ||
| 301 | |||
| 302 | memcpy(&probe, &video->streaming->ctrl, sizeof probe); | ||
| 303 | interval = uvc_fraction_to_interval( | ||
| 304 | parm->parm.capture.timeperframe.numerator, | ||
| 305 | parm->parm.capture.timeperframe.denominator); | ||
| 306 | |||
| 307 | uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n", | ||
| 308 | parm->parm.capture.timeperframe.numerator, | ||
| 309 | parm->parm.capture.timeperframe.denominator, | ||
| 310 | interval); | ||
| 311 | probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); | ||
| 312 | |||
| 313 | /* Probe the device with the new settings. */ | ||
| 314 | if ((ret = uvc_probe_video(video, &probe)) < 0) | ||
| 315 | return ret; | ||
| 316 | |||
| 317 | /* Commit the new settings. */ | ||
| 318 | if ((ret = uvc_set_video_ctrl(video, &probe, 0)) < 0) | ||
| 319 | return ret; | ||
| 320 | |||
| 321 | memcpy(&video->streaming->ctrl, &probe, sizeof probe); | ||
| 322 | |||
| 323 | /* Return the actual frame period. */ | ||
| 324 | parm->parm.capture.timeperframe.numerator = probe.dwFrameInterval; | ||
| 325 | parm->parm.capture.timeperframe.denominator = 10000000; | ||
| 326 | uvc_simplify_fraction(&parm->parm.capture.timeperframe.numerator, | ||
| 327 | &parm->parm.capture.timeperframe.denominator, | ||
| 328 | 8, 333); | ||
| 329 | |||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | |||
| 333 | /* ------------------------------------------------------------------------ | ||
| 334 | * Privilege management | ||
| 335 | */ | ||
| 336 | |||
| 337 | /* | ||
| 338 | * Privilege management is the multiple-open implementation basis. The current | ||
| 339 | * implementation is completely transparent for the end-user and doesn't | ||
| 340 | * require explicit use of the VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY ioctls. | ||
| 341 | * Those ioctls enable finer control on the device (by making possible for a | ||
| 342 | * user to request exclusive access to a device), but are not mature yet. | ||
| 343 | * Switching to the V4L2 priority mechanism might be considered in the future | ||
| 344 | * if this situation changes. | ||
| 345 | * | ||
| 346 | * Each open instance of a UVC device can either be in a privileged or | ||
| 347 | * unprivileged state. Only a single instance can be in a privileged state at | ||
| 348 | * a given time. Trying to perform an operation which requires privileges will | ||
| 349 | * automatically acquire the required privileges if possible, or return -EBUSY | ||
| 350 | * otherwise. Privileges are dismissed when closing the instance. | ||
| 351 | * | ||
| 352 | * Operations which require privileges are: | ||
| 353 | * | ||
| 354 | * - VIDIOC_S_INPUT | ||
| 355 | * - VIDIOC_S_PARM | ||
| 356 | * - VIDIOC_S_FMT | ||
| 357 | * - VIDIOC_TRY_FMT | ||
| 358 | * - VIDIOC_REQBUFS | ||
| 359 | */ | ||
| 360 | static int uvc_acquire_privileges(struct uvc_fh *handle) | ||
| 361 | { | ||
| 362 | int ret = 0; | ||
| 363 | |||
| 364 | /* Always succeed if the handle is already privileged. */ | ||
| 365 | if (handle->state == UVC_HANDLE_ACTIVE) | ||
| 366 | return 0; | ||
| 367 | |||
| 368 | /* Check if the device already has a privileged handle. */ | ||
| 369 | mutex_lock(&uvc_driver.open_mutex); | ||
| 370 | if (atomic_inc_return(&handle->device->active) != 1) { | ||
| 371 | atomic_dec(&handle->device->active); | ||
| 372 | ret = -EBUSY; | ||
| 373 | goto done; | ||
| 374 | } | ||
| 375 | |||
| 376 | handle->state = UVC_HANDLE_ACTIVE; | ||
| 377 | |||
| 378 | done: | ||
| 379 | mutex_unlock(&uvc_driver.open_mutex); | ||
| 380 | return ret; | ||
| 381 | } | ||
| 382 | |||
| 383 | static void uvc_dismiss_privileges(struct uvc_fh *handle) | ||
| 384 | { | ||
| 385 | if (handle->state == UVC_HANDLE_ACTIVE) | ||
| 386 | atomic_dec(&handle->device->active); | ||
| 387 | |||
| 388 | handle->state = UVC_HANDLE_PASSIVE; | ||
| 389 | } | ||
| 390 | |||
| 391 | static int uvc_has_privileges(struct uvc_fh *handle) | ||
| 392 | { | ||
| 393 | return handle->state == UVC_HANDLE_ACTIVE; | ||
| 394 | } | ||
| 395 | |||
| 396 | /* ------------------------------------------------------------------------ | ||
| 397 | * V4L2 file operations | ||
| 398 | */ | ||
| 399 | |||
| 400 | static int uvc_v4l2_open(struct inode *inode, struct file *file) | ||
| 401 | { | ||
| 402 | struct video_device *vdev; | ||
| 403 | struct uvc_video_device *video; | ||
| 404 | struct uvc_fh *handle; | ||
| 405 | int ret = 0; | ||
| 406 | |||
| 407 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n"); | ||
| 408 | mutex_lock(&uvc_driver.open_mutex); | ||
| 409 | vdev = video_devdata(file); | ||
| 410 | video = video_get_drvdata(vdev); | ||
| 411 | |||
| 412 | if (video->dev->state & UVC_DEV_DISCONNECTED) { | ||
| 413 | ret = -ENODEV; | ||
| 414 | goto done; | ||
| 415 | } | ||
| 416 | |||
| 417 | ret = usb_autopm_get_interface(video->dev->intf); | ||
| 418 | if (ret < 0) | ||
| 419 | goto done; | ||
| 420 | |||
| 421 | /* Create the device handle. */ | ||
| 422 | handle = kzalloc(sizeof *handle, GFP_KERNEL); | ||
| 423 | if (handle == NULL) { | ||
| 424 | usb_autopm_put_interface(video->dev->intf); | ||
| 425 | ret = -ENOMEM; | ||
| 426 | goto done; | ||
| 427 | } | ||
| 428 | |||
| 429 | handle->device = video; | ||
| 430 | handle->state = UVC_HANDLE_PASSIVE; | ||
| 431 | file->private_data = handle; | ||
| 432 | |||
| 433 | kref_get(&video->dev->kref); | ||
| 434 | |||
| 435 | done: | ||
| 436 | mutex_unlock(&uvc_driver.open_mutex); | ||
| 437 | return ret; | ||
| 438 | } | ||
| 439 | |||
| 440 | static int uvc_v4l2_release(struct inode *inode, struct file *file) | ||
| 441 | { | ||
| 442 | struct video_device *vdev = video_devdata(file); | ||
| 443 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
| 444 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | ||
| 445 | |||
| 446 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); | ||
| 447 | |||
| 448 | /* Only free resources if this is a privileged handle. */ | ||
| 449 | if (uvc_has_privileges(handle)) { | ||
| 450 | uvc_video_enable(video, 0); | ||
| 451 | |||
| 452 | mutex_lock(&video->queue.mutex); | ||
| 453 | if (uvc_free_buffers(&video->queue) < 0) | ||
| 454 | uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to " | ||
| 455 | "free buffers.\n"); | ||
| 456 | mutex_unlock(&video->queue.mutex); | ||
| 457 | } | ||
| 458 | |||
| 459 | /* Release the file handle. */ | ||
| 460 | uvc_dismiss_privileges(handle); | ||
| 461 | kfree(handle); | ||
| 462 | file->private_data = NULL; | ||
| 463 | |||
| 464 | usb_autopm_put_interface(video->dev->intf); | ||
| 465 | kref_put(&video->dev->kref, uvc_delete); | ||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, | ||
| 470 | unsigned int cmd, void *arg) | ||
| 471 | { | ||
| 472 | struct video_device *vdev = video_devdata(file); | ||
| 473 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
| 474 | struct uvc_fh *handle = (struct uvc_fh *)file->private_data; | ||
| 475 | int ret = 0; | ||
| 476 | |||
| 477 | if (uvc_trace_param & UVC_TRACE_IOCTL) | ||
| 478 | v4l_printk_ioctl(cmd); | ||
| 479 | |||
| 480 | switch (cmd) { | ||
| 481 | /* Query capabilities */ | ||
| 482 | case VIDIOC_QUERYCAP: | ||
| 483 | { | ||
| 484 | struct v4l2_capability *cap = arg; | ||
| 485 | |||
| 486 | memset(cap, 0, sizeof *cap); | ||
| 487 | strncpy(cap->driver, "uvcvideo", sizeof cap->driver); | ||
| 488 | strncpy(cap->card, vdev->name, 32); | ||
| 489 | strncpy(cap->bus_info, video->dev->udev->bus->bus_name, | ||
| 490 | sizeof cap->bus_info); | ||
| 491 | cap->version = DRIVER_VERSION_NUMBER; | ||
| 492 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | ||
| 493 | | V4L2_CAP_STREAMING; | ||
| 494 | break; | ||
| 495 | } | ||
| 496 | |||
| 497 | /* Get, Set & Query control */ | ||
| 498 | case VIDIOC_QUERYCTRL: | ||
| 499 | return uvc_query_v4l2_ctrl(video, arg); | ||
| 500 | |||
| 501 | case VIDIOC_G_CTRL: | ||
| 502 | { | ||
| 503 | struct v4l2_control *ctrl = arg; | ||
| 504 | struct v4l2_ext_control xctrl; | ||
| 505 | |||
| 506 | memset(&xctrl, 0, sizeof xctrl); | ||
| 507 | xctrl.id = ctrl->id; | ||
| 508 | |||
| 509 | uvc_ctrl_begin(video); | ||
| 510 | ret = uvc_ctrl_get(video, &xctrl); | ||
| 511 | uvc_ctrl_rollback(video); | ||
| 512 | if (ret >= 0) | ||
| 513 | ctrl->value = xctrl.value; | ||
| 514 | break; | ||
| 515 | } | ||
| 516 | |||
| 517 | case VIDIOC_S_CTRL: | ||
| 518 | { | ||
| 519 | struct v4l2_control *ctrl = arg; | ||
| 520 | struct v4l2_ext_control xctrl; | ||
| 521 | |||
| 522 | memset(&xctrl, 0, sizeof xctrl); | ||
| 523 | xctrl.id = ctrl->id; | ||
| 524 | xctrl.value = ctrl->value; | ||
| 525 | |||
| 526 | uvc_ctrl_begin(video); | ||
| 527 | ret = uvc_ctrl_set(video, &xctrl); | ||
| 528 | if (ret < 0) { | ||
| 529 | uvc_ctrl_rollback(video); | ||
| 530 | return ret; | ||
| 531 | } | ||
| 532 | ret = uvc_ctrl_commit(video); | ||
| 533 | break; | ||
| 534 | } | ||
| 535 | |||
| 536 | case VIDIOC_QUERYMENU: | ||
| 537 | return uvc_v4l2_query_menu(video, arg); | ||
| 538 | |||
| 539 | case VIDIOC_G_EXT_CTRLS: | ||
| 540 | { | ||
| 541 | struct v4l2_ext_controls *ctrls = arg; | ||
| 542 | struct v4l2_ext_control *ctrl = ctrls->controls; | ||
| 543 | unsigned int i; | ||
| 544 | |||
| 545 | uvc_ctrl_begin(video); | ||
| 546 | for (i = 0; i < ctrls->count; ++ctrl, ++i) { | ||
| 547 | ret = uvc_ctrl_get(video, ctrl); | ||
| 548 | if (ret < 0) { | ||
| 549 | uvc_ctrl_rollback(video); | ||
| 550 | ctrls->error_idx = i; | ||
| 551 | return ret; | ||
| 552 | } | ||
| 553 | } | ||
| 554 | ctrls->error_idx = 0; | ||
| 555 | ret = uvc_ctrl_rollback(video); | ||
| 556 | break; | ||
| 557 | } | ||
| 558 | |||
| 559 | case VIDIOC_S_EXT_CTRLS: | ||
| 560 | case VIDIOC_TRY_EXT_CTRLS: | ||
| 561 | { | ||
| 562 | struct v4l2_ext_controls *ctrls = arg; | ||
| 563 | struct v4l2_ext_control *ctrl = ctrls->controls; | ||
| 564 | unsigned int i; | ||
| 565 | |||
| 566 | ret = uvc_ctrl_begin(video); | ||
| 567 | if (ret < 0) | ||
| 568 | return ret; | ||
| 569 | |||
| 570 | for (i = 0; i < ctrls->count; ++ctrl, ++i) { | ||
| 571 | ret = uvc_ctrl_set(video, ctrl); | ||
| 572 | if (ret < 0) { | ||
| 573 | uvc_ctrl_rollback(video); | ||
| 574 | ctrls->error_idx = i; | ||
| 575 | return ret; | ||
| 576 | } | ||
| 577 | } | ||
| 578 | |||
| 579 | ctrls->error_idx = 0; | ||
| 580 | |||
| 581 | if (cmd == VIDIOC_S_EXT_CTRLS) | ||
| 582 | ret = uvc_ctrl_commit(video); | ||
| 583 | else | ||
| 584 | ret = uvc_ctrl_rollback(video); | ||
| 585 | break; | ||
| 586 | } | ||
| 587 | |||
| 588 | /* Get, Set & Enum input */ | ||
| 589 | case VIDIOC_ENUMINPUT: | ||
| 590 | { | ||
| 591 | const struct uvc_entity *selector = video->selector; | ||
| 592 | struct v4l2_input *input = arg; | ||
| 593 | struct uvc_entity *iterm = NULL; | ||
| 594 | u32 index = input->index; | ||
| 595 | int pin = 0; | ||
| 596 | |||
| 597 | if (selector == NULL || | ||
| 598 | (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { | ||
| 599 | if (index != 0) | ||
| 600 | return -EINVAL; | ||
| 601 | iterm = list_first_entry(&video->iterms, | ||
| 602 | struct uvc_entity, chain); | ||
| 603 | pin = iterm->id; | ||
| 604 | } else if (pin < selector->selector.bNrInPins) { | ||
| 605 | pin = selector->selector.baSourceID[index]; | ||
| 606 | list_for_each_entry(iterm, video->iterms.next, chain) { | ||
| 607 | if (iterm->id == pin) | ||
| 608 | break; | ||
| 609 | } | ||
| 610 | } | ||
| 611 | |||
| 612 | if (iterm == NULL || iterm->id != pin) | ||
| 613 | return -EINVAL; | ||
| 614 | |||
| 615 | memset(input, 0, sizeof *input); | ||
| 616 | input->index = index; | ||
| 617 | strncpy(input->name, iterm->name, sizeof input->name); | ||
| 618 | if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA) | ||
| 619 | input->type = V4L2_INPUT_TYPE_CAMERA; | ||
| 620 | break; | ||
| 621 | } | ||
| 622 | |||
| 623 | case VIDIOC_G_INPUT: | ||
| 624 | { | ||
| 625 | u8 input; | ||
| 626 | |||
| 627 | if (video->selector == NULL || | ||
| 628 | (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { | ||
| 629 | *(int *)arg = 0; | ||
| 630 | break; | ||
| 631 | } | ||
| 632 | |||
| 633 | ret = uvc_query_ctrl(video->dev, GET_CUR, video->selector->id, | ||
| 634 | video->dev->intfnum, SU_INPUT_SELECT_CONTROL, | ||
| 635 | &input, 1); | ||
| 636 | if (ret < 0) | ||
| 637 | return ret; | ||
| 638 | |||
| 639 | *(int *)arg = input - 1; | ||
| 640 | break; | ||
| 641 | } | ||
| 642 | |||
| 643 | case VIDIOC_S_INPUT: | ||
| 644 | { | ||
| 645 | u8 input = *(u32 *)arg + 1; | ||
| 646 | |||
| 647 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
| 648 | return ret; | ||
| 649 | |||
| 650 | if (video->selector == NULL || | ||
| 651 | (video->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { | ||
| 652 | if (input != 1) | ||
| 653 | return -EINVAL; | ||
| 654 | break; | ||
| 655 | } | ||
| 656 | |||
| 657 | if (input > video->selector->selector.bNrInPins) | ||
| 658 | return -EINVAL; | ||
| 659 | |||
| 660 | return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id, | ||
| 661 | video->dev->intfnum, SU_INPUT_SELECT_CONTROL, | ||
| 662 | &input, 1); | ||
| 663 | } | ||
| 664 | |||
| 665 | /* Try, Get, Set & Enum format */ | ||
| 666 | case VIDIOC_ENUM_FMT: | ||
| 667 | { | ||
| 668 | struct v4l2_fmtdesc *fmt = arg; | ||
| 669 | struct uvc_format *format; | ||
| 670 | |||
| 671 | if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
| 672 | fmt->index >= video->streaming->nformats) | ||
| 673 | return -EINVAL; | ||
| 674 | |||
| 675 | format = &video->streaming->format[fmt->index]; | ||
| 676 | fmt->flags = 0; | ||
| 677 | if (format->flags & UVC_FMT_FLAG_COMPRESSED) | ||
| 678 | fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; | ||
| 679 | strncpy(fmt->description, format->name, | ||
| 680 | sizeof fmt->description); | ||
| 681 | fmt->description[sizeof fmt->description - 1] = 0; | ||
| 682 | fmt->pixelformat = format->fcc; | ||
| 683 | break; | ||
| 684 | } | ||
| 685 | |||
| 686 | case VIDIOC_TRY_FMT: | ||
| 687 | { | ||
| 688 | struct uvc_streaming_control probe; | ||
| 689 | |||
| 690 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
| 691 | return ret; | ||
| 692 | |||
| 693 | return uvc_v4l2_try_format(video, arg, &probe, NULL, NULL); | ||
| 694 | } | ||
| 695 | |||
| 696 | case VIDIOC_S_FMT: | ||
| 697 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
| 698 | return ret; | ||
| 699 | |||
| 700 | return uvc_v4l2_set_format(video, arg); | ||
| 701 | |||
| 702 | case VIDIOC_G_FMT: | ||
| 703 | return uvc_v4l2_get_format(video, arg); | ||
| 704 | |||
| 705 | /* Frame size enumeration */ | ||
| 706 | case VIDIOC_ENUM_FRAMESIZES: | ||
| 707 | { | ||
| 708 | struct v4l2_frmsizeenum *fsize = arg; | ||
| 709 | struct uvc_format *format = NULL; | ||
| 710 | struct uvc_frame *frame; | ||
| 711 | int i; | ||
| 712 | |||
| 713 | /* Look for the given pixel format */ | ||
| 714 | for (i = 0; i < video->streaming->nformats; i++) { | ||
| 715 | if (video->streaming->format[i].fcc == | ||
| 716 | fsize->pixel_format) { | ||
| 717 | format = &video->streaming->format[i]; | ||
| 718 | break; | ||
| 719 | } | ||
| 720 | } | ||
| 721 | if (format == NULL) | ||
| 722 | return -EINVAL; | ||
| 723 | |||
| 724 | if (fsize->index >= format->nframes) | ||
| 725 | return -EINVAL; | ||
| 726 | |||
| 727 | frame = &format->frame[fsize->index]; | ||
| 728 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
| 729 | fsize->discrete.width = frame->wWidth; | ||
| 730 | fsize->discrete.height = frame->wHeight; | ||
| 731 | break; | ||
| 732 | } | ||
| 733 | |||
| 734 | /* Frame interval enumeration */ | ||
| 735 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
| 736 | { | ||
| 737 | struct v4l2_frmivalenum *fival = arg; | ||
| 738 | struct uvc_format *format = NULL; | ||
| 739 | struct uvc_frame *frame = NULL; | ||
| 740 | int i; | ||
| 741 | |||
| 742 | /* Look for the given pixel format and frame size */ | ||
| 743 | for (i = 0; i < video->streaming->nformats; i++) { | ||
| 744 | if (video->streaming->format[i].fcc == | ||
| 745 | fival->pixel_format) { | ||
| 746 | format = &video->streaming->format[i]; | ||
| 747 | break; | ||
| 748 | } | ||
| 749 | } | ||
| 750 | if (format == NULL) | ||
| 751 | return -EINVAL; | ||
| 752 | |||
| 753 | for (i = 0; i < format->nframes; i++) { | ||
| 754 | if (format->frame[i].wWidth == fival->width && | ||
| 755 | format->frame[i].wHeight == fival->height) { | ||
| 756 | frame = &format->frame[i]; | ||
| 757 | break; | ||
| 758 | } | ||
| 759 | } | ||
| 760 | if (frame == NULL) | ||
| 761 | return -EINVAL; | ||
| 762 | |||
| 763 | if (frame->bFrameIntervalType) { | ||
| 764 | if (fival->index >= frame->bFrameIntervalType) | ||
| 765 | return -EINVAL; | ||
| 766 | |||
| 767 | fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; | ||
| 768 | fival->discrete.numerator = | ||
| 769 | frame->dwFrameInterval[fival->index]; | ||
| 770 | fival->discrete.denominator = 10000000; | ||
| 771 | uvc_simplify_fraction(&fival->discrete.numerator, | ||
| 772 | &fival->discrete.denominator, 8, 333); | ||
| 773 | } else { | ||
| 774 | fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; | ||
| 775 | fival->stepwise.min.numerator = | ||
| 776 | frame->dwFrameInterval[0]; | ||
| 777 | fival->stepwise.min.denominator = 10000000; | ||
| 778 | fival->stepwise.max.numerator = | ||
| 779 | frame->dwFrameInterval[1]; | ||
| 780 | fival->stepwise.max.denominator = 10000000; | ||
| 781 | fival->stepwise.step.numerator = | ||
| 782 | frame->dwFrameInterval[2]; | ||
| 783 | fival->stepwise.step.denominator = 10000000; | ||
| 784 | uvc_simplify_fraction(&fival->stepwise.min.numerator, | ||
| 785 | &fival->stepwise.min.denominator, 8, 333); | ||
| 786 | uvc_simplify_fraction(&fival->stepwise.max.numerator, | ||
| 787 | &fival->stepwise.max.denominator, 8, 333); | ||
| 788 | uvc_simplify_fraction(&fival->stepwise.step.numerator, | ||
| 789 | &fival->stepwise.step.denominator, 8, 333); | ||
| 790 | } | ||
| 791 | break; | ||
| 792 | } | ||
| 793 | |||
| 794 | /* Get & Set streaming parameters */ | ||
| 795 | case VIDIOC_G_PARM: | ||
| 796 | return uvc_v4l2_get_streamparm(video, arg); | ||
| 797 | |||
| 798 | case VIDIOC_S_PARM: | ||
| 799 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
| 800 | return ret; | ||
| 801 | |||
| 802 | return uvc_v4l2_set_streamparm(video, arg); | ||
| 803 | |||
| 804 | /* Cropping and scaling */ | ||
| 805 | case VIDIOC_CROPCAP: | ||
| 806 | { | ||
| 807 | struct v4l2_cropcap *ccap = arg; | ||
| 808 | struct uvc_frame *frame = video->streaming->cur_frame; | ||
| 809 | |||
| 810 | if (ccap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 811 | return -EINVAL; | ||
| 812 | |||
| 813 | ccap->bounds.left = 0; | ||
| 814 | ccap->bounds.top = 0; | ||
| 815 | ccap->bounds.width = frame->wWidth; | ||
| 816 | ccap->bounds.height = frame->wHeight; | ||
| 817 | |||
| 818 | ccap->defrect = ccap->bounds; | ||
| 819 | |||
| 820 | ccap->pixelaspect.numerator = 1; | ||
| 821 | ccap->pixelaspect.denominator = 1; | ||
| 822 | break; | ||
| 823 | } | ||
| 824 | |||
| 825 | case VIDIOC_G_CROP: | ||
| 826 | case VIDIOC_S_CROP: | ||
| 827 | return -EINVAL; | ||
| 828 | |||
| 829 | /* Buffers & streaming */ | ||
| 830 | case VIDIOC_REQBUFS: | ||
| 831 | { | ||
| 832 | struct v4l2_requestbuffers *rb = arg; | ||
| 833 | unsigned int bufsize = | ||
| 834 | video->streaming->ctrl.dwMaxVideoFrameSize; | ||
| 835 | |||
| 836 | if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || | ||
| 837 | rb->memory != V4L2_MEMORY_MMAP) | ||
| 838 | return -EINVAL; | ||
| 839 | |||
| 840 | if ((ret = uvc_acquire_privileges(handle)) < 0) | ||
| 841 | return ret; | ||
| 842 | |||
| 843 | ret = uvc_alloc_buffers(&video->queue, rb->count, bufsize); | ||
| 844 | if (ret < 0) | ||
| 845 | return ret; | ||
| 846 | |||
| 847 | if (!(video->streaming->cur_format->flags & | ||
| 848 | UVC_FMT_FLAG_COMPRESSED)) | ||
| 849 | video->queue.flags |= UVC_QUEUE_DROP_INCOMPLETE; | ||
| 850 | |||
| 851 | rb->count = ret; | ||
| 852 | ret = 0; | ||
| 853 | break; | ||
| 854 | } | ||
| 855 | |||
| 856 | case VIDIOC_QUERYBUF: | ||
| 857 | { | ||
| 858 | struct v4l2_buffer *buf = arg; | ||
| 859 | |||
| 860 | if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 861 | return -EINVAL; | ||
| 862 | |||
| 863 | if (!uvc_has_privileges(handle)) | ||
| 864 | return -EBUSY; | ||
| 865 | |||
| 866 | return uvc_query_buffer(&video->queue, buf); | ||
| 867 | } | ||
| 868 | |||
| 869 | case VIDIOC_QBUF: | ||
| 870 | if (!uvc_has_privileges(handle)) | ||
| 871 | return -EBUSY; | ||
| 872 | |||
| 873 | return uvc_queue_buffer(&video->queue, arg); | ||
| 874 | |||
| 875 | case VIDIOC_DQBUF: | ||
| 876 | if (!uvc_has_privileges(handle)) | ||
| 877 | return -EBUSY; | ||
| 878 | |||
| 879 | return uvc_dequeue_buffer(&video->queue, arg, | ||
| 880 | file->f_flags & O_NONBLOCK); | ||
| 881 | |||
| 882 | case VIDIOC_STREAMON: | ||
| 883 | { | ||
| 884 | int *type = arg; | ||
| 885 | |||
| 886 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 887 | return -EINVAL; | ||
| 888 | |||
| 889 | if (!uvc_has_privileges(handle)) | ||
| 890 | return -EBUSY; | ||
| 891 | |||
| 892 | if ((ret = uvc_video_enable(video, 1)) < 0) | ||
| 893 | return ret; | ||
| 894 | break; | ||
| 895 | } | ||
| 896 | |||
| 897 | case VIDIOC_STREAMOFF: | ||
| 898 | { | ||
| 899 | int *type = arg; | ||
| 900 | |||
| 901 | if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
| 902 | return -EINVAL; | ||
| 903 | |||
| 904 | if (!uvc_has_privileges(handle)) | ||
| 905 | return -EBUSY; | ||
| 906 | |||
| 907 | return uvc_video_enable(video, 0); | ||
| 908 | } | ||
| 909 | |||
| 910 | /* Analog video standards make no sense for digital cameras. */ | ||
| 911 | case VIDIOC_ENUMSTD: | ||
| 912 | case VIDIOC_QUERYSTD: | ||
| 913 | case VIDIOC_G_STD: | ||
| 914 | case VIDIOC_S_STD: | ||
| 915 | |||
| 916 | case VIDIOC_OVERLAY: | ||
| 917 | |||
| 918 | case VIDIOC_ENUMAUDIO: | ||
| 919 | case VIDIOC_ENUMAUDOUT: | ||
| 920 | |||
| 921 | case VIDIOC_ENUMOUTPUT: | ||
| 922 | uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd); | ||
| 923 | return -EINVAL; | ||
| 924 | |||
| 925 | /* Dynamic controls. */ | ||
| 926 | case UVCIOC_CTRL_ADD: | ||
| 927 | { | ||
| 928 | struct uvc_xu_control_info *xinfo = arg; | ||
| 929 | struct uvc_control_info *info; | ||
| 930 | |||
| 931 | if (!capable(CAP_SYS_ADMIN)) | ||
| 932 | return -EPERM; | ||
| 933 | |||
| 934 | info = kmalloc(sizeof *info, GFP_KERNEL); | ||
| 935 | if (info == NULL) | ||
| 936 | return -ENOMEM; | ||
| 937 | |||
| 938 | memcpy(info->entity, xinfo->entity, sizeof info->entity); | ||
| 939 | info->index = xinfo->index; | ||
| 940 | info->selector = xinfo->selector; | ||
| 941 | info->size = xinfo->size; | ||
| 942 | info->flags = xinfo->flags; | ||
| 943 | |||
| 944 | info->flags |= UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | | ||
| 945 | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF; | ||
| 946 | |||
| 947 | ret = uvc_ctrl_add_info(info); | ||
| 948 | if (ret < 0) | ||
| 949 | kfree(info); | ||
| 950 | break; | ||
| 951 | } | ||
| 952 | |||
| 953 | case UVCIOC_CTRL_MAP: | ||
| 954 | { | ||
| 955 | struct uvc_xu_control_mapping *xmap = arg; | ||
| 956 | struct uvc_control_mapping *map; | ||
| 957 | |||
| 958 | if (!capable(CAP_SYS_ADMIN)) | ||
| 959 | return -EPERM; | ||
| 960 | |||
| 961 | map = kmalloc(sizeof *map, GFP_KERNEL); | ||
| 962 | if (map == NULL) | ||
| 963 | return -ENOMEM; | ||
| 964 | |||
| 965 | map->id = xmap->id; | ||
| 966 | memcpy(map->name, xmap->name, sizeof map->name); | ||
| 967 | memcpy(map->entity, xmap->entity, sizeof map->entity); | ||
| 968 | map->selector = xmap->selector; | ||
| 969 | map->size = xmap->size; | ||
| 970 | map->offset = xmap->offset; | ||
| 971 | map->v4l2_type = xmap->v4l2_type; | ||
| 972 | map->data_type = xmap->data_type; | ||
| 973 | |||
| 974 | ret = uvc_ctrl_add_mapping(map); | ||
| 975 | if (ret < 0) | ||
| 976 | kfree(map); | ||
| 977 | break; | ||
| 978 | } | ||
| 979 | |||
| 980 | case UVCIOC_CTRL_GET: | ||
| 981 | return uvc_xu_ctrl_query(video, arg, 0); | ||
| 982 | |||
| 983 | case UVCIOC_CTRL_SET: | ||
| 984 | return uvc_xu_ctrl_query(video, arg, 1); | ||
| 985 | |||
| 986 | default: | ||
| 987 | if ((ret = v4l_compat_translate_ioctl(inode, file, cmd, arg, | ||
| 988 | uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD) | ||
| 989 | uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", | ||
| 990 | cmd); | ||
| 991 | return ret; | ||
| 992 | } | ||
| 993 | |||
| 994 | return ret; | ||
| 995 | } | ||
| 996 | |||
| 997 | static int uvc_v4l2_ioctl(struct inode *inode, struct file *file, | ||
| 998 | unsigned int cmd, unsigned long arg) | ||
| 999 | { | ||
| 1000 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_ioctl\n"); | ||
| 1001 | return video_usercopy(inode, file, cmd, arg, uvc_v4l2_do_ioctl); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | static ssize_t uvc_v4l2_read(struct file *file, char __user *data, | ||
| 1005 | size_t count, loff_t *ppos) | ||
| 1006 | { | ||
| 1007 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n"); | ||
| 1008 | return -ENODEV; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | /* | ||
| 1012 | * VMA operations. | ||
| 1013 | */ | ||
| 1014 | static void uvc_vm_open(struct vm_area_struct *vma) | ||
| 1015 | { | ||
| 1016 | struct uvc_buffer *buffer = vma->vm_private_data; | ||
| 1017 | buffer->vma_use_count++; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | static void uvc_vm_close(struct vm_area_struct *vma) | ||
| 1021 | { | ||
| 1022 | struct uvc_buffer *buffer = vma->vm_private_data; | ||
| 1023 | buffer->vma_use_count--; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | static struct vm_operations_struct uvc_vm_ops = { | ||
| 1027 | .open = uvc_vm_open, | ||
| 1028 | .close = uvc_vm_close, | ||
| 1029 | }; | ||
| 1030 | |||
| 1031 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 1032 | { | ||
| 1033 | struct video_device *vdev = video_devdata(file); | ||
| 1034 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
| 1035 | struct uvc_buffer *buffer; | ||
| 1036 | struct page *page; | ||
| 1037 | unsigned long addr, start, size; | ||
| 1038 | unsigned int i; | ||
| 1039 | int ret = 0; | ||
| 1040 | |||
| 1041 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n"); | ||
| 1042 | |||
| 1043 | start = vma->vm_start; | ||
| 1044 | size = vma->vm_end - vma->vm_start; | ||
| 1045 | |||
| 1046 | mutex_lock(&video->queue.mutex); | ||
| 1047 | |||
| 1048 | for (i = 0; i < video->queue.count; ++i) { | ||
| 1049 | buffer = &video->queue.buffer[i]; | ||
| 1050 | if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) | ||
| 1051 | break; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | if (i == video->queue.count || size != video->queue.buf_size) { | ||
| 1055 | ret = -EINVAL; | ||
| 1056 | goto done; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | /* | ||
| 1060 | * VM_IO marks the area as being an mmaped region for I/O to a | ||
| 1061 | * device. It also prevents the region from being core dumped. | ||
| 1062 | */ | ||
| 1063 | vma->vm_flags |= VM_IO; | ||
| 1064 | |||
| 1065 | addr = (unsigned long)video->queue.mem + buffer->buf.m.offset; | ||
| 1066 | while (size > 0) { | ||
| 1067 | page = vmalloc_to_page((void *)addr); | ||
| 1068 | if ((ret = vm_insert_page(vma, start, page)) < 0) | ||
| 1069 | goto done; | ||
| 1070 | |||
| 1071 | start += PAGE_SIZE; | ||
| 1072 | addr += PAGE_SIZE; | ||
| 1073 | size -= PAGE_SIZE; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | vma->vm_ops = &uvc_vm_ops; | ||
| 1077 | vma->vm_private_data = buffer; | ||
| 1078 | uvc_vm_open(vma); | ||
| 1079 | |||
| 1080 | done: | ||
| 1081 | mutex_unlock(&video->queue.mutex); | ||
| 1082 | return ret; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) | ||
| 1086 | { | ||
| 1087 | struct video_device *vdev = video_devdata(file); | ||
| 1088 | struct uvc_video_device *video = video_get_drvdata(vdev); | ||
| 1089 | |||
| 1090 | uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); | ||
| 1091 | |||
| 1092 | return uvc_queue_poll(&video->queue, file, wait); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | struct file_operations uvc_fops = { | ||
| 1096 | .owner = THIS_MODULE, | ||
| 1097 | .open = uvc_v4l2_open, | ||
| 1098 | .release = uvc_v4l2_release, | ||
| 1099 | .ioctl = uvc_v4l2_ioctl, | ||
| 1100 | .compat_ioctl = v4l_compat_ioctl32, | ||
| 1101 | .llseek = no_llseek, | ||
| 1102 | .read = uvc_v4l2_read, | ||
| 1103 | .mmap = uvc_v4l2_mmap, | ||
| 1104 | .poll = uvc_v4l2_poll, | ||
| 1105 | }; | ||
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c new file mode 100644 index 000000000000..6faf1fb21614 --- /dev/null +++ b/drivers/media/video/uvc/uvc_video.c | |||
| @@ -0,0 +1,934 @@ | |||
| 1 | /* | ||
| 2 | * uvc_video.c -- USB Video Class driver - Video handling | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005-2008 | ||
| 5 | * Laurent Pinchart (laurent.pinchart@skynet.be) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/version.h> | ||
| 16 | #include <linux/list.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/usb.h> | ||
| 19 | #include <linux/videodev2.h> | ||
| 20 | #include <linux/vmalloc.h> | ||
| 21 | #include <linux/wait.h> | ||
| 22 | #include <asm/atomic.h> | ||
| 23 | #include <asm/unaligned.h> | ||
| 24 | |||
| 25 | #include <media/v4l2-common.h> | ||
| 26 | |||
| 27 | #include "uvcvideo.h" | ||
| 28 | |||
| 29 | /* ------------------------------------------------------------------------ | ||
| 30 | * UVC Controls | ||
| 31 | */ | ||
| 32 | |||
| 33 | static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | ||
| 34 | __u8 intfnum, __u8 cs, void *data, __u16 size, | ||
| 35 | int timeout) | ||
| 36 | { | ||
| 37 | __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; | ||
| 38 | unsigned int pipe; | ||
| 39 | int ret; | ||
| 40 | |||
| 41 | pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0) | ||
| 42 | : usb_sndctrlpipe(dev->udev, 0); | ||
| 43 | type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT; | ||
| 44 | |||
| 45 | ret = usb_control_msg(dev->udev, pipe, query, type, cs << 8, | ||
| 46 | unit << 8 | intfnum, data, size, timeout); | ||
| 47 | |||
| 48 | if (ret != size) { | ||
| 49 | uvc_printk(KERN_ERR, "Failed to query (%u) UVC control %u " | ||
| 50 | "(unit %u) : %d (exp. %u).\n", query, cs, unit, ret, | ||
| 51 | size); | ||
| 52 | return -EIO; | ||
| 53 | } | ||
| 54 | |||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | ||
| 59 | __u8 intfnum, __u8 cs, void *data, __u16 size) | ||
| 60 | { | ||
| 61 | return __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size, | ||
| 62 | UVC_CTRL_CONTROL_TIMEOUT); | ||
| 63 | } | ||
| 64 | |||
| 65 | static void uvc_fixup_buffer_size(struct uvc_video_device *video, | ||
| 66 | struct uvc_streaming_control *ctrl) | ||
| 67 | { | ||
| 68 | struct uvc_format *format; | ||
| 69 | struct uvc_frame *frame; | ||
| 70 | |||
| 71 | if (ctrl->bFormatIndex <= 0 || | ||
| 72 | ctrl->bFormatIndex > video->streaming->nformats) | ||
| 73 | return; | ||
| 74 | |||
| 75 | format = &video->streaming->format[ctrl->bFormatIndex - 1]; | ||
| 76 | |||
| 77 | if (ctrl->bFrameIndex <= 0 || | ||
| 78 | ctrl->bFrameIndex > format->nframes) | ||
| 79 | return; | ||
| 80 | |||
| 81 | frame = &format->frame[ctrl->bFrameIndex - 1]; | ||
| 82 | |||
| 83 | if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) || | ||
| 84 | (ctrl->dwMaxVideoFrameSize == 0 && | ||
| 85 | video->dev->uvc_version < 0x0110)) | ||
| 86 | ctrl->dwMaxVideoFrameSize = | ||
| 87 | frame->dwMaxVideoFrameBufferSize; | ||
| 88 | } | ||
| 89 | |||
| 90 | static int uvc_get_video_ctrl(struct uvc_video_device *video, | ||
| 91 | struct uvc_streaming_control *ctrl, int probe, __u8 query) | ||
| 92 | { | ||
| 93 | __u8 data[34]; | ||
| 94 | __u8 size; | ||
| 95 | int ret; | ||
| 96 | |||
| 97 | size = video->dev->uvc_version >= 0x0110 ? 34 : 26; | ||
| 98 | ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, | ||
| 99 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size, | ||
| 100 | UVC_CTRL_STREAMING_TIMEOUT); | ||
| 101 | |||
| 102 | if (ret < 0) | ||
| 103 | return ret; | ||
| 104 | |||
| 105 | ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); | ||
| 106 | ctrl->bFormatIndex = data[2]; | ||
| 107 | ctrl->bFrameIndex = data[3]; | ||
| 108 | ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]); | ||
| 109 | ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]); | ||
| 110 | ctrl->wPFrameRate = le16_to_cpup((__le16 *)&data[10]); | ||
| 111 | ctrl->wCompQuality = le16_to_cpup((__le16 *)&data[12]); | ||
| 112 | ctrl->wCompWindowSize = le16_to_cpup((__le16 *)&data[14]); | ||
| 113 | ctrl->wDelay = le16_to_cpup((__le16 *)&data[16]); | ||
| 114 | ctrl->dwMaxVideoFrameSize = | ||
| 115 | le32_to_cpu(get_unaligned((__le32 *)&data[18])); | ||
| 116 | ctrl->dwMaxPayloadTransferSize = | ||
| 117 | le32_to_cpu(get_unaligned((__le32 *)&data[22])); | ||
| 118 | |||
| 119 | if (size == 34) { | ||
| 120 | ctrl->dwClockFrequency = | ||
| 121 | le32_to_cpu(get_unaligned((__le32 *)&data[26])); | ||
| 122 | ctrl->bmFramingInfo = data[30]; | ||
| 123 | ctrl->bPreferedVersion = data[31]; | ||
| 124 | ctrl->bMinVersion = data[32]; | ||
| 125 | ctrl->bMaxVersion = data[33]; | ||
| 126 | } else { | ||
| 127 | ctrl->dwClockFrequency = video->dev->clock_frequency; | ||
| 128 | ctrl->bmFramingInfo = 0; | ||
| 129 | ctrl->bPreferedVersion = 0; | ||
| 130 | ctrl->bMinVersion = 0; | ||
| 131 | ctrl->bMaxVersion = 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* Some broken devices return a null or wrong dwMaxVideoFrameSize. | ||
| 135 | * Try to get the value from the format and frame descriptor. | ||
| 136 | */ | ||
| 137 | uvc_fixup_buffer_size(video, ctrl); | ||
| 138 | |||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | int uvc_set_video_ctrl(struct uvc_video_device *video, | ||
| 143 | struct uvc_streaming_control *ctrl, int probe) | ||
| 144 | { | ||
| 145 | __u8 data[34]; | ||
| 146 | __u8 size; | ||
| 147 | |||
| 148 | size = video->dev->uvc_version >= 0x0110 ? 34 : 26; | ||
| 149 | memset(data, 0, sizeof data); | ||
| 150 | |||
| 151 | *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint); | ||
| 152 | data[2] = ctrl->bFormatIndex; | ||
| 153 | data[3] = ctrl->bFrameIndex; | ||
| 154 | *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval); | ||
| 155 | *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate); | ||
| 156 | *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate); | ||
| 157 | *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality); | ||
| 158 | *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize); | ||
| 159 | *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay); | ||
| 160 | /* Note: Some of the fields below are not required for IN devices (see | ||
| 161 | * UVC spec, 4.3.1.1), but we still copy them in case support for OUT | ||
| 162 | * devices is added in the future. */ | ||
| 163 | put_unaligned(cpu_to_le32(ctrl->dwMaxVideoFrameSize), | ||
| 164 | (__le32 *)&data[18]); | ||
| 165 | put_unaligned(cpu_to_le32(ctrl->dwMaxPayloadTransferSize), | ||
| 166 | (__le32 *)&data[22]); | ||
| 167 | |||
| 168 | if (size == 34) { | ||
| 169 | put_unaligned(cpu_to_le32(ctrl->dwClockFrequency), | ||
| 170 | (__le32 *)&data[26]); | ||
| 171 | data[30] = ctrl->bmFramingInfo; | ||
| 172 | data[31] = ctrl->bPreferedVersion; | ||
| 173 | data[32] = ctrl->bMinVersion; | ||
| 174 | data[33] = ctrl->bMaxVersion; | ||
| 175 | } | ||
| 176 | |||
| 177 | return __uvc_query_ctrl(video->dev, SET_CUR, 0, | ||
| 178 | video->streaming->intfnum, | ||
| 179 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size, | ||
| 180 | UVC_CTRL_STREAMING_TIMEOUT); | ||
| 181 | } | ||
| 182 | |||
| 183 | int uvc_probe_video(struct uvc_video_device *video, | ||
| 184 | struct uvc_streaming_control *probe) | ||
| 185 | { | ||
| 186 | struct uvc_streaming_control probe_min, probe_max; | ||
| 187 | __u16 bandwidth; | ||
| 188 | unsigned int i; | ||
| 189 | int ret; | ||
| 190 | |||
| 191 | mutex_lock(&video->streaming->mutex); | ||
| 192 | |||
| 193 | /* Perform probing. The device should adjust the requested values | ||
| 194 | * according to its capabilities. However, some devices, namely the | ||
| 195 | * first generation UVC Logitech webcams, don't implement the Video | ||
| 196 | * Probe control properly, and just return the needed bandwidth. For | ||
| 197 | * that reason, if the needed bandwidth exceeds the maximum available | ||
| 198 | * bandwidth, try to lower the quality. | ||
| 199 | */ | ||
| 200 | if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0) | ||
| 201 | goto done; | ||
| 202 | |||
| 203 | /* Get the minimum and maximum values for compression settings. */ | ||
| 204 | if (!(video->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) { | ||
| 205 | ret = uvc_get_video_ctrl(video, &probe_min, 1, GET_MIN); | ||
| 206 | if (ret < 0) | ||
| 207 | goto done; | ||
| 208 | ret = uvc_get_video_ctrl(video, &probe_max, 1, GET_MAX); | ||
| 209 | if (ret < 0) | ||
| 210 | goto done; | ||
| 211 | |||
| 212 | probe->wCompQuality = probe_max.wCompQuality; | ||
| 213 | } | ||
| 214 | |||
| 215 | for (i = 0; i < 2; ++i) { | ||
| 216 | if ((ret = uvc_set_video_ctrl(video, probe, 1)) < 0 || | ||
| 217 | (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) | ||
| 218 | goto done; | ||
| 219 | |||
| 220 | if (video->streaming->intf->num_altsetting == 1) | ||
| 221 | break; | ||
| 222 | |||
| 223 | bandwidth = probe->dwMaxPayloadTransferSize; | ||
| 224 | if (bandwidth <= video->streaming->maxpsize) | ||
| 225 | break; | ||
| 226 | |||
| 227 | if (video->dev->quirks & UVC_QUIRK_PROBE_MINMAX) { | ||
| 228 | ret = -ENOSPC; | ||
| 229 | goto done; | ||
| 230 | } | ||
| 231 | |||
| 232 | /* TODO: negotiate compression parameters */ | ||
| 233 | probe->wKeyFrameRate = probe_min.wKeyFrameRate; | ||
| 234 | probe->wPFrameRate = probe_min.wPFrameRate; | ||
| 235 | probe->wCompQuality = probe_max.wCompQuality; | ||
| 236 | probe->wCompWindowSize = probe_min.wCompWindowSize; | ||
| 237 | } | ||
| 238 | |||
| 239 | done: | ||
| 240 | mutex_unlock(&video->streaming->mutex); | ||
| 241 | return ret; | ||
| 242 | } | ||
| 243 | |||
| 244 | /* ------------------------------------------------------------------------ | ||
| 245 | * Video codecs | ||
| 246 | */ | ||
| 247 | |||
| 248 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | ||
| 249 | #define UVC_STREAM_EOH (1 << 7) | ||
| 250 | #define UVC_STREAM_ERR (1 << 6) | ||
| 251 | #define UVC_STREAM_STI (1 << 5) | ||
| 252 | #define UVC_STREAM_RES (1 << 4) | ||
| 253 | #define UVC_STREAM_SCR (1 << 3) | ||
| 254 | #define UVC_STREAM_PTS (1 << 2) | ||
| 255 | #define UVC_STREAM_EOF (1 << 1) | ||
| 256 | #define UVC_STREAM_FID (1 << 0) | ||
| 257 | |||
| 258 | /* Video payload decoding is handled by uvc_video_decode_start(), | ||
| 259 | * uvc_video_decode_data() and uvc_video_decode_end(). | ||
| 260 | * | ||
| 261 | * uvc_video_decode_start is called with URB data at the start of a bulk or | ||
| 262 | * isochronous payload. It processes header data and returns the header size | ||
| 263 | * in bytes if successful. If an error occurs, it returns a negative error | ||
| 264 | * code. The following error codes have special meanings. | ||
| 265 | * | ||
| 266 | * - EAGAIN informs the caller that the current video buffer should be marked | ||
| 267 | * as done, and that the function should be called again with the same data | ||
| 268 | * and a new video buffer. This is used when end of frame conditions can be | ||
| 269 | * reliably detected at the beginning of the next frame only. | ||
| 270 | * | ||
| 271 | * If an error other than -EAGAIN is returned, the caller will drop the current | ||
| 272 | * payload. No call to uvc_video_decode_data and uvc_video_decode_end will be | ||
| 273 | * made until the next payload. -ENODATA can be used to drop the current | ||
| 274 | * payload if no other error code is appropriate. | ||
| 275 | * | ||
| 276 | * uvc_video_decode_data is called for every URB with URB data. It copies the | ||
| 277 | * data to the video buffer. | ||
| 278 | * | ||
| 279 | * uvc_video_decode_end is called with header data at the end of a bulk or | ||
| 280 | * isochronous payload. It performs any additional header data processing and | ||
| 281 | * returns 0 or a negative error code if an error occured. As header data have | ||
| 282 | * already been processed by uvc_video_decode_start, this functions isn't | ||
| 283 | * required to perform sanity checks a second time. | ||
| 284 | * | ||
| 285 | * For isochronous transfers where a payload is always transfered in a single | ||
| 286 | * URB, the three functions will be called in a row. | ||
| 287 | * | ||
| 288 | * To let the decoder process header data and update its internal state even | ||
| 289 | * when no video buffer is available, uvc_video_decode_start must be prepared | ||
| 290 | * to be called with a NULL buf parameter. uvc_video_decode_data and | ||
| 291 | * uvc_video_decode_end will never be called with a NULL buffer. | ||
| 292 | */ | ||
| 293 | static int uvc_video_decode_start(struct uvc_video_device *video, | ||
| 294 | struct uvc_buffer *buf, const __u8 *data, int len) | ||
| 295 | { | ||
| 296 | __u8 fid; | ||
| 297 | |||
| 298 | /* Sanity checks: | ||
| 299 | * - packet must be at least 2 bytes long | ||
| 300 | * - bHeaderLength value must be at least 2 bytes (see above) | ||
| 301 | * - bHeaderLength value can't be larger than the packet size. | ||
| 302 | */ | ||
| 303 | if (len < 2 || data[0] < 2 || data[0] > len) | ||
| 304 | return -EINVAL; | ||
| 305 | |||
| 306 | /* Skip payloads marked with the error bit ("error frames"). */ | ||
| 307 | if (data[1] & UVC_STREAM_ERR) { | ||
| 308 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (error bit " | ||
| 309 | "set).\n"); | ||
| 310 | return -ENODATA; | ||
| 311 | } | ||
| 312 | |||
| 313 | fid = data[1] & UVC_STREAM_FID; | ||
| 314 | |||
| 315 | /* Store the payload FID bit and return immediately when the buffer is | ||
| 316 | * NULL. | ||
| 317 | */ | ||
| 318 | if (buf == NULL) { | ||
| 319 | video->last_fid = fid; | ||
| 320 | return -ENODATA; | ||
| 321 | } | ||
| 322 | |||
| 323 | /* Synchronize to the input stream by waiting for the FID bit to be | ||
| 324 | * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. | ||
| 325 | * queue->last_fid is initialized to -1, so the first isochronous | ||
| 326 | * frame will always be in sync. | ||
| 327 | * | ||
| 328 | * If the device doesn't toggle the FID bit, invert video->last_fid | ||
| 329 | * when the EOF bit is set to force synchronisation on the next packet. | ||
| 330 | */ | ||
| 331 | if (buf->state != UVC_BUF_STATE_ACTIVE) { | ||
| 332 | if (fid == video->last_fid) { | ||
| 333 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " | ||
| 334 | "sync).\n"); | ||
| 335 | if ((video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) && | ||
| 336 | (data[1] & UVC_STREAM_EOF)) | ||
| 337 | video->last_fid ^= UVC_STREAM_FID; | ||
| 338 | return -ENODATA; | ||
| 339 | } | ||
| 340 | |||
| 341 | /* TODO: Handle PTS and SCR. */ | ||
| 342 | buf->state = UVC_BUF_STATE_ACTIVE; | ||
| 343 | } | ||
| 344 | |||
| 345 | /* Mark the buffer as done if we're at the beginning of a new frame. | ||
| 346 | * End of frame detection is better implemented by checking the EOF | ||
| 347 | * bit (FID bit toggling is delayed by one frame compared to the EOF | ||
| 348 | * bit), but some devices don't set the bit at end of frame (and the | ||
| 349 | * last payload can be lost anyway). We thus must check if the FID has | ||
| 350 | * been toggled. | ||
| 351 | * | ||
| 352 | * queue->last_fid is initialized to -1, so the first isochronous | ||
| 353 | * frame will never trigger an end of frame detection. | ||
| 354 | * | ||
| 355 | * Empty buffers (bytesused == 0) don't trigger end of frame detection | ||
| 356 | * as it doesn't make sense to return an empty buffer. This also | ||
| 357 | * avoids detecting and of frame conditions at FID toggling if the | ||
| 358 | * previous payload had the EOF bit set. | ||
| 359 | */ | ||
| 360 | if (fid != video->last_fid && buf->buf.bytesused != 0) { | ||
| 361 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " | ||
| 362 | "toggled).\n"); | ||
| 363 | buf->state = UVC_BUF_STATE_DONE; | ||
| 364 | return -EAGAIN; | ||
| 365 | } | ||
| 366 | |||
| 367 | video->last_fid = fid; | ||
| 368 | |||
| 369 | return data[0]; | ||
| 370 | } | ||
| 371 | |||
| 372 | static void uvc_video_decode_data(struct uvc_video_device *video, | ||
| 373 | struct uvc_buffer *buf, const __u8 *data, int len) | ||
| 374 | { | ||
| 375 | struct uvc_video_queue *queue = &video->queue; | ||
| 376 | unsigned int maxlen, nbytes; | ||
| 377 | void *mem; | ||
| 378 | |||
| 379 | if (len <= 0) | ||
| 380 | return; | ||
| 381 | |||
| 382 | /* Copy the video data to the buffer. */ | ||
| 383 | maxlen = buf->buf.length - buf->buf.bytesused; | ||
| 384 | mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; | ||
| 385 | nbytes = min((unsigned int)len, maxlen); | ||
| 386 | memcpy(mem, data, nbytes); | ||
| 387 | buf->buf.bytesused += nbytes; | ||
| 388 | |||
| 389 | /* Complete the current frame if the buffer size was exceeded. */ | ||
| 390 | if (len > maxlen) { | ||
| 391 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); | ||
| 392 | buf->state = UVC_BUF_STATE_DONE; | ||
| 393 | } | ||
| 394 | } | ||
| 395 | |||
| 396 | static void uvc_video_decode_end(struct uvc_video_device *video, | ||
| 397 | struct uvc_buffer *buf, const __u8 *data, int len) | ||
| 398 | { | ||
| 399 | /* Mark the buffer as done if the EOF marker is set. */ | ||
| 400 | if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) { | ||
| 401 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); | ||
| 402 | if (data[0] == len) | ||
| 403 | uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); | ||
| 404 | buf->state = UVC_BUF_STATE_DONE; | ||
| 405 | if (video->dev->quirks & UVC_QUIRK_STREAM_NO_FID) | ||
| 406 | video->last_fid ^= UVC_STREAM_FID; | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | /* ------------------------------------------------------------------------ | ||
| 411 | * URB handling | ||
| 412 | */ | ||
| 413 | |||
| 414 | /* | ||
| 415 | * Completion handler for video URBs. | ||
| 416 | */ | ||
| 417 | static void uvc_video_decode_isoc(struct urb *urb, | ||
| 418 | struct uvc_video_device *video, struct uvc_buffer *buf) | ||
| 419 | { | ||
| 420 | u8 *mem; | ||
| 421 | int ret, i; | ||
| 422 | |||
| 423 | for (i = 0; i < urb->number_of_packets; ++i) { | ||
| 424 | if (urb->iso_frame_desc[i].status < 0) { | ||
| 425 | uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame " | ||
| 426 | "lost (%d).\n", urb->iso_frame_desc[i].status); | ||
| 427 | continue; | ||
| 428 | } | ||
| 429 | |||
| 430 | /* Decode the payload header. */ | ||
| 431 | mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset; | ||
| 432 | do { | ||
| 433 | ret = uvc_video_decode_start(video, buf, mem, | ||
| 434 | urb->iso_frame_desc[i].actual_length); | ||
| 435 | if (ret == -EAGAIN) | ||
| 436 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
| 437 | } while (ret == -EAGAIN); | ||
| 438 | |||
| 439 | if (ret < 0) | ||
| 440 | continue; | ||
| 441 | |||
| 442 | /* Decode the payload data. */ | ||
| 443 | uvc_video_decode_data(video, buf, mem + ret, | ||
| 444 | urb->iso_frame_desc[i].actual_length - ret); | ||
| 445 | |||
| 446 | /* Process the header again. */ | ||
| 447 | uvc_video_decode_end(video, buf, mem, ret); | ||
| 448 | |||
| 449 | if (buf->state == UVC_BUF_STATE_DONE || | ||
| 450 | buf->state == UVC_BUF_STATE_ERROR) | ||
| 451 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
| 452 | } | ||
| 453 | } | ||
| 454 | |||
| 455 | static void uvc_video_decode_bulk(struct urb *urb, | ||
| 456 | struct uvc_video_device *video, struct uvc_buffer *buf) | ||
| 457 | { | ||
| 458 | u8 *mem; | ||
| 459 | int len, ret; | ||
| 460 | |||
| 461 | mem = urb->transfer_buffer; | ||
| 462 | len = urb->actual_length; | ||
| 463 | video->bulk.payload_size += len; | ||
| 464 | |||
| 465 | /* If the URB is the first of its payload, decode and save the | ||
| 466 | * header. | ||
| 467 | */ | ||
| 468 | if (video->bulk.header_size == 0) { | ||
| 469 | do { | ||
| 470 | ret = uvc_video_decode_start(video, buf, mem, len); | ||
| 471 | if (ret == -EAGAIN) | ||
| 472 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
| 473 | } while (ret == -EAGAIN); | ||
| 474 | |||
| 475 | /* If an error occured skip the rest of the payload. */ | ||
| 476 | if (ret < 0 || buf == NULL) { | ||
| 477 | video->bulk.skip_payload = 1; | ||
| 478 | return; | ||
| 479 | } | ||
| 480 | |||
| 481 | video->bulk.header_size = ret; | ||
| 482 | memcpy(video->bulk.header, mem, video->bulk.header_size); | ||
| 483 | |||
| 484 | mem += ret; | ||
| 485 | len -= ret; | ||
| 486 | } | ||
| 487 | |||
| 488 | /* The buffer queue might have been cancelled while a bulk transfer | ||
| 489 | * was in progress, so we can reach here with buf equal to NULL. Make | ||
| 490 | * sure buf is never dereferenced if NULL. | ||
| 491 | */ | ||
| 492 | |||
| 493 | /* Process video data. */ | ||
| 494 | if (!video->bulk.skip_payload && buf != NULL) | ||
| 495 | uvc_video_decode_data(video, buf, mem, len); | ||
| 496 | |||
| 497 | /* Detect the payload end by a URB smaller than the maximum size (or | ||
| 498 | * a payload size equal to the maximum) and process the header again. | ||
| 499 | */ | ||
| 500 | if (urb->actual_length < urb->transfer_buffer_length || | ||
| 501 | video->bulk.payload_size >= video->bulk.max_payload_size) { | ||
| 502 | if (!video->bulk.skip_payload && buf != NULL) { | ||
| 503 | uvc_video_decode_end(video, buf, video->bulk.header, | ||
| 504 | video->bulk.header_size); | ||
| 505 | if (buf->state == UVC_BUF_STATE_DONE || | ||
| 506 | buf->state == UVC_BUF_STATE_ERROR) | ||
| 507 | buf = uvc_queue_next_buffer(&video->queue, buf); | ||
| 508 | } | ||
| 509 | |||
| 510 | video->bulk.header_size = 0; | ||
| 511 | video->bulk.skip_payload = 0; | ||
| 512 | video->bulk.payload_size = 0; | ||
| 513 | } | ||
| 514 | } | ||
| 515 | |||
| 516 | static void uvc_video_complete(struct urb *urb) | ||
| 517 | { | ||
| 518 | struct uvc_video_device *video = urb->context; | ||
| 519 | struct uvc_video_queue *queue = &video->queue; | ||
| 520 | struct uvc_buffer *buf = NULL; | ||
| 521 | unsigned long flags; | ||
| 522 | int ret; | ||
| 523 | |||
| 524 | switch (urb->status) { | ||
| 525 | case 0: | ||
| 526 | break; | ||
| 527 | |||
| 528 | default: | ||
| 529 | uvc_printk(KERN_WARNING, "Non-zero status (%d) in video " | ||
| 530 | "completion handler.\n", urb->status); | ||
| 531 | |||
| 532 | case -ENOENT: /* usb_kill_urb() called. */ | ||
| 533 | if (video->frozen) | ||
| 534 | return; | ||
| 535 | |||
| 536 | case -ECONNRESET: /* usb_unlink_urb() called. */ | ||
| 537 | case -ESHUTDOWN: /* The endpoint is being disabled. */ | ||
| 538 | uvc_queue_cancel(queue, urb->status == -ESHUTDOWN); | ||
| 539 | return; | ||
| 540 | } | ||
| 541 | |||
| 542 | spin_lock_irqsave(&queue->irqlock, flags); | ||
| 543 | if (!list_empty(&queue->irqqueue)) | ||
| 544 | buf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | ||
| 545 | queue); | ||
| 546 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
| 547 | |||
| 548 | video->decode(urb, video, buf); | ||
| 549 | |||
| 550 | if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { | ||
| 551 | uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n", | ||
| 552 | ret); | ||
| 553 | } | ||
| 554 | } | ||
| 555 | |||
| 556 | /* | ||
| 557 | * Uninitialize isochronous/bulk URBs and free transfer buffers. | ||
| 558 | */ | ||
| 559 | static void uvc_uninit_video(struct uvc_video_device *video) | ||
| 560 | { | ||
| 561 | struct urb *urb; | ||
| 562 | unsigned int i; | ||
| 563 | |||
| 564 | for (i = 0; i < UVC_URBS; ++i) { | ||
| 565 | if ((urb = video->urb[i]) == NULL) | ||
| 566 | continue; | ||
| 567 | |||
| 568 | usb_kill_urb(urb); | ||
| 569 | /* urb->transfer_buffer_length is not touched by USB core, so | ||
| 570 | * we can use it here as the buffer length. | ||
| 571 | */ | ||
| 572 | if (video->urb_buffer[i]) { | ||
| 573 | usb_buffer_free(video->dev->udev, | ||
| 574 | urb->transfer_buffer_length, | ||
| 575 | video->urb_buffer[i], urb->transfer_dma); | ||
| 576 | video->urb_buffer[i] = NULL; | ||
| 577 | } | ||
| 578 | |||
| 579 | usb_free_urb(urb); | ||
| 580 | video->urb[i] = NULL; | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 584 | /* | ||
| 585 | * Initialize isochronous URBs and allocate transfer buffers. The packet size | ||
| 586 | * is given by the endpoint. | ||
| 587 | */ | ||
| 588 | static int uvc_init_video_isoc(struct uvc_video_device *video, | ||
| 589 | struct usb_host_endpoint *ep) | ||
| 590 | { | ||
| 591 | struct urb *urb; | ||
| 592 | unsigned int npackets, i, j; | ||
| 593 | __u16 psize; | ||
| 594 | __u32 size; | ||
| 595 | |||
| 596 | /* Compute the number of isochronous packets to allocate by dividing | ||
| 597 | * the maximum video frame size by the packet size. Limit the result | ||
| 598 | * to UVC_MAX_ISO_PACKETS. | ||
| 599 | */ | ||
| 600 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | ||
| 601 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | ||
| 602 | |||
| 603 | size = video->streaming->ctrl.dwMaxVideoFrameSize; | ||
| 604 | if (size > UVC_MAX_FRAME_SIZE) | ||
| 605 | return -EINVAL; | ||
| 606 | |||
| 607 | npackets = (size + psize - 1) / psize; | ||
| 608 | if (npackets > UVC_MAX_ISO_PACKETS) | ||
| 609 | npackets = UVC_MAX_ISO_PACKETS; | ||
| 610 | |||
| 611 | size = npackets * psize; | ||
| 612 | |||
| 613 | for (i = 0; i < UVC_URBS; ++i) { | ||
| 614 | urb = usb_alloc_urb(npackets, GFP_KERNEL); | ||
| 615 | if (urb == NULL) { | ||
| 616 | uvc_uninit_video(video); | ||
| 617 | return -ENOMEM; | ||
| 618 | } | ||
| 619 | |||
| 620 | video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, | ||
| 621 | size, GFP_KERNEL, &urb->transfer_dma); | ||
| 622 | if (video->urb_buffer[i] == NULL) { | ||
| 623 | usb_free_urb(urb); | ||
| 624 | uvc_uninit_video(video); | ||
| 625 | return -ENOMEM; | ||
| 626 | } | ||
| 627 | |||
| 628 | urb->dev = video->dev->udev; | ||
| 629 | urb->context = video; | ||
| 630 | urb->pipe = usb_rcvisocpipe(video->dev->udev, | ||
| 631 | ep->desc.bEndpointAddress); | ||
| 632 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
| 633 | urb->interval = ep->desc.bInterval; | ||
| 634 | urb->transfer_buffer = video->urb_buffer[i]; | ||
| 635 | urb->complete = uvc_video_complete; | ||
| 636 | urb->number_of_packets = npackets; | ||
| 637 | urb->transfer_buffer_length = size; | ||
| 638 | |||
| 639 | for (j = 0; j < npackets; ++j) { | ||
| 640 | urb->iso_frame_desc[j].offset = j * psize; | ||
| 641 | urb->iso_frame_desc[j].length = psize; | ||
| 642 | } | ||
| 643 | |||
| 644 | video->urb[i] = urb; | ||
| 645 | } | ||
| 646 | |||
| 647 | return 0; | ||
| 648 | } | ||
| 649 | |||
| 650 | /* | ||
| 651 | * Initialize bulk URBs and allocate transfer buffers. The packet size is | ||
| 652 | * given by the endpoint. | ||
| 653 | */ | ||
| 654 | static int uvc_init_video_bulk(struct uvc_video_device *video, | ||
| 655 | struct usb_host_endpoint *ep) | ||
| 656 | { | ||
| 657 | struct urb *urb; | ||
| 658 | unsigned int pipe, i; | ||
| 659 | __u16 psize; | ||
| 660 | __u32 size; | ||
| 661 | |||
| 662 | /* Compute the bulk URB size. Some devices set the maximum payload | ||
| 663 | * size to a value too high for memory-constrained devices. We must | ||
| 664 | * then transfer the payload accross multiple URBs. To be consistant | ||
| 665 | * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk | ||
| 666 | * URB. | ||
| 667 | */ | ||
| 668 | psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; | ||
| 669 | size = video->streaming->ctrl.dwMaxPayloadTransferSize; | ||
| 670 | video->bulk.max_payload_size = size; | ||
| 671 | if (size > psize * UVC_MAX_ISO_PACKETS) | ||
| 672 | size = psize * UVC_MAX_ISO_PACKETS; | ||
| 673 | |||
| 674 | pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress); | ||
| 675 | |||
| 676 | for (i = 0; i < UVC_URBS; ++i) { | ||
| 677 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 678 | if (urb == NULL) { | ||
| 679 | uvc_uninit_video(video); | ||
| 680 | return -ENOMEM; | ||
| 681 | } | ||
| 682 | |||
| 683 | video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, | ||
| 684 | size, GFP_KERNEL, &urb->transfer_dma); | ||
| 685 | if (video->urb_buffer[i] == NULL) { | ||
| 686 | usb_free_urb(urb); | ||
| 687 | uvc_uninit_video(video); | ||
| 688 | return -ENOMEM; | ||
| 689 | } | ||
| 690 | |||
| 691 | usb_fill_bulk_urb(urb, video->dev->udev, pipe, | ||
| 692 | video->urb_buffer[i], size, uvc_video_complete, | ||
| 693 | video); | ||
| 694 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
| 695 | |||
| 696 | video->urb[i] = urb; | ||
| 697 | } | ||
| 698 | |||
| 699 | return 0; | ||
| 700 | } | ||
| 701 | |||
| 702 | /* | ||
| 703 | * Initialize isochronous/bulk URBs and allocate transfer buffers. | ||
| 704 | */ | ||
| 705 | static int uvc_init_video(struct uvc_video_device *video) | ||
| 706 | { | ||
| 707 | struct usb_interface *intf = video->streaming->intf; | ||
| 708 | struct usb_host_interface *alts; | ||
| 709 | struct usb_host_endpoint *ep = NULL; | ||
| 710 | int intfnum = video->streaming->intfnum; | ||
| 711 | unsigned int bandwidth, psize, i; | ||
| 712 | int ret; | ||
| 713 | |||
| 714 | video->last_fid = -1; | ||
| 715 | video->bulk.header_size = 0; | ||
| 716 | video->bulk.skip_payload = 0; | ||
| 717 | video->bulk.payload_size = 0; | ||
| 718 | |||
| 719 | if (intf->num_altsetting > 1) { | ||
| 720 | /* Isochronous endpoint, select the alternate setting. */ | ||
| 721 | bandwidth = video->streaming->ctrl.dwMaxPayloadTransferSize; | ||
| 722 | |||
| 723 | if (bandwidth == 0) { | ||
| 724 | uvc_printk(KERN_WARNING, "device %s requested null " | ||
| 725 | "bandwidth, defaulting to lowest.\n", | ||
| 726 | video->vdev->name); | ||
| 727 | bandwidth = 1; | ||
| 728 | } | ||
| 729 | |||
| 730 | for (i = 0; i < intf->num_altsetting; ++i) { | ||
| 731 | alts = &intf->altsetting[i]; | ||
| 732 | ep = uvc_find_endpoint(alts, | ||
| 733 | video->streaming->header.bEndpointAddress); | ||
| 734 | if (ep == NULL) | ||
| 735 | continue; | ||
| 736 | |||
| 737 | /* Check if the bandwidth is high enough. */ | ||
| 738 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | ||
| 739 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | ||
| 740 | if (psize >= bandwidth) | ||
| 741 | break; | ||
| 742 | } | ||
| 743 | |||
| 744 | if (i >= intf->num_altsetting) | ||
| 745 | return -EIO; | ||
| 746 | |||
| 747 | if ((ret = usb_set_interface(video->dev->udev, intfnum, i)) < 0) | ||
| 748 | return ret; | ||
| 749 | |||
| 750 | ret = uvc_init_video_isoc(video, ep); | ||
| 751 | } else { | ||
| 752 | /* Bulk endpoint, proceed to URB initialization. */ | ||
| 753 | ep = uvc_find_endpoint(&intf->altsetting[0], | ||
| 754 | video->streaming->header.bEndpointAddress); | ||
| 755 | if (ep == NULL) | ||
| 756 | return -EIO; | ||
| 757 | |||
| 758 | ret = uvc_init_video_bulk(video, ep); | ||
| 759 | } | ||
| 760 | |||
| 761 | if (ret < 0) | ||
| 762 | return ret; | ||
| 763 | |||
| 764 | /* Submit the URBs. */ | ||
| 765 | for (i = 0; i < UVC_URBS; ++i) { | ||
| 766 | if ((ret = usb_submit_urb(video->urb[i], GFP_KERNEL)) < 0) { | ||
| 767 | uvc_printk(KERN_ERR, "Failed to submit URB %u " | ||
| 768 | "(%d).\n", i, ret); | ||
| 769 | uvc_uninit_video(video); | ||
| 770 | return ret; | ||
| 771 | } | ||
| 772 | } | ||
| 773 | |||
| 774 | return 0; | ||
| 775 | } | ||
| 776 | |||
| 777 | /* -------------------------------------------------------------------------- | ||
| 778 | * Suspend/resume | ||
| 779 | */ | ||
| 780 | |||
| 781 | /* | ||
| 782 | * Stop streaming without disabling the video queue. | ||
| 783 | * | ||
| 784 | * To let userspace applications resume without trouble, we must not touch the | ||
| 785 | * video buffers in any way. We mark the device as frozen to make sure the URB | ||
| 786 | * completion handler won't try to cancel the queue when we kill the URBs. | ||
| 787 | */ | ||
| 788 | int uvc_video_suspend(struct uvc_video_device *video) | ||
| 789 | { | ||
| 790 | if (!uvc_queue_streaming(&video->queue)) | ||
| 791 | return 0; | ||
| 792 | |||
| 793 | video->frozen = 1; | ||
| 794 | uvc_uninit_video(video); | ||
| 795 | usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); | ||
| 796 | return 0; | ||
| 797 | } | ||
| 798 | |||
| 799 | /* | ||
| 800 | * Reconfigure the video interface and restart streaming if it was enable | ||
| 801 | * before suspend. | ||
| 802 | * | ||
| 803 | * If an error occurs, disable the video queue. This will wake all pending | ||
| 804 | * buffers, making sure userspace applications are notified of the problem | ||
| 805 | * instead of waiting forever. | ||
| 806 | */ | ||
| 807 | int uvc_video_resume(struct uvc_video_device *video) | ||
| 808 | { | ||
| 809 | int ret; | ||
| 810 | |||
| 811 | video->frozen = 0; | ||
| 812 | |||
| 813 | if ((ret = uvc_set_video_ctrl(video, &video->streaming->ctrl, 0)) < 0) { | ||
| 814 | uvc_queue_enable(&video->queue, 0); | ||
| 815 | return ret; | ||
| 816 | } | ||
| 817 | |||
| 818 | if (!uvc_queue_streaming(&video->queue)) | ||
| 819 | return 0; | ||
| 820 | |||
| 821 | if ((ret = uvc_init_video(video)) < 0) | ||
| 822 | uvc_queue_enable(&video->queue, 0); | ||
| 823 | |||
| 824 | return ret; | ||
| 825 | } | ||
| 826 | |||
| 827 | /* ------------------------------------------------------------------------ | ||
| 828 | * Video device | ||
| 829 | */ | ||
| 830 | |||
| 831 | /* | ||
| 832 | * Initialize the UVC video device by retrieving the default format and | ||
| 833 | * committing it. | ||
| 834 | * | ||
| 835 | * Some cameras (namely the Fuji Finepix) set the format and frame | ||
| 836 | * indexes to zero. The UVC standard doesn't clearly make this a spec | ||
| 837 | * violation, so try to silently fix the values if possible. | ||
| 838 | * | ||
| 839 | * This function is called before registering the device with V4L. | ||
| 840 | */ | ||
| 841 | int uvc_video_init(struct uvc_video_device *video) | ||
| 842 | { | ||
| 843 | struct uvc_streaming_control *probe = &video->streaming->ctrl; | ||
| 844 | struct uvc_format *format = NULL; | ||
| 845 | struct uvc_frame *frame = NULL; | ||
| 846 | unsigned int i; | ||
| 847 | int ret; | ||
| 848 | |||
| 849 | if (video->streaming->nformats == 0) { | ||
| 850 | uvc_printk(KERN_INFO, "No supported video formats found.\n"); | ||
| 851 | return -EINVAL; | ||
| 852 | } | ||
| 853 | |||
| 854 | /* Alternate setting 0 should be the default, yet the XBox Live Vision | ||
| 855 | * Cam (and possibly other devices) crash or otherwise misbehave if | ||
| 856 | * they don't receive a SET_INTERFACE request before any other video | ||
| 857 | * control request. | ||
| 858 | */ | ||
| 859 | usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); | ||
| 860 | |||
| 861 | /* Some webcams don't suport GET_DEF request on the probe control. We | ||
| 862 | * fall back to GET_CUR if GET_DEF fails. | ||
| 863 | */ | ||
| 864 | if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && | ||
| 865 | (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) | ||
| 866 | return ret; | ||
| 867 | |||
| 868 | /* Check if the default format descriptor exists. Use the first | ||
| 869 | * available format otherwise. | ||
| 870 | */ | ||
| 871 | for (i = video->streaming->nformats; i > 0; --i) { | ||
| 872 | format = &video->streaming->format[i-1]; | ||
| 873 | if (format->index == probe->bFormatIndex) | ||
| 874 | break; | ||
| 875 | } | ||
| 876 | |||
| 877 | if (format->nframes == 0) { | ||
| 878 | uvc_printk(KERN_INFO, "No frame descriptor found for the " | ||
| 879 | "default format.\n"); | ||
| 880 | return -EINVAL; | ||
| 881 | } | ||
| 882 | |||
| 883 | /* Zero bFrameIndex might be correct. Stream-based formats (including | ||
| 884 | * MPEG-2 TS and DV) do not support frames but have a dummy frame | ||
| 885 | * descriptor with bFrameIndex set to zero. If the default frame | ||
| 886 | * descriptor is not found, use the first avalable frame. | ||
| 887 | */ | ||
| 888 | for (i = format->nframes; i > 0; --i) { | ||
| 889 | frame = &format->frame[i-1]; | ||
| 890 | if (frame->bFrameIndex == probe->bFrameIndex) | ||
| 891 | break; | ||
| 892 | } | ||
| 893 | |||
| 894 | /* Commit the default settings. */ | ||
| 895 | probe->bFormatIndex = format->index; | ||
| 896 | probe->bFrameIndex = frame->bFrameIndex; | ||
| 897 | if ((ret = uvc_set_video_ctrl(video, probe, 0)) < 0) | ||
| 898 | return ret; | ||
| 899 | |||
| 900 | video->streaming->cur_format = format; | ||
| 901 | video->streaming->cur_frame = frame; | ||
| 902 | atomic_set(&video->active, 0); | ||
| 903 | |||
| 904 | /* Select the video decoding function */ | ||
| 905 | if (video->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT) | ||
| 906 | video->decode = uvc_video_decode_isight; | ||
| 907 | else if (video->streaming->intf->num_altsetting > 1) | ||
| 908 | video->decode = uvc_video_decode_isoc; | ||
| 909 | else | ||
| 910 | video->decode = uvc_video_decode_bulk; | ||
| 911 | |||
| 912 | return 0; | ||
| 913 | } | ||
| 914 | |||
| 915 | /* | ||
| 916 | * Enable or disable the video stream. | ||
| 917 | */ | ||
| 918 | int uvc_video_enable(struct uvc_video_device *video, int enable) | ||
| 919 | { | ||
| 920 | int ret; | ||
| 921 | |||
| 922 | if (!enable) { | ||
| 923 | uvc_uninit_video(video); | ||
| 924 | usb_set_interface(video->dev->udev, | ||
| 925 | video->streaming->intfnum, 0); | ||
| 926 | uvc_queue_enable(&video->queue, 0); | ||
| 927 | return 0; | ||
| 928 | } | ||
| 929 | |||
| 930 | if ((ret = uvc_queue_enable(&video->queue, 1)) < 0) | ||
| 931 | return ret; | ||
| 932 | |||
| 933 | return uvc_init_video(video); | ||
| 934 | } | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h new file mode 100644 index 000000000000..a995a780db1c --- /dev/null +++ b/drivers/media/video/uvc/uvcvideo.h | |||
| @@ -0,0 +1,796 @@ | |||
| 1 | #ifndef _USB_VIDEO_H_ | ||
| 2 | #define _USB_VIDEO_H_ | ||
| 3 | |||
| 4 | #include <linux/kernel.h> | ||
| 5 | #include <linux/videodev2.h> | ||
| 6 | |||
| 7 | |||
| 8 | /* | ||
| 9 | * Dynamic controls | ||
| 10 | */ | ||
| 11 | |||
| 12 | /* Data types for UVC control data */ | ||
| 13 | #define UVC_CTRL_DATA_TYPE_RAW 0 | ||
| 14 | #define UVC_CTRL_DATA_TYPE_SIGNED 1 | ||
| 15 | #define UVC_CTRL_DATA_TYPE_UNSIGNED 2 | ||
| 16 | #define UVC_CTRL_DATA_TYPE_BOOLEAN 3 | ||
| 17 | #define UVC_CTRL_DATA_TYPE_ENUM 4 | ||
| 18 | #define UVC_CTRL_DATA_TYPE_BITMASK 5 | ||
| 19 | |||
| 20 | /* Control flags */ | ||
| 21 | #define UVC_CONTROL_SET_CUR (1 << 0) | ||
| 22 | #define UVC_CONTROL_GET_CUR (1 << 1) | ||
| 23 | #define UVC_CONTROL_GET_MIN (1 << 2) | ||
| 24 | #define UVC_CONTROL_GET_MAX (1 << 3) | ||
| 25 | #define UVC_CONTROL_GET_RES (1 << 4) | ||
| 26 | #define UVC_CONTROL_GET_DEF (1 << 5) | ||
| 27 | /* Control should be saved at suspend and restored at resume. */ | ||
| 28 | #define UVC_CONTROL_RESTORE (1 << 6) | ||
| 29 | /* Control can be updated by the camera. */ | ||
| 30 | #define UVC_CONTROL_AUTO_UPDATE (1 << 7) | ||
| 31 | |||
| 32 | #define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \ | ||
| 33 | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \ | ||
| 34 | UVC_CONTROL_GET_DEF) | ||
| 35 | |||
| 36 | struct uvc_xu_control_info { | ||
| 37 | __u8 entity[16]; | ||
| 38 | __u8 index; | ||
| 39 | __u8 selector; | ||
| 40 | __u16 size; | ||
| 41 | __u32 flags; | ||
| 42 | }; | ||
| 43 | |||
| 44 | struct uvc_xu_control_mapping { | ||
| 45 | __u32 id; | ||
| 46 | __u8 name[32]; | ||
| 47 | __u8 entity[16]; | ||
| 48 | __u8 selector; | ||
| 49 | |||
| 50 | __u8 size; | ||
| 51 | __u8 offset; | ||
| 52 | enum v4l2_ctrl_type v4l2_type; | ||
| 53 | __u32 data_type; | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct uvc_xu_control { | ||
| 57 | __u8 unit; | ||
| 58 | __u8 selector; | ||
| 59 | __u16 size; | ||
| 60 | __u8 __user *data; | ||
| 61 | }; | ||
| 62 | |||
| 63 | #define UVCIOC_CTRL_ADD _IOW('U', 1, struct uvc_xu_control_info) | ||
| 64 | #define UVCIOC_CTRL_MAP _IOWR('U', 2, struct uvc_xu_control_mapping) | ||
| 65 | #define UVCIOC_CTRL_GET _IOWR('U', 3, struct uvc_xu_control) | ||
| 66 | #define UVCIOC_CTRL_SET _IOW('U', 4, struct uvc_xu_control) | ||
| 67 | |||
| 68 | #ifdef __KERNEL__ | ||
| 69 | |||
| 70 | #include <linux/poll.h> | ||
| 71 | |||
| 72 | /* -------------------------------------------------------------------------- | ||
| 73 | * UVC constants | ||
| 74 | */ | ||
| 75 | |||
| 76 | #define SC_UNDEFINED 0x00 | ||
| 77 | #define SC_VIDEOCONTROL 0x01 | ||
| 78 | #define SC_VIDEOSTREAMING 0x02 | ||
| 79 | #define SC_VIDEO_INTERFACE_COLLECTION 0x03 | ||
| 80 | |||
| 81 | #define PC_PROTOCOL_UNDEFINED 0x00 | ||
| 82 | |||
| 83 | #define CS_UNDEFINED 0x20 | ||
| 84 | #define CS_DEVICE 0x21 | ||
| 85 | #define CS_CONFIGURATION 0x22 | ||
| 86 | #define CS_STRING 0x23 | ||
| 87 | #define CS_INTERFACE 0x24 | ||
| 88 | #define CS_ENDPOINT 0x25 | ||
| 89 | |||
| 90 | /* VideoControl class specific interface descriptor */ | ||
| 91 | #define VC_DESCRIPTOR_UNDEFINED 0x00 | ||
| 92 | #define VC_HEADER 0x01 | ||
| 93 | #define VC_INPUT_TERMINAL 0x02 | ||
| 94 | #define VC_OUTPUT_TERMINAL 0x03 | ||
| 95 | #define VC_SELECTOR_UNIT 0x04 | ||
| 96 | #define VC_PROCESSING_UNIT 0x05 | ||
| 97 | #define VC_EXTENSION_UNIT 0x06 | ||
| 98 | |||
| 99 | /* VideoStreaming class specific interface descriptor */ | ||
| 100 | #define VS_UNDEFINED 0x00 | ||
| 101 | #define VS_INPUT_HEADER 0x01 | ||
| 102 | #define VS_OUTPUT_HEADER 0x02 | ||
| 103 | #define VS_STILL_IMAGE_FRAME 0x03 | ||
| 104 | #define VS_FORMAT_UNCOMPRESSED 0x04 | ||
| 105 | #define VS_FRAME_UNCOMPRESSED 0x05 | ||
| 106 | #define VS_FORMAT_MJPEG 0x06 | ||
| 107 | #define VS_FRAME_MJPEG 0x07 | ||
| 108 | #define VS_FORMAT_MPEG2TS 0x0a | ||
| 109 | #define VS_FORMAT_DV 0x0c | ||
| 110 | #define VS_COLORFORMAT 0x0d | ||
| 111 | #define VS_FORMAT_FRAME_BASED 0x10 | ||
| 112 | #define VS_FRAME_FRAME_BASED 0x11 | ||
| 113 | #define VS_FORMAT_STREAM_BASED 0x12 | ||
| 114 | |||
| 115 | /* Endpoint type */ | ||
| 116 | #define EP_UNDEFINED 0x00 | ||
| 117 | #define EP_GENERAL 0x01 | ||
| 118 | #define EP_ENDPOINT 0x02 | ||
| 119 | #define EP_INTERRUPT 0x03 | ||
| 120 | |||
| 121 | /* Request codes */ | ||
| 122 | #define RC_UNDEFINED 0x00 | ||
| 123 | #define SET_CUR 0x01 | ||
| 124 | #define GET_CUR 0x81 | ||
| 125 | #define GET_MIN 0x82 | ||
| 126 | #define GET_MAX 0x83 | ||
| 127 | #define GET_RES 0x84 | ||
| 128 | #define GET_LEN 0x85 | ||
| 129 | #define GET_INFO 0x86 | ||
| 130 | #define GET_DEF 0x87 | ||
| 131 | |||
| 132 | /* VideoControl interface controls */ | ||
| 133 | #define VC_CONTROL_UNDEFINED 0x00 | ||
| 134 | #define VC_VIDEO_POWER_MODE_CONTROL 0x01 | ||
| 135 | #define VC_REQUEST_ERROR_CODE_CONTROL 0x02 | ||
| 136 | |||
| 137 | /* Terminal controls */ | ||
| 138 | #define TE_CONTROL_UNDEFINED 0x00 | ||
| 139 | |||
| 140 | /* Selector Unit controls */ | ||
| 141 | #define SU_CONTROL_UNDEFINED 0x00 | ||
| 142 | #define SU_INPUT_SELECT_CONTROL 0x01 | ||
| 143 | |||
| 144 | /* Camera Terminal controls */ | ||
| 145 | #define CT_CONTROL_UNDEFINED 0x00 | ||
| 146 | #define CT_SCANNING_MODE_CONTROL 0x01 | ||
| 147 | #define CT_AE_MODE_CONTROL 0x02 | ||
| 148 | #define CT_AE_PRIORITY_CONTROL 0x03 | ||
| 149 | #define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 | ||
| 150 | #define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 | ||
| 151 | #define CT_FOCUS_ABSOLUTE_CONTROL 0x06 | ||
| 152 | #define CT_FOCUS_RELATIVE_CONTROL 0x07 | ||
| 153 | #define CT_FOCUS_AUTO_CONTROL 0x08 | ||
| 154 | #define CT_IRIS_ABSOLUTE_CONTROL 0x09 | ||
| 155 | #define CT_IRIS_RELATIVE_CONTROL 0x0a | ||
| 156 | #define CT_ZOOM_ABSOLUTE_CONTROL 0x0b | ||
| 157 | #define CT_ZOOM_RELATIVE_CONTROL 0x0c | ||
| 158 | #define CT_PANTILT_ABSOLUTE_CONTROL 0x0d | ||
| 159 | #define CT_PANTILT_RELATIVE_CONTROL 0x0e | ||
| 160 | #define CT_ROLL_ABSOLUTE_CONTROL 0x0f | ||
| 161 | #define CT_ROLL_RELATIVE_CONTROL 0x10 | ||
| 162 | #define CT_PRIVACY_CONTROL 0x11 | ||
| 163 | |||
| 164 | /* Processing Unit controls */ | ||
| 165 | #define PU_CONTROL_UNDEFINED 0x00 | ||
| 166 | #define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 | ||
| 167 | #define PU_BRIGHTNESS_CONTROL 0x02 | ||
| 168 | #define PU_CONTRAST_CONTROL 0x03 | ||
| 169 | #define PU_GAIN_CONTROL 0x04 | ||
| 170 | #define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 | ||
| 171 | #define PU_HUE_CONTROL 0x06 | ||
| 172 | #define PU_SATURATION_CONTROL 0x07 | ||
| 173 | #define PU_SHARPNESS_CONTROL 0x08 | ||
| 174 | #define PU_GAMMA_CONTROL 0x09 | ||
| 175 | #define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a | ||
| 176 | #define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b | ||
| 177 | #define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c | ||
| 178 | #define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d | ||
| 179 | #define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e | ||
| 180 | #define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f | ||
| 181 | #define PU_HUE_AUTO_CONTROL 0x10 | ||
| 182 | #define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 | ||
| 183 | #define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 | ||
| 184 | |||
| 185 | #define LXU_MOTOR_PANTILT_RELATIVE_CONTROL 0x01 | ||
| 186 | #define LXU_MOTOR_PANTILT_RESET_CONTROL 0x02 | ||
| 187 | #define LXU_MOTOR_FOCUS_MOTOR_CONTROL 0x03 | ||
| 188 | |||
| 189 | /* VideoStreaming interface controls */ | ||
| 190 | #define VS_CONTROL_UNDEFINED 0x00 | ||
| 191 | #define VS_PROBE_CONTROL 0x01 | ||
| 192 | #define VS_COMMIT_CONTROL 0x02 | ||
| 193 | #define VS_STILL_PROBE_CONTROL 0x03 | ||
| 194 | #define VS_STILL_COMMIT_CONTROL 0x04 | ||
| 195 | #define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 | ||
| 196 | #define VS_STREAM_ERROR_CODE_CONTROL 0x06 | ||
| 197 | #define VS_GENERATE_KEY_FRAME_CONTROL 0x07 | ||
| 198 | #define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 | ||
| 199 | #define VS_SYNC_DELAY_CONTROL 0x09 | ||
| 200 | |||
| 201 | #define TT_VENDOR_SPECIFIC 0x0100 | ||
| 202 | #define TT_STREAMING 0x0101 | ||
| 203 | |||
| 204 | /* Input Terminal types */ | ||
| 205 | #define ITT_VENDOR_SPECIFIC 0x0200 | ||
| 206 | #define ITT_CAMERA 0x0201 | ||
| 207 | #define ITT_MEDIA_TRANSPORT_INPUT 0x0202 | ||
| 208 | |||
| 209 | /* Output Terminal types */ | ||
| 210 | #define OTT_VENDOR_SPECIFIC 0x0300 | ||
| 211 | #define OTT_DISPLAY 0x0301 | ||
| 212 | #define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 | ||
| 213 | |||
| 214 | /* External Terminal types */ | ||
| 215 | #define EXTERNAL_VENDOR_SPECIFIC 0x0400 | ||
| 216 | #define COMPOSITE_CONNECTOR 0x0401 | ||
| 217 | #define SVIDEO_CONNECTOR 0x0402 | ||
| 218 | #define COMPONENT_CONNECTOR 0x0403 | ||
| 219 | |||
| 220 | #define UVC_TERM_INPUT 0x0000 | ||
| 221 | #define UVC_TERM_OUTPUT 0x8000 | ||
| 222 | |||
| 223 | #define UVC_ENTITY_TYPE(entity) ((entity)->type & 0x7fff) | ||
| 224 | #define UVC_ENTITY_IS_UNIT(entity) (((entity)->type & 0xff00) == 0) | ||
| 225 | #define UVC_ENTITY_IS_TERM(entity) (((entity)->type & 0xff00) != 0) | ||
| 226 | #define UVC_ENTITY_IS_ITERM(entity) \ | ||
| 227 | (((entity)->type & 0x8000) == UVC_TERM_INPUT) | ||
| 228 | #define UVC_ENTITY_IS_OTERM(entity) \ | ||
| 229 | (((entity)->type & 0x8000) == UVC_TERM_OUTPUT) | ||
| 230 | |||
| 231 | #define UVC_STATUS_TYPE_CONTROL 1 | ||
| 232 | #define UVC_STATUS_TYPE_STREAMING 2 | ||
| 233 | |||
| 234 | /* ------------------------------------------------------------------------ | ||
| 235 | * GUIDs | ||
| 236 | */ | ||
| 237 | #define UVC_GUID_UVC_CAMERA \ | ||
| 238 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
| 239 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} | ||
| 240 | #define UVC_GUID_UVC_OUTPUT \ | ||
| 241 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
| 242 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02} | ||
| 243 | #define UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT \ | ||
| 244 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
| 245 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03} | ||
| 246 | #define UVC_GUID_UVC_PROCESSING \ | ||
| 247 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
| 248 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01} | ||
| 249 | #define UVC_GUID_UVC_SELECTOR \ | ||
| 250 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ | ||
| 251 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02} | ||
| 252 | |||
| 253 | #define UVC_GUID_LOGITECH_DEV_INFO \ | ||
| 254 | {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ | ||
| 255 | 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1e} | ||
| 256 | #define UVC_GUID_LOGITECH_USER_HW \ | ||
| 257 | {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ | ||
| 258 | 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f} | ||
| 259 | #define UVC_GUID_LOGITECH_VIDEO \ | ||
| 260 | {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ | ||
| 261 | 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50} | ||
| 262 | #define UVC_GUID_LOGITECH_MOTOR \ | ||
| 263 | {0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ | ||
| 264 | 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56} | ||
| 265 | |||
| 266 | #define UVC_GUID_FORMAT_MJPEG \ | ||
| 267 | { 'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, \ | ||
| 268 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 269 | #define UVC_GUID_FORMAT_YUY2 \ | ||
| 270 | { 'Y', 'U', 'Y', '2', 0x00, 0x00, 0x10, 0x00, \ | ||
| 271 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 272 | #define UVC_GUID_FORMAT_NV12 \ | ||
| 273 | { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ | ||
| 274 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 275 | #define UVC_GUID_FORMAT_YV12 \ | ||
| 276 | { 'Y', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, \ | ||
| 277 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 278 | #define UVC_GUID_FORMAT_I420 \ | ||
| 279 | { 'I', '4', '2', '0', 0x00, 0x00, 0x10, 0x00, \ | ||
| 280 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 281 | #define UVC_GUID_FORMAT_UYVY \ | ||
| 282 | { 'U', 'Y', 'V', 'Y', 0x00, 0x00, 0x10, 0x00, \ | ||
| 283 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 284 | #define UVC_GUID_FORMAT_Y800 \ | ||
| 285 | { 'Y', '8', '0', '0', 0x00, 0x00, 0x10, 0x00, \ | ||
| 286 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 287 | #define UVC_GUID_FORMAT_BY8 \ | ||
| 288 | { 'B', 'Y', '8', ' ', 0x00, 0x00, 0x10, 0x00, \ | ||
| 289 | 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71} | ||
| 290 | |||
| 291 | |||
| 292 | /* ------------------------------------------------------------------------ | ||
| 293 | * Driver specific constants. | ||
| 294 | */ | ||
| 295 | |||
| 296 | #define DRIVER_VERSION_NUMBER KERNEL_VERSION(0, 1, 0) | ||
| 297 | |||
| 298 | /* Number of isochronous URBs. */ | ||
| 299 | #define UVC_URBS 5 | ||
| 300 | /* Maximum number of packets per isochronous URB. */ | ||
| 301 | #define UVC_MAX_ISO_PACKETS 40 | ||
| 302 | /* Maximum frame size in bytes, for sanity checking. */ | ||
| 303 | #define UVC_MAX_FRAME_SIZE (16*1024*1024) | ||
| 304 | /* Maximum number of video buffers. */ | ||
| 305 | #define UVC_MAX_VIDEO_BUFFERS 32 | ||
| 306 | |||
| 307 | #define UVC_CTRL_CONTROL_TIMEOUT 300 | ||
| 308 | #define UVC_CTRL_STREAMING_TIMEOUT 1000 | ||
| 309 | |||
| 310 | /* Devices quirks */ | ||
| 311 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 | ||
| 312 | #define UVC_QUIRK_PROBE_MINMAX 0x00000002 | ||
| 313 | #define UVC_QUIRK_PROBE_EXTRAFIELDS 0x00000004 | ||
| 314 | #define UVC_QUIRK_BUILTIN_ISIGHT 0x00000008 | ||
| 315 | #define UVC_QUIRK_STREAM_NO_FID 0x00000010 | ||
| 316 | #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 | ||
| 317 | |||
| 318 | /* Format flags */ | ||
| 319 | #define UVC_FMT_FLAG_COMPRESSED 0x00000001 | ||
| 320 | #define UVC_FMT_FLAG_STREAM 0x00000002 | ||
| 321 | |||
| 322 | /* ------------------------------------------------------------------------ | ||
| 323 | * Structures. | ||
| 324 | */ | ||
| 325 | |||
| 326 | struct uvc_device; | ||
| 327 | |||
| 328 | /* TODO: Put the most frequently accessed fields at the beginning of | ||
| 329 | * structures to maximize cache efficiency. | ||
| 330 | */ | ||
| 331 | struct uvc_streaming_control { | ||
| 332 | __u16 bmHint; | ||
| 333 | __u8 bFormatIndex; | ||
| 334 | __u8 bFrameIndex; | ||
| 335 | __u32 dwFrameInterval; | ||
| 336 | __u16 wKeyFrameRate; | ||
| 337 | __u16 wPFrameRate; | ||
| 338 | __u16 wCompQuality; | ||
| 339 | __u16 wCompWindowSize; | ||
| 340 | __u16 wDelay; | ||
| 341 | __u32 dwMaxVideoFrameSize; | ||
| 342 | __u32 dwMaxPayloadTransferSize; | ||
| 343 | __u32 dwClockFrequency; | ||
| 344 | __u8 bmFramingInfo; | ||
| 345 | __u8 bPreferedVersion; | ||
| 346 | __u8 bMinVersion; | ||
| 347 | __u8 bMaxVersion; | ||
| 348 | }; | ||
| 349 | |||
| 350 | struct uvc_menu_info { | ||
| 351 | __u32 value; | ||
| 352 | __u8 name[32]; | ||
| 353 | }; | ||
| 354 | |||
| 355 | struct uvc_control_info { | ||
| 356 | struct list_head list; | ||
| 357 | struct list_head mappings; | ||
| 358 | |||
| 359 | __u8 entity[16]; | ||
| 360 | __u8 index; | ||
| 361 | __u8 selector; | ||
| 362 | |||
| 363 | __u16 size; | ||
| 364 | __u32 flags; | ||
| 365 | }; | ||
| 366 | |||
| 367 | struct uvc_control_mapping { | ||
| 368 | struct list_head list; | ||
| 369 | |||
| 370 | struct uvc_control_info *ctrl; | ||
| 371 | |||
| 372 | __u32 id; | ||
| 373 | __u8 name[32]; | ||
| 374 | __u8 entity[16]; | ||
| 375 | __u8 selector; | ||
| 376 | |||
| 377 | __u8 size; | ||
| 378 | __u8 offset; | ||
| 379 | enum v4l2_ctrl_type v4l2_type; | ||
| 380 | __u32 data_type; | ||
| 381 | |||
| 382 | struct uvc_menu_info *menu_info; | ||
| 383 | __u32 menu_count; | ||
| 384 | }; | ||
| 385 | |||
| 386 | struct uvc_control { | ||
| 387 | struct uvc_entity *entity; | ||
| 388 | struct uvc_control_info *info; | ||
| 389 | |||
| 390 | __u8 index; /* Used to match the uvc_control entry with a | ||
| 391 | uvc_control_info. */ | ||
| 392 | __u8 dirty : 1, | ||
| 393 | loaded : 1, | ||
| 394 | modified : 1; | ||
| 395 | |||
| 396 | __u8 *data; | ||
| 397 | }; | ||
| 398 | |||
| 399 | struct uvc_format_desc { | ||
| 400 | char *name; | ||
| 401 | __u8 guid[16]; | ||
| 402 | __u32 fcc; | ||
| 403 | }; | ||
| 404 | |||
| 405 | /* The term 'entity' refers to both UVC units and UVC terminals. | ||
| 406 | * | ||
| 407 | * The type field is either the terminal type (wTerminalType in the terminal | ||
| 408 | * descriptor), or the unit type (bDescriptorSubtype in the unit descriptor). | ||
| 409 | * As the bDescriptorSubtype field is one byte long, the type value will | ||
| 410 | * always have a null MSB for units. All terminal types defined by the UVC | ||
| 411 | * specification have a non-null MSB, so it is safe to use the MSB to | ||
| 412 | * differentiate between units and terminals as long as the descriptor parsing | ||
| 413 | * code makes sure terminal types have a non-null MSB. | ||
| 414 | * | ||
| 415 | * For terminals, the type's most significant bit stores the terminal | ||
| 416 | * direction (either UVC_TERM_INPUT or UVC_TERM_OUTPUT). The type field should | ||
| 417 | * always be accessed with the UVC_ENTITY_* macros and never directly. | ||
| 418 | */ | ||
| 419 | |||
| 420 | struct uvc_entity { | ||
| 421 | struct list_head list; /* Entity as part of a UVC device. */ | ||
| 422 | struct list_head chain; /* Entity as part of a video device | ||
| 423 | * chain. */ | ||
| 424 | __u8 id; | ||
| 425 | __u16 type; | ||
| 426 | char name[64]; | ||
| 427 | |||
| 428 | union { | ||
| 429 | struct { | ||
| 430 | __u16 wObjectiveFocalLengthMin; | ||
| 431 | __u16 wObjectiveFocalLengthMax; | ||
| 432 | __u16 wOcularFocalLength; | ||
| 433 | __u8 bControlSize; | ||
| 434 | __u8 *bmControls; | ||
| 435 | } camera; | ||
| 436 | |||
| 437 | struct { | ||
| 438 | __u8 bControlSize; | ||
| 439 | __u8 *bmControls; | ||
| 440 | __u8 bTransportModeSize; | ||
| 441 | __u8 *bmTransportModes; | ||
| 442 | } media; | ||
| 443 | |||
| 444 | struct { | ||
| 445 | __u8 bSourceID; | ||
| 446 | } output; | ||
| 447 | |||
| 448 | struct { | ||
| 449 | __u8 bSourceID; | ||
| 450 | __u16 wMaxMultiplier; | ||
| 451 | __u8 bControlSize; | ||
| 452 | __u8 *bmControls; | ||
| 453 | __u8 bmVideoStandards; | ||
| 454 | } processing; | ||
| 455 | |||
| 456 | struct { | ||
| 457 | __u8 bNrInPins; | ||
| 458 | __u8 *baSourceID; | ||
| 459 | } selector; | ||
| 460 | |||
| 461 | struct { | ||
| 462 | __u8 guidExtensionCode[16]; | ||
| 463 | __u8 bNumControls; | ||
| 464 | __u8 bNrInPins; | ||
| 465 | __u8 *baSourceID; | ||
| 466 | __u8 bControlSize; | ||
| 467 | __u8 *bmControls; | ||
| 468 | __u8 *bmControlsType; | ||
| 469 | } extension; | ||
| 470 | }; | ||
| 471 | |||
| 472 | unsigned int ncontrols; | ||
| 473 | struct uvc_control *controls; | ||
| 474 | }; | ||
| 475 | |||
| 476 | struct uvc_frame { | ||
| 477 | __u8 bFrameIndex; | ||
| 478 | __u8 bmCapabilities; | ||
| 479 | __u16 wWidth; | ||
| 480 | __u16 wHeight; | ||
| 481 | __u32 dwMinBitRate; | ||
| 482 | __u32 dwMaxBitRate; | ||
| 483 | __u32 dwMaxVideoFrameBufferSize; | ||
| 484 | __u8 bFrameIntervalType; | ||
| 485 | __u32 dwDefaultFrameInterval; | ||
| 486 | __u32 *dwFrameInterval; | ||
| 487 | }; | ||
| 488 | |||
| 489 | struct uvc_format { | ||
| 490 | __u8 type; | ||
| 491 | __u8 index; | ||
| 492 | __u8 bpp; | ||
| 493 | __u8 colorspace; | ||
| 494 | __u32 fcc; | ||
| 495 | __u32 flags; | ||
| 496 | |||
| 497 | char name[32]; | ||
| 498 | |||
| 499 | unsigned int nframes; | ||
| 500 | struct uvc_frame *frame; | ||
| 501 | }; | ||
| 502 | |||
| 503 | struct uvc_streaming_header { | ||
| 504 | __u8 bNumFormats; | ||
| 505 | __u8 bEndpointAddress; | ||
| 506 | __u8 bTerminalLink; | ||
| 507 | __u8 bControlSize; | ||
| 508 | __u8 *bmaControls; | ||
| 509 | /* The following fields are used by input headers only. */ | ||
| 510 | __u8 bmInfo; | ||
| 511 | __u8 bStillCaptureMethod; | ||
| 512 | __u8 bTriggerSupport; | ||
| 513 | __u8 bTriggerUsage; | ||
| 514 | }; | ||
| 515 | |||
| 516 | struct uvc_streaming { | ||
| 517 | struct list_head list; | ||
| 518 | |||
| 519 | struct usb_interface *intf; | ||
| 520 | int intfnum; | ||
| 521 | __u16 maxpsize; | ||
| 522 | |||
| 523 | struct uvc_streaming_header header; | ||
| 524 | |||
| 525 | unsigned int nformats; | ||
| 526 | struct uvc_format *format; | ||
| 527 | |||
| 528 | struct uvc_streaming_control ctrl; | ||
| 529 | struct uvc_format *cur_format; | ||
| 530 | struct uvc_frame *cur_frame; | ||
| 531 | |||
| 532 | struct mutex mutex; | ||
| 533 | }; | ||
| 534 | |||
| 535 | enum uvc_buffer_state { | ||
| 536 | UVC_BUF_STATE_IDLE = 0, | ||
| 537 | UVC_BUF_STATE_QUEUED = 1, | ||
| 538 | UVC_BUF_STATE_ACTIVE = 2, | ||
| 539 | UVC_BUF_STATE_DONE = 3, | ||
| 540 | UVC_BUF_STATE_ERROR = 4, | ||
| 541 | }; | ||
| 542 | |||
| 543 | struct uvc_buffer { | ||
| 544 | unsigned long vma_use_count; | ||
| 545 | struct list_head stream; | ||
| 546 | |||
| 547 | /* Touched by interrupt handler. */ | ||
| 548 | struct v4l2_buffer buf; | ||
| 549 | struct list_head queue; | ||
| 550 | wait_queue_head_t wait; | ||
| 551 | enum uvc_buffer_state state; | ||
| 552 | }; | ||
| 553 | |||
| 554 | #define UVC_QUEUE_STREAMING (1 << 0) | ||
| 555 | #define UVC_QUEUE_DISCONNECTED (1 << 1) | ||
| 556 | #define UVC_QUEUE_DROP_INCOMPLETE (1 << 2) | ||
| 557 | |||
| 558 | struct uvc_video_queue { | ||
| 559 | void *mem; | ||
| 560 | unsigned int flags; | ||
| 561 | __u32 sequence; | ||
| 562 | |||
| 563 | unsigned int count; | ||
| 564 | unsigned int buf_size; | ||
| 565 | struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS]; | ||
| 566 | struct mutex mutex; /* protects buffers and mainqueue */ | ||
| 567 | spinlock_t irqlock; /* protects irqqueue */ | ||
| 568 | |||
| 569 | struct list_head mainqueue; | ||
| 570 | struct list_head irqqueue; | ||
| 571 | }; | ||
| 572 | |||
| 573 | struct uvc_video_device { | ||
| 574 | struct uvc_device *dev; | ||
| 575 | struct video_device *vdev; | ||
| 576 | atomic_t active; | ||
| 577 | unsigned int frozen : 1; | ||
| 578 | |||
| 579 | struct list_head iterms; | ||
| 580 | struct uvc_entity *oterm; | ||
| 581 | struct uvc_entity *processing; | ||
| 582 | struct uvc_entity *selector; | ||
| 583 | struct list_head extensions; | ||
| 584 | struct mutex ctrl_mutex; | ||
| 585 | |||
| 586 | struct uvc_video_queue queue; | ||
| 587 | |||
| 588 | /* Video streaming object, must always be non-NULL. */ | ||
| 589 | struct uvc_streaming *streaming; | ||
| 590 | |||
| 591 | void (*decode) (struct urb *urb, struct uvc_video_device *video, | ||
| 592 | struct uvc_buffer *buf); | ||
| 593 | |||
| 594 | /* Context data used by the bulk completion handler. */ | ||
| 595 | struct { | ||
| 596 | __u8 header[256]; | ||
| 597 | unsigned int header_size; | ||
| 598 | int skip_payload; | ||
| 599 | __u32 payload_size; | ||
| 600 | __u32 max_payload_size; | ||
| 601 | } bulk; | ||
| 602 | |||
| 603 | struct urb *urb[UVC_URBS]; | ||
| 604 | char *urb_buffer[UVC_URBS]; | ||
| 605 | |||
| 606 | __u8 last_fid; | ||
| 607 | }; | ||
| 608 | |||
| 609 | enum uvc_device_state { | ||
| 610 | UVC_DEV_DISCONNECTED = 1, | ||
| 611 | }; | ||
| 612 | |||
| 613 | struct uvc_device { | ||
| 614 | struct usb_device *udev; | ||
| 615 | struct usb_interface *intf; | ||
| 616 | __u32 quirks; | ||
| 617 | int intfnum; | ||
| 618 | char name[32]; | ||
| 619 | |||
| 620 | enum uvc_device_state state; | ||
| 621 | struct kref kref; | ||
| 622 | struct list_head list; | ||
| 623 | |||
| 624 | /* Video control interface */ | ||
| 625 | __u16 uvc_version; | ||
| 626 | __u32 clock_frequency; | ||
| 627 | |||
| 628 | struct list_head entities; | ||
| 629 | |||
| 630 | struct uvc_video_device video; | ||
| 631 | |||
| 632 | /* Status Interrupt Endpoint */ | ||
| 633 | struct usb_host_endpoint *int_ep; | ||
| 634 | struct urb *int_urb; | ||
| 635 | __u8 status[16]; | ||
| 636 | struct input_dev *input; | ||
| 637 | |||
| 638 | /* Video Streaming interfaces */ | ||
| 639 | struct list_head streaming; | ||
| 640 | }; | ||
| 641 | |||
| 642 | enum uvc_handle_state { | ||
| 643 | UVC_HANDLE_PASSIVE = 0, | ||
| 644 | UVC_HANDLE_ACTIVE = 1, | ||
| 645 | }; | ||
| 646 | |||
| 647 | struct uvc_fh { | ||
| 648 | struct uvc_video_device *device; | ||
| 649 | enum uvc_handle_state state; | ||
| 650 | }; | ||
| 651 | |||
| 652 | struct uvc_driver { | ||
| 653 | struct usb_driver driver; | ||
| 654 | |||
| 655 | struct mutex open_mutex; /* protects from open/disconnect race */ | ||
| 656 | |||
| 657 | struct list_head devices; /* struct uvc_device list */ | ||
| 658 | struct list_head controls; /* struct uvc_control_info list */ | ||
| 659 | struct mutex ctrl_mutex; /* protects controls and devices | ||
| 660 | lists */ | ||
| 661 | }; | ||
| 662 | |||
| 663 | /* ------------------------------------------------------------------------ | ||
| 664 | * Debugging, printing and logging | ||
| 665 | */ | ||
| 666 | |||
| 667 | #define UVC_TRACE_PROBE (1 << 0) | ||
| 668 | #define UVC_TRACE_DESCR (1 << 1) | ||
| 669 | #define UVC_TRACE_CONTROL (1 << 2) | ||
| 670 | #define UVC_TRACE_FORMAT (1 << 3) | ||
| 671 | #define UVC_TRACE_CAPTURE (1 << 4) | ||
| 672 | #define UVC_TRACE_CALLS (1 << 5) | ||
| 673 | #define UVC_TRACE_IOCTL (1 << 6) | ||
| 674 | #define UVC_TRACE_FRAME (1 << 7) | ||
| 675 | #define UVC_TRACE_SUSPEND (1 << 8) | ||
| 676 | #define UVC_TRACE_STATUS (1 << 9) | ||
| 677 | |||
| 678 | extern unsigned int uvc_trace_param; | ||
| 679 | |||
| 680 | #define uvc_trace(flag, msg...) \ | ||
| 681 | do { \ | ||
| 682 | if (uvc_trace_param & flag) \ | ||
| 683 | printk(KERN_DEBUG "uvcvideo: " msg); \ | ||
| 684 | } while (0) | ||
| 685 | |||
| 686 | #define uvc_printk(level, msg...) \ | ||
| 687 | printk(level "uvcvideo: " msg) | ||
| 688 | |||
| 689 | #define UVC_GUID_FORMAT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" \ | ||
| 690 | "%02x%02x%02x%02x%02x%02x" | ||
| 691 | #define UVC_GUID_ARGS(guid) \ | ||
| 692 | (guid)[3], (guid)[2], (guid)[1], (guid)[0], \ | ||
| 693 | (guid)[5], (guid)[4], \ | ||
| 694 | (guid)[7], (guid)[6], \ | ||
| 695 | (guid)[8], (guid)[9], \ | ||
| 696 | (guid)[10], (guid)[11], (guid)[12], \ | ||
| 697 | (guid)[13], (guid)[14], (guid)[15] | ||
| 698 | |||
| 699 | /* -------------------------------------------------------------------------- | ||
| 700 | * Internal functions. | ||
| 701 | */ | ||
| 702 | |||
| 703 | /* Core driver */ | ||
| 704 | extern struct uvc_driver uvc_driver; | ||
| 705 | extern void uvc_delete(struct kref *kref); | ||
| 706 | |||
| 707 | /* Video buffers queue management. */ | ||
| 708 | extern void uvc_queue_init(struct uvc_video_queue *queue); | ||
| 709 | extern int uvc_alloc_buffers(struct uvc_video_queue *queue, | ||
| 710 | unsigned int nbuffers, unsigned int buflength); | ||
| 711 | extern int uvc_free_buffers(struct uvc_video_queue *queue); | ||
| 712 | extern int uvc_query_buffer(struct uvc_video_queue *queue, | ||
| 713 | struct v4l2_buffer *v4l2_buf); | ||
| 714 | extern int uvc_queue_buffer(struct uvc_video_queue *queue, | ||
| 715 | struct v4l2_buffer *v4l2_buf); | ||
| 716 | extern int uvc_dequeue_buffer(struct uvc_video_queue *queue, | ||
| 717 | struct v4l2_buffer *v4l2_buf, int nonblocking); | ||
| 718 | extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable); | ||
| 719 | extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect); | ||
| 720 | extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | ||
| 721 | struct uvc_buffer *buf); | ||
| 722 | extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, | ||
| 723 | struct file *file, poll_table *wait); | ||
| 724 | static inline int uvc_queue_streaming(struct uvc_video_queue *queue) | ||
| 725 | { | ||
| 726 | return queue->flags & UVC_QUEUE_STREAMING; | ||
| 727 | } | ||
| 728 | |||
| 729 | /* V4L2 interface */ | ||
| 730 | extern struct file_operations uvc_fops; | ||
| 731 | |||
| 732 | /* Video */ | ||
| 733 | extern int uvc_video_init(struct uvc_video_device *video); | ||
| 734 | extern int uvc_video_suspend(struct uvc_video_device *video); | ||
| 735 | extern int uvc_video_resume(struct uvc_video_device *video); | ||
| 736 | extern int uvc_video_enable(struct uvc_video_device *video, int enable); | ||
| 737 | extern int uvc_probe_video(struct uvc_video_device *video, | ||
| 738 | struct uvc_streaming_control *probe); | ||
| 739 | extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | ||
| 740 | __u8 intfnum, __u8 cs, void *data, __u16 size); | ||
| 741 | extern int uvc_set_video_ctrl(struct uvc_video_device *video, | ||
| 742 | struct uvc_streaming_control *ctrl, int probe); | ||
| 743 | |||
| 744 | /* Status */ | ||
| 745 | extern int uvc_status_init(struct uvc_device *dev); | ||
| 746 | extern void uvc_status_cleanup(struct uvc_device *dev); | ||
| 747 | extern int uvc_status_suspend(struct uvc_device *dev); | ||
| 748 | extern int uvc_status_resume(struct uvc_device *dev); | ||
| 749 | |||
| 750 | /* Controls */ | ||
| 751 | extern struct uvc_control *uvc_find_control(struct uvc_video_device *video, | ||
| 752 | __u32 v4l2_id, struct uvc_control_mapping **mapping); | ||
| 753 | extern int uvc_query_v4l2_ctrl(struct uvc_video_device *video, | ||
| 754 | struct v4l2_queryctrl *v4l2_ctrl); | ||
| 755 | |||
| 756 | extern int uvc_ctrl_add_info(struct uvc_control_info *info); | ||
| 757 | extern int uvc_ctrl_add_mapping(struct uvc_control_mapping *mapping); | ||
| 758 | extern int uvc_ctrl_init_device(struct uvc_device *dev); | ||
| 759 | extern void uvc_ctrl_cleanup_device(struct uvc_device *dev); | ||
| 760 | extern int uvc_ctrl_resume_device(struct uvc_device *dev); | ||
| 761 | extern void uvc_ctrl_init(void); | ||
| 762 | |||
| 763 | extern int uvc_ctrl_begin(struct uvc_video_device *video); | ||
| 764 | extern int __uvc_ctrl_commit(struct uvc_video_device *video, int rollback); | ||
| 765 | static inline int uvc_ctrl_commit(struct uvc_video_device *video) | ||
| 766 | { | ||
| 767 | return __uvc_ctrl_commit(video, 0); | ||
| 768 | } | ||
| 769 | static inline int uvc_ctrl_rollback(struct uvc_video_device *video) | ||
| 770 | { | ||
| 771 | return __uvc_ctrl_commit(video, 1); | ||
| 772 | } | ||
| 773 | |||
| 774 | extern int uvc_ctrl_get(struct uvc_video_device *video, | ||
| 775 | struct v4l2_ext_control *xctrl); | ||
| 776 | extern int uvc_ctrl_set(struct uvc_video_device *video, | ||
| 777 | struct v4l2_ext_control *xctrl); | ||
| 778 | |||
| 779 | extern int uvc_xu_ctrl_query(struct uvc_video_device *video, | ||
| 780 | struct uvc_xu_control *ctrl, int set); | ||
| 781 | |||
| 782 | /* Utility functions */ | ||
| 783 | extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator, | ||
| 784 | unsigned int n_terms, unsigned int threshold); | ||
| 785 | extern uint32_t uvc_fraction_to_interval(uint32_t numerator, | ||
| 786 | uint32_t denominator); | ||
| 787 | extern struct usb_host_endpoint *uvc_find_endpoint( | ||
| 788 | struct usb_host_interface *alts, __u8 epaddr); | ||
| 789 | |||
| 790 | /* Quirks support */ | ||
| 791 | void uvc_video_decode_isight(struct urb *urb, struct uvc_video_device *video, | ||
| 792 | struct uvc_buffer *buf); | ||
| 793 | |||
| 794 | #endif /* __KERNEL__ */ | ||
| 795 | |||
| 796 | #endif | ||
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c index 31e8af0ba278..67a661cf5219 100644 --- a/drivers/media/video/videodev.c +++ b/drivers/media/video/videodev.c | |||
| @@ -51,12 +51,51 @@ | |||
| 51 | #define VIDEO_NUM_DEVICES 256 | 51 | #define VIDEO_NUM_DEVICES 256 |
| 52 | #define VIDEO_NAME "video4linux" | 52 | #define VIDEO_NAME "video4linux" |
| 53 | 53 | ||
| 54 | struct std_descr { | ||
| 55 | v4l2_std_id std; | ||
| 56 | const char *descr; | ||
| 57 | }; | ||
| 58 | |||
| 59 | static const struct std_descr standards[] = { | ||
| 60 | { V4L2_STD_NTSC, "NTSC" }, | ||
| 61 | { V4L2_STD_NTSC_M, "NTSC-M" }, | ||
| 62 | { V4L2_STD_NTSC_M_JP, "NTSC-M-JP" }, | ||
| 63 | { V4L2_STD_NTSC_M_KR, "NTSC-M-KR" }, | ||
| 64 | { V4L2_STD_NTSC_443, "NTSC-443" }, | ||
| 65 | { V4L2_STD_PAL, "PAL" }, | ||
| 66 | { V4L2_STD_PAL_BG, "PAL-BG" }, | ||
| 67 | { V4L2_STD_PAL_B, "PAL-B" }, | ||
| 68 | { V4L2_STD_PAL_B1, "PAL-B1" }, | ||
| 69 | { V4L2_STD_PAL_G, "PAL-G" }, | ||
| 70 | { V4L2_STD_PAL_H, "PAL-H" }, | ||
| 71 | { V4L2_STD_PAL_I, "PAL-I" }, | ||
| 72 | { V4L2_STD_PAL_DK, "PAL-DK" }, | ||
| 73 | { V4L2_STD_PAL_D, "PAL-D" }, | ||
| 74 | { V4L2_STD_PAL_D1, "PAL-D1" }, | ||
| 75 | { V4L2_STD_PAL_K, "PAL-K" }, | ||
| 76 | { V4L2_STD_PAL_M, "PAL-M" }, | ||
| 77 | { V4L2_STD_PAL_N, "PAL-N" }, | ||
| 78 | { V4L2_STD_PAL_Nc, "PAL-Nc" }, | ||
| 79 | { V4L2_STD_PAL_60, "PAL-60" }, | ||
| 80 | { V4L2_STD_SECAM, "SECAM" }, | ||
| 81 | { V4L2_STD_SECAM_B, "SECAM-B" }, | ||
| 82 | { V4L2_STD_SECAM_G, "SECAM-G" }, | ||
| 83 | { V4L2_STD_SECAM_H, "SECAM-H" }, | ||
| 84 | { V4L2_STD_SECAM_DK, "SECAM-DK" }, | ||
| 85 | { V4L2_STD_SECAM_D, "SECAM-D" }, | ||
| 86 | { V4L2_STD_SECAM_K, "SECAM-K" }, | ||
| 87 | { V4L2_STD_SECAM_K1, "SECAM-K1" }, | ||
| 88 | { V4L2_STD_SECAM_L, "SECAM-L" }, | ||
| 89 | { V4L2_STD_SECAM_LC, "SECAM-Lc" }, | ||
| 90 | { 0, "Unknown" } | ||
| 91 | }; | ||
| 92 | |||
| 54 | /* video4linux standard ID conversion to standard name | 93 | /* video4linux standard ID conversion to standard name |
| 55 | */ | 94 | */ |
| 56 | char *v4l2_norm_to_name(v4l2_std_id id) | 95 | const char *v4l2_norm_to_name(v4l2_std_id id) |
| 57 | { | 96 | { |
| 58 | char *name; | ||
| 59 | u32 myid = id; | 97 | u32 myid = id; |
| 98 | int i; | ||
| 60 | 99 | ||
| 61 | /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle | 100 | /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle |
| 62 | 64 bit comparations. So, on that architecture, with some gcc | 101 | 64 bit comparations. So, on that architecture, with some gcc |
| @@ -64,110 +103,17 @@ char *v4l2_norm_to_name(v4l2_std_id id) | |||
| 64 | */ | 103 | */ |
| 65 | BUG_ON(myid != id); | 104 | BUG_ON(myid != id); |
| 66 | 105 | ||
| 67 | switch (myid) { | 106 | for (i = 0; standards[i].std; i++) |
| 68 | case V4L2_STD_PAL: | 107 | if (myid == standards[i].std) |
| 69 | name = "PAL"; | 108 | break; |
| 70 | break; | 109 | return standards[i].descr; |
| 71 | case V4L2_STD_PAL_BG: | ||
| 72 | name = "PAL-BG"; | ||
| 73 | break; | ||
| 74 | case V4L2_STD_PAL_DK: | ||
| 75 | name = "PAL-DK"; | ||
| 76 | break; | ||
| 77 | case V4L2_STD_PAL_B: | ||
| 78 | name = "PAL-B"; | ||
| 79 | break; | ||
| 80 | case V4L2_STD_PAL_B1: | ||
| 81 | name = "PAL-B1"; | ||
| 82 | break; | ||
| 83 | case V4L2_STD_PAL_G: | ||
| 84 | name = "PAL-G"; | ||
| 85 | break; | ||
| 86 | case V4L2_STD_PAL_H: | ||
| 87 | name = "PAL-H"; | ||
| 88 | break; | ||
| 89 | case V4L2_STD_PAL_I: | ||
| 90 | name = "PAL-I"; | ||
| 91 | break; | ||
| 92 | case V4L2_STD_PAL_D: | ||
| 93 | name = "PAL-D"; | ||
| 94 | break; | ||
| 95 | case V4L2_STD_PAL_D1: | ||
| 96 | name = "PAL-D1"; | ||
| 97 | break; | ||
| 98 | case V4L2_STD_PAL_K: | ||
| 99 | name = "PAL-K"; | ||
| 100 | break; | ||
| 101 | case V4L2_STD_PAL_M: | ||
| 102 | name = "PAL-M"; | ||
| 103 | break; | ||
| 104 | case V4L2_STD_PAL_N: | ||
| 105 | name = "PAL-N"; | ||
| 106 | break; | ||
| 107 | case V4L2_STD_PAL_Nc: | ||
| 108 | name = "PAL-Nc"; | ||
| 109 | break; | ||
| 110 | case V4L2_STD_PAL_60: | ||
| 111 | name = "PAL-60"; | ||
| 112 | break; | ||
| 113 | case V4L2_STD_NTSC: | ||
| 114 | name = "NTSC"; | ||
| 115 | break; | ||
| 116 | case V4L2_STD_NTSC_M: | ||
| 117 | name = "NTSC-M"; | ||
| 118 | break; | ||
| 119 | case V4L2_STD_NTSC_M_JP: | ||
| 120 | name = "NTSC-M-JP"; | ||
| 121 | break; | ||
| 122 | case V4L2_STD_NTSC_443: | ||
| 123 | name = "NTSC-443"; | ||
| 124 | break; | ||
| 125 | case V4L2_STD_NTSC_M_KR: | ||
| 126 | name = "NTSC-M-KR"; | ||
| 127 | break; | ||
| 128 | case V4L2_STD_SECAM: | ||
| 129 | name = "SECAM"; | ||
| 130 | break; | ||
| 131 | case V4L2_STD_SECAM_DK: | ||
| 132 | name = "SECAM-DK"; | ||
| 133 | break; | ||
| 134 | case V4L2_STD_SECAM_B: | ||
| 135 | name = "SECAM-B"; | ||
| 136 | break; | ||
| 137 | case V4L2_STD_SECAM_D: | ||
| 138 | name = "SECAM-D"; | ||
| 139 | break; | ||
| 140 | case V4L2_STD_SECAM_G: | ||
| 141 | name = "SECAM-G"; | ||
| 142 | break; | ||
| 143 | case V4L2_STD_SECAM_H: | ||
| 144 | name = "SECAM-H"; | ||
| 145 | break; | ||
| 146 | case V4L2_STD_SECAM_K: | ||
| 147 | name = "SECAM-K"; | ||
| 148 | break; | ||
| 149 | case V4L2_STD_SECAM_K1: | ||
| 150 | name = "SECAM-K1"; | ||
| 151 | break; | ||
| 152 | case V4L2_STD_SECAM_L: | ||
| 153 | name = "SECAM-L"; | ||
| 154 | break; | ||
| 155 | case V4L2_STD_SECAM_LC: | ||
| 156 | name = "SECAM-LC"; | ||
| 157 | break; | ||
| 158 | default: | ||
| 159 | name = "Unknown"; | ||
| 160 | break; | ||
| 161 | } | ||
| 162 | |||
| 163 | return name; | ||
| 164 | } | 110 | } |
| 165 | EXPORT_SYMBOL(v4l2_norm_to_name); | 111 | EXPORT_SYMBOL(v4l2_norm_to_name); |
| 166 | 112 | ||
| 167 | /* Fill in the fields of a v4l2_standard structure according to the | 113 | /* Fill in the fields of a v4l2_standard structure according to the |
| 168 | 'id' and 'transmission' parameters. Returns negative on error. */ | 114 | 'id' and 'transmission' parameters. Returns negative on error. */ |
| 169 | int v4l2_video_std_construct(struct v4l2_standard *vs, | 115 | int v4l2_video_std_construct(struct v4l2_standard *vs, |
| 170 | int id, char *name) | 116 | int id, const char *name) |
| 171 | { | 117 | { |
| 172 | u32 index = vs->index; | 118 | u32 index = vs->index; |
| 173 | 119 | ||
| @@ -1218,95 +1164,40 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, | |||
| 1218 | case VIDIOC_ENUMSTD: | 1164 | case VIDIOC_ENUMSTD: |
| 1219 | { | 1165 | { |
| 1220 | struct v4l2_standard *p = arg; | 1166 | struct v4l2_standard *p = arg; |
| 1221 | v4l2_std_id id = vfd->tvnorms,curr_id=0; | 1167 | v4l2_std_id id = vfd->tvnorms, curr_id = 0; |
| 1222 | unsigned int index = p->index,i; | 1168 | unsigned int index = p->index, i, j = 0; |
| 1223 | 1169 | const char *descr = ""; | |
| 1224 | if (index<0) { | 1170 | |
| 1225 | ret=-EINVAL; | 1171 | /* Return norm array in a canonical way */ |
| 1226 | break; | 1172 | for (i = 0; i <= index && id; i++) { |
| 1227 | } | 1173 | /* last std value in the standards array is 0, so this |
| 1228 | 1174 | while always ends there since (id & 0) == 0. */ | |
| 1229 | /* Return norm array on a canonical way */ | 1175 | while ((id & standards[j].std) != standards[j].std) |
| 1230 | for (i=0;i<= index && id; i++) { | 1176 | j++; |
| 1231 | if ( (id & V4L2_STD_PAL) == V4L2_STD_PAL) { | 1177 | curr_id = standards[j].std; |
| 1232 | curr_id = V4L2_STD_PAL; | 1178 | descr = standards[j].descr; |
| 1233 | } else if ( (id & V4L2_STD_PAL_BG) == V4L2_STD_PAL_BG) { | 1179 | j++; |
| 1234 | curr_id = V4L2_STD_PAL_BG; | 1180 | if (curr_id == 0) |
| 1235 | } else if ( (id & V4L2_STD_PAL_DK) == V4L2_STD_PAL_DK) { | ||
| 1236 | curr_id = V4L2_STD_PAL_DK; | ||
| 1237 | } else if ( (id & V4L2_STD_PAL_B) == V4L2_STD_PAL_B) { | ||
| 1238 | curr_id = V4L2_STD_PAL_B; | ||
| 1239 | } else if ( (id & V4L2_STD_PAL_B1) == V4L2_STD_PAL_B1) { | ||
| 1240 | curr_id = V4L2_STD_PAL_B1; | ||
| 1241 | } else if ( (id & V4L2_STD_PAL_G) == V4L2_STD_PAL_G) { | ||
| 1242 | curr_id = V4L2_STD_PAL_G; | ||
| 1243 | } else if ( (id & V4L2_STD_PAL_H) == V4L2_STD_PAL_H) { | ||
| 1244 | curr_id = V4L2_STD_PAL_H; | ||
| 1245 | } else if ( (id & V4L2_STD_PAL_I) == V4L2_STD_PAL_I) { | ||
| 1246 | curr_id = V4L2_STD_PAL_I; | ||
| 1247 | } else if ( (id & V4L2_STD_PAL_D) == V4L2_STD_PAL_D) { | ||
| 1248 | curr_id = V4L2_STD_PAL_D; | ||
| 1249 | } else if ( (id & V4L2_STD_PAL_D1) == V4L2_STD_PAL_D1) { | ||
| 1250 | curr_id = V4L2_STD_PAL_D1; | ||
| 1251 | } else if ( (id & V4L2_STD_PAL_K) == V4L2_STD_PAL_K) { | ||
| 1252 | curr_id = V4L2_STD_PAL_K; | ||
| 1253 | } else if ( (id & V4L2_STD_PAL_M) == V4L2_STD_PAL_M) { | ||
| 1254 | curr_id = V4L2_STD_PAL_M; | ||
| 1255 | } else if ( (id & V4L2_STD_PAL_N) == V4L2_STD_PAL_N) { | ||
| 1256 | curr_id = V4L2_STD_PAL_N; | ||
| 1257 | } else if ( (id & V4L2_STD_PAL_Nc) == V4L2_STD_PAL_Nc) { | ||
| 1258 | curr_id = V4L2_STD_PAL_Nc; | ||
| 1259 | } else if ( (id & V4L2_STD_PAL_60) == V4L2_STD_PAL_60) { | ||
| 1260 | curr_id = V4L2_STD_PAL_60; | ||
| 1261 | } else if ( (id & V4L2_STD_NTSC) == V4L2_STD_NTSC) { | ||
| 1262 | curr_id = V4L2_STD_NTSC; | ||
| 1263 | } else if ( (id & V4L2_STD_NTSC_M) == V4L2_STD_NTSC_M) { | ||
| 1264 | curr_id = V4L2_STD_NTSC_M; | ||
| 1265 | } else if ( (id & V4L2_STD_NTSC_M_JP) == V4L2_STD_NTSC_M_JP) { | ||
| 1266 | curr_id = V4L2_STD_NTSC_M_JP; | ||
| 1267 | } else if ( (id & V4L2_STD_NTSC_443) == V4L2_STD_NTSC_443) { | ||
| 1268 | curr_id = V4L2_STD_NTSC_443; | ||
| 1269 | } else if ( (id & V4L2_STD_NTSC_M_KR) == V4L2_STD_NTSC_M_KR) { | ||
| 1270 | curr_id = V4L2_STD_NTSC_M_KR; | ||
| 1271 | } else if ( (id & V4L2_STD_SECAM) == V4L2_STD_SECAM) { | ||
| 1272 | curr_id = V4L2_STD_SECAM; | ||
| 1273 | } else if ( (id & V4L2_STD_SECAM_DK) == V4L2_STD_SECAM_DK) { | ||
| 1274 | curr_id = V4L2_STD_SECAM_DK; | ||
| 1275 | } else if ( (id & V4L2_STD_SECAM_B) == V4L2_STD_SECAM_B) { | ||
| 1276 | curr_id = V4L2_STD_SECAM_B; | ||
| 1277 | } else if ( (id & V4L2_STD_SECAM_D) == V4L2_STD_SECAM_D) { | ||
| 1278 | curr_id = V4L2_STD_SECAM_D; | ||
| 1279 | } else if ( (id & V4L2_STD_SECAM_G) == V4L2_STD_SECAM_G) { | ||
| 1280 | curr_id = V4L2_STD_SECAM_G; | ||
| 1281 | } else if ( (id & V4L2_STD_SECAM_H) == V4L2_STD_SECAM_H) { | ||
| 1282 | curr_id = V4L2_STD_SECAM_H; | ||
| 1283 | } else if ( (id & V4L2_STD_SECAM_K) == V4L2_STD_SECAM_K) { | ||
| 1284 | curr_id = V4L2_STD_SECAM_K; | ||
| 1285 | } else if ( (id & V4L2_STD_SECAM_K1) == V4L2_STD_SECAM_K1) { | ||
| 1286 | curr_id = V4L2_STD_SECAM_K1; | ||
| 1287 | } else if ( (id & V4L2_STD_SECAM_L) == V4L2_STD_SECAM_L) { | ||
| 1288 | curr_id = V4L2_STD_SECAM_L; | ||
| 1289 | } else if ( (id & V4L2_STD_SECAM_LC) == V4L2_STD_SECAM_LC) { | ||
| 1290 | curr_id = V4L2_STD_SECAM_LC; | ||
| 1291 | } else { | ||
| 1292 | break; | 1181 | break; |
| 1293 | } | 1182 | if (curr_id != V4L2_STD_PAL && |
| 1294 | id &= ~curr_id; | 1183 | curr_id != V4L2_STD_SECAM && |
| 1184 | curr_id != V4L2_STD_NTSC) | ||
| 1185 | id &= ~curr_id; | ||
| 1295 | } | 1186 | } |
| 1296 | if (i<=index) | 1187 | if (i <= index) |
| 1297 | return -EINVAL; | 1188 | return -EINVAL; |
| 1298 | 1189 | ||
| 1299 | v4l2_video_std_construct(p, curr_id,v4l2_norm_to_name(curr_id)); | 1190 | v4l2_video_std_construct(p, curr_id, descr); |
| 1300 | p->index = index; | 1191 | p->index = index; |
| 1301 | 1192 | ||
| 1302 | dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " | 1193 | dbgarg(cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, " |
| 1303 | "framelines=%d\n", p->index, | 1194 | "framelines=%d\n", p->index, |
| 1304 | (unsigned long long)p->id, p->name, | 1195 | (unsigned long long)p->id, p->name, |
| 1305 | p->frameperiod.numerator, | 1196 | p->frameperiod.numerator, |
| 1306 | p->frameperiod.denominator, | 1197 | p->frameperiod.denominator, |
| 1307 | p->framelines); | 1198 | p->framelines); |
| 1308 | 1199 | ||
| 1309 | ret=0; | 1200 | ret = 0; |
| 1310 | break; | 1201 | break; |
| 1311 | } | 1202 | } |
| 1312 | case VIDIOC_G_STD: | 1203 | case VIDIOC_G_STD: |
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 845be1864f68..5ff9a58b6135 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c | |||
| @@ -327,13 +327,14 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf) | |||
| 327 | int hmax = buf->vb.height; | 327 | int hmax = buf->vb.height; |
| 328 | int wmax = buf->vb.width; | 328 | int wmax = buf->vb.width; |
| 329 | struct timeval ts; | 329 | struct timeval ts; |
| 330 | char *tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC); | 330 | char *tmpbuf; |
| 331 | void *vbuf = videobuf_to_vmalloc(&buf->vb); | 331 | void *vbuf = videobuf_to_vmalloc(&buf->vb); |
| 332 | 332 | ||
| 333 | if (!tmpbuf) | 333 | if (!vbuf) |
| 334 | return; | 334 | return; |
| 335 | 335 | ||
| 336 | if (!vbuf) | 336 | tmpbuf = kmalloc(wmax * 2, GFP_ATOMIC); |
| 337 | if (!tmpbuf) | ||
| 337 | return; | 338 | return; |
| 338 | 339 | ||
| 339 | for (h = 0; h < hmax; h++) { | 340 | for (h = 0; h < hmax; h++) { |
