]> mj.ucw.cz Git - home-hw.git/blobdiff - Inc/usb.h
Request/reply protocol
[home-hw.git] / Inc / usb.h
index 589774d6af50e02404e6fa48976edcc392e6f049..6d5eaf417ba6d195e67a399026bf53d1384200d9 100644 (file)
--- a/Inc/usb.h
+++ b/Inc/usb.h
@@ -1,17 +1,22 @@
-#define USB_SELF_POWERED
-
-typedef unsigned int uint;
-typedef uint8_t byte;
-typedef uint16_t u16;
-typedef int16_t s16;
-typedef uint32_t u32;
-typedef int32_t s32;
+/*** Configurable parameters ***/
 
-#define MIN(x,y) ((x) < (y) ? (x) : (y))
-#define MAX(x,y) ((x) > (y) ? (x) : (y))
+#define USB_SELF_POWERED
+#define USB_NUM_CONFIGURATIONS 1
+#define USB_DEBUG
 
 /*** USB state structure ***/
 
+/*
+ *  We have a single buffer for all control transfers.
+ *  It must be able to contain:
+ *
+ *    - 2-byte status replies
+ *    - UTF-16 versions of all string descriptors
+ *
+ *  In addition to that, its length must be even.
+ */
+#define USB_EP0_BUF_SIZE 256
+
 struct usb {
   PCD_HandleTypeDef *hpcd;
   byte state;                  // USB_STATE_xxx
@@ -23,11 +28,18 @@ struct usb {
   u16 ep0_setup_data_length;
   u16 ep0_remaining_length;
   u16 ep0_total_length;
-  byte status_buf[2];
+  byte ep0_buf[USB_EP0_BUF_SIZE];
+  // Descriptor data to be filled by the user during usb_dev_reset()
+  const byte *desc_device;
+  const byte *desc_config;
+  const char * const *desc_string;
+  const byte *desc_languages;
+  u16 desc_device_len;
+  u16 desc_config_len;
+  u16 desc_string_items;
+  u16 desc_languages_len;
 };
 
-void usb_init(struct usb *usb, PCD_HandleTypeDef *hpcd);
-
 enum usb_device_state {
   USB_STATE_DEFAULT,
   USB_STATE_ADDRESSED,
@@ -45,6 +57,61 @@ enum usb_ep0_state {
   USB_EP0_STALL,
 };
 
+#ifdef USB_DEBUG
+#define usb_debug debug_printf
+#else
+static inline void usb_debug(char *msg, ...)
+{ }
+#endif
+
+// Parsed setup request
+struct setup_request {
+  byte bmRequest;
+  byte bRequest;
+  u16 wValue;
+  u16 wIndex;
+  u16 wLength;
+};
+
+/*** Functions provided by low-level code ***/
+
+void usb_init(struct usb *usb, PCD_HandleTypeDef *hpcd);
+void usb_start(struct usb *usb);
+
+void usb_ctl_send_status(struct usb *usb);
+void usb_ctl_recv_status(struct usb *usb);
+void usb_ctl_send_data(struct usb *usb, const byte *data, uint len);
+void usb_ctl_recv_data(struct usb *usb, byte *data, uint len);
+void usb_ctl_error(struct usb *usb);
+void usb_ctl_setup_error(struct usb *usb, struct setup_request *setup);
+
+/*** Callbacks to user code ***/
+
+// Device was reset
+void usb_dev_reset(struct usb *usb);
+
+// Configure the device (usb->config is the selected configuration)
+void usb_dev_configure(struct usb *usb);
+
+// Un-configure the device (usb->config is the configuration we are leaving)
+void usb_dev_unconfigure(struct usb *usb);
+
+// Intercept a setup packet. Returns true if default processing should be skipped.
+// Remember to check if usb->state == USB_STATE_CONFIGURED for most requests.
+bool usb_dev_setup_hook(struct usb *usb, struct setup_request *setup);
+
+// Finished receiving control packet data requested by usb_ctl_recv_data()
+void usb_dev_ctl_recv_done(struct usb *usb);
+
+// Finished sending control packet data requested by usb_ctl_send_data()
+void usb_dev_ctl_send_done(struct usb *usb);
+
+// Finished receiving data on a non-control endpoint
+void usb_dev_recv_done(struct usb *usb, byte epnum);
+
+// Finished sending data on a non-control endpoint
+void usb_dev_send_done(struct usb *usb, byte epnum);
+
 /*** Constants from USB specs ***/
 
 #define USB_REQ_DIRECTION 0x80
@@ -144,9 +211,9 @@ static inline int usb_ep_is_stalled(struct usb *usb, byte ep_addr)
   return ((ep_addr & 0x80) ? usb->hpcd->IN_ep : usb->hpcd->OUT_ep) [ep_addr & 0x7f].is_stall;
 }
 
-static inline HAL_StatusTypeDef usb_ep_transmit(struct usb *usb, byte ep_addr, byte *buf, u32 size)
+static inline HAL_StatusTypeDef usb_ep_send(struct usb *usb, byte ep_addr, const byte *buf, u32 size)
 {
-  return HAL_PCD_EP_Transmit(usb->hpcd, ep_addr, buf, size);
+  return HAL_PCD_EP_Transmit(usb->hpcd, ep_addr, (byte *) buf, size);
 }
 
 static inline HAL_StatusTypeDef usb_ep_receive(struct usb *usb, byte ep_addr, byte *buf, u32 size)