diff options
Diffstat (limited to 'drivers/media/dvb/dvb-usb')
26 files changed, 4323 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig new file mode 100644 index 000000000000..8aa32f6e447b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -0,0 +1,99 @@ | |||
1 | config DVB_USB | ||
2 | tristate "Support for various USB DVB devices" | ||
3 | depends on DVB_CORE && USB | ||
4 | select FW_LOADER | ||
5 | help | ||
6 | By enabling this you will be able to choose the various USB 1.1 and | ||
7 | USB2.0 DVB devices. | ||
8 | |||
9 | Almost every USB device needs a firmware, please look into | ||
10 | <file:Documentation/dvb/README.dvb-usb> | ||
11 | |||
12 | Say Y if you own an USB DVB device. | ||
13 | |||
14 | config DVB_USB_DEBUG | ||
15 | bool "Enable extended debug support for all DVB-USB devices" | ||
16 | depends on DVB_USB | ||
17 | help | ||
18 | Say Y if you want to enable debuging. See modinfo dvb-usb (and the | ||
19 | appropriate drivers) for debug levels. | ||
20 | |||
21 | config DVB_USB_A800 | ||
22 | tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" | ||
23 | depends on DVB_USB | ||
24 | help | ||
25 | Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. | ||
26 | |||
27 | config DVB_USB_DIBUSB_MB | ||
28 | tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" | ||
29 | depends on DVB_USB | ||
30 | help | ||
31 | Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by | ||
32 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. | ||
33 | |||
34 | Devices supported by this driver: | ||
35 | TwinhanDTV USB-Ter (VP7041) | ||
36 | TwinhanDTV Magic Box (VP7041e) | ||
37 | KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0 | ||
38 | Hama DVB-T USB1.1-Box | ||
39 | DiBcom USB1.1 reference devices (non-public) | ||
40 | Ultima Electronic/Artec T1 USB TVBOX | ||
41 | Compro Videomate DVB-U2000 - DVB-T USB | ||
42 | Grandtec DVB-T USB | ||
43 | Avermedia AverTV DVBT USB1.1 | ||
44 | Artec T1 USB1.1 boxes | ||
45 | |||
46 | The VP7041 seems to be identical to "CTS Portable" (Chinese | ||
47 | Television System). | ||
48 | |||
49 | Say Y if you own such a device and want to use it. You should build it as | ||
50 | a module. | ||
51 | |||
52 | config DVB_USB_DIBUSB_MC | ||
53 | tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" | ||
54 | depends on DVB_USB | ||
55 | help | ||
56 | Support for 2.0 DVB-T receivers based on reference designs made by | ||
57 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. | ||
58 | |||
59 | Devices supported by this driver: | ||
60 | DiBcom USB2.0 reference devices (non-public) | ||
61 | Artec T1 USB2.0 boxes | ||
62 | |||
63 | Say Y if you own such a device and want to use it. You should build it as | ||
64 | a module. | ||
65 | |||
66 | config DVB_USB_UMT_010 | ||
67 | tristate "HanfTek UMT-010 DVB-T USB2.0 support" | ||
68 | depends on DVB_USB | ||
69 | help | ||
70 | Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. | ||
71 | |||
72 | config DVB_USB_DIGITV | ||
73 | tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" | ||
74 | depends on DVB_USB | ||
75 | help | ||
76 | Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver. | ||
77 | |||
78 | config DVB_USB_VP7045 | ||
79 | tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support" | ||
80 | depends on DVB_USB | ||
81 | help | ||
82 | Say Y here to support the | ||
83 | TwinhanDTV Alpha (stick) (VP-7045), | ||
84 | TwinhanDTV MagicBox II (VP-7046) and | ||
85 | DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers. | ||
86 | |||
87 | config DVB_USB_NOVA_T_USB2 | ||
88 | tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" | ||
89 | depends on DVB_USB | ||
90 | help | ||
91 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. | ||
92 | |||
93 | config DVB_USB_DTT200U | ||
94 | tristate "Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support" | ||
95 | depends on DVB_USB | ||
96 | help | ||
97 | Say Y here to support the Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver. | ||
98 | |||
99 | The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan). | ||
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile new file mode 100644 index 000000000000..d65b50f9abb0 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -0,0 +1,30 @@ | |||
1 | dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o | ||
2 | obj-$(CONFIG_DVB_USB) += dvb-usb.o | ||
3 | |||
4 | dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o | ||
5 | obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o | ||
6 | |||
7 | dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o | ||
8 | obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o | ||
9 | |||
10 | dvb-usb-dibusb-common-objs = dibusb-common.o | ||
11 | |||
12 | dvb-usb-a800-objs = a800.o | ||
13 | obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o | ||
14 | |||
15 | dvb-usb-dibusb-mb-objs = dibusb-mb.o | ||
16 | obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o | ||
17 | |||
18 | dvb-usb-dibusb-mc-objs = dibusb-mc.o | ||
19 | obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o | ||
20 | |||
21 | dvb-usb-nova-t-usb2-objs = nova-t-usb2.o | ||
22 | obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o | ||
23 | |||
24 | dvb-usb-umt-010-objs = umt-010.o | ||
25 | obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o | ||
26 | |||
27 | dvb-usb-digitv-objs = digitv.o | ||
28 | obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o | ||
29 | |||
30 | EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ | ||
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c new file mode 100644 index 000000000000..a3542935604f --- /dev/null +++ b/drivers/media/dvb/dvb-usb/a800.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T | ||
2 | * USB2.0 (A800) DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * Thanks to | ||
7 | * - AVerMedia who kindly provided information and | ||
8 | * - Glen Harris who suffered from my mistakes during development. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the Free | ||
12 | * Software Foundation, version 2. | ||
13 | * | ||
14 | * see Documentation/dvb/README.dvb-usb for more information | ||
15 | */ | ||
16 | #include "dibusb.h" | ||
17 | |||
18 | static int debug; | ||
19 | module_param(debug, int, 0644); | ||
20 | MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS); | ||
21 | #define deb_rc(args...) dprintk(debug,0x01,args) | ||
22 | |||
23 | static int a800_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
24 | { | ||
25 | /* do nothing for the AVerMedia */ | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | static struct dvb_usb_rc_key a800_rc_keys[] = { | ||
30 | { 0x02, 0x01, KEY_PROG1 }, /* SOURCE */ | ||
31 | { 0x02, 0x00, KEY_POWER }, /* POWER */ | ||
32 | { 0x02, 0x05, KEY_1 }, /* 1 */ | ||
33 | { 0x02, 0x06, KEY_2 }, /* 2 */ | ||
34 | { 0x02, 0x07, KEY_3 }, /* 3 */ | ||
35 | { 0x02, 0x09, KEY_4 }, /* 4 */ | ||
36 | { 0x02, 0x0a, KEY_5 }, /* 5 */ | ||
37 | { 0x02, 0x0b, KEY_6 }, /* 6 */ | ||
38 | { 0x02, 0x0d, KEY_7 }, /* 7 */ | ||
39 | { 0x02, 0x0e, KEY_8 }, /* 8 */ | ||
40 | { 0x02, 0x0f, KEY_9 }, /* 9 */ | ||
41 | { 0x02, 0x12, KEY_LEFT }, /* L / DISPLAY */ | ||
42 | { 0x02, 0x11, KEY_0 }, /* 0 */ | ||
43 | { 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */ | ||
44 | { 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */ | ||
45 | { 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */ | ||
46 | { 0x02, 0x03, KEY_CHANNELUP }, /* CH UP */ | ||
47 | { 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */ | ||
48 | { 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */ | ||
49 | { 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */ | ||
50 | { 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */ | ||
51 | { 0x02, 0x14, KEY_MUTE }, /* MUTE */ | ||
52 | { 0x02, 0x08, KEY_AUDIO }, /* AUDIO */ | ||
53 | { 0x02, 0x19, KEY_RECORD }, /* RECORD */ | ||
54 | { 0x02, 0x18, KEY_PLAY }, /* PLAY */ | ||
55 | { 0x02, 0x1b, KEY_STOP }, /* STOP */ | ||
56 | { 0x02, 0x1a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */ | ||
57 | { 0x02, 0x1d, KEY_BACK }, /* << / RED */ | ||
58 | { 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */ | ||
59 | { 0x02, 0x03, KEY_TEXT }, /* TELETEXT */ | ||
60 | { 0x02, 0x01, KEY_FIRST }, /* |<< / GREEN */ | ||
61 | { 0x02, 0x00, KEY_LAST }, /* >>| / BLUE */ | ||
62 | { 0x02, 0x04, KEY_EPG }, /* EPG */ | ||
63 | { 0x02, 0x15, KEY_MENU }, /* MENU */ | ||
64 | }; | ||
65 | |||
66 | int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
67 | { | ||
68 | u8 key[5]; | ||
69 | if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0), | ||
70 | 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5, | ||
71 | 2*HZ) != 5) | ||
72 | return -ENODEV; | ||
73 | |||
74 | /* call the universal NEC remote processor, to find out the key's state and event */ | ||
75 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
76 | if (key[0] != 0) | ||
77 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /* USB Driver stuff */ | ||
82 | static struct dvb_usb_properties a800_properties; | ||
83 | |||
84 | static int a800_probe(struct usb_interface *intf, | ||
85 | const struct usb_device_id *id) | ||
86 | { | ||
87 | return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE); | ||
88 | } | ||
89 | |||
90 | /* do not change the order of the ID table */ | ||
91 | static struct usb_device_id a800_table [] = { | ||
92 | /* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_COLD) }, | ||
93 | /* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_WARM) }, | ||
94 | { } /* Terminating entry */ | ||
95 | }; | ||
96 | MODULE_DEVICE_TABLE (usb, a800_table); | ||
97 | |||
98 | static struct dvb_usb_properties a800_properties = { | ||
99 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
100 | .pid_filter_count = 32, | ||
101 | |||
102 | .usb_ctrl = CYPRESS_FX2, | ||
103 | |||
104 | .firmware = "dvb-usb-avertv-a800-02.fw", | ||
105 | |||
106 | .size_of_priv = sizeof(struct dibusb_state), | ||
107 | |||
108 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
109 | .pid_filter = dibusb_pid_filter, | ||
110 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
111 | .power_ctrl = a800_power_ctrl, | ||
112 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
113 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
114 | |||
115 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
116 | .rc_key_map = a800_rc_keys, | ||
117 | .rc_key_map_size = ARRAY_SIZE(a800_rc_keys), | ||
118 | .rc_query = a800_rc_query, | ||
119 | |||
120 | .i2c_algo = &dibusb_i2c_algo, | ||
121 | |||
122 | .generic_bulk_ctrl_endpoint = 0x01, | ||
123 | /* parameter for the MPEG2-data transfer */ | ||
124 | .urb = { | ||
125 | .type = DVB_USB_BULK, | ||
126 | .count = 7, | ||
127 | .endpoint = 0x06, | ||
128 | .u = { | ||
129 | .bulk = { | ||
130 | .buffersize = 4096, | ||
131 | } | ||
132 | } | ||
133 | }, | ||
134 | |||
135 | .num_device_descs = 1, | ||
136 | .devices = { | ||
137 | { "AVerMedia AverTV DVB-T USB 2.0 (A800)", | ||
138 | { &a800_table[0], NULL }, | ||
139 | { &a800_table[1], NULL }, | ||
140 | }, | ||
141 | } | ||
142 | }; | ||
143 | |||
144 | static struct usb_driver a800_driver = { | ||
145 | .owner = THIS_MODULE, | ||
146 | .name = "AVerMedia AverTV DVB-T USB 2.0 (A800)", | ||
147 | .probe = a800_probe, | ||
148 | .disconnect = dvb_usb_device_exit, | ||
149 | .id_table = a800_table, | ||
150 | }; | ||
151 | |||
152 | /* module stuff */ | ||
153 | static int __init a800_module_init(void) | ||
154 | { | ||
155 | int result; | ||
156 | if ((result = usb_register(&a800_driver))) { | ||
157 | err("usb_register failed. Error number %d",result); | ||
158 | return result; | ||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void __exit a800_module_exit(void) | ||
165 | { | ||
166 | /* deregister this driver from the USB subsystem */ | ||
167 | usb_deregister(&a800_driver); | ||
168 | } | ||
169 | |||
170 | module_init (a800_module_init); | ||
171 | module_exit (a800_module_exit); | ||
172 | |||
173 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
174 | MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)"); | ||
175 | MODULE_VERSION("1.0"); | ||
176 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c new file mode 100644 index 000000000000..63b626f70c81 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-common.c | |||
@@ -0,0 +1,272 @@ | |||
1 | /* Common methods for dibusb-based-receivers. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the Free | ||
7 | * Software Foundation, version 2. | ||
8 | * | ||
9 | * see Documentation/dvb/README.dvb-usb for more information | ||
10 | */ | ||
11 | #include "dibusb.h" | ||
12 | |||
13 | static int debug; | ||
14 | module_param(debug, int, 0644); | ||
15 | MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS); | ||
16 | MODULE_LICENSE("GPL"); | ||
17 | |||
18 | #define deb_info(args...) dprintk(debug,0x01,args) | ||
19 | |||
20 | /* common stuff used by the different dibusb modules */ | ||
21 | int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff) | ||
22 | { | ||
23 | if (d->priv != NULL) { | ||
24 | struct dib_fe_xfer_ops *ops = d->priv; | ||
25 | if (ops->fifo_ctrl != NULL) | ||
26 | if (ops->fifo_ctrl(d->fe,onoff)) { | ||
27 | err("error while controlling the fifo of the demod."); | ||
28 | return -ENODEV; | ||
29 | } | ||
30 | } | ||
31 | return 0; | ||
32 | } | ||
33 | EXPORT_SYMBOL(dibusb_streaming_ctrl); | ||
34 | |||
35 | int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) | ||
36 | { | ||
37 | if (d->priv != NULL) { | ||
38 | struct dib_fe_xfer_ops *ops = d->priv; | ||
39 | if (d->pid_filtering && ops->pid_ctrl != NULL) | ||
40 | ops->pid_ctrl(d->fe,index,pid,onoff); | ||
41 | } | ||
42 | return 0; | ||
43 | } | ||
44 | EXPORT_SYMBOL(dibusb_pid_filter); | ||
45 | |||
46 | int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff) | ||
47 | { | ||
48 | if (d->priv != NULL) { | ||
49 | struct dib_fe_xfer_ops *ops = d->priv; | ||
50 | if (ops->pid_parse != NULL) | ||
51 | if (ops->pid_parse(d->fe,onoff) < 0) | ||
52 | err("could not handle pid_parser"); | ||
53 | } | ||
54 | return 0; | ||
55 | } | ||
56 | EXPORT_SYMBOL(dibusb_pid_filter_ctrl); | ||
57 | |||
58 | int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
59 | { | ||
60 | u8 b[3]; | ||
61 | int ret; | ||
62 | b[0] = DIBUSB_REQ_SET_IOCTL; | ||
63 | b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; | ||
64 | b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP; | ||
65 | ret = dvb_usb_generic_write(d,b,3); | ||
66 | msleep(10); | ||
67 | return ret; | ||
68 | } | ||
69 | EXPORT_SYMBOL(dibusb_power_ctrl); | ||
70 | |||
71 | int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff) | ||
72 | { | ||
73 | u8 b[2]; | ||
74 | b[0] = DIBUSB_REQ_SET_IOCTL; | ||
75 | b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; | ||
76 | |||
77 | dvb_usb_generic_write(d,b,3); | ||
78 | |||
79 | return dibusb_streaming_ctrl(d,onoff); | ||
80 | } | ||
81 | EXPORT_SYMBOL(dibusb2_0_streaming_ctrl); | ||
82 | |||
83 | int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
84 | { | ||
85 | if (onoff) { | ||
86 | u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP }; | ||
87 | return dvb_usb_generic_write(d,b,3); | ||
88 | } else | ||
89 | return 0; | ||
90 | } | ||
91 | EXPORT_SYMBOL(dibusb2_0_power_ctrl); | ||
92 | |||
93 | static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr, | ||
94 | u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) | ||
95 | { | ||
96 | u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ | ||
97 | /* write only ? */ | ||
98 | int wo = (rbuf == NULL || rlen == 0), | ||
99 | len = 2 + wlen + (wo ? 0 : 2); | ||
100 | |||
101 | sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ; | ||
102 | sndbuf[1] = (addr << 1) | (wo ? 0 : 1); | ||
103 | |||
104 | memcpy(&sndbuf[2],wbuf,wlen); | ||
105 | |||
106 | if (!wo) { | ||
107 | sndbuf[wlen+2] = (rlen >> 8) & 0xff; | ||
108 | sndbuf[wlen+3] = rlen & 0xff; | ||
109 | } | ||
110 | |||
111 | return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0); | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * I2C master xfer function | ||
116 | */ | ||
117 | static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
118 | { | ||
119 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
120 | int i; | ||
121 | |||
122 | if (down_interruptible(&d->i2c_sem) < 0) | ||
123 | return -EAGAIN; | ||
124 | |||
125 | if (num > 2) | ||
126 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
127 | |||
128 | for (i = 0; i < num; i++) { | ||
129 | /* write/read request */ | ||
130 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
131 | if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len, | ||
132 | msg[i+1].buf,msg[i+1].len) < 0) | ||
133 | break; | ||
134 | i++; | ||
135 | } else | ||
136 | if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0) | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | up(&d->i2c_sem); | ||
141 | return i; | ||
142 | } | ||
143 | |||
144 | static u32 dibusb_i2c_func(struct i2c_adapter *adapter) | ||
145 | { | ||
146 | return I2C_FUNC_I2C; | ||
147 | } | ||
148 | |||
149 | struct i2c_algorithm dibusb_i2c_algo = { | ||
150 | .name = "DiBcom USB I2C algorithm", | ||
151 | .id = I2C_ALGO_BIT, | ||
152 | .master_xfer = dibusb_i2c_xfer, | ||
153 | .functionality = dibusb_i2c_func, | ||
154 | }; | ||
155 | EXPORT_SYMBOL(dibusb_i2c_algo); | ||
156 | |||
157 | int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) | ||
158 | { | ||
159 | u8 wbuf[1] = { offs }; | ||
160 | return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1); | ||
161 | } | ||
162 | EXPORT_SYMBOL(dibusb_read_eeprom_byte); | ||
163 | |||
164 | int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d) | ||
165 | { | ||
166 | struct dib3000_config demod_cfg; | ||
167 | struct dibusb_state *st = d->priv; | ||
168 | |||
169 | demod_cfg.pll_set = dvb_usb_pll_set_i2c; | ||
170 | demod_cfg.pll_init = dvb_usb_pll_init_i2c; | ||
171 | |||
172 | for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++) | ||
173 | if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) { | ||
174 | d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | return -ENODEV; | ||
179 | } | ||
180 | EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach); | ||
181 | |||
182 | int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d) | ||
183 | { | ||
184 | d->pll_addr = 0x60; | ||
185 | d->pll_desc = &dvb_pll_env57h1xd5; | ||
186 | return 0; | ||
187 | } | ||
188 | EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); | ||
189 | |||
190 | /* | ||
191 | * common remote control stuff | ||
192 | */ | ||
193 | struct dvb_usb_rc_key dibusb_rc_keys[] = { | ||
194 | /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */ | ||
195 | { 0x00, 0x16, KEY_POWER }, | ||
196 | { 0x00, 0x10, KEY_MUTE }, | ||
197 | { 0x00, 0x03, KEY_1 }, | ||
198 | { 0x00, 0x01, KEY_2 }, | ||
199 | { 0x00, 0x06, KEY_3 }, | ||
200 | { 0x00, 0x09, KEY_4 }, | ||
201 | { 0x00, 0x1d, KEY_5 }, | ||
202 | { 0x00, 0x1f, KEY_6 }, | ||
203 | { 0x00, 0x0d, KEY_7 }, | ||
204 | { 0x00, 0x19, KEY_8 }, | ||
205 | { 0x00, 0x1b, KEY_9 }, | ||
206 | { 0x00, 0x15, KEY_0 }, | ||
207 | { 0x00, 0x05, KEY_CHANNELUP }, | ||
208 | { 0x00, 0x02, KEY_CHANNELDOWN }, | ||
209 | { 0x00, 0x1e, KEY_VOLUMEUP }, | ||
210 | { 0x00, 0x0a, KEY_VOLUMEDOWN }, | ||
211 | { 0x00, 0x11, KEY_RECORD }, | ||
212 | { 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */ | ||
213 | { 0x00, 0x14, KEY_PLAY }, | ||
214 | { 0x00, 0x1a, KEY_STOP }, | ||
215 | { 0x00, 0x40, KEY_REWIND }, | ||
216 | { 0x00, 0x12, KEY_FASTFORWARD }, | ||
217 | { 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */ | ||
218 | { 0x00, 0x4c, KEY_PAUSE }, | ||
219 | { 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */ | ||
220 | { 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */ | ||
221 | /* additional keys TwinHan VisionPlus, the Artec seemingly not have */ | ||
222 | { 0x00, 0x0c, KEY_CANCEL }, /* Cancel */ | ||
223 | { 0x00, 0x1c, KEY_EPG }, /* EPG */ | ||
224 | { 0x00, 0x00, KEY_TAB }, /* Tab */ | ||
225 | { 0x00, 0x48, KEY_INFO }, /* Preview */ | ||
226 | { 0x00, 0x04, KEY_LIST }, /* RecordList */ | ||
227 | { 0x00, 0x0f, KEY_TEXT }, /* Teletext */ | ||
228 | /* Key codes for the KWorld/ADSTech/JetWay remote. */ | ||
229 | { 0x86, 0x12, KEY_POWER }, | ||
230 | { 0x86, 0x0f, KEY_SELECT }, /* source */ | ||
231 | { 0x86, 0x0c, KEY_UNKNOWN }, /* scan */ | ||
232 | { 0x86, 0x0b, KEY_EPG }, | ||
233 | { 0x86, 0x10, KEY_MUTE }, | ||
234 | { 0x86, 0x01, KEY_1 }, | ||
235 | { 0x86, 0x02, KEY_2 }, | ||
236 | { 0x86, 0x03, KEY_3 }, | ||
237 | { 0x86, 0x04, KEY_4 }, | ||
238 | { 0x86, 0x05, KEY_5 }, | ||
239 | { 0x86, 0x06, KEY_6 }, | ||
240 | { 0x86, 0x07, KEY_7 }, | ||
241 | { 0x86, 0x08, KEY_8 }, | ||
242 | { 0x86, 0x09, KEY_9 }, | ||
243 | { 0x86, 0x0a, KEY_0 }, | ||
244 | { 0x86, 0x18, KEY_ZOOM }, | ||
245 | { 0x86, 0x1c, KEY_UNKNOWN }, /* preview */ | ||
246 | { 0x86, 0x13, KEY_UNKNOWN }, /* snap */ | ||
247 | { 0x86, 0x00, KEY_UNDO }, | ||
248 | { 0x86, 0x1d, KEY_RECORD }, | ||
249 | { 0x86, 0x0d, KEY_STOP }, | ||
250 | { 0x86, 0x0e, KEY_PAUSE }, | ||
251 | { 0x86, 0x16, KEY_PLAY }, | ||
252 | { 0x86, 0x11, KEY_BACK }, | ||
253 | { 0x86, 0x19, KEY_FORWARD }, | ||
254 | { 0x86, 0x14, KEY_UNKNOWN }, /* pip */ | ||
255 | { 0x86, 0x15, KEY_ESC }, | ||
256 | { 0x86, 0x1a, KEY_UP }, | ||
257 | { 0x86, 0x1e, KEY_DOWN }, | ||
258 | { 0x86, 0x1f, KEY_LEFT }, | ||
259 | { 0x86, 0x1b, KEY_RIGHT }, | ||
260 | }; | ||
261 | EXPORT_SYMBOL(dibusb_rc_keys); | ||
262 | |||
263 | int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
264 | { | ||
265 | u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE; | ||
266 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | ||
267 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
268 | if (key[0] != 0) | ||
269 | deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
270 | return 0; | ||
271 | } | ||
272 | EXPORT_SYMBOL(dibusb_rc_query); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c new file mode 100644 index 000000000000..fd103e4746e1 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* DVB USB compliant linux driver for mobile DVB-T USB devices based on | ||
2 | * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B) | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * based on GPL code from DiBcom, which has | ||
7 | * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation, version 2. | ||
12 | * | ||
13 | * see Documentation/dvb/README.dvb-usb for more information | ||
14 | */ | ||
15 | #include "dibusb.h" | ||
16 | |||
17 | static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d) | ||
18 | { | ||
19 | struct dib3000_config demod_cfg; | ||
20 | struct dibusb_state *st = d->priv; | ||
21 | |||
22 | demod_cfg.demod_address = 0x8; | ||
23 | demod_cfg.pll_set = dvb_usb_pll_set_i2c; | ||
24 | demod_cfg.pll_init = dvb_usb_pll_init_i2c; | ||
25 | |||
26 | if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) | ||
27 | return -ENODEV; | ||
28 | |||
29 | d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; | ||
30 | |||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | /* some of the dibusb 1.1 device aren't equipped with the default tuner | ||
35 | * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures | ||
36 | * this out. */ | ||
37 | static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d) | ||
38 | { | ||
39 | u8 b[2] = { 0,0 }, b2[1]; | ||
40 | int ret = 0; | ||
41 | struct i2c_msg msg[2] = { | ||
42 | { .flags = 0, .buf = b, .len = 2 }, | ||
43 | { .flags = I2C_M_RD, .buf = b2, .len = 1 }, | ||
44 | }; | ||
45 | |||
46 | /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */ | ||
47 | msg[0].addr = msg[1].addr = 0x60; | ||
48 | |||
49 | if (d->tuner_pass_ctrl) | ||
50 | d->tuner_pass_ctrl(d->fe,1,msg[0].addr); | ||
51 | |||
52 | if (i2c_transfer (&d->i2c_adap, msg, 2) != 2) { | ||
53 | err("tuner i2c write failed."); | ||
54 | ret = -EREMOTEIO; | ||
55 | } | ||
56 | |||
57 | if (d->tuner_pass_ctrl) | ||
58 | d->tuner_pass_ctrl(d->fe,0,msg[0].addr); | ||
59 | |||
60 | if (b2[0] == 0xfe) { | ||
61 | info("this device has the Thomson Cable onboard. Which is default."); | ||
62 | d->pll_addr = 0x61; | ||
63 | d->pll_desc = &dvb_pll_tua6010xs; | ||
64 | } else { | ||
65 | u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab }; | ||
66 | info("this device has the Panasonic ENV77H11D5 onboard."); | ||
67 | d->pll_addr = 0x60; | ||
68 | memcpy(d->pll_init,bpll,4); | ||
69 | d->pll_desc = &dvb_pll_tda665x; | ||
70 | } | ||
71 | |||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | /* USB Driver stuff */ | ||
76 | static struct dvb_usb_properties dibusb1_1_properties; | ||
77 | static struct dvb_usb_properties dibusb1_1_an2235_properties; | ||
78 | static struct dvb_usb_properties dibusb2_0b_properties; | ||
79 | |||
80 | static int dibusb_probe(struct usb_interface *intf, | ||
81 | const struct usb_device_id *id) | ||
82 | { | ||
83 | if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 || | ||
84 | dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) || | ||
85 | dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0) | ||
86 | return 0; | ||
87 | |||
88 | return -EINVAL; | ||
89 | } | ||
90 | |||
91 | /* do not change the order of the ID table */ | ||
92 | static struct usb_device_id dibusb_dib3000mb_table [] = { | ||
93 | /* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_COLD)}, | ||
94 | /* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_WARM)}, | ||
95 | /* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) }, | ||
96 | /* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) }, | ||
97 | /* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) }, | ||
98 | /* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) }, | ||
99 | /* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) }, | ||
100 | /* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) }, | ||
101 | /* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) }, | ||
102 | /* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) }, | ||
103 | /* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) }, | ||
104 | /* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) }, | ||
105 | /* 12 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) }, | ||
106 | /* 13 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) }, | ||
107 | /* 14 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) }, | ||
108 | /* 15 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_COLD) }, | ||
109 | /* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) }, | ||
110 | /* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) }, | ||
111 | /* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) }, | ||
112 | /* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) }, | ||
113 | /* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) }, | ||
114 | /* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) }, | ||
115 | /* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) }, | ||
116 | /* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) }, | ||
117 | /* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) }, | ||
118 | { } /* Terminating entry */ | ||
119 | }; | ||
120 | MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table); | ||
121 | |||
122 | static struct dvb_usb_properties dibusb1_1_properties = { | ||
123 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
124 | .pid_filter_count = 16, | ||
125 | |||
126 | .usb_ctrl = CYPRESS_AN2135, | ||
127 | |||
128 | .firmware = "dvb-usb-dibusb-5.0.0.11.fw", | ||
129 | |||
130 | .size_of_priv = sizeof(struct dibusb_state), | ||
131 | |||
132 | .streaming_ctrl = dibusb_streaming_ctrl, | ||
133 | .pid_filter = dibusb_pid_filter, | ||
134 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
135 | .power_ctrl = dibusb_power_ctrl, | ||
136 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
137 | .tuner_attach = dibusb_dib3000mb_tuner_attach, | ||
138 | |||
139 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
140 | .rc_key_map = dibusb_rc_keys, | ||
141 | .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
142 | .rc_query = dibusb_rc_query, | ||
143 | |||
144 | .i2c_algo = &dibusb_i2c_algo, | ||
145 | |||
146 | .generic_bulk_ctrl_endpoint = 0x01, | ||
147 | /* parameter for the MPEG2-data transfer */ | ||
148 | .urb = { | ||
149 | .type = DVB_USB_BULK, | ||
150 | .count = 7, | ||
151 | .endpoint = 0x02, | ||
152 | .u = { | ||
153 | .bulk = { | ||
154 | .buffersize = 4096, | ||
155 | } | ||
156 | } | ||
157 | }, | ||
158 | |||
159 | .num_device_descs = 8, | ||
160 | .devices = { | ||
161 | { "AVerMedia AverTV DVBT USB1.1", | ||
162 | { &dibusb_dib3000mb_table[0], NULL }, | ||
163 | { &dibusb_dib3000mb_table[1], NULL }, | ||
164 | }, | ||
165 | { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)", | ||
166 | { &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL}, | ||
167 | { &dibusb_dib3000mb_table[3], NULL }, | ||
168 | }, | ||
169 | { "DiBcom USB1.1 DVB-T reference design (MOD3000)", | ||
170 | { &dibusb_dib3000mb_table[5], NULL }, | ||
171 | { &dibusb_dib3000mb_table[6], NULL }, | ||
172 | }, | ||
173 | { "KWorld V-Stream XPERT DTV - DVB-T USB1.1", | ||
174 | { &dibusb_dib3000mb_table[7], NULL }, | ||
175 | { &dibusb_dib3000mb_table[8], NULL }, | ||
176 | }, | ||
177 | { "Grandtec USB1.1 DVB-T", | ||
178 | { &dibusb_dib3000mb_table[9], &dibusb_dib3000mb_table[11], NULL }, | ||
179 | { &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL }, | ||
180 | }, | ||
181 | { "Unkown USB1.1 DVB-T device ???? please report the name to the author", | ||
182 | { &dibusb_dib3000mb_table[13], NULL }, | ||
183 | { &dibusb_dib3000mb_table[14], NULL }, | ||
184 | }, | ||
185 | { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device", | ||
186 | { &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL}, | ||
187 | { &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL}, | ||
188 | }, | ||
189 | { "Artec T1 USB1.1 TVBOX with AN2135", | ||
190 | { &dibusb_dib3000mb_table[19], NULL }, | ||
191 | { &dibusb_dib3000mb_table[20], NULL }, | ||
192 | }, | ||
193 | } | ||
194 | }; | ||
195 | |||
196 | static struct dvb_usb_properties dibusb1_1_an2235_properties = { | ||
197 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
198 | .usb_ctrl = CYPRESS_AN2235, | ||
199 | |||
200 | .firmware = "dvb-usb-dibusb-an2235-01.fw", | ||
201 | |||
202 | .size_of_priv = sizeof(struct dibusb_state), | ||
203 | |||
204 | .streaming_ctrl = dibusb_streaming_ctrl, | ||
205 | .pid_filter = dibusb_pid_filter, | ||
206 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
207 | .power_ctrl = dibusb_power_ctrl, | ||
208 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
209 | .tuner_attach = dibusb_dib3000mb_tuner_attach, | ||
210 | |||
211 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
212 | .rc_key_map = dibusb_rc_keys, | ||
213 | .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
214 | .rc_query = dibusb_rc_query, | ||
215 | |||
216 | .i2c_algo = &dibusb_i2c_algo, | ||
217 | |||
218 | .generic_bulk_ctrl_endpoint = 0x01, | ||
219 | /* parameter for the MPEG2-data transfer */ | ||
220 | .urb = { | ||
221 | .type = DVB_USB_BULK, | ||
222 | .count = 7, | ||
223 | .endpoint = 0x02, | ||
224 | .u = { | ||
225 | .bulk = { | ||
226 | .buffersize = 4096, | ||
227 | } | ||
228 | } | ||
229 | }, | ||
230 | |||
231 | .num_device_descs = 1, | ||
232 | .devices = { | ||
233 | { "Artec T1 USB1.1 TVBOX with AN2235", | ||
234 | { &dibusb_dib3000mb_table[20], NULL }, | ||
235 | { &dibusb_dib3000mb_table[21], NULL }, | ||
236 | }, | ||
237 | } | ||
238 | }; | ||
239 | |||
240 | static struct dvb_usb_properties dibusb2_0b_properties = { | ||
241 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
242 | .usb_ctrl = CYPRESS_FX2, | ||
243 | |||
244 | .firmware = "dvb-usb-adstech-usb2-01.fw", | ||
245 | |||
246 | .size_of_priv = sizeof(struct dibusb_state), | ||
247 | |||
248 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
249 | .pid_filter = dibusb_pid_filter, | ||
250 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
251 | .power_ctrl = dibusb2_0_power_ctrl, | ||
252 | .frontend_attach = dibusb_dib3000mb_frontend_attach, | ||
253 | .tuner_attach = dibusb_dib3000mb_tuner_attach, | ||
254 | |||
255 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
256 | .rc_key_map = dibusb_rc_keys, | ||
257 | .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ | ||
258 | .rc_query = dibusb_rc_query, | ||
259 | |||
260 | .i2c_algo = &dibusb_i2c_algo, | ||
261 | |||
262 | .generic_bulk_ctrl_endpoint = 0x01, | ||
263 | /* parameter for the MPEG2-data transfer */ | ||
264 | .urb = { | ||
265 | .type = DVB_USB_BULK, | ||
266 | .count = 7, | ||
267 | .endpoint = 0x06, | ||
268 | .u = { | ||
269 | .bulk = { | ||
270 | .buffersize = 4096, | ||
271 | } | ||
272 | } | ||
273 | }, | ||
274 | |||
275 | .num_device_descs = 2, | ||
276 | .devices = { | ||
277 | { "KWorld/ADSTech Instant DVB-T USB 2.0", | ||
278 | { &dibusb_dib3000mb_table[23], NULL }, | ||
279 | { &dibusb_dib3000mb_table[24], NULL }, /* device ID with default DIBUSB2_0-firmware */ | ||
280 | }, | ||
281 | } | ||
282 | }; | ||
283 | |||
284 | static struct usb_driver dibusb_driver = { | ||
285 | .owner = THIS_MODULE, | ||
286 | .name = "DiBcom based USB DVB-T devices (DiB3000M-B based)", | ||
287 | .probe = dibusb_probe, | ||
288 | .disconnect = dvb_usb_device_exit, | ||
289 | .id_table = dibusb_dib3000mb_table, | ||
290 | }; | ||
291 | |||
292 | /* module stuff */ | ||
293 | static int __init dibusb_module_init(void) | ||
294 | { | ||
295 | int result; | ||
296 | if ((result = usb_register(&dibusb_driver))) { | ||
297 | err("usb_register failed. Error number %d",result); | ||
298 | return result; | ||
299 | } | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static void __exit dibusb_module_exit(void) | ||
305 | { | ||
306 | /* deregister this driver from the USB subsystem */ | ||
307 | usb_deregister(&dibusb_driver); | ||
308 | } | ||
309 | |||
310 | module_init (dibusb_module_init); | ||
311 | module_exit (dibusb_module_exit); | ||
312 | |||
313 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
314 | MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)"); | ||
315 | MODULE_VERSION("1.0"); | ||
316 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c new file mode 100644 index 000000000000..aad8ed3fe005 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* DVB USB compliant linux driver for mobile DVB-T USB devices based on | ||
2 | * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P) | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * based on GPL code from DiBcom, which has | ||
7 | * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation, version 2. | ||
12 | * | ||
13 | * see Documentation/dvb/README.dvb-usb for more information | ||
14 | */ | ||
15 | #include "dibusb.h" | ||
16 | |||
17 | /* USB Driver stuff */ | ||
18 | static struct dvb_usb_properties dibusb_mc_properties; | ||
19 | |||
20 | static int dibusb_mc_probe(struct usb_interface *intf, | ||
21 | const struct usb_device_id *id) | ||
22 | { | ||
23 | return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE); | ||
24 | } | ||
25 | |||
26 | /* do not change the order of the ID table */ | ||
27 | static struct usb_device_id dibusb_dib3000mc_table [] = { | ||
28 | /* 00 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) }, | ||
29 | /* 01 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) }, | ||
30 | /* 02 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, | ||
31 | { } /* Terminating entry */ | ||
32 | }; | ||
33 | MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table); | ||
34 | |||
35 | static struct dvb_usb_properties dibusb_mc_properties = { | ||
36 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
37 | .pid_filter_count = 32, | ||
38 | |||
39 | .usb_ctrl = CYPRESS_FX2, | ||
40 | .firmware = "dvb-usb-dibusb-6.0.0.8.fw", | ||
41 | |||
42 | .size_of_priv = sizeof(struct dibusb_state), | ||
43 | |||
44 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
45 | .pid_filter = dibusb_pid_filter, | ||
46 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
47 | .power_ctrl = dibusb2_0_power_ctrl, | ||
48 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
49 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
50 | |||
51 | .rc_interval = DEFAULT_RC_INTERVAL, | ||
52 | .rc_key_map = dibusb_rc_keys, | ||
53 | .rc_key_map_size = 63, /* FIXME */ | ||
54 | .rc_query = dibusb_rc_query, | ||
55 | |||
56 | .i2c_algo = &dibusb_i2c_algo, | ||
57 | |||
58 | .generic_bulk_ctrl_endpoint = 0x01, | ||
59 | /* parameter for the MPEG2-data transfer */ | ||
60 | .urb = { | ||
61 | .type = DVB_USB_BULK, | ||
62 | .count = 7, | ||
63 | .endpoint = 0x06, | ||
64 | .u = { | ||
65 | .bulk = { | ||
66 | .buffersize = 4096, | ||
67 | } | ||
68 | } | ||
69 | }, | ||
70 | |||
71 | .num_device_descs = 2, | ||
72 | .devices = { | ||
73 | { "DiBcom USB2.0 DVB-T reference design (MOD3000P)", | ||
74 | { &dibusb_dib3000mc_table[0], NULL }, | ||
75 | { &dibusb_dib3000mc_table[1], NULL }, | ||
76 | }, | ||
77 | { "Artec T1 USB2.0 TVBOX (please report the warm ID)", | ||
78 | { &dibusb_dib3000mc_table[2], NULL }, | ||
79 | { NULL }, | ||
80 | }, | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static struct usb_driver dibusb_mc_driver = { | ||
85 | .owner = THIS_MODULE, | ||
86 | .name = "DiBcom based USB2.0 DVB-T (DiB3000M-C/P based) devices", | ||
87 | .probe = dibusb_mc_probe, | ||
88 | .disconnect = dvb_usb_device_exit, | ||
89 | .id_table = dibusb_dib3000mc_table, | ||
90 | }; | ||
91 | |||
92 | /* module stuff */ | ||
93 | static int __init dibusb_mc_module_init(void) | ||
94 | { | ||
95 | int result; | ||
96 | if ((result = usb_register(&dibusb_mc_driver))) { | ||
97 | err("usb_register failed. Error number %d",result); | ||
98 | return result; | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static void __exit dibusb_mc_module_exit(void) | ||
105 | { | ||
106 | /* deregister this driver from the USB subsystem */ | ||
107 | usb_deregister(&dibusb_mc_driver); | ||
108 | } | ||
109 | |||
110 | module_init (dibusb_mc_module_init); | ||
111 | module_exit (dibusb_mc_module_exit); | ||
112 | |||
113 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
114 | MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices"); | ||
115 | MODULE_VERSION("1.0"); | ||
116 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h new file mode 100644 index 000000000000..6611f62977c0 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dibusb.h | |||
@@ -0,0 +1,122 @@ | |||
1 | /* Header file for all dibusb-based-receivers. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the Free | ||
7 | * Software Foundation, version 2. | ||
8 | * | ||
9 | * see Documentation/dvb/README.dvb-usb for more information | ||
10 | */ | ||
11 | #ifndef _DVB_USB_DIBUSB_H_ | ||
12 | #define _DVB_USB_DIBUSB_H_ | ||
13 | |||
14 | #define DVB_USB_LOG_PREFIX "dibusb" | ||
15 | #include "dvb-usb.h" | ||
16 | |||
17 | #include "dib3000.h" | ||
18 | |||
19 | /* | ||
20 | * protocol of all dibusb related devices | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * bulk msg to/from endpoint 0x01 | ||
25 | * | ||
26 | * general structure: | ||
27 | * request_byte parameter_bytes | ||
28 | */ | ||
29 | |||
30 | #define DIBUSB_REQ_START_READ 0x00 | ||
31 | #define DIBUSB_REQ_START_DEMOD 0x01 | ||
32 | |||
33 | /* | ||
34 | * i2c read | ||
35 | * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word | ||
36 | * bulk read: byte_buffer (length_word bytes) | ||
37 | */ | ||
38 | #define DIBUSB_REQ_I2C_READ 0x02 | ||
39 | |||
40 | /* | ||
41 | * i2c write | ||
42 | * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes | ||
43 | */ | ||
44 | #define DIBUSB_REQ_I2C_WRITE 0x03 | ||
45 | |||
46 | /* | ||
47 | * polling the value of the remote control | ||
48 | * bulk write: 0x04 | ||
49 | * bulk read: byte_buffer (5 bytes) | ||
50 | */ | ||
51 | #define DIBUSB_REQ_POLL_REMOTE 0x04 | ||
52 | |||
53 | /* additional status values for Hauppauge Remote Control Protocol */ | ||
54 | #define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01 | ||
55 | #define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03 | ||
56 | |||
57 | /* streaming mode: | ||
58 | * bulk write: 0x05 mode_byte | ||
59 | * | ||
60 | * mode_byte is mostly 0x00 | ||
61 | */ | ||
62 | #define DIBUSB_REQ_SET_STREAMING_MODE 0x05 | ||
63 | |||
64 | /* interrupt the internal read loop, when blocking */ | ||
65 | #define DIBUSB_REQ_INTR_READ 0x06 | ||
66 | |||
67 | /* io control | ||
68 | * 0x07 cmd_byte param_bytes | ||
69 | * | ||
70 | * param_bytes can be up to 32 bytes | ||
71 | * | ||
72 | * cmd_byte function parameter name | ||
73 | * 0x00 power mode | ||
74 | * 0x00 sleep | ||
75 | * 0x01 wakeup | ||
76 | * | ||
77 | * 0x01 enable streaming | ||
78 | * 0x02 disable streaming | ||
79 | * | ||
80 | * | ||
81 | */ | ||
82 | #define DIBUSB_REQ_SET_IOCTL 0x07 | ||
83 | |||
84 | /* IOCTL commands */ | ||
85 | |||
86 | /* change the power mode in firmware */ | ||
87 | #define DIBUSB_IOCTL_CMD_POWER_MODE 0x00 | ||
88 | #define DIBUSB_IOCTL_POWER_SLEEP 0x00 | ||
89 | #define DIBUSB_IOCTL_POWER_WAKEUP 0x01 | ||
90 | |||
91 | /* modify streaming of the FX2 */ | ||
92 | #define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01 | ||
93 | #define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02 | ||
94 | |||
95 | struct dibusb_state { | ||
96 | struct dib_fe_xfer_ops ops; | ||
97 | |||
98 | /* for RC5 remote control */ | ||
99 | int old_toggle; | ||
100 | int last_repeat_count; | ||
101 | }; | ||
102 | |||
103 | extern struct i2c_algorithm dibusb_i2c_algo; | ||
104 | |||
105 | extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *); | ||
106 | extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *); | ||
107 | |||
108 | extern int dibusb_streaming_ctrl(struct dvb_usb_device *, int); | ||
109 | extern int dibusb_pid_filter(struct dvb_usb_device *, int, u16, int); | ||
110 | extern int dibusb_pid_filter_ctrl(struct dvb_usb_device *, int); | ||
111 | extern int dibusb_power_ctrl(struct dvb_usb_device *, int); | ||
112 | extern int dibusb2_0_streaming_ctrl(struct dvb_usb_device *, int); | ||
113 | extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int); | ||
114 | |||
115 | #define DEFAULT_RC_INTERVAL 150 | ||
116 | //#define DEFAULT_RC_INTERVAL 100000 | ||
117 | |||
118 | extern struct dvb_usb_rc_key dibusb_rc_keys[]; | ||
119 | extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *); | ||
120 | extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *); | ||
121 | |||
122 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c new file mode 100644 index 000000000000..5acf3fde9522 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/digitv.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0 | ||
2 | * receiver | ||
3 | * | ||
4 | * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) and | ||
5 | * Allan Third (allan.third@cs.man.ac.uk) | ||
6 | * | ||
7 | * partly based on the SDK published by Nebula Electronics (TODO do we want this line ?) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation, version 2. | ||
12 | * | ||
13 | * see Documentation/dvb/README.dvb-usb for more information | ||
14 | */ | ||
15 | #include "digitv.h" | ||
16 | |||
17 | #include "mt352.h" | ||
18 | #include "nxt6000.h" | ||
19 | |||
20 | /* debug */ | ||
21 | int dvb_usb_digitv_debug; | ||
22 | module_param_named(debug,dvb_usb_digitv_debug, int, 0644); | ||
23 | MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS); | ||
24 | |||
25 | static int digitv_ctrl_msg(struct dvb_usb_device *d, | ||
26 | u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen) | ||
27 | { | ||
28 | int wo = (rbuf == NULL || rlen == 0); /* write-only */ | ||
29 | u8 sndbuf[7],rcvbuf[7]; | ||
30 | memset(sndbuf,0,7); memset(rcvbuf,0,7); | ||
31 | |||
32 | sndbuf[0] = cmd; | ||
33 | sndbuf[1] = vv; | ||
34 | sndbuf[2] = wo ? wlen : rlen; | ||
35 | |||
36 | if (!wo) { | ||
37 | memcpy(&sndbuf[3],wbuf,wlen); | ||
38 | dvb_usb_generic_write(d,sndbuf,7); | ||
39 | } else { | ||
40 | dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10); | ||
41 | memcpy(&rbuf,&rcvbuf[3],rlen); | ||
42 | } | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | /* I2C */ | ||
47 | static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num) | ||
48 | { | ||
49 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
50 | int i; | ||
51 | |||
52 | if (down_interruptible(&d->i2c_sem) < 0) | ||
53 | return -EAGAIN; | ||
54 | |||
55 | if (num > 2) | ||
56 | warn("more than 2 i2c messages at a time is not handled yet. TODO."); | ||
57 | |||
58 | for (i = 0; i < num; i++) { | ||
59 | /* write/read request */ | ||
60 | if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { | ||
61 | if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0, | ||
62 | msg[i+1].buf,msg[i+1].len) < 0) | ||
63 | break; | ||
64 | i++; | ||
65 | } else | ||
66 | if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0], | ||
67 | &msg[i].buf[1],msg[i].len-1,NULL,0) < 0) | ||
68 | break; | ||
69 | } | ||
70 | |||
71 | up(&d->i2c_sem); | ||
72 | return i; | ||
73 | } | ||
74 | |||
75 | static u32 digitv_i2c_func(struct i2c_adapter *adapter) | ||
76 | { | ||
77 | return I2C_FUNC_I2C; | ||
78 | } | ||
79 | |||
80 | static struct i2c_algorithm digitv_i2c_algo = { | ||
81 | .name = "Nebula DigiTV USB I2C algorithm", | ||
82 | .id = I2C_ALGO_BIT, | ||
83 | .master_xfer = digitv_i2c_xfer, | ||
84 | .functionality = digitv_i2c_func, | ||
85 | }; | ||
86 | |||
87 | /* Callbacks for DVB USB */ | ||
88 | static int digitv_identify_state (struct usb_device *udev, struct | ||
89 | dvb_usb_properties *props, struct dvb_usb_device_description **desc, | ||
90 | int *cold) | ||
91 | { | ||
92 | *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0; | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int digitv_mt352_demod_init(struct dvb_frontend *fe) | ||
97 | { | ||
98 | static u8 mt352_clock_config[] = { 0x89, 0x38, 0x2d }; | ||
99 | static u8 mt352_reset[] = { 0x50, 0x80 }; | ||
100 | static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 }; | ||
101 | |||
102 | static u8 mt352_agc_cfg[] = { 0x68, 0xa0 }; | ||
103 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0xa0 }; | ||
104 | static u8 mt352_acq_ctl[] = { 0x53, 0x50 }; | ||
105 | static u8 mt352_agc_target[] = { 0x67, 0x20 }; | ||
106 | |||
107 | static u8 mt352_rs_err_per[] = { 0x7c, 0x00, 0x01 }; | ||
108 | static u8 mt352_snr_select[] = { 0x79, 0x00, 0x20 }; | ||
109 | |||
110 | static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x05 }; | ||
111 | |||
112 | static u8 mt352_scan_ctl[] = { 0x88, 0x0f }; | ||
113 | static u8 mt352_capt_range[] = { 0x75, 0x32 }; | ||
114 | |||
115 | mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); | ||
116 | mt352_write(fe, mt352_reset, sizeof(mt352_reset)); | ||
117 | msleep(1); | ||
118 | mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio)); | ||
119 | |||
120 | mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); | ||
121 | mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); | ||
122 | mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl)); | ||
123 | mt352_write(fe, mt352_agc_target, sizeof(mt352_agc_target)); | ||
124 | |||
125 | |||
126 | mt352_write(fe, mt352_rs_err_per, sizeof(mt352_rs_err_per)); | ||
127 | mt352_write(fe, mt352_snr_select, sizeof(mt352_snr_select)); | ||
128 | |||
129 | mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1)); | ||
130 | |||
131 | mt352_write(fe, mt352_scan_ctl, sizeof(mt352_scan_ctl)); | ||
132 | mt352_write(fe, mt352_capt_range, sizeof(mt352_capt_range)); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static struct mt352_config digitv_mt352_config = { | ||
138 | .demod_address = 0x0, /* ignored by the digitv anyway */ | ||
139 | .demod_init = digitv_mt352_demod_init, | ||
140 | .pll_set = NULL, /* TODO */ | ||
141 | }; | ||
142 | |||
143 | static struct nxt6000_config digitv_nxt6000_config = { | ||
144 | .demod_address = 0x0, /* ignored by the digitv anyway */ | ||
145 | .clock_inversion = 0x0, | ||
146 | |||
147 | .pll_init = NULL, | ||
148 | .pll_set = NULL, | ||
149 | }; | ||
150 | |||
151 | static int digitv_frontend_attach(struct dvb_usb_device *d) | ||
152 | { | ||
153 | if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) == NULL) | ||
154 | return 0; | ||
155 | if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) == NULL) { | ||
156 | |||
157 | warn("nxt6000 support is not done yet, in fact you are one of the first " | ||
158 | "person who wants to use this device in Linux. Please report to " | ||
159 | "linux-dvb@linuxtv.org"); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | return -EIO; | ||
164 | } | ||
165 | |||
166 | static struct dvb_usb_rc_key digitv_rc_keys[] = { | ||
167 | { 0x00, 0x16, KEY_POWER }, /* dummy key */ | ||
168 | }; | ||
169 | |||
170 | /* TODO is it really the NEC protocol ? */ | ||
171 | int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
172 | { | ||
173 | u8 key[5]; | ||
174 | |||
175 | digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4); | ||
176 | /* TODO state, maybe it is VV ? */ | ||
177 | if (key[1] != 0) | ||
178 | key[0] = 0x01; /* if something is inside the buffer, simulate key press */ | ||
179 | |||
180 | /* call the universal NEC remote processor, to find out the key's state and event */ | ||
181 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
182 | if (key[0] != 0) | ||
183 | deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | |||
188 | /* DVB USB Driver stuff */ | ||
189 | static struct dvb_usb_properties digitv_properties; | ||
190 | |||
191 | static int digitv_probe(struct usb_interface *intf, | ||
192 | const struct usb_device_id *id) | ||
193 | { | ||
194 | return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE); | ||
195 | } | ||
196 | |||
197 | static struct usb_device_id digitv_table [] = { | ||
198 | { USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) }, | ||
199 | { } /* Terminating entry */ | ||
200 | }; | ||
201 | MODULE_DEVICE_TABLE (usb, digitv_table); | ||
202 | |||
203 | static struct dvb_usb_properties digitv_properties = { | ||
204 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
205 | |||
206 | .usb_ctrl = CYPRESS_FX2, | ||
207 | .firmware = "dvb-usb-digitv-01.fw", | ||
208 | |||
209 | .size_of_priv = 0, | ||
210 | |||
211 | .streaming_ctrl = NULL, | ||
212 | .pid_filter = NULL, | ||
213 | .pid_filter_ctrl = NULL, | ||
214 | .power_ctrl = NULL, | ||
215 | .frontend_attach = digitv_frontend_attach, | ||
216 | .tuner_attach = NULL, // digitv_tuner_attach, | ||
217 | .read_mac_address = NULL, | ||
218 | |||
219 | .rc_interval = 1000, | ||
220 | .rc_key_map = digitv_rc_keys, | ||
221 | .rc_key_map_size = ARRAY_SIZE(digitv_rc_keys), | ||
222 | .rc_query = digitv_rc_query, | ||
223 | |||
224 | .identify_state = digitv_identify_state, | ||
225 | |||
226 | .i2c_algo = &digitv_i2c_algo, | ||
227 | |||
228 | .generic_bulk_ctrl_endpoint = 0x01, | ||
229 | /* parameter for the MPEG2-data transfer */ | ||
230 | .urb = { | ||
231 | .type = DVB_USB_BULK, | ||
232 | .count = 7, | ||
233 | .endpoint = 0x02, | ||
234 | .u = { | ||
235 | .bulk = { | ||
236 | .buffersize = 4096, | ||
237 | } | ||
238 | } | ||
239 | }, | ||
240 | |||
241 | .num_device_descs = 2, | ||
242 | .devices = { | ||
243 | { "Nebula Electronics uDigiTV DVB-T USB2.0)", | ||
244 | { &digitv_table[0], NULL }, | ||
245 | { NULL }, | ||
246 | }, | ||
247 | } | ||
248 | }; | ||
249 | |||
250 | static struct usb_driver digitv_driver = { | ||
251 | .owner = THIS_MODULE, | ||
252 | .name = "Nebula Electronics uDigiTV DVB-T USB2.0 device", | ||
253 | .probe = digitv_probe, | ||
254 | .disconnect = dvb_usb_device_exit, | ||
255 | .id_table = digitv_table, | ||
256 | }; | ||
257 | |||
258 | /* module stuff */ | ||
259 | static int __init digitv_module_init(void) | ||
260 | { | ||
261 | int result; | ||
262 | if ((result = usb_register(&digitv_driver))) { | ||
263 | err("usb_register failed. Error number %d",result); | ||
264 | return result; | ||
265 | } | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static void __exit digitv_module_exit(void) | ||
271 | { | ||
272 | /* deregister this driver from the USB subsystem */ | ||
273 | usb_deregister(&digitv_driver); | ||
274 | } | ||
275 | |||
276 | module_init (digitv_module_init); | ||
277 | module_exit (digitv_module_exit); | ||
278 | |||
279 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
280 | MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0"); | ||
281 | MODULE_VERSION("1.0-alpha"); | ||
282 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h new file mode 100644 index 000000000000..477ee428a70e --- /dev/null +++ b/drivers/media/dvb/dvb-usb/digitv.h | |||
@@ -0,0 +1,65 @@ | |||
1 | #ifndef _DVB_USB_DIGITV_H_ | ||
2 | #define _DVB_USB_DIGITV_H_ | ||
3 | |||
4 | #define DVB_USB_LOG_PREFIX "digitv" | ||
5 | #include "dvb-usb.h" | ||
6 | |||
7 | extern int dvb_usb_digitv_debug; | ||
8 | #define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args) | ||
9 | |||
10 | /* protocol (from usblogging and the SDK: | ||
11 | * | ||
12 | * Always 7 bytes bulk message(s) for controlling | ||
13 | * | ||
14 | * First byte describes the command. Reads are 2 consecutive transfer (as always). | ||
15 | * | ||
16 | * General structure: | ||
17 | * | ||
18 | * write or first message of a read: | ||
19 | * <cmdbyte> VV <len> B0 B1 B2 B3 | ||
20 | * | ||
21 | * second message of a read | ||
22 | * <cmdbyte> VV <len> R0 R1 R2 R3 | ||
23 | * | ||
24 | * whereas 0 < len <= 4 | ||
25 | * | ||
26 | * I2C address is stored somewhere inside the device. | ||
27 | * | ||
28 | * 0x01 read from EEPROM | ||
29 | * VV = offset; B* = 0; R* = value(s) | ||
30 | * | ||
31 | * 0x02 read register of the COFDM | ||
32 | * VV = register; B* = 0; R* = value(s) | ||
33 | * | ||
34 | * 0x05 write register of the COFDM | ||
35 | * VV = register; B* = value(s); | ||
36 | * | ||
37 | * 0x06 write to the tuner (only for NXT6000) | ||
38 | * VV = 0; B* = PLL data; len = 4; | ||
39 | * | ||
40 | * 0x03 read remote control | ||
41 | * VV = 0; B* = 0; len = 4; R* = key | ||
42 | * | ||
43 | * 0x07 write to the remote (don't know why one should this, resetting ?) | ||
44 | * VV = 0; B* = key; len = 4; | ||
45 | * | ||
46 | * 0x08 write remote type | ||
47 | * VV = 0; B[0] = 0x01, len = 4 | ||
48 | * | ||
49 | * 0x09 write device init | ||
50 | * TODO | ||
51 | */ | ||
52 | #define USB_READ_EEPROM 1 | ||
53 | |||
54 | #define USB_READ_COFDM 2 | ||
55 | #define USB_WRITE_COFDM 5 | ||
56 | |||
57 | #define USB_WRITE_TUNER 6 | ||
58 | |||
59 | #define USB_READ_REMOTE 3 | ||
60 | #define USB_WRITE_REMOTE 7 | ||
61 | #define USB_WRITE_REMOTE_TYPE 8 | ||
62 | |||
63 | #define USB_DEV_INIT 9 | ||
64 | |||
65 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c new file mode 100644 index 000000000000..d17d768038c6 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* Frontend part of the Linux driver for the Yakumo/Hama/Typhoon DVB-T | ||
2 | * USB2.0 receiver. | ||
3 | * | ||
4 | * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include "dtt200u.h" | ||
13 | |||
14 | struct dtt200u_fe_state { | ||
15 | struct dvb_usb_device *d; | ||
16 | |||
17 | struct dvb_frontend_parameters fep; | ||
18 | struct dvb_frontend frontend; | ||
19 | }; | ||
20 | |||
21 | #define moan(which,what) info("unexpected value in '%s' for cmd '%02x' - please report to linux-dvb@linuxtv.org",which,what) | ||
22 | |||
23 | static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat) | ||
24 | { | ||
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 }; | ||
29 | |||
30 | dvb_usb_generic_rw(state->d,&bw,1,br,3,0); | ||
31 | switch (br[0]) { | ||
32 | case 0x01: | ||
33 | *stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
34 | break; | ||
35 | case 0x00: | ||
36 | *stat = 0; | ||
37 | break; | ||
38 | default: | ||
39 | moan("br[0]",GET_TUNE_STAT); | ||
40 | break; | ||
41 | } | ||
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 | return 0; | ||
49 | } | ||
50 | static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | ||
51 | { | ||
52 | 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); | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | ||
60 | { | ||
61 | 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); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | ||
69 | { | ||
70 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
71 | u8 bw = GET_SIG_STRENGTH, b; | ||
72 | dvb_usb_generic_rw(state->d,&bw,1,&b,1,0); | ||
73 | *strength = (b << 8) | b; | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
78 | { | ||
79 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
80 | u8 bw = GET_SNR,br; | ||
81 | dvb_usb_generic_rw(state->d,&bw,1,&br,1,0); | ||
82 | *snr = ~((br << 8) | br); | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static int dtt200u_fe_init(struct dvb_frontend* fe) | ||
87 | { | ||
88 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
89 | u8 b = RESET_DEMOD; | ||
90 | return dvb_usb_generic_write(state->d,&b,1); | ||
91 | } | ||
92 | |||
93 | static int dtt200u_fe_sleep(struct dvb_frontend* fe) | ||
94 | { | ||
95 | return dtt200u_fe_init(fe); | ||
96 | } | ||
97 | |||
98 | static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
99 | { | ||
100 | tune->min_delay_ms = 1500; | ||
101 | tune->step_size = 166667; | ||
102 | tune->max_drift = 166667 * 2; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int dtt200u_fe_set_frontend(struct dvb_frontend* fe, | ||
107 | struct dvb_frontend_parameters *fep) | ||
108 | { | ||
109 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
110 | u16 freq = fep->frequency / 250000; | ||
111 | u8 bw,bwbuf[2] = { SET_BANDWIDTH, 0 }, freqbuf[3] = { SET_FREQUENCY, 0, 0 }; | ||
112 | |||
113 | switch (fep->u.ofdm.bandwidth) { | ||
114 | case BANDWIDTH_8_MHZ: bw = 8; break; | ||
115 | case BANDWIDTH_7_MHZ: bw = 7; break; | ||
116 | case BANDWIDTH_6_MHZ: bw = 6; break; | ||
117 | case BANDWIDTH_AUTO: return -EOPNOTSUPP; | ||
118 | default: | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | deb_info("set_frontend\n"); | ||
122 | |||
123 | bwbuf[1] = bw; | ||
124 | dvb_usb_generic_write(state->d,bwbuf,2); | ||
125 | |||
126 | freqbuf[1] = freq & 0xff; | ||
127 | freqbuf[2] = (freq >> 8) & 0xff; | ||
128 | dvb_usb_generic_write(state->d,freqbuf,3); | ||
129 | |||
130 | memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters)); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, | ||
136 | struct dvb_frontend_parameters *fep) | ||
137 | { | ||
138 | struct dtt200u_fe_state *state = fe->demodulator_priv; | ||
139 | memcpy(fep,&state->fep,sizeof(struct dvb_frontend_parameters)); | ||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static void dtt200u_fe_release(struct dvb_frontend* fe) | ||
144 | { | ||
145 | struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv; | ||
146 | kfree(state); | ||
147 | } | ||
148 | |||
149 | static struct dvb_frontend_ops dtt200u_fe_ops; | ||
150 | |||
151 | struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d) | ||
152 | { | ||
153 | struct dtt200u_fe_state* state = NULL; | ||
154 | |||
155 | /* allocate memory for the internal state */ | ||
156 | state = (struct dtt200u_fe_state*) kmalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL); | ||
157 | if (state == NULL) | ||
158 | goto error; | ||
159 | memset(state,0,sizeof(struct dtt200u_fe_state)); | ||
160 | |||
161 | deb_info("attaching frontend dtt200u\n"); | ||
162 | |||
163 | state->d = d; | ||
164 | |||
165 | state->frontend.ops = &dtt200u_fe_ops; | ||
166 | state->frontend.demodulator_priv = state; | ||
167 | |||
168 | goto success; | ||
169 | error: | ||
170 | return NULL; | ||
171 | success: | ||
172 | return &state->frontend; | ||
173 | } | ||
174 | |||
175 | static struct dvb_frontend_ops dtt200u_fe_ops = { | ||
176 | .info = { | ||
177 | .name = "DTT200U (Yakumo/Typhoon/Hama) DVB-T", | ||
178 | .type = FE_OFDM, | ||
179 | .frequency_min = 44250000, | ||
180 | .frequency_max = 867250000, | ||
181 | .frequency_stepsize = 250000, | ||
182 | .caps = FE_CAN_INVERSION_AUTO | | ||
183 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
184 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
185 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
186 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
187 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
188 | FE_CAN_RECOVER | | ||
189 | FE_CAN_HIERARCHY_AUTO, | ||
190 | }, | ||
191 | |||
192 | .release = dtt200u_fe_release, | ||
193 | |||
194 | .init = dtt200u_fe_init, | ||
195 | .sleep = dtt200u_fe_sleep, | ||
196 | |||
197 | .set_frontend = dtt200u_fe_set_frontend, | ||
198 | .get_frontend = dtt200u_fe_get_frontend, | ||
199 | .get_tune_settings = dtt200u_fe_get_tune_settings, | ||
200 | |||
201 | .read_status = dtt200u_fe_read_status, | ||
202 | .read_ber = dtt200u_fe_read_ber, | ||
203 | .read_signal_strength = dtt200u_fe_read_signal_strength, | ||
204 | .read_snr = dtt200u_fe_read_snr, | ||
205 | .read_ucblocks = dtt200u_fe_read_unc_blocks, | ||
206 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c new file mode 100644 index 000000000000..fb2b5a2da137 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtt200u.c | |||
@@ -0,0 +1,171 @@ | |||
1 | /* DVB USB library compliant Linux driver for the Yakumo/Hama/Typhoon DVB-T | ||
2 | * USB2.0 receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include "dtt200u.h" | ||
13 | |||
14 | /* debug */ | ||
15 | int dvb_usb_dtt200u_debug; | ||
16 | module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644); | ||
17 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS); | ||
18 | |||
19 | static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff) | ||
20 | { | ||
21 | u8 b_streaming[2] = { SET_TS_CTRL, onoff }; | ||
22 | u8 b_rst_pid = RESET_PID_FILTER; | ||
23 | |||
24 | dvb_usb_generic_write(d,b_streaming,2); | ||
25 | |||
26 | if (!onoff) | ||
27 | dvb_usb_generic_write(d,&b_rst_pid,1); | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff) | ||
32 | { | ||
33 | u8 b_pid[4]; | ||
34 | pid = onoff ? pid : 0; | ||
35 | |||
36 | b_pid[0] = SET_PID_FILTER; | ||
37 | b_pid[1] = index; | ||
38 | b_pid[2] = pid & 0xff; | ||
39 | b_pid[3] = (pid >> 8) & 0xff; | ||
40 | |||
41 | return dvb_usb_generic_write(d,b_pid,4); | ||
42 | } | ||
43 | |||
44 | /* remote control */ | ||
45 | /* key list for the tiny remote control (Yakumo, don't know about the others) */ | ||
46 | static struct dvb_usb_rc_key dtt200u_rc_keys[] = { | ||
47 | { 0x80, 0x01, KEY_MUTE }, | ||
48 | { 0x80, 0x02, KEY_CHANNELDOWN }, | ||
49 | { 0x80, 0x03, KEY_VOLUMEDOWN }, | ||
50 | { 0x80, 0x04, KEY_1 }, | ||
51 | { 0x80, 0x05, KEY_2 }, | ||
52 | { 0x80, 0x06, KEY_3 }, | ||
53 | { 0x80, 0x07, KEY_4 }, | ||
54 | { 0x80, 0x08, KEY_5 }, | ||
55 | { 0x80, 0x09, KEY_6 }, | ||
56 | { 0x80, 0x0a, KEY_7 }, | ||
57 | { 0x00, 0x0c, KEY_ZOOM }, | ||
58 | { 0x80, 0x0d, KEY_0 }, | ||
59 | { 0x00, 0x0e, KEY_SELECT }, | ||
60 | { 0x80, 0x12, KEY_POWER }, | ||
61 | { 0x80, 0x1a, KEY_CHANNELUP }, | ||
62 | { 0x80, 0x1b, KEY_8 }, | ||
63 | { 0x80, 0x1e, KEY_VOLUMEUP }, | ||
64 | { 0x80, 0x1f, KEY_9 }, | ||
65 | }; | ||
66 | |||
67 | static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
68 | { | ||
69 | u8 key[5],cmd = GET_RC_KEY; | ||
70 | dvb_usb_generic_rw(d,&cmd,1,key,5,0); | ||
71 | dvb_usb_nec_rc_key_to_event(d,key,event,state); | ||
72 | if (key[0] != 0) | ||
73 | deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int dtt200u_frontend_attach(struct dvb_usb_device *d) | ||
78 | { | ||
79 | d->fe = dtt200u_fe_attach(d); | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static struct dvb_usb_properties dtt200u_properties; | ||
84 | |||
85 | static int dtt200u_usb_probe(struct usb_interface *intf, | ||
86 | const struct usb_device_id *id) | ||
87 | { | ||
88 | return dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE); | ||
89 | } | ||
90 | |||
91 | static struct usb_device_id dtt200u_usb_table [] = { | ||
92 | { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_COLD) }, | ||
93 | { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_WARM) }, | ||
94 | { 0 }, | ||
95 | }; | ||
96 | MODULE_DEVICE_TABLE(usb, dtt200u_usb_table); | ||
97 | |||
98 | static struct dvb_usb_properties dtt200u_properties = { | ||
99 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING, | ||
100 | .pid_filter_count = 255, /* It is a guess, but there are at least 10 */ | ||
101 | |||
102 | .usb_ctrl = CYPRESS_FX2, | ||
103 | .firmware = "dvb-usb-dtt200u-01.fw", | ||
104 | |||
105 | .streaming_ctrl = dtt200u_streaming_ctrl, | ||
106 | .pid_filter = dtt200u_pid_filter, | ||
107 | .frontend_attach = dtt200u_frontend_attach, | ||
108 | |||
109 | .rc_interval = 200, | ||
110 | .rc_key_map = dtt200u_rc_keys, | ||
111 | .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys), | ||
112 | .rc_query = dtt200u_rc_query, | ||
113 | |||
114 | .generic_bulk_ctrl_endpoint = 0x01, | ||
115 | |||
116 | /* parameter for the MPEG2-data transfer */ | ||
117 | .urb = { | ||
118 | .type = DVB_USB_BULK, | ||
119 | .count = 7, | ||
120 | .endpoint = 0x02, | ||
121 | .u = { | ||
122 | .bulk = { | ||
123 | .buffersize = 4096, | ||
124 | } | ||
125 | } | ||
126 | }, | ||
127 | |||
128 | .num_device_descs = 1, | ||
129 | .devices = { | ||
130 | { .name = "Yakumo/Hama/Typhoon DVB-T USB2.0)", | ||
131 | .cold_ids = { &dtt200u_usb_table[0], &dtt200u_usb_table[2] }, | ||
132 | .warm_ids = { &dtt200u_usb_table[1], NULL }, | ||
133 | }, | ||
134 | { 0 }, | ||
135 | } | ||
136 | }; | ||
137 | |||
138 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
139 | static struct usb_driver dtt200u_usb_driver = { | ||
140 | .owner = THIS_MODULE, | ||
141 | .name = "Yakumo/Hama/Typhoon DVB-T USB2.0", | ||
142 | .probe = dtt200u_usb_probe, | ||
143 | .disconnect = dvb_usb_device_exit, | ||
144 | .id_table = dtt200u_usb_table, | ||
145 | }; | ||
146 | |||
147 | /* module stuff */ | ||
148 | static int __init dtt200u_usb_module_init(void) | ||
149 | { | ||
150 | int result; | ||
151 | if ((result = usb_register(&dtt200u_usb_driver))) { | ||
152 | err("usb_register failed. (%d)",result); | ||
153 | return result; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static void __exit dtt200u_usb_module_exit(void) | ||
160 | { | ||
161 | /* deregister this driver from the USB subsystem */ | ||
162 | usb_deregister(&dtt200u_usb_driver); | ||
163 | } | ||
164 | |||
165 | module_init(dtt200u_usb_module_init); | ||
166 | module_exit(dtt200u_usb_module_exit); | ||
167 | |||
168 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
169 | MODULE_DESCRIPTION("Driver for the Yakumo/Hama/Typhoon DVB-T USB2.0 device"); | ||
170 | MODULE_VERSION("1.0"); | ||
171 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h new file mode 100644 index 000000000000..ed4142071518 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dtt200u.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* Common header file of Linux driver for the Yakumo/Hama/Typhoon DVB-T | ||
2 | * USB2.0 receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #ifndef _DVB_USB_DTT200U_H_ | ||
13 | #define _DVB_USB_DTT200U_H_ | ||
14 | |||
15 | #define DVB_USB_LOG_PREFIX "dtt200u" | ||
16 | #include "dvb-usb.h" | ||
17 | |||
18 | extern int dvb_usb_dtt200u_debug; | ||
19 | #define deb_info(args...) dprintk(dvb_usb_dtt200u_debug,0x01,args) | ||
20 | #define deb_xfer(args...) dprintk(dvb_usb_dtt200u_debug,0x02,args) | ||
21 | |||
22 | /* guessed protocol description (reverse engineered): | ||
23 | * read | ||
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 | * 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 | */ | ||
37 | |||
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 | ||
47 | |||
48 | /* write | ||
49 | * 01 - reset the demod | ||
50 | * 02 - frequency (divided by 250000) | ||
51 | * 03 - bandwidth | ||
52 | * 04 - pid table (index pid(7:0) pid(12:8)) | ||
53 | * 05 - reset the pid table | ||
54 | * 08 - demod transfer enabled or not (FX2 transfer is enabled by default) | ||
55 | */ | ||
56 | |||
57 | #define RESET_DEMOD 0x01 | ||
58 | #define SET_FREQUENCY 0x02 | ||
59 | #define SET_BANDWIDTH 0x03 | ||
60 | #define SET_PID_FILTER 0x04 | ||
61 | #define RESET_PID_FILTER 0x05 | ||
62 | #define SET_TS_CTRL 0x08 | ||
63 | |||
64 | extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d); | ||
65 | |||
66 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h new file mode 100644 index 000000000000..67e0d73fbceb --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* dvb-usb-common.h is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * a header file containing prototypes and types for internal use of the dvb-usb-lib | ||
7 | */ | ||
8 | #ifndef _DVB_USB_COMMON_H_ | ||
9 | #define _DVB_USB_COMMON_H_ | ||
10 | |||
11 | #define DVB_USB_LOG_PREFIX "dvb-usb" | ||
12 | #include "dvb-usb.h" | ||
13 | |||
14 | extern int dvb_usb_debug; | ||
15 | |||
16 | #define deb_info(args...) dprintk(dvb_usb_debug,0x01,args) | ||
17 | #define deb_xfer(args...) dprintk(dvb_usb_debug,0x02,args) | ||
18 | #define deb_pll(args...) dprintk(dvb_usb_debug,0x04,args) | ||
19 | #define deb_ts(args...) dprintk(dvb_usb_debug,0x08,args) | ||
20 | #define deb_err(args...) dprintk(dvb_usb_debug,0x10,args) | ||
21 | #define deb_rc(args...) dprintk(dvb_usb_debug,0x20,args) | ||
22 | #define deb_fw(args...) dprintk(dvb_usb_debug,0x40,args) | ||
23 | |||
24 | /* commonly used methods */ | ||
25 | extern int usb_cypress_load_firmware(struct usb_device *, const char *, int); | ||
26 | |||
27 | extern int dvb_usb_urb_submit(struct dvb_usb_device *); | ||
28 | extern int dvb_usb_urb_kill(struct dvb_usb_device *); | ||
29 | extern int dvb_usb_urb_init(struct dvb_usb_device *); | ||
30 | extern int dvb_usb_urb_exit(struct dvb_usb_device *); | ||
31 | |||
32 | extern int dvb_usb_i2c_init(struct dvb_usb_device *); | ||
33 | extern int dvb_usb_i2c_exit(struct dvb_usb_device *); | ||
34 | |||
35 | extern int dvb_usb_dvb_init(struct dvb_usb_device *); | ||
36 | extern int dvb_usb_dvb_exit(struct dvb_usb_device *); | ||
37 | |||
38 | extern int dvb_usb_fe_init(struct dvb_usb_device *); | ||
39 | extern int dvb_usb_fe_exit(struct dvb_usb_device *); | ||
40 | |||
41 | extern int dvb_usb_remote_init(struct dvb_usb_device *); | ||
42 | extern int dvb_usb_remote_exit(struct dvb_usb_device *); | ||
43 | |||
44 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c new file mode 100644 index 000000000000..bdd72f779707 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* dvb-usb-dvb.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for initializing and handling the | ||
7 | * linux-dvb API. | ||
8 | */ | ||
9 | #include "dvb-usb-common.h" | ||
10 | |||
11 | static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) | ||
12 | { | ||
13 | struct dvb_usb_device *d = dvbdmxfeed->demux->priv; | ||
14 | int newfeedcount,ret; | ||
15 | |||
16 | if (d == NULL) | ||
17 | return -ENODEV; | ||
18 | |||
19 | newfeedcount = d->feedcount + (onoff ? 1 : -1); | ||
20 | |||
21 | /* | ||
22 | * stop feed before setting a new pid if there will be no pid anymore | ||
23 | */ | ||
24 | if (newfeedcount == 0) { | ||
25 | deb_ts("stop feeding\n"); | ||
26 | |||
27 | if (d->props.streaming_ctrl != NULL) | ||
28 | if ((ret = d->props.streaming_ctrl(d,0))) | ||
29 | err("error while stopping stream."); | ||
30 | |||
31 | dvb_usb_urb_kill(d); | ||
32 | } | ||
33 | |||
34 | d->feedcount = newfeedcount; | ||
35 | |||
36 | /* activate the pid on the device specific pid_filter */ | ||
37 | deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off"); | ||
38 | if (d->props.caps & DVB_USB_HAS_PID_FILTER && | ||
39 | d->pid_filtering && | ||
40 | d->props.pid_filter != NULL) | ||
41 | d->props.pid_filter(d,dvbdmxfeed->index,dvbdmxfeed->pid,onoff); | ||
42 | |||
43 | /* start the feed if this was the first feed and there is still a feed | ||
44 | * for reception. | ||
45 | */ | ||
46 | if (d->feedcount == onoff && d->feedcount > 0) { | ||
47 | |||
48 | deb_ts("controlling pid parser\n"); | ||
49 | if (d->props.caps & DVB_USB_HAS_PID_FILTER && | ||
50 | d->props.caps & DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF && | ||
51 | d->props.pid_filter_ctrl != NULL) | ||
52 | if (d->props.pid_filter_ctrl(d,d->pid_filtering) < 0) | ||
53 | err("could not handle pid_parser"); | ||
54 | |||
55 | deb_ts("start feeding\n"); | ||
56 | if (d->props.streaming_ctrl != NULL) | ||
57 | if (d->props.streaming_ctrl(d,1)) { | ||
58 | err("error while enabling fifo."); | ||
59 | return -ENODEV; | ||
60 | } | ||
61 | |||
62 | dvb_usb_urb_submit(d); | ||
63 | } | ||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
68 | { | ||
69 | deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type); | ||
70 | return dvb_usb_ctrl_feed(dvbdmxfeed,1); | ||
71 | } | ||
72 | |||
73 | static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | ||
74 | { | ||
75 | deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type); | ||
76 | return dvb_usb_ctrl_feed(dvbdmxfeed,0); | ||
77 | } | ||
78 | |||
79 | int dvb_usb_dvb_init(struct dvb_usb_device *d) | ||
80 | { | ||
81 | int ret; | ||
82 | |||
83 | if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name, | ||
84 | d->owner)) < 0) { | ||
85 | deb_info("dvb_register_adapter failed: error %d", ret); | ||
86 | goto err; | ||
87 | } | ||
88 | d->dvb_adap.priv = d; | ||
89 | |||
90 | if (d->props.read_mac_address) { | ||
91 | if (d->props.read_mac_address(d,d->dvb_adap.proposed_mac) == 0) | ||
92 | info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",d->dvb_adap.proposed_mac[0], | ||
93 | d->dvb_adap.proposed_mac[1],d->dvb_adap.proposed_mac[2], | ||
94 | d->dvb_adap.proposed_mac[3],d->dvb_adap.proposed_mac[4], | ||
95 | d->dvb_adap.proposed_mac[5]); | ||
96 | else | ||
97 | err("MAC address reading failed."); | ||
98 | } | ||
99 | |||
100 | |||
101 | d->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | ||
102 | d->demux.priv = d; | ||
103 | |||
104 | d->demux.feednum = d->demux.filternum = d->max_feed_count; | ||
105 | d->demux.start_feed = dvb_usb_start_feed; | ||
106 | d->demux.stop_feed = dvb_usb_stop_feed; | ||
107 | d->demux.write_to_decoder = NULL; | ||
108 | if ((ret = dvb_dmx_init(&d->demux)) < 0) { | ||
109 | err("dvb_dmx_init failed: error %d",ret); | ||
110 | goto err_dmx; | ||
111 | } | ||
112 | |||
113 | d->dmxdev.filternum = d->demux.filternum; | ||
114 | d->dmxdev.demux = &d->demux.dmx; | ||
115 | d->dmxdev.capabilities = 0; | ||
116 | if ((ret = dvb_dmxdev_init(&d->dmxdev, &d->dvb_adap)) < 0) { | ||
117 | err("dvb_dmxdev_init failed: error %d",ret); | ||
118 | goto err_dmx_dev; | ||
119 | } | ||
120 | |||
121 | dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx); | ||
122 | |||
123 | goto success; | ||
124 | err_dmx_dev: | ||
125 | dvb_dmx_release(&d->demux); | ||
126 | err_dmx: | ||
127 | dvb_unregister_adapter(&d->dvb_adap); | ||
128 | err: | ||
129 | return ret; | ||
130 | success: | ||
131 | d->state |= DVB_USB_STATE_DVB; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | int dvb_usb_dvb_exit(struct dvb_usb_device *d) | ||
136 | { | ||
137 | if (d->state & DVB_USB_STATE_DVB) { | ||
138 | deb_info("unregistering DVB part\n"); | ||
139 | dvb_net_release(&d->dvb_net); | ||
140 | d->demux.dmx.close(&d->demux.dmx); | ||
141 | dvb_dmxdev_release(&d->dmxdev); | ||
142 | dvb_dmx_release(&d->demux); | ||
143 | dvb_unregister_adapter(&d->dvb_adap); | ||
144 | d->state &= ~DVB_USB_STATE_DVB; | ||
145 | } | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int dvb_usb_fe_wakeup(struct dvb_frontend *fe) | ||
150 | { | ||
151 | struct dvb_usb_device *d = fe->dvb->priv; | ||
152 | |||
153 | if (d->props.power_ctrl) | ||
154 | d->props.power_ctrl(d,1); | ||
155 | |||
156 | if (d->fe_init) | ||
157 | d->fe_init(fe); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int dvb_usb_fe_sleep(struct dvb_frontend *fe) | ||
163 | { | ||
164 | struct dvb_usb_device *d = fe->dvb->priv; | ||
165 | |||
166 | if (d->fe_sleep) | ||
167 | d->fe_sleep(fe); | ||
168 | |||
169 | if (d->props.power_ctrl) | ||
170 | d->props.power_ctrl(d,0); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | int dvb_usb_fe_init(struct dvb_usb_device* d) | ||
176 | { | ||
177 | if (d->props.frontend_attach == NULL) { | ||
178 | err("strange '%s' don't want to attach a frontend.",d->desc->name); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | d->props.frontend_attach(d); | ||
183 | |||
184 | /* re-assign sleep and wakeup functions */ | ||
185 | if (d->fe != NULL) { | ||
186 | d->fe_init = d->fe->ops->init; d->fe->ops->init = dvb_usb_fe_wakeup; | ||
187 | d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep; | ||
188 | |||
189 | if (dvb_register_frontend(&d->dvb_adap, d->fe)) { | ||
190 | err("Frontend registration failed."); | ||
191 | if (d->fe->ops->release) | ||
192 | d->fe->ops->release(d->fe); | ||
193 | d->fe = NULL; | ||
194 | return -ENODEV; | ||
195 | } | ||
196 | } else | ||
197 | err("no frontend was attached by '%s'",d->desc->name); | ||
198 | |||
199 | if (d->props.tuner_attach != NULL) | ||
200 | d->props.tuner_attach(d); | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | int dvb_usb_fe_exit(struct dvb_usb_device *d) | ||
206 | { | ||
207 | if (d->fe != NULL) | ||
208 | dvb_unregister_frontend(d->fe); | ||
209 | return 0; | ||
210 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c new file mode 100644 index 000000000000..5244e39770a0 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* dvb-usb-firmware.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices. | ||
7 | * | ||
8 | * FIXME: This part does actually not belong to dvb-usb, but to the usb-subsystem. | ||
9 | */ | ||
10 | #include "dvb-usb-common.h" | ||
11 | |||
12 | #include <linux/firmware.h> | ||
13 | #include <linux/usb.h> | ||
14 | |||
15 | struct usb_cypress_controller { | ||
16 | int id; | ||
17 | const char *name; /* name of the usb controller */ | ||
18 | u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */ | ||
19 | }; | ||
20 | |||
21 | static struct usb_cypress_controller cypress[] = { | ||
22 | { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 }, | ||
23 | { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 }, | ||
24 | { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 }, | ||
25 | }; | ||
26 | |||
27 | /* | ||
28 | * load a firmware packet to the device | ||
29 | */ | ||
30 | static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len) | ||
31 | { | ||
32 | return usb_control_msg(udev, usb_sndctrlpipe(udev,0), | ||
33 | 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ); | ||
34 | } | ||
35 | |||
36 | int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type) | ||
37 | { | ||
38 | const struct firmware *fw = NULL; | ||
39 | u16 addr; | ||
40 | u8 *b,*p; | ||
41 | int ret = 0,i; | ||
42 | |||
43 | if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) { | ||
44 | err("did not find the firmware file. (%s) " | ||
45 | "Please see linux/Documentation/dvb/ for more details on firmware-problems.", | ||
46 | filename); | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name); | ||
51 | |||
52 | p = kmalloc(fw->size,GFP_KERNEL); | ||
53 | if (p != NULL) { | ||
54 | u8 reset; | ||
55 | /* | ||
56 | * you cannot use the fw->data as buffer for | ||
57 | * usb_control_msg, a new buffer has to be | ||
58 | * created | ||
59 | */ | ||
60 | memcpy(p,fw->data,fw->size); | ||
61 | |||
62 | /* stop the CPU */ | ||
63 | reset = 1; | ||
64 | if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1) | ||
65 | err("could not stop the USB controller CPU."); | ||
66 | for(i = 0; p[i+3] == 0 && i < fw->size; ) { | ||
67 | b = (u8 *) &p[i]; | ||
68 | addr = cpu_to_le16( *((u16 *) &b[1]) ); | ||
69 | |||
70 | deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]); | ||
71 | |||
72 | ret = usb_cypress_writemem(udev,addr,&b[4],b[0]); | ||
73 | |||
74 | if (ret != b[0]) { | ||
75 | err("error while transferring firmware " | ||
76 | "(transferred size: %d, block size: %d)", | ||
77 | ret,b[0]); | ||
78 | ret = -EINVAL; | ||
79 | break; | ||
80 | } | ||
81 | i += 5 + b[0]; | ||
82 | } | ||
83 | /* length in ret */ | ||
84 | if (ret > 0) | ||
85 | ret = 0; | ||
86 | /* restart the CPU */ | ||
87 | reset = 0; | ||
88 | if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) { | ||
89 | err("could not restart the USB controller CPU."); | ||
90 | ret = -EINVAL; | ||
91 | } | ||
92 | |||
93 | kfree(p); | ||
94 | } else { | ||
95 | ret = -ENOMEM; | ||
96 | } | ||
97 | release_firmware(fw); | ||
98 | |||
99 | return ret; | ||
100 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c new file mode 100644 index 000000000000..9f0a8d90d146 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* dvb-usb-i2c.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for (de-)initializing an I2C adapter. | ||
7 | */ | ||
8 | #include "dvb-usb-common.h" | ||
9 | |||
10 | int dvb_usb_i2c_init(struct dvb_usb_device *d) | ||
11 | { | ||
12 | int ret = 0; | ||
13 | |||
14 | if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER)) | ||
15 | return 0; | ||
16 | |||
17 | if (d->props.i2c_algo == NULL) { | ||
18 | err("no i2c algorithm specified"); | ||
19 | return -EINVAL; | ||
20 | } | ||
21 | |||
22 | strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE); | ||
23 | #ifdef I2C_ADAP_CLASS_TV_DIGITAL | ||
24 | d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, | ||
25 | #else | ||
26 | d->i2c_adap.class = I2C_CLASS_TV_DIGITAL, | ||
27 | #endif | ||
28 | d->i2c_adap.algo = d->props.i2c_algo; | ||
29 | d->i2c_adap.algo_data = NULL; | ||
30 | d->i2c_adap.id = I2C_ALGO_BIT; | ||
31 | |||
32 | i2c_set_adapdata(&d->i2c_adap, d); | ||
33 | |||
34 | if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0) | ||
35 | err("could not add i2c adapter"); | ||
36 | |||
37 | d->state |= DVB_USB_STATE_I2C; | ||
38 | |||
39 | return ret; | ||
40 | } | ||
41 | |||
42 | int dvb_usb_i2c_exit(struct dvb_usb_device *d) | ||
43 | { | ||
44 | if (d->state & DVB_USB_STATE_I2C) | ||
45 | i2c_del_adapter(&d->i2c_adap); | ||
46 | d->state &= ~DVB_USB_STATE_I2C; | ||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | int dvb_usb_pll_init_i2c(struct dvb_frontend *fe) | ||
51 | { | ||
52 | struct dvb_usb_device *d = fe->dvb->priv; | ||
53 | struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 }; | ||
54 | int ret = 0; | ||
55 | |||
56 | /* if there is nothing to initialize */ | ||
57 | if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 && | ||
58 | d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00) | ||
59 | return 0; | ||
60 | |||
61 | if (d->tuner_pass_ctrl) | ||
62 | d->tuner_pass_ctrl(fe,1,d->pll_addr); | ||
63 | |||
64 | deb_pll("pll init: %x\n",d->pll_addr); | ||
65 | deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1], | ||
66 | d->pll_init[2],d->pll_init[3]); | ||
67 | |||
68 | if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) { | ||
69 | err("tuner i2c write failed for pll_init."); | ||
70 | ret = -EREMOTEIO; | ||
71 | } | ||
72 | msleep(1); | ||
73 | |||
74 | if (d->tuner_pass_ctrl) | ||
75 | d->tuner_pass_ctrl(fe,0,d->pll_addr); | ||
76 | return ret; | ||
77 | } | ||
78 | EXPORT_SYMBOL(dvb_usb_pll_init_i2c); | ||
79 | |||
80 | int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5]) | ||
81 | { | ||
82 | struct dvb_usb_device *d = fe->dvb->priv; | ||
83 | |||
84 | deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc); | ||
85 | |||
86 | b[0] = d->pll_addr << 1; | ||
87 | dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth); | ||
88 | |||
89 | deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | EXPORT_SYMBOL(dvb_usb_pll_set); | ||
94 | |||
95 | int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | ||
96 | { | ||
97 | struct dvb_usb_device *d = fe->dvb->priv; | ||
98 | int ret = 0; | ||
99 | u8 b[5]; | ||
100 | struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 }; | ||
101 | |||
102 | dvb_usb_pll_set(fe,fep,b); | ||
103 | |||
104 | if (d->tuner_pass_ctrl) | ||
105 | d->tuner_pass_ctrl(fe,1,d->pll_addr); | ||
106 | |||
107 | if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) { | ||
108 | err("tuner i2c write failed for pll_set."); | ||
109 | ret = -EREMOTEIO; | ||
110 | } | ||
111 | msleep(1); | ||
112 | |||
113 | if (d->tuner_pass_ctrl) | ||
114 | d->tuner_pass_ctrl(fe,0,d->pll_addr); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | EXPORT_SYMBOL(dvb_usb_pll_set_i2c); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h new file mode 100644 index 000000000000..bcb34191868b --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* dvb-usb-ids.h is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see | ||
4 | * dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * a header file containing define's for the USB device supported by the | ||
7 | * various drivers. | ||
8 | */ | ||
9 | #ifndef _DVB_USB_IDS_H_ | ||
10 | #define _DVB_USB_IDS_H_ | ||
11 | |||
12 | /* Vendor IDs */ | ||
13 | #define USB_VID_ADSTECH 0x06e1 | ||
14 | #define USB_VID_ANCHOR 0x0547 | ||
15 | #define USB_VID_AVERMEDIA_UNK 0x14aa | ||
16 | #define USB_VID_AVERMEDIA 0x07ca | ||
17 | #define USB_VID_COMPRO 0x185b | ||
18 | #define USB_VID_COMPRO_UNK 0x145f | ||
19 | #define USB_VID_CYPRESS 0x04b4 | ||
20 | #define USB_VID_DIBCOM 0x10b8 | ||
21 | #define USB_VID_DVICO 0x0fe9 | ||
22 | #define USB_VID_EMPIA 0xeb1a | ||
23 | #define USB_VID_GRANDTEC 0x5032 | ||
24 | #define USB_VID_HANFTEK 0x15f4 | ||
25 | #define USB_VID_HAUPPAUGE 0x2040 | ||
26 | #define USB_VID_HYPER_PALTEK 0x1025 | ||
27 | #define USB_VID_VISIONPLUS 0x13d3 | ||
28 | #define USB_VID_TWINHAN 0x1822 | ||
29 | #define USB_VID_ULTIMA_ELECTRONIC 0x05d8 | ||
30 | |||
31 | /* Product IDs */ | ||
32 | #define USB_PID_ADSTECH_USB2_COLD 0xa333 | ||
33 | #define USB_PID_ADSTECH_USB2_WARM 0xa334 | ||
34 | #define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 | ||
35 | #define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 | ||
36 | #define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 | ||
37 | #define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801 | ||
38 | #define USB_PID_COMPRO_DVBU2000_COLD 0xd000 | ||
39 | #define USB_PID_COMPRO_DVBU2000_WARM 0xd001 | ||
40 | #define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c | ||
41 | #define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d | ||
42 | #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 | ||
43 | #define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 | ||
44 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 | ||
45 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | ||
46 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | ||
47 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | ||
48 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | ||
49 | #define USB_PID_KWORLD_VSTREAM_COLD 0x17de | ||
50 | #define USB_PID_KWORLD_VSTREAM_WARM 0x17df | ||
51 | #define USB_PID_TWINHAN_VP7041_COLD 0x3201 | ||
52 | #define USB_PID_TWINHAN_VP7041_WARM 0x3202 | ||
53 | #define USB_PID_TWINHAN_VP7045_COLD 0x3205 | ||
54 | #define USB_PID_TWINHAN_VP7045_WARM 0x3206 | ||
55 | #define USB_PID_DNTV_TINYUSB2_COLD 0x3223 | ||
56 | #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 | ||
57 | #define USB_PID_TWINHAN_VP7021_COLD 0x3207 | ||
58 | #define USB_PID_TWINHAN_VP7021_WARM 0x3208 | ||
59 | #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 | ||
60 | #define USB_PID_ULTIMA_TVBOX_WARM 0x8106 | ||
61 | #define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 | ||
62 | #define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 | ||
63 | #define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 | ||
64 | #define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 | ||
65 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 | ||
66 | #define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 | ||
67 | #define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e | ||
68 | #define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f | ||
69 | #define USB_PID_HANFTEK_UMT_010_COLD 0x0001 | ||
70 | #define USB_PID_HANFTEK_UMT_010_WARM 0x0015 | ||
71 | #define USB_PID_DTT200U_COLD 0x0201 | ||
72 | #define USB_PID_DTT200U_WARM 0x0301 | ||
73 | #define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 | ||
74 | #define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 | ||
75 | #define USB_PID_NEBULA_DIGITV 0x0201 | ||
76 | #define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00 | ||
77 | #define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10 | ||
78 | #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 | ||
79 | #define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01 | ||
80 | #define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11 | ||
81 | |||
82 | |||
83 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c new file mode 100644 index 000000000000..3aadec974cf1 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * DVB USB library - provides a generic interface for a DVB USB device driver. | ||
3 | * | ||
4 | * dvb-usb-init.c | ||
5 | * | ||
6 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation, version 2. | ||
11 | * | ||
12 | * see Documentation/dvb/README.dvb-usb for more information | ||
13 | */ | ||
14 | #include "dvb-usb-common.h" | ||
15 | |||
16 | /* debug */ | ||
17 | int dvb_usb_debug; | ||
18 | module_param_named(debug,dvb_usb_debug, int, 0644); | ||
19 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS); | ||
20 | |||
21 | /* general initialization functions */ | ||
22 | int dvb_usb_exit(struct dvb_usb_device *d) | ||
23 | { | ||
24 | deb_info("state before exiting everything: %x\n",d->state); | ||
25 | dvb_usb_remote_exit(d); | ||
26 | dvb_usb_fe_exit(d); | ||
27 | dvb_usb_i2c_exit(d); | ||
28 | dvb_usb_dvb_exit(d); | ||
29 | dvb_usb_urb_exit(d); | ||
30 | deb_info("state should be zero now: %x\n",d->state); | ||
31 | d->state = DVB_USB_STATE_INIT; | ||
32 | kfree(d->priv); | ||
33 | kfree(d); | ||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int dvb_usb_init(struct dvb_usb_device *d) | ||
38 | { | ||
39 | int ret = 0; | ||
40 | |||
41 | sema_init(&d->usb_sem, 1); | ||
42 | sema_init(&d->i2c_sem, 1); | ||
43 | |||
44 | d->state = DVB_USB_STATE_INIT; | ||
45 | |||
46 | /* check the capabilites and set appropriate variables */ | ||
47 | |||
48 | /* speed - when running at FULL speed we need a HW PID filter */ | ||
49 | if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) { | ||
50 | err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a HW PID filter)"); | ||
51 | return -ENODEV; | ||
52 | } | ||
53 | |||
54 | if ((d->udev->speed == USB_SPEED_FULL && d->props.caps & DVB_USB_HAS_PID_FILTER) || | ||
55 | (d->props.caps & DVB_USB_NEED_PID_FILTERING)) { | ||
56 | info("will use the device's hw PID filter."); | ||
57 | d->pid_filtering = 1; | ||
58 | d->max_feed_count = d->props.pid_filter_count; | ||
59 | } else { | ||
60 | info("will pass the complete MPEG2 transport stream to the demuxer."); | ||
61 | d->pid_filtering = 0; | ||
62 | d->max_feed_count = 255; | ||
63 | } | ||
64 | |||
65 | if (d->props.power_ctrl) | ||
66 | d->props.power_ctrl(d,1); | ||
67 | |||
68 | if ((ret = dvb_usb_urb_init(d)) || | ||
69 | (ret = dvb_usb_dvb_init(d)) || | ||
70 | (ret = dvb_usb_i2c_init(d)) || | ||
71 | (ret = dvb_usb_fe_init(d))) { | ||
72 | dvb_usb_exit(d); | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | if ((ret = dvb_usb_remote_init(d))) | ||
77 | err("could not initialize remote control."); | ||
78 | |||
79 | if (d->props.power_ctrl) | ||
80 | d->props.power_ctrl(d,0); | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | /* determine the name and the state of the just found USB device */ | ||
86 | static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_properties *props, int *cold) | ||
87 | { | ||
88 | int i,j; | ||
89 | struct dvb_usb_device_description *desc = NULL; | ||
90 | *cold = -1; | ||
91 | |||
92 | for (i = 0; i < props->num_device_descs; i++) { | ||
93 | |||
94 | for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) { | ||
95 | deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct); | ||
96 | if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && | ||
97 | props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { | ||
98 | *cold = 1; | ||
99 | desc = &props->devices[i]; | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | if (desc != NULL) | ||
105 | break; | ||
106 | |||
107 | for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) { | ||
108 | deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct); | ||
109 | if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) && | ||
110 | props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) { | ||
111 | *cold = 0; | ||
112 | desc = &props->devices[i]; | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | if (desc != NULL && props->identify_state != NULL) | ||
119 | props->identify_state(udev,props,&desc,cold); | ||
120 | |||
121 | return desc; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * USB | ||
126 | */ | ||
127 | int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner) | ||
128 | { | ||
129 | struct usb_device *udev = interface_to_usbdev(intf); | ||
130 | struct dvb_usb_device *d = NULL; | ||
131 | struct dvb_usb_device_description *desc = NULL; | ||
132 | |||
133 | int ret = -ENOMEM,cold=0; | ||
134 | |||
135 | if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) { | ||
136 | deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n"); | ||
137 | return -ENODEV; | ||
138 | } | ||
139 | |||
140 | if (cold) { | ||
141 | info("found a '%s' in cold state, will try to load a firmware",desc->name); | ||
142 | ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl); | ||
143 | } else { | ||
144 | info("found a '%s' in warm state.",desc->name); | ||
145 | d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL); | ||
146 | if (d == NULL) { | ||
147 | err("no memory for 'struct dvb_usb_device'"); | ||
148 | return ret; | ||
149 | } | ||
150 | memset(d,0,sizeof(struct dvb_usb_device)); | ||
151 | |||
152 | d->udev = udev; | ||
153 | memcpy(&d->props,props,sizeof(struct dvb_usb_properties)); | ||
154 | d->desc = desc; | ||
155 | d->owner = owner; | ||
156 | |||
157 | if (d->props.size_of_priv > 0) { | ||
158 | d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL); | ||
159 | if (d->priv == NULL) { | ||
160 | err("no memory for priv in 'struct dvb_usb_device'"); | ||
161 | kfree(d); | ||
162 | return -ENOMEM; | ||
163 | } | ||
164 | memset(d->priv,0,d->props.size_of_priv); | ||
165 | } | ||
166 | |||
167 | usb_set_intfdata(intf, d); | ||
168 | |||
169 | ret = dvb_usb_init(d); | ||
170 | } | ||
171 | |||
172 | if (ret == 0) | ||
173 | info("%s successfully initialized and connected.",desc->name); | ||
174 | else | ||
175 | info("%s error while loading driver (%d)",desc->name,ret); | ||
176 | return ret; | ||
177 | } | ||
178 | EXPORT_SYMBOL(dvb_usb_device_init); | ||
179 | |||
180 | void dvb_usb_device_exit(struct usb_interface *intf) | ||
181 | { | ||
182 | struct dvb_usb_device *d = usb_get_intfdata(intf); | ||
183 | const char *name = "generic DVB-USB module"; | ||
184 | |||
185 | usb_set_intfdata(intf,NULL); | ||
186 | if (d != NULL && d->desc != NULL) { | ||
187 | name = d->desc->name; | ||
188 | dvb_usb_exit(d); | ||
189 | } | ||
190 | info("%s successfully deinitialized and disconnected.",name); | ||
191 | |||
192 | } | ||
193 | EXPORT_SYMBOL(dvb_usb_device_exit); | ||
194 | |||
195 | /* module stuff */ | ||
196 | static int __init dvb_usb_module_init(void) | ||
197 | { | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void __exit dvb_usb_module_exit(void) | ||
202 | { | ||
203 | } | ||
204 | |||
205 | module_init (dvb_usb_module_init); | ||
206 | module_exit (dvb_usb_module_exit); | ||
207 | |||
208 | MODULE_VERSION("0.3"); | ||
209 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
210 | MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices"); | ||
211 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c new file mode 100644 index 000000000000..9f1e23f82bae --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* dvb-usb-remote.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for initializing the the input-device and for handling remote-control-queries. | ||
7 | */ | ||
8 | #include "dvb-usb-common.h" | ||
9 | |||
10 | /* Remote-control poll function - called every dib->rc_query_interval ms to see | ||
11 | * whether the remote control has received anything. | ||
12 | * | ||
13 | * TODO: Fix the repeat rate of the input device. | ||
14 | */ | ||
15 | static void dvb_usb_read_remote_control(void *data) | ||
16 | { | ||
17 | struct dvb_usb_device *d = data; | ||
18 | u32 event; | ||
19 | int state; | ||
20 | |||
21 | /* TODO: need a lock here. We can simply skip checking for the remote control | ||
22 | if we're busy. */ | ||
23 | |||
24 | if (d->props.rc_query(d,&event,&state)) { | ||
25 | err("error while querying for an remote control event."); | ||
26 | goto schedule; | ||
27 | } | ||
28 | |||
29 | |||
30 | switch (state) { | ||
31 | case REMOTE_NO_KEY_PRESSED: | ||
32 | break; | ||
33 | case REMOTE_KEY_PRESSED: | ||
34 | deb_rc("key pressed\n"); | ||
35 | d->last_event = event; | ||
36 | case REMOTE_KEY_REPEAT: | ||
37 | deb_rc("key repeated\n"); | ||
38 | input_event(&d->rc_input_dev, EV_KEY, event, 1); | ||
39 | input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0); | ||
40 | input_sync(&d->rc_input_dev); | ||
41 | break; | ||
42 | default: | ||
43 | break; | ||
44 | } | ||
45 | |||
46 | /* improved repeat handling ??? | ||
47 | switch (state) { | ||
48 | case REMOTE_NO_KEY_PRESSED: | ||
49 | deb_rc("NO KEY PRESSED\n"); | ||
50 | if (d->last_state != REMOTE_NO_KEY_PRESSED) { | ||
51 | deb_rc("releasing event %d\n",d->last_event); | ||
52 | input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0); | ||
53 | input_sync(&d->rc_input_dev); | ||
54 | } | ||
55 | d->last_state = REMOTE_NO_KEY_PRESSED; | ||
56 | d->last_event = 0; | ||
57 | break; | ||
58 | case REMOTE_KEY_PRESSED: | ||
59 | deb_rc("KEY PRESSED\n"); | ||
60 | deb_rc("pressing event %d\n",event); | ||
61 | |||
62 | input_event(&d->rc_input_dev, EV_KEY, event, 1); | ||
63 | input_sync(&d->rc_input_dev); | ||
64 | |||
65 | d->last_event = event; | ||
66 | d->last_state = REMOTE_KEY_PRESSED; | ||
67 | break; | ||
68 | case REMOTE_KEY_REPEAT: | ||
69 | deb_rc("KEY_REPEAT\n"); | ||
70 | if (d->last_state != REMOTE_NO_KEY_PRESSED) { | ||
71 | deb_rc("repeating event %d\n",d->last_event); | ||
72 | input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2); | ||
73 | input_sync(&d->rc_input_dev); | ||
74 | d->last_state = REMOTE_KEY_REPEAT; | ||
75 | } | ||
76 | default: | ||
77 | break; | ||
78 | } | ||
79 | */ | ||
80 | |||
81 | schedule: | ||
82 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); | ||
83 | } | ||
84 | |||
85 | int dvb_usb_remote_init(struct dvb_usb_device *d) | ||
86 | { | ||
87 | int i; | ||
88 | if (d->props.rc_key_map == NULL) | ||
89 | return 0; | ||
90 | |||
91 | /* Initialise the remote-control structures.*/ | ||
92 | init_input_dev(&d->rc_input_dev); | ||
93 | |||
94 | d->rc_input_dev.evbit[0] = BIT(EV_KEY); | ||
95 | d->rc_input_dev.keycodesize = sizeof(unsigned char); | ||
96 | d->rc_input_dev.keycodemax = KEY_MAX; | ||
97 | d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver"; | ||
98 | |||
99 | /* set the bits for the keys */ | ||
100 | deb_rc("key map size: %d\n",d->props.rc_key_map_size); | ||
101 | for (i = 0; i < d->props.rc_key_map_size; i++) { | ||
102 | deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i); | ||
103 | set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit); | ||
104 | } | ||
105 | |||
106 | /* Start the remote-control polling. */ | ||
107 | if (d->props.rc_interval < 40) | ||
108 | d->props.rc_interval = 100; /* default */ | ||
109 | |||
110 | /* setting these two values to non-zero, we have to manage key repeats */ | ||
111 | d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval; | ||
112 | d->rc_input_dev.rep[REP_DELAY] = d->props.rc_interval + 150; | ||
113 | |||
114 | input_register_device(&d->rc_input_dev); | ||
115 | |||
116 | INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d); | ||
117 | |||
118 | info("schedule remote query interval to %d msecs.",d->props.rc_interval); | ||
119 | schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval)); | ||
120 | |||
121 | d->state |= DVB_USB_STATE_REMOTE; | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | int dvb_usb_remote_exit(struct dvb_usb_device *d) | ||
127 | { | ||
128 | if (d->state & DVB_USB_STATE_REMOTE) { | ||
129 | cancel_delayed_work(&d->rc_query_work); | ||
130 | flush_scheduled_work(); | ||
131 | input_unregister_device(&d->rc_input_dev); | ||
132 | } | ||
133 | d->state &= ~DVB_USB_STATE_REMOTE; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | #define DVB_USB_RC_NEC_EMPTY 0x00 | ||
138 | #define DVB_USB_RC_NEC_KEY_PRESSED 0x01 | ||
139 | #define DVB_USB_RC_NEC_KEY_REPEATED 0x02 | ||
140 | int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d, | ||
141 | u8 keybuf[5], u32 *event, int *state) | ||
142 | { | ||
143 | int i; | ||
144 | struct dvb_usb_rc_key *keymap = d->props.rc_key_map; | ||
145 | *event = 0; | ||
146 | *state = REMOTE_NO_KEY_PRESSED; | ||
147 | switch (keybuf[0]) { | ||
148 | case DVB_USB_RC_NEC_EMPTY: | ||
149 | break; | ||
150 | case DVB_USB_RC_NEC_KEY_PRESSED: | ||
151 | if ((u8) ~keybuf[1] != keybuf[2] || | ||
152 | (u8) ~keybuf[3] != keybuf[4]) { | ||
153 | deb_err("remote control checksum failed.\n"); | ||
154 | break; | ||
155 | } | ||
156 | /* See if we can match the raw key code. */ | ||
157 | for (i = 0; i < sizeof(keymap)/sizeof(struct dvb_usb_rc_key); i++) | ||
158 | if (keymap[i].custom == keybuf[1] && | ||
159 | keymap[i].data == keybuf[3]) { | ||
160 | *event = keymap[i].event; | ||
161 | *state = REMOTE_KEY_PRESSED; | ||
162 | break; | ||
163 | } | ||
164 | deb_err("key mapping failed - no appropriate key found in keymapping\n"); | ||
165 | break; | ||
166 | case DVB_USB_RC_NEC_KEY_REPEATED: | ||
167 | *state = REMOTE_KEY_REPEAT; | ||
168 | break; | ||
169 | default: | ||
170 | deb_err("unkown type of remote status: %d\n",keybuf[0]); | ||
171 | break; | ||
172 | } | ||
173 | return 0; | ||
174 | } | ||
175 | EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event); | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c new file mode 100644 index 000000000000..83d476fb410a --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* dvb-usb-urb.c is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * This file contains functions for initializing and handling the | ||
7 | * USB and URB stuff. | ||
8 | */ | ||
9 | #include "dvb-usb-common.h" | ||
10 | |||
11 | int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, | ||
12 | u16 rlen, int delay_ms) | ||
13 | { | ||
14 | int actlen,ret = -ENOMEM; | ||
15 | |||
16 | if (d->props.generic_bulk_ctrl_endpoint == 0) { | ||
17 | err("endpoint for generic control not specified."); | ||
18 | return -EINVAL; | ||
19 | } | ||
20 | |||
21 | if (wbuf == NULL || wlen == 0) | ||
22 | return -EINVAL; | ||
23 | |||
24 | if ((ret = down_interruptible(&d->usb_sem))) | ||
25 | return ret; | ||
26 | |||
27 | debug_dump(wbuf,wlen,deb_xfer); | ||
28 | |||
29 | ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev, | ||
30 | d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen, | ||
31 | 2*HZ); | ||
32 | |||
33 | if (ret) | ||
34 | err("bulk message failed: %d (%d/%d)",ret,wlen,actlen); | ||
35 | else | ||
36 | ret = actlen != wlen ? -1 : 0; | ||
37 | |||
38 | /* an answer is expected, and no error before */ | ||
39 | if (!ret && rbuf && rlen) { | ||
40 | if (delay_ms) | ||
41 | msleep(delay_ms); | ||
42 | |||
43 | ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev, | ||
44 | d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen, | ||
45 | 2*HZ); | ||
46 | |||
47 | if (ret) | ||
48 | err("recv bulk message failed: %d",ret); | ||
49 | else | ||
50 | debug_dump(rbuf,actlen,deb_xfer); | ||
51 | } | ||
52 | |||
53 | up(&d->usb_sem); | ||
54 | return ret; | ||
55 | } | ||
56 | EXPORT_SYMBOL(dvb_usb_generic_rw); | ||
57 | |||
58 | int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) | ||
59 | { | ||
60 | return dvb_usb_generic_rw(d,buf,len,NULL,0,0); | ||
61 | } | ||
62 | EXPORT_SYMBOL(dvb_usb_generic_write); | ||
63 | |||
64 | static void dvb_usb_bulk_urb_complete(struct urb *urb, struct pt_regs *ptregs) | ||
65 | { | ||
66 | struct dvb_usb_device *d = urb->context; | ||
67 | |||
68 | deb_ts("bulk urb completed. feedcount: %d, status: %d, length: %d\n",d->feedcount,urb->status, | ||
69 | urb->actual_length); | ||
70 | |||
71 | switch (urb->status) { | ||
72 | case 0: /* success */ | ||
73 | case -ETIMEDOUT: /* NAK */ | ||
74 | break; | ||
75 | case -ECONNRESET: /* kill */ | ||
76 | case -ENOENT: | ||
77 | case -ESHUTDOWN: | ||
78 | return; | ||
79 | default: /* error */ | ||
80 | deb_ts("urb completition error %d.", urb->status); | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | if (d->feedcount > 0 && urb->actual_length > 0) { | ||
85 | if (d->state & DVB_USB_STATE_DVB) | ||
86 | dvb_dmx_swfilter(&d->demux, (u8*) urb->transfer_buffer,urb->actual_length); | ||
87 | } else | ||
88 | deb_ts("URB dropped because of feedcount.\n"); | ||
89 | |||
90 | usb_submit_urb(urb,GFP_ATOMIC); | ||
91 | } | ||
92 | |||
93 | int dvb_usb_urb_kill(struct dvb_usb_device *d) | ||
94 | { | ||
95 | int i; | ||
96 | for (i = 0; i < d->urbs_submitted; i++) { | ||
97 | deb_info("killing URB no. %d.\n",i); | ||
98 | |||
99 | /* stop the URB */ | ||
100 | usb_kill_urb(d->urb_list[i]); | ||
101 | } | ||
102 | d->urbs_submitted = 0; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | int dvb_usb_urb_submit(struct dvb_usb_device *d) | ||
107 | { | ||
108 | int i,ret; | ||
109 | for (i = 0; i < d->urbs_initialized; i++) { | ||
110 | deb_info("submitting URB no. %d\n",i); | ||
111 | if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) { | ||
112 | err("could not submit URB no. %d - get them all back\n",i); | ||
113 | dvb_usb_urb_kill(d); | ||
114 | return ret; | ||
115 | } | ||
116 | d->urbs_submitted++; | ||
117 | } | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d) | ||
122 | { | ||
123 | int i,bufsize = d->props.urb.count * d->props.urb.u.bulk.buffersize; | ||
124 | |||
125 | deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize); | ||
126 | /* allocate the actual buffer for the URBs */ | ||
127 | if ((d->buffer = usb_buffer_alloc(d->udev, bufsize, SLAB_ATOMIC, &d->dma_handle)) == NULL) { | ||
128 | deb_info("not enough memory for urb-buffer allocation.\n"); | ||
129 | return -ENOMEM; | ||
130 | } | ||
131 | deb_info("allocation successful\n"); | ||
132 | memset(d->buffer,0,bufsize); | ||
133 | |||
134 | d->state |= DVB_USB_STATE_URB_BUF; | ||
135 | |||
136 | /* allocate the URBs */ | ||
137 | for (i = 0; i < d->props.urb.count; i++) { | ||
138 | if (!(d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) { | ||
139 | return -ENOMEM; | ||
140 | } | ||
141 | |||
142 | usb_fill_bulk_urb( d->urb_list[i], d->udev, | ||
143 | usb_rcvbulkpipe(d->udev,d->props.urb.endpoint), | ||
144 | &d->buffer[i*d->props.urb.u.bulk.buffersize], | ||
145 | d->props.urb.u.bulk.buffersize, | ||
146 | dvb_usb_bulk_urb_complete, d); | ||
147 | |||
148 | d->urb_list[i]->transfer_flags = 0; | ||
149 | d->urbs_initialized++; | ||
150 | } | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | int dvb_usb_urb_init(struct dvb_usb_device *d) | ||
155 | { | ||
156 | /* | ||
157 | * when reloading the driver w/o replugging the device | ||
158 | * sometimes a timeout occures, this helps | ||
159 | */ | ||
160 | if (d->props.generic_bulk_ctrl_endpoint != 0) { | ||
161 | usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint)); | ||
162 | usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint)); | ||
163 | } | ||
164 | usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint)); | ||
165 | |||
166 | /* allocate the array for the data transfer URBs */ | ||
167 | d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL); | ||
168 | if (d->urb_list == NULL) | ||
169 | return -ENOMEM; | ||
170 | memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *)); | ||
171 | d->state |= DVB_USB_STATE_URB_LIST; | ||
172 | |||
173 | switch (d->props.urb.type) { | ||
174 | case DVB_USB_BULK: | ||
175 | return dvb_usb_bulk_urb_init(d); | ||
176 | case DVB_USB_ISOC: | ||
177 | err("isochronous transfer not yet implemented in dvb-usb."); | ||
178 | return -EINVAL; | ||
179 | default: | ||
180 | err("unkown URB-type for data transfer."); | ||
181 | return -EINVAL; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | int dvb_usb_urb_exit(struct dvb_usb_device *d) | ||
186 | { | ||
187 | int i; | ||
188 | |||
189 | dvb_usb_urb_kill(d); | ||
190 | |||
191 | if (d->state & DVB_USB_STATE_URB_LIST) { | ||
192 | for (i = 0; i < d->urbs_initialized; i++) { | ||
193 | if (d->urb_list[i] != NULL) { | ||
194 | deb_info("freeing URB no. %d.\n",i); | ||
195 | /* free the URBs */ | ||
196 | usb_free_urb(d->urb_list[i]); | ||
197 | } | ||
198 | } | ||
199 | d->urbs_initialized = 0; | ||
200 | /* free the urb array */ | ||
201 | kfree(d->urb_list); | ||
202 | d->state &= ~DVB_USB_STATE_URB_LIST; | ||
203 | } | ||
204 | |||
205 | if (d->state & DVB_USB_STATE_URB_BUF) | ||
206 | usb_buffer_free(d->udev, d->props.urb.u.bulk.buffersize * d->props.urb.count, | ||
207 | d->buffer, d->dma_handle); | ||
208 | |||
209 | d->state &= ~DVB_USB_STATE_URB_BUF; | ||
210 | return 0; | ||
211 | } | ||
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h new file mode 100644 index 000000000000..abcee1943f64 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h | |||
@@ -0,0 +1,315 @@ | |||
1 | /* dvb-usb.h is part of the DVB USB library. | ||
2 | * | ||
3 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
4 | * see dvb-usb-init.c for copyright information. | ||
5 | * | ||
6 | * the headerfile, all dvb-usb-drivers have to include. | ||
7 | */ | ||
8 | #ifndef __DVB_USB_H__ | ||
9 | #define __DVB_USB_H__ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/input.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/usb.h> | ||
15 | |||
16 | #include "dvb_frontend.h" | ||
17 | #include "dvb_demux.h" | ||
18 | #include "dvb_net.h" | ||
19 | #include "dmxdev.h" | ||
20 | |||
21 | #include "dvb-pll.h" | ||
22 | |||
23 | #include "dvb-usb-ids.h" | ||
24 | |||
25 | /* debug */ | ||
26 | #ifdef CONFIG_DVB_USB_DEBUG | ||
27 | #define dprintk(var,level,args...) \ | ||
28 | do { if ((var & level)) { printk(args); } } while (0) | ||
29 | |||
30 | #define debug_dump(b,l,func) {\ | ||
31 | int loop_; \ | ||
32 | for (loop_ = 0; loop_ < l; loop_++) func("%02x ", b[loop_]); \ | ||
33 | func("\n");\ | ||
34 | } | ||
35 | #define DVB_USB_DEBUG_STATUS | ||
36 | #else | ||
37 | #define dprintk(args...) | ||
38 | #define debug_dump(b,l,func) | ||
39 | |||
40 | #define DVB_USB_DEBUG_STATUS " (debugging is not enabled)" | ||
41 | |||
42 | #endif | ||
43 | |||
44 | /* generic log methods - taken from usb.h */ | ||
45 | #ifndef DVB_USB_LOG_PREFIX | ||
46 | #define DVB_USB_LOG_PREFIX "dvb-usb (please define a log prefix)" | ||
47 | #endif | ||
48 | |||
49 | #undef err | ||
50 | #define err(format, arg...) printk(KERN_ERR DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
51 | #undef info | ||
52 | #define info(format, arg...) printk(KERN_INFO DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
53 | #undef warn | ||
54 | #define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg) | ||
55 | |||
56 | /** | ||
57 | * struct dvb_usb_device_description - name and its according USB IDs | ||
58 | * @name: real name of the box, regardless which DVB USB device class is in use | ||
59 | * @cold_ids: array of struct usb_device_id which describe the device in | ||
60 | * pre-firmware state | ||
61 | * @warm_ids: array of struct usb_device_id which describe the device in | ||
62 | * post-firmware state | ||
63 | * | ||
64 | * Each DVB USB device class can have one or more actual devices, this struct | ||
65 | * assigns a name to it. | ||
66 | */ | ||
67 | struct dvb_usb_device_description { | ||
68 | const char *name; | ||
69 | |||
70 | #define DVB_USB_ID_MAX_NUM 15 | ||
71 | struct usb_device_id *cold_ids[DVB_USB_ID_MAX_NUM]; | ||
72 | struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM]; | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * struct dvb_usb_rc_key - a remote control key and its input-event | ||
77 | * @custom: the vendor/custom part of the key | ||
78 | * @data: the actual key part | ||
79 | * @event: the input event assigned to key identified by custom and data | ||
80 | */ | ||
81 | struct dvb_usb_rc_key { | ||
82 | u8 custom,data; | ||
83 | u32 event; | ||
84 | }; | ||
85 | |||
86 | struct dvb_usb_device; | ||
87 | |||
88 | /** | ||
89 | * struct dvb_usb_properties - properties of a dvb-usb-device | ||
90 | * @caps: capabilites of the DVB USB device. | ||
91 | * @pid_filter_count: number of PID filter position in the optional hardware | ||
92 | * PID-filter. | ||
93 | * | ||
94 | * @usb_ctrl: which USB device-side controller is in use. Needed for firmware | ||
95 | * download. | ||
96 | * @firmware: name of the firmware file. | ||
97 | * | ||
98 | * @size_of_priv: how many bytes shall be allocated for the private field | ||
99 | * of struct dvb_usb_device. | ||
100 | * | ||
101 | * @power_ctrl: called to enable/disable power of the device. | ||
102 | * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the | ||
103 | * device (not URB submitting/killing). | ||
104 | * @pid_filter_ctrl: called to en/disable the PID filter, if any. | ||
105 | * @pid_filter: called to set/unset a PID for filtering. | ||
106 | * | ||
107 | * @read_mac_address: called to read the MAC address of the device. | ||
108 | * | ||
109 | * @frontend_attach: called to attach the possible frontends (fill fe-field | ||
110 | * of struct dvb_usb_device). | ||
111 | * @tuner_attach: called to attach the correct tuner and to fill pll_addr, | ||
112 | * pll_desc and pll_init_buf of struct dvb_usb_device). | ||
113 | * @identify_state: called to determine the state (cold or warm), when it | ||
114 | * is not distinguishable by the USB IDs. | ||
115 | * | ||
116 | * @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable | ||
117 | * remote control handling). | ||
118 | * @rc_key_map_size: number of items in @rc_key_map. | ||
119 | * @rc_query: called to query an event event. | ||
120 | * @rc_interval: time in ms between two queries. | ||
121 | * | ||
122 | * @i2c_algo: i2c_algorithm if the device has I2CoverUSB. | ||
123 | * | ||
124 | * @generic_bulk_ctrl_endpoint: most of the DVB USB devices have a generic | ||
125 | * endpoint which received control messages with bulk transfers. When this | ||
126 | * is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write- | ||
127 | * helper functions. | ||
128 | * | ||
129 | * @urb: describes the kind of USB transfer used for MPEG2-TS-streaming. | ||
130 | * Currently only BULK is implemented | ||
131 | * | ||
132 | * @num_device_descs: number of struct dvb_usb_device_description in @devices | ||
133 | * @devices: array of struct dvb_usb_device_description compatibles with these | ||
134 | * properties. | ||
135 | */ | ||
136 | struct dvb_usb_properties { | ||
137 | |||
138 | #define DVB_USB_HAS_PID_FILTER 0x01 | ||
139 | #define DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF 0x02 | ||
140 | #define DVB_USB_NEED_PID_FILTERING 0x04 | ||
141 | #define DVB_USB_IS_AN_I2C_ADAPTER 0x08 | ||
142 | int caps; | ||
143 | int pid_filter_count; | ||
144 | |||
145 | #define CYPRESS_AN2135 0 | ||
146 | #define CYPRESS_AN2235 1 | ||
147 | #define CYPRESS_FX2 2 | ||
148 | int usb_ctrl; | ||
149 | const char *firmware; | ||
150 | |||
151 | int size_of_priv; | ||
152 | |||
153 | int (*power_ctrl) (struct dvb_usb_device *, int); | ||
154 | int (*streaming_ctrl) (struct dvb_usb_device *, int); | ||
155 | int (*pid_filter_ctrl) (struct dvb_usb_device *, int); | ||
156 | int (*pid_filter) (struct dvb_usb_device *, int, u16, int); | ||
157 | |||
158 | int (*read_mac_address) (struct dvb_usb_device *, u8 []); | ||
159 | int (*frontend_attach) (struct dvb_usb_device *); | ||
160 | int (*tuner_attach) (struct dvb_usb_device *); | ||
161 | |||
162 | int (*identify_state) (struct usb_device *, struct dvb_usb_properties *, | ||
163 | struct dvb_usb_device_description **, int *); | ||
164 | |||
165 | /* remote control properties */ | ||
166 | #define REMOTE_NO_KEY_PRESSED 0x00 | ||
167 | #define REMOTE_KEY_PRESSED 0x01 | ||
168 | #define REMOTE_KEY_REPEAT 0x02 | ||
169 | struct dvb_usb_rc_key *rc_key_map; | ||
170 | int rc_key_map_size; | ||
171 | int (*rc_query) (struct dvb_usb_device *, u32 *, int *); | ||
172 | int rc_interval; | ||
173 | |||
174 | struct i2c_algorithm *i2c_algo; | ||
175 | |||
176 | int generic_bulk_ctrl_endpoint; | ||
177 | |||
178 | struct { | ||
179 | #define DVB_USB_BULK 1 | ||
180 | #define DVB_USB_ISOC 2 | ||
181 | int type; | ||
182 | int count; | ||
183 | int endpoint; | ||
184 | |||
185 | union { | ||
186 | struct { | ||
187 | int buffersize; /* per URB */ | ||
188 | } bulk; | ||
189 | struct { | ||
190 | int framesperurb; | ||
191 | int framesize; | ||
192 | } isoc; | ||
193 | } u; | ||
194 | } urb; | ||
195 | |||
196 | int num_device_descs; | ||
197 | struct dvb_usb_device_description devices[8]; | ||
198 | }; | ||
199 | |||
200 | |||
201 | /** | ||
202 | * struct dvb_usb_device - object of a DVB USB device | ||
203 | * @props: copy of the struct dvb_usb_properties this device belongs to. | ||
204 | * @desc: pointer to the device's struct dvb_usb_device_description. | ||
205 | * @state: initialization and runtime state of the device. | ||
206 | * | ||
207 | * @udev: pointer to the device's struct usb_device. | ||
208 | * @urb_list: array of dynamically allocated struct urb for the MPEG2-TS- | ||
209 | * streaming. | ||
210 | * @buffer: buffer used to streaming. | ||
211 | * @dma_handle: dma_addr_t for buffer. | ||
212 | * @urbs_initialized: number of URBs initialized. | ||
213 | * @urbs_submitted: number of URBs submitted. | ||
214 | * @feedcount: number of reqested feeds (used for streaming-activation) | ||
215 | * @pid_filtering: is hardware pid_filtering used or not. | ||
216 | * @usb_sem: semaphore of USB control messages (reading needs two messages) | ||
217 | * @i2c_sem: semaphore for i2c-transfers | ||
218 | * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB | ||
219 | * @pll_addr: I2C address of the tuner for programming | ||
220 | * @pll_init: array containing the initialization buffer | ||
221 | * @pll_desc: pointer to the appropriate struct dvb_pll_desc | ||
222 | * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod | ||
223 | * @dvb_adap: device's dvb_adapter. | ||
224 | * @dmxdev: device's dmxdev. | ||
225 | * @demux: device's software demuxer. | ||
226 | * @dvb_net: device's dvb_net interfaces. | ||
227 | * @dvb_frontend: device's frontend. | ||
228 | * @max_feed_count: how many feeds can be handled simultaneously by this | ||
229 | * device | ||
230 | * @fe_sleep: rerouted frontend-sleep function. | ||
231 | * @fe_init: rerouted frontend-init (wakeup) function. | ||
232 | * @rc_input_dev: input device for the remote control. | ||
233 | * @rc_query_work: struct work_struct frequent rc queries | ||
234 | * @last_event: last triggered event | ||
235 | * @last_state: last state (no, pressed, repeat) | ||
236 | * @owner: owner of the dvb_adapter | ||
237 | * @priv: private data of the actual driver (allocate by dvb-usb, size defined | ||
238 | * in size_of_priv of dvb_usb_properties). | ||
239 | */ | ||
240 | struct dvb_usb_device { | ||
241 | struct dvb_usb_properties props; | ||
242 | struct dvb_usb_device_description *desc; | ||
243 | |||
244 | #define DVB_USB_STATE_INIT 0x000 | ||
245 | #define DVB_USB_STATE_URB_LIST 0x001 | ||
246 | #define DVB_USB_STATE_URB_BUF 0x002 | ||
247 | #define DVB_USB_STATE_DVB 0x004 | ||
248 | #define DVB_USB_STATE_I2C 0x008 | ||
249 | #define DVB_USB_STATE_REMOTE 0x010 | ||
250 | #define DVB_USB_STATE_URB_SUBMIT 0x020 | ||
251 | int state; | ||
252 | |||
253 | /* usb */ | ||
254 | struct usb_device *udev; | ||
255 | struct urb **urb_list; | ||
256 | u8 *buffer; | ||
257 | dma_addr_t dma_handle; | ||
258 | int urbs_initialized; | ||
259 | int urbs_submitted; | ||
260 | |||
261 | int feedcount; | ||
262 | int pid_filtering; | ||
263 | |||
264 | /* locking */ | ||
265 | struct semaphore usb_sem; | ||
266 | |||
267 | /* i2c */ | ||
268 | struct semaphore i2c_sem; | ||
269 | struct i2c_adapter i2c_adap; | ||
270 | |||
271 | /* tuner programming information */ | ||
272 | u8 pll_addr; | ||
273 | u8 pll_init[4]; | ||
274 | struct dvb_pll_desc *pll_desc; | ||
275 | int (*tuner_pass_ctrl)(struct dvb_frontend *, int, u8); | ||
276 | |||
277 | /* dvb */ | ||
278 | struct dvb_adapter dvb_adap; | ||
279 | struct dmxdev dmxdev; | ||
280 | struct dvb_demux demux; | ||
281 | struct dvb_net dvb_net; | ||
282 | struct dvb_frontend* fe; | ||
283 | int max_feed_count; | ||
284 | |||
285 | int (*fe_sleep) (struct dvb_frontend *); | ||
286 | int (*fe_init) (struct dvb_frontend *); | ||
287 | |||
288 | /* remote control */ | ||
289 | struct input_dev rc_input_dev; | ||
290 | struct work_struct rc_query_work; | ||
291 | u32 last_event; | ||
292 | int last_state; | ||
293 | |||
294 | struct module *owner; | ||
295 | |||
296 | void *priv; | ||
297 | }; | ||
298 | |||
299 | extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *); | ||
300 | extern void dvb_usb_device_exit(struct usb_interface *); | ||
301 | |||
302 | /* the generic read/write method for device control */ | ||
303 | extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int); | ||
304 | extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16); | ||
305 | |||
306 | /* commonly used remote control parsing */ | ||
307 | extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *); | ||
308 | |||
309 | /* commonly used pll init and set functions */ | ||
310 | extern int dvb_usb_pll_init_i2c(struct dvb_frontend *); | ||
311 | extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]); | ||
312 | extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *); | ||
313 | |||
314 | |||
315 | #endif | ||
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c new file mode 100644 index 000000000000..9d83781aef95 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2 | ||
2 | * DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include "dibusb.h" | ||
13 | |||
14 | static int debug; | ||
15 | module_param(debug, int, 0644); | ||
16 | MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS); | ||
17 | |||
18 | #define deb_rc(args...) dprintk(debug,0x01,args) | ||
19 | #define deb_ee(args...) dprintk(debug,0x02,args) | ||
20 | |||
21 | /* Hauppauge NOVA-T USB2 keys */ | ||
22 | static struct dvb_usb_rc_key haupp_rc_keys [] = { | ||
23 | { 0x1e, 0x00, KEY_0 }, | ||
24 | { 0x1e, 0x01, KEY_1 }, | ||
25 | { 0x1e, 0x02, KEY_2 }, | ||
26 | { 0x1e, 0x03, KEY_3 }, | ||
27 | { 0x1e, 0x04, KEY_4 }, | ||
28 | { 0x1e, 0x05, KEY_5 }, | ||
29 | { 0x1e, 0x06, KEY_6 }, | ||
30 | { 0x1e, 0x07, KEY_7 }, | ||
31 | { 0x1e, 0x08, KEY_8 }, | ||
32 | { 0x1e, 0x09, KEY_9 }, | ||
33 | { 0x1e, 0x0a, KEY_KPASTERISK }, | ||
34 | { 0x1e, 0x0b, KEY_RED }, | ||
35 | { 0x1e, 0x0c, KEY_RADIO }, | ||
36 | { 0x1e, 0x0d, KEY_MENU }, | ||
37 | { 0x1e, 0x0e, KEY_GRAVE }, /* # */ | ||
38 | { 0x1e, 0x0f, KEY_MUTE }, | ||
39 | { 0x1e, 0x10, KEY_VOLUMEUP }, | ||
40 | { 0x1e, 0x11, KEY_VOLUMEDOWN }, | ||
41 | { 0x1e, 0x12, KEY_CHANNEL }, | ||
42 | { 0x1e, 0x14, KEY_UP }, | ||
43 | { 0x1e, 0x15, KEY_DOWN }, | ||
44 | { 0x1e, 0x16, KEY_LEFT }, | ||
45 | { 0x1e, 0x17, KEY_RIGHT }, | ||
46 | { 0x1e, 0x18, KEY_VIDEO }, | ||
47 | { 0x1e, 0x19, KEY_AUDIO }, | ||
48 | { 0x1e, 0x1a, KEY_MEDIA }, | ||
49 | { 0x1e, 0x1b, KEY_EPG }, | ||
50 | { 0x1e, 0x1c, KEY_TV }, | ||
51 | { 0x1e, 0x1e, KEY_NEXT }, | ||
52 | { 0x1e, 0x1f, KEY_BACK }, | ||
53 | { 0x1e, 0x20, KEY_CHANNELUP }, | ||
54 | { 0x1e, 0x21, KEY_CHANNELDOWN }, | ||
55 | { 0x1e, 0x24, KEY_LAST }, /* Skip backwards */ | ||
56 | { 0x1e, 0x25, KEY_OK }, | ||
57 | { 0x1e, 0x29, KEY_BLUE}, | ||
58 | { 0x1e, 0x2e, KEY_GREEN }, | ||
59 | { 0x1e, 0x30, KEY_PAUSE }, | ||
60 | { 0x1e, 0x32, KEY_REWIND }, | ||
61 | { 0x1e, 0x34, KEY_FASTFORWARD }, | ||
62 | { 0x1e, 0x35, KEY_PLAY }, | ||
63 | { 0x1e, 0x36, KEY_STOP }, | ||
64 | { 0x1e, 0x37, KEY_RECORD }, | ||
65 | { 0x1e, 0x38, KEY_YELLOW }, | ||
66 | { 0x1e, 0x3b, KEY_GOTO }, | ||
67 | { 0x1e, 0x3d, KEY_POWER }, | ||
68 | }; | ||
69 | |||
70 | /* Firmware bug? sometimes, when a new key is pressed, the previous pressed key | ||
71 | * is delivered. No workaround yet, maybe a new firmware. | ||
72 | */ | ||
73 | static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state) | ||
74 | { | ||
75 | u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom; | ||
76 | u16 raw; | ||
77 | int i; | ||
78 | struct dibusb_state *st = d->priv; | ||
79 | |||
80 | dvb_usb_generic_rw(d,cmd,2,key,5,0); | ||
81 | |||
82 | *state = REMOTE_NO_KEY_PRESSED; | ||
83 | switch (key[0]) { | ||
84 | case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED: | ||
85 | raw = ((key[1] << 8) | key[2]) >> 3; | ||
86 | toggle = !!(raw & 0x800); | ||
87 | data = raw & 0x3f; | ||
88 | custom = (raw >> 6) & 0x1f; | ||
89 | |||
90 | deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); | ||
91 | |||
92 | for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) { | ||
93 | deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom); | ||
94 | if (haupp_rc_keys[i].data == data && | ||
95 | haupp_rc_keys[i].custom == custom) { | ||
96 | *event = haupp_rc_keys[i].event; | ||
97 | *state = REMOTE_KEY_PRESSED; | ||
98 | if (st->old_toggle == toggle) { | ||
99 | if (st->last_repeat_count++ < 2) | ||
100 | *state = REMOTE_NO_KEY_PRESSED; | ||
101 | } else { | ||
102 | st->last_repeat_count = 0; | ||
103 | st->old_toggle = toggle; | ||
104 | } | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | break; | ||
110 | case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY: | ||
111 | default: | ||
112 | break; | ||
113 | } | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6]) | ||
119 | { | ||
120 | int i; | ||
121 | u8 b; | ||
122 | |||
123 | mac[0] = 0x00; | ||
124 | mac[1] = 0x0d; | ||
125 | mac[2] = 0xfe; | ||
126 | |||
127 | /* this is a complete guess, but works for my box */ | ||
128 | for (i = 136; i < 139; i++) { | ||
129 | dibusb_read_eeprom_byte(d,i, &b); | ||
130 | |||
131 | mac[5 - (i - 136)] = b; | ||
132 | |||
133 | /* deb_ee("%02x ",b); | ||
134 | if ((i+1) % 16 == 0) | ||
135 | deb_ee("\n");*/ | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | /* USB Driver stuff */ | ||
142 | static struct dvb_usb_properties nova_t_properties; | ||
143 | |||
144 | static int nova_t_probe(struct usb_interface *intf, | ||
145 | const struct usb_device_id *id) | ||
146 | { | ||
147 | return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE); | ||
148 | } | ||
149 | |||
150 | /* do not change the order of the ID table */ | ||
151 | static struct usb_device_id nova_t_table [] = { | ||
152 | /* 00 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) }, | ||
153 | /* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) }, | ||
154 | { } /* Terminating entry */ | ||
155 | }; | ||
156 | MODULE_DEVICE_TABLE (usb, nova_t_table); | ||
157 | |||
158 | static struct dvb_usb_properties nova_t_properties = { | ||
159 | .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER, | ||
160 | .pid_filter_count = 32, | ||
161 | |||
162 | .usb_ctrl = CYPRESS_FX2, | ||
163 | .firmware = "dvb-usb-nova-t-usb2-01.fw", | ||
164 | |||
165 | .size_of_priv = sizeof(struct dibusb_state), | ||
166 | |||
167 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
168 | .pid_filter = dibusb_pid_filter, | ||
169 | .pid_filter_ctrl = dibusb_pid_filter_ctrl, | ||
170 | .power_ctrl = dibusb2_0_power_ctrl, | ||
171 | .frontend_attach = dibusb_dib3000mc_frontend_attach, | ||
172 | .tuner_attach = dibusb_dib3000mc_tuner_attach, | ||
173 | .read_mac_address = nova_t_read_mac_address, | ||
174 | |||
175 | .rc_interval = 100, | ||
176 | .rc_key_map = haupp_rc_keys, | ||
177 | .rc_key_map_size = ARRAY_SIZE(haupp_rc_keys), | ||
178 | .rc_query = nova_t_rc_query, | ||
179 | |||
180 | .i2c_algo = &dibusb_i2c_algo, | ||
181 | |||
182 | .generic_bulk_ctrl_endpoint = 0x01, | ||
183 | /* parameter for the MPEG2-data transfer */ | ||
184 | .urb = { | ||
185 | .type = DVB_USB_BULK, | ||
186 | .count = 7, | ||
187 | .endpoint = 0x06, | ||
188 | .u = { | ||
189 | .bulk = { | ||
190 | .buffersize = 4096, | ||
191 | } | ||
192 | } | ||
193 | }, | ||
194 | |||
195 | .num_device_descs = 1, | ||
196 | .devices = { | ||
197 | { "Hauppauge WinTV-NOVA-T usb2", | ||
198 | { &nova_t_table[0], NULL }, | ||
199 | { &nova_t_table[1], NULL }, | ||
200 | }, | ||
201 | } | ||
202 | }; | ||
203 | |||
204 | static struct usb_driver nova_t_driver = { | ||
205 | .owner = THIS_MODULE, | ||
206 | .name = "Hauppauge WinTV-NOVA-T usb2", | ||
207 | .probe = nova_t_probe, | ||
208 | .disconnect = dvb_usb_device_exit, | ||
209 | .id_table = nova_t_table, | ||
210 | }; | ||
211 | |||
212 | /* module stuff */ | ||
213 | static int __init nova_t_module_init(void) | ||
214 | { | ||
215 | int result; | ||
216 | if ((result = usb_register(&nova_t_driver))) { | ||
217 | err("usb_register failed. Error number %d",result); | ||
218 | return result; | ||
219 | } | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static void __exit nova_t_module_exit(void) | ||
225 | { | ||
226 | /* deregister this driver from the USB subsystem */ | ||
227 | usb_deregister(&nova_t_driver); | ||
228 | } | ||
229 | |||
230 | module_init (nova_t_module_init); | ||
231 | module_exit (nova_t_module_exit); | ||
232 | |||
233 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
234 | MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2"); | ||
235 | MODULE_VERSION("1.0"); | ||
236 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c new file mode 100644 index 000000000000..aa560422ce7c --- /dev/null +++ b/drivers/media/dvb/dvb-usb/umt-010.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0 | ||
2 | * DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | * see Documentation/dvb/README.dvb-usb for more information | ||
11 | */ | ||
12 | #include "dibusb.h" | ||
13 | |||
14 | #include "mt352.h" | ||
15 | |||
16 | static int umt_mt352_demod_init(struct dvb_frontend *fe) | ||
17 | { | ||
18 | static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d }; | ||
19 | static u8 mt352_reset[] = { 0x50, 0x80 }; | ||
20 | static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 }; | ||
21 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; | ||
22 | static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 }; | ||
23 | |||
24 | static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff }; | ||
25 | static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff }; | ||
26 | static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 }; | ||
27 | static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 }; | ||
28 | static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f }; | ||
29 | |||
30 | static u8 mt352_acq_ctl[] = { 0x53, 0x50 }; | ||
31 | static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 }; | ||
32 | |||
33 | mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); | ||
34 | udelay(2000); | ||
35 | mt352_write(fe, mt352_reset, sizeof(mt352_reset)); | ||
36 | mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio)); | ||
37 | |||
38 | mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); | ||
39 | mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); | ||
40 | |||
41 | mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1)); | ||
42 | mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2)); | ||
43 | mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3)); | ||
44 | mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4)); | ||
45 | mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5)); | ||
46 | |||
47 | mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl)); | ||
48 | mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1)); | ||
49 | |||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static int umt_mt352_frontend_attach(struct dvb_usb_device *d) | ||
54 | { | ||
55 | struct mt352_config umt_config; | ||
56 | |||
57 | memset(&umt_config,0,sizeof(struct mt352_config)); | ||
58 | umt_config.demod_init = umt_mt352_demod_init; | ||
59 | umt_config.demod_address = 0xf; | ||
60 | umt_config.pll_set = dvb_usb_pll_set; | ||
61 | |||
62 | d->fe = mt352_attach(&umt_config, &d->i2c_adap); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int umt_tuner_attach (struct dvb_usb_device *d) | ||
68 | { | ||
69 | d->pll_addr = 0x61; | ||
70 | d->pll_desc = &dvb_pll_tua6034; | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | /* USB Driver stuff */ | ||
75 | static struct dvb_usb_properties umt_properties; | ||
76 | |||
77 | static int umt_probe(struct usb_interface *intf, | ||
78 | const struct usb_device_id *id) | ||
79 | { | ||
80 | if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0) | ||
81 | return 0; | ||
82 | return -EINVAL; | ||
83 | } | ||
84 | |||
85 | /* do not change the order of the ID table */ | ||
86 | static struct usb_device_id umt_table [] = { | ||
87 | /* 00 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) }, | ||
88 | /* 01 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) }, | ||
89 | { } /* Terminating entry */ | ||
90 | }; | ||
91 | MODULE_DEVICE_TABLE (usb, umt_table); | ||
92 | |||
93 | static struct dvb_usb_properties umt_properties = { | ||
94 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
95 | |||
96 | .usb_ctrl = CYPRESS_FX2, | ||
97 | .firmware = "dvb-usb-umt-010-02.fw", | ||
98 | |||
99 | .size_of_priv = sizeof(struct dibusb_state), | ||
100 | |||
101 | .streaming_ctrl = dibusb2_0_streaming_ctrl, | ||
102 | .power_ctrl = dibusb_power_ctrl, | ||
103 | .frontend_attach = umt_mt352_frontend_attach, | ||
104 | .tuner_attach = umt_tuner_attach, | ||
105 | |||
106 | .i2c_algo = &dibusb_i2c_algo, | ||
107 | |||
108 | .generic_bulk_ctrl_endpoint = 0x01, | ||
109 | /* parameter for the MPEG2-data transfer */ | ||
110 | .urb = { | ||
111 | .type = DVB_USB_BULK, | ||
112 | .count = 20, | ||
113 | .endpoint = 0x06, | ||
114 | .u = { | ||
115 | .bulk = { | ||
116 | .buffersize = 512, | ||
117 | } | ||
118 | } | ||
119 | }, | ||
120 | |||
121 | .num_device_descs = 1, | ||
122 | .devices = { | ||
123 | { "Hanftek UMT-010 DVB-T USB2.0", | ||
124 | { &umt_table[0], NULL }, | ||
125 | { &umt_table[1], NULL }, | ||
126 | }, | ||
127 | } | ||
128 | }; | ||
129 | |||
130 | static struct usb_driver umt_driver = { | ||
131 | .owner = THIS_MODULE, | ||
132 | .name = "HanfTek UMT-010 USB2.0 DVB-T devices", | ||
133 | .probe = umt_probe, | ||
134 | .disconnect = dvb_usb_device_exit, | ||
135 | .id_table = umt_table, | ||
136 | }; | ||
137 | |||
138 | /* module stuff */ | ||
139 | static int __init umt_module_init(void) | ||
140 | { | ||
141 | int result; | ||
142 | if ((result = usb_register(&umt_driver))) { | ||
143 | err("usb_register failed. Error number %d",result); | ||
144 | return result; | ||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static void __exit umt_module_exit(void) | ||
151 | { | ||
152 | /* deregister this driver from the USB subsystem */ | ||
153 | usb_deregister(&umt_driver); | ||
154 | } | ||
155 | |||
156 | module_init (umt_module_init); | ||
157 | module_exit (umt_module_exit); | ||
158 | |||
159 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
160 | MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device"); | ||
161 | MODULE_VERSION("1.0"); | ||
162 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c new file mode 100644 index 000000000000..2746edfeccba --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0 | ||
2 | * DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * Thanks to Twinhan who kindly provided hardware and information. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation, version 2. | ||
11 | * | ||
12 | * see Documentation/dvb/README.dvb-usb for more information | ||
13 | * | ||
14 | */ | ||
15 | #include "vp7045.h" | ||
16 | |||
17 | /* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT | ||
18 | * | ||
19 | * Programming is hidden inside the firmware, so set_frontend is very easy. | ||
20 | * Even though there is a Firmware command that one can use to access the demod | ||
21 | * via its registers. This is used for status information. | ||
22 | */ | ||
23 | |||
24 | struct vp7045_fe_state { | ||
25 | struct dvb_frontend fe; | ||
26 | struct dvb_usb_device *d; | ||
27 | }; | ||
28 | |||
29 | |||
30 | static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) | ||
31 | { | ||
32 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
33 | u8 s0 = vp7045_read_reg(state->d,0x00), | ||
34 | s1 = vp7045_read_reg(state->d,0x01), | ||
35 | s3 = vp7045_read_reg(state->d,0x03); | ||
36 | |||
37 | *status = 0; | ||
38 | if (s0 & (1 << 4)) | ||
39 | *status |= FE_HAS_CARRIER; | ||
40 | if (s0 & (1 << 1)) | ||
41 | *status |= FE_HAS_VITERBI; | ||
42 | if (s0 & (1 << 5)) | ||
43 | *status |= FE_HAS_LOCK; | ||
44 | if (s1 & (1 << 1)) | ||
45 | *status |= FE_HAS_SYNC; | ||
46 | if (s3 & (1 << 6)) | ||
47 | *status |= FE_HAS_SIGNAL; | ||
48 | |||
49 | if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != | ||
50 | (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) | ||
51 | *status &= ~FE_HAS_LOCK; | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber) | ||
57 | { | ||
58 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
59 | *ber = (vp7045_read_reg(state->d, 0x0D) << 16) | | ||
60 | (vp7045_read_reg(state->d, 0x0E) << 8) | | ||
61 | vp7045_read_reg(state->d, 0x0F); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) | ||
66 | { | ||
67 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
68 | *unc = (vp7045_read_reg(state->d, 0x10) << 8) | | ||
69 | vp7045_read_reg(state->d, 0x11); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) | ||
74 | { | ||
75 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
76 | u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) | | ||
77 | vp7045_read_reg(state->d, 0x15); | ||
78 | |||
79 | *strength = ~signal; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr) | ||
84 | { | ||
85 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
86 | u8 _snr = vp7045_read_reg(state->d, 0x09); | ||
87 | *snr = (_snr << 8) | _snr; | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int vp7045_fe_init(struct dvb_frontend* fe) | ||
92 | { | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int vp7045_fe_sleep(struct dvb_frontend* fe) | ||
97 | { | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) | ||
102 | { | ||
103 | tune->min_delay_ms = 800; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static int vp7045_fe_set_frontend(struct dvb_frontend* fe, | ||
108 | struct dvb_frontend_parameters *fep) | ||
109 | { | ||
110 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
111 | u8 buf[5]; | ||
112 | u32 freq = fep->frequency / 1000; | ||
113 | |||
114 | buf[0] = (freq >> 16) & 0xff; | ||
115 | buf[1] = (freq >> 8) & 0xff; | ||
116 | buf[2] = freq & 0xff; | ||
117 | buf[3] = 0; | ||
118 | |||
119 | switch (fep->u.ofdm.bandwidth) { | ||
120 | case BANDWIDTH_8_MHZ: buf[4] = 8; break; | ||
121 | case BANDWIDTH_7_MHZ: buf[4] = 7; break; | ||
122 | case BANDWIDTH_6_MHZ: buf[4] = 6; break; | ||
123 | case BANDWIDTH_AUTO: return -EOPNOTSUPP; | ||
124 | default: | ||
125 | return -EINVAL; | ||
126 | } | ||
127 | |||
128 | vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int vp7045_fe_get_frontend(struct dvb_frontend* fe, | ||
133 | struct dvb_frontend_parameters *fep) | ||
134 | { | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static void vp7045_fe_release(struct dvb_frontend* fe) | ||
139 | { | ||
140 | struct vp7045_fe_state *state = fe->demodulator_priv; | ||
141 | kfree(state); | ||
142 | } | ||
143 | |||
144 | static struct dvb_frontend_ops vp7045_fe_ops; | ||
145 | |||
146 | struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d) | ||
147 | { | ||
148 | struct vp7045_fe_state *s = kmalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL); | ||
149 | if (s == NULL) | ||
150 | goto error; | ||
151 | memset(s,0,sizeof(struct vp7045_fe_state)); | ||
152 | |||
153 | s->d = d; | ||
154 | s->fe.ops = &vp7045_fe_ops; | ||
155 | s->fe.demodulator_priv = s; | ||
156 | |||
157 | goto success; | ||
158 | error: | ||
159 | return NULL; | ||
160 | success: | ||
161 | return &s->fe; | ||
162 | } | ||
163 | |||
164 | |||
165 | static struct dvb_frontend_ops vp7045_fe_ops = { | ||
166 | .info = { | ||
167 | .name = "Twinhan VP7045/46 USB DVB-T", | ||
168 | .type = FE_OFDM, | ||
169 | .frequency_min = 44250000, | ||
170 | .frequency_max = 867250000, | ||
171 | .frequency_stepsize = 1000, | ||
172 | .caps = FE_CAN_INVERSION_AUTO | | ||
173 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
174 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
175 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | | ||
176 | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
177 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
178 | FE_CAN_RECOVER | | ||
179 | FE_CAN_HIERARCHY_AUTO, | ||
180 | }, | ||
181 | |||
182 | .release = vp7045_fe_release, | ||
183 | |||
184 | .init = vp7045_fe_init, | ||
185 | .sleep = vp7045_fe_sleep, | ||
186 | |||
187 | .set_frontend = vp7045_fe_set_frontend, | ||
188 | .get_frontend = vp7045_fe_get_frontend, | ||
189 | .get_tune_settings = vp7045_fe_get_tune_settings, | ||
190 | |||
191 | .read_status = vp7045_fe_read_status, | ||
192 | .read_ber = vp7045_fe_read_ber, | ||
193 | .read_signal_strength = vp7045_fe_read_signal_strength, | ||
194 | .read_snr = vp7045_fe_read_snr, | ||
195 | .read_ucblocks = vp7045_fe_read_unc_blocks, | ||
196 | }; | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c new file mode 100644 index 000000000000..02ecc9a8e3b6 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045.c | |||
@@ -0,0 +1,263 @@ | |||
1 | /* DVB USB compliant Linux driver for the | ||
2 | * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver | ||
3 | * - DigitalNow TinyUSB2 DVB-t receiver | ||
4 | * | ||
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
6 | * | ||
7 | * Thanks to Twinhan who kindly provided hardware and information. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation, version 2. | ||
12 | * | ||
13 | * see Documentation/dvb/README.dvb-usb for more information | ||
14 | */ | ||
15 | #include "vp7045.h" | ||
16 | |||
17 | /* debug */ | ||
18 | int dvb_usb_vp7045_debug; | ||
19 | module_param_named(debug,dvb_usb_vp7045_debug, int, 0644); | ||
20 | MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); | ||
21 | |||
22 | int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec) | ||
23 | { | ||
24 | int ret = 0; | ||
25 | u8 inbuf[12] = { 0 }, outbuf[20] = { 0 }; | ||
26 | |||
27 | outbuf[0] = cmd; | ||
28 | |||
29 | if (outlen > 19) | ||
30 | outlen = 19; | ||
31 | |||
32 | if (inlen > 11) | ||
33 | inlen = 11; | ||
34 | |||
35 | if (out != NULL && outlen > 0) | ||
36 | memcpy(&outbuf[1], out, outlen); | ||
37 | |||
38 | deb_xfer("out buffer: "); | ||
39 | debug_dump(outbuf,outlen+1,deb_xfer); | ||
40 | |||
41 | if ((ret = down_interruptible(&d->usb_sem))) | ||
42 | return ret; | ||
43 | |||
44 | if (usb_control_msg(d->udev, | ||
45 | usb_sndctrlpipe(d->udev,0), | ||
46 | TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, | ||
47 | outbuf, 20, 2*HZ) != 20) { | ||
48 | err("USB control message 'out' went wrong."); | ||
49 | ret = -EIO; | ||
50 | goto unlock; | ||
51 | } | ||
52 | |||
53 | msleep(msec); | ||
54 | |||
55 | if (usb_control_msg(d->udev, | ||
56 | usb_rcvctrlpipe(d->udev,0), | ||
57 | TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, | ||
58 | inbuf, 12, 2*HZ) != 12) { | ||
59 | err("USB control message 'in' went wrong."); | ||
60 | ret = -EIO; | ||
61 | goto unlock; | ||
62 | } | ||
63 | |||
64 | deb_xfer("in buffer: "); | ||
65 | debug_dump(inbuf,12,deb_xfer); | ||
66 | |||
67 | if (in != NULL && inlen > 0) | ||
68 | memcpy(in,&inbuf[1],inlen); | ||
69 | |||
70 | unlock: | ||
71 | up(&d->usb_sem); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg) | ||
77 | { | ||
78 | u8 obuf[2] = { 0 },v; | ||
79 | obuf[1] = reg; | ||
80 | |||
81 | vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30); | ||
82 | |||
83 | return v; | ||
84 | } | ||
85 | |||
86 | static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff) | ||
87 | { | ||
88 | u8 v = onoff; | ||
89 | return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150); | ||
90 | } | ||
91 | |||
92 | /* remote control stuff */ | ||
93 | |||
94 | /* The keymapping struct. Somehow this should be loaded to the driver, but | ||
95 | * currently it is hardcoded. */ | ||
96 | static struct dvb_usb_rc_key vp7045_rc_keys[] = { | ||
97 | /* insert the keys like this. to make the raw keys visible, enable | ||
98 | * debug=0x04 when loading dvb-usb-vp7045. */ | ||
99 | |||
100 | /* these keys are probably wrong. I don't have a working IR-receiver on my | ||
101 | * vp7045, so I can't test it. Patches are welcome. */ | ||
102 | { 0x00, 0x01, KEY_1 }, | ||
103 | { 0x00, 0x02, KEY_2 }, | ||
104 | }; | ||
105 | |||
106 | static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state) | ||
107 | { | ||
108 | u8 key; | ||
109 | int i; | ||
110 | vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20); | ||
111 | |||
112 | deb_rc("remote query key: %x %d\n",key,key); | ||
113 | |||
114 | if (key == 0x44) { | ||
115 | *state = REMOTE_NO_KEY_PRESSED; | ||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++) | ||
120 | if (vp7045_rc_keys[i].data == key) { | ||
121 | *state = REMOTE_KEY_PRESSED; | ||
122 | *key_buf = vp7045_rc_keys[i].event; | ||
123 | break; | ||
124 | } | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset) | ||
129 | { | ||
130 | int i = 0; | ||
131 | u8 v,br[2]; | ||
132 | for (i=0; i < len; i++) { | ||
133 | v = offset + i; | ||
134 | vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5); | ||
135 | buf[i] = br[1]; | ||
136 | } | ||
137 | deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i); | ||
138 | debug_dump(buf,i,deb_info); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | |||
143 | static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6]) | ||
144 | { | ||
145 | return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR); | ||
146 | } | ||
147 | |||
148 | static int vp7045_frontend_attach(struct dvb_usb_device *d) | ||
149 | { | ||
150 | u8 buf[255] = { 0 }; | ||
151 | |||
152 | vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0); | ||
153 | buf[10] = '\0'; | ||
154 | deb_info("firmware says: %s ",buf); | ||
155 | |||
156 | vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0); | ||
157 | buf[10] = '\0'; | ||
158 | deb_info("%s ",buf); | ||
159 | |||
160 | vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0); | ||
161 | buf[10] = '\0'; | ||
162 | deb_info("v%s\n",buf); | ||
163 | |||
164 | /* Dump the EEPROM */ | ||
165 | /* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */ | ||
166 | |||
167 | d->fe = vp7045_fe_attach(d); | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static struct dvb_usb_properties vp7045_properties; | ||
173 | |||
174 | static int vp7045_usb_probe(struct usb_interface *intf, | ||
175 | const struct usb_device_id *id) | ||
176 | { | ||
177 | return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE); | ||
178 | } | ||
179 | |||
180 | static struct usb_device_id vp7045_usb_table [] = { | ||
181 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) }, | ||
182 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) }, | ||
183 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) }, | ||
184 | { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) }, | ||
185 | { 0 }, | ||
186 | }; | ||
187 | MODULE_DEVICE_TABLE(usb, vp7045_usb_table); | ||
188 | |||
189 | static struct dvb_usb_properties vp7045_properties = { | ||
190 | .caps = 0, | ||
191 | |||
192 | .usb_ctrl = CYPRESS_FX2, | ||
193 | .firmware = "dvb-usb-vp7045-01.fw", | ||
194 | |||
195 | .power_ctrl = vp7045_power_ctrl, | ||
196 | .frontend_attach = vp7045_frontend_attach, | ||
197 | .read_mac_address = vp7045_read_mac_addr, | ||
198 | |||
199 | .rc_interval = 400, | ||
200 | .rc_key_map = vp7045_rc_keys, | ||
201 | .rc_key_map_size = ARRAY_SIZE(vp7045_rc_keys), | ||
202 | .rc_query = vp7045_rc_query, | ||
203 | |||
204 | /* parameter for the MPEG2-data transfer */ | ||
205 | .urb = { | ||
206 | .type = DVB_USB_BULK, | ||
207 | .count = 7, | ||
208 | .endpoint = 0x02, | ||
209 | .u = { | ||
210 | .bulk = { | ||
211 | .buffersize = 4096, | ||
212 | } | ||
213 | } | ||
214 | }, | ||
215 | |||
216 | .num_device_descs = 2, | ||
217 | .devices = { | ||
218 | { .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)", | ||
219 | .cold_ids = { &vp7045_usb_table[0], NULL }, | ||
220 | .warm_ids = { &vp7045_usb_table[1], NULL }, | ||
221 | }, | ||
222 | { .name = "DigitalNow TinyUSB 2 DVB-t Receiver", | ||
223 | .cold_ids = { &vp7045_usb_table[2], NULL }, | ||
224 | .warm_ids = { &vp7045_usb_table[3], NULL }, | ||
225 | }, | ||
226 | { 0 }, | ||
227 | } | ||
228 | }; | ||
229 | |||
230 | /* usb specific object needed to register this driver with the usb subsystem */ | ||
231 | static struct usb_driver vp7045_usb_driver = { | ||
232 | .owner = THIS_MODULE, | ||
233 | .name = "dvb-usb-vp7045", | ||
234 | .probe = vp7045_usb_probe, | ||
235 | .disconnect = dvb_usb_device_exit, | ||
236 | .id_table = vp7045_usb_table, | ||
237 | }; | ||
238 | |||
239 | /* module stuff */ | ||
240 | static int __init vp7045_usb_module_init(void) | ||
241 | { | ||
242 | int result; | ||
243 | if ((result = usb_register(&vp7045_usb_driver))) { | ||
244 | err("usb_register failed. (%d)",result); | ||
245 | return result; | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static void __exit vp7045_usb_module_exit(void) | ||
252 | { | ||
253 | /* deregister this driver from the USB subsystem */ | ||
254 | usb_deregister(&vp7045_usb_driver); | ||
255 | } | ||
256 | |||
257 | module_init(vp7045_usb_module_init); | ||
258 | module_exit(vp7045_usb_module_exit); | ||
259 | |||
260 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>"); | ||
261 | MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0"); | ||
262 | MODULE_VERSION("1.0"); | ||
263 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/dvb/dvb-usb/vp7045.h new file mode 100644 index 000000000000..9ce21a20fa86 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/vp7045.h | |||
@@ -0,0 +1,78 @@ | |||
1 | /* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII | ||
2 | * USB2.0 DVB-T receiver. | ||
3 | * | ||
4 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) | ||
5 | * | ||
6 | * Thanks to Twinhan who kindly provided hardware and information. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation, version 2. | ||
11 | * | ||
12 | * see Documentation/dvb/README.dvb-usb for more information | ||
13 | */ | ||
14 | #ifndef _DVB_USB_VP7045_H_ | ||
15 | #define _DVB_USB_VP7045_H_ | ||
16 | |||
17 | #define DVB_USB_LOG_PREFIX "vp7045" | ||
18 | #include "dvb-usb.h" | ||
19 | |||
20 | extern int dvb_usb_vp7045_debug; | ||
21 | #define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args) | ||
22 | #define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args) | ||
23 | #define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args) | ||
24 | |||
25 | /* vp7045 commands */ | ||
26 | |||
27 | /* Twinhan Vendor requests */ | ||
28 | #define TH_COMMAND_IN 0xC0 | ||
29 | #define TH_COMMAND_OUT 0xC1 | ||
30 | |||
31 | /* command bytes */ | ||
32 | #define TUNER_REG_READ 0x03 | ||
33 | #define TUNER_REG_WRITE 0x04 | ||
34 | |||
35 | #define RC_VAL_READ 0x05 | ||
36 | #define RC_NO_KEY 0x44 | ||
37 | |||
38 | #define SET_TUNER_POWER 0x06 | ||
39 | #define CHECK_TUNER_POWER 0x12 | ||
40 | #define Tuner_Power_ON 1 | ||
41 | #define Tuner_Power_OFF 0 | ||
42 | |||
43 | #define GET_USB_SPEED 0x07 | ||
44 | #define USB_SPEED_LOW 0 | ||
45 | #define USB_SPEED_FULL 1 | ||
46 | #define USB_SPEED_HIGH 2 | ||
47 | |||
48 | #define LOCK_TUNER_COMMAND 0x09 | ||
49 | |||
50 | #define TUNER_SIGNAL_READ 0x0A | ||
51 | |||
52 | /* FX2 eeprom */ | ||
53 | #define SET_EE_VALUE 0x10 | ||
54 | #define GET_EE_VALUE 0x11 | ||
55 | #define FX2_ID_ADDR 0x00 | ||
56 | #define VID_MSB_ADDR 0x02 | ||
57 | #define VID_LSB_ADDR 0x01 | ||
58 | #define PID_MSB_ADDR 0x04 | ||
59 | #define PID_LSB_ADDR 0x03 | ||
60 | #define MAC_0_ADDR 0x07 | ||
61 | #define MAC_1_ADDR 0x08 | ||
62 | #define MAC_2_ADDR 0x09 | ||
63 | #define MAC_3_ADDR 0x0a | ||
64 | #define MAC_4_ADDR 0x0b | ||
65 | #define MAC_5_ADDR 0x0c | ||
66 | |||
67 | #define RESET_FX2 0x13 | ||
68 | |||
69 | #define FW_VERSION_READ 0x0B | ||
70 | #define VENDOR_STRING_READ 0x0C | ||
71 | #define PRODUCT_STRING_READ 0x0D | ||
72 | #define FW_BCD_VERSION_READ 0x14 | ||
73 | |||
74 | extern struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d); | ||
75 | extern int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen,int msec); | ||
76 | extern u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg); | ||
77 | |||
78 | #endif | ||