@@ -1045,6 +1045,156 @@ static void complete_video_format_dev(size_t idx, struct shell_static_entry *ent
10451045}
10461046SHELL_DYNAMIC_CMD_CREATE (dsub_video_format_dev , complete_video_format_dev );
10471047
1048+ /* Video selection handling */
1049+
1050+ static void video_shell_print_selection (const struct shell * sh , struct video_selection * sel )
1051+ {
1052+ shell_print (sh , "\tselection target: %s: (%u,%u)/%ux%u" ,
1053+ sel -> target == VIDEO_SEL_TGT_CROP ? "crop" :
1054+ sel -> target == VIDEO_SEL_TGT_CROP_BOUND ? "crop_bound" :
1055+ sel -> target == VIDEO_SEL_TGT_NATIVE_SIZE ? "native_size" :
1056+ sel -> target == VIDEO_SEL_TGT_COMPOSE ? "compose" : "unknown" ,
1057+ sel -> rect .left , sel -> rect .top , sel -> rect .width , sel -> rect .height );
1058+ }
1059+
1060+ static int video_shell_selection_parse_target (const struct shell * sh , char const * arg_target ,
1061+ enum video_selection_target * sel_target )
1062+ {
1063+ if (strcmp (arg_target , "crop" ) == 0 ) {
1064+ * sel_target = VIDEO_SEL_TGT_CROP ;
1065+ } else if (strcmp (arg_target , "crop_bound" ) == 0 ) {
1066+ * sel_target = VIDEO_SEL_TGT_CROP_BOUND ;
1067+ } else if (strcmp (arg_target , "native_size" ) == 0 ) {
1068+ * sel_target = VIDEO_SEL_TGT_NATIVE_SIZE ;
1069+ } else if (strcmp (arg_target , "compose" ) == 0 ) {
1070+ * sel_target = VIDEO_SEL_TGT_COMPOSE ;
1071+ } else if (strcmp (arg_target , "compose_bound" ) == 0 ) {
1072+ * sel_target = VIDEO_SEL_TGT_COMPOSE_BOUND ;
1073+ } else {
1074+ shell_error (sh ,
1075+ "Target must be 'crop/crop_bound/native_size/compose or compose_bound" );
1076+ return - EINVAL ;
1077+ }
1078+
1079+ return 0 ;
1080+ }
1081+
1082+ static int video_shell_selection_parse_rect (const struct shell * sh , char const * arg_rect ,
1083+ struct video_rect * rect )
1084+ {
1085+ char * end_size = (char * )arg_rect ;
1086+
1087+ if (* end_size != '(' ) {
1088+ shell_error (sh ,
1089+ "Invalid rectangle format (<left>,<top>)/<width>x<height> parameter %s" ,
1090+ arg_rect );
1091+ return - EINVAL ;
1092+ }
1093+ end_size ++ ;
1094+
1095+ rect -> left = strtoul (end_size , & end_size , 10 );
1096+ if (* end_size != ',' ) {
1097+ shell_error (sh ,
1098+ "Invalid left value in rect <left>,<top>/<width>x<height> parameter %s" ,
1099+ arg_rect );
1100+ return - EINVAL ;
1101+ }
1102+ end_size ++ ;
1103+
1104+ rect -> top = strtoul (end_size , & end_size , 10 );
1105+ if (* end_size != ')' ) {
1106+ shell_error (sh ,
1107+ "Invalid top value in rect <left>,<top>/<width>x<height> parameter %s" ,
1108+ arg_rect );
1109+ return - EINVAL ;
1110+ }
1111+ end_size ++ ;
1112+
1113+ if (* end_size != '/' ) {
1114+ shell_error (sh ,
1115+ "Invalid rectangle format (<left>,<top>)/<width>x<height> parameter %s" ,
1116+ arg_rect );
1117+ return - EINVAL ;
1118+ }
1119+ end_size ++ ;
1120+
1121+ rect -> width = strtoul (end_size , & end_size , 10 );
1122+ if (* end_size != 'x' || rect -> width == 0 ) {
1123+ shell_error (sh ,
1124+ "Invalid width value in rect <left>,<top>/<width>x<height> parameter %s" ,
1125+ arg_rect );
1126+ return - EINVAL ;
1127+ }
1128+ end_size ++ ;
1129+
1130+ rect -> height = strtoul (end_size , & end_size , 10 );
1131+ if (* end_size != '\0' || rect -> height == 0 ) {
1132+ shell_error (sh ,
1133+ "Invalid height value in rect <left>,<top>/<width>x<height> parameter %s" ,
1134+ arg_rect );
1135+ return - EINVAL ;
1136+ }
1137+
1138+ return 0 ;
1139+ }
1140+
1141+ static int cmd_video_selection (const struct shell * sh , size_t argc , char * * argv )
1142+ {
1143+ const struct device * dev ;
1144+ struct video_selection sel = {0 };
1145+ char * arg_device = argv [1 ];
1146+ char * arg_in_out = argv [2 ];
1147+ char * arg_target = argv [3 ];
1148+ int ret ;
1149+
1150+ dev = device_get_binding (arg_device );
1151+ ret = video_shell_check_device (sh , dev );
1152+ if (ret < 0 ) {
1153+ return ret ;
1154+ }
1155+
1156+ ret = video_shell_parse_in_out (sh , arg_in_out , & sel .type );
1157+ if (ret < 0 ) {
1158+ return - ret ;
1159+ }
1160+
1161+ ret = video_shell_selection_parse_target (sh , arg_target , & sel .target );
1162+ if (ret < 0 ) {
1163+ return ret ;
1164+ }
1165+
1166+ switch (argc ) {
1167+ case 4 :
1168+ ret = video_get_selection (dev , & sel );
1169+ if (ret < 0 ) {
1170+ shell_error (sh , "Failed to get %s selection" , dev -> name );
1171+ return - ENODEV ;
1172+ }
1173+
1174+ video_shell_print_selection (sh , & sel );
1175+ break ;
1176+ case 5 :
1177+ ret = video_shell_selection_parse_rect (sh , argv [4 ], & sel .rect );
1178+ if (ret < 0 ) {
1179+ return ret ;
1180+ }
1181+
1182+ ret = video_set_selection (dev , & sel );
1183+ if (ret < 0 ) {
1184+ shell_error (sh , "Failed to set %s selection" , dev -> name );
1185+ return - ENODEV ;
1186+ }
1187+
1188+ video_shell_print_selection (sh , & sel );
1189+ break ;
1190+ default :
1191+ shell_error (sh , "Wrong parameter count" );
1192+ return - EINVAL ;
1193+ }
1194+
1195+ return 0 ;
1196+ }
1197+
10481198/* Video shell commands declaration */
10491199
10501200SHELL_STATIC_SUBCMD_SET_CREATE (sub_video_cmds ,
@@ -1070,6 +1220,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_video_cmds,
10701220 SHELL_HELP ("Query or set video controls of a device" ,
10711221 "<device> [<ctrl> <value>]" ),
10721222 cmd_video_ctrl , 2 , 2 ),
1223+ SHELL_CMD_ARG (selection , & dsub_video_format_dev ,
1224+ SHELL_HELP ("Query or set the video selection of a device" ,
1225+ "<device> <dir> <target> [<left>,<top>/<width>x<height>]" ),
1226+ cmd_video_selection , 4 , 1 ),
10731227 SHELL_SUBCMD_SET_END
10741228);
10751229
0 commit comments