@@ -1079,6 +1079,9 @@ struct scarlett2_device_info {
10791079 /* minimum firmware version required */
10801080 u16 min_firmware_version ;
10811081
1082+ /* has a downloadable device map */
1083+ u8 has_devmap ;
1084+
10821085 /* support for main/alt speaker switching */
10831086 u8 has_speaker_switching ;
10841087
@@ -1773,6 +1776,7 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
17731776static const struct scarlett2_device_info vocaster_one_info = {
17741777 .config_set = & scarlett2_config_set_vocaster ,
17751778 .min_firmware_version = 1769 ,
1779+ .has_devmap = 1 ,
17761780
17771781 .phantom_count = 1 ,
17781782 .inputs_per_phantom = 1 ,
@@ -1815,6 +1819,7 @@ static const struct scarlett2_device_info vocaster_one_info = {
18151819static const struct scarlett2_device_info vocaster_two_info = {
18161820 .config_set = & scarlett2_config_set_vocaster ,
18171821 .min_firmware_version = 1769 ,
1822+ .has_devmap = 1 ,
18181823
18191824 .phantom_count = 2 ,
18201825 .inputs_per_phantom = 1 ,
@@ -1858,6 +1863,7 @@ static const struct scarlett2_device_info vocaster_two_info = {
18581863static const struct scarlett2_device_info solo_gen4_info = {
18591864 .config_set = & scarlett2_config_set_gen4_solo ,
18601865 .min_firmware_version = 2115 ,
1866+ .has_devmap = 1 ,
18611867
18621868 .level_input_count = 1 ,
18631869 .air_input_count = 1 ,
@@ -1912,6 +1918,7 @@ static const struct scarlett2_device_info solo_gen4_info = {
19121918static const struct scarlett2_device_info s2i2_gen4_info = {
19131919 .config_set = & scarlett2_config_set_gen4_2i2 ,
19141920 .min_firmware_version = 2115 ,
1921+ .has_devmap = 1 ,
19151922
19161923 .level_input_count = 2 ,
19171924 .air_input_count = 2 ,
@@ -1966,6 +1973,7 @@ static const struct scarlett2_device_info s2i2_gen4_info = {
19661973static const struct scarlett2_device_info s4i4_gen4_info = {
19671974 .config_set = & scarlett2_config_set_gen4_4i4 ,
19681975 .min_firmware_version = 2089 ,
1976+ .has_devmap = 1 ,
19691977
19701978 .level_input_count = 2 ,
19711979 .air_input_count = 2 ,
@@ -2264,6 +2272,8 @@ static int scarlett2_get_port_start_num(
22642272#define SCARLETT2_USB_GET_DATA 0x00800000
22652273#define SCARLETT2_USB_SET_DATA 0x00800001
22662274#define SCARLETT2_USB_DATA_CMD 0x00800002
2275+ #define SCARLETT2_USB_INFO_DEVMAP 0x0080000c
2276+ #define SCARLETT2_USB_GET_DEVMAP 0x0080000d
22672277
22682278#define SCARLETT2_USB_CONFIG_SAVE 6
22692279
@@ -2277,6 +2287,14 @@ static int scarlett2_get_port_start_num(
22772287#define SCARLETT2_SEGMENT_SETTINGS_NAME "App_Settings"
22782288#define SCARLETT2_SEGMENT_FIRMWARE_NAME "App_Upgrade"
22792289
2290+ /* Gen 4 device firmware provides access to a base64-encoded
2291+ * zlib-compressed JSON description of the device's capabilities and
2292+ * configuration. This device map is made available in
2293+ * /proc/asound/cardX/device-map.json.zz.b64
2294+ */
2295+ #define SCARLETT2_DEVMAP_BLOCK_SIZE 1024
2296+ #define SCARLETT2_DEVMAP_FILENAME "device-map.json.zz.b64"
2297+
22802298/* proprietary request/response format */
22812299struct scarlett2_usb_packet {
22822300 __le32 cmd ;
@@ -9562,6 +9580,116 @@ static int scarlett2_hwdep_init(struct usb_mixer_interface *mixer)
95629580 return 0 ;
95639581}
95649582
9583+ /*** device-map file ***/
9584+
9585+ static ssize_t scarlett2_devmap_read (
9586+ struct snd_info_entry * entry ,
9587+ void * file_private_data ,
9588+ struct file * file ,
9589+ char __user * buf ,
9590+ size_t count ,
9591+ loff_t pos )
9592+ {
9593+ struct usb_mixer_interface * mixer = entry -> private_data ;
9594+ u8 * resp_buf ;
9595+ const size_t block_size = SCARLETT2_DEVMAP_BLOCK_SIZE ;
9596+ size_t copied = 0 ;
9597+
9598+ if (pos >= entry -> size )
9599+ return 0 ;
9600+
9601+ if (pos + count > entry -> size )
9602+ count = entry -> size - pos ;
9603+
9604+ resp_buf = kmalloc (block_size , GFP_KERNEL );
9605+ if (!resp_buf )
9606+ return - ENOMEM ;
9607+
9608+ while (count > 0 ) {
9609+ /* SCARLETT2_USB_GET_DEVMAP reads only on block boundaries,
9610+ * so we need to read a whole block and copy the requested
9611+ * chunk to userspace.
9612+ */
9613+
9614+ __le32 req ;
9615+ int err ;
9616+
9617+ /* offset within the block that we're reading */
9618+ size_t offset = pos % block_size ;
9619+
9620+ /* read_size is block_size except for the last block */
9621+ size_t block_start = pos - offset ;
9622+ size_t read_size = min_t (size_t ,
9623+ block_size ,
9624+ entry -> size - block_start );
9625+
9626+ /* size of the chunk to copy to userspace */
9627+ size_t copy_size = min_t (size_t , count , read_size - offset );
9628+
9629+ /* request the block */
9630+ req = cpu_to_le32 (pos / block_size );
9631+ err = scarlett2_usb (mixer , SCARLETT2_USB_GET_DEVMAP ,
9632+ & req , sizeof (req ), resp_buf , read_size );
9633+ if (err < 0 ) {
9634+ kfree (resp_buf );
9635+ return copied ? copied : err ;
9636+ }
9637+
9638+ if (copy_to_user (buf , resp_buf + offset , copy_size )) {
9639+ kfree (resp_buf );
9640+ return - EFAULT ;
9641+ }
9642+
9643+ buf += copy_size ;
9644+ pos += copy_size ;
9645+ copied += copy_size ;
9646+ count -= copy_size ;
9647+ }
9648+
9649+ kfree (resp_buf );
9650+ return copied ;
9651+ }
9652+
9653+ static const struct snd_info_entry_ops scarlett2_devmap_ops = {
9654+ .read = scarlett2_devmap_read ,
9655+ };
9656+
9657+ static int scarlett2_devmap_init (struct usb_mixer_interface * mixer )
9658+ {
9659+ struct snd_card * card = mixer -> chip -> card ;
9660+ struct scarlett2_data * private = mixer -> private_data ;
9661+ const struct scarlett2_device_info * info = private -> info ;
9662+ __le16 config_len_buf [2 ];
9663+ int config_len ;
9664+ struct snd_info_entry * entry ;
9665+ int err ;
9666+
9667+ /* If the device doesn't support the DEVMAP commands, don't
9668+ * create the /proc/asound/cardX/scarlett.json.zlib entry
9669+ */
9670+ if (!info -> has_devmap )
9671+ return 0 ;
9672+
9673+ err = scarlett2_usb (mixer , SCARLETT2_USB_INFO_DEVMAP ,
9674+ NULL , 0 , & config_len_buf , sizeof (config_len_buf ));
9675+ if (err < 0 )
9676+ return err ;
9677+
9678+ config_len = le16_to_cpu (config_len_buf [1 ]);
9679+
9680+ err = snd_card_proc_new (card , SCARLETT2_DEVMAP_FILENAME , & entry );
9681+ if (err < 0 )
9682+ return err ;
9683+
9684+ entry -> content = SNDRV_INFO_CONTENT_DATA ;
9685+ entry -> private_data = mixer ;
9686+ entry -> c .ops = & scarlett2_devmap_ops ;
9687+ entry -> size = config_len ;
9688+ entry -> mode = S_IFREG | 0444 ;
9689+
9690+ return 0 ;
9691+ }
9692+
95659693int snd_scarlett2_init (struct usb_mixer_interface * mixer )
95669694{
95679695 struct snd_usb_audio * chip = mixer -> chip ;
@@ -9612,11 +9740,20 @@ int snd_scarlett2_init(struct usb_mixer_interface *mixer)
96129740 }
96139741
96149742 err = scarlett2_hwdep_init (mixer );
9615- if (err < 0 )
9743+ if (err < 0 ) {
96169744 usb_audio_err (mixer -> chip ,
96179745 "Error creating %s hwdep device: %d" ,
96189746 entry -> series_name ,
96199747 err );
9748+ return err ;
9749+ }
9750+
9751+ err = scarlett2_devmap_init (mixer );
9752+ if (err < 0 )
9753+ usb_audio_err (mixer -> chip ,
9754+ "Error creating %s devmap entry: %d" ,
9755+ entry -> series_name ,
9756+ err );
96209757
96219758 return err ;
96229759}
0 commit comments