示例#1
0
文件: master.c 项目: atikbif/Relkon6
void write_reg(unsigned char can_num, unsigned char net_adr,unsigned char adr_h,unsigned char adr_l,unsigned char* ptr,unsigned char cnt)
{
	unsigned char* tx_buf;
	unsigned short tmp;
    if((cnt>=128)||(cnt==0)) return;
    tx_buf = get_can_tx_ptr(can_num);
	tx_buf[0]=net_adr;
	tx_buf[1]=0x10;
	tx_buf[2]=adr_h;
	tx_buf[3]=adr_l;
	tx_buf[4]=0;
	tx_buf[5]=cnt;
	tx_buf[6]=cnt*2;
	for(tmp=0;tmp<cnt;tmp++)
	{
		tx_buf[7+tmp*2]=ptr[tmp*2+1];
		tx_buf[8+tmp*2]=ptr[tmp*2];
	}
	tx_buf[7+cnt*2]=getLRC(tx_buf,7+cnt*2);
	if(can_num==1)
	{
		mstr2=0x10;
		if(_Sys.Can2_Type==0) write_canal2(8+cnt*2);
		else write_canal2(bin_to_ascii(tx_buf,8+cnt*2,_MODBUS));
	}
	else
	{
		mstr1=0x10;
		if(_Sys.Can1_Type==0) write_canal(8+cnt*2);
		else write_canal(bin_to_ascii(tx_buf,8+cnt*2,_MODBUS));
	}
}
int output_time_run(void){
	lcd_send_cmd(LINE2);
	bin_to_ascii(get_hours_run(), h_runASCII);
	bin_to_ascii(get_minutes_run(), min_runASCII);
	bin_to_ascii(get_seconds_run(), sec_runASCII);
	bin_to_ascii(get_mseconds_run(), msec_runASCII);
	lcd_printf(h_runASCII); lcd_printf(":");
	lcd_printf(min_runASCII); lcd_printf(":");
	lcd_printf(sec_runASCII); lcd_printf(":");
	lcd_printf(msec_runASCII);
}
int output_date_setting(void){
	// Get binary values + convert to ascii string
	bin_to_ascii(get_day_setting(), daySettingASCII);
	bin_to_ascii(get_month_setting(), monthSettingASCII);
	bin_to_ascii(get_year_setting(), yearSettingASCII);
	// Send to LCD
	lcd_send_cmd(LINE2);
	lcd_printf(daySettingASCII); lcd_printf("-");
	lcd_printf(monthSettingASCII); lcd_printf("-");
	lcd_printf(yearSettingASCII);
	return 0;
}
int output_time_setting(void){
	// Get binary values + convert to ascii string
	bin_to_ascii(get_seconds_setting(), secondSettingASCII);
	bin_to_ascii(get_minutes_setting(), minuteSettingASCII);
	bin_to_ascii(get_hours_setting(), hourSettingASCII);
	// Send to LCD
	lcd_send_cmd(LINE2);
	lcd_printf(hourSettingASCII); lcd_printf(":");
	lcd_printf(minuteSettingASCII); lcd_printf(":");
	lcd_printf(secondSettingASCII);
	return 0;
}
//---------------------------------------------------------------------------------------
//Output Stopwatch (hh:mm:ss:msms)
int output_stopwatch(void){
	// Convert to ASCII
	bin_to_ascii(get_stopwatch_hour(), stopwatchHourASCII);
	bin_to_ascii(get_stopwatch_min(), stopwatchMinuteASCII);
	bin_to_ascii(get_stopwatch_sec(), stopwatchSecondASCII);
	bin_to_ascii(get_stopwatch_msec(), stopwatchMSecondASCII);
	// Send to LCD
	lcd_send_cmd(LINE2);
	lcd_printf(stopwatchHourASCII); lcd_printf(":");
	lcd_printf(stopwatchMinuteASCII); lcd_printf(":");
	lcd_printf(stopwatchSecondASCII); lcd_printf(":");
	lcd_printf(stopwatchMSecondASCII);
	
	return 0;
}
示例#6
0
char *crypt_sun(const char *key, const char *salt) {
  char salt1[2];
  static char result[13];
  char *p;
  int tmp;

  tmp = 0x3f & ascii_to_bin_sun(salt[0]);
  salt1[0] = bin_to_ascii(tmp);
  tmp = 0x3f & ascii_to_bin_sun(salt[1]);
  salt1[1] = bin_to_ascii(tmp);

  p = crypt(key, salt1);
  strncpy(result, p, 13);

  result[0] = salt[0];
  result[1] = salt[1];

  return result;
}
示例#7
0
char *crypt_password(char *typed_password)
{
	time_t tm;
	char salt[2];

	if(typed_password)
	{
		time(&tm);
		salt[0] = bin_to_ascii(tm & 0x3f);
		salt[1] = bin_to_ascii((tm >> 5) & 0x3f);
		strcpy(typed_password,crypt(typed_password, salt));
	}
	return typed_password;
}
//---------------------------------------------------------------------------------------
//Output Date (dd-mm-yy) & Time (hh:mm:ss)
int output_date_time(void){
	// Get the current date and time
	ds1307_read_date_time();
	// Get binary values + convert to ascii string
	bin_to_ascii(get_seconds(), secondASCII);
	bin_to_ascii(get_minutes(), minuteASCII);
	bin_to_ascii(get_hours(), hourASCII);
	bin_to_ascii(get_day(), dayASCII);
	bin_to_ascii(get_month(), monthASCII);
	bin_to_ascii(get_year(), yearASCII);
	// Send to LCD
	lcd_send_cmd(LINE1);
	lcd_printf(hourASCII); lcd_printf(":");
	lcd_printf(minuteASCII); lcd_printf(":");
	lcd_printf(secondASCII);
	lcd_send_cmd(LINE2);
	lcd_printf(dayASCII); lcd_printf("-");
	lcd_printf(monthASCII); lcd_printf("-");
	lcd_printf(yearASCII);
		
	return 0;
}
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
				int argc, const char **argv)
{
	unsigned int ctrl, lctrl;
	int retval, i;
	int remember = -1;

	/* <DO NOT free() THESE> */
	const char *user;
	char *pass_old, *pass_new;
	/* </DO NOT free() THESE> */

	D(("called."));

#ifdef USE_LCKPWDF
	/* our current locking system requires that we lock the
	   entire password database.  This avoids both livelock
	   and deadlock. */
	/* These values for the number of attempts and the sleep time
	   are, of course, completely arbitrary.
	   My reading of the PAM docs is that, once pam_chauthtok() has been
	   called with PAM_UPDATE_AUTHTOK, we are obliged to take any
	   reasonable steps to make sure the token is updated; so retrying
	   for 1/10 sec. isn't overdoing it.
	   The other possibility is to call lckpwdf() on the first
	   pam_chauthtok() pass, and hold the lock until released in the
	   second pass--but is this guaranteed to work? -SRL */
	i=0;
	while((retval = lckpwdf()) != 0 && i < 100) {
		usleep(1000);
	}
	if(retval != 0) {
		return PAM_AUTHTOK_LOCK_BUSY;
	}
#endif
	ctrl = _set_ctrl(pamh, flags, &remember, argc, argv);

	/*
	 * First get the name of a user
	 */
	retval = pam_get_user(pamh, &user, "Username: "******"bad username [%s]", user);
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return PAM_USER_UNKNOWN;
		}
		if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
			_log_err(LOG_DEBUG, pamh, "username [%s] obtained",
			         user);
	} else {
		if (on(UNIX_DEBUG, ctrl))
			_log_err(LOG_DEBUG, pamh,
			         "password - could not identify user");
#ifdef USE_LCKPWDF
		ulckpwdf();
#endif
		return retval;
	}

	D(("Got username of %s", user));

	/*
	 * This is not an AUTH module!
	 */
	if (on(UNIX__NONULL, ctrl))
		set(UNIX__NULLOK, ctrl);

	if (on(UNIX__PRELIM, ctrl)) {
		/*
		 * obtain and verify the current password (OLDAUTHTOK) for
		 * the user.
		 */
		char *Announce;

		D(("prelim check"));

		if (_unix_blankpasswd(ctrl, user)) {
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return PAM_SUCCESS;
		} else if (off(UNIX__IAMROOT, ctrl)) {

			/* instruct user what is happening */
#define greeting "Changing password for "
			Announce = (char *) malloc(sizeof(greeting) + strlen(user));
			if (Announce == NULL) {
				_log_err(LOG_CRIT, pamh,
				         "password - out of memory");
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return PAM_BUF_ERR;
			}
			(void) strcpy(Announce, greeting);
			(void) strcpy(Announce + sizeof(greeting) - 1, user);
#undef greeting

			lctrl = ctrl;
			set(UNIX__OLD_PASSWD, lctrl);
			retval = _unix_read_password(pamh, lctrl
						     ,Announce
					     ,"(current) UNIX password: "******"password - (old) token not obtained");
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return retval;
			}
			/* verify that this is the password for this user */

			retval = _unix_verify_password(pamh, user, pass_old, ctrl);
		} else {
			D(("process run by root so do nothing this time around"));
			pass_old = NULL;
			retval = PAM_SUCCESS;	/* root doesn't have too */
		}

		if (retval != PAM_SUCCESS) {
			D(("Authentication failed"));
			pass_old = NULL;
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
		pass_old = NULL;
		if (retval != PAM_SUCCESS) {
			_log_err(LOG_CRIT, pamh,
			         "failed to set PAM_OLDAUTHTOK");
		}
		retval = _unix_verify_shadow(user, ctrl);
		if (retval == PAM_AUTHTOK_ERR) {
			if (off(UNIX__IAMROOT, ctrl))
				_make_remark(pamh, ctrl, PAM_ERROR_MSG,
					    "You must wait longer to change your password");
			else
				retval = PAM_SUCCESS;
		}
	} else if (on(UNIX__UPDATE, ctrl)) {
		/*
		 * tpass is used below to store the _pam_md() return; it
		 * should be _pam_delete()'d.
		 */

		char *tpass = NULL;
		int retry = 0;

		/*
		 * obtain the proposed password
		 */

		D(("do update"));

		/*
		 * get the old token back. NULL was ok only if root [at this
		 * point we assume that this has already been enforced on a
		 * previous call to this function].
		 */

		if (off(UNIX_NOT_SET_PASS, ctrl)) {
			retval = pam_get_item(pamh, PAM_OLDAUTHTOK
					      ,(const void **) &pass_old);
		} else {
			retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK
					      ,(const void **) &pass_old);
			if (retval == PAM_NO_MODULE_DATA) {
				retval = PAM_SUCCESS;
				pass_old = NULL;
			}
		}
		D(("pass_old [%s]", pass_old));

		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh, "user not authenticated");
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		retval = _unix_verify_shadow(user, ctrl);
		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh, "user not authenticated 2");
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		D(("get new password now"));

		lctrl = ctrl;

		if (on(UNIX_USE_AUTHTOK, lctrl)) {
			set(UNIX_USE_FIRST_PASS, lctrl);
		}
		retry = 0;
		retval = PAM_AUTHTOK_ERR;
		while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) {
			/*
			 * use_authtok is to force the use of a previously entered
			 * password -- needed for pluggable password strength checking
			 */

			retval = _unix_read_password(pamh, lctrl
						     ,NULL
					     ,"Enter new UNIX password: "******"Retype new UNIX password: "******"password - new password not obtained");
				}
				pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return retval;
			}
			D(("returned to _unix_chauthtok"));

			/*
			 * At this point we know who the user is and what they
			 * propose as their new password. Verify that the new
			 * password is acceptable.
			 */

			if (pass_new[0] == '\0') {	/* "\0" password = NULL */
				pass_new = NULL;
			}
			retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
		}

		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh,
			         "new password not acceptable");
			_pam_overwrite(pass_new);
			_pam_overwrite(pass_old);
			pass_new = pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		/*
		 * By reaching here we have approved the passwords and must now
		 * rebuild the password database file.
		 */

		/*
		 * First we encrypt the new password.
		 */

		if (on(UNIX_MD5_PASS, ctrl)) {
			tpass = crypt_md5_wrapper(pass_new);
		} else {
			/*
			 * Salt manipulation is stolen from Rick Faith's passwd
			 * program.  Sorry Rick :) -- alex
			 */

			time_t tm;
			char salt[3];

			time(&tm);
			salt[0] = bin_to_ascii(tm & 0x3f);
			salt[1] = bin_to_ascii((tm >> 6) & 0x3f);
			salt[2] = '\0';

			if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) {
				/* 
				 * to avoid using the _extensions_ of the bigcrypt()
				 * function we truncate the newly entered password
				 */
				char *temp = malloc(9);
				char *e;

				if (temp == NULL) {
					_log_err(LOG_CRIT, pamh,
					         "out of memory for password");
					_pam_overwrite(pass_new);
					_pam_overwrite(pass_old);
					pass_new = pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
					ulckpwdf();
#endif
					return PAM_BUF_ERR;
				}
				/* copy first 8 bytes of password */
				strncpy(temp, pass_new, 8);
				temp[8] = '\0';

				/* no longer need cleartext */
				e = bigcrypt(temp, salt);
				tpass = x_strdup(e);

				_pam_overwrite(e);
				_pam_delete(temp);	/* tidy up */
			} else {
				char *e;

				/* no longer need cleartext */
				e = bigcrypt(pass_new, salt);
				tpass = x_strdup(e);

				_pam_overwrite(e);
			}
		}

		D(("password processed"));

		/* update the password database(s) -- race conditions..? */

		retval = _do_setpass(pamh, user, pass_old, tpass, ctrl,
		                     remember);
		_pam_overwrite(pass_new);
		_pam_overwrite(pass_old);
		_pam_delete(tpass);
		pass_old = pass_new = NULL;
	} else {		/* something has broken with the module */
示例#10
0
int
main(int argc, char *argv[]) {
    struct passwd *pe;
    uid_t gotuid = getuid();
    char *pwdstr = NULL, *cryptstr, *oldstr;
    char pwdstr1[10];
    char *user;
    time_t tm;
    char salt[2];
    int force_passwd = 0;
    int silent = 0;
    int c;
    int opt_index;
    int fullname = 0, shell = 0;
    static const struct option long_options[] =
      {
	{"fullname", no_argument, 0, 'f'},
	{"shell", no_argument, 0, 's'},
	{"force", no_argument, 0, 'o'},
	{"quiet", no_argument, 0, 'q'},
	{"silent", no_argument, 0, 'q'},
	{"version", no_argument, 0, 'v'},
	{0, 0, 0, 0}
	};

    sanitize_env();
    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);

    optind = 0;
    while ((c = getopt_long(argc, argv, "foqsvV",
			    long_options, &opt_index)) != -1) {
	switch (c) {
	case 'f':
	    fullname = 1;
	    break;
	case 's':
	    shell = 1;
	    break;
	case 'o':
	    force_passwd = 1;
	    break;
	case 'q':
	    silent = 1;
	    break;
	case 'V':
	case 'v':
	    printf("%s\n", util_linux_version);
	    exit(0);
	default:
	    fprintf(stderr, _("Usage: passwd [-foqsvV] [user [password]]\n"));
	    exit(1);
	} /* switch (c) */
    } /* while */

    if (fullname || shell) {
	char *args[100];
	int i, j, errsv;

	setuid(getuid()); /* drop special privs. */
	if (fullname)
	  args[0] = _PATH_CHFN;
	else
	  args[0] = _PATH_CHSH;

	for (i = optind, j = 1; (i < argc) && (j < 99); i++, j++)
	  args[j] = argv[i];

	args[j] = NULL;
	execv(args[0], args);
	errsv = errno;
	fprintf(stderr, _("Can't exec %s: %s\n"), args[0], strerror(errsv));
	exit(1);
    }
    
    switch (argc - optind) {
    case 0:
	/* Why use getlogin()? Some systems allow having several
	   usernames with the same uid, especially several root accounts.
	   One changes the password for the username, not the uid. */
	if ( !(user = getlogin()) || !*user ) {
	    if ( !(pe = getpwuid( getuid() )) ) {
		pexit(_("Cannot find login name"));
	    } else
		user = pe->pw_name;
	}
	break;
    case 1:
	if(gotuid) {
	    printf(_("Only root can change the password for others.\n"));
	    exit (1);
	} else
	    user = argv[optind];
	break;
    case 2:
	if(gotuid) {
	    printf(_("Only root can change the password for others.\n"));
	    exit(1);
	} else {
	    user = argv[optind];
	    pwdstr = argv[optind+1];
	}
	break;
    default:
	printf(_("Too many arguments.\n"));
	exit (1);
    } /* switch */

    if(!(pe = getpwnam(user))) {
	pexit(_("Can't find username anywhere. Is `%s' really a user?"), user);
    }
    
    if (!(is_local(user))) {
	puts(_("Sorry, I can only change local passwords. Use yppasswd instead."));
	exit(1);
    }
    
    /* if somebody got into changing utmp... */
    if(gotuid && gotuid != pe->pw_uid) {
	puts(_("UID and username does not match, imposter!"));
	exit(1);
    }
    
    if ( !silent )
	printf( _("Changing password for %s\n"), user );
    
    if ( (gotuid && pe->pw_passwd && pe->pw_passwd[0]) 
	|| (!gotuid && !strcmp(user,"root")) ) {
	oldstr = getpass(_("Enter old password: "******"Illegal password, imposter."));
	    exit(1);
	}
    }

    if ( pwdstr ) {   /* already set on command line */
	if ( !force_passwd && !check_passwd(pwdstr, pe->pw_passwd, user, pe->pw_gecos) )
	    exit (1);
    } else {
	/* password not set on command line by root, ask for it ... */
	
      redo_it:
	pwdstr = getpass(_("Enter new password: "******"Password not changed."));
	    exit(1);
	}

	if ( (gotuid || (!gotuid && !force_passwd))
	     && !check_passwd(pwdstr, pe->pw_passwd, user, pe->pw_gecos) ) 
	    goto redo_it;
	
	xstrncpy(pwdstr1, pwdstr, sizeof(pwdstr1));
	pwdstr = getpass(_("Re-type new password: "******"You misspelled it. Password not changed."));
	    exit(1);
	}
    } /* pwdstr i.e. password set on command line */
    
    time(&tm); tm ^= getpid();
    salt[0] = bin_to_ascii(tm & 0x3f);
    salt[1] = bin_to_ascii((tm >> 6) & 0x3f);
    cryptstr = crypt(pwdstr, salt);

    if (pwdstr[0] == 0) cryptstr = "";

#ifdef LOGALL
    openlog("passwd", 0, LOG_AUTH);
    if (gotuid)
	syslog(LOG_NOTICE,_("password changed, user %s"),user);
    else {
	if ( !strcmp(user, "root") )
	    syslog(LOG_WARNING,_("ROOT PASSWORD CHANGED"));
	else
	    syslog(LOG_NOTICE,_("password changed by root, user %s"),user);
    }
    closelog();
#endif /* LOGALL */

    pe->pw_passwd = cryptstr;
#ifdef DEBUG
    printf (_("calling setpwnam to set password.\n"));
#else
    if (setpwnam( pe ) < 0) {
       perror( "setpwnam" );
       printf( _("Password *NOT* changed.  Try again later.\n" ));
       exit( 1 );
    }
#endif

    if ( !silent )
	printf(_("Password changed.\n"));	
    exit(0);
}
示例#11
0
文件: master.c 项目: atikbif/Relkon6
void can_cmd(request* r)
{
	unsigned short crc_val,tmp;
	unsigned char* tx_buf;
	tx_buf = get_can_tx_ptr(r->canal);
	if(tx_buf==0) return;
	switch(r->cmd)
	{
		case WR_RAM:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0xE4;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=r->amount >> 8;
			tx_buf[5]=r->amount & 0xFF;
			for(tmp=0;tmp < r->amount;tmp++) tx_buf[6+tmp]=r->tx[tmp];
			crc_val=GetCRC16(tx_buf,6+tmp);
			tx_buf[6+tmp]=crc_val>>8;
			tx_buf[7+tmp]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(8+tmp);break;
				case 2:write_canal(8+tmp);break;
				case 3:write_module(8+tmp);break;
			}
			break;
		case WR_US:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0xE0;
			tx_buf[2]=r->mem_addr & 0xFF;
			tx_buf[3]=r->amount & 0xFF;
			for(tmp=0;tmp < r->amount;tmp++) tx_buf[4+tmp]=r->tx[tmp];
			crc_val=GetCRC16(tx_buf,4+tmp);
			tx_buf[4+tmp]=crc_val>>8;
			tx_buf[5+tmp]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(6+tmp);break;
				case 2:write_canal(6+tmp);break;
				case 3:write_module(6+tmp);break;
			}
			break;
		case WR_XRAM:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x64;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			for(tmp=0;tmp < r->amount;tmp++) tx_buf[4+tmp]=r->tx[tmp];
			crc_val=GetCRC16(tx_buf,4+tmp);
			tx_buf[4+tmp]=crc_val>>8;
			tx_buf[5+tmp]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(6+tmp);break;
				case 2:write_canal(6+tmp);break;
				case 3:write_module(6+tmp);break;
			}
			break;
		case WR_REG:
			if((r->amount >= 128)||(r->amount == 0)) break;
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x10;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=0;
			tx_buf[5]=r->amount;
			tx_buf[6]=r->amount*2;
			for(tmp=0;tmp<r->amount;tmp++)
			{
				tx_buf[7+tmp*2]=r->tx[tmp*2+1];
				tx_buf[8+tmp*2]=r->tx[tmp*2];
			}
			tx_buf[7+r->amount*2]=getLRC(tx_buf,7+r->amount*2);
			switch(r->canal)
			{
				case 1:
					mstr2=0x10;
					write_canal2(bin_to_ascii(tx_buf,8+r->amount*2,_MODBUS));
					break;
				case 2:
					mstr1=0x10;
					write_canal(bin_to_ascii(tx_buf,8+r->amount*2,_MODBUS));
					break;
			}

			break;
		case WR_HLD:
			if((r->amount >= 128)||(r->amount == 0)) break;
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x10;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=0;
			tx_buf[5]=r->amount;
			tx_buf[6]=r->amount*2;
			for(tmp=0;tmp<r->amount;tmp++)
			{
				tx_buf[7+tmp*2]=r->tx[tmp*2+1];
				tx_buf[8+tmp*2]=r->tx[tmp*2];
			}
			crc_val=GetCRC16(tx_buf,7+r->amount*2);
			tx_buf[7+r->amount*2]=crc_val>>8;
			tx_buf[8+r->amount*2]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(9+r->amount*2);break;
				case 2:write_canal(9+r->amount*2);break;
				case 3:write_module(9+r->amount*2);break;
			}
			break;
		case WR_COIL:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x05;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			if(r->tx[0])
			{
				tx_buf[4]=0xFF;
				tx_buf[5]=0;
			}
			else
			{
				tx_buf[4]=0;
				tx_buf[5]=0;
			}

			crc_val=GetCRC16(tx_buf,6);
			tx_buf[6]=crc_val>>8;
			tx_buf[7]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(8);break;
				case 2:write_canal(8);break;
				case 3:write_module(8);break;
			}
			break;
		case RD_RAM:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0xD4;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=r->amount >> 8;
			tx_buf[5]=r->amount & 0xFF;
			crc_val=GetCRC16(tx_buf,6);
			tx_buf[6]=crc_val>>8;
			tx_buf[7]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(8);break;
				case 2:write_canal(8);break;
				case 3:write_module(8);break;
			}
			break;
		case RD_US:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0xD0;
			tx_buf[2]=r->mem_addr & 0xFF;
			tx_buf[3]=r->amount & 0xFF;
			crc_val=GetCRC16(tx_buf,4);
			tx_buf[4]=crc_val>>8;
			tx_buf[5]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(6);break;
				case 2:write_canal(6);break;
				case 3:write_module(6);break;
			}
			break;
		case RD_XRAM:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x54;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			crc_val=GetCRC16(tx_buf,4);
			tx_buf[4]=crc_val>>8;
			tx_buf[5]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(6);break;
				case 2:write_canal(6);break;
				case 3:write_module(6);break;
			}
			break;
		case RD_HLD:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x03;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=r->amount >> 8;
			tx_buf[5]=r->amount & 0xFF;
			crc_val=GetCRC16(tx_buf,6);
			tx_buf[6]=crc_val>>8;
			tx_buf[7]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(8);break;
				case 2:write_canal(8);break;
				case 3:write_module(8);break;
			}
			break;
		case RD_INP:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x04;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=r->amount >> 8;
			tx_buf[5]=r->amount & 0xFF;
			crc_val=GetCRC16(tx_buf,6);
			tx_buf[6]=crc_val>>8;
			tx_buf[7]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(8);break;
				case 2:write_canal(8);break;
				case 3:write_module(8);break;
			}
			break;
		case RD_DINP:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x02;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=r->amount >> 8;
			tx_buf[5]=r->amount & 0xFF;
			crc_val=GetCRC16(tx_buf,6);
			tx_buf[6]=crc_val>>8;
			tx_buf[7]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(8);break;
				case 2:write_canal(8);break;
				case 3:write_module(8);break;
			}
			break;
		case RD_COILS:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0x01;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=r->amount >> 8;
			tx_buf[5]=r->amount & 0xFF;
			crc_val=GetCRC16(tx_buf,6);
			tx_buf[6]=crc_val>>8;
			tx_buf[7]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(8);break;
				case 2:write_canal(8);break;
				case 3:write_module(8);break;
			}
			break;
		case RD_IO:
			tx_buf[0]=r->plc_addr;
			tx_buf[1]=0xB0;
			tx_buf[2]=r->mem_addr >> 8;
			tx_buf[3]=r->mem_addr & 0xFF;
			tx_buf[4]=r->amount >> 8;
			tx_buf[5]=r->amount & 0xFF;
			crc_val=GetCRC16(tx_buf,6);
			tx_buf[6]=crc_val>>8;
			tx_buf[7]=crc_val&0xFF;
			clear_rx_cnt(r->canal);
			switch(r->canal)
			{
				case 1:write_canal2(8);break;
				case 2:write_canal(8);break;
				case 3:write_module(8);break;
			}
			break;
        case RD_XRAM51:
            tx_buf[0]=r->plc_addr;
            tx_buf[1]=0x54;
            tx_buf[2]=r->mem_addr >> 8;
            tx_buf[3]=r->mem_addr & 0xFF;
            crc_val=GetCRC16(tx_buf,4);
            tx_buf[4]=crc_val>>8;
            tx_buf[5]=crc_val&0xFF;
            clear_rx_cnt(r->canal);
            switch(r->canal)
			{
				case 1:write_canal2(6);break;
				case 2:write_canal(6);break;
				case 3:write_module(6);break;
			}
            break;
        case RD_RAM51:
            tx_buf[0]=r->plc_addr;
            tx_buf[1]=0x50;
            tx_buf[2]=r->mem_addr;
            crc_val=GetCRC16(tx_buf,3);
            tx_buf[3]=crc_val>>8;
            tx_buf[4]=crc_val&0xFF;
            clear_rx_cnt(r->canal);
            switch(r->canal)
			{
				case 1:write_canal2(5);break;
				case 2:write_canal(5);break;
				case 3:write_module(5);break;
			}
            break;
	}
}
//! This function manages the GET DESCRIPTOR request. The device descriptor,
//! the configuration descriptor and the device qualifier are supported. All
//! other descriptors must be supported by the usb_user_get_descriptor
//! function.
//! Only 1 configuration is supported.
//!
Bool usb_get_descriptor(void)
{
   Bool zlp;
   U16  wLength;
   U8   descriptor_type ;
   U8   string_type;
   U8   dummy;
   U8   nb_byte;
   U8   byte_to_send;
#if (USE_DEVICE_SN_UNIQUE==ENABLE)
   U16  sn_index=0;
   U8   initial_data_to_transfer;
#endif
    
   zlp             = FALSE;                  /* no zero length packet */
   string_type     = Usb_read_byte();        /* read LSB of wValue    */
   descriptor_type = Usb_read_byte();        /* read MSB of wValue    */

   switch (descriptor_type)
   {
      case DESCRIPTOR_DEVICE:
      data_to_transfer = Usb_get_dev_desc_length(); //!< sizeof (usb_user_device_descriptor);
      pbuffer          = Usb_get_dev_desc_pointer();
      break;
      
      case DESCRIPTOR_CONFIGURATION:
      data_to_transfer = Usb_get_conf_desc_length(); //!< sizeof (usb_user_configuration_descriptor);
      pbuffer          = Usb_get_conf_desc_pointer();
      break;
      
      default:
      if( !usb_user_get_descriptor(descriptor_type, string_type))
         return FALSE;  // Unknow descriptor then stall request
      break;
   }

   dummy = Usb_read_byte();                     //!< don't care of wIndex field
   dummy = Usb_read_byte();
   LSB(wLength) = Usb_read_byte();              //!< read wLength
   MSB(wLength) = Usb_read_byte();
   Usb_ack_receive_setup() ;                  //!< clear the receive setup flag

   if (wLength > data_to_transfer)
   {
      if ((data_to_transfer % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
      else { zlp = FALSE; }                   //!< no need of zero length packet
   }
   else
   {
      data_to_transfer = (U8)wLength;         //!< send only requested number of data
   }

   Usb_ack_nak_out();
    
   byte_to_send=0;
#if (USE_DEVICE_SN_UNIQUE==ENABLE)
   initial_data_to_transfer = data_to_transfer;
#endif
   while((data_to_transfer != 0) && (!Is_usb_nak_out_sent()))
   {
      while(!Is_usb_read_control_enabled())
      {
         if (Is_usb_nak_out_sent())
            break;    // don't clear the flag now, it will be cleared after
      }
              
      nb_byte=0;
      while(data_to_transfer != 0)        //!< Send data until necessary
      {
         if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
            break;         
         
#if (USE_DEVICE_SN_UNIQUE==ENABLE)

         if(f_get_serial_string && (data_to_transfer < (initial_data_to_transfer-1)))    //if we are sending the signature characters (third byte and more...)
         {                                                                              //(The first two bytes are the length and the descriptor)
            
            switch (byte_to_send)
            {
               case 0:
               Usb_write_byte(bin_to_ascii((Flash_read_sn(sn_index)>>4) & 0x0F)); //sends the fist part (MSB) of the signature hex number, converted in ascii
               break;
              
               case 1:
               Usb_write_byte(0);                                                   //then, sends a null character (Usb_unicode)                    
               break;
    
               case 2:
               Usb_write_byte(bin_to_ascii(Flash_read_sn(sn_index) & 0x0F));      //sends the second part (LSB) of the signature hex number, converted in ascii 
               break;
    
               case 3:
               Usb_write_byte(0);                                                   //then, sends a null character (Usb_unicode)  
               sn_index++;                                                         //increments the signature address pointer.
               break;
            }
            byte_to_send = (byte_to_send+1)%4;     
         }
         else
         {
            Usb_write_PGM_byte(pbuffer++);                                                 //Write a flash byte to USB        
         }        
#else          
         Usb_write_PGM_byte(pbuffer++);          
#endif
         data_to_transfer --;                                                             //decrements the number of bytes to transmit.
      }
      
      if (Is_usb_nak_out_sent())
         break;
      else
         Usb_send_control_in();
   }