blob: 1b158f1167ed0722793a8b58b990a1fc378e4a34 [file] [log] [blame]
Mike Iselyd8554972006-06-26 20:58:46 -03001/*
2 *
Mike Iselyd8554972006-06-26 20:58:46 -03003 *
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Mauro Carvalho Chehabce4260c2006-06-26 22:26:08 -030024#include <linux/version.h>
Mike Iselyd8554972006-06-26 20:58:46 -030025#include "pvrusb2-context.h"
26#include "pvrusb2-hdw.h"
27#include "pvrusb2.h"
28#include "pvrusb2-debug.h"
29#include "pvrusb2-v4l2.h"
30#include "pvrusb2-ioread.h"
31#include <linux/videodev2.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040032#include <linux/module.h>
Mike Isely43e06022006-09-23 23:47:50 -030033#include <media/v4l2-dev.h>
Hans Verkuila28fbd02013-06-10 09:16:25 -030034#include <media/v4l2-device.h>
Mike Iselyd8554972006-06-26 20:58:46 -030035#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030036#include <media/v4l2-ioctl.h>
Mike Iselyd8554972006-06-26 20:58:46 -030037
38struct pvr2_v4l2_dev;
39struct pvr2_v4l2_fh;
40struct pvr2_v4l2;
41
Mike Iselyd8554972006-06-26 20:58:46 -030042struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030043 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030044 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030045 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030046 /* Information about this device: */
47 enum pvr2_config config; /* Expected stream format */
48 int v4l_type; /* V4L defined type for this device node */
49 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030050};
51
52struct pvr2_v4l2_fh {
53 struct pvr2_channel channel;
Joe Perches108bdd72010-04-05 16:05:39 -030054 struct pvr2_v4l2_dev *pdi;
Mike Iselyd8554972006-06-26 20:58:46 -030055 enum v4l2_priority prio;
56 struct pvr2_ioread *rhp;
57 struct file *file;
58 struct pvr2_v4l2 *vhead;
59 struct pvr2_v4l2_fh *vnext;
60 struct pvr2_v4l2_fh *vprev;
61 wait_queue_head_t wait_data;
62 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030063 /* Map contiguous ordinal value to input id */
64 unsigned char *input_map;
65 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030066};
67
68struct pvr2_v4l2 {
69 struct pvr2_channel channel;
70 struct pvr2_v4l2_fh *vfirst;
71 struct pvr2_v4l2_fh *vlast;
72
73 struct v4l2_prio_state prio;
74
Mike Isely0f0f2572006-12-27 23:19:42 -030075 /* streams - Note that these must be separately, individually,
76 * allocated pointers. This is because the v4l core is going to
77 * manage their deletion - separately, individually... */
78 struct pvr2_v4l2_dev *dev_video;
79 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030080};
81
82static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
83module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030084MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
85static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
86module_param_array(radio_nr, int, NULL, 0444);
87MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
88static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
89module_param_array(vbi_nr, int, NULL, 0444);
90MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030091
Adrian Bunk07e337e2006-06-30 11:30:20 -030092static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030093 .driver = "pvrusb2",
94 .card = "Hauppauge WinTV pvr-usb2",
95 .bus_info = "usb",
Mauro Carvalho Chehab083774d2011-06-25 13:34:24 -030096 .version = LINUX_VERSION_CODE,
Mike Iselyd166b022009-01-14 04:21:29 -030097 .capabilities = (V4L2_CAP_VIDEO_CAPTURE |
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -030098 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
Mike Iselyd8554972006-06-26 20:58:46 -030099 V4L2_CAP_READWRITE),
Mike Iselyd8554972006-06-26 20:58:46 -0300100};
101
Adrian Bunk07e337e2006-06-30 11:30:20 -0300102static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300103 {
104 .index = 0,
105 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
106 .flags = V4L2_FMT_FLAG_COMPRESSED,
107 .description = "MPEG1/2",
108 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
109 // breaks when I do that.
110 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
Mike Iselyd8554972006-06-26 20:58:46 -0300111 }
112};
113
114#define PVR_FORMAT_PIX 0
115#define PVR_FORMAT_VBI 1
116
Adrian Bunk07e337e2006-06-30 11:30:20 -0300117static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300118 [PVR_FORMAT_PIX] = {
119 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
120 .fmt = {
121 .pix = {
122 .width = 720,
123 .height = 576,
124 // This should really be V4L2_PIX_FMT_MPEG,
125 // but xawtv breaks when I do that.
126 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
127 .field = V4L2_FIELD_INTERLACED,
128 .bytesperline = 0, // doesn't make sense
129 // here
130 //FIXME : Don't know what to put here...
131 .sizeimage = (32*1024),
132 .colorspace = 0, // doesn't make sense here
133 .priv = 0
134 }
135 }
136 },
137 [PVR_FORMAT_VBI] = {
138 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
139 .fmt = {
140 .vbi = {
141 .sampling_rate = 27000000,
142 .offset = 248,
143 .samples_per_line = 1443,
144 .sample_format = V4L2_PIX_FMT_GREY,
145 .start = { 0, 0 },
146 .count = { 0, 0 },
147 .flags = 0,
Mike Iselyd8554972006-06-26 20:58:46 -0300148 }
149 }
150 }
151};
152
Mike Isely16eb40d2006-12-30 18:27:32 -0300153
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300154
Mike Iselyd8554972006-06-26 20:58:46 -0300155/*
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300156 * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
Mike Iselyd8554972006-06-26 20:58:46 -0300157 */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300158static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
159{
160 struct pvr2_v4l2_fh *fh = file->private_data;
161 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
162
163 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
164 strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
165 sizeof(cap->bus_info));
166 strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
167 return 0;
168}
169
170static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
Mike Iselyd8554972006-06-26 20:58:46 -0300171{
172 struct pvr2_v4l2_fh *fh = file->private_data;
173 struct pvr2_v4l2 *vp = fh->vhead;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300174
175 *p = v4l2_prio_max(&vp->prio);
176 return 0;
177}
178
179static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
180{
181 struct pvr2_v4l2_fh *fh = file->private_data;
182 struct pvr2_v4l2 *vp = fh->vhead;
183
184 return v4l2_prio_change(&vp->prio, &fh->prio, prio);
185}
186
187static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
188{
189 struct pvr2_v4l2_fh *fh = file->private_data;
Mike Iselyd8554972006-06-26 20:58:46 -0300190 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300191 int val = 0;
192 int ret;
Mike Iselyd8554972006-06-26 20:58:46 -0300193
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300194 ret = pvr2_ctrl_get_value(
195 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
196 *std = val;
197 return ret;
198}
Mike Iselyd8554972006-06-26 20:58:46 -0300199
Hans Verkuil314527a2013-03-15 06:10:40 -0300200static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300201{
202 struct pvr2_v4l2_fh *fh = file->private_data;
203 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300204
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300205 return pvr2_ctrl_set_value(
Hans Verkuil314527a2013-03-15 06:10:40 -0300206 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300207}
Mike Iselyd8554972006-06-26 20:58:46 -0300208
Mike Isely0927ee62012-02-20 02:26:06 -0300209static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
210{
211 struct pvr2_v4l2_fh *fh = file->private_data;
212 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Mike Iselyac04d002012-02-20 02:28:56 -0300213 int val = 0;
214 int ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300215
Mike Iselyac04d002012-02-20 02:28:56 -0300216 ret = pvr2_ctrl_get_value(
217 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
218 *std = val;
219 return ret;
Mike Isely0927ee62012-02-20 02:26:06 -0300220}
221
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300222static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
223{
224 struct pvr2_v4l2_fh *fh = file->private_data;
225 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
226 struct pvr2_ctrl *cptr;
227 struct v4l2_input tmp;
228 unsigned int cnt;
229 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300230
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300231 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
Mike Iselyd8554972006-06-26 20:58:46 -0300232
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300233 memset(&tmp, 0, sizeof(tmp));
234 tmp.index = vi->index;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300235 if (vi->index >= fh->input_cnt)
236 return -EINVAL;
237 val = fh->input_map[vi->index];
238 switch (val) {
239 case PVR2_CVAL_INPUT_TV:
240 case PVR2_CVAL_INPUT_DTV:
241 case PVR2_CVAL_INPUT_RADIO:
242 tmp.type = V4L2_INPUT_TYPE_TUNER;
Mike Iselyd8554972006-06-26 20:58:46 -0300243 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300244 case PVR2_CVAL_INPUT_SVIDEO:
245 case PVR2_CVAL_INPUT_COMPOSITE:
246 tmp.type = V4L2_INPUT_TYPE_CAMERA;
Mike Iselyd8554972006-06-26 20:58:46 -0300247 break;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300248 default:
249 return -EINVAL;
Mike Iselyd8554972006-06-26 20:58:46 -0300250 }
251
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300252 cnt = 0;
253 pvr2_ctrl_get_valname(cptr, val,
254 tmp.name, sizeof(tmp.name) - 1, &cnt);
255 tmp.name[cnt] = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300256
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300257 /* Don't bother with audioset, since this driver currently
258 always switches the audio whenever the video is
259 switched. */
Mike Iselyd8554972006-06-26 20:58:46 -0300260
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300261 /* Handling std is a tougher problem. It doesn't make
262 sense in cases where a device might be multi-standard.
263 We could just copy out the current value for the
264 standard, but it can change over time. For now just
265 leave it zero. */
266 *vi = tmp;
267 return 0;
268}
Mike Iselyd8554972006-06-26 20:58:46 -0300269
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300270static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
271{
272 struct pvr2_v4l2_fh *fh = file->private_data;
273 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
274 unsigned int idx;
275 struct pvr2_ctrl *cptr;
276 int val;
277 int ret;
Mauro Carvalho Chehab7383a472011-10-03 12:22:28 -0300278
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300279 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
280 val = 0;
281 ret = pvr2_ctrl_get_value(cptr, &val);
282 *i = 0;
283 for (idx = 0; idx < fh->input_cnt; idx++) {
284 if (fh->input_map[idx] == val) {
285 *i = idx;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300286 break;
287 }
Mike Iselyd8554972006-06-26 20:58:46 -0300288 }
289 return ret;
290}
291
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300292static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
293{
294 struct pvr2_v4l2_fh *fh = file->private_data;
295 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
296
297 if (inp >= fh->input_cnt)
298 return -EINVAL;
299 return pvr2_ctrl_set_value(
300 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
301 fh->input_map[inp]);
302}
303
304static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
305{
306 /* pkt: FIXME: We are returning one "fake" input here
307 which could very well be called "whatever_we_like".
308 This is for apps that want to see an audio input
309 just to feel comfortable, as well as to test if
310 it can do stereo or sth. There is actually no guarantee
311 that the actual audio input cannot change behind the app's
312 back, but most applications should not mind that either.
313
314 Hopefully, mplayer people will work with us on this (this
315 whole mess is to support mplayer pvr://), or Hans will come
316 up with a more standard way to say "we have inputs but we
317 don 't want you to change them independent of video" which
318 will sort this mess.
319 */
320
321 if (vin->index > 0)
322 return -EINVAL;
323 strncpy(vin->name, "PVRUSB2 Audio", 14);
324 vin->capability = V4L2_AUDCAP_STEREO;
325 return 0;
326}
327
328static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
329{
330 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
331 vin->index = 0;
332 strncpy(vin->name, "PVRUSB2 Audio", 14);
333 vin->capability = V4L2_AUDCAP_STEREO;
334 return 0;
335}
336
Hans Verkuil0e8025b92012-09-04 11:59:31 -0300337static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300338{
339 if (vout->index)
340 return -EINVAL;
341 return 0;
342}
343
344static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
345{
346 struct pvr2_v4l2_fh *fh = file->private_data;
347 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
348
349 if (vt->index != 0)
350 return -EINVAL; /* Only answer for the 1st tuner */
351
352 pvr2_hdw_execute_tuner_poll(hdw);
353 return pvr2_hdw_get_tuner_status(hdw, vt);
354}
355
Hans Verkuil2f73c7c2013-03-15 06:10:06 -0300356static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300357{
358 struct pvr2_v4l2_fh *fh = file->private_data;
359 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
360
361 if (vt->index != 0)
362 return -EINVAL;
363
364 return pvr2_ctrl_set_value(
365 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
366 vt->audmode);
367}
368
Hans Verkuilb530a442013-03-19 04:09:26 -0300369static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300370{
371 struct pvr2_v4l2_fh *fh = file->private_data;
372 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
373 unsigned long fv;
374 struct v4l2_tuner vt;
375 int cur_input;
376 struct pvr2_ctrl *ctrlp;
377 int ret;
378
379 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
380 if (ret != 0)
381 return ret;
382 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
383 ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
384 if (ret != 0)
385 return ret;
386 if (vf->type == V4L2_TUNER_RADIO) {
387 if (cur_input != PVR2_CVAL_INPUT_RADIO)
388 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
389 } else {
390 if (cur_input == PVR2_CVAL_INPUT_RADIO)
391 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
392 }
393 fv = vf->frequency;
394 if (vt.capability & V4L2_TUNER_CAP_LOW)
395 fv = (fv * 125) / 2;
396 else
397 fv = fv * 62500;
398 return pvr2_ctrl_set_value(
399 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
400}
401
402static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
403{
404 struct pvr2_v4l2_fh *fh = file->private_data;
405 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
406 int val = 0;
407 int cur_input;
408 struct v4l2_tuner vt;
409 int ret;
410
411 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
412 if (ret != 0)
413 return ret;
414 ret = pvr2_ctrl_get_value(
415 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
416 &val);
417 if (ret != 0)
418 return ret;
419 pvr2_ctrl_get_value(
420 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
421 &cur_input);
422 if (cur_input == PVR2_CVAL_INPUT_RADIO)
423 vf->type = V4L2_TUNER_RADIO;
424 else
425 vf->type = V4L2_TUNER_ANALOG_TV;
426 if (vt.capability & V4L2_TUNER_CAP_LOW)
427 val = (val * 2) / 125;
428 else
429 val /= 62500;
430 vf->frequency = val;
431 return 0;
432}
433
434static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
435{
436 /* Only one format is supported : mpeg.*/
437 if (fd->index != 0)
438 return -EINVAL;
439
440 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
441 return 0;
442}
443
444static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
445{
446 struct pvr2_v4l2_fh *fh = file->private_data;
447 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
448 int val;
449
450 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
451 val = 0;
452 pvr2_ctrl_get_value(
453 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
454 &val);
455 vf->fmt.pix.width = val;
456 val = 0;
457 pvr2_ctrl_get_value(
458 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
459 &val);
460 vf->fmt.pix.height = val;
461 return 0;
462}
463
464static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
465{
466 struct pvr2_v4l2_fh *fh = file->private_data;
467 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
468 int lmin, lmax, ldef;
469 struct pvr2_ctrl *hcp, *vcp;
470 int h = vf->fmt.pix.height;
471 int w = vf->fmt.pix.width;
472
473 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
474 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
475
476 lmin = pvr2_ctrl_get_min(hcp);
477 lmax = pvr2_ctrl_get_max(hcp);
478 pvr2_ctrl_get_def(hcp, &ldef);
479 if (w == -1)
480 w = ldef;
481 else if (w < lmin)
482 w = lmin;
483 else if (w > lmax)
484 w = lmax;
485 lmin = pvr2_ctrl_get_min(vcp);
486 lmax = pvr2_ctrl_get_max(vcp);
487 pvr2_ctrl_get_def(vcp, &ldef);
488 if (h == -1)
489 h = ldef;
490 else if (h < lmin)
491 h = lmin;
492 else if (h > lmax)
493 h = lmax;
494
495 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
496 sizeof(struct v4l2_format));
497 vf->fmt.pix.width = w;
498 vf->fmt.pix.height = h;
499 return 0;
500}
501
502static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
503{
504 struct pvr2_v4l2_fh *fh = file->private_data;
505 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
506 struct pvr2_ctrl *hcp, *vcp;
507 int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
508
509 if (ret)
510 return ret;
511 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
512 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
513 pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
514 pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
515 return 0;
516}
517
518static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
519{
520 struct pvr2_v4l2_fh *fh = file->private_data;
521 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
522 struct pvr2_v4l2_dev *pdi = fh->pdi;
523 int ret;
524
525 if (!fh->pdi->stream) {
526 /* No stream defined for this node. This means
527 that we're not currently allowed to stream from
528 this node. */
529 return -EPERM;
530 }
531 ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
532 if (ret < 0)
533 return ret;
534 return pvr2_hdw_set_streaming(hdw, !0);
535}
536
537static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
538{
539 struct pvr2_v4l2_fh *fh = file->private_data;
540 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
541
542 if (!fh->pdi->stream) {
543 /* No stream defined for this node. This means
544 that we're not currently allowed to stream from
545 this node. */
546 return -EPERM;
547 }
548 return pvr2_hdw_set_streaming(hdw, 0);
549}
550
551static int pvr2_queryctrl(struct file *file, void *priv,
552 struct v4l2_queryctrl *vc)
553{
554 struct pvr2_v4l2_fh *fh = file->private_data;
555 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
556 struct pvr2_ctrl *cptr;
557 int val;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300558
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300559 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
560 cptr = pvr2_hdw_get_ctrl_nextv4l(
561 hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
562 if (cptr)
563 vc->id = pvr2_ctrl_get_v4lid(cptr);
564 } else {
565 cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
566 }
567 if (!cptr) {
568 pvr2_trace(PVR2_TRACE_V4LIOCTL,
569 "QUERYCTRL id=0x%x not implemented here",
570 vc->id);
571 return -EINVAL;
572 }
573
574 pvr2_trace(PVR2_TRACE_V4LIOCTL,
575 "QUERYCTRL id=0x%x mapping name=%s (%s)",
576 vc->id, pvr2_ctrl_get_name(cptr),
577 pvr2_ctrl_get_desc(cptr));
578 strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
579 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
580 pvr2_ctrl_get_def(cptr, &val);
581 vc->default_value = val;
582 switch (pvr2_ctrl_get_type(cptr)) {
583 case pvr2_ctl_enum:
584 vc->type = V4L2_CTRL_TYPE_MENU;
585 vc->minimum = 0;
586 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
587 vc->step = 1;
588 break;
589 case pvr2_ctl_bool:
590 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
591 vc->minimum = 0;
592 vc->maximum = 1;
593 vc->step = 1;
594 break;
595 case pvr2_ctl_int:
596 vc->type = V4L2_CTRL_TYPE_INTEGER;
597 vc->minimum = pvr2_ctrl_get_min(cptr);
598 vc->maximum = pvr2_ctrl_get_max(cptr);
599 vc->step = 1;
600 break;
601 default:
602 pvr2_trace(PVR2_TRACE_V4LIOCTL,
603 "QUERYCTRL id=0x%x name=%s not mappable",
604 vc->id, pvr2_ctrl_get_name(cptr));
605 return -EINVAL;
606 }
607 return 0;
608}
609
610static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
611{
612 struct pvr2_v4l2_fh *fh = file->private_data;
613 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
614 unsigned int cnt = 0;
615 int ret;
616
617 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
618 vm->index,
619 vm->name, sizeof(vm->name) - 1,
620 &cnt);
621 vm->name[cnt] = 0;
622 return ret;
623}
624
625static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
626{
627 struct pvr2_v4l2_fh *fh = file->private_data;
628 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
629 int val = 0;
630 int ret;
631
632 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
633 &val);
634 vc->value = val;
635 return ret;
636}
637
638static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
639{
640 struct pvr2_v4l2_fh *fh = file->private_data;
641 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
642
643 return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
644 vc->value);
645}
646
647static int pvr2_g_ext_ctrls(struct file *file, void *priv,
648 struct v4l2_ext_controls *ctls)
649{
650 struct pvr2_v4l2_fh *fh = file->private_data;
651 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
652 struct v4l2_ext_control *ctrl;
653 unsigned int idx;
654 int val;
655 int ret;
656
657 ret = 0;
658 for (idx = 0; idx < ctls->count; idx++) {
659 ctrl = ctls->controls + idx;
660 ret = pvr2_ctrl_get_value(
661 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
662 if (ret) {
663 ctls->error_idx = idx;
664 return ret;
665 }
666 /* Ensure that if read as a 64 bit value, the user
667 will still get a hopefully sane value */
668 ctrl->value64 = 0;
669 ctrl->value = val;
670 }
671 return 0;
672}
673
674static int pvr2_s_ext_ctrls(struct file *file, void *priv,
675 struct v4l2_ext_controls *ctls)
676{
677 struct pvr2_v4l2_fh *fh = file->private_data;
678 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
679 struct v4l2_ext_control *ctrl;
680 unsigned int idx;
681 int ret;
682
683 ret = 0;
684 for (idx = 0; idx < ctls->count; idx++) {
685 ctrl = ctls->controls + idx;
686 ret = pvr2_ctrl_set_value(
687 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
688 ctrl->value);
689 if (ret) {
690 ctls->error_idx = idx;
691 return ret;
692 }
693 }
694 return 0;
695}
696
697static int pvr2_try_ext_ctrls(struct file *file, void *priv,
698 struct v4l2_ext_controls *ctls)
699{
700 struct pvr2_v4l2_fh *fh = file->private_data;
701 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
702 struct v4l2_ext_control *ctrl;
703 struct pvr2_ctrl *pctl;
704 unsigned int idx;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300705
706 /* For the moment just validate that the requested control
707 actually exists. */
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300708 for (idx = 0; idx < ctls->count; idx++) {
709 ctrl = ctls->controls + idx;
710 pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
711 if (!pctl) {
712 ctls->error_idx = idx;
713 return -EINVAL;
714 }
715 }
716 return 0;
717}
718
719static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
720{
721 struct pvr2_v4l2_fh *fh = file->private_data;
722 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
723 int ret;
724
725 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
726 return -EINVAL;
727 ret = pvr2_hdw_get_cropcap(hdw, cap);
728 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
729 return ret;
730}
731
732static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
733{
734 struct pvr2_v4l2_fh *fh = file->private_data;
735 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
736 int val = 0;
737 int ret;
738
739 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
740 return -EINVAL;
741 ret = pvr2_ctrl_get_value(
742 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
743 if (ret != 0)
744 return -EINVAL;
745 crop->c.left = val;
746 ret = pvr2_ctrl_get_value(
747 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
748 if (ret != 0)
749 return -EINVAL;
750 crop->c.top = val;
751 ret = pvr2_ctrl_get_value(
752 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
753 if (ret != 0)
754 return -EINVAL;
755 crop->c.width = val;
756 ret = pvr2_ctrl_get_value(
757 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
758 if (ret != 0)
759 return -EINVAL;
760 crop->c.height = val;
761 return 0;
762}
763
Hans Verkuil4f996592012-09-05 05:10:48 -0300764static int pvr2_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300765{
766 struct pvr2_v4l2_fh *fh = file->private_data;
767 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300768 int ret;
769
770 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
771 return -EINVAL;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300772 ret = pvr2_ctrl_set_value(
773 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
774 crop->c.left);
775 if (ret != 0)
776 return -EINVAL;
777 ret = pvr2_ctrl_set_value(
778 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
779 crop->c.top);
780 if (ret != 0)
781 return -EINVAL;
782 ret = pvr2_ctrl_set_value(
783 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
784 crop->c.width);
785 if (ret != 0)
786 return -EINVAL;
787 ret = pvr2_ctrl_set_value(
788 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
789 crop->c.height);
790 if (ret != 0)
791 return -EINVAL;
792 return 0;
793}
794
795static int pvr2_log_status(struct file *file, void *priv)
796{
797 struct pvr2_v4l2_fh *fh = file->private_data;
798 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
799
800 pvr2_hdw_trigger_module_log(hdw);
801 return 0;
802}
803
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300804static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
805 .vidioc_querycap = pvr2_querycap,
806 .vidioc_g_priority = pvr2_g_priority,
807 .vidioc_s_priority = pvr2_s_priority,
808 .vidioc_s_audio = pvr2_s_audio,
809 .vidioc_g_audio = pvr2_g_audio,
810 .vidioc_enumaudio = pvr2_enumaudio,
811 .vidioc_enum_input = pvr2_enum_input,
812 .vidioc_cropcap = pvr2_cropcap,
813 .vidioc_s_crop = pvr2_s_crop,
814 .vidioc_g_crop = pvr2_g_crop,
815 .vidioc_g_input = pvr2_g_input,
816 .vidioc_s_input = pvr2_s_input,
817 .vidioc_g_frequency = pvr2_g_frequency,
818 .vidioc_s_frequency = pvr2_s_frequency,
819 .vidioc_s_tuner = pvr2_s_tuner,
820 .vidioc_g_tuner = pvr2_g_tuner,
821 .vidioc_g_std = pvr2_g_std,
822 .vidioc_s_std = pvr2_s_std,
Mike Isely0927ee62012-02-20 02:26:06 -0300823 .vidioc_querystd = pvr2_querystd,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300824 .vidioc_log_status = pvr2_log_status,
825 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
826 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
827 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
828 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
829 .vidioc_streamon = pvr2_streamon,
830 .vidioc_streamoff = pvr2_streamoff,
831 .vidioc_queryctrl = pvr2_queryctrl,
832 .vidioc_querymenu = pvr2_querymenu,
833 .vidioc_g_ctrl = pvr2_g_ctrl,
834 .vidioc_s_ctrl = pvr2_s_ctrl,
835 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
836 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
837 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300838};
839
Mike Iselyd8554972006-06-26 20:58:46 -0300840static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
841{
Mike Isely0f0f2572006-12-27 23:19:42 -0300842 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300843 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300844 char msg[80];
845 unsigned int mcnt;
846
847 /* Construct the unregistration message *before* we actually
848 perform the unregistration step. By doing it this way we don't
849 have to worry about potentially touching deleted resources. */
850 mcnt = scnprintf(msg, sizeof(msg) - 1,
851 "pvrusb2: unregistered device %s [%s]",
852 video_device_node_name(&dip->devbase),
853 pvr2_config_get_name(cfg));
854 msg[mcnt] = 0;
Mike Isely0f0f2572006-12-27 23:19:42 -0300855
Mike Isely16eb40d2006-12-30 18:27:32 -0300856 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300857
858 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300859 dip->v4lp = NULL;
860 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300861
862 /* Actual deallocation happens later when all internal references
863 are gone. */
864 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300865
Mike Iselyd72baad2010-05-15 00:15:38 -0300866 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f2572006-12-27 23:19:42 -0300867
Mike Iselyd8554972006-06-26 20:58:46 -0300868}
869
870
Mike Isely4a89baa2009-10-12 00:13:28 -0300871static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
872{
873 if (!dip) return;
Hans Verkuila28fbd02013-06-10 09:16:25 -0300874 if (!dip->devbase.v4l2_dev->dev) return;
875 dip->devbase.v4l2_dev->dev = NULL;
Mike Isely4a89baa2009-10-12 00:13:28 -0300876 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
877}
878
879
Mike Iselyd8554972006-06-26 20:58:46 -0300880static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
881{
Mike Isely0f0f2572006-12-27 23:19:42 -0300882 if (vp->dev_video) {
883 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000884 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300885 }
886 if (vp->dev_radio) {
887 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000888 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300889 }
Mike Iselyd8554972006-06-26 20:58:46 -0300890
891 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
892 pvr2_channel_done(&vp->channel);
893 kfree(vp);
894}
895
896
Mike Isely75910052006-09-23 22:30:50 -0300897static void pvr2_video_device_release(struct video_device *vdev)
898{
899 struct pvr2_v4l2_dev *dev;
900 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
901 kfree(dev);
902}
903
904
Adrian Bunk07e337e2006-06-30 11:30:20 -0300905static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300906{
907 struct pvr2_v4l2 *vp;
908 vp = container_of(chp,struct pvr2_v4l2,channel);
909 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300910 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
911 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Mike Iselyd8554972006-06-26 20:58:46 -0300912 if (vp->vfirst) return;
913 pvr2_v4l2_destroy_no_lock(vp);
914}
915
916
Hans Verkuil069b7472008-12-30 07:04:34 -0300917static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300918 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300919{
920
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300921 struct pvr2_v4l2_fh *fh = file->private_data;
922 struct pvr2_v4l2 *vp = fh->vhead;
923 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
924 long ret = -EINVAL;
925
926 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
Hans Verkuil4a085162012-06-22 06:38:06 -0300927 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300928
929 if (!pvr2_hdw_dev_ok(hdw)) {
930 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
931 "ioctl failed - bad or no context");
932 return -EFAULT;
933 }
934
935 /* check priority */
936 switch (cmd) {
937 case VIDIOC_S_CTRL:
938 case VIDIOC_S_STD:
939 case VIDIOC_S_INPUT:
940 case VIDIOC_S_TUNER:
941 case VIDIOC_S_FREQUENCY:
942 ret = v4l2_prio_check(&vp->prio, fh->prio);
943 if (ret)
944 return ret;
945 }
946
947 ret = video_ioctl2(file, cmd, arg);
948
949 pvr2_hdw_commit_ctl(hdw);
950
951 if (ret < 0) {
952 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
953 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Andrey Utkin599bc362014-07-10 09:32:25 -0300954 "pvr2_v4l2_do_ioctl failure, ret=%ld"
955 " command was:", ret);
956 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
Hans Verkuilc6d26cf2012-02-20 02:21:00 -0300957 }
958 } else {
959 pvr2_trace(PVR2_TRACE_V4LIOCTL,
960 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
961 ret, ret);
962 }
963 return ret;
964
Mike Iselyd8554972006-06-26 20:58:46 -0300965}
966
967
Hans Verkuilbec43662008-12-30 06:58:20 -0300968static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300969{
970 struct pvr2_v4l2_fh *fhp = file->private_data;
971 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300972 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300973
974 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
975
976 if (fhp->rhp) {
977 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300978 pvr2_hdw_set_streaming(hdw,0);
979 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300980 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300981 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300982 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300983 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300984
Hans Verkuilffb48772010-05-01 08:03:24 -0300985 v4l2_prio_close(&vp->prio, fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300986 file->private_data = NULL;
987
Mike Isely794b1602008-04-22 14:45:45 -0300988 if (fhp->vnext) {
989 fhp->vnext->vprev = fhp->vprev;
990 } else {
991 vp->vlast = fhp->vprev;
992 }
993 if (fhp->vprev) {
994 fhp->vprev->vnext = fhp->vnext;
995 } else {
996 vp->vfirst = fhp->vnext;
997 }
998 fhp->vnext = NULL;
999 fhp->vprev = NULL;
1000 fhp->vhead = NULL;
1001 pvr2_channel_done(&fhp->channel);
1002 pvr2_trace(PVR2_TRACE_STRUCT,
1003 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -03001004 if (fhp->input_map) {
1005 kfree(fhp->input_map);
1006 fhp->input_map = NULL;
1007 }
Mike Isely794b1602008-04-22 14:45:45 -03001008 kfree(fhp);
1009 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
1010 pvr2_v4l2_destroy_no_lock(vp);
1011 }
Mike Iselyd8554972006-06-26 20:58:46 -03001012 return 0;
1013}
1014
1015
Hans Verkuilbec43662008-12-30 06:58:20 -03001016static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001017{
Mike Isely75910052006-09-23 22:30:50 -03001018 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001019 struct pvr2_v4l2_fh *fhp;
1020 struct pvr2_v4l2 *vp;
1021 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001022 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001023 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001024 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001025
Mike Isely75910052006-09-23 22:30:50 -03001026 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001027
1028 vp = dip->v4lp;
1029 hdw = vp->channel.hdw;
1030
1031 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1032
1033 if (!pvr2_hdw_dev_ok(hdw)) {
1034 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1035 "pvr2_v4l2_open: hardware not ready");
1036 return -EIO;
1037 }
1038
Mike Isely4b85dee2007-01-20 00:03:32 -03001039 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001040 if (!fhp) {
1041 return -ENOMEM;
1042 }
Mike Iselyd8554972006-06-26 20:58:46 -03001043
1044 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001045 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001046
Mike Isely794b1602008-04-22 14:45:45 -03001047 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1048 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001049
Mike Isely1cb03b72008-04-21 03:47:43 -03001050 if (dip->v4l_type == VFL_TYPE_RADIO) {
1051 /* Opening device as a radio, legal input selection subset
1052 is just the radio. */
1053 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1054 } else {
1055 /* Opening the main V4L device, legal input selection
1056 subset includes all analog inputs. */
1057 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1058 (1 << PVR2_CVAL_INPUT_TV) |
1059 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1060 (1 << PVR2_CVAL_INPUT_SVIDEO));
1061 }
1062 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1063 if (ret) {
1064 pvr2_channel_done(&fhp->channel);
1065 pvr2_trace(PVR2_TRACE_STRUCT,
1066 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1067 fhp);
1068
1069 kfree(fhp);
1070 return ret;
1071 }
1072
Mike Iselye57b1c82008-04-21 03:52:34 -03001073 input_mask &= pvr2_hdw_get_input_available(hdw);
1074 input_cnt = 0;
1075 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1076 if (input_mask & (1 << idx)) input_cnt++;
1077 }
1078 fhp->input_cnt = input_cnt;
1079 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1080 if (!fhp->input_map) {
1081 pvr2_channel_done(&fhp->channel);
1082 pvr2_trace(PVR2_TRACE_STRUCT,
1083 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1084 fhp);
1085 kfree(fhp);
1086 return -ENOMEM;
1087 }
1088 input_cnt = 0;
1089 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1090 if (!(input_mask & (1 << idx))) continue;
1091 fhp->input_map[input_cnt++] = idx;
1092 }
1093
Mike Isely794b1602008-04-22 14:45:45 -03001094 fhp->vnext = NULL;
1095 fhp->vprev = vp->vlast;
1096 if (vp->vlast) {
1097 vp->vlast->vnext = fhp;
1098 } else {
1099 vp->vfirst = fhp;
1100 }
1101 vp->vlast = fhp;
1102 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001103
Mike Iselyd8554972006-06-26 20:58:46 -03001104 fhp->file = file;
1105 file->private_data = fhp;
Hans Verkuilffb48772010-05-01 08:03:24 -03001106 v4l2_prio_open(&vp->prio, &fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001107
1108 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1109
1110 return 0;
1111}
1112
1113
1114static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1115{
1116 wake_up(&fhp->wait_data);
1117}
1118
1119static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1120{
1121 int ret;
1122 struct pvr2_stream *sp;
1123 struct pvr2_hdw *hdw;
1124 if (fh->rhp) return 0;
1125
Joe Perches108bdd72010-04-05 16:05:39 -03001126 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001127 /* No stream defined for this node. This means that we're
1128 not currently allowed to stream from this node. */
1129 return -EPERM;
1130 }
1131
Mike Iselyd8554972006-06-26 20:58:46 -03001132 /* First read() attempt. Try to claim the stream and start
1133 it... */
1134 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001135 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001136 /* Someone else must already have it */
1137 return ret;
1138 }
1139
Joe Perches108bdd72010-04-05 16:05:39 -03001140 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001141 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001142 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001143 return -ENOMEM;
1144 }
1145
1146 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001147 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001148 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001149 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001150 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1151 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001152}
1153
1154
1155static ssize_t pvr2_v4l2_read(struct file *file,
1156 char __user *buff, size_t count, loff_t *ppos)
1157{
1158 struct pvr2_v4l2_fh *fh = file->private_data;
1159 int ret;
1160
1161 if (fh->fw_mode_flag) {
1162 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1163 char *tbuf;
1164 int c1,c2;
1165 int tcnt = 0;
1166 unsigned int offs = *ppos;
1167
1168 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1169 if (!tbuf) return -ENOMEM;
1170
1171 while (count) {
1172 c1 = count;
1173 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1174 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1175 if (c2 < 0) {
1176 tcnt = c2;
1177 break;
1178 }
1179 if (!c2) break;
1180 if (copy_to_user(buff,tbuf,c2)) {
1181 tcnt = -EFAULT;
1182 break;
1183 }
1184 offs += c2;
1185 tcnt += c2;
1186 buff += c2;
1187 count -= c2;
1188 *ppos += c2;
1189 }
1190 kfree(tbuf);
1191 return tcnt;
1192 }
1193
1194 if (!fh->rhp) {
1195 ret = pvr2_v4l2_iosetup(fh);
1196 if (ret) {
1197 return ret;
1198 }
1199 }
1200
1201 for (;;) {
1202 ret = pvr2_ioread_read(fh->rhp,buff,count);
1203 if (ret >= 0) break;
1204 if (ret != -EAGAIN) break;
1205 if (file->f_flags & O_NONBLOCK) break;
1206 /* Doing blocking I/O. Wait here. */
1207 ret = wait_event_interruptible(
1208 fh->wait_data,
1209 pvr2_ioread_avail(fh->rhp) >= 0);
1210 if (ret < 0) break;
1211 }
1212
1213 return ret;
1214}
1215
1216
1217static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1218{
1219 unsigned int mask = 0;
1220 struct pvr2_v4l2_fh *fh = file->private_data;
1221 int ret;
1222
1223 if (fh->fw_mode_flag) {
1224 mask |= POLLIN | POLLRDNORM;
1225 return mask;
1226 }
1227
1228 if (!fh->rhp) {
1229 ret = pvr2_v4l2_iosetup(fh);
1230 if (ret) return POLLERR;
1231 }
1232
1233 poll_wait(file,&fh->wait_data,wait);
1234
1235 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1236 mask |= POLLIN | POLLRDNORM;
1237 }
1238
1239 return mask;
1240}
1241
1242
Hans Verkuilbec43662008-12-30 06:58:20 -03001243static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001244 .owner = THIS_MODULE,
1245 .open = pvr2_v4l2_open,
1246 .release = pvr2_v4l2_release,
1247 .read = pvr2_v4l2_read,
1248 .ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001249 .poll = pvr2_v4l2_poll,
1250};
1251
1252
Mike Iselyd8554972006-06-26 20:58:46 -03001253static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001254 .fops = &vdev_fops,
1255};
1256
1257
1258static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1259 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001260 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001261{
1262 int mindevnum;
1263 int unit_number;
Mike Isely598e9782012-02-20 02:35:20 -03001264 struct pvr2_hdw *hdw;
Al Viro89952d12007-03-14 09:17:59 +00001265 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001266 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001267
Mike Isely598e9782012-02-20 02:35:20 -03001268 hdw = vp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -03001269 dip->v4l_type = v4l_type;
1270 switch (v4l_type) {
1271 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001272 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001273 dip->config = pvr2_config_mpeg;
1274 dip->minor_type = pvr2_v4l_type_video;
1275 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001276 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001277 pr_err(KBUILD_MODNAME
1278 ": Failed to set up pvrusb2 v4l video dev"
1279 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001280 return;
1281 }
Mike Iselyd8554972006-06-26 20:58:46 -03001282 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001283 case VFL_TYPE_VBI:
1284 dip->config = pvr2_config_vbi;
1285 dip->minor_type = pvr2_v4l_type_vbi;
1286 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001287 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001288 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001289 dip->stream = &vp->channel.mc_head->video_stream;
1290 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001291 dip->minor_type = pvr2_v4l_type_radio;
1292 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001293 break;
1294 default:
1295 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001296 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1297 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001298 return;
1299 }
1300
Ezequiel Garcia5338c162012-10-23 15:57:09 -03001301 dip->devbase = vdev_template;
Mike Isely75910052006-09-23 22:30:50 -03001302 dip->devbase.release = pvr2_video_device_release;
Hans Verkuilc6d26cf2012-02-20 02:21:00 -03001303 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
Mike Iselyd8329f82012-02-20 02:33:06 -03001304 {
1305 int val;
1306 pvr2_ctrl_get_value(
Mike Isely598e9782012-02-20 02:35:20 -03001307 pvr2_hdw_get_ctrl_by_id(hdw,
Mike Iselyd8329f82012-02-20 02:33:06 -03001308 PVR2_CID_STDAVAIL), &val);
1309 dip->devbase.tvnorms = (v4l2_std_id)val;
1310 }
Mike Iselyd8554972006-06-26 20:58:46 -03001311
1312 mindevnum = -1;
Mike Isely598e9782012-02-20 02:35:20 -03001313 unit_number = pvr2_hdw_get_unit_number(hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001314 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1315 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001316 }
Hans Verkuila28fbd02013-06-10 09:16:25 -03001317 pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase);
Mike Isely16eb40d2006-12-30 18:27:32 -03001318 if ((video_register_device(&dip->devbase,
1319 dip->v4l_type, mindevnum) < 0) &&
1320 (video_register_device(&dip->devbase,
1321 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001322 pr_err(KBUILD_MODNAME
1323 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001324 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001325
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001326 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1327 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001328 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001329
Mike Isely598e9782012-02-20 02:35:20 -03001330 pvr2_hdw_v4l_store_minor_number(hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001331 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001332}
1333
1334
1335struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1336{
1337 struct pvr2_v4l2 *vp;
1338
Mike Isely4b85dee2007-01-20 00:03:32 -03001339 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001340 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001341 pvr2_channel_init(&vp->channel,mnp);
1342 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1343
1344 vp->channel.check_func = pvr2_v4l2_internal_check;
1345
1346 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001347 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1348 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001349 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001350 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1351 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001352 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1353 if (!vp->dev_radio) goto fail;
1354 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1355 }
Mike Iselyd8554972006-06-26 20:58:46 -03001356
1357 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001358 fail:
1359 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1360 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001361 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001362}
1363
1364/*
1365 Stuff for Emacs to see, in order to encourage consistent editing style:
1366 *** Local Variables: ***
1367 *** mode: c ***
1368 *** fill-column: 75 ***
1369 *** tab-width: 8 ***
1370 *** c-basic-offset: 8 ***
1371 *** End: ***
1372 */