blob: 2cc4d2b6f810be171eb2b8bbb9a16cfca84d43b9 [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>
Mike Iselyd8554972006-06-26 20:58:46 -030024#include "pvrusb2-context.h"
25#include "pvrusb2-hdw.h"
26#include "pvrusb2.h"
27#include "pvrusb2-debug.h"
28#include "pvrusb2-v4l2.h"
29#include "pvrusb2-ioread.h"
30#include <linux/videodev2.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040031#include <linux/module.h>
Mike Isely43e06022006-09-23 23:47:50 -030032#include <media/v4l2-dev.h>
Hans Verkuila28fbd02013-06-10 09:16:25 -030033#include <media/v4l2-device.h>
Hans Verkuilcee05cb2015-02-03 10:46:55 -030034#include <media/v4l2-fh.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 {
Hans Verkuilcee05cb2015-02-03 10:46:55 -030053 struct v4l2_fh fh;
Mike Iselyd8554972006-06-26 20:58:46 -030054 struct pvr2_channel channel;
Joe Perches108bdd72010-04-05 16:05:39 -030055 struct pvr2_v4l2_dev *pdi;
Mike Iselyd8554972006-06-26 20:58:46 -030056 struct pvr2_ioread *rhp;
57 struct file *file;
Mike Iselyd8554972006-06-26 20:58:46 -030058 wait_queue_head_t wait_data;
59 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030060 /* Map contiguous ordinal value to input id */
61 unsigned char *input_map;
62 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030063};
64
65struct pvr2_v4l2 {
66 struct pvr2_channel channel;
Mike Iselyd8554972006-06-26 20:58:46 -030067
Mike Isely0f0f257b2006-12-27 23:19:42 -030068 /* streams - Note that these must be separately, individually,
69 * allocated pointers. This is because the v4l core is going to
70 * manage their deletion - separately, individually... */
71 struct pvr2_v4l2_dev *dev_video;
72 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030073};
74
75static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
76module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030077MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
78static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
79module_param_array(radio_nr, int, NULL, 0444);
80MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
81static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
82module_param_array(vbi_nr, int, NULL, 0444);
83MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030084
Adrian Bunk07e337e2006-06-30 11:30:20 -030085static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -030086 {
87 .index = 0,
88 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
89 .flags = V4L2_FMT_FLAG_COMPRESSED,
90 .description = "MPEG1/2",
91 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
92 // breaks when I do that.
93 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
Mike Iselyd8554972006-06-26 20:58:46 -030094 }
95};
96
97#define PVR_FORMAT_PIX 0
98#define PVR_FORMAT_VBI 1
99
Adrian Bunk07e337e2006-06-30 11:30:20 -0300100static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300101 [PVR_FORMAT_PIX] = {
102 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
103 .fmt = {
104 .pix = {
105 .width = 720,
106 .height = 576,
107 // This should really be V4L2_PIX_FMT_MPEG,
108 // but xawtv breaks when I do that.
109 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
110 .field = V4L2_FIELD_INTERLACED,
111 .bytesperline = 0, // doesn't make sense
112 // here
113 //FIXME : Don't know what to put here...
114 .sizeimage = (32*1024),
115 .colorspace = 0, // doesn't make sense here
116 .priv = 0
117 }
118 }
119 },
120 [PVR_FORMAT_VBI] = {
121 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
122 .fmt = {
123 .vbi = {
124 .sampling_rate = 27000000,
125 .offset = 248,
126 .samples_per_line = 1443,
127 .sample_format = V4L2_PIX_FMT_GREY,
128 .start = { 0, 0 },
129 .count = { 0, 0 },
130 .flags = 0,
Mike Iselyd8554972006-06-26 20:58:46 -0300131 }
132 }
133 }
134};
135
Mike Isely16eb40d2006-12-30 18:27:32 -0300136
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300137
Mike Iselyd8554972006-06-26 20:58:46 -0300138/*
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300139 * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
Mike Iselyd8554972006-06-26 20:58:46 -0300140 */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300141static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
142{
143 struct pvr2_v4l2_fh *fh = file->private_data;
144 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
145
Hans Verkuil42639f62015-01-19 06:23:26 -0300146 strlcpy(cap->driver, "pvrusb2", sizeof(cap->driver));
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300147 strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
148 sizeof(cap->bus_info));
149 strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
Hans Verkuil42639f62015-01-19 06:23:26 -0300150 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
151 V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
152 V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS;
153 switch (fh->pdi->devbase.vfl_type) {
154 case VFL_TYPE_GRABBER:
155 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO;
156 break;
157 case VFL_TYPE_RADIO:
158 cap->device_caps = V4L2_CAP_RADIO;
159 break;
160 }
161 cap->device_caps |= V4L2_CAP_TUNER | V4L2_CAP_READWRITE;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300162 return 0;
163}
164
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300165static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
166{
167 struct pvr2_v4l2_fh *fh = file->private_data;
Mike Iselyd8554972006-06-26 20:58:46 -0300168 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300169 int val = 0;
170 int ret;
Mike Iselyd8554972006-06-26 20:58:46 -0300171
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300172 ret = pvr2_ctrl_get_value(
173 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
174 *std = val;
175 return ret;
176}
Mike Iselyd8554972006-06-26 20:58:46 -0300177
Hans Verkuil314527a2013-03-15 06:10:40 -0300178static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300179{
180 struct pvr2_v4l2_fh *fh = file->private_data;
181 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300182
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300183 return pvr2_ctrl_set_value(
Hans Verkuil314527a2013-03-15 06:10:40 -0300184 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300185}
Mike Iselyd8554972006-06-26 20:58:46 -0300186
Mike Isely0927ee62012-02-20 02:26:06 -0300187static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
188{
189 struct pvr2_v4l2_fh *fh = file->private_data;
190 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyac04d002012-02-20 02:28:56 -0300191 int val = 0;
192 int ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300193
Mike Iselyac04d002012-02-20 02:28:56 -0300194 ret = pvr2_ctrl_get_value(
195 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
196 *std = val;
197 return ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300198}
199
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300200static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
201{
202 struct pvr2_v4l2_fh *fh = file->private_data;
203 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
204 struct pvr2_ctrl *cptr;
205 struct v4l2_input tmp;
206 unsigned int cnt;
207 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300208
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300209 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
Mike Iselyd8554972006-06-26 20:58:46 -0300210
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300211 memset(&tmp, 0, sizeof(tmp));
212 tmp.index = vi->index;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300213 if (vi->index >= fh->input_cnt)
214 return -EINVAL;
215 val = fh->input_map[vi->index];
216 switch (val) {
217 case PVR2_CVAL_INPUT_TV:
218 case PVR2_CVAL_INPUT_DTV:
219 case PVR2_CVAL_INPUT_RADIO:
220 tmp.type = V4L2_INPUT_TYPE_TUNER;
Mike Iselyd8554972006-06-26 20:58:46 -0300221 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300222 case PVR2_CVAL_INPUT_SVIDEO:
223 case PVR2_CVAL_INPUT_COMPOSITE:
224 tmp.type = V4L2_INPUT_TYPE_CAMERA;
Mike Iselyd8554972006-06-26 20:58:46 -0300225 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300226 default:
227 return -EINVAL;
Mike Iselyd8554972006-06-26 20:58:46 -0300228 }
229
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300230 cnt = 0;
231 pvr2_ctrl_get_valname(cptr, val,
232 tmp.name, sizeof(tmp.name) - 1, &cnt);
233 tmp.name[cnt] = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300234
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300235 /* Don't bother with audioset, since this driver currently
236 always switches the audio whenever the video is
237 switched. */
Mike Iselyd8554972006-06-26 20:58:46 -0300238
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300239 /* Handling std is a tougher problem. It doesn't make
240 sense in cases where a device might be multi-standard.
241 We could just copy out the current value for the
242 standard, but it can change over time. For now just
243 leave it zero. */
244 *vi = tmp;
245 return 0;
246}
Mike Iselyd8554972006-06-26 20:58:46 -0300247
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300248static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
249{
250 struct pvr2_v4l2_fh *fh = file->private_data;
251 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
252 unsigned int idx;
253 struct pvr2_ctrl *cptr;
254 int val;
255 int ret;
Mauro Carvalho Chehab7383a472011-10-03 12:22:28 -0300256
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300257 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
258 val = 0;
259 ret = pvr2_ctrl_get_value(cptr, &val);
260 *i = 0;
261 for (idx = 0; idx < fh->input_cnt; idx++) {
262 if (fh->input_map[idx] == val) {
263 *i = idx;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300264 break;
265 }
Mike Iselyd8554972006-06-26 20:58:46 -0300266 }
267 return ret;
268}
269
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300270static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
271{
272 struct pvr2_v4l2_fh *fh = file->private_data;
273 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
274
275 if (inp >= fh->input_cnt)
276 return -EINVAL;
277 return pvr2_ctrl_set_value(
278 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
279 fh->input_map[inp]);
280}
281
282static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
283{
284 /* pkt: FIXME: We are returning one "fake" input here
285 which could very well be called "whatever_we_like".
286 This is for apps that want to see an audio input
287 just to feel comfortable, as well as to test if
288 it can do stereo or sth. There is actually no guarantee
289 that the actual audio input cannot change behind the app's
290 back, but most applications should not mind that either.
291
292 Hopefully, mplayer people will work with us on this (this
293 whole mess is to support mplayer pvr://), or Hans will come
294 up with a more standard way to say "we have inputs but we
295 don 't want you to change them independent of video" which
296 will sort this mess.
297 */
298
299 if (vin->index > 0)
300 return -EINVAL;
301 strncpy(vin->name, "PVRUSB2 Audio", 14);
302 vin->capability = V4L2_AUDCAP_STEREO;
303 return 0;
304}
305
306static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
307{
308 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
309 vin->index = 0;
310 strncpy(vin->name, "PVRUSB2 Audio", 14);
311 vin->capability = V4L2_AUDCAP_STEREO;
312 return 0;
313}
314
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300315static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300316{
317 if (vout->index)
318 return -EINVAL;
319 return 0;
320}
321
322static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
323{
324 struct pvr2_v4l2_fh *fh = file->private_data;
325 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
326
327 if (vt->index != 0)
328 return -EINVAL; /* Only answer for the 1st tuner */
329
330 pvr2_hdw_execute_tuner_poll(hdw);
331 return pvr2_hdw_get_tuner_status(hdw, vt);
332}
333
Hans Verkuil2f73c7c2013-03-15 06:10:06 -0300334static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300335{
336 struct pvr2_v4l2_fh *fh = file->private_data;
337 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
338
339 if (vt->index != 0)
340 return -EINVAL;
341
342 return pvr2_ctrl_set_value(
343 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
344 vt->audmode);
345}
346
Hans Verkuilb530a442013-03-19 04:09:26 -0300347static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300348{
349 struct pvr2_v4l2_fh *fh = file->private_data;
350 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
351 unsigned long fv;
352 struct v4l2_tuner vt;
353 int cur_input;
354 struct pvr2_ctrl *ctrlp;
355 int ret;
356
357 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
358 if (ret != 0)
359 return ret;
360 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
361 ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
362 if (ret != 0)
363 return ret;
364 if (vf->type == V4L2_TUNER_RADIO) {
365 if (cur_input != PVR2_CVAL_INPUT_RADIO)
366 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
367 } else {
368 if (cur_input == PVR2_CVAL_INPUT_RADIO)
369 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
370 }
371 fv = vf->frequency;
372 if (vt.capability & V4L2_TUNER_CAP_LOW)
373 fv = (fv * 125) / 2;
374 else
375 fv = fv * 62500;
376 return pvr2_ctrl_set_value(
377 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
378}
379
380static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
381{
382 struct pvr2_v4l2_fh *fh = file->private_data;
383 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
384 int val = 0;
385 int cur_input;
386 struct v4l2_tuner vt;
387 int ret;
388
389 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
390 if (ret != 0)
391 return ret;
392 ret = pvr2_ctrl_get_value(
393 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
394 &val);
395 if (ret != 0)
396 return ret;
397 pvr2_ctrl_get_value(
398 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
399 &cur_input);
400 if (cur_input == PVR2_CVAL_INPUT_RADIO)
401 vf->type = V4L2_TUNER_RADIO;
402 else
403 vf->type = V4L2_TUNER_ANALOG_TV;
404 if (vt.capability & V4L2_TUNER_CAP_LOW)
405 val = (val * 2) / 125;
406 else
407 val /= 62500;
408 vf->frequency = val;
409 return 0;
410}
411
412static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
413{
414 /* Only one format is supported : mpeg.*/
415 if (fd->index != 0)
416 return -EINVAL;
417
418 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
419 return 0;
420}
421
422static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
423{
424 struct pvr2_v4l2_fh *fh = file->private_data;
425 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
426 int val;
427
428 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
429 val = 0;
430 pvr2_ctrl_get_value(
431 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
432 &val);
433 vf->fmt.pix.width = val;
434 val = 0;
435 pvr2_ctrl_get_value(
436 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
437 &val);
438 vf->fmt.pix.height = val;
439 return 0;
440}
441
442static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
443{
444 struct pvr2_v4l2_fh *fh = file->private_data;
445 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
446 int lmin, lmax, ldef;
447 struct pvr2_ctrl *hcp, *vcp;
448 int h = vf->fmt.pix.height;
449 int w = vf->fmt.pix.width;
450
451 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
452 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
453
454 lmin = pvr2_ctrl_get_min(hcp);
455 lmax = pvr2_ctrl_get_max(hcp);
456 pvr2_ctrl_get_def(hcp, &ldef);
457 if (w == -1)
458 w = ldef;
459 else if (w < lmin)
460 w = lmin;
461 else if (w > lmax)
462 w = lmax;
463 lmin = pvr2_ctrl_get_min(vcp);
464 lmax = pvr2_ctrl_get_max(vcp);
465 pvr2_ctrl_get_def(vcp, &ldef);
466 if (h == -1)
467 h = ldef;
468 else if (h < lmin)
469 h = lmin;
470 else if (h > lmax)
471 h = lmax;
472
473 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
474 sizeof(struct v4l2_format));
475 vf->fmt.pix.width = w;
476 vf->fmt.pix.height = h;
477 return 0;
478}
479
480static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
481{
482 struct pvr2_v4l2_fh *fh = file->private_data;
483 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
484 struct pvr2_ctrl *hcp, *vcp;
485 int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
486
487 if (ret)
488 return ret;
489 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
490 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
491 pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
492 pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
493 return 0;
494}
495
496static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
497{
498 struct pvr2_v4l2_fh *fh = file->private_data;
499 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
500 struct pvr2_v4l2_dev *pdi = fh->pdi;
501 int ret;
502
503 if (!fh->pdi->stream) {
504 /* No stream defined for this node. This means
505 that we're not currently allowed to stream from
506 this node. */
507 return -EPERM;
508 }
509 ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
510 if (ret < 0)
511 return ret;
512 return pvr2_hdw_set_streaming(hdw, !0);
513}
514
515static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
516{
517 struct pvr2_v4l2_fh *fh = file->private_data;
518 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
519
520 if (!fh->pdi->stream) {
521 /* No stream defined for this node. This means
522 that we're not currently allowed to stream from
523 this node. */
524 return -EPERM;
525 }
526 return pvr2_hdw_set_streaming(hdw, 0);
527}
528
529static int pvr2_queryctrl(struct file *file, void *priv,
530 struct v4l2_queryctrl *vc)
531{
532 struct pvr2_v4l2_fh *fh = file->private_data;
533 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
534 struct pvr2_ctrl *cptr;
535 int val;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300536
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300537 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
538 cptr = pvr2_hdw_get_ctrl_nextv4l(
539 hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
540 if (cptr)
541 vc->id = pvr2_ctrl_get_v4lid(cptr);
542 } else {
543 cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
544 }
545 if (!cptr) {
546 pvr2_trace(PVR2_TRACE_V4LIOCTL,
547 "QUERYCTRL id=0x%x not implemented here",
548 vc->id);
549 return -EINVAL;
550 }
551
552 pvr2_trace(PVR2_TRACE_V4LIOCTL,
553 "QUERYCTRL id=0x%x mapping name=%s (%s)",
554 vc->id, pvr2_ctrl_get_name(cptr),
555 pvr2_ctrl_get_desc(cptr));
556 strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
557 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
558 pvr2_ctrl_get_def(cptr, &val);
559 vc->default_value = val;
560 switch (pvr2_ctrl_get_type(cptr)) {
561 case pvr2_ctl_enum:
562 vc->type = V4L2_CTRL_TYPE_MENU;
563 vc->minimum = 0;
564 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
565 vc->step = 1;
566 break;
567 case pvr2_ctl_bool:
568 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
569 vc->minimum = 0;
570 vc->maximum = 1;
571 vc->step = 1;
572 break;
573 case pvr2_ctl_int:
574 vc->type = V4L2_CTRL_TYPE_INTEGER;
575 vc->minimum = pvr2_ctrl_get_min(cptr);
576 vc->maximum = pvr2_ctrl_get_max(cptr);
577 vc->step = 1;
578 break;
579 default:
580 pvr2_trace(PVR2_TRACE_V4LIOCTL,
581 "QUERYCTRL id=0x%x name=%s not mappable",
582 vc->id, pvr2_ctrl_get_name(cptr));
583 return -EINVAL;
584 }
585 return 0;
586}
587
588static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
589{
590 struct pvr2_v4l2_fh *fh = file->private_data;
591 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
592 unsigned int cnt = 0;
593 int ret;
594
595 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
596 vm->index,
597 vm->name, sizeof(vm->name) - 1,
598 &cnt);
599 vm->name[cnt] = 0;
600 return ret;
601}
602
603static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
604{
605 struct pvr2_v4l2_fh *fh = file->private_data;
606 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
607 int val = 0;
608 int ret;
609
610 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
611 &val);
612 vc->value = val;
613 return ret;
614}
615
616static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
617{
618 struct pvr2_v4l2_fh *fh = file->private_data;
619 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
620
621 return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
622 vc->value);
623}
624
625static int pvr2_g_ext_ctrls(struct file *file, void *priv,
626 struct v4l2_ext_controls *ctls)
627{
628 struct pvr2_v4l2_fh *fh = file->private_data;
629 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
630 struct v4l2_ext_control *ctrl;
Ricardo Ribalda082afb72015-10-29 08:10:31 -0200631 struct pvr2_ctrl *cptr;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300632 unsigned int idx;
633 int val;
634 int ret;
635
636 ret = 0;
637 for (idx = 0; idx < ctls->count; idx++) {
638 ctrl = ctls->controls + idx;
Ricardo Ribalda082afb72015-10-29 08:10:31 -0200639 cptr = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
640 if (cptr) {
641 if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
642 pvr2_ctrl_get_def(cptr, &val);
643 else
644 ret = pvr2_ctrl_get_value(cptr, &val);
645 } else
646 ret = -EINVAL;
647
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300648 if (ret) {
649 ctls->error_idx = idx;
650 return ret;
651 }
652 /* Ensure that if read as a 64 bit value, the user
653 will still get a hopefully sane value */
654 ctrl->value64 = 0;
655 ctrl->value = val;
656 }
657 return 0;
658}
659
660static int pvr2_s_ext_ctrls(struct file *file, void *priv,
661 struct v4l2_ext_controls *ctls)
662{
663 struct pvr2_v4l2_fh *fh = file->private_data;
664 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
665 struct v4l2_ext_control *ctrl;
666 unsigned int idx;
667 int ret;
668
Ricardo Ribalda082afb72015-10-29 08:10:31 -0200669 /* Default value cannot be changed */
670 if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
671 return -EINVAL;
672
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300673 ret = 0;
674 for (idx = 0; idx < ctls->count; idx++) {
675 ctrl = ctls->controls + idx;
676 ret = pvr2_ctrl_set_value(
677 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
678 ctrl->value);
679 if (ret) {
680 ctls->error_idx = idx;
681 return ret;
682 }
683 }
684 return 0;
685}
686
687static int pvr2_try_ext_ctrls(struct file *file, void *priv,
688 struct v4l2_ext_controls *ctls)
689{
690 struct pvr2_v4l2_fh *fh = file->private_data;
691 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
692 struct v4l2_ext_control *ctrl;
693 struct pvr2_ctrl *pctl;
694 unsigned int idx;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300695
696 /* For the moment just validate that the requested control
697 actually exists. */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300698 for (idx = 0; idx < ctls->count; idx++) {
699 ctrl = ctls->controls + idx;
700 pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
701 if (!pctl) {
702 ctls->error_idx = idx;
703 return -EINVAL;
704 }
705 }
706 return 0;
707}
708
709static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
710{
711 struct pvr2_v4l2_fh *fh = file->private_data;
712 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
713 int ret;
714
715 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
716 return -EINVAL;
717 ret = pvr2_hdw_get_cropcap(hdw, cap);
718 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
719 return ret;
720}
721
Hans Verkuil1f981a42016-07-03 08:14:17 -0300722static int pvr2_g_selection(struct file *file, void *priv,
723 struct v4l2_selection *sel)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300724{
725 struct pvr2_v4l2_fh *fh = file->private_data;
726 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuil1f981a42016-07-03 08:14:17 -0300727 struct v4l2_cropcap cap;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300728 int val = 0;
729 int ret;
730
Hans Verkuil1f981a42016-07-03 08:14:17 -0300731 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300732 return -EINVAL;
Hans Verkuil1f981a42016-07-03 08:14:17 -0300733
734 cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
735
736 switch (sel->target) {
737 case V4L2_SEL_TGT_CROP:
738 ret = pvr2_ctrl_get_value(
739 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
740 if (ret != 0)
741 return -EINVAL;
742 sel->r.left = val;
743 ret = pvr2_ctrl_get_value(
744 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
745 if (ret != 0)
746 return -EINVAL;
747 sel->r.top = val;
748 ret = pvr2_ctrl_get_value(
749 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
750 if (ret != 0)
751 return -EINVAL;
752 sel->r.width = val;
753 ret = pvr2_ctrl_get_value(
754 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
755 if (ret != 0)
756 return -EINVAL;
757 sel->r.height = val;
758 break;
759 case V4L2_SEL_TGT_CROP_DEFAULT:
760 ret = pvr2_hdw_get_cropcap(hdw, &cap);
761 sel->r = cap.defrect;
762 break;
763 case V4L2_SEL_TGT_CROP_BOUNDS:
764 ret = pvr2_hdw_get_cropcap(hdw, &cap);
765 sel->r = cap.bounds;
766 break;
767 default:
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300768 return -EINVAL;
Hans Verkuil1f981a42016-07-03 08:14:17 -0300769 }
770 return ret;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300771}
772
Hans Verkuil1f981a42016-07-03 08:14:17 -0300773static int pvr2_s_selection(struct file *file, void *priv,
774 struct v4l2_selection *sel)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300775{
776 struct pvr2_v4l2_fh *fh = file->private_data;
777 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300778 int ret;
779
Hans Verkuil1f981a42016-07-03 08:14:17 -0300780 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
781 sel->target != V4L2_SEL_TGT_CROP)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300782 return -EINVAL;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300783 ret = pvr2_ctrl_set_value(
784 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
Hans Verkuil1f981a42016-07-03 08:14:17 -0300785 sel->r.left);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300786 if (ret != 0)
787 return -EINVAL;
788 ret = pvr2_ctrl_set_value(
789 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
Hans Verkuil1f981a42016-07-03 08:14:17 -0300790 sel->r.top);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300791 if (ret != 0)
792 return -EINVAL;
793 ret = pvr2_ctrl_set_value(
794 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
Hans Verkuil1f981a42016-07-03 08:14:17 -0300795 sel->r.width);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300796 if (ret != 0)
797 return -EINVAL;
798 ret = pvr2_ctrl_set_value(
799 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
Hans Verkuil1f981a42016-07-03 08:14:17 -0300800 sel->r.height);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300801 if (ret != 0)
802 return -EINVAL;
803 return 0;
804}
805
806static int pvr2_log_status(struct file *file, void *priv)
807{
808 struct pvr2_v4l2_fh *fh = file->private_data;
809 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
810
811 pvr2_hdw_trigger_module_log(hdw);
812 return 0;
813}
814
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300815static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
816 .vidioc_querycap = pvr2_querycap,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300817 .vidioc_s_audio = pvr2_s_audio,
818 .vidioc_g_audio = pvr2_g_audio,
819 .vidioc_enumaudio = pvr2_enumaudio,
820 .vidioc_enum_input = pvr2_enum_input,
821 .vidioc_cropcap = pvr2_cropcap,
Hans Verkuil1f981a42016-07-03 08:14:17 -0300822 .vidioc_s_selection = pvr2_s_selection,
823 .vidioc_g_selection = pvr2_g_selection,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300824 .vidioc_g_input = pvr2_g_input,
825 .vidioc_s_input = pvr2_s_input,
826 .vidioc_g_frequency = pvr2_g_frequency,
827 .vidioc_s_frequency = pvr2_s_frequency,
828 .vidioc_s_tuner = pvr2_s_tuner,
829 .vidioc_g_tuner = pvr2_g_tuner,
830 .vidioc_g_std = pvr2_g_std,
831 .vidioc_s_std = pvr2_s_std,
Mike Isely0927ee62012-02-20 02:26:06 -0300832 .vidioc_querystd = pvr2_querystd,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300833 .vidioc_log_status = pvr2_log_status,
834 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
835 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
836 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
837 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
838 .vidioc_streamon = pvr2_streamon,
839 .vidioc_streamoff = pvr2_streamoff,
840 .vidioc_queryctrl = pvr2_queryctrl,
841 .vidioc_querymenu = pvr2_querymenu,
842 .vidioc_g_ctrl = pvr2_g_ctrl,
843 .vidioc_s_ctrl = pvr2_s_ctrl,
844 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
845 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
846 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300847};
848
Mike Iselyd8554972006-06-26 20:58:46 -0300849static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
850{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300851 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300852 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300853 char msg[80];
854 unsigned int mcnt;
855
856 /* Construct the unregistration message *before* we actually
857 perform the unregistration step. By doing it this way we don't
858 have to worry about potentially touching deleted resources. */
859 mcnt = scnprintf(msg, sizeof(msg) - 1,
860 "pvrusb2: unregistered device %s [%s]",
861 video_device_node_name(&dip->devbase),
862 pvr2_config_get_name(cfg));
863 msg[mcnt] = 0;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300864
Mike Isely16eb40d2006-12-30 18:27:32 -0300865 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300866
867 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300868 dip->v4lp = NULL;
869 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300870
871 /* Actual deallocation happens later when all internal references
872 are gone. */
873 video_unregister_device(&dip->devbase);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300874
Mike Iselyd72baad2010-05-15 00:15:38 -0300875 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300876
Mike Iselyd8554972006-06-26 20:58:46 -0300877}
878
879
Mike Isely4a89baa2009-10-12 00:13:28 -0300880static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
881{
882 if (!dip) return;
Hans Verkuila28fbd02013-06-10 09:16:25 -0300883 if (!dip->devbase.v4l2_dev->dev) return;
884 dip->devbase.v4l2_dev->dev = NULL;
Mike Isely4a89baa2009-10-12 00:13:28 -0300885 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
886}
887
888
Mike Iselyd8554972006-06-26 20:58:46 -0300889static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
890{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300891 if (vp->dev_video) {
892 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000893 vp->dev_video = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300894 }
895 if (vp->dev_radio) {
896 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000897 vp->dev_radio = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300898 }
Mike Iselyd8554972006-06-26 20:58:46 -0300899
900 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
901 pvr2_channel_done(&vp->channel);
902 kfree(vp);
903}
904
905
Mike Isely75910052006-09-23 22:30:50 -0300906static void pvr2_video_device_release(struct video_device *vdev)
907{
908 struct pvr2_v4l2_dev *dev;
909 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
910 kfree(dev);
911}
912
913
Adrian Bunk07e337e2006-06-30 11:30:20 -0300914static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300915{
916 struct pvr2_v4l2 *vp;
917 vp = container_of(chp,struct pvr2_v4l2,channel);
918 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300919 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
920 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300921 if (!list_empty(&vp->dev_video->devbase.fh_list) ||
922 !list_empty(&vp->dev_radio->devbase.fh_list))
923 return;
Mike Iselyd8554972006-06-26 20:58:46 -0300924 pvr2_v4l2_destroy_no_lock(vp);
925}
926
927
Hans Verkuil069b7472008-12-30 07:04:34 -0300928static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300929 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300930{
931
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300932 struct pvr2_v4l2_fh *fh = file->private_data;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300933 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
934 long ret = -EINVAL;
935
936 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
Hans Verkuil4a085162012-06-22 06:38:06 -0300937 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300938
939 if (!pvr2_hdw_dev_ok(hdw)) {
940 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
941 "ioctl failed - bad or no context");
942 return -EFAULT;
943 }
944
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300945 ret = video_ioctl2(file, cmd, arg);
946
947 pvr2_hdw_commit_ctl(hdw);
948
949 if (ret < 0) {
950 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
951 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Andrey Utkin599bc362014-07-10 09:32:25 -0300952 "pvr2_v4l2_do_ioctl failure, ret=%ld"
953 " command was:", ret);
954 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300955 }
956 } else {
957 pvr2_trace(PVR2_TRACE_V4LIOCTL,
958 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
959 ret, ret);
960 }
961 return ret;
962
Mike Iselyd8554972006-06-26 20:58:46 -0300963}
964
965
Hans Verkuilbec43662008-12-30 06:58:20 -0300966static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300967{
968 struct pvr2_v4l2_fh *fhp = file->private_data;
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300969 struct pvr2_v4l2 *vp = fhp->pdi->v4lp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300970 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300971
972 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
973
974 if (fhp->rhp) {
975 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300976 pvr2_hdw_set_streaming(hdw,0);
977 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300978 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300979 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300980 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300981 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300982
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300983 v4l2_fh_del(&fhp->fh);
984 v4l2_fh_exit(&fhp->fh);
Mike Iselyd8554972006-06-26 20:58:46 -0300985 file->private_data = NULL;
986
Mike Isely794b1602008-04-22 14:45:45 -0300987 pvr2_channel_done(&fhp->channel);
988 pvr2_trace(PVR2_TRACE_STRUCT,
989 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -0300990 if (fhp->input_map) {
991 kfree(fhp->input_map);
992 fhp->input_map = NULL;
993 }
Mike Isely794b1602008-04-22 14:45:45 -0300994 kfree(fhp);
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300995 if (vp->channel.mc_head->disconnect_flag &&
996 list_empty(&vp->dev_video->devbase.fh_list) &&
997 list_empty(&vp->dev_radio->devbase.fh_list)) {
Mike Isely794b1602008-04-22 14:45:45 -0300998 pvr2_v4l2_destroy_no_lock(vp);
999 }
Mike Iselyd8554972006-06-26 20:58:46 -03001000 return 0;
1001}
1002
1003
Hans Verkuilbec43662008-12-30 06:58:20 -03001004static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001005{
Mike Isely75910052006-09-23 22:30:50 -03001006 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001007 struct pvr2_v4l2_fh *fhp;
1008 struct pvr2_v4l2 *vp;
1009 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001010 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001011 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001012 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001013
Mike Isely75910052006-09-23 22:30:50 -03001014 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001015
1016 vp = dip->v4lp;
1017 hdw = vp->channel.hdw;
1018
1019 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1020
1021 if (!pvr2_hdw_dev_ok(hdw)) {
1022 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1023 "pvr2_v4l2_open: hardware not ready");
1024 return -EIO;
1025 }
1026
Mike Isely4b85dee2007-01-20 00:03:32 -03001027 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001028 if (!fhp) {
1029 return -ENOMEM;
1030 }
Mike Iselyd8554972006-06-26 20:58:46 -03001031
Hans Verkuilcee05cb2015-02-03 10:46:55 -03001032 v4l2_fh_init(&fhp->fh, &dip->devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001033 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001034 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001035
Mike Isely794b1602008-04-22 14:45:45 -03001036 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1037 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001038
Mike Isely1cb03b72008-04-21 03:47:43 -03001039 if (dip->v4l_type == VFL_TYPE_RADIO) {
1040 /* Opening device as a radio, legal input selection subset
1041 is just the radio. */
1042 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1043 } else {
1044 /* Opening the main V4L device, legal input selection
1045 subset includes all analog inputs. */
1046 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1047 (1 << PVR2_CVAL_INPUT_TV) |
1048 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1049 (1 << PVR2_CVAL_INPUT_SVIDEO));
1050 }
1051 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1052 if (ret) {
1053 pvr2_channel_done(&fhp->channel);
1054 pvr2_trace(PVR2_TRACE_STRUCT,
1055 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1056 fhp);
1057
1058 kfree(fhp);
1059 return ret;
1060 }
1061
Mike Iselye57b1c82008-04-21 03:52:34 -03001062 input_mask &= pvr2_hdw_get_input_available(hdw);
1063 input_cnt = 0;
1064 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1065 if (input_mask & (1 << idx)) input_cnt++;
1066 }
1067 fhp->input_cnt = input_cnt;
1068 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1069 if (!fhp->input_map) {
1070 pvr2_channel_done(&fhp->channel);
1071 pvr2_trace(PVR2_TRACE_STRUCT,
1072 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1073 fhp);
1074 kfree(fhp);
1075 return -ENOMEM;
1076 }
1077 input_cnt = 0;
1078 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1079 if (!(input_mask & (1 << idx))) continue;
1080 fhp->input_map[input_cnt++] = idx;
1081 }
1082
Mike Iselyd8554972006-06-26 20:58:46 -03001083 fhp->file = file;
1084 file->private_data = fhp;
Mike Iselyd8554972006-06-26 20:58:46 -03001085
1086 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
Hans Verkuilcee05cb2015-02-03 10:46:55 -03001087 v4l2_fh_add(&fhp->fh);
Mike Iselyd8554972006-06-26 20:58:46 -03001088
1089 return 0;
1090}
1091
1092
1093static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1094{
1095 wake_up(&fhp->wait_data);
1096}
1097
1098static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1099{
1100 int ret;
1101 struct pvr2_stream *sp;
1102 struct pvr2_hdw *hdw;
1103 if (fh->rhp) return 0;
1104
Joe Perches108bdd72010-04-05 16:05:39 -03001105 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001106 /* No stream defined for this node. This means that we're
1107 not currently allowed to stream from this node. */
1108 return -EPERM;
1109 }
1110
Mike Iselyd8554972006-06-26 20:58:46 -03001111 /* First read() attempt. Try to claim the stream and start
1112 it... */
1113 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001114 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001115 /* Someone else must already have it */
1116 return ret;
1117 }
1118
Joe Perches108bdd72010-04-05 16:05:39 -03001119 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001120 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001121 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001122 return -ENOMEM;
1123 }
1124
1125 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001126 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001127 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001128 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001129 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1130 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001131}
1132
1133
1134static ssize_t pvr2_v4l2_read(struct file *file,
1135 char __user *buff, size_t count, loff_t *ppos)
1136{
1137 struct pvr2_v4l2_fh *fh = file->private_data;
1138 int ret;
1139
1140 if (fh->fw_mode_flag) {
1141 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1142 char *tbuf;
1143 int c1,c2;
1144 int tcnt = 0;
1145 unsigned int offs = *ppos;
1146
1147 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1148 if (!tbuf) return -ENOMEM;
1149
1150 while (count) {
1151 c1 = count;
1152 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1153 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1154 if (c2 < 0) {
1155 tcnt = c2;
1156 break;
1157 }
1158 if (!c2) break;
1159 if (copy_to_user(buff,tbuf,c2)) {
1160 tcnt = -EFAULT;
1161 break;
1162 }
1163 offs += c2;
1164 tcnt += c2;
1165 buff += c2;
1166 count -= c2;
1167 *ppos += c2;
1168 }
1169 kfree(tbuf);
1170 return tcnt;
1171 }
1172
1173 if (!fh->rhp) {
1174 ret = pvr2_v4l2_iosetup(fh);
1175 if (ret) {
1176 return ret;
1177 }
1178 }
1179
1180 for (;;) {
1181 ret = pvr2_ioread_read(fh->rhp,buff,count);
1182 if (ret >= 0) break;
1183 if (ret != -EAGAIN) break;
1184 if (file->f_flags & O_NONBLOCK) break;
1185 /* Doing blocking I/O. Wait here. */
1186 ret = wait_event_interruptible(
1187 fh->wait_data,
1188 pvr2_ioread_avail(fh->rhp) >= 0);
1189 if (ret < 0) break;
1190 }
1191
1192 return ret;
1193}
1194
1195
1196static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1197{
1198 unsigned int mask = 0;
1199 struct pvr2_v4l2_fh *fh = file->private_data;
1200 int ret;
1201
1202 if (fh->fw_mode_flag) {
1203 mask |= POLLIN | POLLRDNORM;
1204 return mask;
1205 }
1206
1207 if (!fh->rhp) {
1208 ret = pvr2_v4l2_iosetup(fh);
1209 if (ret) return POLLERR;
1210 }
1211
1212 poll_wait(file,&fh->wait_data,wait);
1213
1214 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1215 mask |= POLLIN | POLLRDNORM;
1216 }
1217
1218 return mask;
1219}
1220
1221
Hans Verkuilbec43662008-12-30 06:58:20 -03001222static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001223 .owner = THIS_MODULE,
1224 .open = pvr2_v4l2_open,
1225 .release = pvr2_v4l2_release,
1226 .read = pvr2_v4l2_read,
Hans Verkuilab91c612015-02-17 05:44:04 -03001227 .unlocked_ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001228 .poll = pvr2_v4l2_poll,
1229};
1230
1231
Mike Iselyd8554972006-06-26 20:58:46 -03001232static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001233 .fops = &vdev_fops,
1234};
1235
1236
1237static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1238 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001239 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001240{
1241 int mindevnum;
1242 int unit_number;
Mike Isely598e9782012-02-20 02:35:20 -03001243 struct pvr2_hdw *hdw;
Al Viro89952d12007-03-14 09:17:59 +00001244 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001245 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001246
Mike Isely598e9782012-02-20 02:35:20 -03001247 hdw = vp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -03001248 dip->v4l_type = v4l_type;
1249 switch (v4l_type) {
1250 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001251 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001252 dip->config = pvr2_config_mpeg;
1253 dip->minor_type = pvr2_v4l_type_video;
1254 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001255 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001256 pr_err(KBUILD_MODNAME
1257 ": Failed to set up pvrusb2 v4l video dev"
1258 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001259 return;
1260 }
Mike Iselyd8554972006-06-26 20:58:46 -03001261 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001262 case VFL_TYPE_VBI:
1263 dip->config = pvr2_config_vbi;
1264 dip->minor_type = pvr2_v4l_type_vbi;
1265 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001266 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001267 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001268 dip->stream = &vp->channel.mc_head->video_stream;
1269 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001270 dip->minor_type = pvr2_v4l_type_radio;
1271 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001272 break;
1273 default:
1274 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001275 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1276 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001277 return;
1278 }
1279
Ezequiel Garcia5338c162012-10-23 15:57:09 -03001280 dip->devbase = vdev_template;
Mike Isely75910052006-09-23 22:30:50 -03001281 dip->devbase.release = pvr2_video_device_release;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -03001282 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
Mike Iselyd8329f82012-02-20 02:33:06 -03001283 {
1284 int val;
1285 pvr2_ctrl_get_value(
Mike Isely598e9782012-02-20 02:35:20 -03001286 pvr2_hdw_get_ctrl_by_id(hdw,
Mike Iselyd8329f82012-02-20 02:33:06 -03001287 PVR2_CID_STDAVAIL), &val);
1288 dip->devbase.tvnorms = (v4l2_std_id)val;
1289 }
Mike Iselyd8554972006-06-26 20:58:46 -03001290
1291 mindevnum = -1;
Mike Isely598e9782012-02-20 02:35:20 -03001292 unit_number = pvr2_hdw_get_unit_number(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001293 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1294 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001295 }
Hans Verkuila28fbd02013-06-10 09:16:25 -03001296 pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase);
Mike Isely16eb40d2006-12-30 18:27:32 -03001297 if ((video_register_device(&dip->devbase,
1298 dip->v4l_type, mindevnum) < 0) &&
1299 (video_register_device(&dip->devbase,
1300 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001301 pr_err(KBUILD_MODNAME
1302 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001303 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001304
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001305 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1306 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001307 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001308
Mike Isely598e9782012-02-20 02:35:20 -03001309 pvr2_hdw_v4l_store_minor_number(hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001310 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001311}
1312
1313
1314struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1315{
1316 struct pvr2_v4l2 *vp;
1317
Mike Isely4b85dee2007-01-20 00:03:32 -03001318 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001319 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001320 pvr2_channel_init(&vp->channel,mnp);
1321 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1322
1323 vp->channel.check_func = pvr2_v4l2_internal_check;
1324
1325 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001326 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1327 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001328 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001329 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1330 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001331 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1332 if (!vp->dev_radio) goto fail;
1333 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1334 }
Mike Iselyd8554972006-06-26 20:58:46 -03001335
1336 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001337 fail:
1338 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1339 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001340 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001341}