uvc_v4l2_subscribe_event(struct v4l2_fh *fh,
                         const struct v4l2_event_subscription *sub)
 {
+       struct uvc_device *uvc = video_get_drvdata(fh->vdev);
+       struct uvc_file_handle *handle = to_uvc_file_handle(fh);
+       int ret;
+
        if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
                return -EINVAL;
 
-       return v4l2_event_subscribe(fh, sub, 2, NULL);
+       if (sub->type == UVC_EVENT_SETUP && uvc->func_connected)
+               return -EBUSY;
+
+       ret = v4l2_event_subscribe(fh, sub, 2, NULL);
+       if (ret < 0)
+               return ret;
+
+       if (sub->type == UVC_EVENT_SETUP) {
+               uvc->func_connected = true;
+               handle->is_uvc_app_handle = true;
+               uvc_function_connect(uvc);
+       }
+
+       return 0;
+}
+
+static void uvc_v4l2_disable(struct uvc_device *uvc)
+{
+       uvc->func_connected = false;
+       uvc_function_disconnect(uvc);
+       uvcg_video_enable(&uvc->video, 0);
+       uvcg_free_buffers(&uvc->video.queue);
 }
 
 static int
 uvc_v4l2_unsubscribe_event(struct v4l2_fh *fh,
                           const struct v4l2_event_subscription *sub)
 {
-       return v4l2_event_unsubscribe(fh, sub);
+       struct uvc_device *uvc = video_get_drvdata(fh->vdev);
+       struct uvc_file_handle *handle = to_uvc_file_handle(fh);
+       int ret;
+
+       ret = v4l2_event_unsubscribe(fh, sub);
+       if (ret < 0)
+               return ret;
+
+       if (sub->type == UVC_EVENT_SETUP && handle->is_uvc_app_handle) {
+               uvc_v4l2_disable(uvc);
+               handle->is_uvc_app_handle = false;
+       }
+
+       return 0;
 }
 
 static long
        handle->device = &uvc->video;
        file->private_data = &handle->vfh;
 
-       uvc_function_connect(uvc);
        return 0;
 }
 
        struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
        struct uvc_video *video = handle->device;
 
-       uvc_function_disconnect(uvc);
-
        mutex_lock(&video->mutex);
-       uvcg_video_enable(video, 0);
-       uvcg_free_buffers(&video->queue);
+       if (handle->is_uvc_app_handle)
+               uvc_v4l2_disable(uvc);
        mutex_unlock(&video->mutex);
 
        file->private_data = NULL;