usb7-再谈usb数据采集仪

上文将设备侧的端点1作为中断输入端点,来传输数据。
也可以以将端点1定义成批量端点,来传输数据。分为两个部分,设备侧和主机侧。端点的类型对设备侧编程几乎没有影响,主要是对主机侧的影响,体现在后面再说...。
设备侧只改一个地方,是端点描述符的属性,就是设备要告诉主机说我是批量端点请您做好准备,如下
     //struct HID_DESCRIPTOR Hid_Desc;
      {
       0x07,                // bLength
       0x05,                // bDescriptorType
       0x81,                // bEndpointAddress
       0x02,                // bmAttributes 02是批量端点,03中断端点
       SWAP16( EP1_PACKET_SIZE ),  // MaxPacketSize (LITTLE ENDIAN)
       EP_INTERVAL                   // bInterval  如果bmAttributes=02,则此项就没用了,因为主机驱动中根本没用到这个东东
    }, //end of Endpoint1Desc

主机侧要改的地方也没几个,将操作中断输入端点的洞洞改成批量端点的就行。
pipe = usb_rcvbulkpipe(dev, endpoint->bEndpointAddress); //申请批量管道
usb_fill_bulk_urb //初始化urb时使用批量管道
 usb_endpoint_is_bulk_in //判断是否是批量输入端点

/*
 *  Copyright (c) 1999-2001 Vojtech Pavlik
 *
 *  USB HIDBP test support
 */

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Should you need to contact me, the author, you can do so either by
 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>
#include <linux/miscdevice.h> 
#include <asm/uaccess.h>  


/*
 * Version Information
 */
#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "song"
#define DRIVER_DESC "usb test"
#define DRIVER_LICENSE "GPL"

#define DEVICE_NAME "song_data_dev"

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);

#define DEBUG
#ifdef DEBUG  
#define DBG(...) printk(" DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); printk(__VA_ARGS__)  
#else  
#define DBG(...)  
#endif  

struct usb_test {
        char name[128];
        char phys[64];
        struct usb_device *usbdev;
        struct miscdevice  *dev;
        struct urb *irq;

        unsigned char *data;
        dma_addr_t data_dma;
} ;
static struct usb_test  *test;

union flt_chr  
{  
  //float flt;  
  unsigned int flt;  
  unsigned char chr[4];  
}fltchr; 

static struct timer_list report_timer; 
static unsigned short t_interval = HZ;//delay 1 s  

ssize_t read_test(struct file *filp, char __user *buf, size_t count,  loff_t *f_pos)  
{  
    int ret;
    if (count == 0) return count; 
    DBG("to copy to user %d bytes\n", count);

    ret = copy_to_user(buf, test->data,  count);//kbuf->buf,if success,ret=0  
    DBG("copied %d bytes  \n", count-ret);
    
     return count-ret ;  //return the bytes quantity have copied
} 
 
static struct file_operations dev_fops = {  
//  .owner  =   THIS_MODULE,  
//  .open   =   open_test,  
    .read   =   read_test,  
//  .write  =   write_test,  
 // .release=   release_test,  
};  

static struct miscdevice misc = {  
    .minor = MISC_DYNAMIC_MINOR,  
    .name = DEVICE_NAME,  
    .fops = &dev_fops,  
};  

static void handle_timer(unsigned long data)  
{  /*    int i;
    for(i=0;i<8;i++){
    fltchr.chr[0]=test->data[i*4];
    fltchr.chr[1]=test->data[i*4+1];
    fltchr.chr[2]=test->data[i*4+2];
    fltchr.chr[3]=test->data[i*4+3];
    DBG("%d\n",fltchr.flt);
    }
    DBG("ok\n");
       report_timer.expires = jiffies + t_interval;  
       add_timer(&report_timer);  */
}  



static void usb_test_irq(struct urb *urb)
{
    struct usb_test *test = urb->context;

    if (usb_submit_urb(test->irq, GFP_KERNEL))
        {
        DBG("err\n");        
        }

}

static int test_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
    struct usb_device *dev = interface_to_usbdev(intf);
    struct usb_host_interface *interface;
    struct usb_endpoint_descriptor *endpoint;

    struct miscdevice *miscdev;
    int pipe, maxp;
    int error = -ENOMEM;

    DBG("ok\n");
    interface = intf->cur_altsetting;

    if (interface->desc.bNumEndpoints != 2)
        {
        DBG("err\n");
        return -ENODEV;
        }
    DBG("ok\n");

    endpoint = &interface->endpoint[0].desc;

    if(!usb_endpoint_is_bulk_in(endpoint))
        {
        DBG("err !usb_endpoint_is_bulk_in\n");
        return -ENODEV;
        }

    /*
    if (!usb_endpoint_is_bulk_in(endpoint))
        {
        DBG("err\n");
        return -ENODEV;
        }
    */

    DBG("ok usb_endpoint_is_bulk_in\n");
    
    //pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
    pipe = usb_rcvbulkpipe(dev, endpoint->bEndpointAddress);
    maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
    DBG("maxp=%d\n",maxp);

    test = kzalloc(sizeof(struct usb_test), GFP_KERNEL);//test

    if (!test)
        goto fail1;
    miscdev = &misc;
    test->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &test->data_dma);//test->data
    if (!test->data)
        goto fail2;
    test->irq = usb_alloc_urb(0, GFP_KERNEL);//test->irq
    if (!test->irq)
        goto fail3;


    test->usbdev = dev;
    test->dev = miscdev;

    if (dev->manufacturer)
        strlcpy(test->name, dev->manufacturer, sizeof(test->name));
    if (dev->product) {
        if (dev->manufacturer)
            strlcat(test->name, " ", sizeof(test->name));
        strlcat(test->name, dev->product, sizeof(test->name));
    }

    /*usb_fill_int_urb(test->irq, dev, pipe, test->data,
             (maxp > 8? maxp : 8 ),
            usb_test_irq, test, endpoint->bInterval);*/

    usb_fill_bulk_urb(test->irq,
            dev,
            pipe,
            test->data,
            maxp,
            usb_test_irq,
            test);

    test->irq->transfer_dma = test->data_dma;
    test->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

    misc_register(&misc);  
    //usb_set_intfdata(intf, test);
    DBG("ok\n");

    if (usb_submit_urb(test->irq, GFP_KERNEL))
        {
        DBG("err\n");        
        return -EIO;
        }
    DBG("ok\n");

    init_timer(&report_timer);  
        report_timer.expires = jiffies + t_interval;  
        report_timer.function = handle_timer;  
        add_timer(&report_timer);  
    DBG("ok\n");
    return 0;


fail3:    usb_free_urb(test->irq);    
fail2:    usb_buffer_free(dev, 8, test->data, test->data_dma);
fail1:    kfree(test);
    DBG("err\n");
    return error;
}

static void test_usb_disconnect(struct usb_interface *intf)
{    
    
    del_timer(&report_timer); 
    misc_deregister(&misc);  
    printk("disconnect\n");
}

static struct usb_device_id test_usb_id_table [] = {
    {USB_DEVICE(0x0606,0x0001) },    /* Terminating entry */
    {}
};

    MODULE_DEVICE_TABLE (usb, test_usb_id_table);

    static struct usb_driver test_usb_driver = {
    .name        = "test_song",
    .probe        = test_usb_probe,
    .disconnect    = test_usb_disconnect,
    .id_table    = test_usb_id_table,
    };

static int __init test_usb_init(void)
{
    int retval = usb_register(&test_usb_driver);
    if (retval == 0)
    DBG("usb_register success!\n");
    return retval;
}

static void __exit test_usb_exit(void)
{

    usb_deregister(&test_usb_driver);
    DBG("usb_deregister success!\n");    
}

module_init(test_usb_init);
module_exit(test_usb_exit);
执行结果如下:
[root@FriendlyARM plg]# usb 1-1.1: new full speed USB device using s3c2410-ohci and address 4
usb 1-1.1: New USB device found, idVendor=0606, idProduct=0001
usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1.1: Product: nRF24LU1 ADapter
usb 1-1.1: Manufacturer: Weisdigital
usb 1-1.1: SerialNumber: Ver1.0 N000
usb 1-1.1: configuration #1 chosen from 1 choice
 DBG(/opt/usb/test_usb.c, test_usb_probe(), 143): ok
 DBG(/opt/usb/test_usb.c, test_usb_probe(), 151): ok
 DBG(/opt/usb/test_usb.c, test_usb_probe(), 169): ok usb_endpoint_is_bulk_in //是批量端点
 DBG(/opt/usb/test_usb.c, test_usb_probe(), 174): maxp=32
 DBG(/opt/usb/test_usb.c, test_usb_probe(), 217): ok
 DBG(/opt/usb/test_usb.c, test_usb_probe(), 224): ok
 DBG(/opt/usb/test_usb.c, test_usb_probe(), 230): ok

[root@FriendlyARM plg]# 
[root@FriendlyARM plg]# ./read_app /dev/song_data_dev 
 DBG(read_app.c, main(), 26): press Ctrl-C to stop DBG(/opt/usb/test_usb.c, read_test(), 84): to copy to user 32 bytes
 DBG(/opt/usb/test_usb.c, read_test(), 87): copied 32 bytes  

 DBG(read_app.c, main(), 34): to read : 32 bytes 
 DBG(read_app.c, main(), 37): return : 32 bytes 
 DBG(read_app.c, main(), 44): 3436 mv
 DBG(read_app.c, main(), 44): 3436 mv
 DBG(read_app.c, main(), 44): 1725 mv
 DBG(read_app.c, main(), 44): 3436 mv
 DBG(read_app.c, main(), 44): 3436 mv
 DBG(read_app.c, main(), 44): 3440 mv
 DBG(read_app.c, main(), 44): 3436 mv
 DBG(read_app.c, main(), 44): 3436 mv
[root@FriendlyARM plg]# 

我觉得批量端点和中断端点的不同之处在于usb主控器驱动(or usbcore)对这两种端点类型的访问方式和大小控制---看到的不要全信,仅是个人笔记,若有错欢迎指正。
①对于中断端点,usb主控制器驱动会自动按照该端点描述符里的bInterval请求周期去发in令牌包请求数据而对批量端点则不会如此做,大概是由于中断端点一般用于hid设备,需要人机交互,实时性要求较高,而批量端点不是时刻都在传递数据,而是每次传输较多数据。这也导致了下面不同。
②对于中断端点,协议规定的可支持的最大容量远远小于批量端点。
③在具体驱动里面区别不大,访问哪种端点就申请哪种pipe就行,然后用这个pipe初始化urb再提交即可。
所以对于不需要实时传递数据的数据流就用批量端点实现。会减少主机linux的开销。




我要啦免费统计
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值