Template Information

Trang

USB Davicom dm9601 programming in LInux

Thứ Bảy, 4 tháng 6, 2011 / 21:56


/* AFTER PROBE.DEFINING OPEN FUNCTION.*/

#include<linux/init.h>
#include<linux/module.h>
#include <linux/kernel.h>
#include<linux/usb.h>
#include<linux/netdevice.h>
#include<linux/etherdevice.h>
#include<linux/delay.h>

#define USB_VENDOR_ID     0x0A46
#define USB_PRODUCT_ID     0x9601
#define MACADDR     0x0010
#define RESET       0x00
#define RX_ENABLE    0x05

#define READ_REQUSET     0x00
#define READ_REQUEST_TYPE 0xc0
#define READ_VALUE     0x0000
#define WRITE_REQUSET     0x01
#define WRITE_REQUEST_TYPE 0x40
#define WRITE_VALUE     0x0000
#define MAX_MTU 1536
MODULE_LICENSE("Dual BSD/GPL");

/* table of devices that work with this driver */
static struct usb_device_id table[]={
                    {USB_DEVICE(USB_VENDOR_ID,USB_PRODUCT_ID)},
                    {}
                     };
MODULE_DEVICE_TABLE (usb,table);

int usb_probe(struct usb_interface *interface,const struct usb_device_id *id);
void usb_disconnect(struct usb_interface *intf);
static int open_dev(struct net_device *net_dev);
static int transmit( struct sk_buff *skb, struct net_device *net_dev);
int close_dev(struct net_device *net_dev);
static void rx_callback( struct urb *urb );
static void tx_callback(struct urb *urb);
struct net_device_stats* get_stats(struct net_device *net_dev);

static struct usb_driver driver_structure = {
                                      
                        .name="dm_9601_driver",
                        .id_table=table,
                        .probe=usb_probe,
                        .disconnect=usb_disconnect,

                              };
struct usb_skel {
    struct usb_device *    udev;            /* the usb device for this device */
    struct usb_interface *    interface;
    struct net_device *     net_dev;
    struct net_device_stats    stats;
    struct urb tx_urb;
    struct urb rx_urb;
    unsigned char *        tx_buff;
    unsigned char *        rx_buff;
    unsigned char *        bulk_in_buffer;        /* the buffer to receive data */
    size_t            bulk_in_size;        /* the size of the receive buffer */
    __u8            bulk_in_endpointAddr;    /* the address of the bulk in endpoint */
    __u8            bulk_out_endpointAddr;    /* the address of the bulk out endpoint */
    __le16             buffer_size;   
    char *data;

 };


int usb_probe(struct usb_interface *interface,const struct usb_device_id *id)
{
   
      printk(KERN_NOTICE "prob called");
        struct net_device *net_dev=NULL;
    struct usb_skel *dev = NULL;
    struct usb_host_interface *iface_desc;
    struct usb_endpoint_descriptor *endpoint;
    size_t buffer_size;
    int i,x;
    int retval = -ENOMEM;
net_dev = alloc_etherdev(sizeof(struct usb_skel));
dev=netdev_priv(net_dev);
memset(dev,0, sizeof (struct usb_skel));


dev->net_dev=net_dev;
    printk("hai\n");
    usb_init_urb(&dev->tx_urb);
    usb_init_urb(&dev->rx_urb);
    net_dev->mtu=1536;
    net_dev->open=open_dev;
    net_dev->stop=&close_dev;
    net_dev->hard_start_xmit=transmit;
    net_dev->get_stats=get_stats;
    dev->udev = usb_get_dev(interface_to_usbdev(interface));
    dev->interface = interface;

    /* set up the endpoint information */
    dev->data=kmalloc(6,GFP_KERNEL);
    x=usb_control_msg(dev->udev,usb_rcvctrlpipe(dev->udev,0),0x00,0xc0,0x0000,                             MACADDR,dev->data,6,0);
    printk("mac address length is  %x bytes\n",x);
    memcpy(net_dev->name,"ravi_eth0",11);                //setting interface name
    memcpy(net_dev->dev_addr,dev->data,x);
        printk(KERN_NOTICE "name of device is %s",net_dev->name);   

   
    /* use only the first bulk-in and bulk-out endpoints */
    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 &&
            (endpoint->bEndpointAddress & USB_DIR_IN) &&
            ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
                    == USB_ENDPOINT_XFER_BULK)) {
            /* we found a bulk in endpoint */
        printk(KERN_NOTICE "\nfound bulk in end point");
            buffer_size = endpoint->wMaxPacketSize;
            dev->bulk_in_size = 1536;
            dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
            dev->bulk_in_buffer = usb_buffer_alloc(dev->udev,MAX_MTU,GFP_KERNEL,&dev->tx_urb.transfer_dma);
            if (!dev->bulk_in_buffer) {
                err("Could not allocate bulk_in_buffer");
                goto error;
            }
        }

        if (!dev->bulk_out_endpointAddr &&
            !(endpoint->bEndpointAddress & USB_DIR_IN) &&
            ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
                    == USB_ENDPOINT_XFER_BULK)) {
            /* we found a bulk out endpoint */
        printk(KERN_NOTICE "found bulk out end point");
            dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
        }
    }
    if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) {
        err("Could not find both bulk-in and bulk-out endpoints");
        goto error;
    }

    /* save our data pointer in this interface device */
    usb_set_intfdata(interface, dev);
    SET_MODULE_OWNER(net_dev);
    if(register_netdev(net_dev))
    {
        printk("\nRegistration of net device is  Failed");
        retval=-1;
    }

    printk(KERN_NOTICE " prob module succ called ");
    return 0;

error:
    printk(KERN_NOTICE "some error is occure in prob module");
    return retval;

 
}

//open start
static int open_dev(struct net_device *net_dev)
{
    printk(KERN_NOTICE "\nopen called");
//Reseting the device
    struct usb_skel *dev=netdev_priv(net_dev);
    int x,result;
        u8 register_value;
       x=usb_control_msg(dev->udev,usb_rcvctrlpipe(dev->udev,0),READ_REQUSET,READ_REQUEST_TYPE,READ_VALUE,                             RESET,&register_value,1,0);
    printk("Before Rst %x\n",register_value);
    register_value=0x01;
    x=usb_control_msg(dev->udev,usb_sndctrlpipe(dev->udev,0),WRITE_REQUSET,WRITE_REQUEST_TYPE,WRITE_VALUE,
                            RESET,&register_value,1,0);
    udelay(20);
    x=usb_control_msg(dev->udev,usb_rcvctrlpipe(dev->udev,0),READ_REQUSET,READ_REQUEST_TYPE,READ_VALUE,                             RESET,&register_value,1,0);
    printk("after Rst %x\n",register_value);

//recive enable
    x=usb_control_msg(dev->udev,usb_rcvctrlpipe(dev->udev,0),READ_REQUSET,READ_REQUEST_TYPE,READ_VALUE,                             RX_ENABLE,&register_value,1,0);
    printk("Before RX_ENABLING %x\n",register_value);
    register_value=0x11;
    x=usb_control_msg(dev->udev,usb_sndctrlpipe(dev->udev,0),WRITE_REQUSET,WRITE_REQUEST_TYPE,WRITE_VALUE,
                            RX_ENABLE,&register_value,1,0);
    udelay(20);
    x=usb_control_msg(dev->udev,usb_rcvctrlpipe(dev->udev,0),READ_REQUSET,READ_REQUEST_TYPE,READ_VALUE,                             RX_ENABLE,&register_value,1,0);
    printk("after RX_ENABLING  %x\n",register_value);
//initialising urb's

    usb_fill_bulk_urb(&dev->rx_urb,dev->udev,
              usb_rcvbulkpipe(dev->udev,dev->bulk_in_endpointAddr),dev->bulk_in_buffer,
              dev->bulk_in_size,rx_callback,dev);
    dev->rx_urb.transfer_flags|=URB_NO_TRANSFER_DMA_MAP;
    if ((result = usb_submit_urb(&dev->rx_urb,GFP_KERNEL)))
    {
        printk("err submiting of urb is failed line no.196 rx_urb %d", result);
   
        return -1;// have to implement cleanup module
    }

    netif_start_queue(net_dev);
   printk("open is ending");
            
  return 0;
}

// rx_callback function start here
static void rx_callback( struct urb *urb  )
{
    struct usb_skel *dev =urb->context;
    struct net_device *net_dev = dev->net_dev;
    int count = urb->actual_length;
    printk("count is %d\n",count);
    __u8 rx_status;
    struct sk_buff    *skb;
    __u16 actual_data;
    unsigned char *bufptr=dev->bulk_in_buffer;
    printk("recive is in progress\n");
    rx_status = *(__u8 *)(bufptr);
    actual_data = *(__u16 *)(bufptr + 1) - 4;
    if ( !(skb = dev_alloc_skb(actual_data + 2)) )   //+2 is because  skbpacket=actualdata+2(net_ip_allinment)
        goto out;

    skb->dev = net_dev;
    skb_reserve(skb, 2);
    memcpy(skb_put(skb,actual_data), bufptr + 3, actual_data);
    skb->protocol = eth_type_trans(skb, net_dev);
    netif_rx(skb);
    dev->stats.rx_packets++;
    dev->stats.rx_bytes += actual_data;
          printk("rx_callback is at last line");
out:
    usb_fill_bulk_urb(&dev->rx_urb,dev->udev,usb_rcvbulkpipe(dev->udev,
                        dev->bulk_in_endpointAddr),dev->bulk_in_buffer,
                        dev->bulk_in_size,rx_callback,dev);
    if (usb_submit_urb(&dev->rx_urb,GFP_ATOMIC))
    {
            printk(KERN_NOTICE"\n rx error in submitting urb");

    }
   

}

// trasmit start
static int transmit( struct sk_buff *skb, struct net_device *net_dev)
{
printk(KERN_NOTICE "\n   transmit functiion is called ");
struct usb_skel *dev = netdev_priv(net_dev);
    int count = skb->len + 2;
    int res;
    __u16 len=skb->len;
    netif_stop_queue( net_dev );
    if (!(count & 0x3f))
    {
        count++;
        len++;
    }
    dev->tx_buff=usb_buffer_alloc(dev->udev,count,GFP_KERNEL,&dev->tx_urb.transfer_dma);
    ((__u16*)dev->tx_buff)[0]=cpu_to_le16(len);
    ((__u8*)dev->tx_buff)[1]=skb->len>>8;
    memcpy(dev->tx_buff + 2, skb->data, skb->len);
    printk("xmit packet size %x\n",skb->len);
   
    usb_fill_bulk_urb(&dev->tx_urb,dev->udev,usb_sndbulkpipe(dev->udev,
                        dev->bulk_out_endpointAddr),dev->tx_buff,count,
                        tx_callback,dev);
    dev->tx_urb.transfer_flags|=URB_NO_TRANSFER_DMA_MAP;
    if ((res = usb_submit_urb(&dev->tx_urb,GFP_KERNEL)))
    {
        printk("failed tx_urb %d", res);
        dev->stats.tx_errors++;
        netif_start_queue( net_dev );
    }
    else
    {
        dev->stats.tx_packets++;
        dev->stats.tx_bytes += skb->len;
    }
    dev_kfree_skb(skb);
 return 0;
}

// tx_callback start

static void tx_callback(struct urb *urb)
{
    printk("tx callback function is called\n");   
    struct usb_skel *dev =urb->context;
    if(urb->status && !(urb->status == -ENOENT || -ECONNRESET || -ESHUTDOWN))
    {
        printk("urb status is %d\n",urb->status);
    }
    usb_buffer_free(urb->dev,urb->transfer_buffer_length,urb->transfer_buffer,urb->transfer_dma);
    printk("tx callback is ending\n");
    netif_wake_queue(dev-> net_dev );
    return;
}

    struct net_device_stats* get_stats(struct net_device *net_dev)
{
        struct usb_skel *dev=netdev_priv(dev);
        return &dev->stats;
}
// disconnect function:
void usb_disconnect(struct usb_interface *interface)
{
     struct usb_skel *dev;
    dev = usb_get_intfdata(interface);
    usb_set_intfdata(interface, NULL);
    unregister_netdev(dev->net_dev);
    free_netdev(dev->net_dev);

    printk(KERN_NOTICE "\ndisconnect called");
}

    int close_dev(struct net_device *net_dev)
{
    netif_stop_queue(net_dev);
    return 0;
}

static int init_9601_driver(void)
{
    int result;
    result=usb_register(&driver_structure);
    if(result==0)
    {
    printk(KERN_NOTICE "REGISTERED\n");
    return result;
    }
        else
    return result;
}
static void exit_9601_driver(void)
{
    usb_deregister(&driver_structure);
      printk(KERN_NOTICE "9601 DRIVER UNREGISTERED");
}
module_init(init_9601_driver);
module_exit(exit_9601_driver);


0 nhận xét:

Đăng nhận xét