usb 轉(zhuǎn)串口驅(qū)動(dòng)程序_第1頁
usb 轉(zhuǎn)串口驅(qū)動(dòng)程序_第2頁
usb 轉(zhuǎn)串口驅(qū)動(dòng)程序_第3頁
usb 轉(zhuǎn)串口驅(qū)動(dòng)程序_第4頁
usb 轉(zhuǎn)串口驅(qū)動(dòng)程序_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

/*

*ProlificPL2303USBtoserialadaptordriver

*

*Copyright(C)2001-2007GregKroah-Hartman(

greg@

)

*Copyright(C)2003IBMCorp.

*

*Originaldriverfor2.2.xbyanonymous

*

*Thisprogramisfreesoftware;youcanredistributeitand/or

*modifyitunderthetermsoftheGNUGeneralPublicLicenseversion

*2aspublishedbytheFreeSoftwareFoundation.

*

*SeeDocumentation/usb/usb-serial.txtformoreinformationonusingthis

*driver

*

*/

#include<linux/kernel.h>

#include<linux/errno.h>

#include<linux/init.h>

#include<linux/slab.h>

#include<linux/tty.h>

#include<linux/tty_driver.h>

#include<linux/tty_flip.h>

#include<linux/serial.h>

#include<linux/module.h>

#include<linux/moduleparam.h>

#include<linux/spinlock.h>

#include<linux/uaccess.h>

#include<linux/usb.h>

#include<linux/usb/serial.h>

#include"pl2303.h"

/*

*VersionInformation

*/

#defineDRIVER_DESC"ProlificPL2303USBtoserialadaptordriver"

staticintdebug;

#definePL2303_CLOSING_WAIT(30*HZ)

#definePL2303_BUF_SIZE1024

#definePL2303_TMP_BUF_SIZE1024

structpl2303_buf{

unsignedintbuf_size;

char*buf_buf;

char*buf_get;

char*buf_put;

};

staticstructusb_device_idid_table[]={

{USB_DEVICE(PL2303_VENDOR_ID,PL2303_PRODUCT_ID)},

{USB_DEVICE(PL2303_VENDOR_ID,PL2303_PRODUCT_ID_RSAQ2)},

{USB_DEVICE(PL2303_VENDOR_ID,PL2303_PRODUCT_ID_DCU11)},

{USB_DEVICE(PL2303_VENDOR_ID,PL2303_PRODUCT_ID_RSAQ3)},

{USB_DEVICE(PL2303_VENDOR_ID,PL2303_PRODUCT_ID_PHAROS)},

{USB_DEVICE(PL2303_VENDOR_ID,PL2303_PRODUCT_ID_ALDIGA)},

{USB_DEVICE(PL2303_VENDOR_ID,PL2303_PRODUCT_ID_MMX)},

{USB_DEVICE(PL2303_VENDOR_ID,PL2303_PRODUCT_ID_GPRS)},

{USB_DEVICE(IODATA_VENDOR_ID,IODATA_PRODUCT_ID)},

{USB_DEVICE(IODATA_VENDOR_ID,IODATA_PRODUCT_ID_RSAQ5)},

{USB_DEVICE(ATEN_VENDOR_ID,ATEN_PRODUCT_ID)},

{USB_DEVICE(ATEN_VENDOR_ID2,ATEN_PRODUCT_ID)},

{USB_DEVICE(ELCOM_VENDOR_ID,ELCOM_PRODUCT_ID)},

{USB_DEVICE(ELCOM_VENDOR_ID,ELCOM_PRODUCT_ID_UCSGT)},

{USB_DEVICE(ITEGNO_VENDOR_ID,ITEGNO_PRODUCT_ID)},

{USB_DEVICE(ITEGNO_VENDOR_ID,ITEGNO_PRODUCT_ID_2080)},

{USB_DEVICE(MA620_VENDOR_ID,MA620_PRODUCT_ID)},

{USB_DEVICE(RATOC_VENDOR_ID,RATOC_PRODUCT_ID)},

{USB_DEVICE(TRIPP_VENDOR_ID,TRIPP_PRODUCT_ID)},

{USB_DEVICE(RADIOSHACK_VENDOR_ID,RADIOSHACK_PRODUCT_ID)},

{USB_DEVICE(DCU10_VENDOR_ID,DCU10_PRODUCT_ID)},

{USB_DEVICE(SITECOM_VENDOR_ID,SITECOM_PRODUCT_ID)},

{USB_DEVICE(ALCATEL_VENDOR_ID,ALCATEL_PRODUCT_ID)},

{USB_DEVICE(SAMSUNG_VENDOR_ID,SAMSUNG_PRODUCT_ID)},

{USB_DEVICE(SIEMENS_VENDOR_ID,SIEMENS_PRODUCT_ID_SX1)},

{USB_DEVICE(SIEMENS_VENDOR_ID,SIEMENS_PRODUCT_ID_X65)},

{USB_DEVICE(SIEMENS_VENDOR_ID,SIEMENS_PRODUCT_ID_X75)},

{USB_DEVICE(SIEMENS_VENDOR_ID,SIEMENS_PRODUCT_ID_EF81)},

{USB_DEVICE(SYNTECH_VENDOR_ID,SYNTECH_PRODUCT_ID)},

{USB_DEVICE(NOKIA_CA42_VENDOR_ID,NOKIA_CA42_PRODUCT_ID)},

{USB_DEVICE(CA_42_CA42_VENDOR_ID,CA_42_CA42_PRODUCT_ID)},

{USB_DEVICE(SAGEM_VENDOR_ID,SAGEM_PRODUCT_ID)},

{USB_DEVICE(LEADTEK_VENDOR_ID,LEADTEK_9531_PRODUCT_ID)},

{USB_DEVICE(SPEEDDRAGON_VENDOR_ID,SPEEDDRAGON_PRODUCT_ID)},

{USB_DEVICE(DATAPILOT_U2_VENDOR_ID,DATAPILOT_U2_PRODUCT_ID)},

{USB_DEVICE(BELKIN_VENDOR_ID,BELKIN_PRODUCT_ID)},{USB_DEVICE(ALCOR_VENDOR_ID,ALCOR_PRODUCT_ID)},

{USB_DEVICE(WS002IN_VENDOR_ID,WS002IN_PRODUCT_ID)},

{USB_DEVICE(COREGA_VENDOR_ID,COREGA_PRODUCT_ID)},

{USB_DEVICE(YCCABLE_VENDOR_ID,YCCABLE_PRODUCT_ID)},

{USB_DEVICE(SUPERIAL_VENDOR_ID,SUPERIAL_PRODUCT_ID)},

{USB_DEVICE(HP_VENDOR_ID,HP_LD220_PRODUCT_ID)},

{}/*Terminatingentry*/

};

MODULE_DEVICE_TABLE(usb,id_table);

staticstructusb_driverpl2303_driver={

.name="pl2303",

.probe=usb_serial_probe,

.disconnect=usb_serial_disconnect,

.id_table=id_table,

.suspend=usb_serial_suspend,

.resume=usb_serial_resume,

.no_dynamic_id=1,

.supports_autosuspend=1,

};

#defineSET_LINE_REQUEST_TYPE0x21

TOC\o"1-5"\h\z

#defineSET_LINE_REQUEST0x20

#defineSET_CONTROL_REQUEST_TYPE0x21

#defineSET_CONTROL_REQUEST0x22

#defineCONTROL_DTR0x01

#defineCONTROL_RTS0x02

#defineBREAK_REQUEST_TYPE0x21

#defineBREAK_REQUEST0x23

#defineBREAK_ON0xffff

#defineBREAK_OFF0x0000

#defineGET_LINE_REQUEST_TYPE0xa1

#defineGET_LINE_REQUEST0x21

#defineVENDOR_WRITE_REQUEST_TYPE0x40

#defineVENDOR_WRITE_REQUEST0x01

#defineVENDOR_READ_REQUEST_TYPE0xc0

#defineVENDOR_READ_REQUEST0x01

#defineUART_STATE0x08

#defineUART_STATE_TRANSIENT_MASK0x74

TOC\o"1-5"\h\z

#defineUART_DCD0x01

#defineUART_DSR0x02

#defineUART_BREAK_ERROR0x04

#defineUART_RING0x08

#defineUART_FRAME_ERROR0x10

#defineUART_PARITY_ERROR0x20

#defineUART_OVERRUN_ERROR0x40#defineUART_CTS0x80enumpl2303_type{

type_0,/*don'tknowthedifferencebetweentype0and*/

type_1,/*type1,untilsomeonefromprolifictellsus...*/

HX,/*HXversionofthepl2303chip*/

};

structpl2303_private{

spinlock_tlock;

structpl2303_buf*buf;

intwrite_urb_in_use;

wait_queue_head_tdelta_msr_wait;

u8line_control;

u8line_status;

enumpl2303_typetype;

};

/*

*pl2303_buf_alloc

*

*Allocateacircularbufferandallassociatedmemory.

*/

staticstructpl2303_buf*pl2303_buf_alloc(unsignedintsize)

{

structpl2303_buf*pb;

if(size==0)

returnNULL;

pb=kmalloc(sizeof(structpl2303_buf),GFP_KERNEL);

if(pb==NULL)

returnNULL;

pb->buf_buf=kmalloc(size,GFP_KERNEL);if(pb->buf_buf==NULL){

kfree(pb);returnNULL;

}

pb->buf_size=size;

pb->buf_get=pb->buf_put=pb->buf_buf;

returnpb;

}

/*

*pl2303_buf_free

*

*Freethebufferandallassociatedmemory.

*/

staticvoidpl2303_buf_free(structpl2303_buf*pb){

if(pb){

kfree(pb->buf_buf);kfree(pb);

}

}

/*

*pl2303_buf_clear

*

*Clearoutalldatainthecircularbuffer.

*/

staticvoidpl2303_buf_clear(structpl2303_buf*pb)

{

if(pb!=NULL)pb->buf_get=pb->buf_put;

/*equivalenttoagetofalldataavailable*/

}

/*

*pl2303_buf_data_avail

*

*Returnthenumberofbytesofdataavailableinthecircular*buffer.

*/

staticunsignedintpl2303_buf_data_avail(structpl2303_buf*pb){

if(pb==NULL)

return0;

return(pb->buf_size+pb->buf_put-pb->buf_get)%pb->buf_size;}

/*

*pl2303_buf_space_avail

*

*Returnthenumberofbytesofspaceavailableinthecircular

*buffer.

*/

staticunsignedintpl2303_buf_space_avail(structpl2303_buf*pb){

if(pb==NULL)

return0;

return(pb->buf_size+pb->buf_get-pb->buf_put-1)%pb->buf_size;}

/*

*pl2303_buf_put

*

*Copydatadatafromauserbufferandputitintothecircularbuffer.

*Restricttotheamountofspaceavailable.

*

*Returnthenumberofbytescopied.

*/

staticunsignedintpl2303_buf_put(structpl2303_buf*pb,constchar*buf,unsignedintcount)

{

unsignedintlen;

if(pb==NULL)

return0;

len=pl2303_buf_space_avail(pb);

if(count>len)

count=len;

if(count==0)return0;

len=pb->buf_buf+pb->buf_size-pb->buf_put;

if(count>len){

memcpy(pb->buf_put,buf,len);

memcpy(pb->buf_buf,buf+len,count-len);pb->buf_put=pb->buf_buf+count-len;

}else{

memcpy(pb->buf_put,buf,count);

if(count<len)

pb->buf_put+=count;

else/*count==len*/

pb->buf_put=pb->buf_buf;

}

returncount;

}

/*

*pl2303_buf_get

*

*Getdatafromthecircularbufferandcopytothegivenbuffer.

*Restricttotheamountofdataavailable.

*

*Returnthenumberofbytescopied.

*/

staticunsignedintpl2303_buf_get(structpl2303_buf*pb,char*buf,unsignedintcount)

{

unsignedintlen;

if(pb==NULL)

return0;

len=pl2303_buf_data_avail(pb);

if(count>len)

count=len;

if(count==0)

return0;

len=pb->buf_buf+pb->buf_size-pb->buf_get;

if(count>len){

memcpy(buf,pb->buf_get,len);

memcpy(buf+len,pb->buf_buf,count-len);

pb->buf_get=pb->buf_buf+count-len;

}else{

memcpy(buf,pb->buf_get,count);

if(count<len)

pb->buf_get+=count;

else/*count==len*/

pb->buf_get=pb->buf_buf;

}

returncount;

}

staticintpl2303_vendor_read(__u16value,__u16index,

structusb_serial*serial,unsignedchar*buf)

{

intres=usb_control_msg(serial->dev,usb_rcvctrlpipe(serial->dev,0),VENDOR_READ_REQUEST,VENDOR_READ_REQUEST_TYPE,value,index,buf,1,100);

dbg("0x%x:0x%x:0x%x:0x%x%d-%x",VENDOR_READ_REQUEST_TYPE,VENDOR_READ_REQUEST,value,index,res,buf[0]);

returnres;

}

staticintpl2303_vendor_write(__u16value,__u16index,

structusb_serial*serial)

{

intres=usb_control_msg(serial->dev,usb_sndctrlpipe(serial->dev,0),VENDOR_WRITE_REQUEST,VENDOR_WRITE_REQUEST_TYPE,value,index,NULL,0,100);

dbg("0x%x:0x%x:0x%x:0x%x%d",VENDOR_WRITE_REQUEST_TYPE,VENDOR_WRITE_REQUEST,value,index,res);

returnres;

}

staticintpl2303_startup(structusb_serial*serial)

{

structpl2303_private*priv;

enumpl2303_typetype=type_0;

unsignedchar*buf;

inti;

buf=kmalloc(10,GFP_KERNEL);

if(buf==NULL)

return-ENOMEM;

if(serial->dev->descriptor.bDeviceClass==0x02)type=type_0;

elseif(serial->dev->descriptor.bMaxPacketSize0==0x40)type=HX;

elseif(serial->dev->descriptor.bDeviceClass==0x00)type=type_1;

elseif(serial->dev->descriptor.bDeviceClass==0xFF)

type=type_1;

dbg("devicetype:%d",type);

for(i=0;i<serial->num_ports;++i){

priv=kzalloc(sizeof(structpl2303_private),GFP_KERNEL);if(!priv)

gotocleanup;

spin_lock_init(&priv->lock);

priv->buf=pl2303_buf_alloc(PL2303_BUF_SIZE);

if(priv->buf==NULL){

kfree(priv);

gotocleanup;

}init_waitqueue_head(&priv->delta_msr_wait);priv->type=type;

usb_set_serial_port_data(serial->port[i],priv);

}

pl2303_vendor_read(0x8484,0,serial,buf);pl2303_vendor_write(0x0404,0,serial);pl2303_vendor_read(0x8484,0,serial,buf);pl2303_vendor_read(0x8383,0,serial,buf);pl2303_vendor_read(0x8484,0,serial,buf);pl2303_vendor_write(0x0404,1,serial);pl2303_vendor_read(0x8484,0,serial,buf);pl2303_vendor_read(0x8383,0,serial,buf);pl2303_vendor_write(0,1,serial);pl2303_vendor_write(1,0,serial);

if(type==HX)pl2303_vendor_write(2,0x44,serial);

else

pl2303_vendor_write(2,0x24,serial);

kfree(buf);

return0;

cleanup:

kfree(buf);

for(--i;i>=0;--i){

priv=usb_get_serial_port_data(serial->port[i]);pl2303_buf_free(priv->buf);

kfree(priv);usb_set_serial_port_data(serial->port[i],NULL);

}

return-ENOMEM;

}

staticintset_control_lines(structusb_device*dev,u8value)

{

intretval;

retval=usb_control_msg(dev,usb_sndctrlpipe(dev,0),SET_CONTROL_REQUEST,SET_CONTROL_REQUEST_TYPE,value,0,NULL,0,100);

dbg("%s-value=%d,retval=%d",__func__,value,retval);returnretval;

}

staticvoidpl2303_send(structusb_serial_port*port)

{

intcount,result;

structpl2303_private*priv=usb_get_serial_port_data(port);unsignedlongflags;

dbg("%s-port%d",__func__,port->number);spin_lock_irqsave(&priv->lock,flags);

if(priv->write_urb_in_use){spin_unlock_irqrestore(&priv->lock,flags);return;

}

count=pl2303_buf_get(priv->buf,port->write_urb->transfer_buffer,port->bulk_out_size);

if(count==0){spin_unlock_irqrestore(&priv->lock,flags);return;

priv->write_urb_in_use=1;

spin_unlock_irqrestore(&priv->lock,flags);

usb_serial_debug_data(debug,&port->dev,__func__,count,

port->write_urb->transfer_buffer);

port->write_urb->transfer_buffer_length=count;

port->write_urb->dev=port->serial->dev;

result=usb_submit_urb(port->write_urb,GFP_ATOMIC);

if(result){

dev_err(&port->dev,"%s-failedsubmittingwriteurb,"

"error%d\n",__func__,result);

priv->write_urb_in_use=0;

/*TODO:reschedulepl2303_send*/

}

usb_serial_port_softint(port);

}

staticintpl2303_write(structtty_struct*tty,structusb_serial_port*port,constunsignedchar*buf,intcount)

{

structpl2303_private*priv=usb_get_serial_port_data(port);

unsignedlongflags;

dbg("%s-port%d,%dbytes",__func__,port->number,count);

if(!count)

returncount;

spin_lock_irqsave(&priv->lock,flags);

count=pl2303_buf_put(priv->buf,buf,count);

spin_unlock_irqrestore(&priv->lock,flags);

pl2303_send(port);

returncount;

}

staticintpl2303_write_room(structtty_struct*tty)

{

structusb_serial_port*port=tty->driver_data;

structpl2303_private*priv=usb_get_serial_port_data(port);introom=0;

unsignedlongflags;

dbg("%s-port%d",__func__,port->number);

spin_lock_irqsave(&priv->lock,flags);room=pl2303_buf_space_avail(priv->buf);spin_unlock_irqrestore(&priv->lock,flags);

dbg("%s-returns%d",__func__,room);returnroom;

}

staticintpl2303_chars_in_buffer(structtty_struct*tty)

{

structusb_serial_port*port=tty->driver_data;

structpl2303_private*priv=usb_get_serial_port_data(port);intchars=0;

unsignedlongflags;

dbg("%s-port%d",__func__,port->number);

spin_lock_irqsave(&priv->lock,flags);chars=pl2303_buf_data_avail(priv->buf);spin_unlock_irqrestore(&priv->lock,flags);

dbg("%s-returns%d",__func__,chars);returnchars;

}

staticvoidpl2303_set_termios(structtty_struct*tty,

structusb_serial_port*port,structktermios*old_termios){

structusb_serial*serial=port->serial;

structpl2303_private*priv=usb_get_serial_port_data(port);unsignedlongflags;

unsignedintcflag;

unsignedchar*buf;

intbaud;

inti;

u8control;

dbg("%s-port%d",__func__,port->number);

/*ThePL2303isreportedtolosebytesifyouchangeserialsettingseventothesamevaluesasbefore.Thusweactuallyneedtofilterinthisspecificcase*/

if(!tty_termios_hw_change(tty->termios,old_termios))return;

cflag=tty->termios->c_cflag;

buf=kzalloc(7,GFP_KERNEL);

if(!buf){

dev_err(&port->dev,"%s-outofmemory.\n",__func__);/*Reportbacknochangeoccurred*/

*tty->termios=*old_termios;

return;

}

i=usb_control_msg(serial->dev,usb_rcvctrlpipe(serial->dev,0),GET_LINE_REQUEST,GET_LINE_REQUEST_TYPE,0,0,buf,7,100);

dbg("0xa1:0x21:0:0%d-%x%x%x%x%x%x%x",i,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6]);

if(cflag&CSIZE){

switch(cflag&CSIZE){

caseCS5:

buf[6]=5;

break;

caseCS6:

buf[6]=6;

break;

caseCS7:

buf[6]=7;

break;

default:

caseCS8:

buf[6]=8;

break;

}

dbg("%s-databits=%d",__func__,buf[6]);

}

baud=tty_get_baud_rate(tty);

dbg("%s-baud=%d",__func__,baud);

if(baud){

buf[0]=baud&0xff;

buf[1]=(baud>>8)&0xff;

buf[2]=(baud>>16)&0xff;

buf[3]=(baud>>24)&0xff;

}

/*Forreferencebuf[4]=0is1stopbits*/

/*Forreferencebuf[4]=1is1.5stopbits*/

/*Forreferencebuf[4]=2is2stopbits*/

if(cflag&CSTOPB){

buf[4]=2;

dbg("%s-stopbits=2",__func__);

}else{

buf[4]=0;

dbg("%s-stopbits=1",__func__);

}

if(cflag&PARENB){

/*Forreferencebuf[5]=0isnoneparity*/

/*Forreferencebuf[5]=1isoddparity*/

/*Forreferencebuf[5]=2isevenparity*/

/*Forreferencebuf[5]=3ismarkparity*/

/*Forreferencebuf[5]=4isspaceparity*/

if(cflag&PARODD){

buf[5]=1;

dbg("%s-parity=odd",__func__);

}else{

buf[5]=2;

dbg("%s-parity=even",__func__);

}

}else{

buf[5]=0;

dbg("%s-parity=none",__func__);

}

i=usb_control_msg(serial->dev,usb_sndctrlpipe(serial->dev,0),SET_LINE_REQUEST,SET_LINE_REQUEST_TYPE,0,0,buf,7,100);

dbg("0x21:0x20:0:0%d",i);

/*changecontrollinesifweareswitchingtoorfromB0*/spin_lock_irqsave(&priv->lock,flags);

control=priv->line_control;

if((cflag&CBAUD)==B0)

priv->line_control&=~(CONTROL_DTR|CONTROL_RTS);else

priv->line_control|=(CONTROL_DTR|CONTROL_RTS);

if(control!=priv->line_control){control=priv->line_control;spin_unlock_irqrestore(&priv->lock,flags);set_control_lines(serial->dev,control);

}else{spin_unlock_irqrestore(&priv->lock,flags);

}

buf[0]=buf[1]=buf[2]=buf[3]=buf[4]=buf[5]=buf[6]=0;

i=usb_control_msg(serial->dev,usb_rcvctrlpipe(serial->dev,0),GET_LINE_REQUEST,GET_LINE_REQUEST_TYPE,0,0,buf,7,100);

dbg("0xa1:0x21:0:0%d-%x%x%x%x%x%x%x",i,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6]);

if(cflag&CRTSCTS){

if(priv->type==HX)pl2303_vendor_write(0x0,0x61,serial);

elsepl2303_vendor_write(0x0,0x41,serial);

}else{pl2303_vendor_write(0x0,0x0,serial);

}

/*FIXME:Needtoreadbackresultingbaudrate*/

if(baud)

tty_encode_baud_rate(tty,baud,baud);

kfree(buf);

}

staticvoidpl2303_close(structtty_struct*

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論