diff options
author | Ezequiel GarcĂa <elezegarcia@gmail.com> | 2012-02-24 09:24:14 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-15 07:53:46 -0400 |
commit | ab019fd41d993911ba32db0204bb1233682705ee (patch) | |
tree | 1635ffc06f9ca904be58fbec5e55c5b579b85b6e /drivers | |
parent | ad3537b56742848743aa11d42ccc1d336682bd5b (diff) |
[media] staging: easycap: Split device struct alloc and retrieval code
When the device is probed a driver struct is either
allocated or retrieved.
This operation is logically splitted in several functions.
Signed-off-by: Ezequiel Garcia <elezegarcia@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/media/easycap/easycap_main.c | 384 |
1 files changed, 216 insertions, 168 deletions
diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c index d0fe34afc2e5..c4198be6344c 100644 --- a/drivers/staging/media/easycap/easycap_main.c +++ b/drivers/staging/media/easycap/easycap_main.c | |||
@@ -2842,6 +2842,209 @@ static void easycap_complete(struct urb *purb) | |||
2842 | return; | 2842 | return; |
2843 | } | 2843 | } |
2844 | 2844 | ||
2845 | static struct easycap *alloc_easycap(u8 bInterfaceNumber) | ||
2846 | { | ||
2847 | struct easycap *peasycap; | ||
2848 | int i; | ||
2849 | |||
2850 | peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL); | ||
2851 | if (!peasycap) { | ||
2852 | SAY("ERROR: Could not allocate peasycap\n"); | ||
2853 | return NULL; | ||
2854 | } | ||
2855 | |||
2856 | if (mutex_lock_interruptible(&mutex_dongle)) { | ||
2857 | SAY("ERROR: cannot lock mutex_dongle\n"); | ||
2858 | kfree(peasycap); | ||
2859 | return NULL; | ||
2860 | } | ||
2861 | |||
2862 | /* Find a free dongle in easycapdc60_dongle array */ | ||
2863 | for (i = 0; i < DONGLE_MANY; i++) { | ||
2864 | |||
2865 | if ((!easycapdc60_dongle[i].peasycap) && | ||
2866 | (!mutex_is_locked(&easycapdc60_dongle[i].mutex_video)) && | ||
2867 | (!mutex_is_locked(&easycapdc60_dongle[i].mutex_audio))) { | ||
2868 | |||
2869 | easycapdc60_dongle[i].peasycap = peasycap; | ||
2870 | peasycap->isdongle = i; | ||
2871 | JOM(8, "intf[%i]: peasycap-->easycap" | ||
2872 | "_dongle[%i].peasycap\n", | ||
2873 | bInterfaceNumber, i); | ||
2874 | break; | ||
2875 | } | ||
2876 | } | ||
2877 | |||
2878 | mutex_unlock(&mutex_dongle); | ||
2879 | |||
2880 | if (i >= DONGLE_MANY) { | ||
2881 | SAM("ERROR: too many dongles\n"); | ||
2882 | kfree(peasycap); | ||
2883 | return NULL; | ||
2884 | } | ||
2885 | |||
2886 | return peasycap; | ||
2887 | } | ||
2888 | |||
2889 | /* | ||
2890 | * FIXME: Identify the appropriate pointer peasycap for interfaces | ||
2891 | * 1 and 2. The address of peasycap->pusb_device is reluctantly used | ||
2892 | * for this purpose. | ||
2893 | */ | ||
2894 | static struct easycap *get_easycap(struct usb_device *usbdev, | ||
2895 | u8 bInterfaceNumber) | ||
2896 | { | ||
2897 | int i; | ||
2898 | struct easycap *peasycap; | ||
2899 | |||
2900 | for (i = 0; i < DONGLE_MANY; i++) { | ||
2901 | if (easycapdc60_dongle[i].peasycap->pusb_device == usbdev) { | ||
2902 | peasycap = easycapdc60_dongle[i].peasycap; | ||
2903 | JOT(8, "intf[%i]: dongle[%i].peasycap\n", | ||
2904 | bInterfaceNumber, i); | ||
2905 | break; | ||
2906 | } | ||
2907 | } | ||
2908 | if (i >= DONGLE_MANY) { | ||
2909 | SAY("ERROR: peasycap is unknown when probing interface %i\n", | ||
2910 | bInterfaceNumber); | ||
2911 | return NULL; | ||
2912 | } | ||
2913 | if (!peasycap) { | ||
2914 | SAY("ERROR: peasycap is NULL when probing interface %i\n", | ||
2915 | bInterfaceNumber); | ||
2916 | return NULL; | ||
2917 | } | ||
2918 | |||
2919 | return peasycap; | ||
2920 | } | ||
2921 | |||
2922 | static void init_easycap(struct easycap *peasycap, | ||
2923 | struct usb_device *usbdev, | ||
2924 | struct usb_interface *intf, | ||
2925 | u8 bInterfaceNumber) | ||
2926 | { | ||
2927 | /* Save usb_device and usb_interface */ | ||
2928 | peasycap->pusb_device = usbdev; | ||
2929 | peasycap->pusb_interface = intf; | ||
2930 | |||
2931 | peasycap->minor = -1; | ||
2932 | kref_init(&peasycap->kref); | ||
2933 | JOM(8, "intf[%i]: after kref_init(..._video) " | ||
2934 | "%i=peasycap->kref.refcount.counter\n", | ||
2935 | bInterfaceNumber, peasycap->kref.refcount.counter); | ||
2936 | |||
2937 | /* module params */ | ||
2938 | peasycap->gain = (s8)clamp(easycap_gain, 0, 31); | ||
2939 | |||
2940 | init_waitqueue_head(&peasycap->wq_video); | ||
2941 | init_waitqueue_head(&peasycap->wq_audio); | ||
2942 | init_waitqueue_head(&peasycap->wq_trigger); | ||
2943 | |||
2944 | peasycap->allocation_video_struct = sizeof(struct easycap); | ||
2945 | |||
2946 | peasycap->microphone = false; | ||
2947 | |||
2948 | peasycap->video_interface = -1; | ||
2949 | peasycap->video_altsetting_on = -1; | ||
2950 | peasycap->video_altsetting_off = -1; | ||
2951 | peasycap->video_endpointnumber = -1; | ||
2952 | peasycap->video_isoc_maxframesize = -1; | ||
2953 | peasycap->video_isoc_buffer_size = -1; | ||
2954 | |||
2955 | peasycap->audio_interface = -1; | ||
2956 | peasycap->audio_altsetting_on = -1; | ||
2957 | peasycap->audio_altsetting_off = -1; | ||
2958 | peasycap->audio_endpointnumber = -1; | ||
2959 | peasycap->audio_isoc_maxframesize = -1; | ||
2960 | peasycap->audio_isoc_buffer_size = -1; | ||
2961 | |||
2962 | peasycap->frame_buffer_many = FRAME_BUFFER_MANY; | ||
2963 | } | ||
2964 | |||
2965 | static int populate_inputset(struct easycap *peasycap) | ||
2966 | { | ||
2967 | struct inputset *inputset; | ||
2968 | struct easycap_format *peasycap_format; | ||
2969 | struct v4l2_pix_format *pix; | ||
2970 | int m, i, k, mask, fmtidx; | ||
2971 | s32 value; | ||
2972 | |||
2973 | inputset = peasycap->inputset; | ||
2974 | |||
2975 | /* FIXME: peasycap->ntsc is not yet initialized */ | ||
2976 | fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN; | ||
2977 | |||
2978 | m = 0; | ||
2979 | mask = 0; | ||
2980 | for (i = 0; easycap_standard[i].mask != 0xffff; i++) { | ||
2981 | if (fmtidx == easycap_standard[i].v4l2_standard.index) { | ||
2982 | m++; | ||
2983 | for (k = 0; k < INPUT_MANY; k++) | ||
2984 | inputset[k].standard_offset = i; | ||
2985 | mask = easycap_standard[i].mask; | ||
2986 | } | ||
2987 | } | ||
2988 | |||
2989 | if (m != 1) { | ||
2990 | SAM("ERROR: inputset->standard_offset unpopulated, %i=m\n", m); | ||
2991 | return -ENOENT; | ||
2992 | } | ||
2993 | |||
2994 | peasycap_format = &easycap_format[0]; | ||
2995 | m = 0; | ||
2996 | for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) { | ||
2997 | pix = &peasycap_format->v4l2_format.fmt.pix; | ||
2998 | if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) | ||
2999 | && pix->field == V4L2_FIELD_NONE | ||
3000 | && pix->pixelformat == V4L2_PIX_FMT_UYVY | ||
3001 | && pix->width == 640 && pix->height == 480) { | ||
3002 | m++; | ||
3003 | for (k = 0; k < INPUT_MANY; k++) | ||
3004 | inputset[k].format_offset = i; | ||
3005 | break; | ||
3006 | } | ||
3007 | peasycap_format++; | ||
3008 | } | ||
3009 | if (m != 1) { | ||
3010 | SAM("ERROR: inputset[]->format_offset unpopulated\n"); | ||
3011 | return -ENOENT; | ||
3012 | } | ||
3013 | |||
3014 | m = 0; | ||
3015 | for (i = 0; easycap_control[i].id != 0xffffffff; i++) { | ||
3016 | value = easycap_control[i].default_value; | ||
3017 | if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) { | ||
3018 | m++; | ||
3019 | for (k = 0; k < INPUT_MANY; k++) | ||
3020 | inputset[k].brightness = value; | ||
3021 | } else if (V4L2_CID_CONTRAST == easycap_control[i].id) { | ||
3022 | m++; | ||
3023 | for (k = 0; k < INPUT_MANY; k++) | ||
3024 | inputset[k].contrast = value; | ||
3025 | } else if (V4L2_CID_SATURATION == easycap_control[i].id) { | ||
3026 | m++; | ||
3027 | for (k = 0; k < INPUT_MANY; k++) | ||
3028 | inputset[k].saturation = value; | ||
3029 | } else if (V4L2_CID_HUE == easycap_control[i].id) { | ||
3030 | m++; | ||
3031 | for (k = 0; k < INPUT_MANY; k++) | ||
3032 | inputset[k].hue = value; | ||
3033 | } | ||
3034 | } | ||
3035 | |||
3036 | if (m != 4) { | ||
3037 | SAM("ERROR: inputset[]->brightness underpopulated\n"); | ||
3038 | return -ENOENT; | ||
3039 | } | ||
3040 | |||
3041 | for (k = 0; k < INPUT_MANY; k++) | ||
3042 | inputset[k].input = k; | ||
3043 | JOM(4, "populated inputset[]\n"); | ||
3044 | |||
3045 | return 0; | ||
3046 | } | ||
3047 | |||
2845 | static const struct v4l2_file_operations v4l2_fops = { | 3048 | static const struct v4l2_file_operations v4l2_fops = { |
2846 | .owner = THIS_MODULE, | 3049 | .owner = THIS_MODULE, |
2847 | .open = easycap_open_noinode, | 3050 | .open = easycap_open_noinode, |
@@ -2863,7 +3066,6 @@ static int easycap_usb_probe(struct usb_interface *intf, | |||
2863 | struct usb_interface_descriptor *interface; | 3066 | struct usb_interface_descriptor *interface; |
2864 | struct urb *purb; | 3067 | struct urb *purb; |
2865 | struct easycap *peasycap; | 3068 | struct easycap *peasycap; |
2866 | int ndong; | ||
2867 | struct data_urb *pdata_urb; | 3069 | struct data_urb *pdata_urb; |
2868 | int i, j, k, m, rc; | 3070 | int i, j, k, m, rc; |
2869 | u8 bInterfaceNumber; | 3071 | u8 bInterfaceNumber; |
@@ -2874,11 +3076,6 @@ static int easycap_usb_probe(struct usb_interface *intf, | |||
2874 | int okepn[8]; | 3076 | int okepn[8]; |
2875 | int okmps[8]; | 3077 | int okmps[8]; |
2876 | int maxpacketsize; | 3078 | int maxpacketsize; |
2877 | u16 mask; | ||
2878 | s32 value; | ||
2879 | struct easycap_format *peasycap_format; | ||
2880 | int fmtidx; | ||
2881 | struct inputset *inputset; | ||
2882 | 3079 | ||
2883 | usbdev = interface_to_usbdev(intf); | 3080 | usbdev = interface_to_usbdev(intf); |
2884 | 3081 | ||
@@ -2916,76 +3113,16 @@ static int easycap_usb_probe(struct usb_interface *intf, | |||
2916 | * interfaces 1 and 2 are probed. | 3113 | * interfaces 1 and 2 are probed. |
2917 | */ | 3114 | */ |
2918 | if (0 == bInterfaceNumber) { | 3115 | if (0 == bInterfaceNumber) { |
2919 | peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL); | 3116 | /* |
2920 | if (!peasycap) { | 3117 | * Alloc structure and save it in a free slot in |
2921 | SAY("ERROR: Could not allocate peasycap\n"); | 3118 | * easycapdc60_dongle array |
2922 | return -ENOMEM; | 3119 | */ |
2923 | } | 3120 | peasycap = alloc_easycap(bInterfaceNumber); |
2924 | 3121 | if (!peasycap) | |
2925 | /* Perform urgent initializations */ | ||
2926 | peasycap->minor = -1; | ||
2927 | kref_init(&peasycap->kref); | ||
2928 | JOM(8, "intf[%i]: after kref_init(..._video) " | ||
2929 | "%i=peasycap->kref.refcount.counter\n", | ||
2930 | bInterfaceNumber, peasycap->kref.refcount.counter); | ||
2931 | |||
2932 | /* module params */ | ||
2933 | peasycap->gain = (s8)clamp(easycap_gain, 0, 31); | ||
2934 | |||
2935 | init_waitqueue_head(&peasycap->wq_video); | ||
2936 | init_waitqueue_head(&peasycap->wq_audio); | ||
2937 | init_waitqueue_head(&peasycap->wq_trigger); | ||
2938 | |||
2939 | if (mutex_lock_interruptible(&mutex_dongle)) { | ||
2940 | SAY("ERROR: cannot down mutex_dongle\n"); | ||
2941 | return -ERESTARTSYS; | ||
2942 | } | ||
2943 | |||
2944 | for (ndong = 0; ndong < DONGLE_MANY; ndong++) { | ||
2945 | if ((!easycapdc60_dongle[ndong].peasycap) && | ||
2946 | (!mutex_is_locked(&easycapdc60_dongle | ||
2947 | [ndong].mutex_video)) && | ||
2948 | (!mutex_is_locked(&easycapdc60_dongle | ||
2949 | [ndong].mutex_audio))) { | ||
2950 | easycapdc60_dongle[ndong].peasycap = peasycap; | ||
2951 | peasycap->isdongle = ndong; | ||
2952 | JOM(8, "intf[%i]: peasycap-->easycap" | ||
2953 | "_dongle[%i].peasycap\n", | ||
2954 | bInterfaceNumber, ndong); | ||
2955 | break; | ||
2956 | } | ||
2957 | } | ||
2958 | |||
2959 | if (DONGLE_MANY <= ndong) { | ||
2960 | SAM("ERROR: too many dongles\n"); | ||
2961 | mutex_unlock(&mutex_dongle); | ||
2962 | return -ENOMEM; | 3122 | return -ENOMEM; |
2963 | } | ||
2964 | mutex_unlock(&mutex_dongle); | ||
2965 | 3123 | ||
2966 | peasycap->allocation_video_struct = sizeof(struct easycap); | 3124 | /* Perform basic struct initialization */ |
2967 | 3125 | init_easycap(peasycap, usbdev, intf, bInterfaceNumber); | |
2968 | /* and further initialize the structure */ | ||
2969 | peasycap->pusb_device = usbdev; | ||
2970 | peasycap->pusb_interface = intf; | ||
2971 | |||
2972 | peasycap->microphone = false; | ||
2973 | |||
2974 | peasycap->video_interface = -1; | ||
2975 | peasycap->video_altsetting_on = -1; | ||
2976 | peasycap->video_altsetting_off = -1; | ||
2977 | peasycap->video_endpointnumber = -1; | ||
2978 | peasycap->video_isoc_maxframesize = -1; | ||
2979 | peasycap->video_isoc_buffer_size = -1; | ||
2980 | |||
2981 | peasycap->audio_interface = -1; | ||
2982 | peasycap->audio_altsetting_on = -1; | ||
2983 | peasycap->audio_altsetting_off = -1; | ||
2984 | peasycap->audio_endpointnumber = -1; | ||
2985 | peasycap->audio_isoc_maxframesize = -1; | ||
2986 | peasycap->audio_isoc_buffer_size = -1; | ||
2987 | |||
2988 | peasycap->frame_buffer_many = FRAME_BUFFER_MANY; | ||
2989 | 3126 | ||
2990 | /* Dynamically fill in the available formats */ | 3127 | /* Dynamically fill in the available formats */ |
2991 | rc = easycap_video_fillin_formats(); | 3128 | rc = easycap_video_fillin_formats(); |
@@ -2996,103 +3133,14 @@ static int easycap_usb_probe(struct usb_interface *intf, | |||
2996 | JOM(4, "%i formats available\n", rc); | 3133 | JOM(4, "%i formats available\n", rc); |
2997 | 3134 | ||
2998 | /* Populate easycap.inputset[] */ | 3135 | /* Populate easycap.inputset[] */ |
2999 | inputset = peasycap->inputset; | 3136 | rc = populate_inputset(peasycap); |
3000 | fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN; | 3137 | if (rc < 0) |
3001 | m = 0; | 3138 | return rc; |
3002 | mask = 0; | ||
3003 | for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) { | ||
3004 | if (fmtidx == easycap_standard[i].v4l2_standard.index) { | ||
3005 | m++; | ||
3006 | for (k = 0; k < INPUT_MANY; k++) | ||
3007 | inputset[k].standard_offset = i; | ||
3008 | |||
3009 | mask = easycap_standard[i].mask; | ||
3010 | } | ||
3011 | } | ||
3012 | if (1 != m) { | ||
3013 | SAM("ERROR: " | ||
3014 | "inputset->standard_offset unpopulated, %i=m\n", m); | ||
3015 | return -ENOENT; | ||
3016 | } | ||
3017 | |||
3018 | peasycap_format = &easycap_format[0]; | ||
3019 | m = 0; | ||
3020 | for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) { | ||
3021 | struct v4l2_pix_format *pix = | ||
3022 | &peasycap_format->v4l2_format.fmt.pix; | ||
3023 | if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && | ||
3024 | pix->field == V4L2_FIELD_NONE && | ||
3025 | pix->pixelformat == V4L2_PIX_FMT_UYVY && | ||
3026 | pix->width == 640 && pix->height == 480) { | ||
3027 | m++; | ||
3028 | for (k = 0; k < INPUT_MANY; k++) | ||
3029 | inputset[k].format_offset = i; | ||
3030 | break; | ||
3031 | } | ||
3032 | peasycap_format++; | ||
3033 | } | ||
3034 | if (1 != m) { | ||
3035 | SAM("ERROR: inputset[]->format_offset unpopulated\n"); | ||
3036 | return -ENOENT; | ||
3037 | } | ||
3038 | |||
3039 | m = 0; | ||
3040 | for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) { | ||
3041 | value = easycap_control[i].default_value; | ||
3042 | if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) { | ||
3043 | m++; | ||
3044 | for (k = 0; k < INPUT_MANY; k++) | ||
3045 | inputset[k].brightness = value; | ||
3046 | } else if (V4L2_CID_CONTRAST == easycap_control[i].id) { | ||
3047 | m++; | ||
3048 | for (k = 0; k < INPUT_MANY; k++) | ||
3049 | inputset[k].contrast = value; | ||
3050 | } else if (V4L2_CID_SATURATION == easycap_control[i].id) { | ||
3051 | m++; | ||
3052 | for (k = 0; k < INPUT_MANY; k++) | ||
3053 | inputset[k].saturation = value; | ||
3054 | } else if (V4L2_CID_HUE == easycap_control[i].id) { | ||
3055 | m++; | ||
3056 | for (k = 0; k < INPUT_MANY; k++) | ||
3057 | inputset[k].hue = value; | ||
3058 | } | ||
3059 | } | ||
3060 | |||
3061 | if (4 != m) { | ||
3062 | SAM("ERROR: inputset[]->brightness underpopulated\n"); | ||
3063 | return -ENOENT; | ||
3064 | } | ||
3065 | for (k = 0; k < INPUT_MANY; k++) | ||
3066 | inputset[k].input = k; | ||
3067 | JOM(4, "populated inputset[]\n"); | ||
3068 | JOM(4, "finished initialization\n"); | 3139 | JOM(4, "finished initialization\n"); |
3069 | } else { | 3140 | } else { |
3070 | 3141 | peasycap = get_easycap(usbdev, bInterfaceNumber); | |
3071 | /* | 3142 | if (!peasycap) |
3072 | * FIXME: Identify the appropriate pointer | ||
3073 | * peasycap for interfaces 1 and 2. | ||
3074 | * The address of peasycap->pusb_device | ||
3075 | * is reluctantly used for this purpose. | ||
3076 | */ | ||
3077 | for (ndong = 0; ndong < DONGLE_MANY; ndong++) { | ||
3078 | if (usbdev == easycapdc60_dongle[ndong].peasycap-> | ||
3079 | pusb_device) { | ||
3080 | peasycap = easycapdc60_dongle[ndong].peasycap; | ||
3081 | JOT(8, "intf[%i]: dongle[%i].peasycap\n", | ||
3082 | bInterfaceNumber, ndong); | ||
3083 | break; | ||
3084 | } | ||
3085 | } | ||
3086 | if (DONGLE_MANY <= ndong) { | ||
3087 | SAY("ERROR: peasycap is unknown when probing interface %i\n", | ||
3088 | bInterfaceNumber); | ||
3089 | return -ENODEV; | 3143 | return -ENODEV; |
3090 | } | ||
3091 | if (!peasycap) { | ||
3092 | SAY("ERROR: peasycap is NULL when probing interface %i\n", | ||
3093 | bInterfaceNumber); | ||
3094 | return -ENODEV; | ||
3095 | } | ||
3096 | } | 3144 | } |
3097 | 3145 | ||
3098 | if ((USB_CLASS_VIDEO == bInterfaceClass) || | 3146 | if ((USB_CLASS_VIDEO == bInterfaceClass) || |