de1_dev.c

来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 1,083 行 · 第 1/2 页

C
1,083
字号
{    int port = 0;    unsigned int bmRequestType;    unsigned int bRequest;    int return_status = ERROR;        struct de1_priv * priv =         (recv_urb->device->function_instance_array+port)->privdata;        cy_dbg("de1_recv_setup enter");        bmRequestType = recv_urb->device_request.bmRequestType & USB_REQ_TYPE_MASK;    bRequest = recv_urb->device_request.bRequest;        if((recv_urb != NULL) && (recv_urb->status != RECV_ERROR)) {               if(recv_urb->actual_length <= 0) {            usbd_recycle_urb(recv_urb);        }                // CHECK FOR VENDOR SPECIFIC SETUP COMMAND        if(bmRequestType & USB_REQ_TYPE_VENDOR) {            switch(bRequest) {                case 0:                     /* status report from the host, place the data on the                      * vendor queue */                    urb_append_irq(&priv->vendor_rcv, recv_urb);                    return_status = SUCCESS;                    break;                            case 1:                    /* update seven segment display to sync with host */                    urb_append_irq(&priv->vendor_rcv, recv_urb);                    return_status = SUCCESS;                                break;                            default:                    cy_info("DE1_RECV_SETUP:  Invalid vendor type.");                    break;            }        }    }    return(return_status); }#endif/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */static ssize_t de1_read(struct file *file, char *buffer, size_t count,                         loff_t *ppos){    ssize_t ret;    struct de1_priv * priv = (struct de1_priv *) file->private_data;	down(&priv->sem);    ret = ep_read( priv, buffer, count, BULK_OUT_EP );    up(&priv->sem);    return ret;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */static ssize_t ep_read(struct de1_priv *priv, char *buffer, size_t count, int endpoint){    struct usbd_urb * urb;    ssize_t return_value = ERROR;    int length;    struct urb_link *urb_link;        cy_dbg("ep_read enter, count:%d, ep:%d", count, endpoint);    if( endpoint == INT_OUT_EP )    {        urb_link = &priv->int_out_rcv;    }    else if( endpoint == BULK_OUT_EP )    {        urb_link = &priv->bulk_out_rcv;    }    else    {        cy_err("Reading on unknown endpoint");        return -EINVAL;    }    /* verify that the device wasn't unplugged */	if( priv->device != NULL &&         !( priv->device->status == USBD_OK &&            priv->device->device_state == DEVICE_CONFIGURED ) )    {        cy_dbg("device not connected");        return -ENOTCONN;	}            if( (urb = first_urb_detached(urb_link)) == NULL )    {        return -EAGAIN;    }    length = urb->actual_length;            if(count >= length)     {        if( copy_to_user(buffer, urb->buffer, length) )         {            /* put back on queue */            urb_link_init(&urb->link);            urb_append_irq(urb_link, urb);            cy_err("copy_to_user failure");            return_value = -EFAULT;        }        else         {            usbd_recycle_urb(urb);            return_value = length;        }                    cy_dbg("1:de1_read, return:%d", return_value);    }    else    {        /* there is more data in this URB than is currently requested,           return the requested amount, and then place the remaining data           back in the receive queue, at the head. */        int difference;                difference = length - count; /* size of remaining data of URB buffer */                if( copy_to_user(buffer, urb->buffer, count) )         {            /* put back on queue */            urb_link_init(&urb->link);            urb_append_irq(urb_link, urb);            cy_err("copy_to_user failure");            return_value = -EFAULT;        }        else {            memcpy(urb->buffer, urb->buffer + count, difference);             urb->actual_length = difference;             /* put back on queue */            urb_link_init(&urb->link);            urb_append_irq(urb_link, urb);            return_value = count;        }        cy_dbg("2:de1_read, return:%d", return_value);    }    return return_value;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */static ssize_t de1_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){    ssize_t ret;    struct de1_priv *priv = (struct de1_priv *) file->private_data;	down(&priv->sem);    ret = ep_write(priv, buffer, count, BULK_IN_EP);    up(&priv->sem);    return ret;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */static ssize_t ep_write(struct de1_priv *priv, const char *buffer, size_t count, int endpoint){    struct usbd_urb * urb;    ssize_t return_value = ERROR;    ssize_t bytes_written = 0;    struct urb_link *urb_link;        cy_dbg("ep_write enter - count:%d, ep:%d", count, endpoint);    /* verify that the device wasn't unplugged */	if( priv->device != NULL &&         !( priv->device->status == USBD_OK &&            priv->device->device_state == DEVICE_CONFIGURED ) )    {        cy_dbg("device not connected");        return -ENOTCONN;	}        /* is the count set */    if(count <= 0 || buffer == NULL) {        cy_err("invalid count/buffer");        return -EINVAL;    }    if( endpoint == INT_IN_EP )    {        urb_link = &priv->int_in_tx;    }    else if( endpoint == BULK_IN_EP )    {        urb_link = &priv->bulk_in_tx;    }    else    {        cy_err("Writing on unknown endpoint");        return -EINVAL;    }        /* we have some data to send, get a URB and send it */    //urb = usbd_alloc_urb(priv->device, priv->device->function_instance_array,                          //BULK_IN_EP, count);    urb = first_urb_detached(urb_link);    if( urb == 0 ) {        cy_dbg("no urb pointer");        return -EAGAIN;    }#if 0    {    unsigned long int_flags;    local_irq_save(int_flags);    --free_urb;    local_irq_restore(int_flags);    }#endif	/* we can only write as much as 1 urb will hold */	bytes_written = (count > urb->buffer_length) ? urb->buffer_length : count;    //bytes_written = count;	/* copy the data from userspace into our urb */	if (copy_from_user(urb->buffer, buffer, bytes_written)) {        de1_recycle_urb(urb, urb_link);        cy_err("copy from user error");        return -EFAULT;	}    urb->actual_length = bytes_written;    /* submit the URB */    //HWTrace(0x7171);    if( usbd_send_urb(urb) == 0 )    {        return_value = bytes_written;    }    else    {        cy_err("Failed to send urb");        de1_recycle_urb(urb, urb_link);        return_value = -EAGAIN;    }    cy_dbg("write exit");    	return return_value;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */static int de1_open(struct inode *inode, struct file *file){	int subminor;	int retval = 0;	    cy_dbg("de1_open enter");	subminor = MINOR(inode->i_rdev) - USB_DE1_MINOR_BASE;	if ((subminor < 0) ||	    (subminor >= MAX_DEVICES)) {		return -ENODEV;	}        MOD_INC_USE_COUNT;	/* lock this device */	down(&de1_priv->sem);	/* increment our usage count for the driver */	++de1_priv->open_count;	/* save our object in the file's private structure */	file->private_data = de1_priv;	/* unlock this device */	up(&de1_priv->sem);    cy_dbg("de1_open exit");	return retval;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */int de1_release(struct inode *inode, struct file *filp){    cy_dbg("de1_release enter");	if (de1_priv == NULL) {		cy_err("%s - object is NULL", __FUNCTION__);        return -EFAULT;	}	/* lock our device */	down(&de1_priv->sem);    	/* decrement our usage count for the module */	MOD_DEC_USE_COUNT;        up(&de1_priv->sem);    cy_dbg("de1_release exit");    return 0;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */static int de1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct de1_priv * priv;	int return_value = ERROR;    cy_dbg("de1_ioctl enter, %d", cmd);	if((priv = (struct de1_priv *) file->private_data) != NULL) {    	/* lock this object */    	down(&priv->sem);        	    /* verify that the device wasn't unplugged */	    if(priv->device != NULL) {            /* we have a valid device */                        switch(cmd) {            case IOCTL_ACCEPT_HNP:                usbd_device_event(de1_priv->device, DEVICE_ACCEPT_HNP, 0);                return_value = SUCCESS;                break;                case IOCTL_REQUEST_SRP:                usbd_device_event(de1_priv->device, DEVICE_REQUEST_SRP, 0);                return_value = SUCCESS;                break;            case IOCTL_GET_DE_RPT:                {                    unsigned char count;                    if( arg != 0 &&                         !copy_from_user(&count, (void*)arg, 1) )                     {                        return_value = ep_read( priv, (char*)arg, count,                                                 INT_OUT_EP );                        if( return_value >=0 )                        {                            return_value = SUCCESS;                        }                    }                }                break;            case IOCTL_SEND_DE_RPT:                {                    unsigned char count;                    if( arg != 0 &&                         !copy_from_user(&count, (void*)arg, 1) )                     {                        cy_dbg("rpt size: %d", count);                        return_value =                             ep_write( priv, (char*)arg, count, INT_IN_EP );                        if( return_value >=0 )                        {                            return_value = SUCCESS;                        }                    }                }                break;            case TCGETS:                break;	        default:                cy_err("unrecognized ioctl command: 0x%x", cmd);                break;	        }	    }        /* unlock the device */        up(&priv->sem);    }    cy_dbg("de1_ioctl exit");    	return return_value;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: recycle transmit urbs * *  RETURNS: * */void de1_recycle_urb(struct usbd_urb *urb, struct urb_link *link){    if( urb != 0 && link != 0)    {        unsigned long int_flags;        //HWTrace(0x7474);        urb_link_init(&urb->link);        local_irq_save(int_flags);        urb_append_irq(link, urb);        //++free_urb;        local_irq_restore(int_flags);    }}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */int __init de1_modinit(void){    int err;    cy_dbg("de1_modinit enter");    /* optional name override */    de1_function_driver.name = DRIVER_NAME;            /* register this function driver with the USBD core */    err = usbd_register_function(&de1_function_driver);    if( err != 0 )     {        cy_err("usbd_register_function() failed.");    }    return err;}/****************************************************************************** *  PARAMETERS: * *  DESCRIPTION: * *  RETURNS: * */void __exit de1_modexit(void){    cy_dbg("de1_modexit enter");    usbd_deregister_function(&de1_function_driver);}/*****************************************************************************/#ifdef MODULEmodule_init(de1_modinit);module_exit(de1_modexit);#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?