Tecla Fn para Bluetooth Apple Magic Keyboard (2015)

2

Estou com problemas para usar meu Teclado Apple Magic (sem fio bluetooth com bateria LiIon, porta Lightning para carregar e amarrado uso) com o Fedora 25 (kernel: 4.8.15-300.fc25.x86_64 ).

O problema é que quando usado no modo sem fio, a chave Fn não parece se registrar. Eu tentei xev e a chave em si não aciona nenhum evento, nem a tecla pressionada com outra tecla faz com que o evento acionado seja diferente comparado à outra tecla que está sendo pressionada sozinha. A razão pela qual eu gostaria de usar a tecla Fn é porque eu quero mapear Fn + / para Home e End respectivamente e também usam as teclas multimídia que são agora teclas de função por padrão.

O interessante é que este teclado funciona como um teclado com fio normal da Apple quando eu o conecto com o cabo do relâmpago ao computador no qual presumo que o rádio bluetooth não esteja sendo usado e recorra a hardware / drivers USB (talvez está registrado com um ID de dispositivo USB diferente do teclado de alumínio original da Apple, que eu não verifiquei). Isso permite o uso de teclas de função e todos os truques como teclas de função ou teclas multimídia por padrão que você encontra na internet.

No entanto, eu gostaria de ter os mesmos recursos disponíveis quando usá-lo como um teclado bluetooth. Eu iria até remendar o kernel, mas não tenho idéia de onde começar e como testar e depurar (obviamente eu gostaria de experimentar menos "invasivo" significa primeiro).

Qualquer ideia sobre como resolver este problema é bem-vinda.

Atualizar

Quando eu leio do /dev/hidraw0 , eu obtenho alguma atividade quando pressiono a tecla Fn , então isso pode significar que o pressionamento da tecla fn é registrado pelo sistema, mas perdido em algum lugar ao longo do caminho ...

Update2

evtest não mostra nenhum evento quando pressionar a tecla Fn e /dev/input/event4 (que é o dispositivo de evento do Teclado Mágico) não aciona um evento (outras teclas). Então eu acho que o problema é que a chave Fn é lida pelo sistema (implícita por /dev/hidraw0 mostrando dados) mas não é passada para /dev/input/event4 . Mas isso é apenas especulação, já que não sei como o fluxo de dados de entrada do usuário deve funcionar no Linux.

Atualização 3

Isto é o que várias teclas fn pressionam (press + release) produzem:

> sudo cat /dev/hidraw2 | hexdump
0000000 0001 0000 0000 0000 0000 0001 0000 0000
0000010 0000 0200 0001 0000 0000 0000 0000 0001
0000020 0000 0000 0000 0200 0001 0000 0000 0000
0000030 0000 0001 0000 0000 0000 0200 0001 0000
0000040 0000 0000 0000 0001 0000 0000 0000 0200
0000050 0001 0000 0000 0000 0000 0001 0000 0000
0000060 0000 0200 0001 0000 0000 0000 0000 0001
0000070 0000 0000 0000 0200 0001 0000 0000 0000
0000080 0000 0001 0000 0000 0000 0200 0001 0000
0000090 0000 0000 0000 0001 0000 0000 0000 0200
00000a0 0001 0000 0000 0000 0000 0001 0000 0000
00000b0 0000 0200 0001 0000 0000 0000 0000 0001
00000c0 0000 0000 0000 0200 0001 0000 0000 0000
00000d0 0000 0001 0000 0000 0000 0200 0001 0000
00000e0 0000 0000 0000 0001 0000 0000 0000 0200
00000f0 0001 0000 0000 0000 0000 0001 0000 0000
0000100 0000 0200 0001 0000 0000 0000 0000 0001
0000110 0000 0000 0000 0200 0001 0000 0000 0000
0000120 0000 0001 0000 0000 0000 0200 0001 0000
0000130 0000 0000 0000 0001 0000 0000 0000 0200
0000140 0001 0000 0000 0000 0000 0001 0000 0000
0000150 0000 0200 0001 0000 0000 0000 0000 0001
0000160 0000 0000 0000 0200 0001 0000 0000 0000
0000170 0000 0001 0000 0000 0000 0200 0001 0000
0000180 0000 0000 0000 0001 0000 0000 0000 0200
0000190 0001 0000 0000 0000 0000 0001 0000 0000
00001a0 0000 0200 0001 0000 0000 0000 0000 0001
00001b0 0000 0000 0000 0200 0001 0000 0000 0000
00001c0 0000 0001 0000 0000 0000 0200 0001 0000
00001d0 0000 0000 0000 0001 0000 0000 0000 0200
00001e0 0001 0000 0000 0000 0000 0001 0000 0000
00001f0 0000 0200 0001 0000 0000 0000 0000 0001
0000200 0000 0000 0000 0200 0001 0000 0000 0000
0000210 0000 0001 0000 0000 0000 0200 0001 0000
0000220 0000 0000 0000 0001 0000 0000 0000 0200
0000230 0001 0000 0000 0000 0000 0001 0000 0000

Estranhamente, às vezes 2 linhas, mas principalmente 1 linha, são impressas depois de liberar fn .

Isto é o que F2 e Fn + F2 , respectivamente, se parecem com:

sudo cat /dev/hidraw2 | hexdump
0000000 0001 0000 0000 0000 0000 0001 3b00 0000
^[OQ0000010 0000 0000 0001 0000 0000 0000 0000 0001
^[OQ0000020 3b00 0000 0000 0000 0001 0000 0000 0000
^[OQ0000030 0000 0001 3b00 0000 0000 0000 0001 0000
0000040 0000 0000 0000 0001 3b00 0000 0000 0000
^[OQ0000050 0001 0000 0000 0000 0000 0001 3b00 0000
^[OQ0000060 0000 0000 0001 0000 0000 0000 0000 0001
^[OQ0000070 3b00 0000 0000 0000 0001 0000 0000 0000
0000080 0000 0101 0000 0000 0000 0000 0101 0600
^C

Fn + F2 :

> sudo cat /dev/hidraw2 | hexdump
0000000 0001 0000 0000 0000 0000 0001 0000 0000
^[OQ0000010 0000 0200 0001 3b00 0000 0000 0200 0001
0000020 0000 0000 0000 0200 0001 3b00 0000 0000
^[OQ0000030 0200 0001 0000 0000 0000 0200 0001 3b00
^[OQ0000040 0000 0000 0200 0001 0000 0000 0000 0200
^[OQ0000050 0001 3b00 0000 0000 0200 0001 0000 0000
^[OQ0000060 0000 0200 0001 3b00 0000 0000 0200 0001
0000070 0000 0000 0000 0200 0001 3b00 0000 0000
^[OQ0000080 0200 0001 0000 0000 0000 0200 0001 3b00
^[OQ0000090 0000 0000 0200 0001 0000 0000 0000 0200
^[OQ00000a0 0001 3b00 0000 0000 0200 0001 0000 0000
00000b0 0000 0200 0001 0000 0000 0000 0000 0101
00000c0 0000 0000 0000 0000 0101 0600 0000 0000
^C

Atualização 4

Como solicitado pelo @dirkt, aqui estão as informações do descritor do relatório (não consegui executar a linha de acordo com o comentário, aqui está o despejo completo; observe também que agora é hidraw2 , pois eu tive que substituir o teclado):

> sudo ./hid-desc /dev/hidraw2
Report Descriptor Size: 171
Report Descriptor:
05 01 09 06 a1 01 85 01 05 07 15 00 25 01 19 e0 29 e7 75 01 95 08 81 02 95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 03 95 08 75 01 15 00 25 01 06 00 ff 09 03 81 03 95 06 75 08 15 00 25 65 05 07 19 00 29 65 81 00 95 01 75 01 15 00 25 01 05 0c 09 b8 81 02 95 01 75 01 06 00 ff 09 03 81 02 95 01 75 06 81 03 06 02 ff 09 55 85 55 15 00 26 ff 00 75 08 95 40 b1 a2 c0 06 00 ff 09 14 a1 01 85 90 05 84 75 01 95 03 15 00 25 01 09 61 05 85 09 44 09 46 81 02 95 05 81 01 75 08 95 01 15 00 26 ff 00 09 65 81 02 c0 00 

Raw Name: Magic Keyboard
Raw Phys: 00:c2:c6:f7:eb:57
Raw Info:
    bustype: 5 (Bluetooth)
    vendor: 0x004c
    product: 0x0267
    
por orange 01.01.2017 / 06:07

2 respostas

2

Resposta parcial : Entendendo a infraestrutura da HID e os dados brutos da HID

(Disclaimer: Eu só fiz tudo isso para USB, mas suponho que será aplicado da mesma forma ou de forma semelhante ao Bluetooth).

Os dispositivos HID podem enviar e receber relatórios em um formato bem definido. O formato para um dispositivo em particular é dado pelo descritor HID , que para USB é muito semelhante aos outros descritores USB (por exemplo, lsusb pode listá-los se eles não estiverem vinculados). Detalhes (para USB) podem ser encontrados na Definição de classe de dispositivos para dispositivos de interface humana (HID) Documento PDF .

A documentação do kernel para HID pode ser encontrada em Documentation/hid . Como explica hiddev.txt , o fluxo de dados para um evento é assim:

 usb.c --> hid-core.c --> hid-input.c --> input-subsystem

Em drivers/hid/hid-input.c , em particular na rotina hidinput_configure_usage , um relatório é analisado de acordo com o descritor HID.

Então, se você não consegue ver a chave Fn , é aí que as coisas dão errado.

A saída vista em hidraw0 parece suspeitamente como se houvesse vários tipos de relatórios com IDs diferentes (esse relatório tem o ID 1, os relatórios normais do teclado têm o ID 0).

Mas para ter certeza, precisamos do (s) descritor (es) HID. Os descritores HID estão disponíveis por meio de um ioctl no dispositivo hidraw . Você pode usar, por exemplo, https://github.com/DIGImend/usbhid-dump para obter o descritor (somente USB) e https://github.com/DIGImend/hidrd para analisá-lo. Há também o arquivo /samples/hidraw/hid-example.c na fonte do kernel que mostra como obter o descritor HID via ioctl; Ele pode ser facilmente modificado para produzir um dump hexadecimal similar a usbhid-dump . Você terá que usar isso para Bluetooth, então eu coloquei em um pastebin . Compile com make .

(Se você não está acostumado a compilar projetos externos: Faça o download do arquivo zip para ambos, descompacte cada um em um diretório vazio, ./bootstrap , ./configure , make . Agora você pode usar os binários diretamente, adicioná-los $PATH , etc.)

Agora você pode analisar o descritor usando

sudo ./hid-desc /dev/hidraw0 | tail -n+3 | head -1 | hidrd-convert -ihex -ospec

Além de fornecer esta saída (ou o hexdump, se alguma coisa não funcionar), por favor, teste o que acontece em hidraw se você pressionar o Fn em combinação com várias outras chaves (alfabético , Setas; flechas). Também teste o que acontece para pressionamentos de tecla normais.

Não tenho certeza sobre a melhor maneira de proceder se não for possível fazer o kernel reconhecer os relatórios especiais. Talvez a maneira mais simples seja escrever um programa em C que analise eventos de hidraw e produza eventos de entrada adicionais, da mesma forma que input-create .

Atualizar : o descritor HID contém um 00 extra no final. Se você remover isso, ele será analisado em

Usage Page (Desktop),                           ; Generic desktop controls (01h)
Usage (Keyboard),                               ; Keyboard (06h, application collection)
Collection (Application),
    Report ID (1),                      ; +00 report id
    Usage Page (Keyboard),                      ; Keyboard/keypad (07h)
    Logical Minimum (0),
    Logical Maximum (1),
    Usage Minimum (KB Leftcontrol),             ; Keyboard left control (E0h, dynamic value)
    Usage Maximum (KB Right GUI),               ; Keyboard right GUI (E7h, dynamic value)
    Report Size (1),
    Report Count (8),
    Input (Variable),                   ; +01 modifier
    Report Count (5),
    Report Size (1),
    Usage Page (LED),                           ; LEDs (08h)
    Usage Minimum (01h),
    Usage Maximum (05h),
    Output (Variable),
    Report Count (1),
    Report Size (3),
    Output (Constant, Variable),
    Report Count (8),
    Report Size (1),
    Logical Minimum (0),
    Logical Maximum (1),
    Usage Page (FF00h),                         ; FF00h, vendor-defined
    Usage (03h),
    Input (Constant, Variable),         ; +02 vendor
    Report Count (6),
    Report Size (8),
    Logical Minimum (0),
    Logical Maximum (101),
    Usage Page (Keyboard),                      ; Keyboard/keypad (07h)
    Usage Minimum (None),                       ; No event (00h, selector)
    Usage Maximum (KB Application),             ; Keyboard Application (65h, selector)
    Input,                              ; +03 6 keysym bytes
    Report Count (1),
    Report Size (1),
    Logical Minimum (0),
    Logical Maximum (1),
    Usage Page (Consumer),                      ; Consumer (0Ch)
    Usage (Eject),                              ; Eject (B8h, one-shot control)
    Input (Variable),                   : +09.0
    Report Count (1),
    Report Size (1),
    Usage Page (FF00h),                         ; FF00h, vendor-defined
    Usage (03h),
    Input (Variable),                   ; +09.1
    Report Count (1),
    Report Size (6),
    Input (Constant, Variable),         : +09.2-7
    Usage Page (FF02h),                         ; FF02h, vendor-defined
    Usage (55h),
    Report ID (85),
    Logical Minimum (0),
    Logical Maximum (255),
    Report Size (8),
    Report Count (64),
    Feature (Variable, No Preferred, Volatile),
End Collection,
Usage Page (FF00h),                             ; FF00h, vendor-defined
Usage (14h),
Collection (Application),
    Report ID (144),
    Usage Page (Power Device),                  ; Power device (84h, power page)
    Report Size (1),
    Report Count (3),
    Logical Minimum (0),
    Logical Maximum (1),
    Usage (61h),
    Usage Page (Power Batsys),                  ; Power battery system (85h, power page)
    Usage (44h),
    Usage (46h),
    Input (Variable),
    Report Count (5),
    Input (Constant),
    Report Size (8),
    Report Count (1),
    Logical Minimum (0),
    Logical Maximum (255),
    Usage (65h),
    Input (Variable),
End Collection

Há um relatório de evento de entrada com o ID hex 01 , um relatório de status da bateria com ID hex 90 , uma saída para definir os LEDs normalmente e um controle de recurso específico do fornecedor.

Marquei os bytes para o relatório de eventos de entrada. Há vários campos definidos pelo fornecedor onde não sabemos o que eles fazem e temos que adivinhar.

O relatório de eventos de entrada consiste em 10 bytes e seus exemplos são decodificados da seguinte forma:

ID MM VA K1 K2 K3 K4 K5 K6 VB

01 00 00 00 00 00 00 00 00 02  ; press? Fn 
01 00 00 00 00 00 00 00 00 00  ; release? Fn

01 00 00 3b 00 00 00 00 00 00  ; press F2
01 00 00 00 00 00 00 00 00 00  ; release

01 00 00 00 00 00 00 00 00 00  ;
01 00 00 00 00 00 00 00 00 02  ; press Fn?
01 00 00 3b 00 00 00 00 00 02  ; press F2
01 00 00 00 00 00 00 00 00 02  ; release F2 (but not Fn?)

ID é o relatório. MM são os bits modificadores padrão 8, que não têm espaço para a chave Fn . K1 to K6 são até 6 teclas pressionadas simultaneamente. VA e VB são específicos do fornecedor. Assumindo que você segurou Fn e apenas pressionou e liberou F2 no último exemplo, meu palpite é que o bit 1 em VB representa o modificador para Fn (ou pelo menos algo relacionado a isso).

Use hexdump -e '10/1 "%02X ""\n"' para obter 9 bytes de saída por linha e teste essa hipótese combinando Fn com várias chaves, incluindo aquelas que você deseja redefinir no final.

Atualização : Para referência futura e completa, embora eu suponha que não seja mais relevante para este caso específico: é possível injetar eventos HID usando o UHID, veja Documentation/hid/uhid.txt e samples/uhid/uhid-example.c no kernel .

    
por 02.01.2017 / 17:20
2

Com a ajuda das dicas acima, foi possível criar um patch que faz a tecla Fn funcionar quando o Apple Magic Keyboard é conectado via bluetooth.

Parte do problema foi que o Magic Keyboard aparece com o ID do fornecedor 0x004c (ID do fornecedor de bluetooth para a Apple) e o hid-apple só procura 0x05ac (ID do fornecedor da Apple USB) para que o módulo gen-hid seja usado em vez de hid -apple.

O segundo problema foi em apple_input_mapping , que originalmente vem do código em hidinput_configure_usage de acordo com o git log.

O patch está publicado aqui: link

    
por 04.09.2017 / 22:23