?? usb1284.c
字號:
/************************************************************* * * usb_ieee1284.c * * Driver for AN2131QC based USB to IEEE1284 converter. * Copyright (C) 2002 Michael Hetherington * chinook@pacific.net.sg * * This software is based on uss720.c * USS720 USB Parport cable driver * Copyright (C) 1999 Thomas Sailer * <sailer@ife.ee.ethz.ch> * * Data sheet for USS720 USB-to-IEEE 1284 bridge could be * found on John Hyde's "USB Design by Example" CDROM * Wiley Computer Publishing 1999 * * History: * 0.01 6.16.2002 Created *************************************************************/#include <linux/module.h>#include <linux/socket.h>#include <linux/parport.h>#include <linux/parport_pc.h>#include <linux/init.h>#include <linux/usb.h>#define DRIVER_VERSION "Version 0.01"#define DRIVER_AUTHOR "Michael Hetherington, chinook@pacific.net.sg"#define DRIVER_DESC "Cypress AN2131 based USB to IEEE 1284 converter"struct parport_usb1284_private { struct usb_device * usbdev; struct urb irq_urb; unsigned char irq_buffer; unsigned char irq_status; unsigned char reg;};/************************************************************* * basic functions *************************************************************/static unsigned char get_request(struct parport *pp, unsigned char request, unsigned char value, unsigned char index){ struct parport_usb1284_private * priv = pp->private_data; struct usb_device *usbdev = priv->usbdev; int ret; ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), request,0xC0,(unsigned int)value, (unsigned int)index,&priv->reg,1,HZ); if(ret != 1) printk(KERN_WARNING "%s: get_request(pp, %2x, %2x, %2x) failed, status %d\n", __FILE__, (unsigned int)request & 0xFF, (unsigned int)value & 0xFF, (unsigned int)index & 0xFF, ret); return priv->reg;}static int set_request(struct parport *pp, unsigned char request, unsigned char value, unsigned char index){ struct parport_usb1284_private * priv = pp->private_data; struct usb_device *usbdev = priv->usbdev; int ret; ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), request,0x40,(unsigned int)value, (unsigned int)index,NULL,0,HZ); if (ret) printk(KERN_WARNING "%s: set_request(pp, %2x, %2x, %2x) failed, status %d\n", __FILE__, (unsigned int)request & 0xFF, (unsigned int)value & 0xFF, (unsigned int)index & 0xFF, ret); return ret;}static int bulk_out(struct parport *pp, const void * buf, size_t len){ struct parport_usb1284_private * priv = pp->private_data; struct usb_device * usbdev = priv->usbdev; int ret; int s = 0; ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev,1), (void *)buf,(unsigned char)len,&s,10*HZ); if(ret) printk (KERN_WARNING "%s: bulk_out(pp,%d) failed, status %d, bytes sent %d\n", __FILE__, len, ret, s); return s;}static size_t transfer_out (struct parport *pp, const void * buf, size_t length, unsigned char mode){ size_t ret = 0; size_t i; while(1){ if(length <= 64){ set_request(pp,2,mode,length); bulk_out(pp,buf,length); i = get_request(pp,2,0,0); return (ret + i); } else { set_request(pp,2,mode,64); bulk_out(pp,buf,64); i = get_request(pp,2,0,0); if (i < 64) return (ret + i); ret += 64; length -= 64; buf += 64; } }}static int bulk_in(struct parport *pp, const void * buf, size_t len){ struct parport_usb1284_private * priv = pp->private_data; struct usb_device * usbdev = priv->usbdev; int ret; int s = 0; ret = usb_bulk_msg(usbdev,usb_rcvbulkpipe(usbdev,2), (void *)buf,(unsigned char)len,&s,10*HZ); if(ret) printk (KERN_WARNING "%s: bulk_in(pp,%d) failed, status %d, bytes received %d\n", __FILE__, len, ret, s); return s;}static size_t transfer_in (struct parport *pp, const void * buf, size_t length, unsigned char mode){ size_t ret = 0; size_t i; while(1){ if (length <= 64){ set_request(pp,2,mode,length); i = bulk_in(pp,buf,length); return (ret + i); } else { set_request(pp,2,mode,64); i = bulk_in(pp,buf,64); if (i < 64) return (ret + i); ret += 64; length -= 64; buf += 64; } }}/* parport_usb1284_write_data */static void parport_usb1284_write_data(struct parport *pp, unsigned char d){ set_request(pp,3,d,0);}/* parport_usb1284_read_data */static unsigned char parport_usb1284_read_data(struct parport *pp){ return get_request(pp,3,0,0);}/* parport_usb1284_write_control */static void parport_usb1284_write_control(struct parport *pp, unsigned char d){ get_request(pp,1,d,0x0F);}/* parport_usb1284_read_control */static unsigned char parport_usb1284_read_control(struct parport *pp){ return (get_request(pp,1,0,0) & 0x0F);}/* parport_usb1284_frob_control */static unsigned char parport_usb1284_frob_control(struct parport *pp, unsigned char mask, unsigned char value){ return (get_request(pp,1, value & 0x2F, mask & 0x2F) & 0x0F);}/* parport_usb1284_read_status */static unsigned char parport_usb1284_read_status (struct parport *pp){ return (get_request(pp,0,0,0) & 0xF8);}/* parport_usb1284_disable_irq */static void parport_usb1284_disable_irq(struct parport *pp){ set_request(pp,4,0,0);}/* parport_usb1284_enable_irq */static void parport_usb1284_enable_irq(struct parport *pp){ struct parport_usb1284_private * priv = pp->private_data; priv->irq_status = get_request(pp,0,0,0) & 0xF8; set_request(pp,4,0x40,0); printk (KERN_WARNING "IRQ enabled\n");}/* parport_usb1284_data_forward */static void parport_usb1284_data_forward(struct parport *pp){ get_request(pp,1,0,0x20);}/* parport_usb1284_data_reverse */static void parport_usb1284_data_reverse(struct parport *pp){ get_request(pp,1,0x20,0x20);}/* parport_usb1284_init_state */static void parport_usb1284_init_state(struct pardevice *dev, struct parport_state *s){ s->u.pc.ctr = 0x0C | (dev->irq_func ? 0x10 : 0x0);}/* parport_usb1284_save_state */static void parport_usb1284_save_state(struct parport * pp, struct parport_state *s){ s->u.pc.ctr = get_request(pp,1,0,0); /* disable irq */ if(s->u.pc.ctr & 0x10) set_request(pp,4,0,0);}/* parport_usb1284_restore_state */static void parport_usb1284_restore_state(struct parport * pp, struct parport_state *s){ get_request(pp,1,s->u.pc.ctr,0x2F); /* enable interrupt */ if(s->u.pc.ctr & 0x10) set_request(pp,4,0x40,0);}/* parport_usb1284_inc_use_count */static void parport_usb1284_inc_use_count(void){ MOD_INC_USE_COUNT;}/* parport_usb1284_dec_use_count */static void parport_usb1284_dec_use_count(void){ MOD_DEC_USE_COUNT;}/* parport_usb1284_epp_write_data */static size_t parport_usb1284_epp_write_data(struct parport *pp, const void *buf, size_t length, int flags){ return transfer_out(pp,buf,length,0x03);}/* parport_usb1284_epp_read_data */static size_t parport_usb1284_epp_read_data(struct parport *pp, void *buf, size_t length, int flags){ return transfer_in(pp,buf,length,0x83);}/* parport_usb1284_epp_write_addr */static size_t parport_usb1284_epp_write_addr(struct parport *pp, const void *buf, size_t length, int flags){ return transfer_out(pp,buf,length,0x04);}/* parport_usb1284_epp_read_addr */static size_t parport_usb1284_epp_read_addr(struct parport *pp, void *buf, size_t length, int flags){ return transfer_in(pp,buf,length,0x84);}/* parport_usb1284_write_compat */static size_t parport_usb1284_write_compat (struct parport *pp, const void *buf, size_t length, int flags){ return transfer_out(pp,buf,length,0x01);}/* parport_usb1284_read_nibble */static size_t parport_usb1284_read_nibble (struct parport *pp, void *buf, size_t length, int flags){ return transfer_in(pp,buf,length,0x81);}/************************************************************* * parport_usb1284_ops *************************************************************/static struct parport_operations parport_usb1284_ops = { parport_usb1284_write_data, parport_usb1284_read_data, parport_usb1284_write_control, parport_usb1284_read_control, parport_usb1284_frob_control, parport_usb1284_read_status, parport_usb1284_enable_irq, parport_usb1284_disable_irq, parport_usb1284_data_forward, parport_usb1284_data_reverse, parport_usb1284_init_state, parport_usb1284_save_state, parport_usb1284_restore_state, parport_usb1284_inc_use_count, parport_usb1284_dec_use_count, parport_usb1284_epp_write_data, parport_usb1284_epp_read_data, parport_usb1284_epp_write_addr, parport_usb1284_epp_read_addr, parport_ieee1284_ecp_write_data, parport_ieee1284_ecp_read_data, parport_ieee1284_ecp_write_addr, parport_usb1284_write_compat, parport_usb1284_read_nibble, parport_ieee1284_read_byte,};/************************************************************* * usb1284_irq() *************************************************************/void usb1284_irq(struct urb * urb){ struct parport * pp = urb->context; struct parport_usb1284_private * priv = pp->private_data; if(urb->status == 0){ if ((priv->irq_status ^ priv->irq_buffer) & 0x40) parport_generic_irq(0, pp, NULL); } printk (KERN_WARNING "%s: IRQ called ...\n", __FILE__);}/************************************************************* * usb1284_probe() *************************************************************/static void * usb1284_probe(struct usb_device * usbdev, unsigned int ifnum, const struct usb_device_id *id){ struct usb_interface_descriptor * interface; struct usb_endpoint_descriptor * endpoint; struct parport_usb1284_private * priv; struct parport *pp; /* allocate space */ if(!(priv = kmalloc(sizeof(struct parport_usb1284_private), GFP_KERNEL))) return NULL; /* allocate parport interface */ if(!(pp = parport_register_port(0,PARPORT_IRQ_NONE,PARPORT_DMA_NONE, &parport_usb1284_ops))){ printk(KERN_WARNING "%s: failed to register parport ...\n", __FILE__); goto abort; } printk(KERN_INFO "%s: registered parport%d ...\n", __FILE__, pp->portnum); pp->private_data = priv; priv->usbdev = usbdev; pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_COMPAT | PARPORT_MODE_SAFEININT; /* allocate interrupt pipe */ interface = &usbdev->actconfig->interface[ifnum].altsetting[0]; endpoint = &interface->endpoint[3]; FILL_INT_URB(&priv->irq_urb,usbdev, usb_rcvintpipe(usbdev,4), &priv->irq_buffer,1,usb1284_irq, pp,endpoint->bInterval); if(usb_submit_urb(&priv->irq_urb)){ printk(KERN_WARNING "%s: interrupt allocation failed ...\n", __FILE__); goto abort_port; } printk(KERN_INFO "%s: interrupt is allocated ...\n", __FILE__); parport_proc_register(pp); parport_announce_port(pp); MOD_INC_USE_COUNT; return pp; abort_port: parport_unregister_port(pp); abort: kfree(priv); return NULL;}/************************************************************* * usb1284_disconnect() *************************************************************/static void usb1284_disconnect(struct usb_device * usbdev, void * data){ struct parport * pp = (struct parport *) data; struct parport_usb1284_private * priv = pp->private_data; if(usb_unlink_urb(&priv->irq_urb)) printk(KERN_WARNING "%s: interrupt unlink failed ...\n", __FILE__); priv->usbdev = NULL; printk(KERN_INFO "%s: unregistering parport%d ...\n", __FILE__, pp->portnum); parport_proc_unregister(pp); parport_unregister_port(pp); kfree(priv); MOD_DEC_USE_COUNT;}/************************************************************* * administrative stuff *************************************************************/#include "vendor.id"static struct usb_device_id usb1284_table [] = { { USB_DEVICE(VENDORID,PRODUCTID) }, { }};MODULE_DEVICE_TABLE(usb,usb1284_table);static struct usb_driver usb1284_driver = { name: "usb1284", probe: usb1284_probe, disconnect: usb1284_disconnect, id_table: usb1284_table,};MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );static int __init usb1284_init(void){ if (usb_register(&usb1284_driver) < 0) return -1; printk(KERN_INFO "%s: %s, %s\n", __FILE__, DRIVER_DESC, DRIVER_VERSION); return 0;}static void __exit usb1284_cleanup(void){ usb_deregister(&usb1284_driver); }module_init(usb1284_init);module_exit(usb1284_cleanup);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -