aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}