📄 mdc800.c
字号:
mdc800_usb_download_notify, mdc800 ); mdc800->state=READY; up (&mdc800->io_lock); usb_set_intfdata(intf, mdc800); return 0;}/* * Disconnect USB device (maybe the MDC800) */static void mdc800_usb_disconnect (struct usb_interface *intf){ struct mdc800_data* mdc800 = usb_get_intfdata(intf); dbg ("(mdc800_usb_disconnect) called"); if (mdc800) { if (mdc800->state == NOT_CONNECTED) return; usb_deregister_dev(intf, &mdc800_class); mdc800->state=NOT_CONNECTED; usb_kill_urb(mdc800->irq_urb); usb_kill_urb(mdc800->write_urb); usb_kill_urb(mdc800->download_urb); mdc800->dev = NULL; usb_set_intfdata(intf, NULL); } info ("Mustek MDC800 disconnected from USB.");}/*************************************************************************** The Misc device Part (file_operations)****************************************************************************//* * This Function calc the Answersize for a command. */static int mdc800_getAnswerSize (char command){ switch ((unsigned char) command) { case 0x2a: case 0x49: case 0x51: case 0x0d: case 0x20: case 0x07: case 0x01: case 0x25: case 0x00: return 8; case 0x05: case 0x3e: return mdc800->pic_len; case 0x09: return 4096; default: return 0; }}/* * Init the device: (1) alloc mem (2) Increase MOD Count .. */static int mdc800_device_open (struct inode* inode, struct file *file){ int retval=0; int errn=0; down (&mdc800->io_lock); if (mdc800->state == NOT_CONNECTED) { errn=-EBUSY; goto error_out; } if (mdc800->open) { errn=-EBUSY; goto error_out; } mdc800->in_count=0; mdc800->out_count=0; mdc800->out_ptr=0; mdc800->pic_index=0; mdc800->pic_len=-1; mdc800->download_left=0; mdc800->camera_busy=0; mdc800->camera_request_ready=0; retval=0; mdc800->irq_urb->dev = mdc800->dev; if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL)) { err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status); errn = -EIO; goto error_out; } mdc800->open=1; dbg ("Mustek MDC800 device opened.");error_out: up (&mdc800->io_lock); return errn;}/* * Close the Camera and release Memory */static int mdc800_device_release (struct inode* inode, struct file *file){ int retval=0; dbg ("Mustek MDC800 device closed."); down (&mdc800->io_lock); if (mdc800->open && (mdc800->state != NOT_CONNECTED)) { usb_kill_urb(mdc800->irq_urb); usb_kill_urb(mdc800->write_urb); usb_kill_urb(mdc800->download_urb); mdc800->open=0; } else { retval=-EIO; } up(&mdc800->io_lock); return retval;}/* * The Device read callback Function */static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t len, loff_t *pos){ size_t left=len, sts=len; /* single transfer size */ char __user *ptr = buf; down (&mdc800->io_lock); if (mdc800->state == NOT_CONNECTED) { up (&mdc800->io_lock); return -EBUSY; } if (mdc800->state == WORKING) { warn ("Illegal State \"working\" reached during read ?!"); up (&mdc800->io_lock); return -EBUSY; } if (!mdc800->open) { up (&mdc800->io_lock); return -EBUSY; } while (left) { if (signal_pending (current)) { up (&mdc800->io_lock); return -EINTR; } sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left; if (sts <= 0) { /* Too less Data in buffer */ if (mdc800->state == DOWNLOAD) { mdc800->out_count=0; mdc800->out_ptr=0; /* Download -> Request new bytes */ mdc800->download_urb->dev = mdc800->dev; if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL)) { err ("Can't submit download urb (status=%i)",mdc800->download_urb->status); up (&mdc800->io_lock); return len-left; } wait_event_timeout(mdc800->download_wait, mdc800->downloaded, TO_DOWNLOAD_GET_READY*HZ/1000); mdc800->downloaded = 0; if (mdc800->download_urb->status != 0) { err ("request download-bytes fails (status=%i)",mdc800->download_urb->status); up (&mdc800->io_lock); return len-left; } } else { /* No more bytes -> that's an error*/ up (&mdc800->io_lock); return -EIO; } } else { /* Copy Bytes */ if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], sts)) { up(&mdc800->io_lock); return -EFAULT; } ptr+=sts; left-=sts; mdc800->out_ptr+=sts; } } up (&mdc800->io_lock); return len-left;}/* * The Device write callback Function * If a 8Byte Command is received, it will be send to the camera. * After this the driver initiates the request for the answer or * just waits until the camera becomes ready. */static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos){ size_t i=0; down (&mdc800->io_lock); if (mdc800->state != READY) { up (&mdc800->io_lock); return -EBUSY; } if (!mdc800->open ) { up (&mdc800->io_lock); return -EBUSY; } while (i<len) { unsigned char c; if (signal_pending (current)) { up (&mdc800->io_lock); return -EINTR; } if(get_user(c, buf+i)) { up(&mdc800->io_lock); return -EFAULT; } /* check for command start */ if (c == 0x55) { mdc800->in_count=0; mdc800->out_count=0; mdc800->out_ptr=0; mdc800->download_left=0; } /* save command byte */ if (mdc800->in_count < 8) { mdc800->in[mdc800->in_count] = c; mdc800->in_count++; } else { up (&mdc800->io_lock); return -EIO; } /* Command Buffer full ? -> send it to camera */ if (mdc800->in_count == 8) { int answersize; if (mdc800_usb_waitForIRQ (0,TO_GET_READY)) { err ("Camera didn't get ready.\n"); up (&mdc800->io_lock); return -EIO; } answersize=mdc800_getAnswerSize (mdc800->in[1]); mdc800->state=WORKING; memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8); mdc800->write_urb->dev = mdc800->dev; if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL)) { err ("submitting write urb fails (status=%i)", mdc800->write_urb->status); up (&mdc800->io_lock); return -EIO; } wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000); mdc800->written = 0; if (mdc800->state == WORKING) { usb_kill_urb(mdc800->write_urb); up (&mdc800->io_lock); return -EIO; } switch ((unsigned char) mdc800->in[1]) { case 0x05: /* Download Image */ case 0x3e: /* Take shot in Fine Mode (WCam Mode) */ if (mdc800->pic_len < 0) { err ("call 0x07 before 0x05,0x3e"); mdc800->state=READY; up (&mdc800->io_lock); return -EIO; } mdc800->pic_len=-1; case 0x09: /* Download Thumbnail */ mdc800->download_left=answersize+64; mdc800->state=DOWNLOAD; mdc800_usb_waitForIRQ (0,TO_DOWNLOAD_GET_BUSY); break; default: if (answersize) { if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ)) { err ("requesting answer from irq fails"); up (&mdc800->io_lock); return -EIO; } /* Write dummy data, (this is ugly but part of the USB Protocol */ /* if you use endpoint 1 as bulk and not as irq) */ memcpy (mdc800->out, mdc800->camera_response,8); /* This is the interpreted answer */ memcpy (&mdc800->out[8], mdc800->camera_response,8); mdc800->out_ptr=0; mdc800->out_count=16; /* Cache the Imagesize, if command was getImageSize */ if (mdc800->in [1] == (char) 0x07) { mdc800->pic_len=(int) 65536*(unsigned char) mdc800->camera_response[0]+256*(unsigned char) mdc800->camera_response[1]+(unsigned char) mdc800->camera_response[2]; dbg ("cached imagesize = %i",mdc800->pic_len); } } else { if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND)) { err ("Command Timeout."); up (&mdc800->io_lock); return -EIO; } } mdc800->state=READY; break; } } i++; } up (&mdc800->io_lock); return i;}/*************************************************************************** Init and Cleanup this driver (Structs and types)****************************************************************************//* File Operations of this drivers */static struct file_operations mdc800_device_ops ={ .owner = THIS_MODULE, .read = mdc800_device_read, .write = mdc800_device_write, .open = mdc800_device_open, .release = mdc800_device_release,};static struct usb_device_id mdc800_table [] = { { USB_DEVICE(MDC800_VENDOR_ID, MDC800_PRODUCT_ID) }, { } /* Terminating entry */};MODULE_DEVICE_TABLE (usb, mdc800_table);/* * USB Driver Struct for this device */static struct usb_driver mdc800_usb_driver ={ .owner = THIS_MODULE, .name = "mdc800", .probe = mdc800_usb_probe, .disconnect = mdc800_usb_disconnect, .id_table = mdc800_table};/************************************************************************ Init and Cleanup this driver (Main Functions)*************************************************************************/static int __init usb_mdc800_init (void){ int retval = -ENODEV; /* Allocate Memory */ mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL); if (!mdc800) goto cleanup_on_fail; memset(mdc800, 0, sizeof(struct mdc800_data)); mdc800->dev = NULL; mdc800->open=0; mdc800->state=NOT_CONNECTED; init_MUTEX (&mdc800->io_lock); init_waitqueue_head (&mdc800->irq_wait); init_waitqueue_head (&mdc800->write_wait); init_waitqueue_head (&mdc800->download_wait); mdc800->irq_woken = 0; mdc800->downloaded = 0; mdc800->written = 0; mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL); if (!mdc800->irq_urb_buffer) goto cleanup_on_fail; mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL); if (!mdc800->write_urb_buffer) goto cleanup_on_fail; mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL); if (!mdc800->download_urb_buffer) goto cleanup_on_fail; mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL); if (!mdc800->irq_urb) goto cleanup_on_fail; mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL); if (!mdc800->download_urb) goto cleanup_on_fail; mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL); if (!mdc800->write_urb) goto cleanup_on_fail; /* Register the driver */ retval = usb_register(&mdc800_usb_driver); if (retval) goto cleanup_on_fail; info (DRIVER_VERSION ":" DRIVER_DESC); return 0; /* Clean driver up, when something fails */cleanup_on_fail: if (mdc800 != NULL) { err ("can't alloc memory!"); kfree(mdc800->download_urb_buffer); kfree(mdc800->write_urb_buffer); kfree(mdc800->irq_urb_buffer); usb_free_urb(mdc800->write_urb); usb_free_urb(mdc800->download_urb); usb_free_urb(mdc800->irq_urb); kfree (mdc800); } mdc800 = NULL; return retval;}static void __exit usb_mdc800_cleanup (void){ usb_deregister (&mdc800_usb_driver); usb_free_urb (mdc800->irq_urb); usb_free_urb (mdc800->download_urb); usb_free_urb (mdc800->write_urb); kfree (mdc800->irq_urb_buffer); kfree (mdc800->write_urb_buffer); kfree (mdc800->download_urb_buffer); kfree (mdc800); mdc800 = NULL;}module_init (usb_mdc800_init);module_exit (usb_mdc800_cleanup);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -