2

Bluetoothデバイスと通信するためにIOBluetoothCocoaフレームワークを使用しています。これまでのところ、デバイスとそのサービスを検出し、ペアリングし、接続するプロセス全体を理解してきました。実際のコマンドを送信したいのですが、問題が発生しています。以下は、私が使用しようとしているAVRCPプロファイルの仕様の図です。ここでPDFを表示できます。

画像に示されているように、5バイトの値を書き込む必要があると思います。

代替テキスト

これが私が今持っているデータを書き込む方法です:

- (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*)l2capChannel status:(IOReturn)error {
    NSLog(@"Open Complete");
    NSMutableData *playData = [[NSMutableData alloc] initWithCapacity:5];

    unsigned char ctype = 0x0;
    unsigned char subunit = 0x90;
    unsigned char opcode = 0x7C;
    unsigned char opid = 0x44;
    unsigned char opdata = 0x0;

    [playData appendBytes:&ctype length:8];
    [playData appendBytes:&subunit length:8];
    [playData appendBytes:&opcode length:8];
    [playData appendBytes:&opid length:8];
    [playData appendBytes:&opdata length:8];

    usleep(1000);

    [l2capChannel writeAsync:[playData mutableBytes] length:40 refcon:nil];
}

その関数が実行されると、デバイスは次の16進値0x400010で応答します。

  1. 私はこれに正しく近づいているかどうかさえわかりません!
  2. 画像の例に従って、送信する値は正しいですか?
  3. ここで学ぶための私の努力の助けをいただければ幸いです!
4

2 に答える 2

3

AV / Cフレームを頻繁に操作する場合は、構造体を作成するのではなく(部分バイトのパッキングにはあまり役立ちません)、AVCFrameこれらのフレームを簡単にセットアップできるクラスを作成する必要があります。 、sanityは指定された値をチェックし、デバッグの説明があり、すべての汚れた詳細を処理します。

コードは次のようになります。

AVCFrame *frame = [AVCFrame frameWithCommandType:AVCCommandTypePlay
                                     subunitType:mySubunitType
                                       subunitID:mySubunitID];
// You likely won't actually be writing to the L2CAPChannel. See below.
[l2capChannel writeAsync:[frame mutableBytes] length:[frame length] refcon:nil];

それは最高のインターフェースではありません。AV/Cデジタルインターフェイスコマンドセットの一般仕様をお読みください。

バイトパッキングに関する限り(そして最終的には発生する必要があります)、次のようなものを使用する必要があります。

// Returns |subunitType| shifted and masked appropriately for bit_oring
// with subunit ID to create an address octet.
inline UInt8
AVRCAddressSubunitType(UInt8 subunitType) {
   const UInt8 kLeastThreeBytes = 0x07;
   UInt8 shiftedType = (subunitType << 3) & ~kLeastThreeBytes;
   return shiftedType;
}

// Returns |subunitID| masked appropriately for bit_oring with subunit type
// to create an address octet.
inline UInt8
AVRCAddressSubunitID(UInt8 subunitID) {
   const UInt8 kLeastThreeBytes = 0x07;
   UInt8 maskedID = subunitID & kLeastThreeBytes;
   if (subunitID & ~kLeastThreeBytes) {
      NSLog(@"*** %s: subunit ID %#hhx > 0x07 cannot be represented "
            "in the 3 bits allotted. Truncating to %#hhx.",
            __PRETTY_FUNCTION__, subunitID, maskedID);
   }
   return maskedID;
}

- (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel *)l2capChannel
                          status:(IOReturn)error {
  /* might be worth looking at the error... */
  NSLog(@"%s: open complete - "
        "error: (system: %#x; subsystem: %#x; code: %#x)",
         __PRETTY_FUNCTION__,
         err_get_system(error), err_get_sub(error), err_get_code(error));

  /* to send, first pack your data into byte-sized variables */
  // some variables...
  // address byte layout is [3:7] = 9 = PANEL; [0:2] = 0 = subunit ID
  UInt8 address = (AVRCAddressSubunitType(0x09) | AVRCAddressSubunitID(0x00));
  // some more variables...

  /* create a mutable data and append the bytes in sequence */
  // some appending...
  [playData appendBytes:&address length:sizeof(address)];
  // more appending...

  /* finally, send all the bytes */
  [l2capChannel writeAsync:[playData mutableBytes]
                    length:[playData length]
                    refcon:NULL];
}

の詳細についてはIOWhatever、広範なIOKitドキュメントを参照してください。少なくとも10.5では、ドキュメントセット内の(プログラミングガイドではなく)リファレンスドキュメントはやや厄介だったので、ヘッダー自体をよく見ることができます。

これまでに見たよりも多くのドキュメントを参照する必要があります。ダイアグラムを含めたAV/Cコマンドフレームは、実際にはAVCTPフレームのペイロード([コマンド/応答メッセージ情報]フィールドに表示されます)であり、これは実際にL2CAPトランスポートを介して送信する必要があります。AVCTP仕様は、「付録A、AVCTP上位インターフェース」の基本的なAPIをスケッチしています。

AV / Cコマンドフレームを送信するには、AVCTPライブラリを見つけるか自分で作成する必要があります。AVCTPライブラリでL2CAPチャネルをラップして、実際にAVCTPライブラリを介してコマンドフレームを送信し、そこからコマンドフレームを受信できるようにする必要があります。幸運を!ハードウェアとのインターフェースはとても楽しいものであり、多くのことを学ぶことができます。

于 2009-09-08T04:03:26.833 に答える
1

これは、バイトの配列を入力するだけの非常に多くの作業です。また、-appendBytes:length:メッセージのそれぞれで8バイトをplayDataに追加しようとしています。

このような状況では、BTコマンドフレームの構造体を宣言するだけです。NSDataは、ここではあまり提供していません。

于 2009-09-06T20:42:28.027 に答える