📄 osrfx2.c~
字号:
flags = (file->f_flags & O_ACCMODE); if ((flags == O_WRONLY) || (flags == O_RDWR)) atomic_inc( &fx2dev->bulk_write_available ); if ((flags == O_RDONLY) || (flags == O_RDWR)) atomic_inc( &fx2dev->bulk_read_available ); /* * Decrement the ref-count on the device instance. */ kref_put(&fx2dev->kref, osrfx2_delete); return 0;}/*****************************************************************************//* *//*****************************************************************************/static ssize_t osrfx2_read(struct file * file, char * buffer, size_t count, loff_t * ppos){ struct osrfx2 * fx2dev; int retval = 0; int bytes_read; int pipe; fx2dev = (struct osrfx2 *)file->private_data; pipe = usb_rcvbulkpipe(fx2dev->udev, fx2dev->bulk_in_endpointAddr), /* * Do a blocking bulk read to get data from the device */ retval = usb_bulk_msg( fx2dev->udev, pipe, fx2dev->bulk_in_buffer, min(fx2dev->bulk_in_size, count), &bytes_read, 10000 ); /* * If the read was successful, copy the data to userspace */ if (!retval) { if (copy_to_user(buffer, fx2dev->bulk_in_buffer, bytes_read)) { retval = -EFAULT; } else { retval = bytes_read; } /* * Increment the pending_data counter by the byte count received. */ fx2dev->pending_data -= retval; } return retval;}/*****************************************************************************//* *//*****************************************************************************/static void write_bulk_backend(struct urb * urb, struct pt_regs * regs){ struct osrfx2 * fx2dev = (struct osrfx2 *)urb->context; /* * Filter sync and async unlink events as non-errors. */ if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) { dev_err(&fx2dev->interface->dev, "%s - non-zero status received: %d\n", __FUNCTION__, urb->status); } /* * Free the spent buffer. */ usb_buffer_free( urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma );}/*****************************************************************************//* *//*****************************************************************************/static ssize_t osrfx2_write(struct file * file, const char * user_buffer, size_t count, loff_t * ppos){ struct osrfx2 * fx2dev; struct urb * urb = NULL; char * buf = NULL; int pipe; int retval = 0; fx2dev = (struct osrfx2 *)file->private_data; if (count == 0) return count; /* * Create a urb, and a buffer for it, and copy the data to the urb. */ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { retval = -ENOMEM; goto error; } buf = usb_buffer_alloc( fx2dev->udev, count, GFP_KERNEL, &urb->transfer_dma ); if (!buf) { retval = -ENOMEM; goto error; } if (copy_from_user(buf, user_buffer, count)) { retval = -EFAULT; goto error; } /* * Initialize the urb properly. */ pipe = usb_sndbulkpipe( fx2dev->udev, fx2dev->bulk_out_endpointAddr ); usb_fill_bulk_urb( urb, fx2dev->udev, pipe, buf, count, write_bulk_backend, fx2dev ); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* * Send the data out the bulk port */ retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) { dev_err(&fx2dev->interface->dev, "%s - usb_submit_urb failed: %d\n", __FUNCTION__, retval); goto error; } /* * Increment the pending_data counter by the byte count sent. */ fx2dev->pending_data += count; /* * Release the reference to this urb, the USB core * will eventually free it entirely. */ usb_free_urb(urb); return count;error: usb_buffer_free(fx2dev->udev, count, buf, urb->transfer_dma); usb_free_urb(urb); return retval;}/*****************************************************************************//* *//*****************************************************************************/static unsigned int osrfx2_poll(struct file * file, poll_table * wait){ struct osrfx2 * fx2dev = (struct osrfx2 *)file->private_data; unsigned int mask = 0; int retval = 0; retval = down_interruptible( &fx2dev->sem ); poll_wait(file, &fx2dev->FieldEventQueue, wait); if ( fx2dev->notify == TRUE ) { fx2dev->notify = FALSE; mask |= POLLPRI; } if ( fx2dev->pending_data > 0) { mask |= POLLIN | POLLRDNORM; } up( &fx2dev->sem ); return mask;}/*****************************************************************************//* This fills-in the driver-supported file_operations fields. *//*****************************************************************************/static struct file_operations osrfx2_file_ops = { .owner = THIS_MODULE, .open = osrfx2_open, .release = osrfx2_release, .read = osrfx2_read, .write = osrfx2_write, .poll = osrfx2_poll,}; /*****************************************************************************//* Usb class driver info in order to get a minor number from the usb core, *//* and to have the device registered with devfs and the driver core. *//*****************************************************************************/static struct usb_class_driver osrfx2_class = { .name = "device/osrfx2_%d", .fops = &osrfx2_file_ops, .minor_base = DEVICE_MINOR_BASE,#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH,#endif};/*****************************************************************************//* Event: un-bound device instance is querying for suitable owner driver. *//*****************************************************************************/static int osrfx2_probe(struct usb_interface * interface, const struct usb_device_id * id){ struct usb_device * udev = interface_to_usbdev(interface); struct osrfx2 * fx2dev = NULL; int retval; fx2dev = kmalloc(sizeof(struct osrfx2), GFP_KERNEL); if (fx2dev == NULL) { retval = -ENOMEM; goto error; } memset(fx2dev, 0, sizeof(*fx2dev)); kref_init( &fx2dev->kref ); fx2dev->udev = usb_get_dev(udev); fx2dev->interface = interface; fx2dev->suspended = FALSE; fx2dev->bulk_write_available = (atomic_t) ATOMIC_INIT(1); fx2dev->bulk_read_available = (atomic_t) ATOMIC_INIT(1); usb_set_intfdata(interface, fx2dev); //device_create_file(&interface->dev, &dev_attr_switches); device_create_file(&interface->dev, &dev_attr_start); //device_create_file(&interface->dev, &dev_attr_7segment); retval = find_endpoints( fx2dev ); if (retval != 0) goto error; /*retval = init_interrupts( fx2dev ); if (retval != 0) goto error;*/ retval = init_bulks( fx2dev ); if (retval != 0) goto error; retval = usb_register_dev(interface, &osrfx2_class); if (retval != 0) { usb_set_intfdata(interface, NULL); } dev_info(&interface->dev, "OSR USB-FX2 device now attached.\n"); return 0;error: dev_err(&interface->dev, "OSR USB-FX2 device probe failed: %d.\n", retval); if (fx2dev) { kref_put( &fx2dev->kref, osrfx2_delete ); } return retval;}/*****************************************************************************//* Event: device instance is being disconnected (deleted) *//*****************************************************************************/static void osrfx2_disconnect(struct usb_interface * interface){ struct osrfx2 * fx2dev; lock_kernel(); fx2dev = usb_get_intfdata(interface); //usb_kill_urb(fx2dev->int_in_urb); usb_set_intfdata(interface, NULL); //device_remove_file(&interface->dev, &dev_attr_switches); device_remove_file(&interface->dev, &dev_attr_start); //device_remove_file(&interface->dev, &dev_attr_7segment); usb_deregister_dev(interface, &osrfx2_class); unlock_kernel(); kref_put( &fx2dev->kref, osrfx2_delete ); dev_info(&interface->dev, "OSR USB-FX2 now disconnected.\n");}#if 0/*****************************************************************************//* Event: device is being suspended. *//*****************************************************************************/#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)static int osrfx2_suspend(struct usb_interface * intf, pm_message_t message)#else static int osrfx2_suspend(struct usb_interface * intf, pm_message_t state)#endif{ struct osrfx2 * fx2dev = usb_get_intfdata(intf); dev_info(&intf->dev, "%s - entry\n", __FUNCTION__); if (down_interruptible(&fx2dev->sem)) { return -ERESTARTSYS; } fx2dev->suspended = TRUE; /* * Stop the interrupt pipe read urb. */ //usb_kill_urb(fx2dev->int_in_urb); up(&fx2dev->sem); return 0;}#endif#if 0/*****************************************************************************//* Event: device is being resumed *//*****************************************************************************/static int osrfx2_resume(struct usb_interface * intf){ int retval; struct osrfx2 * fx2dev = usb_get_intfdata(intf); dev_info(&intf->dev, "%s - entry\n", __FUNCTION__); if (down_interruptible(&fx2dev->sem)) { return -ERESTARTSYS; } fx2dev->suspended = FALSE; /* * Re-start the interrupt pipe read urb. */ //retval = usb_submit_urb( fx2dev->int_in_urb, GFP_KERNEL ); retval = 0; if (retval) { dev_err(&intf->dev, "%s - usb_submit_urb failed %d\n", __FUNCTION__, retval); switch (retval) { case -EHOSTUNREACH: dev_err(&intf->dev, "%s - EHOSTUNREACH probably cause: " "parent hub/port still suspended.\n", __FUNCTION__); break; default: break; } } up(&fx2dev->sem); return 0;}#endif/*****************************************************************************//* This driver's usb_driver structure: ref-ed by osrfx2_init and osrfx2_exit *//*****************************************************************************/static struct usb_driver osrfx2_driver = { .name = "osrfx2", .probe = osrfx2_probe, .disconnect = osrfx2_disconnect, //.suspend = osrfx2_suspend, //.resume = osrfx2_resume, .id_table = id_table,#if 0 /* Fedora Core-5 seems to have a problem with .owner so just remove it */ .owner = THIS_MODULE,#endif};/*****************************************************************************//* This driver's commission routine: just register with USB subsystem. *//*****************************************************************************/static int __init osrfx2_init(void){ int retval; retval = usb_register(&osrfx2_driver); return retval;}/*****************************************************************************//* This driver's decommission routine: just deregister with USB subsystem. *//*****************************************************************************/static void __exit osrfx2_exit(void){ usb_deregister( &osrfx2_driver );}/*****************************************************************************//* Advertise this driver's init and exit routines *//*****************************************************************************/module_init( osrfx2_init );module_exit( osrfx2_exit );MODULE_AUTHOR("Yunxiang Liu");MODULE_DESCRIPTION("A driver for the FCUSB-CY7C68013-128 board");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -