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 #define TAG CHANNELS_TAG("rdpecam.server")
32 CAMERA_DEVICE_INITIAL,
34 } eCameraDeviceChannelState;
38 CameraDeviceServerContext context;
51 eCameraDeviceChannelState state;
56 static UINT device_server_initialize(CameraDeviceServerContext* context, BOOL externalThread)
58 UINT error = CHANNEL_RC_OK;
59 device_server* device = (device_server*)context;
65 WLog_WARN(TAG,
"Application error: Camera channel already initialized, "
66 "calling in this state is not possible!");
67 return ERROR_INVALID_STATE;
70 device->externalThread = externalThread;
75 static UINT device_server_open_channel(device_server* device)
77 CameraDeviceServerContext* context = &device->context;
78 DWORD Error = ERROR_SUCCESS;
80 DWORD BytesReturned = 0;
81 PULONG pSessionId = NULL;
87 if (WTSQuerySessionInformationA(device->context.vcm, WTS_CURRENT_SESSION, WTSSessionId,
88 (LPSTR*)&pSessionId, &BytesReturned) == FALSE)
90 WLog_ERR(TAG,
"WTSQuerySessionInformationA failed!");
91 return ERROR_INTERNAL_ERROR;
94 device->SessionId = (DWORD)*pSessionId;
95 WTSFreeMemory(pSessionId);
96 hEvent = WTSVirtualChannelManagerGetEventHandle(device->context.vcm);
98 if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED)
100 Error = GetLastError();
101 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", Error);
105 device->device_channel = WTSVirtualChannelOpenEx(device->SessionId, context->virtualChannelName,
106 WTS_CHANNEL_OPTION_DYNAMIC);
107 if (!device->device_channel)
109 Error = GetLastError();
110 WLog_ERR(TAG,
"WTSVirtualChannelOpenEx failed with error %" PRIu32
"!", Error);
114 channelId = WTSChannelGetIdByHandle(device->device_channel);
116 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
119 WLog_ERR(TAG,
"context->ChannelIdAssigned failed!");
120 return ERROR_INTERNAL_ERROR;
126 static UINT device_server_handle_success_response(CameraDeviceServerContext* context,
wStream* s,
130 UINT error = CHANNEL_RC_OK;
132 WINPR_ASSERT(context);
133 WINPR_ASSERT(header);
135 pdu.Header = *header;
137 IFCALLRET(context->SuccessResponse, error, context, &pdu);
139 WLog_ERR(TAG,
"context->SuccessResponse failed with error %" PRIu32
"", error);
144 static UINT device_server_recv_error_response(CameraDeviceServerContext* context,
wStream* s,
148 UINT error = CHANNEL_RC_OK;
150 WINPR_ASSERT(context);
151 WINPR_ASSERT(header);
153 pdu.Header = *header;
155 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
156 return ERROR_NO_DATA;
158 Stream_Read_UINT32(s, pdu.ErrorCode);
160 IFCALLRET(context->ErrorResponse, error, context, &pdu);
162 WLog_ERR(TAG,
"context->ErrorResponse failed with error %" PRIu32
"", error);
167 static UINT device_server_recv_stream_list_response(CameraDeviceServerContext* context,
wStream* s,
171 UINT error = CHANNEL_RC_OK;
173 WINPR_ASSERT(context);
174 WINPR_ASSERT(header);
176 pdu.Header = *header;
178 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
179 return ERROR_NO_DATA;
181 pdu.N_Descriptions = 255;
182 const size_t len = Stream_GetRemainingLength(s) / 5;
184 pdu.N_Descriptions = (BYTE)len;
186 for (BYTE i = 0; i < pdu.N_Descriptions; ++i)
190 Stream_Read_UINT16(s, StreamDescription->FrameSourceTypes);
191 Stream_Read_UINT8(s, StreamDescription->StreamCategory);
192 Stream_Read_UINT8(s, StreamDescription->Selected);
193 Stream_Read_UINT8(s, StreamDescription->CanBeShared);
196 IFCALLRET(context->StreamListResponse, error, context, &pdu);
198 WLog_ERR(TAG,
"context->StreamListResponse failed with error %" PRIu32
"", error);
203 static UINT device_server_recv_media_type_list_response(CameraDeviceServerContext* context,
208 UINT error = CHANNEL_RC_OK;
210 WINPR_ASSERT(context);
211 WINPR_ASSERT(header);
213 pdu.Header = *header;
215 if (!Stream_CheckAndLogRequiredLength(TAG, s, 26))
216 return ERROR_NO_DATA;
218 pdu.N_Descriptions = Stream_GetRemainingLength(s) / 26;
221 if (!pdu.MediaTypeDescriptions)
223 WLog_ERR(TAG,
"Failed to allocate %zu CAM_MEDIA_TYPE_DESCRIPTION structs",
225 return ERROR_NOT_ENOUGH_MEMORY;
228 for (
size_t i = 0; i < pdu.N_Descriptions; ++i)
232 Stream_Read_UINT8(s, MediaTypeDescriptions->Format);
233 Stream_Read_UINT32(s, MediaTypeDescriptions->Width);
234 Stream_Read_UINT32(s, MediaTypeDescriptions->Height);
235 Stream_Read_UINT32(s, MediaTypeDescriptions->FrameRateNumerator);
236 Stream_Read_UINT32(s, MediaTypeDescriptions->FrameRateDenominator);
237 Stream_Read_UINT32(s, MediaTypeDescriptions->PixelAspectRatioNumerator);
238 Stream_Read_UINT32(s, MediaTypeDescriptions->PixelAspectRatioDenominator);
239 Stream_Read_UINT8(s, MediaTypeDescriptions->Flags);
242 IFCALLRET(context->MediaTypeListResponse, error, context, &pdu);
244 WLog_ERR(TAG,
"context->MediaTypeListResponse failed with error %" PRIu32
"", error);
246 free(pdu.MediaTypeDescriptions);
251 static UINT device_server_recv_current_media_type_response(CameraDeviceServerContext* context,
256 UINT error = CHANNEL_RC_OK;
258 WINPR_ASSERT(context);
259 WINPR_ASSERT(header);
261 pdu.Header = *header;
263 if (!Stream_CheckAndLogRequiredLength(TAG, s, 26))
264 return ERROR_NO_DATA;
266 Stream_Read_UINT8(s, pdu.MediaTypeDescription.Format);
267 Stream_Read_UINT32(s, pdu.MediaTypeDescription.Width);
268 Stream_Read_UINT32(s, pdu.MediaTypeDescription.Height);
269 Stream_Read_UINT32(s, pdu.MediaTypeDescription.FrameRateNumerator);
270 Stream_Read_UINT32(s, pdu.MediaTypeDescription.FrameRateDenominator);
271 Stream_Read_UINT32(s, pdu.MediaTypeDescription.PixelAspectRatioNumerator);
272 Stream_Read_UINT32(s, pdu.MediaTypeDescription.PixelAspectRatioDenominator);
273 Stream_Read_UINT8(s, pdu.MediaTypeDescription.Flags);
275 IFCALLRET(context->CurrentMediaTypeResponse, error, context, &pdu);
277 WLog_ERR(TAG,
"context->CurrentMediaTypeResponse failed with error %" PRIu32
"", error);
282 static UINT device_server_recv_sample_response(CameraDeviceServerContext* context,
wStream* s,
286 UINT error = CHANNEL_RC_OK;
288 WINPR_ASSERT(context);
289 WINPR_ASSERT(header);
291 pdu.Header = *header;
293 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
294 return ERROR_NO_DATA;
296 Stream_Read_UINT8(s, pdu.StreamIndex);
298 pdu.SampleSize = Stream_GetRemainingLength(s);
299 pdu.Sample = Stream_Pointer(s);
301 IFCALLRET(context->SampleResponse, error, context, &pdu);
303 WLog_ERR(TAG,
"context->SampleResponse failed with error %" PRIu32
"", error);
308 static UINT device_server_recv_sample_error_response(CameraDeviceServerContext* context,
wStream* s,
312 UINT error = CHANNEL_RC_OK;
314 WINPR_ASSERT(context);
315 WINPR_ASSERT(header);
317 pdu.Header = *header;
319 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
320 return ERROR_NO_DATA;
322 Stream_Read_UINT8(s, pdu.StreamIndex);
323 Stream_Read_UINT32(s, pdu.ErrorCode);
325 IFCALLRET(context->SampleErrorResponse, error, context, &pdu);
327 WLog_ERR(TAG,
"context->SampleErrorResponse failed with error %" PRIu32
"", error);
332 static UINT device_server_recv_property_list_response(CameraDeviceServerContext* context,
337 UINT error = CHANNEL_RC_OK;
339 WINPR_ASSERT(context);
340 WINPR_ASSERT(header);
342 pdu.Header = *header;
344 pdu.N_Properties = Stream_GetRemainingLength(s) / 19;
346 if (pdu.N_Properties > 0)
351 WLog_ERR(TAG,
"Failed to allocate %zu CAM_PROPERTY_DESCRIPTION structs",
353 return ERROR_NOT_ENOUGH_MEMORY;
356 for (
size_t i = 0; i < pdu.N_Properties; ++i)
358 Stream_Read_UINT8(s, pdu.Properties[i].PropertySet);
359 Stream_Read_UINT8(s, pdu.Properties[i].PropertyId);
360 Stream_Read_UINT8(s, pdu.Properties[i].Capabilities);
361 Stream_Read_INT32(s, pdu.Properties[i].MinValue);
362 Stream_Read_INT32(s, pdu.Properties[i].MaxValue);
363 Stream_Read_INT32(s, pdu.Properties[i].Step);
364 Stream_Read_INT32(s, pdu.Properties[i].DefaultValue);
368 IFCALLRET(context->PropertyListResponse, error, context, &pdu);
370 WLog_ERR(TAG,
"context->PropertyListResponse failed with error %" PRIu32
"", error);
372 free(pdu.Properties);
377 static UINT device_server_recv_property_value_response(CameraDeviceServerContext* context,
382 UINT error = CHANNEL_RC_OK;
384 WINPR_ASSERT(context);
385 WINPR_ASSERT(header);
387 pdu.Header = *header;
389 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
390 return ERROR_NO_DATA;
392 Stream_Read_UINT8(s, pdu.PropertyValue.Mode);
393 Stream_Read_INT32(s, pdu.PropertyValue.Value);
395 IFCALLRET(context->PropertyValueResponse, error, context, &pdu);
397 WLog_ERR(TAG,
"context->PropertyValueResponse failed with error %" PRIu32
"", error);
402 static UINT device_process_message(device_server* device)
405 UINT error = ERROR_INTERNAL_ERROR;
406 ULONG BytesReturned = 0;
410 WINPR_ASSERT(device);
411 WINPR_ASSERT(device->device_channel);
416 Stream_SetPosition(s, 0);
417 rc = WTSVirtualChannelRead(device->device_channel, 0, NULL, 0, &BytesReturned);
421 if (BytesReturned < 1)
423 error = CHANNEL_RC_OK;
427 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
429 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
430 error = CHANNEL_RC_NO_MEMORY;
434 if (WTSVirtualChannelRead(device->device_channel, 0, Stream_BufferAs(s,
char),
435 (ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
437 WLog_ERR(TAG,
"WTSVirtualChannelRead failed!");
441 Stream_SetLength(s, BytesReturned);
442 if (!Stream_CheckAndLogRequiredLength(TAG, s, CAM_HEADER_SIZE))
443 return ERROR_NO_DATA;
445 Stream_Read_UINT8(s, header.Version);
446 Stream_Read_UINT8(s, header.MessageId);
448 switch (header.MessageId)
450 case CAM_MSG_ID_SuccessResponse:
451 error = device_server_handle_success_response(&device->context, s, &header);
453 case CAM_MSG_ID_ErrorResponse:
454 error = device_server_recv_error_response(&device->context, s, &header);
456 case CAM_MSG_ID_StreamListResponse:
457 error = device_server_recv_stream_list_response(&device->context, s, &header);
459 case CAM_MSG_ID_MediaTypeListResponse:
460 error = device_server_recv_media_type_list_response(&device->context, s, &header);
462 case CAM_MSG_ID_CurrentMediaTypeResponse:
463 error = device_server_recv_current_media_type_response(&device->context, s, &header);
465 case CAM_MSG_ID_SampleResponse:
466 error = device_server_recv_sample_response(&device->context, s, &header);
468 case CAM_MSG_ID_SampleErrorResponse:
469 error = device_server_recv_sample_error_response(&device->context, s, &header);
471 case CAM_MSG_ID_PropertyListResponse:
472 error = device_server_recv_property_list_response(&device->context, s, &header);
474 case CAM_MSG_ID_PropertyValueResponse:
475 error = device_server_recv_property_value_response(&device->context, s, &header);
478 WLog_ERR(TAG,
"device_process_message: unknown or invalid MessageId %" PRIu8
"",
485 WLog_ERR(TAG,
"Response failed with error %" PRIu32
"!", error);
490 static UINT device_server_context_poll_int(CameraDeviceServerContext* context)
492 device_server* device = (device_server*)context;
493 UINT error = ERROR_INTERNAL_ERROR;
495 WINPR_ASSERT(device);
497 switch (device->state)
499 case CAMERA_DEVICE_INITIAL:
500 error = device_server_open_channel(device);
502 WLog_ERR(TAG,
"device_server_open_channel failed with error %" PRIu32
"!", error);
504 device->state = CAMERA_DEVICE_OPENED;
506 case CAMERA_DEVICE_OPENED:
507 error = device_process_message(device);
516 static HANDLE device_server_get_channel_handle(device_server* device)
519 DWORD BytesReturned = 0;
520 HANDLE ChannelEvent = NULL;
522 WINPR_ASSERT(device);
524 if (WTSVirtualChannelQuery(device->device_channel, WTSVirtualEventHandle, &buffer,
525 &BytesReturned) == TRUE)
527 if (BytesReturned ==
sizeof(HANDLE))
528 ChannelEvent = *(HANDLE*)buffer;
530 WTSFreeMemory(buffer);
536 static DWORD WINAPI device_server_thread_func(LPVOID arg)
539 HANDLE events[2] = { 0 };
540 device_server* device = (device_server*)arg;
541 UINT error = CHANNEL_RC_OK;
544 WINPR_ASSERT(device);
547 events[nCount++] = device->stopEvent;
549 while ((error == CHANNEL_RC_OK) && (WaitForSingleObject(events[0], 0) != WAIT_OBJECT_0))
551 switch (device->state)
553 case CAMERA_DEVICE_INITIAL:
554 error = device_server_context_poll_int(&device->context);
555 if (error == CHANNEL_RC_OK)
557 events[1] = device_server_get_channel_handle(device);
561 case CAMERA_DEVICE_OPENED:
562 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
567 case WAIT_OBJECT_0 + 1:
569 error = device_server_context_poll_int(&device->context);
574 error = ERROR_INTERNAL_ERROR;
583 (void)WTSVirtualChannelClose(device->device_channel);
584 device->device_channel = NULL;
586 if (error && device->context.rdpcontext)
587 setChannelError(device->context.rdpcontext, error,
588 "device_server_thread_func reported an error");
594 static UINT device_server_open(CameraDeviceServerContext* context)
596 device_server* device = (device_server*)context;
598 WINPR_ASSERT(device);
600 if (!device->externalThread && (device->thread == NULL))
602 device->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
603 if (!device->stopEvent)
605 WLog_ERR(TAG,
"CreateEvent failed!");
606 return ERROR_INTERNAL_ERROR;
609 device->thread = CreateThread(NULL, 0, device_server_thread_func, device, 0, NULL);
612 WLog_ERR(TAG,
"CreateThread failed!");
613 (void)CloseHandle(device->stopEvent);
614 device->stopEvent = NULL;
615 return ERROR_INTERNAL_ERROR;
618 device->isOpened = TRUE;
620 return CHANNEL_RC_OK;
623 static UINT device_server_close(CameraDeviceServerContext* context)
625 UINT error = CHANNEL_RC_OK;
626 device_server* device = (device_server*)context;
628 WINPR_ASSERT(device);
630 if (!device->externalThread && device->thread)
632 (void)SetEvent(device->stopEvent);
634 if (WaitForSingleObject(device->thread, INFINITE) == WAIT_FAILED)
636 error = GetLastError();
637 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
641 (void)CloseHandle(device->thread);
642 (void)CloseHandle(device->stopEvent);
643 device->thread = NULL;
644 device->stopEvent = NULL;
646 if (device->externalThread)
648 if (device->state != CAMERA_DEVICE_INITIAL)
650 (void)WTSVirtualChannelClose(device->device_channel);
651 device->device_channel = NULL;
652 device->state = CAMERA_DEVICE_INITIAL;
655 device->isOpened = FALSE;
660 static UINT device_server_context_poll(CameraDeviceServerContext* context)
662 device_server* device = (device_server*)context;
664 WINPR_ASSERT(device);
666 if (!device->externalThread)
667 return ERROR_INTERNAL_ERROR;
669 return device_server_context_poll_int(context);
672 static BOOL device_server_context_handle(CameraDeviceServerContext* context, HANDLE* handle)
674 device_server* device = (device_server*)context;
676 WINPR_ASSERT(device);
677 WINPR_ASSERT(handle);
679 if (!device->externalThread)
681 if (device->state == CAMERA_DEVICE_INITIAL)
684 *handle = device_server_get_channel_handle(device);
689 static wStream* device_server_packet_new(
size_t size, BYTE version, BYTE messageId)
694 s = Stream_New(NULL, size + CAM_HEADER_SIZE);
697 WLog_ERR(TAG,
"Stream_New failed!");
701 Stream_Write_UINT8(s, version);
702 Stream_Write_UINT8(s, messageId);
707 static UINT device_server_packet_send(CameraDeviceServerContext* context,
wStream* s)
709 device_server* device = (device_server*)context;
710 UINT error = CHANNEL_RC_OK;
713 WINPR_ASSERT(context);
716 const size_t len = Stream_GetPosition(s);
717 WINPR_ASSERT(len <= UINT32_MAX);
718 if (!WTSVirtualChannelWrite(device->device_channel, Stream_BufferAs(s,
char), (UINT32)len,
721 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
722 error = ERROR_INTERNAL_ERROR;
726 if (written < Stream_GetPosition(s))
728 WLog_WARN(TAG,
"Unexpected bytes written: %" PRIu32
"/%" PRIuz
"", written,
729 Stream_GetPosition(s));
733 Stream_Free(s, TRUE);
737 static UINT device_server_write_and_send_header(CameraDeviceServerContext* context, BYTE messageId)
741 WINPR_ASSERT(context);
743 s = device_server_packet_new(0, context->protocolVersion, messageId);
745 return ERROR_NOT_ENOUGH_MEMORY;
747 return device_server_packet_send(context, s);
751 device_send_activate_device_request_pdu(CameraDeviceServerContext* context,
754 WINPR_ASSERT(context);
756 return device_server_write_and_send_header(context, CAM_MSG_ID_ActivateDeviceRequest);
759 static UINT device_send_deactivate_device_request_pdu(
760 CameraDeviceServerContext* context,
763 WINPR_ASSERT(context);
765 return device_server_write_and_send_header(context, CAM_MSG_ID_DeactivateDeviceRequest);
768 static UINT device_send_stream_list_request_pdu(CameraDeviceServerContext* context,
771 WINPR_ASSERT(context);
773 return device_server_write_and_send_header(context, CAM_MSG_ID_StreamListRequest);
777 device_send_media_type_list_request_pdu(CameraDeviceServerContext* context,
782 WINPR_ASSERT(context);
783 WINPR_ASSERT(mediaTypeListRequest);
785 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_MediaTypeListRequest);
787 return ERROR_NOT_ENOUGH_MEMORY;
789 Stream_Write_UINT8(s, mediaTypeListRequest->StreamIndex);
791 return device_server_packet_send(context, s);
794 static UINT device_send_current_media_type_request_pdu(
795 CameraDeviceServerContext* context,
800 WINPR_ASSERT(context);
801 WINPR_ASSERT(currentMediaTypeRequest);
803 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_CurrentMediaTypeRequest);
805 return ERROR_NOT_ENOUGH_MEMORY;
807 Stream_Write_UINT8(s, currentMediaTypeRequest->StreamIndex);
809 return device_server_packet_send(context, s);
813 device_send_start_streams_request_pdu(CameraDeviceServerContext* context,
818 WINPR_ASSERT(context);
819 WINPR_ASSERT(startStreamsRequest);
821 s = device_server_packet_new(startStreamsRequest->N_Infos * 27ul, context->protocolVersion,
822 CAM_MSG_ID_StartStreamsRequest);
824 return ERROR_NOT_ENOUGH_MEMORY;
826 for (
size_t i = 0; i < startStreamsRequest->N_Infos; ++i)
831 Stream_Write_UINT8(s, info->StreamIndex);
833 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, description->Format));
834 Stream_Write_UINT32(s, description->Width);
835 Stream_Write_UINT32(s, description->Height);
836 Stream_Write_UINT32(s, description->FrameRateNumerator);
837 Stream_Write_UINT32(s, description->FrameRateDenominator);
838 Stream_Write_UINT32(s, description->PixelAspectRatioNumerator);
839 Stream_Write_UINT32(s, description->PixelAspectRatioDenominator);
840 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, description->Flags));
843 return device_server_packet_send(context, s);
846 static UINT device_send_stop_streams_request_pdu(CameraDeviceServerContext* context,
849 WINPR_ASSERT(context);
851 return device_server_write_and_send_header(context, CAM_MSG_ID_StopStreamsRequest);
854 static UINT device_send_sample_request_pdu(CameraDeviceServerContext* context,
859 WINPR_ASSERT(context);
860 WINPR_ASSERT(sampleRequest);
862 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_SampleRequest);
864 return ERROR_NOT_ENOUGH_MEMORY;
866 Stream_Write_UINT8(s, sampleRequest->StreamIndex);
868 return device_server_packet_send(context, s);
872 device_send_property_list_request_pdu(CameraDeviceServerContext* context,
875 WINPR_ASSERT(context);
877 return device_server_write_and_send_header(context, CAM_MSG_ID_PropertyListRequest);
881 device_send_property_value_request_pdu(CameraDeviceServerContext* context,
886 WINPR_ASSERT(context);
887 WINPR_ASSERT(propertyValueRequest);
889 s = device_server_packet_new(2, context->protocolVersion, CAM_MSG_ID_PropertyValueRequest);
891 return ERROR_NOT_ENOUGH_MEMORY;
893 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, propertyValueRequest->PropertySet));
894 Stream_Write_UINT8(s, propertyValueRequest->PropertyId);
896 return device_server_packet_send(context, s);
899 static UINT device_send_set_property_value_request_pdu(
900 CameraDeviceServerContext* context,
905 WINPR_ASSERT(context);
906 WINPR_ASSERT(setPropertyValueRequest);
908 s = device_server_packet_new(2 + 5, context->protocolVersion,
909 CAM_MSG_ID_SetPropertyValueRequest);
911 return ERROR_NOT_ENOUGH_MEMORY;
913 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, setPropertyValueRequest->PropertySet));
914 Stream_Write_UINT8(s, setPropertyValueRequest->PropertyId);
917 s, WINPR_ASSERTING_INT_CAST(uint8_t, setPropertyValueRequest->PropertyValue.Mode));
918 Stream_Write_INT32(s, setPropertyValueRequest->PropertyValue.Value);
920 return device_server_packet_send(context, s);
923 CameraDeviceServerContext* camera_device_server_context_new(HANDLE vcm)
925 device_server* device = (device_server*)calloc(1,
sizeof(device_server));
930 device->context.vcm = vcm;
931 device->context.Initialize = device_server_initialize;
932 device->context.Open = device_server_open;
933 device->context.Close = device_server_close;
934 device->context.Poll = device_server_context_poll;
935 device->context.ChannelHandle = device_server_context_handle;
937 device->context.ActivateDeviceRequest = device_send_activate_device_request_pdu;
938 device->context.DeactivateDeviceRequest = device_send_deactivate_device_request_pdu;
940 device->context.StreamListRequest = device_send_stream_list_request_pdu;
941 device->context.MediaTypeListRequest = device_send_media_type_list_request_pdu;
942 device->context.CurrentMediaTypeRequest = device_send_current_media_type_request_pdu;
944 device->context.StartStreamsRequest = device_send_start_streams_request_pdu;
945 device->context.StopStreamsRequest = device_send_stop_streams_request_pdu;
946 device->context.SampleRequest = device_send_sample_request_pdu;
948 device->context.PropertyListRequest = device_send_property_list_request_pdu;
949 device->context.PropertyValueRequest = device_send_property_value_request_pdu;
950 device->context.SetPropertyValueRequest = device_send_set_property_value_request_pdu;
952 device->buffer = Stream_New(NULL, 4096);
956 return &device->context;
958 WINPR_PRAGMA_DIAG_PUSH
959 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
960 camera_device_server_context_free(&device->context);
961 WINPR_PRAGMA_DIAG_POP
965 void camera_device_server_context_free(CameraDeviceServerContext* context)
967 device_server* device = (device_server*)context;
971 device_server_close(context);
972 Stream_Free(device->buffer, TRUE);
975 free(context->virtualChannelName);