blob: a728ca2a37d5902d8e6959c609e818f92f9ab708 [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 Iselyc74e0062006-12-30 18:31:22 -030060 int prev_input_val;
Mike Iselyd8554972006-06-26 20:58:46 -030061};
62
63struct pvr2_v4l2 {
64 struct pvr2_channel channel;
65 struct pvr2_v4l2_fh *vfirst;
66 struct pvr2_v4l2_fh *vlast;
67
68 struct v4l2_prio_state prio;
69
Mike Isely0f0f2572006-12-27 23:19:42 -030070 /* streams - Note that these must be separately, individually,
71 * allocated pointers. This is because the v4l core is going to
72 * manage their deletion - separately, individually... */
73 struct pvr2_v4l2_dev *dev_video;
74 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030075};
76
77static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
78module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030079MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
80static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
81module_param_array(radio_nr, int, NULL, 0444);
82MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
83static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
84module_param_array(vbi_nr, int, NULL, 0444);
85MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030086
Adrian Bunk07e337e2006-06-30 11:30:20 -030087static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030088 .driver = "pvrusb2",
89 .card = "Hauppauge WinTV pvr-usb2",
90 .bus_info = "usb",
91 .version = KERNEL_VERSION(0,8,0),
92 .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -030093 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
Mike Iselyd8554972006-06-26 20:58:46 -030094 V4L2_CAP_READWRITE),
95 .reserved = {0,0,0,0}
96};
97
Adrian Bunk07e337e2006-06-30 11:30:20 -030098static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -030099 {
100 .index = 0,
101 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
102 .flags = V4L2_FMT_FLAG_COMPRESSED,
103 .description = "MPEG1/2",
104 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
105 // breaks when I do that.
106 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
107 .reserved = { 0, 0, 0, 0 }
108 }
109};
110
111#define PVR_FORMAT_PIX 0
112#define PVR_FORMAT_VBI 1
113
Adrian Bunk07e337e2006-06-30 11:30:20 -0300114static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300115 [PVR_FORMAT_PIX] = {
116 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
117 .fmt = {
118 .pix = {
119 .width = 720,
120 .height = 576,
121 // This should really be V4L2_PIX_FMT_MPEG,
122 // but xawtv breaks when I do that.
123 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
124 .field = V4L2_FIELD_INTERLACED,
125 .bytesperline = 0, // doesn't make sense
126 // here
127 //FIXME : Don't know what to put here...
128 .sizeimage = (32*1024),
129 .colorspace = 0, // doesn't make sense here
130 .priv = 0
131 }
132 }
133 },
134 [PVR_FORMAT_VBI] = {
135 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
136 .fmt = {
137 .vbi = {
138 .sampling_rate = 27000000,
139 .offset = 248,
140 .samples_per_line = 1443,
141 .sample_format = V4L2_PIX_FMT_GREY,
142 .start = { 0, 0 },
143 .count = { 0, 0 },
144 .flags = 0,
145 .reserved = { 0, 0 }
146 }
147 }
148 }
149};
150
Mike Isely16eb40d2006-12-30 18:27:32 -0300151
152static const char *get_v4l_name(int v4l_type)
153{
154 switch (v4l_type) {
155 case VFL_TYPE_GRABBER: return "video";
156 case VFL_TYPE_RADIO: return "radio";
157 case VFL_TYPE_VBI: return "vbi";
158 default: return "?";
159 }
160}
161
162
Mike Iselyd8554972006-06-26 20:58:46 -0300163/*
164 * pvr_ioctl()
165 *
166 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
167 *
168 */
169static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
170 unsigned int cmd, void *arg)
171{
172 struct pvr2_v4l2_fh *fh = file->private_data;
173 struct pvr2_v4l2 *vp = fh->vhead;
174 struct pvr2_v4l2_dev *dev_info = fh->dev_info;
175 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
176 int ret = -EINVAL;
177
178 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
179 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
180 }
181
182 if (!pvr2_hdw_dev_ok(hdw)) {
183 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
184 "ioctl failed - bad or no context");
185 return -EFAULT;
186 }
187
188 /* check priority */
189 switch (cmd) {
190 case VIDIOC_S_CTRL:
191 case VIDIOC_S_STD:
192 case VIDIOC_S_INPUT:
193 case VIDIOC_S_TUNER:
194 case VIDIOC_S_FREQUENCY:
195 ret = v4l2_prio_check(&vp->prio, &fh->prio);
196 if (ret)
197 return ret;
198 }
199
200 switch (cmd) {
201 case VIDIOC_QUERYCAP:
202 {
203 struct v4l2_capability *cap = arg;
204
205 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
206
207 ret = 0;
208 break;
209 }
210
211 case VIDIOC_G_PRIORITY:
212 {
213 enum v4l2_priority *p = arg;
214
215 *p = v4l2_prio_max(&vp->prio);
216 ret = 0;
217 break;
218 }
219
220 case VIDIOC_S_PRIORITY:
221 {
222 enum v4l2_priority *prio = arg;
223
224 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
225 break;
226 }
227
228 case VIDIOC_ENUMSTD:
229 {
230 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
231 int idx = vs->index;
232 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
233 break;
234 }
235
236 case VIDIOC_G_STD:
237 {
238 int val = 0;
239 ret = pvr2_ctrl_get_value(
240 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
241 *(v4l2_std_id *)arg = val;
242 break;
243 }
244
245 case VIDIOC_S_STD:
246 {
247 ret = pvr2_ctrl_set_value(
248 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
249 *(v4l2_std_id *)arg);
250 break;
251 }
252
253 case VIDIOC_ENUMINPUT:
254 {
255 struct pvr2_ctrl *cptr;
256 struct v4l2_input *vi = (struct v4l2_input *)arg;
257 struct v4l2_input tmp;
258 unsigned int cnt;
259
260 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
261
262 memset(&tmp,0,sizeof(tmp));
263 tmp.index = vi->index;
264 ret = 0;
265 switch (vi->index) {
266 case PVR2_CVAL_INPUT_TV:
267 case PVR2_CVAL_INPUT_RADIO:
268 tmp.type = V4L2_INPUT_TYPE_TUNER;
269 break;
270 case PVR2_CVAL_INPUT_SVIDEO:
271 case PVR2_CVAL_INPUT_COMPOSITE:
272 tmp.type = V4L2_INPUT_TYPE_CAMERA;
273 break;
274 default:
275 ret = -EINVAL;
276 break;
277 }
278 if (ret < 0) break;
279
280 cnt = 0;
281 pvr2_ctrl_get_valname(cptr,vi->index,
282 tmp.name,sizeof(tmp.name)-1,&cnt);
283 tmp.name[cnt] = 0;
284
285 /* Don't bother with audioset, since this driver currently
286 always switches the audio whenever the video is
287 switched. */
288
289 /* Handling std is a tougher problem. It doesn't make
290 sense in cases where a device might be multi-standard.
291 We could just copy out the current value for the
292 standard, but it can change over time. For now just
293 leave it zero. */
294
295 memcpy(vi, &tmp, sizeof(tmp));
296
297 ret = 0;
298 break;
299 }
300
301 case VIDIOC_G_INPUT:
302 {
303 struct pvr2_ctrl *cptr;
304 struct v4l2_input *vi = (struct v4l2_input *)arg;
305 int val;
306 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
307 val = 0;
308 ret = pvr2_ctrl_get_value(cptr,&val);
309 vi->index = val;
310 break;
311 }
312
313 case VIDIOC_S_INPUT:
314 {
315 struct v4l2_input *vi = (struct v4l2_input *)arg;
316 ret = pvr2_ctrl_set_value(
317 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
318 vi->index);
319 break;
320 }
321
322 case VIDIOC_ENUMAUDIO:
323 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300324 /* pkt: FIXME: We are returning one "fake" input here
325 which could very well be called "whatever_we_like".
326 This is for apps that want to see an audio input
327 just to feel comfortable, as well as to test if
328 it can do stereo or sth. There is actually no guarantee
329 that the actual audio input cannot change behind the app's
330 back, but most applications should not mind that either.
331
332 Hopefully, mplayer people will work with us on this (this
333 whole mess is to support mplayer pvr://), or Hans will come
334 up with a more standard way to say "we have inputs but we
335 don 't want you to change them independent of video" which
336 will sort this mess.
337 */
338 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300339 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300340 if (vin->index > 0) break;
341 strncpy(vin->name, "PVRUSB2 Audio",14);
342 vin->capability = V4L2_AUDCAP_STEREO;
343 ret = 0;
344 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300345 break;
346 }
347
348 case VIDIOC_G_AUDIO:
349 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300350 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
351 struct v4l2_audio *vin = arg;
352 memset(vin,0,sizeof(*vin));
353 vin->index = 0;
354 strncpy(vin->name, "PVRUSB2 Audio",14);
355 vin->capability = V4L2_AUDCAP_STEREO;
356 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300357 break;
358 }
359
360 case VIDIOC_S_AUDIO:
361 {
362 ret = -EINVAL;
363 break;
364 }
365 case VIDIOC_G_TUNER:
366 {
367 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mike Isely18103c52007-01-20 00:09:47 -0300368 pvr2_hdw_execute_tuner_poll(hdw);
369 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300370 break;
371 }
372
373 case VIDIOC_S_TUNER:
374 {
375 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
376
377 if (vt->index != 0)
378 break;
379
380 ret = pvr2_ctrl_set_value(
381 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
382 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300383 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300384 }
385
386 case VIDIOC_S_FREQUENCY:
387 {
388 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300389 unsigned long fv;
Mike Isely18103c52007-01-20 00:09:47 -0300390 struct v4l2_tuner vt;
391 int cur_input;
392 struct pvr2_ctrl *ctrlp;
393 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
394 if (ret != 0) break;
395 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
396 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
397 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300398 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c52007-01-20 00:09:47 -0300399 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
400 pvr2_ctrl_set_value(ctrlp,
401 PVR2_CVAL_INPUT_RADIO);
402 }
403 } else {
404 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
405 pvr2_ctrl_set_value(ctrlp,
406 PVR2_CVAL_INPUT_TV);
407 }
408 }
409 fv = vf->frequency;
410 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300411 fv = (fv * 125) / 2;
412 } else {
413 fv = fv * 62500;
414 }
Mike Iselyd8554972006-06-26 20:58:46 -0300415 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300416 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300417 break;
418 }
419
420 case VIDIOC_G_FREQUENCY:
421 {
422 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
423 int val = 0;
Mike Isely18103c52007-01-20 00:09:47 -0300424 int cur_input;
425 struct v4l2_tuner vt;
426 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
427 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300428 ret = pvr2_ctrl_get_value(
429 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
430 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300431 if (ret != 0) break;
432 pvr2_ctrl_get_value(
433 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
434 &cur_input);
435 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300436 vf->type = V4L2_TUNER_RADIO;
437 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300438 vf->type = V4L2_TUNER_ANALOG_TV;
439 }
Mike Isely18103c52007-01-20 00:09:47 -0300440 if (vt.capability & V4L2_TUNER_CAP_LOW) {
441 val = (val * 2) / 125;
442 } else {
443 val /= 62500;
444 }
445 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300446 break;
447 }
448
449 case VIDIOC_ENUM_FMT:
450 {
451 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
452
453 /* Only one format is supported : mpeg.*/
454 if (fd->index != 0)
455 break;
456
457 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
458 ret = 0;
459 break;
460 }
461
462 case VIDIOC_G_FMT:
463 {
464 struct v4l2_format *vf = (struct v4l2_format *)arg;
465 int val;
466 switch(vf->type) {
467 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
468 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
469 sizeof(struct v4l2_format));
470 val = 0;
471 pvr2_ctrl_get_value(
472 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
473 &val);
474 vf->fmt.pix.width = val;
475 val = 0;
476 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300477 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
478 &val);
479 vf->fmt.pix.height = val;
480 ret = 0;
481 break;
482 case V4L2_BUF_TYPE_VBI_CAPTURE:
483 // ????? Still need to figure out to do VBI correctly
484 ret = -EINVAL;
485 break;
486 default:
487 ret = -EINVAL;
488 break;
489 }
490 break;
491 }
492
493 case VIDIOC_TRY_FMT:
494 case VIDIOC_S_FMT:
495 {
496 struct v4l2_format *vf = (struct v4l2_format *)arg;
497
498 ret = 0;
499 switch(vf->type) {
500 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Mike Iselye95a1912006-08-08 09:10:07 -0300501 int lmin,lmax;
502 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300503 int h = vf->fmt.pix.height;
504 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300505 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
506 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300507
Mike Iselye95a1912006-08-08 09:10:07 -0300508 lmin = pvr2_ctrl_get_min(hcp);
509 lmax = pvr2_ctrl_get_max(hcp);
Mike Iselye95a1912006-08-08 09:10:07 -0300510 if (w < lmin) {
511 w = lmin;
512 } else if (w > lmax) {
513 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300514 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300515 lmin = pvr2_ctrl_get_min(vcp);
516 lmax = pvr2_ctrl_get_max(vcp);
517 if (h < lmin) {
518 h = lmin;
519 } else if (h > lmax) {
520 h = lmax;
521 }
Mike Iselyd8554972006-06-26 20:58:46 -0300522
523 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
524 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300525 vf->fmt.pix.width = w;
526 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300527
528 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300529 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
530 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300531 }
532 } break;
533 case V4L2_BUF_TYPE_VBI_CAPTURE:
534 // ????? Still need to figure out to do VBI correctly
535 ret = -EINVAL;
536 break;
537 default:
538 ret = -EINVAL;
539 break;
540 }
541 break;
542 }
543
544 case VIDIOC_STREAMON:
545 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300546 if (!fh->dev_info->stream) {
547 /* No stream defined for this node. This means
548 that we're not currently allowed to stream from
549 this node. */
550 ret = -EPERM;
551 break;
552 }
Mike Iselyd8554972006-06-26 20:58:46 -0300553 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
554 if (ret < 0) return ret;
555 ret = pvr2_hdw_set_streaming(hdw,!0);
556 break;
557 }
558
559 case VIDIOC_STREAMOFF:
560 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300561 if (!fh->dev_info->stream) {
562 /* No stream defined for this node. This means
563 that we're not currently allowed to stream from
564 this node. */
565 ret = -EPERM;
566 break;
567 }
Mike Iselyd8554972006-06-26 20:58:46 -0300568 ret = pvr2_hdw_set_streaming(hdw,0);
569 break;
570 }
571
572 case VIDIOC_QUERYCTRL:
573 {
574 struct pvr2_ctrl *cptr;
575 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
576 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300577 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
578 cptr = pvr2_hdw_get_ctrl_nextv4l(
579 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
580 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
581 } else {
582 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
583 }
Mike Iselyd8554972006-06-26 20:58:46 -0300584 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300585 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300586 "QUERYCTRL id=0x%x not implemented here",
587 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300588 ret = -EINVAL;
589 break;
590 }
591
Mike Iselya761f432006-06-25 20:04:44 -0300592 pvr2_trace(PVR2_TRACE_V4LIOCTL,
593 "QUERYCTRL id=0x%x mapping name=%s (%s)",
594 vc->id,pvr2_ctrl_get_name(cptr),
595 pvr2_ctrl_get_desc(cptr));
596 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
597 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300598 vc->default_value = pvr2_ctrl_get_def(cptr);
599 switch (pvr2_ctrl_get_type(cptr)) {
600 case pvr2_ctl_enum:
601 vc->type = V4L2_CTRL_TYPE_MENU;
602 vc->minimum = 0;
603 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
604 vc->step = 1;
605 break;
Mike Isely33213962006-06-25 20:04:40 -0300606 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300607 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300608 vc->minimum = 0;
609 vc->maximum = 1;
610 vc->step = 1;
611 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300612 case pvr2_ctl_int:
613 vc->type = V4L2_CTRL_TYPE_INTEGER;
614 vc->minimum = pvr2_ctrl_get_min(cptr);
615 vc->maximum = pvr2_ctrl_get_max(cptr);
616 vc->step = 1;
617 break;
618 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300619 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300620 "QUERYCTRL id=0x%x name=%s not mappable",
621 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300622 ret = -EINVAL;
623 break;
624 }
625 break;
626 }
627
628 case VIDIOC_QUERYMENU:
629 {
630 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
631 unsigned int cnt = 0;
632 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
633 vm->index,
634 vm->name,sizeof(vm->name)-1,
635 &cnt);
636 vm->name[cnt] = 0;
637 break;
638 }
639
640 case VIDIOC_G_CTRL:
641 {
642 struct v4l2_control *vc = (struct v4l2_control *)arg;
643 int val = 0;
644 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
645 &val);
646 vc->value = val;
647 break;
648 }
649
650 case VIDIOC_S_CTRL:
651 {
652 struct v4l2_control *vc = (struct v4l2_control *)arg;
653 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
654 vc->value);
655 break;
656 }
657
Mike Isely1d9f8462006-06-25 20:04:58 -0300658 case VIDIOC_G_EXT_CTRLS:
659 {
660 struct v4l2_ext_controls *ctls =
661 (struct v4l2_ext_controls *)arg;
662 struct v4l2_ext_control *ctrl;
663 unsigned int idx;
664 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300665 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300666 for (idx = 0; idx < ctls->count; idx++) {
667 ctrl = ctls->controls + idx;
668 ret = pvr2_ctrl_get_value(
669 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
670 if (ret) {
671 ctls->error_idx = idx;
672 break;
673 }
674 /* Ensure that if read as a 64 bit value, the user
675 will still get a hopefully sane value */
676 ctrl->value64 = 0;
677 ctrl->value = val;
678 }
679 break;
680 }
681
682 case VIDIOC_S_EXT_CTRLS:
683 {
684 struct v4l2_ext_controls *ctls =
685 (struct v4l2_ext_controls *)arg;
686 struct v4l2_ext_control *ctrl;
687 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300688 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300689 for (idx = 0; idx < ctls->count; idx++) {
690 ctrl = ctls->controls + idx;
691 ret = pvr2_ctrl_set_value(
692 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
693 ctrl->value);
694 if (ret) {
695 ctls->error_idx = idx;
696 break;
697 }
698 }
699 break;
700 }
701
702 case VIDIOC_TRY_EXT_CTRLS:
703 {
704 struct v4l2_ext_controls *ctls =
705 (struct v4l2_ext_controls *)arg;
706 struct v4l2_ext_control *ctrl;
707 struct pvr2_ctrl *pctl;
708 unsigned int idx;
709 /* For the moment just validate that the requested control
710 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300711 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300712 for (idx = 0; idx < ctls->count; idx++) {
713 ctrl = ctls->controls + idx;
714 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
715 if (!pctl) {
716 ret = -EINVAL;
717 ctls->error_idx = idx;
718 break;
719 }
720 }
721 break;
722 }
723
Mike Iselyd8554972006-06-26 20:58:46 -0300724 case VIDIOC_LOG_STATUS:
725 {
Mike Iselyd8554972006-06-26 20:58:46 -0300726 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300727 ret = 0;
728 break;
729 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300730#ifdef CONFIG_VIDEO_ADV_DEBUG
731 case VIDIOC_INT_G_REGISTER:
732 case VIDIOC_INT_S_REGISTER:
733 {
734 u32 val;
735 struct v4l2_register *req = (struct v4l2_register *)arg;
736 if (cmd == VIDIOC_INT_S_REGISTER) val = req->val;
737 ret = pvr2_hdw_register_access(
738 hdw,req->i2c_id,req->reg,
739 cmd == VIDIOC_INT_S_REGISTER,&val);
Mike Isely6d988162006-09-28 17:53:49 -0300740 if (cmd == VIDIOC_INT_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300741 break;
742 }
743#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300744
745 default :
746 ret = v4l_compat_translate_ioctl(inode,file,cmd,
747 arg,pvr2_v4l2_do_ioctl);
748 }
749
750 pvr2_hdw_commit_ctl(hdw);
751
752 if (ret < 0) {
753 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300754 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300755 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
756 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300757 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
758 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300759 "pvr2_v4l2_do_ioctl failure, ret=%d"
760 " command was:",ret);
761 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
762 cmd);
763 }
764 }
765 } else {
766 pvr2_trace(PVR2_TRACE_V4LIOCTL,
767 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
768 ret,ret);
769 }
770 return ret;
771}
772
773
774static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
775{
Mike Isely0f0f2572006-12-27 23:19:42 -0300776 int minor_id = dip->devbase.minor;
Mike Isely0f0f2572006-12-27 23:19:42 -0300777 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300778 enum pvr2_config cfg = dip->config;
779 int v4l_type = dip->v4l_type;
Mike Isely0f0f2572006-12-27 23:19:42 -0300780
Mike Isely16eb40d2006-12-30 18:27:32 -0300781 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300782
783 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300784 dip->v4lp = NULL;
785 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300786
787 /* Actual deallocation happens later when all internal references
788 are gone. */
789 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300790
Mike Isely16eb40d2006-12-30 18:27:32 -0300791 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
792 get_v4l_name(v4l_type),minor_id & 0x1f,
793 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300794
Mike Iselyd8554972006-06-26 20:58:46 -0300795}
796
797
798static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
799{
Mike Isely0f0f2572006-12-27 23:19:42 -0300800 if (vp->dev_video) {
801 pvr2_v4l2_dev_destroy(vp->dev_video);
802 vp->dev_video = 0;
803 }
804 if (vp->dev_radio) {
805 pvr2_v4l2_dev_destroy(vp->dev_radio);
806 vp->dev_radio = 0;
807 }
Mike Iselyd8554972006-06-26 20:58:46 -0300808
809 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
810 pvr2_channel_done(&vp->channel);
811 kfree(vp);
812}
813
814
Mike Isely75910052006-09-23 22:30:50 -0300815static void pvr2_video_device_release(struct video_device *vdev)
816{
817 struct pvr2_v4l2_dev *dev;
818 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
819 kfree(dev);
820}
821
822
Adrian Bunk07e337e2006-06-30 11:30:20 -0300823static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300824{
825 struct pvr2_v4l2 *vp;
826 vp = container_of(chp,struct pvr2_v4l2,channel);
827 if (!vp->channel.mc_head->disconnect_flag) return;
828 if (vp->vfirst) return;
829 pvr2_v4l2_destroy_no_lock(vp);
830}
831
832
Adrian Bunk07e337e2006-06-30 11:30:20 -0300833static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
834 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300835{
836
837/* Temporary hack : use ivtv api until a v4l2 one is available. */
838#define IVTV_IOC_G_CODEC 0xFFEE7703
839#define IVTV_IOC_S_CODEC 0xFFEE7704
840 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
841 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
842}
843
844
Adrian Bunk07e337e2006-06-30 11:30:20 -0300845static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300846{
847 struct pvr2_v4l2_fh *fhp = file->private_data;
848 struct pvr2_v4l2 *vp = fhp->vhead;
849 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
Mike Iselyc74e0062006-12-30 18:31:22 -0300850 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300851
852 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
853
854 if (fhp->rhp) {
855 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300856 pvr2_hdw_set_streaming(hdw,0);
857 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300858 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300859 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300860 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300861 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300862
Mike Iselyd8554972006-06-26 20:58:46 -0300863 v4l2_prio_close(&vp->prio, &fhp->prio);
864 file->private_data = NULL;
865
866 pvr2_context_enter(mp); do {
Mike Iselyc74e0062006-12-30 18:31:22 -0300867 /* Restore the previous input selection, if it makes sense
868 to do so. */
869 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
870 struct pvr2_ctrl *cp;
871 int pval;
872 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
873 pvr2_ctrl_get_value(cp,&pval);
874 /* Only restore if we're still selecting the radio */
875 if (pval == PVR2_CVAL_INPUT_RADIO) {
876 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
877 pvr2_hdw_commit_ctl(hdw);
878 }
879 }
880
Mike Iselyd8554972006-06-26 20:58:46 -0300881 if (fhp->vnext) {
882 fhp->vnext->vprev = fhp->vprev;
883 } else {
884 vp->vlast = fhp->vprev;
885 }
886 if (fhp->vprev) {
887 fhp->vprev->vnext = fhp->vnext;
888 } else {
889 vp->vfirst = fhp->vnext;
890 }
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300891 fhp->vnext = NULL;
892 fhp->vprev = NULL;
893 fhp->vhead = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300894 pvr2_channel_done(&fhp->channel);
895 pvr2_trace(PVR2_TRACE_STRUCT,
896 "Destroying pvr_v4l2_fh id=%p",fhp);
897 kfree(fhp);
898 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
899 pvr2_v4l2_destroy_no_lock(vp);
900 }
901 } while (0); pvr2_context_exit(mp);
902 return 0;
903}
904
905
Adrian Bunk07e337e2006-06-30 11:30:20 -0300906static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300907{
Mike Isely75910052006-09-23 22:30:50 -0300908 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300909 struct pvr2_v4l2_fh *fhp;
910 struct pvr2_v4l2 *vp;
911 struct pvr2_hdw *hdw;
912
Mike Isely75910052006-09-23 22:30:50 -0300913 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300914
915 vp = dip->v4lp;
916 hdw = vp->channel.hdw;
917
918 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
919
920 if (!pvr2_hdw_dev_ok(hdw)) {
921 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
922 "pvr2_v4l2_open: hardware not ready");
923 return -EIO;
924 }
925
Mike Isely4b85dee2007-01-20 00:03:32 -0300926 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300927 if (!fhp) {
928 return -ENOMEM;
929 }
Mike Iselyd8554972006-06-26 20:58:46 -0300930
931 init_waitqueue_head(&fhp->wait_data);
932 fhp->dev_info = dip;
933
934 pvr2_context_enter(vp->channel.mc_head); do {
935 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
936 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300937
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300938 fhp->vnext = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300939 fhp->vprev = vp->vlast;
940 if (vp->vlast) {
941 vp->vlast->vnext = fhp;
942 } else {
943 vp->vfirst = fhp;
944 }
945 vp->vlast = fhp;
946 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300947
948 /* Opening the /dev/radioX device implies a mode switch.
949 So execute that here. Note that you can get the
950 IDENTICAL effect merely by opening the normal video
951 device and setting the input appropriately. */
952 if (dip->v4l_type == VFL_TYPE_RADIO) {
953 struct pvr2_ctrl *cp;
954 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
955 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
956 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
957 pvr2_hdw_commit_ctl(hdw);
958 }
Mike Iselyd8554972006-06-26 20:58:46 -0300959 } while (0); pvr2_context_exit(vp->channel.mc_head);
960
961 fhp->file = file;
962 file->private_data = fhp;
963 v4l2_prio_open(&vp->prio,&fhp->prio);
964
965 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
966
967 return 0;
968}
969
970
971static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
972{
973 wake_up(&fhp->wait_data);
974}
975
976static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
977{
978 int ret;
979 struct pvr2_stream *sp;
980 struct pvr2_hdw *hdw;
981 if (fh->rhp) return 0;
982
Mike Isely16eb40d2006-12-30 18:27:32 -0300983 if (!fh->dev_info->stream) {
984 /* No stream defined for this node. This means that we're
985 not currently allowed to stream from this node. */
986 return -EPERM;
987 }
988
Mike Iselyd8554972006-06-26 20:58:46 -0300989 /* First read() attempt. Try to claim the stream and start
990 it... */
991 if ((ret = pvr2_channel_claim_stream(&fh->channel,
992 fh->dev_info->stream)) != 0) {
993 /* Someone else must already have it */
994 return ret;
995 }
996
997 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
998 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300999 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001000 return -ENOMEM;
1001 }
1002
1003 hdw = fh->channel.mc_head->hdw;
1004 sp = fh->dev_info->stream->stream;
1005 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1006 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
1007 pvr2_hdw_set_streaming(hdw,!0);
1008 ret = pvr2_ioread_set_enabled(fh->rhp,!0);
1009
1010 return ret;
1011}
1012
1013
1014static ssize_t pvr2_v4l2_read(struct file *file,
1015 char __user *buff, size_t count, loff_t *ppos)
1016{
1017 struct pvr2_v4l2_fh *fh = file->private_data;
1018 int ret;
1019
1020 if (fh->fw_mode_flag) {
1021 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1022 char *tbuf;
1023 int c1,c2;
1024 int tcnt = 0;
1025 unsigned int offs = *ppos;
1026
1027 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1028 if (!tbuf) return -ENOMEM;
1029
1030 while (count) {
1031 c1 = count;
1032 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1033 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1034 if (c2 < 0) {
1035 tcnt = c2;
1036 break;
1037 }
1038 if (!c2) break;
1039 if (copy_to_user(buff,tbuf,c2)) {
1040 tcnt = -EFAULT;
1041 break;
1042 }
1043 offs += c2;
1044 tcnt += c2;
1045 buff += c2;
1046 count -= c2;
1047 *ppos += c2;
1048 }
1049 kfree(tbuf);
1050 return tcnt;
1051 }
1052
1053 if (!fh->rhp) {
1054 ret = pvr2_v4l2_iosetup(fh);
1055 if (ret) {
1056 return ret;
1057 }
1058 }
1059
1060 for (;;) {
1061 ret = pvr2_ioread_read(fh->rhp,buff,count);
1062 if (ret >= 0) break;
1063 if (ret != -EAGAIN) break;
1064 if (file->f_flags & O_NONBLOCK) break;
1065 /* Doing blocking I/O. Wait here. */
1066 ret = wait_event_interruptible(
1067 fh->wait_data,
1068 pvr2_ioread_avail(fh->rhp) >= 0);
1069 if (ret < 0) break;
1070 }
1071
1072 return ret;
1073}
1074
1075
1076static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1077{
1078 unsigned int mask = 0;
1079 struct pvr2_v4l2_fh *fh = file->private_data;
1080 int ret;
1081
1082 if (fh->fw_mode_flag) {
1083 mask |= POLLIN | POLLRDNORM;
1084 return mask;
1085 }
1086
1087 if (!fh->rhp) {
1088 ret = pvr2_v4l2_iosetup(fh);
1089 if (ret) return POLLERR;
1090 }
1091
1092 poll_wait(file,&fh->wait_data,wait);
1093
1094 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1095 mask |= POLLIN | POLLRDNORM;
1096 }
1097
1098 return mask;
1099}
1100
1101
Arjan van de Venfa027c22007-02-12 00:55:33 -08001102static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001103 .owner = THIS_MODULE,
1104 .open = pvr2_v4l2_open,
1105 .release = pvr2_v4l2_release,
1106 .read = pvr2_v4l2_read,
1107 .ioctl = pvr2_v4l2_ioctl,
1108 .llseek = no_llseek,
1109 .poll = pvr2_v4l2_poll,
1110};
1111
1112
1113#define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */
1114
1115static struct video_device vdev_template = {
1116 .owner = THIS_MODULE,
1117 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1118 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1119 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1120 | V4L2_CAP_READWRITE),
1121 .hardware = VID_HARDWARE_PVRUSB2,
1122 .fops = &vdev_fops,
1123};
1124
1125
1126static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1127 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001128 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001129{
1130 int mindevnum;
1131 int unit_number;
Mike Isely16eb40d2006-12-30 18:27:32 -03001132 int *nr_ptr = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001133 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001134
1135
Mike Isely16eb40d2006-12-30 18:27:32 -03001136 dip->v4l_type = v4l_type;
1137 switch (v4l_type) {
1138 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001139 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001140 dip->config = pvr2_config_mpeg;
1141 dip->minor_type = pvr2_v4l_type_video;
1142 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001143 if (!dip->stream) {
1144 err("Failed to set up pvrusb2 v4l video dev"
1145 " due to missing stream instance");
1146 return;
1147 }
Mike Iselyd8554972006-06-26 20:58:46 -03001148 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001149 case VFL_TYPE_VBI:
1150 dip->config = pvr2_config_vbi;
1151 dip->minor_type = pvr2_v4l_type_vbi;
1152 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001153 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001154 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001155 dip->stream = &vp->channel.mc_head->video_stream;
1156 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001157 dip->minor_type = pvr2_v4l_type_radio;
1158 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001159 break;
1160 default:
1161 /* Bail out (this should be impossible) */
1162 err("Failed to set up pvrusb2 v4l dev"
1163 " due to unrecognized config");
1164 return;
1165 }
1166
Mike Isely75910052006-09-23 22:30:50 -03001167 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1168 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001169
1170 mindevnum = -1;
1171 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001172 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1173 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001174 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001175 if ((video_register_device(&dip->devbase,
1176 dip->v4l_type, mindevnum) < 0) &&
1177 (video_register_device(&dip->devbase,
1178 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001179 err("Failed to register pvrusb2 v4l device");
1180 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001181
1182 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1183 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1184 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001185
Mike Iselyd8554972006-06-26 20:58:46 -03001186 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001187 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001188}
1189
1190
1191struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1192{
1193 struct pvr2_v4l2 *vp;
1194
Mike Isely4b85dee2007-01-20 00:03:32 -03001195 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001196 if (!vp) return vp;
Mike Isely4b85dee2007-01-20 00:03:32 -03001197 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1198 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
Mike Isely0f0f2572006-12-27 23:19:42 -03001199 if (!(vp->dev_video && vp->dev_radio)) {
Mike Isely6710fb82007-01-20 00:02:26 -03001200 kfree(vp->dev_video);
1201 kfree(vp->dev_radio);
Mike Isely75910052006-09-23 22:30:50 -03001202 kfree(vp);
Randy Dunlapc2625bf2006-10-29 11:12:27 -03001203 return NULL;
Mike Isely75910052006-09-23 22:30:50 -03001204 }
Mike Iselyd8554972006-06-26 20:58:46 -03001205 pvr2_channel_init(&vp->channel,mnp);
1206 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1207
1208 vp->channel.check_func = pvr2_v4l2_internal_check;
1209
1210 /* register streams */
Mike Isely16eb40d2006-12-30 18:27:32 -03001211 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1212 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
Mike Iselyd8554972006-06-26 20:58:46 -03001213
1214 return vp;
1215}
1216
1217/*
1218 Stuff for Emacs to see, in order to encourage consistent editing style:
1219 *** Local Variables: ***
1220 *** mode: c ***
1221 *** fill-column: 75 ***
1222 *** tab-width: 8 ***
1223 *** c-basic-offset: 8 ***
1224 *** End: ***
1225 */