static int rkusb_do_task_cmd( struct rkusb_dev *dev ) { switch( DEV_FUNC(dev )) { case FUNC_TASKF_PING: rkusb_send_csw( dev , RKUSB_STATUS_PASS ); break; default: return RKUSB_CB_FAILD; } return RKUSB_CB_OK_NONE; }
/* * call at main thread. */ static int rkusb_file_path( struct rkusb_dev *dev ) { FILE_INFO *fi = (FILE_INFO*)dev->private_tmp; struct file *fp; struct inode *inode = NULL; int flags ; if( FI_WRITE(fi) ) { /* write */ flags = O_TRUNC|O_CREAT|O_WRONLY; } else { flags = O_RDONLY; } fp = filp_open(fi->file_path , flags , (fi->mod&0777) ); rk28printk("%s::open file %s ,rw=0x%x,mod=0%o\n" , __func__ , fi->file_path , fi->rw , fi->mod ); if (IS_ERR(fp)) { fi->error = (int)fp; printk("%s::unable to open file: %s,ret=%d\n",__func__ , fi->file_path , fi->error ); goto failed; } if( !FI_WRITE(fi) ) { /* file read ,get file size */ inode = fp->f_path.dentry->d_inode; if( !inode || !S_ISREG( inode->i_mode ) ) { fi->error = -EINVAL; fput( fp ); goto failed; } fi->mod = inode->i_mode; fi->file_size = (unsigned long)i_size_read(inode); /* 20100115,HSL@RK,for sysfs,procfs ,the size will be zero or not right */ if( !fi->file_size && (!strncmp(fi->file_path,"/proc/" , 6)||!strncmp(fi->file_path,"/sys/" , 5))) { //fi->mod |= FILE_MOD_TREAT; fi->file_size = PAGE_SIZE; } } fi->file = fp; rkusb_send_csw( dev , RKUSB_STATUS_PASS ); return 0; failed: rkusb_send_csw( dev , RKUSB_STATUS_FAIL ); return -1; }
static int rkusb_do_write_sdram( struct rkusb_dev *dev ) { int r; int status = RKUSB_STATUS_PASS; char *src = __rkusb_rwbuffer_start( dev ); rk28printk("%s::copy to user,task=%s,lba=0x%p,len=0x%x\n" , __func__ , dev->slave_task->comm, dev->private_tmp , dev->buf_nfill ); if( dev->slave_task == current ) { r= copy_to_user((void __user *) dev->private_tmp, src , dev->buf_nfill ); if( r ) status = RKUSB_STATUS_FAIL; } else { r = access_process_vm(dev->slave_task,(unsigned long)dev->private_tmp, src , dev->buf_nfill , 1 ); if( r != dev->buf_nfill ) { status = RKUSB_STATUS_FAIL; rk28printk("set user data error,task=%s,lba=0x%p,r=0x%x\n" , dev->slave_task->comm, dev->private_tmp, r); } } rkusb_send_csw( dev , status); return RKUSB_CB_OK_NONE; }
static int rkusb_do_thread_cmd( struct rkusb_dev *dev ) { rk28printk("rkusb thread cmd = 0x%x,func=0x%x,len=%d\n" , DEV_CMD(dev),DEV_FUNC(dev) , DEV_LENGTH(dev)); switch( DEV_CMD(dev)) { #if RKUSB_XFILE case K_FW_XFERFILE: { FILE_INFO *fi = rkusb_xfer_cmd_valid( dev ); if( !fi ) { rk28printk("invalid FILE_INFO for K_FW_XFERFILE[0x%x]\n" , K_FW_XFERFILE ); break; } switch( DEV_FUNC(dev )) { case FUNC_XFER_FILE_PATH: rkusb_file_path( dev ); break; case FUNC_RFILE_DATA: case FUNC_WFILE_DATA: rkusb_xfer_file_task( dev ); break; default: break; } if( fi->error ) rkusb_xfer_free_fi( dev ); } break; #endif /* RKUSB_XFILE */ case K_FW_TASKFUN: rkusb_do_task_cmd( dev ); break; case K_FW_SDRAM_READ_10: rkusb_do_read_sdram( dev ); break; case K_FW_SDRAM_WRITE_10: rkusb_do_write_sdram( dev ); break; case K_FW_FUNCALL: rkusb_do_func_call( dev ); break; case K_FW_USBCMD : if(FUNC_UCMD_RKUSBVER== DEV_FUNC(dev ) && (DEV_OFFSET(dev) == ECC_SWITCH_MSC || DEV_OFFSET(dev) == ECC_RESET) ) { char cmd[32]; char *p=(char *)DEV_INREQ_BUF(dev); strncpy( cmd , p , sizeof(cmd) ); rkusb_send_csw( dev , RKUSB_STATUS_PASS ); mdelay(10); sys_sync(); kernel_restart( cmd ); } else { rkusb_send_csw( dev , RKUSB_STATUS_FAIL ); } break; default: return -ENOTSUPP; break; } return 0; }
/* * 20091221,add file offset for large file. */ static int rkusb_xfer_file_task( struct rkusb_dev *dev ) { int nread; int mount; int total; int real_tranfs; FILE_INFO *fi = (FILE_INFO*)dev->private_tmp; char *buf_bak; loff_t pos = DEV_OFFSET(dev); real_tranfs = mount = __rkusb_rwbuffer_end(dev) -__rkusb_rwbuffer_start(dev); dev->buf_filled = 0; fi->error = 0; total = 0; if( FI_WRITE(fi) ) buf_bak = rkusb_reset_req_buf(dev->req_out,dev->buf); else buf_bak = rkusb_reset_req_buf(dev->req_in,dev->buf);; for(; ;) { if (signal_pending(current)) break; if( FI_WRITE(fi) ) { if( DEV_LENGTH( dev ) < mount ) { //mount = DEV_LENGTH( dev ) ; real_tranfs = DEV_LENGTH( dev ) ; //rk28printk("vfs r/w last pack , len =0x%x\n" , real_tranfs ); } //rk28printk("total write=0x%x,remain=0x%x,file size=0x%lx,mount=0x%x\n" , // total , DEV_LENGTH(dev) , fi->file_size , mount ); #if 1 rkusb_get_data_buffer( dev , mount , rkusb_rw_file_cb ); #else //__rkusb_set_dest_or_source( dev , rwb->buf ); rkusb_normal_data_xfer_max_size( dev , rkusb_rw_file_cb , mount); #endif while( !dev->buf_filled ) { rkusb_sleep_thread( dev ); } if( fi->error ) break; nread = vfs_write(fi->file, dev->buf , real_tranfs ,&pos); if( nread < 0 ) { rk28printk("vfs write failed , ret =%d\n" , nread ); fi->error = nread; } else { dev->buf_filled = 0; total += nread; } if( DEV_LENGTH( dev ) == 0 ) break; } else { //rk28printk("total read=0x%x,remain=0x%x,file size=0x%lx,mount=0x%x\n" , // total , DEV_LENGTH(dev) , fi->file_size , mount ); while( dev->buf_filled ) { rkusb_sleep_thread( dev ); } if( fi->error ) break; if( DEV_LENGTH( dev ) == 0 ) break; nread = vfs_read(fi->file, dev->buf , real_tranfs ,&pos); if( nread < 0 ) { rk28printk("vfs read failed , ret =%d\n" , nread ); fi->error = nread; } else { dev->buf_filled = 1; total += nread; if( nread < real_tranfs && total < fi->file_size ) { /* 20100115,HSL@RK,set 0 at pc tools */ //rwb->buf[nread] = 0; //if( real_tranfs - nread > 5 ) // strcpy(rwb->buf+nread+1,"@#$"); nread = real_tranfs; } } //rk28printk("read finish,nread=0x%x,start transfer,real transfer=0x%x\n" , // nread , real_tranfs ); #if 1 rkusb_send_data_buffer( dev , nread , rkusb_rw_file_cb ); #else __rkusb_set_dest_or_source( dev , rwb->buf ); rkusb_normal_data_xfer_max_size( dev , rkusb_rw_file_cb , mount); #endif } } rk28printk("file transfer finish,error=%d\n" , fi->error ); if( FI_WRITE(fi) ) { rkusb_reset_req_buf(dev->req_out , buf_bak); rkusb_get_cb( dev , RKUSB_BULK_CB_WRAP_LEN ); } else rkusb_reset_req_buf(dev->req_in , buf_bak); /* close file , free FILE_INFO */ if( !fi->error ) { fi->error = - FI_ERR_CLEAR; rkusb_send_csw( dev , RKUSB_STATUS_PASS ); } else { rkusb_send_csw( dev , RKUSB_STATUS_FAIL ); } return 0; }
static int rkusb_command( struct rkusb_dev *dev ) { int r= RKUSB_CB_FAILD; //dev->cb.DataTransferLength = __be32_to_cpu( dev->cb.DataTransferLength ); //dev->cb.Lba = __be32_to_cpu( dev->cb.Lba ); //dev->cb.pid = __be16_to_cpu( dev->cb.pid ); rkusb_print_cb( dev ); if( DEV_LENGTH(dev) > dev->req_buf_length ){ rk28printk("data length[0x%x] > limit[0x%x]\n" , DEV_LENGTH(dev),dev->req_buf_length); DEV_LENGTH(dev) = dev->req_buf_length; } //dev->thread_task->mm = NULL; dev->slave_task = NULL; switch ( DEV_CMD(dev) ) { case K_FW_GETRESULT: r = rkusb_get_lastcmd_result( dev ); break; case K_FW_GETLOG: r = rkusb_get_log( dev ); break; case K_FW_SETLOG: r = rkusb_set_log( dev ); break; case K_FW_TRACE: r = rkusb_do_trace( dev ); break; case K_FW_USBCMD: r = rkusb_usb_command( dev ); break; case K_FW_XFERFILE: r = rkusb_do_xfer_file( dev ); break; case K_FW_FUNCALL: r = rkusb_function_call( dev ); break; case K_FW_SDRAM_READ_10: r = rkusb_read_sdram( dev ); break; case K_FW_SDRAM_WRITE_10: r = rkusb_write_sdram( dev ); break; case K_FW_GETSYMB: r = rkusb_get_symbol( dev ); break; case K_FW_TASKFUN: r = rkusb_task_cmd( dev ); break; default: return RKUSB_NOT_HANDLED; } if( RKUSB_CB_FAILD == r ) { /* 20100330,HSL@RK,for failed cmd,must handle it */ DEV_OFFSET(dev) = 0; rkusb_normal_data_xfer( dev , rkusb_failed_cb ); return 0 ; /* RKUSB_NOT_HANDLED;*/ } else if( RKUSB_CB_OK_CSW == r ) rkusb_send_csw( dev , RKUSB_STATUS_PASS ); else if( RKUSB_CB_FAILD_CSW == r ) rkusb_send_csw( dev , RKUSB_STATUS_FAIL); return 0; }