Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Add support for SendBreak requests #64

Open
cyrozap opened this issue Mar 13, 2023 · 0 comments
Open

Feature request: Add support for SendBreak requests #64

cyrozap opened this issue Mar 13, 2023 · 0 comments

Comments

@cyrozap
Copy link
Contributor

cyrozap commented Mar 13, 2023

From the spec:

This request sends special carrier modulation that generates an RS-232 style break.

The wValue field contains the length of time, in milliseconds, of the break signal. If wValue contains a
value of FFFFh, then the device will send a break until another SendBreak request is received with the
wValue of 0000h.

The code that follows is my hacky attempt at implementing the functionality. I call it "hacky" because I used a loop to implement the delay time (which IIRC isn't accurate at all--I don't remember exactly because it's been almost 18 months since I last worked on this), and the pin mode change involves using memcpy to clone the old TX pin configuration, change it to GPIO, and then use the modified configuration to re-init the pin. Also, I'm not sure if it's a good idea to handle the delay inside the USB control endpoint event handler, since the delay can in theory be up to 65.534 seconds long. Also, now that I've thought about this more, if the delay was done outside of the event handler, what should be done if an indefinite SendBreak is sent, and then TX data is sent? Since the break is just holding the TX line low, if that data was transmitted during that time it would all be lost.

If anyone knows a better way to implement this, please let me know.

diff --git a/usb_cdc.c b/usb_cdc.c
index b48f4b5..300466c 100644
--- a/usb_cdc.c
+++ b/usb_cdc.c
@@ -241,6 +241,27 @@ static void usb_cdc_set_port_txa(int port, int txa_active) {
     }
 }
 
+static usb_status_t usb_cdc_send_break(int port, uint16_t duration_ms) {
+    if (port < USB_CDC_NUM_PORTS) {
+        const gpio_pin_t *tx_pin = &device_config_get()->cdc_config.port_config[port].pins[cdc_pin_tx];
+        if (duration_ms != 0) {
+            gpio_pin_t tx_pin_new = { 0 };
+            memcpy(&tx_pin_new, tx_pin, sizeof(gpio_pin_t));
+            tx_pin_new.func = gpio_func_general;
+            gpio_pin_init(&tx_pin_new);
+            gpio_pin_set(tx_pin, 0);
+        }
+        if (duration_ms != 0xffff) {
+            for (int i=0; i < 8000*duration_ms; i++) {
+                __NOP();
+            }
+            gpio_pin_set(tx_pin, 1);
+            gpio_pin_init(tx_pin);
+        }
+    }
+    return usb_status_ack;
+}
+
 static usb_status_t usb_cdc_set_control_line_state(int port, uint16_t state) {
     usb_cdc_set_port_dtr(port, (state & USB_CDC_CONTROL_LINE_STATE_DTR_MASK));
     usb_cdc_set_port_rts(port, (state & USB_CDC_CONTROL_LINE_STATE_RTS_MASK));
@@ -741,6 +762,8 @@ usb_status_t usb_cdc_ctrl_process_request(usb_setup_t *setup, void **payload,
                     return usb_status_ack;
                 }
                 break;
+            case usb_cdc_request_send_break:
+                return usb_cdc_send_break(port, setup->wValue);
             default:
                 ;
             }
diff --git a/usb_cdc.h b/usb_cdc.h
index c37bc7c..86b01eb 100644
--- a/usb_cdc.h
+++ b/usb_cdc.h
@@ -42,7 +42,7 @@ typedef enum {
 #define USB_CDC_ACM_CAPABILITY_SEND_BREAK           0x04
 #define USB_CDC_ACM_CAPABILITY_NETWORK_CONNECTION   0x08
 
-#define USB_CDC_ACM_CAPABILITIES (USB_CDC_ACM_CAPABILITY_LINE_CODING)
+#define USB_CDC_ACM_CAPABILITIES (USB_CDC_ACM_CAPABILITY_SEND_BREAK | USB_CDC_ACM_CAPABILITY_LINE_CODING)
 
 /* USB CDC Header Functional Descriptor */
 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant