ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
usb_printer_vendor_ch9.h
Go to the documentation of this file.
1
50
51#pragma once
52
53#ifdef __cplusplus
54extern "C" {
55#endif
56
57#include <stdint.h>
58
59#include "ra8_usb.h"
60
61/* =============================================================================
62 * SETUP-envelope field constants (USB 2.0 sec 9.3 "USB Device Requests")
63 * =============================================================================
64 */
65
87
102
108typedef enum : uint8_t {
113
123
124/* =============================================================================
125 * Router action
126 * =============================================================================
127 */
128
151
152/* =============================================================================
153 * Descriptor tables (USB 2.0 sec 9.6 "Standard USB Descriptor Definitions")
154 * =============================================================================
155 */
156
165static const uint8_t g_pv_device_desc[] = {
166 0x12U, /* bLength = 18 */
167 0x01U, /* bDescriptorType = DEVICE */
168 0x00U,
169 0x02U, /* bcdUSB = 2.00 */
170 0x00U, /* bDeviceClass = 0 (per-iface) */
171 0x00U, /* bDeviceSubClass */
172 0x00U, /* bDeviceProtocol */
173 0x40U, /* bMaxPacketSize0 = 64 */
174 0x09U,
175 0x12U, /* idVendor = 0x1209 (pid.codes) */
176 0x01U,
177 0x00U, /* idProduct = 0x0001 */
178 0x00U,
179 0x01U, /* bcdDevice = 1.00 */
180 0x00U, /* iManufacturer = 0 */
181 0x00U, /* iProduct = 0 */
182 0x00U, /* iSerialNumber = 0 */
183 0x01U, /* bNumConfigurations = 1 */
184};
185
196static const uint8_t g_pv_config_desc[] = {
197 /* Configuration descriptor (USB 2.0 sec 9.6.3) -- 9 bytes. */
198 0x09U, /* bLength */
199 0x02U, /* bDescriptorType = CONFIGURATION */
200 0x37U,
201 0x00U, /* wTotalLength = 55 */
202 0x02U, /* bNumInterfaces = 2 */
203 0x01U, /* bConfigurationValue = 1 */
204 0x00U, /* iConfiguration = 0 */
205 0x80U, /* bmAttributes = bus-powered */
206 0x32U, /* bMaxPower = 100 mA */
207 /* IF0 -- Printer, bi-directional (USB Printer Class 1.1 sec 4.1). */
208 0x09U, /* bLength */
209 0x04U, /* bDescriptorType = INTERFACE */
210 0x00U, /* bInterfaceNumber = 0 */
211 0x00U, /* bAlternateSetting = 0 */
212 0x02U, /* bNumEndpoints = 2 */
213 0x07U, /* bInterfaceClass = Printer */
214 0x01U, /* bInterfaceSubClass = Printers */
215 0x02U, /* bInterfaceProtocol = bi-dir */
216 0x00U, /* iInterface = 0 */
217 /* Printer bulk OUT endpoint (print data). */
218 0x07U, /* bLength */
219 0x05U, /* bDescriptorType = ENDPOINT */
220 0x01U, /* bEndpointAddress = EP1 OUT */
221 0x02U, /* bmAttributes = bulk */
222 0x40U,
223 0x00U, /* wMaxPacketSize = 64 */
224 0x00U, /* bInterval = 0 */
225 /* Printer bulk IN endpoint (status). */
226 0x07U, /* bLength */
227 0x05U, /* bDescriptorType = ENDPOINT */
228 0x82U, /* bEndpointAddress = EP2 IN */
229 0x02U, /* bmAttributes = bulk */
230 0x40U,
231 0x00U, /* wMaxPacketSize = 64 */
232 0x00U, /* bInterval = 0 */
233 /* IF1 -- Vendor specific (USB-IF class 0xFF). */
234 0x09U, /* bLength */
235 0x04U, /* bDescriptorType = INTERFACE */
236 0x01U, /* bInterfaceNumber = 1 */
237 0x00U, /* bAlternateSetting = 0 */
238 0x02U, /* bNumEndpoints = 2 */
239 0xFFU, /* bInterfaceClass = Vendor */
240 0x00U, /* bInterfaceSubClass */
241 0x00U, /* bInterfaceProtocol */
242 0x00U, /* iInterface = 0 */
243 /* Vendor bulk IN endpoint. */
244 0x07U, /* bLength */
245 0x05U, /* bDescriptorType = ENDPOINT */
246 0x81U, /* bEndpointAddress = EP1 IN */
247 0x02U, /* bmAttributes = bulk */
248 0x40U,
249 0x00U, /* wMaxPacketSize = 64 */
250 0x00U, /* bInterval = 0 */
251 /* Vendor bulk OUT endpoint. */
252 0x07U, /* bLength */
253 0x05U, /* bDescriptorType = ENDPOINT */
254 0x02U, /* bEndpointAddress = EP2 OUT */
255 0x02U, /* bmAttributes = bulk */
256 0x40U,
257 0x00U, /* wMaxPacketSize = 64 */
258 0x00U, /* bInterval = 0 */
259};
260
270static const uint8_t g_pv_string0_desc[] = {
271 0x04U, /* bLength = 4 */
272 0x03U, /* bDescriptorType = STRING */
273 0x09U,
274 0x04U, /* wLANGID[0] = 0x0409 (en-US) */
275};
276
277/* =============================================================================
278 * Router helpers
279 * =============================================================================
280 */
281
298{
299 const uint8_t desc_type = (uint8_t)(setup->w_value >> 8U);
300 switch (desc_type) {
301 case (uint8_t)k_pv_dt_device:
303 case (uint8_t)k_pv_dt_config:
305 case (uint8_t)k_pv_dt_string:
307 default:
308 return k_pv_action_stall;
309 }
310}
311
327{
328 switch (setup->b_request) {
329 case (uint8_t)k_pv_std_get_descriptor:
330 return pv_route_get_descriptor(setup);
331 case (uint8_t)k_pv_std_set_address:
333 case (uint8_t)k_pv_std_set_configuration:
335 default:
336 return k_pv_action_stall;
337 }
338}
339
340/* =============================================================================
341 * Public router + accessors
342 * =============================================================================
343 */
344
376static inline pv_action_t pv_route_setup(const ra8_usb_setup_t* setup)
377{
378 if (setup == nullptr) {
379 return k_pv_action_stall;
380 }
381 const uint8_t req_type = (uint8_t)(setup->bm_request_type & (uint8_t)k_pv_bm_type_mask);
382 switch (req_type) {
383 case (uint8_t)k_pv_bm_type_standard:
384 return pv_route_standard(setup);
385 case (uint8_t)k_pv_bm_type_class:
387 case (uint8_t)k_pv_bm_type_vendor:
389 default:
390 return k_pv_action_stall;
391 }
392}
393
415static inline bool pv_is_printer_class_request(const ra8_usb_setup_t* setup)
416{
417 if (setup == nullptr) {
418 return false;
419 }
420 const bool is_iface =
421 ((setup->bm_request_type & (uint8_t)k_pv_bm_recip_mask) == (uint8_t)k_pv_bm_recip_iface);
422 const bool is_known = ((setup->b_request == (uint8_t)k_pv_pprn_get_device_id) ||
423 (setup->b_request == (uint8_t)k_pv_pprn_get_port_status) ||
424 (setup->b_request == (uint8_t)k_pv_pprn_soft_reset));
425 return is_iface && is_known;
426}
427
448static inline bool pv_descriptor(pv_action_t action, const uint8_t** out_desc, uint16_t* out_len)
449{
450 if ((out_desc == nullptr) || (out_len == nullptr)) {
451 return false;
452 }
453 switch (action) {
455 *out_desc = g_pv_device_desc;
456 *out_len = (uint16_t)sizeof(g_pv_device_desc);
457 return true;
459 *out_desc = g_pv_config_desc;
460 *out_len = (uint16_t)sizeof(g_pv_config_desc);
461 return true;
463 *out_desc = g_pv_string0_desc;
464 *out_len = (uint16_t)sizeof(g_pv_string0_desc);
465 return true;
466 default:
467 return false;
468 }
469}
470
485static inline uint16_t pv_clamp_len(uint16_t available, uint16_t requested)
486{
487 return (available < requested) ? available : requested;
488}
489
490#ifdef __cplusplus
491}
492#endif
Native USB controller driver public API (device + host modes).
Decoded 8-byte USB SETUP packet.
uint8_t b_request
bRequest code.
uint8_t bm_request_type
Request direction / type / recipient.
uint16_t w_value
wValue.
static pv_action_t pv_route_setup(const ra8_usb_setup_t *setup)
Classify an 8-byte SETUP envelope into a pv_action_t.
pv_std_request_t
Standard bRequest codes this device answers (USB 2.0 Table 9-4).
@ k_pv_std_get_descriptor
GET_DESCRIPTOR.
@ k_pv_std_set_address
SET_ADDRESS.
@ k_pv_std_set_configuration
SET_CONFIGURATION.
pv_printer_request_t
Printer class bRequest codes (USB Printer Class 1.1 sec 4.2).
@ k_pv_pprn_get_device_id
GET_DEVICE_ID.
@ k_pv_pprn_get_port_status
GET_PORT_STATUS.
@ k_pv_pprn_soft_reset
SOFT_RESET.
static const uint8_t g_pv_config_desc[]
55-byte CONFIGURATION descriptor: IF0 Printer + IF1 Vendor.
static pv_action_t pv_route_standard(const ra8_usb_setup_t *setup)
Route a standard request by its bRequest code.
static pv_action_t pv_route_get_descriptor(const ra8_usb_setup_t *setup)
Route a standard GET_DESCRIPTOR by its wValue high byte.
pv_req_field_t
Masks + values used to decode a SETUP bmRequestType byte.
@ k_pv_bm_type_vendor
Vendor request.
@ k_pv_bm_dir_mask
Direction bit 7 (1 = device->host).
@ k_pv_bm_recip_mask
Recipient field, bits 4:0.
@ k_pv_bm_recip_iface
Interface recipient.
@ k_pv_bm_type_mask
Request-type field, bits 6:5.
@ k_pv_bm_type_class
Class request.
@ k_pv_bm_dir_in
Device-to-host control read.
@ k_pv_bm_type_standard
Standard request.
static const uint8_t g_pv_device_desc[]
18-byte DEVICE descriptor for the composite printer + vendor gadget.
pv_desc_type_t
bDescriptorType values carried in the GET_DESCRIPTOR wValue high byte (USB 2.0 Table 9-5).
@ k_pv_dt_config
CONFIGURATION descriptor.
@ k_pv_dt_string
STRING descriptor.
@ k_pv_dt_device
DEVICE descriptor.
static bool pv_is_printer_class_request(const ra8_usb_setup_t *setup)
Recognise an interface-directed Printer class-specific request.
static uint16_t pv_clamp_len(uint16_t available, uint16_t requested)
Clamp a descriptor length to the host's advertised wLength.
pv_action_t
The decision pv_route_setup produces for a SETUP envelope.
@ k_pv_action_get_device_desc
Stage the DEVICE descriptor.
@ k_pv_action_get_config_desc
Stage the CONFIGURATION descriptor.
@ k_pv_action_vendor_class
Route to the Vendor class layer.
@ k_pv_action_get_string_desc
Stage the STRING (LANGID) descriptor.
@ k_pv_action_set_address
SET_ADDRESS: SIE-owned, ACK.
@ k_pv_action_stall
Unsupported: STALL EP0.
@ k_pv_action_set_configuration
SET_CONFIGURATION: ACK + go live.
@ k_pv_action_printer_class
Route to the Printer class layer.
static const uint8_t g_pv_string0_desc[]
STRING descriptor index 0 – the supported-language ID array.
static bool pv_descriptor(pv_action_t action, const uint8_t **out_desc, uint16_t *out_len)
Fetch the descriptor byte table + length for a descriptor action.