blob: 156e375c93e9ed1cc0ebd53608544f2ad3c1c25e [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>
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
Adrian Bunk07e337e2006-06-30 11:30:20 -030084static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030085 .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
Adrian Bunk07e337e2006-06-30 11:30:20 -0300114static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300115 {
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
Adrian Bunk07e337e2006-06-30 11:30:20 -0300130static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300131 [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(
Mike Iselyd8554972006-06-26 20:58:46 -0300438 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: {
Mike Iselye95a1912006-08-08 09:10:07 -0300462 int lmin,lmax;
463 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300464 int h = vf->fmt.pix.height;
465 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300466 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
467 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300468
Mike Iselye95a1912006-08-08 09:10:07 -0300469 lmin = pvr2_ctrl_get_min(hcp);
470 lmax = pvr2_ctrl_get_max(hcp);
Mike Iselye95a1912006-08-08 09:10:07 -0300471 if (w < lmin) {
472 w = lmin;
473 } else if (w > lmax) {
474 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300475 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300476 lmin = pvr2_ctrl_get_min(vcp);
477 lmax = pvr2_ctrl_get_max(vcp);
478 if (h < lmin) {
479 h = lmin;
480 } else if (h > lmax) {
481 h = lmax;
482 }
Mike Iselyd8554972006-06-26 20:58:46 -0300483
484 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
485 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300486 vf->fmt.pix.width = w;
487 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300488
489 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300490 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
491 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300492 }
493 } break;
494 case V4L2_BUF_TYPE_VBI_CAPTURE:
495 // ????? Still need to figure out to do VBI correctly
496 ret = -EINVAL;
497 break;
498 default:
499 ret = -EINVAL;
500 break;
501 }
502 break;
503 }
504
505 case VIDIOC_STREAMON:
506 {
507 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
508 if (ret < 0) return ret;
509 ret = pvr2_hdw_set_streaming(hdw,!0);
510 break;
511 }
512
513 case VIDIOC_STREAMOFF:
514 {
515 ret = pvr2_hdw_set_streaming(hdw,0);
516 break;
517 }
518
519 case VIDIOC_QUERYCTRL:
520 {
521 struct pvr2_ctrl *cptr;
522 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
523 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300524 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
525 cptr = pvr2_hdw_get_ctrl_nextv4l(
526 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
527 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
528 } else {
529 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
530 }
Mike Iselyd8554972006-06-26 20:58:46 -0300531 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300532 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300533 "QUERYCTRL id=0x%x not implemented here",
534 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300535 ret = -EINVAL;
536 break;
537 }
538
Mike Iselya761f432006-06-25 20:04:44 -0300539 pvr2_trace(PVR2_TRACE_V4LIOCTL,
540 "QUERYCTRL id=0x%x mapping name=%s (%s)",
541 vc->id,pvr2_ctrl_get_name(cptr),
542 pvr2_ctrl_get_desc(cptr));
543 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
544 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300545 vc->default_value = pvr2_ctrl_get_def(cptr);
546 switch (pvr2_ctrl_get_type(cptr)) {
547 case pvr2_ctl_enum:
548 vc->type = V4L2_CTRL_TYPE_MENU;
549 vc->minimum = 0;
550 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
551 vc->step = 1;
552 break;
Mike Isely33213962006-06-25 20:04:40 -0300553 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300554 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300555 vc->minimum = 0;
556 vc->maximum = 1;
557 vc->step = 1;
558 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300559 case pvr2_ctl_int:
560 vc->type = V4L2_CTRL_TYPE_INTEGER;
561 vc->minimum = pvr2_ctrl_get_min(cptr);
562 vc->maximum = pvr2_ctrl_get_max(cptr);
563 vc->step = 1;
564 break;
565 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300566 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300567 "QUERYCTRL id=0x%x name=%s not mappable",
568 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300569 ret = -EINVAL;
570 break;
571 }
572 break;
573 }
574
575 case VIDIOC_QUERYMENU:
576 {
577 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
578 unsigned int cnt = 0;
579 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
580 vm->index,
581 vm->name,sizeof(vm->name)-1,
582 &cnt);
583 vm->name[cnt] = 0;
584 break;
585 }
586
587 case VIDIOC_G_CTRL:
588 {
589 struct v4l2_control *vc = (struct v4l2_control *)arg;
590 int val = 0;
591 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
592 &val);
593 vc->value = val;
594 break;
595 }
596
597 case VIDIOC_S_CTRL:
598 {
599 struct v4l2_control *vc = (struct v4l2_control *)arg;
600 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
601 vc->value);
602 break;
603 }
604
Mike Isely1d9f8462006-06-25 20:04:58 -0300605 case VIDIOC_G_EXT_CTRLS:
606 {
607 struct v4l2_ext_controls *ctls =
608 (struct v4l2_ext_controls *)arg;
609 struct v4l2_ext_control *ctrl;
610 unsigned int idx;
611 int val;
612 for (idx = 0; idx < ctls->count; idx++) {
613 ctrl = ctls->controls + idx;
614 ret = pvr2_ctrl_get_value(
615 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
616 if (ret) {
617 ctls->error_idx = idx;
618 break;
619 }
620 /* Ensure that if read as a 64 bit value, the user
621 will still get a hopefully sane value */
622 ctrl->value64 = 0;
623 ctrl->value = val;
624 }
625 break;
626 }
627
628 case VIDIOC_S_EXT_CTRLS:
629 {
630 struct v4l2_ext_controls *ctls =
631 (struct v4l2_ext_controls *)arg;
632 struct v4l2_ext_control *ctrl;
633 unsigned int idx;
634 for (idx = 0; idx < ctls->count; idx++) {
635 ctrl = ctls->controls + idx;
636 ret = pvr2_ctrl_set_value(
637 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
638 ctrl->value);
639 if (ret) {
640 ctls->error_idx = idx;
641 break;
642 }
643 }
644 break;
645 }
646
647 case VIDIOC_TRY_EXT_CTRLS:
648 {
649 struct v4l2_ext_controls *ctls =
650 (struct v4l2_ext_controls *)arg;
651 struct v4l2_ext_control *ctrl;
652 struct pvr2_ctrl *pctl;
653 unsigned int idx;
654 /* For the moment just validate that the requested control
655 actually exists. */
656 for (idx = 0; idx < ctls->count; idx++) {
657 ctrl = ctls->controls + idx;
658 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
659 if (!pctl) {
660 ret = -EINVAL;
661 ctls->error_idx = idx;
662 break;
663 }
664 }
665 break;
666 }
667
Mike Iselyd8554972006-06-26 20:58:46 -0300668 case VIDIOC_LOG_STATUS:
669 {
Mike Iselyd8554972006-06-26 20:58:46 -0300670 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300671 ret = 0;
672 break;
673 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300674#ifdef CONFIG_VIDEO_ADV_DEBUG
675 case VIDIOC_INT_G_REGISTER:
676 case VIDIOC_INT_S_REGISTER:
677 {
678 u32 val;
679 struct v4l2_register *req = (struct v4l2_register *)arg;
680 if (cmd == VIDIOC_INT_S_REGISTER) val = req->val;
681 ret = pvr2_hdw_register_access(
682 hdw,req->i2c_id,req->reg,
683 cmd == VIDIOC_INT_S_REGISTER,&val);
684 if (cmd == 0) req->val = val;
685 break;
686 }
687#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300688
689 default :
690 ret = v4l_compat_translate_ioctl(inode,file,cmd,
691 arg,pvr2_v4l2_do_ioctl);
692 }
693
694 pvr2_hdw_commit_ctl(hdw);
695
696 if (ret < 0) {
697 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300698 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300699 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
700 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300701 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
702 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300703 "pvr2_v4l2_do_ioctl failure, ret=%d"
704 " command was:",ret);
705 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
706 cmd);
707 }
708 }
709 } else {
710 pvr2_trace(PVR2_TRACE_V4LIOCTL,
711 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
712 ret,ret);
713 }
714 return ret;
715}
716
717
718static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
719{
Mike Isely47ed3bc2006-06-29 09:26:43 -0300720 printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n",
721 dip->vdev->minor,pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -0300722 if (dip->ctxt_idx >= 0) {
723 mutex_lock(&device_lock);
724 devices[dip->ctxt_idx] = NULL;
725 dip->ctxt_idx = -1;
726 mutex_unlock(&device_lock);
727 }
728 video_unregister_device(dip->vdev);
729}
730
731
732static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
733{
734 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1);
735 pvr2_v4l2_dev_destroy(&vp->video_dev);
736
737 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
738 pvr2_channel_done(&vp->channel);
739 kfree(vp);
740}
741
742
Adrian Bunk07e337e2006-06-30 11:30:20 -0300743static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300744{
745 struct pvr2_v4l2 *vp;
746 vp = container_of(chp,struct pvr2_v4l2,channel);
747 if (!vp->channel.mc_head->disconnect_flag) return;
748 if (vp->vfirst) return;
749 pvr2_v4l2_destroy_no_lock(vp);
750}
751
752
Adrian Bunk07e337e2006-06-30 11:30:20 -0300753static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
754 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300755{
756
757/* Temporary hack : use ivtv api until a v4l2 one is available. */
758#define IVTV_IOC_G_CODEC 0xFFEE7703
759#define IVTV_IOC_S_CODEC 0xFFEE7704
760 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
761 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
762}
763
764
Adrian Bunk07e337e2006-06-30 11:30:20 -0300765static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300766{
767 struct pvr2_v4l2_fh *fhp = file->private_data;
768 struct pvr2_v4l2 *vp = fhp->vhead;
769 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
770
771 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
772
773 if (fhp->rhp) {
774 struct pvr2_stream *sp;
775 struct pvr2_hdw *hdw;
776 hdw = fhp->channel.mc_head->hdw;
777 pvr2_hdw_set_streaming(hdw,0);
778 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300779 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300780 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300781 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300782 }
783 v4l2_prio_close(&vp->prio, &fhp->prio);
784 file->private_data = NULL;
785
786 pvr2_context_enter(mp); do {
787 if (fhp->vnext) {
788 fhp->vnext->vprev = fhp->vprev;
789 } else {
790 vp->vlast = fhp->vprev;
791 }
792 if (fhp->vprev) {
793 fhp->vprev->vnext = fhp->vnext;
794 } else {
795 vp->vfirst = fhp->vnext;
796 }
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300797 fhp->vnext = NULL;
798 fhp->vprev = NULL;
799 fhp->vhead = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300800 pvr2_channel_done(&fhp->channel);
801 pvr2_trace(PVR2_TRACE_STRUCT,
802 "Destroying pvr_v4l2_fh id=%p",fhp);
803 kfree(fhp);
804 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
805 pvr2_v4l2_destroy_no_lock(vp);
806 }
807 } while (0); pvr2_context_exit(mp);
808 return 0;
809}
810
811
Adrian Bunk07e337e2006-06-30 11:30:20 -0300812static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300813{
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300814 struct pvr2_v4l2_dev *dip = NULL; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300815 struct pvr2_v4l2_fh *fhp;
816 struct pvr2_v4l2 *vp;
817 struct pvr2_hdw *hdw;
818
819 mutex_lock(&device_lock);
820 /* MCI 7-Jun-2006 Even though we're just doing what amounts to an
821 atomic read of the device mapping array here, we still need the
822 mutex. The problem is that there is a tiny race possible when
823 we register the device. We can't update the device mapping
824 array until after the device has been registered, owing to the
825 fact that we can't know the minor device number until after the
826 registration succeeds. And if another thread tries to open the
827 device in the window of time after registration but before the
828 map is updated, then it will get back an erroneous null pointer
829 and the open will result in a spurious failure. The only way to
830 prevent that is to (a) be inside the mutex here before we access
831 the array, and (b) cover the entire registration process later
832 on with this same mutex. Thus if we get inside the mutex here,
833 then we can be assured that the registration process actually
834 completed correctly. This is an unhappy complication from the
835 use of global data in a driver that lives in a preemptible
836 environment. It sure would be nice if the video device itself
837 had a means for storing and retrieving a local context pointer.
838 Oh wait. It did. But now it's gone. Silly me. */
839 {
840 unsigned int midx = iminor(file->f_dentry->d_inode);
841 if (midx < sizeof(devices)/sizeof(devices[0])) {
842 dip = devices[midx];
843 }
844 }
845 mutex_unlock(&device_lock);
846
847 if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */
848
849 vp = dip->v4lp;
850 hdw = vp->channel.hdw;
851
852 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
853
854 if (!pvr2_hdw_dev_ok(hdw)) {
855 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
856 "pvr2_v4l2_open: hardware not ready");
857 return -EIO;
858 }
859
860 fhp = kmalloc(sizeof(*fhp),GFP_KERNEL);
861 if (!fhp) {
862 return -ENOMEM;
863 }
864 memset(fhp,0,sizeof(*fhp));
865
866 init_waitqueue_head(&fhp->wait_data);
867 fhp->dev_info = dip;
868
869 pvr2_context_enter(vp->channel.mc_head); do {
870 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
871 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300872 fhp->vnext = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300873 fhp->vprev = vp->vlast;
874 if (vp->vlast) {
875 vp->vlast->vnext = fhp;
876 } else {
877 vp->vfirst = fhp;
878 }
879 vp->vlast = fhp;
880 fhp->vhead = vp;
881 } while (0); pvr2_context_exit(vp->channel.mc_head);
882
883 fhp->file = file;
884 file->private_data = fhp;
885 v4l2_prio_open(&vp->prio,&fhp->prio);
886
887 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
888
889 return 0;
890}
891
892
893static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
894{
895 wake_up(&fhp->wait_data);
896}
897
898static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
899{
900 int ret;
901 struct pvr2_stream *sp;
902 struct pvr2_hdw *hdw;
903 if (fh->rhp) return 0;
904
905 /* First read() attempt. Try to claim the stream and start
906 it... */
907 if ((ret = pvr2_channel_claim_stream(&fh->channel,
908 fh->dev_info->stream)) != 0) {
909 /* Someone else must already have it */
910 return ret;
911 }
912
913 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
914 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300915 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300916 return -ENOMEM;
917 }
918
919 hdw = fh->channel.mc_head->hdw;
920 sp = fh->dev_info->stream->stream;
921 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
922 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
923 pvr2_hdw_set_streaming(hdw,!0);
924 ret = pvr2_ioread_set_enabled(fh->rhp,!0);
925
926 return ret;
927}
928
929
930static ssize_t pvr2_v4l2_read(struct file *file,
931 char __user *buff, size_t count, loff_t *ppos)
932{
933 struct pvr2_v4l2_fh *fh = file->private_data;
934 int ret;
935
936 if (fh->fw_mode_flag) {
937 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
938 char *tbuf;
939 int c1,c2;
940 int tcnt = 0;
941 unsigned int offs = *ppos;
942
943 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
944 if (!tbuf) return -ENOMEM;
945
946 while (count) {
947 c1 = count;
948 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
949 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
950 if (c2 < 0) {
951 tcnt = c2;
952 break;
953 }
954 if (!c2) break;
955 if (copy_to_user(buff,tbuf,c2)) {
956 tcnt = -EFAULT;
957 break;
958 }
959 offs += c2;
960 tcnt += c2;
961 buff += c2;
962 count -= c2;
963 *ppos += c2;
964 }
965 kfree(tbuf);
966 return tcnt;
967 }
968
969 if (!fh->rhp) {
970 ret = pvr2_v4l2_iosetup(fh);
971 if (ret) {
972 return ret;
973 }
974 }
975
976 for (;;) {
977 ret = pvr2_ioread_read(fh->rhp,buff,count);
978 if (ret >= 0) break;
979 if (ret != -EAGAIN) break;
980 if (file->f_flags & O_NONBLOCK) break;
981 /* Doing blocking I/O. Wait here. */
982 ret = wait_event_interruptible(
983 fh->wait_data,
984 pvr2_ioread_avail(fh->rhp) >= 0);
985 if (ret < 0) break;
986 }
987
988 return ret;
989}
990
991
992static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
993{
994 unsigned int mask = 0;
995 struct pvr2_v4l2_fh *fh = file->private_data;
996 int ret;
997
998 if (fh->fw_mode_flag) {
999 mask |= POLLIN | POLLRDNORM;
1000 return mask;
1001 }
1002
1003 if (!fh->rhp) {
1004 ret = pvr2_v4l2_iosetup(fh);
1005 if (ret) return POLLERR;
1006 }
1007
1008 poll_wait(file,&fh->wait_data,wait);
1009
1010 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1011 mask |= POLLIN | POLLRDNORM;
1012 }
1013
1014 return mask;
1015}
1016
1017
1018static struct file_operations vdev_fops = {
1019 .owner = THIS_MODULE,
1020 .open = pvr2_v4l2_open,
1021 .release = pvr2_v4l2_release,
1022 .read = pvr2_v4l2_read,
1023 .ioctl = pvr2_v4l2_ioctl,
1024 .llseek = no_llseek,
1025 .poll = pvr2_v4l2_poll,
1026};
1027
1028
1029#define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */
1030
1031static struct video_device vdev_template = {
1032 .owner = THIS_MODULE,
1033 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1034 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1035 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1036 | V4L2_CAP_READWRITE),
1037 .hardware = VID_HARDWARE_PVRUSB2,
1038 .fops = &vdev_fops,
1039};
1040
1041
1042static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1043 struct pvr2_v4l2 *vp,
1044 enum pvr2_config cfg)
1045{
1046 int mindevnum;
1047 int unit_number;
1048 int v4l_type;
1049 dip->v4lp = vp;
1050 dip->config = cfg;
1051
1052
1053 switch (cfg) {
1054 case pvr2_config_mpeg:
1055 v4l_type = VFL_TYPE_GRABBER;
1056 dip->stream = &vp->channel.mc_head->video_stream;
1057 break;
1058 case pvr2_config_vbi:
1059 v4l_type = VFL_TYPE_VBI;
1060 break;
1061 case pvr2_config_radio:
1062 v4l_type = VFL_TYPE_RADIO;
1063 break;
1064 default:
1065 /* Bail out (this should be impossible) */
1066 err("Failed to set up pvrusb2 v4l dev"
1067 " due to unrecognized config");
1068 return;
1069 }
1070
1071 if (!dip->stream) {
1072 err("Failed to set up pvrusb2 v4l dev"
1073 " due to missing stream instance");
1074 return;
1075 }
1076
1077 dip->vdev = video_device_alloc();
1078 if (!dip->vdev) {
1079 err("Alloc of pvrusb2 v4l video device failed");
1080 return;
1081 }
1082
1083 memcpy(dip->vdev,&vdev_template,sizeof(vdev_template));
1084 dip->vdev->release = video_device_release;
1085 mutex_lock(&device_lock);
1086
1087 mindevnum = -1;
1088 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
1089 if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
1090 mindevnum = video_nr[unit_number];
1091 }
1092 if ((video_register_device(dip->vdev, v4l_type, mindevnum) < 0) &&
1093 (video_register_device(dip->vdev, v4l_type, -1) < 0)) {
1094 err("Failed to register pvrusb2 v4l video device");
1095 } else {
Mike Isely47ed3bc2006-06-29 09:26:43 -03001096 printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
1097 dip->vdev->minor,pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001098 }
1099
1100 if ((dip->vdev->minor < sizeof(devices)/sizeof(devices[0])) &&
1101 (devices[dip->vdev->minor] == NULL)) {
1102 dip->ctxt_idx = dip->vdev->minor;
1103 devices[dip->ctxt_idx] = dip;
1104 }
1105 mutex_unlock(&device_lock);
1106
1107 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
1108 dip->vdev->minor);
1109}
1110
1111
1112struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1113{
1114 struct pvr2_v4l2 *vp;
1115
1116 vp = kmalloc(sizeof(*vp),GFP_KERNEL);
1117 if (!vp) return vp;
1118 memset(vp,0,sizeof(*vp));
1119 vp->video_dev.ctxt_idx = -1;
1120 pvr2_channel_init(&vp->channel,mnp);
1121 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1122
1123 vp->channel.check_func = pvr2_v4l2_internal_check;
1124
1125 /* register streams */
1126 pvr2_v4l2_dev_init(&vp->video_dev,vp,pvr2_config_mpeg);
1127
1128
1129 return vp;
1130}
1131
1132/*
1133 Stuff for Emacs to see, in order to encourage consistent editing style:
1134 *** Local Variables: ***
1135 *** mode: c ***
1136 *** fill-column: 75 ***
1137 *** tab-width: 8 ***
1138 *** c-basic-offset: 8 ***
1139 *** End: ***
1140 */