Beispiel #1
0
static ssize_t odev_set_picture(struct asus_oled_dev *odev,
				const char *buf, size_t count)
{
	size_t offs = 0, max_offs;

	if (count < 1)
		return 0;

	if (tolower(buf[0]) == 'b') {
		/* binary mode, set the entire memory*/

		size_t i;

		odev->buf_size = (odev->dev_width * ASUS_OLED_DISP_HEIGHT) / 8;

		kfree(odev->buf);
		odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
		if (odev->buf == NULL) {
			odev->buf_size = 0;
;
			return -ENOMEM;
		}

		memset(odev->buf, 0xff, odev->buf_size);

		for (i = 1; i < count && i <= 32 * 32; i++) {
			odev->buf[i-1] = buf[i];
			odev->buf_offs = i-1;
		}

		odev->width = odev->dev_width / 8;
		odev->height = ASUS_OLED_DISP_HEIGHT;
		odev->x_shift = 0;
		odev->y_shift = 0;
		odev->last_val =  0;

		send_data(odev);

		return count;
	}

	if (buf[0] == '<') {
		size_t i;
		size_t w = 0, h = 0;
		size_t w_mem, h_mem;

		if (count < 10 || buf[2] != ':')
			goto error_header;


		switch (tolower(buf[1])) {
		case ASUS_OLED_STATIC:
		case ASUS_OLED_ROLL:
		case ASUS_OLED_FLASH:
			odev->pic_mode = buf[1];
			break;
		default:
//			printk(ASUS_OLED_ERROR "Wrong picture mode: '%c'.\n",
;
			return -EIO;
			break;
		}

		for (i = 3; i < count; ++i) {
			if (buf[i] >= '0' && buf[i] <= '9') {
				w = 10*w + (buf[i] - '0');

				if (w > ASUS_OLED_MAX_WIDTH)
					goto error_width;
			} else if (tolower(buf[i]) == 'x') {
				break;
			} else {
				goto error_width;
			}
		}

		for (++i; i < count; ++i) {
			if (buf[i] >= '0' && buf[i] <= '9') {
				h = 10*h + (buf[i] - '0');

				if (h > ASUS_OLED_DISP_HEIGHT)
					goto error_height;
			} else if (tolower(buf[i]) == '>') {
				break;
			} else {
				goto error_height;
			}
		}

		if (w < 1 || w > ASUS_OLED_MAX_WIDTH)
			goto error_width;

		if (h < 1 || h > ASUS_OLED_DISP_HEIGHT)
			goto error_height;

		if (i >= count || buf[i] != '>')
			goto error_header;

		offs = i+1;

		if (w % (odev->dev_width) != 0)
			w_mem = (w/(odev->dev_width) + 1)*(odev->dev_width);
		else
			w_mem = w;

		if (h < ASUS_OLED_DISP_HEIGHT)
			h_mem = ASUS_OLED_DISP_HEIGHT;
		else
			h_mem = h;

		odev->buf_size = w_mem * h_mem / 8;

		kfree(odev->buf);
		odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);

		if (odev->buf == NULL) {
			odev->buf_size = 0;
;
			return -ENOMEM;
		}

		memset(odev->buf, 0xff, odev->buf_size);

		odev->buf_offs = 0;
		odev->width = w;
		odev->height = h;
		odev->x_shift = 0;
		odev->y_shift = 0;
		odev->last_val = 0;

		if (odev->pic_mode == ASUS_OLED_FLASH) {
			if (h < ASUS_OLED_DISP_HEIGHT/2)
				odev->y_shift = (ASUS_OLED_DISP_HEIGHT/2 - h)/2;
		} else {
			if (h < ASUS_OLED_DISP_HEIGHT)
				odev->y_shift = (ASUS_OLED_DISP_HEIGHT - h)/2;
		}

		if (w < (odev->dev_width))
			odev->x_shift = ((odev->dev_width) - w)/2;
	}

	max_offs = odev->width * odev->height;

	while (offs < count && odev->buf_offs < max_offs) {
		int ret = 0;

		if (buf[offs] == '1' || buf[offs] == '#') {
			ret = append_values(odev, 1, 1);
			if (ret < 0)
				return ret;
		} else if (buf[offs] == '0' || buf[offs] == ' ') {
			ret = append_values(odev, 0, 1);
			if (ret < 0)
				return ret;
		} else if (buf[offs] == '\n') {
			/* New line detected. Lets assume, that all characters
			   till the end of the line were equal to the last
			   character in this line.*/
			if (odev->buf_offs % odev->width != 0)
				ret = append_values(odev, odev->last_val,
						    odev->width -
						    (odev->buf_offs %
						     odev->width));
			if (ret < 0)
				return ret;
		}

		offs++;
	}

	if (odev->buf_offs >= max_offs)
		send_data(odev);

	return count;

error_width:
;
	return -EIO;

error_height:
;
	return -EIO;

error_header:
;
	return -EIO;
}
static ssize_t set_picture(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
	size_t offs = 0, max_offs;
	struct usb_interface *intf = to_usb_interface(dev);
	struct asus_oled_dev *odev = usb_get_intfdata(intf);
	
	if (count < 1) return 0;
	
	if (buf[0] == '<') {
		size_t i;
		size_t w = 0, h = 0;
		size_t w_mem, h_mem;
		
		if (count < 10 || buf[2] != ':') {
			goto error_header;
		}
		
		switch(tolower(buf[1])) {
			case ASUS_OLED_STATIC:
			case ASUS_OLED_ROLL:
			case ASUS_OLED_FLASH:
				odev->pic_mode = buf[1];
			break;
			default:
				printk(ASUS_OLED_ERROR "Wrong picture mode: '%c'.\n", buf[1]);
				return -EIO;
			break;
		}
		
		for (i = 3; i < count; ++i) {
			if (buf[i] >= '0' && buf[i] <= '9') {
				w = 10*w + (buf[i] - '0');
				
				if (w > ASUS_OLED_MAX_WIDTH) goto error_width;
			}
			else if (tolower(buf[i]) == 'x') break;
			else goto error_width;
		}
		
		for (++i; i < count; ++i) {
			if (buf[i] >= '0' && buf[i] <= '9') {
				h = 10*h + (buf[i] - '0');
				
				if (h > ASUS_OLED_DISP_HEIGHT) goto error_height;
			}
			else if (tolower(buf[i]) == '>') break;
			else goto error_height;
		}
		
		if (w < 1 || w > ASUS_OLED_MAX_WIDTH) goto error_width;
		
		if (h < 1 || h > ASUS_OLED_DISP_HEIGHT) goto error_height;
		
		if (i >= count || buf[i] != '>') goto error_header;
		
		offs = i+1;
		
		if (w % ASUS_OLED_DISP_WIDTH != 0)
			w_mem = (w/ASUS_OLED_DISP_WIDTH + 1)*ASUS_OLED_DISP_WIDTH;
		else
			w_mem = w;
		
		if (h < ASUS_OLED_DISP_HEIGHT)
			h_mem = ASUS_OLED_DISP_HEIGHT;
		else
			h_mem = h;
		
		odev->buf_size = w_mem * h_mem / 8;
		
		if (odev->buf) kfree(odev->buf);
		odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
		
		if (odev->buf == NULL) {
			odev->buf_size = 0;
			printk(ASUS_OLED_ERROR "Out of memory!\n");
			return -ENOMEM;
		}
		
		memset(odev->buf, 0xff, odev->buf_size);
		
		odev->buf_offs = 0;
		odev->width = w;
		odev->height = h;
		odev->x_shift = 0;
		odev->y_shift = 0;
		odev->last_val = 0;
		
		if (odev->pic_mode == ASUS_OLED_FLASH) {
			if (h < ASUS_OLED_DISP_HEIGHT/2)
					odev->y_shift = (ASUS_OLED_DISP_HEIGHT/2 - h)/2;
		}
		else {
			if (h < ASUS_OLED_DISP_HEIGHT)
				odev->y_shift = (ASUS_OLED_DISP_HEIGHT - h)/2;
		}
		
		if (w < ASUS_OLED_DISP_WIDTH)
			odev->x_shift = (ASUS_OLED_DISP_WIDTH - w)/2;
	}
	
	max_offs = odev->width * odev->height;
	
	while (offs < count && odev->buf_offs < max_offs) {
		int ret;
		
		if (buf[offs] == '1' || buf[offs] == '#') {
			if ( (ret = append_values(odev, 1, 1)) < 0) return ret;
		}
		else if (buf[offs] == '0' || buf[offs] == ' ') {
			if ( (ret = append_values(odev, 0, 1)) < 0) return ret;
		}
		else if (buf[offs] == '\n') {
			// New line detected. Lets assume, that all characters till the end of the
			// line were equal to the last character in this line.
			if (odev->buf_offs % odev->width != 0)
				if ( (ret = append_values(odev, odev->last_val,
						odev->width - (odev->buf_offs % odev->width))) < 0) return ret;
		}
		
		offs++;
	}
	
	if (odev->buf_offs >= max_offs) send_data(odev);
	
	return count;

error_width:
	printk(ASUS_OLED_ERROR "Wrong picture width specified.\n");
	return -EIO;
	
error_height:
	printk(ASUS_OLED_ERROR "Wrong picture height specified.\n");
	return -EIO;

error_header:
	printk(ASUS_OLED_ERROR "Wrong picture header.\n");
	return -EIO;
}