📄 de3_dev.c
字号:
case INT_IN_EP: de3_recycle_urb(sent_urb, &de3_priv->int_in_tx); return_value = SUCCESS; break; default: cy_warn("ERROR didn't recycle urb"); break; } break; default: cy_err("ERROR de3_urb_sent: unhandled sent status."); break; } return(return_value);}/****************************************************************************** * * DESCRIPTION: Called to receive a URB, called in the interrupt context. * This function determines to which endpoint the received URB belongs, and * saves off the pointer to this URB in the function's private data. This * will then be processed in the read() function when called by the * application. The read() function will then recycle the URB. * * In the future, this may just store the data in a buffer and return. Then * the read function would read directly from the buffer. This implementation * would return the URB's immediately to the peripheral controller driver. * Currently, instead of allocating a separate buffer, this function saves * off a pointer to the URB and the read() function handles it directly, * essentially using the URB buffer to store the data, instead of allocating * separate buffer space. * * RETURNS: A negative value for an error condition, and zero for success. * If an error is returned, then the calling function will check this return * value, and recycle the URB, essentially discarding the data. * */int de3_recv_urb(struct usbd_urb * recv_urb){ int ret_value = -EINVAL; dev_dbg("de3_recv_urb enter"); if((recv_urb != NULL) && (recv_urb->status != RECV_ERROR)) { // determine which endpoint received the URB. switch(recv_urb->endpoint->endpoint_address & 0xf) { default: usbd_recycle_urb(recv_urb); break; } } else { usbd_recycle_urb(recv_urb); } return ret_value;}/****************************************************************************** * * DESCRIPTION: Linux read function * * RETURNS: * */ssize_t de3_read(struct file *file, char *buffer, size_t count, loff_t *ppos){ cy_err("Bulk reads not supported in DE3"); return -EINVAL;}/****************************************************************************** * * DESCRIPTION: Linux write function * * RETURNS: * */ssize_t de3_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){ cy_err("Bulk writes not supported in DE3"); return -EINVAL;}/****************************************************************************** * * DESCRIPTION: Shared write function for Linux writes and ioctls * * RETURNS: * */ssize_t ep_write(struct de3_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; dev_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 ) ) { dev_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 { cy_err("Writing on unknown endpoint"); return -EINVAL; } /* we have some data to send, get a URB and send it */ urb = first_urb_detached(urb_link); if( urb == 0 ) { dev_dbg("no urb pointer"); return -EAGAIN; } /* we can only write as much as 1 urb will hold */ bytes_written = (count > urb->buffer_length) ? urb->buffer_length : count; /* copy the data from userspace into our urb */ if (copy_from_user(urb->buffer, buffer, bytes_written)) { de3_recycle_urb(urb, urb_link); cy_err("copy from user error"); return -EFAULT; } urb->actual_length = bytes_written; /* submit the URB */ if( usbd_send_urb(urb) == 0 ) { return_value = bytes_written; } else { cy_err("Failed to send urb"); de3_recycle_urb(urb, urb_link); return_value = -EAGAIN; } dev_dbg("write exit"); return return_value;}/****************************************************************************** * * DESCRIPTION: Linux device open * * RETURNS: * */int de3_open(struct inode *inode, struct file *file){ int subminor; int retval = 0; dev_dbg("de3_open enter"); subminor = MINOR(inode->i_rdev) - USB_DE3_MINOR_BASE; if ((subminor < 0) || (subminor >= MAX_DEVICES)) { return -ENODEV; } MOD_INC_USE_COUNT; /* lock this device */ down(&de3_priv->sem); /* increment our usage count for the driver */ ++de3_priv->open_count; /* save our object in the file's private structure */ file->private_data = de3_priv; /* unlock this device */ up(&de3_priv->sem); dev_dbg("de3_open exit"); return retval;}/****************************************************************************** * * DESCRIPTION: Linux device close * * RETURNS: * */int de3_release(struct inode *inode, struct file *filp){ dev_dbg("de3_release enter"); if (de3_priv == NULL) { cy_err("%s - object is NULL", __FUNCTION__); return -EFAULT; } /* lock our device */ down(&de3_priv->sem); /* decrement our usage count for the module */ MOD_DEC_USE_COUNT; up(&de3_priv->sem); dev_dbg("de3_release exit"); return 0;}/****************************************************************************** * * DESCRIPTION: Linux device ioctl * * RETURNS: * */int de3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct de3_priv * priv; int return_value = ERROR; hid_keyboard_report_t *hidrpt = (hid_keyboard_report_t *) arg; //dev_dbg("de3_ioctl enter, %d", cmd); if((priv = (struct de3_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_SEND_HID_RPT: if (hidrpt != NULL) { return_value = ep_write( priv, (char*)hidrpt->report, HID_REPORT_SIZE, 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); } //dev_dbg("de3_ioctl exit"); return return_value;}/****************************************************************************** * * DESCRIPTION: recycle transmit urbs * * RETURNS: * */void de3_recycle_urb(struct usbd_urb *urb, struct urb_link *link){ if( urb != 0 && link != 0) { unsigned long int_flags; urb_link_init(&urb->link); local_irq_save(int_flags); urb_append_irq(link, urb); local_irq_restore(int_flags); }}/****************************************************************************** * * DESCRIPTION: Module initialization * * RETURNS: * */int __init de3_modinit(void){ int err; dev_dbg("de3_modinit enter"); /* optional name override */ de3_function_driver.name = DRIVER_NAME; /* register this function driver with the USBD core */ err = usbd_register_function(&de3_function_driver); if( err != 0 ) { cy_err("usbd_register_function() failed."); } return err;}/****************************************************************************** * * DESCRIPTION: Module exit - not used in DE3 * * RETURNS: * */void __exit de3_modexit(void){ dev_dbg("de3_modexit enter"); usbd_deregister_function(&de3_function_driver);}/*****************************************************************************/#ifdef MODULEmodule_init(de3_modinit);module_exit(de3_modexit);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -