Forráskód Böngészése

projects/usb_amr/fw: Add support for {SET,GET,CLEAR}_COMM_FEATURE

This is not officially a part of DLM model but it's the closest
we got to something standard to allow the host to set the country
specific line parameters.

Also add the matching functional descriptor.

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Sylvain Munaut 1 éve
szülő
commit
e730ddc644

+ 1 - 1
cores/no2usb

@@ -1 +1 @@
-Subproject commit aa52a2371409101537ec6bb3d66f5c6bbce5b626
+Subproject commit d359102614762fbd6506024ab19331e30da27cf5

+ 74 - 1
projects/usb_amr/fw/cdc-dlm.c

@@ -7,6 +7,8 @@
  * SPDX-License-Identifier: LGPL-3.0-or-later
  */
 
+#include <string.h>
+
 #include <no2usb/usb.h>
 #include <no2usb/usb_hw.h>
 #include <no2usb/usb_priv.h>
@@ -36,6 +38,69 @@ dlm_send_notif_ring_detect(void)
 }
 
 
+static int16_t g_cc = 0;
+
+static bool
+dlm_set_comm_feature_country_cb(struct usb_xfer *xfer)
+{
+	uint16_t new_cc;
+
+	if (xfer->len != sizeof(uint16_t))
+		return USB_FND_ERROR;
+
+	memcpy(&new_cc, xfer->data, sizeof(uint16_t));
+
+	if (mc97_select_country(new_cc)) {
+		g_cc = new_cc;
+		return USB_FND_SUCCESS;
+	}
+
+	return USB_FND_ERROR;
+}
+
+static enum usb_fnd_resp
+dlm_set_comm_feature(struct usb_ctrl_req *req, struct usb_xfer *xfer)
+{
+	/* Only country selection supported */
+	if (req->wValue != 0x02 /* COUNTRY_SETTING */)
+		return USB_FND_ERROR;
+
+	/* Setup call back */
+	xfer->len = sizeof(uint16_t);
+	xfer->cb_done = dlm_set_comm_feature_country_cb;
+
+	return USB_FND_SUCCESS;
+}
+
+static enum usb_fnd_resp
+dlm_get_comm_feature(struct usb_ctrl_req *req, struct usb_xfer *xfer)
+{
+	/* Only country selection supported */
+	if (req->wValue != 0x02 /* COUNTRY_SETTING */)
+		return USB_FND_ERROR;
+
+	/* Send the currently selected country code */
+	xfer->len = sizeof(uint16_t);
+	memcpy(xfer->data, &g_cc, sizeof(uint16_t));
+
+	return USB_FND_SUCCESS;
+}
+
+static enum usb_fnd_resp
+dlm_clear_comm_feature(struct usb_ctrl_req *req, struct usb_xfer *xfer)
+{
+	/* Only country selection supported */
+	if (req->wValue != 0x02 /* COUNTRY_SETTING */)
+		return USB_FND_ERROR;
+
+	/* Restore default */
+	g_cc = 0;
+	mc97_select_country(0);
+
+	return USB_FND_SUCCESS;
+}
+
+
 static enum usb_fnd_resp
 dlm_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
 {
@@ -73,10 +138,18 @@ dlm_ctrl_req(struct usb_ctrl_req *req, struct usb_xfer *xfer)
 	case USB_RT_CDC_SET_PULSE_TIME:
 		return USB_FND_ERROR;
 
-	/* TODO: Maybe implement SET_COMM_FEATURE for country selection ? */
+	/* Implement SET_COMM_FEATURE for country selection ? */
 	/* In theory not part of DLM but it's the closest to a standard
 	 * thing to support tweaking the codec params to match local specs
 	 * for a phone line */
+	case USB_RT_CDC_SET_COMM_FEATURE:
+		return dlm_set_comm_feature(req, xfer);
+
+	case USB_RT_CDC_GET_COMM_FEATURE:
+		return dlm_get_comm_feature(req, xfer);
+
+	case USB_RT_CDC_CLEAR_COMM_FEATURE:
+		return dlm_clear_comm_feature(req, xfer);
 	}
 
 	return USB_FND_ERROR;

+ 19 - 1
projects/usb_amr/fw/usb_desc_app.c

@@ -29,6 +29,7 @@
 
 
 usb_cdc_union_desc_def(1);
+usb_cdc_coutry_sel_desc_def(71);
 usb_ac_ac_hdr_desc_def(2);
 usb_ac_ac_feature_desc_def(4);
 usb_ac_as_fmt_type1_desc_def(3);
@@ -80,6 +81,7 @@ static const struct {
 		struct usb_cdc_hdr_desc hdr;
 		struct usb_cdc_dlm_desc dlm;
 		struct usb_cdc_union_desc__1 ud;
+		struct usb_cdc_country_sel_desc__71 csd;
 		struct usb_ep_desc ep;
 	} __attribute__ ((packed)) cdc_dlm;
 
@@ -368,12 +370,28 @@ static const struct {
 			.bmCapabilities		= 0x02,
 		},
 		.ud = {
-			.bLength		= sizeof(struct usb_cdc_union_desc) + 1,
+			.bLength		= sizeof(struct usb_cdc_union_desc__1),
 			.bDescriptorType	= USB_CS_DT_INTF,
 			.bDescriptorsubtype	= USB_CDC_DST_UNION,
 			.bMasterInterface	= 4,
 			.bSlaveInterface	= { 1 },
 		},
+		.csd = {
+			.bLength		= sizeof(struct usb_cdc_country_sel_desc__71),
+			.bDescriptorType	= USB_CS_DT_INTF,
+			.bDescriptorsubtype	= USB_CDC_DST_COUNTRY_SEL,
+			.iCountryCodeRelDate	= 9,
+			.wCountryCode		= {
+				 32,  36,  40,  48,  56,  76, 100, 124, 152, 156,
+				158, 170, 191, 196, 203, 208, 218, 222, 246, 250,
+				276, 300, 316, 344, 348, 352, 356, 360, 372, 376,
+				380, 392, 398, 400, 410, 414, 422, 428, 442, 446,
+				458, 470, 484, 504, 512, 528, 554, 566, 578, 586,
+				604, 608, 616, 620, 642, 643, 682, 702, 703, 705,
+				710, 724, 752, 756, 760, 764, 784, 818, 826, 840,
+				887,
+			},
+		},
 		.ep = {
 			.bLength		= sizeof(struct usb_ep_desc),
 			.bDescriptorType	= USB_DT_EP,

+ 1 - 0
projects/usb_amr/fw/usb_str_app.txt

@@ -6,3 +6,4 @@ DFU runtime
 Line 1 In
 Line 1 Out
 Off-hook
+05042023