void soft_reset_print( ) { /* 控制传输:软复位打印机 */ tog_send=tog_recv=0; /* 复位USB数据同步标志 */ toggle_send( 0 ); /* SETUP阶段为DATA0 */ buffer[0]=0x21; buffer[1]=2; buffer[2]=buffer[3]=buffer[4]=buffer[5]=buffer[6]=buffer[7]=0; /* SETUP数据,SOFT_RESET */ wr_usb_data( 8, buffer ); /* SETUP数据总是8字节 */ if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_SETUP )==USB_INT_SUCCESS ) { /* SETUP阶段操作成功 */ toggle_recv( 1 ); /* STATUS阶段,准备接收DATA1 */ if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_IN )==USB_INT_SUCCESS ) return; /* STATUS阶段操作成功,操作成功返回 */ } }
unsigned char get_port_status( ) { /* 查询打印机端口状态,返回状态码,如果为0FFH则说明操作失败 */ /* 返回状态码中: 位5(Paper Empty)为1说明无纸, 位4(Select)为1说明打印机联机, 位3(Not Error)为0说明打印机出错 */ toggle_send( 0 ); /* 下面通过控制传输获取打印机的状态, SETUP阶段为DATA0 */ buffer[0]=0xA1; buffer[1]=1; buffer[2]=buffer[3]=buffer[4]=buffer[5]=0; buffer[6]=1; buffer[7]=0; /* SETUP数据,GET_PORT_STATUS */ wr_usb_data( 8, buffer ); /* SETUP数据总是8字节 */ if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_SETUP )==USB_INT_SUCCESS ) { /* SETUP阶段操作成功 */ toggle_recv( 1 ); /* DATA阶段,准备接收DATA1 */ if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_IN )==USB_INT_SUCCESS ) { /* DATA阶段操作成功 */ rd_usb_data( buffer ); /* 读出接收到的数据,通常只有1个字节 */ toggle_send( 1 ); /* STATUS阶段为DATA1 */ wr_usb_data( 0, buffer ); /* 发送0长度的数据说明控制传输成功 */ if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_OUT )==USB_INT_SUCCESS ) return( buffer[0] ); /* 返回状态码 */ } } return( 0xFF ); /* 返回操作失败 */ }
unsigned char MeUsb::host_recv() { unsigned char irq; toggle_recv(); irq = issue_token( ( endp_in_addr << 4 ) | DEF_USB_PID_IN ); if(irq==USB_INT_SUCCESS){ int len = rd_usb_data(RECV_BUFFER); #ifdef USB_DBG for(int i=0;i<len;i++){ // point hid device Serial.print("0x"); Serial.println((int)RECV_BUFFER[i],HEX); } Serial.println(); #endif stallCount = 0; return len; }else if(irq==USB_INT_DISCONNECT){ device_online = false; device_ready = false; #ifdef USB_DBG Serial.println("##### disconn #####"); #endif return 0; }else{ clr_stall6(); #ifdef USB_DBG Serial.println("##### stall #####"); #endif delay(10); /* stallCount++; if(stallCount>10){ device_online = false; device_ready = false; resetBus(); } */ return 0; } }
/* 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功 */ CH375_WR_CMD_PORT( CMD_ISSUE_TKN_X ); CH375_WR_DAT_PORT( tog ); /* 同步标志的位7为主机端点IN的同步触发位, 位6为主机端点OUT的同步触发位, 位5~位0必须为0 */ CH375_WR_DAT_PORT( endp_and_pid ); /* 高4位目的端点号, 低4位令牌PID */ return( wait_interrupt() ); /* 等待CH375操作完成 */ } void soft_reset_print( ) { /* 控制传输:软复位打印机 */ tog_send=tog_recv=0; /* 复位USB数据同步标志 */ toggle_send( 0 ); /* SETUP阶段为DATA0 */ buffer[0]=0x21; buffer[1]=2; buffer[2]=buffer[3]=buffer[4]=buffer[5]=buffer[6]=buffer[7]=0; /* SETUP数据,SOFT_RESET */ wr_usb_data( 8, buffer ); /* SETUP数据总是8字节 */ if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_SETUP )==USB_INT_SUCCESS ) { /* SETUP阶段操作成功 */ toggle_recv( 1 ); /* STATUS阶段,准备接收DATA1 */ if ( issue_token( ( 0 << 4 ) | DEF_USB_PID_IN )==USB_INT_SUCCESS ) return; /* STATUS阶段操作成功,操作成功返回 */ } } #define USB_INT_RET_NAK 0x2A /* 00101010B,返回NAK */ void send_data( unsigned short len, unsigned char *buf ) { /* 主机发送数据块,一次最多64KB */ unsigned char l, s; while( len ) { /* 连续输出数据块给USB打印机 */ toggle_send( tog_send ); /* 数据同步 */ l = len>endp_out_size?endp_out_size:len; /* 单次发送不能超过端点尺寸 */ wr_usb_data( l, buf ); /* 将数据先复制到CH375芯片中 */ s = issue_token( ( endp_out_addr << 4 ) | DEF_USB_PID_OUT ); /* 请求CH375输出数据 */ if ( s==USB_INT_SUCCESS ) { /* CH375成功发出数据 */ tog_send = ~ tog_send; /* 切换DATA0和DATA1进行数据同步 */ len-=l; /* 计数 */ buf+=l; /* 操作成功 */ } else if ( s==USB_INT_RET_NAK ) { /* USB打印机正忙,如果未执行SET_RETRY命令则CH375自动重试,所以不会返回USB_INT_RET_NAK状态 */ /* USB打印机正忙,正常情况下应该稍后重试 */ /* s=get_port_status( ); 如果有必要,可以检查是什么原因导致打印机忙 */ } else { /* 操作失败,正常情况下不会失败 */ clr_stall( endp_out_addr ); /* 清除打印机的数据接收端点,或者 soft_reset_print() */ /* soft_reset_print(); 打印机出现意外错误,软复位 */ tog_send = 0; /* 操作失败 */ } /* 如果数据量较大,可以定期调用get_port_status()检查打印机状态 */ } }