(Avançar) Explicação detalhada do protocolo de diagnóstico UDS automotivo (1)

I. Visão geral

UDS (UnifiedDiagnostic Services, serviço de diagnóstico unificado, às vezes chamado de diagnóstico aprimorado) é um protocolo baseado na camada de aplicativo no modelo OSI definido pela ISO-14229. Dentre elas, a ISO 14229-1 define serviços de diagnóstico, mas não envolve a camada de rede e métodos de implementação, apenas o conteúdo da camada de aplicação, podendo ser implementada em diferentes barramentos automotivos (como CAN, LIN, Flexray, Ethernet e K-line, etc.).

Combinado com ISO 15765-3 e ISO 14229-1, o serviço de diagnóstico unificado de veículos UDS baseado em barramento CAN é realizado. Como mostrado abaixo:

ISO15765-4 especifica o conteúdo de diagnóstico relacionado a emissões

camadas OSI Diagnósticos aprimorados para montadoras Diagnósticos relacionados a emissões (OBD) exigidos pelos regulamentos
aplicativo de diagnóstico usuário definido ISO 15031-5
camada de aplicação ISO 15765-3/ISO 14229-1 ISO 15031-5
camada de apresentação nenhum nenhum
camada de sessão ISO 15765-3 ISO 15765-4
camada de transporte nenhum nenhum
Camada de rede ISO 15765-2 ISO 15765-4
camada de enlace de dados ISO 11898-1 ISO 15765-4
camada física usuário definido ISO 15765-4

O UDS não é exigido por leis e regulamentos e não existe um padrão de implementação unificado.Sua vantagem é que facilita o desenvolvimento de equipamentos de teste de linha de produção e, ao mesmo tempo, facilita a realização de funções de manutenção pós-venda e rede automotiva.

O processo de comunicação de diagnóstico é muito fácil de entender do ponto de vista do usuário. O instrumento de diagnóstico envia uma solicitação de diagnóstico (solicitação) e a ECU dá uma resposta de diagnóstico (resposta). O UDS define um conteúdo e formato unificados para a solicitação e resposta de diferentes funções de diagnóstico.

2. Modo de interação do serviço de diagnóstico

O UDS é essencialmente uma comunicação direcional, um protocolo interativo (Solicitação/Resposta), ou seja, a parte de diagnóstico envia dados de solicitação especificados (Solicitação) para a ECU, e a ECU realimenta as informações para a parte de diagnóstico (Resposta).

Formato da Solicitação de Diagnóstico:

O formato de DiagnosticRequest pode ser dividido em duas categorias:

Uma classe tem subfunção;

Uma classe não tem subfunção;

O comprimento do Service ID (doravante referido como SID) é fixado em 1 byte, o que representa a função executada por este comando de diagnóstico. O comprimento da subfunção também é de 1 byte, o que normalmente indica a operação específica neste serviço de diagnóstico, como iniciar, parar ou consultar este serviço de diagnóstico. Este último parâmetro tem conteúdo diferenciado de acordo com os diferentes serviços de diagnóstico, não havendo especificação uniforme de comprimento e formato, sendo utilizado para limitar as condições de execução dos serviços de diagnóstico, como o tempo de execução de um determinado serviço de diagnóstico. Uma aplicação importante do parâmetro é como um identificador para identificar o conteúdo dos dados a serem lidos por uma solicitação de diagnóstico.

Uma coisa a acrescentar é que a subfunção é estritamente falando de 7 bits, não de 1 byte, porque seu bit mais alto é usado para suprimir a resposta positiva (Suprimir Resposta Ppositiva, SPR). Se este bit for definido como 1, a ECU não dará uma resposta positiva (PositiveResponse); se este bit for definido como 0, a ECU dará uma resposta positiva. O objetivo é avisar a ECU para não enviar Response desnecessários, economizando recursos de comunicação.

Formato da resposta diagnóstica:

As respostas diagnósticas são divididas em categorias positivas e negativas.

Resposta positiva significa que a solicitação de diagnóstico enviada pelo instrumento de diagnóstico foi executada, enquanto resposta negativa significa que a ECU não pode executar a solicitação de diagnóstico enviada pelo instrumento de diagnóstico por algum motivo, e o motivo da incapacidade de execução existe no NRC na mensagem de resposta negativa

O formato de resposta positiva é composto de três partes. O byte SID de resposta é usado como eco da solicitação de diagnóstico e a resposta é [SID+0x40]. Por exemplo, solicitação 10, resposta 50; solicitação 22, resposta 62, a resposta é um conjunto de dados. Os dois bytes seguintes são subfunções e outros, dependendo dos serviços de diagnóstico específicos.

O formato da resposta negativa é fixado em 3 bytes, resposta [7F+SID+NRC], o primeiro byte é 0x7F, o segundo byte é o SID rejeitado e o terceiro byte é o código de resposta negativa NRC. Por exemplo, se a ECU der uma resposta negativa de 7F22 13, significa que o serviço com SID=22 não pode ser executado porque o tamanho dos dados da solicitação de diagnóstico está errado (NRC=13). O código de resposta negativa do NRC é mostrado na figura abaixo:

por exemplo:

Tome como exemplo a rede de barramento CAN. Oito bytes de dados de quadro, o primeiro byte é ocupado pela camada de rede (ISO 15765-2).

O terminal de diagnóstico envia uma solicitação (Request): 02 10 02 xx xx xx xx xx; 02 é um único quadro SF na camada de rede, o que significa que o campo de dados possui 2 bytes, 10 é SID e 02 é uma subfunção.

Se a resposta positiva da ECU (Resposta Positiva): 02 50 02 xx xx xxxx xx; 02 é o mesmo que acima, 10+40 significa uma resposta positiva ao SID e 02 é uma subfunção (detalhada abaixo).

Se a resposta negativa da ECU (Resposta Negativa): 03 7F 10 22 xx xxxx xx; 03 é o mesmo que acima, o que significa que o campo de dados possui 3 bytes, 7F significa resposta negativa, 10 é SID e 22 é NRC.

Em termos leigos, o processo de comunicação de diagnóstico é a troca de dados entre o instrumento de diagnóstico e a ECU. O primeiro envia uma solicitação e a segunda uma resposta. O papel mais importante do UDS é definir o formato e o conteúdo dessas solicitações e respostas.

3. Conteúdo do serviço de diagnóstico

O protocolo UDS define os seguintes 26 serviços:

Este artigo explicará primeiro os serviços de "diagnóstico e gerenciamento de comunicação", "transmissão de dados" e "transmissão de dados de armazenamento" na figura acima. Atualizações subsequentes serão feitas abaixo

Serviços de gerenciamento de diagnóstico e comunicação

1. DiagnosticSessionControl(0x10)

$ 10 é usado para controlar a ECU para alternar entre diferentes sessões. Uma sessão pode ser considerada como um estado de software no qual a ECU está localizada. Em diferentes sessões, a autoridade de execução do serviço de diagnóstico é diferente. Seu formato de requisição Request é o seguinte:

Formato de solicitação de diagnóstico DiagnosticSessionControl

O primeiro byte é o SID, que aqui é 0x10. O segundo self é a subfunção do serviço $10, e a lista de funções é a seguinte:

Quando a ECU é ligada, ela entra na sessão padrão 0x01 (Padrão). Se você entrar em um estado diferente da sessão padrão, um cronômetro será executado e, se não houver solicitação por um período de tempo, após o tempo, o diagnóstico retornará à sessão padrão 01. Obviamente, temos um serviço de $ 3E que mantém os diagnósticos em um estado não padrão.

Depois que a ECU é ligada, por estar na defaultSession 0x01 por padrão, muitos serviços de diagnóstico não podem ser executados nesta sessão, fazendo com que muitos dados relacionados ao diagnóstico não possam ser lidos ou gravados.

Depois que o instrumento de diagnóstico geral for iniciado, ele enviará 10 03 para a ECU, ou seja, deixará a ECU entrar na ExtendedDiagnosticSession, e existem muitos serviços de diagnóstico que podem ser executados nesta sessão.

E se você quiser manter a ECU na non-defaultSession, você precisa que o instrumento de diagnóstico envie o serviço 0x3E em intervalos regulares, para que a ECU saiba que o instrumento de diagnóstico precisa se comunicar consigo mesma e, assim, manter a non-defaultSession.

Outra sessão comumente usada é 0x02 ProgrammingSession, na qual uma série de serviços de diagnóstico para atualização de software pode ser realizada.

As sessões neste intervalo de 0x40 – 0x5F são usadas pelos OEMs. Por exemplo, alguns serviços de diagnóstico ou operações de dados de diagnóstico precisam ser executados na linha de produção, que é o chamado End-of-Line. Os OEMs podem escolher um valor deste intervalo para representar a sessão EOL; ou se algum tipo de "super" sessão for necessária no estágio de desenvolvimento, eles também podem selecionar um valor daqui para fazer a ECU entrar na sessão do modo de desenvolvimento.

O serviço DiagnosticSessionControl é muito simples, mas é o primeiro comando de diagnóstico para ECU e comunicação de diagnóstico.

ECUReset (0x11)

ECUReset O objetivo deste comando é reiniciar a ECU através de uma solicitação de diagnóstico.

Formato de solicitação de diagnóstico ECUReset

O primeiro byte é o SID, que é 0x11. Os 7 bits inferiores do segundo byte são subfunções, que são usadas para indicar qual método a ECU irá simular para reiniciar. Subfunções comumente usadas incluem (apenas 2 exemplos, UDS também define muitos outros valores)

0x01 hardReset simula o reinício do KL30

0x02 keyOffOnReset Simula o reinício do KL15

Quando reescrevemos alguns dados da ECU através do comando de diagnóstico, ou fazemos algumas configurações na ECU, essas configurações só podem ter efeito depois que a ECU for reiniciada, então existe esse comando de diagnóstico. Após a execução do ECUReset, o ECU retornará da sessão não padrão para a sessão padrão.

SecurityAccess(0x27)

O fabricante pode definir alguns serviços de diagnóstico com um nível de segurança um pouco maior para a ECU, antes de executar tais serviços é necessário executar o comando de diagnóstico SecurityAccess para uma simples verificação de identidade.

A conclusão do SecurityAccess tem as seguintes etapas:

De acordo com a definição UDS de serviço $ 27:

0x03, 0x05, 0x07– 0x41 Este intervalo é reservado para a subfunção usada para requestSeed;

0x04, 0x06, 0x08– 0x42 Este intervalo é reservado para a subfunção usada para sendKey.

Qual par de valores escolher é definido pelo próprio OEM. Os OEMs também podem escolher vários pares de subfunções para diferentes níveis de acesso de segurança.

por exemplo:

Suponha que 0x05 seja usado para requestSeed e 0x06 seja usado para sendKey.

  1. O instrumento de diagnóstico envia 27 05;
  2. ECU responde a 67 05 01 0101 (semente é 01 01 01);
  3. O instrumento de diagnóstico envia 27 06 02 03 04 (o valor da chave é 02 03 04, a semente é 01 01 01, assumindo que a senha local é 01 02 03, e o algoritmo é adicionar a senha e a semente);
  4. Verificação de ECU bem-sucedida 67 06;

Neste momento, a ECU está no estado desbloqueado e os serviços de diagnóstico protegidos e os dados de diagnóstico podem ser operados. De um modo geral, se a ECU reiniciar ou retornar à sessão padrão, o estado desbloqueado será inválido. Se você deseja executar serviços de diagnóstico relacionados, é necessário executar o processo descrito acima novamente.

CommunicationControl (0x28)

Este serviço é utilizado para ativar/desativar o envio/recebimento de determinados tipos de mensagens. Geralmente é utilizado para fazer flash de software ou grande quantidade de dados, pois a ECU não precisa realizar funções relacionadas à comunicação ao fazer flash de software ou parâmetros. Após o fechamento da comunicação, todos os recursos de comunicação podem ser reservados para o download de software ou parâmetros. Após a conclusão do processo de download, use este serviço para restaurar a comunicação.

O formato do serviço 0x28 é mostrado na figura abaixo

A primeira parte é SID, um byte, o valor é 0x28;

A segunda parte é subfunção, ou seja, que tipo de controle é realizado na comunicação da ECU, incluindo:

A terceira parte indica qual tipo de mensagem esta solicitação de diagnóstico deve controlar, o comprimento é de 1 byte, e a definição é mostrada na tabela a seguir:

O mais comumente usado neste byte são os 2 bits inferiores, 0x1 representa pacotes de aplicativos comuns, 0x2 representa pacotes de gerenciamento de rede e 0x3 representa pacotes de aplicativos comuns e pacotes de gerenciamento de rede.

A quarta parte é opcional e só precisa ser utilizada quando o subfuncional for igual a 0x04 ou 0x05.

por exemplo:

28 01 01 significa ativar o recebimento de mensagens do aplicativo e desabilitar o envio de mensagens do aplicativo (mensagens de gerenciamento de rede não são afetadas).

28 00 01 significa ativar o recebimento e envio de mensagens do aplicativo (mensagens de gerenciamento de rede não são afetadas).

TesterPresent (0x3E)

A utilidade deste serviço de diagnóstico pode ser claramente conhecida pelo seu nome, ou seja, para informar a ECU que o instrumento de diagnóstico ainda está conectado. A parte sobre a sessão é mencionada em $ 10. Se não houver envio e recebimento de comandos de diagnóstico, a ECU retornará da sessão não padrão para a sessão padrão. 0x3E é usado para manter a ECU na sessão atual.

Este deve ser o serviço de diagnóstico mais simples em UDS. Sempre tem apenas dois bytes e o formato é o seguinte:

Quando a subfunção é 0x00, a ECU deve dar uma resposta;

Quando a subfunção é 0x80, a ECU não precisa dar uma resposta.

De um modo geral, os OEMs definirão dois parâmetros de tempo para este serviço, um parâmetro é usado para especificar o intervalo no qual o instrumento de diagnóstico envia o serviço 0x3E e o outro parâmetro é usado para definir o tempo limite quando a ECU não pode receber o serviço 0x3E.

ControlDTCSetting (0x85)

Este serviço é usado para controlar o armazenamento DTC (código de problema de diagnóstico) da ECU. Este serviço é freqüentemente usado junto com o serviço 28 mencionado acima. Por exemplo, antes de começar a escrever parâmetros, a fim de obter uma velocidade de transmissão mais rápida, usamos o serviço 28 para fechar a comunicação de todas as ECUs. Mas, neste momento, porque as mensagens relevantes não podem ser recebidas, a ECU armazenará muitos DTCs desnecessariamente. Se usarmos o serviço 85 para desativar temporariamente a função da ECU que armazena DTC, esse problema não será causado.

0x85 formato de solicitação de serviço

A primeira parte é SID, um byte com valor 0x85;

A segunda parte é a subfunção, que é ligar ou desligar o armazenamento DTC da ECU, incluindo:

0x01 em

0x02 desligado

A terceira parte é opcional, que é definida por cada empresa, por exemplo, FF FF FF pode ser usado para indicar que este comando de diagnóstico é para todos os DTCs.

ResponseOnEvent (0x86)

Embora o processo de comunicação de diagnóstico seja do tipo pergunta e resposta, o instrumento de diagnóstico envia uma solicitação e a ECU responde. O serviço 0x86 é uma exceção. Após a ECU receber este serviço 0x86, quando ocorrer um DTC, ela reportará automaticamente o DTC e os dados ambientais relacionados até que outro serviço 0x86 seja usado para fechar o comportamento da ECU.

Esta função é utilizada principalmente na fase inicial de desenvolvimento da ECU, e não será utilizada no pós-venda e produção, e o formato deste serviço é complicado (ou seja, existem muitos parâmetros variáveis), e sua execução é dividida em várias etapas, por isso não vou descrevê-la aqui.

LinkControl (0x87)

Este serviço é usado para converter o estado da camada de link de dados da ECU e da camada física. Por exemplo, a taxa de comunicação normal da ECU no CAN de alta velocidade é de 500 kbit/s, mas também suporta uma taxa de transmissão de 1M bit/s. Se uma grande quantidade de dados precisar ser atualizada, este serviço de diagnóstico pode ser usado para permitir que a ECU se comunique a uma taxa de transmissão de 1M bit/s.

A execução deste serviço de diagnóstico é dividida em duas etapas:

Verifique se a ECU suporta a taxa de transmissão de destino para sintonizar

Deixe a camada de link de dados e a camada física da ECU irem para o estado de comunicação da taxa de transmissão de destino

Somente quando a primeira etapa for verificada, a segunda etapa poderá ser executada com sucesso.

serviço de transferência de dados

Nos serviços de transmissão de dados, 0x22 e 0x2E são usados ​​em pares, e 0x23 e 0x3D são usados ​​em pares.Esses serviços são usados ​​para operações básicas de leitura e gravação de dados de diagnóstico. 0x24, 0x2A, 0x2C são algumas operações especiais.

ReadDataByIdentifier (0x22)

$ 22, leia os dados

l Request (solicitação): 22+DID (identificador de dados, geralmente dois bytes)

l Resposta: 62+DID+Dados

Parte do DID foi especificada pela ISO 14229-1. Por exemplo, 0xF186 é o identificador de dados da sessão de diagnóstico atual, 0xF187 é o identificador de dados do número de peça da fábrica do carro, 0xF188 é o ID de dados do número do software da ECU da fábrica do carro e 0xF189 é o identificador de dados do número da versão do software da ECU da fábrica do carro.

por exemplo:

22 F1 87 (leia o número da peça, DID=F1 87)

62 F1 87 XX YYZZ KK MM NN (fornecer o número da peça)

WriteDataByIdentifier (0x2E)

l Solicitação (solicitação): 2E+DID+Dados

l Resposta: 6E+DID

Observe, por exemplo, que o DID de 0xF186 não oferece suporte à gravação direta de dados e $ 10 são necessários para a conversão da sessão. Ou seja, a solicitação de gravação de dados geralmente precisa ser realizada em uma sessão não padrão e em um estado desbloqueado.

por exemplo:

2E F1 87 XX YY ZZ KK MM NN (escrever o número da peça)

6E F1 87 (dê uma resposta positiva)

ReadMemoryByAddress (0x23)

formato de solicitação de serviço 0x23

A primeira parte é fixada em 1 byte, 0x23;

A segunda parte é a informação de formato, o comprimento é de 1 byte, os 4 bits altos são usados ​​para indicar o comprimento (número de bytes) de memorySize, e os 4 bits baixos são usados ​​para indicar o comprimento (número de bytes) de memoryAddress. Por exemplo, se esse valor for 0x46, o seguinte memorySize é de 6 bytes e memoryAddress é de 4 bytes.

A terceira parte é a informação memoryAddress e seu comprimento é indicado pelo AddressAndLengthFormatIdentifier da segunda parte.

A quarta parte é a informação memorySize e seu comprimento é indicado pelo AddressAndLengthFormatIdentifier da segunda parte.

Se o formato deste comando for 23 22 xx yy aa bb, então seu significado é ler os dados cujo comprimento é aa bb no endereço xx yy.

WriteMemoryByAddress (0x3D)

Conhecendo o uso de 0x23, o uso de 0x3D é fácil de entender, seu método de identificação de memoryAddress e memorySize é o mesmo de 0x23, exceto que um dado a ser escrito é adicionado ao final do comando de diagnóstico.

Serviço de transferência de dados de armazenamento

Serviço de transferência de dados de armazenamento para operar o DTC (código de problema de diagnóstico, código de problema de diagnóstico)

O formato do DTC é claramente definido na ISO15031-6, que define que o DTC consiste em três bytes, conforme mostrado na figura abaixo

Formato DTC

byte 1 byte 2 byte 3
Byte alto do código de problema de diagnóstico Byte baixo do código de problema de diagnóstico Byte de tipo de falha do DTC

Na ISO15031-6, também são definidos especificamente o byte 1 e o byte 2 no formato DTC. Através dessa definição, é fácil determinar a qual tipo o DTC registrado pertence ao veículo.

Até agora, o conceito de códigos de falha DTC foi explicado e o seguinte expandirá a interpretação dos serviços de armazenamento e transmissão:

Este tipo de serviço envolve principalmente dois comandos de diagnóstico, nomeadamente:

0x14:ClearDiagnosticInformation

0x19:ReadDTCInformation

Esses dois serviços são usados ​​para operar o DTC armazenado na ECU, são usados ​​com frequência e refletem melhor o significado da palavra "diagnóstico".

ClearDiagnosticInformation(0x14)

O formato deste comando de diagnóstico é relativamente simples, e o uso é de fácil entendimento, ou seja, deletar o DTC armazenado na ECU.

O primeiro byte é o SID e os três bytes seguintes são usados ​​para identificar o tipo de DTC a ser excluído. UDS estipula que FF FF FF representa todos os tipos de DTCs, e o valor de DTCs como Powertrain, Chassis, Body e Network Communication é definido pelo fabricante.

por exemplo

Pedido: 14+FF+FF+FF; (excluir todos os DTCs em ECU)

Resposta: 54 ;

ReadDTCInformation(0x19)

Esta instrução é usada para ler o DTC armazenado na ECU. A subfunção do serviço 0x19 representa várias maneiras de ler o DTC. O UDS define claramente a subfunção do serviço 19 de 0x00 a 0x19. Aqui estão quatro maneiras comuns.

  • subfunção = 0x01 (reportNumberOfDTCByStatusMask)

É usado para ler o número de DTCs que estão em conformidade com a máscara de status do DTC. Neste momento, o parâmetro é uma máscara de máscara de byte, que é usada para operação "AND" com o DTC Status, e a ECU retorna o número de DTCs cujo resultado não é 0 após a operação "AND".

O Status do DTC é representado por um byte, e os 8 bits representam diferentes estados do DTC. Por exemplo, o bit 0 indica se o DTC está ativo ou passivo e o bit 4 indica se o DTC foi confirmado. Se o status do DTC for confirmado, significa que o DTC foi armazenado pela ECU.

Por exemplo: 19 01 08 O objetivo deste comando é ler o número de todos os DTCs cujo status é confirmado.

  • sub-função = 0x02 (reportDTCByStatusMask)

É usado para ler a lista de DTCs que atendem a condições específicas. Neste momento, o parâmetro ainda é uma máscara de byte, que é usada para operação "AND" com o Status do DTC, e a ECU retorna a lista de DTCs cujo resultado não é 0 após a operação "AND".

Por exemplo, o objetivo do comando 19 02 01 é ler o número de todos os DTCs ativos. Neste momento, o formato retornado pela ECU deve ser 59 02 01 XX XX XX 01 YY YY YY 09.... Cada entrada na lista DTC retornada tem 4 bytes, os três primeiros bytes são usados ​​para identificar o DTC, como XX XX XX, e o último byte é usado para identificar o status do DTC, como 01, indicando que o DTC está ativo e 09, indicando que o DTC está ativo e confirmado.

  • sub-função = 0x06 (reportDTCExtDataRecordByDTCNumber)

Ele é usado para ler um determinado DTC e seus dados ambientais relacionados. Neste momento, o parâmetro é de 4 bytes. Os três primeiros bytes são usados ​​para identificar o DTC que desejamos ler e o quarto byte é usado para identificar a faixa de dados ambientais a serem lidos. O UDS estipula que o FF é usado para indicar que todos os dados ambientais foram lidos. Cada fabricante pode definir outros valores de acordo com suas próprias necessidades para representar a faixa de dados ambientais a serem lidos. Os dados ambientais incluem o status do DTC, prioridade, número de ocorrências, contador de envelhecimento, registro de data e hora, quilometragem, etc. Os fabricantes também podem definir alguns dados de medição quando este DTC é gerado de acordo com suas próprias necessidades.

Por exemplo, 19 06 XX XX XX FF significa ler todos os dados ambientais de XX XXXX DTC, e o valor de retorno de ECU deve ser 59 06 XX XX XX AA BB CC DD..., onde AA BB CCDD... representa os dados ambientais armazenados juntos quando XX XX XX DTC é gerado.

  • subfunção = 0x0E(reportMostRecentConfirmedDTC)

Quando a subfunção = 0x0E, nenhum parâmetro é necessário. 0x0E indica que a ECU é necessária para relatar o último DTC definido como confirmado. O serviço 0x86 foi apresentado acima, e o serviço 19 com subfunção = 0x0E geralmente é passado como parâmetro para o comando 86, exigindo que a ECU informe automaticamente quando ocorre o armazenamento do DTC, ou seja, o comando de dois bytes 19 0E está embutido no comando 86 service. Este comando será usado no estágio de desenvolvimento, como verificar se um caminho de falha é válido.

  1. resumo

Este artigo descreve o protocolo UDS, métodos de interação e algum conteúdo do serviço de diagnóstico (incluindo diagnóstico e classe de gerenciamento de comunicação", "classe de transmissão de dados" e "transmissão de dados de armazenamento").

No futuro, continuaremos a atualizar o conteúdo restante do serviço de diagnóstico (incluindo controle IO, controle de rotina, upload e download) e outros conteúdos relacionados, portanto, fique atento!

Acho que você gosta

Origin blog.csdn.net/gonggong11qqqww/article/details/124966371
Recomendado
Clasificación