*参照元 [#t5697c57] #backlinks *説明 [#b35adc3c] -パス: [[linux-4.4.1/drivers/media/v4l2-core/v4l2-dev.c]] -FIXME: これは何? --説明 **引数 [#qc7e1a50] -struct video_device *vdev -- --[[linux-4.4.1/video_device]] -int type -- -int nr -- -int warn_if_nr_in_use -- -struct module *owner -- --[[linux-4.4.1/module]] **返り値 [#k112e223] -int -- **参考 [#jc90176e] *実装 [#u3770485] /** * __video_register_device - register video4linux devices * @vdev: video device structure we want to register * @type: type of device to register * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ... * -1 == first free) * @warn_if_nr_in_use: warn if the desired device node number * was already in use and another number was chosen instead. * @owner: module that owns the video device node * * The registration code assigns minor numbers and device node numbers * based on the requested type and registers the new device node with * the kernel. * * This function assumes that struct video_device was zeroed when it * was allocated and does not contain any stale date. * * An error is returned if no free minor or device node number could be * found, or if the registration of the device node failed. * * Zero is returned on success. * * Valid types are * * %VFL_TYPE_GRABBER - A frame grabber * * %VFL_TYPE_VBI - Vertical blank data (undecoded) * * %VFL_TYPE_RADIO - A radio card * * %VFL_TYPE_SUBDEV - A subdevice * * %VFL_TYPE_SDR - Software Defined Radio */ int __video_register_device(struct video_device *vdev, int type, int nr, int warn_if_nr_in_use, struct module *owner) { int i = 0; int ret; int minor_offset = 0; int minor_cnt = VIDEO_NUM_DEVICES; const char *name_base; - --[[linux-4.4.1/VIDEO_NUM_DEVICES]] /* A minor value of -1 marks this video device as never having been registered */ vdev->minor = -1; /* the release callback MUST be present */ if (WARN_ON(!vdev->release)) return -EINVAL; /* the v4l2_dev pointer MUST be present */ if (WARN_ON(!vdev->v4l2_dev)) return -EINVAL; - --[[linux-4.4.1/WARN_ON()]] /* v4l2_fh support */ spin_lock_init(&vdev->fh_lock); INIT_LIST_HEAD(&vdev->fh_list); - --[[linux-4.4.1/spin_lock_init()]] --[[linux-4.4.1/INIT_LIST_HEAD()]] /* Part 1: check device type */ switch (type) { case VFL_TYPE_GRABBER: name_base = "video"; break; case VFL_TYPE_VBI: name_base = "vbi"; break; case VFL_TYPE_RADIO: name_base = "radio"; break; case VFL_TYPE_SUBDEV: name_base = "v4l-subdev"; break; case VFL_TYPE_SDR: /* Use device name 'swradio' because 'sdr' was already taken. */ name_base = "swradio"; break; default: printk(KERN_ERR "%s called with unknown type: %d\n", __func__, type); return -EINVAL; } - --[[linux-4.4.1/printk()]] vdev->vfl_type = type; vdev->cdev = NULL; if (vdev->dev_parent == NULL) vdev->dev_parent = vdev->v4l2_dev->dev; if (vdev->ctrl_handler == NULL) vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; /* If the prio state pointer is NULL, then use the v4l2_device prio state. */ if (vdev->prio == NULL) vdev->prio = &vdev->v4l2_dev->prio; - --vdev->v4l2_dev は struct v4l2_device * 型 --[[linux-4.4.1/v4l2_device]] /* Part 2: find a free minor, device node number and device index. */ #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES /* Keep the ranges for the first four types for historical * reasons. * Newer devices (not yet in place) should use the range * of 128-191 and just pick the first free minor there * (new style). */ switch (type) { case VFL_TYPE_GRABBER: minor_offset = 0; minor_cnt = 64; break; case VFL_TYPE_RADIO: minor_offset = 64; minor_cnt = 64; break; case VFL_TYPE_VBI: minor_offset = 224; minor_cnt = 32; break; default: minor_offset = 128; minor_cnt = 64; break; } #endif /* Pick a device node number */ mutex_lock(&videodev_lock); - --[[linux-4.4.1/mutex_lock()]] --[[linux-4.4.1/videodev_lock(global)]] nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt); if (nr == minor_cnt) nr = devnode_find(vdev, 0, minor_cnt); - --[[linux-4.4.1/devnode_find()]] if (nr == minor_cnt) { printk(KERN_ERR "could not get a free device node number\n"); mutex_unlock(&videodev_lock); return -ENFILE; } - --[[linux-4.4.1/mutex_unlock()]] #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES /* 1-on-1 mapping of device node number to minor number */ i = nr; #else /* The device node number and minor numbers are independent, so we just find the first free minor number. */ for (i = 0; i < VIDEO_NUM_DEVICES; i++) if (video_device[i] == NULL) break; if (i == VIDEO_NUM_DEVICES) { mutex_unlock(&videodev_lock); printk(KERN_ERR "could not get a free minor\n"); return -ENFILE; } #endif vdev->minor = i + minor_offset; vdev->num = nr; devnode_set(vdev); - --[[linux-4.4.1/devnode_set()]] /* Should not happen since we thought this minor was free */ WARN_ON(video_device[vdev->minor] != NULL); vdev->index = get_index(vdev); video_device[vdev->minor] = vdev; mutex_unlock(&videodev_lock); if (vdev->ioctl_ops) determine_valid_ioctls(vdev); - --[[linux-4.4.1/video_device(global)]] --[[linux-4.4.1/get_index()]] --[[linux-4.4.1/determine_valid_ioctls()]] /* Part 3: Initialize the character device */ vdev->cdev = cdev_alloc(); if (vdev->cdev == NULL) { ret = -ENOMEM; goto cleanup; } - --vdev->cdev は struct cdev * 型 --[[linux-4.4.1/cdev]] --[[linux-4.4.1/cdev_alloc()]] vdev->cdev->ops = &v4l2_fops; vdev->cdev->owner = owner; - --[[linux-4.4.1/v4l2_fops(global)]] ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); if (ret < 0) { printk(KERN_ERR "%s: cdev_add failed\n", __func__); kfree(vdev->cdev); vdev->cdev = NULL; goto cleanup; } - --[[linux-4.4.1/cdev_add()]] --[[linux-4.4.1/MKDEV()]] --[[linux-4.4.1/kfree()]] /* Part 4: register the device with sysfs */ vdev->dev.class = &video_class; vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor); vdev->dev.parent = vdev->dev_parent; dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); - --vdev->dev_parent は struct device * 型 --[[linux-4.4.1/device]] --[[linux-4.4.1/video_class(global)]] --[[linux-4.4.1/dev_set_name()]] ret = device_register(&vdev->dev); if (ret < 0) { printk(KERN_ERR "%s: device_register failed\n", __func__); goto cleanup; } /* Register the release callback that will be called when the last reference to the device goes away. */ vdev->dev.release = v4l2_device_release; - --[[linux-4.4.1/device_register()]] --[[linux-4.4.1/v4l2_device_release()]] if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__, name_base, nr, video_device_node_name(vdev)); /* Increase v4l2_device refcount */ v4l2_device_get(vdev->v4l2_dev); - --[[linux-4.4.1/video_device_node_name()]] --[[linux-4.4.1/v4l2_device_get()]] #if defined(CONFIG_MEDIA_CONTROLLER) /* Part 5: Register the entity. */ if (vdev->v4l2_dev->mdev && vdev->vfl_type != VFL_TYPE_SUBDEV) { vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; vdev->entity.name = vdev->name; vdev->entity.info.dev.major = VIDEO_MAJOR; vdev->entity.info.dev.minor = vdev->minor; ret = media_device_register_entity(vdev->v4l2_dev->mdev, &vdev->entity); if (ret < 0) printk(KERN_WARNING "%s: media_device_register_entity failed\n", __func__); } - --vdev->v4l2_dev は struct v4l2_device * 型 --[[linux-4.4.1/v4l2_device]] --vdev->v4l2_dev は struct media_device * 型 --[[linux-4.4.1/media_device]] --vdev->entity は struct media_entity 型 --[[linux-4.4.1/media_entity]] --[[linux-4.4.1/media_device_register_entity()]] #endif /* Part 6: Activate this minor. The char device can now be used. */ set_bit(V4L2_FL_REGISTERED, &vdev->flags); - --[[linux-4.4.1/set_bit()]] return 0; cleanup: mutex_lock(&videodev_lock); if (vdev->cdev) cdev_del(vdev->cdev); - --[[linux-4.4.1/mutex_lock()]] --[[linux-4.4.1/cdev_del()]] video_device[vdev->minor] = NULL; devnode_clear(vdev); mutex_unlock(&videodev_lock); - --[[linux-4.4.1/devnode_clear()]] --[[linux-4.4.1/mutex_unlock()]] /* Mark this video device as never having been registered. */ vdev->minor = -1; return ret; } EXPORT_SYMBOL(__video_register_device); - --[[linux-4.4.1/EXPORT_SYMBOL()]] *コメント [#n34d2e68]