Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/samples/hid/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  hid_surface_dial.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2022 Benjamin Tissoires
 *
 * This program will morph the Microsoft Surface Dial into a mouse,
 * and depending on the chosen resolution enable or not the haptic feedback:
 * - a resolution (-r) of 3600 will report 3600 "ticks" in one full rotation
 *   without haptic feedback
 * - any other resolution will report N "ticks" in a full rotation with haptic
 *   feedback
 *
 * A good default for low resolution haptic scrolling is 72 (1 "tick" every 5
 * degrees), and set to 3600 for smooth scrolling.
 */


#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <unistd.h>

#include <linux/bpf.h>
#include <linux/errno.h>

#include <bpf/bpf.h>
#include <bpf/libbpf.h>

#include "hid_surface_dial.skel.h"

static bool running = true;

struct haptic_syscall_args {
 unsigned int hid;
 int retval;
};

static void int_exit(int sig)
{
 running = false;
 exit(0);
}

static void usage(const char *prog)
{
 fprintf(stderr,
  "%s: %s [OPTIONS] /sys/bus/hid/devices/0BUS:0VID:0PID:00ID\n\n"
  " OPTIONS:\n"
  " -r N\t set the given resolution to the device (number of ticks per 360°)\n\n",
  __func__, prog);
 fprintf(stderr,
  "This program will morph the Microsoft Surface Dial into a mouse,\n"
  "and depending on the chosen resolution enable or not the haptic feedback:\n"
  "- a resolution (-r) of 3600 will report 3600 'ticks' in one full rotation\n"
  " without haptic feedback\n"
  "- any other resolution will report N 'ticks' in a full rotation with haptic\n"
  " feedback\n"
  "\n"
  "A good default for low resolution haptic scrolling is 72 (1 'tick' every 5\n"
  "degrees), and set to 3600 for smooth scrolling.\n");
}

static int get_hid_id(const char *path)
{
 const char *str_id, *dir;
 char uevent[1024];
 int fd;

 memset(uevent, 0, sizeof(uevent));
 snprintf(uevent, sizeof(uevent) - 1, "%s/uevent", path);

 fd = open(uevent, O_RDONLY | O_NONBLOCK);
 if (fd < 0)
  return -ENOENT;

 close(fd);

 dir = basename((char *)path);

 str_id = dir + sizeof("0003:0001:0A37.");
 return (int)strtol(str_id, NULL, 16);
}

static int set_haptic(struct hid_surface_dial *skel, int hid_id)
{
 struct haptic_syscall_args args = {
  .hid = hid_id,
  .retval = -1,
 };
 int haptic_fd, err;
 DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattr,
       .ctx_in = &args,
       .ctx_size_in = sizeof(args),
 );

 haptic_fd = bpf_program__fd(skel->progs.set_haptic);
 if (haptic_fd < 0) {
  fprintf(stderr, "can't locate haptic prog: %m\n");
  return 1;
 }

 err = bpf_prog_test_run_opts(haptic_fd, &tattr);
 if (err) {
  fprintf(stderr, "can't set haptic configuration to hid device %d: %m (err: %d)\n",
   hid_id, err);
  return 1;
 }
 return 0;
}

int main(int argc, char **argv)
{
 struct hid_surface_dial *skel;
 const char *optstr = "r:";
 struct bpf_link *link;
 const char *sysfs_path;
 int err, opt, hid_id, resolution = 72;

 while ((opt = getopt(argc, argv, optstr)) != -1) {
  switch (opt) {
  case 'r':
   {
    char *endp = NULL;
    long l = -1;

    if (optarg) {
     l = strtol(optarg, &endp, 10);
     if (endp && *endp)
      l = -1;
    }

    if (l < 0) {
     fprintf(stderr,
      "invalid r option %s - expecting a number\n",
      optarg ? optarg : "");
     exit(EXIT_FAILURE);
    };

    resolution = (int) l;
    break;
   }
  default:
   usage(basename(argv[0]));
   return 1;
  }
 }

 if (optind == argc) {
  usage(basename(argv[0]));
  return 1;
 }

 sysfs_path = argv[optind];
 if (!sysfs_path) {
  perror("sysfs");
  return 1;
 }

 skel = hid_surface_dial__open();
 if (!skel) {
  fprintf(stderr, "%s %s:%d", __func__, __FILE__, __LINE__);
  return -1;
 }

 hid_id = get_hid_id(sysfs_path);
 if (hid_id < 0) {
  fprintf(stderr, "can not open HID device: %m\n");
  return 1;
 }

 skel->struct_ops.surface_dial->hid_id = hid_id;

 err = hid_surface_dial__load(skel);
 if (err < 0) {
  fprintf(stderr, "can not load HID-BPF program: %m\n");
  return 1;
 }

 skel->data->resolution = resolution;
 skel->data->physical = (int)(resolution / 72);

 link = bpf_map__attach_struct_ops(skel->maps.surface_dial);
 if (!link) {
  fprintf(stderr, "can not attach HID-BPF program: %m\n");
  return 1;
 }

 signal(SIGINT, int_exit);
 signal(SIGTERM, int_exit);

 set_haptic(skel, hid_id);

 while (running)
  sleep(1);

 hid_surface_dial__destroy(skel);

 return 0;
}

Messung V0.5
C=100 H=96 G=97

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.