| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- /*
- * Copyright : (C) 2022 Phytium Information Technology, Inc.
- * All Rights Reserved.
- *
- * This program is OPEN SOURCE software: you can redistribute it and/or modify it
- * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
- * either version 1.0 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 Phytium Public License for more details.
- *
- *
- * FilePath: fusb_dev.c
- * Date: 2022-02-11 13:33:11
- * LastEditTime: 2022-02-18 09:18:45
- * Description: This files is for USB device function implementation
- *
- * Modify History:
- * Ver Who Date Changes
- * ----- ------ -------- --------------------------------------
- * 1.0 Zhugengyu 2022/2/7 init commit
- */
- #include <string.h>
- #include "fdebug.h"
- #include "fusb_private.h"
- #define FUSB_DEBUG_TAG "FUSB-DEV"
- #define FUSB_ERROR(format, ...) FT_DEBUG_PRINT_E(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FUSB_WARN(format, ...) FT_DEBUG_PRINT_W(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FUSB_INFO(format, ...) FT_DEBUG_PRINT_I(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FUSB_DEBUG(format, ...) FT_DEBUG_PRINT_D(FUSB_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FUSB_DR_DESC FUsbGenerateReqType(FUSB_REQ_DEVICE_TO_HOST, FUSB_REQ_TYPE_STANDARD, FUSB_REQ_RECP_DEV)
- #define FUSB_SKIP_BYTES(desc, bytes) ((FUsbDescriptor *) ((u8 *) (desc) + (bytes)))
- #define FUSB_CONFIG_DESC_SIZE 512 /* best guess */
- static void FUsbNopDevDestory(FUsbDev *dev)
- {
- FUsbNopDevInit(dev);
- dev->address = FUSB_NO_DEV_ADDR;
- dev->hub = FUSB_NO_HUB;
- dev->port = FUSB_NO_PORT;
- }
- static void FUsbNopDevPoll(FUsbDev *dev)
- {
- return;
- }
- /**
- * @name: FUsbNopDevInit
- * @msg: 默认的USB设备初始化函数
- * @return {*}
- * @param {FUsbDev} *dev, USB设备实例
- */
- void FUsbNopDevInit(FUsbDev *dev)
- {
- dev->descriptor = NULL;
- dev->configuration = NULL;
- dev->destroy = FUsbNopDevDestory;
- dev->poll = FUsbNopDevPoll;
- }
- static inline boolean FUsbParserIsValid(const FUsbConfigParser *parser)
- {
- FASSERT(parser);
- return parser->is_valid;
- }
- static FError FUsbParserDescriptor(FUsbConfigParser *parser)
- {
- FASSERT(parser && parser->buf);
- const FUsbDescriptor *cur_pos = parser->buf;
- const FUsbDescriptor *desc_end;
- FUsbDescriptorType last_desc_type = FUSB_DESC_TYPE_NONE;
- FUsbDescriptorType desc_type;
- u8 desc_len, exp_len, alt_len;
- FError ret = FUSB_SUCCESS;
- while (FUSB_SKIP_BYTES(cur_pos, FUSB_DESCRIPTOR_HEADER_SIZE) < parser->end_pos)
- {
- /* get length and type of descriptor */
- desc_len = cur_pos->header.len;
- desc_type = cur_pos->header.type;
- desc_end = FUSB_SKIP_BYTES(cur_pos, desc_len);
- if (desc_end > parser->end_pos)
- {
- FUSB_ERROR("Parse descriptor out of boundary !!!");
- parser->err_pos = cur_pos;
- ret = FUSB_ERR_DESC_PARSE_ERR;
- goto err_handle;
- }
- exp_len = 0;
- alt_len = 0;
- switch (desc_type)
- {
- case FUSB_DESC_TYPE_CONFIG:
- if (FUSB_DESC_TYPE_NONE != last_desc_type)
- {
- FUSB_ERROR("Configuration descriptor must be the first !!!");
- parser->err_pos = cur_pos;
- ret = FUSB_ERR_DESC_PARSE_ERR;
- goto err_handle;
- }
- exp_len = sizeof(FUsbConfigurationDescriptor);
- break;
- case FUSB_DESC_TYPE_INTERFACE:
- if (FUSB_DESC_TYPE_NONE == last_desc_type)
- {
- FUSB_ERROR("Interface descriptor must not be the first !!!");
- parser->err_pos = cur_pos;
- ret = FUSB_ERR_DESC_PARSE_ERR;
- goto err_handle;
- }
- exp_len = sizeof(FUsbInterfaceDescriptor);
- break;
- case FUSB_DESC_TYPE_ENDPOINT:
- if ((FUSB_DESC_TYPE_NONE == last_desc_type) ||
- (FUSB_DESC_TYPE_CONFIG == last_desc_type))
- {
- FUSB_ERROR("Endpoint descriptor must follow interface descriptor !!!");
- parser->err_pos = cur_pos;
- ret = FUSB_ERR_DESC_PARSE_ERR;
- goto err_handle;
- }
- break;
- default:
- FUSB_DEBUG("Descriptor %d not handled !!!", desc_type);
- break;
- }
- if (((exp_len != 0) && (desc_len != exp_len)) &&
- ((alt_len == 0) || (desc_len != alt_len)))
- {
- FUSB_ERROR("Descriptor %d invalid !!!", desc_type);
- parser->err_pos = cur_pos;
- ret = FUSB_ERR_DESC_PARSE_ERR;
- goto err_handle;
- }
- last_desc_type = desc_type;
- cur_pos = desc_end;
- }
- if (cur_pos != parser->end_pos)
- {
- parser->err_pos = cur_pos;
- ret = FUSB_ERR_DESC_PARSE_ERR;
- goto err_handle;
- }
- err_handle:
- if (FUSB_SUCCESS == ret)
- {
- parser->is_valid = TRUE;
- }
- return ret;
- }
- /**
- * @name: FUsbSetupConfigParser
- * @msg: 配置USB配置描述符解析器
- * @return {*}
- * @param {FUsbDev} *dev, USB设备实例
- * @param {void} *buf, 配置描述符缓冲区
- * @param {u32} buf_len, 配置描述符缓冲区长度
- */
- FError FUsbSetupConfigParser(FUsbDev *dev, const void *buf, u32 buf_len)
- {
- FASSERT(dev && buf && (buf_len > 0));
- const FUsbConfigurationDescriptor *config_desc;
- FUsbConfigParser *parser = &dev->config_parser;
- memset(parser, 0, sizeof(*parser));
- parser->buf = buf;
- parser->buf_len = buf_len;
- parser->is_valid = FALSE;
- parser->end_pos = FUSB_SKIP_BYTES(parser->buf, parser->buf_len);
- parser->next_pos = parser->buf;
- parser->cur_desc = NULL;
- parser->err_pos = parser->buf;
- if ((parser->buf_len < sizeof(u32)) || (parser->buf_len > FUSB_CONFIG_DESC_SIZE))
- {
- FUSB_ERROR("Invalid buffer length !!!");
- return FUSB_ERR_INVALID_DATA;
- }
- /* input buffer must start with config desc */
- config_desc = (FUsbConfigurationDescriptor *)parser->buf;
- if ((config_desc->bLength != sizeof(FUsbConfigurationDescriptor)) ||
- (config_desc->bDescriptorType != FUSB_DESC_TYPE_CONFIG) ||
- (config_desc->wTotalLength > parser->buf_len))
- {
- FUSB_ERROR("Invalid configuration descriptor !!!");
- return FUSB_ERR_INVALID_DATA;
- }
- /* adjust end position */
- if (config_desc->wTotalLength < parser->buf_len)
- {
- parser->end_pos = FUSB_SKIP_BYTES(parser->buf, config_desc->wTotalLength);
- }
- return FUsbParserDescriptor(parser);
- }
- /**
- * @name: FUsbRevokeConfigParser
- * @msg: 去初始化USB配置描述符解析器
- * @return {*}
- * @param {FUsbDev} *dev, USB设备实例
- */
- void FUsbRevokeConfigParser(FUsbDev *dev)
- {
- FASSERT(dev);
- memset(&dev->config_parser, 0, sizeof(dev->config_parser));
- return;
- }
- /**
- * @name: FUsbGetDescriptorFromParser
- * @msg: 从配置描述符解析器中获取指定类型的描述符(端点描述符/接口描述符)
- * @return {const FUsbDescriptor *} 获取的描述符
- * @param {FUsbConfigParser} *parser, 配置描述符解析器
- * @param {FUsbDescriptorType} type, 获取描述符的类型
- */
- const FUsbDescriptor *FUsbGetDescriptorFromParser(FUsbConfigParser *parser, FUsbDescriptorType type)
- {
- FASSERT(parser);
- if (!FUsbParserIsValid(parser))
- {
- FUSB_ERROR("Config parse is not valid !!!");
- return NULL;
- }
- const FUsbDescriptor *result = NULL;
- FUsbDescriptorType desc_type;
- u8 desc_len;
- const FUsbDescriptor *desc_end;
- /* travesal all descriptors */
- while (parser->next_pos < parser->end_pos)
- {
- desc_len = parser->next_pos->header.len;
- desc_type = parser->next_pos->header.type;
- desc_end = FUSB_SKIP_BYTES(parser->next_pos, desc_len);
- if (desc_end > parser->end_pos)
- break;
- if ((FUSB_DESC_TYPE_ENDPOINT == type) &&
- (FUSB_DESC_TYPE_INTERFACE == desc_type))
- break; /* there is no chance to find endpoint desc after interface desc */
- if (type == desc_type)
- {
- /* target desc found !!! */
- result = parser->next_pos;
- parser->next_pos = desc_end;
- break;
- }
- parser->next_pos = desc_end;/* check next one */
- }
- if (NULL != result)
- {
- parser->err_pos = result;
- }
- parser->cur_desc = result;
- return result;
- }
- /**
- * @name: FUsbSetupStringParser
- * @msg: 初始化字符串描述符解析器
- * @return {*}
- * @param {FUsbDev} *dev, USB设备实例
- */
- void FUsbSetupStringParser(FUsbDev *dev)
- {
- FASSERT(dev);
- FUsbStringParser *parser = &dev->string_parser;
- if (NULL != parser->usb_str)
- {
- FUSB_WARN("String descriptor exists, might cause memory leakage !!!");
- }
- parser->usb_str = NULL;
- memset(parser->str_buf, 0, sizeof(parser->str_buf));
- return;
- }
- /**
- * @name: FUsbRevokeStringParser
- * @msg: 去初始化字符串描述符解析器
- * @return {*}
- * @param {FUsbDev} *dev, USB设备实例
- */
- void FUsbRevokeStringParser(FUsbDev *dev)
- {
- FASSERT(dev);
- FUsbStringParser *parser = &dev->string_parser;
- FASSERT(dev->controller && dev->controller->usb);
- FUsb *instance = dev->controller->usb;
- if (NULL != parser->usb_str)
- {
- FUSB_FREE(instance, parser->usb_str);
- parser->usb_str = NULL;
- }
- return;
- }
- /**
- * @name: FUsbSearchStringDescriptor
- * @msg: 检索字符串描述符,保存在FUsbStringParser结构中
- * @return {*}
- * @param {FUsb} *instance, USB实例
- * @param {FUsbDev} *dev, USB设备实例
- * @param {u8} id, 要获取字符串描述符的ID
- */
- FError FUsbSearchStringDescriptor(FUsb *instance, FUsbDev *dev, u8 id)
- {
- FASSERT(instance && dev);
- FUsbStringParser *parser = &dev->string_parser;
- const FUsbStringDescriptor *usb_str = NULL;
- u8 total_len;
- u8 char_num;
- u16 character;
- /* re-malloc usb string desc buffer with length 4 */
- if (NULL != parser->usb_str)
- {
- FUSB_FREE(instance, parser->usb_str);
- parser->usb_str = NULL;
- }
- parser->usb_str = FUSB_ALLOCATE(instance, FUSB_USBSTR_MIN_LEN, FUSB_DEFAULT_ALIGN);
- if (NULL == parser->usb_str)
- return FUSB_ERR_ALLOCATE_FAIL;
- /* get header of string for the full length */
- if (FUsbGetStringDescriptor(dev, FUSB_DR_DESC, FUSB_DESC_TYPE_STRING, id, FUSB_DEFAULT_LANG_ID,
- parser->usb_str, FUSB_USBSTR_MIN_LEN) < 0)
- {
- FUSB_ERROR("Parse string descriptor failed (len: %d) !!!", FUSB_USBSTR_MIN_LEN);
- return FUSB_ERR_DESC_PARSE_ERR;
- }
- /* check if string descriptor header is valid */
- total_len = parser->usb_str->len;
- if ((total_len < FUSB_DESCRIPTOR_HEADER_SIZE) ||
- ((total_len & 1) != 0) ||
- (parser->usb_str->type != FUSB_DESC_TYPE_STRING))
- {
- FUSB_ERROR("Get invalid string descriptor (len: %d) !!!", FUSB_USBSTR_MIN_LEN);
- return FUSB_ERR_DESC_PARSE_ERR;
- }
- /* return if no need to get more */
- if (total_len <= FUSB_USBSTR_MIN_LEN)
- return FUSB_SUCCESS;
- /* re-malloc usb string desc buffer with full length */
- FASSERT(parser->usb_str);
- FUSB_FREE(instance, parser->usb_str);
- parser->usb_str = NULL;
- parser->usb_str = FUSB_ALLOCATE(instance, total_len, FUSB_DEFAULT_ALIGN);
- if (NULL == parser->usb_str)
- return FUSB_ERR_ALLOCATE_FAIL;
- /* get the whole string descriptor */
- if (FUsbGetStringDescriptor(dev, FUSB_DR_DESC, FUSB_DESC_TYPE_STRING, id, FUSB_DEFAULT_LANG_ID,
- parser->usb_str, total_len) < 0)
- {
- FUSB_ERROR("Parse string descriptor failed (len: %d)!!!", total_len);
- return FUSB_ERR_DESC_PARSE_ERR;
- }
- if ((parser->usb_str->len < FUSB_DESCRIPTOR_HEADER_SIZE) ||
- ((parser->usb_str->len & 1) != 0) ||
- (parser->usb_str->type != FUSB_DESC_TYPE_STRING))
- {
- FUSB_ERROR("Get invalid string descriptor (len: %d) !!!", total_len);
- return FUSB_ERR_DESC_PARSE_ERR;
- }
- /* convert into ASCII string */
- usb_str = parser->usb_str;
- char_num = (usb_str->len - FUSB_DESCRIPTOR_HEADER_SIZE) / 2; /* in 16-bit way */
- if (char_num >= FUSB_STRDESC_BUF_MAX - 1)
- {
- return FUSB_ERR_NOT_SUPPORT;
- }
- for (u8 i = 0; i < char_num; i++)
- {
- character = usb_str->string[i];
- if (character < ' ' /* 0x20 */
- || character > '~') /* 0x7E */
- {
- character = '_';
- }
- parser->str_buf[i] = (char)character;
- }
- parser->str_buf[char_num] = '\0';
- return FUSB_SUCCESS;
- }
- /**
- * @name: FUsbGetString
- * @msg: 获取刚刚检索到的字符串描述符内容
- * @return {const char *}, 字符串描述符中的内容
- * @param {FUsbDev} *dev, USB设备实例
- */
- const char *FUsbGetString(const FUsbDev *const dev)
- {
- FASSERT(dev);
- return (const char *)dev->string_parser.str_buf;
- }
|