?? usb-func.c
字號:
else
rv = 0;
dbg("Leave");
return rv;
}
static int go_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
pusb_t s;
s = (pusb_t) file->private_data;
err("ioctl %x %x", cmd, arg);
if(cmd != IOCTL_GO_COMMAND) {
err("cmd != IOCTL_GO_COMMAND");
return 0;
}
err("will OnIoctlProc");
return OnIoctlProc(s, arg);
}
static int go_open (struct inode *inode, struct file *file)
{
pusb_t s;
int minor;
int rv;
dbg("Enter");
rv = 0;
minor = MINOR(inode->i_rdev);
dbg("minor = %d", minor);
if(minor < 0 || minor >= MAX_DEVICES){
return -ENODEV;
}
down(&usb_dev_table_mutex);
s = usb_dev_table[minor];
if(s == NULL){
err("device (%d) not exist", minor);
up(&usb_dev_table_mutex);
return -ENODEV;
}
if (s->DeviceState != DS_IDLE){
err("ERROR: device is nod IDLE");
rv = -EIO;
goto exit;
}
down (&s->mutex);
s->opened = 1;
file->f_pos = 0;
file->private_data = s;
s->open_count++;
StreamBuffer_Init(&(s->StreamBuffer));
s->DeviceState = DS_OPENED;
s->rd_irq_data.allow_irq = 1;
up(&s->mutex);
exit:
up(&usb_dev_table_mutex);
dbg("Leave");
return rv;
}
static int go_release (struct inode *inode, struct file *file)
{
pusb_t s;
int rv;
dbg("Enter");
s = (pusb_t) file->private_data;
/* Lock minor table and our device */
down(&usb_dev_table_mutex);
down(&s->mutex);
if(s->DeviceState != DS_OPENED && s->DeviceState != DS_RUNNING){
rv = -ENODEV;
goto exit;
}
lock_kernel();
s->opened = 0;
StreamBuffer_Uninit(&(s->StreamBuffer));
unlock_kernel();
if(s->usbdev == NULL){
up(&s->mutex);
go_delete(s);
up(&usb_dev_table_mutex);
return 0;
}
s->DeviceState = DS_IDLE;
s->rd_irq_data.allow_irq = 0;
exit:
up(&s->mutex);
up(&usb_dev_table_mutex);
dbg("Leave");
return 0;
}
/*
static struct file_operations go_fops =
{
owner: THIS_MODULE,
read: go_read,
write: go_write,
open: go_open,
release: go_release,
};
*/
static struct file_operations go_fops =
{
owner: THIS_MODULE,
read: go_read,
write: go_write,
ioctl: go_ioctl,
open: go_open,
release: go_release,
};
/* --------------------------------------------------------------------- */
static void *go_probe (struct usb_device *usbdev, unsigned int ifnum,
const struct usb_device_id *id)
{
int i;
int minor;
struct usb_endpoint_descriptor *pEP;
pusb_t s = NULL;
dbg("Enter");
dbg("vendor id 0x%x, device id 0x%x ifnum:%d",
usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
/* We don't handle multiple configurations */
if (usbdev->descriptor.bNumConfigurations != 1)
return NULL;
down(&usb_dev_table_mutex);
minor = GODEV_MINOR(usbdev->bus->busnum, usbdev->devnum);
info("go_probe: Device %d on Bus %d, minor = %d",
usbdev->devnum, usbdev->bus->busnum, minor);
if(minor < 0 || minor >= 256) {
err("Invalid minor: %d", minor);
goto failed;
}
if(usb_dev_table[minor] != NULL) {
err("ERROR: minor conflict");
goto failed;
}
/* Allocate dev data structure */
s = kmalloc(sizeof(usb_t), GFP_KERNEL);
if(s == NULL){
err("Out of memory");
goto failed;
}
usb_dev_table[minor] = s;
/* Initialization */
memset (s, 0, sizeof (usb_t));
init_MUTEX (&s->mutex);
s->usbdev = usbdev;
s->minor = minor;
s->total_buffer_size = buffers;
s->bh.func = read_stream_bh;
s->bh.data = (unsigned long) s;
sprintf(s->StreamBuffer.cachename, "DEV%d", minor);
init_waitqueue_head(&s->wq_control_pipe);
init_waitqueue_head(&s->wq_download_pipe);
init_waitqueue_head(&s->wq_stream_pipe);
init_waitqueue_head(&s->wq_interrupt_pipe);
init_waitqueue_head(&s->wq_stop_stream_thread);
init_waitqueue_head(&s->wait);
init_waitqueue_head(&s->remove_ok);
spin_lock_init(&s->lock);
INIT_LIST_HEAD(&s->free_buff_list);
INIT_LIST_HEAD(&s->rec_buff_list);
/* ----------- */
down (&s->mutex);
/* Enumerate endpoints */
for(i=0;i<usbdev->config[0].interface[0].altsetting[0].bNumEndpoints;i++) {
pEP = &(usbdev->config[0].interface[0].altsetting[0].endpoint[i]);
dbg("------- %d 0x%02x %02d %x %d",
pEP->bDescriptorType,
pEP->bEndpointAddress,
pEP->wMaxPacketSize,
pEP->bmAttributes, pEP->bInterval);
if((pEP->bEndpointAddress & 0x80) &&
((pEP->bmAttributes & 3) == 0x02)) {
/* we found a bulk in endpoint */
s->bulk_in_buffer = kmalloc(BULK_IN_BUFSIZE, GFP_KERNEL);
s->bulkin_urb = usb_alloc_urb(0);
}
if(((pEP->bEndpointAddress & 0x80) == 0x00) &&
((pEP->bmAttributes & 3) == 0x02)) {
/* we found a bulk out endpoint */
s->bulk_out_size = pEP->wMaxPacketSize;
}
}
s->remove_pending = 0;
s->usbdev = usbdev;
/* Pre-allocate Interrupt URB */
s->irq_urb = usb_alloc_urb(0);
s->irq_buf = kmalloc(4, GFP_KERNEL);
FILL_INT_URB(s->irq_urb, s->usbdev,
usb_rcvintpipe(s->usbdev, INTERRUPT_PIPE),
s->irq_buf, 4,
interrupt_pipe_complete, s, 0x40);
s->irq_urb->transfer_flags = 0x10;
{
int rv;
s->rd_irq_data.ready = 0;
s->rd_irq_data.allow_irq = 0;
rv = usb_submit_urb(s->irq_urb);
dbg("usb_submit_urb: %d\n", rv);
}
#if 0
if (usb_set_configuration (usbdev, usbdev->config[0].bConfigurationValue) < 0) {
err("set_configuration failed");
goto failed;
}
#endif
/* --------- */
up (&s->mutex);
s->DeviceState = DS_IDLE;
up(&usb_dev_table_mutex);
dbg("Leave (successful)");
return s;
failed:
up(&usb_dev_table_mutex);
dbg("Leave (probe failed)");
return NULL;
}
static void go_disconnect (struct usb_device *usbdev, void *ptr)
{
int minor;
pusb_t s = (pusb_t) ptr;
dbg("Enter");
down (&s->mutex);
minor = s->minor;
s->remove_pending = 1;
wake_up (&s->wait);
s->usbdev = NULL;
s->overruns = 0;
if(s->irq_urb)
{
dbg("Unlink IRQ URB");
usb_unlink_urb(s->irq_urb);
usb_free_urb(s->irq_urb);
}
if(s->bulkin_urb)
{
dbg("Unlink Bulk-In URB");
usb_unlink_urb(s->bulkin_urb);
usb_free_urb(s->bulkin_urb);
}
if(s->DeviceState == DS_IDLE){
up(&s->mutex);
go_delete(s);
} else {
s->usbdev = NULL;
up(&s->mutex);
}
info("GO7007 #%d now disconnected", minor);
dbg("Leave");
}
static struct usb_device_id go_ids [] = {
// { USB_DEVICE(0x0547, 0x1002) },
{ USB_DEVICE(0x0EB1, 0x7007) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, go_ids);
static struct usb_driver go_driver =
{
name: "go",
probe: go_probe,
disconnect: go_disconnect,
id_table: go_ids,
};
/* --------------------------------------------------------------------- */
static int __init go_init (void)
{
int rv;
unsigned u;
/* initialize struct */
for (u = 0; u < MAX_DEVICES; u++){
usb_dev_table[u] = NULL;
}
/* Register devfs device*/
rv = devfs_register_chrdev(USB_GO_MAJOR,
"go7007", &go_fops);
if(rv){
err("failed to register devfs device. Error number %d", rv);
return -1;
}
/* Register usb device */
rv = usb_register(&go_driver);
if(rv){
err("usb_register failed. Error number %d", rv);
return -1;
}
dbg("usb_init: driver registered");
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
}
static void __exit go_cleanup (void)
{
dbg("usb_cleanup");
usb_deregister (&go_driver);
devfs_unregister_chrdev(USB_GO_MAJOR, "go7007");
}
/* --------------------------------------------------------------------- */
MODULE_AUTHOR ("JUN DING & HONGJUN YUAN");
MODULE_DESCRIPTION (" GO 7007 Driver for Linux (c)2002");
MODULE_PARM (buffers, "i");
MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
MODULE_LICENSE("-Tech");
module_init (go_init);
module_exit (go_cleanup);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -