static usb_request_status_t usb_standard_request_get_descriptor_setup(
	usb_endpoint_t* const endpoint
) {
	switch( endpoint->setup.value_h ) {
	case USB_DESCRIPTOR_TYPE_DEVICE:
		return usb_send_descriptor(endpoint, endpoint->device->descriptor);
		
	case USB_DESCRIPTOR_TYPE_CONFIGURATION:
		// TODO: Duplicated code. Refactor.
		if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
			return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l);
		} else {
			return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l);
		}
	
	case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
		return usb_send_descriptor(endpoint, endpoint->device->qualifier_descriptor);

	case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
		// TODO: Duplicated code. Refactor.
		if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
			return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l);
		} else {
			return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l);
		}
	
	case USB_DESCRIPTOR_TYPE_STRING:
		return usb_send_descriptor_string(endpoint);
		
	case USB_DESCRIPTOR_TYPE_INTERFACE:
	case USB_DESCRIPTOR_TYPE_ENDPOINT:
	default:
		return USB_REQUEST_STATUS_STALL;
	}
}
static void usb_setup_get_descriptor(int type, int index, int lang, int len)
{
    (void)lang;
    usb_data_stage_enable(DIR_TX);
    switch (type)
    {
        case 1:
            if (index == 0)
                usb_send_descriptor(device_descriptor,
                                    sizeof(device_descriptor), len);
            else
                usb_request_error();
            break;
        case 2:
            if (index == 0)
                usb_send_descriptor(cfg_descriptor,
                                    sizeof(cfg_descriptor), len);
            else
                usb_request_error();
            break;
        case 3:
            if (index == 0)
                usb_send_descriptor(lang_descriptor,
                                    sizeof(lang_descriptor), len);
            else if (index <= N_STRING_DESCRIPTORS)
                usb_send_descriptor(string_descriptor[index - 1],
                                    string_descriptor[index - 1][0],
                                    len);
            else
                usb_request_error();
            break;
        default:
            usb_request_error();
    }
}
static usb_request_status_t usb_send_descriptor_string(
	usb_endpoint_t* const endpoint
) {
	if ((endpoint->setup.value_l == 0xee) &&
		(endpoint->device->wcid_string_descriptor != NULL)) { /* MS WCID string */
		return usb_send_descriptor(endpoint, endpoint->device->wcid_string_descriptor);
	} else {
		uint_fast8_t index = endpoint->setup.value_l;
		for( uint_fast8_t i=0; endpoint->device->descriptor_strings[i] != 0; i++ ) {
			if( i == index ) {
				return usb_send_descriptor(endpoint, endpoint->device->descriptor_strings[i]);
			}
		}
	}
	return USB_REQUEST_STATUS_STALL;
}
usb_request_status_t usb_vendor_request_read_wcid(
		usb_endpoint_t* const endpoint,
		const usb_transfer_stage_t stage
) {
	if( stage == USB_TRANSFER_STAGE_SETUP ) {
		if ((endpoint->setup.index == 0x04) &&
			(endpoint->device->wcid_feature_descriptor != NULL)) {
			usb_send_descriptor(endpoint, endpoint->device->wcid_feature_descriptor);
			return USB_REQUEST_STATUS_OK;
		}
		if ((endpoint->setup.index == 0x05) &&
			(endpoint->device->wcid_extended_properties_descriptor != NULL)) {
			usb_send_descriptor(endpoint, endpoint->device->wcid_extended_properties_descriptor);
			return USB_REQUEST_STATUS_OK;
		}
		return USB_REQUEST_STATUS_STALL;
	}
	return USB_REQUEST_STATUS_OK;
}
static usb_request_status_t usb_send_descriptor_string(
	usb_endpoint_t* const endpoint
) {
	uint_fast8_t index = endpoint->setup.value_l;
	for( uint_fast8_t i=0; usb_descriptor_strings[i] != 0; i++ ) {
		if( i == index ) {
			return usb_send_descriptor(endpoint, usb_descriptor_strings[i]);
		}
	}

	return USB_REQUEST_STATUS_STALL;
}
static usb_request_status_t usb_send_descriptor_config(
	usb_endpoint_t* const endpoint,
	usb_speed_t speed,
	const uint8_t config_num
) {
	usb_configuration_t** config = *(endpoint->device->configurations);
	unsigned int i = 0;
	for( ; *config != NULL; config++ ) {
		if( (*config)->speed == speed) {
			if (i == config_num) {
				return usb_send_descriptor(endpoint, (*config)->descriptor);
			} else {
				i++;
			}
		}
	}
	return USB_REQUEST_STATUS_STALL;
}
Exemple #7
0
void usb_handle_StandardDeviceRequest(BDentry *bdp) {
    unsigned char *packet = bdp->BDADDR;
    int i;

    switch (packet[USB_bRequest]) {
        case USB_REQUEST_GET_STATUS:
            rbdp->BDADDR[0] = usb_device_status & 0xFF;
            rbdp->BDADDR[1] = usb_device_status >> 8;

            // JTR I added usb_ack_dat1() simply so that the handling
            // of STANDARD and CLASS requests (in cdc.c) were consistant
            // rather than have the same thing done in two different ways.

            usb_ack_dat1(rbdp, 2); // JTR common addition for STD and CLASS ACK
            break;
        case USB_REQUEST_CLEAR_FEATURE:
            if (0x01u == packet[USB_wValue]) { // TODO: Remove magic (REMOTE_WAKEUP_FEATURE)
                usb_device_status &= ~0x0002;
                usb_ack_dat1(rbdp, 0); // JTR common addition for STD and CLASS ACK
            } else
                usb_RequestError();
            break;
        case USB_REQUEST_SET_FEATURE:
            if (0x01u == packet[USB_wValue]) { // TODO: Remove magic (REMOTE_WAKEUP_FEATURE)
                usb_device_status |= 0x0002;
                usb_ack_dat1(rbdp, 0); // JTR common addition for STD and CLASS ACK
            } else
                usb_RequestError();
            break;
        case USB_REQUEST_SET_ADDRESS:
            if (0x00u == packet[USB_wValueHigh] && 0x7Fu >= packet[USB_wValue]) {
                usb_addr_pending = packet[USB_wValue];
                usb_ack_dat1(rbdp, 0); // JTR common addition for STD and CLASS ACK
                usb_set_in_handler(0, usb_set_address);
            } else
                usb_RequestError();
            break;


        case USB_REQUEST_GET_DESCRIPTOR:
            switch (packet[USB_bDescriptorType]) {
                case USB_DEVICE_DESCRIPTOR_TYPE:
                    usb_desc_ptr = usb_device_descriptor;
                    usb_desc_len = usb_device_descriptor[0];
                    if ((0 == packet[USB_wLengthHigh] && packet[USB_wLength] < usb_desc_ptr[0]))
                        usb_desc_len = packet[USB_wLength];
                    break;
                case USB_CONFIGURATION_DESCRIPTOR_TYPE:
                    if (packet[USB_bDescriptorIndex] >= usb_device_descriptor[17]) // TODO: remove magic
                        usb_RequestError();
                    usb_desc_ptr = usb_config_descriptor;
                    usb_desc_len = usb_desc_ptr[2] + usb_desc_ptr[3] * 256;
                    for (i = 0; i < packet[USB_bDescriptorIndex]; i++) { // Implicit linked list traversal until requested configuration
                        usb_desc_ptr += usb_desc_len;
                        usb_desc_len = usb_desc_ptr[2] + usb_desc_ptr[3] * 256;
                    }
                    if ((packet[USB_wLengthHigh] < usb_desc_ptr[3]) ||
                            (packet[USB_wLengthHigh] == usb_desc_ptr[3] && packet[USB_wLength] < usb_desc_ptr[2]))
                        usb_desc_len = packet[USB_wLength] + packet[USB_wLengthHigh] * 256;
                    break;
                case USB_STRING_DESCRIPTOR_TYPE:
                    // TODO: Handle language request. For now return standard language.
                    if (packet[USB_bDescriptorIndex] >= usb_num_string_descriptors)
                        usb_RequestError();
                    usb_desc_ptr = usb_string_descriptor;
                    usb_desc_len = usb_desc_ptr[0];
                    for (i = 0; i < packet[USB_bDescriptorIndex]; i++) { // Implicit linked list traversal until requested configuration
                        usb_desc_ptr += usb_desc_len;
                        usb_desc_len = usb_desc_ptr[0];
                    }
                    if ((0 == packet[USB_wLengthHigh] && packet[USB_wLength] < usb_desc_ptr[0]))
                        usb_desc_len = packet[USB_wLength];
                    break;
                case USB_INTERFACE_DESCRIPTOR_TYPE:
                case USB_ENDPOINT_DESCRIPTOR_TYPE:
                default:
                    usb_RequestError();
            }
            usb_send_descriptor(); // Send first part of packet right away
            usb_set_in_handler(0, usb_send_descriptor);
            break;
        case USB_REQUEST_GET_CONFIGURATION:
            rbdp->BDADDR[0] = usb_current_cfg;
            usb_ack_dat1(rbdp, 1); // JTR common addition for STD and CLASS ACK
            //		rbdp->BDCNT = 1;
            //		rbdp->BDSTAT = UOWN + DTS + DTSEN;
            break;

        case USB_REQUEST_SET_CONFIGURATION:
            if (USB_NUM_CONFIGURATIONS >= packet[USB_wValue]) {
                // TODO: Support multiple configurations
                /* Configure endpoints (USB_UEPn - registers) */
                usb_current_cfg = packet[USB_wValue];
                if (usb_current_cfg != 0) {

                    // JTR user_configured_init major addition. This is a CALLBACK to the USER when the device is enumerated.
                    // This is when we setup non EP0 endpoints.
                    // TODO: This really could be a function pointer

                    usb_device_state = CONFIGURED_STATE;
                    user_configured_init();
                } else {
                    usb_device_state = ADDRESS_STATE;
                }

                usb_ack_dat1(rbdp, 0); // JTR common addition for STD and CLASS ACK

            } else
                usb_RequestError();
            break;

        case USB_REQUEST_SET_DESCRIPTOR:
        default:
            usb_RequestError();
    }
}