de3_dev.c
来自「linux嵌入式课程实践中的一个关于声卡驱动程序 。」· C语言 代码 · 共 901 行 · 第 1/2 页
C
901 行
/******************************************************************* * * DESCRIPTION: Peripheral Funciton Driver for Lyberty Design * Example Four of the development kit. * * AUTHOR: GXJ@CYPRESS.COM * * HISTORY: * *******************************************************************//** include files **///#define MODULE#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/list.h>#include <linux/ctype.h>#include <linux/string.h>#include <linux/fs.h>#include <linux/compatmac.h>#include <linux/slab.h>#include <asm/semaphore.h>#include <asm/ioctls.h>#include "../usbd.h"#include "../usbd-func.h"#include "../usbd-bus.h"#include "../usbd-debug.h"#include "../usbd-inline.h"#include "../usbd-arch.h"#include "../usbd-export.h"#include "../usbd-build.h"#include "../../cy7c67200_300_common.h"#include "../../cy7c67200_300_debug.h"#include "de3_dev.h"static int dev_dbg_on = 0;#define dev_dbg(format, arg...) \ if( dev_dbg_on != 0 ) \ printk(KERN_DEBUG __FILE__ ":" "%d: " format "\n" ,__LINE__, ## arg)/** local definitions **/struct de3_priv { int major_number; struct usb_device_instance * device; struct urb_link int_in_tx; int open_count; struct semaphore sem;};static struct de3_priv * de3_priv = NULL;extern int dbgflg_usbdfd_usbe;#define dbg_usbe(lvl,fmt,args...) dbgPRINT(dbgflg_usbdfd_usbe,lvl,fmt,##args)/* function prototypes */static void de3_event(struct usb_device_instance *, usb_device_event_t, int);static int de3_urb_sent(struct usbd_urb *, int);static int de3_recv_urb(struct usbd_urb *);static void de3_function_init(struct usb_bus_instance *, struct usb_device_instance *, struct usb_function_driver *);static void de3_function_exit(struct usb_device_instance *);static ssize_t de3_read(struct file *, char *, size_t, loff_t *);//static ssize_t ep_read(struct de3_priv *, char *, size_t, int);static ssize_t de3_write(struct file *, const char *, size_t, loff_t *);static ssize_t ep_write(struct de3_priv *, const char *, size_t, int);static int de3_open(struct inode *, struct file *);static int de3_release(struct inode *, struct file *);static int de3_ioctl(struct inode *, struct file *, unsigned int, unsigned long);static void de3_recycle_urb(struct usbd_urb *urb, struct urb_link *link);/******************************************************************************* FUNCTION CONFIGURATION DESCRIPTORS *//* Design Example 3 Endpoints * +---------------------+---------------+--------------+ * | Control in | | | * +---------------------+ Endpoint 0 | Control | * | Control out | | | * +---------------------+---------------+--------------+ * | Interrupt in | Endpoint 1 | report | * +---------------------+ --------------+--------------| */ struct usb_endpoint_description de3_endpoint_description[] = { { bEndpointAddress : INT_IN_EP, bmAttributes : INTERRUPT, wMaxPacketSize : 8, bInterval : 10, direction : IN, transferSize : 8, },};struct usb_class_description de3_class_description[] = { { bDescriptorSubtype: USB_ST_HID, elements: 0, description: { hid: { bcdHID: 0x100, bCountryCode: 0x21, bDescriptorType1: USB_ST_REP, // size needs to be consistant with de3_bios.asm // HID report descriptor size wDescriptorLength1: 0x3f, }, }, },}; struct usb_alternate_description de3_alternate_description = { iInterface : 0, bAlternateSetting : 0, classes : sizeof(de3_class_description) / sizeof(struct usb_class_description), class_list : de3_class_description, endpoints : sizeof(de3_endpoint_description) / sizeof(struct usb_endpoint_description), endpoint_list : de3_endpoint_description, otg_description : 0,};struct usb_interface_description de3_interface_description[] = { { bInterfaceClass : HID_INTERFACE_CLASS, bInterfaceSubClass : HID_INTERFACE_SUBCLASS_BOOT, bInterfaceProtocol : HID_INTERFACE_PROTOCOL_KEYBOARD, iInterface : 0, alternates : sizeof(de3_alternate_description) / sizeof(struct usb_alternate_description), alternate_list : &de3_alternate_description },};struct usb_configuration_description de3_configuration_description = { iConfiguration : 0, bmAttributes : BMATTRIBUTE_RESERVED | BMATTRIBUTE_SELF_POWERED, bMaxPower : 0, interfaces : sizeof(de3_interface_description) / sizeof(struct usb_interface_description), interface_list : &de3_interface_description};struct usb_device_description de3_device_description = { bDeviceClass : DE3_DEVICE_CLASS, bDeviceSubClass : DE3_DEVICE_SUBCLASS, bDeviceProtocol : DE3_DEVICE_PROTOCOL, idVendor : DE3_VENDOR_ID, idProduct : DE3_PRODUCT_ID, iManufacturer : DE3_MANUFACTURER_STR, iProduct : DE3_PRODUCT_STR, iSerialNumber : DE3_SERIAL_NUMBER_STR,};/*****************************************************************************/struct usb_function_operations de3_function_ops = { event : de3_event, urb_sent : de3_urb_sent, recv_urb : de3_recv_urb, recv_setup : 0, function_init : de3_function_init, function_exit : de3_function_exit,};struct usb_function_driver de3_function_driver = { name : "DE3_function_driver", ops : &de3_function_ops, device_description : &de3_device_description, configurations : sizeof(de3_configuration_description) / sizeof(struct usb_configuration_description), configuration_description : &de3_configuration_description, this_module : THIS_MODULE,};struct file_operations de3_file_ops = { owner : THIS_MODULE, read : de3_read, write : de3_write, open : de3_open, release : de3_release, ioctl : de3_ioctl,};/****************************************************************************** * PARAMETERS: bus -> pointer to usb_bus_instance * device -> pointer to usb_device_instance * func_driver -> pointer to usb_function_driver * DESCRIPTION: This routine will initialize the function driver's private * data. It is called from the peripheral controller * * RETURNS: * */void de3_function_init(struct usb_bus_instance * bus, struct usb_device_instance * device, struct usb_function_driver * func_driver){ dev_dbg("de3_function_init enter"); de3_priv = kmalloc( sizeof(struct de3_priv), GFP_KERNEL); if(de3_priv == NULL) { cy_err("de3_priv memory allocation failed."); return; } /* Register device driver */ de3_priv->major_number = register_chrdev( 0, DE3_DEVICE_NAME, &de3_file_ops ); if( de3_priv->major_number == 0 ) { cy_err("register_chrdev() failed."); kfree(de3_priv); de3_priv = NULL; return; } /* save off the usb_device_instance pointer */ de3_priv->device = device; de3_priv->open_count = 0; /* initialize the semaphore, (kernel) */ sema_init(&de3_priv->sem, 1); /* save our private data into the usb_function_instance private pointer */ device->function_instance_array->privdata = de3_priv;}/****************************************************************************** * PARAMETERS: * * DESCRIPTION: * * RETURNS: * */void de3_function_exit(struct usb_device_instance * device){ int i; dev_dbg("de3_function_exit enter"); /* deallocate URB's for each endpoint */ for(i = 0; i < TOTAL_ENDPOINTS; i++) { /* free up URB buffers */ // FIXME next line needs to be fixed //kfree(dev->endpoint_data[i].buffer); } unregister_chrdev( de3_priv->major_number, DE3_DEVICE_NAME ); /* deallocate the function private structure */ kfree(de3_priv); de3_priv = NULL; /* set the usb_function_instance privdata pointer to null */ device->function_instance_array->privdata = NULL;}/****************************************************************************** * PARAMETERS: * * DESCRIPTION: * * RETURNS: * */void de3_event(struct usb_device_instance * device, usb_device_event_t event, int data){ extern char *usbd_device_events[]; dev_dbg("de3_event enter: event: %s, data = %d", usbd_device_events[event], data); switch(event) { case DEVICE_UNKNOWN: break; case DEVICE_INIT: { struct usbd_urb * urb; size_t i; /* initialize URB linked lists */ urb_link_init(&de3_priv->int_in_tx); /* allocate int send urbs */ for(i=0; i<5; i++) { urb = usbd_alloc_urb(device, device->function_instance_array, INT_IN_EP, 64); de3_recycle_urb(urb, &de3_priv->int_in_tx); } } break; case DEVICE_CREATE: break; case DEVICE_HUB_CONFIGURED: break; case DEVICE_RESET: break; case DEVICE_ADDRESS_ASSIGNED: break; case DEVICE_CONFIGURED: break; case DEVICE_SET_INTERFACE: break; case DEVICE_SET_FEATURE: break; case DEVICE_CLEAR_FEATURE: break; case DEVICE_DE_CONFIGURED: break; case DEVICE_BUS_INACTIVE: break; case DEVICE_BUS_ACTIVITY: break; case DEVICE_POWER_INTERRUPTION: break; case DEVICE_HUB_RESET: break; case DEVICE_DESTROY: break; case DEVICE_FUNCTION_PRIVATE: break; }}/****************************************************************************** * PARAMETERS: * * DESCRIPTION: Callback to notify function that a URB has been transmitted * on the bus successfully. * * RETURNS: Zero for SUCCESS, negative for ERROR. * */int de3_urb_sent(struct usbd_urb * sent_urb, int data){ int return_value = ERROR; dev_dbg("de3_urb_sent enter"); /* check the status of the completed URB */ switch(sent_urb->status) { case SEND_FINISHED_OK: case SEND_FINISHED_ERROR: switch( sent_urb->endpoint->endpoint_address & 0xf) { 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);}/****************************************************************************** * PARAMETERS: recv_urb -> a pointer to a URB passed from the peripheral core * layer. * * 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");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?