Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] dvb: usb: add supprt for WideView WT-220U

Add support and rewrote some parts with the help of vendor information
(Thanks to Steve Chang from WideView, Inc.):

o added support for the WT-220U (Pensize DVB-T receiver)
o corrected byte order for unc,ber and the pid filter
o corrected number of pids that can be fetched at the same time.
o added some comments in Kconfig-file
o added USB IDs for the WT-220U

Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Patrick Boettcher and committed by
Linus Torvalds
d590f9c2 4b2bd30e

+130 -73
+3 -1
drivers/media/dvb/dvb-usb/Kconfig
··· 109 109 Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. 110 110 111 111 config DVB_USB_DTT200U 112 - tristate "WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support" 112 + tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)" 113 113 depends on DVB_USB 114 114 help 115 115 Say Y here to support the WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver. 116 116 117 117 The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan). 118 + 119 + The WT-220U and its clones are pen-sized.
+37 -35
drivers/media/dvb/dvb-usb/dtt200u-fe.c
··· 14 14 struct dtt200u_fe_state { 15 15 struct dvb_usb_device *d; 16 16 17 + fe_status_t stat; 18 + 17 19 struct dvb_frontend_parameters fep; 18 20 struct dvb_frontend frontend; 19 21 }; 20 22 21 - #define moan(which,what) info("unexpected value in '%s' for cmd '%02x' - please report to linux-dvb@linuxtv.org",which,what) 22 - 23 23 static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) 24 24 { 25 25 struct dtt200u_fe_state *state = fe->demodulator_priv; 26 - u8 bw = GET_TUNE_STAT; 27 - u8 br[3] = { 0 }; 28 - // u8 bdeb[5] = { 0 }; 26 + u8 st = GET_TUNE_STATUS, b[3]; 29 27 30 - dvb_usb_generic_rw(state->d,&bw,1,br,3,0); 31 - switch (br[0]) { 28 + dvb_usb_generic_rw(state->d,&st,1,b,3,0); 29 + 30 + switch (b[0]) { 32 31 case 0x01: 33 - *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 32 + *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | 33 + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 34 34 break; 35 - case 0x00: 36 - *stat = 0; 35 + case 0x00: /* pending */ 36 + *stat = FE_TIMEDOUT; /* during set_frontend */ 37 37 break; 38 38 default: 39 - moan("br[0]",GET_TUNE_STAT); 39 + case 0x02: /* failed */ 40 + *stat = 0; 40 41 break; 41 42 } 42 - 43 - // bw[0] = 0x88; 44 - // dvb_usb_generic_rw(state->d,bw,1,bdeb,5,0); 45 - 46 - // deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]); 47 - 48 43 return 0; 49 44 } 45 + 50 46 static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) 51 47 { 52 48 struct dtt200u_fe_state *state = fe->demodulator_priv; 53 - u8 bw = GET_BER; 54 - *ber = 0; 55 - dvb_usb_generic_rw(state->d,&bw,1,(u8*) ber,3,0); 49 + u8 bw = GET_VIT_ERR_CNT,b[3]; 50 + dvb_usb_generic_rw(state->d,&bw,1,b,3,0); 51 + *ber = (b[0] << 16) | (b[1] << 8) | b[2]; 56 52 return 0; 57 53 } 58 54 59 55 static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) 60 56 { 61 57 struct dtt200u_fe_state *state = fe->demodulator_priv; 62 - u8 bw = GET_UNK; 63 - *unc = 0; 64 - dvb_usb_generic_rw(state->d,&bw,1,(u8*) unc,3,0); 58 + u8 bw = GET_RS_UNCOR_BLK_CNT,b[2]; 59 + 60 + dvb_usb_generic_rw(state->d,&bw,1,b,2,0); 61 + *unc = (b[0] << 8) | b[1]; 65 62 return 0; 66 63 } 67 64 68 65 static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) 69 66 { 70 67 struct dtt200u_fe_state *state = fe->demodulator_priv; 71 - u8 bw = GET_SIG_STRENGTH, b; 68 + u8 bw = GET_AGC, b; 72 69 dvb_usb_generic_rw(state->d,&bw,1,&b,1,0); 73 70 *strength = (b << 8) | b; 74 71 return 0; ··· 83 86 static int dtt200u_fe_init(struct dvb_frontend* fe) 84 87 { 85 88 struct dtt200u_fe_state *state = fe->demodulator_priv; 86 - u8 b = RESET_DEMOD; 89 + u8 b = SET_INIT; 87 90 return dvb_usb_generic_write(state->d,&b,1); 88 91 } 89 92 ··· 95 98 static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) 96 99 { 97 100 tune->min_delay_ms = 1500; 98 - tune->step_size = 166667; 99 - tune->max_drift = 166667 * 2; 101 + tune->step_size = 0; 102 + tune->max_drift = 0; 100 103 return 0; 101 104 } 102 105 ··· 104 107 struct dvb_frontend_parameters *fep) 105 108 { 106 109 struct dtt200u_fe_state *state = fe->demodulator_priv; 110 + int i; 111 + fe_status_t st; 107 112 u16 freq = fep->frequency / 250000; 108 - u8 bw,bwbuf[2] = { SET_BANDWIDTH, 0 }, freqbuf[3] = { SET_FREQUENCY, 0, 0 }; 113 + u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 }; 109 114 110 115 switch (fep->u.ofdm.bandwidth) { 111 - case BANDWIDTH_8_MHZ: bw = 8; break; 112 - case BANDWIDTH_7_MHZ: bw = 7; break; 113 - case BANDWIDTH_6_MHZ: bw = 6; break; 116 + case BANDWIDTH_8_MHZ: bwbuf[1] = 8; break; 117 + case BANDWIDTH_7_MHZ: bwbuf[1] = 7; break; 118 + case BANDWIDTH_6_MHZ: bwbuf[1] = 6; break; 114 119 case BANDWIDTH_AUTO: return -EOPNOTSUPP; 115 120 default: 116 121 return -EINVAL; 117 122 } 118 - deb_info("set_frontend\n"); 119 123 120 - bwbuf[1] = bw; 121 124 dvb_usb_generic_write(state->d,bwbuf,2); 122 125 123 126 freqbuf[1] = freq & 0xff; 124 127 freqbuf[2] = (freq >> 8) & 0xff; 125 128 dvb_usb_generic_write(state->d,freqbuf,3); 126 129 127 - memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters)); 130 + for (i = 0; i < 30; i++) { 131 + msleep(20); 132 + dtt200u_fe_read_status(fe, &st); 133 + if (st & FE_TIMEDOUT) 134 + continue; 135 + } 128 136 129 137 return 0; 130 138 } ··· 176 174 177 175 static struct dvb_frontend_ops dtt200u_fe_ops = { 178 176 .info = { 179 - .name = "DTT200U (Yakumo/Typhoon/Hama) DVB-T", 177 + .name = "WideView USB DVB-T", 180 178 .type = FE_OFDM, 181 179 .frequency_min = 44250000, 182 180 .frequency_max = 867250000,
+74 -12
drivers/media/dvb/dvb-usb/dtt200u.c
··· 3 3 * 4 4 * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) 5 5 * 6 + * Thanks to Steve Chang from WideView for providing support for the WT-220U. 7 + * 6 8 * This program is free software; you can redistribute it and/or modify it 7 9 * under the terms of the GNU General Public License as published by the Free 8 10 * Software Foundation, version 2. ··· 18 16 module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); 19 17 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); 20 18 19 + static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff) 20 + { 21 + u8 b = SET_INIT; 22 + 23 + if (onoff) 24 + dvb_usb_generic_write(d,&b,2); 25 + 26 + return 0; 27 + } 28 + 21 29 static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff) 22 30 { 23 - u8 b_streaming[2] = { SET_TS_CTRL, onoff }; 31 + u8 b_streaming[2] = { SET_STREAMING, onoff }; 24 32 u8 b_rst_pid = RESET_PID_FILTER; 25 33 26 34 dvb_usb_generic_write(d,b_streaming,2); 27 35 28 - if (!onoff) 36 + if (onoff == 0) 29 37 dvb_usb_generic_write(d,&b_rst_pid,1); 30 38 return 0; 31 39 } ··· 48 36 b_pid[0] = SET_PID_FILTER; 49 37 b_pid[1] = index; 50 38 b_pid[2] = pid & 0xff; 51 - b_pid[3] = (pid >> 8) & 0xff; 39 + b_pid[3] = (pid >> 8) & 0x1f; 52 40 53 41 return dvb_usb_generic_write(d,b_pid,4); 54 42 } ··· 66 54 { 0x80, 0x08, KEY_5 }, 67 55 { 0x80, 0x09, KEY_6 }, 68 56 { 0x80, 0x0a, KEY_7 }, 69 - { 0x00, 0x0c, KEY_ZOOM }, 57 + { 0x80, 0x0c, KEY_ZOOM }, 70 58 { 0x80, 0x0d, KEY_0 }, 71 - { 0x00, 0x0e, KEY_SELECT }, 59 + { 0x80, 0x0e, KEY_SELECT }, 72 60 { 0x80, 0x12, KEY_POWER }, 73 61 { 0x80, 0x1a, KEY_CHANNELUP }, 74 62 { 0x80, 0x1b, KEY_8 }, ··· 78 66 79 67 static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) 80 68 { 81 - u8 key[5],cmd = GET_RC_KEY; 69 + u8 key[5],cmd = GET_RC_CODE; 82 70 dvb_usb_generic_rw(d,&cmd,1,key,5,0); 83 71 dvb_usb_nec_rc_key_to_event(d,key,event,state); 84 72 if (key[0] != 0) ··· 93 81 } 94 82 95 83 static struct dvb_usb_properties dtt200u_properties; 84 + static struct dvb_usb_properties wt220u_properties; 96 85 97 86 static int dtt200u_usb_probe(struct usb_interface *intf, 98 87 const struct usb_device_id *id) 99 88 { 100 - return dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE); 89 + if (dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE) == 0 || 90 + dvb_usb_device_init(intf,&wt220u_properties,THIS_MODULE) == 0) 91 + return 0; 92 + 93 + return -ENODEV; 101 94 } 102 95 103 96 static struct usb_device_id dtt200u_usb_table [] = { 97 + // { USB_DEVICE(0x04b4,0x8613) }, 104 98 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_COLD) }, 105 99 { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_DTT200U_WARM) }, 100 + { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_COLD) }, 101 + { USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_WT220U_WARM) }, 106 102 { 0 }, 107 103 }; 108 104 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); 109 105 110 106 static struct dvb_usb_properties dtt200u_properties = { 111 107 .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING, 112 - .pid_filter_count = 255, /* It is a guess, but there are at least 10 */ 108 + .pid_filter_count = 15, 113 109 114 110 .usb_ctrl = CYPRESS_FX2, 115 111 .firmware = "dvb-usb-dtt200u-01.fw", 116 112 113 + .power_ctrl = dtt200u_power_ctrl, 117 114 .streaming_ctrl = dtt200u_streaming_ctrl, 118 115 .pid_filter = dtt200u_pid_filter, 119 116 .frontend_attach = dtt200u_frontend_attach, 120 117 121 - .rc_interval = 200, 118 + .rc_interval = 300, 122 119 .rc_key_map = dtt200u_rc_keys, 123 120 .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys), 124 121 .rc_query = dtt200u_rc_query, ··· 148 127 149 128 .num_device_descs = 1, 150 129 .devices = { 151 - { .name = "WideView/Yakumo/Hama/Typhoon DVB-T USB2.0)", 130 + { .name = "WideView/Yuan/Yakumo/Hama/Typhoon DVB-T USB2.0 (WT-200U)", 152 131 .cold_ids = { &dtt200u_usb_table[0], NULL }, 153 132 .warm_ids = { &dtt200u_usb_table[1], NULL }, 133 + }, 134 + { 0 }, 135 + } 136 + }; 137 + 138 + static struct dvb_usb_properties wt220u_properties = { 139 + .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING, 140 + .pid_filter_count = 15, 141 + 142 + .usb_ctrl = CYPRESS_FX2, 143 + .firmware = "dvb-usb-wt220u-01.fw", 144 + 145 + .power_ctrl = dtt200u_power_ctrl, 146 + .streaming_ctrl = dtt200u_streaming_ctrl, 147 + .pid_filter = dtt200u_pid_filter, 148 + .frontend_attach = dtt200u_frontend_attach, 149 + 150 + .rc_interval = 300, 151 + .rc_key_map = dtt200u_rc_keys, 152 + .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys), 153 + .rc_query = dtt200u_rc_query, 154 + 155 + .generic_bulk_ctrl_endpoint = 0x01, 156 + 157 + /* parameter for the MPEG2-data transfer */ 158 + .urb = { 159 + .type = DVB_USB_BULK, 160 + .count = 7, 161 + .endpoint = 0x02, 162 + .u = { 163 + .bulk = { 164 + .buffersize = 4096, 165 + } 166 + } 167 + }, 168 + 169 + .num_device_descs = 1, 170 + .devices = { 171 + { .name = "WideView WT-220U PenType Receiver (and clones)", 172 + .cold_ids = { &dtt200u_usb_table[2], NULL }, 173 + .warm_ids = { &dtt200u_usb_table[3], NULL }, 154 174 }, 155 175 { 0 }, 156 176 } ··· 200 138 /* usb specific object needed to register this driver with the usb subsystem */ 201 139 static struct usb_driver dtt200u_usb_driver = { 202 140 .owner = THIS_MODULE, 203 - .name = "dtt200u", 141 + .name = "dvb_usb_dtt200u", 204 142 .probe = dtt200u_usb_probe, 205 143 .disconnect = dvb_usb_device_exit, 206 144 .id_table = dtt200u_usb_table, ··· 228 166 module_exit(dtt200u_usb_module_exit); 229 167 230 168 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); 231 - MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon DVB-T USB2.0 device"); 169 + MODULE_DESCRIPTION("Driver for the WideView/Yakumo/Hama/Typhoon DVB-T USB2.0 devices"); 232 170 MODULE_VERSION("1.0"); 233 171 MODULE_LICENSE("GPL");
+14 -24
drivers/media/dvb/dvb-usb/dtt200u.h
··· 22 22 /* guessed protocol description (reverse engineered): 23 23 * read 24 24 * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1 25 - * 81 - <TS_LOCK> <current frequency divided by 250000> 26 - * 82 - crash - do not touch 27 - * 83 - crash - do not touch 28 - * 84 - remote control 29 - * 85 - crash - do not touch (OK, stop testing here) 30 25 * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal) 31 - * 89 - noise-to-signal 32 - * 8a - unkown 1 byte - signal_strength 33 - * 8c - ber ??? 34 - * 8d - ber 35 - * 8e - unc 36 26 */ 37 27 38 - #define GET_SPEED 0x00 39 - #define GET_TUNE_STAT 0x81 40 - #define GET_RC_KEY 0x84 41 - #define GET_STATUS 0x88 42 - #define GET_SNR 0x89 43 - #define GET_SIG_STRENGTH 0x8a 44 - #define GET_UNK 0x8c 45 - #define GET_BER 0x8d 46 - #define GET_UNC 0x8e 28 + #define GET_SPEED 0x00 29 + #define GET_TUNE_STATUS 0x81 30 + #define GET_RC_CODE 0x84 31 + #define GET_CONFIGURATION 0x88 32 + #define GET_AGC 0x89 33 + #define GET_SNR 0x8a 34 + #define GET_VIT_ERR_CNT 0x8c 35 + #define GET_RS_ERR_CNT 0x8d 36 + #define GET_RS_UNCOR_BLK_CNT 0x8e 47 37 48 38 /* write 49 - * 01 - reset the demod 39 + * 01 - init 50 40 * 02 - frequency (divided by 250000) 51 41 * 03 - bandwidth 52 42 * 04 - pid table (index pid(7:0) pid(12:8)) 53 43 * 05 - reset the pid table 54 - * 08 - demod transfer enabled or not (FX2 transfer is enabled by default) 44 + * 08 - transfer switch 55 45 */ 56 46 57 - #define RESET_DEMOD 0x01 58 - #define SET_FREQUENCY 0x02 47 + #define SET_INIT 0x01 48 + #define SET_RF_FREQ 0x02 59 49 #define SET_BANDWIDTH 0x03 60 50 #define SET_PID_FILTER 0x04 61 51 #define RESET_PID_FILTER 0x05 62 - #define SET_TS_CTRL 0x08 52 + #define SET_STREAMING 0x08 63 53 64 54 extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d); 65 55
+2 -1
drivers/media/dvb/dvb-usb/dvb-usb-ids.h
··· 72 72 #define USB_PID_HANFTEK_UMT_010_WARM 0x0015 73 73 #define USB_PID_DTT200U_COLD 0x0201 74 74 #define USB_PID_DTT200U_WARM 0x0301 75 + #define USB_PID_WT220U_COLD 0x0222 76 + #define USB_PID_WT220U_WARM 0x0221 75 77 #define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 76 78 #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 77 79 #define USB_PID_NEBULA_DIGITV 0x0201 ··· 85 83 #define USB_PID_MEDION_MD95700 0x0932 86 84 #define USB_PID_KYE_DVB_T_COLD 0x701e 87 85 #define USB_PID_KYE_DVB_T_WARM 0x701f 88 - 89 86 90 87 #endif