~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/hid/hid-bpf.rst

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /Documentation/hid/hid-bpf.rst (Version linux-6.12-rc7) and /Documentation/hid/hid-bpf.rst (Version linux-4.16.18)


  1 .. SPDX-License-Identifier: GPL-2.0               
  2                                                   
  3 =======                                           
  4 HID-BPF                                           
  5 =======                                           
  6                                                   
  7 HID is a standard protocol for input devices b    
  8 custom tweaks, traditionally done with a kerne    
  9 capabilities instead speeds up development and    
 10 existing HID interfaces.                          
 11                                                   
 12 .. contents::                                     
 13     :local:                                       
 14     :depth: 2                                     
 15                                                   
 16                                                   
 17 When (and why) to use HID-BPF                     
 18 =============================                     
 19                                                   
 20 There are several use cases when using HID-BPF    
 21 than standard kernel driver fix:                  
 22                                                   
 23 Dead zone of a joystick                           
 24 -----------------------                           
 25                                                   
 26 Assuming you have a joystick that is getting o    
 27 wobbling around its neutral point. This is usu    
 28 level by adding a *dead zone* for this specifi    
 29                                                   
 30 With HID-BPF, we can apply this filtering in t    
 31 does not get woken up when nothing else is hap    
 32                                                   
 33 Of course, given that this dead zone is specif    
 34 can not create a generic fix for all of the sa    
 35 kernel API for this (e.g. by adding a sysfs en    
 36 kernel API will be broadly adopted and maintai    
 37                                                   
 38 HID-BPF allows the userspace program to load t    
 39 only load the custom API when we have a user.     
 40                                                   
 41 Simple fixup of report descriptor                 
 42 ---------------------------------                 
 43                                                   
 44 In the HID tree, half of the drivers only fix     
 45 in the report descriptor. These fixes all requ    
 46 subsequent shepherding into a release, a long     
 47                                                   
 48 We can reduce this burden by providing an eBPF    
 49 program  has been verified by the user, we can    
 50 kernel tree and ship the eBPF program and load    
 51 a specific kernel module for it.                  
 52                                                   
 53 Note: distribution of eBPF programs and their     
 54 yet fully implemented                             
 55                                                   
 56 Add a new feature that requires a new kernel A    
 57 ----------------------------------------------    
 58                                                   
 59 An example for such a feature are the Universa    
 60 Basically, USI pens require a new kernel API b    
 61 channels of communication that our HID and inp    
 62 Instead of using hidraw or creating new sysfs     
 63 on eBPF to have the kernel API controlled by t    
 64 impact the performances by waking up userspace    
 65 event.                                            
 66                                                   
 67 Morph a device into something else and control    
 68 ----------------------------------------------    
 69                                                   
 70 The kernel has a relatively static mapping of     
 71 It cannot decide to dynamically transform a gi    
 72 as it does not have the required context and a    
 73 undone (or even discovered) by userspace.         
 74                                                   
 75 However, some devices are useless with that st    
 76 example, the Microsoft Surface Dial is a pushb    
 77 is barely usable as of today.                     
 78                                                   
 79 With eBPF, userspace can morph that device int    
 80 events into wheel events. Also, the userspace     
 81 feedback depending on the context. For example    
 82 screen we likely need to have a haptic click e    
 83 scrolling in a web page the user experience is    
 84 events at the highest resolution.                 
 85                                                   
 86 Firewall                                          
 87 --------                                          
 88                                                   
 89 What if we want to prevent other users to acce    
 90 device? (think a possibly broken firmware upda    
 91                                                   
 92 With eBPF, we can intercept any HID command em    
 93 validate it or not.                               
 94                                                   
 95 This also allows to sync the state between the    
 96 kernel/bpf program because we can intercept an    
 97                                                   
 98 Tracing                                           
 99 -------                                           
100                                                   
101 The last usage is tracing events and all the f    
102 and analyze events.                               
103                                                   
104 Right now, tracing relies on hidraw. It works     
105 of issues:                                        
106                                                   
107 1. if the driver doesn't export a hidraw node,    
108    (eBPF will be a "god-mode" there, so this m    
109 2. hidraw doesn't catch other processes' reque    
110    means that we have cases where we need to a    
111    to understand what is happening.               
112                                                   
113 High-level view of HID-BPF                        
114 ==========================                        
115                                                   
116 The main idea behind HID-BPF is that it works     
117 Thus, all of the parsing of the HID report and    
118 must be implemented in the userspace component    
119 program.                                          
120                                                   
121 For example, in the dead zone joystick from ab    
122 in the data stream needs to be set to ``0`` ne    
123                                                   
124 A corollary of this is that HID-BPF doesn't kn    
125 available in the kernel. *You can not directly    
126 input API from eBPF*.                             
127                                                   
128 When a BPF program needs to emit input events,    
129 protocol, and rely on the HID kernel processin    
130 input events.                                     
131                                                   
132 In-tree HID-BPF programs and ``udev-hid-bpf``     
133 =============================================     
134                                                   
135 Official device fixes are shipped in the kerne    
136 ``drivers/hid/bpf/progs`` directory. This allo    
137 ``tools/testing/selftests/hid``.                  
138                                                   
139 However, the compilation of these objects is n    
140 given that they need an external tool to be lo    
141 `udev-hid-bpf <https://libevdev.pages.freedesk    
142                                                   
143 For convenience, that external repository dupl    
144 ``drivers/hid/bpf/progs`` into its own ``src/b    
145 distributions to not have to pull the entire k    
146 those HID-BPF fixes. ``udev-hid-bpf`` also has    
147 objects files depending on the kernel the user    
148                                                   
149 Available types of programs                       
150 ===========================                       
151                                                   
152 HID-BPF is built "on top" of BPF, meaning that    
153 declare our programs.                             
154                                                   
155 HID-BPF has the following attachment types ava    
156                                                   
157 1. event processing/filtering with ``SEC("stru    
158 2. actions coming from userspace with ``SEC("s    
159 3. change of the report descriptor with ``SEC(    
160    ``SEC("struct_ops.s/hid_rdesc_fixup")`` in     
161                                                   
162 A ``hid_device_event`` is calling a BPF progra    
163 the device. Thus we are in IRQ context and can    
164 And given that we are in IRQ context, we can n    
165                                                   
166 A ``syscall`` means that userspace called the     
167 This time, we can do any operations allowed by    
168 allowed.                                          
169                                                   
170 Last, ``hid_rdesc_fixup`` is different from th    
171 BPF program of this type. This is called on ``    
172 change the report descriptor from the BPF prog    
173 program has been loaded, it is not possible to    
174 inserted it allows us by pinning the program a    
175                                                   
176 Note that ``hid_rdesc_fixup`` can be declared     
177                                                   
178                                                   
179 Developer API:                                    
180 ==============                                    
181                                                   
182 Available ``struct_ops`` for HID-BPF:             
183 -------------------------------------             
184                                                   
185 .. kernel-doc:: include/linux/hid_bpf.h           
186    :identifiers: hid_bpf_ops                      
187                                                   
188                                                   
189 User API data structures available in programs    
190 ----------------------------------------------    
191                                                   
192 .. kernel-doc:: include/linux/hid_bpf.h           
193    :identifiers: hid_bpf_ctx                      
194                                                   
195 Available API that can be used in all HID-BPF     
196 ----------------------------------------------    
197                                                   
198 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispat    
199    :identifiers: hid_bpf_get_data                 
200                                                   
201 Available API that can be used in syscall HID-    
202 ----------------------------------------------    
203                                                   
204 .. kernel-doc:: drivers/hid/bpf/hid_bpf_dispat    
205    :identifiers: hid_bpf_hw_request hid_bpf_hw    
206                                                   
207 General overview of a HID-BPF program             
208 =====================================             
209                                                   
210 Accessing the data attached to the context        
211 ------------------------------------------        
212                                                   
213 The ``struct hid_bpf_ctx`` doesn't export the     
214 it, a bpf program needs to first call :c:func:    
215                                                   
216 ``offset`` can be any integer, but ``size`` ne    
217 time.                                             
218                                                   
219 This allows the following:                        
220                                                   
221 1. for a given device, if we know that the rep    
222    we can request the ``data`` pointer to poin    
223                                                   
224    The kernel will ensure we are using a corre    
225    the code will not attempt to read or write     
226                                                   
227      __u8 *data = hid_bpf_get_data(ctx, 0 /* o    
228                                                   
229      if (!data)                                   
230          return 0; /* ensure data is correct,     
231                     * have 256 bytes available    
232                                                   
233      bpf_printk("hello world: %02x %02x %02x",    
234                                                   
235 2. if the report length is variable, but we kn    
236    integer, we can then have a pointer to that    
237                                                   
238       __u16 *x = hid_bpf_get_data(ctx, offset,    
239                                                   
240       if (!x)                                     
241           return 0; /* something went wrong */    
242                                                   
243       *x += 1; /* increment X by one */           
244                                                   
245 Effect of a HID-BPF program                       
246 ---------------------------                       
247                                                   
248 For all HID-BPF attachment types except for :c    
249 programs can be attached to the same device. I    
250 :c:func:`hid_rdesc_fixup` while another is alr    
251 kernel will return `-EINVAL` when attaching th    
252                                                   
253 Unless ``BPF_F_BEFORE`` is added to the flags     
254 program is appended at the end of the list.       
255 ``BPF_F_BEFORE`` will insert the new program a    
256 useful for e.g. tracing where we need to get t    
257                                                   
258 Note that if there are multiple programs using    
259 only the most recently loaded one is actually     
260                                                   
261 ``SEC("struct_ops/hid_device_event")``            
262 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~            
263                                                   
264 Whenever a matching event is raised, the eBPF     
265 and are working on the same data buffer.          
266                                                   
267 If a program changes the data associated with     
268 the modified data but it will have *no* idea o    
269                                                   
270 Once all the programs are run and return ``0``    
271 HID stack will work on the modified data, with    
272 being the new size of the input stream of data    
273                                                   
274 A BPF program returning a negative error disca    
275 processed by the HID stack. Clients (hidraw, i    
276                                                   
277 ``SEC("syscall")``                                
278 ~~~~~~~~~~~~~~~~~~                                
279                                                   
280 ``syscall`` are not attached to a given device    
281 with, userspace needs to refer to the device b    
282 in the sysfs path: ``/sys/bus/hid/devices/xxxx    
283                                                   
284 To retrieve a context associated with the devi    
285 hid_bpf_allocate_context() and must release it    
286 before returning.                                 
287 Once the context is retrieved, one can also re    
288 hid_bpf_get_data(). This memory is big enough     
289 reports of the given device.                      
290                                                   
291 ``SEC("struct_ops/hid_rdesc_fixup")``             
292 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~             
293                                                   
294 The ``hid_rdesc_fixup`` program works in a sim    
295 of ``struct hid_driver``.                         
296                                                   
297 When the device is probed, the kernel sets the    
298 content of the report descriptor. The memory a    
299 ``HID_MAX_DESCRIPTOR_SIZE`` (currently 4kB).      
300                                                   
301 The eBPF program can modify the data buffer at    
302 modified content and size as the report descri    
303                                                   
304 Whenever a struct_ops containing a ``SEC("stru    
305 is attached (if no program was attached before    
306 the HID device and does a reprobe.                
307                                                   
308 In the same way, when this struct_ops is detac    
309 on the device.                                    
310                                                   
311 There is no ``detach`` facility in HID-BPF. De    
312 all the user space file descriptors pointing a    
313 Thus, if we need to replace a report descripto    
314 required from the owner of the original report    
315 The previous owner will likely pin the struct_    
316 replace it through normal bpf operations.         
317                                                   
318 Attaching a bpf program to a device               
319 ===================================               
320                                                   
321 We now use standard struct_ops attachment thro    
322 But given that we need to attach a struct_ops     
323 must set ``hid_id`` in the struct_ops map befo    
324                                                   
325 ``hid_id`` is the unique system ID of the HID     
326 sysfs path: ``/sys/bus/hid/devices/xxxx:yyyy:z    
327                                                   
328 One can also set ``flags``, which is of type `    
329                                                   
330 We can not rely on hidraw to bind a BPF progra    
331 artefact of the processing of the HID device,     
332 even disable it, so that removes the tracing c    
333 (where it is interesting to get the non-hidraw    
334                                                   
335 On the other hand, the ``hid_id`` is stable fo    
336 even if we change its report descriptor.          
337                                                   
338 Given that hidraw is not stable when the devic    
339 accessing the current report descriptor of the    
340 This is available at ``/sys/bus/hid/devices/BU    
341 binary stream.                                    
342                                                   
343 Parsing the report descriptor is the responsib    
344 component that loads the eBPF program.            
345                                                   
346 An (almost) complete example of a BPF enhanced    
347 ==============================================    
348                                                   
349 *Foreword: for most parts, this could be imple    
350                                                   
351 Let's imagine we have a new tablet device that    
352 to simulate the surface the user is scratching    
353 a specific 3 positions switch to toggle betwee    
354 and *brush on a painting canvas*. To make thin    
355 physical position of the switch through a feat    
356                                                   
357 And of course, the switch is relying on some u    
358 haptic feature of the device itself.              
359                                                   
360 Filtering events                                  
361 ----------------                                  
362                                                   
363 The first step consists in filtering events fr    
364 position is actually reported in the flow of t    
365 that filtering would mean that we wake up user    
366                                                   
367 This is OK for libinput, but having an externa    
368 one byte in the report is less than ideal.        
369                                                   
370 For that, we can create a basic skeleton for o    
371                                                   
372   #include "vmlinux.h"                            
373   #include <bpf/bpf_helpers.h>                    
374   #include <bpf/bpf_tracing.h>                    
375                                                   
376   /* HID programs need to be GPL */               
377   char _license[] SEC("license") = "GPL";         
378                                                   
379   /* HID-BPF kfunc API definitions */             
380   extern __u8 *hid_bpf_get_data(struct hid_bpf    
381                               unsigned int off    
382                               const size_t __s    
383                                                   
384   struct {                                        
385         __uint(type, BPF_MAP_TYPE_RINGBUF);       
386         __uint(max_entries, 4096 * 64);           
387   } ringbuf SEC(".maps");                         
388                                                   
389   __u8 current_value = 0;                         
390                                                   
391   SEC("struct_ops/hid_device_event")              
392   int BPF_PROG(filter_switch, struct hid_bpf_c    
393   {                                               
394         __u8 *data = hid_bpf_get_data(hid_ctx,    
395         __u8 *buf;                                
396                                                   
397         if (!data)                                
398                 return 0; /* EPERM check */       
399                                                   
400         if (current_value != data[152]) {         
401                 buf = bpf_ringbuf_reserve(&rin    
402                 if (!buf)                         
403                         return 0;                 
404                                                   
405                 *buf = data[152];                 
406                                                   
407                 bpf_ringbuf_commit(buf, 0);       
408                                                   
409                 current_value = data[152];        
410         }                                         
411                                                   
412         return 0;                                 
413   }                                               
414                                                   
415   SEC(".struct_ops.link")                         
416   struct hid_bpf_ops haptic_tablet = {            
417         .hid_device_event = (void *)filter_swi    
418   };                                              
419                                                   
420                                                   
421 To attach ``haptic_tablet``, userspace needs t    
422                                                   
423   static int attach_filter(struct hid *hid_ske    
424   {                                               
425         int err, link_fd;                         
426                                                   
427         hid_skel->struct_ops.haptic_tablet->hi    
428         err = hid__load(skel);                    
429         if (err)                                  
430                 return err;                       
431                                                   
432         link_fd = bpf_map__attach_struct_ops(h    
433         if (!link_fd) {                           
434                 fprintf(stderr, "can not attac    
435                 return -1;                        
436         }                                         
437                                                   
438         return link_fd; /* the fd of the creat    
439   }                                               
440                                                   
441 Our userspace program can now listen to notifi    
442 is awaken only when the value changes.            
443                                                   
444 When the userspace program doesn't need to lis    
445 close the returned bpf link from :c:func:`atta    
446 detach the program from the HID device.           
447                                                   
448 Of course, in other use cases, the userspace p    
449 BPF filesystem through a call to :c:func:`bpf_    
450                                                   
451 Controlling the device                            
452 ----------------------                            
453                                                   
454 To be able to change the haptic feedback from     
455 needs to emit a feature report on the device i    
456                                                   
457 Instead of using hidraw for that, we can creat    
458 that talks to the device::                        
459                                                   
460   /* some more HID-BPF kfunc API definitions *    
461   extern struct hid_bpf_ctx *hid_bpf_allocate_    
462   extern void hid_bpf_release_context(struct h    
463   extern int hid_bpf_hw_request(struct hid_bpf    
464                               __u8* data,         
465                               size_t len,         
466                               enum hid_report_    
467                               enum hid_class_r    
468                                                   
469                                                   
470   struct hid_send_haptics_args {                  
471         /* data needs to come at offset 0 so w    
472         __u8 data[10];                            
473         unsigned int hid;                         
474   };                                              
475                                                   
476   SEC("syscall")                                  
477   int send_haptic(struct hid_send_haptics_args    
478   {                                               
479         struct hid_bpf_ctx *ctx;                  
480         int ret = 0;                              
481                                                   
482         ctx = hid_bpf_allocate_context(args->h    
483         if (!ctx)                                 
484                 return 0; /* EPERM check */       
485                                                   
486         ret = hid_bpf_hw_request(ctx,             
487                                  args->data,      
488                                  10,              
489                                  HID_FEATURE_R    
490                                  HID_REQ_SET_R    
491                                                   
492         hid_bpf_release_context(ctx);             
493                                                   
494         return ret;                               
495   }                                               
496                                                   
497 And then userspace needs to call that program     
498                                                   
499   static int set_haptic(struct hid *hid_skel,     
500   {                                               
501         int err, prog_fd;                         
502         int ret = -1;                             
503         struct hid_send_haptics_args args = {     
504                 .hid = hid_id,                    
505         };                                        
506         DECLARE_LIBBPF_OPTS(bpf_test_run_opts,    
507                 .ctx_in = &args,                  
508                 .ctx_size_in = sizeof(args),      
509         );                                        
510                                                   
511         args.data[0] = 0x02; /* report ID of t    
512         args.data[1] = haptic_value;              
513                                                   
514         prog_fd = bpf_program__fd(hid_skel->pr    
515                                                   
516         err = bpf_prog_test_run_opts(prog_fd,     
517         return err;                               
518   }                                               
519                                                   
520 Now our userspace program is aware of the hapt    
521 program could make this state further availabl    
522 (e.g. via a DBus API).                            
523                                                   
524 The interesting bit here is that we did not cr    
525 Which means that if there is a bug in our impl    
526 interface with the kernel at-will, because the    
527 responsible for its own usage.                    
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php