Commit | Line | Data |
---|---|---|
776338e1 JS |
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"); | |
8126fdbc | 26 | dvb_usb_urb_kill(d); |
776338e1 JS |
27 | |
28 | if (d->props.streaming_ctrl != NULL) | |
29 | if ((ret = d->props.streaming_ctrl(d,0))) | |
30 | err("error while stopping stream."); | |
31 | ||
776338e1 JS |
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) { | |
8126fdbc PB |
47 | deb_ts("submitting all URBs\n"); |
48 | dvb_usb_urb_submit(d); | |
776338e1 JS |
49 | |
50 | deb_ts("controlling pid parser\n"); | |
51 | if (d->props.caps & DVB_USB_HAS_PID_FILTER && | |
52 | d->props.caps & DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF && | |
53 | d->props.pid_filter_ctrl != NULL) | |
54 | if (d->props.pid_filter_ctrl(d,d->pid_filtering) < 0) | |
55 | err("could not handle pid_parser"); | |
56 | ||
57 | deb_ts("start feeding\n"); | |
58 | if (d->props.streaming_ctrl != NULL) | |
59 | if (d->props.streaming_ctrl(d,1)) { | |
60 | err("error while enabling fifo."); | |
61 | return -ENODEV; | |
62 | } | |
63 | ||
776338e1 JS |
64 | } |
65 | return 0; | |
66 | } | |
67 | ||
68 | static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed) | |
69 | { | |
70 | deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type); | |
71 | return dvb_usb_ctrl_feed(dvbdmxfeed,1); | |
72 | } | |
73 | ||
74 | static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) | |
75 | { | |
76 | deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type); | |
77 | return dvb_usb_ctrl_feed(dvbdmxfeed,0); | |
78 | } | |
79 | ||
80 | int dvb_usb_dvb_init(struct dvb_usb_device *d) | |
81 | { | |
82 | int ret; | |
83 | ||
84 | if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name, | |
d09dbf92 | 85 | d->owner, &d->udev->dev)) < 0) { |
776338e1 JS |
86 | deb_info("dvb_register_adapter failed: error %d", ret); |
87 | goto err; | |
88 | } | |
89 | d->dvb_adap.priv = d; | |
90 | ||
91 | if (d->props.read_mac_address) { | |
92 | if (d->props.read_mac_address(d,d->dvb_adap.proposed_mac) == 0) | |
93 | info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",d->dvb_adap.proposed_mac[0], | |
94 | d->dvb_adap.proposed_mac[1],d->dvb_adap.proposed_mac[2], | |
95 | d->dvb_adap.proposed_mac[3],d->dvb_adap.proposed_mac[4], | |
96 | d->dvb_adap.proposed_mac[5]); | |
97 | else | |
98 | err("MAC address reading failed."); | |
99 | } | |
100 | ||
101 | ||
102 | d->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING; | |
103 | d->demux.priv = d; | |
104 | ||
105 | d->demux.feednum = d->demux.filternum = d->max_feed_count; | |
106 | d->demux.start_feed = dvb_usb_start_feed; | |
107 | d->demux.stop_feed = dvb_usb_stop_feed; | |
108 | d->demux.write_to_decoder = NULL; | |
109 | if ((ret = dvb_dmx_init(&d->demux)) < 0) { | |
110 | err("dvb_dmx_init failed: error %d",ret); | |
111 | goto err_dmx; | |
112 | } | |
113 | ||
114 | d->dmxdev.filternum = d->demux.filternum; | |
115 | d->dmxdev.demux = &d->demux.dmx; | |
116 | d->dmxdev.capabilities = 0; | |
117 | if ((ret = dvb_dmxdev_init(&d->dmxdev, &d->dvb_adap)) < 0) { | |
118 | err("dvb_dmxdev_init failed: error %d",ret); | |
119 | goto err_dmx_dev; | |
120 | } | |
121 | ||
122 | dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx); | |
123 | ||
8397703e TP |
124 | d->state |= DVB_USB_STATE_DVB; |
125 | return 0; | |
126 | ||
776338e1 JS |
127 | err_dmx_dev: |
128 | dvb_dmx_release(&d->demux); | |
129 | err_dmx: | |
130 | dvb_unregister_adapter(&d->dvb_adap); | |
131 | err: | |
132 | return ret; | |
776338e1 JS |
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) { | |
8df3d460 | 178 | err("strange '%s' doesn't want to attach a frontend.",d->desc->name); |
776338e1 JS |
179 | return 0; |
180 | } | |
181 | ||
182 | d->props.frontend_attach(d); | |
183 | ||
184 | /* re-assign sleep and wakeup functions */ | |
185 | if (d->fe != NULL) { | |
dea74869 PB |
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; | |
776338e1 JS |
188 | |
189 | if (dvb_register_frontend(&d->dvb_adap, d->fe)) { | |
190 | err("Frontend registration failed."); | |
dea74869 PB |
191 | if (d->fe->ops.release) |
192 | d->fe->ops.release(d->fe); | |
776338e1 JS |
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 | } |