当前位置:文档之家› USB驱动程序源代码

USB驱动程序源代码

项目报告7USB驱动程序源代码作者:罗仕波一.头文件go7007sb.h/**go7007sb.h - this file includes all relative header files that*will be used in go7007sb vedio usb interface driver, and it*also defines all relative driver private data structures and*it's io control commands.*/#ifndef _GO7007SB_H#define _GO7007SB_H#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <asm/uaccess.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/ioctl.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/fs.h>#include <linux/devfs_fs_kernel.h>//#define DEBUG#define DRIVER_VERSION "1.0.0"#define DRIVER_DESC "USB GO7007SB Driver"#include <linux/usb.h>MODULE_AUTHOR("Luo Shibo");MODULE_DESCRIPTION(DRIVER_DESC" "DRIVER_VERSION);MODULE_LICENSE("GPL");/**io control commands definition,these commands will be*used to control the device in function iocntl_go7007sb*/#define GO7007SB_IOC_MAGIC 'U' //command magic number#define GO7007SB_IOC_RESET _IO(GO7007SB_IOC_MAGIC,0) //software reset the device#define GO7007SB_IOC_SHUTDOWN _IO(GO7007SB_IOC_MAGIC,1) //shutdown the device#define GO7007SB_IOC_PAUSE _IO(GO7007SB_IOC_MAGIC,2) //pause compression#define GO7007SB_IOC_RESUME _IO(GO7007SB_IOC_MAGIC,3) //resume from pause status#define GO7007SB_IOC_GETSTATE _IOR(GO7007SB_IOC_MAGIC,4,unsigned int)//get state of dev/**go7007sb device file number,the major of all USB devices have been defined as 180,*we just need to define minors here,currently,we accept only 4 devices*their minors start from 64,so minors:64,65,66,67 should be ok.*/#ifdef __KERNEL__ /*__KERNEL__*/#define GO7007SB_MAX_MNR 4#define GO7007SB_BASE_MNR 64#define USB_GO7007SB_MINOR(inode) MINOR((inode)->i_rdev)-GO7007SB_BASE_MNR/**go7007sb video interface number*/#define GO7007SB_VIDEO_IFNUM 0/**endpoints definition*/#define GO7007SB_MAX_EP_NUM 4 //maximum endpoint number#define GO7007SB_EP_BULK_IN 1 //in endpoint for stream#define GO7007SB_EP_CTRL 2 //out endpoint for control#define GO7007SB_EP_BULK_OUT 3 //out endpoint for initialization#define GO7007SB_EP_INTR 4 //in endpoint for interrupt#define IS_EP_BULK(ep) ((ep).bmAttributes==USB_ENDPOINT_XFER_BULK ? 1 : 0)#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep)&& \((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_IN)#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep)&& \((ep).bEndpointAddress & USB_ENDPOINT_DIR_MASK)==USB_DIR_OUT)#define IS_EP_INTR(ep) ((ep).bmAttributes==USB_ENDPOINT_XFER_INT ? 1 : 0)#define IS_EP_CTRL(ep) ((ep).bmAttributes==USB_ENDPOINT_XFER_CONTROL ? 1 : 0)#define USB_ENDPOINT_NUM(ep) ((ep).bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)#define USB_EP_DIR_IN 0#define USB_EP_DIR_OUT 1/**buffer sizes*/#define GO7007SB_STRM_BUF_SZ 128 //streaming buffer#define GO7007SB_INIT_BUF_SZ 64 //initial buffer#define IN_URB_BUF_SZ 1024 //buffer for in urb#define OUT_URB_BUF_SZ 4*GO7007SB_INIT_BUF_SZ //buffer for out urb/**times*/#define GO7007SB_INT_INTERVAL 5 //interrupt interval:5ms#define GO7007SB_RD_TIMEOUT 3*HZ //timeout per read:3s#define GO7007SB_RD_EXPIRE 3 //expires after 3 read timeouts#define GO7007SB_WR_TIMEOUT 3*HZ#define GO7007SB_WR_EXPIRE 10/**interrupts and command values:values with REQ are requests sent from go7007sb*values with CMD are commands sent from host to control go7007sb*/#define GO7007SB_IRQ_VALUE_MASK 0xFFFF0000#define go7007sb_irq_value(u32_data) (((u32_data) & GO7007SB_IRQ_VALUE_MASK) >> 16)#define GO7007SB_IRQ_BOOT 0x55AA //boota : go7007sb request to boot#define GO7007SB_IRQ_INIT 0x5A5A //bootb2: boot done, request to init#define GO7007SB_IRQ_RUN 0x0000 //initz : init done, request to run#define GO7007SB_IRQ_PAUSE 0x0020 //the ack of PAUSE command#define GO7007SB_IRQ_SHUTDOWN 0xA55A //fatal error,request to shutdown#define GO7007SB_CMD_BOOT 0x55AA //boot go7007sb,write it into init buffer#define GO7007SB_CMD_INIT_BICP 0x1000 //use Block-Init-Config-Package to init#define GO7007SB_CMD_INIT_RICP 0x2000 //use Register-Init_Config-Package to init#define GO7007SB_CMD_INIT_DICP 0x4000 //use DRAM-Init-Config-Packet to init#define GO7007SB_CMD_START 0x8000 //start encoding#define GO7007SB_CMD_PAUSE 0x0020 //pause encoding#define GO7007SB_CMD_SHUTDOWN 0x0081 //shutdown the device#define GO7007SB_CMD_SOFTRESET 0x0082 //software reset the device#define XRISC_EXCODE_START_ADDR 0x0200 //xrisc executable code starting address#define NUM_OF_FIRMWARE_PKT 1 //number of firmware packet downloaded/**file paths*/#define PKT_TYPE_FIRMWARE 0#define PKT_TYPE_INITPKT 1#define DEFAULT_FIRMWARE_PATH "/etc/go7007sb/go7007fw.bin"#define DEFAULT_INITPKT_PATH "/etc/go7007sb/go7007in.bin"#define DEFAULT_CONF_FILE_PATH "/etc/go7007sb.conf"/**go7007sb device id:this will be used for system to*find the driver for a hotpluged go7007sb vedio device*here we only need to match vendor and productor id.*/static struct usb_device_id go7007sb_device_id={match_flags: USB_DEVICE_ID_MATCH_DEVICE |USB_DEVICE_ID_MATCH_INT_CLASS |USB_DEVICE_ID_MATCH_INT_SUBCLASS,idVendor: 0x0EB1,idProduct: 0x7007,bInterfaceClass: 0xFF,bInterfaceSubClass: 0x00,};#endif /*__KERNEL__*//**go7007sb device private data:this struct descripts the*relative info about this device.*/#define GO7007SB_STATE_NOTBOOTED 0 //before bootA state#define GO7007SB_STATE_BOOTFAILED 1 //failed to bootup the device#define GO7007SB_STATE_BOOTDONE 2 //succeeded to boot the device#define GO7007SB_STATE_INITFAILED 3 //failed to initialize the device #define GO7007SB_STATE_PAUSED 4 //paused#define GO7007SB_STATE_HALTED 5 //device halted#define GO7007SB_STATE_RUNNING 6 //device is running#define GO7007SB_STATE_READY 7 //start-coding command sent#ifdef __KERNEL__ /*__KERNEL__*/struct go7007sb_usb_data{struct usb_device *go7007sb_dev; //the usb device structstruct urb go7007sb_irq;//the interrupt urb of this deviceunsigned int ifnum; //interface number of the vedio interface kdev_t go7007sb_minor; //the device minor number of go7007sb char isopen; //not zero if the device is openchar present; //not zero if the device is presentunsigned int state; //device state__u32 irq; //buffer for interrupt endpoint,4 bytes__u64 ctrl; //buffer for control endpoint,8 byteschar *out_buf,*in_buf;//the io buffers used to transferchar bulk_in_ep; //data in endpoint,should be 1char ctrl_ep; //control out endpoint num,should be 2char bulk_out_ep; //init out endpoint,should be 3char intr_ep; //interrupt listening endpoint,should be 4 wait_queue_head_t rd_wait_q; //wait queue on read requestwait_queue_head_t wr_wait_q; //wait queue on write requeststruct semaphore sem; //semphore to prevent concurrent operation unsigned int rd_nak_timeout; //seconds to wait before timeoutunsigned int wr_nak_timeout; //seconds to wait before timeout};#endif /*__KERNEL__*/#endif二.源代码go7007sb.c/**go7007sb.c - defines all the global varibales and functions of the driver*/#ifndef MODULE#define MODULE#endif#ifndef __KERNEL__#define __KERNEL__#endif#include "go7007sb.h"/**global variables*/struct go7007sb_usb_data *p_go7007sb_data_table[GO7007SB_MAX_MNR]={NULL,/*...*/};static DECLARE_MUTEX(go7007sb_mutex);/**macroes to get/set the device state*/#define set_state(go_data,s) \do{ \(go_data)->state=(s); \}while(0)#define get_state(go_data) ((go_data)->state)/**function to build the initial buffer to send command to the device */static inline int build_cmd_buffer(char *buf,__u16 cmd){__u16 *u16_buf=(__u16 *)buf;if(!u16_buf)return -ENOMEM;switch(cmd){case GO7007SB_CMD_BOOT :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_BOOT);u16_buf[1]=cpu_to_le16(XRISC_EXCODE_START_ADDR);u16_buf[3]=cpu_to_le16(NUM_OF_FIRMWARE_PKT);break;case GO7007SB_CMD_START :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_START);/*note:buffer[1]-buffer[31]should reffer to*//*the vendor sdk and to be handled later */break;case GO7007SB_CMD_PAUSE :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_PAUSE);break;case GO7007SB_CMD_SHUTDOWN :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_SHUTDOWN);break;case GO7007SB_CMD_SOFTRESET :u16_buf[0]=cpu_to_le16(GO7007SB_CMD_SOFTRESET);break;default:return -EINVAL;}return 0;}/**function to locate the paths of firmware and config packet*/static struct file *locate_vendor_image(int type){struct file *filp;switch(type){case PKT_TYPE_FIRMWARE :filp=filp_open(DEFAULT_FIRMWARE_PATH,O_RDONLY,0644);if(IS_ERR(filp))goto error;break;case PKT_TYPE_INITPKT :filp=filp_open(DEFAULT_INITPKT_PATH,O_RDONLY,0644);if(IS_ERR(filp))goto error;break;default:goto error;}return filp;error:return NULL;}/**function to send command to device through bulk out endpoint*/static int send_command(struct go7007sb_usb_data *go_data,__u16 cmd) {int retval;int bytes;int wr_expires=GO7007SB_WR_EXPIRE;struct usb_device *dev;char *cmd_buf=go_data->out_buf;kdev_t go_minor=go_data->go7007sb_minor;if(!cmd_buf)return -ENOMEM;/**build the initial buffer*/if((retval=build_cmd_buffer(cmd_buf,cmd))!=0)return retval;/**fill the urb and then submit it*/dev=go_data->go7007sb_dev;try_again:retval=usb_bulk_msg(dev,usb_sndbulkpipe(dev,go_data->bulk_out_ep),cmd_buf,GO7007SB_INIT_BUF_SZ,&bytes,GO7007SB_WR_TIMEOUT);/**check the result*/if(retval==USB_ST_TIMEOUT && !bytes){//timeout and no data sentif(--wr_expires<=0){err("send_command(%d):sending command timed out!",go_minor);}elsegoto try_again;;}else if(retval==-EPIPE){ //endpoint haltedif(usb_clear_halt(dev,go_data->bulk_out_ep)){err("send_command(%d):endpoint halted!",go_minor);}goto try_again;}else if(retval<0){ //other errorserr("send_command(%d):sending command failed!",go_minor);}return retval;}/**function to download file to initial buffer*/static int download_file(struct go7007sb_usb_data *go_data,struct file *fp){char *buf;int count;int partial;int this_write;int result;int wr_expires;struct usb_device *dev;kdev_t go_minor=go_data->go7007sb_minor;buf=go_data->out_buf;if(!buf){return -ENOMEM;}dev=go_data->go7007sb_dev;result=0;wr_expires=GO7007SB_WR_EXPIRE;while((count=kernel_read(fp,fp->f_pos,buf,OUT_URB_BUF_SZ))>0){this_write=(count < OUT_URB_BUF_SZ) ? count : OUT_URB_BUF_SZ;result=usb_bulk_msg(dev,usb_sndbulkpipe(dev,go_data->bulk_out_ep),buf,this_write,&partial,GO7007SB_WR_TIMEOUT);if(result==USB_ST_TIMEOUT && !partial){ //timed out and no data writen if(--wr_expires<=0){err("download_file(%d):downloading file timed out!",go_minor);break;}elsecontinue;}else if(result==-EPIPE){ //endpoint halted, try to repare itif(usb_clear_halt(dev,go_data->bulk_out_ep)){err("download_file(%d):bulk out endpoint halted!",go_minor);break;}continue; //if halt condition cleared}else if(result<0){ //we can not torrent any error in downloadingerr("download_file(%d):downloading file failed!",go_minor);break;}fp->f_pos+=partial;}return result;}///////////////////////////////////////////////////////////////////// go7007sb device file operations definition block////////////////////////////////////////////////////////////////////**function:open_go7007sb - to open the device*/static int open_go7007sb(struct inode *inode,struct file *file){struct go7007sb_usb_data *go_data;struct usb_device *dev;kdev_t go_minor;int err=0;down(&go7007sb_mutex);go_minor=USB_GO7007SB_MINOR(inode);dbg("open_go7007sb(%d): try to open device",go_minor);go_data=p_go7007sb_data_table[go_minor];if(!go_data){printk("<1>open_go7007sb(%d):unable to get private data of devide\n",go_minor);err=-ENODEV;goto out_error;}dev=go_data->go7007sb_dev;if(!dev){printk("<1>open_go7007sb(%d):device is not present!\n",go_minor);err=-ENODEV;goto out_error;}if(!go_data->present){printk("<1>open_go7007sb(%d):device is not present!\n",go_minor);err=-ENODEV;goto out_error;}if(go_data->isopen){printk("<1>open_go7007sb(%d):device is already opened!\n",go_minor);err=-EBUSY;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_READY){printk("<1>open_go7007sb(%d):device is not ready!\n",go_minor);err=-ENODEV;goto out_error;}down(&go_data->sem);/**then send the "start coding" command*/if((err=send_command(go_data,GO7007SB_CMD_START))!=0){printk("<1>open_go7007sb(%d):send \"start\" command failed!\n",go_minor);up(&go_data->sem);goto out_error;}up(&go_data->sem); //release the mutex before sleeping/**wait for the processing of command*/interruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem); //regain the mutexif(signal_pending(current)){up(&go_data->sem);err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_RUNNING){printk("<1>open_go7007sb(%d):process \"start\" command failed!\n",go_minor);up(&go_data->sem);err=-EAGAIN;goto out_error;}dbg("open_go7007sb(%d):device opened!",go_minor);go_data->isopen=1;up(&go_data->sem);file->private_data=go_data;MOD_INC_USE_COUNT;out_error:up(&go7007sb_mutex );return err;}/**function:close_go7007sb - to close the device*/static int close_go7007sb(struct inode *inode,struct file *file){struct go7007sb_usb_data *go_data;kdev_t go_minor;int err=0;down(&go7007sb_mutex);go_minor=USB_GO7007SB_MINOR(inode);dbg("close_go7007sb(%d):try to close device",go_minor);go_data=p_go7007sb_data_table[go_minor];if(!go_data){printk("<1>close_go7007sb(%d):invalid device minor\n",go_minor);err=-ENODEV;goto out_error;}down(&go_data->sem);if((err=send_command(go_data,GO7007SB_CMD_PAUSE))!=0){printk("<1>close_go7007sb(%d):send \"pause\" command failed!\n",go_minor);up(&go_data->sem);goto out_error;}up(&go_data->sem);interruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem);if(signal_pending(current)){up(&go_data->sem);err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_READY){printk("<1>close_go7007sb(%d):send \"pause\" command failed!\n",go_minor);err=-EAGAIN;up(&go_data->sem);goto out_error;}dbg("close_go7007sb:device(%d):device closed!\n",go_minor);go_data->isopen=0;up(&go_data->sem);file->private_data=NULL;MOD_DEC_USE_COUNT;out_error:up(&go7007sb_mutex);return err;}/**function:read_go7007sb - to read data from go7007sb device*/static ssize_t read_go7007sb(struct file *file,char *buffer,size_t count,loff_t *ppos){struct go7007sb_usb_data *go_data;struct usb_device *dev;ssize_t ret; //return valuessize_t bytes_read; //totally bytes readkdev_t go_minor;int result; //function statusint partial; //actually bytes per readint this_read; //bytes wanted per readint rd_expire; //how many timeouts will drive us mad char *urb_buf;go_data=file->private_data;down(&go_data->sem); //enter the critical sectiondev=go_data->go7007sb_dev;go_minor=go_data->go7007sb_minor;urb_buf=go_data->in_buf;bytes_read=0;ret=0;rd_expire=GO7007SB_RD_EXPIRE;/**update the access time*/file->f_dentry->d_inode->i_atime=CURRENT_TIME;while(count>0){this_read=(count > IN_URB_BUF_SZ) ? IN_URB_BUF_SZ : count;result=usb_bulk_msg(dev,usb_rcvbulkpipe(dev,go_data->bulk_in_ep),urb_buf,this_read,&partial,GO7007SB_RD_TIMEOUT);/**now check the return status of submited urb*/if(result==-ETIMEDOUT){ //timed outif(!partial){ //no data readif(--rd_expire<=0){warn("read_go7007sb(%d):excessive NAKs received!",go_minor);ret=result;break;}else //keep trying to read datacontinue;}else //timed out,but did receive some datagoto data_rcvd;if(result==-EPIPE){ //endpoint halted, try to recover itif(usb_clear_halt(dev,go_data->bulk_in_ep))err("read_go7007sb(%d):failed to clear endpoint halt condition!",go_minor);ret=result;break;}}else if(result<0 && result!=USB_ST_DATAUNDERRUN){//funky packetwarn("read_scanner(%d):funky result!",go_minor);ret=-EIO;break;}data_rcvd:if(partial){ //there received some dataif(copy_to_user(buffer,urb_buf,partial)){//copy data to user's bufferret=-EFAULT;break;}count-=partial; //update bytes leftbytes_read+=partial; //update bytes have been readbuffer+=partial; //adjust buffer pointer}else{ //no error or data-underrun,but read 0 byte ret=0;break;}}//whileup(&go_data->sem);return ret ? ret : bytes_read;}/**function:write_go7007sb - to write data to go7007sb device,*commonly,this happens when trying to initialize the device*/static ssize_t write_go7007sb(struct file *file,const char *buffer,size_t count,loff_t *ppos){/**write operation is not allowed*/return -EOPNOTSUPP;}/**function:ioctl_go7007sb - to control the device*/static int reset_go7007sb(struct go7007sb_usb_data *go_data){kdev_t go_minor=go_data->go7007sb_minor;int err=0;down(&go_data->sem);*reset the state*/set_state(go_data,GO7007SB_STATE_NOTBOOTED);/**this command has no response,if succeeded,*go7007sb will send BootA irq to the host*/if((err=send_command(go_data,GO7007SB_CMD_SOFTRESET))!=0){printk("<1>reset_go7007sb(%d):send \"reset\" command failed!\n",go_minor);goto out_error;}/**then we must wait for the boot and initial procedure done*so sleep and wait for the state is set to "standby", and*then send the start-coding command to the device*/up(&go_data->sem); //release mutex before sleepingerr=wait_event_interruptible(go_data->wr_wait_q,get_state(go_data)==GO7007SB_STATE_READY);if(!err) //interrupted by signalsreturn err;down(&go_data->sem); //regain the mutexif((err=send_command(go_data,GO7007SB_CMD_START))!=0){printk("<1>reset_go7007sb(%d):send \"start\" command failed!\n",go_minor);goto out_error;}/**wait for the device to start coding*/up(&go_data->sem);interruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem);if(signal_pending(current)){err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_RUNNING){printk("<1>reset_go7007sb(%d):process \"start\" command failed!\n",go_minor);err=-EAGAIN;goto out_error;}dbg("reset_go7007sb(%d):reset device succeeded!",go_minor);out_error:up(&go_data->sem);return err;}static int shutdown_go7007sb(struct go7007sb_usb_data *go_data){int err=0;kdev_t go_minor=go_data->go7007sb_minor;down(&go_data->sem);if((err=send_command(go_data,GO7007SB_CMD_SHUTDOWN))!=0){printk("<1>shutdown_go7007sb(%d):send \"shutdown\" command failed!\n",go_minor);goto out_error;}up(&go_data->sem); //release mutex before sleepinginterruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem); //regain mutexif(signal_pending(current)){err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_HALTED){printk("<1>shutdown_go7007sb(%d):process \"shutdown\" command failed\n",go_minor);err=-EAGAIN;goto out_error;}dbg("shutdown_go7007sb(%d):shutdown device succeeded!",go_minor);out_error:up(&go_data->sem);return err;}static int pause_go7007sb(struct go7007sb_usb_data *go_data){int err=0;kdev_t go_minor=go_data->go7007sb_minor;down(&go_data->sem);if((err=send_command(go_data,GO7007SB_CMD_PAUSE))!=0){printk("<1>pause_go7007sb(%d):send \"pause\" command failed!\n",go_minor);goto out_error;}up(&go_data->sem); //release mutex before sleepinginterruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem); //regain mutexif(signal_pending(current)){err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_PAUSED){printk("<1>pause_go7007sb(%d):process \"pause\" command failed\n",go_minor);err=-EAGAIN;goto out_error;}dbg("pause_go7007sb(%d):pause device succeeded!",go_minor);out_error:up(&go_data->sem);return err;}static int resume_go7007sb(struct go7007sb_usb_data *go_data){int err=0;kdev_t go_minor=go_data->go7007sb_minor;down(&go_data->sem);if((err=send_command(go_data,GO7007SB_CMD_START))!=0){printk("<1>resume_go7007sb(%d):send \"resume\" command failed!\n",go_minor);goto out_error;}up(&go_data->sem); //release mutex before sleepinginterruptible_sleep_on_timeout(&go_data->wr_wait_q,GO7007SB_WR_TIMEOUT);down(&go_data->sem); //regain mutexif(signal_pending(current)){err=-EINTR;goto out_error;}if(get_state(go_data)!=GO7007SB_STATE_RUNNING){printk("<1>resume_go7007sb(%d):process \"resume\" command failed\n",go_minor);err=-EAGAIN;goto out_error;}dbg("resume_go7007sb(%d):resume device succeeded!",go_minor);out_error:up(&go_data->sem);return err;}static int ioctl_go7007sb(struct inode *inode,struct file *file, unsigned int cmd,unsigned long arg) {struct usb_device *dev;struct go7007sb_usb_data *go_data;int result;kdev_t go_minor;go_data=(struct go7007sb_usb_data *)file->private_data;dev=go_data->go7007sb_dev;go_minor=USB_GO7007SB_MINOR(inode);switch(cmd){case GO7007SB_IOC_GETSTATE :down(&go_data->sem);result=put_user(get_state(go_data),(int *)arg);up(&go_data->sem);break;case GO7007SB_IOC_RESET :result=reset_go7007sb(go_data);break;case GO7007SB_IOC_SHUTDOWN :result=shutdown_go7007sb(go_data);break;case GO7007SB_IOC_PAUSE :result=pause_go7007sb(go_data);break;case GO7007SB_IOC_RESUME :result=resume_go7007sb(go_data);default:result=-ENOIOCTLCMD;}return result;}/**global variable:usb_go7007sb_fops - this variable*defines the operations of go7007sb,the functions*in the struct will be called when access the device*/static struct file_operations usb_go7007sb_fops={owner: THIS_MODULE,read: read_go7007sb,write: write_go7007sb,ioctl: ioctl_go7007sb,open: open_go7007sb,release: close_go7007sb,};/////////////////////////////////////////////////////////////////////// //// go7007sb device driver definition block///////////////////////////////////////////////////////////////////////// /**functions to handle interrupts from go7007sb,*if succeed,return 0, otherwise, return a nonzero number*/static int handle_go7007sb_boot(struct go7007sb_usb_data *go_data){struct file *fm_fp;int retval;kdev_t go_minor=go_data->go7007sb_minor;/**get the file-pointers of firmware and init config packet files*if failed, boot procedure will abort*/if(!(fm_fp=locate_vendor_image(PKT_TYPE_FIRMWARE))){printk("<1>handle_go7007sb_boot(%d):could not locate firmware file!\n",go_minor);return retval;}down(&go_data->sem);/**now send the "start boot" command to the device through bulk out endpoint*this command notify the device we will begin to download firmware data.*/if((retval=send_command(go_data,GO7007SB_CMD_BOOT))<0){printk("<1>handle_go7007sb_boo(%d)t:send \"boot\" command failed!\n",go_minor);goto failed;}/**the begin download the data*/if((retval=download_file(go_data,fm_fp))!=0){printk("<1>handle_go7007sb_boot(%d):download firmware failed!\n",go_minor);goto failed;}set_state(go_data,GO7007SB_STATE_BOOTDONE);goto out;failed:set_state(go_data,GO7007SB_STATE_BOOTFAILED);out:up(&go_data->sem);wake_up_interruptible(&go_data->wr_wait_q);return retval;}static int handle_go7007sb_init(struct go7007sb_usb_data *go_data){struct file *cfg_fp;int retval;kdev_t go_minor=go_data->go7007sb_minor;/**get the file pointer of init configuration packet*/retval=-EINVAL;if(!(cfg_fp=locate_vendor_image(PKT_TYPE_INITPKT))){printk("<1>handle_go7007sb_init(%d):could not locate init packet file!\n",go_minor);return retval;}down(&go_data->sem);/**then download the file*/if((retval=download_file(go_data,cfg_fp))!=0){printk("<1>handle_go7007sb_init(%d):download init packet failed!\n",go_minor);goto failed;}set_state(go_data,GO7007SB_STATE_READY);dbg("handle_go7007sb_init(%d):device is now ready!",go_minor);goto out;failed:set_state(go_data,GO7007SB_STATE_INITFAILED);out:up(&go_data->sem);wake_up_interruptible(&go_data->wr_wait_q);return retval;}static int handle_go7007sb_run(struct go7007sb_usb_data *go_data){down(&go_data->sem);/**just need to change the state*/set_state(go_data,GO7007SB_STATE_RUNNING);up(&go_data->sem);/**wakeup the process in the wr_wait_q*it slept after sending the command*/wake_up_interruptible(&go_data->wr_wait_q);return 0;}static int handle_go7007sb_pause(struct go7007sb_usb_data *go_data) {down(&go_data->sem);/**just need to change the state*/set_state(go_data,GO7007SB_STATE_READY);up(&go_data->sem);wake_up_interruptible(&go_data->wr_wait_q);return 0;}static int handle_go7007sb_shutdown(struct go7007sb_usb_data *go_data) {down(&go_data->sem);/**just need to change the state*/。

相关主题