Send cmd to SD card but error 22 on Linux - c++

I refer an article:
Any way to send commands to SD card from Linux userspace?
and use the source of mmc-util to send cmd to SD card, there is the code:
int cmd_test(int fd, __u8 *ext_csd)
{
int ret = 0;
struct mmc_ioc_cmd idata;
memset(&idata, 0, sizeof(idata));
memset(ext_csd, 0, sizeof(__u8) * 512);
idata.write_flag = 0;
idata.opcode = 17;
idata.arg = 0;
idata.flags = MMC_DATA_READ;
idata.blksz = 512;
idata.blocks = 1;
mmc_ioc_cmd_set_data(idata, ext_csd);
ret = ioctl(fd, MMC_IOC_CMD, &idata);
if (ret)
perror("ioctl");
return ret;
}
finally receive error 22: invalid argument. I try another opcode like 10, 56..., it finally result same error.
The SD card is connected by usb reader, does it cause the error? or there are parameter setting error?
Thanks.

Related

ESP32 - SPI "spi_bus_initialize: host already in use" with SDCARD

I am trying to write to a sd card using an esp32. The problem is that I cannot mount the unit. The SPI bus does not seem to work. I am using VSPI, since using HSPI it restarts constantly, it seems to be due to the use of pin 12
My code is:
esp_err_t ret;
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
.format_if_mount_failed = format,
.max_files = 5,
.allocation_unit_size = 16 * 1024
};
const char mount_point[] = MOUNT_POINT;
ESP_LOGI(TAG, "Initializing SD card");
ESP_LOGI(TAG, "Using SPI peripheral");
//spi_host_device_t host = SDSPI_HOST_DEFAULT(); //Usa HSPI (SPI2) o VSPI (SPI3) host.
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
host.slot = VSPI_HOST;
spi_bus_config_t bus_cfg = {
.mosi_io_num = PIN_NUM_MOSI,
.miso_io_num = PIN_NUM_MISO,
.sclk_io_num = PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
//ret = spi_bus_initialize((spi_host_device_t)host.slot, &bus_cfg, 0);
ret = spi_bus_initialize(VSPI_HOST, &bus_cfg, 2);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize bus.");
card = NULL;
return;
}
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); // SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = (gpio_num_t)cs_pin;
//slot_config.host_id = host.slot;
//ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to mount card.");
card = NULL;
return;
}
Also use esp_vfs_fat_sdmmc_mount instead of esp_vfs_fat_sdspi_mount because the esp_vfs_fat_sdspi_mount function does not exist. why?
Pin used:
CS: 5
SCLK: 18
MISO: 19
MOSI: 23
Use platformio with Visual Studio Code.
This is my output console:
(320) sdcard: Initializing SD card␛[0m
␛[0;32mI (321) sdcard: Using SPI peripheral␛[0m
␛[0;31mE (321) spi: SPI3 already claimed by spi master.␛[0m
␛[0;31mE (323) spi_master: spi_bus_initialize(232): host already in use␛[0m
␛[0;31mE (330) sdcard: Failed to mount card.␛[0m

Xcode app for macOS. This is how I setup to get audio from usb mic input. Worked a year ago, now doesn't. Why

Here is my audio init code. My app responds when queue buffers are ready, but all data in buffer is zero. Checking sound in system preferences shows that USB Audio CODEC in sound input dialog is active. AudioInit() is called right after app launches.
{
#pragma mark user data struct
typedef struct MyRecorder
{
AudioFileID recordFile;
SInt64 recordPacket;
Float32 *pSampledData;
MorseDecode *pMorseDecoder;
} MyRecorder;
#pragma mark utility functions
void CheckError(OSStatus error, const char *operation)
{
if(error == noErr) return;
char errorString[20];
// see if it appears to be a 4 char code
*(UInt32*)(errorString + 1) = CFSwapInt32HostToBig(error);
if (isprint(errorString[1]) && isprint(errorString[2]) &&
isprint(errorString[3]) && isprint(errorString[4]))
{
errorString[0] = errorString[5] = '\'';
errorString[6] = '\0';
}
else
{
sprintf(errorString, "%d", (int)error);
}
fprintf(stderr, "Error: %s (%s)\n", operation, errorString);
}
OSStatus MyGetDefaultInputDeviceSampleRate(Float64 *outSampleRate)
{
OSStatus error;
AudioDeviceID deviceID = 0;
AudioObjectPropertyAddress propertyAddress;
UInt32 propertySize;
propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = 0;
propertySize = sizeof(AudioDeviceID);
error = AudioObjectGetPropertyData(kAudioObjectSystemObject,
&propertyAddress,
0,
NULL,
&propertySize,
&deviceID);
if(error)
return error;
propertyAddress.mSelector = kAudioDevicePropertyNominalSampleRate;
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = 0;
propertySize = sizeof(Float64);
error = AudioObjectGetPropertyData(deviceID,
&propertyAddress,
0,
NULL,
&propertySize,
outSampleRate);
return error;
}
static int MyComputeRecordBufferSize(const AudioStreamBasicDescription *format,
AudioQueueRef queue,
float seconds)
{
int packets, frames, bytes;
frames = (int)ceil(seconds * format->mSampleRate);
if(format->mBytesPerFrame > 0)
{
bytes = frames * format->mBytesPerFrame;
}
else
{
UInt32 maxPacketSize;
if(format->mBytesPerPacket > 0)
{
// constant packet size
maxPacketSize = format->mBytesPerPacket;
}
else
{
// get the largest single packet size possible
UInt32 propertySize = sizeof(maxPacketSize);
CheckError(AudioQueueGetProperty(queue,
kAudioConverterPropertyMaximumOutputPacketSize,
&maxPacketSize,
&propertySize),
"Couldn't get queues max output packet size");
}
if(format->mFramesPerPacket > 0)
packets = frames / format->mFramesPerPacket;
else
// worst case scenario: 1 frame in a packet
packets = frames;
// sanity check
if(packets == 0)
packets = 1;
bytes = packets * maxPacketSize;
}
return bytes;
}
extern void bridgeToMainThread(MorseDecode *pDecode);
static int callBacks = 0;
// ---------------------------------------------
static void MyAQInputCallback(void *inUserData,
AudioQueueRef inQueue,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp *inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription *inPacketDesc)
{
MyRecorder *recorder = (MyRecorder*)inUserData;
Float32 *pAudioData = (Float32*)(inBuffer->mAudioData);
recorder->pMorseDecoder->pBuffer = pAudioData;
recorder->pMorseDecoder->bufferSize = inNumPackets;
bridgeToMainThread(recorder->pMorseDecoder);
CheckError(AudioQueueEnqueueBuffer(inQueue,
inBuffer,
0,
NULL),
"AudioQueueEnqueueBuffer failed");
printf("packets = %ld, bytes = %ld\n",(long)inNumPackets,(long)inBuffer->mAudioDataByteSize);
callBacks++;
//printf("\ncallBacks = %d\n",callBacks);
//if(callBacks == 0)
//audioStop();
}
static AudioQueueRef queue = {0};
static MyRecorder recorder = {0};
static AudioStreamBasicDescription recordFormat;
void audioInit()
{
// set up format
memset(&recordFormat,0,sizeof(recordFormat));
recordFormat.mFormatID = kAudioFormatLinearPCM;
recordFormat.mChannelsPerFrame = 2;
recordFormat.mBitsPerChannel = 32;
recordFormat.mBytesPerPacket = recordFormat.mBytesPerFrame = recordFormat.mChannelsPerFrame * sizeof(Float32);
recordFormat.mFramesPerPacket = 1;
//recordFormat.mFormatFlags = kAudioFormatFlagsCanonical;
recordFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
MyGetDefaultInputDeviceSampleRate(&recordFormat.mSampleRate);
UInt32 propSize = sizeof(recordFormat);
CheckError(AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
0,
NULL,
&propSize,
&recordFormat),
"AudioFormatProperty failed");
recorder.pMorseDecoder = MorseDecode::pInstance();
recorder.pMorseDecoder->m_sampleRate = recordFormat.mSampleRate;
// recorder.pMorseDecoder->setCircularBuffer();
//set up queue
CheckError(AudioQueueNewInput(&recordFormat,
MyAQInputCallback,
&recorder,
NULL,
kCFRunLoopCommonModes,
0,
&queue),
"AudioQueueNewInput failed");
UInt32 size = sizeof(recordFormat);
CheckError(AudioQueueGetProperty(queue,
kAudioConverterCurrentOutputStreamDescription,
&recordFormat,
&size), "Couldn't get queue's format");
// set up buffers and enqueue
const int kNumberRecordBuffers = 3;
int bufferByteSize = MyComputeRecordBufferSize(&recordFormat, queue, AUDIO_BUFFER_DURATION);
for(int bufferIndex = 0; bufferIndex < kNumberRecordBuffers; bufferIndex++)
{
AudioQueueBufferRef buffer;
CheckError(AudioQueueAllocateBuffer(queue,
bufferByteSize,
&buffer),
"AudioQueueAllocateBuffer failed");
CheckError(AudioQueueEnqueueBuffer(queue,
buffer,
0,
NULL),
"AudioQueueEnqueueBuffer failed");
}
}
void audioRun()
{
CheckError(AudioQueueStart(queue, NULL), "AudioQueueStart failed");
}
void audioStop()
{
CheckError(AudioQueuePause(queue), "AudioQueuePause failed");
}
}
This sounds like the new macOS 'microphone privacy' setting, which, if set to 'no access' for your app, will cause precisely this behaviour. So:
Open the System Preferences pane.
Click on 'Security and Privacy'.
Select the Privacy tab.
Click on 'Microphone' in the left-hand pane.
Locate your app in the right-hand pane and tick the checkbox next to it.
Then restart your app and test it.
Tedious, no?
Edit: As stated in the comments, you can't directly request microphone access, but you can detect whether it has been granted to your app or not by calling [AVCaptureDevice authorizationStatusForMediaType: AVMediaTypeAudio].

Get device name from usb

lsusb command
i want to get device name like on lsusb. I found this code and i tried its all descriptor parameters.Is there any way to get device name like on picture like Log. Opt. Gam. Mouse
#include <stdio.h>
#include <usb.h>
main(){
struct usb_bus *bus;
struct usb_device *dev;
usb_init();
usb_find_busses();
usb_find_devices();
for (bus = usb_busses; bus; bus = bus->next)
for (dev = bus->devices; dev; dev = dev->next){
printf("Trying device %s/%s\n", bus->dirname, dev->filename);
printf("\tID_VENDOR = 0x%04x\n", dev->descriptor.idVendor);
printf("\tID_PRODUCT = 0x%04x\n", dev->descriptor.idProduct);
}
}
the poiter for you is look into libusb library.
starting with libusb_get_device_list which Returns a list of USB devices currently attached to the system.
https://libusb.sourceforge.io/api-1.0/group__libusb__dev.html
you can take it from there.
if you want other way reading /sys/bus/usb/devices directory and read valid devices.
except root hub or other hubs.
EDIT1:
updated link
here is usage
libusb_device **list;
ssize_t cnt = libusb_get_device_list(NULL, &list);
ssize_t i = 0;
if (cnt < 0)
handle_error(); //handle error and return
for (i = 0; i < cnt; i++) {
libusb_device *device = list[i];
// do your work
}
libusb_free_device_list(list, 1);

ioctrl using SCSI pass through

Using Windows I can easily communicate with my USB device using the following simplified code:
DWORD dwJunk; // discard results from DeviceIOControl()
int iReply;
char cBuffer[100];
// cBuffer is initialized here.
HANDLE hDevice; // handle to the drive to be examined
CString sDrive = _T(\\\\.\\H:); // drive H: for this test
hDevice = CreateFile(sDrive, // drive to open
GENERIC_READ | GENERIC_WRITE, // read and write access to the drive
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes
iReply = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &cBuffer, sizeof(cBuffer), &cBuffer, sizeof(cBuffer), &dwJunk, (LPOVERLAPPED)NULL);
I'm trying to do the same in linux but have not been able to figure out the ioctrl() parameters, or better put the structure. A code snippet would be vey much appreciated. Thanks.
Unfortunately the code I modified using your link didn't return any results. Here's the stripped code I used. ioctl() returned without errors:
#define DEF_TIMEOUT 5000 // 5 seconds
char cDiskName[] = "/dev/sg3";
int fd = open(cDiskName, O_RDWR);
if (fd < 0)
{
printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno));
return 1;
}
unsigned char turCmbBlk[] = {0x00, 0, 0, 0, 0, 0};
struct sg_io_hdr io_hdr;
unsigned char cIOBuffer[100];
// buffer initialization code omitted
memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = sizeof(turCmbBlk);
io_hdr.mx_sb_len = sizeof(cIOBuffer);
io_hdr.dxfer_direction = SG_DXFER_NONE;
io_hdr.cmdp = turCmbBlk;
io_hdr.sbp = cIOBuffer;
io_hdr.timeout = DEF_TIMEOUT;
if (ioctl(fd, SG_IO, &io_hdr) < 0)
{
printf("ioctl error: errno=%d (%s)\n", errno, strerror(errno));
}
// Code returned here without any errors but cIOBuffer remains unchanged.
Maybe the call needs a different request code?
Here's some more documentation:
Notes on Linux's SG driver version 2.1.36
SCSI-Programming, page 8 (handle_SCSI_cmd function), page 9, page 11 (example) and some more
Generic SCSI Target Subsystem for Linux
See here:
#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
Parameters:
Filedescriptor (must be open!)
Request code number (depends on device)
Untyped pointer to memory (going to / coming from driver)
Example
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
void main(int argc, char **argv)
{
const char *filename;
int fd;
filename = argv[1];
fd = open(filename, O_WRONLY);
ioctl(fd, USBDEVFS_RESET, 0);
close(fd);
return;
}
Documentation:
ioctl(2) - Linux man page
IOCTL(2)
Generic I/O Control operations (GNU libc)
The ioctl() Requests
usb.c (Example that might help you)
Linux / Unix Command: ioctl
How to Reset USB Device in Linux (Example)
An example Program with IOCTL
Edit
#define BUFF_SIZE 100 // - Buffersize
#define DEF_TIMEOUT 5000 // 5 seconds
char cDiskName[] = "/dev/sg3";
int fd = open(cDiskName, O_RDWR);
if (fd < 0)
{
printf("Open error: %s, errno=%d (%s)\n", cDiskName, errno, strerror(errno));
return 1;
}
unsigned char turCmbBlk[] = {0x00, 0, 0, 0, 0, 0};
struct sg_io_hdr *p = (struct sg_io_hdr *) malloc(sizeof(struct sg_io_hdr)); // - dynamic memory allocation - free() required somewhere
unsigned char cIOBuffer[BUFF_SIZE];
unsigned char replyBuffer[BUFF_SIZE]; // - dxfer buffer
// buffer initialization code omitted
memset(p, 0, sizeof(struct sg_io_hdr));
p->interface_id = 'S';
p->cmd_len = sizeof(turCmbBlk);
p->mx_sb_len = BUFF_SIZE;
p->dxfer_direction = SG_DXFER_NONE;
p->cmdp = turCmbBlk;
p->sbp = cIOBuffer;
p->timeout = DEF_TIMEOUT;
p->flags = SG_FLAG_DIRECT_IO; // - Does this help?
p->dxferp = replyBuffer; // - Set dxferp buffer - (A)
p->dxfer_len = BUFF_SIZE; // - buffersize
if (ioctl(fd, SG_IO, p) < 0)
{
printf("ioctl error: errno=%d (%s)\n", errno, strerror(errno));
}
// Code returned here without any errors but cIOBuffer remains unchanged.
Note (A): Please try setting your input / output buffer you work on here.
Documentation:
SCSI Generic HOWTO, SG_IO_HDR_T
Tour the Linux generic SCSI driver

i2c communication in IOKit on Mac OS X

I'm trying to communicate with display over ddc/ci using MacOS X function IOI2CSendRequest.
All works if i just send "set" command, like set brightness. I see that display receive command, because display change brightness.
But when i'm trying to receive reply from display i receive some garbage. What is correct way for send and receive reply with IOI2CSendRequest?
Here is my current code:
memset(&request, 0, sizeof (request));
request.commFlags = 0;
request.sendAddress = addr << 1;
request.sendTransactionType = kIOI2CSimpleTransactionType;
request.sendBuffer = (vm_address_t) package;
request.sendBytes = i;
request.replyAddress = (addr << 1) + 1;
request.replyTransactionType = kIOI2CNoTransactionType;
request.replyBuffer = NULL;
request.replyBytes = 0;
kr = IOI2CSendRequest(Display_, kNilOptions, &request);
mysleep(1000);
memset(&request, 0, sizeof (request));
request.commFlags = 0;
request.sendAddress = addr << 1;
request.sendTransactionType = kIOI2CNoTransactionType;
request.sendBuffer = (vm_address_t)package;
request.sendBytes = 0;
request.replyAddress = (addr << 1) + 1;
request.replyTransactionType = kIOI2CSimpleTransactionType;
request.replyBuffer = (vm_address_t) buf;
request.replyBytes = 127;
memset(buf, 0, request.replyBytes);
kr = IOI2CSendRequest(Display_, kNilOptions, &request);
Both kr and request.result equal to kIOReturnSuccess, but no valid data in buf.
Sent command is "51 82 01 10 AC", where is AC is checksum.
OS is 10.6.8 (Snow Leopard)
Any idea what is wrong in this code?