int pingpang_buffer_read(struct modem_buffer *buffer,char *data,int size)
{
	int read_len = 0;
	int data_size = 0;
	int i;
	int read_point= buffer->buffer[0].read_point;

	if (buffer->type==BUF_RECV) {
		do{
			if (buffer->buffer[0].write_point != buffer->buffer[0].read_point)
				break;
			down(&buffer->buf_read_sem);
		}while(1);
		data_size = buffer_data_size(&buffer->buffer[0]);
		if(data_size==0)
			return 0;

		if(data_size < size){
			read_len = data_size;
		} else {
			read_len = size;
		}
		for (i=0;i<read_len;i++) {
			data[i]= buffer->buffer[0].addr[read_point++];
			if(read_point >= buffer->buffer[0].size)
				read_point = 0;
		}
		dloader_record_timestamp(0x30000000|buffer->buffer[0].read_point);
		dloader_record_timestamp(0x40000000|read_point);
		buffer->buffer[0].read_point = read_point;
		up(&buffer->buf_read_sem);
		return read_len;
	}
	return 0;
}
int save_to_receive_buffer(struct modem_buffer *buffer,char *data,int size)
{
	int free_space = 0;	
	int data_size = 0;
	int i;
	int write_point= buffer->buffer[0].write_point;

	if (buffer->type==BUF_RECV) {
		do{
			data_size = buffer_data_size(&buffer->buffer[0]);	
			free_space = buffer->buffer[0].size-1-data_size;
			if (free_space >= size)
				break;
			down(&buffer->buf_read_sem);
		}while(1);
		for(i=0;i<size;i++){
			buffer->buffer[0].addr[write_point++]=data[i];
			if(write_point >= buffer->buffer[0].size)
				write_point = 0;
		}
		buffer->buffer[0].write_point = write_point;
		up(&buffer->buf_read_sem);
		return size;
	}
	return 0;
}
int pingpang_buffer_write(struct modem_buffer *buffer,char *data,int size)
{
	int index = 0;
	int data_size;
	int free_space;
	int write_point;
	int save_flag = 0;
	int i;
	unsigned long flags;
	enum BUF_status_t status;

	if(buffer->type == BUF_SEND){
		if (size >= buffer->buffer[0].size)
			return 0;

		do{
			index = buffer->save_index;
			for(i=0;i<2;i++){
				local_irq_save(flags);
				status = buffer->buffer[index].status;
				if ((status != BUF_STATUS_SENT) &&
				    (status != BUF_STATUS_FULL) &&
				    (status != BUF_STATUS_WRITTEN)) {
					buffer->buffer[index].status = BUF_STATUS_WRITTEN;
					local_irq_restore(flags);
					data_size = buffer_data_size(&buffer->buffer[index]);
					free_space = buffer->buffer[index].size -1 - data_size;
					if(free_space < size){
						buffer->buffer[index].status = BUF_STATUS_FULL;
						if(buffer->trans_index == 0xFF)
							buffer->trans_index = index;
						index = 1 - index;
						buffer->save_index = index;
					} else {
						write_point = buffer->buffer[index].write_point;
						for(i=0;i<size;i++){
							buffer->buffer[index].addr[write_point++]=data[i];
							if(write_point >= buffer->buffer[index].size)
								write_point = 0;
						}
						dloader_record_timestamp(0x10000000|(index<<24)|buffer->buffer[index].write_point);
						dloader_record_timestamp(0x20000000|(index<<24)|write_point);
						buffer->buffer[index].write_point = write_point;
						buffer->buffer[index].status = BUF_STATUS_NOEMPTY;
						buffer->buffer[index].status = BUF_STATUS_FULL;
						if(buffer->trans_index == 0xFF)
							buffer->trans_index = index;
						save_flag = 1;
					}
				} else {
					local_irq_restore(flags);
					index = 1 - index;
				}
			}
			if(save_flag==0)
				down(&buffer->buf_write_sem);
		}while(save_flag == 0);
	}
	return size;
}
int pingpang_buffer_read(struct modem_buffer *buffer,char __user *data,int size)
{
	int read_len = 0;
	int data_size = 0;	
	int i;
	int read_point= buffer->buffer[0].read_point;

	if (buffer->type==BUF_RECV) {
		do{
			if (buffer->buffer[0].write_point != buffer->buffer[0].read_point)
				break;
			down(&buffer->buf_read_sem);
		}while(1);

		data_size = buffer_data_size(&buffer->buffer[0]);

		if(data_size==0)
			return 0;

		if(data_size < size){
			read_len = data_size;
		} else {
			read_len = size;
		}
                if(copy_to_user(data,&buffer->buffer[0].addr[read_point],read_len)){
			printk("copy_to_user(%d,%d,%d) failed\n",read_len,size,data_size);
                        up(&buffer->buf_read_sem);
                        return -EFAULT;
                }

		buffer->buffer[0].read_point = 0; 
		buffer->buffer[0].write_point = 0; 
		up(&buffer->buf_read_sem);
		return read_len;
	}
	return 0;
}