@ -1157,110 +1157,10 @@ static struct wlr_drm_crtc *connector_get_current_crtc(
return NULL ;
}
static void disconnect_drm_connector ( struct wlr_drm_connector * conn ) ;
void scan_drm_connectors ( struct wlr_drm_backend * drm ,
struct wlr_device_hotplug_event * event ) {
if ( event ! = NULL & & event - > connector_id ! = 0 ) {
wlr_log ( WLR_INFO , " Scanning DRM connector % " PRIu32 " on %s " ,
event - > connector_id , drm - > name ) ;
} else {
wlr_log ( WLR_INFO , " Scanning DRM connectors on %s " , drm - > name ) ;
}
drmModeRes * res = drmModeGetResources ( drm - > fd ) ;
if ( ! res ) {
wlr_log_errno ( WLR_ERROR , " Failed to get DRM resources " ) ;
return ;
}
size_t seen_len = wl_list_length ( & drm - > outputs ) ;
// +1 so length can never be 0, which is undefined behaviour.
// Last element isn't used.
bool seen [ seen_len + 1 ] ;
memset ( seen , false , sizeof ( seen ) ) ;
size_t new_outputs_len = 0 ;
struct wlr_drm_connector * new_outputs [ res - > count_connectors + 1 ] ;
for ( int i = 0 ; i < res - > count_connectors ; + + i ) {
uint32_t conn_id = res - > connectors [ i ] ;
ssize_t index = - 1 ;
struct wlr_drm_connector * c , * wlr_conn = NULL ;
wl_list_for_each ( c , & drm - > outputs , link ) {
index + + ;
if ( c - > id = = conn_id ) {
wlr_conn = c ;
break ;
}
}
// If the hotplug event contains a connector ID, ignore any other
// connector.
if ( event ! = NULL & & event - > connector_id ! = 0 & &
event - > connector_id ! = conn_id ) {
if ( wlr_conn ! = NULL ) {
seen [ index ] = true ;
}
continue ;
}
drmModeConnector * drm_conn = drmModeGetConnector ( drm - > fd , conn_id ) ;
if ( ! drm_conn ) {
wlr_log_errno ( WLR_ERROR , " Failed to get DRM connector " ) ;
continue ;
}
if ( ! wlr_conn ) {
wlr_conn = calloc ( 1 , sizeof ( * wlr_conn ) ) ;
if ( ! wlr_conn ) {
wlr_log_errno ( WLR_ERROR , " Allocation failed " ) ;
drmModeFreeConnector ( drm_conn ) ;
continue ;
}
wlr_conn - > backend = drm ;
wlr_conn - > status = DRM_MODE_DISCONNECTED ;
wlr_conn - > id = drm_conn - > connector_id ;
const char * conn_name =
drmModeGetConnectorTypeName ( drm_conn - > connector_type ) ;
if ( conn_name = = NULL ) {
conn_name = " Unknown " ;
}
snprintf ( wlr_conn - > name , sizeof ( wlr_conn - > name ) ,
" %s-% " PRIu32 , conn_name , drm_conn - > connector_type_id ) ;
wl_list_insert ( drm - > outputs . prev , & wlr_conn - > link ) ;
wlr_log ( WLR_INFO , " Found connector '%s' " , wlr_conn - > name ) ;
} else {
seen [ index ] = true ;
}
wlr_conn - > crtc = connector_get_current_crtc ( wlr_conn , drm_conn ) ;
// This can only happen *after* hotplug, since we haven't read the
// connector properties yet
if ( wlr_conn - > props . link_status ! = 0 ) {
uint64_t link_status ;
if ( ! get_drm_prop ( drm - > fd , wlr_conn - > id ,
wlr_conn - > props . link_status , & link_status ) ) {
wlr_drm_conn_log ( wlr_conn , WLR_ERROR ,
" Failed to get link status prop " ) ;
continue ;
}
if ( link_status = = DRM_MODE_LINK_STATUS_BAD ) {
// We need to reload our list of modes and force a modeset
wlr_drm_conn_log ( wlr_conn , WLR_INFO , " Bad link detected " ) ;
disconnect_drm_connector ( wlr_conn ) ;
}
}
static void connect_drm_connector ( struct wlr_drm_connector * wlr_conn ,
const drmModeConnector * drm_conn ) {
struct wlr_drm_backend * drm = wlr_conn - > backend ;
if ( wlr_conn - > status = = DRM_MODE_DISCONNECTED & &
drm_conn - > connection = = DRM_MODE_CONNECTED ) {
wlr_log ( WLR_INFO , " '%s' connected " , wlr_conn - > name ) ;
wlr_log ( WLR_DEBUG , " Current CRTC: %d " ,
wlr_conn - > crtc ? ( int ) wlr_conn - > crtc - > id : - 1 ) ;
@ -1392,6 +1292,113 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
wlr_output_update_enabled ( & wlr_conn - > output , wlr_conn - > crtc ! = NULL ) ;
wlr_conn - > status = DRM_MODE_CONNECTED ;
}
static void disconnect_drm_connector ( struct wlr_drm_connector * conn ) ;
void scan_drm_connectors ( struct wlr_drm_backend * drm ,
struct wlr_device_hotplug_event * event ) {
if ( event ! = NULL & & event - > connector_id ! = 0 ) {
wlr_log ( WLR_INFO , " Scanning DRM connector % " PRIu32 " on %s " ,
event - > connector_id , drm - > name ) ;
} else {
wlr_log ( WLR_INFO , " Scanning DRM connectors on %s " , drm - > name ) ;
}
drmModeRes * res = drmModeGetResources ( drm - > fd ) ;
if ( ! res ) {
wlr_log_errno ( WLR_ERROR , " Failed to get DRM resources " ) ;
return ;
}
size_t seen_len = wl_list_length ( & drm - > outputs ) ;
// +1 so length can never be 0, which is undefined behaviour.
// Last element isn't used.
bool seen [ seen_len + 1 ] ;
memset ( seen , false , sizeof ( seen ) ) ;
size_t new_outputs_len = 0 ;
struct wlr_drm_connector * new_outputs [ res - > count_connectors + 1 ] ;
for ( int i = 0 ; i < res - > count_connectors ; + + i ) {
uint32_t conn_id = res - > connectors [ i ] ;
ssize_t index = - 1 ;
struct wlr_drm_connector * c , * wlr_conn = NULL ;
wl_list_for_each ( c , & drm - > outputs , link ) {
index + + ;
if ( c - > id = = conn_id ) {
wlr_conn = c ;
break ;
}
}
// If the hotplug event contains a connector ID, ignore any other
// connector.
if ( event ! = NULL & & event - > connector_id ! = 0 & &
event - > connector_id ! = conn_id ) {
if ( wlr_conn ! = NULL ) {
seen [ index ] = true ;
}
continue ;
}
drmModeConnector * drm_conn = drmModeGetConnector ( drm - > fd , conn_id ) ;
if ( ! drm_conn ) {
wlr_log_errno ( WLR_ERROR , " Failed to get DRM connector " ) ;
continue ;
}
if ( ! wlr_conn ) {
wlr_conn = calloc ( 1 , sizeof ( * wlr_conn ) ) ;
if ( ! wlr_conn ) {
wlr_log_errno ( WLR_ERROR , " Allocation failed " ) ;
drmModeFreeConnector ( drm_conn ) ;
continue ;
}
wlr_conn - > backend = drm ;
wlr_conn - > status = DRM_MODE_DISCONNECTED ;
wlr_conn - > id = drm_conn - > connector_id ;
const char * conn_name =
drmModeGetConnectorTypeName ( drm_conn - > connector_type ) ;
if ( conn_name = = NULL ) {
conn_name = " Unknown " ;
}
snprintf ( wlr_conn - > name , sizeof ( wlr_conn - > name ) ,
" %s-% " PRIu32 , conn_name , drm_conn - > connector_type_id ) ;
wl_list_insert ( drm - > outputs . prev , & wlr_conn - > link ) ;
wlr_log ( WLR_INFO , " Found connector '%s' " , wlr_conn - > name ) ;
} else {
seen [ index ] = true ;
}
wlr_conn - > crtc = connector_get_current_crtc ( wlr_conn , drm_conn ) ;
// This can only happen *after* hotplug, since we haven't read the
// connector properties yet
if ( wlr_conn - > props . link_status ! = 0 ) {
uint64_t link_status ;
if ( ! get_drm_prop ( drm - > fd , wlr_conn - > id ,
wlr_conn - > props . link_status , & link_status ) ) {
wlr_drm_conn_log ( wlr_conn , WLR_ERROR ,
" Failed to get link status prop " ) ;
continue ;
}
if ( link_status = = DRM_MODE_LINK_STATUS_BAD ) {
// We need to reload our list of modes and force a modeset
wlr_drm_conn_log ( wlr_conn , WLR_INFO , " Bad link detected " ) ;
disconnect_drm_connector ( wlr_conn ) ;
}
}
if ( wlr_conn - > status = = DRM_MODE_DISCONNECTED & &
drm_conn - > connection = = DRM_MODE_CONNECTED ) {
wlr_log ( WLR_INFO , " '%s' connected " , wlr_conn - > name ) ;
connect_drm_connector ( wlr_conn , drm_conn ) ;
new_outputs [ new_outputs_len + + ] = wlr_conn ;
} else if ( wlr_conn - > status = = DRM_MODE_CONNECTED & &
drm_conn - > connection ! = DRM_MODE_CONNECTED ) {