blob: 802b43b23d0c361d67880da2e9d782230b309351 [file] [log] [blame]
Mike Iselyd8554972006-06-26 20:58:46 -03001/*
2 *
Mike Iselyd8554972006-06-26 20:58:46 -03003 *
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Mauro Carvalho Chehabce4260c2006-06-26 22:26:08 -030024#include <linux/version.h>
Mike Iselyd8554972006-06-26 20:58:46 -030025#include "pvrusb2-context.h"
26#include "pvrusb2-hdw.h"
27#include "pvrusb2.h"
28#include "pvrusb2-debug.h"
29#include "pvrusb2-v4l2.h"
30#include "pvrusb2-ioread.h"
31#include <linux/videodev2.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040032#include <linux/module.h>
Mike Isely43e06022006-09-23 23:47:50 -030033#include <media/v4l2-dev.h>
Hans Verkuila28fbd02013-06-10 09:16:25 -030034#include <media/v4l2-device.h>
Hans Verkuilcee05cb2015-02-03 10:46:55 -030035#include <media/v4l2-fh.h>
Mike Iselyd8554972006-06-26 20:58:46 -030036#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030037#include <media/v4l2-ioctl.h>
Mike Iselyd8554972006-06-26 20:58:46 -030038
39struct pvr2_v4l2_dev;
40struct pvr2_v4l2_fh;
41struct pvr2_v4l2;
42
Mike Iselyd8554972006-06-26 20:58:46 -030043struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030044 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030045 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030046 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030047 /* Information about this device: */
48 enum pvr2_config config; /* Expected stream format */
49 int v4l_type; /* V4L defined type for this device node */
50 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030051};
52
53struct pvr2_v4l2_fh {
Hans Verkuilcee05cb2015-02-03 10:46:55 -030054 struct v4l2_fh fh;
Mike Iselyd8554972006-06-26 20:58:46 -030055 struct pvr2_channel channel;
Joe Perches108bdd72010-04-05 16:05:39 -030056 struct pvr2_v4l2_dev *pdi;
Mike Iselyd8554972006-06-26 20:58:46 -030057 struct pvr2_ioread *rhp;
58 struct file *file;
Mike Iselyd8554972006-06-26 20:58:46 -030059 wait_queue_head_t wait_data;
60 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030061 /* Map contiguous ordinal value to input id */
62 unsigned char *input_map;
63 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030064};
65
66struct pvr2_v4l2 {
67 struct pvr2_channel channel;
Mike Iselyd8554972006-06-26 20:58:46 -030068
Mike Isely0f0f257b2006-12-27 23:19:42 -030069 /* streams - Note that these must be separately, individually,
70 * allocated pointers. This is because the v4l core is going to
71 * manage their deletion - separately, individually... */
72 struct pvr2_v4l2_dev *dev_video;
73 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030074};
75
76static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
77module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030078MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
79static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
80module_param_array(radio_nr, int, NULL, 0444);
81MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
82static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
83module_param_array(vbi_nr, int, NULL, 0444);
84MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030085
Adrian Bunk07e337e2006-06-30 11:30:20 -030086static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -030087 {
88 .index = 0,
89 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
90 .flags = V4L2_FMT_FLAG_COMPRESSED,
91 .description = "MPEG1/2",
92 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
93 // breaks when I do that.
94 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
Mike Iselyd8554972006-06-26 20:58:46 -030095 }
96};
97
98#define PVR_FORMAT_PIX 0
99#define PVR_FORMAT_VBI 1
100
Adrian Bunk07e337e2006-06-30 11:30:20 -0300101static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300102 [PVR_FORMAT_PIX] = {
103 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
104 .fmt = {
105 .pix = {
106 .width = 720,
107 .height = 576,
108 // This should really be V4L2_PIX_FMT_MPEG,
109 // but xawtv breaks when I do that.
110 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
111 .field = V4L2_FIELD_INTERLACED,
112 .bytesperline = 0, // doesn't make sense
113 // here
114 //FIXME : Don't know what to put here...
115 .sizeimage = (32*1024),
116 .colorspace = 0, // doesn't make sense here
117 .priv = 0
118 }
119 }
120 },
121 [PVR_FORMAT_VBI] = {
122 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
123 .fmt = {
124 .vbi = {
125 .sampling_rate = 27000000,
126 .offset = 248,
127 .samples_per_line = 1443,
128 .sample_format = V4L2_PIX_FMT_GREY,
129 .start = { 0, 0 },
130 .count = { 0, 0 },
131 .flags = 0,
Mike Iselyd8554972006-06-26 20:58:46 -0300132 }
133 }
134 }
135};
136
Mike Isely16eb40d2006-12-30 18:27:32 -0300137
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300138
Mike Iselyd8554972006-06-26 20:58:46 -0300139/*
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300140 * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
Mike Iselyd8554972006-06-26 20:58:46 -0300141 */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300142static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
143{
144 struct pvr2_v4l2_fh *fh = file->private_data;
145 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
146
Hans Verkuil42639f62015-01-19 06:23:26 -0300147 strlcpy(cap->driver, "pvrusb2", sizeof(cap->driver));
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300148 strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
149 sizeof(cap->bus_info));
150 strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
Hans Verkuil42639f62015-01-19 06:23:26 -0300151 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
152 V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
153 V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS;
154 switch (fh->pdi->devbase.vfl_type) {
155 case VFL_TYPE_GRABBER:
156 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO;
157 break;
158 case VFL_TYPE_RADIO:
159 cap->device_caps = V4L2_CAP_RADIO;
160 break;
161 }
162 cap->device_caps |= V4L2_CAP_TUNER | V4L2_CAP_READWRITE;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300163 return 0;
164}
165
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300166static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
167{
168 struct pvr2_v4l2_fh *fh = file->private_data;
Mike Iselyd8554972006-06-26 20:58:46 -0300169 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300170 int val = 0;
171 int ret;
Mike Iselyd8554972006-06-26 20:58:46 -0300172
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300173 ret = pvr2_ctrl_get_value(
174 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
175 *std = val;
176 return ret;
177}
Mike Iselyd8554972006-06-26 20:58:46 -0300178
Hans Verkuil314527a2013-03-15 06:10:40 -0300179static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300180{
181 struct pvr2_v4l2_fh *fh = file->private_data;
182 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300183
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300184 return pvr2_ctrl_set_value(
Hans Verkuil314527a2013-03-15 06:10:40 -0300185 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300186}
Mike Iselyd8554972006-06-26 20:58:46 -0300187
Mike Isely0927ee62012-02-20 02:26:06 -0300188static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
189{
190 struct pvr2_v4l2_fh *fh = file->private_data;
191 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyac04d002012-02-20 02:28:56 -0300192 int val = 0;
193 int ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300194
Mike Iselyac04d002012-02-20 02:28:56 -0300195 ret = pvr2_ctrl_get_value(
196 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
197 *std = val;
198 return ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300199}
200
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300201static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
202{
203 struct pvr2_v4l2_fh *fh = file->private_data;
204 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
205 struct pvr2_ctrl *cptr;
206 struct v4l2_input tmp;
207 unsigned int cnt;
208 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300209
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300210 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
Mike Iselyd8554972006-06-26 20:58:46 -0300211
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300212 memset(&tmp, 0, sizeof(tmp));
213 tmp.index = vi->index;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300214 if (vi->index >= fh->input_cnt)
215 return -EINVAL;
216 val = fh->input_map[vi->index];
217 switch (val) {
218 case PVR2_CVAL_INPUT_TV:
219 case PVR2_CVAL_INPUT_DTV:
220 case PVR2_CVAL_INPUT_RADIO:
221 tmp.type = V4L2_INPUT_TYPE_TUNER;
Mike Iselyd8554972006-06-26 20:58:46 -0300222 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300223 case PVR2_CVAL_INPUT_SVIDEO:
224 case PVR2_CVAL_INPUT_COMPOSITE:
225 tmp.type = V4L2_INPUT_TYPE_CAMERA;
Mike Iselyd8554972006-06-26 20:58:46 -0300226 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300227 default:
228 return -EINVAL;
Mike Iselyd8554972006-06-26 20:58:46 -0300229 }
230
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300231 cnt = 0;
232 pvr2_ctrl_get_valname(cptr, val,
233 tmp.name, sizeof(tmp.name) - 1, &cnt);
234 tmp.name[cnt] = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300235
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300236 /* Don't bother with audioset, since this driver currently
237 always switches the audio whenever the video is
238 switched. */
Mike Iselyd8554972006-06-26 20:58:46 -0300239
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300240 /* Handling std is a tougher problem. It doesn't make
241 sense in cases where a device might be multi-standard.
242 We could just copy out the current value for the
243 standard, but it can change over time. For now just
244 leave it zero. */
245 *vi = tmp;
246 return 0;
247}
Mike Iselyd8554972006-06-26 20:58:46 -0300248
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300249static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
250{
251 struct pvr2_v4l2_fh *fh = file->private_data;
252 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
253 unsigned int idx;
254 struct pvr2_ctrl *cptr;
255 int val;
256 int ret;
Mauro Carvalho Chehab7383a472011-10-03 12:22:28 -0300257
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300258 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
259 val = 0;
260 ret = pvr2_ctrl_get_value(cptr, &val);
261 *i = 0;
262 for (idx = 0; idx < fh->input_cnt; idx++) {
263 if (fh->input_map[idx] == val) {
264 *i = idx;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300265 break;
266 }
Mike Iselyd8554972006-06-26 20:58:46 -0300267 }
268 return ret;
269}
270
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300271static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
272{
273 struct pvr2_v4l2_fh *fh = file->private_data;
274 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
275
276 if (inp >= fh->input_cnt)
277 return -EINVAL;
278 return pvr2_ctrl_set_value(
279 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
280 fh->input_map[inp]);
281}
282
283static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
284{
285 /* pkt: FIXME: We are returning one "fake" input here
286 which could very well be called "whatever_we_like".
287 This is for apps that want to see an audio input
288 just to feel comfortable, as well as to test if
289 it can do stereo or sth. There is actually no guarantee
290 that the actual audio input cannot change behind the app's
291 back, but most applications should not mind that either.
292
293 Hopefully, mplayer people will work with us on this (this
294 whole mess is to support mplayer pvr://), or Hans will come
295 up with a more standard way to say "we have inputs but we
296 don 't want you to change them independent of video" which
297 will sort this mess.
298 */
299
300 if (vin->index > 0)
301 return -EINVAL;
302 strncpy(vin->name, "PVRUSB2 Audio", 14);
303 vin->capability = V4L2_AUDCAP_STEREO;
304 return 0;
305}
306
307static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
308{
309 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
310 vin->index = 0;
311 strncpy(vin->name, "PVRUSB2 Audio", 14);
312 vin->capability = V4L2_AUDCAP_STEREO;
313 return 0;
314}
315
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300316static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300317{
318 if (vout->index)
319 return -EINVAL;
320 return 0;
321}
322
323static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
324{
325 struct pvr2_v4l2_fh *fh = file->private_data;
326 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
327
328 if (vt->index != 0)
329 return -EINVAL; /* Only answer for the 1st tuner */
330
331 pvr2_hdw_execute_tuner_poll(hdw);
332 return pvr2_hdw_get_tuner_status(hdw, vt);
333}
334
Hans Verkuil2f73c7c2013-03-15 06:10:06 -0300335static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300336{
337 struct pvr2_v4l2_fh *fh = file->private_data;
338 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
339
340 if (vt->index != 0)
341 return -EINVAL;
342
343 return pvr2_ctrl_set_value(
344 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
345 vt->audmode);
346}
347
Hans Verkuilb530a442013-03-19 04:09:26 -0300348static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300349{
350 struct pvr2_v4l2_fh *fh = file->private_data;
351 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
352 unsigned long fv;
353 struct v4l2_tuner vt;
354 int cur_input;
355 struct pvr2_ctrl *ctrlp;
356 int ret;
357
358 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
359 if (ret != 0)
360 return ret;
361 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
362 ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
363 if (ret != 0)
364 return ret;
365 if (vf->type == V4L2_TUNER_RADIO) {
366 if (cur_input != PVR2_CVAL_INPUT_RADIO)
367 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
368 } else {
369 if (cur_input == PVR2_CVAL_INPUT_RADIO)
370 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
371 }
372 fv = vf->frequency;
373 if (vt.capability & V4L2_TUNER_CAP_LOW)
374 fv = (fv * 125) / 2;
375 else
376 fv = fv * 62500;
377 return pvr2_ctrl_set_value(
378 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
379}
380
381static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
382{
383 struct pvr2_v4l2_fh *fh = file->private_data;
384 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
385 int val = 0;
386 int cur_input;
387 struct v4l2_tuner vt;
388 int ret;
389
390 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
391 if (ret != 0)
392 return ret;
393 ret = pvr2_ctrl_get_value(
394 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
395 &val);
396 if (ret != 0)
397 return ret;
398 pvr2_ctrl_get_value(
399 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
400 &cur_input);
401 if (cur_input == PVR2_CVAL_INPUT_RADIO)
402 vf->type = V4L2_TUNER_RADIO;
403 else
404 vf->type = V4L2_TUNER_ANALOG_TV;
405 if (vt.capability & V4L2_TUNER_CAP_LOW)
406 val = (val * 2) / 125;
407 else
408 val /= 62500;
409 vf->frequency = val;
410 return 0;
411}
412
413static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
414{
415 /* Only one format is supported : mpeg.*/
416 if (fd->index != 0)
417 return -EINVAL;
418
419 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
420 return 0;
421}
422
423static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
424{
425 struct pvr2_v4l2_fh *fh = file->private_data;
426 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
427 int val;
428
429 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
430 val = 0;
431 pvr2_ctrl_get_value(
432 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
433 &val);
434 vf->fmt.pix.width = val;
435 val = 0;
436 pvr2_ctrl_get_value(
437 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
438 &val);
439 vf->fmt.pix.height = val;
440 return 0;
441}
442
443static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
444{
445 struct pvr2_v4l2_fh *fh = file->private_data;
446 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
447 int lmin, lmax, ldef;
448 struct pvr2_ctrl *hcp, *vcp;
449 int h = vf->fmt.pix.height;
450 int w = vf->fmt.pix.width;
451
452 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
453 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
454
455 lmin = pvr2_ctrl_get_min(hcp);
456 lmax = pvr2_ctrl_get_max(hcp);
457 pvr2_ctrl_get_def(hcp, &ldef);
458 if (w == -1)
459 w = ldef;
460 else if (w < lmin)
461 w = lmin;
462 else if (w > lmax)
463 w = lmax;
464 lmin = pvr2_ctrl_get_min(vcp);
465 lmax = pvr2_ctrl_get_max(vcp);
466 pvr2_ctrl_get_def(vcp, &ldef);
467 if (h == -1)
468 h = ldef;
469 else if (h < lmin)
470 h = lmin;
471 else if (h > lmax)
472 h = lmax;
473
474 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
475 sizeof(struct v4l2_format));
476 vf->fmt.pix.width = w;
477 vf->fmt.pix.height = h;
478 return 0;
479}
480
481static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
482{
483 struct pvr2_v4l2_fh *fh = file->private_data;
484 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
485 struct pvr2_ctrl *hcp, *vcp;
486 int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
487
488 if (ret)
489 return ret;
490 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
491 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
492 pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
493 pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
494 return 0;
495}
496
497static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
498{
499 struct pvr2_v4l2_fh *fh = file->private_data;
500 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
501 struct pvr2_v4l2_dev *pdi = fh->pdi;
502 int ret;
503
504 if (!fh->pdi->stream) {
505 /* No stream defined for this node. This means
506 that we're not currently allowed to stream from
507 this node. */
508 return -EPERM;
509 }
510 ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
511 if (ret < 0)
512 return ret;
513 return pvr2_hdw_set_streaming(hdw, !0);
514}
515
516static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
517{
518 struct pvr2_v4l2_fh *fh = file->private_data;
519 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
520
521 if (!fh->pdi->stream) {
522 /* No stream defined for this node. This means
523 that we're not currently allowed to stream from
524 this node. */
525 return -EPERM;
526 }
527 return pvr2_hdw_set_streaming(hdw, 0);
528}
529
530static int pvr2_queryctrl(struct file *file, void *priv,
531 struct v4l2_queryctrl *vc)
532{
533 struct pvr2_v4l2_fh *fh = file->private_data;
534 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
535 struct pvr2_ctrl *cptr;
536 int val;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300537
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300538 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
539 cptr = pvr2_hdw_get_ctrl_nextv4l(
540 hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
541 if (cptr)
542 vc->id = pvr2_ctrl_get_v4lid(cptr);
543 } else {
544 cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
545 }
546 if (!cptr) {
547 pvr2_trace(PVR2_TRACE_V4LIOCTL,
548 "QUERYCTRL id=0x%x not implemented here",
549 vc->id);
550 return -EINVAL;
551 }
552
553 pvr2_trace(PVR2_TRACE_V4LIOCTL,
554 "QUERYCTRL id=0x%x mapping name=%s (%s)",
555 vc->id, pvr2_ctrl_get_name(cptr),
556 pvr2_ctrl_get_desc(cptr));
557 strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
558 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
559 pvr2_ctrl_get_def(cptr, &val);
560 vc->default_value = val;
561 switch (pvr2_ctrl_get_type(cptr)) {
562 case pvr2_ctl_enum:
563 vc->type = V4L2_CTRL_TYPE_MENU;
564 vc->minimum = 0;
565 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
566 vc->step = 1;
567 break;
568 case pvr2_ctl_bool:
569 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
570 vc->minimum = 0;
571 vc->maximum = 1;
572 vc->step = 1;
573 break;
574 case pvr2_ctl_int:
575 vc->type = V4L2_CTRL_TYPE_INTEGER;
576 vc->minimum = pvr2_ctrl_get_min(cptr);
577 vc->maximum = pvr2_ctrl_get_max(cptr);
578 vc->step = 1;
579 break;
580 default:
581 pvr2_trace(PVR2_TRACE_V4LIOCTL,
582 "QUERYCTRL id=0x%x name=%s not mappable",
583 vc->id, pvr2_ctrl_get_name(cptr));
584 return -EINVAL;
585 }
586 return 0;
587}
588
589static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
590{
591 struct pvr2_v4l2_fh *fh = file->private_data;
592 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
593 unsigned int cnt = 0;
594 int ret;
595
596 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
597 vm->index,
598 vm->name, sizeof(vm->name) - 1,
599 &cnt);
600 vm->name[cnt] = 0;
601 return ret;
602}
603
604static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
605{
606 struct pvr2_v4l2_fh *fh = file->private_data;
607 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
608 int val = 0;
609 int ret;
610
611 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
612 &val);
613 vc->value = val;
614 return ret;
615}
616
617static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
618{
619 struct pvr2_v4l2_fh *fh = file->private_data;
620 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
621
622 return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
623 vc->value);
624}
625
626static int pvr2_g_ext_ctrls(struct file *file, void *priv,
627 struct v4l2_ext_controls *ctls)
628{
629 struct pvr2_v4l2_fh *fh = file->private_data;
630 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
631 struct v4l2_ext_control *ctrl;
632 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;
639 ret = pvr2_ctrl_get_value(
640 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
641 if (ret) {
642 ctls->error_idx = idx;
643 return ret;
644 }
645 /* Ensure that if read as a 64 bit value, the user
646 will still get a hopefully sane value */
647 ctrl->value64 = 0;
648 ctrl->value = val;
649 }
650 return 0;
651}
652
653static int pvr2_s_ext_ctrls(struct file *file, void *priv,
654 struct v4l2_ext_controls *ctls)
655{
656 struct pvr2_v4l2_fh *fh = file->private_data;
657 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
658 struct v4l2_ext_control *ctrl;
659 unsigned int idx;
660 int ret;
661
662 ret = 0;
663 for (idx = 0; idx < ctls->count; idx++) {
664 ctrl = ctls->controls + idx;
665 ret = pvr2_ctrl_set_value(
666 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
667 ctrl->value);
668 if (ret) {
669 ctls->error_idx = idx;
670 return ret;
671 }
672 }
673 return 0;
674}
675
676static int pvr2_try_ext_ctrls(struct file *file, void *priv,
677 struct v4l2_ext_controls *ctls)
678{
679 struct pvr2_v4l2_fh *fh = file->private_data;
680 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
681 struct v4l2_ext_control *ctrl;
682 struct pvr2_ctrl *pctl;
683 unsigned int idx;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300684
685 /* For the moment just validate that the requested control
686 actually exists. */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300687 for (idx = 0; idx < ctls->count; idx++) {
688 ctrl = ctls->controls + idx;
689 pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
690 if (!pctl) {
691 ctls->error_idx = idx;
692 return -EINVAL;
693 }
694 }
695 return 0;
696}
697
698static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
699{
700 struct pvr2_v4l2_fh *fh = file->private_data;
701 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
702 int ret;
703
704 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
705 return -EINVAL;
706 ret = pvr2_hdw_get_cropcap(hdw, cap);
707 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
708 return ret;
709}
710
711static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
712{
713 struct pvr2_v4l2_fh *fh = file->private_data;
714 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
715 int val = 0;
716 int ret;
717
718 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
719 return -EINVAL;
720 ret = pvr2_ctrl_get_value(
721 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
722 if (ret != 0)
723 return -EINVAL;
724 crop->c.left = val;
725 ret = pvr2_ctrl_get_value(
726 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
727 if (ret != 0)
728 return -EINVAL;
729 crop->c.top = val;
730 ret = pvr2_ctrl_get_value(
731 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
732 if (ret != 0)
733 return -EINVAL;
734 crop->c.width = val;
735 ret = pvr2_ctrl_get_value(
736 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
737 if (ret != 0)
738 return -EINVAL;
739 crop->c.height = val;
740 return 0;
741}
742
Hans Verkuil4f996592012-09-05 05:10:48 -0300743static int pvr2_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300744{
745 struct pvr2_v4l2_fh *fh = file->private_data;
746 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300747 int ret;
748
749 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
750 return -EINVAL;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300751 ret = pvr2_ctrl_set_value(
752 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
753 crop->c.left);
754 if (ret != 0)
755 return -EINVAL;
756 ret = pvr2_ctrl_set_value(
757 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
758 crop->c.top);
759 if (ret != 0)
760 return -EINVAL;
761 ret = pvr2_ctrl_set_value(
762 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
763 crop->c.width);
764 if (ret != 0)
765 return -EINVAL;
766 ret = pvr2_ctrl_set_value(
767 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
768 crop->c.height);
769 if (ret != 0)
770 return -EINVAL;
771 return 0;
772}
773
774static int pvr2_log_status(struct file *file, void *priv)
775{
776 struct pvr2_v4l2_fh *fh = file->private_data;
777 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
778
779 pvr2_hdw_trigger_module_log(hdw);
780 return 0;
781}
782
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300783static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
784 .vidioc_querycap = pvr2_querycap,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300785 .vidioc_s_audio = pvr2_s_audio,
786 .vidioc_g_audio = pvr2_g_audio,
787 .vidioc_enumaudio = pvr2_enumaudio,
788 .vidioc_enum_input = pvr2_enum_input,
789 .vidioc_cropcap = pvr2_cropcap,
790 .vidioc_s_crop = pvr2_s_crop,
791 .vidioc_g_crop = pvr2_g_crop,
792 .vidioc_g_input = pvr2_g_input,
793 .vidioc_s_input = pvr2_s_input,
794 .vidioc_g_frequency = pvr2_g_frequency,
795 .vidioc_s_frequency = pvr2_s_frequency,
796 .vidioc_s_tuner = pvr2_s_tuner,
797 .vidioc_g_tuner = pvr2_g_tuner,
798 .vidioc_g_std = pvr2_g_std,
799 .vidioc_s_std = pvr2_s_std,
Mike Isely0927ee62012-02-20 02:26:06 -0300800 .vidioc_querystd = pvr2_querystd,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300801 .vidioc_log_status = pvr2_log_status,
802 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
803 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
804 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
805 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
806 .vidioc_streamon = pvr2_streamon,
807 .vidioc_streamoff = pvr2_streamoff,
808 .vidioc_queryctrl = pvr2_queryctrl,
809 .vidioc_querymenu = pvr2_querymenu,
810 .vidioc_g_ctrl = pvr2_g_ctrl,
811 .vidioc_s_ctrl = pvr2_s_ctrl,
812 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
813 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
814 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300815};
816
Mike Iselyd8554972006-06-26 20:58:46 -0300817static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
818{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300819 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300820 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300821 char msg[80];
822 unsigned int mcnt;
823
824 /* Construct the unregistration message *before* we actually
825 perform the unregistration step. By doing it this way we don't
826 have to worry about potentially touching deleted resources. */
827 mcnt = scnprintf(msg, sizeof(msg) - 1,
828 "pvrusb2: unregistered device %s [%s]",
829 video_device_node_name(&dip->devbase),
830 pvr2_config_get_name(cfg));
831 msg[mcnt] = 0;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300832
Mike Isely16eb40d2006-12-30 18:27:32 -0300833 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300834
835 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300836 dip->v4lp = NULL;
837 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300838
839 /* Actual deallocation happens later when all internal references
840 are gone. */
841 video_unregister_device(&dip->devbase);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300842
Mike Iselyd72baad2010-05-15 00:15:38 -0300843 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300844
Mike Iselyd8554972006-06-26 20:58:46 -0300845}
846
847
Mike Isely4a89baa2009-10-12 00:13:28 -0300848static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
849{
850 if (!dip) return;
Hans Verkuila28fbd02013-06-10 09:16:25 -0300851 if (!dip->devbase.v4l2_dev->dev) return;
852 dip->devbase.v4l2_dev->dev = NULL;
Mike Isely4a89baa2009-10-12 00:13:28 -0300853 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
854}
855
856
Mike Iselyd8554972006-06-26 20:58:46 -0300857static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
858{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300859 if (vp->dev_video) {
860 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000861 vp->dev_video = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300862 }
863 if (vp->dev_radio) {
864 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000865 vp->dev_radio = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300866 }
Mike Iselyd8554972006-06-26 20:58:46 -0300867
868 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
869 pvr2_channel_done(&vp->channel);
870 kfree(vp);
871}
872
873
Mike Isely75910052006-09-23 22:30:50 -0300874static void pvr2_video_device_release(struct video_device *vdev)
875{
876 struct pvr2_v4l2_dev *dev;
877 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
878 kfree(dev);
879}
880
881
Adrian Bunk07e337e2006-06-30 11:30:20 -0300882static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300883{
884 struct pvr2_v4l2 *vp;
885 vp = container_of(chp,struct pvr2_v4l2,channel);
886 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300887 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
888 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300889 if (!list_empty(&vp->dev_video->devbase.fh_list) ||
890 !list_empty(&vp->dev_radio->devbase.fh_list))
891 return;
Mike Iselyd8554972006-06-26 20:58:46 -0300892 pvr2_v4l2_destroy_no_lock(vp);
893}
894
895
Hans Verkuil069b7472008-12-30 07:04:34 -0300896static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300897 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300898{
899
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300900 struct pvr2_v4l2_fh *fh = file->private_data;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300901 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
902 long ret = -EINVAL;
903
904 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
Hans Verkuil4a085162012-06-22 06:38:06 -0300905 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300906
907 if (!pvr2_hdw_dev_ok(hdw)) {
908 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
909 "ioctl failed - bad or no context");
910 return -EFAULT;
911 }
912
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300913 ret = video_ioctl2(file, cmd, arg);
914
915 pvr2_hdw_commit_ctl(hdw);
916
917 if (ret < 0) {
918 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
919 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Andrey Utkin599bc362014-07-10 09:32:25 -0300920 "pvr2_v4l2_do_ioctl failure, ret=%ld"
921 " command was:", ret);
922 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300923 }
924 } else {
925 pvr2_trace(PVR2_TRACE_V4LIOCTL,
926 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
927 ret, ret);
928 }
929 return ret;
930
Mike Iselyd8554972006-06-26 20:58:46 -0300931}
932
933
Hans Verkuilbec43662008-12-30 06:58:20 -0300934static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300935{
936 struct pvr2_v4l2_fh *fhp = file->private_data;
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300937 struct pvr2_v4l2 *vp = fhp->pdi->v4lp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300938 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300939
940 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
941
942 if (fhp->rhp) {
943 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300944 pvr2_hdw_set_streaming(hdw,0);
945 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300946 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300947 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300948 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300949 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300950
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300951 v4l2_fh_del(&fhp->fh);
952 v4l2_fh_exit(&fhp->fh);
Mike Iselyd8554972006-06-26 20:58:46 -0300953 file->private_data = NULL;
954
Mike Isely794b1602008-04-22 14:45:45 -0300955 pvr2_channel_done(&fhp->channel);
956 pvr2_trace(PVR2_TRACE_STRUCT,
957 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -0300958 if (fhp->input_map) {
959 kfree(fhp->input_map);
960 fhp->input_map = NULL;
961 }
Mike Isely794b1602008-04-22 14:45:45 -0300962 kfree(fhp);
Hans Verkuilcee05cb2015-02-03 10:46:55 -0300963 if (vp->channel.mc_head->disconnect_flag &&
964 list_empty(&vp->dev_video->devbase.fh_list) &&
965 list_empty(&vp->dev_radio->devbase.fh_list)) {
Mike Isely794b1602008-04-22 14:45:45 -0300966 pvr2_v4l2_destroy_no_lock(vp);
967 }
Mike Iselyd8554972006-06-26 20:58:46 -0300968 return 0;
969}
970
971
Hans Verkuilbec43662008-12-30 06:58:20 -0300972static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300973{
Mike Isely75910052006-09-23 22:30:50 -0300974 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300975 struct pvr2_v4l2_fh *fhp;
976 struct pvr2_v4l2 *vp;
977 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -0300978 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -0300979 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -0300980 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300981
Mike Isely75910052006-09-23 22:30:50 -0300982 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300983
984 vp = dip->v4lp;
985 hdw = vp->channel.hdw;
986
987 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
988
989 if (!pvr2_hdw_dev_ok(hdw)) {
990 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
991 "pvr2_v4l2_open: hardware not ready");
992 return -EIO;
993 }
994
Mike Isely4b85dee2007-01-20 00:03:32 -0300995 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300996 if (!fhp) {
997 return -ENOMEM;
998 }
Mike Iselyd8554972006-06-26 20:58:46 -0300999
Hans Verkuilcee05cb2015-02-03 10:46:55 -03001000 v4l2_fh_init(&fhp->fh, &dip->devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001001 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001002 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001003
Mike Isely794b1602008-04-22 14:45:45 -03001004 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1005 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001006
Mike Isely1cb03b72008-04-21 03:47:43 -03001007 if (dip->v4l_type == VFL_TYPE_RADIO) {
1008 /* Opening device as a radio, legal input selection subset
1009 is just the radio. */
1010 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1011 } else {
1012 /* Opening the main V4L device, legal input selection
1013 subset includes all analog inputs. */
1014 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1015 (1 << PVR2_CVAL_INPUT_TV) |
1016 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1017 (1 << PVR2_CVAL_INPUT_SVIDEO));
1018 }
1019 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1020 if (ret) {
1021 pvr2_channel_done(&fhp->channel);
1022 pvr2_trace(PVR2_TRACE_STRUCT,
1023 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1024 fhp);
1025
1026 kfree(fhp);
1027 return ret;
1028 }
1029
Mike Iselye57b1c82008-04-21 03:52:34 -03001030 input_mask &= pvr2_hdw_get_input_available(hdw);
1031 input_cnt = 0;
1032 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1033 if (input_mask & (1 << idx)) input_cnt++;
1034 }
1035 fhp->input_cnt = input_cnt;
1036 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1037 if (!fhp->input_map) {
1038 pvr2_channel_done(&fhp->channel);
1039 pvr2_trace(PVR2_TRACE_STRUCT,
1040 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1041 fhp);
1042 kfree(fhp);
1043 return -ENOMEM;
1044 }
1045 input_cnt = 0;
1046 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1047 if (!(input_mask & (1 << idx))) continue;
1048 fhp->input_map[input_cnt++] = idx;
1049 }
1050
Mike Iselyd8554972006-06-26 20:58:46 -03001051 fhp->file = file;
1052 file->private_data = fhp;
Mike Iselyd8554972006-06-26 20:58:46 -03001053
1054 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
Hans Verkuilcee05cb2015-02-03 10:46:55 -03001055 v4l2_fh_add(&fhp->fh);
Mike Iselyd8554972006-06-26 20:58:46 -03001056
1057 return 0;
1058}
1059
1060
1061static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1062{
1063 wake_up(&fhp->wait_data);
1064}
1065
1066static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1067{
1068 int ret;
1069 struct pvr2_stream *sp;
1070 struct pvr2_hdw *hdw;
1071 if (fh->rhp) return 0;
1072
Joe Perches108bdd72010-04-05 16:05:39 -03001073 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001074 /* No stream defined for this node. This means that we're
1075 not currently allowed to stream from this node. */
1076 return -EPERM;
1077 }
1078
Mike Iselyd8554972006-06-26 20:58:46 -03001079 /* First read() attempt. Try to claim the stream and start
1080 it... */
1081 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001082 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001083 /* Someone else must already have it */
1084 return ret;
1085 }
1086
Joe Perches108bdd72010-04-05 16:05:39 -03001087 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001088 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001089 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001090 return -ENOMEM;
1091 }
1092
1093 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001094 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001095 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001096 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001097 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1098 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001099}
1100
1101
1102static ssize_t pvr2_v4l2_read(struct file *file,
1103 char __user *buff, size_t count, loff_t *ppos)
1104{
1105 struct pvr2_v4l2_fh *fh = file->private_data;
1106 int ret;
1107
1108 if (fh->fw_mode_flag) {
1109 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1110 char *tbuf;
1111 int c1,c2;
1112 int tcnt = 0;
1113 unsigned int offs = *ppos;
1114
1115 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1116 if (!tbuf) return -ENOMEM;
1117
1118 while (count) {
1119 c1 = count;
1120 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1121 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1122 if (c2 < 0) {
1123 tcnt = c2;
1124 break;
1125 }
1126 if (!c2) break;
1127 if (copy_to_user(buff,tbuf,c2)) {
1128 tcnt = -EFAULT;
1129 break;
1130 }
1131 offs += c2;
1132 tcnt += c2;
1133 buff += c2;
1134 count -= c2;
1135 *ppos += c2;
1136 }
1137 kfree(tbuf);
1138 return tcnt;
1139 }
1140
1141 if (!fh->rhp) {
1142 ret = pvr2_v4l2_iosetup(fh);
1143 if (ret) {
1144 return ret;
1145 }
1146 }
1147
1148 for (;;) {
1149 ret = pvr2_ioread_read(fh->rhp,buff,count);
1150 if (ret >= 0) break;
1151 if (ret != -EAGAIN) break;
1152 if (file->f_flags & O_NONBLOCK) break;
1153 /* Doing blocking I/O. Wait here. */
1154 ret = wait_event_interruptible(
1155 fh->wait_data,
1156 pvr2_ioread_avail(fh->rhp) >= 0);
1157 if (ret < 0) break;
1158 }
1159
1160 return ret;
1161}
1162
1163
1164static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1165{
1166 unsigned int mask = 0;
1167 struct pvr2_v4l2_fh *fh = file->private_data;
1168 int ret;
1169
1170 if (fh->fw_mode_flag) {
1171 mask |= POLLIN | POLLRDNORM;
1172 return mask;
1173 }
1174
1175 if (!fh->rhp) {
1176 ret = pvr2_v4l2_iosetup(fh);
1177 if (ret) return POLLERR;
1178 }
1179
1180 poll_wait(file,&fh->wait_data,wait);
1181
1182 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1183 mask |= POLLIN | POLLRDNORM;
1184 }
1185
1186 return mask;
1187}
1188
1189
Hans Verkuilbec43662008-12-30 06:58:20 -03001190static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001191 .owner = THIS_MODULE,
1192 .open = pvr2_v4l2_open,
1193 .release = pvr2_v4l2_release,
1194 .read = pvr2_v4l2_read,
Hans Verkuilab91c612015-02-17 05:44:04 -03001195 .unlocked_ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001196 .poll = pvr2_v4l2_poll,
1197};
1198
1199
Mike Iselyd8554972006-06-26 20:58:46 -03001200static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001201 .fops = &vdev_fops,
1202};
1203
1204
1205static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1206 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001207 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001208{
1209 int mindevnum;
1210 int unit_number;
Mike Isely598e9782012-02-20 02:35:20 -03001211 struct pvr2_hdw *hdw;
Al Viro89952d12007-03-14 09:17:59 +00001212 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001213 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001214
Mike Isely598e9782012-02-20 02:35:20 -03001215 hdw = vp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -03001216 dip->v4l_type = v4l_type;
1217 switch (v4l_type) {
1218 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001219 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001220 dip->config = pvr2_config_mpeg;
1221 dip->minor_type = pvr2_v4l_type_video;
1222 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001223 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001224 pr_err(KBUILD_MODNAME
1225 ": Failed to set up pvrusb2 v4l video dev"
1226 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001227 return;
1228 }
Mike Iselyd8554972006-06-26 20:58:46 -03001229 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001230 case VFL_TYPE_VBI:
1231 dip->config = pvr2_config_vbi;
1232 dip->minor_type = pvr2_v4l_type_vbi;
1233 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001234 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001235 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001236 dip->stream = &vp->channel.mc_head->video_stream;
1237 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001238 dip->minor_type = pvr2_v4l_type_radio;
1239 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001240 break;
1241 default:
1242 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001243 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1244 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001245 return;
1246 }
1247
Ezequiel Garcia5338c162012-10-23 15:57:09 -03001248 dip->devbase = vdev_template;
Mike Isely75910052006-09-23 22:30:50 -03001249 dip->devbase.release = pvr2_video_device_release;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -03001250 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
Mike Iselyd8329f82012-02-20 02:33:06 -03001251 {
1252 int val;
1253 pvr2_ctrl_get_value(
Mike Isely598e9782012-02-20 02:35:20 -03001254 pvr2_hdw_get_ctrl_by_id(hdw,
Mike Iselyd8329f82012-02-20 02:33:06 -03001255 PVR2_CID_STDAVAIL), &val);
1256 dip->devbase.tvnorms = (v4l2_std_id)val;
1257 }
Mike Iselyd8554972006-06-26 20:58:46 -03001258
1259 mindevnum = -1;
Mike Isely598e9782012-02-20 02:35:20 -03001260 unit_number = pvr2_hdw_get_unit_number(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001261 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1262 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001263 }
Hans Verkuila28fbd02013-06-10 09:16:25 -03001264 pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase);
Mike Isely16eb40d2006-12-30 18:27:32 -03001265 if ((video_register_device(&dip->devbase,
1266 dip->v4l_type, mindevnum) < 0) &&
1267 (video_register_device(&dip->devbase,
1268 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001269 pr_err(KBUILD_MODNAME
1270 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001271 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001272
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001273 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1274 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001275 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001276
Mike Isely598e9782012-02-20 02:35:20 -03001277 pvr2_hdw_v4l_store_minor_number(hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001278 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001279}
1280
1281
1282struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1283{
1284 struct pvr2_v4l2 *vp;
1285
Mike Isely4b85dee2007-01-20 00:03:32 -03001286 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001287 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001288 pvr2_channel_init(&vp->channel,mnp);
1289 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1290
1291 vp->channel.check_func = pvr2_v4l2_internal_check;
1292
1293 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001294 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1295 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001296 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001297 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1298 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001299 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1300 if (!vp->dev_radio) goto fail;
1301 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1302 }
Mike Iselyd8554972006-06-26 20:58:46 -03001303
1304 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001305 fail:
1306 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1307 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001308 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001309}