如何写入由 hid-sony.c 创建的 Buzz 控制器 HID 设备以使 LED 工作?

如何写入由 hid-sony.c 创建的 Buzz 控制器 HID 设备以使 LED 工作?

我已经尝试了一段时间,但一直无法找到一种方法来控制游戏 Buzz(有线,来自 Playstation 2)的一组控制器上的灯光。您可以在 Stack Overflow 上的问题中看到我的一些失败尝试

因此,我转向了一种更基本的 Linux 发送消息方法,但通过将数据管道传输到 /dev/hidraw0 也失败了。

然后我在 linux 存储库中发现了一个文件,该文件专门引用了嗡嗡声控制器(/linux/drivers/hid/hid-sony.c),以及它们有灯这一事实。它甚至有一个名为buzz_set_leds的方法(第1512行):

static void buzz_set_leds(struct sony_sc *sc)

所以我 100% 确定这就是我想要做的代码。

我尝试过将其包含在 ac 文件中,但无法包含 hid-sony,因为我似乎丢失了这些文件。

#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/leds.h>
#include <linux/power_supply.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/idr.h>
#include <linux/input/mt.h>

#include "hid-ids.h"

在编译中,我收到此错误:

hid-sony.c:29:26: fatal error: linux/device.h: No such file or directory
 #include <linux/device.h>
                          ^
compilation terminated.

抱歉,我是一名没有 C 背景的 Ruby 程序员。

如何获取这些丢失的“linux/”文件并从我的 c 库中引用它们 - 或者如何从 shell 写入控制器?

答案1

从 shell 脚本来看,它相对简单,但需要知道要发送的正确内容。 /dev/hidraw 设备被称为“原始”,因为它们就是这样(我怀疑) - 来自本文在一个名为developerFusion的网站上,我很久以前就发现了这个网站(特别是“图3”)——该作者报告说该设备需要向其发送一个六字节的报告来切换4个LED(每个LED一个)四个“玩家”控制器)打开或关闭。简而言之,他们发现,对于六个字节 1-6,它们被使用:

字节 1:不关心 - 建议使用 0x00
字节 2:不关心 - 建议使用 0x00
字节 3:0x00(关)或 0xFF(开)- 听筒 1
字节 4:0x00(关)或 0xFF(开)-听筒 2
字节 5:0x00(关闭)或 0xFF(打开) - 听筒 3
字节 6:0x00(关闭)或 0xFF(打开) - 听筒 4

因此,经过一些实验,我发现,对于 udev 系统(?)已命名/符号链接到以下内容的“Buzz”控制器,/dev/hidraw0每个 LED 将按顺序闪烁:

#!/bin/bash

延迟=0.1 而[真];做 echo -e "\x00\x00\x00\x00\x00\x00\x00" > /dev/hidraw0 睡眠${延迟} echo -e "\x00\x00\x00\x00\x00\xff\x00" > /dev/hidraw0 睡眠${延迟} echo -e "\x00\x00\x00\x00\xff\x00\x00" > /dev/hidraw0 睡眠${延迟} echo -e "\x00\x00\x00\xff\x00\x00\x00" > /dev/hidraw0 睡眠${延迟} echo -e "\x00\x00\xff\x00\x00\x00\x00" > /dev/hidraw0 睡眠${延迟} echo -e "\x00\x00\x00\x00\x00\x00\x00" > /dev/hidraw0 睡眠${延迟} 完毕

思考需要最后一个 ASCII“nul”字符来结束字符串,或者它可能是该文章作者所使用的语言(.NET / c#)的产物,该语言隐藏了正在使用的七个字节而不是六个字节 - 但随后那些语言对我来说完全陌生。我发现,如果未使用正确长度的字符串,则最后一个字节会被忽略 - 该字符串不会被识别,至少在发送第一个字符串之后,我认为这符合“固定报告长度”的要求。

我想通过使用 udev 为此类设备提供有意义的名称来使事情变得更简单,因此我/lib/udev/rules.d/10-local.rules为我的 Debian Linux“Jessie”PC 创建了一个文件(使用 sysV“init”而不是“systemd”):

ACTION!="添加|更改", GOTO="结束"

# 为任何 Sony Buzz 控制器的嗡嗡声符号链接分配一个唯一的编号
SUBSYSTEM==“usb”,ATTRS{idVendor}==“054c”,ATTRS{idProduct}==“1000”,PROGRAM==“/sbin/unique_number /dev嗡嗡声”,SYMLINK+=“buzz%c”,TAG+= “嗡嗡声”,OPTIONS+=last_rule
SUBSYSTEM==“usb”,ATTRS{idVendor}==“054c”,ATTRS{idProduct}==“0002”,PROGRAM==“/sbin/unique_number /dev嗡嗡声”,SYMLINK+=“buzz%c”,TAG+= “嗡嗡声”,OPTIONS+=last_rule

标签=“结束”

并提供一个唯一的编号 - 特别是在我插入带有多个 Buzz 控制器的集线器并且同时添加或删除多个设备的情况下,我使用了以下/sbin/unique_number源自 SE 上某处的内容 - (我将接受编辑以提供有效的归属/版权...):

#!/bin/bash

# 版权所有 (C) 2015,作者:Stephen Lyons -[电子邮件受保护]
#
# unique_number:此脚本用于为某个文件提供唯一的后缀
# 给定目录中的文件

如果 [ $# -ne 2 ];然后
    echo "用法: $0 位置前缀\n\n" >&2
    echo "查找第一个未使用的整数#后缀的文件"
    echo “在由位置给出的目录中的形式前缀#,”
    echo "并打印该数字。"
    1号出口

位置=“$1”
前缀=“$2”

索引=0

while [ -e "/var/lock/unique_number.lock" ];做
    睡眠 0.1;
完毕

触摸“/var/lock/unique_number.lock”

直到 [ ! -e "${位置}/${前缀}${索引}"];做
    ((索引++));
完毕
回显“$索引”

rm“/var/lock/unique_number.lock”
出口0

然而,虽然这确实提供了我想要的 /dev/buzz0、/dev/buzz1,这种组合不能提供可以替换/dev/hidraw0第一个脚本中的等的东西。

答案2

那么,你的源文件对应于linux驱动程序的源。因此,您必须将其编译为模块。要从内核源代码树中编译它,我建议您使用以下 makefile:

ifneq ($(KERNELRELEASE),)
        obj-m := hid-sony.o
else
        KDIR ?= /lib/modules/$(shell uname -r)/build
        PWD := $(shell pwd)

default:
        $(MAKE) -C $(KDIR) M=$(PWD) modules
endif

将此内容复制到与 c 源代码相同的位置中命名为“makefile”的文件,然后运行命令“make”。您需要安装 Linux 内核头文件,通常可以从软件包中获取它们(debian 上为 linux-headers-x.yy.zz-your_arch)。这将为您生成一个 .ko 文件,然后您可以使用 insmod 命令将其加载到内核中(需要是 root 用户)。

答案3

加载 sony 驱动程序后,该驱动程序提供标准 led 内核接口:

echo 255 > /sys/class/leds/*buzz1/brightness
echo 0 > /sys/class/leds/*buzz1/brightness

相关内容