예제 #1
0
static int rkusb_write_sdram( struct rkusb_dev *dev )
{
        int pid;
        if( __rkusb_write_enable() ) {
                int max_len;
                if( DEV_OFFSET(dev) >= 0xc0000000 ) {
                        rkusb_normal_data_xfer( dev , NULL ); 
                        return RKUSB_CB_OK_NONE;
                }
                max_len = DEV_RWBUF_LENGTH( dev );
                if( max_len < DEV_LENGTH(dev) ) {
                            return RKUSB_CB_FAILD;
                }
                pid = DEV_PID( dev );
                if( pid ) {
                        dev->slave_task = find_task_by_pid( pid );
                        if(!dev->slave_task )
                                return RKUSB_CB_FAILD;
                        //rk28printk("%s::pid=%d,task=%s\n" , __func__ , pid , dev->slave_task->comm );
                } else {
                        dev->slave_task = current ;
                }
                /* bakeup real offset and length */
                dev->private_tmp = (void*)DEV_OFFSET(dev);
                dev->buf_nfill = DEV_LENGTH(dev);
                __rkusb_set_dest_or_source( dev , __rkusb_rwbuffer_start( dev ) );
                rkusb_normal_data_xfer( dev , rkusb_write_sdram_cb);
                return RKUSB_CB_OK_NONE;
        }
        return RKUSB_CB_FAILD;
}
예제 #2
0
static int rkusb_rw_file_cb( struct rkusb_dev *dev )
{
        FILE_INFO               *fi = rkusb_xfer_cmd_valid( dev );
        int data_in = DEV_DATA_IN(dev);
        int actual = dev->req_out->actual;
        if( data_in )
                actual = dev->req_in->actual;
        DEV_LENGTH( dev ) -= actual;
        //rk28printk("%s::remain len=0x%x,actual=0x%x\n" ,__func__, DEV_LENGTH(dev) ,actual );
        #if 0
        if( DEV_LENGTH(dev) > 0 ) {
                if(!fi || (fi->error && fi->error != - FI_ERR_CLEAR) ) { /* error !*/
                        __rkusb_set_dest_or_source( dev , rwb->buf );
                        rkusb_normal_data_xfer_max_size( dev , rkusb_rw_file_cb , 0X40000000 );
                        return RKUSB_CB_FAILD_CSW;
                } 
        }
        #endif
        /* 20091222,HSL@RK,write last packed */
        if( FI_WRITE(fi) ) {
                dev->buf_filled = 1;
        } else {
                dev->buf_filled = 0;
        }
        rkusb_wakeup_thread( dev );
        return RKUSB_CB_OK_NONE;
}
예제 #3
0
파일: rk28_usb.c 프로젝트: Tigrouzen/k1099
static int rkusb_reinit_req( struct rkusb_dev *dev,struct usb_ep* ep_in,struct usb_ep* ep_out ) 
{
                __rkusb_free_ep_req( dev->ep_in, dev->req_in );
                if( !ep_in )
                        return 0;
                dev->req_in = __rkusb_init_ep_req(dev, ep_in);
                dev->ep_in = ep_in;

                if( !dev->req_in )
                        return -ENOMEM;
                dev->req_in->complete = rkusb_complete_in;
#if 0                        
                buf = __rkusb_free_ep_req( dev->ep_out, dev->req_out);
                dev->req_out = __rkusb_init_ep_req(dev, ep_out , buf );
                dev->ep_out = ep_out;
                
                if( !dev->req_out ) {
                        if( buf )       
                                kfree( buf );
                        buf = __rkusb_free_ep_req( dev->ep_in, dev->req_in );
                        if( buf )       
                                kfree( buf );
                        return -ENOMEM;
                }
                dev->req_out->complete = rkusb_complete_out;
                DEV_LENGTH(dev) = RKUSB_BULK_CB_WRAP_LEN;
                rkusb_get_cb( dev , DEV_LENGTH(dev) );
#endif                
                return 0;
}
예제 #4
0
static int rkusb_xfer_file_path( struct rkusb_dev *dev )
{
        if( DEV_LENGTH(dev) < sizeof(FILE_INFO) || DEV_LENGTH(dev) > RKUSB_BUFFER_SIZE ) {
                return RKUSB_CB_FAILD;
        }
        rkusb_normal_data_xfer( dev , rkusb_xfer_file_path_cb );
        return RKUSB_CB_OK_NONE;
}
예제 #5
0
static int rkusb_xfer_read_filesize( struct rkusb_dev *dev )
{
        FILE_INFO               *fi = rkusb_xfer_cmd_valid( dev );
        if( !fi  || DEV_LENGTH(dev)  < sizeof(unsigned long ) ) {
                rkusb_xfer_error( fi , dev , -FI_ERR_CLEAR);
                return RKUSB_CB_FAILD;
        }
        rk28printk("read file size =0x%lx,trans len=%d\n" , fi->file_size , DEV_LENGTH(dev))
        rkusb_normal_data_xfer_onetime(dev , &fi->file_size);
        return RKUSB_CB_OK_NONE;
}
예제 #6
0
파일: rk28_usb.c 프로젝트: Tigrouzen/k1099
static int rkusb_get_lastcmd_result( struct rkusb_dev *dev )
{
        if( DEV_LENGTH(dev) != RKUSB_RESULT_LEN )
                return RKUSB_CB_FAILD;
        rkusb_normal_data_xfer_onetime( dev , &dev->cr );
        return RKUSB_CB_OK_NONE;
}
예제 #7
0
/*
 *  20100108,HSL@RK,new r/w sdram code. if not kernel space,read at thread one time.
 */
static int rkusb_do_read_sdram( struct rkusb_dev *dev )
{
        int r;
        char *dest = __rkusb_rwbuffer_start( dev );
        #if 0
        r= copy_from_user(dest , (void __user *) DEV_OFFSET( dev ),
                DEV_LENGTH(dev) );
        #else
        r = access_process_vm(dev->slave_task,  DEV_OFFSET( dev ), dest , DEV_LENGTH(dev) , 0);
        #endif
        rk28printk("%s::read task=%s,lba=0x%x,len=%d\n" , __func__ , dev->slave_task->comm,
                DEV_OFFSET( dev ) , DEV_LENGTH(dev));
        if( r  !=  DEV_LENGTH(dev)) {
                rk28printk("get user data error,task=%s,lba=0x%x,r=0x%x\n" , dev->slave_task->comm,DEV_OFFSET( dev ) , r);
        }
        rkusb_normal_data_xfer_onetime( dev , dest );
        return RKUSB_CB_OK_NONE;
}
예제 #8
0
static int rkusb_xfer_file( struct rkusb_dev *dev )
{
        FILE_INFO               *fi = rkusb_xfer_cmd_valid( dev );
        if( !fi || DEV_LENGTH(dev) > fi->file_size ||
                DEV_OFFSET(dev) > fi->file_size ||
                DEV_OFFSET(dev)+DEV_LENGTH(dev)>fi->file_size ) {
                rkusb_xfer_error( fi , dev , -EINVAL);
                return RKUSB_CB_FAILD;
        }
        #if 0
        if( FI_WRITE(fi) ) { /* write */
                dev->phase = RKUSB_PHASE_DATAOUT;
        } else {
                dev->phase = RKUSB_PHASE_DATAIN;
        }
        #endif
        rkusb_wakeup_thread( dev );
        return RKUSB_CB_OK_NONE;
}
예제 #9
0
/*
 * for cmd must run at task env.not irq env.
 */
static int rkusb_task_cmd( struct rkusb_dev *dev )
{
        int r = RKUSB_CB_FAILD;
        switch( DEV_FUNC(dev )) {
        case FUNC_TASKF_PING:
                /*20100108,HSL@RK, for get cb at complete out.*/
                DEV_LENGTH(dev) = RKUSB_BULK_CB_WRAP_LEN;
                r= RKUSB_CB_OK_NONE;
                break;
        default:
                break;
        }
        if( r != RKUSB_CB_FAILD )
                rkusb_wakeup_thread( dev );
        return r;
}
예제 #10
0
static int rkusb_get_task_cmd( struct rkusb_dev *dev )
{
        struct task_struct *p;
        int     pid = DEV_OFFSET(dev);
        if( DEV_LENGTH(dev) > DEV_RWBUF_LENGTH( dev ) )
                return RKUSB_CB_FAILD;
        if( pid == 0 )
                p = current ;
        else {
                p = find_task_by_pid( pid );
                if( !p )
                        return RKUSB_CB_FAILD;
        }
        dev->slave_task = p;
        return RKUSB_CB_OK_NONE;
}
예제 #11
0
static int rkusb_xfer_file_path_cb( struct rkusb_dev *dev )
{
        FILE_INFO       *fi = (FILE_INFO*)dev->req_out->buf;
        if( !fi || FI_INVALID(fi) || fi->size < sizeof(FILE_INFO) )
                return RKUSB_CB_FAILD_CSW;
        if( FI_WRITE(fi) && fi->file_size == 0 ) /* write */
                return RKUSB_CB_FAILD_CSW;
        fi = (FILE_INFO*)kmalloc( sizeof( FILE_INFO ), GFP_ATOMIC );
        memcpy( fi , dev->req_out->buf , dev->req_out->actual );
        fi->file = fi->private_data = NULL;
        fi->error = 0;
        if( !FI_WRITE(fi) ) { 
                fi->file_size = 0;
        }
        dev->private_tmp = fi;
        /*20100112,HSL@RK, for get cb at complete out.*/
        DEV_LENGTH(dev) = RKUSB_BULK_CB_WRAP_LEN;
        rkusb_wakeup_thread( dev );
        return RKUSB_CB_OK_NONE;
}
예제 #12
0
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;
}
예제 #13
0
static int rkusb_read_sdram( struct rkusb_dev *dev )
{
        int pid;
        if( __rkusb_read_enable() ) {
                if( DEV_OFFSET(dev) >= 0xc0000000 ) {
                        rkusb_normal_data_xfer( dev , NULL ); 
                        return RKUSB_CB_OK_NONE;
                }
                pid = DEV_PID( dev );
                if( pid ) {
                        dev->slave_task = find_task_by_pid( pid );
                        if(!dev->slave_task )
                                return RKUSB_CB_FAILD;
                        //rk28printk("%s::pid=%d,task=%s\n" , __func__ , pid , dev->slave_task->comm );
                } else {
                        dev->slave_task = current ;
                }
                if( dev->slave_task == current ){
                        char *dest = __rkusb_rwbuffer_start( dev );
                        int n = copy_from_user((void*)dest, (const void __user*)DEV_OFFSET(dev), DEV_LENGTH(dev));
                        if( !n ) {
                                rkusb_normal_data_xfer_onetime( dev , dest );
                                return RKUSB_CB_OK_NONE;
                        } else 
                                return RKUSB_CB_FAILD;
                }
                rkusb_wakeup_thread( dev );
                return RKUSB_CB_OK_NONE;
        }
        return RKUSB_CB_FAILD;
}
예제 #14
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;
}
예제 #15
0
파일: rk28_usb.c 프로젝트: Tigrouzen/k1099
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;
}
예제 #16
0
static int rkusb_write_sdram_cb( struct rkusb_dev *dev )
{
        DEV_LENGTH(dev) = RKUSB_BULK_CB_WRAP_LEN;
        rkusb_wakeup_thread( dev );
        return RKUSB_CB_OK_NONE;
}
예제 #17
0
파일: rk28_usb.c 프로젝트: Tigrouzen/k1099
static int rkusb_usb_command( struct rkusb_dev *dev )
{
        int r = RKUSB_CB_FAILD;
        rk28printk("%s::func=%d,len=%d\n" , __func__ , DEV_FUNC(dev),DEV_LENGTH(dev));
        switch( DEV_FUNC(dev) ) {
                case FUNC_UCMD_DEVREADY:
                        r = RKUSB_CB_OK_CSW;
                        break;
                case FUNC_UCMD_DISCONNECTMSC:
                        rk28_msc_switch( 0 );
                        r = RKUSB_CB_OK_CSW;
                        break;
                case FUNC_UCMD_SYSTEMINFO:
                        {
                        unsigned int off_len[2];
                        off_len[0] = (unsigned int)system_type;
                        off_len[1] = strlen(system_type)+1;
                        rkusb_normal_data_xfer_onetime(dev , off_len );
                        r = RKUSB_CB_OK_NONE;
                        }
                        break;
                case FUNC_UCMD_RESTART:
                        rk28printk("get restart cmd,lun=%d\n" , DEV_LUN(dev));
                        if( DEV_LUN(dev) == 0 ) { /* normal restart */
                                rk28_restart(0);
                        } else if( DEV_LUN(dev) == 1 ) { /* to loader rkusb */
                                rk28_restart(1);
                        }
                        break;
                case FUNC_UCMD_GETVERSION:
                        r = rkusb_ucmd_get_version( dev );
                        break;
                case FUNC_UCMD_GETCHIPINFO:
                        {
                        unsigned int off_len[2];
                        off_len[1] = kld_get_tag_data( 0X524B0000 , (void**)&off_len );
                        rkusb_normal_data_xfer_onetime(dev , off_len );
                        r = RKUSB_CB_OK_NONE;
                        }
                        break;
                case FUNC_UCMD_GETSN:
                        {
                        unsigned int off_len[2];
                        off_len[1] = kld_get_tag_data( 0X524B0006 , (void**)&off_len );
                        rkusb_normal_data_xfer_onetime(dev , off_len );
                        r = RKUSB_CB_OK_NONE;
                        }
                        break;
                case FUNC_UCMD_DEBUGINFO:
                        {
                        RKDEBUG_INFO      *dbi = DEV_FAST_ALLOC(dev,RKDEBUG_INFO);
                        dbi->size = sizeof(RKDEBUG_INFO);
                        dbi->adb_support = adb_support;
                        dbi->dbg_level = __rkusb_write_enable(dev)?2:(__rkusb_read_enable(dev)?1:0);
                        dbi->tr_length = dev->req_buf_length;
                        dbi->save_length = dev->buf_length;
                        dbi->save_buf = (unsigned long)__rkusb_rwbuffer_start(dev);
                        if( dev->fsg )
                                strcpy(dbi->cur_device,"msc");
                        else
                                strcpy(dbi->cur_device,"adb");
                        strcpy( dbi->cur_version,RKUSB_KVERSION);
                        #if 0
                        dbi->cmds[0]=K_FW_SDRAM_READ_10;
                        dbi->cmds[1]=K_FW_SDRAM_WRITE_10;
                        dbi->cmds[2]=K_FW_TRACE;
                        dbi->cmds[3]=K_FW_GETLOG;
                        dbi->cmds[4]=K_FW_FUNCALL;
                        dbi->cmds[5]=K_FW_GETSYMB;
                        dbi->cmds[6]=K_FW_GETRESULT;
                        dbi->cmds[7]=K_FW_USBCMD;
                        #endif
                        rkusb_normal_data_xfer_onetime(dev , dbi );
                        r = RKUSB_CB_OK_NONE;
                        }
                        break;
                 case FUNC_UCMD_OPENADB:
                        {
                        /* lun:0 close,1: open */
                        adb_function_enable(DEV_LUN(dev));
                        usb_vbus_status = 0; /* force to reconnect! */
                        r = RKUSB_CB_OK_CSW;
                        }
                        break;
                default:
                        break ;
        }
        return r;
}