📄 ul_cps1.c
字号:
/******************************************************************* uLan Communication - uL_DRV - multiplatform uLan driver ul_cps1.c - chip driver for USB2uLan device developed by Petr Smolik (C) Copyright 1996-2004 by Pavel Pisa - project originator http://cmp.felk.cvut.cz/~pisa (C) Copyright 1996-2004 PiKRON Ltd. http://www.pikron.com (C) Copyright 2002-2004 Petr Smolik The uLan driver project can be used and distributed in compliance with any of next licenses - GPL - GNU Public License See file COPYING for details. - LGPL - Lesser GNU Public License - MPL - Mozilla Public License - and other licenses added by project originator Code can be modified and re-distributed under any combination of the above listed licenses. If contributor does not agree with some of the licenses, he/she can delete appropriate line. WARNING: if you delete all lines, you are not allowed to distribute code or sources in any form. *******************************************************************//*******************************************************************//* usb2ulan device requests */#define U2U_PKT_BUF_SIZE 32 /* driver maximal supported packed size */#define U2U_MAX_MSG_INPR 4 /* maximal number of messages in progress */#define VENDOR_START_ULAN 0 /* Inform converter about uLan driver ready */#define VENDOR_STOP_ULAN 1 /* Inform about uLan driver stopping */#define VENDOR_IS_RUNNING_ULAN 2#define VENDOR_ARC_ON_ULAN 3 /* Set promiscuous monitoring mode */#define VENDOR_ARC_OFF_ULAN 4 /* Return to std. adress recognition mode */#define U2UBFL_NORE 0x040 /* Do not try to repeat if error occurs */ #define U2UBFL_TAIL 0x020 /* Message has tail frame */#define U2UBFL_REC 0x010 /* Request receiption of block */#define U2UBFL_FAIL 0x008 /* Message cannot be send - error */#define U2UBFL_PROC 0x004 /* Message succesfull send */#define U2UBFL_AAP 0x003 /* Request imediate proccessing of frame by receiver station with acknowledge */#define U2UBFL_PRQ 0x002 /* Request imediate proccessing of frame by receiver station */#define U2UBFL_ARQ 0x001 /* Request imediate acknowledge by receiving station *//* Definition of chip_buff usage */#define ul_usb_in_urb_st chip_buff[0] /* completion status of ?_complete_in */#define ul_usb_max_pkt_size chip_buff[1] /* maximal USB packet size */#define ul_usb_max_msg_inpr chip_buff[2] /* maximal number of messages in progress */#define ul_usb_outpipe_nr chip_buff[3] /* OUT pipe number */#define ul_usb_inpipe_nr chip_buff[4] /* IN pipe number */#ifdef FOR_LINUX_KERNEL#if (LINUX_VERSION_CODE <= VERSION(2,4,10)) #define usb_fill_bulk_urb FILL_BULK_URB#endif#if (LINUX_VERSION_CODE < VERSION(2,5,0)) #define kc_usb_alloc_urb(urb, gfp) usb_alloc_urb(urb) #define kc_usb_submit_urb(urb, gfp) usb_submit_urb(urb) #else #define kc_usb_alloc_urb usb_alloc_urb #define kc_usb_submit_urb usb_submit_urb#endif#endif /*FOR_LINUX_KERNEL*/#ifdef _WIN32int ul_usb_msg_inpr=0; /* number of concurrent messages sent over USB */#elseextern int ul_usb_msg_inpr; /* number of concurrent messages sent over USB */#endif /* _WIN32 *//* Support for multiple submitted messages */typedef struct ul_usb_tx_fifo_slot{ ul_mem_blk *msg; unsigned char ustamp;}ul_usb_tx_fifo_slot;typedef struct ul_usb_tx_fifo{ ul_usb_tx_fifo_slot slot[U2U_MAX_MSG_INPR]; int size; int used; int idxin; int idxout;}ul_usb_tx_fifo;static int ul_usb_tx_fifo_empty(const ul_usb_tx_fifo *fifo){ return fifo->slot[fifo->idxout].msg==NULL;}static int ul_usb_tx_fifo_full(const ul_usb_tx_fifo *fifo){ return fifo->slot[fifo->idxin].msg!=NULL;}static int ul_usb_tx_fifo_incidx(const ul_usb_tx_fifo *fifo, int idx){ if(++idx>=fifo->size) idx=0; return idx;}static void ul_usb_tx_fifo_print(const ul_usb_tx_fifo *fifo){ int i; LOG_MESSAGES("ul_usb: tx_fifo: idxin=%d idxout=%d [", fifo->idxin,fifo->idxout); for(i=0;i<fifo->size;i++){ if(i) LOG_MESSAGES(","); if(!fifo->slot[i].msg){ LOG_MESSAGES("Empty"); }else{ LOG_MESSAGES("%d",fifo->slot[i].ustamp); } } LOG_MESSAGES("]\n");}/*** Input completion for Petr Smolik's USB2uLan converter ***/#ifdef FOR_LINUX_KERNEL#if (LINUX_VERSION_CODE >= VERSION(2,6,0)) void ul_usb_ps1_complete_in(struct urb *urb,struct pt_regs *regs)#else void ul_usb_ps1_complete_in(struct urb *urb)#endif#else /*FOR_LINUX_KERNEL*/ NTSTATUS ul_usb_ps1_complete_in( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)#endif /*FOR_LINUX_KERNEL*/{ ul_drv *udrv; int st; #ifdef FOR_LINUX_KERNEL udrv=urb->context; #else /*FOR_LINUX_KERNEL*/ udrv=(ul_drv*)Context; #endif /*FOR_LINUX_KERNEL*/ if(udrv->magic!=UL_DRV_MAGIC){ LOG_FATAL(KERN_CRIT "ul_usb_ps1_complete_in: Wrong uLan MAGIC number!!!\n"); #ifdef _WIN32 return STATUS_INVALID_PARAMETER; #else /* _WIN32 */ return; #endif /* _WIN32 */ } #ifdef FOR_LINUX_KERNEL if(urb->status<0) st=16-urb->status; else st=2; #else st=2; #endif LOG_IRQ(KERN_CRIT "ul_usb_ps1_complete_in\n"); UL_MB(); udrv->ul_usb_in_urb_st=st; uld_kwt_wake(udrv); #ifdef _WIN32 return STATUS_SUCCESS; #endif /* _WIN32 */}/*** Send one frame to USB2uLan converter ***/int ul_usb_ps1_send_frame(ul_drv *udrv, ul_mem_blk *frame, unsigned char ustamp){ unsigned char buf[U2U_PKT_BUF_SIZE]; int i, len, ret; ul_data_it di; struct usb_device *dev=(struct usb_device *)udrv->dev; int max_pkt=udrv->ul_usb_max_pkt_size; buf[0]=UL_BLK_HEAD(frame).dadr; buf[1]=UL_BLK_HEAD(frame).sadr; buf[2]=UL_BLK_HEAD(frame).cmd; i=UL_BLK_HEAD(frame).flg; buf[3]=0; if(i&UL_BFL_ARQ) buf[3]|=U2UBFL_ARQ; if(i&UL_BFL_PRQ) buf[3]|=U2UBFL_PRQ; if(i&UL_BFL_NORE) buf[3]|=U2UBFL_NORE; if(i&UL_BFL_TAIL) buf[3]|=U2UBFL_TAIL; if(i&UL_BFL_REC) buf[3]|=U2UBFL_REC; buf[4]=ustamp; buf[5]=0; len=UL_BLK_HEAD(frame).len; if(i&UL_BFL_REC){ /* Placeholder message for receive does not */ len=0; /* need data, but should check UL_BFL_LNMM !!! */ } buf[6]=(unsigned char)len; buf[7]=(unsigned char)(len/0x100); LOG_IRQ(KERN_CRIT "ul_usb : sending head URB (d:%d,s:%d,c:%X,f:%X,l:%d) stmp %d\n", buf[0],buf[1],buf[2],buf[3], buf[6]+0x100*buf[7],buf[4]); ret=usb_bulk_msg(dev, usb_sndbulkpipe(dev, udrv->ul_usb_outpipe_nr), buf, 8, &i, ULD_HZ); if(ret<0) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_send_frame: usb_bulk_write head error %d returned\n",ret); return ret; } ul_di_init(&di,frame); while(len>0) { i=len<max_pkt?len:max_pkt; len-=i; ul_di_read(&di, buf, i); ret=usb_bulk_msg(dev, usb_sndbulkpipe(dev, udrv->ul_usb_outpipe_nr), buf, i, &i, ULD_HZ); if(ret<0) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_send_frame: usb_bulk_write data error %d returned\n",ret); return ret; } } return di.pos;}/*** Receive data of one frame from USB2uLan converter ***/int ul_usb_ps1_receive_data(ul_drv *udrv, ul_mem_blk *frame, int len){ unsigned char buf[U2U_PKT_BUF_SIZE]; int i, ret; ul_data_it di; struct usb_device *dev=(struct usb_device *)udrv->dev; int max_pkt=udrv->ul_usb_max_pkt_size; ul_di_init(&di,frame); while(len>0) { i=len<max_pkt?len:max_pkt; len-=i; ret=usb_bulk_msg(dev, usb_rcvbulkpipe(dev, udrv->ul_usb_inpipe_nr), buf, i, &i, ULD_HZ); if(ret<0) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: usb_bulk_read data error %d returned\n",ret); return ret; break; } else { if(i!=ul_di_write(&di, buf, i)){ #ifdef FOR_LINUX_KERNEL return -EIO; #else return -1; #endif /* FOR_LINUX_KERNEL */ } } } return di.pos;}/*** Worker thread for Petr Smolik's USB2uLan converter ***/int ul_usb_ps1_thread(void *ptr){ ul_drv *udrv=(ul_drv *)ptr; struct usb_device *dev; int ret; int i, len; int fatal_err=0; volatile unsigned char in_buf[8]; unsigned char u2u_ret[2]; unsigned char ustamp=0; ul_mem_blk *tx_mes=NULL; ul_mem_blk *rx_mes=NULL; ul_mem_blk *frame; ul_mem_blk *tail_frame=NULL; long tx_sta_time; ul_usb_tx_fifo tx_fifo; #ifdef FOR_LINUX_KERNEL struct urb *in_urb; #else PURB in_urb=NULL; PIRP in_irp=NULL; #endif /* FOR_LINUX_KERNEL */ volatile unsigned in_urb_st; if(udrv->magic!=UL_DRV_MAGIC) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: Wrong uLan MAGIC number!!!\n"); uld_kwt_set_stopped(udrv); return -ENODEV; } dev=(struct usb_device *)udrv->dev; if(udrv->ul_usb_max_pkt_size>U2U_PKT_BUF_SIZE) udrv->ul_usb_max_pkt_size=U2U_PKT_BUF_SIZE; if(udrv->ul_usb_max_msg_inpr>U2U_MAX_MSG_INPR) udrv->ul_usb_max_msg_inpr=U2U_MAX_MSG_INPR; memset(&tx_fifo,0,sizeof(tx_fifo)); tx_fifo.size=udrv->ul_usb_max_msg_inpr;#ifdef FOR_LINUX_KERNEL#if (LINUX_VERSION_CODE >= VERSION(2,6,0)) daemonize("kulusbps1d"); /*allow_signal(SIGKILL);*/#else /* <2.6.0 */ lock_kernel(); daemonize(); #if (LINUX_VERSION_CODE >= VERSION(2,4,10)) exit_files(current); current->files = init_task.files; atomic_inc(¤t->files->count); daemonize(); reparent_to_init(); #endif /* >=2.4.10 */ /* avoid getting signals */ spin_lock_irq(¤t->sigmask_lock); flush_signals(current); sigfillset(¤t->blocked); recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); set_fs(KERNEL_DS); strcpy(current->comm, "kulusbps1d"); unlock_kernel();#endif /* <2.6.0 */#endif /*FOR_LINUX_KERNEL*/ if(udrv->baud_val) udrv->baud_div=(udrv->baud_base+udrv->baud_val/2)/udrv->baud_val; /* Set converter parameters */ ret=usb_control_msg(dev, usb_rcvctrlpipe(dev,0), VENDOR_START_ULAN, USB_TYPE_VENDOR, /*value*/ (short)udrv->baud_val, /*index*/ (short)udrv->my_adr, u2u_ret, 1, 2*ULD_HZ); if(ret<0) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: KWT usb_control_msg error %d returned\n",ret); fatal_err=1; } if(!u2u_ret[0]) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: not supported baudrate (%d)\n",udrv->baud_val); fatal_err=1; } #ifdef FOR_LINUX_KERNEL if((in_urb=kc_usb_alloc_urb(0, GFP_KERNEL))) { /* URB allocated OK */ }else{ LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: KWT cannot alloc in_urb\n"); fatal_err=1; } #else in_urb = MALLOC(sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER)); if ( !in_urb) { LOG_FATAL(KERN_CRIT "ul_usb_ps1_thread: KWT cannot alloc in_urb\n"); fatal_err=1; } #endif /* FOR_LINUX_KERNEL */ usb_clear_halt(dev, usb_sndbulkpipe(dev, udrv->ul_usb_outpipe_nr)); usb_clear_halt(dev, usb_rcvbulkpipe(dev, udrv->ul_usb_inpipe_nr)); udrv->ul_usb_in_urb_st=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -