| 1 | #!/usr/bin/perl |
|---|
| 2 | ############################################################################# |
|---|
| 3 | # |
|---|
| 4 | # Copyright (c) 2004-2008, Broadcom Corporation. |
|---|
| 5 | # All rights reserved. |
|---|
| 6 | # Confidential Property of Broadcom Corporation. |
|---|
| 7 | # |
|---|
| 8 | # THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE |
|---|
| 9 | # AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR |
|---|
| 10 | # EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 11 | # |
|---|
| 12 | # $brcm_Workfile: bapi_driver_ioctl.pm $ |
|---|
| 13 | # $brcm_Revision: 7 $ |
|---|
| 14 | # $brcm_Date: 1/23/08 3:09p $ |
|---|
| 15 | # |
|---|
| 16 | # File Description: |
|---|
| 17 | # |
|---|
| 18 | # Revision History: |
|---|
| 19 | # |
|---|
| 20 | # $brcm_Log: /BSEAV/api/build/proxy/bapi_driver_ioctl.pm $ |
|---|
| 21 | # |
|---|
| 22 | # 7 1/23/08 3:09p mphillip |
|---|
| 23 | # PR38923: Mosaic decode handles also require managing |
|---|
| 24 | # |
|---|
| 25 | # 6 11/21/07 3:43p gmohile |
|---|
| 26 | # PR 36570 : fix array sizes |
|---|
| 27 | # |
|---|
| 28 | # 5 1/10/07 10:34a erickson |
|---|
| 29 | # PR26351: bdecode_acquire_capture_buffer needs to have its bsurface_t |
|---|
| 30 | # destroyed |
|---|
| 31 | # |
|---|
| 32 | # 4 3/10/06 4:26p vle |
|---|
| 33 | # PR 20136: add pcmplay to the list of handles |
|---|
| 34 | # |
|---|
| 35 | # 3 11/2/05 11:24a vsilyaev |
|---|
| 36 | # PR 17883: Don't shutdown SettopApi stack if signal is pending |
|---|
| 37 | # |
|---|
| 38 | # 2 9/12/05 12:35p mphillip |
|---|
| 39 | # PR16870: Fix kernel-mode macrovision support |
|---|
| 40 | # |
|---|
| 41 | # 1 2/7/05 6:55p dlwin |
|---|
| 42 | # Merge down for release 2005_REFSW_MERGETOMAIN: |
|---|
| 43 | # |
|---|
| 44 | # Irvine_BSEAVSW_Devel/15 12/2/04 4:45p vsilyaev |
|---|
| 45 | # PR 13351: Added code to pass through NULL pointers as arguments. |
|---|
| 46 | # |
|---|
| 47 | # Irvine_BSEAVSW_Devel/14 8/31/04 1:36p erickson |
|---|
| 48 | # PR11869: buser_input must also be a managed handle |
|---|
| 49 | # |
|---|
| 50 | # Irvine_BSEAVSW_Devel/13 8/12/04 9:28a erickson |
|---|
| 51 | # PR11135: reworked bhandle_mgr autogen code to be data driven and close |
|---|
| 52 | # down in correct order |
|---|
| 53 | # |
|---|
| 54 | # Irvine_BSEAVSW_Devel/12 7/23/04 2:41p erickson |
|---|
| 55 | # PR11771: updated proxy layer for settop api changes |
|---|
| 56 | # |
|---|
| 57 | # Irvine_BSEAVSW_Devel/11 7/9/04 1:38p erickson |
|---|
| 58 | # PR11771: rebuilt proxy layer for settop api dataflow redesign, and |
|---|
| 59 | # handle all callbacks with new perl module |
|---|
| 60 | # |
|---|
| 61 | # Irvine_BSEAVSW_Devel/10 6/29/04 11:27a erickson |
|---|
| 62 | # PR11135: handle overflow callback |
|---|
| 63 | # |
|---|
| 64 | # Irvine_BSEAVSW_Devel/9 6/24/04 2:37p erickson |
|---|
| 65 | # PR11135: adapted proxy layer to bsettop_callback |
|---|
| 66 | # |
|---|
| 67 | # Irvine_BSEAVSW_Devel/8 6/24/04 10:24a erickson |
|---|
| 68 | # PR11135: added "don't modify" headers |
|---|
| 69 | # |
|---|
| 70 | # Irvine_BSEAVSW_Devel/7 6/21/04 4:38p erickson |
|---|
| 71 | # PR11135: use double curly braces to prevent stack overflow in the |
|---|
| 72 | # switch statement |
|---|
| 73 | # |
|---|
| 74 | # Irvine_BSEAVSW_Devel/6 6/18/04 12:33p erickson |
|---|
| 75 | # PR11135: destroy callbacks when closing |
|---|
| 76 | # |
|---|
| 77 | # Irvine_BSEAVSW_Devel/5 6/17/04 9:37a erickson |
|---|
| 78 | # PR11135: recpump callback enabled |
|---|
| 79 | # |
|---|
| 80 | # Irvine_BSEAVSW_Devel/4 6/16/04 5:15p erickson |
|---|
| 81 | # PR11135: added callback support |
|---|
| 82 | # |
|---|
| 83 | # Irvine_BSEAVSW_Devel/3 6/1/04 11:28a erickson |
|---|
| 84 | # PR11135: added support for strings (const char *) |
|---|
| 85 | # |
|---|
| 86 | # Irvine_BSEAVSW_Devel/2 5/25/04 11:46a erickson |
|---|
| 87 | # PR11135: playback must be managed |
|---|
| 88 | # |
|---|
| 89 | # Irvine_BSEAVSW_Devel/1 5/17/04 11:13a erickson |
|---|
| 90 | # PR11135: added initial linux proxy impl |
|---|
| 91 | # |
|---|
| 92 | ############################################################################# |
|---|
| 93 | use strict; |
|---|
| 94 | use bapi_callbacks; |
|---|
| 95 | |
|---|
| 96 | package bapi_driver_ioctl; |
|---|
| 97 | |
|---|
| 98 | # For managed handles, the open function must return a handle. |
|---|
| 99 | # The close function must take only the handle as a parameter. |
|---|
| 100 | # The order of this list determines the order in which handles will be autoclosed |
|---|
| 101 | # by bhandle_mgr. It will close from the top down. |
|---|
| 102 | my @managed_handles = ( |
|---|
| 103 | ["btuner_tune_rf", "bstream_close", "stream"], |
|---|
| 104 | ["btuner_tune_linein", "bstream_close", "stream"], |
|---|
| 105 | ["bstream_open", "bstream_close", "stream"], |
|---|
| 106 | ["bstream_open_child", "bstream_close", "stream"], |
|---|
| 107 | ["btuner_open", "btuner_close", "tuner"], |
|---|
| 108 | ["bplaypump_open", "bplaypump_close", "playpump"], |
|---|
| 109 | ["brecpump_open", "brecpump_close", "recpump"], |
|---|
| 110 | ["bdecode_window_open", "bdecode_window_close", "window"], |
|---|
| 111 | ["bdecode_window_open_mosaic", "bdecode_window_close", "window"], |
|---|
| 112 | ["bdecode_window_clone", "bdecode_window_close", "window"], |
|---|
| 113 | ["bdecode_open", "bdecode_close", "decode"], |
|---|
| 114 | ["bdecode_open_mosaic", "bdecode_close", "decode"], |
|---|
| 115 | ["buser_input_open", "buser_input_close", "ui"], |
|---|
| 116 | ["bsurface_create", "bsurface_destroy", "surface"], |
|---|
| 117 | ["bdecode_acquire_capture_buffer", "bsurface_destroy", "surface"], |
|---|
| 118 | ["bgraphics_open", "bgraphics_close", "graphics"], |
|---|
| 119 | ["bdisplay_open", "bdisplay_close", "display"], |
|---|
| 120 | ["bpcm_play_open", "bpcm_play_close", "pcmplay"] |
|---|
| 121 | ); |
|---|
| 122 | |
|---|
| 123 | sub build_addhandle { |
|---|
| 124 | my $func = shift; |
|---|
| 125 | my $mh; |
|---|
| 126 | my $text = ""; |
|---|
| 127 | |
|---|
| 128 | for $mh (@managed_handles) { |
|---|
| 129 | if ($mh->[0] eq $func->{FUNCNAME}) { |
|---|
| 130 | my $close_func = $mh->[1]; |
|---|
| 131 | $text .= " bhandle_mgr_add(file->private_data, st.__retval, (settopapi_close_func)$close_func, \"$close_func\");\n"; |
|---|
| 132 | last; |
|---|
| 133 | } |
|---|
| 134 | } |
|---|
| 135 | return $text; |
|---|
| 136 | } |
|---|
| 137 | |
|---|
| 138 | sub build_removehandle { |
|---|
| 139 | my $func = shift; |
|---|
| 140 | my $mh; |
|---|
| 141 | my $text = ""; |
|---|
| 142 | |
|---|
| 143 | for $mh (@managed_handles) { |
|---|
| 144 | if ($mh->[1] eq $func->{FUNCNAME}) { |
|---|
| 145 | my $close_func = $mh->[1]; |
|---|
| 146 | my $handle = $mh->[2]; |
|---|
| 147 | $text .= " bhandle_mgr_remove(file->private_data, st.$handle, \"$close_func\");\n"; |
|---|
| 148 | last; |
|---|
| 149 | } |
|---|
| 150 | } |
|---|
| 151 | return $text; |
|---|
| 152 | } |
|---|
| 153 | |
|---|
| 154 | sub build_closelist |
|---|
| 155 | { |
|---|
| 156 | my ($filename, @funcs) = @_; |
|---|
| 157 | my $mh; |
|---|
| 158 | |
|---|
| 159 | open FILE, ">$filename" || die "Cannot open $filename"; |
|---|
| 160 | |
|---|
| 161 | print FILE "/*********************************\n"; |
|---|
| 162 | print FILE "*\n"; |
|---|
| 163 | print FILE "* This file is autogenerated. Do not modify.\n"; |
|---|
| 164 | print FILE "*\n"; |
|---|
| 165 | print FILE "*********************************/\n"; |
|---|
| 166 | |
|---|
| 167 | print FILE "#include \"bhandle_mgr.h\"\n"; |
|---|
| 168 | print FILE "#include \"bsettop.h\"\n"; |
|---|
| 169 | print FILE "static settopapi_close_func g_closefuncs[] = {\n"; |
|---|
| 170 | for $mh (@managed_handles) { |
|---|
| 171 | my $close_func = $mh->[1]; |
|---|
| 172 | print FILE " (settopapi_close_func) $close_func,\n"; |
|---|
| 173 | } |
|---|
| 174 | print FILE " 0\n"; |
|---|
| 175 | print FILE "};\n"; |
|---|
| 176 | close FILE; |
|---|
| 177 | } |
|---|
| 178 | |
|---|
| 179 | sub parse |
|---|
| 180 | { |
|---|
| 181 | my ($filename, @funcs) = @_; |
|---|
| 182 | my $func; |
|---|
| 183 | open FILE, ">$filename" || die "Cannot open $filename"; |
|---|
| 184 | |
|---|
| 185 | print FILE "/*********************************\n"; |
|---|
| 186 | print FILE "*\n"; |
|---|
| 187 | print FILE "* This file is autogenerated. Do not modify.\n"; |
|---|
| 188 | print FILE "*\n"; |
|---|
| 189 | print FILE "*********************************/\n"; |
|---|
| 190 | |
|---|
| 191 | # |
|---|
| 192 | # This function only generates the case statements. The switch statement |
|---|
| 193 | # and the rest of the function context can be found in BSEAV/linux/driver/97038/bcmdriver.c. |
|---|
| 194 | # |
|---|
| 195 | for $func (@funcs) { |
|---|
| 196 | my $params = $func->{PARAMS}; |
|---|
| 197 | my $param; |
|---|
| 198 | |
|---|
| 199 | print FILE "case BSETTOP_IOCTL_$func->{FUNCNAME}:\n"; |
|---|
| 200 | # Using double curly braces causes the stack to be allocated for |
|---|
| 201 | # each case statement instead of for the whole switch statement. |
|---|
| 202 | # This prevents stack overflow in the kernel. If this compiler trick stops |
|---|
| 203 | # working in the future, use a union or put each case statement in a function. |
|---|
| 204 | print FILE " {{\n"; |
|---|
| 205 | |
|---|
| 206 | if (!$func->{NOSTRUCT}) { |
|---|
| 207 | print FILE " ioctl_settopapi_struct_$func->{FUNCNAME} st;\n"; |
|---|
| 208 | for $param (@$params) { |
|---|
| 209 | if ($param->{ISREF}) { |
|---|
| 210 | if ($param->{ARRAYLENGTH}) { |
|---|
| 211 | if ($param->{ARRAYLENGTH} ne "__maxstringlength") { |
|---|
| 212 | print FILE " $param->{TYPE} $param->{NAME};\n"; |
|---|
| 213 | } |
|---|
| 214 | } |
|---|
| 215 | else { |
|---|
| 216 | print FILE " $param->{BASETYPE} $param->{NAME};\n"; |
|---|
| 217 | } |
|---|
| 218 | } |
|---|
| 219 | } |
|---|
| 220 | if ($func->{FUNCNAME} eq "bdisplay_set") { |
|---|
| 221 | print FILE " bmacrovision_tables mv_tables;\n"; |
|---|
| 222 | } |
|---|
| 223 | print FILE "\n"; |
|---|
| 224 | |
|---|
| 225 | print FILE " rc = copy_from_user(&st, (void*)arg, sizeof(st));\n"; |
|---|
| 226 | print FILE " if (rc) break;\n"; |
|---|
| 227 | } |
|---|
| 228 | |
|---|
| 229 | # This bracket is necessary in order to dynamically allocate arrays |
|---|
| 230 | # using values in st. |
|---|
| 231 | print FILE " {\n"; |
|---|
| 232 | |
|---|
| 233 | for $param (@$params) { |
|---|
| 234 | my $arraylength = $param->{ARRAYLENGTH}; |
|---|
| 235 | if ($arraylength && !($arraylength eq "__maxstringlength")) { |
|---|
| 236 | $arraylength = "st." . $arraylength; |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | if ($param->{ISREF}) { |
|---|
| 240 | if ($param->{ARRAYLENGTH}) { |
|---|
| 241 | if ($param->{ARRAYLENGTH} ne "__maxstringlength") { |
|---|
| 242 | print FILE " $param->{BASETYPE} $param->{NAME}_array[$arraylength];\n"; |
|---|
| 243 | print FILE " $param->{NAME} = $param->{NAME}_array;\n"; |
|---|
| 244 | } |
|---|
| 245 | else { |
|---|
| 246 | print FILE " $param->{BASETYPE} $param->{NAME}\[$arraylength\];\n"; |
|---|
| 247 | } |
|---|
| 248 | } |
|---|
| 249 | if ($param->{INPARAM}) { |
|---|
| 250 | if ($param->{ARRAYLENGTH}) { |
|---|
| 251 | print FILE " rc = copy_from_user((void*)$param->{NAME}, st.$param->{NAME}, $arraylength*sizeof($param->{BASETYPE}));\n"; |
|---|
| 252 | print FILE " if (rc) break;\n"; |
|---|
| 253 | } |
|---|
| 254 | else { |
|---|
| 255 | print FILE " if (st.$param->{NAME}) {\n"; |
|---|
| 256 | print FILE " rc = copy_from_user((void*)&$param->{NAME}, st.$param->{NAME}, sizeof($param->{NAME}));\n"; |
|---|
| 257 | print FILE " if (rc) break;\n"; |
|---|
| 258 | print FILE " }\n"; |
|---|
| 259 | } |
|---|
| 260 | } |
|---|
| 261 | } |
|---|
| 262 | } |
|---|
| 263 | |
|---|
| 264 | if ($func->{FUNCNAME} eq "bdisplay_set") { |
|---|
| 265 | print FILE " if (st.settings && settings.macrovision_tables) {\n"; |
|---|
| 266 | print FILE " rc = copy_from_user(&mv_tables, (void*)settings.macrovision_tables, sizeof(mv_tables));\n"; |
|---|
| 267 | print FILE " if (rc) break;\n"; |
|---|
| 268 | print FILE " settings.macrovision_tables = &mv_tables;\n"; |
|---|
| 269 | print FILE " }\n"; |
|---|
| 270 | } |
|---|
| 271 | |
|---|
| 272 | # switch user-mode callback for a kernel-mode callback |
|---|
| 273 | my $callback_text = bapi_callbacks::build_kernel_callback($func); |
|---|
| 274 | if ($callback_text) { |
|---|
| 275 | printf FILE $callback_text; |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | print FILE "\n /* Make the function call */\n"; |
|---|
| 279 | if ($func->{RETTYPE} =~ /\*$/) { |
|---|
| 280 | print FILE " $func->{RETTYPE} __retval = $func->{FUNCNAME}("; |
|---|
| 281 | } |
|---|
| 282 | elsif ($func->{RETTYPE} eq "void") { |
|---|
| 283 | print FILE " $func->{FUNCNAME}("; |
|---|
| 284 | } |
|---|
| 285 | else { |
|---|
| 286 | print FILE " st.__retval = $func->{FUNCNAME}("; |
|---|
| 287 | } |
|---|
| 288 | my $i; |
|---|
| 289 | for $param (@$params) { |
|---|
| 290 | if ($param->{ISREF}) { |
|---|
| 291 | if ($param->{ARRAYLENGTH}) { |
|---|
| 292 | print FILE "$param->{NAME}"; |
|---|
| 293 | } |
|---|
| 294 | else { |
|---|
| 295 | print FILE "st.$param->{NAME} ? &$param->{NAME}:NULL"; |
|---|
| 296 | } |
|---|
| 297 | } |
|---|
| 298 | else { |
|---|
| 299 | print FILE "st.$param->{NAME}"; |
|---|
| 300 | } |
|---|
| 301 | if ($i++ != $#$params) { |
|---|
| 302 | print FILE ","; |
|---|
| 303 | } |
|---|
| 304 | } |
|---|
| 305 | print FILE ");\n"; |
|---|
| 306 | if ($func->{RETTYPE} =~ /\*$/) { |
|---|
| 307 | print FILE " if (__retval) {\n"; |
|---|
| 308 | print FILE " st.__retval = *__retval;\n"; |
|---|
| 309 | print FILE " }\n"; |
|---|
| 310 | print FILE " else {\n"; |
|---|
| 311 | print FILE " rc = -EIO; break;\n"; |
|---|
| 312 | print FILE " }\n"; |
|---|
| 313 | } |
|---|
| 314 | |
|---|
| 315 | # |
|---|
| 316 | # interface with the bhandle_mgr |
|---|
| 317 | # |
|---|
| 318 | my $addition = build_addhandle($func); |
|---|
| 319 | if ($addition) { |
|---|
| 320 | print FILE $addition; |
|---|
| 321 | } |
|---|
| 322 | my $addition = build_removehandle($func); |
|---|
| 323 | if ($addition) { |
|---|
| 324 | print FILE $addition; |
|---|
| 325 | } |
|---|
| 326 | |
|---|
| 327 | if ($func->{RETTYPE} eq "void") { |
|---|
| 328 | print FILE " rc = 0;\n\n"; |
|---|
| 329 | } |
|---|
| 330 | else { |
|---|
| 331 | # Don't fail the ioctl if the settop api call failed. The |
|---|
| 332 | # app will need to detect the error. |
|---|
| 333 | print FILE " rc = copy_to_user((void*)arg, &st, sizeof(st));\n"; |
|---|
| 334 | print FILE " if (rc) {rc = -EFAULT; break;}\n"; |
|---|
| 335 | } |
|---|
| 336 | |
|---|
| 337 | for $param (@$params) { |
|---|
| 338 | my $arraylength = $param->{ARRAYLENGTH}; |
|---|
| 339 | if ($arraylength && !($arraylength eq "__maxstringlength")) { |
|---|
| 340 | $arraylength = "st." . $arraylength; |
|---|
| 341 | } |
|---|
| 342 | |
|---|
| 343 | if ($param->{ISREF} && !$param->{INPARAM}) { |
|---|
| 344 | print FILE " if (st.$param->{NAME}) {\n"; |
|---|
| 345 | if ($param->{ARRAYLENGTH}) { |
|---|
| 346 | print FILE " rc = copy_to_user(st.$param->{NAME}, $param->{NAME}, $arraylength*sizeof($param->{BASETYPE}));\n"; |
|---|
| 347 | } |
|---|
| 348 | else { |
|---|
| 349 | print FILE " rc = copy_to_user(st.$param->{NAME}, &$param->{NAME}, sizeof($param->{NAME}));\n"; |
|---|
| 350 | } |
|---|
| 351 | print FILE " if (rc) {rc = -EFAULT; break;}\n"; |
|---|
| 352 | print FILE " }\n"; |
|---|
| 353 | } |
|---|
| 354 | } |
|---|
| 355 | |
|---|
| 356 | print FILE " }\n"; |
|---|
| 357 | print FILE " }}\n"; |
|---|
| 358 | print FILE " break;\n\n"; |
|---|
| 359 | } |
|---|
| 360 | close FILE; |
|---|
| 361 | } |
|---|
| 362 | |
|---|
| 363 | 1; |
|---|
| 364 | |
|---|