blob: 6930676051e74fb0efda27771520ca0dd913b7fc [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 Isely0f0f2572006-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
Mauro Carvalho Chehabf4a51222012-10-27 14:17:42 -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(
205 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), *std);
206}
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
355static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
356{
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
Mauro Carvalho Chehabf4a51222012-10-27 14:17:42 -0300368static int pvr2_s_frequency(struct file *file, void *priv, 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
803#ifdef CONFIG_VIDEO_ADV_DEBUG
804static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
805{
806 struct pvr2_v4l2_fh *fh = file->private_data;
807 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
808 u64 val;
809 int ret;
810
811 ret = pvr2_hdw_register_access(
812 hdw, &req->match, req->reg,
813 0, &val);
814 req->val = val;
815 return ret;
816}
817
818static int pvr2_s_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
819{
820 struct pvr2_v4l2_fh *fh = file->private_data;
821 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
822 u64 val;
823 int ret;
824
825 val = req->val;
826 ret = pvr2_hdw_register_access(
827 hdw, &req->match, req->reg,
828 1, &val);
829 return ret;
830}
831#endif
832
833static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
834 .vidioc_querycap = pvr2_querycap,
835 .vidioc_g_priority = pvr2_g_priority,
836 .vidioc_s_priority = pvr2_s_priority,
837 .vidioc_s_audio = pvr2_s_audio,
838 .vidioc_g_audio = pvr2_g_audio,
839 .vidioc_enumaudio = pvr2_enumaudio,
840 .vidioc_enum_input = pvr2_enum_input,
841 .vidioc_cropcap = pvr2_cropcap,
842 .vidioc_s_crop = pvr2_s_crop,
843 .vidioc_g_crop = pvr2_g_crop,
844 .vidioc_g_input = pvr2_g_input,
845 .vidioc_s_input = pvr2_s_input,
846 .vidioc_g_frequency = pvr2_g_frequency,
847 .vidioc_s_frequency = pvr2_s_frequency,
848 .vidioc_s_tuner = pvr2_s_tuner,
849 .vidioc_g_tuner = pvr2_g_tuner,
850 .vidioc_g_std = pvr2_g_std,
851 .vidioc_s_std = pvr2_s_std,
Mike Isely0927ee62012-02-20 02:26:06 -0300852 .vidioc_querystd = pvr2_querystd,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300853 .vidioc_log_status = pvr2_log_status,
854 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
855 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
856 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
857 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
858 .vidioc_streamon = pvr2_streamon,
859 .vidioc_streamoff = pvr2_streamoff,
860 .vidioc_queryctrl = pvr2_queryctrl,
861 .vidioc_querymenu = pvr2_querymenu,
862 .vidioc_g_ctrl = pvr2_g_ctrl,
863 .vidioc_s_ctrl = pvr2_s_ctrl,
864 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
865 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
866 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
867#ifdef CONFIG_VIDEO_ADV_DEBUG
868 .vidioc_g_register = pvr2_g_register,
869 .vidioc_s_register = pvr2_s_register,
870#endif
871};
872
Mike Iselyd8554972006-06-26 20:58:46 -0300873static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
874{
Mike Isely0f0f2572006-12-27 23:19:42 -0300875 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300876 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300877 char msg[80];
878 unsigned int mcnt;
879
880 /* Construct the unregistration message *before* we actually
881 perform the unregistration step. By doing it this way we don't
882 have to worry about potentially touching deleted resources. */
883 mcnt = scnprintf(msg, sizeof(msg) - 1,
884 "pvrusb2: unregistered device %s [%s]",
885 video_device_node_name(&dip->devbase),
886 pvr2_config_get_name(cfg));
887 msg[mcnt] = 0;
Mike Isely0f0f2572006-12-27 23:19:42 -0300888
Mike Isely16eb40d2006-12-30 18:27:32 -0300889 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300890
891 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300892 dip->v4lp = NULL;
893 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300894
895 /* Actual deallocation happens later when all internal references
896 are gone. */
897 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300898
Mike Iselyd72baad2010-05-15 00:15:38 -0300899 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f2572006-12-27 23:19:42 -0300900
Mike Iselyd8554972006-06-26 20:58:46 -0300901}
902
903
Mike Isely4a89baa2009-10-12 00:13:28 -0300904static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
905{
906 if (!dip) return;
907 if (!dip->devbase.parent) return;
908 dip->devbase.parent = NULL;
909 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
910}
911
912
Mike Iselyd8554972006-06-26 20:58:46 -0300913static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
914{
Mike Isely0f0f2572006-12-27 23:19:42 -0300915 if (vp->dev_video) {
916 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000917 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300918 }
919 if (vp->dev_radio) {
920 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000921 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300922 }
Mike Iselyd8554972006-06-26 20:58:46 -0300923
924 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
925 pvr2_channel_done(&vp->channel);
926 kfree(vp);
927}
928
929
Mike Isely75910052006-09-23 22:30:50 -0300930static void pvr2_video_device_release(struct video_device *vdev)
931{
932 struct pvr2_v4l2_dev *dev;
933 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
934 kfree(dev);
935}
936
937
Adrian Bunk07e337e2006-06-30 11:30:20 -0300938static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300939{
940 struct pvr2_v4l2 *vp;
941 vp = container_of(chp,struct pvr2_v4l2,channel);
942 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300943 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
944 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Mike Iselyd8554972006-06-26 20:58:46 -0300945 if (vp->vfirst) return;
946 pvr2_v4l2_destroy_no_lock(vp);
947}
948
949
Hans Verkuil069b7472008-12-30 07:04:34 -0300950static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300951 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300952{
953
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300954 struct pvr2_v4l2_fh *fh = file->private_data;
955 struct pvr2_v4l2 *vp = fh->vhead;
956 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
957 long ret = -EINVAL;
958
959 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
Hans Verkuil4a085162012-06-22 06:38:06 -0300960 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300961
962 if (!pvr2_hdw_dev_ok(hdw)) {
963 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
964 "ioctl failed - bad or no context");
965 return -EFAULT;
966 }
967
968 /* check priority */
969 switch (cmd) {
970 case VIDIOC_S_CTRL:
971 case VIDIOC_S_STD:
972 case VIDIOC_S_INPUT:
973 case VIDIOC_S_TUNER:
974 case VIDIOC_S_FREQUENCY:
975 ret = v4l2_prio_check(&vp->prio, fh->prio);
976 if (ret)
977 return ret;
978 }
979
980 ret = video_ioctl2(file, cmd, arg);
981
982 pvr2_hdw_commit_ctl(hdw);
983
984 if (ret < 0) {
985 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
986 pvr2_trace(PVR2_TRACE_V4LIOCTL,
987 "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
988 } else {
989 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
990 pvr2_trace(PVR2_TRACE_V4LIOCTL,
991 "pvr2_v4l2_do_ioctl failure, ret=%ld"
992 " command was:", ret);
Hans Verkuil4a085162012-06-22 06:38:06 -0300993 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw),
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300994 cmd);
995 }
996 }
997 } else {
998 pvr2_trace(PVR2_TRACE_V4LIOCTL,
999 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
1000 ret, ret);
1001 }
1002 return ret;
1003
Mike Iselyd8554972006-06-26 20:58:46 -03001004}
1005
1006
Hans Verkuilbec43662008-12-30 06:58:20 -03001007static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001008{
1009 struct pvr2_v4l2_fh *fhp = file->private_data;
1010 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -03001011 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -03001012
1013 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
1014
1015 if (fhp->rhp) {
1016 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -03001017 pvr2_hdw_set_streaming(hdw,0);
1018 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001019 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001020 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001021 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001022 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001023
Hans Verkuilffb48772010-05-01 08:03:24 -03001024 v4l2_prio_close(&vp->prio, fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001025 file->private_data = NULL;
1026
Mike Isely794b1602008-04-22 14:45:45 -03001027 if (fhp->vnext) {
1028 fhp->vnext->vprev = fhp->vprev;
1029 } else {
1030 vp->vlast = fhp->vprev;
1031 }
1032 if (fhp->vprev) {
1033 fhp->vprev->vnext = fhp->vnext;
1034 } else {
1035 vp->vfirst = fhp->vnext;
1036 }
1037 fhp->vnext = NULL;
1038 fhp->vprev = NULL;
1039 fhp->vhead = NULL;
1040 pvr2_channel_done(&fhp->channel);
1041 pvr2_trace(PVR2_TRACE_STRUCT,
1042 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -03001043 if (fhp->input_map) {
1044 kfree(fhp->input_map);
1045 fhp->input_map = NULL;
1046 }
Mike Isely794b1602008-04-22 14:45:45 -03001047 kfree(fhp);
1048 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
1049 pvr2_v4l2_destroy_no_lock(vp);
1050 }
Mike Iselyd8554972006-06-26 20:58:46 -03001051 return 0;
1052}
1053
1054
Hans Verkuilbec43662008-12-30 06:58:20 -03001055static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001056{
Mike Isely75910052006-09-23 22:30:50 -03001057 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001058 struct pvr2_v4l2_fh *fhp;
1059 struct pvr2_v4l2 *vp;
1060 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001061 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001062 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001063 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001064
Mike Isely75910052006-09-23 22:30:50 -03001065 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001066
1067 vp = dip->v4lp;
1068 hdw = vp->channel.hdw;
1069
1070 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1071
1072 if (!pvr2_hdw_dev_ok(hdw)) {
1073 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1074 "pvr2_v4l2_open: hardware not ready");
1075 return -EIO;
1076 }
1077
Mike Isely4b85dee2007-01-20 00:03:32 -03001078 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001079 if (!fhp) {
1080 return -ENOMEM;
1081 }
Mike Iselyd8554972006-06-26 20:58:46 -03001082
1083 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001084 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001085
Mike Isely794b1602008-04-22 14:45:45 -03001086 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1087 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001088
Mike Isely1cb03b72008-04-21 03:47:43 -03001089 if (dip->v4l_type == VFL_TYPE_RADIO) {
1090 /* Opening device as a radio, legal input selection subset
1091 is just the radio. */
1092 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1093 } else {
1094 /* Opening the main V4L device, legal input selection
1095 subset includes all analog inputs. */
1096 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1097 (1 << PVR2_CVAL_INPUT_TV) |
1098 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1099 (1 << PVR2_CVAL_INPUT_SVIDEO));
1100 }
1101 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1102 if (ret) {
1103 pvr2_channel_done(&fhp->channel);
1104 pvr2_trace(PVR2_TRACE_STRUCT,
1105 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1106 fhp);
1107
1108 kfree(fhp);
1109 return ret;
1110 }
1111
Mike Iselye57b1c82008-04-21 03:52:34 -03001112 input_mask &= pvr2_hdw_get_input_available(hdw);
1113 input_cnt = 0;
1114 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1115 if (input_mask & (1 << idx)) input_cnt++;
1116 }
1117 fhp->input_cnt = input_cnt;
1118 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1119 if (!fhp->input_map) {
1120 pvr2_channel_done(&fhp->channel);
1121 pvr2_trace(PVR2_TRACE_STRUCT,
1122 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1123 fhp);
1124 kfree(fhp);
1125 return -ENOMEM;
1126 }
1127 input_cnt = 0;
1128 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1129 if (!(input_mask & (1 << idx))) continue;
1130 fhp->input_map[input_cnt++] = idx;
1131 }
1132
Mike Isely794b1602008-04-22 14:45:45 -03001133 fhp->vnext = NULL;
1134 fhp->vprev = vp->vlast;
1135 if (vp->vlast) {
1136 vp->vlast->vnext = fhp;
1137 } else {
1138 vp->vfirst = fhp;
1139 }
1140 vp->vlast = fhp;
1141 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001142
Mike Iselyd8554972006-06-26 20:58:46 -03001143 fhp->file = file;
1144 file->private_data = fhp;
Hans Verkuilffb48772010-05-01 08:03:24 -03001145 v4l2_prio_open(&vp->prio, &fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001146
1147 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1148
1149 return 0;
1150}
1151
1152
1153static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1154{
1155 wake_up(&fhp->wait_data);
1156}
1157
1158static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1159{
1160 int ret;
1161 struct pvr2_stream *sp;
1162 struct pvr2_hdw *hdw;
1163 if (fh->rhp) return 0;
1164
Joe Perches108bdd72010-04-05 16:05:39 -03001165 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001166 /* No stream defined for this node. This means that we're
1167 not currently allowed to stream from this node. */
1168 return -EPERM;
1169 }
1170
Mike Iselyd8554972006-06-26 20:58:46 -03001171 /* First read() attempt. Try to claim the stream and start
1172 it... */
1173 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001174 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001175 /* Someone else must already have it */
1176 return ret;
1177 }
1178
Joe Perches108bdd72010-04-05 16:05:39 -03001179 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001180 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001181 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001182 return -ENOMEM;
1183 }
1184
1185 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001186 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001187 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001188 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001189 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1190 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001191}
1192
1193
1194static ssize_t pvr2_v4l2_read(struct file *file,
1195 char __user *buff, size_t count, loff_t *ppos)
1196{
1197 struct pvr2_v4l2_fh *fh = file->private_data;
1198 int ret;
1199
1200 if (fh->fw_mode_flag) {
1201 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1202 char *tbuf;
1203 int c1,c2;
1204 int tcnt = 0;
1205 unsigned int offs = *ppos;
1206
1207 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1208 if (!tbuf) return -ENOMEM;
1209
1210 while (count) {
1211 c1 = count;
1212 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1213 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1214 if (c2 < 0) {
1215 tcnt = c2;
1216 break;
1217 }
1218 if (!c2) break;
1219 if (copy_to_user(buff,tbuf,c2)) {
1220 tcnt = -EFAULT;
1221 break;
1222 }
1223 offs += c2;
1224 tcnt += c2;
1225 buff += c2;
1226 count -= c2;
1227 *ppos += c2;
1228 }
1229 kfree(tbuf);
1230 return tcnt;
1231 }
1232
1233 if (!fh->rhp) {
1234 ret = pvr2_v4l2_iosetup(fh);
1235 if (ret) {
1236 return ret;
1237 }
1238 }
1239
1240 for (;;) {
1241 ret = pvr2_ioread_read(fh->rhp,buff,count);
1242 if (ret >= 0) break;
1243 if (ret != -EAGAIN) break;
1244 if (file->f_flags & O_NONBLOCK) break;
1245 /* Doing blocking I/O. Wait here. */
1246 ret = wait_event_interruptible(
1247 fh->wait_data,
1248 pvr2_ioread_avail(fh->rhp) >= 0);
1249 if (ret < 0) break;
1250 }
1251
1252 return ret;
1253}
1254
1255
1256static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1257{
1258 unsigned int mask = 0;
1259 struct pvr2_v4l2_fh *fh = file->private_data;
1260 int ret;
1261
1262 if (fh->fw_mode_flag) {
1263 mask |= POLLIN | POLLRDNORM;
1264 return mask;
1265 }
1266
1267 if (!fh->rhp) {
1268 ret = pvr2_v4l2_iosetup(fh);
1269 if (ret) return POLLERR;
1270 }
1271
1272 poll_wait(file,&fh->wait_data,wait);
1273
1274 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1275 mask |= POLLIN | POLLRDNORM;
1276 }
1277
1278 return mask;
1279}
1280
1281
Hans Verkuilbec43662008-12-30 06:58:20 -03001282static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001283 .owner = THIS_MODULE,
1284 .open = pvr2_v4l2_open,
1285 .release = pvr2_v4l2_release,
1286 .read = pvr2_v4l2_read,
1287 .ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001288 .poll = pvr2_v4l2_poll,
1289};
1290
1291
Mike Iselyd8554972006-06-26 20:58:46 -03001292static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001293 .fops = &vdev_fops,
1294};
1295
1296
1297static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1298 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001299 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001300{
Mike Isely4a89baa2009-10-12 00:13:28 -03001301 struct usb_device *usbdev;
Mike Iselyd8554972006-06-26 20:58:46 -03001302 int mindevnum;
1303 int unit_number;
Mike Isely598e9782012-02-20 02:35:20 -03001304 struct pvr2_hdw *hdw;
Al Viro89952d12007-03-14 09:17:59 +00001305 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001306 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001307
Mike Isely598e9782012-02-20 02:35:20 -03001308 hdw = vp->channel.mc_head->hdw;
1309 usbdev = pvr2_hdw_get_dev(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001310 dip->v4l_type = v4l_type;
1311 switch (v4l_type) {
1312 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001313 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001314 dip->config = pvr2_config_mpeg;
1315 dip->minor_type = pvr2_v4l_type_video;
1316 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001317 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001318 pr_err(KBUILD_MODNAME
1319 ": Failed to set up pvrusb2 v4l video dev"
1320 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001321 return;
1322 }
Mike Iselyd8554972006-06-26 20:58:46 -03001323 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001324 case VFL_TYPE_VBI:
1325 dip->config = pvr2_config_vbi;
1326 dip->minor_type = pvr2_v4l_type_vbi;
1327 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001328 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001329 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001330 dip->stream = &vp->channel.mc_head->video_stream;
1331 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001332 dip->minor_type = pvr2_v4l_type_radio;
1333 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001334 break;
1335 default:
1336 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001337 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1338 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001339 return;
1340 }
1341
Mike Isely75910052006-09-23 22:30:50 -03001342 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1343 dip->devbase.release = pvr2_video_device_release;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -03001344 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
Mike Iselyd8329f82012-02-20 02:33:06 -03001345 {
1346 int val;
1347 pvr2_ctrl_get_value(
Mike Isely598e9782012-02-20 02:35:20 -03001348 pvr2_hdw_get_ctrl_by_id(hdw,
Mike Iselyd8329f82012-02-20 02:33:06 -03001349 PVR2_CID_STDAVAIL), &val);
1350 dip->devbase.tvnorms = (v4l2_std_id)val;
1351 }
Mike Iselyd8554972006-06-26 20:58:46 -03001352
1353 mindevnum = -1;
Mike Isely598e9782012-02-20 02:35:20 -03001354 unit_number = pvr2_hdw_get_unit_number(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001355 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1356 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001357 }
Mike Isely4a89baa2009-10-12 00:13:28 -03001358 dip->devbase.parent = &usbdev->dev;
Mike Isely16eb40d2006-12-30 18:27:32 -03001359 if ((video_register_device(&dip->devbase,
1360 dip->v4l_type, mindevnum) < 0) &&
1361 (video_register_device(&dip->devbase,
1362 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001363 pr_err(KBUILD_MODNAME
1364 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001365 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001366
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001367 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1368 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001369 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001370
Mike Isely598e9782012-02-20 02:35:20 -03001371 pvr2_hdw_v4l_store_minor_number(hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001372 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001373}
1374
1375
1376struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1377{
1378 struct pvr2_v4l2 *vp;
1379
Mike Isely4b85dee2007-01-20 00:03:32 -03001380 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001381 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001382 pvr2_channel_init(&vp->channel,mnp);
1383 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1384
1385 vp->channel.check_func = pvr2_v4l2_internal_check;
1386
1387 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001388 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1389 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001390 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001391 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1392 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001393 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1394 if (!vp->dev_radio) goto fail;
1395 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1396 }
Mike Iselyd8554972006-06-26 20:58:46 -03001397
1398 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001399 fail:
1400 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1401 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001402 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001403}
1404
1405/*
1406 Stuff for Emacs to see, in order to encourage consistent editing style:
1407 *** Local Variables: ***
1408 *** mode: c ***
1409 *** fill-column: 75 ***
1410 *** tab-width: 8 ***
1411 *** c-basic-offset: 8 ***
1412 *** End: ***
1413 */