2

編集

奇妙なことに、私はこの問題を回避しましたが、それでも私を悩ませています。私はこれを回避するために、長すぎる書き込みを送信し、ゼロを埋めました。コードは機能しますが、数百の不要なバイトが送信されます。具体的には、7 または 19 バイトのパケットではなく、正確に 992 バイトのパケットを送信する必要があります。しかし、私の疑問は依然として残っています。なぜ、7 バイトまたは 19 バイトの書き込みを行うことができないのに、Logitech コードができるのでしょうか。


渡されたデータの長さに応じて、特定のコード ブロックが失敗または成功するという問題が発生しています。これは私には意味がありません。私は明らかに何か間違ったことをしていますが、何を言うことはできません。

USB デバイス (2 つの Logitech G シリーズ キーボードの 1 つ) にバイト ストリームを書き込む、次のコード ブロックを使用しようとしている 3 つのケースがあります。

Friend Function WriteData(ByVal Keyboard As GSeriesKeyboard, ByVal Data() As Byte) As Integer
   Dim BytesWritten As Integer = Data.Length
   Dim Success As Boolean = Win32.WriteFile(Keyboard.ExternalIOHandle, Data, Data.Length, BytesWritten, Nothing)
   Dim ErrorCode As Integer = GetLastError()
   Return ErrorCode
End Function

<DllImport("kernel32.dll", SetlastError:=True)> Friend Shared Function WriteFile( _
    ByVal File As SafeFileHandle, _
    ByVal Buffer() As Byte, _
    ByVal NumberOfBytesToWrite As Integer, _
    ByRef NumberOfBytesWritten As Integer, _
    ByRef Overlapped As System.Threading.NativeOverlapped) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

最初のケースでは、992 バイトのストリームを渡し、書き込みが正常に完了しました。2 番目と 3 番目のケースでは、7 バイトまたは 19 バイトを書き込んでおり、WriteFile は 7 バイトのエラー ERROR_INVALID_USER_BUFFER または 19 バイトの ERROR_INVALID_PARAMETER を生成します。読み取りと書き込みのためにハンドルを開きましたが、重複していません。

USBTrace を使用すると、デフォルトの Logitech プログラムは 3 つのケースすべてを問題なく書き込めますが、私のコードでは 992 バイトのケースしか書き込めません。この動作は、コードを x86 としてコンパイルしても x64 としてコンパイルしても同じです。

ハンドルを開くために使用しているコードは次のとおりです。

    Friend Function OpenInterface(ByVal KeyboardPath As String) As SafeFileHandle

        Dim SecurityData As New SECURITY_ATTRIBUTES()
        Dim security As New DirectorySecurity()
        Dim DescriptorBinary As Byte() = security.GetSecurityDescriptorBinaryForm()
        Dim SecurityDescriptorPtr As IntPtr = Marshal.AllocHGlobal(DescriptorBinary.Length)

        SecurityData.nLength = Marshal.SizeOf(SecurityData)
        Marshal.Copy(DescriptorBinary, 0, SecurityDescriptorPtr, DescriptorBinary.Length)
        SecurityData.lpSecurityDescriptor = SecurityDescriptorPtr

        Dim Handle As SafeFileHandle = Win32.CreateFile(KeyboardPath, GENERIC_READ Or GENERIC_WRITE, _
                                                        FILE_SHARE_READ Or FILE_SHARE_WRITE, SecurityData, _
                                                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)

        If Handle.IsInvalid Then
            Dim ErrorInfo As New ComponentModel.Win32Exception()
            Debug.Print("Failed to get device IO handle: " & ErrorInfo.Message)
        End If

        Return Handle
    End Function

    Friend Overridable Function BitmapToLcdFormat(ByVal SourceBitmap As Bitmap) As Byte()
        'Base class is for the generic B&W 160x43 LCD.  Override for G19 if I ever get my hands on one
        Dim Data As Byte() = New Byte(991) {}
        ' USBTrace says 992 bytes
        Dim Image(640 * 48) As Byte 'Temp array for image conversion.  Adds additional 5 lines of unused pixels to avoid an out-of-bounds error
        Dim BitmapData As BitmapData = SourceBitmap.LockBits(New Rectangle(0, 0, 160, 43), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)
        Marshal.Copy(BitmapData.Scan0, Image, 0, (640 * 43))

        Data(0) = &H3 'Set-LCD
        Dim output As Integer = 32 'First byte of image data starts at byte 32; 960 bytes of image data
        Dim ImageOffset As Integer = 0
        For Row As Integer = 0 To 5
            For Column As Integer = 0 To (SourceBitmap.Width << 2) - 1 Step 4

                Dim r As Integer = _
                ((Image(ImageOffset + Column + BitmapData.Stride * 0) And &H80) >> 7) Or _
                ((Image(ImageOffset + Column + BitmapData.Stride * 1) And &H80) >> 6) Or _
                ((Image(ImageOffset + Column + BitmapData.Stride * 2) And &H80) >> 5) Or _
                ((Image(ImageOffset + Column + BitmapData.Stride * 3) And &H80) >> 4) Or _
                ((Image(ImageOffset + Column + BitmapData.Stride * 4) And &H80) >> 3) Or _
                ((Image(ImageOffset + Column + BitmapData.Stride * 5) And &H80) >> 2) Or _
                ((Image(ImageOffset + Column + BitmapData.Stride * 6) And &H80) >> 1) Or _
                ((Image(ImageOffset + Column + BitmapData.Stride * 7) And &H80) >> 0)

                Data(output) = CByte(r)

                output += 1
            Next
            ImageOffset += BitmapData.Stride * 8
        Next
        SourceBitmap.UnlockBits(BitmapData)
        Return Data
    End Function

WriteData() を呼び出す正確なコード ブロックは次のとおりです。

(Logitech G15)
    HardwareInterface.WriteData(Me, New Byte() {2, 0, 0, 0, 0, 0, 0})

(Logitech G510)
    HardwareInterface.WriteData(Me, New Byte() {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})

(Both; the one that works)
    HardwareInterface.WriteData(Me, BitmapToLcdFormat(NewImage)) 'Build 992-byte LCD-format bitmap from source iumage

これらの特定のコマンドは、ボード上のマクロ (「G」) キーを別の文字コードに再マップするために使用されます。この場合、00 はキーを無効にします。G15/G19/G510 キーボードを使用している場合は、Logitech ゲームパネル ソフトウェアを無効にしてキーボードを再接続することで、この問題を確認できます。G3 はメモ帳の F3 (次を検索) のように機能しますが、ゲームパネル ソフトウェアを再起動すると機能しなくなります。

4

2 に答える 2

1

申し訳ありませんが、これは本当に有用な回答ではありません。あなたが見ているものはあなたの特定のシナリオに固有のものであると確信しており、このシナリオ全体を知りません。

しかし、私の意見であなたが見ているものの最も可能性の高い理由はこれです。あなたが書いているのは実際のファイルではありません(あなたが間違いなく知っているように)それはあなたのキーボードへの単なるインターフェースであり、ファイルとして表面化されています。このため、通常のファイルとはまったく異なる一連の動作が見られるのは当然のことです。ほとんどの場合、ファイルシステム内のファイルに書き込むことができます。キーボードを使用すると、それを機能させるために従わなければならないプロトコルが存在する可能性があります。

私がここで起こっていると思うのは、あなたが書き込もうとしているものが失敗し、正しい状態で書き込もうとしていないということです。あなたがそれらを書いているとき、何らかの理由でキーボードはそれらを期待していません。

USBTraceで問題なく受け入れられていることがわかります。これは、それらが適切に書き込まれる正しい状態があることを意味します。

私は、キーボードで行っている一連の対話を調べ、入力を処理するキーボードの機能に何が影響するかを考えて調査を開始します。

于 2011-06-09T06:25:25.833 に答える
1

偶数バイトを書き込んでみては?

于 2011-06-09T06:33:28.157 に答える