Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


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.12 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge