Current directory :
Root directory

Tree directory :
ilya.muromec@jabber.ru
  Filter :
  Language :  
 
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
 
#include <linux/moto_accy.h>
#include <linux/power_ic.h>
#include <linux/ezxusbd.h>
#include <linux/apm_bios.h>
 
// battery voltage
enum {
  VOLTAGE_MIN,
  VOLTAGE_405 = VOLTAGE_MIN,
  VOLTAGE_410,
  VOLTAGE_415,
  VOLTAGE_420,
  VOLTAGE_425,
  VOLTAGE_430,
  VOLTAGE_380,
  VOLTAGE_450,
  VOLTAGE_MAX = VOLTAGE_450
};
 
// charger current
enum {
  CURRENT_MIN,
  CURRENT_0 = CURRENT_MIN,
  CURRENT_100,
  CURRENT_200,
  CURRENT_300,
  CURRENT_400,
  CURRENT_500,
  CURRENT_600,
  CURRENT_700,
  CURRENT_800,
  CURRENT_900,
  CURRENT_1000,
  CURRENT_1100,
  CURRENT_1200,
  CURRENT_1300,
  CURRENT_1800,
  CURRENT_MAX
};
 
// control fds  
int apm,usb,accy,power;
 
// TODO: config 
bool usb_charge = false;
 
bool charging;
 
// motorola 2.4 kernel charge current and voltage setting
int set_charge_current(int current) {
  return ioctl(power,POWER_IC_IOCTL_CHARGER_SET_CHARGE_CURRENT,current);
}
 
int set_charge_voltage(int voltage) {
  return ioctl(power,POWER_IC_IOCTL_CHARGER_SET_CHARGE_VOLTAGE,voltage);
}
 
int battery() {
  POWER_IC_ATOD_REQUEST_BATT_AND_CURR_T info; 
  info.timing = 0;
 
  ioctl (power,POWER_IC_IOCTL_ATOD_BATT_AND_CURR,&info);
  return info.batt_result;
}
 
void charge_alarm(int sig);
 
void charger(int current, int voltage) {
  int ret;
  ret = set_charge_current(current);
  printf("current set: %d, ret: %d\n",current,ret);
  set_charge_voltage(voltage);
  printf("voltage set: %d, ret: %d\n",voltage,ret);
 
  if (current)  {
    int flag = open("/tmp/charging", O_CREAT);
    close(flag);
 
    alarm(30);
    signal(SIGALRM, charge_alarm);
 
    charging = true;
 
  } else {
    unlink("/tmp/charging");
 
    charging = false;
  }
 
}
// usb mode switching
void usb_mode(int mode) {
  ioctl(usb,MOTUSBD_IOCTL_SET_USBMODE,&mode);
}
 
void plug_cable(int type) {
 
  switch (type) {
 
    case MOTO_ACCY_TYPE_CHARGER_MID:
 
        printf("charger attached\n");
        charger(CURRENT_1300,VOLTAGE_425);
 
      break;
    case MOTO_ACCY_TYPE_CABLE_USB:
 
        printf("usb cable attached\n");
 
        if (usb_charge)
          charger(CURRENT_200,VOLTAGE_425);
 
        usb_mode(USB_STATUS_NET);
 
      break;
    case MOTO_ACCY_TYPE_HEADSET_MONO:
    case MOTO_ACCY_TYPE_HEADSET_STEREO:
    case MOTO_ACCY_TYPE_HEADSET_EMU_MONO:
    case MOTO_ACCY_TYPE_HEADSET_EMU_STEREO:
        printf("headset attached %d\n",type);
        break;
    default:
        printf("attached cable %d\n",type);
    }
 
 
}
 
void unplug_cable(int type) {
 
  switch (type) {
 
    case MOTO_ACCY_TYPE_CHARGER_MID:
 
      printf("charger detached\n");
      charger(CURRENT_0,VOLTAGE_MIN);
 
 
      break;
    case MOTO_ACCY_TYPE_CABLE_USB:
 
        printf("usb cable detached\n");
        if (usb_charge)
          charger(CURRENT_0,VOLTAGE_MIN);
 
        usb_mode(0);
 
      break;
 
    case MOTO_ACCY_TYPE_HEADSET_MONO:
    case MOTO_ACCY_TYPE_HEADSET_STEREO:
    case MOTO_ACCY_TYPE_HEADSET_EMU_MONO:
    case MOTO_ACCY_TYPE_HEADSET_EMU_STEREO:
        printf("headset detached %d\n",type);
        break;
 
    default:
        printf("detached cable %d\n",type);  
    }
 
 
}
 
 
void charge_alarm(int sig) {
 
  int b = battery();
 
  printf("d: %d %d\n", charging, b );
 
  if ( charging && ( b > 709 ) ) {
 
    charger(0,0);
 
  } else if (  charging && ( b > 700 ) ) {
    alarm(10);
    printf("no-no\n");
  } else {
    printf("no..\n");
    alarm(30);
 
  }
 
}
 
void battery_update(int sig) {
  printf("hauuuu...\n");
  int fd = open("/tmp/battery",O_CREAT | O_RDWR );
  char b[4];
  sprintf(b,"%d",battery() );
  write(fd,&b,4);
  close(fd);
}
 
int main(int argc, char *argv[]) {
 
 
  //if ( fork() )
  //  return;
 
 
  int pid = open("/var/run/motod.pid",O_CREAT | O_RDWR | O_TRUNC);
  char cpid[11];
  int n = sprintf(cpid,"%d",(int)getpid() );
  write(pid,&cpid,n);
  close(pid);
 
  //freopen("/var/log/motod", "w", stdout);
 
 
  fd_set devs, devs_back;
 
  usb   = open("/dev/motusbd",  O_RDWR);
  apm   = open("/dev/apm_bios", O_RDWR);
  accy  = open("/dev/accy",     O_RDWR);
  power = open("/dev/power_ic", O_RDWR);
 
  if (usb < 0) {
    printf("cant open usb\n");
    return 1;
  }
 
  if (apm < 0) {
    printf("cant open apm\n");
    return 1;
  }
 
  if (accy < 0) {
    printf("cant open accy\n");
    return 1;
  }
 
  if (power < 0){
    printf("cant open power\n");
    return 1;
  }
 
  battery_update(0);
  signal(SIGUSR1,battery_update);
 
  FD_ZERO(&devs);
 
  //FD_SET(usb,  &devs);
  FD_SET(apm,  &devs);
  FD_SET(accy, &devs);
  FD_SET(power,&devs);
 
 
  unsigned short event[40];
  memset(event,0,sizeof(event));
 
  apm_event_t *apm_event;
 
  devs_back = devs;
 
  n = ioctl(apm, APM_IOC_STARTPMU, NULL);
  printf("APM_IOC_STARTPMU %d\n", n);
 
  n = ioctl(apm, APM_IOC_SET_SPROF_WIN, 1);
  printf("APM_IOC_SET_SPROF_WIN %d\n",n);
 
  while (1) {
    devs = devs_back;
    select(FD_SETSIZE,&devs,NULL,NULL,NULL);
 
    if(FD_ISSET(apm,&devs) ) {
      read(apm,apm_event,40);
 
      switch(apm_event->type) {
        case APM_EVENT_DEVICE:
          printf("apm device kind:%x info:%x\n",
              apm_event->kind,
              apm_event->info
              );
          break;
        case APM_EVENT_PROFILER:
          switch(apm_event->kind)
          {
            case EVENT_PROF_IDLE:
              printf("cpu idle\n");
              break;
            case EVENT_PROF_PERF:
              printf("performance!?+\n");
              break;
            case EVENT_PROF_SLEEP:
              printf("a wanna sleep!\n");
              break;
            default:
              printf("profiler %x:%x\n",apm_event->kind,apm_event->info);
           }
          break;
        default:
          printf("apm event: %x:%x:%x\n", event[0],event[1],event[2]);
 
      }
 
 
 
    }
 
    /*
    if(FD_ISSET(usb,&devs) ) {
      read(usb,&event,40); 
      printf("usb event: %d\n", event[0]);
    }*/
 
 
    if(FD_ISSET(accy,&devs) ) {
      read(accy,&event,40);
 
      if(event[1])
        plug_cable(event[0]);
      else
        unplug_cable(event[0]);
    }
 
    if(FD_ISSET(power,&devs) ) {
      read(power,&event,40);
      printf("power event: %d\n", event[0]);
    }
 
 
 
  }
 
 
 
}
 
VIP: No | Used: 83M/101M | 0.073 sec / GZIP-2