aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-v4l2.c')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c1126
1 files changed, 1126 insertions, 0 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
new file mode 100644
index 000000000000..961951010c27
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -0,0 +1,1126 @@
1/*
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>
24#include <linux/version.h>
25#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>
32#include <media/v4l2-common.h>
33
34struct pvr2_v4l2_dev;
35struct pvr2_v4l2_fh;
36struct pvr2_v4l2;
37
38/* V4L no longer provide the ability to set / get a private context pointer
39 (i.e. video_get_drvdata / video_set_drvdata), which means we have to
40 concoct our own context locating mechanism. Supposedly this is intended
41 to simplify driver implementation. It's not clear to me how that can
42 possibly be true. Our solution here is to maintain a lookup table of
43 our context instances, indexed by the minor device number of the V4L
44 device. See pvr2_v4l2_open() for some implications of this approach. */
45static struct pvr2_v4l2_dev *devices[256];
46static DEFINE_MUTEX(device_lock);
47
48struct pvr2_v4l2_dev {
49 struct pvr2_v4l2 *v4lp;
50 struct video_device *vdev;
51 struct pvr2_context_stream *stream;
52 int ctxt_idx;
53 enum pvr2_config config;
54};
55
56struct pvr2_v4l2_fh {
57 struct pvr2_channel channel;
58 struct pvr2_v4l2_dev *dev_info;
59 enum v4l2_priority prio;
60 struct pvr2_ioread *rhp;
61 struct file *file;
62 struct pvr2_v4l2 *vhead;
63 struct pvr2_v4l2_fh *vnext;
64 struct pvr2_v4l2_fh *vprev;
65 wait_queue_head_t wait_data;
66 int fw_mode_flag;
67};
68
69struct pvr2_v4l2 {
70 struct pvr2_channel channel;
71 struct pvr2_v4l2_fh *vfirst;
72 struct pvr2_v4l2_fh *vlast;
73
74 struct v4l2_prio_state prio;
75
76 /* streams */
77 struct pvr2_v4l2_dev video_dev;
78};
79
80static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
81module_param_array(video_nr, int, NULL, 0444);
82MODULE_PARM_DESC(video_nr, "Offset for device's minor");
83
84struct v4l2_capability pvr_capability ={
85 .driver = "pvrusb2",
86 .card = "Hauppauge WinTV pvr-usb2",
87 .bus_info = "usb",
88 .version = KERNEL_VERSION(0,8,0),
89 .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
90 V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
91 V4L2_CAP_READWRITE),
92 .reserved = {0,0,0,0}
93};
94
95static struct v4l2_tuner pvr_v4l2_tuners[]= {
96 {
97 .index = 0,
98 .name = "TV Tuner",
99 .type = V4L2_TUNER_ANALOG_TV,
100 .capability = (V4L2_TUNER_CAP_NORM |
101 V4L2_TUNER_CAP_STEREO |
102 V4L2_TUNER_CAP_LANG1 |
103 V4L2_TUNER_CAP_LANG2),
104 .rangelow = 0,
105 .rangehigh = 0,
106 .rxsubchans = V4L2_TUNER_SUB_STEREO,
107 .audmode = V4L2_TUNER_MODE_STEREO,
108 .signal = 0,
109 .afc = 0,
110 .reserved = {0,0,0,0}
111 }
112};
113
114struct v4l2_fmtdesc pvr_fmtdesc [] = {
115 {
116 .index = 0,
117 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
118 .flags = V4L2_FMT_FLAG_COMPRESSED,
119 .description = "MPEG1/2",
120 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
121 // breaks when I do that.
122 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
123 .reserved = { 0, 0, 0, 0 }
124 }
125};
126
127#define PVR_FORMAT_PIX 0
128#define PVR_FORMAT_VBI 1
129
130struct v4l2_format pvr_format [] = {
131 [PVR_FORMAT_PIX] = {
132 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
133 .fmt = {
134 .pix = {
135 .width = 720,
136 .height = 576,
137 // This should really be V4L2_PIX_FMT_MPEG,
138 // but xawtv breaks when I do that.
139 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
140 .field = V4L2_FIELD_INTERLACED,
141 .bytesperline = 0, // doesn't make sense
142 // here
143 //FIXME : Don't know what to put here...
144 .sizeimage = (32*1024),
145 .colorspace = 0, // doesn't make sense here
146 .priv = 0
147 }
148 }
149 },
150 [PVR_FORMAT_VBI] = {
151 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
152 .fmt = {
153 .vbi = {
154 .sampling_rate = 27000000,
155 .offset = 248,
156 .samples_per_line = 1443,
157 .sample_format = V4L2_PIX_FMT_GREY,
158 .start = { 0, 0 },
159 .count = { 0, 0 },
160 .flags = 0,
161 .reserved = { 0, 0 }
162 }
163 }
164 }
165};
166
167/*
168 * pvr_ioctl()
169 *
170 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
171 *
172 */
173static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
174 unsigned int cmd, void *arg)
175{
176 struct pvr2_v4l2_fh *fh = file->private_data;
177 struct pvr2_v4l2 *vp = fh->vhead;
178 struct pvr2_v4l2_dev *dev_info = fh->dev_info;
179 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
180 int ret = -EINVAL;
181
182 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
183 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
184 }
185
186 if (!pvr2_hdw_dev_ok(hdw)) {
187 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
188 "ioctl failed - bad or no context");
189 return -EFAULT;
190 }
191
192 /* check priority */
193 switch (cmd) {
194 case VIDIOC_S_CTRL:
195 case VIDIOC_S_STD:
196 case VIDIOC_S_INPUT:
197 case VIDIOC_S_TUNER:
198 case VIDIOC_S_FREQUENCY:
199 ret = v4l2_prio_check(&vp->prio, &fh->prio);
200 if (ret)
201 return ret;
202 }
203
204 switch (cmd) {
205 case VIDIOC_QUERYCAP:
206 {
207 struct v4l2_capability *cap = arg;
208
209 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
210
211 ret = 0;
212 break;
213 }
214
215 case VIDIOC_G_PRIORITY:
216 {
217 enum v4l2_priority *p = arg;
218
219 *p = v4l2_prio_max(&vp->prio);
220 ret = 0;
221 break;
222 }
223
224 case VIDIOC_S_PRIORITY:
225 {
226 enum v4l2_priority *prio = arg;
227
228 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
229 break;
230 }
231
232 case VIDIOC_ENUMSTD:
233 {
234 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
235 int idx = vs->index;
236 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
237 break;
238 }
239
240 case VIDIOC_G_STD:
241 {
242 int val = 0;
243 ret = pvr2_ctrl_get_value(
244 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
245 *(v4l2_std_id *)arg = val;
246 break;
247 }
248
249 case VIDIOC_S_STD:
250 {
251 ret = pvr2_ctrl_set_value(
252 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
253 *(v4l2_std_id *)arg);
254 break;
255 }
256
257 case VIDIOC_ENUMINPUT:
258 {
259 struct pvr2_ctrl *cptr;
260 struct v4l2_input *vi = (struct v4l2_input *)arg;
261 struct v4l2_input tmp;
262 unsigned int cnt;
263
264 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
265
266 memset(&tmp,0,sizeof(tmp));
267 tmp.index = vi->index;
268 ret = 0;
269 switch (vi->index) {
270 case PVR2_CVAL_INPUT_TV:
271 case PVR2_CVAL_INPUT_RADIO:
272 tmp.type = V4L2_INPUT_TYPE_TUNER;
273 break;
274 case PVR2_CVAL_INPUT_SVIDEO:
275 case PVR2_CVAL_INPUT_COMPOSITE:
276 tmp.type = V4L2_INPUT_TYPE_CAMERA;
277 break;
278 default:
279 ret = -EINVAL;
280 break;
281 }
282 if (ret < 0) break;
283
284 cnt = 0;
285 pvr2_ctrl_get_valname(cptr,vi->index,
286 tmp.name,sizeof(tmp.name)-1,&cnt);
287 tmp.name[cnt] = 0;
288
289 /* Don't bother with audioset, since this driver currently
290 always switches the audio whenever the video is
291 switched. */
292
293 /* Handling std is a tougher problem. It doesn't make
294 sense in cases where a device might be multi-standard.
295 We could just copy out the current value for the
296 standard, but it can change over time. For now just
297 leave it zero. */
298
299 memcpy(vi, &tmp, sizeof(tmp));
300
301 ret = 0;
302 break;
303 }
304
305 case VIDIOC_G_INPUT:
306 {
307 struct pvr2_ctrl *cptr;
308 struct v4l2_input *vi = (struct v4l2_input *)arg;
309 int val;
310 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
311 val = 0;
312 ret = pvr2_ctrl_get_value(cptr,&val);
313 vi->index = val;
314 break;
315 }
316
317 case VIDIOC_S_INPUT:
318 {
319 struct v4l2_input *vi = (struct v4l2_input *)arg;
320 ret = pvr2_ctrl_set_value(
321 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
322 vi->index);
323 break;
324 }
325
326 case VIDIOC_ENUMAUDIO:
327 {
328 ret = -EINVAL;
329 break;
330 }
331
332 case VIDIOC_G_AUDIO:
333 {
334 ret = -EINVAL;
335 break;
336 }
337
338 case VIDIOC_S_AUDIO:
339 {
340 ret = -EINVAL;
341 break;
342 }
343 case VIDIOC_G_TUNER:
344 {
345 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
346 unsigned int status_mask;
347 int val;
348 if (vt->index !=0) break;
349
350 status_mask = pvr2_hdw_get_signal_status(hdw);
351
352 memcpy(vt, &pvr_v4l2_tuners[vt->index],
353 sizeof(struct v4l2_tuner));
354
355 vt->signal = 0;
356 if (status_mask & PVR2_SIGNAL_OK) {
357 if (status_mask & PVR2_SIGNAL_STEREO) {
358 vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
359 } else {
360 vt->rxsubchans = V4L2_TUNER_SUB_MONO;
361 }
362 if (status_mask & PVR2_SIGNAL_SAP) {
363 vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 |
364 V4L2_TUNER_SUB_LANG2);
365 }
366 vt->signal = 65535;
367 }
368
369 val = 0;
370 ret = pvr2_ctrl_get_value(
371 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
372 &val);
373 vt->audmode = val;
374 break;
375 }
376
377 case VIDIOC_S_TUNER:
378 {
379 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
380
381 if (vt->index != 0)
382 break;
383
384 ret = pvr2_ctrl_set_value(
385 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
386 vt->audmode);
387 }
388
389 case VIDIOC_S_FREQUENCY:
390 {
391 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
392 ret = pvr2_ctrl_set_value(
393 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
394 vf->frequency * 62500);
395 break;
396 }
397
398 case VIDIOC_G_FREQUENCY:
399 {
400 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
401 int val = 0;
402 ret = pvr2_ctrl_get_value(
403 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
404 &val);
405 val /= 62500;
406 vf->frequency = val;
407 break;
408 }
409
410 case VIDIOC_ENUM_FMT:
411 {
412 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
413
414 /* Only one format is supported : mpeg.*/
415 if (fd->index != 0)
416 break;
417
418 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
419 ret = 0;
420 break;
421 }
422
423 case VIDIOC_G_FMT:
424 {
425 struct v4l2_format *vf = (struct v4l2_format *)arg;
426 int val;
427 switch(vf->type) {
428 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
429 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
430 sizeof(struct v4l2_format));
431 val = 0;
432 pvr2_ctrl_get_value(
433 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
434 &val);
435 vf->fmt.pix.width = val;
436 val = 0;
437 pvr2_ctrl_get_value(
438 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
439 &val);
440 vf->fmt.pix.height = val;
441 ret = 0;
442 break;
443 case V4L2_BUF_TYPE_VBI_CAPTURE:
444 // ????? Still need to figure out to do VBI correctly
445 ret = -EINVAL;
446 break;
447 default:
448 ret = -EINVAL;
449 break;
450 }
451 break;
452 }
453
454 case VIDIOC_TRY_FMT:
455 case VIDIOC_S_FMT:
456 {
457 struct v4l2_format *vf = (struct v4l2_format *)arg;
458
459 ret = 0;
460 switch(vf->type) {
461 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
462 int h = vf->fmt.pix.height;
463 int w = vf->fmt.pix.width;
464
465 if (h < 200) {
466 h = 200;
467 } else if (h > 625) {
468 h = 625;
469 }
470 if (w < 320) {
471 w = 320;
472 } else if (w > 720) {
473 w = 720;
474 }
475
476 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
477 sizeof(struct v4l2_format));
478 vf->fmt.pix.width = w;
479 vf->fmt.pix.height = h;
480
481 if (cmd == VIDIOC_S_FMT) {
482 pvr2_ctrl_set_value(
483 pvr2_hdw_get_ctrl_by_id(hdw,
484 PVR2_CID_HRES),
485 vf->fmt.pix.width);
486 pvr2_ctrl_set_value(
487 pvr2_hdw_get_ctrl_by_id(hdw,
488 PVR2_CID_VRES),
489 vf->fmt.pix.height);
490 }
491 } break;
492 case V4L2_BUF_TYPE_VBI_CAPTURE:
493 // ????? Still need to figure out to do VBI correctly
494 ret = -EINVAL;
495 break;
496 default:
497 ret = -EINVAL;
498 break;
499 }
500 break;
501 }
502
503 case VIDIOC_STREAMON:
504 {
505 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
506 if (ret < 0) return ret;
507 ret = pvr2_hdw_set_streaming(hdw,!0);
508 break;
509 }
510
511 case VIDIOC_STREAMOFF:
512 {
513 ret = pvr2_hdw_set_streaming(hdw,0);
514 break;
515 }
516
517 case VIDIOC_QUERYCTRL:
518 {
519 struct pvr2_ctrl *cptr;
520 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
521 ret = 0;
522 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
523 cptr = pvr2_hdw_get_ctrl_nextv4l(
524 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
525 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
526 } else {
527 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
528 }
529 if (!cptr) {
530 pvr2_trace(PVR2_TRACE_V4LIOCTL,
531 "QUERYCTRL id=0x%x not implemented here",
532 vc->id);
533 ret = -EINVAL;
534 break;
535 }
536
537 pvr2_trace(PVR2_TRACE_V4LIOCTL,
538 "QUERYCTRL id=0x%x mapping name=%s (%s)",
539 vc->id,pvr2_ctrl_get_name(cptr),
540 pvr2_ctrl_get_desc(cptr));
541 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
542 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
543 vc->default_value = pvr2_ctrl_get_def(cptr);
544 switch (pvr2_ctrl_get_type(cptr)) {
545 case pvr2_ctl_enum:
546 vc->type = V4L2_CTRL_TYPE_MENU;
547 vc->minimum = 0;
548 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
549 vc->step = 1;
550 break;
551 case pvr2_ctl_bool:
552 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
553 vc->minimum = 0;
554 vc->maximum = 1;
555 vc->step = 1;
556 break;
557 case pvr2_ctl_int:
558 vc->type = V4L2_CTRL_TYPE_INTEGER;
559 vc->minimum = pvr2_ctrl_get_min(cptr);
560 vc->maximum = pvr2_ctrl_get_max(cptr);
561 vc->step = 1;
562 break;
563 default:
564 pvr2_trace(PVR2_TRACE_V4LIOCTL,
565 "QUERYCTRL id=0x%x name=%s not mappable",
566 vc->id,pvr2_ctrl_get_name(cptr));
567 ret = -EINVAL;
568 break;
569 }
570 break;
571 }
572
573 case VIDIOC_QUERYMENU:
574 {
575 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
576 unsigned int cnt = 0;
577 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
578 vm->index,
579 vm->name,sizeof(vm->name)-1,
580 &cnt);
581 vm->name[cnt] = 0;
582 break;
583 }
584
585 case VIDIOC_G_CTRL:
586 {
587 struct v4l2_control *vc = (struct v4l2_control *)arg;
588 int val = 0;
589 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
590 &val);
591 vc->value = val;
592 break;
593 }
594
595 case VIDIOC_S_CTRL:
596 {
597 struct v4l2_control *vc = (struct v4l2_control *)arg;
598 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
599 vc->value);
600 break;
601 }
602
603 case VIDIOC_G_EXT_CTRLS:
604 {
605 struct v4l2_ext_controls *ctls =
606 (struct v4l2_ext_controls *)arg;
607 struct v4l2_ext_control *ctrl;
608 unsigned int idx;
609 int val;
610 for (idx = 0; idx < ctls->count; idx++) {
611 ctrl = ctls->controls + idx;
612 ret = pvr2_ctrl_get_value(
613 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
614 if (ret) {
615 ctls->error_idx = idx;
616 break;
617 }
618 /* Ensure that if read as a 64 bit value, the user
619 will still get a hopefully sane value */
620 ctrl->value64 = 0;
621 ctrl->value = val;
622 }
623 break;
624 }
625
626 case VIDIOC_S_EXT_CTRLS:
627 {
628 struct v4l2_ext_controls *ctls =
629 (struct v4l2_ext_controls *)arg;
630 struct v4l2_ext_control *ctrl;
631 unsigned int idx;
632 for (idx = 0; idx < ctls->count; idx++) {
633 ctrl = ctls->controls + idx;
634 ret = pvr2_ctrl_set_value(
635 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
636 ctrl->value);
637 if (ret) {
638 ctls->error_idx = idx;
639 break;
640 }
641 }
642 break;
643 }
644
645 case VIDIOC_TRY_EXT_CTRLS:
646 {
647 struct v4l2_ext_controls *ctls =
648 (struct v4l2_ext_controls *)arg;
649 struct v4l2_ext_control *ctrl;
650 struct pvr2_ctrl *pctl;
651 unsigned int idx;
652 /* For the moment just validate that the requested control
653 actually exists. */
654 for (idx = 0; idx < ctls->count; idx++) {
655 ctrl = ctls->controls + idx;
656 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
657 if (!pctl) {
658 ret = -EINVAL;
659 ctls->error_idx = idx;
660 break;
661 }
662 }
663 break;
664 }
665
666 case VIDIOC_LOG_STATUS:
667 {
668 pvr2_hdw_trigger_module_log(hdw);
669 ret = 0;
670 break;
671 }
672
673 default :
674 ret = v4l_compat_translate_ioctl(inode,file,cmd,
675 arg,pvr2_v4l2_do_ioctl);
676 }
677
678 pvr2_hdw_commit_ctl(hdw);
679
680 if (ret < 0) {
681 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
682 pvr2_trace(PVR2_TRACE_V4LIOCTL,
683 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
684 } else {
685 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
686 pvr2_trace(PVR2_TRACE_V4LIOCTL,
687 "pvr2_v4l2_do_ioctl failure, ret=%d"
688 " command was:",ret);
689 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
690 cmd);
691 }
692 }
693 } else {
694 pvr2_trace(PVR2_TRACE_V4LIOCTL,
695 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
696 ret,ret);
697 }
698 return ret;
699}
700
701
702static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
703{
704 pvr2_trace(PVR2_TRACE_INIT,
705 "unregistering device video%d [%s]",
706 dip->vdev->minor,pvr2_config_get_name(dip->config));
707 if (dip->ctxt_idx >= 0) {
708 mutex_lock(&device_lock);
709 devices[dip->ctxt_idx] = NULL;
710 dip->ctxt_idx = -1;
711 mutex_unlock(&device_lock);
712 }
713 video_unregister_device(dip->vdev);
714}
715
716
717static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
718{
719 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1);
720 pvr2_v4l2_dev_destroy(&vp->video_dev);
721
722 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
723 pvr2_channel_done(&vp->channel);
724 kfree(vp);
725}
726
727
728void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
729{
730 struct pvr2_v4l2 *vp;
731 vp = container_of(chp,struct pvr2_v4l2,channel);
732 if (!vp->channel.mc_head->disconnect_flag) return;
733 if (vp->vfirst) return;
734 pvr2_v4l2_destroy_no_lock(vp);
735}
736
737
738int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
739 unsigned int cmd, unsigned long arg)
740{
741
742/* Temporary hack : use ivtv api until a v4l2 one is available. */
743#define IVTV_IOC_G_CODEC 0xFFEE7703
744#define IVTV_IOC_S_CODEC 0xFFEE7704
745 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
746 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
747}
748
749
750int pvr2_v4l2_release(struct inode *inode, struct file *file)
751{
752 struct pvr2_v4l2_fh *fhp = file->private_data;
753 struct pvr2_v4l2 *vp = fhp->vhead;
754 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
755
756 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
757
758 if (fhp->rhp) {
759 struct pvr2_stream *sp;
760 struct pvr2_hdw *hdw;
761 hdw = fhp->channel.mc_head->hdw;
762 pvr2_hdw_set_streaming(hdw,0);
763 sp = pvr2_ioread_get_stream(fhp->rhp);
764 if (sp) pvr2_stream_set_callback(sp,0,0);
765 pvr2_ioread_destroy(fhp->rhp);
766 fhp->rhp = 0;
767 }
768 v4l2_prio_close(&vp->prio, &fhp->prio);
769 file->private_data = NULL;
770
771 pvr2_context_enter(mp); do {
772 if (fhp->vnext) {
773 fhp->vnext->vprev = fhp->vprev;
774 } else {
775 vp->vlast = fhp->vprev;
776 }
777 if (fhp->vprev) {
778 fhp->vprev->vnext = fhp->vnext;
779 } else {
780 vp->vfirst = fhp->vnext;
781 }
782 fhp->vnext = 0;
783 fhp->vprev = 0;
784 fhp->vhead = 0;
785 pvr2_channel_done(&fhp->channel);
786 pvr2_trace(PVR2_TRACE_STRUCT,
787 "Destroying pvr_v4l2_fh id=%p",fhp);
788 kfree(fhp);
789 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
790 pvr2_v4l2_destroy_no_lock(vp);
791 }
792 } while (0); pvr2_context_exit(mp);
793 return 0;
794}
795
796
797int pvr2_v4l2_open(struct inode *inode, struct file *file)
798{
799 struct pvr2_v4l2_dev *dip = 0; /* Our own context pointer */
800 struct pvr2_v4l2_fh *fhp;
801 struct pvr2_v4l2 *vp;
802 struct pvr2_hdw *hdw;
803
804 mutex_lock(&device_lock);
805 /* MCI 7-Jun-2006 Even though we're just doing what amounts to an
806 atomic read of the device mapping array here, we still need the
807 mutex. The problem is that there is a tiny race possible when
808 we register the device. We can't update the device mapping
809 array until after the device has been registered, owing to the
810 fact that we can't know the minor device number until after the
811 registration succeeds. And if another thread tries to open the
812 device in the window of time after registration but before the
813 map is updated, then it will get back an erroneous null pointer
814 and the open will result in a spurious failure. The only way to
815 prevent that is to (a) be inside the mutex here before we access
816 the array, and (b) cover the entire registration process later
817 on with this same mutex. Thus if we get inside the mutex here,
818 then we can be assured that the registration process actually
819 completed correctly. This is an unhappy complication from the
820 use of global data in a driver that lives in a preemptible
821 environment. It sure would be nice if the video device itself
822 had a means for storing and retrieving a local context pointer.
823 Oh wait. It did. But now it's gone. Silly me. */
824 {
825 unsigned int midx = iminor(file->f_dentry->d_inode);
826 if (midx < sizeof(devices)/sizeof(devices[0])) {
827 dip = devices[midx];
828 }
829 }
830 mutex_unlock(&device_lock);
831
832 if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */
833
834 vp = dip->v4lp;
835 hdw = vp->channel.hdw;
836
837 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
838
839 if (!pvr2_hdw_dev_ok(hdw)) {
840 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
841 "pvr2_v4l2_open: hardware not ready");
842 return -EIO;
843 }
844
845 fhp = kmalloc(sizeof(*fhp),GFP_KERNEL);
846 if (!fhp) {
847 return -ENOMEM;
848 }
849 memset(fhp,0,sizeof(*fhp));
850
851 init_waitqueue_head(&fhp->wait_data);
852 fhp->dev_info = dip;
853
854 pvr2_context_enter(vp->channel.mc_head); do {
855 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
856 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
857 fhp->vnext = 0;
858 fhp->vprev = vp->vlast;
859 if (vp->vlast) {
860 vp->vlast->vnext = fhp;
861 } else {
862 vp->vfirst = fhp;
863 }
864 vp->vlast = fhp;
865 fhp->vhead = vp;
866 } while (0); pvr2_context_exit(vp->channel.mc_head);
867
868 fhp->file = file;
869 file->private_data = fhp;
870 v4l2_prio_open(&vp->prio,&fhp->prio);
871
872 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
873
874 return 0;
875}
876
877
878static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
879{
880 wake_up(&fhp->wait_data);
881}
882
883static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
884{
885 int ret;
886 struct pvr2_stream *sp;
887 struct pvr2_hdw *hdw;
888 if (fh->rhp) return 0;
889
890 /* First read() attempt. Try to claim the stream and start
891 it... */
892 if ((ret = pvr2_channel_claim_stream(&fh->channel,
893 fh->dev_info->stream)) != 0) {
894 /* Someone else must already have it */
895 return ret;
896 }
897
898 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
899 if (!fh->rhp) {
900 pvr2_channel_claim_stream(&fh->channel,0);
901 return -ENOMEM;
902 }
903
904 hdw = fh->channel.mc_head->hdw;
905 sp = fh->dev_info->stream->stream;
906 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
907 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
908 pvr2_hdw_set_streaming(hdw,!0);
909 ret = pvr2_ioread_set_enabled(fh->rhp,!0);
910
911 return ret;
912}
913
914
915static ssize_t pvr2_v4l2_read(struct file *file,
916 char __user *buff, size_t count, loff_t *ppos)
917{
918 struct pvr2_v4l2_fh *fh = file->private_data;
919 int ret;
920
921 if (fh->fw_mode_flag) {
922 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
923 char *tbuf;
924 int c1,c2;
925 int tcnt = 0;
926 unsigned int offs = *ppos;
927
928 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
929 if (!tbuf) return -ENOMEM;
930
931 while (count) {
932 c1 = count;
933 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
934 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
935 if (c2 < 0) {
936 tcnt = c2;
937 break;
938 }
939 if (!c2) break;
940 if (copy_to_user(buff,tbuf,c2)) {
941 tcnt = -EFAULT;
942 break;
943 }
944 offs += c2;
945 tcnt += c2;
946 buff += c2;
947 count -= c2;
948 *ppos += c2;
949 }
950 kfree(tbuf);
951 return tcnt;
952 }
953
954 if (!fh->rhp) {
955 ret = pvr2_v4l2_iosetup(fh);
956 if (ret) {
957 return ret;
958 }
959 }
960
961 for (;;) {
962 ret = pvr2_ioread_read(fh->rhp,buff,count);
963 if (ret >= 0) break;
964 if (ret != -EAGAIN) break;
965 if (file->f_flags & O_NONBLOCK) break;
966 /* Doing blocking I/O. Wait here. */
967 ret = wait_event_interruptible(
968 fh->wait_data,
969 pvr2_ioread_avail(fh->rhp) >= 0);
970 if (ret < 0) break;
971 }
972
973 return ret;
974}
975
976
977static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
978{
979 unsigned int mask = 0;
980 struct pvr2_v4l2_fh *fh = file->private_data;
981 int ret;
982
983 if (fh->fw_mode_flag) {
984 mask |= POLLIN | POLLRDNORM;
985 return mask;
986 }
987
988 if (!fh->rhp) {
989 ret = pvr2_v4l2_iosetup(fh);
990 if (ret) return POLLERR;
991 }
992
993 poll_wait(file,&fh->wait_data,wait);
994
995 if (pvr2_ioread_avail(fh->rhp) >= 0) {
996 mask |= POLLIN | POLLRDNORM;
997 }
998
999 return mask;
1000}
1001
1002
1003static struct file_operations vdev_fops = {
1004 .owner = THIS_MODULE,
1005 .open = pvr2_v4l2_open,
1006 .release = pvr2_v4l2_release,
1007 .read = pvr2_v4l2_read,
1008 .ioctl = pvr2_v4l2_ioctl,
1009 .llseek = no_llseek,
1010 .poll = pvr2_v4l2_poll,
1011};
1012
1013
1014#define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */
1015
1016static struct video_device vdev_template = {
1017 .owner = THIS_MODULE,
1018 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1019 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1020 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1021 | V4L2_CAP_READWRITE),
1022 .hardware = VID_HARDWARE_PVRUSB2,
1023 .fops = &vdev_fops,
1024};
1025
1026
1027static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1028 struct pvr2_v4l2 *vp,
1029 enum pvr2_config cfg)
1030{
1031 int mindevnum;
1032 int unit_number;
1033 int v4l_type;
1034 dip->v4lp = vp;
1035 dip->config = cfg;
1036
1037
1038 switch (cfg) {
1039 case pvr2_config_mpeg:
1040 v4l_type = VFL_TYPE_GRABBER;
1041 dip->stream = &vp->channel.mc_head->video_stream;
1042 break;
1043 case pvr2_config_vbi:
1044 v4l_type = VFL_TYPE_VBI;
1045 break;
1046 case pvr2_config_radio:
1047 v4l_type = VFL_TYPE_RADIO;
1048 break;
1049 default:
1050 /* Bail out (this should be impossible) */
1051 err("Failed to set up pvrusb2 v4l dev"
1052 " due to unrecognized config");
1053 return;
1054 }
1055
1056 if (!dip->stream) {
1057 err("Failed to set up pvrusb2 v4l dev"
1058 " due to missing stream instance");
1059 return;
1060 }
1061
1062 dip->vdev = video_device_alloc();
1063 if (!dip->vdev) {
1064 err("Alloc of pvrusb2 v4l video device failed");
1065 return;
1066 }
1067
1068 memcpy(dip->vdev,&vdev_template,sizeof(vdev_template));
1069 dip->vdev->release = video_device_release;
1070 mutex_lock(&device_lock);
1071
1072 mindevnum = -1;
1073 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
1074 if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
1075 mindevnum = video_nr[unit_number];
1076 }
1077 if ((video_register_device(dip->vdev, v4l_type, mindevnum) < 0) &&
1078 (video_register_device(dip->vdev, v4l_type, -1) < 0)) {
1079 err("Failed to register pvrusb2 v4l video device");
1080 } else {
1081 pvr2_trace(PVR2_TRACE_INIT,
1082 "registered device video%d [%s]",
1083 dip->vdev->minor,pvr2_config_get_name(dip->config));
1084 }
1085
1086 if ((dip->vdev->minor < sizeof(devices)/sizeof(devices[0])) &&
1087 (devices[dip->vdev->minor] == NULL)) {
1088 dip->ctxt_idx = dip->vdev->minor;
1089 devices[dip->ctxt_idx] = dip;
1090 }
1091 mutex_unlock(&device_lock);
1092
1093 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
1094 dip->vdev->minor);
1095}
1096
1097
1098struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1099{
1100 struct pvr2_v4l2 *vp;
1101
1102 vp = kmalloc(sizeof(*vp),GFP_KERNEL);
1103 if (!vp) return vp;
1104 memset(vp,0,sizeof(*vp));
1105 vp->video_dev.ctxt_idx = -1;
1106 pvr2_channel_init(&vp->channel,mnp);
1107 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1108
1109 vp->channel.check_func = pvr2_v4l2_internal_check;
1110
1111 /* register streams */
1112 pvr2_v4l2_dev_init(&vp->video_dev,vp,pvr2_config_mpeg);
1113
1114
1115 return vp;
1116}
1117
1118/*
1119 Stuff for Emacs to see, in order to encourage consistent editing style:
1120 *** Local Variables: ***
1121 *** mode: c ***
1122 *** fill-column: 75 ***
1123 *** tab-width: 8 ***
1124 *** c-basic-offset: 8 ***
1125 *** End: ***
1126 */