blob: 82f619ba5cca5b69ed7faadb491f0e42167ab2e1 [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>
Mike Iselyd8554972006-06-26 20:58:46 -030034#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030035#include <media/v4l2-ioctl.h>
Mike Iselyd8554972006-06-26 20:58:46 -030036
37struct pvr2_v4l2_dev;
38struct pvr2_v4l2_fh;
39struct pvr2_v4l2;
40
Mike Iselyd8554972006-06-26 20:58:46 -030041struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030042 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030043 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030044 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030045 /* Information about this device: */
46 enum pvr2_config config; /* Expected stream format */
47 int v4l_type; /* V4L defined type for this device node */
48 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030049};
50
51struct pvr2_v4l2_fh {
52 struct pvr2_channel channel;
Joe Perches108bdd72010-04-05 16:05:39 -030053 struct pvr2_v4l2_dev *pdi;
Mike Iselyd8554972006-06-26 20:58:46 -030054 enum v4l2_priority prio;
55 struct pvr2_ioread *rhp;
56 struct file *file;
57 struct pvr2_v4l2 *vhead;
58 struct pvr2_v4l2_fh *vnext;
59 struct pvr2_v4l2_fh *vprev;
60 wait_queue_head_t wait_data;
61 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030062 /* Map contiguous ordinal value to input id */
63 unsigned char *input_map;
64 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030065};
66
67struct pvr2_v4l2 {
68 struct pvr2_channel channel;
69 struct pvr2_v4l2_fh *vfirst;
70 struct pvr2_v4l2_fh *vlast;
71
72 struct v4l2_prio_state prio;
73
Mike Isely0f0f257b2006-12-27 23:19:42 -030074 /* streams - Note that these must be separately, individually,
75 * allocated pointers. This is because the v4l core is going to
76 * manage their deletion - separately, individually... */
77 struct pvr2_v4l2_dev *dev_video;
78 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030079};
80
81static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
82module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030083MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
84static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
85module_param_array(radio_nr, int, NULL, 0444);
86MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
87static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
88module_param_array(vbi_nr, int, NULL, 0444);
89MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030090
Adrian Bunk07e337e2006-06-30 11:30:20 -030091static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030092 .driver = "pvrusb2",
93 .card = "Hauppauge WinTV pvr-usb2",
94 .bus_info = "usb",
Mauro Carvalho Chehab083774d2011-06-25 13:34:24 -030095 .version = LINUX_VERSION_CODE,
Mike Iselyd166b022009-01-14 04:21:29 -030096 .capabilities = (V4L2_CAP_VIDEO_CAPTURE |
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -030097 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
Mike Iselyd8554972006-06-26 20:58:46 -030098 V4L2_CAP_READWRITE),
Mike Iselyd8554972006-06-26 20:58:46 -030099};
100
Adrian Bunk07e337e2006-06-30 11:30:20 -0300101static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300102 {
103 .index = 0,
104 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
105 .flags = V4L2_FMT_FLAG_COMPRESSED,
106 .description = "MPEG1/2",
107 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
108 // breaks when I do that.
109 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
Mike Iselyd8554972006-06-26 20:58:46 -0300110 }
111};
112
113#define PVR_FORMAT_PIX 0
114#define PVR_FORMAT_VBI 1
115
Adrian Bunk07e337e2006-06-30 11:30:20 -0300116static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300117 [PVR_FORMAT_PIX] = {
118 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
119 .fmt = {
120 .pix = {
121 .width = 720,
122 .height = 576,
123 // This should really be V4L2_PIX_FMT_MPEG,
124 // but xawtv breaks when I do that.
125 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
126 .field = V4L2_FIELD_INTERLACED,
127 .bytesperline = 0, // doesn't make sense
128 // here
129 //FIXME : Don't know what to put here...
130 .sizeimage = (32*1024),
131 .colorspace = 0, // doesn't make sense here
132 .priv = 0
133 }
134 }
135 },
136 [PVR_FORMAT_VBI] = {
137 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
138 .fmt = {
139 .vbi = {
140 .sampling_rate = 27000000,
141 .offset = 248,
142 .samples_per_line = 1443,
143 .sample_format = V4L2_PIX_FMT_GREY,
144 .start = { 0, 0 },
145 .count = { 0, 0 },
146 .flags = 0,
Mike Iselyd8554972006-06-26 20:58:46 -0300147 }
148 }
149 }
150};
151
Mike Isely16eb40d2006-12-30 18:27:32 -0300152
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300153
Mike Iselyd8554972006-06-26 20:58:46 -0300154/*
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300155 * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
Mike Iselyd8554972006-06-26 20:58:46 -0300156 */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300157static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
158{
159 struct pvr2_v4l2_fh *fh = file->private_data;
160 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
161
162 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
163 strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
164 sizeof(cap->bus_info));
165 strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
166 return 0;
167}
168
169static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
Mike Iselyd8554972006-06-26 20:58:46 -0300170{
171 struct pvr2_v4l2_fh *fh = file->private_data;
172 struct pvr2_v4l2 *vp = fh->vhead;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300173
174 *p = v4l2_prio_max(&vp->prio);
175 return 0;
176}
177
178static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
179{
180 struct pvr2_v4l2_fh *fh = file->private_data;
181 struct pvr2_v4l2 *vp = fh->vhead;
182
183 return v4l2_prio_change(&vp->prio, &fh->prio, prio);
184}
185
186static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
187{
188 struct pvr2_v4l2_fh *fh = file->private_data;
Mike Iselyd8554972006-06-26 20:58:46 -0300189 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300190 int val = 0;
191 int ret;
Mike Iselyd8554972006-06-26 20:58:46 -0300192
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300193 ret = pvr2_ctrl_get_value(
194 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
195 *std = val;
196 return ret;
197}
Mike Iselyd8554972006-06-26 20:58:46 -0300198
Hans Verkuil314527a2013-03-15 06:10:40 -0300199static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300200{
201 struct pvr2_v4l2_fh *fh = file->private_data;
202 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300203
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300204 return pvr2_ctrl_set_value(
Hans Verkuil314527a2013-03-15 06:10:40 -0300205 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300206}
Mike Iselyd8554972006-06-26 20:58:46 -0300207
Mike Isely0927ee62012-02-20 02:26:06 -0300208static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
209{
210 struct pvr2_v4l2_fh *fh = file->private_data;
211 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyac04d002012-02-20 02:28:56 -0300212 int val = 0;
213 int ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300214
Mike Iselyac04d002012-02-20 02:28:56 -0300215 ret = pvr2_ctrl_get_value(
216 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
217 *std = val;
218 return ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300219}
220
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300221static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
222{
223 struct pvr2_v4l2_fh *fh = file->private_data;
224 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
225 struct pvr2_ctrl *cptr;
226 struct v4l2_input tmp;
227 unsigned int cnt;
228 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300229
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300230 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
Mike Iselyd8554972006-06-26 20:58:46 -0300231
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300232 memset(&tmp, 0, sizeof(tmp));
233 tmp.index = vi->index;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300234 if (vi->index >= fh->input_cnt)
235 return -EINVAL;
236 val = fh->input_map[vi->index];
237 switch (val) {
238 case PVR2_CVAL_INPUT_TV:
239 case PVR2_CVAL_INPUT_DTV:
240 case PVR2_CVAL_INPUT_RADIO:
241 tmp.type = V4L2_INPUT_TYPE_TUNER;
Mike Iselyd8554972006-06-26 20:58:46 -0300242 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300243 case PVR2_CVAL_INPUT_SVIDEO:
244 case PVR2_CVAL_INPUT_COMPOSITE:
245 tmp.type = V4L2_INPUT_TYPE_CAMERA;
Mike Iselyd8554972006-06-26 20:58:46 -0300246 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300247 default:
248 return -EINVAL;
Mike Iselyd8554972006-06-26 20:58:46 -0300249 }
250
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300251 cnt = 0;
252 pvr2_ctrl_get_valname(cptr, val,
253 tmp.name, sizeof(tmp.name) - 1, &cnt);
254 tmp.name[cnt] = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300255
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300256 /* Don't bother with audioset, since this driver currently
257 always switches the audio whenever the video is
258 switched. */
Mike Iselyd8554972006-06-26 20:58:46 -0300259
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300260 /* Handling std is a tougher problem. It doesn't make
261 sense in cases where a device might be multi-standard.
262 We could just copy out the current value for the
263 standard, but it can change over time. For now just
264 leave it zero. */
265 *vi = tmp;
266 return 0;
267}
Mike Iselyd8554972006-06-26 20:58:46 -0300268
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300269static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
270{
271 struct pvr2_v4l2_fh *fh = file->private_data;
272 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
273 unsigned int idx;
274 struct pvr2_ctrl *cptr;
275 int val;
276 int ret;
Mauro Carvalho Chehab7383a472011-10-03 12:22:28 -0300277
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300278 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
279 val = 0;
280 ret = pvr2_ctrl_get_value(cptr, &val);
281 *i = 0;
282 for (idx = 0; idx < fh->input_cnt; idx++) {
283 if (fh->input_map[idx] == val) {
284 *i = idx;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300285 break;
286 }
Mike Iselyd8554972006-06-26 20:58:46 -0300287 }
288 return ret;
289}
290
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300291static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
292{
293 struct pvr2_v4l2_fh *fh = file->private_data;
294 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
295
296 if (inp >= fh->input_cnt)
297 return -EINVAL;
298 return pvr2_ctrl_set_value(
299 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
300 fh->input_map[inp]);
301}
302
303static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
304{
305 /* pkt: FIXME: We are returning one "fake" input here
306 which could very well be called "whatever_we_like".
307 This is for apps that want to see an audio input
308 just to feel comfortable, as well as to test if
309 it can do stereo or sth. There is actually no guarantee
310 that the actual audio input cannot change behind the app's
311 back, but most applications should not mind that either.
312
313 Hopefully, mplayer people will work with us on this (this
314 whole mess is to support mplayer pvr://), or Hans will come
315 up with a more standard way to say "we have inputs but we
316 don 't want you to change them independent of video" which
317 will sort this mess.
318 */
319
320 if (vin->index > 0)
321 return -EINVAL;
322 strncpy(vin->name, "PVRUSB2 Audio", 14);
323 vin->capability = V4L2_AUDCAP_STEREO;
324 return 0;
325}
326
327static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
328{
329 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
330 vin->index = 0;
331 strncpy(vin->name, "PVRUSB2 Audio", 14);
332 vin->capability = V4L2_AUDCAP_STEREO;
333 return 0;
334}
335
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300336static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300337{
338 if (vout->index)
339 return -EINVAL;
340 return 0;
341}
342
343static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
344{
345 struct pvr2_v4l2_fh *fh = file->private_data;
346 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
347
348 if (vt->index != 0)
349 return -EINVAL; /* Only answer for the 1st tuner */
350
351 pvr2_hdw_execute_tuner_poll(hdw);
352 return pvr2_hdw_get_tuner_status(hdw, vt);
353}
354
Hans Verkuil2f73c7c2013-03-15 06:10:06 -0300355static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300356{
357 struct pvr2_v4l2_fh *fh = file->private_data;
358 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
359
360 if (vt->index != 0)
361 return -EINVAL;
362
363 return pvr2_ctrl_set_value(
364 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
365 vt->audmode);
366}
367
Hans Verkuilb530a442013-03-19 04:09:26 -0300368static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300369{
370 struct pvr2_v4l2_fh *fh = file->private_data;
371 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
372 unsigned long fv;
373 struct v4l2_tuner vt;
374 int cur_input;
375 struct pvr2_ctrl *ctrlp;
376 int ret;
377
378 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
379 if (ret != 0)
380 return ret;
381 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
382 ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
383 if (ret != 0)
384 return ret;
385 if (vf->type == V4L2_TUNER_RADIO) {
386 if (cur_input != PVR2_CVAL_INPUT_RADIO)
387 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
388 } else {
389 if (cur_input == PVR2_CVAL_INPUT_RADIO)
390 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
391 }
392 fv = vf->frequency;
393 if (vt.capability & V4L2_TUNER_CAP_LOW)
394 fv = (fv * 125) / 2;
395 else
396 fv = fv * 62500;
397 return pvr2_ctrl_set_value(
398 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
399}
400
401static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
402{
403 struct pvr2_v4l2_fh *fh = file->private_data;
404 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
405 int val = 0;
406 int cur_input;
407 struct v4l2_tuner vt;
408 int ret;
409
410 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
411 if (ret != 0)
412 return ret;
413 ret = pvr2_ctrl_get_value(
414 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
415 &val);
416 if (ret != 0)
417 return ret;
418 pvr2_ctrl_get_value(
419 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
420 &cur_input);
421 if (cur_input == PVR2_CVAL_INPUT_RADIO)
422 vf->type = V4L2_TUNER_RADIO;
423 else
424 vf->type = V4L2_TUNER_ANALOG_TV;
425 if (vt.capability & V4L2_TUNER_CAP_LOW)
426 val = (val * 2) / 125;
427 else
428 val /= 62500;
429 vf->frequency = val;
430 return 0;
431}
432
433static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
434{
435 /* Only one format is supported : mpeg.*/
436 if (fd->index != 0)
437 return -EINVAL;
438
439 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
440 return 0;
441}
442
443static int pvr2_g_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 val;
448
449 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
450 val = 0;
451 pvr2_ctrl_get_value(
452 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
453 &val);
454 vf->fmt.pix.width = val;
455 val = 0;
456 pvr2_ctrl_get_value(
457 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
458 &val);
459 vf->fmt.pix.height = val;
460 return 0;
461}
462
463static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
464{
465 struct pvr2_v4l2_fh *fh = file->private_data;
466 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
467 int lmin, lmax, ldef;
468 struct pvr2_ctrl *hcp, *vcp;
469 int h = vf->fmt.pix.height;
470 int w = vf->fmt.pix.width;
471
472 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
473 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
474
475 lmin = pvr2_ctrl_get_min(hcp);
476 lmax = pvr2_ctrl_get_max(hcp);
477 pvr2_ctrl_get_def(hcp, &ldef);
478 if (w == -1)
479 w = ldef;
480 else if (w < lmin)
481 w = lmin;
482 else if (w > lmax)
483 w = lmax;
484 lmin = pvr2_ctrl_get_min(vcp);
485 lmax = pvr2_ctrl_get_max(vcp);
486 pvr2_ctrl_get_def(vcp, &ldef);
487 if (h == -1)
488 h = ldef;
489 else if (h < lmin)
490 h = lmin;
491 else if (h > lmax)
492 h = lmax;
493
494 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
495 sizeof(struct v4l2_format));
496 vf->fmt.pix.width = w;
497 vf->fmt.pix.height = h;
498 return 0;
499}
500
501static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
502{
503 struct pvr2_v4l2_fh *fh = file->private_data;
504 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
505 struct pvr2_ctrl *hcp, *vcp;
506 int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
507
508 if (ret)
509 return ret;
510 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
511 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
512 pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
513 pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
514 return 0;
515}
516
517static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
518{
519 struct pvr2_v4l2_fh *fh = file->private_data;
520 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
521 struct pvr2_v4l2_dev *pdi = fh->pdi;
522 int ret;
523
524 if (!fh->pdi->stream) {
525 /* No stream defined for this node. This means
526 that we're not currently allowed to stream from
527 this node. */
528 return -EPERM;
529 }
530 ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
531 if (ret < 0)
532 return ret;
533 return pvr2_hdw_set_streaming(hdw, !0);
534}
535
536static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
537{
538 struct pvr2_v4l2_fh *fh = file->private_data;
539 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
540
541 if (!fh->pdi->stream) {
542 /* No stream defined for this node. This means
543 that we're not currently allowed to stream from
544 this node. */
545 return -EPERM;
546 }
547 return pvr2_hdw_set_streaming(hdw, 0);
548}
549
550static int pvr2_queryctrl(struct file *file, void *priv,
551 struct v4l2_queryctrl *vc)
552{
553 struct pvr2_v4l2_fh *fh = file->private_data;
554 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
555 struct pvr2_ctrl *cptr;
556 int val;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300557
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300558 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
559 cptr = pvr2_hdw_get_ctrl_nextv4l(
560 hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
561 if (cptr)
562 vc->id = pvr2_ctrl_get_v4lid(cptr);
563 } else {
564 cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
565 }
566 if (!cptr) {
567 pvr2_trace(PVR2_TRACE_V4LIOCTL,
568 "QUERYCTRL id=0x%x not implemented here",
569 vc->id);
570 return -EINVAL;
571 }
572
573 pvr2_trace(PVR2_TRACE_V4LIOCTL,
574 "QUERYCTRL id=0x%x mapping name=%s (%s)",
575 vc->id, pvr2_ctrl_get_name(cptr),
576 pvr2_ctrl_get_desc(cptr));
577 strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
578 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
579 pvr2_ctrl_get_def(cptr, &val);
580 vc->default_value = val;
581 switch (pvr2_ctrl_get_type(cptr)) {
582 case pvr2_ctl_enum:
583 vc->type = V4L2_CTRL_TYPE_MENU;
584 vc->minimum = 0;
585 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
586 vc->step = 1;
587 break;
588 case pvr2_ctl_bool:
589 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
590 vc->minimum = 0;
591 vc->maximum = 1;
592 vc->step = 1;
593 break;
594 case pvr2_ctl_int:
595 vc->type = V4L2_CTRL_TYPE_INTEGER;
596 vc->minimum = pvr2_ctrl_get_min(cptr);
597 vc->maximum = pvr2_ctrl_get_max(cptr);
598 vc->step = 1;
599 break;
600 default:
601 pvr2_trace(PVR2_TRACE_V4LIOCTL,
602 "QUERYCTRL id=0x%x name=%s not mappable",
603 vc->id, pvr2_ctrl_get_name(cptr));
604 return -EINVAL;
605 }
606 return 0;
607}
608
609static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
610{
611 struct pvr2_v4l2_fh *fh = file->private_data;
612 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
613 unsigned int cnt = 0;
614 int ret;
615
616 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
617 vm->index,
618 vm->name, sizeof(vm->name) - 1,
619 &cnt);
620 vm->name[cnt] = 0;
621 return ret;
622}
623
624static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
625{
626 struct pvr2_v4l2_fh *fh = file->private_data;
627 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
628 int val = 0;
629 int ret;
630
631 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
632 &val);
633 vc->value = val;
634 return ret;
635}
636
637static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
638{
639 struct pvr2_v4l2_fh *fh = file->private_data;
640 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
641
642 return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
643 vc->value);
644}
645
646static int pvr2_g_ext_ctrls(struct file *file, void *priv,
647 struct v4l2_ext_controls *ctls)
648{
649 struct pvr2_v4l2_fh *fh = file->private_data;
650 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
651 struct v4l2_ext_control *ctrl;
652 unsigned int idx;
653 int val;
654 int ret;
655
656 ret = 0;
657 for (idx = 0; idx < ctls->count; idx++) {
658 ctrl = ctls->controls + idx;
659 ret = pvr2_ctrl_get_value(
660 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
661 if (ret) {
662 ctls->error_idx = idx;
663 return ret;
664 }
665 /* Ensure that if read as a 64 bit value, the user
666 will still get a hopefully sane value */
667 ctrl->value64 = 0;
668 ctrl->value = val;
669 }
670 return 0;
671}
672
673static int pvr2_s_ext_ctrls(struct file *file, void *priv,
674 struct v4l2_ext_controls *ctls)
675{
676 struct pvr2_v4l2_fh *fh = file->private_data;
677 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
678 struct v4l2_ext_control *ctrl;
679 unsigned int idx;
680 int ret;
681
682 ret = 0;
683 for (idx = 0; idx < ctls->count; idx++) {
684 ctrl = ctls->controls + idx;
685 ret = pvr2_ctrl_set_value(
686 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
687 ctrl->value);
688 if (ret) {
689 ctls->error_idx = idx;
690 return ret;
691 }
692 }
693 return 0;
694}
695
696static int pvr2_try_ext_ctrls(struct file *file, void *priv,
697 struct v4l2_ext_controls *ctls)
698{
699 struct pvr2_v4l2_fh *fh = file->private_data;
700 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
701 struct v4l2_ext_control *ctrl;
702 struct pvr2_ctrl *pctl;
703 unsigned int idx;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300704
705 /* For the moment just validate that the requested control
706 actually exists. */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300707 for (idx = 0; idx < ctls->count; idx++) {
708 ctrl = ctls->controls + idx;
709 pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
710 if (!pctl) {
711 ctls->error_idx = idx;
712 return -EINVAL;
713 }
714 }
715 return 0;
716}
717
718static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
719{
720 struct pvr2_v4l2_fh *fh = file->private_data;
721 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
722 int ret;
723
724 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
725 return -EINVAL;
726 ret = pvr2_hdw_get_cropcap(hdw, cap);
727 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
728 return ret;
729}
730
731static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
732{
733 struct pvr2_v4l2_fh *fh = file->private_data;
734 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
735 int val = 0;
736 int ret;
737
738 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
739 return -EINVAL;
740 ret = pvr2_ctrl_get_value(
741 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
742 if (ret != 0)
743 return -EINVAL;
744 crop->c.left = val;
745 ret = pvr2_ctrl_get_value(
746 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
747 if (ret != 0)
748 return -EINVAL;
749 crop->c.top = val;
750 ret = pvr2_ctrl_get_value(
751 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
752 if (ret != 0)
753 return -EINVAL;
754 crop->c.width = val;
755 ret = pvr2_ctrl_get_value(
756 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
757 if (ret != 0)
758 return -EINVAL;
759 crop->c.height = val;
760 return 0;
761}
762
Hans Verkuil4f996592012-09-05 05:10:48 -0300763static int pvr2_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300764{
765 struct pvr2_v4l2_fh *fh = file->private_data;
766 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300767 int ret;
768
769 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
770 return -EINVAL;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300771 ret = pvr2_ctrl_set_value(
772 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
773 crop->c.left);
774 if (ret != 0)
775 return -EINVAL;
776 ret = pvr2_ctrl_set_value(
777 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
778 crop->c.top);
779 if (ret != 0)
780 return -EINVAL;
781 ret = pvr2_ctrl_set_value(
782 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
783 crop->c.width);
784 if (ret != 0)
785 return -EINVAL;
786 ret = pvr2_ctrl_set_value(
787 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
788 crop->c.height);
789 if (ret != 0)
790 return -EINVAL;
791 return 0;
792}
793
794static int pvr2_log_status(struct file *file, void *priv)
795{
796 struct pvr2_v4l2_fh *fh = file->private_data;
797 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
798
799 pvr2_hdw_trigger_module_log(hdw);
800 return 0;
801}
802
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300803static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
804 .vidioc_querycap = pvr2_querycap,
805 .vidioc_g_priority = pvr2_g_priority,
806 .vidioc_s_priority = pvr2_s_priority,
807 .vidioc_s_audio = pvr2_s_audio,
808 .vidioc_g_audio = pvr2_g_audio,
809 .vidioc_enumaudio = pvr2_enumaudio,
810 .vidioc_enum_input = pvr2_enum_input,
811 .vidioc_cropcap = pvr2_cropcap,
812 .vidioc_s_crop = pvr2_s_crop,
813 .vidioc_g_crop = pvr2_g_crop,
814 .vidioc_g_input = pvr2_g_input,
815 .vidioc_s_input = pvr2_s_input,
816 .vidioc_g_frequency = pvr2_g_frequency,
817 .vidioc_s_frequency = pvr2_s_frequency,
818 .vidioc_s_tuner = pvr2_s_tuner,
819 .vidioc_g_tuner = pvr2_g_tuner,
820 .vidioc_g_std = pvr2_g_std,
821 .vidioc_s_std = pvr2_s_std,
Mike Isely0927ee62012-02-20 02:26:06 -0300822 .vidioc_querystd = pvr2_querystd,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300823 .vidioc_log_status = pvr2_log_status,
824 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
825 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
826 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
827 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
828 .vidioc_streamon = pvr2_streamon,
829 .vidioc_streamoff = pvr2_streamoff,
830 .vidioc_queryctrl = pvr2_queryctrl,
831 .vidioc_querymenu = pvr2_querymenu,
832 .vidioc_g_ctrl = pvr2_g_ctrl,
833 .vidioc_s_ctrl = pvr2_s_ctrl,
834 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
835 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
836 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300837};
838
Mike Iselyd8554972006-06-26 20:58:46 -0300839static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
840{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300841 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300842 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300843 char msg[80];
844 unsigned int mcnt;
845
846 /* Construct the unregistration message *before* we actually
847 perform the unregistration step. By doing it this way we don't
848 have to worry about potentially touching deleted resources. */
849 mcnt = scnprintf(msg, sizeof(msg) - 1,
850 "pvrusb2: unregistered device %s [%s]",
851 video_device_node_name(&dip->devbase),
852 pvr2_config_get_name(cfg));
853 msg[mcnt] = 0;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300854
Mike Isely16eb40d2006-12-30 18:27:32 -0300855 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300856
857 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300858 dip->v4lp = NULL;
859 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300860
861 /* Actual deallocation happens later when all internal references
862 are gone. */
863 video_unregister_device(&dip->devbase);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300864
Mike Iselyd72baad2010-05-15 00:15:38 -0300865 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300866
Mike Iselyd8554972006-06-26 20:58:46 -0300867}
868
869
Mike Isely4a89baa2009-10-12 00:13:28 -0300870static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
871{
872 if (!dip) return;
873 if (!dip->devbase.parent) return;
874 dip->devbase.parent = NULL;
875 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
876}
877
878
Mike Iselyd8554972006-06-26 20:58:46 -0300879static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
880{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300881 if (vp->dev_video) {
882 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000883 vp->dev_video = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300884 }
885 if (vp->dev_radio) {
886 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000887 vp->dev_radio = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300888 }
Mike Iselyd8554972006-06-26 20:58:46 -0300889
890 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
891 pvr2_channel_done(&vp->channel);
892 kfree(vp);
893}
894
895
Mike Isely75910052006-09-23 22:30:50 -0300896static void pvr2_video_device_release(struct video_device *vdev)
897{
898 struct pvr2_v4l2_dev *dev;
899 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
900 kfree(dev);
901}
902
903
Adrian Bunk07e337e2006-06-30 11:30:20 -0300904static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300905{
906 struct pvr2_v4l2 *vp;
907 vp = container_of(chp,struct pvr2_v4l2,channel);
908 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300909 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
910 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Mike Iselyd8554972006-06-26 20:58:46 -0300911 if (vp->vfirst) return;
912 pvr2_v4l2_destroy_no_lock(vp);
913}
914
915
Hans Verkuil069b7472008-12-30 07:04:34 -0300916static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300917 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300918{
919
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300920 struct pvr2_v4l2_fh *fh = file->private_data;
921 struct pvr2_v4l2 *vp = fh->vhead;
922 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
923 long ret = -EINVAL;
924
925 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
Hans Verkuil4a085162012-06-22 06:38:06 -0300926 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300927
928 if (!pvr2_hdw_dev_ok(hdw)) {
929 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
930 "ioctl failed - bad or no context");
931 return -EFAULT;
932 }
933
934 /* check priority */
935 switch (cmd) {
936 case VIDIOC_S_CTRL:
937 case VIDIOC_S_STD:
938 case VIDIOC_S_INPUT:
939 case VIDIOC_S_TUNER:
940 case VIDIOC_S_FREQUENCY:
941 ret = v4l2_prio_check(&vp->prio, fh->prio);
942 if (ret)
943 return ret;
944 }
945
946 ret = video_ioctl2(file, cmd, arg);
947
948 pvr2_hdw_commit_ctl(hdw);
949
950 if (ret < 0) {
951 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
952 pvr2_trace(PVR2_TRACE_V4LIOCTL,
953 "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
954 } else {
955 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
956 pvr2_trace(PVR2_TRACE_V4LIOCTL,
957 "pvr2_v4l2_do_ioctl failure, ret=%ld"
958 " command was:", ret);
Hans Verkuil4a085162012-06-22 06:38:06 -0300959 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw),
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300960 cmd);
961 }
962 }
963 } else {
964 pvr2_trace(PVR2_TRACE_V4LIOCTL,
965 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
966 ret, ret);
967 }
968 return ret;
969
Mike Iselyd8554972006-06-26 20:58:46 -0300970}
971
972
Hans Verkuilbec43662008-12-30 06:58:20 -0300973static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300974{
975 struct pvr2_v4l2_fh *fhp = file->private_data;
976 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300977 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300978
979 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
980
981 if (fhp->rhp) {
982 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300983 pvr2_hdw_set_streaming(hdw,0);
984 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300985 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300986 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300987 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300988 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300989
Hans Verkuilffb48772010-05-01 08:03:24 -0300990 v4l2_prio_close(&vp->prio, fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300991 file->private_data = NULL;
992
Mike Isely794b1602008-04-22 14:45:45 -0300993 if (fhp->vnext) {
994 fhp->vnext->vprev = fhp->vprev;
995 } else {
996 vp->vlast = fhp->vprev;
997 }
998 if (fhp->vprev) {
999 fhp->vprev->vnext = fhp->vnext;
1000 } else {
1001 vp->vfirst = fhp->vnext;
1002 }
1003 fhp->vnext = NULL;
1004 fhp->vprev = NULL;
1005 fhp->vhead = NULL;
1006 pvr2_channel_done(&fhp->channel);
1007 pvr2_trace(PVR2_TRACE_STRUCT,
1008 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -03001009 if (fhp->input_map) {
1010 kfree(fhp->input_map);
1011 fhp->input_map = NULL;
1012 }
Mike Isely794b1602008-04-22 14:45:45 -03001013 kfree(fhp);
1014 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
1015 pvr2_v4l2_destroy_no_lock(vp);
1016 }
Mike Iselyd8554972006-06-26 20:58:46 -03001017 return 0;
1018}
1019
1020
Hans Verkuilbec43662008-12-30 06:58:20 -03001021static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001022{
Mike Isely75910052006-09-23 22:30:50 -03001023 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001024 struct pvr2_v4l2_fh *fhp;
1025 struct pvr2_v4l2 *vp;
1026 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001027 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001028 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001029 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001030
Mike Isely75910052006-09-23 22:30:50 -03001031 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001032
1033 vp = dip->v4lp;
1034 hdw = vp->channel.hdw;
1035
1036 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1037
1038 if (!pvr2_hdw_dev_ok(hdw)) {
1039 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1040 "pvr2_v4l2_open: hardware not ready");
1041 return -EIO;
1042 }
1043
Mike Isely4b85dee2007-01-20 00:03:32 -03001044 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001045 if (!fhp) {
1046 return -ENOMEM;
1047 }
Mike Iselyd8554972006-06-26 20:58:46 -03001048
1049 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001050 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001051
Mike Isely794b1602008-04-22 14:45:45 -03001052 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1053 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001054
Mike Isely1cb03b72008-04-21 03:47:43 -03001055 if (dip->v4l_type == VFL_TYPE_RADIO) {
1056 /* Opening device as a radio, legal input selection subset
1057 is just the radio. */
1058 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1059 } else {
1060 /* Opening the main V4L device, legal input selection
1061 subset includes all analog inputs. */
1062 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1063 (1 << PVR2_CVAL_INPUT_TV) |
1064 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1065 (1 << PVR2_CVAL_INPUT_SVIDEO));
1066 }
1067 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1068 if (ret) {
1069 pvr2_channel_done(&fhp->channel);
1070 pvr2_trace(PVR2_TRACE_STRUCT,
1071 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1072 fhp);
1073
1074 kfree(fhp);
1075 return ret;
1076 }
1077
Mike Iselye57b1c82008-04-21 03:52:34 -03001078 input_mask &= pvr2_hdw_get_input_available(hdw);
1079 input_cnt = 0;
1080 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1081 if (input_mask & (1 << idx)) input_cnt++;
1082 }
1083 fhp->input_cnt = input_cnt;
1084 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1085 if (!fhp->input_map) {
1086 pvr2_channel_done(&fhp->channel);
1087 pvr2_trace(PVR2_TRACE_STRUCT,
1088 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1089 fhp);
1090 kfree(fhp);
1091 return -ENOMEM;
1092 }
1093 input_cnt = 0;
1094 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1095 if (!(input_mask & (1 << idx))) continue;
1096 fhp->input_map[input_cnt++] = idx;
1097 }
1098
Mike Isely794b1602008-04-22 14:45:45 -03001099 fhp->vnext = NULL;
1100 fhp->vprev = vp->vlast;
1101 if (vp->vlast) {
1102 vp->vlast->vnext = fhp;
1103 } else {
1104 vp->vfirst = fhp;
1105 }
1106 vp->vlast = fhp;
1107 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001108
Mike Iselyd8554972006-06-26 20:58:46 -03001109 fhp->file = file;
1110 file->private_data = fhp;
Hans Verkuilffb48772010-05-01 08:03:24 -03001111 v4l2_prio_open(&vp->prio, &fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001112
1113 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1114
1115 return 0;
1116}
1117
1118
1119static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1120{
1121 wake_up(&fhp->wait_data);
1122}
1123
1124static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1125{
1126 int ret;
1127 struct pvr2_stream *sp;
1128 struct pvr2_hdw *hdw;
1129 if (fh->rhp) return 0;
1130
Joe Perches108bdd72010-04-05 16:05:39 -03001131 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001132 /* No stream defined for this node. This means that we're
1133 not currently allowed to stream from this node. */
1134 return -EPERM;
1135 }
1136
Mike Iselyd8554972006-06-26 20:58:46 -03001137 /* First read() attempt. Try to claim the stream and start
1138 it... */
1139 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001140 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001141 /* Someone else must already have it */
1142 return ret;
1143 }
1144
Joe Perches108bdd72010-04-05 16:05:39 -03001145 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001146 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001147 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001148 return -ENOMEM;
1149 }
1150
1151 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001152 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001153 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001154 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001155 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1156 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001157}
1158
1159
1160static ssize_t pvr2_v4l2_read(struct file *file,
1161 char __user *buff, size_t count, loff_t *ppos)
1162{
1163 struct pvr2_v4l2_fh *fh = file->private_data;
1164 int ret;
1165
1166 if (fh->fw_mode_flag) {
1167 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1168 char *tbuf;
1169 int c1,c2;
1170 int tcnt = 0;
1171 unsigned int offs = *ppos;
1172
1173 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1174 if (!tbuf) return -ENOMEM;
1175
1176 while (count) {
1177 c1 = count;
1178 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1179 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1180 if (c2 < 0) {
1181 tcnt = c2;
1182 break;
1183 }
1184 if (!c2) break;
1185 if (copy_to_user(buff,tbuf,c2)) {
1186 tcnt = -EFAULT;
1187 break;
1188 }
1189 offs += c2;
1190 tcnt += c2;
1191 buff += c2;
1192 count -= c2;
1193 *ppos += c2;
1194 }
1195 kfree(tbuf);
1196 return tcnt;
1197 }
1198
1199 if (!fh->rhp) {
1200 ret = pvr2_v4l2_iosetup(fh);
1201 if (ret) {
1202 return ret;
1203 }
1204 }
1205
1206 for (;;) {
1207 ret = pvr2_ioread_read(fh->rhp,buff,count);
1208 if (ret >= 0) break;
1209 if (ret != -EAGAIN) break;
1210 if (file->f_flags & O_NONBLOCK) break;
1211 /* Doing blocking I/O. Wait here. */
1212 ret = wait_event_interruptible(
1213 fh->wait_data,
1214 pvr2_ioread_avail(fh->rhp) >= 0);
1215 if (ret < 0) break;
1216 }
1217
1218 return ret;
1219}
1220
1221
1222static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1223{
1224 unsigned int mask = 0;
1225 struct pvr2_v4l2_fh *fh = file->private_data;
1226 int ret;
1227
1228 if (fh->fw_mode_flag) {
1229 mask |= POLLIN | POLLRDNORM;
1230 return mask;
1231 }
1232
1233 if (!fh->rhp) {
1234 ret = pvr2_v4l2_iosetup(fh);
1235 if (ret) return POLLERR;
1236 }
1237
1238 poll_wait(file,&fh->wait_data,wait);
1239
1240 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1241 mask |= POLLIN | POLLRDNORM;
1242 }
1243
1244 return mask;
1245}
1246
1247
Hans Verkuilbec43662008-12-30 06:58:20 -03001248static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001249 .owner = THIS_MODULE,
1250 .open = pvr2_v4l2_open,
1251 .release = pvr2_v4l2_release,
1252 .read = pvr2_v4l2_read,
1253 .ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001254 .poll = pvr2_v4l2_poll,
1255};
1256
1257
Mike Iselyd8554972006-06-26 20:58:46 -03001258static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001259 .fops = &vdev_fops,
1260};
1261
1262
1263static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1264 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001265 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001266{
Mike Isely4a89baa2009-10-12 00:13:28 -03001267 struct usb_device *usbdev;
Mike Iselyd8554972006-06-26 20:58:46 -03001268 int mindevnum;
1269 int unit_number;
Mike Isely598e9782012-02-20 02:35:20 -03001270 struct pvr2_hdw *hdw;
Al Viro89952d12007-03-14 09:17:59 +00001271 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001272 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001273
Mike Isely598e9782012-02-20 02:35:20 -03001274 hdw = vp->channel.mc_head->hdw;
1275 usbdev = pvr2_hdw_get_dev(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001276 dip->v4l_type = v4l_type;
1277 switch (v4l_type) {
1278 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001279 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001280 dip->config = pvr2_config_mpeg;
1281 dip->minor_type = pvr2_v4l_type_video;
1282 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001283 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001284 pr_err(KBUILD_MODNAME
1285 ": Failed to set up pvrusb2 v4l video dev"
1286 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001287 return;
1288 }
Mike Iselyd8554972006-06-26 20:58:46 -03001289 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001290 case VFL_TYPE_VBI:
1291 dip->config = pvr2_config_vbi;
1292 dip->minor_type = pvr2_v4l_type_vbi;
1293 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001294 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001295 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001296 dip->stream = &vp->channel.mc_head->video_stream;
1297 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001298 dip->minor_type = pvr2_v4l_type_radio;
1299 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001300 break;
1301 default:
1302 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001303 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1304 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001305 return;
1306 }
1307
Ezequiel Garcia5338c162012-10-23 15:57:09 -03001308 dip->devbase = vdev_template;
Mike Isely75910052006-09-23 22:30:50 -03001309 dip->devbase.release = pvr2_video_device_release;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -03001310 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
Mike Iselyd8329f82012-02-20 02:33:06 -03001311 {
1312 int val;
1313 pvr2_ctrl_get_value(
Mike Isely598e9782012-02-20 02:35:20 -03001314 pvr2_hdw_get_ctrl_by_id(hdw,
Mike Iselyd8329f82012-02-20 02:33:06 -03001315 PVR2_CID_STDAVAIL), &val);
1316 dip->devbase.tvnorms = (v4l2_std_id)val;
1317 }
Mike Iselyd8554972006-06-26 20:58:46 -03001318
1319 mindevnum = -1;
Mike Isely598e9782012-02-20 02:35:20 -03001320 unit_number = pvr2_hdw_get_unit_number(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001321 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1322 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001323 }
Mike Isely4a89baa2009-10-12 00:13:28 -03001324 dip->devbase.parent = &usbdev->dev;
Mike Isely16eb40d2006-12-30 18:27:32 -03001325 if ((video_register_device(&dip->devbase,
1326 dip->v4l_type, mindevnum) < 0) &&
1327 (video_register_device(&dip->devbase,
1328 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001329 pr_err(KBUILD_MODNAME
1330 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001331 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001332
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001333 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1334 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001335 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001336
Mike Isely598e9782012-02-20 02:35:20 -03001337 pvr2_hdw_v4l_store_minor_number(hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001338 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001339}
1340
1341
1342struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1343{
1344 struct pvr2_v4l2 *vp;
1345
Mike Isely4b85dee2007-01-20 00:03:32 -03001346 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001347 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001348 pvr2_channel_init(&vp->channel,mnp);
1349 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1350
1351 vp->channel.check_func = pvr2_v4l2_internal_check;
1352
1353 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001354 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1355 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001356 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001357 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1358 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001359 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1360 if (!vp->dev_radio) goto fail;
1361 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1362 }
Mike Iselyd8554972006-06-26 20:58:46 -03001363
1364 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001365 fail:
1366 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1367 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001368 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001369}
1370
1371/*
1372 Stuff for Emacs to see, in order to encourage consistent editing style:
1373 *** Local Variables: ***
1374 *** mode: c ***
1375 *** fill-column: 75 ***
1376 *** tab-width: 8 ***
1377 *** c-basic-offset: 8 ***
1378 *** End: ***
1379 */