aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2012-02-20 00:21:00 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-07 15:49:09 -0400
commitc6d26cfe26e475c9ddd09667dd6694b34469f4dc (patch)
treec4cc0acd78c242d5eb62d9ae922110993245d3a3 /drivers/media/video/pvrusb2
parent5f1a12f5d03ecd920e09c08e1b9fc1312a1d6da4 (diff)
[media] pvrusb2: convert to video_ioctl2
Note: there is one FIXME remaining: the tvnorms field of struct video_device should be set up correctly. I have used V4L2_STD_ALL for now, but I'm sure this can be improved. This field is used by video_ioctl2 to implement ENUMSTD. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/pvrusb2')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c1318
1 files changed, 679 insertions, 639 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 5e462faa272..83bc4675ec2 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -150,733 +150,719 @@ static struct v4l2_format pvr_format [] = {
150}; 150};
151 151
152 152
153
153/* 154/*
154 * pvr_ioctl() 155 * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
155 *
156 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
157 *
158 */ 156 */
159static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) 157static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
160{ 158{
161 struct pvr2_v4l2_fh *fh = file->private_data; 159 struct pvr2_v4l2_fh *fh = file->private_data;
162 struct pvr2_v4l2 *vp = fh->vhead;
163 struct pvr2_v4l2_dev *pdi = fh->pdi;
164 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; 160 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
165 long ret = -EINVAL;
166
167 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
168 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
169 }
170 161
171 if (!pvr2_hdw_dev_ok(hdw)) { 162 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
172 pvr2_trace(PVR2_TRACE_ERROR_LEGS, 163 strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
173 "ioctl failed - bad or no context"); 164 sizeof(cap->bus_info));
174 return -EFAULT; 165 strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
175 } 166 return 0;
176 167}
177 /* check priority */
178 switch (cmd) {
179 case VIDIOC_S_CTRL:
180 case VIDIOC_S_STD:
181 case VIDIOC_S_INPUT:
182 case VIDIOC_S_TUNER:
183 case VIDIOC_S_FREQUENCY:
184 ret = v4l2_prio_check(&vp->prio, fh->prio);
185 if (ret)
186 return ret;
187 }
188 168
189 switch (cmd) { 169static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
190 case VIDIOC_QUERYCAP: 170{
191 { 171 struct pvr2_v4l2_fh *fh = file->private_data;
192 struct v4l2_capability *cap = arg; 172 struct pvr2_v4l2 *vp = fh->vhead;
193 173
194 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability)); 174 *p = v4l2_prio_max(&vp->prio);
195 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw), 175 return 0;
196 sizeof(cap->bus_info)); 176}
197 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
198 177
199 ret = 0; 178static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
200 break; 179{
201 } 180 struct pvr2_v4l2_fh *fh = file->private_data;
181 struct pvr2_v4l2 *vp = fh->vhead;
202 182
203 case VIDIOC_G_PRIORITY: 183 return v4l2_prio_change(&vp->prio, &fh->prio, prio);
204 { 184}
205 enum v4l2_priority *p = arg;
206 185
207 *p = v4l2_prio_max(&vp->prio); 186static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
208 ret = 0; 187{
209 break; 188 struct pvr2_v4l2_fh *fh = file->private_data;
210 } 189 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
190 int val = 0;
191 int ret;
211 192
212 case VIDIOC_S_PRIORITY: 193 ret = pvr2_ctrl_get_value(
213 { 194 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
214 enum v4l2_priority *prio = arg; 195 *std = val;
196 return ret;
197}
215 198
216 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio); 199int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
217 break; 200{
218 } 201 struct pvr2_v4l2_fh *fh = file->private_data;
202 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
219 203
220 case VIDIOC_ENUMSTD: 204 return pvr2_ctrl_set_value(
221 { 205 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), *std);
222 struct v4l2_standard *vs = (struct v4l2_standard *)arg; 206}
223 int idx = vs->index;
224 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
225 break;
226 }
227 207
228 case VIDIOC_QUERYSTD: 208static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
229 { 209{
230 v4l2_std_id *std = arg; 210 struct pvr2_v4l2_fh *fh = file->private_data;
231 *std = V4L2_STD_ALL; 211 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
232 ret = pvr2_hdw_get_detected_std(hdw, std); 212 struct pvr2_ctrl *cptr;
233 break; 213 struct v4l2_input tmp;
234 } 214 unsigned int cnt;
215 int val;
216 int ret;
235 217
236 case VIDIOC_G_STD: 218 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
237 { 219
238 int val = 0; 220 memset(&tmp, 0, sizeof(tmp));
239 ret = pvr2_ctrl_get_value( 221 tmp.index = vi->index;
240 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val); 222 ret = 0;
241 *(v4l2_std_id *)arg = val; 223 if (vi->index >= fh->input_cnt)
224 return -EINVAL;
225 val = fh->input_map[vi->index];
226 switch (val) {
227 case PVR2_CVAL_INPUT_TV:
228 case PVR2_CVAL_INPUT_DTV:
229 case PVR2_CVAL_INPUT_RADIO:
230 tmp.type = V4L2_INPUT_TYPE_TUNER;
242 break; 231 break;
243 } 232 case PVR2_CVAL_INPUT_SVIDEO:
244 233 case PVR2_CVAL_INPUT_COMPOSITE:
245 case VIDIOC_S_STD: 234 tmp.type = V4L2_INPUT_TYPE_CAMERA;
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; 235 break;
236 default:
237 return -EINVAL;
251 } 238 }
252 239
253 case VIDIOC_ENUMINPUT: 240 cnt = 0;
254 { 241 pvr2_ctrl_get_valname(cptr, val,
255 struct pvr2_ctrl *cptr; 242 tmp.name, sizeof(tmp.name) - 1, &cnt);
256 struct v4l2_input *vi = (struct v4l2_input *)arg; 243 tmp.name[cnt] = 0;
257 struct v4l2_input tmp;
258 unsigned int cnt;
259 int val;
260
261 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
262
263 memset(&tmp,0,sizeof(tmp));
264 tmp.index = vi->index;
265 ret = 0;
266 if (vi->index >= fh->input_cnt) {
267 ret = -EINVAL;
268 break;
269 }
270 val = fh->input_map[vi->index];
271 switch (val) {
272 case PVR2_CVAL_INPUT_TV:
273 case PVR2_CVAL_INPUT_DTV:
274 case PVR2_CVAL_INPUT_RADIO:
275 tmp.type = V4L2_INPUT_TYPE_TUNER;
276 break;
277 case PVR2_CVAL_INPUT_SVIDEO:
278 case PVR2_CVAL_INPUT_COMPOSITE:
279 tmp.type = V4L2_INPUT_TYPE_CAMERA;
280 break;
281 default:
282 ret = -EINVAL;
283 break;
284 }
285 if (ret < 0) break;
286
287 cnt = 0;
288 pvr2_ctrl_get_valname(cptr,val,
289 tmp.name,sizeof(tmp.name)-1,&cnt);
290 tmp.name[cnt] = 0;
291
292 /* Don't bother with audioset, since this driver currently
293 always switches the audio whenever the video is
294 switched. */
295
296 /* Handling std is a tougher problem. It doesn't make
297 sense in cases where a device might be multi-standard.
298 We could just copy out the current value for the
299 standard, but it can change over time. For now just
300 leave it zero. */
301 244
302 memcpy(vi, &tmp, sizeof(tmp)); 245 /* Don't bother with audioset, since this driver currently
246 always switches the audio whenever the video is
247 switched. */
303 248
304 ret = 0; 249 /* Handling std is a tougher problem. It doesn't make
305 break; 250 sense in cases where a device might be multi-standard.
306 } 251 We could just copy out the current value for the
252 standard, but it can change over time. For now just
253 leave it zero. */
254 *vi = tmp;
255 return 0;
256}
307 257
308 case VIDIOC_G_INPUT: 258static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
309 { 259{
310 unsigned int idx; 260 struct pvr2_v4l2_fh *fh = file->private_data;
311 struct pvr2_ctrl *cptr; 261 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
312 struct v4l2_input *vi = (struct v4l2_input *)arg; 262 unsigned int idx;
313 int val; 263 struct pvr2_ctrl *cptr;
314 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); 264 int val;
315 val = 0; 265 int ret;
316 ret = pvr2_ctrl_get_value(cptr,&val);
317 vi->index = 0;
318 for (idx = 0; idx < fh->input_cnt; idx++) {
319 if (fh->input_map[idx] == val) {
320 vi->index = idx;
321 break;
322 }
323 }
324 break;
325 }
326 266
327 case VIDIOC_S_INPUT: 267 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
328 { 268 val = 0;
329 struct v4l2_input *vi = (struct v4l2_input *)arg; 269 ret = pvr2_ctrl_get_value(cptr, &val);
330 if (vi->index >= fh->input_cnt) { 270 *i = 0;
331 ret = -ERANGE; 271 for (idx = 0; idx < fh->input_cnt; idx++) {
272 if (fh->input_map[idx] == val) {
273 *i = idx;
332 break; 274 break;
333 } 275 }
334 ret = pvr2_ctrl_set_value(
335 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
336 fh->input_map[vi->index]);
337 break;
338 } 276 }
277 return ret;
278}
339 279
340 case VIDIOC_ENUMAUDIO: 280static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
341 { 281{
342 /* pkt: FIXME: We are returning one "fake" input here 282 struct pvr2_v4l2_fh *fh = file->private_data;
343 which could very well be called "whatever_we_like". 283 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
344 This is for apps that want to see an audio input
345 just to feel comfortable, as well as to test if
346 it can do stereo or sth. There is actually no guarantee
347 that the actual audio input cannot change behind the app's
348 back, but most applications should not mind that either.
349
350 Hopefully, mplayer people will work with us on this (this
351 whole mess is to support mplayer pvr://), or Hans will come
352 up with a more standard way to say "we have inputs but we
353 don 't want you to change them independent of video" which
354 will sort this mess.
355 */
356 struct v4l2_audio *vin = arg;
357 ret = -EINVAL;
358 if (vin->index > 0) break;
359 strncpy(vin->name, "PVRUSB2 Audio",14);
360 vin->capability = V4L2_AUDCAP_STEREO;
361 ret = 0;
362 break;
363 break;
364 }
365 284
366 case VIDIOC_G_AUDIO: 285 if (inp >= fh->input_cnt)
367 { 286 return -EINVAL;
368 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */ 287 return pvr2_ctrl_set_value(
369 struct v4l2_audio *vin = arg; 288 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
370 memset(vin,0,sizeof(*vin)); 289 fh->input_map[inp]);
371 vin->index = 0; 290}
372 strncpy(vin->name, "PVRUSB2 Audio",14);
373 vin->capability = V4L2_AUDCAP_STEREO;
374 ret = 0;
375 break;
376 }
377 291
378 case VIDIOC_G_TUNER: 292static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
379 { 293{
380 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; 294 /* pkt: FIXME: We are returning one "fake" input here
295 which could very well be called "whatever_we_like".
296 This is for apps that want to see an audio input
297 just to feel comfortable, as well as to test if
298 it can do stereo or sth. There is actually no guarantee
299 that the actual audio input cannot change behind the app's
300 back, but most applications should not mind that either.
301
302 Hopefully, mplayer people will work with us on this (this
303 whole mess is to support mplayer pvr://), or Hans will come
304 up with a more standard way to say "we have inputs but we
305 don 't want you to change them independent of video" which
306 will sort this mess.
307 */
308
309 if (vin->index > 0)
310 return -EINVAL;
311 strncpy(vin->name, "PVRUSB2 Audio", 14);
312 vin->capability = V4L2_AUDCAP_STEREO;
313 return 0;
314}
381 315
382 if (vt->index != 0) break; /* Only answer for the 1st tuner */ 316static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
317{
318 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
319 vin->index = 0;
320 strncpy(vin->name, "PVRUSB2 Audio", 14);
321 vin->capability = V4L2_AUDCAP_STEREO;
322 return 0;
323}
383 324
384 pvr2_hdw_execute_tuner_poll(hdw); 325static int pvr2_s_audio(struct file *file, void *priv, struct v4l2_audio *vout)
385 ret = pvr2_hdw_get_tuner_status(hdw,vt); 326{
386 break; 327 if (vout->index)
387 } 328 return -EINVAL;
329 return 0;
330}
388 331
389 case VIDIOC_S_TUNER: 332static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
390 { 333{
391 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; 334 struct pvr2_v4l2_fh *fh = file->private_data;
335 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
392 336
393 if (vt->index != 0) 337 if (vt->index != 0)
394 break; 338 return -EINVAL; /* Only answer for the 1st tuner */
395 339
396 ret = pvr2_ctrl_set_value( 340 pvr2_hdw_execute_tuner_poll(hdw);
397 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), 341 return pvr2_hdw_get_tuner_status(hdw, vt);
342}
343
344static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
345{
346 struct pvr2_v4l2_fh *fh = file->private_data;
347 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
348
349 if (vt->index != 0)
350 return -EINVAL;
351
352 return pvr2_ctrl_set_value(
353 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
398 vt->audmode); 354 vt->audmode);
399 break; 355}
400 }
401 356
402 case VIDIOC_S_FREQUENCY: 357int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
403 { 358{
404 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; 359 struct pvr2_v4l2_fh *fh = file->private_data;
405 unsigned long fv; 360 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
406 struct v4l2_tuner vt; 361 unsigned long fv;
407 int cur_input; 362 struct v4l2_tuner vt;
408 struct pvr2_ctrl *ctrlp; 363 int cur_input;
409 ret = pvr2_hdw_get_tuner_status(hdw,&vt); 364 struct pvr2_ctrl *ctrlp;
410 if (ret != 0) break; 365 int ret;
411 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); 366
412 ret = pvr2_ctrl_get_value(ctrlp,&cur_input); 367 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
413 if (ret != 0) break; 368 if (ret != 0)
414 if (vf->type == V4L2_TUNER_RADIO) { 369 return ret;
415 if (cur_input != PVR2_CVAL_INPUT_RADIO) { 370 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
416 pvr2_ctrl_set_value(ctrlp, 371 ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
417 PVR2_CVAL_INPUT_RADIO); 372 if (ret != 0)
418 } 373 return ret;
419 } else { 374 if (vf->type == V4L2_TUNER_RADIO) {
420 if (cur_input == PVR2_CVAL_INPUT_RADIO) { 375 if (cur_input != PVR2_CVAL_INPUT_RADIO)
421 pvr2_ctrl_set_value(ctrlp, 376 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
422 PVR2_CVAL_INPUT_TV); 377 } else {
423 } 378 if (cur_input == PVR2_CVAL_INPUT_RADIO)
424 } 379 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
425 fv = vf->frequency; 380 }
426 if (vt.capability & V4L2_TUNER_CAP_LOW) { 381 fv = vf->frequency;
427 fv = (fv * 125) / 2; 382 if (vt.capability & V4L2_TUNER_CAP_LOW)
428 } else { 383 fv = (fv * 125) / 2;
429 fv = fv * 62500; 384 else
430 } 385 fv = fv * 62500;
431 ret = pvr2_ctrl_set_value( 386 return pvr2_ctrl_set_value(
432 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv); 387 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
433 break; 388}
434 }
435 389
436 case VIDIOC_G_FREQUENCY: 390static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
437 { 391{
438 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; 392 struct pvr2_v4l2_fh *fh = file->private_data;
439 int val = 0; 393 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
440 int cur_input; 394 int val = 0;
441 struct v4l2_tuner vt; 395 int cur_input;
442 ret = pvr2_hdw_get_tuner_status(hdw,&vt); 396 struct v4l2_tuner vt;
443 if (ret != 0) break; 397 int ret;
444 ret = pvr2_ctrl_get_value( 398
445 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), 399 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
400 if (ret != 0)
401 return ret;
402 ret = pvr2_ctrl_get_value(
403 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
446 &val); 404 &val);
447 if (ret != 0) break; 405 if (ret != 0)
448 pvr2_ctrl_get_value( 406 return ret;
449 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), 407 pvr2_ctrl_get_value(
408 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
450 &cur_input); 409 &cur_input);
451 if (cur_input == PVR2_CVAL_INPUT_RADIO) { 410 if (cur_input == PVR2_CVAL_INPUT_RADIO)
452 vf->type = V4L2_TUNER_RADIO; 411 vf->type = V4L2_TUNER_RADIO;
453 } else { 412 else
454 vf->type = V4L2_TUNER_ANALOG_TV; 413 vf->type = V4L2_TUNER_ANALOG_TV;
455 } 414 if (vt.capability & V4L2_TUNER_CAP_LOW)
456 if (vt.capability & V4L2_TUNER_CAP_LOW) { 415 val = (val * 2) / 125;
457 val = (val * 2) / 125; 416 else
458 } else { 417 val /= 62500;
459 val /= 62500; 418 vf->frequency = val;
460 } 419 return 0;
461 vf->frequency = val; 420}
462 break;
463 }
464 421
465 case VIDIOC_ENUM_FMT: 422static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
466 { 423{
467 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg; 424 /* Only one format is supported : mpeg.*/
425 if (fd->index != 0)
426 return -EINVAL;
468 427
469 /* Only one format is supported : mpeg.*/ 428 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
470 if (fd->index != 0) 429 return 0;
471 break; 430}
472 431
473 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc)); 432static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
474 ret = 0; 433{
475 break; 434 struct pvr2_v4l2_fh *fh = file->private_data;
476 } 435 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
436 int val;
477 437
478 case VIDIOC_G_FMT: 438 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
479 { 439 val = 0;
480 struct v4l2_format *vf = (struct v4l2_format *)arg; 440 pvr2_ctrl_get_value(
481 int val; 441 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
482 switch(vf->type) { 442 &val);
483 case V4L2_BUF_TYPE_VIDEO_CAPTURE: 443 vf->fmt.pix.width = val;
484 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], 444 val = 0;
485 sizeof(struct v4l2_format)); 445 pvr2_ctrl_get_value(
486 val = 0; 446 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
487 pvr2_ctrl_get_value( 447 &val);
488 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES), 448 vf->fmt.pix.height = val;
489 &val); 449 return 0;
490 vf->fmt.pix.width = val; 450}
491 val = 0;
492 pvr2_ctrl_get_value(
493 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
494 &val);
495 vf->fmt.pix.height = val;
496 ret = 0;
497 break;
498 case V4L2_BUF_TYPE_VBI_CAPTURE:
499 // ????? Still need to figure out to do VBI correctly
500 ret = -EINVAL;
501 break;
502 default:
503 ret = -EINVAL;
504 break;
505 }
506 break;
507 }
508 451
509 case VIDIOC_TRY_FMT: 452static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
510 case VIDIOC_S_FMT: 453{
511 { 454 struct pvr2_v4l2_fh *fh = file->private_data;
512 struct v4l2_format *vf = (struct v4l2_format *)arg; 455 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
513 456 int lmin, lmax, ldef;
514 ret = 0; 457 struct pvr2_ctrl *hcp, *vcp;
515 switch(vf->type) { 458 int h = vf->fmt.pix.height;
516 case V4L2_BUF_TYPE_VIDEO_CAPTURE: { 459 int w = vf->fmt.pix.width;
517 int lmin,lmax,ldef; 460
518 struct pvr2_ctrl *hcp,*vcp; 461 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
519 int h = vf->fmt.pix.height; 462 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
520 int w = vf->fmt.pix.width; 463
521 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES); 464 lmin = pvr2_ctrl_get_min(hcp);
522 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES); 465 lmax = pvr2_ctrl_get_max(hcp);
523 466 pvr2_ctrl_get_def(hcp, &ldef);
524 lmin = pvr2_ctrl_get_min(hcp); 467 if (w == -1)
525 lmax = pvr2_ctrl_get_max(hcp); 468 w = ldef;
526 pvr2_ctrl_get_def(hcp, &ldef); 469 else if (w < lmin)
527 if (w == -1) { 470 w = lmin;
528 w = ldef; 471 else if (w > lmax)
529 } else if (w < lmin) { 472 w = lmax;
530 w = lmin; 473 lmin = pvr2_ctrl_get_min(vcp);
531 } else if (w > lmax) { 474 lmax = pvr2_ctrl_get_max(vcp);
532 w = lmax; 475 pvr2_ctrl_get_def(vcp, &ldef);
533 } 476 if (h == -1)
534 lmin = pvr2_ctrl_get_min(vcp); 477 h = ldef;
535 lmax = pvr2_ctrl_get_max(vcp); 478 else if (h < lmin)
536 pvr2_ctrl_get_def(vcp, &ldef); 479 h = lmin;
537 if (h == -1) { 480 else if (h > lmax)
538 h = ldef; 481 h = lmax;
539 } else if (h < lmin) { 482
540 h = lmin; 483 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
541 } else if (h > lmax) { 484 sizeof(struct v4l2_format));
542 h = lmax; 485 vf->fmt.pix.width = w;
543 } 486 vf->fmt.pix.height = h;
487 return 0;
488}
544 489
545 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], 490static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
546 sizeof(struct v4l2_format)); 491{
547 vf->fmt.pix.width = w; 492 struct pvr2_v4l2_fh *fh = file->private_data;
548 vf->fmt.pix.height = h; 493 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
494 struct pvr2_ctrl *hcp, *vcp;
495 int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
549 496
550 if (cmd == VIDIOC_S_FMT) { 497 if (ret)
551 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width); 498 return ret;
552 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height); 499 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
553 } 500 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
554 } break; 501 pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
555 case V4L2_BUF_TYPE_VBI_CAPTURE: 502 pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
556 // ????? Still need to figure out to do VBI correctly 503 return 0;
557 ret = -EINVAL; 504}
558 break;
559 default:
560 ret = -EINVAL;
561 break;
562 }
563 break;
564 }
565 505
566 case VIDIOC_STREAMON: 506static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
567 { 507{
568 if (!fh->pdi->stream) { 508 struct pvr2_v4l2_fh *fh = file->private_data;
569 /* No stream defined for this node. This means 509 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
570 that we're not currently allowed to stream from 510 struct pvr2_v4l2_dev *pdi = fh->pdi;
571 this node. */ 511 int ret;
572 ret = -EPERM; 512
573 break; 513 if (!fh->pdi->stream) {
574 } 514 /* No stream defined for this node. This means
575 ret = pvr2_hdw_set_stream_type(hdw,pdi->config); 515 that we're not currently allowed to stream from
576 if (ret < 0) return ret; 516 this node. */
577 ret = pvr2_hdw_set_streaming(hdw,!0); 517 return -EPERM;
578 break;
579 } 518 }
519 ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
520 if (ret < 0)
521 return ret;
522 return pvr2_hdw_set_streaming(hdw, !0);
523}
580 524
581 case VIDIOC_STREAMOFF: 525static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
582 { 526{
583 if (!fh->pdi->stream) { 527 struct pvr2_v4l2_fh *fh = file->private_data;
584 /* No stream defined for this node. This means 528 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
585 that we're not currently allowed to stream from 529
586 this node. */ 530 if (!fh->pdi->stream) {
587 ret = -EPERM; 531 /* No stream defined for this node. This means
588 break; 532 that we're not currently allowed to stream from
589 } 533 this node. */
590 ret = pvr2_hdw_set_streaming(hdw,0); 534 return -EPERM;
591 break;
592 } 535 }
536 return pvr2_hdw_set_streaming(hdw, 0);
537}
593 538
594 case VIDIOC_QUERYCTRL: 539static int pvr2_queryctrl(struct file *file, void *priv,
595 { 540 struct v4l2_queryctrl *vc)
596 struct pvr2_ctrl *cptr; 541{
597 int val; 542 struct pvr2_v4l2_fh *fh = file->private_data;
598 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; 543 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
599 ret = 0; 544 struct pvr2_ctrl *cptr;
600 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { 545 int val;
601 cptr = pvr2_hdw_get_ctrl_nextv4l( 546 int ret;
602 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
603 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
604 } else {
605 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
606 }
607 if (!cptr) {
608 pvr2_trace(PVR2_TRACE_V4LIOCTL,
609 "QUERYCTRL id=0x%x not implemented here",
610 vc->id);
611 ret = -EINVAL;
612 break;
613 }
614 547
548 ret = 0;
549 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
550 cptr = pvr2_hdw_get_ctrl_nextv4l(
551 hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
552 if (cptr)
553 vc->id = pvr2_ctrl_get_v4lid(cptr);
554 } else {
555 cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
556 }
557 if (!cptr) {
615 pvr2_trace(PVR2_TRACE_V4LIOCTL, 558 pvr2_trace(PVR2_TRACE_V4LIOCTL,
616 "QUERYCTRL id=0x%x mapping name=%s (%s)", 559 "QUERYCTRL id=0x%x not implemented here",
617 vc->id,pvr2_ctrl_get_name(cptr), 560 vc->id);
618 pvr2_ctrl_get_desc(cptr)); 561 return -EINVAL;
619 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); 562 }
620 vc->flags = pvr2_ctrl_get_v4lflags(cptr); 563
621 pvr2_ctrl_get_def(cptr, &val); 564 pvr2_trace(PVR2_TRACE_V4LIOCTL,
622 vc->default_value = val; 565 "QUERYCTRL id=0x%x mapping name=%s (%s)",
623 switch (pvr2_ctrl_get_type(cptr)) { 566 vc->id, pvr2_ctrl_get_name(cptr),
624 case pvr2_ctl_enum: 567 pvr2_ctrl_get_desc(cptr));
625 vc->type = V4L2_CTRL_TYPE_MENU; 568 strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
626 vc->minimum = 0; 569 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
627 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1; 570 pvr2_ctrl_get_def(cptr, &val);
628 vc->step = 1; 571 vc->default_value = val;
629 break; 572 switch (pvr2_ctrl_get_type(cptr)) {
630 case pvr2_ctl_bool: 573 case pvr2_ctl_enum:
631 vc->type = V4L2_CTRL_TYPE_BOOLEAN; 574 vc->type = V4L2_CTRL_TYPE_MENU;
632 vc->minimum = 0; 575 vc->minimum = 0;
633 vc->maximum = 1; 576 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
634 vc->step = 1; 577 vc->step = 1;
635 break;
636 case pvr2_ctl_int:
637 vc->type = V4L2_CTRL_TYPE_INTEGER;
638 vc->minimum = pvr2_ctrl_get_min(cptr);
639 vc->maximum = pvr2_ctrl_get_max(cptr);
640 vc->step = 1;
641 break;
642 default:
643 pvr2_trace(PVR2_TRACE_V4LIOCTL,
644 "QUERYCTRL id=0x%x name=%s not mappable",
645 vc->id,pvr2_ctrl_get_name(cptr));
646 ret = -EINVAL;
647 break;
648 }
649 break; 578 break;
650 } 579 case pvr2_ctl_bool:
651 580 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
652 case VIDIOC_QUERYMENU: 581 vc->minimum = 0;
653 { 582 vc->maximum = 1;
654 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg; 583 vc->step = 1;
655 unsigned int cnt = 0;
656 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
657 vm->index,
658 vm->name,sizeof(vm->name)-1,
659 &cnt);
660 vm->name[cnt] = 0;
661 break; 584 break;
662 } 585 case pvr2_ctl_int:
663 586 vc->type = V4L2_CTRL_TYPE_INTEGER;
664 case VIDIOC_G_CTRL: 587 vc->minimum = pvr2_ctrl_get_min(cptr);
665 { 588 vc->maximum = pvr2_ctrl_get_max(cptr);
666 struct v4l2_control *vc = (struct v4l2_control *)arg; 589 vc->step = 1;
667 int val = 0;
668 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
669 &val);
670 vc->value = val;
671 break; 590 break;
591 default:
592 pvr2_trace(PVR2_TRACE_V4LIOCTL,
593 "QUERYCTRL id=0x%x name=%s not mappable",
594 vc->id, pvr2_ctrl_get_name(cptr));
595 return -EINVAL;
672 } 596 }
597 return 0;
598}
673 599
674 case VIDIOC_S_CTRL: 600static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
675 { 601{
676 struct v4l2_control *vc = (struct v4l2_control *)arg; 602 struct pvr2_v4l2_fh *fh = file->private_data;
677 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id), 603 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
678 vc->value); 604 unsigned int cnt = 0;
679 break; 605 int ret;
680 }
681 606
682 case VIDIOC_G_EXT_CTRLS: 607 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
683 { 608 vm->index,
684 struct v4l2_ext_controls *ctls = 609 vm->name, sizeof(vm->name) - 1,
685 (struct v4l2_ext_controls *)arg; 610 &cnt);
686 struct v4l2_ext_control *ctrl; 611 vm->name[cnt] = 0;
687 unsigned int idx; 612 return ret;
688 int val; 613}
689 ret = 0; 614
690 for (idx = 0; idx < ctls->count; idx++) { 615static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
691 ctrl = ctls->controls + idx; 616{
692 ret = pvr2_ctrl_get_value( 617 struct pvr2_v4l2_fh *fh = file->private_data;
693 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val); 618 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
694 if (ret) { 619 int val = 0;
695 ctls->error_idx = idx; 620 int ret;
696 break; 621
697 } 622 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
698 /* Ensure that if read as a 64 bit value, the user 623 &val);
699 will still get a hopefully sane value */ 624 vc->value = val;
700 ctrl->value64 = 0; 625 return ret;
701 ctrl->value = val; 626}
627
628static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
629{
630 struct pvr2_v4l2_fh *fh = file->private_data;
631 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
632
633 return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
634 vc->value);
635}
636
637static int pvr2_g_ext_ctrls(struct file *file, void *priv,
638 struct v4l2_ext_controls *ctls)
639{
640 struct pvr2_v4l2_fh *fh = file->private_data;
641 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
642 struct v4l2_ext_control *ctrl;
643 unsigned int idx;
644 int val;
645 int ret;
646
647 ret = 0;
648 for (idx = 0; idx < ctls->count; idx++) {
649 ctrl = ctls->controls + idx;
650 ret = pvr2_ctrl_get_value(
651 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
652 if (ret) {
653 ctls->error_idx = idx;
654 return ret;
702 } 655 }
703 break; 656 /* Ensure that if read as a 64 bit value, the user
657 will still get a hopefully sane value */
658 ctrl->value64 = 0;
659 ctrl->value = val;
704 } 660 }
661 return 0;
662}
705 663
706 case VIDIOC_S_EXT_CTRLS: 664static int pvr2_s_ext_ctrls(struct file *file, void *priv,
707 { 665 struct v4l2_ext_controls *ctls)
708 struct v4l2_ext_controls *ctls = 666{
709 (struct v4l2_ext_controls *)arg; 667 struct pvr2_v4l2_fh *fh = file->private_data;
710 struct v4l2_ext_control *ctrl; 668 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
711 unsigned int idx; 669 struct v4l2_ext_control *ctrl;
712 ret = 0; 670 unsigned int idx;
713 for (idx = 0; idx < ctls->count; idx++) { 671 int ret;
714 ctrl = ctls->controls + idx; 672
715 ret = pvr2_ctrl_set_value( 673 ret = 0;
716 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id), 674 for (idx = 0; idx < ctls->count; idx++) {
675 ctrl = ctls->controls + idx;
676 ret = pvr2_ctrl_set_value(
677 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
717 ctrl->value); 678 ctrl->value);
718 if (ret) { 679 if (ret) {
719 ctls->error_idx = idx; 680 ctls->error_idx = idx;
720 break; 681 return ret;
721 }
722 } 682 }
723 break;
724 } 683 }
684 return 0;
685}
725 686
726 case VIDIOC_TRY_EXT_CTRLS: 687static int pvr2_try_ext_ctrls(struct file *file, void *priv,
727 { 688 struct v4l2_ext_controls *ctls)
728 struct v4l2_ext_controls *ctls = 689{
729 (struct v4l2_ext_controls *)arg; 690 struct pvr2_v4l2_fh *fh = file->private_data;
730 struct v4l2_ext_control *ctrl; 691 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
731 struct pvr2_ctrl *pctl; 692 struct v4l2_ext_control *ctrl;
732 unsigned int idx; 693 struct pvr2_ctrl *pctl;
733 /* For the moment just validate that the requested control 694 unsigned int idx;
734 actually exists. */ 695 int ret;
735 ret = 0;
736 for (idx = 0; idx < ctls->count; idx++) {
737 ctrl = ctls->controls + idx;
738 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
739 if (!pctl) {
740 ret = -EINVAL;
741 ctls->error_idx = idx;
742 break;
743 }
744 }
745 break;
746 }
747 696
748 case VIDIOC_CROPCAP: 697 /* For the moment just validate that the requested control
749 { 698 actually exists. */
750 struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg; 699 ret = 0;
751 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 700 for (idx = 0; idx < ctls->count; idx++) {
752 ret = -EINVAL; 701 ctrl = ctls->controls + idx;
753 break; 702 pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
703 if (!pctl) {
704 ctls->error_idx = idx;
705 return -EINVAL;
754 } 706 }
755 ret = pvr2_hdw_get_cropcap(hdw, cap);
756 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
757 break;
758 } 707 }
759 case VIDIOC_G_CROP: 708 return 0;
760 { 709}
761 struct v4l2_crop *crop = (struct v4l2_crop *)arg; 710
762 int val = 0; 711static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
763 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 712{
764 ret = -EINVAL; 713 struct pvr2_v4l2_fh *fh = file->private_data;
765 break; 714 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
766 } 715 int ret;
767 ret = pvr2_ctrl_get_value( 716
717 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
718 return -EINVAL;
719 ret = pvr2_hdw_get_cropcap(hdw, cap);
720 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
721 return ret;
722}
723
724static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
725{
726 struct pvr2_v4l2_fh *fh = file->private_data;
727 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
728 int val = 0;
729 int ret;
730
731 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
732 return -EINVAL;
733 ret = pvr2_ctrl_get_value(
768 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val); 734 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
769 if (ret != 0) { 735 if (ret != 0)
770 ret = -EINVAL; 736 return -EINVAL;
771 break; 737 crop->c.left = val;
772 } 738 ret = pvr2_ctrl_get_value(
773 crop->c.left = val;
774 ret = pvr2_ctrl_get_value(
775 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val); 739 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
776 if (ret != 0) { 740 if (ret != 0)
777 ret = -EINVAL; 741 return -EINVAL;
778 break; 742 crop->c.top = val;
779 } 743 ret = pvr2_ctrl_get_value(
780 crop->c.top = val;
781 ret = pvr2_ctrl_get_value(
782 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val); 744 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
783 if (ret != 0) { 745 if (ret != 0)
784 ret = -EINVAL; 746 return -EINVAL;
785 break; 747 crop->c.width = val;
786 } 748 ret = pvr2_ctrl_get_value(
787 crop->c.width = val;
788 ret = pvr2_ctrl_get_value(
789 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val); 749 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
790 if (ret != 0) { 750 if (ret != 0)
791 ret = -EINVAL; 751 return -EINVAL;
792 break; 752 crop->c.height = val;
793 } 753 return 0;
794 crop->c.height = val; 754}
795 } 755
796 case VIDIOC_S_CROP: 756static int pvr2_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
797 { 757{
798 struct v4l2_crop *crop = (struct v4l2_crop *)arg; 758 struct pvr2_v4l2_fh *fh = file->private_data;
799 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 759 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
800 ret = -EINVAL; 760 struct v4l2_cropcap cap;
801 break; 761 int ret;
802 } 762
803 ret = pvr2_ctrl_set_value( 763 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
764 return -EINVAL;
765 cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
766 ret = pvr2_ctrl_set_value(
804 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), 767 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
805 crop->c.left); 768 crop->c.left);
806 if (ret != 0) { 769 if (ret != 0)
807 ret = -EINVAL; 770 return -EINVAL;
808 break; 771 ret = pvr2_ctrl_set_value(
809 }
810 ret = pvr2_ctrl_set_value(
811 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), 772 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
812 crop->c.top); 773 crop->c.top);
813 if (ret != 0) { 774 if (ret != 0)
814 ret = -EINVAL; 775 return -EINVAL;
815 break; 776 ret = pvr2_ctrl_set_value(
816 }
817 ret = pvr2_ctrl_set_value(
818 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), 777 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
819 crop->c.width); 778 crop->c.width);
820 if (ret != 0) { 779 if (ret != 0)
821 ret = -EINVAL; 780 return -EINVAL;
822 break; 781 ret = pvr2_ctrl_set_value(
823 }
824 ret = pvr2_ctrl_set_value(
825 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), 782 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
826 crop->c.height); 783 crop->c.height);
827 if (ret != 0) { 784 if (ret != 0)
828 ret = -EINVAL; 785 return -EINVAL;
829 break; 786 return 0;
830 } 787}
831 } 788
832 case VIDIOC_LOG_STATUS: 789static int pvr2_log_status(struct file *file, void *priv)
833 { 790{
834 pvr2_hdw_trigger_module_log(hdw); 791 struct pvr2_v4l2_fh *fh = file->private_data;
835 ret = 0; 792 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
836 break; 793
837 } 794 pvr2_hdw_trigger_module_log(hdw);
795 return 0;
796}
797
838#ifdef CONFIG_VIDEO_ADV_DEBUG 798#ifdef CONFIG_VIDEO_ADV_DEBUG
839 case VIDIOC_DBG_S_REGISTER: 799static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
840 case VIDIOC_DBG_G_REGISTER: 800{
841 { 801 struct pvr2_v4l2_fh *fh = file->private_data;
842 u64 val; 802 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
843 struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg; 803 u64 val;
844 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val; 804 int ret;
845 ret = pvr2_hdw_register_access(
846 hdw, &req->match, req->reg,
847 cmd == VIDIOC_DBG_S_REGISTER, &val);
848 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
849 break;
850 }
851#endif
852 805
853 default : 806 ret = pvr2_hdw_register_access(
854 ret = -ENOTTY; 807 hdw, &req->match, req->reg,
855 break; 808 0, &val);
856 } 809 req->val = val;
810 return ret;
811}
857 812
858 pvr2_hdw_commit_ctl(hdw); 813static int pvr2_s_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
814{
815 struct pvr2_v4l2_fh *fh = file->private_data;
816 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
817 u64 val;
818 int ret;
859 819
860 if (ret < 0) { 820 val = req->val;
861 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { 821 ret = pvr2_hdw_register_access(
862 pvr2_trace(PVR2_TRACE_V4LIOCTL, 822 hdw, &req->match, req->reg,
863 "pvr2_v4l2_do_ioctl failure, ret=%ld", ret); 823 1, &val);
864 } else {
865 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
866 pvr2_trace(PVR2_TRACE_V4LIOCTL,
867 "pvr2_v4l2_do_ioctl failure, ret=%ld"
868 " command was:", ret);
869 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
870 cmd);
871 }
872 }
873 } else {
874 pvr2_trace(PVR2_TRACE_V4LIOCTL,
875 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
876 ret, ret);
877 }
878 return ret; 824 return ret;
879} 825}
826#endif
827
828static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
829 .vidioc_querycap = pvr2_querycap,
830 .vidioc_g_priority = pvr2_g_priority,
831 .vidioc_s_priority = pvr2_s_priority,
832 .vidioc_s_audio = pvr2_s_audio,
833 .vidioc_g_audio = pvr2_g_audio,
834 .vidioc_enumaudio = pvr2_enumaudio,
835 .vidioc_enum_input = pvr2_enum_input,
836 .vidioc_cropcap = pvr2_cropcap,
837 .vidioc_s_crop = pvr2_s_crop,
838 .vidioc_g_crop = pvr2_g_crop,
839 .vidioc_g_input = pvr2_g_input,
840 .vidioc_s_input = pvr2_s_input,
841 .vidioc_g_frequency = pvr2_g_frequency,
842 .vidioc_s_frequency = pvr2_s_frequency,
843 .vidioc_s_tuner = pvr2_s_tuner,
844 .vidioc_g_tuner = pvr2_g_tuner,
845 .vidioc_g_std = pvr2_g_std,
846 .vidioc_s_std = pvr2_s_std,
847 .vidioc_log_status = pvr2_log_status,
848 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
849 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
850 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
851 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
852 .vidioc_streamon = pvr2_streamon,
853 .vidioc_streamoff = pvr2_streamoff,
854 .vidioc_queryctrl = pvr2_queryctrl,
855 .vidioc_querymenu = pvr2_querymenu,
856 .vidioc_g_ctrl = pvr2_g_ctrl,
857 .vidioc_s_ctrl = pvr2_s_ctrl,
858 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
859 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
860 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
861#ifdef CONFIG_VIDEO_ADV_DEBUG
862 .vidioc_g_register = pvr2_g_register,
863 .vidioc_s_register = pvr2_s_register,
864#endif
865};
880 866
881static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) 867static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
882{ 868{
@@ -959,7 +945,56 @@ static long pvr2_v4l2_ioctl(struct file *file,
959 unsigned int cmd, unsigned long arg) 945 unsigned int cmd, unsigned long arg)
960{ 946{
961 947
962 return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl); 948 struct pvr2_v4l2_fh *fh = file->private_data;
949 struct pvr2_v4l2 *vp = fh->vhead;
950 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
951 long ret = -EINVAL;
952
953 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
954 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
955
956 if (!pvr2_hdw_dev_ok(hdw)) {
957 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
958 "ioctl failed - bad or no context");
959 return -EFAULT;
960 }
961
962 /* check priority */
963 switch (cmd) {
964 case VIDIOC_S_CTRL:
965 case VIDIOC_S_STD:
966 case VIDIOC_S_INPUT:
967 case VIDIOC_S_TUNER:
968 case VIDIOC_S_FREQUENCY:
969 ret = v4l2_prio_check(&vp->prio, fh->prio);
970 if (ret)
971 return ret;
972 }
973
974 ret = video_ioctl2(file, cmd, arg);
975
976 pvr2_hdw_commit_ctl(hdw);
977
978 if (ret < 0) {
979 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
980 pvr2_trace(PVR2_TRACE_V4LIOCTL,
981 "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
982 } else {
983 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
984 pvr2_trace(PVR2_TRACE_V4LIOCTL,
985 "pvr2_v4l2_do_ioctl failure, ret=%ld"
986 " command was:", ret);
987 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
988 cmd);
989 }
990 }
991 } else {
992 pvr2_trace(PVR2_TRACE_V4LIOCTL,
993 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
994 ret, ret);
995 }
996 return ret;
997
963} 998}
964 999
965 1000
@@ -1298,6 +1333,11 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1298 1333
1299 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template)); 1334 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1300 dip->devbase.release = pvr2_video_device_release; 1335 dip->devbase.release = pvr2_video_device_release;
1336 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
1337 /* FIXME: tvnorms should be set to the set of supported standards
1338 by this device. Then video_ioctl2 will implement VIDIOC_ENUMSTD
1339 based on this field. */
1340 dip->devbase.tvnorms = V4L2_STD_ALL;
1301 1341
1302 mindevnum = -1; 1342 mindevnum = -1;
1303 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); 1343 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);