您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 质量控制/管理 > CH340-341驱动源码
USB转串口CH340\341驱动源码#includelinux/kernel.h#includelinux/init.h#includelinux/tty.h#includelinux/module.h#includelinux/usb.h#includelinux/usb/serial.h#includelinux/serial.h#defineDEFAULT_BAUD_RATE2400staticintdebug;staticstructusb_device_idid_table[]={{USB_DEVICE(0x4348,0x5523)},{},};MODULE_DEVICE_TABLE(usb,id_table);structch341_private{unsignedbaud_rate;u8dtr;u8rts;};staticintch341_control_out(structusb_device*dev,u8request,u16value,u16index){intr;dbg(ch341_control_out(%02x,%02x,%04x,%04x),USB_DIR_OUT|0x40,(int)request,(int)value,(int)index);r=usb_control_msg(dev,usb_sndctrlpipe(dev,0),request,USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_OUT,value,index,NULL,0,1000);returnr;}staticintch341_control_in(structusb_device*dev,u8request,u16value,u16index,char*buf,unsignedbufsize){intr;dbg(ch341_control_in(%02x,%02x,%04x,%04x,%p,%u),USB_DIR_IN|0x40,(int)request,(int)value,(int)index,buf,(int)bufsize);r=usb_control_msg(dev,usb_rcvctrlpipe(dev,0),request,USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,value,index,buf,bufsize,1000);returnr;}intch341_set_baudrate(structusb_device*dev,structch341_private*priv){shorta,b;intr;dbg(ch341_set_baudrate(%d),priv-baud_rate);switch(priv-baud_rate){case2400:a=0xd901;b=0x0038;break;case4800:a=0x6402;b=0x001f;break;case9600:a=0xb202;b=0x0013;break;case19200:a=0xd902;b=0x000d;break;case38400:a=0x6403;b=0x000a;break;case115200:a=0xcc03;b=0x0008;break;default:return-EINVAL;}r=ch341_control_out(dev,0x9a,0x1312,a);if(!r)r=ch341_control_out(dev,0x9a,0x0f2c,b);returnr;}intch341_set_handshake(structusb_device*dev,structch341_private*priv){dbg(ch341_set_handshake(%d,%d),priv-dtr,priv-rts);returnch341_control_out(dev,0xa4,~((priv-dtr?15:0)|(priv-rts?16:0)),0);}intch341_get_status(structusb_device*dev){char*buffer;intr=-ENOMEM;constunsignedsize=8;dbg(ch341_get_status());buffer=kmalloc(size,GFP_KERNEL);if(!buffer)gotoout;r=ch341_control_in(dev,0x95,0x0706,0,buffer,size);/*returnvalueignored*/r=0;out:kfree(buffer);returnr;}/*--------------------------------------------------------------------------*/intch341_configure(structusb_device*dev,structch341_private*priv){char*buffer;intr=-ENOMEM;constunsignedsize=8;dbg(ch341_configure());buffer=kmalloc(size,GFP_KERNEL);if(!buffer)gotoout;/*expecttwobytes0x270x00*/r=ch341_control_in(dev,0x5f,0,0,buffer,size);if(r0)gotoout;r=ch341_control_out(dev,0xa1,0,0);if(r0)gotoout;r=ch341_set_baudrate(dev,priv);if(r0)gotoout;/*expecttwobytes0x560x00*/r=ch341_control_in(dev,0x95,0x2518,0,buffer,size);if(r0)gotoout;r=ch341_control_out(dev,0x9a,0x2518,0x0050);if(r0)gotoout;/*expect0xff0xee*/r=ch341_get_status(dev);if(r0)gotoout;r=ch341_control_out(dev,0xa1,0x501f,0xd90a);if(r0)gotoout;r=ch341_set_baudrate(dev,priv);if(r0)gotoout;r=ch341_set_handshake(dev,priv);if(r0)gotoout;/*expect0x9f0xee*/r=ch341_get_status(dev);out:kfree(buffer);returnr;}/*allocateprivatedata*/staticintch341_attach(structusb_serial*serial){structch341_private*priv;intr;dbg(ch341_attach());/*privatedata*/priv=kzalloc(sizeof(structch341_private),GFP_KERNEL);if(!priv)return-ENOMEM;priv-baud_rate=DEFAULT_BAUD_RATE;priv-dtr=1;priv-rts=1;r=ch341_configure(serial-dev,priv);if(r0)returnr;usb_set_serial_port_data(serial-port[0],priv);return0;}/*openthisdevice,setdefaultparameters*/staticintch341_open(structusb_serial_port*port,structfile*filp){structusb_serial*serial=port-serial;structch341_private*priv=usb_get_serial_port_data(serial-port[0]);intr;dbg(ch341_open());priv-baud_rate=DEFAULT_BAUD_RATE;priv-dtr=1;priv-rts=1;r=ch341_configure(serial-dev,priv);if(r)gotoout;r=ch341_set_handshake(serial-dev,priv);if(r)gotoout;r=ch341_set_baudrate(serial-dev,priv);if(r)gotoout;r=usb_serial_generic_open(port,filp);out:returnr;}/*Old_termioscontainstheoriginaltermiossettingsand*tty-termioscontainsthenewsettingtobeused.*/staticvoidch341_set_termios(structusb_serial_port*port,structktermios*old_termios){structch341_private*priv=usb_get_serial_port_data(port);structtty_struct*tty=port-tty;unsignedcflag;unsignedbaud_rate;dbg(ch341_set_termios(%p,%p),port,old_termios);if(!port-tty||!port-tty-termios)return;cflag=tty-termios-c_cflag;/*checkthattheyreallywantustochangesomething*/if(old_termios&&cflag==old_termios-c_cflag)return;baud_rate=tty_get_baud_rate(tty);switch(baud_rate){case2400:case4800:case9600:case19200:case38400:case115200:priv-baud_rate=baud_rate;break;default:dbg(Rate%dnotsupported,using%d,baud_rate,DEFAULT_BAUD_RATE);priv-baud_rate=DEFAULT_BAUD_RATE;}ch341_set_baudrate(port-serial-dev,priv);/*Unimplemented:*(cflag&CSIZE):databits[5,8]*(cflag&PARENB):parity{NONE,EVEN,ODD}*(cflag&CSTOPB):stopbits[1,2]*/return;}staticstructusb_driverch341_driver={.name=ch341,.probe=usb_serial_probe,.disconnect=usb_serial_disconnect,.id_table=id_table,.no_dynamic_id=1,};staticstructusb_serial_driverch341_device={.driver={.owner=THIS_MODULE,.name=ch341-uart,},.id_table=id_table,.usb_driver=&ch341_driver,.num_interrupt_in=NUM_DONT_CARE,.num_bulk_in=1,.num_bulk_out=1,.num_ports=1,.o
本文标题:CH340-341驱动源码
链接地址:https://www.777doc.com/doc-4515820 .html