@@ -86,6 +86,16 @@ config SAMPLE_FPROBE
This builds a fprobe example module. This module has an option 'symbol'.
You can specify a probed symbol or symbols separated with ','.
+config SAMPLE_GHID_GET_REPORT
+ bool "GHID sample get report"
+ depends on CC_CAN_LINK && HEADERS_INSTALL
+ help
+ Build GHID sample get report program. This program can send reports from
+ userspace(gadget side) which are saved in the kernel in a linked list.
+ When a host requests a particular report based on report number and type,
+ corresponding report can be send to host, instead of a zero filled in report.
+ This program can add, delete reports and modify an existing report.
+
config SAMPLE_KFIFO
tristate "Build kfifo examples -- loadable modules only"
depends on m
@@ -6,6 +6,7 @@ subdir-$(CONFIG_SAMPLE_ANDROID_BINDERFS) += binderfs
obj-$(CONFIG_SAMPLE_CONFIGFS) += configfs/
obj-$(CONFIG_SAMPLE_CONNECTOR) += connector/
obj-$(CONFIG_SAMPLE_FANOTIFY_ERROR) += fanotify/
+subdir-$(SAMPLE_GHID_GET_REPORT) += ghid
subdir-$(CONFIG_SAMPLE_HIDRAW) += hidraw
obj-$(CONFIG_SAMPLE_HW_BREAKPOINT) += hw_breakpoint/
obj-$(CONFIG_SAMPLE_KDB) += kdb/
new file mode 100644
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+userprogs-always-y += test-hid
+
+userccflags += -I usr/include
new file mode 100644
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * usb hidg GET_REPORT example, device/gadget side
+ * This program tests the newly implemented GET_REPORT feature
+ *
+ * Copyright (c) 2022 Amarula Solutions India PVT LTD
+ *
+ * Authors:
+ * Copyright (c) 2022 Suniel Mahesh <sunil@amarulasolutions.com>
+ *
+ */
+
+#include <pthread.h>
+/* Linux */
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/hidraw.h>
+#include <linux/uhid.h>
+#include <uapi/linux/usb/g_hid.h>
+
+/* Unix */
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* C */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+
+/*
+ * fix for failing compilation on systems that don't
+ * yet populate new version of uapi/linux/usb/g_hid.h
+ * to userspace.
+ */
+#define GADGET_ADD_REPORT_STATUS _IOWR('g', 0x41, struct uhid_set_report_req)
+#define GADGET_REMOVE_REPORT_STATUS _IOWR('g', 0x42, struct uhid_get_report_req)
+#define GADGET_UPDATE_REPORT_STATUS _IOWR('g', 0x43, struct uhid_set_report_req)
+
+struct uhid_set_report_req *create_report(void)
+{
+ struct uhid_set_report_req *rep;
+ int i;
+
+ rep = (struct uhid_set_report_req *)calloc(1, sizeof(struct uhid_set_report_req));
+ if (rep == NULL) {
+ perror("calloc() failed");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("enter report id:\n");
+ scanf("%u", &rep->id);
+ printf("enter report number:\n");
+ scanf("%hhu", &rep->rnum);
+ printf("enter report type:\n");
+ scanf("%hhu", &rep->rtype);
+ printf("enter report size:\n");
+ scanf("%hu", &rep->size);
+ printf("enter report data:\n");
+
+ for (i = 0; i < rep->size; i++)
+ scanf("%hhu", &rep->data[i]);
+
+ return rep;
+}
+
+int main(int argc, char **argv)
+{
+ const char *filename = NULL;
+ struct uhid_set_report_req *report;
+ int fd = 0, res = 0, i, reports;
+
+ if (argc < 1) {
+ fprintf(stderr, "Usage: %s /dev/hidg0\n", argv[0]);
+ return -1;
+ }
+
+ filename = argv[1];
+ fd = open(filename, O_RDWR, 0666);
+
+ if (fd == -1) {
+ perror(filename);
+ return -2;
+ }
+
+ printf("enter no of reports to send from userspace:\n");
+ scanf("%d", &reports);
+
+ if (reports == 0)
+ goto out;
+
+ for (i = 0; i < reports; i++) {
+ report = create_report();
+/* send reports to device */
+ res = ioctl(fd, GADGET_ADD_REPORT_STATUS, report);
+ if (res < 0) {
+ perror("GADGET_ADD_REPORT_STATUS");
+ res = -3;
+ goto test_end;
+ }
+ free(report);
+ }
+
+/* delete report with report number specified */
+ printf("deleting report w.r.t rtype and rnum:\n");
+ report = create_report();
+ res = ioctl(fd, GADGET_REMOVE_REPORT_STATUS, report);
+ if (res < 0) {
+ perror("GADGET_REMOVE_REPORT_STATUS");
+ res = -4;
+ goto test_end;
+ }
+ free(report);
+
+/* modify an existing report identified by report number */
+ printf("modify report w.r.t rtype and rnum:\n");
+ report = create_report();
+ res = ioctl(fd, GADGET_UPDATE_REPORT_STATUS, report);
+ if (res < 0) {
+ perror("GADGET_UPDATE_REPORT_STATUS");
+ res = -5;
+ }
+
+test_end:
+ free(report);
+ report = NULL;
+out:
+ close(fd);
+ return res;
+}
This adds a user-space ghid sample get report program at gadget side. This program sends reports from userspace(gadget side) which are saved in the kernel in a list. When a host requests a particular report based on report number and type, corresponding report can be send to host, instead of a zero filled in report. This program can add, delete reports and modify an existing report. Signed-off-by: Suniel Mahesh <sunil@amarulasolutions.com> --- samples/Kconfig | 10 +++ samples/Makefile | 1 + samples/ghid/Makefile | 4 ++ samples/ghid/test-hid.c | 134 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 samples/ghid/Makefile create mode 100644 samples/ghid/test-hid.c