#include <ntddk.h>
#include <usbdi.h>
#include <wdf.h>
#include <wdfio.h>
#include <wdfusb.h>
#include <ntstrsafe.h>
#include <wdm.h>
#include <ntddser.h>
#include "public.h"
void usb_device_interrupt(WDFUSBPIPE pipe, WDFMEMORY buffer, size_t len, WDFCONTEXT ctx)
{
/*devargs *args;*/
UNREFERENCED_PARAMETER(pipe);
UNREFERENCED_PARAMETER(buffer);
UNREFERENCED_PARAMETER(len);
UNREFERENCED_PARAMETER(ctx);
KdPrint((DRIVER_NAME "-->USB interrupt into\n"));
/*args = (devargs *)ctx;*/
/*KdPrint(("usb_device_interrupt: %x @@ %i\n", buffer, len));*/
KdPrint((DRIVER_NAME "<--USB interrupt into\n"));
return ;
}
void usb_read(IN WDFQUEUE queue, IN WDFREQUEST req, IN size_t len)
{
devargs *args;
UNREFERENCED_PARAMETER(queue);
UNREFERENCED_PARAMETER(req);
UNREFERENCED_PARAMETER(len);
KdPrint((DRIVER_NAME "-->usb_read into\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
WdfWaitLockAcquire(args->lock, NULL);
args->status.AmountInOutQueue = 0;
WdfWaitLockRelease(args->lock);
WdfRequestCompleteWithInformation(req, STATUS_SUCCESS, 0);
KdPrint((DRIVER_NAME "<--usb_read into\n"));
return ;
}
void usb_write_complete(IN WDFREQUEST req, IN WDFIOTARGET target, IN PWDF_REQUEST_COMPLETION_PARAMS param, IN WDFCONTEXT ctx)
{
PWDF_USB_REQUEST_COMPLETION_PARAMS comp_params;
devargs *args;
UNREFERENCED_PARAMETER(target);
UNREFERENCED_PARAMETER(ctx);
KdPrint((DRIVER_NAME "-->usb_write_complete into\n"));
args = getdevargs(WdfIoQueueGetDevice(WdfRequestGetIoQueue(req)));
comp_params = param->Parameters.Usb.Completion;
if(NT_SUCCESS(param->IoStatus.Status))
{
KdPrint((DRIVER_NAME " Completed the write request with %d bytes\n", comp_params->Parameters.PipeWrite.Length));
}
else
{
KdPrint((DRIVER_NAME " Failed the read request with status 0x%08x\n", param->IoStatus.Status));
}
WdfWaitLockAcquire(args->lock, NULL);
args->status.AmountInInQueue = comp_params->Parameters.PipeWrite.Length;
WdfWaitLockRelease(args->lock);
WdfRequestCompleteWithInformation(req, param->IoStatus.Status, comp_params->Parameters.PipeWrite.Length);
KdPrint((DRIVER_NAME "<--usb_write_complete into\n"));
return ;
}
void usb_write(IN WDFQUEUE queue, IN WDFREQUEST req, IN size_t len)
{
NTSTATUS stat = STATUS_SUCCESS;
WDFMEMORY buf;
devargs *args;
UNREFERENCED_PARAMETER(len);
KdPrint((DRIVER_NAME "-->usb_write into\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveInputMemory(req, &buf);
if (!NT_SUCCESS(stat))
{
KdPrint((DRIVER_NAME " write failed\n"));
WdfRequestComplete(req, stat);
return ;
}
stat = WdfUsbTargetPipeFormatRequestForWrite(args->usb_bulk_out, req, buf, NULL);
if (!NT_SUCCESS(stat))
{
KdPrint((DRIVER_NAME " write failed2\n"));
WdfRequestComplete(req, stat);
return ;
}
WdfRequestSetCompletionRoutine(req, usb_write_complete, args->usb_bulk_out);
if (WdfRequestSend(req, WdfUsbTargetPipeGetIoTarget(args->usb_bulk_out), NULL) == FALSE)
{
KdPrint((DRIVER_NAME " write failed3\n"));
stat = WdfRequestGetStatus(req);
WdfRequestComplete(req, stat);
return;
}
KdPrint((DRIVER_NAME "<--usb_write into\n"));
return ;
}
const char *getioctlname(IN ULONG ioctcode)
{
switch (ioctcode)
{
case IOCTL_SERIAL_SET_BAUD_RATE:
return "IOCTL_SERIAL_SET_BAUD_RATE";
case IOCTL_SERIAL_SET_QUEUE_SIZE:
return "IOCTL_SERIAL_SET_QUEUE_SIZE";
case IOCTL_SERIAL_SET_LINE_CONTROL:
return "IOCTL_SERIAL_SET_LINE_CONTROL";
case IOCTL_SERIAL_SET_BREAK_ON:
return "IOCTL_SERIAL_SET_BREAK_ON";
case IOCTL_SERIAL_SET_BREAK_OFF:
return "IOCTL_SERIAL_SET_BREAK_OFF";
case IOCTL_SERIAL_IMMEDIATE_CHAR:
return "IOCTL_SERIAL_IMMEDIATE_CHAR";
case IOCTL_SERIAL_SET_TIMEOUTS:
return "IOCTL_SERIAL_SET_TIMEOUTS";
case IOCTL_SERIAL_GET_TIMEOUTS:
return "IOCTL_SERIAL_GET_TIMEOUTS";
case IOCTL_SERIAL_SET_DTR:
return "IOCTL_SERIAL_SET_DTR";
case IOCTL_SERIAL_CLR_DTR:
return "IOCTL_SERIAL_CLR_DTR";
case IOCTL_SERIAL_RESET_DEVICE:
return "IOCTL_SERIAL_RESET_DEVICE";
case IOCTL_SERIAL_SET_RTS:
return "IOCTL_SERIAL_SET_RTS";
case IOCTL_SERIAL_CLR_RTS:
return "IOCTL_SERIAL_CLR_RTS";
case IOCTL_SERIAL_SET_XOFF:
return "IOCTL_SERIAL_SET_XOFF";
case IOCTL_SERIAL_SET_XON:
return "IOCTL_SERIAL_SET_XON";
case IOCTL_SERIAL_GET_WAIT_MASK:
return "IOCTL_SERIAL_GET_WAIT_MASK";
case IOCTL_SERIAL_SET_WAIT_MASK:
return "IOCTL_SERIAL_SET_WAIT_MASK";
case IOCTL_SERIAL_WAIT_ON_MASK:
return "IOCTL_SERIAL_WAIT_ON_MASK";
case IOCTL_SERIAL_PURGE:
return "IOCTL_SERIAL_PURGE";
case IOCTL_SERIAL_GET_BAUD_RATE:
return "IOCTL_SERIAL_GET_BAUD_RATE";
case IOCTL_SERIAL_GET_LINE_CONTROL:
return "IOCTL_SERIAL_GET_LINE_CONTROL";
case IOCTL_SERIAL_GET_CHARS:
return "IOCTL_SERIAL_GET_CHARS";
case IOCTL_SERIAL_SET_CHARS:
return "IOCTL_SERIAL_SET_CHARS";
case IOCTL_SERIAL_GET_HANDFLOW:
return "IOCTL_SERIAL_GET_HANDFLOW";
case IOCTL_SERIAL_SET_HANDFLOW:
return "IOCTL_SERIAL_SET_HANDFLOW";
case IOCTL_SERIAL_GET_MODEMSTATUS:
return "IOCTL_SERIAL_GET_MODEMSTATUS";
case IOCTL_SERIAL_GET_COMMSTATUS:
return "IOCTL_SERIAL_GET_COMMSTATUS";
case IOCTL_SERIAL_XOFF_COUNTER:
return "IOCTL_SERIAL_XOFF_COUNTER";
case IOCTL_SERIAL_GET_PROPERTIES:
return "IOCTL_SERIAL_GET_PROPERTIES";
case IOCTL_SERIAL_GET_DTRRTS:
return "IOCTL_SERIAL_GET_DTRRTS";
default:
return "Unknow";
}
}
void usb_ioctl(IN WDFQUEUE queue, IN WDFREQUEST req, IN size_t outbuflen, IN size_t inbuflen, IN ULONG ioctcode)
{
NTSTATUS stat;
void *buffer;
size_t len;
devargs *args;
ULONG Mask;
UNREFERENCED_PARAMETER(queue);
UNREFERENCED_PARAMETER(outbuflen);
UNREFERENCED_PARAMETER(inbuflen);
switch (ioctcode)
{
case IOCTL_SERIAL_GET_BAUD_RATE:
KdPrint((" IOCTL_SERIAL_GET_BAUD_RATE\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveOutputBuffer(req, sizeof(ULONG), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
*((ULONG*)buffer) = args->baudrate;
WdfRequestCompleteWithInformation(req, stat, sizeof(ULONG));
break;
case IOCTL_SERIAL_GET_LINE_CONTROL:
KdPrint((" IOCTL_SERIAL_GET_LINE_CONTROL\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveOutputBuffer(req, sizeof(SERIAL_LINE_CONTROL), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
((SERIAL_LINE_CONTROL*)buffer)->StopBits = args->StopBits;
((SERIAL_LINE_CONTROL*)buffer)->Parity = args->Parity;
((SERIAL_LINE_CONTROL*)buffer)->WordLength = args->WordLength;
WdfRequestCompleteWithInformation(req, stat, sizeof(SERIAL_LINE_CONTROL));
break;
case IOCTL_SERIAL_SET_QUEUE_SIZE:
KdPrint((" IOCTL_SERIAL_SET_QUEUE_SIZE\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveInputBuffer(req, sizeof(SERIAL_QUEUE_SIZE), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
WdfRequestComplete(req, STATUS_SUCCESS);
break;
case IOCTL_SERIAL_PURGE:
KdPrint((" IOCTL_SERIAL_PURGE\n"));
stat = WdfRequestRetrieveInputBuffer(req, sizeof(ULONG), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
Mask = *((ULONG *)(buffer));
if ((!Mask) || (Mask & (~(SERIAL_PURGE_TXABORT |
SERIAL_PURGE_RXABORT |
SERIAL_PURGE_TXCLEAR |
SERIAL_PURGE_RXCLEAR))))
{
WdfRequestComplete(req, STATUS_INVALID_PARAMETER);
break;
}
WdfRequestComplete(req, STATUS_SUCCESS);
break;
case IOCTL_SERIAL_GET_COMMSTATUS:
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveOutputBuffer(req, sizeof(SERIAL_STATUS), &buffer, &len);
KdPrint((" IOCTL_SERIAL_GET_COMMSTATUS : \n"/*, len*/));
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
WdfWaitLockAcquire(args->lock, NULL);
((PSERIAL_STATUS)buffer)->AmountInInQueue = args->status.AmountInInQueue;
((PSERIAL_STATUS)buffer)->AmountInOutQueue = args->status.AmountInOutQueue;
((PSERIAL_STATUS)buffer)->EofReceived = FALSE;
((PSERIAL_STATUS)buffer)->Errors = 0;
((PSERIAL_STATUS)buffer)->HoldReasons = 0;
((PSERIAL_STATUS)buffer)->WaitForImmediate = FALSE;
buffer = &(args->status);
WdfRequestCompleteWithInformation(req, stat, sizeof(SERIAL_STATUS));
args->status.AmountInInQueue = 0;
args->status.AmountInOutQueue = 0;
/*WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);*/
WdfWaitLockRelease(args->lock);
break;
case IOCTL_SERIAL_SET_TIMEOUTS:
KdPrint((" IOCTL_SERIAL_SET_TIMEOUTS\n"));
WdfRequestComplete(req, STATUS_SUCCESS);
break;
case IOCTL_SERIAL_GET_CHARS:
KdPrint((" IOCTL_SERIAL_GET_CHARS\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveOutputBuffer(req, sizeof(SERIAL_CHARS), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
((SERIAL_CHARS*)buffer)->XonChar = args->chars.XonChar;
((SERIAL_CHARS*)buffer)->XoffChar = args->chars.XoffChar;
WdfRequestCompleteWithInformation(req, stat, sizeof(SERIAL_CHARS));
break ;
case IOCTL_SERIAL_GET_HANDFLOW:
KdPrint((" IOCTL_SERIAL_GET_HANDFLOW\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveOutputBuffer(req, sizeof(SERIAL_HANDFLOW), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
((SERIAL_HANDFLOW*)buffer)->ControlHandShake = args->hf.ControlHandShake;
((SERIAL_HANDFLOW*)buffer)->FlowReplace = args->hf.FlowReplace;
((SERIAL_HANDFLOW*)buffer)->XoffLimit = args->hf.XoffLimit;
((SERIAL_HANDFLOW*)buffer)->XonLimit = args->hf.XonLimit;
WdfRequestCompleteWithInformation(req, stat, sizeof(SERIAL_HANDFLOW));
break ;
case IOCTL_SERIAL_SET_BAUD_RATE:
KdPrint((" IOCTL_SERIAL_SET_BAUD_RATE\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveInputBuffer(req, sizeof(ULONG), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
args->baudrate = *((ULONG*)buffer);
WdfRequestComplete(req, STATUS_SUCCESS);
break;
case IOCTL_SERIAL_SET_LINE_CONTROL:
KdPrint((" IOCTL_SERIAL_SET_LINE_CONTROL\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveInputBuffer(req, sizeof(SERIAL_LINE_CONTROL), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
args->StopBits = ((SERIAL_LINE_CONTROL*)buffer)->StopBits;
args->Parity = ((SERIAL_LINE_CONTROL*)buffer)->Parity;
args->WordLength = ((SERIAL_LINE_CONTROL*)buffer)->WordLength;;
WdfRequestComplete(req, STATUS_SUCCESS);
break;
case IOCTL_SERIAL_CLR_DTR:
case IOCTL_SERIAL_SET_DTR:
KdPrint((" DTR\n"));
WdfRequestComplete(req, STATUS_SUCCESS);
break;
case IOCTL_SERIAL_CLR_RTS:
case IOCTL_SERIAL_SET_RTS:
KdPrint((" RTS\n"));
WdfRequestComplete(req, STATUS_SUCCESS);
break;
case IOCTL_SERIAL_SET_CHARS:
KdPrint((" SET_CHARS\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveInputBuffer(req, sizeof(SERIAL_CHARS), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
args->chars.XonChar = ((SERIAL_CHARS*)buffer)->XonChar;
args->chars.XoffChar = ((SERIAL_CHARS*)buffer)->XoffChar;
args->chars.EofChar = ((SERIAL_CHARS*)buffer)->EofChar;
args->chars.ErrorChar = ((SERIAL_CHARS*)buffer)->ErrorChar;
args->chars.BreakChar = ((SERIAL_CHARS*)buffer)->BreakChar;
args->chars.EventChar = ((SERIAL_CHARS*)buffer)->EventChar;
WdfRequestComplete(req, STATUS_SUCCESS);
break ;
case IOCTL_SERIAL_SET_HANDFLOW:
KdPrint((" SET_HANFLOW\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveInputBuffer(req, sizeof(SERIAL_HANDFLOW), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
args->hf.ControlHandShake = ((SERIAL_HANDFLOW*)buffer)->ControlHandShake;
args->hf.FlowReplace = ((SERIAL_HANDFLOW*)buffer)->FlowReplace;
args->hf.XoffLimit = ((SERIAL_HANDFLOW*)buffer)->XoffLimit;
args->hf.XonLimit = ((SERIAL_HANDFLOW*)buffer)->XonLimit;
WdfRequestCompleteWithInformation(req, stat, sizeof(SERIAL_HANDFLOW));
break ;
case IOCTL_SERIAL_GET_WAIT_MASK:
KdPrint((" GET_WAIT_MASK\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveOutputBuffer(req, sizeof(ULONG), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
*((ULONG*)buffer) = 0;
WdfRequestCompleteWithInformation(req, stat, sizeof(ULONG));
break;
case IOCTL_SERIAL_SET_WAIT_MASK:
KdPrint((" SET_WAIT_MASK\n"));
args = getdevargs(WdfIoQueueGetDevice(queue));
stat = WdfRequestRetrieveInputBuffer(req, sizeof(ULONG), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
*((ULONG*)buffer) = 0;
WdfRequestCompleteWithInformation(req, stat, sizeof(ULONG));
break ;
case IOCTL_SERIAL_WAIT_ON_MASK:
stat = WdfRequestRetrieveOutputBuffer(req, sizeof(ULONG), &buffer, &len);
if(!NT_SUCCESS(stat))
{
KdPrint((" Get memory error\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
*((ULONG*)buffer) = 0;
WdfRequestCompleteWithInformation(req, stat, sizeof(ULONG));
break ;
case IOCTL_SERIAL_SET_BREAK_ON:
case IOCTL_SERIAL_SET_BREAK_OFF:
case IOCTL_SERIAL_IMMEDIATE_CHAR:
case IOCTL_SERIAL_GET_TIMEOUTS:
case IOCTL_SERIAL_RESET_DEVICE:
case IOCTL_SERIAL_SET_XOFF:
case IOCTL_SERIAL_SET_XON:
case IOCTL_SERIAL_GET_MODEMSTATUS:
case IOCTL_SERIAL_XOFF_COUNTER:
case IOCTL_SERIAL_GET_PROPERTIES:
case IOCTL_SERIAL_GET_DTRRTS:
KdPrint((" %s not implem\n", getioctlname(ioctcode)));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
default:
KdPrint((DRIVER_NAME " Ioctl %i not implemented\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
break;
}
return ;
}
void usb_default(IN WDFQUEUE queue, IN WDFREQUEST req)
{
UNREFERENCED_PARAMETER(queue);
KdPrint((DRIVER_NAME "-->usb_default into\n"));
WdfRequestComplete(req, STATUS_NOT_IMPLEMENTED);
KdPrint((DRIVER_NAME "<--usb_default into\n"));
return ;
}