blob: 536210b39428c98ce1f8385b48ab1a13ba2cf7d2 [file] [log] [blame]
Mike Iselyd8554972006-06-26 20:58:46 -03001/*
2 *
Mike Iselyd8554972006-06-26 20:58:46 -03003 *
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Mauro Carvalho Chehabce4260c2006-06-26 22:26:08 -030024#include <linux/version.h>
Mike Iselyd8554972006-06-26 20:58:46 -030025#include "pvrusb2-context.h"
26#include "pvrusb2-hdw.h"
27#include "pvrusb2.h"
28#include "pvrusb2-debug.h"
29#include "pvrusb2-v4l2.h"
30#include "pvrusb2-ioread.h"
31#include <linux/videodev2.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040032#include <linux/module.h>
Mike Isely43e06022006-09-23 23:47:50 -030033#include <media/v4l2-dev.h>
Hans Verkuila28fbd02013-06-10 09:16:25 -030034#include <media/v4l2-device.h>
Mike Iselyd8554972006-06-26 20:58:46 -030035#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030036#include <media/v4l2-ioctl.h>
Mike Iselyd8554972006-06-26 20:58:46 -030037
38struct pvr2_v4l2_dev;
39struct pvr2_v4l2_fh;
40struct pvr2_v4l2;
41
Mike Iselyd8554972006-06-26 20:58:46 -030042struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030043 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030044 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030045 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030046 /* Information about this device: */
47 enum pvr2_config config; /* Expected stream format */
48 int v4l_type; /* V4L defined type for this device node */
49 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030050};
51
52struct pvr2_v4l2_fh {
53 struct pvr2_channel channel;
Joe Perches108bdd72010-04-05 16:05:39 -030054 struct pvr2_v4l2_dev *pdi;
Mike Iselyd8554972006-06-26 20:58:46 -030055 enum v4l2_priority prio;
56 struct pvr2_ioread *rhp;
57 struct file *file;
58 struct pvr2_v4l2 *vhead;
59 struct pvr2_v4l2_fh *vnext;
60 struct pvr2_v4l2_fh *vprev;
61 wait_queue_head_t wait_data;
62 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030063 /* Map contiguous ordinal value to input id */
64 unsigned char *input_map;
65 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030066};
67
68struct pvr2_v4l2 {
69 struct pvr2_channel channel;
70 struct pvr2_v4l2_fh *vfirst;
71 struct pvr2_v4l2_fh *vlast;
72
73 struct v4l2_prio_state prio;
74
Mike Isely0f0f257b2006-12-27 23:19:42 -030075 /* streams - Note that these must be separately, individually,
76 * allocated pointers. This is because the v4l core is going to
77 * manage their deletion - separately, individually... */
78 struct pvr2_v4l2_dev *dev_video;
79 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030080};
81
82static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
83module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030084MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
85static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
86module_param_array(radio_nr, int, NULL, 0444);
87MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
88static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
89module_param_array(vbi_nr, int, NULL, 0444);
90MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030091
Adrian Bunk07e337e2006-06-30 11:30:20 -030092static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -030093 {
94 .index = 0,
95 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
96 .flags = V4L2_FMT_FLAG_COMPRESSED,
97 .description = "MPEG1/2",
98 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
99 // breaks when I do that.
100 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
Mike Iselyd8554972006-06-26 20:58:46 -0300101 }
102};
103
104#define PVR_FORMAT_PIX 0
105#define PVR_FORMAT_VBI 1
106
Adrian Bunk07e337e2006-06-30 11:30:20 -0300107static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300108 [PVR_FORMAT_PIX] = {
109 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
110 .fmt = {
111 .pix = {
112 .width = 720,
113 .height = 576,
114 // This should really be V4L2_PIX_FMT_MPEG,
115 // but xawtv breaks when I do that.
116 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
117 .field = V4L2_FIELD_INTERLACED,
118 .bytesperline = 0, // doesn't make sense
119 // here
120 //FIXME : Don't know what to put here...
121 .sizeimage = (32*1024),
122 .colorspace = 0, // doesn't make sense here
123 .priv = 0
124 }
125 }
126 },
127 [PVR_FORMAT_VBI] = {
128 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
129 .fmt = {
130 .vbi = {
131 .sampling_rate = 27000000,
132 .offset = 248,
133 .samples_per_line = 1443,
134 .sample_format = V4L2_PIX_FMT_GREY,
135 .start = { 0, 0 },
136 .count = { 0, 0 },
137 .flags = 0,
Mike Iselyd8554972006-06-26 20:58:46 -0300138 }
139 }
140 }
141};
142
Mike Isely16eb40d2006-12-30 18:27:32 -0300143
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300144
Mike Iselyd8554972006-06-26 20:58:46 -0300145/*
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300146 * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
Mike Iselyd8554972006-06-26 20:58:46 -0300147 */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300148static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
149{
150 struct pvr2_v4l2_fh *fh = file->private_data;
151 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
152
Hans Verkuil42639f62015-01-19 06:23:26 -0300153 strlcpy(cap->driver, "pvrusb2", sizeof(cap->driver));
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300154 strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
155 sizeof(cap->bus_info));
156 strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
Hans Verkuil42639f62015-01-19 06:23:26 -0300157 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
158 V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
159 V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS;
160 switch (fh->pdi->devbase.vfl_type) {
161 case VFL_TYPE_GRABBER:
162 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO;
163 break;
164 case VFL_TYPE_RADIO:
165 cap->device_caps = V4L2_CAP_RADIO;
166 break;
167 }
168 cap->device_caps |= V4L2_CAP_TUNER | V4L2_CAP_READWRITE;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300169 return 0;
170}
171
172static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
Mike Iselyd8554972006-06-26 20:58:46 -0300173{
174 struct pvr2_v4l2_fh *fh = file->private_data;
175 struct pvr2_v4l2 *vp = fh->vhead;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300176
177 *p = v4l2_prio_max(&vp->prio);
178 return 0;
179}
180
181static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
182{
183 struct pvr2_v4l2_fh *fh = file->private_data;
184 struct pvr2_v4l2 *vp = fh->vhead;
185
186 return v4l2_prio_change(&vp->prio, &fh->prio, prio);
187}
188
189static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
190{
191 struct pvr2_v4l2_fh *fh = file->private_data;
Mike Iselyd8554972006-06-26 20:58:46 -0300192 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300193 int val = 0;
194 int ret;
Mike Iselyd8554972006-06-26 20:58:46 -0300195
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300196 ret = pvr2_ctrl_get_value(
197 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
198 *std = val;
199 return ret;
200}
Mike Iselyd8554972006-06-26 20:58:46 -0300201
Hans Verkuil314527a2013-03-15 06:10:40 -0300202static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300203{
204 struct pvr2_v4l2_fh *fh = file->private_data;
205 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300206
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300207 return pvr2_ctrl_set_value(
Hans Verkuil314527a2013-03-15 06:10:40 -0300208 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300209}
Mike Iselyd8554972006-06-26 20:58:46 -0300210
Mike Isely0927ee62012-02-20 02:26:06 -0300211static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
212{
213 struct pvr2_v4l2_fh *fh = file->private_data;
214 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyac04d002012-02-20 02:28:56 -0300215 int val = 0;
216 int ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300217
Mike Iselyac04d002012-02-20 02:28:56 -0300218 ret = pvr2_ctrl_get_value(
219 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
220 *std = val;
221 return ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300222}
223
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300224static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
225{
226 struct pvr2_v4l2_fh *fh = file->private_data;
227 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
228 struct pvr2_ctrl *cptr;
229 struct v4l2_input tmp;
230 unsigned int cnt;
231 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300232
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300233 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
Mike Iselyd8554972006-06-26 20:58:46 -0300234
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300235 memset(&tmp, 0, sizeof(tmp));
236 tmp.index = vi->index;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300237 if (vi->index >= fh->input_cnt)
238 return -EINVAL;
239 val = fh->input_map[vi->index];
240 switch (val) {
241 case PVR2_CVAL_INPUT_TV:
242 case PVR2_CVAL_INPUT_DTV:
243 case PVR2_CVAL_INPUT_RADIO:
244 tmp.type = V4L2_INPUT_TYPE_TUNER;
Mike Iselyd8554972006-06-26 20:58:46 -0300245 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300246 case PVR2_CVAL_INPUT_SVIDEO:
247 case PVR2_CVAL_INPUT_COMPOSITE:
248 tmp.type = V4L2_INPUT_TYPE_CAMERA;
Mike Iselyd8554972006-06-26 20:58:46 -0300249 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300250 default:
251 return -EINVAL;
Mike Iselyd8554972006-06-26 20:58:46 -0300252 }
253
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300254 cnt = 0;
255 pvr2_ctrl_get_valname(cptr, val,
256 tmp.name, sizeof(tmp.name) - 1, &cnt);
257 tmp.name[cnt] = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300258
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300259 /* Don't bother with audioset, since this driver currently
260 always switches the audio whenever the video is
261 switched. */
Mike Iselyd8554972006-06-26 20:58:46 -0300262
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300263 /* Handling std is a tougher problem. It doesn't make
264 sense in cases where a device might be multi-standard.
265 We could just copy out the current value for the
266 standard, but it can change over time. For now just
267 leave it zero. */
268 *vi = tmp;
269 return 0;
270}
Mike Iselyd8554972006-06-26 20:58:46 -0300271
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300272static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
273{
274 struct pvr2_v4l2_fh *fh = file->private_data;
275 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
276 unsigned int idx;
277 struct pvr2_ctrl *cptr;
278 int val;
279 int ret;
Mauro Carvalho Chehab7383a472011-10-03 12:22:28 -0300280
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300281 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
282 val = 0;
283 ret = pvr2_ctrl_get_value(cptr, &val);
284 *i = 0;
285 for (idx = 0; idx < fh->input_cnt; idx++) {
286 if (fh->input_map[idx] == val) {
287 *i = idx;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300288 break;
289 }
Mike Iselyd8554972006-06-26 20:58:46 -0300290 }
291 return ret;
292}
293
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300294static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
295{
296 struct pvr2_v4l2_fh *fh = file->private_data;
297 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
298
299 if (inp >= fh->input_cnt)
300 return -EINVAL;
301 return pvr2_ctrl_set_value(
302 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
303 fh->input_map[inp]);
304}
305
306static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
307{
308 /* pkt: FIXME: We are returning one "fake" input here
309 which could very well be called "whatever_we_like".
310 This is for apps that want to see an audio input
311 just to feel comfortable, as well as to test if
312 it can do stereo or sth. There is actually no guarantee
313 that the actual audio input cannot change behind the app's
314 back, but most applications should not mind that either.
315
316 Hopefully, mplayer people will work with us on this (this
317 whole mess is to support mplayer pvr://), or Hans will come
318 up with a more standard way to say "we have inputs but we
319 don 't want you to change them independent of video" which
320 will sort this mess.
321 */
322
323 if (vin->index > 0)
324 return -EINVAL;
325 strncpy(vin->name, "PVRUSB2 Audio", 14);
326 vin->capability = V4L2_AUDCAP_STEREO;
327 return 0;
328}
329
330static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
331{
332 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
333 vin->index = 0;
334 strncpy(vin->name, "PVRUSB2 Audio", 14);
335 vin->capability = V4L2_AUDCAP_STEREO;
336 return 0;
337}
338
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300339static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300340{
341 if (vout->index)
342 return -EINVAL;
343 return 0;
344}
345
346static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
347{
348 struct pvr2_v4l2_fh *fh = file->private_data;
349 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
350
351 if (vt->index != 0)
352 return -EINVAL; /* Only answer for the 1st tuner */
353
354 pvr2_hdw_execute_tuner_poll(hdw);
355 return pvr2_hdw_get_tuner_status(hdw, vt);
356}
357
Hans Verkuil2f73c7c2013-03-15 06:10:06 -0300358static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300359{
360 struct pvr2_v4l2_fh *fh = file->private_data;
361 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
362
363 if (vt->index != 0)
364 return -EINVAL;
365
366 return pvr2_ctrl_set_value(
367 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
368 vt->audmode);
369}
370
Hans Verkuilb530a442013-03-19 04:09:26 -0300371static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300372{
373 struct pvr2_v4l2_fh *fh = file->private_data;
374 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
375 unsigned long fv;
376 struct v4l2_tuner vt;
377 int cur_input;
378 struct pvr2_ctrl *ctrlp;
379 int ret;
380
381 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
382 if (ret != 0)
383 return ret;
384 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
385 ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
386 if (ret != 0)
387 return ret;
388 if (vf->type == V4L2_TUNER_RADIO) {
389 if (cur_input != PVR2_CVAL_INPUT_RADIO)
390 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
391 } else {
392 if (cur_input == PVR2_CVAL_INPUT_RADIO)
393 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
394 }
395 fv = vf->frequency;
396 if (vt.capability & V4L2_TUNER_CAP_LOW)
397 fv = (fv * 125) / 2;
398 else
399 fv = fv * 62500;
400 return pvr2_ctrl_set_value(
401 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
402}
403
404static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
405{
406 struct pvr2_v4l2_fh *fh = file->private_data;
407 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
408 int val = 0;
409 int cur_input;
410 struct v4l2_tuner vt;
411 int ret;
412
413 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
414 if (ret != 0)
415 return ret;
416 ret = pvr2_ctrl_get_value(
417 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
418 &val);
419 if (ret != 0)
420 return ret;
421 pvr2_ctrl_get_value(
422 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
423 &cur_input);
424 if (cur_input == PVR2_CVAL_INPUT_RADIO)
425 vf->type = V4L2_TUNER_RADIO;
426 else
427 vf->type = V4L2_TUNER_ANALOG_TV;
428 if (vt.capability & V4L2_TUNER_CAP_LOW)
429 val = (val * 2) / 125;
430 else
431 val /= 62500;
432 vf->frequency = val;
433 return 0;
434}
435
436static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
437{
438 /* Only one format is supported : mpeg.*/
439 if (fd->index != 0)
440 return -EINVAL;
441
442 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
443 return 0;
444}
445
446static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
447{
448 struct pvr2_v4l2_fh *fh = file->private_data;
449 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
450 int val;
451
452 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
453 val = 0;
454 pvr2_ctrl_get_value(
455 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
456 &val);
457 vf->fmt.pix.width = val;
458 val = 0;
459 pvr2_ctrl_get_value(
460 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
461 &val);
462 vf->fmt.pix.height = val;
463 return 0;
464}
465
466static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
467{
468 struct pvr2_v4l2_fh *fh = file->private_data;
469 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
470 int lmin, lmax, ldef;
471 struct pvr2_ctrl *hcp, *vcp;
472 int h = vf->fmt.pix.height;
473 int w = vf->fmt.pix.width;
474
475 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
476 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
477
478 lmin = pvr2_ctrl_get_min(hcp);
479 lmax = pvr2_ctrl_get_max(hcp);
480 pvr2_ctrl_get_def(hcp, &ldef);
481 if (w == -1)
482 w = ldef;
483 else if (w < lmin)
484 w = lmin;
485 else if (w > lmax)
486 w = lmax;
487 lmin = pvr2_ctrl_get_min(vcp);
488 lmax = pvr2_ctrl_get_max(vcp);
489 pvr2_ctrl_get_def(vcp, &ldef);
490 if (h == -1)
491 h = ldef;
492 else if (h < lmin)
493 h = lmin;
494 else if (h > lmax)
495 h = lmax;
496
497 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
498 sizeof(struct v4l2_format));
499 vf->fmt.pix.width = w;
500 vf->fmt.pix.height = h;
501 return 0;
502}
503
504static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
505{
506 struct pvr2_v4l2_fh *fh = file->private_data;
507 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
508 struct pvr2_ctrl *hcp, *vcp;
509 int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
510
511 if (ret)
512 return ret;
513 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
514 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
515 pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
516 pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
517 return 0;
518}
519
520static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
521{
522 struct pvr2_v4l2_fh *fh = file->private_data;
523 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
524 struct pvr2_v4l2_dev *pdi = fh->pdi;
525 int ret;
526
527 if (!fh->pdi->stream) {
528 /* No stream defined for this node. This means
529 that we're not currently allowed to stream from
530 this node. */
531 return -EPERM;
532 }
533 ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
534 if (ret < 0)
535 return ret;
536 return pvr2_hdw_set_streaming(hdw, !0);
537}
538
539static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
540{
541 struct pvr2_v4l2_fh *fh = file->private_data;
542 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
543
544 if (!fh->pdi->stream) {
545 /* No stream defined for this node. This means
546 that we're not currently allowed to stream from
547 this node. */
548 return -EPERM;
549 }
550 return pvr2_hdw_set_streaming(hdw, 0);
551}
552
553static int pvr2_queryctrl(struct file *file, void *priv,
554 struct v4l2_queryctrl *vc)
555{
556 struct pvr2_v4l2_fh *fh = file->private_data;
557 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
558 struct pvr2_ctrl *cptr;
559 int val;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300560
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300561 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
562 cptr = pvr2_hdw_get_ctrl_nextv4l(
563 hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
564 if (cptr)
565 vc->id = pvr2_ctrl_get_v4lid(cptr);
566 } else {
567 cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
568 }
569 if (!cptr) {
570 pvr2_trace(PVR2_TRACE_V4LIOCTL,
571 "QUERYCTRL id=0x%x not implemented here",
572 vc->id);
573 return -EINVAL;
574 }
575
576 pvr2_trace(PVR2_TRACE_V4LIOCTL,
577 "QUERYCTRL id=0x%x mapping name=%s (%s)",
578 vc->id, pvr2_ctrl_get_name(cptr),
579 pvr2_ctrl_get_desc(cptr));
580 strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
581 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
582 pvr2_ctrl_get_def(cptr, &val);
583 vc->default_value = val;
584 switch (pvr2_ctrl_get_type(cptr)) {
585 case pvr2_ctl_enum:
586 vc->type = V4L2_CTRL_TYPE_MENU;
587 vc->minimum = 0;
588 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
589 vc->step = 1;
590 break;
591 case pvr2_ctl_bool:
592 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
593 vc->minimum = 0;
594 vc->maximum = 1;
595 vc->step = 1;
596 break;
597 case pvr2_ctl_int:
598 vc->type = V4L2_CTRL_TYPE_INTEGER;
599 vc->minimum = pvr2_ctrl_get_min(cptr);
600 vc->maximum = pvr2_ctrl_get_max(cptr);
601 vc->step = 1;
602 break;
603 default:
604 pvr2_trace(PVR2_TRACE_V4LIOCTL,
605 "QUERYCTRL id=0x%x name=%s not mappable",
606 vc->id, pvr2_ctrl_get_name(cptr));
607 return -EINVAL;
608 }
609 return 0;
610}
611
612static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
613{
614 struct pvr2_v4l2_fh *fh = file->private_data;
615 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
616 unsigned int cnt = 0;
617 int ret;
618
619 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
620 vm->index,
621 vm->name, sizeof(vm->name) - 1,
622 &cnt);
623 vm->name[cnt] = 0;
624 return ret;
625}
626
627static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
628{
629 struct pvr2_v4l2_fh *fh = file->private_data;
630 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
631 int val = 0;
632 int ret;
633
634 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
635 &val);
636 vc->value = val;
637 return ret;
638}
639
640static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
641{
642 struct pvr2_v4l2_fh *fh = file->private_data;
643 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
644
645 return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
646 vc->value);
647}
648
649static int pvr2_g_ext_ctrls(struct file *file, void *priv,
650 struct v4l2_ext_controls *ctls)
651{
652 struct pvr2_v4l2_fh *fh = file->private_data;
653 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
654 struct v4l2_ext_control *ctrl;
655 unsigned int idx;
656 int val;
657 int ret;
658
659 ret = 0;
660 for (idx = 0; idx < ctls->count; idx++) {
661 ctrl = ctls->controls + idx;
662 ret = pvr2_ctrl_get_value(
663 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
664 if (ret) {
665 ctls->error_idx = idx;
666 return ret;
667 }
668 /* Ensure that if read as a 64 bit value, the user
669 will still get a hopefully sane value */
670 ctrl->value64 = 0;
671 ctrl->value = val;
672 }
673 return 0;
674}
675
676static int pvr2_s_ext_ctrls(struct file *file, void *priv,
677 struct v4l2_ext_controls *ctls)
678{
679 struct pvr2_v4l2_fh *fh = file->private_data;
680 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
681 struct v4l2_ext_control *ctrl;
682 unsigned int idx;
683 int ret;
684
685 ret = 0;
686 for (idx = 0; idx < ctls->count; idx++) {
687 ctrl = ctls->controls + idx;
688 ret = pvr2_ctrl_set_value(
689 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
690 ctrl->value);
691 if (ret) {
692 ctls->error_idx = idx;
693 return ret;
694 }
695 }
696 return 0;
697}
698
699static int pvr2_try_ext_ctrls(struct file *file, void *priv,
700 struct v4l2_ext_controls *ctls)
701{
702 struct pvr2_v4l2_fh *fh = file->private_data;
703 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
704 struct v4l2_ext_control *ctrl;
705 struct pvr2_ctrl *pctl;
706 unsigned int idx;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300707
708 /* For the moment just validate that the requested control
709 actually exists. */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300710 for (idx = 0; idx < ctls->count; idx++) {
711 ctrl = ctls->controls + idx;
712 pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
713 if (!pctl) {
714 ctls->error_idx = idx;
715 return -EINVAL;
716 }
717 }
718 return 0;
719}
720
721static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
722{
723 struct pvr2_v4l2_fh *fh = file->private_data;
724 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
725 int ret;
726
727 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
728 return -EINVAL;
729 ret = pvr2_hdw_get_cropcap(hdw, cap);
730 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
731 return ret;
732}
733
734static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
735{
736 struct pvr2_v4l2_fh *fh = file->private_data;
737 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
738 int val = 0;
739 int ret;
740
741 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
742 return -EINVAL;
743 ret = pvr2_ctrl_get_value(
744 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
745 if (ret != 0)
746 return -EINVAL;
747 crop->c.left = val;
748 ret = pvr2_ctrl_get_value(
749 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
750 if (ret != 0)
751 return -EINVAL;
752 crop->c.top = val;
753 ret = pvr2_ctrl_get_value(
754 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
755 if (ret != 0)
756 return -EINVAL;
757 crop->c.width = val;
758 ret = pvr2_ctrl_get_value(
759 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
760 if (ret != 0)
761 return -EINVAL;
762 crop->c.height = val;
763 return 0;
764}
765
Hans Verkuil4f996592012-09-05 05:10:48 -0300766static int pvr2_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300767{
768 struct pvr2_v4l2_fh *fh = file->private_data;
769 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300770 int ret;
771
772 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
773 return -EINVAL;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300774 ret = pvr2_ctrl_set_value(
775 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
776 crop->c.left);
777 if (ret != 0)
778 return -EINVAL;
779 ret = pvr2_ctrl_set_value(
780 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
781 crop->c.top);
782 if (ret != 0)
783 return -EINVAL;
784 ret = pvr2_ctrl_set_value(
785 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
786 crop->c.width);
787 if (ret != 0)
788 return -EINVAL;
789 ret = pvr2_ctrl_set_value(
790 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
791 crop->c.height);
792 if (ret != 0)
793 return -EINVAL;
794 return 0;
795}
796
797static int pvr2_log_status(struct file *file, void *priv)
798{
799 struct pvr2_v4l2_fh *fh = file->private_data;
800 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
801
802 pvr2_hdw_trigger_module_log(hdw);
803 return 0;
804}
805
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300806static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
807 .vidioc_querycap = pvr2_querycap,
808 .vidioc_g_priority = pvr2_g_priority,
809 .vidioc_s_priority = pvr2_s_priority,
810 .vidioc_s_audio = pvr2_s_audio,
811 .vidioc_g_audio = pvr2_g_audio,
812 .vidioc_enumaudio = pvr2_enumaudio,
813 .vidioc_enum_input = pvr2_enum_input,
814 .vidioc_cropcap = pvr2_cropcap,
815 .vidioc_s_crop = pvr2_s_crop,
816 .vidioc_g_crop = pvr2_g_crop,
817 .vidioc_g_input = pvr2_g_input,
818 .vidioc_s_input = pvr2_s_input,
819 .vidioc_g_frequency = pvr2_g_frequency,
820 .vidioc_s_frequency = pvr2_s_frequency,
821 .vidioc_s_tuner = pvr2_s_tuner,
822 .vidioc_g_tuner = pvr2_g_tuner,
823 .vidioc_g_std = pvr2_g_std,
824 .vidioc_s_std = pvr2_s_std,
Mike Isely0927ee62012-02-20 02:26:06 -0300825 .vidioc_querystd = pvr2_querystd,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300826 .vidioc_log_status = pvr2_log_status,
827 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
828 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
829 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
830 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
831 .vidioc_streamon = pvr2_streamon,
832 .vidioc_streamoff = pvr2_streamoff,
833 .vidioc_queryctrl = pvr2_queryctrl,
834 .vidioc_querymenu = pvr2_querymenu,
835 .vidioc_g_ctrl = pvr2_g_ctrl,
836 .vidioc_s_ctrl = pvr2_s_ctrl,
837 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
838 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
839 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300840};
841
Mike Iselyd8554972006-06-26 20:58:46 -0300842static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
843{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300844 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300845 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300846 char msg[80];
847 unsigned int mcnt;
848
849 /* Construct the unregistration message *before* we actually
850 perform the unregistration step. By doing it this way we don't
851 have to worry about potentially touching deleted resources. */
852 mcnt = scnprintf(msg, sizeof(msg) - 1,
853 "pvrusb2: unregistered device %s [%s]",
854 video_device_node_name(&dip->devbase),
855 pvr2_config_get_name(cfg));
856 msg[mcnt] = 0;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300857
Mike Isely16eb40d2006-12-30 18:27:32 -0300858 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300859
860 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300861 dip->v4lp = NULL;
862 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300863
864 /* Actual deallocation happens later when all internal references
865 are gone. */
866 video_unregister_device(&dip->devbase);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300867
Mike Iselyd72baad2010-05-15 00:15:38 -0300868 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300869
Mike Iselyd8554972006-06-26 20:58:46 -0300870}
871
872
Mike Isely4a89baa2009-10-12 00:13:28 -0300873static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
874{
875 if (!dip) return;
Hans Verkuila28fbd02013-06-10 09:16:25 -0300876 if (!dip->devbase.v4l2_dev->dev) return;
877 dip->devbase.v4l2_dev->dev = NULL;
Mike Isely4a89baa2009-10-12 00:13:28 -0300878 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
879}
880
881
Mike Iselyd8554972006-06-26 20:58:46 -0300882static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
883{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300884 if (vp->dev_video) {
885 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000886 vp->dev_video = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300887 }
888 if (vp->dev_radio) {
889 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000890 vp->dev_radio = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300891 }
Mike Iselyd8554972006-06-26 20:58:46 -0300892
893 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
894 pvr2_channel_done(&vp->channel);
895 kfree(vp);
896}
897
898
Mike Isely75910052006-09-23 22:30:50 -0300899static void pvr2_video_device_release(struct video_device *vdev)
900{
901 struct pvr2_v4l2_dev *dev;
902 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
903 kfree(dev);
904}
905
906
Adrian Bunk07e337e2006-06-30 11:30:20 -0300907static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300908{
909 struct pvr2_v4l2 *vp;
910 vp = container_of(chp,struct pvr2_v4l2,channel);
911 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300912 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
913 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Mike Iselyd8554972006-06-26 20:58:46 -0300914 if (vp->vfirst) return;
915 pvr2_v4l2_destroy_no_lock(vp);
916}
917
918
Hans Verkuil069b7472008-12-30 07:04:34 -0300919static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300920 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300921{
922
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300923 struct pvr2_v4l2_fh *fh = file->private_data;
924 struct pvr2_v4l2 *vp = fh->vhead;
925 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
926 long ret = -EINVAL;
927
928 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
Hans Verkuil4a085162012-06-22 06:38:06 -0300929 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300930
931 if (!pvr2_hdw_dev_ok(hdw)) {
932 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
933 "ioctl failed - bad or no context");
934 return -EFAULT;
935 }
936
937 /* check priority */
938 switch (cmd) {
939 case VIDIOC_S_CTRL:
940 case VIDIOC_S_STD:
941 case VIDIOC_S_INPUT:
942 case VIDIOC_S_TUNER:
943 case VIDIOC_S_FREQUENCY:
944 ret = v4l2_prio_check(&vp->prio, fh->prio);
945 if (ret)
946 return ret;
947 }
948
949 ret = video_ioctl2(file, cmd, arg);
950
951 pvr2_hdw_commit_ctl(hdw);
952
953 if (ret < 0) {
954 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
955 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Andrey Utkin599bc362014-07-10 09:32:25 -0300956 "pvr2_v4l2_do_ioctl failure, ret=%ld"
957 " command was:", ret);
958 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300959 }
960 } else {
961 pvr2_trace(PVR2_TRACE_V4LIOCTL,
962 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
963 ret, ret);
964 }
965 return ret;
966
Mike Iselyd8554972006-06-26 20:58:46 -0300967}
968
969
Hans Verkuilbec43662008-12-30 06:58:20 -0300970static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300971{
972 struct pvr2_v4l2_fh *fhp = file->private_data;
973 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300974 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300975
976 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
977
978 if (fhp->rhp) {
979 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300980 pvr2_hdw_set_streaming(hdw,0);
981 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300982 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300983 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300984 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300985 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300986
Hans Verkuilffb48772010-05-01 08:03:24 -0300987 v4l2_prio_close(&vp->prio, fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300988 file->private_data = NULL;
989
Mike Isely794b1602008-04-22 14:45:45 -0300990 if (fhp->vnext) {
991 fhp->vnext->vprev = fhp->vprev;
992 } else {
993 vp->vlast = fhp->vprev;
994 }
995 if (fhp->vprev) {
996 fhp->vprev->vnext = fhp->vnext;
997 } else {
998 vp->vfirst = fhp->vnext;
999 }
1000 fhp->vnext = NULL;
1001 fhp->vprev = NULL;
1002 fhp->vhead = NULL;
1003 pvr2_channel_done(&fhp->channel);
1004 pvr2_trace(PVR2_TRACE_STRUCT,
1005 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -03001006 if (fhp->input_map) {
1007 kfree(fhp->input_map);
1008 fhp->input_map = NULL;
1009 }
Mike Isely794b1602008-04-22 14:45:45 -03001010 kfree(fhp);
1011 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
1012 pvr2_v4l2_destroy_no_lock(vp);
1013 }
Mike Iselyd8554972006-06-26 20:58:46 -03001014 return 0;
1015}
1016
1017
Hans Verkuilbec43662008-12-30 06:58:20 -03001018static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001019{
Mike Isely75910052006-09-23 22:30:50 -03001020 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001021 struct pvr2_v4l2_fh *fhp;
1022 struct pvr2_v4l2 *vp;
1023 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001024 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001025 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001026 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001027
Mike Isely75910052006-09-23 22:30:50 -03001028 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001029
1030 vp = dip->v4lp;
1031 hdw = vp->channel.hdw;
1032
1033 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1034
1035 if (!pvr2_hdw_dev_ok(hdw)) {
1036 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1037 "pvr2_v4l2_open: hardware not ready");
1038 return -EIO;
1039 }
1040
Mike Isely4b85dee2007-01-20 00:03:32 -03001041 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001042 if (!fhp) {
1043 return -ENOMEM;
1044 }
Mike Iselyd8554972006-06-26 20:58:46 -03001045
1046 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001047 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001048
Mike Isely794b1602008-04-22 14:45:45 -03001049 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1050 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001051
Mike Isely1cb03b72008-04-21 03:47:43 -03001052 if (dip->v4l_type == VFL_TYPE_RADIO) {
1053 /* Opening device as a radio, legal input selection subset
1054 is just the radio. */
1055 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1056 } else {
1057 /* Opening the main V4L device, legal input selection
1058 subset includes all analog inputs. */
1059 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1060 (1 << PVR2_CVAL_INPUT_TV) |
1061 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1062 (1 << PVR2_CVAL_INPUT_SVIDEO));
1063 }
1064 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1065 if (ret) {
1066 pvr2_channel_done(&fhp->channel);
1067 pvr2_trace(PVR2_TRACE_STRUCT,
1068 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1069 fhp);
1070
1071 kfree(fhp);
1072 return ret;
1073 }
1074
Mike Iselye57b1c82008-04-21 03:52:34 -03001075 input_mask &= pvr2_hdw_get_input_available(hdw);
1076 input_cnt = 0;
1077 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1078 if (input_mask & (1 << idx)) input_cnt++;
1079 }
1080 fhp->input_cnt = input_cnt;
1081 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1082 if (!fhp->input_map) {
1083 pvr2_channel_done(&fhp->channel);
1084 pvr2_trace(PVR2_TRACE_STRUCT,
1085 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1086 fhp);
1087 kfree(fhp);
1088 return -ENOMEM;
1089 }
1090 input_cnt = 0;
1091 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1092 if (!(input_mask & (1 << idx))) continue;
1093 fhp->input_map[input_cnt++] = idx;
1094 }
1095
Mike Isely794b1602008-04-22 14:45:45 -03001096 fhp->vnext = NULL;
1097 fhp->vprev = vp->vlast;
1098 if (vp->vlast) {
1099 vp->vlast->vnext = fhp;
1100 } else {
1101 vp->vfirst = fhp;
1102 }
1103 vp->vlast = fhp;
1104 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001105
Mike Iselyd8554972006-06-26 20:58:46 -03001106 fhp->file = file;
1107 file->private_data = fhp;
Hans Verkuilffb48772010-05-01 08:03:24 -03001108 v4l2_prio_open(&vp->prio, &fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001109
1110 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1111
1112 return 0;
1113}
1114
1115
1116static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1117{
1118 wake_up(&fhp->wait_data);
1119}
1120
1121static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1122{
1123 int ret;
1124 struct pvr2_stream *sp;
1125 struct pvr2_hdw *hdw;
1126 if (fh->rhp) return 0;
1127
Joe Perches108bdd72010-04-05 16:05:39 -03001128 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001129 /* No stream defined for this node. This means that we're
1130 not currently allowed to stream from this node. */
1131 return -EPERM;
1132 }
1133
Mike Iselyd8554972006-06-26 20:58:46 -03001134 /* First read() attempt. Try to claim the stream and start
1135 it... */
1136 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001137 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001138 /* Someone else must already have it */
1139 return ret;
1140 }
1141
Joe Perches108bdd72010-04-05 16:05:39 -03001142 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001143 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001144 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001145 return -ENOMEM;
1146 }
1147
1148 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001149 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001150 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001151 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001152 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1153 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001154}
1155
1156
1157static ssize_t pvr2_v4l2_read(struct file *file,
1158 char __user *buff, size_t count, loff_t *ppos)
1159{
1160 struct pvr2_v4l2_fh *fh = file->private_data;
1161 int ret;
1162
1163 if (fh->fw_mode_flag) {
1164 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1165 char *tbuf;
1166 int c1,c2;
1167 int tcnt = 0;
1168 unsigned int offs = *ppos;
1169
1170 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1171 if (!tbuf) return -ENOMEM;
1172
1173 while (count) {
1174 c1 = count;
1175 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1176 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1177 if (c2 < 0) {
1178 tcnt = c2;
1179 break;
1180 }
1181 if (!c2) break;
1182 if (copy_to_user(buff,tbuf,c2)) {
1183 tcnt = -EFAULT;
1184 break;
1185 }
1186 offs += c2;
1187 tcnt += c2;
1188 buff += c2;
1189 count -= c2;
1190 *ppos += c2;
1191 }
1192 kfree(tbuf);
1193 return tcnt;
1194 }
1195
1196 if (!fh->rhp) {
1197 ret = pvr2_v4l2_iosetup(fh);
1198 if (ret) {
1199 return ret;
1200 }
1201 }
1202
1203 for (;;) {
1204 ret = pvr2_ioread_read(fh->rhp,buff,count);
1205 if (ret >= 0) break;
1206 if (ret != -EAGAIN) break;
1207 if (file->f_flags & O_NONBLOCK) break;
1208 /* Doing blocking I/O. Wait here. */
1209 ret = wait_event_interruptible(
1210 fh->wait_data,
1211 pvr2_ioread_avail(fh->rhp) >= 0);
1212 if (ret < 0) break;
1213 }
1214
1215 return ret;
1216}
1217
1218
1219static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1220{
1221 unsigned int mask = 0;
1222 struct pvr2_v4l2_fh *fh = file->private_data;
1223 int ret;
1224
1225 if (fh->fw_mode_flag) {
1226 mask |= POLLIN | POLLRDNORM;
1227 return mask;
1228 }
1229
1230 if (!fh->rhp) {
1231 ret = pvr2_v4l2_iosetup(fh);
1232 if (ret) return POLLERR;
1233 }
1234
1235 poll_wait(file,&fh->wait_data,wait);
1236
1237 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1238 mask |= POLLIN | POLLRDNORM;
1239 }
1240
1241 return mask;
1242}
1243
1244
Hans Verkuilbec43662008-12-30 06:58:20 -03001245static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001246 .owner = THIS_MODULE,
1247 .open = pvr2_v4l2_open,
1248 .release = pvr2_v4l2_release,
1249 .read = pvr2_v4l2_read,
1250 .ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001251 .poll = pvr2_v4l2_poll,
1252};
1253
1254
Mike Iselyd8554972006-06-26 20:58:46 -03001255static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001256 .fops = &vdev_fops,
1257};
1258
1259
1260static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1261 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001262 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001263{
1264 int mindevnum;
1265 int unit_number;
Mike Isely598e9782012-02-20 02:35:20 -03001266 struct pvr2_hdw *hdw;
Al Viro89952d12007-03-14 09:17:59 +00001267 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001268 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001269
Mike Isely598e9782012-02-20 02:35:20 -03001270 hdw = vp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -03001271 dip->v4l_type = v4l_type;
1272 switch (v4l_type) {
1273 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001274 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001275 dip->config = pvr2_config_mpeg;
1276 dip->minor_type = pvr2_v4l_type_video;
1277 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001278 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001279 pr_err(KBUILD_MODNAME
1280 ": Failed to set up pvrusb2 v4l video dev"
1281 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001282 return;
1283 }
Mike Iselyd8554972006-06-26 20:58:46 -03001284 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001285 case VFL_TYPE_VBI:
1286 dip->config = pvr2_config_vbi;
1287 dip->minor_type = pvr2_v4l_type_vbi;
1288 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001289 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001290 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001291 dip->stream = &vp->channel.mc_head->video_stream;
1292 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001293 dip->minor_type = pvr2_v4l_type_radio;
1294 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001295 break;
1296 default:
1297 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001298 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1299 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001300 return;
1301 }
1302
Ezequiel Garcia5338c162012-10-23 15:57:09 -03001303 dip->devbase = vdev_template;
Mike Isely75910052006-09-23 22:30:50 -03001304 dip->devbase.release = pvr2_video_device_release;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -03001305 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
Mike Iselyd8329f82012-02-20 02:33:06 -03001306 {
1307 int val;
1308 pvr2_ctrl_get_value(
Mike Isely598e9782012-02-20 02:35:20 -03001309 pvr2_hdw_get_ctrl_by_id(hdw,
Mike Iselyd8329f82012-02-20 02:33:06 -03001310 PVR2_CID_STDAVAIL), &val);
1311 dip->devbase.tvnorms = (v4l2_std_id)val;
1312 }
Mike Iselyd8554972006-06-26 20:58:46 -03001313
1314 mindevnum = -1;
Mike Isely598e9782012-02-20 02:35:20 -03001315 unit_number = pvr2_hdw_get_unit_number(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001316 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1317 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001318 }
Hans Verkuila28fbd02013-06-10 09:16:25 -03001319 pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase);
Mike Isely16eb40d2006-12-30 18:27:32 -03001320 if ((video_register_device(&dip->devbase,
1321 dip->v4l_type, mindevnum) < 0) &&
1322 (video_register_device(&dip->devbase,
1323 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001324 pr_err(KBUILD_MODNAME
1325 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001326 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001327
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001328 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1329 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001330 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001331
Mike Isely598e9782012-02-20 02:35:20 -03001332 pvr2_hdw_v4l_store_minor_number(hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001333 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001334}
1335
1336
1337struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1338{
1339 struct pvr2_v4l2 *vp;
1340
Mike Isely4b85dee2007-01-20 00:03:32 -03001341 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001342 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001343 pvr2_channel_init(&vp->channel,mnp);
1344 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1345
1346 vp->channel.check_func = pvr2_v4l2_internal_check;
1347
1348 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001349 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1350 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001351 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001352 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1353 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001354 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1355 if (!vp->dev_radio) goto fail;
1356 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1357 }
Mike Iselyd8554972006-06-26 20:58:46 -03001358
1359 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001360 fail:
1361 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1362 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001363 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001364}
1365
1366/*
1367 Stuff for Emacs to see, in order to encourage consistent editing style:
1368 *** Local Variables: ***
1369 *** mode: c ***
1370 *** fill-column: 75 ***
1371 *** tab-width: 8 ***
1372 *** c-basic-offset: 8 ***
1373 *** End: ***
1374 */