Linux

如何寫入由 hid-sony.c 創建的 Buzz 控制器 HID 設備以使 LED 工作?

  • August 30, 2016

我已經嘗試了一段時間,但還沒有找到一種方法來控制遊戲 Buzz(有線,來自 Playstation 2)中的一組控制器上的燈。您可以在 Stack Overflow 上的問題中看到我的一些失敗嘗試

所以我轉向了一種更基礎的 linux 發送消息的方法,但也未能通過管道數據到 /dev/hidraw0 來做到這一點。

然後我在 linux 儲存庫中發現了一個文件,它專門引用了 Buzz 控制器(/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 寫入控制器?

從 shell 腳本來看,它相對簡單,但需要知道要發送的正確內容。/dev/hidraw 設備被稱為“原始”設備,因為它們就是(我懷疑)——從很久以前我在一個名為 developerFusion 的網站上發現的這篇文章(特別是“圖 3”)——作者報告說該設備希望向其發送一個六字節的報告,以打開或關閉 4 個 LED(四個“播放器”控制器中的每一個中的一個)。簡而言之,他們發現,對於 1-6 的六個字節,它們被使用:

字節 1:不關心 - 建議使用 0x00

字節 2:不關​​心 - 建議使用 0x00

字節 3:0x00(關閉)或 0xFF(開啟) - 手機 1

字節 4:0x00(關閉)或 0xFF(開啟) -手機 2

字節 5:0x00(關閉)或 0xFF(開啟)-手機 3

字節 6:0x00(關閉)或 0xFF(開啟)-手機 4

因此,經過一些試驗後,我發現,對於 udev 系統(?)已命名/符號連結到/dev/hidraw0以下內容的“Buzz”控制器,每個 LED 將按順序閃爍:

#!/bin/bash

延遲=0.1
而[真];做
迴聲 -e "\x00\x00\x00\x00\x00\x00\x00" > /dev/hidraw0
睡眠 ${延遲}
迴聲 -e "\x00\x00\x00\x00\x00\xff\x00" > /dev/hidraw0
睡眠 ${延遲}
迴聲 -e "\x00\x00\x00\x00\xff\x00\x00" > /dev/hidraw0
睡眠 ${延遲}
迴聲 -e "\x00\x00\x00\xff\x00\x00\x00" > /dev/hidraw0
睡眠 ${延遲}
迴聲 -e "\x00\x00\xff\x00\x00\x00\x00" > /dev/hidraw0
睡眠 ${延遲}
迴聲 -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!="add|change", GOTO="end"

# 為任何 Sony Buzz 控制器的 Buzz 符號連結分配一個唯一編號
SUBSYSTEM=="usb", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="1000", PROGRAM=="/sbin/unique_number /dev buzz", SYMLINK+="buzz%c", TAG+= “嗡嗡聲”,選項+=last_rule
SUBSYSTEM=="usb", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0002", PROGRAM=="/sbin/unique_number /dev buzz", SYMLINK+="buzz%c", TAG+= “嗡嗡聲”,選項+=last_rule

標籤="結束"

並提供一個唯一的編號 - 特別是在我插入一個帶有多個 Buzz 控制器的集線器並且將同時添加或刪除多個設備的情況下,我使用了以下/sbin/unique_number從 SE 某處派生的 - (我將接受編輯以提供有效的歸屬/版權…):

#!/bin/bash

# Copyright (C) 2015 by Stephen Lyons - slysven@virginmedia.com
#
# unique_number:此腳本用於為
# 給定目錄中的文件

如果 [ $# -ne 2 ]; 然後
echo "用法:$0 位置前綴\n\n" >&2
echo " 查找第一個未使用的整數 # 後綴文件"
在位置給定的目錄中回顯“形式前綴#”,
echo " 並列印該數字。"
1號出口
是

位置="$1"
前綴="$2"

索引=0

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

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

直到 [ !-e "${location}/${prefix}${index}" ]; 做
((索引++));
完畢
迴聲“$索引”

rm "/var/lock/unique_number.lock"
出口 0

但是,雖然這確實提供了我想要的 /dev/buzz0、/dev/buzz1,但這種組合不能/dev/hidraw0在第一個腳本中提供可以替換等的東西。

嗯,你的源文件對應一個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 使用者)。

引用自:https://unix.stackexchange.com/questions/230399