LM3643 Initial Commit : Synchronous Boost Dual LED Flash Driver
[windows-iot-driver/drivers.git] / LM3643 / TxnwLedLm3643 / Device.c
1 /*++\r
2 Copyright (c) Texas Instruments Inc. All Rights Reserved.\r
3 Sample code for Dual LED FLASH LM3643.\r
4 \r
5 The MIT License (MIT)\r
6 \r
7 Permission is hereby granted, free of charge, to any person obtaining a copy\r
8 of this software and associated documentation files (the "Software"), to deal\r
9 in the Software without restriction, including without limitation the rights\r
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
11 copies of the Software, and to permit persons to whom the Software is\r
12 furnished to do so, subject to the following conditions:\r
13 \r
14 The above copyright notice and this permission notice shall be included in\r
15 all copies or substantial portions of the Software.\r
16 \r
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
23 THE SOFTWARE.\r
24 \r
25 Module Name:\r
26 \r
27     device.c - Device handling events for example driver.\r
28 \r
29 Abstract:\r
30 \r
31    This file contains the device entry points and callbacks.\r
32     \r
33 Environment:\r
34 \r
35     Kernel-mode Driver Framework\r
36 \r
37 --*/\r
38 \r
39 #include "driver.h"\r
40 #include "device.tmh"\r
41 #include "spb.h"\r
42 #include "public.h"\r
43 \r
44 #ifdef ALLOC_PRAGMA\r
45         #pragma alloc_text(PAGE, OnD0Exit)\r
46 #endif\r
47 \r
48 \r
49 NTSTATUS\r
50 RegUpdateSynchronously(\r
51         IN SPB_CONTEXT *SpbContext,\r
52         IN UCHAR Address,\r
53         IN UCHAR Mask,\r
54         IN UCHAR Data\r
55         )\r
56 {\r
57         NTSTATUS status;\r
58         BYTE rData;\r
59 \r
60         status = SpbReadDataSynchronously(SpbContext, Address, &rData, 1);\r
61         if (!NT_SUCCESS(status))\r
62                 return status;\r
63 \r
64         rData &= ~Mask;\r
65         rData |= (Data & Mask);\r
66 \r
67         status = SpbWriteDataSynchronously(SpbContext, Address, &rData, 1);\r
68 \r
69         return status;\r
70 }\r
71 \r
72 NTSTATUS\r
73 OnD0Entry(\r
74         IN WDFDEVICE Device,\r
75         IN WDF_POWER_DEVICE_STATE PreviousState\r
76         )\r
77         /*++\r
78 \r
79         Routine Description:\r
80 \r
81         This routine will power on the hardware\r
82 \r
83         Arguments:\r
84 \r
85         Device - WDF device to power on\r
86         PreviousState - Prior power state\r
87 \r
88         Return Value:\r
89 \r
90         NTSTATUS indicating success or failure\r
91 \r
92         */\r
93 {\r
94         NTSTATUS status;\r
95         PDEVICE_EXTENSION devContext;\r
96 \r
97         devContext = GetDeviceContext(Device);\r
98 \r
99         UNREFERENCED_PARAMETER(PreviousState);\r
100 \r
101         BYTE rData;\r
102         SPB_CONTEXT *SpbContext = &devContext->I2CContext;\r
103         status = SpbReadDataSynchronously(SpbContext, 0x0C, &rData, 1);\r
104 \r
105         devContext->ServiceInterruptsAfterD0Entry = TRUE;\r
106 \r
107         return status;\r
108 }\r
109 \r
110 NTSTATUS\r
111 OnD0Exit(\r
112         IN WDFDEVICE Device,\r
113         IN WDF_POWER_DEVICE_STATE TargetState\r
114         )\r
115         /*++\r
116 \r
117         Routine Description:\r
118 \r
119         This routine will power down the hardware\r
120 \r
121         Arguments:\r
122 \r
123         Device - WDF device to power off\r
124 \r
125         PreviousState - Prior power state\r
126 \r
127         Return Value:\r
128 \r
129         NTSTATUS indicating success or failure\r
130 \r
131         */\r
132 {\r
133         NTSTATUS status;\r
134         PDEVICE_EXTENSION devContext;\r
135 \r
136         PAGED_CODE();\r
137         devContext = GetDeviceContext(Device);\r
138         UNREFERENCED_PARAMETER(TargetState);\r
139 \r
140         SPB_CONTEXT *SpbContext = &devContext->I2CContext;\r
141         status = RegUpdateSynchronously(SpbContext, 0x01, 0x03, 0);\r
142         return status;\r
143 }\r
144 \r
145 NTSTATUS\r
146 OnPrepareHardware(\r
147         IN WDFDEVICE FxDevice,\r
148         IN WDFCMRESLIST FxResourcesRaw,\r
149         IN WDFCMRESLIST FxResourcesTranslated\r
150         )\r
151         /*++\r
152 \r
153         Routine Description:\r
154 \r
155         This routine is called by the PnP manager and supplies thie device instance\r
156         with it's SPB resources (CmResourceTypeConnection) needed to find the I2C\r
157         driver.\r
158 \r
159         Arguments:\r
160 \r
161         FxDevice - a handle to the framework device object\r
162         FxResourcesRaw - list of translated hardware resources that\r
163         the PnP manager has assigned to the device\r
164         FxResourcesTranslated - list of raw hardware resources that\r
165         the PnP manager has assigned to the device\r
166 \r
167         Return Value:\r
168 \r
169         NTSTATUS indicating sucess or failure\r
170 \r
171         --*/\r
172 {\r
173         NTSTATUS status;\r
174         PCM_PARTIAL_RESOURCE_DESCRIPTOR res;\r
175         PDEVICE_EXTENSION devContext;\r
176         ULONG resourceCount;\r
177         ULONG i;\r
178 \r
179         UNREFERENCED_PARAMETER(FxResourcesRaw);\r
180 \r
181         status = STATUS_INSUFFICIENT_RESOURCES;\r
182         devContext = GetDeviceContext(FxDevice);\r
183         resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated);\r
184 \r
185         for (i = 0; i < resourceCount; i++)\r
186         {\r
187                 res = WdfCmResourceListGetDescriptor(FxResourcesTranslated, i);\r
188 \r
189                 if (res->Type == CmResourceTypeConnection &&\r
190                         res->u.Connection.Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL &&\r
191                         res->u.Connection.Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C)\r
192                 {\r
193                         devContext->I2CContext.I2cResHubId.LowPart =\r
194                                 res->u.Connection.IdLowPart;\r
195                         devContext->I2CContext.I2cResHubId.HighPart =\r
196                                 res->u.Connection.IdHighPart;\r
197 \r
198                         status = STATUS_SUCCESS;\r
199                 }\r
200         }\r
201 \r
202         if (!NT_SUCCESS(status))\r
203                 goto exit;\r
204 \r
205         //\r
206         // Initialize Spb so the driver can issue reads/writes\r
207         //\r
208         status = SpbTargetInitialize(FxDevice, &devContext->I2CContext);\r
209 \r
210         if (!NT_SUCCESS(status))\r
211                 goto exit;\r
212         \r
213         // \r
214         // Read Device Id - LM3643 ID should be 0x02\r
215         // \r
216         BYTE rData;\r
217         SPB_CONTEXT *SpbContext = &devContext->I2CContext;\r
218         status = SpbReadDataSynchronously(SpbContext, 0x0C, &rData, 1);\r
219 \r
220         // \r
221         // Add additional chip initialize code here if it is needed\r
222         // such as TX-pin, IVFM Levels/Hysteresis, Selection etc \r
223         \r
224 exit:\r
225 \r
226         return status;\r
227 }\r
228 \r
229 NTSTATUS\r
230 OnReleaseHardware(\r
231         IN WDFDEVICE FxDevice,\r
232         IN WDFCMRESLIST FxResourcesTranslated\r
233         )\r
234         /*++\r
235 \r
236         Routine Description:\r
237 \r
238         This routine cleans up any resources provided.\r
239 \r
240         Arguments:\r
241 \r
242         FxDevice - a handle to the framework device object\r
243         FxResourcesRaw - list of translated hardware resources that\r
244         the PnP manager has assigned to the device\r
245         FxResourcesTranslated - list of raw hardware resources that\r
246         the PnP manager has assigned to the device\r
247 \r
248         Return Value:\r
249 \r
250         NTSTATUS indicating sucesss or failure\r
251 \r
252         --*/\r
253 {\r
254         NTSTATUS status;\r
255         PDEVICE_EXTENSION devContext;\r
256 \r
257         UNREFERENCED_PARAMETER(FxResourcesTranslated);\r
258 \r
259         devContext = GetDeviceContext(FxDevice);\r
260         \r
261         BYTE rData;\r
262         SPB_CONTEXT *SpbContext = &devContext->I2CContext;\r
263         status = SpbReadDataSynchronously(SpbContext, 0x01, &rData, 1);\r
264         if (!NT_SUCCESS(status))\r
265         {\r
266                 return status;\r
267         }\r
268 \r
269         rData &= (~0x03); //LED1, 2 OFF\r
270         SpbWriteDataSynchronously(SpbContext, 0x01, &rData, 1);\r
271         if (!NT_SUCCESS(status))\r
272         {\r
273                 return status;\r
274         }\r
275 \r
276         SpbTargetDeinitialize(FxDevice, &GetDeviceContext(FxDevice)->I2CContext);\r
277 \r
278         return status;\r
279 }\r
280 \r
281 \r
282 \r
283 VOID\r
284 OnDeviceControl(\r
285         IN WDFQUEUE Queue,\r
286         IN WDFREQUEST Request,\r
287         IN size_t OutputBufferLength,\r
288         IN size_t InputBufferLength,\r
289         IN ULONG IoControlCode\r
290         )\r
291         /*++\r
292 \r
293         Routine Description:\r
294 \r
295         This event is called when the framework receives\r
296         IRP_MJ_INTERNAL DEVICE_CONTROL requests from the system.\r
297 \r
298         Arguments:\r
299 \r
300         Queue - Handle to the framework queue object that is associated\r
301         with the I/O request.\r
302 \r
303         Request - Handle to a framework request object.\r
304 \r
305         OutputBufferLength - length of the request's output buffer,\r
306         if an output buffer is available.\r
307 \r
308         InputBufferLength - length of the request's input buffer,\r
309         if an input buffer is available.\r
310 \r
311         IoControlCode - the driver-defined or system-defined I/O control code\r
312         (IOCTL) that is associated with the request.\r
313 \r
314         Return Value:\r
315 \r
316         None, status is indicated when completing the request\r
317 \r
318         --*/\r
319 {\r
320         NTSTATUS status;\r
321         PDEVICE_EXTENSION devContext;\r
322         WDFDEVICE device;\r
323         BOOLEAN requestPending;\r
324         BYTE rData = 0, wData = 0;\r
325         USHORT rData2b = 0;\r
326         ULONG* inputVal;\r
327         ULONG* retVal;\r
328 \r
329         UNREFERENCED_PARAMETER(OutputBufferLength);\r
330         UNREFERENCED_PARAMETER(InputBufferLength);\r
331 \r
332         device = WdfIoQueueGetDevice(Queue);\r
333         devContext = GetDeviceContext(device);\r
334         requestPending = FALSE;\r
335 \r
336         SPB_CONTEXT *SpbContext = &devContext->I2CContext;\r
337         \r
338         WdfRequestRetrieveInputBuffer(Request, sizeof(ULONG), (void**)&inputVal, NULL);\r
339         WdfRequestRetrieveOutputBuffer(Request, sizeof(ULONG),(void**)&retVal, NULL);\r
340         wData = (*inputVal) & 0xff;\r
341 \r
342         switch (IoControlCode) {\r
343 \r
344         case IOCTL_LM3643_DEVID:\r
345                 status = SpbReadDataSynchronously(SpbContext, 0x0C, &rData, 1);\r
346                 *retVal = (ULONG)rData;\r
347                 break;\r
348 \r
349         case  IOCTL_LM3643_MODE:\r
350                 status = RegUpdateSynchronously(SpbContext, 0x01, 0x0C, (wData << 2));\r
351                 status |= SpbReadDataSynchronously(SpbContext, 0x01, &rData, 1);\r
352                 *retVal = (ULONG)rData;\r
353                 break;\r
354 \r
355         case  IOCTL_LM3643_TORCH_PIN_ENABLE:\r
356                 status = RegUpdateSynchronously(SpbContext, 0x01, 0x10, (wData << 4));\r
357                 status |= SpbReadDataSynchronously(SpbContext, 0x01, &rData, 1);\r
358                 *retVal = (ULONG)rData;\r
359                 break;\r
360 \r
361         case  IOCTL_LM3643_STROBE_PIN_ENABLE:\r
362                 status = RegUpdateSynchronously(SpbContext, 0x01, 0x20, (wData << 5));\r
363                 status |= SpbReadDataSynchronously(SpbContext, 0x01, &rData, 1);\r
364                 *retVal = (ULONG)rData;\r
365                 break;\r
366 \r
367         case  IOCTL_LM3643_STATUS:              \r
368                 status = SpbReadDataSynchronously(SpbContext, 0x0A, &rData, 1);\r
369                 rData2b |= ( ( rData& 0xff) << 8);\r
370                 status = SpbReadDataSynchronously(SpbContext, 0x0B, &rData, 1);\r
371                 rData2b |= (rData & 0xff);\r
372                 *retVal = (ULONG)rData2b;\r
373                 break;\r
374 \r
375         case  IOCTL_LM3643_LED1_ENABLE:\r
376                 status = RegUpdateSynchronously(SpbContext, 0x01, 0x01, (wData << 0));\r
377                 status |= SpbReadDataSynchronously(SpbContext, 0x01, &rData, 1);\r
378                 *retVal = (ULONG)rData;\r
379                 break;\r
380 \r
381         case  IOCTL_LM3643_LED1_BRT_FLASH:\r
382                 status = RegUpdateSynchronously(SpbContext, 0x03, 0x3f, (wData << 0));\r
383                 status |= SpbReadDataSynchronously(SpbContext, 0x03, &rData, 1);\r
384                 *retVal = (ULONG)rData;\r
385                 break;\r
386 \r
387         case  IOCTL_LM3643_LED1_BRT_TORCH:\r
388                 status = RegUpdateSynchronously(SpbContext, 0x05, 0x3f, (wData << 0));\r
389                 status |= SpbReadDataSynchronously(SpbContext, 0x05, &rData, 1);\r
390                 *retVal = (ULONG)rData;\r
391                 break;
392 \r
393         case  IOCTL_LM3643_LED2_ENABLE:\r
394                 status = RegUpdateSynchronously(SpbContext, 0x01, 0x02, (wData << 1));\r
395                 status |= SpbReadDataSynchronously(SpbContext, 0x01, &rData, 1);\r
396                 *retVal = (ULONG)rData;\r
397                 break;
399         case  IOCTL_LM3643_LED2_BRT_FLASH:\r
400                 status = RegUpdateSynchronously(SpbContext, 0x04, 0x3f, (wData << 0));\r
401                 status |= SpbReadDataSynchronously(SpbContext, 0x04, &rData, 1);\r
402                 *retVal = (ULONG)rData;\r
403                 break;\r
404 \r
405         case  IOCTL_LM3643_LED2_BRT_TORCH:\r
406                 status = RegUpdateSynchronously(SpbContext, 0x06, 0x3f, (wData << 0));\r
407                 status |= SpbReadDataSynchronously(SpbContext, 0x06, &rData, 1);\r
408                 *retVal = (ULONG)rData;\r
409                 break;\r
410 \r
411         case  IOCTL_LM3643_FLASH_TOUT:\r
412                 status = RegUpdateSynchronously(SpbContext, 0x08, 0x0f, (wData << 0));\r
413                 status |= SpbReadDataSynchronously(SpbContext, 0x08, &rData, 1);\r
414                 *retVal = (ULONG)rData;\r
415                 break;
416 \r
417         default:\r
418                 status = STATUS_NOT_SUPPORTED;\r
419                 break;\r
420         }\r
421 \r
422         if (!requestPending)\r
423         {\r
424                 WdfRequestCompleteWithInformation(Request, status, sizeof(ULONG));\r
425         }\r
426 \r
427         return;\r
428 }\r
429 \r
430 \r