2016-06-18 27 views
2

USBフラッシュドライブ用に私自身のシンプルなUSBドライバを書き込もうとしているうちに、私はそのデバイスに書き込んだデータを読み込みませんでした。 私の最初の質問は次のとおりです。Linuxのドライバを使ってUSBストレージデバイスを読み書きする方法は?

デバイスの転送とストレージはどのように進行していますか? USER-から

  • 転送データをDMAバッファを割り当て

    • は、URB(USB要求ブロック)を作成
    • (詳細)は、私は、次の手順を実行する必要があります知っていますDMAバッファ

    • にスペースがデバイス

    私は任意のドキュメントを見つけることができませんでしたし、パイプを介してデータを送信しますデバイスがこのデータをどのように扱うかに関する情報。

    このようなドライバを作成することも可能ですか、特別なコマンドを送信するには、USBデバイスを逆アセンブルする必要がありますか?

    私が書いたコードは、次のようなもので、ldd3と "http://lxr.free-electrons.com/source/drivers/usb/usb-skeleton.c"のものです。重要な機能の短縮版のみを表示します。

    ドライバをカーネルにロードした後、私はデバイスに何もエラーなく書き込むことができますが、私が読むとEPIPEエラーが発生します。 Ldd3は、usb_clear_halt()がこの問題を解決できる可能性があると述べていますが、そうではありません。

    // This function is called when the device is plugged in 
    static int my_driver_probe(struct usb_interface* interface, const struct usb_device_id* id) 
    { 
        struct usb_skel* dev = NULL; 
        struct usb_device* udev = interface_to_usbdev(interface); 
        struct usb_host_interface* iface_desc; 
        struct usb_endpoint_descriptor* endpoint; 
        int retval = -ENODEV; 
        int i = 0; 
        size_t buffer_size; 
    
        dev = kzalloc(sizeof(struct usb_skel), GFP_KERNEL); 
    
        // Check vendor and product id 
        // … 
    
        dev->udev = udev; 
        dev->interface = interface; 
    
        // Set up the endpoint information 
        iface_desc = interface->cur_altsetting; 
        for(i=0; i < iface_desc->desc.bNumEndpoints; ++i) { 
         endpoint = &iface_desc->endpoint[i].desc; 
    
         if(!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { 
          buffer_size = endpoint->wMaxPacketSize; 
          dev->bulk_in_size = buffer_size; 
          dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; 
          dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); 
          if(!dev->bulk_in_buffer) { 
           printk("Could not allocate bulk_in_buffer\n"); 
           goto error; 
          } 
          dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); 
         } 
         if(!dev->bulk_out_endpointAddr && usb_endpoint_is_bulk_out(endpoint)) 
          dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; 
        } 
        // Check that the endpoints are set 
        // … 
    
        // Save our data pointer in this interface device 
        usb_set_intfdata(interface, dev); 
    
        // Register the device 
        retval = usb_register_dev(interface, &class_descr); 
        return retval; 
    } 
    
    // Is called when another program writes into /dev/my_usb_driver 
    static ssize_t my_driver_write(struct file* file, const char __user* user_buffer, size_t count, loff_t* offs) 
    { 
        struct usb_skel* dev = file->private_data; 
        struct urb* urb = NULL; 
        char* buf = NULL; 
        int retval = 0; 
        size_t writesize = min(count, (size_t)MAX_TRANSFER); 
    
        // Create a urb, and a buffer for it, and copy the data to the urb 
        urb = usb_alloc_urb(0, GFP_KERNEL); 
    
        // Creates a DMA buffer 
        buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma); 
    
        // The data that is passed to the driver should be copied into the DMA buffer 
        copy_from_user(buf, user_buffer, writesize; 
    
        // Initialize the urb proberly 
        usb_fill_bulk_urb(urb, dev->udev, 
            usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), 
            buf, writesize, (void*)my_write_bulk_callback, dev); 
    
        // Send the data out the bulk port 
        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 
    
        usb_submit_urb(urb, GFP_KERNEL); 
    
        return writesize; 
    } 
    
    // Is called when another program reads from /dev/my_usb_driver 
    static ssize_t my_driver_read(struct file *file, char* buffer, size_t count, loff_t* offs) 
    { 
        struct usb_skel* dev = file->private_data; 
        int retval = 0; 
    
        // Check that we have data to read 
        // … 
    
        usb_fill_bulk_urb(dev->bulk_in_urb, dev->udev, 
            usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), 
            dev->bulk_in_buffer, 
            min(dev->bulk_in_size, count), read_bulk_callback, dev); 
    
        retval = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL); 
    
        // If the read was succesful, copy the data to user space 
        copy_to_user(buffer, dev->bulk_in_buffer, count); 
    
        return retval; 
    } 
    
  • 答えて

    1

    USBは単なるトランスポート層です。記憶装置は、一般にSCSIプロトコルを実装する。ユーザー空間が送信したデータを読み書きするためのSCSIコマンドを作成します。次に、SCSIコマンド用のURBを作成し、USBデバイスに送信します。

    SCSIは巨大なプロトコルなので、USBデバイスドライバの開発を学ぶためには、USBからシリアルデバイスのような単純なデバイスを使用することをお勧めします。

    関連する問題