You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
3.6 KiB
186 lines
3.6 KiB
/** |
|
* USB debuggign tool for Pinephone keyboard |
|
* |
|
* Copyright (C) 2021 Ondřej Jirman <megi@xff.cz> |
|
* |
|
* This program is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, either version 3 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
|
|
#include "common.c" |
|
|
|
int kb_open(void) |
|
{ |
|
int ret, fd; |
|
|
|
// first check if keyboard USB device is available, if it is |
|
// we need to first switch to bootloader mode |
|
|
|
fd = open_usb_dev(0x04f3, 0xb001); |
|
if (fd >= 0) { |
|
struct usbdevfs_disconnect_claim dc = { |
|
.interface = 0, |
|
}; |
|
|
|
ret = ioctl(fd, USBDEVFS_DISCONNECT_CLAIM, &dc); |
|
syscall_error(ret < 0, "USBDEVFS_DISCONNECT_CLAIM failed"); |
|
} |
|
|
|
return fd; |
|
} |
|
|
|
static int usb_fd = -1; |
|
|
|
int command(uint8_t req[8]) |
|
{ |
|
int ret; |
|
struct usbdevfs_urb urb = { |
|
.type = USBDEVFS_URB_TYPE_INTERRUPT, |
|
.endpoint = 0x01, |
|
// .flags = USBDEVFS_URB_ZERO_PACKET, |
|
.buffer = req, |
|
.buffer_length = 8, |
|
.actual_length = 8, |
|
}; |
|
|
|
ret = handle_urb(usb_fd, &urb, 100); |
|
if (ret) |
|
return ret; |
|
|
|
debug("CMD:"); |
|
for (int i = 0; i < urb.actual_length; i++) |
|
debug(" %02hhx", req[i]); |
|
debug("\n"); |
|
|
|
return 0; |
|
} |
|
|
|
int response(uint8_t res[8]) |
|
{ |
|
int ret; |
|
struct usbdevfs_urb urb = { |
|
.type = USBDEVFS_URB_TYPE_INTERRUPT, |
|
.endpoint = 0x82, |
|
.flags = USBDEVFS_URB_SHORT_NOT_OK, |
|
.buffer = res, |
|
.buffer_length = 8, |
|
.actual_length = 0, |
|
}; |
|
|
|
ret = handle_urb(usb_fd, &urb, 100); |
|
if (ret) |
|
return ret; |
|
|
|
if (urb.actual_length != 8) |
|
error("Status response size invalid, must be 8 bytes, got %d", urb.actual_length); |
|
|
|
debug("RES:"); |
|
for (int i = 0; i < urb.actual_length; i++) |
|
debug(" %02hhx", res[i]); |
|
debug("\n"); |
|
|
|
return 0; |
|
} |
|
|
|
int read_stdout(void) |
|
{ |
|
int ret; |
|
|
|
uint8_t buf[64]; |
|
struct usbdevfs_urb urb = { |
|
.type = USBDEVFS_URB_TYPE_INTERRUPT, |
|
.endpoint = 0x83, |
|
.buffer = buf, |
|
.buffer_length = 64, |
|
.actual_length = 0, |
|
}; |
|
|
|
ret = handle_urb(usb_fd, &urb, 10); |
|
if (ret) |
|
return ret; |
|
|
|
debug("STD%d:", urb.actual_length); |
|
for (int i = 0; i < urb.actual_length; i++) |
|
debug(" %02hhx", buf[i]); |
|
debug("\n"); |
|
|
|
if (urb.actual_length > 0) { |
|
ssize_t rv = xwrite(1, buf, urb.actual_length); |
|
if (rv < 0) |
|
return -1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
int read_keys(uint8_t buf[12]) |
|
{ |
|
int ret; |
|
struct usbdevfs_urb urb = { |
|
.type = USBDEVFS_URB_TYPE_INTERRUPT, |
|
.endpoint = 0x84, |
|
.flags = USBDEVFS_URB_SHORT_NOT_OK, |
|
.buffer = buf, |
|
.buffer_length = 12, |
|
.actual_length = 0, |
|
}; |
|
|
|
ret = handle_urb(usb_fd, &urb, 10); |
|
if (ret) |
|
return ret; |
|
|
|
return 0; |
|
} |
|
|
|
void print_bitmap(uint8_t* map) |
|
{ |
|
// printf("\033[H"); |
|
for (int r = 0; r < 6; r++) { |
|
if (r == 0) { |
|
printf(" C"); |
|
for (int c = 0; c < 12; c++) |
|
printf("%-3d", c + 1); |
|
printf("\n"); |
|
} |
|
|
|
printf("R%d", r + 1); |
|
for (int c = 0; c < 12; c++) |
|
printf(" %s", map[c] & (1u << r) ? "X" : "."); |
|
printf("\n"); |
|
} |
|
} |
|
|
|
int main(int ac, char* av[]) |
|
{ |
|
int ret; |
|
uint8_t keys[12]; |
|
|
|
usb_fd = kb_open(); |
|
if (usb_fd < 0) |
|
error("Failed to open the keyboard"); |
|
|
|
while (1) { |
|
ret = read_stdout(); |
|
if (ret < 0 && errno != 110) |
|
syscall_error(true, "read_stdout failed"); |
|
|
|
ret = read_keys(keys); |
|
if (ret < 0 && errno != 110) |
|
syscall_error(true, "read_keys failed"); |
|
|
|
if (ret == 0) |
|
print_bitmap(keys); |
|
} |
|
|
|
return 0; |
|
}
|
|
|