blob: 087a18245560f467fb059590a91531c4840a4d0d [file] [log] [blame]
Mike Iselyd8554972006-06-26 20:58:46 -03001/*
2 *
3 * $Id$
4 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <linux/kernel.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>
Mike Isely43e06022006-09-23 23:47:50 -030032#include <media/v4l2-dev.h>
Mike Iselyd8554972006-06-26 20:58:46 -030033#include <media/v4l2-common.h>
34
35struct pvr2_v4l2_dev;
36struct pvr2_v4l2_fh;
37struct pvr2_v4l2;
38
Mike Iselyd8554972006-06-26 20:58:46 -030039struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030040 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030041 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030042 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030043 /* Information about this device: */
44 enum pvr2_config config; /* Expected stream format */
45 int v4l_type; /* V4L defined type for this device node */
46 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030047};
48
49struct pvr2_v4l2_fh {
50 struct pvr2_channel channel;
51 struct pvr2_v4l2_dev *dev_info;
52 enum v4l2_priority prio;
53 struct pvr2_ioread *rhp;
54 struct file *file;
55 struct pvr2_v4l2 *vhead;
56 struct pvr2_v4l2_fh *vnext;
57 struct pvr2_v4l2_fh *vprev;
58 wait_queue_head_t wait_data;
59 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030060 /* Map contiguous ordinal value to input id */
61 unsigned char *input_map;
62 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030063};
64
65struct pvr2_v4l2 {
66 struct pvr2_channel channel;
67 struct pvr2_v4l2_fh *vfirst;
68 struct pvr2_v4l2_fh *vlast;
69
70 struct v4l2_prio_state prio;
71
Mike Isely0f0f2572006-12-27 23:19:42 -030072 /* streams - Note that these must be separately, individually,
73 * allocated pointers. This is because the v4l core is going to
74 * manage their deletion - separately, individually... */
75 struct pvr2_v4l2_dev *dev_video;
76 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030077};
78
79static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
80module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030081MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
82static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
83module_param_array(radio_nr, int, NULL, 0444);
84MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
85static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
86module_param_array(vbi_nr, int, NULL, 0444);
87MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030088
Adrian Bunk07e337e2006-06-30 11:30:20 -030089static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030090 .driver = "pvrusb2",
91 .card = "Hauppauge WinTV pvr-usb2",
92 .bus_info = "usb",
93 .version = KERNEL_VERSION(0,8,0),
94 .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -030095 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
Mike Iselyd8554972006-06-26 20:58:46 -030096 V4L2_CAP_READWRITE),
97 .reserved = {0,0,0,0}
98};
99
Adrian Bunk07e337e2006-06-30 11:30:20 -0300100static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300101 {
102 .index = 0,
103 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
104 .flags = V4L2_FMT_FLAG_COMPRESSED,
105 .description = "MPEG1/2",
106 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
107 // breaks when I do that.
108 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
109 .reserved = { 0, 0, 0, 0 }
110 }
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,
147 .reserved = { 0, 0 }
148 }
149 }
150 }
151};
152
Mike Isely16eb40d2006-12-30 18:27:32 -0300153
154static const char *get_v4l_name(int v4l_type)
155{
156 switch (v4l_type) {
157 case VFL_TYPE_GRABBER: return "video";
158 case VFL_TYPE_RADIO: return "radio";
159 case VFL_TYPE_VBI: return "vbi";
160 default: return "?";
161 }
162}
163
164
Mike Iselyd8554972006-06-26 20:58:46 -0300165/*
166 * pvr_ioctl()
167 *
168 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
169 *
170 */
171static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
172 unsigned int cmd, void *arg)
173{
174 struct pvr2_v4l2_fh *fh = file->private_data;
175 struct pvr2_v4l2 *vp = fh->vhead;
176 struct pvr2_v4l2_dev *dev_info = fh->dev_info;
177 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
178 int ret = -EINVAL;
179
180 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
181 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
182 }
183
184 if (!pvr2_hdw_dev_ok(hdw)) {
185 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
186 "ioctl failed - bad or no context");
187 return -EFAULT;
188 }
189
190 /* check priority */
191 switch (cmd) {
192 case VIDIOC_S_CTRL:
193 case VIDIOC_S_STD:
194 case VIDIOC_S_INPUT:
195 case VIDIOC_S_TUNER:
196 case VIDIOC_S_FREQUENCY:
197 ret = v4l2_prio_check(&vp->prio, &fh->prio);
198 if (ret)
199 return ret;
200 }
201
202 switch (cmd) {
203 case VIDIOC_QUERYCAP:
204 {
205 struct v4l2_capability *cap = arg;
206
207 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
Mike Isely31a18542007-04-08 01:11:47 -0300208 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
209 sizeof(cap->bus_info));
Mike Isely78a47102007-11-26 01:58:20 -0300210 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
Mike Iselyd8554972006-06-26 20:58:46 -0300211
212 ret = 0;
213 break;
214 }
215
216 case VIDIOC_G_PRIORITY:
217 {
218 enum v4l2_priority *p = arg;
219
220 *p = v4l2_prio_max(&vp->prio);
221 ret = 0;
222 break;
223 }
224
225 case VIDIOC_S_PRIORITY:
226 {
227 enum v4l2_priority *prio = arg;
228
229 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
230 break;
231 }
232
233 case VIDIOC_ENUMSTD:
234 {
235 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
236 int idx = vs->index;
237 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
238 break;
239 }
240
241 case VIDIOC_G_STD:
242 {
243 int val = 0;
244 ret = pvr2_ctrl_get_value(
245 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
246 *(v4l2_std_id *)arg = val;
247 break;
248 }
249
250 case VIDIOC_S_STD:
251 {
252 ret = pvr2_ctrl_set_value(
253 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
254 *(v4l2_std_id *)arg);
255 break;
256 }
257
258 case VIDIOC_ENUMINPUT:
259 {
260 struct pvr2_ctrl *cptr;
261 struct v4l2_input *vi = (struct v4l2_input *)arg;
262 struct v4l2_input tmp;
263 unsigned int cnt;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300264 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300265
266 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
267
268 memset(&tmp,0,sizeof(tmp));
269 tmp.index = vi->index;
270 ret = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -0300271 if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300272 ret = -EINVAL;
273 break;
274 }
Mike Iselye57b1c82008-04-21 03:52:34 -0300275 val = fh->input_map[vi->index];
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300276 switch (val) {
Mike Iselyd8554972006-06-26 20:58:46 -0300277 case PVR2_CVAL_INPUT_TV:
Mike Isely895c3e82008-04-22 14:45:37 -0300278 case PVR2_CVAL_INPUT_DTV:
Mike Iselyd8554972006-06-26 20:58:46 -0300279 case PVR2_CVAL_INPUT_RADIO:
280 tmp.type = V4L2_INPUT_TYPE_TUNER;
281 break;
282 case PVR2_CVAL_INPUT_SVIDEO:
283 case PVR2_CVAL_INPUT_COMPOSITE:
284 tmp.type = V4L2_INPUT_TYPE_CAMERA;
285 break;
286 default:
287 ret = -EINVAL;
288 break;
289 }
290 if (ret < 0) break;
291
292 cnt = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300293 pvr2_ctrl_get_valname(cptr,val,
Mike Iselyd8554972006-06-26 20:58:46 -0300294 tmp.name,sizeof(tmp.name)-1,&cnt);
295 tmp.name[cnt] = 0;
296
297 /* Don't bother with audioset, since this driver currently
298 always switches the audio whenever the video is
299 switched. */
300
301 /* Handling std is a tougher problem. It doesn't make
302 sense in cases where a device might be multi-standard.
303 We could just copy out the current value for the
304 standard, but it can change over time. For now just
305 leave it zero. */
306
307 memcpy(vi, &tmp, sizeof(tmp));
308
309 ret = 0;
310 break;
311 }
312
313 case VIDIOC_G_INPUT:
314 {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300315 unsigned int idx;
Mike Iselyd8554972006-06-26 20:58:46 -0300316 struct pvr2_ctrl *cptr;
317 struct v4l2_input *vi = (struct v4l2_input *)arg;
318 int val;
319 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
320 val = 0;
321 ret = pvr2_ctrl_get_value(cptr,&val);
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300322 vi->index = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -0300323 for (idx = 0; idx < fh->input_cnt; idx++) {
324 if (fh->input_map[idx] == val) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300325 vi->index = idx;
326 break;
327 }
328 }
Mike Iselyd8554972006-06-26 20:58:46 -0300329 break;
330 }
331
332 case VIDIOC_S_INPUT:
333 {
334 struct v4l2_input *vi = (struct v4l2_input *)arg;
Mike Iselye57b1c82008-04-21 03:52:34 -0300335 if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300336 ret = -ERANGE;
337 break;
338 }
Mike Iselyd8554972006-06-26 20:58:46 -0300339 ret = pvr2_ctrl_set_value(
340 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
Mike Iselye57b1c82008-04-21 03:52:34 -0300341 fh->input_map[vi->index]);
Mike Iselyd8554972006-06-26 20:58:46 -0300342 break;
343 }
344
345 case VIDIOC_ENUMAUDIO:
346 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300347 /* pkt: FIXME: We are returning one "fake" input here
348 which could very well be called "whatever_we_like".
349 This is for apps that want to see an audio input
350 just to feel comfortable, as well as to test if
351 it can do stereo or sth. There is actually no guarantee
352 that the actual audio input cannot change behind the app's
353 back, but most applications should not mind that either.
354
355 Hopefully, mplayer people will work with us on this (this
356 whole mess is to support mplayer pvr://), or Hans will come
357 up with a more standard way to say "we have inputs but we
358 don 't want you to change them independent of video" which
359 will sort this mess.
360 */
361 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300362 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300363 if (vin->index > 0) break;
364 strncpy(vin->name, "PVRUSB2 Audio",14);
365 vin->capability = V4L2_AUDCAP_STEREO;
366 ret = 0;
367 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300368 break;
369 }
370
371 case VIDIOC_G_AUDIO:
372 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300373 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
374 struct v4l2_audio *vin = arg;
375 memset(vin,0,sizeof(*vin));
376 vin->index = 0;
377 strncpy(vin->name, "PVRUSB2 Audio",14);
378 vin->capability = V4L2_AUDCAP_STEREO;
379 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300380 break;
381 }
382
383 case VIDIOC_S_AUDIO:
384 {
385 ret = -EINVAL;
386 break;
387 }
388 case VIDIOC_G_TUNER:
389 {
390 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300391
Michael Krufky8d364362007-01-22 02:17:55 -0300392 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300393
Mike Isely18103c572007-01-20 00:09:47 -0300394 pvr2_hdw_execute_tuner_poll(hdw);
395 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300396 break;
397 }
398
399 case VIDIOC_S_TUNER:
400 {
401 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
402
403 if (vt->index != 0)
404 break;
405
406 ret = pvr2_ctrl_set_value(
407 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
408 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300409 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300410 }
411
412 case VIDIOC_S_FREQUENCY:
413 {
414 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300415 unsigned long fv;
Mike Isely18103c572007-01-20 00:09:47 -0300416 struct v4l2_tuner vt;
417 int cur_input;
418 struct pvr2_ctrl *ctrlp;
419 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
420 if (ret != 0) break;
421 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
422 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
423 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300424 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c572007-01-20 00:09:47 -0300425 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
426 pvr2_ctrl_set_value(ctrlp,
427 PVR2_CVAL_INPUT_RADIO);
428 }
429 } else {
430 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
431 pvr2_ctrl_set_value(ctrlp,
432 PVR2_CVAL_INPUT_TV);
433 }
434 }
435 fv = vf->frequency;
436 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300437 fv = (fv * 125) / 2;
438 } else {
439 fv = fv * 62500;
440 }
Mike Iselyd8554972006-06-26 20:58:46 -0300441 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300442 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300443 break;
444 }
445
446 case VIDIOC_G_FREQUENCY:
447 {
448 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
449 int val = 0;
Mike Isely18103c572007-01-20 00:09:47 -0300450 int cur_input;
451 struct v4l2_tuner vt;
452 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
453 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300454 ret = pvr2_ctrl_get_value(
455 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
456 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300457 if (ret != 0) break;
458 pvr2_ctrl_get_value(
459 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
460 &cur_input);
461 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300462 vf->type = V4L2_TUNER_RADIO;
463 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300464 vf->type = V4L2_TUNER_ANALOG_TV;
465 }
Mike Isely18103c572007-01-20 00:09:47 -0300466 if (vt.capability & V4L2_TUNER_CAP_LOW) {
467 val = (val * 2) / 125;
468 } else {
469 val /= 62500;
470 }
471 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300472 break;
473 }
474
475 case VIDIOC_ENUM_FMT:
476 {
477 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
478
479 /* Only one format is supported : mpeg.*/
480 if (fd->index != 0)
481 break;
482
483 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
484 ret = 0;
485 break;
486 }
487
488 case VIDIOC_G_FMT:
489 {
490 struct v4l2_format *vf = (struct v4l2_format *)arg;
491 int val;
492 switch(vf->type) {
493 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
494 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
495 sizeof(struct v4l2_format));
496 val = 0;
497 pvr2_ctrl_get_value(
498 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
499 &val);
500 vf->fmt.pix.width = val;
501 val = 0;
502 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300503 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
504 &val);
505 vf->fmt.pix.height = val;
506 ret = 0;
507 break;
508 case V4L2_BUF_TYPE_VBI_CAPTURE:
509 // ????? Still need to figure out to do VBI correctly
510 ret = -EINVAL;
511 break;
512 default:
513 ret = -EINVAL;
514 break;
515 }
516 break;
517 }
518
519 case VIDIOC_TRY_FMT:
520 case VIDIOC_S_FMT:
521 {
522 struct v4l2_format *vf = (struct v4l2_format *)arg;
523
524 ret = 0;
525 switch(vf->type) {
526 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300527 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300528 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300529 int h = vf->fmt.pix.height;
530 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300531 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
532 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300533
Mike Iselye95a1912006-08-08 09:10:07 -0300534 lmin = pvr2_ctrl_get_min(hcp);
535 lmax = pvr2_ctrl_get_max(hcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300536 ldef = pvr2_ctrl_get_def(hcp);
537 if (w == -1) {
538 w = ldef;
539 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300540 w = lmin;
541 } else if (w > lmax) {
542 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300543 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300544 lmin = pvr2_ctrl_get_min(vcp);
545 lmax = pvr2_ctrl_get_max(vcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300546 ldef = pvr2_ctrl_get_def(vcp);
547 if (h == -1) {
548 h = ldef;
549 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300550 h = lmin;
551 } else if (h > lmax) {
552 h = lmax;
553 }
Mike Iselyd8554972006-06-26 20:58:46 -0300554
555 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
556 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300557 vf->fmt.pix.width = w;
558 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300559
560 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300561 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
562 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300563 }
564 } break;
565 case V4L2_BUF_TYPE_VBI_CAPTURE:
566 // ????? Still need to figure out to do VBI correctly
567 ret = -EINVAL;
568 break;
569 default:
570 ret = -EINVAL;
571 break;
572 }
573 break;
574 }
575
576 case VIDIOC_STREAMON:
577 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300578 if (!fh->dev_info->stream) {
579 /* No stream defined for this node. This means
580 that we're not currently allowed to stream from
581 this node. */
582 ret = -EPERM;
583 break;
584 }
Mike Iselyd8554972006-06-26 20:58:46 -0300585 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
586 if (ret < 0) return ret;
587 ret = pvr2_hdw_set_streaming(hdw,!0);
588 break;
589 }
590
591 case VIDIOC_STREAMOFF:
592 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300593 if (!fh->dev_info->stream) {
594 /* No stream defined for this node. This means
595 that we're not currently allowed to stream from
596 this node. */
597 ret = -EPERM;
598 break;
599 }
Mike Iselyd8554972006-06-26 20:58:46 -0300600 ret = pvr2_hdw_set_streaming(hdw,0);
601 break;
602 }
603
604 case VIDIOC_QUERYCTRL:
605 {
606 struct pvr2_ctrl *cptr;
607 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
608 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300609 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
610 cptr = pvr2_hdw_get_ctrl_nextv4l(
611 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
612 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
613 } else {
614 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
615 }
Mike Iselyd8554972006-06-26 20:58:46 -0300616 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300617 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300618 "QUERYCTRL id=0x%x not implemented here",
619 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300620 ret = -EINVAL;
621 break;
622 }
623
Mike Iselya761f432006-06-25 20:04:44 -0300624 pvr2_trace(PVR2_TRACE_V4LIOCTL,
625 "QUERYCTRL id=0x%x mapping name=%s (%s)",
626 vc->id,pvr2_ctrl_get_name(cptr),
627 pvr2_ctrl_get_desc(cptr));
628 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
629 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300630 vc->default_value = pvr2_ctrl_get_def(cptr);
631 switch (pvr2_ctrl_get_type(cptr)) {
632 case pvr2_ctl_enum:
633 vc->type = V4L2_CTRL_TYPE_MENU;
634 vc->minimum = 0;
635 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
636 vc->step = 1;
637 break;
Mike Isely33213962006-06-25 20:04:40 -0300638 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300639 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300640 vc->minimum = 0;
641 vc->maximum = 1;
642 vc->step = 1;
643 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300644 case pvr2_ctl_int:
645 vc->type = V4L2_CTRL_TYPE_INTEGER;
646 vc->minimum = pvr2_ctrl_get_min(cptr);
647 vc->maximum = pvr2_ctrl_get_max(cptr);
648 vc->step = 1;
649 break;
650 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300651 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300652 "QUERYCTRL id=0x%x name=%s not mappable",
653 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300654 ret = -EINVAL;
655 break;
656 }
657 break;
658 }
659
660 case VIDIOC_QUERYMENU:
661 {
662 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
663 unsigned int cnt = 0;
664 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
665 vm->index,
666 vm->name,sizeof(vm->name)-1,
667 &cnt);
668 vm->name[cnt] = 0;
669 break;
670 }
671
672 case VIDIOC_G_CTRL:
673 {
674 struct v4l2_control *vc = (struct v4l2_control *)arg;
675 int val = 0;
676 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
677 &val);
678 vc->value = val;
679 break;
680 }
681
682 case VIDIOC_S_CTRL:
683 {
684 struct v4l2_control *vc = (struct v4l2_control *)arg;
685 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
686 vc->value);
687 break;
688 }
689
Mike Isely1d9f8462006-06-25 20:04:58 -0300690 case VIDIOC_G_EXT_CTRLS:
691 {
692 struct v4l2_ext_controls *ctls =
693 (struct v4l2_ext_controls *)arg;
694 struct v4l2_ext_control *ctrl;
695 unsigned int idx;
696 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300697 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300698 for (idx = 0; idx < ctls->count; idx++) {
699 ctrl = ctls->controls + idx;
700 ret = pvr2_ctrl_get_value(
701 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
702 if (ret) {
703 ctls->error_idx = idx;
704 break;
705 }
706 /* Ensure that if read as a 64 bit value, the user
707 will still get a hopefully sane value */
708 ctrl->value64 = 0;
709 ctrl->value = val;
710 }
711 break;
712 }
713
714 case VIDIOC_S_EXT_CTRLS:
715 {
716 struct v4l2_ext_controls *ctls =
717 (struct v4l2_ext_controls *)arg;
718 struct v4l2_ext_control *ctrl;
719 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300720 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300721 for (idx = 0; idx < ctls->count; idx++) {
722 ctrl = ctls->controls + idx;
723 ret = pvr2_ctrl_set_value(
724 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
725 ctrl->value);
726 if (ret) {
727 ctls->error_idx = idx;
728 break;
729 }
730 }
731 break;
732 }
733
734 case VIDIOC_TRY_EXT_CTRLS:
735 {
736 struct v4l2_ext_controls *ctls =
737 (struct v4l2_ext_controls *)arg;
738 struct v4l2_ext_control *ctrl;
739 struct pvr2_ctrl *pctl;
740 unsigned int idx;
741 /* For the moment just validate that the requested control
742 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300743 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300744 for (idx = 0; idx < ctls->count; idx++) {
745 ctrl = ctls->controls + idx;
746 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
747 if (!pctl) {
748 ret = -EINVAL;
749 ctls->error_idx = idx;
750 break;
751 }
752 }
753 break;
754 }
755
Mike Iselyd8554972006-06-26 20:58:46 -0300756 case VIDIOC_LOG_STATUS:
757 {
Mike Iselyd8554972006-06-26 20:58:46 -0300758 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300759 ret = 0;
760 break;
761 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300762#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300763 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300764 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300765 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300766 u64 val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300767 struct v4l2_register *req = (struct v4l2_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300768 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300769 ret = pvr2_hdw_register_access(
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300770 hdw,req->match_type,req->match_chip,req->reg,
Trent Piepho52ebc762007-01-23 22:38:13 -0300771 cmd == VIDIOC_DBG_S_REGISTER,&val);
772 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300773 break;
774 }
775#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300776
777 default :
778 ret = v4l_compat_translate_ioctl(inode,file,cmd,
779 arg,pvr2_v4l2_do_ioctl);
780 }
781
782 pvr2_hdw_commit_ctl(hdw);
783
784 if (ret < 0) {
785 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300786 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300787 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
788 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300789 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
790 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300791 "pvr2_v4l2_do_ioctl failure, ret=%d"
792 " command was:",ret);
793 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
794 cmd);
795 }
796 }
797 } else {
798 pvr2_trace(PVR2_TRACE_V4LIOCTL,
799 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
800 ret,ret);
801 }
802 return ret;
803}
804
805
806static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
807{
Mike Isely0f0f2572006-12-27 23:19:42 -0300808 int minor_id = dip->devbase.minor;
Mike Isely0f0f2572006-12-27 23:19:42 -0300809 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300810 enum pvr2_config cfg = dip->config;
811 int v4l_type = dip->v4l_type;
Mike Isely0f0f2572006-12-27 23:19:42 -0300812
Mike Isely16eb40d2006-12-30 18:27:32 -0300813 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300814
815 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300816 dip->v4lp = NULL;
817 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300818
819 /* Actual deallocation happens later when all internal references
820 are gone. */
821 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300822
Mike Isely16eb40d2006-12-30 18:27:32 -0300823 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
824 get_v4l_name(v4l_type),minor_id & 0x1f,
825 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300826
Mike Iselyd8554972006-06-26 20:58:46 -0300827}
828
829
830static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
831{
Mike Isely0f0f2572006-12-27 23:19:42 -0300832 if (vp->dev_video) {
833 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000834 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300835 }
836 if (vp->dev_radio) {
837 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000838 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300839 }
Mike Iselyd8554972006-06-26 20:58:46 -0300840
841 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
842 pvr2_channel_done(&vp->channel);
843 kfree(vp);
844}
845
846
Mike Isely75910052006-09-23 22:30:50 -0300847static void pvr2_video_device_release(struct video_device *vdev)
848{
849 struct pvr2_v4l2_dev *dev;
850 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
851 kfree(dev);
852}
853
854
Adrian Bunk07e337e2006-06-30 11:30:20 -0300855static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300856{
857 struct pvr2_v4l2 *vp;
858 vp = container_of(chp,struct pvr2_v4l2,channel);
859 if (!vp->channel.mc_head->disconnect_flag) return;
860 if (vp->vfirst) return;
861 pvr2_v4l2_destroy_no_lock(vp);
862}
863
864
Adrian Bunk07e337e2006-06-30 11:30:20 -0300865static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
866 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300867{
868
869/* Temporary hack : use ivtv api until a v4l2 one is available. */
870#define IVTV_IOC_G_CODEC 0xFFEE7703
871#define IVTV_IOC_S_CODEC 0xFFEE7704
872 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
873 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
874}
875
876
Adrian Bunk07e337e2006-06-30 11:30:20 -0300877static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300878{
879 struct pvr2_v4l2_fh *fhp = file->private_data;
880 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300881 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300882
883 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
884
885 if (fhp->rhp) {
886 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300887 pvr2_hdw_set_streaming(hdw,0);
888 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300889 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300890 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300891 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300892 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300893
Mike Iselyd8554972006-06-26 20:58:46 -0300894 v4l2_prio_close(&vp->prio, &fhp->prio);
895 file->private_data = NULL;
896
Mike Isely794b1602008-04-22 14:45:45 -0300897 if (fhp->vnext) {
898 fhp->vnext->vprev = fhp->vprev;
899 } else {
900 vp->vlast = fhp->vprev;
901 }
902 if (fhp->vprev) {
903 fhp->vprev->vnext = fhp->vnext;
904 } else {
905 vp->vfirst = fhp->vnext;
906 }
907 fhp->vnext = NULL;
908 fhp->vprev = NULL;
909 fhp->vhead = NULL;
910 pvr2_channel_done(&fhp->channel);
911 pvr2_trace(PVR2_TRACE_STRUCT,
912 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -0300913 if (fhp->input_map) {
914 kfree(fhp->input_map);
915 fhp->input_map = NULL;
916 }
Mike Isely794b1602008-04-22 14:45:45 -0300917 kfree(fhp);
918 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
919 pvr2_v4l2_destroy_no_lock(vp);
920 }
Mike Iselyd8554972006-06-26 20:58:46 -0300921 return 0;
922}
923
924
Adrian Bunk07e337e2006-06-30 11:30:20 -0300925static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300926{
Mike Isely75910052006-09-23 22:30:50 -0300927 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300928 struct pvr2_v4l2_fh *fhp;
929 struct pvr2_v4l2 *vp;
930 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -0300931 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -0300932 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -0300933 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300934
Mike Isely75910052006-09-23 22:30:50 -0300935 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300936
937 vp = dip->v4lp;
938 hdw = vp->channel.hdw;
939
940 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
941
942 if (!pvr2_hdw_dev_ok(hdw)) {
943 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
944 "pvr2_v4l2_open: hardware not ready");
945 return -EIO;
946 }
947
Mike Isely4b85dee2007-01-20 00:03:32 -0300948 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300949 if (!fhp) {
950 return -ENOMEM;
951 }
Mike Iselyd8554972006-06-26 20:58:46 -0300952
953 init_waitqueue_head(&fhp->wait_data);
954 fhp->dev_info = dip;
955
Mike Isely794b1602008-04-22 14:45:45 -0300956 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
957 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300958
Mike Isely1cb03b72008-04-21 03:47:43 -0300959 if (dip->v4l_type == VFL_TYPE_RADIO) {
960 /* Opening device as a radio, legal input selection subset
961 is just the radio. */
962 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
963 } else {
964 /* Opening the main V4L device, legal input selection
965 subset includes all analog inputs. */
966 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
967 (1 << PVR2_CVAL_INPUT_TV) |
968 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
969 (1 << PVR2_CVAL_INPUT_SVIDEO));
970 }
971 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
972 if (ret) {
973 pvr2_channel_done(&fhp->channel);
974 pvr2_trace(PVR2_TRACE_STRUCT,
975 "Destroying pvr_v4l2_fh id=%p (input mask error)",
976 fhp);
977
978 kfree(fhp);
979 return ret;
980 }
981
Mike Iselye57b1c82008-04-21 03:52:34 -0300982 input_mask &= pvr2_hdw_get_input_available(hdw);
983 input_cnt = 0;
984 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
985 if (input_mask & (1 << idx)) input_cnt++;
986 }
987 fhp->input_cnt = input_cnt;
988 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
989 if (!fhp->input_map) {
990 pvr2_channel_done(&fhp->channel);
991 pvr2_trace(PVR2_TRACE_STRUCT,
992 "Destroying pvr_v4l2_fh id=%p (input map failure)",
993 fhp);
994 kfree(fhp);
995 return -ENOMEM;
996 }
997 input_cnt = 0;
998 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
999 if (!(input_mask & (1 << idx))) continue;
1000 fhp->input_map[input_cnt++] = idx;
1001 }
1002
Mike Isely794b1602008-04-22 14:45:45 -03001003 fhp->vnext = NULL;
1004 fhp->vprev = vp->vlast;
1005 if (vp->vlast) {
1006 vp->vlast->vnext = fhp;
1007 } else {
1008 vp->vfirst = fhp;
1009 }
1010 vp->vlast = fhp;
1011 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001012
Mike Iselyd8554972006-06-26 20:58:46 -03001013 fhp->file = file;
1014 file->private_data = fhp;
1015 v4l2_prio_open(&vp->prio,&fhp->prio);
1016
1017 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1018
1019 return 0;
1020}
1021
1022
1023static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1024{
1025 wake_up(&fhp->wait_data);
1026}
1027
1028static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1029{
1030 int ret;
1031 struct pvr2_stream *sp;
1032 struct pvr2_hdw *hdw;
1033 if (fh->rhp) return 0;
1034
Mike Isely16eb40d2006-12-30 18:27:32 -03001035 if (!fh->dev_info->stream) {
1036 /* No stream defined for this node. This means that we're
1037 not currently allowed to stream from this node. */
1038 return -EPERM;
1039 }
1040
Mike Iselyd8554972006-06-26 20:58:46 -03001041 /* First read() attempt. Try to claim the stream and start
1042 it... */
1043 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1044 fh->dev_info->stream)) != 0) {
1045 /* Someone else must already have it */
1046 return ret;
1047 }
1048
1049 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1050 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001051 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001052 return -ENOMEM;
1053 }
1054
1055 hdw = fh->channel.mc_head->hdw;
1056 sp = fh->dev_info->stream->stream;
1057 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1058 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
Mike Isely681c7392007-11-26 01:48:52 -03001059 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1060 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001061}
1062
1063
1064static ssize_t pvr2_v4l2_read(struct file *file,
1065 char __user *buff, size_t count, loff_t *ppos)
1066{
1067 struct pvr2_v4l2_fh *fh = file->private_data;
1068 int ret;
1069
1070 if (fh->fw_mode_flag) {
1071 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1072 char *tbuf;
1073 int c1,c2;
1074 int tcnt = 0;
1075 unsigned int offs = *ppos;
1076
1077 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1078 if (!tbuf) return -ENOMEM;
1079
1080 while (count) {
1081 c1 = count;
1082 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1083 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1084 if (c2 < 0) {
1085 tcnt = c2;
1086 break;
1087 }
1088 if (!c2) break;
1089 if (copy_to_user(buff,tbuf,c2)) {
1090 tcnt = -EFAULT;
1091 break;
1092 }
1093 offs += c2;
1094 tcnt += c2;
1095 buff += c2;
1096 count -= c2;
1097 *ppos += c2;
1098 }
1099 kfree(tbuf);
1100 return tcnt;
1101 }
1102
1103 if (!fh->rhp) {
1104 ret = pvr2_v4l2_iosetup(fh);
1105 if (ret) {
1106 return ret;
1107 }
1108 }
1109
1110 for (;;) {
1111 ret = pvr2_ioread_read(fh->rhp,buff,count);
1112 if (ret >= 0) break;
1113 if (ret != -EAGAIN) break;
1114 if (file->f_flags & O_NONBLOCK) break;
1115 /* Doing blocking I/O. Wait here. */
1116 ret = wait_event_interruptible(
1117 fh->wait_data,
1118 pvr2_ioread_avail(fh->rhp) >= 0);
1119 if (ret < 0) break;
1120 }
1121
1122 return ret;
1123}
1124
1125
1126static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1127{
1128 unsigned int mask = 0;
1129 struct pvr2_v4l2_fh *fh = file->private_data;
1130 int ret;
1131
1132 if (fh->fw_mode_flag) {
1133 mask |= POLLIN | POLLRDNORM;
1134 return mask;
1135 }
1136
1137 if (!fh->rhp) {
1138 ret = pvr2_v4l2_iosetup(fh);
1139 if (ret) return POLLERR;
1140 }
1141
1142 poll_wait(file,&fh->wait_data,wait);
1143
1144 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1145 mask |= POLLIN | POLLRDNORM;
1146 }
1147
1148 return mask;
1149}
1150
1151
Arjan van de Venfa027c22007-02-12 00:55:33 -08001152static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001153 .owner = THIS_MODULE,
1154 .open = pvr2_v4l2_open,
1155 .release = pvr2_v4l2_release,
1156 .read = pvr2_v4l2_read,
1157 .ioctl = pvr2_v4l2_ioctl,
1158 .llseek = no_llseek,
1159 .poll = pvr2_v4l2_poll,
1160};
1161
1162
Mike Iselyd8554972006-06-26 20:58:46 -03001163static struct video_device vdev_template = {
1164 .owner = THIS_MODULE,
1165 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1166 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1167 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1168 | V4L2_CAP_READWRITE),
Mike Iselyd8554972006-06-26 20:58:46 -03001169 .fops = &vdev_fops,
1170};
1171
1172
1173static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1174 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001175 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001176{
1177 int mindevnum;
1178 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001179 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001180 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001181
1182
Mike Isely16eb40d2006-12-30 18:27:32 -03001183 dip->v4l_type = v4l_type;
1184 switch (v4l_type) {
1185 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001186 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001187 dip->config = pvr2_config_mpeg;
1188 dip->minor_type = pvr2_v4l_type_video;
1189 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001190 if (!dip->stream) {
1191 err("Failed to set up pvrusb2 v4l video dev"
1192 " due to missing stream instance");
1193 return;
1194 }
Mike Iselyd8554972006-06-26 20:58:46 -03001195 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001196 case VFL_TYPE_VBI:
1197 dip->config = pvr2_config_vbi;
1198 dip->minor_type = pvr2_v4l_type_vbi;
1199 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001200 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001201 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001202 dip->stream = &vp->channel.mc_head->video_stream;
1203 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001204 dip->minor_type = pvr2_v4l_type_radio;
1205 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001206 break;
1207 default:
1208 /* Bail out (this should be impossible) */
1209 err("Failed to set up pvrusb2 v4l dev"
1210 " due to unrecognized config");
1211 return;
1212 }
1213
Mike Isely75910052006-09-23 22:30:50 -03001214 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1215 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001216
1217 mindevnum = -1;
1218 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001219 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1220 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001221 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001222 if ((video_register_device(&dip->devbase,
1223 dip->v4l_type, mindevnum) < 0) &&
1224 (video_register_device(&dip->devbase,
1225 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001226 err("Failed to register pvrusb2 v4l device");
1227 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001228
1229 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1230 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1231 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001232
Mike Iselyd8554972006-06-26 20:58:46 -03001233 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001234 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001235}
1236
1237
1238struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1239{
1240 struct pvr2_v4l2 *vp;
1241
Mike Isely4b85dee2007-01-20 00:03:32 -03001242 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001243 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001244 pvr2_channel_init(&vp->channel,mnp);
1245 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1246
1247 vp->channel.check_func = pvr2_v4l2_internal_check;
1248
1249 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001250 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1251 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001252 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001253 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1254 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001255 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1256 if (!vp->dev_radio) goto fail;
1257 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1258 }
Mike Iselyd8554972006-06-26 20:58:46 -03001259
1260 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001261 fail:
1262 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1263 pvr2_v4l2_destroy_no_lock(vp);
1264 return 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001265}
1266
1267/*
1268 Stuff for Emacs to see, in order to encourage consistent editing style:
1269 *** Local Variables: ***
1270 *** mode: c ***
1271 *** fill-column: 75 ***
1272 *** tab-width: 8 ***
1273 *** c-basic-offset: 8 ***
1274 *** End: ***
1275 */