3232#include <linux/usb/ch9.h>
3333#include "hid-ids.h"
3434
35+ #define CP2112_REPORT_MAX_LENGTH 64
36+ #define CP2112_GPIO_CONFIG_LENGTH 5
37+ #define CP2112_GPIO_GET_LENGTH 2
38+ #define CP2112_GPIO_SET_LENGTH 3
39+
3540enum {
3641 CP2112_GPIO_CONFIG = 0x02 ,
3742 CP2112_GPIO_GET = 0x03 ,
@@ -161,6 +166,8 @@ struct cp2112_device {
161166 atomic_t read_avail ;
162167 atomic_t xfer_avail ;
163168 struct gpio_chip gc ;
169+ u8 * in_out_buffer ;
170+ spinlock_t lock ;
164171};
165172
166173static int gpio_push_pull = 0xFF ;
@@ -171,97 +178,131 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
171178{
172179 struct cp2112_device * dev = gpiochip_get_data (chip );
173180 struct hid_device * hdev = dev -> hdev ;
174- u8 buf [5 ];
181+ u8 * buf = dev -> in_out_buffer ;
182+ unsigned long flags ;
175183 int ret ;
176184
185+ spin_lock_irqsave (& dev -> lock , flags );
186+
177187 ret = hid_hw_raw_request (hdev , CP2112_GPIO_CONFIG , buf ,
178- sizeof ( buf ) , HID_FEATURE_REPORT ,
179- HID_REQ_GET_REPORT );
180- if (ret != sizeof ( buf ) ) {
188+ CP2112_GPIO_CONFIG_LENGTH , HID_FEATURE_REPORT ,
189+ HID_REQ_GET_REPORT );
190+ if (ret != CP2112_GPIO_CONFIG_LENGTH ) {
181191 hid_err (hdev , "error requesting GPIO config: %d\n" , ret );
182- return ret ;
192+ goto exit ;
183193 }
184194
185195 buf [1 ] &= ~(1 << offset );
186196 buf [2 ] = gpio_push_pull ;
187197
188- ret = hid_hw_raw_request (hdev , CP2112_GPIO_CONFIG , buf , sizeof (buf ),
189- HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
198+ ret = hid_hw_raw_request (hdev , CP2112_GPIO_CONFIG , buf ,
199+ CP2112_GPIO_CONFIG_LENGTH , HID_FEATURE_REPORT ,
200+ HID_REQ_SET_REPORT );
190201 if (ret < 0 ) {
191202 hid_err (hdev , "error setting GPIO config: %d\n" , ret );
192- return ret ;
203+ goto exit ;
193204 }
194205
195- return 0 ;
206+ ret = 0 ;
207+
208+ exit :
209+ spin_unlock_irqrestore (& dev -> lock , flags );
210+ return ret <= 0 ? ret : - EIO ;
196211}
197212
198213static void cp2112_gpio_set (struct gpio_chip * chip , unsigned offset , int value )
199214{
200215 struct cp2112_device * dev = gpiochip_get_data (chip );
201216 struct hid_device * hdev = dev -> hdev ;
202- u8 buf [3 ];
217+ u8 * buf = dev -> in_out_buffer ;
218+ unsigned long flags ;
203219 int ret ;
204220
221+ spin_lock_irqsave (& dev -> lock , flags );
222+
205223 buf [0 ] = CP2112_GPIO_SET ;
206224 buf [1 ] = value ? 0xff : 0 ;
207225 buf [2 ] = 1 << offset ;
208226
209- ret = hid_hw_raw_request (hdev , CP2112_GPIO_SET , buf , sizeof (buf ),
210- HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
227+ ret = hid_hw_raw_request (hdev , CP2112_GPIO_SET , buf ,
228+ CP2112_GPIO_SET_LENGTH , HID_FEATURE_REPORT ,
229+ HID_REQ_SET_REPORT );
211230 if (ret < 0 )
212231 hid_err (hdev , "error setting GPIO values: %d\n" , ret );
232+
233+ spin_unlock_irqrestore (& dev -> lock , flags );
213234}
214235
215236static int cp2112_gpio_get (struct gpio_chip * chip , unsigned offset )
216237{
217238 struct cp2112_device * dev = gpiochip_get_data (chip );
218239 struct hid_device * hdev = dev -> hdev ;
219- u8 buf [2 ];
240+ u8 * buf = dev -> in_out_buffer ;
241+ unsigned long flags ;
220242 int ret ;
221243
222- ret = hid_hw_raw_request (hdev , CP2112_GPIO_GET , buf , sizeof (buf ),
223- HID_FEATURE_REPORT , HID_REQ_GET_REPORT );
224- if (ret != sizeof (buf )) {
244+ spin_lock_irqsave (& dev -> lock , flags );
245+
246+ ret = hid_hw_raw_request (hdev , CP2112_GPIO_GET , buf ,
247+ CP2112_GPIO_GET_LENGTH , HID_FEATURE_REPORT ,
248+ HID_REQ_GET_REPORT );
249+ if (ret != CP2112_GPIO_GET_LENGTH ) {
225250 hid_err (hdev , "error requesting GPIO values: %d\n" , ret );
226- return ret ;
251+ ret = ret < 0 ? ret : - EIO ;
252+ goto exit ;
227253 }
228254
229- return (buf [1 ] >> offset ) & 1 ;
255+ ret = (buf [1 ] >> offset ) & 1 ;
256+
257+ exit :
258+ spin_unlock_irqrestore (& dev -> lock , flags );
259+
260+ return ret ;
230261}
231262
232263static int cp2112_gpio_direction_output (struct gpio_chip * chip ,
233264 unsigned offset , int value )
234265{
235266 struct cp2112_device * dev = gpiochip_get_data (chip );
236267 struct hid_device * hdev = dev -> hdev ;
237- u8 buf [5 ];
268+ u8 * buf = dev -> in_out_buffer ;
269+ unsigned long flags ;
238270 int ret ;
239271
272+ spin_lock_irqsave (& dev -> lock , flags );
273+
240274 ret = hid_hw_raw_request (hdev , CP2112_GPIO_CONFIG , buf ,
241- sizeof ( buf ) , HID_FEATURE_REPORT ,
242- HID_REQ_GET_REPORT );
243- if (ret != sizeof ( buf ) ) {
275+ CP2112_GPIO_CONFIG_LENGTH , HID_FEATURE_REPORT ,
276+ HID_REQ_GET_REPORT );
277+ if (ret != CP2112_GPIO_CONFIG_LENGTH ) {
244278 hid_err (hdev , "error requesting GPIO config: %d\n" , ret );
245- return ret ;
279+ goto fail ;
246280 }
247281
248282 buf [1 ] |= 1 << offset ;
249283 buf [2 ] = gpio_push_pull ;
250284
251- ret = hid_hw_raw_request (hdev , CP2112_GPIO_CONFIG , buf , sizeof (buf ),
252- HID_FEATURE_REPORT , HID_REQ_SET_REPORT );
285+ ret = hid_hw_raw_request (hdev , CP2112_GPIO_CONFIG , buf ,
286+ CP2112_GPIO_CONFIG_LENGTH , HID_FEATURE_REPORT ,
287+ HID_REQ_SET_REPORT );
253288 if (ret < 0 ) {
254289 hid_err (hdev , "error setting GPIO config: %d\n" , ret );
255- return ret ;
290+ goto fail ;
256291 }
257292
293+ spin_unlock_irqrestore (& dev -> lock , flags );
294+
258295 /*
259296 * Set gpio value when output direction is already set,
260297 * as specified in AN495, Rev. 0.2, cpt. 4.4
261298 */
262299 cp2112_gpio_set (chip , offset , value );
263300
264301 return 0 ;
302+
303+ fail :
304+ spin_unlock_irqrestore (& dev -> lock , flags );
305+ return ret < 0 ? ret : - EIO ;
265306}
266307
267308static int cp2112_hid_get (struct hid_device * hdev , unsigned char report_number ,
@@ -1007,6 +1048,17 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
10071048 struct cp2112_smbus_config_report config ;
10081049 int ret ;
10091050
1051+ dev = devm_kzalloc (& hdev -> dev , sizeof (* dev ), GFP_KERNEL );
1052+ if (!dev )
1053+ return - ENOMEM ;
1054+
1055+ dev -> in_out_buffer = devm_kzalloc (& hdev -> dev , CP2112_REPORT_MAX_LENGTH ,
1056+ GFP_KERNEL );
1057+ if (!dev -> in_out_buffer )
1058+ return - ENOMEM ;
1059+
1060+ spin_lock_init (& dev -> lock );
1061+
10101062 ret = hid_parse (hdev );
10111063 if (ret ) {
10121064 hid_err (hdev , "parse failed\n" );
@@ -1063,12 +1115,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
10631115 goto err_power_normal ;
10641116 }
10651117
1066- dev = kzalloc (sizeof (* dev ), GFP_KERNEL );
1067- if (!dev ) {
1068- ret = - ENOMEM ;
1069- goto err_power_normal ;
1070- }
1071-
10721118 hid_set_drvdata (hdev , (void * )dev );
10731119 dev -> hdev = hdev ;
10741120 dev -> adap .owner = THIS_MODULE ;
@@ -1087,7 +1133,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
10871133
10881134 if (ret ) {
10891135 hid_err (hdev , "error registering i2c adapter\n" );
1090- goto err_free_dev ;
1136+ goto err_power_normal ;
10911137 }
10921138
10931139 hid_dbg (hdev , "adapter registered\n" );
@@ -1123,8 +1169,6 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
11231169 gpiochip_remove (& dev -> gc );
11241170err_free_i2c :
11251171 i2c_del_adapter (& dev -> adap );
1126- err_free_dev :
1127- kfree (dev );
11281172err_power_normal :
11291173 hid_hw_power (hdev , PM_HINT_NORMAL );
11301174err_hid_close :
@@ -1149,7 +1193,6 @@ static void cp2112_remove(struct hid_device *hdev)
11491193 */
11501194 hid_hw_close (hdev );
11511195 hid_hw_stop (hdev );
1152- kfree (dev );
11531196}
11541197
11551198static int cp2112_raw_event (struct hid_device * hdev , struct hid_report * report ,
0 commit comments