| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- /**
- * @file usbd_rndis.c
- * @brief
- *
- * Copyright (c) 2022 sakumisu
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- */
- #include "usbd_core.h"
- #include "usbd_rndis.h"
- #include "rndis_protocol.h"
- #define RNDIS_INQUIRY_PUT(src, len) (memcpy(infomation_buffer, src, len))
- #define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
- /* Device data structure */
- struct usbd_rndis_cfg_priv {
- uint32_t drv_version;
- uint32_t media_status;
- uint32_t speed;
- uint32_t mtu;
- uint32_t net_filter;
- usb_eth_stat_t eth_state;
- rndis_state_t init_state;
- uint8_t mac[6];
- uint32_t vendor_id;
- uint8_t *vendor_desc;
- } usbd_rndis_cfg = { .drv_version = 0x0001,
- .media_status = NDIS_MEDIA_STATE_DISCONNECTED,
- .mtu = RNDIS_MTU,
- .speed = 0,
- .init_state = rndis_uninitialized,
- .mac = { 0x00, 0x00, 0x5E, 0x00, 0x53, 0x01 },
- .vendor_id = 0xffffffff,
- .vendor_desc = "CherryUSB" };
- /* RNDIS options list */
- const uint32_t oid_supported_list[] = {
- OID_GEN_SUPPORTED_LIST,
- OID_GEN_HARDWARE_STATUS,
- OID_GEN_MEDIA_SUPPORTED,
- OID_GEN_MEDIA_IN_USE,
- OID_GEN_MAXIMUM_FRAME_SIZE,
- OID_GEN_LINK_SPEED,
- OID_GEN_TRANSMIT_BLOCK_SIZE,
- OID_GEN_RECEIVE_BLOCK_SIZE,
- OID_GEN_VENDOR_ID,
- OID_GEN_VENDOR_DESCRIPTION,
- OID_GEN_VENDOR_DRIVER_VERSION,
- OID_GEN_CURRENT_PACKET_FILTER,
- OID_GEN_MAXIMUM_TOTAL_SIZE,
- OID_GEN_PROTOCOL_OPTIONS,
- OID_GEN_MAC_OPTIONS,
- OID_GEN_MEDIA_CONNECT_STATUS,
- OID_GEN_MAXIMUM_SEND_PACKETS,
- OID_802_3_PERMANENT_ADDRESS,
- OID_802_3_CURRENT_ADDRESS,
- OID_802_3_MULTICAST_LIST,
- OID_802_3_MAXIMUM_LIST_SIZE,
- OID_802_3_MAC_OPTIONS
- };
- static uint8_t rndis_encapsulated_resp_buffer[CONFIG_RNDIS_RESP_BUFFER_SIZE];
- static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len);
- // static int rndis_encapsulated_resp_handler(uint8_t *data, uint32_t *len);
- static void rndis_notify_rsp(void);
- /**
- * @brief Handler called for Class requests not handled by the USB stack.
- *
- * @param setup Information about the request to execute.
- * @param len Size of the buffer.
- * @param data Buffer containing the request result.
- *
- * @return 0 on success, negative errno code on fail.
- */
- static int rndis_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
- {
- switch (setup->bRequest) {
- case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
- rndis_encapsulated_cmd_handler(data, len);
- break;
- case CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
- *data = rndis_encapsulated_resp_buffer;
- *len = ((rndis_generic_msg_t *)rndis_encapsulated_resp_buffer)->MessageLength;
- break;
- default:
- return -1;
- }
- }
- static void rndis_notify_rsp(void)
- {
- uint8_t notify_buf[8] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- usbd_ep_write(0x81, notify_buf, 8, NULL);
- }
- static int rndis_init_cmd_handler(uint8_t *data, uint32_t len);
- static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len);
- static int rndis_query_cmd_handler(uint8_t *data, uint32_t len);
- static int rndis_set_cmd_handler(uint8_t *data, uint32_t len);
- static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len);
- static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len);
- static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len)
- {
- switch (((rndis_generic_msg_t *)data)->MessageType) {
- case REMOTE_NDIS_INITIALIZE_MSG:
- rndis_init_cmd_handler(data, len);
- break;
- case REMOTE_NDIS_HALT_MSG:
- rndis_halt_cmd_handler(data, len);
- break;
- case REMOTE_NDIS_QUERY_MSG:
- rndis_query_cmd_handler(data, len);
- break;
- case REMOTE_NDIS_SET_MSG:
- rndis_set_cmd_handler(data, len);
- break;
- case REMOTE_NDIS_RESET_MSG:
- rndis_reset_cmd_handler(data, len);
- break;
- case REMOTE_NDIS_KEEPALIVE_MSG:
- rndis_keepalive_cmd_handler(data, len);
- break;
- default:
- break;
- }
- }
- static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
- {
- rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
- rndis_initialize_cmplt_t *resp;
- resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
- resp->RequestId = cmd->RequestId;
- resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
- resp->MessageLength = sizeof(rndis_initialize_cmplt_t);
- resp->MajorVersion = RNDIS_MAJOR_VERSION;
- resp->MinorVersion = RNDIS_MINOR_VERSION;
- resp->Status = RNDIS_STATUS_SUCCESS;
- resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
- resp->Medium = RNDIS_MEDIUM_802_3;
- resp->MaxPacketsPerTransfer = 1;
- resp->MaxTransferSize = usbd_rndis_cfg.mtu + ETH_HEADER_SIZE + sizeof(rndis_data_packet_t);
- resp->PacketAlignmentFactor = 0;
- resp->AfListOffset = 0;
- resp->AfListSize = 0;
- usbd_rndis_cfg.init_state = rndis_initialized;
- rndis_notify_rsp();
- return 0;
- }
- static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
- {
- usbd_rndis_cfg.init_state = rndis_uninitialized;
- return 0;
- }
- static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
- {
- rndis_query_msg_t *cmd = (rndis_initialize_msg_t *)data;
- rndis_query_cmplt_t *resp;
- uint8_t *infomation_buffer;
- uint32_t infomation_len = 0;
- resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
- resp->Status = RNDIS_STATUS_SUCCESS;
- resp->RequestId = cmd->RequestId;
- resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
- resp->InformationBufferOffset = 16;
- infomation_buffer = (uint8_t *)resp + sizeof(rndis_initialize_cmplt_t);
- switch (cmd->Oid) {
- case OID_GEN_SUPPORTED_LIST:
- RNDIS_INQUIRY_PUT(oid_supported_list, sizeof(oid_supported_list));
- infomation_len = sizeof(oid_supported_list);
- break;
- case OID_GEN_VENDOR_DRIVER_VERSION:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.drv_version);
- infomation_len = 4;
- break;
- case OID_802_3_CURRENT_ADDRESS:
- RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
- infomation_len = 6;
- break;
- case OID_802_3_PERMANENT_ADDRESS:
- RNDIS_INQUIRY_PUT(usbd_rndis_cfg.mac, 6);
- infomation_len = 6;
- break;
- case OID_GEN_MEDIA_SUPPORTED:
- RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
- infomation_len = 4;
- break;
- case OID_GEN_MEDIA_IN_USE:
- RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
- infomation_len = 4;
- break;
- case OID_GEN_PHYSICAL_MEDIUM:
- RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
- infomation_len = 4;
- break;
- case OID_GEN_HARDWARE_STATUS:
- RNDIS_INQUIRY_PUT_LE32(0);
- infomation_len = 4;
- break;
- case OID_GEN_LINK_SPEED:
- RNDIS_INQUIRY_PUT_LE32(RNDIS_LINK_SPEED / 100);
- infomation_len = 4;
- break;
- case OID_GEN_VENDOR_ID:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.vendor_id);
- infomation_len = 4;
- break;
- case OID_GEN_VENDOR_DESCRIPTION:
- RNDIS_INQUIRY_PUT(usbd_rndis_cfg.vendor_desc, strlen(usbd_rndis_cfg.vendor_desc) + 1);
- infomation_len = (strlen(usbd_rndis_cfg.vendor_desc) + 1);
- break;
- case OID_GEN_CURRENT_PACKET_FILTER:
- RNDIS_INQUIRY_PUT_LE32(0x00FFFFFF);
- infomation_len = 4;
- break;
- case OID_GEN_MAXIMUM_FRAME_SIZE:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.mtu);
- infomation_len = 4;
- break;
- case OID_GEN_MAXIMUM_TOTAL_SIZE:
- case OID_GEN_TRANSMIT_BLOCK_SIZE:
- case OID_GEN_RECEIVE_BLOCK_SIZE:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.mtu + ETH_HEADER_SIZE + sizeof(rndis_data_packet_t));
- infomation_len = 4;
- break;
- case OID_GEN_MEDIA_CONNECT_STATUS:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.media_status);
- infomation_len = 4;
- break;
- case OID_GEN_RNDIS_CONFIG_PARAMETER:
- RNDIS_INQUIRY_PUT_LE32(0);
- infomation_len = 4;
- break;
- case OID_802_3_MAXIMUM_LIST_SIZE:
- RNDIS_INQUIRY_PUT_LE32(1); /* one address */
- infomation_len = 4;
- break;
- case OID_802_3_MULTICAST_LIST:
- RNDIS_INQUIRY_PUT_LE32(0xE0000000); /* 224.0.0.0 */
- infomation_len = 4;
- break;
- case OID_802_3_MAC_OPTIONS:
- infomation_len = 0;
- break;
- case OID_GEN_MAC_OPTIONS:
- RNDIS_INQUIRY_PUT_LE32(0);
- infomation_len = 4;
- break;
- case OID_802_3_RCV_ERROR_ALIGNMENT:
- RNDIS_INQUIRY_PUT_LE32(0);
- infomation_len = 4;
- break;
- case OID_802_3_XMIT_ONE_COLLISION:
- RNDIS_INQUIRY_PUT_LE32(0);
- infomation_len = 4;
- break;
- case OID_802_3_XMIT_MORE_COLLISIONS:
- RNDIS_INQUIRY_PUT_LE32(0);
- infomation_len = 4;
- break;
- case OID_GEN_XMIT_OK:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txok);
- infomation_len = 4;
- break;
- case OID_GEN_RCV_OK:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxok);
- infomation_len = 4;
- break;
- case OID_GEN_RCV_ERROR:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.rxbad);
- infomation_len = 4;
- break;
- case OID_GEN_XMIT_ERROR:
- RNDIS_INQUIRY_PUT_LE32(usbd_rndis_cfg.eth_state.txbad);
- infomation_len = 4;
- break;
- case OID_GEN_RCV_NO_BUFFER:
- RNDIS_INQUIRY_PUT_LE32(0);
- infomation_len = 4;
- break;
- default:
- resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
- USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
- break;
- }
- resp->MessageLength = sizeof(rndis_query_cmplt_t) + infomation_len;
- resp->InformationBufferLength = infomation_len;
- rndis_notify_rsp();
- return 0;
- }
- static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
- {
- rndis_set_msg_t *cmd = (rndis_set_msg_t *)data;
- rndis_set_cmplt_t *resp;
- rndis_config_parameter_t *param;
- resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
- resp->RequestId = cmd->RequestId;
- resp->MessageType = REMOTE_NDIS_SET_CMPLT;
- resp->MessageLength = sizeof(rndis_set_cmplt_t);
- resp->Status = RNDIS_STATUS_SUCCESS;
- switch (cmd->Oid) {
- case OID_GEN_RNDIS_CONFIG_PARAMETER:
- break;
- case OID_GEN_CURRENT_PACKET_FILTER:
- if (cmd->InformationBufferLength < sizeof(usbd_rndis_cfg.net_filter)) {
- resp->Status = RNDIS_STATUS_INVALID_DATA;
- } else {
- /* Parameter starts at offset buf_offset of the req_id field */
- param = (rndis_config_parameter_t *)((uint8_t *)&cmd->RequestId + cmd->InformationBufferOffset);
- //usbd_rndis_cfg.net_filter = param->ParameterNameOffset;
- }
- break;
- case OID_GEN_CURRENT_LOOKAHEAD:
- break;
- case OID_GEN_PROTOCOL_OPTIONS:
- break;
- case OID_802_3_MULTICAST_LIST:
- break;
- case OID_PNP_ADD_WAKE_UP_PATTERN:
- case OID_PNP_REMOVE_WAKE_UP_PATTERN:
- case OID_PNP_ENABLE_WAKE_UP:
- default:
- resp->Status = RNDIS_STATUS_FAILURE;
- break;
- }
- rndis_notify_rsp();
- return 0;
- }
- static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
- {
- rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
- rndis_reset_cmplt_t *resp;
- resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
- resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
- resp->MessageLength = sizeof(rndis_reset_cmplt_t);
- resp->Status = RNDIS_STATUS_SUCCESS;
- resp->AddressingReset = 1;
- rndis_notify_rsp();
- return 0;
- }
- static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
- {
- rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
- rndis_keepalive_cmplt_t *resp;
- resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
- resp->RequestId = cmd->RequestId;
- resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
- resp->MessageLength = sizeof(rndis_keepalive_cmplt_t);
- resp->Status = RNDIS_STATUS_SUCCESS;
- rndis_notify_rsp();
- return 0;
- }
- static void rndis_notify_handler(uint8_t event, void *arg)
- {
- switch (event) {
- case USBD_EVENT_RESET:
- break;
- default:
- break;
- }
- }
- void usbd_rndis_add_interface(usbd_class_t *devclass, usbd_interface_t *intf)
- {
- static usbd_class_t *last_class = NULL;
- if (last_class != devclass) {
- last_class = devclass;
- usbd_class_register(devclass);
- }
- intf->class_handler = rndis_class_request_handler;
- intf->custom_handler = NULL;
- intf->vendor_handler = NULL;
- intf->notify_handler = rndis_notify_handler;
- usbd_class_add_interface(devclass, intf);
- }
|