It's been a while, but it's a continuation of Last time. This time
These two. However, since Focusrite software does not support Linux, you need to do the initialization sequence that Windows did for you. First of all, from the analysis.
First, start Ratatoskr and then turn on / off the power of Scarlett 18i20.
A considerable amount of communication is being performed, but the point is to reset the serial number, so pay attention to the position of the serial number and make a hit. The position of the serial number is like 15..16 bytes, so if you think about it normally, the serial number is 0 or 1, and it seems that the feature appears in the message type part of 9..14 bytes. (* In the image, various filters are used to suppress.)
As a result, the following two control transfers were hit as it was.
SEND 21 02 00 00 03 00 10 00 00 00 00 00 00 00 01 00
SEND 21 02 00 00 03 00 10 00 02 00 00 00 00 00 01 00
I have sent the message with serial number 1 twice, but it seems that the first one is the serial number reset process, and the second one normally sends the message with serial number 1. First, write the code exactly as it is, and try to operate the previously written device status acquisition code with the serial number after reset. (The code below is an excerpt. See the previous code for details.)
reset_seq.py
device.ctrl_transfer(0x21, 0x02, 0x00, 0x03,
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
device.ctrl_transfer(0xA1, 0x03, 0x00, 0x03, 0x0010)
device.ctrl_transfer(0x21, 0x02, 0x00, 0x03,
[0x00, 0x00, 0x80, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00])
By the way, it seems that the value of the serial number part of the serial number reset command can be anything.
When looking at communication with USB devices on Linux, I think the method using wireshark is quite major, but I cat under / sys / kernel / debug / usbmon and play unnecessary output with grep -v. (In any case, it is necessary to install the usbmon module.)
Also, Linux seems to have a slightly different initialization process from Windows, for example, if you call set_configuration poorly, an error will occur.
analogstat4linux.py
import usb.core
import usb.backend.libusb1
from ctypes import c_void_p, c_int
backend = usb.backend.libusb1.get_backend()
from usb.util import CTRL_IN, CTRL_OUT, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE, build_request_type
from usb.control import get_status
VENDOR_ID = 0x1235
PRODUCT_ID = 0x8215
device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, backend=backend)
device.ctrl_transfer(0x21, 0x02, 0x00, 0x03,
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
device.ctrl_transfer(0xA1, 0x03, 0x00, 0x03, 0x0010)
device.ctrl_transfer(0x21, 0x02, 0x00, 0x03,
[0x00, 0x00, 0x80, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00])
device.read(0x83, 8, 100)
ret = bytearray(device.ctrl_transfer(0xA1, 0x03, 0x00, 0x03, 0x0028))
print(' '.join(map(lambda x: '{0:0{1}x}'.format(x, 2), ret)))
$ sudo cat /sys/kernel/debug/usbmon/3t > dump.txt
* Script execution in another terminal
Ctrl-C
$ grep -v 'Z[io]:' dump.txt
ffff95a78595f500 560234266 S Co:013:00 s 21 02 0000 0003 0010 16 = 00000000 00000100 00000000 00000000
ffff95a78595f500 560234401 C Co:013:00 0 16 >
ffff95a78595f500 560234429 S Ci:013:00 s a1 03 0000 0003 0010 16 <
ffff95a78595f500 560234646 C Ci:013:00 0 16 = 00000000 00000000 00000000 00000000
ffff95a78595f500 560234667 S Co:013:00 s 21 02 0000 0003 0018 24 = 00008000 08000100 00000000 00000000 7c000000 18000000
ffff95a78595f500 560234893 C Co:013:00 0 24 >
ffff95a78595f500 560235404 S Ii:013:03 -115 8 <
ffff95a78595f500 560235649 C Ii:013:03 0 8 = 01000000 00000000
ffff95a78595f500 560235693 S Ci:013:00 s a1 03 0000 0003 0028 40 <
ffff95a78595f500 560235776 C Ci:013:00 0 40 = 00008000 18000100 00000000 00000000 00000000 00000000 00000000 00000000
Apparently, this is also the expected result. (* There is a part that does not match the result of the Windows environment because some byte order conversion is included)
While writing various codes and experimenting, there were times when the device hung due to Operation Timeout, but at present, no recovery method has been found other than turning off the hardware. This is a future issue.
Finally the main subject. Among the functions of Scarlett 18i20, the functions that cannot be supported by the switch of the main unit and cannot be operated by the general-purpose driver of Linux are as follows.
The latter is rather complicated or troublesome, but it is not so troublesome for me to use [^ 2], so in addition to the former, LINE / INST IMPEDANCE [^ 3] switching and input PAD [^ 4] I will try to correspond.
The procedure is almost the same as before.
As a result, the following communication seems to be AIR switching.
Sequence (1)
SEND: 21 02 00 00 00 03 00 19 01 00 80 00 09 00 01 00 00 00 00 00 00 00 00 00 8c 00 00 00 01 00 00 00 01
SEND: 03 00 00 00 03 00 10
RECV: 01 00 80 00 00 00 01 00 00 00 00 00 00 00 00 00
Sequence (2)
SEND: 21 02 00 00 00 03 00 14 02 00 80 00 04 00 02 00 00 00 00 00 00 00 00 00 08 00 00 00
SEND: 03 00 00 00 03 00 10
RECV: 01 00 80 00 00 00 02 00 00 00 00 00 00 00 00 00
As a result of switching IMPEDANCE etc., the output control transfer in the analog input state change sequence (1) seems to be in the following format.
The details of the 25th byte are as follows.
Also, I was wondering what the output control transfer of sequence (2) meant, but it seems that this is a display switching command of the indicator on the main unit. ** If you do not send this message, the INST / PAD / AIR indicator on the main unit will not switch. ** **
The following is the code that switches the AIR state of analog input 1 each time it is executed.
switch_air.py
import usb.core
import usb.backend.libusb1
from ctypes import c_void_p, c_int
backend = usb.backend.libusb1.get_backend()
from usb.util import CTRL_IN, CTRL_OUT, CTRL_TYPE_CLASS, CTRL_RECIPIENT_INTERFACE, build_request_type
from usb.control import get_status
VENDOR_ID = 0x1235
PRODUCT_ID = 0x8215
device = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, backend=backend)
device.ctrl_transfer(0x21, 0x02, 0x00, 0x03,
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
device.ctrl_transfer(0xA1, 0x03, 0x00, 0x03, 0x0010)
#Status inquiry
device.ctrl_transfer(0x21, 0x02, 0x00, 0x03,
[0x00, 0x00, 0x80, 0x00, 0x08, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00])
device.read(0x83, 8, 100)
ret = bytearray(device.ctrl_transfer(0xA1, 0x03, 0x00, 0x03, 0x0028))
stat = ret[32] #AIR with analog input 1
device.ctrl_transfer(0x21, 0x02, 0x00, 0x03, [0x01, 0x00, 0x80, 0x00, 0x09, 0x00, 0x02, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x8C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
stat ^1]) #Switch state with XOR
device.ctrl_transfer(0xA1, 0x03, 0x00, 0x03, 0x0010)
#Switching indicators
device.ctrl_transfer(0x21, 0x02, 0x00, 0x03, [0x02, 0x00, 0x80, 0x00, 0x04, 0x00, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00])
device.ctrl_transfer(0xA1, 0x03, 0x00, 0x03, 0x0010)
The code I am actually developing is available below.
I'm so busy that I'm completely out of hand
If you fall under any of the above, please cooperate. [^ 6]
[^ 1]: A function that changes the sound quality during microphone recording to an emulation of the company's best-selling microphone preamplifier. If you can't use this, it's not worth buying for 56,000 yen. [^ 2]: During recording work, while recording the input signal on a PC, it is sometimes connected directly to the output for monitoring without latency, so it is best to play with the built-in mixer. [^ 3]: Since the impedance of the signal flowing differs depending on the equipment, switch it. [^ 4]: Decrease the gain for excessive input. [^ 5]: It is necessary to devise according to the situation, such as clearing the log once with F4 after the startup sequence is completed, narrowing down with a filter as mentioned last time. Is it important not to perform extra operations? [^ 6]: I don't know how many people are in Japan. I found two people doing similar things overseas.
Recommended Posts