aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
diff options
context:
space:
mode:
authorPantelis Koukousoulas <pakt223@freemail.gr>2006-12-27 21:09:55 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2007-02-21 10:34:23 -0500
commitae2b9e25fdfb63efed3659b19c5cc8778fd981ba (patch)
treefbe27d954b42b17e9f663a95fc2433d897568f24 /drivers/media/video/pvrusb2/pvrusb2-v4l2.c
parent99cfdf5cc6dbe0bd748d810953874d4e08051a9f (diff)
V4L/DVB (5039): Pvrusb2: Implement /dev/radioX
The "main" V4L2 interface patch. This is yet very incomplete, incorrect and probably inappropriate for inclusion as-is, but at least with this I 'm able to tune and play radio through a V4L2 program (pvr-radio.c, a "thumb" version of ivtv-radio.c with just the essentials). Therefore, it kinda gives an idea of what is needed to support this, hm, interface (partly used also by e.g., kradio). Please point out any mistakes on this code. I 'm sure I 'm messing up some struct initialization somewhere but currently I 'm too lazy to actually think this through until I complete the functionality (e.g., handle the VIDIOC_S_STD, ENUMINPUT, etc ioctls appropriately). Signed-off-by: Pantelis Koukousoulas <pakt223@freemail.gr> Signed-off-by: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-v4l2.c')
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-v4l2.c83
1 files changed, 76 insertions, 7 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 02a541fbeff9..3cea6101e9f0 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -32,6 +32,8 @@
32#include <media/v4l2-dev.h> 32#include <media/v4l2-dev.h>
33#include <media/v4l2-common.h> 33#include <media/v4l2-common.h>
34 34
35#define PVR2_NR_STREAMS 3
36
35struct pvr2_v4l2_dev; 37struct pvr2_v4l2_dev;
36struct pvr2_v4l2_fh; 38struct pvr2_v4l2_fh;
37struct pvr2_v4l2; 39struct pvr2_v4l2;
@@ -77,7 +79,7 @@ static struct v4l2_capability pvr_capability ={
77 .bus_info = "usb", 79 .bus_info = "usb",
78 .version = KERNEL_VERSION(0,8,0), 80 .version = KERNEL_VERSION(0,8,0),
79 .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | 81 .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
80 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | 82 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
81 V4L2_CAP_READWRITE), 83 V4L2_CAP_READWRITE),
82 .reserved = {0,0,0,0} 84 .reserved = {0,0,0,0}
83}; 85};
@@ -784,6 +786,18 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file)
784 pvr2_ioread_destroy(fhp->rhp); 786 pvr2_ioread_destroy(fhp->rhp);
785 fhp->rhp = NULL; 787 fhp->rhp = NULL;
786 } 788 }
789
790 if (fhp->dev_info->config == pvr2_config_radio) {
791 int ret;
792 struct pvr2_hdw *hdw;
793 hdw = fhp->channel.mc_head->hdw;
794 if ((ret = pvr2_ctrl_set_value(
795 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
796 PVR2_CVAL_INPUT_TV))) {
797 return ret;
798 }
799 }
800
787 v4l2_prio_close(&vp->prio, &fhp->prio); 801 v4l2_prio_close(&vp->prio, &fhp->prio);
788 file->private_data = NULL; 802 file->private_data = NULL;
789 803
@@ -845,6 +859,32 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file)
845 pvr2_context_enter(vp->channel.mc_head); do { 859 pvr2_context_enter(vp->channel.mc_head); do {
846 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); 860 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
847 pvr2_channel_init(&fhp->channel,vp->channel.mc_head); 861 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
862
863 /* pk: warning, severe ugliness follows. 18+ only.
864 please blaim V4L(ivtv) for braindamaged interfaces,
865 not the implementor. This is probably flawed, but
866 suggestions on how to do this "right" are welcome! */
867 if (dip->config == pvr2_config_radio) {
868 int ret;
869 if ((pvr2_channel_check_stream_no_lock(&fhp->channel,
870 fhp->dev_info->stream)) != 0) {
871 /* We can 't switch modes while streaming */
872 pvr2_channel_done(&fhp->channel);
873 kfree(fhp);
874 pvr2_context_exit(vp->channel.mc_head);
875 return -EBUSY;
876 }
877
878 if ((ret = pvr2_ctrl_set_value(
879 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
880 PVR2_CVAL_INPUT_RADIO))) {
881 pvr2_channel_done(&fhp->channel);
882 kfree(fhp);
883 pvr2_context_exit(vp->channel.mc_head);
884 return ret;
885 }
886 }
887
848 fhp->vnext = NULL; 888 fhp->vnext = NULL;
849 fhp->vprev = vp->vlast; 889 fhp->vprev = vp->vlast;
850 if (vp->vlast) { 890 if (vp->vlast) {
@@ -942,6 +982,12 @@ static ssize_t pvr2_v4l2_read(struct file *file,
942 return tcnt; 982 return tcnt;
943 } 983 }
944 984
985 if (fh->dev_info->config == pvr2_config_radio) {
986 /* Radio device nodes on this device
987 cannot be read or written. */
988 return -EPERM;
989 }
990
945 if (!fh->rhp) { 991 if (!fh->rhp) {
946 ret = pvr2_v4l2_iosetup(fh); 992 ret = pvr2_v4l2_iosetup(fh);
947 if (ret) { 993 if (ret) {
@@ -976,6 +1022,12 @@ static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
976 return mask; 1022 return mask;
977 } 1023 }
978 1024
1025 if (fh->dev_info->config == pvr2_config_radio) {
1026 /* Radio device nodes on this device
1027 cannot be read or written. */
1028 return -EPERM;
1029 }
1030
979 if (!fh->rhp) { 1031 if (!fh->rhp) {
980 ret = pvr2_v4l2_iosetup(fh); 1032 ret = pvr2_v4l2_iosetup(fh);
981 if (ret) return POLLERR; 1033 if (ret) return POLLERR;
@@ -1044,7 +1096,8 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1044 return; 1096 return;
1045 } 1097 }
1046 1098
1047 if (!dip->stream) { 1099 /* radio device doesn 't need its own stream */
1100 if (!dip->stream && cfg != pvr2_config_radio) {
1048 err("Failed to set up pvrusb2 v4l dev" 1101 err("Failed to set up pvrusb2 v4l dev"
1049 " due to missing stream instance"); 1102 " due to missing stream instance");
1050 return; 1103 return;
@@ -1060,10 +1113,25 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1060 } 1113 }
1061 if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) && 1114 if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) &&
1062 (video_register_device(&dip->devbase, v4l_type, -1) < 0)) { 1115 (video_register_device(&dip->devbase, v4l_type, -1) < 0)) {
1063 err("Failed to register pvrusb2 v4l video device"); 1116 err("Failed to register pvrusb2 v4l device");
1064 } else { 1117 }
1118 switch (cfg) {
1119 case pvr2_config_mpeg:
1065 printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n", 1120 printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
1066 dip->devbase.minor,pvr2_config_get_name(dip->config)); 1121 dip->devbase.minor,pvr2_config_get_name(dip->config));
1122 break;
1123 case pvr2_config_vbi:
1124 printk(KERN_INFO "pvrusb2: registered device vbi%d [%s]\n",
1125 dip->devbase.minor - MINOR_VFL_TYPE_VBI_MIN,
1126 pvr2_config_get_name(dip->config));
1127 break;
1128 case pvr2_config_radio:
1129 printk(KERN_INFO "pvrusb2: registered device radio%d [%s]\n",
1130 dip->devbase.minor - MINOR_VFL_TYPE_RADIO_MIN,
1131 pvr2_config_get_name(dip->config));
1132 break;
1133 default:
1134 break;
1067 } 1135 }
1068 1136
1069 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, 1137 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
@@ -1078,19 +1146,20 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1078 vp = kmalloc(sizeof(*vp),GFP_KERNEL); 1146 vp = kmalloc(sizeof(*vp),GFP_KERNEL);
1079 if (!vp) return vp; 1147 if (!vp) return vp;
1080 memset(vp,0,sizeof(*vp)); 1148 memset(vp,0,sizeof(*vp));
1081 vp->vdev = kmalloc(sizeof(*vp->vdev),GFP_KERNEL); 1149 vp->vdev = kmalloc(sizeof(*vp->vdev)*PVR2_NR_STREAMS,GFP_KERNEL);
1082 if (!vp->vdev) { 1150 if (!vp->vdev) {
1083 kfree(vp); 1151 kfree(vp);
1084 return NULL; 1152 return NULL;
1085 } 1153 }
1086 memset(vp->vdev,0,sizeof(*vp->vdev)); 1154 memset(vp->vdev,0,sizeof(*vp->vdev)*PVR2_NR_STREAMS);
1087 pvr2_channel_init(&vp->channel,mnp); 1155 pvr2_channel_init(&vp->channel,mnp);
1088 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); 1156 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1089 1157
1090 vp->channel.check_func = pvr2_v4l2_internal_check; 1158 vp->channel.check_func = pvr2_v4l2_internal_check;
1091 1159
1092 /* register streams */ 1160 /* register streams */
1093 pvr2_v4l2_dev_init(vp->vdev,vp,pvr2_config_mpeg); 1161 pvr2_v4l2_dev_init(&vp->vdev[0],vp,pvr2_config_mpeg);
1162 pvr2_v4l2_dev_init(&vp->vdev[2],vp,pvr2_config_radio);
1094 1163
1095 return vp; 1164 return vp;
1096} 1165}