/* 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,®ister_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,®ister_value,1,0);
udelay(20);
x=usb_control_msg(dev->udev,usb_rcvctrlpipe(dev->udev,0),READ_REQUSET,READ_REQUEST_TYPE,READ_VALUE, RESET,®ister_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,®ister_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,®ister_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,®ister_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