blob: 864830d4c74129a9c038b971dc890feeaa3efcbc [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 *
Mike Iselyd8554972006-06-26 20:58:46 -030016 */
17
18#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090019#include <linux/slab.h>
Mike Iselyd8554972006-06-26 20:58:46 -030020#include "pvrusb2-context.h"
21#include "pvrusb2-hdw.h"
22#include "pvrusb2.h"
23#include "pvrusb2-debug.h"
24#include "pvrusb2-v4l2.h"
25#include "pvrusb2-ioread.h"
26#include <linux/videodev2.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040027#include <linux/module.h>
Mike Isely43e06022006-09-23 23:47:50 -030028#include <media/v4l2-dev.h>
Hans Verkuila28fbd02013-06-10 09:16:25 -030029#include <media/v4l2-device.h>
Hans Verkuilcee05cb2015-02-03 10:46:55 -030030#include <media/v4l2-fh.h>
Mike Iselyd8554972006-06-26 20:58:46 -030031#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030032#include <media/v4l2-ioctl.h>
Mike Iselyd8554972006-06-26 20:58:46 -030033
34struct pvr2_v4l2_dev;
35struct pvr2_v4l2_fh;
36struct pvr2_v4l2;
37
Mike Iselyd8554972006-06-26 20:58:46 -030038struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030039 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030040 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030041 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030042 /* Information about this device: */
43 enum pvr2_config config; /* Expected stream format */
44 int v4l_type; /* V4L defined type for this device node */
45 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030046};
47
48struct pvr2_v4l2_fh {
Hans Verkuilcee05cb2015-02-03 10:46:55 -030049 struct v4l2_fh fh;
Mike Iselyd8554972006-06-26 20:58:46 -030050 struct pvr2_channel channel;
Joe Perches108bdd72010-04-05 16:05:39 -030051 struct pvr2_v4l2_dev *pdi;
Mike Iselyd8554972006-06-26 20:58:46 -030052 struct pvr2_ioread *rhp;
53 struct file *file;
Mike Iselyd8554972006-06-26 20:58:46 -030054 wait_queue_head_t wait_data;
55 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030056 /* Map contiguous ordinal value to input id */
57 unsigned char *input_map;
58 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030059};
60
61struct pvr2_v4l2 {
62 struct pvr2_channel channel;
Mike Iselyd8554972006-06-26 20:58:46 -030063
Mike Isely0f0f257b2006-12-27 23:19:42 -030064 /* streams - Note that these must be separately, individually,
65 * allocated pointers. This is because the v4l core is going to
66 * manage their deletion - separately, individually... */
67 struct pvr2_v4l2_dev *dev_video;
68 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030069};
70
71static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
72module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030073MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
74static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
75module_param_array(radio_nr, int, NULL, 0444);
76MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
77static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
78module_param_array(vbi_nr, int, NULL, 0444);
79MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030080
Adrian Bunk07e337e2006-06-30 11:30:20 -030081static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -030082 {
83 .index = 0,
84 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
85 .flags = V4L2_FMT_FLAG_COMPRESSED,
86 .description = "MPEG1/2",
87 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
88 // breaks when I do that.
89 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
Mike Iselyd8554972006-06-26 20:58:46 -030090 }
91};
92
93#define PVR_FORMAT_PIX 0
94#define PVR_FORMAT_VBI 1
95
Adrian Bunk07e337e2006-06-30 11:30:20 -030096static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -030097 [PVR_FORMAT_PIX] = {
98 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
99 .fmt = {
100 .pix = {
101 .width = 720,
102 .height = 576,
103 // This should really be V4L2_PIX_FMT_MPEG,
104 // but xawtv breaks when I do that.
105 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
106 .field = V4L2_FIELD_INTERLACED,
107 .bytesperline = 0, // doesn't make sense
108 // here
109 //FIXME : Don't know what to put here...
110 .sizeimage = (32*1024),
111 .colorspace = 0, // doesn't make sense here
112 .priv = 0
113 }
114 }
115 },
116 [PVR_FORMAT_VBI] = {
117 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
118 .fmt = {
119 .vbi = {
120 .sampling_rate = 27000000,
121 .offset = 248,
122 .samples_per_line = 1443,
123 .sample_format = V4L2_PIX_FMT_GREY,
124 .start = { 0, 0 },
125 .count = { 0, 0 },
126 .flags = 0,
Mike Iselyd8554972006-06-26 20:58:46 -0300127 }
128 }
129 }
130};
131
Mike Isely16eb40d2006-12-30 18:27:32 -0300132
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300133
Mike Iselyd8554972006-06-26 20:58:46 -0300134/*
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300135 * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
Mike Iselyd8554972006-06-26 20:58:46 -0300136 */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300137static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
138{
139 struct pvr2_v4l2_fh *fh = file->private_data;
140 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
141
Hans Verkuil42639f62015-01-19 06:23:26 -0300142 strlcpy(cap->driver, "pvrusb2", sizeof(cap->driver));
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300143 strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
144 sizeof(cap->bus_info));
145 strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
Hans Verkuil42639f62015-01-19 06:23:26 -0300146 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
147 V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
148 V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS;
149 switch (fh->pdi->devbase.vfl_type) {
150 case VFL_TYPE_GRABBER:
151 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO;
152 break;
153 case VFL_TYPE_RADIO:
154 cap->device_caps = V4L2_CAP_RADIO;
155 break;
Mauro Carvalho Chehab4839c582017-09-28 18:39:32 -0400156 default:
157 return -EINVAL;
Hans Verkuil42639f62015-01-19 06:23:26 -0300158 }
159 cap->device_caps |= V4L2_CAP_TUNER | V4L2_CAP_READWRITE;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300160 return 0;
161}
162
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300163static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
164{
165 struct pvr2_v4l2_fh *fh = file->private_data;
Mike Iselyd8554972006-06-26 20:58:46 -0300166 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300167 int val = 0;
168 int ret;
Mike Iselyd8554972006-06-26 20:58:46 -0300169
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300170 ret = pvr2_ctrl_get_value(
171 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
172 *std = val;
173 return ret;
174}
Mike Iselyd8554972006-06-26 20:58:46 -0300175
Hans Verkuil314527a2013-03-15 06:10:40 -0300176static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300177{
178 struct pvr2_v4l2_fh *fh = file->private_data;
179 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300180
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300181 return pvr2_ctrl_set_value(
Hans Verkuil314527a2013-03-15 06:10:40 -0300182 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300183}
Mike Iselyd8554972006-06-26 20:58:46 -0300184
Mike Isely0927ee62012-02-20 02:26:06 -0300185static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
186{
187 struct pvr2_v4l2_fh *fh = file->private_data;
188 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyac04d002012-02-20 02:28:56 -0300189 int val = 0;
190 int ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300191
Mike Iselyac04d002012-02-20 02:28:56 -0300192 ret = pvr2_ctrl_get_value(
193 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
194 *std = val;
195 return ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300196}
197
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300198static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
199{
200 struct pvr2_v4l2_fh *fh = file->private_data;
201 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
202 struct pvr2_ctrl *cptr;
203 struct v4l2_input tmp;
204 unsigned int cnt;
205 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300206
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300207 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
Mike Iselyd8554972006-06-26 20:58:46 -0300208
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300209 memset(&tmp, 0, sizeof(tmp));
210 tmp.index = vi->index;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300211 if (vi->index >= fh->input_cnt)
212 return -EINVAL;
213 val = fh->input_map[vi->index];
214 switch (val) {
215 case PVR2_CVAL_INPUT_TV:
216 case PVR2_CVAL_INPUT_DTV:
217 case PVR2_CVAL_INPUT_RADIO:
218 tmp.type = V4L2_INPUT_TYPE_TUNER;
Mike Iselyd8554972006-06-26 20:58:46 -0300219 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300220 case PVR2_CVAL_INPUT_SVIDEO:
221 case PVR2_CVAL_INPUT_COMPOSITE:
222 tmp.type = V4L2_INPUT_TYPE_CAMERA;
Mike Iselyd8554972006-06-26 20:58:46 -0300223 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300224 default:
225 return -EINVAL;
Mike Iselyd8554972006-06-26 20:58:46 -0300226 }
227
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300228 cnt = 0;
229 pvr2_ctrl_get_valname(cptr, val,
230 tmp.name, sizeof(tmp.name) - 1, &cnt);
231 tmp.name[cnt] = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300232
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300233 /* Don't bother with audioset, since this driver currently
234 always switches the audio whenever the video is
235 switched. */
Mike Iselyd8554972006-06-26 20:58:46 -0300236
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300237 /* Handling std is a tougher problem. It doesn't make
238 sense in cases where a device might be multi-standard.
239 We could just copy out the current value for the
240 standard, but it can change over time. For now just
241 leave it zero. */
242 *vi = tmp;
243 return 0;
244}
Mike Iselyd8554972006-06-26 20:58:46 -0300245
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300246static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
247{
248 struct pvr2_v4l2_fh *fh = file->private_data;
249 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
250 unsigned int idx;
251 struct pvr2_ctrl *cptr;
252 int val;
253 int ret;
Mauro Carvalho Chehab7383a472011-10-03 12:22:28 -0300254
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300255 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
256 val = 0;
257 ret = pvr2_ctrl_get_value(cptr, &val);
258 *i = 0;
259 for (idx = 0; idx < fh->input_cnt; idx++) {
260 if (fh->input_map[idx] == val) {
261 *i = idx;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300262 break;
263 }
Mike Iselyd8554972006-06-26 20:58:46 -0300264 }
265 return ret;
266}
267
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300268static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
269{
270 struct pvr2_v4l2_fh *fh = file->private_data;
271 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
272
273 if (inp >= fh->input_cnt)
274 return -EINVAL;
275 return pvr2_ctrl_set_value(
276 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
277 fh->input_map[inp]);
278}
279
280static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
281{
282 /* pkt: FIXME: We are returning one "fake" input here
283 which could very well be called "whatever_we_like".
284 This is for apps that want to see an audio input
285 just to feel comfortable, as well as to test if
286 it can do stereo or sth. There is actually no guarantee
287 that the actual audio input cannot change behind the app's
288 back, but most applications should not mind that either.
289
290 Hopefully, mplayer people will work with us on this (this
291 whole mess is to support mplayer pvr://), or Hans will come
292 up with a more standard way to say "we have inputs but we
293 don 't want you to change them independent of video" which
294 will sort this mess.
295 */
296
297 if (vin->index > 0)
298 return -EINVAL;
299 strncpy(vin->name, "PVRUSB2 Audio", 14);
300 vin->capability = V4L2_AUDCAP_STEREO;
301 return 0;
302}
303
304static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
305{
306 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
307 vin->index = 0;
308 strncpy(vin->name, "PVRUSB2 Audio", 14);
309 vin->capability = V4L2_AUDCAP_STEREO;
310 return 0;
311}
312
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300313static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300314{
315 if (vout->index)
316 return -EINVAL;
317 return 0;
318}
319
320static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
321{
322 struct pvr2_v4l2_fh *fh = file->private_data;
323 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
324
325 if (vt->index != 0)
326 return -EINVAL; /* Only answer for the 1st tuner */
327
328 pvr2_hdw_execute_tuner_poll(hdw);
329 return pvr2_hdw_get_tuner_status(hdw, vt);
330}
331
Hans Verkuil2f73c7c2013-03-15 06:10:06 -0300332static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300333{
334 struct pvr2_v4l2_fh *fh = file->private_data;
335 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
336
337 if (vt->index != 0)
338 return -EINVAL;
339
340 return pvr2_ctrl_set_value(
341 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
342 vt->audmode);
343}
344
Hans Verkuilb530a442013-03-19 04:09:26 -0300345static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300346{
347 struct pvr2_v4l2_fh *fh = file->private_data;
348 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
349 unsigned long fv;
350 struct v4l2_tuner vt;
351 int cur_input;
352 struct pvr2_ctrl *ctrlp;
353 int ret;
354
355 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
356 if (ret != 0)
357 return ret;
358 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
359 ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
360 if (ret != 0)
361 return ret;
362 if (vf->type == V4L2_TUNER_RADIO) {
363 if (cur_input != PVR2_CVAL_INPUT_RADIO)
364 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
365 } else {
366 if (cur_input == PVR2_CVAL_INPUT_RADIO)
367 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
368 }
369 fv = vf->frequency;
370 if (vt.capability & V4L2_TUNER_CAP_LOW)
371 fv = (fv * 125) / 2;
372 else
373 fv = fv * 62500;
374 return pvr2_ctrl_set_value(
375 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
376}
377
378static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
379{
380 struct pvr2_v4l2_fh *fh = file->private_data;
381 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
382 int val = 0;
383 int cur_input;
384 struct v4l2_tuner vt;
385 int ret;
386
387 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
388 if (ret != 0)
389 return ret;
390 ret = pvr2_ctrl_get_value(
391 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
392 &val);
393 if (ret != 0)
394 return ret;
395 pvr2_ctrl_get_value(
396 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
397 &cur_input);
398 if (cur_input == PVR2_CVAL_INPUT_RADIO)
399 vf->type = V4L2_TUNER_RADIO;
400 else
401 vf->type = V4L2_TUNER_ANALOG_TV;
402 if (vt.capability & V4L2_TUNER_CAP_LOW)
403 val = (val * 2) / 125;
404 else
405 val /= 62500;
406 vf->frequency = val;
407 return 0;
408}
409
410static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
411{
412 /* Only one format is supported : mpeg.*/
413 if (fd->index != 0)
414 return -EINVAL;
415
416 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
417 return 0;
418}
419
420static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
421{
422 struct pvr2_v4l2_fh *fh = file->private_data;
423 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
424 int val;
425
426 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
427 val = 0;
428 pvr2_ctrl_get_value(
429 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
430 &val);
431 vf->fmt.pix.width = val;
432 val = 0;
433 pvr2_ctrl_get_value(
434 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
435 &val);
436 vf->fmt.pix.height = val;
437 return 0;
438}
439
440static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
441{
442 struct pvr2_v4l2_fh *fh = file->private_data;
443 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
444 int lmin, lmax, ldef;
445 struct pvr2_ctrl *hcp, *vcp;
446 int h = vf->fmt.pix.height;
447 int w = vf->fmt.pix.width;
448
449 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
450 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
451
452 lmin = pvr2_ctrl_get_min(hcp);
453 lmax = pvr2_ctrl_get_max(hcp);
454 pvr2_ctrl_get_def(hcp, &ldef);
455 if (w == -1)
456 w = ldef;
457 else if (w < lmin)
458 w = lmin;
459 else if (w > lmax)
460 w = lmax;
461 lmin = pvr2_ctrl_get_min(vcp);
462 lmax = pvr2_ctrl_get_max(vcp);
463 pvr2_ctrl_get_def(vcp, &ldef);
464 if (h == -1)
465 h = ldef;
466 else if (h < lmin)
467 h = lmin;
468 else if (h > lmax)
469 h = lmax;
470
471 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
472 sizeof(struct v4l2_format));
473 vf->fmt.pix.width = w;
474 vf->fmt.pix.height = h;
475 return 0;
476}
477
478static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
479{
480 struct pvr2_v4l2_fh *fh = file->private_data;
481 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
482 struct pvr2_ctrl *hcp, *vcp;
483 int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
484
485 if (ret)
486 return ret;
487 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
488 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
489 pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
490 pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
491 return 0;
492}
493
494static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
495{
496 struct pvr2_v4l2_fh *fh = file->private_data;
497 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
498 struct pvr2_v4l2_dev *pdi = fh->pdi;
499 int ret;
500
501 if (!fh->pdi->stream) {
502 /* No stream defined for this node. This means
503 that we're not currently allowed to stream from
504 this node. */
505 return -EPERM;
506 }
507 ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
508 if (ret < 0)
509 return ret;
510 return pvr2_hdw_set_streaming(hdw, !0);
511}
512
513static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
514{
515 struct pvr2_v4l2_fh *fh = file->private_data;
516 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
517
518 if (!fh->pdi->stream) {
519 /* No stream defined for this node. This means
520 that we're not currently allowed to stream from
521 this node. */
522 return -EPERM;
523 }
524 return pvr2_hdw_set_streaming(hdw, 0);
525}
526
527static int pvr2_queryctrl(struct file *file, void *priv,
528 struct v4l2_queryctrl *vc)
529{
530 struct pvr2_v4l2_fh *fh = file->private_data;
531 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
532 struct pvr2_ctrl *cptr;
533 int val;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300534
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300535 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
536 cptr = pvr2_hdw_get_ctrl_nextv4l(
537 hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
538 if (cptr)
539 vc->id = pvr2_ctrl_get_v4lid(cptr);
540 } else {
541 cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
542 }
543 if (!cptr) {
544 pvr2_trace(PVR2_TRACE_V4LIOCTL,
545 "QUERYCTRL id=0x%x not implemented here",
546 vc->id);
547 return -EINVAL;
548 }
549
550 pvr2_trace(PVR2_TRACE_V4LIOCTL,
551 "QUERYCTRL id=0x%x mapping name=%s (%s)",
552 vc->id, pvr2_ctrl_get_name(cptr),
553 pvr2_ctrl_get_desc(cptr));
554 strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
555 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
556 pvr2_ctrl_get_def(cptr, &val);
557 vc->default_value = val;
558 switch (pvr2_ctrl_get_type(cptr)) {
559 case pvr2_ctl_enum:
560 vc->type = V4L2_CTRL_TYPE_MENU;
561 vc->minimum = 0;
562 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
563 vc->step = 1;
564 break;
565 case pvr2_ctl_bool:
566 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
567 vc->minimum = 0;
568 vc->maximum = 1;
569 vc->step = 1;
570 break;
571 case pvr2_ctl_int:
572 vc->type = V4L2_CTRL_TYPE_INTEGER;
573 vc->minimum = pvr2_ctrl_get_min(cptr);
574 vc->maximum = pvr2_ctrl_get_max(cptr);
575 vc->step = 1;
576 break;
577 default:
578 pvr2_trace(PVR2_TRACE_V4LIOCTL,
579 "QUERYCTRL id=0x%x name=%s not mappable",
580 vc->id, pvr2_ctrl_get_name(cptr));
581 return -EINVAL;
582 }
583 return 0;
584}
585
586static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
587{
588 struct pvr2_v4l2_fh *fh = file->private_data;
589 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
590 unsigned int cnt = 0;
591 int ret;
592
593 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
594 vm->index,
595 vm->name, sizeof(vm->name) - 1,
596 &cnt);
597 vm->name[cnt] = 0;
598 return ret;
599}
600
601static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
602{
603 struct pvr2_v4l2_fh *fh = file->private_data;
604 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
605 int val = 0;
606 int ret;
607
608 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
609 &val);
610 vc->value = val;
611 return ret;
612}
613
614static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
615{
616 struct pvr2_v4l2_fh *fh = file->private_data;
617 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
618
619 return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
620 vc->value);
621}
622
623static int pvr2_g_ext_ctrls(struct file *file, void *priv,
624 struct v4l2_ext_controls *ctls)
625{
626 struct pvr2_v4l2_fh *fh = file->private_data;
627 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
628 struct v4l2_ext_control *ctrl;
Ricardo Ribalda082afb72015-10-29 08:10:31 -0200629 struct pvr2_ctrl *cptr;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300630 unsigned int idx;
631 int val;
632 int ret;
633
634 ret = 0;
635 for (idx = 0; idx < ctls->count; idx++) {
636 ctrl = ctls->controls + idx;
Ricardo Ribalda082afb72015-10-29 08:10:31 -0200637 cptr = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
638 if (cptr) {
639 if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
640 pvr2_ctrl_get_def(cptr, &val);
641 else
642 ret = pvr2_ctrl_get_value(cptr, &val);
643 } else
644 ret = -EINVAL;
645
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300646 if (ret) {
647 ctls->error_idx = idx;
648 return ret;
649 }
650 /* Ensure that if read as a 64 bit value, the user
651 will still get a hopefully sane value */
652 ctrl->value64 = 0;
653 ctrl->value = val;
654 }
655 return 0;
656}
657
658static int pvr2_s_ext_ctrls(struct file *file, void *priv,
659 struct v4l2_ext_controls *ctls)
660{
661 struct pvr2_v4l2_fh *fh = file->private_data;
662 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
663 struct v4l2_ext_control *ctrl;
664 unsigned int idx;
665 int ret;
666
Ricardo Ribalda082afb72015-10-29 08:10:31 -0200667 /* Default value cannot be changed */
668 if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
669 return -EINVAL;
670
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300671 ret = 0;
672 for (idx = 0; idx < ctls->count; idx++) {
673 ctrl = ctls->controls + idx;
674 ret = pvr2_ctrl_set_value(
675 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
676 ctrl->value);
677 if (ret) {
678 ctls->error_idx = idx;
679 return ret;
680 }
681 }
682 return 0;
683}
684
685static int pvr2_try_ext_ctrls(struct file *file, void *priv,
686 struct v4l2_ext_controls *ctls)
687{
688 struct pvr2_v4l2_fh *fh = file->private_data;
689 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
690 struct v4l2_ext_control *ctrl;
691 struct pvr2_ctrl *pctl;
692 unsigned int idx;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300693
694 /* For the moment just validate that the requested control
695 actually exists. */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300696 for (idx = 0; idx < ctls->count; idx++) {
697 ctrl = ctls->controls + idx;
698 pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
699 if (!pctl) {
700 ctls->error_idx = idx;
701 return -EINVAL;
702 }
703 }
704 return 0;
705}
706
707static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
708{
709 struct pvr2_v4l2_fh *fh = file->private_data;
710 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
711 int ret;
712
713 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
714 return -EINVAL;
715 ret = pvr2_hdw_get_cropcap(hdw, cap);
716 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
717 return ret;
718}
719
Hans Verkuil1f981a42016-07-03 08:14:17 -0300720static int pvr2_g_selection(struct file *file, void *priv,
721 struct v4l2_selection *sel)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300722{
723 struct pvr2_v4l2_fh *fh = file->private_data;
724 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuil1f981a42016-07-03 08:14:17 -0300725 struct v4l2_cropcap cap;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300726 int val = 0;
727 int ret;
728
Hans Verkuil1f981a42016-07-03 08:14:17 -0300729 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300730 return -EINVAL;
Hans Verkuil1f981a42016-07-03 08:14:17 -0300731
732 cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
733
734 switch (sel->target) {
735 case V4L2_SEL_TGT_CROP:
736 ret = pvr2_ctrl_get_value(
737 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
738 if (ret != 0)
739 return -EINVAL;
740 sel->r.left = val;
741 ret = pvr2_ctrl_get_value(
742 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
743 if (ret != 0)
744 return -EINVAL;
745 sel->r.top = val;
746 ret = pvr2_ctrl_get_value(
747 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
748 if (ret != 0)
749 return -EINVAL;
750 sel->r.width = val;
751 ret = pvr2_ctrl_get_value(
752 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
753 if (ret != 0)
754 return -EINVAL;
755 sel->r.height = val;
756 break;
757 case V4L2_SEL_TGT_CROP_DEFAULT:
758 ret = pvr2_hdw_get_cropcap(hdw, &cap);
759 sel->r = cap.defrect;
760 break;
761 case V4L2_SEL_TGT_CROP_BOUNDS:
762 ret = pvr2_hdw_get_cropcap(hdw, &cap);
763 sel->r = cap.bounds;
764 break;
765 default:
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300766 return -EINVAL;
Hans Verkuil1f981a42016-07-03 08:14:17 -0300767 }
768 return ret;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300769}
770
Hans Verkuil1f981a42016-07-03 08:14:17 -0300771static int pvr2_s_selection(struct file *file, void *priv,
772 struct v4l2_selection *sel)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300773{
774 struct pvr2_v4l2_fh *fh = file->private_data;
775 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300776 int ret;
777
Hans Verkuil1f981a42016-07-03 08:14:17 -0300778 if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
779 sel->target != V4L2_SEL_TGT_CROP)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300780 return -EINVAL;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300781 ret = pvr2_ctrl_set_value(
782 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
Hans Verkuil1f981a42016-07-03 08:14:17 -0300783 sel->r.left);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300784 if (ret != 0)
785 return -EINVAL;
786 ret = pvr2_ctrl_set_value(
787 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
Hans Verkuil1f981a42016-07-03 08:14:17 -0300788 sel->r.top);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300789 if (ret != 0)
790 return -EINVAL;
791 ret = pvr2_ctrl_set_value(
792 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
Hans Verkuil1f981a42016-07-03 08:14:17 -0300793 sel->r.width);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300794 if (ret != 0)
795 return -EINVAL;
796 ret = pvr2_ctrl_set_value(
797 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
Hans Verkuil1f981a42016-07-03 08:14:17 -0300798 sel->r.height);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300799 if (ret != 0)
800 return -EINVAL;
801 return 0;
802}
803
804static int pvr2_log_status(struct file *file, void *priv)
805{
806 struct pvr2_v4l2_fh *fh = file->private_data;
807 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
808
809 pvr2_hdw_trigger_module_log(hdw);
810 return 0;
811}
812
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300813static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
814 .vidioc_querycap = pvr2_querycap,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300815 .vidioc_s_audio = pvr2_s_audio,
816 .vidioc_g_audio = pvr2_g_audio,
817 .vidioc_enumaudio = pvr2_enumaudio,
818 .vidioc_enum_input = pvr2_enum_input,
819 .vidioc_cropcap = pvr2_cropcap,
Hans Verkuil1f981a42016-07-03 08:14:17 -0300820 .vidioc_s_selection = pvr2_s_selection,
821 .vidioc_g_selection = pvr2_g_selection,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300822 .vidioc_g_input = pvr2_g_input,
823 .vidioc_s_input = pvr2_s_input,
824 .vidioc_g_frequency = pvr2_g_frequency,
825 .vidioc_s_frequency = pvr2_s_frequency,
826 .vidioc_s_tuner = pvr2_s_tuner,
827 .vidioc_g_tuner = pvr2_g_tuner,
828 .vidioc_g_std = pvr2_g_std,
829 .vidioc_s_std = pvr2_s_std,
Mike Isely0927ee62012-02-20 02:26:06 -0300830 .vidioc_querystd = pvr2_querystd,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300831 .vidioc_log_status = pvr2_log_status,
832 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
833 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
834 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
835 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
836 .vidioc_streamon = pvr2_streamon,
837 .vidioc_streamoff = pvr2_streamoff,
838 .vidioc_queryctrl = pvr2_queryctrl,
839 .vidioc_querymenu = pvr2_querymenu,
840 .vidioc_g_ctrl = pvr2_g_ctrl,
841 .vidioc_s_ctrl = pvr2_s_ctrl,
842 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
843 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
844 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300845};
846
Mike Iselyd8554972006-06-26 20:58:46 -0300847static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
848{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300849 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300850 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300851 char msg[80];
852 unsigned int mcnt;
853
854 /* Construct the unregistration message *before* we actually
855 perform the unregistration step. By doing it this way we don't
856 have to worry about potentially touching deleted resources. */
857 mcnt = scnprintf(msg, sizeof(msg) - 1,
858 "pvrusb2: unregistered device %s [%s]",
859 video_device_node_name(&dip->devbase),
860 pvr2_config_get_name(cfg));
861 msg[mcnt] = 0;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300862
Mike Isely16eb40d2006-12-30 18:27:32 -0300863 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300864
865 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300866 dip->v4lp = NULL;
867 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300868
869 /* Actual deallocation happens later when all internal references
870 are gone. */
871 video_unregister_device(&dip->devbase);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300872
Mike Iselyd72baad2010-05-15 00:15:38 -0300873 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300874
Mike Iselyd8554972006-06-26 20:58:46 -0300875}
876
877
Mike Isely4a89baa2009-10-12 00:13:28 -0300878static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
879{
880 if (!dip) return;
Hans Verkuila28fbd02013-06-10 09:16:25 -0300881 if (!dip->devbase.v4l2_dev->dev) return;
882 dip->devbase.v4l2_dev->dev = NULL;
Mike Isely4a89baa2009-10-12 00:13:28 -0300883 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
884}
885
886
Mike Iselyd8554972006-06-26 20:58:46 -0300887static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
888{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300889 if (vp->dev_video) {
890 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000891 vp->dev_video = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300892 }
893 if (vp->dev_radio) {
894 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000895 vp->dev_radio = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300896 }
Mike Iselyd8554972006-06-26 20:58:46 -0300897
898 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
899 pvr2_channel_done(&vp->channel);
900 kfree(vp);
901}
902
903
Mike Isely75910052006-09-23 22:30:50 -0300904static void pvr2_video_device_release(struct video_device *vdev)
905{
906 struct pvr2_v4l2_dev *dev;
907 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
908 kfree(dev);
909}
910
911
Adrian Bunk07e337e2006-06-30 11:30:20 -0300912static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300913{
914 struct pvr2_v4l2 *vp;
915 vp = container_of(chp,struct pvr2_v4l2,channel);
916 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300917 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
918 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300919 if (!list_empty(&vp->dev_video->devbase.fh_list) ||
920 !list_empty(&vp->dev_radio->devbase.fh_list))
921 return;
Mike Iselyd8554972006-06-26 20:58:46 -0300922 pvr2_v4l2_destroy_no_lock(vp);
923}
924
925
Hans Verkuil069b7472008-12-30 07:04:34 -0300926static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300927 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300928{
929
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300930 struct pvr2_v4l2_fh *fh = file->private_data;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300931 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
932 long ret = -EINVAL;
933
934 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
Hans Verkuil4a085162012-06-22 06:38:06 -0300935 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300936
937 if (!pvr2_hdw_dev_ok(hdw)) {
938 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
939 "ioctl failed - bad or no context");
940 return -EFAULT;
941 }
942
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300943 ret = video_ioctl2(file, cmd, arg);
944
945 pvr2_hdw_commit_ctl(hdw);
946
947 if (ret < 0) {
948 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
949 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mauro Carvalho Chehab96292c82016-10-18 17:44:18 -0200950 "pvr2_v4l2_do_ioctl failure, ret=%ld command was:",
951ret);
Andrey Utkin599bc362014-07-10 09:32:25 -0300952 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300953 }
954 } else {
955 pvr2_trace(PVR2_TRACE_V4LIOCTL,
956 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
957 ret, ret);
958 }
959 return ret;
960
Mike Iselyd8554972006-06-26 20:58:46 -0300961}
962
963
Hans Verkuilbec43662008-12-30 06:58:20 -0300964static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300965{
966 struct pvr2_v4l2_fh *fhp = file->private_data;
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300967 struct pvr2_v4l2 *vp = fhp->pdi->v4lp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300968 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300969
970 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
971
972 if (fhp->rhp) {
973 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300974 pvr2_hdw_set_streaming(hdw,0);
975 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300976 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300977 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300978 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300979 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300980
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300981 v4l2_fh_del(&fhp->fh);
982 v4l2_fh_exit(&fhp->fh);
Mike Iselyd8554972006-06-26 20:58:46 -0300983 file->private_data = NULL;
984
Mike Isely794b1602008-04-22 14:45:45 -0300985 pvr2_channel_done(&fhp->channel);
986 pvr2_trace(PVR2_TRACE_STRUCT,
987 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -0300988 if (fhp->input_map) {
989 kfree(fhp->input_map);
990 fhp->input_map = NULL;
991 }
Mike Isely794b1602008-04-22 14:45:45 -0300992 kfree(fhp);
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300993 if (vp->channel.mc_head->disconnect_flag &&
994 list_empty(&vp->dev_video->devbase.fh_list) &&
995 list_empty(&vp->dev_radio->devbase.fh_list)) {
Mike Isely794b1602008-04-22 14:45:45 -0300996 pvr2_v4l2_destroy_no_lock(vp);
997 }
Mike Iselyd8554972006-06-26 20:58:46 -0300998 return 0;
999}
1000
1001
Hans Verkuilbec43662008-12-30 06:58:20 -03001002static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001003{
Mike Isely75910052006-09-23 22:30:50 -03001004 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001005 struct pvr2_v4l2_fh *fhp;
1006 struct pvr2_v4l2 *vp;
1007 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001008 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001009 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001010 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001011
Mike Isely75910052006-09-23 22:30:50 -03001012 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001013
1014 vp = dip->v4lp;
1015 hdw = vp->channel.hdw;
1016
1017 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1018
1019 if (!pvr2_hdw_dev_ok(hdw)) {
1020 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1021 "pvr2_v4l2_open: hardware not ready");
1022 return -EIO;
1023 }
1024
Mike Isely4b85dee2007-01-20 00:03:32 -03001025 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001026 if (!fhp) {
1027 return -ENOMEM;
1028 }
Mike Iselyd8554972006-06-26 20:58:46 -03001029
Hans Verkuilcee05cb2015-02-03 10:46:55 -03001030 v4l2_fh_init(&fhp->fh, &dip->devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001031 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001032 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001033
Mike Isely794b1602008-04-22 14:45:45 -03001034 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1035 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001036
Mike Isely1cb03b72008-04-21 03:47:43 -03001037 if (dip->v4l_type == VFL_TYPE_RADIO) {
1038 /* Opening device as a radio, legal input selection subset
1039 is just the radio. */
1040 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1041 } else {
1042 /* Opening the main V4L device, legal input selection
1043 subset includes all analog inputs. */
1044 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1045 (1 << PVR2_CVAL_INPUT_TV) |
1046 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1047 (1 << PVR2_CVAL_INPUT_SVIDEO));
1048 }
1049 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1050 if (ret) {
1051 pvr2_channel_done(&fhp->channel);
1052 pvr2_trace(PVR2_TRACE_STRUCT,
1053 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1054 fhp);
Santosh Kumar Singh01faa0d2016-12-19 15:20:37 -02001055 v4l2_fh_exit(&fhp->fh);
Mike Isely1cb03b72008-04-21 03:47:43 -03001056 kfree(fhp);
1057 return ret;
1058 }
1059
Mike Iselye57b1c82008-04-21 03:52:34 -03001060 input_mask &= pvr2_hdw_get_input_available(hdw);
1061 input_cnt = 0;
1062 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1063 if (input_mask & (1 << idx)) input_cnt++;
1064 }
1065 fhp->input_cnt = input_cnt;
1066 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1067 if (!fhp->input_map) {
1068 pvr2_channel_done(&fhp->channel);
1069 pvr2_trace(PVR2_TRACE_STRUCT,
1070 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1071 fhp);
Santosh Kumar Singh01faa0d2016-12-19 15:20:37 -02001072 v4l2_fh_exit(&fhp->fh);
Mike Iselye57b1c82008-04-21 03:52:34 -03001073 kfree(fhp);
1074 return -ENOMEM;
1075 }
1076 input_cnt = 0;
1077 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1078 if (!(input_mask & (1 << idx))) continue;
1079 fhp->input_map[input_cnt++] = idx;
1080 }
1081
Mike Iselyd8554972006-06-26 20:58:46 -03001082 fhp->file = file;
1083 file->private_data = fhp;
Mike Iselyd8554972006-06-26 20:58:46 -03001084
1085 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
Hans Verkuilcee05cb2015-02-03 10:46:55 -03001086 v4l2_fh_add(&fhp->fh);
Mike Iselyd8554972006-06-26 20:58:46 -03001087
1088 return 0;
1089}
1090
1091
1092static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1093{
1094 wake_up(&fhp->wait_data);
1095}
1096
1097static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1098{
1099 int ret;
1100 struct pvr2_stream *sp;
1101 struct pvr2_hdw *hdw;
1102 if (fh->rhp) return 0;
1103
Joe Perches108bdd72010-04-05 16:05:39 -03001104 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001105 /* No stream defined for this node. This means that we're
1106 not currently allowed to stream from this node. */
1107 return -EPERM;
1108 }
1109
Mike Iselyd8554972006-06-26 20:58:46 -03001110 /* First read() attempt. Try to claim the stream and start
1111 it... */
1112 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001113 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001114 /* Someone else must already have it */
1115 return ret;
1116 }
1117
Joe Perches108bdd72010-04-05 16:05:39 -03001118 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001119 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001120 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001121 return -ENOMEM;
1122 }
1123
1124 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001125 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001126 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001127 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001128 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1129 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001130}
1131
1132
1133static ssize_t pvr2_v4l2_read(struct file *file,
1134 char __user *buff, size_t count, loff_t *ppos)
1135{
1136 struct pvr2_v4l2_fh *fh = file->private_data;
1137 int ret;
1138
1139 if (fh->fw_mode_flag) {
1140 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1141 char *tbuf;
1142 int c1,c2;
1143 int tcnt = 0;
1144 unsigned int offs = *ppos;
1145
1146 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1147 if (!tbuf) return -ENOMEM;
1148
1149 while (count) {
1150 c1 = count;
1151 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1152 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1153 if (c2 < 0) {
1154 tcnt = c2;
1155 break;
1156 }
1157 if (!c2) break;
1158 if (copy_to_user(buff,tbuf,c2)) {
1159 tcnt = -EFAULT;
1160 break;
1161 }
1162 offs += c2;
1163 tcnt += c2;
1164 buff += c2;
1165 count -= c2;
1166 *ppos += c2;
1167 }
1168 kfree(tbuf);
1169 return tcnt;
1170 }
1171
1172 if (!fh->rhp) {
1173 ret = pvr2_v4l2_iosetup(fh);
1174 if (ret) {
1175 return ret;
1176 }
1177 }
1178
1179 for (;;) {
1180 ret = pvr2_ioread_read(fh->rhp,buff,count);
1181 if (ret >= 0) break;
1182 if (ret != -EAGAIN) break;
1183 if (file->f_flags & O_NONBLOCK) break;
1184 /* Doing blocking I/O. Wait here. */
1185 ret = wait_event_interruptible(
1186 fh->wait_data,
1187 pvr2_ioread_avail(fh->rhp) >= 0);
1188 if (ret < 0) break;
1189 }
1190
1191 return ret;
1192}
1193
1194
1195static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1196{
1197 unsigned int mask = 0;
1198 struct pvr2_v4l2_fh *fh = file->private_data;
1199 int ret;
1200
1201 if (fh->fw_mode_flag) {
1202 mask |= POLLIN | POLLRDNORM;
1203 return mask;
1204 }
1205
1206 if (!fh->rhp) {
1207 ret = pvr2_v4l2_iosetup(fh);
1208 if (ret) return POLLERR;
1209 }
1210
1211 poll_wait(file,&fh->wait_data,wait);
1212
1213 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1214 mask |= POLLIN | POLLRDNORM;
1215 }
1216
1217 return mask;
1218}
1219
1220
Hans Verkuilbec43662008-12-30 06:58:20 -03001221static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001222 .owner = THIS_MODULE,
1223 .open = pvr2_v4l2_open,
1224 .release = pvr2_v4l2_release,
1225 .read = pvr2_v4l2_read,
Hans Verkuilab91c612015-02-17 05:44:04 -03001226 .unlocked_ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001227 .poll = pvr2_v4l2_poll,
1228};
1229
1230
Bhumika Goyal86844942017-08-26 09:11:30 -04001231static const struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001232 .fops = &vdev_fops,
1233};
1234
1235
1236static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1237 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001238 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001239{
1240 int mindevnum;
1241 int unit_number;
Mike Isely598e9782012-02-20 02:35:20 -03001242 struct pvr2_hdw *hdw;
Al Viro89952d12007-03-14 09:17:59 +00001243 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001244 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001245
Mike Isely598e9782012-02-20 02:35:20 -03001246 hdw = vp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -03001247 dip->v4l_type = v4l_type;
1248 switch (v4l_type) {
1249 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001250 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001251 dip->config = pvr2_config_mpeg;
1252 dip->minor_type = pvr2_v4l_type_video;
1253 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001254 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001255 pr_err(KBUILD_MODNAME
Mauro Carvalho Chehab96292c82016-10-18 17:44:18 -02001256 ": Failed to set up pvrusb2 v4l video dev due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001257 return;
1258 }
Mike Iselyd8554972006-06-26 20:58:46 -03001259 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001260 case VFL_TYPE_VBI:
1261 dip->config = pvr2_config_vbi;
1262 dip->minor_type = pvr2_v4l_type_vbi;
1263 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001264 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001265 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001266 dip->stream = &vp->channel.mc_head->video_stream;
1267 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001268 dip->minor_type = pvr2_v4l_type_radio;
1269 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001270 break;
1271 default:
1272 /* Bail out (this should be impossible) */
Mauro Carvalho Chehab96292c82016-10-18 17:44:18 -02001273 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001274 return;
1275 }
1276
Ezequiel Garcia5338c162012-10-23 15:57:09 -03001277 dip->devbase = vdev_template;
Mike Isely75910052006-09-23 22:30:50 -03001278 dip->devbase.release = pvr2_video_device_release;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -03001279 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
Mike Iselyd8329f82012-02-20 02:33:06 -03001280 {
1281 int val;
1282 pvr2_ctrl_get_value(
Mike Isely598e9782012-02-20 02:35:20 -03001283 pvr2_hdw_get_ctrl_by_id(hdw,
Mike Iselyd8329f82012-02-20 02:33:06 -03001284 PVR2_CID_STDAVAIL), &val);
1285 dip->devbase.tvnorms = (v4l2_std_id)val;
1286 }
Mike Iselyd8554972006-06-26 20:58:46 -03001287
1288 mindevnum = -1;
Mike Isely598e9782012-02-20 02:35:20 -03001289 unit_number = pvr2_hdw_get_unit_number(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001290 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1291 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001292 }
Hans Verkuila28fbd02013-06-10 09:16:25 -03001293 pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase);
Mike Isely16eb40d2006-12-30 18:27:32 -03001294 if ((video_register_device(&dip->devbase,
1295 dip->v4l_type, mindevnum) < 0) &&
1296 (video_register_device(&dip->devbase,
1297 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001298 pr_err(KBUILD_MODNAME
1299 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001300 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001301
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001302 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1303 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001304 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001305
Mike Isely598e9782012-02-20 02:35:20 -03001306 pvr2_hdw_v4l_store_minor_number(hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001307 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001308}
1309
1310
1311struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1312{
1313 struct pvr2_v4l2 *vp;
1314
Mike Isely4b85dee2007-01-20 00:03:32 -03001315 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001316 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001317 pvr2_channel_init(&vp->channel,mnp);
1318 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1319
1320 vp->channel.check_func = pvr2_v4l2_internal_check;
1321
1322 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001323 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1324 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001325 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001326 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1327 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001328 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1329 if (!vp->dev_radio) goto fail;
1330 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1331 }
Mike Iselyd8554972006-06-26 20:58:46 -03001332
1333 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001334 fail:
1335 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1336 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001337 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001338}