Como posso escrever no dispositivo HID dos controladores Buzz criado por hid-sony.c para trabalhar com os LEDs?

2

Eu tenho tentado por um tempo, mas não consegui encontrar uma maneira de controlar as luzes em um conjunto de controles do jogo Buzz (com fio, do Playstation 2). Você pode ver algumas das minhas tentativas fracassadas nas minhas perguntas no Stack Overflow

Então eu mudei para um método linux mais básico de envio de mensagens, e falhei em fazer piping de dados para / dev / hidraw0 também.

Então eu descobri um arquivo no repositório linux que se refere especificamente aos controladores de buzz (), e o fato de que eles têm uma luz. Ele ainda tem um método chamado buzz_set_leds (linha 1512):

static void buzz_set_leds(struct sony_sc *sc)

Portanto, tenho 100% de certeza de que este código faz o que estou tentando fazer.

Eu tive a chance de incluir isso em um arquivo c, mas não consigo incluir o hid-sony porque parece que estou perdendo esses arquivos.

#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"

Na compilação, recebo este erro:

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

Desculpe, sou um programador Ruby sem experiência em C.

Como obtenho esses arquivos 'linux /' em falta e me refiro a eles em minha biblioteca c - ou como posso gravar nos controllers a partir do shell?

    
por AJFaraday 17.09.2015 / 22:53

3 respostas

1

com o driver sony carregado, o driver fornece interfaces de kernel padrão:

echo 255 > /sys/class/leds/*buzz1/brightness
echo 0 > /sys/class/leds/*buzz1/brightness
    
por 30.08.2016 / 15:16
5

De um shell script é relativamente simples, mas requer o conhecimento da coisa certa a ser enviada. Dispositivos / dev / hidraw são chamados de "raw" porque eles são apenas isso (eu suspeito) - de este artigo em um site chamado developerFusion, que eu encontrei há muito tempo atrás (especificamente "figura 3") - esse autor relatou que o dispositivo queria que um relatório de seis bytes fosse enviado para ele LEDs (um em cada um dos quatro controladores "player") ligados ou desligados. Resumidamente, eles descobriram que, por seis bytes 1-6, eles foram usados:

Byte 1: não importa - sugira usar o 0x00
Byte 2: não importa - sugira usar o 0x00
Byte 3: 0x00 (desligado) ou 0xFF (ligado) - Monofone 1
Byte 4: 0 x 00 (desligado) ou 0xFF (ligado) - fone 2
Byte 5: 0x00 (desligado) ou 0xFF (ligado) - fone 3
Byte 6: 0x00 (desligado) ou 0xFF (ligado) - Monofone 4

Então, depois de algumas experiências eu descobri que, para um Controlador "Buzz" que o sistema udev (?) nomeou / symlinked para /dev/hidraw0 o seguinte irá piscar cada um dos LEDs em seqüência:

#!/bin/bash

delay=0.1 while [ true ]; do echo -e "\x00\x00\x00\x00\x00\x00\x00" > /dev/hidraw0 sleep ${delay} echo -e "\x00\x00\x00\x00\x00\xff\x00" > /dev/hidraw0 sleep ${delay} echo -e "\x00\x00\x00\x00\xff\x00\x00" > /dev/hidraw0 sleep ${delay} echo -e "\x00\x00\x00\xff\x00\x00\x00" > /dev/hidraw0 sleep ${delay} echo -e "\x00\x00\xff\x00\x00\x00\x00" > /dev/hidraw0 sleep ${delay} echo -e "\x00\x00\x00\x00\x00\x00\x00" > /dev/hidraw0 sleep ${delay} done

I acha que o último caractere ASCII "nul" é necessário para terminar a cadeia ou pode ser um artefato da linguagem que o autor do artigo estava usando (.NET / c #) que ocultava que sete bytes estavam sendo usados, não seis - mas essas línguas são completamente estranhas para mim. O que eu descobri foi que, se a string de comprimento certo não é usada, esse último byte é deixado de lado - a string não é reconhecida, pelo menos depois que a primeira string enviada é consistente com um requisito de "duração fixa do relatório".

Eu queria simplificar as coisas usando o udev para fornecer nomes significativos para esses dispositivos, então criei um arquivo /lib/udev/rules.d/10-local.rules para o meu PC Debian "Jessie" (usando sysV "init" NOT "systemd"):

ACTION!="add|change", GOTO="end"

# Assign a unique number to a buzz symbolic link to any Sony Buzz controllers
SUBSYSTEM=="usb", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="1000", PROGRAM=="/sbin/unique_number /dev buzz", SYMLINK+="buzz%c", TAG+="buzz", OPTIONS+=last_rule
SUBSYSTEM=="usb", ATTRS{idVendor}=="054c", ATTRS{idProduct}=="0002", PROGRAM=="/sbin/unique_number /dev buzz", SYMLINK+="buzz%c", TAG+="buzz", OPTIONS+=last_rule

LABEL="end"

e para fornecer um número único - especial no caso de eu conectar um hub com vários controladores Buzz e ter vários dispositivos adicionados ou removidos ao mesmo tempo, usei o seguinte /sbin/unique_number que foi derivado de algum lugar no SE - (EU irei aceitar edições para atribuir atribuições / copyrights válidas ...):

#!/bin/bash

# Copyright (C) 2015 by Stephen Lyons - [email protected]
#
# unique_number: This script is used to provide a unique suffix for a
#                file in a given directory

if [ $# -ne 2 ]; then
    echo "Usage: $0 location prefix\n\n" >&2
    echo "       Finds the first unused integer # suffixed file"
    echo "       of form prefix# in directory given by location,"
    echo "       and prints that number."
    exit 1
fi

location="$1"
prefix="$2"

index=0

while [ -e "/var/lock/unique_number.lock" ]; do
    sleep 0.1;
done

touch "/var/lock/unique_number.lock"

until [ ! -e "${location}/${prefix}${index}" ]; do
    (( index++ ));
done
echo "$index"

rm "/var/lock/unique_number.lock"
exit 0

No entanto, embora isso forneça / dev / buzz0, / dev / buzz1 como eu queria, essa combinação não funciona para fornecer algo que possa substituir /dev/hidraw0 etc. no primeiro script.

    
por 21.12.2015 / 20:22
2

Bem, seu arquivo de origem corresponde a uma fonte de driver linux. Então você terá que compilá-lo como um módulo. Para compilá-lo fora da árvore fonte do kernel, recomendo que você use o seguinte 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

Copie este conteúdo para um arquivo que você nomeará "makefile" no mesmo local que seu código-fonte c, em seguida, execute o comando "make". Você precisará ter o cabeçalho do kernel do linux instalado, você normalmente pode obtê-los dos pacotes (linux-headers-x.yy.zz-your_arch no debian). Isto produzirá um arquivo .ko que você pode carregar no seu kernel com o comando insmod (precisa ser root).

    
por 18.09.2015 / 01:39