20#include <winpr/cast.h>
22#include <freerdp/config.h>
24#include <freerdp/freerdp.h>
25#include <freerdp/channels/log.h>
26#include <freerdp/server/rdpecam.h>
28#include "rdpecam-utils.h"
30#define TAG CHANNELS_TAG("rdpecam.server")
34 CAMERA_DEVICE_INITIAL,
36} eCameraDeviceChannelState;
40 CameraDeviceServerContext context;
53 eCameraDeviceChannelState state;
58static UINT device_server_initialize(CameraDeviceServerContext* context, BOOL externalThread)
60 UINT error = CHANNEL_RC_OK;
61 device_server* device = (device_server*)context;
67 WLog_WARN(TAG,
"Application error: Camera channel already initialized, "
68 "calling in this state is not possible!");
69 return ERROR_INVALID_STATE;
72 device->externalThread = externalThread;
77static UINT device_server_open_channel(device_server* device)
79 CameraDeviceServerContext* context = &device->context;
80 DWORD Error = ERROR_SUCCESS;
82 DWORD BytesReturned = 0;
83 PULONG pSessionId = NULL;
89 if (WTSQuerySessionInformationA(device->context.vcm, WTS_CURRENT_SESSION, WTSSessionId,
90 (LPSTR*)&pSessionId, &BytesReturned) == FALSE)
92 WLog_ERR(TAG,
"WTSQuerySessionInformationA failed!");
93 return ERROR_INTERNAL_ERROR;
96 device->SessionId = (DWORD)*pSessionId;
97 WTSFreeMemory(pSessionId);
98 hEvent = WTSVirtualChannelManagerGetEventHandle(device->context.vcm);
100 if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED)
102 Error = GetLastError();
103 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", Error);
107 device->device_channel = WTSVirtualChannelOpenEx(device->SessionId, context->virtualChannelName,
108 WTS_CHANNEL_OPTION_DYNAMIC);
109 if (!device->device_channel)
111 Error = GetLastError();
112 WLog_ERR(TAG,
"WTSVirtualChannelOpenEx failed with error %" PRIu32
"!", Error);
116 channelId = WTSChannelGetIdByHandle(device->device_channel);
118 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
121 WLog_ERR(TAG,
"context->ChannelIdAssigned failed!");
122 return ERROR_INTERNAL_ERROR;
128static UINT device_server_handle_success_response(CameraDeviceServerContext* context,
133 UINT error = CHANNEL_RC_OK;
135 WINPR_ASSERT(context);
136 WINPR_ASSERT(header);
138 pdu.Header = *header;
140 IFCALLRET(context->SuccessResponse, error, context, &pdu);
142 WLog_ERR(TAG,
"context->SuccessResponse failed with error %" PRIu32
"", error);
147static UINT device_server_recv_error_response(CameraDeviceServerContext* context,
wStream* s,
151 UINT error = CHANNEL_RC_OK;
153 WINPR_ASSERT(context);
154 WINPR_ASSERT(header);
156 pdu.Header = *header;
158 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
159 return ERROR_NO_DATA;
162 const UINT32 val = Stream_Get_UINT32(s);
163 if (!rdpecam_valid_CamErrorCode(val))
164 return ERROR_INVALID_DATA;
165 pdu.ErrorCode = (CAM_ERROR_CODE)val;
168 IFCALLRET(context->ErrorResponse, error, context, &pdu);
170 WLog_ERR(TAG,
"context->ErrorResponse failed with error %" PRIu32
"", error);
175static UINT device_server_recv_stream_list_response(CameraDeviceServerContext* context,
wStream* s,
179 UINT error = CHANNEL_RC_OK;
181 WINPR_ASSERT(context);
182 WINPR_ASSERT(header);
184 pdu.Header = *header;
186 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
187 return ERROR_NO_DATA;
189 pdu.N_Descriptions = 255;
190 const size_t len = Stream_GetRemainingLength(s) / 5;
192 pdu.N_Descriptions = (BYTE)len;
194 for (BYTE i = 0; i < pdu.N_Descriptions; ++i)
199 const UINT16 val = Stream_Get_UINT16(s);
200 if (!rdpecam_valid_CamStreamFrameSourceType(val))
201 return ERROR_INVALID_DATA;
202 StreamDescription->FrameSourceTypes = (CAM_STREAM_FRAME_SOURCE_TYPES)val;
205 const UINT8 val = Stream_Get_UINT8(s);
206 if (!rdpecam_valid_CamStreamCategory(val))
207 return ERROR_INVALID_DATA;
208 StreamDescription->StreamCategory = (CAM_STREAM_CATEGORY)val;
210 Stream_Read_UINT8(s, StreamDescription->Selected);
211 Stream_Read_UINT8(s, StreamDescription->CanBeShared);
214 IFCALLRET(context->StreamListResponse, error, context, &pdu);
216 WLog_ERR(TAG,
"context->StreamListResponse failed with error %" PRIu32
"", error);
221static UINT device_server_recv_media_type_list_response(CameraDeviceServerContext* context,
226 UINT error = CHANNEL_RC_OK;
228 WINPR_ASSERT(context);
229 WINPR_ASSERT(header);
231 pdu.Header = *header;
233 if (!Stream_CheckAndLogRequiredLength(TAG, s, 26))
234 return ERROR_NO_DATA;
236 pdu.N_Descriptions = Stream_GetRemainingLength(s) / 26;
239 if (!pdu.MediaTypeDescriptions)
241 WLog_ERR(TAG,
"Failed to allocate %zu CAM_MEDIA_TYPE_DESCRIPTION structs",
243 return ERROR_NOT_ENOUGH_MEMORY;
246 for (
size_t i = 0; i < pdu.N_Descriptions; ++i)
251 const UINT8 val = Stream_Get_UINT8(s);
252 if (!rdpecam_valid_CamMediaFormat(val))
254 free(pdu.MediaTypeDescriptions);
255 return ERROR_INVALID_DATA;
257 MediaTypeDescriptions->Format = (CAM_MEDIA_FORMAT)val;
259 Stream_Read_UINT32(s, MediaTypeDescriptions->Width);
260 Stream_Read_UINT32(s, MediaTypeDescriptions->Height);
261 Stream_Read_UINT32(s, MediaTypeDescriptions->FrameRateNumerator);
262 Stream_Read_UINT32(s, MediaTypeDescriptions->FrameRateDenominator);
263 Stream_Read_UINT32(s, MediaTypeDescriptions->PixelAspectRatioNumerator);
264 Stream_Read_UINT32(s, MediaTypeDescriptions->PixelAspectRatioDenominator);
266 const UINT8 val = Stream_Get_UINT8(s);
267 if (!rdpecam_valid_MediaTypeDescriptionFlags(val))
269 free(pdu.MediaTypeDescriptions);
270 return ERROR_INVALID_DATA;
272 MediaTypeDescriptions->Flags = (CAM_MEDIA_TYPE_DESCRIPTION_FLAGS)val;
276 IFCALLRET(context->MediaTypeListResponse, error, context, &pdu);
278 WLog_ERR(TAG,
"context->MediaTypeListResponse failed with error %" PRIu32
"", error);
280 free(pdu.MediaTypeDescriptions);
285static UINT device_server_recv_current_media_type_response(CameraDeviceServerContext* context,
290 UINT error = CHANNEL_RC_OK;
292 WINPR_ASSERT(context);
293 WINPR_ASSERT(header);
295 pdu.Header = *header;
297 if (!Stream_CheckAndLogRequiredLength(TAG, s, 26))
298 return ERROR_NO_DATA;
301 const UINT8 val = Stream_Get_UINT8(s);
302 if (!rdpecam_valid_CamMediaFormat(val))
303 return ERROR_INVALID_DATA;
304 pdu.MediaTypeDescription.Format = (CAM_MEDIA_FORMAT)val;
307 Stream_Read_UINT32(s, pdu.MediaTypeDescription.Width);
308 Stream_Read_UINT32(s, pdu.MediaTypeDescription.Height);
309 Stream_Read_UINT32(s, pdu.MediaTypeDescription.FrameRateNumerator);
310 Stream_Read_UINT32(s, pdu.MediaTypeDescription.FrameRateDenominator);
311 Stream_Read_UINT32(s, pdu.MediaTypeDescription.PixelAspectRatioNumerator);
312 Stream_Read_UINT32(s, pdu.MediaTypeDescription.PixelAspectRatioDenominator);
314 const UINT8 val = Stream_Get_UINT8(s);
315 if (!rdpecam_valid_MediaTypeDescriptionFlags(val))
316 return ERROR_INVALID_DATA;
317 pdu.MediaTypeDescription.Flags = (CAM_MEDIA_TYPE_DESCRIPTION_FLAGS)val;
320 IFCALLRET(context->CurrentMediaTypeResponse, error, context, &pdu);
322 WLog_ERR(TAG,
"context->CurrentMediaTypeResponse failed with error %" PRIu32
"", error);
327static UINT device_server_recv_sample_response(CameraDeviceServerContext* context,
wStream* s,
331 UINT error = CHANNEL_RC_OK;
333 WINPR_ASSERT(context);
334 WINPR_ASSERT(header);
336 pdu.Header = *header;
338 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
339 return ERROR_NO_DATA;
341 Stream_Read_UINT8(s, pdu.StreamIndex);
343 pdu.SampleSize = Stream_GetRemainingLength(s);
344 pdu.Sample = Stream_Pointer(s);
346 IFCALLRET(context->SampleResponse, error, context, &pdu);
348 WLog_ERR(TAG,
"context->SampleResponse failed with error %" PRIu32
"", error);
353static UINT device_server_recv_sample_error_response(CameraDeviceServerContext* context,
wStream* s,
357 UINT error = CHANNEL_RC_OK;
359 WINPR_ASSERT(context);
360 WINPR_ASSERT(header);
362 pdu.Header = *header;
364 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
365 return ERROR_NO_DATA;
367 Stream_Read_UINT8(s, pdu.StreamIndex);
369 const UINT32 val = Stream_Get_UINT32(s);
370 if (!rdpecam_valid_CamErrorCode(val))
371 return ERROR_INVALID_DATA;
372 pdu.ErrorCode = (CAM_ERROR_CODE)val;
375 IFCALLRET(context->SampleErrorResponse, error, context, &pdu);
377 WLog_ERR(TAG,
"context->SampleErrorResponse failed with error %" PRIu32
"", error);
382static UINT device_server_recv_property_list_response(CameraDeviceServerContext* context,
387 UINT error = CHANNEL_RC_OK;
389 WINPR_ASSERT(context);
390 WINPR_ASSERT(header);
392 pdu.Header = *header;
394 pdu.N_Properties = Stream_GetRemainingLength(s) / 19;
396 if (pdu.N_Properties > 0)
401 WLog_ERR(TAG,
"Failed to allocate %zu CAM_PROPERTY_DESCRIPTION structs",
403 return ERROR_NOT_ENOUGH_MEMORY;
406 for (
size_t i = 0; i < pdu.N_Properties; ++i)
410 const UINT8 val = Stream_Get_UINT8(s);
411 if (!rdpecam_valid_CamPropertySet(val))
413 free(pdu.Properties);
414 return ERROR_INVALID_DATA;
416 cur->PropertySet = (CAM_PROPERTY_SET)val;
418 Stream_Read_UINT8(s, cur->PropertyId);
420 const UINT8 val = Stream_Get_UINT8(s);
421 if (!rdpecam_valid_CamPropertyCapabilities(val))
423 free(pdu.Properties);
424 return ERROR_INVALID_DATA;
426 cur->Capabilities = (CAM_PROPERTY_CAPABILITIES)val;
428 Stream_Read_INT32(s, cur->MinValue);
429 Stream_Read_INT32(s, cur->MaxValue);
430 Stream_Read_INT32(s, cur->Step);
431 Stream_Read_INT32(s, cur->DefaultValue);
435 IFCALLRET(context->PropertyListResponse, error, context, &pdu);
437 WLog_ERR(TAG,
"context->PropertyListResponse failed with error %" PRIu32
"", error);
439 free(pdu.Properties);
444static UINT device_server_recv_property_value_response(CameraDeviceServerContext* context,
449 UINT error = CHANNEL_RC_OK;
451 WINPR_ASSERT(context);
452 WINPR_ASSERT(header);
454 pdu.Header = *header;
456 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
457 return ERROR_NO_DATA;
460 const UINT8 val = Stream_Get_UINT8(s);
461 if (!rdpecam_valid_CamPropertyMode(val))
462 return ERROR_INVALID_DATA;
463 pdu.PropertyValue.Mode = (CAM_PROPERTY_MODE)val;
466 Stream_Read_INT32(s, pdu.PropertyValue.Value);
468 IFCALLRET(context->PropertyValueResponse, error, context, &pdu);
470 WLog_ERR(TAG,
"context->PropertyValueResponse failed with error %" PRIu32
"", error);
475static UINT device_process_message(device_server* device)
478 UINT error = ERROR_INTERNAL_ERROR;
479 ULONG BytesReturned = 0;
483 WINPR_ASSERT(device);
484 WINPR_ASSERT(device->device_channel);
489 Stream_SetPosition(s, 0);
490 rc = WTSVirtualChannelRead(device->device_channel, 0, NULL, 0, &BytesReturned);
494 if (BytesReturned < 1)
496 error = CHANNEL_RC_OK;
500 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
502 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
503 error = CHANNEL_RC_NO_MEMORY;
507 if (WTSVirtualChannelRead(device->device_channel, 0, Stream_BufferAs(s,
char),
508 (ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
510 WLog_ERR(TAG,
"WTSVirtualChannelRead failed!");
514 Stream_SetLength(s, BytesReturned);
515 if (!Stream_CheckAndLogRequiredLength(TAG, s, CAM_HEADER_SIZE))
516 return ERROR_NO_DATA;
518 Stream_Read_UINT8(s, header.Version);
520 const UINT8
id = Stream_Get_UINT8(s);
521 if (!rdpecam_valid_messageId(
id))
522 return ERROR_INVALID_DATA;
523 header.MessageId = (CAM_MSG_ID)
id;
526 switch (header.MessageId)
528 case CAM_MSG_ID_SuccessResponse:
529 error = device_server_handle_success_response(&device->context, s, &header);
531 case CAM_MSG_ID_ErrorResponse:
532 error = device_server_recv_error_response(&device->context, s, &header);
534 case CAM_MSG_ID_StreamListResponse:
535 error = device_server_recv_stream_list_response(&device->context, s, &header);
537 case CAM_MSG_ID_MediaTypeListResponse:
538 error = device_server_recv_media_type_list_response(&device->context, s, &header);
540 case CAM_MSG_ID_CurrentMediaTypeResponse:
541 error = device_server_recv_current_media_type_response(&device->context, s, &header);
543 case CAM_MSG_ID_SampleResponse:
544 error = device_server_recv_sample_response(&device->context, s, &header);
546 case CAM_MSG_ID_SampleErrorResponse:
547 error = device_server_recv_sample_error_response(&device->context, s, &header);
549 case CAM_MSG_ID_PropertyListResponse:
550 error = device_server_recv_property_list_response(&device->context, s, &header);
552 case CAM_MSG_ID_PropertyValueResponse:
553 error = device_server_recv_property_value_response(&device->context, s, &header);
556 WLog_ERR(TAG,
"device_process_message: unknown or invalid MessageId %" PRIu8
"",
563 WLog_ERR(TAG,
"Response failed with error %" PRIu32
"!", error);
568static UINT device_server_context_poll_int(CameraDeviceServerContext* context)
570 device_server* device = (device_server*)context;
571 UINT error = ERROR_INTERNAL_ERROR;
573 WINPR_ASSERT(device);
575 switch (device->state)
577 case CAMERA_DEVICE_INITIAL:
578 error = device_server_open_channel(device);
580 WLog_ERR(TAG,
"device_server_open_channel failed with error %" PRIu32
"!", error);
582 device->state = CAMERA_DEVICE_OPENED;
584 case CAMERA_DEVICE_OPENED:
585 error = device_process_message(device);
594static HANDLE device_server_get_channel_handle(device_server* device)
597 DWORD BytesReturned = 0;
598 HANDLE ChannelEvent = NULL;
600 WINPR_ASSERT(device);
602 if (WTSVirtualChannelQuery(device->device_channel, WTSVirtualEventHandle, &buffer,
603 &BytesReturned) == TRUE)
605 if (BytesReturned ==
sizeof(HANDLE))
606 ChannelEvent = *(HANDLE*)buffer;
608 WTSFreeMemory(buffer);
614static DWORD WINAPI device_server_thread_func(LPVOID arg)
617 HANDLE events[2] = { 0 };
618 device_server* device = (device_server*)arg;
619 UINT error = CHANNEL_RC_OK;
622 WINPR_ASSERT(device);
625 events[nCount++] = device->stopEvent;
627 while ((error == CHANNEL_RC_OK) && (WaitForSingleObject(events[0], 0) != WAIT_OBJECT_0))
629 switch (device->state)
631 case CAMERA_DEVICE_INITIAL:
632 error = device_server_context_poll_int(&device->context);
633 if (error == CHANNEL_RC_OK)
635 events[1] = device_server_get_channel_handle(device);
639 case CAMERA_DEVICE_OPENED:
640 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
645 case WAIT_OBJECT_0 + 1:
647 error = device_server_context_poll_int(&device->context);
652 error = ERROR_INTERNAL_ERROR;
661 (void)WTSVirtualChannelClose(device->device_channel);
662 device->device_channel = NULL;
664 if (error && device->context.rdpcontext)
665 setChannelError(device->context.rdpcontext, error,
666 "device_server_thread_func reported an error");
672static UINT device_server_open(CameraDeviceServerContext* context)
674 device_server* device = (device_server*)context;
676 WINPR_ASSERT(device);
678 if (!device->externalThread && (device->thread == NULL))
680 device->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
681 if (!device->stopEvent)
683 WLog_ERR(TAG,
"CreateEvent failed!");
684 return ERROR_INTERNAL_ERROR;
687 device->thread = CreateThread(NULL, 0, device_server_thread_func, device, 0, NULL);
690 WLog_ERR(TAG,
"CreateThread failed!");
691 (void)CloseHandle(device->stopEvent);
692 device->stopEvent = NULL;
693 return ERROR_INTERNAL_ERROR;
696 device->isOpened = TRUE;
698 return CHANNEL_RC_OK;
701static UINT device_server_close(CameraDeviceServerContext* context)
703 UINT error = CHANNEL_RC_OK;
704 device_server* device = (device_server*)context;
706 WINPR_ASSERT(device);
708 if (!device->externalThread && device->thread)
710 (void)SetEvent(device->stopEvent);
712 if (WaitForSingleObject(device->thread, INFINITE) == WAIT_FAILED)
714 error = GetLastError();
715 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
719 (void)CloseHandle(device->thread);
720 (void)CloseHandle(device->stopEvent);
721 device->thread = NULL;
722 device->stopEvent = NULL;
724 if (device->externalThread)
726 if (device->state != CAMERA_DEVICE_INITIAL)
728 (void)WTSVirtualChannelClose(device->device_channel);
729 device->device_channel = NULL;
730 device->state = CAMERA_DEVICE_INITIAL;
733 device->isOpened = FALSE;
738static UINT device_server_context_poll(CameraDeviceServerContext* context)
740 device_server* device = (device_server*)context;
742 WINPR_ASSERT(device);
744 if (!device->externalThread)
745 return ERROR_INTERNAL_ERROR;
747 return device_server_context_poll_int(context);
750static BOOL device_server_context_handle(CameraDeviceServerContext* context, HANDLE* handle)
752 device_server* device = (device_server*)context;
754 WINPR_ASSERT(device);
755 WINPR_ASSERT(handle);
757 if (!device->externalThread)
759 if (device->state == CAMERA_DEVICE_INITIAL)
762 *handle = device_server_get_channel_handle(device);
767static wStream* device_server_packet_new(
size_t size, BYTE version, BYTE messageId)
772 s = Stream_New(NULL, size + CAM_HEADER_SIZE);
775 WLog_ERR(TAG,
"Stream_New failed!");
779 Stream_Write_UINT8(s, version);
780 Stream_Write_UINT8(s, messageId);
785static UINT device_server_packet_send(CameraDeviceServerContext* context,
wStream* s)
787 device_server* device = (device_server*)context;
788 UINT error = CHANNEL_RC_OK;
791 WINPR_ASSERT(context);
794 const size_t len = Stream_GetPosition(s);
795 WINPR_ASSERT(len <= UINT32_MAX);
796 if (!WTSVirtualChannelWrite(device->device_channel, Stream_BufferAs(s,
char), (UINT32)len,
799 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
800 error = ERROR_INTERNAL_ERROR;
804 if (written < Stream_GetPosition(s))
806 WLog_WARN(TAG,
"Unexpected bytes written: %" PRIu32
"/%" PRIuz
"", written,
807 Stream_GetPosition(s));
811 Stream_Free(s, TRUE);
815static UINT device_server_write_and_send_header(CameraDeviceServerContext* context, BYTE messageId)
819 WINPR_ASSERT(context);
821 s = device_server_packet_new(0, context->protocolVersion, messageId);
823 return ERROR_NOT_ENOUGH_MEMORY;
825 return device_server_packet_send(context, s);
828static UINT device_send_activate_device_request_pdu(
829 CameraDeviceServerContext* context,
832 WINPR_ASSERT(context);
834 return device_server_write_and_send_header(context, CAM_MSG_ID_ActivateDeviceRequest);
837static UINT device_send_deactivate_device_request_pdu(
838 CameraDeviceServerContext* context,
841 WINPR_ASSERT(context);
843 return device_server_write_and_send_header(context, CAM_MSG_ID_DeactivateDeviceRequest);
846static UINT device_send_stream_list_request_pdu(
847 CameraDeviceServerContext* context,
850 WINPR_ASSERT(context);
852 return device_server_write_and_send_header(context, CAM_MSG_ID_StreamListRequest);
856device_send_media_type_list_request_pdu(CameraDeviceServerContext* context,
861 WINPR_ASSERT(context);
862 WINPR_ASSERT(mediaTypeListRequest);
864 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_MediaTypeListRequest);
866 return ERROR_NOT_ENOUGH_MEMORY;
868 Stream_Write_UINT8(s, mediaTypeListRequest->StreamIndex);
870 return device_server_packet_send(context, s);
873static UINT device_send_current_media_type_request_pdu(
874 CameraDeviceServerContext* context,
879 WINPR_ASSERT(context);
880 WINPR_ASSERT(currentMediaTypeRequest);
882 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_CurrentMediaTypeRequest);
884 return ERROR_NOT_ENOUGH_MEMORY;
886 Stream_Write_UINT8(s, currentMediaTypeRequest->StreamIndex);
888 return device_server_packet_send(context, s);
892device_send_start_streams_request_pdu(CameraDeviceServerContext* context,
897 WINPR_ASSERT(context);
898 WINPR_ASSERT(startStreamsRequest);
900 s = device_server_packet_new(startStreamsRequest->N_Infos * 27ul, context->protocolVersion,
901 CAM_MSG_ID_StartStreamsRequest);
903 return ERROR_NOT_ENOUGH_MEMORY;
905 for (
size_t i = 0; i < startStreamsRequest->N_Infos; ++i)
910 Stream_Write_UINT8(s, info->StreamIndex);
912 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, description->Format));
913 Stream_Write_UINT32(s, description->Width);
914 Stream_Write_UINT32(s, description->Height);
915 Stream_Write_UINT32(s, description->FrameRateNumerator);
916 Stream_Write_UINT32(s, description->FrameRateDenominator);
917 Stream_Write_UINT32(s, description->PixelAspectRatioNumerator);
918 Stream_Write_UINT32(s, description->PixelAspectRatioDenominator);
919 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, description->Flags));
922 return device_server_packet_send(context, s);
925static UINT device_send_stop_streams_request_pdu(
926 CameraDeviceServerContext* context,
929 WINPR_ASSERT(context);
931 return device_server_write_and_send_header(context, CAM_MSG_ID_StopStreamsRequest);
934static UINT device_send_sample_request_pdu(CameraDeviceServerContext* context,
939 WINPR_ASSERT(context);
940 WINPR_ASSERT(sampleRequest);
942 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_SampleRequest);
944 return ERROR_NOT_ENOUGH_MEMORY;
946 Stream_Write_UINT8(s, sampleRequest->StreamIndex);
948 return device_server_packet_send(context, s);
951static UINT device_send_property_list_request_pdu(
952 CameraDeviceServerContext* context,
955 WINPR_ASSERT(context);
957 return device_server_write_and_send_header(context, CAM_MSG_ID_PropertyListRequest);
961device_send_property_value_request_pdu(CameraDeviceServerContext* context,
966 WINPR_ASSERT(context);
967 WINPR_ASSERT(propertyValueRequest);
969 s = device_server_packet_new(2, context->protocolVersion, CAM_MSG_ID_PropertyValueRequest);
971 return ERROR_NOT_ENOUGH_MEMORY;
973 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, propertyValueRequest->PropertySet));
974 Stream_Write_UINT8(s, propertyValueRequest->PropertyId);
976 return device_server_packet_send(context, s);
979static UINT device_send_set_property_value_request_pdu(
980 CameraDeviceServerContext* context,
985 WINPR_ASSERT(context);
986 WINPR_ASSERT(setPropertyValueRequest);
988 s = device_server_packet_new(2 + 5, context->protocolVersion,
989 CAM_MSG_ID_SetPropertyValueRequest);
991 return ERROR_NOT_ENOUGH_MEMORY;
993 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, setPropertyValueRequest->PropertySet));
994 Stream_Write_UINT8(s, setPropertyValueRequest->PropertyId);
997 s, WINPR_ASSERTING_INT_CAST(uint8_t, setPropertyValueRequest->PropertyValue.Mode));
998 Stream_Write_INT32(s, setPropertyValueRequest->PropertyValue.Value);
1000 return device_server_packet_send(context, s);
1003CameraDeviceServerContext* camera_device_server_context_new(HANDLE vcm)
1005 device_server* device = (device_server*)calloc(1,
sizeof(device_server));
1010 device->context.vcm = vcm;
1011 device->context.Initialize = device_server_initialize;
1012 device->context.Open = device_server_open;
1013 device->context.Close = device_server_close;
1014 device->context.Poll = device_server_context_poll;
1015 device->context.ChannelHandle = device_server_context_handle;
1017 device->context.ActivateDeviceRequest = device_send_activate_device_request_pdu;
1018 device->context.DeactivateDeviceRequest = device_send_deactivate_device_request_pdu;
1020 device->context.StreamListRequest = device_send_stream_list_request_pdu;
1021 device->context.MediaTypeListRequest = device_send_media_type_list_request_pdu;
1022 device->context.CurrentMediaTypeRequest = device_send_current_media_type_request_pdu;
1024 device->context.StartStreamsRequest = device_send_start_streams_request_pdu;
1025 device->context.StopStreamsRequest = device_send_stop_streams_request_pdu;
1026 device->context.SampleRequest = device_send_sample_request_pdu;
1028 device->context.PropertyListRequest = device_send_property_list_request_pdu;
1029 device->context.PropertyValueRequest = device_send_property_value_request_pdu;
1030 device->context.SetPropertyValueRequest = device_send_set_property_value_request_pdu;
1032 device->buffer = Stream_New(NULL, 4096);
1033 if (!device->buffer)
1036 return &device->context;
1038 WINPR_PRAGMA_DIAG_PUSH
1039 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1040 camera_device_server_context_free(&device->context);
1041 WINPR_PRAGMA_DIAG_POP
1045void camera_device_server_context_free(CameraDeviceServerContext* context)
1047 device_server* device = (device_server*)context;
1051 device_server_close(context);
1052 Stream_Free(device->buffer, TRUE);
1055 free(context->virtualChannelName);