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