// Check if device attached to port static int usb_hub_detect(struct usbhub_s *hub, u32 port) { // Turn on power to port. int ret = set_port_feature(hub, port, USB_PORT_FEAT_POWER); if (ret) goto fail; // Wait for port power to stabilize. msleep(hub->powerwait); // Check periodically for a device connect. struct usb_port_status sts; u64 end = calc_future_tsc(USB_TIME_SIGATT); for (;;) { ret = get_port_status(hub, port, &sts); if (ret) goto fail; if (sts.wPortStatus & USB_PORT_STAT_CONNECTION) // Device connected. break; if (check_tsc(end)) // No device found. return -1; msleep(5); } // XXX - wait USB_TIME_ATTDB time? return 0; fail: dprintf(1, "Failure on hub port %d detect\n", port); return -1; }
/* 主机端的主程序简单示例 */ main() { unsigned char xdata data_to_send[200]; /* 缓冲区 */ unsigned char str_to_print[]="OK, support text print\n"; unsigned char s; mDelaymS( 200 ); set_usb_mode( 6 ); /* 设置USB主机模式 */ while ( wait_interrupt()!=USB_INT_CONNECT ); /* 等待USB打印机连接上来 */ /* 如果设备端是CH341转打印口或者是CH37X,那么以下步骤是可选的,如果是其它USB芯片,那么可能需要执行以下步骤 */ #define USB_RESET_FIRST 1 /* USB规范中未要求在USB设备插入后必须复位该设备,但是计算机的WINDOWS总是这样做,所以有些USB设备也要求在插入后必须先复位才能工作 */ #ifdef USB_RESET_FIRST set_usb_mode( 7 ); /* 复位USB设备,CH375向USB信号线的D+和D-输出低电平 */ /* 如果单片机对CH375的INT#引脚采用中断方式而不是查询方式,那么应该在复制USB设备期间禁止CH375中断,在USB设备复位完成后清除CH375中断标志再允许中断 */ mDelaymS( 10 ); /* 复位时间不少于1mS,建议为10mS */ set_usb_mode( 6 ); /* 结束复位 */ mDelaymS( 100 ); while ( wait_interrupt()!=USB_INT_CONNECT ); /* 等待复位之后的设备端再次连接上来 */ #endif mDelaymS( 200 ); /* 有些USB设备要等待数百毫秒才能正常工作 */ if ( init_print()!=USB_INT_SUCCESS ) while(1); /* 错误 */ while ( 1 ) { s = get_port_status( ); if ( s!=0xFF ) { /* if ( s&0x20 ) printf("No paper!\n"); if ( (s&0x08) == 0 ) printf("Print ERROR!\n");*/ } send_data( strlen(str_to_print), str_to_print ); /* 输出数据给打印机,与通过并口方式输出一样 */ send_data( sizeof(data_to_send), data_to_send ); /* 输出的数据必须按照打印机的格式要求或者遵循打印描述语言 */ /* 可以再次继续发送数据或者接收数据 */ } }
/****************************************************************************** * Funcao: resetSDLC * * "Abre" e configura modem SDLC * * * * Retornos: POS_ERRO * * POS_SUCESS * ******************************************************************************/ STAT resetSDLC ( void ) { int i; char aux[16]; struct Opn_Blk mblk; if (stsSDLC == SDLC_RESETED) return POS_SUCESS; /* Se dispositivo resetado apenas retorna */ if (hComModem >= 0) /* Com modem Aberta */ { get_port_status (hComModem, aux); /* Obtem status do modem */ if ((aux[3] & 0x08) != 0) /* Portadora presente! */ { aux[0] = 0; /* derruba DTR & RTS */ set_serial_lines ( hComModem, aux ); } xmdm_hangup (hComModem, -1, 0); /* fecha antes de programar */ xmdm_close (hComModem, 0, 0); hComModem = -1; SVC_WAIT ( 100 ); } hComModem = open (DEV_COM3, 0); /* abertura */ debugH ("handle Modem:[%d]\n", hComModem); aux[0] = 0; /* derruba DTR & RTS */ set_serial_lines ( hComModem, aux ); /* * Define: Baud Rate + Paridade + protocolo */ mblk.rate = Rt_19200; mblk.format = Fmt_A7E1 | Fmt_DTR; mblk.protocol = P_char_mode; set_opn_blk ( hComModem, &mblk ); for (i = AT_INIT_SDLC; i <= AT_FIN_SDLC; i++) { if (ATCmdSDLC (i, 0) != POS_SUCESS) { debugH ("ERRO ATCMD\n", hComModem); return POS_ERRO; } } stsSDLC = SDLC_RESETED; return POS_SUCESS; }
static int hub_port_status(struct usb_device *dev, int port, u16 *status, u16 *change) { struct usb_hub *hub = usb_get_intfdata (dev->actconfig->interface); int ret; ret = get_port_status(dev, port + 1, &hub->status->port); if (ret < 0) dev_err (hubdev (dev), "%s failed (err = %d)\n", __FUNCTION__, ret); else { *status = le16_to_cpu(hub->status->port.wPortStatus); *change = le16_to_cpu(hub->status->port.wPortChange); ret = 0; } return ret; }
/****************************************************************************** * Funcao: sndSDLC * * envia bytes para o modem SDLC * * * * Retornos: POS_SUCESS - transmissao sem erros * * POS_ERRO - falha transmissao * * POS_CANCEL - timeout trasmissao * ******************************************************************************/ STAT sndSDLC ( char * inBuf, int sz ) { char xbuff[32]; ulong tempoCOM; int st; tempoCOM = COM_TIMEOUT * 1000; /* tempo em milisegundos */ tempoCOM += get_milli_sec (); /* hora de vencimento do timeout */ flushMDM (); /* elimina buffer interno de recebimento antes do envio */ while (sz > 0 && tempoCOM >= get_milli_sec ()) { for (st = 0; get_port_status (hComModem, xbuff) != 0 && st < 50; st++) { SVC_WAIT ( 20 ); } st = sz; /* tamanho do fragmento */ if (write (hComModem, inBuf, st) > 0) { /* OK. transferencia feita */ inBuf += st; sz -= st; } else /* FALHA. Houve algum problema */ { return POS_ERRO; } } if ( sz > 0 ) /* saida por time out */ return POS_CANCEL; tmoRespSDLC = read_ticks () + 60000l; /* aciona time-out de P2 */ return POS_SUCESS; }
// Reset device on port static int usb_hub_reset(struct usbhub_s *hub, u32 port) { int ret = set_port_feature(hub, port, USB_PORT_FEAT_RESET); if (ret) goto fail; // Wait for reset to complete. struct usb_port_status sts; u64 end = calc_future_tsc(USB_TIME_DRST * 2); for (;;) { ret = get_port_status(hub, port, &sts); if (ret) goto fail; if (!(sts.wPortStatus & USB_PORT_STAT_RESET)) break; if (check_tsc(end)) { warn_timeout(); goto fail; } msleep(5); } // Reset complete. if (!(sts.wPortStatus & USB_PORT_STAT_CONNECTION)) // Device no longer present return -1; return ((sts.wPortStatus & USB_PORT_STAT_SPEED_MASK) >> USB_PORT_STAT_SPEED_SHIFT); fail: dprintf(1, "Failure on hub port %d reset\n", port); usb_hub_disconnect(hub, port); return -1; }
/****************************************************************************** * Funcao: recvSDLC * * obtem bytes recebidos pelo modem SDLC * * * * Retornos: POS_SUCESS - transmissao sem erros * * POS_ERRO - falha transmissao * * POS_CANCEL - timeout trasmissao * ******************************************************************************/ STAT recvSDLC ( char * outBuf, int * sz ) { // Devido ao teste SDLC, funcao de recepcao esta em sua forma mais simples sem considerar tamanho de resposta ou protocolos... char respBuf[1024]; int ct = 0; if (!outBuf && !sz) return POS_ERRO; while (TRUE) { get_port_status ( hComModem, respBuf ); /* status da portadora */ if ((respBuf[3] & 0x08) == 0) /* Portadora NAO presente! caiu conexao*/ { debugH ("[recvSDLC]PORTADORA NAO PRESENTE\n"); return POS_CANCEL; } /* Verifica se ha dados no buffer fisico da COM. */ SVC_WAIT (20); get_port_status (hComModem, (char *)respBuf ); if (respBuf[0] == 0) /* NAO ha novos dados */ { if (read_ticks () < tmoRespSDLC) { continue; } else { debugH ("[recvSDLC]OCORREU TIMEOUT P2\n"); return POS_ERRO; /* excedeu time-out */ } } else break; /* chegou dados */ } /* Ha dados. Transfere para o buffer sincrono. */ *sz = 0; SVC_WAIT (1000); while ((ct = read (hComModem, &outBuf[*sz], 1024)) > 0) /* desconsiderado tratamento de fragmentos */ *sz += ct; /* desconsiderado tratamento de lixo */ if (*sz > 0) { debugH ("[recvSDLC]chegou [%d]bytes\n", *sz); return POS_SUCESS; } if (ct < 0) { debugH ("[recvSDLC]falha recepcao\n", *sz); return POS_CANCEL; } return POS_ERRO; }
/****************************************************************************** * Funcao: chk_sdlc * * "verifica status da conexao SDLC * * * * Retornos: POS_ERRO * * POS_SUCESS * ******************************************************************************/ STAT chk_sdlc ( void ) { struct Opn_Blk Com3ob; int status; int ct; char mdm_buff[42]; STAT ret; get_port_status (hComModem, mdm_buff); if ((mdm_buff[3] & DCD_ON) == 0) { ret = ATCmdSDLC (-1, 2); /* ainda nao conectado, obtem resposta */ debugH ("chk_sdlc-ret[0x%0.4X]\n", ret); if (ret == SDLC_ATCMD_TMO || ret == SDLC_CONNECTED) { if (read_ticks () < tmoDiscSDLC) return POS_SUCESS; /* discando... */ else /* time-out discagem */ { stsSDLC = SDLC_NO_ANSWER; return POS_ERRO; } } stsSDLC = ret; debugH ("[chk_sdlc]ERRO_DISC:stsSDLC=0x%0.4X\n", stsSDLC); return POS_ERRO; /* falha */ } debugH ("SDLC_CONECTADO\n"); /* portadora presente, trata outros sinais */ ct = 5; do { mdm_buff[0] = DTR_RTS_ON; status = set_serial_lines (hComModem, mdm_buff); SVC_WAIT (100); } while (status != 0 && --ct > 0); ct = 5; do { status = get_port_status (hComModem, mdm_buff); SVC_WAIT (20); } while ((mdm_buff[3] & CTS_ON) == 0 && --ct > 0); Com3ob.rate = Rt_19200; Com3ob.format = Fmt_SDLC | Fmt_DTR | Fmt_RTS; Com3ob.protocol = P_sdlc_mode; Com3ob.trailer.sdlc_parms.address = 0x30; Com3ob.trailer.sdlc_parms.option = P_sdlc_sec; ct = 5; do { status = set_opn_blk (hComModem, &Com3ob); SVC_WAIT (50); } while (status != 0 && --ct > 0); ct = 5; do { mdm_buff[0] = DTR_RTS_ON; status = set_serial_lines (hComModem, mdm_buff); SVC_WAIT (100); } while (status != 0 && --ct > 0); if (status == 0) status = 5; stsSDLC = SDLC_CONNECTED; debugH ("SDLC_SINCRONIZADO\n"); return ( POS_SUCESS ); /* conexao OK */ }