diff options
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 83 |
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 | |||
35 | struct pvr2_v4l2_dev; | 37 | struct pvr2_v4l2_dev; |
36 | struct pvr2_v4l2_fh; | 38 | struct pvr2_v4l2_fh; |
37 | struct pvr2_v4l2; | 39 | struct 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 | } |