2011年1月10日 星期一

dnw on linux

DNW是Samsung提供的軟體, 讓我們能透過USB做檔案傳輸, 原本Samsung只提供了Windows版本, 而網路上的不知名高手亦將DNW porting到Linux上.

藉由前人的努力, 現在想在Linux上跑DNW只要簡單幾個步驟
1. Download dnw2 source code
2. Add checksum in dnw2 and compile it

This source code is come from am8 and patched by cyl's blog
/* dnw2 linux main file. This depends on libusb.
 *
 * Author:   Fox <hulifox008@163.com>
 * License:  GPL
 *
 */

#include <stdio.h>
#include <usb.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define    IDEA6410_SECBULK_IDVENDOR   0x04e8
#define    IDEA6410_SECBULK_IDPRODUCT  0x1234

struct usb_dev_handle * open_port()
{
  struct usb_bus *busses, *bus;

  usb_init();
  usb_find_busses();
  usb_find_devices();

  busses = usb_get_busses();
  for(bus=busses;bus;bus=bus->next)
  {
     struct usb_device *dev;
    for(dev=bus->devices;dev;dev=dev->next)
    {
      if( IDEA6410_SECBULK_IDVENDOR==dev->descriptor.idVendor
      &&  IDEA6410_SECBULK_IDPRODUCT==dev->descriptor.idProduct)
      {
        printf("Target usb device found!\n");
        struct usb_dev_handle *hdev = usb_open(dev);
        if(!hdev)
        {
          perror("Cannot open device"); 
        }
        else
        {
          if(0!=usb_claim_interface(hdev, 0))
          {
            perror("Cannot claim interface");
            usb_close(hdev);
            hdev = NULL;
          }
        }
        return hdev;
      }
    }
  }
 
  printf("Target usb device not found!\n");

  return NULL;
}

void usage()
{
  printf("Usage: dnw2 <file>\n\n");
}

unsigned char* prepare_write_buf(char *filename, unsigned int *len)
{
  unsigned char *write_buf = NULL;
  struct stat fs;

  int fd = open(filename, O_RDONLY);
  if(-1==fd)
  {
    perror("Cannot open file");
    return NULL;
  }
  if(-1==fstat(fd, &fs))
  {
    perror("Cannot get file size");
    goto error;
  }
  write_buf = (unsigned char*)malloc(fs.st_size+10);
  if(NULL==write_buf)
  {
    perror("malloc failed");
    goto error;
  }

  if(fs.st_size != read(fd, write_buf+8, fs.st_size))
  {
    perror("Reading file failed");
    goto error;
  }

  printf("Filename : %s\n", filename);
  printf("Filesize : %d bytes\n", fs.st_size);

  *((u_int32_t*)write_buf) = 0x30000000;    //download address
  *((u_int32_t*)write_buf+1) = fs.st_size + 10;  //download size;

  //cy: compute checksum
  int k;
  u_int16_t csum=0;
  for(k=0; k<(int)fs.st_size; k++){
    csum +=write_buf[8+k];
  }
  printf("CheckSum=%d\n",(int)csum);

  write_buf[fs.st_size+ 8] = csum; //checksum;
  write_buf[fs.st_size+ 9] = csum>>8; //checksum;
  // end of checksum

  *len = fs.st_size + 10;
  return write_buf;

error:
  if(fd!=-1) close(fd);
  if(NULL!=write_buf) free(write_buf);
  fs.st_size = 0;
  return NULL;
 
}

int main(int argc, char *argv[])
{
  if(2!=argc)
  {
    usage();
    return 1;
  }

  struct usb_dev_handle *hdev = open_port();
  if(!hdev)
  {
    return 1;
  }

  unsigned int len = 0;
  unsigned char* write_buf = prepare_write_buf(argv[1], &len);
  if(NULL==write_buf) return 1;

  unsigned int remain = len;
  unsigned int towrite;
  printf("Writing data ...\n");
  while(remain)
  {
    towrite = remain>512 ? 512 : remain;
    if(towrite != usb_bulk_write(hdev, 0x2, write_buf+(len-remain), towrite, 3000))
    {
      perror("usb_bulk_write failed");
      break;
    }
    remain-=towrite;
    printf("\r%d%\t %d bytes     ", (len-remain)*100/len, len-remain);
    fflush(stdout);
  }
  if(0==remain) printf("Done!\n");
  return 0;
}
當換版子時, 可能會改的地方有USB的VID/PID 跟 download address
USB資訊可透過lsusb得到, 而download address可能需要找data sheet裡面RAM的起始位址

3. Execute dnw2 to send file to target board
sudo dnw2 file_name

參考資料:
[1] linux 上的dnw程式
[2] Linux下用USB传输文件到开发板

沒有留言:

張貼留言