Ejemplo n.º 1
0
int16_t MeUSBHost::initHIDDevice()
{
  int16_t irq, len, address;
  if(usbtype==USB1_0) set_freq(); //work on a lower freq, necessary for ch375
  irq = get_desr(1);
#ifdef CH375_DBG
  Serial.printf("get des irq:%x\n",irq);
#endif
  if(irq==USB_INT_SUCCESS){
      len = rd_usb_data( RECV_BUFFER );
#ifdef CH375_DBG
      Serial.printf("descr1 len %d type %x\r\n",len,p_dev_descr->bDescriptorType);
#endif
      irq = set_addr(2);
      if(irq==USB_INT_SUCCESS){
        irq = get_desr(2); // max buf 64byte, todo:config descr overflow
        if(irq==USB_INT_SUCCESS){
          len = rd_usb_data( RECV_BUFFER );
#ifdef CH375_DBG
          Serial.printf("descr2 len %d class %x subclass %x\r\n",len,p_cfg_descr->itf_descr.bInterfaceClass, p_cfg_descr->itf_descr.bInterfaceSubClass); // interface class should be 0x03 for HID
          Serial.printf("num of ep %d\r\n",p_cfg_descr->itf_descr.bNumEndpoints);
          Serial.printf("ep0 %x %x\r\n",p_cfg_descr->endp_descr[0].bLength, p_cfg_descr->endp_descr[0].bDescriptorType);
#endif
          if(p_cfg_descr->endp_descr[0].bDescriptorType==0x21){ // skip hid des
            tmpEp = (PUSB_ENDP_DESCR)((int8_t*)(&(p_cfg_descr->endp_descr[0]))+p_cfg_descr->endp_descr[0].bLength); // get the real ep position
          }
#ifdef CH375_DBG
          Serial.printf("endpoint %x %x\r\n",tmpEp->bEndpointAddress,tmpEp->bDescriptorType);
#endif
          endp_out_addr=endp_in_addr=0;
          address =tmpEp->bEndpointAddress;  /* Address of First EndPoint */
          // actually we only care about the input end points
          if( address&0x80 ){
            endp_in_addr = address&0x0f;  /* Address of IN EndPoint */
          }else{  /* OUT EndPoint */
            endp_out_addr = address&0x0f;
            endp_out_size = p_cfg_descr->endp_descr[0].wMaxPacketSize;
			/* Length of Package for Received Data EndPoint */
            if( endp_out_size == 0 || endp_out_size > 64 )
              endp_out_size = 64;
          }
          // todo: some joystick with more than 2 node
          // just assume every thing is fine, bring the device up
          irq = set_config(p_cfg_descr->cfg_descr.bConfigurationvalue);
          if(irq==USB_INT_SUCCESS){
            CH375_WR( CMD_SET_RETRY );  // set the retry times
            CH375_WR( 0x25 );
            CH375_WR( 0x85 );
            device_ready = true;
            return 1;
          }
        }

      }
  }
  return 0;
}
Ejemplo n.º 2
0
unsigned char init_print() {  /* 初始化USB打印机,完成打印机枚举 */
#define	p_dev_descr		((PUSB_DEV_DESCR)buffer)
#define	p_cfg_descr		((PUSB_CFG_DESCR_LONG)buffer)
	unsigned char status, len, c;
	status=get_descr(1);  /* 获取设备描述符 */
	if ( status==USB_INT_SUCCESS ) {
		len=rd_usb_data( buffer );  /* 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中,返回描述符长度 */
		if ( len<18 || p_dev_descr->bDescriptorType!=1 ) return( UNKNOWN_USB_DEVICE );  /* 意外错误:描述符长度错误或者类型错误 */
		if ( p_dev_descr->bDeviceClass!=0 ) return( UNKNOWN_USB_DEVICE );  /* 连接的USB设备不是USB打印机,或者不符合USB规范 */
		status=set_addr(3);  /* 设置打印机的USB地址 */
		if ( status==USB_INT_SUCCESS ) {
			status=get_descr(2);  /* 获取配置描述符 */
			if ( status==USB_INT_SUCCESS ) {  /* 操作成功则读出描述符并分析 */
				len=rd_usb_data( buffer );  /* 将获取的描述符数据从CH375中读出到单片机的RAM缓冲区中,返回描述符长度 */
				if ( p_cfg_descr->itf_descr.bInterfaceClass!=7 || p_cfg_descr->itf_descr.bInterfaceSubClass!=1 ) return( UNKNOWN_USB_PRINT );  /* 不是USB打印机或者不符合USB规范 */
				endp_out_addr=endp_in_addr=0;
				c=p_cfg_descr->endp_descr[0].bEndpointAddress;  /* 第一个端点的地址 */
				if ( c&0x80 ) endp_in_addr=c&0x0f;  /* IN端点的地址 */
				else {  /* OUT端点 */
					endp_out_addr=c&0x0f;
					endp_out_size=p_cfg_descr->endp_descr[0].wMaxPacketSize;  /* 数据接收端点的最大包长度 */
				}
				if ( p_cfg_descr->itf_descr.bNumEndpoints>=2 ) {  /* 接口有两个以上的端点 */
					if ( p_cfg_descr->endp_descr[1].bDescriptorType==5 ) {  /* 端点描述符 */
						c=p_cfg_descr->endp_descr[1].bEndpointAddress;  /* 第二个端点的地址 */
						if ( c&0x80 ) endp_in_addr=c&0x0f;  /* IN端点 */
						else {  /* OUT端点 */
							endp_out_addr=c&0x0f;
							endp_out_size=p_cfg_descr->endp_descr[1].wMaxPacketSize;
						}
					}
				}
				if ( p_cfg_descr->itf_descr.bInterfaceProtocol<=1 ) endp_in_addr=0;  /* 单向接口不需要IN端点 */
				if ( endp_out_addr==0 ) return( UNKNOWN_USB_PRINT );  /* 不是USB打印机或者不符合USB规范 */
				status=set_config( p_cfg_descr->cfg_descr.bConfigurationValue );  /* 加载USB配置值 */
				if ( status==USB_INT_SUCCESS ) {
					CH375_WR_CMD_PORT( CMD_SET_RETRY );  /* 设置USB事务操作的重试次数 */
					CH375_WR_DAT_PORT( 0x25 );
					CH375_WR_DAT_PORT( 0x89 );  /* 位7为1则收到NAK时无限重试, 位3~位0为超时后的重试次数 */
/* 如果单片机在打印机忙时并无事可做,建议设置位7为1,使CH375在收到NAK时自动重试直到操作成功或者失败 */
/* 如果希望单片机在打印机忙时能够做其它事,那么应该设置位7为0,使CH375在收到NAK时不重试,
   所以在下面的USB通讯过程中,如果USB打印机正忙,issue_token等子程序将得到状态码USB_INT_RET_NAK */
				}
			}
		}
	}
	return(status);
}
Ejemplo n.º 3
0
unsigned char get_port_status_X( ) {  /* 查询打印机端口状态,返回状态码,如果为0FFH则说明操作失败,适用于CH375A */
/* 返回状态码中: 位5(Paper Empty)为1说明无纸, 位4(Select)为1说明打印机联机, 位3(Not Error)为0说明打印机出错 */
	buffer[0]=0xA1; buffer[1]=1; buffer[2]=buffer[3]=buffer[4]=buffer[5]=0; buffer[6]=1; buffer[7]=0;  /* 控制传输获取打印机状态,SETUP数据 */
	wr_usb_data( 8, buffer );  /* SETUP数据总是8字节 */
	if ( issue_token_X( ( 0 << 4 ) | DEF_USB_PID_SETUP, 0x00 )==USB_INT_SUCCESS ) {  /* SETUP阶段DATA0操作成功 */
		if ( issue_token_X( ( 0 << 4 ) | DEF_USB_PID_IN, 0x80 )==USB_INT_SUCCESS ) {  /* DATA阶段DATA1接收操作成功 */
			rd_usb_data( buffer );  /* 读出接收到的数据,通常只有1个字节 */
			wr_usb_data( 0, buffer );  /* 发送0长度的数据DATA1说明控制传输成功 */
			if ( issue_token_X( ( 0 << 4 ) | DEF_USB_PID_OUT, 0x40 )==USB_INT_SUCCESS ) return( buffer[0] );  /* STATUS阶段操作成功,返回状态码 */
		}
	}
	return( 0xFF );  /* 返回操作失败 */
}
Ejemplo n.º 4
0
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 );  /* 返回操作失败 */
}
Ejemplo n.º 5
0
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;
  }
}