/* 主机端的主程序简单示例 */ 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 ); /* 输出的数据必须按照打印机的格式要求或者遵循打印描述语言 */ /* 可以再次继续发送数据或者接收数据 */ } }
unsigned char issue_token_X( unsigned char endp_and_pid, unsigned char tog ) { /* 执行USB事务,适用于CH375A */ /* 执行完成后, 将产生中断通知单片机, 如果是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操作完成 */ }
unsigned char set_addr( unsigned char addr ) { /* 设置设备端的USB地址 */ unsigned char status; CH375_WR_CMD_PORT( CMD_SET_ADDRESS ); /* 设置USB设备端的USB地址 */ CH375_WR_DAT_PORT( addr ); /* 地址, 从1到127之间的任意值, 常用2到20 */ status=wait_interrupt(); /* 等待CH375操作完成 */ if ( status==USB_INT_SUCCESS ) { /* 操作成功 */ CH375_WR_CMD_PORT( CMD_SET_USB_ADDR ); /* 设置USB主机端的USB地址 */ CH375_WR_DAT_PORT( addr ); /* 当目标USB设备的地址成功修改后,应该同步修改主机端的USB地址 */ } mDelaymS( 5 ); return( status ); }
int lis2dw12_stream_read(struct sensor *sensor, sensor_type_t sensor_type, sensor_data_func_t read_func, void *read_arg, uint32_t time_ms) { struct lis2dw12 *lis2dw12; struct sensor_itf *itf; int rc; os_time_t time_ticks; os_time_t stop_ticks = 0; struct lis2dw12_private_driver_data *pdd; uint8_t fifo_samples; /* If the read isn't looking for accel data, don't do anything. */ if (!(sensor_type & SENSOR_TYPE_ACCELEROMETER)) { return SYS_EINVAL; } lis2dw12 = (struct lis2dw12 *)SENSOR_GET_DEVICE(sensor); itf = SENSOR_GET_ITF(sensor); pdd = &lis2dw12->pdd; undo_interrupt(&lis2dw12->intr); if (pdd->interrupt) { return SYS_EBUSY; } /* enable interrupt */ pdd->interrupt = &lis2dw12->intr; rc = enable_interrupt(sensor, lis2dw12->cfg.stream_read_interrupt); if (rc) { goto done; } if (time_ms != 0) { rc = os_time_ms_to_ticks(time_ms, &time_ticks); if (rc) { goto done; } stop_ticks = os_time_get() + time_ticks; } for (;;) { wait_interrupt(&lis2dw12->intr, pdd->int_num); fifo_samples = 1; while(fifo_samples > 0) { rc = lis2dw12_do_read(sensor, read_func, read_arg); if (rc) { goto done; } rc = lis2dw12_get_fifo_samples(itf, &fifo_samples); if (rc) { goto done; } } if (time_ms != 0 && OS_TIME_TICK_GT(os_time_get(), stop_ticks)) { break; } } done: /* disable interrupt */ pdd->interrupt = NULL; rc = disable_interrupt(sensor, lis2dw12->cfg.stream_read_interrupt); return rc; }
unsigned char set_config( unsigned char cfg ) { /* 设置设备端的USB配置 */ tog_send=tog_recv=0; /* 复位USB数据同步标志 */ CH375_WR_CMD_PORT( CMD_SET_CONFIG ); /* 设置USB设备端的配置值 */ CH375_WR_DAT_PORT( cfg ); /* 此值取自USB设备的配置描述符中 */ return( wait_interrupt() ); /* 等待CH375操作完成 */ }
unsigned char get_descr( unsigned char type ) { /* 从设备端获取描述符 */ CH375_WR_CMD_PORT( CMD_GET_DESCR ); CH375_WR_DAT_PORT( type ); /* 描述符类型, 只支持1(设备)或者2(配置) */ return( wait_interrupt() ); /* 等待CH375操作完成 */ }
unsigned char issue_token( unsigned char endp_and_pid ) { /* 执行USB事务 */ /* 执行完成后, 将产生中断通知单片机, 如果是USB_INT_SUCCESS就说明操作成功 */ CH375_WR_CMD_PORT( CMD_ISSUE_TOKEN ); CH375_WR_DAT_PORT( endp_and_pid ); /* 高4位目的端点号, 低4位令牌PID */ return( wait_interrupt() ); /* 等待CH375操作完成 */ }
unsigned char clr_stall( unsigned char endp_addr ) { /* USB通讯失败后,复位设备端的指定端点到DATA0 */ CH375_WR_CMD_PORT( CMD_CLR_STALL ); CH375_WR_DAT_PORT( endp_addr ); return( wait_interrupt() ); }
/* * Generic i2c master transfer entrypoint */ static int keywest_xfer( struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct keywest_chan* chan = i2c_get_adapdata(adap); struct keywest_iface* iface = chan->iface; struct i2c_msg *pmsg; int i, completed; int rc = 0; if (iface->state == state_dead) return -ENXIO; if (pmac_low_i2c_lock(iface->node)) return -ENXIO; /* Set adapter to standard mode */ iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; iface->cur_mode |= KW_I2C_MODE_STANDARD; completed = 0; for (i = 0; rc >= 0 && i < num;) { u8 addr; pmsg = &msgs[i++]; addr = pmsg->addr; if (pmsg->flags & I2C_M_TEN) { printk(KERN_ERR "i2c-keywest: 10 bits addr not supported !\n"); rc = -EINVAL; break; } pr_debug("xfer: chan: %d, doing %s %d bytes to 0x%02x - %d of %d messages\n", chan->chan_no, pmsg->flags & I2C_M_RD ? "read" : "write", pmsg->len, addr, i, num); /* Setup channel & clear pending irqs */ write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); write_reg(reg_isr, read_reg(reg_isr)); write_reg(reg_status, 0); iface->data = pmsg->buf; iface->datalen = pmsg->len; iface->state = state_addr; iface->result = 0; if (pmsg->flags & I2C_M_RD) iface->read_write = I2C_SMBUS_READ; else iface->read_write = I2C_SMBUS_WRITE; /* Set up address and r/w bit */ if (pmsg->flags & I2C_M_REV_DIR_ADDR) addr ^= 1; write_reg(reg_addr, (addr << 1) | ((iface->read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); #ifndef POLLED_MODE /* Arm timeout */ iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; add_timer(&iface->timeout_timer); #endif /* Start sending address & enable interrupt*/ write_reg(reg_ier, KW_I2C_IRQ_MASK); write_reg(reg_control, KW_I2C_CTL_XADDR); #ifdef POLLED_MODE pr_debug("using polled mode...\n"); /* State machine, to turn into an interrupt handler */ while(iface->state != state_idle) { u8 isr = wait_interrupt(iface); handle_interrupt(iface, isr); } #else /* POLLED_MODE */ pr_debug("using interrupt mode...\n"); wait_for_completion(&iface->complete); #endif /* POLLED_MODE */ rc = iface->result; if (rc == 0) completed++; pr_debug("transfer done, result: %d\n", rc); } /* Release sem */ pmac_low_i2c_unlock(iface->node); return completed; }
/* * SMBUS-type transfer entrypoint */ static s32 keywest_smbus_xfer( struct i2c_adapter* adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data* data) { struct keywest_chan* chan = i2c_get_adapdata(adap); struct keywest_iface* iface = chan->iface; int len; u8* buffer; u16 cur_word; int rc = 0; if (iface->state == state_dead) return -ENXIO; /* Prepare datas & select mode */ iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; switch (size) { case I2C_SMBUS_QUICK: len = 0; buffer = NULL; iface->cur_mode |= KW_I2C_MODE_STANDARD; break; case I2C_SMBUS_BYTE: len = 1; buffer = &data->byte; iface->cur_mode |= KW_I2C_MODE_STANDARD; break; case I2C_SMBUS_BYTE_DATA: len = 1; buffer = &data->byte; iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; break; case I2C_SMBUS_WORD_DATA: len = 2; cur_word = cpu_to_le16(data->word); buffer = (u8 *)&cur_word; iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; break; case I2C_SMBUS_BLOCK_DATA: len = data->block[0]; buffer = &data->block[1]; iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; break; default: return -1; } /* Turn a standardsub read into a combined mode access */ if (read_write == I2C_SMBUS_READ && (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB) { iface->cur_mode &= ~KW_I2C_MODE_MODE_MASK; iface->cur_mode |= KW_I2C_MODE_COMBINED; } /* Original driver had this limitation */ if (len > 32) len = 32; if (pmac_low_i2c_lock(iface->node)) return -ENXIO; pr_debug("chan: %d, addr: 0x%x, transfer len: %d, read: %d\n", chan->chan_no, addr, len, read_write == I2C_SMBUS_READ); iface->data = buffer; iface->datalen = len; iface->state = state_addr; iface->result = 0; iface->read_write = read_write; /* Setup channel & clear pending irqs */ write_reg(reg_isr, read_reg(reg_isr)); write_reg(reg_mode, iface->cur_mode | (chan->chan_no << 4)); write_reg(reg_status, 0); /* Set up address and r/w bit */ write_reg(reg_addr, (addr << 1) | ((read_write == I2C_SMBUS_READ) ? 0x01 : 0x00)); /* Set up the sub address */ if ((iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB || (iface->cur_mode & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED) write_reg(reg_subaddr, command); #ifndef POLLED_MODE /* Arm timeout */ iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; add_timer(&iface->timeout_timer); #endif /* Start sending address & enable interrupt*/ write_reg(reg_control, KW_I2C_CTL_XADDR); write_reg(reg_ier, KW_I2C_IRQ_MASK); #ifdef POLLED_MODE pr_debug("using polled mode...\n"); /* State machine, to turn into an interrupt handler */ while(iface->state != state_idle) { unsigned long flags; u8 isr = wait_interrupt(iface); spin_lock_irqsave(&iface->lock, flags); handle_interrupt(iface, isr); spin_unlock_irqrestore(&iface->lock, flags); } #else /* POLLED_MODE */ pr_debug("using interrupt mode...\n"); wait_for_completion(&iface->complete); #endif /* POLLED_MODE */ rc = iface->result; pr_debug("transfer done, result: %d\n", rc); if (rc == 0 && size == I2C_SMBUS_WORD_DATA && read_write == I2C_SMBUS_READ) data->word = le16_to_cpu(cur_word); /* Release sem */ pmac_low_i2c_unlock(iface->node); return rc; }