forked from mirrors/qmk_userspace
		
	[Maintenance] USB HID control packet as struct (#21688)
* ChibiOS: USB HID control request as dedicated struct Instead of accessing the raw USB setup packet and documenting the values as the corresponding USB HID control request fields we introduce a struct that allows direct access to the fields. This is safer and self documenting. * Rename usb_request.h to usb_types.h In the future all shared USB data types can live in this file.
This commit is contained in:
		
					parent
					
						
							
								64d1ce751f
							
						
					
				
			
			
				commit
				
					
						5856d5e13b
					
				
			
		
					 2 changed files with 82 additions and 92 deletions
				
			
		| 
						 | 
					@ -43,6 +43,7 @@
 | 
				
			||||||
#include "usb_device_state.h"
 | 
					#include "usb_device_state.h"
 | 
				
			||||||
#include "usb_descriptor.h"
 | 
					#include "usb_descriptor.h"
 | 
				
			||||||
#include "usb_driver.h"
 | 
					#include "usb_driver.h"
 | 
				
			||||||
 | 
					#include "usb_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef NKRO_ENABLE
 | 
					#ifdef NKRO_ENABLE
 | 
				
			||||||
#    include "keycode_config.h"
 | 
					#    include "keycode_config.h"
 | 
				
			||||||
| 
						 | 
					@ -103,30 +104,18 @@ union {
 | 
				
			||||||
            NULL, /* SETUP buffer (not a SETUP endpoint) */
 | 
					            NULL, /* SETUP buffer (not a SETUP endpoint) */
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* HID specific constants */
 | 
					 | 
				
			||||||
#define HID_GET_REPORT 0x01
 | 
					 | 
				
			||||||
#define HID_GET_IDLE 0x02
 | 
					 | 
				
			||||||
#define HID_GET_PROTOCOL 0x03
 | 
					 | 
				
			||||||
#define HID_SET_REPORT 0x09
 | 
					 | 
				
			||||||
#define HID_SET_IDLE 0x0A
 | 
					 | 
				
			||||||
#define HID_SET_PROTOCOL 0x0B
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Handles the GET_DESCRIPTOR callback
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns the proper descriptor
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) {
 | 
					static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) {
 | 
				
			||||||
    (void)usbp;
 | 
					    usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
 | 
				
			||||||
    static USBDescriptor desc;
 | 
					
 | 
				
			||||||
    uint16_t             wValue  = ((uint16_t)dtype << 8) | dindex;
 | 
					    static USBDescriptor descriptor;
 | 
				
			||||||
    uint16_t             wLength = ((uint16_t)usbp->setup[7] << 8) | usbp->setup[6];
 | 
					    descriptor.ud_string = NULL;
 | 
				
			||||||
    desc.ud_string               = NULL;
 | 
					    descriptor.ud_size   = get_usb_descriptor(setup->wValue.word, setup->wIndex, setup->wLength, (const void **const) & descriptor.ud_string);
 | 
				
			||||||
    desc.ud_size                 = get_usb_descriptor(wValue, wIndex, wLength, (const void **const) & desc.ud_string);
 | 
					
 | 
				
			||||||
    if (desc.ud_string == NULL)
 | 
					    if (descriptor.ud_string == NULL) {
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    else
 | 
					    }
 | 
				
			||||||
        return &desc;
 | 
					
 | 
				
			||||||
 | 
					    return &descriptor;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -497,8 +486,7 @@ void usb_event_queue_task(void) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Handles the USB driver global events
 | 
					/* Handles the USB driver global events. */
 | 
				
			||||||
 * TODO: maybe disable some things when connection is lost? */
 | 
					 | 
				
			||||||
static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
 | 
					static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
 | 
				
			||||||
    switch (event) {
 | 
					    switch (event) {
 | 
				
			||||||
        case USB_EVENT_ADDRESS:
 | 
					        case USB_EVENT_ADDRESS:
 | 
				
			||||||
| 
						 | 
					@ -570,16 +558,6 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Function used locally in os/hal/src/usb.c for getting descriptors
 | 
					 | 
				
			||||||
 * need it here for HID descriptor */
 | 
					 | 
				
			||||||
static uint16_t get_hword(uint8_t *p) {
 | 
					 | 
				
			||||||
    uint16_t hw;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    hw = (uint16_t)*p++;
 | 
					 | 
				
			||||||
    hw |= (uint16_t)*p << 8U;
 | 
					 | 
				
			||||||
    return hw;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Appendix G: HID Request Support Requirements
 | 
					 * Appendix G: HID Request Support Requirements
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -596,7 +574,9 @@ static uint16_t get_hword(uint8_t *p) {
 | 
				
			||||||
static uint8_t set_report_buf[2] __attribute__((aligned(4)));
 | 
					static uint8_t set_report_buf[2] __attribute__((aligned(4)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void set_led_transfer_cb(USBDriver *usbp) {
 | 
					static void set_led_transfer_cb(USBDriver *usbp) {
 | 
				
			||||||
    if (usbp->setup[6] == 2) { /* LSB(wLength) */
 | 
					    usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (setup->wLength == 2) {
 | 
				
			||||||
        uint8_t report_id = set_report_buf[0];
 | 
					        uint8_t report_id = set_report_buf[0];
 | 
				
			||||||
        if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) {
 | 
					        if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) {
 | 
				
			||||||
            keyboard_led_state = set_report_buf[1];
 | 
					            keyboard_led_state = set_report_buf[1];
 | 
				
			||||||
| 
						 | 
					@ -606,24 +586,16 @@ static void set_led_transfer_cb(USBDriver *usbp) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Callback for SETUP request on the endpoint 0 (control) */
 | 
					static bool usb_requests_hook_cb(USBDriver *usbp) {
 | 
				
			||||||
static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
					    usb_control_request_t *setup = (usb_control_request_t *)usbp->setup;
 | 
				
			||||||
    const USBDescriptor *dp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* usbp->setup fields:
 | 
					 | 
				
			||||||
     *  0:   bmRequestType (bitmask)
 | 
					 | 
				
			||||||
     *  1:   bRequest
 | 
					 | 
				
			||||||
     *  2,3: (LSB,MSB) wValue
 | 
					 | 
				
			||||||
     *  4,5: (LSB,MSB) wIndex
 | 
					 | 
				
			||||||
     *  6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Handle HID class specific requests */
 | 
					    /* Handle HID class specific requests */
 | 
				
			||||||
    if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) && ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
 | 
					    if ((setup->bmRequestType & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE)) {
 | 
				
			||||||
        switch (usbp->setup[0] & USB_RTYPE_DIR_MASK) {
 | 
					        switch (setup->bmRequestType & USB_RTYPE_DIR_MASK) {
 | 
				
			||||||
            case USB_RTYPE_DIR_DEV2HOST:
 | 
					            case USB_RTYPE_DIR_DEV2HOST:
 | 
				
			||||||
                switch (usbp->setup[1]) { /* bRequest */
 | 
					                switch (setup->bRequest) {
 | 
				
			||||||
                    case HID_GET_REPORT:
 | 
					                    case HID_REQ_GetReport:
 | 
				
			||||||
                        switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
 | 
					                        switch (setup->wIndex) {
 | 
				
			||||||
#ifndef KEYBOARD_SHARED_EP
 | 
					#ifndef KEYBOARD_SHARED_EP
 | 
				
			||||||
                            case KEYBOARD_INTERFACE:
 | 
					                            case KEYBOARD_INTERFACE:
 | 
				
			||||||
                                usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL);
 | 
					                                usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL);
 | 
				
			||||||
| 
						 | 
					@ -639,59 +611,54 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
				
			||||||
#ifdef SHARED_EP_ENABLE
 | 
					#ifdef SHARED_EP_ENABLE
 | 
				
			||||||
                            case SHARED_INTERFACE:
 | 
					                            case SHARED_INTERFACE:
 | 
				
			||||||
#    ifdef KEYBOARD_SHARED_EP
 | 
					#    ifdef KEYBOARD_SHARED_EP
 | 
				
			||||||
                                if (usbp->setup[2] == REPORT_ID_KEYBOARD) {
 | 
					                                if (setup->wValue.lbyte == REPORT_ID_KEYBOARD) {
 | 
				
			||||||
                                    usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL);
 | 
					                                    usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL);
 | 
				
			||||||
                                    return TRUE;
 | 
					                                    return true;
 | 
				
			||||||
                                    break;
 | 
					 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
#    endif
 | 
					#    endif
 | 
				
			||||||
#    ifdef MOUSE_SHARED_EP
 | 
					#    ifdef MOUSE_SHARED_EP
 | 
				
			||||||
                                if (usbp->setup[2] == REPORT_ID_MOUSE) {
 | 
					                                if (setup->wValue.lbyte == REPORT_ID_MOUSE) {
 | 
				
			||||||
                                    usbSetupTransfer(usbp, (uint8_t *)&mouse_report_sent, sizeof(mouse_report_sent), NULL);
 | 
					                                    usbSetupTransfer(usbp, (uint8_t *)&mouse_report_sent, sizeof(mouse_report_sent), NULL);
 | 
				
			||||||
                                    return TRUE;
 | 
					                                    return true;
 | 
				
			||||||
                                    break;
 | 
					 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
#    endif
 | 
					#    endif
 | 
				
			||||||
#endif /* SHARED_EP_ENABLE */
 | 
					#endif /* SHARED_EP_ENABLE */
 | 
				
			||||||
                            default:
 | 
					                            default:
 | 
				
			||||||
                                universal_report_blank.report_id = usbp->setup[2];
 | 
					                                universal_report_blank.report_id = setup->wValue.lbyte;
 | 
				
			||||||
                                usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, usbp->setup[6], NULL);
 | 
					                                usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, setup->wLength, NULL);
 | 
				
			||||||
                                return TRUE;
 | 
					                                return true;
 | 
				
			||||||
                                break;
 | 
					 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case HID_GET_PROTOCOL:
 | 
					                    case HID_REQ_GetProtocol:
 | 
				
			||||||
                        if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
 | 
					                        if (setup->wIndex == KEYBOARD_INTERFACE) {
 | 
				
			||||||
                            usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
 | 
					                            usbSetupTransfer(usbp, &keyboard_protocol, sizeof(uint8_t), NULL);
 | 
				
			||||||
                            return TRUE;
 | 
					                            return true;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case HID_GET_IDLE:
 | 
					                    case HID_REQ_GetIdle:
 | 
				
			||||||
                        usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
 | 
					                        usbSetupTransfer(usbp, &keyboard_idle, sizeof(uint8_t), NULL);
 | 
				
			||||||
                        return TRUE;
 | 
					                        return true;
 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            case USB_RTYPE_DIR_HOST2DEV:
 | 
					            case USB_RTYPE_DIR_HOST2DEV:
 | 
				
			||||||
                switch (usbp->setup[1]) { /* bRequest */
 | 
					                switch (setup->bRequest) {
 | 
				
			||||||
                    case HID_SET_REPORT:
 | 
					                    case HID_REQ_SetReport:
 | 
				
			||||||
                        switch (usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
 | 
					                        switch (setup->wIndex) {
 | 
				
			||||||
                            case KEYBOARD_INTERFACE:
 | 
					                            case KEYBOARD_INTERFACE:
 | 
				
			||||||
#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
 | 
					#if defined(SHARED_EP_ENABLE) && !defined(KEYBOARD_SHARED_EP)
 | 
				
			||||||
                            case SHARED_INTERFACE:
 | 
					                            case SHARED_INTERFACE:
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
                                usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
 | 
					                                usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb);
 | 
				
			||||||
                                return TRUE;
 | 
					                                return true;
 | 
				
			||||||
                                break;
 | 
					 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case HID_SET_PROTOCOL:
 | 
					                    case HID_REQ_SetProtocol:
 | 
				
			||||||
                        if ((usbp->setup[4] == KEYBOARD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
 | 
					                        if (setup->wIndex == KEYBOARD_INTERFACE) {
 | 
				
			||||||
                            keyboard_protocol = ((usbp->setup[2]) != 0x00);                    /* LSB(wValue) */
 | 
					                            keyboard_protocol = setup->wValue.word;
 | 
				
			||||||
#ifdef NKRO_ENABLE
 | 
					#ifdef NKRO_ENABLE
 | 
				
			||||||
                            if (!keyboard_protocol && keyboard_idle) {
 | 
					                            if (!keyboard_protocol && keyboard_idle) {
 | 
				
			||||||
#else  /* NKRO_ENABLE */
 | 
					#else  /* NKRO_ENABLE */
 | 
				
			||||||
| 
						 | 
					@ -704,12 +671,11 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        usbSetupTransfer(usbp, NULL, 0, NULL);
 | 
					                        usbSetupTransfer(usbp, NULL, 0, NULL);
 | 
				
			||||||
                        return TRUE;
 | 
					                        return true;
 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    case HID_SET_IDLE:
 | 
					                    case HID_REQ_SetIdle:
 | 
				
			||||||
                        keyboard_idle = usbp->setup[3]; /* MSB(wValue) */
 | 
					                        keyboard_idle = setup->wValue.hbyte;
 | 
				
			||||||
                                                        /* arm the timer */
 | 
					                        /* arm the timer */
 | 
				
			||||||
#ifdef NKRO_ENABLE
 | 
					#ifdef NKRO_ENABLE
 | 
				
			||||||
                        if (!keymap_config.nkro && keyboard_idle) {
 | 
					                        if (!keymap_config.nkro && keyboard_idle) {
 | 
				
			||||||
#else  /* NKRO_ENABLE */
 | 
					#else  /* NKRO_ENABLE */
 | 
				
			||||||
| 
						 | 
					@ -720,19 +686,21 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
				
			||||||
                            osalSysUnlockFromISR();
 | 
					                            osalSysUnlockFromISR();
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        usbSetupTransfer(usbp, NULL, 0, NULL);
 | 
					                        usbSetupTransfer(usbp, NULL, 0, NULL);
 | 
				
			||||||
                        return TRUE;
 | 
					                        return true;
 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
 | 
					    /* Handle the Get_Descriptor Request for HID class, which is not handled by
 | 
				
			||||||
    if ((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
 | 
					     * the ChibiOS USB driver */
 | 
				
			||||||
        dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
 | 
					    if (((setup->bmRequestType & (USB_RTYPE_DIR_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_DIR_DEV2HOST | USB_RTYPE_RECIPIENT_INTERFACE)) && (setup->bRequest == USB_REQ_GET_DESCRIPTOR)) {
 | 
				
			||||||
        if (dp == NULL) return FALSE;
 | 
					        const USBDescriptor *descriptor = usbp->config->get_descriptor_cb(usbp, setup->wValue.lbyte, setup->wValue.hbyte, setup->wIndex);
 | 
				
			||||||
        usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
 | 
					        if (descriptor == NULL) {
 | 
				
			||||||
        return TRUE;
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        usbSetupTransfer(usbp, (uint8_t *)descriptor->ud_string, descriptor->ud_size, NULL);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int i = 0; i < NUM_USB_DRIVERS; i++) {
 | 
					    for (int i = 0; i < NUM_USB_DRIVERS; i++) {
 | 
				
			||||||
| 
						 | 
					@ -742,10 +710,9 @@ static bool usb_request_hook_cb(USBDriver *usbp) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return FALSE;
 | 
					    return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Start-of-frame callback */
 | 
					 | 
				
			||||||
static void usb_sof_cb(USBDriver *usbp) {
 | 
					static void usb_sof_cb(USBDriver *usbp) {
 | 
				
			||||||
    osalSysLockFromISR();
 | 
					    osalSysLockFromISR();
 | 
				
			||||||
    for (int i = 0; i < NUM_USB_DRIVERS; i++) {
 | 
					    for (int i = 0; i < NUM_USB_DRIVERS; i++) {
 | 
				
			||||||
| 
						 | 
					@ -758,7 +725,7 @@ static void usb_sof_cb(USBDriver *usbp) {
 | 
				
			||||||
static const USBConfig usbcfg = {
 | 
					static const USBConfig usbcfg = {
 | 
				
			||||||
    usb_event_cb,          /* USB events callback */
 | 
					    usb_event_cb,          /* USB events callback */
 | 
				
			||||||
    usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
 | 
					    usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
 | 
				
			||||||
    usb_request_hook_cb,   /* Requests hook callback */
 | 
					    usb_requests_hook_cb,  /* Requests hook callback */
 | 
				
			||||||
    usb_sof_cb             /* Start Of Frame callback */
 | 
					    usb_sof_cb             /* Start Of Frame callback */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								tmk_core/protocol/usb_types.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tmk_core/protocol/usb_types.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					// Copyright 2023 Stefan Kerkmann
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0-or-later
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Common USB 2.0 control request structure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint8_t bmRequestType; // [0] (Bitmask)
 | 
				
			||||||
 | 
					    uint8_t bRequest;      // [1]
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					            uint8_t lbyte; // [2] (LSB)
 | 
				
			||||||
 | 
					            uint8_t hbyte; // [3] (MSB)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        uint16_t word; // [2,3] (LSB,MSB)
 | 
				
			||||||
 | 
					    } wValue;
 | 
				
			||||||
 | 
					    uint16_t wIndex;  // [4,5] (LSB,MSB)
 | 
				
			||||||
 | 
					    uint16_t wLength; // [6,7] (LSB,MSB)
 | 
				
			||||||
 | 
					} PACKED usb_control_request_t;
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue