forked from mirrors/linux
		
	Bluetooth: Use the control channel for raw HID reports
In commit 2da31939a4, support
for Bluetooth hid_output_raw_report was added, but it pushes
the data to the interrupt channel instead of the contol one.
This patch makes hid_output_raw_report use the control channel
instead. Using the interrupt channel was a mistake.
Signed-off-by: Bastien Nocera <hadess@hadess.net>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
			
			
This commit is contained in:
		
							parent
							
								
									9670d80a9a
								
							
						
					
					
						commit
						6bf8268f9a
					
				
					 1 changed files with 36 additions and 34 deletions
				
			
		| 
						 | 
					@ -243,6 +243,39 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
 | 
				
			||||||
	input_sync(dev);
 | 
						input_sync(dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __hidp_send_ctrl_message(struct hidp_session *session,
 | 
				
			||||||
 | 
								unsigned char hdr, unsigned char *data, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sk_buff *skb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BT_DBG("session %p data %p size %d", session, data, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
 | 
				
			||||||
 | 
							BT_ERR("Can't allocate memory for new frame");
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*skb_put(skb, 1) = hdr;
 | 
				
			||||||
 | 
						if (data && size > 0)
 | 
				
			||||||
 | 
							memcpy(skb_put(skb, size), data, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						skb_queue_tail(&session->ctrl_transmit, skb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int hidp_send_ctrl_message(struct hidp_session *session,
 | 
				
			||||||
 | 
								unsigned char hdr, unsigned char *data, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = __hidp_send_ctrl_message(session, hdr, data, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hidp_schedule(session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hidp_queue_report(struct hidp_session *session,
 | 
					static int hidp_queue_report(struct hidp_session *session,
 | 
				
			||||||
				unsigned char *data, int size)
 | 
									unsigned char *data, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -282,7 +315,9 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count)
 | 
					static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (hidp_queue_report(hid->driver_data, data, count))
 | 
						if (hidp_send_ctrl_message(hid->driver_data,
 | 
				
			||||||
 | 
								HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE,
 | 
				
			||||||
 | 
								data, count))
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
	return count;
 | 
						return count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -307,39 +342,6 @@ static inline void hidp_del_timer(struct hidp_session *session)
 | 
				
			||||||
		del_timer(&session->timer);
 | 
							del_timer(&session->timer);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __hidp_send_ctrl_message(struct hidp_session *session,
 | 
					 | 
				
			||||||
			unsigned char hdr, unsigned char *data, int size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sk_buff *skb;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	BT_DBG("session %p data %p size %d", session, data, size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
 | 
					 | 
				
			||||||
		BT_ERR("Can't allocate memory for new frame");
 | 
					 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*skb_put(skb, 1) = hdr;
 | 
					 | 
				
			||||||
	if (data && size > 0)
 | 
					 | 
				
			||||||
		memcpy(skb_put(skb, size), data, size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	skb_queue_tail(&session->ctrl_transmit, skb);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int hidp_send_ctrl_message(struct hidp_session *session,
 | 
					 | 
				
			||||||
			unsigned char hdr, unsigned char *data, int size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = __hidp_send_ctrl_message(session, hdr, data, size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hidp_schedule(session);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void hidp_process_handshake(struct hidp_session *session,
 | 
					static void hidp_process_handshake(struct hidp_session *session,
 | 
				
			||||||
					unsigned char param)
 | 
										unsigned char param)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue