~ruther/stm32h747i-disco-usb-image-viewer

ref: a9ffd7282525bfe771b156f3ea8c56ab25939f6e stm32h747i-disco-usb-image-viewer/src/usb.c -rw-r--r-- 4.4 KiB
a9ffd728 — Rutherther fix: make sure to error if endpoint id not found in interrupt 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "usb.h"

typedef union {
  uint32_t word;
  uint16_t halfwords[2];
  uint8_t bytes[4];
} usb_data_t;

void usb_generic_send(uint8_t* data, uint16_t size, volatile uint32_t *fifo_tx_target) {
  usb_data_t tx_data;
  uint8_t subWordBytes = size % 4;
  uint8_t wordCount = size / 4;

  for (uint8_t i = 0; i < wordCount; i++) {
    tx_data.word = *((uint32_t*)data);
    *fifo_tx_target = tx_data.word;
    data += 4;
  }

  // TODO: check where to put it... beginning, end...
  if (subWordBytes != 0) {
    tx_data.word = 0;
    for (uint8_t i = 0; i < subWordBytes; i++) {
      tx_data.bytes[i] = *(data + i);
    }
    *fifo_tx_target = tx_data.word;
  }
}

void usb_generic_read(uint8_t *data, uint16_t size, volatile uint32_t *fifo_rx_source) {
  usb_data_t rx_data;
  uint8_t subWordBytes = size % 4;
  uint8_t wordCount = size / 4;

  for (uint8_t i = 0; i < wordCount; i++) {
    rx_data.word = *fifo_rx_source;
    *((uint32_t*)data) = rx_data.word;
    data += 4;
  }

  // TODO: check where to put it... beginning, end...
  if (subWordBytes > 0) {
    rx_data.word = 0;
    for (uint8_t i = 0; i < subWordBytes; i++) {
      *(data + i) = rx_data.bytes[i];
    }
  }
}

void usb_send_descriptor(usb_descriptor_t *descriptor,
                         volatile uint32_t *fifo_tx_target) {
  usb_generic_send((uint8_t*)descriptor, descriptor->bLength, fifo_tx_target);
}

void usb_send_configuration_descriptor(
    usb_configuration_descriptor_t *descriptor, volatile uint32_t *fifo_tx_target) {
  descriptor->header.bDescriptorType = DESCRIPTOR_CONFIGURATION;
  descriptor->header.bLength = sizeof(usb_configuration_descriptor_t);
  usb_send_descriptor(&descriptor->header, fifo_tx_target);
}
void usb_send_device_descriptor(usb_device_descriptor_t *descriptor,
                                   volatile uint32_t *fifo_tx_target) {
  descriptor->header.bDescriptorType = DESCRIPTOR_DEVICE;
  descriptor->header.bLength = sizeof(usb_device_descriptor_t);
  usb_send_descriptor(&descriptor->header, fifo_tx_target);
}
void usb_send_device_qualifier_descriptor(usb_device_qualifier_t *descriptor,
                                   volatile uint32_t *fifo_tx_target) {
  descriptor->header.bDescriptorType = DESCRIPTOR_DEVICE_QUALIFIER;
  descriptor->header.bLength = sizeof(usb_device_qualifier_t);
  usb_send_descriptor(&descriptor->header, fifo_tx_target);
}
void usb_send_interface_descriptor(usb_interface_descriptor_t *descriptor,
                                   volatile uint32_t *fifo_tx_target) {
  descriptor->header.bDescriptorType = DESCRIPTOR_INTERFACE;
  descriptor->header.bLength = sizeof(usb_interface_descriptor_t);
  usb_send_descriptor(&descriptor->header, fifo_tx_target);
}
void usb_send_endpoint_descriptor(usb_endpoint_descriptor_t *descriptor,
                                  volatile uint32_t *fifo_tx_target) {
  descriptor->header.bDescriptorType = DESCRIPTOR_ENDPOINT;
  descriptor->header.bLength = sizeof(usb_endpoint_descriptor_t);
  usb_send_descriptor(&descriptor->header, fifo_tx_target);
}

void usb_send_string_descriptor_zero(usb_string_descriptor_zero_t *string_descriptor,
                              volatile uint32_t *fifo_tx_target) {
  usb_data_t data;
  data.word = 0;

  data.bytes[0] = string_descriptor->header.bLength;
  data.bytes[1] = string_descriptor->header.bDescriptorType;

  if (string_descriptor->header.bLength == 2) {
    *fifo_tx_target = data.word;
    return;
  }

  data.halfwords[1] = string_descriptor->wLANGID[0];

  *fifo_tx_target = data.word;

  // TODO: Now the rest only from wLANGID[1..]
  if (string_descriptor->header.bLength > 4) {
    usb_generic_send((uint8_t *)&string_descriptor->wLANGID[1],
                     string_descriptor->header.bLength - 4,
                     fifo_tx_target);
  }
}
void usb_send_unicode_string_descriptor(
    usb_unicode_string_descriptor_t *string_descriptor,
    volatile uint32_t *fifo_tx_target) {
  usb_data_t data = { .word = 0 };
  data.halfwords[0] = *((uint16_t*)string_descriptor);
  if (string_descriptor->bString != 0 && string_descriptor->header.bLength > 2) {
    // NOTE: if the string had length of just one, there would be two bytes
    // read here. That shouldn't usually matter much, so we don't care about
    // that here.
    data.halfwords[1] = *((uint16_t*)string_descriptor->bString);
  }
  *fifo_tx_target = data.word;

  if (string_descriptor->header.bLength > 4) {
    usb_generic_send(&string_descriptor->bString[2], string_descriptor->header.bLength - 4, fifo_tx_target);
  }
}
Do not follow this link