usb_port
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende Überarbeitung | |||
| usb_port [2020-07-05 22:05:42] – [C/C++] manfred | usb_port [2020-07-05 23:47:55] (aktuell) – [USB-Standards] manfred | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| + | ====== USB Port ====== | ||
| + | |||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | |||
| + | |||
| + | ===== allgemeines ===== | ||
| + | |||
| + | * [[http:// | ||
| + | |||
| + | USB ist die Abkürzung für Universal Serial Bus, und wie der Name schon sagt ist es wirklich ein universeller serieller Bus. | ||
| + | Er ist der Nachfolger für die meisten Schnittstellen des PCs, beispielsweise für die serielle Schnittstelle (RS-232) und den Parallelport sowie PS/2 (Maus- u. Tastatur-Anschluss). | ||
| + | Für den Hobby-Elektroniker ist der USB-Bus attraktiv, da er den Bus auch zur Stromversorgung nutzen kann und sich um das Protokoll und Parameter wie die Geschwindigkeit wenig Gedanken machen muss. | ||
| + | |||
| + | Von dem USB-Stardard wird USB mechanisch, elektrisch und logisch spezifiziert. Im Gegensatz zum Parallelport sind daher die Datenprotokolle hier schon im Standard spezifiziert. USB ist auch interruptfähig, | ||
| + | Wie auch Firewire hat USB eine Stromversorgungs- und eine Massen-Ader, | ||
| + | Eine gute Übersicht über die Pins und Modi des USB findet man unter [[http:// | ||
| + | . Auf diesem in der Mitte der 90er entwickelten Bus werden die Daten differentiell über ein Aderpaar übertragen. Hierdurch können die Daten, im Gegensatz zu Firewire, das (mindestens) zwei Adernpaare verwendet, nicht gleichzeitig gesendet und empfangen werden. Dadurch verwendet USB weniger Hardware und ist entsprechend auch bei den Kabeln billiger als Alternativen wie Firewire. Dies hat, im Vergleich zu Firewire, einige Nachteile, wie sich beispielsweise an externen Festplatten sowohl bei der Performance (Latenzzeit u. Transferrate) als auch der CPU-Last zeigt. Ein weiterer Nachteil ist, dass es an einem USB-Bus nur einen Controller gibt, der den Bus verwaltet. Hierdurch können USB-Peripherie-Geräte über einen Bus nicht direkt miteinander kommunizieren und auch PCs können nicht direkt verbunden werden, während dies mit Firewire geht. | ||
| + | |||
| + | USB kann die anderen Schnittstellen (Parallelport, | ||
| + | |||
| + | Da zum Ansteuern der USB-Hardware spezifische Treiber benötigt werden, greift die Software für die am USB angeschlossene Hardware praktisch nie direkt auf die Hardware zu, sondern verwendet die Schnittstellen zum USB-Treiber. Aus diesem Grund wird hier nur die indirekte Ansteuerung des USB behandelt. | ||
| + | |||
| + | In der Praxis gibt es mit dem USB-Bus einige Probleme, weil sich die Hersteller nicht immer an die Standards halten. Als Folge hiervon funktioniert nicht jedes USB-Gerät an jedem PC; einige Kombinationen sind einfach unverträglich. Dies Phänomen ist aber auch von anderer Hardware bekannt, beispielsweise PCI-Karten. | ||
| + | Ein weiteres Problem ist, dass der USB nicht sehr stabil ist und beispielsweise Kartenleser nach einigen Tagen am USB-Bus Fehler produzieren, | ||
| + | |||
| + | |||
| + | ==== USB-Standards ==== | ||
| + | |||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | ^ USB 3.2 versions | ||
| + | ^ New name ^ Old name ^ Original name ^ SuperSpeed name ^ Max speed ^ | ||
| + | | USB 3.2 Gen 2x2 | N/A | USB 3.2 | SuperSpeed USB 20Gbps | 20Gbps | ||
| + | | USB 3.2 Gen 2 | USB 3.1 Gen 2 | USB 3.1 | SuperSpeed USB 10Gbps | 10Gbps | ||
| + | | USB 3.2 Gen 1 | USB 3.1 Gen 1 | USB 3.0 | SuperSpeed USB | 5Gbps | | ||
| + | |||
| + | |||
| + | ===== C/C++ ===== | ||
| + | |||
| + | * [[http:// | ||
| + | * [[http:// | ||
| + | |||
| + | |||
| + | === usbpanicbutton.c === | ||
| + | |||
| + | * [[http:// | ||
| + | |||
| + | Mit "lsusb -vvv" lassen sich Informationen über die HID Struktur eines USB Geräts ermitteln. | ||
| + | |||
| + | / | ||
| + | PoC for USB Panic Button under unix | ||
| + | | ||
| + | by: Benjamin Kendinibilir | ||
| + | | ||
| + | | ||
| + | run: sudo ./upb (needs root) | ||
| + | ==============================================*/ | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | #define VENDOR_ID 0x1130 | ||
| + | #define PRODUCT_ID 0x0202 | ||
| + | #define IFACE_NO 0 | ||
| + | #define PACKET_SIZE 8 | ||
| + | #define PATH1 0x00010000 | ||
| + | #define PATH2 0x00000000 | ||
| + | #define PATH_LEN 2 | ||
| + | |||
| + | int loop = 1; | ||
| + | |||
| + | void endloop(int signum) { | ||
| + | loop = 0; | ||
| + | } | ||
| + | |||
| + | int main(int argc, char *argv[]) { | ||
| + | hid_return ret; | ||
| + | HIDInterface* hid; | ||
| + | char packet[PACKET_SIZE]; | ||
| + | |||
| + | int const path_in[] = { PATH1, PATH2 }; | ||
| + | int const path_out[] = { PATH1, PATH2 }; | ||
| + | |||
| + | HIDInterfaceMatcher matcher = { VENDOR_ID, PRODUCT_ID, NULL, NULL, 0 }; | ||
| + | |||
| + | #ifdef DEBUG | ||
| + | hid_set_debug(HID_DEBUG_ALL); | ||
| + | hid_set_debug_stream(stderr); | ||
| + | hid_set_usb_debug(0); | ||
| + | #endif | ||
| + | |||
| + | ret = hid_init(); | ||
| + | if (ret != HID_RET_SUCCESS) { | ||
| + | fprintf(stderr, | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | hid = hid_new_HIDInterface(); | ||
| + | if (hid == 0) { | ||
| + | fprintf(stderr, | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | ret = hid_force_open(hid, | ||
| + | if (ret != HID_RET_SUCCESS) { | ||
| + | fprintf(stderr, | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | #ifdef DEBUG | ||
| + | ret = hid_write_identification(stdout, | ||
| + | if (ret != HID_RET_SUCCESS) { | ||
| + | fprintf(stderr, | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | ret = hid_dump_tree(stdout, | ||
| + | if (ret != HID_RET_SUCCESS) { | ||
| + | fprintf(stderr, | ||
| + | return 1; | ||
| + | } | ||
| + | #endif | ||
| + | |||
| + | signal(SIGINT, | ||
| + | signal(SIGHUP, | ||
| + | signal(SIGTERM, | ||
| + | |||
| + | printf(" | ||
| + | |||
| + | while(loop) { | ||
| + | ret = hid_get_input_report(hid, | ||
| + | if (ret != HID_RET_SUCCESS) { | ||
| + | fprintf(stderr, | ||
| + | } | ||
| + | |||
| + | if(packet[0] == 0x1) { | ||
| + | printf(" | ||
| + | fflush(stdout); | ||
| + | } | ||
| + | |||
| + | usleep(200000); | ||
| + | } | ||
| + | |||
| + | printf(" | ||
| + | |||
| + | ret = hid_close(hid); | ||
| + | if (ret != HID_RET_SUCCESS) { | ||
| + | fprintf(stderr, | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | hid_delete_HIDInterface(& | ||
| + | |||
| + | ret = hid_cleanup(); | ||
| + | if (ret != HID_RET_SUCCESS) { | ||
| + | fprintf(stderr, | ||
| + | return 1; | ||
| + | } | ||
| + | |||
| + | printf(" | ||
| + | |||
| + | return 0; | ||
| + | } | ||
| + | |||
| + | |||
| + | === generic_hid.c === | ||
| + | |||
| + | * [[http:// | ||
| + | |||
| + | Demonstrates communicating with generic HID-class USB devices using libusb-1.0. | ||
| + | |||
| + | /* | ||
| + | * generic_hid.c | ||
| + | * | ||
| + | | ||
| + | | ||
| + | * | ||
| + | * Demonstrates communicating with a device designed for use with a generic HID-class USB device. | ||
| + | * Sends and receives 2-byte reports. | ||
| + | * Requires: an attached HID-class device that supports 2-byte | ||
| + | * Input, Output, and Feature reports. | ||
| + | * The device firmware should respond to a received report by sending a report. | ||
| + | * Change VENDOR_ID and PRODUCT_ID to match your device' | ||
| + | * See Lvr.com/ | ||
| + | * This firmware is adapted from code provided by Xiaofan. | ||
| + | * Note: libusb error codes are negative numbers. | ||
| + | |||
| + | The application uses the libusb 1.0 API from libusb.org. | ||
| + | Compile the application with the -lusb-1.0 option. | ||
| + | Use the -I option if needed to specify the path to the libusb.h header file. For example: | ||
| + | -I/ | ||
| + | */ | ||
| + | | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | | ||
| + | // Values for bmRequestType in the Setup transaction' | ||
| + | | ||
| + | static const int CONTROL_REQUEST_TYPE_IN = LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE; | ||
| + | static const int CONTROL_REQUEST_TYPE_OUT = LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE; | ||
| + | | ||
| + | // From the HID spec: | ||
| + | static const int HID_GET_REPORT = 0x01; | ||
| + | static const int HID_SET_REPORT = 0x09; | ||
| + | static const int HID_REPORT_TYPE_INPUT = 0x01; | ||
| + | static const int HID_REPORT_TYPE_OUTPUT = 0x02; | ||
| + | static const int HID_REPORT_TYPE_FEATURE = 0x03; | ||
| + | | ||
| + | // With firmware support, transfers can be > the endpoint' | ||
| + | | ||
| + | static const int MAX_CONTROL_IN_TRANSFER_SIZE = 2; | ||
| + | static const int MAX_CONTROL_OUT_TRANSFER_SIZE = 2; | ||
| + | | ||
| + | static const int INTERFACE_NUMBER = 0; | ||
| + | static const int TIMEOUT_MS = 5000; | ||
| + | | ||
| + | int exchange_feature_reports_via_control_transfers(libusb_device_handle *devh); | ||
| + | int exchange_input_and_output_reports_via_control_transfers(libusb_device_handle *devh); | ||
| + | int exchange_input_and_output_reports_via_interrupt_transfers(libusb_device_handle *devh); | ||
| + | | ||
| + | int main(void) | ||
| + | { | ||
| + | // Change these as needed to match idVendor and idProduct in your device' | ||
| + | | ||
| + | static const int VENDOR_ID = 0x0925; | ||
| + | static const int PRODUCT_ID = 0x7001; | ||
| + | | ||
| + | struct libusb_device_handle *devh = NULL; | ||
| + | int device_ready = 0; | ||
| + | int result; | ||
| + | | ||
| + | result = libusb_init(NULL); | ||
| + | if (result >= 0) | ||
| + | { | ||
| + | devh = libusb_open_device_with_vid_pid(NULL, | ||
| + | | ||
| + | if (devh != NULL) | ||
| + | { | ||
| + | // The HID has been detected. | ||
| + | // Detach the hidusb driver from the HID to enable using libusb. | ||
| + | | ||
| + | libusb_detach_kernel_driver(devh, | ||
| + | { | ||
| + | result = libusb_claim_interface(devh, | ||
| + | if (result >= 0) | ||
| + | { | ||
| + | device_ready = 1; | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | } | ||
| + | | ||
| + | if (device_ready) | ||
| + | { | ||
| + | // Send and receive data. | ||
| + | | ||
| + | exchange_input_and_output_reports_via_interrupt_transfers(devh); | ||
| + | exchange_input_and_output_reports_via_control_transfers(devh); | ||
| + | exchange_feature_reports_via_control_transfers(devh); | ||
| + | | ||
| + | // Finished using the device. | ||
| + | | ||
| + | libusb_release_interface(devh, | ||
| + | } | ||
| + | libusb_close(devh); | ||
| + | libusb_exit(NULL); | ||
| + | return 0; | ||
| + | } | ||
| + | | ||
| + | // Uses control transfers to write a Feature report to the HID | ||
| + | // and receive a Feature report from the HID. | ||
| + | // Returns - zero on success, libusb error code on failure. | ||
| + | | ||
| + | int exchange_feature_reports_via_control_transfers(libusb_device_handle *devh) | ||
| + | { | ||
| + | int bytes_received; | ||
| + | int bytes_sent; | ||
| + | char data_in[MAX_CONTROL_IN_TRANSFER_SIZE]; | ||
| + | char data_out[MAX_CONTROL_OUT_TRANSFER_SIZE]; | ||
| + | int result = 0; | ||
| + | | ||
| + | // Store example data in the output buffer for sending. | ||
| + | // This example uses binary data. | ||
| + | | ||
| + | for (i=0;i < MAX_CONTROL_OUT_TRANSFER_SIZE; | ||
| + | { | ||
| + | data_out[i]=0x30+i; | ||
| + | } | ||
| + | | ||
| + | // Send data to the device. | ||
| + | | ||
| + | bytes_sent = libusb_control_transfer( | ||
| + | devh, | ||
| + | CONTROL_REQUEST_TYPE_OUT , | ||
| + | HID_SET_REPORT, | ||
| + | (HID_REPORT_TYPE_FEATURE<< | ||
| + | INTERFACE_NUMBER, | ||
| + | data_out, | ||
| + | sizeof(data_out), | ||
| + | TIMEOUT_MS); | ||
| + | | ||
| + | if (bytes_sent >= 0) | ||
| + | { | ||
| + | printf(" | ||
| + | for(i = 0; i < bytes_sent; i++) | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | printf(" | ||
| + | | ||
| + | // Request data from the device. | ||
| + | | ||
| + | bytes_received = libusb_control_transfer( | ||
| + | devh, | ||
| + | CONTROL_REQUEST_TYPE_IN , | ||
| + | HID_GET_REPORT, | ||
| + | (HID_REPORT_TYPE_FEATURE<< | ||
| + | INTERFACE_NUMBER, | ||
| + | data_in, | ||
| + | MAX_CONTROL_IN_TRANSFER_SIZE, | ||
| + | TIMEOUT_MS); | ||
| + | | ||
| + | if (bytes_received >= 0) | ||
| + | { | ||
| + | printf(" | ||
| + | for(i = 0; i < bytes_received; | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | printf(" | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | return result; | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | return result; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | | ||
| + | // Uses control transfers to write an Output report to the HID | ||
| + | // and receive an Input report from the HID. | ||
| + | // Returns - zero on success, libusb error code on failure. | ||
| + | | ||
| + | int exchange_input_and_output_reports_via_control_transfers(libusb_device_handle *devh) | ||
| + | { | ||
| + | int bytes_received; | ||
| + | int bytes_sent; | ||
| + | char data_in[MAX_CONTROL_IN_TRANSFER_SIZE]; | ||
| + | char data_out[MAX_CONTROL_OUT_TRANSFER_SIZE]; | ||
| + | int result = 0; | ||
| + | | ||
| + | // Store example data in the output buffer for sending. | ||
| + | // This example uses binary data. | ||
| + | | ||
| + | for (i=0;i < MAX_CONTROL_OUT_TRANSFER_SIZE; | ||
| + | { | ||
| + | data_out[i]=0x40+i; | ||
| + | } | ||
| + | | ||
| + | // Send data to the device. | ||
| + | | ||
| + | bytes_sent = libusb_control_transfer( | ||
| + | devh, | ||
| + | CONTROL_REQUEST_TYPE_OUT , | ||
| + | HID_SET_REPORT, | ||
| + | (HID_REPORT_TYPE_OUTPUT<< | ||
| + | INTERFACE_NUMBER, | ||
| + | data_out, | ||
| + | sizeof(data_out), | ||
| + | TIMEOUT_MS); | ||
| + | | ||
| + | if (bytes_sent >= 0) | ||
| + | { | ||
| + | printf(" | ||
| + | for(i = 0; i < bytes_sent; i++) | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | printf(" | ||
| + | | ||
| + | // Request data from the device. | ||
| + | | ||
| + | bytes_received = libusb_control_transfer( | ||
| + | devh, | ||
| + | CONTROL_REQUEST_TYPE_IN , | ||
| + | HID_GET_REPORT, | ||
| + | (HID_REPORT_TYPE_INPUT<< | ||
| + | INTERFACE_NUMBER, | ||
| + | data_in, | ||
| + | MAX_CONTROL_IN_TRANSFER_SIZE, | ||
| + | TIMEOUT_MS); | ||
| + | | ||
| + | if (bytes_received >= 0) | ||
| + | { | ||
| + | printf(" | ||
| + | for(i = 0; i < bytes_received; | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | printf(" | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | return result; | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | return result; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | | ||
| + | // Use interrupt transfers to to write data to the device and receive data from the device. | ||
| + | // Returns - zero on success, libusb error code on failure. | ||
| + | | ||
| + | int exchange_input_and_output_reports_via_interrupt_transfers(libusb_device_handle *devh) | ||
| + | { | ||
| + | | ||
| + | // Assumes interrupt endpoint 2 IN and OUT: | ||
| + | | ||
| + | static const int INTERRUPT_IN_ENDPOINT = 0x81; | ||
| + | static const int INTERRUPT_OUT_ENDPOINT = 0x01; | ||
| + | | ||
| + | // With firmware support, transfers can be > the endpoint' | ||
| + | | ||
| + | static const int MAX_INTERRUPT_IN_TRANSFER_SIZE = 2; | ||
| + | static const int MAX_INTERRUPT_OUT_TRANSFER_SIZE = 2; | ||
| + | | ||
| + | int bytes_transferred; | ||
| + | int i = 0; | ||
| + | int result = 0;; | ||
| + | | ||
| + | char data_in[MAX_INTERRUPT_IN_TRANSFER_SIZE]; | ||
| + | char data_out[MAX_INTERRUPT_OUT_TRANSFER_SIZE]; | ||
| + | | ||
| + | // Store data in a buffer for sending. | ||
| + | | ||
| + | for (i=0;i < MAX_INTERRUPT_OUT_TRANSFER_SIZE; | ||
| + | { | ||
| + | data_out[i]=0x40+i; | ||
| + | } | ||
| + | // Write data to the device. | ||
| + | | ||
| + | result = libusb_interrupt_transfer( | ||
| + | devh, | ||
| + | INTERRUPT_OUT_ENDPOINT, | ||
| + | data_out, | ||
| + | MAX_INTERRUPT_OUT_TRANSFER_SIZE, | ||
| + | & | ||
| + | TIMEOUT_MS); | ||
| + | | ||
| + | if (result >= 0) | ||
| + | { | ||
| + | printf(" | ||
| + | for(i = 0; i < bytes_transferred; | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | printf(" | ||
| + | | ||
| + | // Read data from the device. | ||
| + | | ||
| + | result = libusb_interrupt_transfer( | ||
| + | devh, | ||
| + | INTERRUPT_IN_ENDPOINT, | ||
| + | data_in, | ||
| + | MAX_INTERRUPT_OUT_TRANSFER_SIZE, | ||
| + | & | ||
| + | TIMEOUT_MS); | ||
| + | | ||
| + | if (result >= 0) | ||
| + | { | ||
| + | if (bytes_transferred > 0) | ||
| + | { | ||
| + | printf(" | ||
| + | for(i = 0; i < bytes_transferred; | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | printf(" | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | return -1; | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | return result; | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | fprintf(stderr, | ||
| + | return result; | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | |||
