#include #include #include static DECLARE_BITMAP(fb_device_ids, FRAMEBUFFER_DEVICE_MAX); static spin_lock_t fb_device_ids_lock = SPIN_LOCK_INIT; struct framebuffer_device *framebuffer_device_create(void) { struct device *dev = device_alloc(); if (!dev) { return NULL; } dev->dev_type = DEV_TYPE_FRAMEBUFFER; return FRAMEBUFFER_DEVICE(dev); } struct framebuffer_device *framebuffer_device_from_generic(struct device *dev) { dev->dev_type = DEV_TYPE_FRAMEBUFFER; return FRAMEBUFFER_DEVICE(dev); } static kern_status_t generate_name(struct framebuffer_device *dev, char out[DEV_NAME_MAX]) { snprintf(out, DEV_NAME_MAX, "fb%u", dev->fb_id); return KERN_OK; } kern_status_t framebuffer_device_register(struct device *dev) { unsigned long flags; spin_lock_irqsave(&fb_device_ids_lock, &flags); unsigned int id = bitmap_lowest_clear(fb_device_ids, INPUT_DEVICE_MAX); bitmap_set(fb_device_ids, id); spin_unlock_irqrestore(&fb_device_ids_lock, flags); struct framebuffer_device *fbdev = &dev->fb; fbdev->fb_id = id; char name[DEV_NAME_MAX]; generate_name(fbdev, name); char path[OBJECT_PATH_MAX]; snprintf(path, sizeof path, "/dev/video/%s", name); return object_namespace_create_link(global_namespace(), path, &dev->dev_base); } kern_status_t framebuffer_get_fixedinfo(struct device *dev, struct framebuffer_fixedinfo *out) { struct framebuffer_device *fbdev = FRAMEBUFFER_DEVICE(dev); if (!fbdev) { return KERN_INVALID_ARGUMENT; } memcpy(out, &fbdev->fb_fixedinfo, sizeof *out); return KERN_OK; } kern_status_t framebuffer_get_varinfo(struct device *dev, struct framebuffer_varinfo *out) { struct framebuffer_device *fbdev = FRAMEBUFFER_DEVICE(dev); if (!fbdev) { return KERN_INVALID_ARGUMENT; } memcpy(out, &fbdev->fb_varinfo, sizeof *out); return KERN_OK; } kern_status_t framebuffer_set_varinfo(struct device *dev, const struct framebuffer_varinfo *varinfo) { struct framebuffer_device *fbdev = FRAMEBUFFER_DEVICE(dev); if (!fbdev) { return KERN_INVALID_ARGUMENT; } if (!fbdev->fb_ops || !fbdev->fb_ops->set_varinfo) { return KERN_UNSUPPORTED; } kern_status_t status = fbdev->fb_ops->set_varinfo(dev, varinfo); if (status == KERN_OK) { memcpy(&fbdev->fb_varinfo, varinfo, sizeof *varinfo); } return status; } struct device_type_ops framebuffer_type_ops = { .register_device = framebuffer_device_register, };