blob: 8f0587ebd4bd8609b4e97f785f3641f176b01344 [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));
Mike Isely31a18542007-04-08 01:11:47 -0300206 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
207 sizeof(cap->bus_info));
Mike Isely78a47102007-11-26 01:58:20 -0300208 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
Mike Iselyd8554972006-06-26 20:58:46 -0300209
210 ret = 0;
211 break;
212 }
213
214 case VIDIOC_G_PRIORITY:
215 {
216 enum v4l2_priority *p = arg;
217
218 *p = v4l2_prio_max(&vp->prio);
219 ret = 0;
220 break;
221 }
222
223 case VIDIOC_S_PRIORITY:
224 {
225 enum v4l2_priority *prio = arg;
226
227 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
228 break;
229 }
230
231 case VIDIOC_ENUMSTD:
232 {
233 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
234 int idx = vs->index;
235 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
236 break;
237 }
238
239 case VIDIOC_G_STD:
240 {
241 int val = 0;
242 ret = pvr2_ctrl_get_value(
243 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
244 *(v4l2_std_id *)arg = val;
245 break;
246 }
247
248 case VIDIOC_S_STD:
249 {
250 ret = pvr2_ctrl_set_value(
251 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
252 *(v4l2_std_id *)arg);
253 break;
254 }
255
256 case VIDIOC_ENUMINPUT:
257 {
258 struct pvr2_ctrl *cptr;
259 struct v4l2_input *vi = (struct v4l2_input *)arg;
260 struct v4l2_input tmp;
261 unsigned int cnt;
262
263 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
264
265 memset(&tmp,0,sizeof(tmp));
266 tmp.index = vi->index;
267 ret = 0;
268 switch (vi->index) {
269 case PVR2_CVAL_INPUT_TV:
270 case PVR2_CVAL_INPUT_RADIO:
271 tmp.type = V4L2_INPUT_TYPE_TUNER;
272 break;
273 case PVR2_CVAL_INPUT_SVIDEO:
274 case PVR2_CVAL_INPUT_COMPOSITE:
275 tmp.type = V4L2_INPUT_TYPE_CAMERA;
276 break;
277 default:
278 ret = -EINVAL;
279 break;
280 }
281 if (ret < 0) break;
282
283 cnt = 0;
284 pvr2_ctrl_get_valname(cptr,vi->index,
285 tmp.name,sizeof(tmp.name)-1,&cnt);
286 tmp.name[cnt] = 0;
287
288 /* Don't bother with audioset, since this driver currently
289 always switches the audio whenever the video is
290 switched. */
291
292 /* Handling std is a tougher problem. It doesn't make
293 sense in cases where a device might be multi-standard.
294 We could just copy out the current value for the
295 standard, but it can change over time. For now just
296 leave it zero. */
297
298 memcpy(vi, &tmp, sizeof(tmp));
299
300 ret = 0;
301 break;
302 }
303
304 case VIDIOC_G_INPUT:
305 {
306 struct pvr2_ctrl *cptr;
307 struct v4l2_input *vi = (struct v4l2_input *)arg;
308 int val;
309 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
310 val = 0;
311 ret = pvr2_ctrl_get_value(cptr,&val);
312 vi->index = val;
313 break;
314 }
315
316 case VIDIOC_S_INPUT:
317 {
318 struct v4l2_input *vi = (struct v4l2_input *)arg;
319 ret = pvr2_ctrl_set_value(
320 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
321 vi->index);
322 break;
323 }
324
325 case VIDIOC_ENUMAUDIO:
326 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300327 /* pkt: FIXME: We are returning one "fake" input here
328 which could very well be called "whatever_we_like".
329 This is for apps that want to see an audio input
330 just to feel comfortable, as well as to test if
331 it can do stereo or sth. There is actually no guarantee
332 that the actual audio input cannot change behind the app's
333 back, but most applications should not mind that either.
334
335 Hopefully, mplayer people will work with us on this (this
336 whole mess is to support mplayer pvr://), or Hans will come
337 up with a more standard way to say "we have inputs but we
338 don 't want you to change them independent of video" which
339 will sort this mess.
340 */
341 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300342 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300343 if (vin->index > 0) break;
344 strncpy(vin->name, "PVRUSB2 Audio",14);
345 vin->capability = V4L2_AUDCAP_STEREO;
346 ret = 0;
347 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300348 break;
349 }
350
351 case VIDIOC_G_AUDIO:
352 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300353 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
354 struct v4l2_audio *vin = arg;
355 memset(vin,0,sizeof(*vin));
356 vin->index = 0;
357 strncpy(vin->name, "PVRUSB2 Audio",14);
358 vin->capability = V4L2_AUDCAP_STEREO;
359 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300360 break;
361 }
362
363 case VIDIOC_S_AUDIO:
364 {
365 ret = -EINVAL;
366 break;
367 }
368 case VIDIOC_G_TUNER:
369 {
370 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300371
Michael Krufky8d364362007-01-22 02:17:55 -0300372 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300373
Mike Isely18103c572007-01-20 00:09:47 -0300374 pvr2_hdw_execute_tuner_poll(hdw);
375 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300376 break;
377 }
378
379 case VIDIOC_S_TUNER:
380 {
381 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
382
383 if (vt->index != 0)
384 break;
385
386 ret = pvr2_ctrl_set_value(
387 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
388 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300389 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300390 }
391
392 case VIDIOC_S_FREQUENCY:
393 {
394 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300395 unsigned long fv;
Mike Isely18103c572007-01-20 00:09:47 -0300396 struct v4l2_tuner vt;
397 int cur_input;
398 struct pvr2_ctrl *ctrlp;
399 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
400 if (ret != 0) break;
401 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
402 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
403 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300404 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c572007-01-20 00:09:47 -0300405 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
406 pvr2_ctrl_set_value(ctrlp,
407 PVR2_CVAL_INPUT_RADIO);
408 }
409 } else {
410 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
411 pvr2_ctrl_set_value(ctrlp,
412 PVR2_CVAL_INPUT_TV);
413 }
414 }
415 fv = vf->frequency;
416 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300417 fv = (fv * 125) / 2;
418 } else {
419 fv = fv * 62500;
420 }
Mike Iselyd8554972006-06-26 20:58:46 -0300421 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300422 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300423 break;
424 }
425
426 case VIDIOC_G_FREQUENCY:
427 {
428 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
429 int val = 0;
Mike Isely18103c572007-01-20 00:09:47 -0300430 int cur_input;
431 struct v4l2_tuner vt;
432 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
433 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300434 ret = pvr2_ctrl_get_value(
435 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
436 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300437 if (ret != 0) break;
438 pvr2_ctrl_get_value(
439 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
440 &cur_input);
441 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300442 vf->type = V4L2_TUNER_RADIO;
443 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300444 vf->type = V4L2_TUNER_ANALOG_TV;
445 }
Mike Isely18103c572007-01-20 00:09:47 -0300446 if (vt.capability & V4L2_TUNER_CAP_LOW) {
447 val = (val * 2) / 125;
448 } else {
449 val /= 62500;
450 }
451 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300452 break;
453 }
454
455 case VIDIOC_ENUM_FMT:
456 {
457 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
458
459 /* Only one format is supported : mpeg.*/
460 if (fd->index != 0)
461 break;
462
463 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
464 ret = 0;
465 break;
466 }
467
468 case VIDIOC_G_FMT:
469 {
470 struct v4l2_format *vf = (struct v4l2_format *)arg;
471 int val;
472 switch(vf->type) {
473 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
474 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
475 sizeof(struct v4l2_format));
476 val = 0;
477 pvr2_ctrl_get_value(
478 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
479 &val);
480 vf->fmt.pix.width = val;
481 val = 0;
482 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300483 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
484 &val);
485 vf->fmt.pix.height = val;
486 ret = 0;
487 break;
488 case V4L2_BUF_TYPE_VBI_CAPTURE:
489 // ????? Still need to figure out to do VBI correctly
490 ret = -EINVAL;
491 break;
492 default:
493 ret = -EINVAL;
494 break;
495 }
496 break;
497 }
498
499 case VIDIOC_TRY_FMT:
500 case VIDIOC_S_FMT:
501 {
502 struct v4l2_format *vf = (struct v4l2_format *)arg;
503
504 ret = 0;
505 switch(vf->type) {
506 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300507 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300508 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300509 int h = vf->fmt.pix.height;
510 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300511 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
512 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300513
Mike Iselye95a1912006-08-08 09:10:07 -0300514 lmin = pvr2_ctrl_get_min(hcp);
515 lmax = pvr2_ctrl_get_max(hcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300516 ldef = pvr2_ctrl_get_def(hcp);
517 if (w == -1) {
518 w = ldef;
519 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300520 w = lmin;
521 } else if (w > lmax) {
522 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300523 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300524 lmin = pvr2_ctrl_get_min(vcp);
525 lmax = pvr2_ctrl_get_max(vcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300526 ldef = pvr2_ctrl_get_def(vcp);
527 if (h == -1) {
528 h = ldef;
529 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300530 h = lmin;
531 } else if (h > lmax) {
532 h = lmax;
533 }
Mike Iselyd8554972006-06-26 20:58:46 -0300534
535 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
536 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300537 vf->fmt.pix.width = w;
538 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300539
540 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300541 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
542 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300543 }
544 } break;
545 case V4L2_BUF_TYPE_VBI_CAPTURE:
546 // ????? Still need to figure out to do VBI correctly
547 ret = -EINVAL;
548 break;
549 default:
550 ret = -EINVAL;
551 break;
552 }
553 break;
554 }
555
556 case VIDIOC_STREAMON:
557 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300558 if (!fh->dev_info->stream) {
559 /* No stream defined for this node. This means
560 that we're not currently allowed to stream from
561 this node. */
562 ret = -EPERM;
563 break;
564 }
Mike Iselyd8554972006-06-26 20:58:46 -0300565 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
566 if (ret < 0) return ret;
567 ret = pvr2_hdw_set_streaming(hdw,!0);
568 break;
569 }
570
571 case VIDIOC_STREAMOFF:
572 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300573 if (!fh->dev_info->stream) {
574 /* No stream defined for this node. This means
575 that we're not currently allowed to stream from
576 this node. */
577 ret = -EPERM;
578 break;
579 }
Mike Iselyd8554972006-06-26 20:58:46 -0300580 ret = pvr2_hdw_set_streaming(hdw,0);
581 break;
582 }
583
584 case VIDIOC_QUERYCTRL:
585 {
586 struct pvr2_ctrl *cptr;
587 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
588 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300589 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
590 cptr = pvr2_hdw_get_ctrl_nextv4l(
591 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
592 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
593 } else {
594 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
595 }
Mike Iselyd8554972006-06-26 20:58:46 -0300596 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300597 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300598 "QUERYCTRL id=0x%x not implemented here",
599 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300600 ret = -EINVAL;
601 break;
602 }
603
Mike Iselya761f432006-06-25 20:04:44 -0300604 pvr2_trace(PVR2_TRACE_V4LIOCTL,
605 "QUERYCTRL id=0x%x mapping name=%s (%s)",
606 vc->id,pvr2_ctrl_get_name(cptr),
607 pvr2_ctrl_get_desc(cptr));
608 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
609 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300610 vc->default_value = pvr2_ctrl_get_def(cptr);
611 switch (pvr2_ctrl_get_type(cptr)) {
612 case pvr2_ctl_enum:
613 vc->type = V4L2_CTRL_TYPE_MENU;
614 vc->minimum = 0;
615 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
616 vc->step = 1;
617 break;
Mike Isely33213962006-06-25 20:04:40 -0300618 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300619 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300620 vc->minimum = 0;
621 vc->maximum = 1;
622 vc->step = 1;
623 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300624 case pvr2_ctl_int:
625 vc->type = V4L2_CTRL_TYPE_INTEGER;
626 vc->minimum = pvr2_ctrl_get_min(cptr);
627 vc->maximum = pvr2_ctrl_get_max(cptr);
628 vc->step = 1;
629 break;
630 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300631 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300632 "QUERYCTRL id=0x%x name=%s not mappable",
633 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300634 ret = -EINVAL;
635 break;
636 }
637 break;
638 }
639
640 case VIDIOC_QUERYMENU:
641 {
642 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
643 unsigned int cnt = 0;
644 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
645 vm->index,
646 vm->name,sizeof(vm->name)-1,
647 &cnt);
648 vm->name[cnt] = 0;
649 break;
650 }
651
652 case VIDIOC_G_CTRL:
653 {
654 struct v4l2_control *vc = (struct v4l2_control *)arg;
655 int val = 0;
656 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
657 &val);
658 vc->value = val;
659 break;
660 }
661
662 case VIDIOC_S_CTRL:
663 {
664 struct v4l2_control *vc = (struct v4l2_control *)arg;
665 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
666 vc->value);
667 break;
668 }
669
Mike Isely1d9f8462006-06-25 20:04:58 -0300670 case VIDIOC_G_EXT_CTRLS:
671 {
672 struct v4l2_ext_controls *ctls =
673 (struct v4l2_ext_controls *)arg;
674 struct v4l2_ext_control *ctrl;
675 unsigned int idx;
676 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300677 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300678 for (idx = 0; idx < ctls->count; idx++) {
679 ctrl = ctls->controls + idx;
680 ret = pvr2_ctrl_get_value(
681 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
682 if (ret) {
683 ctls->error_idx = idx;
684 break;
685 }
686 /* Ensure that if read as a 64 bit value, the user
687 will still get a hopefully sane value */
688 ctrl->value64 = 0;
689 ctrl->value = val;
690 }
691 break;
692 }
693
694 case VIDIOC_S_EXT_CTRLS:
695 {
696 struct v4l2_ext_controls *ctls =
697 (struct v4l2_ext_controls *)arg;
698 struct v4l2_ext_control *ctrl;
699 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300700 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300701 for (idx = 0; idx < ctls->count; idx++) {
702 ctrl = ctls->controls + idx;
703 ret = pvr2_ctrl_set_value(
704 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
705 ctrl->value);
706 if (ret) {
707 ctls->error_idx = idx;
708 break;
709 }
710 }
711 break;
712 }
713
714 case VIDIOC_TRY_EXT_CTRLS:
715 {
716 struct v4l2_ext_controls *ctls =
717 (struct v4l2_ext_controls *)arg;
718 struct v4l2_ext_control *ctrl;
719 struct pvr2_ctrl *pctl;
720 unsigned int idx;
721 /* For the moment just validate that the requested control
722 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300723 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300724 for (idx = 0; idx < ctls->count; idx++) {
725 ctrl = ctls->controls + idx;
726 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
727 if (!pctl) {
728 ret = -EINVAL;
729 ctls->error_idx = idx;
730 break;
731 }
732 }
733 break;
734 }
735
Mike Iselyd8554972006-06-26 20:58:46 -0300736 case VIDIOC_LOG_STATUS:
737 {
Mike Iselyd8554972006-06-26 20:58:46 -0300738 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300739 ret = 0;
740 break;
741 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300742#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300743 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300744 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300745 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300746 u64 val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300747 struct v4l2_register *req = (struct v4l2_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300748 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300749 ret = pvr2_hdw_register_access(
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300750 hdw,req->match_type,req->match_chip,req->reg,
Trent Piepho52ebc762007-01-23 22:38:13 -0300751 cmd == VIDIOC_DBG_S_REGISTER,&val);
752 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300753 break;
754 }
755#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300756
757 default :
758 ret = v4l_compat_translate_ioctl(inode,file,cmd,
759 arg,pvr2_v4l2_do_ioctl);
760 }
761
762 pvr2_hdw_commit_ctl(hdw);
763
764 if (ret < 0) {
765 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300766 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300767 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
768 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300769 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
770 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300771 "pvr2_v4l2_do_ioctl failure, ret=%d"
772 " command was:",ret);
773 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
774 cmd);
775 }
776 }
777 } else {
778 pvr2_trace(PVR2_TRACE_V4LIOCTL,
779 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
780 ret,ret);
781 }
782 return ret;
783}
784
785
786static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
787{
Mike Isely0f0f2572006-12-27 23:19:42 -0300788 int minor_id = dip->devbase.minor;
Mike Isely0f0f2572006-12-27 23:19:42 -0300789 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300790 enum pvr2_config cfg = dip->config;
791 int v4l_type = dip->v4l_type;
Mike Isely0f0f2572006-12-27 23:19:42 -0300792
Mike Isely16eb40d2006-12-30 18:27:32 -0300793 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300794
795 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300796 dip->v4lp = NULL;
797 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300798
799 /* Actual deallocation happens later when all internal references
800 are gone. */
801 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300802
Mike Isely16eb40d2006-12-30 18:27:32 -0300803 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
804 get_v4l_name(v4l_type),minor_id & 0x1f,
805 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300806
Mike Iselyd8554972006-06-26 20:58:46 -0300807}
808
809
810static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
811{
Mike Isely0f0f2572006-12-27 23:19:42 -0300812 if (vp->dev_video) {
813 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000814 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300815 }
816 if (vp->dev_radio) {
817 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000818 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300819 }
Mike Iselyd8554972006-06-26 20:58:46 -0300820
821 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
822 pvr2_channel_done(&vp->channel);
823 kfree(vp);
824}
825
826
Mike Isely75910052006-09-23 22:30:50 -0300827static void pvr2_video_device_release(struct video_device *vdev)
828{
829 struct pvr2_v4l2_dev *dev;
830 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
831 kfree(dev);
832}
833
834
Adrian Bunk07e337e2006-06-30 11:30:20 -0300835static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300836{
837 struct pvr2_v4l2 *vp;
838 vp = container_of(chp,struct pvr2_v4l2,channel);
839 if (!vp->channel.mc_head->disconnect_flag) return;
840 if (vp->vfirst) return;
841 pvr2_v4l2_destroy_no_lock(vp);
842}
843
844
Adrian Bunk07e337e2006-06-30 11:30:20 -0300845static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
846 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300847{
848
849/* Temporary hack : use ivtv api until a v4l2 one is available. */
850#define IVTV_IOC_G_CODEC 0xFFEE7703
851#define IVTV_IOC_S_CODEC 0xFFEE7704
852 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
853 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
854}
855
856
Adrian Bunk07e337e2006-06-30 11:30:20 -0300857static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300858{
859 struct pvr2_v4l2_fh *fhp = file->private_data;
860 struct pvr2_v4l2 *vp = fhp->vhead;
861 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
Mike Iselyc74e0062006-12-30 18:31:22 -0300862 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300863
864 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
865
866 if (fhp->rhp) {
867 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300868 pvr2_hdw_set_streaming(hdw,0);
869 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300870 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300871 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300872 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300873 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300874
Mike Iselyd8554972006-06-26 20:58:46 -0300875 v4l2_prio_close(&vp->prio, &fhp->prio);
876 file->private_data = NULL;
877
878 pvr2_context_enter(mp); do {
Mike Iselyc74e0062006-12-30 18:31:22 -0300879 /* Restore the previous input selection, if it makes sense
880 to do so. */
881 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
882 struct pvr2_ctrl *cp;
883 int pval;
884 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
885 pvr2_ctrl_get_value(cp,&pval);
886 /* Only restore if we're still selecting the radio */
887 if (pval == PVR2_CVAL_INPUT_RADIO) {
888 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
889 pvr2_hdw_commit_ctl(hdw);
890 }
891 }
892
Mike Iselyd8554972006-06-26 20:58:46 -0300893 if (fhp->vnext) {
894 fhp->vnext->vprev = fhp->vprev;
895 } else {
896 vp->vlast = fhp->vprev;
897 }
898 if (fhp->vprev) {
899 fhp->vprev->vnext = fhp->vnext;
900 } else {
901 vp->vfirst = fhp->vnext;
902 }
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300903 fhp->vnext = NULL;
904 fhp->vprev = NULL;
905 fhp->vhead = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300906 pvr2_channel_done(&fhp->channel);
907 pvr2_trace(PVR2_TRACE_STRUCT,
908 "Destroying pvr_v4l2_fh id=%p",fhp);
909 kfree(fhp);
910 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
911 pvr2_v4l2_destroy_no_lock(vp);
912 }
913 } while (0); pvr2_context_exit(mp);
914 return 0;
915}
916
917
Adrian Bunk07e337e2006-06-30 11:30:20 -0300918static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300919{
Mike Isely75910052006-09-23 22:30:50 -0300920 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300921 struct pvr2_v4l2_fh *fhp;
922 struct pvr2_v4l2 *vp;
923 struct pvr2_hdw *hdw;
924
Mike Isely75910052006-09-23 22:30:50 -0300925 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300926
927 vp = dip->v4lp;
928 hdw = vp->channel.hdw;
929
930 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
931
932 if (!pvr2_hdw_dev_ok(hdw)) {
933 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
934 "pvr2_v4l2_open: hardware not ready");
935 return -EIO;
936 }
937
Mike Isely4b85dee2007-01-20 00:03:32 -0300938 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300939 if (!fhp) {
940 return -ENOMEM;
941 }
Mike Iselyd8554972006-06-26 20:58:46 -0300942
943 init_waitqueue_head(&fhp->wait_data);
944 fhp->dev_info = dip;
945
946 pvr2_context_enter(vp->channel.mc_head); do {
947 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
948 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300949
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300950 fhp->vnext = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300951 fhp->vprev = vp->vlast;
952 if (vp->vlast) {
953 vp->vlast->vnext = fhp;
954 } else {
955 vp->vfirst = fhp;
956 }
957 vp->vlast = fhp;
958 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300959
960 /* Opening the /dev/radioX device implies a mode switch.
961 So execute that here. Note that you can get the
962 IDENTICAL effect merely by opening the normal video
963 device and setting the input appropriately. */
964 if (dip->v4l_type == VFL_TYPE_RADIO) {
965 struct pvr2_ctrl *cp;
966 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
967 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
968 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
969 pvr2_hdw_commit_ctl(hdw);
970 }
Mike Iselyd8554972006-06-26 20:58:46 -0300971 } while (0); pvr2_context_exit(vp->channel.mc_head);
972
973 fhp->file = file;
974 file->private_data = fhp;
975 v4l2_prio_open(&vp->prio,&fhp->prio);
976
977 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
978
979 return 0;
980}
981
982
983static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
984{
985 wake_up(&fhp->wait_data);
986}
987
988static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
989{
990 int ret;
991 struct pvr2_stream *sp;
992 struct pvr2_hdw *hdw;
993 if (fh->rhp) return 0;
994
Mike Isely16eb40d2006-12-30 18:27:32 -0300995 if (!fh->dev_info->stream) {
996 /* No stream defined for this node. This means that we're
997 not currently allowed to stream from this node. */
998 return -EPERM;
999 }
1000
Mike Iselyd8554972006-06-26 20:58:46 -03001001 /* First read() attempt. Try to claim the stream and start
1002 it... */
1003 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1004 fh->dev_info->stream)) != 0) {
1005 /* Someone else must already have it */
1006 return ret;
1007 }
1008
1009 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1010 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001011 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001012 return -ENOMEM;
1013 }
1014
1015 hdw = fh->channel.mc_head->hdw;
1016 sp = fh->dev_info->stream->stream;
1017 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1018 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
Mike Isely681c7392007-11-26 01:48:52 -03001019 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1020 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001021}
1022
1023
1024static ssize_t pvr2_v4l2_read(struct file *file,
1025 char __user *buff, size_t count, loff_t *ppos)
1026{
1027 struct pvr2_v4l2_fh *fh = file->private_data;
1028 int ret;
1029
1030 if (fh->fw_mode_flag) {
1031 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1032 char *tbuf;
1033 int c1,c2;
1034 int tcnt = 0;
1035 unsigned int offs = *ppos;
1036
1037 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1038 if (!tbuf) return -ENOMEM;
1039
1040 while (count) {
1041 c1 = count;
1042 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1043 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1044 if (c2 < 0) {
1045 tcnt = c2;
1046 break;
1047 }
1048 if (!c2) break;
1049 if (copy_to_user(buff,tbuf,c2)) {
1050 tcnt = -EFAULT;
1051 break;
1052 }
1053 offs += c2;
1054 tcnt += c2;
1055 buff += c2;
1056 count -= c2;
1057 *ppos += c2;
1058 }
1059 kfree(tbuf);
1060 return tcnt;
1061 }
1062
1063 if (!fh->rhp) {
1064 ret = pvr2_v4l2_iosetup(fh);
1065 if (ret) {
1066 return ret;
1067 }
1068 }
1069
1070 for (;;) {
1071 ret = pvr2_ioread_read(fh->rhp,buff,count);
1072 if (ret >= 0) break;
1073 if (ret != -EAGAIN) break;
1074 if (file->f_flags & O_NONBLOCK) break;
1075 /* Doing blocking I/O. Wait here. */
1076 ret = wait_event_interruptible(
1077 fh->wait_data,
1078 pvr2_ioread_avail(fh->rhp) >= 0);
1079 if (ret < 0) break;
1080 }
1081
1082 return ret;
1083}
1084
1085
1086static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1087{
1088 unsigned int mask = 0;
1089 struct pvr2_v4l2_fh *fh = file->private_data;
1090 int ret;
1091
1092 if (fh->fw_mode_flag) {
1093 mask |= POLLIN | POLLRDNORM;
1094 return mask;
1095 }
1096
1097 if (!fh->rhp) {
1098 ret = pvr2_v4l2_iosetup(fh);
1099 if (ret) return POLLERR;
1100 }
1101
1102 poll_wait(file,&fh->wait_data,wait);
1103
1104 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1105 mask |= POLLIN | POLLRDNORM;
1106 }
1107
1108 return mask;
1109}
1110
1111
Arjan van de Venfa027c22007-02-12 00:55:33 -08001112static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001113 .owner = THIS_MODULE,
1114 .open = pvr2_v4l2_open,
1115 .release = pvr2_v4l2_release,
1116 .read = pvr2_v4l2_read,
1117 .ioctl = pvr2_v4l2_ioctl,
1118 .llseek = no_llseek,
1119 .poll = pvr2_v4l2_poll,
1120};
1121
1122
Mike Iselyd8554972006-06-26 20:58:46 -03001123static struct video_device vdev_template = {
1124 .owner = THIS_MODULE,
1125 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1126 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1127 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1128 | V4L2_CAP_READWRITE),
Mike Iselyd8554972006-06-26 20:58:46 -03001129 .fops = &vdev_fops,
1130};
1131
1132
1133static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1134 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001135 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001136{
1137 int mindevnum;
1138 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001139 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001140 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001141
1142
Mike Isely16eb40d2006-12-30 18:27:32 -03001143 dip->v4l_type = v4l_type;
1144 switch (v4l_type) {
1145 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001146 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001147 dip->config = pvr2_config_mpeg;
1148 dip->minor_type = pvr2_v4l_type_video;
1149 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001150 if (!dip->stream) {
1151 err("Failed to set up pvrusb2 v4l video dev"
1152 " due to missing stream instance");
1153 return;
1154 }
Mike Iselyd8554972006-06-26 20:58:46 -03001155 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001156 case VFL_TYPE_VBI:
1157 dip->config = pvr2_config_vbi;
1158 dip->minor_type = pvr2_v4l_type_vbi;
1159 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001160 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001161 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001162 dip->stream = &vp->channel.mc_head->video_stream;
1163 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001164 dip->minor_type = pvr2_v4l_type_radio;
1165 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001166 break;
1167 default:
1168 /* Bail out (this should be impossible) */
1169 err("Failed to set up pvrusb2 v4l dev"
1170 " due to unrecognized config");
1171 return;
1172 }
1173
Mike Isely75910052006-09-23 22:30:50 -03001174 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1175 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001176
1177 mindevnum = -1;
1178 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001179 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1180 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001181 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001182 if ((video_register_device(&dip->devbase,
1183 dip->v4l_type, mindevnum) < 0) &&
1184 (video_register_device(&dip->devbase,
1185 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001186 err("Failed to register pvrusb2 v4l device");
1187 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001188
1189 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1190 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1191 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001192
Mike Iselyd8554972006-06-26 20:58:46 -03001193 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001194 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001195}
1196
1197
1198struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1199{
1200 struct pvr2_v4l2 *vp;
1201
Mike Isely4b85dee2007-01-20 00:03:32 -03001202 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001203 if (!vp) return vp;
Mike Isely4b85dee2007-01-20 00:03:32 -03001204 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1205 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
Mike Isely0f0f2572006-12-27 23:19:42 -03001206 if (!(vp->dev_video && vp->dev_radio)) {
Mike Isely6710fb82007-01-20 00:02:26 -03001207 kfree(vp->dev_video);
1208 kfree(vp->dev_radio);
Mike Isely75910052006-09-23 22:30:50 -03001209 kfree(vp);
Randy Dunlapc2625bf2006-10-29 11:12:27 -03001210 return NULL;
Mike Isely75910052006-09-23 22:30:50 -03001211 }
Mike Iselyd8554972006-06-26 20:58:46 -03001212 pvr2_channel_init(&vp->channel,mnp);
1213 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1214
1215 vp->channel.check_func = pvr2_v4l2_internal_check;
1216
1217 /* register streams */
Mike Isely16eb40d2006-12-30 18:27:32 -03001218 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1219 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
Mike Iselyd8554972006-06-26 20:58:46 -03001220
1221 return vp;
1222}
1223
1224/*
1225 Stuff for Emacs to see, in order to encourage consistent editing style:
1226 *** Local Variables: ***
1227 *** mode: c ***
1228 *** fill-column: 75 ***
1229 *** tab-width: 8 ***
1230 *** c-basic-offset: 8 ***
1231 *** End: ***
1232 */