elan: Don't rotate frames on 0x0c03

There has been a report that a 0x0c03 was installed straight (other
readers so far have produced images that are 90 degrees rotated). There
is no way for the dirver to know how a device is installed, so for now just
make an exception.
This commit is contained in:
Igor Filatov 2018-02-28 11:36:33 +02:00 committed by Bastien Nocera
parent b28b006d61
commit 75fe328f64
2 changed files with 46 additions and 22 deletions

View file

@ -77,7 +77,7 @@ struct elan_dev {
unsigned short *background;
unsigned char frame_width;
unsigned char frame_height;
unsigned char raw_frame_width;
unsigned char raw_frame_height;
int num_frames;
GSList *frames;
/* end state */
@ -111,18 +111,33 @@ static void elan_save_frame(struct elan_dev *elandev, unsigned short *frame)
{
G_DEBUG_HERE();
unsigned char raw_height = elandev->frame_width;
unsigned char raw_width = elandev->raw_frame_width;
/* so far 3 types of readers by sensor dimensions and orientation have been
* seen in the wild:
* 1. 144x64. Raw images are in portrait orientation while readers themselves
* are placed (e.g. built into a touchpad) in landscape orientation. These
* need to be rotated before assembling.
* 2. 96x96 rotated. Like the first type but square. Likewise, need to be
* rotated before assembling.
* 3. 96x96 normal. Square and need NOT be rotated. So far there's only been
* 1 report of a 0c03 of this type. Hopefully this type can be identified
* by device id (and manufacturers don't just install the readers as they
* please).
* we also discard stripes of 'frame_margin' from bottom and top because
* assembling works bad for tall frames */
/* Raw images are vertical and perpendicular to swipe direction of a
* normalized image, which means we need to make them horizontal before
* assembling. We also discard stripes of 'frame_margin' along raw
* height. */
unsigned char frame_margin = (raw_width - elandev->frame_height) / 2;
for (int y = 0; y < raw_height; y++)
for (int x = frame_margin; x < raw_width - frame_margin; x++) {
int frame_idx = y + (x - frame_margin) * raw_height;
int raw_idx = x + y * raw_width;
unsigned char frame_width = elandev->frame_width;
unsigned char frame_height = elandev->frame_height;
unsigned char raw_height = elandev->raw_frame_height;
unsigned char frame_margin = (raw_height - elandev->frame_height) / 2;
int frame_idx, raw_idx;
for (int y = 0; y < frame_height; y++)
for (int x = 0; x < frame_width; x++) {
if (elandev->dev_type & ELAN_NOT_ROTATED)
raw_idx = x + (y + frame_margin) * frame_width;
else
raw_idx = frame_margin + y + x * raw_height;
frame_idx = x + y * frame_width;
frame[frame_idx] =
((unsigned short *)elandev->last_read)[raw_idx];
}
@ -344,7 +359,7 @@ static void elan_cmd_read(struct fpi_ssm *ssm)
if (elandev->cmd->cmd == get_image_cmd.cmd)
/* raw data has 2-byte "pixels" and the frame is vertical */
response_len =
elandev->raw_frame_width * elandev->frame_width * 2;
elandev->raw_frame_height * elandev->frame_width * 2;
struct libusb_transfer *transfer = libusb_alloc_transfer(0);
if (!transfer) {
@ -701,15 +716,20 @@ static void activate_run_state(struct fpi_ssm *ssm)
elan_run_cmd(ssm, &get_sensor_dim_cmd, ELAN_CMD_TIMEOUT);
break;
case ACTIVATE_SET_SENSOR_DIM:
/* see elan_save_frame for details */
if (elandev->dev_type & ELAN_NOT_ROTATED) {
elandev->frame_width = elandev->last_read[0];
elandev->frame_height = elandev->raw_frame_height =
elandev->last_read[2];
} else {
elandev->frame_width = elandev->last_read[2];
elandev->raw_frame_width = elandev->last_read[0];
if (elandev->raw_frame_width < ELAN_MAX_FRAME_HEIGHT)
elandev->frame_height = elandev->raw_frame_width;
else
elandev->frame_height = elandev->raw_frame_height =
elandev->last_read[0];
}
if (elandev->frame_height > ELAN_MAX_FRAME_HEIGHT)
elandev->frame_height = ELAN_MAX_FRAME_HEIGHT;
/* see elan_save_frame for why it's width x raw_width */
fp_dbg("sensor dimensions, WxH: %dx%d", elandev->frame_width,
elandev->raw_frame_width);
elandev->raw_frame_height);
fpi_ssm_next_state(ssm);
break;
case ACTIVATE_CMD_1:

View file

@ -30,7 +30,11 @@
#define ELAN_ALL_DEV 0
/* devices with quirks */
#define ELAN_0907 1
#define ELAN_0907 (1 << 0)
#define ELAN_0C03 (1 << 1)
/* devices which don't require frame rotation before assembling */
#define ELAN_NOT_ROTATED ELAN_0C03
/* min FW version that supports calibration */
#define ELAN_MIN_CALIBRATION_FW 0x0138
@ -155,7 +159,7 @@ static const struct usb_id elan_id_table[] = {
{.vendor = ELAN_VEND_ID,.product = 0x0907,.driver_data = ELAN_0907},
{.vendor = ELAN_VEND_ID,.product = 0x0c01,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c02,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c03,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c03,.driver_data = ELAN_0C03},
{.vendor = ELAN_VEND_ID,.product = 0x0c04,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c05,.driver_data = ELAN_ALL_DEV},
{.vendor = ELAN_VEND_ID,.product = 0x0c06,.driver_data = ELAN_ALL_DEV},