Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/hakchi2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-03-16 23:20:11 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-03-16 23:20:11 +0300
commit620c4e3fab2e7c9155f80f1a782775568131e519 (patch)
tree32acb4390901c0f1a6aa8b4e220911973771d347 /clovercon
parent582acadd37d8cb48d6241c6631a16bd1a3689ae8 (diff)
clovercon - data format autodetection
Diffstat (limited to 'clovercon')
-rw-r--r--clovercon/clovercon.c99
1 files changed, 64 insertions, 35 deletions
diff --git a/clovercon/clovercon.c b/clovercon/clovercon.c
index 37cca47f..9ec56c92 100644
--- a/clovercon/clovercon.c
+++ b/clovercon/clovercon.c
@@ -64,7 +64,6 @@ MODULE_LICENSE("GPL");
//Delay expressed in polling intervals
#define RETRY_BASE_DELAY 512
-#define DATA_FORMAT 1
#define D_BTN_R 1
#define D_BTN_START 2
#define D_BTN_HOME 3
@@ -178,6 +177,7 @@ struct clovercon_info {
bool autofire_x;
bool autofire_y;
int start_counter;
+ u8 data_format;
};
static struct clovercon_info con_info_list[MAX_CON_COUNT];
@@ -299,8 +299,9 @@ static int clovercon_read_controller_info(struct i2c_client *client, u8 *data, s
// print_hex_dump(KERN_DEBUG, "Controller info data: " , DUMP_PREFIX_NONE, 16, 256, data, len, false);
}
-static int clovercon_setup(struct i2c_client *client) {
- u8 init_data[] = { 0xf0, 0x55, 0xfb, 0x00, 0xfe, DATA_FORMAT };
+static int clovercon_setup(struct clovercon_info *info) {
+ struct i2c_client *client = info->client;
+ u8 init_data[] = { 0xf0, 0x55, 0xfb, 0x00, 0xfe, 3 };
static const int CON_INFO_LEN = 6;
u8 con_info_data[CON_INFO_LEN];
int ret;
@@ -313,9 +314,8 @@ static int clovercon_setup(struct i2c_client *client) {
ret = clovercon_write(client, &init_data[2], 2);
if (ret)
goto err;
+ // trying to set data format to 3
ret = clovercon_write(client, &init_data[4], 2);
- if (ret)
- goto err;
ret = clovercon_read_controller_info(client, con_info_data, CON_INFO_LEN);
if (ret < 0) {
@@ -326,11 +326,12 @@ static int clovercon_setup(struct i2c_client *client) {
ret = -EIO;
goto err;
}
- if (con_info_data[4] != DATA_FORMAT) {
- ERR("failed to set data format, value is %i", (int)con_info_data[4]);
- ret = -EIO;
- goto err;
- }
+
+ // autodetecting data format
+ // it should be 0x03 for original classic controllers and clovercons
+ // but seems like not every 3rd party controller supports data format selection
+ info->data_format = con_info_data[4];
+
if (con_info_data[5] != 1) {
ERR("unsupported controller id %i", (int)con_info_data[5]);
ret = -EIO;
@@ -415,6 +416,7 @@ static void clovercon_poll(struct input_polled_dev *polled_dev) {
* Use that as last resort discarding criteria */
jy = 0;
for (jx=8; jx<21; jx++) {
+ if (data[jx] == 0xFF) data[jx] = 0; // for 3rd party controllers
jy += data[jx];
}
if (jy) {
@@ -422,29 +424,56 @@ static void clovercon_poll(struct input_polled_dev *polled_dev) {
break;
}
- jx = ((data[0] & 0x3f) - 0x20) * 4;
- rx = (((data[2] >> 7) | ((data[1] & 0xC0) >> 5) | ((data[0] & 0xC0) >> 3)) - 0x10) * 8;
- jy = ((data[1] & 0x3f) - 0x20) * -4;
- ry = ((data[2] & 0x1f) - 0x10) * -8;
- tl = ((data[3] >> 5) | ((data[2] & 0x60) >> 2)) * 8;
- tr = (data[3] & 0x1f) * 8;
-
- r = !get_bit(data[4], D_BTN_R);
- start = !get_bit(data[4], D_BTN_START);
- home = !get_bit(data[4], D_BTN_HOME);
- select = !get_bit(data[4], D_BTN_SELECT);
- l = !get_bit(data[4], D_BTN_L);
- down = !get_bit(data[4], D_BTN_DOWN);
- right = !get_bit(data[4], D_BTN_RIGHT);
-
- up = !get_bit(data[5], D_BTN_UP);
- left = !get_bit(data[5], D_BTN_LEFT);
- zr = !get_bit(data[5], D_BTN_ZR);
- x = !get_bit(data[5], D_BTN_X);
- y = !get_bit(data[5], D_BTN_Y);
- a = !get_bit(data[5], D_BTN_A);
- b = !get_bit(data[5], D_BTN_B);
- zl = !get_bit(data[5], D_BTN_ZL);
+ if (info->data_format == 3)
+ {
+ jx = data[0] - 0x80;
+ rx = data[1] - 0x80;
+ jy = 0x7fl - data[2];
+ ry = 0x7fl - data[3];
+ tl = data[4];
+ tr = data[5];
+
+ r = !get_bit(data[6], D_BTN_R);
+ start = !get_bit(data[6], D_BTN_START);
+ home = !get_bit(data[6], D_BTN_HOME);
+ select = !get_bit(data[6], D_BTN_SELECT);
+ l = !get_bit(data[6], D_BTN_L);
+ down = !get_bit(data[6], D_BTN_DOWN);
+ right = !get_bit(data[6], D_BTN_RIGHT);
+
+ up = !get_bit(data[7], D_BTN_UP);
+ left = !get_bit(data[7], D_BTN_LEFT);
+ zr = !get_bit(data[7], D_BTN_ZR);
+ x = !get_bit(data[7], D_BTN_X);
+ y = !get_bit(data[7], D_BTN_Y);
+ a = !get_bit(data[7], D_BTN_A);
+ b = !get_bit(data[7], D_BTN_B);
+ zl = !get_bit(data[7], D_BTN_ZL);
+ } else {
+ jx = ((data[0] & 0x3f) - 0x20) * 4;
+ rx = (((data[2] >> 7) | ((data[1] & 0xC0) >> 5) | ((data[0] & 0xC0) >> 3)) - 0x10) * 8;
+ jy = ((data[1] & 0x3f) - 0x20) * -4;
+ ry = ((data[2] & 0x1f) - 0x10) * -8;
+ tl = ((data[3] >> 5) | ((data[2] & 0x60) >> 2)) * 8;
+ tr = (data[3] & 0x1f) * 8;
+
+ r = !get_bit(data[4], D_BTN_R);
+ start = !get_bit(data[4], D_BTN_START);
+ home = !get_bit(data[4], D_BTN_HOME);
+ select = !get_bit(data[4], D_BTN_SELECT);
+ l = !get_bit(data[4], D_BTN_L);
+ down = !get_bit(data[4], D_BTN_DOWN);
+ right = !get_bit(data[4], D_BTN_RIGHT);
+
+ up = !get_bit(data[5], D_BTN_UP);
+ left = !get_bit(data[5], D_BTN_LEFT);
+ zr = !get_bit(data[5], D_BTN_ZR);
+ x = !get_bit(data[5], D_BTN_X);
+ y = !get_bit(data[5], D_BTN_Y);
+ a = !get_bit(data[5], D_BTN_A);
+ b = !get_bit(data[5], D_BTN_B);
+ zl = !get_bit(data[5], D_BTN_ZL);
+ }
// Reset combination
reset =
@@ -580,7 +609,7 @@ static void clovercon_poll(struct input_polled_dev *polled_dev) {
info->retry_counter++;
if (info->retry_counter == retry_delay) {
DBG("retrying controller setup");
- ret = clovercon_setup(info->client);
+ ret = clovercon_setup(info);
if (ret) {
info->state = MIN(CS_ERR, info->state + 1);
} else {
@@ -597,7 +626,7 @@ static void clovercon_poll(struct input_polled_dev *polled_dev) {
static void clovercon_open(struct input_polled_dev *polled_dev) {
struct clovercon_info *info = polled_dev->private;
- if (clovercon_setup(info->client)) {
+ if (clovercon_setup(info)) {
info->retry_counter = 0;
info->state = CS_RETRY_1;
INF("opened controller %i, controller in error state after failed setup", info->id);