@@ -447,38 +447,267 @@ static int drm_mode_resolve_obj_type(drm_device_t *dev, uint32_t obj_id, uint32_
447447 return 0 ;
448448}
449449
450- static void drm_sysfs_write_file (vfs_node_t parent , const char * name , const char * content ) {
451- vfs_node_t node ;
452- sysfs_handle_t * handle ;
453- size_t len ;
450+ typedef enum drm_sysfs_attr {
451+ DRM_SYSFS_ATTR_VERSION ,
452+ DRM_SYSFS_ATTR_DEV ,
453+ DRM_SYSFS_ATTR_MODES ,
454+ DRM_SYSFS_ATTR_UEVENT ,
455+ } drm_sysfs_attr_t ;
456+
457+ typedef struct drm_sysfs_file {
458+ sysfs_handle_t handle ;
459+ drm_device_t * dev ;
460+ drm_sysfs_attr_t attr ;
461+ } drm_sysfs_file_t ;
462+
463+ static char * drm_sysfs_join_path (vfs_node_t parent , const char * name ) {
464+ if (parent == NULL || name == NULL ) {
465+ return NULL ;
466+ }
467+
468+ char * base = vfs_get_fullpath (parent );
469+ if (base == NULL ) {
470+ return NULL ;
471+ }
472+
473+ size_t base_len = strlen (base );
474+ size_t name_len = strlen (name );
475+ size_t path_len = base_len + name_len + 2 ;
476+ char * path = malloc (path_len );
477+ if (path == NULL ) {
478+ free (base );
479+ return NULL ;
480+ }
481+
482+ if (strcmp (base , "/" ) == 0 ) {
483+ sprintf (path , "/%s" , name );
484+ } else {
485+ sprintf (path , "%s/%s" , base , name );
486+ }
487+
488+ free (base );
489+ return path ;
490+ }
491+
492+ static vfs_node_t drm_sysfs_lookup_child (vfs_node_t parent , const char * name ) {
493+ char * path = drm_sysfs_join_path (parent , name );
494+ if (path == NULL ) {
495+ return NULL ;
496+ }
497+
498+ vfs_node_t node = vfs_open (path );
499+ free (path );
500+ return node ;
501+ }
454502
455- if (!parent || !name || !content ) {
503+ static void drm_sysfs_release_handle (vfs_node_t node ) {
504+ if (node == NULL || node -> handle == NULL ) {
456505 return ;
457506 }
458507
459- node = sysfs_child_append (parent , name , false);
460- if (!node ) {
508+ sysfs_header_t * header = node -> handle ;
509+ if (header -> type == SYSFS_NONE ) {
510+ sysfs_handle_t * handle = node -> handle ;
511+ if (handle -> data != NULL ) {
512+ free (handle -> data );
513+ }
514+ }
515+
516+ free (node -> handle );
517+ node -> handle = NULL ;
518+ }
519+
520+ static size_t drm_sysfs_format_modes_text (
521+ drm_device_t * drm_dev , char * buffer , size_t buffer_size
522+ ) {
523+ uint32_t width = 1024 ;
524+ uint32_t height = 768 ;
525+ uint32_t bpp = 32 ;
526+
527+ for (size_t i = 0 ; i < DRM_MAX_CONNECTORS_PER_DEVICE ; i ++ ) {
528+ drm_connector_t * connector = drm_dev -> resource_mgr .connectors [i ];
529+ if (connector == NULL || connector -> modes == NULL || connector -> count_modes == 0 ) {
530+ continue ;
531+ }
532+
533+ width = connector -> modes [0 ].hdisplay ;
534+ height = connector -> modes [0 ].vdisplay ;
535+ goto out ;
536+ }
537+
538+ if (drm_dev -> op && drm_dev -> op -> get_display_info ) {
539+ drm_dev -> op -> get_display_info (drm_dev , & width , & height , & bpp );
540+ }
541+
542+ out :
543+ snprintf (buffer , buffer_size , "%ux%u\n" , width , height );
544+ return strlen (buffer );
545+ }
546+
547+ static size_t drm_sysfs_format_dev_text (drm_device_t * drm_dev , char * buffer , size_t buffer_size ) {
548+ int major = (drm_dev -> dev_nr >> 8 ) & 0xff ;
549+ int minor = drm_dev -> dev_nr & 0xff ;
550+
551+ snprintf (buffer , buffer_size , "%d:%d\n" , major , minor );
552+ return strlen (buffer );
553+ }
554+
555+ static size_t drm_sysfs_format_uevent_text (
556+ drm_device_t * drm_dev , char * buffer , size_t buffer_size
557+ ) {
558+ int minor = drm_dev -> dev_nr & 0xff ;
559+ int major = (drm_dev -> dev_nr >> 8 ) & 0xff ;
560+ char dev_name [32 ];
561+
562+ snprintf (dev_name , sizeof (dev_name ), "card%d" , minor );
563+ snprintf (
564+ buffer ,
565+ buffer_size ,
566+ "MAJOR=%d\nMINOR=%d\nDEVNAME=dri/%s\nDEVTYPE=drm_minor\nSUBSYSTEM=drm\n" ,
567+ major ,
568+ minor ,
569+ dev_name
570+ );
571+ return strlen (buffer );
572+ }
573+
574+ static size_t drm_sysfs_format_attr (
575+ drm_sysfs_file_t * handle , char * buffer , size_t buffer_size
576+ ) {
577+ if (handle == NULL || buffer == NULL || buffer_size == 0 ) {
578+ return 0 ;
579+ }
580+
581+ switch (handle -> attr ) {
582+ case DRM_SYSFS_ATTR_VERSION :
583+ snprintf (buffer , buffer_size , "drm 1.1.0 20060810\n" );
584+ return strlen (buffer );
585+ case DRM_SYSFS_ATTR_DEV :
586+ return drm_sysfs_format_dev_text (handle -> dev , buffer , buffer_size );
587+ case DRM_SYSFS_ATTR_MODES :
588+ return drm_sysfs_format_modes_text (handle -> dev , buffer , buffer_size );
589+ case DRM_SYSFS_ATTR_UEVENT :
590+ return drm_sysfs_format_uevent_text (handle -> dev , buffer , buffer_size );
591+ default :
592+ return 0 ;
593+ }
594+ }
595+
596+ static size_t drm_sysfs_attr_read (void * file , void * addr , size_t offset , size_t size ) {
597+ drm_sysfs_file_t * handle = file ;
598+ if (handle == NULL || handle -> dev == NULL || addr == NULL ) {
599+ return 0 ;
600+ }
601+
602+ char content [256 ];
603+ size_t len = drm_sysfs_format_attr (handle , content , sizeof (content ));
604+ if (len == 0 || offset >= len ) {
605+ return 0 ;
606+ }
607+
608+ size_t actual = len - offset ;
609+ if (actual > size ) {
610+ actual = size ;
611+ }
612+
613+ memcpy (addr , content + offset , actual );
614+ return actual ;
615+ }
616+
617+ static size_t drm_sysfs_attr_write (void * file , const void * addr , size_t offset , size_t size ) {
618+ drm_sysfs_file_t * handle = file ;
619+ UNUSED (addr , offset );
620+
621+ if (handle == NULL ) {
622+ return 0 ;
623+ }
624+
625+ return handle -> attr == DRM_SYSFS_ATTR_UEVENT ? size : 0 ;
626+ }
627+
628+ static void drm_sysfs_install_attr_file (
629+ vfs_node_t parent , const char * name , drm_device_t * drm_dev , drm_sysfs_attr_t attr
630+ ) {
631+ vfs_node_t node = drm_sysfs_lookup_child (parent , name );
632+ if (node == NULL ) {
633+ node = sysfs_child_append (parent , name , SYSFS_NONE );
634+ }
635+ if (node == NULL ) {
461636 return ;
462637 }
463638
464- handle = node -> handle ;
465- len = strlen (content );
466- handle -> data = strdup (content );
467- handle -> size = len ;
468- handle -> capacity = len + 1 ;
469- node -> size = len ;
639+ drm_sysfs_release_handle (node );
640+
641+ drm_sysfs_file_t * handle = calloc (1 , sizeof (drm_sysfs_file_t ));
642+ strncpy (handle -> handle .name , name , sizeof (handle -> handle .name ) - 1 );
643+ handle -> handle .header .node = node ;
644+ handle -> handle .header .type = SYSFS_NONE ;
645+ handle -> handle .header .read = drm_sysfs_attr_read ;
646+ handle -> handle .header .write = drm_sysfs_attr_write ;
647+ handle -> dev = drm_dev ;
648+ handle -> attr = attr ;
649+
650+ node -> handle = handle ;
651+ char content [256 ];
652+ node -> size = drm_sysfs_format_attr (handle , content , sizeof (content ));
653+ node -> mode = attr == DRM_SYSFS_ATTR_UEVENT ? 0644 : 0444 ;
654+ }
655+
656+ static void drm_sysfs_ensure_symlink (vfs_node_t parent , const char * name , const char * target ) {
657+ if (parent == NULL || name == NULL || target == NULL ) {
658+ return ;
659+ }
660+
661+ if (drm_sysfs_lookup_child (parent , name ) != NULL ) {
662+ return ;
663+ }
664+
665+ sysfs_child_append_symlink (parent , name , target );
666+ }
667+
668+ static void drm_sysfs_ensure_symlink_node (vfs_node_t parent , const char * name , vfs_node_t target ) {
669+ if (parent == NULL || name == NULL || target == NULL ) {
670+ return ;
671+ }
672+
673+ if (drm_sysfs_lookup_child (parent , name ) != NULL ) {
674+ return ;
675+ }
676+
677+ sysfs_child_append_symlink_node (parent , name , target );
678+ }
679+
680+ static vfs_node_t drm_sysfs_get_device_root (drm_device_t * drm_dev , const char * dev_name ) {
681+ if (drm_dev -> pci_dev != NULL ) {
682+ return sysfs_get_pci_device_node (
683+ drm_dev -> pci_dev -> segment ,
684+ drm_dev -> pci_dev -> bus ,
685+ drm_dev -> pci_dev -> slot ,
686+ drm_dev -> pci_dev -> func
687+ );
688+ }
689+
690+ vfs_node_t system_root = sysfs_ensure_dir (sysfs_get_devices_root (), "system" );
691+ if (system_root == NULL ) {
692+ return NULL ;
693+ }
694+
695+ vfs_node_t display_root = sysfs_ensure_dir (system_root , "display" );
696+ if (display_root == NULL ) {
697+ return NULL ;
698+ }
699+
700+ char device_name [48 ];
701+ snprintf (device_name , sizeof (device_name ), "%s-device" , dev_name );
702+ return sysfs_ensure_dir (display_root , device_name );
470703}
471704
472705static void drm_sysfs_register_device (drm_device_t * drm_dev ) {
473- vfs_node_t dev_char_dir ;
474- vfs_node_t dev_root ;
475706 vfs_node_t device_dir ;
476707 vfs_node_t drm_dir ;
477708 vfs_node_t card_dir ;
478- vfs_node_t class_dir ;
479709 vfs_node_t class_drm_dir ;
480710 char dev_name [32 ];
481- char path [256 ];
482711 char content [128 ];
483712 int major ;
484713 int minor ;
@@ -487,88 +716,42 @@ static void drm_sysfs_register_device(drm_device_t *drm_dev) {
487716 return ;
488717 }
489718
490- dev_char_dir = vfs_open ("/sys/dev/char" );
491- if (!dev_char_dir ) {
492- return ;
493- }
494- vfs_close (dev_char_dir );
495-
496719 major = (drm_dev -> dev_nr >> 8 ) & 0xff ;
497720 minor = drm_dev -> dev_nr & 0xff ;
498- sprintf (dev_name , "card%d" , minor );
721+ snprintf (dev_name , sizeof ( dev_name ) , "card%d" , minor );
499722
500- sprintf (content , "SUBSYSTEM=drm\n" );
501- dev_root = sysfs_regist_dev ('c' , major , minor , "" , dev_name , content );
502- if (!dev_root ) {
503- return ;
504- }
505-
506- device_dir = sysfs_child_append (dev_root , "device" , true);
723+ device_dir = drm_sysfs_get_device_root (drm_dev , dev_name );
507724 if (!device_dir ) {
508725 return ;
509726 }
510727
511- drm_dir = sysfs_child_append (device_dir , "drm" , true );
728+ drm_dir = sysfs_ensure_dir (device_dir , "drm" );
512729 if (!drm_dir ) {
513730 return ;
514731 }
515732
516- card_dir = sysfs_child_append (drm_dir , dev_name , true );
733+ card_dir = sysfs_ensure_dir (drm_dir , dev_name );
517734 if (!card_dir ) {
518735 return ;
519736 }
520737
521- if (drm_dev -> pci_dev ) {
522- sprintf (
523- content ,
524- "PCI_SLOT_NAME=%04x:%02x:%02x.%u\n" ,
525- drm_dev -> pci_dev -> segment ,
526- drm_dev -> pci_dev -> bus ,
527- drm_dev -> pci_dev -> slot ,
528- drm_dev -> pci_dev -> func
529- );
530- } else {
531- sprintf (content , "PCI_SLOT_NAME=0000:00:00.0\n" );
532- }
533- drm_sysfs_write_file (device_dir , "uevent" , content );
534- sprintf (content , "0x%04x\n" , drm_dev -> pci_dev ? drm_dev -> pci_dev -> vendor_id : 0 );
535- drm_sysfs_write_file (device_dir , "vendor" , content );
536- sprintf (content , "0x%04x\n" , drm_dev -> pci_dev ? drm_dev -> pci_dev -> device_id : 0 );
537- drm_sysfs_write_file (device_dir , "device" , content );
538- sprintf (
539- content ,
540- "0x%04x\n" ,
541- drm_dev -> pci_dev ? drm_dev -> pci_dev -> subsystem_vendor_id : 0
542- );
543- drm_sysfs_write_file (device_dir , "subsystem_vendor" , content );
544- sprintf (
545- content ,
546- "0x%04x\n" ,
547- drm_dev -> pci_dev ? drm_dev -> pci_dev -> subsystem_device_id : 0
548- );
549- drm_sysfs_write_file (device_dir , "subsystem_device" , content );
550- sprintf (content , "0x%02x\n" , drm_dev -> pci_dev ? drm_dev -> pci_dev -> revision_id : 0 );
551- drm_sysfs_write_file (device_dir , "revision" , content );
552- drm_sysfs_write_file (drm_dir , "version" , "drm 1.1.0 20060810\n" );
553-
554- sprintf (content , "MAJOR=%d\nMINOR=%d\nDEVNAME=dri/%s\nSUBSYSTEM=drm\n" , major , minor , dev_name );
555- drm_sysfs_write_file (card_dir , "uevent" , content );
738+ drm_sysfs_install_attr_file (drm_dir , "version" , drm_dev , DRM_SYSFS_ATTR_VERSION );
739+ drm_sysfs_install_attr_file (card_dir , "dev" , drm_dev , DRM_SYSFS_ATTR_DEV );
740+ drm_sysfs_install_attr_file (card_dir , "modes" , drm_dev , DRM_SYSFS_ATTR_MODES );
741+ drm_sysfs_install_attr_file (card_dir , "uevent" , drm_dev , DRM_SYSFS_ATTR_UEVENT );
742+ drm_sysfs_ensure_symlink (card_dir , "subsystem" , "/sys/class/drm" );
743+ drm_sysfs_ensure_symlink_node (card_dir , "device" , device_dir );
556744
557- sysfs_child_append_symlink (card_dir , "subsystem" , "/sys/class/drm" );
558- sysfs_child_append_symlink (device_dir , "subsystem" , "/sys/bus/pci" );
745+ class_drm_dir = sysfs_ensure_dir (sysfs_get_class_root (), "drm" );
746+ if (class_drm_dir ) {
747+ drm_sysfs_ensure_symlink_node (class_drm_dir , dev_name , card_dir );
748+ }
559749
560- class_dir = vfs_open ("/sys/class" );
561- if (class_dir ) {
562- class_drm_dir = vfs_open ("/sys/class/drm" );
563- if (!class_drm_dir ) {
564- class_drm_dir = sysfs_child_append (class_dir , "drm" , true);
565- }
566- if (class_drm_dir ) {
567- sprintf (path , "/sys/dev/char/%d:%d/device/drm/%s" , major , minor , dev_name );
568- sysfs_child_append_symlink (class_drm_dir , dev_name , path );
569- vfs_close (class_drm_dir );
570- }
571- vfs_close (class_dir );
750+ drm_sysfs_format_uevent_text (drm_dev , content , sizeof (content ));
751+ char * card_path = vfs_get_fullpath (card_dir );
752+ if (card_path != NULL ) {
753+ sysfs_regist_dev ('c' , major , minor , card_path , dev_name , content );
754+ free (card_path );
572755 }
573756}
574757
0 commit comments