void usbdump(int f) { int a; for (a = 1; a < USB_MAX_DEVICES; a++) { if (!done[a]) usbdev(f, a, 1); } }
void dumpone(char *name, int f, int addr) { if (verbose) printf("Controller %s:\n", name); indent = 0; memset(done, 0, sizeof done); if (addr) usbdev(f, addr, 0); else usbdump(f); }
void usbdev(int f, int a, int rec) { struct usb_device_info di; int e, p, i; di.udi_addr = a; e = ioctl(f, USB_DEVICEINFO, &di); if (e) { if (errno != ENXIO) printf("addr %d: I/O error\n", a); return; } printf("addr %d: ", a); done[a] = 1; if (verbose) { switch (di.udi_speed) { case USB_SPEED_LOW: printf("low speed, "); break; case USB_SPEED_FULL: printf("full speed, "); break; case USB_SPEED_HIGH: printf("high speed, "); break; default: break; } if (di.udi_power) printf("power %d mA, ", di.udi_power); else printf("self powered, "); if (di.udi_config) printf("config %d, ", di.udi_config); else printf("unconfigured, "); } if (verbose) { printf("%s(0x%04x), %s(0x%04x), rev %s", di.udi_product, di.udi_productNo, di.udi_vendor, di.udi_vendorNo, di.udi_release); } else printf("%s, %s", di.udi_product, di.udi_vendor); printf("\n"); if (showdevs) { for (i = 0; i < USB_MAX_DEVNAMES; i++) if (di.udi_devnames[i][0]) printf("%*s %s\n", indent, "", di.udi_devnames[i]); } if (!rec) return; for (p = 0; p < di.udi_nports; p++) { int s = di.udi_ports[p]; if (s >= USB_MAX_DEVICES) { if (verbose) { printf("%*sport %d %s\n", indent+1, "", p+1, s == USB_PORT_ENABLED ? "enabled" : s == USB_PORT_SUSPENDED ? "suspended" : s == USB_PORT_POWERED ? "powered" : s == USB_PORT_DISABLED ? "disabled" : "???"); } continue; } indent++; printf("%*s", indent, ""); if (verbose) printf("port %d ", p+1); if (s == 0) printf("addr 0 should never happen!\n"); else usbdev(f, s, 1); indent--; } }
int main(int argc, char** argv) { Options opts = parse_args(argc, argv); usb_init(); usb_find_busses(); usb_find_devices(); struct usb_device* dev = find_usb_device(0x20d6, 0xcb17); int acc_x_min = 0; int acc_y_min = 0; int acc_z_min = 0; int acc_x_max = 0; int acc_y_max = 0; int acc_z_max = 0; int touch_pos_x = 0; int touch_pos_y = 0; bool finger_touching = false; bool pinch_touching = false; bool scroll_wheel = false; int wheel_distance = 0; if (dev) { std::unique_ptr<USBDevice> usbdev(new USBDevice(dev)); usbdev->print_info(); usbdev->detach_kernel_driver(0); usbdev->claim_interface(0); Evdev evdev; // init evdev if (opts.gamepad_mode) { evdev.add_abs(ABS_X, -1, 1, 0, 0); evdev.add_abs(ABS_Y, -1, 1, 0, 0); evdev.add_key(BTN_A); evdev.add_key(BTN_B); evdev.add_key(BTN_X); evdev.add_key(BTN_Y); evdev.add_key(BTN_START); evdev.add_key(BTN_SELECT); evdev.add_key(BTN_Z); } else if (opts.keyboard_mode) { evdev.add_key(KEY_LEFT); evdev.add_key(KEY_RIGHT); evdev.add_key(KEY_UP); evdev.add_key(KEY_DOWN); evdev.add_key(KEY_ENTER); evdev.add_key(KEY_SPACE); evdev.add_key(KEY_A); evdev.add_key(KEY_Z); evdev.add_key(KEY_ESC); evdev.add_key(KEY_TAB); } else if (opts.tablet_mode) { evdev.add_abs(ABS_X, 0, 1913, 0, 0); evdev.add_abs(ABS_Y, 0, 1076, 0, 0); evdev.add_abs(ABS_PRESSURE, 0, 143, 0, 0); evdev.add_key(BTN_TOUCH); evdev.add_key(BTN_TOOL_PEN); evdev.add_rel(REL_WHEEL); evdev.add_rel(REL_HWHEEL); evdev.add_rel(REL_X); evdev.add_rel(REL_Y); } else if (opts.touchpad_mode) { evdev.add_key(BTN_LEFT); evdev.add_key(BTN_RIGHT); evdev.add_key(BTN_MIDDLE); /* add_key(KEY_FORWARD); add_key(KEY_BACK); */ evdev.add_rel(REL_WHEEL); evdev.add_rel(REL_HWHEEL); evdev.add_rel(REL_X); evdev.add_rel(REL_Y); } evdev.finish(); usbdev->listen (3, [&](uint8_t* data, int size) { UDrawDecoder decoder(data, size); if (opts.keyboard_mode) { evdev.send(EV_KEY, KEY_LEFT, decoder.get_left()); evdev.send(EV_KEY, KEY_RIGHT, decoder.get_right()); evdev.send(EV_KEY, KEY_UP, decoder.get_up()); evdev.send(EV_KEY, KEY_DOWN, decoder.get_down()); evdev.send(EV_KEY, KEY_ENTER, decoder.get_cross()); evdev.send(EV_KEY, KEY_SPACE, decoder.get_circle()); evdev.send(EV_KEY, KEY_A, decoder.get_square()); evdev.send(EV_KEY, KEY_Z, decoder.get_triangle()); evdev.send(EV_KEY, KEY_ESC, decoder.get_start()); evdev.send(EV_KEY, KEY_TAB, decoder.get_select()); evdev.send(EV_SYN, SYN_REPORT, 0); } else if (opts.gamepad_mode) { evdev.send(EV_ABS, ABS_X, -1 * decoder.get_left() + 1 * decoder.get_right()); evdev.send(EV_ABS, ABS_Y, -1 * decoder.get_up() + 1 * decoder.get_down()); evdev.send(EV_KEY, BTN_A, decoder.get_cross()); evdev.send(EV_KEY, BTN_B, decoder.get_circle()); evdev.send(EV_KEY, BTN_X, decoder.get_square()); evdev.send(EV_KEY, BTN_Y, decoder.get_triangle()); evdev.send(EV_KEY, BTN_START, decoder.get_start()); evdev.send(EV_KEY, BTN_SELECT, decoder.get_select()); evdev.send(EV_KEY, BTN_Z, decoder.get_guide()); evdev.send(EV_SYN, SYN_REPORT, 0); } else if (opts.tablet_mode) { if (decoder.get_mode() == UDrawDecoder::PEN_MODE) { evdev.send(EV_ABS, ABS_X, decoder.get_x()); evdev.send(EV_ABS, ABS_Y, decoder.get_y()); evdev.send(EV_ABS, ABS_PRESSURE, decoder.get_pressure()); evdev.send(EV_KEY, BTN_TOOL_PEN, 1); if (decoder.get_pressure() > 0) { evdev.send(EV_KEY, BTN_TOUCH, 1); } else { evdev.send(EV_KEY, BTN_TOUCH, 0); } evdev.send(EV_SYN, SYN_REPORT, 0); } else { evdev.send(EV_KEY, BTN_TOOL_PEN, 0); evdev.send(EV_SYN, SYN_REPORT, 0); } } else if (opts.touchpad_mode) { evdev.send(EV_KEY, BTN_LEFT, decoder.get_right()); evdev.send(EV_KEY, BTN_RIGHT, decoder.get_left()); if (decoder.get_mode() == UDrawDecoder::FINGER_MODE) { if (!finger_touching) { touch_pos_x = decoder.get_x(); touch_pos_y = decoder.get_y(); finger_touching = true; if (touch_pos_x > 1800) { scroll_wheel = true; wheel_distance = 0; } else { scroll_wheel = false; } } if (scroll_wheel) { wheel_distance += (decoder.get_y() - touch_pos_y) / 10; int rel = wheel_distance/10; if (rel != 0) { evdev.send(EV_REL, REL_WHEEL, -rel); wheel_distance -= rel; touch_pos_x = decoder.get_x(); touch_pos_y = decoder.get_y(); //std::cout << rel << " " << wheel_distance << std::endl; } } else { evdev.send(EV_REL, REL_X, decoder.get_x() - touch_pos_x); evdev.send(EV_REL, REL_Y, decoder.get_y() - touch_pos_y); touch_pos_x = decoder.get_x(); touch_pos_y = decoder.get_y(); } } else { finger_touching = false; } evdev.send(EV_SYN, SYN_REPORT, 0); } else if (opts.accelerometer_mode) { if (size != 27) { std::cerr << "unknown read size: " << size << std::endl; } else { //data[0]; int x = data[15] * 255 + data[17]; // x - pen: 3px resolution int y = data[16] * 255 + data[18]; // y - finger: 1px resolution if (data[11] == 0x00) { std::cout << "nothing"; } else if (data[11] == 0x80) { std::cout << boost::format("finger: x: %4d y: %4d") % x % y; } else if (data[11] == 0x40) { std::cout << boost::format("pen: x: %4d y: %4d - pressure: %3d") % x % y % (int(data[13]) - 0x70); } else { std::cout << boost::format("pinch: x: %4d y: %4d distance: %4d orientation: %02x") % x % y % int(data[12]) % (int(data[11]) - 0xc0); } int acc_x = ((data[19] + data[20] * 255) - 512); int acc_y = ((data[21] + data[22] * 255) - 512); int acc_z = ((data[23] + data[24] * 255) - 512); acc_x_min = std::min(acc_x, acc_x_min); acc_y_min = std::min(acc_y, acc_y_min); acc_z_min = std::min(acc_z, acc_z_min); acc_x_max = std::max(acc_x, acc_x_max); acc_y_max = std::max(acc_y, acc_y_max); acc_z_max = std::max(acc_z, acc_z_max); // acc_min -31 -33 -33 // acc_max 31 28 29 // ~22 == 1g // accelerometer std::cout << boost::format("%4d %4d %4d - %4d %4d %4d - %4d %4d %4d") % acc_x % acc_y % acc_z % acc_x_min % acc_y_min % acc_z_min % acc_x_max % acc_y_max % acc_z_max; std::cout << std::endl; } } else { print_raw_data(std::cout, data, size); std::cout << std::endl; } if (false) { evdev.send(EV_KEY, BTN_RIGHT, decoder.get_left()); evdev.send(EV_KEY, BTN_MIDDLE, decoder.get_up()); evdev.send(EV_KEY, BTN_LEFT, decoder.get_right()); evdev.send(EV_REL, REL_WHEEL, decoder.get_triangle() ? 1 : 0); evdev.send(EV_REL, REL_WHEEL, decoder.get_cross() ? -1 : 0); evdev.send(EV_KEY, KEY_BACK, decoder.get_circle()); evdev.send(EV_KEY, KEY_FORWARD, decoder.get_square()); if (false) { // FIXME: does not work as is, needs throttling if (decoder.get_mode() == UDrawDecoder::PINCH_MODE) { if (!pinch_touching) { touch_pos_x = decoder.get_x(); touch_pos_y = decoder.get_y(); pinch_touching = true; } evdev.send(EV_REL, REL_HWHEEL, decoder.get_x() - touch_pos_x); evdev.send(EV_REL, REL_WHEEL, decoder.get_y() - touch_pos_y); touch_pos_x = decoder.get_x(); touch_pos_y = decoder.get_y(); } else { pinch_touching = false; } evdev.send(EV_SYN, SYN_REPORT, 0); } } }); } return 0; }