<divid="app"><divclass="Layout"data-v-5d98c3a5><!--[--><!--]--><!--[--><spantabindex="-1"data-v-0f60ec36></span><ahref="#VPContent"class="VPSkipLink visually-hidden"data-v-0f60ec36> Skip to content </a><!--]--><!----><headerclass="VPNav"data-v-5d98c3a5data-v-ae24b3ad><divclass="VPNavBar has-sidebar top"data-v-ae24b3addata-v-ccf7ddec><divclass="wrapper"data-v-ccf7ddec><divclass="container"data-v-ccf7ddec><divclass="title"data-v-ccf7ddec><divclass="VPNavBarTitle has-sidebar"data-v-ccf7ddecdata-v-ab179fa1><aclass="title"href="/"data-v-ab179fa1><!--[--><!--]--><!--[--><!--[--><!--[--><imgclass="VPImage dark logo"src="/badge-community-dark.svg"altdata-v-8426fc1a><!--]--><!--[--><imgclass="VPImage light logo"src="/badge-community-light.svg"altdata-v-8426fc1a><!--]--><!--]--><!--]--><!----><!--[--><!--]--></a></div></div><divclass="content"data-v-ccf7ddec><divclass="content-body"data-v-ccf7ddec><!--[--><!--]--><divclass="VPNavBarSearch search"data-v-ccf7ddec><!--[--><!----><divid="local-search"><buttontype="button"class="DocSearch DocSearch-Button"aria-label="Search"><spanclass="DocSearch-Button-Container"><spanclass="vp-icon DocSearch-Search-Icon"></span><spanclass="DocSearch-Button-Placeholder">Search</span></span><spanclass="DocSearch-Button-Keys"><kbdclass="DocSearch-Button-Key"></kbd><kbdclass="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><navaria-labelledby="main-nav-aria-label"class="VPNavBarMenu menu"data-v-ccf7ddecdata-v-7f418b0f><spanid="main-nav-aria-label"class="visually-hidden"data-v-7f418b0f>Main Navigation</span><!--[--><!--[--><aclass="VPLink link VPNavBarMenuLink"href="./"tabindex="0"data-v-7f418b0fdata-v-9c663999><!--[--><spandata-v-9c663999>Home</span><!--]--></a><!--]--><!--]--></nav><!----><divclass="VPNavBarAppearance appearance"data-v-ccf7ddecdata-v-e6aabb21><buttonclass="VPSwitch VPSwitchAppearance"type="button"role="switch"title="Switch to dark theme"aria-checked="false"data-v-e6aabb21data-v-d1f28634data-v-1d5665e3><spanclass="check"data-v-1d5665e3><spanclass="icon"data-v-1d5665e3><!--[--><spanclass="vpi-sun sun"data-v-d1f28634></span><spanclass="vpi-moon moon"data-v-d1f28634></span><!--]--></span></span></button></div><divclass="VPSocialLinks VPNavBarSocialLinks social-links"data-v-ccf7ddecdata-v-0394ad82data-v-7bc22406><!--[--><aclass="VPSocialLink no-icon"href="https://reddit.com/r/olkb"aria-labeltarget="_blank"rel="noopener"data-v-7bc22406data-v-eee4e7cb><svgxmlns="http://www.w3.org/2000/svg"viewBox="0 0 50 50"width="50px"height="50px"><pathd="M293C28.0625327.1640633.38281326.54C25.8359384.61718825.3632815.433594256.40625C24.3554698.14062524.08593810.39453124.0312513.03125C19.23437513.17968814.82031314.42187511.2812516.46875C10.21484415.468758.85546914.968757.514.96875C6.08984414.968754.67578115.5117193.5937516.59375C1.42578118.7617191.42578122.2382813.5937524.40625L3.8437524.65625C3.312526.035156327.488281329C333.5273445.56640637.5859389.562540.4375C13.55859443.28906319.007813452545C30.9921884536.44140643.28906340.437540.4375C44.43359437.5859384733.5273444729C4727.48828146.687526.03515646.1562524.65625L46.4062524.40625C48.57421922.23828148.57421918.76171946.4062516.59375C45.32421915.51171943.91015614.9687542.514.96875C41.14453114.9687539.78515615.4687538.7187516.46875C35.19531314.43359430.80078113.19140626.0312513.03125C26.0937510.54687526.3632818.4687526.8757.09375C27.1640636.31640627.5273445.75781327.8755.4375C28.2226565.11718828.5390635295C29.460938529.6835945.12530.031255.40625C30.3789065.687530.7851566.14843831.31256.6875C32.2539067.65234433.6953138.71484436.093758.9375C36.53906311.23828138.574219134113C43.75134610.75468C465.2543.753413C38.605469336.5742194.71093836.093756.96875C34.31256.79687533.5273446.10937532.755.3125C32.3007814.85156331.8867194.312531.31253.843
<spanclass="line"><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // Your code goes here</span></span>
<spanclass="line"><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // `data` is a pointer to the buffer containing the received HID report</span></span>
<spanclass="line"><spanstyle="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // `length` is the length of the report - always `RAW_EPSIZE`</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><divclass="warning custom-block"><pclass="custom-block-title">WARNING</p><p>Because the HID specification does not support variable length reports, all reports in both directions must be exactly <code>RAW_EPSIZE</code> (currently 32) bytes long, regardless of actual payload length. However, variable length payloads can potentially be implemented on top of this by creating your own data structure that may span multiple reports.</p></div><h2id="receiving-data-from-the-keyboard"tabindex="-1">Receiving Data from the Keyboard <aclass="header-anchor"href="#receiving-data-from-the-keyboard"aria-label="Permalink to "Receiving Data from the Keyboard {#receiving-data-from-the-keyboard}""></a></h2><p>If you need the keyboard to send data back to the host, simply call the <code>raw_hid_send()</code> function. It requires two arguments - a pointer to a 32-byte buffer containing the data you wish to send, and the length (which should always be <code>RAW_EPSIZE</code>).</p><p>The received report can then be handled in whichever way your HID library provides.</p><h2id="simple-example"tabindex="-1">Simple Example <aclass="header-anchor"href="#simple-example"aria-label="Permalink to "Simple Example {#simple-example}""></a></h2><p>The following example reads the first byte of the received report from the host, and if it is an ASCII "A", responds with "B". <code>memset()</code> is used to fill the response buffer (which could still contain the previous response) with null bytes.</p><divclass="language-c vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">c</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">void</span><spanstyle="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> raw_hid_receive</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint8_t</span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;"> *</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;">data</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">uint8_t</span><spanstyle="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> length</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>On the host side (here we are using Python and the <code>pyhidapi</code> library), the HID device is opened by enumerating the interfaces on the USB device, then filtering on the usage page and usage ID. Then, a report containing a single ASCII "A" (hex <code>0x41</code>) is constructed and sent.</p><p>For demonstration purposes, the manufacturer and product strings of the device, along with the request and response, are also printed.</p><divclass="language-python vp-adaptive-theme"><buttontitle="Copy Code"class="copy"></button><spanclass="lang">python</span><preclass="shiki shiki-themes github-light github-dark vp-code"><code><spanclass="line"><spanstyle="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> sys</span></span>
<spanclass="line"><spanstyle="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ])</span></span></code></pre></div><h2id="api"tabindex="-1">API <aclass="header-anchor"href="#api"aria-label="Permalink to "API {#api}""></a></h2><h3id="api-raw-hid-receive"tabindex="-1"><code>void raw_hid_receive(uint8_t *data, uint8_t length)</code><aclass="header-anchor"href="#api-raw-hid-receive"aria-label="Permalink to "`void raw_hid_receive(uint8_t *data, uint8_t length)` {#api-raw-hid-receive}""></a></h3><p>Callback, invoked when a raw HID report has been received from the host.</p><h4id="api-raw-hid-receive-arguments"tabindex="-1">Arguments <aclass="header-anchor"href="#api-raw-hid-receive-arguments"aria-label="Permalink to "Arguments {#api-raw-hid-receive-arguments}""></a></h4><ul><li><code>uint8_t *data</code><br> A pointer to the received data. Always 32 bytes in length.</li><li><code>uint8_t length</code><br> The length of the buffer. Always 32.</li></ul><hr><h3id="api-raw-hid-send"tabindex="-1"><code>void raw_hid_send(uint8_t *data, uint8_t length)</code><aclass="header-anchor"href="#api-raw-hid-send"aria-label="Permalink to "`void raw_hid_send(uint8_t *data, uint8_t length)` {#api-raw-hid-send}""></a></h3><p>Send an HID report.</p><h4id="api-raw-hid-send-arguments"tabindex="-1">Arguments <aclass="header-anchor"href="#api-raw-hid-send-arguments"aria-label="Permalink to "Arguments {#api-raw-hid-send-arguments}""></a></h4><ul><li><code>uint8_t *data</code><br> A pointer to the data to send. Must always be 32 bytes in length.</li><li><code>uint8_t length</code><br> The length of the buffer. Must always be 32.</li></ul></div></div></main><footerclass="VPDocFooter"data-v-39a288b8data-v-09de1c0f><!--[--><!--]--><!----><navclass="prev-next"data-v-09de1c0f><divclass="pager"data-v-09de1c0f><aclass="VPLink link pager-link prev"href="/feature_os_detection"data-v-09de1c0f><!--[--><spanclass="desc"data-v-09de1c0f>Previous page</span><spanclass="title"data-v-09de1c0f>OS Detection</span><!--]--></a></div><divclass="pager"data-v-09de1c0f><aclass="VPLink link pager-link next"href="/feature_secure"data-v-09de1c0f><!--[--><spanclass="desc"data-v-09de1c0f>Next page</span><spanclass="title"data-v-09de1c0f>Secure</span><!--]--></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><!----><!--[--><!--]--></div></div>