#include "gadget_chips.h"
-
+#ifdef CONFIG_ARCH_ROCKCHIP
+#include <linux/power_supply.h>
+#include <linux/reboot.h>
+#include <linux/syscalls.h>
+#endif
/*------------------------------------------------------------------------*/
#define FSG_DRIVER_DESC "Mass Storage Function"
amount = min(amount_left, FSG_BUFLEN);
amount = min((loff_t)amount,
curlun->file_length - file_offset);
+ /* kever@rk
+ * max size for dwc_otg ctonroller is 64(max pkt sizt) * 1023(pkt)
+ * because of the DOEPTSIZ.PKTCNT has only 10 bits
+ */
+ if((common->gadget->speed != USB_SPEED_HIGH)&&(amount >0x8000))
+ amount = 0x8000;
+
/* Wait for the next buffer to become available */
bh = common->next_buffhd_to_fill;
if (amount_left_to_req == 0)
get_some_more = 0;
+ /* kever@rk
+ * max size for dwc_otg ctonroller is 64(max pkt sizt) * 1023(pkt)
+ * because of the DOEPTSIZ.PKTCNT has only 10 bits
+ */
+ if((common->gadget->speed != USB_SPEED_HIGH)&&(amount >0x8000))
+ amount = 0x8000;
+
/*
* Except at the end of the transfer, amount will be
* equal to the buffer size, which is divisible by
mask, needs_medium, name);
}
+#ifdef CONFIG_ARCH_ROCKCHIP
+static void deferred_restart(struct work_struct *dummy)
+{
+ sys_sync();
+ kernel_restart("loader");
+}
+static DECLARE_WORK(restart_work, deferred_restart);
+
+typedef struct tagLoaderParam
+{
+ int tag;
+ int length;
+ char parameter[1];
+ int crc;
+} PARM_INFO;
+#define PARM_TAG 0x4D524150
+#define MSC_EXT_DBG 1
+extern int GetParamterInfo(char * pbuf , int len);
+
+/* the buf is bh->buf,it is large enough. */
+static char * get_param_tag( char* buf , const char* tag )
+{
+ PARM_INFO *pi;
+ int i;
+ char *pp = buf+256;
+ char *spp;
+ i = GetParamterInfo( pp , 1024 );
+ pi = (PARM_INFO*)pp;
+ if( pi->tag != PARM_TAG ){
+error_out:
+ printk("paramter error,tag=0x%x\n" , pi->tag );
+ return NULL;
+ }
+ if( pi->length+sizeof(PARM_INFO) > i ) {
+ GetParamterInfo( pp , pi->length+sizeof(PARM_INFO) + 511 );
+ }
+ pp = strstr( pi->parameter , tag );
+ if( !pp )
+ goto error_out;
+ pp += strlen(tag); // sizeof "MACHINE_MODEL:"
+ while( *pp == ' ' || *pp == '\t' ) {
+ if(pp - pi->parameter >= pi->length)
+ break;
+ pp++;
+ }
+ spp = pp;
+ while( *pp != 0x0d && *pp != 0x0a ) {
+ if(pp - pi->parameter >= pi->length)
+ break;
+ pp++;
+ }
+ *pp = 0;
+ if( spp == pp ) return NULL;
+ return spp;
+}
+
+static int do_get_product_name(int ret ,char *buf)
+{
+ char *tag = "MACHINE_MODEL:";
+ char *pname;
+#if MSC_EXT_DBG
+ char tbuf[1300];
+ if( buf == NULL ) buf = tbuf;
+#endif
+ memset( buf , 0 , ret );
+ pname = get_param_tag( buf , tag );
+ if( pname ){
+ strcpy( buf , pname);
+ }
+#if MSC_EXT_DBG
+ printk("%s%s\n" , tag , buf );
+#endif
+ return ret;
+}
+
+static int do_get_versions( int ret ,char* buf )
+{
+ /* get boot version and fireware version from cmdline
+ * bootver=2010-07-08#4.02 firmware_ver=1.0.0 // Firmware Ver:16.01.0000
+ * return format: 0x02 0x04 0x00 0x00 0x00 0x01
+ * RK29: bootver=2011-07-18#2.05 firmware_ver=0.2.3 (==00.02.0003)
+ * for the old loader,the firmware_ver may be empty,so get the fw ver from paramter.
+ */
+#define ASC_BCD0( c ) (((c-'0'))&0xf)
+#define ASC_BCD1( c ) (((c-'0')<<4)&0xf0)
+
+ char *ver = buf;
+ char *p_l , *p_f;
+ char *l_tag = "bootver=";
+ char *fw_tag = "FIRMWARE_VER:";
+
+#if MSC_EXT_DBG
+ char tbuf[1300];
+ if( ver == NULL )
+ ver = tbuf;
+#endif
+
+ memset( ver , 0x00 , ret );
+ p_l = strstr( saved_command_line , l_tag );
+ if( !p_l ) {
+ return ret;
+ }
+ p_l+=strlen( l_tag );
+ if( (p_l = strchr( p_l,'#')) ) {
+ p_l++;
+ if( p_l[1] == '.' ) {
+ ver[1] = ASC_BCD0(p_l[0]);
+ p_l+=2;
+ } else {
+ ver[1] = ASC_BCD1(p_l[0])|ASC_BCD0(p_l[1]);
+ p_l+=3;
+ }
+ ver[0] = ASC_BCD1(p_l[0])|ASC_BCD0(p_l[1]);
+ }
+
+ p_f = get_param_tag( ver , fw_tag );
+ if( !p_f ) return ret;
+
+ if( p_f[1] == '.' ) {
+ ver[5] = ASC_BCD0(p_f[0]);
+ p_f+=2;
+ } else {
+ ver[5] = ASC_BCD1(p_f[0])|ASC_BCD0(p_f[1]);
+ p_f+=3;
+ }
+ if( p_f[1] == '.' ) {
+ ver[4] = ASC_BCD0(p_f[0]);
+ p_f+=2;
+ } else {
+ ver[4] = ASC_BCD1(p_f[0])|ASC_BCD0(p_f[1]);
+ p_f+=3;
+ }
+ ver[2] = ASC_BCD0(p_f[0]);
+ p_f++;
+ if( p_f[0] != ' ' ){
+ ver[2] |= ASC_BCD1(p_f[0]);
+ p_f++;
+ }
+ // only support 2 byte version.
+ ver[3] = 0;
+
+#if MSC_EXT_DBG
+ printk("VERSION:%02x %02x %02x %02x %02x %02x\n" ,
+ ver[0],ver[1],ver[2],ver[3],ver[4],ver[5]);
+#endif
+ return ret;
+}
+
+#endif
+
static int do_scsi_command(struct fsg_common *common)
{
struct fsg_buffhd *bh;
int reply = -EINVAL;
int i;
static char unknown[16];
+#ifdef CONFIG_ARCH_ROCKCHIP
+ struct fsg_common *fsg = common;
+#endif
dump_cdb(common);
(1<<1) | (0xf<<2) | (3<<7), 1,
"VERIFY");
if (reply == 0)
+#ifdef CONFIG_ARCH_ROCKCHIP
+ reply = 0; //zyf 20100302
+#else
reply = do_verify(common);
+#endif
break;
case WRITE_6:
reply = -EINVAL;
}
break;
+#ifdef CONFIG_ARCH_ROCKCHIP
+ case 0xff:
+ if( fsg->cmnd[1] != 0xe0 ||
+ fsg->cmnd[2] != 0xff || fsg->cmnd[3] != 0xff ||
+ fsg->cmnd[4] != 0xff )
+ break;
+ if (fsg->cmnd_size >= 6 && fsg->cmnd[5] == 0xfe) {
+ schedule_work(&restart_work);
+ }else if ( fsg->cmnd[5] == 0xf3 ) {
+ fsg->data_size_from_cmnd = fsg->data_size;
+ /* get product name from parameter section */
+ reply = do_get_product_name( fsg->data_size,bh->buf );
+ }else if ( fsg->cmnd[5] == 0xff ){
+ fsg->data_size_from_cmnd = fsg->data_size;
+ reply = do_get_versions( fsg->data_size,bh->buf );
+ }
+ break;
+#endif
}
up_read(&common->filesem);