blob: cde5f5f3e8f2dab131a3e9454647d32ef02ac6af [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;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300368
369 if (vt->index != 0)
370 break;
371
Mike Isely18103c52007-01-20 00:09:47 -0300372 pvr2_hdw_execute_tuner_poll(hdw);
373 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300374 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);
Mike Isely11fc76c2007-01-20 00:24:52 -0300387 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300388 }
389
390 case VIDIOC_S_FREQUENCY:
391 {
392 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300393 unsigned long fv;
Mike Isely18103c52007-01-20 00:09:47 -0300394 struct v4l2_tuner vt;
395 int cur_input;
396 struct pvr2_ctrl *ctrlp;
397 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
398 if (ret != 0) break;
399 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
400 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
401 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300402 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c52007-01-20 00:09:47 -0300403 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
404 pvr2_ctrl_set_value(ctrlp,
405 PVR2_CVAL_INPUT_RADIO);
406 }
407 } else {
408 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
409 pvr2_ctrl_set_value(ctrlp,
410 PVR2_CVAL_INPUT_TV);
411 }
412 }
413 fv = vf->frequency;
414 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300415 fv = (fv * 125) / 2;
416 } else {
417 fv = fv * 62500;
418 }
Mike Iselyd8554972006-06-26 20:58:46 -0300419 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300420 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300421 break;
422 }
423
424 case VIDIOC_G_FREQUENCY:
425 {
426 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
427 int val = 0;
Mike Isely18103c52007-01-20 00:09:47 -0300428 int cur_input;
429 struct v4l2_tuner vt;
430 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
431 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300432 ret = pvr2_ctrl_get_value(
433 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
434 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300435 if (ret != 0) break;
436 pvr2_ctrl_get_value(
437 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
438 &cur_input);
439 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300440 vf->type = V4L2_TUNER_RADIO;
441 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300442 vf->type = V4L2_TUNER_ANALOG_TV;
443 }
Mike Isely18103c52007-01-20 00:09:47 -0300444 if (vt.capability & V4L2_TUNER_CAP_LOW) {
445 val = (val * 2) / 125;
446 } else {
447 val /= 62500;
448 }
449 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300450 break;
451 }
452
453 case VIDIOC_ENUM_FMT:
454 {
455 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
456
457 /* Only one format is supported : mpeg.*/
458 if (fd->index != 0)
459 break;
460
461 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
462 ret = 0;
463 break;
464 }
465
466 case VIDIOC_G_FMT:
467 {
468 struct v4l2_format *vf = (struct v4l2_format *)arg;
469 int val;
470 switch(vf->type) {
471 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
472 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
473 sizeof(struct v4l2_format));
474 val = 0;
475 pvr2_ctrl_get_value(
476 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
477 &val);
478 vf->fmt.pix.width = val;
479 val = 0;
480 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300481 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
482 &val);
483 vf->fmt.pix.height = val;
484 ret = 0;
485 break;
486 case V4L2_BUF_TYPE_VBI_CAPTURE:
487 // ????? Still need to figure out to do VBI correctly
488 ret = -EINVAL;
489 break;
490 default:
491 ret = -EINVAL;
492 break;
493 }
494 break;
495 }
496
497 case VIDIOC_TRY_FMT:
498 case VIDIOC_S_FMT:
499 {
500 struct v4l2_format *vf = (struct v4l2_format *)arg;
501
502 ret = 0;
503 switch(vf->type) {
504 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300505 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300506 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300507 int h = vf->fmt.pix.height;
508 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300509 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
510 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300511
Mike Iselye95a1912006-08-08 09:10:07 -0300512 lmin = pvr2_ctrl_get_min(hcp);
513 lmax = pvr2_ctrl_get_max(hcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300514 ldef = pvr2_ctrl_get_def(hcp);
515 if (w == -1) {
516 w = ldef;
517 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300518 w = lmin;
519 } else if (w > lmax) {
520 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300521 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300522 lmin = pvr2_ctrl_get_min(vcp);
523 lmax = pvr2_ctrl_get_max(vcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300524 ldef = pvr2_ctrl_get_def(vcp);
525 if (h == -1) {
526 h = ldef;
527 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300528 h = lmin;
529 } else if (h > lmax) {
530 h = lmax;
531 }
Mike Iselyd8554972006-06-26 20:58:46 -0300532
533 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
534 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300535 vf->fmt.pix.width = w;
536 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300537
538 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300539 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
540 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300541 }
542 } break;
543 case V4L2_BUF_TYPE_VBI_CAPTURE:
544 // ????? Still need to figure out to do VBI correctly
545 ret = -EINVAL;
546 break;
547 default:
548 ret = -EINVAL;
549 break;
550 }
551 break;
552 }
553
554 case VIDIOC_STREAMON:
555 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300556 if (!fh->dev_info->stream) {
557 /* No stream defined for this node. This means
558 that we're not currently allowed to stream from
559 this node. */
560 ret = -EPERM;
561 break;
562 }
Mike Iselyd8554972006-06-26 20:58:46 -0300563 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
564 if (ret < 0) return ret;
565 ret = pvr2_hdw_set_streaming(hdw,!0);
566 break;
567 }
568
569 case VIDIOC_STREAMOFF:
570 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300571 if (!fh->dev_info->stream) {
572 /* No stream defined for this node. This means
573 that we're not currently allowed to stream from
574 this node. */
575 ret = -EPERM;
576 break;
577 }
Mike Iselyd8554972006-06-26 20:58:46 -0300578 ret = pvr2_hdw_set_streaming(hdw,0);
579 break;
580 }
581
582 case VIDIOC_QUERYCTRL:
583 {
584 struct pvr2_ctrl *cptr;
585 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
586 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300587 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
588 cptr = pvr2_hdw_get_ctrl_nextv4l(
589 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
590 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
591 } else {
592 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
593 }
Mike Iselyd8554972006-06-26 20:58:46 -0300594 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300595 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300596 "QUERYCTRL id=0x%x not implemented here",
597 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300598 ret = -EINVAL;
599 break;
600 }
601
Mike Iselya761f432006-06-25 20:04:44 -0300602 pvr2_trace(PVR2_TRACE_V4LIOCTL,
603 "QUERYCTRL id=0x%x mapping name=%s (%s)",
604 vc->id,pvr2_ctrl_get_name(cptr),
605 pvr2_ctrl_get_desc(cptr));
606 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
607 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300608 vc->default_value = pvr2_ctrl_get_def(cptr);
609 switch (pvr2_ctrl_get_type(cptr)) {
610 case pvr2_ctl_enum:
611 vc->type = V4L2_CTRL_TYPE_MENU;
612 vc->minimum = 0;
613 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
614 vc->step = 1;
615 break;
Mike Isely33213962006-06-25 20:04:40 -0300616 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300617 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300618 vc->minimum = 0;
619 vc->maximum = 1;
620 vc->step = 1;
621 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300622 case pvr2_ctl_int:
623 vc->type = V4L2_CTRL_TYPE_INTEGER;
624 vc->minimum = pvr2_ctrl_get_min(cptr);
625 vc->maximum = pvr2_ctrl_get_max(cptr);
626 vc->step = 1;
627 break;
628 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300629 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300630 "QUERYCTRL id=0x%x name=%s not mappable",
631 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300632 ret = -EINVAL;
633 break;
634 }
635 break;
636 }
637
638 case VIDIOC_QUERYMENU:
639 {
640 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
641 unsigned int cnt = 0;
642 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
643 vm->index,
644 vm->name,sizeof(vm->name)-1,
645 &cnt);
646 vm->name[cnt] = 0;
647 break;
648 }
649
650 case VIDIOC_G_CTRL:
651 {
652 struct v4l2_control *vc = (struct v4l2_control *)arg;
653 int val = 0;
654 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
655 &val);
656 vc->value = val;
657 break;
658 }
659
660 case VIDIOC_S_CTRL:
661 {
662 struct v4l2_control *vc = (struct v4l2_control *)arg;
663 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
664 vc->value);
665 break;
666 }
667
Mike Isely1d9f8462006-06-25 20:04:58 -0300668 case VIDIOC_G_EXT_CTRLS:
669 {
670 struct v4l2_ext_controls *ctls =
671 (struct v4l2_ext_controls *)arg;
672 struct v4l2_ext_control *ctrl;
673 unsigned int idx;
674 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300675 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300676 for (idx = 0; idx < ctls->count; idx++) {
677 ctrl = ctls->controls + idx;
678 ret = pvr2_ctrl_get_value(
679 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
680 if (ret) {
681 ctls->error_idx = idx;
682 break;
683 }
684 /* Ensure that if read as a 64 bit value, the user
685 will still get a hopefully sane value */
686 ctrl->value64 = 0;
687 ctrl->value = val;
688 }
689 break;
690 }
691
692 case VIDIOC_S_EXT_CTRLS:
693 {
694 struct v4l2_ext_controls *ctls =
695 (struct v4l2_ext_controls *)arg;
696 struct v4l2_ext_control *ctrl;
697 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300698 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300699 for (idx = 0; idx < ctls->count; idx++) {
700 ctrl = ctls->controls + idx;
701 ret = pvr2_ctrl_set_value(
702 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
703 ctrl->value);
704 if (ret) {
705 ctls->error_idx = idx;
706 break;
707 }
708 }
709 break;
710 }
711
712 case VIDIOC_TRY_EXT_CTRLS:
713 {
714 struct v4l2_ext_controls *ctls =
715 (struct v4l2_ext_controls *)arg;
716 struct v4l2_ext_control *ctrl;
717 struct pvr2_ctrl *pctl;
718 unsigned int idx;
719 /* For the moment just validate that the requested control
720 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300721 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300722 for (idx = 0; idx < ctls->count; idx++) {
723 ctrl = ctls->controls + idx;
724 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
725 if (!pctl) {
726 ret = -EINVAL;
727 ctls->error_idx = idx;
728 break;
729 }
730 }
731 break;
732 }
733
Mike Iselyd8554972006-06-26 20:58:46 -0300734 case VIDIOC_LOG_STATUS:
735 {
Mike Iselyd8554972006-06-26 20:58:46 -0300736 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300737 ret = 0;
738 break;
739 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300740#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300741 case VIDIOC_DBG_S_REGISTER:
742 if (!capable(CAP_SYS_ADMIN)) {
743 ret = -EPERM;
744 break;
745 } /* fall through */
746 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300747 {
748 u32 val;
749 struct v4l2_register *req = (struct v4l2_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300750 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300751 ret = pvr2_hdw_register_access(
752 hdw,req->i2c_id,req->reg,
Trent Piepho52ebc762007-01-23 22:38:13 -0300753 cmd == VIDIOC_DBG_S_REGISTER,&val);
754 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300755 break;
756 }
757#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300758
759 default :
760 ret = v4l_compat_translate_ioctl(inode,file,cmd,
761 arg,pvr2_v4l2_do_ioctl);
762 }
763
764 pvr2_hdw_commit_ctl(hdw);
765
766 if (ret < 0) {
767 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300768 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300769 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
770 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300771 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
772 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300773 "pvr2_v4l2_do_ioctl failure, ret=%d"
774 " command was:",ret);
775 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
776 cmd);
777 }
778 }
779 } else {
780 pvr2_trace(PVR2_TRACE_V4LIOCTL,
781 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
782 ret,ret);
783 }
784 return ret;
785}
786
787
788static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
789{
Mike Isely0f0f2572006-12-27 23:19:42 -0300790 int minor_id = dip->devbase.minor;
Mike Isely0f0f2572006-12-27 23:19:42 -0300791 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300792 enum pvr2_config cfg = dip->config;
793 int v4l_type = dip->v4l_type;
Mike Isely0f0f2572006-12-27 23:19:42 -0300794
Mike Isely16eb40d2006-12-30 18:27:32 -0300795 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300796
797 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300798 dip->v4lp = NULL;
799 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300800
801 /* Actual deallocation happens later when all internal references
802 are gone. */
803 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300804
Mike Isely16eb40d2006-12-30 18:27:32 -0300805 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
806 get_v4l_name(v4l_type),minor_id & 0x1f,
807 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300808
Mike Iselyd8554972006-06-26 20:58:46 -0300809}
810
811
812static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
813{
Mike Isely0f0f2572006-12-27 23:19:42 -0300814 if (vp->dev_video) {
815 pvr2_v4l2_dev_destroy(vp->dev_video);
816 vp->dev_video = 0;
817 }
818 if (vp->dev_radio) {
819 pvr2_v4l2_dev_destroy(vp->dev_radio);
820 vp->dev_radio = 0;
821 }
Mike Iselyd8554972006-06-26 20:58:46 -0300822
823 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
824 pvr2_channel_done(&vp->channel);
825 kfree(vp);
826}
827
828
Mike Isely75910052006-09-23 22:30:50 -0300829static void pvr2_video_device_release(struct video_device *vdev)
830{
831 struct pvr2_v4l2_dev *dev;
832 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
833 kfree(dev);
834}
835
836
Adrian Bunk07e337e2006-06-30 11:30:20 -0300837static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300838{
839 struct pvr2_v4l2 *vp;
840 vp = container_of(chp,struct pvr2_v4l2,channel);
841 if (!vp->channel.mc_head->disconnect_flag) return;
842 if (vp->vfirst) return;
843 pvr2_v4l2_destroy_no_lock(vp);
844}
845
846
Adrian Bunk07e337e2006-06-30 11:30:20 -0300847static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
848 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300849{
850
851/* Temporary hack : use ivtv api until a v4l2 one is available. */
852#define IVTV_IOC_G_CODEC 0xFFEE7703
853#define IVTV_IOC_S_CODEC 0xFFEE7704
854 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
855 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
856}
857
858
Adrian Bunk07e337e2006-06-30 11:30:20 -0300859static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300860{
861 struct pvr2_v4l2_fh *fhp = file->private_data;
862 struct pvr2_v4l2 *vp = fhp->vhead;
863 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
Mike Iselyc74e0062006-12-30 18:31:22 -0300864 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300865
866 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
867
868 if (fhp->rhp) {
869 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300870 pvr2_hdw_set_streaming(hdw,0);
871 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300872 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300873 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300874 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300875 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300876
Mike Iselyd8554972006-06-26 20:58:46 -0300877 v4l2_prio_close(&vp->prio, &fhp->prio);
878 file->private_data = NULL;
879
880 pvr2_context_enter(mp); do {
Mike Iselyc74e0062006-12-30 18:31:22 -0300881 /* Restore the previous input selection, if it makes sense
882 to do so. */
883 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
884 struct pvr2_ctrl *cp;
885 int pval;
886 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
887 pvr2_ctrl_get_value(cp,&pval);
888 /* Only restore if we're still selecting the radio */
889 if (pval == PVR2_CVAL_INPUT_RADIO) {
890 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
891 pvr2_hdw_commit_ctl(hdw);
892 }
893 }
894
Mike Iselyd8554972006-06-26 20:58:46 -0300895 if (fhp->vnext) {
896 fhp->vnext->vprev = fhp->vprev;
897 } else {
898 vp->vlast = fhp->vprev;
899 }
900 if (fhp->vprev) {
901 fhp->vprev->vnext = fhp->vnext;
902 } else {
903 vp->vfirst = fhp->vnext;
904 }
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300905 fhp->vnext = NULL;
906 fhp->vprev = NULL;
907 fhp->vhead = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300908 pvr2_channel_done(&fhp->channel);
909 pvr2_trace(PVR2_TRACE_STRUCT,
910 "Destroying pvr_v4l2_fh id=%p",fhp);
911 kfree(fhp);
912 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
913 pvr2_v4l2_destroy_no_lock(vp);
914 }
915 } while (0); pvr2_context_exit(mp);
916 return 0;
917}
918
919
Adrian Bunk07e337e2006-06-30 11:30:20 -0300920static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300921{
Mike Isely75910052006-09-23 22:30:50 -0300922 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300923 struct pvr2_v4l2_fh *fhp;
924 struct pvr2_v4l2 *vp;
925 struct pvr2_hdw *hdw;
926
Mike Isely75910052006-09-23 22:30:50 -0300927 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300928
929 vp = dip->v4lp;
930 hdw = vp->channel.hdw;
931
932 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
933
934 if (!pvr2_hdw_dev_ok(hdw)) {
935 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
936 "pvr2_v4l2_open: hardware not ready");
937 return -EIO;
938 }
939
Mike Isely4b85dee2007-01-20 00:03:32 -0300940 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300941 if (!fhp) {
942 return -ENOMEM;
943 }
Mike Iselyd8554972006-06-26 20:58:46 -0300944
945 init_waitqueue_head(&fhp->wait_data);
946 fhp->dev_info = dip;
947
948 pvr2_context_enter(vp->channel.mc_head); do {
949 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
950 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300951
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300952 fhp->vnext = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300953 fhp->vprev = vp->vlast;
954 if (vp->vlast) {
955 vp->vlast->vnext = fhp;
956 } else {
957 vp->vfirst = fhp;
958 }
959 vp->vlast = fhp;
960 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300961
962 /* Opening the /dev/radioX device implies a mode switch.
963 So execute that here. Note that you can get the
964 IDENTICAL effect merely by opening the normal video
965 device and setting the input appropriately. */
966 if (dip->v4l_type == VFL_TYPE_RADIO) {
967 struct pvr2_ctrl *cp;
968 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
969 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
970 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
971 pvr2_hdw_commit_ctl(hdw);
972 }
Mike Iselyd8554972006-06-26 20:58:46 -0300973 } while (0); pvr2_context_exit(vp->channel.mc_head);
974
975 fhp->file = file;
976 file->private_data = fhp;
977 v4l2_prio_open(&vp->prio,&fhp->prio);
978
979 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
980
981 return 0;
982}
983
984
985static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
986{
987 wake_up(&fhp->wait_data);
988}
989
990static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
991{
992 int ret;
993 struct pvr2_stream *sp;
994 struct pvr2_hdw *hdw;
995 if (fh->rhp) return 0;
996
Mike Isely16eb40d2006-12-30 18:27:32 -0300997 if (!fh->dev_info->stream) {
998 /* No stream defined for this node. This means that we're
999 not currently allowed to stream from this node. */
1000 return -EPERM;
1001 }
1002
Mike Iselyd8554972006-06-26 20:58:46 -03001003 /* First read() attempt. Try to claim the stream and start
1004 it... */
1005 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1006 fh->dev_info->stream)) != 0) {
1007 /* Someone else must already have it */
1008 return ret;
1009 }
1010
1011 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1012 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001013 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001014 return -ENOMEM;
1015 }
1016
1017 hdw = fh->channel.mc_head->hdw;
1018 sp = fh->dev_info->stream->stream;
1019 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1020 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
1021 pvr2_hdw_set_streaming(hdw,!0);
1022 ret = pvr2_ioread_set_enabled(fh->rhp,!0);
1023
1024 return ret;
1025}
1026
1027
1028static ssize_t pvr2_v4l2_read(struct file *file,
1029 char __user *buff, size_t count, loff_t *ppos)
1030{
1031 struct pvr2_v4l2_fh *fh = file->private_data;
1032 int ret;
1033
1034 if (fh->fw_mode_flag) {
1035 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1036 char *tbuf;
1037 int c1,c2;
1038 int tcnt = 0;
1039 unsigned int offs = *ppos;
1040
1041 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1042 if (!tbuf) return -ENOMEM;
1043
1044 while (count) {
1045 c1 = count;
1046 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1047 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1048 if (c2 < 0) {
1049 tcnt = c2;
1050 break;
1051 }
1052 if (!c2) break;
1053 if (copy_to_user(buff,tbuf,c2)) {
1054 tcnt = -EFAULT;
1055 break;
1056 }
1057 offs += c2;
1058 tcnt += c2;
1059 buff += c2;
1060 count -= c2;
1061 *ppos += c2;
1062 }
1063 kfree(tbuf);
1064 return tcnt;
1065 }
1066
1067 if (!fh->rhp) {
1068 ret = pvr2_v4l2_iosetup(fh);
1069 if (ret) {
1070 return ret;
1071 }
1072 }
1073
1074 for (;;) {
1075 ret = pvr2_ioread_read(fh->rhp,buff,count);
1076 if (ret >= 0) break;
1077 if (ret != -EAGAIN) break;
1078 if (file->f_flags & O_NONBLOCK) break;
1079 /* Doing blocking I/O. Wait here. */
1080 ret = wait_event_interruptible(
1081 fh->wait_data,
1082 pvr2_ioread_avail(fh->rhp) >= 0);
1083 if (ret < 0) break;
1084 }
1085
1086 return ret;
1087}
1088
1089
1090static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1091{
1092 unsigned int mask = 0;
1093 struct pvr2_v4l2_fh *fh = file->private_data;
1094 int ret;
1095
1096 if (fh->fw_mode_flag) {
1097 mask |= POLLIN | POLLRDNORM;
1098 return mask;
1099 }
1100
1101 if (!fh->rhp) {
1102 ret = pvr2_v4l2_iosetup(fh);
1103 if (ret) return POLLERR;
1104 }
1105
1106 poll_wait(file,&fh->wait_data,wait);
1107
1108 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1109 mask |= POLLIN | POLLRDNORM;
1110 }
1111
1112 return mask;
1113}
1114
1115
Arjan van de Venfa027c22007-02-12 00:55:33 -08001116static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001117 .owner = THIS_MODULE,
1118 .open = pvr2_v4l2_open,
1119 .release = pvr2_v4l2_release,
1120 .read = pvr2_v4l2_read,
1121 .ioctl = pvr2_v4l2_ioctl,
1122 .llseek = no_llseek,
1123 .poll = pvr2_v4l2_poll,
1124};
1125
1126
1127#define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */
1128
1129static struct video_device vdev_template = {
1130 .owner = THIS_MODULE,
1131 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1132 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1133 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1134 | V4L2_CAP_READWRITE),
1135 .hardware = VID_HARDWARE_PVRUSB2,
1136 .fops = &vdev_fops,
1137};
1138
1139
1140static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1141 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001142 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001143{
1144 int mindevnum;
1145 int unit_number;
Mike Isely16eb40d2006-12-30 18:27:32 -03001146 int *nr_ptr = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001147 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001148
1149
Mike Isely16eb40d2006-12-30 18:27:32 -03001150 dip->v4l_type = v4l_type;
1151 switch (v4l_type) {
1152 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001153 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001154 dip->config = pvr2_config_mpeg;
1155 dip->minor_type = pvr2_v4l_type_video;
1156 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001157 if (!dip->stream) {
1158 err("Failed to set up pvrusb2 v4l video dev"
1159 " due to missing stream instance");
1160 return;
1161 }
Mike Iselyd8554972006-06-26 20:58:46 -03001162 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001163 case VFL_TYPE_VBI:
1164 dip->config = pvr2_config_vbi;
1165 dip->minor_type = pvr2_v4l_type_vbi;
1166 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001167 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001168 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001169 dip->stream = &vp->channel.mc_head->video_stream;
1170 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001171 dip->minor_type = pvr2_v4l_type_radio;
1172 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001173 break;
1174 default:
1175 /* Bail out (this should be impossible) */
1176 err("Failed to set up pvrusb2 v4l dev"
1177 " due to unrecognized config");
1178 return;
1179 }
1180
Mike Isely75910052006-09-23 22:30:50 -03001181 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1182 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001183
1184 mindevnum = -1;
1185 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001186 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1187 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001188 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001189 if ((video_register_device(&dip->devbase,
1190 dip->v4l_type, mindevnum) < 0) &&
1191 (video_register_device(&dip->devbase,
1192 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001193 err("Failed to register pvrusb2 v4l device");
1194 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001195
1196 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1197 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1198 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001199
Mike Iselyd8554972006-06-26 20:58:46 -03001200 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001201 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001202}
1203
1204
1205struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1206{
1207 struct pvr2_v4l2 *vp;
1208
Mike Isely4b85dee2007-01-20 00:03:32 -03001209 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001210 if (!vp) return vp;
Mike Isely4b85dee2007-01-20 00:03:32 -03001211 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1212 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
Mike Isely0f0f2572006-12-27 23:19:42 -03001213 if (!(vp->dev_video && vp->dev_radio)) {
Mike Isely6710fb82007-01-20 00:02:26 -03001214 kfree(vp->dev_video);
1215 kfree(vp->dev_radio);
Mike Isely75910052006-09-23 22:30:50 -03001216 kfree(vp);
Randy Dunlapc2625bf2006-10-29 11:12:27 -03001217 return NULL;
Mike Isely75910052006-09-23 22:30:50 -03001218 }
Mike Iselyd8554972006-06-26 20:58:46 -03001219 pvr2_channel_init(&vp->channel,mnp);
1220 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1221
1222 vp->channel.check_func = pvr2_v4l2_internal_check;
1223
1224 /* register streams */
Mike Isely16eb40d2006-12-30 18:27:32 -03001225 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1226 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
Mike Iselyd8554972006-06-26 20:58:46 -03001227
1228 return vp;
1229}
1230
1231/*
1232 Stuff for Emacs to see, in order to encourage consistent editing style:
1233 *** Local Variables: ***
1234 *** mode: c ***
1235 *** fill-column: 75 ***
1236 *** tab-width: 8 ***
1237 *** c-basic-offset: 8 ***
1238 *** End: ***
1239 */