deploy: e1b44579b0f416a20cfe7b9ba0205e1fb674dba5

This commit is contained in:
jserv 2024-04-15 22:26:49 +00:00
parent 8095fb7d7c
commit eef1f24901
3 changed files with 329 additions and 318 deletions

View File

@ -6352,145 +6352,149 @@ static key works.
<a id='x1-65151r61'></a><span class='ecrm-0500'>61</span>
<a id='x1-65153r62'></a><span class='ecrm-0500'>62</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3383'><span class='ectt-0800'>"I was assigned major number %d</span></span><span id='textcolor3384'><span class='ectt-0800'>\n</span></span><span id='textcolor3385'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, major);</span>
<a id='x1-65155r63'></a><span class='ecrm-0500'>63</span>
<a id='x1-65157r64'></a><span class='ecrm-0500'>64</span><span class='ectt-0800'>    cls = class_create(THIS_MODULE, DEVICE_NAME);</span>
<a id='x1-65159r65'></a><span class='ecrm-0500'>65</span>
<a id='x1-65161r66'></a><span class='ecrm-0500'>66</span><span class='ectt-0800'>    device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);</span>
<a id='x1-65163r67'></a><span class='ecrm-0500'>67</span>
<a id='x1-65165r68'></a><span class='ecrm-0500'>68</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3386'><span class='ectt-0800'>"Device created on /dev/%s</span></span><span id='textcolor3387'><span class='ectt-0800'>\n</span></span><span id='textcolor3388'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, DEVICE_NAME);</span>
<a id='x1-65157r64'></a><span class='ecrm-0500'>64</span><span id='textcolor3386'><span class='ectt-0800'>#if LINUX_VERSION_CODE &lt; KERNEL_VERSION(6, 4, 0)</span></span>
<a id='x1-65159r65'></a><span class='ecrm-0500'>65</span><span class='ectt-0800'>    cls = class_create(THIS_MODULE, DEVICE_NAME);</span>
<a id='x1-65161r66'></a><span class='ecrm-0500'>66</span><span id='textcolor3387'><span class='ectt-0800'>#else</span></span>
<a id='x1-65163r67'></a><span class='ecrm-0500'>67</span><span class='ectt-0800'>    cls = class_create(DEVICE_NAME);</span>
<a id='x1-65165r68'></a><span class='ecrm-0500'>68</span><span id='textcolor3388'><span class='ectt-0800'>#endif</span></span>
<a id='x1-65167r69'></a><span class='ecrm-0500'>69</span>
<a id='x1-65169r70'></a><span class='ecrm-0500'>70</span><span class='ectt-0800'>    </span><span id='textcolor3389'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65171r71'></a><span class='ecrm-0500'>71</span><span class='ectt-0800'>}</span>
<a id='x1-65173r72'></a><span class='ecrm-0500'>72</span>
<a id='x1-65175r73'></a><span class='ecrm-0500'>73</span><span id='textcolor3390'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3391'><span class='ectt-0800'>void</span></span><span class='ectt-0800'> __exit chardev_exit(</span><span id='textcolor3392'><span class='ectt-0800'>void</span></span><span class='ectt-0800'>)</span>
<a id='x1-65177r74'></a><span class='ecrm-0500'>74</span><span class='ectt-0800'>{</span>
<a id='x1-65179r75'></a><span class='ecrm-0500'>75</span><span class='ectt-0800'>    device_destroy(cls, MKDEV(major, 0));</span>
<a id='x1-65181r76'></a><span class='ecrm-0500'>76</span><span class='ectt-0800'>    class_destroy(cls);</span>
<a id='x1-65183r77'></a><span class='ecrm-0500'>77</span>
<a id='x1-65185r78'></a><span class='ecrm-0500'>78</span><span class='ectt-0800'>    </span><span id='textcolor3393'><span class='ectt-0800'>/* Unregister the device */</span></span>
<a id='x1-65187r79'></a><span class='ecrm-0500'>79</span><span class='ectt-0800'>    unregister_chrdev(major, DEVICE_NAME);</span>
<a id='x1-65189r80'></a><span class='ecrm-0500'>80</span><span class='ectt-0800'>}</span>
<a id='x1-65169r70'></a><span class='ecrm-0500'>70</span><span class='ectt-0800'>    device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);</span>
<a id='x1-65171r71'></a><span class='ecrm-0500'>71</span>
<a id='x1-65173r72'></a><span class='ecrm-0500'>72</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3389'><span class='ectt-0800'>"Device created on /dev/%s</span></span><span id='textcolor3390'><span class='ectt-0800'>\n</span></span><span id='textcolor3391'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, DEVICE_NAME);</span>
<a id='x1-65175r73'></a><span class='ecrm-0500'>73</span>
<a id='x1-65177r74'></a><span class='ecrm-0500'>74</span><span class='ectt-0800'>    </span><span id='textcolor3392'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65179r75'></a><span class='ecrm-0500'>75</span><span class='ectt-0800'>}</span>
<a id='x1-65181r76'></a><span class='ecrm-0500'>76</span>
<a id='x1-65183r77'></a><span class='ecrm-0500'>77</span><span id='textcolor3393'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3394'><span class='ectt-0800'>void</span></span><span class='ectt-0800'> __exit chardev_exit(</span><span id='textcolor3395'><span class='ectt-0800'>void</span></span><span class='ectt-0800'>)</span>
<a id='x1-65185r78'></a><span class='ecrm-0500'>78</span><span class='ectt-0800'>{</span>
<a id='x1-65187r79'></a><span class='ecrm-0500'>79</span><span class='ectt-0800'>    device_destroy(cls, MKDEV(major, 0));</span>
<a id='x1-65189r80'></a><span class='ecrm-0500'>80</span><span class='ectt-0800'>    class_destroy(cls);</span>
<a id='x1-65191r81'></a><span class='ecrm-0500'>81</span>
<a id='x1-65193r82'></a><span class='ecrm-0500'>82</span><span id='textcolor3394'><span class='ectt-0800'>/* Methods */</span></span>
<a id='x1-65195r83'></a><span class='ecrm-0500'>83</span>
<a id='x1-65197r84'></a><span class='ecrm-0500'>84</span><span id='textcolor3395'><span class='ectt-0800'>/**</span></span>
<a id='x1-65199r85'></a><span class='ecrm-0500'>85</span><span id='textcolor3396'><span class='ectt-0800'> * Called when a process tried to open the device file, like</span></span>
<a id='x1-65201r86'></a><span class='ecrm-0500'>86</span><span id='textcolor3397'><span class='ectt-0800'> * cat /dev/key_state</span></span>
<a id='x1-65203r87'></a><span class='ecrm-0500'>87</span><span id='textcolor3398'><span class='ectt-0800'> */</span></span>
<a id='x1-65205r88'></a><span class='ecrm-0500'>88</span><span id='textcolor3399'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3400'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> device_open(</span><span id='textcolor3401'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> inode *inode, </span><span id='textcolor3402'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *file)</span>
<a id='x1-65207r89'></a><span class='ecrm-0500'>89</span><span class='ectt-0800'>{</span>
<a id='x1-65209r90'></a><span class='ecrm-0500'>90</span><span class='ectt-0800'>    </span><span id='textcolor3403'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (atomic_cmpxchg(&amp;already_open, CDEV_NOT_USED, CDEV_EXCLUSIVE_OPEN))</span>
<a id='x1-65211r91'></a><span class='ecrm-0500'>91</span><span class='ectt-0800'>        </span><span id='textcolor3404'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EBUSY;</span>
<a id='x1-65213r92'></a><span class='ecrm-0500'>92</span>
<a id='x1-65215r93'></a><span class='ecrm-0500'>93</span><span class='ectt-0800'>    sprintf(msg, static_key_enabled(&amp;fkey) ? </span><span id='textcolor3405'><span class='ectt-0800'>"enabled</span></span><span id='textcolor3406'><span class='ectt-0800'>\n</span></span><span id='textcolor3407'><span class='ectt-0800'>"</span></span><span class='ectt-0800'> : </span><span id='textcolor3408'><span class='ectt-0800'>"disabled</span></span><span id='textcolor3409'><span class='ectt-0800'>\n</span></span><span id='textcolor3410'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65217r94'></a><span class='ecrm-0500'>94</span>
<a id='x1-65219r95'></a><span class='ecrm-0500'>95</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3411'><span class='ectt-0800'>"fastpath 1</span></span><span id='textcolor3412'><span class='ectt-0800'>\n</span></span><span id='textcolor3413'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65221r96'></a><span class='ecrm-0500'>96</span><span class='ectt-0800'>    </span><span id='textcolor3414'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (static_branch_unlikely(&amp;fkey))</span>
<a id='x1-65223r97'></a><span class='ecrm-0500'>97</span><span class='ectt-0800'>        pr_alert(</span><span id='textcolor3415'><span class='ectt-0800'>"do unlikely thing</span></span><span id='textcolor3416'><span class='ectt-0800'>\n</span></span><span id='textcolor3417'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65225r98'></a><span class='ecrm-0500'>98</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3418'><span class='ectt-0800'>"fastpath 2</span></span><span id='textcolor3419'><span class='ectt-0800'>\n</span></span><span id='textcolor3420'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65227r99'></a><span class='ecrm-0500'>99</span>
<a id='x1-65229r100'></a><span class='ecrm-0500'>100</span><span class='ectt-0800'>    try_module_get(THIS_MODULE);</span>
<a id='x1-65231r101'></a><span class='ecrm-0500'>101</span>
<a id='x1-65233r102'></a><span class='ecrm-0500'>102</span><span class='ectt-0800'>    </span><span id='textcolor3421'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65235r103'></a><span class='ecrm-0500'>103</span><span class='ectt-0800'>}</span>
<a id='x1-65237r104'></a><span class='ecrm-0500'>104</span>
<a id='x1-65239r105'></a><span class='ecrm-0500'>105</span><span id='textcolor3422'><span class='ectt-0800'>/**</span></span>
<a id='x1-65241r106'></a><span class='ecrm-0500'>106</span><span id='textcolor3423'><span class='ectt-0800'> * Called when a process closes the device file</span></span>
<a id='x1-65243r107'></a><span class='ecrm-0500'>107</span><span id='textcolor3424'><span class='ectt-0800'> */</span></span>
<a id='x1-65245r108'></a><span class='ecrm-0500'>108</span><span id='textcolor3425'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3426'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> device_release(</span><span id='textcolor3427'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> inode *inode, </span><span id='textcolor3428'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *file)</span>
<a id='x1-65247r109'></a><span class='ecrm-0500'>109</span><span class='ectt-0800'>{</span>
<a id='x1-65249r110'></a><span class='ecrm-0500'>110</span><span class='ectt-0800'>    </span><span id='textcolor3429'><span class='ectt-0800'>/* We are now ready for our next caller. */</span></span>
<a id='x1-65251r111'></a><span class='ecrm-0500'>111</span><span class='ectt-0800'>    atomic_set(&amp;already_open, CDEV_NOT_USED);</span>
<a id='x1-65253r112'></a><span class='ecrm-0500'>112</span>
<a id='x1-65255r113'></a><span class='ecrm-0500'>113</span><span class='ectt-0800'>    </span><span id='textcolor3430'><span class='ectt-0800'>/**</span></span>
<a id='x1-65257r114'></a><span class='ecrm-0500'>114</span><span id='textcolor3431'><span class='ectt-0800'>     * Decrement the usage count, or else once you opened the file, you will</span></span>
<a id='x1-65259r115'></a><span class='ecrm-0500'>115</span><span id='textcolor3432'><span class='ectt-0800'>     * never get rid of the module.</span></span>
<a id='x1-65261r116'></a><span class='ecrm-0500'>116</span><span id='textcolor3433'><span class='ectt-0800'>     */</span></span>
<a id='x1-65263r117'></a><span class='ecrm-0500'>117</span><span class='ectt-0800'>    module_put(THIS_MODULE);</span>
<a id='x1-65265r118'></a><span class='ecrm-0500'>118</span>
<a id='x1-65267r119'></a><span class='ecrm-0500'>119</span><span class='ectt-0800'>    </span><span id='textcolor3434'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65269r120'></a><span class='ecrm-0500'>120</span><span class='ectt-0800'>}</span>
<a id='x1-65271r121'></a><span class='ecrm-0500'>121</span>
<a id='x1-65273r122'></a><span class='ecrm-0500'>122</span><span id='textcolor3435'><span class='ectt-0800'>/**</span></span>
<a id='x1-65275r123'></a><span class='ecrm-0500'>123</span><span id='textcolor3436'><span class='ectt-0800'> * Called when a process, which already opened the dev file, attempts to</span></span>
<a id='x1-65277r124'></a><span class='ecrm-0500'>124</span><span id='textcolor3437'><span class='ectt-0800'> * read from it.</span></span>
<a id='x1-65279r125'></a><span class='ecrm-0500'>125</span><span id='textcolor3438'><span class='ectt-0800'> */</span></span>
<a id='x1-65281r126'></a><span class='ecrm-0500'>126</span><span id='textcolor3439'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3440'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> device_read(</span><span id='textcolor3441'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *filp, </span><span id='textcolor3442'><span class='ectt-0800'>/* see include/linux/fs.h */</span></span>
<a id='x1-65283r127'></a><span class='ecrm-0500'>127</span><span class='ectt-0800'>                           </span><span id='textcolor3443'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> __user *buffer, </span><span id='textcolor3444'><span class='ectt-0800'>/* buffer to fill with data */</span></span>
<a id='x1-65285r128'></a><span class='ecrm-0500'>128</span><span class='ectt-0800'>                           </span><span id='textcolor3445'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> length, </span><span id='textcolor3446'><span class='ectt-0800'>/* length of the buffer */</span></span>
<a id='x1-65287r129'></a><span class='ecrm-0500'>129</span><span class='ectt-0800'>                           loff_t *offset)</span>
<a id='x1-65289r130'></a><span class='ecrm-0500'>130</span><span class='ectt-0800'>{</span>
<a id='x1-65291r131'></a><span class='ecrm-0500'>131</span><span class='ectt-0800'>    </span><span id='textcolor3447'><span class='ectt-0800'>/* Number of the bytes actually written to the buffer */</span></span>
<a id='x1-65293r132'></a><span class='ecrm-0500'>132</span><span class='ectt-0800'>    </span><span id='textcolor3448'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> bytes_read = 0;</span>
<a id='x1-65295r133'></a><span class='ecrm-0500'>133</span><span class='ectt-0800'>    </span><span id='textcolor3449'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor3450'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *msg_ptr = msg;</span>
<a id='x1-65297r134'></a><span class='ecrm-0500'>134</span>
<a id='x1-65299r135'></a><span class='ecrm-0500'>135</span><span class='ectt-0800'>    </span><span id='textcolor3451'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (!*(msg_ptr + *offset)) { </span><span id='textcolor3452'><span class='ectt-0800'>/* We are at the end of the message */</span></span>
<a id='x1-65301r136'></a><span class='ecrm-0500'>136</span><span class='ectt-0800'>        *offset = 0; </span><span id='textcolor3453'><span class='ectt-0800'>/* reset the offset */</span></span>
<a id='x1-65303r137'></a><span class='ecrm-0500'>137</span><span class='ectt-0800'>        </span><span id='textcolor3454'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> 0; </span><span id='textcolor3455'><span class='ectt-0800'>/* signify end of file */</span></span>
<a id='x1-65305r138'></a><span class='ecrm-0500'>138</span><span class='ectt-0800'>    }</span>
<a id='x1-65307r139'></a><span class='ecrm-0500'>139</span>
<a id='x1-65309r140'></a><span class='ecrm-0500'>140</span><span class='ectt-0800'>    msg_ptr += *offset;</span>
<a id='x1-65311r141'></a><span class='ecrm-0500'>141</span>
<a id='x1-65313r142'></a><span class='ecrm-0500'>142</span><span class='ectt-0800'>    </span><span id='textcolor3456'><span class='ectt-0800'>/* Actually put the data into the buffer */</span></span>
<a id='x1-65315r143'></a><span class='ecrm-0500'>143</span><span class='ectt-0800'>    </span><span id='textcolor3457'><span class='ectt-0800'>while</span></span><span class='ectt-0800'> (length &amp;&amp; *msg_ptr) {</span>
<a id='x1-65317r144'></a><span class='ecrm-0500'>144</span><span class='ectt-0800'>        </span><span id='textcolor3458'><span class='ectt-0800'>/**</span></span>
<a id='x1-65319r145'></a><span class='ecrm-0500'>145</span><span id='textcolor3459'><span class='ectt-0800'>         * The buffer is in the user data segment, not the kernel</span></span>
<a id='x1-65321r146'></a><span class='ecrm-0500'>146</span><span id='textcolor3460'><span class='ectt-0800'>         * segment so "*" assignment won</span><span class='tctt-0800'>'</span><span class='ectt-0800'>t work. We have to use</span></span>
<a id='x1-65323r147'></a><span class='ecrm-0500'>147</span><span id='textcolor3461'><span class='ectt-0800'>         * put_user which copies data from the kernel data segment to</span></span>
<a id='x1-65325r148'></a><span class='ecrm-0500'>148</span><span id='textcolor3462'><span class='ectt-0800'>         * the user data segment.</span></span>
<a id='x1-65327r149'></a><span class='ecrm-0500'>149</span><span id='textcolor3463'><span class='ectt-0800'>         */</span></span>
<a id='x1-65329r150'></a><span class='ecrm-0500'>150</span><span class='ectt-0800'>        put_user(*(msg_ptr++), buffer++);</span>
<a id='x1-65331r151'></a><span class='ecrm-0500'>151</span><span class='ectt-0800'>        length--;</span>
<a id='x1-65333r152'></a><span class='ecrm-0500'>152</span><span class='ectt-0800'>        bytes_read++;</span>
<a id='x1-65335r153'></a><span class='ecrm-0500'>153</span><span class='ectt-0800'>    }</span>
<a id='x1-65337r154'></a><span class='ecrm-0500'>154</span>
<a id='x1-65339r155'></a><span class='ecrm-0500'>155</span><span class='ectt-0800'>    *offset += bytes_read;</span>
<a id='x1-65341r156'></a><span class='ecrm-0500'>156</span>
<a id='x1-65343r157'></a><span class='ecrm-0500'>157</span><span class='ectt-0800'>    </span><span id='textcolor3464'><span class='ectt-0800'>/* Most read functions return the number of bytes put into the buffer. */</span></span>
<a id='x1-65345r158'></a><span class='ecrm-0500'>158</span><span class='ectt-0800'>    </span><span id='textcolor3465'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> bytes_read;</span>
<a id='x1-65347r159'></a><span class='ecrm-0500'>159</span><span class='ectt-0800'>}</span>
<a id='x1-65193r82'></a><span class='ecrm-0500'>82</span><span class='ectt-0800'>    </span><span id='textcolor3396'><span class='ectt-0800'>/* Unregister the device */</span></span>
<a id='x1-65195r83'></a><span class='ecrm-0500'>83</span><span class='ectt-0800'>    unregister_chrdev(major, DEVICE_NAME);</span>
<a id='x1-65197r84'></a><span class='ecrm-0500'>84</span><span class='ectt-0800'>}</span>
<a id='x1-65199r85'></a><span class='ecrm-0500'>85</span>
<a id='x1-65201r86'></a><span class='ecrm-0500'>86</span><span id='textcolor3397'><span class='ectt-0800'>/* Methods */</span></span>
<a id='x1-65203r87'></a><span class='ecrm-0500'>87</span>
<a id='x1-65205r88'></a><span class='ecrm-0500'>88</span><span id='textcolor3398'><span class='ectt-0800'>/**</span></span>
<a id='x1-65207r89'></a><span class='ecrm-0500'>89</span><span id='textcolor3399'><span class='ectt-0800'> * Called when a process tried to open the device file, like</span></span>
<a id='x1-65209r90'></a><span class='ecrm-0500'>90</span><span id='textcolor3400'><span class='ectt-0800'> * cat /dev/key_state</span></span>
<a id='x1-65211r91'></a><span class='ecrm-0500'>91</span><span id='textcolor3401'><span class='ectt-0800'> */</span></span>
<a id='x1-65213r92'></a><span class='ecrm-0500'>92</span><span id='textcolor3402'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3403'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> device_open(</span><span id='textcolor3404'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> inode *inode, </span><span id='textcolor3405'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *file)</span>
<a id='x1-65215r93'></a><span class='ecrm-0500'>93</span><span class='ectt-0800'>{</span>
<a id='x1-65217r94'></a><span class='ecrm-0500'>94</span><span class='ectt-0800'>    </span><span id='textcolor3406'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (atomic_cmpxchg(&amp;already_open, CDEV_NOT_USED, CDEV_EXCLUSIVE_OPEN))</span>
<a id='x1-65219r95'></a><span class='ecrm-0500'>95</span><span class='ectt-0800'>        </span><span id='textcolor3407'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EBUSY;</span>
<a id='x1-65221r96'></a><span class='ecrm-0500'>96</span>
<a id='x1-65223r97'></a><span class='ecrm-0500'>97</span><span class='ectt-0800'>    sprintf(msg, static_key_enabled(&amp;fkey) ? </span><span id='textcolor3408'><span class='ectt-0800'>"enabled</span></span><span id='textcolor3409'><span class='ectt-0800'>\n</span></span><span id='textcolor3410'><span class='ectt-0800'>"</span></span><span class='ectt-0800'> : </span><span id='textcolor3411'><span class='ectt-0800'>"disabled</span></span><span id='textcolor3412'><span class='ectt-0800'>\n</span></span><span id='textcolor3413'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65225r98'></a><span class='ecrm-0500'>98</span>
<a id='x1-65227r99'></a><span class='ecrm-0500'>99</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3414'><span class='ectt-0800'>"fastpath 1</span></span><span id='textcolor3415'><span class='ectt-0800'>\n</span></span><span id='textcolor3416'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65229r100'></a><span class='ecrm-0500'>100</span><span class='ectt-0800'>    </span><span id='textcolor3417'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (static_branch_unlikely(&amp;fkey))</span>
<a id='x1-65231r101'></a><span class='ecrm-0500'>101</span><span class='ectt-0800'>        pr_alert(</span><span id='textcolor3418'><span class='ectt-0800'>"do unlikely thing</span></span><span id='textcolor3419'><span class='ectt-0800'>\n</span></span><span id='textcolor3420'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65233r102'></a><span class='ecrm-0500'>102</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3421'><span class='ectt-0800'>"fastpath 2</span></span><span id='textcolor3422'><span class='ectt-0800'>\n</span></span><span id='textcolor3423'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65235r103'></a><span class='ecrm-0500'>103</span>
<a id='x1-65237r104'></a><span class='ecrm-0500'>104</span><span class='ectt-0800'>    try_module_get(THIS_MODULE);</span>
<a id='x1-65239r105'></a><span class='ecrm-0500'>105</span>
<a id='x1-65241r106'></a><span class='ecrm-0500'>106</span><span class='ectt-0800'>    </span><span id='textcolor3424'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65243r107'></a><span class='ecrm-0500'>107</span><span class='ectt-0800'>}</span>
<a id='x1-65245r108'></a><span class='ecrm-0500'>108</span>
<a id='x1-65247r109'></a><span class='ecrm-0500'>109</span><span id='textcolor3425'><span class='ectt-0800'>/**</span></span>
<a id='x1-65249r110'></a><span class='ecrm-0500'>110</span><span id='textcolor3426'><span class='ectt-0800'> * Called when a process closes the device file</span></span>
<a id='x1-65251r111'></a><span class='ecrm-0500'>111</span><span id='textcolor3427'><span class='ectt-0800'> */</span></span>
<a id='x1-65253r112'></a><span class='ecrm-0500'>112</span><span id='textcolor3428'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3429'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> device_release(</span><span id='textcolor3430'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> inode *inode, </span><span id='textcolor3431'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *file)</span>
<a id='x1-65255r113'></a><span class='ecrm-0500'>113</span><span class='ectt-0800'>{</span>
<a id='x1-65257r114'></a><span class='ecrm-0500'>114</span><span class='ectt-0800'>    </span><span id='textcolor3432'><span class='ectt-0800'>/* We are now ready for our next caller. */</span></span>
<a id='x1-65259r115'></a><span class='ecrm-0500'>115</span><span class='ectt-0800'>    atomic_set(&amp;already_open, CDEV_NOT_USED);</span>
<a id='x1-65261r116'></a><span class='ecrm-0500'>116</span>
<a id='x1-65263r117'></a><span class='ecrm-0500'>117</span><span class='ectt-0800'>    </span><span id='textcolor3433'><span class='ectt-0800'>/**</span></span>
<a id='x1-65265r118'></a><span class='ecrm-0500'>118</span><span id='textcolor3434'><span class='ectt-0800'>     * Decrement the usage count, or else once you opened the file, you will</span></span>
<a id='x1-65267r119'></a><span class='ecrm-0500'>119</span><span id='textcolor3435'><span class='ectt-0800'>     * never get rid of the module.</span></span>
<a id='x1-65269r120'></a><span class='ecrm-0500'>120</span><span id='textcolor3436'><span class='ectt-0800'>     */</span></span>
<a id='x1-65271r121'></a><span class='ecrm-0500'>121</span><span class='ectt-0800'>    module_put(THIS_MODULE);</span>
<a id='x1-65273r122'></a><span class='ecrm-0500'>122</span>
<a id='x1-65275r123'></a><span class='ecrm-0500'>123</span><span class='ectt-0800'>    </span><span id='textcolor3437'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65277r124'></a><span class='ecrm-0500'>124</span><span class='ectt-0800'>}</span>
<a id='x1-65279r125'></a><span class='ecrm-0500'>125</span>
<a id='x1-65281r126'></a><span class='ecrm-0500'>126</span><span id='textcolor3438'><span class='ectt-0800'>/**</span></span>
<a id='x1-65283r127'></a><span class='ecrm-0500'>127</span><span id='textcolor3439'><span class='ectt-0800'> * Called when a process, which already opened the dev file, attempts to</span></span>
<a id='x1-65285r128'></a><span class='ecrm-0500'>128</span><span id='textcolor3440'><span class='ectt-0800'> * read from it.</span></span>
<a id='x1-65287r129'></a><span class='ecrm-0500'>129</span><span id='textcolor3441'><span class='ectt-0800'> */</span></span>
<a id='x1-65289r130'></a><span class='ecrm-0500'>130</span><span id='textcolor3442'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3443'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> device_read(</span><span id='textcolor3444'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *filp, </span><span id='textcolor3445'><span class='ectt-0800'>/* see include/linux/fs.h */</span></span>
<a id='x1-65291r131'></a><span class='ecrm-0500'>131</span><span class='ectt-0800'>                           </span><span id='textcolor3446'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> __user *buffer, </span><span id='textcolor3447'><span class='ectt-0800'>/* buffer to fill with data */</span></span>
<a id='x1-65293r132'></a><span class='ecrm-0500'>132</span><span class='ectt-0800'>                           </span><span id='textcolor3448'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> length, </span><span id='textcolor3449'><span class='ectt-0800'>/* length of the buffer */</span></span>
<a id='x1-65295r133'></a><span class='ecrm-0500'>133</span><span class='ectt-0800'>                           loff_t *offset)</span>
<a id='x1-65297r134'></a><span class='ecrm-0500'>134</span><span class='ectt-0800'>{</span>
<a id='x1-65299r135'></a><span class='ecrm-0500'>135</span><span class='ectt-0800'>    </span><span id='textcolor3450'><span class='ectt-0800'>/* Number of the bytes actually written to the buffer */</span></span>
<a id='x1-65301r136'></a><span class='ecrm-0500'>136</span><span class='ectt-0800'>    </span><span id='textcolor3451'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> bytes_read = 0;</span>
<a id='x1-65303r137'></a><span class='ecrm-0500'>137</span><span class='ectt-0800'>    </span><span id='textcolor3452'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor3453'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *msg_ptr = msg;</span>
<a id='x1-65305r138'></a><span class='ecrm-0500'>138</span>
<a id='x1-65307r139'></a><span class='ecrm-0500'>139</span><span class='ectt-0800'>    </span><span id='textcolor3454'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (!*(msg_ptr + *offset)) { </span><span id='textcolor3455'><span class='ectt-0800'>/* We are at the end of the message */</span></span>
<a id='x1-65309r140'></a><span class='ecrm-0500'>140</span><span class='ectt-0800'>        *offset = 0; </span><span id='textcolor3456'><span class='ectt-0800'>/* reset the offset */</span></span>
<a id='x1-65311r141'></a><span class='ecrm-0500'>141</span><span class='ectt-0800'>        </span><span id='textcolor3457'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> 0; </span><span id='textcolor3458'><span class='ectt-0800'>/* signify end of file */</span></span>
<a id='x1-65313r142'></a><span class='ecrm-0500'>142</span><span class='ectt-0800'>    }</span>
<a id='x1-65315r143'></a><span class='ecrm-0500'>143</span>
<a id='x1-65317r144'></a><span class='ecrm-0500'>144</span><span class='ectt-0800'>    msg_ptr += *offset;</span>
<a id='x1-65319r145'></a><span class='ecrm-0500'>145</span>
<a id='x1-65321r146'></a><span class='ecrm-0500'>146</span><span class='ectt-0800'>    </span><span id='textcolor3459'><span class='ectt-0800'>/* Actually put the data into the buffer */</span></span>
<a id='x1-65323r147'></a><span class='ecrm-0500'>147</span><span class='ectt-0800'>    </span><span id='textcolor3460'><span class='ectt-0800'>while</span></span><span class='ectt-0800'> (length &amp;&amp; *msg_ptr) {</span>
<a id='x1-65325r148'></a><span class='ecrm-0500'>148</span><span class='ectt-0800'>        </span><span id='textcolor3461'><span class='ectt-0800'>/**</span></span>
<a id='x1-65327r149'></a><span class='ecrm-0500'>149</span><span id='textcolor3462'><span class='ectt-0800'>         * The buffer is in the user data segment, not the kernel</span></span>
<a id='x1-65329r150'></a><span class='ecrm-0500'>150</span><span id='textcolor3463'><span class='ectt-0800'>         * segment so "*" assignment won</span><span class='tctt-0800'>'</span><span class='ectt-0800'>t work. We have to use</span></span>
<a id='x1-65331r151'></a><span class='ecrm-0500'>151</span><span id='textcolor3464'><span class='ectt-0800'>         * put_user which copies data from the kernel data segment to</span></span>
<a id='x1-65333r152'></a><span class='ecrm-0500'>152</span><span id='textcolor3465'><span class='ectt-0800'>         * the user data segment.</span></span>
<a id='x1-65335r153'></a><span class='ecrm-0500'>153</span><span id='textcolor3466'><span class='ectt-0800'>         */</span></span>
<a id='x1-65337r154'></a><span class='ecrm-0500'>154</span><span class='ectt-0800'>        put_user(*(msg_ptr++), buffer++);</span>
<a id='x1-65339r155'></a><span class='ecrm-0500'>155</span><span class='ectt-0800'>        length--;</span>
<a id='x1-65341r156'></a><span class='ecrm-0500'>156</span><span class='ectt-0800'>        bytes_read++;</span>
<a id='x1-65343r157'></a><span class='ecrm-0500'>157</span><span class='ectt-0800'>    }</span>
<a id='x1-65345r158'></a><span class='ecrm-0500'>158</span>
<a id='x1-65347r159'></a><span class='ecrm-0500'>159</span><span class='ectt-0800'>    *offset += bytes_read;</span>
<a id='x1-65349r160'></a><span class='ecrm-0500'>160</span>
<a id='x1-65351r161'></a><span class='ecrm-0500'>161</span><span id='textcolor3466'><span class='ectt-0800'>/* Called when a process writes to dev file; echo "enable" &gt; /dev/key_state */</span></span>
<a id='x1-65353r162'></a><span class='ecrm-0500'>162</span><span id='textcolor3467'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3468'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> device_write(</span><span id='textcolor3469'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *filp, </span><span id='textcolor3470'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor3471'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> __user *buffer,</span>
<a id='x1-65355r163'></a><span class='ecrm-0500'>163</span><span class='ectt-0800'>                            </span><span id='textcolor3472'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> length, loff_t *offset)</span>
<a id='x1-65357r164'></a><span class='ecrm-0500'>164</span><span class='ectt-0800'>{</span>
<a id='x1-65359r165'></a><span class='ecrm-0500'>165</span><span class='ectt-0800'>    </span><span id='textcolor3473'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> command[10];</span>
<a id='x1-65361r166'></a><span class='ecrm-0500'>166</span>
<a id='x1-65363r167'></a><span class='ecrm-0500'>167</span><span class='ectt-0800'>    </span><span id='textcolor3474'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (length &gt; 10) {</span>
<a id='x1-65365r168'></a><span class='ecrm-0500'>168</span><span class='ectt-0800'>        pr_err(</span><span id='textcolor3475'><span class='ectt-0800'>"command exceeded 10 char</span></span><span id='textcolor3476'><span class='ectt-0800'>\n</span></span><span id='textcolor3477'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65367r169'></a><span class='ecrm-0500'>169</span><span class='ectt-0800'>        </span><span id='textcolor3478'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EINVAL;</span>
<a id='x1-65369r170'></a><span class='ecrm-0500'>170</span><span class='ectt-0800'>    }</span>
<a id='x1-65371r171'></a><span class='ecrm-0500'>171</span>
<a id='x1-65373r172'></a><span class='ecrm-0500'>172</span><span class='ectt-0800'>    </span><span id='textcolor3479'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (copy_from_user(command, buffer, length))</span>
<a id='x1-65375r173'></a><span class='ecrm-0500'>173</span><span class='ectt-0800'>        </span><span id='textcolor3480'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EFAULT;</span>
<a id='x1-65377r174'></a><span class='ecrm-0500'>174</span>
<a id='x1-65379r175'></a><span class='ecrm-0500'>175</span><span class='ectt-0800'>    </span><span id='textcolor3481'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (strncmp(command, </span><span id='textcolor3482'><span class='ectt-0800'>"enable"</span></span><span class='ectt-0800'>, strlen(</span><span id='textcolor3483'><span class='ectt-0800'>"enable"</span></span><span class='ectt-0800'>)) == 0)</span>
<a id='x1-65381r176'></a><span class='ecrm-0500'>176</span><span class='ectt-0800'>        static_branch_enable(&amp;fkey);</span>
<a id='x1-65383r177'></a><span class='ecrm-0500'>177</span><span class='ectt-0800'>    </span><span id='textcolor3484'><span class='ectt-0800'>else</span></span><span class='ectt-0800'> </span><span id='textcolor3485'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (strncmp(command, </span><span id='textcolor3486'><span class='ectt-0800'>"disable"</span></span><span class='ectt-0800'>, strlen(</span><span id='textcolor3487'><span class='ectt-0800'>"disable"</span></span><span class='ectt-0800'>)) == 0)</span>
<a id='x1-65385r178'></a><span class='ecrm-0500'>178</span><span class='ectt-0800'>        static_branch_disable(&amp;fkey);</span>
<a id='x1-65387r179'></a><span class='ecrm-0500'>179</span><span class='ectt-0800'>    </span><span id='textcolor3488'><span class='ectt-0800'>else</span></span><span class='ectt-0800'> {</span>
<a id='x1-65389r180'></a><span class='ecrm-0500'>180</span><span class='ectt-0800'>        pr_err(</span><span id='textcolor3489'><span class='ectt-0800'>"Invalid command: %s</span></span><span id='textcolor3490'><span class='ectt-0800'>\n</span></span><span id='textcolor3491'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, command);</span>
<a id='x1-65391r181'></a><span class='ecrm-0500'>181</span><span class='ectt-0800'>        </span><span id='textcolor3492'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EINVAL;</span>
<a id='x1-65393r182'></a><span class='ecrm-0500'>182</span><span class='ectt-0800'>    }</span>
<a id='x1-65395r183'></a><span class='ecrm-0500'>183</span>
<a id='x1-65397r184'></a><span class='ecrm-0500'>184</span><span class='ectt-0800'>    </span><span id='textcolor3493'><span class='ectt-0800'>/* Again, return the number of input characters used. */</span></span>
<a id='x1-65399r185'></a><span class='ecrm-0500'>185</span><span class='ectt-0800'>    </span><span id='textcolor3494'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> length;</span>
<a id='x1-65401r186'></a><span class='ecrm-0500'>186</span><span class='ectt-0800'>}</span>
<a id='x1-65351r161'></a><span class='ecrm-0500'>161</span><span class='ectt-0800'>    </span><span id='textcolor3467'><span class='ectt-0800'>/* Most read functions return the number of bytes put into the buffer. */</span></span>
<a id='x1-65353r162'></a><span class='ecrm-0500'>162</span><span class='ectt-0800'>    </span><span id='textcolor3468'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> bytes_read;</span>
<a id='x1-65355r163'></a><span class='ecrm-0500'>163</span><span class='ectt-0800'>}</span>
<a id='x1-65357r164'></a><span class='ecrm-0500'>164</span>
<a id='x1-65359r165'></a><span class='ecrm-0500'>165</span><span id='textcolor3469'><span class='ectt-0800'>/* Called when a process writes to dev file; echo "enable" &gt; /dev/key_state */</span></span>
<a id='x1-65361r166'></a><span class='ecrm-0500'>166</span><span id='textcolor3470'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3471'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> device_write(</span><span id='textcolor3472'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *filp, </span><span id='textcolor3473'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor3474'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> __user *buffer,</span>
<a id='x1-65363r167'></a><span class='ecrm-0500'>167</span><span class='ectt-0800'>                            </span><span id='textcolor3475'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> length, loff_t *offset)</span>
<a id='x1-65365r168'></a><span class='ecrm-0500'>168</span><span class='ectt-0800'>{</span>
<a id='x1-65367r169'></a><span class='ecrm-0500'>169</span><span class='ectt-0800'>    </span><span id='textcolor3476'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> command[10];</span>
<a id='x1-65369r170'></a><span class='ecrm-0500'>170</span>
<a id='x1-65371r171'></a><span class='ecrm-0500'>171</span><span class='ectt-0800'>    </span><span id='textcolor3477'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (length &gt; 10) {</span>
<a id='x1-65373r172'></a><span class='ecrm-0500'>172</span><span class='ectt-0800'>        pr_err(</span><span id='textcolor3478'><span class='ectt-0800'>"command exceeded 10 char</span></span><span id='textcolor3479'><span class='ectt-0800'>\n</span></span><span id='textcolor3480'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65375r173'></a><span class='ecrm-0500'>173</span><span class='ectt-0800'>        </span><span id='textcolor3481'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EINVAL;</span>
<a id='x1-65377r174'></a><span class='ecrm-0500'>174</span><span class='ectt-0800'>    }</span>
<a id='x1-65379r175'></a><span class='ecrm-0500'>175</span>
<a id='x1-65381r176'></a><span class='ecrm-0500'>176</span><span class='ectt-0800'>    </span><span id='textcolor3482'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (copy_from_user(command, buffer, length))</span>
<a id='x1-65383r177'></a><span class='ecrm-0500'>177</span><span class='ectt-0800'>        </span><span id='textcolor3483'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EFAULT;</span>
<a id='x1-65385r178'></a><span class='ecrm-0500'>178</span>
<a id='x1-65387r179'></a><span class='ecrm-0500'>179</span><span class='ectt-0800'>    </span><span id='textcolor3484'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (strncmp(command, </span><span id='textcolor3485'><span class='ectt-0800'>"enable"</span></span><span class='ectt-0800'>, strlen(</span><span id='textcolor3486'><span class='ectt-0800'>"enable"</span></span><span class='ectt-0800'>)) == 0)</span>
<a id='x1-65389r180'></a><span class='ecrm-0500'>180</span><span class='ectt-0800'>        static_branch_enable(&amp;fkey);</span>
<a id='x1-65391r181'></a><span class='ecrm-0500'>181</span><span class='ectt-0800'>    </span><span id='textcolor3487'><span class='ectt-0800'>else</span></span><span class='ectt-0800'> </span><span id='textcolor3488'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (strncmp(command, </span><span id='textcolor3489'><span class='ectt-0800'>"disable"</span></span><span class='ectt-0800'>, strlen(</span><span id='textcolor3490'><span class='ectt-0800'>"disable"</span></span><span class='ectt-0800'>)) == 0)</span>
<a id='x1-65393r182'></a><span class='ecrm-0500'>182</span><span class='ectt-0800'>        static_branch_disable(&amp;fkey);</span>
<a id='x1-65395r183'></a><span class='ecrm-0500'>183</span><span class='ectt-0800'>    </span><span id='textcolor3491'><span class='ectt-0800'>else</span></span><span class='ectt-0800'> {</span>
<a id='x1-65397r184'></a><span class='ecrm-0500'>184</span><span class='ectt-0800'>        pr_err(</span><span id='textcolor3492'><span class='ectt-0800'>"Invalid command: %s</span></span><span id='textcolor3493'><span class='ectt-0800'>\n</span></span><span id='textcolor3494'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, command);</span>
<a id='x1-65399r185'></a><span class='ecrm-0500'>185</span><span class='ectt-0800'>        </span><span id='textcolor3495'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EINVAL;</span>
<a id='x1-65401r186'></a><span class='ecrm-0500'>186</span><span class='ectt-0800'>    }</span>
<a id='x1-65403r187'></a><span class='ecrm-0500'>187</span>
<a id='x1-65405r188'></a><span class='ecrm-0500'>188</span><span class='ectt-0800'>module_init(chardev_init);</span>
<a id='x1-65407r189'></a><span class='ecrm-0500'>189</span><span class='ectt-0800'>module_exit(chardev_exit);</span>
<a id='x1-65409r190'></a><span class='ecrm-0500'>190</span>
<a id='x1-65411r191'></a><span class='ecrm-0500'>191</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3495'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
<a id='x1-65405r188'></a><span class='ecrm-0500'>188</span><span class='ectt-0800'>    </span><span id='textcolor3496'><span class='ectt-0800'>/* Again, return the number of input characters used. */</span></span>
<a id='x1-65407r189'></a><span class='ecrm-0500'>189</span><span class='ectt-0800'>    </span><span id='textcolor3497'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> length;</span>
<a id='x1-65409r190'></a><span class='ecrm-0500'>190</span><span class='ectt-0800'>}</span>
<a id='x1-65411r191'></a><span class='ecrm-0500'>191</span>
<a id='x1-65413r192'></a><span class='ecrm-0500'>192</span><span class='ectt-0800'>module_init(chardev_init);</span>
<a id='x1-65415r193'></a><span class='ecrm-0500'>193</span><span class='ectt-0800'>module_exit(chardev_exit);</span>
<a id='x1-65417r194'></a><span class='ecrm-0500'>194</span>
<a id='x1-65419r195'></a><span class='ecrm-0500'>195</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3498'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
<!-- l. 2076 --><p class='indent'> To check the state of the static key, we can use the <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/dev/key_state</span></span></span>
interface.
</p><!-- l. 1 --><p class='indent'>
</p>
<pre class='fancyvrb' id='fancyvrb99'><a id='x1-65414r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>cat /dev/key_state</span></pre>
<pre class='fancyvrb' id='fancyvrb99'><a id='x1-65422r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>cat /dev/key_state</span></pre>
<!-- l. 2082 --><p class='indent'> This will display the current state of the key, which is disabled by default.
</p><!-- l. 2084 --><p class='indent'> To change the state of the static key, we can perform a write operation on the
file:
</p><!-- l. 1 --><p class='indent'>
</p>
<pre class='fancyvrb' id='fancyvrb100'><a id='x1-65417r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo enable &gt; /dev/key_state</span></pre>
<pre class='fancyvrb' id='fancyvrb100'><a id='x1-65425r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo enable &gt; /dev/key_state</span></pre>
<!-- l. 2090 --><p class='indent'> This will enable the static key, causing the code path to switch from the fastpath
to the slowpath.
</p><!-- l. 2092 --><p class='indent'> In some cases, the key is enabled or disabled at initialization and never changed,

View File

@ -4086,116 +4086,119 @@ span#textcolor3382{color:rgb(0,0,255)}
span#textcolor3383{color:rgb(163,20,20)}
span#textcolor3384{color:rgb(163,20,20)}
span#textcolor3385{color:rgb(163,20,20)}
span#textcolor3386{color:rgb(163,20,20)}
span#textcolor3387{color:rgb(163,20,20)}
span#textcolor3388{color:rgb(163,20,20)}
span#textcolor3389{color:rgb(0,0,255)}
span#textcolor3390{color:rgb(0,0,255)}
span#textcolor3391{color:rgb(43,145,175)}
span#textcolor3392{color:rgb(43,145,175)}
span#textcolor3393{color:rgb(0,127,0)}
span#textcolor3394{color:rgb(0,127,0)}
span#textcolor3395{color:rgb(0,127,0)}
span#textcolor3386{color:rgb(0,0,255)}
span#textcolor3387{color:rgb(0,0,255)}
span#textcolor3388{color:rgb(0,0,255)}
span#textcolor3389{color:rgb(163,20,20)}
span#textcolor3390{color:rgb(163,20,20)}
span#textcolor3391{color:rgb(163,20,20)}
span#textcolor3392{color:rgb(0,0,255)}
span#textcolor3393{color:rgb(0,0,255)}
span#textcolor3394{color:rgb(43,145,175)}
span#textcolor3395{color:rgb(43,145,175)}
span#textcolor3396{color:rgb(0,127,0)}
span#textcolor3397{color:rgb(0,127,0)}
span#textcolor3398{color:rgb(0,127,0)}
span#textcolor3399{color:rgb(0,0,255)}
span#textcolor3400{color:rgb(43,145,175)}
span#textcolor3401{color:rgb(0,0,255)}
span#textcolor3399{color:rgb(0,127,0)}
span#textcolor3400{color:rgb(0,127,0)}
span#textcolor3401{color:rgb(0,127,0)}
span#textcolor3402{color:rgb(0,0,255)}
span#textcolor3403{color:rgb(0,0,255)}
span#textcolor3403{color:rgb(43,145,175)}
span#textcolor3404{color:rgb(0,0,255)}
span#textcolor3405{color:rgb(163,20,20)}
span#textcolor3406{color:rgb(163,20,20)}
span#textcolor3407{color:rgb(163,20,20)}
span#textcolor3405{color:rgb(0,0,255)}
span#textcolor3406{color:rgb(0,0,255)}
span#textcolor3407{color:rgb(0,0,255)}
span#textcolor3408{color:rgb(163,20,20)}
span#textcolor3409{color:rgb(163,20,20)}
span#textcolor3410{color:rgb(163,20,20)}
span#textcolor3411{color:rgb(163,20,20)}
span#textcolor3412{color:rgb(163,20,20)}
span#textcolor3413{color:rgb(163,20,20)}
span#textcolor3414{color:rgb(0,0,255)}
span#textcolor3414{color:rgb(163,20,20)}
span#textcolor3415{color:rgb(163,20,20)}
span#textcolor3416{color:rgb(163,20,20)}
span#textcolor3417{color:rgb(163,20,20)}
span#textcolor3417{color:rgb(0,0,255)}
span#textcolor3418{color:rgb(163,20,20)}
span#textcolor3419{color:rgb(163,20,20)}
span#textcolor3420{color:rgb(163,20,20)}
span#textcolor3421{color:rgb(0,0,255)}
span#textcolor3422{color:rgb(0,127,0)}
span#textcolor3423{color:rgb(0,127,0)}
span#textcolor3424{color:rgb(0,127,0)}
span#textcolor3425{color:rgb(0,0,255)}
span#textcolor3426{color:rgb(43,145,175)}
span#textcolor3427{color:rgb(0,0,255)}
span#textcolor3421{color:rgb(163,20,20)}
span#textcolor3422{color:rgb(163,20,20)}
span#textcolor3423{color:rgb(163,20,20)}
span#textcolor3424{color:rgb(0,0,255)}
span#textcolor3425{color:rgb(0,127,0)}
span#textcolor3426{color:rgb(0,127,0)}
span#textcolor3427{color:rgb(0,127,0)}
span#textcolor3428{color:rgb(0,0,255)}
span#textcolor3429{color:rgb(0,127,0)}
span#textcolor3430{color:rgb(0,127,0)}
span#textcolor3431{color:rgb(0,127,0)}
span#textcolor3429{color:rgb(43,145,175)}
span#textcolor3430{color:rgb(0,0,255)}
span#textcolor3431{color:rgb(0,0,255)}
span#textcolor3432{color:rgb(0,127,0)}
span#textcolor3433{color:rgb(0,127,0)}
span#textcolor3434{color:rgb(0,0,255)}
span#textcolor3434{color:rgb(0,127,0)}
span#textcolor3435{color:rgb(0,127,0)}
span#textcolor3436{color:rgb(0,127,0)}
span#textcolor3437{color:rgb(0,127,0)}
span#textcolor3437{color:rgb(0,0,255)}
span#textcolor3438{color:rgb(0,127,0)}
span#textcolor3439{color:rgb(0,0,255)}
span#textcolor3440{color:rgb(43,145,175)}
span#textcolor3441{color:rgb(0,0,255)}
span#textcolor3442{color:rgb(0,127,0)}
span#textcolor3439{color:rgb(0,127,0)}
span#textcolor3440{color:rgb(0,127,0)}
span#textcolor3441{color:rgb(0,127,0)}
span#textcolor3442{color:rgb(0,0,255)}
span#textcolor3443{color:rgb(43,145,175)}
span#textcolor3444{color:rgb(0,127,0)}
span#textcolor3445{color:rgb(43,145,175)}
span#textcolor3446{color:rgb(0,127,0)}
span#textcolor3444{color:rgb(0,0,255)}
span#textcolor3445{color:rgb(0,127,0)}
span#textcolor3446{color:rgb(43,145,175)}
span#textcolor3447{color:rgb(0,127,0)}
span#textcolor3448{color:rgb(43,145,175)}
span#textcolor3449{color:rgb(0,0,255)}
span#textcolor3450{color:rgb(43,145,175)}
span#textcolor3451{color:rgb(0,0,255)}
span#textcolor3452{color:rgb(0,127,0)}
span#textcolor3453{color:rgb(0,127,0)}
span#textcolor3449{color:rgb(0,127,0)}
span#textcolor3450{color:rgb(0,127,0)}
span#textcolor3451{color:rgb(43,145,175)}
span#textcolor3452{color:rgb(0,0,255)}
span#textcolor3453{color:rgb(43,145,175)}
span#textcolor3454{color:rgb(0,0,255)}
span#textcolor3455{color:rgb(0,127,0)}
span#textcolor3456{color:rgb(0,127,0)}
span#textcolor3457{color:rgb(0,0,255)}
span#textcolor3458{color:rgb(0,127,0)}
span#textcolor3459{color:rgb(0,127,0)}
span#textcolor3460{color:rgb(0,127,0)}
span#textcolor3460{color:rgb(0,0,255)}
span#textcolor3461{color:rgb(0,127,0)}
span#textcolor3462{color:rgb(0,127,0)}
span#textcolor3463{color:rgb(0,127,0)}
span#textcolor3464{color:rgb(0,127,0)}
span#textcolor3465{color:rgb(0,0,255)}
span#textcolor3465{color:rgb(0,127,0)}
span#textcolor3466{color:rgb(0,127,0)}
span#textcolor3467{color:rgb(0,0,255)}
span#textcolor3468{color:rgb(43,145,175)}
span#textcolor3469{color:rgb(0,0,255)}
span#textcolor3467{color:rgb(0,127,0)}
span#textcolor3468{color:rgb(0,0,255)}
span#textcolor3469{color:rgb(0,127,0)}
span#textcolor3470{color:rgb(0,0,255)}
span#textcolor3471{color:rgb(43,145,175)}
span#textcolor3472{color:rgb(43,145,175)}
span#textcolor3473{color:rgb(43,145,175)}
span#textcolor3474{color:rgb(0,0,255)}
span#textcolor3475{color:rgb(163,20,20)}
span#textcolor3476{color:rgb(163,20,20)}
span#textcolor3477{color:rgb(163,20,20)}
span#textcolor3478{color:rgb(0,0,255)}
span#textcolor3479{color:rgb(0,0,255)}
span#textcolor3480{color:rgb(0,0,255)}
span#textcolor3472{color:rgb(0,0,255)}
span#textcolor3473{color:rgb(0,0,255)}
span#textcolor3474{color:rgb(43,145,175)}
span#textcolor3475{color:rgb(43,145,175)}
span#textcolor3476{color:rgb(43,145,175)}
span#textcolor3477{color:rgb(0,0,255)}
span#textcolor3478{color:rgb(163,20,20)}
span#textcolor3479{color:rgb(163,20,20)}
span#textcolor3480{color:rgb(163,20,20)}
span#textcolor3481{color:rgb(0,0,255)}
span#textcolor3482{color:rgb(163,20,20)}
span#textcolor3483{color:rgb(163,20,20)}
span#textcolor3482{color:rgb(0,0,255)}
span#textcolor3483{color:rgb(0,0,255)}
span#textcolor3484{color:rgb(0,0,255)}
span#textcolor3485{color:rgb(0,0,255)}
span#textcolor3485{color:rgb(163,20,20)}
span#textcolor3486{color:rgb(163,20,20)}
span#textcolor3487{color:rgb(163,20,20)}
span#textcolor3487{color:rgb(0,0,255)}
span#textcolor3488{color:rgb(0,0,255)}
span#textcolor3489{color:rgb(163,20,20)}
span#textcolor3490{color:rgb(163,20,20)}
span#textcolor3491{color:rgb(163,20,20)}
span#textcolor3492{color:rgb(0,0,255)}
span#textcolor3493{color:rgb(0,127,0)}
span#textcolor3494{color:rgb(0,0,255)}
span#textcolor3495{color:rgb(163,20,20)}
span#textcolor3491{color:rgb(0,0,255)}
span#textcolor3492{color:rgb(163,20,20)}
span#textcolor3493{color:rgb(163,20,20)}
span#textcolor3494{color:rgb(163,20,20)}
span#textcolor3495{color:rgb(0,0,255)}
span#textcolor3496{color:rgb(0,127,0)}
span#textcolor3497{color:rgb(0,0,255)}
span#textcolor3498{color:rgb(163,20,20)}
pre#fancyvrb99{padding:5.69054pt;}
pre#fancyvrb99{ border-top: solid 0.4pt; }
pre#fancyvrb99{ border-left: solid 0.4pt; }

View File

@ -6352,145 +6352,149 @@ static key works.
<a id='x1-65151r61'></a><span class='ecrm-0500'>61</span>
<a id='x1-65153r62'></a><span class='ecrm-0500'>62</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3383'><span class='ectt-0800'>"I was assigned major number %d</span></span><span id='textcolor3384'><span class='ectt-0800'>\n</span></span><span id='textcolor3385'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, major);</span>
<a id='x1-65155r63'></a><span class='ecrm-0500'>63</span>
<a id='x1-65157r64'></a><span class='ecrm-0500'>64</span><span class='ectt-0800'>    cls = class_create(THIS_MODULE, DEVICE_NAME);</span>
<a id='x1-65159r65'></a><span class='ecrm-0500'>65</span>
<a id='x1-65161r66'></a><span class='ecrm-0500'>66</span><span class='ectt-0800'>    device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);</span>
<a id='x1-65163r67'></a><span class='ecrm-0500'>67</span>
<a id='x1-65165r68'></a><span class='ecrm-0500'>68</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3386'><span class='ectt-0800'>"Device created on /dev/%s</span></span><span id='textcolor3387'><span class='ectt-0800'>\n</span></span><span id='textcolor3388'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, DEVICE_NAME);</span>
<a id='x1-65157r64'></a><span class='ecrm-0500'>64</span><span id='textcolor3386'><span class='ectt-0800'>#if LINUX_VERSION_CODE &lt; KERNEL_VERSION(6, 4, 0)</span></span>
<a id='x1-65159r65'></a><span class='ecrm-0500'>65</span><span class='ectt-0800'>    cls = class_create(THIS_MODULE, DEVICE_NAME);</span>
<a id='x1-65161r66'></a><span class='ecrm-0500'>66</span><span id='textcolor3387'><span class='ectt-0800'>#else</span></span>
<a id='x1-65163r67'></a><span class='ecrm-0500'>67</span><span class='ectt-0800'>    cls = class_create(DEVICE_NAME);</span>
<a id='x1-65165r68'></a><span class='ecrm-0500'>68</span><span id='textcolor3388'><span class='ectt-0800'>#endif</span></span>
<a id='x1-65167r69'></a><span class='ecrm-0500'>69</span>
<a id='x1-65169r70'></a><span class='ecrm-0500'>70</span><span class='ectt-0800'>    </span><span id='textcolor3389'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65171r71'></a><span class='ecrm-0500'>71</span><span class='ectt-0800'>}</span>
<a id='x1-65173r72'></a><span class='ecrm-0500'>72</span>
<a id='x1-65175r73'></a><span class='ecrm-0500'>73</span><span id='textcolor3390'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3391'><span class='ectt-0800'>void</span></span><span class='ectt-0800'> __exit chardev_exit(</span><span id='textcolor3392'><span class='ectt-0800'>void</span></span><span class='ectt-0800'>)</span>
<a id='x1-65177r74'></a><span class='ecrm-0500'>74</span><span class='ectt-0800'>{</span>
<a id='x1-65179r75'></a><span class='ecrm-0500'>75</span><span class='ectt-0800'>    device_destroy(cls, MKDEV(major, 0));</span>
<a id='x1-65181r76'></a><span class='ecrm-0500'>76</span><span class='ectt-0800'>    class_destroy(cls);</span>
<a id='x1-65183r77'></a><span class='ecrm-0500'>77</span>
<a id='x1-65185r78'></a><span class='ecrm-0500'>78</span><span class='ectt-0800'>    </span><span id='textcolor3393'><span class='ectt-0800'>/* Unregister the device */</span></span>
<a id='x1-65187r79'></a><span class='ecrm-0500'>79</span><span class='ectt-0800'>    unregister_chrdev(major, DEVICE_NAME);</span>
<a id='x1-65189r80'></a><span class='ecrm-0500'>80</span><span class='ectt-0800'>}</span>
<a id='x1-65169r70'></a><span class='ecrm-0500'>70</span><span class='ectt-0800'>    device_create(cls, NULL, MKDEV(major, 0), NULL, DEVICE_NAME);</span>
<a id='x1-65171r71'></a><span class='ecrm-0500'>71</span>
<a id='x1-65173r72'></a><span class='ecrm-0500'>72</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3389'><span class='ectt-0800'>"Device created on /dev/%s</span></span><span id='textcolor3390'><span class='ectt-0800'>\n</span></span><span id='textcolor3391'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, DEVICE_NAME);</span>
<a id='x1-65175r73'></a><span class='ecrm-0500'>73</span>
<a id='x1-65177r74'></a><span class='ecrm-0500'>74</span><span class='ectt-0800'>    </span><span id='textcolor3392'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65179r75'></a><span class='ecrm-0500'>75</span><span class='ectt-0800'>}</span>
<a id='x1-65181r76'></a><span class='ecrm-0500'>76</span>
<a id='x1-65183r77'></a><span class='ecrm-0500'>77</span><span id='textcolor3393'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3394'><span class='ectt-0800'>void</span></span><span class='ectt-0800'> __exit chardev_exit(</span><span id='textcolor3395'><span class='ectt-0800'>void</span></span><span class='ectt-0800'>)</span>
<a id='x1-65185r78'></a><span class='ecrm-0500'>78</span><span class='ectt-0800'>{</span>
<a id='x1-65187r79'></a><span class='ecrm-0500'>79</span><span class='ectt-0800'>    device_destroy(cls, MKDEV(major, 0));</span>
<a id='x1-65189r80'></a><span class='ecrm-0500'>80</span><span class='ectt-0800'>    class_destroy(cls);</span>
<a id='x1-65191r81'></a><span class='ecrm-0500'>81</span>
<a id='x1-65193r82'></a><span class='ecrm-0500'>82</span><span id='textcolor3394'><span class='ectt-0800'>/* Methods */</span></span>
<a id='x1-65195r83'></a><span class='ecrm-0500'>83</span>
<a id='x1-65197r84'></a><span class='ecrm-0500'>84</span><span id='textcolor3395'><span class='ectt-0800'>/**</span></span>
<a id='x1-65199r85'></a><span class='ecrm-0500'>85</span><span id='textcolor3396'><span class='ectt-0800'> * Called when a process tried to open the device file, like</span></span>
<a id='x1-65201r86'></a><span class='ecrm-0500'>86</span><span id='textcolor3397'><span class='ectt-0800'> * cat /dev/key_state</span></span>
<a id='x1-65203r87'></a><span class='ecrm-0500'>87</span><span id='textcolor3398'><span class='ectt-0800'> */</span></span>
<a id='x1-65205r88'></a><span class='ecrm-0500'>88</span><span id='textcolor3399'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3400'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> device_open(</span><span id='textcolor3401'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> inode *inode, </span><span id='textcolor3402'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *file)</span>
<a id='x1-65207r89'></a><span class='ecrm-0500'>89</span><span class='ectt-0800'>{</span>
<a id='x1-65209r90'></a><span class='ecrm-0500'>90</span><span class='ectt-0800'>    </span><span id='textcolor3403'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (atomic_cmpxchg(&amp;already_open, CDEV_NOT_USED, CDEV_EXCLUSIVE_OPEN))</span>
<a id='x1-65211r91'></a><span class='ecrm-0500'>91</span><span class='ectt-0800'>        </span><span id='textcolor3404'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EBUSY;</span>
<a id='x1-65213r92'></a><span class='ecrm-0500'>92</span>
<a id='x1-65215r93'></a><span class='ecrm-0500'>93</span><span class='ectt-0800'>    sprintf(msg, static_key_enabled(&amp;fkey) ? </span><span id='textcolor3405'><span class='ectt-0800'>"enabled</span></span><span id='textcolor3406'><span class='ectt-0800'>\n</span></span><span id='textcolor3407'><span class='ectt-0800'>"</span></span><span class='ectt-0800'> : </span><span id='textcolor3408'><span class='ectt-0800'>"disabled</span></span><span id='textcolor3409'><span class='ectt-0800'>\n</span></span><span id='textcolor3410'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65217r94'></a><span class='ecrm-0500'>94</span>
<a id='x1-65219r95'></a><span class='ecrm-0500'>95</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3411'><span class='ectt-0800'>"fastpath 1</span></span><span id='textcolor3412'><span class='ectt-0800'>\n</span></span><span id='textcolor3413'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65221r96'></a><span class='ecrm-0500'>96</span><span class='ectt-0800'>    </span><span id='textcolor3414'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (static_branch_unlikely(&amp;fkey))</span>
<a id='x1-65223r97'></a><span class='ecrm-0500'>97</span><span class='ectt-0800'>        pr_alert(</span><span id='textcolor3415'><span class='ectt-0800'>"do unlikely thing</span></span><span id='textcolor3416'><span class='ectt-0800'>\n</span></span><span id='textcolor3417'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65225r98'></a><span class='ecrm-0500'>98</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3418'><span class='ectt-0800'>"fastpath 2</span></span><span id='textcolor3419'><span class='ectt-0800'>\n</span></span><span id='textcolor3420'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65227r99'></a><span class='ecrm-0500'>99</span>
<a id='x1-65229r100'></a><span class='ecrm-0500'>100</span><span class='ectt-0800'>    try_module_get(THIS_MODULE);</span>
<a id='x1-65231r101'></a><span class='ecrm-0500'>101</span>
<a id='x1-65233r102'></a><span class='ecrm-0500'>102</span><span class='ectt-0800'>    </span><span id='textcolor3421'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65235r103'></a><span class='ecrm-0500'>103</span><span class='ectt-0800'>}</span>
<a id='x1-65237r104'></a><span class='ecrm-0500'>104</span>
<a id='x1-65239r105'></a><span class='ecrm-0500'>105</span><span id='textcolor3422'><span class='ectt-0800'>/**</span></span>
<a id='x1-65241r106'></a><span class='ecrm-0500'>106</span><span id='textcolor3423'><span class='ectt-0800'> * Called when a process closes the device file</span></span>
<a id='x1-65243r107'></a><span class='ecrm-0500'>107</span><span id='textcolor3424'><span class='ectt-0800'> */</span></span>
<a id='x1-65245r108'></a><span class='ecrm-0500'>108</span><span id='textcolor3425'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3426'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> device_release(</span><span id='textcolor3427'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> inode *inode, </span><span id='textcolor3428'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *file)</span>
<a id='x1-65247r109'></a><span class='ecrm-0500'>109</span><span class='ectt-0800'>{</span>
<a id='x1-65249r110'></a><span class='ecrm-0500'>110</span><span class='ectt-0800'>    </span><span id='textcolor3429'><span class='ectt-0800'>/* We are now ready for our next caller. */</span></span>
<a id='x1-65251r111'></a><span class='ecrm-0500'>111</span><span class='ectt-0800'>    atomic_set(&amp;already_open, CDEV_NOT_USED);</span>
<a id='x1-65253r112'></a><span class='ecrm-0500'>112</span>
<a id='x1-65255r113'></a><span class='ecrm-0500'>113</span><span class='ectt-0800'>    </span><span id='textcolor3430'><span class='ectt-0800'>/**</span></span>
<a id='x1-65257r114'></a><span class='ecrm-0500'>114</span><span id='textcolor3431'><span class='ectt-0800'>     * Decrement the usage count, or else once you opened the file, you will</span></span>
<a id='x1-65259r115'></a><span class='ecrm-0500'>115</span><span id='textcolor3432'><span class='ectt-0800'>     * never get rid of the module.</span></span>
<a id='x1-65261r116'></a><span class='ecrm-0500'>116</span><span id='textcolor3433'><span class='ectt-0800'>     */</span></span>
<a id='x1-65263r117'></a><span class='ecrm-0500'>117</span><span class='ectt-0800'>    module_put(THIS_MODULE);</span>
<a id='x1-65265r118'></a><span class='ecrm-0500'>118</span>
<a id='x1-65267r119'></a><span class='ecrm-0500'>119</span><span class='ectt-0800'>    </span><span id='textcolor3434'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65269r120'></a><span class='ecrm-0500'>120</span><span class='ectt-0800'>}</span>
<a id='x1-65271r121'></a><span class='ecrm-0500'>121</span>
<a id='x1-65273r122'></a><span class='ecrm-0500'>122</span><span id='textcolor3435'><span class='ectt-0800'>/**</span></span>
<a id='x1-65275r123'></a><span class='ecrm-0500'>123</span><span id='textcolor3436'><span class='ectt-0800'> * Called when a process, which already opened the dev file, attempts to</span></span>
<a id='x1-65277r124'></a><span class='ecrm-0500'>124</span><span id='textcolor3437'><span class='ectt-0800'> * read from it.</span></span>
<a id='x1-65279r125'></a><span class='ecrm-0500'>125</span><span id='textcolor3438'><span class='ectt-0800'> */</span></span>
<a id='x1-65281r126'></a><span class='ecrm-0500'>126</span><span id='textcolor3439'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3440'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> device_read(</span><span id='textcolor3441'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *filp, </span><span id='textcolor3442'><span class='ectt-0800'>/* see include/linux/fs.h */</span></span>
<a id='x1-65283r127'></a><span class='ecrm-0500'>127</span><span class='ectt-0800'>                           </span><span id='textcolor3443'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> __user *buffer, </span><span id='textcolor3444'><span class='ectt-0800'>/* buffer to fill with data */</span></span>
<a id='x1-65285r128'></a><span class='ecrm-0500'>128</span><span class='ectt-0800'>                           </span><span id='textcolor3445'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> length, </span><span id='textcolor3446'><span class='ectt-0800'>/* length of the buffer */</span></span>
<a id='x1-65287r129'></a><span class='ecrm-0500'>129</span><span class='ectt-0800'>                           loff_t *offset)</span>
<a id='x1-65289r130'></a><span class='ecrm-0500'>130</span><span class='ectt-0800'>{</span>
<a id='x1-65291r131'></a><span class='ecrm-0500'>131</span><span class='ectt-0800'>    </span><span id='textcolor3447'><span class='ectt-0800'>/* Number of the bytes actually written to the buffer */</span></span>
<a id='x1-65293r132'></a><span class='ecrm-0500'>132</span><span class='ectt-0800'>    </span><span id='textcolor3448'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> bytes_read = 0;</span>
<a id='x1-65295r133'></a><span class='ecrm-0500'>133</span><span class='ectt-0800'>    </span><span id='textcolor3449'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor3450'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *msg_ptr = msg;</span>
<a id='x1-65297r134'></a><span class='ecrm-0500'>134</span>
<a id='x1-65299r135'></a><span class='ecrm-0500'>135</span><span class='ectt-0800'>    </span><span id='textcolor3451'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (!*(msg_ptr + *offset)) { </span><span id='textcolor3452'><span class='ectt-0800'>/* We are at the end of the message */</span></span>
<a id='x1-65301r136'></a><span class='ecrm-0500'>136</span><span class='ectt-0800'>        *offset = 0; </span><span id='textcolor3453'><span class='ectt-0800'>/* reset the offset */</span></span>
<a id='x1-65303r137'></a><span class='ecrm-0500'>137</span><span class='ectt-0800'>        </span><span id='textcolor3454'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> 0; </span><span id='textcolor3455'><span class='ectt-0800'>/* signify end of file */</span></span>
<a id='x1-65305r138'></a><span class='ecrm-0500'>138</span><span class='ectt-0800'>    }</span>
<a id='x1-65307r139'></a><span class='ecrm-0500'>139</span>
<a id='x1-65309r140'></a><span class='ecrm-0500'>140</span><span class='ectt-0800'>    msg_ptr += *offset;</span>
<a id='x1-65311r141'></a><span class='ecrm-0500'>141</span>
<a id='x1-65313r142'></a><span class='ecrm-0500'>142</span><span class='ectt-0800'>    </span><span id='textcolor3456'><span class='ectt-0800'>/* Actually put the data into the buffer */</span></span>
<a id='x1-65315r143'></a><span class='ecrm-0500'>143</span><span class='ectt-0800'>    </span><span id='textcolor3457'><span class='ectt-0800'>while</span></span><span class='ectt-0800'> (length &amp;&amp; *msg_ptr) {</span>
<a id='x1-65317r144'></a><span class='ecrm-0500'>144</span><span class='ectt-0800'>        </span><span id='textcolor3458'><span class='ectt-0800'>/**</span></span>
<a id='x1-65319r145'></a><span class='ecrm-0500'>145</span><span id='textcolor3459'><span class='ectt-0800'>         * The buffer is in the user data segment, not the kernel</span></span>
<a id='x1-65321r146'></a><span class='ecrm-0500'>146</span><span id='textcolor3460'><span class='ectt-0800'>         * segment so "*" assignment won</span><span class='tctt-0800'>'</span><span class='ectt-0800'>t work. We have to use</span></span>
<a id='x1-65323r147'></a><span class='ecrm-0500'>147</span><span id='textcolor3461'><span class='ectt-0800'>         * put_user which copies data from the kernel data segment to</span></span>
<a id='x1-65325r148'></a><span class='ecrm-0500'>148</span><span id='textcolor3462'><span class='ectt-0800'>         * the user data segment.</span></span>
<a id='x1-65327r149'></a><span class='ecrm-0500'>149</span><span id='textcolor3463'><span class='ectt-0800'>         */</span></span>
<a id='x1-65329r150'></a><span class='ecrm-0500'>150</span><span class='ectt-0800'>        put_user(*(msg_ptr++), buffer++);</span>
<a id='x1-65331r151'></a><span class='ecrm-0500'>151</span><span class='ectt-0800'>        length--;</span>
<a id='x1-65333r152'></a><span class='ecrm-0500'>152</span><span class='ectt-0800'>        bytes_read++;</span>
<a id='x1-65335r153'></a><span class='ecrm-0500'>153</span><span class='ectt-0800'>    }</span>
<a id='x1-65337r154'></a><span class='ecrm-0500'>154</span>
<a id='x1-65339r155'></a><span class='ecrm-0500'>155</span><span class='ectt-0800'>    *offset += bytes_read;</span>
<a id='x1-65341r156'></a><span class='ecrm-0500'>156</span>
<a id='x1-65343r157'></a><span class='ecrm-0500'>157</span><span class='ectt-0800'>    </span><span id='textcolor3464'><span class='ectt-0800'>/* Most read functions return the number of bytes put into the buffer. */</span></span>
<a id='x1-65345r158'></a><span class='ecrm-0500'>158</span><span class='ectt-0800'>    </span><span id='textcolor3465'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> bytes_read;</span>
<a id='x1-65347r159'></a><span class='ecrm-0500'>159</span><span class='ectt-0800'>}</span>
<a id='x1-65193r82'></a><span class='ecrm-0500'>82</span><span class='ectt-0800'>    </span><span id='textcolor3396'><span class='ectt-0800'>/* Unregister the device */</span></span>
<a id='x1-65195r83'></a><span class='ecrm-0500'>83</span><span class='ectt-0800'>    unregister_chrdev(major, DEVICE_NAME);</span>
<a id='x1-65197r84'></a><span class='ecrm-0500'>84</span><span class='ectt-0800'>}</span>
<a id='x1-65199r85'></a><span class='ecrm-0500'>85</span>
<a id='x1-65201r86'></a><span class='ecrm-0500'>86</span><span id='textcolor3397'><span class='ectt-0800'>/* Methods */</span></span>
<a id='x1-65203r87'></a><span class='ecrm-0500'>87</span>
<a id='x1-65205r88'></a><span class='ecrm-0500'>88</span><span id='textcolor3398'><span class='ectt-0800'>/**</span></span>
<a id='x1-65207r89'></a><span class='ecrm-0500'>89</span><span id='textcolor3399'><span class='ectt-0800'> * Called when a process tried to open the device file, like</span></span>
<a id='x1-65209r90'></a><span class='ecrm-0500'>90</span><span id='textcolor3400'><span class='ectt-0800'> * cat /dev/key_state</span></span>
<a id='x1-65211r91'></a><span class='ecrm-0500'>91</span><span id='textcolor3401'><span class='ectt-0800'> */</span></span>
<a id='x1-65213r92'></a><span class='ecrm-0500'>92</span><span id='textcolor3402'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3403'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> device_open(</span><span id='textcolor3404'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> inode *inode, </span><span id='textcolor3405'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *file)</span>
<a id='x1-65215r93'></a><span class='ecrm-0500'>93</span><span class='ectt-0800'>{</span>
<a id='x1-65217r94'></a><span class='ecrm-0500'>94</span><span class='ectt-0800'>    </span><span id='textcolor3406'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (atomic_cmpxchg(&amp;already_open, CDEV_NOT_USED, CDEV_EXCLUSIVE_OPEN))</span>
<a id='x1-65219r95'></a><span class='ecrm-0500'>95</span><span class='ectt-0800'>        </span><span id='textcolor3407'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EBUSY;</span>
<a id='x1-65221r96'></a><span class='ecrm-0500'>96</span>
<a id='x1-65223r97'></a><span class='ecrm-0500'>97</span><span class='ectt-0800'>    sprintf(msg, static_key_enabled(&amp;fkey) ? </span><span id='textcolor3408'><span class='ectt-0800'>"enabled</span></span><span id='textcolor3409'><span class='ectt-0800'>\n</span></span><span id='textcolor3410'><span class='ectt-0800'>"</span></span><span class='ectt-0800'> : </span><span id='textcolor3411'><span class='ectt-0800'>"disabled</span></span><span id='textcolor3412'><span class='ectt-0800'>\n</span></span><span id='textcolor3413'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65225r98'></a><span class='ecrm-0500'>98</span>
<a id='x1-65227r99'></a><span class='ecrm-0500'>99</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3414'><span class='ectt-0800'>"fastpath 1</span></span><span id='textcolor3415'><span class='ectt-0800'>\n</span></span><span id='textcolor3416'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65229r100'></a><span class='ecrm-0500'>100</span><span class='ectt-0800'>    </span><span id='textcolor3417'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (static_branch_unlikely(&amp;fkey))</span>
<a id='x1-65231r101'></a><span class='ecrm-0500'>101</span><span class='ectt-0800'>        pr_alert(</span><span id='textcolor3418'><span class='ectt-0800'>"do unlikely thing</span></span><span id='textcolor3419'><span class='ectt-0800'>\n</span></span><span id='textcolor3420'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65233r102'></a><span class='ecrm-0500'>102</span><span class='ectt-0800'>    pr_info(</span><span id='textcolor3421'><span class='ectt-0800'>"fastpath 2</span></span><span id='textcolor3422'><span class='ectt-0800'>\n</span></span><span id='textcolor3423'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65235r103'></a><span class='ecrm-0500'>103</span>
<a id='x1-65237r104'></a><span class='ecrm-0500'>104</span><span class='ectt-0800'>    try_module_get(THIS_MODULE);</span>
<a id='x1-65239r105'></a><span class='ecrm-0500'>105</span>
<a id='x1-65241r106'></a><span class='ecrm-0500'>106</span><span class='ectt-0800'>    </span><span id='textcolor3424'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65243r107'></a><span class='ecrm-0500'>107</span><span class='ectt-0800'>}</span>
<a id='x1-65245r108'></a><span class='ecrm-0500'>108</span>
<a id='x1-65247r109'></a><span class='ecrm-0500'>109</span><span id='textcolor3425'><span class='ectt-0800'>/**</span></span>
<a id='x1-65249r110'></a><span class='ecrm-0500'>110</span><span id='textcolor3426'><span class='ectt-0800'> * Called when a process closes the device file</span></span>
<a id='x1-65251r111'></a><span class='ecrm-0500'>111</span><span id='textcolor3427'><span class='ectt-0800'> */</span></span>
<a id='x1-65253r112'></a><span class='ecrm-0500'>112</span><span id='textcolor3428'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3429'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> device_release(</span><span id='textcolor3430'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> inode *inode, </span><span id='textcolor3431'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *file)</span>
<a id='x1-65255r113'></a><span class='ecrm-0500'>113</span><span class='ectt-0800'>{</span>
<a id='x1-65257r114'></a><span class='ecrm-0500'>114</span><span class='ectt-0800'>    </span><span id='textcolor3432'><span class='ectt-0800'>/* We are now ready for our next caller. */</span></span>
<a id='x1-65259r115'></a><span class='ecrm-0500'>115</span><span class='ectt-0800'>    atomic_set(&amp;already_open, CDEV_NOT_USED);</span>
<a id='x1-65261r116'></a><span class='ecrm-0500'>116</span>
<a id='x1-65263r117'></a><span class='ecrm-0500'>117</span><span class='ectt-0800'>    </span><span id='textcolor3433'><span class='ectt-0800'>/**</span></span>
<a id='x1-65265r118'></a><span class='ecrm-0500'>118</span><span id='textcolor3434'><span class='ectt-0800'>     * Decrement the usage count, or else once you opened the file, you will</span></span>
<a id='x1-65267r119'></a><span class='ecrm-0500'>119</span><span id='textcolor3435'><span class='ectt-0800'>     * never get rid of the module.</span></span>
<a id='x1-65269r120'></a><span class='ecrm-0500'>120</span><span id='textcolor3436'><span class='ectt-0800'>     */</span></span>
<a id='x1-65271r121'></a><span class='ecrm-0500'>121</span><span class='ectt-0800'>    module_put(THIS_MODULE);</span>
<a id='x1-65273r122'></a><span class='ecrm-0500'>122</span>
<a id='x1-65275r123'></a><span class='ecrm-0500'>123</span><span class='ectt-0800'>    </span><span id='textcolor3437'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> SUCCESS;</span>
<a id='x1-65277r124'></a><span class='ecrm-0500'>124</span><span class='ectt-0800'>}</span>
<a id='x1-65279r125'></a><span class='ecrm-0500'>125</span>
<a id='x1-65281r126'></a><span class='ecrm-0500'>126</span><span id='textcolor3438'><span class='ectt-0800'>/**</span></span>
<a id='x1-65283r127'></a><span class='ecrm-0500'>127</span><span id='textcolor3439'><span class='ectt-0800'> * Called when a process, which already opened the dev file, attempts to</span></span>
<a id='x1-65285r128'></a><span class='ecrm-0500'>128</span><span id='textcolor3440'><span class='ectt-0800'> * read from it.</span></span>
<a id='x1-65287r129'></a><span class='ecrm-0500'>129</span><span id='textcolor3441'><span class='ectt-0800'> */</span></span>
<a id='x1-65289r130'></a><span class='ecrm-0500'>130</span><span id='textcolor3442'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3443'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> device_read(</span><span id='textcolor3444'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *filp, </span><span id='textcolor3445'><span class='ectt-0800'>/* see include/linux/fs.h */</span></span>
<a id='x1-65291r131'></a><span class='ecrm-0500'>131</span><span class='ectt-0800'>                           </span><span id='textcolor3446'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> __user *buffer, </span><span id='textcolor3447'><span class='ectt-0800'>/* buffer to fill with data */</span></span>
<a id='x1-65293r132'></a><span class='ecrm-0500'>132</span><span class='ectt-0800'>                           </span><span id='textcolor3448'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> length, </span><span id='textcolor3449'><span class='ectt-0800'>/* length of the buffer */</span></span>
<a id='x1-65295r133'></a><span class='ecrm-0500'>133</span><span class='ectt-0800'>                           loff_t *offset)</span>
<a id='x1-65297r134'></a><span class='ecrm-0500'>134</span><span class='ectt-0800'>{</span>
<a id='x1-65299r135'></a><span class='ecrm-0500'>135</span><span class='ectt-0800'>    </span><span id='textcolor3450'><span class='ectt-0800'>/* Number of the bytes actually written to the buffer */</span></span>
<a id='x1-65301r136'></a><span class='ecrm-0500'>136</span><span class='ectt-0800'>    </span><span id='textcolor3451'><span class='ectt-0800'>int</span></span><span class='ectt-0800'> bytes_read = 0;</span>
<a id='x1-65303r137'></a><span class='ecrm-0500'>137</span><span class='ectt-0800'>    </span><span id='textcolor3452'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor3453'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> *msg_ptr = msg;</span>
<a id='x1-65305r138'></a><span class='ecrm-0500'>138</span>
<a id='x1-65307r139'></a><span class='ecrm-0500'>139</span><span class='ectt-0800'>    </span><span id='textcolor3454'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (!*(msg_ptr + *offset)) { </span><span id='textcolor3455'><span class='ectt-0800'>/* We are at the end of the message */</span></span>
<a id='x1-65309r140'></a><span class='ecrm-0500'>140</span><span class='ectt-0800'>        *offset = 0; </span><span id='textcolor3456'><span class='ectt-0800'>/* reset the offset */</span></span>
<a id='x1-65311r141'></a><span class='ecrm-0500'>141</span><span class='ectt-0800'>        </span><span id='textcolor3457'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> 0; </span><span id='textcolor3458'><span class='ectt-0800'>/* signify end of file */</span></span>
<a id='x1-65313r142'></a><span class='ecrm-0500'>142</span><span class='ectt-0800'>    }</span>
<a id='x1-65315r143'></a><span class='ecrm-0500'>143</span>
<a id='x1-65317r144'></a><span class='ecrm-0500'>144</span><span class='ectt-0800'>    msg_ptr += *offset;</span>
<a id='x1-65319r145'></a><span class='ecrm-0500'>145</span>
<a id='x1-65321r146'></a><span class='ecrm-0500'>146</span><span class='ectt-0800'>    </span><span id='textcolor3459'><span class='ectt-0800'>/* Actually put the data into the buffer */</span></span>
<a id='x1-65323r147'></a><span class='ecrm-0500'>147</span><span class='ectt-0800'>    </span><span id='textcolor3460'><span class='ectt-0800'>while</span></span><span class='ectt-0800'> (length &amp;&amp; *msg_ptr) {</span>
<a id='x1-65325r148'></a><span class='ecrm-0500'>148</span><span class='ectt-0800'>        </span><span id='textcolor3461'><span class='ectt-0800'>/**</span></span>
<a id='x1-65327r149'></a><span class='ecrm-0500'>149</span><span id='textcolor3462'><span class='ectt-0800'>         * The buffer is in the user data segment, not the kernel</span></span>
<a id='x1-65329r150'></a><span class='ecrm-0500'>150</span><span id='textcolor3463'><span class='ectt-0800'>         * segment so "*" assignment won</span><span class='tctt-0800'>'</span><span class='ectt-0800'>t work. We have to use</span></span>
<a id='x1-65331r151'></a><span class='ecrm-0500'>151</span><span id='textcolor3464'><span class='ectt-0800'>         * put_user which copies data from the kernel data segment to</span></span>
<a id='x1-65333r152'></a><span class='ecrm-0500'>152</span><span id='textcolor3465'><span class='ectt-0800'>         * the user data segment.</span></span>
<a id='x1-65335r153'></a><span class='ecrm-0500'>153</span><span id='textcolor3466'><span class='ectt-0800'>         */</span></span>
<a id='x1-65337r154'></a><span class='ecrm-0500'>154</span><span class='ectt-0800'>        put_user(*(msg_ptr++), buffer++);</span>
<a id='x1-65339r155'></a><span class='ecrm-0500'>155</span><span class='ectt-0800'>        length--;</span>
<a id='x1-65341r156'></a><span class='ecrm-0500'>156</span><span class='ectt-0800'>        bytes_read++;</span>
<a id='x1-65343r157'></a><span class='ecrm-0500'>157</span><span class='ectt-0800'>    }</span>
<a id='x1-65345r158'></a><span class='ecrm-0500'>158</span>
<a id='x1-65347r159'></a><span class='ecrm-0500'>159</span><span class='ectt-0800'>    *offset += bytes_read;</span>
<a id='x1-65349r160'></a><span class='ecrm-0500'>160</span>
<a id='x1-65351r161'></a><span class='ecrm-0500'>161</span><span id='textcolor3466'><span class='ectt-0800'>/* Called when a process writes to dev file; echo "enable" &gt; /dev/key_state */</span></span>
<a id='x1-65353r162'></a><span class='ecrm-0500'>162</span><span id='textcolor3467'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3468'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> device_write(</span><span id='textcolor3469'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *filp, </span><span id='textcolor3470'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor3471'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> __user *buffer,</span>
<a id='x1-65355r163'></a><span class='ecrm-0500'>163</span><span class='ectt-0800'>                            </span><span id='textcolor3472'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> length, loff_t *offset)</span>
<a id='x1-65357r164'></a><span class='ecrm-0500'>164</span><span class='ectt-0800'>{</span>
<a id='x1-65359r165'></a><span class='ecrm-0500'>165</span><span class='ectt-0800'>    </span><span id='textcolor3473'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> command[10];</span>
<a id='x1-65361r166'></a><span class='ecrm-0500'>166</span>
<a id='x1-65363r167'></a><span class='ecrm-0500'>167</span><span class='ectt-0800'>    </span><span id='textcolor3474'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (length &gt; 10) {</span>
<a id='x1-65365r168'></a><span class='ecrm-0500'>168</span><span class='ectt-0800'>        pr_err(</span><span id='textcolor3475'><span class='ectt-0800'>"command exceeded 10 char</span></span><span id='textcolor3476'><span class='ectt-0800'>\n</span></span><span id='textcolor3477'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65367r169'></a><span class='ecrm-0500'>169</span><span class='ectt-0800'>        </span><span id='textcolor3478'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EINVAL;</span>
<a id='x1-65369r170'></a><span class='ecrm-0500'>170</span><span class='ectt-0800'>    }</span>
<a id='x1-65371r171'></a><span class='ecrm-0500'>171</span>
<a id='x1-65373r172'></a><span class='ecrm-0500'>172</span><span class='ectt-0800'>    </span><span id='textcolor3479'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (copy_from_user(command, buffer, length))</span>
<a id='x1-65375r173'></a><span class='ecrm-0500'>173</span><span class='ectt-0800'>        </span><span id='textcolor3480'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EFAULT;</span>
<a id='x1-65377r174'></a><span class='ecrm-0500'>174</span>
<a id='x1-65379r175'></a><span class='ecrm-0500'>175</span><span class='ectt-0800'>    </span><span id='textcolor3481'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (strncmp(command, </span><span id='textcolor3482'><span class='ectt-0800'>"enable"</span></span><span class='ectt-0800'>, strlen(</span><span id='textcolor3483'><span class='ectt-0800'>"enable"</span></span><span class='ectt-0800'>)) == 0)</span>
<a id='x1-65381r176'></a><span class='ecrm-0500'>176</span><span class='ectt-0800'>        static_branch_enable(&amp;fkey);</span>
<a id='x1-65383r177'></a><span class='ecrm-0500'>177</span><span class='ectt-0800'>    </span><span id='textcolor3484'><span class='ectt-0800'>else</span></span><span class='ectt-0800'> </span><span id='textcolor3485'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (strncmp(command, </span><span id='textcolor3486'><span class='ectt-0800'>"disable"</span></span><span class='ectt-0800'>, strlen(</span><span id='textcolor3487'><span class='ectt-0800'>"disable"</span></span><span class='ectt-0800'>)) == 0)</span>
<a id='x1-65385r178'></a><span class='ecrm-0500'>178</span><span class='ectt-0800'>        static_branch_disable(&amp;fkey);</span>
<a id='x1-65387r179'></a><span class='ecrm-0500'>179</span><span class='ectt-0800'>    </span><span id='textcolor3488'><span class='ectt-0800'>else</span></span><span class='ectt-0800'> {</span>
<a id='x1-65389r180'></a><span class='ecrm-0500'>180</span><span class='ectt-0800'>        pr_err(</span><span id='textcolor3489'><span class='ectt-0800'>"Invalid command: %s</span></span><span id='textcolor3490'><span class='ectt-0800'>\n</span></span><span id='textcolor3491'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, command);</span>
<a id='x1-65391r181'></a><span class='ecrm-0500'>181</span><span class='ectt-0800'>        </span><span id='textcolor3492'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EINVAL;</span>
<a id='x1-65393r182'></a><span class='ecrm-0500'>182</span><span class='ectt-0800'>    }</span>
<a id='x1-65395r183'></a><span class='ecrm-0500'>183</span>
<a id='x1-65397r184'></a><span class='ecrm-0500'>184</span><span class='ectt-0800'>    </span><span id='textcolor3493'><span class='ectt-0800'>/* Again, return the number of input characters used. */</span></span>
<a id='x1-65399r185'></a><span class='ecrm-0500'>185</span><span class='ectt-0800'>    </span><span id='textcolor3494'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> length;</span>
<a id='x1-65401r186'></a><span class='ecrm-0500'>186</span><span class='ectt-0800'>}</span>
<a id='x1-65351r161'></a><span class='ecrm-0500'>161</span><span class='ectt-0800'>    </span><span id='textcolor3467'><span class='ectt-0800'>/* Most read functions return the number of bytes put into the buffer. */</span></span>
<a id='x1-65353r162'></a><span class='ecrm-0500'>162</span><span class='ectt-0800'>    </span><span id='textcolor3468'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> bytes_read;</span>
<a id='x1-65355r163'></a><span class='ecrm-0500'>163</span><span class='ectt-0800'>}</span>
<a id='x1-65357r164'></a><span class='ecrm-0500'>164</span>
<a id='x1-65359r165'></a><span class='ecrm-0500'>165</span><span id='textcolor3469'><span class='ectt-0800'>/* Called when a process writes to dev file; echo "enable" &gt; /dev/key_state */</span></span>
<a id='x1-65361r166'></a><span class='ecrm-0500'>166</span><span id='textcolor3470'><span class='ectt-0800'>static</span></span><span class='ectt-0800'> </span><span id='textcolor3471'><span class='ectt-0800'>ssize_t</span></span><span class='ectt-0800'> device_write(</span><span id='textcolor3472'><span class='ectt-0800'>struct</span></span><span class='ectt-0800'> file *filp, </span><span id='textcolor3473'><span class='ectt-0800'>const</span></span><span class='ectt-0800'> </span><span id='textcolor3474'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> __user *buffer,</span>
<a id='x1-65363r167'></a><span class='ecrm-0500'>167</span><span class='ectt-0800'>                            </span><span id='textcolor3475'><span class='ectt-0800'>size_t</span></span><span class='ectt-0800'> length, loff_t *offset)</span>
<a id='x1-65365r168'></a><span class='ecrm-0500'>168</span><span class='ectt-0800'>{</span>
<a id='x1-65367r169'></a><span class='ecrm-0500'>169</span><span class='ectt-0800'>    </span><span id='textcolor3476'><span class='ectt-0800'>char</span></span><span class='ectt-0800'> command[10];</span>
<a id='x1-65369r170'></a><span class='ecrm-0500'>170</span>
<a id='x1-65371r171'></a><span class='ecrm-0500'>171</span><span class='ectt-0800'>    </span><span id='textcolor3477'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (length &gt; 10) {</span>
<a id='x1-65373r172'></a><span class='ecrm-0500'>172</span><span class='ectt-0800'>        pr_err(</span><span id='textcolor3478'><span class='ectt-0800'>"command exceeded 10 char</span></span><span id='textcolor3479'><span class='ectt-0800'>\n</span></span><span id='textcolor3480'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>);</span>
<a id='x1-65375r173'></a><span class='ecrm-0500'>173</span><span class='ectt-0800'>        </span><span id='textcolor3481'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EINVAL;</span>
<a id='x1-65377r174'></a><span class='ecrm-0500'>174</span><span class='ectt-0800'>    }</span>
<a id='x1-65379r175'></a><span class='ecrm-0500'>175</span>
<a id='x1-65381r176'></a><span class='ecrm-0500'>176</span><span class='ectt-0800'>    </span><span id='textcolor3482'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (copy_from_user(command, buffer, length))</span>
<a id='x1-65383r177'></a><span class='ecrm-0500'>177</span><span class='ectt-0800'>        </span><span id='textcolor3483'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EFAULT;</span>
<a id='x1-65385r178'></a><span class='ecrm-0500'>178</span>
<a id='x1-65387r179'></a><span class='ecrm-0500'>179</span><span class='ectt-0800'>    </span><span id='textcolor3484'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (strncmp(command, </span><span id='textcolor3485'><span class='ectt-0800'>"enable"</span></span><span class='ectt-0800'>, strlen(</span><span id='textcolor3486'><span class='ectt-0800'>"enable"</span></span><span class='ectt-0800'>)) == 0)</span>
<a id='x1-65389r180'></a><span class='ecrm-0500'>180</span><span class='ectt-0800'>        static_branch_enable(&amp;fkey);</span>
<a id='x1-65391r181'></a><span class='ecrm-0500'>181</span><span class='ectt-0800'>    </span><span id='textcolor3487'><span class='ectt-0800'>else</span></span><span class='ectt-0800'> </span><span id='textcolor3488'><span class='ectt-0800'>if</span></span><span class='ectt-0800'> (strncmp(command, </span><span id='textcolor3489'><span class='ectt-0800'>"disable"</span></span><span class='ectt-0800'>, strlen(</span><span id='textcolor3490'><span class='ectt-0800'>"disable"</span></span><span class='ectt-0800'>)) == 0)</span>
<a id='x1-65393r182'></a><span class='ecrm-0500'>182</span><span class='ectt-0800'>        static_branch_disable(&amp;fkey);</span>
<a id='x1-65395r183'></a><span class='ecrm-0500'>183</span><span class='ectt-0800'>    </span><span id='textcolor3491'><span class='ectt-0800'>else</span></span><span class='ectt-0800'> {</span>
<a id='x1-65397r184'></a><span class='ecrm-0500'>184</span><span class='ectt-0800'>        pr_err(</span><span id='textcolor3492'><span class='ectt-0800'>"Invalid command: %s</span></span><span id='textcolor3493'><span class='ectt-0800'>\n</span></span><span id='textcolor3494'><span class='ectt-0800'>"</span></span><span class='ectt-0800'>, command);</span>
<a id='x1-65399r185'></a><span class='ecrm-0500'>185</span><span class='ectt-0800'>        </span><span id='textcolor3495'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> -EINVAL;</span>
<a id='x1-65401r186'></a><span class='ecrm-0500'>186</span><span class='ectt-0800'>    }</span>
<a id='x1-65403r187'></a><span class='ecrm-0500'>187</span>
<a id='x1-65405r188'></a><span class='ecrm-0500'>188</span><span class='ectt-0800'>module_init(chardev_init);</span>
<a id='x1-65407r189'></a><span class='ecrm-0500'>189</span><span class='ectt-0800'>module_exit(chardev_exit);</span>
<a id='x1-65409r190'></a><span class='ecrm-0500'>190</span>
<a id='x1-65411r191'></a><span class='ecrm-0500'>191</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3495'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
<a id='x1-65405r188'></a><span class='ecrm-0500'>188</span><span class='ectt-0800'>    </span><span id='textcolor3496'><span class='ectt-0800'>/* Again, return the number of input characters used. */</span></span>
<a id='x1-65407r189'></a><span class='ecrm-0500'>189</span><span class='ectt-0800'>    </span><span id='textcolor3497'><span class='ectt-0800'>return</span></span><span class='ectt-0800'> length;</span>
<a id='x1-65409r190'></a><span class='ecrm-0500'>190</span><span class='ectt-0800'>}</span>
<a id='x1-65411r191'></a><span class='ecrm-0500'>191</span>
<a id='x1-65413r192'></a><span class='ecrm-0500'>192</span><span class='ectt-0800'>module_init(chardev_init);</span>
<a id='x1-65415r193'></a><span class='ecrm-0500'>193</span><span class='ectt-0800'>module_exit(chardev_exit);</span>
<a id='x1-65417r194'></a><span class='ecrm-0500'>194</span>
<a id='x1-65419r195'></a><span class='ecrm-0500'>195</span><span class='ectt-0800'>MODULE_LICENSE(</span><span id='textcolor3498'><span class='ectt-0800'>"GPL"</span></span><span class='ectt-0800'>);</span></pre>
<!-- l. 2076 --><p class='indent'> To check the state of the static key, we can use the <span class='obeylines-h'><span class='verb'><span class='ectt-1000'>/dev/key_state</span></span></span>
interface.
</p><!-- l. 1 --><p class='indent'>
</p>
<pre class='fancyvrb' id='fancyvrb99'><a id='x1-65414r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>cat /dev/key_state</span></pre>
<pre class='fancyvrb' id='fancyvrb99'><a id='x1-65422r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>cat /dev/key_state</span></pre>
<!-- l. 2082 --><p class='indent'> This will display the current state of the key, which is disabled by default.
</p><!-- l. 2084 --><p class='indent'> To change the state of the static key, we can perform a write operation on the
file:
</p><!-- l. 1 --><p class='indent'>
</p>
<pre class='fancyvrb' id='fancyvrb100'><a id='x1-65417r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo enable &gt; /dev/key_state</span></pre>
<pre class='fancyvrb' id='fancyvrb100'><a id='x1-65425r1'></a><span class='ecrm-0500'>1</span><span class='ectt-1000'>echo enable &gt; /dev/key_state</span></pre>
<!-- l. 2090 --><p class='indent'> This will enable the static key, causing the code path to switch from the fastpath
to the slowpath.
</p><!-- l. 2092 --><p class='indent'> In some cases, the key is enabled or disabled at initialization and never changed,