why does linux 0.11 use read lock when doing block reading? - linux-kernel

I have read linux source code about block device part of version 0.11 and i found if two processes do reading block operation, one will lock the buffer(bh),another one has to wait this lock, my question is why reading will block each other by using such kind of locker? isn't it supposed to be write operation?
make_request (int major, int rw, struct buffer_head *bh)
{
struct request *req;
int rw_ahead;
if (rw_ahead = (rw == READA || rw == WRITEA))
{
if (bh->b_lock)
return;
if (rw == READA)
rw = READ;
else
rw = WRITE;
}
if (rw != READ && rw != WRITE)
panic ("Bad block dev command, must be R/W/RA/WA");
lock_buffer (bh);
if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate))
{
unlock_buffer (bh);
return;
}
repeat:
if (rw == READ)
req = request + NR_REQUEST;
else
req = request + ((NR_REQUEST * 2) / 3);
/* find an empty request */
while (--req >= request)
if (req->dev < 0)
break;
if (req < request)
{
if (rw_ahead)
{
unlock_buffer (bh);
return;
}
sleep_on (&wait_for_request);
goto repeat;
}
req->dev = bh->b_dev;
req->cmd = rw;
req->errors = 0;
req->sector = bh->b_blocknr << 1;
req->nr_sectors = 2;
req->buffer = bh->b_data;
req->waiting = NULL;
req->bh = bh;
req->next = NULL;
add_request (major + blk_dev, req);
}

Related

Debugging VM after vmlaunch

Description:
I'm following the tutorial on hypervisor development. After day 4 of the series I cannot make my code run. Right after __vmx_vmlaunch instruction gets executed successfully, the virtual machine I'm testing the hypervisor on, reboots. I believe this is caused by some incorrect settings of VMCS Host State Area (Chapter 24.5). There is no BSOD, crash nor error message in WinDbg.
I see two ways to approach this problem. One is to somehow extract more information from WinDbg. And the second one would require someone to spot what stupid thing I'm doing or missing in the vmcs initialization.
Unfortunately the code in tutorial is incomplete. I've spend some fair time to make sure that everything that tutorial covers is the same in my code. I will highlight parts which where added by me.
I'm really sorry for such an amount of code. Again let me emphasise that I believe the problem lies within the HOST fields (as the crash inside guest vm shouldn't crash the host).
int init_vmcs(struct __vcpu_t* vcpu)
{
log_entry("init_vmcs()\n");
// Determinate exact size which is implementation specific.
// We expect it to be 4KB, but it is not guaranteed.
union __vmx_basic_msr_t vmx_basic_msr = { 0 };
vmx_basic_msr.control = __readmsr(IA32_VMX_BASIC);
if (vmx_basic_msr.bits.vmxon_region_size != sizeof(struct __vmcs_t)) {
log_error("Non standard vmcs region size: %llx. Support not yet implemented.\n",
vmx_basic_msr.bits.vmxon_region_size);
log_exit("init_vmcs()\n");
return -1;
}
PHYSICAL_ADDRESS physical_max;
physical_max.QuadPart = MAXULONG64;
vcpu->vmcs = MmAllocateContiguousMemory(sizeof(struct __vmcs_t), physical_max);
if (!vcpu->vmcs) {
log_error("Failed to allocate vcpu->vmcs(MmAllocateContiguousMemory failed).\n");
log_exit("init_vmcs()\n");
return -1;
}
RtlSecureZeroMemory(vcpu->vmcs, sizeof(struct __vmcs_t));
vcpu->vmcs_physical = MmGetPhysicalAddress(vcpu->vmcs).QuadPart;
// Discover VMCS revision identifier that a processor uses by reading the
// VMX capability MSR IA32_VMX_BASIC.
vcpu->vmcs->header.bits.revision_identifier = (unsigned int)vmx_basic_msr.bits.vmcs_revision_identifier;
vcpu->vmcs->header.bits.shadow_vmcs_indicator = 0;
// Before loading vmcs we invoke vmclear to flush data which might be cached by processor.
if (__vmx_vmclear(&vcpu->vmcs_physical) || __vmx_vmptrld(&vcpu->vmcs_physical)) {
log_error("Failed to flush data or load vmcs. (__vmx_vmclear or __vmx_vmptrld failed).\n");
log_exit("init_vmcs()\n");
return -1;
}
// Initialize VMCS Guest State Area.
if (__vmx_vmwrite(GUEST_CR0, __readcr0()) ||
__vmx_vmwrite(GUEST_CR3, __readcr3()) ||
__vmx_vmwrite(GUEST_CR4, __readcr4()) ||
__vmx_vmwrite(GUEST_DR7, __readdr(7)) ||
__vmx_vmwrite(GUEST_RSP, vcpu->guest_rsp) ||
__vmx_vmwrite(GUEST_RIP, vcpu->guest_rip) ||
__vmx_vmwrite(GUEST_RFLAGS, __readeflags()) ||
__vmx_vmwrite(GUEST_DEBUG_CONTROL, __readmsr(IA32_DEBUGCTL)) ||
__vmx_vmwrite(GUEST_SYSENTER_ESP, __readmsr(IA32_SYSENTER_ESP)) ||
__vmx_vmwrite(GUEST_SYSENTER_EIP, __readmsr(IA32_SYSENTER_EIP)) ||
__vmx_vmwrite(GUEST_SYSENTER_CS, __readmsr(IA32_SYSENTER_CS)) ||
__vmx_vmwrite(GUEST_VMCS_LINK_POINTER, ~0ULL) ||
__vmx_vmwrite(GUEST_FS_BASE, __readmsr(IA32_FS_BASE)) ||
__vmx_vmwrite(GUEST_GS_BASE, __readmsr(IA32_GS_BASE))
) {
log_error("Failed to set guest state. (__vmx_vmwrite failed).\n");
log_exit("init_vmcs()\n");
return -1;
}
if (__vmx_vmwrite(CR0_READ_SHADOW, __readcr0()) ||
__vmx_vmwrite(CR4_READ_SHADOW, __readcr4())
) {
log_error("Failed to set cr0_read_shadow or cr4_read_shadow. (__vmx_vmwrite failed).\n");
log_exit("init_vmcs()\n");
return -1;
}
union __vmx_entry_control_t entry_controls = { 0 };
entry_controls.bits.ia32e_mode_guest = 1;
vmx_adjust_entry_controls(&entry_controls);
__vmx_vmwrite(VM_ENTRY_CONTROLS, entry_controls.control);
union __vmx_exit_control_t exit_controls = { 0 };
exit_controls.bits.host_address_space_size = 1;
vmx_adjust_exit_controls(&exit_controls);
__vmx_vmwrite(VM_EXIT_CONTROLS, exit_controls.control);
union __vmx_pinbased_control_msr_t pinbased_controls = { 0 };
vmx_adjust_pinbased_controls(&pinbased_controls);
__vmx_vmwrite(PIN_BASED_VM_EXECUTION_CONTROLS, pinbased_controls.control);
union __vmx_primary_processor_based_control_t primary_controls = { 0 };
primary_controls.bits.use_msr_bitmaps = 1;
primary_controls.bits.active_secondary_controls = 1;
vmx_adjust_primary_processor_based_controls(&primary_controls);
__vmx_vmwrite(PRIMARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, primary_controls.control);
union __vmx_secondary_processor_based_control_t secondary_controls = { 0 };
secondary_controls.bits.enable_rdtscp = 1;
secondary_controls.bits.enable_xsave_xrstor = 1;
secondary_controls.bits.enable_invpcid = 1;
vmx_adjust_secondary_processor_based_controls(&secondary_controls);
__vmx_vmwrite(SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS, secondary_controls.control);
__vmx_vmwrite(GUEST_CS_SELECTOR, __read_cs());
__vmx_vmwrite(GUEST_SS_SELECTOR, __read_ss());
__vmx_vmwrite(GUEST_DS_SELECTOR, __read_ds());
__vmx_vmwrite(GUEST_ES_SELECTOR, __read_es());
__vmx_vmwrite(GUEST_FS_SELECTOR, __read_fs());
__vmx_vmwrite(GUEST_GS_SELECTOR, __read_gs());
__vmx_vmwrite(GUEST_LDTR_SELECTOR, __read_ldtr());
__vmx_vmwrite(GUEST_TR_SELECTOR, __read_tr());
__vmx_vmwrite(GUEST_CS_LIMIT, __segmentlimit(__read_cs()));
__vmx_vmwrite(GUEST_SS_LIMIT, __segmentlimit(__read_ss()));
__vmx_vmwrite(GUEST_DS_LIMIT, __segmentlimit(__read_ds()));
__vmx_vmwrite(GUEST_ES_LIMIT, __segmentlimit(__read_es()));
__vmx_vmwrite(GUEST_FS_LIMIT, __segmentlimit(__read_fs()));
__vmx_vmwrite(GUEST_GS_LIMIT, __segmentlimit(__read_gs()));
__vmx_vmwrite(GUEST_LDTR_LIMIT, __segmentlimit(__read_ldtr()));
__vmx_vmwrite(GUEST_TR_LIMIT, __segmentlimit(__read_tr()));
struct __pseudo_descriptor_64_t gdtr;
struct __pseudo_descriptor_64_t idtr;
_sgdt(&gdtr);
__sidt(&idtr);
__vmx_vmwrite(GUEST_GDTR_BASE, gdtr.base_address);
__vmx_vmwrite(GUEST_GDTR_LIMIT, gdtr.limit);
__vmx_vmwrite(GUEST_IDTR_BASE, idtr.base_address);
__vmx_vmwrite(GUEST_IDTR_LIMIT, idtr.limit);
__vmx_vmwrite(GUEST_CS_BASE, get_segment_base(gdtr.base_address, __read_cs()));
__vmx_vmwrite(GUEST_DS_BASE, get_segment_base(gdtr.base_address, __read_ds()));
__vmx_vmwrite(GUEST_SS_BASE, get_segment_base(gdtr.base_address, __read_ss()));
__vmx_vmwrite(GUEST_ES_BASE, get_segment_base(gdtr.base_address, __read_es()));
__vmx_vmwrite(GUEST_CS_ACCESS_RIGHTS, read_segment_access_rights(__read_cs()));
__vmx_vmwrite(GUEST_SS_ACCESS_RIGHTS, read_segment_access_rights(__read_ss()));
__vmx_vmwrite(GUEST_DS_ACCESS_RIGHTS, read_segment_access_rights(__read_ds()));
__vmx_vmwrite(GUEST_ES_ACCESS_RIGHTS, read_segment_access_rights(__read_es()));
__vmx_vmwrite(GUEST_FS_ACCESS_RIGHTS, read_segment_access_rights(__read_fs()));
__vmx_vmwrite(GUEST_GS_ACCESS_RIGHTS, read_segment_access_rights(__read_gs()));
__vmx_vmwrite(GUEST_LDTR_ACCESS_RIGHTS, read_segment_access_rights(__read_ldtr()));
__vmx_vmwrite(GUEST_TR_ACCESS_RIGHTS, read_segment_access_rights(__read_tr()));
__vmx_vmwrite(GUEST_LDTR_BASE, get_segment_base(gdtr.base_address, __read_ldtr()));
__vmx_vmwrite(GUEST_TR_BASE, get_segment_base(gdtr.base_address, __read_tr()));
// Initialize VMCS Host State Area.
__vmx_vmwrite(HOST_CR0, __readcr0()); // Added by me
__vmx_vmwrite(HOST_CR3, __readcr3()); // Added by me
__vmx_vmwrite(HOST_CR4, __readcr4()); // Added by me
// Fields RPL and TI in host selector fields must be cleared.
unsigned short host_selector_mask = 7;
__vmx_vmwrite(HOST_CS_SELECTOR, __read_cs() & ~host_selector_mask);
__vmx_vmwrite(HOST_SS_SELECTOR, __read_ss() & ~host_selector_mask);
__vmx_vmwrite(HOST_DS_SELECTOR, __read_ds() & ~host_selector_mask);
__vmx_vmwrite(HOST_ES_SELECTOR, __read_es() & ~host_selector_mask);
__vmx_vmwrite(HOST_FS_SELECTOR, __read_fs() & ~host_selector_mask);
__vmx_vmwrite(HOST_GS_SELECTOR, __read_gs() & ~host_selector_mask);
__vmx_vmwrite(HOST_TR_SELECTOR, __read_tr() & ~host_selector_mask);
__vmx_vmwrite(HOST_TR_BASE, get_segment_base(gdtr.base_address, __read_tr()));
__vmx_vmwrite(HOST_GDTR_BASE, gdtr.base_address);
__vmx_vmwrite(HOST_IDTR_BASE, idtr.base_address);
unsigned __int64 vmm_stack = (unsigned __int64)vcpu->vmm_context->stack + VMM_STACK_SIZE;
if (__vmx_vmwrite(HOST_RSP, vmm_stack) ||
__vmx_vmwrite(HOST_RIP, vmm_entrypoint)
) {
log_error("Failed to set host_rsp, host_rip. (__vmx_vmwrite failed).\n");
log_exit("init_vmcs()\n");
return -1;
}
log_exit("init_vmcs()\n");
return 0;
}
void init_logical_processor(struct __vmm_context_t *vmm_context, void *guest_rsp)
{
log_entry("init_logical_processor()\n");
unsigned long cur_processor_number = KeGetCurrentProcessorNumber();
struct __vcpu_t* vcpu = vmm_context->vcpu_table[cur_processor_number];
log_debug("vcpu: %llx, guest_rsp: %llx\n", cur_processor_number, guest_rsp);
vcpu->guest_rsp = guest_rsp;
vcpu->guest_rip = (void*) guest_entry_stub;
adjust_control_registers();
if (enable_vmx_operation() != 0) {
log_error("Failed to enable_vmx_operation.\n");
goto _end;
}
if (!vm_has_cpuid_support()) {
log_error("VMX operation is not supported by the processor.\n");
goto _end;
}
log_success("VMX operation is supported by the processor.\n");
if (init_vmxon(vcpu)) {
log_error("Failed to initialize vmxon region.\n");
goto _end;
}
log_success("Initialized vmxon region.\n");
unsigned char vmxon_res = __vmx_on(&vcpu->vmxon_physical);
if (vmxon_res != 0) {
log_error("Failed to put vcpu into VMX operation. Error code: %d\n", vmxon_res);
goto _end;
}
log_success("vmx_on succeeded.\n");
if (init_vmcs(vcpu)) {
log_error("Failed to initialize vmcs.\n");
goto _end;
}
log_success("Initialized vmcs.\n");
unsigned char vmlaunch_res = vmxlaunch(); // just a wrapper over __vmx_vmlaunch
if (vmlaunch_res != 0) {
goto _end;
}
_end:
log_exit("init_logical_processor()\n");
}
vmm_entrypoint proc
int 3 ; addded by me
vmm_entrypoint endp
guest_entry_stub proc
mov rax, 1337h
hlt
guest_entry_stub endp
Update
I've read again the Intel manual section regarding VM-entry checks and found out that my init_vmcs function wasn't setting HOST_FS_BASE, HOST_GS_BASE. After adding these fields it finally worked and trapped inside vmm_entrypoint.
However I would love to hear some solution on how to debug the unexpected shutdowns.

buildroot uboot saveenv to emmc fat partition

I'm attempting to save the uboot environment to the FAT partition of an mmc device on a CM3 rpi module. The OS has been built in buildroot I can printenv and this shows the inbuilt env in the binary. The saveenv command is recognised, firstly states it's saving to fat and the filename is uboot-env.bin. The file exists and is found but the function bcm2835_transfer_block_pio seems to write nothing and repeatedly spits out fsm 1, hsts 000001. The mmc is selected as dev0 partition1 (0:1) in buildroot. Anyone come across this error and know how to fix it?
Source for mmc driver:
static int bcm2835_transfer_block_pio(struct bcm2835_host *host, bool is_read)
{
struct mmc_data *data = host->data;
size_t blksize = data->blocksize;
int copy_words;
u32 hsts = 0;
u32 *buf;
if (blksize % sizeof(u32))
return -EINVAL;
buf = is_read ? (u32 *)data->dest : (u32 *)data->src;
if (is_read)
data->dest += blksize;
else
data->src += blksize;
copy_words = blksize / sizeof(u32);
/*
* Copy all contents from/to the FIFO as far as it reaches,
* then wait for it to fill/empty again and rewind.
*/
while (copy_words) {
int burst_words, words;
u32 edm;
burst_words = min(SDDATA_FIFO_PIO_BURST, copy_words);
edm = readl(host->ioaddr + SDEDM);
if (is_read)
words = edm_fifo_fill(edm);
else
words = SDDATA_FIFO_WORDS - edm_fifo_fill(edm);
if (words < burst_words) {
int fsm_state = (edm & SDEDM_FSM_MASK);
if ((is_read &&
(fsm_state != SDEDM_FSM_READDATA &&
fsm_state != SDEDM_FSM_READWAIT &&
fsm_state != SDEDM_FSM_READCRC)) ||
(!is_read &&
(fsm_state != SDEDM_FSM_WRITEDATA &&
fsm_state != SDEDM_FSM_WRITESTART1 &&
fsm_state != SDEDM_FSM_WRITESTART2))) {
hsts = readl(host->ioaddr + SDHSTS);
printf("fsm %x, hsts %08x\n", fsm_state, hsts);
if (hsts & SDHSTS_ERROR_MASK)
break;
}
continue;
} else if (words > copy_words) {
words = copy_words;
}
copy_words -= words;
/* Copy current chunk to/from the FIFO */
while (words) {
if (is_read)
*(buf++) = readl(host->ioaddr + SDDATA);
else
writel(*(buf++), host->ioaddr + SDDATA);
words--;
}
}
return 0;
}

How to read a array value from the opcua server by client

I have been trying to do a simple OPC UA client server application using the open62541 stack. I can access the value from the open62541 implemented server. But i need to know, how a array value from the server can be interpreted/retrieved by the open62541 client?
Ex:
This is how i do for single value-
UA_Client_readValueAttribute(client, UA_NODEID_STRING(1, "value"), &value);
if(status == UA_STATUSCODE_GOOD &&
UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_INT32])) {
printf("value is: %i\n", *(UA_Int32*)value.data);
}
Here is an example how to read the namespace array.
It works in the same way as any other array value:
UA_ReadRequest request;
UA_ReadRequest_init(&request);
UA_ReadValueId id;
UA_ReadValueId_init(&id);
id.attributeId = UA_ATTRIBUTEID_VALUE;
id.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY);
request.nodesToRead = &id;
request.nodesToReadSize = 1;
UA_ReadResponse response = UA_Client_Service_read(client, request);
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
retval = response.responseHeader.serviceResult;
else if(response.resultsSize != 1 || !response.results[0].hasValue)
retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING])
retval = UA_STATUSCODE_BADTYPEMISMATCH;
if(retval != UA_STATUSCODE_GOOD) {
UA_ReadResponse_deleteMembers(&response);
return retval;
}
retval = UA_STATUSCODE_BADNOTFOUND;
UA_String *ns = (UA_String *)response.results[0].value.data;
for(size_t i = 0; i < response.results[0].value.arrayLength; ++i){
printf("The NS is %*.s", (int)ns[i].length, ns[i].data);
}
UA_ReadResponse_deleteMembers(&response);
The important thing is that response.results[0].value.data holds the array, and response.results[0].value.arrayLength the length of the array itself.

how to work CORRECTLY with SSL_read() and select()?

I try to make a C++ TLS client with OpenSSL which use non-blocking socket on Windows.
I want to work with SSL_read()/SSL_write() and select() functions but I don't find the algorithme which work well and the net not provide good and simple exemple. There is allready a timeout return by select() after the last block of data recved.
I don't understand OpenSSL api, SSL_pending() return already 0 and select a time out??
Select cause a criticale delay at last bloc of data.
My algorithme for recv_buffer() is this:
I have function which check if a socket is readable or writeable (work well):
int CSocket::socket_RWable(int rw_flag, const int time_out)
{
fd_set rwfs;
int error = 0;
struct timeval timeout;
try
{
memset(&timeout, 0, sizeof(struct timeval));
timeout.tv_sec = time_out;
while( 1 ) // boucle de surveillance
{
FD_ZERO(&rwfs);
FD_SET(m_socket, &rwfs);
// surveiller la socket en lecture ou ecriture
if(rw_flag == R_MODE)
error = select(m_socket+1, &rwfs, NULL, NULL, &timeout);
else if(rw_flag == W_MODE)
error = select(m_socket+1, NULL, &rwfs, NULL, &timeout);
if(error < 0) // echec de select
throw 1;
else if(error == 0) // fin du time out
throw 2;
// Une opération d' entree/sortie sur la socket est disponible
if(FD_ISSET(m_socket, &rwfs) != 0)
{
FD_CLR(m_socket, &rwfs );
return 0;
}
}
}
catch(int ret)
{
FD_CLR(m_socket, &rwfs );
if(ret == 1) throw CErreur("[-] CSocket : select : ", CWinUtil::Win_sys_error(NET_ERROR));
else if(ret == 2) return -1;
}
return -1;
}
UPDATE:
and this function recve the data into a buffer and cause a time out after the las block of data:
int CTLSClient::recv_buffer(char *buffer, const int buffer_size, const int time_out)
{
int selectErr = 0;
int sslErr = 0;
int retRead = 0;
int recvData = 0;
selectErr = m_socket->socket_RWable(R_MODE, time_out);
while(selectErr == 0)
{
retRead = SSL_read(m_ssl, buffer+recvData, buffer_size-recvData);
sslErr = SSL_get_error(m_ssl, retRead);
if(sslErr == SSL_ERROR_NONE)
{
cout<<"DEBUG 2 SSL_ERROR_NONE recv data="<<retRead<<endl;
recvData += retRead;
}
else if(sslErr == SSL_ERROR_WANT_READ)
{
cout<<"DEBUG 3 SSL_ERROR_WANT_READ select()"<<endl;
selectErr = m_socket->socket_RWable(R_MODE, time_out);
}
else if(sslErr == SSL_ERROR_WANT_WRITE)
{
cout<<"DEBUG 4 SSL_ERROR_WANT_WRITE select()"<<endl;
selectErr = m_socket->socket_RWable(W_MODE, time_out);
}
else if(sslErr == SSL_ERROR_ZERO_RETURN)
{
return -1;
}
else
return -1;
}
return recvData;
}
this is a output with connection to a POP3 server:
DEBUG 2 SSL_ERROR_NONE recv data=35
DEBUG 3 SSL_ERROR_WANT_READ select()
[S]+OK BLU0-POP617 POP3 server ready
total data -> 35
DEBUG 2 SSL_ERROR_NONE recv data=23
DEBUG 3 SSL_ERROR_WANT_READ select()
[S]+OK password required
total data -> 23
DEBUG 2 SSL_ERROR_NONE recv data=30
DEBUG 3 SSL_ERROR_WANT_READ select()
[S]+OK mailbox has 180 messages
total data -> 30
DEBUG 2 SSL_ERROR_NONE recv data=18
DEBUG 3 SSL_ERROR_WANT_READ select()
[S]+OK 180 12374432
total data -> 18
DEBUG 2 SSL_ERROR_NONE recv data=13
DEBUG 3 SSL_ERROR_WANT_READ select()
[S]+OK 1 23899
total data -> 13
DEBUG 2 SSL_ERROR_NONE recv data=5
DEBUG 3 SSL_ERROR_WANT_READ select()
DEBUG 2 SSL_ERROR_NONE recv data=8192
DEBUG 2 SSL_ERROR_NONE recv data=8192
DEBUG 3 SSL_ERROR_WANT_READ select()
DEBUG 3 SSL_ERROR_WANT_READ select()
DEBUG 2 SSL_ERROR_NONE recv data=7521
DEBUG 3 SSL_ERROR_WANT_READ select()
[S]total data -> 23910
Assuming you have already read the headers, for some reason SSL_read() hangs after reading the email message and returns SSL_WANT_READ. I solved this problem by looping through the message body one line at a time until I find the ending period. When I reach this line, I call SSL_pending(). Although there is no pending data, it prevents an endless loop where SSL_read() returns SSL_WANT_READ. However, I am looking for a better solution.
for(;;)
{
char *line = ReadLine(ssl, buf, sizeof(buf));
if(line != NULL)
{
if(*line == '.')
{
int pending = SSL_pending(ssl);
if(pending > 0)
{
int read = SSL_read(ssl,buf,pending);
}
}
}
}
This function reads one character at a time until it reaches an end of line character and returns the line.
char *ReadLine(SSL *ssl, char *buf, int size)
{
int i = 0;
char *ptr = NULL;
for (ptr = str; size > 1; size--, ptr++)
{
i = SSL_read(out, ptr, 1);
switch (SSL_get_error(out, i)){
case SSL_ERROR_NONE:
break;
case SSL_ERROR_ZERO_RETURN:
break;
case SSL_ERROR_WANT_READ:
break;
case SSL_ERROR_WANT_WRITE:
break;
default:
TRACE("SSL problem\r\n");
}
if (*ptr == '\n')
break;
if (*ptr == '\r'){
ptr--;
}
}
*ptr = '\0';
return(str);
}

libusb data transfer

Hii I have to make a code to read data from usb drive which can be pendrive and later a data acquisition card . i have written this much of code which detects all usb connection n print their info. Altough i don't know how to proceed further . I m also confused as to reading data from say pendrive means as in opening some files or what? Please also tell how to find endpoint of device currently i'm jsut using hit n trial to find it .
PLEASE help me out .I have read whole documentation on synchronous and asynchronous I/O.
enter code here
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libusb-1.0/libusb.h>
//=========================================================================
// This program detects usb and print out their details
//=========================================================================
int main (int argc, char *argv)
{
libusb_device **devList = NULL;
libusb_device *devPtr = NULL;
libusb_device_handle *devHandle = NULL;
libusb_context *ctx = NULL; //a libusb session
struct libusb_device_descriptor devDesc;
unsigned char strDesc[256];
ssize_t numUsbDevs = 0; // pre-initialized scalars
ssize_t idx = 0;
int retVal = 0;
//========================================================================
// test out the libusb functions
//========================================================================
printf ("*************************\n USB Detection Program:\n*************************\n");
retVal = libusb_init (&ctx);
if(retVal < 0) {
printf ("%d",retVal," Init Error "); //there was an error
return 1;
}
//========================================================================
// Get the list of USB devices visible to the system.
//========================================================================
numUsbDevs = libusb_get_device_list (ctx, &devList);
//========================================================================
// Loop through the list, looking for the device
//========================================================================
while (idx < numUsbDevs)
{
printf ("\n\n[%d]\n", idx+1);
//=====================================================================
// Get next device pointer out of the list, use it to open the device.
//=====================================================================
devPtr = devList[idx];
retVal = libusb_open (devPtr, &devHandle);
if (retVal != LIBUSB_SUCCESS)
break;
//=====================================================================
// Get the device descriptor for this device.
//=====================================================================
retVal = libusb_get_device_descriptor (devPtr, &devDesc);
if (retVal != LIBUSB_SUCCESS)
break;
//=====================================================================
// Get the string associated with iManufacturer index.
//=====================================================================
printf ("iManufacturer = %d", devDesc.iManufacturer);
if (devDesc.iManufacturer > 0)
{
retVal = libusb_get_string_descriptor_ascii
(devHandle, devDesc.iManufacturer, strDesc, 256);
if (retVal < 0)
break;
printf (" string = %s", strDesc);
}
//========================================================================
// Get string associated with iProduct index.
//========================================================================
printf (" \niProduct = %d", devDesc.iProduct);
if (devDesc.iProduct > 0)
{
retVal = libusb_get_string_descriptor_ascii
(devHandle, devDesc.iProduct, strDesc, 256);
if (retVal < 0)
break;
printf (" string = %s", strDesc);
}
//==================================================================
// Get string associated with iSerialNumber index.
//==================================================================
printf (" \niSerialNumber = %d", devDesc.iSerialNumber);
if (devDesc.iSerialNumber > 0)
{
retVal = libusb_get_string_descriptor_ascii
(devHandle, devDesc.iSerialNumber, strDesc, 256);
if (retVal < 0)
break;
printf (" string = %s", strDesc);
}
//==================================================================
// Print product id and Vendor id
//==================================================================
printf (" \nProductid = %d", devDesc.idProduct);
printf (" \nVendorid = %d", devDesc.idVendor);
//========================================================================
// Close and try next one.
//========================================================================
libusb_close (devHandle);
devHandle = NULL;
idx++;
//========================================================================
// Selection of device by user
//========================================================================
if(idx==numUsbDevs)
{ printf("\n\nselect the device : ");
scanf("%d",&idx);
if(idx > numUsbDevs)
{printf("Invalid input, Quitting.............");
break; }
devPtr = devList[idx-1];
retVal = libusb_open (devPtr, &devHandle);
if (retVal != LIBUSB_SUCCESS)
break;
retVal = libusb_get_device_descriptor (devPtr, &devDesc);
if (retVal != LIBUSB_SUCCESS)
break;
printf (" \nProductid = %d", devDesc.idProduct);
printf (" \nVendorid = %d", devDesc.idVendor);
unsigned char data[4] ; //data to read
//data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values
int r; //for return values
r = libusb_claim_interface(devHandle, 1); //claim interface 0 (the first) of device
if(r < 0) {
printf("\nCannot Claim Interface");
return 1;
}
printf("\nClaimed Interface");
int actual_length; //used to find out how many bytes were written
r = libusb_bulk_transfer(devHandle,LIBUSB_ENDPOINT_IN, data, 2, &actual_length, 0);
if (r == 0 && actual_length == sizeof(data)) {
// results of the transaction can now be found in the data buffer
// parse them here and report button press
}
else {
error();
}
r = libusb_release_interface(devHandle, 1); //release the claimed interface
if(r!=0) {
printf("\nCannot Release Interface");
return 1;
}
printf("\nReleased Interface");
idx=numUsbDevs +2;
}
} // end of while loop
if (devHandle != NULL)
{
//========================================================================
// Close device if left open due to break out of loop on error.
//========================================================================
libusb_close (devHandle);
}
libusb_exit (ctx); //close the session
printf ("\n*************************\n Done\n*************************\n");
return 0;
}
//==========================================
// EOF
//====================

Resources