2

USBスティックのurb情報を取得しようとしています。そして次のように書いています。

#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <usb.h>
/* #include <stropts.h> */
/* #include <inttypes.h> */
#include <linux/usbdevice_fs.h>
/* #include <asm/byteorder.h> */
/* #include <linux/usb/ch9.h> */
#define USBDEVFS_REAPURB           _IOW('U', 12, void *)
int main(int argc, char *argv[])
{ 
  int fd;
  int result;
  int i;
  struct usbdevfs_urb * receive;
  receive = malloc(sizeof (struct usbdevfs_urb));

  bzero(receive, sizeof (struct usbdevfs_urb));

  char file[30];
  strncpy (file, argv[1], 30);

  if ((fd = open(file, O_RDWR)) < 0)
    {
      printf("failed to open device: %s, \n error: %s \n", file, strerror(errno));
    }
  else 
    {
      printf ("Open successed: Device: %s\n", file);
      for (i = 0; i < 1000; ++i)
        {
          printf ("polling...\n");
          result = ioctl(fd, USBDEVFS_REAPURB, receive);
            if (result < 0)
              {
                printf ("Error!  : ioctl returned : %d\n errno =%s\n", result, strerror(errno));
                break;
              }
          printf ("The %d th time ok.\n", i + 1);
          usleep(2000);
        }
    }
  close(fd);
  return 0;
}

コンパイルできます。しかし、実行すると、無効な引数と表示されました。それで、私の何が問題なのですか?

4

2 に答える 2

5

同様の問題が発生しました-ここに私のメモがあります...コメントでこれまでに指摘された問題に加えて、OPコードの主な問題は次のとおりだと思います。

  1. URB を単に "刈り取る" ことはできません。最初に(読み取りまたは書き込み)URBを「送信」する必要があり、次にそれを「取得」します
  2. コマンド ライン引数 ( ) からパスとして取得しopenた文字列だけでは、URB に有効なファイル記述子を取得できません。fileargv[1]ioctl

1については、おそらくcを参照してください-デバイスからホストへのユーザーモードUSBアイソクロナス転送

また、この構造を埋めたら、次のように呼び出す必要があると考えるのは正しいです。
int retSubmit = ioctl( fd, USBDEVFS_SUBMITURB, &usbRequest );
送信したら、リクエストが完了するまで待つことができます
USBDEVFS_REAPURBNDELAY

または「[Linux-usb-users] usbfs urb reap problem.」- マーク

URB を送信するために使用するルーチンとその呼び出しは次のとおりです
。 ... URB の送信は正常に
機能します。これが私がそれを刈り取ろうとする方法です:
...

linux.usb.devel - Re: usbdevfs に関する質問 (およびその他...) - msg#00167

はい、BULK タイプの usbdevfs_urb を割り込みエンドポイントに送信します。1 パケットのデータを取得します。キューに入る複数のものを送信できます。そして、「reap」は死神とは異なり、REAd Pointer であると推測しています (ただし、そうかもしれませんが...:)

仮想 USB アナライザー - チュートリアルに記載されているように、「送信」と「取得」は「送信」と「完了」と同等であると思います (ただし、100% とは言えません)

2.に関しては、デバイスの種類によって異なります。たとえば、FT232 USB シリアル チップを搭載した Arduino Duemillanove を Linux PC に接続すると、カーネル ドライバーが自動的に読み込まれ、ftdi_sio次にカーネル ドライバーが読み込まれusbserial、ファイル (デバイス ノード) が作成されます/dev/ttyUSB0。したがって、Linux はこのファイルをせいぜい普通のシリアル ポートとして認識します。必ずしも URB 要求に関連するものではありません (USB フラッシュ サムドライブにも同様のことが当てはまると思います)。の引数でOPコードを呼び出そうとすると、OPと同じエラーが発生しました/dev/ttyUSB0

例を追跡するのがちょっと難しいので、このファイル記述子を取得するのはやや難しいです:

「Re: USBDEVFS で USB デバイスにアクセスする」 - MARC

2006 年 5 月 5 日金曜日の 04:45:30PM -0400 に、Danny Budik は次
のように書いています。/dev/bus/usb ファイルから読み込もう
としたところ、bind - address already in use エラーが発生しました。

これを行う方法の良い例として、libusb がどのように実装されているかを見てください。
「lsusb」のソース コードもここで役に立ちます。

Linux カーネルのドキュメント/usb/proc_usb_info.txt


: 「devfs」との混乱を避けるために、ファイルシステムの名前が「usbdevfs」から「usbfs」に変更されました。
古い「usbdevfs」名への参照がまだ表示される 場合があります。

私は基本的に[Discuss-gnuradio] New implementation for fusb_linux without allocs/freesのコードから始めて、Arduino Duemillanove で動作するように OP コードを変更しようとしました。libusb-0.1問題は、ヘッダーと関数の名前がいくつか異なる古いコードを使用していることです。たとえばlibusb-0.1libusb/usbi.hがあり、新しいものlibusb-1.0にはlibusb/libusbi.hがあります。基本的に、libusb関数を使用して適切なファイル記述子を取得できます。

変更された OP コードは以下のとおりtestu.cです。Ubuntu Natty でテストしました。最初に、ドライバーをフックする Arduino Duemillanove を接続しftdi_sioます (これは、ターミナルで で確認できますtail -f /var/log/syslog)。そのため、まず、自動フックされたドライバーを削除します (libusbデバイスと通信するために必要ではなく、干渉する可能性があります。削除後、/dev/ttyUSB0ファイルはもう存在しないことに注意してください)。

sudo modprobe -r ftdi_sio   # this also removes usbserial 
lsmod | grep ftdi           # make sure ftdi_sio isn't listed by lsmod

次に、USB ベンダー/製品 ID を使用して、デバイスに接続しlibusbます。それを見つけるには、次を使用しますlsusb

$ lsusb | grep FT
Bus 002 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC

VID:PID0403:6001はハードコードされていtestu.cます。その後、ビルドして実行できます。testuプログラムは root として ( 経由でsudo)実行する必要があることに注意してください。そうlibusbしないと、デバイスと通信できません。

$ gcc -o testu -Wall -g testu.c `pkg-config --libs --cflags libusb-1.0`
testu.c:23:1: warning: ‘fd_from_usb_dev_handle’ defined but not used

$ sudo ./testu
First
Second 0x8B4B4F0
Open successed: Device: 0403:6001 6
polling...
The 1 th time ok.
polling...
The 2 th time ok.
polling...
The 3 th time ok.
polling...
The 4 th time ok.
polling...
The 5 th time ok.
polling...
The 6 th time ok.
polling...
The 7 th time ok.
polling...
The 8 th time ok.
polling...
The 9 th time ok.
polling...
The 10 th time ok.

コードは (エンドポイント 0x02 で) 書き込み要求を送信し、それを取得します。Arduino で RX LED が点滅しているのがわかります。つまり、予想どおり、一部のデータがそこに到達することを意味します。ただし、それ以上のことは起こりません-したがって、コードが「USBのurb情報を取得する」部分に応答するかどう:)かはわかりません. libusb なしで同じことを行うには、おそらくソースをさらに深く掘り下げる必要があります)。ioctllibusblibusb

これは次のとおりですtestu.c(注、libusb-devコンパイルできるようにパッケージをインストールしてください):

#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <usb.h>
/* #include <stropts.h> */
/* #include <inttypes.h> */
#include <linux/usbdevice_fs.h>
/* #include <asm/byteorder.h> */
/* #include <linux/usb/ch9.h> */
//~ #define USBDEVFS_REAPURB           _IOW('U', 12, void *)

#include <libusb.h>

struct libusb_device_handle *d_udh = NULL;


// [http://www.mail-archive.com/discuss-gnuradio@gnu.org/msg17549.html [Discuss-gnuradio] New implementation for fusb_linux without allocs/frees]
static int
fd_from_usb_dev_handle (libusb_device_handle *udh) //(usb_dev_handle *udh)
{
  return *((int *) udh);
}

//~ ./libusb/os/linux_usbfs.c
struct linux_device_handle_priv {
  int fd;
};

//~ ./libusb/libusbi.h
#define usbi_mutex_t                    pthread_mutex_t
struct list_head {
        struct list_head *prev, *next;
};
struct libusb_device_handle {
        /* lock protects claimed_interfaces */
        usbi_mutex_t lock;
        unsigned long claimed_interfaces;

        struct list_head list;
        struct libusb_device *dev;
        unsigned char os_priv[0];
};

//~ ./libusb/os/linux_usbfs.c
struct linux_device_handle_priv* _device_handle_priv(
        struct libusb_device_handle *handle)
{
  struct linux_device_handle_priv* out;
  out =  (struct linux_device_handle_priv *) handle->os_priv;
  return out;
};



int main(int argc, char *argv[])
{
  int fd;
  int result;
  int i;
  struct usbdevfs_urb * receive;
  struct usbdevfs_urb * send;
  struct linux_device_handle_priv *hpriv;
  send = malloc(sizeof (struct usbdevfs_urb));
  memset(send, 0, sizeof (*send));
  send->buffer_length = 10;
  send->buffer = malloc(sizeof(unsigned char)*10);
  send->type = USBDEVFS_URB_TYPE_BULK;
  send->endpoint = 0x02;
  send->signr = 0;


  receive = malloc(sizeof (struct usbdevfs_urb));

  bzero(receive, sizeof (struct usbdevfs_urb));

  char file[30];
  if (argv[1]) strncpy (file, argv[1], 30);

  printf ("First\n");
  result = libusb_init(NULL);
  if (result < 0)
  {
    printf("failed to initialise libusb:\n");
  }
  d_udh = libusb_open_device_with_vid_pid(NULL, 0x0403, 0x6001);
  hpriv = _device_handle_priv(d_udh);
  printf ("Second 0x%X\n", (unsigned int)d_udh);
  result = d_udh ? 0 : -EIO;
  //~ if ((fd = open(file, O_RDWR)) < 0)
  if (result < 0)
    {
      printf("failed to open device: %s, \n error: %s \n", "0403:6001", strerror(errno)); //file
    }
  else
    {
      //~ fd = fd_from_usb_dev_handle(d_udh); // doesn't work
      fd = _device_handle_priv(d_udh)->fd;
      printf ("Open successed: Device: %s %d\n", "0403:6001", fd ); // file);
      for (i = 0; i < 10; ++i)
        {
          result = ioctl (fd, USBDEVFS_SUBMITURB, send);
            if (result < 0)
              {
                printf ("Error! USBDEVFS_SUBMITURB : ioctl returned : %d\n errno =%s\n", result, strerror(errno));
                break;
              }
          printf ("polling...\n");
          result = ioctl(fd, USBDEVFS_REAPURB, receive);
            if (result < 0)
              {
                printf ("Error! USBDEVFS_REAPURB : ioctl returned : %d\n errno =%s\n", result, strerror(errno));
                break;
              }
          printf ("The %d th time ok.\n", i + 1);
          usleep(2000);
        }
    }
  close(fd);
  return 0;
}

さて、これが誰かに役立つことを願っています、
乾杯!

于 2013-03-21T01:08:07.077 に答える
0

USB 要求がカーネル ドライバーに干渉しないことを注意深く確認することで、カーネル ドライバーを切り離さずにそのような要求を実行できます。しかし、libusb ワークフローは、デバイスを要求することを強制し、その結果、その非 USB サブカーネル ドライバーを切り離します。そのため、 usb ioctlを自分で実行する必要があります。

以下は、ftdi_sio カーネル ドライバーをデタッチせずに、USB 制御メッセージを FTDI USB デバイスに送信して、その RX および TX FIFO をフラッシュする例です。

于 2016-06-01T11:19:20.600 に答える